mirror of
https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System.git
synced 2025-01-13 00:30:25 +08:00
Fixed proper hiding of dock areas without any visible content when dragging out singkle widgets, prevente single dock widget from dragging if it is the last dock widget in a floating widget
This commit is contained in:
parent
b93e723a83
commit
6ec38b48ef
@ -49,6 +49,7 @@
|
|||||||
#include "DockManager.h"
|
#include "DockManager.h"
|
||||||
#include "DockOverlay.h"
|
#include "DockOverlay.h"
|
||||||
#include "DockAreaTabBar.h"
|
#include "DockAreaTabBar.h"
|
||||||
|
#include "DockSplitter.h"
|
||||||
|
|
||||||
|
|
||||||
namespace ads
|
namespace ads
|
||||||
@ -76,7 +77,6 @@ struct DockAreaWidgetPrivate
|
|||||||
QPushButton* CloseButton;
|
QPushButton* CloseButton;
|
||||||
int TabsLayoutInitCount;
|
int TabsLayoutInitCount;
|
||||||
CDockManager* DockManager = nullptr;
|
CDockManager* DockManager = nullptr;
|
||||||
QVector<CDockWidget*> OpenDockWidgets;
|
|
||||||
bool MenuOutdated = true;
|
bool MenuOutdated = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -216,7 +216,7 @@ void DockAreaWidgetPrivate::updateTabBar()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Container->isFloating() && (Container->dockAreaCount() == 1) && (_this->count() == 1))
|
if (Container->isFloating() && (Container->dockAreaCount() == 1) && (_this->dockWidgetsCount() == 1))
|
||||||
{
|
{
|
||||||
TitleBar->setVisible(false);
|
TitleBar->setVisible(false);
|
||||||
}
|
}
|
||||||
@ -380,6 +380,13 @@ void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
|
|||||||
dockContainer()->removeDockArea(this);
|
dockContainer()->removeDockArea(this);
|
||||||
this->deleteLater();;
|
this->deleteLater();;
|
||||||
}
|
}
|
||||||
|
else if (!NextDockWidget)
|
||||||
|
{
|
||||||
|
// if contents layout is not empty but there are no more open dock
|
||||||
|
// widgets, then we need to hide the dock area because it does not
|
||||||
|
// contain any visible content
|
||||||
|
hideAreaWithNoVisibleContent();
|
||||||
|
}
|
||||||
|
|
||||||
d->updateTabBar();
|
d->updateTabBar();
|
||||||
DockWidget->setDockArea(nullptr);
|
DockWidget->setDockArea(nullptr);
|
||||||
@ -387,6 +394,42 @@ void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
void CDockAreaWidget::hideAreaWithNoVisibleContent()
|
||||||
|
{
|
||||||
|
this->hide();
|
||||||
|
|
||||||
|
// Hide empty parent splitter
|
||||||
|
auto Splitter = internal::findParent<CDockSplitter*>(this);
|
||||||
|
while (Splitter && Splitter->isVisible())
|
||||||
|
{
|
||||||
|
if (!Splitter->hasVisibleContent())
|
||||||
|
{
|
||||||
|
Splitter->hide();
|
||||||
|
}
|
||||||
|
Splitter = internal::findParent<CDockSplitter*>(Splitter);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Hide empty floating widget
|
||||||
|
CDockContainerWidget* Container = this->dockContainer();
|
||||||
|
if (Container->isFloating() && Container->openedDockAreas().isEmpty())
|
||||||
|
{
|
||||||
|
CFloatingDockContainer* FloatingWidget = internal::findParent<CFloatingDockContainer*>(Container);
|
||||||
|
FloatingWidget->hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
void CDockAreaWidget::hideAreaIfNoVisibleContent()
|
||||||
|
{
|
||||||
|
if (openedDockWidgets().isEmpty())
|
||||||
|
{
|
||||||
|
hideAreaIfNoVisibleContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
void CDockAreaWidget::onDockWidgetTitleClicked()
|
void CDockAreaWidget::onDockWidgetTitleClicked()
|
||||||
{
|
{
|
||||||
@ -512,6 +555,21 @@ QList<CDockWidget*> CDockAreaWidget::dockWidgets() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
int CDockAreaWidget::openDockWidgetsCount() const
|
||||||
|
{
|
||||||
|
int Count = 0;
|
||||||
|
for (int i = 0; i < d->ContentsLayout->count(); ++i)
|
||||||
|
{
|
||||||
|
if (!dockWidget(i)->isClosed())
|
||||||
|
{
|
||||||
|
++Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
QList<CDockWidget*> CDockAreaWidget::openedDockWidgets() const
|
QList<CDockWidget*> CDockAreaWidget::openedDockWidgets() const
|
||||||
{
|
{
|
||||||
@ -544,7 +602,7 @@ int CDockAreaWidget::indexOfContentByTitlePos(const QPoint& p, QWidget* exclude)
|
|||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
int CDockAreaWidget::count() const
|
int CDockAreaWidget::dockWidgetsCount() const
|
||||||
{
|
{
|
||||||
return d->ContentsLayout->count();
|
return d->ContentsLayout->count();
|
||||||
}
|
}
|
||||||
|
@ -118,6 +118,19 @@ protected:
|
|||||||
*/
|
*/
|
||||||
int index(CDockWidget* DockWidget);
|
int index(CDockWidget* DockWidget);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this function, if you already know, that the dock does not
|
||||||
|
* contain any visible content (any open dock widgets).
|
||||||
|
*/
|
||||||
|
void hideAreaWithNoVisibleContent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function checks, if the dock area has visible content, that means
|
||||||
|
* if any dock widget is open, and then calls hideAreaWithNoVisibleContent()
|
||||||
|
* if it does not find any visible content
|
||||||
|
*/
|
||||||
|
void hideAreaIfNoVisibleContent();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Default Constructor
|
* Default Constructor
|
||||||
@ -150,22 +163,27 @@ public:
|
|||||||
*/
|
*/
|
||||||
QRect contentAreaGeometry() const;
|
QRect contentAreaGeometry() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of dock widgets in this area
|
||||||
|
*/
|
||||||
|
int dockWidgetsCount() 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.
|
* This list contains open and closed dock widgets.
|
||||||
*/
|
*/
|
||||||
QList<CDockWidget*> dockWidgets() const;
|
QList<CDockWidget*> dockWidgets() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of dock widgets in this area
|
||||||
|
*/
|
||||||
|
int openDockWidgetsCount() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of dock widgets that are not closed
|
* Returns a list of dock widgets that are not closed
|
||||||
*/
|
*/
|
||||||
QList<CDockWidget*> openedDockWidgets() const;
|
QList<CDockWidget*> openedDockWidgets() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of dock widgets in this area
|
|
||||||
*/
|
|
||||||
int count() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a dock widget by its index
|
* Returns a dock widget by its index
|
||||||
*/
|
*/
|
||||||
|
@ -537,7 +537,7 @@ bool DockContainerWidgetPrivate::restoreDockArea(QXmlStreamReader& s,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DockArea->count())
|
if (!DockArea->dockWidgetsCount())
|
||||||
{
|
{
|
||||||
delete DockArea;
|
delete DockArea;
|
||||||
DockArea = nullptr;
|
DockArea = nullptr;
|
||||||
@ -1073,9 +1073,11 @@ QSplitter* CDockContainerWidget::rootSplitter() const
|
|||||||
//============================================================================
|
//============================================================================
|
||||||
void CDockContainerWidget::dumpLayout()
|
void CDockContainerWidget::dumpLayout()
|
||||||
{
|
{
|
||||||
|
#if (ADS_DEBUG_LEVEL > 0)
|
||||||
qDebug("\n\nDumping layout --------------------------");
|
qDebug("\n\nDumping layout --------------------------");
|
||||||
d->dumpRecursive(0, d->RootSplitter);
|
d->dumpRecursive(0, d->RootSplitter);
|
||||||
qDebug("--------------------------\n\n");
|
qDebug("--------------------------\n\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,11 +91,6 @@ struct DockWidgetPrivate
|
|||||||
*/
|
*/
|
||||||
void hideDockWidget();
|
void hideDockWidget();
|
||||||
|
|
||||||
/**
|
|
||||||
* Hides a parent splitter if all dock widgets in the splitter are closed
|
|
||||||
*/
|
|
||||||
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
|
* This function updates the current selected tab and hides the parent
|
||||||
@ -103,12 +98,6 @@ struct DockWidgetPrivate
|
|||||||
*/
|
*/
|
||||||
void updateParentDockArea();
|
void updateParentDockArea();
|
||||||
|
|
||||||
/**
|
|
||||||
* Hides a floating widget if all dock areas are empty - that means,
|
|
||||||
* if all dock widgets in all dock areas are closed
|
|
||||||
*/
|
|
||||||
void hideEmptyFloatingWidget();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup the top tool bar
|
* Setup the top tool bar
|
||||||
*/
|
*/
|
||||||
@ -165,23 +154,6 @@ void DockWidgetPrivate::hideDockWidget()
|
|||||||
{
|
{
|
||||||
TabWidget->hide();
|
TabWidget->hide();
|
||||||
updateParentDockArea();
|
updateParentDockArea();
|
||||||
hideEmptyParentSplitters();
|
|
||||||
hideEmptyFloatingWidget();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void DockWidgetPrivate::hideEmptyParentSplitters()
|
|
||||||
{
|
|
||||||
auto Splitter = internal::findParent<CDockSplitter*>(_this);
|
|
||||||
while (Splitter && Splitter->isVisible())
|
|
||||||
{
|
|
||||||
if (!Splitter->hasVisibleContent())
|
|
||||||
{
|
|
||||||
Splitter->hide();
|
|
||||||
}
|
|
||||||
Splitter = internal::findParent<CDockSplitter*>(Splitter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -195,19 +167,7 @@ void DockWidgetPrivate::updateParentDockArea()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DockArea->hide();
|
DockArea->hideAreaWithNoVisibleContent();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void DockWidgetPrivate::hideEmptyFloatingWidget()
|
|
||||||
{
|
|
||||||
CDockContainerWidget* Container = _this->dockContainer();
|
|
||||||
if (Container->isFloating() && Container->openedDockAreas().isEmpty())
|
|
||||||
{
|
|
||||||
CFloatingDockContainer* FloatingWidget = internal::findParent<CFloatingDockContainer*>(Container);
|
|
||||||
FloatingWidget->hide();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,7 +345,7 @@ bool CDockWidget::isFloating() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dockContainer()->dockArea(0)->count() != 1)
|
if (dockContainer()->dockArea(0)->dockWidgetsCount() != 1)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -164,13 +164,13 @@ bool DockWidgetTabPrivate::startFloating()
|
|||||||
{
|
{
|
||||||
qDebug() << "isFloating " << DockWidget->dockContainer()->isFloating();
|
qDebug() << "isFloating " << DockWidget->dockContainer()->isFloating();
|
||||||
qDebug() << "areaCount " << DockWidget->dockContainer()->dockAreaCount();
|
qDebug() << "areaCount " << DockWidget->dockContainer()->dockAreaCount();
|
||||||
qDebug() << "widgetCount " << DockWidget->dockAreaWidget()->count();
|
qDebug() << "widgetCount " << DockWidget->dockAreaWidget()->dockWidgetsCount();
|
||||||
// if this is the last dock widget inside of this floating widget,
|
// if this is the last dock widget inside of this floating widget,
|
||||||
// then it does not make any sense, to make it floating because
|
// then it does not make any sense, to make it floating because
|
||||||
// it is already floating
|
// it is already floating
|
||||||
if (DockWidget->dockContainer()->isFloating()
|
if (DockWidget->dockContainer()->isFloating()
|
||||||
&& (DockWidget->dockContainer()->visibleDockAreaCount() == 1)
|
&& (DockWidget->dockContainer()->visibleDockAreaCount() == 1)
|
||||||
&& (DockWidget->dockAreaWidget()->count() == 1))
|
&& (DockWidget->dockAreaWidget()->dockWidgetsCount() == 1))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -179,7 +179,7 @@ bool DockWidgetTabPrivate::startFloating()
|
|||||||
DragState = DraggingFloatingWidget;
|
DragState = DraggingFloatingWidget;
|
||||||
QSize Size = DockArea->size();
|
QSize Size = DockArea->size();
|
||||||
CFloatingDockContainer* FloatingWidget = nullptr;
|
CFloatingDockContainer* FloatingWidget = nullptr;
|
||||||
if (DockArea->count() > 1)
|
if (DockArea->dockWidgetsCount() > 1)
|
||||||
{
|
{
|
||||||
// If section widget has multiple tabs, we take only one tab
|
// If section widget has multiple tabs, we take only one tab
|
||||||
FloatingWidget = new CFloatingDockContainer(DockWidget);
|
FloatingWidget = new CFloatingDockContainer(DockWidget);
|
||||||
@ -248,7 +248,7 @@ void CDockWidgetTab::mouseReleaseEvent(QMouseEvent* ev)
|
|||||||
int toIndex = d->DockArea->indexOfContentByTitlePos(pos, this);
|
int toIndex = d->DockArea->indexOfContentByTitlePos(pos, this);
|
||||||
if (-1 == toIndex)
|
if (-1 == toIndex)
|
||||||
{
|
{
|
||||||
toIndex = d->DockArea->count() - 1;
|
toIndex = d->DockArea->dockWidgetsCount() - 1;
|
||||||
}
|
}
|
||||||
qDebug() << "Move tab from " << fromIndex << " to " << toIndex;
|
qDebug() << "Move tab from " << fromIndex << " to " << toIndex;
|
||||||
d->DockArea->reorderDockWidget(fromIndex, toIndex);
|
d->DockArea->reorderDockWidget(fromIndex, toIndex);
|
||||||
@ -294,6 +294,16 @@ void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
|
|||||||
bool MouseInsideTitleArea = d->titleAreaGeometryContains(ev->globalPos());
|
bool MouseInsideTitleArea = d->titleAreaGeometryContains(ev->globalPos());
|
||||||
if (!MouseInsideTitleArea)
|
if (!MouseInsideTitleArea)
|
||||||
{
|
{
|
||||||
|
// If this is the last dock area in a dock container with only
|
||||||
|
// one single dock widget it does not make sense to move it to a new
|
||||||
|
// floating widget and leave this one empty
|
||||||
|
if (d->DockArea->dockContainer()->isFloating()
|
||||||
|
&& d->DockArea->openDockWidgetsCount() == 1
|
||||||
|
&& d->DockArea->dockContainer()->visibleDockAreaCount() == 1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Floating is only allowed for widgets that are movable
|
// Floating is only allowed for widgets that are movable
|
||||||
if (d->DockWidget->features().testFlag(CDockWidget::DockWidgetMovable))
|
if (d->DockWidget->features().testFlag(CDockWidget::DockWidgetMovable))
|
||||||
{
|
{
|
||||||
@ -301,7 +311,7 @@ void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (d->DockArea->count() > 1
|
else if (d->DockArea->openDockWidgetsCount() > 1
|
||||||
&& (ev->pos() - d->DragStartMousePosition).manhattanLength() >= QApplication::startDragDistance()) // Wait a few pixels before start moving
|
&& (ev->pos() - d->DragStartMousePosition).manhattanLength() >= QApplication::startDragDistance()) // Wait a few pixels before start moving
|
||||||
{
|
{
|
||||||
d->DragState = DraggingTab;
|
d->DragState = DraggingTab;
|
||||||
@ -381,7 +391,7 @@ void CDockWidgetTab::mouseDoubleClickEvent(QMouseEvent *event)
|
|||||||
// If this is the last dock area in a dock container it does not make
|
// If this is the last dock area in a dock container it does not make
|
||||||
// sense to move it to a new floating widget and leave this one
|
// sense to move it to a new floating widget and leave this one
|
||||||
// empty
|
// empty
|
||||||
if (!d->DockArea->dockContainer()->isFloating() || d->DockArea->count() > 1)
|
if (!d->DockArea->dockContainer()->isFloating() || d->DockArea->dockWidgetsCount() > 1)
|
||||||
{
|
{
|
||||||
d->startFloating();
|
d->startFloating();
|
||||||
}
|
}
|
||||||
|
@ -409,7 +409,9 @@ bool CFloatingDockContainer::event(QEvent *e)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (ADS_DEBUG_LEVEL > 0)
|
||||||
qDebug() << "CFloatingDockContainer::event " << e->type();
|
qDebug() << "CFloatingDockContainer::event " << e->type();
|
||||||
|
#endif
|
||||||
return QWidget::event(e);
|
return QWidget::event(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -520,7 +522,7 @@ bool CFloatingDockContainer::hasSingleDockWidget() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return d->DockContainer->dockArea(0)->count() == 1;
|
return d->DockContainer->dockArea(0)->dockWidgetsCount() == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,6 +39,8 @@
|
|||||||
#define ADS_EXPORT Q_DECL_IMPORT
|
#define ADS_EXPORT Q_DECL_IMPORT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ADS_DEBUG_LEVEL 0
|
||||||
|
|
||||||
class QSplitter;
|
class QSplitter;
|
||||||
|
|
||||||
namespace ads
|
namespace ads
|
||||||
|
Loading…
Reference in New Issue
Block a user