Custom QAbstractTableModel class updating QTableView
-
@Sebbo
First please make sure that the connect() call returns true. If not check the console output for the cause.Also no line of this code makes any (functional) sense:
int row1 = csvMatrix.rowCount(); QModelIndex index; beginInsertRows(QModelIndex(), row1, row1 + index.row() - 1); QModelIndex transposedIndex = createIndex(index.column(), index.row()); emit dataChanged(transposedIndex, transposedIndex); emit layoutChanged(); endInsertRows();
As i said the correct approach for the loadFromFile() method would be to call
beginRestModel()
at the beginning of the method andendRestModel()
at the end of the method. No dataChanged(), no beginInsertRows(), no layoutChanged(), etc. signals ...The dataChanged() signal should only called for already existing indexes.
-
I forgot to tell that I tested the method with beginResetModel() and endResetModel() as well (without trying to emit all the signals) which didn't do the trick. My apologies.
The connect() call returns true.
-
@Sebbo
but to make sure i didn't mean that the beginResetModel()/endResetModel() signals do internally emit the dataChanged() singal! Instead they emitmodelAboutToBeReset()
andmodelReset()
respectively.Whats do you actually want to achieve in the onModelsDataChanged() slot?
-
@raven-worx
Thank you for the effort!!For testing purposes I've added a pushbutton which adds a row with some foo-text to the csv file. But since I wasn't able to show the newly stored data inside the qtableview I wanted to see whether the dataChanged() signal is emitted and calls the method with just a console output.
What I've done in first place was torepaint() / update()
the tableview inside the onModelsDataChanged() method. -
@Sebbo
ok here are my thoughts:The simplest approach is the "static" one. It just displays the contents of the csv file at the time it is opened:
- in the loadFromFile() method do like i said and use the reset mechanism; the reset tells the view that it should forget all about what it knows from the model and that it should get all the data again
The disadvantage of the rest-method is that the view looses it's selection, scroll position, current index, etc.
For a more "dynamic" approach you need to do this:
- implement the same loadFromFile() method like for the "static" approach. But additionally you also install an QFileSystemWatcher on that file and connect it's fileChanged() signal to a new slot called something like "csvFileContentsChanged"
- in the loadFromFile() method you need to uninstall the old QFileSystemWatcher everytime a new/different file is set
- also save the count of lineNumbers read from the csv file
- in the new csvFileContentsChanged slot read the csv file line by line and compare the new line count to the previously stored one. If the new line count is higher you need to call beginInsertRows()/endInsertRows() signals, if the new count is smaller you need to call beginRemoveRows()/endRemoveRows(). And dataChanged() for the rest of the indexes which are already there.
Pseudo code:
void csvFileContentsChanged() { // read cvs file again into a local "tmpCsvMatrix" temporary variable int newLineCount = ...; int diff = qAbs( newLineCount - oldLineCount ); if( newLineCount < oldLineCount ) { beginRemoveRows( QModelindex(), newLineCount, newLineCount + diff - 1 ); csvMatrix = tmpCsvmatrix; endRemoveRows(); } else if( newLineCount > oldLineCount ) { beginInsertRows( QModelindex(), oldLineCount, oldLineCount + diff - 1 ); csvMatrix = tmpCsvMatrix; endInsertRows(); } // emit dataChanged for the rest of the indexes, since we do not know if their content actually has changed inside the csv file if( rowCount() > 0 && columnsCount() > 0 ) emit dataChanged( index(0, columnCount()-1), index(newLineCount-1 ,columnCount()-1) ); }
I haven't tested this though.
-
Thank you so much for your efforts and thoughts!!!
I like the idea of your 2nd dynamic approach but I have to admit that the 1st one still doesn't work for me.beginResetModel(); csvMatrix.clear(); endResetModel();
doesn't update the QTableView neither if new data is added outside Qt nor if the QPushButton is clicked which opens the file, writes into it (QTextStream) and closes it afterwards. :(
-
@Sebbo
because is said you should trigger these signals at the beginning and the end of the loadFromFile() method. Mens the very first and very last call inside the method.
Between those 2 signal calls you need to update your data structure. -
That is exactly what I'm not getting right now. Don't get me wrong I know where to put the begin/endReset members of the model but I'm embarrassingly lost on how to update the data in between....
-
@Sebbo
in between these 2 signals you just need to replace yourcsvMatrix
variable, thats all
Since you take all the model data from this variable -
@raven-worx
Jackpot! Thank you so much for your help!! Finally I did it using QFileSystemWatcher.
Thumbs up for you (if possible?!). :)Thread marked as solved.
Cheers