Unsolved TableView selectRow immediately after model reset doesn't work as expected
-
Hi,
I've been investing the better part of a day trying to figure out what is wrong with my otherwise fully functional QTableView/QTabelModel. The problem shows up when during selecting the tab that contains the view. In the context of the tab current changed slot, I update the model (which in turns call a beginModelReset and endModelReset) and I want to select the first row of the TableView. Now if I call tableView->selectRow(0) immediately after the model reset. Nothing happens... but if I do the same call for example when I click on a button somewhere else in my UI then it works fine. I managed to duplicate the problem with the fetchMore example from Qt.
Should I be waiting for the view to finish its refresh and if so how can I do that? I must be missing something trivial but I can't find the answer anywhere else.
Kind regards
-
I would connect (QueuedConnection) to QAbstractItemModel::modelReset() to make sure the internals of the model and view had time to react on the new state.
-
@Christian-Ehrlicher Thanks for your help and quick reply, sadly enough this is still not working... I've implemented it in the fetchMore example, this is seriously frustrating as it should be such a simple thing to accomplish. Any other ideas?
-
I don't see a reason why it should not work. What did you modify in the example so we can reproduce it?
-
@Christian-Ehrlicher Here it is:
{#include "filelistmodel.h" #include "window.h" #include <QtWidgets> Window::Window(QWidget *parent) : QWidget(parent) { FileListModel *model = new FileListModel(this); model->setDirPath(QLibraryInfo::location(QLibraryInfo::PrefixPath)); QLabel *label = new QLabel(tr("&Directory:")); QLineEdit *lineEdit = new QLineEdit; label->setBuddy(lineEdit); view = new QListView; view->setSelectionBehavior(QAbstractItemView::SelectRows); view->setModel(model); logViewer = new QTextBrowser; logViewer->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred)); connect(lineEdit, &QLineEdit::textChanged, model, &FileListModel::setDirPath); connect(lineEdit, &QLineEdit::textChanged, logViewer, &QTextEdit::clear); connect(model, &FileListModel::numberPopulated, this, &Window::updateLog); connect(model, &FileListModel::modelReset, this, &Window::selectARow); connect(view, &QListView::clicked, this, &Window::selectARow); QGridLayout *layout = new QGridLayout; layout->addWidget(label, 0, 0); layout->addWidget(lineEdit, 0, 1); layout->addWidget(view, 1, 0, 1, 2); layout->addWidget(logViewer, 2, 0, 1, 2); setLayout(layout); setWindowTitle(tr("Fetch More Example")); } void Window::updateLog(int number) { logViewer->append(tr("%1 items added.").arg(number)); } void Window::selectARow() { QModelIndex i = view->model()->index(1,0); if(i.isValid()) view->setCurrentIndex(i); }
I've connected the selectARow with two signals, one being the modelReset of the model and the other one being the clicked of the view to confirm my code indeed works as expected. This is just a quick and dirty demo, and I know there are corner cases where this might fail but it demonstrates the behavior I observe. Of course the prototypes for the selectARow slot needs to be added to the .h file, I didn't include the latter to keep this long post as short as possible.
Any help pointing me in the right direction would be much appreciated!
Kind regards
-
In the example you posted the problem comes from the fact that
view->model()->index(1,0);
does not exist as it was not loaded yet.If you reimplement
index()
in the model with something like this, you'll see everything works fineQModelIndex index(int row, int column, const QModelIndex &parent) const override { if(parent.isValid() || row<0 || column!=0) return QModelIndex(); while(row>=rowCount() && canFetchMore(QModelIndex())) const_cast<FileListModel*>(this)->fetchMore(QModelIndex()); if(row>=rowCount()) return QModelIndex(); return createIndex(row, column); }
Yes, this is a very bad implementation of
index()
but it's just to show where the problem is -
@VRonin Thanks for your help but it still isn't working. I've implemented index as you suggested but the view stubbornly refuses to select the proper entry after a model reset.... It seems to be independent of the model I use since as highlighted in the post title, I've started with a table model and now reverted back to the list model and still see the exact same behavior.
Am I trying to do something that was not intended to be done with the framework?
I'm using the default QListView/QTableView perhaps I need to derive my own and reimplement some functions to accomplish what I'm looking for...Again, any help or pointer to documentation or existing examples really appreciated
Kind regards
-
I tested the implementation above and works with the fetchMore example from Qt.
I suspect you have something similar in your model. Since there's no such thing as aQTabelModel
, could you post your model implementation so we can have a look at what's going wrong?