diff --git a/containment/package/contents/ui/editmode/HeaderSettings.qml b/containment/package/contents/ui/editmode/HeaderSettings.qml index 79481fbd..f3e2df26 100644 --- a/containment/package/contents/ui/editmode/HeaderSettings.qml +++ b/containment/package/contents/ui/editmode/HeaderSettings.qml @@ -1,121 +1,123 @@ /* * 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.7 import QtQuick.Layouts 1.1 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.latte 0.2 as Latte import "controls" as SettingsControls Item { id: headerSettings width: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? parent.width : parent.height height: thickness readonly property bool containsMouse: rearrangeBtn.containsMouse readonly property int thickness: rearrangeBtn.implicitHeight readonly property string tooltip: rearrangeBtn.tooltip rotation: { if (plasmoid.formFactor === PlasmaCore.Types.Horizontal) { return 0; } if (plasmoid.location === PlasmaCore.Types.LeftEdge) { return 90; } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { return -90; } } x: { if (plasmoid.formFactor === PlasmaCore.Types.Horizontal) { return 0; } if (plasmoid.location === PlasmaCore.Types.LeftEdge) { return visibilityManager.thicknessNormalOriginalValue + ruler.thickness + spacing * 2 - width/2 + height/2; } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { return spacing - width/2 + height/2; } } y: { if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { return width/2 - height/2; } if (plasmoid.location === PlasmaCore.Types.BottomEdge) { return spacing; } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { return parent.height - rearrangeBtn.height - spacing; } } SettingsControls.Button{ id: rearrangeBtn anchors.horizontalCenter: parent.horizontalCenter anchors.top: parent.top text: i18n("Rearrange and configure your widgets") tooltip: i18n("Feel free to move around your widgets and configure them from their tooltips") reverseIcon: plasmoid.location === PlasmaCore.Types.RightEdge textColor: containsMouse ? colorizerManager.buttonTextColor : settingsRoot.textColor backgroundColor: containsMouse ? hoveredBackground : normalBackground// "transparent" checkedTextColor: colorizerManager.buttonTextColor checkedBackgroundColor: colorizerManager.buttonFocusColor checked: root.inConfigureAppletsMode + hoveredExternal: rearrangeTooltipBtn.hovered property color normalBackground: Qt.rgba(colorizerManager.buttonHoverColor.r, colorizerManager.buttonHoverColor.g, colorizerManager.buttonHoverColor.b, 0.3) property color hoveredBackground: Qt.rgba(colorizerManager.buttonHoverColor.r, colorizerManager.buttonHoverColor.g, colorizerManager.buttonHoverColor.b, 0.7) onPressed: { if (Latte.WindowSystem.compositingActive) { plasmoid.configuration.inConfigureAppletsMode = !plasmoid.configuration.inConfigureAppletsMode; } } } PlasmaComponents.Button { + id: rearrangeTooltipBtn anchors.fill: rearrangeBtn opacity: 0 tooltip: headerSettings.tooltip onPressedChanged: { if (Latte.WindowSystem.compositingActive && pressed) { plasmoid.configuration.inConfigureAppletsMode = !plasmoid.configuration.inConfigureAppletsMode; } } } } diff --git a/containment/package/contents/ui/editmode/controls/Button.qml b/containment/package/contents/ui/editmode/controls/Button.qml index 9896fd9d..e4d7e6d6 100644 --- a/containment/package/contents/ui/editmode/controls/Button.qml +++ b/containment/package/contents/ui/editmode/controls/Button.qml @@ -1,101 +1,102 @@ /* * 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.7 import QtQuick.Layouts 1.1 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.latte 0.2 as Latte Item{ id: button width: visibleButton.width height: visibleButton.height signal pressed(); property bool checked: false + property bool hoveredExternal: false property bool reverseIcon: false property string text: "Default Text" property string tooltip: "" - readonly property bool containsMouse: buttonMouseArea.containsMouse + readonly property bool containsMouse: buttonMouseArea.containsMouse || hoveredExternal readonly property int implicitHeight: visibleButton.height readonly property color appliedTextColor: checked ? checkedTextColor : textColor readonly property color appliedBackgroundColor: checked ? checkedBackgroundColor : backgroundColor property color textColor: "white" property color backgroundColor: "black" property color checkedTextColor: "black" property color checkedBackgroundColor: "white" Rectangle { id: visibleButton width: buttonRow.width + 4 * margin height: buttonRow.height + 2 * margin radius: 2 color: appliedBackgroundColor // border.width: 1 // border.color: checked ? appliedBackgroundColor : appliedTextColor readonly property int margin: units.smallSpacing RowLayout{ id: buttonRow anchors.centerIn: parent spacing: units.smallSpacing layoutDirection: reverseIcon ? Qt.RightToLeft : Qt.LeftToRight RearrangeIcon{ width: height height: textLbl.implicitHeight iconColor: button.appliedTextColor } PlasmaComponents.Label{ id: textLbl text: button.text color: button.appliedTextColor } } /* Rectangle { anchors.topMargin: 1 anchors.top: buttonRow.bottom anchors.horizontalCenter: buttonRow.horizontalCenter width: visibleButton.width height: 1 color: button.appliedTextColor visible: buttonMouseArea.containsMouse }*/ } MouseArea{ id: buttonMouseArea anchors.fill: visibleButton hoverEnabled: true onClicked: button.pressed(); } } diff --git a/containment/package/contents/ui/main.qml b/containment/package/contents/ui/main.qml index 713fdf2a..33c26d7f 100644 --- a/containment/package/contents/ui/main.qml +++ b/containment/package/contents/ui/main.qml @@ -1,1928 +1,1927 @@ /* * 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.1 import QtQuick.Layouts 1.1 import QtQuick.Window 2.2 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.kquickcontrolsaddons 2.0 import org.kde.draganddrop 2.0 as DragDrop import org.kde.plasma.plasmoid 2.0 import org.kde.latte 0.2 as Latte import "applet" as Applet import "colorizer" as Colorizer import "editmode" as EditMode import "indicators" as Indicators import "layouts" as Layouts import "../code/LayoutManager.js" as LayoutManager DragDrop.DropArea { id: root objectName: "containmentViewLayout" LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft && !root.isVertical LayoutMirroring.childrenInherit: true //// BEGIN SIGNALS signal clearZoomSignal(); signal destroyInternalViewSplitters(); signal emptyAreasWheel(QtObject wheel); signal separatorsUpdated(); signal signalActivateEntryAtIndex(int entryIndex); signal signalNewInstanceForEntryAtIndex(int entryIndex); signal updateEffectsArea(); signal updateIndexes(); signal updateScale(int delegateIndex, real newScale, real step); signal broadcastedToApplet(string pluginName, string action, variant value); //// END SIGNALS ////BEGIN properties property bool debugMode: Qt.application.arguments.indexOf("--graphics")>=0 property bool debugModeSpacers: Qt.application.arguments.indexOf("--spacers")>=0 property bool debugModeTimers: Qt.application.arguments.indexOf("--timers")>=0 property bool debugModeWindow: Qt.application.arguments.indexOf("--with-window")>=0 property bool debugModeOverloadedIcons: Qt.application.arguments.indexOf("--overloaded-icons")>=0 property bool globalDirectRender: false //it is used as a globalDirectRender for all elements in the dock property int directRenderAnimationTime: 0 property bool addLaunchersMessage: false property bool addLaunchersInTaskManager: plasmoid.configuration.addLaunchersInTaskManager // when there are only plasma style task managers OR any applets that fill width or height // the automatic icon size algorithm should better be disabled property bool autoDecreaseIconSize: !containsOnlyPlasmaTasks && layoutsContainer.fillApplets<=0 property bool backgroundOnlyOnMaximized: plasmoid.configuration.backgroundOnlyOnMaximized property bool behaveAsPlasmaPanel: { if (!latteView || !latteView.visibility) { return false; } return (visibilityManager.panelIsBiggerFromIconSize && (maxZoomFactor === 1.0) && (latteView.visibility.mode === Latte.Types.AlwaysVisible || latteView.visibility.mode === Latte.Types.WindowsGoBelow) && (plasmoid.configuration.panelPosition === Latte.Types.Justify) && !root.editMode); } property int viewType: { if ((plasmoid.configuration.panelPosition === Latte.Types.Justify) && (plasmoid.configuration.useThemePanel) && (plasmoid.configuration.panelSize === 100) && (maxZoomFactor === 1.0)) { return Latte.Types.PanelView; } return Latte.Types.DockView; } property bool blurEnabled: plasmoid.configuration.blurEnabled && (!forceTransparentPanel || forcePanelForBusyBackground) property bool confirmedDragEntered: false property bool containsOnlyPlasmaTasks: false //this is flag to indicate when from tasks only a plasma based one is found property bool dockContainsMouse: latteView && latteView.visibility ? latteView.visibility.containsMouse : false property bool disablePanelShadowMaximized: plasmoid.configuration.disablePanelShadowForMaximized && Latte.WindowSystem.compositingActive property bool drawShadowsExternal: panelShadowsActive && behaveAsPlasmaPanel && !visibilityManager.inTempHiding property bool editMode: editModeVisual.inEditMode property bool windowIsTouching: latteView && latteView.windowsTracker && (latteView.windowsTracker.activeWindowTouching || hasExpandedApplet) property bool forceSolidPanel: (latteView && latteView.visibility && Latte.WindowSystem.compositingActive && !inConfigureAppletsMode && userShowPanelBackground && ( (plasmoid.configuration.solidBackgroundForMaximized && !(hasExpandedApplet && !plasmaBackgroundForPopups) && latteView.windowsTracker.existsWindowTouching) || (hasExpandedApplet && plasmaBackgroundForPopups) )) || !Latte.WindowSystem.compositingActive property bool forceTransparentPanel: root.backgroundOnlyOnMaximized && latteView && latteView.visibility && Latte.WindowSystem.compositingActive && !inConfigureAppletsMode && !forceSolidPanel && !(windowColors === Latte.Types.TouchingWindowColors && latteView.windowsTracker.activeWindowTouching) && !(windowColors === Latte.Types.ActiveWindowColors && latteView.windowsTracker.existsWindowActive) property bool forcePanelForBusyBackground: userShowPanelBackground && root.forceTransparentPanel && colorizerManager.mustBeShown && colorizerManager.backgroundIsBusy property int themeColors: plasmoid.configuration.themeColors property int windowColors: plasmoid.configuration.windowColors property bool colorizerEnabled: themeColors !== Latte.Types.PlasmaThemeColors || windowColors !== Latte.Types.NoneWindowColors property bool plasmaBackgroundForPopups: plasmoid.configuration.plasmaBackgroundForPopups readonly property bool hasExpandedApplet: plasmoid.applets.some(function (item) { return (item.status >= PlasmaCore.Types.NeedsAttentionStatus && item.status !== PlasmaCore.Types.HiddenStatus && item.pluginName !== root.plasmoidName && item.pluginName !== "org.kde.plasma.appmenu" && item.pluginName !== "org.kde.windowappmenu" && item.pluginName !== "org.kde.activeWindowControl"); }) readonly property bool hasUserSpecifiedBackground: (latteView && latteView.managedLayout && latteView.managedLayout.background.startsWith("/")) ? true : false readonly property bool inConfigureAppletsMode: root.editMode && (plasmoid.configuration.inConfigureAppletsMode || !Latte.WindowSystem.compositingActive) readonly property bool parabolicEffectEnabled: zoomFactor>1 && !inConfigureAppletsMode property bool dockIsShownCompletely: !(dockIsHidden || inSlidingIn || inSlidingOut) && !root.editMode property bool dragActiveWindowEnabled: plasmoid.configuration.dragActiveWindowEnabled property bool immutable: plasmoid.immutable property bool inFullJustify: (plasmoid.configuration.panelPosition === Latte.Types.Justify) && (plasmoid.configuration.maxLength===100) property bool inSlidingIn: visibilityManager ? visibilityManager.inSlidingIn : false property bool inSlidingOut: visibilityManager ? visibilityManager.inSlidingOut : false property bool inStartup: true property bool isHalfShown: false //is used to disable the zoom hovering effect at sliding in-out the dock property bool isHorizontal: plasmoid.formFactor === PlasmaCore.Types.Horizontal property bool isReady: !(dockIsHidden || inSlidingIn || inSlidingOut) property bool isVertical: !isHorizontal property bool isHovered: latteApplet ? ((latteAppletHoveredIndex !== -1) || (layoutsContainer.hoveredIndex !== -1)) //|| wholeArea.containsMouse : (layoutsContainer.hoveredIndex !== -1) //|| wholeArea.containsMouse property bool mouseWheelActions: plasmoid.configuration.mouseWheelActions - property bool normalState : false property bool onlyAddingStarup: true //is used for the initialization phase in startup where there aren't removals, this variable provides a way to grow icon size property bool shrinkThickMargins: plasmoid.configuration.shrinkThickMargins property bool showLatteShortcutBadges: false property bool showAppletShortcutBadges: false property bool showMetaBadge: false property int applicationLauncherId: -1 //FIXME: possibly this is going to be the default behavior, this user choice //has been dropped from the Dock Configuration Window //property bool smallAutomaticIconJumps: plasmoid.configuration.smallAutomaticIconJumps property bool smallAutomaticIconJumps: true property bool userShowPanelBackground: Latte.WindowSystem.compositingActive ? plasmoid.configuration.useThemePanel : true property bool useThemePanel: noApplets === 0 || !Latte.WindowSystem.compositingActive ? true : (plasmoid.configuration.useThemePanel || plasmoid.configuration.solidBackgroundForMaximized) property alias hoveredIndex: layoutsContainer.hoveredIndex property alias directRenderDelayerIsRunning: directRenderDelayerForEnteringTimer.running property int actionsBlockHiding: 0 //actions that block hiding property int animationsNeedBothAxis:0 //animations need space in both axes, e.g zooming a task property int animationsNeedLength: 0 // animations need length, e.g. adding a task property int animationsNeedThickness: 0 // animations need thickness, e.g. bouncing animation property int animationTime: durationTime*2.8*units.longDuration property int automaticIconSizeBasedSize: -1 //it is not set, this is the defautl //what is the highest icon size based on what icon size is used, screen calculated or user specified property int maxIconSize: proportionIconSize!==-1 ? proportionIconSize : plasmoid.configuration.iconSize property int iconSize: automaticIconSizeBasedSize > 0 && autoDecreaseIconSize ? Math.min(automaticIconSizeBasedSize, root.maxIconSize) : root.maxIconSize property int proportionIconSize: { //icon size based on screen height if ((plasmoid.configuration.proportionIconSize===-1) || !latteView) return -1; return Math.max(16,Math.round(latteView.screenGeometry.height * plasmoid.configuration.proportionIconSize/100/8)*8); } property int iconStep: 8 property int latteAppletPos: -1 property int maxLength: { if (root.isHorizontal) { return behaveAsPlasmaPanel ? width : width * (plasmoid.configuration.maxLength/100) } else { return behaveAsPlasmaPanel ? height : height * (plasmoid.configuration.maxLength/100) } } 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 scrollAction: plasmoid.configuration.scrollAction property bool panelOutline: plasmoid.configuration.panelOutline property int panelEdgeSpacing: Math.max(panelBoxBackground.lengthMargins, 1.5*appShadowSize) property int panelTransparency: plasmoid.configuration.panelTransparency //user set property int currentPanelTransparency: 0 //application override readonly property real currentPanelOpacity: currentPanelTransparency/100 property bool panelShadowsActive: { if (!userShowPanelBackground) { return false; } if (inConfigureAppletsMode) { return plasmoid.configuration.panelShadows; } //! Draw shadows for isBusy state only when current panelTransparency is greater than 40% if (plasmoid.configuration.panelShadows && root.forcePanelForBusyBackground && currentPanelTransparency>40) { return true; } if (( (plasmoid.configuration.panelShadows && !root.backgroundOnlyOnMaximized) || (plasmoid.configuration.panelShadows && root.backgroundOnlyOnMaximized && !root.forceTransparentPanel)) && !(disablePanelShadowMaximized && latteView && latteView.windowsTracker && latteView.windowsTracker.activeWindowMaximized)) { return true; } if (hasExpandedApplet && plasmaBackgroundForPopups) { return true; } return false; } property int appShadowOpacity: (plasmoid.configuration.shadowOpacity/100) * 255 property int appShadowSize: enableShadows ? (0.5*root.iconSize) * (plasmoid.configuration.shadowSize/100) : 0 property int appShadowSizeOriginal: enableShadows ? (0.5*maxIconSize) * (plasmoid.configuration.shadowSize/100) : 0 property string appChosenShadowColor: { if (plasmoid.configuration.shadowColorType === Latte.Types.ThemeColorShadow) { var strC = String(theme.textColor); return strC.indexOf("#") === 0 ? strC.substr(1) : strC; } else if (plasmoid.configuration.shadowColorType === Latte.Types.UserColorShadow) { return plasmoid.configuration.shadowColor; } // default shadow color return "080808"; } property string appShadowColor: "#" + decimalToHex(appShadowOpacity) + appChosenShadowColor property string appShadowColorSolid: "#" + appChosenShadowColor property int totalPanelEdgeSpacing: 0 //this is set by PanelBox //FIXME: this is not needed any more probably property int previousAllTasks: -1 //is used to forbid updateAutomaticIconSize when hovering property int offset: { if (behaveAsPlasmaPanel) { return 0; } if (root.isHorizontal) { return width * (plasmoid.configuration.offset/100); } else { height * (plasmoid.configuration.offset/100) } } //center the layout correctly when the user uses an offset property int offsetFixed: (offset===0 || panelAlignment === Latte.Types.Center || plasmoid.configuration.panelPosition === Latte.Types.Justify)? offset : offset+panelMarginLength/2+totalPanelEdgeSpacing/2 property int realPanelSize: 0 property int realPanelLength: 0 property int realPanelThickness: 0 //this is set by the PanelBox property int panelThickMarginBase: 0 property int panelThickMarginHigh: 0 property int panelMarginLength: 0 property int panelShadow: 0 //shadowsSize property int editShadow: { if (!Latte.WindowSystem.compositingActive) { return 0; } else if (latteView && latteView.screenGeometry) { return latteView.screenGeometry.height/90; } else { return 7; } } property int themePanelThickness: { var panelBase = root.panelThickMarginHigh; var margin = shrinkThickMargins ? 0 : thickMargins; var maxPanelSize = (iconSize + margin) - panelBase; var percentage = Latte.WindowSystem.compositingActive ? plasmoid.configuration.panelSize/100 : 1; return Math.max(panelBase, panelBase + percentage*maxPanelSize); } property int lengthIntMargin: lengthIntMarginFactor * root.iconSize property int lengthExtMargin: lengthExtMarginFactor * root.iconSize property real lengthIntMarginFactor: indicators.isEnabled ? indicators.padding : 0 property real lengthExtMarginFactor: plasmoid.configuration.lengthExtMargin / 100 property real thickMarginFactor: { if (shrinkThickMargins) { return indicators.info.minThicknessPadding; } //0.075 old statesLineSize and 0.06 old default thickMargin return Math.max(indicators.info.minThicknessPadding, plasmoid.configuration.thickMargin / 100) } property int thickMargin: thickMarginFactor * root.iconSize //! thickness margins are always two and equal in order for items //! to be always correctly centered property int thickMargins: 2 * thickMargin //it is used in order to not break the calculations for the thickness placement //especially in automatic icon sizes calculations property int maxThickMargin: thickMarginFactor * maxIconSize property int lengthMargin: lengthIntMargin + lengthExtMargin property int lengthMargins: 2 * lengthMargin property int widthMargins: root.isVertical ? thickMargins : lengthMargins property int heightMargins: root.isHorizontal ? thickMargins : lengthMargins property int internalWidthMargins: root.isVertical ? thickMargins : 2 * lengthIntMargin property int internalHeightMargins: root.isHorizontal ? thickMargins : 2 * lengthIntMargin ///FIXME: I can't remember why this is needed, maybe for the anchorings!!! In order for the Double Layout to not mess the anchorings... //property int layoutsContainer.mainLayoutPosition: !plasmoid.immutable ? Latte.Types.Center : (root.isVertical ? Latte.Types.Top : Latte.Types.Left) //property int panelAlignment: plasmoid.configuration.panelPosition !== Latte.Types.Justify ? plasmoid.configuration.panelPosition : layoutsContainer.mainLayoutPosition property int panelAlignment: !root.inConfigureAppletsMode ? plasmoid.configuration.panelPosition : ( plasmoid.configuration.panelPosition === Latte.Types.Justify ? Latte.Types.Center : plasmoid.configuration.panelPosition ) property int panelUserSetAlignment: plasmoid.configuration.panelPosition property real zoomFactor: Latte.WindowSystem.compositingActive && root.animationsEnabled ? ( 1 + (plasmoid.configuration.zoomLevel / 20) ) : 1 readonly property string plasmoidName: "org.kde.latte.plasmoid" property var badgesForActivate: { if (!shortcutsEngine) { return ['1','2','3','4','5','6','7','8','9','0', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.']; } return shortcutsEngine.badgesForActivate; } property var iconsArray: [16, 22, 32, 48, 64, 96, 128, 256] property Item dragOverlay property Item toolBox property Item latteAppletContainer property Item latteApplet readonly property Item indicatorsManager: indicators readonly property Item parabolicManager: _parabolicManager property QtObject latteView: null property QtObject shortcutsEngine: null property QtObject themeExtended: null property QtObject universalSettings: null property QtObject universalLayoutManager: null property QtObject managedLayout: latteView && latteView.managedLayout ? latteView.managedLayout : null // TO BE DELETED, if not needed: property int counter:0; ///BEGIN properties provided to Latte Plasmoid //shadows for applets, it should be removed as the appleitems don't need it any more property bool enableShadows: plasmoid.configuration.shadows || (root.forceTransparentPanel && plasmoid.configuration.shadows>0) property bool dockIsHidden: latteView ? latteView.visibility.isHidden : true property bool groupTasksByDefault: plasmoid.configuration.groupTasksByDefault property bool showInfoBadge: plasmoid.configuration.showInfoBadge property bool showProgressBadge: plasmoid.configuration.showProgressBadge property bool showAudioBadge: plasmoid.configuration.showAudioBadge property bool audioBadgeActionsEnabled: plasmoid.configuration.audioBadgeActionsEnabled property bool showWindowActions: plasmoid.configuration.showWindowActions property bool showWindowsOnlyFromLaunchers: plasmoid.configuration.showWindowsOnlyFromLaunchers property bool showOnlyCurrentScreen: plasmoid.configuration.showOnlyCurrentScreen property bool showOnlyCurrentDesktop: plasmoid.configuration.showOnlyCurrentDesktop property bool showOnlyCurrentActivity: plasmoid.configuration.showOnlyCurrentActivity property bool titleTooltips: plasmoid.configuration.titleTooltips property bool unifiedGlobalShortcuts: plasmoid.configuration.unifiedGlobalShortcuts readonly property bool hasInternalSeparator: latteApplet ? latteApplet.hasInternalSeparator : false property int animationStep: { if (!universalSettings || universalSettings.mouseSensitivity === Latte.Types.HighSensitivity) { return 1; } else if (universalSettings.mouseSensitivity === Latte.Types.MediumSensitivity) { return Math.max(3, root.iconSize / 18); } else if (universalSettings.mouseSensitivity === Latte.Types.LowSensitivity) { return Math.max(5, root.iconSize / 10); } } property int latteAppletHoveredIndex: latteApplet ? latteApplet.hoveredIndex : -1 property int launchersGroup: plasmoid.configuration.launchersGroup property int tasksCount: latteApplet ? latteApplet.tasksCount : 0 //! Animations property bool animationsEnabled: plasmoid.configuration.animationsEnabled && Latte.WindowSystem.compositingActive property bool animationLauncherBouncing: animationsEnabled && latteApplet && plasmoid.configuration.animationLauncherBouncing property bool animationWindowInAttention: animationsEnabled && latteApplet && plasmoid.configuration.animationWindowInAttention property bool animationNewWindowSliding: animationsEnabled && latteApplet && plasmoid.configuration.animationNewWindowSliding property bool animationWindowAddedInGroup: animationsEnabled && latteApplet && plasmoid.configuration.animationWindowAddedInGroup property bool animationWindowRemovedFromGroup: animationsEnabled && latteApplet && plasmoid.configuration.animationWindowRemovedFromGroup property real appliedDurationTime: animationsEnabled ? durationTime : 2 property real durationTime: { if (!animationsEnabled) { return 0; } /*if ((latteView && latteView.effects && latteView.effects.animationsBlocked) || !animationsEnabled) { return 0; }*/ if (plasmoid.configuration.durationTime === 0 || plasmoid.configuration.durationTime === 2 ) return plasmoid.configuration.durationTime; if (plasmoid.configuration.durationTime === 1) return 1.65; else if (plasmoid.configuration.durationTime === 3) return 2.35; return 2; } property real animationsZoomFactor : { if (!animationsEnabled) { return 1; } if (latteApplet && (animationLauncherBouncing || animationWindowInAttention || animationWindowAddedInGroup)) { return 1.65; } return 1; } property real maxZoomFactor: Math.max(zoomFactor, animationsZoomFactor) property rect screenGeometry: latteView ? latteView.screenGeometry : plasmoid.screenGeometry readonly property color minimizedDotColor: colorizerManager.minimizedDotColor ///END properties from latteApplet Plasmoid.backgroundHints: PlasmaCore.Types.NoBackground //// BEGIN properties in functions property int noApplets: { var count1 = 0; var count2 = 0; count1 = layoutsContainer.mainLayout.children.length; var tempLength = layoutsContainer.mainLayout.children.length; for (var i=tempLength-1; i>=0; --i) { var applet = layoutsContainer.mainLayout.children[i]; if (applet && (applet === dndSpacer || applet === lastSpacer || applet.isInternalViewSplitter)) count1--; } count2 = layoutsContainer.endLayout.children.length; tempLength = layoutsContainer.endLayout.children.length; for (var i=tempLength-1; i>=0; --i) { var applet = layoutsContainer.endLayout.children[i]; if (applet && (applet === dndSpacer || applet === lastSpacer || applet.isInternalViewSplitter)) count2--; } return (count1 + count2); } ///The index of user's current icon size property int currentIconIndex:{ for(var i=iconsArray.length-1; i>=0; --i){ if(iconsArray[i] === iconSize){ return i; } } return 3; } //// END properties in functions ////////////////END properties //// BEGIN OF Behaviors Behavior on thickMargin { NumberAnimation { duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } Behavior on lengthIntMargin { NumberAnimation { duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } Behavior on lengthExtMargin { NumberAnimation { duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } Behavior on iconSize { enabled: !(root.editMode && root.behaveAsPlasmaPanel) NumberAnimation { duration: 0.8 * root.animationTime onRunningChanged: { if (!running) { delayUpdateMaskArea.start(); } } } } Behavior on offset { enabled: editModeVisual.editAnimationInFullThickness NumberAnimation { id: offsetAnimation duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } //// END OF Behaviors //////////////START OF CONNECTIONS onContainsOnlyPlasmaTasksChanged: updateAutomaticIconSize(); onEditModeChanged: { if (editMode) { visibilityManager.updateMaskArea(); updateAutomaticIconSize(); clearZoom(); } else { updateAutomaticIconSize(); layoutsContainer.updateSizeForAppletsInFill(); } //! This is used in case the dndspacer has been left behind //! e.g. the user drops a folder and a context menu is appearing //! but the user decides to not make a choice for the applet type if (dndSpacer.parent !== root) { dndSpacer.parent = root; } } onInConfigureAppletsModeChanged: { if (inConfigureAppletsMode && panelUserSetAlignment===Latte.Types.Justify) { joinLayoutsToMainLayout(); } else if (!inConfigureAppletsMode) { splitMainLayoutToLayouts(); } updateIndexes(); } //! It is used only when the user chooses different alignment types //! and not during startup onPanelUserSetAlignmentChanged: { if (!root.editMode) { return; } if (!inConfigureAppletsMode){ if (panelUserSetAlignment===Latte.Types.Justify) { addInternalViewSplitters(); splitMainLayoutToLayouts(); } else { joinLayoutsToMainLayout(); root.destroyInternalViewSplitters(); } } else { if (panelUserSetAlignment===Latte.Types.Justify) { addInternalViewSplitters(); } else { root.destroyInternalViewSplitters(); } } LayoutManager.save(); updateIndexes(); } onLatteViewChanged: { if (latteView) { latteView.onXChanged.connect(visibilityManager.updateMaskArea); latteView.onYChanged.connect(visibilityManager.updateMaskArea); latteView.onWidthChanged.connect(visibilityManager.updateMaskArea); latteView.onHeightChanged.connect(visibilityManager.updateMaskArea); latteView.positioner.hideDockDuringLocationChangeStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterLocationChangeFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringScreenChangeStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterScreenChangeFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringMovingToLayoutStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterMovingToLayoutFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.visibility.onContainsMouseChanged.connect(visibilityManager.slotContainsMouseChanged); latteView.visibility.onMustBeHide.connect(visibilityManager.slotMustBeHide); latteView.visibility.onMustBeShown.connect(visibilityManager.slotMustBeShown); updateContainsOnlyPlasmaTasks(); } } onDockContainsMouseChanged: { if (!dockContainsMouse) { initializeHoveredIndexes(); } } onDragEnter: { if (plasmoid.immutable || dockIsHidden || visibilityManager.inSlidingIn || visibilityManager.inSlidingOut) { event.ignore(); return; } if (event.mimeData.formats.indexOf("application/x-orgkdeplasmataskmanager_taskbuttonitem") >= 0) { return; } if (latteApplet) { if (latteApplet.launchersDrop(event)) { root.addLaunchersMessage = true; if (root.addLaunchersInTaskManager) { return; } } else { var isSeparator = ( latteView.mimeContainsPlasmoid(event.mimeData, "audoban.applet.separator") || latteView.mimeContainsPlasmoid(event.mimeData, "org.kde.latte.separator") ); if (isSeparator && root.latteAppletContainer.containsPos(event)) { confirmedDragEntered = true dndSpacer.opacity = 0; dndSpacer.parent = root; return; } } } if (!confirmedDragEntered) { confirmedDragEntered = true; slotAnimationsNeedLength(1); } if (!latteApplet || (latteApplet && !latteView.mimeContainsPlasmoid(event.mimeData, "org.kde.latte.plasmoid"))) { LayoutManager.insertAtCoordinates2(dndSpacer, event.x, event.y) dndSpacer.opacity = 1; } } onDragMove: { if (event.mimeData.formats.indexOf("application/x-orgkdeplasmataskmanager_taskbuttonitem") >= 0 || dockIsHidden || visibilityManager.inSlidingIn || visibilityManager.inSlidingOut) { return; } if (latteApplet) { if (latteApplet.launchersDrop(event)) { root.addLaunchersMessage = true; if (root.addLaunchersInTaskManager) { return; } } else { var isSeparator = ( latteView.mimeContainsPlasmoid(event.mimeData, "audoban.applet.separator") || latteView.mimeContainsPlasmoid(event.mimeData, "org.kde.latte.separator") ); if (isSeparator && root.latteAppletContainer.containsPos(event)) { confirmedDragEntered = true dndSpacer.opacity = 0; dndSpacer.parent = root; return; } } } if (!latteApplet || (latteApplet && !latteView.mimeContainsPlasmoid(event.mimeData, "org.kde.latte.plasmoid"))) { LayoutManager.insertAtCoordinates2(dndSpacer, event.x, event.y) dndSpacer.opacity = 1; } } onDragLeave: { if (confirmedDragEntered) { slotAnimationsNeedLength(-1); confirmedDragEntered = false; } root.addLaunchersMessage = false; dndSpacer.opacity = 0; dndSpacer.parent = root; } onDrop: { if (dockIsHidden || visibilityManager.inSlidingIn || visibilityManager.inSlidingOut) { return; } if (event.mimeData.formats.indexOf("application/x-orgkdeplasmataskmanager_taskbuttonitem") < 0) { if (latteApplet && latteApplet.launchersDrop(event) && root.addLaunchersInTaskManager) { latteApplet.launchersDropped(event.mimeData.urls); } else if (!latteApplet || (latteApplet && !latteView.mimeContainsPlasmoid(event.mimeData, "org.kde.latte.plasmoid"))) { plasmoid.processMimeData(event.mimeData, event.x, event.y); event.accept(event.proposedAction); } } if (confirmedDragEntered) { slotAnimationsNeedLength(-1); confirmedDragEntered = false; } root.addLaunchersMessage = false; dndSpacer.opacity = 0; //! this line is very important because it positions correctly the new applets //dndSpacer.parent = root; } onMaxLengthChanged: { layoutsContainer.updateSizeForAppletsInFill(); if (root.editMode) { updateAutomaticIconSize(); } } onToolBoxChanged: { if (toolBox) { toolBox.visible = false; } } property bool automaticSizeAnimation: false; onAutomaticIconSizeBasedSizeChanged: { if (!automaticSizeAnimation) { automaticSizeAnimation = true; slotAnimationsNeedBothAxis(1); } } onIconSizeChanged: { if (((iconSize === automaticIconSizeBasedSize) || (iconSize === root.maxIconSize)) && automaticSizeAnimation){ slotAnimationsNeedBothAxis(-1); automaticSizeAnimation=false; } } onIsReadyChanged: { if (isReady && !titleTooltipDialog.visible && titleTooltipDialog.activeItemHovered){ titleTooltipDialog.show(titleTooltipDialog.activeItem, titleTooltipDialog.activeItemText); } } onIsVerticalChanged: { if (isVertical) { if (plasmoid.configuration.panelPosition === Latte.Types.Left) plasmoid.configuration.panelPosition = Latte.Types.Top; else if (plasmoid.configuration.panelPosition === Latte.Types.Right) plasmoid.configuration.panelPosition = Latte.Types.Bottom; } else { if (plasmoid.configuration.panelPosition === Latte.Types.Top) plasmoid.configuration.panelPosition = Latte.Types.Left; else if (plasmoid.configuration.panelPosition === Latte.Types.Bottom) plasmoid.configuration.panelPosition = Latte.Types.Right; } } onProportionIconSizeChanged: { if (proportionIconSize!==-1) updateAutomaticIconSize(); } // onIconSizeChanged: console.log("Icon Size Changed:"+iconSize); Component.onCompleted: { // currentLayout.isLayoutHorizontal = isHorizontal LayoutManager.plasmoid = plasmoid; LayoutManager.root = root; LayoutManager.layout = layoutsContainer.mainLayout; LayoutManager.layoutS = layoutsContainer.startLayout; LayoutManager.layoutE = layoutsContainer.endLayout; LayoutManager.lastSpacer = lastSpacer; LayoutManager.restore(); plasmoid.action("configure").visible = !plasmoid.immutable; plasmoid.action("configure").enabled = !plasmoid.immutable; inStartupTimer.start(); } Component.onDestruction: { console.debug("Destroying Latte Dock Containment ui..."); if (latteView) { latteView.onXChanged.disconnect(visibilityManager.updateMaskArea); latteView.onYChanged.disconnect(visibilityManager.updateMaskArea); latteView.onWidthChanged.disconnect(visibilityManager.updateMaskArea); latteView.onHeightChanged.disconnect(visibilityManager.updateMaskArea); latteView.positioner.hideDockDuringLocationChangeStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterLocationChangeFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringScreenChangeStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterScreenChangeFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringMovingToLayoutStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterMovingToLayoutFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); if (latteView.visibility) { latteView.visibility.onContainsMouseChanged.disconnect(visibilityManager.slotContainsMouseChanged); latteView.visibility.onMustBeHide.disconnect(visibilityManager.slotMustBeHide); latteView.visibility.onMustBeShown.disconnect(visibilityManager.slotMustBeShown); } } } Containment.onAppletAdded: { addApplet(applet, x, y); console.log(applet.pluginName); LayoutManager.save(); updateIndexes(); } Containment.onAppletRemoved: { LayoutManager.removeApplet(applet); var flexibleFound = false; for (var i = 0; i < layoutsContainer.mainLayout.children.length; ++i) { var applet = layoutsContainer.mainLayout.children[i].applet; if (applet && ((root.isHorizontal && applet.Layout.fillWidth) || (!root.isHorizontal && applet.Layout.fillHeight)) && applet.visible) { flexibleFound = true; break } } if (!flexibleFound) { lastSpacer.parent = layoutsContainer.mainLayout; } console.log(applet.pluginName); LayoutManager.save(); updateIndexes(); updateContainsOnlyPlasmaTasks(); } Plasmoid.onUserConfiguringChanged: { if (plasmoid.immutable) { if (dragOverlay) { dragOverlay.destroy(); } return; } // console.debug("user configuring", plasmoid.userConfiguring) if (plasmoid.userConfiguring) { latteView.setBlockHiding(true); // console.log("applets------"); for (var i = 0; i < plasmoid.applets.length; ++i) { // console.log("applet:"+i); plasmoid.applets[i].expanded = false; } if (!dragOverlay) { var component = Qt.createComponent("editmode/ConfigOverlay.qml"); if (component.status == Component.Ready) { dragOverlay = component.createObject(root); } else { console.log("Could not create ConfigOverlay"); console.log(component.errorString()); } component.destroy(); } else { dragOverlay.visible = true; } } else { latteView.setBlockHiding(false); if (latteView.visibility.isHidden) { latteView.visibility.mustBeShown(); } if (dragOverlay) { dragOverlay.visible = false; dragOverlay.destroy(); } } } Plasmoid.onImmutableChanged: { plasmoid.action("configure").visible = !plasmoid.immutable; plasmoid.action("configure").enabled = !plasmoid.immutable; ///Set Preferred Sizes/// ///Notice: they are set here because if they are set with a binding ///they break the !immutable experience, the latteView becomes too small ///to add applets /* if (plasmoid.immutable) { if(root.isHorizontal) { root.Layout.preferredWidth = (plasmoid.configuration.panelPosition === Latte.Types.Justify ? layoutsContainer.width + 0.5*iconMargin : layoutsContainer.mainLayout.width + iconMargin); } else { root.Layout.preferredHeight = (plasmoid.configuration.panelPosition === Latte.Types.Justify ? layoutsContainer.height + 0.5*iconMargin : layoutsContainer.mainLayout.height + iconMargin); } } else { if (root.isHorizontal) { root.Layout.preferredWidth = Screen.width; } else { root.Layout.preferredHeight = Screen.height; } }*/ visibilityManager.updateMaskArea(); } //////////////END OF CONNECTIONS //////////////START OF FUNCTIONS function addApplet(applet, x, y) { var container = appletContainerComponent.createObject(dndSpacer.parent) container.applet = applet; applet.parent = container.appletWrapper; applet.anchors.fill = container.appletWrapper; applet.visible = true; // don't show applet if it chooses to be hidden but still make it // accessible in the panelcontroller container.visible = Qt.binding(function() { return applet.status !== PlasmaCore.Types.HiddenStatus || (!plasmoid.immutable && plasmoid.userConfiguring) }) addContainerInLayout(container, applet, x, y); updateContainsOnlyPlasmaTasks(); } function addContainerInLayout(container, applet, x, y){ // Is there a DND placeholder? Replace it! if ( (dndSpacer.parent === layoutsContainer.mainLayout) || (dndSpacer.parent === layoutsContainer.startLayout) || (dndSpacer.parent===layoutsContainer.endLayout)) { LayoutManager.insertBeforeForLayout(dndSpacer.parent, dndSpacer, container); dndSpacer.parent = root; return; // If the provided position is valid, use it. } else if (x >= 0 && y >= 0) { var index = LayoutManager.insertAtCoordinates2(container, x , y); // Fall through to determining an appropriate insert position. } else { var before = null; container.animationsEnabled = false; if (lastSpacer.parent === layoutsContainer.mainLayout) { before = lastSpacer; } // Insert icons to the left of whatever is at the center (usually a Task Manager), // if it exists. // FIXME TODO: This is a real-world fix to produce a sensible initial position for // launcher icons added by launcher menu applets. The basic approach has been used // since Plasma 1. However, "add launcher to X" is a generic-enough concept and // frequent-enough occurrence that we'd like to abstract it further in the future // and get rid of the ugliness of parties external to the containment adding applets // of a specific type, and the containment caring about the applet type. In a better // system the containment would be informed of requested launchers, and determine by // itself what it wants to do with that information. if (applet.pluginName == "org.kde.plasma.icon") { var middle = layoutsContainer.mainLayout.childAt(root.width / 2, root.height / 2); if (middle) { before = middle; } // Otherwise if lastSpacer is here, enqueue before it. } if (before) { LayoutManager.insertBefore(before, container); // Fall through to adding at the end. } else { container.parent = layoutsContainer.mainLayout; } } //Important, removes the first children of the layoutsContainer.mainLayout after the first //applet has been added lastSpacer.parent = root; updateIndexes(); } function addInternalViewSplitters(){ if (internalViewSplittersCount() === 0) { addInternalViewSplitter(plasmoid.configuration.splitterPosition); addInternalViewSplitter(plasmoid.configuration.splitterPosition2); } } function addInternalViewSplitter(pos){ var splittersCount = internalViewSplittersCount(); if(splittersCount<2){ var container = appletContainerComponent.createObject(root); container.internalSplitterId = splittersCount+1; container.visible = true; if(pos>=0 ){ LayoutManager.insertAtIndex(container, pos); } else { LayoutManager.insertAtIndex(container, Math.floor(layoutsContainer.mainLayout.count / 2)); } } } //! it is used in order to check the right click position //! the only way to take into account the visual appearance //! of the applet (including its spacers) function appletContainsPos(appletId, pos){ for (var i = 0; i < layoutsContainer.startLayout.children.length; ++i) { var child = layoutsContainer.startLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } for (var i = 0; i < layoutsContainer.mainLayout.children.length; ++i) { var child = layoutsContainer.mainLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } for (var i = 0; i < layoutsContainer.endLayout.children.length; ++i) { var child = layoutsContainer.endLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } return false; } function checkLastSpacer() { lastSpacer.parent = root var expands = false; if (isHorizontal) { for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if (item.Layout && item.Layout.fillWidth) { expands = true; } } } else { for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if (item.Layout && item.Layout.fillHeight) { expands = true; } } } if (!expands) { lastSpacer.parent = layoutsContainer.mainLayout } } function clearZoom(){ if (latteApplet){ latteApplet.clearZoom(); } root.clearZoomSignal(); } function containmentActions(){ return latteView.containmentActions(); } function decimalToHex(d, padding) { var hex = Number(d).toString(16); padding = typeof (padding) === "undefined" || padding === null ? padding = 2 : padding; while (hex.length < padding) { hex = "0" + hex; } return hex; } function disableDirectRender(){ // root.globalDirectRender = false; } function internalViewSplittersCount(){ var splitters = 0; for (var container in layoutsContainer.startLayout.children) { var item = layoutsContainer.startLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } for (var container in layoutsContainer.endLayout.children) { var item = layoutsContainer.endLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } return splitters; } function initializeHoveredIndexes() { layoutsContainer.hoveredIndex = -1; layoutsContainer.currentSpot = -1000; if (latteApplet) { latteApplet.initializeHoveredIndex(); } } function layoutManagerInsertBefore(place, item) { LayoutManager.insertBefore(place, item); } function layoutManagerInsertAfter(place, item) { LayoutManager.insertAfter(place, item); } function layoutManagerSave() { LayoutManager.save(); } function layoutManagerSaveOptions() { LayoutManager.saveOptions(); } function mouseInCanBeHoveredApplet(){ if (latteApplet && latteApplet.containsMouse()) return true; var applets = layoutsContainer.startLayout.children; for(var i=0; i=0; --i){ if(iconsArray[i] === size){ return true; } } return false; } function slotAnimationsNeedBothAxis(step) { if (step === 0) { return; } animationsNeedBothAxis = Math.max(animationsNeedBothAxis + step, 0); visibilityManager.updateMaskArea(); } function slotAnimationsNeedLength(step) { if (step === 0) { return; } animationsNeedLength = Math.max(animationsNeedLength + step, 0); //when need length animations are ended it would be a good idea //to update the tasks geometries in the plasmoid if(animationsNeedLength === 0 && latteApplet) { latteApplet.publishTasksGeometries(); } visibilityManager.updateMaskArea(); } function slotAnimationsNeedThickness(step) { if (step === 0) { return; } animationsNeedThickness = Math.max(animationsNeedThickness + step, 0); visibilityManager.updateMaskArea(); } //this is used when dragging a task in order to not hide the dock //and also by the menu appearing from tasks for the same reason function slotActionsBlockHiding(step) { //if (root.editMode) { // return; // } if ((step === 0) || (!latteView)) { return; } actionsBlockHiding = Math.max(actionsBlockHiding + step, 0); if (actionsBlockHiding > 0){ latteView.setBlockHiding(true); } else { if (!root.editMode) latteView.setBlockHiding(false); } } function slotPreviewsShown(){ if (latteView) { latteView.deactivateApplets(); } } function startCheckRestoreZoomTimer(){ checkRestoreZoom.start(); } function stopCheckRestoreZoomTimer(){ checkRestoreZoom.stop(); } function startDirectRenderDelayerDuringEntering(){ directRenderDelayerForEnteringTimer.start(); } function setGlobalDirectRender(value) { if (latteApplet && latteApplet.waitingLaunchers.length > 0) return; if (value === true) { if (mouseInCanBeHoveredApplet()) { root.globalDirectRender = true; } else { // console.log("direct render true ignored..."); } } else { root.globalDirectRender = false; } } function updateAutomaticIconSize() { if ( !blockAutomaticUpdateIconSize.running && !visibilityManager.inTempHiding && ((visibilityManager.normalState || root.editMode) && (root.autoDecreaseIconSize || (!root.autoDecreaseIconSize && root.iconSize!=root.maxIconSize))) && (iconSize===root.maxIconSize || iconSize === automaticIconSizeBasedSize) ) { blockAutomaticUpdateIconSize.start(); var layoutLength; var maxLength = root.maxLength; //console.log("------Entered check-----"); //console.log("max length: "+ maxLength); if (root.isVertical) { layoutLength = (plasmoid.configuration.panelPosition === Latte.Types.Justify) ? layoutsContainer.startLayout.height+layoutsContainer.mainLayout.height+layoutsContainer.endLayout.height : layoutsContainer.mainLayout.height } else { layoutLength = (plasmoid.configuration.panelPosition === Latte.Types.Justify) ? layoutsContainer.startLayout.width+layoutsContainer.mainLayout.width+layoutsContainer.endLayout.width : layoutsContainer.mainLayout.width } var toShrinkLimit = maxLength-((root.zoomFactor-1)*(iconSize + thickMargins)); var toGrowLimit = maxLength-1.5*((root.zoomFactor-1)*(iconSize + thickMargins)); var newIconSizeFound = false; if (layoutLength > toShrinkLimit) { //must shrink // console.log("step3"); var nextIconSize = root.maxIconSize; do { nextIconSize = nextIconSize - iconStep; var factor = nextIconSize / iconSize; var nextLength = factor * layoutLength; } while ( (nextLength>toShrinkLimit) && (nextIconSize !== 16)); automaticIconSizeBasedSize = nextIconSize; newIconSizeFound = true; console.log("Step 3 - found:"+automaticIconSizeBasedSize); } else if ((layoutLength 0) { if (foundGoodSize === root.maxIconSize) { automaticIconSizeBasedSize = -1; } else { automaticIconSizeBasedSize = foundGoodSize; } newIconSizeFound = true // console.log("Step 4 - found:"+automaticIconSizeBasedSize); } else { // console.log("Step 4 - did not found..."); } } } } function updateContainsOnlyPlasmaTasks() { if (latteView) { root.containsOnlyPlasmaTasks = (latteView.tasksPresent() && !latteApplet); } else { root.containsOnlyPlasmaTasks = false; } } function updateSizeForAppletsInFill() { layoutsContainer.updateSizeForAppletsInFill(); } function splitMainLayoutToLayouts() { if (internalViewSplittersCount() === 2) { console.log("LAYOUTS: Moving applets from MAIN to THREE Layouts mode..."); var splitter = -1; var splitter2 = -1; var totalChildren = layoutsContainer.mainLayout.children.length; for (var i=0; i=0 && splitter2 === -1) { splitter2 = i; } } // console.log("update layouts 1:"+splitter + " - "+splitter2); for (var i=0; i<=splitter; ++i){ var item = layoutsContainer.mainLayout.children[0]; item.parent = layoutsContainer.startLayout; } splitter2 = splitter2 - splitter - 1; // console.log("update layouts 2:"+splitter + " - "+splitter2); totalChildren = layoutsContainer.mainLayout.children.length; for (var i=splitter2+1; i=0; --i) { var item1 = layoutsContainer.mainLayout.children[0]; item1.parent = layoutsContainer.startLayout; } var totalChildren2 = layoutsContainer.endLayout.children.length; for (var i=totalChildren2-1; i>=0; --i) { var item2 = layoutsContainer.endLayout.children[0]; item2.parent = layoutsContainer.startLayout; } var totalChildrenL = layoutsContainer.startLayout.children.length; for (var i=totalChildrenL-1; i>=0; --i) { var itemL = layoutsContainer.startLayout.children[0]; itemL.parent = layoutsContainer.mainLayout; } } //END functions ////BEGIN interfaces Connections { target: Latte.WindowSystem onCompositingActiveChanged: { visibilityManager.updateMaskArea(); } } Connections { target: latteView onWidthChanged:{ if (root.isHorizontal && proportionIconSize!==-1) updateAutomaticIconSize(); } onHeightChanged:{ if (root.isVertical && proportionIconSize!==-1) updateAutomaticIconSize(); } onContextMenuIsShownChanged: { if (!latteView.contextMenuIsShown) { checkRestoreZoom.start(); } else { root.setGlobalDirectRender(false); } } } Connections{ target: latteView && latteView.visibility ? latteView.visibility : root ignoreUnknownSignals : true onContainsMouseChanged: { if (mouseInHoverableArea()) { stopCheckRestoreZoomTimer(); } else { startCheckRestoreZoomTimer(); } } } Connections{ target: layoutsContainer onHoveredIndexChanged: { if (latteApplet && layoutsContainer.hoveredIndex>-1){ latteApplet.setHoveredIndex(-1); } if (latteApplet && latteApplet.windowPreviewIsShown && layoutsContainer.hoveredIndex>-1) { latteApplet.hidePreview(); } } } ////END interfaces /////BEGIN: Title Tooltip/////////// PlasmaCore.Dialog{ id: titleTooltipDialog type: PlasmaCore.Dialog.Tooltip flags: Qt.WindowStaysOnTopHint | Qt.WindowDoesNotAcceptFocus | Qt.ToolTip location: plasmoid.location mainItem: RowLayout{ Layout.fillWidth: true Layout.fillHeight: true PlasmaComponents.Label{ id:titleLbl Layout.leftMargin: 4 Layout.rightMargin: 4 Layout.topMargin: 2 Layout.bottomMargin: 2 text: titleTooltipDialog.title } } visible: false property string title: "" property bool activeItemHovered: false property Item activeItem: null property Item activeItemTooltipParent: null property string activeItemText: "" Component.onCompleted: { root.clearZoomSignal.connect(titleTooltipDialog.hide); } Component.onDestruction: { root.clearZoomSignal.disconnect(titleTooltipDialog.hide); } function hide(debug){ if (!root.titleTooltips) return; activeItemHovered = false; hideTitleTooltipTimer.start(); } function show(taskItem, text){ if (!root.titleTooltips || (latteApplet && latteApplet.contextMenu)){ return; } activeItemHovered = true; if (activeItem !== taskItem) { activeItem = taskItem; activeItemTooltipParent = taskItem.tooltipVisualParent; activeItemText = text; } if (isReady) { showTitleTooltipTimer.start(); } } function update() { activeItemHovered = true title = activeItemText; visualParent = activeItemTooltipParent; if (latteApplet && latteApplet.windowPreviewIsShown) { latteApplet.hidePreview(); } visible = true; } } Timer { id: showTitleTooltipTimer interval: 100 onTriggered: { if (latteView && latteView.visibility && latteView.visibility.containsMouse) { titleTooltipDialog.update(); } if (titleTooltipDialog.visible) { titleTooltipCheckerToNotShowTimer.start(); } if (root.debugModeTimers) { console.log("containment timer: showTitleTooltipTimer called..."); } } } Timer { id: hideTitleTooltipTimer interval: 200 onTriggered: { if (!titleTooltipDialog.activeItemHovered) { titleTooltipDialog.visible = false; } if (root.debugModeTimers) { console.log("containment timer: hideTitleTooltipTimer called..."); } } } //! Timer to fix #811, rare cases that both a window preview and context menu are //! shown Timer { id: titleTooltipCheckerToNotShowTimer interval: 250 onTriggered: { if (titleTooltipDialog.visible && latteApplet && (latteApplet.contextMenu || latteApplet.windowPreviewIsShown)) { titleTooltipDialog.visible = false; } } } /////END: Title Tooltip/////////// ///////////////BEGIN components Component { id: appletContainerComponent Applet.AppletItem{} } ParabolicManager{ id: _parabolicManager } Indicators.Manager{ id: indicators } ///////////////END components PlasmaCore.ColorScope{ id: colorScopePalette } ///////////////BEGIN UI elements //it is used to check if the mouse is outside the layoutsContainer borders, //so in that case the onLeave event behavior should be trigerred RootMouseArea{ id: rootMouseArea } Loader{ active: root.debugModeWindow sourceComponent: DebugWindow{} } //! Load a sepia background in order to avoid black background Loader{ anchors.fill: parent active: !Latte.WindowSystem.compositingActive sourceComponent: Image{ anchors.fill: parent fillMode: Image.Tile source: root.hasUserSpecifiedBackground ? latteView.managedLayout.background : "../icons/wheatprint.jpg" } } EditMode.Visual{ id:editModeVisual // z: root.behaveAsPlasmaPanel ? 1 : 0 } Item{ id: panelBox anchors.fill:layoutsContainer // z: root.behaveAsPlasmaPanel ? 0 : 1 PanelBox{ id: panelBoxBackground } } Item { id: lastSpacer parent: layoutsContainer.mainLayout Layout.fillWidth: true Layout.fillHeight: true z:10 Rectangle{ anchors.fill: parent color: "transparent" border.color: "yellow" border.width: 1 } } Item { id: dndSpacer property int normalSize: root.iconSize + root.thickMargins - 1 width: normalSize height: normalSize Layout.preferredWidth: width Layout.preferredHeight: height opacity: 0 z:10 AddWidgetVisual{} } Loader{ anchors.fill: parent active: root.debugMode z:10 sourceComponent: Item{ Rectangle{ anchors.fill: parent color: "yellow" opacity: 0.30 } } } VisibilityManager{ id: visibilityManager } Layouts.LayoutsContainer { id: layoutsContainer } Colorizer.Manager { id: colorizerManager } ///////////////END UI elements ///////////////BEGIN TIMER elements //Timer to check if the mouse is still outside the latteView in order to restore zooms to 1.0 Timer{ id:checkRestoreZoom interval: 90 onTriggered: { if (latteApplet && (latteApplet.previewContainsMouse() || latteApplet.contextMenu)) return; if (latteView.contextMenuIsShown) return; if (!mouseInHoverableArea()) { setGlobalDirectRender(false); root.initializeHoveredIndexes(); root.clearZoom(); } if (root.debugModeTimers) { console.log("containment timer: checkRestoreZoom called..."); } } } //! Delayer in order to not activate directRendering when the mouse //! enters until the timer has ended. This way we make sure that the //! zoom-in animations will have ended. Timer{ id:directRenderDelayerForEnteringTimer interval: 3.2 * root.durationTime * units.shortDuration } //this is a delayer to update mask area, it is used in cases //that animations can not catch up with animations signals //e.g. the automaicIconSize case Timer{ id:delayUpdateMaskArea repeat:false; interval:300; onTriggered: { if (layoutsContainer.animationSent) { root.slotAnimationsNeedLength(-1); layoutsContainer.animationSent = false; } visibilityManager.updateMaskArea(); if (root.debugModeTimers) { console.log("containment timer: delayUpdateMaskArea called..."); } } } // This function is very costly! This timer makes sure that it can be called // only once every 1sec. Timer{ id:blockAutomaticUpdateIconSize interval: 1000 repeat: false onTriggered: root.updateAutomaticIconSize(); } //! It is used in order to slide-in the latteView on startup Timer{ id: inStartupTimer interval: 1500 repeat: false onTriggered: { if (inStartup) { visibilityManager.slotMustBeShown(); } } } ///////////////END TIMER elements } diff --git a/declarativeimports/components/ExternalShadow.qml b/declarativeimports/components/ExternalShadow.qml index ac5e9f32..b5dffa19 100644 --- a/declarativeimports/components/ExternalShadow.qml +++ b/declarativeimports/components/ExternalShadow.qml @@ -1,125 +1,122 @@ /* * 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.1 import org.kde.plasma.core 2.0 as PlasmaCore import QtGraphicalEffects 1.0 import org.kde.latte 0.2 as Latte Item{ id: shadowRoot property int shadowDirection: PlasmaCore.Types.BottomEdge property int shadowSize: 7 property real shadowOpacity: 1 + property color shadowColor: "#040404" readonly property bool isHorizontal : (shadowDirection !== PlasmaCore.Types.LeftEdge) && (shadowDirection !== PlasmaCore.Types.RightEdge) readonly property int implicitWidth: shadow.width readonly property int implicitHeight: shadow.height Item{ id: shadow width: isHorizontal ? shadowRoot.width + 2*shadowSize : shadowSize height: isHorizontal ? shadowSize: shadowRoot.height + 2*shadowSize opacity: shadowOpacity clip: true Rectangle{ id: editShadow width: shadowRoot.width height: shadowRoot.height color: "white" layer.enabled: true layer.effect: DropShadow { radius: shadowSize fast: true samples: 2 * radius - color: "#040404" + color: shadowRoot.shadowColor } } states: [ ///topShadow State { name: "topShadow" when: (shadowDirection === PlasmaCore.Types.BottomEdge) AnchorChanges { target: editShadow - anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; - horizontalCenter:parent.horizontalCenter; verticalCenter:parent.undefined} + anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined} } PropertyChanges{ target: editShadow anchors{ leftMargin: 0; rightMargin:0; topMargin:shadowSize; bottomMargin:0} } }, ///bottomShadow State { name: "bottomShadow" when: (shadowDirection === PlasmaCore.Types.TopEdge) AnchorChanges { target: editShadow - anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; - horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} + anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined} } PropertyChanges{ target: editShadow anchors{ leftMargin: 0; rightMargin:0; topMargin:0; bottomMargin:shadowSize} } }, ///leftShadow State { name: "leftShadow" when: (shadowDirection === PlasmaCore.Types.RightEdge) AnchorChanges { target: editShadow - anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; - horizontalCenter:undefined; verticalCenter:undefined} + anchors{ top:parent.top; bottom: undefined; left:parent.left; right:undefined} } PropertyChanges{ target: editShadow anchors{ leftMargin: shadowSize; rightMargin:0; topMargin:0; bottomMargin:0} } }, ///rightShadow State { name: "rightShadow" when: (shadowDirection === PlasmaCore.Types.LeftEdge) AnchorChanges { target: editShadow - anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right; - horizontalCenter:undefined; verticalCenter:undefined} + anchors{top:parent.top; bottom:undefined; left:undefined; right:parent.right} } PropertyChanges{ target: editShadow anchors{ leftMargin: 0; rightMargin:shadowSize; topMargin:0; bottomMargin:0} } } ] } } diff --git a/plasmoid/package/contents/ui/ScrollEdgeShadows.qml b/plasmoid/package/contents/ui/ScrollEdgeShadows.qml new file mode 100644 index 00000000..9b1d915a --- /dev/null +++ b/plasmoid/package/contents/ui/ScrollEdgeShadows.qml @@ -0,0 +1,103 @@ +/* + * Copyright 2019 Michail Vourlakos + * + * This program 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. + * + * This program 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.Controls 1.4 +import QtGraphicalEffects 1.2 + +import org.kde.plasma.plasmoid 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore + +Item { + id: shadowsContainer + opacity: 0.4 + + readonly property int gradientLength: root.iconSize / 3 + readonly property int thickness: latteView ? latteView.realPanelSize : root.iconSize + root.thickMargins + readonly property color appliedColor: root.appShadowColorSolid + + LinearGradient { + id: firstGradient + width: !root.vertical ? gradientLength : shadowsContainer.thickness + height: !root.vertical ? shadowsContainer.thickness : gradientLength + + start: Qt.point(0, 0) + end: !root.vertical ? Qt.point(width, 0) : Qt.point(0,height) + + gradient: Gradient { + GradientStop { position: 0.0; color: (scrollableList.currentPos > scrollableList.scrollFirstPos ? appliedColor : "transparent") } + GradientStop { position: 1.0; color: "transparent" } + } + } + + LinearGradient { + id: lastGradient + width: firstGradient.width + height: firstGradient.height + start: firstGradient.start + end: firstGradient.end + + gradient: Gradient { + GradientStop { position: 0.0; color: "transparent" } + GradientStop { position: 1.0; color: (scrollableList.currentPos < scrollableList.scrollLastPos ? appliedColor : "transparent") } + } + } + + states: [ + ///Left Edge + State { + name: "bottom" + when: plasmoid.location === PlasmaCore.Types.BottomEdge + + AnchorChanges { + target: firstGradient + anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; + horizontalCenter:undefined; verticalCenter:undefined} + } + AnchorChanges { + target: lastGradient + anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; + horizontalCenter:undefined; verticalCenter:undefined} + } + AnchorChanges { + target: shadowsContainer + anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; + horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} + } + }, + State { + name: "left" + when: plasmoid.location === PlasmaCore.Types.LeftEdge + + AnchorChanges { + target: firstGradient + anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; + horizontalCenter:undefined; verticalCenter:undefined} + } + AnchorChanges { + target: lastGradient + anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; + horizontalCenter:undefined; verticalCenter:undefined} + } + AnchorChanges { + target: shadowsContainer + anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; + horizontalCenter:undefined; verticalCenter:parent.verticalCenter} + } + } + ] +} diff --git a/plasmoid/package/contents/ui/ScrollOpacityMask.qml b/plasmoid/package/contents/ui/ScrollOpacityMask.qml new file mode 100644 index 00000000..9f2addf0 --- /dev/null +++ b/plasmoid/package/contents/ui/ScrollOpacityMask.qml @@ -0,0 +1,113 @@ +/* + * Copyright 2019 Michail Vourlakos + * + * This program 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. + * + * This program 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.Controls 1.4 +import QtGraphicalEffects 1.2 + +import org.kde.plasma.plasmoid 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore + +Item { + + readonly property int gradientLength: root.iconSize / 3 + + LinearGradient { + id: firstGradient + width: !root.vertical ? gradientLength : scrollableList.thickness + height: !root.vertical ? scrollableList.thickness : gradientLength + + start: Qt.point(0, 0) + end: !root.vertical ? Qt.point(gradientLength, 0) : Qt.point(0, gradientLength) + + gradient: Gradient { + GradientStop { position: 0.0; color: scrollableList.currentPos <= scrollableList.scrollFirstPos ? "white" : "transparent" } + GradientStop { position: 1.0; color: "white" } + } + } + + Rectangle { + id: centralRectangle + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + width: !root.vertical ? length : firstGradient.width + height: !root.vertical ? firstGradient.height : length + color: "white" + + property int length: !root.vertical ? parent.width - 2*gradientLength : parent.height - 2*gradientLength + } + + LinearGradient { + id: lastGradient + anchors.top: parent.top + anchors.right: parent.right + width: firstGradient.width + height: firstGradient.height + + start: firstGradient.start + end: firstGradient.end + + gradient: Gradient { + GradientStop { position: 0.0; color: "white" } + GradientStop { position: 1.0; color: (scrollableList.currentPos >= scrollableList.scrollLastPos ? "white" : "transparent") } + } + } + + states: [ + ///Left Edge + State { + name: "bottom" + when: plasmoid.location === PlasmaCore.Types.BottomEdge + + AnchorChanges { + target: firstGradient + anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; + horizontalCenter:undefined; verticalCenter:undefined} + } + AnchorChanges { + target: centralRectangle + anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; + horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} + } + AnchorChanges { + target: lastGradient + anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; + horizontalCenter:undefined; verticalCenter:undefined} + } + }, + State { + name: "left" + when: plasmoid.location === PlasmaCore.Types.LeftEdge + + AnchorChanges { + target: firstGradient + anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; + horizontalCenter:undefined; verticalCenter:undefined} + } + AnchorChanges { + target: centralRectangle + anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; + horizontalCenter:undefined; verticalCenter:parent.verticalCenter} + } + AnchorChanges { + target: lastGradient + anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; + horizontalCenter:undefined; verticalCenter:undefined} + } + } + ] +} diff --git a/plasmoid/package/contents/ui/ScrollableList.qml b/plasmoid/package/contents/ui/ScrollableList.qml new file mode 100644 index 00000000..aa43b277 --- /dev/null +++ b/plasmoid/package/contents/ui/ScrollableList.qml @@ -0,0 +1,278 @@ +/* + * Copyright 2019 Michail Vourlakos + * + * This program 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. + * + * This program 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.Controls 1.4 + +import org.kde.plasma.plasmoid 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore + +import org.kde.latte 0.2 as Latte + +Flickable{ + id: flickableContainer + clip: false + flickableDirection: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? Flickable.HorizontalFlick : Flickable.VerticalFlick + interactive: false + + property int alignment: Latte.Types.BottomEdgeCenterAlign + property int offset: 0 + + readonly property bool contentsExceed: !root.vertical ? Math.floor(contentWidth) > width : Math.floor(contentHeight) > height + readonly property int contentsExtraSpace: { + if (contentsExceed) { + if (!root.vertical) { + return contentWidth - width; + } else { + return contentHeight - height; + } + } + + return 0; + } + + readonly property int scrollFirstPos: 0 + readonly property int scrollLastPos: contentsExtraSpace + readonly property int scrollStep: root.iconSize * 1.5 + + readonly property int currentPos: !root.vertical ? contentX : contentY + + function increasePos() { + if (!root.vertical) { + contentX = Math.min(scrollLastPos, contentX + scrollStep); + } else { + contentY = Math.min(scrollLastPos, contentY + scrollStep); + } + + } + + function decreasePos() { + if (!root.vertical) { + contentX = Math.max(scrollFirstPos, contentX - scrollStep); + } else { + contentY = Math.max(scrollFirstPos, contentY - scrollStep); + } + } + + onContentsExtraSpaceChanged: { + if (!root.vertical) { + if (contentX < scrollFirstPos) { + contentX = scrollFirstPos; + } else if (contentX > scrollLastPos) { + contentX = scrollLastPos; + } + } else { + if (contentY < scrollFirstPos) { + contentY = scrollFirstPos; + } else if (contentY > scrollLastPos) { + contentY = scrollLastPos; + } + } + } + + Behavior on contentX { + NumberAnimation { + duration: root.durationTime*units.longDuration + easing.type: Easing.OutQuad + } + } + + Behavior on contentY { + NumberAnimation { + duration: root.durationTime*units.longDuration + easing.type: Easing.OutQuad + } + } + + //////////////////////////BEGIN states + //user set Panel Positions + // 0-Center, 1-Left, 2-Right, 3-Top, 4-Bottom + states: [ + ///Left Edge + State { + name: "leftCenter" + when: flickableContainer.alignment === Latte.Types.LeftEdgeCenterAlign + + AnchorChanges { + target: flickableContainer + anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} + } + PropertyChanges{ + target: flickableContainer; + anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:0; + anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: flickableContainer.offset; + } + }, + State { + name: "leftTop" + when: flickableContainer.alignment === Latte.Types.LeftEdgeTopAlign + + AnchorChanges { + target: flickableContainer + anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} + } + PropertyChanges{ + target: flickableContainer; + anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:flickableContainer.offset; anchors.bottomMargin:flickableContainer.lastMargin; + anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; + } + }, + State { + name: "leftBottom" + when: flickableContainer.alignment === Latte.Types.LeftEdgeBottomAlign + + AnchorChanges { + target: flickableContainer + anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} + } + PropertyChanges{ + target: flickableContainer; + anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:flickableContainer.lastMargin; anchors.bottomMargin:flickableContainer.offset; + anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; + } + }, + ///Right Edge + State { + name: "rightCenter" + when: flickableContainer.alignment === Latte.Types.RightEdgeCenterAlign + + AnchorChanges { + target: flickableContainer + anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} + } + PropertyChanges{ + target: flickableContainer; + anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:0; + anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: flickableContainer.offset; + } + }, + State { + name: "rightTop" + when: flickableContainer.alignment === Latte.Types.RightEdgeTopAlign + + AnchorChanges { + target: flickableContainer + anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} + } + PropertyChanges{ + target: flickableContainer; + anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:flickableContainer.offset; anchors.bottomMargin:flickableContainer.lastMargin; + anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; + } + }, + State { + name: "rightBottom" + when: flickableContainer.alignment === Latte.Types.RightEdgeBottomAlign + + AnchorChanges { + target: flickableContainer + anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} + } + PropertyChanges{ + target: flickableContainer; + anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:flickableContainer.lastMargin; anchors.bottomMargin:flickableContainer.offset; + anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; + } + }, + ///Bottom Edge + State { + name: "bottomCenter" + when: flickableContainer.alignment === Latte.Types.BottomEdgeCenterAlign + + AnchorChanges { + target: flickableContainer + anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} + } + PropertyChanges{ + target: flickableContainer; + anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:0; + anchors.horizontalCenterOffset: flickableContainer.offset; anchors.verticalCenterOffset: 0; + } + }, + State { + name: "bottomLeft" + when: flickableContainer.alignment === Latte.Types.BottomEdgeLeftAlign + + AnchorChanges { + target: flickableContainer + anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} + } + PropertyChanges{ + target: flickableContainer; + anchors.leftMargin: flickableContainer.offset; anchors.rightMargin:flickableContainer.lastMargin; anchors.topMargin:0; anchors.bottomMargin:0; + anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; + } + }, + State { + name: "bottomRight" + when: flickableContainer.alignment === Latte.Types.BottomEdgeRightAlign + + AnchorChanges { + target: flickableContainer + anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} + } + PropertyChanges{ + target: flickableContainer; + anchors.leftMargin: flickableContainer.lastMargin; anchors.rightMargin:flickableContainer.offset; anchors.topMargin:0; anchors.bottomMargin:0; + anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; + } + }, + ///Top Edge + State { + name: "topCenter" + when: flickableContainer.alignment === Latte.Types.TopEdgeCenterAlign + + AnchorChanges { + target: flickableContainer + anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} + } + PropertyChanges{ + target: flickableContainer; + anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:0; + anchors.horizontalCenterOffset: flickableContainer.offset; anchors.verticalCenterOffset: 0; + } + }, + State { + name: "topLeft" + when: flickableContainer.alignment === Latte.Types.TopEdgeLeftAlign + + AnchorChanges { + target: flickableContainer + anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} + } + PropertyChanges{ + target: flickableContainer; + anchors.leftMargin: flickableContainer.offset; anchors.rightMargin:flickableContainer.lastMargin; anchors.topMargin:0; anchors.bottomMargin:0; + anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; + } + }, + State { + name: "topRight" + when: flickableContainer.alignment === Latte.Types.TopEdgeRightAlign + + AnchorChanges { + target: flickableContainer + anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} + } + PropertyChanges{ + target: flickableContainer; + anchors.leftMargin: flickableContainer.lastMargin; anchors.rightMargin:flickableContainer.offset; anchors.topMargin:0; anchors.bottomMargin:0; + anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; + } + } + ] +} diff --git a/plasmoid/package/contents/ui/main.qml b/plasmoid/package/contents/ui/main.qml index 0a86acc6..74bbc71f 100644 --- a/plasmoid/package/contents/ui/main.qml +++ b/plasmoid/package/contents/ui/main.qml @@ -1,2165 +1,2227 @@ /* * 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.0 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 0.2 as Latte import "task" as Task import "../code/tools.js" as TaskTools import "../code/activitiesTools.js" as ActivitiesTools import "../code/ColorizerTools.js" as ColorizerTools Item { id:root - // Layout.fillHeight: userPanelPosition === 0 ? true : false - // Layout.fillWidth: userPanelPosition === 0 ? true : false + Layout.fillWidth: scrollingEnabled && !root.vertical ? true : false + Layout.fillHeight: scrollingEnabled && root.vertical ? true : false ///IMPORTANT: These values must be tested when the Now Dock Panel support ///also the four new anchors. A small issue is shown between the animation /// of the now dock plasmoid and the neighbour widgets... - Layout.minimumWidth: (userPanelPosition !== 0)&&(!latteView) ? clearWidth : -1 - Layout.minimumHeight: (userPanelPosition !== 0)&&(!latteView) ? clearHeight : -1 - Layout.preferredWidth: (userPanelPosition !== 0)&&(!latteView) ? tasksWidth : -1 - Layout.preferredHeight: (userPanelPosition !== 0)&&(!latteView) ? tasksHeight : -1 + Layout.minimumWidth: -1 //(userPanelPosition !== 0)&&(!latteView) ? clearWidth : -1 + Layout.minimumHeight: -1 //(userPanelPosition !== 0)&&(!latteView) ? clearHeight : -1 + Layout.preferredWidth: tasksWidth //(userPanelPosition !== 0)&&(!latteView) ? tasksWidth : tasksWidth + Layout.preferredHeight: tasksHeight //(userPanelPosition !== 0)&&(!latteView) ? tasksHeight : tasksHeight + Layout.maximumWidth: -1 + Layout.maximumHeight: -1 + LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft && !root.vertical LayoutMirroring.childrenInherit: true property bool debugLocation: false //it is used to check both the applet and the containment for direct render property bool globalDirectRender: latteView ? latteView.globalDirectRender : icList.directRender property bool plasma515: Latte.WindowSystem.plasmaDesktopVersion >= Latte.WindowSystem.makeVersion(5,14,90) 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 readonly property bool hasInternalSeparator: parabolicManager.hasInternalSeparator 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: ((root.position === PlasmaCore.Types.LeftPositioned) || - (root.position === PlasmaCore.Types.RightPositioned)) ? true : false + property bool vertical: plasmoid.formFactor === PlasmaCore.Types.Vertical ? true : false property int clearWidth property int clearHeight property int newLocationDebugUse: PlasmaCore.Types.BottomPositioned property int newDroppedPosition: -1 property int noInitCreatedBuffers: 0 property int noTasksInAnimation: 0 property int themePanelSize: plasmoid.configuration.panelSize property int position : PlasmaCore.Types.BottomPositioned property int tasksStarting: 0 ///Don't use Math.floor it adds one pixel in animations and creates glitches property int widthMargins: root.vertical ? thickMargins : lengthMargins property int heightMargins: !root.vertical ? thickMargins : lengthMargins property int internalWidthMargins: root.vertical ? thickMargins : 2 * lengthIntMargin property int internalHeightMargins: !root.vertical ? thickMargins : 2 * lengthIntMargin property real textColorBrightness: ColorizerTools.colorBrightness(theme.textColor) property color minimizedDotColor: { if (latteView) { return latteView.minimizedDotColor; } return textColorBrightness > 127.5 ? Qt.darker(theme.textColor, 1.7) : Qt.lighter(theme.textColor, 7) } //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: [] property variant waitingLaunchers: [] //! launchers that are shown after a window removal and must be shown //! immediately because they are already present! property variant immediateLaunchers: [] //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 //separator calculations based on audoban's design property int maxSeparatorLength: { if (root.vertical) return 5 + heightMargins; else return 5 + widthMargins; } property real missingSeparatorLength: { if (!root.isVertical) return ((iconSize + widthMargins) * zoomFactor) - maxSeparatorLength; else return ((iconSize + heightMargins) * zoomFactor) - maxSeparatorLength; } //! it is used to play the animation correct when the user removes a launcher property string launcherForRemoval: "" //BEGIN Latte Dock properties property bool dockIsShownCompletely: latteView ? latteView.dockIsShownCompletely : true property bool enableShadows: latteView ? latteView.enableShadows > 0 : plasmoid.configuration.showShadows property bool forceHidePanel: false property bool directRenderDelayerIsRunning: latteView ? latteView.directRenderDelayerIsRunning : directRenderDelayerForEnteringTimer.running property bool disableLeftSpacer: false property bool disableRightSpacer: false property bool dockIsHidden: latteView ? latteView.dockIsHidden : false property bool groupTasksByDefault: latteView ? latteView.groupTasksByDefault: true property bool highlightWindows: latteView ? latteView.hoverAction === Latte.Types.HighlightWindows || latteView.hoverAction === Latte.Types.PreviewAndHighlightWindows : plasmoid.configuration.highlightWindows property bool mouseWheelActions: latteView ? latteView.mouseWheelActions : true property bool parabolicEffectEnabled: latteView ? latteView.parabolicEffectEnabled : zoomFactor>1 && !root.editMode property bool showInfoBadge: latteView ? latteView.showInfoBadge : plasmoid.configuration.showInfoBadge property bool showProgressBadge: latteView ? latteView.showProgressBadge : plasmoid.configuration.showInfoBadge property bool showAudioBadge: latteView ? latteView.showAudioBadge : plasmoid.configuration.showAudioBadge property bool audioBadgeActionsEnabled: latteView ? latteView.audioBadgeActionsEnabled : true property bool showOnlyCurrentScreen: latteView ? latteView.showOnlyCurrentScreen : plasmoid.configuration.showOnlyCurrentScreen property bool showOnlyCurrentDesktop: latteView ? latteView.showOnlyCurrentDesktop : plasmoid.configuration.showOnlyCurrentDesktop property bool showOnlyCurrentActivity: latteView ? latteView.showOnlyCurrentActivity : plasmoid.configuration.showOnlyCurrentActivity property bool showPreviews: latteView ? latteView.hoverAction === Latte.Types.PreviewWindows || latteView.hoverAction === Latte.Types.PreviewAndHighlightWindows : plasmoid.configuration.showToolTips property bool showWindowActions: latteView ? latteView.showWindowActions : plasmoid.configuration.showWindowActions property bool showWindowsOnlyFromLaunchers: latteView ? latteView.showWindowsOnlyFromLaunchers : false + property bool scrollingEnabled: true + property bool titleTooltips: latteView ? latteView.titleTooltips : false property alias windowPreviewIsShown: windowsPreviewDlg.visible property int animationStep: latteView ? latteView.animationStep : 1 property int directRenderAnimationTime: latteView ? latteView.directRenderAnimationTime : 0 property int dockHoveredIndex : latteView ? latteView.hoveredIndex : -1 property int iconSize: latteView ? latteView.iconSize : Math.max(plasmoid.configuration.iconSize, 16) property int maxIconSize: latteView ? latteView.maxIconSize : iconSize property int leftClickAction: latteView ? latteView.leftClickAction : Latte.Types.PresentWindows property int middleClickAction: latteView ? latteView.middleClickAction : plasmoid.configuration.middleClickAction property int hoverAction: latteView ? latteView.hoverAction : Latte.Types.NoneAction property int modifier: latteView ? latteView.modifier : -1 property int modifierClickAction: latteView ? latteView.modifierClickAction : -1 property int modifierClick: latteView ? latteView.modifierClick : -1 property int modifierQt:{ if (modifier === Latte.Types.Shift) return Qt.ShiftModifier; else if (modifier === Latte.Types.Ctrl) return Qt.ControlModifier; else if (modifier === Latte.Types.Alt) return Qt.AltModifier; else if (modifier === Latte.Types.Meta) return Qt.MetaModifier; else return -1; } property int thickMargin: latteView ? latteView.thickMargin : 0.16*iconSize property int thickMargins: 2 * thickMargin property int lengthIntMargin: latteView ? latteView.lengthIntMargin : 0.04*iconSize property int lengthExtMargin: latteView ? latteView.lengthExtMargin : 0.1 * iconSize property int lengthMargin: lengthIntMargin + lengthExtMargin property int lengthMargins: 2 * lengthMargin property int tasksHeight: mouseHandler.height property int tasksWidth: mouseHandler.width property int userPanelPosition: latteView ? latteView.panelAlignment : plasmoid.configuration.plasmoidPosition readonly property real currentPanelOpacity: latteView ? latteView.currentPanelTransparency / 100 : 1 //! Animations property bool animationsEnabled: latteView ? latteView.animationsEnabled : durationTime !== 0 property bool animationLauncherBouncing: latteView ? latteView.animationLauncherBouncing : durationTime !== 0 property bool animationWindowInAttention: latteView ? latteView.animationWindowInAttention : durationTime !== 0 property bool animationNewWindowSliding: latteView ? latteView.animationNewWindowSliding : durationTime !== 0 property bool animationWindowAddedInGroup: latteView ? latteView.animationWindowAddedInGroup : durationTime !== 0 property bool animationWindowRemovedFromGroup: latteView ? latteView.animationWindowRemovedFromGroup : durationTime !== 0 property real animationsZoomFactor: latteView ? latteView.animationsZoomFactor : durationTime === 0 ? 1 : 1.65 property real maxZoomFactor: latteView ? latteView.maxZoomFactor : Math.max(zoomFactor, animationsZoomFactor) property real appliedDurationTime: animationsEnabled ? durationTime : 2 property real durationTime: latteView ? latteView.durationTime : plasmoid.configuration.durationTime property real zoomFactor: latteView ? latteView.zoomFactor : ( 1 + (plasmoid.configuration.zoomLevel / 20) ) property int appShadowSize: latteView ? latteView.appShadowSize : Math.ceil(0.12*iconSize) property string appShadowColor: latteView ? latteView.appShadowColor : "#ff080808" property string appShadowColorSolid: latteView ? latteView.appShadowColorSolid : "#ff080808" property alias tasksCount: tasksModel.count property alias hoveredIndex: icList.hoveredIndex property QtObject currentLayout : latteView && latteView.managedLayout ? latteView.managedLayout : null property var badgesForActivate: latteView ? latteView.badgesForActivate : [] property var managedLayoutName: currentLayout ? currentLayout.name : "" 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 onLatteBridgeChanged: { if (latteBridge) { latteBridge.actions.setProperty(plasmoid.id, "latteSideColoringEnabled", false); } } //END Latte Dock Communicator //BEGIN Latte based properties readonly property bool enforceLattePalette: latteBridge && latteBridge.applyPalette && latteBridge.palette readonly property bool latteInEditMode: latteBridge && latteBridge.inEditMode //END Latte based properties Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation Plasmoid.backgroundHints: PlasmaCore.Types.NoBackground signal clearZoomSignal(); signal draggingFinished(); signal hiddenTasksUpdated(); signal launchersUpdatedFor(string launcher); signal presentWindows(variant winIds); signal requestLayout; signal separatorsUpdated(); signal signalActionsBlockHiding(int value); signal signalAnimationsNeedBothAxis(int value); signal signalAnimationsNeedLength(int value); signal signalAnimationsNeedThickness(int value); 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 waitingLauncherRemoved(string launch); 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.configuration.isInLatteDock = true; } else { plasmoid.configuration.isInLatteDock = false; } } Connections { target: plasmoid onLocationChanged: { root.updatePosition(); 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"); } } onLaunchersGroupChanged:{ if( latteView && latteView.editMode) { tasksModel.updateLaunchersList(); } } } Connections{ target: latteView && latteView.universalLayoutManager ? latteView.universalLayoutManager : null onCurrentLayoutNameChanged: root.publishTasksGeometries(); } Connections{ target: icList onHoveredIndexChanged:{ if (latteView && icList.hoveredIndex>-1){ latteView.setHoveredIndex(-1); } } } ///// PlasmaCore.ColorScope{ id: colorScopePalette } Loader { id: indicatorsStandaloneLoader active: !latteView && !plasmoid.configuration.isInLatteDock source: "indicators/Manager.qml" } ///// function initializeHoveredIndex() { icList.hoveredIndex = -1; icList.currentSpot = -1000; } function launchersDropped(urls){ mouseHandler.urlsDroppedOnArea(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= Latte.Types.LayoutLaunchers) { latteView.universalLayoutManager.launchersSignals.validateLaunchersOrder(root.managedLayoutName, plasmoid.id, latteView.launchersGroup, currentLauncherList()); } } } else { plasmoid.configuration.launchers59 = launcherList; } } else { plasmoid.configuration.launchers59 = launcherList; } } onGroupingAppIdBlacklistChanged: { plasmoid.configuration.groupingAppIdBlacklist = groupingAppIdBlacklist; } onGroupingLauncherUrlBlacklistChanged: { plasmoid.configuration.groupingLauncherUrlBlacklist = groupingLauncherUrlBlacklist; } onAnyTaskDemandsAttentionChanged: { if (anyTaskDemandsAttention){ plasmoid.status = PlasmaCore.Types.RequiresAttentionStatus; attentionTimerComponent.createObject(root); } } Component.onCompleted: { ActivitiesTools.launchersOnActivities = root.launchersOnActivities ActivitiesTools.currentActivity = String(activityInfo.currentActivity); ActivitiesTools.plasmoid = plasmoid; //var loadedLaunchers = ActivitiesTools.restoreLaunchers(); ActivitiesTools.importLaunchersToNewArchitecture(); if (currentLayout && latteView.universalSettings && (latteView.launchersGroup === Latte.Types.LayoutLaunchers || latteView.launchersGroup === Latte.Types.GlobalLaunchers)) { if (latteView.launchersGroup === Latte.Types.LayoutLaunchers) { launcherList = latteView.managedLayout.launchers; } else if (latteView.launchersGroup === Latte.Types.GlobalLaunchers) { launcherList = latteView.universalSettings.launchers; } } else { launcherList = plasmoid.configuration.launchers59; } groupingAppIdBlacklist = plasmoid.configuration.groupingAppIdBlacklist; groupingLauncherUrlBlacklist = plasmoid.configuration.groupingLauncherUrlBlacklist; icList.model = tasksModel; tasksStarting = count; ///Plasma 5.9 enforce grouping at all cases if (Latte.WindowSystem.plasmaDesktopVersion >= Latte.WindowSystem.makeVersion(5,9,0)) { groupingWindowTasksThreshold = -1; } } } //! TaskManagerBackend required a groupDialog setting otherwise it crashes. This patch //! sets one just in order not to crash TaskManagerBackend PlasmaCore.Dialog { //ghost group Dialog to not crash TaskManagerBackend id: groupDialogGhost visible: false type: PlasmaCore.Dialog.PopupMenu flags: Qt.WindowStaysOnTopHint hideOnWindowDeactivate: true location: plasmoid.location } TaskManagerApplet.Backend { id: backend taskManagerItem: root toolTipItem: toolTipDelegate highlightWindows: root.highlightWindows onAddLauncher: { tasksModel.requestAddLauncher(url); } Component.onCompleted: { //! In Plasma 5.9 TaskManagerBackend required a groupDialog setting //! otherwise it crashes. //! frameworks 5.29.0 provide id 335104 //! work only after Plasma 5.9 and frameworks 5.29 //! + added a check for groupDialog also when it is present //! in plasma 5.8 (that was introduced after 5.8.5) if (Latte.WindowSystem.frameworksVersion >= 335104 || (groupDialog !== undefined)) { groupDialog = groupDialogGhost; } } } TaskManagerApplet.DragHelper { id: dragHelper dragIconSize: units.iconSizes.medium } TaskManager.VirtualDesktopInfo { id: virtualDesktopInfo } TaskManager.ActivityInfo { id: activityInfo property string previousActivity: "" onCurrentActivityChanged: { root.inActivityChange = true; activityChangeDelayer.start(); } Component.onCompleted: previousActivity = currentActivity; } PlasmaCore.DataSource { id: mpris2Source engine: "mpris2" connectedSources: sources function sourceNameForLauncherUrl(launcherUrl, pid) { if (!launcherUrl || launcherUrl == "") { return ""; } // MPRIS spec explicitly mentions that "DesktopEntry" is with .desktop extension trimmed // Moreover, remove URL parameters, like wmClass (part after the question mark) var desktopFileName = launcherUrl.toString().split('/').pop().split('?')[0].replace(".desktop", "") if (desktopFileName.indexOf("applications:") === 0) { desktopFileName = desktopFileName.substr(13) } for (var i = 0, length = connectedSources.length; i < length; ++i) { var source = connectedSources[i]; // we intend to connect directly, otherwise the multiplexer steals the connection away if (source === "@multiplex") { continue; } var sourceData = data[source]; if (!sourceData || sourceData.DesktopEntry !== desktopFileName) { continue; } if (pid === undefined || sourceData.InstancePid === pid) { return source; } var metadata = sourceData.Metadata; if (metadata) { var kdePid = metadata["kde:pid"]; if (kdePid && pid === kdePid) { return source; } } } return "" } function startOperation(source, op) { var service = serviceForSource(source) var operation = service.operationDescription(op) return service.startOperationCall(operation) } function goPrevious(source) { startOperation(source, "Previous"); } function goNext(source) { startOperation(source, "Next"); } function playPause(source) { startOperation(source, "PlayPause"); } function stop(source) { startOperation(source, "Stop"); } function raise(source) { startOperation(source, "Raise"); } function quit(source) { startOperation(source, "Quit"); } } Loader { id: pulseAudio source: "PulseAudio.qml" active: root.showAudioBadge } ParabolicManager{ id: _parabolicManager } /* IconsModel{ id: iconsmdl }*/ Component{ id: attentionTimerComponent Timer{ id: attentionTimer interval:8500 onTriggered: { plasmoid.status = PlasmaCore.Types.PassiveStatus; destroy(); if (latteView && latteView.debugModeTimers) { console.log("plasmoid timer: attentionTimer called..."); } } Component.onCompleted: { start(); } } } //Timer to check if the mouse is still inside the ListView //IMPORTANT ::: This timer should be used only when the Latte plasmoid //is not inside a Latte dock Timer{ id:checkListHovered repeat:false; interval: 120 property int normalInterval: Math.max(120, 2 * (root.durationTime * 1.2 * units.shortDuration) + 50) onTriggered: { if(root.latteView) console.log("Plasmoid, checkListHoveredTimer was called, even though it shouldn't..."); if (!root.containsMouse()) { icList.directRender = false; root.clearZoom(); } interval = normalInterval; if (latteView && latteView.debugModeTimers) { console.log("plasmoid timer: checkListHovered called..."); } } function startNormal(){ interval = normalInterval; start(); } function startDuration( duration){ interval = duration; start(); } } //! Delayer in order to not activate directRendering when the mouse //! enters until the timer has ended. This way we make sure that the //! zoom-in animations will have ended. Timer{ id:directRenderDelayerForEnteringTimer interval: 3.2 * root.durationTime * units.shortDuration } //this timer restores the draggingPhase flag to false //after a dragging has finished... This delay is needed //in order to not animate any tasks are added after a //dragging Timer { id: restoreDraggingPhaseTimer interval: 150 onTriggered: inDraggingPhase = false; } ///Red Liner!!! show the upper needed limit for animations Rectangle{ anchors.horizontalCenter: !root.vertical ? parent.horizontalCenter : undefined anchors.verticalCenter: root.vertical ? parent.verticalCenter : undefined width: root.vertical ? 1 : 2 * root.iconSize height: root.vertical ? 2 * root.iconSize : 1 color: "red" x: (root.position === PlasmaCore.Types.LeftPositioned) ? neededSpace : parent.width - neededSpace y: (root.position === PlasmaCore.Types.TopPositioned) ? neededSpace : parent.height - neededSpace visible: plasmoid.configuration.zoomHelper property int neededSpace: zoomFactor*(iconSize+lengthMargins) } Item{ id:barLine - /* anchors.bottom: (root.position === PlasmaCore.Types.BottomPositioned) ? parent.bottom : undefined - anchors.top: (root.position === PlasmaCore.Types.TopPositioned) ? parent.top : undefined - anchors.left: (root.position === PlasmaCore.Types.LeftPositioned) ? parent.left : undefined - anchors.right: (root.position === PlasmaCore.Types.RightPositioned) ? parent.right : undefined - - anchors.horizontalCenter: !parent.vertical ? parent.horizontalCenter : undefined - anchors.verticalCenter: parent.vertical ? parent.verticalCenter : undefined */ - width: ( icList.orientation === Qt.Horizontal ) ? icList.width + spacing : smallSize height: ( icList.orientation === Qt.Vertical ) ? icList.height + spacing : smallSize property int spacing: root.iconSize / 2 property int smallSize: Math.max(0.10 * root.iconSize, 16) Behavior on opacity{ NumberAnimation { duration: root.durationTime*units.longDuration } } /// plasmoid's default panel BorderImage{ anchors.fill:parent source: "../images/panel-west.png" border { left:8; right:8; top:8; bottom:8 } opacity: (plasmoid.configuration.showBarLine && !plasmoid.configuration.useThemePanel && !root.forceHidePanel) ? 1 : 0 visible: (opacity == 0) ? false : true horizontalTileMode: BorderImage.Stretch verticalTileMode: BorderImage.Stretch Behavior on opacity{ NumberAnimation { duration: root.durationTime*units.longDuration } } } /// item which is used as anchors for the plasma's theme Item{ id:belower width: (root.position === PlasmaCore.Types.LeftPositioned) ? shadowsSvgItem.margins.left : shadowsSvgItem.margins.right height: (root.position === PlasmaCore.Types.BottomPositioned)? shadowsSvgItem.margins.bottom : shadowsSvgItem.margins.top anchors.top: (root.position === PlasmaCore.Types.BottomPositioned) ? parent.bottom : undefined anchors.bottom: (root.position === PlasmaCore.Types.TopPositioned) ? parent.top : undefined anchors.right: (root.position === PlasmaCore.Types.LeftPositioned) ? parent.left : undefined anchors.left: (root.position === PlasmaCore.Types.RightPositioned) ? parent.right : undefined } /// the current theme's panel PlasmaCore.FrameSvgItem{ id: shadowsSvgItem anchors.bottom: (root.position === PlasmaCore.Types.BottomPositioned) ? belower.bottom : undefined anchors.top: (root.position === PlasmaCore.Types.TopPositioned) ? belower.top : undefined anchors.left: (root.position === PlasmaCore.Types.LeftPositioned) ? belower.left : undefined anchors.right: (root.position === PlasmaCore.Types.RightPositioned) ? belower.right : undefined anchors.horizontalCenter: !root.vertical ? parent.horizontalCenter : undefined anchors.verticalCenter: root.vertical ? parent.verticalCenter : undefined width: root.vertical ? panelSize + margins.left + margins.right: parent.width height: root.vertical ? parent.height : panelSize + margins.top + margins.bottom imagePath: "translucent/widgets/panel-background" prefix:"shadow" opacity: (plasmoid.configuration.showBarLine && plasmoid.configuration.useThemePanel && !root.forceHidePanel) ? 1 : 0 visible: (opacity == 0) ? false : true property int panelSize: ((root.position === PlasmaCore.Types.BottomPositioned) || (root.position === PlasmaCore.Types.TopPositioned)) ? plasmoid.configuration.panelSize + belower.height: plasmoid.configuration.panelSize + belower.width Behavior on opacity{ NumberAnimation { duration: root.durationTime*units.longDuration } } PlasmaCore.FrameSvgItem{ anchors.margins: belower.width-1 anchors.fill:parent imagePath: plasmoid.configuration.transparentPanel ? "translucent/widgets/panel-background" : "widgets/panel-background" } } MouseHandler { id: mouseHandler - anchors.bottom: (root.position === PlasmaCore.Types.BottomPositioned) ? icList.bottom : undefined - anchors.top: (root.position === PlasmaCore.Types.TopPositioned) ? icList.top : undefined - anchors.left: (root.position === PlasmaCore.Types.LeftPositioned) ? icList.left : undefined - anchors.right: (root.position === PlasmaCore.Types.RightPositioned) ? icList.right : undefined + anchors.bottom: (root.position === PlasmaCore.Types.BottomPositioned) ? scrollableList.bottom : undefined + anchors.top: (root.position === PlasmaCore.Types.TopPositioned) ? scrollableList.top : undefined + anchors.left: (root.position === PlasmaCore.Types.LeftPositioned) ? scrollableList.left : undefined + anchors.right: (root.position === PlasmaCore.Types.RightPositioned) ? scrollableList.right : undefined - anchors.horizontalCenter: !root.vertical ? icList.horizontalCenter : undefined - anchors.verticalCenter: root.vertical ? icList.verticalCenter : undefined + anchors.horizontalCenter: !root.vertical ? scrollableList.horizontalCenter : undefined + anchors.verticalCenter: root.vertical ? scrollableList.verticalCenter : undefined width: root.vertical ? maxSize : icList.width height: root.vertical ? icList.height : maxSize target: icList property int maxSize: (((root.hoveredIndex>=0 || dockHoveredIndex>=0 ) || windowPreviewIsShown) && !root.dragSource) ? root.zoomFactor * (root.iconSize + root.thickMargins) : root.iconSize + root.thickMargins function onlyLaunchersInList(list){ return list.every(function (item) { return backend.isApplication(item) }); } function urlsDroppedOnArea(urls){ // If all dropped URLs point to application desktop files, we'll add a launcher for each of them. if (onlyLaunchersInList(urls)) { urls.forEach(function (item) { addLauncher(item); }); return; } if (!hoveredItem) { return; } // DeclarativeMimeData urls is a QJsonArray but requestOpenUrls expects a proper QList. var urlsList = backend.jsonArrayToUrlList(urls); // Otherwise we'll just start a new instance of the application with the URLs as argument, // as you probably don't expect some of your files to open in the app and others to spawn launchers. tasksModel.requestOpenUrls(hoveredItem.modelIndex(), urlsList); } onUrlsDropped: { //! inform synced docks for new dropped launchers if (latteView && latteView.launchersGroup >= Latte.Types.LayoutLaunchers && onlyLaunchersInList(urls)) { latteView.universalLayoutManager.launchersSignals.urlsDropped(root.managedLayoutName, latteView.launchersGroup, urls); return; } //! if the list does not contain only launchers then just open the corresponding //! urls with the relevant app urlsDroppedOnArea(urls); } } + ScrollableList { + id: scrollableList + width: !root.vertical ? Math.min(root.width, icList.width) : thickness + height: root.vertical ? Math.min(root.height, icList.height) : thickness + contentWidth: icList.width + contentHeight: icList.height - ListView { - id:icList - boundsBehavior: Flickable.StopAtBounds + readonly property bool centered: userPanelPosition === Latte.Types.Center + readonly property bool reversed: Qt.application.layoutDirection === Qt.RightToLeft - property int currentSpot : -1000 - property int hoveredIndex : -1 - property int previousCount : 0 + property int thickness: !thickAnimated ? root.thickMargins + root.iconSize : (root.thickMargins + root.iconSize) * root.zoomFactor - property int tasksCount: tasksModel.count + readonly property bool thickAnimated: latteView && (latteView.animationsNeedBothAxis>0 || latteView.animationsNeedThickness>0) - property bool directRender: false + //onCurrentPosChanged: console.log("CP :: "+ currentPos + " icW:"+icList.width + " rw: "+root.width + " w:" +width); - // onTasksCountChanged: updateImplicits(); + alignment: { + if (plasmoid.location === PlasmaCore.Types.LeftEdge) { + if (centered) return Latte.Types.LeftEdgeCenterAlign; + if (root.panelAlignment === Latte.Types.Top) return Latte.Types.LeftEdgeTopAlign; + if (root.panelAlignment === Latte.Types.Bottom) return Latte.Types.LeftEdgeBottomAlign; + } - // property int count: children ? children.length : 0 - /* anchors.bottom: (root.position === PlasmaCore.Types.BottomPositioned) ? parent.bottom : undefined - anchors.top: (root.position === PlasmaCore.Types.TopPositioned) ? parent.top : undefined - anchors.left: (root.position === PlasmaCore.Types.LeftPositioned) ? parent.left : undefined - anchors.right: (root.position === PlasmaCore.Types.RightPositioned) ? parent.right : undefined + if (plasmoid.location === PlasmaCore.Types.RightEdge) { + if (centered) return Latte.Types.RightEdgeCenterAlign; + if (root.panelAlignment === Latte.Types.Top) return Latte.Types.RightEdgeTopAlign; + if (root.panelAlignment === Latte.Types.Bottom) return Latte.Types.RightEdgeBottomAlign; + } - anchors.horizontalCenter: !root.vertical ? parent.horizontalCenter : undefined - anchors.verticalCenter: root.vertical ? parent.verticalCenter : undefined */ + if (plasmoid.location === PlasmaCore.Types.BottomEdge) { + if (centered) return Latte.Types.BottomEdgeCenterAlign; - width: !root.vertical ? contentWidth : mouseHandler.maxSize - height: root.vertical ? contentHeight : mouseHandler.maxSize + if ((root.panelAlignment === Latte.Types.Left && !reversed) + || (root.panelAlignment === Latte.Types.Right && reversed)) { + return Latte.Types.BottomEdgeLeftAlign; + } - orientation: Qt.Horizontal + if ((root.panelAlignment === Latte.Types.Right && !reversed) + || (root.panelAlignment === Latte.Types.Left && reversed)) { + return Latte.Types.BottomEdgeRightAlign; + } + } - delegate: Task.TaskItem{} + if (plasmoid.location === PlasmaCore.Types.TopEdge) { + if (centered) return Latte.Types.TopEdgeCenterAlign; - /* Rectangle{ - anchors.fill: parent - border.width: 1 - border.color: "red" - color: "transparent" - } */ + if ((root.panelAlignment === Latte.Types.Left && !reversed) + || (root.panelAlignment === Latte.Types.Right && reversed)) { + return Latte.Types.TopEdgeLeftAlign; + } - //the duration of this animation should be as small as possible - //it fixes a small issue with the dragging an item to change it's - //position, if the duration is too big there is a point in the - //list that an item is going back and forth too fast + if ((root.panelAlignment === Latte.Types.Right && !reversed) + || (root.panelAlignment === Latte.Types.Left && reversed)) { + return Latte.Types.TopEdgeRightAlign; + } + } - //more of a trouble - moveDisplaced: Transition { - NumberAnimation { properties: "x,y"; duration: root.durationTime*units.longDuration; easing.type: Easing.Linear } + return Latte.Types.BottomEdgeCenterAlign; } - ///this transition can not be used with dragging !!!! I breaks - ///the lists indexes !!!!! - /* move: Transition { - NumberAnimation { properties: "x,y"; duration: 400; easing.type: Easing.Linear } - } */ + layer.enabled: contentsExceed && root.scrollingEnabled + layer.effect: OpacityMask { + maskSource: ScrollOpacityMask{ + width: scrollableList.width + root.lengthMargins + height: scrollableList.height + } + } + + Rectangle { + id: listViewBase + x: !root.vertical ? icList.width / 2 : 0 + y: !root.vertical ? 0 : icList.height / 2 + width: !root.vertical ? 1 : scrollableList.width + height: !root.vertical ? scrollableList.height : 1 + color: "transparent" + border.width: 1 + border.color: "transparent"//"purple" + + ListView { + id:icList + width: !root.vertical ? contentWidth : mouseHandler.maxSize + height: root.vertical ? contentHeight : mouseHandler.maxSize + boundsBehavior: Flickable.StopAtBounds + orientation: Qt.Horizontal + delegate: Task.TaskItem{} - function childAtPos(x, y){ - var tasks = icList.contentItem.children; + property int currentSpot : -1000 + property int hoveredIndex : -1 + property int previousCount : 0 - for(var i=0; i=choords.x) && (x<=choords.x+task.width) - && (y>=choords.y) && (y<=choords.y+task.height)){ - return task; + //the duration of this animation should be as small as possible + //it fixes a small issue with the dragging an item to change it's + //position, if the duration is too big there is a point in the + //list that an item is going back and forth too fast + + //more of a trouble + moveDisplaced: Transition { + NumberAnimation { properties: "x,y"; duration: root.durationTime*units.longDuration; easing.type: Easing.Linear } } - } - return null; - } + ///this transition can not be used with dragging !!!! I breaks + ///the lists indexes !!!!! + ///move: Transition { + /// NumberAnimation { properties: "x,y"; duration: 400; easing.type: Easing.Linear } + ///} - function childAtIndex(position) { - var tasks = icList.contentItem.children; + function childAtPos(x, y){ + var tasks = icList.contentItem.children; - if (position < 0) - return; + for(var i=0; i=choords.x) && (x<=choords.x+task.width) + && (y>=choords.y) && (y<=choords.y+task.height)){ + return task; + } + } + + return null; } - } - return undefined; + function childAtIndex(position) { + var tasks = icList.contentItem.children; + + if (position < 0) + return; + + for(var i=0; i=0; --i) { if (currentLaunchers[i] !== launchers[i]) { var p = launcherValidPos(currentLaunchers[i]); if (p === -1) { console.log("No pos found for :"+currentLaunchers[i] + " at: "+launchers); restart(); return; } console.log(" moving:" +i + " _ " + p ); tasksModel.move(i, p); restart(); return; } } } console.log("why we reached ??? "); console.log("CURRENT ::: " + currentLaunchers); console.log("VALID ::: " + launchers); } } } ///////// //// functions function movePanel(obj, newPosition){ var bLine = obj; if (newPosition === PlasmaCore.Types.BottomPositioned){ bLine.anchors.horizontalCenter = bLine.parent.horizontalCenter; bLine.anchors.verticalCenter = undefined; bLine.anchors.bottom = bLine.parent.bottom; bLine.anchors.top = undefined; bLine.anchors.left = undefined; bLine.anchors.right = undefined; } else if (newPosition === PlasmaCore.Types.TopPositioned){ bLine.anchors.horizontalCenter = bLine.parent.horizontalCenter; bLine.anchors.verticalCenter = undefined; bLine.anchors.bottom = undefined; bLine.anchors.top = bLine.parent.top; bLine.anchors.left = undefined; bLine.anchors.right = undefined; } else if (newPosition === PlasmaCore.Types.LeftPositioned){ bLine.anchors.horizontalCenter = undefined; bLine.anchors.verticalCenter = bLine.parent.verticalCenter; bLine.anchors.bottom = undefined; bLine.anchors.top = undefined; bLine.anchors.left = bLine.parent.left; bLine.anchors.right = undefined; } else if (newPosition === PlasmaCore.Types.RightPositioned){ bLine.anchors.horizontalCenter = undefined; bLine.anchors.verticalCenter = bLine.parent.verticalCenter; bLine.anchors.bottom = undefined; bLine.anchors.top = undefined; bLine.anchors.left =undefined; bLine.anchors.right = bLine.parent.right; } } property int ncounter:0 function updateImplicits(){ if(icList.previousCount !== icList.count){ icList.previousCount = icList.count; var zoomedLength = Math.floor( 1.2 * (iconSize+thickMargins) * (root.zoomFactor)); var bigAxis = (tasksModel.count-1) * (iconSize+thickMargins) + zoomedLength; var smallAxis = zoomedLength; var clearBigAxis = tasksModel.count * (iconSize+thickMargins) + (barLine.spacing/2); var clearSmallAxis = iconSize+thickMargins; // debugging code // ncounter++; // console.log("Implicits______ "+ncounter+". - "+tasksModel.count); if (root.vertical){ root.implicitWidth = smallAxis; root.implicitHeight = bigAxis; root.clearWidth = clearSmallAxis; root.clearHeight = clearBigAxis; } else{ root.implicitWidth = bigAxis; root.implicitHeight = smallAxis; root.clearWidth = clearBigAxis; root.clearHeight = clearSmallAxis; } iconGeometryTimer.restart(); } } PlasmaComponents.Button{ id: orientationBtn text:"Orientation" anchors.centerIn: parent visible: root.debugLocation onClicked:{ switch(root.position){ case PlasmaCore.Types.BottomPositioned: root.newLocationDebugUse = PlasmaCore.Types.LeftEdge; break; case PlasmaCore.Types.LeftPositioned: root.newLocationDebugUse = PlasmaCore.Types.TopEdge; break; case PlasmaCore.Types.TopPositioned: root.newLocationDebugUse = PlasmaCore.Types.RightEdge; break; case PlasmaCore.Types.RightPositioned: root.newLocationDebugUse = PlasmaCore.Types.BottomEdge; break; } updatePosition(); } } function addInternalSeparatorAtPos(pos) { var separatorName = parabolicManager.freeAvailableSeparatorName(); if (separatorName !== "") { parabolicManager.addLauncherToBeMoved(separatorName, Math.max(0,pos)); if (latteView && latteView.launchersGroup >= Latte.Types.LayoutLaunchers) { latteView.universalLayoutManager.launchersSignals.addLauncher(root.managedLayoutName, latteView.launchersGroup, separatorName); } else { tasksModel.requestAddLauncher(separatorName); } } } // This is called by dockcorona in response to a Meta+number shortcut. function activateTaskAtIndex(index) { if (typeof index !== "number") { return; } var tasks = icList.contentItem.children; //! this is used to bypass the internal separators if they exist var confirmedIndex = parabolicManager.realTaskIndex(index - 1); for(var i=0; i=0 ? ident1.substring(n + 1) : identifier; for(var i=0; i= 0) { return badgers[i]; } } } function updateBadge(identifier, value) { var tasks = icList.contentItem.children; var identifierF = identifier.concat(".desktop"); for(var i=0; i= 0) { task.badgeIndicator = value === "" ? 0 : Number(value); var badge = getBadger(identifierF); if (badge) { badge.value = value; } else { badgers.push({id: identifierF, value: value}); } } } } function getLauncherList() { return plasmoid.configuration.launchers59; } //! BEGIN ::: external launchers signals in order to update the tasks model function extSignalAddLauncher(group, launcher) { if (group === latteView.launchersGroup) { tasksModel.requestAddLauncher(launcher); launchersUpdatedFor(launcher); tasksModel.syncLaunchers(); } } function extSignalRemoveLauncher(group, launcher) { if (group === latteView.launchersGroup) { root.launcherForRemoval = launcher; tasksModel.requestRemoveLauncher(launcher); launchersUpdatedFor(launcher); tasksModel.syncLaunchers(); } } function extSignalAddLauncherToActivity(group, launcher, activity) { if (group === latteView.launchersGroup) { var launcherActivities = tasksModel.launcherActivities(launcher); if (activity !== tasksModel.activity && (launcherActivities[0] === "00000000-0000-0000-0000-000000000000")) { root.launcherForRemoval = launcher; } tasksModel.requestAddLauncherToActivity(launcher, activity); launchersUpdatedFor(launcher); tasksModel.syncLaunchers(); } } function extSignalRemoveLauncherFromActivity(group, launcher, activity) { if (group === latteView.launchersGroup) { if (activity === tasksModel.activity) { root.launcherForRemoval = launcher; } tasksModel.requestRemoveLauncherFromActivity(launcher, activity); launchersUpdatedFor(launcher); tasksModel.syncLaunchers(); } } function extSignalUrlsDropped(group, urls) { if (group === latteView.launchersGroup) { mouseHandler.urlsDroppedOnArea(urls); } } function extSignalMoveTask(group, from, to) { if (group === latteView.launchersGroup && !root.dragSource) { tasksModel.move(from, to); parabolicManager.updateTasksEdgesIndexes(); root.separatorsUpdated(); tasksModel.syncLaunchers(); } } function extSignalValidateLaunchersOrder(group, launchers) { if (group === latteView.launchersGroup && !root.dragSource) { launchersOrderValidatorTimer.stop(); launchersOrderValidatorTimer.launchers = launchers; launchersOrderValidatorTimer.start(); } } //! END ::: external launchers signals in order to update the tasks model //! it is used to add the fake desktop file which represents //! the separator (fake launcher) function addSeparator(pos){ var separatorName = parabolicManager.freeAvailableSeparatorName(); if (separatorName !== "") { parabolicManager.addLauncherToBeMoved(separatorName, Math.max(0,pos)); if (latteView && latteView.launchersGroup >= Latte.Types.LayoutLaunchers) { latteView.universalLayoutManager.launchersSignals.addLauncher(latteView.launchersGroup, separatorName); } else { tasksModel.requestAddLauncher(separatorName); } } } function removeLastSeparator(){ var separatorName = parabolicManager.lastPresentSeparatorName(); if (separatorName !== "") { if (latteView && latteView.launchersGroup >= Latte.Types.LayoutLaunchers) { latteView.universalLayoutManager.launchersSignals.removeLauncher(root.managedLayoutName, latteView.launchersGroup, separatorName); } else { root.launcherForRemoval = separatorName; tasksModel.requestRemoveLauncher(separatorName); } } } //! show/hide tasks numbered badges e.g. from global shortcuts function setShowTaskShortcutBadges(showBadges){ showTaskShortcutBadges = showBadges; } //! setup the tasks first index based on the fact that this is a plasmoid //! and applets could exist before it function setTasksBaseIndex(base){ tasksBaseIndex = base; } function previewContainsMouse() { if(toolTipDelegate && toolTipDelegate.containsMouse && toolTipDelegate.parentTask) { return true; } else { return false; } } function containsMouse(){ //console.log("s1..."); if (disableRestoreZoom && (root.contextMenu || windowsPreviewDlg.visible)) { return; } else { disableRestoreZoom = false; } //if (previewContainsMouse()) // windowsPreviewDlg.hide(4); if (previewContainsMouse()) return true; //console.log("s3..."); var tasks = icList.contentItem.children; for(var i=0; i0) { url = url.substring( 0, url.indexOf("?iconData=" ) ); } tasksModel.requestAddLauncher(url); launchersUpdatedFor(url); tasksModel.syncLaunchers(); } function resetDragSource() { dragSource.z = 0; dragSource = null; } function setGlobalDirectRender(value) { if (waitingLaunchers.length > 0) return; if (latteView) { latteView.setGlobalDirectRender(value); } else { if (value === true) { if (root.containsMouse()) { icList.directRender = true; } else { // console.log("direct render true ignored..."); } } else { icList.directRender = false; } } } function startCheckRestoreZoomTimer(duration) { if (latteView) { latteView.startCheckRestoreZoomTimer(); } else { if (duration > 0) { checkListHovered.startDuration(duration); } else { checkListHovered.startNormal(); } } } function stopCheckRestoreZoomTimer() { if (latteView) { latteView.stopCheckRestoreZoomTimer(); } else { checkListHovered.stop(); } } function startDirectRenderDelayerDuringEntering(){ if (latteView) { latteView.startDirectRenderDelayerDuringEntering(); } else { directRenderDelayerForEnteringTimer.start(); } } ///REMOVE /*function createContextMenu(task) { var menu = root.contextMenuComponent.createObject(task); menu.visualParent = task; menu.mpris2Source = mpris2Source; menu.activitiesCount = activityModelInstance.count; return menu; }*/ function createContextMenu(rootTask, modelIndex, args) { var initialArgs = args || {} initialArgs.visualParent = rootTask; initialArgs.modelIndex = modelIndex; initialArgs.mpris2Source = mpris2Source; initialArgs.backend = backend; root.contextMenu = root.contextMenuComponent.createObject(rootTask, initialArgs); return root.contextMenu; } Component.onCompleted: { updatePosition(); root.presentWindows.connect(backend.presentWindows); root.windowsHovered.connect(backend.windowsHovered); dragHelper.dropped.connect(resetDragSource); } Component.onDestruction: { root.presentWindows.disconnect(backend.presentWindows); root.windowsHovered.disconnect(backend.windowsHovered); dragHelper.dropped.disconnect(resetDragSource); } //BEGIN states //user set Panel Positions // 0-Center, 1-Left, 2-Right, 3-Top, 4-Bottom states: [ ///Bottom Edge State { name: "bottomCenter" when: (root.position === PlasmaCore.Types.BottomPosition && userPanelPosition===Latte.Types.Center) AnchorChanges { target: barLine anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } AnchorChanges { target: icList anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } }, State { name: "bottomLeft" when: (root.position === PlasmaCore.Types.BottomPosition && userPanelPosition===Latte.Types.Left) AnchorChanges { target: barLine anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: icList anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } }, State { name: "bottomRight" when: (root.position === PlasmaCore.Types.BottomPosition && userPanelPosition===Latte.Types.Right) AnchorChanges { target: barLine anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: icList anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } }, ///Top Edge State { name: "topCenter" when: (root.position === PlasmaCore.Types.TopPosition && userPanelPosition===Latte.Types.Center) AnchorChanges { target: barLine anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } AnchorChanges { target: icList anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } }, State { name: "topLeft" when: (root.position === PlasmaCore.Types.TopPosition && userPanelPosition===Latte.Types.Left) AnchorChanges { target: barLine anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: icList anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } }, State { name: "topRight" when: (root.position === PlasmaCore.Types.TopPosition && userPanelPosition===Latte.Types.Right) AnchorChanges { target: barLine anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: icList anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } }, ////Left Edge State { name: "leftCenter" when: (root.position === PlasmaCore.Types.LeftPosition && userPanelPosition===Latte.Types.Center) AnchorChanges { target: barLine anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } AnchorChanges { target: icList anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } }, State { name: "leftTop" when: (root.position === PlasmaCore.Types.LeftPosition && userPanelPosition===Latte.Types.Top) AnchorChanges { target: barLine anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: icList anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } }, State { name: "leftBottom" when: (root.position === PlasmaCore.Types.LeftPosition && userPanelPosition===Latte.Types.Bottom) AnchorChanges { target: barLine anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: icList anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } }, ///Right Edge State { name: "rightCenter" when: (root.position === PlasmaCore.Types.RightPosition && userPanelPosition===Latte.Types.Center) AnchorChanges { target: barLine anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } AnchorChanges { target: icList anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } }, State { name: "rightTop" when: (root.position === PlasmaCore.Types.RightPosition && userPanelPosition===Latte.Types.Top) AnchorChanges { target: barLine anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: icList anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } }, State { name: "rightBottom" when: (root.position === PlasmaCore.Types.RightPosition && userPanelPosition===Latte.Types.Bottom) AnchorChanges { target: barLine anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: icList anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } } ] //END states } diff --git a/plasmoid/package/contents/ui/task/TaskItem.qml b/plasmoid/package/contents/ui/task/TaskItem.qml index 430177a0..20732872 100644 --- a/plasmoid/package/contents/ui/task/TaskItem.qml +++ b/plasmoid/package/contents/ui/task/TaskItem.qml @@ -1,1542 +1,1549 @@ /* * 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.0 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.plasma.private.taskmanager 0.1 as TaskManagerApplet import org.kde.latte 0.2 as Latte import "animations" as TaskAnimations import "indicator" as Indicator MouseArea{ id: taskItem visible: false //true//(isStartup && root.durationTime !== 0) ? false : true anchors.bottom: (root.position === PlasmaCore.Types.BottomPositioned) ? parent.bottom : undefined anchors.top: (root.position === PlasmaCore.Types.TopPositioned) ? parent.top : undefined anchors.left: (root.position === PlasmaCore.Types.LeftPositioned) ? parent.left : undefined anchors.right: (root.position === PlasmaCore.Types.RightPositioned) ? parent.right : undefined objectName: "TaskItem" width: { if (!visible) return 0; if (isSeparator) return root.vertical ? root.iconSize + root.thickMargins : (root.dragSource || !root.parabolicEffectEnabled ? 5+root.lengthMargins : 0); if (root.vertical) { return wrapper.width; } else { return hiddenSpacerLeft.width+wrapper.width+hiddenSpacerRight.width; } } /*onWidthChanged: { console.log("T: " + itemIndex + " - " + launcherUrl + " - " + width + " _ "+ hiddenSpacerLeft.width + " _ " + wrapper.width + " _ " + hiddenSpacerRight.width); }*/ height: { if (!visible) return 0; if (isSeparator) return !root.vertical ? root.iconSize + root.thickMargins : (root.dragSource || !root.parabolicEffectEnabled ? 5+root.lengthMargins: 0); if (root.vertical) { return hiddenSpacerLeft.height + wrapper.height + hiddenSpacerRight.height; } else { return wrapper.height; } } acceptedButtons: Qt.LeftButton | Qt.MidButton | Qt.RightButton hoverEnabled: visible && (!inAnimation) && (!IsStartup) && (!root.taskInAnimation) &&(!inBouncingAnimation) && !isSeparator // hoverEnabled: false //opacity : isSeparator && (hiddenSpacerLeft.neighbourSeparator || hiddenSpacerRight.neighbourSeparator) ? 0 : 1 property bool buffersAreReady: false property bool delayingRemove: ListView.delayRemove property bool scalesUpdatedOnce: false //states that exist in windows in a Group of windows property bool hasActive: isActive property bool hasMinimized: (IsGroupParent === true) ? subWindows.hasMinimized : isMinimized property bool hasShown: (IsGroupParent === true) ? subWindows.hasShown : !isMinimized && isWindow property bool inAttention: isDemandingAttention && plasmoid.status === PlasmaCore.Types.RequiresAttentionStatus ? true : false /*animations flags*/ property bool inAnimation: true property bool inAddRemoveAnimation: true property bool inAttentionAnimation: false property bool inBlockingAnimation: false property bool inBouncingAnimation: false property bool inFastRestoreAnimation: false property bool inMimicParabolicAnimation: false property bool inNewWindowAnimation: false property real mimicParabolicScale: -1 property bool inPopup: false property bool inRemoveStage: false property bool isAbleToShowPreview: true property bool isActive: (IsActive === true) ? true : false property bool isDemandingAttention: (IsDemandingAttention === true) ? true : false property bool isDragged: false property bool isGroupable: (IsGroupable === true) ? true : false property bool isGroupParent: (IsGroupParent === true) ? true : false property bool isForcedHidden: false property bool isLauncher: (IsLauncher === true) ? true : false property bool isMinimized: (IsMinimized === true) ? true : false property bool isSeparator: false property bool isStartup: (IsStartup === true) ? true : false property bool isWindow: (IsWindow === true) ? true : false property bool isZoomed: false property bool canPublishGeometries: (isWindow || isStartup || isGroupParent) && visible && width>=root.iconSize && height>=root.iconSize && !taskItem.delayingRemove && (wrapper.mScale===1 || wrapper.mScale===root.zoomFactor) //don't publish during zoomFactor property bool pressed: false property bool wheelIsBlocked: false property int animationTime: (animationsEnabled ? root.durationTime : 2) * (1.2 *units.shortDuration) property int badgeIndicator: 0 //it is used from external apps property int hoveredIndex: icList.hoveredIndex property int itemIndex: index property int lastValidIndex: -1 //used for the removal animation property int lastButtonClicked: -1; property int pressX: -1 property int pressY: -1 property int resistanceDelay: 450 property int spacersMaxSize: Math.max(0,Math.ceil(0.55*root.iconSize) - root.lengthMargins) property int windowsCount: subWindows.windowsCount property int windowsMinimizedCount: subWindows.windowsMinimized property string activity: tasksModel.activity readonly property var m: model readonly property int pid: model && model.AppPid ? model.AppPid : -1 readonly property string appName: model && model.AppName ? model.AppName : "" property string modelLauncherUrl: (LauncherUrlWithoutIcon && LauncherUrlWithoutIcon !== null) ? LauncherUrlWithoutIcon : "" property string modelLauncherUrlWithIcon: (LauncherUrl && LauncherUrl !== null) ? LauncherUrl : "" property string launcherUrl: "" property string launcherUrlWithIcon: "" property string launcherName: "" property Item tooltipVisualParent: wrapper.titleTooltipVisualParent property Item previewsVisualParent: wrapper.previewsTooltipVisualParent property Item wrapperAlias: wrapper onModelLauncherUrlChanged: { if (modelLauncherUrl !== ""){ launcherUrl = modelLauncherUrl; //!extract the launcherName if possible var nameStarts = launcherUrl.lastIndexOf("/"); if (nameStarts === -1){ nameStarts = launcherUrl.lastIndexOf(":"); } var nameEnds = launcherUrl.lastIndexOf(".desktop"); if (nameStarts!==-1 && nameEnds!==-1 && nameStarts 0 && !isLauncher readonly property bool playingAudio: hasAudioStream && audioStreams.some(function (item) { return !item.corked }) readonly property bool muted: hasAudioStream && audioStreams.every(function (item) { return item.muted }) readonly property int volume: { if (!hasAudioStream){ return 0; } var maxVolume = 0; for (var i=0; i maxVolume) maxVolume = audioStreams[i].volume; } return maxVolume; } ////// property QtObject contextMenu: null property QtObject draggingResistaner: null property QtObject hoveredTimerObj: null signal groupWindowAdded(); signal groupWindowRemoved(); signal checkWindowsStates(); Behavior on opacity { // NumberAnimation { duration: (IsStartup || (IsLauncher) ) ? 0 : 400 } NumberAnimation { duration: root.durationTime*units.longDuration } } SubWindows{ id: subWindows property int previousCount: 0 onWindowsCountChanged: { if (root.showWindowsOnlyFromLaunchers && !root.indicatorsEnabled) { return; } if ((windowsCount >= 2) && (windowsCount > previousCount) && !(taskItem.containsMouse || parabolicManager.neighbourIsHovered(itemIndex)) ){ if(root.dragSource == null) taskItem.groupWindowAdded(); } else if ((windowsCount >=1) &&(windowsCount < previousCount)){ //sometimes this is triggered in dragging with no reason if(root.dragSource == null && !taskItem.delayingRemove) taskItem.groupWindowRemoved(); } if (windowsCount>=1) { taskItem.slotPublishGeometries(); } //! workaround in order to update correctly the previousCount //! windowsCount can not return to zero because is such case //! the window task is removed and the launcher is added from //! libtaskmanager if (windowsCount>=1) { previousCount = windowsCount; } } } Loader { id: isSeparatorRectangle active: (opacityN>0) width: taskItem.width height: taskItem.height anchors.centerIn: separatorItem property real opacityN: isSeparator && root.contextMenu && root.contextMenu.visualParent === taskItem ? 1 : 0 Behavior on opacityN { NumberAnimation { duration: root.durationTime*units.longDuration } } sourceComponent: Rectangle{ anchors.fill: parent opacity: isSeparatorRectangle.opacityN radius: 3 property color tempColor: theme.highlightColor color: tempColor border.width: 1 border.color: theme.highlightColor onTempColorChanged: tempColor.a = 0.35; } } Item{ id:separatorItem anchors.centerIn: parent opacity: separatorShadow.active || forceHiddenState ? 0 : 0.4 visible: taskItem.isSeparator width: root.vertical ? root.iconSize : (root.dragSource || root.editMode) ? 5+root.lengthMargins: 1 height: !root.vertical ? root.iconSize : (root.dragSource || root.editMode) ? 5+root.lengthMargins: 1 property bool forceHiddenState: false Behavior on opacity { NumberAnimation { duration: root.durationTime*units.longDuration } } function updateForceHiddenState() { if (!isSeparator || root.editMode || root.dragSource) { forceHiddenState = false; } else { var firstPosition = (index>=0) && (index < parabolicManager.firstRealTaskIndex); var sepNeighbour = taskItem.hasNeighbourSeparator(index-1, false); var firstSepFromLastSeparatorsGroup = (index>=0) && (index > parabolicManager.lastRealTaskIndex); forceHiddenState = (firstPosition || sepNeighbour || firstSepFromLastSeparatorsGroup); } } Component.onCompleted: { updateForceHiddenState(); root.hiddenTasksUpdated.connect(updateForceHiddenState); } Component.onDestruction: { root.hiddenTasksUpdated.disconnect(updateForceHiddenState); } onForceHiddenStateChanged: root.separatorsUpdated(); Connections{ target: root onEditModeChanged: separatorItem.updateForceHiddenState(); onDragSourceChanged: separatorItem.updateForceHiddenState(); onSeparatorsUpdated: separatorItem.updateForceHiddenState(); //! During dock sliding-in because the parabolic effect isnt trigerred //! immediately but we wait first the dock to go to its final normal //! place we might miss the activation of the parabolic effect. //! By catching that signal we are trying to solve this. onDockIsShownCompletelyChanged: { if (dockIsShownCompletely && taskItem.containsMouse) { if (root.vertical) { taskItem.mousePosChanged(taskItem.mouseY); } else { taskItem.mousePosChanged(taskItem.mouseX); } } } onGlobalDirectRenderChanged:{ if (root.globalDirectRender && restoreAnimation.running) { // console.log("Cleat Task Scale !!!!"); restoreAnimation.stop(); } } onShowWindowsOnlyFromLaunchersChanged: { if (!root.editMode) { return; } taskItem.updateVisibilityBasedOnLaunchers(); } onInActivityChangeChanged: { if (root.showWindowsOnlyFromLaunchers && !root.inActivityChange) { taskItem.updateVisibilityBasedOnLaunchers(); } } } Rectangle { anchors.centerIn: parent width: root.vertical ? root.iconSize - 4 : 1 height: !root.vertical ? root.iconSize - 4 : 1 color: enforceLattePalette ? latteBridge.palette.textColor : theme.textColor } } ///Shadow in tasks Loader{ id: separatorShadow anchors.fill: separatorItem active: root.enableShadows && isSeparator opacity: separatorItem.forceHiddenState ? 0 : 0.4 Behavior on opacity { NumberAnimation { duration: root.durationTime*units.longDuration } } sourceComponent: DropShadow{ anchors.fill: parent color: root.appShadowColor fast: true samples: 2 * radius source: separatorItem radius: root.appShadowSize verticalOffset: 2 } } /* Rectangle{ anchors.fill: parent color: "transparent" border.width: 1 border.color: "blue" } */ Flow{ id: taskFlow width: parent.width height: parent.height // 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.Loader{ id: indicatorBackLayer level: Indicator.LevelOptions { isBackground: true bridge: indicatorBridge } } Wrapper{id: wrapper} Indicator.Loader{ id: indicatorFrontLayer level: Indicator.LevelOptions { isForeground: true bridge: indicatorBridge } } } // a hidden spacer on the right for the last item to add stability HiddenSpacer{ id:hiddenSpacerRight; rightSpacer: true } }// Flow with hidden spacers inside /*Rectangle{ anchors.fill: taskFlow color: "transparent" border.width: 1 border.color: "blue" }*/ Component { id: taskInitComponent Timer { id: timer interval: 800 repeat: false onTriggered: { // taskItem.hoverEnabled = true; slotPublishGeometries(); if (latteView && latteView.debugModeTimers) { console.log("plasmoid timer: taskInitComponentTimer called..."); } timer.destroy(); } Component.onCompleted: timer.start() } } ////// Values Changes ///// //restore scales when there is no zoom factor for that item or //the mouse is out of the ListView // onItemIndexChanged: { // } onAppNameChanged: updateAudioStreams() onPidChanged: updateAudioStreams() onHasAudioStreamChanged: updateAudioStreams() onCanPublishGeometriesChanged: { if (canPublishGeometries) { slotPublishGeometries(); taskInitComponent.createObject(taskItem); } } onHoveredIndexChanged: { var distanceFromHovered = Math.abs(index - icList.hoveredIndex); /*if( (distanceFromHovered > 1) && (hoveredIndex !== -1)){ if(!isDragged) wrapper.mScale = 1; }*/ if (distanceFromHovered >= 1 && !inAttentionAnimation && !inFastRestoreAnimation && !inMimicParabolicAnimation) { hiddenSpacerLeft.nScale = 0; hiddenSpacerRight.nScale = 0; } } onItemIndexChanged: { if (isSeparator) { root.separatorsUpdated(); } if (itemIndex>=0) lastValidTimer.start(); } onLastValidIndexChanged: { if (lastValidIndex>=0 && lastValidIndex parabolicManager.lastRealTaskIndex)) { parabolicManager.updateTasksEdgesIndexes(); } } if (parabolicManager.hasInternalSeparator) { root.separatorsUpdated(); } } onIsDraggedChanged: { if(isDragged && (!root.editMode)){ root.dragSource = taskItem; dragHelper.startDrag(taskItem, model.MimeType, model.MimeData, model.LauncherUrlWithoutIcon, model.decoration); pressX = -1; pressY = -1; } } onIsMinimizedChanged: { checkWindowsStates(); } onIsActiveChanged: { checkWindowsStates(); } onIsForcedHiddenChanged: root.hiddenTasksUpdated(); onIsSeparatorChanged: { if (isSeparator) { root.separatorsUpdated(); if (parabolicManager.isLauncherToBeMoved(launcherUrl) && itemIndex>=0) { parabolicManager.moveLauncherToCorrectPos(launcherUrl, itemIndex); } } else { root.separatorsUpdated(); } } onLauncherUrlChanged: updateBadge(); ////// End of Values Changes ///// ///////////////// Mouse Area Events /////////////////// onEntered: { root.stopCheckRestoreZoomTimer(); if (restoreAnimation.running) { restoreAnimation.stop(); } - // console.log("entered task:" + icList.hoveredIndex); if (icList.hoveredIndex === -1 && root.dockHoveredIndex ===-1) { root.startDirectRenderDelayerDuringEntering(); } if ((icList.hoveredIndex !== itemIndex) && isLauncher && windowsPreviewDlg.visible) { windowsPreviewDlg.hide(1); } if (!latteView || (latteView && !(latteView.dockIsHidden || latteView.inSlidingIn || latteView.inSlidingOut))){ icList.hoveredIndex = index; } if (root.latteView && !root.showPreviews && root.titleTooltips){ showTitleTooltip(); } //! show previews if enabled if(isAbleToShowPreview && ((root.showPreviews && windowsPreviewDlg.activeItem !== taskItem) || root.highlightWindows)){ if (hoveredTimerObj) { //! don't delay showing preview in normal states, //! that is when the dock wasn't hidden if (!hoveredTimerObj.running) { hoveredTimerObj.start(); } } else { if (!root.disableAllWindowsFunctionality) { hoveredTimerObj = hoveredTimerComponent.createObject(taskItem); } } } if (root.latteView && root.latteView.isHalfShown) { return; } } // IMPORTANT: This must be improved ! even for small milliseconds it reduces performance onExited: { scalesUpdatedOnce = false; isAbleToShowPreview = true; if (root.latteView && (!root.showPreviews || (root.showPreviews && isLauncher))){ root.latteView.hideTooltipLabel(); } if(taskItem.contextMenu && taskItem.contextMenu.status == PlasmaComponents.DialogStatus.Open){ ///don't check to restore zooms } else{ if(!inAnimation){ root.startCheckRestoreZoomTimer(); } } /* if(draggingResistaner != null){ draggingResistaner.destroy(); draggingResistaner = null; isDragged = false; }*/ } //! mouseX-Y values are delayed to be updated onEntered events and at the same time //! onPositionChanged signal may be delayed. we can fix this by don't delay at all //! when mouseX-Y is updated based on the plasmoid formFactor function mousePosChanged(mousePos) { if (mousePos<0 || (inBlockingAnimation && !(inAttentionAnimation||inFastRestoreAnimation||inMimicParabolicAnimation))) return; root.stopCheckRestoreZoomTimer(); if (root.latteView && root.latteView.isHalfShown) { return; } if((inAnimation == false)&&(!root.taskInAnimation)&&(!root.disableRestoreZoom) && hoverEnabled){ if (icList.hoveredIndex === -1 && root.dockHoveredIndex ===-1) { root.startDirectRenderDelayerDuringEntering(); } if (!latteView || (latteView && !(latteView.dockIsHidden || latteView.inSlidingIn || latteView.inSlidingOut))){ icList.hoveredIndex = index; } if (!root.globalDirectRender && !root.directRenderDelayerIsRunning) { root.setGlobalDirectRender(true); } if( ((wrapper.mScale == 1 || wrapper.mScale === root.zoomFactor) && !root.globalDirectRender) || root.globalDirectRender || !scalesUpdatedOnce) { if(root.dragSource == null){ var step = Math.abs(icList.currentSpot-mousePos); if (step >= root.animationStep){ icList.currentSpot = mousePos; wrapper.calculateScales(mousePos); } } } } } onMouseXChanged: { if (!root.vertical) { mousePosChanged(mouseX); } } onMouseYChanged: { if (root.vertical) { mousePosChanged(mouseY); } } onPositionChanged: { if ((inBlockingAnimation && !(inAttentionAnimation||inFastRestoreAnimation||inMimicParabolicAnimation))) return; if (root.latteView && root.latteView.isHalfShown) { return; } if((inAnimation == false)&&(!root.taskInAnimation)&&(!root.disableRestoreZoom) && hoverEnabled){ // mouse.button is always 0 here, hence checking with mouse.buttons if (pressX != -1 && mouse.buttons == Qt.LeftButton && isDragged && dragHelper.isDrag(pressX, pressY, mouse.x, mouse.y) ) { root.dragSource = taskItem; dragHelper.startDrag(taskItem, model.MimeType, model.MimeData, model.LauncherUrlWithoutIcon, model.decoration); pressX = -1; pressY = -1; } } } onContainsMouseChanged:{ if(!containsMouse && !inAnimation) { pressed=false; } ////disable hover effect/// if (isWindow && root.highlightWindows && !containsMouse) { root.windowsHovered( root.plasma515 ? model.WinIdList : model.LegacyWinIdList , false); } } onPressed: { //console.log("Pressed Task Delegate.."); if (Latte.WindowSystem.compositingActive && !Latte.WindowSystem.isPlatformWayland) { if(root.leftClickAction !== Latte.Types.PreviewWindows) { isAbleToShowPreview = false; windowsPreviewDlg.hide(2); } } var modAccepted = modifierAccepted(mouse); if ((mouse.button == Qt.LeftButton)||(mouse.button == Qt.MidButton) || modAccepted) { lastButtonClicked = mouse.button; pressed = true; pressX = mouse.x; pressY = mouse.y; if(draggingResistaner == null && !modAccepted) draggingResistaner = resistanerTimerComponent.createObject(taskItem); } else if (mouse.button == Qt.RightButton && !modAccepted){ // When we're a launcher, there's no window controls, so we can show all // places without the menu getting super huge. if (model.IsLauncher === true && !isSeparator) { showContextMenu({showAllPlaces: true}) } else { showContextMenu(); } } } onReleased: { //console.log("Released Task Delegate..."); if (draggingResistaner != null){ draggingResistaner.destroy(); draggingResistaner = null; } if(pressed && (!inBlockingAnimation || inAttentionAnimation) && !isSeparator){ if (modifierAccepted(mouse) && !root.disableAllWindowsFunctionality){ if( !taskItem.isLauncher){ if (root.modifierClickAction == Latte.Types.NewInstance) { tasksModel.requestNewInstance(modelIndex()); } else if (root.modifierClickAction == Latte.Types.Close) { tasksModel.requestClose(modelIndex()); } else if (root.modifierClickAction == Latte.Types.ToggleMinimized) { tasksModel.requestToggleMinimized(modelIndex()); } else if ( root.modifierClickAction == Latte.Types.CycleThroughTasks) { if (isGroupParent) subWindows.activateNextTask(); else activateTask(); } else if (root.modifierClickAction == Latte.Types.ToggleGrouping) { tasksModel.requestToggleGrouping(modelIndex()); } } else { activateTask(); } } else if (mouse.button == Qt.MidButton && !root.disableAllWindowsFunctionality){ if( !taskItem.isLauncher){ if (root.middleClickAction == Latte.Types.NewInstance) { tasksModel.requestNewInstance(modelIndex()); } else if (root.middleClickAction == Latte.Types.Close) { tasksModel.requestClose(modelIndex()); } else if (root.middleClickAction == Latte.Types.ToggleMinimized) { tasksModel.requestToggleMinimized(modelIndex()); } else if ( root.middleClickAction == Latte.Types.CycleThroughTasks) { if (isGroupParent) subWindows.activateNextTask(); else activateTask(); } else if (root.middleClickAction == Latte.Types.ToggleGrouping) { tasksModel.requestToggleGrouping(modelIndex()); } } else { activateTask(); } } else if (mouse.button == Qt.LeftButton){ if( !taskItem.isLauncher){ if (root.leftClickAction === Latte.Types.PresentWindows && !(isGroupParent && !Latte.WindowSystem.compositingActive)) { activateTask(); } else if (root.leftClickAction === Latte.Types.CycleThroughTasks) { if (isGroupParent) subWindows.activateNextTask(); else activateTask(); } else if (root.leftClickAction === Latte.Types.PreviewWindows || !Latte.WindowSystem.compositingActive) { if(windowsPreviewDlg.activeItem !== taskItem){ showPreviewWindow(); } else { hidePreviewWindow(); } } } else { activateTask(); } } backend.cancelHighlightWindows(); } pressed = false; if(!inAnimation) { startCheckRestoreZoomTimer(3*units.longDuration); } } - onWheel: { + onWheel: { if (isSeparator || !root.mouseWheelActions || wheelIsBlocked || inBouncingAnimation || (latteView && (latteView.dockIsHidden || latteView.inSlidingIn || latteView.inSlidingOut))){ return; } var angle = wheel.angleDelta.y / 8; wheelIsBlocked = true; scrollDelayer.start(); //positive direction if (angle > 12) { - if (isLauncher || root.disableAllWindowsFunctionality) { - wrapper.runLauncherAnimation(); - } else if (isGroupParent) { - subWindows.activateNextTask(); + if (root.scrollingEnabled && scrollableList.contentsExceed) { + scrollableList.increasePos(); } else { - var taskIndex = modelIndex(); + if (isLauncher || root.disableAllWindowsFunctionality) { + wrapper.runLauncherAnimation(); + } else if (isGroupParent) { + subWindows.activateNextTask(); + } else { + var taskIndex = modelIndex(); + + if (isMinimized) { + tasksModel.requestToggleMinimized(taskIndex); + } - if (isMinimized) { - tasksModel.requestToggleMinimized(taskIndex); + tasksModel.requestActivate(taskIndex); } - tasksModel.requestActivate(taskIndex); + hidePreviewWindow(); } - - hidePreviewWindow(); - //negative direction } else if (angle < -12) { - if (isLauncher || root.disableAllWindowsFunctionality) { - // do nothing - } else if (isGroupParent) { - subWindows.activatePreviousTask(); + //negative direction + if (root.scrollingEnabled && scrollableList.contentsExceed) { + scrollableList.decreasePos(); } else { - var taskIndex = modelIndex(); + if (isLauncher || root.disableAllWindowsFunctionality) { + // do nothing + } else if (isGroupParent) { + subWindows.activatePreviousTask(); + } else { + var taskIndex = modelIndex(); - if (isMinimized) { - tasksModel.requestToggleMinimized(taskIndex); + if (isMinimized) { + tasksModel.requestToggleMinimized(taskIndex); + } + + tasksModel.requestActivate(taskIndex); } - tasksModel.requestActivate(taskIndex); + hidePreviewWindow(); } - - hidePreviewWindow(); } } //! 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: 400 onTriggered: taskItem.wheelIsBlocked = false; } ///////////////// End Of Mouse Area Events /////////////////// ///// Handlers for Signals ///// function animationStarted(){ // console.log("Animation started: " + index); inAnimation = true; } function animationEnded(){ // console.log("Animation ended: " + index); inAnimation = false; } function clearZoom(){ if(!root) return; if (root.hoveredIndex === -1 && root.dockHoveredIndex === -1) { restoreAnimation.start(); } } function handlerDraggingFinished(){ isDragged = false; } ///// End of Handlers ////// ///// Helper functions ///// function activateNextTask() { subWindows.activateNextTask(); } function activateTask() { if( taskItem.isLauncher || root.disableAllWindowsFunctionality){ if (Latte.WindowSystem.compositingActive) { wrapper.runLauncherAnimation(); } else { launcherAction(); } } else{ if (model.IsGroupParent) { if (Latte.WindowSystem.compositingActive && backend.canPresentWindows()) { root.presentWindows(root.plasma515 ? model.WinIdList: model.LegacyWinIdList ); } } else { if (IsMinimized === true) { var i = modelIndex(); tasksModel.requestToggleMinimized(i); tasksModel.requestActivate(i); } else if (IsActive === true) { tasksModel.requestToggleMinimized(modelIndex()); } else { tasksModel.requestActivate(modelIndex()); } } } } function hasNeighbourSeparator(ind, positive) { var cursor = ind; while (((!positive && cursor>=0) || (positive && cursor<=root.tasksCount-1)) && parabolicManager.taskIsForcedHidden(cursor) ) { cursor = positive ? cursor + 1 : cursor - 1; } return parabolicManager.taskIsSeparator(cursor); } function showPreviewWindow() { if (root.disableAllWindowsFunctionality || !isAbleToShowPreview) { return; } if(windowsPreviewDlg.activeItem !== taskItem){ if (!root.latteView || (root.latteView && !root.latteView.isHalfShown && !root.latteView.inSlidingIn && !root.latteView.inSlidingOut)) { if (root.latteView && root.titleTooltips) { root.latteView.hideTooltipLabel(); } taskItem.preparePreviewWindow(false); windowsPreviewDlg.show(taskItem); } } } function showTitleTooltip() { if (root.latteView && root.titleTooltips){ var displayText = isWindow ? model.display : model.AppName; var maxCharacters = 80; var fixedDisplayText = displayText.length>maxCharacters ? displayText.substring(0,maxCharacters-1) + "..." : displayText; root.latteView.showTooltipLabel(taskItem, fixedDisplayText); } } function hidePreviewWindow() { if(windowsPreviewDlg.activeItem === taskItem){ windowsPreviewDlg.hide("14.1"); if (root.latteView && root.titleTooltips && containsMouse) { showTitleTooltip(); } } } function preparePreviewWindow(hideClose){ windowsPreviewDlg.visualParent = previewsVisualParent; toolTipDelegate.parentTask = taskItem; toolTipDelegate.rootIndex = tasksModel.makeModelIndex(itemIndex, -1); toolTipDelegate.hideCloseButtons = hideClose; toolTipDelegate.appName = Qt.binding(function() { return model.AppName; }); if (!isLauncher) { toolTipDelegate.pidParent = Qt.binding(function() { return model.AppPid; }); } else { toolTipDelegate.pidParent = -1; } toolTipDelegate.windows = Qt.binding(function() { return root.plasma515 ? model.WinIdList : model.LegacyWinIdList ; }); toolTipDelegate.isGroup = Qt.binding(function() { return model.IsGroupParent == true; }); toolTipDelegate.icon = Qt.binding(function() { return model.decoration; }); toolTipDelegate.launcherUrl = Qt.binding(function() { return model.LauncherUrlWithoutIcon; }); toolTipDelegate.isLauncher = Qt.binding(function() { return model.IsLauncher == true; }); toolTipDelegate.isMinimizedParent = Qt.binding(function() { return model.IsMinimized == true; }); toolTipDelegate.displayParent = Qt.binding(function() { return model.display; }); toolTipDelegate.genericName = Qt.binding(function() { return model.GenericName; }); toolTipDelegate.virtualDesktopParent = Qt.binding(function() { return (model.VirtualDesktops !== undefined || model.VirtualDesktops.length === 0) ? model.VirtualDesktops : [0]; }); toolTipDelegate.isOnAllVirtualDesktopsParent = Qt.binding(function() { return model.IsOnAllVirtualDesktops == true; }); toolTipDelegate.activitiesParent = Qt.binding(function() { return model.Activities; }); } function launcherAction(){ // if ((lastButtonClicked == Qt.LeftButton)||(lastButtonClicked == Qt.MidButton)){ if (Latte.WindowSystem.compositingActive) { inBouncingAnimation = true; root.addWaitingLauncher(taskItem.launcherUrl); } if (root.disableAllWindowsFunctionality) { tasksModel.requestNewInstance(modelIndex()); } else { tasksModel.requestActivate(modelIndex()); } } ///window previews/// function generateSubText(task) { var subTextEntries = new Array(); if (!plasmoid.configuration.showOnlyCurrentDesktop && virtualDesktopInfo.numberOfDesktops > 1 && model.IsOnAllVirtualDesktops !== true && model.VirtualDesktop != -1 && model.VirtualDesktop != undefined) { subTextEntries.push(i18n("On %1", virtualDesktopInfo.desktopNames[model.VirtualDesktop - 1])); } if (model.Activities == undefined) { return subTextEntries.join("\n"); } if (model.Activities.length == 0 && activityInfo.numberOfRunningActivities > 1) { subTextEntries.push(i18nc("Which virtual desktop a window is currently on", "Available on all activities")); } else if (model.Activities.length > 0) { var activityNames = new Array(); for (var i = 0; i < model.Activities.length; i++) { var activity = model.Activities[i]; if (plasmoid.configuration.showOnlyCurrentActivity) { if (activity != activityInfo.currentActivity) { activityNames.push(activityInfo.activityName(model.Activities[i])); } } else if (activity != activityInfo.currentActivity) { activityNames.push(activityInfo.activityName(model.Activities[i])); } } if (plasmoid.configuration.showOnlyCurrentActivity) { if (activityNames.length > 0) { subTextEntries.push(i18nc("Activities a window is currently on (apart from the current one)", "Also available on %1", activityNames.join(", "))); } } else if (activityNames.length > 0) { subTextEntries.push(i18nc("Which activities a window is currently on", "Available on %1", activityNames.join(", "))); } } return subTextEntries.join("\n"); } ///window previews//// function modelIndex(){ return tasksModel.makeModelIndex(index); } function showContextMenu(args) { if (isSeparator && !root.editMode) return; if (!root.contextMenu) { contextMenu = root.createContextMenu(taskItem, modelIndex(), args); contextMenu.show(); } else { //! make sure that context menu isnt deleted multiple times and creates a crash //! bug case: 397635 var cMenu = root.contextMenu; root.contextMenu = null; cMenu.destroy(); } } function modifierAccepted(mouse){ if (mouse.modifiers & root.modifierQt){ if ((mouse.button === Qt.LeftButton && root.modifierClick === Latte.Types.LeftClick) || (mouse.button === Qt.MiddleButton && root.modifierClick === Latte.Types.MiddleClick) || (mouse.button === Qt.RightButton && root.modifierClick === Latte.Types.RightClick)) return true; } return false; } function setBlockingAnimation(value){ inBlockingAnimation = value; } function slotMimicEnterForParabolic(){ if (containsMouse) { if (inMimicParabolicAnimation) { mimicParabolicScale = root.zoomFactor; } wrapper.calculateScales(icList.currentSpot); } } function slotShowPreviewForTasks(group) { if (group === taskItem && !windowsPreviewDlg.visible) { preparePreviewWindow(true); windowsPreviewDlg.show(taskItem); } } function slotPublishGeometries() { //! this way we make sure that layouts that are in different activities that the current layout //! don't publish their geometries if ( canPublishGeometries && (!latteView || (latteView && currentLayout && latteView.universalLayoutManager && currentLayout.name === latteView.universalLayoutManager.currentLayoutName))) { var globalChoords = backend.globalRect(taskItem); //! Magic Lamp effect doesn't like coordinates outside the screen and //! width,heights of zero value... So we now normalize the geometries //! sent in order to avoid such circumstances if (root.vertical) { globalChoords.width = 1; globalChoords.height = Math.max(root.iconSize, taskItem.height); } else { globalChoords.height = 1; globalChoords.width = Math.max(root.iconSize, taskItem.width); } if (root.position === PlasmaCore.Types.BottomPositioned) { globalChoords.y = plasmoid.screenGeometry.y+plasmoid.screenGeometry.height-1; } else if (root.position === PlasmaCore.Types.TopPositioned) { globalChoords.y = plasmoid.screenGeometry.y+1; } else if (root.position === PlasmaCore.Types.LeftPositioned) { globalChoords.x = plasmoid.screenGeometry.x+1; } else if (root.position === PlasmaCore.Types.RightPositioned) { globalChoords.x = plasmoid.screenGeometry.x+plasmoid.screenGeometry.width - 1; } tasksModel.requestPublishDelegateGeometry(taskItem.modelIndex(), globalChoords, taskItem); } } function slotWaitingLauncherRemoved(launch) { if ((isWindow || isStartup || isLauncher) && !visible && launch === launcherUrl) { wrapper.mScale = 1; visible = true; } } function updateAudioStreams() { if (root.dragSource !== null) { audioStreams = []; return; } var pa = pulseAudio.item; if (!pa) { audioStreams = []; return; } var streams = pa.streamsForPid(taskItem.pid); if (streams.length) { pa.registerPidMatch(taskItem.appName); } else { // We only want to fall back to appName matching if we never managed to map // a PID to an audio stream window. Otherwise if you have two instances of // an application, one playing and the other not, it will look up appName // for the non-playing instance and erroneously show an indicator on both. if (!pa.hasPidMatch(taskItem.appName)) { var streams_result; streams_result = pa.streamsForAppName(taskItem.appName); if (streams_result.length===0 && launcherName !== "") { streams_result = pa.streamsForAppName(launcherName); } streams = streams_result; } } // fix a binding loop concerning audiostreams, the audiostreams // should be updated only when they have changed var changed = false; if (streams.length !== audioStreams.length) { changed = true; } else { for(var i=0; i= 0){ taskItem.lastValidIndex = taskItem.itemIndex; if (root.showWindowsOnlyFromLaunchers) { parabolicManager.updateTasksEdgesIndexes(); } } if (latteView && latteView.debugModeTimers) { console.log("plasmoid timer: lastValidTimer called..."); } } } ///Item's Removal Animation ListView.onRemove: TaskAnimations.RealRemovalAnimation{ id: taskRealRemovalAnimation } }// main Item