Summary:
This introduces the use of QQmlParserStatus to delay populating
the model until all properties have been set, to avoid delegate
churn.
TasksModel is also meant to be used by C++. There's no good way
to determine whether an object is being instanciated by QML
during construction time, therefore this patch also introduces a
delay in initial population of the model after construction via
a single-shot timer. At the time the slot is invoked we know if
we're used by QML (because QQmlParserStatus::classBegin has
either been called or not by then) so we can decide to populate
or wait more for QQmlParserStatus::componentComplete.
I'm not super happy with this behavior change for C++ users,
however as the model is usually used via QML currently, it's
pragmatic to optimize performance for the common case, and it
doesn't technically break QAbstractItemModel semantics, as model
population isn't required to be sync.
There's a decent change this fixes a recently-reported crash as a
by-product:
CCBUG:386630
Reviewers: #plasma, davidedmundson, mart
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D8723
This way when a third party like pinning or dragging from Kickoff sends an absolute desktop file
path we would still only store the application id if possible.
CCBUG: 385594
Differential Revision: https://phabricator.kde.org/D8260
begin() and end() operate on the hash values.
This avoids creating a temporary list just for this.
Differential Revision: https://phabricator.kde.org/D7917
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
Summary:
TaskGroupingProxyModel uses a simple QVector<QVector<int>> populated
with source model row indices to represent the task group tree. To
implement QAbstractItemModel::parent(), its implementation of index()
encodes row indices of the top-level vector into the internal ids of
child item model indices. This allows parent() to produce the parent
model index by simply decoding the parent row from the passed-in child
index and call index() with that row.
Top-level row indices shift up and down as the list of top-level items
changes, invalidating those internal ids. QModelIndex is not meant to
be stored, and the proxy model does take care of updating any persis-
tent model indexes with new ids, so this should be fine.
However, where it falls apart is that as internal ids are invalidated,
a QSortFilterProxyModel on top of this proxy (i.e. TasksModel) may end
up with multiple indexes with identical internal ids in its mappings,
causing it to mess up its mappings as it uses them (e.g. taking things
from them). This causes the often-reported crash/assert there.
The fix is to refactor index()/parent() not to rely on row indices as
internal ids, but instead use pointers to internal data structures
instead.
This patch achieves this by changing the map to QVector<QVector<int> *>.
This screams fugly, but the alternative would basically just be to
create some wrapper struct to hide the fugly appeareance a little,
which I don't think is worth it.
On the flip side, it saves a QVector::replace() call as a multable
vector iterator can work directly on a vector without making a copy,
and it's now no longer necessary to manually update the persistent
model indices beyond what endRemoveRows() does implicitly.
BUG:381006
Reviewers: #plasma, davidedmundson
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D7139
Summary:
TaskGroupingProxyModel uses a simple QVector<QVector<int>> populated
with source model row indices to represent the task group tree. To
implement QAbstractItemModel::parent(), its implementation of index()
encodes row indices of the top-level vector into the internal ids of
child item model indices. This allows parent() to produce the parent
model index by simply decoding the parent row from the passed-in child
index and call index() with that row.
Top-level row indices shift up and down as the list of top-level items
changes, invalidating those internal ids. QModelIndex is not meant to
be stored, and the proxy model does take care of updating any persis-
tent model indexes with new ids, so this should be fine.
However, where it falls apart is that as internal ids are invalidated,
a QSortFilterProxyModel on top of this proxy (i.e. TasksModel) may end
up with multiple indexes with identical internal ids in its mappings,
causing it to mess up its mappings as it uses them (e.g. taking things
from them). This causes the often-reported crash/assert there.
The fix is to refactor index()/parent() not to rely on row indices as
internal ids, but instead use pointers to internal data structures
instead.
This patch achieves this by changing the map to QVector<QVector<int> *>.
This screams fugly, but the alternative would basically just be to
create some wrapper struct to hide the fugly appeareance a little,
which I don't think is worth it.
On the flip side, it saves a QVector::replace() call as a multable
vector iterator can work directly on a vector without making a copy,
and it's now no longer necessary to manually update the persistent
model indices beyond what endRemoveRows() does implicitly.
BUG:381006
Reviewers: #plasma, davidedmundson
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D7139
Summary:
Windows we can't find an app icon for using the normal means
get the icon used by the windowing system in the Task Manager.
This fallback icon was then not updated when changed on the
window, only occasionally as a side-effect of cache evictions
and model data requests.
This patch notes which windows hit the fallback path, and for
those windows evicts the cache when the icon changes on the
window, causing it to be re-retrieved from the windowing system
as views respond to the dataChanged signal for the decoration
role.
Evicting the entire cache is a little bit costly, but:
- This is a fallback codepath.
- Apps conventionally update title and icon in one go, meaning
the cache is often already getting evicted anyway.
- Icons don't change that often.
BUG:383017
Reviewers: #plasma, davidedmundson
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D7092
This is done in XWindowTasksModel and WaylandTasksModel but was forgotten in LauncherTasksModel.
Differential Revision: https://phabricator.kde.org/D6869
Summary:
Also better sanity-checking of found services being app services
all around.
I'm not particularly happy about adding more X11 code outside of
XWindowTasksModel, but it means greater code reuse (in something that
has experienced unwelcome drift before) and there's a precedent in
LauncherTasksModel.
Reviewers: #plasma, broulik
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D6358
Summary:
Otherwise we:
* ... don't get startup notifications.
BUG:381500
* ... don't contribute data to recent/most used apps.
This is a surprisingly large oversight.
Reviewers: #plasma
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D6354
Summary:
The pinned launchers that are assigned to other activities
will have a -1 as the order. We should not forget them
when saving to the configuration file.
Reviewers: hein, mart
Reviewed By: hein
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D5933
Summary:
The pinned launchers that are assigned to other activities
will have a -1 as the order. We should not forget them
when saving to the configuration file.
Reviewers: hein, mart
Reviewed By: hein
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D5933
Summary:
This factors the app identification heuristic out of XWindowTasksModel
and turns it into generic code in TaskTools, producing a URL from a set
of window metadata bits. The key metadata is the 'appId', which is the
classClass part of WM_CLASS on X11 and PlasmaWindow::appId on Wayland -
which KWin sets to the former for XWayland clients. The result is much
improved support for XWayland clients in the Wayland session, with most
X clients now identified correctly.
As a side effect, the Wayland model gains access to the X model's much
superior code for grabbing a suitable icon, with PlasmaWindow::icon now
serving only as a fallback, similar to KWindowSystem::icon in the X
model.
Moving the code to TaskTools also means it now sports nice API docs.
The heuristic has seen some work as well, namely adding two passes that
try to parse the appId as a path to a desktop file, which we've never
seen on X11 but is common on Wayland - this heuristic was previously in
appDataFromAppId, which has been removed here since the shared heuristic
now satisfies this case.
Further, an old codepath handling kcmshell in a special way has been
removed. This is no longer necessary as we have better ways to tell
libtaskmanager about the KCM KService now, such as the .desktop file
window hint on X11 and a reliable appId on Wayland.
This patch also fixes some bugs around app data cache eviction and
telling model clients about data changes when cache eviction happens.
The X model didn't use to evict the cache and refresh when the
taskmanagerrulesrc file was changed at runtime, and the refresh for
sycoca changes didn't refresh the LauncherUrlWithoutIcon role. It does
now, and the Wayland model - which has gained taskmanagerrulesrc support
by way of the shared heuristic - now behaves in the same way.
The combined changes achieve near behavior parity between the X
and Wayland models when it comes to identifying apps by window meta
data, with the only exception being XWayland clients that need to be
identified by the (incorrectly used by the client developer) instance
name part of the WM_CLASS window property, which we can't access (this
case is so rare it's not worth handling at this time).
Depends on D5747, D5755.
Reviewers: #plasma, davidedmundson
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D5818
Summary:
This introduces a TryIgnoreRuntimes key in taskmanagerrulesrc's Settings
group that can be used to list known runtime executables that can be
ignored when trying to identify the application owning a window by the
command line of the associated process.
A concrete example is the Frozen Bubble application. Frozen Bubble
installs a frozen-bubble.desktop with Exec=frozen-bubble, yet its
WM_CLASS is ("perl", "perl") and its command line is as follows:
/usr/bin/perl /usr/bin/frozen-bubble
The existing servicesFromPid() (now split into servicesFromPid() and
servicesFromCmdLine()) does not find the frozen-bubble service because
it works with the leading executable in the command line.
In this patch, TryIgnoreRuntimes is introduced with a default of
"perl". In the new code, after the initial command line matching pass
fails, TryIgnoreRuntimes is checked for whether the leading command
line executable is on the list, and if so, a second command line
matching pass is run with the remainder of the process' command line,
now succeeding.
Note that the approach of "try one more thing" rather than checking
against TryIgnoreRuntimes first is deliberate: The Exec= key in many
.desktop files contains a complete command line prefixed with the
runtime executable. In those cases we don't want to ignore the runtime
executable, or matching would fail.
To complement this, the "perl" WM_CLASS is added to the
MatchCommandLineFirst rc key. Due to the shoddy metadata Frozen
Bubble already ended up in servicesFromPid() regardless, but this
saves some busywork for this WM_CLASS, which can reliably be presumed
bad.
The patch also fixes a small logic error in the match-command-line-
without-arguments block, where the result of a KServiceTypeTrader
query was ignored and immediately overridden by another.
Reviewers: #plasma, davidedmundson, broulik
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D5522
Summary:
This is implemented by TasksModel and allows clients to reliably
query whether a row has an associated launcher. Useful for things
like Pin/Unpin action state or layout decisions.
Previously clients would have to reimplement something like
TaskTools::appsMatch on top of the model, which we absolutely do
not want to do - there should only be one copy of the app matching
logic for consistency's sake. In practice clients would do things
like fetch LauncherUrl and run it by launcherPosition(), which
omits appsMatch's AppId comparision, as an example of such unwated
drift. This approach also avoids the large performance overhead
involved.
The role is not implemented by the single-type or munging tasks
models as it has no use there.
Reviewers: #plasma, davidedmundson
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D5504
Summary:
Previously we updated the prop after checking for
AbstractTasksModel::IsDemandingAttention on window closure, but
as the window is gone, we can't actually get state for it anymore,
so we always need to update.
To make up for it, this patch also optimizes the prop updates to occur
only once per insert/remove batch - this is a bit academic because
the source models currently only insert single rows at a time, but
it's good hygiene.
BUG:378254
Reviewers: #plasma, mart
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D5261
Summary:
We currently match Krita by Name. It's classClass is "krita",
but its DesktopEntryName is org.kde.krita.desktop. However,
Krita also installs numerous additional .desktop entries to
associate more file types by itself, all of which match by
name, and the first one in the list isn't the right one. All
of those extra .desktop files are NoDisplay=true however, so
we can filter them out, which brings the match list down to
the one and only .desktop file we care for.
Reviewers: #plasma, broulik, davidedmundson
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D4928
Summary:
The new activity-aware implementation of
LauncherTasksModel::setLauncherList() would only accept the passed list
when it changed any activities associations, not when the order changed.
This would effectively turn TasksModel::move involving launcher tasks
into a no-op.
Rearranging launchers works like this:
1. A client calls TasksModel::move one or many times. TasksModel::move
updates TasksModel's internal sort mapping and implements it, causing
a visible order change in any views.
2. When it is done calling move(), the client calls
TasksModel::syncLaunchers. TasksModel::syncLaunchers calls
LauncherTasksModel::setLauncherList with a new list derived from
its sort mapping, and updates its sort mapping in expectation of
row indices changing in the launcher tasks source model.
Due to the above bug, the sort mapping would be adjusted in expectation
of changes the launcher tasks model would not actually do, appearing to
undo the moves the next time a view is updated from source data.
CCMAIL:ivan.cukic@kde.org
Reviewers: #plasma, davidedmundson, mart
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D4749
Summary:
WM_CLASS instance and general classes are checked against StartupWMClass
prior to most rewrite and mapping rules, and prior to the DesktopEntryName
and Name checks.
This matches the fd.o spec more closely and makes Chrome Apps and
LibreOffice work without special mapping rules, which is also a speed
win.
Reviewers: #plasma, davidedmundson, broulik
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D4706
We only matched for the "Default" suffix which is the default profile but this breaks
when having apps installed in different profiles where they get e.g. "Profile_1" suffix.
BUG: 376695
FIXED-IN: 5.9.3
Differential Revision: https://phabricator.kde.org/D4680