Make mode hiding and style available from mode selector

Add the View > Modes menu as a context menu to the mode selector in the
emtpy areas. Add a context menu with "Hide" and the mode style to the
modes that don't have a menu, and extend existing mode menus (Debug
mode) with these items too.

Change-Id: I28106d9b6c4f0d69b2d06c4ec9664eb67e2b1216
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Eike Ziller
2024-07-09 15:57:48 +02:00
parent d386421998
commit e1560a3c7c
9 changed files with 105 additions and 47 deletions

View File

@@ -212,11 +212,10 @@ void FancyTabBar::mousePressEvent(QMouseEvent *event)
continue; continue;
const QRect rect = tabRect(visibleIndex); const QRect rect = tabRect(visibleIndex);
if (rect.contains(event->pos())) { if (rect.contains(event->pos())) {
if (isTabEnabled(index)) { if (isTabEnabled(index) && event->button() == Qt::LeftButton) {
if (m_tabs.at(index)->hasMenu if (m_tabs.at(index)->hasMenu
&& ((!m_iconsOnly && rect.right() - event->pos().x() <= kMenuButtonWidth) && (!m_iconsOnly && rect.right() - event->pos().x() <= kMenuButtonWidth)) {
|| event->button() == Qt::RightButton)) { // menu arrow clicked
// menu arrow clicked or right-click
emit menuTriggered(index, event); emit menuTriggered(index, event);
} else { } else {
if (index != m_currentIndex) { if (index != m_currentIndex) {
@@ -226,11 +225,16 @@ void FancyTabBar::mousePressEvent(QMouseEvent *event)
emit currentChanged(m_currentIndex); emit currentChanged(m_currentIndex);
} }
} }
} else if (event->button() == Qt::RightButton) {
emit menuTriggered(index, event);
} }
break; return;
} }
++visibleIndex; ++visibleIndex;
} }
// not in a mode button
if (event->button() == Qt::RightButton)
emit menuTriggered(-1, event);
} }
static void paintSelectedTabBackground(QPainter *painter, const QRect &spanRect) static void paintSelectedTabBackground(QPainter *painter, const QRect &spanRect)
@@ -457,7 +461,7 @@ public:
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
} }
void mousePressEvent(QMouseEvent *ev) override { emit clicked(ev->button(), ev->modifiers()); } void mousePressEvent(QMouseEvent *ev) override { emit clicked(ev); }
void paintEvent(QPaintEvent *event) override void paintEvent(QPaintEvent *event) override
{ {
@@ -475,7 +479,7 @@ public:
} }
signals: signals:
void clicked(Qt::MouseButton button, Qt::KeyboardModifiers modifiers); void clicked(QMouseEvent *ev);
}; };
////// //////
@@ -490,7 +494,12 @@ FancyTabWidget::FancyTabWidget(QWidget *parent)
auto bar = new StyledBar; auto bar = new StyledBar;
auto fancyButton = new FancyColorButton; auto fancyButton = new FancyColorButton;
connect(fancyButton, &FancyColorButton::clicked, this, &FancyTabWidget::topAreaClicked); connect(fancyButton, &FancyColorButton::clicked, this, [this](QMouseEvent *event) {
if (event->button() == Qt::RightButton)
emit menuTriggered(-1, event);
else
emit topAreaClicked(event);
});
m_modesStack = new QStackedLayout; m_modesStack = new QStackedLayout;
m_modesStack->addWidget(new QWidget(this)); m_modesStack->addWidget(new QWidget(this));
@@ -499,6 +508,7 @@ FancyTabWidget::FancyTabWidget(QWidget *parent)
QVBoxLayout *vlayout; QVBoxLayout *vlayout;
// clang-format off
using namespace Layouting; using namespace Layouting;
Row { fancyButton, noMargin }.attachTo(bar); Row { fancyButton, noMargin }.attachTo(bar);
Row { Row {
@@ -507,10 +517,9 @@ FancyTabWidget::FancyTabWidget(QWidget *parent)
Column { Column {
bar, bar,
m_tabBar, m_tabBar,
st,
Widget { Widget {
bindTo(&m_cornerWidgetContainer), bindTo(&m_cornerWidgetContainer),
Column { st, spacing(0), noMargin }, Column { spacing(0), noMargin },
}, },
spacing(0), noMargin, spacing(0), noMargin,
}, },
@@ -518,6 +527,7 @@ FancyTabWidget::FancyTabWidget(QWidget *parent)
Column { bindTo(&vlayout), m_modesStack, m_statusBar, spacing(0) }, Column { bindTo(&vlayout), m_modesStack, m_statusBar, spacing(0) },
spacing(1), noMargin, spacing(1), noMargin,
}.attachTo(this); }.attachTo(this);
// clang-format on
m_selectionWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); m_selectionWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);

View File

@@ -156,7 +156,7 @@ signals:
void currentAboutToShow(int index); void currentAboutToShow(int index);
void currentChanged(int index); void currentChanged(int index);
void menuTriggered(int index, QMouseEvent *event); void menuTriggered(int index, QMouseEvent *event);
void topAreaClicked(Qt::MouseButton button, Qt::KeyboardModifiers modifiers); void topAreaClicked(QMouseEvent *event);
public slots: public slots:
void setCurrentIndex(int index); void setCurrentIndex(int index);

View File

@@ -79,6 +79,7 @@
#include <QDebug> #include <QDebug>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QLibraryInfo> #include <QLibraryInfo>
#include <QLoggingCategory>
#include <QMenu> #include <QMenu>
#include <QMenuBar> #include <QMenuBar>
#include <QMessageBox> #include <QMessageBox>
@@ -96,6 +97,8 @@
#include <malloc.h> #include <malloc.h>
#endif #endif
Q_LOGGING_CATEGORY(coreLog, "qtc.core", QtWarningMsg)
/*! /*!
\namespace Core \namespace Core
\inmodule QtCreator \inmodule QtCreator
@@ -1373,8 +1376,8 @@ void ICorePrivate::init()
QApplication::setStyle(new ManhattanStyle(baseName)); QApplication::setStyle(new ManhattanStyle(baseName));
m_modeManager = new ModeManager(m_modeStack); m_modeManager = new ModeManager(m_modeStack);
connect(m_modeStack, &FancyTabWidget::topAreaClicked, this, [](Qt::MouseButton, Qt::KeyboardModifiers modifiers) { connect(m_modeStack, &FancyTabWidget::topAreaClicked, this, [](QMouseEvent *event) {
if (modifiers & Qt::ShiftModifier) { if (event->modifiers() & Qt::ShiftModifier) {
QColor color = QColorDialog::getColor(StyleHelper::requestedBaseColor(), ICore::dialogParent()); QColor color = QColorDialog::getColor(StyleHelper::requestedBaseColor(), ICore::dialogParent());
if (color.isValid()) if (color.isValid())
StyleHelper::setBaseColor(color); StyleHelper::setBaseColor(color);
@@ -2412,6 +2415,10 @@ void ICorePrivate::updateContext()
uniquecontexts.add(id); uniquecontexts.add(id);
} }
if (coreLog().isDebugEnabled()) {
qCDebug(coreLog) << "context changed:"
<< Utils::transform<QList<QString>>(uniquecontexts, &Id::toString);
}
ActionManager::setContext(uniquecontexts); ActionManager::setContext(uniquecontexts);
emit m_core->contextChanged(uniquecontexts); emit m_core->contextChanged(uniquecontexts);
} }

View File

@@ -21,7 +21,7 @@ class IModePrivate
public: public:
QString m_displayName; QString m_displayName;
QIcon m_icon; QIcon m_icon;
QMenu *m_menu = nullptr; std::function<void(QMenu *)> m_menuFunction;
Utils::FancyMainWindow *m_mainWindow = nullptr; Utils::FancyMainWindow *m_mainWindow = nullptr;
int m_priority = -1; int m_priority = -1;
Utils::Id m_id; Utils::Id m_id;
@@ -110,15 +110,6 @@ public:
This property holds the ID of the mode. This property holds the ID of the mode.
*/ */
/*!
\property IMode::menu
This property holds the mode's menu.
By default, a mode does not have a menu. When you set a menu, it is not
owned by the mode unless you set the parent explicitly.
*/
/*! /*!
Creates an IMode with an optional \a parent. Creates an IMode with an optional \a parent.
@@ -194,9 +185,15 @@ void IMode::setId(Utils::Id id)
m_d->m_isVisible.readSettings(); m_d->m_isVisible.readSettings();
} }
void IMode::setMenu(QMenu *menu) /*!
Sets a \a menuFunction that is used to add the mode specific items
to the mode's context menu. This is called every time the context
menu is requested with a new QMenu instance.
The menu is destroyed after the it closes.
*/
void IMode::setMenu(std::function<void(QMenu *)> menuFunction)
{ {
m_d->m_menu = menu; m_d->m_menuFunction = menuFunction;
} }
void IMode::setContext(const Context &context) void IMode::setContext(const Context &context)
@@ -232,9 +229,25 @@ bool IMode::isVisible() const
return m_d->m_isVisible.value(); return m_d->m_isVisible.value();
} }
QMenu *IMode::menu() const /*!
Returns if the mode provides mode specific context menu items.
\sa setMenu()
*/
bool IMode::hasMenu() const
{ {
return m_d->m_menu; return bool(m_d->m_menuFunction);
}
/*!
Adds the mode specific items to the \a menu, if any.
\sa setMenu()
*/
void IMode::addToMenu(QMenu *menu) const
{
if (m_d->m_menuFunction)
m_d->m_menuFunction(menu);
} }
Context IMode::context() const Context IMode::context() const

View File

@@ -10,6 +10,7 @@
#include <QIcon> #include <QIcon>
#include <QMenu> #include <QMenu>
#include <functional>
#include <memory.h> #include <memory.h>
namespace Utils { namespace Utils {
@@ -29,7 +30,6 @@ class CORE_EXPORT IMode : public QObject
Q_PROPERTY(QIcon icon READ icon WRITE setIcon) Q_PROPERTY(QIcon icon READ icon WRITE setIcon)
Q_PROPERTY(int priority READ priority WRITE setPriority) Q_PROPERTY(int priority READ priority WRITE setPriority)
Q_PROPERTY(Utils::Id id READ id WRITE setId) Q_PROPERTY(Utils::Id id READ id WRITE setId)
Q_PROPERTY(QMenu *menu READ menu WRITE setMenu)
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledStateChanged) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledStateChanged)
public: public:
@@ -42,7 +42,8 @@ public:
Utils::Id id() const; Utils::Id id() const;
bool isEnabled() const; bool isEnabled() const;
bool isVisible() const; bool isVisible() const;
QMenu *menu() const; bool hasMenu() const;
void addToMenu(QMenu *menu) const;
Context context() const; Context context() const;
QWidget *widget() const; QWidget *widget() const;
@@ -52,7 +53,7 @@ public:
void setIcon(const QIcon &icon); void setIcon(const QIcon &icon);
void setPriority(int priority); void setPriority(int priority);
void setId(Utils::Id id); void setId(Utils::Id id);
void setMenu(QMenu *menu); void setMenu(std::function<void(QMenu *)> menuFunction);
void setContext(const Context &context); void setContext(const Context &context);
void setWidget(QWidget *widget); void setWidget(QWidget *widget);

View File

@@ -104,8 +104,34 @@ static int indexOf(Id id)
void ModeManagerPrivate::showMenu(int index, QMouseEvent *event) void ModeManagerPrivate::showMenu(int index, QMouseEvent *event)
{ {
QTC_ASSERT(m_modes.at(index)->menu(), return); if (index < 0) {
m_modes.at(index)->menu()->popup(event->globalPosition().toPoint()); ActionContainer *viewContainer = ActionManager::actionContainer(
Constants::M_VIEW_MODESTYLES);
QTC_ASSERT(viewContainer, return);
QMenu *viewMenu = viewContainer->menu();
QTC_ASSERT(viewMenu, return);
QList<QAction *> actions = viewMenu->actions();
if (actions.isEmpty())
return;
auto menu = new QMenu(m_actionBar);
menu->setAttribute(Qt::WA_DeleteOnClose);
for (QAction *a : actions)
menu->addAction(a);
menu->popup(event->globalPosition().toPoint());
return;
}
IMode *mode = m_modes.value(index);
QTC_ASSERT(mode, return);
auto menu = new QMenu(m_actionBar);
menu->setAttribute(Qt::WA_DeleteOnClose);
mode->addToMenu(menu);
menu->addSeparator();
menu->addAction(Tr::tr("Hide"), mode, [mode] { mode->setVisible(false); });
menu->addSeparator();
menu->addAction(m_setModeSelectorStyleIconsAndTextAction);
menu->addAction(m_setModeSelectorStyleIconsOnlyAction);
menu->addAction(m_setModeSelectorStyleHiddenAction);
menu->popup(event->globalPosition().toPoint());
} }
ModeManager::ModeManager(Internal::FancyTabWidget *modeStack) ModeManager::ModeManager(Internal::FancyTabWidget *modeStack)
@@ -277,8 +303,7 @@ void ModeManagerPrivate::appendMode(IMode *mode)
{ {
const int index = m_modeCommands.count(); const int index = m_modeCommands.count();
m_modeStack->insertTab(index, mode->widget(), mode->icon(), mode->displayName(), m_modeStack->insertTab(index, mode->widget(), mode->icon(), mode->displayName(), mode->hasMenu());
mode->menu() != nullptr);
m_modeStack->setTabEnabled(index, mode->isEnabled()); m_modeStack->setTabEnabled(index, mode->isEnabled());
m_modeStack->setTabVisible(index, mode->isVisible()); m_modeStack->setTabVisible(index, mode->isVisible());

View File

@@ -192,15 +192,7 @@ DebuggerMainWindowPrivate::DebuggerMainWindowPrivate(DebuggerMainWindow *parent)
m_perspectiveMenu = new QMenu; m_perspectiveMenu = new QMenu;
connect(m_perspectiveMenu, &QMenu::aboutToShow, this, [this] { connect(m_perspectiveMenu, &QMenu::aboutToShow, this, [this] {
m_perspectiveMenu->clear(); m_perspectiveMenu->clear();
for (Perspective *perspective : std::as_const(m_perspectives)) { DebuggerMainWindow::addPerspectiveMenu(m_perspectiveMenu);
m_perspectiveMenu->addAction(perspective->d->m_name, perspective, [perspective] {
if (auto subPerspective = Perspective::findPerspective(
perspective->d->m_lastActiveSubPerspectiveId))
subPerspective->select();
else
perspective->select();
});
}
}); });
auto viewButton = new QToolButton; auto viewButton = new QToolButton;
@@ -511,9 +503,19 @@ void DebuggerMainWindow::addSubPerspectiveSwitcher(QWidget *widget)
d->m_subPerspectiveSwitcherLayout->addWidget(widget); d->m_subPerspectiveSwitcherLayout->addWidget(widget);
} }
QMenu *DebuggerMainWindow::perspectiveMenu() void DebuggerMainWindow::addPerspectiveMenu(QMenu *menu)
{ {
return theMainWindow ? theMainWindow->d->m_perspectiveMenu : nullptr; if (!theMainWindow)
return;
for (Perspective *perspective : std::as_const(theMainWindow->d->m_perspectives)) {
menu->addAction(perspective->d->m_name, perspective, [perspective] {
if (auto subPerspective = Perspective::findPerspective(
perspective->d->m_lastActiveSubPerspectiveId))
subPerspective->select();
else
perspective->select();
});
}
} }
DebuggerMainWindow *DebuggerMainWindow::instance() DebuggerMainWindow *DebuggerMainWindow::instance()

View File

@@ -142,7 +142,7 @@ public:
static QWidget *centralWidgetStack(); static QWidget *centralWidgetStack();
void addSubPerspectiveSwitcher(QWidget *widget); void addSubPerspectiveSwitcher(QWidget *widget);
static QMenu *perspectiveMenu(); static void addPerspectiveMenu(QMenu *menu);
static Perspective *currentPerspective(); static Perspective *currentPerspective();

View File

@@ -497,7 +497,7 @@ public:
setWidget(splitter); setWidget(splitter);
setMainWindow(mainWindow); setMainWindow(mainWindow);
setMenu(DebuggerMainWindow::perspectiveMenu()); setMenu(&DebuggerMainWindow::addPerspectiveMenu);
} }
~DebugMode() { delete widget(); } ~DebugMode() { delete widget(); }