File indexing completed on 2024-05-19 05:37:49
0001 /* 0002 SPDX-FileCopyrightText: 2010 Chani Armitage <chani@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "activityengine.h" 0008 #include "activityservice.h" 0009 0010 #include <plasmaactivities/controller.h> 0011 #include <plasmaactivities/info.h> 0012 0013 #include <QApplication> 0014 #include <QDBusServiceWatcher> 0015 0016 #define ACTIVITYMANAGER_SERVICE "org.kde.kactivitymanagerd" 0017 #define ACTIVITYRANKING_OBJECT "/ActivityRanking" 0018 0019 ActivityEngine::ActivityEngine(QObject *parent) 0020 : Plasma5Support::DataEngine(parent) 0021 { 0022 init(); 0023 } 0024 0025 void ActivityEngine::init() 0026 { 0027 if (qApp->applicationName() == QLatin1String("plasma-netbook")) { 0028 // hack for the netbook 0029 // FIXME can I read a setting or something instead? 0030 } else { 0031 m_activityController = new KActivities::Controller(this); 0032 m_currentActivity = m_activityController->currentActivity(); 0033 const QStringList activities = m_activityController->activities(); 0034 // setData("allActivities", activities); 0035 for (const QString &id : activities) { 0036 insertActivity(id); 0037 } 0038 0039 connect(m_activityController, &KActivities::Controller::activityAdded, this, &ActivityEngine::activityAdded); 0040 connect(m_activityController, &KActivities::Controller::activityRemoved, this, &ActivityEngine::activityRemoved); 0041 connect(m_activityController, &KActivities::Controller::currentActivityChanged, this, &ActivityEngine::currentActivityChanged); 0042 0043 // some convenience sources for times when checking every activity source would suck 0044 // it starts with _ so that it can easily be filtered out of sources() 0045 // maybe I should just make it not included in sources() instead? 0046 m_runningActivities = m_activityController->activities(KActivities::Info::Running); 0047 setData(QStringLiteral("Status"), QStringLiteral("Current"), m_currentActivity); 0048 setData(QStringLiteral("Status"), QStringLiteral("Running"), m_runningActivities); 0049 0050 m_watcher = new QDBusServiceWatcher(ACTIVITYMANAGER_SERVICE, 0051 QDBusConnection::sessionBus(), 0052 QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration, 0053 this); 0054 0055 connect(m_watcher, &QDBusServiceWatcher::serviceRegistered, this, &ActivityEngine::enableRanking); 0056 connect(m_watcher, &QDBusServiceWatcher::serviceUnregistered, this, &ActivityEngine::disableRanking); 0057 0058 if (QDBusConnection::sessionBus().interface()->isServiceRegistered(ACTIVITYMANAGER_SERVICE)) { 0059 enableRanking(); 0060 } 0061 } 0062 } 0063 0064 void ActivityEngine::insertActivity(const QString &id) 0065 { 0066 // id -> name, icon, state 0067 KActivities::Info *activity = new KActivities::Info(id, this); 0068 m_activities[id] = activity; 0069 setData(id, QStringLiteral("Name"), activity->name()); 0070 setData(id, QStringLiteral("Icon"), activity->icon()); 0071 setData(id, QStringLiteral("Current"), m_currentActivity == id); 0072 0073 QString state; 0074 switch (activity->state()) { 0075 case KActivities::Info::Running: 0076 state = QLatin1String("Running"); 0077 break; 0078 case KActivities::Info::Starting: 0079 state = QLatin1String("Starting"); 0080 break; 0081 case KActivities::Info::Stopping: 0082 state = QLatin1String("Stopping"); 0083 break; 0084 case KActivities::Info::Stopped: 0085 state = QLatin1String("Stopped"); 0086 break; 0087 case KActivities::Info::Invalid: 0088 default: 0089 state = QLatin1String("Invalid"); 0090 } 0091 setData(id, QStringLiteral("State"), state); 0092 setData(id, QStringLiteral("Score"), m_activityScores.value(id)); 0093 0094 connect(activity, &KActivities::Info::infoChanged, this, &ActivityEngine::activityDataChanged); 0095 connect(activity, &KActivities::Info::stateChanged, this, &ActivityEngine::activityStateChanged); 0096 0097 m_runningActivities << id; 0098 } 0099 0100 void ActivityEngine::disableRanking() 0101 { 0102 delete m_activityRankingClient; 0103 } 0104 0105 void ActivityEngine::enableRanking() 0106 { 0107 m_activityRankingClient = new org::kde::ActivityManager::ActivityRanking(ACTIVITYMANAGER_SERVICE, ACTIVITYRANKING_OBJECT, QDBusConnection::sessionBus()); 0108 connect(m_activityRankingClient, &org::kde::ActivityManager::ActivityRanking::rankingChanged, this, &ActivityEngine::rankingChanged); 0109 0110 QDBusMessage msg = QDBusMessage::createMethodCall(ACTIVITYMANAGER_SERVICE, 0111 ACTIVITYRANKING_OBJECT, 0112 QStringLiteral("org.kde.ActivityManager.ActivityRanking"), 0113 QStringLiteral("activities")); 0114 QDBusPendingReply<ActivityDataList> reply = QDBusConnection::sessionBus().asyncCall(msg); 0115 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); 0116 QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, &ActivityEngine::activityScoresReply); 0117 } 0118 0119 void ActivityEngine::activityScoresReply(QDBusPendingCallWatcher *watcher) 0120 { 0121 QDBusPendingReply<ActivityDataList> reply = *watcher; 0122 if (reply.isError()) { 0123 qDebug() << "Error getting activity scores: " << reply.error().message(); 0124 } else { 0125 setActivityScores(reply.value()); 0126 } 0127 0128 watcher->deleteLater(); 0129 } 0130 0131 void ActivityEngine::rankingChanged(const QStringList &topActivities, const ActivityDataList &activities) 0132 { 0133 Q_UNUSED(topActivities) 0134 0135 setActivityScores(activities); 0136 } 0137 0138 void ActivityEngine::setActivityScores(const ActivityDataList &activities) 0139 { 0140 QSet<QString> presentActivities; 0141 m_activityScores.clear(); 0142 0143 for (const ActivityData &activity : activities) { 0144 if (m_activities.contains(activity.id)) { 0145 setData(activity.id, QStringLiteral("Score"), activity.score); 0146 } 0147 presentActivities.insert(activity.id); 0148 m_activityScores[activity.id] = activity.score; 0149 } 0150 0151 const auto controllerActivities = m_activityController->activities(); 0152 for (const QString &activityId : controllerActivities) { 0153 if (!presentActivities.contains(activityId) && m_activities.contains(activityId)) { 0154 setData(activityId, QStringLiteral("Score"), 0); 0155 } 0156 } 0157 } 0158 0159 void ActivityEngine::activityAdded(const QString &id) 0160 { 0161 insertActivity(id); 0162 setData(QStringLiteral("Status"), QStringLiteral("Running"), m_runningActivities); 0163 } 0164 0165 void ActivityEngine::activityRemoved(const QString &id) 0166 { 0167 removeSource(id); 0168 KActivities::Info *activity = m_activities.take(id); 0169 if (activity) { 0170 delete activity; 0171 } 0172 m_runningActivities.removeAll(id); 0173 setData(QStringLiteral("Status"), QStringLiteral("Running"), m_runningActivities); 0174 } 0175 0176 void ActivityEngine::currentActivityChanged(const QString &id) 0177 { 0178 setData(m_currentActivity, QStringLiteral("Current"), false); 0179 m_currentActivity = id; 0180 setData(id, QStringLiteral("Current"), true); 0181 setData(QStringLiteral("Status"), QStringLiteral("Current"), id); 0182 } 0183 0184 void ActivityEngine::activityDataChanged() 0185 { 0186 KActivities::Info *activity = qobject_cast<KActivities::Info *>(sender()); 0187 if (!activity) { 0188 return; 0189 } 0190 setData(activity->id(), QStringLiteral("Name"), activity->name()); 0191 setData(activity->id(), QStringLiteral("Icon"), activity->icon()); 0192 setData(activity->id(), QStringLiteral("Current"), m_currentActivity == activity->id()); 0193 setData(activity->id(), QStringLiteral("Score"), m_activityScores.value(activity->id())); 0194 } 0195 0196 void ActivityEngine::activityStateChanged() 0197 { 0198 KActivities::Info *activity = qobject_cast<KActivities::Info *>(sender()); 0199 const QString id = activity->id(); 0200 if (!activity) { 0201 return; 0202 } 0203 QString state; 0204 switch (activity->state()) { 0205 case KActivities::Info::Running: 0206 state = QLatin1String("Running"); 0207 break; 0208 case KActivities::Info::Starting: 0209 state = QLatin1String("Starting"); 0210 break; 0211 case KActivities::Info::Stopping: 0212 state = QLatin1String("Stopping"); 0213 break; 0214 case KActivities::Info::Stopped: 0215 state = QLatin1String("Stopped"); 0216 break; 0217 case KActivities::Info::Invalid: 0218 default: 0219 state = QLatin1String("Invalid"); 0220 } 0221 setData(id, QStringLiteral("State"), state); 0222 0223 if (activity->state() == KActivities::Info::Running) { 0224 if (!m_runningActivities.contains(id)) { 0225 m_runningActivities << id; 0226 } 0227 } else { 0228 m_runningActivities.removeAll(id); 0229 } 0230 0231 setData(QStringLiteral("Status"), QStringLiteral("Running"), m_runningActivities); 0232 } 0233 0234 Plasma5Support::Service *ActivityEngine::serviceForSource(const QString &source) 0235 { 0236 // FIXME validate the name 0237 ActivityService *service = new ActivityService(m_activityController, source); 0238 service->setParent(this); 0239 return service; 0240 } 0241 0242 K_PLUGIN_CLASS_WITH_JSON(ActivityEngine, "plasma-dataengine-activities.json") 0243 0244 #include "activityengine.moc"