diff --git a/demo/mainwindow.cpp b/demo/mainwindow.cpp index 71171e2..0c436ac 100644 --- a/demo/mainwindow.cpp +++ b/demo/mainwindow.cpp @@ -26,7 +26,7 @@ static ads::CDockWidget* createLongTextLabelDockWidget(QMenu* ViewMenu) QLabel* l = new QLabel(); l->setWordWrap(true); l->setAlignment(Qt::AlignTop | Qt::AlignLeft); - l->setText(QString("Lorem Ipsum ist ein einfacher Demo-Text für die Print- " + l->setText(QString("Label %1 %2 - Lorem Ipsum ist ein einfacher Demo-Text für die Print- " "und Schriftindustrie. Lorem Ipsum ist in der Industrie bereits der " "Standard Demo-Text seit 1500, als ein unbekannter Schriftsteller eine " "Hand voll Wörter nahm und diese durcheinander warf um ein Musterbuch zu " @@ -34,7 +34,9 @@ static ads::CDockWidget* createLongTextLabelDockWidget(QMenu* ViewMenu) "Spruch in die elektronische Schriftbearbeitung geschafft (bemerke, nahezu " "unverändert). Bekannt wurde es 1960, mit dem erscheinen von Letrase, " "welches Passagen von Lorem Ipsum enhielt, so wie Desktop Software wie " - "Aldus PageMaker - ebenfalls mit Lorem Ipsum.")); + "Aldus PageMaker - ebenfalls mit Lorem Ipsum.") + .arg(LabelCount) + .arg(QTime::currentTime().toString("hh:mm:ss:zzz"))); ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Label %1").arg(LabelCount++)); DockWidget->setWidget(l); diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 6eb6a96..728d83c 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -504,6 +504,18 @@ CDockWidget* CDockAreaWidget::currentDockWidget() const } +//============================================================================ +void CDockAreaWidget::setCurrentDockWidget(CDockWidget* DockWidget) +{ + int Index = tabIndex(DockWidget); + if (Index < 0) + { + return; + } + setCurrentIndex(Index); +} + + //============================================================================ void CDockAreaWidget::setCurrentIndex(int index) { @@ -530,6 +542,7 @@ void CDockAreaWidget::setCurrentIndex(int index) if (i == index) { + TitleWidget->show(); TitleWidget->setActiveTab(true); d->TabsScrollArea->ensureWidgetVisible(TitleWidget); auto Features = TitleWidget->dockWidget()->features(); @@ -542,6 +555,7 @@ void CDockAreaWidget::setCurrentIndex(int index) } d->ContentsLayout->setCurrentIndex(index); + d->ContentsLayout->currentWidget()->show(); emit currentChanged(index); } @@ -585,6 +599,22 @@ QList CDockAreaWidget::dockWidgets() const } +//============================================================================ +QList CDockAreaWidget::openDockWidgets() const +{ + QList DockWidgetList; + for (int i = 0; i < d->ContentsLayout->count(); ++i) + { + CDockWidget* DockWidget = dockWidget(i); + if (!DockWidget->isClosed()) + { + DockWidgetList.append(dockWidget(i)); + } + } + return DockWidgetList; +} + + //============================================================================ int CDockAreaWidget::indexOfContentByTitlePos(const QPoint& p, QWidget* exclude) const { @@ -665,6 +695,22 @@ void CDockAreaWidget::updateDockArea() d->updateTabBar(); } + +//============================================================================ +void CDockAreaWidget::hideEvent(QHideEvent* event) +{ + QFrame::hideEvent(event); + emit visibilityChanged(isVisible()); +} + + +//============================================================================ +void CDockAreaWidget::showEvent(QShowEvent* event) +{ + QFrame::showEvent(event); + emit visibilityChanged(isVisible()); +} + } // namespace ads //--------------------------------------------------------------------------- diff --git a/src/DockAreaWidget.h b/src/DockAreaWidget.h index a458ef8..332dc5e 100644 --- a/src/DockAreaWidget.h +++ b/src/DockAreaWidget.h @@ -56,6 +56,10 @@ private slots: void onTabsMenuActionTriggered(QAction* Action); void onCloseButtonClicked(); +protected: + virtual void hideEvent(QHideEvent *) override; + virtual void showEvent(QShowEvent *) override; + public: /** * Default Constructor @@ -120,10 +124,16 @@ public: int indexOfContentByTitlePos(const QPoint& pos, QWidget* exclude = nullptr) const; /** - * Returns a list of all dock widgets in this dock area + * Returns a list of all dock widgets in this dock area. + * This list contains open and closed dock widgets. */ QList dockWidgets() const; + /** + * Returns a list of dock widgets that are not closed + */ + QList openDockWidgets() const; + /** * Returns the number of dock widgets in this area */ @@ -149,6 +159,11 @@ public: */ CDockWidget* currentDockWidget() const; + /** + * Shows the tab with tghe given dock widget + */ + void setCurrentDockWidget(CDockWidget* DockWidget); + public slots: /** * This sets the index position of the current tab page. @@ -172,6 +187,14 @@ signals: * @param index */ void currentChanged(int index); + + /** + * This signal is emitted if a dock areas visibility changed. + * The visibility changes, if the last dock widget in a dock area is closed + * or if one dock widget in a dock area with only closed dock widgets + * becomes visible + */ + void visibilityChanged(bool Visible); }; // class DockAreaWidget } // namespace ads diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 74dca12..8df425d 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -497,6 +497,7 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area) area->setParent(0); if (!(Splitter && Splitter->count() == 1)) { + emit dockAreasRemoved(); return; } @@ -586,6 +587,7 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi } } + } // namespace ads //--------------------------------------------------------------------------- diff --git a/src/DockContainerWidget.h b/src/DockContainerWidget.h index 0943fda..1f93dfe 100644 --- a/src/DockContainerWidget.h +++ b/src/DockContainerWidget.h @@ -52,6 +52,7 @@ class CDockContainerWidget : public QFrame private: DockContainerWidgetPrivate* d; ///< private data (pimpl) friend class DockContainerWidgetPrivate; + protected: /** * Handles activation events to update zOrderIndex diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp index 3ea389a..d15e5d5 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -62,6 +62,7 @@ struct DockWidgetPrivate CDockManager* DockManager = nullptr; CDockAreaWidget* DockArea = nullptr; QAction* ToggleViewAction; + bool Closed = false; struct CapturedState { QString DockTreePosition; @@ -83,6 +84,16 @@ struct DockWidgetPrivate * Show dock widget */ void showDockWidget(); + + /** + * Hides a parent splitter if all dock widgets in the splitter are closed + */ + void hideEmptyParentSplitter(); + + /** + * Hides a dock area if all dock widgets in the area are closed + */ + void hideEmptyParentDockArea(); }; // struct DockWidgetPrivate @@ -131,32 +142,8 @@ void DockWidgetPrivate::capturedState() //============================================================================ void DockWidgetPrivate::showDockWidget() { - /*if (!CapturedState.DockContainer) - { - auto FloatingWidget = new CFloatingDockContainer(_this); - FloatingWidget->setGeometry(CapturedState.GlobalGeometry); - FloatingWidget->show(); - return; - } - - CDockContainerWidget* DockContainer = CapturedState.DockContainer.data(); - QStringList DockTree = this->CapturedState.DockTreePosition.split(' '); - QSplitter* splitter = DockContainer->findChild(QString(), Qt::FindDirectChildrenOnly); - - while (splitter) - { - - } - - for (const auto& TreeItem : DockTree) - { - - }*/ - - std::cout << "DockWidgetPrivate::showDockWidget()" << std::endl; - _this->show(); DockArea->show(); - + DockArea->setCurrentIndex(DockArea->tabIndex(_this)); QSplitter* Splitter = internal::findParent(_this); if (Splitter) { @@ -165,6 +152,53 @@ void DockWidgetPrivate::showDockWidget() } +//============================================================================ +void DockWidgetPrivate::hideEmptyParentSplitter() +{ + QSplitter* Splitter = internal::findParent(_this); + if (!Splitter) + { + return; + } + + for (int i = 0; i < Splitter->count(); ++i) + { + if (Splitter->widget(i)->isVisible()) + { + return; + } + } + + Splitter->hide(); +} + + +//============================================================================ +void DockWidgetPrivate::hideEmptyParentDockArea() +{ + auto OpenDockWidgets = DockArea->openDockWidgets(); + if (OpenDockWidgets.count() > 1) + { + CDockWidget* NextDockWidget; + if (OpenDockWidgets.last() == _this) + { + NextDockWidget = OpenDockWidgets[OpenDockWidgets.count() - 2]; + } + else + { + int NextIndex = OpenDockWidgets.indexOf(_this) + 1; + NextDockWidget = OpenDockWidgets[NextIndex]; + } + + DockArea->setCurrentDockWidget(NextDockWidget); + } + else + { + DockArea->hide(); + } +} + + //============================================================================ CDockWidget::CDockWidget(const QString &title, QWidget *parent) : QFrame(parent), @@ -270,6 +304,13 @@ bool CDockWidget::isFloating() const } +//============================================================================ +bool CDockWidget::isClosed() const +{ + return d->Closed; +} + + //============================================================================ QAction* CDockWidget::toggleViewAction() const { @@ -280,28 +321,15 @@ QAction* CDockWidget::toggleViewAction() const //============================================================================ void CDockWidget::toggleView(bool Open) { - /*if ((d->DockArea != nullptr) == Open) - { - return; - } - - if (!Open && d->DockArea) - { - hideDockWidget(true); - } - else if (Open && !d->DockArea) - { - d->showDockWidget(); - }*/ - if (Open) { d->showDockWidget(); } else { - hideDockWidget(true); + hideDockWidget(); } + d->Closed = !Open; } @@ -315,59 +343,13 @@ void CDockWidget::setDockArea(CDockAreaWidget* DockArea) //============================================================================ -void CDockWidget::hideDockWidget(bool RemoveFromDockArea) +void CDockWidget::hideDockWidget() { - /*d->capturedState(); - if (d->DockArea && RemoveFromDockArea) - { - d->DockArea->removeDockWidget(this); - } - this->setParent(d->DockManager); - this->setDockArea(nullptr); - // Remove title from dock area widget to prevent its deletion if dock - // area is deleted - d->TitleWidget->setParent(this);*/ - - std::cout << "CDockWidget::hideDockWidget" << std::endl; - this->hide(); + CDockAreaWidget* DockArea = d->DockArea; d->ToggleViewAction->setChecked(false); d->TitleWidget->hide(); - CDockAreaWidget* DockArea = d->DockArea; - for (int i = 0; i < DockArea->count(); ++i) - { - if (DockArea->dockWidget(i)->isVisible()) - { - return; - } - } - - if (DockArea->count() > 1) - { - if (DockArea->currentIndex() == (DockArea->count() - 1)) - { - DockArea->setCurrentIndex(DockArea->currentIndex() - 1); - } - else - { - DockArea->setCurrentIndex(DockArea->currentIndex() + 1); - } - } - QSplitter* Splitter = internal::findParent(this); - if (!Splitter) - { - return; - } - - std::cout << "DockWidgets " << Splitter->count() << std::endl; - for (int i = 0; i < Splitter->count(); ++i) - { - if (Splitter->widget(i)->isVisible()) - { - return; - } - } - - Splitter->hide(); + d->hideEmptyParentDockArea(); + d->hideEmptyParentSplitter(); } } // namespace ads diff --git a/src/DockWidget.h b/src/DockWidget.h index 2b5d32f..257b456 100644 --- a/src/DockWidget.h +++ b/src/DockWidget.h @@ -71,10 +71,8 @@ protected: /** * Hide dock widget. - * If RemoveFromDockArea is true, the dock widget will be properly removed - * from dock area. */ - void hideDockWidget(bool RemoveFromDockArea = true); + void hideDockWidget(); public: enum DockWidgetFeature @@ -157,6 +155,11 @@ public: */ bool isFloating() const; + /** + * Returns true, if this dock widget is closed. + */ + bool isClosed() const; + /** * Returns a checkable action that can be used to show or close this dock widget. * The action's text is set to the dock widget's window title. diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp index 2828180..b16b12d 100644 --- a/src/FloatingDockContainer.cpp +++ b/src/FloatingDockContainer.cpp @@ -172,7 +172,7 @@ CFloatingDockContainer::CFloatingDockContainer(CDockManager* DockManager) : QWidget(DockManager, Qt::Window), d(new FloatingDockContainerPrivate(this)) { - setAttribute(Qt::WA_DeleteOnClose); + //setAttribute(Qt::WA_DeleteOnClose); d->DockManager = DockManager; QBoxLayout* l = new QBoxLayout(QBoxLayout::TopToBottom); l->setContentsMargins(0, 0, 0, 0); @@ -210,6 +210,7 @@ CFloatingDockContainer::CFloatingDockContainer(CDockWidget* DockWidget) : //============================================================================ CFloatingDockContainer::~CFloatingDockContainer() { + std::cout << "~CFloatingDockContainer" << std::endl; if (d->DockManager) { d->DockManager->removeFloatingWidget(this); @@ -269,17 +270,21 @@ void CFloatingDockContainer::closeEvent(QCloseEvent *event) auto DockWidgets = dockContainer()->dockArea(i)->dockWidgets(); for (auto DockWidget : DockWidgets) { - DockWidget->hideDockWidget(false); + DockWidget->hideDockWidget(); } } QWidget::closeEvent(event); } else { - std::cout << "Closing single tab" << std::endl; - event->ignore(); auto DockArea = dockContainer()->dockArea(0); - DockArea->currentDockWidget()->hideDockWidget(true); + DockArea->currentDockWidget()->hideDockWidget(); + // As long as there are open dock widgets, we do not close the floating + // window + if (DockArea->openDockWidgets().count()) + { + event->ignore(); + } } }