mirror of
https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System.git
synced 2025-02-05 02:26:46 +08:00
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:
parent
72ee4a53df
commit
67199a81f4
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user