Warning, /plasma/latte-dock/containment/package/contents/ui/abilities/AutoSize.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 SPDX-FileCopyrightText: 2019 Michail Vourlakos <mvourlakos@gmail.com> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 import QtQuick 2.8 0007 0008 import org.kde.plasma.plasmoid 2.0 0009 import org.kde.plasma.core 2.0 as PlasmaCore 0010 0011 import org.kde.latte.core 0.2 as LatteCore 0012 0013 Item { 0014 id: sizer 0015 0016 // when there are only plasma style task managers OR any applets that fill width or height 0017 // the automatic icon size algorithm should better be disabled 0018 readonly property bool isActive: root.behaveAsDockWithMask 0019 && plasmoid.configuration.autoSizeEnabled 0020 && !root.containsOnlyPlasmaTasks 0021 && layouter.fillApplets<=0 0022 && !(root.inConfigureAppletsMode && plasmoid.configuration.alignment === LatteCore.Types.Justify) /*block shrinking for justify splitters*/ 0023 && latteView 0024 && latteView.visibility.mode !== LatteCore.Types.SidebarOnDemand 0025 && latteView.visibility.mode !== LatteCore.Types.SidebarAutoHide 0026 0027 property int iconSize: -1 //it is not set, this is the default 0028 0029 readonly property bool inCalculatedIconSize: ((metrics.iconSize === sizer.iconSize) || (metrics.iconSize === metrics.maxIconSize)) 0030 readonly property bool inAutoSizeAnimation: !inCalculatedIconSize 0031 0032 readonly property int automaticStep: 8 0033 readonly property int historyMaxSize: 10 0034 readonly property int historyMinSize: 4 0035 0036 0037 //! Prediction History of the algorithm in order to track cases where the algorithm produces 0038 //! grows and shrinks endlessly 0039 property variant history: [] 0040 0041 //! required elements 0042 property Item layouts 0043 property Item layouter 0044 property Item metrics 0045 property Item visibility 0046 0047 onInAutoSizeAnimationChanged: { 0048 if (inAutoSizeAnimation) { 0049 animations.needBothAxis.addEvent(sizer); 0050 } else { 0051 animations.needBothAxis.removeEvent(sizer); 0052 } 0053 } 0054 0055 onIsActiveChanged: { 0056 clearHistory(); 0057 updateIconSize(); 0058 } 0059 0060 Connections { 0061 target: root 0062 onContainsOnlyPlasmaTasksChanged: sizer.updateIconSize(); 0063 onMaxLengthChanged: { 0064 if (latteView && latteView.positioner && !latteView.positioner.isOffScreen) { 0065 sizer.updateIconSize(); 0066 } 0067 } 0068 } 0069 0070 Connections { 0071 target: metrics 0072 0073 onPortionIconSizeChanged: { 0074 if (metrics.portionIconSize!==-1) { 0075 sizer.updateIconSize(); 0076 } 0077 } 0078 } 0079 0080 Connections { 0081 target: latteView 0082 onWidthChanged:{ 0083 if (root.isHorizontal && metrics.portionIconSize!==-1) { 0084 sizer.updateIconSize(); 0085 } 0086 } 0087 0088 onHeightChanged:{ 0089 if (root.isVertical && metrics.portionIconSize!==-1) { 0090 sizer.updateIconSize(); 0091 } 0092 } 0093 } 0094 0095 Connections { 0096 target: latteView && latteView.positioner ? latteView.positioner : null 0097 onIsOffScreenChanged: { 0098 if (!latteView.positioner.isOffScreen) { 0099 sizer.updateIconSize(); 0100 } 0101 } 0102 } 0103 0104 Connections { 0105 target: visibilityManager 0106 onInNormalStateChanged: { 0107 if (visibilityManager.inNormalState) { 0108 sizer.updateIconSize(); 0109 } 0110 } 0111 } 0112 0113 //! Prediction History Functions 0114 function clearHistory() { 0115 history.length = 0; 0116 } 0117 0118 function addPrediction(currentLength, prediction) { 0119 history.unshift({current: currentLength, predicted: prediction}); 0120 0121 /* console.log(" -- PREDICTION ARRAY -- "); 0122 for(var i=0; i<history.length; ++i) { 0123 console.log( i + ". " + history[i].current + " : " + history[i].predicted); 0124 }*/ 0125 0126 if (history.length > historyMaxSize) { 0127 history.splice(historyMinSize, history.length - historyMinSize); 0128 } 0129 } 0130 0131 function producesEndlessLoop(currentLength, prediction) { 0132 if (history.length < 2) { 0133 return false; 0134 } 0135 0136 if (history[1].current === currentLength 0137 && history[1].predicted === prediction) { 0138 //! the current prediction is the same like two steps before in prediction history 0139 0140 if(history[0].current > history[0].predicted && history[1].current < history[1].predicted) { 0141 //! case2: the algorithm that is trying to SHRINK has already produced same results subsequently 0142 console.log(" AUTOMATIC ITEM SIZE PROTECTOR, :: ENDLESS AUTOMATIC SIZE LOOP DETECTED"); 0143 return true; 0144 } 0145 } 0146 0147 return false; 0148 } 0149 0150 0151 function updateIconSize() { 0152 if (!isActive && iconSize !== -1) { 0153 // restore original icon size 0154 iconSize = -1; 0155 } 0156 0157 if ( !doubleCallAutomaticUpdateIconSize.running && !visibility.inRelocationHiding /*block too many calls and dont apply during relocatinon hiding*/ 0158 && (visibility.inNormalState && sizer.isActive) /*in normal and auto size active state*/ 0159 && (metrics.iconSize===metrics.maxIconSize || metrics.iconSize === sizer.iconSize) /*not during animations*/) { 0160 0161 //!doubler timer 0162 if (!doubleCallAutomaticUpdateIconSize.secondTimeCallApplied) { 0163 doubleCallAutomaticUpdateIconSize.start(); 0164 } else { 0165 doubleCallAutomaticUpdateIconSize.secondTimeCallApplied = false; 0166 } 0167 0168 var layoutLength; 0169 var maxLength = root.maxLength; 0170 0171 //console.log("------Entered check-----"); 0172 //console.log("max length: "+ maxLength); 0173 0174 layoutLength = (plasmoid.configuration.alignment === LatteCore.Types.Justify) ? 0175 layouts.startLayout.length+layouts.mainLayout.length+layouts.endLayout.length : layouts.mainLayout.length 0176 0177 0178 var itemLength = metrics.totals.length; 0179 0180 var toShrinkLimit = maxLength - (parabolic.factor.zoom * itemLength); 0181 //! to grow limit must be a little less than the shrink one in order to be more robust and 0182 //! not create endless loops from early calculations 0183 var toGrowLimit = maxLength - (1.2 * parabolic.factor.zoom * itemLength); 0184 0185 //console.log("toShrinkLimit: "+ toShrinkLimit); 0186 //console.log("toGrowLimit: "+ toGrowLimit); 0187 0188 var newIconSizeFound = false; 0189 if (layoutLength > toShrinkLimit) { //must shrink 0190 // console.log("step3"); 0191 var nextIconSize = metrics.maxIconSize; 0192 0193 do { 0194 nextIconSize = nextIconSize - automaticStep; 0195 var factor = nextIconSize / metrics.iconSize; 0196 var nextLength = factor * layoutLength; 0197 0198 } while ( (nextLength>toShrinkLimit) && (nextIconSize !== 16)); 0199 0200 var intLength = Math.round(layoutLength); 0201 var intNextLength = Math.round(nextLength); 0202 0203 iconSize = nextIconSize; 0204 newIconSizeFound = true; 0205 0206 addPrediction(intLength, intNextLength); 0207 // console.log("Step 3 - found:"+iconSize); 0208 } else if ((layoutLength<toGrowLimit 0209 && (metrics.iconSize === iconSize)) ) { //must grow probably 0210 // console.log("step4"); 0211 var nextIconSize2 = iconSize; 0212 var foundGoodSize = -1; 0213 0214 do { 0215 nextIconSize2 = nextIconSize2 + automaticStep; 0216 var factor2 = nextIconSize2 / iconSize; 0217 var nextLength2 = factor2 * layoutLength; 0218 0219 if (nextLength2 < toGrowLimit) { 0220 foundGoodSize = nextIconSize2; 0221 } 0222 } while ( (nextLength2<toGrowLimit) && (nextIconSize2 !== metrics.maxIconSize )); 0223 0224 var intLength2 = Math.round(layoutLength); 0225 var intNextLength2 = Math.round(nextLength2); 0226 0227 if (foundGoodSize > 0 && !producesEndlessLoop(intLength2, intNextLength2)) { 0228 if (foundGoodSize === metrics.maxIconSize) { 0229 iconSize = -1; 0230 } else { 0231 iconSize = foundGoodSize; 0232 } 0233 newIconSizeFound = true 0234 0235 addPrediction(intLength2, intNextLength2); 0236 // console.log("Step 4 - found:"+iconSize); 0237 } else { 0238 // console.log("Step 4 - did not found..."); 0239 } 0240 } 0241 } 0242 } 0243 0244 //! This functions makes sure to call the updateIconSize(); function which is costly 0245 //! one more time after its last call to confirm the applied icon size found 0246 Timer{ 0247 id:doubleCallAutomaticUpdateIconSize 0248 interval: 1000 0249 property bool secondTimeCallApplied: false 0250 0251 onTriggered: { 0252 if (!secondTimeCallApplied) { 0253 secondTimeCallApplied = true; 0254 sizer.updateIconSize(); 0255 } 0256 } 0257 } 0258 }