File indexing completed on 2024-05-12 17:10:22

0001 /*
0002     SPDX-FileCopyrightText: 2009 Aaron Seigo <aseigo@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "containment.h"
0008 
0009 #include <QAction>
0010 #include <QQuickItem>
0011 
0012 #include <kactioncollection.h>
0013 #include <kdeclarative/configpropertymap.h>
0014 #include <klocalizedstring.h>
0015 
0016 #include <Plasma/Containment>
0017 #include <Plasma/Corona>
0018 #include <Plasma/PluginLoader>
0019 
0020 #include "scriptengine.h"
0021 #include "shellcorona.h"
0022 #include "widget.h"
0023 
0024 namespace WorkspaceScripting
0025 {
0026 class Containment::Private
0027 {
0028 public:
0029     QPointer<Plasma::Containment> containment;
0030     ShellCorona *corona;
0031     QString oldWallpaperPlugin;
0032     QString wallpaperPlugin;
0033     QString oldWallpaperMode;
0034     QString wallpaperMode;
0035 
0036     QString type;
0037     QString plugin;
0038 };
0039 
0040 Containment::Containment(Plasma::Containment *containment, ScriptEngine *engine)
0041     : Applet(engine)
0042     , d(new Containment::Private)
0043 {
0044     d->containment = containment;
0045     d->corona = qobject_cast<ShellCorona *>(containment->corona());
0046 
0047     setCurrentConfigGroup(QStringList());
0048     setCurrentGlobalConfigGroup(QStringList());
0049     if (containment) {
0050         d->oldWallpaperPlugin = d->wallpaperPlugin = containment->wallpaper();
0051     }
0052 }
0053 
0054 Containment::~Containment()
0055 {
0056     if (d->containment) {
0057         if (d->oldWallpaperPlugin != d->wallpaperPlugin || d->oldWallpaperMode != d->wallpaperMode) {
0058             d->containment->setWallpaper(d->wallpaperPlugin);
0059         }
0060     }
0061 
0062     reloadConfigIfNeeded();
0063 
0064     delete d;
0065 }
0066 
0067 ShellCorona *Containment::corona() const
0068 {
0069     return d->corona;
0070 }
0071 
0072 int Containment::screen() const
0073 {
0074     if (!d->containment) {
0075         return -1;
0076     }
0077 
0078     return d->containment->screen();
0079 }
0080 
0081 QString Containment::wallpaperPlugin() const
0082 {
0083     return d->wallpaperPlugin;
0084 }
0085 
0086 void Containment::setWallpaperPlugin(const QString &wallpaperPlugin)
0087 {
0088     d->wallpaperPlugin = wallpaperPlugin;
0089 }
0090 
0091 QString Containment::wallpaperMode() const
0092 {
0093     return d->wallpaperMode;
0094 }
0095 
0096 void Containment::setWallpaperMode(const QString &wallpaperMode)
0097 {
0098     d->wallpaperMode = wallpaperMode;
0099 }
0100 
0101 QString Containment::formFactor() const
0102 {
0103     if (!d->containment) {
0104         return QStringLiteral("Planar");
0105     }
0106 
0107     switch (d->containment->formFactor()) {
0108     case Plasma::Types::Planar:
0109         return QStringLiteral("planar");
0110     case Plasma::Types::MediaCenter:
0111         return QStringLiteral("mediacenter");
0112     case Plasma::Types::Horizontal:
0113         return QStringLiteral("horizontal");
0114     case Plasma::Types::Vertical:
0115         return QStringLiteral("vertical");
0116     case Plasma::Types::Application:
0117         return QStringLiteral("application");
0118     }
0119 
0120     return QStringLiteral("Planar");
0121 }
0122 
0123 QList<int> Containment::widgetIds() const
0124 {
0125     // FIXME: the ints could overflow since Applet::id() returns a uint,
0126     //       however QScript deals with QList<uint> very, very poory
0127     QList<int> w;
0128 
0129     if (d->containment) {
0130         foreach (const Plasma::Applet *applet, d->containment->applets()) {
0131             w.append(applet->id());
0132         }
0133     }
0134 
0135     return w;
0136 }
0137 
0138 QJSValue Containment::widgetById(const QJSValue &paramId) const
0139 {
0140     if (!paramId.isNumber()) {
0141         return engine()->newError(i18n("widgetById requires an id"));
0142     }
0143 
0144     const uint id = paramId.toInt();
0145 
0146     if (d->containment) {
0147         foreach (Plasma::Applet *w, d->containment->applets()) {
0148             if (w->id() == id) {
0149                 return engine()->wrap(w);
0150             }
0151         }
0152     }
0153 
0154     return QJSValue();
0155 }
0156 
0157 QJSValue Containment::addWidget(const QJSValue &v, qreal x, qreal y, qreal w, qreal h, const QVariantList &args)
0158 {
0159     if (!v.isString() && !v.isQObject()) {
0160         return engine()->newError(i18n("addWidget requires a name of a widget or a widget object"));
0161     }
0162 
0163     if (!d->containment) {
0164         return QJSValue();
0165     }
0166 
0167     QRectF geometry(x, y, w, h);
0168 
0169     Plasma::Applet *applet = nullptr;
0170     if (v.isString()) {
0171         // A position has been supplied: search for the containment's graphics object
0172         QQuickItem *containmentItem = nullptr;
0173 
0174         if (geometry.x() >= 0 && geometry.y() >= 0) {
0175             containmentItem = d->containment->property("_plasma_graphicObject").value<QQuickItem *>();
0176 
0177             if (containmentItem) {
0178                 QMetaObject::invokeMethod(containmentItem,
0179                                           "createApplet",
0180                                           Qt::DirectConnection,
0181                                           Q_RETURN_ARG(Plasma::Applet *, applet),
0182                                           Q_ARG(QString, v.toString()),
0183                                           Q_ARG(QVariantList, args),
0184                                           Q_ARG(QRectF, geometry));
0185             }
0186             if (applet) {
0187                 return engine()->wrap(applet);
0188             }
0189             return engine()->newError(i18n("Could not create the %1 widget!", v.toString()));
0190         }
0191 
0192         // Case in which either:
0193         // * a geometry wasn't provided
0194         // * containmentItem wasn't found
0195         applet = d->containment->createApplet(v.toString(), args);
0196 
0197         if (applet) {
0198             return engine()->wrap(applet);
0199         }
0200 
0201         return engine()->newError(i18n("Could not create the %1 widget!", v.toString()));
0202     } else if (Widget *widget = qobject_cast<Widget *>(v.toQObject())) {
0203         applet = widget->applet();
0204         d->containment->addApplet(applet);
0205         return v;
0206     }
0207 
0208     return QJSValue();
0209 }
0210 
0211 QJSValue Containment::widgets(const QString &widgetType) const
0212 {
0213     if (!d->containment) {
0214         return QJSValue();
0215     }
0216 
0217     QJSValue widgets = engine()->newArray();
0218     int count = 0;
0219 
0220     foreach (Plasma::Applet *widget, d->containment->applets()) {
0221         if (widgetType.isEmpty() || widget->pluginMetaData().pluginId() == widgetType) {
0222             widgets.setProperty(count, engine()->wrap(widget));
0223             ++count;
0224         }
0225     }
0226 
0227     widgets.setProperty(QStringLiteral("length"), count);
0228     return widgets;
0229 }
0230 
0231 uint Containment::id() const
0232 {
0233     if (!d->containment) {
0234         return 0;
0235     }
0236 
0237     return d->containment->id();
0238 }
0239 
0240 QString Containment::type() const
0241 {
0242     if (!d->containment) {
0243         return QString();
0244     }
0245 
0246     return d->containment->pluginMetaData().pluginId();
0247 }
0248 
0249 void Containment::remove()
0250 {
0251     if (d->containment) {
0252         d->containment->destroy();
0253     }
0254 }
0255 
0256 void Containment::showConfigurationInterface()
0257 {
0258     if (d->containment) {
0259         QAction *configAction = d->containment->actions()->action(QStringLiteral("configure"));
0260         if (configAction && configAction->isEnabled()) {
0261             configAction->trigger();
0262         }
0263     }
0264 }
0265 
0266 Plasma::Applet *Containment::applet() const
0267 {
0268     return d->containment;
0269 }
0270 
0271 Plasma::Containment *Containment::containment() const
0272 {
0273     return d->containment;
0274 }
0275 
0276 }