Warning, /plasma/latte-dock/plasmoid/package/contents/ui/TasksExtendedManager.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.0 0007 0008 import org.kde.plasma.plasmoid 2.0 0009 0010 //! Trying to WORKAROUND all the Plasma LibTaskManager limitations 0011 //! concerning Tasks AND Launchers. 0012 //! 0013 //! Plasma LibTaskManager constantly creates ADDITIONS/REMOVALS when 0014 //! a Task is changing its type from Launcher<->Startup<->Window. 0015 //! This libtaskmanager behavior limits a lot the animations that 0016 //! can be created in order to provide a moder user experience 0017 //! 0018 //! All the logic that is trying to improve the mentioned limits is provided 0019 //! from this class 0020 0021 Item { 0022 id: tasksExtManager 0023 0024 /// Launchers that are playing an ADD or REMOVAL animation 0025 /// and their Starups/Windows should be aware of 0026 property variant waitingLaunchers: [] 0027 0028 //! Launchers that must be shown IMMEDIATELY after a window removal 0029 //! because they are already present from a present libtaskmanager state 0030 property variant immediateLaunchers: [] 0031 0032 //! New launchers in order to be moved in correct place: 0033 //! launcher, pos) 0034 property variant launchersToBeMoved: [] 0035 0036 //! Launchers that are added from user actions. They can be used in order 0037 //! to provide addition animations properly 0038 property variant launchersToBeAdded: [] 0039 0040 //! Launchers that are added from user actions. They can be used in order 0041 //! to provide removal animations properly 0042 property variant launchersToBeRemoved: [] 0043 0044 //! Tasks that change state (launcher,startup,window) and 0045 //! at the next state must look the same concerning the parabolic effect: 0046 //! (id, zoom) 0047 property variant frozenTasks: [] 0048 0049 readonly property int launchersInPausedStateCount: launchersToBeMovedCount + launchersToBeAddedCount + launchersToBeRemovedCount 0050 0051 property int launchersToBeMovedCount: 0 //is used to update instantly relevant bindings 0052 property int launchersToBeAddedCount: 0 //is used to update instantly relevant bindings 0053 property int launchersToBeRemovedCount: 0 //is used to update instantly relevant bindings 0054 0055 signal waitingLauncherRemoved(string launch); 0056 0057 0058 /////////// FUNCTIONALITY //////////////////// 0059 0060 0061 /// WAITING LAUNCHERS 0062 function addWaitingLauncher(launch){ 0063 arraysGarbageCollectorTimer.restart(); 0064 0065 if (waitingLauncherExists(launch)) { 0066 return; 0067 } 0068 0069 waitingLaunchers.push(launch); 0070 } 0071 0072 function removeWaitingLauncher(launch){ 0073 for(var i=0; i<waitingLaunchers.length; ++i){ 0074 if (equals(waitingLaunchers[i], launch)) { 0075 waitingLaunchers.splice(i,1); 0076 waitingLauncherRemoved(launch); 0077 return; 0078 } 0079 } 0080 } 0081 0082 function waitingLauncherExists(launch){ 0083 for(var i=0; i<waitingLaunchers.length; ++i){ 0084 if (equals(waitingLaunchers[i], launch)) { 0085 return true; 0086 } 0087 } 0088 0089 return false; 0090 } 0091 0092 function equals(waitingLauncher, launcher) { 0093 var equals = ( launcher !== "" 0094 && waitingLauncher !== "" 0095 && (launcher.indexOf(waitingLauncher) >= 0 || waitingLauncher.indexOf(launcher) >= 0)); 0096 0097 return equals; 0098 } 0099 0100 function waitingLaunchersLength() { 0101 return waitingLaunchers.length; 0102 } 0103 0104 function printWaitingLaunchers() { 0105 console.log("WAITING LAUNCHERS ::: " + waitingLaunchers); 0106 } 0107 0108 //! LAUNCHERSTOBEADDED 0109 function addToBeAddedLauncher(launcher){ 0110 arraysGarbageCollectorTimer.restart(); 0111 0112 if (toBeAddedLauncherExists(launcher)) { 0113 return; 0114 } 0115 0116 launchersToBeAdded.push(launcher); 0117 launchersToBeAddedCount++; 0118 } 0119 0120 function removeToBeAddedLauncher(launcher){ 0121 for(var i=0; i<launchersToBeAdded.length; ++i){ 0122 if (equals(launchersToBeAdded[i], launcher)) { 0123 launchersToBeAdded.splice(i,1); 0124 launchersToBeAddedCount--; 0125 return; 0126 } 0127 } 0128 } 0129 0130 function toBeAddedLauncherExists(launcher) { 0131 for(var i=0; i<launchersToBeAdded.length; ++i){ 0132 if (equals(launchersToBeAdded[i], launcher)) { 0133 return true; 0134 } 0135 } 0136 0137 return false; 0138 } 0139 0140 0141 function printToBeAddedLaunchers() { 0142 console.log("TO BE ADDED LAUNCHERS ::: " + launchersToBeAdded); 0143 } 0144 0145 //! LAUNCHERSTOBEREMOVED 0146 function addToBeRemovedLauncher(launcher){ 0147 arraysGarbageCollectorTimer.restart(); 0148 0149 if (isLauncherToBeRemoved(launcher)) { 0150 return; 0151 } 0152 0153 launchersToBeRemoved.push(launcher); 0154 launchersToBeRemovedCount++; 0155 } 0156 0157 function removeToBeRemovedLauncher(launcher){ 0158 if (!isLauncherToBeRemoved(launcher)) { 0159 return; 0160 } 0161 0162 for(var i=0; i<launchersToBeRemoved.length; ++i){ 0163 if (launchersToBeRemoved[i] === launcher) { 0164 launchersToBeRemoved.splice(i,1); 0165 launchersToBeRemovedCount--; 0166 return; 0167 } 0168 } 0169 } 0170 0171 function isLauncherToBeRemoved(launcher) { 0172 return launchersToBeRemoved.indexOf(launcher)>=0; 0173 } 0174 0175 0176 function printToBeRemovedLaunchers() { 0177 console.log("TO BE REMOVED LAUNCHERS ::: " + launchersToBeRemoved); 0178 } 0179 0180 //! IMMEDIATELAUNCHERS 0181 function addImmediateLauncher(launch){ 0182 arraysGarbageCollectorTimer.restart(); 0183 0184 if (!immediateLauncherExists(launch)) { 0185 //console.log("Immediate Launcher Added::: "+launch); 0186 immediateLaunchers.push(launch); 0187 } 0188 } 0189 0190 function removeImmediateLauncher(launch){ 0191 for(var i=0; i<immediateLaunchers.length; ++i){ 0192 if (immediateLaunchers[i]===launch) { 0193 immediateLaunchers.splice(i,1); 0194 //console.log("Immediate Launcher Removed::: "+launch); 0195 return; 0196 } 0197 } 0198 } 0199 0200 function immediateLauncherExists(launch){ 0201 for(var i=0; i<immediateLaunchers.length; ++i){ 0202 if (immediateLaunchers[i]===launch) { 0203 return true; 0204 } 0205 } 0206 0207 return false; 0208 } 0209 0210 function printImmediateLaunchers() { 0211 console.log("IMMEDIATE LAUNCHERS ::: " + immediateLaunchers); 0212 } 0213 //! 0214 0215 //! FROZENTASKS 0216 function getFrozenTask(identifier) { 0217 for(var i=0; i<frozenTasks.length; ++i) { 0218 if (frozenTasks[i].id === identifier) { 0219 return frozenTasks[i]; 0220 } 0221 } 0222 } 0223 0224 function removeFrozenTask(identifier) { 0225 var taskIndex = -1; 0226 for(var i=0; i<frozenTasks.length; ++i) { 0227 if (frozenTasks[i].id === identifier) { 0228 taskIndex = i; 0229 } 0230 } 0231 0232 if (taskIndex > -1) { 0233 frozenTasks.splice(taskIndex, 1); 0234 } 0235 } 0236 0237 function setFrozenTask(identifier, scale) { 0238 arraysGarbageCollectorTimer.restart(); 0239 0240 var frozenTaskExists = false; 0241 //console.log("SET FROZEN :: "+identifier+" - "+scale); 0242 var frozenTask = getFrozenTask(identifier); 0243 0244 if (frozenTask) { 0245 frozenTask.zoom = scale; 0246 } else { 0247 frozenTasks.push({id: identifier, zoom: scale}); 0248 } 0249 } 0250 0251 function printFrozenTasks() { 0252 var fzTasks= ""; 0253 0254 for(var i=0; i<frozenTasks.length; ++i) { 0255 fzTasks = frozenTasks[i].id + "," + frozenTasks[i].zoom + "__"; 0256 } 0257 0258 console.log("FROZEN TASKS ::: " + fzTasks); 0259 } 0260 0261 //! LAUNCHERSTOBEMOVED 0262 0263 //! launchersToBeMoved, new launchers to have been added and must be repositioned 0264 function addLauncherToBeMoved(launcherUrl, toPos) { 0265 arraysGarbageCollectorTimer.restart(); 0266 0267 if (!isLauncherToBeMoved(launcherUrl)) { 0268 launchersToBeMoved.push({launcher: launcherUrl, pos: Math.max(0,toPos)}); 0269 launchersToBeMovedCount++; 0270 } 0271 } 0272 0273 function moveLauncherToCorrectPos(launcherUrl, from) { 0274 if (isLauncherToBeMoved(launcherUrl)) { 0275 launchersToBeMovedTimer.from = from; 0276 launchersToBeMovedTimer.to = posOfLauncherToBeMoved(launcherUrl); 0277 launchersToBeMovedTimer.launcherUrl = launcherUrl 0278 0279 removeLauncherToBeMoved(launcherUrl); 0280 launchersToBeMovedTimer.start(); 0281 } 0282 } 0283 0284 function removeLauncherToBeMoved(launcherUrl) { 0285 if (isLauncherToBeMoved(launcherUrl)) { 0286 var sLength = launchersToBeMoved.length; 0287 var index = -1; 0288 0289 for (var i=0; i<sLength; ++i) { 0290 //!safety checker 0291 if (i>=launchersToBeMoved.length) 0292 return -1; 0293 0294 if (launchersToBeMoved[i].launcher === launcherUrl) { 0295 index = i; 0296 break; 0297 } 0298 } 0299 0300 if (index > -1) { 0301 // console.log("removing launcher to be moved:: "+launcherUrl); 0302 launchersToBeMoved.splice(index, 1); 0303 } 0304 } 0305 } 0306 0307 function posOfLauncherToBeMoved(launcherUrl) { 0308 var sLength = launchersToBeMoved.length; 0309 0310 for (var i=0; i<sLength; ++i) { 0311 //!safety checker 0312 if (i>=launchersToBeMoved.length) 0313 return -1; 0314 0315 if (launchersToBeMoved[i].launcher === launcherUrl) 0316 return launchersToBeMoved[i].pos; 0317 } 0318 0319 return -1; 0320 } 0321 0322 function isLauncherToBeMoved(launcher) { 0323 return (posOfLauncherToBeMoved(launcher) >= 0); 0324 } 0325 0326 function printToBeMovedLaunchers() { 0327 var tbmLaunchers= ""; 0328 0329 for(var i=0; i<launchersToBeMoved.length; ++i) { 0330 tbmLaunchers = launchersToBeMoved[i].launcher + "," + launchersToBeMoved[i].pos + "__"; 0331 } 0332 0333 console.log("TO BE MOVED LAUNCHERS ::: " + tbmLaunchers); 0334 } 0335 0336 //! Connections 0337 Connections { 0338 target: appletAbilities.launchers 0339 onLauncherInRemoving: tasksExtManager.addToBeRemovedLauncher(launcherUrl); 0340 onLauncherInAdding: tasksExtManager.addToBeAddedLauncher(launcherUrl); 0341 onLauncherInMoving: tasksExtManager.addLauncherToBeMoved(launcherUrl, pos); 0342 } 0343 0344 0345 //!Trying to avoid a binding loop in TaskItem for modelLauncherUrl 0346 Timer { 0347 id: launchersToBeMovedTimer 0348 interval: 50 0349 property int from: -1 0350 property int to: -1 0351 0352 property string launcherUrl: "" 0353 0354 onTriggered: { 0355 tasksModel.move(from, to); 0356 delayedLaynchersSyncTimer.start(); 0357 } 0358 } 0359 0360 //! delay a bit the launchers syncing in order to avoid a crash 0361 //! the crash was caused from TasksExtendedManager when adding and moving a launcher (e.g. internal separator) 0362 //! and there were more than one synced docks 0363 Timer { 0364 id: delayedLaynchersSyncTimer 0365 interval: 450 0366 onTriggered: { 0367 tasksModel.syncLaunchers(); 0368 appletAbilities.launchers.validateSyncedLaunchersOrder(); 0369 //! In case there are multiple launchers in moving state 0370 launchersToBeMovedCount = 0; 0371 } 0372 } 0373 0374 0375 //! Timer to clean up all arrays used from TasksExtendedManager after a specified interval 0376 //! The arrays may have ghost records that were not used from animations or other plasmoid parts. 0377 //! Each record of the arrays is usually only a matter of secs to be used, cleaning them after 0378 //! a big interval from the last addition it is safe 0379 Timer { 0380 id: arraysGarbageCollectorTimer 0381 interval: 30 * 1000 0382 onTriggered: { 0383 console.log(" TASKS EXTENDED MANAGER Garbage Collector..."); 0384 tasksExtManager.printImmediateLaunchers(); 0385 tasksExtManager.printToBeAddedLaunchers(); 0386 tasksExtManager.printToBeMovedLaunchers(); 0387 tasksExtManager.printToBeRemovedLaunchers(); 0388 tasksExtManager.printWaitingLaunchers(); 0389 tasksExtManager.printFrozenTasks(); 0390 0391 immediateLaunchers.splice(0, immediateLaunchers.length); 0392 launchersToBeAdded.splice(0, launchersToBeAdded.length); 0393 launchersToBeMoved.splice(0, launchersToBeMoved.length); 0394 launchersToBeRemoved.splice(0, launchersToBeRemoved.length); 0395 waitingLaunchers.splice(0, waitingLaunchers.length); 0396 frozenTasks.splice(0, frozenTasks.length); 0397 0398 //! clear up launchers counters 0399 tasksExtManager.launchersToBeMovedCount = 0; 0400 tasksExtManager.launchersToBeAddedCount = 0; 0401 tasksExtManager.launchersToBeRemovedCount = 0; 0402 } 0403 } 0404 }