From 2c9056255a9560b20fd08a7f9848fcf69c0b1078 Mon Sep 17 00:00:00 2001 From: Alex Tran Date: Sat, 29 Mar 2025 17:57:16 -0700 Subject: [PATCH 1/4] Expand/Collapse Property Editor --- src/Gui/propertyeditor/PropertyEditor.cpp | 57 +++++++++++++++++++++++ src/Gui/propertyeditor/PropertyEditor.h | 3 ++ 2 files changed, 60 insertions(+) diff --git a/src/Gui/propertyeditor/PropertyEditor.cpp b/src/Gui/propertyeditor/PropertyEditor.cpp index 26531779af..a37bb62929 100644 --- a/src/Gui/propertyeditor/PropertyEditor.cpp +++ b/src/Gui/propertyeditor/PropertyEditor.cpp @@ -52,6 +52,7 @@ using namespace Gui::PropertyEditor; PropertyEditor::PropertyEditor(QWidget* parent) : QTreeView(parent) + , autocollapse(false) , autoexpand(false) , autoupdate(false) , committing(false) @@ -118,6 +119,14 @@ PropertyEditor::~PropertyEditor() delete f; } +void PropertyEditor::setAutomaticCollapse(bool v) { + autocollapse = v; +} + +bool PropertyEditor::isAutomaticCollapse(bool) const { + return autocollapse; +} + void PropertyEditor::setAutomaticExpand(bool v) { autoexpand = v; @@ -715,6 +724,10 @@ void PropertyEditor::buildUp(PropertyModel::PropertyList&& props, bool _checkDoc if (autoexpand) { expandAll(); } + + if (autocollapse) { + collapseAll(); + } } void PropertyEditor::updateProperty(const App::Property& prop) @@ -769,7 +782,10 @@ void PropertyEditor::renameProperty(const App::Property& prop) enum MenuAction { + MA_AutoCollapse, MA_AutoExpand, + MA_CollapseAll, + MA_ExpandAll, MA_ShowHidden, MA_Expression, MA_RemoveProp, @@ -841,6 +857,7 @@ void PropertyEditor::contextMenuEvent(QContextMenuEvent*) { QMenu menu; QAction* autoExpand = nullptr; + QAction* autoCollapse = nullptr; auto contextIndex = currentIndex(); @@ -904,12 +921,26 @@ void PropertyEditor::contextMenuEvent(QContextMenuEvent*) showHidden->setChecked(PropertyView::showAll()); showHidden->setData(QVariant(MA_ShowHidden)); + // auto collapse + autoCollapse = menu.addAction(tr("Auto collapse")); + autoCollapse->setCheckable(true); + autoCollapse->setChecked(autocollapse); + autoCollapse->setData(QVariant(MA_AutoCollapse)); + // auto expand autoExpand = menu.addAction(tr("Auto-Expand")); autoExpand->setCheckable(true); autoExpand->setChecked(autoexpand); autoExpand->setData(QVariant(MA_AutoExpand)); + QAction* collapseall = menu.addAction(tr("Collapse all")); + collapseall->setData(QVariant(MA_CollapseAll)); + + QAction* expandall = menu.addAction(tr("Expand all")); + expandall->setData(QVariant(MA_ExpandAll)); + + menu.addSeparator(); + // expression if (props.size() == 1) { auto item = static_cast(contextIndex.internalPointer()); @@ -969,17 +1000,43 @@ void PropertyEditor::contextMenuEvent(QContextMenuEvent*) } switch (action->data().toInt()) { + case MA_AutoCollapse: + if (autoCollapse) { + autocollapse = autoCollapse->isChecked(); + + // uncheck auto expand + if (autoExpand->isChecked()) { + autoexpand = false; + } + + if (autocollapse) { + collapseAll(); + } + } + return; case MA_AutoExpand: if (autoExpand) { // Variable autoExpand should not be null when we arrive here, but // since we explicitly initialize the variable to nullptr, a check // nonetheless. autoexpand = autoExpand->isChecked(); + + // uncheck auto collapse + if (autoCollapse->isChecked()) { + autocollapse = false; + } + if (autoexpand) { expandAll(); } } return; + case MA_CollapseAll: + collapseAll(); + return; + case MA_ExpandAll: + expandAll(); + return; case MA_ShowHidden: PropertyView::setShowAll(action->isChecked()); return; diff --git a/src/Gui/propertyeditor/PropertyEditor.h b/src/Gui/propertyeditor/PropertyEditor.h index f41cbbb5f3..01c73f66ac 100644 --- a/src/Gui/propertyeditor/PropertyEditor.h +++ b/src/Gui/propertyeditor/PropertyEditor.h @@ -79,6 +79,8 @@ public: void updateProperty(const App::Property&); void removeProperty(const App::Property&); void renameProperty(const App::Property&); + void setAutomaticCollapse(bool); + bool isAutomaticCollapse(bool) const; void setAutomaticExpand(bool); bool isAutomaticExpand(bool) const; void setAutomaticDocumentUpdate(bool); @@ -148,6 +150,7 @@ private: QStringList selectedProperty; PropertyModel::PropertyList propList; std::unordered_set propOwners; + bool autocollapse; bool autoexpand; bool autoupdate; bool committing; From 76e43efdc67cffeb88831102e5f02d2e8b19e769 Mon Sep 17 00:00:00 2001 From: Alex Tran Date: Sat, 29 Mar 2025 18:54:13 -0700 Subject: [PATCH 2/4] Read auto collapse user preferences --- src/Gui/PropertyView.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Gui/PropertyView.cpp b/src/Gui/PropertyView.cpp index d0ef38aaab..603e66c658 100644 --- a/src/Gui/PropertyView.cpp +++ b/src/Gui/PropertyView.cpp @@ -86,12 +86,14 @@ PropertyView::PropertyView(QWidget *parent) propertyEditorView->setObjectName(QStringLiteral("propertyEditorView")); propertyEditorView->setAutomaticDocumentUpdate(_GetParam()->GetBool("AutoTransactionView", false)); propertyEditorView->setAutomaticExpand(_GetParam()->GetBool("AutoExpandView", false)); + propertyEditorView->setAutomaticCollapse(_GetParam()->GetBool("AutoCollapseView", false)); tabs->addTab(propertyEditorView, tr("View")); propertyEditorData = new Gui::PropertyEditor::PropertyEditor(); propertyEditorData->setObjectName(QStringLiteral("propertyEditorData")); propertyEditorData->setAutomaticDocumentUpdate(_GetParam()->GetBool("AutoTransactionData", true)); propertyEditorData->setAutomaticExpand(_GetParam()->GetBool("AutoExpandData", false)); + propertyEditorView->setAutomaticCollapse(_GetParam()->GetBool("AutoCollapseData", false)); tabs->addTab(propertyEditorData, tr("Data")); int preferredTab = _GetParam()->GetInt("LastTabIndex", 1); From 8e1f983e37c033b6dfd9c179f27cbb5927f9a53e Mon Sep 17 00:00:00 2001 From: Pieter Hijma Date: Mon, 1 Sep 2025 14:18:21 +0200 Subject: [PATCH 3/4] Gui: Create a Property View submenu for expansion The Property View's context menu has a submenu for property expansion that allows you set the property expansion to default (remembers state), to expand all and to collapse all. Then there are toggles for default/auto expand/auto collapse that always collapses or expands or remembers the state. --- src/Gui/PropertyView.cpp | 4 - src/Gui/propertyeditor/PropertyEditor.cpp | 194 +++++++++++++--------- src/Gui/propertyeditor/PropertyEditor.h | 17 +- 3 files changed, 130 insertions(+), 85 deletions(-) diff --git a/src/Gui/PropertyView.cpp b/src/Gui/PropertyView.cpp index 603e66c658..1aa08e7fae 100644 --- a/src/Gui/PropertyView.cpp +++ b/src/Gui/PropertyView.cpp @@ -85,15 +85,11 @@ PropertyView::PropertyView(QWidget *parent) propertyEditorView = new Gui::PropertyEditor::PropertyEditor(); propertyEditorView->setObjectName(QStringLiteral("propertyEditorView")); propertyEditorView->setAutomaticDocumentUpdate(_GetParam()->GetBool("AutoTransactionView", false)); - propertyEditorView->setAutomaticExpand(_GetParam()->GetBool("AutoExpandView", false)); - propertyEditorView->setAutomaticCollapse(_GetParam()->GetBool("AutoCollapseView", false)); tabs->addTab(propertyEditorView, tr("View")); propertyEditorData = new Gui::PropertyEditor::PropertyEditor(); propertyEditorData->setObjectName(QStringLiteral("propertyEditorData")); propertyEditorData->setAutomaticDocumentUpdate(_GetParam()->GetBool("AutoTransactionData", true)); - propertyEditorData->setAutomaticExpand(_GetParam()->GetBool("AutoExpandData", false)); - propertyEditorView->setAutomaticCollapse(_GetParam()->GetBool("AutoCollapseData", false)); tabs->addTab(propertyEditorData, tr("Data")); int preferredTab = _GetParam()->GetInt("LastTabIndex", 1); diff --git a/src/Gui/propertyeditor/PropertyEditor.cpp b/src/Gui/propertyeditor/PropertyEditor.cpp index a37bb62929..d601842b92 100644 --- a/src/Gui/propertyeditor/PropertyEditor.cpp +++ b/src/Gui/propertyeditor/PropertyEditor.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -52,8 +53,7 @@ using namespace Gui::PropertyEditor; PropertyEditor::PropertyEditor(QWidget* parent) : QTreeView(parent) - , autocollapse(false) - , autoexpand(false) + , expansionMode(ExpansionMode::DefaultExpand) , autoupdate(false) , committing(false) , delaybuild(false) @@ -119,24 +119,6 @@ PropertyEditor::~PropertyEditor() delete f; } -void PropertyEditor::setAutomaticCollapse(bool v) { - autocollapse = v; -} - -bool PropertyEditor::isAutomaticCollapse(bool) const { - return autocollapse; -} - -void PropertyEditor::setAutomaticExpand(bool v) -{ - autoexpand = v; -} - -bool PropertyEditor::isAutomaticExpand(bool) const -{ - return autoexpand; -} - void PropertyEditor::onItemExpanded(const QModelIndex& index) { auto item = static_cast(index.internalPointer()); @@ -721,12 +703,16 @@ void PropertyEditor::buildUp(PropertyModel::PropertyList&& props, bool _checkDoc } } - if (autoexpand) { + switch (expansionMode) { + case ExpansionMode::DefaultExpand: + // take the current expansion state + break; + case ExpansionMode::AutoExpand: expandAll(); - } - - if (autocollapse) { + break; + case ExpansionMode::AutoCollapse: collapseAll(); + break; } } @@ -784,6 +770,8 @@ enum MenuAction { MA_AutoCollapse, MA_AutoExpand, + MA_ExpandToDefault, + MA_DefaultExpand, MA_CollapseAll, MA_ExpandAll, MA_ShowHidden, @@ -804,6 +792,94 @@ enum MenuAction MA_Copy, }; +void PropertyEditor::setFirstLevelExpanded(bool doExpand) +{ + if (!propertyModel) { + return; + } + + std::function setExpanded = [&]( + const QModelIndex& index, bool doExpand) { + if (!index.isValid()) { + return; + } + + auto* item = static_cast(index.internalPointer()); + if (item == nullptr || item->childCount() <= 0) { + return; + } + + if (doExpand) { + expand(index); + } + else { + collapse(index); + } + + for (int row = 0; row < propertyModel->rowCount(index); ++row) { + setExpanded(propertyModel->index(row, 0, index), false); + } + }; + + const QModelIndex root = QModelIndex(); + for (int row = 0; row rowCount(root); ++row) { + setExpanded(propertyModel->index(row, 0, root), doExpand); + } +} + +void PropertyEditor::expandToDefault() +{ + setFirstLevelExpanded(true); +} + +void PropertyEditor::collapseAll() +{ + setFirstLevelExpanded(false); +} + +QMenu* PropertyEditor::setupExpansionSubmenu(QWidget* parent) +{ + auto* expandMenu = new QMenu(tr("Expand/Collapse Properties"), parent); + + QAction* expandToDefault = expandMenu->addAction(tr("Expand to Default")); + expandToDefault->setData(QVariant(MA_ExpandToDefault)); + QAction* expandAll = expandMenu->addAction(tr("Expand All")); + expandAll->setData(QVariant(MA_ExpandAll)); + QAction* collapseAll = expandMenu->addAction(tr("Collapse All")); + collapseAll->setData(QVariant(MA_CollapseAll)); + + auto* group = new QActionGroup(expandMenu); + group->setExclusive(true); + + QAction* defaultExpand = expandMenu->addAction(tr("Default Expand")); + defaultExpand->setData(QVariant(MA_DefaultExpand)); + + QAction* autoExpand = expandMenu->addAction(tr("Auto Expand")); + autoExpand->setData(QVariant(MA_AutoExpand)); + + QAction* autoCollapse = expandMenu->addAction(tr("Auto Collapse")); + autoCollapse->setData(QVariant(MA_AutoCollapse)); + + for (QAction* action : {defaultExpand, autoExpand, autoCollapse}) { + action->setCheckable(true); + group->addAction(action); + } + + switch (expansionMode) { + case ExpansionMode::DefaultExpand: + defaultExpand->setChecked(true); + break; + case ExpansionMode::AutoExpand: + autoExpand->setChecked(true); + break; + case ExpansionMode::AutoCollapse: + autoCollapse->setChecked(true); + break; + } + + return expandMenu; +} + static App::PropertyContainer* getSelectedPropertyContainer() { auto sels = Gui::Selection().getSelection("*"); @@ -856,9 +932,6 @@ void PropertyEditor::removeProperties(const std::unordered_set& void PropertyEditor::contextMenuEvent(QContextMenuEvent*) { QMenu menu; - QAction* autoExpand = nullptr; - QAction* autoCollapse = nullptr; - auto contextIndex = currentIndex(); std::unordered_set props = acquireSelectedProperties(); @@ -915,30 +988,15 @@ void PropertyEditor::contextMenuEvent(QContextMenuEvent*) // add a separator between adding/removing properties and the rest menu.addSeparator(); + QMenu* expandMenu = setupExpansionSubmenu(&menu); + menu.addMenu(expandMenu); + // show all QAction* showHidden = menu.addAction(tr("Show Hidden")); showHidden->setCheckable(true); showHidden->setChecked(PropertyView::showAll()); showHidden->setData(QVariant(MA_ShowHidden)); - // auto collapse - autoCollapse = menu.addAction(tr("Auto collapse")); - autoCollapse->setCheckable(true); - autoCollapse->setChecked(autocollapse); - autoCollapse->setData(QVariant(MA_AutoCollapse)); - - // auto expand - autoExpand = menu.addAction(tr("Auto-Expand")); - autoExpand->setCheckable(true); - autoExpand->setChecked(autoexpand); - autoExpand->setData(QVariant(MA_AutoExpand)); - - QAction* collapseall = menu.addAction(tr("Collapse all")); - collapseall->setData(QVariant(MA_CollapseAll)); - - QAction* expandall = menu.addAction(tr("Expand all")); - expandall->setData(QVariant(MA_ExpandAll)); - menu.addSeparator(); // expression @@ -1000,36 +1058,8 @@ void PropertyEditor::contextMenuEvent(QContextMenuEvent*) } switch (action->data().toInt()) { - case MA_AutoCollapse: - if (autoCollapse) { - autocollapse = autoCollapse->isChecked(); - - // uncheck auto expand - if (autoExpand->isChecked()) { - autoexpand = false; - } - - if (autocollapse) { - collapseAll(); - } - } - return; - case MA_AutoExpand: - if (autoExpand) { - // Variable autoExpand should not be null when we arrive here, but - // since we explicitly initialize the variable to nullptr, a check - // nonetheless. - autoexpand = autoExpand->isChecked(); - - // uncheck auto collapse - if (autoCollapse->isChecked()) { - autocollapse = false; - } - - if (autoexpand) { - expandAll(); - } - } + case MA_ExpandToDefault: + expandToDefault(); return; case MA_CollapseAll: collapseAll(); @@ -1037,6 +1067,20 @@ void PropertyEditor::contextMenuEvent(QContextMenuEvent*) case MA_ExpandAll: expandAll(); return; + case MA_DefaultExpand: + action->setChecked(true); + expansionMode = ExpansionMode::DefaultExpand; + return; + case MA_AutoCollapse: + action->setChecked(true); + expansionMode = ExpansionMode::AutoCollapse; + collapseAll(); + return; + case MA_AutoExpand: + action->setChecked(true); + expansionMode = ExpansionMode::AutoExpand; + expandAll(); + return; case MA_ShowHidden: PropertyView::setShowAll(action->isChecked()); return; diff --git a/src/Gui/propertyeditor/PropertyEditor.h b/src/Gui/propertyeditor/PropertyEditor.h index 01c73f66ac..4f5da0511d 100644 --- a/src/Gui/propertyeditor/PropertyEditor.h +++ b/src/Gui/propertyeditor/PropertyEditor.h @@ -70,6 +70,12 @@ class GuiExport PropertyEditor: public QTreeView // clang-format on public: + enum class ExpansionMode { + DefaultExpand, + AutoExpand, + AutoCollapse + }; + PropertyEditor(QWidget* parent = nullptr); ~PropertyEditor() override; @@ -79,10 +85,6 @@ public: void updateProperty(const App::Property&); void removeProperty(const App::Property&); void renameProperty(const App::Property&); - void setAutomaticCollapse(bool); - bool isAutomaticCollapse(bool) const; - void setAutomaticExpand(bool); - bool isAutomaticExpand(bool) const; void setAutomaticDocumentUpdate(bool); bool isAutomaticDocumentUpdate(bool) const; /*! Reset the internal state of the view. */ @@ -133,6 +135,10 @@ protected: void keyPressEvent(QKeyEvent* event) override; private: + void setFirstLevelExpanded(bool doExpand); + void expandToDefault(); + QMenu* setupExpansionSubmenu(QWidget* parent); + void collapseAll(); void setEditorMode(const QModelIndex& parent, int start, int end); void closeTransaction(); void recomputeDocument(App::Document*); @@ -150,8 +156,7 @@ private: QStringList selectedProperty; PropertyModel::PropertyList propList; std::unordered_set propOwners; - bool autocollapse; - bool autoexpand; + ExpansionMode expansionMode; bool autoupdate; bool committing; bool delaybuild; From ade4e4d96a2b026807019efdc717ed28793b09ad Mon Sep 17 00:00:00 2001 From: Pieter Hijma Date: Mon, 15 Sep 2025 15:07:32 +0200 Subject: [PATCH 4/4] Gui: Enable single click expand property editor --- src/Gui/propertyeditor/PropertyEditor.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Gui/propertyeditor/PropertyEditor.cpp b/src/Gui/propertyeditor/PropertyEditor.cpp index d601842b92..2ee9d7428b 100644 --- a/src/Gui/propertyeditor/PropertyEditor.cpp +++ b/src/Gui/propertyeditor/PropertyEditor.cpp @@ -76,7 +76,7 @@ PropertyEditor::PropertyEditor(QWidget* parent) setAlternatingRowColors(true); setRootIsDecorated(false); - setExpandsOnDoubleClick(true); + setExpandsOnDoubleClick(false); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QStyleOptionViewItem opt = PropertyEditor::viewOptions(); @@ -411,6 +411,18 @@ void PropertyEditor::openEditor(const QModelIndex& index) void PropertyEditor::onItemActivated(const QModelIndex& index) { + if (!index.isValid()) { + return; + } + if (auto* prop = static_cast(index.internalPointer()); + prop && prop->isSeparator()) { + + // setExpanded() only works on column 0 + QModelIndex idxFirstColum = propertyModel->index(index.row(), 0, index.parent()); + setExpanded(idxFirstColum, !isExpanded(idxFirstColum)); + return; + } + if (index.column() != 1) { return; }