From 0034c7da79a50186a58620b059fa3944b819d49f Mon Sep 17 00:00:00 2001 From: Marco Martin Date: Wed, 24 Apr 2013 22:54:46 +0200 Subject: [PATCH] move the config dialog in the shell it still doesn't successfully load --- CMakeLists.txt | 2 + configview.cpp | 332 ++++++++++++++++++++++++++++++++++++++ configview.h | 141 ++++++++++++++++ containmentconfigview.cpp | 138 ++++++++++++++++ containmentconfigview.h | 62 +++++++ desktopcorona.cpp | 31 +++- desktopcorona.h | 5 + 7 files changed, 710 insertions(+), 1 deletion(-) create mode 100644 configview.cpp create mode 100644 configview.h create mode 100644 containmentconfigview.cpp create mode 100644 containmentconfigview.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ff12f232..009ff5a4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,8 @@ set(widgetexplorer_SRC add_executable(plasma-shell main.cpp + configview.cpp + containmentconfigview.cpp desktopcorona.cpp panelview.cpp shellpluginloader.cpp diff --git a/configview.cpp b/configview.cpp new file mode 100644 index 000000000..00646c0c2 --- /dev/null +++ b/configview.cpp @@ -0,0 +1,332 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, 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 Library 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. + */ + +#include "configview.h" +#include "Plasma/Applet" +#include "Plasma/Containment" +//#include "plasmoid/wallpaperinterface.h" +#include "kdeclarative/configpropertymap.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +///////////////////////ConfigCategory + +ConfigCategory::ConfigCategory(QObject *parent) + : QObject(parent) +{ +} + +ConfigCategory::~ConfigCategory() +{} + +QString ConfigCategory::name() const +{ + return m_name; +} + +void ConfigCategory::setName(const QString &name) +{ + if (m_name == name) { + return; + } + + m_name = name; + emit nameChanged(); +} + + +QString ConfigCategory::icon() const +{ + return m_icon; +} + +void ConfigCategory::setIcon(const QString &icon) +{ + if (m_icon == icon) { + return; + } + + m_icon = icon; + emit iconChanged(); +} + + +QString ConfigCategory::source() const +{ + return m_source; +} + +void ConfigCategory::setSource(const QString &source) +{ + if (m_source == source) { + return; + } + + m_source = source; + emit sourceChanged(); +} + +QString ConfigCategory::pluginName() const +{ + return m_pluginName; +} + +void ConfigCategory::setPluginName(const QString &name) +{ + if (m_pluginName == name) { + return; + } + + m_pluginName = name; + emit pluginNameChanged(); +} + + + +//////////////////////////////ConfigModel +ConfigModel::ConfigModel(QObject *parent) + : QAbstractListModel(parent) +{ + QHash roleNames; + roleNames[NameRole] = "name"; + roleNames[IconRole] = "icon"; + roleNames[SourceRole] = "source"; + roleNames[PluginNameRole] = "pluginName"; + + setRoleNames(roleNames); + qDebug() << " XXX loaded QALM"; +} + +ConfigModel::~ConfigModel() +{} + +int ConfigModel::rowCount(const QModelIndex &index) const +{ + if (index.column() > 0) { + return 0; + } + return m_categories.count(); +} + +QVariant ConfigModel::data(const QModelIndex& index, int role) const +{ + if (index.row() < 0 || index.row() >= m_categories.count()) { + return QVariant(); + } + switch (role) { + case NameRole: + return m_categories.at(index.row())->name(); + case IconRole: + return m_categories.at(index.row())->icon(); + case SourceRole: + if (m_appletInterface) { + return QUrl::fromLocalFile(m_appletInterface.data()->package().filePath("ui", m_categories.at(index.row())->source())); + } else { + return m_categories.at(index.row())->source(); + } + case PluginNameRole: + return m_categories.at(index.row())->pluginName(); + default: + return QVariant(); + } +} + +QVariant ConfigModel::get(int row) const +{ + QVariantMap value; + if (row < 0 || row >= m_categories.count()) { + return value; + } + + value["name"] = m_categories.at(row)->name(); + value["icon"] = m_categories.at(row)->icon(); + if (m_appletInterface) { + value["source"] = QUrl::fromLocalFile(m_appletInterface.data()->package().filePath("components", m_categories.at(row)->source())); + } else { + value["source"] = m_categories.at(row)->source(); + } + return value; +} + +void ConfigModel::appendCategory(ConfigCategory *c) +{ + beginInsertRows(QModelIndex(), m_categories.size(), m_categories.size()); + m_categories.append(c); + endInsertRows(); + emit countChanged(); +} + +void ConfigModel::clear() +{ + beginResetModel(); + while (!m_categories.isEmpty()) { + m_categories.first()->setParent(0); + m_categories.pop_front(); + } + endResetModel(); + emit countChanged(); +} + +void ConfigModel::setApplet(Plasma::Applet *interface) +{ + m_appletInterface = interface; +} + +Plasma::Applet *ConfigModel::applet() const +{ + return m_appletInterface.data(); +} + +QQmlListProperty ConfigModel::categories() +{ + return QQmlListProperty(this, 0, ConfigModel::categories_append, + ConfigModel::categories_count, + ConfigModel::categories_at, + ConfigModel::categories_clear); + +} + +ConfigCategory *ConfigModel::categories_at(QQmlListProperty *prop, int index) +{ + ConfigModel *model = qobject_cast(prop->object); + if (!model || index >= model->m_categories.count() || index < 0) + return 0; + else + return model->m_categories.at(index); +} + +void ConfigModel::categories_append(QQmlListProperty *prop, ConfigCategory *o) +{ + ConfigModel *model = qobject_cast(prop->object); + if (!o || !model) { + return; + } + + if (o->parent() == prop->object) { + o->setParent(0); + } + + o->setParent(prop->object); + model->appendCategory(o); +} + +int ConfigModel::categories_count(QQmlListProperty *prop) +{ + ConfigModel *model = qobject_cast(prop->object); + if (model) { + return model->m_categories.count(); + } else { + return 0; + } +} + +void ConfigModel::categories_clear(QQmlListProperty *prop) +{ + ConfigModel *model = qobject_cast(prop->object); + if (!model) { + return; + } + + model->clear(); +} + + + +//////////////////////////////ConfigView +ConfigView::ConfigView(Plasma::Applet *interface, QWindow *parent) + : QQuickView(parent), + m_applet(interface) +{ + qmlRegisterType("org.kde.plasma.configuration", 2, 0, "ConfigModel"); + qmlRegisterType("org.kde.plasma.configuration", 2, 0, "ConfigCategory"); + + //FIXME: problem on nvidia, all windows should be transparent or won't show + setColor(Qt::transparent); + setTitle(i18n("%1 Settings", m_applet->title())); + + + if (!m_applet->containment()->corona()->package().isValid()) { + qWarning() << "Invalid home screen package"; + } + + setResizeMode(QQuickView::SizeViewToRootObject); + + + //config model local of the applet + QQmlComponent *component = new QQmlComponent(engine(), QUrl::fromLocalFile(m_applet->package().filePath("configmodel")), this); + QObject *object = component->create(engine()->rootContext()); + m_configModel = qobject_cast(object); + if (m_configModel) { + m_configModel->setApplet(m_applet); + } else { + delete object; + } + delete component; + + Plasma::Containment *cont = qobject_cast(m_applet); + + engine()->rootContext()->setContextProperty("plasmoid", interface); + engine()->rootContext()->setContextProperty("configDialog", this); +} + +ConfigView::~ConfigView() +{ +} + +void ConfigView::init() +{ + setSource(QUrl::fromLocalFile(m_applet->containment()->corona()->package().filePath("configurationui"))); +} + +ConfigModel *ConfigView::configModel() const +{ + return m_configModel; +} + + +//To emulate Qt::WA_DeleteOnClose that QWindow doesn't have +void ConfigView::hideEvent(QHideEvent *ev) +{ + QQuickWindow::hideEvent(ev); + deleteLater(); +} + +void ConfigView::resizeEvent(QResizeEvent *re) +{ + if (!rootObject()) { + return; + } + rootObject()->setWidth(re->size().width()); + rootObject()->setHeight(re->size().height()); + QQuickWindow::resizeEvent(re); +} + + +#include "moc_configview.cpp" diff --git a/configview.h b/configview.h new file mode 100644 index 000000000..064e54a6e --- /dev/null +++ b/configview.h @@ -0,0 +1,141 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, 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 Library 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. + */ + +#ifndef CONFIGUILOADER_H +#define CONFIGUILOADER_H + + +#include +#include +#include +#include + +namespace Plasma { + class Applet; +} + +class ConfigPropertyMap; + + +class ConfigCategory : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + Q_PROPERTY(QString icon READ icon WRITE setIcon NOTIFY iconChanged) + Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged) + Q_PROPERTY(QString pluginName READ pluginName WRITE setPluginName NOTIFY pluginNameChanged) + +public: + ConfigCategory(QObject *parent = 0); + ~ConfigCategory(); + + QString name() const; + void setName(const QString &name); + + QString icon() const; + void setIcon(const QString &icon); + + QString source() const; + void setSource(const QString &source); + + QString pluginName() const; + void setPluginName(const QString &pluginName); + +Q_SIGNALS: + void nameChanged(); + void iconChanged(); + void sourceChanged(); + void pluginNameChanged(); + +private: + QString m_name; + QString m_icon; + QString m_source; + QString m_pluginName; +}; + +class ConfigModel : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(QQmlListProperty categories READ categories CONSTANT) + Q_CLASSINFO("DefaultProperty", "categories") + Q_PROPERTY(int count READ count NOTIFY countChanged) + +public: + enum Roles { + NameRole = Qt::UserRole+1, + IconRole, + SourceRole, + PluginNameRole + }; + ConfigModel(QObject *parent = 0); + ~ConfigModel(); + + void appendCategory(ConfigCategory *c); + void clear(); + + void setApplet(Plasma::Applet *interface); + Plasma::Applet *applet() const; + + int count() {return rowCount();} + virtual int rowCount(const QModelIndex &index = QModelIndex()) const; + virtual QVariant data(const QModelIndex&, int) const; + Q_INVOKABLE QVariant get(int row) const; + + QQmlListProperty categories(); + + static ConfigCategory *categories_at(QQmlListProperty *prop, int index); + static void categories_append(QQmlListProperty *prop, ConfigCategory *o); + static int categories_count(QQmlListProperty *prop); + static void categories_clear(QQmlListProperty *prop); + +Q_SIGNALS: + void countChanged(); + +private: + QListm_categories; + QWeakPointer m_appletInterface; +}; + + +//TODO: the config view for the containment should be a subclass +//TODO: is it possible to move this in the shell? +class ConfigView : public QQuickView +{ + Q_OBJECT + Q_PROPERTY(ConfigModel *configModel READ configModel CONSTANT) + +public: + ConfigView(Plasma::Applet *applet, QWindow *parent = 0); + virtual ~ConfigView(); + + void init(); + + ConfigModel *configModel() const; + +protected: + void hideEvent(QHideEvent *ev); + void resizeEvent(QResizeEvent *re); + +private: + Plasma::Applet *m_applet; + ConfigModel *m_configModel; +}; + +#endif // multiple inclusion guard diff --git a/containmentconfigview.cpp b/containmentconfigview.cpp new file mode 100644 index 000000000..481255e74 --- /dev/null +++ b/containmentconfigview.cpp @@ -0,0 +1,138 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, 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 Library 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. + */ + +#include "containmentconfigview.h" +#include +//#include "plasmoid/wallpaperinterface.h" +#include + +#include +#include +#include +#include + + +#include + +#include + + +//////////////////////////////ContainmentConfigView +ContainmentConfigView::ContainmentConfigView(Plasma::Containment *cont, QWindow *parent) + : ConfigView(cont, parent), + m_containment(cont), + m_wallpaperConfigModel(0), + m_currentWallpaperConfig(0) +{ + engine()->rootContext()->setContextProperty("configDialog", this); + setCurrentWallpaper(cont->containment()->wallpaper()); +} + +ContainmentConfigView::~ContainmentConfigView() +{ +} + +ConfigModel *ContainmentConfigView::wallpaperConfigModel() +{ + if (!m_wallpaperConfigModel) { + m_wallpaperConfigModel = new ConfigModel(this); + QStringList dirs(QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "plasma/wallpapers", QStandardPaths::LocateDirectory)); + Plasma::Package pkg = Plasma::PluginLoader::self()->loadPackage("Plasma/Generic"); + foreach (const QString &dirPath, dirs) { + QDir dir(dirPath); + pkg.setDefaultPackageRoot(dirPath); + QStringList packages; + + foreach (const QString &sdir, dir.entryList(QDir::AllDirs | QDir::Readable)) { + QString metadata = dirPath + '/' + sdir + "/metadata.desktop"; + if (QFile::exists(metadata)) { + packages << sdir; + } + } + + foreach (const QString &package, packages) { + pkg.setPath(package); + if (!pkg.isValid()) { + continue; + } + ConfigCategory *cat = new ConfigCategory(m_wallpaperConfigModel); + cat->setName(pkg.metadata().name()); + cat->setIcon(pkg.metadata().icon()); + cat->setSource(pkg.filePath("ui", "config.qml")); + cat->setPluginName(package); + m_wallpaperConfigModel->appendCategory(cat); + } + } + } + return m_wallpaperConfigModel; +} + +ConfigPropertyMap *ContainmentConfigView::wallpaperConfiguration() const +{ + return m_currentWallpaperConfig; +} + +QString ContainmentConfigView::currentWallpaper() const +{ + return m_currentWallpaper; +} + +void ContainmentConfigView::setCurrentWallpaper(const QString &wallpaper) +{ + /*if (m_currentWallpaper == wallpaper) { + return; + } + + if (m_containment->containment()->wallpaper() == wallpaper) { + delete m_currentWallpaperConfig; + if (m_containment->wallpaperInterface()) { + m_currentWallpaperConfig = m_containment->wallpaperInterface()->configuration(); + } + } else { + if (m_containment->containment()->wallpaper() != m_currentWallpaper) { + delete m_currentWallpaperConfig; + } + + //we have to construct an independent ConfigPropertyMap when we want to configure wallpapers that are not the current one + Plasma::Package pkg = Plasma::PluginLoader::self()->loadPackage("Plasma/Generic"); + pkg.setDefaultPackageRoot("plasma/wallpapers"); + pkg.setPath(wallpaper); + QFile file(pkg.filePath("config", "main.xml")); + KConfigGroup cfg = m_containment->containment()->config(); + cfg = KConfigGroup(&cfg, "Wallpaper"); + m_currentWallpaperConfig = new ConfigPropertyMap(new Plasma::ConfigLoader(&cfg, &file), this); + }*/ + + m_currentWallpaper = wallpaper; + emit currentWallpaperChanged(); + emit wallpaperConfigurationChanged(); +} + +void ContainmentConfigView::applyWallpaper() +{ + /*m_containment->containment()->setWallpaper(m_currentWallpaper); + + if (m_currentWallpaperConfig != m_containment->wallpaperInterface()->configuration()) { + delete m_currentWallpaperConfig; + m_currentWallpaperConfig = m_containment->wallpaperInterface()->configuration(); + emit wallpaperConfigurationChanged(); + }*/ +} + +#include "moc_containmentconfigview.cpp" diff --git a/containmentconfigview.h b/containmentconfigview.h new file mode 100644 index 000000000..1d2dfb16a --- /dev/null +++ b/containmentconfigview.h @@ -0,0 +1,62 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, 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 Library 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. + */ + +#ifndef CONTAINMENTCONFIGVIEW_H +#define CONTAINMENTCONFIGVIEW_H + + +#include "configview.h" + +namespace Plasma { + class Containment; +} +class ConfigPropertyMap; + + +//TODO: is it possible to move this in the shell? +class ContainmentConfigView : public ConfigView +{ + Q_OBJECT + Q_PROPERTY(ConfigModel *wallpaperConfigModel READ wallpaperConfigModel CONSTANT) + Q_PROPERTY(ConfigPropertyMap *wallpaperConfiguration READ wallpaperConfiguration NOTIFY wallpaperConfigurationChanged) + Q_PROPERTY(QString currentWallpaper READ currentWallpaper WRITE setCurrentWallpaper NOTIFY currentWallpaperChanged) + +public: + ContainmentConfigView(Plasma::Containment *interface, QWindow *parent = 0); + virtual ~ContainmentConfigView(); + + ConfigModel *wallpaperConfigModel(); + QString currentWallpaper() const; + void setCurrentWallpaper(const QString &wallpaper); + ConfigPropertyMap *wallpaperConfiguration() const; + + Q_INVOKABLE void applyWallpaper(); + +Q_SIGNALS: + void currentWallpaperChanged(); + void wallpaperConfigurationChanged(); + +private: + Plasma::Containment *m_containment; + ConfigModel *m_wallpaperConfigModel; + QString m_currentWallpaper; + ConfigPropertyMap *m_currentWallpaperConfig; +}; + +#endif // multiple inclusion guard diff --git a/desktopcorona.cpp b/desktopcorona.cpp index 0f33b368a..6265cd031 100644 --- a/desktopcorona.cpp +++ b/desktopcorona.cpp @@ -29,6 +29,7 @@ #include #include +#include "containmentconfigview.h" #include "panelview.h" #include "view.h" #include "scripting/desktopscriptengine.h" @@ -266,7 +267,10 @@ void DesktopCorona::updateScreenOwner(int wasScreen, int isScreen, Plasma::Conta void DesktopCorona::handleContainmentAdded(Plasma::Containment* c) { - connect(c, &Plasma::Containment::showAddWidgetsInterface, this, &DesktopCorona::showWidgetExplorer); + connect(c, &Plasma::Containment::showAddWidgetsInterface, + this, &DesktopCorona::showWidgetExplorer); + connect(c, &Plasma::Containment::configureRequested, + this, &DesktopCorona::showConfigurationInterface); } void DesktopCorona::showWidgetExplorer() @@ -300,5 +304,30 @@ void DesktopCorona::printScriptMessage(const QString &message) qDebug() << message; } +void DesktopCorona::showConfigurationInterface(Plasma::Applet *applet) +{ + if (m_configView) { + m_configView.data()->hide(); + m_configView.data()->deleteLater(); + } + + if (!applet || !applet->containment()) { + return; + } + + if (!m_configView) { + Plasma::Containment *cont = qobject_cast(applet); + + if (cont) { + m_configView = new ContainmentConfigView(cont); + } else { + m_configView = new ConfigView(applet); + } + m_configView.data()->init(); + } + + m_configView.data()->show(); +} + #include "desktopcorona.moc" diff --git a/desktopcorona.h b/desktopcorona.h index a0a8dcf08..ea110d483 100644 --- a/desktopcorona.h +++ b/desktopcorona.h @@ -23,6 +23,8 @@ class * Free Software Foundation, Inc., #include "plasma/corona.h" +#include "configview.h" + class QDesktopWidget; class QQuickView; class PanelView; @@ -83,6 +85,8 @@ protected Q_SLOTS: void printScriptError(const QString &error); void printScriptMessage(const QString &message); + void showConfigurationInterface(Plasma::Applet *applet); + private Q_SLOTS: void handleContainmentAdded(Plasma::Containment *c); void showWidgetExplorer(); @@ -93,6 +97,7 @@ private: WidgetExplorerView *m_widgetExplorerView; QHash m_panelViews; KConfigGroup m_desktopDefaultsConfig; + QWeakPointer m_configView; }; #endif