diff --git a/package/contents/ui/KCMContainer.qml b/package/contents/ui/KCMContainer.qml new file mode 100644 index 0000000..d0d61a5 --- /dev/null +++ b/package/contents/ui/KCMContainer.qml @@ -0,0 +1,42 @@ +import QtQuick 2.6 +import QtQuick.Controls 2.2 as Controls +import org.kde.kirigami 2.5 as Kirigami + +import org.kde.plasma.settings 0.1 + +Kirigami.Page { + id: container + title: internalPage.title + property QtObject kcm + property Item internalPage + topPadding: 0 + leftPadding: 0 + rightPadding: 0 + bottomPadding: 0 + flickable: internalPage.flickable + actions.main: internalPage.actions.main + actions.contextualActions: internalPage.contextualActions + + onInternalPageChanged: { + internalPage.parent = contentItem; + internalPage.anchors.fill = contentItem; + } + + data: [ + Connections { + target: kcm + onPagePushed: { + pageStack.push(kcmContainer.createObject(pageStack, {"internalPage": page})); + } + onPageRemoved: pageStack.pop(); + }, + Connections { + target: pageStack + onPageRemoved: { + if (page == container) { + page.destroy(); + } + } + } + ] + } diff --git a/package/contents/ui/ModulesList.qml b/package/contents/ui/ModulesList.qml index b27b413..0c56597 100644 --- a/package/contents/ui/ModulesList.qml +++ b/package/contents/ui/ModulesList.qml @@ -1,138 +1,105 @@ /*************************************************************************** * * * Copyright 2011-2014 Sebastian Kügler * * * * 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) any later version. * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ import QtQuick 2.2 import QtQuick.Layouts 1.2 import QtQuick.Controls 2.2 as Controls import org.kde.kirigami 2.8 as Kirigami import org.kde.plasma.settings 0.1 Kirigami.ScrollablePage { id: settingsRoot title: i18n("Settings") property alias currentIndex: listView.currentIndex Kirigami.Theme.colorSet: Kirigami.Theme.View background: Rectangle { color: Kirigami.Theme.backgroundColor } Component { id: settingsModuleDelegate Kirigami.AbstractListItem { id: delegateItem enabled: true checked: listView.currentIndex == index && !rootItem.compactMode leftPadding: Kirigami.Units.largeSpacing RowLayout { id: bah spacing: Kirigami.Units.largeSpacing Kirigami.Icon { id: iconItem selected: delegateItem.down Layout.maximumWidth: Layout.preferredWidth Layout.preferredWidth: Kirigami.Units.iconSizes.medium Layout.preferredHeight: Layout.preferredWidth source: iconName } ColumnLayout { Layout.alignment: Qt.AlignLeft Layout.fillWidth: true Controls.Label { Layout.alignment: Qt.AlignLeft Layout.fillWidth: true text: name } Controls.Label { text: description Layout.fillWidth: true font.pointSize: Kirigami.Theme.defaultFont.pointSize -1 opacity: 0.6 elide: Text.ElideRight } } Connections { target: settingsApp onModuleRequested: { if (rootItem.currentModule == model.module) { listView.currentIndex = index; } } } } onClicked: { print("Clicked ndex: " + index + " current: " + listView.currentIndex + " " + name + " curr: " + rootItem.currentModule); // Only the first main page has a kcm property var container = kcmContainer.createObject(pageStack, {"kcm": model.kcm, "internalPage": model.kcm.mainUi}); pageStack.push(container); } } } // This is pretty much a placeholder of what will be the sandboxing mechanism: this element will be a wayland compositor that will contain off-process kcm pages Component { id: kcmContainer - Kirigami.Page { - id: container - title: internalPage.title - property QtObject kcm - property Item internalPage - topPadding: 0 - leftPadding: 0 - rightPadding: 0 - bottomPadding: 0 - flickable: internalPage.flickable - actions.main: internalPage.actions.main - actions.contextualActions: internalPage.contextualActions - onInternalPageChanged: { - internalPage.parent = contentItem; - internalPage.anchors.fill = contentItem; - } - - data: [ - Connections { - target: kcm - onPagePushed: { - pageStack.push(kcmContainer.createObject(pageStack, {"internalPage": page})); - } - onPageRemoved: pageStack.pop(); - }, - Connections { - target: pageStack - onPageRemoved: { - if (page == container) { - page.destroy(); - } - } - } - ] - } + KCMContainer {} } + ListView { id: listView model: ModulesModel{} delegate: settingsModuleDelegate } } diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index 91dba48..7026fe6 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -1,63 +1,59 @@ /*************************************************************************** * * * Copyright 2017 Marco Martin * * Copyright 2011-2014 Sebastian Kügler * * * * 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) any later version. * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ import QtQuick 2.6 import QtQuick.Controls 2.2 as Controls import org.kde.kirigami 2.5 as Kirigami import org.kde.plasma.settings 0.1 Kirigami.ApplicationWindow { id: rootItem - property Item currentModule - pageStack.initialPage: modulesList pageStack.globalToolBar.style: Kirigami.ApplicationHeaderStyle.Breadcrumb contextDrawer: Kirigami.ContextDrawer { id: contextDrawer } - Connections { - target: settingsApp - onActivateRequested: rootItem.requestActivate(); - onModuleRequested: { - pageStack.currentIndex = 0; - rootItem.currentModule = module; - } - } - onCurrentModuleChanged: { - if (currentModule.length > 0) { - pageStack.push(moduleItem); - } - pageStack.currentIndex = 1; - } - Component.onCompleted: { if (startModule.length > 0) { - rootItem.currentModule = startModule; + module.name = startModule + var container = kcmContainer.createObject(pageStack, {"kcm": module.kcm, "internalPage": module.kcm.mainUi}); + pageStack.push(container); } } + + Module { + id: module + } + ModulesList { id: modulesList } + + Component { + id: kcmContainer + + KCMContainer {} + } } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 55c9d09..c5c7d24 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,23 +1,24 @@ # These are only needed here, consider porting away from both! find_package(Qt5 REQUIRED NO_MODULE COMPONENTS Gui) set(plasma-settings_SRCS main.cpp settingsapp.cpp modulesmodel.cpp + module.cpp ) add_executable(plasma-settings ${plasma-settings_SRCS}) target_link_libraries(plasma-settings Qt5::Quick Qt5::Gui KF5::Package KF5::DBusAddons KF5::QuickAddons KF5::I18n KF5::WindowSystem KF5::Declarative ) install( TARGETS plasma-settings ${INSTALL_TARGETS_DEFAULT_ARGS} ) diff --git a/src/main.cpp b/src/main.cpp index 48de2ac..0b214fb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,166 +1,168 @@ /*************************************************************************** * * * Copyright 2011-2015 Sebastian Kügler * * * * 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) any later version. * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ // std #include #include //own #include "settingsapp.h" #include "modulesmodel.h" +#include "module.h" // Qt #include #include #include #include #include #include #include // Frameworks #include #include #include #include #include #include #include #include static const char description[] = I18N_NOOP("Plasma Mobile Settings"); static const char version[] = "2.0"; static const char HOME_URL[] = "http://plasma-mobile.org"; int main(int argc, char **argv) { QApplication app(argc, argv); KLocalizedString::setApplicationDomain("plasma-settings"); // About data KAboutData aboutData("mobile.plasmasettings", i18n("Settings"), version, i18n("Touch-friendly settings application."), KAboutLicense::GPL, i18n("Copyright 2011-2015, Sebastian Kügler")); aboutData.addAuthor(i18n("Sebastian Kügler"), i18n("Maintainer"), "sebas@kde.org"); aboutData.addAuthor(i18n("Marco Martin"), i18n("Maintainer"), "mart@kde.org"); aboutData.setDesktopFileName("org.kde.mobile.plasmasettings"); KAboutData::setApplicationData(aboutData); app.setWindowIcon(QIcon::fromTheme("preferences-system")); const static auto _l = QStringLiteral("list"); const static auto _m = QStringLiteral("module"); const static auto _f = QStringLiteral("fullscreen"); const static auto _ui = QStringLiteral("layout"); const static auto _ff = QStringLiteral("formfactor"); QCommandLineOption _list = QCommandLineOption(QStringList() << QStringLiteral("l") << _l, i18n("List available settings modules")); QCommandLineOption _module = QCommandLineOption(QStringList() << QStringLiteral("m") << _m, i18n("Settings module to open"), i18n("modulename")); QCommandLineOption _fullscreen = QCommandLineOption(QStringList() << QStringLiteral("f") << _f, i18n("Start window fullscreen")); QCommandLineOption _layout = QCommandLineOption(QStringList() << _ui, i18n("Package to use for the UI (default org.kde.mobile.settings)"), i18n("packagename")); QCommandLineOption _formfactor = QCommandLineOption(QStringList() << QStringLiteral("x") << _ff, i18n("Limit to modules suitable for , e.g. handset, tablet, mediacenter, desktop, test, all (default handset)"), i18n("formfactor")); QCommandLineParser parser; parser.addOption(_list); parser.addOption(_formfactor); parser.addOption(_module); parser.addOption(_fullscreen); parser.addOption(_layout); aboutData.setupCommandLine(&parser); parser.process(app); aboutData.processCommandLine(&parser); if (parser.isSet(_list)) { int nameWidth = 24; QSet seen; std::cout << std::setfill('.'); auto formfactor = parser.value("formfactor"); for (auto plugin : KPackage::PackageLoader::self()->listPackages(QString(), "kpackage/kcms/")) { if (seen.contains(plugin.pluginId())) { continue; } // Filter out modules that are not explicitely suitable for the "handset" formfactor //const QStringList &formFactors = plugin.formFactors(); if (!formfactor.isEmpty() && !plugin.formFactors().contains(formfactor) && formfactor != QStringLiteral("all")) { continue; } const int len = plugin.pluginId().length(); if (len > nameWidth) { nameWidth = len; } seen << plugin.pluginId(); std::cout << plugin.pluginId().toLocal8Bit().data() << ' ' << std::setw(nameWidth - plugin.pluginId().length() + 2) << '.' << ' ' << plugin.description().toLocal8Bit().data() << std::endl; //qDebug() << "Formafactors: " << formFactors; } for (auto plugin : KPluginLoader::findPlugins("kcms")) { if (seen.contains(plugin.pluginId())) { continue; } if (!formfactor.isEmpty() && !plugin.formFactors().contains(formfactor) && formfactor != QStringLiteral("all")) { continue; } const int len = plugin.pluginId().length(); if (len > nameWidth) { nameWidth = len; } std::cout << plugin.pluginId().toLocal8Bit().data() << ' ' << std::setw(nameWidth - plugin.pluginId().length() + 2) << '.' << ' ' << plugin.description().toLocal8Bit().data() << std::endl; } return 0; } const QString module = parser.value(_m); QString ui = parser.isSet(_ui) ? parser.value(_ui) : "org.kde.plasma.settings"; KPackage::Package package = KPackage::PackageLoader::self()->loadPackage("KPackage/GenericQML"); package.setPath(ui); auto *settingsApp = new SettingsApp(parser); qmlRegisterType("org.kde.plasma.settings", 0, 1, "ModulesModel"); + qmlRegisterType("org.kde.plasma.settings", 0, 1, "Module"); QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("settingsApp", settingsApp); engine.rootContext()->setContextProperty("startModule", module); engine.load(package.filePath("mainscript")); return app.exec(); } diff --git a/package/contents/ui/main.qml b/src/module.cpp similarity index 56% copy from package/contents/ui/main.qml copy to src/module.cpp index 91dba48..ddbcd0c 100644 --- a/package/contents/ui/main.qml +++ b/src/module.cpp @@ -1,63 +1,61 @@ /*************************************************************************** * * - * Copyright 2017 Marco Martin * - * Copyright 2011-2014 Sebastian Kügler * + * 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) any later version. * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ -import QtQuick 2.6 -import QtQuick.Controls 2.2 as Controls -import org.kde.kirigami 2.5 as Kirigami +#include "module.h" -import org.kde.plasma.settings 0.1 +#include +#include -Kirigami.ApplicationWindow { - id: rootItem - - property Item currentModule +KQuickAddons::ConfigModule *Module::kcm() const +{ + return m_kcm; +} - pageStack.initialPage: modulesList - pageStack.globalToolBar.style: Kirigami.ApplicationHeaderStyle.Breadcrumb +QString Module::name() const +{ + return m_name; +} - contextDrawer: Kirigami.ContextDrawer { - id: contextDrawer +void Module::setName(const QString& name) +{ + if (m_name == name) { + return; } - Connections { - target: settingsApp - onActivateRequested: rootItem.requestActivate(); - onModuleRequested: { - pageStack.currentIndex = 0; - rootItem.currentModule = module; - } - } - onCurrentModuleChanged: { - if (currentModule.length > 0) { - pageStack.push(moduleItem); - } - pageStack.currentIndex = 1; - } + m_name = name; + Q_EMIT nameChanged(); + + const QString pluginPath = KPluginLoader::findPlugin(QLatin1String("kcms/") + name); + + KPluginLoader loader(pluginPath); + KPluginFactory* factory = loader.factory(); - Component.onCompleted: { - if (startModule.length > 0) { - rootItem.currentModule = startModule; + if (!factory) { + qWarning() << "Error loading KCM plugin:" << loader.errorString(); + } else { + m_kcm = factory->create(); + if (!m_kcm) { + qWarning() << "Error creating object from plugin" << loader.fileName(); } } - ModulesList { - id: modulesList - } + + Q_EMIT kcmChanged(); } + diff --git a/package/contents/ui/main.qml b/src/module.h similarity index 55% copy from package/contents/ui/main.qml copy to src/module.h index 91dba48..13a35ce 100644 --- a/package/contents/ui/main.qml +++ b/src/module.h @@ -1,63 +1,44 @@ /*************************************************************************** * * - * Copyright 2017 Marco Martin * - * Copyright 2011-2014 Sebastian Kügler * + * 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) any later version. * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ -import QtQuick 2.6 -import QtQuick.Controls 2.2 as Controls -import org.kde.kirigami 2.5 as Kirigami +#pragma once -import org.kde.plasma.settings 0.1 +#include +#include -Kirigami.ApplicationWindow { - id: rootItem +class Module : public QObject +{ + Q_OBJECT + Q_PROPERTY(KQuickAddons::ConfigModule* kcm READ kcm NOTIFY kcmChanged) + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) - property Item currentModule +public: + KQuickAddons::ConfigModule *kcm() const; + QString name() const; + void setName(const QString &name); - pageStack.initialPage: modulesList - pageStack.globalToolBar.style: Kirigami.ApplicationHeaderStyle.Breadcrumb +Q_SIGNALS: + void kcmChanged(); + void nameChanged(); - contextDrawer: Kirigami.ContextDrawer { - id: contextDrawer - } - - Connections { - target: settingsApp - onActivateRequested: rootItem.requestActivate(); - onModuleRequested: { - pageStack.currentIndex = 0; - rootItem.currentModule = module; - } - } - onCurrentModuleChanged: { - if (currentModule.length > 0) { - pageStack.push(moduleItem); - } - pageStack.currentIndex = 1; - } - - Component.onCompleted: { - if (startModule.length > 0) { - rootItem.currentModule = startModule; - } - } - ModulesList { - id: modulesList - } -} +private: + KQuickAddons::ConfigModule *m_kcm = nullptr; + QString m_name; +};