From 8294b34006737f0eb9a5c916bba5979356263c60 Mon Sep 17 00:00:00 2001 From: tetektoza Date: Sun, 2 Nov 2025 16:40:11 +0100 Subject: [PATCH 1/3] Gui: Respect Selectable property for objects inside Part containers Currently if user selects object with `Selectable=false` property which is nested inside a Part container, for example `Part->Body->Pad`, parent Part container will get highlighted in the 3D view, even though the user clicked on a non-selectable child object. Cause of that is that tree view's `getTopParent()` function resolves nested objects selections to their top-level container. When a Pad inside Part is selected, `SoFCUnifiedSelection` was only checking Part's `isSelectable()` status, even though the target is `Pad`. So the fix is to resolve subname to get the final target object and checks its `isSelectable()` status before checking for highlighting. --- src/Gui/Selection/SoFCUnifiedSelection.cpp | 23 ++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/Gui/Selection/SoFCUnifiedSelection.cpp b/src/Gui/Selection/SoFCUnifiedSelection.cpp index 32328d0cf7..c851341d9f 100644 --- a/src/Gui/Selection/SoFCUnifiedSelection.cpp +++ b/src/Gui/Selection/SoFCUnifiedSelection.cpp @@ -454,10 +454,25 @@ void SoFCUnifiedSelection::doAction(SoAction* action) // selection changes inside the 3d view are handled in handleEvent() App::Document* doc = App::GetApplication().getDocument(selectionAction->SelChange.pDocName); App::DocumentObject* obj = doc->getObject(selectionAction->SelChange.pObjectName); - ViewProvider* vp = Application::Instance->getViewProvider(obj); - if (vp && (useNewSelection.getValue() || vp->useNewSelectionModel()) - && vp->isSelectable()) { - SoDetail* detail = nullptr; + ViewProvider*vp = Application::Instance->getViewProvider(obj); + + // check if the actual subobject being selected is selectable + bool isSelectable = false; + if (vp) { + if (selectionAction->SelChange.pSubName && selectionAction->SelChange.pSubName[0]) { + if (auto subObj = obj->getSubObject(selectionAction->SelChange.pSubName)) { + auto subVp = Application::Instance->getViewProvider(subObj); + isSelectable = subVp ? subVp->isSelectable() : false; + } else { + isSelectable = vp->isSelectable(); + } + } else { + isSelectable = vp->isSelectable(); + } + } + + if (vp && (useNewSelection.getValue() || vp->useNewSelectionModel()) && isSelectable) { + SoDetail *detail = nullptr; detailPath->truncate(0); auto subName = selectionAction->SelChange.pSubName; App::ElementNamePair elementName; From 91933f7f426078e2b4d2d6286307ca43528f659a Mon Sep 17 00:00:00 2001 From: tetektoza Date: Fri, 26 Dec 2025 13:48:51 +0100 Subject: [PATCH 2/3] Gui: Respect parent container selectability in nested selections --- src/Gui/Selection/SoFCUnifiedSelection.cpp | 29 ++++++++++++++-------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/Gui/Selection/SoFCUnifiedSelection.cpp b/src/Gui/Selection/SoFCUnifiedSelection.cpp index c851341d9f..b225d8025d 100644 --- a/src/Gui/Selection/SoFCUnifiedSelection.cpp +++ b/src/Gui/Selection/SoFCUnifiedSelection.cpp @@ -454,25 +454,32 @@ void SoFCUnifiedSelection::doAction(SoAction* action) // selection changes inside the 3d view are handled in handleEvent() App::Document* doc = App::GetApplication().getDocument(selectionAction->SelChange.pDocName); App::DocumentObject* obj = doc->getObject(selectionAction->SelChange.pObjectName); - ViewProvider*vp = Application::Instance->getViewProvider(obj); - - // check if the actual subobject being selected is selectable + ViewProvider* vp = Application::Instance->getViewProvider(obj); + + // check if the subobject and all its parent containers are selectable bool isSelectable = false; if (vp) { if (selectionAction->SelChange.pSubName && selectionAction->SelChange.pSubName[0]) { - if (auto subObj = obj->getSubObject(selectionAction->SelChange.pSubName)) { - auto subVp = Application::Instance->getViewProvider(subObj); - isSelectable = subVp ? subVp->isSelectable() : false; - } else { - isSelectable = vp->isSelectable(); + // get the entire object hierarchy from root to leaf + auto objList = obj->getSubObjectList(selectionAction->SelChange.pSubName); + + isSelectable = true; + for (auto* checkObj : objList) { + if (auto checkVp = Application::Instance->getViewProvider(checkObj)) { + if (!checkVp->isSelectable()) { + isSelectable = false; + break; + } + } } - } else { + } + else { isSelectable = vp->isSelectable(); } } - + if (vp && (useNewSelection.getValue() || vp->useNewSelectionModel()) && isSelectable) { - SoDetail *detail = nullptr; + SoDetail* detail = nullptr; detailPath->truncate(0); auto subName = selectionAction->SelChange.pSubName; App::ElementNamePair elementName; From 913bf82de9cf25193e9eb3fa683de013524c3447 Mon Sep 17 00:00:00 2001 From: tetektoza Date: Tue, 30 Dec 2025 18:12:13 +0100 Subject: [PATCH 3/3] Gui: Add Selectable property to Part containers Change `ViewProviderPart` to inherit from `ViewProviderGeometryObject`, giving Part containers the Selectable property. This allows recursive selectability checks to respect the entire container hierarchy. --- src/Gui/ViewProviderPart.cpp | 6 +++--- src/Gui/ViewProviderPart.h | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Gui/ViewProviderPart.cpp b/src/Gui/ViewProviderPart.cpp index 8dff54813f..7c576959a6 100644 --- a/src/Gui/ViewProviderPart.cpp +++ b/src/Gui/ViewProviderPart.cpp @@ -39,7 +39,7 @@ using namespace Gui; -PROPERTY_SOURCE_WITH_EXTENSIONS(Gui::ViewProviderPart, Gui::ViewProviderDragger) +PROPERTY_SOURCE_WITH_EXTENSIONS(Gui::ViewProviderPart, Gui::ViewProviderGeometryObject) /** @@ -62,7 +62,7 @@ ViewProviderPart::~ViewProviderPart() = default; */ void ViewProviderPart::onChanged(const App::Property* prop) { - ViewProviderDragger::onChanged(prop); + ViewProviderGeometryObject::onChanged(prop); } void ViewProviderPart::setupContextMenu(QMenu* menu, QObject* receiver, const char* member) @@ -74,7 +74,7 @@ void ViewProviderPart::setupContextMenu(QMenu* menu, QObject* receiver, const ch act->setChecked(isActivePart()); func->trigger(act, [this]() { this->toggleActivePart(); }); - ViewProviderDragger::setupContextMenu(menu, receiver, member); + ViewProviderGeometryObject::setupContextMenu(menu, receiver, member); } bool ViewProviderPart::isActivePart() diff --git a/src/Gui/ViewProviderPart.h b/src/Gui/ViewProviderPart.h index 4098fcae22..5d9ec8db4a 100644 --- a/src/Gui/ViewProviderPart.h +++ b/src/Gui/ViewProviderPart.h @@ -23,7 +23,7 @@ #ifndef GUI_VIEWPROVIDER_ViewProviderPart_H #define GUI_VIEWPROVIDER_ViewProviderPart_H -#include "ViewProviderDragger.h" +#include "ViewProviderGeometryObject.h" #include "ViewProviderOriginGroup.h" #include "ViewProviderFeaturePython.h" @@ -31,7 +31,8 @@ namespace Gui { -class GuiExport ViewProviderPart: public ViewProviderDragger, public ViewProviderOriginGroupExtension +class GuiExport ViewProviderPart: public ViewProviderGeometryObject, + public ViewProviderOriginGroupExtension { PROPERTY_HEADER_WITH_EXTENSIONS(Gui::ViewProviderPart);