1/* 2 SPDX-FileCopyrightText: 2016 Smith AR <audoban@openmailbox.org> 3 SPDX-FileCopyrightText: 2016 Michail Vourlakos <mvourlakos@gmail.com> 4 SPDX-License-Identifier: GPL-2.0-or-later 5*/ 6 7import QtQuick 2.8 8import QtQuick.Layouts 1.1 9import QtQuick.Window 2.2 10import QtGraphicalEffects 1.0 11 12import org.kde.plasma.core 2.0 as PlasmaCore 13import org.kde.plasma.components 2.0 as PlasmaComponents 14import org.kde.kquickcontrolsaddons 2.0 15import org.kde.plasma.plasmoid 2.0 16 17import org.kde.latte.abilities.host 0.1 as AbilityHost 18 19import org.kde.latte.core 0.2 as LatteCore 20import org.kde.latte.components 1.0 as LatteComponents 21import org.kde.latte.private.app 0.1 as LatteApp 22import org.kde.latte.private.containment 0.1 as LatteContainment 23 24import "abilities" as Ability 25import "applet" as Applet 26import "colorizer" as Colorizer 27import "editmode" as EditMode 28import "layouts" as Layouts 29import "./background" as Background 30import "./debugger" as Debugger 31 32Item { 33 id: root 34 objectName: "containmentViewLayout" 35 36 LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft && !root.isVertical 37 LayoutMirroring.childrenInherit: true 38 39 //// BEGIN SIGNALS 40 signal destroyInternalViewSplitters(); 41 signal emptyAreasWheel(QtObject wheel); 42 signal separatorsUpdated(); 43 signal updateEffectsArea(); 44 signal updateIndexes(); 45 46 signal broadcastedToApplet(string pluginName, string action, variant value); 47 //// END SIGNALS 48 49 ////BEGIN properties 50 readonly property int version: LatteCore.Environment.makeVersion(0,9,75) 51 readonly property bool kirigamiLibraryIsFound: LatteCore.Environment.frameworksVersion >= LatteCore.Environment.makeVersion(5,69,0) 52 53 property bool backgroundOnlyOnMaximized: plasmoid.configuration.backgroundOnlyOnMaximized 54 readonly property bool behaveAsPlasmaPanel: viewType === LatteCore.Types.PanelView 55 readonly property bool behaveAsDockWithMask: !behaveAsPlasmaPanel 56 57 readonly property bool viewIsAvailable: latteView && latteView.visibility && latteView.effects 58 59 property int viewType: { 60 if (!latteView || !latteView.visibility) { 61 return LatteCore.Types.DockView; 62 } 63 64 if (screenEdgeMarginEnabled && root.floatingInternalGapIsForced) { 65 //! dont use when floating views are requesting internal floating gap which is in client side 66 return LatteCore.Types.DockView; 67 } 68 69 return viewTypeInQuestion; 70 } 71 72 property int viewTypeInQuestion: { 73 //! viewType as chosen before considering other optios such as floating internal gap enforcement. 74 //! It helps with binding loops 75 if (!latteView || !latteView.visibility) { 76 return LatteCore.Types.DockView; 77 } 78 79 if (background.customShadowedRectangleIsEnabled) { 80 return LatteCore.Types.DockView; 81 } 82 83 var staticLayout = (plasmoid.configuration.minLength === plasmoid.configuration.maxLength); 84 85 if ((plasmoid.configuration.alignment === LatteCore.Types.Justify || staticLayout) 86 && background.isGreaterThanItemThickness 87 && (parabolic.factor.maxZoom === 1.0)) { 88 return LatteCore.Types.PanelView; 89 } 90 91 return LatteCore.Types.DockView; 92 } 93 94 property bool blurEnabled: plasmoid.configuration.blurEnabled && (!forceTransparentPanel || forcePanelForBusyBackground) 95 96 readonly property bool inDraggingOverAppletOrOutOfContainment: latteView && latteView.containsDrag && !backDropArea.containsDrag 97 98 readonly property Item dragInfo: Item { 99 property bool entered: backDropArea.dragInfo.entered 100 property bool isTask: backDropArea.dragInfo.isTask 101 property bool isPlasmoid: backDropArea.dragInfo.isPlasmoid 102 property bool isSeparator: backDropArea.dragInfo.isSeparator 103 property bool isLatteTasks: backDropArea.dragInfo.isLatteTasks 104 property bool onlyLaunchers: backDropArea.dragInfo.onlyLaunchers 105 } 106 107 property bool containsOnlyPlasmaTasks: latteView ? latteView.extendedInterface.hasPlasmaTasks && !latteView.extendedInterface.hasLatteTasks : false 108 property bool dockContainsMouse: latteView && latteView.visibility ? latteView.visibility.containsMouse : false 109 110 property bool disablePanelShadowMaximized: plasmoid.configuration.disablePanelShadowForMaximized && LatteCore.WindowSystem.compositingActive 111 property bool drawShadowsExternal: panelShadowsActive && behaveAsPlasmaPanel 112 113 property bool editMode: plasmoid.userConfiguring 114 property bool windowIsTouching: latteView && latteView.windowsTracker 115 && (latteView.windowsTracker.currentScreen.activeWindowTouching 116 || latteView.windowsTracker.currentScreen.activeWindowTouchingEdge 117 || hasExpandedApplet) 118 119 property bool floatingInternalGapIsForced: plasmoid.configuration.floatingInternalGapIsForced 120 121 property bool hasFloatingGapInputEventsDisabled: root.screenEdgeMarginEnabled 122 && !latteView.byPassWM 123 && !root.inConfigureAppletsMode 124 && !parabolic.isEnabled 125 && (root.behaveAsPlasmaPanel || (root.behaveAsDockWithMask && !root.floatingInternalGapIsForced)) 126 127 property bool forceSolidPanel: (latteView && latteView.visibility 128 && LatteCore.WindowSystem.compositingActive 129 && !inConfigureAppletsMode 130 && userShowPanelBackground 131 && ( (plasmoid.configuration.solidBackgroundForMaximized 132 && !(hasExpandedApplet && !plasmaBackgroundForPopups) 133 && (latteView.windowsTracker.currentScreen.existsWindowTouching 134 || latteView.windowsTracker.currentScreen.existsWindowTouchingEdge)) 135 || (hasExpandedApplet && plasmaBackgroundForPopups) )) 136 || !LatteCore.WindowSystem.compositingActive 137 138 property bool forceTransparentPanel: root.backgroundOnlyOnMaximized 139 && latteView && latteView.visibility 140 && LatteCore.WindowSystem.compositingActive 141 && !inConfigureAppletsMode 142 && !forceSolidPanel 143 && !(latteView.windowsTracker.currentScreen.existsWindowTouching 144 || latteView.windowsTracker.currentScreen.existsWindowTouchingEdge) 145 && !(windowColors === LatteContainment.Types.ActiveWindowColors && selectedWindowsTracker.existsWindowActive) 146 147 property bool forcePanelForBusyBackground: userShowPanelBackground && (normalBusyForTouchingBusyVerticalView 148 || ( root.forceTransparentPanel 149 && colorizerManager.backgroundIsBusy 150 && root.themeColors === LatteContainment.Types.SmartThemeColors)) 151 152 property bool normalBusyForTouchingBusyVerticalView: (latteView && latteView.windowsTracker /*is touching a vertical view that is in busy state and the user prefers isBusy transparency*/ 153 && latteView.windowsTracker.currentScreen.isTouchingBusyVerticalView 154 && plasmoid.configuration.backgroundOnlyOnMaximized) 155 156 property bool appletIsDragged: root.dragOverlay && root.dragOverlay.pressed 157 property bool hideThickScreenGap: false /*set through binding*/ 158 property bool hideLengthScreenGaps: false /*set through binding*/ 159 160 property bool mirrorScreenGap: screenEdgeMarginEnabled 161 && plasmoid.configuration.floatingGapIsMirrored 162 && latteView.visibility.mode === LatteCore.Types.AlwaysVisible 163 164 165 166 property int themeColors: plasmoid.configuration.themeColors 167 property int windowColors: plasmoid.configuration.windowColors 168 169 property bool colorizerEnabled: themeColors !== LatteContainment.Types.PlasmaThemeColors || windowColors !== LatteContainment.Types.NoneWindowColors 170 171 property bool plasmaBackgroundForPopups: plasmoid.configuration.plasmaBackgroundForPopups 172 173 readonly property bool hasExpandedApplet: latteView && latteView.extendedInterface.hasExpandedApplet; 174 readonly property bool hasUserSpecifiedBackground: (latteView && latteView.layout && latteView.layout.background.startsWith("/")) ? 175 true : false 176 177 readonly property bool inConfigureAppletsMode: root.editMode && plasmoid.configuration.inConfigureAppletsMode 178 179 property bool closeActiveWindowEnabled: plasmoid.configuration.closeActiveWindowEnabled 180 property bool dragActiveWindowEnabled: plasmoid.configuration.dragActiveWindowEnabled 181 property bool immutable: plasmoid.immutable 182 property bool inFullJustify: (plasmoid.configuration.alignment === LatteCore.Types.Justify) && (maxLengthPerCentage===100) 183 property bool inStartup: true 184 185 property bool isHorizontal: plasmoid.formFactor === PlasmaCore.Types.Horizontal 186 property bool isVertical: !isHorizontal 187 188 property bool mouseWheelActions: plasmoid.configuration.mouseWheelActions 189 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 190 191 //FIXME: possibly this is going to be the default behavior, this user choice 192 //has been dropped from the Dock Configuration Window 193 //property bool smallAutomaticIconJumps: plasmoid.configuration.smallAutomaticIconJumps 194 property bool smallAutomaticIconJumps: true 195 196 property bool userShowPanelBackground: LatteCore.WindowSystem.compositingActive ? plasmoid.configuration.useThemePanel : true 197 property bool useThemePanel: noApplets === 0 || !LatteCore.WindowSystem.compositingActive ? 198 true : (plasmoid.configuration.useThemePanel || plasmoid.configuration.solidBackgroundForMaximized) 199 200 property bool plasma515: LatteCore.Environment.plasmaDesktopVersion >= LatteCore.Environment.makeVersion(5,15,0) 201 property bool plasma518: LatteCore.Environment.plasmaDesktopVersion >= LatteCore.Environment.makeVersion(5,18,0) 202 203 readonly property int minAppletLengthInConfigure: 16 204 readonly property int maxJustifySplitterSize: 64 205 206 property real minLengthPerCentage: plasmoid.configuration.minLength 207 property real maxLengthPerCentage: hideLengthScreenGaps ? 100 : plasmoid.configuration.maxLength 208 209 property int minLength: { 210 if (myView.alignment === LatteCore.Types.Justify) { 211 return maxLength; 212 } 213 214 if (root.isHorizontal) { 215 return behaveAsPlasmaPanel && LatteCore.WindowSystem.compositingActive ? width : width * (minLengthPerCentage/100) 216 } else { 217 return behaveAsPlasmaPanel && LatteCore.WindowSystem.compositingActive ? height : height * (minLengthPerCentage/100) 218 } 219 } 220 221 property int maxLength: { 222 if (root.isHorizontal) { 223 return behaveAsPlasmaPanel ? width : width * (maxLengthPerCentage/100) 224 } else { 225 return behaveAsPlasmaPanel ? height : height * (maxLengthPerCentage/100) 226 } 227 } 228 229 property int scrollAction: plasmoid.configuration.scrollAction 230 231 property bool panelOutline: plasmoid.configuration.panelOutline 232 property int panelEdgeSpacing: Math.max(background.lengthMargins, 1.5*myView.itemShadow.size) 233 234 property bool backgroundShadowsInRegularStateEnabled: LatteCore.WindowSystem.compositingActive 235 && userShowPanelBackground 236 && plasmoid.configuration.panelShadows 237 238 property bool panelShadowsActive: { 239 if (!userShowPanelBackground) { 240 return false; 241 } 242 243 if (inConfigureAppletsMode) { 244 return plasmoid.configuration.panelShadows; 245 } 246 247 var forcedNoShadows = (plasmoid.configuration.panelShadows && disablePanelShadowMaximized 248 && latteView && latteView.windowsTracker && latteView.windowsTracker.currentScreen.activeWindowMaximized); 249 250 if (forcedNoShadows) { 251 return false; 252 } 253 254 var transparencyCheck = (blurEnabled || (!blurEnabled && background.currentOpacity>20)); 255 256 //! Draw shadows for isBusy state only when current background opacity is greater than 10% 257 if (plasmoid.configuration.panelShadows && root.forcePanelForBusyBackground && transparencyCheck) { 258 return true; 259 } 260 261 if (( (plasmoid.configuration.panelShadows && !root.backgroundOnlyOnMaximized) 262 || (plasmoid.configuration.panelShadows && root.backgroundOnlyOnMaximized && !root.forceTransparentPanel)) 263 && !forcedNoShadows) { 264 return true; 265 } 266 267 if (hasExpandedApplet && plasmaBackgroundForPopups) { 268 return true; 269 } 270 271 return false; 272 } 273 274 property int offset: { 275 if (behaveAsPlasmaPanel) { 276 return 0; 277 } 278 279 if (root.isHorizontal) { 280 return width * (plasmoid.configuration.offset/100); 281 } else { 282 height * (plasmoid.configuration.offset/100) 283 } 284 } 285 286 property int editShadow: { 287 if (!LatteCore.WindowSystem.compositingActive) { 288 return 0; 289 } else if (latteView && latteView.screenGeometry) { 290 return latteView.screenGeometry.height/90; 291 } else { 292 return 7; 293 } 294 } 295 296 property bool screenEdgeMarginEnabled: plasmoid.configuration.screenEdgeMargin >= 0 297 298 property int widthMargins: root.isVertical ? metrics.totals.thicknessEdges : metrics.totals.lengthEdges 299 property int heightMargins: root.isHorizontal ? metrics.totals.thicknessEdges : metrics.totals.lengthEdges 300 301 property var iconsArray: [16, 22, 32, 48, 64, 96, 128, 256] 302 303 property Item dragOverlay: _dragOverlay 304 property Item toolBox 305 306 readonly property alias animations: _animations 307 readonly property alias autosize: _autosize 308 readonly property alias background: _background 309 readonly property alias debug: _debug 310 readonly property alias environment: _environment 311 readonly property alias indexer: _indexer 312 readonly property alias indicators: _indicators 313 readonly property alias layouter: _layouter 314 readonly property alias launchers: _launchers 315 readonly property alias metrics: _metrics 316 readonly property alias myView: _myView 317 readonly property alias parabolic: _parabolic 318 readonly property alias thinTooltip: _thinTooltip 319 readonly property alias userRequests: _userRequests 320 321 readonly property alias maskManager: visibilityManager 322 readonly property alias layoutsContainerItem: layoutsContainer 323 324 readonly property alias latteView: _interfaces.view 325 readonly property alias layoutsManager: _interfaces.layoutsManager 326 readonly property alias shortcutsEngine: _interfaces.globalShortcuts 327 readonly property alias themeExtended: _interfaces.themeExtended 328 readonly property alias universalSettings: _interfaces.universalSettings 329 330 readonly property QtObject selectedWindowsTracker: { 331 if (latteView && latteView.windowsTracker) { 332 switch(plasmoid.configuration.activeWindowFilter) { 333 case LatteContainment.Types.ActiveInCurrentScreen: 334 return latteView.windowsTracker.currentScreen; 335 case LatteContainment.Types.ActiveFromAllScreens: 336 return latteView.windowsTracker.allScreens; 337 } 338 } 339 340 return null; 341 } 342 343 Plasmoid.backgroundHints: PlasmaCore.Types.NoBackground 344 345 //// BEGIN properties in functions 346 property int noApplets: { 347 var count1 = 0; 348 var count2 = 0; 349 350 count1 = layoutsContainer.mainLayout.children.length; 351 var tempLength = layoutsContainer.mainLayout.children.length; 352 353 for (var i=tempLength-1; i>=0; --i) { 354 var applet = layoutsContainer.mainLayout.children[i]; 355 if (applet && (applet === dndSpacer || applet.isInternalViewSplitter)) 356 count1--; 357 } 358 359 count2 = layoutsContainer.endLayout.children.length; 360 tempLength = layoutsContainer.endLayout.children.length; 361 362 for (var i=tempLength-1; i>=0; --i) { 363 var applet = layoutsContainer.endLayout.children[i]; 364 if (applet && (applet === dndSpacer || applet.isInternalViewSplitter)) 365 count2--; 366 } 367 368 return (count1 + count2); 369 } 370 371 ///The index of user's current icon size 372 property int currentIconIndex:{ 373 for(var i=iconsArray.length-1; i>=0; --i){ 374 if(iconsArray[i] === metrics.iconSize){ 375 return i; 376 } 377 } 378 return 3; 379 } 380 381 //// END properties in functions 382 383 ////////////////END properties 384 385 //////////////START OF BINDINGS 386 387 //! Wait until the mouse leaves the view 388 Binding { 389 target: root 390 property: "hideThickScreenGap" 391 when: !(plasmoid.configuration.floatingGapHidingWaitsMouse && dockContainsMouse) 392 value: screenEdgeMarginEnabled 393 && plasmoid.configuration.hideFloatingGapForMaximized 394 && latteView && latteView.windowsTracker 395 && latteView.windowsTracker.currentScreen.existsWindowMaximized 396 } 397 398 //! Binding is needed in order for hideLengthScreenGaps to be activated or not only after 399 //! View sliding in/out has finished. This way the animation is smoother for behaveAsPlasmaPanels 400 Binding{ 401 target: root 402 property: "hideLengthScreenGaps" 403 when: latteView && latteView.positioner && latteView.visibility 404 && ((root.behaveAsPlasmaPanel && latteView.positioner.slideOffset === 0) 405 || root.behaveAsDockWithMask) 406 && !(plasmoid.configuration.floatingGapHidingWaitsMouse && dockContainsMouse) 407 value: (hideThickScreenGap 408 && (latteView.visibility.mode === LatteCore.Types.AlwaysVisible 409 || latteView.visibility.mode === LatteCore.Types.WindowsGoBelow) 410 && (plasmoid.configuration.alignment === LatteCore.Types.Justify) 411 && plasmoid.configuration.maxLength>85) 412 } 413 414 //////////////END OF BINDINGS 415 416 417 //////////////START OF CONNECTIONS 418 onEditModeChanged: { 419 if (!editMode) { 420 layouter.updateSizeForAppletsInFill(); 421 } 422 423 //! This is used in case the dndspacer has been left behind 424 //! e.g. the user drops a folder and a context menu is appearing 425 //! but the user decides to not make a choice for the applet type 426 if (dndSpacer.parent !== root) { 427 dndSpacer.parent = root; 428 } 429 430 //Block Hiding events 431 if (editMode) { 432 latteView.visibility.addBlockHidingEvent("main[qml]::inEditMode()"); 433 } else { 434 latteView.visibility.removeBlockHidingEvent("main[qml]::inEditMode()"); 435 } 436 } 437 438 onInConfigureAppletsModeChanged: { 439 updateIndexes(); 440 } 441 442 //! It is used only when the user chooses different alignment types and not during startup 443 Connections { 444 target: latteView ? latteView : null 445 onAlignmentChanged: { 446 if (latteView.alignment === LatteCore.Types.NoneAlignment) { 447 return; 448 } 449 450 var previousalignment = plasmoid.configuration.alignment; 451 452 if (latteView.alignment===LatteCore.Types.Justify && previousalignment!==LatteCore.Types.Justify) { // main -> justify 453 layouter.appletsInParentChange = true; 454 fastLayoutManager.addJustifySplittersInMainLayout(); 455 console.log("LAYOUTS: Moving applets from MAIN to THREE Layouts mode..."); 456 fastLayoutManager.moveAppletsBasedOnJustifyAlignment(); 457 layouter.appletsInParentChange = false; 458 } else if (latteView.alignment!==LatteCore.Types.Justify && previousalignment===LatteCore.Types.Justify ) { // justify ->main 459 layouter.appletsInParentChange = true; 460 console.log("LAYOUTS: Moving applets from THREE to MAIN Layout mode..."); 461 fastLayoutManager.joinLayoutsToMainLayout(); 462 layouter.appletsInParentChange = false; 463 } 464 465 plasmoid.configuration.alignment = latteView.alignment; 466 fastLayoutManager.save(); 467 } 468 } 469 470 onLatteViewChanged: { 471 if (latteView) { 472 if (latteView.positioner) { 473 latteView.positioner.hidingForRelocationStarted.connect(visibilityManager.slotHideDockDuringLocationChange); 474 latteView.positioner.showingAfterRelocationFinished.connect(visibilityManager.slotShowDockAfterLocationChange); 475 } 476 477 if (latteView.visibility) { 478 latteView.visibility.onContainsMouseChanged.connect(visibilityManager.slotContainsMouseChanged); 479 latteView.visibility.onMustBeHide.connect(visibilityManager.slotMustBeHide); 480 latteView.visibility.onMustBeShown.connect(visibilityManager.slotMustBeShown); 481 } 482 } 483 } 484 485 Connections { 486 target: latteView 487 onPositionerChanged: { 488 if (latteView.positioner) { 489 latteView.positioner.hidingForRelocationStarted.connect(visibilityManager.slotHideDockDuringLocationChange); 490 latteView.positioner.showingAfterRelocationFinished.connect(visibilityManager.slotShowDockAfterLocationChange); 491 } 492 } 493 494 onVisibilityChanged: { 495 if (latteView.visibility) { 496 latteView.visibility.onContainsMouseChanged.connect(visibilityManager.slotContainsMouseChanged); 497 latteView.visibility.onMustBeHide.connect(visibilityManager.slotMustBeHide); 498 latteView.visibility.onMustBeShown.connect(visibilityManager.slotMustBeShown); 499 } 500 } 501 } 502 503 504 onMaxLengthChanged: { 505 layouter.updateSizeForAppletsInFill(); 506 } 507 508 onToolBoxChanged: { 509 if (toolBox) { 510 toolBox.visible = false; 511 } 512 } 513 514 onIsVerticalChanged: { 515 if (isVertical) { 516 if (plasmoid.configuration.alignment === LatteCore.Types.Left) 517 plasmoid.configuration.alignment = LatteCore.Types.Top; 518 else if (plasmoid.configuration.alignment === LatteCore.Types.Right) 519 plasmoid.configuration.alignment = LatteCore.Types.Bottom; 520 } else { 521 if (plasmoid.configuration.alignment === LatteCore.Types.Top) 522 plasmoid.configuration.alignment = LatteCore.Types.Left; 523 else if (plasmoid.configuration.alignment === LatteCore.Types.Bottom) 524 plasmoid.configuration.alignment = LatteCore.Types.Right; 525 } 526 } 527 528 Component.onCompleted: { 529 upgrader_v010_alignment(); 530 531 fastLayoutManager.restore(); 532 plasmoid.action("configure").visible = !plasmoid.immutable; 533 plasmoid.action("configure").enabled = !plasmoid.immutable; 534 } 535 536 Component.onDestruction: { 537 console.debug("Destroying Latte Dock Containment ui..."); 538 539 layouter.appletsInParentChange = true; 540 fastLayoutManager.save(); 541 542 if (latteView) { 543 if (latteView.positioner) { 544 latteView.positioner.hidingForRelocationStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); 545 latteView.positioner.showingAfterRelocationFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); 546 } 547 548 if (latteView.visibility) { 549 latteView.visibility.onContainsMouseChanged.disconnect(visibilityManager.slotContainsMouseChanged); 550 latteView.visibility.onMustBeHide.disconnect(visibilityManager.slotMustBeHide); 551 latteView.visibility.onMustBeShown.disconnect(visibilityManager.slotMustBeShown); 552 } 553 } 554 } 555 556 Containment.onAppletAdded: fastLayoutManager.addAppletItem(applet, x, y); 557 Containment.onAppletRemoved: fastLayoutManager.removeAppletItem(applet); 558 559 Plasmoid.onUserConfiguringChanged: { 560 if (plasmoid.userConfiguring) { 561 for (var i = 0; i < plasmoid.applets.length; ++i) { 562 plasmoid.applets[i].expanded = false; 563 } 564 } 565 } 566 567 Plasmoid.onImmutableChanged: { 568 plasmoid.action("configure").visible = !plasmoid.immutable; 569 plasmoid.action("configure").enabled = !plasmoid.immutable; 570 } 571 //////////////END OF CONNECTIONS 572 573 //////////////START OF FUNCTIONS 574 function createAppletItem(applet) { 575 var appletItem = appletItemComponent.createObject(dndSpacer.parent); 576 appletItem.applet = applet; 577 applet.parent = appletItem.appletWrapper; 578 applet.anchors.fill = appletItem.appletWrapper; 579 applet.visible = true; 580 581 // don't show applet if it chooses to be hidden but still make it accessible in the panelcontroller 582 appletItem.visible = Qt.binding(function() { 583 return applet.status !== PlasmaCore.Types.HiddenStatus || (!plasmoid.immutable && root.inConfigureAppletsMode) 584 }); 585 586 return appletItem; 587 } 588 589 function createJustifySplitter() { 590 var splitter = appletItemComponent.createObject(root); 591 splitter.internalSplitterId = internalViewSplittersCount()+1; 592 splitter.visible = true; 593 return splitter; 594 } 595 596 //! it is used in order to check the right click position 597 //! the only way to take into account the visual appearance 598 //! of the applet (including its spacers) 599 function appletContainsPos(appletId, pos){ 600 for (var i = 0; i < layoutsContainer.startLayout.children.length; ++i) { 601 var child = layoutsContainer.startLayout.children[i]; 602 603 if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) 604 return true; 605 } 606 607 for (var i = 0; i < layoutsContainer.mainLayout.children.length; ++i) { 608 var child = layoutsContainer.mainLayout.children[i]; 609 610 if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) 611 return true; 612 } 613 614 for (var i = 0; i < layoutsContainer.endLayout.children.length; ++i) { 615 var child = layoutsContainer.endLayout.children[i]; 616 617 if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) 618 return true; 619 } 620 621 return false; 622 } 623 624 function internalViewSplittersCount(){ 625 var splitters = 0; 626 for (var container in layoutsContainer.startLayout.children) { 627 var item = layoutsContainer.startLayout.children[container]; 628 if(item && item.isInternalViewSplitter) { 629 splitters = splitters + 1; 630 } 631 } 632 633 for (var container in layoutsContainer.mainLayout.children) { 634 var item = layoutsContainer.mainLayout.children[container]; 635 if(item && item.isInternalViewSplitter) { 636 splitters = splitters + 1; 637 } 638 } 639 640 for (var container in layoutsContainer.endLayout.children) { 641 var item = layoutsContainer.endLayout.children[container]; 642 if(item && item.isInternalViewSplitter) { 643 splitters = splitters + 1; 644 } 645 } 646 647 return splitters; 648 } 649 650 function mouseInCanBeHoveredApplet(){ 651 var applets = layoutsContainer.startLayout.children; 652 653 for(var i=0; i<applets.length; ++i){ 654 var applet = applets[i]; 655 656 if(applet && applet.containsMouse && !applet.originalAppletBehavior && applet.parabolicEffectIsSupported){ 657 return true; 658 } 659 } 660 661 applets = layoutsContainer.mainLayout.children; 662 663 for(var i=0; i<applets.length; ++i){ 664 var applet = applets[i]; 665 666 if(applet && applet.containsMouse && !applet.originalAppletBehavior && applet.parabolicEffectIsSupported){ 667 return true; 668 } 669 } 670 671 ///check second layout also 672 applets = layoutsContainer.endLayout.children; 673 674 for(var i=0; i<applets.length; ++i){ 675 var applet = applets[i]; 676 677 if(applet && applet.containsMouse && !applet.originalAppletBehavior && applet.parabolicEffectIsSupported){ 678 return true; 679 } 680 } 681 682 return false; 683 } 684 685 function sizeIsFromAutomaticMode(size){ 686 687 for(var i=iconsArray.length-1; i>=0; --i){ 688 if(iconsArray[i] === size){ 689 return true; 690 } 691 } 692 693 return false; 694 } 695 696 function upgrader_v010_alignment() { 697 //! IMPORTANT, special case because it needs to be loaded on Component constructor 698 if (!plasmoid.configuration.alignmentUpgraded) { 699 plasmoid.configuration.alignment = plasmoid.configuration.panelPosition; 700 plasmoid.configuration.alignmentUpgraded = true; 701 } 702 } 703 //END functions 704 705 ///////////////BEGIN components 706 Component { 707 id: appletItemComponent 708 Applet.AppletItem{ 709 animations: _animations 710 debug: _debug 711 environment: _environment 712 indexer: _indexer 713 indicators: _indicators 714 launchers: _launchers 715 layouter: _layouter 716 layouts: layoutsContainer 717 metrics: _metrics 718 myView: _myView 719 parabolic: _parabolic 720 shortcuts: _shortcuts 721 thinTooltip: _thinTooltip 722 userRequests: _userRequests 723 } 724 } 725 726 Upgrader { 727 id: upgrader 728 } 729 730 ///////////////END components 731 732 PlasmaCore.ColorScope{ 733 id: colorScopePalette 734 } 735 736 LatteContainment.LayoutManager{ 737 id:fastLayoutManager 738 plasmoidObj: plasmoid 739 rootItem: root 740 dndSpacerItem: dndSpacer 741 mainLayout: layoutsContainer.mainLayout 742 startLayout: layoutsContainer.startLayout 743 endLayout: layoutsContainer.endLayout 744 metrics: _metrics 745 746 onLockedZoomAppletsChanged: plasmoid.configuration.lockedZoomApplets = fastLayoutManager.lockedZoomApplets; 747 onUserBlocksColorizingAppletsChanged: plasmoid.configuration.userBlocksColorizingApplets = fastLayoutManager.userBlocksColorizingApplets; 748 749 onAppletOrderChanged: { 750 plasmoid.configuration.appletOrder = fastLayoutManager.appletOrder; 751 root.updateIndexes(); 752 } 753 754 onSplitterPositionChanged: { 755 plasmoid.configuration.splitterPosition = fastLayoutManager.splitterPosition; 756 root.updateIndexes(); 757 } 758 759 onSplitterPosition2Changed: { 760 plasmoid.configuration.splitterPosition2 = fastLayoutManager.splitterPosition2; 761 root.updateIndexes(); 762 } 763 } 764 765 ///////////////BEGIN UI elements 766 767 Loader{ 768 active: debug.windowEnabled 769 sourceComponent: Debugger.DebugWindow{} 770 } 771 772 Loader{ 773 anchors.fill: parent 774 active: debug.graphicsEnabled 775 z:10 776 777 sourceComponent: Item{ 778 Rectangle{ 779 anchors.fill: parent 780 color: "yellow" 781 opacity: 0.06 782 } 783 } 784 } 785 786 BindingsExternal { 787 id: bindingsExternal 788 } 789 790 VisibilityManager{ 791 id: visibilityManager 792 layouts: layoutsContainer 793 } 794 795 DragDropArea { 796 id: backDropArea 797 anchors.fill: parent 798 799 Item{ 800 anchors.fill: layoutsContainer 801 802 Background.MultiLayered{ 803 id: _background 804 } 805 } 806 807 Layouts.LayoutsContainer { 808 id: layoutsContainer 809 } 810 } 811 812 Colorizer.Manager { 813 id: colorizerManager 814 } 815 816 EditMode.ConfigOverlay{ 817 id: _dragOverlay 818 } 819 820 Item { 821 id: dndSpacer 822 823 width: root.isHorizontal ? length : thickness 824 height: root.isHorizontal ? thickness : length 825 826 property int length: opacity > 0 ? (dndSpacerAddItem.length + metrics.totals.lengthEdges + metrics.totals.lengthPaddings) : 0 827 828 readonly property bool isDndSpacer: true 829 readonly property int thickness: metrics.totals.thickness + metrics.margin.screenEdge 830 readonly property int maxLength: 96 831 832 Layout.minimumWidth: width 833 Layout.minimumHeight: height 834 Layout.preferredWidth: Layout.minimumWidth 835 Layout.preferredHeight: Layout.minimumHeight 836 Layout.maximumWidth: Layout.minimumWidth 837 Layout.maximumHeight: Layout.minimumHeight 838 opacity: 0 839 visible: parent === layoutsContainer.startLayout 840 || parent === layoutsContainer.mainLayout 841 || parent === layoutsContainer.endLayout 842 843 z:1500 844 845 Behavior on length { 846 NumberAnimation { 847 duration: animations.duration.large 848 easing.type: Easing.InQuad 849 } 850 } 851 852 Behavior on opacity { 853 NumberAnimation { 854 duration: animations.duration.large 855 easing.type: Easing.InQuad 856 } 857 } 858 859 Item { 860 id: dndSpacerAddItemContainer 861 width: root.isHorizontal ? parent.length : parent.thickness - metrics.margin.screenEdge 862 height: root.isHorizontal ? parent.thickness - metrics.margin.screenEdge : parent.length 863 864 property int thickMargin: metrics.margin.screenEdge //+ metrics.margin.thickness 865 866 LatteComponents.AddItem{ 867 id: dndSpacerAddItem 868 anchors.centerIn: parent 869 width: length 870 height: width 871 872 readonly property int length: Math.min(metrics.iconSize, 96) 873 } 874 875 states:[ 876 State{ 877 name: "bottom" 878 when: plasmoid.location === PlasmaCore.Types.BottomEdge 879 880 AnchorChanges{ 881 target: dndSpacerAddItemContainer; 882 anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; 883 anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.bottom; 884 } 885 PropertyChanges{ 886 target: dndSpacerAddItemContainer; 887 anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: dndSpacerAddItemContainer.thickMargin; 888 anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; 889 } 890 }, 891 State{ 892 name: "top" 893 when: plasmoid.location === PlasmaCore.Types.TopEdge 894 895 AnchorChanges{ 896 target: dndSpacerAddItemContainer; 897 anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; 898 anchors.right: undefined; anchors.left: undefined; anchors.top: parent.top; anchors.bottom: undefined; 899 } 900 PropertyChanges{ 901 target: dndSpacerAddItemContainer; 902 anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin: dndSpacerAddItemContainer.thickMargin; anchors.bottomMargin: 0; 903 anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; 904 } 905 }, 906 State{ 907 name: "left" 908 when: plasmoid.location === PlasmaCore.Types.LeftEdge 909 910 AnchorChanges{ 911 target: dndSpacerAddItemContainer; 912 anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; 913 anchors.right: undefined; anchors.left: parent.left; anchors.top: undefined; anchors.bottom: undefined; 914 } 915 PropertyChanges{ 916 target: dndSpacerAddItemContainer; 917 anchors.leftMargin: dndSpacerAddItemContainer.thickMargin; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: 0; 918 anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; 919 } 920 }, 921 State{ 922 name: "right" 923 when: plasmoid.location === PlasmaCore.Types.RightEdge 924 925 AnchorChanges{ 926 target: dndSpacerAddItemContainer; 927 anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; 928 anchors.right: parent.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined; 929 } 930 PropertyChanges{ 931 target: dndSpacerAddItemContainer; 932 anchors.leftMargin: 0; anchors.rightMargin: dndSpacerAddItemContainer.thickMargin; anchors.topMargin:0; anchors.bottomMargin: 0; 933 anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; 934 } 935 } 936 ] 937 } 938 } 939 940 Behavior on maxLengthPerCentage { 941 enabled: root.behaveAsDockWithMask && plasmoid.configuration.floatingGapHidingWaitsMouse && dockContainsMouse 942 NumberAnimation { 943 duration: animations.duration.short 944 easing.type: Easing.InQuad 945 } 946 } 947 948 ///////////////END UI elements 949 950 ///////////////BEGIN ABILITIES 951 952 Ability.Animations { 953 id: _animations 954 layouts: layoutsContainer 955 metrics: _metrics 956 settings: universalSettings 957 } 958 959 Ability.AutoSize { 960 id: _autosize 961 layouts: layoutsContainer 962 layouter: _layouter 963 metrics: _metrics 964 visibility: visibilityManager 965 } 966 967 Ability.Debug { 968 id: _debug 969 } 970 971 AbilityHost.Environment{ 972 id: _environment 973 } 974 975 Ability.Indexer { 976 id: _indexer 977 layouts: layoutsContainer 978 } 979 980 Ability.Indicators{ 981 id: _indicators 982 view: latteView 983 } 984 985 Ability.Launchers { 986 id: _launchers 987 layouts: layoutsContainer 988 layoutName: latteView && latteView.layout ? latteView.layout.name : "" 989 } 990 991 Ability.Layouter { 992 id: _layouter 993 animations: _animations 994 indexer: _indexer 995 layouts: layoutsContainer 996 } 997 998 Ability.Metrics { 999 id: _metrics 1000 animations: _animations 1001 autosize: _autosize 1002 background: _background 1003 indicators: _indicators 1004 parabolic: _parabolic 1005 } 1006 1007 Ability.MyView { 1008 id: _myView 1009 layouts: layoutsContainer 1010 } 1011 1012 Ability.ParabolicEffect { 1013 id: _parabolic 1014 animations: _animations 1015 debug: _debug 1016 layouts: layoutsContainer 1017 view: latteView 1018 } 1019 1020 Ability.PositionShortcuts { 1021 id: _shortcuts 1022 layouts: layoutsContainer 1023 } 1024 1025 Ability.ThinTooltip { 1026 id: _thinTooltip 1027 debug: _debug 1028 layouts: layoutsContainer 1029 view: latteView 1030 } 1031 1032 Ability.UserRequests { 1033 id: _userRequests 1034 view: latteView 1035 } 1036 1037 LatteApp.Interfaces { 1038 id: _interfaces 1039 plasmoidInterface: plasmoid 1040 1041 Component.onCompleted: { 1042 view.interfacesGraphicObj = _interfaces; 1043 } 1044 1045 onViewChanged: { 1046 if (view) { 1047 view.interfacesGraphicObj = _interfaces; 1048 1049 if (!root.inStartup) { 1050 //! used from recreating views 1051 root.inStartup = true; 1052 startupDelayer.start(); 1053 } 1054 } 1055 } 1056 } 1057 1058 ///////////////END ABILITIES 1059 1060 ///////////////BEGIN TIMER elements 1061 1062 //! It is used in order to slide-in the latteView on startup 1063 onInStartupChanged: { 1064 if (!inStartup) { 1065 latteView.positioner.startupFinished(); 1066 latteView.positioner.slideInDuringStartup(); 1067 visibilityManager.slotMustBeShown(); 1068 } 1069 } 1070 1071 Connections { 1072 target:fastLayoutManager 1073 onHasRestoredAppletsChanged: { 1074 if (fastLayoutManager.hasRestoredApplets) { 1075 startupDelayer.start(); 1076 } 1077 } 1078 } 1079 1080 Timer { 1081 //! Give a little more time to layouter and applets to load and be positioned properly during startup when 1082 //! the view is drawn out-of-screen and afterwards trigger the startup animation sequence: 1083 //! 1.slide-out when out-of-screen //slotMustBeHide() 1084 //! 2.be positioned properly at correct screen //slideInDuringStartup(), triggers Positioner::syncGeometry() 1085 //! 3.slide-in properly in correct screen //slotMustBeShown(); 1086 id: startupDelayer 1087 interval: 1000 1088 onTriggered: { 1089 visibilityManager.slotMustBeHide(); 1090 } 1091 } 1092 1093 ///////////////END TIMER elements 1094 1095 Loader{ 1096 anchors.fill: parent 1097 active: debug.localGeometryEnabled 1098 sourceComponent: Rectangle{ 1099 x: latteView.localGeometry.x 1100 y: latteView.localGeometry.y 1101 //! when view is resized there is a chance that geometry is faulty stacked in old values 1102 width: Math.min(latteView.localGeometry.width, root.width) //! fixes updating 1103 height: Math.min(latteView.localGeometry.height, root.height) //! fixes updating 1104 1105 color: "blue" 1106 border.width: 2 1107 border.color: "red" 1108 1109 opacity: 0.35 1110 } 1111 } 1112 1113 Loader{ 1114 anchors.fill: parent 1115 active: latteView && latteView.effects && debug.inputMaskEnabled 1116 sourceComponent: Rectangle{ 1117 x: latteView.effects.inputMask.x 1118 y: latteView.effects.inputMask.y 1119 //! when view is resized there is a chance that geometry is faulty stacked in old values 1120 width: Math.min(latteView.effects.inputMask.width, root.width) //! fixes updating 1121 height: Math.min(latteView.effects.inputMask.height, root.height) //! fixes updating 1122 1123 color: "purple" 1124 border.width: 1 1125 border.color: "black" 1126 1127 opacity: 0.20 1128 } 1129 } 1130} 1131