25#include <QApplication>
30TitleBarButton::TitleBarButton(
bool showInTitleBar,
bool hideWhenDisabled,
Qx::DockTitleBarButton id, QWidget *parent)
33 , m_showInTitleBar(showInTitleBar)
34 , m_hideWhenDisabled(
DockManager::testConfigFlag(
DockManager::DockAreaHideDisabledButtons) && hideWhenDisabled)
36 setFocusPolicy(Qt::NoFocus);
49 return qobject_cast<DockTitleBar *>(parentWidget());
69 visible = isEnabled();
72 Super::setVisible(visible);
81 return Super::event(e);
100 QMetaObject::invokeMethod(
this,
"setVisible", Qt::QueuedConnection,
101 Q_ARG(
bool, isEnabledTo(this->parentWidget()) & show));
103 return Super::event(e);
109 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
110 setStyleSheet(
"border: none; background: none;");
113class DockTitleBarPrivate
118 DockTitleBarPrivate();
122 void createButtons();
123 void createAutoHideTitleLabel();
128 void startFloating(
const QPoint &offset);
133 QAction *createAutoHideToAction(
const QString &title,
Qx::DockSideBarArea area, QMenu *menu);
136 QBoxLayout *m_layout =
nullptr;
139 QPointer<TitleBarButton> m_tabsMenuButton;
140 QPointer<TitleBarButton> m_undockButton;
141 QPointer<TitleBarButton> m_closeButton;
142 QPointer<TitleBarButton> m_autoHideButton;
143 QPointer<TitleBarButton> m_minimizeButton;
145 QList<TitleBarButton *> m_dockWidgetActionsButtons;
146 bool m_menuOutdated =
true;
149 QPoint m_dragStartMousePos;
151 DockLabel *m_autoHideTitleLabel =
nullptr;
154DockTitleBarPrivate::DockTitleBarPrivate()
158void DockTitleBarPrivate::init()
162 m_layout =
new QBoxLayout(QBoxLayout::LeftToRight);
163 m_layout->setContentsMargins(0, 0, 0, 0);
164 m_layout->setSpacing(0);
165 q->setLayout(m_layout);
169 createAutoHideTitleLabel();
172void DockTitleBarPrivate::createTabBar()
175 m_tabBar =
new DockTabBar(m_panel);
178 m_tabBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
179 m_layout->addWidget(m_tabBar);
180 q->connect(m_tabBar, SIGNAL(tabClosed(
int)), SLOT(markTabsMenuOutdated()));
181 q->connect(m_tabBar, SIGNAL(tabOpened(
int)), SLOT(markTabsMenuOutdated()));
182 q->connect(m_tabBar, SIGNAL(tabInserted(
int)), SLOT(markTabsMenuOutdated()));
183 q->connect(m_tabBar, SIGNAL(tabMoved(
int,
int)), SLOT(markTabsMenuOutdated()));
184 q->connect(m_tabBar, SIGNAL(removingTab(
int)), SLOT(markTabsMenuOutdated()));
185 q->connect(m_tabBar, SIGNAL(currentChanged(
int)), SLOT(onCurrentTabChanged(
int)));
186 q->connect(m_tabBar, SIGNAL(tabBarClicked(
int)), SIGNAL(tabBarClicked(
int)));
187 q->connect(m_tabBar, SIGNAL(elidedChanged(
bool)), SLOT(markTabsMenuOutdated()));
190void DockTitleBarPrivate::createButtons()
194 QSizePolicy sp(QSizePolicy::Fixed, QSizePolicy::Expanding);
199 m_tabsMenuButton->setObjectName(
"dockTabsMenuButton");
200 m_tabsMenuButton->setAutoRaise(
true);
201 m_tabsMenuButton->setPopupMode(QToolButton::InstantPopup);
203 QMenu *tabsMenu =
new QMenu(m_tabsMenuButton);
205 tabsMenu->setToolTipsVisible(
true);
207 q->connect(tabsMenu, SIGNAL(aboutToShow()), SLOT(onTabsMenuAboutToShow()));
208 q->connect(tabsMenu, SIGNAL(triggered(QAction *)), SLOT(onTabsMenuActionTriggered(QAction *)));
209 m_tabsMenuButton->setMenu(tabsMenu);
211 m_tabsMenuButton->setSizePolicy(sp);
212 m_layout->addWidget(m_tabsMenuButton, 0);
217 m_undockButton->setObjectName(
"dockDetachGroupButton");
218 m_undockButton->setAutoRaise(
true);
221 m_undockButton->setSizePolicy(sp);
222 m_layout->addWidget(m_undockButton, 0);
223 q->connect(m_undockButton, SIGNAL(clicked()), SLOT(onUndockButtonClicked()));
230 m_autoHideButton->setObjectName(
"dockPanelAutoHideButton");
231 m_autoHideButton->setAutoRaise(
true);
234 m_autoHideButton->setSizePolicy(sp);
236 m_autoHideButton->setChecked(
false);
237 m_layout->addWidget(m_autoHideButton, 0);
238 q->connect(m_autoHideButton, SIGNAL(clicked()), SLOT(onAutoHideButtonClicked()));
243 m_minimizeButton->setObjectName(
"dockPanelMinimizeButton");
244 m_minimizeButton->setAutoRaise(
true);
245 m_minimizeButton->setVisible(
false);
248 m_minimizeButton->setSizePolicy(sp);
249 m_layout->addWidget(m_minimizeButton, 0);
250 q->connect(m_minimizeButton, SIGNAL(clicked()), SLOT(minimizeAutoHideContainer()));
255 m_closeButton->setObjectName(
"dockPanelCloseButton");
256 m_closeButton->setAutoRaise(
true);
259 m_closeButton->setSizePolicy(sp);
260 m_closeButton->setIconSize(QSize(16, 16));
261 m_layout->addWidget(m_closeButton, 0);
262 q->connect(m_closeButton, SIGNAL(clicked()), SLOT(onCloseButtonClicked()));
265void DockTitleBarPrivate::createAutoHideTitleLabel()
268 m_autoHideTitleLabel =
new DockLabel(
"");
269 m_autoHideTitleLabel->setObjectName(
"dockAutoHideTitleLabel");
271 m_layout->insertWidget(1, m_autoHideTitleLabel);
272 m_autoHideTitleLabel->setVisible(
false);
273 m_layout->insertWidget(2,
new SpacerWidget(q));
276DockWindow *DockTitleBarPrivate::dockWindow()
const
278 return m_panel->dockWindow();
283 return m_dragState == dragState;
286void DockTitleBarPrivate::startFloating(
const QPoint &offset)
288 if (m_panel->autoHideContainer()) {
289 m_panel->autoHideContainer()->hide();
298DockFloatingWidget *DockTitleBarPrivate::makeAreaFloating(
const QPoint &offset,
Qx::DockDragState dragState)
300 QSize sz = m_panel->size();
301 m_dragState = dragState;
303 DockFloatingContainer *floatingContainer =
nullptr;
304 DockFloatingWidget *floatingWidget;
305 if (needCreateFloatingContainer) {
306 if (m_panel->autoHideContainer()) {
308 m_panel->autoHideContainer()->cleanupAndDelete();
310 floatingWidget = floatingContainer =
new DockFloatingContainer(m_panel);
312 auto w =
new DockFloatingPreview(m_panel);
318 floatingWidget->startFloating(offset, sz, dragState,
nullptr);
319 if (floatingContainer) {
320 auto topLevelWidget = floatingContainer->topLevelDockWidget();
321 if (topLevelWidget) {
322 topLevelWidget->emitTopLevelChanged(
true);
325 return floatingWidget;
342QAction *DockTitleBarPrivate::createAutoHideToAction(
const QString &title,
Qx::DockSideBarArea area, QMenu *menu)
345 auto action = menu->addAction(title);
346 action->setProperty(internal::LocationProperty, area);
359 setObjectName(
"dockTitleBar");
360 setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
361 setFocusPolicy(Qt::NoFocus);
387 return d->m_tabsMenuButton;
389 return d->m_undockButton;
391 return d->m_closeButton;
393 return d->m_autoHideButton;
395 return d->m_minimizeButton;
407 return d->m_autoHideTitleLabel;
416 d->m_tabBar->setVisible(!show);
417 d->m_minimizeButton->setVisible(show);
418 d->m_autoHideTitleLabel->setVisible(show);
427 auto tab = d->m_tabBar->currentTab();
433 if (!d->m_dockWidgetActionsButtons.isEmpty()) {
434 for (
auto b : d->m_dockWidgetActionsButtons) {
435 d->m_layout->removeWidget(b);
438 d->m_dockWidgetActionsButtons.clear();
441 if (actions.isEmpty()) {
444 int insertIndex =
indexOf(d->m_tabsMenuButton);
445 for (
auto a : actions) {
447 btn->setDefaultAction(a);
448 btn->setAutoRaise(
true);
449 btn->setPopupMode(QToolButton::InstantPopup);
450 btn->setObjectName(a->objectName());
451 d->m_layout->insertWidget(insertIndex++, btn, 0);
452 d->m_dockWidgetActionsButtons.append(btn);
462 Super::setVisible(visible);
474 d->m_layout->insertWidget(index, widget);
489 return d->m_layout->indexOf(widget);
501 if (d->m_panel->isAutoHide()) {
502 return tr(
"Unpin (Dock)");
506 return tr(
"Pin Group");
508 return tr(
"Pin Active Tab (Press Ctrl to Pin Group)");
513 if (d->m_panel->isAutoHide()) {
515 return minimize ? tr(
"Minimize") : tr(
"Close");
519 return tr(
"Close Active Tab");
521 return tr(
"Close Group");
534 return d->m_panel && d->m_panel->isAutoHide();
546 auto container = d->m_panel->dockContainer();
547 if (container->isFloating() && container->dockPanelCount() == 1 && !d->m_panel->isAutoHide()) {
566 bool tabsMenuButtonVisible =
false;
568 tabsMenuButtonVisible = d->m_tabBar->areTabsOverflowing();
570 bool hasElidedTabTitle =
false;
571 for (
int i = 0; i < d->m_tabBar->count(); ++i) {
572 if (!d->m_tabBar->isTabOpen(i)) {
575 DockTab *tab = d->m_tabBar->tab(i);
577 hasElidedTabTitle =
true;
581 tabsMenuButtonVisible = (hasElidedTabTitle && (d->m_tabBar->count() > 1));
583 QMetaObject::invokeMethod(d->m_tabsMenuButton,
"setVisible", Qt::QueuedConnection,
584 Q_ARG(
bool, tabsMenuButtonVisible));
586 d->m_menuOutdated =
true;
592 if (!d->m_menuOutdated) {
595 QMenu *menu = d->m_tabsMenuButton->menu();
597 for (
int i = 0; i < d->m_tabBar->count(); ++i) {
598 if (!d->m_tabBar->isTabOpen(i)) {
601 auto tab = d->m_tabBar->tab(i);
602 QAction *action = menu->addAction(tab->icon(), tab->text());
606 d->m_menuOutdated =
false;
612 int index = a->data().toInt();
613 d->m_tabBar->setCurrentIndex(index);
635 d->m_panel->autoHideContainer()) {
636 d->m_panel->autoHideContainer()->collapseView(
true);
638 d->m_tabBar->closeTab(d->m_tabBar->currentIndex());
640 d->m_panel->closeArea();
656 qApp->keyboardModifiers().testFlag(Qt::ControlModifier)) {
657 d->m_panel->toggleAutoHide();
659 d->m_panel->currentDockWidget()->toggleAutoHide();
666 auto autoHideContainer = d->m_panel->autoHideContainer();
667 if (autoHideContainer) {
668 autoHideContainer->collapseView(
true);
675 d->m_panel->toggleAutoHide();
681 int location = sender()->property(internal::LocationProperty).toInt();
688 d->m_panel->closeArea();
694 if (e->button() == Qt::LeftButton) {
696 d->m_dragStartMousePos = e->pos();
699 d->dockWindow()->dockFocusController()->setDockWidgetTabFocused(d->m_tabBar->currentTab());
703 Super::mousePressEvent(e);
709 if (e->button() == Qt::LeftButton) {
711 auto currentDragState = d->m_dragState;
712 d->m_dragStartMousePos = QPoint();
715 d->m_floatingWidget->finishDragging();
720 Super::mouseReleaseEvent(e);
726 Super::mouseMoveEvent(e);
734 d->m_floatingWidget->moveFloating();
740 if (d->m_panel->dockContainer()->isFloating() && d->m_panel->dockContainer()->visibleDockPanelCount() == 1 &&
741 !d->m_panel->isAutoHide()) {
748 auto features = d->m_panel->features();
753 int dragDistance = (d->m_dragStartMousePos - e->pos()).manhattanLength();
756 d->startFloating(d->m_dragStartMousePos);
757 auto overlay = d->m_panel->dockWindow()->containerOverlay();
769 if (d->m_panel->dockContainer()->isFloating() && d->m_panel->dockContainer()->dockPanelCount() == 1) {
788 const bool isAutoHide = d->m_panel->isAutoHide();
789 const bool isTopLevelArea = d->m_panel->isTopLevelArea();
792 if (!isTopLevelArea) {
796 action = menu.addAction(
isAutoHide ? tr(
"Unpin (Dock)") : tr(
"Pin Group"),
this,
799 action->setEnabled(areaIsPinnable);
802 auto pinMenu = menu.addMenu(tr(
"Pin Group To..."));
803 pinMenu->setEnabled(areaIsPinnable);
822 action = menu.addAction(tr(
"Close Other Groups"), d->m_panel, SLOT(closeOtherAreas()));
824 menu.exec(e->globalPos());
829 Super::resizeEvent(e);
The dock manager that maintains the complete docking system.
ConfigFlag
These global configuration flags configure some global dock manager settings.
@ DockAreaHasTabsMenuButton
@ DockAreaDynamicTabsMenuButtonVisibility
@ DockAreaHasUndockButton
@ DockAreaCloseButtonClosesTab
static bool testConfigFlag(ConfigFlag flag)
AutoHideFlag
These global configuration flags configure some dock manager auto hide settings Set the dock manager ...
@ AutoHideHasMinimizeButton
@ DockAreaHasAutoHideButton
@ AutoHideCloseButtonCollapsesDock
@ AutoHideButtonCheckable
@ AutoHideButtonTogglesArea
static bool testAutoHideConfigFlag(AutoHideFlag flag)
static int startDragDistance()
The distance the user needs to move the mouse with the left button hold down before a dock widget sta...
DockPanel manages multiple instances of DockWidgets.
Custom tabbar implementation for tab area that is shown on top of a dock panel widget.
DockWidget * dockWidget() const
bool isTitleElided() const
Title bar of a dock panel.
void tabBarClicked(int index)
void showAutoHideControls(bool show)
Call this function, to create all the required auto hide controls
void insertWidget(int index, QWidget *widget)
Inserts a custom widget at position index into this title bar.
void updateDockWidgetActionsButtons()
Updates the visibility of the dock widget actions in the title bar
void onCurrentTabChanged(int index)
void onTabsMenuActionTriggered(QAction *a)
void minimizeAutoHideContainer()
void onUndockButtonClicked()
virtual void mousePressEvent(QMouseEvent *e) override
void onCloseButtonClicked()
void onAutoHideCloseActionTriggered()
void onAutoHideButtonClicked()
virtual void mouseReleaseEvent(QMouseEvent *e) override
DockPanel * dockPanel() const
void onTabsMenuAboutToShow()
DockTitleBar(DockPanel *parent=nullptr)
QString titleBarButtonToolTip(Qx::DockTitleBarButton id) const
Close group tool tip based on the current state Auto hide widgets can only have one dock widget so it...
void setAreaFloating()
Moves the dock panel into its own floating widget if the area DockWidgetFloatable flag is true
virtual void resizeEvent(QResizeEvent *e) override
void onAutoHideDockAreaActionClicked()
int indexOf(QWidget *widget) const
Searches for widget in this title bar.
virtual void mouseMoveEvent(QMouseEvent *e) override
virtual void contextMenuEvent(QContextMenuEvent *e) override
virtual void mouseDoubleClickEvent(QMouseEvent *e) override
DockTabBar * tabBar() const
void markTabsMenuOutdated()
Call this slot to tell the title bar that it should update the tabs menu the next time it is shown.
DockLabel * autoHideTitleLabel() const
Returns the auto hide title label, used when the dock panel is expanded and auto hidden
void onAutoHideToActionClicked()
virtual void setVisible(bool visible) override
Marks the tabs menu outdated before it calls its base class implementation
QAbstractButton * button(Qx::DockTitleBarButton which) const
The central dock window that maintains the complete docking system.
#define QX_DOCK_PRINT(s)
Copyleft (C) 2024 maminjie canpool@163.com SPDX-License-Identifier: MulanPSL-2.0
void setButtonIcon(QAbstractButton *b, QStyle::StandardPixmap pixmap, Qx::DockIcon iconId)
Helper function to set the icon of a certain button.
const int DockedWidgetDragStartEvent
void setToolTip(QObjectPtr obj, const QString &tip)
@ DockDraggingFloatingWidget
@ DockDraggingMousePressed
#define QX_INIT_PRIVATE(Class)
#define QX_DECLARE_PUBLIC(Class)
#define QX_FINI_PRIVATE()
#define QX_DOCK_END_NAMESPACE
#define QX_DOCK_BEGIN_NAMESPACE