diff --git a/src/plasma/applet.cpp b/src/plasma/applet.cpp index 10230ff48..5a0b34603 100644 --- a/src/plasma/applet.cpp +++ b/src/plasma/applet.cpp @@ -1,842 +1,852 @@ /* * Copyright 2005 by Aaron Seigo * Copyright 2007 by Riccardo Iaconelli * Copyright 2008 by Ménard Alexis * Copyright (c) 2009 Chani Armitage * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "applet.h" #include "private/applet_p.h" #include "config-plasma.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "containment.h" #include "corona.h" #include "package.h" #include "plasma.h" #include "scripting/appletscript.h" #include "pluginloader.h" #include "private/associatedapplicationmanager_p.h" #include "private/containment_p.h" #include "private/package_p.h" #include "debug_p.h" namespace Plasma { static KPluginMetaData appletMetadataForDirectory(const QString &path) { return QFile::exists(path + QLatin1String("/metadata.json")) ? KPluginMetaData(path + QLatin1String("/metadata.json")) : KPluginMetaData::fromDesktopFile(path + QLatin1String("/metadata.desktop"), { QStringLiteral("plasma-applet.desktop") }); } Applet::Applet(const KPluginMetaData &info, QObject *parent, uint appletId) : QObject(parent), d(new AppletPrivate(info, appletId, this)) { qCDebug(LOG_PLASMA) << " From KPluginMetaData, valid? " << info.isValid(); // WARNING: do not access config() OR globalConfig() in this method! // that requires a scene, which is not available at this point d->init(); d->setupPackage(); } Applet::Applet(const KPluginInfo &info, QObject *parent, uint appletId) : Applet(info.toMetaData(), parent, appletId) { } Applet::Applet(QObject *parent, const QString &serviceID, uint appletId) : QObject(parent), d(new AppletPrivate(KPluginMetaData(serviceID), appletId, this)) { // WARNING: do not access config() OR globalConfig() in this method! // that requires a scene, which is not available at this point d->init(); d->setupPackage(); } Applet::Applet(QObject *parentObject, const QVariantList &args) : QObject(0), d(new AppletPrivate(KPluginMetaData(), args.count() > 2 ? args[2].toInt() : 0, this)) { setParent(parentObject); if (args.count() > 0) { const QVariant first = args.first(); if (first.canConvert()) { d->package = first.value(); } } if (args.count() > 1) { const QVariant second = args[1]; if (second.canConvert()) { d->appletDescription = KPluginMetaData(second.toString()); } else if (second.canConvert()) { auto metadata = second.toMap().value(QStringLiteral("MetaData")).toMap(); d->appletDescription = KPluginMetaData(QJsonObject::fromVariantMap(metadata), {}); } } d->icon = d->appletDescription.iconName(); if (args.contains(QVariant::fromValue(QStringLiteral("org.kde.plasma:force-create")))) { setProperty("org.kde.plasma:force-create", true); } // WARNING: do not access config() OR globalConfig() in this method! // that requires a scene, which is not available at this point d->init(QString(), args.mid(3)); d->setupPackage(); } Applet::Applet(const QString &packagePath, uint appletId) : QObject(nullptr), d(new AppletPrivate(appletMetadataForDirectory(packagePath), appletId, this)) { d->init(packagePath); d->setupPackage(); } Applet::~Applet() { if (d->transient) { d->resetConfigurationObject(); } //let people know that i will die emit appletDeleted(this); delete d; } void Applet::init() { //Don't implement anything here, it will be overridden by subclasses } uint Applet::id() const { return d->appletId; } void Applet::save(KConfigGroup &g) const { if (d->transient || !d->appletDescription.isValid()) { return; } KConfigGroup group = g; if (!group.isValid()) { group = *d->mainConfigGroup(); } //qCDebug(LOG_PLASMA) << "saving" << pluginName() << "to" << group.name(); // we call the dptr member directly for locked since isImmutable() // also checks kiosk and parent containers group.writeEntry("immutability", (int)d->immutability); group.writeEntry("plugin", d->appletDescription.pluginId()); if (!d->started) { return; } KConfigGroup appletConfigGroup(&group, "Configuration"); saveState(appletConfigGroup); if (d->configLoader) { // we're saving so we know its changed, we don't need or want the configChanged // signal bubbling up at this point due to that disconnect(d->configLoader, SIGNAL(configChanged()), this, SLOT(propagateConfigChanged())); d->configLoader->save(); connect(d->configLoader, SIGNAL(configChanged()), this, SLOT(propagateConfigChanged())); } } void Applet::restore(KConfigGroup &group) { setImmutability((Types::ImmutabilityType)group.readEntry("immutability", (int)Types::Mutable)); KConfigGroup shortcutConfig(&group, "Shortcuts"); QString shortcutText = shortcutConfig.readEntryUntranslated("global", QString()); if (!shortcutText.isEmpty()) { setGlobalShortcut(QKeySequence(shortcutText)); /* #ifndef NDEBUG // qCDebug(LOG_PLASMA) << "got global shortcut for" << name() << "of" << QKeySequence(shortcutText); #endif #ifndef NDEBUG // qCDebug(LOG_PLASMA) << "set to" << d->activationAction->objectName() #endif << d->activationAction->globalShortcut().primary(); */ } // local shortcut, if any //TODO: implement; the shortcut will need to be registered with the containment /* #include "accessmanager.h" #include "private/plasmoidservice_p.h" #include "authorizationmanager.h" #include "authorizationmanager.h" shortcutText = shortcutConfig.readEntryUntranslated("local", QString()); if (!shortcutText.isEmpty()) { //TODO: implement; the shortcut } */ } void Applet::setLaunchErrorMessage(const QString &message) { if (message == d->launchErrorMessage) { return; } d->failed = true; d->launchErrorMessage = message; } void Applet::saveState(KConfigGroup &group) const { if (d->script) { emit d->script->saveState(group); } if (group.config()->name() != config().config()->name()) { // we're being saved to a different file! // let's just copy the current values in our configuration over KConfigGroup c = config(); c.copyTo(&group); } } KConfigGroup Applet::config() const { if (d->transient) { return KConfigGroup(KSharedConfig::openConfig(), "PlasmaTransientsConfig"); } if (isContainment()) { return *(d->mainConfigGroup()); } return KConfigGroup(d->mainConfigGroup(), "Configuration"); } KConfigGroup Applet::globalConfig() const { KConfigGroup globalAppletConfig; QString group = isContainment() ? QStringLiteral("ContainmentGlobals") : QStringLiteral("AppletGlobals"); Containment *cont = containment(); Corona *corona = 0; if (cont) { corona = cont->corona(); } if (corona) { KSharedConfig::Ptr coronaConfig = corona->config(); globalAppletConfig = KConfigGroup(coronaConfig, group); } else { globalAppletConfig = KConfigGroup(KSharedConfig::openConfig(), group); } return KConfigGroup(&globalAppletConfig, d->globalName()); } void Applet::destroy() { if (immutability() != Types::Mutable || d->transient || !d->started) { return; //don't double delete } d->setDestroyed(true); //FIXME: an animation on leave if !isContainment() would be good again .. which should be handled by the containment class d->cleanUpAndDelete(); } bool Applet::destroyed() const { return d->transient; } KConfigLoader *Applet::configScheme() const { if (!d->configLoader) { const QString xmlPath = d->package.isValid() ? d->package.filePath("mainconfigxml") : QString(); KConfigGroup cfg = config(); if (xmlPath.isEmpty()) { d->configLoader = new KConfigLoader(cfg, 0); } else { QFile file(xmlPath); d->configLoader = new KConfigLoader(cfg, &file); QObject::connect(d->configLoader, SIGNAL(configChanged()), this, SLOT(propagateConfigChanged())); } } return d->configLoader; } Package Applet::package() const { Package p; p.d->internalPackage = new KPackage::Package(d->package); return p; } KPackage::Package Applet::kPackage() const { return d->package; } void Applet::updateConstraints(Plasma::Types::Constraints constraints) { d->scheduleConstraintsUpdate(constraints); } void Applet::constraintsEvent(Plasma::Types::Constraints constraints) { //NOTE: do NOT put any code in here that reacts to constraints updates // as it will not get called for any applet that reimplements constraintsEvent // without calling the Applet:: version as well, which it shouldn't need to. // INSTEAD put such code into flushPendingConstraintsEvents Q_UNUSED(constraints) //qCDebug(LOG_PLASMA) << constraints << "constraints are FormFactor: " << formFactor() // << ", Location: " << location(); if (d->script) { d->script->constraintsEvent(constraints); } } QString Applet::title() const { if (!d->customTitle.isEmpty()) { return d->customTitle; } if (d->appletDescription.isValid()) { return d->appletDescription.name(); } return i18n("Unknown"); } void Applet::setTitle(const QString &title) { if (title == d->customTitle) { return; } d->customTitle = title; emit titleChanged(title); } QString Applet::icon() const { return d->icon; } void Applet::setIcon(const QString &icon) { if (icon == d->icon) { return; } d->icon = icon; emit iconChanged(icon); } bool Applet::isBusy() const { return d->busy; } void Applet::setBusy(bool busy) { if (busy == d->busy) { return; } d->busy = busy; emit busyChanged(busy); } KPluginInfo Applet::pluginInfo() const { return KPluginInfo(d->appletDescription); } KPluginMetaData Applet::pluginMetaData() const { return d->appletDescription; } Types::ImmutabilityType Applet::immutability() const { // if this object is itself system immutable, then just return that; it's the most // restrictive setting possible and will override anything that might be happening above it // in the Corona->Containment->Applet hierarchy if (d->transient || (d->mainConfig && d->mainConfig->isImmutable())) { return Types::SystemImmutable; } //Returning the more strict immutability between the applet immutability, Containment and Corona Types::ImmutabilityType upperImmutability = Types::Mutable; if (isContainment()) { Corona *cor = static_cast(const_cast(this))->corona(); if (cor) { upperImmutability = cor->immutability(); } } else { const Containment *cont = containment(); if (cont) { if (cont->corona()) { upperImmutability = cont->corona()->immutability(); } else { upperImmutability = cont->immutability(); } } } if (upperImmutability != Types::Mutable) { // it's either system or user immutable, and we already check for local system immutability, // so upperImmutability is guaranteed to be as or more severe as this object's immutability return upperImmutability; } else { return d->immutability; } } void Applet::setImmutability(const Types::ImmutabilityType immutable) { if (d->immutability == immutable || immutable == Types::SystemImmutable) { // we do not store system immutability in d->immutability since that gets saved // out to the config file; instead, we check with // the config group itself for this information at all times. this differs from // corona, where SystemImmutability is stored in d->immutability. return; } d->immutability = immutable; updateConstraints(Types::ImmutableConstraint); } QString Applet::launchErrorMessage() const { return d->launchErrorMessage; } bool Applet::failedToLaunch() const { return d->failed; } bool Applet::configurationRequired() const { return d->needsConfig; } QString Applet::configurationRequiredReason() const { return d->configurationRequiredReason; } void Applet::setConfigurationRequired(bool needsConfig, const QString &reason) { if (d->needsConfig == needsConfig && reason == d->configurationRequiredReason) { return; } d->needsConfig = needsConfig; d->configurationRequiredReason = reason; emit configurationRequiredChanged(needsConfig, reason); } bool Applet::isUserConfiguring() const { return d->userConfiguring; } void Applet::setUserConfiguring(bool configuring) { if (configuring == d->userConfiguring) { return; } d->userConfiguring = configuring; emit userConfiguringChanged(configuring); } Types::ItemStatus Applet::status() const { return d->itemStatus; } void Applet::setStatus(const Types::ItemStatus status) { if (status == d->itemStatus) { return; } d->itemStatus = status; emit statusChanged(status); } void Applet::flushPendingConstraintsEvents() { if (d->pendingConstraints == Types::NoConstraint) { return; } if (d->constraintsTimer.isActive()) { d->constraintsTimer.stop(); } //qCDebug(LOG_PLASMA) << "fushing constraints: " << d->pendingConstraints << "!!!!!!!!!!!!!!!!!!!!!!!!!!!"; Plasma::Types::Constraints c = d->pendingConstraints; d->pendingConstraints = Types::NoConstraint; if (c & Plasma::Types::UiReadyConstraint) { d->setUiReady(); } if (c & Plasma::Types::StartupCompletedConstraint) { //common actions bool unlocked = immutability() == Types::Mutable; QAction *closeApplet = d->actions->action(QStringLiteral("remove")); if (closeApplet) { closeApplet->setEnabled(unlocked); closeApplet->setVisible(unlocked); connect(closeApplet, SIGNAL(triggered(bool)), this, SLOT(askDestroy()), Qt::UniqueConnection); } QAction *configAction = d->actions->action(QStringLiteral("configure")); if (configAction) { if (d->hasConfigurationInterface) { bool canConfig = unlocked || KAuthorized::authorize(QStringLiteral("plasma/allow_configure_when_locked")); configAction->setVisible(canConfig); configAction->setEnabled(canConfig); } } QAction *runAssociatedApplication = d->actions->action(QStringLiteral("run associated application")); if (runAssociatedApplication) { connect(runAssociatedApplication, SIGNAL(triggered(bool)), this, SLOT(runAssociatedApplication()), Qt::UniqueConnection); } d->updateShortcuts(); } if (c & Plasma::Types::ImmutableConstraint) { bool unlocked = immutability() == Types::Mutable; QAction *action = d->actions->action(QStringLiteral("remove")); if (action) { action->setVisible(unlocked); action->setEnabled(unlocked); } action = d->actions->action(QStringLiteral("configure")); if (action && d->hasConfigurationInterface) { bool canConfig = unlocked || KAuthorized::authorize(QStringLiteral("plasma/allow_configure_when_locked")); action->setVisible(canConfig); action->setEnabled(canConfig); } //an immutable constraint will alwasy happen at startup //make sure don't emit a change signal for nothing if (d->oldImmutability != immutability()) { emit immutabilityChanged(immutability()); } d->oldImmutability = immutability(); } // now take care of constraints in special subclass: Contaiment Containment *containment = qobject_cast(this); if (containment) { containment->d->containmentConstraintsEvent(c); } // pass the constraint on to the actual subclass constraintsEvent(c); if (c & Types::StartupCompletedConstraint) { // start up is done, we can now go do a mod timer if (d->modificationsTimer) { if (d->modificationsTimer->isActive()) { d->modificationsTimer->stop(); } } else { d->modificationsTimer = new QBasicTimer; } } if (c & Plasma::Types::FormFactorConstraint) { emit formFactorChanged(formFactor()); } if (c & Plasma::Types::LocationConstraint) { emit locationChanged(location()); } + + if (c & Plasma::Types::InputModeConstraint) { + emit inputModeChanged(inputMode()); + } } QList Applet::contextualActions() { //qCDebug(LOG_PLASMA) << "empty context actions"; return d->script ? d->script->contextualActions() : QList(); } KActionCollection *Applet::actions() const { return d->actions; } Types::FormFactor Applet::formFactor() const { Containment *c = containment(); QObject *pw = qobject_cast(parent()); Plasma::Applet *parentApplet = qobject_cast(pw); //assumption: this loop is usually is -really- short or doesn't run at all while (!parentApplet && pw && pw->parent()) { pw = pw->parent(); parentApplet = qobject_cast(pw); } return c ? c->d->formFactor : Plasma::Types::Planar; } Containment *Applet::containment() const { Containment *c = qobject_cast(const_cast(this)); if (c && c->isContainment()) { return c; } else { c = 0; } QObject *parent = this->parent(); while (parent) { Containment *possibleC = qobject_cast(parent); if (possibleC && possibleC->isContainment()) { c = possibleC; break; } parent = parent->parent(); } return c; } void Applet::setGlobalShortcut(const QKeySequence &shortcut) { if (!d->activationAction) { d->activationAction = new QAction(this); d->activationAction->setText(i18n("Activate %1 Widget", title())); d->activationAction->setObjectName(QStringLiteral("activate widget %1").arg(id())); // NO I18N connect(d->activationAction, SIGNAL(triggered()), this, SIGNAL(activated())); connect(d->activationAction, SIGNAL(changed()), this, SLOT(globalShortcutChanged())); } else if (d->activationAction->shortcut() == shortcut) { return; } d->activationAction->setShortcut(shortcut); d->globalShortcutEnabled = true; QList seqs; seqs << shortcut; KGlobalAccel::self()->setShortcut(d->activationAction, seqs, KGlobalAccel::NoAutoloading); d->globalShortcutChanged(); } QKeySequence Applet::globalShortcut() const { if (d->activationAction) { QList shortcuts = KGlobalAccel::self()->shortcut(d->activationAction); if (!shortcuts.isEmpty()) { return shortcuts.first(); } } return QKeySequence(); } Types::Location Applet::location() const { Containment *c = containment(); return c ? c->d->location : Plasma::Types::Desktop; } +Types::InputMode Applet::inputMode() const +{ + Containment *c = containment(); + return c && c->corona() ? c->corona()->inputMode() : Plasma::Types::DesktopInputMode; +} + bool Applet::hasConfigurationInterface() const { return d->hasConfigurationInterface; } void Applet::setHasConfigurationInterface(bool hasInterface) { if (hasInterface == d->hasConfigurationInterface) { return; } QAction *configAction = d->actions->action(QStringLiteral("configure")); if (configAction) { bool enable = hasInterface; if (enable) { const bool unlocked = immutability() == Types::Mutable; enable = unlocked || KAuthorized::authorize(QStringLiteral("plasma/allow_configure_when_locked")); } configAction->setEnabled(enable); } d->hasConfigurationInterface = hasInterface; } void Applet::configChanged() { if (d->script) { if (d->configLoader) { d->configLoader->load(); } d->script->configChanged(); } } void Applet::setAssociatedApplication(const QString &string) { AssociatedApplicationManager::self()->setApplication(this, string); QAction *runAssociatedApplication = d->actions->action(QStringLiteral("run associated application")); if (runAssociatedApplication) { bool valid = AssociatedApplicationManager::self()->appletHasValidAssociatedApplication(this); runAssociatedApplication->setVisible(valid); runAssociatedApplication->setEnabled(valid); } } void Applet::setAssociatedApplicationUrls(const QList &urls) { AssociatedApplicationManager::self()->setUrls(this, urls); QAction *runAssociatedApplication = d->actions->action(QStringLiteral("run associated application")); if (runAssociatedApplication) { bool valid = AssociatedApplicationManager::self()->appletHasValidAssociatedApplication(this); runAssociatedApplication->setVisible(valid); runAssociatedApplication->setEnabled(valid); } } QString Applet::associatedApplication() const { return AssociatedApplicationManager::self()->application(this); } QList Applet::associatedApplicationUrls() const { return AssociatedApplicationManager::self()->urls(this); } void Applet::runAssociatedApplication() { AssociatedApplicationManager::self()->run(this); } bool Applet::hasValidAssociatedApplication() const { return AssociatedApplicationManager::self()->appletHasValidAssociatedApplication(this); } Applet *Applet::loadPlasmoid(const QString &path, uint appletId) { const KPluginMetaData md = appletMetadataForDirectory(path); if (md.isValid()) { QStringList types = md.serviceTypes(); if (types.contains(QStringLiteral("Plasma/Containment"))) { return new Containment(md, appletId); } else { return new Applet(md, nullptr, appletId); } } return 0; } void Applet::timerEvent(QTimerEvent *event) { if (d->transient) { d->constraintsTimer.stop(); if (d->modificationsTimer) { d->modificationsTimer->stop(); } return; } if (event->timerId() == d->constraintsTimer.timerId()) { d->constraintsTimer.stop(); // Don't flushPendingConstraints if we're just starting up // flushPendingConstraints will be called by Corona if (!(d->pendingConstraints & Plasma::Types::StartupCompletedConstraint)) { flushPendingConstraintsEvents(); } } else if (d->modificationsTimer && event->timerId() == d->modificationsTimer->timerId()) { d->modificationsTimer->stop(); // invalid group, will result in save using the default group KConfigGroup cg; save(cg); emit configNeedsSaving(); } } bool Applet::isContainment() const { //HACK: this is a special case for the systray //containment in an applet that is not a containment Applet *pa = qobject_cast(parent()); if (pa && !pa->isContainment()) { return true; } //normal "acting as a containment" condition return qobject_cast(this) && qobject_cast(parent()); } } // Plasma namespace #include "moc_applet.cpp" diff --git a/src/plasma/applet.h b/src/plasma/applet.h index 31f42298c..4dd6fb9f0 100644 --- a/src/plasma/applet.h +++ b/src/plasma/applet.h @@ -1,726 +1,742 @@ /* * Copyright 2006-2007 by Aaron Seigo * Copyright 2007 by Riccardo Iaconelli * Copyright 2008 by Ménard Alexis * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef PLASMA_APPLET_H #define PLASMA_APPLET_H #include #include #include #include #include #include #include #include #include class KActionCollection; class KConfigLoader; namespace Plasma { class AppletPrivate; class Containment; class DataEngine; class Package; /** * @class Applet plasma/applet.h * * @short The base Applet class * * Applet provides several important roles for add-ons widgets in Plasma. * * First, it is the base class for the plugin system and therefore is the * interface to applets for host applications. It also handles the life time * management of data engines (e.g. all data engines accessed via * Applet::dataEngine(const QString&) are properly deref'd on Applet * destruction), background painting (allowing for consistent and complex * look and feel in just one line of code for applets), loading and starting * of scripting support for each applet, providing access to the associated * plasmoid package (if any) and access to configuration data. * * See techbase.kde.org for tutorials on writing Applets using this class. */ class PLASMA_EXPORT Applet : public QObject { Q_OBJECT Q_PROPERTY(Plasma::Types::ItemStatus status READ status WRITE setStatus NOTIFY statusChanged) Q_PROPERTY(Plasma::Types::ImmutabilityType immutability READ immutability WRITE setImmutability NOTIFY immutabilityChanged) Q_PROPERTY(Plasma::Types::FormFactor formFactor READ formFactor NOTIFY formFactorChanged) Q_PROPERTY(Plasma::Types::Location location READ location NOTIFY locationChanged) Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged FINAL) Q_PROPERTY(QString icon READ icon WRITE setIcon NOTIFY iconChanged FINAL) Q_PROPERTY(bool busy READ isBusy WRITE setBusy NOTIFY busyChanged FINAL) public: //CONSTRUCTORS /** * @param parent the QObject this applet is parented to * @param serviceId the name of the .desktop file containing the * information about the widget * @param appletId a unique id used to differentiate between multiple * instances of the same Applet type */ explicit Applet(QObject *parent = nullptr, const QString &serviceId = QString(), uint appletId = 0); /** * @param parent the QObject this applet is parented to * @param info the plugin information object for this Applet * @param appletId a unique id used to differentiate between multiple * instances of the same Applet type * @since 4.6 * * @deprecated prefer using KPluginMetaData */ PLASMA_DEPRECATED explicit Applet(const KPluginInfo &info, QObject *parent = nullptr, uint appletId = 0); /** * @param parent the QObject this applet is parented to * @param metadata the plugin information object for this Applet * @param appletId a unique id used to differentiate between multiple * instances of the same Applet type * @since 5.27 */ explicit Applet(const KPluginMetaData &metadata, QObject *parent = nullptr, uint appletId = 0); ~Applet(); //BOOKKEEPING /** * @return the id of this applet */ uint id() const; /** * @return The type of immutability of this applet */ Types::ImmutabilityType immutability() const; /** * If for some reason, the applet fails to get up on its feet (the * library couldn't be loaded, necessary hardware support wasn't found, * etc..) this method returns the reason why, in an user-readable way. * @since 5.0 **/ QString launchErrorMessage() const; /** * If for some reason, the applet fails to get up on its feet (the * library couldn't be loaded, necessary hardware support wasn't found, * etc..) this method returns true. **/ bool failedToLaunch() const; /** * @return true if destroy() was called; useful for Applets which should avoid * certain tasks if they are about to be deleted permanently */ bool destroyed() const; /** * @return the Containment, if any, this applet belongs to **/ Containment *containment() const; /** * @return true if this Applet is currently being used as a Containment, false otherwise */ bool isContainment() const; /** * @return the status of the applet * @since 4.4 */ Types::ItemStatus status() const; /** * Returns the current form factor the applet is being displayed in. * * @see Plasma::FormFactor */ Types::FormFactor formFactor() const; /** * Returns the location of the scene which is displaying applet. * * @see Plasma::Types::Location */ Types::Location location() const; + /** + * @return the preferred input mode, which will be the same + * for all applets. + * It's global to the device, which may be in Desktop(keyboard/mouse) or Tablet (only touchscreen) mode + * @since 5.42 + */ + Types::InputMode inputMode() const; + //CONFIGURATION /** * Returns the KConfigGroup to access the applets configuration. * * This config object will write to an instance * specific config file named \\rc * in the Plasma appdata directory. **/ KConfigGroup config() const; /** * Returns a KConfigGroup object to be shared by all applets of this * type. * * This config object will write to an applet-specific config object * named plasma_\rc in the local config directory. */ KConfigGroup globalConfig() const; /** * Returns the config skeleton object from this applet's package, * if any. * * @return config skeleton object, or 0 if none **/ KConfigLoader *configScheme() const; /** * Saves state information about this applet that will * be accessed when next instantiated in the restore(KConfigGroup&) method. * * This method does not need to be reimplmented by Applet * subclasses, but can be useful for Applet specializations * (such as Containment) to do so. * * Applet subclasses may instead want to reimplement saveState(). **/ virtual void save(KConfigGroup &group) const; /** * Restores state information about this applet saved previously * in save(KConfigGroup&). * * This method does not need to be reimplmented by Applet * subclasses, but can be useful for Applet specializations * (such as Containment) to do so. **/ virtual void restore(KConfigGroup &group); /** * @return true if the applet currently needs to be configured, * otherwise, false */ bool configurationRequired() const; /** * @return A translated message for the user explaining that the * applet needs configuring; this should note what needs * to be configured * * @see setConfigurationRequired * @since 5.20 */ QString configurationRequiredReason() const; /** * @return true when the configuration interface is being shown * @since 4.5 */ bool isUserConfiguring() const; /** * Tells the applet the user is configuring * @param configuring true if the configuration ui is showing */ void setUserConfiguring(bool configuring); //UTILS #ifndef PLASMA_NO_DEPRECATED /** * Accessor for the associated Package object if any. * Generally, only Plasmoids come in a Package. * Deprecated: please use kPackage() * * @deprecated use kPackage() instead * @return the Package object, or an invalid one if none **/ PLASMA_DEPRECATED Package package() const; #endif /** * Accessor for the associated Package object if any. * Generally, only Plasmoids come in a Package. * * @return the Package object, or an invalid one if none * @since 5.6 **/ KPackage::Package kPackage() const; /** * Called when any of the geometry constraints have been updated. * This method calls constraintsEvent, which may be reimplemented, * once the Applet has been prepared for updating the constraints. * * @param constraints the type of constraints that were updated */ void updateConstraints(Plasma::Types::Constraints constraints = Plasma::Types::AllConstraints); //METADATA /** * @return metadata information about this plugin * @see KPluginInfo, pluginMetaData * @since 5.0 * @deprecated use pluginMetaData instead */ PLASMA_DEPRECATED KPluginInfo pluginInfo() const; /** * @return metadata information about this plugin * * @since 5.27 */ KPluginMetaData pluginMetaData() const; /** * Returns the user-visible title for the applet, as specified in the * Name field of the .desktop file. Can be changed with @see setTitle * * @since 5.0 * @return the user-visible title for the applet. **/ QString title() const; /** * Sets a custom title for this instance of the applet. E.g. a clock might * use the timezone as its name rather than the .desktop file * * @since 5.0 * @param title the user-visible title for the applet. */ void setTitle(const QString &title); /** * Attempts to load an applet from a package * * Returns a pointer to the applet if successful. * The caller takes responsibility for the applet, including * deleting it when no longer needed. * Deprecated: use Containment::createApplet instead, you are not * supposed to have applets without containments * If you instance a plasmoid with this deprecated API, the * automated default setup scripts won't be executed for that plasmoid * * @param path the path to the package * @param appletId unique ID to assign the applet, or zero to have one * assigned automatically. * @return a pointer to the loaded applet, or 0 on load failure * @since 4.3 **/ PLASMA_DEPRECATED static Applet *loadPlasmoid(const QString &path, uint appletId = 0); /** * @returns The icon name related to this applet * By default is the one in the plasmoid desktop file **/ QString icon() const; /** * Sets an icon name for this applet * @param icon Freedesktop compatible icon name */ void setIcon(const QString &icon); /** * @returns true if the applet should show a busy status, for instance doing * some network operation * @since 5.21 */ bool isBusy() const; /** * Sets the Applet to have a busy status hint, for instance the applet doing * some network operation. * The graphical representation of the busy status depends completely from * the visualization. * @param busy true if the applet is busy * @since 5.21 */ void setBusy(bool busy); //ACTIONS /** * Returns a list of context-related QAction instances. * * This is used e.g. within the \a DesktopView to display a * contextmenu. * * @return A list of actions. The default implementation returns an * empty list. **/ virtual QList contextualActions(); /** * Returns the collection of actions for this Applet */ KActionCollection *actions() const; /** * Sets the global shortcut to associate with this widget. */ void setGlobalShortcut(const QKeySequence &shortcut); /** * @return the global shortcut associated with this wiget, or * an empty shortcut if no global shortcut is associated. */ QKeySequence globalShortcut() const; // ASSOCIATED APPLICATION /** * Sets an application associated to this applet, that will be * regarded as a full view of what is represented in the applet * * @param string the name of the application. it can be * \li a name understood by KService::serviceByDesktopName * (e.g. "konqueror") * \li a command in $PATH * \li or an absolute path to an executable * @since 4.4 */ void setAssociatedApplication(const QString &string); /** * Sets a list of urls associated to this application, * they will be used as parameters for the associated application * @see setAssociatedApplication() * * @param urls */ void setAssociatedApplicationUrls(const QList &urls); /** * @return the application associated to this applet * @since 4.4 */ QString associatedApplication() const; /** * @return the urls associated to this applet * @since 4.4 */ QList associatedApplicationUrls() const; /** * @return true if the applet has a valid associated application or urls * @since 4.4 */ bool hasValidAssociatedApplication() const; //Completely UI-specific, remove or move to scriptengine /** * @return true if this plasmoid provides a GUI configuration **/ bool hasConfigurationInterface() const; Q_SIGNALS: //BOOKEEPING /** * Emitted when the immutability changes * @since 4.4 */ void immutabilityChanged(Plasma::Types::ImmutabilityType immutable); /** * Emitted when the applet status changes * @since 4.4 */ void statusChanged(Plasma::Types::ItemStatus status); /** * Emitted when the applet has been scheduled for destruction * or the destruction has been undone * @since 5.4 */ void destroyedChanged(bool destroyed); /** * Emitted when the title has changed * @since 5.20 */ void titleChanged(const QString &title); /** * Emitted when the icon name for the applet has changed * @since 5.20 */ void iconChanged(const QString &icon); /** * Emitted when the busy status has changed * @since 5.21 */ void busyChanged(bool busy); //CONFIGURATION /** * Emitted when an applet has changed values in its configuration * and wishes for them to be saved at the next save point. As this implies * disk activity, this signal should be used with care. * * @note This does not need to be emitted from saveState by individual * applets. */ void configNeedsSaving(); /** * emitted when the config ui appears or disappears */ void userConfiguringChanged(bool configuring); //ACTIONS /** * Emitted just before the contextual actions are about to show * For instance just before the context menu containing the actions * added with setAction() is shown */ void contextualActionsAboutToShow(); /** * Emitted when activation is requested due to, for example, a global * keyboard shortcut. By default the wiget is given focus. */ void activated(); //TODO: fix usage in containment, port to QObject::destroyed /** * Emitted when the applet is deleted */ void appletDeleted(Plasma::Applet *applet); /** * Emitted when the formfactor changes */ void formFactorChanged(Plasma::Types::FormFactor formFactor); /** * Emitted when the location changes */ void locationChanged(Plasma::Types::Location location); /** * Emitted when setConfigurationRequired was called * @see setConfigurationRequired * @since 5.20 */ void configurationRequiredChanged(bool needsConfig, const QString &reason); + /** + * Emitted when the platform preferred input mode changed, + * such as when a transformable laptop goes from desktop + * to tablet mode + * @since 5.42 + */ + void inputModeChanged(Plasma::Types::InputMode mode); + public Q_SLOTS: //BOOKKEEPING /** * Call this method when the applet fails to launch properly. An * optional reason can be provided. * * Not that all children items will be deleted when this method is * called. If you have pointers to these items, you will need to * reset them after calling this method. * * @param failed true when the applet failed, false when it succeeded * @param reason an optional reason to show the user why the applet * failed to launch * @since 5.0 **/ void setLaunchErrorMessage(const QString &reason = QString()); /** * Sets the immutability type for this applet (not immutable, * user immutable or system immutable) * @param immutable the new immutability type of this applet */ void setImmutability(const Types::ImmutabilityType immutable); /** * Destroys the applet; it will be removed nicely and deleted. * Its configuration will also be deleted. * If you want to remove the Applet configuration, use this, don't just delete the Applet * */ void destroy(); /** * sets the status for this applet * @since 4.4 */ void setStatus(const Types::ItemStatus stat); //CONFIGURATION /** * Called when applet configuration values have changed. */ virtual void configChanged(); //UTILS /** * Sends all pending constraints updates to the applet. Will usually * be called automatically, but can also be called manually if needed. */ void flushPendingConstraintsEvents(); /** * This method is called once the applet is loaded and added to a Corona. * If the applet requires a Scene or has an particularly intensive * set of initialization routines to go through, consider implementing it * in this method instead of the constructor. * * Note: paintInterface may get called before init() depending on initialization * order. Painting is managed by the canvas (QGraphisScene), and may schedule a * paint event prior to init() being called. **/ virtual void init(); //ASSOCIATED APPLICATION /** * Open the application associated to this applet, if it's not set * but some urls are, open those urls with the proper application * for their mimetype * @see setAssociatedApplication() * @see setAssociatedApplicationUrls() * @since 4.4 */ void runAssociatedApplication(); protected: //CONSTRUCTORS /** * This constructor is to be used with the plugin loading systems * found in KPluginInfo and KService. The argument list is expected * to have two elements: the KService service ID for the desktop entry * and an applet ID which must be a base 10 number. * * @param parent a QObject parent; you probably want to pass in 0 * @param args a list of strings containing two entries: the service id * and the applet id */ Applet(QObject *parent, const QVariantList &args); //CONFIGURATION /** * When called, the Applet should write any information needed as part * of the Applet's running state to the configuration object in config() * and/or globalConfig(). * * Applets that always sync their settings/state with the config * objects when these settings/states change do not need to reimplement * this method. **/ virtual void saveState(KConfigGroup &config) const; /** * Sets whether or not this applet provides a user interface for * configuring the applet. * * It defaults to false, and if true is passed in you should * also reimplement createConfigurationInterface() * * @param hasInterface whether or not there is a user interface available **/ void setHasConfigurationInterface(bool hasInterface); /** * When the applet needs to be configured before being usable, this * method can be called to show a standard interface prompting the user * to configure the applet * * @param needsConfiguring true if the applet needs to be configured, * or false if it doesn't * @param reason a translated message for the user explaining that the * applet needs configuring; this should note what needs * to be configured */ void setConfigurationRequired(bool needsConfiguring, const QString &reason = QString()); //UTILS /** * Called when any of the constraints for the applet have been updated. These constraints * range from notifying when the applet has officially "started up" to when geometry changes * to when the form factor changes. * * Each constraint that has been changed is passed in the constraints flag. * All of the constraints and how they work is documented in the @see Plasma::Constraints * enumeration. * * On applet creation, this is always called prior to painting and can be used as an * opportunity to layout the widget, calculate sizings, etc. * * Do not call update() from this method; an update() will be triggered * at the appropriate time for the applet. * * @param constraints the type of constraints that were updated * @property constraint */ virtual void constraintsEvent(Plasma::Types::Constraints constraints); //TODO: timerEvent should go into AppletPrivate /** * Reimplemented from QObject */ void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE; private: /** * @internal This constructor is to be used with the Package loading system. * * @param parent a QObject parent; you probably want to pass in 0 * @param args a list of strings containing two entries: the service id * and the applet id * @since 4.3 */ Applet(const QString &packagePath, uint appletId); Q_PRIVATE_SLOT(d, void cleanUpAndDelete()) Q_PRIVATE_SLOT(d, void askDestroy()) Q_PRIVATE_SLOT(d, void updateShortcuts()) Q_PRIVATE_SLOT(d, void globalShortcutChanged()) Q_PRIVATE_SLOT(d, void propagateConfigChanged()) Q_PRIVATE_SLOT(d, void requestConfiguration()) AppletPrivate *const d; //Corona needs to access setLaunchErrorMessage and init friend class Corona; friend class CoronaPrivate; friend class Containment; friend class ContainmentPrivate; friend class AppletScript; friend class AppletPrivate; friend class AccessAppletJobPrivate; friend class GraphicsViewAppletPrivate; friend class PluginLoader; friend class AssociatedApplicationManager; }; } // Plasma namespace /** * Register an applet when it is contained in a loadable module */ #define K_EXPORT_PLASMA_APPLET(libname, classname) \ K_PLUGIN_FACTORY(factory, registerPlugin();) \ K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION) #define K_EXPORT_PLASMA_APPLET_WITH_JSON(libname, classname, jsonFile) \ K_PLUGIN_FACTORY_WITH_JSON(factory, jsonFile, registerPlugin();) \ K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION) #endif // multiple inclusion guard diff --git a/src/plasma/corona.cpp b/src/plasma/corona.cpp index cf99611d7..d3deae9ed 100644 --- a/src/plasma/corona.cpp +++ b/src/plasma/corona.cpp @@ -1,625 +1,631 @@ /* * Copyright 2007 Matt Broadstone * Copyright 2007-2011 Aaron Seigo * Copyright 2007 Riccardo Iaconelli * Copyright (c) 2009 Chani Armitage * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "corona.h" #include "private/corona_p.h" #include #include #include #include #include #include #include #include #include #include #include "containment.h" #include "pluginloader.h" #include "packagestructure.h" #include "private/applet_p.h" #include "private/containment_p.h" #include "private/package_p.h" #include "private/timetracker.h" #include "debug_p.h" using namespace Plasma; namespace Plasma { Corona::Corona(QObject *parent) : QObject(parent), d(new CoronaPrivate(this)) { #ifndef NDEBUG // qCDebug(LOG_PLASMA) << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "Corona ctor start"; #endif d->init(); #ifndef NDEBUG if (qEnvironmentVariableIsSet("PLASMA_TRACK_STARTUP")) { new TimeTracker(this); } #endif } Corona::~Corona() { KConfigGroup trans(KSharedConfig::openConfig(), "PlasmaTransientsConfig"); trans.deleteGroup(); delete d; } Plasma::Package Corona::package() const { Package p; p.d->internalPackage = new KPackage::Package(d->package); return p; } void Corona::setPackage(const Plasma::Package &package) { setKPackage(*package.d->internalPackage); emit packageChanged(package); } KPackage::Package Corona::kPackage() const { return d->package; } void Corona::setKPackage(const KPackage::Package &package) { d->package = package; emit kPackageChanged(package); } void Corona::saveLayout(const QString &configName) const { KSharedConfigPtr c; if (configName.isEmpty() || configName == d->configName) { c = config(); } else { c = KSharedConfig::openConfig(configName, KConfig::SimpleConfig); } d->saveLayout(c); } void Corona::exportLayout(KConfigGroup &config, QList containments) { foreach (const QString &group, config.groupList()) { KConfigGroup cg(&config, group); cg.deleteGroup(); } //temporarily unlock so that removal works Types::ImmutabilityType oldImm = immutability(); d->immutability = Types::Mutable; KConfigGroup dest(&config, "Containments"); KConfigGroup dummy; foreach (Plasma::Containment *c, containments) { c->save(dummy); c->config().reparent(&dest); //ensure the containment is unlocked //this is done directly because we have to bypass any Types::SystemImmutable checks c->Applet::d->immutability = Types::Mutable; foreach (Applet *a, c->applets()) { a->d->immutability = Types::Mutable; } c->destroy(); } //restore immutability d->immutability = oldImm; config.sync(); } void Corona::requestConfigSync() { // constant controlling how long between requesting a configuration sync // and one happening should occur. currently 10 seconds static const int CONFIG_SYNC_TIMEOUT = 10000; // TODO: should we check into our immutability before doing this? //NOTE: this is a pretty simplistic model: we simply save no more than CONFIG_SYNC_TIMEOUT // after the first time this is called. not much of a heuristic for save points, but // it should at least compress these activities a bit and provide a way for applet // authors to ween themselves from the sync() disease. A more interesting/dynamic // algorithm for determining when to actually sync() to disk might be better, though. if (!d->configSyncTimer->isActive()) { d->configSyncTimer->start(CONFIG_SYNC_TIMEOUT); } } void Corona::requireConfigSync() { d->syncConfig(); } void Corona::loadLayout(const QString &configName) { if (!configName.isEmpty() && configName != d->configName) { // if we have a new config name passed in, then use that as the config file for this Corona d->config = 0; d->configName = configName; } KConfigGroup conf(config(), QString()); if (!config()->groupList().isEmpty()) { d->importLayout(conf, false); } else { loadDefaultLayout(); d->notifyContainmentsReady(); } KConfigGroup cg(config(), "General"); setImmutability((Plasma::Types::ImmutabilityType)cg.readEntry("immutability", (int)Plasma::Types::Mutable)); } QList Corona::importLayout(const KConfigGroup &conf) { return d->importLayout(conf, true); } Containment *Corona::containmentForScreen(int screen) const { foreach (Containment *containment, d->containments) { if (containment->screen() == screen && (containment->containmentType() == Plasma::Types::DesktopContainment || containment->containmentType() == Plasma::Types::CustomContainment)) { return containment; } } return 0; } Containment *Corona::containmentForScreen(int screen, const QString &defaultPluginIfNonExistent, const QVariantList &defaultArgs) { Containment *containment = containmentForScreen(screen); if (!containment && !defaultPluginIfNonExistent.isEmpty()) { // screen requests are allowed to bypass immutability if (screen >= 0) { Plasma::Types::ImmutabilityType imm = d->immutability; d->immutability = Types::Mutable; containment = d->addContainment(defaultPluginIfNonExistent, defaultArgs, 0, false); if (containment) { // containment->setScreen(screen); } d->immutability = imm; } } return containment; } QList Corona::containments() const { return d->containments; } bool Corona::isStartupCompleted() const { return d->containmentsStarting <= 0; } KSharedConfigPtr Corona::config() const { if (!d->config) { d->config = KSharedConfig::openConfig(d->configName, KConfig::SimpleConfig); } return d->config; } Containment *Corona::createContainment(const QString &name, const QVariantList &args) { if (d->immutability == Types::Mutable || args.contains(QVariant::fromValue(QStringLiteral("org.kde.plasma:force-create")))) { return d->addContainment(name, args, 0); } return 0; } Containment *Corona::createContainmentDelayed(const QString &name, const QVariantList &args) { if (d->immutability == Types::Mutable) { return d->addContainment(name, args, 0, true); } return 0; } int Corona::screenForContainment(const Containment *) const { return -1; } int Corona::numScreens() const { return 1; } QRegion Corona::availableScreenRegion(int id) const { return QRegion(screenGeometry(id)); } QRect Corona::availableScreenRect(int id) const { return screenGeometry(id); } void Corona::loadDefaultLayout() { //Default implementation does nothing } Types::ImmutabilityType Corona::immutability() const { return d->immutability; } void Corona::setImmutability(const Types::ImmutabilityType immutable) { if (d->immutability == immutable || d->immutability == Types::SystemImmutable) { return; } #ifndef NDEBUG // qCDebug(LOG_PLASMA) << "setting immutability to" << immutable; #endif d->immutability = immutable; d->updateContainmentImmutability(); //tell non-containments that might care (like plasmaapp or a custom corona) emit immutabilityChanged(immutable); //update our actions QAction *action = d->actions.action(QStringLiteral("lock widgets")); if (action) { if (d->immutability == Types::SystemImmutable) { action->setEnabled(false); action->setVisible(false); } else { bool unlocked = d->immutability == Types::Mutable; action->setText(unlocked ? i18n("Lock Widgets") : i18n("Unlock Widgets")); action->setIcon(QIcon::fromTheme(unlocked ? QStringLiteral("object-locked") : QStringLiteral("object-unlocked"))); action->setEnabled(true); action->setVisible(true); } } if (d->immutability != Types::SystemImmutable) { KConfigGroup cg(config(), "General"); // we call the dptr member directly for locked since isImmutable() // also checks kiosk and parent containers cg.writeEntry("immutability", (int)d->immutability); requestConfigSync(); } } +Types::InputMode Corona::inputMode() const +{ + return d->inputMode; +} + QList Corona::freeEdges(int screen) const { QList freeEdges; freeEdges << Plasma::Types::TopEdge << Plasma::Types::BottomEdge << Plasma::Types::LeftEdge << Plasma::Types::RightEdge; foreach (Containment *containment, containments()) { if (containment->screen() == screen && freeEdges.contains(containment->location())) { freeEdges.removeAll(containment->location()); } } return freeEdges; } KActionCollection *Corona::actions() const { return &d->actions; } CoronaPrivate::CoronaPrivate(Corona *corona) : q(corona), immutability(Types::Mutable), + inputMode(Types::DesktopInputMode), config(0), configSyncTimer(new QTimer(corona)), actions(corona), containmentsStarting(0) { //TODO: make Package path configurable KConfigGroup config(KSharedConfig::openConfig(), "General"); if (QCoreApplication::instance()) { configName = QCoreApplication::instance()->applicationName() + QStringLiteral("-appletsrc"); } else { configName = QStringLiteral("plasma-appletsrc"); } } CoronaPrivate::~CoronaPrivate() { qDeleteAll(containments); } void CoronaPrivate::init() { desktopDefaultsConfig = KConfigGroup(KSharedConfig::openConfig(package.filePath("defaults")), "Desktop"); configSyncTimer->setSingleShot(true); QObject::connect(configSyncTimer, SIGNAL(timeout()), q, SLOT(syncConfig())); //some common actions actions.setConfigGroup(QStringLiteral("Shortcuts")); QAction *lockAction = actions.add(QStringLiteral("lock widgets")); QObject::connect(lockAction, SIGNAL(triggered(bool)), q, SLOT(toggleImmutability())); lockAction->setText(i18n("Lock Widgets")); lockAction->setAutoRepeat(true); lockAction->setIcon(QIcon::fromTheme(QStringLiteral("object-locked"))); lockAction->setData(Plasma::Types::ControlAction); lockAction->setShortcut(QKeySequence(QStringLiteral("alt+d, l"))); lockAction->setShortcutContext(Qt::ApplicationShortcut); //fake containment/applet actions KActionCollection *containmentActions = AppletPrivate::defaultActions(q); //containment has to start with applet stuff ContainmentPrivate::addDefaultActions(containmentActions); //now it's really containment } void CoronaPrivate::toggleImmutability() { if (immutability == Types::Mutable) { q->setImmutability(Types::UserImmutable); } else { q->setImmutability(Types::Mutable); } } void CoronaPrivate::saveLayout(KSharedConfigPtr cg) const { KConfigGroup containmentsGroup(cg, "Containments"); foreach (const Containment *containment, containments) { QString cid = QString::number(containment->id()); KConfigGroup containmentConfig(&containmentsGroup, cid); containment->save(containmentConfig); } } void CoronaPrivate::updateContainmentImmutability() { foreach (Containment *c, containments) { // we need to tell each containment that immutability has been altered c->updateConstraints(Types::ImmutableConstraint); } } void CoronaPrivate::containmentDestroyed(QObject *obj) { // we do a static_cast here since it really isn't an Containment by this // point anymore since we are in the qobject dtor. we don't actually // try and do anything with it, we just need the value of the pointer // so this unsafe looking code is actually just fine. Containment *containment = static_cast(obj); int index = containments.indexOf(containment); if (index > -1) { containments.removeAt(index); q->requestConfigSync(); } } void CoronaPrivate::syncConfig() { q->config()->sync(); emit q->configSynced(); } Containment *CoronaPrivate::addContainment(const QString &name, const QVariantList &args, uint id, bool delayedInit) { QString pluginName = name; Containment *containment = 0; Applet *applet = 0; // qCDebug(LOG_PLASMA) << "Loading" << name << args << id; if (pluginName.isEmpty() || pluginName == QLatin1String("default")) { // default to the desktop containment pluginName = desktopDefaultsConfig.readEntry("Containment", "org.kde.desktopcontainment"); } bool loadingNull = pluginName == QLatin1String("null"); if (!loadingNull) { applet = PluginLoader::self()->loadApplet(pluginName, id, args); containment = dynamic_cast(applet); if (containment) { containment->setParent(q); } } if (!containment) { if (!loadingNull) { #ifndef NDEBUG // qCDebug(LOG_PLASMA) << "loading of containment" << name << "failed."; #endif } // in case we got a non-Containment from Applet::loadApplet or // a null containment was requested if (applet) { // the applet probably doesn't know what's hit it, so let's pretend it can be // initialized to make assumptions in the applet's dtor safer applet->init(); delete applet; } applet = containment = new Containment(q, {}, id); //if it's a dummy containment, just say its ui is ready, not blocking the corona applet->updateConstraints(Plasma::Types::UiReadyConstraint); // we want to provide something and don't care about the failure to launch containment->setFormFactor(Plasma::Types::Planar); } // if this is a new containment, we need to ensure that there are no stale // configuration data around if (id == 0) { KConfigGroup conf(q->config(), "Containments"); conf = KConfigGroup(&conf, QString::number(containment->id())); conf.deleteGroup(); } //make sure the containments are sorted by id auto position = std::lower_bound(containments.begin(), containments.end(), containment, [](Plasma::Containment *c1, Plasma::Containment *c2) { return c1->id() < c2->id(); }); containments.insert(position, containment); QObject::connect(containment, SIGNAL(destroyed(QObject*)), q, SLOT(containmentDestroyed(QObject*))); QObject::connect(containment, SIGNAL(configNeedsSaving()), q, SLOT(requestConfigSync())); QObject::connect(containment, SIGNAL(screenChanged(int)), q, SIGNAL(screenOwnerChanged(int))); if (!delayedInit) { containment->init(); KConfigGroup cg = containment->config(); containment->restore(cg); containment->updateConstraints(Plasma::Types::StartupCompletedConstraint); containment->save(cg); q->requestConfigSync(); containment->flushPendingConstraintsEvents(); emit q->containmentAdded(containment); //if id = 0 a new containment has been created, not restored if (id == 0) { emit q->containmentCreated(containment); } } return containment; } QList CoronaPrivate::importLayout(const KConfigGroup &conf, bool mergeConfig) { if (!conf.isValid()) { return QList(); } QList newContainments; QSet containmentsIds; foreach (Containment *containment, containments) { containmentsIds.insert(containment->id()); } KConfigGroup containmentsGroup(&conf, "Containments"); QStringList groups = containmentsGroup.groupList(); qSort(groups.begin(), groups.end()); foreach (const QString &group, groups) { KConfigGroup containmentConfig(&containmentsGroup, group); if (containmentConfig.entryMap().isEmpty()) { continue; } uint cid = group.toUInt(); if (containmentsIds.contains(cid)) { cid = ++AppletPrivate::s_maxAppletId; } else if (cid > AppletPrivate::s_maxAppletId) { AppletPrivate::s_maxAppletId = cid; } if (mergeConfig) { KConfigGroup realConf(q->config(), "Containments"); realConf = KConfigGroup(&realConf, QString::number(cid)); // in case something was there before us realConf.deleteGroup(); containmentConfig.copyTo(&realConf); } //qCDebug(LOG_PLASMA) << "got a containment in the config, trying to make a" << containmentConfig.readEntry("plugin", QString()) << "from" << group; #ifndef NDEBUG // qCDebug(LOG_PLASMA) << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "Adding Containment" << containmentConfig.readEntry("plugin", QString()); #endif Containment *c = addContainment(containmentConfig.readEntry("plugin", QString()), QVariantList(), cid); if (!c) { continue; } newContainments.append(c); containmentsIds.insert(c->id()); #ifndef NDEBUG // qCDebug(LOG_PLASMA) << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "Restored Containment" << c->pluginName(); #endif } if (!mergeConfig) { notifyContainmentsReady(); } return newContainments; } void CoronaPrivate::notifyContainmentsReady() { containmentsStarting = 0; foreach (Containment *containment, containments) { if (!containment->isUiReady() && containment->screen() >= 0) { ++containmentsStarting; QObject::connect(containment, &Plasma::Containment::uiReadyChanged, q, [this](bool ready) { containmentReady(ready); } ); } } if (containmentsStarting <= 0) { emit q->startupCompleted(); } } void CoronaPrivate::containmentReady(bool ready) { if (!ready) { return; } --containmentsStarting; if (containmentsStarting <= 0) { emit q->startupCompleted(); } } } // namespace Plasma #include "moc_corona.cpp" diff --git a/src/plasma/corona.h b/src/plasma/corona.h index 6a5d004bd..92b9d66c4 100644 --- a/src/plasma/corona.h +++ b/src/plasma/corona.h @@ -1,392 +1,407 @@ /* * Copyright 2007 Aaron Seigo * Copyright 2007 Matt Broadstone * Copyright 2012 Marco MArtin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef PLASMA_CORONA_H #define PLASMA_CORONA_H #include #include #include class QAction; namespace Plasma { class CoronaPrivate; /** * @class Corona plasma/Corona.h * * @short A bookkeeping Scene for Plasma::Applets */ class PLASMA_EXPORT Corona : public QObject { Q_OBJECT Q_PROPERTY(bool isStartupCompleted READ isStartupCompleted NOTIFY startupCompleted) Q_PROPERTY(Package package READ package NOTIFY packageChanged) Q_PROPERTY(KPackage::Package kPackage READ kPackage NOTIFY kPackageChanged) public: explicit Corona(QObject *parent = nullptr); ~Corona(); #ifndef PLASMA_NO_DEPRECATED /** * Accessor for the associated Package object if any. * A Corona package defines how Containments are laid out in a View, * ToolBoxes, default layout, error messages * and in genelal all the furniture specific of a particular * device form factor. * * @deprecated use kPackage instead * @return the Package object, or an invalid one if none * @since 5.0 **/ PLASMA_DEPRECATED Plasma::Package package() const; /** * Setting the package name * @deprecated use setKPackage instead */ PLASMA_DEPRECATED void setPackage(const Plasma::Package &package); #endif /** * Accessor for the associated Package object if any. * A Corona package defines how Containments are laid out in a View, * ToolBoxes, default layout, error messages * and in genelal all the furniture specific of a particular * device form factor. * * @return the Package object, or an invalid one if none * @since 5.5 **/ KPackage::Package kPackage() const; /** * Setting the package for the corona * @since 5.5 */ void setKPackage(const KPackage::Package &package); /** * @return all containments on this Corona */ QList containments() const; /** * @returns true when the startup is over, and * all the ui graphics has been instantiated */ bool isStartupCompleted() const; /** * Returns the config file used to store the configuration for this Corona */ KSharedConfig::Ptr config() const; /** * Adds a Containment to the Corona * * @param name the plugin name for the containment, as given by * KPluginInfo::pluginName(). If an empty string is passed in, the default * containment plugin will be used (usually DesktopContainment). If the * string literal "null" is passed in, then no plugin will be loaded and * a simple Containment object will be created instead. * @param args argument list to pass to the containment * * @return a pointer to the containment on success, or 0 on failure. Failure can be * caused by too restrictive of an Immutability type, as containments cannot be added * when widgets are locked. * If the requested containment plugin can not be located or successfully loaded, the Containment will have an invalid pluginInfo(). */ Containment *createContainment(const QString &name, const QVariantList &args = QVariantList()); /** * Returns the Containment, if any, for a given physical screen * * @param screen number of the physical screen to locate */ Containment *containmentForScreen(int screen) const; /** * Returns the Containment for a given physical screen and desktop, creating one * if none exists * * @param screen number of the physical screen to locate * @param defaultPluginIfNonExistent the plugin to load by default; "null" is an empty * Containment and "default" creates the default plugin * @param defaultArgs optional arguments to pass in when creating a Containment if needed */ Containment *containmentForScreen(int screen, const QString &defaultPluginIfNonExistent, const QVariantList &defaultArgs = QVariantList()); /** * Returns the number of screens available to plasma. * Subclasses should override this method as the default * implementation returns a meaningless value. */ virtual int numScreens() const; /** * Returns the geometry of a given screen. * Valid screen ids are 0 to numScreen()-1, or -1 for the full desktop geometry. * Subclasses should override this method as the default * implementation returns a meaningless value. */ virtual QRect screenGeometry(int id) const = 0; /** * Returns the available region for a given screen. * The available region excludes panels and similar windows. * Valid screen ids are 0 to numScreens()-1. * By default this method returns a rectangular region * equal to screenGeometry(id); subclasses that need another * behavior should override this method. */ virtual QRegion availableScreenRegion(int id) const; /** * Returns the available rect for a given screen. * The difference between this and availableScreenRegion() * is that this method returns only a rectangular * available space (it doesn't care if your panel is not 100% width). * The available rect excludes panels and similar windows. * Valid screen ids are 0 to numScreens()-1. * By default this method returns a rectangular region * equal to screenGeometry(id); subclasses that need another * behavior should override this method. */ virtual QRect availableScreenRect(int id) const; /** * This method is useful in order to retrieve the list of available * screen edges for panel type containments. * @param screen the id of the screen to look for free edges. * @returns a list of free edges not filled with panel type containments. */ QList freeEdges(int screen) const; /** * The actions assocated with this Corona */ KActionCollection *actions() const; /** * Imports an applet layout from a config file. The results will be added to the * current set of Containments. * * @param config the name of the config file to load from, * or the default config file if QString() * @return the list of containments that were loaded * @since 4.6 */ QList importLayout(const KConfigGroup &config); /** * Exports a set of containments to a config file. * * @param config the config group to save to * @param containments the list of containments to save * @since 4.6 */ void exportLayout(KConfigGroup &config, QList containments); /** * @returns the id of the screen which is showing @p containment * -1 is returned if the containment is not associated with a screen. */ virtual int screenForContainment(const Containment *containment) const; /** * @return The type of immutability of this Corona */ Types::ImmutabilityType immutability() const; + /** + * @return the preferred input mode for the whole corona. + * It's global to the device, which may be in Desktop(keyboard/mouse) or Tablet (only touchscreen) mode + * @since 5.42 + */ + Types::InputMode inputMode() const; + public Q_SLOTS: /** * Load applet layout from a config file. The results will be added to the * current set of Containments. * * @param config the name of the config file to load from, * or the default config file if QString() */ void loadLayout(const QString &config = QString()); /** * Save applets layout to file * @param config the file to save to, or the default config file if QString() */ void saveLayout(const QString &config = QString()) const; /** * Sets the immutability type for this Corona (not immutable, * user immutable or system immutable) * @param immutable the new immutability type of this applet */ void setImmutability(const Types::ImmutabilityType immutable); /** * Schedules a flush-to-disk synchronization of the configuration state * at the next convenient moment. */ void requestConfigSync(); /** * Schedules a time sensitive flush-to-disk synchronization of the * configuration state. Since this method does not provide any sort of * event compression, it should only be used when an *immediate* disk * sync is *absolutely* required. Otherwise, use @see requestConfigSync() * which does do event compression. */ void requireConfigSync(); Q_SIGNALS: /** * This signal indicates a new containment has been added to * the Corona: it may occur after creation or restore from config */ void containmentAdded(Plasma::Containment *containment); /** * This signal indicates a new containment has been created * in the Corona. Compared to containmentAdded it can only happen * after the creation of a new containment. * * @see containmentAdded * @since 5.16 */ void containmentCreated(Plasma::Containment *containment); /** * This signal indicates that a containment has been newly * associated (or dissociated) with a physical screen. * * @param isScreen the screen it is now associated with */ void screenOwnerChanged(int isScreen); /** * This signal indicates that the configuration file was flushed to disk. */ void configSynced(); /** * This signal indicates that a change in available screen geometry occurred. */ void availableScreenRegionChanged(); /** * This signal indicates that a change in available screen geometry occurred. */ void availableScreenRectChanged(); /** * This signal indicates that a change in geometry for the screen occurred. */ void screenGeometryChanged(int id); /** * emitted when immutability changes. * this is for use by things that don't get constraints events, like plasmaapp. * it's NOT for containments or applets or any of the other stuff on the scene. * if your code's not in shells/ it probably shouldn't be using it. */ void immutabilityChanged(Plasma::Types::ImmutabilityType immutability); + /** + * Emitted when the preferred input mode changed, such + * as a transformable laptop switched from laptop to tablet + * mode. + * @since 5.42 + */ + void inputModeChanged(Plasma::Types::InputMode); + /** This signal indicates the screen with the specified id was removed. * @since 5.40 */ void screenRemoved(int id); /** This signal indicates a new screen with the specified id was added. * @since 5.40 */ void screenAdded(int id); #ifndef PLASMA_NO_DEPRECATED /** * Emitted when the package for this corona has been changed. * Shells must support changing the shell package on the fly (for instance due to device form factor changing) * * @deprecated use kPackageChanged instead * @param package the new package that defines the Corona furniture and behavior */ PLASMA_DEPRECATED void packageChanged(const Plasma::Package &package); #endif /** * Emitted when the package for this corona has been changed. * Shells must support changing the shell package on the fly (for instance due to device form factor changing) * * @param package the new package that defines the Corona furniture and behavior */ void kPackageChanged(const KPackage::Package &package); /** * Emitted when the startup phase has been completed */ void startupCompleted(); protected: /** * Loads the default (system wide) layout for this user **/ virtual void loadDefaultLayout(); /** * Loads a containment with delayed initialization, primarily useful * for implementations of loadDefaultLayout. The caller is responsible * for all initializating, saving and notification of a new containment. * * @param name the plugin name for the containment, as given by * KPluginInfo::pluginName(). If an empty string is passed in, the defalt * containment plugin will be used (usually DesktopContainment). If the * string literal "null" is passed in, then no plugin will be loaded and * a simple Containment object will be created instead. * @param args argument list to pass to the containment * * @return a pointer to the containment on success, or 0 on failure. Failure can * be caused by the Immutability type being too restrictive, as containments can't be added * when widgets are locked, or if the requested containment plugin can not be located * or successfully loaded. * @see addContainment **/ Containment *createContainmentDelayed(const QString &name, const QVariantList &args = QVariantList()); private: CoronaPrivate *const d; Q_PRIVATE_SLOT(d, void containmentDestroyed(QObject *)) Q_PRIVATE_SLOT(d, void syncConfig()) Q_PRIVATE_SLOT(d, void toggleImmutability()) Q_PRIVATE_SLOT(d, void containmentReady(bool)) friend class CoronaPrivate; friend class View; }; } // namespace Plasma #endif diff --git a/src/plasma/plasma.h b/src/plasma/plasma.h index 5f8936d1d..a257faa05 100644 --- a/src/plasma/plasma.h +++ b/src/plasma/plasma.h @@ -1,315 +1,326 @@ /* * Copyright 2005 by Aaron Seigo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef PLASMA_DEFS_H #define PLASMA_DEFS_H /** @header plasma/plasma.h */ #include #include class QAction; /** * Namespace for everything in libplasma */ namespace Plasma { /** * @class Types plasma/plasma.h * @short Enums and constants used in Plasma * */ class PLASMA_EXPORT Types : public QObject { Q_OBJECT public: ~Types(); /** * The Constraint enumeration lists the various constraints that Plasma * objects have managed for them and which they may wish to react to, * for instance in Applet::constraintsUpdated */ enum Constraint { NoConstraint = 0, /**< No constraint; never passed in to Applet::constraintsEvent on its own */ FormFactorConstraint = 1, /**< The FormFactor for an object */ LocationConstraint = 2, /**< The Location of an object */ ScreenConstraint = 4, /**< Which screen an object is on */ ImmutableConstraint = 8, /**< the immutability (locked) nature of the applet changed */ StartupCompletedConstraint = 16, /**< application startup has completed */ ContextConstraint = 32, /**< the context (e.g. activity) has changed */ UiReadyConstraint = 64, /**< The ui has been completely loaded */ // (FIXME: merged with StartupCompletedConstraint?) + InputModeConstraint = 128, /** Yhe preferred input mode changed, eg from Desktop to Tablet @since 5.42*/ AllConstraints = FormFactorConstraint | LocationConstraint | ScreenConstraint | - ImmutableConstraint + ImmutableConstraint | InputModeConstraint }; Q_ENUM(Constraint) Q_DECLARE_FLAGS(Constraints, Constraint) /** * The FormFactor enumeration describes how a Plasma::Applet should arrange * itself. The value is derived from the container managing the Applet * (e.g. in Plasma, a Corona on the desktop or on a panel). **/ enum FormFactor { Planar = 0, /**< The applet lives in a plane and has two degrees of freedom to grow. Optimize for desktop, laptop or tablet usage: a high resolution screen 1-3 feet distant from the viewer. */ MediaCenter, /**< As with Planar, the applet lives in a plane but the interface should be optimized for medium-to-high resolution screens that are 5-15 feet distant from the viewer. Sometimes referred to as a "ten foot interface".*/ Horizontal, /**< The applet is constrained vertically, but can expand horizontally. */ Vertical, /**< The applet is constrained horizontally, but can expand vertically. */ Application /**< The Applet lives in a plane and should be optimized to look as a full application, for the desktop or the particular device. */ }; Q_ENUM(FormFactor) + /** + * The preferred input mode the device is in can influence how the UI looks, in Tabllet mode it will have bigger touch friendly controls and gestures will be preferred compared to Desktop mode where mouse and keyboard are preferred + * @since 5.42 + */ + enum InputMode { + DesktopInputMode = 1, /** Mouse and keyboard preferred */ + TabletInputMode /** Touchscreen preferred (this includes tablets, phones or transformable laptops in tablet mode)*/ + }; + Q_ENUM(InputMode) + /** * This enumeration describes the type of the Containment. * DesktopContainments represent main containments that will own a screen in a mutually exclusive fashion, * while PanelContainments are accessories which can be present multiple per screen. */ enum ContainmentType { NoContainmentType = -1, /**< @internal */ DesktopContainment = 0, /**< A desktop containment */ PanelContainment, /**< A desktop panel */ CustomContainment = 127, /**< A containment that is neither a desktop nor a panel but something application specific */ CustomPanelContainment = 128, /**< A customized desktop panel */ CustomEmbeddedContainment = 129 /**< A customized containment embedded in another applet */ }; Q_ENUM(ContainmentType) /** * A descriptrive type for QActions, to help categorizing them when presented to the user */ enum ActionType { AddAction = 0, /**< The action will cause something new being created*/ ConfigureAction = 100, /**< The Action will make some kind of configuration ui to appear */ ControlAction = 200, /**< Generic control, similar to ConfigureAction TODO: better doc */ MiscAction = 300, /**< A type of action that doesn't fit in the oher categories */ DestructiveAction = 400, /**< A dangerous action, such as deletion of objects, plasmoids and files. They are intended to be shown separed from other actions */ UserAction = DestructiveAction + 1000 /**< If new types are needed in a C++ implementation, define them as ids more than UserAction*/ }; Q_ENUM(ActionType) /** * The Direction enumeration describes in which direction, relative to the * Applet (and its managing container), popup menus, expanders, balloons, * message boxes, arrows and other such visually associated widgets should * appear in. This is usually the oposite of the Location. **/ enum Direction { Down = 0, /**< Display downards */ Up, /**< Display upwards */ Left, /**< Display to the left */ Right /**< Display to the right */ }; Q_ENUM(Direction) /** * The Location enumeration describes where on screen an element, such as an * Applet or its managing container, is positioned on the screen. **/ enum Location { Floating = 0, /**< Free floating. Neither geometry or z-ordering is described precisely by this value. */ Desktop, /**< On the planar desktop layer, extending across the full screen from edge to edge */ FullScreen, /**< Full screen */ TopEdge, /**< Along the top of the screen*/ BottomEdge, /**< Along the bottom of the screen*/ LeftEdge, /**< Along the left side of the screen */ RightEdge /**< Along the right side of the screen */ }; Q_ENUM(Location) /** * The position enumeration * **/ enum Position { LeftPositioned, /**< Positioned left */ RightPositioned, /**< Positioned right */ TopPositioned, /**< Positioned top */ BottomPositioned, /**< Positioned bottom */ CenterPositioned /**< Positioned in the center */ }; Q_ENUM(Position) /** * The popup position enumeration relatively to his attached widget * **/ enum PopupPlacement { FloatingPopup = 0, /**< Free floating, non attached popup */ TopPosedLeftAlignedPopup, /**< Popup positioned on the top, aligned to the left of the wigdet */ TopPosedRightAlignedPopup, /**< Popup positioned on the top, aligned to the right of the widget */ LeftPosedTopAlignedPopup, /**< Popup positioned on the left, aligned to the top of the wigdet */ LeftPosedBottomAlignedPopup, /**< Popup positioned on the left, aligned to the bottom of the widget */ BottomPosedLeftAlignedPopup, /**< Popup positioned on the bottom, aligned to the left of the wigdet */ BottomPosedRightAlignedPopup, /**< Popup positioned on the bottom, aligned to the right of the widget */ RightPosedTopAlignedPopup, /**< Popup positioned on the right, aligned to the top of the wigdet */ RightPosedBottomAlignedPopup /**< Popup positioned on the right, aligned to the bottom of the widget */ }; Q_ENUM(PopupPlacement) /** * Flip enumeration */ enum FlipDirection { NoFlip = 0, /**< Do not flip */ HorizontalFlip = 1, /**< Flip horizontally */ VerticalFlip = 2 /**< Flip vertically */ }; Q_ENUM(FlipDirection) Q_DECLARE_FLAGS(Flip, FlipDirection) /** * Possible timing alignments **/ enum IntervalAlignment { NoAlignment = 0, /**< No alignment **/ AlignToMinute, /**< Align to the minute **/ AlignToHour /**< Align to the hour **/ }; Q_ENUM(IntervalAlignment) /** * Defines the immutability of items like applets, corona and containments * they can be free to modify, locked down by the user or locked down by the * system (e.g. kiosk setups). */ enum ImmutabilityType { Mutable = 1, /**< The item can be modified in any way **/ UserImmutable = 2, /**< The user has requested a lock down, and can undo the lock down at any time **/ SystemImmutable = 4 /**< the item is locked down by the system, the user can't unlock it **/ }; Q_ENUM(ImmutabilityType) /** * The ComonentType enumeration refers to the various types of components, * or plugins, supported by plasma. */ enum ComponentType { AppletComponent = 1, /**< Plasma::Applet based plugins **/ DataEngineComponent = 2, /**< Plasma::DataEngine based plugins **/ ContainmentComponent = 4,/**< Plasma::Containment based plugins **/ WallpaperComponent = 8, /**< Plasma::Wallpaper based plugins **/ GenericComponent = 16 /** Generic repositories of files, usually they keep QML files and their assets **/ }; Q_ENUM(ComponentType) Q_DECLARE_FLAGS(ComponentTypes, ComponentType) enum MarginEdge { TopMargin = 0, /**< The top margin **/ BottomMargin, /**< The bottom margin **/ LeftMargin, /**< The left margin **/ RightMargin /**< The right margin **/ }; Q_ENUM(MarginEdge) /** * Status of an applet * @since 4.3 */ enum ItemStatus { UnknownStatus = 0, /**< The status is unknown **/ PassiveStatus = 1, /**< The Item is passive **/ ActiveStatus = 2, /**< The Item is active **/ NeedsAttentionStatus = 3, /**< The Item needs attention **/ RequiresAttentionStatus = 4, /**< The Item needs persistent attention **/ AcceptingInputStatus = 5, /**< The Item is accepting input **/ //FIXME KF6: this should be the smallest status HiddenStatus = 6 /**< The Item will be hidden totally **/ }; Q_ENUM(ItemStatus) enum TrustLevel { UnverifiableTrust = 0, /**< The trust of the object can not be verified, usually because no trust information (e.g. a cryptographic signature) was provided */ CompletelyUntrusted, /**< The signature is broken/expired/false */ UnknownTrusted, /**< The signature is valid, but the key is unknown */ UserTrusted, /**< The signature is valid and made with a key signed by one of the user's own keys*/ SelfTrusted, /**< The signature is valid and made with one of the user's own keys*/ FullyTrusted, /**< The signature is valid and made with a key signed by the vendor's key*/ UltimatelyTrusted /**< The signature is valid and made with the vendor's key*/ }; Q_ENUM(TrustLevel) /** * Description on how draw a background for the applet */ enum BackgroundHints { NoBackground = 0, /**< Not drawing a background under the applet, the applet has its own implementation */ StandardBackground = 1, /**< The standard background from the theme is drawn */ TranslucentBackground = 2, /**< An alternate version of the background is drawn, usually more translucent */ DefaultBackground = StandardBackground /**< Default settings: both standard background */ }; Q_ENUM(BackgroundHints) private: Types(QObject *parent = nullptr); }; /** * Converts a location to a direction. Handy for figuring out which way to send a popup based on * location or to point arrows and other directional items. * * @param location the location of the container the element will appear in * @return the visual direction the element should be oriented in **/ PLASMA_EXPORT Types::Direction locationToDirection(Types::Location location); /** * Converts a location to the direction facing it. Handy for figuring out which way to collapse * a popup or to point arrows at the item itself. * * @param location the location of the container the element will appear in * @return the visual direction the element should be oriented in **/ PLASMA_EXPORT Types::Direction locationToInverseDirection(Types::Location location); } // Plasma namespace Q_DECLARE_OPERATORS_FOR_FLAGS(Plasma::Types::Constraints) Q_DECLARE_OPERATORS_FOR_FLAGS(Plasma::Types::Flip) Q_DECLARE_OPERATORS_FOR_FLAGS(Plasma::Types::ComponentTypes) #endif // multiple inclusion guard diff --git a/src/plasma/private/corona_p.h b/src/plasma/private/corona_p.h index d556baf36..ff8c337f0 100644 --- a/src/plasma/private/corona_p.h +++ b/src/plasma/private/corona_p.h @@ -1,67 +1,68 @@ /* * Copyright 2007-2011 Aaron Seigo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef PLASMA_CORONA_P_H #define PLASMA_CORONA_P_H #include #include #include "package.h" class KShortcutsDialog; namespace Plasma { class Containment; class CoronaPrivate { public: CoronaPrivate(Corona *corona); ~CoronaPrivate(); void init(); void toggleImmutability(); void saveLayout(KSharedConfigPtr cg) const; void updateContainmentImmutability(); void containmentDestroyed(QObject *obj); void syncConfig(); void notifyContainmentsReady(); void containmentReady(bool ready); Containment *addContainment(const QString &name, const QVariantList &args, uint id, bool delayedInit = false); QList importLayout(const KConfigGroup &conf, bool mergeConfig); Corona *q; KPackage::Package package; KConfigGroup desktopDefaultsConfig; Types::ImmutabilityType immutability; + Types::InputMode inputMode; QString configName; KSharedConfigPtr config; QTimer *configSyncTimer; QList containments; KActionCollection actions; int containmentsStarting; }; } #endif