22#include "core/LayoutSaver_p.h"
23#include "core/Logging_p.h"
24#include "core/Position_p.h"
25#include "core/Utils_p.h"
26#include "core/View_p.h"
34#include "core/DockWidget_p.h"
36#include "core/nlohmann_helpers_p.h"
37#include "core/layouting/Item_p.h"
67std::map<QString, LayoutSaver::DockWidget::Ptr> LayoutSaver::DockWidget::s_dockWidgets;
68LayoutSaver::Layout *LayoutSaver::Layout::s_currentLayoutBeingRestored =
nullptr;
69std::unordered_map<QString, std::shared_ptr<KDDockWidgets::Position>> LayoutSaver::Private::s_unrestoredPositions;
70std::unordered_map<QString, CloseReason> LayoutSaver::Private::s_unrestoredProperties;
74 InternalRestoreOptions ret = {};
76 ret.setFlag(InternalRestoreOption::SkipMainWindowGeometry);
77 ret.setFlag(InternalRestoreOption::RelativeFloatingWindowGeometry);
81 ret.setFlag(InternalRestoreOption::RelativeFloatingWindowGeometry,
false);
86 KDDW_ERROR(
"Unknown options={}",
int(options));
92bool LayoutSaver::Private::s_restoreInProgress =
false;
97T
jsonValue(
const nlohmann::json &json,
const char *name,
const T &defaultValue)
101 return json.value(name, defaultValue);
107template<
typename Type>
108void to_json(nlohmann::json &json,
const typename Type::List &list)
110 for (
const auto &l : list) {
115void to_json(nlohmann::json &json,
const LayoutSaver::Group &f)
118 json[
"isNull"] = f.isNull;
119 json[
"objectName"] = f.objectName;
120 json[
"geometry"] = f.geometry;
121 json[
"options"] = f.options;
122 json[
"currentTabIndex"] = f.currentTabIndex;
123 json[
"mainWindowUniqueName"] = f.mainWindowUniqueName;
124 json[
"dockWidgets"] = dockWidgetNames(f.dockWidgets);
126void from_json(
const nlohmann::json &json, LayoutSaver::Group &f)
129 f.isNull =
jsonValue(json,
"isNull",
true);
131 f.geometry =
jsonValue(json,
"geometry", Rect());
133 f.currentTabIndex =
jsonValue(json,
"currentTabIndex", 0);
134 f.mainWindowUniqueName =
jsonValue(json,
"mainWindowUniqueName",
QString());
136 auto it = json.find(
"dockWidgets");
137 if (it == json.end())
140 auto &dockWidgets = *it;
141 f.dockWidgets.reserve((
int )dockWidgets.size());
142 for (
const auto &d : dockWidgets) {
143 LayoutSaver::DockWidget::Ptr dw =
144 LayoutSaver::DockWidget::dockWidgetForName(d.get<
QString>());
145 f.dockWidgets.push_back(dw);
149void to_json(nlohmann::json &json,
const LayoutSaver::MultiSplitter &s)
151 json[
"layout"] = s.layout;
152 auto &groups = json[
"frames"];
153 for (
const auto &it : s.groups) {
154 const auto &group = it.second;
155 groups[group.id.toStdString()] = group;
159void from_json(
const nlohmann::json &json, LayoutSaver::MultiSplitter &s)
162 s.layout =
jsonValue(json,
"layout", nlohmann::json::object());
163 auto it = json.find(
"frames");
164 if (it == json.end())
170 if (!frms.is_object())
171 KDDW_ERROR(
"Unexpected not object");
173 for (
const auto &kv : frms.items()) {
175 auto group = kv.value().get<LayoutSaver::Group>();
176 s.groups[key] = group;
180void to_json(nlohmann::json &json,
const LayoutSaver::MainWindow &mw)
182 json[
"options"] = int(mw.options);
183 json[
"multiSplitterLayout"] = mw.multiSplitterLayout;
184 json[
"uniqueName"] = mw.uniqueName;
185 json[
"geometry"] = mw.geometry;
186 json[
"normalGeometry"] = mw.normalGeometry;
187 json[
"screenIndex"] = mw.screenIndex;
188 json[
"screenSize"] = mw.screenSize;
189 json[
"isVisible"] = mw.isVisible;
190 json[
"affinities"] = mw.affinities;
191 json[
"windowState"] = mw.windowState;
197 std::string key = std::string(
"sidebar-") + std::to_string((
int )loc);
198 json[key] = dockWidgets;
203void from_json(
const nlohmann::json &json, LayoutSaver::MainWindow &mw)
205 mw.options =
static_cast<decltype(mw.options)
>(
jsonValue(json,
"options", 0));
206 mw.multiSplitterLayout =
jsonValue(json,
"multiSplitterLayout", LayoutSaver::MultiSplitter());
208 mw.geometry =
jsonValue(json,
"geometry", Rect());
209 mw.normalGeometry =
jsonValue(json,
"normalGeometry", Rect());
210 mw.screenIndex =
jsonValue(json,
"screenIndex", 0);
211 mw.screenSize =
jsonValue(json,
"screenSize", Size(800, 600));
212 mw.isVisible =
jsonValue(json,
"isVisible",
false);
218 if (json.find(
"affinityName") != json.end()) {
220 if (!mw.affinities.contains(affinityName)) {
227 std::string key = std::string(
"sidebar-") + std::to_string((
int )loc);
228 auto it = json.find(key);
229 if (it == json.end())
232 if (val.is_array() && !val.empty()) {
238void to_json(nlohmann::json &json,
const LayoutSaver::FloatingWindow &window)
240 json[
"multiSplitterLayout"] = window.multiSplitterLayout;
241 json[
"parentIndex"] = window.parentIndex;
242 json[
"geometry"] = window.geometry;
243 json[
"normalGeometry"] = window.normalGeometry;
244 json[
"screenIndex"] = window.screenIndex;
245 json[
"screenSize"] = window.screenSize;
246 json[
"flags"] = window.flags;
247 json[
"isVisible"] = window.isVisible;
248 json[
"windowState"] = window.windowState;
250 if (!window.affinities.isEmpty()) {
251 json[
"affinities"] = window.affinities;
255void from_json(
const nlohmann::json &json, LayoutSaver::FloatingWindow &window)
257 window.multiSplitterLayout =
jsonValue(json,
"multiSplitterLayout", LayoutSaver::MultiSplitter());
258 window.parentIndex =
jsonValue(json,
"parentIndex", -1);
259 window.geometry =
jsonValue(json,
"geometry", Rect());
260 window.normalGeometry =
jsonValue(json,
"normalGeometry", Rect());
261 window.screenIndex =
jsonValue(json,
"screenIndex", 0);
262 window.screenSize =
jsonValue(json,
"screenSize", Size(800, 600));
263 window.isVisible =
jsonValue(json,
"isVisible",
false);
271 if (!affinityName.
isEmpty() && !window.affinities.contains(affinityName)) {
272 window.affinities.push_back(affinityName);
276void to_json(nlohmann::json &json,
const LayoutSaver::ScreenInfo &screenInfo)
278 json[
"index"] = screenInfo.index;
279 json[
"geometry"] = screenInfo.geometry;
280 json[
"name"] = screenInfo.name;
281 json[
"devicePixelRatio"] = screenInfo.devicePixelRatio;
283void from_json(
const nlohmann::json &j, LayoutSaver::ScreenInfo &screenInfo)
285 screenInfo.index = j.value(
"index", 0);
286 screenInfo.geometry = j.value(
"geometry", Rect());
287 screenInfo.name = j.value(
"name",
QString());
288 screenInfo.devicePixelRatio = j.value(
"devicePixelRatio", 1.0);
291void to_json(nlohmann::json &json,
const LayoutSaver::Placeholder &placeHolder)
293 json[
"isFloatingWindow"] = placeHolder.isFloatingWindow;
294 json[
"itemIndex"] = placeHolder.itemIndex;
295 if (placeHolder.isFloatingWindow)
296 json[
"indexOfFloatingWindow"] = placeHolder.indexOfFloatingWindow;
298 json[
"mainWindowUniqueName"] = placeHolder.mainWindowUniqueName;
301void from_json(
const nlohmann::json &json, LayoutSaver::Placeholder &placeHolder)
303 placeHolder.isFloatingWindow =
jsonValue(json,
"isFloatingWindow",
false);
304 placeHolder.itemIndex =
jsonValue(json,
"itemIndex", 0);
305 placeHolder.indexOfFloatingWindow =
jsonValue(json,
"indexOfFloatingWindow", -1);
306 placeHolder.mainWindowUniqueName =
jsonValue(json,
"mainWindowUniqueName",
QString());
309void to_json(nlohmann::json &json,
const LayoutSaver::Position &pos)
311 json[
"lastFloatingGeometry"] = pos.lastFloatingGeometry;
312 json[
"lastOverlayedGeometries"] = pos.lastOverlayedGeometries;
313 json[
"tabIndex"] = pos.tabIndex;
314 json[
"wasFloating"] = pos.wasFloating;
315 json[
"placeholders"] = pos.placeholders;
318void from_json(
const nlohmann::json &json, LayoutSaver::Position &pos)
320 pos.lastFloatingGeometry =
jsonValue(json,
"lastFloatingGeometry", Rect());
321 pos.lastOverlayedGeometries =
jsonValue(json,
"lastOverlayedGeometries", std::unordered_map<KDDockWidgets::SideBarLocation, Rect>());
322 pos.tabIndex =
jsonValue(json,
"tabIndex", 0);
323 pos.wasFloating =
jsonValue(json,
"wasFloating",
false);
324 pos.placeholders =
jsonValue(json,
"placeholders", LayoutSaver::Placeholder::List());
327void to_json(nlohmann::json &json,
const LayoutSaver::DockWidget &dw)
329 if (!dw.affinities.isEmpty())
330 json[
"affinities"] = dw.affinities;
331 json[
"uniqueName"] = dw.uniqueName;
332 json[
"lastPosition"] = dw.lastPosition;
333 json[
"lastCloseReason"] = dw.lastCloseReason;
335void from_json(
const nlohmann::json &json, LayoutSaver::DockWidget &dw)
337 auto it = json.find(
"affinities");
338 if (it != json.end())
342 if (dw.uniqueName.isEmpty())
343 KDDW_ERROR(
"Unexpected no uniqueName for dockWidget");
345 dw.lastPosition =
jsonValue(json,
"lastPosition", LayoutSaver::Position());
349void to_json(nlohmann::json &json,
const typename LayoutSaver::DockWidget::List &list)
351 for (
const auto &mw : list) {
356void from_json(
const nlohmann::json &json,
typename LayoutSaver::DockWidget::List &list)
359 for (
const auto &v : json) {
360 auto it = v.find(
"uniqueName");
362 KDDW_ERROR(
"Unexpected no uniqueName");
366 auto dw = LayoutSaver::DockWidget::dockWidgetForName(uniqueName);
375 : d(new Private(options))
377 d->m_dockRegistry->registerLayoutSaver();
382 d->m_dockRegistry->unregisterLayoutSaver();
390 std::ofstream file(jsonFilename.
toStdString(), std::ios::binary);
391 if (!file.is_open()) {
392 KDDW_ERROR(
"Failed to open {}", jsonFilename);
414 if (!d->m_dockRegistry->isSane()) {
415 KDDW_ERROR(
"Refusing to serialize this layout. Check previous warnings.");
419 LayoutSaver::Layout layout;
422 d->m_dockRegistry->ensureAllFloatingWidgetsAreMorphed();
424 const auto mainWindows = d->m_dockRegistry->mainwindows();
425 layout.mainWindows.reserve(mainWindows.size());
426 for (
auto mainWindow : mainWindows) {
427 if (d->matchesAffinity(mainWindow->affinities()))
428 layout.mainWindows.push_back(mainWindow->serialize());
432 d->m_dockRegistry->floatingWindows(
false,
true);
433 layout.floatingWindows.reserve(floatingWindows.
size());
435 if (d->matchesAffinity(floatingWindow->affinities()))
436 layout.floatingWindows.push_back(floatingWindow->serialize());
441 layout.closedDockWidgets.reserve(closedDockWidgets.
size());
443 if (d->matchesAffinity(dockWidget->affinities()))
444 layout.closedDockWidgets.push_back(dockWidget->d->serialize());
451 layout.allDockWidgets.reserve(dockWidgets.
size());
453 if (!dockWidget->skipsRestore() && d->matchesAffinity(dockWidget->affinities())) {
454 auto dw = dockWidget->d->serialize();
455 dw->lastPosition = dockWidget->d->lastPosition()->serialize();
456 layout.allDockWidgets.push_back(dw);
460 return layout.toJson();
465 LayoutSaver::DockWidget::s_dockWidgets.clear();
466 d->clearRestoredProperty();
479 m_saver->d->deleteEmptyGroups();
482 GroupCleanup(
const GroupCleanup &) =
delete;
483 GroupCleanup &operator=(
const GroupCleanup) =
delete;
488 GroupCleanup cleanup(
this);
489 LayoutSaver::Layout layout;
490 if (!layout.fromJson(data)) {
491 KDDW_ERROR(
"Failed to parse json data");
495 if (!layout.isValid()) {
499 layout.scaleSizes(d->m_restoreOptions);
501 d->floatWidgetsWhichSkipRestore(layout.mainWindowNames());
502 d->floatUnknownWidgets(layout);
504 Private::RAIIIsRestoring isRestoring;
509 d->m_dockRegistry->clear(d->m_dockRegistry->dockWidgets(layout.dockWidgetsToClose()),
510 d->m_dockRegistry->mainWindows(layout.mainWindowNames()),
514 for (
const LayoutSaver::MainWindow &mw : std::as_const(layout.mainWindows)) {
515 auto mainWindow = d->m_dockRegistry->mainWindowByName(mw.uniqueName);
518 mainWindow = mwFunc(mw.uniqueName, mw.options);
520 KDDW_ERROR(
"Failed to restore layout create MainWindow with name {} first");
525 if (!d->matchesAffinity(mainWindow->affinities()))
528 if (!(d->m_restoreOptions & InternalRestoreOption::SkipMainWindowGeometry)) {
529 Window::Ptr window = mainWindow->view()->window();
536 d->deserializeWindowGeometry(mw, window);
537 window->setWindowState(mw.windowState);
540 if (!mainWindow->deserialize(mw))
545 for (LayoutSaver::FloatingWindow &fw : layout.floatingWindows) {
546 if (!d->matchesAffinity(fw.affinities) || fw.skipsRestore())
552 auto flags =
static_cast<FloatingWindowFlags
>(fw.flags);
555 auto floatingWindow =
557 fw.floatingWindowInstance = floatingWindow;
558 d->deserializeWindowGeometry(fw, floatingWindow->view()->window());
559 if (!floatingWindow->deserialize(fw)) {
560 KDDW_ERROR(
"Failed to deserialize floating window");
567 for (
const auto &dw : std::as_const(layout.closedDockWidgets)) {
568 if (d->matchesAffinity(dw->affinities)) {
573 LayoutSaver::Private::s_unrestoredPositions.clear();
574 LayoutSaver::Private::s_unrestoredProperties.clear();
577 for (
const auto &dw : std::as_const(layout.allDockWidgets)) {
578 if (!d->matchesAffinity(dw->affinities))
583 dockWidget->d->lastPosition()->deserialize(dw->lastPosition);
585 KDDW_INFO(
"Couldn't find dock widget {}", dw->uniqueName);
586 auto pos = std::make_shared<KDDockWidgets::Position>();
587 pos->deserialize(dw->lastPosition);
588 LayoutSaver::Private::s_unrestoredPositions[dw->uniqueName] = pos;
589 LayoutSaver::Private::s_unrestoredProperties[dw->uniqueName] = dw->lastCloseReason;
598 d->m_affinityNames = affinityNames;
601 d->m_affinityNames.push_back(
QString());
616 if (dw->d->m_wasRestored)
617 result.push_back(dw);
623void LayoutSaver::Private::clearRestoredProperty()
627 dw->d->m_wasRestored =
false;
632void LayoutSaver::Private::deserializeWindowGeometry(
const T &saved, Window::Ptr window)
637 Rect geometry = saved.geometry;
638 if (!isNormalWindowState(saved.windowState)) {
641 geometry = saved.normalGeometry;
646 window->setGeometry(geometry);
647 window->setVisible(saved.isVisible);
650LayoutSaver::Private::Private(RestoreOptions options)
663 auto it = s_unrestoredPositions.find(dw->
uniqueName());
664 if (it != s_unrestoredPositions.end()) {
665 dw->
d->m_lastPosition = it->second;
666 s_unrestoredPositions.erase(it);
671 auto it = s_unrestoredProperties.find(dw->
uniqueName());
672 if (it != s_unrestoredProperties.end()) {
673 dw->
d->m_lastCloseReason = it->second;
674 s_unrestoredProperties.erase(it);
679bool LayoutSaver::Private::matchesAffinity(
const Vector<QString> &affinities)
const
681 return m_affinityNames.isEmpty() || affinities.
isEmpty()
685void LayoutSaver::Private::floatWidgetsWhichSkipRestore(
const Vector<QString> &mainWindowNames)
693 for (
auto mw : mainWindows) {
695 for (
auto dw : docks) {
703void LayoutSaver::Private::floatUnknownWidgets(
const LayoutSaver::Layout &layout)
710 for (
auto mw : mainWindows) {
713 if (!layout.containsDockWidget(dw->
uniqueName())) {
720void LayoutSaver::Private::deleteEmptyGroups()
const
725 const auto groups = m_dockRegistry->groups();
726 for (
auto group : groups) {
727 if (!group->beingDeletedLater() && group->isEmpty() && !group->isCentralGroup()) {
728 if (
auto item = group->layoutItem()) {
729 item->turnIntoPlaceholder();
732 KDDW_ERROR(
"Expected item for group");
741 return Private::s_restoreInProgress;
744bool LayoutSaver::Layout::isValid()
const
746 if (serializationVersion != KDDOCKWIDGETS_SERIALIZATION_VERSION) {
747 KDDW_ERROR(
"Serialization format is too old {}, current={}", serializationVersion, KDDOCKWIDGETS_SERIALIZATION_VERSION);
751 for (
auto &m : mainWindows) {
756 for (
auto &m : floatingWindows) {
761 for (
auto &m : allDockWidgets) {
782 LayoutSaver::Layout layout;
783 if (!layout.fromJson(serialized))
787 names.
reserve(layout.allDockWidgets.size());
789 for (
const auto &dock : std::as_const(layout.allDockWidgets)) {
790 auto it = std::find_if(layout.closedDockWidgets.cbegin(), layout.closedDockWidgets.cend(), [&dock](
auto closedDock) {
791 return dock->uniqueName == closedDock->uniqueName;
794 const bool itsOpen = it == layout.closedDockWidgets.cend();
796 names.push_back(dock->uniqueName);
815 LayoutSaver::Layout layout;
816 if (!layout.fromJson(serialized))
820 names.
reserve(layout.allDockWidgets.size());
822 for (
const auto &mainWindow : std::as_const(layout.mainWindows)) {
823 for (
const auto &it : mainWindow.dockWidgetsPerSideBar) {
824 for (
const auto &name : it.second)
825 names.push_back(name);
833void to_json(nlohmann::json &j,
const LayoutSaver::Layout &layout)
835 j[
"serializationVersion"] = layout.serializationVersion;
836 j[
"mainWindows"] = layout.mainWindows;
837 j[
"floatingWindows"] = layout.floatingWindows;
838 j[
"closedDockWidgets"] = ::dockWidgetNames(layout.closedDockWidgets);
839 j[
"allDockWidgets"] = layout.allDockWidgets;
840 j[
"screenInfo"] = layout.screenInfo;
843void from_json(
const nlohmann::json &j, LayoutSaver::Layout &layout)
845 layout.serializationVersion = j.value(
"serializationVersion", 0);
846 layout.mainWindows = j.value(
"mainWindows", LayoutSaver::MainWindow::List {});
847 layout.allDockWidgets = j.value(
"allDockWidgets", LayoutSaver::DockWidget::List {});
849 layout.closedDockWidgets.clear();
851 const auto closedDockWidgets = j.value(
"closedDockWidgets",
Vector<QString>());
852 for (
const QString &name : closedDockWidgets) {
853 layout.closedDockWidgets.push_back(
854 LayoutSaver::DockWidget::dockWidgetForName(name));
857 layout.floatingWindows = j.value(
"floatingWindows", LayoutSaver::FloatingWindow::List {});
858 layout.screenInfo = j.value(
"screenInfo", LayoutSaver::ScreenInfo::List {});
864 nlohmann::json json = *
this;
868bool LayoutSaver::Layout::fromJson(
const QByteArray &jsonData)
870 nlohmann::json json = nlohmann::json::parse(jsonData,
nullptr,
false);
871 if (json.is_discarded()) {
877 }
catch (
const std::exception &e) {
878 KDDW_ERROR(
"LayoutSaver::Layout::fromJson: Caught exception: {}", e.what());
881 KDDW_ERROR(
"LayoutSaver::Layout::fromJson: Caught exception.");
888void LayoutSaver::Layout::scaleSizes(InternalRestoreOptions options)
890 if (mainWindows.isEmpty())
893 const bool skipsMainWindowGeometry = options & InternalRestoreOption::SkipMainWindowGeometry;
894 if (!skipsMainWindowGeometry) {
903 for (
auto &mw : mainWindows)
909 const bool useRelativeSizesForFloatingWidgets =
910 options & InternalRestoreOption::RelativeFloatingWindowGeometry;
912 if (useRelativeSizesForFloatingWidgets) {
913 for (
auto &fw : floatingWindows) {
914 LayoutSaver::MainWindow mw = mainWindowForIndex(fw.parentIndex);
915 if (mw.scalingInfo.isValid())
916 fw.scaleSizes(mw.scalingInfo);
920 const ScalingInfo firstScalingInfo = mainWindows.constFirst().scalingInfo;
921 if (firstScalingInfo.isValid()) {
922 for (
auto &dw : allDockWidgets) {
926 dw->scaleSizes(firstScalingInfo);
931LayoutSaver::MainWindow LayoutSaver::Layout::mainWindowForIndex(
int index)
const
933 if (index < 0 || index >= mainWindows.size())
936 return mainWindows.at(index);
939LayoutSaver::FloatingWindow LayoutSaver::Layout::floatingWindowForIndex(
int index)
const
941 if (index < 0 || index >= floatingWindows.size())
944 return floatingWindows.at(index);
950 names.
reserve(mainWindows.size());
951 for (
const auto &mw : mainWindows) {
952 names.push_back(mw.uniqueName);
962 for (
const auto &dw : allDockWidgets) {
977 for (
const auto &dw : allDockWidgets) {
982 if (dockWidget->skipsRestore()) {
983 if (
auto fw = dockWidget->floatingWindow()) {
1000bool LayoutSaver::Layout::containsDockWidget(
const QString &uniqueName)
const
1002 return std::find_if(allDockWidgets.cbegin(), allDockWidgets.cend(),
1003 [uniqueName](
const std::shared_ptr<LayoutSaver::DockWidget> &dock) {
1004 return dock->uniqueName == uniqueName;
1006 != allDockWidgets.cend();
1009bool LayoutSaver::Group::isValid()
const
1014 if (!geometry.isValid()) {
1015 KDDW_ERROR(
"Invalid geometry");
1020 KDDW_ERROR(
"Invalid id");
1024 if (!dockWidgets.isEmpty()) {
1025 if (currentTabIndex >= dockWidgets.size() || currentTabIndex < 0) {
1028 KDDW_ERROR(
"Invalid tab index = {}, size = {}", currentTabIndex, dockWidgets.size());
1033 KDDW_WARN(
"Invalid tab index = {}, size = {}", currentTabIndex, dockWidgets.size());
1034 const_cast<LayoutSaver::Group *
>(
this)->currentTabIndex = 0;
1038 for (
auto &dw : dockWidgets) {
1046bool LayoutSaver::Group::hasSingleDockWidget()
const
1048 return dockWidgets.size() == 1;
1051bool LayoutSaver::Group::skipsRestore()
const
1053 return std::all_of(dockWidgets.cbegin(), dockWidgets.cend(),
1054 [](LayoutSaver::DockWidget::Ptr dw) { return dw->skipsRestore(); });
1057LayoutSaver::DockWidget::Ptr LayoutSaver::Group::singleDockWidget()
const
1059 if (!hasSingleDockWidget())
1062 return dockWidgets.first();
1065bool LayoutSaver::DockWidget::isValid()
const
1070void LayoutSaver::DockWidget::scaleSizes(
const ScalingInfo &scalingInfo)
1072 lastPosition.scaleSizes(scalingInfo);
1075bool LayoutSaver::DockWidget::skipsRestore()
const
1083bool LayoutSaver::FloatingWindow::isValid()
const
1085 if (!multiSplitterLayout.isValid())
1088 if (!geometry.isValid()) {
1089 KDDW_ERROR(
"Invalid geometry");
1096bool LayoutSaver::FloatingWindow::hasSingleDockWidget()
const
1098 return multiSplitterLayout.hasSingleDockWidget();
1101LayoutSaver::DockWidget::Ptr LayoutSaver::FloatingWindow::singleDockWidget()
const
1103 return multiSplitterLayout.singleDockWidget();
1106bool LayoutSaver::FloatingWindow::skipsRestore()
const
1108 return multiSplitterLayout.skipsRestore();
1111void LayoutSaver::FloatingWindow::scaleSizes(
const ScalingInfo &scalingInfo)
1113 scalingInfo.applyFactorsTo( geometry);
1116bool LayoutSaver::MainWindow::isValid()
const
1118 return multiSplitterLayout.isValid();
1123 auto it = dockWidgetsPerSideBar.find(loc);
1124 return it == dockWidgetsPerSideBar.cend() ?
Vector<QString>() : it->second;
1127void LayoutSaver::MainWindow::scaleSizes()
1129 if (scalingInfo.isValid()) {
1135 scalingInfo = ScalingInfo(uniqueName, geometry, screenIndex);
1138bool LayoutSaver::MultiSplitter::isValid()
const
1140 return layout.is_object() && !layout.empty();
1143bool LayoutSaver::MultiSplitter::hasSingleDockWidget()
const
1145 return groups.size() == 1 && groups.cbegin()->second.hasSingleDockWidget();
1148LayoutSaver::DockWidget::Ptr LayoutSaver::MultiSplitter::singleDockWidget()
const
1150 if (!hasSingleDockWidget())
1153 const auto &group = groups.begin()->second;
1154 return group.singleDockWidget();
1157bool LayoutSaver::MultiSplitter::skipsRestore()
const
1159 return std::all_of(groups.cbegin(), groups.cend(),
1160 [](
auto it) { return it.second.skipsRestore(); });
1163void LayoutSaver::Position::scaleSizes(
const ScalingInfo &scalingInfo)
1165 scalingInfo.applyFactorsTo( lastFloatingGeometry);
1172 return mw->
view()->
d->screen();
1177LayoutSaver::ScalingInfo::ScalingInfo(
const QString &mainWindowId, Rect savedMainWindowGeo,
1182 KDDW_ERROR(
"Failed to find main window with name {}", mainWindowId);
1186 if (!savedMainWindowGeo.isValid() || savedMainWindowGeo.isNull()) {
1187 KDDW_ERROR(
"Invalid saved main window geometry {}", savedMainWindowGeo);
1191 if (!mainWindow->geometry().isValid() || mainWindow->geometry().isNull()) {
1192 KDDW_ERROR(
"Invalid main window geometry {}", mainWindow->geometry());
1196 const int currentScreenIndex =
1199 this->mainWindowName = mainWindowId;
1200 this->savedMainWindowGeometry = savedMainWindowGeo;
1201 realMainWindowGeometry =
1202 mainWindow->window()->d->windowGeometry();
1203 widthFactor = double(realMainWindowGeometry.width()) / savedMainWindowGeo.width();
1204 heightFactor = double(realMainWindowGeometry.height()) / savedMainWindowGeo.height();
1205 mainWindowChangedScreen = currentScreenIndex != screenIndex;
1208void LayoutSaver::ScalingInfo::translatePos(Point &pt)
const
1210 const int deltaX = pt.x() - savedMainWindowGeometry.x();
1211 const int deltaY = pt.y() - savedMainWindowGeometry.y();
1213 const double newDeltaX = deltaX * widthFactor;
1214 const double newDeltaY = deltaY * heightFactor;
1216 pt.setX(
int(std::ceil(savedMainWindowGeometry.x() + newDeltaX)));
1217 pt.setY(
int(std::ceil(savedMainWindowGeometry.y() + newDeltaY)));
1220void LayoutSaver::ScalingInfo::applyFactorsTo(Point &pt)
const
1225void LayoutSaver::ScalingInfo::applyFactorsTo(Size &sz)
const
1227 sz.setWidth(
int(widthFactor * sz.width()));
1228 sz.setHeight(
int(heightFactor * sz.height()));
1231void LayoutSaver::ScalingInfo::applyFactorsTo(Rect &rect)
const
1236 Point pos = rect.topLeft();
1237 Size size = rect.size();
1239 applyFactorsTo( size);
1242 if (!mainWindowChangedScreen) {
1247 applyFactorsTo( pos);
1250 rect.moveTopLeft(pos);
1254LayoutSaver::Private::RAIIIsRestoring::RAIIIsRestoring()
1256 LayoutSaver::Private::s_restoreInProgress =
true;
1259LayoutSaver::Private::RAIIIsRestoring::~RAIIIsRestoring()
1261 LayoutSaver::Private::s_restoreInProgress =
false;
Application-wide config to tune certain behaviours of the framework.
InternalRestoreOptions internalRestoreOptions(RestoreOptions options)
Class to save and restore dockwidget layouts.
A widget that supports an arbitrary number of splitters (called Separators) in any combination of ver...
The MainWindow base-class. MainWindow and MainWindowBase are only split in two so we can share some c...
The MainWindow base-class that's shared between QtWidgets and QtQuick stack.
const char * constData() const const
QByteArray fromStdString(const std::string &str)
bool isEmpty() const const
QString fromStdString(const std::string &str)
bool isEmpty() const const
std::string toStdString() const const