From 42098ae51473d002c8e7c730cd6cd754771d7250 Mon Sep 17 00:00:00 2001 From: Neil Horne Date: Fri, 23 Jun 2023 09:07:55 +1000 Subject: [PATCH] feat(cpn): Add radio sort order edit and sorting models list by any column (#3659) * feat(cpn): Add radio sort order edit (color) and sorting models list by any column (all) * Add column double click to enable/disable model sorting (disabled by default) --- companion/src/firmwares/radiodata.cpp | 35 ++++++++ companion/src/firmwares/radiodata.h | 16 ++++ companion/src/mdichild.cpp | 124 +++++++++++++++++++------- companion/src/mdichild.h | 10 ++- companion/src/modelslist.cpp | 13 ++- companion/src/modelslist.h | 61 ++++++++----- 6 files changed, 204 insertions(+), 55 deletions(-) diff --git a/companion/src/firmwares/radiodata.cpp b/companion/src/firmwares/radiodata.cpp index f02a91411..c09dd801b 100644 --- a/companion/src/firmwares/radiodata.cpp +++ b/companion/src/firmwares/radiodata.cpp @@ -21,6 +21,7 @@ #include "radiodata.h" #include "radiodataconversionstate.h" #include "eeprominterface.h" +#include "compounditemmodels.h" RadioData::RadioData() : sortOrder(0) @@ -308,3 +309,37 @@ QString RadioData::unEscapeCSV(QString str) str.replace("//","/"); return str; } + +// static +QString RadioData::modelSortOrderToString(int value) +{ + switch(value) { + case MSO_NO_SORT: + return tr("None"); + case MSO_NAME_ASC: + return tr("Name %1").arg(CPN_STR_SW_INDICATOR_UP); + case MSO_NAME_DES: + return tr("Name %1").arg(CPN_STR_SW_INDICATOR_DN); + case MSO_DATE_ASC: + return tr("Last Opened %1").arg(CPN_STR_SW_INDICATOR_UP); + case MSO_DATE_DES: + return tr("Last Opened %1").arg(CPN_STR_SW_INDICATOR_DN); + default: + return CPN_STR_UNKNOWN_ITEM; + } +} + +// static +AbstractStaticItemModel * RadioData::modelSortOrderItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName("radio.modelsortorder"); + + for (int i = 0; i < MSO_SORT_COUNT; i++) { + mdl->appendToItemList(modelSortOrderToString(i), i); + } + + mdl->loadItemList(); + return mdl; +} + diff --git a/companion/src/firmwares/radiodata.h b/companion/src/firmwares/radiodata.h index 4bd35b28a..36db06466 100644 --- a/companion/src/firmwares/radiodata.h +++ b/companion/src/firmwares/radiodata.h @@ -8,7 +8,20 @@ #include +// identiying names of static abstract item models +constexpr char AIM_RADIO_MODEL_SORT_ORDER[] {"radio.modelsortorder"}; + class RadioDataConversionState; +class AbstractStaticItemModel; + +enum MODEL_SORT_ORDER{ + MSO_NO_SORT, + MSO_NAME_ASC, + MSO_NAME_DES, + MSO_DATE_ASC, + MSO_DATE_DES, + MSO_SORT_COUNT +}; class RadioData { Q_DECLARE_TR_FUNCTIONS(RadioData) @@ -52,6 +65,9 @@ class RadioData { void fixModelFilenames(); QString getNextModelFilename(); + static QString modelSortOrderToString(int value); + static AbstractStaticItemModel * modelSortOrderItemModel(); + // leave here until all calls repointed static QString getElementName(const QString & prefix, unsigned int index, const char * name = 0, bool padding = false) { return DataHelpers::getElementName(prefix, index, name, padding); } diff --git a/companion/src/mdichild.cpp b/companion/src/mdichild.cpp index 4c18f39a8..2a10e32c2 100644 --- a/companion/src/mdichild.cpp +++ b/companion/src/mdichild.cpp @@ -41,19 +41,20 @@ MdiChild::MdiChild(QWidget * parent, QWidget * parentWin, Qt::WindowFlags f): QWidget(parent, f), ui(new Ui::MdiChild), - modelsListModel(NULL), - labelsListModel(NULL), + modelsListModel(nullptr), + labelsListModel(nullptr), + modelsListProxyModel(nullptr), parentWindow(parentWin), - radioToolbar(NULL), - modelsToolbar(NULL), - labelsToolbar(NULL), - lblLabels(NULL), - + radioToolbar(nullptr), + modelsToolbar(nullptr), + labelsToolbar(nullptr), + lblLabels(nullptr), firmware(getCurrentFirmware()), lastSelectedModel(-1), isUntitled(true), forceCloseFlag(false), - stateDataVersion(1) + stateDataVersion(1), + cboModelSortOrder(nullptr) { ui->setupUi(this); setWindowIcon(CompanionIcon("open.png")); @@ -76,6 +77,7 @@ MdiChild::MdiChild(QWidget * parent, QWidget * parentWin, Qt::WindowFlags f): ui->modelsList->setDragDropMode(QAbstractItemView::DragDrop); ui->modelsList->setStyle(new ItemViewProxyStyle(ui->modelsList->style())); ui->modelsList->setStyleSheet("QTreeView::item {margin: 2px 0;}"); // a little more space for our drop indicators + ui->lstLabels->setContextMenuPolicy(Qt::CustomContextMenu); retranslateUi(); @@ -117,6 +119,7 @@ MdiChild::MdiChild(QWidget * parent, QWidget * parentWin, Qt::WindowFlags f): MdiChild::~MdiChild() { + delete modelSortOrderItemModel; delete ui; } @@ -191,7 +194,7 @@ QAction * MdiChild::addAct(Actions actId, const QString & icon, const char * slo newAction->setIcon(CompanionIcon(icon)); if (!shortcut.isEmpty()) newAction->setShortcut(shortcut); - if (slotObj == NULL) + if (slotObj == nullptr) slotObj = this; if (slot) connect(newAction, SIGNAL(triggered()), slotObj, slot); @@ -206,7 +209,7 @@ void MdiChild::setupNavigation() act->deleteLater(); } action.clear(); - action.fill(NULL, ACT_ENUM_END); + action.fill(nullptr, ACT_ENUM_END); addAct(ACT_GEN_EDT, "edit.png", SLOT(generalEdit()), tr("Alt+Shift+E")); addAct(ACT_GEN_CPY, "copy.png", SLOT(copyGeneralSettings()), tr("Ctrl+Alt+C")); @@ -284,6 +287,18 @@ void MdiChild::setupNavigation() if ((btn = qobject_cast(radioToolbar->widgetForAction(action[ACT_GEN_SIM])))) { btn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); } + + if (cboModelSortOrder) + cboModelSortOrder->deleteLater(); + cboModelSortOrder = new QComboBox(this); + modelSortOrderItemModel = RadioData::modelSortOrderItemModel(); + cboModelSortOrder->setModel(modelSortOrderItemModel); + connect(cboModelSortOrder, QOverload::of(&QComboBox::currentIndexChanged), [=] (int index) { + radioData.sortOrder = index; + setModified(); + }); + action.replace(ACT_GEN_SRT, radioToolbar->addWidget(cboModelSortOrder)); + // add spacer to right-align the buttons QWidget * sp = new QWidget(this); sp->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); @@ -328,7 +343,14 @@ void MdiChild::updateNavigation() labelsToolbar->setVisible(hasLabels); ui->lstLabels->setVisible(hasLabels); lblLabels->setVisible(hasLabels); + action[ACT_GEN_PST]->setEnabled(hasClipboardData(1)); + if (hasLabels) { + cboModelSortOrder->blockSignals(true); + cboModelSortOrder->setCurrentIndex(radioData.sortOrder); + cboModelSortOrder->blockSignals(false); + } + action[ACT_GEN_SRT]->setVisible(hasLabels); action[ACT_MDL_CUT]->setEnabled(modelsSelected); action[ACT_MDL_CUT]->setText(tr("Cut") % (modelsSelected ? sp % modelsRemvTxt : ns)); @@ -355,6 +377,7 @@ void MdiChild::retranslateUi() action[ACT_GEN_CPY]->setText(tr("Copy Radio Settings")); action[ACT_GEN_PST]->setText(tr("Paste Radio Settings")); action[ACT_GEN_SIM]->setText(tr("Simulate Radio")); + cboModelSortOrder->setToolTip(tr("Radio Models Order")); action[ACT_ITM_EDT]->setText(tr("Edit Model")); action[ACT_ITM_DEL]->setText(tr("Delete")); @@ -437,17 +460,17 @@ QAction * MdiChild::getAction(const MdiChild::Actions type) if (type < ACT_ENUM_END) return action[type]; else - return NULL; + return nullptr; } void MdiChild::showModelsListContextMenu(const QPoint & pos) { - QModelIndex modelIndex = ui->modelsList->indexAt(pos); + QModelIndex viewIndex = ui->modelsList->indexAt(pos); QMenu contextMenu; updateNavigation(); - if (modelsListModel->isModelType(modelIndex)) { + if (modelsListModel->isModelType(getDataIndex(viewIndex))) { contextMenu.addActions(getEditActions()); if (countSelectedModels() == 1) { contextMenu.addSeparator(); @@ -507,6 +530,11 @@ void MdiChild::adjustToolbarLayout() void MdiChild::initModelsList() { + if (modelsListProxyModel) + delete modelsListProxyModel; + + modelsListProxyModel = new ModelsListProxyModel(); + if (modelsListModel) delete modelsListModel; @@ -516,12 +544,15 @@ void MdiChild::initModelsList() connect(modelsListModel, &ModelsListModel::refreshRequested, this, &MdiChild::refresh); connect(modelsListModel, &QAbstractItemModel::dataChanged, this, &MdiChild::onDataChanged); - ui->modelsList->setModel(modelsListModel); + modelsListProxyModel->setSourceModel(modelsListModel); + + ui->modelsList->setModel(modelsListProxyModel); ui->modelsList->selectionModel()->currentIndex().row(); // Labels Editor + Model - if(labelsListModel) + if (labelsListModel) delete labelsListModel; + labelsListModel = new LabelsModel(ui->modelsList->selectionModel(), &radioData, this); connect(labelsListModel, &LabelsModel::modelChanged, this, &MdiChild::modelLabelsChanged); @@ -531,9 +562,23 @@ void MdiChild::initModelsList() ui->lstLabels->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed); ui->lstLabels->setItemDelegate(new LabelEditTextDelegate); + modelsListProxyModel->setFilter(labelsListModel); // TODO Used for filters when developed + ui->modelsList->setIndentation(0); refresh(); + modelsListProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + + connect(ui->modelsList->header(), &QHeaderView::sectionDoubleClicked, [=] (int logicalIndex) { + if (ui->modelsList->header()->isSortIndicatorShown()) { + ui->modelsList->sortByColumn(-1, Qt::AscendingOrder); // turn off sort indicator shown and return proxy model to its unsorted order + ui->modelsList->setSortingEnabled(false); // disable clicking a column to sort + } + else { + ui->modelsList->setSortingEnabled(true); // enable sorting by clicking a column + ui->modelsList->sortByColumn(logicalIndex, Qt::AscendingOrder); + } + }); if (firmware->getCapability(Capability::HasModelLabels)) { ui->modelsList->header()->resizeSection(0, ui->modelsList->header()->sectionSize(0) * 1.5); // pad out model names @@ -546,11 +591,10 @@ void MdiChild::initModelsList() void MdiChild::refresh() { - bool expand = true; // TODO: restore user-preferred state clearCutList(); modelsListModel->refresh(); - if (expand) - ui->modelsList->expandAll(); + modelsListProxyModel->invalidate(); // force view refresh + ui->modelsList->expandAll(); if (lastSelectedModel > -1) { setSelectedModel(lastSelectedModel); lastSelectedModel = -1; @@ -561,8 +605,9 @@ void MdiChild::refresh() void MdiChild::onItemActivated(const QModelIndex index) { - if (modelsListModel->isModelType(index)) { - int mIdx = modelsListModel->getModelIndex(index); + QModelIndex srcIdx = getDataIndex(index); + if (modelsListModel->isModelType(srcIdx)) { + int mIdx = modelsListModel->getModelIndex(srcIdx); if (mIdx < 0 || mIdx >= (int)radioData.models.size()) return; if (radioData.models[mIdx].isEmpty()) @@ -593,7 +638,7 @@ void MdiChild::onDataChanged(const QModelIndex & index) QModelIndex MdiChild::getCurrentIndex() const { - return ui->modelsList->selectionModel()->currentIndex(); + return getDataIndex(ui->modelsList->selectionModel()->currentIndex()); } int MdiChild::getCurrentModel() const @@ -601,12 +646,24 @@ int MdiChild::getCurrentModel() const return modelsListModel->getModelIndex(getCurrentIndex()); } +QModelIndex MdiChild::getDataIndex(QModelIndex viewIndex) const +{ + return modelsListProxyModel->mapToSource(viewIndex); +} + +int MdiChild::getDataModel(QModelIndex viewIndex) const +{ + return modelsListModel->getModelIndex(getDataIndex(viewIndex)); +} + int MdiChild::countSelectedModels() const { int ret = 0; - foreach (QModelIndex index, ui->modelsList->selectionModel()->selectedRows()) { - if (index.isValid() && modelsListModel->isModelType(index) && !radioData.models.at(modelsListModel->getModelIndex(index)).isEmpty()) + foreach (QModelIndex viewIndex, ui->modelsList->selectionModel()->selectedRows()) { + QModelIndex index = getDataIndex(viewIndex); + if (index.isValid() && modelsListModel->isModelType(index) && + !radioData.models.at(modelsListModel->getModelIndex(index)).isEmpty()) ++ret; } return ret; @@ -621,8 +678,9 @@ bool MdiChild::setSelectedModel(const int modelIndex) { QModelIndex idx = modelsListModel->getIndexForModel(modelIndex); if (idx.isValid()) { - ui->modelsList->scrollTo(idx); - ui->modelsList->setCurrentIndex(idx); + QModelIndex viewIdx = modelsListProxyModel->mapFromSource(idx); + ui->modelsList->scrollTo(viewIdx); + ui->modelsList->setCurrentIndex(viewIdx); return true; } return false; @@ -631,7 +689,8 @@ bool MdiChild::setSelectedModel(const int modelIndex) QVector MdiChild::getSelectedModels() const { QVector models; - foreach (QModelIndex index, ui->modelsList->selectionModel()->selectedRows()) { + foreach (QModelIndex viewIndex, ui->modelsList->selectionModel()->selectedRows()) { + QModelIndex index = getDataIndex(viewIndex); if (index.isValid() && modelsListModel->isModelType(index)) models.append(modelsListModel->getModelIndex(index)); } @@ -957,7 +1016,7 @@ void MdiChild::pasteGeneralData(const QMimeData * mimeData) GeneralSettings gs; bool hasGenSettings = false; - if (!ModelsListModel::decodeMimeData(mimeData, NULL, &gs, &hasGenSettings)) + if (!ModelsListModel::decodeMimeData(mimeData, nullptr, &gs, &hasGenSettings)) return; if (hasGenSettings && askQuestion(tr("Do you want to overwrite radio general settings?")) == QMessageBox::Yes) { @@ -999,7 +1058,8 @@ void MdiChild::pasteGeneralSettings() void MdiChild::copy() { - QMimeData * mimeData = modelsListModel->getModelsMimeData(ui->modelsList->selectionModel()->selectedRows()); + QModelIndexList indexes = modelsListProxyModel->mapSelectionToSource(ui->modelsList->selectionModel()->selection()).indexes(); + QMimeData * mimeData = modelsListModel->getModelsMimeData(indexes); modelsListModel->getHeaderMimeData(mimeData); QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); clearCutList(); // clear the list by default, populate afterwards, eg. in cut(). @@ -1009,7 +1069,8 @@ void MdiChild::cut() { copy(); cutModels = getSelectedModels(); - modelsListModel->markItemsForCut(ui->modelsList->selectionModel()->selectedIndexes()); + QModelIndexList indexes = modelsListProxyModel->mapSelectionToSource(ui->modelsList->selectionModel()->selection()).indexes(); + modelsListModel->markItemsForCut(indexes); } void MdiChild::removeModelFromCutList(const int modelIndex) @@ -1151,7 +1212,7 @@ void MdiChild::openModelEditWindow(int row) void MdiChild::print(int model, const QString & filename) { // TODO - PrintDialog * pd = NULL; + PrintDialog * pd = nullptr; if (model>=0 && !filename.isEmpty()) { pd = new PrintDialog(this, firmware, radioData.generalSettings, radioData.models[model], filename); @@ -1171,6 +1232,7 @@ void MdiChild::setDefault() int row = getCurrentModel(); if (!radioData.models[row].isEmpty() && radioData.generalSettings.currModelIndex != (unsigned)row) { radioData.setCurrentModel(row); + refresh(); } } @@ -1370,7 +1432,7 @@ bool MdiChild::convertStorage(Board::Type from, Board::Type to, bool newFile) isUntitled = true; if (cstate.hasLogEntries(RadioDataConversionState::EVT_INF)) { - auto * msgBox = new QDialog(Q_NULLPTR, Qt::Dialog | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); + auto * msgBox = new QDialog(nullptr, Qt::Dialog | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); auto * tv = new ExportableTableView(msgBox); tv->setSortingEnabled(true); diff --git a/companion/src/mdichild.h b/companion/src/mdichild.h index 221824483..e700a0d3a 100644 --- a/companion/src/mdichild.h +++ b/companion/src/mdichild.h @@ -53,6 +53,7 @@ class MdiChild : public QWidget ACT_GEN_CPY, ACT_GEN_PST, ACT_GEN_SIM, + ACT_GEN_SRT, // model sort order ACT_ITM_EDT, ACT_ITM_DEL, ACT_LBL_ADD, @@ -76,7 +77,7 @@ class MdiChild : public QWidget ACT_ENUM_END }; - MdiChild(QWidget *parent = Q_NULLPTR, QWidget * parentWin = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); + MdiChild(QWidget *parent = nullptr, QWidget * parentWin = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); ~MdiChild(); QString currentFile() const; @@ -165,10 +166,12 @@ class MdiChild : public QWidget void pasteGeneralData(const QMimeData * mimeData); private: - QAction *addAct(Actions actId, const QString & icon, const char * slot = 0, const QKeySequence & shortcut = 0, QObject * slotObj = NULL); + QAction *addAct(Actions actId, const QString & icon, const char * slot = 0, const QKeySequence & shortcut = 0, QObject * slotObj = nullptr); QModelIndex getCurrentIndex() const; int getCurrentModel() const; + QModelIndex getDataIndex(QModelIndex viewIndex) const; + int getDataModel(QModelIndex viewIndex) const; int countSelectedModels() const; bool hasSelectedModel(); bool setSelectedModel(const int modelIndex); @@ -204,6 +207,7 @@ class MdiChild : public QWidget Ui::MdiChild * ui; ModelsListModel * modelsListModel; LabelsModel * labelsListModel; + ModelsListProxyModel * modelsListProxyModel; QWidget * parentWindow; QString curFile; @@ -222,6 +226,8 @@ class MdiChild : public QWidget bool showLabelToolbar; bool forceCloseFlag; const quint16 stateDataVersion; + AbstractStaticItemModel* modelSortOrderItemModel; + QComboBox* cboModelSortOrder; }; // This will draw the drop indicator across all columns of a model View (vs. in just one column), and lets us make the indicator more obvious. diff --git a/companion/src/modelslist.cpp b/companion/src/modelslist.cpp index f4efab9eb..2d9de5cad 100644 --- a/companion/src/modelslist.cpp +++ b/companion/src/modelslist.cpp @@ -22,7 +22,7 @@ ModelListItem::ModelListItem(const QVector & itemData): itemData(itemData), - parentItem(NULL), + parentItem(nullptr), modelIndex(-1), flags(0), highlightRX(false) @@ -609,7 +609,7 @@ void ModelsListModel::refresh() for (unsigned i = 0; i < radioData->models.size(); i++) { ModelData & model = radioData->models[i]; int currentColumn = 0; - ModelListItem * current = NULL; + ModelListItem * current = nullptr; model.modelIndex = i; @@ -679,3 +679,12 @@ bool ModelsListModel::isModelIdUnique(unsigned modelIdx, unsigned module, unsign return true; } +/* + ModelsListProxyModel +*/ + +bool ModelsListProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const +{ + return true; +} + diff --git a/companion/src/modelslist.h b/companion/src/modelslist.h index c85d8561a..dfce4319a 100644 --- a/companion/src/modelslist.h +++ b/companion/src/modelslist.h @@ -21,7 +21,10 @@ #pragma once #include "eeprominterface.h" +#include "labels.h" + #include +#include #include #include @@ -82,32 +85,32 @@ class ModelsListModel : public QAbstractItemModel ModelsListModel(RadioData * radioData, QObject *parent = 0); virtual ~ModelsListModel(); - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; - virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; - virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) Q_DECL_OVERRIDE; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; - virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; - virtual QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE; - virtual Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE; + virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; + virtual QModelIndex parent(const QModelIndex &index) const override; + virtual Qt::ItemFlags flags(const QModelIndex &index) const override; - virtual int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; - virtual int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; - virtual bool removeRows(int position, int rows, const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE; - //virtual bool insertRows(int row, int count, const QModelIndex & parent) Q_DECL_OVERRIDE; + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override; + virtual bool removeRows(int position, int rows, const QModelIndex &parent = QModelIndex()) override; + //virtual bool insertRows(int row, int count, const QModelIndex & parent) override; - virtual QStringList mimeTypes() const Q_DECL_OVERRIDE; - virtual Qt::DropActions supportedDropActions() const Q_DECL_OVERRIDE; - virtual Qt::DropActions supportedDragActions() const Q_DECL_OVERRIDE; - virtual QMimeData * mimeData(const QModelIndexList & indexes) const Q_DECL_OVERRIDE; - virtual bool canDropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) const Q_DECL_OVERRIDE; - virtual bool dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) Q_DECL_OVERRIDE; + virtual QStringList mimeTypes() const override; + virtual Qt::DropActions supportedDropActions() const override; + virtual Qt::DropActions supportedDragActions() const override; + virtual QMimeData * mimeData(const QModelIndexList & indexes) const override; + virtual bool canDropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) const override; + virtual bool dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) override; void encodeModelsData(const QModelIndexList & indexes, QByteArray * data) const; void encodeGeneralData(QByteArray * data) const; void encodeHeaderData(QByteArray * data) const; - QMimeData * getModelsMimeData(const QModelIndexList & indexes, QMimeData * mimeData = NULL) const; - QMimeData * getGeneralMimeData(QMimeData * mimeData = NULL) const; - QMimeData * getHeaderMimeData(QMimeData * mimeData = NULL) const; + QMimeData * getModelsMimeData(const QModelIndexList & indexes, QMimeData * mimeData = nullptr) const; + QMimeData * getGeneralMimeData(QMimeData * mimeData = nullptr) const; + QMimeData * getHeaderMimeData(QMimeData * mimeData = nullptr) const; QUuid getMimeDataSourceId(const QMimeData * mimeData) const; bool hasSupportedMimeData(const QMimeData * mimeData) const; bool hasModelsMimeData(const QMimeData * mimeData) const; @@ -116,7 +119,7 @@ class ModelsListModel : public QAbstractItemModel bool hasOwnMimeData(const QMimeData * mimeData) const; static bool decodeHeaderData(const QMimeData * mimeData, MimeHeaderData * header); - static bool decodeMimeData(const QMimeData * mimeData, QVector * models = NULL, GeneralSettings * gs = NULL, bool * hasGenSet = NULL); + static bool decodeMimeData(const QMimeData * mimeData, QVector * models = nullptr, GeneralSettings * gs = nullptr, bool * hasGenSet = nullptr); static int countModelsInMimeData(const QMimeData * mimeData); QModelIndex getIndexForModel(const int modelIndex, QModelIndex parent = QModelIndex()); @@ -147,3 +150,21 @@ class ModelsListModel : public QAbstractItemModel MimeHeaderData mimeHeaderData; bool hasLabels; }; + +class ModelsListProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT + + public: + ModelsListProxyModel() {} + virtual ~ModelsListProxyModel() {} + + public slots: + void setFilter(LabelsModel* labels) { m_labels = labels; } + + protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const override; + + private: + LabelsModel* m_labels; +};