diff --git a/examples/dockwidgets/main.cpp b/examples/dockwidgets/main.cpp index 59ca8f87..125884c1 100644 --- a/examples/dockwidgets/main.cpp +++ b/examples/dockwidgets/main.cpp @@ -120,13 +120,17 @@ int main(int argc, char **argv) parser.addOption(dontCloseBeforeRestore); QCommandLineOption showButtonsInTabBarIfTitleBarHidden("show-buttons-in-tabbar-if-titlebar-hidden", - QCoreApplication::translate("main", "If we're not using title bars we'll still show the close and float button in the tab bar")); + QCoreApplication::translate("main", "If we're not using title bars we'll still show the close and float button in the tab bar")); parser.addOption(showButtonsInTabBarIfTitleBarHidden); QCommandLineOption centralWidget("central-widget", QCoreApplication::translate("main", "The main window will have a non-detachable central widget")); parser.addOption(centralWidget); + QCommandLineOption ctxtMenuOnTabs("allow-switch-tabs-via-menu", + QCoreApplication::translate("main", "Allow switching tabs via context menu in tabs area")); + parser.addOption(ctxtMenuOnTabs); + #if defined(DOCKS_DEVELOPER_MODE) parser.addOption(centralFrame); @@ -237,6 +241,9 @@ int main(int argc, char **argv) if (parser.isSet(tabsHaveCloseButton)) flags |= KDDockWidgets::Config::Flag_TabsHaveCloseButton; + if (parser.isSet(ctxtMenuOnTabs)) + flags |= KDDockWidgets::Config::Flag_AllowSwitchingTabsViaMenu; + if (parser.isSet(doubleClickMaximize)) flags |= KDDockWidgets::Config::Flag_DoubleClickMaximizes; diff --git a/src/Config.h b/src/Config.h index 7ba78b0c..74dfc685 100644 --- a/src/Config.h +++ b/src/Config.h @@ -83,6 +83,7 @@ public: Flag_KeepAboveIfNotUtilityWindow = 0x10000, ///< Only meaningful if Flag_DontUseUtilityFloatingWindows is set. If floating windows are normal windows, you might still want them to keep above and not minimize when you focus the main window. Flag_CloseOnlyCurrentTab = 0x20000, ///< The TitleBar's close button will only close the current tab, instead of all of them Flag_ShowButtonsOnTabBarIfTitleBarHidden = 0x40000, ///< When using Flag_HideTitleBarWhenTabsVisible the close/float buttons disappear with the title bar. With Flag_ShowButtonsOnTabBarIfHidden they'll be shown in the tab bar. + Flag_AllowSwitchingTabsViaMenu = 0x80000, ///< Allow switching tabs via a context menu when right clicking on the tab area Flag_Default = Flag_AeroSnapWithClientDecos ///< The defaults }; Q_DECLARE_FLAGS(Flags, Flag) diff --git a/src/MainWindowBase.cpp b/src/MainWindowBase.cpp index 47c7ba55..7b446416 100644 --- a/src/MainWindowBase.cpp +++ b/src/MainWindowBase.cpp @@ -788,4 +788,4 @@ QWidgetOrQuick *MainWindowBase::persistentCentralWidget() const return dw->widget(); return nullptr; -} \ No newline at end of file +} diff --git a/src/private/widgets/TabWidgetWidget.cpp b/src/private/widgets/TabWidgetWidget.cpp index 938e1150..80970131 100644 --- a/src/private/widgets/TabWidgetWidget.cpp +++ b/src/private/widgets/TabWidgetWidget.cpp @@ -27,6 +27,7 @@ #include #include #include +#include using namespace KDDockWidgets; @@ -38,6 +39,9 @@ TabWidgetWidget::TabWidgetWidget(Frame *parent) setTabBar(static_cast(m_tabBar->asWidget())); setTabsClosable(Config::self().flags() & Config::Flag_TabsHaveCloseButton); + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, &QTabWidget::customContextMenuRequested, this, &TabWidgetWidget::showContextMenu); + // In case tabs closable is set by the factory, a tabClosedRequested() is emitted when the user presses [x] connect(this, &QTabWidget::tabCloseRequested, this, [this](int index) { if (DockWidgetBase *dw = dockwidgetAt(index)) { @@ -201,3 +205,34 @@ void TabWidgetWidget::updateMargins() m_cornerWidgetLayout->setContentsMargins(QMargins(0, 0, 2, 0) * factor); m_cornerWidgetLayout->setSpacing(int(2 * factor)); } + +void TabWidgetWidget::showContextMenu(QPoint pos) +{ + if (!(Config::self().flags() & Config::Flag_AllowSwitchingTabsViaMenu)) + return; + + QTabBar *tabBar = QTabWidget::tabBar(); + // We dont want context menu if there is only one tab + if (tabBar->count() <= 1) + return; + + // Click on a tab => No menu + if (tabBar->tabAt(pos) >= 0) + return; + + // Right click is allowed only on the tabs area + QRect tabAreaRect = tabBar->rect(); + tabAreaRect.setWidth(this->width()); + if (!tabAreaRect.contains(pos)) + return; + + QMenu menu(this); + for (int i = 0; i < tabBar->count(); ++i) { + QAction *action = menu.addAction(tabText(i), this, [this, i] { + setCurrentIndex(i); + }); + if (i == currentIndex()) + action->setDisabled(true); + } + menu.exec(mapToGlobal(pos)); +} diff --git a/src/private/widgets/TabWidgetWidget_p.h b/src/private/widgets/TabWidgetWidget_p.h index 1ebc8314..15a80c59 100644 --- a/src/private/widgets/TabWidgetWidget_p.h +++ b/src/private/widgets/TabWidgetWidget_p.h @@ -65,6 +65,10 @@ protected: DockWidgetBase *dockwidgetAt(int index) const override; int currentIndex() const override; + /// @brief Shows the context menu. Override to implement your own context menu. + /// By default it's used to honour Config::Flag_AllowSwitchingTabsViaMenu + virtual void showContextMenu(QPoint pos); + private: void updateMargins(); void setupTabBarButtons();