diff --git a/app/shortcuts/globalshortcuts.cpp b/app/shortcuts/globalshortcuts.cpp index c57ce9929..9caa3e4ac 100644 --- a/app/shortcuts/globalshortcuts.cpp +++ b/app/shortcuts/globalshortcuts.cpp @@ -28,6 +28,7 @@ #include "../layouts/manager.h" #include "../layouts/synchronizer.h" #include "../settings/universalsettings.h" +#include "../view/containmentinterface.h" #include "../view/view.h" // C++ @@ -221,154 +222,71 @@ void GlobalShortcuts::activateLauncherMenu() } for (const auto view : sortedViews) { - const auto applets = view->containment()->applets(); - - for (auto applet : applets) { - const auto provides = applet->kPackage().metadata().value(QStringLiteral("X-Plasma-Provides")); - - if (provides.contains(QLatin1String("org.kde.plasma.launchermenu"))) { - if (view->visibility()->isHidden()) { - if (!m_hideViews.contains(view)) { - m_hideViews.append(view); - } - - m_lastInvokedAction = m_singleMetaAction; + if (view->interface()->containsApplicationLauncher()) { + if (view->visibility()->isHidden()) { + if (!m_hideViews.contains(view)) { + m_hideViews.append(view); + } - view->visibility()->setBlockHiding(true); + m_lastInvokedAction = m_singleMetaAction; - //! delay the execution in order to show first the view - QTimer::singleShot(APPLETEXECUTIONDELAY, [this, view, applet]() { - view->toggleAppletExpanded(applet->id()); - }); + view->visibility()->setBlockHiding(true); - m_hideViewsTimer.start(); - } else { - view->toggleAppletExpanded(applet->id()); - } + //! delay the execution in order to show first the view + QTimer::singleShot(APPLETEXECUTIONDELAY, [this, view]() { + view->toggleAppletExpanded(view->interface()->applicationLauncherId()); + }); - return; + m_hideViewsTimer.start(); + } else { + view->toggleAppletExpanded(view->interface()->applicationLauncherId()); } + + return; } } } -bool GlobalShortcuts::activatePlasmaTaskManagerEntryAtContainment(const Plasma::Containment *c, int index, Qt::Key modifier) +bool GlobalShortcuts::activatePlasmaTaskManager(const Latte::View *view, int index, Qt::Key modifier) { - const auto &applets = c->applets(); - - for (auto *applet : applets) { - const auto &provides = KPluginMetaData::readStringList(applet->pluginMetaData().rawData(), QStringLiteral("X-Plasma-Provides")); - - if (provides.contains(QLatin1String("org.kde.plasma.multitasking"))) { - if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value()) { - const auto &childItems = appletInterface->childItems(); - - if (childItems.isEmpty()) { - continue; - } - - KPluginMetaData meta = applet->kPackage().metadata(); - - for (QQuickItem *item : childItems) { - if (auto *metaObject = item->metaObject()) { - // not using QMetaObject::invokeMethod to avoid warnings when calling - // this on applets that don't have it or other child items since this - // is pretty much trial and error. - - // Also, "var" arguments are treated as QVariant in QMetaObject - int methodIndex = modifier == static_cast(Qt::META) ? - metaObject->indexOfMethod("activateTaskAtIndex(QVariant)") : - metaObject->indexOfMethod("newInstanceForTaskAtIndex(QVariant)"); - - int methodIndex2 = metaObject->indexOfMethod("setShowTaskShortcutBadges(QVariant)"); - - if (methodIndex == -1 || (methodIndex2 == -1 && meta.pluginId() == "org.kde.latte.plasmoid")) { - continue; - } - - int showMethodIndex = -1; - - if (!m_viewItemsCalled.contains(item)) { - m_viewItemsCalled.append(item); - m_showShortcutBadgesMethods.append(metaObject->method(methodIndex)); - showMethodIndex = m_showShortcutBadgesMethods.count() - 1; - } else { - showMethodIndex = m_showShortcutBadgesMethods.indexOf(metaObject->method(methodIndex)); - } - - QMetaMethod method = metaObject->method(methodIndex); - - if (method.invoke(item, Q_ARG(QVariant, index - 1))) { - if (methodIndex2 != -1) { - m_showShortcutBadgesMethods[showMethodIndex].invoke(item, Q_ARG(QVariant, true)); - } - - return true; - } - - } - } + bool activation{modifier == static_cast(Qt::META)}; + bool newInstance{!activation}; + + if (view->visibility()->isHidden()) { + //! delay the execution in order to show first the view + QTimer::singleShot(APPLETEXECUTIONDELAY, [this, view, index, activation]() { + if (activation) { + view->interface()->activatePlasmaTask(index); + } else { + view->interface()->newInstanceForPlasmaTask(index); } - } - } + }); - return false; + return true; + } else { + return (activation ? view->interface()->activatePlasmaTask(index) : view->interface()->newInstanceForPlasmaTask(index)); + } } -bool GlobalShortcuts::activateLatteEntryAtContainment(const Latte::View *view, int index, Qt::Key modifier) +bool GlobalShortcuts::activateLatteEntry(const Latte::View *view, int index, Qt::Key modifier) { - if (QQuickItem *containmentInterface = view->containment()->property("_plasma_graphicObject").value()) { - const auto &childItems = containmentInterface->childItems(); - - for (QQuickItem *item : childItems) { - if (auto *metaObject = item->metaObject()) { - // not using QMetaObject::invokeMethod to avoid warnings when calling - // this on applets that don't have it or other child items since this - // is pretty much trial and error. - - // Also, "var" arguments are treated as QVariant in QMetaObject - int methodIndex = modifier == static_cast(Qt::META) ? - metaObject->indexOfMethod("activateEntryAtIndex(QVariant)") : - metaObject->indexOfMethod("newInstanceForEntryAtIndex(QVariant)"); - - int methodIndex2 = metaObject->indexOfMethod("setShowAppletShortcutBadges(QVariant,QVariant,QVariant,QVariant)"); - - if (methodIndex == -1 || (methodIndex2 == -1)) { - continue; - } - - int appLauncher = m_corona->universalSettings()->kwin_metaForwardedToLatte() ? - applicationLauncherId(view->containment()) : -1; - - int showMethodIndex = -1; - - if (!m_viewItemsCalled.contains(item)) { - m_viewItemsCalled.append(item); - m_showShortcutBadgesMethods.append(metaObject->method(methodIndex2)); - showMethodIndex = m_showShortcutBadgesMethods.count() - 1; - } else { - showMethodIndex = m_showShortcutBadgesMethods.indexOf(metaObject->method(methodIndex2)); - } - - QMetaMethod method = metaObject->method(methodIndex); - - if (view->visibility()->isHidden()) { - //! delay the execution in order to show first the view - QTimer::singleShot(APPLETEXECUTIONDELAY, [this, item, method, index]() { - method.invoke(item, Q_ARG(QVariant, index)); - }); - - return true; - } else { - if (method.invoke(item, Q_ARG(QVariant, index))) { - return true; - } - } + bool activation{modifier == static_cast(Qt::META)}; + bool newInstance{!activation}; + + if (view->visibility()->isHidden()) { + //! delay the execution in order to show first the view + QTimer::singleShot(APPLETEXECUTIONDELAY, [this, view, index, activation]() { + if (activation) { + view->interface()->activateEntry(index); + } else { + view->interface()->newInstanceForEntry(index); } - } - } + }); - return false; + return true; + } else { + return (activation ? view->interface()->activateEntry(index) : view->interface()->newInstanceForEntry(index)); + } } @@ -390,8 +308,8 @@ void GlobalShortcuts::activateEntry(int index, Qt::Key modifier) } if ((!view->latteTasksArePresent() && view->tasksPresent() && - activatePlasmaTaskManagerEntryAtContainment(view->containment(), index, modifier)) - || activateLatteEntryAtContainment(view, index, modifier)) { + activatePlasmaTaskManager(view, index, modifier)) + || activateLatteEntry(view, index, modifier)) { if (!m_hideViews.contains(view)) { m_hideViews.append(view); @@ -408,49 +326,6 @@ void GlobalShortcuts::activateEntry(int index, Qt::Key modifier) //! update badge for specific view item void GlobalShortcuts::updateViewItemBadge(QString identifier, QString value) { - //qDebug() << "DBUS CALL ::: " << identifier << " - " << value; - auto updateBadgeForTaskInContainment = [this](const Plasma::Containment * c, QString identifier, QString value) { - const auto &applets = c->applets(); - - for (auto *applet : applets) { - KPluginMetaData meta = applet->kPackage().metadata(); - - if (meta.pluginId() == "org.kde.latte.plasmoid") { - - if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value()) { - const auto &childItems = appletInterface->childItems(); - - if (childItems.isEmpty()) { - continue; - } - - for (QQuickItem *item : childItems) { - if (auto *metaObject = item->metaObject()) { - // not using QMetaObject::invokeMethod to avoid warnings when calling - // this on applets that don't have it or other child items since this - // is pretty much trial and error. - // Also, "var" arguments are treated as QVariant in QMetaObject - - int methodIndex = metaObject->indexOfMethod("updateBadge(QVariant,QVariant)"); - - if (methodIndex == -1) { - continue; - } - - QMetaMethod method = metaObject->method(methodIndex); - - if (method.invoke(item, Q_ARG(QVariant, identifier), Q_ARG(QVariant, value))) { - return true; - } - } - } - } - } - } - - return false; - }; - CentralLayout *currentLayout = m_corona->layoutsManager()->currentLayout(); QList views; @@ -460,55 +335,8 @@ void GlobalShortcuts::updateViewItemBadge(QString identifier, QString value) // update badges in all Latte Tasks plasmoids for (const auto &view : views) { - updateBadgeForTaskInContainment(view->containment(), identifier, value); - } -} - -bool GlobalShortcuts::isCapableToShowShortcutBadges(Latte::View *view) -{ - if (!view->latteTasksArePresent() && view->tasksPresent()) { - return false; - } - - const Plasma::Containment *c = view->containment(); - - if (QQuickItem *containmentInterface = c->property("_plasma_graphicObject").value()) { - const auto &childItems = containmentInterface->childItems(); - - for (QQuickItem *item : childItems) { - if (auto *metaObject = item->metaObject()) { - // not using QMetaObject::invokeMethod to avoid warnings when calling - // this on applets that don't have it or other child items since this - // is pretty much trial and error. - - // Also, "var" arguments are treated as QVariant in QMetaObject - int methodIndex = metaObject->indexOfMethod("setShowAppletShortcutBadges(QVariant,QVariant,QVariant,QVariant)"); - - if (methodIndex == -1) { - continue; - } - - return true; - } - } + view->interface()->updateBadgeForLatteTask(identifier, value); } - - return false; -} - -int GlobalShortcuts::applicationLauncherId(const Plasma::Containment *c) -{ - const auto applets = c->applets(); - - for (auto applet : applets) { - const auto provides = applet->kPackage().metadata().value(QStringLiteral("X-Plasma-Provides")); - - if (provides.contains(QLatin1String("org.kde.plasma.launchermenu"))) { - return applet->id(); - } - } - - return -1; } void GlobalShortcuts::showViews() @@ -519,95 +347,6 @@ void GlobalShortcuts::showViews() m_lastInvokedAction = m_singleMetaAction; } - auto invokeShowShortcuts = [this](const Plasma::Containment * c, const bool showLatteShortcuts, const bool showMeta) { - if (QQuickItem *containmentInterface = c->property("_plasma_graphicObject").value()) { - const auto &childItems = containmentInterface->childItems(); - - for (QQuickItem *item : childItems) { - if (auto *metaObject = item->metaObject()) { - // not using QMetaObject::invokeMethod to avoid warnings when calling - // this on applets that don't have it or other child items since this - // is pretty much trial and error. - - // Also, "var" arguments are treated as QVariant in QMetaObject - int methodIndex = metaObject->indexOfMethod("setShowAppletShortcutBadges(QVariant,QVariant,QVariant,QVariant)"); - - if (methodIndex == -1) { - continue; - } - - int appLauncher = m_corona->universalSettings()->kwin_metaForwardedToLatte() && showMeta ? - applicationLauncherId(c) : -1; - - int showMethodIndex = -1; - - if (!m_viewItemsCalled.contains(item)) { - m_viewItemsCalled.append(item); - m_showShortcutBadgesMethods.append(metaObject->method(methodIndex)); - showMethodIndex = m_showShortcutBadgesMethods.count() - 1; - } else { - showMethodIndex = m_showShortcutBadgesMethods.indexOf(metaObject->method(methodIndex)); - } - - if (m_showShortcutBadgesMethods[showMethodIndex].invoke(item, - Q_ARG(QVariant, showLatteShortcuts), - Q_ARG(QVariant, true), - Q_ARG(QVariant, showMeta), - Q_ARG(QVariant, appLauncher))) { - return true; - } - - } - } - } - - return false; - }; - - auto invokeShowOnlyMeta = [this](const Plasma::Containment * c, const bool showLatteShortcuts) { - if (QQuickItem *containmentInterface = c->property("_plasma_graphicObject").value()) { - const auto &childItems = containmentInterface->childItems(); - - for (QQuickItem *item : childItems) { - if (auto *metaObject = item->metaObject()) { - // not using QMetaObject::invokeMethod to avoid warnings when calling - // this on applets that don't have it or other child items since this - // is pretty much trial and error. - - // Also, "var" arguments are treated as QVariant in QMetaObject - int methodIndex = metaObject->indexOfMethod("setShowAppletShortcutBadges(QVariant,QVariant,QVariant,QVariant)"); - - if (methodIndex == -1) { - continue; - } - - int appLauncher = m_corona->universalSettings()->kwin_metaForwardedToLatte() ? - applicationLauncherId(c) : -1; - - int showMethodIndex = -1; - - if (!m_viewItemsCalled.contains(item)) { - m_viewItemsCalled.append(item); - m_showShortcutBadgesMethods.append(metaObject->method(methodIndex)); - showMethodIndex = m_showShortcutBadgesMethods.count() - 1; - } else { - showMethodIndex = m_showShortcutBadgesMethods.indexOf(metaObject->method(methodIndex)); - } - - if (m_showShortcutBadgesMethods[showMethodIndex].invoke(item, - Q_ARG(QVariant, showLatteShortcuts), - Q_ARG(QVariant, true), - Q_ARG(QVariant, true), - Q_ARG(QVariant, appLauncher))) { - return true; - } - } - } - } - - return false; - }; - QList sortedViews; CentralLayout *currentLayout = m_corona->layoutsManager()->currentLayout(); @@ -619,16 +358,18 @@ void GlobalShortcuts::showViews() Latte::View *viewWithMeta{nullptr}; for(const auto view : sortedViews) { - if (!viewWithTasks && (!view->layout()->preferredForShortcutsTouched() || view->isPreferredForShortcuts()) && isCapableToShowShortcutBadges(view)) { + if (!viewWithTasks + && view->interface()->isCapableToShowShortcutBadges() + && (!view->layout()->preferredForShortcutsTouched() || view->isPreferredForShortcuts())) { viewWithTasks = view; break; } } //! show Meta if it is not already shown for Tasks Latte View - if (!viewWithTasks || applicationLauncherId(viewWithTasks->containment()) == -1) { + if (!viewWithTasks || !viewWithTasks->interface()->containsApplicationLauncher()) { for(const auto view : sortedViews) { - if (!viewWithMeta && m_corona->universalSettings()->kwin_metaForwardedToLatte() && applicationLauncherId(view->containment()) > -1) { + if (!viewWithMeta && m_corona->universalSettings()->kwin_metaForwardedToLatte() && view->interface()->containsApplicationLauncher()) { viewWithMeta = view; break; } @@ -639,15 +380,10 @@ void GlobalShortcuts::showViews() if (!m_hideViewsTimer.isActive()) { m_hideViews.clear(); - - if (viewWithTasks || viewWithMeta) { - m_viewItemsCalled.clear(); - m_showShortcutBadgesMethods.clear(); - } } //! show view that contains tasks plasmoid - if (viewWithTasks && invokeShowShortcuts(viewWithTasks->containment(), true, true)) { + if (viewWithTasks && viewWithTasks->interface()->showShortcutBadges(true, true)) { viewFound = true; if (!m_hideViewsTimer.isActive()) { @@ -657,7 +393,7 @@ void GlobalShortcuts::showViews() } //! show view that contains only meta - if (viewWithMeta && viewWithMeta != viewWithTasks && invokeShowOnlyMeta(viewWithMeta->containment(), false)) { + if (viewWithMeta && viewWithMeta != viewWithTasks && viewWithMeta->interface()->showOnlyMeta()) { viewFound = true; if (!m_hideViewsTimer.isActive()) { @@ -679,7 +415,7 @@ void GlobalShortcuts::showViews() if (!m_hideViewsTimer.isActive()) { for(const auto view : viewsWithShortcuts) { if (view != viewWithTasks && view != viewWithMeta) { - if (invokeShowShortcuts(view->containment(), false, false)) { + if (view->interface()->showShortcutBadges(false, false)) { m_hideViews.append(view); view->visibility()->setBlockHiding(true); } @@ -757,22 +493,11 @@ void GlobalShortcuts::hideViewsTimerSlot() if (viewsToHideAreValid()) { for(const auto latteView : m_hideViews) { latteView->visibility()->setBlockHiding(false); - } - - if (m_viewItemsCalled.count() > 0) { - for (int i = 0; i < m_viewItemsCalled.count(); ++i) { - m_showShortcutBadgesMethods[i].invoke(m_viewItemsCalled[i], - Q_ARG(QVariant, false), - Q_ARG(QVariant, false), - Q_ARG(QVariant, false), - Q_ARG(QVariant, -1)); - } - } + latteView->interface()->hideShortcutBadges(); + } } m_hideViews.clear(); - m_viewItemsCalled.clear(); - m_showShortcutBadgesMethods.clear(); m_metaShowedViews = false; }; diff --git a/app/shortcuts/globalshortcuts.h b/app/shortcuts/globalshortcuts.h index 0ffa7cd61..78d16a8bd 100644 --- a/app/shortcuts/globalshortcuts.h +++ b/app/shortcuts/globalshortcuts.h @@ -25,8 +25,7 @@ #include "../liblatte2/types.h" // Qt -#include -#include +#include #include #include @@ -74,14 +73,12 @@ private: void showViews(); void showSettings(); - bool activateLatteEntryAtContainment(const Latte::View *view, int index, Qt::Key modifier); - bool activatePlasmaTaskManagerEntryAtContainment(const Plasma::Containment *c, int index, Qt::Key modifier); + bool activateLatteEntry(const Latte::View *view, int index, Qt::Key modifier); + bool activatePlasmaTaskManager(const Latte::View *view, int index, Qt::Key modifier); bool viewAtLowerEdgePriority(Latte::View *test, Latte::View *base); bool viewAtLowerScreenPriority(Latte::View *test, Latte::View *base); bool viewsToHideAreValid(); - bool isCapableToShowShortcutBadges(Latte::View *view); - int applicationLauncherId(const Plasma::Containment *c); QList sortedViewsList(QHash *views); private: @@ -96,9 +93,6 @@ private: QTimer m_hideViewsTimer; QList m_hideViews; - QList m_viewItemsCalled; - QList m_showShortcutBadgesMethods; - QPointer m_modifierTracker; QPointer m_shortcutsTracker; QPointer m_corona; diff --git a/app/view/CMakeLists.txt b/app/view/CMakeLists.txt index dad1537b9..ed59182b1 100644 --- a/app/view/CMakeLists.txt +++ b/app/view/CMakeLists.txt @@ -1,5 +1,6 @@ set(lattedock-app_SRCS ${lattedock-app_SRCS} + ${CMAKE_CURRENT_SOURCE_DIR}/containmentinterface.cpp ${CMAKE_CURRENT_SOURCE_DIR}/contextmenu.cpp ${CMAKE_CURRENT_SOURCE_DIR}/effects.cpp ${CMAKE_CURRENT_SOURCE_DIR}/panelshadows.cpp diff --git a/app/view/containmentinterface.cpp b/app/view/containmentinterface.cpp new file mode 100644 index 000000000..9267deaf1 --- /dev/null +++ b/app/view/containmentinterface.cpp @@ -0,0 +1,308 @@ +/* +* Copyright 2019 Michail Vourlakos +* +* This file is part of Latte-Dock +* +* Latte-Dock is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License, or (at your option) any later version. +* +* Latte-Dock 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 General Public License +* along with this program. If not, see . +*/ + +#include "containmentinterface.h" + +// local +#include "view.h" +#include "../lattecorona.h" +#include "../settings/universalsettings.h" + +// Qt +#include + +// Plasma +#include +#include + +// KDE +#include +#include + +namespace Latte { +namespace ViewPart { + +ContainmentInterface::ContainmentInterface(Latte::View *parent) + : QObject(parent), + m_view(parent) +{ + m_corona = qobject_cast(m_view->corona()); +} + +ContainmentInterface::~ContainmentInterface() +{ +} + +void ContainmentInterface::identifyMainItem() +{ + if (m_mainItem) { + return; + } + + if (QQuickItem *graphicItem = m_view->containment()->property("_plasma_graphicObject").value()) { + const auto &childItems = graphicItem->childItems(); + + for (QQuickItem *item : childItems) { + if (item->objectName() == "containmentViewLayout" ) { + m_mainItem = item; + identifyMethods(); + return; + } + } + } +} + +void ContainmentInterface::identifyMethods() +{ + int aeIndex = m_mainItem->metaObject()->indexOfMethod("activateEntryAtIndex(QVariant)"); + int niIndex = m_mainItem->metaObject()->indexOfMethod("newInstanceForEntryAtIndex(QVariant)"); + int sbIndex = m_mainItem->metaObject()->indexOfMethod("setShowAppletShortcutBadges(QVariant,QVariant,QVariant,QVariant)"); + + m_activateEntryMethod = m_mainItem->metaObject()->method(aeIndex); + m_newInstanceMethod = m_mainItem->metaObject()->method(niIndex); + m_showShortcutsMethod = m_mainItem->metaObject()->method(sbIndex); +} + +bool ContainmentInterface::containsApplicationLauncher() const +{ + return applicationLauncherId() == -1 ? false : true; +} + +bool ContainmentInterface::isCapableToShowShortcutBadges() const +{ + if (!m_view->latteTasksArePresent() && m_view->tasksPresent()) { + return false; + } + + return m_showShortcutsMethod.isValid(); +} + +int ContainmentInterface::applicationLauncherId() const +{ + const auto applets = m_view->containment()->applets(); + + for (auto applet : applets) { + const auto provides = applet->kPackage().metadata().value(QStringLiteral("X-Plasma-Provides")); + + if (provides.contains(QLatin1String("org.kde.plasma.launchermenu"))) { + return applet->id(); + } + } + + return -1; +} + +bool ContainmentInterface::updateBadgeForLatteTask(const QString identifier, const QString value) +{ + if (!m_view->latteTasksArePresent()) { + return false; + } + + const auto &applets = m_view->containment()->applets(); + + for (auto *applet : applets) { + KPluginMetaData meta = applet->kPackage().metadata(); + + if (meta.pluginId() == "org.kde.latte.plasmoid") { + + if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value()) { + const auto &childItems = appletInterface->childItems(); + + if (childItems.isEmpty()) { + continue; + } + + for (QQuickItem *item : childItems) { + if (auto *metaObject = item->metaObject()) { + // not using QMetaObject::invokeMethod to avoid warnings when calling + // this on applets that don't have it or other child items since this + // is pretty much trial and error. + // Also, "var" arguments are treated as QVariant in QMetaObject + + int methodIndex = metaObject->indexOfMethod("updateBadge(QVariant,QVariant)"); + + if (methodIndex == -1) { + continue; + } + + QMetaMethod method = metaObject->method(methodIndex); + + if (method.invoke(item, Q_ARG(QVariant, identifier), Q_ARG(QVariant, value))) { + return true; + } + } + } + } + } + } + + return false; +} + +bool ContainmentInterface::activatePlasmaTask(const int index) +{ + bool containsPlasmaTaskManager{m_view->tasksPresent() && !m_view->latteTasksArePresent()}; + + if (!containsPlasmaTaskManager) { + return false; + } + + const auto &applets = m_view->containment()->applets(); + + for (auto *applet : applets) { + const auto &provides = KPluginMetaData::readStringList(applet->pluginMetaData().rawData(), QStringLiteral("X-Plasma-Provides")); + + if (provides.contains(QLatin1String("org.kde.plasma.multitasking"))) { + if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value()) { + const auto &childItems = appletInterface->childItems(); + + if (childItems.isEmpty()) { + continue; + } + + KPluginMetaData meta = applet->kPackage().metadata(); + + for (QQuickItem *item : childItems) { + if (auto *metaObject = item->metaObject()) { + int methodIndex{metaObject->indexOfMethod("activateTaskAtIndex(QVariant)")}; + + if (methodIndex == -1) { + continue; + } + + QMetaMethod method = metaObject->method(methodIndex); + + if (method.invoke(item, Q_ARG(QVariant, index - 1))) { + showShortcutBadges(false, true); + + return true; + } + } + } + } + } + } + + return false; +} + +bool ContainmentInterface::newInstanceForPlasmaTask(const int index) +{ + bool containsPlasmaTaskManager{m_view->tasksPresent() && !m_view->latteTasksArePresent()}; + + if (!containsPlasmaTaskManager) { + return false; + } + + const auto &applets = m_view->containment()->applets(); + + for (auto *applet : applets) { + const auto &provides = KPluginMetaData::readStringList(applet->pluginMetaData().rawData(), QStringLiteral("X-Plasma-Provides")); + + if (provides.contains(QLatin1String("org.kde.plasma.multitasking"))) { + if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value()) { + const auto &childItems = appletInterface->childItems(); + + if (childItems.isEmpty()) { + continue; + } + + KPluginMetaData meta = applet->kPackage().metadata(); + + for (QQuickItem *item : childItems) { + if (auto *metaObject = item->metaObject()) { + int methodIndex{metaObject->indexOfMethod("ewInstanceForTaskAtIndex(QVariant)")}; + + if (methodIndex == -1) { + continue; + } + + QMetaMethod method = metaObject->method(methodIndex); + + if (method.invoke(item, Q_ARG(QVariant, index - 1))) { + showShortcutBadges(false, true); + + return true; + } + } + } + } + } + } + + return false; +} + +bool ContainmentInterface::activateEntry(const int index) +{ + identifyMainItem(); + + if (!m_activateEntryMethod.isValid()) { + return false; + } + + return m_activateEntryMethod.invoke(m_mainItem, Q_ARG(QVariant, index)); +} + +bool ContainmentInterface::newInstanceForEntry(const int index) +{ + identifyMainItem(); + + if (!m_newInstanceMethod.isValid()) { + return false; + } + + return m_newInstanceMethod.invoke(m_mainItem, Q_ARG(QVariant, index)); +} + +bool ContainmentInterface::hideShortcutBadges() +{ + identifyMainItem(); + + if (!m_showShortcutsMethod.isValid()) { + return false; + } + + return m_showShortcutsMethod.invoke(m_mainItem, Q_ARG(QVariant, false), Q_ARG(QVariant, false), Q_ARG(QVariant, false), Q_ARG(QVariant, -1)); +} + +bool ContainmentInterface::showOnlyMeta() +{ + if (!m_corona->universalSettings()->kwin_metaForwardedToLatte()) { + return false; + } + + return showShortcutBadges(false, true); +} + +bool ContainmentInterface::showShortcutBadges(const bool showLatteShortcuts, const bool showMeta) +{ + identifyMainItem(); + + if (!m_showShortcutsMethod.isValid()) { + return false; + } + + int appLauncherId = m_corona->universalSettings()->kwin_metaForwardedToLatte() && showMeta ? applicationLauncherId() : -1; + + return m_showShortcutsMethod.invoke(m_mainItem, Q_ARG(QVariant, showLatteShortcuts), Q_ARG(QVariant, true), Q_ARG(QVariant, showMeta), Q_ARG(QVariant, appLauncherId)); +} + +} +} diff --git a/app/view/containmentinterface.h b/app/view/containmentinterface.h new file mode 100644 index 000000000..dfc5f8e08 --- /dev/null +++ b/app/view/containmentinterface.h @@ -0,0 +1,80 @@ +/* +* Copyright 2019 Michail Vourlakos +* +* This file is part of Latte-Dock +* +* Latte-Dock is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License, or (at your option) any later version. +* +* Latte-Dock 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 General Public License +* along with this program. If not, see . +*/ + +#ifndef VIEWCONTAINMENTINTERFACE_H +#define VIEWCONTAINMENTINTERFACE_H + +// Qt +#include +#include +#include +#include + +namespace Latte { +class Corona; +class View; +} + +namespace Latte { +namespace ViewPart { + +class ContainmentInterface: public QObject +{ + Q_OBJECT + +public: + ContainmentInterface(Latte::View *parent); + virtual ~ContainmentInterface(); + + bool containsApplicationLauncher() const; + bool isCapableToShowShortcutBadges() const; + + bool activateEntry(const int index); + bool newInstanceForEntry(const int index); + + bool activatePlasmaTask(const int index); + bool newInstanceForPlasmaTask(const int index); + + bool hideShortcutBadges(); + bool showOnlyMeta(); + bool showShortcutBadges(const bool showLatteShortcuts, const bool showMeta); + + //! this is updated from external apps e.g. a thunderbird plugin + bool updateBadgeForLatteTask(const QString identifier, const QString value); + + int applicationLauncherId() const; + +private slots: + void identifyMainItem(); + void identifyMethods(); + +private: + QMetaMethod m_activateEntryMethod; + QMetaMethod m_newInstanceMethod; + QMetaMethod m_showShortcutsMethod; + + QPointer m_corona; + QPointer m_view; + QPointer m_mainItem; +}; + +} +} + +#endif diff --git a/app/view/view.cpp b/app/view/view.cpp index 47511447e..036809ad7 100644 --- a/app/view/view.cpp +++ b/app/view/view.cpp @@ -67,7 +67,8 @@ namespace Latte { View::View(Plasma::Corona *corona, QScreen *targetScreen, bool byPassWM) : PlasmaQuick::ContainmentView(corona), m_contextMenu(new ViewPart::ContextMenu(this)), - m_effects(new ViewPart::Effects(this)) + m_effects(new ViewPart::Effects(this)), + m_interface(new ViewPart::ContainmentInterface(this)) { //! needs to be created after Effects because it catches some of its signals //! and avoid a crash from View::winId() at the same time @@ -205,6 +206,10 @@ View::~View() delete m_indicator; } + if (m_interface) { + delete m_interface; + } + if (m_visibility) { delete m_visibility; } @@ -1112,6 +1117,11 @@ ViewPart::Indicator *View::indicator() const return m_indicator; } +ViewPart::ContainmentInterface *View::interface() const +{ + return m_interface; +} + ViewPart::Positioner *View::positioner() const { return m_positioner; diff --git a/app/view/view.h b/app/view/view.h index 23a7a5ef0..884894022 100644 --- a/app/view/view.h +++ b/app/view/view.h @@ -22,6 +22,7 @@ #define VIEW_H // local +#include "containmentinterface.h" #include "effects.h" #include "positioner.h" #include "visibilitymanager.h" @@ -195,8 +196,9 @@ public: PlasmaQuick::ConfigView *configView(); - ViewPart::Effects *effects() const; + ViewPart::Effects *effects() const; ViewPart::Indicator *indicator() const; + ViewPart::ContainmentInterface *interface() const; ViewPart::Positioner *positioner() const; ViewPart::VisibilityManager *visibility() const; ViewPart::WindowsTracker *windowsTracker() const; @@ -356,6 +358,7 @@ private: QPointer m_contextMenu; QPointer m_effects; QPointer m_indicator; + QPointer m_interface; QPointer m_positioner; QPointer m_visibility; QPointer m_windowsTracker;