1 /*
2 SPDX-FileCopyrightText: 2019 David Edmundson <davidedmundson@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 #include "extended_process_list.h"
7 #include "kcoreaddons_version.h"
8
9 #include <KLocalizedString>
10 #include <KPluginFactory>
11 #include <KPluginLoader>
12 #include <KPluginMetaData>
13 #include <KUser>
14
15 #include "process.h"
16 #include "process_attribute.h"
17 #include "process_data_provider.h"
18 #include "processcore_debug.h"
19
20 using namespace KSysGuard;
21
22 class Q_DECL_HIDDEN ExtendedProcesses::Private
23 {
24 public:
25 Private(ExtendedProcesses *q);
26 void loadPlugins();
27
28 ExtendedProcesses *q;
29 QVector<ProcessAttribute *> m_coreAttributes;
30 QVector<ProcessDataProvider *> m_providers;
31 QHash<K_UID, KUser> m_userCache;
32 };
33
34 enum GroupPolicy { Accumulate, Average, ForwardFirstEntry };
35
36 template<class T>
37 class ProcessSensor : public KSysGuard::ProcessAttribute
38 {
39 public:
ProcessSensor(ExtendedProcesses * parent,const QString & id,const QString & name,std::function<T (KSysGuard::Process *)> extractFunc,KSysGuard::Process::Change changeFlag=KSysGuard::Process::Nothing,GroupPolicy groupPolicy=Accumulate)40 ProcessSensor(ExtendedProcesses *parent,
41 const QString &id,
42 const QString &name,
43 std::function<T(KSysGuard::Process *)> extractFunc,
44 KSysGuard::Process::Change changeFlag = KSysGuard::Process::Nothing,
45 GroupPolicy groupPolicy = Accumulate)
46 : KSysGuard::ProcessAttribute(id, name, parent)
47 , m_extractFunc(extractFunc)
48 , m_changeFlag(changeFlag)
49 , m_groupPolicy(groupPolicy)
50 {
51 if (m_changeFlag != 0) {
52 connect(parent, &ExtendedProcesses::processChanged, this, [this](KSysGuard::Process *process) {
53 if (!process->changes().testFlag(m_changeFlag)) {
54 return;
55 }
56 emit dataChanged(process);
57 });
58 }
59 }
60
data(KSysGuard::Process * process) const61 QVariant data(KSysGuard::Process *process) const override
62 {
63 return QVariant::fromValue(m_extractFunc(process));
64 }
65
66 private:
67 std::function<T(KSysGuard::Process *)> m_extractFunc;
68 KSysGuard::Process::Change m_changeFlag;
69 GroupPolicy m_groupPolicy = Accumulate;
70 };
71
Private(ExtendedProcesses * _q)72 ExtendedProcesses::Private::Private(ExtendedProcesses *_q)
73 : q(_q)
74 {
75 }
76
ExtendedProcesses(QObject * parent)77 ExtendedProcesses::ExtendedProcesses(QObject *parent)
78 : Processes(QString(), parent)
79 , d(new Private(this))
80 {
81 d->loadPlugins();
82
83 auto pidSensor =
84 new ProcessSensor<qlonglong>(this, QStringLiteral("pid"), i18n("PID"), &KSysGuard::Process::pid, KSysGuard::Process::Status, ForwardFirstEntry);
85 pidSensor->setDescription(i18n("The unique Process ID that identifies this process."));
86 d->m_coreAttributes << pidSensor;
87
88 auto parentPidSensor = new ProcessSensor<qlonglong>(this,
89 QStringLiteral("parentPid"),
90 i18n("Parent PID"),
91 &KSysGuard::Process::parentPid,
92 Process::Nothing,
93 ForwardFirstEntry);
94 d->m_coreAttributes << parentPidSensor;
95
96 auto loginSensor =
97 new ProcessSensor<QString>(this, QStringLiteral("login"), i18n("Login"), &KSysGuard::Process::login, KSysGuard::Process::Login, ForwardFirstEntry);
98 loginSensor->setDescription(i18n("The user who owns this process."));
99 d->m_coreAttributes << loginSensor;
100
101 auto uidSensor =
102 new ProcessSensor<qlonglong>(this, QStringLiteral("uid"), i18n("UID"), &KSysGuard::Process::uid, KSysGuard::Process::Uids, ForwardFirstEntry);
103 d->m_coreAttributes << uidSensor;
104
105 auto userNameSensor = new ProcessSensor<QString>(
106 this,
107 QStringLiteral("username"),
108 i18n("Username"),
109 [this](KSysGuard::Process *p) {
110 const K_UID uid = p->uid();
111 auto userIt = d->m_userCache.find(uid);
112 if (userIt == d->m_userCache.end()) {
113 userIt = d->m_userCache.insert(uid, KUser(uid));
114 }
115 return userIt->loginName();
116 },
117 KSysGuard::Process::Uids,
118 ForwardFirstEntry);
119 d->m_coreAttributes << userNameSensor;
120
121 auto canUserLoginSensor = new ProcessSensor<bool>(
122 this,
123 QStringLiteral("canUserLogin"),
124 i18n("Can Login"),
125 [this](KSysGuard::Process *p) {
126 const K_UID uid = p->uid();
127 if (uid == 65534) { // special value meaning nobody
128 return false;
129 }
130 auto userIt = d->m_userCache.find(uid);
131 if (userIt == d->m_userCache.end()) {
132 userIt = d->m_userCache.insert(uid, KUser(uid));
133 }
134
135 if (!userIt->isValid()) {
136 // For some reason the user isn't recognised. This might happen under certain security situations.
137 // Just return true to be safe
138 return true;
139 }
140 const QString shell = userIt->shell();
141 if (shell == QLatin1String("/bin/false")) { // FIXME - add in any other shells it could be for false
142 return false;
143 }
144 return true;
145 },
146 KSysGuard::Process::Uids,
147 ForwardFirstEntry);
148 d->m_coreAttributes << canUserLoginSensor;
149
150 auto euidSensor =
151 new ProcessSensor<qlonglong>(this, QStringLiteral("euid"), i18n("EUID"), &KSysGuard::Process::euid, KSysGuard::Process::Uids, ForwardFirstEntry);
152 d->m_coreAttributes << euidSensor;
153
154 auto suidSensor =
155 new ProcessSensor<qlonglong>(this, QStringLiteral("suid"), i18n("suid"), &KSysGuard::Process::suid, KSysGuard::Process::Uids, ForwardFirstEntry);
156 d->m_coreAttributes << suidSensor;
157
158 auto fsuidSensor =
159 new ProcessSensor<qlonglong>(this, QStringLiteral("fsuid"), i18n("fsuid"), &KSysGuard::Process::fsuid, KSysGuard::Process::Uids, ForwardFirstEntry);
160 d->m_coreAttributes << fsuidSensor;
161
162 auto gidSensor =
163 new ProcessSensor<qlonglong>(this, QStringLiteral("gid"), i18n("gid"), &KSysGuard::Process::gid, KSysGuard::Process::Gids, ForwardFirstEntry);
164 d->m_coreAttributes << gidSensor;
165
166 auto egidSensor =
167 new ProcessSensor<qlonglong>(this, QStringLiteral("egid"), i18n("egid"), &KSysGuard::Process::egid, KSysGuard::Process::Gids, ForwardFirstEntry);
168 d->m_coreAttributes << egidSensor;
169
170 auto sgidSensor =
171 new ProcessSensor<qlonglong>(this, QStringLiteral("sgid"), i18n("sgid"), &KSysGuard::Process::sgid, KSysGuard::Process::Gids, ForwardFirstEntry);
172 d->m_coreAttributes << sgidSensor;
173
174 auto fsgidSensor =
175 new ProcessSensor<qlonglong>(this, QStringLiteral("fsgid"), i18n("fsgid"), &KSysGuard::Process::fsgid, KSysGuard::Process::Gids, ForwardFirstEntry);
176 d->m_coreAttributes << fsgidSensor;
177
178 auto tracerpidSensor = new ProcessSensor<qlonglong>(this,
179 QStringLiteral("tracerpid"),
180 i18n("Tracer Pid"),
181 &KSysGuard::Process::tracerpid,
182 Process::Nothing,
183 ForwardFirstEntry);
184 d->m_coreAttributes << tracerpidSensor;
185
186 auto ttySensor =
187 new ProcessSensor<QByteArray>(this, QStringLiteral("tty"), i18n("tty"), &KSysGuard::Process::tty, KSysGuard::Process::Tty, ForwardFirstEntry);
188 ttySensor->setDescription(i18n("The controlling terminal on which this process is running."));
189 d->m_coreAttributes << ttySensor;
190
191 auto userTimeSensor = new ProcessSensor<qlonglong>(this, QStringLiteral("userTime"), i18n("User Time"), &KSysGuard::Process::userTime);
192 d->m_coreAttributes << userTimeSensor;
193
194 auto sysTimeSensor = new ProcessSensor<qlonglong>(this, QStringLiteral("sysTime"), i18n("System Time"), &KSysGuard::Process::sysTime);
195 sysTimeSensor->setUnit(KSysGuard::UnitSecond);
196 d->m_coreAttributes << sysTimeSensor;
197
198 auto timeSensor = new ProcessSensor<qlonglong>(
199 this,
200 QStringLiteral("totalUsage"),
201 i18n("Total Time"),
202 [](KSysGuard::Process *p) {
203 return p->userTime() + p->sysTime();
204 },
205 KSysGuard::Process::Usage);
206 timeSensor->setShortName(i18n("Time"));
207 timeSensor->setUnit(KSysGuard::UnitSecond);
208 timeSensor->setDescription(i18n("The total user and system time that this process has been running for"));
209 d->m_coreAttributes << timeSensor;
210
211 auto startTimeSensor = new ProcessSensor<qlonglong>(this,
212 QStringLiteral("startTime"),
213 i18n("Start Time"),
214 &KSysGuard::Process::startTime,
215 Process::Nothing,
216 ForwardFirstEntry); // Is this correct for apps?
217 startTimeSensor->setDescription(i18n("The elapsed time since the process was started."));
218 startTimeSensor->setUnit(KSysGuard::UnitTime);
219 d->m_coreAttributes << startTimeSensor;
220
221 const int maximumCpuPercent = 100 * numberProcessorCores();
222
223 auto userUsageSensor =
224 new ProcessSensor<int>(this, QStringLiteral("userUsage"), i18n("User CPU Usage"), &KSysGuard::Process::userUsage, KSysGuard::Process::Usage);
225 userUsageSensor->setShortName(i18n("User CPU"));
226 userUsageSensor->setMin(0);
227 userUsageSensor->setMax(maximumCpuPercent);
228 userUsageSensor->setUnit(KSysGuard::UnitPercent);
229 d->m_coreAttributes << userUsageSensor;
230
231 auto sysUsageSensor =
232 new ProcessSensor<int>(this, QStringLiteral("sysUsage"), i18n("System CPU Usage"), &KSysGuard::Process::sysUsage, KSysGuard::Process::Usage);
233 sysUsageSensor->setShortName(i18n("System CPU"));
234 sysUsageSensor->setMin(0);
235 sysUsageSensor->setMax(maximumCpuPercent);
236 sysUsageSensor->setUnit(KSysGuard::UnitPercent);
237 d->m_coreAttributes << sysUsageSensor;
238
239 auto usageSensor = new ProcessSensor<int>(
240 this,
241 QStringLiteral("usage"),
242 i18n("Total CPU Usage"),
243 [](KSysGuard::Process *p) {
244 return p->userUsage() + p->sysUsage();
245 },
246 KSysGuard::Process::Usage,
247 Accumulate);
248 usageSensor->setShortName(i18n("CPU"));
249 usageSensor->setMin(0);
250 usageSensor->setMax(maximumCpuPercent);
251 usageSensor->setUnit(KSysGuard::UnitPercent);
252 usageSensor->setDescription(i18n("The current total CPU usage of the process."));
253 d->m_coreAttributes << usageSensor;
254
255 auto totalUserUsageSensor = new ProcessSensor<int>(this,
256 QStringLiteral("totalUserUsage"),
257 i18n("Group User CPU Usage"),
258 &KSysGuard::Process::totalUserUsage,
259 KSysGuard::Process::TotalUsage,
260 Average);
261 totalUserUsageSensor->setDescription(i18n("The amount of userspace CPU used by this process and all its children."));
262 totalUserUsageSensor->setMin(0);
263 totalUserUsageSensor->setMax(maximumCpuPercent);
264 totalUserUsageSensor->setUnit(KSysGuard::UnitPercent);
265 d->m_coreAttributes << totalUserUsageSensor;
266
267 auto totalSysUsageSensor = new ProcessSensor<int>(this,
268 QStringLiteral("totalSysUsage"),
269 i18n("Group System CPU Usage"),
270 &KSysGuard::Process::totalSysUsage,
271 KSysGuard::Process::TotalUsage,
272 Average);
273 totalUserUsageSensor->setDescription(i18n("The amount of system CPU used by this process and all its children."));
274 totalSysUsageSensor->setMin(0);
275 totalSysUsageSensor->setMax(maximumCpuPercent);
276 totalSysUsageSensor->setUnit(KSysGuard::UnitPercent);
277 d->m_coreAttributes << totalSysUsageSensor;
278
279 auto totalUsageSensor = new ProcessSensor<int>(
280 this,
281 QStringLiteral("totalUsage"),
282 i18n("Group Total CPU Usage"),
283 [](KSysGuard::Process *p) {
284 return p->totalUserUsage() + p->totalSysUsage();
285 },
286 KSysGuard::Process::TotalUsage,
287 Average);
288 totalUsageSensor->setShortName(i18n("Group CPU"));
289 totalUserUsageSensor->setDescription(i18n("The total amount of CPU used by this process and all its children."));
290 totalUsageSensor->setMin(0);
291 totalUsageSensor->setMax(maximumCpuPercent);
292 totalUsageSensor->setUnit(KSysGuard::UnitPercent);
293 d->m_coreAttributes << totalUsageSensor;
294
295 auto niceLevelSensor =
296 new ProcessSensor<int>(this, QStringLiteral("niceLevel"), i18n("Nice Level"), &KSysGuard::Process::niceLevel, KSysGuard::Process::NiceLevels);
297 niceLevelSensor->setDescription(i18n(
298 "The priority with which this process is being run. For the normal scheduler, this ranges from 19 (very nice, least priority) to -19 (top priority)."));
299 d->m_coreAttributes << niceLevelSensor;
300
301 auto schedulerSensor =
302 new ProcessSensor<uint>(this, QStringLiteral("scheduler"), i18n("Scheduler"), &KSysGuard::Process::scheduler, KSysGuard::Process::NiceLevels);
303 d->m_coreAttributes << schedulerSensor;
304
305 auto ioPriorityClassSensor = new ProcessSensor<uint>(this,
306 QStringLiteral("ioPriorityClass"),
307 i18n("IO Priority Class"),
308 &KSysGuard::Process::ioPriorityClass,
309 KSysGuard::Process::NiceLevels);
310 d->m_coreAttributes << ioPriorityClassSensor;
311
312 auto ioniceLevelSensor =
313 new ProcessSensor<int>(this, QStringLiteral("ioniceLevel"), i18n("IO Nice Level"), &KSysGuard::Process::ioniceLevel, KSysGuard::Process::NiceLevels);
314 ioniceLevelSensor->setUnit(KSysGuard::UnitNone);
315 d->m_coreAttributes << ioniceLevelSensor;
316
317 auto vmSizeSensor = new ProcessSensor<qlonglong>(this, QStringLiteral("vmSize"), i18n("VM Size"), &KSysGuard::Process::vmSize, KSysGuard::Process::VmSize);
318 vmSizeSensor->setUnit(KSysGuard::UnitKiloByte);
319 vmSizeSensor->setMin(0);
320 vmSizeSensor->setMax(totalPhysicalMemory());
321 vmSizeSensor->setDescription(
322 i18n("This is the amount of virtual memory space that the process is using, included shared libraries, graphics memory, files on disk, and so on. This "
323 "number is almost meaningless."));
324 d->m_coreAttributes << vmSizeSensor;
325
326 auto vmRSSSensor =
327 new ProcessSensor<qlonglong>(this, QStringLiteral("vmRSS"), i18n("RSS Memory Usage"), &KSysGuard::Process::vmRSS, KSysGuard::Process::VmRSS);
328 vmRSSSensor->setUnit(KSysGuard::UnitKiloByte);
329 vmRSSSensor->setMin(0);
330 vmRSSSensor->setMax(totalPhysicalMemory());
331 vmRSSSensor->setDescription(
332 i18n("This is the amount of physical memory that this process is using and includes the amount of memory used by shared libraries."));
333
334 auto vmURSSSensor =
335 new ProcessSensor<qlonglong>(this, QStringLiteral("vmURSS"), i18n("Private Memory Usage"), &KSysGuard::Process::vmURSS, KSysGuard::Process::VmURSS);
336 vmURSSSensor->setUnit(KSysGuard::UnitKiloByte);
337 vmURSSSensor->setShortName(i18n("Private"));
338 vmURSSSensor->setMin(0);
339 vmURSSSensor->setMax(totalPhysicalMemory());
340 vmURSSSensor->setDescription(
341 i18n("This is the amount of physical memory that this process is using by itself, and approximates the Private memory usage of the process.<br>It does "
342 "not include any swapped out memory, nor the code size of its shared libraries."));
343 d->m_coreAttributes << vmURSSSensor;
344
345 auto sharedMemorySensor = new ProcessSensor<qlonglong>(
346 this,
347 QStringLiteral("vmShared"),
348 i18n("Shared Memory Usage"),
349 [](KSysGuard::Process *p) -> qlonglong {
350 if (p->vmRSS() - p->vmURSS() < 0 || p->vmURSS() == -1) {
351 return 0;
352 }
353 return (qlonglong)(p->vmRSS() - p->vmURSS());
354 },
355 KSysGuard::Process::VmRSS);
356 d->m_coreAttributes << sharedMemorySensor;
357 sharedMemorySensor->setShortName(i18n("Shared"));
358 sharedMemorySensor->setDescription(
359 i18n("This is approximately the amount of real physical memory that this process's shared libraries are using.<br>This memory is shared among all "
360 "processes that use this library."));
361 sharedMemorySensor->setUnit(KSysGuard::UnitKiloByte);
362 sharedMemorySensor->setMin(0);
363 sharedMemorySensor->setMax(totalPhysicalMemory());
364
365 auto vmPSSSensor = new ProcessSensor<qlonglong>(this, QStringLiteral("vmPSS"), i18n("Memory Usage"), &KSysGuard::Process::vmPSS, KSysGuard::Process::VmPSS);
366 vmPSSSensor->setShortName(i18n("Memory"));
367 vmPSSSensor->setUnit(KSysGuard::UnitKiloByte);
368 vmPSSSensor->setMin(0);
369 vmPSSSensor->setMax(totalPhysicalMemory());
370 vmPSSSensor->setRequiredUpdateFlags(Processes::Smaps);
371 vmPSSSensor->setDescription(
372 i18n("This is an approximation of the real amount of physical memory that this process is using. It is calculated by dividing the process' shared "
373 "memory usage by the amount of processes sharing that memory, then adding the process' private memory."));
374 d->m_coreAttributes << vmPSSSensor;
375
376 auto nameSensor =
377 new ProcessSensor<QString>(this, QStringLiteral("name"), i18n("Name"), &KSysGuard::Process::name, KSysGuard::Process::Name, ForwardFirstEntry);
378 nameSensor->setDescription(i18n("The process name."));
379 d->m_coreAttributes << nameSensor;
380
381 auto commandSensor = new ProcessSensor<QString>(this,
382 QStringLiteral("command"),
383 i18n("Command"),
384 &KSysGuard::Process::command,
385 KSysGuard::Process::Command,
386 ForwardFirstEntry);
387 commandSensor->setDescription(i18n("The command with which this process was launched."));
388 d->m_coreAttributes << commandSensor;
389
390 auto statusSensor =
391 new ProcessSensor<QString>(this, QStringLiteral("status"), i18n("Status"), &KSysGuard::Process::translatedStatus, KSysGuard::Process::Status);
392 d->m_coreAttributes << statusSensor;
393
394 auto ioCharactersReadSensor = new ProcessSensor<qlonglong>(this,
395 QStringLiteral("ioCharactersRead"),
396 i18n("IO Characters Read"),
397 &KSysGuard::Process::ioCharactersRead,
398 KSysGuard::Process::IO);
399 ioCharactersReadSensor->setUnit(KSysGuard::UnitByte);
400 ioCharactersReadSensor->setRequiredUpdateFlags(Processes::IOStatistics);
401 d->m_coreAttributes << ioCharactersReadSensor;
402
403 auto ioCharactersWrittenSensor = new ProcessSensor<qlonglong>(this,
404 QStringLiteral("ioCharactersWritten"),
405 i18n("IO Characters Written"),
406 &KSysGuard::Process::ioCharactersWritten,
407 KSysGuard::Process::IO);
408 ioCharactersWrittenSensor->setUnit(KSysGuard::UnitByte);
409 ioCharactersWrittenSensor->setRequiredUpdateFlags(Processes::IOStatistics);
410 d->m_coreAttributes << ioCharactersWrittenSensor;
411
412 auto ioReadSyscallsSensor = new ProcessSensor<qlonglong>(this,
413 QStringLiteral("ioReadSyscalls"),
414 i18n("IO Read Syscalls"),
415 &KSysGuard::Process::ioReadSyscalls,
416 KSysGuard::Process::IO);
417 ioReadSyscallsSensor->setUnit(KSysGuard::UnitRate);
418 ioReadSyscallsSensor->setRequiredUpdateFlags(Processes::IOStatistics);
419 d->m_coreAttributes << ioReadSyscallsSensor;
420
421 auto ioReadSyscallsRateSensor = new ProcessSensor<qlonglong>(this,
422 QStringLiteral("ioReadSyscallsRate"),
423 i18n("IO Read Syscalls Rate"),
424 &KSysGuard::Process::ioReadSyscallsRate,
425 KSysGuard::Process::IO);
426 ioReadSyscallsRateSensor->setUnit(KSysGuard::UnitRate);
427 ioReadSyscallsRateSensor->setRequiredUpdateFlags(Processes::IOStatistics);
428 d->m_coreAttributes << ioReadSyscallsSensor;
429
430 auto ioWriteSyscallsSensor = new ProcessSensor<qlonglong>(this,
431 QStringLiteral("ioWriteSyscalls"),
432 i18n("IO Write Syscalls"),
433 &KSysGuard::Process::ioWriteSyscalls,
434 KSysGuard::Process::IO);
435 ioWriteSyscallsSensor->setUnit(KSysGuard::UnitRate);
436 ioWriteSyscallsSensor->setRequiredUpdateFlags(Processes::IOStatistics);
437 d->m_coreAttributes << ioWriteSyscallsSensor;
438
439 auto ioWriteSyscallsRateSensor = new ProcessSensor<qlonglong>(this,
440 QStringLiteral("ioReadSyscallsRate"),
441 i18n("IO Write Syscalls Rate"),
442 &KSysGuard::Process::ioWriteSyscallsRate,
443 KSysGuard::Process::IO);
444 ioWriteSyscallsRateSensor->setUnit(KSysGuard::UnitRate);
445 ioWriteSyscallsRateSensor->setRequiredUpdateFlags(Processes::IOStatistics);
446 d->m_coreAttributes << ioWriteSyscallsRateSensor;
447
448 auto ioCharactersActuallyReadSensor = new ProcessSensor<qlonglong>(this,
449 QStringLiteral("ioCharactersActuallyRead"),
450 i18n("IO Characters Actually Read"),
451 &KSysGuard::Process::ioCharactersActuallyRead,
452 KSysGuard::Process::IO);
453 ioCharactersActuallyReadSensor->setUnit(KSysGuard::UnitByte);
454 ioCharactersActuallyReadSensor->setRequiredUpdateFlags(Processes::IOStatistics);
455 d->m_coreAttributes << ioCharactersActuallyReadSensor;
456
457 auto ioCharactersReadRateSensor = new ProcessSensor<qlonglong>(this,
458 QStringLiteral("ioCharactersReadRate"),
459 i18n("IO Characters Read Rate"),
460 &KSysGuard::Process::ioCharactersReadRate,
461 KSysGuard::Process::IO);
462 ioCharactersReadRateSensor->setDescription(i18n("The read rate for all of a process' IO, including disk cache and other nonphysical IO."));
463 ioCharactersReadRateSensor->setUnit(KSysGuard::UnitByteRate);
464 ioCharactersReadRateSensor->setRequiredUpdateFlags(Processes::IOStatistics);
465 d->m_coreAttributes << ioCharactersReadRateSensor;
466
467 auto ioCharactersWrittenRateSensor = new ProcessSensor<qlonglong>(this,
468 QStringLiteral("ioCharactersWrittenRate"),
469 i18n("IO Characters Written Rate"),
470 &KSysGuard::Process::ioCharactersWrittenRate,
471 KSysGuard::Process::IO);
472 ioCharactersWrittenRateSensor->setDescription(i18n("The write rate for all of a process' IO, including disk cache and other nonphysical IO."));
473 ioCharactersWrittenRateSensor->setUnit(KSysGuard::UnitByteRate);
474 ioCharactersWrittenRateSensor->setRequiredUpdateFlags(Processes::IOStatistics);
475 d->m_coreAttributes << ioCharactersWrittenRateSensor;
476
477 auto ioCharactersActuallyReadRateSensor = new ProcessSensor<qlonglong>(this,
478 QStringLiteral("ioCharactersActuallyReadRate"),
479 i18n("Disk Read Rate"),
480 &KSysGuard::Process::ioCharactersActuallyReadRate,
481 KSysGuard::Process::IO);
482 ioCharactersActuallyReadRateSensor->setUnit(KSysGuard::UnitByteRate);
483 ioCharactersActuallyReadRateSensor->setShortName(i18n("Read"));
484 ioCharactersActuallyReadRateSensor->setDescription(i18n("The rate of data being read from disk."));
485 ioCharactersActuallyReadRateSensor->setRequiredUpdateFlags(Processes::IOStatistics);
486 d->m_coreAttributes << ioCharactersActuallyReadRateSensor;
487
488 auto ioCharactersActuallyWrittenRateSensor = new ProcessSensor<qlonglong>(this,
489 QStringLiteral("ioCharactersActuallyWrittenRate"),
490 i18n("Disk Write Rate"),
491 &KSysGuard::Process::ioCharactersActuallyWrittenRate,
492 KSysGuard::Process::IO);
493 ioCharactersActuallyWrittenRateSensor->setUnit(KSysGuard::UnitByteRate);
494 ioCharactersActuallyWrittenRateSensor->setShortName(i18n("Write"));
495 ioCharactersActuallyWrittenRateSensor->setDescription(i18n("The rate of data being written to the disk."));
496 ioCharactersActuallyWrittenRateSensor->setRequiredUpdateFlags(Processes::IOStatistics);
497 d->m_coreAttributes << ioCharactersActuallyWrittenRateSensor;
498
499 auto numThreadsSensor = new ProcessSensor<int>(this,
500 QStringLiteral("numThreads"),
501 i18n("Threads"),
502 &KSysGuard::Process::numThreads,
503 KSysGuard::Process::NumThreads,
504 ForwardFirstEntry);
505 d->m_coreAttributes << numThreadsSensor;
506
507 connect(this, &KSysGuard::Processes::beginRemoveProcess, this, [this](KSysGuard::Process *process) {
508 const auto attrs = attributes();
509 for (auto a : attrs) {
510 a->clearData(process);
511 }
512 });
513
514 connect(this, &KSysGuard::Processes::updated, this, [this]() {
515 for (auto p : qAsConst(d->m_providers)) {
516 if (p->enabled()) {
517 p->update();
518 }
519 }
520 });
521 }
522
~ExtendedProcesses()523 ExtendedProcesses::~ExtendedProcesses()
524 {
525 }
526
attributes() const527 QVector<ProcessAttribute *> ExtendedProcesses::attributes() const
528 {
529 return d->m_coreAttributes + extendedAttributes();
530 }
531
extendedAttributes() const532 QVector<ProcessAttribute *> ExtendedProcesses::extendedAttributes() const
533 {
534 QVector<ProcessAttribute *> rc;
535 for (auto p : qAsConst(d->m_providers)) {
536 rc << p->attributes();
537 }
538 return rc;
539 }
540
loadPlugins()541 void ExtendedProcesses::Private::loadPlugins()
542 {
543 #if KCOREADDONS_VERSION < QT_VERSION_CHECK(5, 86, 0)
544 const QVector<KPluginMetaData> listMetaData = KPluginLoader::findPlugins(QStringLiteral("ksysguard/process"));
545 #else
546 const QVector<KPluginMetaData> listMetaData = KPluginMetaData::findPlugins(QStringLiteral("ksysguard/process"));
547 #endif
548 // instantiate all plugins
549 for (const auto &pluginMetaData : listMetaData) {
550 qCDebug(LIBKSYSGUARD_PROCESSCORE) << "loading plugin" << pluginMetaData.name();
551 auto factory = qobject_cast<KPluginFactory *>(pluginMetaData.instantiate());
552 if (!factory) {
553 qCCritical(LIBKSYSGUARD_PROCESSCORE) << "failed to load plugin factory" << pluginMetaData.name();
554 continue;
555 }
556 ProcessDataProvider *provider = factory->create<ProcessDataProvider>(q);
557 if (!provider) {
558 qCCritical(LIBKSYSGUARD_PROCESSCORE) << "failed to instantiate ProcessDataProvider" << pluginMetaData.name();
559 continue;
560 }
561 m_providers << provider;
562 }
563 }
564
instance()565 QSharedPointer<ExtendedProcesses> ExtendedProcesses::instance()
566 {
567 static QWeakPointer<ExtendedProcesses> instance;
568 auto processes = instance.lock();
569 if (!processes) {
570 processes = QSharedPointer<ExtendedProcesses>(new ExtendedProcesses, [](ExtendedProcesses *p) {
571 delete p;
572 });
573 instance = processes;
574 }
575 return processes;
576 }
577