diff --git a/abstractentry.cpp b/abstractentry.cpp index 846a5482c..1e5e714d0 100644 --- a/abstractentry.cpp +++ b/abstractentry.cpp @@ -1,95 +1,100 @@ /*************************************************************************** * Copyright (C) 2014-2015 by Eike Hein * * * * 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 . * ***************************************************************************/ #include "abstractentry.h" AbstractEntry::AbstractEntry(AbstractModel *owner) : m_owner(owner) { } AbstractEntry::~AbstractEntry() { } AbstractModel *AbstractEntry::owner() const { return m_owner; } bool AbstractEntry::isValid() const { return true; } QIcon AbstractEntry::icon() const { return QIcon(); } QString AbstractEntry::name() const { return QString(); } +QString AbstractEntry::description() const +{ + return QString(); +} + QString AbstractEntry::id() const { return QString(); } QUrl AbstractEntry::url() const { return QUrl(); } bool AbstractEntry::hasChildren() const { return false; } AbstractModel *AbstractEntry::childModel() const { return nullptr; } bool AbstractEntry::hasActions() const { return false; } QVariantList AbstractEntry::actions() const { return QVariantList(); } bool AbstractEntry::run(const QString& actionId, const QVariant &argument) { Q_UNUSED(actionId) Q_UNUSED(argument) return false; } AbstractGroupEntry::AbstractGroupEntry(AbstractModel *owner) : AbstractEntry(owner) { } SeparatorEntry::SeparatorEntry(AbstractModel *owner) : AbstractEntry(owner) { } diff --git a/abstractentry.h b/abstractentry.h index e09b3cfa6..81781bb55 100644 --- a/abstractentry.h +++ b/abstractentry.h @@ -1,77 +1,78 @@ /*************************************************************************** * Copyright (C) 2012 Aurélien Gâteau * * Copyright (C) 2014-2015 by Eike Hein * * * * 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 . * ***************************************************************************/ #ifndef ABSTRACTENTRY_H #define ABSTRACTENTRY_H #include "abstractmodel.h" #include #include class AbstractEntry { public: explicit AbstractEntry(AbstractModel *owner); virtual ~AbstractEntry(); enum EntryType { RunnableType, GroupType, SeparatorType }; virtual EntryType type() const = 0; AbstractModel *owner() const; virtual bool isValid() const; virtual QIcon icon() const; virtual QString name() const; + virtual QString description() const; virtual QString id() const; virtual QUrl url() const; virtual bool hasChildren() const; virtual AbstractModel *childModel() const; virtual bool hasActions() const; virtual QVariantList actions() const; virtual bool run(const QString& actionId = QString(), const QVariant &argument = QVariant()); protected: AbstractModel* m_owner; }; class AbstractGroupEntry : public AbstractEntry { public: explicit AbstractGroupEntry(AbstractModel *owner); EntryType type() const { return GroupType; } }; class SeparatorEntry : public AbstractEntry { public: explicit SeparatorEntry(AbstractModel *owner); EntryType type() const { return SeparatorType; } }; #endif diff --git a/abstractmodel.cpp b/abstractmodel.cpp index 18eed0357..2cd4aaad1 100644 --- a/abstractmodel.cpp +++ b/abstractmodel.cpp @@ -1,135 +1,136 @@ /*************************************************************************** * Copyright (C) 2014-2015 by Eike Hein * * * * 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 . * ***************************************************************************/ #include "abstractmodel.h" #include "actionlist.h" AbstractModel::AbstractModel(QObject *parent) : QAbstractListModel(parent) , m_iconSize(32) { } AbstractModel::~AbstractModel() { } QHash AbstractModel::roleNames() const { QHash roles; roles.insert(Qt::DisplayRole, "display"); roles.insert(Qt::DecorationRole, "decoration"); + roles.insert(Kicker::DescriptionRole, "description"); roles.insert(Kicker::FavoriteIdRole, "favoriteId"); roles.insert(Kicker::IsParentRole, "isParent"); roles.insert(Kicker::IsSeparatorRole, "isSeparator"); roles.insert(Kicker::HasChildrenRole, "hasChildren"); roles.insert(Kicker::HasActionListRole, "hasActionList"); roles.insert(Kicker::ActionListRole, "actionList"); roles.insert(Kicker::UrlRole, "url"); return roles; } int AbstractModel::count() const { return rowCount(); } int AbstractModel::separatorCount() const { return 0; } int AbstractModel::columnCount(const QModelIndex &parent) const { if (parent.isValid()) { return 0; } return 1; } int AbstractModel::iconSize() const { return m_iconSize; } void AbstractModel::setIconSize(int iconSize) { if (m_iconSize != iconSize) { m_iconSize = iconSize; refresh(); } } void AbstractModel::refresh() { } QString AbstractModel::labelForRow(int row) { return data(index(row, 0), Qt::DisplayRole).toString(); } AbstractModel *AbstractModel::modelForRow(int row) { Q_UNUSED(row) return 0; } bool AbstractModel::hasActions() const { return false; } QVariantList AbstractModel::actions() const { return QVariantList(); } AbstractModel* AbstractModel::favoritesModel() { return rootModel()->favoritesModel(); } AbstractModel* AbstractModel::rootModel() { if (!parent()) { return nullptr; } QObject *p = this; AbstractModel *rootModel = nullptr; while (p) { if (qobject_cast(p)) { rootModel = qobject_cast(p); } else { return rootModel; } p = p->parent(); } return rootModel; } void AbstractModel::entryChanged(AbstractEntry *entry) { Q_UNUSED(entry) } diff --git a/actionlist.h b/actionlist.h index 4aaa1d5c9..065ce9d45 100644 --- a/actionlist.h +++ b/actionlist.h @@ -1,53 +1,54 @@ /*************************************************************************** * Copyright (C) 2013 by Aurélien Gâteau * * Copyright (C) 2014-2015 by Eike Hein * * * * 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 . * ***************************************************************************/ #include #include class KFileItem; namespace Kicker { enum { - FavoriteIdRole = Qt::UserRole + 1, + DescriptionRole = Qt::UserRole + 1, + FavoriteIdRole, IsSeparatorRole, IsDropPlaceholderRole, IsParentRole, HasChildrenRole, HasActionListRole, ActionListRole, UrlRole }; QVariantMap createActionItem(const QString &label, const QString &actionId, const QVariant &argument = QVariant()); QVariantMap createTitleActionItem(const QString &label); QVariantMap createSeparatorActionItem(); QVariantList createActionListForFileItem(const KFileItem &fileItem); bool handleFileItemAction(const KFileItem &fileItem, const QString &actionId, const QVariant &argument, bool *close); QVariantList recentDocumentActions(KService::Ptr service); bool handleRecentDocumentAction(KService::Ptr service, const QString &actionId, const QVariant &argument); } diff --git a/appentry.cpp b/appentry.cpp index 34bab3d9f..34ca07e79 100644 --- a/appentry.cpp +++ b/appentry.cpp @@ -1,309 +1,314 @@ /*************************************************************************** * Copyright (C) 201 by Eike Hein * * * * 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 . * ***************************************************************************/ #include "appentry.h" #include "actionlist.h" #include "appsmodel.h" #include "containmentinterface.h" #include "menuentryeditor.h" #ifdef PackageKitQt5_FOUND #include "findpackagenamejob.h" #endif #include #include #include #include #if HAVE_X11 #include #endif #include #include #include #include #include #include #include #include #include #include QObject *AppEntry::m_appletInterface = nullptr; QQmlPropertyMap *AppEntry::m_appletConfig = nullptr; MenuEntryEditor *AppEntry::m_menuEntryEditor = nullptr; AppEntry::AppEntry(AbstractModel *owner, KService::Ptr service, NameFormat nameFormat) : AbstractEntry(owner) , m_service(service) { if (m_service) { init(nameFormat); } } AppEntry::AppEntry(AbstractModel *owner, const QString &id) : AbstractEntry(owner) { const QUrl url(id); if (url.scheme() == QStringLiteral("preferred")) { m_service = defaultAppByName(url.host()); m_id = id; } else { m_service = KService::serviceByStorageId(id); } if (m_service) { init((NameFormat)qobject_cast(owner->rootModel())->appNameFormat()); } } void AppEntry::init(NameFormat nameFormat) { m_name = nameFromService(m_service, nameFormat); m_icon = QIcon::fromTheme(m_service->icon(), QIcon::fromTheme("unknown")); if (!m_appletInterface) { AbstractModel *rootModel = m_owner->rootModel(); m_appletInterface = rootModel->property("appletInterface").value(); m_appletConfig = qobject_cast(m_appletInterface->property("configuration").value()); } if (!m_menuEntryEditor) { m_menuEntryEditor = new MenuEntryEditor(); } } bool AppEntry::isValid() const { return m_service; } QIcon AppEntry::icon() const { return m_icon; } QString AppEntry::name() const { return m_name; } +QString AppEntry::description() const +{ + return m_service->comment(); +} + KService::Ptr AppEntry::service() const { return m_service; } QString AppEntry::id() const { if (!m_id.isEmpty()) { return m_id; } return m_service->storageId(); } QUrl AppEntry::url() const { return QUrl::fromLocalFile(m_service->entryPath()); } bool AppEntry::hasActions() const { return true; } QVariantList AppEntry::actions() const { QVariantList actionList; actionList << Kicker::recentDocumentActions(m_service); if (actionList.count()) { actionList << Kicker::createSeparatorActionItem(); } if (ContainmentInterface::mayAddLauncher(m_appletInterface, ContainmentInterface::Desktop)) { actionList << Kicker::createActionItem(i18n("Add to Desktop"), "addToDesktop"); } if (ContainmentInterface::mayAddLauncher(m_appletInterface, ContainmentInterface::Panel)) { actionList << Kicker::createActionItem(i18n("Add to Panel"), "addToPanel"); } if (ContainmentInterface::mayAddLauncher(m_appletInterface, ContainmentInterface::TaskManager, m_service->entryPath())) { actionList << Kicker::createActionItem(i18n("Add as Launcher"), "addToTaskManager"); } if (m_menuEntryEditor->canEdit(m_service->entryPath())) { actionList << Kicker::createSeparatorActionItem(); QVariantMap editAction = Kicker::createActionItem(i18n("Edit Application..."), "editApplication"); editAction["icon"] = "kmenuedit"; // TODO: Using the KMenuEdit icon might be misleading. actionList << editAction; } #ifdef PackageKitQt5_FOUND QStringList files(m_service->entryPath()); if (m_service->isApplication()) { files += QStandardPaths::findExecutable(KShell::splitArgs(m_service->exec()).first()); } FindPackageJob* job = new FindPackageJob(files); // TODO: Would be great to make this async. if (job->exec() && !job->packageNames().isEmpty()) { QString packageName = job->packageNames().first(); QVariantMap removeAction = Kicker::createActionItem(i18n("Remove '%1'...", packageName), "removeApplication", packageName); removeAction["icon"] = "applications-other"; actionList << removeAction; } #endif if (m_appletConfig && m_appletConfig->contains("hiddenApplications") && qobject_cast(m_owner)) { const QStringList &hiddenApps = m_appletConfig->value("hiddenApplications").toStringList(); if (!hiddenApps.contains(m_service->menuId())) { actionList << Kicker::createActionItem(i18n("Hide Application"), "hideApplication"); } } return actionList; } bool AppEntry::run(const QString& actionId, const QVariant &argument) { if (actionId.isEmpty()) { quint32 timeStamp = 0; #if HAVE_X11 if (QX11Info::isPlatformX11()) { timeStamp = QX11Info::appUserTime(); } #endif new KRun(QUrl::fromLocalFile(m_service->entryPath()), 0, true, KStartupInfo::createNewStartupIdForTimestamp(timeStamp)); KActivities::ResourceInstance::notifyAccessed(QUrl("applications:" + m_service->storageId()), "org.kde.plasma.kicker"); return true; } else if (actionId == "addToDesktop" && ContainmentInterface::mayAddLauncher(m_appletInterface, ContainmentInterface::Desktop)) { ContainmentInterface::addLauncher(m_appletInterface, ContainmentInterface::Desktop, m_service->entryPath()); } else if (actionId == "addToPanel" && ContainmentInterface::mayAddLauncher(m_appletInterface, ContainmentInterface::Panel)) { ContainmentInterface::addLauncher(m_appletInterface, ContainmentInterface::Panel, m_service->entryPath()); } else if (actionId == "addToTaskManager" && ContainmentInterface::mayAddLauncher(m_appletInterface, ContainmentInterface::TaskManager, m_service->entryPath())) { ContainmentInterface::addLauncher(m_appletInterface, ContainmentInterface::TaskManager, m_service->entryPath()); } else if (actionId == "editApplication" && m_menuEntryEditor->canEdit(m_service->entryPath())) { m_menuEntryEditor->edit(m_service->entryPath(), m_service->menuId()); return true; } else if (actionId == "removeApplication") { if (m_appletConfig && m_appletConfig->contains("removeApplicationCommand")) { const QStringList &removeAppCmd = KShell::splitArgs(m_appletConfig->value("removeApplicationCommand").toString()); if (!removeAppCmd.isEmpty()) { return QProcess::startDetached(removeAppCmd.first(), removeAppCmd.mid(1) << argument.toString()); } } } return Kicker::handleRecentDocumentAction(m_service, actionId, argument); } QString AppEntry::nameFromService(const KService::Ptr service, NameFormat nameFormat) { const QString &name = service->name(); QString genericName = service->genericName(); if (genericName.isEmpty()) { genericName = service->comment(); } if (nameFormat == NameOnly || genericName.isEmpty() || name == genericName) { return name; } else if (nameFormat == GenericNameOnly) { return genericName; } else if (nameFormat == NameAndGenericName) { return i18nc("App name (Generic name)", "%1 (%2)", name, genericName); } else { return i18nc("Generic name (App name)", "%1 (%2)", genericName, name); } } KService::Ptr AppEntry::defaultAppByName(const QString& name) { if (name == QLatin1String("browser")) { KConfigGroup config(KSharedConfig::openConfig(), "General"); QString browser = config.readPathEntry("BrowserApplication", QString()); if (browser.isEmpty()) { return KMimeTypeTrader::self()->preferredService(QLatin1String("text/html")); } else if (browser.startsWith('!')) { browser = browser.mid(1); } return KService::serviceByStorageId(browser); } return KService::Ptr(); } AppGroupEntry::AppGroupEntry(AppsModel *parentModel, KServiceGroup::Ptr group, bool flat, bool separators, int appNameFormat) : AbstractGroupEntry(parentModel) { m_name = group->caption(); m_icon = QIcon::fromTheme(group->icon(), QIcon::fromTheme("unknown")); AppsModel* model = new AppsModel(group->entryPath(), flat, separators, parentModel); model->setAppNameFormat(appNameFormat); m_childModel = model; QObject::connect(parentModel, &AppsModel::cleared, model, &AppsModel::deleteLater); QObject::connect(model, &AppsModel::countChanged, [parentModel, this] { if (parentModel) { parentModel->entryChanged(this); } } ); QObject::connect(model, &AppsModel::hiddenEntriesChanged, [parentModel, this] { if (parentModel) { parentModel->entryChanged(this); } } ); } QIcon AppGroupEntry::icon() const { return m_icon; } QString AppGroupEntry::name() const { return m_name; } bool AppGroupEntry::hasChildren() const { return m_childModel && m_childModel->count() > 0; } AbstractModel *AppGroupEntry::childModel() const { return m_childModel; } diff --git a/appentry.h b/appentry.h index 3d0b1bdbf..4074519ea 100644 --- a/appentry.h +++ b/appentry.h @@ -1,95 +1,96 @@ /*************************************************************************** * Copyright (C) 201 by Eike Hein * * * * 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 . * ***************************************************************************/ #ifndef APPENTRY_H #define APPENTRY_H #include "abstractentry.h" #include #include class AppsModel; class MenuEntryEditor; class QQmlPropertyMap; class AppEntry : public AbstractEntry { public: enum NameFormat { NameOnly = 0, GenericNameOnly, NameAndGenericName, GenericNameAndName }; explicit AppEntry(AbstractModel *owner, KService::Ptr service, NameFormat nameFormat); explicit AppEntry(AbstractModel *owner, const QString &id); EntryType type() const { return RunnableType; } bool isValid() const; QIcon icon() const; QString name() const; + QString description() const; KService::Ptr service() const; QString id() const; QUrl url() const; bool hasActions() const; QVariantList actions() const; bool run(const QString& actionId = QString(), const QVariant &argument = QVariant()); static QString nameFromService(const KService::Ptr service, NameFormat nameFormat); static KService::Ptr defaultAppByName(const QString &name); private: void init(NameFormat nameFormat); QString m_id; QString m_name; QIcon m_icon; KService::Ptr m_service; static QObject *m_appletInterface; static QQmlPropertyMap *m_appletConfig; static MenuEntryEditor *m_menuEntryEditor; }; class AppGroupEntry : public AbstractGroupEntry { public: AppGroupEntry(AppsModel *parentModel, KServiceGroup::Ptr group, bool flat, bool separators, int appNameFormat); QIcon icon() const; QString name() const; bool hasChildren() const; AbstractModel *childModel() const; private: QString m_name; QIcon m_icon; QPointer m_childModel; }; #endif diff --git a/appsmodel.cpp b/appsmodel.cpp index 821ae88a2..b2c246518 100644 --- a/appsmodel.cpp +++ b/appsmodel.cpp @@ -1,512 +1,514 @@ /*************************************************************************** * Copyright (C) 2012 Aurélien Gâteau * * Copyright (C) 2013-2015 by Eike Hein * * * * 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 . * ***************************************************************************/ #include "appsmodel.h" #include "actionlist.h" #include #include #include #include #include AppsModel::AppsModel(const QString &entryPath, bool flat, bool separators, QObject *parent) : AbstractModel(parent) , m_deleteEntriesOnDestruction(true) , m_separatorCount(0) , m_showSeparators(separators) , m_description(i18n("Applications")) , m_entryPath(entryPath) , m_staticEntryList(false) , m_changeTimer(0) , m_flat(flat) , m_sortNeeded(false) , m_appNameFormat(AppEntry::NameOnly) { if (!m_entryPath.isEmpty()) { refresh(); } } AppsModel::AppsModel(const QList entryList, bool deleteEntriesOnDestruction, QObject *parent) : AbstractModel(parent) , m_deleteEntriesOnDestruction(deleteEntriesOnDestruction) , m_separatorCount(0) , m_showSeparators(false) , m_description(i18n("Applications")) , m_entryPath(QString()) , m_staticEntryList(true) , m_changeTimer(0) , m_flat(true) , m_sortNeeded(false) , m_appNameFormat(AppEntry::NameOnly) { foreach(AbstractEntry *suggestedEntry, entryList) { bool found = false; foreach (const AbstractEntry *entry, m_entryList) { if (entry->type() == AbstractEntry::RunnableType && static_cast(entry)->service()->storageId() == static_cast(suggestedEntry)->service()->storageId()) { found = true; } } if (!found) { m_entryList << suggestedEntry; } } sortEntries(); } AppsModel::~AppsModel() { if (m_deleteEntriesOnDestruction) { qDeleteAll(m_entryList); } } QString AppsModel::description() const { return m_description; } void AppsModel::setDescription(const QString &text) { if (m_description != text) { m_description = text; emit descriptionChanged(); } } QVariant AppsModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.row() >= m_entryList.count()) { return QVariant(); } const AbstractEntry *entry = m_entryList.at(index.row()); if (role == Qt::DisplayRole) { return entry->name(); } else if (role == Qt::DecorationRole) { return entry->icon(); + } else if (role == Kicker::DescriptionRole) { + return entry->description(); } else if (role == Kicker::FavoriteIdRole && entry->type() == AbstractEntry::RunnableType) { return entry->id(); } else if (role == Kicker::UrlRole && entry->type() == AbstractEntry::RunnableType) { return entry->url(); } else if (role == Kicker::IsParentRole) { return (entry->type() == AbstractEntry::GroupType); } else if (role == Kicker::IsSeparatorRole) { return (entry->type() == AbstractEntry::SeparatorType); } else if (role == Kicker::HasChildrenRole) { return entry->hasChildren(); } else if (role == Kicker::HasActionListRole) { const AppsModel *appsModel = qobject_cast(entry->childModel()); return entry->hasActions() || (appsModel && !appsModel->hiddenEntries().isEmpty()); } else if (role == Kicker::ActionListRole) { QVariantList actionList = entry->actions(); if (!m_hiddenEntries.isEmpty()) { actionList << Kicker::createSeparatorActionItem(); actionList << Kicker::createActionItem(i18n("Unhide Applications in this Submenu"), "unhideSiblingApplications"); } const AppsModel *appsModel = qobject_cast(entry->childModel()); if (appsModel && !appsModel->hiddenEntries().isEmpty()) { actionList << Kicker::createActionItem(i18n("Unhide Applications in '%1'", entry->name()), "unhideChildApplications"); } return actionList; } return QVariant(); } QModelIndex AppsModel::index(int row, int column, const QModelIndex &parent) const { return hasIndex(row, column, parent) ? createIndex(row, column, m_entryList.at(row)) : QModelIndex(); } int AppsModel::rowCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : m_entryList.count(); } bool AppsModel::trigger(int row, const QString &actionId, const QVariant &argument) { if (row < 0 || row >= m_entryList.count()) { return false; } AbstractEntry *entry = m_entryList.at(row); if (actionId == "hideApplication" && entry->type() == AbstractEntry::RunnableType) { QObject *appletInterface = rootModel()->property("appletInterface").value(); QQmlPropertyMap *appletConfig = qobject_cast(appletInterface->property("configuration").value()); if (appletConfig && appletConfig->contains("hiddenApplications")) { QStringList hiddenApps = appletConfig->value("hiddenApplications").toStringList(); KService::Ptr service = static_cast(entry)->service(); if (!hiddenApps.contains(service->menuId())) { hiddenApps << service->menuId(); appletConfig->insert("hiddenApplications", hiddenApps); QMetaObject::invokeMethod(appletConfig, "valueChanged", Qt::DirectConnection, Q_ARG(QString, "hiddenApplications"), Q_ARG(QVariant, hiddenApps)); refresh(); emit hiddenEntriesChanged(); } } return false; } else if (actionId == "unhideSiblingApplications") { QObject *appletInterface = rootModel()->property("appletInterface").value(); QQmlPropertyMap *appletConfig = qobject_cast(appletInterface->property("configuration").value()); if (appletConfig && appletConfig->contains("hiddenApplications")) { QStringList hiddenApps = appletConfig->value("hiddenApplications").toStringList(); foreach(const QString& app, m_hiddenEntries) { hiddenApps.removeOne(app); } appletConfig->insert("hiddenApplications", hiddenApps); QMetaObject::invokeMethod(appletConfig, "valueChanged", Qt::DirectConnection, Q_ARG(QString, "hiddenApplications"), Q_ARG(QVariant, hiddenApps)); m_hiddenEntries.clear(); refresh(); emit hiddenEntriesChanged(); } return false; } else if (actionId == "unhideChildApplications") { QObject *appletInterface = rootModel()->property("appletInterface").value(); QQmlPropertyMap *appletConfig = qobject_cast(appletInterface->property("configuration").value()); if (entry->type() == AbstractEntry::GroupType && appletConfig && appletConfig->contains("hiddenApplications")) { const AppsModel *appsModel = qobject_cast(entry->childModel()); if (!appsModel) { return false; } QStringList hiddenApps = appletConfig->value("hiddenApplications").toStringList(); foreach(const QString& app, appsModel->hiddenEntries()) { hiddenApps.removeOne(app); } appletConfig->insert("hiddenApplications", hiddenApps); QMetaObject::invokeMethod(appletConfig, "valueChanged", Qt::DirectConnection, Q_ARG(QString, "hiddenApplications"), Q_ARG(QVariant, hiddenApps)); refresh(); emit hiddenEntriesChanged(); } return false; } return entry->run(actionId, argument); } AbstractModel *AppsModel::modelForRow(int row) { if (row < 0 || row >= m_entryList.count()) { return 0; } return m_entryList.at(row)->childModel(); } int AppsModel::separatorCount() const { return m_separatorCount; } bool AppsModel::flat() const { return m_flat; } void AppsModel::setFlat(bool flat) { if (m_flat != flat) { m_flat = flat; refresh(); emit flatChanged(); } } bool AppsModel::showSeparators() const { return m_showSeparators; } void AppsModel::setShowSeparators(bool showSeparators) { if (m_showSeparators != showSeparators) { m_showSeparators = showSeparators; refresh(); emit showSeparatorsChanged(); } } int AppsModel::appNameFormat() const { return m_appNameFormat; } void AppsModel::setAppNameFormat(int format) { if (m_appNameFormat != (AppEntry::NameFormat)format) { m_appNameFormat = (AppEntry::NameFormat)format; refresh(); emit appNameFormatChanged(); } } QStringList AppsModel::hiddenEntries() const { return m_hiddenEntries; } void AppsModel::refresh() { if (m_staticEntryList) { return; } beginResetModel(); refreshInternal(); endResetModel(); emit countChanged(); emit separatorCountChanged(); } void AppsModel::refreshInternal() { if (m_staticEntryList) { return; } if (m_entryList.count()) { qDeleteAll(m_entryList); m_entryList.clear(); emit cleared(); } m_hiddenEntries.clear(); m_separatorCount = 0; m_sortNeeded = false; if (m_entryPath.isEmpty()) { KServiceGroup::Ptr group = KServiceGroup::root(); bool sortByGenericName = (appNameFormat() == AppEntry::GenericNameOnly || appNameFormat() == AppEntry::GenericNameAndName); KServiceGroup::List list = group->entries(true /* sorted */, true /* excludeNoDisplay */, true /* allowSeparators */, sortByGenericName /* sortByGenericName */); for (KServiceGroup::List::ConstIterator it = list.constBegin(); it != list.constEnd(); it++) { const KSycocaEntry::Ptr p = (*it); if (p->isType(KST_KServiceGroup)) { KServiceGroup::Ptr subGroup(static_cast(p.data())); if (!subGroup->noDisplay() && subGroup->childCount() > 0) { AppGroupEntry *groupEntry = new AppGroupEntry(this, subGroup, m_flat, m_showSeparators, m_appNameFormat); m_entryList << groupEntry; } } } m_changeTimer = new QTimer(this); m_changeTimer->setSingleShot(true); m_changeTimer->setInterval(100); connect(m_changeTimer, SIGNAL(timeout()), this, SLOT(refresh())); connect(KSycoca::self(), SIGNAL(databaseChanged(QStringList)), SLOT(checkSycocaChanges(QStringList))); } else { KServiceGroup::Ptr group = KServiceGroup::group(m_entryPath); processServiceGroup(group); if (m_entryList.count()) { while (m_entryList.last()->type() == AbstractEntry::SeparatorType) { m_entryList.removeLast(); --m_separatorCount; } } if (m_sortNeeded) { sortEntries(); } } } void AppsModel::processServiceGroup(KServiceGroup::Ptr group) { if (!group || !group->isValid()) { return; } bool hasSubGroups = false; foreach(KServiceGroup::Ptr subGroup, group->groupEntries(KServiceGroup::ExcludeNoDisplay)) { if (subGroup->childCount() > 0) { hasSubGroups = true; break; } } bool sortByGenericName = (appNameFormat() == AppEntry::GenericNameOnly || appNameFormat() == AppEntry::GenericNameAndName); KServiceGroup::List list = group->entries(true /* sorted */, true /* excludeNoDisplay */, (!m_flat || (m_flat && !hasSubGroups)) /* allowSeparators */, sortByGenericName /* sortByGenericName */); QStringList hiddenApps; QObject *appletInterface = rootModel()->property("appletInterface").value(); QQmlPropertyMap *appletConfig = qobject_cast(appletInterface->property("configuration").value()); if (appletConfig && appletConfig->contains("hiddenApplications")) { hiddenApps = appletConfig->value("hiddenApplications").toStringList(); } for (KServiceGroup::List::ConstIterator it = list.constBegin(); it != list.constEnd(); it++) { const KSycocaEntry::Ptr p = (*it); if (p->isType(KST_KService)) { const KService::Ptr service(static_cast(p.data())); if (service->noDisplay()) { continue; } if (hiddenApps.contains(service->menuId())) { m_hiddenEntries << service->menuId(); continue; } bool found = false; foreach (const AbstractEntry *entry, m_entryList) { if (entry->type() == AbstractEntry::RunnableType && static_cast(entry)->service()->storageId() == service->storageId()) { found = true; } } if (!found) { m_entryList << new AppEntry(this, service, m_appNameFormat); } } else if (p->isType(KST_KServiceSeparator) && m_showSeparators) { if (!m_entryList.count()) { continue; } if (m_entryList.last()->type() == AbstractEntry::SeparatorType) { continue; } m_entryList << new SeparatorEntry(this); ++m_separatorCount; } else if (p->isType(KST_KServiceGroup)) { const KServiceGroup::Ptr subGroup(static_cast(p.data())); if (subGroup->childCount() == 0) { continue; } if (m_flat) { m_sortNeeded = true; const KServiceGroup::Ptr serviceGroup(static_cast(p.data())); processServiceGroup(serviceGroup); } else { AppGroupEntry *groupEntry = new AppGroupEntry(this, subGroup, m_flat, m_showSeparators, m_appNameFormat); m_entryList << groupEntry; } } } } void AppsModel::sortEntries() { QCollator c; std::sort(m_entryList.begin(), m_entryList.end(), [&c](AbstractEntry* a, AbstractEntry* b) { if (a->type() != b->type()) { return a->type() > b->type(); } else { return c.compare(a->name(), b->name()) < 0; } }); } void AppsModel::checkSycocaChanges(const QStringList &changes) { if (changes.contains("services") || changes.contains("apps") || changes.contains("xdgdata-apps")) { m_changeTimer->start(); } } void AppsModel::entryChanged(AbstractEntry *entry) { int i = m_entryList.indexOf(entry); if (i != -1) { QModelIndex idx = index(i, 0); emit dataChanged(idx, idx); } } diff --git a/favoritesmodel.cpp b/favoritesmodel.cpp index 4931a1600..0ee6a5391 100644 --- a/favoritesmodel.cpp +++ b/favoritesmodel.cpp @@ -1,331 +1,333 @@ /*************************************************************************** * Copyright (C) 2014-2015 by Eike Hein * * * * 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 . * ***************************************************************************/ #include "favoritesmodel.h" #include "appentry.h" #include "contactentry.h" #include "fileentry.h" #include "systementry.h" #include "actionlist.h" #include FavoritesModel::FavoritesModel(QObject *parent) : AbstractModel(parent) , m_enabled(true) , m_maxFavorites(-1) , m_dropPlaceholderIndex(-1) { } FavoritesModel::~FavoritesModel() { qDeleteAll(m_entryList); } QString FavoritesModel::description() const { return i18n("Favorites"); } QVariant FavoritesModel::data(const QModelIndex& index, int role) const { if (!index.isValid() || index.row() >= rowCount()) { return QVariant(); } if (index.row() == m_dropPlaceholderIndex) { if (role == Kicker::IsDropPlaceholderRole) { return true; } else { return QVariant(); } } int mappedIndex = index.row(); if (m_dropPlaceholderIndex != -1 && mappedIndex > m_dropPlaceholderIndex) { --mappedIndex; } const AbstractEntry *entry = m_entryList.at(mappedIndex); if (role == Qt::DisplayRole) { return entry->name(); } else if (role == Qt::DecorationRole) { return entry->icon(); + } else if (role == Kicker::DescriptionRole) { + return entry->description(); } else if (role == Kicker::FavoriteIdRole) { return entry->id(); } else if (role == Kicker::UrlRole) { return entry->url(); } else if (role == Kicker::HasActionListRole) { return entry->hasActions(); } else if (role == Kicker::ActionListRole) { return entry->actions(); } return QVariant(); } int FavoritesModel::rowCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : m_entryList.count() + (m_dropPlaceholderIndex != -1 ? 1 : 0); } bool FavoritesModel::trigger(int row, const QString &actionId, const QVariant &argument) { if (row < 0 || row >= m_entryList.count()) { return false; } return m_entryList.at(row)->run(actionId, argument); } bool FavoritesModel::enabled() const { return m_enabled; } void FavoritesModel::setEnabled(bool enable) { if (m_enabled != enable) { m_enabled = enable; emit enabledChanged(); } } QStringList FavoritesModel::favorites() const { return m_favorites; } void FavoritesModel::setFavorites(const QStringList& favorites) { QStringList _favorites(favorites); _favorites.removeDuplicates(); if (_favorites != m_favorites) { m_favorites = _favorites; refresh(); } } int FavoritesModel::maxFavorites() const { return m_maxFavorites; } void FavoritesModel::setMaxFavorites(int max) { if (m_maxFavorites != max) { m_maxFavorites = max; if (m_maxFavorites != -1 && m_favorites.count() > m_maxFavorites) { refresh(); } emit maxFavoritesChanged(); } } bool FavoritesModel::isFavorite(const QString &id) const { return m_favorites.contains(id); } void FavoritesModel::addFavorite(const QString &id, int index) { if (!m_enabled || id.isEmpty()) { return; } if (m_maxFavorites != -1 && m_favorites.count() == m_maxFavorites) { return; } AbstractEntry *entry = favoriteFromId(id); if (!entry || !entry->isValid()) { delete entry; return; } setDropPlaceholderIndex(-1); int insertIndex = (index != -1) ? index : m_entryList.count(); beginInsertRows(QModelIndex(), insertIndex, insertIndex); m_entryList.insert(insertIndex, entry); m_favorites.insert(insertIndex, entry->id()); endInsertRows(); emit countChanged(); emit favoritesChanged(); } void FavoritesModel::removeFavorite(const QString &id) { if (!m_enabled || id.isEmpty()) { return; } int index = m_favorites.indexOf(id); if (index != -1) { setDropPlaceholderIndex(-1); beginRemoveRows(QModelIndex(), index, index); delete m_entryList[index]; m_entryList.removeAt(index); m_favorites.removeAt(index); endRemoveRows(); emit countChanged(); emit favoritesChanged(); } } void FavoritesModel::moveRow(int from, int to) { if (from >= m_favorites.count() || to >= m_favorites.count()) { return; } if (from == to) { return; } setDropPlaceholderIndex(-1); int modelTo = to + (to > from ? 1 : 0); bool ok = beginMoveRows(QModelIndex(), from, from, QModelIndex(), modelTo); if (ok) { m_entryList.move(from, to); m_favorites.move(from, to); endMoveRows(); emit favoritesChanged(); } } int FavoritesModel::dropPlaceholderIndex() const { return m_dropPlaceholderIndex; } void FavoritesModel::setDropPlaceholderIndex(int index) { if (index == -1 && m_dropPlaceholderIndex != -1) { beginRemoveRows(QModelIndex(), m_dropPlaceholderIndex, m_dropPlaceholderIndex); m_dropPlaceholderIndex = index; endRemoveRows(); emit countChanged(); } else if (index != -1 && m_dropPlaceholderIndex == -1) { beginInsertRows(QModelIndex(), index, index); m_dropPlaceholderIndex = index; endInsertRows(); emit countChanged(); } else if (m_dropPlaceholderIndex != index) { int modelTo = index + (index > m_dropPlaceholderIndex ? 1 : 0); bool ok = beginMoveRows(QModelIndex(), m_dropPlaceholderIndex, m_dropPlaceholderIndex, QModelIndex(), modelTo); if (ok) { m_dropPlaceholderIndex = index; endMoveRows(); } } } AbstractModel *FavoritesModel::favoritesModel() { return this; } void FavoritesModel::refresh() { beginResetModel(); setDropPlaceholderIndex(-1); int oldCount = m_entryList.count(); qDeleteAll(m_entryList); m_entryList.clear(); QStringList newFavorites; foreach(const QString &id, m_favorites) { AbstractEntry *entry = favoriteFromId(id); if (entry && entry->isValid()) { m_entryList << entry; newFavorites << entry->id(); if (m_maxFavorites != -1 && newFavorites.count() == m_maxFavorites) { break; } } else if (entry) { delete entry; } } m_favorites = newFavorites; endResetModel(); if (oldCount != m_entryList.count()) { emit countChanged(); } emit favoritesChanged(); } AbstractEntry *FavoritesModel::favoriteFromId(const QString &id) { const QUrl url(id); const QString &s = url.scheme(); if ((s.isEmpty() && id.contains(QStringLiteral(".desktop"))) || s == QStringLiteral("preferred")) { return new AppEntry(this, id); } else if (s == QStringLiteral("ktp")) { return new ContactEntry(this, id); } else if (url.isValid() && !url.scheme().isEmpty()) { return new FileEntry(this, url); } else { return new SystemEntry(this, id); } return nullptr; } diff --git a/fileentry.cpp b/fileentry.cpp index 693816d15..d76a9b59a 100644 --- a/fileentry.cpp +++ b/fileentry.cpp @@ -1,109 +1,118 @@ /*************************************************************************** * Copyright (C) 201 by Eike Hein * * * * 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 . * ***************************************************************************/ #include "fileentry.h" #include "actionlist.h" #include #include FileEntry::FileEntry(AbstractModel *owner, const QUrl &url) : AbstractEntry(owner) , m_fileItem(nullptr) { if (url.isValid()) { m_fileItem = new KFileItem(url); m_fileItem->determineMimeType(); } } bool FileEntry::isValid() const { return m_fileItem && m_fileItem->isFile(); } QIcon FileEntry::icon() const { if (m_fileItem) { return QIcon::fromTheme(m_fileItem->iconName(), QIcon::fromTheme("unknown")); } return QIcon::fromTheme("unknown"); } QString FileEntry::name() const { if (m_fileItem) { return m_fileItem->url().fileName(); } return QString(); } +QString FileEntry::description() const +{ + if (m_fileItem) { + return m_fileItem->url().toString(); + } + + return QString(); +} + QString FileEntry::id() const { if (m_fileItem) { return m_fileItem->url().toString(); } return QString(); } QUrl FileEntry::url() const { if (m_fileItem) { return m_fileItem->url(); } return QUrl(); } bool FileEntry::hasActions() const { return m_fileItem && m_fileItem->isFile(); } QVariantList FileEntry::actions() const { if (m_fileItem) { return Kicker::createActionListForFileItem(*m_fileItem); } return QVariantList(); } bool FileEntry::run(const QString& actionId, const QVariant &argument) { if (!m_fileItem) { return false; } if (actionId.isEmpty()) { new KRun(m_fileItem->url(), 0); return true; } else { bool close = false; if (Kicker::handleFileItemAction(*m_fileItem, actionId, argument, &close)) { return close; } } return false; } diff --git a/fileentry.h b/fileentry.h index cd4e54a12..4c67e794d 100644 --- a/fileentry.h +++ b/fileentry.h @@ -1,51 +1,52 @@ /*************************************************************************** * Copyright (C) 201 by Eike Hein * * * * 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 . * ***************************************************************************/ #ifndef FILEENTRY_H #define FILEENTRY_H #include "abstractentry.h" class KFileItem; class FileEntry : public AbstractEntry { public: explicit FileEntry(AbstractModel *owner, const QUrl &url); EntryType type() const { return RunnableType; } bool isValid() const; QIcon icon() const; QString name() const; + QString description() const; QString id() const; QUrl url() const; bool hasActions() const; QVariantList actions() const; bool run(const QString& actionId = QString(), const QVariant &argument = QVariant()); private: KFileItem *m_fileItem; }; #endif diff --git a/runnermatchesmodel.cpp b/runnermatchesmodel.cpp index d375fd728..6f625a5cc 100644 --- a/runnermatchesmodel.cpp +++ b/runnermatchesmodel.cpp @@ -1,175 +1,177 @@ /*************************************************************************** * Copyright (C) 2012 by Aurélien Gâteau * * Copyright (C) 2014-2015 by Eike Hein * * * * 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 . * ***************************************************************************/ #include "runnermatchesmodel.h" #include "runnermodel.h" #include "actionlist.h" #include #include #include #include RunnerMatchesModel::RunnerMatchesModel(const QString &runnerId, const QString &name, Plasma::RunnerManager *manager, QObject *parent) : AbstractModel(parent) , m_runnerId(runnerId) , m_name(name) , m_runnerManager(manager) { } QString RunnerMatchesModel::description() const { return m_name; } QVariant RunnerMatchesModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.row() >= m_matches.count()) { return QVariant(); } Plasma::QueryMatch match = m_matches.at(index.row()); if (role == Qt::DisplayRole) { return match.text(); } else if (role == Qt::DecorationRole) { return match.icon(); + } else if (role == Kicker::DescriptionRole) { + return match.subtext(); } else if (role == Kicker::FavoriteIdRole) { if (m_runnerId == "services") { return match.data().toString(); } } else if (role == Kicker::HasActionListRole) { // Hack to expose the protected Plasma::AbstractRunner::actions() method. class MyRunner : public Plasma::AbstractRunner { public: using Plasma::AbstractRunner::actions;; }; MyRunner *runner = static_cast(match.runner()); Q_ASSERT(runner); return !runner->actions().isEmpty(); } else if (role == Kicker::ActionListRole) { QVariantList actionList; foreach (QAction *action, m_runnerManager->actionsForMatch(match)) { QVariantMap item = Kicker::createActionItem(action->text(), "runnerAction", QVariant::fromValue(action)); item["icon"] = action->icon(); actionList << item; } return actionList; } return QVariant(); } int RunnerMatchesModel::rowCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : m_matches.count(); } bool RunnerMatchesModel::trigger(int row, const QString &actionId, const QVariant &argument) { if (row < 0 || row >= m_matches.count()) { return false; } Plasma::QueryMatch match = m_matches.at(row); if (!match.isEnabled()) { return false; } if (!actionId.isEmpty()) { QObject *obj = argument.value(); if (!obj) { return false; } QAction *action = qobject_cast(obj); if (!action) { return false; } match.setSelectedAction(action); } m_runnerManager->run(match); return true; } void RunnerMatchesModel::setMatches(const QList< Plasma::QueryMatch > &matches) { int oldCount = m_matches.count(); int newCount = matches.count(); bool emitCountChange = (oldCount != newCount); int ceiling = qMin(oldCount, newCount); bool emitDataChange = false; for (int row = 0; row < ceiling; ++row) { if (!(m_matches.at(row) == matches.at(row))) { emitDataChange = true; break; } } if (newCount > oldCount) { beginInsertRows(QModelIndex(), oldCount, newCount - 1); m_matches = matches; endInsertRows(); } else if (newCount < oldCount) { beginRemoveRows(QModelIndex(), newCount, oldCount - 1); m_matches = matches; endRemoveRows(); } if (emitDataChange) { m_matches = matches; emit dataChanged(index(0, 0), index(ceiling - 1, 0)); } if (emitCountChange) { emit countChanged(); } } AbstractModel *RunnerMatchesModel::favoritesModel() { return static_cast(parent())->favoritesModel(); } diff --git a/systementry.cpp b/systementry.cpp index ec527dad6..30d9cb93d 100644 --- a/systementry.cpp +++ b/systementry.cpp @@ -1,286 +1,320 @@ /*************************************************************************** * Copyright (C) 2015 by Eike Hein * * * * 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 . * ***************************************************************************/ #include "systementry.h" #include #include #include #include #include #include #include #include #include #include "ksmserver_interface.h" #include KDisplayManager *SystemEntry::m_displayManager = new KDisplayManager(); SystemEntry::SystemEntry(AbstractModel *owner, Action action) : AbstractEntry(owner) , m_action(action) , m_valid(false) { init(); } SystemEntry::SystemEntry(AbstractModel *owner, const QString &id) : AbstractEntry(owner) , m_action(NoAction) , m_valid(false) { if (id == QStringLiteral("lock-screen")) { m_action = LockSession; } else if (id == QStringLiteral("logout")) { m_action = LogoutSession; } else if (id == QStringLiteral("save-session")) { m_action = SaveSession; } else if (id == QStringLiteral("switch-user")) { m_action = NewSession; } else if (id == QStringLiteral("suspend")) { m_action = SuspendToRam; } else if (id == QStringLiteral("hibernate")) { m_action = SuspendToDisk; } else if (id == QStringLiteral("reboot")) { m_action = Reboot; } else if (id == QStringLiteral("shutdown")) { m_action = Shutdown; } init(); } void SystemEntry::init() { switch (m_action) { case NoAction: m_valid = false; break; case LockSession: m_valid = KAuthorized::authorizeKAction("lock_screen"); break; case LogoutSession: case SaveSession: { bool authorize = KAuthorized::authorizeKAction("logout") && KAuthorized::authorize("logout"); if (m_action == SaveSession) { const KConfigGroup c(KSharedConfig::openConfig("ksmserverrc", KConfig::NoGlobals), "General"); m_valid = authorize && c.readEntry("loginMode") == "restoreSavedSession"; } else { m_valid = authorize; } break; } case NewSession: m_valid = KAuthorized::authorizeKAction("start_new_session") && m_displayManager->isSwitchable() && m_displayManager->numReserve() >= 0; break; case SuspendToRam: m_valid = Solid::PowerManagement::supportedSleepStates().contains(Solid::PowerManagement::SuspendState); break; case SuspendToDisk: m_valid = Solid::PowerManagement::supportedSleepStates().contains(Solid::PowerManagement::HibernateState); break; case Reboot: m_valid = KWorkSpace::canShutDown(KWorkSpace::ShutdownConfirmDefault, KWorkSpace::ShutdownTypeReboot); break; case Shutdown: m_valid = KWorkSpace::canShutDown(KWorkSpace::ShutdownConfirmDefault, KWorkSpace::ShutdownTypeHalt); break; default: m_valid = true; } } bool SystemEntry::isValid() const { return m_valid; } QIcon SystemEntry::icon() const { const QString &name = iconName(); if (!name.isEmpty()) { return QIcon::fromTheme(name, QIcon::fromTheme("unknown")); } return QIcon::fromTheme("unknown"); } QString SystemEntry::iconName() const { switch (m_action) { case LockSession: return "system-lock-screen"; break; case LogoutSession: return "system-log-out"; break; case SaveSession: return "system-save-session"; break; case NewSession: return "system-switch-user"; break; case SuspendToRam: return "system-suspend"; break; case SuspendToDisk: return "system-suspend-hibernate"; break; case Reboot: return "system-reboot"; break; case Shutdown: return "system-shutdown"; break; default: break; } return QString(); } QString SystemEntry::name() const { switch (m_action) { case LockSession: return i18n("Lock"); break; case LogoutSession: return i18n("Logout"); break; case SaveSession: return i18n("Save Session"); break; case NewSession: return i18n("New Session"); break; case SuspendToRam: return i18n("Suspend"); break; case SuspendToDisk: return i18n("Hibernate"); break; case Reboot: return i18n("Restart"); break; case Shutdown: return i18n("Shutdown"); break; default: break; } return QString(); } +QString SystemEntry::description() const +{ + switch (m_action) { + case LockSession: + return i18n("Lock screen"); + break; + case LogoutSession: + return i18n("End session"); + break; + case SaveSession: + return i18n("Save Session"); + break; + case NewSession: + return i18n("Start a parallel session as a different user"); + break; + case SuspendToRam: + return i18n("Suspend to RAM"); + break; + case SuspendToDisk: + return i18n("Suspend to disk"); + break; + case Reboot: + return i18n("Restart computer"); + break; + case Shutdown: + return i18n("Turn off computer"); + break; + default: + break; + } + + return QString(); +} + QString SystemEntry::id() const { switch (m_action) { case LockSession: return QStringLiteral("lock-screen"); break; case LogoutSession: return QStringLiteral("logout"); break; case SaveSession: return QStringLiteral("save-session"); break; case NewSession: return QStringLiteral("switch-user"); break; case SuspendToRam: return QStringLiteral("suspend"); break; case SuspendToDisk: return QStringLiteral("hibernate"); break; case Reboot: return QStringLiteral("reboot"); break; case Shutdown: return QStringLiteral("shutdown"); break; default: break; } return QString(); } bool SystemEntry::run(const QString& actionId, const QVariant &argument) { Q_UNUSED(actionId) Q_UNUSED(argument) switch (m_action) { case LockSession: { QDBusConnection bus = QDBusConnection::sessionBus(); QDBusInterface interface("org.freedesktop.ScreenSaver", "/ScreenSaver", "org.freedesktop.ScreenSaver", bus); interface.asyncCall("Lock"); break; } case LogoutSession: KWorkSpace::requestShutDown(KWorkSpace::ShutdownConfirmDefault, KWorkSpace::ShutdownTypeNone); break; case SaveSession: { org::kde::KSMServerInterface ksmserver(QStringLiteral("org.kde.ksmserver"), QStringLiteral("/KSMServer"), QDBusConnection::sessionBus()); if (ksmserver.isValid()) { ksmserver.saveCurrentSession(); } break; } case NewSession: { QDBusConnection bus = QDBusConnection::sessionBus(); QDBusInterface interface("org.freedesktop.ScreenSaver", "/ScreenSaver", "org.freedesktop.ScreenSaver", bus); interface.asyncCall("Lock"); m_displayManager->startReserve(); break; }; case SuspendToRam: Solid::PowerManagement::requestSleep(Solid::PowerManagement::SuspendState, 0, 0); break; case SuspendToDisk: Solid::PowerManagement::requestSleep(Solid::PowerManagement::HibernateState, 0, 0); break; case Reboot: KWorkSpace::requestShutDown(KWorkSpace::ShutdownConfirmDefault, KWorkSpace::ShutdownTypeReboot); break; case Shutdown: KWorkSpace::requestShutDown(KWorkSpace::ShutdownConfirmDefault, KWorkSpace::ShutdownTypeHalt); break; default: return false; } return true; } diff --git a/systementry.h b/systementry.h index df0712bcd..245d45661 100644 --- a/systementry.h +++ b/systementry.h @@ -1,67 +1,68 @@ /*************************************************************************** * Copyright (C) 2015 by Eike Hein * * * * 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 . * ***************************************************************************/ #ifndef SYSTEMENTRY_H #define SYSTEMENTRY_H #include "abstractentry.h" class KDisplayManager; class SystemEntry : public AbstractEntry { public: enum Action { NoAction = 0, LockSession, LogoutSession, SaveSession, NewSession, SuspendToRam, SuspendToDisk, Reboot, Shutdown }; explicit SystemEntry(AbstractModel *owner, Action action); explicit SystemEntry(AbstractModel *owner, const QString &id); EntryType type() const { return RunnableType; } bool isValid() const; QIcon icon() const; QString iconName() const; QString name() const; + QString description() const; QString id() const; bool run(const QString& actionId = QString(), const QVariant &argument = QVariant()); private: void init(); Action m_action; bool m_valid; static KDisplayManager *m_displayManager; }; #endif