Populating Table Widget from Text File in Qt - qt

I'm new to Qt and need some help with the following:
I would like to create a GUI containing a Table Widget that is populated by information coming from a tab delimited text file. In my GUI, the user would first browse for the text file and then it would then show the contents in the Table Widget. I've done the browse part, but how do I load the data from the text file into the Table Widget?

It's two steps, parse the file, and then push it into the widget.
I grabbed these lines from the QFile documentation.
QFile file("in.txt");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;
while (!file.atEnd()) {
QByteArray line = file.readLine();
process_line(line);
}
Your process_line function should look like this:
static int row = 0;
QStringList ss = line.split('\t');
if(ui->tableWidget->rowCount() < row + 1)
ui->tableWidget->setRowCount(row + 1);
if(ui->tableWidget->columnCount() < ss.size())
ui->tableWidget->setColumnCount( ss.size() );
for( int column = 0; column < ss.size(); column++)
{
QTableWidgetItem *newItem = new QTableWidgetItem( ss.at(column) );
ui->tableWidget->setItem(row, column, newItem);
}
row++;
For more information about manipulating QTableWidgets, check the documentation. For new users using the GUI builder in Qt Creator, it is tricky figuring it out at first.
Eventually I would recommend to switching to building the GUI the way they do in all their examples... by adding everything by hand in the code instead of dragging and dropping.

Sorry...
void squidlogreader_::process_line(QString line)
{
static int row = 0;
QStringList ss = line.split('\t');
if(ui->tableWidget->rowCount() < row + 1)
ui->tableWidget->setRowCount(row + 1);
if(ui->tableWidget->columnCount() < ss.size())
ui->tableWidget->setColumnCount( ss.size() );
for( int column = 0; column < ss.size(); column++)
{
QTableWidgetItem *newItem = new QTableWidgetItem( ss.at(column) );
ui->tableWidget->setItem(row, column, newItem);
}
row++;
}
void squidlogreader_::on_pushButton_clicked()
{
QFile file("in.txt");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;
while (!file.atEnd()) {
QString line = file.readLine();
process_line(line);
}

Related

Print db file displayed in tableView

Is it possible to add print option to print the db contents in tableView of Qt?
ie, I have a test.db displayed in tableView. I want to add an option to print the database. Is it possible?
If you mean printing with a printer, it can be basicly done like this:
int width = 0;
int height = 0;
tableView->resizeColumnsToContents();
const int columnCnt = tableView->model()->columnCount();
for( int i = 0; i < columnCnt; ++i )
{
width += pTableView->columnWidth(i);
}
const int rowCnt = tableView->model()->rowCount();
for( int i = 0; i < rowCnt; ++i )
{
height += tableView->rowHeight(i);
}
tableView->setFixedSize(width, height);
QPrinter printer;
// ... printer settings ...
tableView->render(&printer);
You can find more about this topic here:
http://blog.qt.io/blog/2012/08/24/qt-commercial-support-weekly-25-printing-large-tables-2/
I used the code in the below link
http://www.qtcentre.org/archive/index.php/t-64182.html
but when I call the function using a QPushButton, the application freezes and get closed.
What's the error in the code?

Saving a qlistwidget after closing application

I have a program that allows for a user to create a profile that saves values using qsettings, the user accesses their profile by clicking on the name in a qlistwidget. I am trying to save the names of the profiles by using a text file but I am having trouble saving more than one profile name at a time. thank you! here is the code:
for saving a profilename to the text document
void Profile::writeProfilenames()
{
QString profilename = ui->lineEdit_profilename->text();
profilename = profilename.simplified();
QFile pfile("profilenames.txt");
if (!pfile.open(QFile::WriteOnly | QIODevice::Text))
{
return;
}
QTextStream out(&pfile);
out << profilename;
pfile.flush();
pfile.close();
}
for retrieving the profile names from the document
void Profile::readProfilenames()
{
QFile pfile("profilenames.txt");
if (!pfile.open(QIODevice::ReadOnly |
QIODevice::Text))
{
return;
}
QString proname = pfile.readLine();
QListWidgetItem *itm = new QListWidgetItem;
itm->setText(proname);
ui->listWidget_profiles->insertItem(0,itm);
}
P.S. if you know of a better way to do this then feel free to share! (with example please)
I don't quite see why you're saving the list of names in a text file, while the settings themselves are saved in a platform-specific fashion using QSettings.
The code you show has several problems:
Presumably you don't want to "write" the name to the file, overwriting the existing contents at the beginning, but specifically to append to the file. You also must specify a writable path to the file, so far you're using the current working directory that is: variable, not under your control, and not necessarily writable. Your code also doesn't handle repeated names.
QFile is a proper C++ class, and embodies the RAII principles. You don't have to do anything to flush and close the file. The compiler takes care of generating the proper code for you. That's why you're using C++ and not C, after all. Yes, your code compiles, but it reads like C, and such verbosity is unnecessary and counterproductive.
You're only retrieving one name from the file. You want to retrieve all of them.
I'd say that you should dispense with the file access, set up your application's identification, a crucial prerequisite to using QSettings, and, finally, use them:
struct Profile {
QString name;
int age;
}
void saveProfiles(const QList<Profile> & profiles)
{
QSettings s;
s.beginWriteArray("profiles");
for (int i = 0; i < profiles.size(); ++i) {
s.setArrayIndex(i);
const Profile & p = profiles.at(i);
s.setValue("name", p.name);
s.setValue("age", p.age);
}
s.endArray(); //optional
}
QList<Profile> loadProfiles()
{
QList<Profile> profiles;
QSettings s;
int size = s.beginReadArray("profiles");
for (int i = 0; i < size; ++i) {
s.setArrayIndex(i);
Profile p;
p.name = s.value("name").toString();
p.age = s.value("age").toInt();
profiles << p;
}
s.endArray(); // optional
return profiles;
}
int main(int argc, char ** argv) {
QApplication app(argc, argv);
app.setOrganizationName("fluxD613"); // ideally use setOrganizationDomain instead
app.setApplicationName("fluxer");
...
return app.exec();
}
After a lot more research and trial and error I came up with the following code that does the trick:
this function is implemented when I close the profiles dialog window and return to the main window using QCloseEvent.
void Profile::writeProfilenames()
{
QFile pfile("profilenames.txt");
if (!pfile.open(QFile::WriteOnly | QIODevice::Text))
{
return;
}
for(int row = 0; row < ui->listWidget_profiles->count(); row++)
{
QListWidgetItem *item = ui->listWidget_profiles->item(row);
QTextStream out(&pfile);
out << item->text().simplified() << "\n";
}
pfile.close();
}
reading the list of profilenames is implemented when I open the dialog window just under ui->setup(this).
void Profile::readProfilenames()
{
QFile pfile("profilenames.txt");
if (!pfile.open(QIODevice::ReadOnly |
QIODevice::Text))
{
return;
}
QTextStream in(&pfile);
while (!in.atEnd())
{
QString line = in.readLine();
QListWidgetItem *item = new QListWidgetItem;
item->setText(line);
ui->listWidget_profiles->addItem(item);
}
pfile.close();
}
I am now working on making sure the user does not enter a profilename that already exists and deleting a profilename from the QListWidget.

Multiple file insert in QTreewidget using Drag and Drop events

I am working in Qt4.7 on MAC OSx. I want to insert files in QTreewidget using the Drag and Drop events. I want to add multiple files at a time. I am using this:
void MainWindow::dragEnterEvent(QDragEnterEvent * e)
{
if(e->mimeData()->hasUrls())
{
e->acceptProposedAction();
}
}
void MainWindow::dropEvent(QDropEvent * e)
{
QTreeWidgetItem *Items = new QTreeWidgetItem(ui->treeWidget);
foreach(const QUrl &url,e->mimeData()->urls())
{
const QString &filename = url.toLocalFile();
qDebug() << "Dropped file:" << filename;
Items->setText(0,filename);
}
}
Using this, I am able to insert only one file at a time. Is there anyone who can help me out in this issue ? Your help will really appreciate.
Thanks,
Ashish.
The problem is that you create only one tree view item. However you need one per each Url you passed with the mime data:
void MainWindow::dropEvent(QDropEvent *e)
{
foreach(const QUrl &url, e->mimeData()->urls()) {
QString filename = url.toLocalFile();
qDebug() << "Dropped file:" << filename;
QTreeWidgetItem *item = new QTreeWidgetItem(ui->treeWidget);
item->setText(0, filename);
}
}

QT :how to check if there Empty cell in qt table widget

i have table widget with specific row and column ,
my function is as follow
get value from the first column and second column
compare between them and return result in the third column
Ex: first column :1 2 3 Second column 2 2 3 Result column No Yes Yes
I make sure that my code work by using the qDebug, however when I compile and run it the mainwindow stopped and crash.
I use for loop to go throw all rows for(int row=0;rowtableWidget->rowCount();row++)
I think this line rowtableWidget->rowCount() coz when it read empty cells the app Freeze and stop working .
how can I void that to happen
void MainWindow::GenerateRes() {
QString Result;
for(int row = 0; row < ui->tableWidget->rowCount(); row++) {
QString R1 = ui->tableWidget->item(row, 0)->text();
QString R2 = ui->tableWidget->item(row, 1)->text();
if(R1 == R2) {
Result = "P" ;
} else {
Result = "F" ;
}
QTableWidgetItem *Item = new QTableWidgetItem(Result);
ui->tableWidget->setItem(row, 2, Item);
qDebug() << Item;
}
}
To check whether the cell(i,j) in QTableWidget is empty or not, use isNull() or isEmpty().
Example:
for(int i=0; i < ui->tableWidget->rowCount(); i++)
{
for(int j=0; j < ui->tableWidget->columnCount(); j++)
{
bool flag = ui->tableWidget->item(i,j)->text().isNull();
if (!flag) /* the cell is not empty */
{
// do stuff
}
else /* the cell is empty */
{
// do stuff
}
}
}
maybe you should check the values returned from tableWidget::item(), because the functions can return 0 if no item is asigned to the provided coordinates, and in that case you're trying to call a method (QTableWidgetItem::text()) on a zero pointer.
Try something like:
QString R1;
QTableWidgetItem *item1(ui->tableWidget->item(row,0));
if (item1) {
R1 = item1->text();
}
// and so on...
Your code looks strange anyway, the 5th line (ui->tableWidget->rowCount()) doesn't make sense, you shouldn't be able to compile that (at least you're missing a semicolon).

Updating a view displayed by QTableView

I have a QTableView widget which is filled with the help of QStandardItemModel.
In every two seconds the function containing these two classes is called using QTimer and next 50 entries are given.
The function runs properly after every two seconds but the values arent refreshed in the window displayed.
Thanks in advance for any help.
Code :
void Box::create_frame()
{
k=0;
tablegroup = new QGroupBox(tr("Table"));
QVBoxLayout *layout = new QVBoxLayout;
table = new QTableView(this);
table->setUpdatesEnabled(false);
cout << "recent check" <<endl;
QStandardItemModel *mode = new QStandardItemModel(1,2,this);
mode->setHorizontalHeaderItem(0, new QStandardItem(QString("ID")));
mode->setHorizontalHeaderItem(1, new QStandardItem(QString("DATA")));
map<int,QString>::iterator it;
for(it=dataa.begin();it!=dataa.end();it++)
{
for(int i=0;i<=1;i++)
{
QStandardItem *item;
item = new QStandardItem();
item->setEditable(true);
if(i==0)
{
item->setData(((*it).first), Qt::DisplayRole);
mode->setItem(k,i,item);
}
else
{
item->setData(((*it).second), Qt::DisplayRole);
mode->setItem(k,i,item);
}
}
k++;
}
//setUpdatesEnabled(false);
table->setUpdatesEnabled(true);
cout << "create frame check" << endl;
table->setModel(mode);
layout->addWidget(table);
tablegroup->setLayout(layout);
}
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(refresh()));
timer->start(2000);
}
void dataThread::run()
{
boost::posix_time::seconds delay(2);
int g=0;
int h=50;
while(1)
{
while(g<h)
{
dataa.insert(pair<int,QString>(g+1,"HELLO"));
g++;
}
boost::this_thread::sleep(delay);
h=h+50;
}
}
First, it's late here so maybe I'm overlooking something but from your run loop, it doesn't look like you are actually adding any data to your table's model rather you're just adding entries to your dataa vector/list.
Maybe you should add this to your run loop
while( g < h )
{
dataa.insert(pair<int,QString>(g+1,"HELLO"));
QStandardItem *item;
item = new QStandardItem();
item->setEditable(true);
item->setData( g+1, Qt::DisplayRole );
// You need the model here
table->model()->setItem( h + g, 0, item );
item = new QStandardItem();
item->setData( "Hello", Qt::DisplayRole );
// You need the model again here
table->model->setItem( h + g, 1, item );
++g;
}
Again its late but I think you get the idea. You're currently not changing the model that your table is set to, rather just changing your dataa vector/list.

Resources