diff --git a/containment/package/contents/ui/main.qml b/containment/package/contents/ui/main.qml index 07e83150..3cdf3d6d 100644 --- a/containment/package/contents/ui/main.qml +++ b/containment/package/contents/ui/main.qml @@ -1,1587 +1,1591 @@ /* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import QtQuick 2.8 import QtQuick.Layouts 1.1 import QtQuick.Window 2.2 import QtGraphicalEffects 1.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 import org.kde.plasma.plasmoid 2.0 import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.components 1.0 as LatteComponents import org.kde.latte.private.app 0.1 as LatteApp import org.kde.latte.private.containment 0.1 as LatteContainment import "abilities" as Ability import "applet" as Applet import "colorizer" as Colorizer import "editmode" as EditMode import "indicators" as Indicators import "layouts" as Layouts import "./background" as Background import "./debug" as Debug import "../code/LayoutManager.js" as LayoutManager Item { id: root objectName: "containmentViewLayout" LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft && !root.isVertical LayoutMirroring.childrenInherit: true //// BEGIN SIGNALS signal destroyInternalViewSplitters(); signal emptyAreasWheel(QtObject wheel); signal separatorsUpdated(); signal updateEffectsArea(); signal updateIndexes(); signal broadcastedToApplet(string pluginName, string action, variant value); //// END SIGNALS ////BEGIN properties property bool debugMode: Qt.application.arguments.indexOf("--graphics")>=0 property bool debugModeLayouter: Qt.application.arguments.indexOf("--layouter")>=0 property bool debugModeLocalGeometry: Qt.application.arguments.indexOf("--localgeometry")>=0 property bool debugModeSpacers: Qt.application.arguments.indexOf("--spacers")>=0 property bool debugModeTimers: Qt.application.arguments.indexOf("--timers")>=0 property bool debugModeWindow: Qt.application.arguments.indexOf("--with-window")>=0 property bool debugModeOverloadedIcons: Qt.application.arguments.indexOf("--overloaded-icons")>=0 readonly property int version: LatteCore.Environment.makeVersion(0,9,4) property bool addLaunchersMessage: false - property bool addLaunchersInTaskManager: plasmoid.configuration.addLaunchersInTaskManager && latteView && (latteView.extendedInterface.latteTasksModel.count === 1) + property bool addLaunchersInTaskManager: plasmoid.configuration.addLaunchersInTaskManager + && latteView + && (latteView.extendedInterface.latteTasksModel.count === 1) + && (latteView.extendedInterface.plasmaTasksModel.count === 0) + property bool backgroundOnlyOnMaximized: plasmoid.configuration.backgroundOnlyOnMaximized property bool behaveAsPlasmaPanel: { if (!LatteCore.WindowSystem.compositingActive) { //! In NOCOMPOSITING mode VIEWS should behave as real windows and that way //! we gain also the snapping features from KWin return true; } if (!latteView || !latteView.visibility) { return false; } if (screenEdgeMarginEnabled && plasmoid.configuration.fittsLawIsRequested) { //! dont use when floating views are requesting Fitt's Law return false; } var staticLayout = (plasmoid.configuration.minLength === plasmoid.configuration.maxLength); return (visibilityManager.panelIsBiggerFromIconSize && (parabolic.factor.maxZoom === 1.0) && (plasmoid.configuration.alignment === LatteCore.Types.Justify || staticLayout) && !root.editMode && !visibilityManager.inLocationAnimation); } readonly property bool behaveAsDockWithMask: !behaveAsPlasmaPanel readonly property bool viewIsAvailable: latteView && latteView.visibility && latteView.effects property int viewType: { var staticLayout = (plasmoid.configuration.minLength === plasmoid.configuration.maxLength); if ((plasmoid.configuration.alignment === LatteCore.Types.Justify || staticLayout) && (plasmoid.configuration.useThemePanel) && (plasmoid.configuration.panelSize === 100) && (parabolic.factor.maxZoom === 1.0)) { return LatteCore.Types.PanelView; } return LatteCore.Types.DockView; } property bool blurEnabled: plasmoid.configuration.blurEnabled && (!forceTransparentPanel || forcePanelForBusyBackground) readonly property bool ignoreRegularFilesDragging: !root.editMode && (dragInfo.computationsAreValid || foreDropArea.dragInfo.computationsAreValid) && !root.dragInfo.isPlasmoid && !root.dragInfo.onlyLaunchers readonly property Item dragInfo: Item { property bool entered: backDropArea.dragInfo.entered || foreDropArea.dragInfo.entered property bool isTask: backDropArea.dragInfo.isTask || foreDropArea.dragInfo.isTask property bool isPlasmoid: backDropArea.dragInfo.isPlasmoid || foreDropArea.dragInfo.isPlasmoid property bool isSeparator: backDropArea.dragInfo.isSeparator || foreDropArea.dragInfo.isSeparator property bool isLatteTasks: backDropArea.dragInfo.isLatteTasks || foreDropArea.dragInfo.isLatteTasks property bool onlyLaunchers: backDropArea.dragInfo.onlyLaunchers || foreDropArea.dragInfo.onlyLaunchers // onIsPlasmoidChanged: console.log("isPlasmoid :: " + backDropArea.dragInfo.isPlasmoid + " _ " + foreDropArea.dragInfo.isPlasmoid ); // onEnteredChanged: console.log("entered :: " + backDropArea.dragInfo.entered + " _ " + foreDropArea.dragInfo.entered ); } property bool containsOnlyPlasmaTasks: latteView ? latteView.extendedInterface.hasPlasmaTasks && !latteView.extendedInterface.hasLatteTasks : false property bool dockContainsMouse: latteView && latteView.visibility ? latteView.visibility.containsMouse : false property bool disablePanelShadowMaximized: plasmoid.configuration.disablePanelShadowForMaximized && LatteCore.WindowSystem.compositingActive property bool drawShadowsExternal: panelShadowsActive && behaveAsPlasmaPanel && !visibilityManager.inTempHiding property bool editMode: editModeVisual.inEditMode property bool windowIsTouching: latteView && latteView.windowsTracker && (latteView.windowsTracker.currentScreen.activeWindowTouching || latteView.windowsTracker.currentScreen.activeWindowTouchingEdge || hasExpandedApplet) property bool forceSolidPanel: (latteView && latteView.visibility && LatteCore.WindowSystem.compositingActive && !inConfigureAppletsMode && userShowPanelBackground && ( (plasmoid.configuration.solidBackgroundForMaximized && !(hasExpandedApplet && !plasmaBackgroundForPopups) && (latteView.windowsTracker.currentScreen.existsWindowTouching || latteView.windowsTracker.currentScreen.existsWindowTouchingEdge)) || (hasExpandedApplet && plasmaBackgroundForPopups) )) || solidBusyForTouchingBusyVerticalView || plasmaStyleBusyForTouchingBusyVerticalView || !LatteCore.WindowSystem.compositingActive property bool forceTransparentPanel: root.backgroundOnlyOnMaximized && latteView && latteView.visibility && LatteCore.WindowSystem.compositingActive && !inConfigureAppletsMode && !forceSolidPanel && !(latteView.windowsTracker.currentScreen.existsWindowTouching || latteView.windowsTracker.currentScreen.existsWindowTouchingEdge) && !(windowColors === LatteContainment.Types.ActiveWindowColors && selectedWindowsTracker.existsWindowActive) property bool forcePanelForBusyBackground: userShowPanelBackground && (root.themeColors === LatteContainment.Types.SmartThemeColors) && ( (root.forceTransparentPanel && colorizerManager.backgroundIsBusy) || normalBusyForTouchingBusyVerticalView ) property bool normalBusyForTouchingBusyVerticalView: (latteView && latteView.windowsTracker /*is touching a vertical view that is in busy state and the user prefers isBusy transparency*/ && latteView.windowsTracker.currentScreen.isTouchingBusyVerticalView && root.themeColors === LatteContainment.Types.SmartThemeColors && plasmoid.configuration.backgroundOnlyOnMaximized /*&& !plasmoid.configuration.solidBackgroundForMaximized && !plasmaBackgroundForPopups*/) property bool solidBusyForTouchingBusyVerticalView: false //DISABLED, until to check if the normalBusyForTouchingBusyVerticalView is enough to catch and handle the case /*(latteView && latteView.windowsTracker /*is touching a vertical view that is in busy state and the user prefers solidness*/ /* && latteView.windowsTracker.currentScreen.isTouchingBusyVerticalView && root.themeColors === LatteContainment.Types.SmartThemeColors && plasmoid.configuration.backgroundOnlyOnMaximized && plasmoid.configuration.solidBackgroundForMaximized && !plasmaBackgroundForPopups)*/ property bool plasmaStyleBusyForTouchingBusyVerticalView: false //DISABLED, until to check if the normalBusyForTouchingBusyVerticalView is enough to catch and handle the case //(latteView && latteView.windowsTracker /*is touching a vertical view that is in busy state and the user prefers solidness*/ /* && latteView.windowsTracker.currentScreen.isTouchingBusyVerticalView && root.themeColors === LatteContainment.Types.SmartThemeColors && plasmoid.configuration.backgroundOnlyOnMaximized && plasmaBackgroundForPopups)*/ property bool hideThickScreenGap: screenEdgeMarginEnabled && plasmoid.configuration.hideScreenGapForMaximized && latteView && latteView.windowsTracker && latteView.windowsTracker.currentScreen.existsWindowMaximized property bool hideLengthScreenGaps: hideThickScreenGap && (latteView.visibility.mode === LatteCore.Types.AlwaysVisible || latteView.visibility.mode === LatteCore.Types.WindowsGoBelow) && (plasmoid.configuration.alignment === LatteCore.Types.Justify) && plasmoid.configuration.maxLength>85 && !root.editMode property int themeColors: plasmoid.configuration.themeColors property int windowColors: plasmoid.configuration.windowColors property bool colorizerEnabled: themeColors !== LatteContainment.Types.PlasmaThemeColors || windowColors !== LatteContainment.Types.NoneWindowColors property bool plasmaBackgroundForPopups: plasmoid.configuration.plasmaBackgroundForPopups readonly property bool hasExpandedApplet: latteView && latteView.extendedInterface.hasExpandedApplet; readonly property bool hasUserSpecifiedBackground: (latteView && latteView.layout && latteView.layout.background.startsWith("/")) ? true : false readonly property bool inConfigureAppletsMode: root.editMode && (plasmoid.configuration.inConfigureAppletsMode || !LatteCore.WindowSystem.compositingActive) readonly property bool parabolicEffectEnabled: parabolic.factor.zoom>1 && !inConfigureAppletsMode property bool dockIsShownCompletely: !(dockIsHidden || inSlidingIn || inSlidingOut) && !root.editMode property bool closeActiveWindowEnabled: plasmoid.configuration.closeActiveWindowEnabled property bool dragActiveWindowEnabled: plasmoid.configuration.dragActiveWindowEnabled property bool immutable: plasmoid.immutable property bool inFullJustify: (plasmoid.configuration.alignment === LatteCore.Types.Justify) && (maxLengthPerCentage===100) property bool inSlidingIn: visibilityManager ? visibilityManager.inSlidingIn : false property bool inSlidingOut: visibilityManager ? visibilityManager.inSlidingOut : false property bool inStartup: true property bool isHalfShown: false //is used to disable the zoom hovering effect at sliding in-out the dock property bool isHorizontal: plasmoid.formFactor === PlasmaCore.Types.Horizontal property bool isReady: !(dockIsHidden || inSlidingIn || inSlidingOut) property bool isVertical: !isHorizontal property bool mouseWheelActions: plasmoid.configuration.mouseWheelActions property bool onlyAddingStarup: true //is used for the initialization phase in startup where there aren't removals, this variable provides a way to grow icon size property bool shrinkThickMargins: plasmoid.configuration.shrinkThickMargins //FIXME: possibly this is going to be the default behavior, this user choice //has been dropped from the Dock Configuration Window //property bool smallAutomaticIconJumps: plasmoid.configuration.smallAutomaticIconJumps property bool smallAutomaticIconJumps: true property bool userShowPanelBackground: LatteCore.WindowSystem.compositingActive ? plasmoid.configuration.useThemePanel : true property bool useThemePanel: noApplets === 0 || !LatteCore.WindowSystem.compositingActive ? true : (plasmoid.configuration.useThemePanel || plasmoid.configuration.solidBackgroundForMaximized) property bool plasma515: LatteCore.Environment.plasmaDesktopVersion >= LatteCore.Environment.makeVersion(5,15,0) property bool plasma518: LatteCore.Environment.plasmaDesktopVersion >= LatteCore.Environment.makeVersion(5,18,0) readonly property int minAppletLengthInConfigure: 16 readonly property int maxJustifySplitterSize: 64 property int latteAppletPos: -1 property real minLengthPerCentage: plasmoid.configuration.minLength property real maxLengthPerCentage: hideLengthScreenGaps ? 100 : plasmoid.configuration.maxLength property int minLength: { if (root.panelAlignment === LatteCore.Types.Justify) { return maxLength; } if (root.isHorizontal) { return behaveAsPlasmaPanel && LatteCore.WindowSystem.compositingActive ? width : width * (minLengthPerCentage/100) } else { return behaveAsPlasmaPanel && LatteCore.WindowSystem.compositingActive ? height : height * (minLengthPerCentage/100) } } property int maxLength: { if (root.isHorizontal) { return behaveAsPlasmaPanel ? width : width * (maxLengthPerCentage/100) } else { return behaveAsPlasmaPanel ? height : height * (maxLengthPerCentage/100) } } property int scrollAction: plasmoid.configuration.scrollAction property bool panelOutline: plasmoid.configuration.panelOutline property int panelEdgeSpacing: Math.max(background.lengthMargins, 1.5*appShadowSize) property int panelTransparency: plasmoid.configuration.panelTransparency //user set property bool panelShadowsActive: { if (!userShowPanelBackground) { return false; } if (inConfigureAppletsMode) { return plasmoid.configuration.panelShadows; } var forcedNoShadows = (plasmoid.configuration.panelShadows && disablePanelShadowMaximized && latteView && latteView.windowsTracker && latteView.windowsTracker.currentScreen.activeWindowMaximized); if (forcedNoShadows) { return false; } var transparencyCheck = (blurEnabled || (!blurEnabled && background.currentOpacity>20)); //! Draw shadows for isBusy state only when current panelTransparency is greater than 10% if (plasmoid.configuration.panelShadows && root.forcePanelForBusyBackground && transparencyCheck) { return true; } if (( (plasmoid.configuration.panelShadows && !root.backgroundOnlyOnMaximized) || (plasmoid.configuration.panelShadows && root.backgroundOnlyOnMaximized && !root.forceTransparentPanel)) && !forcedNoShadows) { return true; } if (hasExpandedApplet && plasmaBackgroundForPopups) { return true; } return false; } property int appShadowOpacity: (plasmoid.configuration.shadowOpacity/100) * 255 property int appShadowSize: enableShadows ? (0.5*metrics.iconSize) * (plasmoid.configuration.shadowSize/100) : 0 property int appShadowSizeOriginal: enableShadows ? (0.5*metrics.maxIconSize) * (plasmoid.configuration.shadowSize/100) : 0 property string appChosenShadowColor: { if (plasmoid.configuration.shadowColorType === LatteContainment.Types.ThemeColorShadow) { var strC = String(theme.textColor); return strC.indexOf("#") === 0 ? strC.substr(1) : strC; } else if (plasmoid.configuration.shadowColorType === LatteContainment.Types.UserColorShadow) { return plasmoid.configuration.shadowColor; } // default shadow color return "080808"; } property string appShadowColor: "#" + decimalToHex(appShadowOpacity) + appChosenShadowColor property string appShadowColorSolid: "#" + appChosenShadowColor property int offset: { if (behaveAsPlasmaPanel) { return 0; } if (root.isHorizontal) { return width * (plasmoid.configuration.offset/100); } else { height * (plasmoid.configuration.offset/100) } } property int editShadow: { if (!LatteCore.WindowSystem.compositingActive) { return 0; } else if (latteView && latteView.screenGeometry) { return latteView.screenGeometry.height/90; } else { return 7; } } property bool screenEdgeMarginEnabled: plasmoid.configuration.screenEdgeMargin >= 0 && !plasmoid.configuration.shrinkThickMargins property int widthMargins: root.isVertical ? metrics.totals.thicknessEdges : metrics.totals.lengthEdges property int heightMargins: root.isHorizontal ? metrics.totals.thicknessEdges : metrics.totals.lengthEdges property int panelAlignment: plasmoid.configuration.alignment readonly property string plasmoidName: "org.kde.latte.plasmoid" property var iconsArray: [16, 22, 32, 48, 64, 96, 128, 256] property Item dragOverlay property Item toolBox property Item latteAppletContainer property Item latteApplet readonly property alias animations: _animations readonly property alias background: _background readonly property alias autosize: _autosize readonly property alias indexer: _indexer readonly property alias indicatorsManager: indicators readonly property alias layouter: _layouter readonly property alias metrics: _metrics readonly property alias parabolic: _parabolic readonly property alias maskManager: visibilityManager readonly property alias layoutsContainerItem: layoutsContainer readonly property alias latteView: _interfaces.view readonly property alias layoutsManager: _interfaces.layoutsManager readonly property alias shortcutsEngine: _interfaces.globalShortcuts readonly property alias themeExtended: _interfaces.themeExtended readonly property alias universalSettings: _interfaces.universalSettings readonly property QtObject viewLayout: latteView && latteView.layout ? latteView.layout : null readonly property QtObject selectedWindowsTracker: { if (latteView && latteView.windowsTracker) { switch(plasmoid.configuration.activeWindowFilter) { case LatteContainment.Types.ActiveInCurrentScreen: return latteView.windowsTracker.currentScreen; case LatteContainment.Types.ActiveFromAllScreens: return latteView.windowsTracker.allScreens; } } return null; } // TO BE DELETED, if not needed: property int counter:0; ///BEGIN properties provided to Latte Plasmoid //shadows for applets, it should be removed as the appleitems don't need it any more property bool badges3DStyle: universalSettings ? universalSettings.badges3DStyle : true property bool enableShadows: plasmoid.configuration.appletShadowsEnabled property bool dockIsHidden: latteView && latteView.visibility ? latteView.visibility.isHidden : true property bool titleTooltips: plasmoid.configuration.titleTooltips property int tasksCount: latteApplet ? latteApplet.tasksCount : 0 property rect screenGeometry: latteView ? latteView.screenGeometry : plasmoid.screenGeometry readonly property color minimizedDotColor: colorizerManager.minimizedDotColor ///END properties from latteApplet Plasmoid.backgroundHints: PlasmaCore.Types.NoBackground //// BEGIN properties in functions property int noApplets: { var count1 = 0; var count2 = 0; count1 = layoutsContainer.mainLayout.children.length; var tempLength = layoutsContainer.mainLayout.children.length; for (var i=tempLength-1; i>=0; --i) { var applet = layoutsContainer.mainLayout.children[i]; if (applet && (applet === dndSpacer || applet === lastSpacer || applet.isInternalViewSplitter)) count1--; } count2 = layoutsContainer.endLayout.children.length; tempLength = layoutsContainer.endLayout.children.length; for (var i=tempLength-1; i>=0; --i) { var applet = layoutsContainer.endLayout.children[i]; if (applet && (applet === dndSpacer || applet === lastSpacer || applet.isInternalViewSplitter)) count2--; } return (count1 + count2); } ///The index of user's current icon size property int currentIconIndex:{ for(var i=iconsArray.length-1; i>=0; --i){ if(iconsArray[i] === metrics.iconSize){ return i; } } return 3; } //// END properties in functions ////////////////END properties //// BEGIN OF Behaviors Behavior on offset { enabled: editModeVisual.editAnimationInFullThickness NumberAnimation { id: offsetAnimation duration: 0.8 * animations.duration.proposed easing.type: Easing.OutCubic } } //// END OF Behaviors //////////////START OF CONNECTIONS onEditModeChanged: { if (!editMode) { layouter.updateSizeForAppletsInFill(); } //! This is used in case the dndspacer has been left behind //! e.g. the user drops a folder and a context menu is appearing //! but the user decides to not make a choice for the applet type if (dndSpacer.parent !== root) { dndSpacer.parent = root; } } onInConfigureAppletsModeChanged: { updateIndexes(); } //! It is used only when the user chooses different alignment types //! and not during startup onPanelAlignmentChanged: { if (!root.editMode) { return; } if (root.editMode/*!inConfigureAppletsMode*/){ if (panelAlignment===LatteCore.Types.Justify) { addInternalViewSplitters(); splitMainLayoutToLayouts(); } else { joinLayoutsToMainLayout(); root.destroyInternalViewSplitters(); } } LayoutManager.save(); updateIndexes(); } onLatteViewChanged: { if (latteView) { if (latteView.positioner) { latteView.positioner.hideDockDuringLocationChangeStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterLocationChangeFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringScreenChangeStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterScreenChangeFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringMovingToLayoutStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterMovingToLayoutFinished.connect(visibilityManager.slotShowDockAfterLocationChange); } if (latteView.visibility) { latteView.visibility.onContainsMouseChanged.connect(visibilityManager.slotContainsMouseChanged); latteView.visibility.onMustBeHide.connect(visibilityManager.slotMustBeHide); latteView.visibility.onMustBeShown.connect(visibilityManager.slotMustBeShown); } } } Connections { target: latteView onPositionerChanged: { if (latteView.positioner) { latteView.positioner.hideDockDuringLocationChangeStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterLocationChangeFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringScreenChangeStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterScreenChangeFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringMovingToLayoutStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterMovingToLayoutFinished.connect(visibilityManager.slotShowDockAfterLocationChange); } } onVisibilityChanged: { if (latteView.visibility) { latteView.visibility.onContainsMouseChanged.connect(visibilityManager.slotContainsMouseChanged); latteView.visibility.onMustBeHide.connect(visibilityManager.slotMustBeHide); latteView.visibility.onMustBeShown.connect(visibilityManager.slotMustBeShown); } } } onMaxLengthChanged: { layouter.updateSizeForAppletsInFill(); } onToolBoxChanged: { if (toolBox) { toolBox.visible = false; } } onIsReadyChanged: { if (isReady && !titleTooltipDialog.visible && titleTooltipDialog.activeItemHovered){ titleTooltipDialog.show(titleTooltipDialog.activeItem, titleTooltipDialog.activeItemText); } } onIsVerticalChanged: { if (isVertical) { if (plasmoid.configuration.alignment === LatteCore.Types.Left) plasmoid.configuration.alignment = LatteCore.Types.Top; else if (plasmoid.configuration.alignment === LatteCore.Types.Right) plasmoid.configuration.alignment = LatteCore.Types.Bottom; } else { if (plasmoid.configuration.alignment === LatteCore.Types.Top) plasmoid.configuration.alignment = LatteCore.Types.Left; else if (plasmoid.configuration.alignment === LatteCore.Types.Bottom) plasmoid.configuration.alignment = LatteCore.Types.Right; } } 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.metrics = metrics; upgrader_v010_alignment(); LayoutManager.restore(); plasmoid.action("configure").visible = !plasmoid.immutable; plasmoid.action("configure").enabled = !plasmoid.immutable; inStartupTimer.start(); } Component.onDestruction: { console.debug("Destroying Latte Dock Containment ui..."); layouter.appletsInParentChange = true; if (latteView) { if (latteView.positioner) { latteView.positioner.hideDockDuringLocationChangeStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterLocationChangeFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringScreenChangeStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterScreenChangeFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringMovingToLayoutStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterMovingToLayoutFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); } if (latteView.visibility) { latteView.visibility.onContainsMouseChanged.disconnect(visibilityManager.slotContainsMouseChanged); latteView.visibility.onMustBeHide.disconnect(visibilityManager.slotMustBeHide); latteView.visibility.onMustBeShown.disconnect(visibilityManager.slotMustBeShown); } } } Containment.onAppletAdded: { addApplet(applet, x, y); console.log(applet.pluginName); LayoutManager.save(); updateIndexes(); } Containment.onAppletRemoved: { LayoutManager.removeApplet(applet); var flexibleFound = false; for (var i = 0; i < layoutsContainer.mainLayout.children.length; ++i) { var applet = layoutsContainer.mainLayout.children[i].applet; if (applet && ((root.isHorizontal && applet.Layout.fillWidth) || (!root.isHorizontal && applet.Layout.fillHeight)) && applet.visible) { flexibleFound = true; break } } if (!flexibleFound) { lastSpacer.parent = layoutsContainer.mainLayout; } LayoutManager.save(); updateIndexes(); } Plasmoid.onUserConfiguringChanged: { if (plasmoid.immutable) { if (dragOverlay) { dragOverlay.destroy(); } return; } // console.debug("user configuring", plasmoid.userConfiguring) if (plasmoid.userConfiguring) { // console.log("applets------"); for (var i = 0; i < plasmoid.applets.length; ++i) { // console.log("applet:"+i); plasmoid.applets[i].expanded = false; } if (!dragOverlay) { var component = Qt.createComponent("editmode/ConfigOverlay.qml"); if (component.status == Component.Ready) { dragOverlay = component.createObject(root); } else { console.log("Could not create ConfigOverlay"); console.log(component.errorString()); } component.destroy(); } else { dragOverlay.visible = true; } } else { if (dragOverlay) { dragOverlay.visible = false; dragOverlay.destroy(); } } } Plasmoid.onImmutableChanged: { plasmoid.action("configure").visible = !plasmoid.immutable; plasmoid.action("configure").enabled = !plasmoid.immutable; ///Set Preferred Sizes/// ///Notice: they are set here because if they are set with a binding ///they break the !immutable experience, the latteView becomes too small ///to add applets /* if (plasmoid.immutable) { if(root.isHorizontal) { root.Layout.preferredWidth = (plasmoid.configuration.alignment === LatteCore.Types.Justify ? layoutsContainer.width + 0.5*iconMargin : layoutsContainer.mainLayout.width + iconMargin); } else { root.Layout.preferredHeight = (plasmoid.configuration.alignment === LatteCore.Types.Justify ? layoutsContainer.height + 0.5*iconMargin : layoutsContainer.mainLayout.height + iconMargin); } } else { if (root.isHorizontal) { root.Layout.preferredWidth = Screen.width; } else { root.Layout.preferredHeight = Screen.height; } }*/ visibilityManager.updateMaskArea(); } //////////////END OF CONNECTIONS //////////////START OF FUNCTIONS function addApplet(applet, x, y) { var container = appletContainerComponent.createObject(dndSpacer.parent) container.applet = applet; applet.parent = container.appletWrapper; applet.anchors.fill = container.appletWrapper; applet.visible = true; // don't show applet if it chooses to be hidden but still make it // accessible in the panelcontroller container.visible = Qt.binding(function() { return applet.status !== PlasmaCore.Types.HiddenStatus || (!plasmoid.immutable && root.inConfigureAppletsMode) }) addContainerInLayout(container, applet, x, y); } function addContainerInLayout(container, applet, x, y){ // Is there a DND placeholder? Replace it! if ( (dndSpacer.parent === layoutsContainer.mainLayout) || (dndSpacer.parent === layoutsContainer.startLayout) || (dndSpacer.parent===layoutsContainer.endLayout)) { LayoutManager.insertBeforeForLayout(dndSpacer.parent, dndSpacer, container); dndSpacer.parent = root; return; // If the provided position is valid, use it. } else if (x >= 0 && y >= 0) { var index = LayoutManager.insertAtCoordinates2(container, x , y); // Fall through to determining an appropriate insert position. } else { var before = null; container.animationsEnabled = false; if (lastSpacer.parent === layoutsContainer.mainLayout) { before = lastSpacer; } // Insert icons to the left of whatever is at the center (usually a Task Manager), // if it exists. // FIXME TODO: This is a real-world fix to produce a sensible initial position for // launcher icons added by launcher menu applets. The basic approach has been used // since Plasma 1. However, "add launcher to X" is a generic-enough concept and // frequent-enough occurrence that we'd like to abstract it further in the future // and get rid of the ugliness of parties external to the containment adding applets // of a specific type, and the containment caring about the applet type. In a better // system the containment would be informed of requested launchers, and determine by // itself what it wants to do with that information. if (applet.pluginName == "org.kde.plasma.icon") { var middle = layoutsContainer.mainLayout.childAt(root.width / 2, root.height / 2); if (middle) { before = middle; } // Otherwise if lastSpacer is here, enqueue before it. } if (before) { LayoutManager.insertBefore(before, container); // Fall through to adding at the end. } else { container.parent = layoutsContainer.mainLayout; } } //Important, removes the first children of the layoutsContainer.mainLayout after the first //applet has been added lastSpacer.parent = root; updateIndexes(); } function addInternalViewSplitters(){ if (internalViewSplittersCount() === 0) { addInternalViewSplitter(plasmoid.configuration.splitterPosition); addInternalViewSplitter(plasmoid.configuration.splitterPosition2); } } function addInternalViewSplitter(pos){ var splittersCount = internalViewSplittersCount(); if(splittersCount<2){ var container = appletContainerComponent.createObject(root); container.internalSplitterId = splittersCount+1; container.visible = true; if(pos>=0 ){ LayoutManager.insertAtIndex(layoutsContainer.mainLayout, container, pos); } else { LayoutManager.insertAtIndex(layoutsContainer.mainLayout, container, Math.floor(layouter.mainLayout.count / 2)); } } } //! it is used in order to check the right click position //! the only way to take into account the visual appearance //! of the applet (including its spacers) function appletContainsPos(appletId, pos){ for (var i = 0; i < layoutsContainer.startLayout.children.length; ++i) { var child = layoutsContainer.startLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } for (var i = 0; i < layoutsContainer.mainLayout.children.length; ++i) { var child = layoutsContainer.mainLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } for (var i = 0; i < layoutsContainer.endLayout.children.length; ++i) { var child = layoutsContainer.endLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } return false; } function checkLastSpacer() { lastSpacer.parent = root var expands = false; if (isHorizontal) { for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if (item.Layout && item.Layout.fillWidth) { expands = true; } } } else { for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if (item.Layout && item.Layout.fillHeight) { expands = true; } } } if (!expands) { lastSpacer.parent = layoutsContainer.mainLayout } } function containmentActions(){ return latteView.containmentActions(); } function decimalToHex(d, padding) { var hex = Number(d).toString(16); padding = typeof (padding) === "undefined" || padding === null ? padding = 2 : padding; while (hex.length < padding) { hex = "0" + hex; } return hex; } function internalViewSplittersCount(){ var splitters = 0; for (var container in layoutsContainer.startLayout.children) { var item = layoutsContainer.startLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } for (var container in layoutsContainer.endLayout.children) { var item = layoutsContainer.endLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } return splitters; } function layoutManager() { return LayoutManager; } function layoutManagerInsertBefore(place, item) { LayoutManager.insertBefore(place, item); } function layoutManagerInsertAfter(place, item) { LayoutManager.insertAfter(place, item); } function layoutManagerSave() { LayoutManager.save(); } function layoutManagerSaveOptions() { LayoutManager.saveOptions(); } function mouseInCanBeHoveredApplet(){ var applets = layoutsContainer.startLayout.children; for(var i=0; i=0; --i){ if(iconsArray[i] === size){ return true; } } return false; } function slotPreviewsShown(){ if (latteView) { latteView.extendedInterface.deactivateApplets(); } } function layoutManagerMoveAppletsBasedOnJustifyAlignment() { if (plasmoid.configuration.alignment !== 10) { return; } layouter.appletsInParentChange = true; var splitter = -1; var startChildrenLength = layoutsContainer.startLayout.children.length; //! Check if there is a splitter inside start layout after the user was dragging its applets for (var i=0; i=0) { for (var i=startChildrenLength-1; i>=splitter; --i){ var item = layoutsContainer.startLayout.children[i]; LayoutManager.insertAtIndex(layoutsContainer.mainLayout, item, 0); } } var splitter2 = -1; var endChildrenLength = layoutsContainer.endLayout.children.length; //! Check if there is a splitter inside endlayout after the user was dragging its applets for (var i=0; i=0) { for (var i=0; i<=splitter2; ++i){ var item = layoutsContainer.endLayout.children[0]; item.parent = layoutsContainer.mainLayout; } } //! Validate applets positioning and move applets out of splitters to start/endlayouts accordingly splitMainLayoutToLayouts(); layouter.appletsInParentChange = false; } function splitMainLayoutToLayouts() { if (internalViewSplittersCount() === 2) { layouter.appletsInParentChange = true; console.log("LAYOUTS: Moving applets from MAIN to THREE Layouts mode..."); var splitter = -1; var splitter2 = -1; var totalChildren = layoutsContainer.mainLayout.children.length; for (var i=0; i=0 && splitter2 === -1) { splitter2 = i; } } // console.log("update layouts 1:"+splitter + " - "+splitter2); if (splitter > 0) { for (var i=0; i 0) { splitter2 = splitter2 - splitter; // console.log("update layouts 2:"+splitter + " - "+splitter2); totalChildren = layoutsContainer.mainLayout.children.length; for (var i=totalChildren-1; i>=splitter2+1; --i){ var item = layoutsContainer.mainLayout.children[i]; LayoutManager.insertAtIndex(layoutsContainer.endLayout, item, 0); } } layouter.appletsInParentChange = false; } } function joinLayoutsToMainLayout() { layouter.appletsInParentChange = true; console.log("LAYOUTS: Moving applets from THREE to MAIN Layout mode..."); var totalChildren1 = layoutsContainer.mainLayout.children.length; for (var i=totalChildren1-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; } layouter.appletsInParentChange = false; } function upgrader_v010_alignment() { //! IMPORTANT, special case because it needs to be loaded on Component constructor if (!plasmoid.configuration.alignmentUpgraded) { plasmoid.configuration.alignment = plasmoid.configuration.panelPosition; plasmoid.configuration.alignmentUpgraded = true; } } //END functions ////BEGIN interfaces Connections { target: LatteCore.WindowSystem onCompositingActiveChanged: { visibilityManager.updateMaskArea(); } } ////END interfaces /////BEGIN: Title Tooltip/////////// PlasmaCore.Dialog{ id: titleTooltipDialog type: PlasmaCore.Dialog.Tooltip flags: Qt.WindowStaysOnTopHint | Qt.WindowDoesNotAcceptFocus | Qt.ToolTip location: plasmoid.location mainItem: RowLayout{ Layout.fillWidth: true Layout.fillHeight: true PlasmaComponents.Label{ id:titleLbl Layout.leftMargin: 4 Layout.rightMargin: 4 Layout.topMargin: 2 Layout.bottomMargin: 2 text: titleTooltipDialog.title } } visible: false property string title: "" property bool activeItemHovered: false property Item activeItem: null property Item activeItemTooltipParent: null property string activeItemText: "" Component.onCompleted: { parabolic.sglClearZoom.connect(titleTooltipDialog.hide); } Component.onDestruction: { parabolic.sglClearZoom.disconnect(titleTooltipDialog.hide); } function hide(debug){ if (!root.titleTooltips) return; activeItemHovered = false; hideTitleTooltipTimer.start(); } function show(taskItem, text){ if (!root.titleTooltips || (latteApplet && latteApplet.contextMenu)){ return; } activeItemHovered = true; if (activeItem !== taskItem) { activeItem = taskItem; activeItemTooltipParent = taskItem.tooltipVisualParent; activeItemText = text; } if (isReady) { showTitleTooltipTimer.start(); } } function update() { activeItemHovered = true title = activeItemText; visualParent = activeItemTooltipParent; if (latteApplet && latteApplet.windowPreviewIsShown) { latteApplet.hidePreview(); } visible = true; } } Timer { id: showTitleTooltipTimer interval: 100 onTriggered: { if (latteView && latteView.visibility && latteView.visibility.containsMouse) { titleTooltipDialog.update(); } if (titleTooltipDialog.visible) { titleTooltipCheckerToNotShowTimer.start(); } if (root.debugModeTimers) { console.log("containment timer: showTitleTooltipTimer called..."); } } } Timer { id: hideTitleTooltipTimer interval: 200 onTriggered: { if (!titleTooltipDialog.activeItemHovered) { titleTooltipDialog.visible = false; } if (root.debugModeTimers) { console.log("containment timer: hideTitleTooltipTimer called..."); } } } //! Timer to fix #811, rare cases that both a window preview and context menu are //! shown Timer { id: titleTooltipCheckerToNotShowTimer interval: 250 onTriggered: { if (titleTooltipDialog.visible && latteApplet && (latteApplet.contextMenu || latteApplet.windowPreviewIsShown)) { titleTooltipDialog.visible = false; } } } /////END: Title Tooltip/////////// ///////////////BEGIN components Component { id: appletContainerComponent Applet.AppletItem{ animations: _animations indexer: _indexer layouter: _layouter metrics: _metrics parabolic: _parabolic shortcuts: _shortcuts } } Indicators.Manager{ id: indicators } Item { id: graphicsSystem readonly property bool isAccelerated: (GraphicsInfo.api !== GraphicsInfo.Software) && (GraphicsInfo.api !== GraphicsInfo.Unknown) } Upgrader { id: upgrader } ///////////////END components PlasmaCore.ColorScope{ id: colorScopePalette } ///////////////BEGIN UI elements //it is used to check if the mouse is outside the layoutsContainer borders, //so in that case the onLeave event behavior should be trigerred RootMouseArea{ id: rootMouseArea } Loader{ active: root.debugModeWindow sourceComponent: Debug.DebugWindow{} } EditMode.Visual{ id:editModeVisual // z: root.behaveAsPlasmaPanel ? 1 : 0 } 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 } } Loader{ anchors.fill: parent active: root.debugMode z:10 sourceComponent: Item{ Rectangle{ anchors.fill: parent color: "yellow" opacity: 0.06 } } } VisibilityManager{ id: visibilityManager applets: layoutsContainer.applets } DragDropArea { id: backDropArea anchors.fill: parent readonly property bool higherPriority: latteView && latteView.containsDrag && ((root.dragInfo.isPlasmoid && root.dragInfo.isSeparator) || (foreDropArea.dragInfo.computationsAreValid && !root.dragInfo.isPlasmoid && !root.dragInfo.onlyLaunchers)) Item{ anchors.fill: layoutsContainer Background.MultiLayered{ id: _background } } Layouts.LayoutsContainer { id: layoutsContainer } DragDropArea { id: foreDropArea anchors.fill: parent visible: !backDropArea.higherPriority isForeground: true /* Rectangle { anchors.fill: parent color: "blue" opacity: 0.5 }*/ } } Colorizer.Manager { id: colorizerManager } Item { id: dndSpacer width: root.isHorizontal ? length : thickness height: root.isHorizontal ? thickness : length readonly property bool isDndSpacer: true readonly property int length: metrics.totals.length readonly property int thickness: metrics.totals.thickness + metrics.margin.screenEdge Layout.preferredWidth: width Layout.preferredHeight: height opacity: 0 z:1500 LatteComponents.AddItem{ id: dndSpacerAddItem width: root.isHorizontal ? parent.width : parent.width - metrics.margin.screenEdge height: root.isHorizontal ? parent.height - metrics.margin.screenEdge: parent.height states:[ State{ name: "bottom" when: plasmoid.location === PlasmaCore.Types.BottomEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.bottom; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: metrics.margin.screenEdge; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "top" when: plasmoid.location === PlasmaCore.Types.TopEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: parent.top; anchors.bottom: undefined; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin: metrics.margin.screenEdge; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "left" when: plasmoid.location === PlasmaCore.Types.LeftEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: undefined; anchors.left: parent.left; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: metrics.margin.screenEdge; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "right" when: plasmoid.location === PlasmaCore.Types.RightEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: parent.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: 0; anchors.rightMargin: metrics.margin.screenEdge; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } } ] } } ///////////////END UI elements ///////////////BEGIN ABILITIES Ability.Animations { id: _animations metrics: _metrics settings: universalSettings } Ability.AutoSize { id: _autosize layouts: layoutsContainer layouter: _layouter metrics: _metrics visibility: visibilityManager } Ability.Indexer { id: _indexer layouts: layoutsContainer } Ability.Layouter { id: _layouter animations: _animations indexer: _indexer layouts: layoutsContainer } Ability.Metrics { id: _metrics animations: _animations autosize: _autosize background: _background indicators: indicatorsManager } Ability.ParabolicEffect { id: _parabolic animations: _animations applets: layoutsContainer.applets view: latteView } Ability.PositionShortcuts { id: _shortcuts layouts: layoutsContainer } LatteApp.Interfaces { id: _interfaces plasmoidInterface: plasmoid Component.onCompleted: { view.interfacesGraphicObj = _interfaces; } onViewChanged: { if (view) { view.interfacesGraphicObj = _interfaces; } } } ///////////////END ABILITIES ///////////////BEGIN TIMER elements //! It is used in order to slide-in the latteView on startup Timer{ id: inStartupTimer interval: 1500 repeat: false onTriggered: { if (inStartup) { visibilityManager.slotMustBeShown(); } } } ///////////////END TIMER elements Loader{ anchors.fill: parent active: root.debugModeLocalGeometry sourceComponent: Rectangle{ x: latteView.localGeometry.x y: latteView.localGeometry.y width: latteView.localGeometry.width height: latteView.localGeometry.height color: "blue" border.width: 2 border.color: "red" opacity: 0.35 } } } diff --git a/shell/package/contents/configuration/LatteDockConfiguration.qml b/shell/package/contents/configuration/LatteDockConfiguration.qml index f79918e6..9c0767b3 100644 --- a/shell/package/contents/configuration/LatteDockConfiguration.qml +++ b/shell/package/contents/configuration/LatteDockConfiguration.qml @@ -1,688 +1,689 @@ /* * 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.components 3.0 as PlasmaComponents3 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.core 0.2 as LatteCore import org.kde.latte.components 1.0 as LatteComponents import "pages" as Pages import "../controls" as LatteExtraControls FocusScope { id: dialog readonly property bool basicLevel: !advancedLevel readonly property bool advancedLevel: viewConfig.inAdvancedMode readonly property bool inConfigureAppletsMode: plasmoid.configuration.inConfigureAppletsMode || !LatteCore.WindowSystem.compositingActive //! max size based on screen resolution //! TODO: if we can access availableScreenGeometry.height this can be improved, currently //! we use 100px. or 50px. in order to give space for othe views to be shown and to have also //! some space around the settings window property int maxHeight: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? viewConfig.availableScreenGeometry.height - (latteView.editThickness - latteView.normalThickness) - 16 : viewConfig.availableScreenGeometry.height - 2 * units.largeSpacing property int maxWidth: 0.6 * latteView.screenGeometry.width //! propose size based on font size property int proposedWidth: 0.82 * proposedHeight + units.smallSpacing * 2 property int proposedHeight: 36 * theme.mSize(theme.defaultFont).height //! chosen size to be applied, if the user has set or not a different scale for the settings window property int chosenWidth: userScaleWidth !== 1 ? userScaleWidth * proposedWidth : proposedWidth property int chosenHeight: userScaleHeight !== 1 ? userScaleHeight * heightLevel * proposedHeight : heightLevel * proposedHeight readonly property int optionsWidth: appliedWidth - units.smallSpacing * 10 //! user set scales based on its preference, e.g. 96% of the proposed size property real userScaleWidth: 1 property real userScaleHeight: 1 readonly property real heightLevel: (dialog.advancedLevel ? 100 : 1) onHeightChanged: viewConfig.syncGeometry(); //! applied size in order to not be out of boundaries //! width can be between 200px - maxWidth //! height can be between 400px - maxHeight property int appliedWidth: Math.min(maxWidth, Math.max(200, chosenWidth)) property int appliedHeight: Math.min(maxHeight, Math.max(400, chosenHeight)) width: appliedWidth height: appliedHeight Layout.minimumWidth: width Layout.minimumHeight: height LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft LayoutMirroring.childrenInherit: true readonly property bool viewIsPanel: latteView.type === LatteCore.Types.PanelView property bool panelIsVertical: plasmoid.formFactor === PlasmaCore.Types.Vertical property int subGroupSpacing: units.largeSpacing + units.smallSpacing * 1.5 property color bC: theme.backgroundColor property color transparentBackgroundColor: Qt.rgba(bC.r, bC.g, bC.b, 0.7) onAdvancedLevelChanged: { //! switch to appearancePage when effectsPage becomes hidden because //! advancedLevel was disabled by the user if (!advancedLevel && tabGroup.currentTab === effectsPage) { tabGroup.currentTab = appearancePage; tabBar.currentTab = appearanceTabBtn; } } Component.onCompleted: { updateScales(); } Connections { target: latteView.positioner onCurrentScreenNameChanged: dialog.updateScales(); } function updateScales() { userScaleWidth = universalSettings.screenWidthScale(latteView.positioner.currentScreenName); userScaleHeight = universalSettings.screenHeightScale(latteView.positioner.currentScreenName); } PlasmaCore.FrameSvgItem{ id: backgroundFrameSvgItem anchors.fill: parent imagePath: "dialogs/background" enabledBorders: viewConfig.enabledBorders onEnabledBordersChanged: viewConfig.updateEffects() Component.onCompleted: viewConfig.updateEffects() } MouseArea{ id: backgroundMouseArea anchors.fill: parent hoverEnabled: true property bool blockWheel: false property bool updatingWidthScale: false property bool updatingHeightScale: false property bool wheelTriggeredOnce: false property real scaleStep: 0.04 onWheel: { var metaModifier = (wheel.modifiers & Qt.MetaModifier); var ctrlModifier = (wheel.modifiers & Qt.ControlModifier); if (blockWheel || !(metaModifier || ctrlModifier)){ return; } updatingWidthScale = metaModifier || (dialog.advancedLevel && ctrlModifier); updatingHeightScale = dialog.basicLevel && ctrlModifier; blockWheel = true; wheelTriggeredOnce = true; scrollDelayer.start(); var angle = wheel.angleDelta.y / 8; //positive direction if (angle > 12) { var scales; if (updatingWidthScale) { userScaleWidth = userScaleWidth + scaleStep; } if (updatingHeightScale) { userScaleHeight = userScaleHeight + scaleStep; } universalSettings.setScreenScales(latteView.positioner.currentScreenName, userScaleWidth, userScaleHeight); viewConfig.syncGeometry(); //negative direction } else if (angle < -12) { if (updatingWidthScale) { userScaleWidth = userScaleWidth - scaleStep; } if (updatingHeightScale) { userScaleHeight = userScaleHeight - scaleStep; } universalSettings.setScreenScales(latteView.positioner.currentScreenName, userScaleWidth, userScaleHeight); viewConfig.syncGeometry(); } } } PlasmaComponents.Button { id: backgroundMouseAreaTooltip anchors.fill: parent opacity: 0 //tooltip: i18n("You can use Ctrl/Meta + Scroll Wheel to alter the window size") onHoveredChanged: { if (!hovered) { backgroundMouseArea.wheelTriggeredOnce = false; } } } PlasmaComponents.Label{ anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter text: backgroundMouseArea.updatingWidthScale ? i18nc("view settings width scale","Width scale at %0%").arg(userScaleWidth * 100) : i18nc("view settings height scale","Height scale at %0%").arg(userScaleHeight * 100) visible: backgroundMouseAreaTooltip.hovered && backgroundMouseArea.wheelTriggeredOnce } //! 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: 75 onTriggered: backgroundMouseArea.blockWheel = false; } ColumnLayout { id: content Layout.minimumWidth: width Layout.minimumHeight: calculatedHeight Layout.preferredWidth: width Layout.preferredHeight: calculatedHeight width: (dialog.appliedWidth - units.smallSpacing * 2) anchors.horizontalCenter: parent.horizontalCenter anchors.top: parent.top spacing: units.smallSpacing property int calculatedHeight: header.height + headerSpacer.height+ tabBar.height + pagesBackground.height + actionButtons.height + spacing * 3 Keys.onPressed: { if (event.key === Qt.Key_Escape) { viewConfig.hideConfigWindow(); } } Component.onCompleted: forceActiveFocus(); RowLayout { id: header Layout.fillWidth: true spacing: 0 Item { Layout.alignment: Qt.AlignLeft | Qt.AlignTop Layout.fillWidth: false Layout.topMargin: units.smallSpacing Layout.preferredWidth: width Layout.preferredHeight: height width: Qt.application.layoutDirection !== Qt.RightToLeft ? logo.width + latteTxt.width + units.smallSpacing : logo.width + units.smallSpacing height: logo.height LatteCore.IconItem { id: logo width: Math.round(1.4 * latteTxtMetrics.font.pixelSize) height: width smooth: true source: "latte-dock" usesPlasmaTheme: false } PlasmaComponents.Label { id: latteTxtMetrics text: i18n("Latte") width: 0 font.pointSize: 2 * theme.defaultFont.pointSize visible: false } PlasmaCore.SvgItem{ id: latteTxt width: 2.2 * height height: 0.4 * latteTxtMetrics.font.pixelSize visible: Qt.application.layoutDirection !== Qt.RightToLeft anchors.left: logo.right anchors.verticalCenter: logo.verticalCenter svg: PlasmaCore.Svg{ imagePath: universalSettings.trademarkIconPath() } } } Item{ id: headerSpacer Layout.minimumHeight: advancedSettings.height + 2*units.smallSpacing } ColumnLayout { PlasmaComponents3.ToolButton { id: pinButton Layout.fillWidth: false Layout.fillHeight: false Layout.preferredWidth: width Layout.preferredHeight: height Layout.alignment: Qt.AlignRight | Qt.AlignVCenter Layout.bottomMargin: units.smallSpacing * 1.5 //!avoid editMode box shadow Layout.topMargin: units.smallSpacing * 2 Layout.rightMargin: units.smallSpacing icon.name: "window-pin" checkable: true width: 7 * units.smallSpacing height: width property bool inStartup: true onClicked: { plasmoid.configuration.configurationSticker = checked viewConfig.setSticker(checked) } Component.onCompleted: { checked = plasmoid.configuration.configurationSticker viewConfig.setSticker(plasmoid.configuration.configurationSticker) } } RowLayout { id: advancedSettings Layout.fillWidth: true Layout.rightMargin: units.smallSpacing * 2 Layout.alignment: Qt.AlignRight | Qt.AlignTop PlasmaComponents.Label { Layout.fillWidth: true Layout.alignment: Qt.AlignRight } PlasmaComponents.Label { id: advancedLbl Layout.alignment: Qt.AlignRight // opacity: dialog.basicLevel ? basicOpacity : 1 //! TODO: the term here is not accurate because the expert settings mode //! is used currently. In the future this term will be rethought if //! it must remain or be changed text: i18nc("advanced settings", "Advanced") readonly property real textColorBrightness: colorBrightness(theme.textColor) readonly property real basicOpacity: textColorBrightness > 127 ? 0.7 : 0.3 color: { if (dialog.basicLevel) { return textColorBrightness > 127 ? Qt.darker(theme.textColor, 1.4) : Qt.lighter(theme.textColor, 2.8); } return theme.textColor; } function colorBrightness(color) { return colorBrightnessFromRGB(color.r * 255, color.g * 255, color.b * 255); } // formula for brightness according to: // https://www.w3.org/TR/AERT/#color-contrast function colorBrightnessFromRGB(r, g, b) { return (r * 299 + g * 587 + b * 114) / 1000 } MouseArea { id: advancedMouseArea anchors.fill: parent hoverEnabled: true onClicked: { advancedSwitch.checked = !advancedSwitch.checked; } } } LatteComponents.Switch { id: advancedSwitch checked: viewConfig.inAdvancedMode onCheckedChanged: viewConfig.inAdvancedMode = checked; } } } } PlasmaComponents.TabBar { id: tabBar Layout.fillWidth: true Layout.maximumWidth: (dialog.appliedWidth - units.smallSpacing * 2) PlasmaComponents.TabButton { id: behaviorTabBtn text: i18n("Behavior") tab: behaviorPage } PlasmaComponents.TabButton { id: appearanceTabBtn text: i18n("Appearance") tab: appearancePage } PlasmaComponents.TabButton { id: effectsTabBtn text: i18n("Effects") tab: effectsPage visible: dialog.advancedLevel } Repeater { id: tasksTabButtonRepeater model: latteView.extendedInterface.latteTasksModel PlasmaComponents.TabButton { text: index >= 1 ? i18nc("tasks header and index","Tasks <%0>").arg(index+1) : i18n("Tasks") tab: tasksRepeater.itemAt(index) } } } Rectangle { id: pagesBackground Layout.fillWidth: true Layout.fillHeight: false Layout.minimumWidth: dialog.appliedWidth - units.smallSpacing * 4 Layout.minimumHeight: height Layout.maximumHeight: height width: dialog.appliedWidth - units.smallSpacing * 3 height: availableFreeHeight + units.smallSpacing * 4 color: transparentBackgroundColor border.width: 1 border.color: theme.backgroundColor //fix the height binding loop when showing the configuration window property int availableFreeHeight: dialog.appliedHeight - header.height - headerSpacer.height - tabBar.height - actionButtons.height - 2 * units.smallSpacing 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 Pages.BehaviorConfig { id: behaviorPage } Pages.AppearanceConfig { id: appearancePage } Pages.EffectsConfig { id: effectsPage } } } Repeater { id: tasksRepeater //! needs to be out of TabGroup otherwise the Repeater is consider as TabGroup direct children //! and thus only the first Tasks tab is shown model: latteView.extendedInterface.latteTasksModel //! Reparent TasksPages when all of them are loaded //! this way we avoid warnings from ::stackAfter //! After startup any new TasksPages can be added directly property bool isReady: false property int pages: 0 Pages.TasksConfig { id: tasksPage Component.onCompleted: { if (tasksRepeater.isReady) { parent = tabGroup; } else { tasksRepeater.pages = tasksRepeater.pages + 1; } } } onPagesChanged: { if (pages === latteView.extendedInterface.latteTasksModel.count) { //! Reparent TasksPages when all of them are loaded //! this way we avoid warnings from ::stackAfter for(var i=0; i 1 ? dialog.width / 2 : 150 property var centralLayoutsNames: [] property var sharedLayoutsNames: [] Component.onCompleted: { comboBox.model = actionsModel; } ListModel { id: actionsModel } Connections{ target: actionsComboBtn.comboBox Component.onCompleted:{ actionsComboBtn.addModel(); } onActivated: { if (index==0) { latteView.copyView(); } else if (index>=1) { var layouts = actionsComboBtn.sharedLayoutsNames.concat(actionsComboBtn.centralLayoutsNames); latteView.positioner.hideDockDuringMovingToLayout(layouts[index-1]); } actionsComboBtn.comboBox.currentIndex = -1; } onEnabledChanged: { if (enabled) { actionsComboBtn.addModel(); } else { actionsComboBtn.emptyModel(); } } } Connections{ target: actionsComboBtn.button onClicked: latteView.layout.addNewView(); } Connections{ target: latteView onTypeChanged: actionsComboBtn.updateCopyText() } function addModel() { actionsModel.clear(); var copy = {actionId: 'copy:', enabled: true, name: '', icon: 'edit-copy'}; actionsModel.append(copy); updateCopyText(); var tempCentralLayouts = layoutsManager.centralLayoutsNames(); var tempSharedLayouts = layoutsManager.sharedLayoutsNames(); if (tempSharedLayouts.length > 0) { var curIndex = tempSharedLayouts.indexOf(latteView.layout.name); if (curIndex >=0) { tempSharedLayouts.splice(curIndex,1); } sharedLayoutsNames = tempSharedLayouts; var icon = "document-share"; for(var i=0; i 0) { var curIndex = tempCentralLayouts.indexOf(latteView.layout.name); if (curIndex >=0) { tempCentralLayouts.splice(curIndex,1); } centralLayoutsNames = tempCentralLayouts; var iconArrow = Qt.application.layoutDirection === Qt.RightToLeft ? 'arrow-left' : 'arrow-right'; for(var i=0; i 1 + enabled: latteView.layout.viewsCount > 1 + opacity: enabled ? 1 : 0 tooltip: i18n("Remove current dock") onClicked: latteView.removeView() } PlasmaComponents.Button { id: closeButton Layout.fillWidth: true text: i18n("Close") iconSource: "dialog-close" tooltip: i18n("Close settings window") onClicked: viewConfig.hideConfigWindow(); } } } //! HACK FOR X11 environments //! show an inner shadow similar to Latte::View editShadow in order to //! not break the visual user experience LatteExtraControls.InnerShadow{ width: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? dialog.width + 2*shadowSize : shadowSize height: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? shadowSize : dialog.height + 2*shadowSize shadowSize: latteView.effects.editShadow shadowOpacity: Math.max(0.35, maxOpacity) shadowDirection: plasmoid.location visible: !LatteCore.WindowSystem.isPlatformWayland && LatteCore.WindowSystem.compositingActive readonly property real maxOpacity: LatteCore.WindowSystem.compositingActive && !plasmoid.configuration.inConfigureAppletsMode ? plasmoid.configuration.editBackgroundOpacity : 1 } } diff --git a/shell/package/contents/configuration/pages/TasksConfig.qml b/shell/package/contents/configuration/pages/TasksConfig.qml index fc8d9ac4..ce77ee01 100644 --- a/shell/package/contents/configuration/pages/TasksConfig.qml +++ b/shell/package/contents/configuration/pages/TasksConfig.qml @@ -1,724 +1,725 @@ /* * 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 org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.components 3.0 as PlasmaComponents3 import org.kde.plasma.plasmoid 2.0 import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.components 1.0 as LatteComponents import org.kde.latte.private.tasks 0.1 as LatteTasks PlasmaComponents.Page { Layout.maximumWidth: content.width + content.Layout.leftMargin * 2 Layout.maximumHeight: content.height + units.smallSpacing * 2 property bool disableAllWindowsFunctionality: tasks.configuration.showWindowsOnlyFromLaunchers && !latteView.indicator.enabled ColumnLayout { id: content width: (dialog.appliedWidth - units.smallSpacing * 2) - Layout.leftMargin * 2 spacing: dialog.subGroupSpacing anchors.horizontalCenter: parent.horizontalCenter Layout.leftMargin: units.smallSpacing * 2 Layout.rightMargin: units.smallSpacing * 2 //! BEGIN: Badges ColumnLayout { spacing: units.smallSpacing Layout.topMargin: units.smallSpacing visible: dialog.advancedLevel LatteComponents.Header { text: i18n("Badges") } LatteComponents.CheckBoxesColumn { Layout.leftMargin: units.smallSpacing * 2 Layout.rightMargin: units.smallSpacing * 2 LatteComponents.CheckBox { Layout.maximumWidth: dialog.optionsWidth text: i18n("Notifications from tasks") checked: tasks.configuration.showInfoBadge tooltip: i18n("Show unread messages or notifications from tasks") onClicked: { tasks.configuration.showInfoBadge = checked } } LatteComponents.CheckBox { Layout.maximumWidth: dialog.optionsWidth text: i18n("Progress information for tasks") checked: tasks.configuration.showProgressBadge tooltip: i18n("Show a progress animation for tasks e.g. when copying files with Dolphin") onClicked: { tasks.configuration.showProgressBadge = checked } } LatteComponents.CheckBox { Layout.maximumWidth: dialog.optionsWidth text: i18n("Audio playing from tasks") checked: tasks.configuration.showAudioBadge tooltip: i18n("Show audio playing from tasks") onClicked: { tasks.configuration.showAudioBadge = checked } } LatteComponents.CheckBox { Layout.maximumWidth: dialog.optionsWidth text: i18n("Prominent color for notification badge") checked: tasks.configuration.infoBadgeProminentColorEnabled enabled: tasks.configuration.showInfoBadge tooltip: i18n("Notification badge uses a more prominent background which is usually red") onClicked: { tasks.configuration.infoBadgeProminentColorEnabled = !tasks.configuration.infoBadgeProminentColorEnabled; } } LatteComponents.CheckBox { Layout.maximumWidth: dialog.optionsWidth text: i18n("Change volume when scrolling audio badge") checked: tasks.configuration.audioBadgeActionsEnabled enabled: tasks.configuration.showAudioBadge tooltip: i18n("The user is able to mute/unmute with click or change the volume with mouse wheel") onClicked: { tasks.configuration.audioBadgeActionsEnabled = checked } } } } //! END: Badges //! BEGIN: Tasks Interaction ColumnLayout { Layout.topMargin: dialog.basicLevel ? units.smallSpacing : 0 spacing: units.smallSpacing LatteComponents.Header { text: i18n("Interaction") } LatteComponents.CheckBoxesColumn { Layout.leftMargin: units.smallSpacing * 2 Layout.rightMargin: units.smallSpacing * 2 LatteComponents.CheckBox { Layout.maximumWidth: dialog.optionsWidth text: i18n("Add launchers only in the Tasks Area") checked: plasmoid.configuration.addLaunchersInTaskManager tooltip: i18n("Launchers are added only in the taskmanager and not as plasma applets") enabled: latteView.extendedInterface.latteTasksModel.count === 1 + && latteView.extendedInterface.plasmaTasksModel.count === 0 onClicked: { plasmoid.configuration.addLaunchersInTaskManager = checked; } } LatteComponents.CheckBox { id: windowActionsChk Layout.maximumWidth: dialog.optionsWidth text: i18n("Window actions in the context menu") checked: tasks.configuration.showWindowActions visible: dialog.advancedLevel enabled: !disableAllWindowsFunctionality onClicked: { tasks.configuration.showWindowActions = checked } } LatteComponents.CheckBox { id: unifyGlobalShortcutsChk Layout.maximumWidth: dialog.optionsWidth text: i18n("➊ Based on position shortcuts apply only on tasks") // checked: tasks.configuration.isPreferredForPositionShortcuts //! Disabled because it was not updated between multiple Tasks tooltip: i18n("Based on position global shortcuts are enabled only for tasks and not for applets") visible: dialog.advancedLevel enabled: latteView.isPreferredForShortcuts || (!latteView.layout.preferredForShortcutsTouched && latteView.isHighestPriorityView()) readonly property bool isPreferredForShotcuts: tasks.configuration.isPreferredForPositionShortcuts onIsPreferredForShotcutsChanged: checked = isPreferredForShotcuts; onClicked: { tasks.configuration.isPreferredForPositionShortcuts = !tasks.configuration.isPreferredForPositionShortcuts; } } } } //! END: Tasks Interaction //! BEGIN: Tasks Filters ColumnLayout { spacing: units.smallSpacing LatteComponents.Header { text: i18n("Filters") } LatteComponents.CheckBoxesColumn { Layout.leftMargin: units.smallSpacing * 2 Layout.rightMargin: units.smallSpacing * 2 LatteComponents.CheckBox { Layout.maximumWidth: dialog.optionsWidth text: i18n("Show only tasks from the current screen") checked: tasks.configuration.showOnlyCurrentScreen onClicked: { tasks.configuration.showOnlyCurrentScreen = checked } } LatteComponents.CheckBox { Layout.maximumWidth: dialog.optionsWidth text: i18n("Show only tasks from the current desktop") checked: tasks.configuration.showOnlyCurrentDesktop onClicked: { tasks.configuration.showOnlyCurrentDesktop = checked } } LatteComponents.CheckBox { Layout.maximumWidth: dialog.optionsWidth text: i18n("Show only tasks from the current activity") checked: tasks.configuration.showOnlyCurrentActivity onClicked: { tasks.configuration.showOnlyCurrentActivity = checked } } LatteComponents.CheckBox { Layout.maximumWidth: dialog.optionsWidth text: i18n("Show only tasks from launchers") checked: tasks.configuration.showWindowsOnlyFromLaunchers visible: dialog.advancedLevel onClicked: { tasks.configuration.showWindowsOnlyFromLaunchers = checked } } LatteComponents.CheckBox { Layout.maximumWidth: dialog.optionsWidth text: i18n("Group tasks of the same application") checked: tasks.configuration.groupTasksByDefault tooltip: i18n("By default group tasks of the same application") visible: dialog.advancedLevel onClicked: { tasks.configuration.groupTasksByDefault = checked } } } } //! END: Tasks Filters //! BEGIN: Animations ColumnLayout { spacing: units.smallSpacing enabled: plasmoid.configuration.animationsEnabled visible: dialog.advancedLevel LatteComponents.Header { text: i18n("Animations") } LatteComponents.CheckBoxesColumn { Layout.leftMargin: units.smallSpacing * 2 Layout.rightMargin: units.smallSpacing * 2 LatteComponents.CheckBox { Layout.maximumWidth: dialog.optionsWidth text: i18n("Bounce launchers when triggered") checked: tasks.configuration.animationLauncherBouncing onClicked: { tasks.configuration.animationLauncherBouncing = !tasks.configuration.animationLauncherBouncing; } } LatteComponents.CheckBox { Layout.maximumWidth: dialog.optionsWidth text: i18n("Bounce tasks that need attention") checked: tasks.configuration.animationWindowInAttention onClicked: { tasks.configuration.animationWindowInAttention = !tasks.configuration.animationWindowInAttention; } } LatteComponents.CheckBox { Layout.maximumWidth: dialog.optionsWidth text: i18n("Slide in and out single windows") checked: tasks.configuration.animationNewWindowSliding onClicked: { tasks.configuration.animationNewWindowSliding = !tasks.configuration.animationNewWindowSliding; } } LatteComponents.CheckBox { Layout.maximumWidth: dialog.optionsWidth text: i18n("Grouped tasks bounce their new windows") checked: tasks.configuration.animationWindowAddedInGroup onClicked: { tasks.configuration.animationWindowAddedInGroup = !tasks.configuration.animationWindowAddedInGroup; } } LatteComponents.CheckBox { Layout.maximumWidth: dialog.optionsWidth text: i18n("Grouped tasks slide out their closed windows") checked: tasks.configuration.animationWindowRemovedFromGroup onClicked: { tasks.configuration.animationWindowRemovedFromGroup = !tasks.configuration.animationWindowRemovedFromGroup; } } } } //! END: Animations //! BEGIN: Launchers Group ColumnLayout { spacing: units.smallSpacing LatteComponents.Header { text: i18n("Launchers") } ColumnLayout { Layout.leftMargin: units.smallSpacing * 2 Layout.rightMargin: units.smallSpacing * 2 spacing: 0 LatteComponents.SubHeader { isFirstSubCategory: true text: i18nc("launchers group", "Group"); } RowLayout { Layout.fillWidth: true spacing: 2 property int group: tasks.configuration.launchersGroup readonly property int buttonsCount: layoutGroupButton.visible ? 3 : 2 readonly property int buttonSize: (dialog.optionsWidth - (spacing * buttonsCount-1)) / buttonsCount ExclusiveGroup { id: launchersGroup onCurrentChanged: { if (current.checked) { viewConfig.updateLaunchersForGroup(current.group); tasks.configuration.launchersGroup = current.group; } } } PlasmaComponents.Button { Layout.minimumWidth: parent.buttonSize Layout.maximumWidth: Layout.minimumWidth text: i18nc("unique launchers group","Unique") checked: parent.group === group checkable: true exclusiveGroup: launchersGroup tooltip: i18n("Use a unique set of launchers for this view which is independent from any other view") readonly property int group: LatteCore.Types.UniqueLaunchers } PlasmaComponents.Button { id: layoutGroupButton Layout.minimumWidth: parent.buttonSize Layout.maximumWidth: Layout.minimumWidth text: i18nc("layout launchers group","Layout") checked: parent.group === group checkable: true exclusiveGroup: launchersGroup tooltip: i18n("Use the current layout set of launchers for this latteView. This group provides launchers synchronization between different views in the same layout") //! it is shown only when the user has activated that option manually from the text layout file visible: tasks.configuration.launchersGroup === group readonly property int group: LatteCore.Types.LayoutLaunchers } PlasmaComponents.Button { Layout.minimumWidth: parent.buttonSize Layout.maximumWidth: Layout.minimumWidth text: i18nc("global launchers group","Global") checked: parent.group === group checkable: true exclusiveGroup: launchersGroup tooltip: i18n("Use the global set of launchers for this latteView. This group provides launchers synchronization between different views and between different layouts") readonly property int group: LatteCore.Types.GlobalLaunchers } } } } //! END: Launchers Group //! BEGIN: Scrolling ColumnLayout { spacing: units.smallSpacing visible: dialog.advancedLevel LatteComponents.HeaderSwitch { id: scrollingHeader Layout.minimumWidth: dialog.optionsWidth + 2 *units.smallSpacing Layout.maximumWidth: Layout.minimumWidth Layout.minimumHeight: implicitHeight Layout.bottomMargin: units.smallSpacing enabled: LatteCore.WindowSystem.compositingActive checked: tasks.configuration.scrollTasksEnabled text: i18n("Scrolling") tooltip: i18n("Enable tasks scrolling when they overflow and exceed the available space"); onPressed: { tasks.configuration.scrollTasksEnabled = !tasks.configuration.scrollTasksEnabled;; } } ColumnLayout { Layout.leftMargin: units.smallSpacing * 2 Layout.rightMargin: units.smallSpacing * 2 spacing: 0 enabled: scrollingHeader.checked GridLayout { columns: 2 Layout.minimumWidth: dialog.optionsWidth Layout.maximumWidth: Layout.minimumWidth Layout.topMargin: units.smallSpacing PlasmaComponents.Label { Layout.fillWidth: true text: i18n("Manual") } LatteComponents.ComboBox { id: manualScrolling Layout.minimumWidth: leftClickAction.width Layout.maximumWidth: leftClickAction.width model: [i18nc("disabled manual scrolling", "Disabled scrolling"), dialog.panelIsVertical ? i18n("Only vertical scrolling") : i18n("Only horizontal scrolling"), i18n("Horizontal and vertical scrolling")] currentIndex: tasks.configuration.manualScrollTasksType onCurrentIndexChanged: tasks.configuration.manualScrollTasksType = currentIndex; } PlasmaComponents.Label { id: autoScrollText Layout.fillWidth: true text: i18n("Automatic") } LatteComponents.ComboBox { id: autoScrolling Layout.minimumWidth: leftClickAction.width Layout.maximumWidth: leftClickAction.width model: [ i18n("Disabled"), i18n("Enabled") ] currentIndex: tasks.configuration.autoScrollTasksEnabled onCurrentIndexChanged: { if (currentIndex === 0) { tasks.configuration.autoScrollTasksEnabled = false; } else { tasks.configuration.autoScrollTasksEnabled = true; } } } } } } //! END: Scolling //! BEGIN: Actions ColumnLayout { spacing: units.smallSpacing visible: dialog.advancedLevel LatteComponents.Header { text: i18n("Actions") } ColumnLayout { Layout.leftMargin: units.smallSpacing * 2 Layout.rightMargin: units.smallSpacing * 2 spacing: 0 GridLayout { columns: 2 Layout.minimumWidth: dialog.optionsWidth Layout.maximumWidth: Layout.minimumWidth Layout.topMargin: units.smallSpacing enabled: !disableAllWindowsFunctionality PlasmaComponents.Label { id: leftClickLbl text: i18n("Left Click") } LatteComponents.ComboBox { id: leftClickAction Layout.fillWidth: true model: [i18nc("present windows action", "Present Windows"), i18n("Cycle Through Tasks"), i18n("Preview Windows")] currentIndex: { switch(tasks.configuration.leftClickAction) { case LatteTasks.Types.PresentWindows: return 0; case LatteTasks.Types.CycleThroughTasks: return 1; case LatteTasks.Types.PreviewWindows: return 2; } return 0; } onCurrentIndexChanged: { switch(currentIndex) { case 0: tasks.configuration.leftClickAction = LatteTasks.Types.PresentWindows; break; case 1: tasks.configuration.leftClickAction = LatteTasks.Types.CycleThroughTasks; break; case 2: tasks.configuration.leftClickAction = LatteTasks.Types.PreviewWindows; break; } } } PlasmaComponents.Label { id: middleClickText text: i18n("Middle Click") } LatteComponents.ComboBox { id: middleClickAction Layout.fillWidth: true model: [ i18nc("The click action", "None"), i18n("Close Window or Group"), i18n("New Instance"), i18n("Minimize/Restore Window or Group"), i18n("Cycle Through Tasks"), i18n("Toggle Task Grouping") ] currentIndex: tasks.configuration.middleClickAction onCurrentIndexChanged: tasks.configuration.middleClickAction = currentIndex } PlasmaComponents.Label { text: i18n("Hover") } LatteComponents.ComboBox { id: hoverAction Layout.fillWidth: true model: [ i18nc("none action", "None"), i18n("Preview Windows"), i18n("Highlight Windows"), i18n("Preview and Highlight Windows"), ] currentIndex: { switch(tasks.configuration.hoverAction) { case LatteTasks.Types.NoneAction: return 0; case LatteTasks.Types.PreviewWindows: return 1; case LatteTasks.Types.HighlightWindows: return 2; case LatteTasks.Types.PreviewAndHighlightWindows: return 3; } return 0; } onCurrentIndexChanged: { switch(currentIndex) { case 0: tasks.configuration.hoverAction = LatteTasks.Types.NoneAction; break; case 1: tasks.configuration.hoverAction = LatteTasks.Types.PreviewWindows; break; case 2: tasks.configuration.hoverAction = LatteTasks.Types.HighlightWindows; break; case 3: tasks.configuration.hoverAction = LatteTasks.Types.PreviewAndHighlightWindows; break; } } } PlasmaComponents.Label { text: i18n("Wheel") } LatteComponents.ComboBox { id: wheelAction Layout.fillWidth: true model: [ i18nc("none action", "None"), i18n("Cycle Through Tasks"), i18n("Cycle And Minimize Tasks") ] currentIndex: tasks.configuration.taskScrollAction onCurrentIndexChanged: tasks.configuration.taskScrollAction = currentIndex } RowLayout { spacing: units.smallSpacing enabled: !disableAllWindowsFunctionality Layout.minimumWidth: middleClickText.width Layout.maximumWidth: middleClickText.width LatteComponents.ComboBox { id: modifier Layout.fillWidth: true model: ["Shift", "Ctrl", "Alt", "Meta"] currentIndex: tasks.configuration.modifier onCurrentIndexChanged: tasks.configuration.modifier = currentIndex } PlasmaComponents.Label { text: "+" } } RowLayout { spacing: units.smallSpacing enabled: !disableAllWindowsFunctionality readonly property int maxSize: 0.4 * dialog.optionsWidth LatteComponents.ComboBox { id: modifierClick Layout.preferredWidth: 0.7 * parent.maxSize Layout.maximumWidth: parent.maxSize model: [i18n("Left Click"), i18n("Middle Click"), i18n("Right Click")] currentIndex: tasks.configuration.modifierClick onCurrentIndexChanged: tasks.configuration.modifierClick = currentIndex } PlasmaComponents.Label { text: "=" } LatteComponents.ComboBox { id: modifierClickAction Layout.fillWidth: true model: [i18nc("The click action", "None"), i18n("Close Window or Group"), i18n("New Instance"), i18n("Minimize/Restore Window or Group"), i18n("Cycle Through Tasks"), i18n("Toggle Task Grouping")] currentIndex: tasks.configuration.modifierClickAction onCurrentIndexChanged: tasks.configuration.modifierClickAction = currentIndex } } } RowLayout { Layout.minimumWidth: dialog.optionsWidth Layout.maximumWidth: Layout.minimumWidth Layout.topMargin: units.smallSpacing spacing: units.smallSpacing enabled: !disableAllWindowsFunctionality } } } //! END: Actions //! BEGIN: Recycling /* ColumnLayout { spacing: units.smallSpacing visible: dialog.advancedLevel LatteComponents.Header { text: i18n("Recycling") } PlasmaComponents.Button { Layout.minimumWidth: dialog.optionsWidth Layout.maximumWidth: Layout.minimumWidth Layout.leftMargin: units.smallSpacing * 2 Layout.rightMargin: units.smallSpacing * 2 Layout.topMargin: units.smallSpacing text: i18n("Remove Latte Tasks Applet") enabled: latteView.latteTasksArePresent tooltip: i18n("Remove Latte Tasks plasmoid") onClicked: { latteView.removeTasksPlasmoid(); } } }*/ } }