File indexing completed on 2024-04-28 15:27:44

0001 /*
0002  *  SPDX-FileCopyrightText: 2016 Marco Martin <mart@kde.org>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 #include "settings.h"
0008 
0009 #include <QDebug>
0010 #include <QFile>
0011 #include <QGuiApplication>
0012 #include <QIcon>
0013 #include <QMouseEvent>
0014 #include <QSettings>
0015 #include <QStandardPaths>
0016 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0017 #include <QTouchDevice>
0018 #else
0019 #include <QInputDevice>
0020 #endif
0021 #include <QWindow>
0022 
0023 #include <QtGui/private/qguiapplication_p.h>
0024 #include <QtGui/qpa/qplatformmenu.h>
0025 #include <QtGui/qpa/qplatformtheme.h>
0026 
0027 #include "libkirigami/tabletmodewatcher.h"
0028 
0029 #ifndef KIRIGAMI_BUILD_TYPE_STATIC
0030 #include "../kirigami_version.h"
0031 #endif
0032 
0033 class SettingsSingleton
0034 {
0035 public:
0036     Settings self;
0037 };
0038 
0039 Q_GLOBAL_STATIC(SettingsSingleton, privateSettingsSelf)
0040 
0041 Settings::Settings(QObject *parent)
0042     : QObject(parent)
0043     , m_hasTouchScreen(false)
0044     , m_hasTransientTouchInput(false)
0045 {
0046     m_tabletModeAvailable = Kirigami::TabletModeWatcher::self()->isTabletModeAvailable();
0047     connect(Kirigami::TabletModeWatcher::self(), &Kirigami::TabletModeWatcher::tabletModeAvailableChanged, this, [this](bool tabletModeAvailable) {
0048         setTabletModeAvailable(tabletModeAvailable);
0049     });
0050 
0051     m_tabletMode = Kirigami::TabletModeWatcher::self()->isTabletMode();
0052     connect(Kirigami::TabletModeWatcher::self(), &Kirigami::TabletModeWatcher::tabletModeChanged, this, [this](bool tabletMode) {
0053         setTabletMode(tabletMode);
0054     });
0055 
0056 #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(UBUNTU_TOUCH)
0057     m_mobile = true;
0058     m_hasTouchScreen = true;
0059 #else
0060     // Mostly for debug purposes and for platforms which are always mobile,
0061     // such as Plasma Mobile
0062     if (qEnvironmentVariableIsSet("QT_QUICK_CONTROLS_MOBILE")) {
0063         m_mobile = QByteArrayList{"1", "true"}.contains(qgetenv("QT_QUICK_CONTROLS_MOBILE"));
0064     } else {
0065         m_mobile = false;
0066     }
0067 
0068 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0069     const auto touchDevices = QTouchDevice::devices();
0070     const auto touchDeviceType = QTouchDevice::TouchScreen;
0071 #else
0072     const auto touchDevices = QInputDevice::devices();
0073     const auto touchDeviceType = QInputDevice::DeviceType::TouchScreen;
0074 #endif
0075     for (const auto &device : touchDevices) {
0076         if (device->type() == touchDeviceType) {
0077             m_hasTouchScreen = true;
0078             break;
0079         }
0080     }
0081     if (m_hasTouchScreen) {
0082         connect(qApp, &QGuiApplication::focusWindowChanged, this, [this](QWindow *win) {
0083             if (win) {
0084                 win->installEventFilter(this);
0085             }
0086         });
0087     }
0088 #endif
0089 
0090     auto bar = QGuiApplicationPrivate::platformTheme()->createPlatformMenuBar();
0091     m_hasPlatformMenuBar = bar != nullptr;
0092     if (bar != nullptr) {
0093         bar->deleteLater();
0094     }
0095 
0096     const QString configPath = QStandardPaths::locate(QStandardPaths::ConfigLocation, QStringLiteral("kdeglobals"));
0097     if (QFile::exists(configPath)) {
0098         QSettings globals(configPath, QSettings::IniFormat);
0099         globals.beginGroup(QStringLiteral("KDE"));
0100         m_scrollLines = qMax(1, globals.value(QStringLiteral("WheelScrollLines"), 3).toInt());
0101     } else {
0102         m_scrollLines = 3;
0103     }
0104 }
0105 
0106 Settings::~Settings()
0107 {
0108 }
0109 
0110 Settings *Settings::self()
0111 {
0112     return &privateSettingsSelf()->self;
0113 }
0114 
0115 bool Settings::eventFilter(QObject *watched, QEvent *event)
0116 {
0117     Q_UNUSED(watched)
0118     switch (event->type()) {
0119     case QEvent::TouchBegin:
0120         setTransientTouchInput(true);
0121         break;
0122     case QEvent::MouseButtonPress:
0123     case QEvent::MouseMove: {
0124         QMouseEvent *me = static_cast<QMouseEvent *>(event);
0125         if (me->source() == Qt::MouseEventNotSynthesized) {
0126             setTransientTouchInput(false);
0127         }
0128         break;
0129     }
0130     case QEvent::Wheel:
0131         setTransientTouchInput(false);
0132     default:
0133         break;
0134     }
0135 
0136     return false;
0137 }
0138 
0139 void Settings::setTabletModeAvailable(bool mobileAvailable)
0140 {
0141     if (mobileAvailable == m_tabletModeAvailable) {
0142         return;
0143     }
0144 
0145     m_tabletModeAvailable = mobileAvailable;
0146     Q_EMIT tabletModeAvailableChanged();
0147 }
0148 
0149 bool Settings::isTabletModeAvailable() const
0150 {
0151     return m_tabletModeAvailable;
0152 }
0153 
0154 void Settings::setIsMobile(bool mobile)
0155 {
0156     if (mobile == m_mobile) {
0157         return;
0158     }
0159 
0160     m_mobile = mobile;
0161     Q_EMIT isMobileChanged();
0162 }
0163 
0164 bool Settings::isMobile() const
0165 {
0166     return m_mobile;
0167 }
0168 
0169 void Settings::setTabletMode(bool tablet)
0170 {
0171     if (tablet == m_tabletMode) {
0172         return;
0173     }
0174 
0175     m_tabletMode = tablet;
0176     Q_EMIT tabletModeChanged();
0177 }
0178 
0179 bool Settings::tabletMode() const
0180 {
0181     return m_tabletMode;
0182 }
0183 
0184 void Settings::setTransientTouchInput(bool touch)
0185 {
0186     if (touch == m_hasTransientTouchInput) {
0187         return;
0188     }
0189 
0190     m_hasTransientTouchInput = touch;
0191     if (!m_tabletMode) {
0192         Q_EMIT hasTransientTouchInputChanged();
0193     }
0194 }
0195 
0196 bool Settings::hasTransientTouchInput() const
0197 {
0198     return m_hasTransientTouchInput || m_tabletMode;
0199 }
0200 
0201 QString Settings::style() const
0202 {
0203     return m_style;
0204 }
0205 
0206 void Settings::setStyle(const QString &style)
0207 {
0208     m_style = style;
0209 }
0210 
0211 int Settings::mouseWheelScrollLines() const
0212 {
0213     return m_scrollLines;
0214 }
0215 
0216 QStringList Settings::information() const
0217 {
0218     return {
0219 #ifndef KIRIGAMI_BUILD_TYPE_STATIC
0220         tr("KDE Frameworks %1").arg(QStringLiteral(KIRIGAMI2_VERSION_STRING)),
0221 #endif
0222         tr("The %1 windowing system").arg(QGuiApplication::platformName()),
0223         tr("Qt %2 (built against %3)").arg(QString::fromLocal8Bit(qVersion()), QStringLiteral(QT_VERSION_STR))};
0224 }
0225 
0226 QVariant Settings::applicationWindowIcon() const
0227 {
0228     const QIcon &windowIcon = qApp->windowIcon();
0229     if (windowIcon.isNull()) {
0230         return QVariant();
0231     }
0232     return windowIcon;
0233 }
0234 
0235 bool Settings::hasPlatformMenuBar() const
0236 {
0237     return m_hasPlatformMenuBar;
0238 }
0239 
0240 #include "moc_settings.cpp"