diff --git a/CMakeLists.txt b/CMakeLists.txt
index b099cccf4..981b8032d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,7 +8,7 @@ set (RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE
project(kdeconnect VERSION ${RELEASE_SERVICE_VERSION})
-set(KF_MIN_VERSION "5.240")
+set(KF_MIN_VERSION "6.0.0")
set(QT_MIN_VERSION "6.7.0")
set(CMAKE_CXX_STANDARD 20)
@@ -94,7 +94,7 @@ ecm_find_qmlmodule(QtQuick.Particles 2.0)
add_definitions(-DQT_NO_URL_CAST_FROM_STRING -DQT_NO_KEYWORDS -DQT_NO_CAST_FROM_ASCII)
-find_package(Qt6 ${QT_MIN_VERSION} REQUIRED COMPONENTS DBus Quick QuickControls2 Network Multimedia)
+find_package(Qt6 ${QT_MIN_VERSION} REQUIRED COMPONENTS DBus Quick QuickWidgets QuickControls2 Network Multimedia)
find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS I18n ConfigWidgets DBusAddons IconThemes Notifications
KIO KCMUtils Service Solid Kirigami People WindowSystem GuiAddons DocTools Crash)
diff --git a/app/qml/FindDevicesPage.qml b/app/qml/FindDevicesPage.qml
index 6d6b67c53..8c7745bb2 100644
--- a/app/qml/FindDevicesPage.qml
+++ b/app/qml/FindDevicesPage.qml
@@ -57,6 +57,7 @@ Kirigami.ScrollablePage
text: i18nd("kdeconnect-app", "No devices found")
icon.name: 'edit-none-symbolic'
anchors.centerIn: parent
+ width: parent.width - (Kirigami.Units.largeSpacing * 4)
visible: devices.count === 0
}
diff --git a/kcm/CMakeLists.txt b/kcm/CMakeLists.txt
index 690cc2e24..dec601b49 100644
--- a/kcm/CMakeLists.txt
+++ b/kcm/CMakeLists.txt
@@ -1,7 +1,8 @@
+qt_add_resources(kcm_SRCS assets.qrc)
+
add_definitions(-DTRANSLATION_DOMAIN="kdeconnect-kcm")
-
-kcoreaddons_add_plugin(kcm_kdeconnect SOURCES kcm.cpp INSTALL_NAMESPACE plasma/kcms/systemsettings_qwidgets)
+kcoreaddons_add_plugin(kcm_kdeconnect SOURCES kcm.cpp ${kcm_SRCS} INSTALL_NAMESPACE plasma/kcms/systemsettings_qwidgets)
kcmutils_generate_desktop_file(kcm_kdeconnect)
ki18n_wrap_ui(kcm_kdeconnect kcm.ui)
@@ -9,6 +10,7 @@ ki18n_wrap_ui(kcm_kdeconnect kcm.ui)
target_link_libraries(kcm_kdeconnect
Qt::Core
Qt::Gui
+ Qt::QuickWidgets
KF6::I18n
KF6::KCMUtils
kdeconnectinterfaces
diff --git a/kcm/Messages.sh b/kcm/Messages.sh
index 150dda395..814dba6df 100755
--- a/kcm/Messages.sh
+++ b/kcm/Messages.sh
@@ -5,5 +5,6 @@ $XGETTEXT rc.cpp -o $podir/kdeconnect-kcm.pot
rm -f rc.cpp
#.cpp (-j passed to merge into existing file)
+$XGETTEXT `find . -name '*.qml'` -j -o $podir/kdeconnect-kcm.pot
$XGETTEXT `find . -name '*.cpp'` -j -o $podir/kdeconnect-kcm.pot
diff --git a/kcm/assets.qrc b/kcm/assets.qrc
new file mode 100644
index 000000000..daf779c30
--- /dev/null
+++ b/kcm/assets.qrc
@@ -0,0 +1,7 @@
+
+
+
+
+ list.qml
+
+
diff --git a/kcm/kcm.cpp b/kcm/kcm.cpp
index 4cd9add52..6bc6feb62 100644
--- a/kcm/kcm.cpp
+++ b/kcm/kcm.cpp
@@ -14,6 +14,9 @@
#include
#include
+#include
+#include
+
#include "dbushelpers.h"
#include "dbusinterfaces.h"
#include "devicesmodel.h"
@@ -22,6 +25,21 @@
K_PLUGIN_CLASS_WITH_JSON(KdeConnectKcm, "kcm_kdeconnect.json")
+class QQuickWidgetPaleteChangeWatcher : public QObject
+{
+ using QObject::QObject;
+
+ bool eventFilter(QObject *watched, QEvent *event) override
+ {
+ if (event->type() == QEvent::PaletteChange || event->type() == QEvent::ApplicationPaletteChange) {
+ // We know that watched is a QQuickWidget
+ QQuickWidget *w = static_cast(watched);
+ w->setClearColor(w->palette().color(QPalette::Window));
+ }
+ return QObject::eventFilter(watched, event);
+ }
+};
+
KdeConnectKcm::KdeConnectKcm(QObject *parent, const KPluginMetaData &md, const QVariantList &args)
: KCModule(parent, md)
, daemon(new DaemonDbusInterface(this))
@@ -37,7 +55,14 @@ KdeConnectKcm::KdeConnectKcm(QObject *parent, const KPluginMetaData &md, const Q
sortProxyModel = new DevicesSortProxyModel(devicesModel);
- kcmUi.deviceList->setModel(sortProxyModel);
+ kcmUi.list_quick_widget->setMinimumWidth(250 * kcmUi.list_quick_widget->devicePixelRatio());
+ kcmUi.list_quick_widget->rootContext()->setContextObject(new KLocalizedContext(kcmUi.list_quick_widget));
+ kcmUi.list_quick_widget->setClearColor(kcmUi.list_quick_widget->palette().color(QPalette::Window));
+ kcmUi.list_quick_widget->setSource(QUrl(QStringLiteral("qrc:/kdeconnectkcm/list.qml")));
+ kcmUi.list_quick_widget->rootObject()->setProperty("model", QVariant::fromValue(sortProxyModel));
+ connect(kcmUi.list_quick_widget->rootObject(), SIGNAL(clicked(QString)), this, SLOT(deviceSelected(QString)));
+
+ kcmUi.list_quick_widget->installEventFilter(new QQuickWidgetPaleteChangeWatcher(kcmUi.list_quick_widget));
kcmUi.deviceInfo->setVisible(false);
kcmUi.progressBar->setVisible(false);
@@ -67,8 +92,6 @@ KdeConnectKcm::KdeConnectKcm(QObject *parent, const KPluginMetaData &md, const Q
setButtons(KCModule::Help | KCModule::NoAdditionalButton);
- connect(devicesModel, &QAbstractItemModel::dataChanged, this, &KdeConnectKcm::resetSelection);
- connect(kcmUi.deviceList->selectionModel(), &QItemSelectionModel::currentChanged, this, &KdeConnectKcm::deviceSelected);
connect(kcmUi.accept_button, &QAbstractButton::clicked, this, &KdeConnectKcm::acceptPairing);
connect(kcmUi.reject_button, &QAbstractButton::clicked, this, &KdeConnectKcm::cancelPairing);
connect(kcmUi.cancel_button, &QAbstractButton::clicked, this, &KdeConnectKcm::cancelPairing);
@@ -88,11 +111,8 @@ KdeConnectKcm::KdeConnectKcm(QObject *parent, const KPluginMetaData &md, const Q
const QString pluginCM = colonIdx < 0 ? QString() : input.mid(colonIdx + 1);
connect(devicesModel, &DevicesModel::rowsInserted, this, [this, deviceId, pluginCM]() {
- auto row = devicesModel->rowForDevice(deviceId);
- if (row >= 0) {
- const QModelIndex idx = sortProxyModel->mapFromSource(devicesModel->index(row));
- kcmUi.deviceList->selectionModel()->setCurrentIndex(idx, QItemSelectionModel::ClearAndSelect);
- }
+ kcmUi.list_quick_widget->rootObject()->setProperty("currentDeviceId", deviceId);
+ deviceSelected(deviceId);
if (!pluginCM.isEmpty()) {
kcmUi.pluginSelector->showConfiguration(pluginCM);
}
@@ -136,29 +156,19 @@ void KdeConnectKcm::refresh()
daemon->forceOnNetworkChange();
}
-void KdeConnectKcm::resetSelection()
-{
- if (!currentDevice) {
- return;
- }
- kcmUi.deviceList->selectionModel()->setCurrentIndex(sortProxyModel->mapFromSource(currentIndex), QItemSelectionModel::ClearAndSelect);
-}
-
-void KdeConnectKcm::deviceSelected(const QModelIndex ¤t)
+void KdeConnectKcm::deviceSelected(const QString &deviceId)
{
if (currentDevice) {
disconnect(currentDevice, nullptr, this, nullptr);
}
- if (!current.isValid()) {
+ currentDevice = devicesModel->getDevice(devicesModel->rowForDevice(deviceId));
+ if (!currentDevice) {
currentDevice = nullptr;
kcmUi.deviceInfo->setVisible(false);
return;
}
- currentIndex = sortProxyModel->mapToSource(current);
- currentDevice = devicesModel->getDevice(currentIndex.row());
-
kcmUi.noDevicePlaceholder->setVisible(false);
bool valid = (currentDevice != nullptr && currentDevice->isValid());
kcmUi.deviceInfo->setVisible(valid);
diff --git a/kcm/kcm.h b/kcm/kcm.h
index 0fa2831a9..7d2a9d574 100644
--- a/kcm/kcm.h
+++ b/kcm/kcm.h
@@ -30,11 +30,10 @@ private:
void save() override;
private Q_SLOTS:
- void deviceSelected(const QModelIndex ¤t);
+ void deviceSelected(const QString &deviceId);
void requestPairing();
void pluginsConfigChanged(bool changed);
void sendPing();
- void resetSelection();
void pairingFailed(const QString &error);
void refresh();
void renameShow();
@@ -53,7 +52,6 @@ private:
DevicesModel *devicesModel;
DevicesSortProxyModel *sortProxyModel;
DeviceDbusInterface *currentDevice;
- QModelIndex currentIndex;
QStringList m_oldSupportedPluginNames;
public Q_SLOTS:
diff --git a/kcm/kcm.ui b/kcm/kcm.ui
index a1521a1f8..b3e561de8 100644
--- a/kcm/kcm.ui
+++ b/kcm/kcm.ui
@@ -51,7 +51,6 @@
12
- 75
true
@@ -59,14 +58,14 @@
KDE Connect
- Qt::PlainText
+ Qt::TextFormat::PlainText
-
- Qt::Horizontal
+ Qt::Orientation::Horizontal
@@ -82,8 +81,7 @@
Edit
-
- ..
+
@@ -104,15 +102,24 @@
Save
-
- ..
+
-
-
+
+
+
+ 0
+ 0
+
+
+
+ QQuickWidget::ResizeMode::SizeRootObjectToView
+
+
-
@@ -152,7 +159,7 @@
- QLayout::SetMaximumSize
+ QLayout::SizeConstraint::SetMaximumSize
-
@@ -185,7 +192,6 @@
10
- 75
true
@@ -193,7 +199,7 @@
Device
- Qt::PlainText
+ Qt::TextFormat::PlainText
@@ -213,7 +219,7 @@
-
- Qt::Horizontal
+ Qt::Orientation::Horizontal
@@ -229,10 +235,10 @@
-
- 🔑 abababab
+ KSqueezedTextLabel
- Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
+ Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByMouse
@@ -241,7 +247,7 @@
-
- Qt::Horizontal
+ Qt::Orientation::Horizontal
@@ -340,7 +346,7 @@
-
-
+
-
@@ -351,7 +357,7 @@
- Qt::WheelFocus
+ Qt::FocusPolicy::WheelFocus
@@ -373,10 +379,10 @@
<html><head/><body><p>No device selected.<br><br>If you own an Android device, make sure to install the <a href="https://play.google.com/store/apps/details?id=org.kde.kdeconnect_tp"><span style=" text-decoration: underline;">KDE Connect Android app</span></a> (also available <a href="https://f-droid.org/repository/browse/?fdid=org.kde.kdeconnect_tp"><span style=" text-decoration: underline;">from F-Droid</span></a>) and it should appear in the list. If you have an iPhone, make sure to install the <a href="https://apps.apple.com/us/app/kde-connect/id1580245991"><span style=" text-decoration: underline;">KDE Connect iOS app</span></a> <br><br>If you are having problems, visit the <a href="https://userbase.kde.org/KDEConnect"><span style=" text-decoration: underline;">KDE Connect Community wiki</span></a> for help.</p></body></html>
- Qt::RichText
+ Qt::TextFormat::RichText
- Qt::AlignCenter
+ Qt::AlignmentFlag::AlignCenter
true
@@ -388,7 +394,7 @@
true
- Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse
+ Qt::TextInteractionFlag::LinksAccessibleByKeyboard|Qt::TextInteractionFlag::LinksAccessibleByMouse
@@ -401,12 +407,6 @@
-
- KPluginWidget
- QWidget
-
- 1
-
KMessageWidget
QFrame
@@ -418,6 +418,17 @@
QLabel
+
+ QQuickWidget
+ QWidget
+ QtQuickWidgets/QQuickWidget
+
+
+ KPluginWidget
+ QWidget
+
+ 1
+
diff --git a/kcm/list.qml b/kcm/list.qml
new file mode 100644
index 000000000..41f16e657
--- /dev/null
+++ b/kcm/list.qml
@@ -0,0 +1,81 @@
+/*
+ * SPDX-FileCopyrightText: 2016 Aleix Pol Gonzalez
+ *
+ * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
+ */
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import org.kde.kirigami as Kirigami
+import org.kde.kdeconnect
+
+ScrollView {
+ id: root
+
+ focus: true
+
+ signal clicked(string device)
+
+ property string currentDeviceId
+
+ property alias model: devices.model
+
+ Component.onCompleted: {
+ if (background) {
+ background.visible = true
+ }
+ }
+
+ ListView {
+ id: devices
+
+ focus: true
+
+ section {
+ property: "status"
+ delegate: Kirigami.ListSectionHeader {
+
+ width: ListView.view.width
+
+ text: switch (parseInt(section))
+ {
+ case DevicesModel.Paired:
+ return i18nd("kdeconnect-kcm", "Remembered")
+ case DevicesModel.Reachable:
+ return i18nd("kdeconnect-kcm", "Available")
+ case (DevicesModel.Reachable | DevicesModel.Paired):
+ return i18nd("kdeconnect-kcm", "Connected")
+ }
+ }
+ }
+ Kirigami.PlaceholderMessage {
+ text: i18nd("kdeconnect-kcm", "No devices found")
+ icon.name: 'edit-none-symbolic'
+ anchors.centerIn: parent
+ width: parent.width - (Kirigami.Units.largeSpacing * 4)
+ visible: devices.count === 0
+ }
+
+ delegate: ItemDelegate {
+ id: delegate
+ icon.name: iconName
+ text: model.name
+ width: ListView.view.width
+ highlighted: root.currentDeviceId === deviceId
+
+ focus: true
+
+ contentItem: Kirigami.IconTitleSubtitle {
+ title: delegate.text
+ subtitle: toolTip
+ icon: icon.fromControlsIcon(delegate.icon)
+ }
+
+ onClicked: {
+ root.currentDeviceId = deviceId
+ root.clicked(deviceId)
+ }
+ }
+ }
+}