From e162fbe7e18434e166110c6a321cba4c77107549 Mon Sep 17 00:00:00 2001 From: cristian64 Date: Fri, 24 May 2024 23:17:36 +0100 Subject: [PATCH] Add **Group** context menu action to group currently selected entries. A new group node is added in the place of the first selected entry, and all the selected entries are moved from their current parents (which can be different parents) into the newly created group node. --- Source/GUI/MemWatcher/MemWatchModel.cpp | 58 ++++++++++++++++++++++++ Source/GUI/MemWatcher/MemWatchModel.h | 2 + Source/GUI/MemWatcher/MemWatchWidget.cpp | 14 ++++++ Source/GUI/MemWatcher/MemWatchWidget.h | 1 + Source/MemoryWatch/MemWatchTreeNode.cpp | 10 ++++ Source/MemoryWatch/MemWatchTreeNode.h | 1 + 6 files changed, 86 insertions(+) diff --git a/Source/GUI/MemWatcher/MemWatchModel.cpp b/Source/GUI/MemWatcher/MemWatchModel.cpp index ae54bf7..c669e4a 100644 --- a/Source/GUI/MemWatcher/MemWatchModel.cpp +++ b/Source/GUI/MemWatcher/MemWatchModel.cpp @@ -207,6 +207,52 @@ void MemWatchModel::deleteNode(const QModelIndex& index) } } +void MemWatchModel::groupSelection(const QModelIndexList& indexes) +{ + if (indexes.isEmpty()) + return; + + // Collect nodes from indexes; indexes will be invalidated shortly as nodes are removed from their + // parents. + std::vector nodes; + for (const QModelIndex& index : indexes) + { + nodes.push_back(static_cast(index.internalPointer())); + } + + MemWatchTreeNode* newParent{}; + int newRow{std::numeric_limits::max()}; + + // Extract nodes from their current parent. + for (MemWatchTreeNode* const node : nodes) + { + MemWatchTreeNode* const parent{node->getParent()}; + const int row{static_cast(parent->getChildren().indexOf(node))}; + + if (!newParent || newParent == parent) + { + newParent = parent; + newRow = std::min(newRow, row); + } + + beginRemoveRows(getIndexFromTreeNode(parent), row, row); + parent->removeChild(node); + endRemoveRows(); + } + + beginInsertRows(getIndexFromTreeNode(newParent), newRow, newRow); + + // Create new group with all the extracted nodes, and insert in the new parent. + MemWatchTreeNode* const group{new MemWatchTreeNode(nullptr, nullptr, true, "New Group")}; + for (MemWatchTreeNode* const node : nodes) + { + group->appendChild(node); + } + newParent->insertChild(newRow, group); + + endInsertRows(); +} + int MemWatchModel::columnCount(const QModelIndex& parent) const { (void)parent; @@ -630,3 +676,15 @@ MemWatchTreeNode* MemWatchModel::getTreeNodeFromIndex(const QModelIndex& index) { return static_cast(index.internalPointer()); } + +QModelIndex MemWatchModel::getIndexFromTreeNode(const MemWatchTreeNode* const node) +{ + if (node == m_rootNode) + { + return createIndex(0, 0, m_rootNode); + } + + const MemWatchTreeNode* const parent{node->getParent()}; + return index(static_cast(parent->getChildren().indexOf(node)), 0, + getIndexFromTreeNode(parent)); +} diff --git a/Source/GUI/MemWatcher/MemWatchModel.h b/Source/GUI/MemWatcher/MemWatchModel.h index e4e2bbc..e0389b8 100644 --- a/Source/GUI/MemWatcher/MemWatchModel.h +++ b/Source/GUI/MemWatcher/MemWatchModel.h @@ -62,6 +62,7 @@ class MemWatchModel : public QAbstractItemModel void editEntry(MemWatchEntry* entry, const QModelIndex& index); void clearRoot(); void deleteNode(const QModelIndex& index); + void groupSelection(const QModelIndexList& indexes); void onUpdateTimer(); void onFreezeTimer(); void loadRootFromJsonRecursive(const QJsonObject& json); @@ -71,6 +72,7 @@ class MemWatchModel : public QAbstractItemModel bool hasAnyNodes() const; MemWatchTreeNode* getRootNode() const; static MemWatchTreeNode* getTreeNodeFromIndex(const QModelIndex& index); + QModelIndex getIndexFromTreeNode(const MemWatchTreeNode* node); bool editData(const QModelIndex& index, const QVariant& value, int role, bool emitEdit = false); signals: diff --git a/Source/GUI/MemWatcher/MemWatchWidget.cpp b/Source/GUI/MemWatcher/MemWatchWidget.cpp index 93cbf33..54b2da9 100644 --- a/Source/GUI/MemWatcher/MemWatchWidget.cpp +++ b/Source/GUI/MemWatcher/MemWatchWidget.cpp @@ -247,6 +247,15 @@ void MemWatchWidget::onMemWatchContextMenuRequested(const QPoint& pos) node = m_watchModel->getRootNode(); } + const QModelIndexList simplifiedSelection{simplifySelection()}; + if (!simplifiedSelection.empty()) + { + QAction* const groupAction{new QAction(tr("&Group"), this)}; + connect(groupAction, &QAction::triggered, this, &MemWatchWidget::groupCurrentSelection); + contextMenu->addAction(groupAction); + contextMenu->addSeparator(); + } + QAction* cut = new QAction(tr("Cu&t"), this); connect(cut, &QAction::triggered, this, [this] { cutSelectedWatchesToClipBoard(); }); contextMenu->addAction(cut); @@ -293,6 +302,11 @@ void MemWatchWidget::setSelectedWatchesBase(MemWatchEntry* entry, Common::MemBas m_hasUnsavedChanges = true; } +void MemWatchWidget::groupCurrentSelection() +{ + m_watchModel->groupSelection(simplifySelection()); +} + void MemWatchWidget::cutSelectedWatchesToClipBoard() { copySelectedWatchesToClipBoard(); diff --git a/Source/GUI/MemWatcher/MemWatchWidget.h b/Source/GUI/MemWatcher/MemWatchWidget.h index 45e36c8..cb8098d 100644 --- a/Source/GUI/MemWatcher/MemWatchWidget.h +++ b/Source/GUI/MemWatcher/MemWatchWidget.h @@ -33,6 +33,7 @@ class MemWatchWidget : public QWidget void onRowsInserted(const QModelIndex& parent, int first, int last); void openWatchFile(); void setSelectedWatchesBase(MemWatchEntry* entry, Common::MemBase base); + void groupCurrentSelection(); void copySelectedWatchesToClipBoard(); void cutSelectedWatchesToClipBoard(); void pasteWatchFromClipBoard(const QModelIndex& referenceIndex); diff --git a/Source/MemoryWatch/MemWatchTreeNode.cpp b/Source/MemoryWatch/MemWatchTreeNode.cpp index c98b6b9..89a2a71 100644 --- a/Source/MemoryWatch/MemWatchTreeNode.cpp +++ b/Source/MemoryWatch/MemWatchTreeNode.cpp @@ -109,9 +109,19 @@ void MemWatchTreeNode::insertChild(const int row, MemWatchTreeNode* node) void MemWatchTreeNode::removeChild(const int row) { + m_children[row]->m_parent = nullptr; m_children.remove(row); } +void MemWatchTreeNode::removeChild(MemWatchTreeNode* const child) +{ + m_children.removeAll(child); + if (child->m_parent == this) + { + child->m_parent = nullptr; + } +} + void MemWatchTreeNode::removeChildren() { m_children.clear(); diff --git a/Source/MemoryWatch/MemWatchTreeNode.h b/Source/MemoryWatch/MemWatchTreeNode.h index b52e99c..1dc6a1f 100644 --- a/Source/MemoryWatch/MemWatchTreeNode.h +++ b/Source/MemoryWatch/MemWatchTreeNode.h @@ -36,6 +36,7 @@ class MemWatchTreeNode void appendChild(MemWatchTreeNode* node); void insertChild(int row, MemWatchTreeNode* node); void removeChild(int row); + void removeChild(MemWatchTreeNode* child); void removeChildren(); void deleteChildren();