diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,6 +99,11 @@ SOVERSION 5 ) +#use dbus on linux, bsd etc, but not andoid and apple stuff +if (UNIX AND NOT CMAKE_SYSTEM_NAME STREQUAL "Android" AND NOT(APPLE)) + find_package(Qt5DBus) +endif() + if(BUILD_EXAMPLES AND CMAKE_SYSTEM_NAME STREQUAL "Android") find_package(Qt5AndroidExtras ${REQUIRED_QT_VERSION} REQUIRED) endif() diff --git a/examples/gallerydata/contents/ui/gallery/ListViewGallery.qml b/examples/gallerydata/contents/ui/gallery/ListViewGallery.qml --- a/examples/gallerydata/contents/ui/gallery/ListViewGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/ListViewGallery.qml @@ -99,10 +99,12 @@ actions: [ Kirigami.Action { iconName: "document-decrypt" + text: "Action 1" onTriggered: showPassiveNotification(model.text + " Action 1 clicked") }, Kirigami.Action { iconName: "mail-reply-sender" + text: "Action 2" onTriggered: showPassiveNotification(model.text + " Action 2 clicked") }] } diff --git a/examples/gallerydata/contents/ui/gallery/MiscGallery.qml b/examples/gallerydata/contents/ui/gallery/MiscGallery.qml --- a/examples/gallerydata/contents/ui/gallery/MiscGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/MiscGallery.qml @@ -176,6 +176,14 @@ } } } + Label { + Layout.alignment: Qt.AlignHCenter + text: Settings.isMobile ? "We are in mobile device mode" : "We not in mobile mode" + } + Label { + Layout.alignment: Qt.AlignHCenter + text: Settings.tabletMode ? "We are in tablet mode" : "We are not in tablet mode" + } Column { Layout.alignment: Qt.AlignHCenter Controls.ItemDelegate { diff --git a/examples/gallerydata/contents/ui/gallery/TextFieldGallery.qml b/examples/gallerydata/contents/ui/gallery/TextFieldGallery.qml --- a/examples/gallerydata/contents/ui/gallery/TextFieldGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/TextFieldGallery.qml @@ -60,24 +60,20 @@ Controls.Label { text: "Text area:" } - //this to make text selection work on Android - //QQC2 should do this by itself - MouseArea { + + Controls.TextArea { + id: field Layout.fillWidth: true - drag.filterChildren: Settings.isMobile - implicitHeight: field.implicitHeight + text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent eu nisl ac nibh malesuada pretium ut sit amet libero. Nulla libero arcu, pharetra a dignissim nec, iaculis sit amet metus. Suspendisse quis justo efficitur, pharetra dui maximus, aliquam dolor. Vestibulum vel imperdiet turpis. Mauris ut leo mauris. Praesent ut libero sollicitudin, tincidunt nisi a, efficitur erat. Curabitur lacinia leo et tempor aliquam." + Layout.minimumWidth: Kirigami.Units.gridUnit * 12 + Layout.minimumHeight: Kirigami.Units.gridUnit * 12 + wrapMode: Controls.TextArea.WordWrap + //this to make text selection work on Android + //QQC2 should do this by itself onPressAndHold: { - field.forceActiveFocus(); - field.cursorPosition = field.positionAt(mouse.x, mouse.y); - field.selectWord(); - } - Controls.TextArea { - id: field - anchors.fill: parent - text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent eu nisl ac nibh malesuada pretium ut sit amet libero. Nulla libero arcu, pharetra a dignissim nec, iaculis sit amet metus. Suspendisse quis justo efficitur, pharetra dui maximus, aliquam dolor. Vestibulum vel imperdiet turpis. Mauris ut leo mauris. Praesent ut libero sollicitudin, tincidunt nisi a, efficitur erat. Curabitur lacinia leo et tempor aliquam." - Layout.minimumWidth: Kirigami.Units.gridUnit * 12 - Layout.minimumHeight: Kirigami.Units.gridUnit * 12 - wrapMode: Controls.TextArea.WordWrap + forceActiveFocus(); + cursorPosition = positionAt(event.x, event.y); + selectWord(); } } } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -37,7 +37,11 @@ if(STATIC_LIBRARY) SET_TARGET_PROPERTIES(kirigamiplugin PROPERTIES AUTOMOC_MOC_OPTIONS -Muri=org.kde.kirigami) - set(Kirigami_EXTRA_LIBS "") + if (UNIX AND NOT CMAKE_SYSTEM_NAME STREQUAL "Android" AND NOT(APPLE)) + set(Kirigami_EXTRA_LIBS Qt5::DBus) + else() + set(Kirigami_EXTRA_LIBS "") + endif() else(STATIC_LIBRARY) set(Kirigami_EXTRA_LIBS KF5::Kirigami2) endif(STATIC_LIBRARY) diff --git a/src/controls/BasicListItem.qml b/src/controls/BasicListItem.qml --- a/src/controls/BasicListItem.qml +++ b/src/controls/BasicListItem.qml @@ -60,7 +60,7 @@ RowLayout { id: layout spacing: Units.smallSpacing*2 - property bool indicateActiveFocus: listItem.pressed || Settings.isMobile || listItem.activeFocus || (listItem.ListView.view ? listItem.ListView.view.activeFocus : false) + property bool indicateActiveFocus: listItem.pressed || Settings.tabletMode || listItem.activeFocus || (listItem.ListView.view ? listItem.ListView.view.activeFocus : false) Icon { id: iconItem source: listItem.icon && listItem.icon.hasOwnProperty && listItem.icon.hasOwnProperty("name") ? listItem.icon.name : listItem.icon diff --git a/src/controls/private/ActionButton.qml b/src/controls/private/ActionButton.qml --- a/src/controls/private/ActionButton.qml +++ b/src/controls/private/ActionButton.qml @@ -121,7 +121,7 @@ hoverEnabled: true - Controls.ToolTip.visible: containsMouse && !Settings.isMobile && actionUnderMouse + Controls.ToolTip.visible: containsMouse && !Settings.tabletMode && actionUnderMouse Controls.ToolTip.text: actionUnderMouse ? actionUnderMouse.text : "" Controls.ToolTip.delay: Units.toolTipDelay @@ -192,7 +192,7 @@ } //if an action has been assigned, show a message like a tooltip - if (actionUnderMouse && actionUnderMouse.text && Settings.isMobile) { + if (actionUnderMouse && actionUnderMouse.text && Settings.tabletMode) { Controls.ToolTip.show(actionUnderMouse.text, 3000) } } diff --git a/src/controls/private/DefaultListItemBackground.qml b/src/controls/private/DefaultListItemBackground.qml --- a/src/controls/private/DefaultListItemBackground.qml +++ b/src/controls/private/DefaultListItemBackground.qml @@ -27,9 +27,9 @@ visible: listItem.ListView.view ? listItem.ListView.view.highlight === null : true Rectangle { id: internal - property bool indicateActiveFocus: listItem.pressed || Settings.isMobile || listItem.activeFocus || (listItem.ListView.view ? listItem.ListView.view.activeFocus : false) + property bool indicateActiveFocus: listItem.pressed || Settings.tabletMode || listItem.activeFocus || (listItem.ListView.view ? listItem.ListView.view.activeFocus : false) anchors.fill: parent - visible: !Settings.isMobile && listItem.supportsMouseEvents + visible: !Settings.tabletMode && listItem.supportsMouseEvents color: listItem.activeBackgroundColor opacity: (listItem.hovered || listItem.highlighted) && !listItem.pressed ? (indicateActiveFocus ? 0.2 : 0.1 ) : 0 Behavior on opacity { NumberAnimation { duration: Units.longDuration } } diff --git a/src/controls/templates/AbstractCard.qml b/src/controls/templates/AbstractCard.qml --- a/src/controls/templates/AbstractCard.qml +++ b/src/controls/templates/AbstractCard.qml @@ -72,7 +72,7 @@ implicitHeight: mainLayout.implicitHeight + topPadding + bottomPadding - hoverEnabled: !Kirigami.Settings.isMobile && showClickFeedback + hoverEnabled: !Kirigami.Settings.tabletMode && showClickFeedback //if it's in a CardLayout, try to expand horizontal cards to both columns Layout.columnSpan: headerOrientation == Qt.Horizontal && parent.hasOwnProperty("columns") ? parent.columns : 1 diff --git a/src/controls/templates/AbstractListItem.qml b/src/controls/templates/AbstractListItem.qml --- a/src/controls/templates/AbstractListItem.qml +++ b/src/controls/templates/AbstractListItem.qml @@ -121,7 +121,7 @@ QtObject { id: internal property Flickable view: listItem.ListView.view || (listItem.parent ? listItem.parent.ListView.view : null) - property bool indicateActiveFocus: listItem.pressed || Settings.isMobile || listItem.activeFocus || (view ? view.activeFocus : false) + property bool indicateActiveFocus: listItem.pressed || Settings.tabletMode || listItem.activeFocus || (view ? view.activeFocus : false) } Accessible.role: Accessible.ListItem diff --git a/src/controls/templates/SwipeListItem.qml b/src/controls/templates/SwipeListItem.qml --- a/src/controls/templates/SwipeListItem.qml +++ b/src/controls/templates/SwipeListItem.qml @@ -148,7 +148,7 @@ z: -1 //TODO: a global "open" state enabled: background.x !== 0 - property bool indicateActiveFocus: listItem.pressed || Settings.isMobile || listItem.activeFocus || (view ? view.activeFocus : false) + property bool indicateActiveFocus: listItem.pressed || Settings.tabletMode || listItem.activeFocus || (view ? view.activeFocus : false) property Flickable view: listItem.ListView.view || listItem.parent.ListView.view anchors { fill: parent @@ -187,8 +187,8 @@ Row { id: actionsLayout z: 1 - parent: Settings.isMobile ? behindItem : listItem - opacity: Settings.isMobile ? 1 : (listItem.hovered ? 1 : 0) + parent: Settings.tabletMode ? behindItem : listItem + opacity: Settings.tabletMode ? 1 : (listItem.hovered ? 1 : 0) Behavior on opacity { OpacityAnimator { duration: Units.longDuration @@ -226,10 +226,10 @@ id: actionMouse anchors { fill: parent; - margins: Settings.isMobile ? -Units.smallSpacing : 0; + margins: Settings.tabletMode ? -Units.smallSpacing : 0; } enabled: (modelData && modelData.enabled !== undefined) ? modelData.enabled : true; - hoverEnabled: !Settings.isMobile + hoverEnabled: !Settings.tabletMode onClicked: { if (modelData && modelData.trigger !== undefined) { modelData.trigger(); @@ -240,7 +240,7 @@ } Controls.ToolTip.delay: 1000 Controls.ToolTip.timeout: 5000 - Controls.ToolTip.visible: (Settings.isMobile ? actionMouse.pressed : actionMouse.containsMouse) && Controls.ToolTip.text.length > 0 + Controls.ToolTip.visible: (Settings.tabletMode ? actionMouse.pressed : actionMouse.containsMouse) && Controls.ToolTip.text.length > 0 Controls.ToolTip.text: modelData.tooltip || modelData.text } @@ -252,7 +252,7 @@ MouseArea { id: handleMouse parent: listItem.background - visible: Settings.isMobile + visible: Settings.tabletMode z: 99 anchors { right: parent.right @@ -339,12 +339,30 @@ } Component.onCompleted: { //this will happen only once - if (Settings.isMobile && !swipeFilterConnection.swipeFilterItem) { + if (Settings.tabletMode && !swipeFilterConnection.swipeFilterItem) { var component = Qt.createComponent(Qt.resolvedUrl("../private/SwipeItemEventFilter.qml")); behindItem.view.parent.parent._swipeFilter = component.createObject(behindItem.view.parent.parent); } listItem.contentItemChanged(); } + Connections { + target: Settings + onTabletModeChanged: { + if (Settings.tabletMode) { + if (!swipeFilterConnection.swipeFilterItem) { + var component = Qt.createComponent(Qt.resolvedUrl("../private/SwipeItemEventFilter.qml")); + listItem.ListView.view.parent.parent._swipeFilter = component.createObject(listItem.ListView.view.parent.parent); + } + } else { + if (listItem.ListView.view.parent.parent._swipeFilter) { + listItem.ListView.view.parent.parent._swipeFilter.destroy(); + positionAnimation.to = 0; + positionAnimation.from = background.x; + positionAnimation.running = true; + } + } + } + } Connections { id: swipeFilterConnection readonly property QtObject swipeFilterItem: (behindItem.view && behindItem.view && behindItem.view.parent && behindItem.view.parent.parent) ? behindItem.view.parent.parent._swipeFilter : null diff --git a/src/controls/templates/private/ScrollView.qml b/src/controls/templates/private/ScrollView.qml --- a/src/controls/templates/private/ScrollView.qml +++ b/src/controls/templates/private/ScrollView.qml @@ -44,23 +44,23 @@ scrollBarCreationTimer.restart(); } - drag.filterChildren: !Settings.isMobile + drag.filterChildren: !Settings.tabletMode onPressed: { - if (Settings.isMobile) { + if (Settings.tabletMode) { return; } mouse.accepted = false; flickableItem.interactive = true; } onReleased: { - if (Settings.isMobile) { + if (Settings.tabletMode) { return; } mouse.accepted = false; flickableItem.interactive = false; } onWheel: { - if (Settings.isMobile || flickableItem.contentHeight" ) +#use dbus on linux, bsd etc, but not andoid and apple stuff +if (UNIX AND NOT CMAKE_SYSTEM_NAME STREQUAL "Android" AND NOT(APPLE)) + set(LIBKIRIGAMKI_EXTRA_LIBS Qt5::DBus) +endif() + + target_link_libraries(KF5Kirigami2 PUBLIC Qt5::Core PRIVATE Qt5::Qml Qt5::Quick Qt5::QuickControls2 + ${LIBKIRIGAMKI_EXTRA_LIBS} ) set_target_properties(KF5Kirigami2 PROPERTIES @@ -42,6 +53,7 @@ HEADER_NAMES PlatformTheme KirigamiPluginFactory + TabletModeWatcher REQUIRED_HEADERS Kirigami2_HEADERS ) diff --git a/src/libkirigami/org.kde.KWin.TabletModeManager.xml b/src/libkirigami/org.kde.KWin.TabletModeManager.xml new file mode 100644 --- /dev/null +++ b/src/libkirigami/org.kde.KWin.TabletModeManager.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/libkirigami/tabletmodewatcher.h b/src/libkirigami/tabletmodewatcher.h new file mode 100644 --- /dev/null +++ b/src/libkirigami/tabletmodewatcher.h @@ -0,0 +1,88 @@ +/* + * Copyright 2018 Marco Martin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef KIRIGAMI_TABLETMODEWATCHER +#define KIRIGAMI_TABLETMODEWATCHER + +#include + +#ifndef KIRIGAMI_BUILD_TYPE_STATIC +#include +#endif + +namespace Kirigami { + +class TabletModeWatcherPrivate; + +/** + * This class reports on the status of certain transformable + * devices which can be both tablets and laptops at the same time, + * with a detachable keyboard. + * It reports whether the device supports a tablet mode and if + * the device is currently in such mode or not, emitting a signal + * when the user switches. + */ +#ifdef KIRIGAMI_BUILD_TYPE_STATIC +class TabletModeWatcher : public QObject +#else +class KIRIGAMI2_EXPORT TabletModeWatcher : public QObject +#endif +{ + Q_OBJECT + Q_PROPERTY(bool tabletModeAvailable READ isTabletModeAvailable NOTIFY tabletModeAvailableChanged) + Q_PROPERTY(bool tabletMode READ isTabletMode NOTIFY tabletModeChanged) + +public: + ~TabletModeWatcher(); + static TabletModeWatcher *self(); + + /** + * @returns true if the device supports a tablet mode and has a switch + * to report when the device has been transformed. + * For debug purposes, if either the environment variable QT_QUICK_CONTROLS_MOBILE + * or KDE_KIRIGAMI_TABLET_MODE are set to true, isTabletModeAvailable will be true + */ + bool isTabletModeAvailable() const; + + /** + * @returns true if the machine is now in tablet mode, such as the + * laptop keyboard flipped away or detached. + * Note that this doesn't mean exactly a tablet form factor, but + * that the preferred input mode for the device is the touch screen + * and that pointer and keyboard are either secondary or not available. + * + * For debug purposes, if either the environment variable QT_QUICK_CONTROLS_MOBILE + * or KDE_KIRIGAMI_TABLET_MODE are set to true, isTabletMode will be true + */ + bool isTabletMode() const; + +Q_SIGNALS: + void tabletModeAvailableChanged(bool tabletModeAvailable); + void tabletModeChanged(bool tabletMode); + +private: + TabletModeWatcher(QObject *parent = 0); + TabletModeWatcherPrivate *d; + friend class TabletModeWatcherSingleton; +}; +} + +#endif // KIRIGAMI_TABLETMODEWATCHER diff --git a/src/libkirigami/tabletmodewatcher.cpp b/src/libkirigami/tabletmodewatcher.cpp new file mode 100644 --- /dev/null +++ b/src/libkirigami/tabletmodewatcher.cpp @@ -0,0 +1,142 @@ +/* + * Copyright 2018 Marco Martin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "tabletmodewatcher.h" +#include "tabletmodemanager_interface.h" + +#ifdef Q_OS_ANDROID +#include +#endif + +//TODO: All the dbus stuff should be conditional, optional win32 support + +namespace Kirigami { + +class TabletModeWatcherSingleton +{ +public: + TabletModeWatcher self; +}; + +Q_GLOBAL_STATIC(TabletModeWatcherSingleton, privateTabletModeWatcherSelf) + + +class TabletModeWatcherPrivate +{ +public: + TabletModeWatcherPrivate(TabletModeWatcher *watcher) + : q(watcher) + { +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) + isTabletModeAvailable = true; + isTabletMode = true; +#elif defined(Q_OS_MACOS) + isTabletModeAvailable = false; + isTabletMode = false; +#elif defined(Q_OS_LINUX) || defined(Q_OS_UNIX) + //Mostly for debug purposes and for platforms which are always mobile, + //such as Plasma Mobile + if (qEnvironmentVariableIsSet("QT_QUICK_CONTROLS_MOBILE") || + qEnvironmentVariableIsSet("KDE_KIRIGAMI_TABLET_MODE")) { + isTabletMode = (QString::fromLatin1(qgetenv("QT_QUICK_CONTROLS_MOBILE")) == QStringLiteral("1") || + QString::fromLatin1(qgetenv("QT_QUICK_CONTROLS_MOBILE")) == QStringLiteral("true")) || + (QString::fromLatin1(qgetenv("KDE_KIRIGAMI_TABLET_MODE")) == QStringLiteral("1") || + QString::fromLatin1(qgetenv("KDE_KIRIGAMI_TABLET_MODE")) == QStringLiteral("true")); + isTabletModeAvailable = isTabletMode; + } else { + m_interface = new OrgKdeKWinTabletModeManagerInterface(QStringLiteral("org.kde.KWin"), QStringLiteral("/org/kde/KWin"), QDBusConnection::sessionBus(), q); + + if (m_interface->isValid()) { + //NOTE: the initial call is actually sync, because is better a tiny freeze than having the ui always recalculated and changed at the start + isTabletModeAvailable = m_interface->tabletModeAvailable(); + isTabletMode = m_interface->tabletMode(); + QObject::connect(m_interface, &OrgKdeKWinTabletModeManagerInterface::tabletModeChanged, + q, [this](bool tabletMode) { + setIsTablet(tabletMode); + }); + QObject::connect(m_interface, &OrgKdeKWinTabletModeManagerInterface::tabletModeAvailableChanged, + q, [this](bool avail) { + isTabletModeAvailable = avail; + emit q->tabletModeAvailableChanged(avail); + }); + } else { + isTabletModeAvailable = false; + isTabletMode = false; + } + } +//TODO: case for Windows +#else + isTabletModeAvailable = false; + isTabletMode = false; +#endif + } + ~TabletModeWatcherPrivate() {}; + void setIsTablet(bool tablet); + + TabletModeWatcher *q; +#if (defined(Q_OS_LINUX) || defined(Q_OS_UNIX)) && !defined(Q_OS_ANDROID) + OrgKdeKWinTabletModeManagerInterface *m_interface = nullptr; +#endif + bool isTabletModeAvailable = false; + bool isTabletMode = false; +}; + +void TabletModeWatcherPrivate::setIsTablet(bool tablet) +{ + if (isTabletMode == tablet) { + return; + } + + isTabletMode = tablet; + emit q->tabletModeChanged(tablet); +} + + + +TabletModeWatcher::TabletModeWatcher(QObject *parent) + : QObject(parent), + d(new TabletModeWatcherPrivate(this)) +{ +} + +TabletModeWatcher::~TabletModeWatcher() +{ + delete d; +} + +TabletModeWatcher *TabletModeWatcher::self() +{ + return &privateTabletModeWatcherSelf()->self; +} + +bool TabletModeWatcher::isTabletModeAvailable() const +{ + return d->isTabletModeAvailable; +} + +bool TabletModeWatcher::isTabletMode() const +{ + return d->isTabletMode; +} + +} + +#include "moc_tabletmodewatcher.cpp" diff --git a/src/settings.h b/src/settings.h --- a/src/settings.h +++ b/src/settings.h @@ -25,30 +25,69 @@ { Q_OBJECT + /** + * True if the system can dynamically enter in tablet mode + * (or the device is actually a tablet). + * such as transformable laptops that support keyboard detachment + */ + Q_PROPERTY(bool tabletModeAvailable READ isTabletModeAvailable NOTIFY tabletModeAvailableChanged) + + /** + * True if we are running on a small mobile device such as a mobile phone + * This is used when we want to do specific adaptations to our UI for + * small screen form factors, such as having bigger touch areas. + */ Q_PROPERTY(bool isMobile READ isMobile NOTIFY isMobileChanged) + + /** + * True if the device we are running on is behaving like a tablet: + * Note that this doesn't mean exactly a tablet form factor, but + * that the preferred input mode for the device is the touch screen + * and that pointer and keyboard are either secondary or not available. + */ + Q_PROPERTY(bool tabletMode READ tabletMode NOTIFY tabletModeChanged) + + /** + * name of the QtQuickControls2 style we are using, + * for instance org.kde.desktop, Plasma, Material, Universal etc + */ Q_PROPERTY(QString style READ style CONSTANT) + //TODO: make this adapt without file watchers? + /** + * How many lines of text the mouse wheel should scroll + */ Q_PROPERTY(int mouseWheelScrollLines READ mouseWheelScrollLines CONSTANT) public: Settings(QObject *parent=0); ~Settings(); + void setTabletModeAvailable(bool mobile); + bool isTabletModeAvailable() const; + void setIsMobile(bool mobile); bool isMobile() const; + void setTabletMode(bool tablet); + bool tabletMode() const; + QString style() const; void setStyle(const QString &style); int mouseWheelScrollLines() const; Q_SIGNALS: + void tabletModeAvailableChanged(); + void tabletModeChanged(); void isMobileChanged(); private: QString m_style; int m_scrollLines = 0; + bool m_tabletModeAvailable : 1; bool m_mobile : 1; + bool m_tabletMode : 1; }; #endif diff --git a/src/settings.cpp b/src/settings.cpp --- a/src/settings.cpp +++ b/src/settings.cpp @@ -24,16 +24,22 @@ #include #include +#include "libkirigami/tabletmodewatcher.h" + Settings::Settings(QObject *parent) : QObject(parent) { -#if defined(Q_OS_IOS) || defined(Q_OS_ANDROID) || defined(Q_OS_BLACKBERRY) || defined(Q_OS_QNX) || defined(Q_OS_WINRT) - m_mobile = true; -#else - m_mobile = qEnvironmentVariableIsSet("QT_QUICK_CONTROLS_MOBILE") && - (QString::fromLatin1(qgetenv("QT_QUICK_CONTROLS_MOBILE")) == QStringLiteral("1") || - QString::fromLatin1(qgetenv("QT_QUICK_CONTROLS_MOBILE")) == QStringLiteral("true")); -#endif + m_tabletModeAvailable = Kirigami::TabletModeWatcher::self()->isTabletModeAvailable(); + connect(Kirigami::TabletModeWatcher::self(), &Kirigami::TabletModeWatcher::tabletModeAvailableChanged, + this, [this](bool tabletModeAvailable) { + setTabletModeAvailable(tabletModeAvailable); + }); + + m_tabletMode = Kirigami::TabletModeWatcher::self()->isTabletMode(); + connect(Kirigami::TabletModeWatcher::self(), &Kirigami::TabletModeWatcher::tabletModeChanged, + this, [this](bool tabletMode) { + setTabletMode(tabletMode); + }); const QString configPath = QStandardPaths::locate(QStandardPaths::ConfigLocation, QStringLiteral("kdeglobals")); if (QFile::exists(configPath)) { @@ -50,9 +56,24 @@ { } +void Settings::setTabletModeAvailable(bool mobileAvailable) +{ + if (mobileAvailable == m_tabletModeAvailable) { + return; + } + + m_tabletModeAvailable = mobileAvailable; + emit tabletModeAvailableChanged(); +} + +bool Settings::isTabletModeAvailable() const +{ + return m_tabletModeAvailable; +} + void Settings::setIsMobile(bool mobile) { - if (mobile != m_mobile) { + if (mobile == m_mobile) { return; } @@ -65,6 +86,21 @@ return m_mobile; } +void Settings::setTabletMode(bool tablet) +{ + if (tablet == m_tabletMode) { + return; + } + + m_tabletMode = tablet; + emit tabletModeChanged(); +} + +bool Settings::tabletMode() const +{ + return m_tabletMode; +} + QString Settings::style() const { return m_style;