diff --git a/app/view/containmentinterface.cpp b/app/view/containmentinterface.cpp index a4c49227..0919dc6e 100644 --- a/app/view/containmentinterface.cpp +++ b/app/view/containmentinterface.cpp @@ -1,639 +1,639 @@ /* * 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 "../layout/genericlayout.h" #include "../settings/universalsettings.h" // Qt #include // Plasma #include #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()); m_latteTasksModel = new TasksModel(this); m_plasmaTasksModel = new TasksModel(this); m_appletsExpandedConnectionsTimer.setInterval(2000); m_appletsExpandedConnectionsTimer.setSingleShot(true); connect(&m_appletsExpandedConnectionsTimer, &QTimer::timeout, this, &ContainmentInterface::updateAppletsTracking); connect(m_view, &View::containmentChanged , this, [&]() { if (m_view->containment()) { connect(m_view->containment(), &Plasma::Containment::appletAdded, this, &ContainmentInterface::on_appletAdded); m_appletsExpandedConnectionsTimer.start(); } }); connect(m_latteTasksModel, &TasksModel::countChanged, this, &ContainmentInterface::onLatteTasksCountChanged); connect(m_plasmaTasksModel, &TasksModel::countChanged, this, &ContainmentInterface::onPlasmaTasksCountChanged); } ContainmentInterface::~ContainmentInterface() { } void ContainmentInterface::identifyShortcutsHost() { if (m_shortcutsHost) { return; } if (QQuickItem *graphicItem = m_view->containment()->property("_plasma_graphicObject").value()) { const auto &childItems = graphicItem->childItems(); for (QQuickItem *item : childItems) { if (item->objectName() == "containmentViewLayout" ) { for (QQuickItem *subitem : item->childItems()) { if (subitem->objectName() == "PositionShortcutsAbilityHost") { m_shortcutsHost = subitem; identifyMethods(); return; } } } } } } void ContainmentInterface::identifyMethods() { int aeIndex = m_shortcutsHost->metaObject()->indexOfMethod("activateEntryAtIndex(QVariant)"); int niIndex = m_shortcutsHost->metaObject()->indexOfMethod("newInstanceForEntryAtIndex(QVariant)"); int sbIndex = m_shortcutsHost->metaObject()->indexOfMethod("setShowAppletShortcutBadges(QVariant,QVariant,QVariant,QVariant)"); int afiIndex = m_shortcutsHost->metaObject()->indexOfMethod("appletIdForIndex(QVariant)"); m_activateEntryMethod = m_shortcutsHost->metaObject()->method(aeIndex); m_appletIdForIndexMethod = m_shortcutsHost->metaObject()->method(afiIndex); m_newInstanceMethod = m_shortcutsHost->metaObject()->method(niIndex); m_showShortcutsMethod = m_shortcutsHost->metaObject()->method(sbIndex); } bool ContainmentInterface::applicationLauncherHasGlobalShortcut() const { if (!containsApplicationLauncher()) { return false; } uint launcherAppletId = applicationLauncherId(); const auto applets = m_view->containment()->applets(); for (auto applet : applets) { if (applet->id() == launcherAppletId) { return !applet->globalShortcut().isEmpty(); } } return false; } bool ContainmentInterface::applicationLauncherInPopup() const { if (!containsApplicationLauncher()) { return false; } uint launcherAppletId = applicationLauncherId(); QString launcherPluginId; const auto applets = m_view->containment()->applets(); for (auto applet : applets) { if (applet->id() == launcherAppletId) { launcherPluginId = applet->kPackage().metadata().pluginId(); } } return launcherPluginId != "org.kde.plasma.kickerdash"; } bool ContainmentInterface::containsApplicationLauncher() const { return (applicationLauncherId() >= 0); } bool ContainmentInterface::isCapableToShowShortcutBadges() { identifyShortcutsHost(); if (!hasLatteTasks() && hasPlasmaTasks()) { return false; } return m_showShortcutsMethod.isValid(); } int ContainmentInterface::applicationLauncherId() const { const auto applets = m_view->containment()->applets(); auto launcherId{-1}; for (auto applet : applets) { const auto provides = applet->kPackage().metadata().value(QStringLiteral("X-Plasma-Provides")); if (provides.contains(QLatin1String("org.kde.plasma.launchermenu"))) { if (!applet->globalShortcut().isEmpty()) { return applet->id(); } else if (launcherId == -1) { launcherId = applet->id(); } } } return launcherId; } bool ContainmentInterface::updateBadgeForLatteTask(const QString identifier, const QString value) { if (!hasLatteTasks()) { 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{hasPlasmaTasks() && !hasLatteTasks()}; 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{hasPlasmaTasks() && !hasLatteTasks()}; 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)")}; + int methodIndex{metaObject->indexOfMethod("newInstanceForTaskAtIndex(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) { identifyShortcutsHost(); if (!m_activateEntryMethod.isValid()) { return false; } return m_activateEntryMethod.invoke(m_shortcutsHost, Q_ARG(QVariant, index)); } bool ContainmentInterface::newInstanceForEntry(const int index) { identifyShortcutsHost(); if (!m_newInstanceMethod.isValid()) { return false; } return m_newInstanceMethod.invoke(m_shortcutsHost, Q_ARG(QVariant, index)); } bool ContainmentInterface::hideShortcutBadges() { identifyShortcutsHost(); if (!m_showShortcutsMethod.isValid()) { return false; } return m_showShortcutsMethod.invoke(m_shortcutsHost, 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) { identifyShortcutsHost(); if (!m_showShortcutsMethod.isValid() || !isCapableToShowShortcutBadges()) { return false; } int appLauncherId = m_corona->universalSettings()->kwin_metaForwardedToLatte() && showMeta ? applicationLauncherId() : -1; return m_showShortcutsMethod.invoke(m_shortcutsHost, Q_ARG(QVariant, showLatteShortcuts), Q_ARG(QVariant, true), Q_ARG(QVariant, showMeta), Q_ARG(QVariant, appLauncherId)); } int ContainmentInterface::appletIdForVisualIndex(const int index) { identifyShortcutsHost(); if (!m_appletIdForIndexMethod.isValid()) { return false; } QVariant appletId{-1}; m_appletIdForIndexMethod.invoke(m_shortcutsHost, Q_RETURN_ARG(QVariant, appletId), Q_ARG(QVariant, index)); return appletId.toInt(); } void ContainmentInterface::deactivateApplets() { if (!m_view->containment() || !m_view->inReadyState()) { return; } for (const auto applet : m_view->containment()->applets()) { PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value(); if (ai) { ai->setExpanded(false); } } } bool ContainmentInterface::appletIsExpandable(const int id) { if (!m_view->containment() || !m_view->inReadyState()) { return false; } for (const auto applet : m_view->containment()->applets()) { if (applet && applet->id() == (uint)id) { if (m_view->layout() && m_view->layout()->isInternalContainment(applet)) { return true; } PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value(); if (ai) { return appletIsExpandable(ai); } } } return false; } bool ContainmentInterface::appletIsExpandable(PlasmaQuick::AppletQuickItem *appletQuickItem) { if (!appletQuickItem || !m_view->inReadyState()) { return false; } return (appletQuickItem->fullRepresentation() != nullptr && appletQuickItem->preferredRepresentation() != appletQuickItem->fullRepresentation()); } bool ContainmentInterface::hasExpandedApplet() const { return m_expandedAppletIds.count() > 0; } bool ContainmentInterface::hasLatteTasks() const { return (m_latteTasksModel->count() > 0); } bool ContainmentInterface::hasPlasmaTasks() const { return (m_plasmaTasksModel->count() > 0); } void ContainmentInterface::addExpandedApplet(const int &id) { if (m_expandedAppletIds.contains(id) && appletIsExpandable(id)) { return; } bool isExpanded = hasExpandedApplet(); m_expandedAppletIds << id; if (isExpanded != hasExpandedApplet()) { emit hasExpandedAppletChanged(); } emit expandedAppletStateChanged(); } void ContainmentInterface::removeExpandedApplet(const int &id) { if (!m_expandedAppletIds.contains(id)) { return; } bool isExpanded = hasExpandedApplet(); m_expandedAppletIds.removeAll(id); if (isExpanded != hasExpandedApplet()) { emit hasExpandedAppletChanged(); } emit expandedAppletStateChanged(); } QAbstractListModel *ContainmentInterface::latteTasksModel() const { return m_latteTasksModel; } QAbstractListModel *ContainmentInterface::plasmaTasksModel() const { return m_plasmaTasksModel; } void ContainmentInterface::on_appletExpandedChanged() { PlasmaQuick::AppletQuickItem *appletItem = static_cast(QObject::sender()); if (appletItem) { if (appletItem->isExpanded()) { addExpandedApplet(appletItem->applet()->id()); } else { removeExpandedApplet(appletItem->applet()->id()); } } } void ContainmentInterface::onLatteTasksCountChanged() { if ((m_hasLatteTasks && m_latteTasksModel->count()>0) || (!m_hasLatteTasks && m_latteTasksModel->count() == 0)) { return; } m_hasLatteTasks = (m_latteTasksModel->count() > 0); emit hasLatteTasksChanged(); } void ContainmentInterface::onPlasmaTasksCountChanged() { if ((m_hasPlasmaTasks && m_plasmaTasksModel->count()>0) || (!m_hasPlasmaTasks && m_plasmaTasksModel->count() == 0)) { return; } m_hasPlasmaTasks = (m_plasmaTasksModel->count() > 0); emit hasPlasmaTasksChanged(); } bool ContainmentInterface::appletIsExpanded(const int id) { return m_expandedAppletIds.contains(id); } void ContainmentInterface::toggleAppletExpanded(const int id) { if (!m_view->containment() || !m_view->inReadyState()) { return; } for (const auto applet : m_view->containment()->applets()) { if (applet->id() == (uint)id && !m_view->layout()->isInternalContainment(applet)/*block for internal containments*/) { PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value(); if (ai) { if (appletIsExpandable(ai)) { ai->setExpanded(!ai->isExpanded()); } else { emit applet->activated(); } } } } } void ContainmentInterface::updateAppletsTracking() { if (!m_view->containment()) { return; } for (const auto applet : m_view->containment()->applets()) { on_appletAdded(applet); } } void ContainmentInterface::on_appletAdded(Plasma::Applet *applet) { if (!m_view->containment() || !applet) { return; } if (m_view->layout() && m_view->layout()->isInternalContainment(applet)) { //! internal containment case Plasma::Containment *internalC = m_view->layout()->internalContainmentOf(applet); PlasmaQuick::AppletQuickItem *contAi = applet->property("_plasma_graphicObject").value(); if (contAi && !m_appletsExpandedConnections.contains(contAi)) { m_appletsExpandedConnections[contAi] = connect(contAi, &PlasmaQuick::AppletQuickItem::expandedChanged, this, &ContainmentInterface::on_appletExpandedChanged); connect(contAi, &QObject::destroyed, this, [&, contAi](){ m_appletsExpandedConnections.remove(contAi); removeExpandedApplet(contAi->applet()->id()); }); } for (const auto internalApplet : internalC->applets()) { PlasmaQuick::AppletQuickItem *ai = internalApplet->property("_plasma_graphicObject").value(); if (ai && !m_appletsExpandedConnections.contains(ai) ){ m_appletsExpandedConnections[ai] = connect(ai, &PlasmaQuick::AppletQuickItem::expandedChanged, this, &ContainmentInterface::on_appletExpandedChanged); connect(ai, &QObject::destroyed, this, [&, ai](){ m_appletsExpandedConnections.remove(ai); removeExpandedApplet(ai->applet()->id()); }); } } } else { PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value(); if (!ai) { return; } KPluginMetaData meta = applet->kPackage().metadata(); const auto &provides = KPluginMetaData::readStringList(meta.rawData(), QStringLiteral("X-Plasma-Provides")); if (meta.pluginId() == "org.kde.latte.plasmoid") { //! populate latte tasks applet m_latteTasksModel->addTask(ai); } else if (provides.contains(QLatin1String("org.kde.plasma.multitasking"))) { //! populate plasma tasks applet m_plasmaTasksModel->addTask(ai); } else if (!m_appletsExpandedConnections.contains(ai)) { m_appletsExpandedConnections[ai] = connect(ai, &PlasmaQuick::AppletQuickItem::expandedChanged, this, &ContainmentInterface::on_appletExpandedChanged); connect(ai, &QObject::destroyed, this, [&, ai](){ m_appletsExpandedConnections.remove(ai); removeExpandedApplet(ai->applet()->id()); }); } } } } } diff --git a/containment/package/contents/ui/abilities/PositionShortcuts.qml b/containment/package/contents/ui/abilities/PositionShortcuts.qml index da665dda..555716ca 100644 --- a/containment/package/contents/ui/abilities/PositionShortcuts.qml +++ b/containment/package/contents/ui/abilities/PositionShortcuts.qml @@ -1,66 +1,66 @@ /* * 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 . */ import QtQuick 2.8 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.plasmoid 2.0 import "./privates" as Ability Ability.PositionShortcutsPrivate { id: _shortcuts objectName: "PositionShortcutsAbilityHost" //! do not update during dragging/moving applets inConfigureAppletsMode updateIsBlocked: (root.dragOverlay && root.dragOverlay.pressed) || layouter.appletsInParentChange //! this is called from globalshortcuts c++ side function setShowAppletShortcutBadges(showPositionShortcuts, showShortcuts, showMeta, applicationLauncher){ showPositionShortcutBadges = showPositionShortcuts; showAppletShortcutBadges = showShortcuts; showMetaBadge = showMeta; applicationLauncherId = applicationLauncher; } //! this is called from Latte::View::ContainmentInterface - function activateEntryAtIndex(index) { - if (typeof index !== "number") { + function activateEntryAtIndex(entryIndex) { + if (typeof entryIndex !== "number") { return; } - sglActivateEntryAtIndex(index); + sglActivateEntryAtIndex(entryIndex); } //! this is called from Latte::View::ContainmentInterface - function newInstanceForEntryAtIndex(index) { - if (typeof index !== "number") { + function newInstanceForEntryAtIndex(entryIndex) { + if (typeof entryIndex !== "number") { return; } - sglNewInstanceForEntryAtIndex(index); + sglNewInstanceForEntryAtIndex(entryIndex); } //! this is called from Latte::View::ContainmentInterface - function appletIdForIndex(index) { - return indexer.appletIdForVisibleIndex(index); + function appletIdForIndex(entryIndex) { + return indexer.appletIdForVisibleIndex(entryIndex); } } diff --git a/containment/package/contents/ui/abilities/privates/PositionShortcutsPrivate.qml b/containment/package/contents/ui/abilities/privates/PositionShortcutsPrivate.qml index e25a0a40..0a133add 100644 --- a/containment/package/contents/ui/abilities/privates/PositionShortcutsPrivate.qml +++ b/containment/package/contents/ui/abilities/privates/PositionShortcutsPrivate.qml @@ -1,83 +1,81 @@ /* * Copyright 2020 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 . */ import QtQuick 2.7 -Item { +import org.kde.latte.abilities.definitions 0.1 as AbilityDefinition + +AbilityDefinition.PositionShortcuts { id: _shortcutsprivate property Item layouts: null property bool updateIsBlocked: false readonly property bool unifiedGlobalShortcuts: appletIdStealingPositionShortcuts === -1 - property bool showPositionShortcutBadges: false property bool showAppletShortcutBadges: false property bool showMetaBadge: false property int applicationLauncherId: -1 property int appletIdStealingPositionShortcuts: -1 - signal sglActivateEntryAtIndex(int entryIndex); - signal sglNewInstanceForEntryAtIndex(int entryIndex); - Binding { target: _shortcutsprivate property: "appletIdStealingPositionShortcuts" when: !updateIsBlocked value: { var sLayout = layouts.startLayout; for (var i=0; i=0 && appletItem.communicator - && appletItem.communicator.onPositionShortcutsAreSupported + && appletItem.communicator.positionShortcutsAreSupported && appletItem.communicator.bridge.shortcuts.client.isStealingGlobalPositionShortcuts) { return appletItem.index; } } var mLayout = layouts.mainLayout; for (var i=0; i=0 && appletItem.communicator - && appletItem.communicator.onPositionShortcutsAreSupported + && appletItem.communicator.positionShortcutsAreSupported && appletItem.communicator.bridge.shortcuts.client.isStealingGlobalPositionShortcuts) { return appletItem.index; } } var eLayout = layouts.endLayout; for (var i=0; i=0 && appletItem.communicator - && appletItem.communicator.onPositionShortcutsAreSupported + && appletItem.communicator.positionShortcutsAreSupported && appletItem.communicator.bridge.shortcuts.client.isStealingGlobalPositionShortcuts) { return appletItem.index; } } return -1; } } } diff --git a/containment/package/contents/ui/applet/AppletItem.qml b/containment/package/contents/ui/applet/AppletItem.qml index ef329b53..bdbbea63 100644 --- a/containment/package/contents/ui/applet/AppletItem.qml +++ b/containment/package/contents/ui/applet/AppletItem.qml @@ -1,1199 +1,1199 @@ /* * Copyright 2016 Smith AR * 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 . */ import QtQuick 2.7 import QtQuick.Layouts 1.1 import QtGraphicalEffects 1.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.components 1.0 as LatteComponents import "colorizer" as Colorizer import "communicator" as Communicator import "indicator" as Indicator import "../debug" as Debug Item { id: appletItem visible: false width: isInternalViewSplitter && !root.inConfigureAppletsMode ? 0 : computeWidth height: isInternalViewSplitter && !root.inConfigureAppletsMode ? 0 : computeHeight //any applets that exceed their limits should not take events from their surrounding applets clip: !isSeparator signal mousePressed(int x, int y, int button); signal mouseReleased(int x, int y, int button); property bool animationsEnabled: true property bool parabolicEffectIsSupported: true property bool canShowAppletNumberBadge: !isSeparator && !isHidden && !isLattePlasmoid && !isSpacer && !isInternalViewSplitter //! Fill Applet(s) property bool inFillCalculations: false //temp record, is used in calculations for fillWidth,fillHeight applets property bool isAutoFillApplet: { if (!applet || !applet.Layout) return false; if (((root.isHorizontal && applet.Layout.fillWidth===true) || (root.isVertical && applet.Layout.fillHeight===true)) && (applet.status !== PlasmaCore.Types.HiddenStatus)) return true; else return false; } property int maxAutoFillLength: -1 //it is used in calculations for fillWidth,fillHeight applets property int minAutoFillLength: -1 //it is used in calculations for fillWidth,fillHeight applets property bool userBlocksColorizing: false property bool appletBlocksColorizing: !communicator.requires.latteSideColoringEnabled property bool appletBlocksParabolicEffect: communicator.requires.parabolicEffectLocked property bool lockZoom: false property bool isActive: (isExpanded && applet.pluginName !== root.plasmoidName && applet.pluginName !== "org.kde.activeWindowControl" && applet.pluginName !== "org.kde.plasma.appmenu") property bool isExpanded: false property bool isHidden: (applet && applet.status === PlasmaCore.Types.HiddenStatus) || (isInternalViewSplitter && !root.inConfigureAppletsMode) property bool isInternalViewSplitter: (internalSplitterId > 0) property bool isLattePlasmoid: latteApplet !== null property bool isZoomed: false property bool isSeparator: applet && (applet.pluginName === "audoban.applet.separator" || applet.pluginName === "org.kde.latte.separator") property bool isSpacer: applet && (applet.pluginName === "org.kde.latte.spacer") property bool isSystray: applet && (applet.pluginName === "org.kde.plasma.systemtray" || applet.pluginName === "org.nomad.systemtray" ) property bool firstChildOfStartLayout: index === appletItem.layouter.startLayout.firstVisibleIndex property bool firstChildOfMainLayout: index === appletItem.layouter.mainLayout.firstVisibleIndex property bool lastChildOfMainLayout: index === appletItem.layouter.mainLayout.lastVisibleIndex property bool lastChildOfEndLayout: index === appletItem.layouter.endLayout.lastVisibleIndex readonly property bool atScreenEdge: { if (root.panelAlignment !== LatteCore.Types.Justify || root.inConfigureAppletsMode || plasmoid.configuration.offset!==0) { return false; } if (root.panelAlignment === LatteCore.Types.Justify) { //! Justify case if (root.maxLengthPerCentage!==100) { return false; } if (root.isHorizontal) { if (firstChildOfStartLayout) { return latteView && latteView.x === latteView.screenGeometry.x; } else if (lastChildOfEndLayout) { return latteView && ((latteView.x + latteView.width) === (latteView.screenGeometry.x + latteView.screenGeometry.width)); } } else { if (firstChildOfStartLayout) { return latteView && latteView.y === latteView.screenGeometry.y; } else if (lastChildOfEndLayout) { return latteView && ((latteView.y + latteView.height) === (latteView.screenGeometry.y + latteView.screenGeometry.height)); } } return false; } //! [disabled] because it is probably not needed at all. If in the future there is a report //! describing a case that this would be useful this disablement choice can be rethought /*if (root.panelAlignment === LatteCore.Types.Left) { //! Left case return firstChildOfMainLayout; } else if (root.panelAlignment === LatteCore.Types.Right) { //! Right case return lastChildOfMainLayout } if (root.panelAlignment === LatteCore.Types.Top) { return firstChildOfMainLayout && latteView && latteView.y === latteView.screenGeometry.y; } else if (root.panelAlignment === LatteCore.Types.Bottom) { return lastChildOfMainLayout && latteView && ((latteView.y + latteView.height) === (latteView.screenGeometry.y + latteView.screenGeometry.height)); }*/ return false; } //applet is in starting edge property bool firstAppletInContainer: (index >=0) && ((index === layouter.startLayout.firstVisibleIndex) || (index === layouter.mainLayout.firstVisibleIndex) || (index === layouter.endLayout.firstVisibleIndex)) //applet is in ending edge property bool lastAppletInContainer: (index >=0) && ((index === layouter.startLayout.lastVisibleIndex) || (index === layouter.mainLayout.lastVisibleIndex) || (index === layouter.endLayout.lastVisibleIndex)) readonly property bool acceptMouseEvents: applet && !isLattePlasmoid && !originalAppletBehavior && !appletItem.isSeparator && !communicator.requires.parabolicEffectLocked readonly property bool originalAppletBehavior: (appletItem.parabolic.factor.zoom === 1 && !lockZoom /*hacky flag to keep Latte behavior*/) || (appletItem.parabolic.factor.zoom>1 && !parabolicEffectIsSupported) || (appletItem.parabolic.factor.zoom>1 && parabolicEffectIsSupported && lockZoom) readonly property bool isSquare: communicator.overlayLatteIconIsActive readonly property bool screenEdgeMarginSupported: communicator.requires.screenEdgeMarginSupported property int animationTime: appletItem.animations.speedFactor.normal * (1.2*appletItem.animations.duration.small) property int index: -1 property int maxWidth: root.isHorizontal ? root.height : root.width property int maxHeight: root.isHorizontal ? root.height : root.width property int internalSplitterId: 0 property int previousIndex: -1 property int spacersMaxSize: Math.max(0,Math.ceil(0.55 * metrics.iconSize) - metrics.totals.lengthEdges) property int status: applet ? applet.status : -1 //! separators tracking readonly property bool tailAppletIsSeparator: { if (isSeparator || index<0) { return false; } var tail = index - 1; while(tail>=0 && indexer.hidden.indexOf(tail)>=0) { //! when a tail applet contains sub-indexing and does not influence //! tracking is considered hidden tail = tail - 1; } if (tail >= 0 && indexer.clients.indexOf(tail)>=0) { //! tail applet contains items sub-indexing var tailBridge = indexer.getClientBridge(tail); if (tailBridge && tailBridge.client) { return tailBridge.client.lastHeadItemIsSeparator; } } // tail applet is normal return (indexer.separators.indexOf(tail)>=0); } readonly property bool headAppletIsSeparator: { if (isSeparator || index<0) { return false; } var head = index + 1; while(head>=0 && indexer.hidden.indexOf(head)>=0) { //! when a head applet contains sub-indexing and does not influence //! tracking is considered hidden head = head + 1; } if (head >= 0 && indexer.clients.indexOf(head)>=0) { //! head applet contains items sub-indexing var headBridge = indexer.getClientBridge(head); if (headBridge && headBridge.client) { return headBridge.client.firstTailItemIsSeparator; } } // head applet is normal return (indexer.separators.indexOf(head)>=0); } //! local margins readonly property bool parabolicEffectMarginsEnabled: appletItem.parabolic.factor.zoom>1 && !originalAppletBehavior && !communicator.parabolicEffectIsSupported property int lengthAppletPadding: metrics.fraction.lengthAppletPadding === -1 || parabolicEffectMarginsEnabled ? metrics.padding.length : metrics.padding.lengthApplet property int lengthAppletFullMargin: 0 property int lengthAppletFullMargins: 2 * lengthAppletFullMargin property int internalWidthMargins: { if (root.isVertical) { return metrics.totals.thicknessEdges; } /*TODO, Fitt's case: is temporary until the atScreenEdge applets are aligned properly to the corner and the wrapper is taking all the space needed in order to fill right. For atScreenEdge appplets that should be: applet size + lengthAppletPadding + lengthAppletExtMargin. The indicator should follow also the applet alignment in this in order to feel right */ return 2 * lengthAppletPadding; } property int internalHeightMargins: { if (root.isHorizontal) { return root.metrics.totals.thicknessEdges; } /*TODO,Fitt's case: is temporary until the atScreenEdge applets are aligned properly to the corner and the wrapper is taking all the space needed in order to fill right. For atScreenEdge appplets that should be: applet size + lengthAppletPadding + lengthAppletExtMargin. The indicator should follow also the applet alignment in this in order to feel right */ return 2 * lengthAppletPadding; } //! are set by the indicator property int iconOffsetX: 0 property int iconOffsetY: 0 property real computeWidth: root.isVertical ? wrapper.width : hiddenSpacerLeft.width+wrapper.width+hiddenSpacerRight.width property real computeHeight: root.isVertical ? hiddenSpacerLeft.height + wrapper.height + hiddenSpacerRight.height : wrapper.height property string title: isInternalViewSplitter ? "Now Dock Splitter" : "" property Item applet: null property Item latteApplet: applet && (applet.pluginName === root.plasmoidName) ? (applet.children[0] ? applet.children[0] : null) : null property Item latteStyleApplet: applet && ((applet.pluginName === "org.kde.latte.spacer") || (applet.pluginName === "org.kde.latte.separator")) ? (applet.children[0] ? applet.children[0] : null) : null property Item appletWrapper: applet && (applet.pluginName === root.plasmoidName )? wrapper : wrapper.wrapperContainer property Item tooltipVisualParent: titleTooltipParent readonly property alias communicator: _communicator readonly property alias wrapper: _wrapper property Item animations: null property Item indexer: null property Item layouter: null property Item metrics: null property Item parabolic: null property Item shortcuts: null property bool containsMouse: appletMouseArea.containsMouse || (isLattePlasmoid && latteApplet.containsMouse) property bool pressed: viewSignalsConnector.pressed || clickedAnimation.running //// BEGIN :: Animate Applet when a new applet is dragged in the view //when the applet moves caused by its resize, don't animate. //this is completely heuristic, but looks way less "jumpy" property bool movingForResize: false property int oldX: x property int oldY: y onXChanged: { if (root.isVertical) { return; } if (movingForResize) { movingForResize = false; return; } var draggingAppletInConfigure = root.dragOverlay && root.dragOverlay.currentApplet; var isCurrentAppletInDragging = draggingAppletInConfigure && (root.dragOverlay.currentApplet === appletItem); var dropApplet = root.dragInfo.entered && foreDropArea.visible if (isCurrentAppletInDragging || !draggingAppletInConfigure && !dropApplet) { return; } if (!root.isVertical) { translation.x = oldX - x; translation.y = 0; } else { translation.y = oldY - y; translation.x = 0; } translAnim.running = true if (!root.isVertical) { oldX = x; oldY = 0; } else { oldY = y; oldX = 0; } } onYChanged: { if (root.isHorizontal) { return; } if (movingForResize) { movingForResize = false; return; } var draggingAppletInConfigure = root.dragOverlay && root.dragOverlay.currentApplet; var isCurrentAppletInDragging = draggingAppletInConfigure && (root.dragOverlay.currentApplet === appletItem); var dropApplet = root.dragInfo.entered && foreDropArea.visible if (isCurrentAppletInDragging || !draggingAppletInConfigure && !dropApplet) { return; } if (!root.isVertical) { translation.x = oldX - x; translation.y = 0; } else { translation.y = oldY - y; translation.x = 0; } translAnim.running = true; if (!root.isVertical) { oldX = x; oldY = 0; } else { oldY = y; oldX = 0; } } transform: Translate { id: translation } NumberAnimation { id: translAnim duration: appletItem.animations.duration.large easing.type: Easing.InOutQuad target: translation properties: "x,y" to: 0 } Behavior on lengthAppletPadding { NumberAnimation { duration: 0.8 * appletItem.animations.duration.proposed easing.type: Easing.OutCubic } } //// END :: Animate Applet when a new applet is dragged in the view /// BEGIN functions function activateAppletForNeutralAreas(mouse){ //if the event is at the active indicator or spacers area then try to expand the applet, //unfortunately for other applets there is no other way to activate them yet //for example the icon-only applets var choords = mapToItem(appletItem.appletWrapper, mouse.x, mouse.y); var wrapperContainsMouse = choords.x>=0 && choords.y>=0 && choords.x=0 && mouse.y>=0 && mouse.x0); var appletNeutralAreaEnabled = !(inThicknessNeutralArea && root.dragActiveWindowEnabled); if (appletItemContainsMouse && !wrapperContainsMouse && appletNeutralAreaEnabled) { //console.log("PASSED"); latteView.extendedInterface.toggleAppletExpanded(applet.id); } else { //console.log("REJECTED"); } } function checkIndex(){ index = -1; for(var i=0; i maxSize || applet.Layout.minimumWidth > maxForMinimumSize)) || (applet && root.isVertical && (applet.height > maxSize || applet.Layout.minimumHeight > maxForMinimumSize))) && !appletItem.isSpacer && !communicator.canShowOverlaiedLatteIcon) ) { appletItem.parabolicEffectIsSupported = false; } else { appletItem.parabolicEffectIsSupported = true; } } } function slotDestroyInternalViewSplitters() { if (isInternalViewSplitter) { destroy(); } } //! pos in global root positioning function containsPos(pos) { var relPos = root.mapToItem(appletItem,pos.x, pos.y); if (relPos.x>=0 && relPos.x<=width && relPos.y>=0 && relPos.y<=height) return true; return false; } function refersEntryIndex(entryIndex) { return (entryIndex === parabolicManager.pseudoAppletIndex(appletItem.index)); } ///END functions //BEGIN connections onAppletChanged: { if (!applet) { destroy(); } } onIndexChanged: { if (appletItem.latteApplet) { root.latteAppletPos = index; } if (index>-1) { previousIndex = index; } } onIsExpandedChanged: { if (isExpanded) { root.hideTooltipLabel(); } } onIsSystrayChanged: { updateParabolicEffectIsSupported(); } onLatteAppletChanged: { if(appletItem.latteApplet){ root.latteApplet = appletItem.latteApplet; root.latteAppletContainer = appletItem; root.latteAppletPos = index; appletItem.latteApplet.latteView = root; appletItem.latteApplet.forceHidePanel = true; appletItem.latteApplet.signalPreviewsShown.connect(slotPreviewsShown); } } onIsAutoFillAppletChanged: updateParabolicEffectIsSupported(); Component.onCompleted: { checkIndex(); root.updateIndexes.connect(checkIndex); root.destroyInternalViewSplitters.connect(slotDestroyInternalViewSplitters); parabolic.sglClearZoom.connect(sltClearZoom); } Component.onDestruction: { appletItem.animations.needBothAxis.removeEvent(appletItem); if(root.latteAppletPos>=0 && root.latteAppletPos === index){ root.latteApplet = null; root.latteAppletContainer = null; root.latteAppletPos = -1; } root.updateIndexes.disconnect(checkIndex); root.destroyInternalViewSplitters.disconnect(slotDestroyInternalViewSplitters); parabolic.sglClearZoom.disconnect(sltClearZoom); if (appletItem.latteApplet) { appletItem.latteApplet.signalPreviewsShown.disconnect(slotPreviewsShown); } } //! Bindings Binding { //! is used to aboid loop binding warnings on startup target: appletItem property: "lengthAppletFullMargin" when: !communicator.inStartup value: lengthAppletPadding + metrics.margin.length; } //! Connections Connections{ target: appletItem.shortcuts onSglActivateEntryAtIndex: { - if (parabolicManager.pseudoIndexBelongsToLatteApplet(entryIndex) && appletItem.isLattePlasmoid) { - latteApplet.activateTaskAtIndex(entryIndex - latteApplet.tasksBaseIndex); - } else if (shortcuts.unifiedGlobalShortcuts && refersEntryIndex(entryIndex)) { + var visibleIndex = appletItem.indexer.visibleIndex(appletItem.index); + + if (visibleIndex === entryIndex && !communicator.positionShortcutsAreSupported) { latteView.extendedInterface.toggleAppletExpanded(applet.id); } } onSglNewInstanceForEntryAtIndex: { - if (parabolicManager.pseudoIndexBelongsToLatteApplet(entryIndex) && appletItem.isLattePlasmoid) { - latteApplet.newInstanceForTaskAtIndex(entryIndex - latteApplet.tasksBaseIndex); - } else if (shortcuts.unifiedGlobalShortcuts && refersEntryIndex(entryIndex)) { + var visibleIndex = appletItem.indexer.visibleIndex(appletItem.index); + + if (visibleIndex === entryIndex && !communicator.positionShortcutsAreSupported) { latteView.extendedInterface.toggleAppletExpanded(applet.id); } } } Connections { id: viewSignalsConnector target: root.latteView ? root.latteView : null enabled: !appletItem.isLattePlasmoid && !appletItem.isSeparator && !appletItem.isSpacer && !appletItem.isHidden property bool pressed: false property bool blockWheel: false onMousePressed: { if (appletItem.containsPos(pos)) { viewSignalsConnector.pressed = true; var local = appletItem.mapFromItem(root, pos.x, pos.y); appletItem.mousePressed(local.x, local.y, button); if (button === Qt.LeftButton) { appletItem.activateAppletForNeutralAreas(local); } } } onMouseReleased: { if (appletItem.containsPos(pos)) { viewSignalsConnector.pressed = false; var local = appletItem.mapFromItem(root, pos.x, pos.y); appletItem.mouseReleased(local.x, local.y, button); } } onWheelScrolled: { if (!appletItem.applet || !root.mouseWheelActions || viewSignalsConnector.blockWheel || (root.latteViewIsHidden || root.inSlidingIn || root.inSlidingOut)) { return; } blockWheel = true; scrollDelayer.start(); if (appletItem.containsPos(pos) && root.latteView.extendedInterface.appletIsExpandable(applet.id)) { var angle = angleDelta.y / 8; var expanded = root.latteView.extendedInterface.appletIsExpanded(applet.id); if ((angle > 12 && !expanded) /*positive direction*/ || (angle < -12 && expanded) /*negative direction*/) { latteView.extendedInterface.toggleAppletExpanded(applet.id); } } } } Connections { target: root.latteView ? root.latteView.extendedInterface : null enabled: !appletItem.isLattePlasmoid && !appletItem.isSeparator && !appletItem.isSpacer && !appletItem.isHidden onExpandedAppletStateChanged: { if (latteView.extendedInterface.hasExpandedApplet && appletItem.applet) { appletItem.isExpanded = latteView.extendedInterface.appletIsExpandable(appletItem.applet.id) && latteView.extendedInterface.appletIsExpanded(appletItem.applet.id); } else { appletItem.isExpanded = false; } } } ///END connections //! It is used for any communication needed with the underlying applet Communicator.Engine{ id: _communicator //set up the overlayed appletItems and properties for when a overlaiedIconItem must be presented to the user //because the plasma widgets specific implementation breaks the Latte experience onOverlayLatteIconIsActiveChanged:{ if (!overlayLatteIconIsActive && applet.opacity===0) { applet.opacity = 1; } else if (overlayLatteIconIsActive && applet.opacity>0) { applet.opacity = 0; if (applet.pluginName === "org.kde.plasma.folder") { applet.parent = wrapper.containerForOverlayIcon; applet.anchors.fill = wrapper.containerForOverlayIcon; } } } } /* Rectangle{ anchors.fill: parent color: "transparent" border.color: "green" border.width: 1 }*/ /* DEPRECATED in favor of VIEW::MouseSignalsTracking MouseArea{ id: appletMouseAreaBottom anchors.fill: parent propagateComposedEvents: true visible: (!appletMouseArea.visible || !appletMouseArea.enabled) && !root.editMode && !originalAppletBehavior onPressed: { appletItem.activateAppletForNeutralAreas(mouse); mouse.accepted = false; } onReleased: { mouse.accepted = false; } }*/ //! Main Applet Shown Area Flow{ id: appletFlow width: appletItem.computeWidth height: appletItem.computeHeight // a hidden spacer for the first element to add stability // IMPORTANT: hidden spacers must be tested on vertical !!! HiddenSpacer{id: hiddenSpacerLeft} Item { width: wrapper.width height: wrapper.height Indicator.Bridge{ id: indicatorBridge } //! Indicator Back Layer Indicator.Loader{ id: indicatorBackLayer level: Indicator.LevelOptions { id: backLevelOptions isBackground: true bridge: indicatorBridge Binding { target: appletItem property: "iconOffsetX" value: backLevelOptions.requested.iconOffsetX } Binding { target: appletItem property: "iconOffsetY" value: backLevelOptions.requested.iconOffsetY } } } ItemWrapper{ id: _wrapper TitleTooltipParent{ id: titleTooltipParent metrics: appletItem.metrics parabolic: appletItem.parabolic } } //! The Applet Colorizer Colorizer.Applet { id: appletColorizer anchors.fill: parent opacity: mustBeShown ? 1 : 0 readonly property bool mustBeShown: colorizerManager.mustBeShown && !appletItem.userBlocksColorizing && !appletItem.appletBlocksColorizing && !appletItem.isInternalViewSplitter Behavior on opacity { NumberAnimation { duration: 1.2 * appletItem.animations.duration.proposed easing.type: Easing.OutCubic } } } //! Indicator Front Layer Indicator.Loader{ id: indicatorFrontLayer level: Indicator.LevelOptions { isForeground: true bridge: indicatorBridge } } //! Applet Shortcut Visual Badge Item { id: shortcutBadgeContainer width: { if (root.isHorizontal) { return appletItem.metrics.iconSize * wrapper.zoomScale } else { return badgeThickness; } } height: { if (root.isHorizontal) { return badgeThickness; } else { return appletItem.metrics.iconSize * wrapper.zoomScale } } readonly property int badgeThickness: { if (plasmoid.location === PlasmaCore.Types.BottomEdge || plasmoid.location === PlasmaCore.Types.RightEdge) { return ((appletItem.metrics.iconSize + appletItem.metrics.margin.thickness) * wrapper.zoomScale) + appletItem.metrics.margin.screenEdge; } return ((appletItem.metrics.iconSize + appletItem.metrics.margin.thickness) * wrapper.zoomScale); } ShortcutBadge{ anchors.fill: parent } states:[ State{ name: "horizontal" when: plasmoid.formFactor === PlasmaCore.Types.Horizontal AnchorChanges{ target: shortcutBadgeContainer; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.bottom; } }, State{ name: "vertical" when: plasmoid.formFactor === PlasmaCore.Types.Vertical AnchorChanges{ target: shortcutBadgeContainer; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: parent.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined; } } ] } } // a hidden spacer on the right for the last item to add stability HiddenSpacer{id: hiddenSpacerRight; rightSpacer: true} }// Flow with hidden spacers inside //Busy Indicator PlasmaComponents.BusyIndicator { z: 1000 visible: applet && applet.busy running: visible anchors.centerIn: parent width: Math.min(parent.width, parent.height) height: width } Loader { id: addingAreaLoader width: root.isHorizontal ? parent.width : parent.width - appletItem.metrics.margin.screenEdge height: root.isHorizontal ? parent.height - appletItem.metrics.margin.screenEdge : parent.height active: isLattePlasmoid sourceComponent: LatteComponents.AddingArea{ id: addingAreaItem anchors.fill: parent // width: root.isHorizontal ? parent.width : parent.width - appletItem.metrics.margin.screenEdge // height: root.isHorizontal ? parent.height - appletItem.metrics.margin.screenEdge : parent.height radius: appletItem.metrics.iconSize/10 opacity: root.addLaunchersMessage ? 1 : 0 backgroundOpacity: 0.75 duration: appletItem.animations.speedFactor.current title: i18n("Tasks Area") } //! AddingAreaItem States states:[ State{ name: "bottom" when: plasmoid.location === PlasmaCore.Types.BottomEdge AnchorChanges{ target: addingAreaLoader anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.bottom; } PropertyChanges{ target: addingAreaLoader anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: appletItem.metrics.margin.screenEdge; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "top" when: plasmoid.location === PlasmaCore.Types.TopEdge AnchorChanges{ target: addingAreaLoader anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: parent.top; anchors.bottom: undefined; } PropertyChanges{ target: addingAreaLoader anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin: appletItem.metrics.margin.screenEdge; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "left" when: plasmoid.location === PlasmaCore.Types.LeftEdge AnchorChanges{ target: addingAreaLoader anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: undefined; anchors.left: parent.left; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: addingAreaLoader anchors.leftMargin: appletItem.metrics.margin.screenEdge; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "right" when: plasmoid.location === PlasmaCore.Types.RightEdge AnchorChanges{ target: addingAreaLoader anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: parent.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: addingAreaLoader anchors.leftMargin: 0; anchors.rightMargin: appletItem.metrics.margin.screenEdge; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } } ] } MouseArea{ id: appletMouseArea anchors.fill: parent enabled: visible hoverEnabled: latteApplet ? false : true propagateComposedEvents: true //! a way must be found in order for this be enabled //! only to support springloading for plasma 5.10 //! also on this is based the tooltips behavior by enabling it //! plasma tooltips are disabled visible: acceptMouseEvents property bool blockWheel: false onEntered: { appletItem.parabolic.stopRestoreZoomTimer(); if (restoreAnimation.running) { restoreAnimation.stop(); } if (!(isSeparator || isSpacer)) { root.showTooltipLabel(appletItem, applet.title); } if (originalAppletBehavior || communicator.requires.parabolicEffectLocked || !parabolicEffectIsSupported) { return; } if (root.isHalfShown || (root.latteApplet && (root.latteApplet.noTasksInAnimation>0 || root.latteApplet.contextMenu))) { return; } if (root.isHorizontal){ layoutsContainer.currentSpot = mouseX; wrapper.calculateScales(mouseX); } else{ layoutsContainer.currentSpot = mouseY; wrapper.calculateScales(mouseY); } } onExited:{ if (communicator.appletIconItemIsShown()) { communicator.setAppletIconItemActive(false); } root.hideTooltipLabel(); if (appletItem.parabolic.factor.zoom>1){ appletItem.parabolic.startRestoreZoomTimer(); } } onPositionChanged: { if (originalAppletBehavior || !parabolicEffectIsSupported) { mouse.accepted = false; return; } if (root.isHalfShown || (root.latteApplet && (root.latteApplet.noTasksInAnimation>0 || root.latteApplet.contextMenu))) { return; } var rapidMovement = appletItem.parabolic.lastIndex>=0 && Math.abs(appletItem.parabolic.lastIndex-index)>1; if (rapidMovement) { parabolic.setDirectRenderingEnabled(true); } if( ((wrapper.zoomScale == 1 || wrapper.zoomScale === appletItem.parabolic.factor.zoom) && !parabolic.directRenderingEnabled) || parabolic.directRenderingEnabled) { if (root.isHorizontal){ var step = Math.abs(layoutsContainer.currentSpot-mouse.x); if (step >= appletItem.animations.hoverPixelSensitivity){ layoutsContainer.currentSpot = mouse.x; wrapper.calculateScales(mouse.x); } } else{ var step = Math.abs(layoutsContainer.currentSpot-mouse.y); if (step >= appletItem.animations.hoverPixelSensitivity){ layoutsContainer.currentSpot = mouse.y; wrapper.calculateScales(mouse.y); } } } mouse.accepted = false; } //! these are needed in order for these events to be really forwarded underneath //! otherwise there were applets that did not receive them e.g. lock/logout applet //! when parabolic effect was used onPressed: mouse.accepted = false; onReleased: mouse.accepted = false; } //! Debug Elements Loader{ anchors.bottom: parent.bottom anchors.left: parent.left active: root.debugModeLayouter sourceComponent: Debug.Tag{ label.text: (root.isHorizontal ? appletItem.width : appletItem.height) + labeltext label.color: appletItem.isAutoFillApplet ? "green" : "white" readonly property string labeltext: { if (appletItem.isAutoFillApplet) { return " / max_fill:"+appletItem.maxAutoFillLength + " / min_fill:"+appletItem.minAutoFillLength; } return ""; } } } //! A timer is needed in order to handle also touchpads that probably //! send too many signals very fast. This way the signals per sec are limited. //! The user needs to have a steady normal scroll in order to not //! notice a annoying delay Timer{ id: scrollDelayer interval: 500 onTriggered: viewSignalsConnector.blockWheel = false; } //BEGIN states states: [ State { name: "left" when: (plasmoid.location === PlasmaCore.Types.LeftEdge) AnchorChanges { target: appletFlow anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined;} } }, State { name: "right" when: (plasmoid.location === PlasmaCore.Types.RightEdge) AnchorChanges { target: appletFlow anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right;} } }, State { name: "bottom" when: (plasmoid.location === PlasmaCore.Types.BottomEdge) AnchorChanges { target: appletFlow anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined;} } }, State { name: "top" when: (plasmoid.location === PlasmaCore.Types.TopEdge) AnchorChanges { target: appletFlow anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined;} } } ] //END states //BEGIN animations ///////Restore Zoom Animation///// ParallelAnimation{ id: restoreAnimation PropertyAnimation { target: wrapper property: "zoomScale" to: 1 duration: 3 * appletItem.animationTime easing.type: Easing.InCubic } } /////Clicked Animation///// SequentialAnimation{ id: clickedAnimation alwaysRunToEnd: true running: appletItem.isSquare && !originalAppletBehavior && appletItem.pressed && (appletItem.animations.speedFactor.current > 0) && !indicators.info.providesClickedAnimation ParallelAnimation{ PropertyAnimation { target: wrapper.clickedEffect property: "brightness" to: -0.35 duration: appletItem.animations.duration.large easing.type: Easing.OutQuad } } ParallelAnimation{ PropertyAnimation { target: wrapper.clickedEffect property: "brightness" to: 0 duration: appletItem.animations.duration.large easing.type: Easing.OutQuad } } } //END animations } diff --git a/containment/package/contents/ui/applet/communicator/Engine.qml b/containment/package/contents/ui/applet/communicator/Engine.qml index dec60327..2324bd87 100644 --- a/containment/package/contents/ui/applet/communicator/Engine.qml +++ b/containment/package/contents/ui/applet/communicator/Engine.qml @@ -1,127 +1,127 @@ /* * Copyright 2018 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 . */ import QtQuick 2.7 import org.kde.latte.abilities.definitions 0.1 as AbilityDefinition import "../../../code/AppletIdentifier.js" as AppletIdentifier Item{ id: mainCommunicator // ------------------------------------- // BEGIN OF INTERNAL APPLET PROPERTIES // LATTE<->APPLET COMMUNICATION PROTOCOL // ------------------------------------- // // NAME: latteBridge // USAGE: property QtObject latteBridge: null // EXPLANATION: The main shared object that Latte is using to communicate with the applet property bool appletContainsLatteBridge: appletRootItem && appletRootItem.hasOwnProperty("latteBridge") ? true : false //! END OF INTERNAL APPLET PROPERTIES // ------------------------------------- //! BEGIN OF PROPERTIES //this is used for folderView and icon widgets to fake their visual icons readonly property bool canShowOverlaiedLatteIcon: appletIconItem && appletIconItem.visible readonly property bool overlayLatteIconIsActive: canShowOverlaiedLatteIcon && requires.latteIconOverlayEnabled property bool inStartup: true property Item appletRootItem: appletDiscoveredRootItem ? appletDiscoveredRootItem : appletDefaultRootItem property Item appletDiscoveredRootItem: null property Item appletDefaultRootItem: applet && applet.children && applet.children.length>0 ? applet.children[0] : null property Item appletIconItem; //first applet's IconItem to be used by Latte property Item appletImageItem; //first applet's ImageItem to be used by Latte //! END OF PROPERTIES //! BEGIN OF PUBLIC PROPERTIES SET THROUGH LATTEBRIDGE.ACTIONS readonly property Item requires: AbilityDefinition.AppletRequirements{} //! END OF PUBLIC PROPERTIES SET THROUGH LATTEBRIDGE.ACTIONS //! BEGIN OF ABILITIES SUPPORT readonly property bool indexerIsSupported: bridge && bridge.indexer.client - readonly property bool onPositionShortcutsAreSupported: bridge && bridge.shortcuts.client readonly property bool parabolicEffectIsSupported: bridge && bridge.parabolic.client + readonly property bool positionShortcutsAreSupported: bridge && bridge.shortcuts.client readonly property Item bridge: bridgeLoader.active ? bridgeLoader.item : null //! END OF ABILITIES SUPPORT //! BEGIN OF FUNCTIONS function appletIconItemIsShown() { return appletIconItem && appletIconItem.visible; } function appletImageItemIsShown() { return appletImageItem && appletImageItem.visible; } function reconsiderAppletIconItem() { AppletIdentifier.reconsiderAppletIconItem(); } function setAppletIconItemActive(isActive) { if (appletIconItem) { appletIconItem.active = isActive; } } //! END OF FUNCTIONS //! BEGIN OF CONNECTIONS Connections{ target: appletItem onAppletChanged: { if (applet) { AppletIdentifier.checkAndUpdateAppletRootItem(); AppletIdentifier.reconsiderAppletIconItem(); overlayInitTimer.start(); } } } //! END OF CONNECTIONS //! BEGIN OF LOADERS Loader{ id: bridgeLoader active: appletContainsLatteBridge sourceComponent: LatteBridge{} } //! END OF LOADERS //! BEGIN OF TIMERS //a timer that is used in order to init some Communicator values Timer { id: overlayInitTimer interval: 1000 onTriggered: { AppletIdentifier.checkAndUpdateAppletRootItem(); AppletIdentifier.reconsiderAppletIconItem(); mainCommunicator.inStartup = false; if (root.debugModeTimers) { console.log("containment timer: appletItem fakeInitTimer called..."); } } } //! END OF TIMERS } diff --git a/declarativeimports/abilities/applets/PositionShortcuts.qml b/declarativeimports/abilities/applets/PositionShortcuts.qml new file mode 100644 index 00000000..a6ffc6b3 --- /dev/null +++ b/declarativeimports/abilities/applets/PositionShortcuts.qml @@ -0,0 +1,57 @@ +/* +* Copyright 2020 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 . +*/ + +import QtQuick 2.0 + +import org.kde.latte.abilities.definitions 0.1 as AbilityDefinition + +AbilityDefinition.PositionShortcuts { + id: shortcuts + property Item bridge: null + readonly property bool isActive: bridge !== null + + property bool isStealingGlobalPositionShortcuts: false + readonly property bool showPositionShortcutBadges: ref.shortcuts.showPositionShortcutBadges + + readonly property AbilityDefinition.ParabolicEffect local: AbilityDefinition.ParabolicEffect {} + + Item { + id: ref + readonly property Item shortcuts: bridge ? bridge.shortcuts.host : local + } + + onIsActiveChanged: { + if (isActive) { + bridge.shortcuts.client = shortcuts; + } + } + + Component.onCompleted: { + if (isActive) { + bridge.shortcuts.client = shortcuts; + } + } + + Component.onDestruction: { + if (isActive) { + bridge.shortcuts.client = null; + } + } +} + diff --git a/declarativeimports/abilities/applets/qmldir b/declarativeimports/abilities/applets/qmldir index f70feb63..f0c7c277 100644 --- a/declarativeimports/abilities/applets/qmldir +++ b/declarativeimports/abilities/applets/qmldir @@ -1,7 +1,8 @@ module org.kde.latte.abilities.applets Animations 0.1 Animations.qml Indexer 0.1 Indexer.qml Metrics 0.1 Metrics.qml ParabolicEffect 0.1 ParabolicEffect.qml +PositionShortcuts 0.1 PositionShortcuts.qml Requirements 0.1 Requirements.qml diff --git a/declarativeimports/abilities/bridge/PositionShortcuts.qml b/declarativeimports/abilities/bridge/PositionShortcuts.qml index 144899a8..ddc687b5 100644 --- a/declarativeimports/abilities/bridge/PositionShortcuts.qml +++ b/declarativeimports/abilities/bridge/PositionShortcuts.qml @@ -1,28 +1,47 @@ /* * Copyright 2020 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 . */ import QtQuick 2.0 Item { id: shortcutsBridge property int appletIndex: -1 property Item host: null property Item client: null + + readonly property bool isConnected: host && client + + onIsConnectedChanged: { + if (isConnected) { + host.sglActivateEntryAtIndex.connect(client.sglActivateEntryAtIndex); + host.sglNewInstanceForEntryAtIndex.connect(client.sglNewInstanceForEntryAtIndex); + } else { + host.sglActivateEntryAtIndex.disconnect(client.sglActivateEntryAtIndex); + host.sglNewInstanceForEntryAtIndex.disconnect(client.sglNewInstanceForEntryAtIndex); + } + } + + Component.onDestruction: { + if (isConnected) { + host.sglActivateEntryAtIndex.disconnect(client.sglActivateEntryAtIndex); + host.sglNewInstanceForEntryAtIndex.disconnect(client.sglNewInstanceForEntryAtIndex); + } + } } diff --git a/declarativeimports/abilities/bridge/PositionShortcuts.qml b/declarativeimports/abilities/definitions/PositionShortcuts.qml similarity index 76% copy from declarativeimports/abilities/bridge/PositionShortcuts.qml copy to declarativeimports/abilities/definitions/PositionShortcuts.qml index 144899a8..440881da 100644 --- a/declarativeimports/abilities/bridge/PositionShortcuts.qml +++ b/declarativeimports/abilities/definitions/PositionShortcuts.qml @@ -1,28 +1,27 @@ /* -* Copyright 2020 Michail Vourlakos +* Copyright 2020 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 . */ import QtQuick 2.0 Item { - id: shortcutsBridge - property int appletIndex: -1 + property bool showPositionShortcutBadges: false - property Item host: null - property Item client: null + signal sglActivateEntryAtIndex(int entryIndex); + signal sglNewInstanceForEntryAtIndex(int entryIndex); } diff --git a/declarativeimports/abilities/definitions/qmldir b/declarativeimports/abilities/definitions/qmldir index 387c0169..3a05bf10 100644 --- a/declarativeimports/abilities/definitions/qmldir +++ b/declarativeimports/abilities/definitions/qmldir @@ -1,8 +1,9 @@ module org.kde.latte.abilities.definitions Animations 0.1 Animations.qml AppletRequirements 0.1 AppletRequirements.qml Indexer 0.1 Indexer.qml Metrics 0.1 Metrics.qml ParabolicEffect 0.1 ParabolicEffect.qml +PositionShortcuts 0.1 PositionShortcuts.qml diff --git a/plasmoid/package/contents/ui/abilities/Indexer.qml b/plasmoid/package/contents/ui/abilities/Indexer.qml index de3a4e33..317b1978 100644 --- a/plasmoid/package/contents/ui/abilities/Indexer.qml +++ b/plasmoid/package/contents/ui/abilities/Indexer.qml @@ -1,182 +1,185 @@ /* * Copyright 2020 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 . */ import QtQuick 2.0 import org.kde.plasma.plasmoid 2.0 import org.kde.latte.abilities.applets 0.1 as AppletAbility AppletAbility.Indexer { id: _indexer property Item layout: null readonly property bool tailAppletIsSeparator: isActive ? bridge.indexer.tailAppletIsSeparator : false readonly property bool headAppletIsSeparator: isActive ? bridge.indexer.headAppletIsSeparator : false property int visibleItemsCount: 0 property int allItemsCount: 0 /*is needed to be set from consumer developer in order to avoid binding loops warnings*/ property int firstVisibleItemIndex: -1 property int lastVisibleItemIndex: -1 readonly property int maxIndex: 99999 Binding { target: _indexer property: "firstVisibleItemIndex" when: layout.children.length >= allItemsCount value: { var ind = maxIndex; for(var i=0; i=0 && hidden.indexOf(item.itemIndex)<0 && separators.indexOf(item.itemIndex)<0 && item.itemIndex < ind) { ind = item.itemIndex; } } return ind === maxIndex ? -1 : ind; } } Binding { target: _indexer property: "lastVisibleItemIndex" when: layout.children.length >= allItemsCount value: { var ind = -1; for(var i=0; i=0 && hidden.indexOf(item.itemIndex)<0 && separators.indexOf(item.itemIndex)<0 && item.itemIndex > ind) { //console.log("org.kde.latte SETTING UP ::: " + item.itemIndex + " / " + layout.children.length); ind = item.itemIndex; } } return ind; } } Binding { target: _indexer property: "visibleItemsCount" value: { var count = 0; for(var i=0; i=0 && hidden.indexOf(item.itemIndex)<0 && separators.indexOf(item.itemIndex)<0) { count = count + 1; } } return count; } } readonly property bool firstTailItemIsSeparator: { if (visibleItemsCount === layout.children.length) { return false; } for(var i=0; i=0) { return true; } } return false; } readonly property bool lastHeadItemIsSeparator: { if (visibleItemsCount === layout.children.length) { return false; } var len = layout.children.length; for(var i=len-1; i>lastVisibleItemIndex; --i) { if (separators.indexOf(i)>=0) { return true; } } return false; } separators: { var seps = []; for (var i=0; i=0) { seps.push(item.itemIndex); } } return seps; } hidden: { var hdns = []; for (var i=0; i=0) { hdns.push(item.itemIndex); } } return hdns; } function visibleIndex(taskIndex) { - if (taskIndex < firstVisibleItemIndex || taskIndex>lastVisibleItemIndex) { + if (taskIndexlastVisibleItemIndex + || hidden.indexOf(taskIndex) >= 0 + || separators.indexOf(taskIndex) >= 0) { return -1; } var vindex = -1; if (latteBridge) { vindex = latteBridge.indexer.host.visibleIndex(latteBridge.indexer.appletIndex); } for (var i=0; i=0 || separators.indexOf(item.itemIndex) >=0) { + if (hidden.indexOf(item.itemIndex)>=0 || separators.indexOf(item.itemIndex)>=0) { continue; } if (item.itemIndex * * 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 . */ -import QtQuick 2.0 +import QtQuick 2.7 -Item { - id: shortcutsBridge - property int appletIndex: -1 +import org.kde.plasma.plasmoid 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore - property Item host: null - property Item client: null +import org.kde.latte.abilities.applets 0.1 as AppletAbility + +AppletAbility.PositionShortcuts { + id: shortcuts } diff --git a/plasmoid/package/contents/ui/main.qml b/plasmoid/package/contents/ui/main.qml index 9e50a1ed..bec87a23 100644 --- a/plasmoid/package/contents/ui/main.qml +++ b/plasmoid/package/contents/ui/main.qml @@ -1,2084 +1,2042 @@ /* * Copyright 2016 Smith AR * 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 . */ import QtQuick 2.8 import QtQuick.Layouts 1.1 import QtGraphicalEffects 1.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.plasmoid 2.0 import org.kde.taskmanager 0.1 as TaskManager import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet import org.kde.activities 0.1 as Activities import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.components 1.0 as LatteComponents import org.kde.latte.abilities.applets 0.1 as AppletAbility import org.kde.latte.private.tasks 0.1 as LatteTasks import "abilities" as Ability import "previews" as Previews import "task" as Task import "taskslayout" as TasksLayout import "../code/tools.js" as TaskTools import "../code/activitiesTools.js" as ActivitiesTools import "../code/ColorizerTools.js" as ColorizerTools Item { id:root Layout.fillWidth: scrollingEnabled && !root.vertical Layout.fillHeight: scrollingEnabled && root.vertical Layout.minimumWidth: -1 Layout.minimumHeight: -1 Layout.preferredWidth: tasksWidth Layout.preferredHeight: tasksHeight Layout.maximumWidth: -1 Layout.maximumHeight: -1 LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft && !root.vertical LayoutMirroring.childrenInherit: true property bool plasma515: latteView ? latteView.plasma515 : LatteCore.Environment.plasmaDesktopVersion >= LatteCore.Environment.makeVersion(5,15,0) property bool plasma518: latteView ? latteView.plasma518 : LatteCore.Environment.plasmaDesktopVersion >= LatteCore.Environment.makeVersion(5,18,0) property bool editMode: latteView ? latteView.editMode : plasmoid.userConfiguring property bool inConfigureAppletsMode: latteView ? latteView.inConfigureAppletsMode : true property bool disableRestoreZoom: false //blocks restore animation in rightClick property bool disableAllWindowsFunctionality: root.showWindowsOnlyFromLaunchers && !indicators.isEnabled property bool dropNewLauncher: false property bool inActivityChange: false property bool inDraggingPhase: false property bool initializationStep: false //true property bool isHovered: false property bool showBarLine: plasmoid.configuration.showBarLine - property bool showTaskShortcutBadges: false - property int tasksBaseIndex: 0 property bool useThemePanel: plasmoid.configuration.useThemePanel property bool taskInAnimation: noTasksInAnimation > 0 ? true : false property bool transparentPanel: plasmoid.configuration.transparentPanel property bool vertical: plasmoid.formFactor === PlasmaCore.Types.Vertical ? true : false property int clearWidth property int clearHeight property int newDroppedPosition: -1 property int noInitCreatedBuffers: 0 property int noTasksInAnimation: 0 property int themePanelSize: plasmoid.configuration.panelSize property int location : { if (plasmoid.location === PlasmaCore.Types.LeftEdge || plasmoid.location === PlasmaCore.Types.RightEdge || plasmoid.location === PlasmaCore.Types.TopEdge) { return plasmoid.location; } return PlasmaCore.Types.BottomEdge; } property int tasksStarting: 0 ///Don't use Math.floor it adds one pixel in animations and creates glitches property int widthMargins: root.vertical ? metrics.totals.thicknessEdges : metrics.totals.lengthEdges property int heightMargins: !root.vertical ? metrics.totals.thicknessEdges : metrics.totals.lengthEdges property int internalWidthMargins: root.vertical ? metrics.totals.thicknessEdges : metrics.totals.lengthPaddings property int internalHeightMargins: !root.vertical ? metrics.totals.thicknessEdges : metrics.totals.lengthPaddings property real textColorBrightness: ColorizerTools.colorBrightness(themeTextColor) property color minimizedDotColor: { if (latteView) { return latteView.minimizedDotColor; } return textColorBrightness > 127.5 ? Qt.darker(themeTextColor, 1.7) : Qt.lighter(themeBackgroundColor, 7) } property color themeTextColor: theme.textColor property color themeBackgroundColor: theme.backgroundColor property color lightTextColor: textColorBrightness > 127.5 ? themeTextColor : themeBackgroundColor //a small badgers record (id,value) //in order to track badgers when there are changes //in launcher reference from libtaskmanager property variant badgers:[] property variant launchersOnActivities: [] //global plasmoid reference to the context menu property QtObject contextMenu: null property QtObject contextMenuComponent: Qt.createComponent("ContextMenu.qml"); property Item dragSource: null property Item parabolicManager: _parabolicManager property Item tasksExtendedManager: _tasksExtendedManager readonly property alias animations: _animations readonly property alias indexer: _indexer readonly property alias metrics: _metrics readonly property alias parabolic: _parabolic + readonly property alias shortcuts: _shortcuts readonly property alias containsDrag: mouseHandler.containsDrag readonly property bool dragAreaEnabled: latteView ? (root.dragSource !== null || latteView.dragInfo.isSeparator || latteView.dragInfo.isTask || !latteView.dragInfo.isPlasmoid) : true //! it is used to play the animation correct when the user removes a launcher property string launcherForRemoval: "" //BEGIN Latte Dock properties property bool badges3DStyle: latteView ? latteView.badges3DStyle : true property bool dockIsShownCompletely: latteView ? latteView.dockIsShownCompletely : true property bool enableShadows: latteView ? latteView.enableShadows > 0 : plasmoid.configuration.showShadows property bool forceHidePanel: false property bool disableLeftSpacer: false property bool disableRightSpacer: false property bool dockIsHidden: latteView ? latteView.dockIsHidden : false property bool groupTasksByDefault: plasmoid.configuration.groupTasksByDefault property bool highlightWindows: hoverAction === LatteTasks.Types.HighlightWindows || hoverAction === LatteTasks.Types.PreviewAndHighlightWindows property bool parabolicEffectEnabled: latteView ? latteView.parabolicEffectEnabled : parabolic.factor.zoom && !root.editMode property bool scrollingEnabled: plasmoid.configuration.scrollTasksEnabled property bool autoScrollTasksEnabled: scrollingEnabled && plasmoid.configuration.autoScrollTasksEnabled property bool manualScrollTasksEnabled: scrollingEnabled && manualScrollTasksType !== LatteTasks.Types.ManualScrollDisabled property int manualScrollTasksType: plasmoid.configuration.manualScrollTasksType property bool showInfoBadge: plasmoid.configuration.showInfoBadge property bool showProgressBadge: plasmoid.configuration.showInfoBadge property bool showAudioBadge: plasmoid.configuration.showAudioBadge property bool infoBadgeProminentColorEnabled: plasmoid.configuration.infoBadgeProminentColorEnabled property bool audioBadgeActionsEnabled: plasmoid.configuration.audioBadgeActionsEnabled property bool showOnlyCurrentScreen: plasmoid.configuration.showOnlyCurrentScreen property bool showOnlyCurrentDesktop: plasmoid.configuration.showOnlyCurrentDesktop property bool showOnlyCurrentActivity: plasmoid.configuration.showOnlyCurrentActivity property bool showPreviews: hoverAction === LatteTasks.Types.PreviewWindows || hoverAction === LatteTasks.Types.PreviewAndHighlightWindows property bool showWindowActions: plasmoid.configuration.showWindowActions property bool showWindowsOnlyFromLaunchers: plasmoid.configuration.showWindowsOnlyFromLaunchers property bool titleTooltips: latteView ? latteView.titleTooltips : false property alias windowPreviewIsShown: windowsPreviewDlg.visible property int launchersGroup: plasmoid.configuration.launchersGroup property int leftClickAction: plasmoid.configuration.leftClickAction property int middleClickAction: plasmoid.configuration.middleClickAction property int hoverAction: plasmoid.configuration.hoverAction property int modifier: plasmoid.configuration.modifier property int modifierClickAction: plasmoid.configuration.modifierClickAction property int modifierClick: plasmoid.configuration.modifierClick property int modifierQt:{ if (modifier === LatteTasks.Types.Shift) return Qt.ShiftModifier; else if (modifier === LatteTasks.Types.Ctrl) return Qt.ControlModifier; else if (modifier === LatteTasks.Types.Alt) return Qt.AltModifier; else if (modifier === LatteTasks.Types.Meta) return Qt.MetaModifier; else return -1; } property int taskScrollAction: plasmoid.configuration.taskScrollAction onTaskScrollActionChanged: { if (taskScrollAction > LatteTasks.Types.ScrollToggleMinimized) { //! migrating scroll action to LatteTasks.Types.ScrollAction plasmoid.configuration.taskScrollAction = plasmoid.configuration.taskScrollAction-LatteTasks.Types.ScrollToggleMinimized; } } //! Real properties are need in order for parabolic effect to be 1px precise perfect. //! This way moving from Tasks to Applets and vice versa is pretty stable when hovering with parabolic effect. property real tasksHeight: mouseHandler.height property real tasksWidth: mouseHandler.width //updated from Binding property int alignment readonly property real currentPanelOpacity: latteView ? latteView.currentPanelTransparency / 100 : 1 property int appShadowSize: latteView ? latteView.appShadowSize : Math.ceil(0.12*metrics.iconSize) property string appShadowColor: latteView ? latteView.appShadowColor : "#ff080808" property string appShadowColorSolid: latteView ? latteView.appShadowColorSolid : "#ff080808" property alias tasksCount: tasksModel.count readonly property rect screenGeometry: latteView ? latteView.screenGeometry : plasmoid.screenGeometry readonly property bool viewLayoutIsCurrent: latteView && viewLayout && latteView.layoutsManager && viewLayout.name === latteView.layoutsManager.currentLayoutName readonly property string viewLayoutName: viewLayout ? viewLayout.name : "" readonly property QtObject viewLayout : latteView && latteView.viewLayout ? latteView.viewLayout : null property var badgesForActivate: latteView ? latteView.badgesForActivate : [] property Item latteView: null readonly property Item indicators: latteView ? latteView.indicatorsManager : indicatorsStandaloneLoader.item //END Latte Dock Panel properties //BEGIN Latte Dock Communicator property QtObject latteBridge: null readonly property bool enforceLattePalette: latteBridge && latteBridge.applyPalette && latteBridge.palette readonly property bool latteInEditMode: latteBridge && latteBridge.inEditMode //END Latte Dock Communicator Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation Plasmoid.backgroundHints: PlasmaCore.Types.NoBackground signal draggingFinished(); signal hiddenTasksUpdated(); signal launchersUpdatedFor(string launcher); signal presentWindows(variant winIds); signal requestLayout; signal signalPreviewsShown(); //signal signalDraggingState(bool value); signal showPreviewForTasks(QtObject group); //trigger updating scaling of neighbour delegates of zoomed delegate signal updateScale(int delegateIndex, real newScale, real step) signal mimicEnterForParabolic(); signal publishTasksGeometries(); signal windowsHovered(variant winIds, bool hovered) //onAnimationsChanged: console.log(animations); /* Rectangle{ anchors.fill: parent border.width: 1 border.color: "red" color: "white" } */ onLatteViewChanged: { if (latteView) { plasmoid.action("configure").visible = false; plasmoid.configuration.isInLatteDock = true; if (root.launchersGroup === LatteCore.Types.LayoutLaunchers || root.launchersGroup === LatteCore.Types.GlobalLaunchers) { tasksModel.updateLaunchersList(); } } else { plasmoid.configuration.isInLatteDock = false; } } onLaunchersGroupChanged:{ if(latteView) { tasksModel.updateLaunchersList(); } } Connections { target: plasmoid onLocationChanged: { iconGeometryTimer.start(); } } Connections { target: plasmoid.configuration // onLaunchersChanged: tasksModel.launcherList = plasmoid.configuration.launchers onGroupingAppIdBlacklistChanged: tasksModel.groupingAppIdBlacklist = plasmoid.configuration.groupingAppIdBlacklist; onGroupingLauncherUrlBlacklistChanged: tasksModel.groupingLauncherUrlBlacklist = plasmoid.configuration.groupingLauncherUrlBlacklist; } Connections{ target: latteView onDockIsHiddenChanged:{ if (latteView.dockIsHidden) { windowsPreviewDlg.hide("3.3"); } } } Connections{ target: latteView && latteView.layoutsManager ? latteView.layoutsManager : null onCurrentLayoutNameChanged: root.publishTasksGeometries(); } Binding { target: plasmoid property: "status" value: (tasksModel.anyTaskDemandsAttentionInValidTime || root.dragSource ? PlasmaCore.Types.NeedsAttentionStatus : PlasmaCore.Types.PassiveStatus); } ///// PlasmaCore.ColorScope{ id: colorScopePalette } //! Item { id: graphicsSystem readonly property bool isAccelerated: (GraphicsInfo.api !== GraphicsInfo.Software) && (GraphicsInfo.api !== GraphicsInfo.Unknown) } Loader { id: indicatorsStandaloneLoader active: !latteView && !plasmoid.configuration.isInLatteDock source: "indicators/Manager.qml" } Binding { target: root property: "alignment" value: { if (latteView) { if (latteView.panelAlignment === -1) { return; } if (latteView.panelAlignment === LatteCore.Types.Justify) { if (latteView.latteAppletPos>=0 && latteView.latteAppletPos<100) { return plasmoid.formFactor === PlasmaCore.Types.Horizontal ? LatteCore.Types.Left : LatteCore.Types.Top; } else if (latteView.latteAppletPos>=100 && latteView.latteAppletPos<200) { return LatteCore.Types.Center; } else if (latteView.latteAppletPos>=200) { return plasmoid.formFactor === PlasmaCore.Types.Horizontal ? LatteCore.Types.Right : LatteCore.Types.Bottom; } return LatteCore.Types.Center; } return latteView.panelAlignment; } return LatteCore.Types.Center; } } ///// function launchersDropped(urls){ mouseHandler.urlsDropped(urls); } ///UPDATE function launcherExists(url) { return (ActivitiesTools.getIndex(url, tasksModel.launcherList)>=0); } function taskExists(url) { var tasks = icList.contentItem.children; for(var i=0; i -1) { launch.push(explicitLauncher); } } } return launch; } function currentListViewLauncherList() { var launch = []; var tasks = icList.contentItem.children; for(var i=0; i