/*SPDX-FileCopyrightText: 2012-2016 Eike Hein <hein@kde.org>SPDX-License-Identifier: GPL-2.0-or-later*/import QtQuickimport org.kde.taskmanager as TaskManagerimport org.kde.plasma.plasmoidimport plasma.applet.org.kde.plasma.taskmanager as TaskManagerAppletDropArea {id: dropAreasignal urlsDropped(var urls)property Item targetproperty Item ignoredItemproperty Item hoveredItemproperty bool isGroupDialog: falseproperty bool moved: falseproperty alias handleWheelEvents: wheelHandler.handleWheelEvents//ignore anything that is neither internal to TaskManager or a URL listonEntered: event => {if (event.formats.indexOf("text/x-plasmoidservicename") >= 0) {event.accepted = false;}if (target.animating) { // Not all targets have an animating propertytarget.animating = false;}}onPositionChanged: event => {if (target.animating) {return;}// RtL horizontal TaskLists do not include the spacer (which are initial in this// configuration), if any, but the mouse event coordinates do. We need to subtract// them, or we end thinking we're dragging way right of where we actually are.const rtlSpacerAdjustment = target.LayoutMirroring.enabled ? tasks.width - target.width : 0;let above;if (isGroupDialog) {above = target.itemAt(event.x - rtlSpacerAdjustment, event.y);} else {above = target.childAt(event.x - rtlSpacerAdjustment, event.y);}if (!above) {hoveredItem = null;activationTimer.stop();return;}// If we're mixing launcher tasks with other tasks and are moving// a (small) launcher task across a non-launcher task, don't allow// the latter to be the move target twice in a row for a while, as// it will naturally be moved underneath the cursor as result of the// initial move, due to being far larger than the launcher delegate.// TODO: This restriction (minus the timer, which improves things)// has been proven out in the EITM fork, but could be improved later// by tracking the cursor movement vector and allowing the drag if// the movement direction has reversed, establishing user intent to// move back.if (!Plasmoid.configuration.separateLaunchers&& tasks.dragSource?.model.IsLauncher&& !above.model.IsLauncher&& above === ignoredItem) {return;} else {ignoredItem = null;}if (tasksModel.sortMode === TaskManager.TasksModel.SortManual && tasks.dragSource) {// Reject drags between different TaskList instances.if (tasks.dragSource.parent !== above.parent) {return;}const insertAt = above.index;if (tasks.dragSource !== above && tasks.dragSource.index !== insertAt) {if (tasks.groupDialog) {tasksModel.move(tasks.dragSource.index, insertAt,tasksModel.makeModelIndex(tasks.groupDialog.visualParent.index));} else {tasksModel.move(tasks.dragSource.index, insertAt);}ignoredItem = above;ignoreItemTimer.restart();}} else if (!tasks.dragSource && hoveredItem !== above) {hoveredItem = above;activationTimer.restart();}}onExited: {hoveredItem = null;activationTimer.stop();}onDropped: event => {// Reject internal drops.if (event.formats.indexOf("application/x-orgkdeplasmataskmanager_taskbuttonitem") >= 0) {event.accepted = false;return;}// Reject plasmoid drops.if (event.formats.indexOf("text/x-plasmoidservicename") >= 0) {event.accepted = false;return;}if (event.hasUrls) {urlsDropped(event.urls);return;}}Connections {target: tasksfunction onDragSourceChanged(): void {if (!dragSource) {dropArea.ignoredItem = null;ignoreItemTimer.stop();}}}Timer {id: ignoreItemTimerrepeat: falseinterval: 750onTriggered: {dropArea.ignoredItem = null;}}Timer {id: activationTimerinterval: 250repeat: falseonTriggered: {if (parent.hoveredItem.model.IsGroupParent) {TaskManagerApplet.TaskTools.createGroupDialog(parent.hoveredItem, tasks);} else if (!parent.hoveredItem.model.IsLauncher) {tasksModel.requestActivate(parent.hoveredItem.modelIndex());}}}WheelHandler {id: wheelHandleracceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPadproperty bool handleWheelEvents: trueenabled: handleWheelEvents && Plasmoid.configuration.wheelEnabled !== 0onWheel: event => {// magic number 15 for common "one scroll"// See https://doc.qt.io/qt-6/qml-qtquick-wheelhandler.html#rotation-proplet increment = 0;while (rotation >= 15) {rotation -= 15;increment++;}while (rotation <= -15) {rotation += 15;increment--;}const anchor = dropArea.target.childAt(event.x, event.y);if (Plasmoid.configuration.wheelEnabled === 3) {const loudest = anchor?.audioStreams?.reduce((loudest, stream) => Math.max(loudest, stream.volume), 0)const step = (pulseAudio.item.normalVolume - pulseAudio.item.minimalVolume) * pulseAudio.item.globalConfig.volumeStep / 100;anchor?.audioStreams?.forEach((stream) => {let delta = step * increment;if (loudest > 0) {delta *= stream.volume / loudest;}const volume = stream.volume + delta;console.log(volume, Math.max(pulseAudio.item.minimalVolume, Math.min(volume, pulseAudio.item.normalVolume)));stream.model.Volume = Math.max(pulseAudio.item.minimalVolume, Math.min(volume, pulseAudio.item.normalVolume));stream.model.Muted = volume === 0})return;}while (increment !== 0) {TaskManagerApplet.TaskTools.activateNextPrevTask(anchor, increment < 0, Plasmoid.configuration.wheelSkipMinimized, Plasmoid.configuration.wheelEnabled, tasks);increment += (increment < 0) ? 1 : -1;}}}}