2017-02-27 21:15:20 +08:00
|
|
|
/*******************************************************************************
|
|
|
|
** QtAdcancedDockingSystem
|
|
|
|
** Copyright (C) 2017 Uwe Kindler
|
|
|
|
**
|
|
|
|
** This program is free software: you can redistribute it and/or modify
|
|
|
|
** it under the terms of the GNU General Public License as published by
|
|
|
|
** the Free Software Foundation, either version 3 of the License, or
|
|
|
|
** (at your option) any later version.
|
|
|
|
**
|
|
|
|
** This program 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 General Public License for more details.
|
|
|
|
**
|
|
|
|
** You should have received a copy of the GNU General Public License
|
|
|
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
******************************************************************************/
|
|
|
|
|
2017-02-27 01:13:56 +08:00
|
|
|
|
2017-02-25 05:44:02 +08:00
|
|
|
//============================================================================
|
|
|
|
/// \file DockManager.cpp
|
|
|
|
/// \author Uwe Kindler
|
2017-02-27 01:13:56 +08:00
|
|
|
/// \date 26.02.2017
|
|
|
|
/// \brief Implementation of CDockManager class
|
2017-02-25 05:44:02 +08:00
|
|
|
//============================================================================
|
|
|
|
|
2017-02-27 21:15:20 +08:00
|
|
|
|
2017-02-25 05:44:02 +08:00
|
|
|
//============================================================================
|
|
|
|
// INCLUDES
|
|
|
|
//============================================================================
|
|
|
|
#include "DockManager.h"
|
|
|
|
|
2017-02-27 01:13:56 +08:00
|
|
|
#include <QMainWindow>
|
2017-03-01 21:09:56 +08:00
|
|
|
#include <QList>
|
2017-03-27 16:41:27 +08:00
|
|
|
#include <QMap>
|
2017-03-28 16:57:03 +08:00
|
|
|
#include <QVariant>
|
2017-03-28 18:01:27 +08:00
|
|
|
#include <QDebug>
|
2017-03-28 19:05:18 +08:00
|
|
|
#include <QFile>
|
|
|
|
#include <QApplication>
|
2017-03-29 04:38:47 +08:00
|
|
|
#include <QAction>
|
2017-03-01 21:09:56 +08:00
|
|
|
|
|
|
|
#include "FloatingDockContainer.h"
|
2017-03-01 23:13:37 +08:00
|
|
|
#include "DockOverlay.h"
|
2017-03-27 16:41:27 +08:00
|
|
|
#include "DockWidget.h"
|
|
|
|
#include "ads_globals.h"
|
|
|
|
#include "DockStateSerialization.h"
|
2017-03-28 16:57:03 +08:00
|
|
|
#include "DockWidgetTitleBar.h"
|
2017-03-29 04:38:47 +08:00
|
|
|
#include "DockAreaWidget.h"
|
2017-02-27 01:13:56 +08:00
|
|
|
|
2017-02-25 05:44:02 +08:00
|
|
|
namespace ads
|
|
|
|
{
|
2017-03-23 22:57:15 +08:00
|
|
|
|
2017-02-27 01:13:56 +08:00
|
|
|
/**
|
|
|
|
* Private data class of CDockManager class (pimpl)
|
|
|
|
*/
|
|
|
|
struct DockManagerPrivate
|
|
|
|
{
|
|
|
|
CDockManager* _this;
|
2017-03-01 21:09:56 +08:00
|
|
|
QList<CFloatingDockContainer*> FloatingWidgets;
|
2017-03-01 23:13:37 +08:00
|
|
|
QList<CDockContainerWidget*> Containers;
|
|
|
|
CDockOverlay* ContainerOverlay;
|
|
|
|
CDockOverlay* DockAreaOverlay;
|
2017-03-27 16:41:27 +08:00
|
|
|
QMap<QString, CDockWidget*> DockWidgetsMap;
|
2017-02-27 01:13:56 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Private data constructor
|
|
|
|
*/
|
|
|
|
DockManagerPrivate(CDockManager* _public);
|
2017-03-23 22:57:15 +08:00
|
|
|
|
2017-03-27 16:41:27 +08:00
|
|
|
/**
|
|
|
|
* Checks if the given data stream is a valid docking system state
|
|
|
|
* file.
|
|
|
|
*/
|
|
|
|
bool checkFormat(const QByteArray &state, int version);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Restores the state
|
|
|
|
*/
|
|
|
|
bool restoreState(const QByteArray &state, int version);
|
2017-03-28 16:57:03 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Restores the container with the given index
|
|
|
|
*/
|
|
|
|
bool restoreContainer(int Index, QDataStream& stream, bool Testing);
|
2017-03-28 19:05:18 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Loads the stylesheet
|
|
|
|
*/
|
|
|
|
void loadStylesheet();
|
2017-02-27 01:13:56 +08:00
|
|
|
};
|
|
|
|
// struct DockManagerPrivate
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
DockManagerPrivate::DockManagerPrivate(CDockManager* _public) :
|
|
|
|
_this(_public)
|
|
|
|
{
|
2017-02-25 05:44:02 +08:00
|
|
|
|
2017-02-27 01:13:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-28 19:05:18 +08:00
|
|
|
//============================================================================
|
|
|
|
void DockManagerPrivate::loadStylesheet()
|
|
|
|
{
|
|
|
|
QString Result;
|
|
|
|
QFile StyleSheetFile(":ads/stylesheets/default.css");
|
|
|
|
StyleSheetFile.open(QIODevice::ReadOnly);
|
|
|
|
QTextStream StyleSheetStream(&StyleSheetFile);
|
|
|
|
Result = StyleSheetStream.readAll();
|
|
|
|
StyleSheetFile.close();
|
|
|
|
_this->setStyleSheet(Result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-27 16:41:27 +08:00
|
|
|
//============================================================================
|
|
|
|
bool DockManagerPrivate::checkFormat(const QByteArray &state, int version)
|
|
|
|
{
|
|
|
|
if (state.isEmpty())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
QByteArray sd = state;
|
|
|
|
QDataStream stream(&sd, QIODevice::ReadOnly);
|
|
|
|
|
|
|
|
int marker;
|
|
|
|
int v;
|
|
|
|
stream >> marker;
|
|
|
|
stream >> v;
|
|
|
|
|
|
|
|
if (stream.status() != QDataStream::Ok || marker != internal::VersionMarker || v != version)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Result = true;
|
|
|
|
int ContainerCount;
|
|
|
|
stream >> ContainerCount;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < ContainerCount; ++i)
|
|
|
|
{
|
|
|
|
if (!Containers[0]->restoreState(stream, internal::RestoreTesting))
|
|
|
|
{
|
|
|
|
Result = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-28 16:57:03 +08:00
|
|
|
//============================================================================
|
|
|
|
bool DockManagerPrivate::restoreContainer(int Index, QDataStream& stream, bool Testing)
|
|
|
|
{
|
|
|
|
if (Index >= Containers.count())
|
|
|
|
{
|
|
|
|
CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(_this);
|
|
|
|
return FloatingWidget->restoreState(stream, internal::Restore);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-03-28 18:01:27 +08:00
|
|
|
qDebug() << "d->Containers[i]->restoreState ";
|
2017-03-28 16:57:03 +08:00
|
|
|
return Containers[Index]->restoreState(stream, internal::Restore);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-27 16:41:27 +08:00
|
|
|
//============================================================================
|
|
|
|
bool DockManagerPrivate::restoreState(const QByteArray &state, int version)
|
|
|
|
{
|
|
|
|
if (state.isEmpty())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
QByteArray sd = state;
|
|
|
|
QDataStream stream(&sd, QIODevice::ReadOnly);
|
|
|
|
|
|
|
|
int marker;
|
|
|
|
int v;
|
|
|
|
stream >> marker;
|
|
|
|
stream >> v;
|
|
|
|
|
|
|
|
if (stream.status() != QDataStream::Ok || marker != internal::VersionMarker || v != version)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Result = true;
|
|
|
|
int ContainerCount;
|
|
|
|
stream >> ContainerCount;
|
2017-03-28 18:01:27 +08:00
|
|
|
qDebug() << "ContainerCount " << ContainerCount;
|
2017-03-27 16:41:27 +08:00
|
|
|
int i;
|
|
|
|
for (i = 0; i < ContainerCount; ++i)
|
|
|
|
{
|
2017-03-28 16:57:03 +08:00
|
|
|
Result = restoreContainer(i, stream, internal::Restore);
|
|
|
|
if (!Result)
|
2017-03-27 16:41:27 +08:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete remaining empty floating widgets
|
|
|
|
int FloatingWidgetIndex = i - 1;
|
|
|
|
int DeleteCount = FloatingWidgets.count() - FloatingWidgetIndex;
|
2017-03-29 04:38:47 +08:00
|
|
|
/*std::cout << "DeleteCount " << DeleteCount << " FloatingWidgets.count() "
|
|
|
|
<< FloatingWidgets.count() << " FloatingWdgetIndex " << FloatingWidgetIndex << std::endl;*/
|
2017-03-27 16:41:27 +08:00
|
|
|
for (int i = 0; i < DeleteCount; ++i)
|
|
|
|
{
|
2017-03-29 04:38:47 +08:00
|
|
|
FloatingWidgets[FloatingWidgetIndex + i]->deleteLater();
|
2017-03-27 16:41:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return Result;
|
2017-03-23 22:57:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-27 01:13:56 +08:00
|
|
|
//============================================================================
|
|
|
|
CDockManager::CDockManager(QWidget *parent) :
|
|
|
|
CDockContainerWidget(this, parent),
|
|
|
|
d(new DockManagerPrivate(this))
|
|
|
|
{
|
|
|
|
QMainWindow* MainWindow = dynamic_cast<QMainWindow*>(parent);
|
|
|
|
if (MainWindow)
|
|
|
|
{
|
|
|
|
MainWindow->setCentralWidget(this);
|
|
|
|
}
|
2017-03-01 23:13:37 +08:00
|
|
|
|
2017-03-02 18:43:48 +08:00
|
|
|
d->DockAreaOverlay = new CDockOverlay(this, CDockOverlay::ModeDockAreaOverlay);
|
|
|
|
d->ContainerOverlay = new CDockOverlay(this, CDockOverlay::ModeContainerOverlay);
|
2017-03-01 23:13:37 +08:00
|
|
|
d->Containers.append(this);
|
2017-03-28 19:05:18 +08:00
|
|
|
d->loadStylesheet();
|
2017-02-27 01:13:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
CDockManager::~CDockManager()
|
|
|
|
{
|
2017-03-03 22:47:03 +08:00
|
|
|
auto FloatingWidgets = d->FloatingWidgets;
|
|
|
|
for (auto FloatingWidget : FloatingWidgets)
|
|
|
|
{
|
|
|
|
delete FloatingWidget;
|
|
|
|
}
|
2017-02-27 01:13:56 +08:00
|
|
|
delete d;
|
|
|
|
}
|
2017-03-01 21:09:56 +08:00
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CDockManager::registerFloatingWidget(CFloatingDockContainer* FloatingWidget)
|
|
|
|
{
|
|
|
|
d->FloatingWidgets.append(FloatingWidget);
|
2017-03-28 18:01:27 +08:00
|
|
|
qDebug() << "d->FloatingWidgets.count() " << d->FloatingWidgets.count();
|
2017-03-01 21:09:56 +08:00
|
|
|
}
|
2017-03-01 23:13:37 +08:00
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CDockManager::removeFloatingWidget(CFloatingDockContainer* FloatingWidget)
|
|
|
|
{
|
|
|
|
d->FloatingWidgets.removeAll(FloatingWidget);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CDockManager::registerDockContainer(CDockContainerWidget* DockContainer)
|
|
|
|
{
|
|
|
|
d->Containers.append(DockContainer);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CDockManager::removeDockContainer(CDockContainerWidget* DockContainer)
|
|
|
|
{
|
|
|
|
if (this != DockContainer)
|
|
|
|
{
|
|
|
|
d->Containers.removeAll(DockContainer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
CDockOverlay* CDockManager::containerOverlay() const
|
|
|
|
{
|
|
|
|
return d->ContainerOverlay;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
CDockOverlay* CDockManager::dockAreaOverlay() const
|
|
|
|
{
|
|
|
|
return d->DockAreaOverlay;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
const QList<CDockContainerWidget*> CDockManager::dockContainers() const
|
|
|
|
{
|
|
|
|
return d->Containers;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
const QList<CFloatingDockContainer*> CDockManager::floatingWidgets() const
|
|
|
|
{
|
|
|
|
return d->FloatingWidgets;
|
|
|
|
}
|
2017-03-02 22:49:53 +08:00
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
unsigned int CDockManager::zOrderIndex() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2017-03-23 22:57:15 +08:00
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
QByteArray CDockManager::saveState(int version) const
|
|
|
|
{
|
|
|
|
QByteArray data;
|
|
|
|
QDataStream stream(&data, QIODevice::WriteOnly);
|
2017-03-27 16:41:27 +08:00
|
|
|
stream << internal::VersionMarker;
|
2017-03-23 22:57:15 +08:00
|
|
|
stream << version;
|
|
|
|
|
|
|
|
stream << d->Containers.count();
|
|
|
|
for (auto Container : d->Containers)
|
|
|
|
{
|
|
|
|
Container->saveState(stream);
|
|
|
|
}
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
bool CDockManager::restoreState(const QByteArray &state, int version)
|
|
|
|
{
|
2017-03-27 16:41:27 +08:00
|
|
|
if (!d->checkFormat(state, version))
|
2017-03-23 22:57:15 +08:00
|
|
|
{
|
2017-03-28 18:01:27 +08:00
|
|
|
qDebug() << "checkFormat: Error checking format!!!!!!!";
|
2017-03-27 16:41:27 +08:00
|
|
|
return false;
|
2017-03-23 22:57:15 +08:00
|
|
|
}
|
|
|
|
|
2017-03-28 16:57:03 +08:00
|
|
|
for (auto DockWidget : d->DockWidgetsMap)
|
|
|
|
{
|
|
|
|
DockWidget->setProperty("dirty", true);
|
|
|
|
}
|
|
|
|
|
2017-03-27 16:41:27 +08:00
|
|
|
if (!d->restoreState(state, version))
|
2017-03-23 22:57:15 +08:00
|
|
|
{
|
2017-03-28 18:01:27 +08:00
|
|
|
qDebug() << "restoreState: Error restoring state!!!!!!!";
|
2017-03-27 16:41:27 +08:00
|
|
|
return false;
|
2017-03-23 22:57:15 +08:00
|
|
|
}
|
|
|
|
|
2017-03-28 16:57:03 +08:00
|
|
|
// All dock widgets, that have not been processed in the restore state
|
|
|
|
// function are invisible to the user now and have no assigned dock area
|
|
|
|
// The do not belong to any dock container, until the user toggles the
|
|
|
|
// toggle view action the next time
|
|
|
|
for (auto DockWidget : d->DockWidgetsMap)
|
|
|
|
{
|
|
|
|
if (DockWidget->property("dirty").toBool())
|
|
|
|
{
|
|
|
|
DockWidget->flagAsUnassigned();
|
|
|
|
}
|
2017-03-29 04:38:47 +08:00
|
|
|
else if (!DockWidget->property("closed").toBool())
|
|
|
|
{
|
|
|
|
DockWidget->toggleView(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-29 17:09:05 +08:00
|
|
|
// Now all dock areas are properly restored and we setup the index of
|
|
|
|
// The dock areas because the previous toggleView() action has changed
|
|
|
|
// the dock area index
|
2017-03-29 04:38:47 +08:00
|
|
|
for (auto DockContainer : d->Containers)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < DockContainer->dockAreaCount(); ++i)
|
|
|
|
{
|
|
|
|
CDockAreaWidget* DockArea = DockContainer->dockArea(i);
|
|
|
|
int CurrentIndex = DockArea->property("currentIndex").toInt();
|
|
|
|
if (CurrentIndex < DockArea->count() && DockArea->count() > 1 && CurrentIndex > -1)
|
|
|
|
{
|
|
|
|
DockArea->setCurrentIndex(CurrentIndex);
|
|
|
|
}
|
|
|
|
}
|
2017-03-28 16:57:03 +08:00
|
|
|
}
|
|
|
|
|
2017-03-27 16:41:27 +08:00
|
|
|
return true;
|
|
|
|
}
|
2017-03-23 22:57:15 +08:00
|
|
|
|
|
|
|
|
2017-03-27 16:41:27 +08:00
|
|
|
//============================================================================
|
|
|
|
CDockAreaWidget* CDockManager::addDockWidget(DockWidgetArea area,
|
|
|
|
CDockWidget* Dockwidget, CDockAreaWidget* DockAreaWidget)
|
|
|
|
{
|
|
|
|
d->DockWidgetsMap.insert(Dockwidget->objectName(), Dockwidget);
|
|
|
|
return CDockContainerWidget::addDockWidget(area, Dockwidget, DockAreaWidget);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
CDockWidget* CDockManager::findDockWidget(const QString& ObjectName)
|
|
|
|
{
|
|
|
|
return d->DockWidgetsMap.value(ObjectName, nullptr);
|
2017-03-23 22:57:15 +08:00
|
|
|
}
|
2017-02-25 05:44:02 +08:00
|
|
|
} // namespace ads
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// EOF DockManager.cpp
|