/* * Copyright 2013 Marco Martin * Copyright 2015 Eike Hein * * 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 "private/configcategory_p.h" #include "configview.h" #include "configmodel.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 #include namespace PlasmaQuick { //////////////////////////////ConfigModel class ConfigModelPrivate { public: ConfigModelPrivate(ConfigModel *model); ~ConfigModelPrivate(); ConfigModel *q; QList categories; QWeakPointer appletInterface; QHash kcms; void appendCategory(ConfigCategory *c); void clear(); QVariant get(int row) const; 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); }; ConfigModelPrivate::ConfigModelPrivate(ConfigModel *model) : q(model) { } ConfigModelPrivate::~ConfigModelPrivate() { } ConfigCategory *ConfigModelPrivate::categories_at(QQmlListProperty *prop, int index) { ConfigModel *model = qobject_cast(prop->object); if (!model || index >= model->d->categories.count() || index < 0) { return 0; } else { return model->d->categories.at(index); } } void ConfigModelPrivate::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->d->appendCategory(o); } int ConfigModelPrivate::categories_count(QQmlListProperty *prop) { ConfigModel *model = qobject_cast(prop->object); if (model) { return model->d->categories.count(); } else { return 0; } } void ConfigModelPrivate::categories_clear(QQmlListProperty *prop) { ConfigModel *model = qobject_cast(prop->object); if (!model) { return; } model->clear(); } void ConfigModelPrivate::clear() { q->beginResetModel(); while (!categories.isEmpty()) { categories.first()->setParent(0); categories.pop_front(); } q->endResetModel(); emit q->countChanged(); } void ConfigModelPrivate::appendCategory(ConfigCategory *c) { q->beginInsertRows(QModelIndex(), categories.size(), categories.size()); categories.append(c); auto emitChange = [this, c] { const int row = categories.indexOf(c); if (row > -1) { QModelIndex modelIndex = q->index(row); emit q->dataChanged(modelIndex, modelIndex); } }; QObject::connect(c, &ConfigCategory::nameChanged, q, emitChange); QObject::connect(c, &ConfigCategory::iconChanged, q, emitChange); QObject::connect(c, &ConfigCategory::sourceChanged, q, emitChange); QObject::connect(c, &ConfigCategory::pluginNameChanged, q, emitChange); QObject::connect(c, &ConfigCategory::visibleChanged, q, emitChange); q->endInsertRows(); emit q->countChanged(); } QVariant ConfigModelPrivate::get(int row) const { QVariantMap value; if (row < 0 || row >= categories.count()) { return value; } value[QStringLiteral("name")] = categories.at(row)->name(); value[QStringLiteral("icon")] = categories.at(row)->icon(); value[QStringLiteral("pluginName")] = categories.at(row)->pluginName(); value[QStringLiteral("source")] = q->data(q->index(row, 0), ConfigModel::SourceRole); value[QStringLiteral("visible")] = categories.at(row)->visible(); value[QStringLiteral("kcm")] = q->data(q->index(row, 0), ConfigModel::KCMRole); return value; } ConfigModel::ConfigModel(QObject *parent) : QAbstractListModel(parent), d(new ConfigModelPrivate(this)) { } ConfigModel::~ConfigModel() { delete d; } int ConfigModel::rowCount(const QModelIndex &index) const { if (index.column() > 0) { return 0; } return d->categories.count(); } QVariant ConfigModel::data(const QModelIndex &index, int role) const { if (index.row() < 0 || index.row() >= d->categories.count()) { return QVariant(); } switch (role) { case NameRole: return d->categories.at(index.row())->name(); case IconRole: return d->categories.at(index.row())->icon(); case SourceRole: { const QString source = d->categories.at(index.row())->source(); // Quick check if source is an absolute path or not if (d->appletInterface && !source.isEmpty() && !(source.startsWith('/') && source.endsWith(QLatin1String("qml")))) { if(!d->appletInterface.data()->kPackage().isValid()) qWarning() << "wrong applet" << d->appletInterface.data()->pluginMetaData().name(); return QUrl::fromLocalFile(d->appletInterface.data()->kPackage().filePath("ui", source)); } else { return source; } } case PluginNameRole: return d->categories.at(index.row())->pluginName(); case VisibleRole: return d->categories.at(index.row())->visible(); case KCMRole: { const QString pluginName = d->categories.at(index.row())->pluginName(); const QString pluginPath = KPluginLoader::findPlugin(pluginName); //no kcm is registered for this row, it's a normal qml-only entry if (pluginName.isEmpty() || pluginPath.isEmpty()) { return QVariant(); } if (d->kcms.contains(pluginName)) { return QVariant::fromValue(d->kcms.value(pluginName)); } KPluginLoader loader(pluginPath); KPluginFactory* factory = loader.factory(); if (!factory) { qWarning() << "Error loading KCM:" << loader.errorString(); } else { KQuickAddons::ConfigModule *cm = factory->create(const_cast(this)); if (!cm) { qWarning() << "Error creating KCM object from plugin" << loader.fileName(); } d->kcms[pluginName] = cm; return QVariant::fromValue(cm); } } default: return QVariant(); } } QHash ConfigModel::roleNames() const { return { {NameRole, "name"}, {IconRole, "icon"}, {SourceRole, "source"}, {PluginNameRole, "pluginName"}, {VisibleRole, "visible"}, {KCMRole, "kcm"}, }; } QVariant ConfigModel::get(int row) const { return d->get(row); } void ConfigModel::appendCategory(const QString &iconName, const QString &name, const QString &path, const QString &pluginName) { ConfigCategory *cat = new ConfigCategory(this); cat->setIcon(iconName); cat->setName(name); cat->setSource(path); cat->setPluginName(pluginName); d->appendCategory(cat); } void ConfigModel::appendCategory(const QString &iconName, const QString &name, const QString &path, const QString &pluginName, bool visible) { ConfigCategory *cat = new ConfigCategory(this); cat->setIcon(iconName); cat->setName(name); cat->setSource(path); cat->setPluginName(pluginName); cat->setVisible(visible); d->appendCategory(cat); } void ConfigModel::clear() { d->clear(); } void ConfigModel::setApplet(Plasma::Applet *interface) { d->appletInterface = interface; } Plasma::Applet *ConfigModel::applet() const { return d->appletInterface.data(); } QQmlListProperty ConfigModel::categories() { return QQmlListProperty(this, 0, ConfigModelPrivate::categories_append, ConfigModelPrivate::categories_count, ConfigModelPrivate::categories_at, ConfigModelPrivate::categories_clear); } } #include "moc_configmodel.cpp"