KDDockWidgets API Documentation 2.1
Loading...
Searching...
No Matches
Position.cpp
Go to the documentation of this file.
1/*
2 This file is part of KDDockWidgets.
3
4 SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
5 Author: SĂ©rgio Martins <sergio.martins@kdab.com>
6
7 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
8
9 Contact KDAB at <info@kdab.com> for commercial licensing options.
10*/
11
18#include "Position_p.h"
19#include "LayoutSaver_p.h"
20#include "Logging_p.h"
21#include "ScopedValueRollback_p.h"
22#include "core/layouting/Item_p.h"
23#include "core/layouting/LayoutingHost_p.h"
24#include "kddockwidgets/core/FloatingWindow.h"
25#include "kddockwidgets/core/Layout.h"
26#include "kddockwidgets/core/MainWindow.h"
27#include "kddockwidgets/core/DockRegistry.h"
28
29#include <algorithm>
30#include <utility>
31
32using namespace KDDockWidgets;
33
34Position::~Position()
35{
36 m_placeholders.clear();
37}
38
39void Position::addPlaceholderItem(Core::Item *placeholder)
40{
41 assert(placeholder);
42
43 // 1. Already exists, nothing to do
44 if (containsPlaceholder(placeholder))
45 return;
46
47 if (DockRegistry::self()->itemIsInMainWindow(placeholder)) {
48 // 2. If we have a MainWindow placeholder we don't need nothing else
49 removePlaceholders();
50 } else {
51 // 3. It's a placeholder to a FloatingWindow. Let's still keep any MainWindow placeholders
52 // we have as FloatingWindow are temporary so we might need the MainWindow placeholder
53 // later.
54 removeNonMainWindowPlaceholders();
55 }
56
57 // Make sure our list only contains valid placeholders. We save the result so we can disconnect
58 // from the lambda, since the Item might outlive Position
59 auto conn = placeholder->deleted.connect([this, placeholder] { removePlaceholder(placeholder); });
60
61 m_placeholders.push_back(std::make_unique<ItemRef>(conn, placeholder));
62
63 // NOTE: We use a list instead of simply two variables to keep the placeholders, because
64 // a placeholder from a FloatingWindow might become a MainWindow one without we knowing,
65 // like when dragging a floating window into a MainWindow. So, isInMainWindow() won't return
66 // the same value always, hence we just shove them into a list, instead of giving them
67 // meaningful names in separated variables
68}
69
70Core::Item *Position::layoutItem() const
71{
72 // Return the layout item that is in a MainWindow, that's where we restore the dock widget to.
73 // In the future we might want to restore it to FloatingWindows.
74
75 for (const auto &itemref : m_placeholders) {
76 if (itemref->isInMainWindow())
77 return itemref->item;
78 }
79
80 return nullptr;
81}
82
83bool Position::containsPlaceholder(Core::Item *item) const
84{
85 for (const auto &itemRef : m_placeholders)
86 if (itemRef->item == item)
87 return true;
88
89 return false;
90}
91
92void Position::removePlaceholders()
93{
94 ScopedValueRollback clearGuard(m_clearing, true);
95 m_placeholders.clear();
96}
97
98void Position::removePlaceholders(const Core::LayoutingHost *host)
99{
100 m_placeholders.erase(std::remove_if(m_placeholders.begin(), m_placeholders.end(),
101 [host](const std::unique_ptr<ItemRef> &itemref) {
102 if (!itemref->item)
103 return true;
104 return host == itemref->item->host();
105 }),
106 m_placeholders.end());
107}
108
109void Position::removeNonMainWindowPlaceholders()
110{
111 auto it = m_placeholders.begin();
112 while (it != m_placeholders.end()) {
113 ItemRef *itemref = it->get();
114 if (!itemref->isInMainWindow())
115 it = m_placeholders.erase(it);
116 else
117 ++it;
118 }
119}
120
121void Position::removePlaceholder(Core::Item *placeholder)
122{
123 if (m_clearing) // reentrancy guard
124 return;
125
126 m_placeholders.erase(std::remove_if(m_placeholders.begin(), m_placeholders.end(),
127 [placeholder](const std::unique_ptr<ItemRef> &itemref) {
128 return itemref->item == placeholder || !itemref->item;
129 }),
130 m_placeholders.end());
131}
132
133void Position::deserialize(const LayoutSaver::Position &lp)
134{
135 m_lastFloatingGeometry = lp.lastFloatingGeometry;
136 m_lastOverlayedGeometries = lp.lastOverlayedGeometries;
137
138 for (const auto &placeholder : std::as_const(lp.placeholders)) {
139 Core::Layout *layout = nullptr;
140 int itemIndex = placeholder.itemIndex;
141 if (placeholder.isFloatingWindow) {
142 const int index = placeholder.indexOfFloatingWindow;
143 if (index == -1) {
144 continue; // Skip
145 } else {
146 assert(LayoutSaver::Layout::s_currentLayoutBeingRestored);
147 auto serializedFw =
148 LayoutSaver::Layout::s_currentLayoutBeingRestored->floatingWindowForIndex(
149 index);
150 if (serializedFw.isValid()) {
151 if (auto fw = serializedFw.floatingWindowInstance) {
152 layout = fw->layout();
153 } else {
154 continue;
155 }
156 } else {
157 KDDW_ERROR("Invalid floating window position to restore. index={}", index);
158 continue;
159 }
160 }
161 } else {
162 Core::MainWindow *mainWindow =
163 DockRegistry::self()->mainWindowByName(placeholder.mainWindowUniqueName);
164 layout = mainWindow->layout();
165 }
166
167 const Core::Item::List &items = layout->items();
168 if (itemIndex >= 0 && itemIndex < items.size()) {
169 Core::Item *item = items.at(itemIndex);
170 addPlaceholderItem(item);
171 } else {
172 // Shouldn't happen, maybe even assert
173 KDDW_ERROR("Couldn't find item index {}", itemIndex);
174 }
175 }
176
177 m_tabIndex = lp.tabIndex;
178 m_wasFloating = lp.wasFloating;
179}
180
181LayoutSaver::Position Position::serialize() const
182{
183 LayoutSaver::Position l;
184
185 for (auto &itemRef : m_placeholders) {
186 LayoutSaver::Placeholder p;
187
188 Core::Item *item = itemRef->item;
190 const auto itemIndex = layout->items().indexOf(item);
191
192 auto fw = layout->floatingWindow();
193 auto mainWindow = layout->mainWindow(/*honourNesting=*/true);
194 assert(mainWindow || fw);
195 p.isFloatingWindow = fw;
196
197 if (p.isFloatingWindow) {
198 p.indexOfFloatingWindow = fw->beingDeleted()
199 ? -1
200 : DockRegistry::self()->floatingWindows().indexOf(
201 fw);
202 } else {
203 p.mainWindowUniqueName = mainWindow->uniqueName();
204 assert(!p.mainWindowUniqueName.isEmpty());
205 }
206
207 p.itemIndex = itemIndex;
208 l.placeholders.push_back(p);
209 }
210
211 l.tabIndex = m_tabIndex;
212 l.wasFloating = m_wasFloating;
213
214 l.lastFloatingGeometry = lastFloatingGeometry();
215 l.lastOverlayedGeometries = m_lastOverlayedGeometries;
216
217 return l;
218}
219
220ItemRef::ItemRef(KDBindings::ConnectionHandle conn, Core::Item *it)
221 : item(it)
222 , connection(std::move(conn))
223{
224 item->ref();
225}
226
227ItemRef::~ItemRef()
228{
229 if (item && !item->m_inDtor) {
230 connection.disconnect();
231 item->unref();
232 }
233}
234
235bool ItemRef::isInMainWindow() const
236{
237 return item && DockRegistry::self()->itemIsInMainWindow(item);
238}
A ConnectionHandle represents the connection of a Signal to a slot (i.e. a function that is called wh...
Definition signal.h:68
The widget (QWidget or QQuickItem) which holds a layout of dock widgets.
Definition Layout.h:57
Vector< Core::Item * > items() const
The list of items in this layout.
Definition Layout.cpp:194
Core::MainWindow * mainWindow(bool honourNesting=false) const
Definition Layout.cpp:73
Core::FloatingWindow * floatingWindow() const
Definition Layout.cpp:95
The MainWindow base-class. MainWindow and MainWindowBase are only split in two so we can share some c...
QString uniqueName() const
Returns the unique name that was passed via constructor. Used internally by the save/restore mechanis...
Vector< Core::FloatingWindow * > floatingWindows(bool includeBeingDeleted=false, bool honourSkipped=false) const
returns all FloatingWindow instances. Not necessarily all floating dock widgets, As there might be Do...
Q_INVOKABLE KDDockWidgets::Core::MainWindow * mainWindowByName(const QString &) const
static DockRegistry * self()
bool itemIsInMainWindow(const Core::Item *) const
Returns whether the item is in a main window. Nesting is honoured. (MDIArea inside DropArea inside Ma...
Core::Layout * layoutForItem(const Core::Item *) const
Returns the Layout where the specified item is in.
Class to abstract QAction, so code still works with QtQuick and Flutter.
Definition utils.h:161

© Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
KDDockWidgets
Advanced Dock Widget Framework for Qt
https://www.kdab.com/development-resources/qt-tools/kddockwidgets/
Generated by doxygen 1.9.8