From 11e5f9c95ac6b8e11d7b0e73cb00a372006c1479 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Fri, 12 Oct 2018 14:51:57 +0200 Subject: [PATCH] Properly implemented DockAreaTitle bar to encapsulate title bar functionality --- src/DockAreaTabBar.cpp | 12 +-- src/DockAreaTitleBar.cpp | 22 +++-- src/DockAreaTitleBar.h | 1 + src/DockAreaWidget.cpp | 186 ++++++--------------------------------- src/DockAreaWidget.h | 12 +-- src/DockOverlay.cpp | 2 +- src/DockWidgetTab.cpp | 4 +- 7 files changed, 53 insertions(+), 186 deletions(-) diff --git a/src/DockAreaTabBar.cpp b/src/DockAreaTabBar.cpp index 1844295..b922fe1 100644 --- a/src/DockAreaTabBar.cpp +++ b/src/DockAreaTabBar.cpp @@ -467,16 +467,12 @@ bool CDockAreaTabBar::eventFilter(QObject *watched, QEvent *event) return Result; } - if (event->type() == QEvent::Hide) - { - return Result; - } - - int TabIndex = d->TabsLayout->indexOf(Tab); switch (event->type()) { - case QEvent::Hide: emit tabClosed(TabIndex); break; - case QEvent::Show: emit tabOpened(TabIndex); break; + case QEvent::Hide: + emit tabClosed(d->TabsLayout->indexOf(Tab)); break; + case QEvent::Show: + emit tabOpened(d->TabsLayout->indexOf(Tab)); break; default: break; } diff --git a/src/DockAreaTitleBar.cpp b/src/DockAreaTitleBar.cpp index 62a89c9..92b4a0e 100644 --- a/src/DockAreaTitleBar.cpp +++ b/src/DockAreaTitleBar.cpp @@ -83,7 +83,7 @@ void DockAreaTitleBarPrivate::createButtons() _this->connect(TabsMenu, SIGNAL(aboutToShow()), SLOT(onTabsMenuAboutToShow())); TabsMenuButton->setMenu(TabsMenu); TopLayout->addWidget(TabsMenuButton, 0); - TabsMenuButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + TabsMenuButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); _this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)), SLOT(onTabsMenuActionTriggered(QAction*))); @@ -92,7 +92,7 @@ void DockAreaTitleBarPrivate::createButtons() CloseButton->setFlat(true); CloseButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarCloseButton)); CloseButton->setToolTip(QObject::tr("Close")); - CloseButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); TopLayout->addWidget(CloseButton, 0); _this->connect(CloseButton, SIGNAL(clicked()), SLOT(onCloseButtonClicked())); } @@ -103,10 +103,12 @@ void DockAreaTitleBarPrivate::createTabBar() { TabBar = new CDockAreaTabBar(DockArea); TopLayout->addWidget(TabBar); - _this->connect(TabBar, SIGNAL(tabClosed()), SLOT(markTabsMenuOutdated())); - _this->connect(TabBar, SIGNAL(tabOpened()), SLOT(markTabsMenuOutdated())); - _this->connect(TabBar, SIGNAL(tabInserted()), SLOT(markTabsMenuOutdated())); - _this->connect(TabBar, SIGNAL(tabRemoved()), SLOT(markTabsMenuOutdated())); + _this->connect(TabBar, SIGNAL(tabClosed(int)), SLOT(markTabsMenuOutdated())); + _this->connect(TabBar, SIGNAL(tabOpened(int)), SLOT(markTabsMenuOutdated())); + _this->connect(TabBar, SIGNAL(tabInserted(int)), SLOT(markTabsMenuOutdated())); + _this->connect(TabBar, SIGNAL(removingTab(int)), SLOT(markTabsMenuOutdated())); + _this->connect(TabBar, SIGNAL(tabMoved(int, int)), SLOT(markTabsMenuOutdated())); + _this->connect(TabBar, SIGNAL(currentChanged(int)), SLOT(onCurrentTabChanged(int))); } @@ -193,6 +195,14 @@ void CDockAreaTitleBar::onTabsMenuActionTriggered(QAction* Action) } +//============================================================================ +void CDockAreaTitleBar::onCurrentTabChanged(int Index) +{ + CDockWidget* DockWidget = d->TabBar->tab(Index)->dockWidget(); + d->CloseButton->setVisible(DockWidget->features().testFlag(CDockWidget::DockWidgetClosable)); +} + + } // namespace ads //--------------------------------------------------------------------------- diff --git a/src/DockAreaTitleBar.h b/src/DockAreaTitleBar.h index 1b15956..cd53cd2 100644 --- a/src/DockAreaTitleBar.h +++ b/src/DockAreaTitleBar.h @@ -33,6 +33,7 @@ private slots: void onTabsMenuAboutToShow(); void onCloseButtonClicked(); void onTabsMenuActionTriggered(QAction* Action); + void onCurrentTabChanged(int Index); public: using Super = QFrame; diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index ef3c52d..97fa5d9 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -52,6 +52,7 @@ #include "DockOverlay.h" #include "DockAreaTabBar.h" #include "DockSplitter.h" +#include "DockAreaTitleBar.h" #include @@ -209,14 +210,9 @@ struct DockAreaWidgetPrivate { CDockAreaWidget* _this; QBoxLayout* Layout; - QFrame* TitleBar; - QBoxLayout* TopLayout; DockAreaLayout* ContentsLayout; - CDockAreaTabBar* TabBar; - QPushButton* TabsMenuButton; - QPushButton* CloseButton; + CDockAreaTitleBar* TitleBar; CDockManager* DockManager = nullptr; - bool MenuOutdated = true; /** * Private data constructor @@ -226,7 +222,7 @@ struct DockAreaWidgetPrivate /** * Creates the layout for top area with tabs and close button */ - void createTabBar(); + void createTitleBar(); /** * Returns the dock widget with the given index @@ -244,13 +240,6 @@ struct DockAreaWidgetPrivate return dockWidgetAt(index)->tabWidget(); } - /** - * Adds a tabs menu entry for the given dock widget - * If menu is 0, a menu entry is added to the menu of the TabsMenuButton - * member. If menu is a valid menu pointer, the entry will be added to - * the given menu - */ - void addTabsMenuEntry(CDockWidget* DockWidget, int Index = -1, QMenu* menu = 0); /** * Returns the tab action of the given dock widget @@ -268,22 +257,19 @@ struct DockAreaWidgetPrivate return DockWidget->property(INDEX_PROPERTY).toInt(); } - /** - * Update the tabs menu if dock widget order changed or if dock widget has - * been removed - */ - void markTabsMenuOutdated(); - - /** - * Updates the tabs menu if it is outdated - */ - void updateTabsMenu(); - /** * Updates the tab bar visibility depending on the number of dock widgets * in this area */ void updateTabBar(); + + /** + * Convenience function for tabbar access + */ + CDockAreaTabBar* tabBar() const + { + return TitleBar->tabBar(); + } }; // struct DockAreaWidgetPrivate @@ -297,43 +283,14 @@ DockAreaWidgetPrivate::DockAreaWidgetPrivate(CDockAreaWidget* _public) : //============================================================================ -void DockAreaWidgetPrivate::createTabBar() +void DockAreaWidgetPrivate::createTitleBar() { - TitleBar = new QFrame(_this); - TitleBar->setObjectName("dockAreaTitleBar"); - TopLayout = new QBoxLayout(QBoxLayout::LeftToRight); - TopLayout->setContentsMargins(0, 0, 0, 0); - TopLayout->setSpacing(0); - TitleBar->setLayout(TopLayout); + TitleBar = new CDockAreaTitleBar(_this); Layout->addWidget(TitleBar); - TitleBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - - TabBar = new CDockAreaTabBar(_this); - TopLayout->addWidget(TabBar, 1); - _this->connect(TabBar, SIGNAL(currentChanged(int)), SLOT(setCurrentIndex(int))); - _this->connect(TabBar, SIGNAL(tabMoved(int, int)), SLOT(reorderDockWidget(int, int))); - - TabsMenuButton = new QPushButton(); - TabsMenuButton->setObjectName("tabsMenuButton"); - TabsMenuButton->setFlat(true); - TabsMenuButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarUnshadeButton)); - TabsMenuButton->setMaximumWidth(TabsMenuButton->iconSize().width()); - QMenu* TabsMenu = new QMenu(TabsMenuButton); - _this->connect(TabsMenu, SIGNAL(aboutToShow()), SLOT(onTabsMenuAboutToShow())); - TabsMenuButton->setMenu(TabsMenu); - TopLayout->addWidget(TabsMenuButton, 0); - TabsMenuButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - _this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)), - SLOT(onTabsMenuActionTriggered(QAction*))); - - CloseButton = new QPushButton(); - CloseButton->setObjectName("closeButton"); - CloseButton->setFlat(true); - CloseButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarCloseButton)); - CloseButton->setToolTip(_this->tr("Close")); - CloseButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - TopLayout->addWidget(CloseButton, 0); - _this->connect(CloseButton, SIGNAL(clicked()), SLOT(onCloseButtonClicked())); + _this->connect(tabBar(), SIGNAL(tabCloseRequested(int)), + SLOT(onTabCloseRequested(int))); + _this->connect(tabBar(), SIGNAL(tabBarClicked(int)), + SLOT(setCurrentIndex(int))); } @@ -350,57 +307,6 @@ void DockAreaWidgetPrivate::updateTabBar() } -//============================================================================ -void DockAreaWidgetPrivate::addTabsMenuEntry(CDockWidget* DockWidget, - int Index, QMenu* menu) -{ - menu = menu ? menu : TabsMenuButton->menu(); - QAction* Action; - if (Index >= 0 && Index < menu->actions().count()) - { - Action = new QAction(DockWidget->icon(), DockWidget->windowTitle()); - menu->insertAction(menu->actions().at(Index), Action); - } - else - { - Action = menu->addAction(DockWidget->icon(), DockWidget->windowTitle()); - } - Action->setProperty(DOCKWIDGET_PROPERTY, QVariant::fromValue(DockWidget)); - QVariant vAction = QVariant::fromValue(Action); - DockWidget->setProperty(ACTION_PROPERTY, vAction); -} - - -//============================================================================ -void DockAreaWidgetPrivate::markTabsMenuOutdated() -{ - MenuOutdated = true; -} - - -//============================================================================ -void DockAreaWidgetPrivate::updateTabsMenu() -{ - if (!MenuOutdated) - { - return; - } - - QMenu* menu = TabsMenuButton->menu(); - menu->clear(); - for (int i = 0; i < ContentsLayout->count(); ++i) - { - if (dockWidgetAt(i)->isClosed()) - { - continue; - } - addTabsMenuEntry(dockWidgetAt(i), APPEND, menu); - } - - MenuOutdated = false; -} - - //============================================================================ CDockAreaWidget::CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent) : QFrame(parent), @@ -412,7 +318,7 @@ CDockAreaWidget::CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget d->Layout->setSpacing(0); setLayout(d->Layout); - d->createTabBar(); + d->createTitleBar(); d->ContentsLayout = new DockAreaLayout(d->Layout); } @@ -453,10 +359,9 @@ void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget, d->ContentsLayout->insertWidget(index, DockWidget); DockWidget->tabWidget()->setDockAreaWidget(this); auto TabWidget = DockWidget->tabWidget(); - d->TabBar->insertTab(index, TabWidget); + d->tabBar()->insertTab(index, TabWidget); TabWidget->setVisible(!DockWidget->isClosed()); DockWidget->setProperty(INDEX_PROPERTY, index); - d->markTabsMenuOutdated(); if (Activate) { setCurrentIndex(index); @@ -474,11 +379,10 @@ void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget) d->ContentsLayout->removeWidget(DockWidget); auto TabWidget = DockWidget->tabWidget(); TabWidget->hide(); - d->TabBar->removeTab(TabWidget); + d->tabBar()->removeTab(TabWidget); if (NextOpenDockWidget) { setCurrentDockWidget(NextOpenDockWidget); - d->markTabsMenuOutdated(); } else if (d->ContentsLayout->isEmpty()) { @@ -541,9 +445,10 @@ void CDockAreaWidget::hideAreaIfNoVisibleContent() //============================================================================ -void CDockAreaWidget::onCloseButtonClicked() +void CDockAreaWidget::onTabCloseRequested(int Index) { - currentDockWidget()->toggleView(false); + qDebug() << "CDockAreaWidget::onTabCloseRequested " << Index; + dockWidget(Index)->toggleView(false); } @@ -576,18 +481,15 @@ void CDockAreaWidget::setCurrentDockWidget(CDockWidget* DockWidget) void CDockAreaWidget::setCurrentIndex(int index) { std::cout << "CDockAreaWidget::setCurrentIndex " << index << std::endl; - if (index < 0 || index > (d->TabBar->count() - 1)) + auto TabBar = d->tabBar(); + if (index < 0 || index > (TabBar->count() - 1)) { qWarning() << Q_FUNC_INFO << "Invalid index" << index; return; } emit currentChanging(index); - d->TabBar->setCurrentIndex(index); - CDockWidgetTab* CurrentTab = d->TabBar->currentTab(); - auto Features = CurrentTab->dockWidget()->features(); - d->CloseButton->setVisible(Features.testFlag(CDockWidget::DockWidgetClosable)); - + TabBar->setCurrentIndex(index); d->ContentsLayout->setCurrentIndex(index); d->ContentsLayout->currentWidget()->show(); emit currentChanged(index); @@ -602,9 +504,9 @@ int CDockAreaWidget::currentIndex() const //============================================================================ -QRect CDockAreaWidget::titleAreaGeometry() const +QRect CDockAreaWidget::titleBarGeometry() const { - return d->TopLayout->geometry(); + return d->TitleBar->geometry(); } //============================================================================ @@ -664,21 +566,6 @@ QList CDockAreaWidget::openedDockWidgets() const } -//============================================================================ -int CDockAreaWidget::indexOfContentByTitlePos(const QPoint& p, QWidget* exclude) const -{ - for (int i = 0; i < d->ContentsLayout->count(); ++i) - { - auto TabWidget = d->tabWidgetAt(i); - if (TabWidget->isVisible() && TabWidget->geometry().contains(p) && (!exclude || TabWidget != exclude)) - { - return i; - } - } - return -1; -} - - //============================================================================ int CDockAreaWidget::dockWidgetsCount() const { @@ -716,16 +603,6 @@ void CDockAreaWidget::toggleDockWidgetView(CDockWidget* DockWidget, bool Open) Q_UNUSED(DockWidget); Q_UNUSED(Open); updateTabBarVisibility(); - d->markTabsMenuOutdated(); -} - - -//============================================================================ -void CDockAreaWidget::onTabsMenuActionTriggered(QAction* Action) -{ - QVariant vDockWidget = Action->property(DOCKWIDGET_PROPERTY); - CDockWidget* DockWidget = vDockWidget.value(); - setCurrentDockWidget(DockWidget); } @@ -777,13 +654,6 @@ CDockWidget* CDockAreaWidget::nextOpenDockWidget(CDockWidget* DockWidget) const } } - -//============================================================================ -void CDockAreaWidget::onTabsMenuAboutToShow() -{ - d->updateTabsMenu(); -} - } // namespace ads //--------------------------------------------------------------------------- diff --git a/src/DockAreaWidget.h b/src/DockAreaWidget.h index 666425c..0e6ae20 100644 --- a/src/DockAreaWidget.h +++ b/src/DockAreaWidget.h @@ -63,9 +63,7 @@ private: friend class CDockWidget; private slots: - void onTabsMenuActionTriggered(QAction* Action); - void onCloseButtonClicked(); - void onTabsMenuAboutToShow(); + void onTabCloseRequested(int Index); /** * Reorder the index position of DockWidget at fromIndx to toIndex @@ -94,12 +92,6 @@ protected: */ void removeDockWidget(CDockWidget* DockWidget); - /** - * Returns the index of contents of the title widget that is located at - * mouse position pos - */ - int indexOfContentByTitlePos(const QPoint& pos, QWidget* exclude = nullptr) const; - /** * Called from dock widget if it is opened or closed */ @@ -161,7 +153,7 @@ public: /** * Returns the rectangle of the title area */ - QRect titleAreaGeometry() const; + QRect titleBarGeometry() const; /** * Returns the rectangle of the content diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index 09c0c08..f1a6ce0 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -346,7 +346,7 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const return Result; } - if (DockArea->titleAreaGeometry().contains(DockArea->mapFromGlobal(QCursor::pos()))) + if (DockArea->titleBarGeometry().contains(DockArea->mapFromGlobal(QCursor::pos()))) { return CenterDockWidgetArea; } diff --git a/src/DockWidgetTab.cpp b/src/DockWidgetTab.cpp index f6f526b..eb1fd23 100644 --- a/src/DockWidgetTab.cpp +++ b/src/DockWidgetTab.cpp @@ -107,7 +107,7 @@ struct DockWidgetTabPrivate */ bool titleAreaGeometryContains(const QPoint& GlobalPos) const { - return DockArea->titleAreaGeometry().contains(DockArea->mapFromGlobal(GlobalPos)); + return DockArea->titleBarGeometry().contains(DockArea->mapFromGlobal(GlobalPos)); } /** @@ -227,7 +227,6 @@ void CDockWidgetTab::mousePressEvent(QMouseEvent* ev) { if (ev->button() == Qt::LeftButton) { - qDebug() << "CDockWidgetTab::mousePressEvent"; ev->accept(); d->DragStartMousePosition = ev->pos(); d->DragState = DraggingMousePressed; @@ -242,7 +241,6 @@ void CDockWidgetTab::mousePressEvent(QMouseEvent* ev) //============================================================================ void CDockWidgetTab::mouseReleaseEvent(QMouseEvent* ev) { - qDebug() << "CDockWidgetTab::mouseReleaseEvent"; // End of tab moving, emit signal if (d->isDraggingState(DraggingTab) && d->DockArea) {