Files
KDDockWidgets/src/LayoutSaver_p.h
2020-07-24 18:16:13 -04:00

318 lines
8.1 KiB
C++

/*
This file is part of KDDockWidgets.
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
Author: Sérgio Martins <sergio.martins@kdab.com>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
Contact KDAB at <info@kdab.com> for commercial licensing options.
*/
#ifndef KD_LAYOUTSAVER_P_H
#define KD_LAYOUTSAVER_P_H
#include "LayoutSaver.h"
#include "KDDockWidgets.h"
#include <QRect>
#include <QDebug>
#include <QScreen>
#include <QApplication>
#include <QJsonDocument>
#include <memory>
#define MULTISPLITTER_LAYOUT_MAGIC_MARKER "bac9948e-5f1b-4271-acc5-07f1708e2611"
/**
* Bump whenever the format changes, so we can still load old layouts.
* version 1: Initial version
* version 2: Introduced MainWindow::screenSize and FloatingWindow::screenSize
* version 3: New layouting engine
*/
#define KDDOCKWIDGETS_SERIALIZATION_VERSION 3
namespace KDDockWidgets {
template <typename T>
typename T::List fromVariantList(const QVariantList &listV)
{
typename T::List result;
result.reserve(listV.size());
for (const QVariant &v : listV) {
T t;
t.fromVariantMap(v.toMap());
result.push_back(t);
}
return result;
}
template <typename T>
QVariantList toVariantList(const typename T::List &list)
{
QVariantList result;
result.reserve(list.size());
for (const T &v : list)
result.push_back(v.toVariantMap());
return result;
}
struct LayoutSaver::Placeholder
{
typedef QVector<LayoutSaver::Placeholder> List;
QVariantMap toVariantMap() const;
void fromVariantMap(const QVariantMap &map);
bool isFloatingWindow;
int indexOfFloatingWindow;
int itemIndex;
QString mainWindowUniqueName;
};
///@brief contains info about how a main window is scaled.
///Used for RestoreOption_RelativeToMainWindow
struct LayoutSaver::ScalingInfo
{
ScalingInfo() = default;
explicit ScalingInfo(const QString &mainWindowId, QRect savedMainWindowGeo);
bool isValid() const {
return heightFactor > 0 && widthFactor > 0 && !((qFuzzyCompare(widthFactor, 1) && qFuzzyCompare(heightFactor, 1)));
}
void translatePos(QPoint &) const;
void applyFactorsTo(QPoint &) const;
void applyFactorsTo(QSize &) const;
void applyFactorsTo(QRect &) const;
QString mainWindowName;
QRect savedMainWindowGeometry;
QRect realMainWindowGeometry;
double heightFactor = -1;
double widthFactor = -1;
};
struct LayoutSaver::Position
{
QRect lastFloatingGeometry;
int tabIndex;
bool wasFloating;
LayoutSaver::Placeholder::List placeholders;
/// Iterates through the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
void scaleSizes(const ScalingInfo &scalingInfo);
QVariantMap toVariantMap() const;
void fromVariantMap(const QVariantMap &map);
};
struct DOCKS_EXPORT LayoutSaver::DockWidget
{
// Using shared ptr, as we need to modify shared instances
typedef std::shared_ptr<LayoutSaver::DockWidget> Ptr;
typedef QVector<Ptr> List;
static QHash<QString, Ptr> s_dockWidgets;
bool isValid() const;
/// Iterates through the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
void scaleSizes(const ScalingInfo &scalingInfo);
static Ptr dockWidgetForName(const QString &name)
{
auto dw = s_dockWidgets.value(name);
if (dw)
return dw;
dw = Ptr(new LayoutSaver::DockWidget);
s_dockWidgets.insert(name, dw);
dw->uniqueName = name;
return dw;
}
QVariantMap toVariantMap() const;
void fromVariantMap(const QVariantMap &map);
QString uniqueName;
QStringList affinities;
LayoutSaver::Position lastPosition;
private:
DockWidget() {}
};
inline QVariantList toVariantList(const LayoutSaver::DockWidget::List &list)
{
QVariantList result;
result.reserve(list.size());
for (const auto &dw : list)
result.push_back(dw->toVariantMap());
return result;
}
inline QVariantList dockWidgetNames(const LayoutSaver::DockWidget::List &list)
{
QVariantList result;
result.reserve(list.size());
for (auto &dw : list)
result.push_back(dw->uniqueName);
return result;
}
struct LayoutSaver::Frame
{
bool isValid() const;
/// Iterates through the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
void scaleSizes(const ScalingInfo &scalingInfo);
QVariantMap toVariantMap() const;
void fromVariantMap(const QVariantMap &map);
bool isNull = true;
QString objectName;
QRect geometry;
unsigned int options;
int currentTabIndex;
QString id; // for coorelation purposes
LayoutSaver::DockWidget::List dockWidgets;
};
struct LayoutSaver::MultiSplitter
{
bool isValid() const;
/// Iterates through the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
void scaleSizes(const ScalingInfo &scalingInfo);
QVariantMap toVariantMap() const;
void fromVariantMap(const QVariantMap &map);
QVariantMap layout;
QHash<QString, LayoutSaver::Frame> frames;
};
struct LayoutSaver::FloatingWindow
{
typedef QVector<LayoutSaver::FloatingWindow> List;
bool isValid() const;
/// Iterates through the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
void scaleSizes(const ScalingInfo &);
QVariantMap toVariantMap() const;
void fromVariantMap(const QVariantMap &map);
LayoutSaver::MultiSplitter multiSplitterLayout;
QStringList affinities;
int parentIndex = -1;
QRect geometry;
int screenIndex;
QSize screenSize; // for relative-size restoring
bool isVisible = true;
};
struct LayoutSaver::MainWindow
{
public:
typedef QVector<LayoutSaver::MainWindow> List;
bool isValid() const;
/// Iterates through the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
void scaleSizes();
QVariantMap toVariantMap() const;
void fromVariantMap(const QVariantMap &map);
KDDockWidgets::MainWindowOptions options;
LayoutSaver::MultiSplitter multiSplitterLayout;
QString uniqueName;
QStringList affinities;
QRect geometry;
int screenIndex;
QSize screenSize; // for relative-size restoring
bool isVisible;
ScalingInfo scalingInfo;
};
///@brief we serialize some info about screens, so eventually we can make restore smarter when switching screens
///Not used currently, but nice to have in the json already
struct LayoutSaver::ScreenInfo
{
typedef QVector<LayoutSaver::ScreenInfo> List;
QVariantMap toVariantMap() const;
void fromVariantMap(const QVariantMap &map);
int index;
QRect geometry;
QString name;
double devicePixelRatio;
};
struct LayoutSaver::Layout
{
public:
Layout() {
s_currentLayoutBeingRestored = this;
const QList<QScreen*> screens = qApp->screens();
for (int i = 0; i < screens.size(); ++i) {
ScreenInfo info;
info.index = i;
info.geometry = screens[i]->geometry();
info.name = screens[i]->name();
info.devicePixelRatio = screens[i]->devicePixelRatio();
screenInfo.push_back(info);
}
}
~Layout() {
s_currentLayoutBeingRestored = nullptr;
}
bool isValid() const;
QByteArray toJson() const;
bool fromJson(const QByteArray &jsonData);
QVariantMap toVariantMap() const;
void fromVariantMap(const QVariantMap &map);
/// Iterates through the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
void scaleSizes();
static LayoutSaver::Layout* s_currentLayoutBeingRestored;
LayoutSaver::MainWindow mainWindowForIndex(int index) const;
QStringList mainWindowNames() const;
QStringList dockWidgetNames() const;
int serializationVersion = KDDOCKWIDGETS_SERIALIZATION_VERSION;
LayoutSaver::MainWindow::List mainWindows;
LayoutSaver::FloatingWindow::List floatingWindows;
LayoutSaver::DockWidget::List closedDockWidgets;
LayoutSaver::DockWidget::List allDockWidgets;
ScreenInfo::List screenInfo;
private:
Q_DISABLE_COPY(Layout)
};
}
#endif