[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [plasma-workspace] libtaskmanager: Avoid absolute paths to .desktop files in launcher URLs.
From:       Eike Hein <null () kde ! org>
Date:       2017-08-29 22:46:28
Message-ID: E1dmpHA-0002bZ-Kn () code ! kde ! org
[Download RAW message or body]

Git commit a47d1f19e1e0bda300ff799dfc6f377802a2a678 by Eike Hein.
Committed on 29/08/2017 at 22:46.
Pushed by hein into branch 'master'.

Avoid absolute paths to .desktop files in launcher URLs.

Summary:
In any place we look up a KService, check if it has a menuId,
and then generate KAStats-style applications: URL with it. Also
learn how to handle applications: URLs.

This was requested by Kai in D7203. His patch makes Kate
dynamically add its sessions as jump list actions to a copy of its
.desktop file in $HOME. As the library would generate the absolute
path to a .desktop file e.g. in /usr as launcher URL before, the
TM applet would ignore the overriding copy in $HOME and the actions
wouldn't be found.

This patch won't rewrite existing config, but LauncherTasksModel
will resolve the absolute path to the applications: URL as it goes
through TaskTools, and then return that. The window and startup
tasks models produce those URLs, too, so things match up. Newly-
added launchers will then store the applications: URL in config
directly.

Moving away from storing absolute paths when we can is also nice
in case there is a $HOME .desktop file at the time a launcher is
added which later gets deleted. Using the new storage format, we
will now fall back to a system file instead.

Note the conservative approach taken: We only generate an
applications: URL when the service returns something for menuId().
We don't use KService::storageId() here, which can fall back to
KService::entryPath() - in this case we're better off just using
the absolute path we already have. We still use storageId() when
generating the applications: URL for KAStats db insertions, as
that is more liberal (and matches Kicker).

It makes sense to look at the Kicker backend code to see if should
store applications: URLs (which it already produces to insert into
KAStats) as well.

This will need a subsequent patch to the Task Manager applet to
handle applications: URLs there in code that consumes launcher URLs
to parse things out of .desktop files.

Contains other minor cleanup and fixes, such as porting the
LauncherTasksModel to use TaskTools::runApp (which now understands
preferred: URLs as well), a fix for a small logic error there (the
&& before the !isApplication should have been ||, now moot), and
not needlessly opening and parsing a .desktop file in
TaskTools::appDataFromUrl.

Subscribers: plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D7561

M  +1    -35   libtaskmanager/launchertasksmodel.cpp
M  +8    -0    libtaskmanager/startuptasksmodel.cpp
M  +70   -17   libtaskmanager/tasktools.cpp
M  +8    -0    libtaskmanager/xwindowtasksmodel.cpp

https://commits.kde.org/plasma-workspace/a47d1f19e1e0bda300ff799dfc6f377802a2a678

diff --git a/libtaskmanager/launchertasksmodel.cpp \
b/libtaskmanager/launchertasksmodel.cpp index ea2a0451..bc4ae726 100644
--- a/libtaskmanager/launchertasksmodel.cpp
+++ b/libtaskmanager/launchertasksmodel.cpp
@@ -544,41 +544,7 @@ void LauncherTasksModel::requestNewInstance(const QModelIndex \
&index)  return;
     }
 
-    const QUrl &url = d->launchersOrder.at(index.row());
-
-    quint32 timeStamp = 0;
-
-#if HAVE_X11
-        if (KWindowSystem::isPlatformX11()) {
-            timeStamp = QX11Info::appUserTime();
-        }
-#endif
-
-    if (url.scheme() == QLatin1String("preferred")) {
-        const KService::Ptr service = \
                KService::serviceByStorageId(defaultApplication(url));
-
-        if (!service && !service->isApplication()) {
-            return;
-        }
-
-        KRun::runApplication(*service, QList<QUrl>(), nullptr, 0, {},
-            KStartupInfo::createNewStartupIdForTimestamp(timeStamp));
-
-        KActivities::ResourceInstance::notifyAccessed(QUrl(QStringLiteral("applications:") \
                + service->storageId()),
-            QStringLiteral("org.kde.libtaskmanager"));
-    } else {
-        const KService::Ptr service = \
                KService::serviceByDesktopPath(url.toLocalFile());
-
-        if (service && service->isApplication()) {
-            KRun::runApplication(*service, QList<QUrl>(), nullptr, 0, {},
-                KStartupInfo::createNewStartupIdForTimestamp(timeStamp));
-
-            KActivities::ResourceInstance::notifyAccessed(QUrl(QStringLiteral("applications:") \
                + service->storageId()),
-                QStringLiteral("org.kde.libtaskmanager"));
-        } else {
-            new KRun(url, 0, false, \
                KStartupInfo::createNewStartupIdForTimestamp(timeStamp));
-        }
-    }
+    runApp(d->appData(d->launchersOrder.at(index.row())));
 }
 
 void LauncherTasksModel::requestOpenUrls(const QModelIndex &index, const QList<QUrl> \
                &urls)
diff --git a/libtaskmanager/startuptasksmodel.cpp \
b/libtaskmanager/startuptasksmodel.cpp index 2847ffe9..13977b35 100644
--- a/libtaskmanager/startuptasksmodel.cpp
+++ b/libtaskmanager/startuptasksmodel.cpp
@@ -193,6 +193,14 @@ QUrl StartupTasksModel::Private::launcherUrl(const \
KStartupInfoData &data)  }
 
     if (!services.empty()) {
+        const QString &menuId = services.at(0)->menuId();
+
+        // applications: URLs are used to refer to applications by their \
KService::menuId +        // (i.e. .desktop file name) rather than the absolute path \
to a .desktop file. +        if (!menuId.isEmpty()) {
+            return QUrl(QStringLiteral("applications:") + menuId);
+        }
+
         QString path = services.at(0)->entryPath();
 
         if (path.isEmpty()) {
diff --git a/libtaskmanager/tasktools.cpp b/libtaskmanager/tasktools.cpp
index 08499148..342d3c46 100644
--- a/libtaskmanager/tasktools.cpp
+++ b/libtaskmanager/tasktools.cpp
@@ -69,11 +69,36 @@ AppData appDataFromUrl(const QUrl &url, const QIcon \
&fallbackIcon)  }
     }
 
+    // applications: URLs are used to refer to applications by their \
KService::menuId +    // (i.e. .desktop file name) rather than the absolute path to a \
.desktop file. +    if (url.scheme() == QStringLiteral("applications")) {
+        const KService::Ptr service = KService::serviceByMenuId(url.path());
+
+        if (service && url.path() == service->menuId()) {
+            data.name = service->name();
+            data.genericName = service->genericName();
+            data.id = service->storageId();
+
+            if (data.icon.isNull()) {
+                data.icon = QIcon::fromTheme(service->icon());
+            }
+        }
+    }
+
     if (url.isLocalFile() && KDesktopFile::isDesktopFile(url.toLocalFile())) {
         KDesktopFile f(url.toLocalFile());
 
         const KService::Ptr service = KService::serviceByStorageId(f.fileName());
 
+        // Resolve to non-absolute menuId-based URL if possible.
+        if (service) {
+            const QString &menuId = service->menuId();
+
+            if (!menuId.isEmpty()) {
+                data.url = QUrl(QStringLiteral("applications:") + menuId);
+            }
+        }
+
         if (service && QUrl::fromLocalFile(service->entryPath()) == url) {
             data.name = service->name();
             data.genericName = service->genericName();
@@ -101,23 +126,23 @@ AppData appDataFromUrl(const QUrl &url, const QIcon \
                &fallbackIcon)
         const KService::Ptr service = KService::serviceByStorageId(data.id);
 
         if (service) {
-            QString desktopFile = service->entryPath();
-
-            // Update with resolved URL.
-            data.url = QUrl::fromLocalFile(desktopFile);
-
-            KDesktopFile f(desktopFile);
-            KConfigGroup cg(&f, "Desktop Entry");
+            const QString &menuId = service->menuId();
+            const QString &desktopFile = service->entryPath();
 
-            data.icon = QIcon::fromTheme(f.readIcon());
-            const QString exec = cg.readEntry("Exec", QString());
-            data.name = cg.readEntry("Name", QString());
+            data.name = service->name();
+            data.genericName = service->genericName();
+            data.id = service->storageId();
 
-            if (data.name.isEmpty() && !exec.isEmpty()) {
-                data.name = exec.split(' ').at(0);
+            if (data.icon.isNull()) {
+                data.icon = QIcon::fromTheme(service->icon());
             }
 
-            data.genericName = f.readGenericName();
+            // Update with resolved URL.
+            if (!menuId.isEmpty()) {
+                data.url = QUrl(QStringLiteral("applications:") + menuId);
+            } else {
+                data.url = QUrl::fromLocalFile(desktopFile);
+            }
         }
     }
 
@@ -142,7 +167,16 @@ AppData appDataFromAppId(const QString &appId)
         data.id = service->storageId();
         data.name = service->name();
         data.genericName = service->genericName();
-        data.url = QUrl::fromLocalFile(service->entryPath());
+
+        const QString &menuId = service->menuId();
+
+        // applications: URLs are used to refer to applications by their \
KService::menuId +        // (i.e. .desktop file name) rather than the absolute path \
to a .desktop file. +        if (!menuId.isEmpty()) {
+            data.url = QUrl(QStringLiteral("applications:") + menuId);
+        } else {
+            data.url = QUrl::fromLocalFile(service->entryPath());
+        }
 
         return data;
     }
@@ -375,9 +409,18 @@ QUrl windowUrlFromMetadata(const QString &appId, quint32 pid,
     }
 
     if (!services.empty()) {
-        QString path = services[0]->entryPath();
+        const QString &menuId = services.at(0)->menuId();
+
+        // applications: URLs are used to refer to applications by their \
KService::menuId +        // (i.e. .desktop file name) rather than the absolute path \
to a .desktop file. +        if (!menuId.isEmpty()) {
+            return QUrl(QStringLiteral("applications:") + menuId);
+        }
+
+        QString path = services.at(0)->entryPath();
+
         if (path.isEmpty()) {
-            path = services[0]->exec();
+            path = services.at(0)->exec();
         }
 
         if (!path.isEmpty()) {
@@ -640,7 +683,17 @@ void runApp(const AppData &appData, const QList<QUrl> &urls)
         }
 #endif
 
-        const KService::Ptr service = \
KService::serviceByDesktopPath(appData.url.toLocalFile()); +        KService::Ptr \
service; +
+        // applications: URLs are used to refer to applications by their \
KService::menuId +        // (i.e. .desktop file name) rather than the absolute path \
to a .desktop file. +        if (appData.url.scheme() == \
QStringLiteral("applications")) { +            service = \
KService::serviceByMenuId(appData.url.path()); +        } else if \
(appData.url.scheme() == QLatin1String("preferred")) { +            const \
KService::Ptr service = \
KService::serviceByStorageId(defaultApplication(appData.url)); +        } else {
+            service = KService::serviceByDesktopPath(appData.url.toLocalFile());
+        }
 
         if (service && service->isApplication()) {
             KRun::runApplication(*service, urls, nullptr, 0, {},
diff --git a/libtaskmanager/xwindowtasksmodel.cpp \
b/libtaskmanager/xwindowtasksmodel.cpp index 1cef6c97..349faae9 100644
--- a/libtaskmanager/xwindowtasksmodel.cpp
+++ b/libtaskmanager/xwindowtasksmodel.cpp
@@ -484,6 +484,14 @@ QUrl XWindowTasksModel::Private::windowUrl(WId window)
         KService::Ptr service = KService::serviceByStorageId(desktopFile);
 
         if (service) {
+            const QString &menuId = service->menuId();
+
+            // applications: URLs are used to refer to applications by their \
KService::menuId +            // (i.e. .desktop file name) rather than the absolute \
path to a .desktop file. +            if (!menuId.isEmpty()) {
+                return QUrl(QStringLiteral("applications:") + menuId);
+            }
+
             return QUrl::fromLocalFile(service->entryPath());
         }
 


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic