diff --git a/libtaskmanager/launchertasksmodel.h b/libtaskmanager/launchertasksmodel.h --- a/libtaskmanager/launchertasksmodel.h +++ b/libtaskmanager/launchertasksmodel.h @@ -118,7 +118,7 @@ * @param url A launcher URL. * @returns @c true if a launcher was added. */ - bool requestAddLauncherToActivity(const QUrl &url); + bool requestAddLauncherToActivity(const QUrl &url, const QString &activity); /** * Request removing the launcher with the given URL from the current activity. @@ -131,7 +131,7 @@ * @param url A launcher URL. * @returns @c true if the launcher was removed. */ - bool requestRemoveLauncherFromActivity(const QUrl &url); + bool requestRemoveLauncherFromActivity(const QUrl &url, const QString &activity); /** * Return the list of activities the launcher belongs to. diff --git a/libtaskmanager/launchertasksmodel.cpp b/libtaskmanager/launchertasksmodel.cpp --- a/libtaskmanager/launchertasksmodel.cpp +++ b/libtaskmanager/launchertasksmodel.cpp @@ -33,6 +33,8 @@ #include #include +#include +#include #if HAVE_X11 #include #endif @@ -42,15 +44,32 @@ namespace TaskManager { +typedef QSet ActivitiesSet; + +template +inline bool isOnAllActivities(const ActivitiesCollection &activities) +{ + return activities.isEmpty() || activities.contains(NULL_UUID); +} + + class LauncherTasksModel::Private { public: Private(LauncherTasksModel *q); - KActivities::Consumer activities; + KActivities::Consumer activitiesConsumer; QList launchersOrder; - QHash activitiesForLauncher; + + QHash activitiesForLauncher; + inline void setActivitiesForLauncher(const QUrl &url, const ActivitiesSet &activities) { + if (activities.size() == activitiesConsumer.activities().size()) { + activitiesForLauncher[url] = { NULL_UUID }; + } else { + activitiesForLauncher[url] = activities; + } + } QHash appDataCache; QTimer sycocaChangeTimer; @@ -115,11 +134,12 @@ return appDataCache.value(url); } -bool LauncherTasksModel::Private::requestAddLauncherToActivities(const QUrl &_url, const QStringList &activities) +bool LauncherTasksModel::Private::requestAddLauncherToActivities(const QUrl &_url, const QStringList &_activities) { // isValid() for the passed-in URL might return true if it was // constructed in TolerantMode, but we want to reject invalid URLs. QUrl url(_url.toString(), QUrl::StrictMode); + const auto activities = ActivitiesSet::fromList(_activities); if (url.isEmpty() || !url.isValid()) { return false; @@ -131,30 +151,42 @@ ++row; if (launcherUrlsMatch(url, launcher, IgnoreQueryItems)) { - QStringList newActivities; + ActivitiesSet newActivities; if (!activitiesForLauncher.contains(url)) { // If we don't have the activities assigned to this url // for some reason newActivities = activities; } else { - // If any of the lists are empty, we are on all activities, - // otherwise, lets merge the lists - if (activitiesForLauncher[url].isEmpty() || activities.isEmpty()) { - newActivities.clear(); + if (isOnAllActivities(activities)) { + // If the new list is empty, or has a null uuid, this + // launcher should be on all activities + newActivities = ActivitiesSet { NULL_UUID }; + + } else if (isOnAllActivities(activitiesForLauncher[url])) { + // If we have been on all activities before, and we have + // been asked to be on a specific one, lets make an + // exception - we will set the activities to exactly + // what we have been asked + newActivities = activities; + } else { - newActivities.append(activities); - newActivities.append(activitiesForLauncher[url]); + newActivities += activities; + newActivities += activitiesForLauncher[url]; } } if (newActivities != activitiesForLauncher[url]) { + setActivitiesForLauncher(url, newActivities); + emit q->dataChanged( q->index(row, 0), q->index(row, 0)); + + emit q->launcherListChanged(); return true; } @@ -166,7 +198,7 @@ // This is a new one const auto count = launchersOrder.count(); q->beginInsertRows(QModelIndex(), count, count); - activitiesForLauncher[url] = activities; + setActivitiesForLauncher(url, activities); launchersOrder.append(url); q->endInsertRows(); @@ -183,19 +215,21 @@ if (launcherUrlsMatch(url, launcher, IgnoreQueryItems) || launcherUrlsMatch(url, appData(launcher).url, IgnoreQueryItems)) { - const QStringList currentActivities = activitiesForLauncher[url]; - QStringList newActivities; + const auto currentActivities = activitiesForLauncher[url]; + ActivitiesSet newActivities; + bool remove = false; bool update = false; - if (currentActivities.isEmpty()) { + if (isOnAllActivities(currentActivities)) { // We are currently on all activities. // Should we go away, or just remove from the current one? - if (activities.isEmpty()) { + + if (isOnAllActivities(activities)) { remove = true; } else { - for (const auto& activity: currentActivities) { + for (const auto& activity: activitiesConsumer.activities()) { if (!activities.contains(activity)) { newActivities << activity; } else { @@ -229,7 +263,7 @@ q->endRemoveRows(); } else if (update) { - activitiesForLauncher[url] = newActivities; + setActivitiesForLauncher(url, newActivities); emit q->dataChanged( q->index(row, 0), @@ -294,7 +328,7 @@ } else if (role == IsOnAllVirtualDesktops) { return true; } else if (role == Activities) { - return d->activitiesForLauncher[url]; + return QStringList(d->activitiesForLauncher[url].toList()); } return QVariant(); @@ -314,12 +348,12 @@ const auto &activities = d->activitiesForLauncher[launcher]; QString serializedLauncher; - if (activities.isEmpty()) { + if (isOnAllActivities(activities)) { serializedLauncher = launcher.toString(); } else { serializedLauncher = - "[" + d->activitiesForLauncher[launcher].join(",") + "]\n" + + "[" + d->activitiesForLauncher[launcher].toList().join(",") + "]\n" + launcher.toString(); } @@ -333,29 +367,31 @@ { // Clearing everything QList newLaunchersOrder; - QHash newActivitiesForLauncher; + QHash newActivitiesForLauncher; // Loading the activity to launchers map QHash> launchersForActivitiesCandidates; for (const auto& serializedLauncher: serializedLaunchers) { - QStringList activities; + QStringList _activities; QUrl url; - std::tie(url, activities) = + std::tie(url, _activities) = deserializeLauncher(serializedLauncher); + auto activities = ActivitiesSet::fromList(_activities); + // Is url is not valid, ignore it if (!url.isValid()) continue; // If we have a null uuid, it means we are on all activities - if (activities.contains(NULL_UUID)) { - activities.clear(); - } + // and we should contain only the null uuid + if (isOnAllActivities(activities)) { + activities = { NULL_UUID }; - // Filter invalid activities - if (!activities.isEmpty()) { - const auto allActivities = d->activities.activities(); - QStringList validActivities; + } else { + // Filter out invalid activities + const auto allActivities = d->activitiesConsumer.activities(); + ActivitiesSet validActivities; for (const auto& activity: activities) { if (allActivities.contains(activity)) { validActivities << activity; @@ -394,12 +430,15 @@ // This is the first time we got this url newActivitiesForLauncher[url] = activities; - } else if (newActivitiesForLauncher[url].isEmpty()) { + } else if (newActivitiesForLauncher[url].contains(NULL_UUID)) { // Do nothing, we are already on all activities + } else if (activities.contains(NULL_UUID)) { + newActivitiesForLauncher[url] = { NULL_UUID }; + } else { // We are not on all activities, append the new ones - newActivitiesForLauncher[url].append(activities); + newActivitiesForLauncher[url] += activities; } } @@ -437,31 +476,40 @@ bool LauncherTasksModel::requestAddLauncher(const QUrl &url) { - return d->requestAddLauncherToActivities(url, QStringList()); + return d->requestAddLauncherToActivities(url, { NULL_UUID }); } bool LauncherTasksModel::requestRemoveLauncher(const QUrl &url) { - return d->requestRemoveLauncherFromActivities(url, QStringList()); + return d->requestRemoveLauncherFromActivities(url, { NULL_UUID }); } -bool LauncherTasksModel::requestAddLauncherToActivity(const QUrl &url) +bool LauncherTasksModel::requestAddLauncherToActivity(const QUrl &url, const QString &activity) { - return d->requestAddLauncherToActivities(url, { d->activities.currentActivity() }); + return d->requestAddLauncherToActivities(url, { activity }); } -bool LauncherTasksModel::requestRemoveLauncherFromActivity(const QUrl &url) +bool LauncherTasksModel::requestRemoveLauncherFromActivity(const QUrl &url, const QString &activity) { - return d->requestRemoveLauncherFromActivities(url, { d->activities.currentActivity() }); + return d->requestRemoveLauncherFromActivities(url, { activity }); } QStringList LauncherTasksModel::launcherActivities(const QUrl &_url) const { const auto position = launcherPosition(_url); - const auto url = d->launchersOrder.at(position); - return d->activitiesForLauncher.contains(url) ? d->activitiesForLauncher[url] - : QStringList { NULL_UUID }; + if (position == -1) { + // If we do not have this launcher, return an empty list + return {}; + + } else { + const auto url = d->launchersOrder.at(position); + + // If the launcher is on all activities, return a null uuid + return d->activitiesForLauncher.contains(url) + ? d->activitiesForLauncher[url].toList() + : QStringList { NULL_UUID }; + } } int LauncherTasksModel::launcherPosition(const QUrl &url) const diff --git a/libtaskmanager/tasksmodel.h b/libtaskmanager/tasksmodel.h --- a/libtaskmanager/tasksmodel.h +++ b/libtaskmanager/tasksmodel.h @@ -558,7 +558,7 @@ * @param url A launcher URL. * @returns @c true if a launcher was added. */ - Q_INVOKABLE bool requestAddLauncherToActivity(const QUrl &url); + Q_INVOKABLE bool requestAddLauncherToActivity(const QUrl &url, const QString &activity); /** * Request removing the launcher with the given URL from the current activity. @@ -571,7 +571,7 @@ * @param url A launcher URL. * @returns @c true if the launcher was removed. */ - Q_INVOKABLE bool requestRemoveLauncherFromActivity(const QUrl &url); + Q_INVOKABLE bool requestRemoveLauncherFromActivity(const QUrl &url, const QString &activity); /** * Return the list of activities the launcher belongs to. diff --git a/libtaskmanager/tasksmodel.cpp b/libtaskmanager/tasksmodel.cpp --- a/libtaskmanager/tasksmodel.cpp +++ b/libtaskmanager/tasksmodel.cpp @@ -1154,11 +1154,11 @@ return false; } -bool TasksModel::requestAddLauncherToActivity(const QUrl &url) +bool TasksModel::requestAddLauncherToActivity(const QUrl &url, const QString &activity) { d->initLauncherTasksModel(); - bool added = d->launcherTasksModel->requestAddLauncherToActivity(url); + bool added = d->launcherTasksModel->requestAddLauncherToActivity(url, activity); // If using manual and launch-in-place sorting with separate launchers, // we need to trigger a sort map update to move any window tasks to @@ -1171,10 +1171,10 @@ return added; } -bool TasksModel::requestRemoveLauncherFromActivity(const QUrl &url) +bool TasksModel::requestRemoveLauncherFromActivity(const QUrl &url, const QString &activity) { if (d->launcherTasksModel) { - bool removed = d->launcherTasksModel->requestRemoveLauncherFromActivity(url); + bool removed = d->launcherTasksModel->requestRemoveLauncherFromActivity(url, activity); // If using manual and launch-in-place sorting with separate launchers, // we need to trigger a sort map update to move any window tasks no