diff --git a/include/QtNodes/internal/DataFlowGraphicsScene.hpp b/include/QtNodes/internal/DataFlowGraphicsScene.hpp index 25698ebe..33382e0b 100644 --- a/include/QtNodes/internal/DataFlowGraphicsScene.hpp +++ b/include/QtNodes/internal/DataFlowGraphicsScene.hpp @@ -25,6 +25,8 @@ class NODE_EDITOR_PUBLIC DataFlowGraphicsScene : public BasicGraphicsScene public: QMenu *createSceneMenu(QPointF const scenePos) override; + void sortSceneMenu(bool sortMenu = true); + public Q_SLOTS: void save() const; @@ -35,6 +37,8 @@ public Q_SLOTS: private: DataFlowGraphModel &_graphModel; + + bool _sortMenu; }; } // namespace QtNodes diff --git a/include/QtNodes/internal/NodeDelegateModelRegistry.hpp b/include/QtNodes/internal/NodeDelegateModelRegistry.hpp index 4f230a4f..3b871fab 100644 --- a/include/QtNodes/internal/NodeDelegateModelRegistry.hpp +++ b/include/QtNodes/internal/NodeDelegateModelRegistry.hpp @@ -9,7 +9,6 @@ #include #include -#include #include #include #include @@ -24,8 +23,7 @@ class NODE_EDITOR_PUBLIC NodeDelegateModelRegistry using RegistryItemPtr = std::unique_ptr; using RegistryItemCreator = std::function; using RegisteredModelCreatorsMap = std::unordered_map; - using RegisteredModelsCategoryMap = std::unordered_map; - using CategoriesSet = std::set; + using RegisteredModelsCategoryMap = std::vector>; //using RegisteredTypeConvertersMap = std::map; @@ -46,8 +44,7 @@ class NODE_EDITOR_PUBLIC NodeDelegateModelRegistry QString const name = computeName(HasStaticMethodName{}, creator); if (!_registeredItemCreators.count(name)) { _registeredItemCreators[name] = std::move(creator); - _categories.insert(category); - _registeredModelsCategory[name] = category; + _registeredModelsCategory.push_back(std::make_pair(name, category)); } } @@ -100,8 +97,6 @@ class NODE_EDITOR_PUBLIC NodeDelegateModelRegistry RegisteredModelsCategoryMap const ®isteredModelsCategoryAssociation() const; - CategoriesSet const &categories() const; - #if 0 TypeConverter getTypeConverter(NodeDataType const& d1, @@ -111,8 +106,6 @@ class NODE_EDITOR_PUBLIC NodeDelegateModelRegistry private: RegisteredModelsCategoryMap _registeredModelsCategory; - CategoriesSet _categories; - RegisteredModelCreatorsMap _registeredItemCreators; #if 0 diff --git a/src/DataFlowGraphicsScene.cpp b/src/DataFlowGraphicsScene.cpp index 506f722f..1ba3c958 100644 --- a/src/DataFlowGraphicsScene.cpp +++ b/src/DataFlowGraphicsScene.cpp @@ -6,10 +6,14 @@ #include "NodeGraphicsObject.hpp" #include "UndoCommands.hpp" +#include +#include +#include #include #include #include #include +#include #include #include @@ -31,6 +35,7 @@ namespace QtNodes { DataFlowGraphicsScene::DataFlowGraphicsScene(DataFlowGraphModel &graphModel, QObject *parent) : BasicGraphicsScene(graphModel, parent) , _graphModel(graphModel) + , _sortMenu(true) { connect(&_graphModel, &DataFlowGraphModel::inPortDataWasSet, @@ -61,77 +66,104 @@ QMenu *DataFlowGraphicsScene::createSceneMenu(QPointF const scenePos) { QMenu *modelMenu = new QMenu(); + QWidget *menuWidget = new QWidget(); + QGridLayout *layout = new QGridLayout(menuWidget); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(3); + // Add filterbox to the context menu - auto *txtBox = new QLineEdit(modelMenu); + QLineEdit *txtBox = new QLineEdit(); txtBox->setPlaceholderText(QStringLiteral("Filter")); txtBox->setClearButtonEnabled(true); + txtBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + layout->addWidget(txtBox, 0, 0); - auto *txtBoxAction = new QWidgetAction(modelMenu); - txtBoxAction->setDefaultWidget(txtBox); - - // 1. - modelMenu->addAction(txtBoxAction); + // Add sort button + QPushButton *sortButton = new QPushButton("Sort"); + sortButton->setCheckable(true); + layout->addWidget(sortButton, 0, 1); // Add result treeview to the context menu - QTreeWidget *treeView = new QTreeWidget(modelMenu); + QTreeView *treeView = new QTreeView(); treeView->header()->close(); + layout->addWidget(treeView, 1, 0, 1, 2); + QStandardItemModel *treeModel = new QStandardItemModel(treeView); - auto *treeViewAction = new QWidgetAction(modelMenu); - treeViewAction->setDefaultWidget(treeView); + auto *menuWidgetAction = new QWidgetAction(menuWidget); + menuWidgetAction->setDefaultWidget(menuWidget); - // 2. - modelMenu->addAction(treeViewAction); + modelMenu->addAction(menuWidgetAction); auto registry = _graphModel.dataModelRegistry(); - for (auto const &cat : registry->categories()) { - auto item = new QTreeWidgetItem(treeView); - item->setText(0, cat); - item->setFlags(item->flags() & ~Qt::ItemIsSelectable); - } - + int sortCount = 0; for (auto const &assoc : registry->registeredModelsCategoryAssociation()) { - QList parent = treeView->findItems(assoc.second, Qt::MatchExactly); + QList parentList; + parentList.clear(); + parentList = treeModel->findItems(assoc.second, Qt::MatchExactly); + + if (parentList.count() <= 0) { + // Create a parent if it does not exist + auto parentItem = new QStandardItem(assoc.second); + parentItem->setData(sortCount, Qt::UserRole); + parentItem->setFlags(parentItem->flags() & ~Qt::ItemIsSelectable); + parentList.push_back(parentItem); + treeModel->appendRow(parentItem); + } - if (parent.count() <= 0) - continue; + auto childItem = new QStandardItem(assoc.first); + childItem->setData(sortCount, Qt::UserRole); + parentList.first()->appendRow(childItem); - auto item = new QTreeWidgetItem(parent.first()); - item->setText(0, assoc.first); + sortCount++; } + treeView->setModel(treeModel); treeView->expandAll(); + if (_sortMenu) { + sortButton->setChecked(_sortMenu); + treeView->sortByColumn(0, Qt::AscendingOrder); + } + + connect(sortButton, &QPushButton::clicked, this, [this, treeModel, treeView](bool checked) { + if (checked) + treeModel->setSortRole(Qt::DisplayRole); + else + treeModel->setSortRole(Qt::UserRole); + + _sortMenu = checked; + treeView->sortByColumn(0, Qt::AscendingOrder); + }); + connect(treeView, - &QTreeWidget::itemClicked, - [this, modelMenu, scenePos](QTreeWidgetItem *item, int) { - if (!(item->flags() & (Qt::ItemIsSelectable))) { + &QTreeView::clicked, + [this, modelMenu, treeModel, scenePos](const QModelIndex &index) { + auto item = treeModel->itemFromIndex(index); + + if (item->hasChildren()) return; - } - this->undoStack().push(new CreateCommand(this, item->text(0), scenePos)); + this->undoStack().push(new CreateCommand(this, item->text(), scenePos)); modelMenu->close(); }); //Setup filtering - connect(txtBox, &QLineEdit::textChanged, [treeView](const QString &text) { - QTreeWidgetItemIterator categoryIt(treeView, QTreeWidgetItemIterator::HasChildren); - while (*categoryIt) - (*categoryIt++)->setHidden(true); - QTreeWidgetItemIterator it(treeView, QTreeWidgetItemIterator::NoChildren); - while (*it) { - auto modelName = (*it)->text(0); - const bool match = (modelName.contains(text, Qt::CaseInsensitive)); - (*it)->setHidden(!match); - if (match) { - QTreeWidgetItem *parent = (*it)->parent(); - while (parent) { - parent->setHidden(false); - parent = parent->parent(); + connect(txtBox, &QLineEdit::textChanged, [treeView, treeModel](const QString &text) { + QModelIndex treeViewIndex = treeView->rootIndex(); + + for (int i = 0; i < treeModel->rowCount(); ++i) { + QStandardItem *parent = treeModel->item(i); + treeView->setRowHidden(i, treeViewIndex, true); + + for (int j = 0; j < parent->rowCount(); ++j) { + const bool match = parent->child(j)->text().contains(text, Qt::CaseInsensitive); + treeView->setRowHidden(j, parent->index(), !match); + if (match) { + treeView->setRowHidden(i, treeViewIndex, false); } } - ++it; } }); @@ -144,6 +176,11 @@ QMenu *DataFlowGraphicsScene::createSceneMenu(QPointF const scenePos) return modelMenu; } +void DataFlowGraphicsScene::sortSceneMenu(bool sortMenu) +{ + _sortMenu = sortMenu; +} + void DataFlowGraphicsScene::save() const { QString fileName = QFileDialog::getSaveFileName(nullptr, diff --git a/src/NodeDelegateModelRegistry.cpp b/src/NodeDelegateModelRegistry.cpp index 11a1f84a..6d08bedf 100644 --- a/src/NodeDelegateModelRegistry.cpp +++ b/src/NodeDelegateModelRegistry.cpp @@ -29,8 +29,3 @@ NodeDelegateModelRegistry::registeredModelsCategoryAssociation() const { return _registeredModelsCategory; } - -NodeDelegateModelRegistry::CategoriesSet const &NodeDelegateModelRegistry::categories() const -{ - return _categories; -}