| 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 | |
| 27 | namespace Kirigami |
| 28 | { |
| 29 | namespace Platform |
| 30 | { |
| 31 | |
| 32 | class SettingsSingleton |
| 33 | { |
| 34 | public: |
| 35 | Settings self; |
| 36 | }; |
| 37 | |
| 38 | Settings::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 | |
| 105 | Settings::~Settings() |
| 106 | { |
| 107 | } |
| 108 | |
| 109 | bool 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 | |
| 133 | void Settings::setTabletModeAvailable(bool mobileAvailable) |
| 134 | { |
| 135 | if (mobileAvailable == m_tabletModeAvailable) { |
| 136 | return; |
| 137 | } |
| 138 | |
| 139 | m_tabletModeAvailable = mobileAvailable; |
| 140 | Q_EMIT tabletModeAvailableChanged(); |
| 141 | } |
| 142 | |
| 143 | bool Settings::isTabletModeAvailable() const |
| 144 | { |
| 145 | return m_tabletModeAvailable; |
| 146 | } |
| 147 | |
| 148 | void Settings::setIsMobile(bool mobile) |
| 149 | { |
| 150 | if (mobile == m_mobile) { |
| 151 | return; |
| 152 | } |
| 153 | |
| 154 | m_mobile = mobile; |
| 155 | Q_EMIT isMobileChanged(); |
| 156 | } |
| 157 | |
| 158 | bool Settings::isMobile() const |
| 159 | { |
| 160 | return m_mobile; |
| 161 | } |
| 162 | |
| 163 | void Settings::setTabletMode(bool tablet) |
| 164 | { |
| 165 | if (tablet == m_tabletMode) { |
| 166 | return; |
| 167 | } |
| 168 | |
| 169 | m_tabletMode = tablet; |
| 170 | Q_EMIT tabletModeChanged(); |
| 171 | } |
| 172 | |
| 173 | bool Settings::tabletMode() const |
| 174 | { |
| 175 | return m_tabletMode; |
| 176 | } |
| 177 | |
| 178 | void 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 | |
| 190 | bool Settings::hasTransientTouchInput() const |
| 191 | { |
| 192 | return m_hasTransientTouchInput || m_tabletMode; |
| 193 | } |
| 194 | |
| 195 | QString Settings::style() const |
| 196 | { |
| 197 | return m_style; |
| 198 | } |
| 199 | |
| 200 | void Settings::setStyle(const QString &style) |
| 201 | { |
| 202 | m_style = style; |
| 203 | } |
| 204 | |
| 205 | int Settings::mouseWheelScrollLines() const |
| 206 | { |
| 207 | return m_scrollLines; |
| 208 | } |
| 209 | |
| 210 | bool Settings::smoothScroll() const |
| 211 | { |
| 212 | return m_smoothScroll; |
| 213 | } |
| 214 | |
| 215 | QStringList 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 | |
| 225 | QVariant Settings::applicationWindowIcon() const |
| 226 | { |
| 227 | const QIcon &windowIcon = qApp->windowIcon(); |
| 228 | if (windowIcon.isNull()) { |
| 229 | return QVariant(); |
| 230 | } |
| 231 | return windowIcon; |
| 232 | } |
| 233 | |
| 234 | bool Settings::() const |
| 235 | { |
| 236 | return m_hasPlatformMenuBar; |
| 237 | } |
| 238 | |
| 239 | } |
| 240 | } |
| 241 | |
| 242 | #include "moc_settings.cpp" |
| 243 | |