/* * 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.abilities.host 0.1 as AbilityHost 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 "layouts" as Layouts import "./background" as Background import "./debugger" as Debugger 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 readonly property int version: LatteCore.Environment.makeVersion(0,9,75) readonly property bool kirigamiLibraryIsFound: LatteCore.Environment.frameworksVersion >= LatteCore.Environment.makeVersion(5,69,0) property bool backgroundOnlyOnMaximized: plasmoid.configuration.backgroundOnlyOnMaximized readonly property bool behaveAsPlasmaPanel: viewType === LatteCore.Types.PanelView readonly property bool behaveAsDockWithMask: !behaveAsPlasmaPanel readonly property bool viewIsAvailable: latteView && latteView.visibility && latteView.effects property int viewType: { if (!latteView || !latteView.visibility) { return LatteCore.Types.DockView; } if (screenEdgeMarginEnabled && root.floatingInternalGapIsForced) { //! dont use when floating views are requesting internal floating gap which is in client side return LatteCore.Types.DockView; } return viewTypeInQuestion; } property int viewTypeInQuestion: { //! viewType as chosen before considering other optios such as floating internal gap enforcement. //! It helps with binding loops if (!latteView || !latteView.visibility) { return LatteCore.Types.DockView; } if (background.customShadowedRectangleIsEnabled) { return LatteCore.Types.DockView; } var staticLayout = (plasmoid.configuration.minLength === plasmoid.configuration.maxLength); if ((plasmoid.configuration.alignment === LatteCore.Types.Justify || staticLayout) && background.isGreaterThanItemThickness && (parabolic.factor.maxZoom === 1.0)) { return LatteCore.Types.PanelView; } return LatteCore.Types.DockView; } property bool blurEnabled: plasmoid.configuration.blurEnabled && (!forceTransparentPanel || forcePanelForBusyBackground) readonly property bool inDraggingOverAppletOrOutOfContainment: latteView && latteView.containsDrag && !backDropArea.containsDrag readonly property Item dragInfo: Item { property bool entered: backDropArea.dragInfo.entered property bool isTask: backDropArea.dragInfo.isTask property bool isPlasmoid: backDropArea.dragInfo.isPlasmoid property bool isSeparator: backDropArea.dragInfo.isSeparator property bool isLatteTasks: backDropArea.dragInfo.isLatteTasks property bool onlyLaunchers: backDropArea.dragInfo.onlyLaunchers } 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 property bool editMode: plasmoid.userConfiguring property bool windowIsTouching: latteView && latteView.windowsTracker && (latteView.windowsTracker.currentScreen.activeWindowTouching || latteView.windowsTracker.currentScreen.activeWindowTouchingEdge || hasExpandedApplet) property bool floatingInternalGapIsForced: plasmoid.configuration.floatingInternalGapIsForced property bool hasFloatingGapInputEventsDisabled: root.screenEdgeMarginEnabled && !latteView.byPassWM && !root.inConfigureAppletsMode && !parabolic.isEnabled && (root.behaveAsPlasmaPanel || (root.behaveAsDockWithMask && !root.floatingInternalGapIsForced)) 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) )) || !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 && (normalBusyForTouchingBusyVerticalView || ( root.forceTransparentPanel && colorizerManager.backgroundIsBusy && root.themeColors === LatteContainment.Types.SmartThemeColors)) 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 && plasmoid.configuration.backgroundOnlyOnMaximized) property bool hideThickScreenGap: screenEdgeMarginEnabled && plasmoid.configuration.hideFloatingGapForMaximized && latteView && latteView.windowsTracker && latteView.windowsTracker.currentScreen.existsWindowMaximized property bool hideLengthScreenGaps: false /*set through binding*/ property bool mirrorScreenGap: screenEdgeMarginEnabled && plasmoid.configuration.floatingGapIsMirrored && latteView.visibility.mode === LatteCore.Types.AlwaysVisible 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 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 inStartup: true property bool isHorizontal: plasmoid.formFactor === PlasmaCore.Types.Horizontal 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 //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 real minLengthPerCentage: plasmoid.configuration.minLength property real maxLengthPerCentage: hideLengthScreenGaps ? 100 : plasmoid.configuration.maxLength property int minLength: { if (myView.alignment === 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*myView.itemShadow.size) property bool backgroundShadowsInRegularStateEnabled: LatteCore.WindowSystem.compositingActive && userShowPanelBackground && plasmoid.configuration.panelShadows 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 background opacity 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 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 property int widthMargins: root.isVertical ? metrics.totals.thicknessEdges : metrics.totals.lengthEdges property int heightMargins: root.isHorizontal ? metrics.totals.thicknessEdges : metrics.totals.lengthEdges property var iconsArray: [16, 22, 32, 48, 64, 96, 128, 256] property Item dragOverlay: _dragOverlay property Item toolBox readonly property alias animations: _animations readonly property alias autosize: _autosize readonly property alias background: _background readonly property alias debug: _debug readonly property alias environment: _environment readonly property alias indexer: _indexer readonly property alias indicators: _indicators readonly property alias layouter: _layouter readonly property alias launchers: _launchers readonly property alias metrics: _metrics readonly property alias myView: _myView readonly property alias parabolic: _parabolic readonly property alias thinTooltip: _thinTooltip readonly property alias userRequests: _userRequests 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 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; } 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 //////////////START OF BINDINGS //! Binding is needed in order for hideLengthScreenGaps to be activated or not only after //! View sliding in/out has finished. This way the animation is smoother for behaveAsPlasmaPanels Binding{ target: root property: "hideLengthScreenGaps" when: latteView && latteView.positioner && latteView.visibility && ((root.behaveAsPlasmaPanel && latteView.positioner.slideOffset === 0) || root.behaveAsDockWithMask) value: (hideThickScreenGap && (latteView.visibility.mode === LatteCore.Types.AlwaysVisible || latteView.visibility.mode === LatteCore.Types.WindowsGoBelow) && (plasmoid.configuration.alignment === LatteCore.Types.Justify) && plasmoid.configuration.maxLength>85) } //////////////END OF BINDINGS //////////////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; } //Block Hiding events if (editMode) { latteView.visibility.addBlockHidingEvent("main[qml]::inEditMode()"); } else { latteView.visibility.removeBlockHidingEvent("main[qml]::inEditMode()"); } } onInConfigureAppletsModeChanged: { updateIndexes(); } //! It is used only when the user chooses different alignment types //! and not during startup Connections { target: myView onAlignmentChanged: { if (!root.editMode) { return; } if (root.editMode){ if (root.myView.alignment===LatteCore.Types.Justify) { layouter.appletsInParentChange = true; fastLayoutManager.addJustifySplittersInMainLayout(); console.log("LAYOUTS: Moving applets from MAIN to THREE Layouts mode..."); fastLayoutManager.moveAppletsBasedOnJustifyAlignment(); layouter.appletsInParentChange = false; } else { layouter.appletsInParentChange = true; console.log("LAYOUTS: Moving applets from THREE to MAIN Layout mode..."); fastLayoutManager.joinLayoutsToMainLayout(); layouter.appletsInParentChange = false; } } fastLayoutManager.save(); } } 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; } } 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(); fastLayoutManager.restore(); 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; fastLayoutManager.save(); 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: { var appletItem = createAppletItem(applet); addAppletItemInLayout(appletItem, x, y); console.log(applet.pluginName); fastLayoutManager.save(); console.log("org.kde.latte configuration from qml appletOrder :: " + plasmoid.configuration.appletOrder + " :: " + fastLayoutManager.appletOrder); } 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; } fastLayoutManager.save(); } Plasmoid.onUserConfiguringChanged: { if (plasmoid.userConfiguring) { for (var i = 0; i < plasmoid.applets.length; ++i) { plasmoid.applets[i].expanded = false; } } } Plasmoid.onImmutableChanged: { plasmoid.action("configure").visible = !plasmoid.immutable; plasmoid.action("configure").enabled = !plasmoid.immutable; } //////////////END OF CONNECTIONS //////////////START OF FUNCTIONS function createAppletItem(applet) { var appletItem = appletItemComponent.createObject(dndSpacer.parent); appletItem.applet = applet; applet.parent = appletItem.appletWrapper; applet.anchors.fill = appletItem.appletWrapper; applet.visible = true; // don't show applet if it chooses to be hidden but still make it accessible in the panelcontroller appletItem.visible = Qt.binding(function() { return applet.status !== PlasmaCore.Types.HiddenStatus || (!plasmoid.immutable && root.inConfigureAppletsMode) }); return appletItem; } function createJustifySplitter() { var splitter = appletItemComponent.createObject(root); splitter.internalSplitterId = internalViewSplittersCount()+1; splitter.visible = true; return splitter; } function addAppletItemInLayout(appletItem, x, y){ if ( (dndSpacer.parent === layoutsContainer.mainLayout) || (dndSpacer.parent === layoutsContainer.startLayout) || (dndSpacer.parent===layoutsContainer.endLayout)) { // Is there a DND placeholder? Replace it! fastLayoutManager.insertBefore(dndSpacer, appletItem); dndSpacer.parent = root; return; } else if (x >= 0 && y >= 0) { // If the provided position is valid, use it. fastLayoutManager.insertAtCoordinates(appletItem, x , y); } else { // Fall through to adding at the end of main layout. appletItem.parent = layoutsContainer.mainLayout; } //Important, removes the first children of the layoutsContainer.mainLayout after the first applet has been added lastSpacer.parent = root; updateIndexes(); } function addInternalViewSplittersInMainLayout(){ if (internalViewSplittersCount() === 0) { addInternalViewSplitterInMain(plasmoid.configuration.splitterPosition); addInternalViewSplitterInMain(plasmoid.configuration.splitterPosition2); } } function addInternalViewSplitterInMain(pos){ addInternalViewSplitterInLayout(layoutsContainer.mainLayout, pos); } function addInternalViewSplitterInLayout(area, pos){ var splittersCount = internalViewSplittersCount(); if(splittersCount<2){ var splitter = appletItemComponent.createObject(root); splitter.internalSplitterId = splittersCount+1; splitter.visible = true; if(pos>=0 ){ LayoutManager.insertAtIndex(area, splitter, pos); } else { LayoutManager.insertAtIndex(area, splitter, Math.floor(area.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 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 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 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 components Component { id: appletItemComponent Applet.AppletItem{ animations: _animations debug: _debug environment: _environment indexer: _indexer indicators: _indicators launchers: _launchers layouter: _layouter layouts: layoutsContainer metrics: _metrics myView: _myView parabolic: _parabolic shortcuts: _shortcuts thinTooltip: _thinTooltip userRequests: _userRequests } } Upgrader { id: upgrader } ///////////////END components PlasmaCore.ColorScope{ id: colorScopePalette } LatteContainment.LayoutManager{ id:fastLayoutManager plasmoidObj: plasmoid rootItem: root dndSpacerItem: dndSpacer mainLayout: layoutsContainer.mainLayout startLayout: layoutsContainer.startLayout endLayout: layoutsContainer.endLayout metrics: _metrics onAppletOrderChanged: { plasmoid.configuration.appletOrder = fastLayoutManager.appletOrder; root.updateIndexes(); } onSplitterPositionChanged: { plasmoid.configuration.splitterPosition = fastLayoutManager.splitterPosition; root.updateIndexes(); } onSplitterPosition2Changed: { plasmoid.configuration.splitterPosition2 = fastLayoutManager.splitterPosition2; root.updateIndexes(); } } ///////////////BEGIN UI elements Loader{ active: debug.windowEnabled sourceComponent: Debugger.DebugWindow{} } 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: debug.graphicsEnabled z:10 sourceComponent: Item{ Rectangle{ anchors.fill: parent color: "yellow" opacity: 0.06 } } } VisibilityManager{ id: visibilityManager layouts: layoutsContainer } DragDropArea { id: backDropArea anchors.fill: parent Item{ anchors.fill: layoutsContainer Background.MultiLayered{ id: _background } } Layouts.LayoutsContainer { id: layoutsContainer } } Colorizer.Manager { id: colorizerManager } EditMode.ConfigOverlay{ id: _dragOverlay } 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: metrics.iconSize height: metrics.iconSize property int thickMargin: metrics.margin.screenEdge + metrics.margin.thickness 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: thickMargin; 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: thickMargin; 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: thickMargin; 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 layouts: layoutsContainer metrics: _metrics settings: universalSettings } Ability.AutoSize { id: _autosize layouts: layoutsContainer layouter: _layouter metrics: _metrics visibility: visibilityManager } Ability.Debug { id: _debug } AbilityHost.Environment{ id: _environment } Ability.Indexer { id: _indexer layouts: layoutsContainer } Ability.Indicators{ id: _indicators view: latteView } Ability.Launchers { id: _launchers layouts: layoutsContainer layoutName: latteView && latteView.layout ? latteView.layout.name : "" } Ability.Layouter { id: _layouter animations: _animations indexer: _indexer layouts: layoutsContainer } Ability.Metrics { id: _metrics animations: _animations autosize: _autosize background: _background indicators: _indicators parabolic: _parabolic } Ability.MyView { id: _myView layouts: layoutsContainer } Ability.ParabolicEffect { id: _parabolic animations: _animations debug: _debug layouts: layoutsContainer view: latteView } Ability.PositionShortcuts { id: _shortcuts layouts: layoutsContainer } Ability.ThinTooltip { id: _thinTooltip debug: _debug layouts: layoutsContainer view: latteView } Ability.UserRequests { id: _userRequests view: latteView } 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: debug.localGeometryEnabled sourceComponent: Rectangle{ x: latteView.localGeometry.x y: latteView.localGeometry.y //! when view is resized there is a chance that geometry is faulty stacked in old values width: Math.min(latteView.localGeometry.width, root.width) //! fixes updating height: Math.min(latteView.localGeometry.height, root.height) //! fixes updating color: "blue" border.width: 2 border.color: "red" opacity: 0.35 } } Loader{ anchors.fill: parent active: latteView && latteView.effects && debug.inputMaskEnabled sourceComponent: Rectangle{ x: latteView.effects.inputMask.x y: latteView.effects.inputMask.y //! when view is resized there is a chance that geometry is faulty stacked in old values width: Math.min(latteView.effects.inputMask.width, root.width) //! fixes updating height: Math.min(latteView.effects.inputMask.height, root.height) //! fixes updating color: "purple" border.width: 1 border.color: "black" opacity: 0.20 } } }