Skip to content

Commit f237863

Browse files
studiofugagithubuser0xFFFF
authored andcommitted
Add ability to customize the DockArea Title Bar and DockWidget Tab context menu
1 parent 509b235 commit f237863

File tree

6 files changed

+110
-32
lines changed

6 files changed

+110
-32
lines changed

demo/MainWindow.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,18 +75,17 @@
7575
#endif
7676
#endif
7777

78-
#include "DockManager.h"
79-
#include "DockWidget.h"
80-
#include "DockAreaWidget.h"
81-
#include "DockAreaTitleBar.h"
8278
#include "DockAreaTabBar.h"
83-
#include "FloatingDockContainer.h"
79+
#include "DockAreaTitleBar.h"
80+
#include "DockAreaWidget.h"
8481
#include "DockComponentsFactory.h"
85-
#include "StatusDialog.h"
82+
#include "DockManager.h"
8683
#include "DockSplitter.h"
84+
#include "DockWidget.h"
85+
#include "FloatingDockContainer.h"
8786
#include "ImageViewer.h"
88-
89-
87+
#include "MyDockAreaTitleBar.h"
88+
#include "StatusDialog.h"
9089

9190
/**
9291
* Returns a random number from 0 to highest - 1
@@ -147,7 +146,7 @@ class CCustomComponentsFactory : public ads::CDockComponentsFactory
147146
using Super = ads::CDockComponentsFactory;
148147
ads::CDockAreaTitleBar* createDockAreaTitleBar(ads::CDockAreaWidget* DockArea) const override
149148
{
150-
auto TitleBar = new ads::CDockAreaTitleBar(DockArea);
149+
auto TitleBar = new MyDockAreaTitleBar(DockArea);
151150
auto CustomButton = new QToolButton(DockArea);
152151
CustomButton->setToolTip(QObject::tr("Help"));
153152
CustomButton->setIcon(svgIcon(":/adsdemo/images/help_outline.svg"));

demo/MyDockAreaTitleBar.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//
2+
// Created by fuga on 08 nov 2024.
3+
//
4+
5+
#ifndef QTADS_MYDOCKAREATITLEBAR_H
6+
#define QTADS_MYDOCKAREATITLEBAR_H
7+
8+
#include <DockAreaTitleBar.h>
9+
10+
class MyDockAreaTitleBar : public ads::CDockAreaTitleBar {
11+
public:
12+
explicit MyDockAreaTitleBar(ads::CDockAreaWidget* parent)
13+
: CDockAreaTitleBar(parent)
14+
{}
15+
16+
QMenu* buildContextMenu(QMenu*) override
17+
{
18+
auto menu = ads::CDockAreaTitleBar::buildContextMenu(nullptr);
19+
menu->addSeparator();
20+
auto action = menu->addAction(tr("Format HardDrive"));
21+
22+
connect(action, &QAction::triggered, this, [this](){
23+
QMessageBox msgBox;
24+
msgBox.setText("No, just kidding");
25+
msgBox.setStandardButtons(QMessageBox::Abort);
26+
msgBox.setDefaultButton(QMessageBox::Abort);
27+
msgBox.exec();
28+
});
29+
30+
return menu;
31+
}
32+
};
33+
34+
#endif // QTADS_MYDOCKAREATITLEBAR_H

src/DockAreaTitleBar.cpp

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -765,53 +765,63 @@ void CDockAreaTitleBar::contextMenuEvent(QContextMenuEvent* ev)
765765
return;
766766
}
767767

768-
const bool isAutoHide = d->DockArea->isAutoHide();
768+
auto Menu = buildContextMenu(nullptr);
769+
Menu->exec(ev->globalPos());
770+
delete Menu;
771+
}
772+
773+
QMenu* CDockAreaTitleBar::buildContextMenu(QMenu *Menu)
774+
{
775+
const bool isAutoHide = d->DockArea->isAutoHide();
769776
const bool isTopLevelArea = d->DockArea->isTopLevelArea();
770777
QAction* Action;
771-
QMenu Menu(this);
772-
if (!isTopLevelArea)
778+
if (Menu == nullptr)
779+
{
780+
Menu = new QMenu(this);
781+
}
782+
783+
if (!isTopLevelArea)
773784
{
774-
Action = Menu.addAction(isAutoHide ? tr("Detach") : tr("Detach Group"),
785+
Action = Menu->addAction(isAutoHide ? tr("Detach") : tr("Detach Group"),
775786
this, SLOT(onUndockButtonClicked()));
776787
Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable));
777788
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
778789
{
779-
Action = Menu.addAction(isAutoHide ? tr("Unpin (Dock)") : tr("Pin Group"), this, SLOT(onAutoHideDockAreaActionClicked()));
790+
Action = Menu->addAction(isAutoHide ? tr("Unpin (Dock)") : tr("Pin Group"), this, SLOT(onAutoHideDockAreaActionClicked()));
780791
auto AreaIsPinnable = d->DockArea->features().testFlag(CDockWidget::DockWidgetPinnable);
781792
Action->setEnabled(AreaIsPinnable);
782793

783794
if (!isAutoHide)
784795
{
785-
auto menu = Menu.addMenu(tr("Pin Group To..."));
796+
auto menu = Menu->addMenu(tr("Pin Group To..."));
786797
menu->setEnabled(AreaIsPinnable);
787798
d->createAutoHideToAction(tr("Top"), SideBarTop, menu);
788799
d->createAutoHideToAction(tr("Left"), SideBarLeft, menu);
789800
d->createAutoHideToAction(tr("Right"), SideBarRight, menu);
790801
d->createAutoHideToAction(tr("Bottom"), SideBarBottom, menu);
791802
}
792803
}
793-
Menu.addSeparator();
804+
Menu->addSeparator();
794805
}
795806

796807
if (isAutoHide)
797808
{
798-
Action = Menu.addAction(tr("Minimize"), this, SLOT(minimizeAutoHideContainer()));
799-
Action = Menu.addAction(tr("Close"), this, SLOT(onAutoHideCloseActionTriggered()));
809+
Action = Menu->addAction(tr("Minimize"), this, SLOT(minimizeAutoHideContainer()));
810+
Action = Menu->addAction(tr("Close"), this, SLOT(onAutoHideCloseActionTriggered()));
800811
}
801812
else
802813
{
803-
Action = Menu.addAction(isAutoHide ? tr("Close") : tr("Close Group"), this, SLOT(onCloseButtonClicked()));
814+
Action = Menu->addAction(isAutoHide ? tr("Close") : tr("Close Group"), this, SLOT(onCloseButtonClicked()));
804815
}
805816

806817
Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetClosable));
807818
if (!isAutoHide && !isTopLevelArea)
808819
{
809-
Action = Menu.addAction(tr("Close Other Groups"), d->DockArea, SLOT(closeOtherAreas()));
820+
Action = Menu->addAction(tr("Close Other Groups"), d->DockArea, SLOT(closeOtherAreas()));
810821
}
811-
Menu.exec(ev->globalPos());
822+
return Menu;
812823
}
813824

814-
815825
//============================================================================
816826
void CDockAreaTitleBar::insertWidget(int index, QWidget *widget)
817827
{

src/DockAreaTitleBar.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,20 @@ public Q_SLOTS:
249249
*/
250250
bool isAutoHide() const;
251251

252+
/**
253+
* Fills the provided menu with standard entries. If a nullptr is passed, a
254+
* new menu is created and filled with standard entries.
255+
* This function is called from the actual version of contextMenuEvent, but
256+
* can be called from any code. Caller is responsible of deleting the created
257+
* object.
258+
*
259+
* @param menu The QMenu to fill with standard entries. If nullptr, a new
260+
* QMenu will be created.
261+
* @return The filled QMenu, either the provided one or a newly created one if
262+
* nullptr was passed.
263+
*/
264+
virtual QMenu *buildContextMenu(QMenu *);
265+
252266
Q_SIGNALS:
253267
/**
254268
* This signal is emitted if a tab in the tab bar is clicked by the user

src/DockWidgetTab.cpp

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -529,26 +529,34 @@ void CDockWidgetTab::contextMenuEvent(QContextMenuEvent* ev)
529529
return;
530530
}
531531

532+
auto Menu = buildContextMenu(nullptr);
532533
d->saveDragStartMousePosition(ev->globalPos());
534+
Menu->exec(ev->globalPos());
535+
}
533536

537+
QMenu* CDockWidgetTab::buildContextMenu(QMenu *Menu)
538+
{
539+
if (Menu == nullptr) {
540+
Menu = new QMenu(this);
541+
}
542+
534543
const bool isFloatable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable);
535544
const bool isNotOnlyTabInContainer = !d->DockArea->dockContainer()->hasTopLevelDockWidget();
536545
const bool isTopLevelArea = d->DockArea->isTopLevelArea();
537546
const bool isDetachable = isFloatable && isNotOnlyTabInContainer;
538547
QAction* Action;
539-
QMenu Menu(this);
540548

541549
if (!isTopLevelArea)
542550
{
543-
Action = Menu.addAction(tr("Detach"), this, SLOT(detachDockWidget()));
551+
Action = Menu->addAction(tr("Detach"), this, SLOT(detachDockWidget()));
544552
Action->setEnabled(isDetachable);
545553
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
546554
{
547-
Action = Menu.addAction(tr("Pin"), this, SLOT(autoHideDockWidget()));
555+
Action = Menu->addAction(tr("Pin"), this, SLOT(autoHideDockWidget()));
548556
auto IsPinnable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetPinnable);
549557
Action->setEnabled(IsPinnable);
550558

551-
auto menu = Menu.addMenu(tr("Pin To..."));
559+
auto menu = Menu->addMenu(tr("Pin To..."));
552560
menu->setEnabled(IsPinnable);
553561
d->createAutoHideToAction(tr("Top"), SideBarTop, menu);
554562
d->createAutoHideToAction(tr("Left"), SideBarLeft, menu);
@@ -557,17 +565,16 @@ void CDockWidgetTab::contextMenuEvent(QContextMenuEvent* ev)
557565
}
558566
}
559567

560-
Menu.addSeparator();
561-
Action = Menu.addAction(tr("Close"), this, SIGNAL(closeRequested()));
568+
Menu->addSeparator();
569+
Action = Menu->addAction(tr("Close"), this, SIGNAL(closeRequested()));
562570
Action->setEnabled(isClosable());
563571
if (d->DockArea->openDockWidgetsCount() > 1)
564572
{
565-
Action = Menu.addAction(tr("Close Others"), this, SIGNAL(closeOtherTabsRequested()));
573+
Action = Menu->addAction(tr("Close Others"), this, SIGNAL(closeOtherTabsRequested()));
566574
}
567-
Menu.exec(ev->globalPos());
568-
}
569-
570575

576+
return Menu;
577+
}
571578
//============================================================================
572579
bool CDockWidgetTab::isActiveTab() const
573580
{

src/DockWidgetTab.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,20 @@ private Q_SLOTS:
186186
*/
187187
eDragState dragState() const;
188188

189+
/**
190+
* Fills the provided menu with standard entries. If a nullptr is passed, a
191+
* new menu is created and filled with standard entries.
192+
* This function is called from the actual version of contextMenuEvent, but
193+
* can be called from any code. Caller is responsible of deleting the created
194+
* object.
195+
*
196+
* @param menu The QMenu to fill with standard entries. If nullptr, a new
197+
* QMenu will be created.
198+
* @return The filled QMenu, either the provided one or a newly created one if
199+
* nullptr was passed.
200+
*/
201+
virtual QMenu *buildContextMenu(QMenu *);
202+
189203
public Q_SLOTS:
190204
virtual void setVisible(bool visible) override;
191205

0 commit comments

Comments
 (0)