Changeset View
Changeset View
Standalone View
Standalone View
applets/systemmonitor/systemmonitor/systemmonitor.cpp
- This file was added.
1 | /*************************************************************************** | ||||
---|---|---|---|---|---|
2 | * Copyright (C) 2019 Marco Martin <mart@kde.org> * | ||||
3 | * * | ||||
4 | * This program is free software; you can redistribute it and/or modify * | ||||
5 | * it under the terms of the GNU General Public License as published by * | ||||
6 | * the Free Software Foundation; either version 2 of the License, or * | ||||
7 | * (at your option) any later version. * | ||||
8 | * * | ||||
9 | * This program is distributed in the hope that it will be useful, * | ||||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||||
12 | * GNU General Public License for more details. * | ||||
13 | * * | ||||
14 | * You should have received a copy of the GNU General Public License * | ||||
15 | * along with this program; if not, write to the * | ||||
16 | * Free Software Foundation, Inc., * | ||||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * | ||||
18 | ***************************************************************************/ | ||||
19 | | ||||
20 | #include "systemmonitor.h" | ||||
21 | | ||||
22 | #include <QtQml> | ||||
23 | #include <QDebug> | ||||
24 | #include <QQuickItem> | ||||
25 | #include <QQuickWindow> | ||||
26 | #include <QStandardPaths> | ||||
27 | #include <QWindow> | ||||
28 | | ||||
29 | #include <sensors/SensorQuery.h> | ||||
30 | | ||||
31 | #include <KConfigLoader> | ||||
32 | #include <KLocalizedString> | ||||
33 | #include <KPackage/PackageLoader> | ||||
34 | #include <KDeclarative/ConfigPropertyMap> | ||||
35 | | ||||
36 | #include <KNewPasswordDialog> | ||||
37 | | ||||
38 | | ||||
39 | FacesModel::FacesModel(QObject *parent) | ||||
40 | : QStandardItemModel(parent) | ||||
41 | {} | ||||
42 | | ||||
43 | void FacesModel::load() | ||||
44 | { | ||||
45 | clear(); | ||||
46 | | ||||
47 | auto list = KPackage::PackageLoader::self()->listPackages(QStringLiteral("Plasma/SensorApplet")); | ||||
48 | // NOTE: This will diable completely the internal in-memory cache | ||||
49 | KPackage::Package p; | ||||
50 | p.install(QString(), QString()); | ||||
51 | | ||||
52 | for (auto plugin : list) { | ||||
53 | QStandardItem *item = new QStandardItem(plugin.name()); | ||||
54 | item->setData(plugin.name(), FacesModel::ModelDataRole); | ||||
55 | item->setData(plugin.pluginId(), FacesModel::PluginIdRole); | ||||
56 | appendRow(item); | ||||
57 | } | ||||
58 | } | ||||
59 | | ||||
60 | QString FacesModel::pluginId(int row) | ||||
61 | { | ||||
62 | return data(index(row, 0), PluginIdRole).toString(); | ||||
63 | } | ||||
64 | | ||||
65 | QHash<int, QByteArray> FacesModel::roleNames() const | ||||
66 | { | ||||
67 | QHash<int, QByteArray> roles = QAbstractItemModel::roleNames(); | ||||
68 | | ||||
69 | roles[ModelDataRole] = "modelData"; | ||||
70 | roles[PluginIdRole] = "pluginId"; | ||||
71 | return roles; | ||||
72 | } | ||||
73 | | ||||
74 | PresetsModel::PresetsModel(QObject *parent) | ||||
75 | : QStandardItemModel(parent) | ||||
76 | {} | ||||
77 | | ||||
78 | QString PresetsModel::pluginId(int row) const | ||||
79 | { | ||||
80 | return data(index(row, 0), PluginIdRole).toString(); | ||||
81 | } | ||||
82 | | ||||
83 | QHash<int, QByteArray> PresetsModel::roleNames() const | ||||
84 | { | ||||
85 | QHash<int, QByteArray> roles = QAbstractItemModel::roleNames(); | ||||
86 | | ||||
87 | roles[ModelDataRole] = "modelData"; | ||||
88 | roles[PluginIdRole] = "pluginId"; | ||||
89 | roles[ConfigRole] = "config"; | ||||
90 | roles[WritableRole] = "writable"; | ||||
91 | return roles; | ||||
92 | } | ||||
93 | | ||||
94 | SystemMonitor::SystemMonitor(QObject *parent, const QVariantList &args) | ||||
95 | : Plasma::Applet(parent, args) | ||||
96 | { | ||||
97 | setHasConfigurationInterface(true); | ||||
98 | | ||||
99 | m_facePackage = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/SensorApplet"), QStringLiteral("org.kde.ksysguard.linechart")); | ||||
100 | | ||||
101 | //Don't set the preset right now as we can't write on the config here because we don't have a Corona yet | ||||
102 | if (args.count() > 2 && args.mid(3).length() > 0) { | ||||
103 | const QString preset = args.mid(3).first().toString(); | ||||
104 | if (preset.length() > 0) { | ||||
105 | m_pendingStartupPreset = preset; | ||||
106 | } | ||||
107 | } | ||||
108 | } | ||||
109 | | ||||
110 | SystemMonitor::~SystemMonitor() | ||||
111 | = default; | ||||
112 | | ||||
113 | void SystemMonitor::init() | ||||
114 | { | ||||
115 | configChanged(); | ||||
116 | | ||||
117 | // NOTE: taking the pluginId this way, we take it from the child applet (cpu monitor, memory, whatever) rather than the parent fallback applet (systemmonitor) | ||||
118 | const QString pluginId = KPluginMetaData(kPackage().path() + QStringLiteral("metadata.desktop")).pluginId(); | ||||
119 | | ||||
120 | if (!m_pendingStartupPreset.isNull()) { | ||||
121 | setCurrentPreset(m_pendingStartupPreset); | ||||
122 | } else { | ||||
123 | //Take it from the config, which is *not* accessible from plasmoid.config as is not in config.xml | ||||
124 | const QString preset = config().readEntry("CurrentPreset", pluginId); | ||||
125 | setCurrentPreset(preset); | ||||
126 | if (preset.isEmpty()) { | ||||
127 | resetToCustomPreset(); | ||||
128 | emit currentPresetChanged(); | ||||
129 | } | ||||
130 | } | ||||
131 | } | ||||
132 | | ||||
133 | void SystemMonitor::configChanged() | ||||
134 | { | ||||
135 | setFace(configScheme()->property("chartFace").toString()); | ||||
136 | } | ||||
137 | | ||||
138 | void SystemMonitor::setFace(const QString &face) | ||||
139 | { | ||||
140 | if (face.length() == 0 || face == m_face || face.contains("..")) { | ||||
141 | return; | ||||
142 | } | ||||
143 | | ||||
144 | // Valid face? | ||||
145 | const QString oldPath = m_facePackage.path(); | ||||
146 | m_facePackage.setPath(face); | ||||
147 | if (!m_facePackage.isValid()) { | ||||
148 | m_facePackage.setPath(oldPath); | ||||
149 | return; | ||||
150 | } | ||||
151 | | ||||
152 | m_face = face; | ||||
153 | | ||||
154 | delete m_faceMetadata; | ||||
155 | m_faceMetadata = new KDesktopFile(m_facePackage.path() + QStringLiteral("metadata.desktop")); | ||||
156 | | ||||
157 | const QString xmlPath = m_facePackage.filePath("mainconfigxml"); | ||||
158 | | ||||
159 | if (!xmlPath.isEmpty()) { | ||||
160 | QFile file(xmlPath); | ||||
161 | KConfigGroup cg = config(); | ||||
162 | cg = KConfigGroup(&cg, face); | ||||
163 | if (m_faceConfiguration) { | ||||
164 | m_faceConfiguration->deleteLater(); | ||||
165 | } | ||||
166 | if (m_faceConfigLoader) { | ||||
167 | m_faceConfigLoader->deleteLater(); | ||||
168 | } | ||||
169 | m_faceConfigLoader = new KConfigLoader(cg, &file, this); | ||||
170 | m_faceConfiguration = new KDeclarative::ConfigPropertyMap(m_faceConfigLoader, this); | ||||
171 | } | ||||
172 | | ||||
173 | emit faceChanged(); | ||||
174 | } | ||||
175 | | ||||
176 | QString SystemMonitor::face() const | ||||
177 | { | ||||
178 | return m_face; | ||||
179 | } | ||||
180 | | ||||
181 | QString SystemMonitor::faceName() const | ||||
182 | { | ||||
183 | if (!m_faceMetadata) { | ||||
184 | return QString(); | ||||
185 | } | ||||
186 | return m_faceMetadata->readName(); | ||||
187 | } | ||||
188 | | ||||
189 | QString SystemMonitor::faceIcon() const | ||||
190 | { | ||||
191 | if (!m_faceMetadata) { | ||||
192 | return QString(); | ||||
193 | } | ||||
194 | return m_faceMetadata->readIcon(); | ||||
195 | } | ||||
196 | | ||||
197 | QString SystemMonitor::currentPreset() const | ||||
198 | { | ||||
199 | return m_currentPreset; | ||||
200 | } | ||||
201 | | ||||
202 | void SystemMonitor::setCurrentPreset(const QString &preset) | ||||
203 | { | ||||
204 | if (preset == m_currentPreset) { | ||||
205 | return; | ||||
206 | } | ||||
207 | | ||||
208 | m_currentPreset = preset; | ||||
209 | config().writeEntry("CurrentPreset", preset); | ||||
210 | | ||||
211 | if (preset.isEmpty()) { | ||||
212 | resetToCustomPreset(); | ||||
213 | emit currentPresetChanged(); | ||||
214 | return; | ||||
215 | } | ||||
216 | | ||||
217 | auto presetPackage = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/Applet")); | ||||
218 | | ||||
219 | presetPackage.setPath(preset); | ||||
220 | | ||||
221 | if (!presetPackage.isValid()) { | ||||
222 | return; | ||||
223 | } | ||||
224 | | ||||
225 | if (presetPackage.metadata().value(QStringLiteral("X-Plasma-RootPath")) != QStringLiteral("org.kde.plasma.systemmonitor")) { | ||||
226 | return; | ||||
227 | } | ||||
228 | | ||||
229 | disconnect(configScheme(), &KCoreConfigSkeleton::configChanged, this, &SystemMonitor::resetToCustomPresetUserConfiguring); | ||||
230 | disconnect(m_faceConfigLoader, &KCoreConfigSkeleton::configChanged, this, &SystemMonitor::resetToCustomPresetUserConfiguring); | ||||
231 | | ||||
232 | KDesktopFile df(presetPackage.path() + QStringLiteral("metadata.desktop")); | ||||
233 | KConfigGroup configGroup(df.group("Config")); | ||||
234 | | ||||
235 | // Load the title | ||||
236 | KConfigSkeletonItem *item = configScheme()->findItemByName(QStringLiteral("title")); | ||||
237 | if (item) { | ||||
238 | item->setProperty(df.readName()); | ||||
239 | configScheme()->save(); | ||||
240 | //why read? read will update KConfigSkeletonItem::mLoadedValue, | ||||
241 | //allowing a write operation to be performed next time | ||||
242 | configScheme()->read(); | ||||
243 | } | ||||
244 | | ||||
245 | //Remove the "custon" value from presets models | ||||
246 | if (m_availablePresetsModel && | ||||
247 | m_availablePresetsModel->data(m_availablePresetsModel->index(0, 0), PresetsModel::PluginIdRole).toString().isEmpty()) { | ||||
248 | m_availablePresetsModel->removeRow(0); | ||||
249 | } | ||||
250 | | ||||
251 | // Load the global config keys | ||||
252 | for (const QString &key : configGroup.keyList()) { | ||||
253 | KConfigSkeletonItem *item = configScheme()->findItemByName(key); | ||||
254 | | ||||
255 | if (item) { | ||||
256 | if (item->property().type() == QVariant::StringList) { | ||||
257 | // Special case: sensor ids or textOnlySensorIds can have wildchars that need to be expanded | ||||
258 | if (key == "sensorIds" || key == "textOnlySensorIds") { | ||||
259 | const QStringList partialEntries = configGroup.readEntry(key, QStringList()); | ||||
260 | QStringList sensors; | ||||
261 | | ||||
262 | for (const QString &id : partialEntries) { | ||||
263 | KSysGuard::SensorQuery query{id}; | ||||
264 | query.execute(); | ||||
265 | query.waitForFinished(); | ||||
266 | | ||||
267 | sensors.append(query.sensorIds()); | ||||
268 | } | ||||
269 | item->setProperty(QVariant::fromValue(sensors)); | ||||
270 | } else { | ||||
271 | item->setProperty(QVariant::fromValue(configGroup.readEntry(key, QStringList()))); | ||||
272 | } | ||||
273 | } else { | ||||
274 | const QString &value = configGroup.readEntry(key); | ||||
275 | if (key == QStringLiteral("chartFace") && value.length() > 0) { | ||||
276 | setFace(value); | ||||
277 | } | ||||
278 | item->setProperty(value); | ||||
279 | } | ||||
280 | configScheme()->save(); | ||||
281 | //why read? read will update KConfigSkeletonItem::mLoadedValue, | ||||
282 | //allowing a write operation to be performed next time | ||||
283 | configScheme()->read(); | ||||
284 | } | ||||
285 | } | ||||
286 | | ||||
287 | if (m_faceConfigLoader) { | ||||
288 | configGroup = KConfigGroup(df.group("FaceConfig")); | ||||
289 | for (const QString &key : configGroup.keyList()) { | ||||
290 | KConfigSkeletonItem *item = m_faceConfigLoader->findItemByName(key); | ||||
291 | if (item) { | ||||
292 | if (item->property().type() == QVariant::StringList) { | ||||
293 | item->setProperty(configGroup.readEntry(key, QStringList())); | ||||
294 | } else { | ||||
295 | item->setProperty(configGroup.readEntry(key)); | ||||
296 | } | ||||
297 | m_faceConfigLoader->save(); | ||||
298 | m_faceConfigLoader->read(); | ||||
299 | } | ||||
300 | } | ||||
301 | } | ||||
302 | | ||||
303 | emit currentPresetChanged(); | ||||
304 | | ||||
305 | connect(configScheme(), &KCoreConfigSkeleton::configChanged, this, &SystemMonitor::resetToCustomPresetUserConfiguring); | ||||
306 | connect(m_faceConfigLoader, &KCoreConfigSkeleton::configChanged, this, &SystemMonitor::resetToCustomPresetUserConfiguring); | ||||
307 | } | ||||
308 | | ||||
309 | void SystemMonitor::resetToCustomPresetUserConfiguring() | ||||
310 | { | ||||
311 | // automatically switch to "custom" preset only when the user changes settings from the dialog, *not* nettings changed programmatically by the plasmoid itself | ||||
312 | if (isUserConfiguring()) { | ||||
313 | resetToCustomPreset(); | ||||
314 | } | ||||
315 | } | ||||
316 | | ||||
317 | void SystemMonitor::resetToCustomPreset() | ||||
318 | { | ||||
319 | if (m_availablePresetsModel && | ||||
320 | !m_availablePresetsModel->data(m_availablePresetsModel->index(0, 0), PresetsModel::PluginIdRole).toString().isEmpty()) { | ||||
321 | QStandardItem *item = new QStandardItem(i18n("Custom")); | ||||
322 | item->setData(i18n("Custom"), PresetsModel::ModelDataRole); | ||||
323 | m_availablePresetsModel->insertRow(0, item); | ||||
324 | } | ||||
325 | | ||||
326 | setCurrentPreset(QString()); | ||||
327 | } | ||||
328 | | ||||
329 | QString SystemMonitor::compactRepresentationPath() const | ||||
330 | { | ||||
331 | return m_facePackage.filePath("CompactRepresentation"); | ||||
332 | } | ||||
333 | | ||||
334 | QString SystemMonitor::fullRepresentationPath() const | ||||
335 | { | ||||
336 | return m_facePackage.filePath("FullRepresentation"); | ||||
337 | } | ||||
338 | | ||||
339 | QString SystemMonitor::configPath() const | ||||
340 | { | ||||
341 | return m_facePackage.filePath("ConfigUI"); | ||||
342 | } | ||||
343 | | ||||
344 | bool SystemMonitor::supportsSensorsColors() const | ||||
345 | { | ||||
346 | if (!m_faceMetadata) { | ||||
347 | return false; | ||||
348 | } | ||||
349 | | ||||
350 | KConfigGroup cg(m_faceMetadata, QStringLiteral("Config")); | ||||
351 | return cg.readEntry("SupportsSensorsColors", false); | ||||
352 | } | ||||
353 | | ||||
354 | bool SystemMonitor::supportsTotalSensor() const | ||||
355 | { | ||||
356 | if (!m_faceMetadata) { | ||||
357 | return false; | ||||
358 | } | ||||
359 | | ||||
360 | KConfigGroup cg(m_faceMetadata, QStringLiteral("Config")); | ||||
361 | return cg.readEntry("SupportsTotalSensor", false); | ||||
362 | } | ||||
363 | | ||||
364 | bool SystemMonitor::supportsTextOnlySensors() const | ||||
365 | { | ||||
366 | if (!m_faceMetadata) { | ||||
367 | return false; | ||||
368 | } | ||||
369 | | ||||
370 | KConfigGroup cg(m_faceMetadata, QStringLiteral("Config")); | ||||
371 | return cg.readEntry("SupportsTextOnlySensors", false); | ||||
372 | } | ||||
373 | | ||||
374 | QAbstractItemModel *SystemMonitor::availableFacesModel() | ||||
375 | { | ||||
376 | if (m_availableFacesModel) { | ||||
377 | return m_availableFacesModel; | ||||
378 | } | ||||
379 | | ||||
380 | m_availableFacesModel = new FacesModel(this); | ||||
381 | m_availableFacesModel->load(); | ||||
382 | return m_availableFacesModel; | ||||
383 | } | ||||
384 | | ||||
385 | QAbstractItemModel *SystemMonitor::availablePresetsModel() | ||||
386 | { | ||||
387 | if (m_availablePresetsModel) { | ||||
388 | return m_availablePresetsModel; | ||||
389 | } | ||||
390 | | ||||
391 | m_availablePresetsModel = new PresetsModel(this); | ||||
392 | | ||||
393 | // TODO move that into a PresetsModel::load() | ||||
394 | reloadAvailablePresetsModel(); | ||||
395 | | ||||
396 | if (m_currentPreset.isEmpty()) { | ||||
397 | resetToCustomPreset(); | ||||
398 | } | ||||
399 | | ||||
400 | return m_availablePresetsModel; | ||||
401 | } | ||||
402 | | ||||
403 | void SystemMonitor::reloadAvailablePresetsModel() | ||||
404 | { | ||||
405 | if (!m_availablePresetsModel) { | ||||
406 | availablePresetsModel(); | ||||
407 | return; | ||||
408 | } | ||||
409 | | ||||
410 | m_availablePresetsModel->clear(); | ||||
411 | QList<KPluginMetaData> plugins = KPackage::PackageLoader::self()->findPackages(QStringLiteral("Plasma/Applet"), QString(), [](const KPluginMetaData &plugin) { | ||||
412 | return plugin.value(QStringLiteral("X-Plasma-RootPath")) == QStringLiteral("org.kde.plasma.systemmonitor"); | ||||
413 | }); | ||||
414 | | ||||
415 | QSet<QString> usedNames; | ||||
416 | | ||||
417 | // We iterate backwards because packages under ~/.local are listed first, while we want them last | ||||
418 | auto it = plugins.rbegin(); | ||||
419 | for (; it != plugins.rend(); ++it) { | ||||
420 | const auto &plugin = *it; | ||||
421 | KPackage::Package p = KPackage::PackageLoader::self()->loadPackage("Plasma/Applet", plugin.pluginId()); | ||||
422 | KDesktopFile df(p.path() + QStringLiteral("metadata.desktop")); | ||||
423 | | ||||
424 | QString baseName = df.readName(); | ||||
425 | QString name = baseName; | ||||
426 | int id = 0; | ||||
427 | | ||||
428 | while (usedNames.contains(name)) { | ||||
429 | name = baseName % " (" % QString::number(++id) % ")"; | ||||
430 | } | ||||
431 | usedNames << name; | ||||
432 | | ||||
433 | QStandardItem *item = new QStandardItem(baseName); | ||||
434 | | ||||
435 | // TODO config | ||||
436 | QVariantMap config; | ||||
437 | | ||||
438 | KConfigGroup configGroup(df.group("Config")); | ||||
439 | | ||||
440 | const QStringList keys = configGroup.keyList(); | ||||
441 | for (const QString &key : keys) { | ||||
442 | // all strings for now, type conversion happens in QML side when we have the config property map | ||||
443 | config.insert(key, configGroup.readEntry(key)); | ||||
444 | } | ||||
445 | | ||||
446 | item->setData(name, PresetsModel::ModelDataRole); | ||||
447 | item->setData(plugin.pluginId(), PresetsModel::PluginIdRole); | ||||
448 | item->setData(config, PresetsModel::ConfigRole); | ||||
449 | | ||||
450 | item->setData(QFileInfo(p.path() + QStringLiteral("metadata.desktop")).isWritable(), PresetsModel::WritableRole); | ||||
451 | | ||||
452 | m_availablePresetsModel->appendRow(item); | ||||
453 | } | ||||
454 | } | ||||
455 | | ||||
456 | QObject *SystemMonitor::faceConfiguration() const | ||||
457 | { | ||||
458 | return m_faceConfiguration; | ||||
459 | } | ||||
460 | | ||||
461 | void SystemMonitor::createNewPreset(const QString &pluginName, const QString &comment, const QString &author, const QString &email, const QString &license, const QString &website) | ||||
462 | { | ||||
463 | QTemporaryDir dir; | ||||
464 | if (!dir.isValid()) { | ||||
465 | return; | ||||
466 | } | ||||
467 | | ||||
468 | KConfig c(dir.path() % QLatin1Literal("/metadata.desktop")); | ||||
469 | | ||||
470 | KConfigGroup cg(&c, "Desktop Entry"); | ||||
471 | cg.writeEntry("Name", configScheme()->property("title")); | ||||
472 | cg.writeEntry("Comment", comment); | ||||
473 | cg.writeEntry("Icon", "ksysguardd"); | ||||
474 | cg.writeEntry("X-Plasma-API", "declarativeappletscript"); | ||||
475 | cg.writeEntry("X-Plasma-MainScript", "ui/main.qml"); | ||||
476 | cg.writeEntry("X-Plasma-Provides", "org.kde.plasma.systemmonitor"); | ||||
477 | cg.writeEntry("X-Plasma-RootPath", "org.kde.plasma.systemmonitor"); | ||||
478 | cg.writeEntry("X-KDE-PluginInfo-Name", pluginName); | ||||
479 | cg.writeEntry("X-KDE-ServiceTypes", "Plasma/Applet"); | ||||
480 | cg.writeEntry("X-KDE-PluginInfo-Author", author); | ||||
481 | cg.writeEntry("X-KDE-PluginInfo-Email", email); | ||||
482 | cg.writeEntry("X-KDE-PluginInfo-Website", website); | ||||
483 | cg.writeEntry("X-KDE-PluginInfo-Category", "System Information"); | ||||
484 | cg.writeEntry("X-KDE-PluginInfo-License", license); | ||||
485 | cg.writeEntry("X-KDE-PluginInfo-EnabledByDefault", "true"); | ||||
486 | cg.writeEntry("X-KDE-PluginInfo-Version", "0.1"); | ||||
487 | cg.sync(); | ||||
488 | | ||||
489 | cg = KConfigGroup(&c, "Config"); | ||||
490 | for (KConfigSkeletonItem *item : configScheme()->items()) { | ||||
491 | cg.writeEntry(item->key(), item->property()); | ||||
492 | } | ||||
493 | cg.sync(); | ||||
494 | | ||||
495 | cg = KConfigGroup(&c, "FaceConfig"); | ||||
496 | for (KConfigSkeletonItem *item : m_faceConfigLoader->items()) { | ||||
497 | cg.writeEntry(item->key(), item->property()); | ||||
498 | } | ||||
499 | cg.sync(); | ||||
500 | | ||||
501 | auto presetPackage = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/Applet")); | ||||
502 | | ||||
503 | auto *job = presetPackage.install(dir.path()); | ||||
504 | | ||||
505 | connect(job, &KJob::finished, this, [this, pluginName] () { | ||||
506 | reloadAvailablePresetsModel(); | ||||
507 | setCurrentPreset(pluginName); | ||||
508 | }); | ||||
509 | } | ||||
510 | | ||||
511 | void SystemMonitor::savePreset() | ||||
512 | { | ||||
513 | QString pluginName = QStringLiteral("org.kde.plasma.systemmonitor.preset"); | ||||
514 | int suffix = 0; | ||||
515 | | ||||
516 | auto presetPackage = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/Applet")); | ||||
517 | | ||||
518 | do { | ||||
519 | presetPackage.setPath(QString()); | ||||
520 | presetPackage.setPath(pluginName + QString::number(++suffix)); | ||||
521 | } while (!presetPackage.filePath("metadata").isEmpty()); | ||||
522 | | ||||
523 | pluginName += QString::number(suffix); | ||||
524 | | ||||
525 | createNewPreset(pluginName, QString(), QString(), QString(), QStringLiteral("LGPL 2.1+"), QString()); | ||||
526 | } | ||||
527 | | ||||
528 | void SystemMonitor::getNewPresets(QQuickItem *ctx) | ||||
529 | { | ||||
530 | return getNewStuff(ctx, QStringLiteral("systemmonitor-presets.knsrc"), i18n("Download New Presets")); | ||||
531 | } | ||||
532 | | ||||
533 | void SystemMonitor::uninstallPreset(const QString &pluginId) | ||||
534 | { | ||||
535 | auto presetPackage = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/Applet"), pluginId); | ||||
536 | | ||||
537 | if (presetPackage.metadata().value("X-Plasma-RootPath") != QStringLiteral("org.kde.plasma.systemmonitor")) { | ||||
538 | return; | ||||
539 | } | ||||
540 | | ||||
541 | QDir root(presetPackage.path()); | ||||
542 | root.cdUp(); | ||||
543 | auto *job = presetPackage.uninstall(pluginId, root.path()); | ||||
544 | | ||||
545 | connect(job, &KJob::finished, this, [this] () { | ||||
546 | reloadAvailablePresetsModel(); | ||||
547 | }); | ||||
548 | } | ||||
549 | | ||||
550 | void SystemMonitor::getNewFaces(QQuickItem *ctx) | ||||
551 | { | ||||
552 | getNewStuff(ctx, QStringLiteral("systemmonitor-faces.knsrc"), i18n("Download New Display Styles")); | ||||
553 | } | ||||
554 | | ||||
555 | void SystemMonitor::getNewStuff(QQuickItem *ctx, const QString &knsrc, const QString &title) | ||||
556 | { | ||||
557 | if (m_newStuffDialog) { | ||||
558 | return; | ||||
559 | } | ||||
560 | | ||||
561 | m_newStuffDialog = new KNS3::DownloadDialog(knsrc); | ||||
562 | m_newStuffDialog->setWindowTitle(title); | ||||
563 | m_newStuffDialog->setWindowModality(Qt::WindowModal); | ||||
564 | m_newStuffDialog->winId(); // so it creates the windowHandle(); | ||||
565 | m_newStuffDialog->setAttribute(Qt::WA_DeleteOnClose); | ||||
566 | | ||||
567 | connect(m_newStuffDialog.data(), &KNS3::DownloadDialog::accepted, this, [this] { | ||||
568 | if (m_availableFacesModel) { | ||||
569 | m_availableFacesModel->load(); | ||||
570 | } | ||||
571 | reloadAvailablePresetsModel(); | ||||
572 | }); | ||||
573 | | ||||
574 | if (ctx && ctx->window()) { | ||||
575 | m_newStuffDialog->windowHandle()->setTransientParent(ctx->window()); | ||||
576 | } | ||||
577 | | ||||
578 | m_newStuffDialog->show(); | ||||
579 | } | ||||
580 | | ||||
581 | K_EXPORT_PLASMA_APPLET_WITH_JSON(systemmonitor, SystemMonitor, "metadata.json") | ||||
582 | | ||||
583 | #include "systemmonitor.moc" |