11#include "private/applet_p.h"
13#include "config-plasma.h"
22#include <KConfigLoader>
23#include <KConfigPropertyMap>
24#include <KGlobalAccel>
25#include <KLocalizedString>
26#include <KPackage/Package>
28#include "containment.h"
31#include "pluginloader.h"
34#include "private/containment_p.h"
43 , d(new AppletPrivate(data, args.count() > 1 ? args[1].toInt() : 0, this))
45 if (!args.isEmpty()) {
46 const QVariant first = args.first();
47 if (first.canConvert<KPackage::Package>()) {
48 d->package = first.value<KPackage::Package>();
51 d->icon = d->appletDescription.iconName();
54 setProperty(
"org.kde.plasma:force-create",
true);
64 for (
QAction *a : d->actions.values()) {
65 disconnect(a,
nullptr,
this,
nullptr);
67 for (
QAction *a : d->contextualActions) {
68 disconnect(a,
nullptr,
this,
nullptr);
72 Q_EMIT appletDeleted(
this);
75 d->resetConfigurationObject();
81 if (d->configLoader) {
82 disconnect(d->configLoader, SIGNAL(configChanged()),
this, SLOT(propagateConfigChanged()));
92uint Applet::id()
const
97QVariantList Applet::startupArguments()
const
99 return d->startupArguments;
104 if (d->transient || !d->appletDescription.isValid()) {
110 group = *d->mainConfigGroup();
116 group.
writeEntry(
"immutability", (
int)d->immutability);
117 group.
writeEntry(
"plugin", d->appletDescription.pluginId());
123 KConfigGroup appletConfigGroup(&group, QStringLiteral(
"Configuration"));
124 saveState(appletConfigGroup);
126 if (d->configLoader) {
129 disconnect(d->configLoader, SIGNAL(configChanged()),
this, SLOT(propagateConfigChanged()));
130 d->configLoader->save();
131 connect(d->configLoader, SIGNAL(configChanged()),
this, SLOT(propagateConfigChanged()));
139 KConfigGroup shortcutConfig(&group, QStringLiteral(
"Shortcuts"));
156 QByteArray hintsString = config().readEntry(
"UserBackgroundHints",
QString()).toUtf8();
162 d->userBackgroundHintsInitialized =
true;
163 Q_EMIT userBackgroundHintsChanged();
164 if (d->backgroundHints & Plasma::Types::ConfigurableBackground) {
165 Q_EMIT effectiveBackgroundHintsChanged();
170void Applet::setLaunchErrorMessage(
const QString &message)
172 if (message == d->launchErrorMessage) {
177 d->launchErrorMessage = message;
182 if (group.
config()->
name() != config().config()->name()) {
196 if (isContainment()) {
197 return *(d->mainConfigGroup());
200 return KConfigGroup(d->mainConfigGroup(), QStringLiteral(
"Configuration"));
206 QString group = isContainment() ? QStringLiteral(
"ContainmentGlobals") : QStringLiteral(
"AppletGlobals");
211 corona = cont->corona();
214 KSharedConfig::Ptr coronaConfig = corona->
config();
220 return KConfigGroup(&globalAppletConfig, d->globalName());
223void Applet::destroy()
225 if (immutability() != Types::Mutable || d->transient || !d->started) {
229 d->setDestroyed(
true);
231 d->cleanUpAndDelete();
234bool Applet::destroyed()
const
241 if (!d->configLoader) {
242 const QString xmlPath = d->package.isValid() ? d->package.filePath(
"mainconfigxml") :
QString();
249 QObject::connect(d->configLoader, SIGNAL(configChanged()),
this, SLOT(propagateConfigChanged()));
253 return d->configLoader;
258 if (!d->configPropertyMap) {
261 d->scheduleModificationNotification();
264 return d->configPropertyMap;
267void Applet::updateConstraints(
Constraints constraints)
269 d->scheduleConstraintsUpdate(constraints);
272void Applet::constraintsEvent(Constraints constraints)
278 Q_UNUSED(constraints)
285 if (!d->customTitle.isEmpty()) {
286 return d->customTitle;
289 if (d->appletDescription.isValid()) {
290 return d->appletDescription.name();
293 return i18n(
"Unknown");
296void Applet::setTitle(
const QString &title)
298 if (title == d->customTitle) {
302 d->customTitle = title;
303 Q_EMIT titleChanged(title);
311void Applet::setIcon(
const QString &icon)
313 if (icon == d->icon) {
318 Q_EMIT iconChanged(icon);
321bool Applet::isBusy()
const
326void Applet::setBusy(
bool busy)
328 if (busy == d->busy) {
333 Q_EMIT busyChanged(busy);
338 return d->backgroundHints;
343 if (d->backgroundHints == hint) {
349 d->backgroundHints = hint;
350 Q_EMIT backgroundHintsChanged();
352 if (oldeffectiveHints != effectiveBackgroundHints()) {
353 Q_EMIT effectiveBackgroundHintsChanged();
359 if (d->userBackgroundHintsInitialized && (d->backgroundHints & Plasma::Types::ConfigurableBackground)) {
360 return d->userBackgroundHints;
362 return d->backgroundHints;
368 return d->userBackgroundHints;
373 if (d->userBackgroundHints == hint && d->userBackgroundHintsInitialized) {
377 d->userBackgroundHints = hint;
378 d->userBackgroundHintsInitialized =
true;
380 config().writeEntry(
"UserBackgroundHints", hintEnum.
valueToKey(d->userBackgroundHints));
381 if (containment() && containment()->corona()) {
382 containment()->corona()->requestConfigSync();
385 Q_EMIT userBackgroundHintsChanged();
387 if (d->backgroundHints & Plasma::Types::ConfigurableBackground) {
388 Q_EMIT effectiveBackgroundHintsChanged();
394 return d->appletDescription;
397QString Applet::pluginName()
const
399 return d->appletDescription.isValid() ? d->appletDescription.pluginId() :
QString();
407 if (d->transient || (d->mainConfig && d->mainConfig->isImmutable())) {
408 return Types::SystemImmutable;
414 if (isContainment()) {
422 if (cont->corona()) {
423 upperImmutability = cont->corona()->immutability();
425 upperImmutability = cont->immutability();
430 if (upperImmutability != Types::Mutable) {
433 return upperImmutability;
435 return d->immutability;
441 if (d->immutability == immutable || immutable == Types::SystemImmutable) {
449 d->immutability = immutable;
450 updateConstraints(ImmutableConstraint);
453bool Applet::immutable()
const
455 return immutability() != Types::Mutable;
458QString Applet::launchErrorMessage()
const
460 return d->launchErrorMessage;
463bool Applet::failedToLaunch()
const
468bool Applet::configurationRequired()
const
470 return d->needsConfig;
473QString Applet::configurationRequiredReason()
const
475 return d->configurationRequiredReason;
478void Applet::setConfigurationRequired(
bool needsConfig,
const QString &reason)
480 if (d->needsConfig == needsConfig && reason == d->configurationRequiredReason) {
484 d->needsConfig = needsConfig;
485 d->configurationRequiredReason = reason;
487 Q_EMIT configurationRequiredChanged(needsConfig, reason);
492 if (d->constraintHints == constraintHints) {
496 d->constraintHints = constraintHints;
497 Q_EMIT constraintHintsChanged(constraintHints);
502 return d->constraintHints;
505bool Applet::isUserConfiguring()
const
507 return d->userConfiguring;
510void Applet::setUserConfiguring(
bool configuring)
512 if (configuring == d->userConfiguring) {
516 d->userConfiguring = configuring;
517 Q_EMIT userConfiguringChanged(configuring);
522 return d->itemStatus;
527 if (
status == d->itemStatus) {
531 Q_EMIT statusChanged(
status);
534void Applet::flushPendingConstraintsEvents()
536 if (d->pendingConstraints == NoConstraint) {
540 if (d->constraintsTimer.isActive()) {
541 d->constraintsTimer.stop();
546 d->pendingConstraints = NoConstraint;
548 if (c & UiReadyConstraint) {
552 if (c & StartupCompletedConstraint) {
554 bool unlocked = immutability() == Types::Mutable;
555 QAction *closeApplet = d->actions.value(QStringLiteral(
"remove"));
562 QAction *configAction = d->actions.value(QStringLiteral(
"configure"));
564 if (d->hasConfigurationInterface) {
565 bool canConfig = unlocked ||
KAuthorized::authorize(QStringLiteral(
"plasma/allow_configure_when_locked"));
572 if (c & ImmutableConstraint) {
573 bool unlocked = immutability() == Types::Mutable;
574 QAction *action = d->actions.value(QStringLiteral(
"remove"));
580 action = d->actions.value(QStringLiteral(
"configure"));
581 if (action && d->hasConfigurationInterface) {
582 bool canConfig = unlocked ||
KAuthorized::authorize(QStringLiteral(
"plasma/allow_configure_when_locked"));
589 if (d->oldImmutability != immutability()) {
590 Q_EMIT immutabilityChanged(immutability());
592 d->oldImmutability = immutability();
596 Containment *containment = qobject_cast<Plasma::Containment *>(
this);
598 containment->d->containmentConstraintsEvent(c);
604 if (c & StartupCompletedConstraint) {
606 if (d->modificationsTimer) {
607 if (d->modificationsTimer->isActive()) {
608 d->modificationsTimer->stop();
615 if (c & FormFactorConstraint) {
616 Q_EMIT formFactorChanged(formFactor());
619 if (c & LocationConstraint) {
620 Q_EMIT locationChanged(location());
626 return d->contextualActions;
633 AppletPrivate::contextualActions_append,
634 AppletPrivate::contextualActions_count,
635 AppletPrivate::contextualActions_at,
636 AppletPrivate::contextualActions_clear,
637 AppletPrivate::contextualActions_replace,
638 AppletPrivate::contextualActions_removeLast);
641void Applet::setInternalAction(
const QString &name,
QAction *action)
648 QAction *oldAction = d->actions.value(name);
653 d->actions[name] = action;
656 d->actions.remove(name);
657 Q_EMIT internalActionsChanged(d->actions.values());
660 Q_EMIT internalActionsChanged(d->actions.values());
665 return d->actions.value(name);
668void Applet::removeInternalAction(
const QString &name)
670 QAction *action = d->actions.value(name);
677 d->actions.remove(name);
679 Q_EMIT internalActionsChanged(d->actions.values());
684 return d->actions.values();
690 QObject *pw = qobject_cast<QObject *>(parent());
691 Plasma::Applet *parentApplet = qobject_cast<Plasma::Applet *>(pw);
693 while (!parentApplet && pw && pw->
parent()) {
695 parentApplet = qobject_cast<Plasma::Applet *>(pw);
705 return c ? c->d->containmentDisplayHints : Plasma::Types::NoContainmentDisplayHint;
717 QObject *parent = this->parent();
720 Containment *possibleC = qobject_cast<Containment *>(parent);
726 parent = parent->
parent();
732void Applet::setGlobalShortcut(
const QKeySequence &shortcut)
734 if (!d->activationAction) {
735 d->activationAction =
new QAction(
this);
736 d->activationAction->setText(
i18n(
"Activate %1 Widget", title()));
737 d->activationAction->setObjectName(QStringLiteral(
"activate widget %1").arg(
id()));
740 if (action == d->activationAction) {
741 d->activationAction->setShortcut(shortcut);
742 d->globalShortcutChanged();
745 }
else if (d->activationAction->shortcut() == shortcut) {
749 d->activationAction->setShortcut(shortcut);
750 d->globalShortcutEnabled =
true;
753 d->globalShortcutChanged();
755 Q_EMIT globalShortcutChanged(shortcut);
760 if (d->activationAction) {
763 return shortcuts.
first();
776bool Applet::hasConfigurationInterface()
const
778 return d->hasConfigurationInterface;
781void Applet::setHasConfigurationInterface(
bool hasInterface)
783 if (hasInterface == d->hasConfigurationInterface) {
787 QAction *configAction = d->actions.value(QStringLiteral(
"configure"));
789 bool enable = hasInterface;
791 const bool unlocked = immutability() == Types::Mutable;
797 d->hasConfigurationInterface = hasInterface;
798 Q_EMIT hasConfigurationInterfaceChanged(hasInterface);
801void Applet::configChanged()
803 if (d->configLoader) {
804 d->configLoader->load();
810 if (d->package.isValid()) {
811 return d->package.fileUrl(key, filename);
816QUrl Applet::mainScript()
const
818 if (d->package.isValid()) {
819 return d->package.fileUrl(
"mainscript");
824QUrl Applet::configModel()
const
826 if (d->package.isValid()) {
827 return d->package.fileUrl(
"configmodel");
833bool Applet::sourceValid()
const
835 return d->package.isValid();
841 d->constraintsTimer.stop();
842 if (d->modificationsTimer) {
843 d->modificationsTimer->stop();
848 if (event->timerId() == d->constraintsTimer.timerId()) {
849 d->constraintsTimer.stop();
853 if (!(d->pendingConstraints & StartupCompletedConstraint)) {
854 flushPendingConstraintsEvents();
856 }
else if (d->modificationsTimer && event->timerId() == d->modificationsTimer->timerId()) {
857 d->modificationsTimer->stop();
862 Q_EMIT configNeedsSaving();
866bool Applet::isContainment()
const
870 Applet *pa = qobject_cast<Applet *>(parent());
875 return qobject_cast<const Containment *>(
this) && qobject_cast<Corona *>(parent());
878QString Applet::translationDomain()
const
880 const QString rootPath = d->appletDescription.value(u
"X-Plasma-RootPath");
884 return QLatin1String(
"plasma_applet_") + d->appletDescription.pluginId();
890#include "moc_applet.cpp"
static Q_INVOKABLE bool authorize(const QString &action)
QString readEntryUntranslated(const char *key, const QString &aDefault=QString()) const
void writeEntry(const char *key, const char *value, WriteConfigFlags pFlags=Normal)
QString readEntry(const char *key, const char *aDefault=nullptr) const
void copyTo(KConfigBase *other, WriteConfigFlags pFlags=Normal) const
static KGlobalAccel * self()
bool setShortcut(QAction *action, const QList< QKeySequence > &shortcut, GlobalShortcutLoading loadFlag=Autoloading)
QList< QKeySequence > shortcut(const QAction *action) const
void globalShortcutChanged(QAction *action, const QKeySequence &seq)
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
bool isContainment
True if this applet is a Containment and is acting as one, such as a desktop or a panel.
Applet(QObject *parentObject, const KPluginMetaData &data, const QVariantList &args)
This constructor can be used with the KCoreAddons plugin loading system.
The base class for plugins that provide backgrounds and applet grouping containers.
A bookkeeping Scene for Plasma::Applets.
KSharedConfig::Ptr config() const
Returns the config file used to store the configuration for this Corona.
Types::ImmutabilityType immutability() const
ImmutabilityType
Defines the immutability of items like applets, corona and containments they can be free to modify,...
ItemStatus
Status of an applet.
BackgroundHints
Description on how draw a background for the applet.
Location
The Location enumeration describes where on screen an element, such as an Applet or its managing cont...
@ Desktop
On the planar desktop layer, extending across the full screen from edge to edge.
FormFactor
The FormFactor enumeration describes how a Plasma::Applet should arrange itself.
@ Planar
The applet lives in a plane and has two degrees of freedom to grow.
Q_SCRIPTABLE CaptureState status()
QString i18n(const char *text, const TYPE &arg...)
Namespace for everything in libplasma.
void triggered(bool checked)
const char * constData() const const
ObjectOwnership objectOwnership(QObject *object)
bool isEmpty() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void destroyed(QObject *obj)
QObject * parent() const const
void setObjectName(QAnyStringView name)
void valueChanged(const QString &key, const QVariant &value)
bool isEmpty() const const
QVariant fromValue(T &&value)