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?
-
QTableWidget inherits QTableView so they are the same thing. I believe accessing the
model()
of QTableWidget is what you want@VRonin The model is not in the same order as view (row orders are changed in view by drag-drop). So, I need a way to read values with same order as QTableWidget.
-
Hi,
The model content should have been moved following your drag & drop action so @VRonin is right.
@SGaist No, By internal moves between rows in table, the model content is not changed and only the view content is changed.
-
@SGaist No, By internal moves between rows in table, the model content is not changed and only the view content is changed.
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(); }
-
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