Commit ee707886 authored by Eike Hein's avatar Eike Hein

Support edit and appstream actions also for application search results

Summary: BUG:384036

Reviewers: #plasma, broulik, davidedmundson

Reviewed By: #plasma, broulik

Subscribers: mak, plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D7567
parent 3a5369e8
......@@ -19,12 +19,17 @@
***************************************************************************/
#include "actionlist.h"
#include "menuentryeditor.h"
#include <config-appstream.h>
#include <QApplication>
#include <QDesktopServices>
#include <KLocalizedString>
#include <KMimeTypeTrader>
#include <KPropertiesDialog>
#include <KProtocolInfo>
#include <KRun>
#include <KActivities/Stats/Cleaning>
......@@ -33,6 +38,10 @@
#include "containmentinterface.h"
#ifdef HAVE_APPSTREAMQT
#include <AppStreamQt/pool.h>
#endif
namespace KAStats = KActivities::Stats;
using namespace KAStats;
......@@ -308,4 +317,89 @@ bool handleRecentDocumentAction(KService::Ptr service, const QString &actionId,
return (KRun::runService(*service, QList<QUrl>() << QUrl(argument), QApplication::activeWindow()) != 0);
}
Q_GLOBAL_STATIC(MenuEntryEditor, menuEntryEditor)
bool canEditApplication(const QString &entryPath)
{
return menuEntryEditor->canEdit(entryPath);
}
void editApplication(const QString &entryPath, const QString &menuId)
{
menuEntryEditor->edit(entryPath, menuId);
}
QVariantList editApplicationAction(const KService::Ptr &service)
{
QVariantList actionList;
if (canEditApplication(service->entryPath())) {
QVariantMap editAction = Kicker::createActionItem(i18n("Edit Application..."), "editApplication");
editAction["icon"] = "kmenuedit"; // TODO: Using the KMenuEdit icon might be misleading.
actionList << editAction;
}
return actionList;
}
bool handleEditApplicationAction(const QString &actionId, const KService::Ptr &service)
{
if (service && actionId == "editApplication" && canEditApplication(service->entryPath())) {
Kicker::editApplication(service->entryPath(), service->menuId());
return true;
}
return false;
}
#ifdef HAVE_APPSTREAMQT
Q_GLOBAL_STATIC(AppStream::Pool, appstreamPool)
#endif
QVariantList appstreamActions(const KService::Ptr &service)
{
QVariantList ret;
#ifdef HAVE_APPSTREAMQT
const KService::Ptr appStreamHandler = KMimeTypeTrader::self()->preferredService(QStringLiteral("x-scheme-handler/appstream"));
// Don't show action if we can't find any app to handle appstream:// URLs.
if (!appStreamHandler) {
if (!KProtocolInfo::isHelperProtocol(QStringLiteral("appstream"))
|| KProtocolInfo::exec(QStringLiteral("appstream")).isEmpty()) {
return ret;
}
}
if (!appstreamPool.exists()) {
appstreamPool->load();
}
const auto components = appstreamPool->componentsById(service->desktopEntryName()+QLatin1String(".desktop"));
for(const auto &component: components) {
const QString componentId = component.id();
QVariantMap appstreamAction = Kicker::createActionItem(i18nc("@action opens a software center with the application", "Manage '%1'...", component.name()), "manageApplication", QVariant(QStringLiteral("appstream://") + componentId));
appstreamAction[QStringLiteral("icon")] = QStringLiteral("applications-other");
ret << appstreamAction;
}
#else
Q_UNUSED(service)
#endif
return ret;
}
bool handleAppstreamActions(const QString &actionId, const QVariant &argument)
{
if (actionId == "manageApplication") {
return QDesktopServices::openUrl(QUrl(argument.toString()));
}
return false;
}
}
......@@ -57,4 +57,12 @@ QVariantList jumpListActions(KService::Ptr service);
QVariantList recentDocumentActions(KService::Ptr service);
bool handleRecentDocumentAction(KService::Ptr service, const QString &actionId, const QVariant &argument);
bool canEditApplication(const QString &entryPath);
void editApplication(const QString &entryPath, const QString &menuId);
QVariantList editApplicationAction(const KService::Ptr &service);
bool handleEditApplicationAction(const QString &actionId, const KService::Ptr &service);
QVariantList appstreamActions(const KService::Ptr &service);
bool handleAppstreamActions(const QString &actionId, const QVariant &argument);
}
......@@ -22,15 +22,12 @@
#include "actionlist.h"
#include "appsmodel.h"
#include "containmentinterface.h"
#include "menuentryeditor.h"
#include <config-X11.h>
#include <config-appstream.h>
#include <QProcess>
#include <QQmlPropertyMap>
#include <QStandardPaths>
#include <QDesktopServices>
#if HAVE_X11
#include <QX11Info>
#endif
......@@ -40,7 +37,6 @@
#include <KJob>
#include <KLocalizedString>
#include <KMimeTypeTrader>
#include <KProtocolInfo>
#include <KRun>
#include <KSycoca>
#include <KShell>
......@@ -49,12 +45,6 @@
#include <Plasma/Plasma>
#ifdef HAVE_APPSTREAMQT
#include <AppStreamQt/pool.h>
#endif
MenuEntryEditor *AppEntry::m_menuEntryEditor = nullptr;
AppEntry::AppEntry(AbstractModel *owner, KService::Ptr service, NameFormat nameFormat)
: AbstractEntry(owner)
, m_service(service)
......@@ -89,10 +79,6 @@ void AppEntry::init(NameFormat nameFormat)
} else {
m_description = nameFromService(m_service, GenericNameOnly);
}
if (!m_menuEntryEditor) {
m_menuEntryEditor = new MenuEntryEditor();
}
}
bool AppEntry::isValid() const
......@@ -142,39 +128,6 @@ bool AppEntry::hasActions() const
return true;
}
#ifdef HAVE_APPSTREAMQT
Q_GLOBAL_STATIC(AppStream::Pool, appstreamPool)
QVariantList appstreamActions(const KService::Ptr &service)
{
QVariantList ret;
const KService::Ptr appStreamHandler = KMimeTypeTrader::self()->preferredService(QStringLiteral("x-scheme-handler/appstream"));
// Don't show action if we can't find any app to handle appstream:// URLs.
if (!appStreamHandler) {
if (!KProtocolInfo::isHelperProtocol(QStringLiteral("appstream"))
|| KProtocolInfo::exec(QStringLiteral("appstream")).isEmpty()) {
return ret;
}
}
if (!appstreamPool.exists()) {
appstreamPool->load();
}
const auto components = appstreamPool->componentsById(service->desktopEntryName()+QLatin1String(".desktop"));
for(const auto &component: components) {
const QString componentId = component.id();
QVariantMap appstreamAction = Kicker::createActionItem(i18nc("@action opens a software center with the application", "Manage '%1'...", component.name()), "manageApplication", QVariant(QStringLiteral("appstream://") + componentId));
appstreamAction[QStringLiteral("icon")] = QStringLiteral("applications-other");
ret << appstreamAction;
}
return ret;
}
#endif
QVariantList AppEntry::actions() const
{
QVariantList actionList;
......@@ -205,19 +158,11 @@ QVariantList AppEntry::actions() const
return actionList;
}
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 HAVE_APPSTREAMQT
if (m_service->isApplication()) {
actionList << appstreamActions(m_service);
actionList << Kicker::createSeparatorActionItem();
actionList << Kicker::editApplicationAction(m_service);
actionList << Kicker::appstreamActions(m_service);
}
#endif
QQmlPropertyMap *appletConfig = qobject_cast<QQmlPropertyMap *>(appletInterface->property("configuration").value<QObject *>());
......@@ -260,12 +205,10 @@ bool AppEntry::run(const QString& actionId, const QVariant &argument)
if (Kicker::handleAddLauncherAction(actionId, appletInterface, m_service)) {
return true;
} else if (actionId == "editApplication" && m_menuEntryEditor->canEdit(m_service->entryPath())) {
m_menuEntryEditor->edit(m_service->entryPath(), m_service->menuId());
} else if (Kicker::handleEditApplicationAction(actionId, m_service)) {
return true;
} else if (Kicker::handleAppstreamActions(actionId, argument)) {
return true;
} else if (actionId == "manageApplication") {
return QDesktopServices::openUrl(QUrl(argument.toString()));
} else if (actionId == "_kicker_jumpListAction") {
return KRun::run(argument.toString(), {}, nullptr, m_service->name(), m_service->icon());
}
......
......@@ -29,6 +29,8 @@
#include <KRunner/RunnerManager>
#include <KRun>
#include <Plasma/Plasma>
RunnerMatchesModel::RunnerMatchesModel(const QString &runnerId, const QString &name,
Plasma::RunnerManager *manager, QObject *parent)
: AbstractModel(parent)
......@@ -104,7 +106,8 @@ QVariant RunnerMatchesModel::data(const QModelIndex &index, int role) const
actionList << Kicker::createSeparatorActionItem();
}
KService::Ptr service = KService::serviceByStorageId(match.data().toString());
const KService::Ptr service = KService::serviceByStorageId(match.data().toString());
if (service) {
const QVariantList &jumpListActions = Kicker::jumpListActions(service);
if (!jumpListActions.isEmpty()) {
......@@ -113,8 +116,10 @@ QVariant RunnerMatchesModel::data(const QModelIndex &index, int role) const
QObject *appletInterface = static_cast<RunnerModel *>(parent())->appletInterface();
const bool systemImmutable = appletInterface->property("immutability").toInt() == Plasma::Types::SystemImmutable;
const QVariantList &addLauncherActions = Kicker::createAddLauncherActionList(appletInterface, service);
if (!addLauncherActions.isEmpty()) {
if (!systemImmutable && !addLauncherActions.isEmpty()) {
actionList << addLauncherActions << Kicker::createSeparatorActionItem();
}
......@@ -122,6 +127,17 @@ QVariant RunnerMatchesModel::data(const QModelIndex &index, int role) const
if (!recentDocuments.isEmpty()) {
actionList << recentDocuments << Kicker::createSeparatorActionItem();
}
// Don't allow adding launchers, editing, hiding, or uninstalling applications
// when system is immutable.
if (systemImmutable) {
return actionList;
}
if (service->isApplication()) {
actionList << Kicker::editApplicationAction(service);
actionList << Kicker::appstreamActions(service);
}
}
return actionList;
......@@ -149,10 +165,14 @@ bool RunnerMatchesModel::trigger(int row, const QString &actionId, const QVarian
QObject *appletInterface = static_cast<RunnerModel *>(parent())->appletInterface();
KService::Ptr service = KService::serviceByStorageId(match.data().toString());
const KService::Ptr service = KService::serviceByStorageId(match.data().toString());
if (Kicker::handleAddLauncherAction(actionId, appletInterface, service)) {
return true;
} else if (Kicker::handleEditApplicationAction(actionId, service)) {
return true;
} else if (Kicker::handleAppstreamActions(actionId, argument)) {
return true;
} else if (actionId == QLatin1String("_kicker_jumpListAction")) {
return KRun::run(argument.toString(), {}, nullptr, service ? service->name() : QString(), service ? service->icon() : QString());
} else if (actionId == QLatin1String("_kicker_recentDocument")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment