1/*
2 * SPDX-FileCopyrightText: 2016 Marco Martin <mart@kde.org>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6
7#include "settings.h"
8
9#include <QDebug>
10#include <QFile>
11#include <QGuiApplication>
12#include <QIcon>
13#include <QInputDevice>
14#include <QMouseEvent>
15#include <QSettings>
16#include <QStandardPaths>
17#include <QWindow>
18
19#include <QtGui/private/qguiapplication_p.h>
20#include <QtGui/qpa/qplatformmenu.h>
21#include <QtGui/qpa/qplatformtheme.h>
22
23#include "kirigamiplatform_version.h"
24#include "smoothscrollwatcher.h"
25#include "tabletmodewatcher.h"
26
27namespace Kirigami
28{
29namespace Platform
30{
31
32class SettingsSingleton
33{
34public:
35 Settings self;
36};
37
38Settings::Settings(QObject *parent)
39 : QObject(parent)
40 , m_hasTouchScreen(false)
41 , m_hasTransientTouchInput(false)
42{
43 m_tabletModeAvailable = TabletModeWatcher::self()->isTabletModeAvailable();
44 connect(sender: TabletModeWatcher::self(), signal: &TabletModeWatcher::tabletModeAvailableChanged, context: this, slot: [this](bool tabletModeAvailable) {
45 setTabletModeAvailable(tabletModeAvailable);
46 });
47
48 m_tabletMode = TabletModeWatcher::self()->isTabletMode();
49 connect(sender: TabletModeWatcher::self(), signal: &TabletModeWatcher::tabletModeChanged, context: this, slot: [this](bool tabletMode) {
50 setTabletMode(tabletMode);
51 });
52
53#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(UBUNTU_TOUCH)
54 m_mobile = true;
55 m_hasTouchScreen = true;
56#else
57 // Mostly for debug purposes and for platforms which are always mobile,
58 // such as Plasma Mobile
59 if (qEnvironmentVariableIsSet(varName: "QT_QUICK_CONTROLS_MOBILE")) {
60 m_mobile = QByteArrayList{"1", "true"}.contains(t: qgetenv(varName: "QT_QUICK_CONTROLS_MOBILE"));
61 } else {
62 m_mobile = false;
63 }
64
65 const auto touchDevices = QInputDevice::devices();
66 const auto touchDeviceType = QInputDevice::DeviceType::TouchScreen;
67 for (const auto &device : touchDevices) {
68 if (device->type() == touchDeviceType) {
69 m_hasTouchScreen = true;
70 break;
71 }
72 }
73 if (m_hasTouchScreen) {
74 connect(qApp, signal: &QGuiApplication::focusWindowChanged, context: this, slot: [this](QWindow *win) {
75 if (win) {
76 win->installEventFilter(filterObj: this);
77 }
78 });
79 }
80#endif
81
82 auto bar = QGuiApplicationPrivate::platformTheme()->createPlatformMenuBar();
83 m_hasPlatformMenuBar = bar != nullptr;
84 if (bar != nullptr) {
85 bar->deleteLater();
86 }
87
88 const QString configPath = QStandardPaths::locate(type: QStandardPaths::ConfigLocation, QStringLiteral("kdeglobals"));
89 if (QFile::exists(fileName: configPath)) {
90 QSettings globals(configPath, QSettings::IniFormat);
91 globals.beginGroup(QStringLiteral("KDE"));
92 m_scrollLines = qMax(a: 1, b: globals.value(QStringLiteral("WheelScrollLines"), defaultValue: 3).toInt());
93 m_smoothScroll = globals.value(QStringLiteral("SmoothScroll"), defaultValue: true).toBool();
94 } else {
95 m_scrollLines = 3;
96 m_smoothScroll = true;
97 }
98
99 connect(sender: SmoothScrollWatcher::self(), signal: &SmoothScrollWatcher::enabledChanged, context: this, slot: [this](bool enabled) {
100 m_smoothScroll = enabled;
101 Q_EMIT smoothScrollChanged();
102 });
103}
104
105Settings::~Settings()
106{
107}
108
109bool Settings::eventFilter(QObject *watched, QEvent *event)
110{
111 Q_UNUSED(watched)
112 switch (event->type()) {
113 case QEvent::TouchBegin:
114 setTransientTouchInput(true);
115 break;
116 case QEvent::MouseButtonPress:
117 case QEvent::MouseMove: {
118 QMouseEvent *me = static_cast<QMouseEvent *>(event);
119 if (me->source() == Qt::MouseEventNotSynthesized) {
120 setTransientTouchInput(false);
121 }
122 break;
123 }
124 case QEvent::Wheel:
125 setTransientTouchInput(false);
126 default:
127 break;
128 }
129
130 return false;
131}
132
133void Settings::setTabletModeAvailable(bool mobileAvailable)
134{
135 if (mobileAvailable == m_tabletModeAvailable) {
136 return;
137 }
138
139 m_tabletModeAvailable = mobileAvailable;
140 Q_EMIT tabletModeAvailableChanged();
141}
142
143bool Settings::isTabletModeAvailable() const
144{
145 return m_tabletModeAvailable;
146}
147
148void Settings::setIsMobile(bool mobile)
149{
150 if (mobile == m_mobile) {
151 return;
152 }
153
154 m_mobile = mobile;
155 Q_EMIT isMobileChanged();
156}
157
158bool Settings::isMobile() const
159{
160 return m_mobile;
161}
162
163void Settings::setTabletMode(bool tablet)
164{
165 if (tablet == m_tabletMode) {
166 return;
167 }
168
169 m_tabletMode = tablet;
170 Q_EMIT tabletModeChanged();
171}
172
173bool Settings::tabletMode() const
174{
175 return m_tabletMode;
176}
177
178void Settings::setTransientTouchInput(bool touch)
179{
180 if (touch == m_hasTransientTouchInput) {
181 return;
182 }
183
184 m_hasTransientTouchInput = touch;
185 if (!m_tabletMode) {
186 Q_EMIT hasTransientTouchInputChanged();
187 }
188}
189
190bool Settings::hasTransientTouchInput() const
191{
192 return m_hasTransientTouchInput || m_tabletMode;
193}
194
195QString Settings::style() const
196{
197 return m_style;
198}
199
200void Settings::setStyle(const QString &style)
201{
202 m_style = style;
203}
204
205int Settings::mouseWheelScrollLines() const
206{
207 return m_scrollLines;
208}
209
210bool Settings::smoothScroll() const
211{
212 return m_smoothScroll;
213}
214
215QStringList Settings::information() const
216{
217 return {
218#ifndef KIRIGAMI_BUILD_TYPE_STATIC
219 tr(s: "KDE Frameworks %1").arg(QStringLiteral(KIRIGAMIPLATFORM_VERSION_STRING)),
220#endif
221 tr(s: "The %1 windowing system").arg(a: QGuiApplication::platformName()),
222 tr(s: "Qt %2 (built against %3)").arg(args: QString::fromLocal8Bit(ba: qVersion()), QStringLiteral(QT_VERSION_STR))};
223}
224
225QVariant Settings::applicationWindowIcon() const
226{
227 const QIcon &windowIcon = qApp->windowIcon();
228 if (windowIcon.isNull()) {
229 return QVariant();
230 }
231 return windowIcon;
232}
233
234bool Settings::hasPlatformMenuBar() const
235{
236 return m_hasPlatformMenuBar;
237}
238
239}
240}
241
242#include "moc_settings.cpp"
243

source code of kirigami/src/platform/settings.cpp