Error when try to read from a QFile - c++

I want to read some data from a file with QT and then show data in a QTableWidget through a QComboBox.
void DemoDataView::on_comboBox_activated(const QString &arg1)
{
ui->tableWidget->setColumnCount(5);
ui->tableWidget->setRowCount(21);
ui->tableWidget->verticalHeader()->setVisible(false);
ui->tableWidget->setHorizontalHeaderLabels(QString("Age Range ; Male Population ; Male Percentage ; Female Population ; Female Percentage").split(";"));
ui->tableWidget->resizeColumnsToContents();
ui->tableWidget->resizeRowsToContents();
QFile inputFile("./data.txt");
if(!inputFile.open(QIODevice::ReadOnly))
{
QMessageBox::information(0, "Error", inputFile.errorString());
}
QTextStream in(&inputFile);
int rows = 0;
while(!in.atEnd()) {
QString mLine = in.readLine();
QStringList fields = mLine.split(" ");
QStringList::iterator it = fields.begin();
QString regName = *it;
ui->label->setText(arg1);
if(regName != "<END>" && QString::compare(regName, arg1) == 0) {
ui->label->setText(regName);
it++;
QString ageRange = *it;
it++;
QString nMale = *it;
double male = nMale.toDouble();
it++;
QString nFemale = *it;
double female = nFemale.toDouble();
ui->tableWidget->setItem(rows, 0, new QTableWidgetItem(ageRange));
ui->tableWidget->setItem(rows, 1, new QTableWidgetItem(nMale));
ui->tableWidget->setItem(rows, 3, new QTableWidgetItem(nFemale));
ui->tableWidget->setItem(rows, 2, new QTableWidgetItem(malePercCalc(male, female)));
ui->tableWidget->setItem(rows, 4, new QTableWidgetItem(femalePercCalc(male, female)));
rows++;
}
inputFile.close();
}
}
The file is in both the project folder and the build project folder.
When I run the application everything works good but in the Application Output tab I have this error message:
"QIODevice:: read (QFile, "./data.txt"): device not open"
Every time I click on a QComboBox item.
If it can be useful, this is the filling code of the QComboBox:
void DemoDataView::setComboBoxRegion() {
QFile inputFile("./data.txt");
if(!inputFile.open(QIODevice::ReadOnly))
{
QMessageBox::information(0, "Error", inputFile.errorString());
}
QTextStream in(&inputFile);
while(!in.atEnd()) {
QString mLine = in.readLine();
QStringList fields = mLine.split(" ");
QStringList::iterator it = fields.begin();
QString regName = *it;
if(regName != "<END>") {
if(ui->comboBox->findText(regName) == -1){
ui->comboBox->addItem(regName);
}
}
}
inputFile.close();
}

Your problem is that you are calling:
inputFile.close();
INSIDE of your loop, which means it is closed in the first loop. I can't really think of any cases that this would be the desired thing to happen;
To solve this, you should move it to the outside of the loop.

Related

Program not responding when export more than 10000 data to csv. QT C++

I'm exporting data to csv. I can export if datas around 8K or 10K but when I try to export data around 100K I get a warning "program not responding".
void MainWindow::exportArraysToCSV(QStringList labelList, QList < QList < double >> dataColums, QChar sep) {
QString filters("CSV files (*.csv);;All files (*.*)");
QString defaultFilter("CSVi files (*.csv)");
QString fileName = QFileDialog::getSaveFileName(0, "Save file", QCoreApplication::applicationDirPath(),
filters, & defaultFilter);
QFile file(fileName);
if (file.open(QFile::WriteOnly | QFile::Append)) {
QTextStream data( & file);
QStringList strList;
QString formula;
foreach(auto label, labelList) {
if (label.length() > 0){
strList.append("," + label + ",");
}
else
strList.append("");
}
data << strList.join(",") << "\n";
int maxRowCount = 0;
foreach(auto column, dataColums)
maxRowCount = qMax(maxRowCount, column.count());
for (int i = 5; i < maxRowCount; ++i) // rows
{
strList.clear();
for (int j = 0; j < 2; ++j) // columns
{
if (i < dataColums[j].count())
strList.append(QString::number(dataColums[j][i], 'f'));
else
strList.append("\"\" ");
}
data << strList.join(",") + "\n";
}
data << "=SUM(A2:A1255)";
file.close();
}
}

How do I connect ComboBox and TextBrowser using PushButton-Qt?

I make a program that reads a file. I have a combobox that reads lines numbers: 1,6,11,..etc. I want to e.g. read lines 1-5 when line number 1 is choosen in combobox and push button is clicked (or read lines 6-10 when line 6 is choosen, end so on).
For now I have this.
int line_counter=1;
if(file.open (QIODevice::ReadOnly | QIODevice::Text))
{
while(!stream.atEnd())
{
line = stream.readLine ();
if(!line.isNull ())
{
if((line_counter%5)==1)
ui->comboBox->addItem (line);
line_counter++;
}
}
}
stream.flush ();
file.close ();
void Servers::on_pushButton_clicked()
{
if(file.open (QIODevice::ReadOnly | QIODevice::Text))
{
for(int i=line_counter;i<line_counter+5;i++)
{
ui->textBrowser->setText(stream.readLine(i));
}
}
file.close ();
}
You can avoid reading from file each team you want to update textBrowser if the text is already in the comboBox.
First of all connect the pushButton signal with your method:
connect(ui->pushButton, &QPushButton::clicked, this, &Servers::on_pushButton_clicked);
Then change on_pushButton_clicked like so:
void Servers::on_pushButton_clicked()
{
if(file.open (QIODevice::ReadOnly | QIODevice::Text))
{
int index = ui->comboBox->currentIndex();
int from = 5 * index;
int to = from + 5;
QTextStream stream(&file);
int lineCount = 0;
QString text;
QString line;
while (stream.readLineInto(&line)) {
if (from >= lineCount && lineCount < to) {
text += line;
text += '\n';
}
lineCount++;
}
ui->textBrowser->setText(text.toString());
}
}

QT: How to replace number (Start, End) in a JSON from server

This is how my JSON file looks like. As you can see, the start_x, start_y, and end_x, end_y, degree_of_rotation is a number.
{
"ID" : "ROLL1",
"action" : "start",
"zone" :
{
"start_x" : 0,
"start_y" : 4,
"end_x" : 10,
"end_y" : 5,
"motion" :
{
"motion_type": "xxxxxx",
"degree_of_rotation": 30,
"rotation_direction": "yyyyyy",
"linear_direction": "+ve"
}
}
}
How can I replace and save the number in JSON from the server? Currently, this is what I have. Qt5 has a new JSON parser and I want to use it. The problem is that it isn't too clear about what the functions do
void JsonFileread::Json_File_Function()
{
try
{
qDebug() <<"file reading";
file.setFileName("/home/JSON/jsonfile.js");
file.open(QIODevice::ReadOnly | QIODevice::Text);
QFileDevice::FileError err = QFileDevice::NoError;
if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
qDebug() <<"Could not open file : "<<file.fileName() <<"for reading :"<<file.errorString()<<endl;
errMsg =file.errorString();
err =file.error();
cout<<"err : "<<err<<endl;
}
settings = file.readAll();
if (file.error() != QFile::NoError) {
qDebug() << QString("Failed to read from file %1, error: %2").arg(file.fileName()).arg(file.errorString());
}
if (settings.isEmpty()) {
qDebug() << "No data was currently available for reading from file" << file.fileName();
}
file.close();
object = EchoClient::jsonstringflag;
QJsonDocument sd = QJsonDocument::fromJson(settings.toUtf8());
QJsonObject sett2 = sd.object();
QJsonValue mainid = sett2["ID"];
mainid = mainid.toString();
QJsonValue action = sett2["action"];
actionstring = action.toString();
QJsonValue value = sett2.value(QString("zone"));
QJsonObject item = value.toObject();
QJsonValue startx = item["start_x"];
startvaluex = startx.toInt();
QJsonValue starty = item["start_y"];
startvaluey = starty.toInt();
QJsonValue endx = item["end_x"];
endvaluex = endx.toInt();
xendvaluestring = endx.toString();
qWarning() << endvaluex<<endl;
QJsonValue endy = item["end_y"];
endvaluey = endy.toInt();
yendvaluestring = endy.toString();
qWarning() << endvaluey<<endl;
QJsonValue motion = item.value(QString("motion"));
QJsonObject motion_object = motion.toObject();
QJsonValue motiontype = motion_object["motion_type"];
motiontypestring = motiontype.toString();
QJsonValue directionlinear = motion_object["linear_direction"];
lineardirection = directionlinear.toString();
QJsonValue rotatingangle = motion_object["degree_of_rotation"];
angleofrotation = rotatingangle.toInt();
}
catch (QJsonParseError error)
{
qDebug() << error.errorString();
}
catch(...)
{
qDebug() << "due to some other error";
}
}
So help to solve the problem
You can write to a QJsonObject very similar to how you read its properties
QJsonObject obj;
obj["key"] = value;
Once you have built the QJsonObject tree, set the top level element on a QJsonDocument and use it to generate the JSON content.

QTableView output save as .csv or .txt

I wrote the below code for a qt gui to view the query output in a QTableView(Model oriented). now i want to save this output as a .csv or .txt file. There were suggestions to use QTableWidget(Item oriented) but I would like to stick to the model based approach.
void MainWindow::on_pushButton_clicked()
{
db = QSqlDatabase::addDatabase("QOCI");
db.setHostName("host");
db.setDatabaseName("db");
db.setUserName("uid");
db.setPassword("pw");
db.setPort(port);
QString MyQuery = ui->lineEdit->text();
if (db.open())
{
qDebug()<<QDateTime::currentDateTime()<<"QUERY DONE SUCCESSFULLY ";
this->model=new QSqlQueryModel();
model->setQuery(MyQuery);
ui->tableView->setModel(model);
}
else
{
qDebug()<<QDateTime::currentDateTime()<<"YOU FORGOT THE QUERY "<<db.lastError().text();
}
}
any guidelines ???
You may customize it according to your actual needs:
// [Collect model data to QString]
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)
}
// [Save to file] (header file <QFile> needed)
// .csv
QFile csvFile("test.csv");
if(csvFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
QTextStream out(&csvFile);
out << textData;
csvFile.close();
}
// .txt
QFile txtFile("test.txt");
if(txtFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
QTextStream out(&txtFile);
out << textData;
txtFile.close();
}
You can save your model to a text file by :
QFile f( "table.txt" );
if( f.open( QIODevice::WriteOnly ) )
{
QTextStream ts( &f );
QStringList strList;
for (int i=0; i<model->rowCount(); i++)
{
strList.clear();
for (int j=0; j<model->columnCount(); j++)
strList << model->data(model->index(i,j)).toString();
ts << strList.join(" ") + "\n";
}
f.close();
}
Here the model data are saved one row in each line separated by space. If you want to separate them by some other character like comma you can just replace the parameter on the join like :
ts << strList.join(",") + "\n";
here is a way to export a qtableview to a csv, including the column names using qt
void staticmethods::exportTableViewToCSV(QTableView *table) {
QString filters("CSV files (*.csv);;All files (*.*)");
QString defaultFilter("CSV files (*.csv)");
QString fileName = QFileDialog::getSaveFileName(0, "Save file", QCoreApplication::applicationDirPath(),
filters, &defaultFilter);
QFile file(fileName);
QAbstractItemModel *model = table->model();
if (file.open(QFile::WriteOnly | QFile::Truncate)) {
QTextStream data(&file);
QStringList strList;
for (int i = 0; i < model->columnCount(); i++) {
if (model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString().length() > 0)
strList.append("\"" + model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString() + "\"");
else
strList.append("");
}
data << strList.join(";") << "\n";
for (int i = 0; i < model->rowCount(); i++) {
strList.clear();
for (int j = 0; j < model->columnCount(); j++) {
if (model->data(model->index(i, j)).toString().length() > 0)
strList.append("\"" + model->data(model->index(i, j)).toString() + "\"");
else
strList.append("");
}
data << strList.join(";") + "\n";
}
file.close();
}
}

QTableView printing

I am new on QT an I try to print out from QTableView
How can I do this?
Thank a lot
Here is a variation of the first answer that gets rid of the intermediate file.
QString strStream;
QTextStream out(&strStream);
const int rowCount = pPublic->tableView->model()->rowCount();
const int columnCount = pPublic->tableView->model()->columnCount();
out << "<html>\n"
"<head>\n"
"<meta Content=\"Text/html; charset=Windows-1251\">\n"
<< QString("<title>%1</title>\n").arg(strTitle)
<< "</head>\n"
"<body bgcolor=#ffffff link=#5000A0>\n"
"<table border=1 cellspacing=0 cellpadding=2>\n";
// headers
out << "<thead><tr bgcolor=#f0f0f0>";
for (int column = 0; column < columnCount; column++)
if (!pPublic->tableView->isColumnHidden(column))
out << QString("<th>%1</th>").arg(pPublic->tableView->model()->headerData(column, Qt::Horizontal).toString());
out << "</tr></thead>\n";
// data table
for (int row = 0; row < rowCount; row++) {
out << "<tr>";
for (int column = 0; column < columnCount; column++) {
if (!pPublic->tableView->isColumnHidden(column)) {
QString data = pPublic->tableView->model()->data(pPublic->tableView->model()->index(row, column)).toString().simplified();
out << QString("<td bkcolor=0>%1</td>").arg((!data.isEmpty()) ? data : QString(" "));
}
}
out << "</tr>\n";
}
out << "</table>\n"
"</body>\n"
"</html>\n";
QTextDocument *document = new QTextDocument();
document->setHtml(strStream);
QPrinter printer;
QPrintDialog *dialog = new QPrintDialog(&printer, NULL);
if (dialog->exec() == QDialog::Accepted) {
document->print(&printer);
}
delete document;
here is my solution of a problem. May be it's too complex... But here you could find more solutions!
1). first I have saved table data to HTML page file:
bool CRefViewerDlg::createHtmlTableFromModel() {
// make a html-dump of table view
if (tableView) {
const QString htmlFileName = QString("%1/%2").arg(qApp->applicationDirPath()).arg("myTable.html");
QFile file(htmlFileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
MSG(QString("Can`t create file %1").arg(htmlFileName));
return false;
}
QTextStream out(&file);
const xbLong rowCount = tableView->model()->rowCount();
const xbLong columnCount = tableView->model()->columnCount();
out << "<html>\n"
"<head>\n"
"<meta Content=\"Text/html; charset=Windows-1251\">\n"
<< QString("<title>%1</title>\n").arg(refTitleName)
<< "</head>\n"
"<body bgcolor=#ffffff link=#5000A0>\n"
"<table border=1 cellspacing=0 cellpadding=2>\n";
// headers
out << "<tr bgcolor=#f0f0f0>";
for (xbLong column = 0; column < columnCount; column++)
if (!tableView->isColumnHidden(column))
out << QString("<th>%1</th>").arg(tableView->model()->headerData(column, Qt::Horizontal).toString());
out << "</tr>\n";
file.flush();
// data table
for (xbLong row = 0; row < rowCount; row++) {
out << "<tr>";
for (xbLong column = 0; column < columnCount; column++) {
if (!tableView->isColumnHidden(column)) {
QString data = tableView->model()->data(tableView->model()->index(row, column)).toString().simplified();
out << QString("<td bkcolor=0>%1</td>").arg((!data.isEmpty()) ? data : QString(" "));
}
}
out << "</tr>\n";
}
out << "</table>\n"
"</body>\n"
"</html>\n";
file.close();
}
return true;
}
2). after I have saved html content to file, it was opened in html view window, where I could print the document with QTextBrowser class:
void CLiveListDlg::on_printPageToolButton_clicked() {
#ifndef QT_NO_PRINTER
QTextBrowser *editor = static_cast<QTextBrowser* >(textBrowser);
QPrinter printer;
QPrintDialog *dialog = new QPrintDialog(&printer, this);
dialog->setWindowTitle(tr("Print Document"));
if (editor->textCursor().hasSelection())
dialog->addEnabledOption(QAbstractPrintDialog::PrintSelection);
if (dialog->exec() != QDialog::Accepted)
return;
editor->print(&printer);
#endif
}
How about this one?
Traverse through the model of your QTableView let's say QStandardItemModel. Obtain the each and individual texts of the items available in the QStandardItemModel.
Now using QTextCursor, insert the obtained texts from your model into QTextDocument. You can make use of the examples given here to insert text into QTextDocument.
After the completion of inserting into QTextDocument, you can print the contents available in the QTextDocument through
void QTextDocument::print ( QPrinter * printer ) const
The thing you have to make sure is that you should be able to traverse through each items so that you can able obtain all the item text from the model.
Hope it helps..