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 "appinterface.h"
0008 #include <config-X11.h>
0009 
0010 #include <QEventLoop>
0011 #include <QTimer>
0012 
0013 #include <Solid/Battery>
0014 #include <Solid/Device>
0015 
0016 #include <Plasma/Containment>
0017 #include <Plasma/Corona>
0018 #include <Plasma/DataEngine>
0019 #include <Plasma/DataEngineConsumer>
0020 #include <Plasma/PluginLoader>
0021 #include <Plasma/Theme>
0022 
0023 #ifdef Q_OS_WIN
0024 #include <windows.h>
0025 #endif
0026 
0027 #if HAVE_X11
0028 #include <X11/Xlib.h>
0029 #include <fixx11h.h>
0030 #endif
0031 
0032 #include "debug.h"
0033 #include "scriptengine.h"
0034 
0035 namespace WorkspaceScripting
0036 {
0037 AppInterface::AppInterface(ScriptEngine *env)
0038     : QObject(env)
0039     , m_env(env)
0040 {
0041     m_theme = new Plasma::Theme(this);
0042 }
0043 
0044 int AppInterface::screenCount() const
0045 {
0046     return m_env->corona()->numScreens();
0047 }
0048 
0049 QJSValue AppInterface::screenGeometry(int screen) const
0050 {
0051     QRectF rect = m_env->corona()->screenGeometry(screen);
0052     QJSValueList args({QJSValue(rect.x()), QJSValue(rect.y()), QJSValue(rect.width()), QJSValue(rect.height())});
0053     return m_env->globalObject().property("QRectF").callAsConstructor(args);
0054 }
0055 
0056 QList<int> AppInterface::activityIds() const
0057 {
0058     // FIXME: the ints could overflow since Applet::id() returns a uint,
0059     //       however QScript deals with QList<uint> very, very poorly
0060     QList<int> containments;
0061 
0062     foreach (Plasma::Containment *c, m_env->corona()->containments()) {
0063         if (!ScriptEngine::isPanel(c)) {
0064             containments.append(c->id());
0065         }
0066     }
0067 
0068     return containments;
0069 }
0070 
0071 QList<int> AppInterface::panelIds() const
0072 {
0073     // FIXME: the ints could overflow since Applet::id() returns a uint,
0074     //       however QScript deals with QList<uint> very, very poorly
0075     QList<int> panels;
0076 
0077     foreach (Plasma::Containment *c, m_env->corona()->containments()) {
0078         // qDebug() << "checking" << (QObject*)c << isPanel(c);
0079         if (ScriptEngine::isPanel(c)) {
0080             panels.append(c->id());
0081         }
0082     }
0083 
0084     return panels;
0085 }
0086 
0087 QString AppInterface::applicationVersion() const
0088 {
0089     return qApp->applicationVersion();
0090 }
0091 
0092 QString AppInterface::platformVersion() const
0093 {
0094     return QString(); // KDE::versionString();
0095 }
0096 
0097 int AppInterface::scriptingVersion() const
0098 {
0099     return PLASMA_DESKTOP_SCRIPTING_VERSION;
0100 }
0101 
0102 QString AppInterface::theme() const
0103 {
0104     return m_theme->themeName();
0105 }
0106 
0107 void AppInterface::setTheme(const QString &name)
0108 {
0109     m_theme->setThemeName(name);
0110 }
0111 
0112 QString AppInterface::locale() const
0113 {
0114     return QLocale::system().name();
0115 }
0116 
0117 QString AppInterface::language() const
0118 {
0119     return QLocale::system().languageToString(QLocale::system().language());
0120 }
0121 
0122 QString AppInterface::languageId() const
0123 {
0124     return QLocale::system().bcp47Name().section(QLatin1Char('-'), 0, 0);
0125 }
0126 
0127 bool AppInterface::multihead() const
0128 {
0129     return false;
0130 }
0131 
0132 int AppInterface::multiheadScreen() const
0133 {
0134     return 0;
0135 }
0136 
0137 void AppInterface::lockCorona(bool locked)
0138 {
0139     m_env->corona()->setImmutability(locked ? Plasma::Types::UserImmutable : Plasma::Types::Mutable);
0140 }
0141 
0142 bool AppInterface::coronaLocked() const
0143 {
0144     return m_env->corona()->immutability() != Plasma::Types::Mutable;
0145 }
0146 
0147 void AppInterface::sleep(int ms)
0148 {
0149     Q_UNUSED(ms)
0150     // TODO KF6 remove
0151 
0152     // Sleep was implemented with a nested event loop which would cause nested
0153     // event processing from QML and offer a wide array of sources for
0154     // segfaulting. There isn't really a need to sleep from the scripting API,
0155     // so it was turned no-op.
0156     qCWarning(PLASMASHELL) << "Plasma scripting sleep() is deprecated and does nothing!";
0157 }
0158 
0159 bool AppInterface::hasBattery() const
0160 {
0161     QList<Solid::Device> batteryDevices = Solid::Device::listFromType(Solid::DeviceInterface::Battery);
0162 
0163     for (auto device : batteryDevices) {
0164         Solid::Battery *battery = device.as<Solid::Battery>();
0165         // check for _both_ primary and power supply status
0166         // apparently some devices misreport as "primary", and we don't
0167         // want to trigger on just having UPC connected to a desktop box
0168         if (battery && battery->type() == Solid::Battery::PrimaryBattery && battery->isPowerSupply()) {
0169             return true;
0170         }
0171     }
0172 
0173     return false;
0174 }
0175 
0176 QStringList AppInterface::knownWidgetTypes() const
0177 {
0178     if (m_knownWidgets.isEmpty()) {
0179         QStringList widgets;
0180         const QList<KPluginMetaData> plugins = Plasma::PluginLoader::self()->listAppletMetaData(QString());
0181 
0182         for (const auto &plugin : plugins) {
0183             widgets.append(plugin.pluginId());
0184         }
0185 
0186         const_cast<AppInterface *>(this)->m_knownWidgets = widgets;
0187     }
0188 
0189     return m_knownWidgets;
0190 }
0191 
0192 QStringList AppInterface::knownActivityTypes() const
0193 {
0194     return knownContainmentTypes(QStringLiteral("Desktop"));
0195 }
0196 
0197 QStringList AppInterface::knownPanelTypes() const
0198 {
0199     return knownContainmentTypes(QStringLiteral("Panel"));
0200 }
0201 
0202 QStringList AppInterface::knownContainmentTypes(const QString &type) const
0203 {
0204     QStringList containments;
0205     const QList<KPluginMetaData> plugins = Plasma::PluginLoader::listContainmentsMetaDataOfType(type);
0206 
0207     containments.reserve(plugins.count());
0208     for (const KPluginMetaData &plugin : plugins) {
0209         containments.append(plugin.pluginId());
0210     }
0211 
0212     return containments;
0213 }
0214 
0215 }