Skip to content

Commit

Permalink
Add ability to customize the DockArea Title Bar and DockWidget Tab co…
Browse files Browse the repository at this point in the history
…ntext menu
  • Loading branch information
studiofuga authored and githubuser0xFFFF committed Nov 20, 2024
1 parent 509b235 commit f237863
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 32 deletions.
17 changes: 8 additions & 9 deletions demo/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,17 @@
#endif
#endif

#include "DockManager.h"
#include "DockWidget.h"
#include "DockAreaWidget.h"
#include "DockAreaTitleBar.h"
#include "DockAreaTabBar.h"
#include "FloatingDockContainer.h"
#include "DockAreaTitleBar.h"
#include "DockAreaWidget.h"
#include "DockComponentsFactory.h"
#include "StatusDialog.h"
#include "DockManager.h"
#include "DockSplitter.h"
#include "DockWidget.h"
#include "FloatingDockContainer.h"
#include "ImageViewer.h"


#include "MyDockAreaTitleBar.h"
#include "StatusDialog.h"

/**
* Returns a random number from 0 to highest - 1
Expand Down Expand Up @@ -147,7 +146,7 @@ class CCustomComponentsFactory : public ads::CDockComponentsFactory
using Super = ads::CDockComponentsFactory;
ads::CDockAreaTitleBar* createDockAreaTitleBar(ads::CDockAreaWidget* DockArea) const override
{
auto TitleBar = new ads::CDockAreaTitleBar(DockArea);
auto TitleBar = new MyDockAreaTitleBar(DockArea);
auto CustomButton = new QToolButton(DockArea);
CustomButton->setToolTip(QObject::tr("Help"));
CustomButton->setIcon(svgIcon(":/adsdemo/images/help_outline.svg"));
Expand Down
34 changes: 34 additions & 0 deletions demo/MyDockAreaTitleBar.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// Created by fuga on 08 nov 2024.
//

#ifndef QTADS_MYDOCKAREATITLEBAR_H
#define QTADS_MYDOCKAREATITLEBAR_H

#include <DockAreaTitleBar.h>

class MyDockAreaTitleBar : public ads::CDockAreaTitleBar {
public:
explicit MyDockAreaTitleBar(ads::CDockAreaWidget* parent)
: CDockAreaTitleBar(parent)
{}

QMenu* buildContextMenu(QMenu*) override
{
auto menu = ads::CDockAreaTitleBar::buildContextMenu(nullptr);
menu->addSeparator();
auto action = menu->addAction(tr("Format HardDrive"));

connect(action, &QAction::triggered, this, [this](){
QMessageBox msgBox;
msgBox.setText("No, just kidding");
msgBox.setStandardButtons(QMessageBox::Abort);
msgBox.setDefaultButton(QMessageBox::Abort);
msgBox.exec();
});

return menu;
}
};

#endif // QTADS_MYDOCKAREATITLEBAR_H
36 changes: 23 additions & 13 deletions src/DockAreaTitleBar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -765,53 +765,63 @@ void CDockAreaTitleBar::contextMenuEvent(QContextMenuEvent* ev)
return;
}

const bool isAutoHide = d->DockArea->isAutoHide();
auto Menu = buildContextMenu(nullptr);
Menu->exec(ev->globalPos());
delete Menu;
}

QMenu* CDockAreaTitleBar::buildContextMenu(QMenu *Menu)
{
const bool isAutoHide = d->DockArea->isAutoHide();
const bool isTopLevelArea = d->DockArea->isTopLevelArea();
QAction* Action;
QMenu Menu(this);
if (!isTopLevelArea)
if (Menu == nullptr)
{
Menu = new QMenu(this);
}

if (!isTopLevelArea)
{
Action = Menu.addAction(isAutoHide ? tr("Detach") : tr("Detach Group"),
Action = Menu->addAction(isAutoHide ? tr("Detach") : tr("Detach Group"),
this, SLOT(onUndockButtonClicked()));
Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable));
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
{
Action = Menu.addAction(isAutoHide ? tr("Unpin (Dock)") : tr("Pin Group"), this, SLOT(onAutoHideDockAreaActionClicked()));
Action = Menu->addAction(isAutoHide ? tr("Unpin (Dock)") : tr("Pin Group"), this, SLOT(onAutoHideDockAreaActionClicked()));
auto AreaIsPinnable = d->DockArea->features().testFlag(CDockWidget::DockWidgetPinnable);
Action->setEnabled(AreaIsPinnable);

if (!isAutoHide)
{
auto menu = Menu.addMenu(tr("Pin Group To..."));
auto menu = Menu->addMenu(tr("Pin Group To..."));
menu->setEnabled(AreaIsPinnable);
d->createAutoHideToAction(tr("Top"), SideBarTop, menu);
d->createAutoHideToAction(tr("Left"), SideBarLeft, menu);
d->createAutoHideToAction(tr("Right"), SideBarRight, menu);
d->createAutoHideToAction(tr("Bottom"), SideBarBottom, menu);
}
}
Menu.addSeparator();
Menu->addSeparator();
}

if (isAutoHide)
{
Action = Menu.addAction(tr("Minimize"), this, SLOT(minimizeAutoHideContainer()));
Action = Menu.addAction(tr("Close"), this, SLOT(onAutoHideCloseActionTriggered()));
Action = Menu->addAction(tr("Minimize"), this, SLOT(minimizeAutoHideContainer()));
Action = Menu->addAction(tr("Close"), this, SLOT(onAutoHideCloseActionTriggered()));
}
else
{
Action = Menu.addAction(isAutoHide ? tr("Close") : tr("Close Group"), this, SLOT(onCloseButtonClicked()));
Action = Menu->addAction(isAutoHide ? tr("Close") : tr("Close Group"), this, SLOT(onCloseButtonClicked()));
}

Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetClosable));
if (!isAutoHide && !isTopLevelArea)
{
Action = Menu.addAction(tr("Close Other Groups"), d->DockArea, SLOT(closeOtherAreas()));
Action = Menu->addAction(tr("Close Other Groups"), d->DockArea, SLOT(closeOtherAreas()));
}
Menu.exec(ev->globalPos());
return Menu;
}


//============================================================================
void CDockAreaTitleBar::insertWidget(int index, QWidget *widget)
{
Expand Down
14 changes: 14 additions & 0 deletions src/DockAreaTitleBar.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,20 @@ public Q_SLOTS:
*/
bool isAutoHide() const;

/**
* Fills the provided menu with standard entries. If a nullptr is passed, a
* new menu is created and filled with standard entries.
* This function is called from the actual version of contextMenuEvent, but
* can be called from any code. Caller is responsible of deleting the created
* object.
*
* @param menu The QMenu to fill with standard entries. If nullptr, a new
* QMenu will be created.
* @return The filled QMenu, either the provided one or a newly created one if
* nullptr was passed.
*/
virtual QMenu *buildContextMenu(QMenu *);

Q_SIGNALS:
/**
* This signal is emitted if a tab in the tab bar is clicked by the user
Expand Down
27 changes: 17 additions & 10 deletions src/DockWidgetTab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,26 +529,34 @@ void CDockWidgetTab::contextMenuEvent(QContextMenuEvent* ev)
return;
}

auto Menu = buildContextMenu(nullptr);
d->saveDragStartMousePosition(ev->globalPos());
Menu->exec(ev->globalPos());
}

QMenu* CDockWidgetTab::buildContextMenu(QMenu *Menu)
{
if (Menu == nullptr) {
Menu = new QMenu(this);
}

const bool isFloatable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable);
const bool isNotOnlyTabInContainer = !d->DockArea->dockContainer()->hasTopLevelDockWidget();
const bool isTopLevelArea = d->DockArea->isTopLevelArea();
const bool isDetachable = isFloatable && isNotOnlyTabInContainer;
QAction* Action;
QMenu Menu(this);

if (!isTopLevelArea)
{
Action = Menu.addAction(tr("Detach"), this, SLOT(detachDockWidget()));
Action = Menu->addAction(tr("Detach"), this, SLOT(detachDockWidget()));
Action->setEnabled(isDetachable);
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
{
Action = Menu.addAction(tr("Pin"), this, SLOT(autoHideDockWidget()));
Action = Menu->addAction(tr("Pin"), this, SLOT(autoHideDockWidget()));
auto IsPinnable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetPinnable);
Action->setEnabled(IsPinnable);

auto menu = Menu.addMenu(tr("Pin To..."));
auto menu = Menu->addMenu(tr("Pin To..."));
menu->setEnabled(IsPinnable);
d->createAutoHideToAction(tr("Top"), SideBarTop, menu);
d->createAutoHideToAction(tr("Left"), SideBarLeft, menu);
Expand All @@ -557,17 +565,16 @@ void CDockWidgetTab::contextMenuEvent(QContextMenuEvent* ev)
}
}

Menu.addSeparator();
Action = Menu.addAction(tr("Close"), this, SIGNAL(closeRequested()));
Menu->addSeparator();
Action = Menu->addAction(tr("Close"), this, SIGNAL(closeRequested()));
Action->setEnabled(isClosable());
if (d->DockArea->openDockWidgetsCount() > 1)
{
Action = Menu.addAction(tr("Close Others"), this, SIGNAL(closeOtherTabsRequested()));
Action = Menu->addAction(tr("Close Others"), this, SIGNAL(closeOtherTabsRequested()));
}
Menu.exec(ev->globalPos());
}


return Menu;
}
//============================================================================
bool CDockWidgetTab::isActiveTab() const
{
Expand Down
14 changes: 14 additions & 0 deletions src/DockWidgetTab.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,20 @@ private Q_SLOTS:
*/
eDragState dragState() const;

/**
* Fills the provided menu with standard entries. If a nullptr is passed, a
* new menu is created and filled with standard entries.
* This function is called from the actual version of contextMenuEvent, but
* can be called from any code. Caller is responsible of deleting the created
* object.
*
* @param menu The QMenu to fill with standard entries. If nullptr, a new
* QMenu will be created.
* @return The filled QMenu, either the provided one or a newly created one if
* nullptr was passed.
*/
virtual QMenu *buildContextMenu(QMenu *);

public Q_SLOTS:
virtual void setVisible(bool visible) override;

Expand Down

0 comments on commit f237863

Please sign in to comment.