Well yes. The auto-update still doesn't work since I'm not able to figure out what else I'm missing..
Well yes. The auto-update still doesn't work since I'm not able to figure out what else I'm missing..
But the initial loading works?
Are you calling the same load method for updating or do you use something else?
Cheers,
_
The data shows up in my QTableView correctly but still when the data of the csv file changes (doesn't matter if that happens outside of the qt app or with a button which adds new data) it doesn't update/refresh itself. It only refreshes if the app is restarted or if the QDialog is closed and reopened.
How do you handle these two cases?
Do you watch the file for changes and then call the load method?
What do you do in the slot connected to the button? Also reload the file?
Cheers,
_
When opening the dialog I've connected the dataChanged() signal to a slot which shows a debug message in the console. the connect() call returns true in debug.
The commented lines (reloading the model) didn't make any difference.Qt Code:
{ ... connect(model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(onModelsDataChanged(const QModelIndex&, const QModelIndex&))); ... } { Q_UNUSED(topLeft); Q_UNUSED(bottomRight); qDebug() << "YES" << endl; // model->loadFromFile(fileName); // fileName = path/to/value.csv // ui->tableView->setModel(model); }To copy to clipboard, switch view to plain text mode
The button just increments a number when it's clicked and writes it to the file:
Qt Code:
void Dialog::onButtonPush() { x++; stream << "Clicked button number;" << x << endl; } log.flush(); log.close(); }To copy to clipboard, switch view to plain text mode
Button and tableview are on the same dialog window and the tableview is supposed to be updated as soon as the data changes - e.g. every time the button is clicked. The updating doesn't work though. :/
I don't understand this ":/value.csv" filename. That is the name for a file that would ordinarily be compiled into your program as a resource. You can't write to it from a logging process, because it doesn't really exist as a disk file. So if you keep trying to load the same file (from resources), of course the content never changes.
As anda_skoa has asked, where is your code for watching the log file on disk and reacting if it changes? You should have a QFileSystemWatcher or some other object that is watching this file, and slot connected to its signal that tells your app when the file has changed. Then you load it into your model using the name of the log file on disk, not the name of the file from the resources.
<=== The Great Pumpkin says ===>
Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.
Hi d_stranz,
thanks for your reply.
I've got a logger class which writes data into that csv file lying on my fs. You're right with the notation - just wanted to shorten it.
The path to the file is /home/micha/qt-app/value.csv. In my case the delimiter of the csv file is ";" instead of ",".
The file is loaded correctly into my tableview and as said i just want to update the tableview during runtime which should work with e.g. the dataChanged() signal. New data is written into that file correctly as well (when I open the file from desktop) or when I restart the application the new data is shown correctly in the tableview underneath the "old" data.
My only problem is that it's not inserted during runtime. The tableview is not showing it until I load the model into it again manually via pushbutton or whatever. I've read a lot about the dataChanged() signal which should be fired as soon as the data (row / column change) of the file changes. Somehow one can connect it to repaint, update, whatever the tableview to automatically show newly added data during runtime. And that is what's not working in my case and I simply don't know why..
Last edited by MichaH; 5th August 2016 at 17:33.
The dataChanged() signal applies only to the model, not to your log file. How is your model being notified that the data in the file is changed? What is causing your model to reload the data from the file (besides your manual push button method)?
I don't see anything in the code you have posted that indicates your program is watching the disk file for changes. There is no automatic connection between the disk file and your model. You have to write some code to watch the disk file that will trigger your model to reload it when it is changed.
<=== The Great Pumpkin says ===>
Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.
That's embarrassing... you're absolutely right! a QFileSystemWatcher could do the trick.
Thank you both so much for your efforts and replies!!! Maybe I'll get back to you if I get stuck on this!
The only code you have posted so far that contains an emit for that signal is setData(), but you have not posted any code that calls setData().
As far as we can tell you just never execute any code that emits dataChanged()
You haven't posted any code that would insert data.
It is emitted then you tell your model to emit it.
Which you do in setData().
Which you don't seem to call at all.
Given your data it is probably never emitted, as that would require that a log record changes.
But in all likelyhood you are just appending new records to the log file.
The table view does that internally.
You mean that when you edit a cell in the table view through the UI, then it doesn't call setData()?
Or that setData() is being called but the signal is not emitted?
Cheers,
_
You're right, I'm not using setData(..) at all. I'm only calling my own slot loadFromFile(..). I'm finally understanding what's causing my problems. Takes some time to refactor everything but I'm letting you know if I managed to get it working!!
Thank you for your advices!
If you are completely replacing the model's content when you re-read the file, and you are not editing the model through the GUI, then don't bother with implementing setData(). In your file load method, first call beginResetModel(), then clear the model and replace the contents, then call endResetModel(). This will take care of notifying any watchers (like your table view) that they need to update their display.
I use this method when I map the output of a data analysis computation into a QAbstractItemModel. The computational results are almost all entirely new, so it is easier to simply trash the model contents and refill it from the new results. This is slower but far easier than having to try to figure out what's changed and update only those bits.
<=== The Great Pumpkin says ===>
Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.
Well I thought that I did that in my loadFromFile() slot (as you can see above) since I don't need to edit the model through the gui at all.
That "static" approach would meet my needs. But I reckon I'm missing the replacing part in my code!?
Yes, I see you are calling begin / endResetModel(). You are missing the QFileSystemWatcher part to trigger the reload.But I reckon I'm missing the replacing part in my code!?
Your code to parse the CSV file looks overly complex. Why don't you simply read the text stream line-by-line into a QString using QTextStream::readLine() (instead of character-by-character), and then use QString::split() with ';' as the split character, and behavior set to KeepEmptyParts? You'd then get a QStringList for every row in the table and could replace about 20 lines of parsing code with 4.
Qt Code:
while ( !in.atEnd() ) { // appendToCSVMatrix( fields ); }To copy to clipboard, switch view to plain text mode
In fact, if all you are doing is reading a CSV file and displaying the fields in a table view, you can dispense with using a QAbstractTableModel entirely and simply use QTableWidget as is and insert the fields as QTableWidgetItem instances. Let your MainWindow handle watching the log file and reloading the table when needed.
Last edited by d_stranz; 5th August 2016 at 19:10.
<=== The Great Pumpkin says ===>
Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.
And you are not emitting it in any method that you are executing.
How is a signal supposed to happen if its emit is not on a code path that is being executed?
Of course that didn't make any difference, there is not a single emit dataChanged() in your load method.
The load method resets the model, if you want to trigger on that connect to modelReset().
No call on the model, so how would the model emit a signal?
Cheers,
_
Bookmarks