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 }