Fixed docking into empty main dock container, fixed tab handling to properly show the right dock widget tab when removing a dock widget, fixed tab menu to only show visible tabs, tab menu is now dynamically created just befor menu is shown

This commit is contained in:
Uwe Kindler 2018-09-07 11:10:14 +02:00
parent 72ee4a53df
commit 67199a81f4
12 changed files with 316 additions and 49 deletions

View File

@ -18,6 +18,7 @@
#include "DockAreaWidget.h" #include "DockAreaWidget.h"
#include "DockOverlay.h" #include "DockOverlay.h"
#include "DockManager.h" #include "DockManager.h"
#include "DockWidget.h"
namespace ads namespace ads
{ {
@ -166,6 +167,10 @@ void CDockAreaTabBar::startFloating(const QPoint& Pos)
CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(d->DockArea); CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(d->DockArea);
FloatingWidget->startFloating(Pos, Size); FloatingWidget->startFloating(Pos, Size);
d->FloatingWidget = FloatingWidget; d->FloatingWidget = FloatingWidget;
if (d->FloatingWidget->hasSingleDockWidget())
{
emit d->FloatingWidget->firstDockWidget()->topLevelChanged(true);
}
} }
} // namespace ads } // namespace ads

View File

@ -41,6 +41,7 @@
#include <QMenu> #include <QMenu>
#include <QSplitter> #include <QSplitter>
#include <QXmlStreamWriter> #include <QXmlStreamWriter>
#include <QVector>
#include "DockContainerWidget.h" #include "DockContainerWidget.h"
@ -50,11 +51,14 @@
#include "DockOverlay.h" #include "DockOverlay.h"
#include "DockAreaTabBar.h" #include "DockAreaTabBar.h"
#include <iostream>
namespace ads namespace ads
{ {
static const char* const INDEX_PROPERTY = "index"; static const char* const INDEX_PROPERTY = "index";
static const char* const ACTION_PROPERTY = "action"; static const char* const ACTION_PROPERTY = "action";
static const char* const DOCKWIDGET_PROPERTY = "dockwidget";
static const int APPEND = -1; static const int APPEND = -1;
@ -75,6 +79,8 @@ struct DockAreaWidgetPrivate
QPushButton* CloseButton; QPushButton* CloseButton;
int TabsLayoutInitCount; int TabsLayoutInitCount;
CDockManager* DockManager = nullptr; CDockManager* DockManager = nullptr;
QVector<CDockWidget*> OpenDockWidgets;
bool MenuOutdated = true;
/** /**
* Private data constructor * Private data constructor
@ -99,7 +105,7 @@ struct DockAreaWidgetPrivate
*/ */
CDockWidgetTab* titleWidgetAt(int index) CDockWidgetTab* titleWidgetAt(int index)
{ {
return dockWidgetAt(index)->titleBar(); return dockWidgetAt(index)->tabWidget();
} }
/** /**
@ -130,6 +136,11 @@ struct DockAreaWidgetPrivate
* Update the tabs menu if dock widget order changed or if dock widget has * Update the tabs menu if dock widget order changed or if dock widget has
* been removed * been removed
*/ */
void markTabsMenuOutdated();
/**
* Updates the tabs menu if it is outdated
*/
void updateTabsMenu(); void updateTabsMenu();
/** /**
@ -178,7 +189,9 @@ void DockAreaWidgetPrivate::createTabBar()
TabsMenuButton->setFlat(true); TabsMenuButton->setFlat(true);
TabsMenuButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarUnshadeButton)); TabsMenuButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarUnshadeButton));
TabsMenuButton->setMaximumWidth(TabsMenuButton->iconSize().width()); TabsMenuButton->setMaximumWidth(TabsMenuButton->iconSize().width());
TabsMenuButton->setMenu(new QMenu(TabsMenuButton)); QMenu* TabsMenu = new QMenu(TabsMenuButton);
_this->connect(TabsMenu, SIGNAL(aboutToShow()), SLOT(onTabsMenuAboutToShow()));
TabsMenuButton->setMenu(TabsMenu);
TopLayout->addWidget(TabsMenuButton, 0); TopLayout->addWidget(TabsMenuButton, 0);
TabsMenuButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); TabsMenuButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
_this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)), _this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)),
@ -232,20 +245,39 @@ void DockAreaWidgetPrivate::addTabsMenuEntry(CDockWidget* DockWidget,
{ {
Action = menu->addAction(DockWidget->icon(), DockWidget->windowTitle()); Action = menu->addAction(DockWidget->icon(), DockWidget->windowTitle());
} }
Action->setProperty(DOCKWIDGET_PROPERTY, QVariant::fromValue(DockWidget));
QVariant vAction = QVariant::fromValue(Action); QVariant vAction = QVariant::fromValue(Action);
DockWidget->setProperty(ACTION_PROPERTY, vAction); DockWidget->setProperty(ACTION_PROPERTY, vAction);
} }
//============================================================================
void DockAreaWidgetPrivate::markTabsMenuOutdated()
{
MenuOutdated = true;
}
//============================================================================ //============================================================================
void DockAreaWidgetPrivate::updateTabsMenu() void DockAreaWidgetPrivate::updateTabsMenu()
{ {
if (!MenuOutdated)
{
return;
}
QMenu* menu = TabsMenuButton->menu(); QMenu* menu = TabsMenuButton->menu();
menu->clear(); menu->clear();
for (int i = 0; i < ContentsLayout->count(); ++i) for (int i = 0; i < ContentsLayout->count(); ++i)
{ {
if (dockWidgetAt(i)->isClosed())
{
continue;
}
addTabsMenuEntry(dockWidgetAt(i), APPEND, menu); addTabsMenuEntry(dockWidgetAt(i), APPEND, menu);
} }
MenuOutdated = false;
} }
@ -313,17 +345,16 @@ void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget,
bool Activate) bool Activate)
{ {
d->ContentsLayout->insertWidget(index, DockWidget); d->ContentsLayout->insertWidget(index, DockWidget);
DockWidget->titleBar()->setDockAreaWidget(this); DockWidget->tabWidget()->setDockAreaWidget(this);
auto TitleBar = DockWidget->titleBar(); auto TabWidget = DockWidget->tabWidget();
d->TabsLayout->insertWidget(index, TitleBar); d->TabsLayout->insertWidget(index, TabWidget);
TitleBar->show(); TabWidget->show();
connect(TitleBar, SIGNAL(clicked()), this, SLOT(onDockWidgetTitleClicked())); connect(TabWidget, SIGNAL(clicked()), this, SLOT(onDockWidgetTitleClicked()));
DockWidget->setProperty(INDEX_PROPERTY, index); DockWidget->setProperty(INDEX_PROPERTY, index);
if (Activate) if (Activate)
{ {
setCurrentIndex(index); setCurrentIndex(index);
} }
d->addTabsMenuEntry(DockWidget, index);
DockWidget->setDockArea(this); DockWidget->setDockArea(this);
} }
@ -332,13 +363,18 @@ void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget,
void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget) void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
{ {
qDebug() << "CDockAreaWidget::removeDockWidget"; qDebug() << "CDockAreaWidget::removeDockWidget";
auto NextDockWidget = nextOpenDockWidget(DockWidget);
d->ContentsLayout->removeWidget(DockWidget); d->ContentsLayout->removeWidget(DockWidget);
auto TitleBar = DockWidget->titleBar(); auto TitleBar = DockWidget->tabWidget();
TitleBar->hide(); TitleBar->hide();
d->TabsLayout->removeWidget(TitleBar); d->TabsLayout->removeWidget(TitleBar);
disconnect(TitleBar, SIGNAL(clicked()), this, SLOT(onDockWidgetTitleClicked())); disconnect(TitleBar, SIGNAL(clicked()), this, SLOT(onDockWidgetTitleClicked()));
setCurrentIndex(d->ContentsLayout->currentIndex()); if (NextDockWidget)
d->updateTabsMenu(); {
setCurrentDockWidget(NextDockWidget);
d->markTabsMenuOutdated();
}
CDockContainerWidget* DockContainer = dockContainer(); CDockContainerWidget* DockContainer = dockContainer();
if (d->ContentsLayout->isEmpty()) if (d->ContentsLayout->isEmpty())
@ -550,7 +586,6 @@ void CDockAreaWidget::reorderDockWidget(int fromIndex, int toIndex)
Menu->insertAction(Menu->actions().at(toIndex), TabsAction); Menu->insertAction(Menu->actions().at(toIndex), TabsAction);
} }
// now reorder contents and title bars // now reorder contents and title bars
QLayoutItem* liFrom = nullptr; QLayoutItem* liFrom = nullptr;
liFrom = d->TabsLayout->takeAt(fromIndex); liFrom = d->TabsLayout->takeAt(fromIndex);
@ -561,11 +596,21 @@ void CDockAreaWidget::reorderDockWidget(int fromIndex, int toIndex)
} }
//============================================================================
void CDockAreaWidget::toggleDockWidgetView(CDockWidget* DockWidget, bool Open)
{
Q_UNUSED(DockWidget);
Q_UNUSED(Open);
d->markTabsMenuOutdated();
}
//============================================================================ //============================================================================
void CDockAreaWidget::onTabsMenuActionTriggered(QAction* Action) void CDockAreaWidget::onTabsMenuActionTriggered(QAction* Action)
{ {
int Index = d->TabsMenuButton->menu()->actions().indexOf(Action); QVariant vDockWidget = Action->property(DOCKWIDGET_PROPERTY);
setCurrentIndex(Index); CDockWidget* DockWidget = vDockWidget.value<CDockWidget*>();
setCurrentDockWidget(DockWidget);
} }
@ -591,6 +636,40 @@ void CDockAreaWidget::saveState(QXmlStreamWriter& s) const
s.writeEndElement(); s.writeEndElement();
} }
//============================================================================
CDockWidget* CDockAreaWidget::nextOpenDockWidget(CDockWidget* DockWidget) const
{
auto OpenDockWidgets = openedDockWidgets();
if (OpenDockWidgets.count() > 1)
{
CDockWidget* NextDockWidget;
if (OpenDockWidgets.last() == DockWidget)
{
NextDockWidget = OpenDockWidgets[OpenDockWidgets.count() - 2];
}
else
{
int NextIndex = OpenDockWidgets.indexOf(DockWidget) + 1;
NextDockWidget = OpenDockWidgets[NextIndex];
}
return NextDockWidget;
}
else
{
return nullptr;
}
}
//============================================================================
void CDockAreaWidget::onTabsMenuAboutToShow()
{
std::cout << "CDockAreaWidget::onTabsMenuAboutToShow()" << std::endl;
d->updateTabsMenu();
}
} // namespace ads } // namespace ads
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@ -59,11 +59,14 @@ private:
friend class CDockContainerWidget; friend class CDockContainerWidget;
friend class DockContainerWidgetPrivate; friend class DockContainerWidgetPrivate;
friend class CDockWidgetTab; friend class CDockWidgetTab;
friend struct DockWidgetPrivate;
friend class CDockWidget;
private slots: private slots:
void onDockWidgetTitleClicked(); void onDockWidgetTitleClicked();
void onTabsMenuActionTriggered(QAction* Action); void onTabsMenuActionTriggered(QAction* Action);
void onCloseButtonClicked(); void onCloseButtonClicked();
void onTabsMenuAboutToShow();
protected: protected:
/** /**
@ -97,6 +100,18 @@ protected:
*/ */
void reorderDockWidget(int fromIndex, int toIndex); void reorderDockWidget(int fromIndex, int toIndex);
/**
* Called from dock widget if it is opened or closed
*/
void toggleDockWidgetView(CDockWidget* DockWidget, bool Open);
/**
* This is a helper function to get the next open dock widget to activate
* if the given DockWidget will be closed or removed.
* The function returns the next widget that should be activated or
* nullptr in case there are no more open widgets in this area.
*/
CDockWidget* nextOpenDockWidget(CDockWidget* DockWidget) const;
public: public:
/** /**
@ -178,7 +193,9 @@ public:
public slots: public slots:
/** /**
* This sets the index position of the current tab page. * This activates the tab for the given tab index.
* If the dock widget for the given tab is not visible, the this function
* call will make it visible.
*/ */
void setCurrentIndex(int index); void setCurrentIndex(int index);

View File

@ -54,6 +54,26 @@ namespace ads
{ {
static unsigned int zOrderCounter = 0; static unsigned int zOrderCounter = 0;
/**
* Converts dock area ID to an index for array access
*/
static int areaIdToIndex(DockWidgetArea area)
{
switch (area)
{
case LeftDockWidgetArea: return 0;
case RightDockWidgetArea: return 1;
case TopDockWidgetArea: return 2;
case BottomDockWidgetArea: return 3;
case CenterDockWidgetArea: return 4;
default:
return 4;
}
return 4;
}
/** /**
* Helper function to ease insertion of dock area into splitter * Helper function to ease insertion of dock area into splitter
*/ */
@ -81,6 +101,7 @@ struct DockContainerWidgetPrivate
QGridLayout* Layout = nullptr; QGridLayout* Layout = nullptr;
QSplitter* RootSplitter; QSplitter* RootSplitter;
bool isFloating = false; bool isFloating = false;
CDockAreaWidget* LastAddedAreaCache[5]{0, 0, 0, 0, 0};
/** /**
* Private data constructor * Private data constructor
@ -172,7 +193,6 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float
auto InsertParam = internal::dockAreaInsertParameters(area); auto InsertParam = internal::dockAreaInsertParameters(area);
auto NewDockAreas = FloatingWidget->dockContainer()->findChildren<CDockAreaWidget*>( auto NewDockAreas = FloatingWidget->dockContainer()->findChildren<CDockAreaWidget*>(
QString(), Qt::FindChildrenRecursively); QString(), Qt::FindChildrenRecursively);
CDockWidget* DockWidget = FloatingWidget->dockContainer()->findChild<CDockWidget*>();
QSplitter* Splitter = RootSplitter; QSplitter* Splitter = RootSplitter;
if (DockAreas.count() <= 1) if (DockAreas.count() <= 1)
@ -209,9 +229,12 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float
RootSplitter = Splitter; RootSplitter = Splitter;
addDockAreasToList(NewDockAreas); addDockAreasToList(NewDockAreas);
FloatingWidget->deleteLater(); FloatingWidget->deleteLater();
if (DockWidget) // If we dropped the floating widget into the main dock container that does
// not contain any dock widgets, then splitter is invisible and we need to
// show it to display the docked widgets
if (!Splitter->isVisible())
{ {
DockWidget->toggleView(true); Splitter->show();
} }
_this->dumpLayout(); _this->dumpLayout();
} }
@ -503,6 +526,8 @@ bool DockContainerWidgetPrivate::restoreDockArea(QXmlStreamReader& s,
qDebug() << "Dock Widget found - parent " << DockWidget->parent(); qDebug() << "Dock Widget found - parent " << DockWidget->parent();
DockArea->addDockWidget(DockWidget); DockArea->addDockWidget(DockWidget);
// We hide the DockArea here to prevent the short display (the flashing)
// of the dock areas during application startup
DockArea->hide(); DockArea->hide();
DockWidget->setToggleViewActionChecked(!Closed); DockWidget->setToggleViewActionChecked(!Closed);
DockWidget->setProperty("closed", Closed); DockWidget->setProperty("closed", Closed);
@ -565,6 +590,7 @@ CDockAreaWidget* DockContainerWidgetPrivate::dockWidgetIntoContainer(DockWidgetA
CDockAreaWidget* NewDockArea = new CDockAreaWidget(DockManager, _this); CDockAreaWidget* NewDockArea = new CDockAreaWidget(DockManager, _this);
NewDockArea->addDockWidget(Dockwidget); NewDockArea->addDockWidget(Dockwidget);
addDockArea(NewDockArea, area); addDockArea(NewDockArea, area);
LastAddedAreaCache[areaIdToIndex(area)] = NewDockArea;
return NewDockArea; return NewDockArea;
} }
@ -689,7 +715,6 @@ CDockContainerWidget::CDockContainerWidget(CDockManager* DockManager, QWidget *p
{ {
d->isFloating = dynamic_cast<CFloatingDockContainer*>(parent) != 0; d->isFloating = dynamic_cast<CFloatingDockContainer*>(parent) != 0;
//setStyleSheet("background: green;");
d->DockManager = DockManager; d->DockManager = DockManager;
if (DockManager != this) if (DockManager != this)
{ {
@ -905,6 +930,8 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
CDockAreaWidget* DockArea = dockAreaAt(TargetPos); CDockAreaWidget* DockArea = dockAreaAt(TargetPos);
auto dropArea = InvalidDockWidgetArea; auto dropArea = InvalidDockWidgetArea;
auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor(); auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor();
CDockWidget* TopLevelDockWidget = FloatingWidget->hasSingleDockWidget() ?
FloatingWidget->firstDockWidget() : nullptr;
if (DockArea) if (DockArea)
{ {
auto dropOverlay = d->DockManager->dockAreaOverlay(); auto dropOverlay = d->DockManager->dockAreaOverlay();
@ -933,6 +960,13 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
d->dropIntoContainer(FloatingWidget, dropArea); d->dropIntoContainer(FloatingWidget, dropArea);
} }
} }
// If we drop a floating widget with only one single dock widget, then we
// drop a top level widget that changes from floating to docked now
if (TopLevelDockWidget)
{
emit TopLevelDockWidget->topLevelChanged(false);
}
} }
@ -1047,6 +1081,13 @@ void CDockContainerWidget::dumpLayout()
} }
//============================================================================
CDockAreaWidget* CDockContainerWidget::lastAddedDockAreaWidget(DockWidgetArea area) const
{
return d->LastAddedAreaCache[areaIdToIndex(area)];
}
} // namespace ads } // namespace ads
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@ -103,6 +103,13 @@ protected:
*/ */
bool restoreState(QXmlStreamReader& Stream, bool Testing); bool restoreState(QXmlStreamReader& Stream, bool Testing);
/**
* This function returns the last added dock area widget for the given
* area identifier or 0 if no dock area widget has been added for the given
* area
*/
CDockAreaWidget* lastAddedDockAreaWidget(DockWidgetArea area) const;
public: public:
/** /**
* Default Constructor * Default Constructor

View File

@ -361,7 +361,8 @@ bool CDockManager::restoreState(const QByteArray &state, int version)
{ {
CDockAreaWidget* DockArea = DockContainer->dockArea(i); CDockAreaWidget* DockArea = DockContainer->dockArea(i);
int CurrentIndex = DockArea->property("currentIndex").toInt(); int CurrentIndex = DockArea->property("currentIndex").toInt();
if (CurrentIndex < DockArea->count() && DockArea->count() > 1 && CurrentIndex > -1) int OpenDockWidgetCount = DockArea->openedDockWidgets().count();
if (CurrentIndex < OpenDockWidgetCount && OpenDockWidgetCount > 1 && CurrentIndex > -1)
{ {
DockArea->setCurrentIndex(CurrentIndex); DockArea->setCurrentIndex(CurrentIndex);
} }
@ -382,6 +383,30 @@ CDockAreaWidget* CDockManager::addDockWidget(DockWidgetArea area,
} }
//============================================================================
CDockAreaWidget* CDockManager::addDockWidgetTab(DockWidgetArea area,
CDockWidget* Dockwidget)
{
CDockAreaWidget* AreaWidget = lastAddedDockAreaWidget(area);
if (AreaWidget)
{
return addDockWidget(ads::CenterDockWidgetArea, Dockwidget, AreaWidget);
}
else
{
return addDockWidget(area, Dockwidget, AreaWidget);
}
}
//============================================================================
CDockAreaWidget* CDockManager::addDockWidgetTabToArea(CDockWidget* Dockwidget,
CDockAreaWidget* DockAreaWidget)
{
return addDockWidget(ads::CenterDockWidgetArea, Dockwidget, DockAreaWidget);
}
//============================================================================ //============================================================================
CDockWidget* CDockManager::findDockWidget(const QString& ObjectName) CDockWidget* CDockManager::findDockWidget(const QString& ObjectName)
{ {

View File

@ -128,6 +128,22 @@ public:
CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget, CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
CDockAreaWidget* DockAreaWidget = nullptr); CDockAreaWidget* DockAreaWidget = nullptr);
/**
* This function will add the given Dockwidget to the given dock area as
* a new tab.
* If no dock area widget exists for the given area identifier, a new
* dock area widget is created.
*/
CDockAreaWidget* addDockWidgetTab(DockWidgetArea area,
CDockWidget* Dockwidget);
/**
* This function will add the given Dockwidget to the given DockAreaWidget
* as a new tab.
*/
CDockAreaWidget* addDockWidgetTabToArea(CDockWidget* Dockwidget,
CDockAreaWidget* DockAreaWidget);
/** /**
* Searches for a registered doc widget with the given ObjectName * Searches for a registered doc widget with the given ObjectName
* \return Return the found dock widget or nullptr if a dock widget with the * \return Return the found dock widget or nullptr if a dock widget with the

View File

@ -59,7 +59,7 @@ struct DockWidgetPrivate
CDockWidget* _this; CDockWidget* _this;
QBoxLayout* Layout; QBoxLayout* Layout;
QWidget* Widget = nullptr; QWidget* Widget = nullptr;
CDockWidgetTab* TitleWidget; CDockWidgetTab* TabWidget;
CDockWidget::DockWidgetFeatures Features = CDockWidget::AllDockWidgetFeatures; CDockWidget::DockWidgetFeatures Features = CDockWidget::AllDockWidgetFeatures;
CDockManager* DockManager = nullptr; CDockManager* DockManager = nullptr;
CDockAreaWidget* DockArea = nullptr; CDockAreaWidget* DockArea = nullptr;
@ -87,9 +87,11 @@ struct DockWidgetPrivate
void hideEmptyParentSplitters(); void hideEmptyParentSplitters();
/** /**
* Hides a dock area if all dock widgets in the area are closed * Hides a dock area if all dock widgets in the area are closed.
* This function updates the current selected tab and hides the parent
* dock area if it is empty
*/ */
void hideEmptyParentDockArea(); void updateParentDockArea();
/** /**
* Hides a floating widget if all dock areas are empty - that means, * Hides a floating widget if all dock areas are empty - that means,
@ -141,8 +143,8 @@ void DockWidgetPrivate::showDockWidget()
//============================================================================ //============================================================================
void DockWidgetPrivate::hideDockWidget() void DockWidgetPrivate::hideDockWidget()
{ {
TitleWidget->hide(); TabWidget->hide();
hideEmptyParentDockArea(); updateParentDockArea();
hideEmptyParentSplitters(); hideEmptyParentSplitters();
hideEmptyFloatingWidget(); hideEmptyFloatingWidget();
} }
@ -164,22 +166,11 @@ void DockWidgetPrivate::hideEmptyParentSplitters()
//============================================================================ //============================================================================
void DockWidgetPrivate::hideEmptyParentDockArea() void DockWidgetPrivate::updateParentDockArea()
{ {
auto OpenDockWidgets = DockArea->openedDockWidgets(); auto NextDockWidget = DockArea->nextOpenDockWidget(_this);
if (OpenDockWidgets.count() > 1) if (NextDockWidget)
{ {
CDockWidget* NextDockWidget;
if (OpenDockWidgets.last() == _this)
{
NextDockWidget = OpenDockWidgets[OpenDockWidgets.count() - 2];
}
else
{
int NextIndex = OpenDockWidgets.indexOf(_this) + 1;
NextDockWidget = OpenDockWidgets[NextIndex];
}
DockArea->setCurrentDockWidget(NextDockWidget); DockArea->setCurrentDockWidget(NextDockWidget);
} }
else else
@ -213,7 +204,7 @@ CDockWidget::CDockWidget(const QString &title, QWidget *parent) :
setWindowTitle(title); setWindowTitle(title);
setObjectName(title); setObjectName(title);
d->TitleWidget = new CDockWidgetTab(this); d->TabWidget = new CDockWidgetTab(this);
d->ToggleViewAction = new QAction(title); d->ToggleViewAction = new QAction(title);
d->ToggleViewAction->setCheckable(true); d->ToggleViewAction->setCheckable(true);
connect(d->ToggleViewAction, SIGNAL(triggered(bool)), this, connect(d->ToggleViewAction, SIGNAL(triggered(bool)), this,
@ -262,9 +253,9 @@ QWidget* CDockWidget::widget() const
//============================================================================ //============================================================================
CDockWidgetTab* CDockWidget::titleBar() const CDockWidgetTab* CDockWidget::tabWidget() const
{ {
return d->TitleWidget; return d->TabWidget;
} }
@ -320,7 +311,39 @@ CDockAreaWidget* CDockWidget::dockAreaWidget() const
//============================================================================ //============================================================================
bool CDockWidget::isFloating() const bool CDockWidget::isFloating() const
{ {
return dockContainer() ? dockContainer()->isFloating() : false; if (!isInFloatingContainer())
{
return false;
}
if (dockContainer()->dockAreaCount() != 1)
{
return false;
}
if (dockContainer()->dockArea(0)->count() != 1)
{
return false;
}
return true;
}
//============================================================================
bool CDockWidget::isInFloatingContainer() const
{
if (!dockContainer())
{
return false;
}
if (!dockContainer()->isFloating())
{
return false;
}
return true;
} }
@ -349,7 +372,7 @@ void CDockWidget::setToggleViewActionMode(eToggleViewActionMode Mode)
else else
{ {
d->ToggleViewAction->setCheckable(false); d->ToggleViewAction->setCheckable(false);
d->ToggleViewAction->setIcon(d->TitleWidget->icon()); d->ToggleViewAction->setIcon(d->TabWidget->icon());
} }
} }
@ -375,6 +398,8 @@ void CDockWidget::toggleView(bool Open)
d->ToggleViewAction->blockSignals(true); d->ToggleViewAction->blockSignals(true);
d->ToggleViewAction->setChecked(Open); d->ToggleViewAction->setChecked(Open);
d->ToggleViewAction->blockSignals(false); d->ToggleViewAction->blockSignals(false);
d->DockArea->toggleDockWidgetView(this, Open);
if (!Open) if (!Open)
{ {
emit closed(); emit closed();
@ -406,7 +431,7 @@ void CDockWidget::flagAsUnassigned()
{ {
setParent(d->DockManager); setParent(d->DockManager);
setDockArea(nullptr); setDockArea(nullptr);
titleBar()->setParent(this); tabWidget()->setParent(this);
} }
@ -424,7 +449,7 @@ bool CDockWidget::event(QEvent *e)
//============================================================================ //============================================================================
void CDockWidget::setIcon(const QIcon& Icon) void CDockWidget::setIcon(const QIcon& Icon)
{ {
d->TitleWidget->setIcon(Icon); d->TabWidget->setIcon(Icon);
if (!d->ToggleViewAction->isCheckable()) if (!d->ToggleViewAction->isCheckable())
{ {
d->ToggleViewAction->setIcon(Icon); d->ToggleViewAction->setIcon(Icon);
@ -435,7 +460,7 @@ void CDockWidget::setIcon(const QIcon& Icon)
//============================================================================ //============================================================================
QIcon CDockWidget::icon() const QIcon CDockWidget::icon() const
{ {
return d->TitleWidget->icon(); return d->TabWidget->icon();
} }

View File

@ -164,7 +164,7 @@ public:
/** /**
* Returns the title bar widget of this dock widget * Returns the title bar widget of this dock widget
*/ */
CDockWidgetTab* titleBar() const; CDockWidgetTab* tabWidget() const;
/** /**
* Sets, whether the dock widget is movable, closable, and floatable. * Sets, whether the dock widget is movable, closable, and floatable.
@ -193,7 +193,7 @@ public:
/** /**
* Returns the dock container widget this dock area widget belongs to or 0 * Returns the dock container widget this dock area widget belongs to or 0
* if this dock widget has nt been docked yet * if this dock widget has not been docked yet
*/ */
CDockContainerWidget* dockContainer() const; CDockContainerWidget* dockContainer() const;
@ -205,9 +205,19 @@ public:
/** /**
* This property holds whether the dock widget is floating. * This property holds whether the dock widget is floating.
* A dock widget is only floating, if it is the one and only widget inside
* of a floating container. If there are more than one dock widget in a
* floating container, the all dock widgets are docked and not floating.
*/ */
bool isFloating() const; bool isFloating() const;
/**
* This function returns true, if this dock widget is in a floating.
* The function returns true, if the dock widget is floating and it also
* returns true if it is docked inside of a floating container.
*/
bool isInFloatingContainer() const;
/** /**
* Returns true, if this dock widget is closed. * Returns true, if this dock widget is closed.
*/ */
@ -266,6 +276,13 @@ signals:
* changed * changed
*/ */
void titleChanged(const QString& Title); void titleChanged(const QString& Title);
/**
* This signal is emitted when the floating property changes.
* The topLevel parameter is true if the dock widget is now floating;
* otherwise it is false.
*/
void topLevelChanged(bool topLevel);
}; // class DockWidget }; // class DockWidget
} }
// namespace ads // namespace ads

View File

@ -196,6 +196,7 @@ bool DockWidgetTabPrivate::startFloating()
auto Overlay = DockWidget->dockManager()->containerOverlay(); auto Overlay = DockWidget->dockManager()->containerOverlay();
Overlay->setAllowedAreas(OuterDockAreas); Overlay->setAllowedAreas(OuterDockAreas);
this->FloatingWidget = FloatingWidget; this->FloatingWidget = FloatingWidget;
emit DockWidget->topLevelChanged(true);
return true; return true;
} }

View File

@ -481,6 +481,25 @@ bool CFloatingDockContainer::restoreState(QXmlStreamReader& Stream, bool Testing
} }
//============================================================================
bool CFloatingDockContainer::hasSingleDockWidget() const
{
if (d->DockContainer->dockAreaCount() != 1)
{
return false;
}
return d->DockContainer->dockArea(0)->count() == 1;
}
//============================================================================
CDockWidget* CFloatingDockContainer::firstDockWidget() const
{
return d->DockContainer->dockArea(0)->dockWidget(0);
}
} // namespace ads } // namespace ads
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@ -132,6 +132,21 @@ public:
* It can be closed, if all dock widgets in all dock areas can be closed * It can be closed, if all dock widgets in all dock areas can be closed
*/ */
bool isClosable() const; bool isClosable() const;
/**
* This function returns true, if this floating widget has only one single
* dock widget in a single dock area.
* The single dock widget is a real top level floating widget because no
* other widgets are docked.
*/
bool hasSingleDockWidget() const;
/**
* This function returns the first dock widget in the first dock area.
* If the function hasSingleDockWidget() returns true, then this function
* returns this single dock widget.
*/
CDockWidget* firstDockWidget() const;
}; // class FloatingDockContainer }; // class FloatingDockContainer
} }
// namespace ads // namespace ads