From fd371573fd59fb3349dca8e0c2330358ea651854 Mon Sep 17 00:00:00 2001 From: forbes Date: Sat, 14 Feb 2026 19:17:42 -0600 Subject: [PATCH] feat(ui): move editing context breadcrumb to viewport overlay (#232) Convert BreadcrumbToolBar from a QToolBar in the MainWindow toolbar area to a QFrame overlay at the top-left of each 3D viewport. Changes: - BreadcrumbToolBar: change base class from QToolBar to QFrame, use QHBoxLayout instead of toolbar actions, semi-transparent overlay background with rounded corners - MainWindow: remove breadcrumb toolbar creation, toolbar break, and signal connection - View3DInventor: create per-view BreadcrumbToolBar as a child of the GL viewer widget, positioned at (8,8) with event filter to keep it raised on viewport resize Each 3D view now has its own breadcrumb instance connected to the EditingContextResolver singleton. This reclaims the full-width toolbar row and keeps the editing context visually tied to the viewport. --- src/Gui/BreadcrumbToolBar.cpp | 37 ++++++++++++++++++----------------- src/Gui/BreadcrumbToolBar.h | 15 +++++++++----- src/Gui/MainWindow.cpp | 18 +---------------- src/Gui/View3DInventor.cpp | 26 ++++++++++++++++++++++++ src/Gui/View3DInventor.h | 3 +++ 5 files changed, 59 insertions(+), 40 deletions(-) diff --git a/src/Gui/BreadcrumbToolBar.cpp b/src/Gui/BreadcrumbToolBar.cpp index 8eaff9216a..f6fd3de4c8 100644 --- a/src/Gui/BreadcrumbToolBar.cpp +++ b/src/Gui/BreadcrumbToolBar.cpp @@ -26,6 +26,7 @@ #include "EditingContext.h" #include +#include #include #include @@ -40,7 +41,6 @@ using namespace Gui; static QString chipStyle(const QString& bgHex) { - // Darken background slightly for contrast, use white text QColor bg(bgHex); QColor textColor(QStringLiteral("#cdd6f4")); // Catppuccin Text @@ -81,24 +81,25 @@ static QString separatorStyle() // --------------------------------------------------------------------------- BreadcrumbToolBar::BreadcrumbToolBar(QWidget* parent) - : QToolBar(parent) + : QFrame(parent) { setObjectName(QStringLiteral("BreadcrumbToolBar")); - setWindowTitle(tr("Editing Context")); - setMovable(false); - setFloatable(false); - setIconSize(QSize(16, 16)); - // Thin toolbar with minimal margins + _layout = new QHBoxLayout(this); + _layout->setContentsMargins(6, 4, 6, 4); + _layout->setSpacing(2); + + // Semi-transparent overlay background setStyleSheet(QStringLiteral( - "QToolBar {" - " background: #1e1e2e;" // Catppuccin Base - " border: none;" - " spacing: 2px;" - " padding: 2px 4px;" - " max-height: 24px;" + "QFrame#BreadcrumbToolBar {" + " background-color: rgba(30, 30, 46, 200);" // Catppuccin Base, ~78% opacity + " border: 1px solid rgba(69, 71, 90, 150);" // Surface1 + " border-radius: 6px;" "}" )); + + setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); + setFixedHeight(28); } @@ -110,6 +111,7 @@ void BreadcrumbToolBar::updateContext(const EditingContext& ctx) { clearSegments(); buildSegments(ctx); + adjustSize(); } @@ -120,17 +122,16 @@ void BreadcrumbToolBar::updateContext(const EditingContext& ctx) void BreadcrumbToolBar::clearSegments() { for (auto* btn : _segments) { - removeAction(btn->defaultAction()); + _layout->removeWidget(btn); delete btn; } _segments.clear(); for (auto* sep : _separators) { + _layout->removeWidget(sep); delete sep; } _separators.clear(); - - clear(); } void BreadcrumbToolBar::buildSegments(const EditingContext& ctx) @@ -144,7 +145,7 @@ void BreadcrumbToolBar::buildSegments(const EditingContext& ctx) if (i > 0) { auto* sep = new QLabel(QStringLiteral("\u203A")); // › character sep->setStyleSheet(separatorStyle()); - addWidget(sep); + _layout->addWidget(sep); _separators.append(sep); } @@ -168,7 +169,7 @@ void BreadcrumbToolBar::buildSegments(const EditingContext& ctx) segmentClicked(segmentIndex); }); - addWidget(btn); + _layout->addWidget(btn); _segments.append(btn); } } diff --git a/src/Gui/BreadcrumbToolBar.h b/src/Gui/BreadcrumbToolBar.h index 13558aaab4..082f126bc0 100644 --- a/src/Gui/BreadcrumbToolBar.h +++ b/src/Gui/BreadcrumbToolBar.h @@ -25,10 +25,11 @@ #ifndef GUI_BREADCRUMBTOOLBAR_H #define GUI_BREADCRUMBTOOLBAR_H -#include +#include #include #include +class QHBoxLayout; class QToolButton; class QLabel; @@ -38,11 +39,14 @@ namespace Gui struct EditingContext; /** - * A thin toolbar that displays the current editing context as color-coded - * breadcrumb segments. Each segment is a clickable QToolButton; clicking - * a parent segment navigates up (exits the current edit, etc.). + * A small overlay widget that displays the current editing context as + * color-coded breadcrumb segments. Each segment is a clickable QToolButton; + * clicking a parent segment navigates up (exits the current edit, etc.). + * + * Intended to be parented to the 3D viewport widget so it floats at the + * top-left corner of the view. */ -class GuiExport BreadcrumbToolBar: public QToolBar +class GuiExport BreadcrumbToolBar: public QFrame { Q_OBJECT @@ -59,6 +63,7 @@ private: void clearSegments(); void buildSegments(const EditingContext& ctx); + QHBoxLayout* _layout; QList _segments; QList _separators; }; diff --git a/src/Gui/MainWindow.cpp b/src/Gui/MainWindow.cpp index 159cf60cf7..7be5dc5c22 100644 --- a/src/Gui/MainWindow.cpp +++ b/src/Gui/MainWindow.cpp @@ -105,8 +105,7 @@ #include "SelectionView.h" #include "SplashScreen.h" #include "StatusBarLabel.h" -#include "BreadcrumbToolBar.h" -#include "EditingContext.h" + #include "ToolBarManager.h" #include "ToolBoxManager.h" #include "Tree.h" @@ -307,7 +306,6 @@ struct MainWindowP QLabel* actionLabel; InputHintWidget* hintLabel; QLabel* rightSideLabel; - BreadcrumbToolBar* breadcrumbBar = nullptr; QTimer* actionTimer; QTimer* statusTimer; QTimer* activityTimer; @@ -492,20 +490,6 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags f) #endif connect(d->mdiArea, &QMdiArea::subWindowActivated, this, &MainWindow::onWindowActivated); - // Breadcrumb toolbar for editing context display - d->breadcrumbBar = new BreadcrumbToolBar(this); - addToolBar(Qt::TopToolBarArea, d->breadcrumbBar); - insertToolBarBreak(d->breadcrumbBar); - - // Initialize the editing context resolver and connect to breadcrumb - auto* ctxResolver = EditingContextResolver::instance(); - connect( - ctxResolver, - &EditingContextResolver::contextChanged, - d->breadcrumbBar, - &BreadcrumbToolBar::updateContext - ); - setupDockWindows(); // accept drops on the window, get handled in dropEvent, dragEnterEvent diff --git a/src/Gui/View3DInventor.cpp b/src/Gui/View3DInventor.cpp index 2dab86ec05..81719fea91 100644 --- a/src/Gui/View3DInventor.cpp +++ b/src/Gui/View3DInventor.cpp @@ -60,7 +60,9 @@ #include "View3DInventor.h" #include "View3DSettings.h" #include "Application.h" +#include "BreadcrumbToolBar.h" #include "BitmapFactory.h" +#include "EditingContext.h" #include "Camera.h" #include "Document.h" #include "FileDialog.h" @@ -145,6 +147,19 @@ View3DInventor::View3DInventor( // apply the user settings applySettings(); + // Breadcrumb overlay at top-left of viewport + _breadcrumb = new BreadcrumbToolBar(_viewer->getWidget()); + _breadcrumb->move(8, 8); + _breadcrumb->raise(); + _breadcrumb->show(); + _viewer->getWidget()->installEventFilter(this); + + auto* ctxResolver = EditingContextResolver::instance(); + connect(ctxResolver, &EditingContextResolver::contextChanged, + _breadcrumb, &BreadcrumbToolBar::updateContext); + // Apply the current context immediately + _breadcrumb->updateContext(ctxResolver->currentContext()); + stopSpinTimer = new QTimer(this); connect(stopSpinTimer, &QTimer::timeout, this, &View3DInventor::stopAnimating); @@ -935,6 +950,17 @@ void View3DInventor::contextMenuEvent(QContextMenuEvent* e) MDIView::contextMenuEvent(e); } +bool View3DInventor::eventFilter(QObject* obj, QEvent* ev) +{ + if (obj == _viewer->getWidget() && ev->type() == QEvent::Resize) { + // Keep breadcrumb at top-left after viewport resize + if (_breadcrumb) { + _breadcrumb->raise(); + } + } + return MDIView::eventFilter(obj, ev); +} + void View3DInventor::customEvent(QEvent* e) { if (e->type() == QEvent::User) { diff --git a/src/Gui/View3DInventor.h b/src/Gui/View3DInventor.h index c3afe5fdee..7a860dfee5 100644 --- a/src/Gui/View3DInventor.h +++ b/src/Gui/View3DInventor.h @@ -40,6 +40,7 @@ class QStackedWidget; namespace Gui { +class BreadcrumbToolBar; class Document; class View3DInventorViewer; class View3DPy; @@ -155,11 +156,13 @@ protected: void keyPressEvent(QKeyEvent* e) override; void keyReleaseEvent(QKeyEvent* e) override; void focusInEvent(QFocusEvent* e) override; + bool eventFilter(QObject* obj, QEvent* ev) override; void customEvent(QEvent* e) override; void contextMenuEvent(QContextMenuEvent* e) override; private: View3DInventorViewer* _viewer; + BreadcrumbToolBar* _breadcrumb; PyObject* _viewerPy; QTimer* stopSpinTimer; QStackedWidget* stack; -- 2.49.1