From e827ec4d6dc553368d2ab7b6c854e6e42413de9e Mon Sep 17 00:00:00 2001 From: Nicolas Fella Date: Wed, 6 Feb 2019 17:27:17 +0100 Subject: [PATCH] [WIP] Add plugin setting to app and start port plugin KCMs to QML --- CMakeLists.txt | 2 +- KDEConnectMacros.cmake | 3 + app/qml/DevicePage.qml | 14 ++ app/qml/PluginInfoPage.qml | 49 +++++++ app/qml/PluginSettings.qml | 79 +++++++++++ app/resources.qrc | 2 + core/daemon.cpp | 4 +- core/kdeconnectpluginconfig.cpp | 60 +++++++- core/kdeconnectpluginconfig.h | 20 ++- declarativeplugin/CMakeLists.txt | 1 + .../kdeconnectdeclarativeplugin.cpp | 4 + interfaces/CMakeLists.txt | 4 + interfaces/pluginmodel.cpp | 133 ++++++++++++++++++ interfaces/pluginmodel.h | 74 ++++++++++ .../kdeconnect_findthisdevice_config.qml | 50 +++++++ plugins/share/kdeconnect_share_config.qml | 51 +++++++ 16 files changed, 542 insertions(+), 8 deletions(-) create mode 100644 app/qml/PluginInfoPage.qml create mode 100644 app/qml/PluginSettings.qml create mode 100644 interfaces/pluginmodel.cpp create mode 100644 interfaces/pluginmodel.h create mode 100644 plugins/findthisdevice/kdeconnect_findthisdevice_config.qml create mode 100644 plugins/share/kdeconnect_share_config.qml diff --git a/CMakeLists.txt b/CMakeLists.txt index 800eb40ba..78cf2c8e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ find_package(PkgConfig) if (SAILFISHOS) set(KF5_MIN_VERSION "5.31.0") set(QT_MIN_VERSION "5.6.0") - set(KF5_REQUIRED_COMPONENTS I18n DBusAddons CoreAddons IconThemes Config) + set(KF5_REQUIRED_COMPONENTS I18n DBusAddons CoreAddons IconThemes Config Service) set(KF5_OPTIONAL_COMPONENTS) set(QCA_MIN_VERSION 2.0.0) pkg_search_module(SFOS REQUIRED sailfishapp) diff --git a/KDEConnectMacros.cmake b/KDEConnectMacros.cmake index bf052ff6b..8e5f90178 100644 --- a/KDEConnectMacros.cmake +++ b/KDEConnectMacros.cmake @@ -5,4 +5,7 @@ # Thoroughly inspired in kdevplatform_add_plugin function(kdeconnect_add_plugin) kcoreaddons_add_plugin(${ARGN} INSTALL_NAMESPACE kdeconnect) + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${ARGV0}_config.qml") + install(FILES "${ARGV0}_config.qml" DESTINATION ${DATA_INSTALL_DIR}/kdeconnect) + endif() endfunction() diff --git a/app/qml/DevicePage.qml b/app/qml/DevicePage.qml index 075df33e9..acc00fe82 100644 --- a/app/qml/DevicePage.qml +++ b/app/qml/DevicePage.qml @@ -72,6 +72,15 @@ Kirigami.Page onTriggered: { deviceView.currentDevice.pluginCall("ping", "sendPing"); } + }, + Kirigami.Action { + text: i18n("Plugin settings") + onTriggered: { + pageStack.push( + deviceComp, + {device: currentDevice.id()} + ); + } } ] @@ -191,6 +200,11 @@ Kirigami.Page } } + Component { + id: deviceComp + PluginSettings {} + } + FileDialog { id: fileDialog title: i18n("Please choose a file") diff --git a/app/qml/PluginInfoPage.qml b/app/qml/PluginInfoPage.qml new file mode 100644 index 000000000..c9607825e --- /dev/null +++ b/app/qml/PluginInfoPage.qml @@ -0,0 +1,49 @@ +/* + * Copyright 2019 Nicolas Fella + * + * 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 . + */ + +import QtQuick 2.2 +import QtQuick.Controls 2.2 +import org.kde.kirigami 2.0 as Kirigami + +Kirigami.ScrollablePage +{ + id: root + property string configFile + property string device + + Loader { + id: loader + + Component.onCompleted: { + setSource(configFile, { + device: root.device + }) + } + } + + actions.main: Kirigami.Action { + icon.name: "dialog-ok" + text: i18n("Apply") + onTriggered: loader.item.apply() + } +} + + + diff --git a/app/qml/PluginSettings.qml b/app/qml/PluginSettings.qml new file mode 100644 index 000000000..cb896e8c1 --- /dev/null +++ b/app/qml/PluginSettings.qml @@ -0,0 +1,79 @@ +/* + * Copyright 2019 Nicolas Fella + * + * 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 . + */ + +import QtQuick 2.2 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.1 +import org.kde.kirigami 2.0 as Kirigami +import org.kde.kdeconnect 1.0 + +Kirigami.ScrollablePage +{ + id: root + title: i18n("Plugin settings") + property string device + + ListView { + id: sinkList + + Component { + id: pluginInfo + PluginInfoPage {} + } + + anchors.fill: parent + spacing: Kirigami.Units.smallSpacing + + model: PluginModel { + deviceId: device + } + + delegate: Kirigami.SwipeListItem { + width: parent.width + enabled: true + supportsMouseEvents: false + + CheckBox { + checked: isChecked + text: name + onClicked: { + isChecked = checked + } + } + + actions: [ + Kirigami.Action { + icon.name: "settings-configure" + visible: configSource != "" + onTriggered: { + pageStack.push(pluginInfo, { + title: name, + configFile: configSource, + device: root.device + }) + } + } + ] + } + } + +} + + diff --git a/app/resources.qrc b/app/resources.qrc index ce3cfab40..3c79529ae 100644 --- a/app/resources.qrc +++ b/app/resources.qrc @@ -10,5 +10,7 @@ qml/FindDevicesPage.qml qml/runcommand.qml qml/volume.qml + qml/PluginSettings.qml + qml/PluginInfoPage.qml diff --git a/core/daemon.cpp b/core/daemon.cpp index e5aa1cea3..76f369242 100644 --- a/core/daemon.cpp +++ b/core/daemon.cpp @@ -71,9 +71,9 @@ Daemon::Daemon(QObject* parent, bool testMode) qCDebug(KDECONNECT_CORE) << "KdeConnect daemon starting"; //Load backends - if (testMode) - d->m_linkProviders.insert(new LoopbackLinkProvider()); + if (testMode){} else { + d->m_linkProviders.insert(new LoopbackLinkProvider()); d->m_linkProviders.insert(new LanLinkProvider()); #ifdef KDECONNECT_BLUETOOTH d->m_linkProviders.insert(new BluetoothLinkProvider()); diff --git a/core/kdeconnectpluginconfig.cpp b/core/kdeconnectpluginconfig.cpp index 9e3045979..fd97de0d4 100644 --- a/core/kdeconnectpluginconfig.cpp +++ b/core/kdeconnectpluginconfig.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include "kdeconnectconfig.h" @@ -34,6 +35,12 @@ struct KdeConnectPluginConfigPrivate QDBusMessage m_signal; }; +KdeConnectPluginConfig::KdeConnectPluginConfig() + : d(new KdeConnectPluginConfigPrivate()) +{ + +} + KdeConnectPluginConfig::KdeConnectPluginConfig(const QString& deviceId, const QString& pluginName) : d(new KdeConnectPluginConfigPrivate()) { @@ -42,8 +49,9 @@ KdeConnectPluginConfig::KdeConnectPluginConfig(const QString& deviceId, const QS d->m_config = new QSettings(d->m_configDir.absoluteFilePath(QStringLiteral("config")), QSettings::IniFormat); - d->m_signal = QDBusMessage::createSignal("/kdeconnect/"+deviceId+"/"+pluginName, QStringLiteral("org.kde.kdeconnect.config"), QStringLiteral("configChanged")); - QDBusConnection::sessionBus().connect(QLatin1String(""), "/kdeconnect/"+deviceId+"/"+pluginName, QStringLiteral("org.kde.kdeconnect.config"), QStringLiteral("configChanged"), this, SLOT(slotConfigChanged())); + d->m_signal = QDBusMessage::createSignal("/kdeconnect/" + deviceId + "/" + pluginName, QStringLiteral("org.kde.kdeconnect.config"), QStringLiteral("configChanged")); + QDBusConnection::sessionBus().connect(QLatin1String(""), "/kdeconnect/" + deviceId + "/" + pluginName, QStringLiteral("org.kde.kdeconnect.config"), QStringLiteral("configChanged"), this, SLOT(slotConfigChanged())); + } KdeConnectPluginConfig::~KdeConnectPluginConfig() @@ -53,6 +61,10 @@ KdeConnectPluginConfig::~KdeConnectPluginConfig() QVariant KdeConnectPluginConfig::get(const QString& key, const QVariant& defaultValue) { + if (!d->m_config) { + loadConfig(); + } + d->m_config->sync(); return d->m_config->value(key, defaultValue); } @@ -98,3 +110,47 @@ void KdeConnectPluginConfig::slotConfigChanged() { Q_EMIT configChanged(); } + +void KdeConnectPluginConfig::setDeviceId(const QString& deviceId) +{ + if (deviceId != m_deviceId) { + m_deviceId = deviceId; + } + + if (!m_deviceId.isEmpty() && !m_pluginName.isEmpty()) { + loadConfig(); + } +} + +QString KdeConnectPluginConfig::deviceId() +{ + return m_deviceId; +} + +void KdeConnectPluginConfig::setPluginName(const QString& pluginName) +{ + if (pluginName != m_pluginName) { + m_pluginName = pluginName; + } + + if (!m_deviceId.isEmpty() && !m_pluginName.isEmpty()) { + loadConfig(); + } +} + +QString KdeConnectPluginConfig::pluginName() +{ + return m_pluginName; +} + +void KdeConnectPluginConfig::loadConfig() +{ + d->m_configDir = KdeConnectConfig::instance()->pluginConfigDir(m_deviceId, m_pluginName); + QDir().mkpath(d->m_configDir.path()); + + d->m_config = new QSettings(d->m_configDir.absoluteFilePath(QStringLiteral("config")), QSettings::IniFormat); + + d->m_signal = QDBusMessage::createSignal("/kdeconnect/" + m_deviceId + "/" + m_pluginName, QStringLiteral("org.kde.kdeconnect.config"), QStringLiteral("configChanged")); + QDBusConnection::sessionBus().connect(QLatin1String(""), "/kdeconnect/" + m_deviceId + "/" + m_pluginName, QStringLiteral("org.kde.kdeconnect.config"), QStringLiteral("configChanged"), this, SLOT(slotConfigChanged())); + Q_EMIT configChanged(); +} diff --git a/core/kdeconnectpluginconfig.h b/core/kdeconnectpluginconfig.h index a13d0041b..a04d13faf 100644 --- a/core/kdeconnectpluginconfig.h +++ b/core/kdeconnectpluginconfig.h @@ -27,7 +27,7 @@ #include #include -#include "kdeconnectcore_export.h" +#include "core/kdeconnectcore_export.h" struct KdeConnectPluginConfigPrivate; @@ -35,14 +35,18 @@ class KDECONNECTCORE_EXPORT KdeConnectPluginConfig : public QObject { Q_OBJECT + Q_PROPERTY(QString deviceId READ deviceId WRITE setDeviceId NOTIFY configChanged) + Q_PROPERTY(QString pluginName READ pluginName WRITE setPluginName NOTIFY configChanged) + public: + KdeConnectPluginConfig(); KdeConnectPluginConfig(const QString& deviceId, const QString& pluginName); ~KdeConnectPluginConfig() override; /** * Store a key-value pair in this config object */ - void set(const QString& key, const QVariant& value); + Q_SCRIPTABLE void set(const QString& key, const QVariant& value); /** * Store a list of values in this config object under the array name @@ -53,7 +57,7 @@ public: /** * Read a key-value pair from this config object */ - QVariant get(const QString& key, const QVariant& defaultValue); + Q_SCRIPTABLE QVariant get(const QString& key, const QVariant& defaultValue); /** * Convenience method that will convert the QVariant to whatever type for you @@ -64,6 +68,12 @@ public: QVariantList getList(const QString& key, const QVariantList& defaultValue = {}); + QString deviceId(); + void setDeviceId(const QString& deviceId); + + QString pluginName(); + void setPluginName(const QString& pluginName); + private Q_SLOTS: void slotConfigChanged(); @@ -71,7 +81,11 @@ Q_SIGNALS: void configChanged(); private: + void loadConfig(); + QScopedPointer d; + QString m_deviceId; + QString m_pluginName; }; #endif diff --git a/declarativeplugin/CMakeLists.txt b/declarativeplugin/CMakeLists.txt index 0e1244708..f06b90cb5 100644 --- a/declarativeplugin/CMakeLists.txt +++ b/declarativeplugin/CMakeLists.txt @@ -24,6 +24,7 @@ add_library(kdeconnectdeclarativeplugin SHARED ${kdeconnectdeclarativeplugin_SRC target_link_libraries(kdeconnectdeclarativeplugin Qt5::Qml kdeconnectinterfaces + kdeconnectcore ) install(TARGETS kdeconnectdeclarativeplugin DESTINATION ${QML_INSTALL_DIR}/org/kde/kdeconnect) install(FILES qmldir ${qml_SRC} DESTINATION ${QML_INSTALL_DIR}/org/kde/kdeconnect) diff --git a/declarativeplugin/kdeconnectdeclarativeplugin.cpp b/declarativeplugin/kdeconnectdeclarativeplugin.cpp index aec3b0a77..2e5e38bd2 100644 --- a/declarativeplugin/kdeconnectdeclarativeplugin.cpp +++ b/declarativeplugin/kdeconnectdeclarativeplugin.cpp @@ -33,6 +33,8 @@ #include "interfaces/notificationsmodel.h" #include #include +#include +#include "core/kdeconnectpluginconfig.h" QObject* createDeviceDbusInterface(const QVariant& deviceId) { @@ -109,6 +111,8 @@ void KdeConnectDeclarativePlugin::registerTypes(const char* uri) qmlRegisterType(uri, 1, 0, "DBusAsyncResponse"); qmlRegisterType(uri, 1, 0, "DevicesSortProxyModel"); qmlRegisterType(uri, 1, 0, "RemoteSinksModel"); + qmlRegisterType(uri, 1, 0, "PluginModel"); + qmlRegisterType(uri, 1, 0, "KdeConnectPluginConfig"); qmlRegisterUncreatableType(uri, 1, 0, "MprisDbusInterface", QStringLiteral("You're not supposed to instantiate interfaces")); qmlRegisterUncreatableType(uri, 1, 0, "LockDeviceDbusInterface", QStringLiteral("You're not supposed to instantiate interfaces")); qmlRegisterUncreatableType(uri, 1, 0, "FindMyPhoneDbusInterface", QStringLiteral("You're not supposed to instantiate interfaces")); diff --git a/interfaces/CMakeLists.txt b/interfaces/CMakeLists.txt index 31187e448..c4cf9543e 100644 --- a/interfaces/CMakeLists.txt +++ b/interfaces/CMakeLists.txt @@ -20,6 +20,7 @@ set(libkdeconnect_SRC conversationmessage.cpp remotecommandsmodel.cpp remotesinksmodel.cpp + pluginmodel.cpp # modeltest.cpp ) @@ -34,6 +35,7 @@ set(libkdeconnect_HEADERS conversationmessage.h dbusinterfaces.h remotecommandsmodel.h + pluginmodel.h ${CMAKE_CURRENT_BINARY_DIR}/kdeconnectinterfaces_export.h ) @@ -67,9 +69,11 @@ generate_export_header(kdeconnectinterfaces EXPORT_FILE_NAME ${CMAKE_CURRENT_BIN target_link_libraries(kdeconnectinterfaces LINK_PUBLIC Qt5::DBus + KF5::Service LINK_PRIVATE KF5::ConfigCore KF5::I18n + KF5::CoreAddons ) configure_file(KDEConnectConfig.cmake.in ${CMAKE_BINARY_DIR}/interfaces/KDEConnectConfig.cmake @ONLY) diff --git a/interfaces/pluginmodel.cpp b/interfaces/pluginmodel.cpp new file mode 100644 index 000000000..7d03f3131 --- /dev/null +++ b/interfaces/pluginmodel.cpp @@ -0,0 +1,133 @@ +/** + * Copyright 2019 Nicolas Fella + * + * 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 "pluginmodel.h" + +#include +#include + +PluginModel::PluginModel(QObject *parent) + : QAbstractListModel(parent) +{ + + connect(this, &QAbstractItemModel::rowsInserted, + this, &PluginModel::rowsChanged); + connect(this, &QAbstractItemModel::rowsRemoved, + this, &PluginModel::rowsChanged); + + + beginResetModel(); + m_plugins = KPluginInfo::fromMetaData(KPluginLoader::findPlugins(QStringLiteral("kdeconnect/"))); + endResetModel(); +} + +PluginModel::~PluginModel() +{ +} + +void PluginModel::setDeviceId(const QString& deviceId) +{ + if (deviceId == m_deviceId) + return; + + m_deviceId = deviceId; + DeviceDbusInterface *device = new DeviceDbusInterface(m_deviceId); + m_config = KSharedConfig::openConfig(device->pluginsConfigFile()); +} + +QVariant PluginModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) { + return QVariant(); + } + + const KPluginInfo &pluginEntry = m_plugins[index.row()]; + + switch (role) { + case CheckedRole: + return m_config->group("Plugins").readEntry(QStringLiteral("%1Enabled").arg(pluginEntry.pluginName()), QStringLiteral("false")) == QStringLiteral("true"); + case NameRole: + return pluginEntry.name(); + case IconRole: + return pluginEntry.icon(); + case IdRole: + return pluginEntry.pluginName(); + case ConfigSourceRole: + { + const QString configFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kdeconnect/%1_config.qml").arg(pluginEntry.pluginName())); + if (configFile.isEmpty()) + return QUrl(); + + return QUrl::fromLocalFile(configFile); + } + default: + return QVariant(); + } +} + + +QHash PluginModel::roleNames() const +{ + QHash roles = QAbstractItemModel::roleNames(); + roles[NameRole] = "name"; + roles[CheckedRole] = "isChecked"; + roles[IconRole] = "iconName"; + roles[IdRole] = "pluginId"; + roles[ConfigSourceRole] = "configSource"; + return roles; +} + + +bool PluginModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid()) { + return false; + } + + bool ret = false; + + if (role == CheckedRole) { + const KPluginInfo &pluginEntry = m_plugins[index.row()]; + m_config->group("Plugins").writeEntry(QStringLiteral("%1Enabled").arg(pluginEntry.pluginName()), value); + ret = true; + } + + m_config->sync(); + + if (ret) { + Q_EMIT dataChanged(index, index); + } + + return ret; +} + +int PluginModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } + + return m_plugins.size(); +} + +QString PluginModel::deviceId() +{ + return m_deviceId; +} diff --git a/interfaces/pluginmodel.h b/interfaces/pluginmodel.h new file mode 100644 index 000000000..c0537e21a --- /dev/null +++ b/interfaces/pluginmodel.h @@ -0,0 +1,74 @@ +/** + * Copyright 2019 Nicolas Fella + * + * 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 PLUGINMODEL +#define PLUGINMODEL + +#include + +#include + +#include "interfaces/dbusinterfaces.h" +#include + +class KDECONNECTINTERFACES_EXPORT PluginModel + : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(QString deviceId READ deviceId WRITE setDeviceId CONSTANT) + +public: + + enum ExtraRoles { + NameRole, + CheckedRole, + IconRole, + IdRole, + ConfigSourceRole + }; + + Q_ENUM(ExtraRoles) + + explicit PluginModel(QObject *parent = nullptr); + ~PluginModel() override; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QHash roleNames() const override; + void setDeviceId(const QString& deviceId); + QString deviceId(); + +Q_SIGNALS: + void deviceIdChanged(const QString& value); + void rowsChanged(); + + +private: + QList m_plugins; + QString m_deviceId; + KSharedConfigPtr m_config; + +}; + + +#endif // KPLUGINSELECTOR_P_H + + diff --git a/plugins/findthisdevice/kdeconnect_findthisdevice_config.qml b/plugins/findthisdevice/kdeconnect_findthisdevice_config.qml new file mode 100644 index 000000000..a5fde6f5d --- /dev/null +++ b/plugins/findthisdevice/kdeconnect_findthisdevice_config.qml @@ -0,0 +1,50 @@ +import QtQuick 2.2 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.1 +import org.kde.kirigami 2.5 as Kirigami +import Qt.labs.platform 1.1 +import org.kde.kdeconnect 1.0 + +Kirigami.FormLayout { + + property string device + + function apply() { + config.set("ringtone", path.text) + } + + FileDialog { + id: fileDialog + currentFile: path.text + + onAccepted: { + path.text = currentFile.toString().replace("file://", "") + } + } + + KdeConnectPluginConfig { + id: config + deviceId: device + pluginName: "kdeconnect_findthisdevice" + + onConfigChanged: { + path.text = get("ringtone", StandardPaths.writableLocation(StandardPaths.DownloadsLocation).toString().replace("file://", "")) + } + } + + RowLayout { + Kirigami.FormData.label: i18n("Sound to play:") + + TextField { + id: path + } + + Button { + icon.name: "document-open" + onClicked: { + fileDialog.open() + } + } + } +} + diff --git a/plugins/share/kdeconnect_share_config.qml b/plugins/share/kdeconnect_share_config.qml new file mode 100644 index 000000000..5eb26f005 --- /dev/null +++ b/plugins/share/kdeconnect_share_config.qml @@ -0,0 +1,51 @@ +import QtQuick 2.2 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.1 +import org.kde.kirigami 2.5 as Kirigami +import Qt.labs.platform 1.1 +import org.kde.kdeconnect 1.0 + +Kirigami.FormLayout { + + property string device + + function apply() { + config.set("incoming_path", path.text) + } + + FolderDialog { + id: folderDialog + currentFolder: path.text + + onAccepted: { + path.text = currentFolder.toString().replace("file://", "") + } + } + + KdeConnectPluginConfig { + id: config + deviceId: device + pluginName: "kdeconnect_share" + + onConfigChanged: { + path.text = get("incoming_path", StandardPaths.writableLocation(StandardPaths.DownloadsLocation).toString().replace("file://", "")) + } + } + + RowLayout { + Kirigami.FormData.label: i18n("Save files in:") + + TextField { + id: path + } + + Button { + icon.name: "document-open" + onClicked: folderDialog.open() + } + } + + Label { + text: "%1 in the path will be replaced with the specific device name" + } +}