File indexing completed on 2024-04-21 16:17:15
0001 /* 0002 * Copyright 2019 Michail Vourlakos <mvourlakos@gmail.com> 0003 * 0004 * This file is part of Latte-Dock 0005 * 0006 * Latte-Dock is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU General Public License as 0008 * published by the Free Software Foundation; either version 2 of 0009 * the License, or (at your option) any later version. 0010 * 0011 * Latte-Dock is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 * GNU General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU General Public License 0017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0018 */ 0019 0020 #include "containmentinterface.h" 0021 0022 // local 0023 #include "view.h" 0024 #include "../lattecorona.h" 0025 #include "../settings/universalsettings.h" 0026 0027 // Qt 0028 #include <QDebug> 0029 0030 // Plasma 0031 #include <Plasma/Applet> 0032 #include <Plasma/Containment> 0033 0034 // KDE 0035 #include <KLocalizedString> 0036 #include <KPluginMetaData> 0037 0038 namespace Latte { 0039 namespace ViewPart { 0040 0041 ContainmentInterface::ContainmentInterface(Latte::View *parent) 0042 : QObject(parent), 0043 m_view(parent) 0044 { 0045 m_corona = qobject_cast<Latte::Corona *>(m_view->corona()); 0046 } 0047 0048 ContainmentInterface::~ContainmentInterface() 0049 { 0050 } 0051 0052 void ContainmentInterface::identifyMainItem() 0053 { 0054 if (m_mainItem) { 0055 return; 0056 } 0057 0058 if (QQuickItem *graphicItem = m_view->containment()->property("_plasma_graphicObject").value<QQuickItem *>()) { 0059 const auto &childItems = graphicItem->childItems(); 0060 0061 for (QQuickItem *item : childItems) { 0062 if (item->objectName() == "containmentViewLayout" ) { 0063 m_mainItem = item; 0064 identifyMethods(); 0065 return; 0066 } 0067 } 0068 } 0069 } 0070 0071 void ContainmentInterface::identifyMethods() 0072 { 0073 int aeIndex = m_mainItem->metaObject()->indexOfMethod("activateEntryAtIndex(QVariant)"); 0074 int niIndex = m_mainItem->metaObject()->indexOfMethod("newInstanceForEntryAtIndex(QVariant)"); 0075 int sbIndex = m_mainItem->metaObject()->indexOfMethod("setShowAppletShortcutBadges(QVariant,QVariant,QVariant,QVariant)"); 0076 int afiIndex = m_mainItem->metaObject()->indexOfMethod("appletIdForIndex(QVariant)"); 0077 0078 m_activateEntryMethod = m_mainItem->metaObject()->method(aeIndex); 0079 m_appletIdForIndexMethod = m_mainItem->metaObject()->method(afiIndex); 0080 m_newInstanceMethod = m_mainItem->metaObject()->method(niIndex); 0081 m_showShortcutsMethod = m_mainItem->metaObject()->method(sbIndex); 0082 } 0083 0084 bool ContainmentInterface::applicationLauncherHasGlobalShortcut() const 0085 { 0086 if (!containsApplicationLauncher()) { 0087 return false; 0088 } 0089 0090 int launcherAppletId = applicationLauncherId(); 0091 0092 const auto applets = m_view->containment()->applets(); 0093 0094 for (auto applet : applets) { 0095 if (applet->id() == launcherAppletId) { 0096 return !applet->globalShortcut().isEmpty(); 0097 } 0098 } 0099 0100 return false; 0101 } 0102 0103 bool ContainmentInterface::applicationLauncherInPopup() const 0104 { 0105 if (!containsApplicationLauncher()) { 0106 return false; 0107 } 0108 0109 int launcherAppletId = applicationLauncherId(); 0110 QString launcherPluginId; 0111 0112 const auto applets = m_view->containment()->applets(); 0113 0114 for (auto applet : applets) { 0115 if (applet->id() == launcherAppletId) { 0116 launcherPluginId = applet->kPackage().metadata().pluginId(); 0117 } 0118 } 0119 0120 return launcherPluginId != "org.kde.plasma.kickerdash"; 0121 } 0122 0123 bool ContainmentInterface::containsApplicationLauncher() const 0124 { 0125 return (applicationLauncherId() >= 0); 0126 } 0127 0128 bool ContainmentInterface::isCapableToShowShortcutBadges() 0129 { 0130 identifyMainItem(); 0131 0132 if (!m_view->latteTasksArePresent() && m_view->tasksPresent()) { 0133 return false; 0134 } 0135 0136 return m_showShortcutsMethod.isValid(); 0137 } 0138 0139 int ContainmentInterface::applicationLauncherId() const 0140 { 0141 const auto applets = m_view->containment()->applets(); 0142 0143 auto launcherId{-1}; 0144 0145 for (auto applet : applets) { 0146 const auto provides = applet->kPackage().metadata().value(QStringLiteral("X-Plasma-Provides")); 0147 0148 if (provides.contains(QLatin1String("org.kde.plasma.launchermenu"))) { 0149 if (!applet->globalShortcut().isEmpty()) { 0150 return applet->id(); 0151 } else if (launcherId == -1) { 0152 launcherId = applet->id(); 0153 } 0154 } 0155 } 0156 0157 return launcherId; 0158 } 0159 0160 bool ContainmentInterface::updateBadgeForLatteTask(const QString identifier, const QString value) 0161 { 0162 if (!m_view->latteTasksArePresent()) { 0163 return false; 0164 } 0165 0166 const auto &applets = m_view->containment()->applets(); 0167 0168 for (auto *applet : applets) { 0169 KPluginMetaData meta = applet->kPackage().metadata(); 0170 0171 if (meta.pluginId() == "org.kde.latte.plasmoid") { 0172 0173 if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value<QQuickItem *>()) { 0174 const auto &childItems = appletInterface->childItems(); 0175 0176 if (childItems.isEmpty()) { 0177 continue; 0178 } 0179 0180 for (QQuickItem *item : childItems) { 0181 if (auto *metaObject = item->metaObject()) { 0182 // not using QMetaObject::invokeMethod to avoid warnings when calling 0183 // this on applets that don't have it or other child items since this 0184 // is pretty much trial and error. 0185 // Also, "var" arguments are treated as QVariant in QMetaObject 0186 0187 int methodIndex = metaObject->indexOfMethod("updateBadge(QVariant,QVariant)"); 0188 0189 if (methodIndex == -1) { 0190 continue; 0191 } 0192 0193 QMetaMethod method = metaObject->method(methodIndex); 0194 0195 if (method.invoke(item, Q_ARG(QVariant, identifier), Q_ARG(QVariant, value))) { 0196 return true; 0197 } 0198 } 0199 } 0200 } 0201 } 0202 } 0203 0204 return false; 0205 } 0206 0207 bool ContainmentInterface::activatePlasmaTask(const int index) 0208 { 0209 bool containsPlasmaTaskManager{m_view->tasksPresent() && !m_view->latteTasksArePresent()}; 0210 0211 if (!containsPlasmaTaskManager) { 0212 return false; 0213 } 0214 0215 const auto &applets = m_view->containment()->applets(); 0216 0217 for (auto *applet : applets) { 0218 const auto &provides = KPluginMetaData::readStringList(applet->pluginMetaData().rawData(), QStringLiteral("X-Plasma-Provides")); 0219 0220 if (provides.contains(QLatin1String("org.kde.plasma.multitasking"))) { 0221 if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value<QQuickItem *>()) { 0222 const auto &childItems = appletInterface->childItems(); 0223 0224 if (childItems.isEmpty()) { 0225 continue; 0226 } 0227 0228 KPluginMetaData meta = applet->kPackage().metadata(); 0229 0230 for (QQuickItem *item : childItems) { 0231 if (auto *metaObject = item->metaObject()) { 0232 int methodIndex{metaObject->indexOfMethod("activateTaskAtIndex(QVariant)")}; 0233 0234 if (methodIndex == -1) { 0235 continue; 0236 } 0237 0238 QMetaMethod method = metaObject->method(methodIndex); 0239 0240 if (method.invoke(item, Q_ARG(QVariant, index - 1))) { 0241 showShortcutBadges(false, true); 0242 0243 return true; 0244 } 0245 } 0246 } 0247 } 0248 } 0249 } 0250 0251 return false; 0252 } 0253 0254 bool ContainmentInterface::newInstanceForPlasmaTask(const int index) 0255 { 0256 bool containsPlasmaTaskManager{m_view->tasksPresent() && !m_view->latteTasksArePresent()}; 0257 0258 if (!containsPlasmaTaskManager) { 0259 return false; 0260 } 0261 0262 const auto &applets = m_view->containment()->applets(); 0263 0264 for (auto *applet : applets) { 0265 const auto &provides = KPluginMetaData::readStringList(applet->pluginMetaData().rawData(), QStringLiteral("X-Plasma-Provides")); 0266 0267 if (provides.contains(QLatin1String("org.kde.plasma.multitasking"))) { 0268 if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value<QQuickItem *>()) { 0269 const auto &childItems = appletInterface->childItems(); 0270 0271 if (childItems.isEmpty()) { 0272 continue; 0273 } 0274 0275 KPluginMetaData meta = applet->kPackage().metadata(); 0276 0277 for (QQuickItem *item : childItems) { 0278 if (auto *metaObject = item->metaObject()) { 0279 int methodIndex{metaObject->indexOfMethod("ewInstanceForTaskAtIndex(QVariant)")}; 0280 0281 if (methodIndex == -1) { 0282 continue; 0283 } 0284 0285 QMetaMethod method = metaObject->method(methodIndex); 0286 0287 if (method.invoke(item, Q_ARG(QVariant, index - 1))) { 0288 showShortcutBadges(false, true); 0289 0290 return true; 0291 } 0292 } 0293 } 0294 } 0295 } 0296 } 0297 0298 return false; 0299 } 0300 0301 bool ContainmentInterface::activateEntry(const int index) 0302 { 0303 identifyMainItem(); 0304 0305 if (!m_activateEntryMethod.isValid()) { 0306 return false; 0307 } 0308 0309 return m_activateEntryMethod.invoke(m_mainItem, Q_ARG(QVariant, index)); 0310 } 0311 0312 bool ContainmentInterface::newInstanceForEntry(const int index) 0313 { 0314 identifyMainItem(); 0315 0316 if (!m_newInstanceMethod.isValid()) { 0317 return false; 0318 } 0319 0320 return m_newInstanceMethod.invoke(m_mainItem, Q_ARG(QVariant, index)); 0321 } 0322 0323 bool ContainmentInterface::hideShortcutBadges() 0324 { 0325 identifyMainItem(); 0326 0327 if (!m_showShortcutsMethod.isValid()) { 0328 return false; 0329 } 0330 0331 return m_showShortcutsMethod.invoke(m_mainItem, Q_ARG(QVariant, false), Q_ARG(QVariant, false), Q_ARG(QVariant, false), Q_ARG(QVariant, -1)); 0332 } 0333 0334 bool ContainmentInterface::showOnlyMeta() 0335 { 0336 if (!m_corona->universalSettings()->kwin_metaForwardedToLatte()) { 0337 return false; 0338 } 0339 0340 return showShortcutBadges(false, true); 0341 } 0342 0343 bool ContainmentInterface::showShortcutBadges(const bool showLatteShortcuts, const bool showMeta) 0344 { 0345 identifyMainItem(); 0346 0347 if (!m_showShortcutsMethod.isValid()) { 0348 return false; 0349 } 0350 0351 int appLauncherId = m_corona->universalSettings()->kwin_metaForwardedToLatte() && showMeta ? applicationLauncherId() : -1; 0352 0353 return m_showShortcutsMethod.invoke(m_mainItem, Q_ARG(QVariant, showLatteShortcuts), Q_ARG(QVariant, true), Q_ARG(QVariant, showMeta), Q_ARG(QVariant, appLauncherId)); 0354 } 0355 0356 int ContainmentInterface::appletIdForIndex(const int index) 0357 { 0358 identifyMainItem(); 0359 0360 if (!m_appletIdForIndexMethod.isValid()) { 0361 return false; 0362 } 0363 0364 QVariant appletId{-1}; 0365 0366 m_appletIdForIndexMethod.invoke(m_mainItem, Q_RETURN_ARG(QVariant, appletId), Q_ARG(QVariant, index)); 0367 0368 return appletId.toInt(); 0369 } 0370 0371 0372 } 0373 }