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 }