diff --git a/src/common/dbus/org.kde.ActivityManager.Activities.xml b/src/common/dbus/org.kde.ActivityManager.Activities.xml --- a/src/common/dbus/org.kde.ActivityManager.Activities.xml +++ b/src/common/dbus/org.kde.ActivityManager.Activities.xml @@ -9,6 +9,12 @@ + + + + + + diff --git a/src/service/Activities.h b/src/service/Activities.h --- a/src/service/Activities.h +++ b/src/service/Activities.h @@ -78,6 +78,16 @@ */ bool SetCurrentActivity(const QString &activity); + /** + * Switches to the previous activity + */ + bool PreviousActivity(); + + /** + * Switches to the next activity + */ + bool NextActivity(); + /** * Adds a new activity * @param name name of the activity diff --git a/src/service/Activities.cpp b/src/service/Activities.cpp --- a/src/service/Activities.cpp +++ b/src/service/Activities.cpp @@ -51,6 +51,16 @@ // Private #define ACTIVITY_MANAGER_CONFIG_FILE_NAME QStringLiteral("kactivitymanagerdrc") +namespace { + inline + bool nameBasedOrdering(const ActivityInfo &info, const ActivityInfo &other) + { + const auto comp = + QString::compare(info.name, other.name, Qt::CaseInsensitive); + return comp < 0 || (comp == 0 && info.id < other.id); + } +} + Activities::Private::KDE4ConfigurationTransitionChecker::KDE4ConfigurationTransitionChecker() { // Checking whether we need to transfer the KActivities/KDE4 @@ -143,6 +153,23 @@ activities[keys] = Activities::Running; } } + + QMetaObject::invokeMethod( + this, + "updateSortedActivityList", + Qt::QueuedConnection); +} + +void Activities::Private::updateSortedActivityList() { + QVector a; + for (const auto &activity : activities.keys()) { + a.append(q->ActivityInformation(activity)); + } + + std::sort(a.begin(), a.end(), &nameBasedOrdering); + + QWriteLocker lock(&activitiesLock); + sortedActivities = a; } void Activities::Private::loadLastActivity() @@ -204,6 +231,32 @@ return true; } +bool Activities::Private::previousActivity() +{ + const auto a = q->ListActivities(Activities::Running); + + for (int i = 0; i < a.count(); ++i) { + if (a[i] == currentActivity) { + return setCurrentActivity(a[(i + a.size() - 1) % a.size()]); + } + } + + return false; +} + +bool Activities::Private::nextActivity() +{ + const auto a = q->ListActivities(Activities::Running); + + for (int i = 0; i < a.count(); ++i) { + if (a[i] == currentActivity) { + return setCurrentActivity(a[(i + 1) % a.size()]); + } + } + + return false; +} + QString Activities::Private::addActivity(const QString &name) { QString activity; @@ -234,6 +287,8 @@ q->SetActivityName(activity, name); + updateSortedActivityList(); + emit q->ActivityAdded(activity); scheduleConfigSync(); @@ -275,6 +330,13 @@ // Removing the activity activities.remove(activity); + for (int i = 0; i < sortedActivities.count(); ++i) { + if (sortedActivities[i].id == activity) { + sortedActivities.remove(i); + break; + } + } + // If the removed activity was the current one, // set another activity as current currentActivityDeleted = (currentActivity == activity); @@ -370,6 +432,8 @@ + activities.keys(Activities::Stopping)); scheduleConfigSync(); } + + updateSortedActivityList(); } void Activities::Private::ensureCurrentActivityIsRunning() @@ -471,6 +535,16 @@ return d->setCurrentActivity(activity); } +bool Activities::PreviousActivity() +{ + return d->previousActivity(); +} + +bool Activities::NextActivity() +{ + return d->nextActivity(); +} + QString Activities::AddActivity(const QString &name) { // We do not care about authorization if this is the first start @@ -494,13 +568,25 @@ QStringList Activities::ListActivities() const { QReadLocker lock(&d->activitiesLock); - return d->activities.keys(); + + QStringList s; + for (const auto &a : d->sortedActivities) { + s << a.id; + } + return s; } QStringList Activities::ListActivities(int state) const { QReadLocker lock(&d->activitiesLock); - return d->activities.keys((State)state); + + QStringList s; + for (const auto &a : d->sortedActivities) { + if (a.state == (State)state) { + s << a.id; + } + } + return s; } QList Activities::ListActivitiesWithInformation() const @@ -596,4 +682,3 @@ QReadLocker lock(&d->activitiesLock); return d->activities.contains(activity) ? d->activities[activity] : Invalid; } - diff --git a/src/service/Activities_p.h b/src/service/Activities_p.h --- a/src/service/Activities_p.h +++ b/src/service/Activities_p.h @@ -54,6 +54,9 @@ public Q_SLOTS: bool setCurrentActivity(const QString &activity); + bool previousActivity(); + bool nextActivity(); + void updateSortedActivityList(); public: void setActivityState(const QString &activity, Activities::State state); @@ -70,6 +73,7 @@ KSMServer *ksmserver; QHash activities; + QVector sortedActivities; QReadWriteLock activitiesLock; QString currentActivity;