Uploading .csv or .txt file to populate QTableView - c++

Recently I was working on a gui application & I wanted to save the data of QTableView in a .csv or .txt file. I Used the guidance received during this question which made me think if the reverse is also possible; i.e. if the QTableView can be populated from a .csv or .txt file. Once again I would prefer staying with a model based design such as QTableView instead of item based QTableWidget.
Any code-snippet or tutorial-documentation would be really helpful.

Consider a test.csv file (it could be generated by any text editor):
And the textstream behind is (if generated by programming):
1,2,3,\n4,5,6,\n7,8,9,\n10,11,12,\n13,14,15,
If opened in Microsoft Office Excel, it might looked like:
To read this .csv file to the model of your QTableView:
QStandardItemModel *model = new QStandardItemModel;
QFile file("test.csv");
if (file.open(QIODevice::ReadOnly)) {
int lineindex = 0; // file line counter
QTextStream in(&file); // read to text stream
while (!in.atEnd()) {
// read one line from textstream(separated by "\n")
QString fileLine = in.readLine();
// parse the read line into separate pieces(tokens) with "," as the delimiter
QStringList lineToken = fileLine.split(",", QString::SkipEmptyParts);
// load parsed data to model accordingly
for (int j = 0; j < lineToken.size(); j++) {
QString value = lineToken.at(j);
QStandardItem *item = new QStandardItem(value);
model->setItem(lineindex, j, item);
}
lineindex++;
}
file.close();
}
(You could manipulate the code to meet you table format)
[Result]

Related

Better way to use QDomDocument data as text

I am a newbie, I am creating a XML file in which I need to give CRC value to cross check on server. For this I need QDomDocument data as text. For this I am first creating XML file with fake CRC value. Then I open it with QFile and read all data. Then I split data and calculate data CRC. Now I have to rewrite whole file again. I know it is the worst idea ever to write same file twice but as I am a newbie, I don't know how to do it in better style. Here is my code:-
QDomElement docElem = doc.documentElement();
QFile xmlfile(filename);
if(!xmlfile.open(QIODevice::ReadWrite | QIODevice::Text))
{
qDebug("Can not open file device.");
}
xmlfile.resize(0);
QXmlStreamWriter xw;
xw.setDevice(&xmlfile); //set file to XML writer
xw.setAutoFormatting(true);
xw.setAutoFormattingIndent(4);
xw.writeStartDocument();
xw.writeStartElement(fileID); //fileID as the start element
if(docElem.hasAttributes())
{
xw.writeAttribute("xmlns:xs",docElem.attribute("xmlns:xs"));
xw.writeAttribute("xmlns",docElem.attribute("xmlns"));
}
xw.writeTextElement("Frame_Start_ID","STX");
xw.writeTextElement("Frame_Length","1234");
xw.writeTextElement("Source_Device_Id","CDIS_PIS ");
xw.writeTextElement("Destination_Device_Id","DDNS-SERVER ");
xw.writeTextElement("Frame_Code","I");
xw.writeStartElement("Frame_Data");
//inside frame data
xw.writeTextElement("File_Number","1");
xw.writeTextElement("File_Name","Event");
for(int j=0;j<logFields.count();j++)
{
xw.writeTextElement(logFields.at(j),logData.at(j));
}
xw.writeEndElement();
xw.writeTextElement("CRC","14405904");
xw.writeTextElement("Frame_End_Id","ETX");
xw.writeEndDocument();
xmlfile.flush();
xmlfile.close();
QFile xmlfyle(filename);
xmlfyle.open(QIODevice::ReadWrite | QIODevice::Text);
QString content = (QString)xmlfyle.readAll();
QStringList list1 = content.split("<CRC>");
qDebug() << "Split value = " << list1.at(0);
QByteArray crc_new = crc_o.crc_generate_modbus((unsigned char*)list1.at(0).data(),list1.at(0).size());
xmlfyle.resize(0);
QXmlStreamWriter xw_new;
xw_new.setDevice(&xmlfyle); //set file to XML writer
xw_new.setAutoFormatting(true);
xw_new.setAutoFormattingIndent(4);
xw_new.writeStartDocument();
xw_new.writeStartElement(fileID); //fileID as the start element
if(docElem.hasAttributes())
{
xw_new.writeAttribute("xmlns:xs",docElem.attribute("xmlns:xs"));
xw_new.writeAttribute("xmlns",docElem.attribute("xmlns"));
}
xw_new.writeTextElement("Frame_Start_ID","STX");
xw_new.writeTextElement("Frame_Length","1234");
xw_new.writeTextElement("Source_Device_Id","CDIS_PIS ");
xw_new.writeTextElement("Destination_Device_Id","DDNS-SERVER ");
xw_new.writeTextElement("Frame_Code","I");
xw_new.writeStartElement("Frame_Data");
xw_new.writeTextElement("File_Number","1");
xw_new.writeTextElement("File_Name","Event");
for(int j=0;j<logFields.count();j++)
{
xw_new.writeTextElement(logFields.at(j),logData.at(j));
}
xw_new.writeEndElement();
char tab[10];
sprintf(tab,"%d",crc_new.data());
xw_new.writeTextElement("CRC",QString::fromUtf8(tab));
xw_new.writeTextElement("Frame_End_Id","ETX");
xw_new.writeEndDocument();
xmlfyle.flush();
xmlfyle.close();
can anyone suggest me what could be a better way to do this.Thanks
One version of QXmlStreamWriter constructor accepts a QByteArray and writes into the array instead of an output file.
QXmlStreamWriter Class
So what you can do is; using QXmlStreamWriter, prepare data for your XML in a QByteArray, do whatever you need to do with the CRC inside this data; and when everything is done, write this QByteArray to the output file.

How to populate Qt ListView with content from a text file?

I have a text file that contains many vocabularies, each vocabulary is separated by a new line.
How can I populate a Qt ListView with vocabularies from the text file?
QStringListModel *model;
// Create model
model = new QStringListModel(this);
QStringList stringList;
// open the file
QFile textFile("/<FullPath>/<fileName>");
if(!textFile.open(QIODevice::ReadOnly)) {
QMessageBox::information(0,"Error",textFile.errorString());
}
// teststream to read from file
QTextStream textStream(&textFile);
while (true)
{
QString line = textStream.readLine();
if (line.isNull())
break;
else
stringList.append(line); // populate the stringlist
}
// Populate the model
model->setStringList(stringList);
// Glue model and view together
ui->listView->setModel(model);
// if you want to add additional feature to listview.
ui->listView->
setEditTriggers(QAbstractItemView::AnyKeyPressed |
QAbstractItemView::DoubleClicked);
You need to read the file line by line, and add to a QStringList, then into listView.
QStringList *allLines = new QStringList(); //Your list for lines from the file.
allLines->clear();
QStringListModel *linesModel = new QStringListModel(*allLines, NULL); //Your model to set to the view.
QFile file("/path/to/yourFileName.txt");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;
while (!file.atEnd()) {
QByteArray line = file.readLine(); //Lines are read as QByteArray.
const char *line_c = line.data(); //convert to const char*
QString line_str = QString(QLatin1String(line_c)); //And finally convert to QString
allLines->append(line_str); //Add to the list
}
linesModel->setStringList(*allLines); //Set your model's list your stringlist
listView->setModel(linesModel); //set model of your listView linesModel. You need to use your listView's name, which might be ui->listView.

Showing images along with text in QTableView model field

I am writing a Qt GUI C++ program where I am planning to populate a tabular view, for example a 3X2 table view. Where the texts in the field will be from a .csv file. And along with the text there will also be a small icon/image.
To give an idea of the UI it might be looking somewhat like;
Now adding text to QTable model view I have done using;
QStandardItemModel *model = new QStandardItemModel;
QFile file("/home/aj/beta_test.csv");
if (file.open(QIODevice::ReadOnly))
{
int lineindex = 0; // file line counter
QTextStream in(&file); // read to text stream
while (!in.atEnd()) {
QStringList lineToken;
QString fileLine = in.readLine(); // read one line (separated by "\n")
lineToken = fileLine.split(",", QString::SkipEmptyParts); // parse a line into separate pieces with "," as the delimiter
for (int j = 0; j < lineToken.size(); j++) // load parsed data to model accordingly
{
QString value = lineToken.at(j);
QStandardItem *item = new QStandardItem(value);
model->setItem(lineindex, j, item);
ui->tableView->setModel(model);
}
lineindex++;
}
file.close();
}
Now how to perform adding the image part???
You can use standard method:
item->setIcon(QIcon("path"));
or do this with index (use setData() and Qt::DecorationRole)
After adding you can call resizeRowsToContents() to show full images in your cells.
Also I noticed that you set your model in every iteration. It is not wrong but it is very inefficient (especially when you populate large data), so set your model one time after the loop.

QTableView export to .csv number of rows fetched is limited to only 256

I wrote a gui program which will connect to an oracle db an retrieve data after a query is typed. the retrieved data is shown in a QTableView table model widget. and later the result of the QTableView is exported to a .csv file
QString MyQuery = ui->lineQuery->text();
db.open();
QSqlQuery query(MyQuery,db);
if(query.exec())
{
qDebug()<<QDateTime::currentDateTime()<<"QUERY SUCCESS ";
ui->queryButton->setStyleSheet("QPushButton {background-color: rgb(0, 255, 0);}");
this->model=new QSqlQueryModel();
model->setQuery(MyQuery);
ui->tableViewOra->setModel(model);
QString textData;
int rows=model->rowCount();
int columns=model->columnCount();
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
textData += model->data(model->index(i,j)).toString();
textData += ", "; // for .csv file format
}
textData += "\n"; // (optional: for new line segmentation)
}
QFile csvfile("/home/aj/ora_exported.csv");
if(csvfile.open(QIODevice::WriteOnly|QIODevice::Truncate))
{
QTextStream out(&csvfile);
out<<textData;
}
csvfile.close();
}
now the problem is, during a query I observed there are 543 rows visible in the QTableView (which is correct cause there are 543 entries). But when the .csv file is exported, only 256 rows are there.
Is there any variable size constraint that I am unaware about ???
Which variables should be taken care of if I want to export .csv files of upto 1000 rows approx ??? thanks.
I think when you first read model->rowCount() the model has not fetched all the results completely. Although it will fetch more later when table view is displayed resulting in a full display of rows in the table view.
Try to use QSqlQueryModel::fetchMore before reading the row count :
while (model->canFetchMore())
model->fetchMore();
int rows=model->rowCount();
int columns=model->columnCount();
[Additional information from Tay2510]:
You could just change the file open flag
if(csvfile.open(QIODevice::WriteOnly|QIODevice::Truncate))
to
if(csvfile.open(QIODevice::WriteOnly))
The former will overwrite the same file while the latter append data on it.

Spliting string and displaying in Qtreewidget

My programming knowledge and experience is very poor. I am using this code block to open the desired file when clicked on a push button ;
QString filename = QFileDialog::getOpenFileName();
QFile file(filename);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;
while (!file.atEnd())
{
QByteArray line = file.readLine();
processline(line);
}
And by this line i am showing it on QtextBrowser
void MainWindow::processline(QByteArray paramline)
{
ui->veri_cikis->append(paramline.constData());
}
The data on the file is like this
0;100;0
0;100;24
24;500;24
24;100;6
6;100;6
i have to split the datas by ";" mark and display them on a Qtreewidget columns. How do i do that ? And i have to show each first part on first column and second on second column and so. I have 3 columns in total
I think what you describe is better fit rather to a table view than a tree view. To parse your strings and split them by ';' character you can use QByteArray::split() function. Here is the sample code, that creates and populates table view with items that read from the file:
QFile file(filename);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;
QTableWidget *table = new QTableWidget;
int row = 0;
while (!file.atEnd()) {
QByteArray line = file.readLine();
QList<QByteArray> tokens = line.split(';');
int column = 0;
row++;
foreach (QByteArray ba, tokens) {
QTableWidgetItem *item = new QTableWidgetItem(ba);
table->setItem(row, column++, item);
}
}