diff --git a/containment/package/contents/ui/main.qml b/containment/package/contents/ui/main.qml index 4d93b2d7..ea5e2538 100644 --- a/containment/package/contents/ui/main.qml +++ b/containment/package/contents/ui/main.qml @@ -1,1477 +1,1480 @@ /* * 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 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.1 as Latte import "applet" as Applet import "../code/LayoutManager.js" as LayoutManager DragDrop.DropArea { id: root objectName: "dockLayoutView" + LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft + LayoutMirroring.childrenInherit: true + //// BEGIN SIGNALS signal clearZoomSignal(); signal separatorsUpdated(); signal updateEffectsArea(); signal updateIndexes(); signal updateScale(int delegateIndex, real newScale, real step); //// END SIGNALS ////BEGIN properties property bool debugMode: Qt.application.arguments.indexOf("--graphics")>=0 property bool debugModeWindow: Qt.application.arguments.indexOf("--with-window")>=0 property bool globalDirectRender: false //it is used as a globalDirectRender for all elements in the dock property bool directRenderTimerIsRunning: enableDirectRenderTimer.running property int directRenderAnimationTime: 0 property bool addLaunchersMessage: false property bool addLaunchersInTaskManager: plasmoid.configuration.addLaunchersInTaskManager // when there are only plasma style task managers the automatic icon size algorithm should better be disabled property bool autoDecreaseIconSize: plasmoid.configuration.autoDecreaseIconSize && !containsOnlyPlasmaTasks property bool backgroundOnlyOnMaximized: plasmoid.configuration.backgroundOnlyOnMaximized property bool behaveAsPlasmaPanel: { if (!dock || !dock.visibility) return false; return (visibilityManager.panelIsBiggerFromIconSize && (zoomFactor === 1.0) && (dock.visibility.mode === Latte.Dock.AlwaysVisible || dock.visibility.mode === Latte.Dock.WindowsGoBelow) && (plasmoid.configuration.panelPosition === Latte.Dock.Justify) && !(root.solidPanel && panelShadowsActive)); } property bool blurEnabled: plasmoid.configuration.blurEnabled && !root.forceTransparentPanel 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: dock && dock.visibility ? dock.visibility.containsMouse : false property bool disablePanelShadowMaximized: plasmoid.configuration.disablePanelShadowForMaximized property bool drawShadowsExternal: panelShadowsActive && behaveAsPlasmaPanel property bool editMode: plasmoid.userConfiguring property bool forceTransparentPanel: root.backgroundOnlyOnMaximized && !windowsModel.hasMaximizedWindow && Latte.WindowSystem.compositingActive && !(hasExpandedApplet && zoomFactor===1 && plasmoid.configuration.panelSize===100) readonly property bool hasExpandedApplet: plasmoid.applets.some(function (item) { return (item.status >= PlasmaCore.Types.NeedsAttentionStatus && item.status !== PlasmaCore.Types.HiddenStatus); }) property bool immutable: plasmoid.immutable property bool indicateAudioStreams: plasmoid.configuration.indicateAudioStreams property bool inFullJustify: (plasmoid.configuration.panelPosition === Latte.Dock.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 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 arent removals, this variable provides a way to grow icon size property bool shrinkThickMargins: plasmoid.configuration.shrinkThickMargins property bool solidPanel: Latte.WindowSystem.compositingActive ? plasmoid.configuration.solidPanel : true //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 useThemePanel: noApplets === 0 || !Latte.WindowSystem.compositingActive ? true : plasmoid.configuration.useThemePanel property alias hoveredIndex: layoutsContainer.hoveredIndex property int activeIndicator: plasmoid.configuration.activeIndicator 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 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) || !dock) return -1; return Math.max(16,Math.round(dock.screenGeometry.height * plasmoid.configuration.proportionIconSize/100/8)*8); } property int iconStep: 8 property int latteAppletPos: -1 property int maxLength: root.isHorizontal ? width * (plasmoid.configuration.maxLength/100) : height * (plasmoid.configuration.maxLength/100) property int middleClickAction: plasmoid.configuration.middleClickAction property int modifier: plasmoid.configuration.modifier property int modifierClickAction: plasmoid.configuration.modifierClickAction property int modifierClick: plasmoid.configuration.modifierClick property int panelEdgeSpacing: iconSize / 3 property int panelTransparency: plasmoid.configuration.panelTransparency property bool panelShadowsActive: (( (plasmoid.configuration.panelShadows && !root.backgroundOnlyOnMaximized) || (plasmoid.configuration.panelShadows && root.backgroundOnlyOnMaximized && !root.forceTransparentPanel)) && !(disablePanelShadowMaximized && windowsModel.hasMaximizedWindow)) || (hasExpandedApplet && zoomFactor===1 && plasmoid.configuration.panelSize===100 && !(root.solidPanel && !plasmoid.configuration.panelShadows) ) property int appShadowOpacity: (plasmoid.configuration.shadowOpacity/100) * 255 property int appShadowSize: (0.4*root.iconSize) * (plasmoid.configuration.shadowSize/100) property string appShadowColor: "#" + decimalToHex(appShadowOpacity) + plasmoid.configuration.shadowColor property int totalPanelEdgeSpacing: 0 //this is set by PanelBox //FIXME: this is not needed any more probably property int previousAllTasks: -1 //is used to forbit 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.Dock.Center || plasmoid.configuration.panelPosition === Latte.Dock.Justify)? offset : offset+panelMarginLength/2+totalPanelEdgeSpacing/2 property int realSize: iconSize + iconMargin property int realPanelSize: 0 property int realPanelLength: 0 property int realPanelThickness: 0 //this is set by the PanelBox property int panelMargin: 0 property int panelMarginLength: 0 property int panelShadow: 0 //shadowsSize property int editShadow: 7 property int themePanelSize: { //root.statesLineSize + root.iconSize + root.iconMargin + 1 var panelBase = root.statesLineSize + root.panelMargin; var margin = latteApplet ? thickMargin : 0; var maxPanelSize = (root.statesLineSize + iconSize + margin + 1) - panelBase; var percentage = Latte.WindowSystem.compositingActive ? plasmoid.configuration.panelSize/100 : 1; return Math.max(panelBase, panelBase + percentage*maxPanelSize); } //decouple iconMargin which now is used only for length calculations with thickMargins //which are used for thickness calculations property int thickMarginBase: shrinkThickMargins ? 0 : Math.ceil(0.06 * iconSize) property int thickMarginHigh: shrinkThickMargins ? 0 : Math.ceil(0.06 * iconSize) property int thickMargin: thickMarginBase + thickMarginHigh //it is used in order to not break the calculations for the thickness placement //especially in automatic icon sizes calculations property int thickMarginOriginal: Math.ceil(0.12 * maxIconSize) //! iconMargin from configuration is a percentage. The calculation provides a length //! for that value between 0.04 - 0.5 of iconSize, this way 100% iconMargin means //! equal to the iconSize property int iconMargin: Math.ceil( ((0.5 * (plasmoid.configuration.iconMargin))/100) * iconSize) property int statesLineSize: latteApplet ? Math.ceil( root.iconSize/13 ) : 0 ///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.Dock.Center : (root.isVertical ? Latte.Dock.Top : Latte.Dock.Left) //property int panelAlignment: plasmoid.configuration.panelPosition !== Latte.Dock.Justify ? plasmoid.configuration.panelPosition : layoutsContainer.mainLayoutPosition property int panelAlignment: !root.editMode ? plasmoid.configuration.panelPosition : ( plasmoid.configuration.panelPosition === Latte.Dock.Justify ? Latte.Dock.Center : plasmoid.configuration.panelPosition ) property real zoomFactor: (Latte.WindowSystem.compositingActive && durationTime>0) ? ( 1 + (plasmoid.configuration.zoomLevel / 20) ) : 1 readonly property string plasmoidName: "org.kde.latte.plasmoid" property var iconsArray: [16, 22, 32, 48, 64, 96, 128, 256] property var layoutManager: LayoutManager property Item dragOverlay property Item toolBox property Item latteAppletContainer property Item latteApplet property Item parabolicManager: _parabolicManager property QtObject dock property QtObject universalSettings property QtObject universalLayoutManager // 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 dont need it any more property bool enableShadows: plasmoid.configuration.shadows || root.forceTransparentPanel property bool dockIsHidden: dock ? dock.visibility.isHidden : true property bool dotsOnActive: plasmoid.configuration.dotsOnActive property bool highlightWindows: plasmoid.configuration.highlightWindows property bool reverseLinesPosition: !latteApplet && plasmoid.configuration.panelSize===100 ? true : plasmoid.configuration.reverseLinesPosition property bool showGlow: plasmoid.configuration.showGlow property bool showToolTips: plasmoid.configuration.showToolTips property bool showWindowActions: plasmoid.configuration.showWindowActions property bool showOnlyCurrentScreen: plasmoid.configuration.showOnlyCurrentScreen property bool showOnlyCurrentDesktop: plasmoid.configuration.showOnlyCurrentDesktop property bool showOnlyCurrentActivity: plasmoid.configuration.showOnlyCurrentActivity property bool smartLaunchersEnabled: plasmoid.configuration.smartLaunchersEnabled property bool threeColorsWindows: plasmoid.configuration.threeColorsWindows property bool titleTooltips: plasmoid.configuration.titleTooltips readonly property int latteInternalSeparatorPos: latteApplet ? latteApplet.internalSeparatorPos : -1 readonly property bool hasInternalSeparator: latteApplet ? latteApplet.hasInternalSeparator : false property int latteAppletHoveredIndex: latteApplet ? latteApplet.hoveredIndex : -1 property int launchersGroup: plasmoid.configuration.launchersGroup property int tasksCount: latteApplet ? latteApplet.tasksCount : 0 property real durationTime: { 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 rect screenGeometry: dock ? dock.screenGeometry : plasmoid.screenGeometry ///END properties from latteApplet /* Layout.preferredWidth: plasmoid.immutable ? (plasmoid.configuration.panelPosition === Latte.Dock.Justify ? layoutsContainer.width + 0.5*iconMargin : layoutsContainer.mainLayout.width + iconMargin) : Screen.width //on unlocked state use the maximum Layout.preferredHeight: plasmoid.immutable ? (plasmoid.configuration.panelPosition === Latte.Dock.Justify ? layoutsContainer.height + 0.5*iconMargin : layoutsContainer.mainLayout.height + iconMargin) : Screen.height //on unlocked state use the maximum*/ 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 iconSize { NumberAnimation { duration: 200 onRunningChanged: { if (!running) { delayUpdateMaskArea.start(); } } } } //// END OF Behaviors //////////////START OF CONNECTIONS onContainsOnlyPlasmaTasksChanged: updateAutomaticIconSize(); onEditModeChanged: { if (editMode) { visibilityManager.updateMaskArea(); } else { updateAutomaticIconSize(); layoutsContainer.updateSizeForAppletsInFill(); } updateLayouts(); //! 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; } } onDockChanged: { if (dock) { dock.onAddInternalViewSplitter.connect(addInternalViewSplitters); dock.onRemoveInternalViewSplitter.connect(removeInternalViewSplitters); dock.onXChanged.connect(visibilityManager.updateMaskArea); dock.onYChanged.connect(visibilityManager.updateMaskArea); dock.onWidthChanged.connect(visibilityManager.updateMaskArea); dock.onHeightChanged.connect(visibilityManager.updateMaskArea); dock.visibility.onContainsMouseChanged.connect(visibilityManager.slotContainsMouseChanged); dock.visibility.onMustBeHide.connect(visibilityManager.slotMustBeHide); dock.visibility.onMustBeShown.connect(visibilityManager.slotMustBeShown); updateContainsOnlyPlasmaTasks(); } } onDragEnter: { if (plasmoid.immutable) { 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; } } } if (!confirmedDragEntered) { confirmedDragEntered = true; slotAnimationsNeedLength(1); } if (!latteApplet || (latteApplet && !dock.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) { return; } if (latteApplet) { if (latteApplet.launchersDrop(event)) { root.addLaunchersMessage = true; if (root.addLaunchersInTaskManager) { return; } } } if (!latteApplet || (latteApplet && !dock.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: { //var relevantLayout = layoutsContainer.mainLayout.mapFromItem(root, event.x, event.y); //plasmoid.processMimeData(event.mimeData, relevantLayout.x, relevantLayout.y); //launchersDropped 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 && !dock.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(); 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; } } onIsVerticalChanged: { if (isVertical) { if (plasmoid.configuration.panelPosition === Latte.Dock.Left) plasmoid.configuration.panelPosition = Latte.Dock.Top; else if (plasmoid.configuration.panelPosition === Latte.Dock.Right) plasmoid.configuration.panelPosition = Latte.Dock.Bottom; } else { if (plasmoid.configuration.panelPosition === Latte.Dock.Top) plasmoid.configuration.panelPosition = Latte.Dock.Left; else if (plasmoid.configuration.panelPosition === Latte.Dock.Bottom) plasmoid.configuration.panelPosition = Latte.Dock.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; if (!plasmoid.immutable) { inStartup = false; } } Component.onDestruction: { console.debug("Destroying Latte Dock Containment ui..."); if (dock) { dock.onAddInternalViewSplitter.disconnect(addInternalViewSplitters); dock.onRemoveInternalViewSplitter.disconnect(removeInternalViewSplitters); dock.onXChanged.disconnect(visibilityManager.updateMaskArea); dock.onYChanged.disconnect(visibilityManager.updateMaskArea); dock.onWidthChanged.disconnect(visibilityManager.updateMaskArea); dock.onHeightChanged.disconnect(visibilityManager.updateMaskArea); if (dock.visibility) { dock.visibility.onContainsMouseChanged.disconnect(visibilityManager.slotContainsMouseChanged); dock.visibility.onMustBeHide.disconnect(visibilityManager.slotMustBeHide); dock.visibility.onMustBeShown.disconnect(visibilityManager.slotMustBeShown); } } } Containment.onAppletAdded: { addApplet(applet, x, y); 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; } LayoutManager.save(); updateIndexes(); updateContainsOnlyPlasmaTasks(); } Plasmoid.onUserConfiguringChanged: { if (plasmoid.immutable) { if (dragOverlay) { dragOverlay.destroy(); } return; } // console.debug("user configuring", plasmoid.userConfiguring) if (plasmoid.userConfiguring) { dock.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("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 { dock.setBlockHiding(false); if (dock.visibility.isHidden) { dock.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 dock becomes too small ///to add applets if (plasmoid.immutable) { if(root.isHorizontal) { root.Layout.preferredWidth = (plasmoid.configuration.panelPosition === Latte.Dock.Justify ? layoutsContainer.width + 0.5*iconMargin : layoutsContainer.mainLayout.width + iconMargin); } else { root.Layout.preferredHeight = (plasmoid.configuration.panelPosition === Latte.Dock.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(root) container.applet = applet; applet.parent = container.appletWrapper; applet.anchors.fill = container.appletWrapper; applet.visible = true; // don't show applet if it choses 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 occurence that we'd like to abstract it further in the future // and get rid of the uglyness 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(){ addInternalViewSplitter(-1); addInternalViewSplitter(-1); } 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)); } layoutManager.save(); } } //! 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(){ layoutsContainer.currentSpot = -1000; layoutsContainer.hoveredIndex = -1; if (latteApplet){ latteApplet.clearZoom(); } root.clearZoomSignal(); } function containmentActions(){ return dock.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++; } } for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters++; } } for (var container in layoutsContainer.endLayout.children) { var item = layoutsContainer.endLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters++; } } return splitters; } 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) || (!dock)) { return; } actionsBlockHiding = Math.max(actionsBlockHiding + step, 0); if (actionsBlockHiding > 0){ dock.setBlockHiding(true); } else { if (!root.editMode) dock.setBlockHiding(false); } } function slotPreviewsShown(){ if (dock) { dock.deactivateApplets(); } } function startEnableDirectRenderTimer(){ if (!enableDirectRenderTimer.running) enableDirectRenderTimer.start(); } function startCheckRestoreZoomTimer(){ checkRestoreZoom.start(); } function setGlobalDirectRender(value) { if (latteApplet && latteApplet.waitingLaunchers.length > 0) return; root.globalDirectRender = value; } function updateAutomaticIconSize() { if ((visibilityManager.normalState && !root.editMode && (root.autoDecreaseIconSize || (!root.autoDecreaseIconSize && root.iconSize!=root.maxIconSize))) && (iconSize===root.maxIconSize || iconSize === automaticIconSizeBasedSize) ) { var layoutLength; var maxLength = root.maxLength; //console.log("------Entered check-----"); //console.log("max length: "+ maxLength); if (root.isVertical) { layoutLength = (plasmoid.configuration.panelPosition === Latte.Dock.Justify) ? layoutsContainer.startLayout.height+layoutsContainer.mainLayout.height+layoutsContainer.endLayout.height : layoutsContainer.mainLayout.height } else { layoutLength = (plasmoid.configuration.panelPosition === Latte.Dock.Justify) ? layoutsContainer.startLayout.width+layoutsContainer.mainLayout.width+layoutsContainer.endLayout.width : layoutsContainer.mainLayout.width } var toShrinkLimit = maxLength-((root.zoomFactor-1)*(iconSize+2*iconMargin)); var toGrowLimit = maxLength-1.5*((root.zoomFactor-1)*(iconSize+2*iconMargin)); 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; console.log("Step 3 - found:"+automaticIconSizeBasedSize); } else if ((layoutLength 0) { if (foundGoodSize === root.maxIconSize) { automaticIconSizeBasedSize = -1; } else { automaticIconSizeBasedSize = foundGoodSize; } // console.log("Step 4 - found:"+automaticIconSizeBasedSize); } else { // console.log("Step 4 - did not found..."); } } } } function updateContainsOnlyPlasmaTasks() { if (dock) { root.containsOnlyPlasmaTasks = (dock.tasksPresent() && !dock.latteTasksPresent()); } else { root.containsOnlyPlasmaTasks = false; } } function updateSizeForAppletsInFill() { layoutsContainer.updateSizeForAppletsInFill(); } function updateLayouts(){ if(!root.editMode){ // console.log("update layout - internal view splitters count:"+internalViewSplittersCount()); if (internalViewSplittersCount() === 2) { 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; } } } updateIndexes(); } //END functions ////BEGIN interfaces Connections { target: Latte.WindowSystem onCompositingActiveChanged: { visibilityManager.updateMaskArea(); } } Connections { target: dock onWidthChanged:{ if (root.isHorizontal && proportionIconSize!==-1) updateAutomaticIconSize(); } onHeightChanged:{ if (root.isVertical && proportionIconSize!==-1) updateAutomaticIconSize(); } onContextMenuIsShownChanged: { if (!dock.contextMenuIsShown) { checkRestoreZoom.start(); } else { root.globalDirectRender = false; } } } Connections{ target: dock && dock.visibility ? dock.visibility : root ignoreUnknownSignals : true onContainsMouseChanged: { if (dock.visibility.containsMouse) { if (checkRestoreZoom.running) checkRestoreZoom.stop(); } else { checkRestoreZoom.start(); } } } ////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 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; } showTitleTooltipTimer.start(); } function update() { activeItemHovered = true title = activeItemText; visualParent = activeItemTooltipParent; visible = true; } } Timer { id: showTitleTooltipTimer interval: 100 onTriggered: { if (dock && dock.visibility && dock.visibility.containsMouse) { titleTooltipDialog.update(); } } } Timer { id: hideTitleTooltipTimer interval: 200 onTriggered: { if (!titleTooltipDialog.activeItemHovered) { titleTooltipDialog.visible = false; if (dock && dock.visibility && !dock.visibility.containsMouse) { enableDirectRenderTimer.stop(); setGlobalDirectRender(false); } } } } /////END: Title Tooltip/////////// ///////////////BEGIN components Component { id: appletContainerComponent Applet.AppletItem{} } ParabolicManager{ id: _parabolicManager } ///////////////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 MouseArea{ id: rootMouseArea anchors.fill: parent hoverEnabled: true onEntered: { if(!root.editMode) checkRestoreZoom.start(); } } 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: "../icons/wheatprint.jpg" } } Loader{ id: windowsModel active: (plasmoid.configuration.backgroundOnlyOnMaximized || root.disablePanelShadowMaximized) && dock property bool hasMaximizedWindow: active && item ? item.maximizedWindowOnScreen : false sourceComponent: WindowsModel{} } EditModeVisual{ id:editModeVisual z: root.behaveAsPlasmaPanel ? 1 : 0 } Item{ anchors.fill:layoutsContainer z: root.behaveAsPlasmaPanel ? 0 : 1 PanelBox{} } 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.statesLineSize + root.iconSize + root.thickMargin - 1 //visibilityManager.statesLineSizeOriginal + root.maxIconSize + visibilityManager.iconMarginOriginal - 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 } LayoutsContainer { id: layoutsContainer } ///////////////END UI elements ///////////////BEGIN TIMER elements //Timer to check if the mouse is still outside the dock in order to restore zooms to 1.0 Timer{ id:checkRestoreZoom repeat:false; interval: 150; onTriggered: { if (latteApplet && (latteApplet.previewContainsMouse() || latteApplet.contextMenu)) return; if (dock.contextMenuIsShown) return; //! dropped because was creating a glitch when the user was clicking the area //! underneath the applet until the screen edge and the applet was zoomed // || (rootMouseArea.containsMouse && !root.editMode) if (!dock.visibility.containsMouse || !mouseInCanBeHoveredApplet()) { if (enableDirectRenderTimer.running) enableDirectRenderTimer.stop(); root.globalDirectRender = false; root.clearZoom(); } } } //this timer adds a delay into enabling direct rendering... //it gives the time to neighbour tasks to complete their animation //during first hovering phase Timer { id: enableDirectRenderTimer interval: 4 * root.durationTime * units.shortDuration onTriggered: { if (latteApplet && latteApplet.waitingLaunchers.length > 0) return; if (dock.visibility.containsMouse) root.globalDirectRender = true; } } //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(); } } ///////////////END TIMER elements } diff --git a/plasmoid/package/contents/ui/main.qml b/plasmoid/package/contents/ui/main.qml index c21c7cf4..97a54299 100644 --- a/plasmoid/package/contents/ui/main.qml +++ b/plasmoid/package/contents/ui/main.qml @@ -1,1723 +1,1725 @@ /* * 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.1 as Latte import "task" as Task import "../code/tools.js" as TaskTools import "../code/activitiesTools.js" as ActivitiesTools Item { id:root // Layout.fillHeight: userPanelPosition === 0 ? true : false // Layout.fillWidth: userPanelPosition === 0 ? 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)&&(!latteDock) ? clearWidth : -1 Layout.minimumHeight: (userPanelPosition !== 0)&&(!latteDock) ? clearHeight : -1 Layout.preferredWidth: (userPanelPosition !== 0)&&(!latteDock) ? tasksWidth : -1 Layout.preferredHeight: (userPanelPosition !== 0)&&(!latteDock) ? tasksHeight : -1 + LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft + LayoutMirroring.childrenInherit: true property bool debugLocation: false //it is used to check both the applet and the containment for direct render property bool globalDirectRender: latteDock ? latteDock.globalDirectRender : icList.directRender property bool directRenderTimerIsRunning: latteDock ? latteDock.directRenderTimerIsRunning : enableDirectRenderTimer.running property bool editMode: latteDock ? latteDock.editMode : plasmoid.userConfiguring property bool disableRestoreZoom: false //blocks restore animation in rightClick property bool dropNewLauncher: false readonly property bool hasInternalSeparator: parabolicManager.hasInternalSeparator readonly property bool internalSeparatorHidden: parabolicManager.internalSeparatorHidden property bool inActivityChange: false property bool initializationStep: false //true property bool initializatedBuffers: true // noInitCreatedBuffers >= tasksStarting ? true : false property bool isHovered: false property bool showBarLine: plasmoid.configuration.showBarLine property bool showTasksNumbers: false 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 int clearWidth property int clearHeight readonly property int internalSeparatorPos: parabolicManager.internalSeparatorPos 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 property int realSize: iconSize + iconMargin ///Dont use Math.floor it adds one pixel in animations and creates glitches property int widthMargins: root.vertical ? thickMargin : iconMargin property int heightMargins: !root.vertical ? thickMargin : iconMargin property real textColorLuma: 0.2126*theme.textColor.r + 0.7152*theme.textColor.g + 0.0722*theme.textColor.b //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: [] //global plasmoid reference to the context menu property QtObject contextMenu: null property QtObject contextMenuComponent: Qt.createComponent("ContextMenu.qml"); property Item dragSource: null property Item parabolicManager: _parabolicManager property color minimizedDotColor: textColorLuma > 0.5 ? Qt.darker(theme.textColor, 1+ (1-textColorLuma)) : Qt.lighter(theme.textColor, 1+(1-textColorLuma)) //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 enableShadows: latteDock ? latteDock.enableShadows > 0 : plasmoid.configuration.showShadows property bool forceHidePanel: false property bool disableLeftSpacer: false property bool disableRightSpacer: false property bool dockIsHidden: latteDock ? latteDock.dockIsHidden : false property bool highlightWindows: latteDock ? latteDock.highlightWindows: plasmoid.configuration.highlightWindows property bool indicateAudioStreams: latteDock ? latteDock.indicateAudioStreams : plasmoid.configuration.indicateAudioStreams property bool mouseWheelActions: latteDock ? latteDock.mouseWheelActions : true property bool reverseLinesPosition: latteDock ? latteDock.reverseLinesPosition : plasmoid.configuration.reverseLinesPosition property bool dotsOnActive: latteDock ? latteDock.dotsOnActive : plasmoid.configuration.dotsOnActive property bool showGlow: latteDock ? latteDock.showGlow : plasmoid.configuration.showGlow property bool showOnlyCurrentScreen: latteDock ? latteDock.showOnlyCurrentScreen : plasmoid.configuration.showOnlyCurrentScreen property bool showOnlyCurrentDesktop: latteDock ? latteDock.showOnlyCurrentDesktop : plasmoid.configuration.showOnlyCurrentDesktop property bool showOnlyCurrentActivity: latteDock ? latteDock.showOnlyCurrentActivity : plasmoid.configuration.showOnlyCurrentActivity property bool showPreviews: latteDock ? latteDock.showToolTips : plasmoid.configuration.showToolTips property bool showWindowActions: latteDock ? latteDock.showWindowActions : plasmoid.configuration.showWindowActions property bool smartLaunchersEnabled: latteDock ? latteDock.smartLaunchersEnabled : plasmoid.configuration.smartLaunchersEnabled property bool threeColorsWindows: latteDock ? latteDock.threeColorsWindows : plasmoid.configuration.threeColorsWindows property bool titleTooltips: latteDock ? latteDock.titleTooltips : false property int directRenderAnimationTime: latteDock ? latteDock.directRenderAnimationTime : 0 property int dockHoveredIndex : latteDock ? latteDock.hoveredIndex : -1 property int iconMargin: latteDock ? latteDock.iconMargin : 0.12*iconSize property int iconSize: latteDock ? latteDock.iconSize : Math.max(plasmoid.configuration.iconSize, 16) property int middleClickAction: latteDock ? latteDock.middleClickAction : plasmoid.configuration.middleClickAction property int modifier: latteDock ? latteDock.modifier : -1 property int modifierClickAction: latteDock ? latteDock.modifierClickAction : -1 property int modifierClick: latteDock ? latteDock.modifierClick : -1 property int modifierQt:{ if (modifier === Latte.Dock.Shift) return Qt.ShiftModifier; else if (modifier === Latte.Dock.Ctrl) return Qt.ControlModifier; else if (modifier === Latte.Dock.Alt) return Qt.AltModifier; else if (modifier === Latte.Dock.Meta) return Qt.MetaModifier; else return -1; } //decouple iconMargin which now is used only for length calculations with thickMargins //which are used for thickness calculations property int thickMarginBase: latteDock ? latteDock.thickMarginBase : Math.ceil(iconMargin/2) property int thickMarginHigh: latteDock ? latteDock.thickMarginHigh : Math.ceil(iconMargin/2) property int thickMargin: thickMarginBase + thickMarginHigh property int statesLineSize: latteDock ? latteDock.statesLineSize : Math.ceil( root.iconSize/13 ) property int tasksHeight: mouseHandler.height property int tasksWidth: mouseHandler.width property int userPanelPosition: latteDock ? latteDock.panelAlignment : plasmoid.configuration.plasmoidPosition property real durationTime: latteDock ? latteDock.durationTime : plasmoid.configuration.durationTime property real zoomFactor: latteDock ? latteDock.zoomFactor : ( 1 + (plasmoid.configuration.zoomLevel / 20) ) property int appShadowSize: latteDock ? latteDock.appShadowSize : Math.ceil(0.12*iconSize) property string appShadowColor: latteDock ? latteDock.appShadowColor : "#ff080808" property alias tasksCount: tasksModel.count property alias hoveredIndex: icList.hoveredIndex property QtObject currentLayout : latteDock && latteDock.universalLayoutManager && latteDock.universalLayoutManager.currentLayout ? latteDock.universalLayoutManager.currentLayout : null property Item latteDock: null //END Now Dock Panel properties Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation Plasmoid.backgroundHints: PlasmaCore.Types.NoBackground signal clearZoomSignal(); signal draggingFinished(); signal presentWindows(variant winIds); signal requestLayout; 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" } */ onLatteDockChanged: { if (latteDock) 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: latteDock onDockIsHiddenChanged:{ if (latteDock.dockIsHidden) { windowsPreviewDlg.hide(); } } } ///// PlasmaCore.ColorScope{ id: colorScopePalette } ///// 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= 0) { hasSep = true; break; } } if (!hasSep) parabolicManager.internalSeparatorPos = -1; } function updateLaunchersList(){ if (latteDock.universalSettings && (latteDock.launchersGroup === Latte.Dock.LayoutLaunchers || latteDock.launchersGroup === Latte.Dock.GlobalLaunchers)) { if (latteDock.launchersGroup === Latte.Dock.LayoutLaunchers) { tasksModel.launcherList = latteDock.universalLayoutManager.currentLayout.launchers; } else if (latteDock.launchersGroup === Latte.Dock.GlobalLaunchers) { tasksModel.launcherList = latteDock.universalSettings.launchers; } } else { tasksModel.launcherList = plasmoid.configuration.launchers59; } } onActivityChanged: { ActivitiesTools.currentActivity = String(activity); } onLauncherListChanged: { if (currentLayout) { if (latteDock && latteDock.universalLayoutManager && latteDock.universalLayoutManager.currentLayout && latteDock.universalSettings && (latteDock.launchersGroup === Latte.Dock.LayoutLaunchers || latteDock.launchersGroup === Latte.Dock.GlobalLaunchers)) { if (latteDock.launchersGroup === Latte.Dock.LayoutLaunchers) { latteDock.universalLayoutManager.currentLayout.launchers = launcherList; } else if (latteDock.launchersGroup === Latte.Dock.GlobalLaunchers) { latteDock.universalSettings.launchers = launcherList; } } else { plasmoid.configuration.launchers59 = launcherList; } checkSeparator(); } } 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 && latteDock.universalSettings && (latteDock.launchersGroup === Latte.Dock.LayoutLaunchers || latteDock.launchersGroup === Latte.Dock.GlobalLaunchers)) { if (latteDock.launchersGroup === Latte.Dock.LayoutLaunchers) { launcherList = latteDock.universalLayoutManager.currentLayout.launchers; } else if (latteDock.launchersGroup === Latte.Dock.GlobalLaunchers) { launcherList = latteDock.universalSettings.launchers; } } else { launcherList = plasmoid.configuration.launchers59; } groupingAppIdBlacklist = plasmoid.configuration.groupingAppIdBlacklist; groupingLauncherUrlBlacklist = plasmoid.configuration.groupingLauncherUrlBlacklist; icList.model = tasksModel; tasksStarting = count; checkSeparator(); ///Plasma 5.9 enforce grouping at all cases if (Latte.WindowSystem.frameworksVersion >= 335104) { 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", "") 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 && (pid === undefined || sourceData.InstancePid === pid)) { 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.indicateAudioStreams } ParabolicManager{ id: _parabolicManager } /* IconsModel{ id: iconsmdl }*/ Component{ id: attentionTimerComponent Timer{ id: attentionTimer interval:8500 onTriggered: { plasmoid.status = PlasmaCore.Types.PassiveStatus; destroy(); } 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.latteDock) console.log("Plasmoid, checkListHoveredTimer was called, even though it shouldnt..."); if (!root.containsMouse()) { if (enableDirectRenderTimer.running) enableDirectRenderTimer.stop(); icList.directRender = false; if(root.latteDock) { root.latteDock.globalDirectRender = false; root.latteDock.clearZoom(); } root.clearZoom(); } interval = normalInterval; } function startNormal(){ interval = normalInterval; start(); } function startDuration( duration){ interval = duration; start(); } } //this timer adds a delay into enabling direct rendering... //it gives the time to neighbour tasks to complete their animation //during first hovering phase //IMPORTANT ::: This timer should be used only when the Latte plasmoid //is not inside a Latte dock Timer { id: enableDirectRenderTimer interval: 4 * root.durationTime * units.shortDuration onTriggered: { if(root.latteDock) console.log("Plasmoid, enableDirectRenderTimer was called, even though it shouldnt..."); if (waitingLaunchers.length > 0) restart(); else icList.directRender = true; } } ///Red Liner!!! show the upper needed limit for annimations 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+iconMargin) + statesLineSize } Item{ id:barLine opacity: (tasksModel.count > 0) && root.initializatedBuffers ? 1 : 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 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(3.7*root.statesLineSize, 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.horizontalCenter: !root.vertical ? icList.horizontalCenter : undefined anchors.verticalCenter: root.vertical ? icList.verticalCenter : undefined width: root.vertical ? maxSize : icList.width height: root.vertical ? icList.height : maxSize target: icList property int maxSize: ((root.hoveredIndex>=0 || dockHoveredIndex>=0 ) && !root.dragSource) ? root.statesLineSize + root.zoomFactor * (root.iconSize + root.thickMargin) : root.statesLineSize + root.iconSize + root.thickMargin function urlsDroppedOnArea(urls){ // If all dropped URLs point to application desktop files, we'll add a launcher for each of them. var createLaunchers = urls.every(function (item) { return backend.isApplication(item) }); if (createLaunchers) { 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: { if (latteDock && latteDock.launchersGroup >= Latte.Dock.LayoutLaunchers) { latteDock.universalLayoutManager.launchersSignals.urlsDropped(latteDock.launchersGroup, urls); } else { urlsDroppedOnArea(urls); } } } ListView { id:icList boundsBehavior: Flickable.StopAtBounds property int currentSpot : -1000 property int hoveredIndex : -1 property int previousCount : 0 property int tasksCount: tasksModel.count property bool delayingRemoval: false property bool directRender: false // onTasksCountChanged: updateImplicits(); // 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 anchors.horizontalCenter: !root.vertical ? parent.horizontalCenter : undefined anchors.verticalCenter: root.vertical ? parent.verticalCenter : undefined */ width: !root.vertical ? contentWidth : mouseHandler.maxSize height: root.vertical ? contentHeight : mouseHandler.maxSize orientation: Qt.Horizontal delegate: Task.TaskDelegate{} /* Rectangle{ anchors.fill: parent border.width: 1 border.color: "red" color: "transparent" } */ //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 } } ///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 childAtPos(x, y){ var tasks = icList.contentItem.children; for(var i=0; i=choords.x) && (x<=choords.x+task.width) && (y>=choords.y) && (y<=choords.y+task.height)){ return task; } } return null; } function childAtIndex(position) { var tasks = icList.contentItem.children; if (position < 0) return; for(var i=0; i=parabolicManager.internalSeparatorPos) ? index+1 : index; for(var i=0; i=parabolicManager.internalSeparatorPos) ? index+1 : index; 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 === latteDock.launchersGroup) { tasksModel.requestAddLauncher(launcher); } } function extSignalRemoveLauncher(group, launcher) { if (group === latteDock.launchersGroup) { root.launcherForRemoval = launcher; tasksModel.requestRemoveLauncher(launcher); } } function extSignalAddLauncherToActivity(group, launcher, activity) { if (group === latteDock.launchersGroup) { var launcherActivities = tasksModel.launcherActivities(launcher); if (activity !== tasksModel.activity && (launcherActivities[0] === "00000000-0000-0000-0000-000000000000")) { root.launcherForRemoval = launcher; } tasksModel.requestAddLauncherToActivity(launcher, activity); } } function extSignalRemoveLauncherFromActivity(group, launcher, activity) { if (group === latteDock.launchersGroup) { if (activity === tasksModel.activity) { root.launcherForRemoval = launcher; } tasksModel.requestRemoveLauncherFromActivity(launcher, activity); } } function extSignalUrlsDropped(group, urls) { if (group === latteDock.launchersGroup) { mouseHandler.urlsDroppedOnArea(urls); } } function extSignalMoveTask(group, from, to) { if (group === latteDock.launchersGroup) { tasksModel.move(from, to); } } //! 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(){ tasksModel.requestAddLauncher("file:///latte-separator.desktop"); } function removeSeparator(){ tasksModel.requestRemoveLauncher("file:///latte-separator.desktop"); } function setShowTasksNumbers(showNumbers){ root.showTasksNumbers = showNumbers; } 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); //console.log("s3..."); var tasks = icList.contentItem.children; for(var i=0; i0) { url = url.substring( 0, url.indexOf("?iconData=" ) ); } tasksModel.requestAddLauncher(url); } function resetDragSource() { dragSource.z = 0; dragSource = null; } function startEnableDirectRenderTimer() { if (latteDock) { latteDock.setGlobalDirectRender(true); latteDock.startEnableDirectRenderTimer(); } else { enableDirectRenderTimer.start(); } } function startCheckRestoreZoomTimer() { if (latteDock) { latteDock.startCheckRestoreZoomTimer(); } else { checkListHovered.startNormal(); } } ///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.Dock.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.Dock.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.Dock.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.Dock.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.Dock.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.Dock.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.Dock.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.Dock.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.Dock.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.Dock.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.Dock.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.Dock.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/shell/package/contents/configuration/LatteDockConfiguration.qml b/shell/package/contents/configuration/LatteDockConfiguration.qml index 42aca1d9..d21c4836 100644 --- a/shell/package/contents/configuration/LatteDockConfiguration.qml +++ b/shell/package/contents/configuration/LatteDockConfiguration.qml @@ -1,381 +1,383 @@ /* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import QtQuick 2.7 import QtQuick.Controls 1.4 import QtQuick.Layouts 1.3 import QtGraphicalEffects 1.0 import QtQuick.Window 2.2 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import QtQuick.Controls.Styles.Plasma 2.0 as Styles import org.kde.plasma.plasmoid 2.0 import org.kde.kquickcontrolsaddons 2.0 as KQuickControlAddons import org.kde.latte 0.1 as Latte PlasmaCore.FrameSvgItem { id: dialog imagePath: "dialogs/background" property int maxWidth: 34 * theme.defaultFont.pixelSize width: maxWidth + units.smallSpacing * 2 height: content.height + units.smallSpacing * 2 Layout.minimumWidth: width Layout.minimumHeight: height + LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft + LayoutMirroring.childrenInherit: true property bool panelIsVertical: plasmoid.formFactor === PlasmaCore.Types.Vertical property int subGroupSpacing: units.largeSpacing + units.smallSpacing * 1.5 PlasmaComponents.ToolButton { id: pinButton anchors.right: parent.right anchors.top: parent.top Layout.fillWidth: false Layout.fillHeight: false Layout.preferredWidth: width Layout.preferredHeight: height Layout.alignment: Qt.AlignRight | Qt.AlignVCenter iconSource: "window-pin" checkable: true width: Math.round(units.gridUnit * 1.25) height: width property bool inStartup: true onClicked: { plasmoid.configuration.configurationSticker = checked dockConfig.setSticker(checked) } Component.onCompleted: { checked = plasmoid.configuration.configurationSticker dockConfig.setSticker(plasmoid.configuration.configurationSticker) } } ColumnLayout { id: content Layout.minimumWidth: width Layout.minimumHeight: height Layout.preferredWidth: width Layout.preferredHeight: height height: header.height + tabBar.height + pagesBackground.height + actionButtons.height + spacing * 3 width: dialog.maxWidth anchors.horizontalCenter: parent.horizontalCenter anchors.top: parent.top spacing: units.smallSpacing RowLayout { id: header Layout.fillWidth: true spacing: 0 Item { Layout.alignment: Qt.AlignLeft | Qt.AlignHCenter Layout.fillWidth: false Layout.preferredWidth: width Layout.preferredHeight: height width: logo.width + latteTxt.width + units.smallSpacing height: logo.height PlasmaCore.IconItem { id: logo width: 1.5 * latteTxt.font.pixelSize height: width source: "latte-dock" animated: true usesPlasmaTheme: false active: aboutMouseArea.containsMouse } PlasmaComponents.Label { id: latteTxt height: logo.height verticalAlignment: Text.AlignVCenter text: "atte" font.family: "Tangerine" font.pointSize: 2 * theme.defaultFont.pointSize font.italic: true anchors.left: logo.right } MouseArea { id: aboutMouseArea acceptedButtons: Qt.LeftButton anchors.fill: parent hoverEnabled: true onClicked: dockConfig.aboutApplication() } } RowLayout { Layout.fillWidth: true Layout.rightMargin: units.smallSpacing Layout.alignment: Qt.AlignRight | Qt.AlignBottom PlasmaComponents.Label { Layout.fillWidth: true Layout.alignment: Qt.AlignRight } PlasmaComponents.Label { text: i18n("Advanced") Layout.alignment: Qt.AlignRight opacity: plasmoid.configuration.advanced ? 1 : 0.3 } Switch { id: advancedSwitch checked: plasmoid.configuration.advanced onPressedChanged: { if(pressed) plasmoid.configuration.advanced = !checked; } style: Styles.SwitchStyle { property bool checked: advancedSwitch.checked } onCheckedChanged: { if (!checked && tabGroup.currentTab === tweaksPage) { if (tasksTabBtn.visible) { tabGroup.currentTab = tasksPage; tabBar.currentTab = tasksTabBtn; } else { tabGroup.currentTab = appearancePage; tabBar.currentTab = appearanceTabBtn; } } } } } } PlasmaComponents.TabBar { id: tabBar Layout.fillWidth: true Layout.maximumWidth: maxWidth PlasmaComponents.TabButton { id: behaviorTabBtn text: i18n("Behavior") tab: behaviorPage } PlasmaComponents.TabButton { id: appearanceTabBtn text: i18n("Appearance") tab: appearancePage } PlasmaComponents.TabButton { id: tasksTabBtn text: i18n("Tasks") tab: tasksPage visible: dock.latteTasksPresent() } PlasmaComponents.TabButton { text: i18n("Tweaks") tab: tweaksPage visible: plasmoid.configuration.advanced } } Rectangle { id: pagesBackground Layout.fillWidth: true Layout.fillHeight: false Layout.minimumWidth: maxWidth - 2*units.smallSpacing Layout.minimumHeight: height Layout.maximumHeight: height width: maxWidth - units.smallSpacing height: behaviorPage.Layout.maximumHeight + units.smallSpacing * 4 property color bC: theme.backgroundColor property color transparentBack: Qt.rgba(bC.r, bC.g, bC.b, 0.7) color: transparentBack border.width: 1 border.color: theme.backgroundColor PlasmaExtras.ScrollArea { id: scrollArea anchors.fill: parent verticalScrollBarPolicy: Qt.ScrollBarAsNeeded horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff flickableItem.flickableDirection: Flickable.VerticalFlick PlasmaComponents.TabGroup { id: tabGroup width: currentTab.Layout.maximumWidth height: currentTab.Layout.maximumHeight BehaviorConfig { id: behaviorPage } AppearanceConfig { id: appearancePage } TasksConfig { id: tasksPage } TweaksConfig { id: tweaksPage } } } } RowLayout { id: actionButtons Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom spacing: units.largeSpacing Connections{ target: dock onDocksCountChanged: actionButtons.updateEnabled(); } function updateEnabled() { addDock.enabled = dock.docksCount < 4 && dock.freeEdges().length > 0 removeDock.enabled = dock.docksCount>1 && !(dock.docksWithTasks()===1 && dock.tasksPresent()) } PlasmaComponents.Button { Layout.alignment: Qt.AlignLeft Layout.fillWidth: true text:" " PlasmaComponents.ComboBox { id: actionsCmb anchors.fill: parent enabled: addDock.enabled function addModel() { var actions = [] actions.push(" " + i18n("Copy Dock")); actionsCmb.model = actions; actionsCmb.currentIndex = -1; } function emptyModel() { var actions = [] actions.push(" "); actionsCmb.model = actions; actionsCmb.currentIndex = -1; } Component.onCompleted:{ addModel(); } onActivated: { if (index==0) { dock.copyDock(); } actionsCmb.currentIndex = -1; } onEnabledChanged: { if (enabled) addModel(); else emptyModel(); } } //overlayed button PlasmaComponents.Button { id: addDock width: parent.width - units.iconSizes.medium + 2*units.smallSpacing height: parent.height text: i18n("New Dock") iconSource: "list-add" tooltip: i18n("Add a new dock") onClicked: dock.addNewDock() Component.onCompleted: { enabled = dock.freeEdges().length > 0 } } } PlasmaComponents.Button { id: removeDock Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter text: i18n("Remove") iconSource: "edit-delete" opacity: dock.totalDocksCount > 1 ? 1 : 0 tooltip: i18n("Remove current dock") onClicked: dock.removeDock() } PlasmaComponents.Button { id: quit Layout.fillWidth: true Layout.alignment: Qt.AlignRight text: i18n("Quit") iconSource: "application-exit" tooltip: i18n("Quit Latte") onClicked: dock.closeApplication() } } } }