Plasma

applet.cpp
1 /*
2  SPDX-FileCopyrightText: 2005 Aaron Seigo <[email protected]>
3  SPDX-FileCopyrightText: 2007 Riccardo Iaconelli <[email protected]>
4  SPDX-FileCopyrightText: 2008 Ménard Alexis <[email protected]>
5  SPDX-FileCopyrightText: 2009 Chani Armitage <[email protected]>
6 
7  SPDX-License-Identifier: LGPL-2.0-or-later
8 */
9 
10 #include "applet.h"
11 #include "private/applet_p.h"
12 
13 #include "config-plasma.h"
14 
15 #include <QAbstractButton>
16 #include <QDebug>
17 #include <QFile>
18 #include <QList>
19 #include <QMessageBox>
20 #include <QMetaEnum>
21 
22 #include <KActionCollection>
23 #include <KAuthorized>
24 #include <KColorScheme>
25 #include <KConfigLoader>
26 #include <KDesktopFile>
27 #include <KGlobalAccel>
28 #include <KLocalizedString>
29 #include <KPackage/Package>
30 #include <KService>
31 
32 #include "containment.h"
33 #include "corona.h"
34 #include "package.h"
35 #include "plasma.h"
36 #include "pluginloader.h"
37 #include "scripting/appletscript.h"
38 
39 #include "debug_p.h"
40 #include "private/associatedapplicationmanager_p.h"
41 #include "private/containment_p.h"
42 #if PLASMA_BUILD_DEPRECATED_SINCE(5, 83)
43 #include "private/package_p.h"
44 #endif
45 
46 #include <cmath>
47 #include <limits>
48 
49 namespace Plasma
50 {
51 #if PLASMA_BUILD_DEPRECATED_SINCE(5, 86)
52 static KPluginMetaData appletMetadataForDirectory(const QString &path)
53 {
54  return QFile::exists(path + QLatin1String("/metadata.json"))
55  ? KPluginMetaData(path + QLatin1String("/metadata.json"))
56  : KPluginMetaData::fromDesktopFile(path + QLatin1String("/metadata.desktop"), {QStringLiteral("plasma-applet.desktop")});
57 }
58 
59 Applet::Applet(const KPluginMetaData &info, QObject *parent, uint appletId)
60  : QObject(parent)
61  , d(new AppletPrivate(info, appletId, this))
62 {
63  qCDebug(LOG_PLASMA) << " From KPluginMetaData, valid? " << info.isValid();
64  // WARNING: do not access config() OR globalConfig() in this method!
65  // that requires a scene, which is not available at this point
66  d->init();
67  d->setupPackage();
68 }
69 
70 #if PLASMA_BUILD_DEPRECATED_SINCE(5, 28)
71 Applet::Applet(const KPluginInfo &info, QObject *parent, uint appletId)
72  : Applet(info.toMetaData(), parent, appletId)
73 {
74 }
75 #endif
76 
77 Applet::Applet(QObject *parent, const QString &serviceID, uint appletId)
78  : QObject(parent)
79  , d(new AppletPrivate(KPluginMetaData(serviceID), appletId, this))
80 {
81  // WARNING: do not access config() OR globalConfig() in this method!
82  // that requires a scene, which is not available at this point
83  d->init();
84  d->setupPackage();
85 }
86 
87 Applet::Applet(QObject *parentObject, const QVariantList &args)
88  : QObject(nullptr)
89  , d(new AppletPrivate(KPluginMetaData(), args.count() > 2 ? args[2].toInt() : 0, this))
90 {
91  setParent(parentObject);
92  if (!args.isEmpty()) {
93  const QVariant first = args.first();
94  if (first.canConvert<KPackage::Package>()) {
95  d->package = first.value<KPackage::Package>();
96  }
97  }
98  if (args.count() > 1) {
99  const QVariant second = args[1];
100  if (second.canConvert<QString>()) {
101  d->appletDescription = KPluginMetaData(second.toString());
102  } else if (second.canConvert<QVariantMap>()) {
103  auto metadata = second.toMap().value(QStringLiteral("MetaData")).toMap();
104  d->appletDescription = KPluginMetaData(QJsonObject::fromVariantMap(metadata), {});
105  }
106  }
107  d->icon = d->appletDescription.iconName();
108 
109  if (args.contains(QVariant::fromValue(QStringLiteral("org.kde.plasma:force-create")))) {
110  setProperty("org.kde.plasma:force-create", true);
111  }
112 
113  // WARNING: do not access config() OR globalConfig() in this method!
114  // that requires a scene, which is not available at this point
115  d->init(QString(), args.mid(3));
116  d->setupPackage();
117 }
118 
119 Applet::Applet(const QString &packagePath, uint appletId)
120  : QObject(nullptr)
121  , d(new AppletPrivate(appletMetadataForDirectory(packagePath), appletId, this))
122 {
123  d->init(packagePath);
124  d->setupPackage();
125 }
126 #endif
127 
128 Applet::Applet(QObject *parentObject, const KPluginMetaData &data, const QVariantList &args)
129  : QObject(nullptr)
130  , d(new AppletPrivate(data, args.count() > 2 ? args[2].toInt() : 0, this))
131 {
132  setParent(parentObject);
133  if (!args.isEmpty()) {
134  const QVariant first = args.first();
135  if (first.canConvert<KPackage::Package>()) {
136  d->package = first.value<KPackage::Package>();
137  }
138  }
139  d->icon = d->appletDescription.iconName();
140 
141  if (args.contains(QVariant::fromValue(QStringLiteral("org.kde.plasma:force-create")))) {
142  setProperty("org.kde.plasma:force-create", true);
143  }
144 
145  // WARNING: do not access config() OR globalConfig() in this method!
146  // that requires a scene, which is not available at this point
147  d->init(QString(), args.mid(3));
148  d->setupPackage();
149 }
150 
151 Applet::~Applet()
152 {
153  if (d->transient) {
154  d->resetConfigurationObject();
155  }
156  // let people know that i will die
157  Q_EMIT appletDeleted(this);
158 
159  // ConfigLoader is deleted when AppletPrivate closes not Applet
160  // It saves on closure and emits a signal.
161  // disconnect early to avoid a crash. See 411221
162  if (d->configLoader) {
163  disconnect(d->configLoader, SIGNAL(configChanged()), this, SLOT(propagateConfigChanged()));
164  }
165  delete d;
166 }
167 
169 {
170  // Don't implement anything here, it will be overridden by subclasses
171 }
172 
173 uint Applet::id() const
174 {
175  return d->appletId;
176 }
177 
179 {
180  if (d->transient || !d->appletDescription.isValid()) {
181  return;
182  }
183 
184  KConfigGroup group = g;
185  if (!group.isValid()) {
186  group = *d->mainConfigGroup();
187  }
188 
189  // qCDebug(LOG_PLASMA) << "saving" << pluginName() << "to" << group.name();
190  // we call the dptr member directly for locked since isImmutable()
191  // also checks kiosk and parent containers
192  group.writeEntry("immutability", (int)d->immutability);
193  group.writeEntry("plugin", d->appletDescription.pluginId());
194 
195  if (!d->started) {
196  return;
197  }
198 
199  KConfigGroup appletConfigGroup(&group, "Configuration");
200  saveState(appletConfigGroup);
201 
202  if (d->configLoader) {
203  // we're saving so we know its changed, we don't need or want the configChanged
204  // signal bubbling up at this point due to that
205  disconnect(d->configLoader, SIGNAL(configChanged()), this, SLOT(propagateConfigChanged()));
206  d->configLoader->save();
207  connect(d->configLoader, SIGNAL(configChanged()), this, SLOT(propagateConfigChanged()));
208  }
209 }
210 
212 {
213  setImmutability((Types::ImmutabilityType)group.readEntry("immutability", (int)Types::Mutable));
214 
215  KConfigGroup shortcutConfig(&group, "Shortcuts");
216  QString shortcutText = shortcutConfig.readEntryUntranslated("global", QString());
217  if (!shortcutText.isEmpty()) {
218  setGlobalShortcut(QKeySequence(shortcutText));
219  /*
220  #ifndef NDEBUG
221  // qCDebug(LOG_PLASMA) << "got global shortcut for" << name() << "of" << QKeySequence(shortcutText);
222  #endif
223  #ifndef NDEBUG
224  // qCDebug(LOG_PLASMA) << "set to" << d->activationAction->objectName()
225  #endif
226  << d->activationAction->globalShortcut().primary();
227  */
228  }
229 
230  // User background hints
231  // TODO support flags in the config
232  QByteArray hintsString = config().readEntry("UserBackgroundHints", QString()).toUtf8();
233  QMetaEnum hintEnum = QMetaEnum::fromType<Plasma::Types::BackgroundHints>();
234  bool ok;
235  int value = hintEnum.keyToValue(hintsString.constData(), &ok);
236  if (ok) {
237  d->userBackgroundHints = Plasma::Types::BackgroundHints(value);
238  d->userBackgroundHintsInitialized = true;
240  if (d->backgroundHints & Plasma::Types::ConfigurableBackground) {
242  }
243  }
244 }
245 
247 {
248  if (message == d->launchErrorMessage) {
249  return;
250  }
251 
252  d->failed = true;
253  d->launchErrorMessage = message;
254 }
255 
256 void Applet::saveState(KConfigGroup &group) const
257 {
258  if (d->script) {
259  Q_EMIT d->script->saveState(group);
260  }
261 
262  if (group.config()->name() != config().config()->name()) {
263  // we're being saved to a different file!
264  // let's just copy the current values in our configuration over
265  KConfigGroup c = config();
266  c.copyTo(&group);
267  }
268 }
269 
271 {
272  if (d->transient) {
273  return KConfigGroup(KSharedConfig::openConfig(), "PlasmaTransientsConfig");
274  }
275 
276  if (isContainment()) {
277  return *(d->mainConfigGroup());
278  }
279 
280  return KConfigGroup(d->mainConfigGroup(), "Configuration");
281 }
282 
284 {
285  KConfigGroup globalAppletConfig;
286  QString group = isContainment() ? QStringLiteral("ContainmentGlobals") : QStringLiteral("AppletGlobals");
287 
288  Containment *cont = containment();
289  Corona *corona = nullptr;
290  if (cont) {
291  corona = cont->corona();
292  }
293  if (corona) {
294  KSharedConfig::Ptr coronaConfig = corona->config();
295  globalAppletConfig = KConfigGroup(coronaConfig, group);
296  } else {
297  globalAppletConfig = KConfigGroup(KSharedConfig::openConfig(), group);
298  }
299 
300  return KConfigGroup(&globalAppletConfig, d->globalName());
301 }
302 
304 {
305  if (immutability() != Types::Mutable || d->transient || !d->started) {
306  return; // don't double delete
307  }
308 
309  d->setDestroyed(true);
310  // FIXME: an animation on leave if !isContainment() would be good again .. which should be handled by the containment class
311  d->cleanUpAndDelete();
312 }
313 
314 bool Applet::destroyed() const
315 {
316  return d->transient;
317 }
318 
320 {
321  if (!d->configLoader) {
322  const QString xmlPath = d->package.isValid() ? d->package.filePath("mainconfigxml") : QString();
323  KConfigGroup cfg = config();
324  if (xmlPath.isEmpty()) {
325  d->configLoader = new KConfigLoader(cfg, nullptr);
326  } else {
327  QFile file(xmlPath);
328  d->configLoader = new KConfigLoader(cfg, &file);
329  QObject::connect(d->configLoader, SIGNAL(configChanged()), this, SLOT(propagateConfigChanged()));
330  }
331  }
332 
333  return d->configLoader;
334 }
335 
336 #if PLASMA_BUILD_DEPRECATED_SINCE(5, 6)
338 {
339  Package p;
340  p.d->internalPackage = new KPackage::Package(d->package);
341  return p;
342 }
343 #endif
344 
346 {
347  return d->package;
348 }
349 
351 {
352  d->scheduleConstraintsUpdate(constraints);
353 }
354 
355 void Applet::constraintsEvent(Plasma::Types::Constraints constraints)
356 {
357  // NOTE: do NOT put any code in here that reacts to constraints updates
358  // as it will not get called for any applet that reimplements constraintsEvent
359  // without calling the Applet:: version as well, which it shouldn't need to.
360  // INSTEAD put such code into flushPendingConstraintsEvents
361  Q_UNUSED(constraints)
362  // qCDebug(LOG_PLASMA) << constraints << "constraints are FormFactor: " << formFactor()
363  // << ", Location: " << location();
364  if (d->script) {
365  d->script->constraintsEvent(constraints);
366  }
367 }
368 
369 QString Applet::title() const
370 {
371  if (!d->customTitle.isEmpty()) {
372  return d->customTitle;
373  }
374 
375  if (d->appletDescription.isValid()) {
376  return d->appletDescription.name();
377  }
378 
379  return i18n("Unknown");
380 }
381 
382 void Applet::setTitle(const QString &title)
383 {
384  if (title == d->customTitle) {
385  return;
386  }
387 
388  d->customTitle = title;
389  Q_EMIT titleChanged(title);
390 }
391 
392 QString Applet::icon() const
393 {
394  return d->icon;
395 }
396 
397 void Applet::setIcon(const QString &icon)
398 {
399  if (icon == d->icon) {
400  return;
401  }
402 
403  d->icon = icon;
404  Q_EMIT iconChanged(icon);
405 }
406 
407 bool Applet::isBusy() const
408 {
409  return d->busy;
410 }
411 
412 void Applet::setBusy(bool busy)
413 {
414  if (busy == d->busy) {
415  return;
416  }
417 
418  d->busy = busy;
419  Q_EMIT busyChanged(busy);
420 }
421 
423 {
424  return d->backgroundHints;
425 }
426 
428 {
429  if (d->backgroundHints == hint) {
430  return;
431  }
432 
434 
435  d->backgroundHints = hint;
437 
438  if (oldeffectiveHints != effectiveBackgroundHints()) {
440  }
441 }
442 
444 {
445  if (d->userBackgroundHintsInitialized && (d->backgroundHints & Plasma::Types::ConfigurableBackground)) {
446  return d->userBackgroundHints;
447  } else {
448  return d->backgroundHints;
449  }
450 }
451 
453 {
454  return d->userBackgroundHints;
455 }
456 
458 {
459  if (d->userBackgroundHints == hint && d->userBackgroundHintsInitialized) {
460  return;
461  }
462 
463  d->userBackgroundHints = hint;
464  d->userBackgroundHintsInitialized = true;
465  QMetaEnum hintEnum = QMetaEnum::fromType<Plasma::Types::BackgroundHints>();
466  config().writeEntry("UserBackgroundHints", hintEnum.valueToKey(d->userBackgroundHints));
467  if (containment() && containment()->corona()) {
469  }
470 
472 
473  if (d->backgroundHints & Plasma::Types::ConfigurableBackground) {
475  }
476 }
477 
478 #if PLASMA_BUILD_DEPRECATED_SINCE(5, 28)
480 {
481  return KPluginInfo(d->appletDescription);
482 }
483 #endif
484 
486 {
487  return d->appletDescription;
488 }
489 
490 Types::ImmutabilityType Applet::immutability() const
491 {
492  // if this object is itself system immutable, then just return that; it's the most
493  // restrictive setting possible and will override anything that might be happening above it
494  // in the Corona->Containment->Applet hierarchy
495  if (d->transient || (d->mainConfig && d->mainConfig->isImmutable())) {
496  return Types::SystemImmutable;
497  }
498 
499  // Returning the more strict immutability between the applet immutability, Containment and Corona
500  Types::ImmutabilityType upperImmutability = Types::Mutable;
501 
502  if (isContainment()) {
503  Corona *cor = static_cast<Containment *>(const_cast<Applet *>(this))->corona();
504  if (cor) {
505  upperImmutability = cor->immutability();
506  }
507  } else {
508  const Containment *cont = containment();
509  if (cont) {
510  if (cont->corona()) {
511  upperImmutability = cont->corona()->immutability();
512  } else {
513  upperImmutability = cont->immutability();
514  }
515  }
516  }
517 
518  if (upperImmutability != Types::Mutable) {
519  // it's either system or user immutable, and we already check for local system immutability,
520  // so upperImmutability is guaranteed to be as or more severe as this object's immutability
521  return upperImmutability;
522  } else {
523  return d->immutability;
524  }
525 }
526 
528 {
529  if (d->immutability == immutable || immutable == Types::SystemImmutable) {
530  // we do not store system immutability in d->immutability since that gets saved
531  // out to the config file; instead, we check with
532  // the config group itself for this information at all times. this differs from
533  // corona, where SystemImmutability is stored in d->immutability.
534  return;
535  }
536 
537  d->immutability = immutable;
539 }
540 
542 {
543  return d->launchErrorMessage;
544 }
545 
547 {
548  return d->failed;
549 }
550 
552 {
553  return d->needsConfig;
554 }
555 
557 {
558  return d->configurationRequiredReason;
559 }
560 
561 void Applet::setConfigurationRequired(bool needsConfig, const QString &reason)
562 {
563  if (d->needsConfig == needsConfig && reason == d->configurationRequiredReason) {
564  return;
565  }
566 
567  d->needsConfig = needsConfig;
568  d->configurationRequiredReason = reason;
569 
570  Q_EMIT configurationRequiredChanged(needsConfig, reason);
571 }
572 
574 {
575  return d->userConfiguring;
576 }
577 
578 void Applet::setUserConfiguring(bool configuring)
579 {
580  if (configuring == d->userConfiguring) {
581  return;
582  }
583 
584  d->userConfiguring = configuring;
585  Q_EMIT userConfiguringChanged(configuring);
586 }
587 
588 Types::ItemStatus Applet::status() const
589 {
590  return d->itemStatus;
591 }
592 
594 {
595  if (status == d->itemStatus) {
596  return;
597  }
598  d->itemStatus = status;
600 }
601 
603 {
604  if (d->pendingConstraints == Types::NoConstraint) {
605  return;
606  }
607 
608  if (d->constraintsTimer.isActive()) {
609  d->constraintsTimer.stop();
610  }
611 
612  // qCDebug(LOG_PLASMA) << "flushing constraints: " << d->pendingConstraints << "!!!!!!!!!!!!!!!!!!!!!!!!!!!";
613  Plasma::Types::Constraints c = d->pendingConstraints;
614  d->pendingConstraints = Types::NoConstraint;
615 
617  d->setUiReady();
618  }
619 
621  // common actions
622  bool unlocked = immutability() == Types::Mutable;
623  QAction *closeApplet = d->actions->action(QStringLiteral("remove"));
624  if (closeApplet) {
625  closeApplet->setEnabled(unlocked);
626  closeApplet->setVisible(unlocked);
627  connect(closeApplet, SIGNAL(triggered(bool)), this, SLOT(askDestroy()), Qt::UniqueConnection);
628  }
629 
630  QAction *configAction = d->actions->action(QStringLiteral("configure"));
631  if (configAction) {
632  if (d->hasConfigurationInterface) {
633  bool canConfig = unlocked || KAuthorized::authorize(QStringLiteral("plasma/allow_configure_when_locked"));
634  configAction->setVisible(canConfig);
635  configAction->setEnabled(canConfig);
636  }
637  }
638 
639  QAction *runAssociatedApplication = d->actions->action(QStringLiteral("run associated application"));
642  }
643 
644  d->updateShortcuts();
645  }
646 
648  bool unlocked = immutability() == Types::Mutable;
649  QAction *action = d->actions->action(QStringLiteral("remove"));
650  if (action) {
651  action->setVisible(unlocked);
652  action->setEnabled(unlocked);
653  }
654 
655  action = d->actions->action(QStringLiteral("configure"));
656  if (action && d->hasConfigurationInterface) {
657  bool canConfig = unlocked || KAuthorized::authorize(QStringLiteral("plasma/allow_configure_when_locked"));
658  action->setVisible(canConfig);
659  action->setEnabled(canConfig);
660  }
661 
662  // an immutable constraint will always happen at startup
663  // make sure don't emit a change signal for nothing
664  if (d->oldImmutability != immutability()) {
665  Q_EMIT immutabilityChanged(immutability());
666  }
667  d->oldImmutability = immutability();
668  }
669 
670  // now take care of constraints in special subclass: Containment
671  Containment *containment = qobject_cast<Plasma::Containment *>(this);
672  if (containment) {
673  containment->d->containmentConstraintsEvent(c);
674  }
675 
676  // pass the constraint on to the actual subclass
677  constraintsEvent(c);
678 
680  // start up is done, we can now go do a mod timer
681  if (d->modificationsTimer) {
682  if (d->modificationsTimer->isActive()) {
683  d->modificationsTimer->stop();
684  }
685  } else {
686  d->modificationsTimer = new QBasicTimer;
687  }
688  }
689 
691  Q_EMIT formFactorChanged(formFactor());
692  }
693 
695  Q_EMIT locationChanged(location());
696  }
697 }
698 
700 {
701  // qCDebug(LOG_PLASMA) << "empty context actions";
702  return d->script ? d->script->contextualActions() : QList<QAction *>();
703 }
704 
706 {
707  return d->actions;
708 }
709 
710 Types::FormFactor Applet::formFactor() const
711 {
712  Containment *c = containment();
713  QObject *pw = qobject_cast<QObject *>(parent());
714  Plasma::Applet *parentApplet = qobject_cast<Plasma::Applet *>(pw);
715  // assumption: this loop is usually is -really- short or doesn't run at all
716  while (!parentApplet && pw && pw->parent()) {
717  pw = pw->parent();
718  parentApplet = qobject_cast<Plasma::Applet *>(pw);
719  }
720 
721  return c ? c->d->formFactor : Plasma::Types::Planar;
722 }
723 
724 Types::ContainmentDisplayHints Applet::containmentDisplayHints() const
725 {
726  Containment *c = containment();
727 
728  return c ? c->d->containmentDisplayHints : Plasma::Types::NoContainmentDisplayHint;
729 }
730 
732 {
733  Containment *c = qobject_cast<Containment *>(const_cast<Applet *>(this));
734  if (c && c->isContainment()) {
735  return c;
736  } else {
737  c = nullptr;
738  }
739 
740  QObject *parent = this->parent();
741 
742  while (parent) {
743  Containment *possibleC = qobject_cast<Containment *>(parent);
744 
745  if (possibleC && possibleC->isContainment()) {
746  c = possibleC;
747  break;
748  }
749  parent = parent->parent();
750  }
751 
752  return c;
753 }
754 
756 {
757  if (!d->activationAction) {
758  d->activationAction = new QAction(this);
759  d->activationAction->setText(i18n("Activate %1 Widget", title()));
760  d->activationAction->setObjectName(QStringLiteral("activate widget %1").arg(id())); // NO I18N
761  connect(d->activationAction, &QAction::triggered, this, &Applet::activated);
762  connect(KGlobalAccel::self(), &KGlobalAccel::globalShortcutChanged, this, [this](QAction *action, const QKeySequence &shortcut) {
763  if (action == d->activationAction) {
764  d->activationAction->setShortcut(shortcut);
765  d->globalShortcutChanged();
766  }
767  });
768  } else if (d->activationAction->shortcut() == shortcut) {
769  return;
770  }
771 
772  d->activationAction->setShortcut(shortcut);
773  d->globalShortcutEnabled = true;
774  QList<QKeySequence> seqs{shortcut};
775  KGlobalAccel::self()->setShortcut(d->activationAction, seqs, KGlobalAccel::NoAutoloading);
776  d->globalShortcutChanged();
777 }
778 
780 {
781  if (d->activationAction) {
782  QList<QKeySequence> shortcuts = KGlobalAccel::self()->shortcut(d->activationAction);
783  if (!shortcuts.isEmpty()) {
784  return shortcuts.first();
785  }
786  }
787 
788  return QKeySequence();
789 }
790 
791 Types::Location Applet::location() const
792 {
793  Containment *c = containment();
794  return c ? c->d->location : Plasma::Types::Desktop;
795 }
796 
798 {
799  return d->hasConfigurationInterface;
800 }
801 
803 {
804  if (hasInterface == d->hasConfigurationInterface) {
805  return;
806  }
807 
808  QAction *configAction = d->actions->action(QStringLiteral("configure"));
809  if (configAction) {
810  bool enable = hasInterface;
811  if (enable) {
812  const bool unlocked = immutability() == Types::Mutable;
813  enable = unlocked || KAuthorized::authorize(QStringLiteral("plasma/allow_configure_when_locked"));
814  }
815  configAction->setEnabled(enable);
816  }
817 
818  d->hasConfigurationInterface = hasInterface;
819 }
820 
822 {
823  if (d->script) {
824  if (d->configLoader) {
825  d->configLoader->load();
826  }
827  d->script->configChanged();
828  }
829 }
830 
832 {
833  AssociatedApplicationManager::self()->setApplication(this, string);
834 
835  QAction *runAssociatedApplication = d->actions->action(QStringLiteral("run associated application"));
837  bool valid = AssociatedApplicationManager::self()->appletHasValidAssociatedApplication(this);
838  runAssociatedApplication->setVisible(valid);
839  runAssociatedApplication->setEnabled(valid);
840  }
841 }
842 
844 {
845  AssociatedApplicationManager::self()->setUrls(this, urls);
846 
847  QAction *runAssociatedApplication = d->actions->action(QStringLiteral("run associated application"));
849  bool valid = AssociatedApplicationManager::self()->appletHasValidAssociatedApplication(this);
850  runAssociatedApplication->setVisible(valid);
851  runAssociatedApplication->setEnabled(valid);
852  }
853 }
854 
856 {
857  return AssociatedApplicationManager::self()->application(this);
858 }
859 
861 {
862  return AssociatedApplicationManager::self()->urls(this);
863 }
864 
866 {
867  AssociatedApplicationManager::self()->run(this);
868 }
869 
871 {
872  return AssociatedApplicationManager::self()->appletHasValidAssociatedApplication(this);
873 }
874 
875 #if PLASMA_BUILD_DEPRECATED_SINCE(5, 19)
876 Applet *Applet::loadPlasmoid(const QString &path, uint appletId)
877 {
878  const KPluginMetaData md = appletMetadataForDirectory(path);
879  if (md.isValid()) {
880  QStringList types = md.serviceTypes();
881 
882  if (types.contains(QLatin1String("Plasma/Containment")) || md.rawData().contains(QStringLiteral("X-Plasma-ContainmentType"))) {
883  return new Containment(md, appletId);
884  } else {
885  return new Applet(md, nullptr, appletId);
886  }
887  }
888 
889  return nullptr;
890 }
891 #endif
892 
893 QString Applet::filePath(const QByteArray &key, const QString &filename) const
894 {
895  if (d->package.isValid()) {
896  return d->package.filePath(key, filename);
897  }
898  return QString();
899 }
900 
902 {
903  if (d->transient) {
904  d->constraintsTimer.stop();
905  if (d->modificationsTimer) {
906  d->modificationsTimer->stop();
907  }
908  return;
909  }
910 
911  if (event->timerId() == d->constraintsTimer.timerId()) {
912  d->constraintsTimer.stop();
913 
914  // Don't flushPendingConstraints if we're just starting up
915  // flushPendingConstraints will be called by Corona
916  if (!(d->pendingConstraints & Plasma::Types::StartupCompletedConstraint)) {
918  }
919  } else if (d->modificationsTimer && event->timerId() == d->modificationsTimer->timerId()) {
920  d->modificationsTimer->stop();
921  // invalid group, will result in save using the default group
922  KConfigGroup cg;
923 
924  save(cg);
926  }
927 }
928 
930 {
931  // HACK: this is a special case for the systray
932  // containment in an applet that is not a containment
933  Applet *pa = qobject_cast<Applet *>(parent());
934  if (pa && !pa->isContainment()) {
935  return true;
936  }
937  // normal "acting as a containment" condition
938  return qobject_cast<const Containment *>(this) && qobject_cast<Corona *>(parent());
939 }
940 
941 } // Plasma namespace
942 
943 #include "moc_applet.cpp"
T & first()
QString readEntry(const char *key, const char *aDefault=nullptr) const
void writeEntry(const char *key, const char *value, WriteConfigFlags pFlags=Normal)
QJsonObject rawData() const
KConfigGroup config() const
Returns the KConfigGroup to access the applets configuration.
Definition: applet.cpp:270
virtual void save(KConfigGroup &group) const
Saves state information about this applet that will be accessed when next instantiated in the restore...
Definition: applet.cpp:178
KActionCollection * actions() const
Returns the collection of actions for this Applet.
Definition: applet.cpp:705
ItemStatus
Status of an applet.
Definition: plasma.h:270
KConfigLoader * configScheme() const
Returns the config skeleton object from this applet's package, if any.
Definition: applet.cpp:319
@ LocationConstraint
The Location of an object.
Definition: plasma.h:42
bool configurationRequired() const
Definition: applet.cpp:551
@ ImmutableConstraint
the immutability (locked) nature of the applet changed
Definition: plasma.h:44
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
Namespace for everything in libplasma.
Definition: datamodel.cpp:14
void requestConfigSync()
Schedules a flush-to-disk synchronization of the configuration state at the next convenient moment.
Definition: corona.cpp:133
void setStatus(const Types::ItemStatus stat)
sets the status for this applet
Definition: applet.cpp:593
BackgroundHints
Description on how draw a background for the applet.
Definition: plasma.h:298
QVariant fromValue(const T &value)
Q_EMITQ_EMIT
QStringList serviceTypes() const
T value() const const
uint id() const
Definition: applet.cpp:173
KPluginMetaData pluginMetaData() const
Definition: applet.cpp:485
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
QString name() const
bool hasValidAssociatedApplication() const
Definition: applet.cpp:870
void runAssociatedApplication()
Open the application associated to this applet, if it's not set but some urls are,...
Definition: applet.cpp:865
void configurationRequiredChanged(bool needsConfig, const QString &reason)
Emitted when setConfigurationRequired was called.
QJsonObject fromVariantMap(const QVariantMap &map)
Plasma::Types::BackgroundHints backgroundHints
How the applet wants its background to be drawn.
Definition: applet.h:86
QString readEntryUntranslated(const char *key, const QString &aDefault=QString()) const
bool isValid() const
bool isValid() const
void configNeedsSaving()
Emitted when an applet has changed values in its configuration and wishes for them to be saved at the...
Plasma::Types::BackgroundHints effectiveBackgroundHints
The effective background hints the applet has, internally decided how to mix with userBackgroundHints...
Definition: applet.h:96
Corona * corona() const
Returns the Corona (if any) that this Containment is hosted by.
void setConfigurationRequired(bool needsConfiguring, const QString &reason=QString())
When the applet needs to be configured before being usable, this method can be called to show a stand...
Definition: applet.cpp:561
Containment * containment() const
Definition: applet.cpp:731
void statusChanged(Plasma::Types::ItemStatus status)
Emitted when the applet status changes.
bool isBusy() const
Definition: applet.cpp:407
void setImmutability(const Types::ImmutabilityType immutable)
Sets the immutability type for this applet (not immutable, user immutable or system immutable)
Definition: applet.cpp:527
void busyChanged(bool busy)
Emitted when the busy status has changed.
QString launchErrorMessage() const
If for some reason, the applet fails to get up on its feet (the library couldn't be loaded,...
Definition: applet.cpp:541
FormFactor
The FormFactor enumeration describes how a Plasma::Applet should arrange itself.
Definition: plasma.h:72
void setBusy(bool busy)
Sets the Applet to have a busy status hint, for instance the applet doing some network operation.
Definition: applet.cpp:412
bool exists() const const
void setGlobalShortcut(const QKeySequence &shortcut)
Sets the global shortcut to associate with this widget.
Definition: applet.cpp:755
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
@ Mutable
The item can be modified in any way.
Definition: plasma.h:236
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
bool contains(const QString &key) const const
@ NoConstraint
No constraint; never passed in to Applet::constraintsEvent on its own.
Definition: plasma.h:40
void effectiveBackgroundHintsChanged()
Emitted when the effective background hints have changed.
QString configurationRequiredReason() const
Definition: applet.cpp:556
KConfigGroup globalConfig() const
Returns a KConfigGroup object to be shared by all applets of this type.
Definition: applet.cpp:283
KPluginInfo pluginInfo() const
Definition: applet.cpp:479
bool setShortcut(QAction *action, const QList< QKeySequence > &shortcut, GlobalShortcutLoading loadFlag=Autoloading)
QKeySequence globalShortcut() const
Definition: applet.cpp:779
void userBackgroundHintsChanged()
Emitted when the user background hints have changed.
bool destroyed() const
Definition: applet.cpp:314
void timerEvent(QTimerEvent *event) override
Reimplemented from QObject.
Definition: applet.cpp:901
bool hasConfigurationInterface() const
Definition: applet.cpp:797
virtual QList< QAction * > contextualActions()
Returns a list of context-related QAction instances.
Definition: applet.cpp:699
virtual bool event(QEvent *e)
QString i18n(const char *text, const TYPE &arg...)
void formFactorChanged(Plasma::Types::FormFactor formFactor)
Emitted when the formfactor changes.
@ Desktop
On the planar desktop layer, extending across the full screen from edge to edge.
Definition: plasma.h:161
Package package() const
Accessor for the associated Package object if any.
Definition: applet.cpp:337
static Applet * loadPlasmoid(const QString &path, uint appletId=0)
Attempts to load an applet from a package.
Definition: applet.cpp:876
void setIcon(const QString &icon)
Sets an icon name for this applet.
Definition: applet.cpp:397
const char * valueToKey(int value) const const
@ SystemImmutable
the item is locked down by the system, the user can't unlock it
Definition: plasma.h:239
void userConfiguringChanged(bool configuring)
emitted when the config ui appears or disappears
void setUserConfiguring(bool configuring)
Tells the applet the user is configuring.
Definition: applet.cpp:578
A bookkeeping Scene for Plasma::Applets.
Definition: corona.h:27
virtual void init()
This method is called once the applet is loaded and added to a Corona.
Definition: applet.cpp:168
int keyToValue(const char *key, bool *ok) const const
void iconChanged(const QString &icon)
Emitted when the icon name for the applet has changed.
bool isEmpty() const const
QByteArray toUtf8() const const
void immutabilityChanged(Plasma::Types::ImmutabilityType immutable)
Emitted when the immutability changes.
void setBackgroundHints(Plasma::Types::BackgroundHints hint)
Sets the applet background hints.
Definition: applet.cpp:427
bool isUserConfiguring() const
Definition: applet.cpp:573
KPackage::Package kPackage() const
Accessor for the associated Package object if any.
Definition: applet.cpp:345
Q_SCRIPTABLE CaptureState status()
UniqueConnection
bool isEmpty() const const
Plasma::Types::BackgroundHints userBackgroundHints
The containment (and/or the user) may decide to use another kind of background instead (if supported ...
Definition: applet.h:91
void locationChanged(Plasma::Types::Location location)
Emitted when the location changes.
void globalShortcutChanged(QAction *action, const QKeySequence &seq)
@ StartupCompletedConstraint
application startup has completed
Definition: plasma.h:45
bool failedToLaunch() const
If for some reason, the applet fails to get up on its feet (the library couldn't be loaded,...
Definition: applet.cpp:546
QMap< QString, QVariant > toMap() const const
KCONFIGCORE_EXPORT bool authorize(const QString &action)
bool canConvert(int targetTypeId) const const
void setVisible(bool)
void activated()
Emitted when activation is requested due to, for example, a global keyboard shortcut.
@ FormFactorConstraint
The FormFactor for an object.
Definition: plasma.h:41
void destroy()
Destroys the applet; it will be removed nicely and deleted.
Definition: applet.cpp:303
void setAssociatedApplication(const QString &string)
Sets an application associated to this applet, that will be regarded as a full view of what is repres...
Definition: applet.cpp:831
bool setProperty(const char *name, const QVariant &value)
bool isContainment() const
Definition: applet.cpp:929
void triggered(bool checked)
virtual void restore(KConfigGroup &group)
Restores state information about this applet saved previously in save(KConfigGroup&).
Definition: applet.cpp:211
void flushPendingConstraintsEvents()
Sends all pending constraints updates to the applet.
Definition: applet.cpp:602
void setEnabled(bool)
const char * constData() const const
virtual void saveState(KConfigGroup &config) const
When called, the Applet should write any information needed as part of the Applet's running state to ...
Definition: applet.cpp:256
void setUserBackgroundHints(Plasma::Types::BackgroundHints hint)
Sets the hints the user wished the background style for the applet to be.
Definition: applet.cpp:457
@ Planar
The applet lives in a plane and has two degrees of freedom to grow.
Definition: plasma.h:73
void setAssociatedApplicationUrls(const QList< QUrl > &urls)
Sets a list of urls associated to this application, they will be used as parameters for the associate...
Definition: applet.cpp:843
void setHasConfigurationInterface(bool hasInterface)
Sets whether or not this applet provides a user interface for configuring the applet.
Definition: applet.cpp:802
void setParent(QObject *parent)
Location
The Location enumeration describes where on screen an element, such as an Applet or its managing cont...
Definition: plasma.h:158
void setTitle(const QString &title)
Sets a custom title for this instance of the applet.
Definition: applet.cpp:382
void copyTo(KConfigBase *other, WriteConfigFlags pFlags=Normal) const
@ UiReadyConstraint
The ui has been completely loaded.
Definition: plasma.h:47
KGuiItem cont()
ImmutabilityType
Defines the immutability of items like applets, corona and containments they can be free to modify,...
Definition: plasma.h:235
void setLaunchErrorMessage(const QString &reason=QString())
Call this method when the applet fails to launch properly.
Definition: applet.cpp:246
virtual void configChanged()
Called when applet configuration values have changed.
Definition: applet.cpp:821
KConfig * config()
static KGlobalAccel * self()
object representing an installed Plasma package
Definition: package.h:76
void titleChanged(const QString &title)
Emitted when the title has changed.
Applet(QObject *parentObject, const KPluginMetaData &data, const QVariantList &args)
This constructor can be used with the KCoreAddons plugin loading system.
Definition: applet.cpp:128
void appletDeleted(Plasma::Applet *applet)
Emitted when the applet is deleted.
QString mid(int position, int n) const const
The base class for plugins that provide backgrounds and applet grouping containers.
Definition: containment.h:45
QString associatedApplication() const
Definition: applet.cpp:855
QList< QUrl > associatedApplicationUrls() const
Definition: applet.cpp:860
void backgroundHintsChanged()
Emitted when the background hints have changed.
QObject * parent() const const
The base Applet class.
Definition: applet.h:71
QString message
void updateConstraints(Plasma::Types::Constraints constraints=Plasma::Types::AllConstraints)
Called when any of the geometry constraints have been updated.
Definition: applet.cpp:350
QList< QKeySequence > shortcut(const QAction *action) const
QString toString() const const
KSharedConfig::Ptr config() const
Returns the config file used to store the configuration for this Corona.
Definition: corona.cpp:276
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Feb 7 2023 04:15:01 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.