diff --git a/containment/package/contents/ui/applet/ItemWrapper.qml b/containment/package/contents/ui/applet/ItemWrapper.qml index 461411e3..c7ca8937 100644 --- a/containment/package/contents/ui/applet/ItemWrapper.qml +++ b/containment/package/contents/ui/applet/ItemWrapper.qml @@ -1,708 +1,707 @@ /* * 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 QtGraphicalEffects 1.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.latte 0.2 as Latte import "../../code/MathTools.js" as MathTools Item{ id: wrapper width: { if (appletItem.isInternalViewSplitter && !root.inConfigureAppletsMode) return 0; if (isSeparator && root.parabolicEffectEnabled && root.isHorizontal) { return -1; } //! width for applets that use fillWidth/fillHeight such plasma taskmanagers and AWC if (appletItem.needsFillSpace && root.isHorizontal) { if (root.panelAlignment !== Latte.Types.Justify) { var maximumValue = (applet.Layout.maximumWidth === Infinity) || applet.Layout.maximumWidth === -1 ? appletItem.sizeForFill : Math.min(appletItem.sizeForFill, applet.Layout.maximumWidth); var constrainedWidth = MathTools.bound(applet.Layout.minimumWidth, applet.Layout.preferredWidth, maximumValue); return root.inConfigureAppletsMode ? Math.max(constrainedWidth, root.iconSize) : constrainedWidth; } if(appletItem.sizeForFill>-1){ return appletItem.sizeForFill; } } if (appletItem.latteApplet) { return latteApplet.tasksWidth; } else { return (root.isHorizontal && root.inConfigureAppletsMode) ? Math.max(root.iconSize, scaledWidth) : scaledWidth; } } height: { if (appletItem.isInternalViewSplitter && !root.inConfigureAppletsMode) return 0; if (isSeparator && root.parabolicEffectEnabled && root.isVertical) { return -1; } //! height for applets that use fillWidth/fillHeight such plasma taskmanagers and AWC if (appletItem.needsFillSpace && root.isVertical) { if (root.panelAlignment !== Latte.Types.Justify) { var maximumValue = (applet.Layout.maximumHeight === Infinity) || applet.Layout.maximumHeight === -1 ? appletItem.sizeForFill : Math.min(appletItem.sizeForFill, applet.Layout.maximumHeight); var constrainedHeight = MathTools.bound(applet.Layout.minimumHeight, applet.Layout.preferredHeight, maximumValue); return root.inConfigureAppletsMode ? Math.max(constrainedHeight, root.iconSize) : constrainedHeight; } if (appletItem.sizeForFill>-1){ return appletItem.sizeForFill; } } if (appletItem.latteApplet) { return latteApplet.tasksHeight; } else { return (root.isVertical && root.inConfigureAppletsMode) ? Math.max(root.iconSize, scaledHeight) : scaledHeight; } } - opacity: appletColorizer.mustBeShown ? 0 : 1 + opacity: appletColorizer.mustBeShown && appletColorizer.isCompiled ? 0 : 1 property bool disableScaleWidth: false property bool disableScaleHeight: false property bool editMode: root.inConfigureAppletsMode property int appletWidth: applet ? applet.width : -1 property int appletHeight: applet ? applet.height : -1 property int appletMinimumWidth: applet && applet.Layout ? applet.Layout.minimumWidth : -1 property int appletMinimumHeight: applet && applet.Layout ? applet.Layout.minimumHeight : -1 property int appletPreferredWidth: applet && applet.Layout ? applet.Layout.preferredWidth : -1 property int appletPreferredHeight: applet && applet.Layout ? applet.Layout.preferredHeight : -1 property int appletMaximumWidth: applet && applet.Layout ? applet.Layout.maximumWidth : -1 property int appletMaximumHeight: applet && applet.Layout ? applet.Layout.maximumHeight : -1 property int iconSize: root.iconSize property int marginWidth: root.isVertical ? root.thickMargins : (root.inFullJustify && atScreenEdge ? 0 : localLengthMargins) //Fitt's Law property int marginHeight: root.isHorizontal ? root.thickMargins : (root.inFullJustify && atScreenEdge ? 0 : localLengthMargins) //Fitt's Law property int localLengthMargins: isSeparator || !communicator.lengthMarginsEnabled ? 0 : root.lengthMargins property real scaledWidth: zoomScaleWidth * (layoutWidth + marginWidth) property real scaledHeight: zoomScaleHeight * (layoutHeight + marginHeight) property real zoomScaleWidth: disableScaleWidth ? 1 : zoomScale property real zoomScaleHeight: disableScaleHeight ? 1 : zoomScale property int layoutWidthResult: 0 property int layoutWidth property int layoutHeight property real center:root.isHorizontal ? (width + hiddenSpacerLeft.separatorSpace + hiddenSpacerRight.separatorSpace) / 2 : (height + hiddenSpacerLeft.separatorSpace + hiddenSpacerRight.separatorSpace) / 2 property real zoomScale: 1 property int index: appletItem.index property Item wrapperContainer: _wrapperContainer property Item clickedEffect: _clickedEffect property Item containerForOverlayIcon: _containerForOverlayIcon property Item overlayIconLoader: _overlayIconLoader Behavior on opacity { NumberAnimation { duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } // property int pHeight: applet ? applet.Layout.preferredHeight : -10 /*function debugLayouts(){ if(applet){ console.log("---------- "+ applet.pluginName +" ----------"); console.log("MinW "+applet.Layout.minimumWidth); console.log("PW "+applet.Layout.preferredWidth); console.log("MaxW "+applet.Layout.maximumWidth); console.log("FillW "+applet.Layout.fillWidth); console.log("-----"); console.log("MinH "+applet.Layout.minimumHeight); console.log("PH "+applet.Layout.preferredHeight); console.log("MaxH "+applet.Layout.maximumHeight); console.log("FillH "+applet.Layout.fillHeight); console.log("-----"); console.log("Real Applet Width: "+applet.width); console.log("Real Applet Height: "+applet.height); console.log("-----"); console.log("Real Wrapper Width: "+wrapper.width); console.log("Real Wrapper Height: "+wrapper.height); console.log("-----"); console.log("Can be hovered: " + canBeHovered); console.log("Icon size: " + root.iconSize); console.log("Thick Margins: " + root.thickMargins); console.log("Intern. Margins: " + (root.lengthIntMargin * 2)); console.log("Intern. Margins: " + (root.lengthExtMargin * 2)); console.log("Max hovered criteria: " + (root.iconSize + thickMargins)); console.log("-----"); console.log("LayoutW: " + layoutWidth); console.log("LayoutH: " + layoutHeight); } } onLayoutWidthChanged: { debugLayouts(); } onLayoutHeightChanged: { debugLayouts(); }*/ onAppletWidthChanged: { if(zoomScale === 1) { checkCanBeHovered(); } } onAppletHeightChanged: { if(zoomScale === 1) { checkCanBeHovered(); } } onAppletMinimumWidthChanged: { if(zoomScale === 1) { checkCanBeHovered(); } updateLayoutWidth(); } onAppletMinimumHeightChanged: { if(zoomScale === 1) { checkCanBeHovered(); } updateLayoutHeight(); } onAppletPreferredWidthChanged: updateLayoutWidth(); onAppletPreferredHeightChanged: updateLayoutHeight(); onAppletMaximumWidthChanged: updateLayoutWidth(); onAppletMaximumHeightChanged: updateLayoutHeight(); Connections { target: appletItem onCanBeHoveredChanged: { updateLayoutWidth(); updateLayoutHeight(); } } onIconSizeChanged: { updateLayoutWidth(); updateLayoutHeight(); } onEditModeChanged: { updateLayoutWidth(); updateLayoutHeight(); } onZoomScaleChanged: { if ((zoomScale === root.zoomFactor) && !root.globalDirectRender) { root.setGlobalDirectRender(true); } if ((zoomScale > 1) && !appletItem.isZoomed) { appletItem.isZoomed = true; if (!animationWasSent) { root.slotAnimationsNeedBothAxis(1); animationWasSent = true; } } else if (zoomScale == 1) { appletItem.isZoomed = false; if (animationWasSent) { root.slotAnimationsNeedBothAxis(-1); animationWasSent = false; } } } Connections { target: root onIsVerticalChanged: { if (appletItem.latteApplet) { return; } wrapper.disableScaleWidth = false; wrapper.disableScaleHeight = false; if (root.isVertical) { wrapper.updateLayoutHeight(); wrapper.updateLayoutWidth(); } else { wrapper.updateLayoutWidth(); wrapper.updateLayoutHeight(); } } } function updateLayoutHeight(){ appletItem.movingForResize = true; if (appletItem.needsFillSpace && root.isVertical) { layoutsContainer.updateSizeForAppletsInFill(); return; } var blockParabolicEffect = false; if (isLattePlasmoid) { return; } else if (appletItem.isInternalViewSplitter){ if(!root.inConfigureAppletsMode) layoutHeight = 0; else layoutHeight = root.iconSize; } else if(appletItem.isSystray && root.isHorizontal){ layoutHeight = root.iconSize; } else{ if(applet && (applet.Layout.minimumHeight > root.iconSize) && root.isVertical && !canBeHovered && !communicator.overlayLatteIconIsActive){ blockParabolicEffect = true; layoutHeight = applet.Layout.minimumHeight; } //it is used for plasmoids that need to scale only one axis... e.g. the Weather Plasmoid else if(applet && ( applet.Layout.maximumHeight < root.iconSize || applet.Layout.preferredHeight > root.iconSize || appletItem.originalAppletBehavior) && root.isVertical && !disableScaleWidth && !communicator.overlayLatteIconIsActive) { //this way improves performance, probably because during animation the preferred sizes update a lot if((applet.Layout.maximumHeight < root.iconSize)){ layoutHeight = applet.Layout.maximumHeight; } else if (applet.Layout.minimumHeight > root.iconSize){ blockParabolicEffect = true; layoutHeight = applet.Layout.minimumHeight; } else if ((applet.Layout.preferredHeight > root.iconSize) || (appletItem.originalAppletBehavior && applet.Layout.preferredHeight > 0 )){ blockParabolicEffect = true; layoutHeight = applet.Layout.preferredHeight; } else{ layoutHeight = root.iconSize; } } else { layoutHeight = root.iconSize; } } if (wrapper.zoomScale === 1) { if (blockParabolicEffect) { disableScaleHeight = true; } else { disableScaleHeight = false; } } } function updateLayoutWidth(){ appletItem.movingForResize = true; if (appletItem.needsFillSpace && root.isHorizontal) { layoutsContainer.updateSizeForAppletsInFill(); return; } var blockParabolicEffect = false; if (isLattePlasmoid) { return; } else if (appletItem.isInternalViewSplitter){ if(!root.inConfigureAppletsMode) layoutWidth = 0; else layoutWidth = root.iconSize; } else if(appletItem.isSystray && root.isVertical){ layoutWidth = root.iconSize; } else{ if(applet && (applet.Layout.minimumWidth > root.iconSize) && root.isHorizontal && !canBeHovered && !communicator.overlayLatteIconIsActive){ blockParabolicEffect = true; layoutWidth = applet.Layout.minimumWidth; } //it is used for plasmoids that need to scale only one axis... e.g. the Weather Plasmoid else if(applet && ( applet.Layout.maximumWidth < root.iconSize || applet.Layout.preferredWidth > root.iconSize || appletItem.originalAppletBehavior) && root.isHorizontal && !disableScaleHeight && !communicator.overlayLatteIconIsActive){ //this way improves performance, probably because during animation the preferred sizes update a lot if((applet.Layout.maximumWidth < root.iconSize)){ // return applet.Layout.maximumWidth; layoutWidth = applet.Layout.maximumWidth; } else if (applet.Layout.minimumWidth > root.iconSize){ blockParabolicEffect = true; layoutWidth = applet.Layout.minimumWidth; } else if ((applet.Layout.preferredWidth > root.iconSize) || (appletItem.originalAppletBehavior && applet.Layout.preferredWidth > 0 )){ blockParabolicEffect = true; layoutWidth = applet.Layout.preferredWidth; } else{ layoutWidth = root.iconSize; } } else{ layoutWidth = root.iconSize; } } if (wrapper.zoomScale === 1) { if (blockParabolicEffect) { disableScaleWidth = true; } else { disableScaleWidth = false; } } } Item{ id:_wrapperContainer width:{ if (appletItem.needsFillSpace && (appletItem.sizeForFill>-1) && root.isHorizontal){ return wrapper.width; } if (appletItem.isInternalViewSplitter) { return wrapper.layoutWidth; } else { if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { return parent.zoomScaleWidth * (root.iconSize + root.thickMargins); } else { return parent.zoomScaleWidth * wrapper.layoutWidth; } } } height:{ if (appletItem.needsFillSpace && (appletItem.sizeForFill>-1) && root.isVertical){ return wrapper.height; } if (appletItem.isInternalViewSplitter) { return wrapper.layoutHeight; } else { if (plasmoid.formFactor === PlasmaCore.Types.Horizontal) { return parent.zoomScaleHeight * (root.iconSize + root.thickMargins); } else { return parent.zoomScaleHeight * wrapper.layoutHeight; } } } - opacity: appletShadow.active ? 0 : 1 - + opacity: appletShadow.active && (appletShadow.item.status === ShaderEffect.Compiled) ? 0 : 1 anchors.centerIn: parent ///Secret MouseArea to be used by the folder widget Loader{ anchors.fill: parent active: communicator.overlayLatteIconIsActive && applet.pluginName === "org.kde.plasma.folder" sourceComponent: MouseArea{ onClicked: latteView.toggleAppletExpanded(applet.id); } } Item{ id: _containerForOverlayIcon anchors.fill: parent } Loader{ id: _overlayIconLoader anchors.fill: parent active: communicator.overlayLatteIconIsActive property color backgroundColor: "black" property color glowColor: "white" sourceComponent: Latte.IconItem{ id: overlayIconItem anchors.fill: parent source: { if (communicator.appletIconItemIsShown()) return communicator.appletIconItem.source; else if (communicator.appletImageItemIsShown()) return communicator.appletImageItem.source; return ""; } providesColors: indicators.info.needsIconColors && source != "" usesPlasmaTheme: communicator.appletIconItemIsShown() ? communicator.appletIconItem.usesPlasmaTheme : false Binding{ target: _overlayIconLoader property: "backgroundColor" when: overlayIconItem.providesColors value: overlayIconItem.backgroundColor } Binding{ target: _overlayIconLoader property: "glowColor" when: overlayIconItem.providesColors value: overlayIconItem.glowColor } Loader{ anchors.centerIn: parent active: root.debugModeOverloadedIcons sourceComponent: Rectangle{ width: 30 height: 30 color: "green" opacity: 0.65 } } } } } Loader{ anchors.fill: _wrapperContainer active: appletItem.isInternalViewSplitter && root.inConfigureAppletsMode rotation: root.isVertical ? 90 : 0 sourceComponent: PlasmaCore.SvgItem{ id:splitterImage anchors.fill: parent svg: PlasmaCore.Svg{ imagePath: root.universalSettings.splitterIconPath() } layer.enabled: true layer.effect: DropShadow { radius: root.appShadowSize fast: true samples: 2 * radius color: root.appShadowColor verticalOffset: 2 } Component.onCompleted: { if (root.isVertical) { wrapper.updateLayoutHeight(); wrapper.updateLayoutWidth(); } else { wrapper.updateLayoutWidth(); wrapper.updateLayoutHeight(); } } } } ///Shadow in applets Loader{ id: appletShadow anchors.fill: appletItem.appletWrapper active: appletItem.applet && !appletColorizer.mustBeShown && (((plasmoid.configuration.shadows === 1 /*Locked Applets*/ && (!appletItem.canBeHovered || (appletItem.originalAppletBehavior && (applet.pluginName !== root.plasmoidName))) ) || (plasmoid.configuration.shadows === 2 /*All Applets*/ && (applet.pluginName !== root.plasmoidName))) || (root.forceTransparentPanel && plasmoid.configuration.shadows>0 && applet.pluginName !== root.plasmoidName)) /*on forced transparent state*/ onActiveChanged: { - if (active && !isSeparator) { + if (active && !isSeparator && item.status === ShaderEffect.Compiled) { wrapperContainer.opacity = 0; } else { wrapperContainer.opacity = 1; } } opacity: isSeparator ? 0.4 : 1 sourceComponent: DropShadow{ anchors.fill: parent color: root.appShadowColor //"#ff080808" fast: true samples: 2 * radius source: communicator.overlayLatteIconIsActive ? _wrapperContainer : appletItem.applet radius: shadowSize verticalOffset: root.forceTransparentPanel || root.forcePanelForBusyBackground ? 0 : 2 property int shadowSize : root.appShadowSize } } BrightnessContrast{ id:hoveredImage anchors.fill: _wrapperContainer source: _wrapperContainer enabled: appletItem.isSquare && !originalAppletBehavior && !indicators.info.providesHoveredAnimation && opacity != 0 ? true : false opacity: appletMouseArea.containsMouse ? 1 : 0 brightness: 0.25 contrast: 0.15 visible: !indicators.info.providesHoveredAnimation Behavior on opacity { NumberAnimation { duration: root.durationTime*units.longDuration } } } BrightnessContrast { id: _clickedEffect anchors.fill: _wrapperContainer source: _wrapperContainer visible: clickedAnimation.running && !indicators.info.providesClickedAnimation } /* onHeightChanged: { if ((index == 1)|| (index==3)){ console.log("H: "+index+" ("+zoomScale+"). "+currentLayout.children[1].height+" - "+currentLayout.children[3].height+" - "+(currentLayout.children[1].height+currentLayout.children[3].height)); } } onZoomScaleChanged:{ if ((index == 1)|| (index==3)){ console.log(index+" ("+zoomScale+"). "+currentLayout.children[1].height+" - "+currentLayout.children[3].height+" - "+(currentLayout.children[1].height+currentLayout.children[3].height)); } }*/ Loader{ anchors.fill: parent active: root.debugMode sourceComponent: Rectangle{ anchors.fill: parent color: "transparent" //! red visualizer, in debug mode for the applets that use fillWidth or fillHeight //! green, for the rest border.color: (appletItem.needsFillSpace && (appletItem.sizeForFill>-1) && root.isHorizontal) ? "red" : "green" border.width: 1 } } Behavior on zoomScale { enabled: !root.globalDirectRender NumberAnimation { duration: 3 * appletItem.animationTime easing.type: Easing.OutCubic } } Behavior on zoomScale { enabled: root.globalDirectRender && !restoreAnimation.running NumberAnimation { duration: root.directRenderAnimationTime } } function calculateScales( currentMousePosition ){ if (root.zoomFactor===1) { return; } var distanceFromHovered = Math.abs(index - layoutsContainer.hoveredIndex); // A new algorithm trying to make the zoom calculation only once // and at the same time fixing glitches if ((distanceFromHovered == 0)&& (currentMousePosition > 0) ){ //use the new parabolicManager in order to handle all parabolic effect messages var scales = parabolicManager.applyParabolicEffect(index, currentMousePosition, center); /*if (root.latteApplet && Math.abs(index - root.latteAppletPos) > 2){ root.latteApplet.clearZoom(); }*/ //Left hiddenSpacer if(appletItem.startEdge){ hiddenSpacerLeft.nScale = scales.leftScale - 1; } //Right hiddenSpacer ///there is one more item in the currentLayout ???? if(appletItem.endEdge){ hiddenSpacerRight.nScale = scales.rightScale - 1; } zoomScale = root.zoomFactor; } } //scale function signalUpdateScale(nIndex, nScale, step){ if(appletItem && !appletItem.containsMouse && (appletItem.index === nIndex)){ if ( ((canBeHovered && !appletItem.originalAppletBehavior) || appletItem.latteApplet) && (applet && applet.status !== PlasmaCore.Types.HiddenStatus) //&& (index != currentLayout.hoveredIndex) ){ if(!appletItem.latteApplet){ if(nScale >= 0) zoomScale = nScale + step; else zoomScale = zoomScale + step; } } } } Component.onCompleted: { root.updateScale.connect(signalUpdateScale); } Component.onDestruction: { root.updateScale.disconnect(signalUpdateScale); } }// Main task area // id:wrapper diff --git a/containment/package/contents/ui/applet/colorizer/Applet.qml b/containment/package/contents/ui/applet/colorizer/Applet.qml index 748ce69e..6fb7061c 100644 --- a/containment/package/contents/ui/applet/colorizer/Applet.qml +++ b/containment/package/contents/ui/applet/colorizer/Applet.qml @@ -1,56 +1,59 @@ /* * Copyright 2018 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import QtQuick 2.7 import QtGraphicalEffects 1.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore Item { + readonly property bool isCompiled: !colorizedAppletShadow.active + || (colorizedAppletShadow.active && colorizedAppletShadow.item.status === ShaderEffect.Compiled) + ColorOverlay { id: colorizer anchors.fill: parent color: colorizerManager.applyColor source: wrapper } ///Shadow in applets Loader{ id: colorizedAppletShadow anchors.fill: colorizer active: (plasmoid.configuration.shadows >= 1) && (appletColorizer.opacity>0) sourceComponent: DropShadow{ anchors.fill: parent color: root.appShadowColor fast: true samples: 2 * radius source: colorizer radius: shadowSize verticalOffset: forcedShadow ? 0 : 2 readonly property int shadowSize : root.appShadowSize readonly property bool forcedShadow: root.forceTransparentPanel && plasmoid.configuration.shadows>0 && applet && applet.pluginName !== root.plasmoidName ? true : false } } } diff --git a/plasmoid/package/contents/ui/task/IconItem.qml b/plasmoid/package/contents/ui/task/IconItem.qml index 3c9383e4..3e1ea2f0 100644 --- a/plasmoid/package/contents/ui/task/IconItem.qml +++ b/plasmoid/package/contents/ui/task/IconItem.qml @@ -1,806 +1,808 @@ /* * 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.4 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.kquickcontrolsaddons 2.0 as KQuickControlAddons import org.kde.latte 0.2 as Latte import org.kde.latte.components 1.0 as LatteComponents import "animations" as TaskAnimations //I am using KQuickControlAddons.QIconItem even though onExit it triggers the following error //QObject::~QObject: Timers cannot be stopped from another thread //but it increases performance almost to double during animation Item{ id: taskIcon width: wrapper.regulatorWidth height: wrapper.regulatorHeight //big interval to show shadows only after all the crappy adds and removes of tasks //have happened property bool firstDrawed: true property bool toBeDestroyed: false // three intervals in order to create the necessary buffers from the // PlasmaCore.IconItem, one big interval for the first creation of the // plasmoid, a second one for the first creation of a task and a small one // for simple updates. // This is done before especially on initialization stage some visuals // are not ready and empty buffers are created //property int firstDrawedInterval: root.initializationStep ? 2000 : 1000 // property int shadowInterval: firstDrawed ? firstDrawedInterval : 250 property int shadowInterval: firstDrawed ? 1000 : 250 property int shadowSize : root.appShadowSize readonly property bool smartLauncherEnabled: ((taskItem.isStartup === false) && (root.showInfoBadge || root.showProgressBadge)) readonly property variant iconDecoration: decoration readonly property color backgroundColor: iconImageBuffer.backgroundColor readonly property color glowColor: iconImageBuffer.glowColor property QtObject buffers: null property QtObject smartLauncherItem: null property Item visualIconItem: iconImageBuffer property Item titleTooltipVisualParent: titleTooltipParent property Item previewsTootipVisualParent: previewsTooltipParent /* Rectangle{ anchors.fill: parent border.width: 1 border.color: "green" color: "transparent" } */ onSmartLauncherEnabledChanged: { if (smartLauncherEnabled && !smartLauncherItem) { var smartLauncher = Qt.createQmlObject( " import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet; TaskManagerApplet.SmartLauncherItem { }", taskIcon); smartLauncher.launcherUrl = Qt.binding(function() { return taskItem.launcherUrlWithIcon; }); smartLauncherItem = smartLauncher; } else if (!smartLauncherEnabled && smartLauncherItem) { smartLauncherItem.destroy(); smartLauncherItem = null; } } Rectangle{ id: draggedRectangle width: taskItem.isSeparator ? parent.width + 1 : iconImageBuffer.width+1 height: taskItem.isSeparator ? parent.height + 1 : iconImageBuffer.height+1 anchors.centerIn: iconGraphic opacity: 0 radius: 3 anchors.margins: 5 property color tempColor: theme.highlightColor color: tempColor border.width: 1 border.color: theme.highlightColor onTempColorChanged: tempColor.a = 0.35; } TitleTooltipParent{ id: titleTooltipParent thickness: root.zoomFactor * (root.iconSize + root.thickMargins) } TitleTooltipParent{ id: previewsTooltipParent thickness: root.zoomFactor * (root.iconSize + root.thickMargins) + 1 } // KQuickControlAddons.QIconItem{ Item{ id: iconGraphic width: parent.width height: parent.height //fix bug #478, when changing form factor sometimes the tasks are not positioned //correctly, in such case we make a fast reinitialization for the sizes Connections { target: plasmoid onFormFactorChanged:{ taskItem.inAddRemoveAnimation = false; wrapper.mScale = 1.01; wrapper.tempScaleWidth = 1.01; wrapper.tempScaleHeight = 1.01; wrapper.mScale = 1; wrapper.tempScaleWidth = 1; wrapper.tempScaleHeight = 1; } } Latte.IconItem{ id: iconImageBuffer anchors.centerIn: parent width: Math.round(newTempSize) height: Math.round(width) source: decoration smooth: root.zoomFactor === 1 ? true : false providesColors: indicators ? indicators.info.needsIconColors : false - opacity: root.enableShadows ? 0 : 1 + opacity: root.enableShadows + && taskWithShadow.active + && (taskWithShadow.item.status === ShaderEffect.Compiled) ? 0 : 1 visible: !taskItem.isSeparator && !badgesLoader.active onValidChanged: { if (!valid && (source === decoration || source === "unknown")) { source = "application-x-executable"; } } //! try to show the correct icon when a window is removed... libtaskmanager when a window is removed //! sends an unknown pixmap as icon Connections { target: taskItem onInRemoveStageChanged: { if (taskItem.inRemoveStage && iconImageBuffer.lastValidSourceName !== "") { iconImageBuffer.source = iconImageBuffer.lastValidSourceName; } } } property int zoomedSize: root.zoomFactor * root.iconSize property real basicScalingWidth : wrapper.inTempScaling ? (root.iconSize * wrapper.scaleWidth) : root.iconSize * wrapper.mScale property real basicScalingHeight : wrapper.inTempScaling ? (root.iconSize * wrapper.scaleHeight) : root.iconSize * wrapper.mScale property real newTempSize: { if (wrapper.opacity == 1) return Math.min(basicScalingWidth, basicScalingHeight) else return Math.max(basicScalingWidth, basicScalingHeight) } //! Latte Side Painting-style if the user chose it Loader{ anchors.fill: iconImageBuffer active: plasmoid.configuration.forceMonochromaticIcons sourceComponent: ColorOverlay { anchors.fill: parent color: latteBridge ? latteBridge.palette.textColor : "transparent" source: iconImageBuffer } } //! Latte Side Painting-style if the user chose it ///states for launcher animation states: [ State{ name: "*" when: !launcherAnimation.running && !newWindowAnimation.running && !taskItem.inAddRemoveAnimation && !fastRestoreAnimation.running AnchorChanges{ target:iconImageBuffer; anchors.horizontalCenter: !root.vertical ? parent.horizontalCenter : undefined; anchors.verticalCenter: root.vertical ? parent.verticalCenter : undefined; anchors.right: root.position === PlasmaCore.Types.RightPositioned ? parent.right : undefined; anchors.left: root.position === PlasmaCore.Types.LeftPositioned ? parent.left : undefined; anchors.top: root.position === PlasmaCore.Types.TopPositioned ? parent.top : undefined; anchors.bottom: root.position === PlasmaCore.Types.BottomPositioned ? parent.bottom : undefined; } }, State{ name: "inAddRemoveAnimation" when: taskItem.inAddRemoveAnimation AnchorChanges{ target:iconImageBuffer; anchors.horizontalCenter: !root.vertical ? parent.horizontalCenter : undefined; anchors.verticalCenter: root.vertical ? parent.verticalCenter : undefined; anchors.right: root.position === PlasmaCore.Types.LeftPositioned ? parent.right : undefined; anchors.left: root.position === PlasmaCore.Types.RightPositioned ? parent.left : undefined; anchors.top: root.position === PlasmaCore.Types.BottomPositioned ? parent.top : undefined; anchors.bottom: root.position === PlasmaCore.Types.TopPositioned ? parent.bottom : undefined; } }, State{ name: "animating" when: (launcherAnimation.running || newWindowAnimation.running || fastRestoreAnimation.running) && !taskItem.inAddRemoveAnimation AnchorChanges{ target:iconImageBuffer; anchors.horizontalCenter: !root.vertical ? parent.horizontalCenter : undefined; anchors.verticalCenter: root.vertical ? parent.verticalCenter : undefined; anchors.right: root.position === PlasmaCore.Types.LeftPositioned ? parent.right : undefined; anchors.left: root.position === PlasmaCore.Types.RightPositioned ? parent.left : undefined; anchors.top: root.position === PlasmaCore.Types.BottomPositioned ? parent.top : undefined; anchors.bottom: root.position === PlasmaCore.Types.TopPositioned ? parent.bottom : undefined; } } ] ///transitions, basic for the anchor changes transitions: [ Transition{ from: "animating" to: "*" enabled: !fastRestoreAnimation.running && !taskItem.inMimicParabolicAnimation AnchorAnimation { duration: 1.5*root.durationTime*units.longDuration } } ] } //IconImageBuffer //! Shadows Loader{ id: taskWithShadow anchors.fill: iconImageBuffer active: root.enableShadows && !taskItem.isSeparator sourceComponent: DropShadow{ anchors.fill: parent color: root.appShadowColor fast: true samples: 2 * radius source: badgesLoader.active ? badgesLoader.item : iconImageBuffer radius: root.appShadowSize verticalOffset: 2 } } //! Shadows //! Combined Loader for Progress and Audio badges masks Loader{ id: badgesLoader anchors.fill: iconImageBuffer active: activateProgress > 0 asynchronous: true opacity: stateColorizer.opacity > 0 ? 0 : 1 property real activateProgress: showInfo || showProgress || showAudio ? 1 : 0 property bool showInfo: (root.showInfoBadge && taskIcon.smartLauncherItem && !taskItem.isSeparator && (taskIcon.smartLauncherItem.countVisible || taskItem.badgeIndicator > 0)) property bool showProgress: root.showProgressBadge && taskIcon.smartLauncherItem && !taskItem.isSeparator && taskIcon.smartLauncherItem.progressVisible property bool showAudio: (root.showAudioBadge && taskItem.hasAudioStream && taskItem.playingAudio && !taskItem.isSeparator) && !shortcutBadge.active Behavior on activateProgress { NumberAnimation { duration: root.durationTime*2*units.longDuration } } sourceComponent: Item{ ShaderEffect { id: iconOverlay enabled: false anchors.fill: parent property var source: ShaderEffectSource { sourceItem: Latte.IconItem{ width: iconImageBuffer.width height: iconImageBuffer.height source: iconImageBuffer.source Loader{ anchors.fill: parent active: plasmoid.configuration.forceMonochromaticIcons sourceComponent: ColorOverlay { anchors.fill: parent color: latteBridge ? latteBridge.palette.textColor : "transparent" source: iconImageBuffer } } } } property var mask: ShaderEffectSource { sourceItem: Item{ LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft && !root.vertical LayoutMirroring.childrenInherit: true width: iconImageBuffer.width height: iconImageBuffer.height Rectangle{ id: maskRect width: Math.max(badgeVisualsLoader.infoBadgeWidth, parent.width / 2) height: parent.height / 2 radius: parent.height visible: badgesLoader.showInfo || badgesLoader.showProgress //! Removes any remainings from the icon around the roundness at the corner Rectangle{ id: maskCorner width: parent.width/2 height: parent.height/2 } states: [ State { name: "default" when: (plasmoid.location !== PlasmaCore.Types.RightEdge) AnchorChanges { target: maskRect anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right;} } AnchorChanges { target: maskCorner anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right;} } }, State { name: "right" when: (plasmoid.location === PlasmaCore.Types.RightEdge) AnchorChanges { target: maskRect anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined;} } AnchorChanges { target: maskCorner anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined;} } } ] } // progressMask Rectangle{ id: maskRect2 width: parent.width/2 height: width radius: width visible: badgesLoader.showAudio Rectangle{ id: maskCorner2 width:parent.width/2 height:parent.height/2 } states: [ State { name: "default" when: (plasmoid.location !== PlasmaCore.Types.RightEdge) AnchorChanges { target: maskRect2 anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined;} } AnchorChanges { target: maskCorner2 anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined;} } }, State { name: "right" when: (plasmoid.location === PlasmaCore.Types.RightEdge) AnchorChanges { target: maskRect2 anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right;} } AnchorChanges { target: maskCorner2 anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right;} } } ] } // audio mask } hideSource: true live: true } //end of mask supportsAtlasTextures: true fragmentShader: " varying highp vec2 qt_TexCoord0; uniform highp float qt_Opacity; uniform lowp sampler2D source; uniform lowp sampler2D mask; void main() { gl_FragColor = texture2D(source, qt_TexCoord0.st) * (1.0 - (texture2D(mask, qt_TexCoord0.st).a)) * qt_Opacity; } " } //end of sourceComponent } } ////! //! START: Badges Visuals //! the badges visual get out from iconGraphic in order to be able to draw shadows that //! extend beyond the iconGraphic boundaries Loader { id: badgeVisualsLoader anchors.fill: iconImageBuffer active: badgesLoader.active readonly property int infoBadgeWidth: active ? publishedInfoBadgeWidth : 0 property int publishedInfoBadgeWidth: 0 sourceComponent: Item { ProgressOverlay{ id: infoBadge anchors.right: parent.right anchors.top: parent.top width: Math.max(parent.width, contentWidth) height: parent.height opacity: badgesLoader.activateProgress visible: badgesLoader.showInfo || badgesLoader.showProgress layer.enabled: root.enableShadows layer.effect: DropShadow { color: root.appShadowColor fast: true samples: 2 * radius source: infoBadge radius: root.appShadowSize verticalOffset: 2 } } AudioStream{ id: audioStreamBadge anchors.fill: parent opacity: badgesLoader.activateProgress visible: badgesLoader.showAudio layer.enabled: root.enableShadows layer.effect: DropShadow { color: root.appShadowColor fast: true samples: 2 * radius source: audioStreamBadge radius: root.appShadowSize verticalOffset: 2 } } Binding { target: badgeVisualsLoader property: "publishedInfoBadgeWidth" value: infoBadge.contentWidth } } } //! GREY-ing the information badges when the task is dragged //! moved out of badgeVisualsLoader in order to avoid crashes //! when the latte view is removed Loader { width: iconImageBuffer.width height: iconImageBuffer.height anchors.centerIn: iconImageBuffer active: badgeVisualsLoader.active sourceComponent: Colorize{ source: badgeVisualsLoader.item //! HACK TO AVOID PIXELIZATION //! WORKAROUND: When Effects are enabled e.g. BrightnessContrast, Colorize etc. //! the icon appears pixelated. It is even most notable when zoomFactor === 1 //! I dont know enabling cached=true helps, but it does. cached: true opacity: stateColorizer.opacity hue: stateColorizer.hue saturation: stateColorizer.saturation lightness: stateColorizer.lightness } } //! END: Badges Visuals //! Effects Colorize{ id: stateColorizer anchors.centerIn: iconImageBuffer width: iconImageBuffer.width height: iconImageBuffer.height //! HACK TO AVOID PIXELIZATION //! WORKAROUND: When Effects are enabled e.g. BrightnessContrast, Colorize etc. //! the icon appears pixelated. It is even most notable when zoomFactor === 1 //! I dont know enabling cached=true helps, but it does. cached: true source: badgesLoader.active ? badgesLoader : iconImageBuffer visible: !isSeparator opacity:0 hue:0 saturation:0 lightness:0 } BrightnessContrast{ id:hoveredImage anchors.centerIn: iconImageBuffer width: iconImageBuffer.width height: iconImageBuffer.height //! HACK TO AVOID PIXELIZATION //! WORKAROUND: When Effects are enabled e.g. BrightnessContrast, Colorize etc. //! the icon appears pixelated. It is even most notable when zoomFactor === 1 //! I dont know enabling cached=true helps, but it does. cached: true source: badgesLoader.active ? badgesLoader : iconImageBuffer visible: !isSeparator opacity: taskItem.containsMouse && !clickedAnimation.running && !indicators.info.providesHoveredAnimation ? 1 : 0 brightness: 0.30 contrast: 0.1 Behavior on opacity { NumberAnimation { duration: root.durationTime*units.longDuration } } } BrightnessContrast { id: brightnessTaskEffect anchors.centerIn: iconImageBuffer width: iconImageBuffer.width height: iconImageBuffer.height //! HACK TO AVOID PIXELIZATION //! WORKAROUND: When Effects are enabled e.g. BrightnessContrast, Colorize etc. //! the icon appears pixelated. It is even most notable when zoomFactor === 1 //! I dont know enabling cached=true helps, but it does. cached: true source: badgesLoader.active ? badgesLoader : iconImageBuffer visible: clickedAnimation.running && !isSeparator } //! Effects ShortcutBadge{ id: shortcutBadge } } Loader { id: dropFilesVisual active: applyOpacity>0 width: !root.vertical ? length : thickness height: !root.vertical ? thickness : length anchors.centerIn: parent readonly property int length: root.iconSize + root.lengthMargins readonly property int thickness: root.iconSize + root.thickMargins readonly property real applyOpacity: root.dropNewLauncher && !mouseHandler.onlyLaunchers && (root.dragSource == null) && (mouseHandler.hoveredItem === taskItem) ? 0.7 : 0 sourceComponent: LatteComponents.AddItem { anchors.fill: parent backgroundOpacity: dropFilesVisual.applyOpacity } } Component.onDestruction: { taskIcon.toBeDestroyed = true; if(removingAnimation.removingItem) removingAnimation.removingItem.destroy(); } Connections{ target: taskItem onInAttentionChanged:{ if (!taskItem.inAttention && newWindowAnimation.running && taskItem.inAttentionAnimation) { newWindowAnimation.pause(); fastRestoreAnimation.start(); } } } ///// Animations ///// TaskAnimations.ClickedAnimation { id: clickedAnimation } TaskAnimations.LauncherAnimation { id:launcherAnimation } TaskAnimations.NewWindowAnimation { id: newWindowAnimation } TaskAnimations.RemoveWindowFromGroupAnimation { id: removingAnimation } TaskAnimations.FastRestoreAnimation { id: fastRestoreAnimation } //////////// States //////////////////// states: [ State{ name: "*" when: !taskItem.isDragged }, State{ name: "isDragged" when: ( (taskItem.isDragged) && (!root.inConfigureAppletsMode) ) } ] //////////// Transitions ////////////// transitions: [ Transition{ id: isDraggedTransition to: "isDragged" property int speed: root.durationTime*units.longDuration SequentialAnimation{ ScriptAction{ script: { icList.directRender = false; if(latteView) { latteView.globalDirectRender=false; } taskItem.inBlockingAnimation = true; root.clearZoom(); } } PropertyAnimation { target: wrapper property: "mScale" to: 1 + ((root.zoomFactor - 1) / 3) duration: isDraggedTransition.speed / 2 easing.type: Easing.OutQuad } ParallelAnimation{ PropertyAnimation { target: draggedRectangle property: "opacity" to: 1 duration: isDraggedTransition.speed easing.type: Easing.OutQuad } PropertyAnimation { target: iconImageBuffer property: "opacity" to: 0 duration: isDraggedTransition.speed easing.type: Easing.OutQuad } PropertyAnimation { target: stateColorizer property: "opacity" to: taskItem.isSeparator ? 0 : 1 duration: isDraggedTransition.speed easing.type: Easing.OutQuad } } } onRunningChanged: { if(running){ taskItem.animationStarted(); //root.animations++; parabolicManager.clearTasksGreaterThan(index); parabolicManager.clearTasksLowerThan(index); if (latteView){ latteView.parabolicManager.clearAppletsGreaterThan(latteView.latteAppletPos); latteView.parabolicManager.clearAppletsLowerThan(latteView.latteAppletPos); } } } }, Transition{ id: defaultTransition from: "isDragged" to: "*" property int speed: root.durationTime*units.longDuration SequentialAnimation{ ScriptAction{ script: { icList.directRender = false; if(latteView) { latteView.globalDirectRender=false; } } } ParallelAnimation{ PropertyAnimation { target: draggedRectangle property: "opacity" to: 0 duration: defaultTransition.speed easing.type: Easing.OutQuad } PropertyAnimation { target: iconImageBuffer property: "opacity" to: 1 duration: defaultTransition.speed easing.type: Easing.OutQuad } PropertyAnimation { target: stateColorizer property: "opacity" to: 0 duration: isDraggedTransition.speed easing.type: Easing.OutQuad } } /* PropertyAnimation { target: wrapper property: "mScale" to: 1; duration: isDraggedTransition.speed easing.type: Easing.OutQuad }*/ ScriptAction{ script: { taskItem.inBlockingAnimation = false; } } } onRunningChanged: { if(!running){ var halfZoom = 1 + ((root.zoomFactor - 1) / 2); wrapper.calculateScales((root.iconSize+root.thickMargins)/2); taskItem.animationEnded(); // root.animations--; } } } ] }// Icon Item diff --git a/plasmoid/package/contents/ui/task/TaskItem.qml b/plasmoid/package/contents/ui/task/TaskItem.qml index 5565dca1..425b9758 100644 --- a/plasmoid/package/contents/ui/task/TaskItem.qml +++ b/plasmoid/package/contents/ui/task/TaskItem.qml @@ -1,1644 +1,1645 @@ /* * 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 } } Loader{ anchors.fill: parent active: latteView && latteView.debugMode sourceComponent: Rectangle{ anchors.fill: parent color: "transparent" border.color: "blue" border.width: 1 } } 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 + opacity: (separatorShadow.active && (separatorShadow.item.status === ShaderEffect.Compiled)) + || 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.inConfigureAppletsMode)){ root.dragSource = taskItem; dragHelper.startDrag(taskItem, model.MimeType, model.MimeData, model.LauncherUrlWithoutIcon, model.decoration); pressX = -1; pressY = -1; } } onIsMinimizedChanged: { checkWindowsStates(); } onIsActiveChanged: { checkWindowsStates(); if (isActive) { scrollableList.focusOn(taskItem); } } onIsForcedHiddenChanged: root.hiddenTasksUpdated(); onIsSeparatorChanged: { if (isSeparator) { root.separatorsUpdated(); if (tasksExtendedManager.isLauncherToBeMoved(launcherUrl) && itemIndex>=0) { tasksExtendedManager.moveLauncherToCorrectPos(launcherUrl, itemIndex); } } else { root.separatorsUpdated(); } } onLauncherUrlChanged: updateBadge(); ////// End of Values Changes ///// ///////////////// Mouse Area Events /////////////////// onEntered: { root.stopCheckRestoreZoomTimer(); if (restoreAnimation.running) { restoreAnimation.stop(); } 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.autoScrollTasksEnabled) { scrollableList.autoScrollFor(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); } } slotPublishGeometries(); 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.PreviewWindows && isGroupParent) || (Latte.WindowSystem.isPlatformWayland && root.leftClickAction === Latte.Types.PresentWindows && isGroupParent) || !Latte.WindowSystem.compositingActive) { if(windowsPreviewDlg.activeItem !== taskItem){ showPreviewWindow(); } else { hidePreviewWindow(); } } else if ( (root.leftClickAction === Latte.Types.PresentWindows && !(isGroupParent && !Latte.WindowSystem.compositingActive)) || ((root.leftClickAction === Latte.Types.PreviewWindows && !isGroupParent)) ) { activateTask(); } else if (root.leftClickAction === Latte.Types.CycleThroughTasks) { if (isGroupParent) subWindows.activateNextTask(); else activateTask(); } } else { activateTask(); } } backend.cancelHighlightWindows(); } pressed = false; if(!inAnimation) { startCheckRestoreZoomTimer(3*units.longDuration); } } onWheel: { if (isSeparator || wheelIsBlocked || !(root.mouseWheelActions || manualScrollTasksEnabled) || inBouncingAnimation || (latteView && (latteView.dockIsHidden || latteView.inSlidingIn || latteView.inSlidingOut))){ return; } var angleVertical = wheel.angleDelta.y / 8; var angleHorizontal = wheel.angleDelta.x / 8; wheelIsBlocked = true; scrollDelayer.start(); var verticalDirection = (Math.abs(angleVertical) > Math.abs(angleHorizontal)); var mainAngle = verticalDirection ? angleVertical : angleHorizontal; var positiveDirection = (mainAngle > 12); var negativeDirection = (mainAngle < -12); var parallelScrolling = (verticalDirection && plasmoid.formFactor === PlasmaCore.Types.Vertical) || (!verticalDirection && plasmoid.formFactor === PlasmaCore.Types.Horizontal); if (positiveDirection) { slotPublishGeometries(); var overflowScrollingAccepted = (root.manualScrollTasksEnabled && scrollableList.contentsExceed && (root.manualScrollTasksType === Latte.Types.ManualScrollVerticalHorizontal || (root.manualScrollTasksType === Latte.Types.ManualScrollOnlyParallel && parallelScrolling)) ); if (overflowScrollingAccepted) { scrollableList.increasePos(); } else if (root.mouseWheelActions){ if (isLauncher || root.disableAllWindowsFunctionality) { wrapper.runLauncherAnimation(); } else if (isGroupParent) { subWindows.activateNextTask(); } else { var taskIndex = modelIndex(); if (isMinimized) { tasksModel.requestToggleMinimized(taskIndex); } tasksModel.requestActivate(taskIndex); } hidePreviewWindow(); } } else if (negativeDirection) { slotPublishGeometries(); var overflowScrollingAccepted = (root.manualScrollTasksEnabled && scrollableList.contentsExceed && (root.manualScrollTasksType === Latte.Types.ManualScrollVerticalHorizontal || (root.manualScrollTasksType === Latte.Types.ManualScrollOnlyParallel && parallelScrolling)) ); if (overflowScrollingAccepted) { scrollableList.decreasePos(); } else if (root.mouseWheelActions){ if (isLauncher || root.disableAllWindowsFunctionality) { // do nothing } else if (isGroupParent) { subWindows.activatePreviousTask(); } else { var taskIndex = modelIndex(); if (isMinimized) { tasksModel.requestToggleMinimized(taskIndex); } tasksModel.requestActivate(taskIndex); } 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; //! WORKAROUND, in order for toolTipDelegate to re-instantiate the previews model when //! previews are changing from single instance preview to another single instance toolTipDelegate.rootIndex = undefined; 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; tasksExtendedManager.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 || root.viewLayoutIsCurrent)) { var globalChoords = backend.globalRect(wrapper.visualIconItem); var limits = backend.globalRect(scrollableList); //! Limit the published geometries boundaries at scrolling area boundaries var adjX = Math.min(limits.x+limits.width, Math.max(limits.x, globalChoords.x)); var adjY = Math.min(limits.y+limits.height, Math.max(limits.y, globalChoords.y)); var length = root.iconSize * wrapper.mScale; //! 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) { if (adjY !== globalChoords.y) { if (((globalChoords.y+globalChoords.height) < limits.y) || (globalChoords.y)>(limits.y+limits.height)) { //! totally out of boundaries length = 4; } else { //! semi-part out of boundaries length = Math.max(4, Math.abs(adjY - globalChoords.y)); } } globalChoords.width = 1; globalChoords.height = length; } else { if (adjX !== globalChoords.x) { if (((globalChoords.x+globalChoords.width) < limits.x) || (globalChoords.x)>(limits.x+limits.width)) { //! totally out of boundaries length = 4; } else { //! semi-part out of boundaries length = Math.max(4, Math.abs(adjX - globalChoords.x)); } } globalChoords.height = 1; globalChoords.width = length; } globalChoords.x = adjX; globalChoords.y = adjY; if (root.position === PlasmaCore.Types.BottomPositioned) { globalChoords.y = root.screenGeometry.y+root.screenGeometry.height-1; } else if (root.position === PlasmaCore.Types.TopPositioned) { globalChoords.y = root.screenGeometry.y+1; } else if (root.position === PlasmaCore.Types.LeftPositioned) { globalChoords.x = root.screenGeometry.x+1; } else if (root.position === PlasmaCore.Types.RightPositioned) { globalChoords.x = root.screenGeometry.x+root.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