You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
latte-dock/plasmoid/package/contents/ui/TasksExtendedManager.qml

405 lines
12 KiB
QML

/*
SPDX-FileCopyrightText: 2019 Michail Vourlakos <mvourlakos@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.0
import org.kde.plasma.plasmoid 2.0
//! Trying to WORKAROUND all the Plasma LibTaskManager limitations
//! concerning Tasks AND Launchers.
//!
//! Plasma LibTaskManager constantly creates ADDITIONS/REMOVALS when
//! a Task is changing its type from Launcher<->Startup<->Window.
//! This libtaskmanager behavior limits a lot the animations that
//! can be created in order to provide a moder user experience
//!
//! All the logic that is trying to improve the mentioned limits is provided
//! from this class
Item {
id: tasksExtManager
/// Launchers that are playing an ADD or REMOVAL animation
/// and their Starups/Windows should be aware of
property variant waitingLaunchers: []
//! Launchers that must be shown IMMEDIATELY after a window removal
//! because they are already present from a present libtaskmanager state
property variant immediateLaunchers: []
//! New launchers in order to be moved in correct place:
//! launcher, pos)
property variant launchersToBeMoved: []
//! Launchers that are added from user actions. They can be used in order
//! to provide addition animations properly
property variant launchersToBeAdded: []
//! Launchers that are added from user actions. They can be used in order
//! to provide removal animations properly
property variant launchersToBeRemoved: []
//! Tasks that change state (launcher,startup,window) and
//! at the next state must look the same concerning the parabolic effect:
//! (id, zoom)
property variant frozenTasks: []
readonly property int launchersInPausedStateCount: launchersToBeMovedCount + launchersToBeAddedCount + launchersToBeRemovedCount
property int launchersToBeMovedCount: 0 //is used to update instantly relevant bindings
property int launchersToBeAddedCount: 0 //is used to update instantly relevant bindings
property int launchersToBeRemovedCount: 0 //is used to update instantly relevant bindings
signal waitingLauncherRemoved(string launch);
/////////// FUNCTIONALITY ////////////////////
/// WAITING LAUNCHERS
function addWaitingLauncher(launch){
arraysGarbageCollectorTimer.restart();
if (waitingLauncherExists(launch)) {
return;
}
waitingLaunchers.push(launch);
}
function removeWaitingLauncher(launch){
for(var i=0; i<waitingLaunchers.length; ++i){
if (equals(waitingLaunchers[i], launch)) {
waitingLaunchers.splice(i,1);
waitingLauncherRemoved(launch);
return;
}
}
}
function waitingLauncherExists(launch){
for(var i=0; i<waitingLaunchers.length; ++i){
if (equals(waitingLaunchers[i], launch)) {
return true;
}
}
return false;
}
function equals(waitingLauncher, launcher) {
var equals = ( launcher !== ""
&& waitingLauncher !== ""
&& (launcher.indexOf(waitingLauncher) >= 0 || waitingLauncher.indexOf(launcher) >= 0));
return equals;
}
function waitingLaunchersLength() {
return waitingLaunchers.length;
}
function printWaitingLaunchers() {
console.log("WAITING LAUNCHERS ::: " + waitingLaunchers);
}
//! LAUNCHERSTOBEADDED
function addToBeAddedLauncher(launcher){
arraysGarbageCollectorTimer.restart();
if (toBeAddedLauncherExists(launcher)) {
return;
}
launchersToBeAdded.push(launcher);
launchersToBeAddedCount++;
}
function removeToBeAddedLauncher(launcher){
for(var i=0; i<launchersToBeAdded.length; ++i){
if (equals(launchersToBeAdded[i], launcher)) {
launchersToBeAdded.splice(i,1);
launchersToBeAddedCount--;
return;
}
}
}
function toBeAddedLauncherExists(launcher) {
for(var i=0; i<launchersToBeAdded.length; ++i){
if (equals(launchersToBeAdded[i], launcher)) {
return true;
}
}
return false;
}
function printToBeAddedLaunchers() {
console.log("TO BE ADDED LAUNCHERS ::: " + launchersToBeAdded);
}
//! LAUNCHERSTOBEREMOVED
function addToBeRemovedLauncher(launcher){
arraysGarbageCollectorTimer.restart();
if (isLauncherToBeRemoved(launcher)) {
return;
}
launchersToBeRemoved.push(launcher);
launchersToBeRemovedCount++;
}
function removeToBeRemovedLauncher(launcher){
if (!isLauncherToBeRemoved(launcher)) {
return;
}
for(var i=0; i<launchersToBeRemoved.length; ++i){
if (launchersToBeRemoved[i] === launcher) {
launchersToBeRemoved.splice(i,1);
launchersToBeRemovedCount--;
return;
}
}
}
function isLauncherToBeRemoved(launcher) {
return launchersToBeRemoved.indexOf(launcher)>=0;
}
function printToBeRemovedLaunchers() {
console.log("TO BE REMOVED LAUNCHERS ::: " + launchersToBeRemoved);
}
//! IMMEDIATELAUNCHERS
function addImmediateLauncher(launch){
arraysGarbageCollectorTimer.restart();
if (!immediateLauncherExists(launch)) {
//console.log("Immediate Launcher Added::: "+launch);
immediateLaunchers.push(launch);
}
}
function removeImmediateLauncher(launch){
for(var i=0; i<immediateLaunchers.length; ++i){
if (immediateLaunchers[i]===launch) {
immediateLaunchers.splice(i,1);
//console.log("Immediate Launcher Removed::: "+launch);
return;
}
}
}
function immediateLauncherExists(launch){
for(var i=0; i<immediateLaunchers.length; ++i){
if (immediateLaunchers[i]===launch) {
return true;
}
}
return false;
}
function printImmediateLaunchers() {
console.log("IMMEDIATE LAUNCHERS ::: " + immediateLaunchers);
}
//!
//! FROZENTASKS
function getFrozenTask(identifier) {
for(var i=0; i<frozenTasks.length; ++i) {
if (frozenTasks[i].id === identifier) {
return frozenTasks[i];
}
}
}
function removeFrozenTask(identifier) {
var taskIndex = -1;
for(var i=0; i<frozenTasks.length; ++i) {
if (frozenTasks[i].id === identifier) {
taskIndex = i;
}
}
if (taskIndex > -1) {
frozenTasks.splice(taskIndex, 1);
}
}
function setFrozenTask(identifier, scale) {
arraysGarbageCollectorTimer.restart();
var frozenTaskExists = false;
//console.log("SET FROZEN :: "+identifier+" - "+scale);
var frozenTask = getFrozenTask(identifier);
if (frozenTask) {
frozenTask.zoom = scale;
} else {
frozenTasks.push({id: identifier, zoom: scale});
}
}
function printFrozenTasks() {
var fzTasks= "";
for(var i=0; i<frozenTasks.length; ++i) {
fzTasks = frozenTasks[i].id + "," + frozenTasks[i].zoom + "__";
}
console.log("FROZEN TASKS ::: " + fzTasks);
}
//! LAUNCHERSTOBEMOVED
//! launchersToBeMoved, new launchers to have been added and must be repositioned
function addLauncherToBeMoved(launcherUrl, toPos) {
arraysGarbageCollectorTimer.restart();
if (!isLauncherToBeMoved(launcherUrl)) {
launchersToBeMoved.push({launcher: launcherUrl, pos: Math.max(0,toPos)});
launchersToBeMovedCount++;
}
}
function moveLauncherToCorrectPos(launcherUrl, from) {
if (isLauncherToBeMoved(launcherUrl)) {
launchersToBeMovedTimer.from = from;
launchersToBeMovedTimer.to = posOfLauncherToBeMoved(launcherUrl);
launchersToBeMovedTimer.launcherUrl = launcherUrl
removeLauncherToBeMoved(launcherUrl);
launchersToBeMovedTimer.start();
}
}
function removeLauncherToBeMoved(launcherUrl) {
if (isLauncherToBeMoved(launcherUrl)) {
var sLength = launchersToBeMoved.length;
var index = -1;
for (var i=0; i<sLength; ++i) {
//!safety checker
if (i>=launchersToBeMoved.length)
return -1;
if (launchersToBeMoved[i].launcher === launcherUrl) {
index = i;
break;
}
}
if (index > -1) {
// console.log("removing launcher to be moved:: "+launcherUrl);
launchersToBeMoved.splice(index, 1);
}
}
}
function posOfLauncherToBeMoved(launcherUrl) {
var sLength = launchersToBeMoved.length;
for (var i=0; i<sLength; ++i) {
//!safety checker
if (i>=launchersToBeMoved.length)
return -1;
if (launchersToBeMoved[i].launcher === launcherUrl)
return launchersToBeMoved[i].pos;
}
return -1;
}
function isLauncherToBeMoved(launcher) {
return (posOfLauncherToBeMoved(launcher) >= 0);
}
function printToBeMovedLaunchers() {
var tbmLaunchers= "";
for(var i=0; i<launchersToBeMoved.length; ++i) {
tbmLaunchers = launchersToBeMoved[i].launcher + "," + launchersToBeMoved[i].pos + "__";
}
console.log("TO BE MOVED LAUNCHERS ::: " + tbmLaunchers);
}
//! Connections
Connections {
target: appletAbilities.launchers
onLauncherInRemoving: tasksExtManager.addToBeRemovedLauncher(launcherUrl);
onLauncherInAdding: tasksExtManager.addToBeAddedLauncher(launcherUrl);
onLauncherInMoving: tasksExtManager.addLauncherToBeMoved(launcherUrl, pos);
}
//!Trying to avoid a binding loop in TaskItem for modelLauncherUrl
Timer {
id: launchersToBeMovedTimer
interval: 50
property int from: -1
property int to: -1
property string launcherUrl: ""
onTriggered: {
tasksModel.move(from, to);
delayedLaynchersSyncTimer.start();
}
}
//! delay a bit the launchers syncing in order to avoid a crash
//! the crash was caused from TasksExtendedManager when adding and moving a launcher (e.g. internal separator)
//! and there were more than one synced docks
Timer {
id: delayedLaynchersSyncTimer
interval: 450
onTriggered: {
tasksModel.syncLaunchers();
appletAbilities.launchers.validateSyncedLaunchersOrder();
//! In case there are multiple launchers in moving state
launchersToBeMovedCount = 0;
}
}
//! Timer to clean up all arrays used from TasksExtendedManager after a specified interval
//! The arrays may have ghost records that were not used from animations or other plasmoid parts.
//! Each record of the arrays is usually only a matter of secs to be used, cleaning them after
//! a big interval from the last addition it is safe
Timer {
id: arraysGarbageCollectorTimer
interval: 30 * 1000
onTriggered: {
console.log(" TASKS EXTENDED MANAGER Garbage Collector...");
tasksExtManager.printImmediateLaunchers();
tasksExtManager.printToBeAddedLaunchers();
tasksExtManager.printToBeMovedLaunchers();
tasksExtManager.printToBeRemovedLaunchers();
tasksExtManager.printWaitingLaunchers();
tasksExtManager.printFrozenTasks();
immediateLaunchers.splice(0, immediateLaunchers.length);
launchersToBeAdded.splice(0, launchersToBeAdded.length);
launchersToBeMoved.splice(0, launchersToBeMoved.length);
launchersToBeRemoved.splice(0, launchersToBeRemoved.length);
waitingLaunchers.splice(0, waitingLaunchers.length);
frozenTasks.splice(0, frozenTasks.length);
//! clear up launchers counters
tasksExtManager.launchersToBeMovedCount = 0;
tasksExtManager.launchersToBeAddedCount = 0;
tasksExtManager.launchersToBeRemovedCount = 0;
}
}
}