diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index 3cb80e658f..13fd4a8210 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -1046,6 +1046,9 @@ void Application::slotNewDocument(const App::Document& Doc, bool isMainDoc) ); pDoc->signalInEdit.connect(std::bind(&Gui::Application::slotInEdit, this, sp::_1)); pDoc->signalResetEdit.connect(std::bind(&Gui::Application::slotResetEdit, this, sp::_1)); + pDoc->signalActivatedViewProvider.connect( + std::bind(&Gui::Application::slotActivatedViewProvider, this, sp::_1, sp::_2) + ); // NOLINTEND signalNewDocument(*pDoc, isMainDoc); @@ -1352,6 +1355,12 @@ void Application::slotResetEdit(const Gui::ViewProviderDocumentObject& vp) this->signalResetEdit(vp); } +void Application::slotActivatedViewProvider( + const Gui::ViewProviderDocumentObject* vp, const char* name) +{ + this->signalActivatedViewProvider(vp, name); +} + void Application::onLastWindowClosed(Gui::Document* pcDoc) { try { diff --git a/src/Gui/Application.h b/src/Gui/Application.h index eff1ac8854..e9dd46f81a 100644 --- a/src/Gui/Application.h +++ b/src/Gui/Application.h @@ -153,6 +153,9 @@ public: fastsignals::signal signalInEdit; /// signal on leaving edit mode fastsignals::signal signalResetEdit; + /// signal on activated view-provider (active-object change, e.g. "pdbody", "part") + fastsignals::signal + signalActivatedViewProvider; /// signal on changing user edit mode fastsignals::signal signalUserEditModeChanged; //@} @@ -174,6 +177,7 @@ protected: void slotActivatedObject(const ViewProvider&); void slotInEdit(const Gui::ViewProviderDocumentObject&); void slotResetEdit(const Gui::ViewProviderDocumentObject&); + void slotActivatedViewProvider(const Gui::ViewProviderDocumentObject*, const char*); public: /// message when a GuiDocument is about to vanish diff --git a/src/Gui/EditingContext.cpp b/src/Gui/EditingContext.cpp index 15f1582df8..2ee94e2f13 100644 --- a/src/Gui/EditingContext.cpp +++ b/src/Gui/EditingContext.cpp @@ -121,6 +121,9 @@ EditingContextResolver::EditingContextResolver() app.signalActiveDocument.connect([this](const Document& doc) { onActiveDocument(doc); }); app.signalActivateView.connect([this](const MDIView* view) { onActivateView(view); }); app.signalActivateWorkbench.connect([this](const char*) { refresh(); }); + app.signalActivatedViewProvider.connect( + [this](const ViewProviderDocumentObject*, const char*) { refresh(); } + ); } EditingContextResolver::~EditingContextResolver() @@ -172,6 +175,23 @@ static App::DocumentObject* getActivePartObject() return view->getActiveObject("part"); } +// --------------------------------------------------------------------------- +// Helper: get the active "pdbody" object from the active view +// --------------------------------------------------------------------------- + +static App::DocumentObject* getActivePdBodyObject() +{ + auto* guiDoc = Application::Instance->activeDocument(); + if (!guiDoc) { + return nullptr; + } + auto* view = guiDoc->getActiveView(); + if (!view) { + return nullptr; + } + return view->getActiveObject("pdbody"); +} + // --------------------------------------------------------------------------- // Helper: get the label of the active "part" object // --------------------------------------------------------------------------- @@ -213,6 +233,34 @@ static QString getInEditLabel() void EditingContextResolver::registerBuiltinContexts() { + // --- PartDesign body active inside an assembly (supersedes assembly.edit) --- + registerContext({ + /*.id =*/QStringLiteral("partdesign.in_assembly"), + /*.labelTemplate =*/QStringLiteral("Body: {name}"), + /*.color =*/QLatin1String(CatppuccinMocha::Mauve), + /*.toolbars =*/ + {QStringLiteral("Part Design Helper Features"), + QStringLiteral("Part Design Modeling Features"), + QStringLiteral("Part Design Dress-Up Features"), + QStringLiteral("Part Design Transformation Features"), + QStringLiteral("Sketcher")}, + /*.priority =*/95, + /*.match =*/ + []() { + auto* body = getActivePdBodyObject(); + if (!body || !objectIsDerivedFrom(body, "PartDesign::Body")) { + return false; + } + // Only match when we're inside an assembly edit session + auto* doc = Application::Instance->activeDocument(); + if (!doc) { + return false; + } + auto* vp = doc->getInEdit(); + return vp && vpObjectIsDerivedFrom(vp, "Assembly::AssemblyObject"); + }, + }); + // --- Sketcher edit (highest priority — VP in edit) --- registerContext({ /*.id =*/QStringLiteral("sketcher.edit"), @@ -272,7 +320,10 @@ void EditingContextResolver::registerBuiltinContexts() /*.priority =*/40, /*.match =*/ []() { - auto* obj = getActivePartObject(); + auto* obj = getActivePdBodyObject(); + if (!obj) { + obj = getActivePartObject(); + } if (!obj || !objectIsDerivedFrom(obj, "PartDesign::Body")) { return false; } @@ -301,7 +352,10 @@ void EditingContextResolver::registerBuiltinContexts() /*.priority =*/30, /*.match =*/ []() { - auto* obj = getActivePartObject(); + auto* obj = getActivePdBodyObject(); + if (!obj) { + obj = getActivePartObject(); + } return obj && objectIsDerivedFrom(obj, "PartDesign::Body"); }, }); @@ -488,6 +542,13 @@ EditingContext EditingContextResolver::resolve() const if (label.contains(QStringLiteral("{name}"))) { // For edit-mode contexts, use the in-edit object name QString name = getInEditLabel(); + if (name.isEmpty()) { + // Try pdbody first for PartDesign contexts + auto* bodyObj = getActivePdBodyObject(); + if (bodyObj) { + name = QString::fromUtf8(bodyObj->Label.getValue()); + } + } if (name.isEmpty()) { name = getActivePartLabel(); } @@ -548,6 +609,25 @@ QStringList EditingContextResolver::buildBreadcrumb(const EditingContext& ctx) c return crumbs; } + // Assembly > Body breadcrumb for in-assembly part editing + if (ctx.id == QStringLiteral("partdesign.in_assembly")) { + auto* guiDoc = Application::Instance->activeDocument(); + if (guiDoc) { + auto* vp = guiDoc->getInEdit(); + if (vp) { + auto* vpd = dynamic_cast(vp); + if (vpd && vpd->getObject()) { + crumbs << QString::fromUtf8(vpd->getObject()->Label.getValue()); + } + } + } + auto* body = getActivePdBodyObject(); + if (body) { + crumbs << QString::fromUtf8(body->Label.getValue()); + } + return crumbs; + } + // Always start with the active part/body/assembly label QString partLabel = getActivePartLabel(); if (!partLabel.isEmpty()) { @@ -582,6 +662,14 @@ QStringList EditingContextResolver::buildBreadcrumbColors(const EditingContext& { QStringList colors; + if (ctx.id == QStringLiteral("partdesign.in_assembly")) { + for (int i = 0; i < ctx.breadcrumb.size(); ++i) { + colors << (i == 0 ? QLatin1String(CatppuccinMocha::Blue) + : QLatin1String(CatppuccinMocha::Mauve)); + } + return colors; + } + if (ctx.breadcrumb.size() <= 1) { colors << ctx.color; return colors;