Reading QTableView row contents with the same order as are seen NOT stored
-
We have a QTableView which are filled with some arbitrary data. User can move rows of the table internally by drag and drop.
We want to read cell contents in the same order as are seen in the QTableView (as seen in the view NOT stored in the model). Currently by calling model->data() we access the cell contents as are stored in the model NOT as seen in the view (ordered are changed by row internal moves).
How is it possible to read cell contents such this way?
-
actually the model is not affected by reordering by internal moves in the view
-
The model is affected indeed, try this one, it works for me:
#include <QApplication> #include <QTableWidget> #include <QDebug> #include <QVBoxLayout> #include <QPushButton> int main(int argc, char* argv[]) { QApplication a(argc, argv); QWidget base; QTableWidget* tablWid = new QTableWidget(&base); tablWid->setDragDropMode(QAbstractItemView::InternalMove); ////////////////////////////////////////////////////////////////////////// // Fill the model with some data tablWid->model()->insertColumn(0); tablWid->model()->insertRows(0,10); for (int i = 0; i < 10; ++i) tablWid->model()->setData(tablWid->model()->index(i, 0), "Item " + QString::number(i)); ////////////////////////////////////////////////////////////////////////// QPushButton* dumpButton = new QPushButton("Dump Model", &base); QObject::connect(dumpButton, &QPushButton::clicked, [tablWid]()->void { for (int j = 0; j < tablWid->model()->rowCount();++j){ qDebug() << tablWid->model()->index(j, 0).data().toString(); } }); QVBoxLayout* baseLay = new QVBoxLayout(&base); baseLay->addWidget(tablWid); baseLay->addWidget(dumpButton); base.show(); return a.exec(); }
-
@VRonin Sorry, I've meant to move sections (vertical header) so change the code this way:
#include <QApplication> #include <QTableWidget> #include <QDebug> #include <QVBoxLayout> #include <QPushButton> #include <QHeaderView> int main(int argc, char* argv[]) { QApplication a(argc, argv); QWidget base; QTableWidget* tablWid = new QTableWidget(&base); // tablWid->setDragDropMode(QAbstractItemView::InternalMove); tablWid->verticalHeader()->setSectionsMovable(true); tablWid->verticalHeader()->setDragEnabled(true); ////////////////////////////////////////////////////////////////////////// // Fill the model with some data tablWid->model()->insertColumn(0); tablWid->model()->insertRows(0,10); for (int i = 0; i < 10; ++i) tablWid->model()->setData(tablWid->model()->index(i, 0), "Item " + QString::number(i)); ////////////////////////////////////////////////////////////////////////// QPushButton* dumpButton = new QPushButton("Dump Model", &base); QObject::connect(dumpButton, &QPushButton::clicked, [tablWid]()->void { for (int j = 0; j < tablWid->model()->rowCount();++j){ qDebug() << tablWid->model()->index(j, 0).data().toString(); } }); QVBoxLayout* baseLay = new QVBoxLayout(&base); baseLay->addWidget(tablWid); baseLay->addWidget(dumpButton); base.show(); return a.exec(); }
Now, by moving vertical sections (reordering rows), the model is not affected by reordered rows.
-
this should return the list of the row indexes as sorted in the view. Hidden rows will be placed at the beginning
QList<int> viewIndexes(const QHeaderView* const view){ if(!view) return QList<int>(); const int numSections= view->count(); QMap<int,int> sorter; for(int i=0;i<numSections;++i) sorter.insert(view->sectionPosition(i),i); return sorter.values(); }
or alternatively:
QVector<int> viewIndexes(const QHeaderView* const view){ if(!view) return QVector<int>(); const int numSections=view->count(); QVector<int> result(numSections); for(int i=0;i<numSections;++i) result[i]=i; // Use stable_sort if you want the hidden sections still placed at the beginning but in the same order as the original model std::sort(result.begin(),result.end(),[view](int a,int b)->bool{return view->sectionPosition(a)<view->sectionPosition(b);}); return result; }
You'll have to benchmark them to tell which is more efficient