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

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