diff --git a/src/plugins/coreplugin/fancytabwidget.cpp b/src/plugins/coreplugin/fancytabwidget.cpp index c4b942e0c51..925efb4b285 100644 --- a/src/plugins/coreplugin/fancytabwidget.cpp +++ b/src/plugins/coreplugin/fancytabwidget.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include using namespace Core; @@ -50,6 +51,8 @@ using namespace Utils; const int FancyTabBar::m_rounding = 22; const int FancyTabBar::m_textPadding = 4; +static const int kMenuButtonWidth = 16; + void FancyTab::fadeIn() { animator.stop(); @@ -83,10 +86,6 @@ FancyTabBar::FancyTabBar(QWidget *parent) setAttribute(Qt::WA_Hover, true); setFocusPolicy(Qt::NoFocus); setMouseTracking(true); // Needed for hover events - m_triggerTimer.setSingleShot(true); - - // We use a zerotimer to keep the sidebar responsive - connect(&m_triggerTimer, &QTimer::timeout, this, &FancyTabBar::emitCurrentIndex); } FancyTabBar::~FancyTabBar() @@ -104,7 +103,7 @@ QSize FancyTabBar::tabSizeHint(bool minimum) const int width = 60 + spacing + 2; int maxLabelwidth = 0; for (int tab=0 ; tabtext); if (width > maxLabelwidth) maxLabelwidth = width; } @@ -211,24 +210,22 @@ QRect FancyTabBar::tabRect(int index) const } -// This keeps the sidebar responsive since -// we get a repaint before loading the -// mode itself -void FancyTabBar::emitCurrentIndex() -{ - emit currentChanged(m_currentIndex); -} - void FancyTabBar::mousePressEvent(QMouseEvent *e) { e->accept(); for (int index = 0; index < m_tabs.count(); ++index) { - if (tabRect(index).contains(e->pos())) { - + const QRect rect = tabRect(index); + if (rect.contains(e->pos())) { if (isTabEnabled(index)) { - m_currentIndex = index; - update(); - m_triggerTimer.start(0); + if (m_tabs.at(index)->hasMenu && rect.right() - e->pos().x() <= kMenuButtonWidth) { + // menu arrow clicked + emit menuTriggered(index, e); + } else { + m_currentIndex = index; + update(); + // update tab bar before showing widget + QTimer::singleShot(0, this, [this]() { emit currentChanged(m_currentIndex); }); + } } break; } @@ -290,6 +287,7 @@ void FancyTabBar::paintTab(QPainter *painter, int tabIndex) const } painter->save(); + FancyTab *tab = m_tabs.at(tabIndex); QRect rect = tabRect(tabIndex); bool selected = (tabIndex == m_currentIndex); bool enabled = isTabEnabled(tabIndex); @@ -303,7 +301,7 @@ void FancyTabBar::paintTab(QPainter *painter, int tabIndex) const } } - QString tabText(this->tabText(tabIndex)); + QString tabText(tab->text); QRect tabTextRect(rect); const bool drawIcon = rect.height() > 36; QRect tabIconRect(tabTextRect); @@ -334,7 +332,7 @@ void FancyTabBar::paintTab(QPainter *painter, int tabIndex) const tabIconRect.adjust(0, 4, 0, -textHeight); const QIcon::Mode iconMode = enabled ? (selected ? QIcon::Active : QIcon::Normal) : QIcon::Disabled; - StyleHelper::drawIconWithShadow(tabIcon(tabIndex), tabIconRect, painter, iconMode); + StyleHelper::drawIconWithShadow(tab->icon, tabIconRect, painter, iconMode); } painter->setOpacity(1.0); //FIXME: was 0.7 before? @@ -350,6 +348,13 @@ void FancyTabBar::paintTab(QPainter *painter, int tabIndex) const painter->translate(0, -1); painter->drawText(tabTextRect, textFlags, tabText); + // menu arrow + if (tab->hasMenu) { + QStyleOption opt; + opt.initFrom(this); + opt.rect = rect.adjusted(rect.width() - kMenuButtonWidth, 0, -8, 0); + StyleHelper::drawArrow(QStyle::PE_IndicatorArrowRight, painter, &opt); + } painter->restore(); } @@ -479,6 +484,7 @@ FancyTabWidget::FancyTabWidget(QWidget *parent) setLayout(mainLayout); connect(m_tabBar, &FancyTabBar::currentChanged, this, &FancyTabWidget::showWidget); + connect(m_tabBar, &FancyTabBar::menuTriggered, this, &FancyTabWidget::menuTriggered); } void FancyTabWidget::setSelectionWidgetVisible(bool visible) @@ -491,10 +497,11 @@ bool FancyTabWidget::isSelectionWidgetVisible() const return m_selectionWidget->isVisible(); } -void FancyTabWidget::insertTab(int index, QWidget *tab, const QIcon &icon, const QString &label) +void FancyTabWidget::insertTab(int index, QWidget *tab, const QIcon &icon, const QString &label, + bool hasMenu) { m_modesStack->insertWidget(index, tab); - m_tabBar->insertTab(index, icon, label); + m_tabBar->insertTab(index, icon, label, hasMenu); } void FancyTabWidget::removeTab(int index) diff --git a/src/plugins/coreplugin/fancytabwidget.h b/src/plugins/coreplugin/fancytabwidget.h index e59d6189ea7..f75dfdf271a 100644 --- a/src/plugins/coreplugin/fancytabwidget.h +++ b/src/plugins/coreplugin/fancytabwidget.h @@ -46,7 +46,7 @@ class FancyTab : public QObject Q_PROPERTY(float fader READ fader WRITE setFader) public: - FancyTab(QWidget *tabbar) : enabled(false), tabbar(tabbar), m_fader(0) { + FancyTab(QWidget *tabbar) : tabbar(tabbar){ animator.setPropertyName("fader"); animator.setTargetObject(this); } @@ -59,12 +59,13 @@ public: QIcon icon; QString text; QString toolTip; - bool enabled; + bool enabled = false; + bool hasMenu = false; private: QPropertyAnimation animator; QWidget *tabbar; - float m_fader; + float m_fader = 0; }; class FancyTabBar : public QWidget @@ -91,10 +92,11 @@ public: void setTabEnabled(int index, bool enable); bool isTabEnabled(int index) const; - void insertTab(int index, const QIcon &icon, const QString &label) { + void insertTab(int index, const QIcon &icon, const QString &label, bool hasMenu) { FancyTab *tab = new FancyTab(this); tab->icon = icon; tab->text = label; + tab->hasMenu = hasMenu; m_tabs.insert(index, tab); updateGeometry(); } @@ -110,16 +112,12 @@ public: void setTabToolTip(int index, QString toolTip) { m_tabs[index]->toolTip = toolTip; } QString tabToolTip(int index) const { return m_tabs.at(index)->toolTip; } - QIcon tabIcon(int index) const { return m_tabs.at(index)->icon; } - QString tabText(int index) const { return m_tabs.at(index)->text; } int count() const {return m_tabs.count(); } QRect tabRect(int index) const; signals: - void currentChanged(int); - -public slots: - void emitCurrentIndex(); + void currentChanged(int index); + void menuTriggered(int index, QMouseEvent *event); private: static const int m_rounding; @@ -128,7 +126,6 @@ private: int m_hoverIndex; int m_currentIndex; QList m_tabs; - QTimer m_triggerTimer; QSize tabSizeHint(bool minimum = false) const; }; @@ -140,7 +137,7 @@ class FancyTabWidget : public QWidget public: FancyTabWidget(QWidget *parent = 0); - void insertTab(int index, QWidget *tab, const QIcon &icon, const QString &label); + void insertTab(int index, QWidget *tab, const QIcon &icon, const QString &label, bool hasMenu); void removeTab(int index); void setBackgroundBrush(const QBrush &brush); void addCornerWidget(QWidget *widget); @@ -161,6 +158,7 @@ public: signals: void currentAboutToShow(int index); void currentChanged(int index); + void menuTriggered(int index, QMouseEvent *event); void topAreaClicked(Qt::MouseButton button, Qt::KeyboardModifiers modifiers); public slots: diff --git a/src/plugins/coreplugin/imode.cpp b/src/plugins/coreplugin/imode.cpp index e457cd8b882..ed105233574 100644 --- a/src/plugins/coreplugin/imode.cpp +++ b/src/plugins/coreplugin/imode.cpp @@ -32,6 +32,12 @@ IMode::IMode(QObject *parent) { } +IMode::~IMode() +{ + if (m_menu) + delete m_menu; +} + void IMode::setEnabled(bool enabled) { if (m_isEnabled == enabled) diff --git a/src/plugins/coreplugin/imode.h b/src/plugins/coreplugin/imode.h index cf745b4516f..4db3e51f095 100644 --- a/src/plugins/coreplugin/imode.h +++ b/src/plugins/coreplugin/imode.h @@ -29,6 +29,7 @@ #include "id.h" #include +#include namespace Core { @@ -39,18 +40,21 @@ class CORE_EXPORT IMode : public IContext public: IMode(QObject *parent = 0); + ~IMode(); QString displayName() const { return m_displayName; } QIcon icon() const { return m_icon; } int priority() const { return m_priority; } Id id() const { return m_id; } bool isEnabled() const; + QMenu *menu() const { return m_menu; } void setEnabled(bool enabled); void setDisplayName(const QString &displayName) { m_displayName = displayName; } void setIcon(const QIcon &icon) { m_icon = icon; } void setPriority(int priority) { m_priority = priority; } void setId(Id id) { m_id = id; } + void setMenu(QMenu *menu) { m_menu = menu; } signals: void enabledStateChanged(bool enabled); @@ -58,6 +62,7 @@ signals: private: QString m_displayName; QIcon m_icon; + QMenu *m_menu = nullptr; int m_priority; Id m_id; bool m_isEnabled; diff --git a/src/plugins/coreplugin/modemanager.cpp b/src/plugins/coreplugin/modemanager.cpp index cbac31062de..588b52c141c 100644 --- a/src/plugins/coreplugin/modemanager.cpp +++ b/src/plugins/coreplugin/modemanager.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include namespace Core { @@ -57,6 +58,8 @@ namespace Core { struct ModeManagerPrivate { + void showMenu(int index, QMouseEvent *event); + Internal::MainWindow *m_mainWindow; Internal::FancyTabWidget *m_modeStack; Internal::FancyActionBar *m_actionBar; @@ -81,6 +84,12 @@ static int indexOf(Id id) return -1; } +void ModeManagerPrivate::showMenu(int index, QMouseEvent *event) +{ + QTC_ASSERT(m_modes.at(index)->menu(), return); + m_modes.at(index)->menu()->popup(event->globalPos()); +} + ModeManager::ModeManager(Internal::MainWindow *mainWindow, Internal::FancyTabWidget *modeStack) { @@ -98,6 +107,8 @@ ModeManager::ModeManager(Internal::MainWindow *mainWindow, this, &ModeManager::currentTabAboutToChange); connect(d->m_modeStack, &Internal::FancyTabWidget::currentChanged, this, &ModeManager::currentTabChanged); + connect(d->m_modeStack, &Internal::FancyTabWidget::menuTriggered, + this, [](int index, QMouseEvent *e) { d->showMenu(index, e); }); } void ModeManager::init() @@ -153,7 +164,8 @@ void ModeManager::objectAdded(QObject *obj) ++index; d->m_modes.insert(index, mode); - d->m_modeStack->insertTab(index, mode->widget(), mode->icon(), mode->displayName()); + d->m_modeStack->insertTab(index, mode->widget(), mode->icon(), mode->displayName(), + mode->menu() != nullptr); d->m_modeStack->setTabEnabled(index, mode->isEnabled()); // Register mode shortcut