Removed unused DockStateSerialization files, added support for opaque splitter resizing

This commit is contained in:
Uwe Kindler 2018-12-11 15:19:59 +01:00
parent 653f475e72
commit 80efed693e
15 changed files with 150 additions and 169 deletions

View File

@ -9,15 +9,11 @@ CONFIG *= c++14
SOURCES += \
main.cpp \
MainWindow.cpp \
mhtabbar.cpp \
mhtabwidget.cpp
MainWindow.cpp
HEADERS += \
MainWindow.h \
mhtabbar.h \
mhtabwidget.h
MainWindow.h
FORMS += \
mainwindow.ui
@ -27,8 +23,8 @@ RESOURCES += main.qrc
LIBS += -L$${ADS_OUT_ROOT}/lib
# Dependency: AdvancedDockingSystem (shared)
win32:CONFIG(release, debug|release): LIBS += -lAdvancedDockingSystem
else:win32:CONFIG(debug, debug|release): LIBS += -lAdvancedDockingSystemd
win32:CONFIG(release, debug|release): LIBS += -lqtadvanceddocking
else:win32:CONFIG(debug, debug|release): LIBS += -lqtadvanceddockingd
else:unix: LIBS += -lAdvancedDockingSystem
INCLUDEPATH += ../src

View File

@ -690,13 +690,13 @@ void CDockAreaWidget::updateTitleBarVisibility()
//============================================================================
void CDockAreaWidget::saveState(QXmlStreamWriter& s) const
{
s.writeStartElement("DockAreaWidget");
s.writeStartElement("Area");
s.writeAttribute("Tabs", QString::number(d->ContentsLayout->count()));
auto CurrentDockWidget = currentDockWidget();
QString Name = CurrentDockWidget ? CurrentDockWidget->objectName() : "";
s.writeAttribute("CurrentDockWidget", Name);
s.writeAttribute("Current", Name);
qDebug() << "CDockAreaWidget::saveState TabCount: " << d->ContentsLayout->count()
<< " CurrentDockWidge: " << Name;
<< " Current: " << Name;
for (int i = 0; i < d->ContentsLayout->count(); ++i)
{
dockWidget(i)->saveState(s);

View File

@ -58,7 +58,7 @@ private:
DockAreaWidgetPrivate* d; ///< private data (pimpl)
friend struct DockAreaWidgetPrivate;
friend class CDockContainerWidget;
friend class DockContainerWidgetPrivate;
friend struct DockContainerWidgetPrivate;
friend class CDockWidgetTab;
friend struct DockWidgetPrivate;
friend class CDockWidget;

View File

@ -44,7 +44,6 @@
#include "DockWidget.h"
#include "FloatingDockContainer.h"
#include "DockOverlay.h"
#include "DockStateSerialization.h"
#include "ads_globals.h"
#include "DockSplitter.h"
@ -101,7 +100,7 @@ public:
unsigned int zOrderIndex = 0;
QList<CDockAreaWidget*> DockAreas;
QGridLayout* Layout = nullptr;
QSplitter* RootSplitter;
QSplitter* RootSplitter = nullptr;
bool isFloating = false;
CDockAreaWidget* LastAddedAreaCache[5]{0, 0, 0, 0, 0};
int VisibleDockAreaCount = -1;
@ -233,6 +232,18 @@ public:
emit _this->dockAreasAdded();
}
/**
* Helper function for creation of new splitter
*/
CDockSplitter* newSplitter(Qt::Orientation orientation, QWidget* parent = 0)
{
CDockSplitter* s = new CDockSplitter(orientation, parent);
s->setOpaqueResize(DockManager->configFlags().testFlag(CDockManager::OpaqueSplitterResize));
s->setChildrenCollapsible(false);
return s;
}
// private slots: ------------------------------------------------------------
void onDockAreaViewToggled(bool Visible)
{
@ -290,7 +301,7 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float
}
else if (Splitter->orientation() != InsertParam.orientation())
{
QSplitter* NewSplitter = internal::newSplitter(InsertParam.orientation());
QSplitter* NewSplitter = newSplitter(InsertParam.orientation());
QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter);
NewSplitter->addWidget(Splitter);
Splitter = NewSplitter;
@ -337,14 +348,35 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin
CDockAreaWidget* TargetArea, DockWidgetArea area)
{
CDockContainerWidget* FloatingContainer = FloatingWidget->dockContainer();
if (area == CenterDockWidgetArea)
// Dropping into center means all dock widgets in the dropped floating
// widget will become tabs of the drop area
if (CenterDockWidgetArea == area)
{
auto NewDockWidgets = FloatingContainer->dockWidgets();
auto TopLevelDockArea = FloatingContainer->topLevelDockArea();
int NewCurrentIndex = -1;
// If the floating widget contains only one single dock are, then the
// current dock widget of the dock area will also be the future current
// dock widget in the drop area.
if (TopLevelDockArea)
{
NewCurrentIndex = TopLevelDockArea->currentIndex();
}
for (int i = 0; i < NewDockWidgets.count(); ++i)
{
TargetArea->insertDockWidget(i, NewDockWidgets[i], false);
CDockWidget* DockWidget = NewDockWidgets[i];
TargetArea->insertDockWidget(i, DockWidget, false);
// If the floating widget contains multiple visible dock areas, then we
// simply pick the first visible open dock widget and make it
// the current one.
if (NewCurrentIndex < 0 && !DockWidget->isClosed())
{
NewCurrentIndex = i;
}
}
TargetArea->setCurrentIndex(0); // make the topmost widget active
TargetArea->setCurrentIndex(NewCurrentIndex);
FloatingWidget->deleteLater();
TargetArea->updateTitleBarVisibility();
return;
@ -357,7 +389,7 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin
if (!TargetAreaSplitter)
{
QSplitter* Splitter = internal::newSplitter(InsertParam.orientation());
QSplitter* Splitter = newSplitter(InsertParam.orientation());
Layout->replaceWidget(TargetArea, Splitter);
Splitter->addWidget(TargetArea);
TargetAreaSplitter = Splitter;
@ -383,7 +415,7 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin
}
else
{
QSplitter* NewSplitter = internal::newSplitter(InsertParam.orientation());
QSplitter* NewSplitter = newSplitter(InsertParam.orientation());
if ((FloatingSplitter->orientation() != InsertParam.orientation()) && FloatingSplitter->count() > 1)
{
NewSplitter->addWidget(Widget);
@ -455,7 +487,7 @@ void DockContainerWidgetPrivate::saveChildNodesState(QXmlStreamWriter& s, QWidge
if (Splitter)
{
s.writeStartElement("Splitter");
s.writeAttribute("Orientation", QString::number(Splitter->orientation()));
s.writeAttribute("Orientation", (Splitter->orientation() == Qt::Horizontal) ? "-" : "|");
s.writeAttribute("Count", QString::number(Splitter->count()));
qDebug() << "NodeSplitter orient: " << Splitter->orientation()
<< " WidgetCont: " << Splitter->count();
@ -488,8 +520,17 @@ bool DockContainerWidgetPrivate::restoreSplitter(QXmlStreamReader& s,
QWidget*& CreatedWidget, bool Testing)
{
bool Ok;
int Orientation = s.attributes().value("Orientation").toInt(&Ok);
if (!Ok)
QString OrientationStr = s.attributes().value("Orientation").toString();
int Orientation;
if (OrientationStr.startsWith("-"))
{
Orientation = Qt::Horizontal;
}
else if (OrientationStr.startsWith("|"))
{
Orientation = Qt::Vertical;
}
else
{
return false;
}
@ -504,7 +545,7 @@ bool DockContainerWidgetPrivate::restoreSplitter(QXmlStreamReader& s,
QSplitter* Splitter = nullptr;
if (!Testing)
{
Splitter = internal::newSplitter((Qt::Orientation)Orientation);
Splitter = newSplitter((Qt::Orientation)Orientation);
}
bool Visible = false;
QList<int> Sizes;
@ -516,7 +557,7 @@ bool DockContainerWidgetPrivate::restoreSplitter(QXmlStreamReader& s,
{
Result = restoreSplitter(s, ChildNode, Testing);
}
else if (s.name() == "DockAreaWidget")
else if (s.name() == "Area")
{
Result = restoreDockArea(s, ChildNode, Testing);
}
@ -593,8 +634,8 @@ bool DockContainerWidgetPrivate::restoreDockArea(QXmlStreamReader& s,
}
QString CurrentDockWidget = s.attributes().value("CurrentDockWidget").toString();
qDebug() << "Restore NodeDockArea Tabs: " << Tabs << " CurrentDockWidget: "
QString CurrentDockWidget = s.attributes().value("Current").toString();
qDebug() << "Restore NodeDockArea Tabs: " << Tabs << " Current: "
<< CurrentDockWidget;
CDockAreaWidget* DockArea = nullptr;
@ -605,12 +646,12 @@ bool DockContainerWidgetPrivate::restoreDockArea(QXmlStreamReader& s,
while (s.readNextStartElement())
{
if (s.name() != "DockWidget")
if (s.name() != "Widget")
{
continue;
}
auto ObjectName = s.attributes().value("ObjectName");
auto ObjectName = s.attributes().value("Name");
if (ObjectName.isEmpty())
{
return false;
@ -673,7 +714,7 @@ bool DockContainerWidgetPrivate::restoreChildNodes(QXmlStreamReader& s,
Result = restoreSplitter(s, CreatedWidget, Testing);
qDebug() << "Splitter";
}
else if (s.name() == "DockAreaWidget")
else if (s.name() == "Area")
{
Result = restoreDockArea(s, CreatedWidget, Testing);
qDebug() << "DockAreaWidget";
@ -720,7 +761,7 @@ void DockContainerWidgetPrivate::addDockArea(CDockAreaWidget* NewDockArea, DockW
}
else
{
QSplitter* NewSplitter = internal::newSplitter(InsertParam.orientation());
QSplitter* NewSplitter = newSplitter(InsertParam.orientation());
if (InsertParam.append())
{
QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter);
@ -820,7 +861,7 @@ CDockAreaWidget* DockContainerWidgetPrivate::dockWidgetIntoDockArea(DockWidgetAr
else
{
qDebug() << "TargetAreaSplitter->orientation() != InsertParam.orientation()";
QSplitter* NewSplitter = internal::newSplitter(InsertParam.orientation());
QSplitter* NewSplitter = newSplitter(InsertParam.orientation());
NewSplitter->addWidget(TargetDockArea);
insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append());
TargetAreaSplitter->insertWidget(index, NewSplitter);
@ -837,20 +878,24 @@ CDockContainerWidget::CDockContainerWidget(CDockManager* DockManager, QWidget *p
QFrame(parent),
d(new DockContainerWidgetPrivate(this))
{
d->isFloating = floatingWidget() != nullptr;
d->DockManager = DockManager;
if (DockManager != this)
{
d->DockManager->registerDockContainer(this);
}
d->isFloating = floatingWidget() != nullptr;
d->Layout = new QGridLayout();
d->Layout->setContentsMargins(0, 1, 0, 1);
d->Layout->setSpacing(0);
setLayout(d->Layout);
d->RootSplitter = internal::newSplitter(Qt::Horizontal);
d->Layout->addWidget(d->RootSplitter);
// The function d->newSplitter() accesses the config flags from dock
// manager which in turn requires a properly constructed dock manager.
// If this dock container is the dock manager, then it is not properly
// constructed yet because this base class constructor is called before
// the constructor of the DockManager private class
if (DockManager != this)
{
d->DockManager->registerDockContainer(this);
createRootSplitter();
}
}
//============================================================================
@ -1131,7 +1176,7 @@ void CDockContainerWidget::saveState(QXmlStreamWriter& s) const
qDebug() << "CDockContainerWidget::saveState isFloating "
<< isFloating();
s.writeStartElement("DockContainerWidget");
s.writeStartElement("Container");
s.writeAttribute("Floating", QString::number(isFloating() ? 1 : 0));
if (isFloating())
{
@ -1193,7 +1238,7 @@ bool CDockContainerWidget::restoreState(QXmlStreamReader& s, bool Testing)
// and we need to create a new empty root splitter
if (!NewRootSplitter)
{
NewRootSplitter = internal::newSplitter(Qt::Horizontal);
NewRootSplitter = d->newSplitter(Qt::Horizontal);
}
d->Layout->replaceWidget(d->RootSplitter, NewRootSplitter);
@ -1212,6 +1257,18 @@ QSplitter* CDockContainerWidget::rootSplitter() const
}
//============================================================================
void CDockContainerWidget::createRootSplitter()
{
if (d->RootSplitter)
{
return;
}
d->RootSplitter = d->newSplitter(Qt::Horizontal);
d->Layout->addWidget(d->RootSplitter);
}
//============================================================================
void CDockContainerWidget::dumpLayout()
{

View File

@ -78,6 +78,11 @@ protected:
*/
QSplitter* rootSplitter() const;
/**
* Helper function for creation of the root splitter
*/
void createRootSplitter();
/**
* Drop floating widget into the container
*/

View File

@ -51,7 +51,6 @@
#include "DockOverlay.h"
#include "DockWidget.h"
#include "ads_globals.h"
#include "DockStateSerialization.h"
#include "DockAreaWidget.h"
@ -217,12 +216,12 @@ bool DockManagerPrivate::restoreStateFromXml(const QByteArray &state, int versi
}
bool Result = true;
int DockContainers = s.attributes().value("DockContainers").toInt();
int DockContainers = s.attributes().value("Containers").toInt();
qDebug() << DockContainers;
int DockContainerCount = 0;
while (s.readNextStartElement())
{
if (s.name() == "DockContainerWidget")
if (s.name() == "Container")
{
Result = restoreContainer(DockContainerCount, s, Testing);
if (!Result)
@ -391,12 +390,12 @@ void DockManagerPrivate::addActionToMenu(QAction* Action, QMenu* Menu, bool Inse
}
//============================================================================
CDockManager::CDockManager(QWidget *parent) :
CDockContainerWidget(this, parent),
d(new DockManagerPrivate(this))
{
createRootSplitter();
QMainWindow* MainWindow = dynamic_cast<QMainWindow*>(parent);
if (MainWindow)
{
@ -498,7 +497,7 @@ QByteArray CDockManager::saveState(eXmlMode XmlMode, int version) const
s.writeStartDocument();
s.writeStartElement("QtAdvancedDockingSystem");
s.writeAttribute("Version", QString::number(version));
s.writeAttribute("DockContainers", QString::number(d->Containers.count()));
s.writeAttribute("Containers", QString::number(d->Containers.count()));
for (auto Container : d->Containers)
{
Container->saveState(s);
@ -606,10 +605,7 @@ void CDockManager::addPerspective(const QString& UniquePrespectiveName)
//============================================================================
void CDockManager::removePerspective(const QString& Name)
{
if (d->Perspectives.remove(Name))
{
emit perspectiveListChanged();
}
removePerspectives({Name});
}
@ -624,6 +620,7 @@ void CDockManager::removePerspectives(const QStringList& Names)
if (Count)
{
emit perspectivesRemoved();
emit perspectiveListChanged();
}
}

View File

@ -123,7 +123,8 @@ public:
ActiveTabHasCloseButton = 0x01, //!< If this flag is set, the active tab in a tab area has a close button
DockAreaHasCloseButton = 0x02, //!< If the flag is set each dock area has a close button
DockAreaCloseButtonClosesTab = 0x04,//!< If the flag is set, the dock area close button closes the active tab, if not set, it closes the complete cock area
DefaultConfig = ActiveTabHasCloseButton | DockAreaHasCloseButton, ///< the default configuration
OpaqueSplitterResize = 0x08, //!< See QSplitter::setOpaqueResize() documentation
DefaultConfig = ActiveTabHasCloseButton | DockAreaHasCloseButton | OpaqueSplitterResize, ///< the default configuration
};
Q_DECLARE_FLAGS(ConfigFlags, eConfigFlag)
@ -330,6 +331,11 @@ signals:
*/
void perspectiveListChanged();
/**
* This signal is emitted if perspectives have been removed
*/
void perspectivesRemoved();
/**
* This signal is emitted, if the restore function is called, just before
* the dock manager starts restoring the state.

View File

@ -52,7 +52,8 @@ CDockSplitter::CDockSplitter(QWidget *parent)
: QSplitter(parent),
d(new DockSplitterPrivate(this))
{
setProperty("ads-splitter", true);
setChildrenCollapsible(false);
}

View File

@ -1,32 +0,0 @@
/*******************************************************************************
** Qt Advanced Docking System
** Copyright (C) 2017 Uwe Kindler
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
//============================================================================
/// \file DockStateSerialization.cpp
/// \author Uwe Kindler
/// \date 26.02.2017
/// \brief Serialization related data, constants and stuff
//============================================================================
//============================================================================
// INCLUDES
//============================================================================
#include "DockStateSerialization.h"

View File

@ -1,55 +0,0 @@
#ifndef DockStateSerializationH
#define DockStateSerializationH
/*******************************************************************************
** Qt Advanced Docking System
** Copyright (C) 2017 Uwe Kindler
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
//============================================================================
/// \file DockStateSerialization.h
/// \author Uwe Kindler
/// \date 26.02.2017
/// \brief Declaration of serialization related data, constants and stuff
//============================================================================
//============================================================================
// INCLUDES
//============================================================================
namespace ads
{
namespace internal
{
// sentinel values used to validate state data
enum VersionMarkers
{
VersionMarker = 0xff,
ContainerMarker = 0xfe,
SplitterMarker = 0xfd,
DockAreaMarker = 0xfc,
DockWidgetMarker = 0xfb
};
static const bool RestoreTesting = true;
static const bool Restore = false;
} // internal
} // namespace ads
//-----------------------------------------------------------------------------
#endif // DockManagerH

View File

@ -47,7 +47,6 @@
#include "DockAreaWidget.h"
#include "DockManager.h"
#include "FloatingDockContainer.h"
#include "DockStateSerialization.h"
#include "DockSplitter.h"
#include "ads_globals.h"
@ -183,7 +182,7 @@ void DockWidgetPrivate::setupToolBar()
{
ToolBar = new QToolBar(_this);
ToolBar->setObjectName("dockWidgetToolBar");
Layout->addWidget(ToolBar);
Layout->insertWidget(0, ToolBar);
ToolBar->setIconSize(QSize(16, 16));
ToolBar->toggleViewAction()->setEnabled(false);
ToolBar->toggleViewAction()->setVisible(false);
@ -474,8 +473,8 @@ void CDockWidget::setDockArea(CDockAreaWidget* DockArea)
//============================================================================
void CDockWidget::saveState(QXmlStreamWriter& s) const
{
s.writeStartElement("DockWidget");
s.writeAttribute("ObjectName", objectName());
s.writeStartElement("Widget");
s.writeAttribute("Name", objectName());
s.writeAttribute("Closed", QString::number(d->Closed ? 1 : 0));
s.writeEndElement();
}

View File

@ -74,7 +74,7 @@ struct DockWidgetTabPrivate
{
CDockWidgetTab* _this;
CDockWidget* DockWidget;
QLabel* IconLabel;
QLabel* IconLabel = nullptr;
tTabLabel* TitleLabel;
QPoint DragStartMousePosition;
bool IsActiveTab = false;
@ -416,15 +416,35 @@ CDockAreaWidget* CDockWidgetTab::dockAreaWidget() const
void CDockWidgetTab::setIcon(const QIcon& Icon)
{
QBoxLayout* Layout = qobject_cast<QBoxLayout*>(layout());
if (!d->IconLabel && Icon.isNull())
{
return;
}
if (!d->IconLabel)
{
d->IconLabel = new QLabel();
d->IconLabel->setAlignment(Qt::AlignVCenter);
d->IconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
d->IconLabel->setToolTip(d->TitleLabel->toolTip());
Layout->insertWidget(0, d->IconLabel, Qt::AlignVCenter);
Layout->insertSpacing(1, qRound(1.5 * Layout->contentsMargins().left() / 2.0));
}
else if (Icon.isNull())
{
// Remove icon label and spacer item
Layout->removeWidget(d->IconLabel);
Layout->removeItem(Layout->itemAt(0));
delete d->IconLabel;
d->IconLabel = nullptr;
}
d->Icon = Icon;
d->IconLabel = new QLabel();
d->IconLabel->setAlignment(Qt::AlignVCenter);
d->IconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
d->IconLabel->setToolTip(d->TitleLabel->toolTip());
d->IconLabel->setPixmap(Icon.pixmap(this->windowHandle(), QSize(16, 16)));
Layout->insertWidget(0, d->IconLabel, Qt::AlignVCenter);
Layout->insertSpacing(1, qRound(1.5 * Layout->contentsMargins().left() / 2.0));
d->IconLabel->setVisible(true);
if (d->IconLabel)
{
d->IconLabel->setPixmap(Icon.pixmap(this->windowHandle(), QSize(16, 16)));
d->IconLabel->setVisible(true);
}
}

View File

@ -40,16 +40,6 @@ namespace ads
namespace internal
{
//============================================================================
QSplitter* newSplitter(Qt::Orientation orientation, QWidget* parent)
{
QSplitter* s = new CDockSplitter(orientation, parent);
s->setProperty("ads-splitter", QVariant(true));
s->setChildrenCollapsible(false);
s->setOpaqueResize(false);
return s;
}
//============================================================================
void replaceSplitterWidget(QSplitter* Splitter, QWidget* From, QWidget* To)
{

View File

@ -33,6 +33,7 @@
#include <QPair>
#include <QtCore/QtGlobal>
#include <QPixmap>
#include <QWidget>
#ifdef ADS_SHARED_EXPORT
#define ADS_EXPORT Q_DECL_EXPORT
@ -73,12 +74,8 @@ enum TitleBarButton
namespace internal
{
/**
* Helper function to create new splitter widgets
*/
QSplitter* newSplitter(Qt::Orientation orientation, QWidget* parent = 0);
static const bool RestoreTesting = true;
static const bool Restore = false;
/**
* Replace the from widget in the given splitter with the To widget

View File

@ -1,7 +1,7 @@
ADS_ROOT = $${PWD}/..
ADS_OUT_ROOT = $${OUT_PWD}/..
TARGET = $$qtLibraryTarget(AdvancedDockingSystem)
TARGET = $$qtLibraryTarget(qtadvanceddocking)
TEMPLATE = lib
DESTDIR = $${ADS_OUT_ROOT}/lib
QT += core gui widgets