Krita Source Code Documentation
Loading...
Searching...
No Matches
KisWindowLayoutManager.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2018 Jouni Pentikäinen <joupent@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include <QWidget>
10#include <QScreen>
11#include <QScreen>
12
13#include <kconfiggroup.h>
14#include <ksharedconfig.h>
15
16#include <KisApplication.h>
17#include <KisMainWindow.h>
18#include <KisPart.h>
19#include <kis_dom_utils.h>
21#include <KisSessionResource.h>
22
24
26 bool showImageInAllWindows{false};
27 bool primaryWorkspaceFollowsFocus{false};
29
31
33 KConfigGroup layoutsCfg(KSharedConfig::openConfig(), "DisplayLayouts");
34 QStringList groups = layoutsCfg.groupList();
35
36 Q_FOREACH(QString name, groups) {
37 loadDisplayLayout(name, layoutsCfg.group(name));
38 }
39 }
40
41 void loadDisplayLayout(const QString &name, KConfigGroup layoutCfg) {
42 DisplayLayout *layout = new DisplayLayout();
43 layout->name = name;
44
45 int displayNumber = 1;
46
47 while (true) {
48 const QString displayDefinition = layoutCfg.readEntry(QString("Display%1").arg(displayNumber++), QString());
49 if (displayDefinition.isEmpty()) break;
50
51 // Just the resolution for now. Later we might want to split by a separator and include things like serial number, etc.
52 const QString &resolutionStr = displayDefinition;
53
54 QStringList dimensions = resolutionStr.split('x');
55 if (dimensions.size() != 2) {
56 qWarning() << "Invalid display definition: " << displayDefinition;
57 break;
58 }
59
60 QSize resolution = QSize(
61 KisDomUtils::toInt(dimensions[0]),
62 KisDomUtils::toInt(dimensions[1])
63 );
64
65 layout->displays.append(Display{resolution});
66 }
67
68 layout->preferredWindowLayout = layoutCfg.readEntry("PreferredLayout", "");
69
70 displayLayouts.append(layout);
71 }
72
73 void saveDisplayLayout(const DisplayLayout &layout) {
74 KConfigGroup layoutsCfg(KSharedConfig::openConfig(), "DisplayLayouts");
75 KConfigGroup layoutCfg = layoutsCfg.group(layout.name);
76 layoutCfg.writeEntry("PreferredLayout", layout.preferredWindowLayout);
77 }
78};
79
81{
82 return resolution == screen->geometry().size();
83}
84
86{
87 if (screens.size() != displays.size()) return false;
88
89 QVector<bool> matchedScreens(screens.size());
90 Q_FOREACH(auto &expectedDisplay, displays) {
91 int i;
92 for (i = 0; i < screens.size(); i++) {
93 if (matchedScreens[i]) continue;
94
95 if (expectedDisplay.matches(screens[i])) {
96 matchedScreens[i] = true;
97 break;
98 }
99 }
100
101 if (i == screens.size()) {
102 return false;
103 }
104 }
105
106 return true;
107}
108
110{
111 return s_instance;
112}
113
115 : d(new Private)
116{
117 d->loadDisplayLayouts();
118
119 connect(qobject_cast<KisApplication*>(KisApplication::instance()),
120 SIGNAL(focusChanged(QWidget*,QWidget*)),
121 this, SLOT(slotFocusChanged(QWidget*,QWidget*)));
122
123 connect(qGuiApp, SIGNAL(screenAdded(QScreen*)), this, SLOT(slotScreensChanged()));
124 connect(qGuiApp, SIGNAL(screenRemoved(QScreen*)), this, SLOT(slotScreensChanged()));
125}
126
128 Q_FOREACH(DisplayLayout *layout, d->displayLayouts) {
129 delete layout;
130 }
131}
132
134{
135 bool wasEnabled = d->showImageInAllWindows;
136
137 d->showImageInAllWindows = showInAll;
138
139 if (!wasEnabled && showInAll) {
140 KisMainWindow *currentMainWindow = KisPart::instance()->currentMainwindow();
141 if (currentMainWindow) {
142 KisView *activeView = currentMainWindow->activeView();
143 if (activeView) {
144 KisDocument *document = activeView->document();
145 if (document) {
146 activeDocumentChanged(document);
147 }
148 }
149 }
150 }
151}
152
154{
155 return d->showImageInAllWindows;
156}
157
159{
160 return d->primaryWorkspaceFollowsFocus;
161}
162
163void KisWindowLayoutManager::setPrimaryWorkspaceFollowsFocus(bool enabled, QUuid primaryWindow)
164{
165 d->primaryWorkspaceFollowsFocus = enabled;
166 d->primaryWindow = primaryWindow;
167}
168
170{
171 return d->primaryWindow;
172}
173
175{
176 if (d->showImageInAllWindows) {
177 Q_FOREACH(QPointer<KisMainWindow> window, KisPart::instance()->mainWindows()) {
178 if (window->isHidden()) continue;
179
180 const auto view = window->activeView();
181 if (!view || view->document() != document) {
182 window->showDocument(document);
183 }
184 }
185 }
186}
187
188void KisWindowLayoutManager::slotFocusChanged(QWidget *old, QWidget *now)
189{
190 Q_UNUSED(old);
191
192 if (!now) return;
193 KisMainWindow *newMainWindow = qobject_cast<KisMainWindow*>(now->window());
194 if (!newMainWindow) return;
195
196 newMainWindow->windowFocused();
197}
198
200{
201 // For automatic switching, only allow a window layout proper
202 KisSessionResource *session = dynamic_cast<KisSessionResource*>(layout);
203 if (session) return;
204
205 QList<QScreen*> screens = QGuiApplication::screens();
206 Q_FOREACH(DisplayLayout *displayLayout, d->displayLayouts) {
207 if (displayLayout->matches(screens)) {
208 displayLayout->preferredWindowLayout = layout->name();
209 d->saveDisplayLayout(*displayLayout);
210 break;
211 }
212 }
213}
214
216{
217 QList<QScreen*> screens = QGuiApplication::screens();
218
219 Q_FOREACH(const DisplayLayout *displayLayout, d->displayLayouts) {
220 if (displayLayout->matches(screens)) {
222 KisWindowLayoutResourceSP layout = windowLayoutServer->resource("", "", displayLayout->preferredWindowLayout);
223
224 if (layout) {
225 setLastUsedLayout(layout.data());
226 layout->applyLayout();
227 return;
228 }
229 }
230 }
231
232 Q_FOREACH(QScreen *screen, screens) {
233 connect(screen, SIGNAL(geometryChanged(QRect)), this, SLOT(slotScreensChanged()), Qt::UniqueConnection);
234 }
235
236}
Q_GLOBAL_STATIC(KisStoragePluginRegistry, s_instance)
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
Main window for Krita.
QPointer< KisView > activeView
static KisPart * instance()
Definition KisPart.cpp:131
KisMainWindow * currentMainwindow() const
Definition KisPart.cpp:483
static KisResourceServerProvider * instance()
KoResourceServer< KisWindowLayoutResource > * windowLayoutServer()
QPointer< KisDocument > document
Definition KisView.cpp:121
void setShowImageInAllWindowsEnabled(bool showInAll)
void setPrimaryWorkspaceFollowsFocus(bool enabled, QUuid primaryWindow)
void setLastUsedLayout(KisWindowLayoutResource *layout)
static KisWindowLayoutManager * instance()
void slotFocusChanged(QWidget *, QWidget *)
void activeDocumentChanged(KisDocument *document)
QScopedPointer< Private > d
QSharedPointer< T > resource(const QString &md5, const QString &fileName, const QString &name)
resource retrieves a resource. If the md5sum is not empty, the resource will only be retrieved if a r...
int toInt(const QString &str, bool *ok=nullptr)
bool matches(QList< QScreen * > screens) const
bool matches(QScreen *screen) const
void saveDisplayLayout(const DisplayLayout &layout)
QVector< DisplayLayout * > displayLayouts
void loadDisplayLayout(const QString &name, KConfigGroup layoutCfg)