From 25cb8e18b520642b15b6bb98c86cc494775982bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=C4=8Cuki=C4=87?= Date: Mon, 10 Oct 2016 20:41:02 +0200 Subject: [PATCH] Methods for adding and removing per-activity launchers --- libtaskmanager/launchertasksmodel.cpp | 190 ++++++++++++++++++++------ libtaskmanager/launchertasksmodel.h | 26 ++++ libtaskmanager/tasksmodel.cpp | 36 +++++ libtaskmanager/tasksmodel.h | 26 ++++ 4 files changed, 233 insertions(+), 45 deletions(-) diff --git a/libtaskmanager/launchertasksmodel.cpp b/libtaskmanager/launchertasksmodel.cpp index 512c475ff..04d1c6e0a 100644 --- a/libtaskmanager/launchertasksmodel.cpp +++ b/libtaskmanager/launchertasksmodel.cpp @@ -58,6 +58,9 @@ public: void init(); AppData appData(const QUrl &url); + bool requestAddLauncherToActivities(const QUrl &_url, const QStringList &activities); + bool requestRemoveLauncherFromActivities(const QUrl &_url, const QStringList &activities); + private: LauncherTasksModel *q; }; @@ -112,6 +115,137 @@ AppData LauncherTasksModel::Private::appData(const QUrl &url) return appDataCache.value(url); } +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); + + if (url.isEmpty() || !url.isValid()) { + return false; + } + + // Merge duplicates + int row = -1; + foreach(const QUrl &launcher, launchersOrder) { + ++row; + + if (launcherUrlsMatch(url, launcher, IgnoreQueryItems)) { + QStringList 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(); + + } else { + newActivities.append(activities); + newActivities.append(activitiesForLauncher[url]); + + } + } + + if (newActivities != activitiesForLauncher[url]) { + emit q->dataChanged( + q->index(row, 0), + q->index(row, 0)); + return true; + + } + + return false; + } + } + + // This is a new one + const auto count = launchersOrder.count(); + q->beginInsertRows(QModelIndex(), count, count); + activitiesForLauncher[url] = activities; + launchersOrder.append(url); + q->endInsertRows(); + + emit q->launcherListChanged(); + + return true; +} + +bool LauncherTasksModel::Private::requestRemoveLauncherFromActivities(const QUrl &url, const QStringList &activities) +{ + for (int row = 0; row < launchersOrder.count(); ++row) { + const QUrl &launcher = launchersOrder.at(row); + + if (launcherUrlsMatch(url, launcher, IgnoreQueryItems) + || launcherUrlsMatch(url, appData(launcher).url, IgnoreQueryItems)) { + + const QStringList currentActivities = activitiesForLauncher[url]; + QStringList newActivities; + bool remove = false; + bool update = false; + + if (currentActivities.isEmpty()) { + // We are currently on all activities. + // Should we go away, or just remove from the current one? + if (activities.isEmpty()) { + remove = true; + + } else { + for (const auto& activity: currentActivities) { + if (!activities.contains(activity)) { + newActivities << activity; + } else { + update = true; + } + } + } + + } else { + // We weren't on all activities, just remove those that + // we were on + + for (const auto& activity: currentActivities) { + if (!activities.contains(activity)) { + newActivities << activity; + } + } + + if (newActivities.isEmpty()) { + remove = true; + } else { + update = true; + } + } + + if (remove) { + q->beginRemoveRows(QModelIndex(), row, row); + launchersOrder.removeAt(row); + activitiesForLauncher.remove(url); + appDataCache.remove(launcher); + q->endRemoveRows(); + + } else if (update) { + activitiesForLauncher[url] = newActivities; + + emit q->dataChanged( + q->index(row, 0), + q->index(row, 0)); + } + + if (remove || update) { + emit q->launcherListChanged(); + return true; + } + } + } + + return false; +} + LauncherTasksModel::LauncherTasksModel(QObject *parent) : AbstractTasksModel(parent) , d(new Private(this)) @@ -301,58 +435,24 @@ void LauncherTasksModel::setLauncherList(const QStringList &serializedLaunchers) } } -bool LauncherTasksModel::requestAddLauncher(const QUrl &_url) +bool LauncherTasksModel::requestAddLauncher(const QUrl &url) { - // 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); - - if (url.isEmpty() || !url.isValid()) { - return false; - } - - // Reject duplicates. - foreach(const QUrl &launcher, d->launchersOrder) { - if (launcherUrlsMatch(url, launcher, IgnoreQueryItems)) { - return false; - } - } - - // Adding the launcher to all activities - const int count = d->launchersOrder.count(); - beginInsertRows(QModelIndex(), count, count); - d->activitiesForLauncher[url]; // = QStringList(); - d->launchersOrder.append(url); - endInsertRows(); - - emit launcherListChanged(); - - return true; + return d->requestAddLauncherToActivities(url, QStringList()); } bool LauncherTasksModel::requestRemoveLauncher(const QUrl &url) { - for (int i = 0; i < d->launchersOrder.count(); ++i) { - const QUrl &launcher = d->launchersOrder.at(i); - - if (launcherUrlsMatch(url, launcher, IgnoreQueryItems) - || launcherUrlsMatch(url, d->appData(launcher).url, IgnoreQueryItems)) { - - // Removing the launcher from all activities - - beginRemoveRows(QModelIndex(), i, i); - d->launchersOrder.removeAt(i); - d->activitiesForLauncher.remove(url); - d->appDataCache.remove(launcher); - endRemoveRows(); - - emit launcherListChanged(); + return d->requestRemoveLauncherFromActivities(url, QStringList()); +} - return true; - } - } +bool LauncherTasksModel::requestAddLauncherToActivity(const QUrl &url) +{ + return d->requestAddLauncherToActivities(url, { d->activities.currentActivity() }); +} - return false; +bool LauncherTasksModel::requestRemoveLauncherFromActivity(const QUrl &url) +{ + return d->requestRemoveLauncherFromActivities(url, { d->activities.currentActivity() }); } int LauncherTasksModel::launcherPosition(const QUrl &url) const diff --git a/libtaskmanager/launchertasksmodel.h b/libtaskmanager/launchertasksmodel.h index 0c7a274fe..516c9f9df 100644 --- a/libtaskmanager/launchertasksmodel.h +++ b/libtaskmanager/launchertasksmodel.h @@ -107,6 +107,32 @@ public: */ bool requestRemoveLauncher(const QUrl &url); + /** + * Request adding a launcher with the given URL to current activity. + * + * If this URL is already in the list, the request will fail. URLs are + * compared for equality after removing the query string used to hold + * metadata. + * + * @see launcherUrlsMatch + * @param url A launcher URL. + * @returns @c true if a launcher was added. + */ + bool requestAddLauncherToActivity(const QUrl &url); + + /** + * Request removing the launcher with the given URL from the current activity. + * + * If this URL is already in the list, the request will fail. URLs are + * compared for equality after removing the query string used to hold + * metadata. + * + * @see launcherUrlsMatch + * @param url A launcher URL. + * @returns @c true if the launcher was removed. + */ + bool requestRemoveLauncherFromActivity(const QUrl &url); + /** * Return the position of the launcher with the given URL. * diff --git a/libtaskmanager/tasksmodel.cpp b/libtaskmanager/tasksmodel.cpp index f31e7784e..542aee5a7 100644 --- a/libtaskmanager/tasksmodel.cpp +++ b/libtaskmanager/tasksmodel.cpp @@ -1154,6 +1154,42 @@ bool TasksModel::requestRemoveLauncher(const QUrl &url) return false; } +bool TasksModel::requestAddLauncherToActivity(const QUrl &url) +{ + d->initLauncherTasksModel(); + + bool added = d->launcherTasksModel->requestAddLauncherToActivity(url); + + // 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 + // their launcher position now. + if (added && d->sortMode == SortManual && (d->launchInPlace || !d->separateLaunchers)) { + d->updateManualSortMap(); + d->forceResort(); + } + + return added; +} + +bool TasksModel::requestRemoveLauncherFromActivity(const QUrl &url) +{ + if (d->launcherTasksModel) { + bool removed = d->launcherTasksModel->requestRemoveLauncherFromActivity(url); + + // 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 + // longer backed by a launcher out of the launcher area. + if (removed && d->sortMode == SortManual && (d->launchInPlace || !d->separateLaunchers)) { + d->updateManualSortMap(); + d->forceResort(); + } + + return removed; + } + + return false; +} + int TasksModel::launcherPosition(const QUrl &url) const { if (d->launcherTasksModel) { diff --git a/libtaskmanager/tasksmodel.h b/libtaskmanager/tasksmodel.h index 8adcff47d..4f479499a 100644 --- a/libtaskmanager/tasksmodel.h +++ b/libtaskmanager/tasksmodel.h @@ -547,6 +547,32 @@ public: */ Q_INVOKABLE bool requestRemoveLauncher(const QUrl &url); + /** + * Request adding a launcher with the given URL to current activity. + * + * If this URL is already in the list, the request will fail. URLs are + * compared for equality after removing the query string used to hold + * metadata. + * + * @see launcherUrlsMatch + * @param url A launcher URL. + * @returns @c true if a launcher was added. + */ + Q_INVOKABLE bool requestAddLauncherToActivity(const QUrl &url); + + /** + * Request removing the launcher with the given URL from the current activity. + * + * If this URL is already in the list, the request will fail. URLs are + * compared for equality after removing the query string used to hold + * metadata. + * + * @see launcherUrlsMatch + * @param url A launcher URL. + * @returns @c true if the launcher was removed. + */ + Q_INVOKABLE bool requestRemoveLauncherFromActivity(const QUrl &url); + /** * Return the position of the launcher with the given URL. *