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:
Uwe Kindler 2018-09-14 08:46:10 +02:00
parent b93e723a83
commit 6ec38b48ef
7 changed files with 110 additions and 58 deletions

View File

@ -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();
} }

View File

@ -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
*/ */

View File

@ -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
} }

View File

@ -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;
} }

View File

@ -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();
} }

View File

@ -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;
} }

View File

@ -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