1 /*
2     SPDX-FileCopyrightText: 2017 Smith AR <audoban@openmailbox.org>
3     SPDX-FileCopyrightText: 2017 Michail Vourlakos <mvourlakos@gmail.com>
4 
5     SPDX-License-Identifier: GPL-2.0-or-later
6 */
7 
8 #include "universalsettings.h"
9 
10 // local
11 #include "../data/contextmenudata.h"
12 #include "../data/layoutdata.h"
13 #include "../layout/centrallayout.h"
14 #include "../layouts/importer.h"
15 #include "../layouts/manager.h"
16 #include "../tools/commontools.h"
17 
18 // Qt
19 #include <QDebug>
20 #include <QDir>
21 #include <QtDBus>
22 
23 // KDE
24 #include <KActivities/Consumer>
25 #include <KDirWatch>
26 #include <KWindowSystem>
27 
28 #define KWINMETAFORWARDTOLATTESTRING "org.kde.lattedock,/Latte,org.kde.LatteDock,activateLauncherMenu"
29 #define KWINMETAFORWARDTOPLASMASTRING "org.kde.plasmashell,/PlasmaShell,org.kde.PlasmaShell,activateLauncherMenu"
30 
31 #define KWINCOLORSSCRIPT "kwin/scripts/lattewindowcolors"
32 #define KWINRC "kwinrc"
33 
34 #define KWINRCTRACKERINTERVAL 2500
35 
36 namespace Latte {
37 
UniversalSettings(KSharedConfig::Ptr config,QObject * parent)38 UniversalSettings::UniversalSettings(KSharedConfig::Ptr config, QObject *parent)
39     : QObject(parent),
40       m_config(config),
41       m_universalGroup(KConfigGroup(config, QStringLiteral("UniversalSettings")))
42 {
43     m_corona = qobject_cast<Latte::Corona *>(parent);
44 
45     connect(this, &UniversalSettings::actionsChanged, this, &UniversalSettings::saveConfig);
46     connect(this, &UniversalSettings::badges3DStyleChanged, this, &UniversalSettings::saveConfig);
47     connect(this, &UniversalSettings::canDisableBordersChanged, this, &UniversalSettings::saveConfig);
48     connect(this, &UniversalSettings::inAdvancedModeForEditSettingsChanged, this, &UniversalSettings::saveConfig);
49     connect(this, &UniversalSettings::isAvailableGeometryBroadcastedToPlasmaChanged, this, &UniversalSettings::saveConfig);
50     connect(this, &UniversalSettings::launchersChanged, this, &UniversalSettings::saveConfig);
51     connect(this, &UniversalSettings::layoutsMemoryUsageChanged, this, &UniversalSettings::saveConfig);
52     connect(this, &UniversalSettings::metaPressAndHoldEnabledChanged, this, &UniversalSettings::saveConfig);
53     connect(this, &UniversalSettings::sensitivityChanged, this, &UniversalSettings::saveConfig);
54     connect(this, &UniversalSettings::screenTrackerIntervalChanged, this, &UniversalSettings::saveConfig);
55     connect(this, &UniversalSettings::showInfoWindowChanged, this, &UniversalSettings::saveConfig);
56     connect(this, &UniversalSettings::singleModeLayoutNameChanged, this, &UniversalSettings::saveConfig);
57     connect(this, &UniversalSettings::versionChanged, this, &UniversalSettings::saveConfig);
58 
59     connect(this, &UniversalSettings::screenScalesChanged, this, &UniversalSettings::saveScalesConfig);
60 
61     connect(qGuiApp, &QGuiApplication::screenAdded, this, &UniversalSettings::screensCountChanged);
62     connect(qGuiApp, &QGuiApplication::screenRemoved, this, &UniversalSettings::screensCountChanged);
63 
64     m_kwinrcPtr = KSharedConfig::openConfig(Latte::configPath() + "/" + KWINRC);
65     m_kwinrcModifierOnlyShortcutsGroup = KConfigGroup(m_kwinrcPtr, QStringLiteral("ModifierOnlyShortcuts"));
66     m_kwinrcWindowsGroup = KConfigGroup(m_kwinrcPtr, QStringLiteral("Windows"));
67 }
68 
~UniversalSettings()69 UniversalSettings::~UniversalSettings()
70 {
71     saveConfig();
72     cleanupSettings();
73 }
74 
load()75 void UniversalSettings::load()
76 {
77     //! check if user has set the autostart option
78     bool autostartUserSet = m_universalGroup.readEntry("userConfiguredAutostart", false);
79 
80     if (!autostartUserSet && !autostart()) {
81         //! the first time the application is running and autostart is not set, autostart is enabled
82         //! and from now own it will not be recreated in the beginning
83 
84         setAutostart(true);
85         m_universalGroup.writeEntry("userConfiguredAutostart", true);
86     }
87 
88     //! init screen scales
89     m_screenScalesGroup = m_universalGroup.group("ScreenScales");
90 
91     //! load configuration
92     loadConfig();
93 
94     //! Track KWin Colors Script Presence
95     updateColorsScriptIsPresent();
96 
97     QStringList colorsScriptPaths = Layouts::Importer::standardPathsFor(KWINCOLORSSCRIPT);
98     for(auto path: colorsScriptPaths) {
99         KDirWatch::self()->addDir(path);
100     }
101 
102     //! Track KWin rc options
103     const QString kwinrcFilePath = Latte::configPath() + "/" + KWINRC;
104     KDirWatch::self()->addFile(kwinrcFilePath);
105     recoverKWinOptions();
106 
107     m_kwinrcTrackerTimer.setSingleShot(true);
108     m_kwinrcTrackerTimer.setInterval(KWINRCTRACKERINTERVAL);
109     connect(&m_kwinrcTrackerTimer, &QTimer::timeout, this, &UniversalSettings::recoverKWinOptions);
110 
111     connect(KDirWatch::self(), &KDirWatch::created, this, &UniversalSettings::trackedFileChanged);
112     connect(KDirWatch::self(), &KDirWatch::deleted, this, &UniversalSettings::trackedFileChanged);
113     connect(KDirWatch::self(), &KDirWatch::dirty, this, &UniversalSettings::trackedFileChanged);
114 
115     //! this is needed to inform globalshortcuts to update its modifiers tracking
116     emit metaPressAndHoldEnabledChanged();
117 }
118 
inAdvancedModeForEditSettings() const119 bool UniversalSettings::inAdvancedModeForEditSettings() const
120 {
121     return m_inAdvancedModeForEditSettings;
122 }
123 
setInAdvancedModeForEditSettings(const bool & inAdvanced)124 void UniversalSettings::setInAdvancedModeForEditSettings(const bool &inAdvanced)
125 {
126     if (m_inAdvancedModeForEditSettings == inAdvanced) {
127         return;
128     }
129 
130     m_inAdvancedModeForEditSettings = inAdvanced;
131     emit inAdvancedModeForEditSettingsChanged();
132 }
133 
isAvailableGeometryBroadcastedToPlasma() const134 bool UniversalSettings::isAvailableGeometryBroadcastedToPlasma() const
135 {
136     return m_isAvailableGeometryBroadcastedToPlasma;
137 }
138 
setIsAvailableGeometryBroadcastedToPlasma(const bool & isBroadcasted)139 void UniversalSettings::setIsAvailableGeometryBroadcastedToPlasma(const bool &isBroadcasted)
140 {
141     if (m_isAvailableGeometryBroadcastedToPlasma == isBroadcasted) {
142         return;
143     }
144 
145     m_isAvailableGeometryBroadcastedToPlasma = isBroadcasted;
146     emit isAvailableGeometryBroadcastedToPlasmaChanged();
147 }
148 
showInfoWindow() const149 bool UniversalSettings::showInfoWindow() const
150 {
151     return m_showInfoWindow;
152 }
153 
setShowInfoWindow(bool show)154 void UniversalSettings::setShowInfoWindow(bool show)
155 {
156     if (m_showInfoWindow == show) {
157         return;
158     }
159 
160     m_showInfoWindow = show;
161     emit showInfoWindowChanged();
162 }
163 
version() const164 int UniversalSettings::version() const
165 {
166     return m_version;
167 }
168 
setVersion(int ver)169 void UniversalSettings::setVersion(int ver)
170 {
171     if (m_version == ver) {
172         return;
173     }
174 
175     m_version = ver;
176     qDebug() << "Universal Settings version updated to : " << m_version;
177 
178     emit versionChanged();
179 }
180 
screenTrackerInterval() const181 int UniversalSettings::screenTrackerInterval() const
182 {
183     return m_screenTrackerInterval;
184 }
185 
setScreenTrackerInterval(int duration)186 void UniversalSettings::setScreenTrackerInterval(int duration)
187 {
188     if (m_screenTrackerInterval == duration) {
189         return;
190     }
191 
192     m_screenTrackerInterval = duration;
193     emit screenTrackerIntervalChanged();
194 }
195 
singleModeLayoutName() const196 QString UniversalSettings::singleModeLayoutName() const
197 {
198     return m_singleModeLayoutName;
199 }
200 
setSingleModeLayoutName(QString layoutName)201 void UniversalSettings::setSingleModeLayoutName(QString layoutName)
202 {
203     if (m_singleModeLayoutName == layoutName) {
204         return;
205     }
206 
207     m_singleModeLayoutName = layoutName;
208     emit singleModeLayoutNameChanged();
209 }
210 
contextMenuActionsAlwaysShown() const211 QStringList UniversalSettings::contextMenuActionsAlwaysShown() const
212 {
213     return m_contextMenuActionsAlwaysShown;
214 }
215 
setContextMenuActionsAlwaysShown(const QStringList & actions)216 void UniversalSettings::setContextMenuActionsAlwaysShown(const QStringList &actions)
217 {
218     if (m_contextMenuActionsAlwaysShown == actions) {
219         return;
220     }
221 
222     m_contextMenuActionsAlwaysShown = actions;
223     emit actionsChanged();
224 }
225 
launchers() const226 QStringList UniversalSettings::launchers() const
227 {
228     return m_launchers;
229 }
230 
setLaunchers(QStringList launcherList)231 void UniversalSettings::setLaunchers(QStringList launcherList)
232 {
233     if (m_launchers == launcherList) {
234         return;
235     }
236 
237     m_launchers = launcherList;
238     emit launchersChanged();
239 }
240 
241 
autostart() const242 bool UniversalSettings::autostart() const
243 {
244     return Layouts::Importer::isAutostartEnabled();
245 }
246 
setAutostart(bool state)247 void UniversalSettings::setAutostart(bool state)
248 {
249     if (autostart() == state) {
250         return;
251     }
252 
253     if (state) {
254         Layouts::Importer::enableAutostart();
255     } else {
256         Layouts::Importer::disableAutostart();
257     }
258 
259     emit autostartChanged();
260 }
261 
badges3DStyle() const262 bool UniversalSettings::badges3DStyle() const
263 {
264     return m_badges3DStyle;
265 }
266 
setBadges3DStyle(bool enable)267 void UniversalSettings::setBadges3DStyle(bool enable)
268 {
269     if (m_badges3DStyle == enable) {
270         return;
271     }
272 
273     m_badges3DStyle = enable;
274     emit badges3DStyleChanged();
275 }
276 
277 
canDisableBorders() const278 bool UniversalSettings::canDisableBorders() const
279 {
280     return m_canDisableBorders;
281 }
282 
setCanDisableBorders(bool enable)283 void UniversalSettings::setCanDisableBorders(bool enable)
284 {
285     if (m_canDisableBorders == enable) {
286         return;
287     }
288 
289     m_canDisableBorders = enable;
290     emit canDisableBordersChanged();
291 }
292 
colorsScriptIsPresent() const293 bool UniversalSettings::colorsScriptIsPresent() const
294 {
295     return m_colorsScriptIsPresent;
296 }
297 
setColorsScriptIsPresent(bool present)298 void UniversalSettings::setColorsScriptIsPresent(bool present)
299 {
300     if (m_colorsScriptIsPresent == present) {
301         return;
302     }
303 
304     m_colorsScriptIsPresent = present;
305     emit colorsScriptIsPresentChanged();
306 }
307 
updateColorsScriptIsPresent()308 void UniversalSettings::updateColorsScriptIsPresent()
309 {
310     qDebug() << "Updating Latte Colors Script presence...";
311 
312     setColorsScriptIsPresent(!Layouts::Importer::standardPath(KWINCOLORSSCRIPT).isEmpty());
313 }
314 
trackedFileChanged(const QString & file)315 void UniversalSettings::trackedFileChanged(const QString &file)
316 {
317     if (file.endsWith(KWINCOLORSSCRIPT)) {
318         updateColorsScriptIsPresent();
319     }
320 
321     if (file.endsWith(KWINRC)) {
322         m_kwinrcTrackerTimer.start();
323     }
324 }
325 
kwin_metaForwardedToLatte() const326 bool UniversalSettings::kwin_metaForwardedToLatte() const
327 {
328     return m_kwinMetaForwardedToLatte;
329 }
330 
kwin_borderlessMaximizedWindowsEnabled() const331 bool UniversalSettings::kwin_borderlessMaximizedWindowsEnabled() const
332 {
333     return m_kwinBorderlessMaximizedWindows;
334 }
335 
kwin_forwardMetaToLatte(bool forward)336 void UniversalSettings::kwin_forwardMetaToLatte(bool forward)
337 {
338     if (m_kwinMetaForwardedToLatte == forward) {
339         return;
340     }
341 
342     if (KWindowSystem::isPlatformWayland()) {
343         // BUG: https://bugs.kde.org/show_bug.cgi?id=428202
344         // KWin::reconfigure() function blocks/freezes Latte under wayland
345         return;
346     }
347 
348     QString forwardStr = (forward ? KWINMETAFORWARDTOLATTESTRING : KWINMETAFORWARDTOPLASMASTRING);
349     m_kwinrcModifierOnlyShortcutsGroup.writeEntry("Meta", forwardStr);
350     m_kwinrcModifierOnlyShortcutsGroup.sync();
351 
352     QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KWin"),
353                                                           QStringLiteral("/KWin"),
354                                                           QStringLiteral("org.kde.KWin"),
355                                                           QStringLiteral("reconfigure"));
356 
357     QDBusConnection::sessionBus().call(message, QDBus::NoBlock);
358 }
359 
kwin_setDisabledMaximizedBorders(bool disable)360 void UniversalSettings::kwin_setDisabledMaximizedBorders(bool disable)
361 {
362     if (m_kwinBorderlessMaximizedWindows == disable) {
363         return;
364     }
365 
366     if (KWindowSystem::isPlatformWayland()) {
367         // BUG: https://bugs.kde.org/show_bug.cgi?id=428202
368         // KWin::reconfigure() function blocks/freezes Latte under wayland
369         return;
370     }
371 
372     bool serviceavailable{false};
373 
374     if (QDBusConnection::sessionBus().interface()) {
375         serviceavailable = QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.KWin").value();
376     }
377 
378     if (serviceavailable) {
379         m_kwinrcWindowsGroup.writeEntry("BorderlessMaximizedWindows", disable);
380         m_kwinrcWindowsGroup.sync();
381 
382         QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KWin"),
383                                                               QStringLiteral("/KWin"),
384                                                               QStringLiteral("org.kde.KWin"),
385                                                               QStringLiteral("reconfigure"));
386 
387         QDBusConnection::sessionBus().call(message, QDBus::NoBlock);
388         m_kwinBorderlessMaximizedWindows = disable;
389     }
390 }
391 
recoverKWinOptions()392 void UniversalSettings::recoverKWinOptions()
393 {
394     qDebug() << "kwinrc: recovering values...";
395 
396     //! Meta forwarded to Latte option
397     QString metaforwardedstr = m_kwinrcModifierOnlyShortcutsGroup.readEntry("Meta", KWINMETAFORWARDTOPLASMASTRING);
398     m_kwinMetaForwardedToLatte = (metaforwardedstr == KWINMETAFORWARDTOLATTESTRING);
399 
400     //! BorderlessMaximizedWindows option
401     m_kwinBorderlessMaximizedWindows = m_kwinrcWindowsGroup.readEntry("BorderlessMaximizedWindows", false);
402 }
403 
metaPressAndHoldEnabled() const404 bool UniversalSettings::metaPressAndHoldEnabled() const
405 {
406     return m_metaPressAndHoldEnabled;
407 }
408 
setMetaPressAndHoldEnabled(bool enabled)409 void UniversalSettings::setMetaPressAndHoldEnabled(bool enabled)
410 {
411     if (m_metaPressAndHoldEnabled == enabled) {
412         return;
413     }
414 
415     m_metaPressAndHoldEnabled = enabled;
416 
417     emit metaPressAndHoldEnabledChanged();
418 }
419 
layoutsMemoryUsage() const420 MemoryUsage::LayoutsMemory UniversalSettings::layoutsMemoryUsage() const
421 {
422     return m_memoryUsage;
423 }
424 
setLayoutsMemoryUsage(MemoryUsage::LayoutsMemory layoutsMemoryUsage)425 void UniversalSettings::setLayoutsMemoryUsage(MemoryUsage::LayoutsMemory layoutsMemoryUsage)
426 {
427     if (m_memoryUsage == layoutsMemoryUsage) {
428         return;
429     }
430 
431     m_memoryUsage = layoutsMemoryUsage;
432     emit layoutsMemoryUsageChanged();
433 }
434 
sensitivity()435 Settings::MouseSensitivity UniversalSettings::sensitivity()
436 {
437     return m_sensitivity;
438 }
439 
setSensitivity(Settings::MouseSensitivity sense)440 void UniversalSettings::setSensitivity(Settings::MouseSensitivity sense)
441 {
442     if (m_sensitivity == sense) {
443         return;
444     }
445 
446     m_sensitivity = sense;
447     emit sensitivityChanged();
448 }
449 
screenWidthScale(QString screenName) const450 float UniversalSettings::screenWidthScale(QString screenName) const
451 {
452     if (!m_screenScales.contains(screenName)) {
453         return 1;
454     }
455 
456     return m_screenScales[screenName].first;
457 }
458 
screenHeightScale(QString screenName) const459 float UniversalSettings::screenHeightScale(QString screenName) const
460 {
461     if (!m_screenScales.contains(screenName)) {
462         return 1;
463     }
464 
465     return m_screenScales[screenName].second;
466 }
467 
setScreenScales(QString screenName,float widthScale,float heightScale)468 void UniversalSettings::setScreenScales(QString screenName, float widthScale, float heightScale)
469 {
470     if (!m_screenScales.contains(screenName)) {
471         m_screenScales[screenName].first = widthScale;
472         m_screenScales[screenName].second = heightScale;
473     } else {
474         if (m_screenScales[screenName].first == widthScale
475                 && m_screenScales[screenName].second == heightScale) {
476             return;
477         }
478 
479         m_screenScales[screenName].first = widthScale;
480         m_screenScales[screenName].second = heightScale;
481     }
482 
483     emit screenScalesChanged();
484 }
485 
syncSettings()486 void UniversalSettings::syncSettings()
487 {
488     m_universalGroup.sync();
489 }
490 
upgrade_v010()491 void UniversalSettings::upgrade_v010()
492 {
493     if (m_singleModeLayoutName.isEmpty()) {
494         //!Upgrading path for v0.9 to v0.10
495         QString lastNonAssigned = m_universalGroup.readEntry("lastNonAssignedLayout", QString());
496         QString currentLayout = m_universalGroup.readEntry("currentLayout", QString());
497 
498         if (!lastNonAssigned.isEmpty()) {
499             m_singleModeLayoutName = lastNonAssigned;
500         } else if (!currentLayout.isEmpty()) {
501             m_singleModeLayoutName = currentLayout;
502         }
503 
504         if (!m_singleModeLayoutName.isEmpty() && Layouts::Importer::layoutExists(m_singleModeLayoutName)) {
505             //! it is executed only after the upgrade path
506             m_universalGroup.writeEntry("singleModeLayoutName", m_singleModeLayoutName);
507             CentralLayout storage(this, Layouts::Importer::layoutUserFilePath(m_singleModeLayoutName));
508             if (m_singleModeLayoutName == lastNonAssigned) {
509                 storage.setActivities(QStringList(Data::Layout::FREEACTIVITIESID));
510             } else if (storage.activities().isEmpty()) {
511                 storage.setActivities(QStringList(Data::Layout::ALLACTIVITIESID));
512             }
513         }
514     }
515 }
516 
loadConfig()517 void UniversalSettings::loadConfig()
518 {
519     m_version = m_universalGroup.readEntry("version", 1);
520     m_badges3DStyle = m_universalGroup.readEntry("badges3DStyle", false);
521     m_canDisableBorders = m_universalGroup.readEntry("canDisableBorders", false);
522     m_contextMenuActionsAlwaysShown = m_universalGroup.readEntry("contextMenuActionsAlwaysShown", Latte::Data::ContextMenu::ACTIONSALWAYSVISIBLE);
523     m_inAdvancedModeForEditSettings = m_universalGroup.readEntry("inAdvancedModeForEditSettings", false);
524     m_isAvailableGeometryBroadcastedToPlasma = m_universalGroup.readEntry("isAvailableGeometryBroadcastedToPlasma", true);
525     m_launchers = m_universalGroup.readEntry("launchers", QStringList());
526     m_metaPressAndHoldEnabled = m_universalGroup.readEntry("metaPressAndHoldEnabled", true);
527     m_screenTrackerInterval = m_universalGroup.readEntry("screenTrackerInterval", 2500);
528     m_showInfoWindow = m_universalGroup.readEntry("showInfoWindow", true);
529     m_singleModeLayoutName = m_universalGroup.readEntry("singleModeLayoutName", QString());
530     m_memoryUsage = static_cast<MemoryUsage::LayoutsMemory>(m_universalGroup.readEntry("memoryUsage", (int)MemoryUsage::SingleLayout));
531     m_sensitivity = static_cast<Settings::MouseSensitivity>(m_universalGroup.readEntry("mouseSensitivity", (int)Settings::HighMouseSensitivity));
532 
533     loadScalesConfig();
534 
535     if (m_singleModeLayoutName.isEmpty()) {
536         upgrade_v010();
537     }
538 }
539 
saveConfig()540 void UniversalSettings::saveConfig()
541 {
542     m_universalGroup.writeEntry("version", m_version);
543     m_universalGroup.writeEntry("badges3DStyle", m_badges3DStyle);
544     m_universalGroup.writeEntry("canDisableBorders", m_canDisableBorders);
545     m_universalGroup.writeEntry("contextMenuActionsAlwaysShown", m_contextMenuActionsAlwaysShown);
546     m_universalGroup.writeEntry("inAdvancedModeForEditSettings", m_inAdvancedModeForEditSettings);
547     m_universalGroup.writeEntry("isAvailableGeometryBroadcastedToPlasma", m_isAvailableGeometryBroadcastedToPlasma);
548     m_universalGroup.writeEntry("launchers", m_launchers);
549     m_universalGroup.writeEntry("metaPressAndHoldEnabled", m_metaPressAndHoldEnabled);
550     m_universalGroup.writeEntry("screenTrackerInterval", m_screenTrackerInterval);
551     m_universalGroup.writeEntry("showInfoWindow", m_showInfoWindow);
552     m_universalGroup.writeEntry("singleModeLayoutName", m_singleModeLayoutName);
553     m_universalGroup.writeEntry("memoryUsage", (int)m_memoryUsage);
554     m_universalGroup.writeEntry("mouseSensitivity", (int)m_sensitivity);
555     syncSettings();
556 }
557 
cleanupSettings()558 void UniversalSettings::cleanupSettings()
559 {
560     KConfigGroup containments = KConfigGroup(m_config, QStringLiteral("Containments"));
561     containments.deleteGroup();
562 
563     containments.sync();
564 }
565 
splitterIconPath()566 QString UniversalSettings::splitterIconPath()
567 {
568     return m_corona->kPackage().filePath("splitter");
569 }
570 
trademarkPath()571 QString UniversalSettings::trademarkPath()
572 {
573     return m_corona->kPackage().filePath("trademark");
574 }
575 
trademarkIconPath()576 QString UniversalSettings::trademarkIconPath()
577 {
578     return m_corona->kPackage().filePath("trademarkicon");
579 }
580 
screens()581 QQmlListProperty<QScreen> UniversalSettings::screens()
582 {
583     return QQmlListProperty<QScreen>(this, nullptr, &countScreens, &atScreens);
584 }
585 
countScreens(QQmlListProperty<QScreen> * property)586 int UniversalSettings::countScreens(QQmlListProperty<QScreen> *property)
587 {
588     Q_UNUSED(property)
589     return qGuiApp->screens().count();
590 }
591 
atScreens(QQmlListProperty<QScreen> * property,int index)592 QScreen *UniversalSettings::atScreens(QQmlListProperty<QScreen> *property, int index)
593 {
594     Q_UNUSED(property)
595     return qGuiApp->screens().at(index);
596 }
597 
loadScalesConfig()598 void UniversalSettings::loadScalesConfig()
599 {
600     for (const auto &screenName : m_screenScalesGroup.keyList()) {
601         QString scalesStr = m_screenScalesGroup.readEntry(screenName, QString());
602         QStringList scales = scalesStr.split(";");
603         if (scales.count() == 2) {
604             m_screenScales[screenName] = qMakePair(scales[0].toFloat(), scales[1].toFloat());
605         }
606     }
607 }
608 
saveScalesConfig()609 void UniversalSettings::saveScalesConfig()
610 {
611     for (const auto &screenName : m_screenScales.keys()) {
612         QStringList scales;
613         scales << QString::number(m_screenScales[screenName].first) << QString::number(m_screenScales[screenName].second);
614         m_screenScalesGroup.writeEntry(screenName, scales.join(";"));
615     }
616 
617     m_screenScalesGroup.sync();
618 }
619 
620 }
621