Multiple items selection without columns intersections in QTableView

14 hours ago 1
ARTICLE AD BOX

I want to create a table with multiple columns. At the same time, I want to allow the user to select several items in one column. If he tries to select items in several columns at once, the items in the other column simply will not be selected. I'm starting to do it like this:

#include "CityDelegate.h" #include <QApplication> #include <QTableView> #include <QStandardItemModel> #include <algorithm> int main(int argc, char *argv[]) { QApplication app(argc, argv); QList<QPair<int, QString>> cities = { {1, "New York"}, {2, "London"}, {3, "Tokyo"}, {4, "Paris"}, {5, "Berlin"}, }; QList<QPair<int, QString>> countries = { {1, "USA"}, {2, "UK"}, {3, "Japan"}, {4, "France"}, {5, "Germany"}, }; int rowSize = std::max(cities.size(), countries.size()); QStandardItemModel model(rowSize, 2); model.setHeaderData(0, Qt::Horizontal, "City"); model.setHeaderData(1, Qt::Horizontal, "Country"); for (int row = 0; row < cities.size(); ++row) { model.setData(model.index(row, 0, QModelIndex()), cities[row].second); } for (int row = 0; row < countries.size(); ++row) { model.setData(model.index(row, 1, QModelIndex()), countries[row].second); } auto *view = new QTableView; view->setModel(&model); view->setItemDelegateForColumn(0, new CityDelegate(cities, view)); view->setItemDelegateForColumn(1, new CityDelegate(countries, view)); view->setSelectionMode(QAbstractItemView::ExtendedSelection); view->setWindowTitle("City Selector"); view->resize(300, 200); view->show(); return app.exec(); }

I create a model, fill it with data, and then give it to the table for display, as well as create a delegate. The delegate looks like this:

#ifndef CITYDELEGATE_H #define CITYDELEGATE_H #include <QStyledItemDelegate> #include <QPair> #include <QString> #include <QVector> class CityDelegate : public QStyledItemDelegate { Q_OBJECT public: explicit CityDelegate(const QList<QPair<int, QString>> &cities, QObject *parent = nullptr); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void setEditorData(QWidget *editor, const QModelIndex &index) const override; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; private: QList<QPair<int, QString>> m_cities; }; #endif // CITYDELEGATE_H

And its implementation:

#include "CityDelegate.h" #include <QComboBox> CityDelegate::CityDelegate(const QList<QPair<int, QString>> &cities, QObject *parent) : QStyledItemDelegate(parent) , m_cities(cities) { } QWidget *CityDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { Q_UNUSED(option) Q_UNUSED(index) auto *combo = new QComboBox(parent); for (const auto &city : m_cities) combo->addItem(city.second, city.first); return combo; } void CityDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { auto *combo = qobject_cast<QComboBox *>(editor); if (!combo) return; const int code = index.data(Qt::UserRole).toInt(); const int idx = combo->findData(code); if (idx >= 0) combo->setCurrentIndex(idx); } void CityDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { auto *combo = qobject_cast<QComboBox *>(editor); if (!combo) return; model->setData(index, combo->currentData(), Qt::UserRole); model->setData(index, combo->currentText(), Qt::DisplayRole); }

The problem at the moment is that it is very difficult to select multiple fields at once. Ideally, what I want looks like this: the user holds down the shift or just moves the mouse over the fields, then selects something in one of the fields and everything that he has selected is automatically selected immediately for the other selected fields. As far as I understand, so that the user can simply swipe down with the mouse and the fields are selected, we add the following line:

view->setSelectionBehavior(QAbstractItemView::SelectItems);

But it doesn't work for me! If I select something in one field, it will be in the same field even though I have pinched the shift. How to fix that?

Read Entire Article