Improved hide / show functionality of dock widgets

This commit is contained in:
Uwe Kindler 2017-03-22 16:08:44 +01:00
parent 0d6f469a36
commit b6ee26adc2
8 changed files with 165 additions and 101 deletions

View File

@ -26,7 +26,7 @@ static ads::CDockWidget* createLongTextLabelDockWidget(QMenu* ViewMenu)
QLabel* l = new QLabel();
l->setWordWrap(true);
l->setAlignment(Qt::AlignTop | Qt::AlignLeft);
l->setText(QString("Lorem Ipsum ist ein einfacher Demo-Text für die Print- "
l->setText(QString("Label %1 %2 - Lorem Ipsum ist ein einfacher Demo-Text für die Print- "
"und Schriftindustrie. Lorem Ipsum ist in der Industrie bereits der "
"Standard Demo-Text seit 1500, als ein unbekannter Schriftsteller eine "
"Hand voll Wörter nahm und diese durcheinander warf um ein Musterbuch zu "
@ -34,7 +34,9 @@ static ads::CDockWidget* createLongTextLabelDockWidget(QMenu* ViewMenu)
"Spruch in die elektronische Schriftbearbeitung geschafft (bemerke, nahezu "
"unverändert). Bekannt wurde es 1960, mit dem erscheinen von Letrase, "
"welches Passagen von Lorem Ipsum enhielt, so wie Desktop Software wie "
"Aldus PageMaker - ebenfalls mit Lorem Ipsum."));
"Aldus PageMaker - ebenfalls mit Lorem Ipsum.")
.arg(LabelCount)
.arg(QTime::currentTime().toString("hh:mm:ss:zzz")));
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Label %1").arg(LabelCount++));
DockWidget->setWidget(l);

View File

@ -504,6 +504,18 @@ CDockWidget* CDockAreaWidget::currentDockWidget() const
}
//============================================================================
void CDockAreaWidget::setCurrentDockWidget(CDockWidget* DockWidget)
{
int Index = tabIndex(DockWidget);
if (Index < 0)
{
return;
}
setCurrentIndex(Index);
}
//============================================================================
void CDockAreaWidget::setCurrentIndex(int index)
{
@ -530,6 +542,7 @@ void CDockAreaWidget::setCurrentIndex(int index)
if (i == index)
{
TitleWidget->show();
TitleWidget->setActiveTab(true);
d->TabsScrollArea->ensureWidgetVisible(TitleWidget);
auto Features = TitleWidget->dockWidget()->features();
@ -542,6 +555,7 @@ void CDockAreaWidget::setCurrentIndex(int index)
}
d->ContentsLayout->setCurrentIndex(index);
d->ContentsLayout->currentWidget()->show();
emit currentChanged(index);
}
@ -585,6 +599,22 @@ QList<CDockWidget*> CDockAreaWidget::dockWidgets() const
}
//============================================================================
QList<CDockWidget*> CDockAreaWidget::openDockWidgets() const
{
QList<CDockWidget*> DockWidgetList;
for (int i = 0; i < d->ContentsLayout->count(); ++i)
{
CDockWidget* DockWidget = dockWidget(i);
if (!DockWidget->isClosed())
{
DockWidgetList.append(dockWidget(i));
}
}
return DockWidgetList;
}
//============================================================================
int CDockAreaWidget::indexOfContentByTitlePos(const QPoint& p, QWidget* exclude) const
{
@ -665,6 +695,22 @@ void CDockAreaWidget::updateDockArea()
d->updateTabBar();
}
//============================================================================
void CDockAreaWidget::hideEvent(QHideEvent* event)
{
QFrame::hideEvent(event);
emit visibilityChanged(isVisible());
}
//============================================================================
void CDockAreaWidget::showEvent(QShowEvent* event)
{
QFrame::showEvent(event);
emit visibilityChanged(isVisible());
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@ -56,6 +56,10 @@ private slots:
void onTabsMenuActionTriggered(QAction* Action);
void onCloseButtonClicked();
protected:
virtual void hideEvent(QHideEvent *) override;
virtual void showEvent(QShowEvent *) override;
public:
/**
* Default Constructor
@ -120,10 +124,16 @@ public:
int indexOfContentByTitlePos(const QPoint& pos, QWidget* exclude = nullptr) const;
/**
* Returns a list of all dock widgets in this dock area
* Returns a list of all dock widgets in this dock area.
* This list contains open and closed dock widgets.
*/
QList<CDockWidget*> dockWidgets() const;
/**
* Returns a list of dock widgets that are not closed
*/
QList<CDockWidget*> openDockWidgets() const;
/**
* Returns the number of dock widgets in this area
*/
@ -149,6 +159,11 @@ public:
*/
CDockWidget* currentDockWidget() const;
/**
* Shows the tab with tghe given dock widget
*/
void setCurrentDockWidget(CDockWidget* DockWidget);
public slots:
/**
* This sets the index position of the current tab page.
@ -172,6 +187,14 @@ signals:
* @param index
*/
void currentChanged(int index);
/**
* This signal is emitted if a dock areas visibility changed.
* The visibility changes, if the last dock widget in a dock area is closed
* or if one dock widget in a dock area with only closed dock widgets
* becomes visible
*/
void visibilityChanged(bool Visible);
}; // class DockAreaWidget
}
// namespace ads

View File

@ -497,6 +497,7 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
area->setParent(0);
if (!(Splitter && Splitter->count() == 1))
{
emit dockAreasRemoved();
return;
}
@ -586,6 +587,7 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
}
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@ -52,6 +52,7 @@ class CDockContainerWidget : public QFrame
private:
DockContainerWidgetPrivate* d; ///< private data (pimpl)
friend class DockContainerWidgetPrivate;
protected:
/**
* Handles activation events to update zOrderIndex

View File

@ -62,6 +62,7 @@ struct DockWidgetPrivate
CDockManager* DockManager = nullptr;
CDockAreaWidget* DockArea = nullptr;
QAction* ToggleViewAction;
bool Closed = false;
struct CapturedState
{
QString DockTreePosition;
@ -83,6 +84,16 @@ struct DockWidgetPrivate
* Show dock widget
*/
void showDockWidget();
/**
* Hides a parent splitter if all dock widgets in the splitter are closed
*/
void hideEmptyParentSplitter();
/**
* Hides a dock area if all dock widgets in the area are closed
*/
void hideEmptyParentDockArea();
};
// struct DockWidgetPrivate
@ -131,32 +142,8 @@ void DockWidgetPrivate::capturedState()
//============================================================================
void DockWidgetPrivate::showDockWidget()
{
/*if (!CapturedState.DockContainer)
{
auto FloatingWidget = new CFloatingDockContainer(_this);
FloatingWidget->setGeometry(CapturedState.GlobalGeometry);
FloatingWidget->show();
return;
}
CDockContainerWidget* DockContainer = CapturedState.DockContainer.data();
QStringList DockTree = this->CapturedState.DockTreePosition.split(' ');
QSplitter* splitter = DockContainer->findChild<QSplitter*>(QString(), Qt::FindDirectChildrenOnly);
while (splitter)
{
}
for (const auto& TreeItem : DockTree)
{
}*/
std::cout << "DockWidgetPrivate::showDockWidget()" << std::endl;
_this->show();
DockArea->show();
DockArea->setCurrentIndex(DockArea->tabIndex(_this));
QSplitter* Splitter = internal::findParent<QSplitter*>(_this);
if (Splitter)
{
@ -165,6 +152,53 @@ void DockWidgetPrivate::showDockWidget()
}
//============================================================================
void DockWidgetPrivate::hideEmptyParentSplitter()
{
QSplitter* Splitter = internal::findParent<QSplitter*>(_this);
if (!Splitter)
{
return;
}
for (int i = 0; i < Splitter->count(); ++i)
{
if (Splitter->widget(i)->isVisible())
{
return;
}
}
Splitter->hide();
}
//============================================================================
void DockWidgetPrivate::hideEmptyParentDockArea()
{
auto OpenDockWidgets = DockArea->openDockWidgets();
if (OpenDockWidgets.count() > 1)
{
CDockWidget* NextDockWidget;
if (OpenDockWidgets.last() == _this)
{
NextDockWidget = OpenDockWidgets[OpenDockWidgets.count() - 2];
}
else
{
int NextIndex = OpenDockWidgets.indexOf(_this) + 1;
NextDockWidget = OpenDockWidgets[NextIndex];
}
DockArea->setCurrentDockWidget(NextDockWidget);
}
else
{
DockArea->hide();
}
}
//============================================================================
CDockWidget::CDockWidget(const QString &title, QWidget *parent) :
QFrame(parent),
@ -270,6 +304,13 @@ bool CDockWidget::isFloating() const
}
//============================================================================
bool CDockWidget::isClosed() const
{
return d->Closed;
}
//============================================================================
QAction* CDockWidget::toggleViewAction() const
{
@ -280,28 +321,15 @@ QAction* CDockWidget::toggleViewAction() const
//============================================================================
void CDockWidget::toggleView(bool Open)
{
/*if ((d->DockArea != nullptr) == Open)
{
return;
}
if (!Open && d->DockArea)
{
hideDockWidget(true);
}
else if (Open && !d->DockArea)
{
d->showDockWidget();
}*/
if (Open)
{
d->showDockWidget();
}
else
{
hideDockWidget(true);
hideDockWidget();
}
d->Closed = !Open;
}
@ -315,59 +343,13 @@ void CDockWidget::setDockArea(CDockAreaWidget* DockArea)
//============================================================================
void CDockWidget::hideDockWidget(bool RemoveFromDockArea)
void CDockWidget::hideDockWidget()
{
/*d->capturedState();
if (d->DockArea && RemoveFromDockArea)
{
d->DockArea->removeDockWidget(this);
}
this->setParent(d->DockManager);
this->setDockArea(nullptr);
// Remove title from dock area widget to prevent its deletion if dock
// area is deleted
d->TitleWidget->setParent(this);*/
std::cout << "CDockWidget::hideDockWidget" << std::endl;
this->hide();
CDockAreaWidget* DockArea = d->DockArea;
d->ToggleViewAction->setChecked(false);
d->TitleWidget->hide();
CDockAreaWidget* DockArea = d->DockArea;
for (int i = 0; i < DockArea->count(); ++i)
{
if (DockArea->dockWidget(i)->isVisible())
{
return;
}
}
if (DockArea->count() > 1)
{
if (DockArea->currentIndex() == (DockArea->count() - 1))
{
DockArea->setCurrentIndex(DockArea->currentIndex() - 1);
}
else
{
DockArea->setCurrentIndex(DockArea->currentIndex() + 1);
}
}
QSplitter* Splitter = internal::findParent<QSplitter*>(this);
if (!Splitter)
{
return;
}
std::cout << "DockWidgets " << Splitter->count() << std::endl;
for (int i = 0; i < Splitter->count(); ++i)
{
if (Splitter->widget(i)->isVisible())
{
return;
}
}
Splitter->hide();
d->hideEmptyParentDockArea();
d->hideEmptyParentSplitter();
}
} // namespace ads

View File

@ -71,10 +71,8 @@ protected:
/**
* Hide dock widget.
* If RemoveFromDockArea is true, the dock widget will be properly removed
* from dock area.
*/
void hideDockWidget(bool RemoveFromDockArea = true);
void hideDockWidget();
public:
enum DockWidgetFeature
@ -157,6 +155,11 @@ public:
*/
bool isFloating() const;
/**
* Returns true, if this dock widget is closed.
*/
bool isClosed() const;
/**
* Returns a checkable action that can be used to show or close this dock widget.
* The action's text is set to the dock widget's window title.

View File

@ -172,7 +172,7 @@ CFloatingDockContainer::CFloatingDockContainer(CDockManager* DockManager) :
QWidget(DockManager, Qt::Window),
d(new FloatingDockContainerPrivate(this))
{
setAttribute(Qt::WA_DeleteOnClose);
//setAttribute(Qt::WA_DeleteOnClose);
d->DockManager = DockManager;
QBoxLayout* l = new QBoxLayout(QBoxLayout::TopToBottom);
l->setContentsMargins(0, 0, 0, 0);
@ -210,6 +210,7 @@ CFloatingDockContainer::CFloatingDockContainer(CDockWidget* DockWidget) :
//============================================================================
CFloatingDockContainer::~CFloatingDockContainer()
{
std::cout << "~CFloatingDockContainer" << std::endl;
if (d->DockManager)
{
d->DockManager->removeFloatingWidget(this);
@ -269,17 +270,21 @@ void CFloatingDockContainer::closeEvent(QCloseEvent *event)
auto DockWidgets = dockContainer()->dockArea(i)->dockWidgets();
for (auto DockWidget : DockWidgets)
{
DockWidget->hideDockWidget(false);
DockWidget->hideDockWidget();
}
}
QWidget::closeEvent(event);
}
else
{
std::cout << "Closing single tab" << std::endl;
event->ignore();
auto DockArea = dockContainer()->dockArea(0);
DockArea->currentDockWidget()->hideDockWidget(true);
DockArea->currentDockWidget()->hideDockWidget();
// As long as there are open dock widgets, we do not close the floating
// window
if (DockArea->openDockWidgets().count())
{
event->ignore();
}
}
}