PDA

View Full Version : QTreeWidget and QProgressDialog?



progman
16th March 2010, 19:25
Hello,

I am writing an app in QT4.5 and the application is dialog based. The purpose of the app is to load in an error file, and parse the information to the user using a textview, which displays the end result in a html formatted view. The user also has push buttons to allow the error file to be exported as text, (it is imported as a bin file...), exported as a .csv formatted file and to allow the user to view the time stamps when all of the errors occured. My problem is with the timestamp part of the application.

I am using a QTreeWidget with QTreeWidgetItem which is called when the user presses the timestamps button. This will open the tree view in its own window, via a call to treeWidget->show(). With smaller files, everything works quite well, but, with larger files, say, 3 Mb in size, the treeWidget takes about 20 seconds before the formatted data is shown to the user. If your patient, not a problem, but I need some way of indicating to the user that the process is in fact occuring. I tried using a QProgressDialog as shown below, but the dialog is never shown to the user, and the treeWidget is not shown either until it has finished parsing the data.

How my tree widgets and progress dialog are called:



QTreeWidget *treeWidget = new QTreeWidget();
treeWidget->setMinimumSize(650, 400); // int width, int height
treeWidget->setColumnCount(3);
treeWidget->setAlternatingRowColors(true);

QStringList headerLabels;
headerLabels << "System Error Messages " << "Time Stamp: HH:MM:SS" << "Parameter";
treeWidget->setHeaderLabels(headerLabels);
treeWidget->resizeColumnToContents(1);
treeWidget->setColumnWidth(0, 325);
treeWidget->setWindowTitle(tr("Error Time Stamps"));
treeWidget->setWindowIcon(QIcon(":/images/My.ico"));

QProgressDialog *infProg = new QProgressDialog("Parsing Time Records...",0,0,0,this);
infProg->setRange(0,0);
infProg->setWindowModality(Qt::WindowModal);
QApplication::processEvents();

.... more code...
// and this is how the widget is displayed

infProg->setAutoClose(true);

treeWidget->show();




My question is, how would I show the progress dialog while the tree view is doing its thing in the background??

Thanks!

aamer4yu
17th March 2010, 05:29
Where is the code that takes 30 sec to process ? Need to see how you are processing it.

progman
17th March 2010, 13:43
Here is th code:

This section creates the main treeWidget....



QTreeWidget *treeWidget = new QTreeWidget();
treeWidget->setMinimumSize(650, 400); // int width, int height
treeWidget->setColumnCount(3);
treeWidget->setAlternatingRowColors(true);

QStringList headerLabels;
headerLabels << "System Error Messages " << "Time Stamp: HH:MM:SS" << "Parameter";
treeWidget->setHeaderLabels(headerLabels);
treeWidget->resizeColumnToContents(1);
treeWidget->setColumnWidth(0, 325);
treeWidget->setWindowTitle(tr("Error Time Stamps"));
treeWidget->setWindowIcon(QIcon(":/images/My.ico"));


This section parses out the error messages. Note that I have about 20 of these, similar in nature, but are used to parse out device specific error codes.



QTreeWidgetItem *tmuRoot = new QTreeWidgetItem(treeWidget); // TMU Errors - parent
tmuRoot->setText(0, tr("TMU Errors"));
treeWidget->addTopLevelItem(tmuRoot);

for(int i = 0; i<error.size();++i)
{
QTreeWidgetItem* infoTmu = new QTreeWidgetItem();
infoTmu->setIcon(0, QIcon(":/images/12-em-cross_12x12.png"));
infoTmu->setText(0, error[i]);
infoTmu->setText(1, time[i]);
infoTmu->setToolTip(0, ttTmu[i]);
infoTmu->setText(2,pTmu[i]);
tmuRoot->addChild(infoTmu);
}

treeWidget->show();


The treeWidget data is collected from an error file, which can be of any length, from as little as 256 bytes, up to 5 Mb. The error file is read into and stored inside four seperate QVectors. If the error file is small, the time stamp treeWidget is parsed rather quickly and has no issues. But if the error file is quite large, (the one I am using for testing is 3 Mb in size....) the treeWidget takes quite a bit of time to fill itself up with all the values, and then when completeted, is shown to the user. The other issue is when a parent is expanded, using the vertical scroll bar to see all the error timestamps is pretty much useless as it takes several seconds to refresh the view, but that is another issue all together.....

One section of errors, in this case anyways, has just over 300,000 child items - and this of course is the bottleneck. This is not normally the case as most child items have maybe a dozen or less errors, but we do get the odd case of a device that has been running for 24 hours or more, generating a large amount of errors.

My original question is how to present some indication to the user that the program is actually doing something in the background once they have clicked on the button to show the timestamps?

Thanks!

aamer4yu
17th March 2010, 17:21
I guess its the for loop in line 5 that processes the items from the file.
try putting this statement in the loop -
qApp->processEvents();

progman
17th March 2010, 17:42
I guess its the for loop in line 5 that processes the items from the file.
try putting this statement in the loop -
qApp->processEvents();

I did as you suggested and the treeview did not speed up any in the initial presentation to the user, but it did increase the performance when scrolling vertically. The treeview will still take a bit while scrolling, but I no longer recieve the 'Not Responding' message when the treeview is trying to update the view - so that's a bit of an improvement....

If I was to re-write this section, are there any class's that I should look at that would maybe speed the entire process up for the end user? Can a model/view architecture be of any benefit in parsing large amounts of data to the user or is there not really any 'clean' way of presenting such large amounts of data?

Thanks!

aamer4yu
18th March 2010, 10:12
Can a model/view architecture be of any benefit in parsing large amounts of data to the user
I guess yes.
In fact I remember we had implemented something similar when QTreeWidget had many items. Items would be cleared and added again on new data..and this was quite inefficient.
You can give model a try

progman
18th March 2010, 18:05
What if I load up the treeview widget, then load the data when someone expands the '+' sign? This way, I can at least show a progress dialog while the children of the root are being populated, but the trouble I am having now is connecting to the expanded signal. This is the code I was using for the signal, but the compiler complains about no matching function call for connect.



connect(&rm06Root, SIGNAL(itemExpanded(QTreeWidgetItem&)), this, SLOT(loadTree()));


rm06Root is declared as such, as well as the code checking for expansion and then calling the function loadTree()



rm06Root = new QTreeWidgetItem(treeWidget); // RMUX Errors - parent
rm06Root->setText(0, tr("Ringmux 6 Errors - Tied to DSP 2A"));
treeWidget->addTopLevelItem(rm06Root);
if(rmx06Err.size() != 0)
rm06Root->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndic ator);

if(rm06Root->isExpanded() == true)
loadTree();


and i have loadTree() declared in privateSlots.....

This is the actual error message:

/errordialog.cpp:80: error: no matching function for call to `ErrorDialog::connect(QTreeWidgetItem**, const char*, ErrorDialog* const, const char*)'

Thanks!