Merge pull request 'feat(ui): move editing context breadcrumb to viewport overlay (#232)' (#236) from feat/breadcrumb-viewport-overlay into main
Some checks failed
Build and Test / build (push) Has been cancelled

Reviewed-on: #236
This commit was merged in pull request #236.
This commit is contained in:
2026-02-15 01:24:09 +00:00
5 changed files with 59 additions and 40 deletions

View File

@@ -26,6 +26,7 @@
#include "EditingContext.h"
#include <QColor>
#include <QHBoxLayout>
#include <QLabel>
#include <QToolButton>
@@ -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);
}
}

View File

@@ -25,10 +25,11 @@
#ifndef GUI_BREADCRUMBTOOLBAR_H
#define GUI_BREADCRUMBTOOLBAR_H
#include <QToolBar>
#include <QFrame>
#include <QList>
#include <FCGlobal.h>
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<QToolButton*> _segments;
QList<QLabel*> _separators;
};

View File

@@ -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

View File

@@ -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) {

View File

@@ -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;