File indexing completed on 2024-12-22 05:15:19

0001 /*
0002     SPDX-FileCopyrightText: 2014 Eike Hein <hein@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "containmentinterface.h"
0008 
0009 #include <Plasma/Applet>
0010 #include <Plasma/Containment>
0011 #include <Plasma/Corona>
0012 #include <PlasmaQuick/AppletQuickItem>
0013 
0014 #include <KActionCollection>
0015 
0016 // FIXME HACK TODO: Unfortunately we have no choice but to hard-code a list of
0017 // applets we know to expose the correct interface right now -- this is slated
0018 // for replacement with some form of generic service.
0019 QStringList ContainmentInterface::m_knownTaskManagers{
0020     QLatin1String("org.kde.plasma.taskmanager"),
0021     QLatin1String("org.kde.plasma.icontasks"),
0022     QLatin1String("org.kde.plasma.expandingiconstaskmanager"),
0023 };
0024 
0025 ContainmentInterface::ContainmentInterface(QObject *parent)
0026     : QObject(parent)
0027 {
0028 }
0029 
0030 ContainmentInterface::~ContainmentInterface()
0031 {
0032 }
0033 
0034 bool ContainmentInterface::mayAddLauncher(QObject *appletInterface, ContainmentInterface::Target target, const KService::Ptr &service)
0035 {
0036     if (!appletInterface) {
0037         return false;
0038     }
0039 
0040     Plasma::Applet *applet = appletInterface->property("_plasma_applet").value<Plasma::Applet *>();
0041     Plasma::Containment *containment = applet->containment();
0042 
0043     if (!containment) {
0044         return false;
0045     }
0046 
0047     Plasma::Corona *corona = containment->corona();
0048 
0049     if (!corona) {
0050         return false;
0051     }
0052 
0053     switch (target) {
0054     case Desktop: {
0055         containment = corona->containmentForScreen(containment->screen(), QString(), QString());
0056 
0057         if (containment) {
0058             return (containment->immutability() == Plasma::Types::Mutable);
0059         }
0060 
0061         break;
0062     }
0063     case Panel: {
0064         if (containment->pluginMetaData().pluginId() == QLatin1String("org.kde.panel")) {
0065             return (containment->immutability() == Plasma::Types::Mutable);
0066         }
0067 
0068         break;
0069     }
0070     case TaskManager: {
0071         if (service && containment->pluginMetaData().pluginId() == QLatin1String("org.kde.panel")) {
0072             auto *taskManager = findTaskManagerApplet(containment);
0073 
0074             if (!taskManager) {
0075                 return false;
0076             }
0077 
0078             auto *taskManagerQuickItem = PlasmaQuick::AppletQuickItem::itemForApplet(taskManager);
0079 
0080             if (!taskManagerQuickItem) {
0081                 return false;
0082             }
0083 
0084             return taskManagerQuickItem->property("supportsLaunchers").toBool();
0085         }
0086 
0087         break;
0088     }
0089     }
0090 
0091     return false;
0092 }
0093 
0094 bool ContainmentInterface::hasLauncher(QObject *appletInterface, ContainmentInterface::Target target, const KService::Ptr &service)
0095 {
0096     // Only the task manager supports toggle-able launchers
0097     if (target != TaskManager) {
0098         return false;
0099     }
0100     if (!appletInterface) {
0101         return false;
0102     }
0103 
0104     Plasma::Applet *applet = appletInterface->property("_plasma_applet").value<Plasma::Applet *>();
0105     Plasma::Containment *containment = applet->containment();
0106 
0107     if (!containment) {
0108         return false;
0109     }
0110 
0111     if (service && containment->pluginMetaData().pluginId() == QLatin1String("org.kde.panel")) {
0112         auto *taskManager = findTaskManagerApplet(containment);
0113 
0114         if (!taskManager) {
0115             return false;
0116         }
0117 
0118         auto *taskManagerQuickItem = PlasmaQuick::AppletQuickItem::itemForApplet(taskManager);
0119 
0120         if (!taskManagerQuickItem) {
0121             return false;
0122         }
0123 
0124         QVariant ret;
0125         QMetaObject::invokeMethod(taskManagerQuickItem,
0126                                   "hasLauncher",
0127                                   Q_RETURN_ARG(QVariant, ret),
0128                                   Q_ARG(QVariant, QUrl(QLatin1String("applications:") + service->storageId())));
0129         return ret.toBool();
0130     }
0131 
0132     return false;
0133 }
0134 
0135 void ContainmentInterface::addLauncher(QObject *appletInterface, ContainmentInterface::Target target, const QString &entryPath)
0136 {
0137     if (!appletInterface) {
0138         return;
0139     }
0140 
0141     Plasma::Applet *applet = appletInterface->property("_plasma_applet").value<Plasma::Applet *>();
0142     Plasma::Containment *containment = applet->containment();
0143 
0144     if (!containment) {
0145         return;
0146     }
0147 
0148     Plasma::Corona *corona = containment->corona();
0149 
0150     if (!corona) {
0151         return;
0152     }
0153 
0154     switch (target) {
0155     case Desktop: {
0156         containment = corona->containmentForScreen(containment->screen(), QString(), QString());
0157 
0158         if (!containment) {
0159             return;
0160         }
0161 
0162         const QStringList &containmentProvides = containment->pluginMetaData().value(QStringLiteral("X-Plasma-Provides"), QStringList());
0163 
0164         if (containmentProvides.contains(QLatin1String("org.kde.plasma.filemanagement"))) {
0165             auto *folderQuickItem = PlasmaQuick::AppletQuickItem::itemForApplet(containment);
0166 
0167             if (!folderQuickItem) {
0168                 return;
0169             }
0170 
0171             QMetaObject::invokeMethod(folderQuickItem, "addLauncher", Q_ARG(QVariant, QUrl::fromLocalFile(entryPath)));
0172         } else {
0173             containment->createApplet(QStringLiteral("org.kde.plasma.icon"), QVariantList() << QUrl::fromLocalFile(entryPath));
0174         }
0175 
0176         break;
0177     }
0178     case Panel: {
0179         if (containment->pluginMetaData().pluginId() == QLatin1String("org.kde.panel")) {
0180             containment->createApplet(QStringLiteral("org.kde.plasma.icon"), QVariantList() << QUrl::fromLocalFile(entryPath));
0181         }
0182 
0183         break;
0184     }
0185     case TaskManager: {
0186         if (containment->pluginMetaData().pluginId() == QLatin1String("org.kde.panel")) {
0187             auto *taskManager = findTaskManagerApplet(containment);
0188 
0189             if (!taskManager) {
0190                 return;
0191             }
0192 
0193             auto *taskManagerQuickItem = PlasmaQuick::AppletQuickItem::itemForApplet(taskManager);
0194 
0195             if (!taskManagerQuickItem) {
0196                 return;
0197             }
0198 
0199             QMetaObject::invokeMethod(taskManagerQuickItem, "addLauncher", Q_ARG(QVariant, QUrl::fromLocalFile(entryPath)));
0200         }
0201 
0202         break;
0203     }
0204     }
0205 }
0206 
0207 QObject *ContainmentInterface::screenContainment(QObject *appletInterface)
0208 {
0209     if (!appletInterface) {
0210         return nullptr;
0211     }
0212 
0213     const Plasma::Applet *applet = appletInterface->property("_plasma_applet").value<Plasma::Applet *>();
0214     Plasma::Containment *containment = applet->containment();
0215 
0216     if (!containment) {
0217         return nullptr;
0218     }
0219 
0220     Plasma::Corona *corona = containment->corona();
0221 
0222     if (!corona) {
0223         return nullptr;
0224     }
0225 
0226     return corona->containmentForScreen(containment->screen(), QString(), QString());
0227 }
0228 
0229 bool ContainmentInterface::screenContainmentMutable(QObject *appletInterface)
0230 {
0231     const Plasma::Containment *containment = static_cast<const Plasma::Containment *>(screenContainment(appletInterface));
0232 
0233     if (containment) {
0234         return (containment->immutability() == Plasma::Types::Mutable);
0235     }
0236 
0237     return false;
0238 }
0239 
0240 void ContainmentInterface::ensureMutable(Plasma::Containment *containment)
0241 {
0242     if (containment && containment->immutability() != Plasma::Types::Mutable) {
0243         containment->internalAction(QStringLiteral("lock widgets"))->trigger();
0244     }
0245 }
0246 
0247 Plasma::Applet *ContainmentInterface::findTaskManagerApplet(Plasma::Containment *containment)
0248 {
0249     const QList<Plasma::Applet *> applets = containment->applets();
0250     const auto found = std::find_if(applets.cbegin(), applets.cend(), [](const Plasma::Applet *applet) {
0251         return m_knownTaskManagers.contains(applet->pluginMetaData().pluginId());
0252     });
0253     return found != applets.cend() ? *found : nullptr;
0254 }