diff --git a/plasmoid/package/contents/config/main.xml b/plasmoid/package/contents/config/main.xml
index 7991a861..3f55a5db 100644
--- a/plasmoid/package/contents/config/main.xml
+++ b/plasmoid/package/contents/config/main.xml
@@ -1,250 +1,254 @@
true
true
true
true
true
false
14
48
false
false
false
true
10
false
false
1
150
false
+
+ false
+
+
0
false
false
true
false
false
true
false
true
true
true
true
false
true
true
true
true
true
false
true
1
6
2
0
1
0
1
0
diff --git a/plasmoid/package/contents/ui/main.qml b/plasmoid/package/contents/ui/main.qml
index afcc8d3d..7e2f93c2 100644
--- a/plasmoid/package/contents/ui/main.qml
+++ b/plasmoid/package/contents/ui/main.qml
@@ -1,2037 +1,2036 @@
/*
* Copyright 2016 Smith AR
* Michail Vourlakos
*
* This file is part of Latte-Dock
*
* Latte-Dock is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* Latte-Dock is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
import QtQuick 2.8
import QtQuick.Layouts 1.1
import QtGraphicalEffects 1.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.plasmoid 2.0
import org.kde.taskmanager 0.1 as TaskManager
import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet
import org.kde.activities 0.1 as Activities
import org.kde.latte.core 0.2 as LatteCore
import org.kde.latte.components 1.0 as LatteComponents
import org.kde.latte.abilities.applets 0.1 as AppletAbility
import org.kde.latte.private.tasks 0.1 as LatteTasks
import "abilities" as Ability
import "previews" as Previews
import "task" as Task
import "taskslayout" as TasksLayout
import "../code/tools.js" as TaskTools
import "../code/activitiesTools.js" as ActivitiesTools
import "../code/ColorizerTools.js" as ColorizerTools
Item {
id:root
Layout.fillWidth: scrollingEnabled && !root.vertical
Layout.fillHeight: scrollingEnabled && root.vertical
Layout.minimumWidth: -1
Layout.minimumHeight: -1
Layout.preferredWidth: tasksWidth
Layout.preferredHeight: tasksHeight
Layout.maximumWidth: -1
Layout.maximumHeight: -1
LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft && !root.vertical
LayoutMirroring.childrenInherit: true
property bool plasma515: latteView ? latteView.plasma515 : LatteCore.Environment.plasmaDesktopVersion >= LatteCore.Environment.makeVersion(5,15,0)
property bool plasma518: latteView ? latteView.plasma518 : LatteCore.Environment.plasmaDesktopVersion >= LatteCore.Environment.makeVersion(5,18,0)
property bool editMode: latteView ? latteView.editMode : plasmoid.userConfiguring
property bool inConfigureAppletsMode: latteView ? latteView.inConfigureAppletsMode : true
property bool disableRestoreZoom: false //blocks restore animation in rightClick
property bool disableAllWindowsFunctionality: plasmoid.configuration.hideAllTasks
property bool dropNewLauncher: false
property bool inActivityChange: false
property bool inDraggingPhase: false
property bool initializationStep: false //true
property bool isHovered: false
property bool showBarLine: plasmoid.configuration.showBarLine
property bool useThemePanel: plasmoid.configuration.useThemePanel
property bool taskInAnimation: noTasksInAnimation > 0 ? true : false
property bool transparentPanel: plasmoid.configuration.transparentPanel
property bool vertical: plasmoid.formFactor === PlasmaCore.Types.Vertical ? true : false
property int clearWidth
property int clearHeight
property int newDroppedPosition: -1
property int noInitCreatedBuffers: 0
property int noTasksInAnimation: 0
property int themePanelSize: plasmoid.configuration.panelSize
property int location : {
if (plasmoid.location === PlasmaCore.Types.LeftEdge
|| plasmoid.location === PlasmaCore.Types.RightEdge
|| plasmoid.location === PlasmaCore.Types.TopEdge) {
return plasmoid.location;
}
return PlasmaCore.Types.BottomEdge;
}
property int tasksStarting: 0
///Don't use Math.floor it adds one pixel in animations and creates glitches
property int widthMargins: root.vertical ? metrics.totals.thicknessEdges : metrics.totals.lengthEdges
property int heightMargins: !root.vertical ? metrics.totals.thicknessEdges : metrics.totals.lengthEdges
property int internalWidthMargins: root.vertical ? metrics.totals.thicknessEdges : metrics.totals.lengthPaddings
property int internalHeightMargins: !root.vertical ? metrics.totals.thicknessEdges : metrics.totals.lengthPaddings
property real textColorBrightness: ColorizerTools.colorBrightness(themeTextColor)
property color minimizedDotColor: {
if (latteView) {
return latteView.minimizedDotColor;
}
return textColorBrightness > 127.5 ? Qt.darker(themeTextColor, 1.7) : Qt.lighter(themeBackgroundColor, 7)
}
property color themeTextColor: theme.textColor
property color themeBackgroundColor: theme.backgroundColor
property color lightTextColor: textColorBrightness > 127.5 ? themeTextColor : themeBackgroundColor
//a small badgers record (id,value)
//in order to track badgers when there are changes
//in launcher reference from libtaskmanager
property variant badgers:[]
property variant launchersOnActivities: []
//global plasmoid reference to the context menu
property QtObject contextMenu: null
property QtObject contextMenuComponent: Qt.createComponent("ContextMenu.qml");
property Item dragSource: null
property Item tasksExtendedManager: _tasksExtendedManager
readonly property alias animations: _animations
readonly property alias indexer: _indexer
readonly property alias launchers: _launchers
readonly property alias metrics: _metrics
readonly property alias parabolic: _parabolic
readonly property alias shortcuts: _shortcuts
readonly property alias containsDrag: mouseHandler.containsDrag
readonly property bool dragAreaEnabled: latteView ? (root.dragSource !== null
|| latteView.dragInfo.isSeparator
|| latteView.dragInfo.isTask
|| !latteView.dragInfo.isPlasmoid)
: true
//! it is used to play the animation correct when the user removes a launcher
property string launcherForRemoval: ""
//BEGIN Latte Dock properties
property bool badges3DStyle: latteView ? latteView.badges3DStyle : true
property bool dockIsShownCompletely: latteView ? latteView.dockIsShownCompletely : true
property bool enableShadows: latteView ? latteView.enableShadows > 0 : plasmoid.configuration.showShadows
property bool forceHidePanel: false
property bool disableLeftSpacer: false
property bool disableRightSpacer: false
property bool dockIsHidden: latteView ? latteView.dockIsHidden : false
property bool groupTasksByDefault: plasmoid.configuration.groupTasksByDefault
property bool highlightWindows: hoverAction === LatteTasks.Types.HighlightWindows || hoverAction === LatteTasks.Types.PreviewAndHighlightWindows
property bool parabolicEffectEnabled: latteView ? latteView.parabolicEffectEnabled : parabolic.factor.zoom && !root.editMode
property bool scrollingEnabled: plasmoid.configuration.scrollTasksEnabled
property bool autoScrollTasksEnabled: scrollingEnabled && plasmoid.configuration.autoScrollTasksEnabled
property bool manualScrollTasksEnabled: scrollingEnabled && manualScrollTasksType !== LatteTasks.Types.ManualScrollDisabled
property int manualScrollTasksType: plasmoid.configuration.manualScrollTasksType
property bool showInfoBadge: plasmoid.configuration.showInfoBadge
property bool showProgressBadge: plasmoid.configuration.showProgressBadge
property bool showAudioBadge: plasmoid.configuration.showAudioBadge
property bool infoBadgeProminentColorEnabled: plasmoid.configuration.infoBadgeProminentColorEnabled
property bool audioBadgeActionsEnabled: plasmoid.configuration.audioBadgeActionsEnabled
property bool showOnlyCurrentScreen: plasmoid.configuration.showOnlyCurrentScreen
property bool showOnlyCurrentDesktop: plasmoid.configuration.showOnlyCurrentDesktop
property bool showOnlyCurrentActivity: plasmoid.configuration.showOnlyCurrentActivity
property bool showPreviews: hoverAction === LatteTasks.Types.PreviewWindows || hoverAction === LatteTasks.Types.PreviewAndHighlightWindows
property bool showWindowActions: plasmoid.configuration.showWindowActions && !disableAllWindowsFunctionality
property bool showWindowsOnlyFromLaunchers: plasmoid.configuration.showWindowsOnlyFromLaunchers && !disableAllWindowsFunctionality
property bool titleTooltips: latteView ? latteView.titleTooltips : false
property alias windowPreviewIsShown: windowsPreviewDlg.visible
property int launchersGroup: plasmoid.configuration.launchersGroup
property int leftClickAction: plasmoid.configuration.leftClickAction
property int middleClickAction: plasmoid.configuration.middleClickAction
property int hoverAction: plasmoid.configuration.hoverAction
property int modifier: plasmoid.configuration.modifier
property int modifierClickAction: plasmoid.configuration.modifierClickAction
property int modifierClick: plasmoid.configuration.modifierClick
property int modifierQt:{
if (modifier === LatteTasks.Types.Shift)
return Qt.ShiftModifier;
else if (modifier === LatteTasks.Types.Ctrl)
return Qt.ControlModifier;
else if (modifier === LatteTasks.Types.Alt)
return Qt.AltModifier;
else if (modifier === LatteTasks.Types.Meta)
return Qt.MetaModifier;
else return -1;
}
property int taskScrollAction: plasmoid.configuration.taskScrollAction
onTaskScrollActionChanged: {
if (taskScrollAction > LatteTasks.Types.ScrollToggleMinimized) {
//! migrating scroll action to LatteTasks.Types.ScrollAction
plasmoid.configuration.taskScrollAction = plasmoid.configuration.taskScrollAction-LatteTasks.Types.ScrollToggleMinimized;
}
}
//! Real properties are need in order for parabolic effect to be 1px precise perfect.
//! This way moving from Tasks to Applets and vice versa is pretty stable when hovering with parabolic effect.
property real tasksHeight: mouseHandler.height
property real tasksWidth: mouseHandler.width
//updated from Binding
property int alignment
readonly property real currentPanelOpacity: latteView ? latteView.currentPanelTransparency / 100 : 1
property int appShadowSize: latteView ? latteView.appShadowSize : Math.ceil(0.12*metrics.iconSize)
property string appShadowColor: latteView ? latteView.appShadowColor : "#ff080808"
property string appShadowColorSolid: latteView ? latteView.appShadowColorSolid : "#ff080808"
property alias tasksCount: tasksModel.count
readonly property rect screenGeometry: latteView ? latteView.screenGeometry : plasmoid.screenGeometry
readonly property bool viewLayoutIsCurrent: latteView && viewLayout && latteView.layoutsManager
&& viewLayout.name === latteView.layoutsManager.currentLayoutName
readonly property string viewLayoutName: viewLayout ? viewLayout.name : ""
readonly property QtObject viewLayout : latteView && latteView.viewLayout ? latteView.viewLayout : null
property Item latteView: null
readonly property Item indicators: latteView ? latteView.indicatorsManager : indicatorsStandaloneLoader.item
//END Latte Dock Panel properties
readonly property bool inEditMode: latteInEditMode || plasmoid.userConfiguring
//BEGIN Latte Dock Communicator
property QtObject latteBridge: null
readonly property bool enforceLattePalette: latteBridge && latteBridge.applyPalette && latteBridge.palette
readonly property bool latteInEditMode: latteBridge && latteBridge.inEditMode
//END Latte Dock Communicator
Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation
Plasmoid.backgroundHints: PlasmaCore.Types.NoBackground
signal draggingFinished();
signal hiddenTasksUpdated();
signal launchersUpdatedFor(string launcher);
signal presentWindows(variant winIds);
signal requestLayout;
signal signalPreviewsShown();
//signal signalDraggingState(bool value);
signal showPreviewForTasks(QtObject group);
//trigger updating scaling of neighbour delegates of zoomed delegate
signal updateScale(int delegateIndex, real newScale, real step)
signal mimicEnterForParabolic();
signal publishTasksGeometries();
signal windowsHovered(variant winIds, bool hovered)
//onAnimationsChanged: console.log(animations);
/* Rectangle{
anchors.fill: parent
border.width: 1
border.color: "red"
color: "white"
} */
onLatteViewChanged: {
if (latteView) {
plasmoid.action("configure").visible = false;
plasmoid.configuration.isInLatteDock = true;
if (root.launchersGroup === LatteCore.Types.LayoutLaunchers
|| root.launchersGroup === LatteCore.Types.GlobalLaunchers) {
tasksModel.updateLaunchersList();
}
} else {
plasmoid.configuration.isInLatteDock = false;
}
}
onLaunchersGroupChanged:{
if(latteView) {
tasksModel.updateLaunchersList();
}
}
Connections {
target: plasmoid
onLocationChanged: {
iconGeometryTimer.start();
}
}
Connections {
target: plasmoid.configuration
// onLaunchersChanged: tasksModel.launcherList = plasmoid.configuration.launchers
onGroupingAppIdBlacklistChanged: tasksModel.groupingAppIdBlacklist = plasmoid.configuration.groupingAppIdBlacklist;
onGroupingLauncherUrlBlacklistChanged: tasksModel.groupingLauncherUrlBlacklist = plasmoid.configuration.groupingLauncherUrlBlacklist;
}
Connections{
target: latteView
onDockIsHiddenChanged:{
if (latteView.dockIsHidden) {
windowsPreviewDlg.hide("3.3");
}
}
}
Connections{
target: latteView && latteView.layoutsManager ? latteView.layoutsManager : null
onCurrentLayoutNameChanged: root.publishTasksGeometries();
}
Binding {
target: plasmoid
property: "status"
value: {
if (tasksModel.anyTaskDemandsAttentionInValidTime || root.dragSource) {
return PlasmaCore.Types.NeedsAttentionStatus;
}
return PlasmaCore.Types.PassiveStatus;
}
}
/////
PlasmaCore.ColorScope{
id: colorScopePalette
}
//!
Item {
id: graphicsSystem
readonly property bool isAccelerated: (GraphicsInfo.api !== GraphicsInfo.Software)
&& (GraphicsInfo.api !== GraphicsInfo.Unknown)
}
Loader {
id: indicatorsStandaloneLoader
active: !latteView && !plasmoid.configuration.isInLatteDock
source: "indicators/Manager.qml"
}
Binding {
target: root
property: "alignment"
value: {
if (latteView) {
if (latteView.panelAlignment === -1) {
return;
}
if (latteView.panelAlignment === LatteCore.Types.Justify) {
if (latteView.latteAppletPos>=0 && latteView.latteAppletPos<100) {
return plasmoid.formFactor === PlasmaCore.Types.Horizontal ? LatteCore.Types.Left : LatteCore.Types.Top;
} else if (latteView.latteAppletPos>=100 && latteView.latteAppletPos<200) {
return LatteCore.Types.Center;
} else if (latteView.latteAppletPos>=200) {
return plasmoid.formFactor === PlasmaCore.Types.Horizontal ? LatteCore.Types.Right : LatteCore.Types.Bottom;
}
return LatteCore.Types.Center;
}
return latteView.panelAlignment;
}
return LatteCore.Types.Center;
}
}
/////
function launchersDropped(urls){
mouseHandler.urlsDropped(urls);
}
///UPDATE
function launcherExists(url) {
return (ActivitiesTools.getIndex(url, tasksModel.launcherList)>=0);
}
function taskExists(url) {
var tasks = icList.contentItem.children;
for(var i=0; i -1) {
launch.push(explicitLauncher);
}
}
}
return launch;
}
function currentListViewLauncherList() {
var launch = [];
var tasks = icList.contentItem.children;
for(var i=0; i= LatteCore.Types.LayoutLaunchers) {
latteView.layoutsManager.launchersSignals.validateLaunchersOrder(root.viewLayoutName,
plasmoid.id,
root.launchersGroup,
currentLauncherList());
}
}
} else {
plasmoid.configuration.launchers59 = launcherList;
}
} else {
plasmoid.configuration.launchers59 = launcherList;
}
}
onGroupingAppIdBlacklistChanged: {
plasmoid.configuration.groupingAppIdBlacklist = groupingAppIdBlacklist;
}
onGroupingLauncherUrlBlacklistChanged: {
plasmoid.configuration.groupingLauncherUrlBlacklist = groupingLauncherUrlBlacklist;
}
onAnyTaskDemandsAttentionChanged: {
if (anyTaskDemandsAttention){
anyTaskDemandsAttentionInValidTime = true;
attentionTimerComponent.createObject(root);
}
}
Component.onCompleted: {
ActivitiesTools.launchersOnActivities = root.launchersOnActivities
ActivitiesTools.currentActivity = String(activityInfo.currentActivity);
ActivitiesTools.plasmoid = plasmoid;
//var loadedLaunchers = ActivitiesTools.restoreLaunchers();
ActivitiesTools.importLaunchersToNewArchitecture();
if (viewLayout && latteView.universalSettings
&& (root.launchersGroup === LatteCore.Types.LayoutLaunchers
|| root.launchersGroup === LatteCore.Types.GlobalLaunchers)) {
if (root.launchersGroup === LatteCore.Types.LayoutLaunchers) {
launcherList = latteView.viewLayout.launchers;
} else if (root.launchersGroup === LatteCore.Types.GlobalLaunchers) {
launcherList = latteView.universalSettings.launchers;
}
} else {
launcherList = plasmoid.configuration.launchers59;
}
groupingAppIdBlacklist = plasmoid.configuration.groupingAppIdBlacklist;
groupingLauncherUrlBlacklist = plasmoid.configuration.groupingLauncherUrlBlacklist;
icList.model = tasksModel;
tasksStarting = count;
///Plasma 5.9 enforce grouping at all cases
if (LatteCore.Environment.plasmaDesktopVersion >= LatteCore.Environment.makeVersion(5,9,0)) {
groupingWindowTasksThreshold = -1;
}
}
}
//! TaskManagerBackend required a groupDialog setting otherwise it crashes. This patch
//! sets one just in order not to crash TaskManagerBackend
PlasmaCore.Dialog {
//ghost group Dialog to not crash TaskManagerBackend
id: groupDialogGhost
visible: false
type: PlasmaCore.Dialog.PopupMenu
flags: Qt.WindowStaysOnTopHint
hideOnWindowDeactivate: true
location: root.location
}
TaskManagerApplet.Backend {
id: backend
taskManagerItem: root
toolTipItem: toolTipDelegate
highlightWindows: root.highlightWindows
onAddLauncher: {
tasksModel.requestAddLauncher(url);
}
Component.onCompleted: {
//! In Plasma 5.9 TaskManagerBackend required a groupDialog setting
//! otherwise it crashes.
//! frameworks 5.29.0 provide id 335104
//! work only after Plasma 5.9 and frameworks 5.29
//! + added a check for groupDialog also when it is present
//! in plasma 5.8 (that was introduced after 5.8.5)
if (LatteCore.Environment.frameworksVersion >= 335104 || (groupDialog !== undefined)) {
groupDialog = groupDialogGhost;
}
}
}
TaskManagerApplet.DragHelper {
id: dragHelper
dragIconSize: units.iconSizes.medium
}
TaskManager.VirtualDesktopInfo {
id: virtualDesktopInfo
}
TaskManager.ActivityInfo {
id: activityInfo
property string previousActivity: ""
onCurrentActivityChanged: {
root.inActivityChange = true;
activityChangeDelayer.start();
}
Component.onCompleted: previousActivity = currentActivity;
}
PlasmaCore.DataSource {
id: mpris2Source
engine: "mpris2"
connectedSources: sources
function sourceNameForLauncherUrl(launcherUrl, pid) {
if (!launcherUrl || launcherUrl === "") {
return "";
}
// MPRIS spec explicitly mentions that "DesktopEntry" is with .desktop extension trimmed
// Moreover, remove URL parameters, like wmClass (part after the question mark)
var desktopFileName = launcherUrl.toString().split('/').pop().split('?')[0].replace(".desktop", "")
if (desktopFileName.indexOf("applications:") === 0) {
desktopFileName = desktopFileName.substr(13)
}
for (var i = 0, length = connectedSources.length; i < length; ++i) {
var source = connectedSources[i];
// we intend to connect directly, otherwise the multiplexer steals the connection away
if (source === "@multiplex") {
continue;
}
var sourceData = data[source];
if (!sourceData) {
continue;
}
if (sourceData.DesktopEntry === desktopFileName || (pid && sourceData.InstancePid === pid)) {
return source;
}
var metadata = sourceData.Metadata;
if (metadata) {
var kdePid = metadata["kde:pid"];
if (kdePid && pid === kdePid) {
return source;
}
}
}
return ""
}
function startOperation(source, op) {
var service = serviceForSource(source)
var operation = service.operationDescription(op)
return service.startOperationCall(operation)
}
function goPrevious(source) {
startOperation(source, "Previous");
}
function goNext(source) {
startOperation(source, "Next");
}
function play(source) {
startOperation(source, "Play");
}
function pause(source) {
startOperation(source, "Pause");
}
function playPause(source) {
startOperation(source, "PlayPause");
}
function stop(source) {
startOperation(source, "Stop");
}
function raise(source) {
startOperation(source, "Raise");
}
function quit(source) {
startOperation(source, "Quit");
}
}
Loader {
id: pulseAudio
source: "PulseAudio.qml"
active: root.showAudioBadge
}
TasksExtendedManager {
id: _tasksExtendedManager
}
Ability.Animations {
id: _animations
bridge: latteBridge
}
Ability.Indexer {
id: _indexer
bridge: latteBridge
layout: icList.contentItem
allItemsCount: tasksModel.count
}
Ability.Launchers {
id: _launchers
}
Ability.Metrics {
id: _metrics
bridge: latteBridge
}
Ability.ParabolicEffect {
id: _parabolic
bridge: latteBridge
local.restoreZoomIsBlocked: root.contextMenu || windowsPreviewDlg.containsMouse
}
Ability.PositionShortcuts {
id: _shortcuts
bridge: latteBridge
isStealingGlobalPositionShortcuts: plasmoid.configuration.isPreferredForPositionShortcuts
onDisabledIsStealingGlobalPositionShortcuts: {
plasmoid.configuration.isPreferredForPositionShortcuts = false;
}
}
AppletAbility.Requirements{
id: _requires
bridge: latteBridge
activeIndicatorEnabled: false
latteIconOverlayEnabled: false
lengthMarginsEnabled: false
latteSideColoringEnabled: false
screenEdgeMarginSupported: true
innerZoomFactor: {
if (!_animations.active || !LatteCore.WindowSystem.compositingActive) {
return 1;
}
var hasHighThicknessAnimation = _animations.launcherBouncingEnabled || _animations.windowInAttentionEnabled || _animations.windowAddedInGroupEnabled;
return hasHighThicknessAnimation ? 1.65 : 1.0;
}
}
Component{
id: attentionTimerComponent
Timer{
id: attentionTimer
interval:8500
onTriggered: {
tasksModel.anyTaskDemandsAttentionInValidTime = false;
destroy();
if (latteView && latteView.debugModeTimers) {
console.log("plasmoid timer: attentionTimer called...");
}
}
Component.onCompleted: {
start();
}
}
}
//this timer restores the draggingPhase flag to false
//after a dragging has finished... This delay is needed
//in order to not animate any tasks are added after a
//dragging
Timer {
id: restoreDraggingPhaseTimer
interval: 150
onTriggered: inDraggingPhase = false;
}
///Red Liner!!! show the upper needed limit for animations
Rectangle{
anchors.horizontalCenter: !root.vertical ? parent.horizontalCenter : undefined
anchors.verticalCenter: root.vertical ? parent.verticalCenter : undefined
width: root.vertical ? 1 : 2 * metrics.iconSize
height: root.vertical ? 2 * metrics.iconSize : 1
color: "red"
x: (root.location === PlasmaCore.Types.LeftEdge) ? neededSpace : parent.width - neededSpace
y: (root.location === PlasmaCore.Types.TopEdge) ? neededSpace : parent.height - neededSpace
visible: plasmoid.configuration.zoomHelper
property int neededSpace: parabolic.factor.zoom*metrics.totals.length
}
Item{
id:barLine
anchors.bottom: (root.location === PlasmaCore.Types.BottomEdge) ? parent.bottom : undefined
anchors.top: (root.location === PlasmaCore.Types.TopEdge) ? parent.top : undefined
anchors.left: (root.location === PlasmaCore.Types.LeftEdge) ? parent.left : undefined
anchors.right: (root.location === PlasmaCore.Types.RightEdge) ? parent.right : undefined
anchors.horizontalCenter: !root.vertical ? parent.horizontalCenter : undefined
anchors.verticalCenter: root.vertical ? parent.verticalCenter : undefined
width: ( icList.orientation === Qt.Horizontal ) ? icList.width + spacing : smallSize
height: ( icList.orientation === Qt.Vertical ) ? icList.height + spacing : smallSize
property int spacing: latteBridge ? 0 : metrics.iconSize / 2
property int smallSize: Math.max(0.10 * metrics.iconSize, 16)
Behavior on opacity{
NumberAnimation { duration: animations.speedFactor.current*animations.duration.large }
}
/// plasmoid's default panel
BorderImage{
anchors.fill:parent
source: "../images/panel-west.png"
border { left:8; right:8; top:8; bottom:8 }
opacity: (plasmoid.configuration.showBarLine && !plasmoid.configuration.useThemePanel && !root.forceHidePanel) ? 1 : 0
visible: (opacity == 0) ? false : true
horizontalTileMode: BorderImage.Stretch
verticalTileMode: BorderImage.Stretch
Behavior on opacity{
NumberAnimation { duration: animations.speedFactor.current*animations.duration.large }
}
}
/// item which is used as anchors for the plasma's theme
Item{
id:belower
width: (root.location === PlasmaCore.Types.LeftEdge) ? shadowsSvgItem.margins.left : shadowsSvgItem.margins.right
height: (root.location === PlasmaCore.Types.BottomEdge)? shadowsSvgItem.margins.bottom : shadowsSvgItem.margins.top
anchors.top: (root.location === PlasmaCore.Types.BottomEdge) ? parent.bottom : undefined
anchors.bottom: (root.location === PlasmaCore.Types.TopEdge) ? parent.top : undefined
anchors.right: (root.location === PlasmaCore.Types.LeftEdge) ? parent.left : undefined
anchors.left: (root.location === PlasmaCore.Types.RightEdge) ? parent.right : undefined
}
/// the current theme's panel
PlasmaCore.FrameSvgItem{
id: shadowsSvgItem
anchors.bottom: (root.location === PlasmaCore.Types.BottomEdge) ? belower.bottom : undefined
anchors.top: (root.location === PlasmaCore.Types.TopEdge) ? belower.top : undefined
anchors.left: (root.location === PlasmaCore.Types.LeftEdge) ? belower.left : undefined
anchors.right: (root.location === PlasmaCore.Types.RightEdge) ? belower.right : undefined
anchors.horizontalCenter: !root.vertical ? parent.horizontalCenter : undefined
anchors.verticalCenter: root.vertical ? parent.verticalCenter : undefined
width: root.vertical ? panelSize + margins.left + margins.right: parent.width
height: root.vertical ? parent.height : panelSize + margins.top + margins.bottom
imagePath: "translucent/widgets/panel-background"
prefix:"shadow"
opacity: (plasmoid.configuration.showBarLine && plasmoid.configuration.useThemePanel && !root.forceHidePanel) ? 1 : 0
visible: (opacity == 0) ? false : true
property int panelSize: ((root.location === PlasmaCore.Types.BottomEdge) ||
(root.location === PlasmaCore.Types.TopEdge)) ?
plasmoid.configuration.panelSize + belower.height:
plasmoid.configuration.panelSize + belower.width
Behavior on opacity{
NumberAnimation { duration: animations.speedFactor.current*animations.duration.large }
}
PlasmaCore.FrameSvgItem{
anchors.margins: belower.width-1
anchors.fill:parent
imagePath: plasmoid.configuration.transparentPanel ? "translucent/widgets/panel-background" :
"widgets/panel-background"
}
}
TasksLayout.MouseHandler {
id: mouseHandler
anchors.bottom: (root.location === PlasmaCore.Types.BottomEdge) ? scrollableList.bottom : undefined
anchors.top: (root.location === PlasmaCore.Types.TopEdge) ? scrollableList.top : undefined
anchors.left: (root.location === PlasmaCore.Types.LeftEdge) ? scrollableList.left : undefined
anchors.right: (root.location === PlasmaCore.Types.RightEdge) ? scrollableList.right : undefined
anchors.horizontalCenter: !root.vertical ? scrollableList.horizontalCenter : undefined
anchors.verticalCenter: root.vertical ? scrollableList.verticalCenter : undefined
width: root.vertical ? maxSize : icList.width
height: root.vertical ? icList.height : maxSize
target: icList
visible: root.dragAreaEnabled
property int maxSize: (parabolic.local.lastIndex>=0 || windowPreviewIsShown || animations.hasThicknessAnimation) ?
(parabolic.factor.maxZoom * metrics.totals.thickness) + metrics.margin.screenEdge :
metrics.totals.thickness + metrics.margin.screenEdge
function onlyLaunchersInList(list){
return list.every(function (item) {
return backend.isApplication(item)
});
}
function urlsDroppedOnArea(urls){
// If all dropped URLs point to application desktop files, we'll add a launcher for each of them.
if (onlyLaunchersInList(urls)) {
urls.forEach(function (item) {
addLauncher(item);
});
return;
}
if (!hoveredItem) {
return;
}
// DeclarativeMimeData urls is a QJsonArray but requestOpenUrls expects a proper QList.
var urlsList = backend.jsonArrayToUrlList(urls);
// Otherwise we'll just start a new instance of the application with the URLs as argument,
// as you probably don't expect some of your files to open in the app and others to spawn launchers.
tasksModel.requestOpenUrls(hoveredItem.modelIndex(), urlsList);
}
onUrlsDropped: {
//! inform synced docks for new dropped launchers
if (latteView && root.launchersGroup >= LatteCore.Types.LayoutLaunchers && onlyLaunchersInList(urls)) {
latteView.layoutsManager.launchersSignals.urlsDropped(root.viewLayoutName,
root.launchersGroup, urls);
return;
}
//! if the list does not contain only launchers then just open the corresponding
//! urls with the relevant app
urlsDroppedOnArea(urls);
}
}
/* Rectangle {
anchors.fill: scrollableList
color: "transparent"
border.width: 1
border.color: "blue"
} */
TasksLayout.ScrollableList {
id: scrollableList
width: !root.vertical ? length : thickness
height: root.vertical ? length : thickness
contentWidth: icList.width
contentHeight: icList.height
property int thickness:0 // through Binding to avoid binding loops
property int length:0 // through Binding to avoid binding loops
//onCurrentPosChanged: console.log("CP :: "+ currentPos + " icW:"+icList.width + " rw: "+root.width + " w:" +width);
layer.enabled: contentsExceed && root.scrollingEnabled
layer.effect: OpacityMask {
maskSource: TasksLayout.ScrollOpacityMask{
width: scrollableList.width
height: scrollableList.height
}
}
Binding {
target: scrollableList
property: "thickness"
when: latteView && !latteView.maskManager.inTempHiding
value: {
if (latteView) {
return animations.hasThicknessAnimation ? latteView.maskManager.thicknessZoom : latteView.maskManager.thicknessNormal;
}
return metrics.totals.thickness * parabolic.factor.zoom;
}
}
Binding {
target: scrollableList
property: "length"
when: latteView && !latteView.maskManager.inTempHiding
value: {
if (root.vertical) {
return Math.min(root.height, icList.height)
}
return Math.min(root.width, icList.width);
}
}
TasksLayout.ScrollPositioner {
id: listViewBase
ListView {
id:icList
anchors.bottom: (root.location === PlasmaCore.Types.BottomEdge) ? parent.bottom : undefined
anchors.top: (root.location === PlasmaCore.Types.TopEdge) ? parent.top : undefined
anchors.left: (root.location === PlasmaCore.Types.LeftEdge) ? parent.left : undefined
anchors.right: (root.location === PlasmaCore.Types.RightEdge) ? parent.right : undefined
anchors.horizontalCenter: !root.vertical ? parent.horizontalCenter : undefined
anchors.verticalCenter: root.vertical ? parent.verticalCenter : undefined
width: !root.vertical ? contentWidth : mouseHandler.maxSize
height: root.vertical ? contentHeight : mouseHandler.maxSize
boundsBehavior: Flickable.StopAtBounds
orientation: plasmoid.formFactor === PlasmaCore.Types.Vertical ? Qt.Vertical : Qt.Horizontal
delegate: Task.TaskItem{
animations: _animations
indexer: _indexer
launchers: _launchers
metrics: _metrics
parabolic: _parabolic
requires: _requires
shortcuts: _shortcuts
}
property int currentSpot : -1000
property int previousCount : 0
property int tasksCount: tasksModel.count
//the duration of this animation should be as small as possible
//it fixes a small issue with the dragging an item to change it's
//position, if the duration is too big there is a point in the
//list that an item is going back and forth too fast
//more of a trouble
moveDisplaced: Transition {
NumberAnimation { properties: "x,y"; duration: animations.speedFactor.current*animations.duration.large; easing.type: Easing.Linear }
}
///this transition can not be used with dragging !!!! I breaks
///the lists indexes !!!!!
///move: Transition {
/// NumberAnimation { properties: "x,y"; duration: 400; easing.type: Easing.Linear }
///}
function childAtPos(x, y){
var tasks = icList.contentItem.children;
for(var i=0; i=choords.x) && (x<=choords.x+task.width)
&& (y>=choords.y) && (y<=choords.y+task.height)){
return task;
}
}
return null;
}
function childAtIndex(position) {
var tasks = icList.contentItem.children;
if (position < 0)
return;
for(var i=0; i 0
radius: metrics.iconSize/10
backgroundOpacity: root.dropNewLauncher && mouseHandler.onlyLaunchers && (root.dragSource == null)? 0.75 : 0
duration: animations.speedFactor.current
title: i18n("Tasks Area")
states: [
///Bottom Edge
State {
name: "left"
when: root.location===PlasmaCore.Types.LeftEdge
AnchorChanges {
target: newDroppedLauncherVisual
anchors{ top:undefined; bottom:undefined; left:scrollableList.left; right:undefined;
horizontalCenter:undefined; verticalCenter:scrollableList.verticalCenter}
}
PropertyChanges {
target: newDroppedLauncherVisual
anchors{ topMargin:0; bottomMargin:0; leftMargin:metrics.margin.screenEdge; rightMargin:0;}
}
},
State {
name: "right"
when: root.location===PlasmaCore.Types.RightEdge
AnchorChanges {
target: newDroppedLauncherVisual
anchors{ top:undefined; bottom:undefined; left:undefined; right:scrollableList.right;
horizontalCenter:undefined; verticalCenter:scrollableList.verticalCenter}
}
PropertyChanges {
target: newDroppedLauncherVisual
anchors{ topMargin:0; bottomMargin:0; leftMargin:0; rightMargin:metrics.margin.screenEdge;}
}
},
State {
name: "top"
when: root.location===PlasmaCore.Types.TopEdge
AnchorChanges {
target: newDroppedLauncherVisual
anchors{ top:scrollableList.top; bottom:undefined; left:undefined; right:undefined;
horizontalCenter:scrollableList.horizontalCenter; verticalCenter:undefined}
}
PropertyChanges {
target: newDroppedLauncherVisual
anchors{ topMargin:metrics.margin.screenEdge; bottomMargin:0; leftMargin:0; rightMargin:0;}
}
},
State {
name: "bottom"
when: root.location!==PlasmaCore.Types.TopEdge
&& root.location !== PlasmaCore.Types.LeftEdge
&& root.location !== PlasmaCore.Types.RightEdge
AnchorChanges {
target: newDroppedLauncherVisual
anchors{ top:undefined; bottom:scrollableList.bottom; left:undefined; right:undefined;
horizontalCenter:scrollableList.horizontalCenter; verticalCenter:undefined}
}
PropertyChanges {
target: newDroppedLauncherVisual
anchors{ topMargin:0; bottomMargin:metrics.margin.screenEdge; leftMargin:0; rightMargin:0;}
}
}
]
}
}
//// helpers
Timer {
id: iconGeometryTimer
// INVESTIGATE: such big interval but unfortunately it does not work otherwise
interval: 500
repeat: false
onTriggered: {
root.publishTasksGeometries();
if (latteView && latteView.debugModeTimers) {
console.log("plasmoid timer: iconGeometryTimer called...");
}
}
}
///REMOVE
////Activities List
////it can be used to cleanup the launchers from garbage-deleted activities....
Item{
id: activityModelInstance
property int count: activityModelRepeater.count
Repeater {
id:activityModelRepeater
model: Activities.ActivityModel {
id: activityModel
// shownStates: "Running"
}
delegate: Item {
visible: false
property string activityId: model.id
property string activityName: model.name
}
}
function activities(){
var activitiesResult = [];
for(var i=0; i=0; --i) {
if (currentLaunchers[i] !== launchers[i]) {
var p = launcherValidPos(currentLaunchers[i]);
if (p === -1) {
console.log("No pos found for :"+currentLaunchers[i] + " at: "+launchers);
restart();
return;
}
var launcherModelIndex = icList.launcherModelIndex(currentLaunchers[i]);
if (launcherModelIndex === -1) {
console.log(" launcher was not found in model, syncing stopped...");
stop();
return;
}
console.log(" moving:" +launcherModelIndex + " _ " + p );
tasksModel.move(launcherModelIndex, p);
restart();
return;
}
}
}
console.log("why we reached ??? ");
console.log("CURRENT ::: " + currentLaunchers);
console.log("VALID ::: " + launchers);
}
}
}
/////////
//// functions
function addInternalSeparatorAtPos(pos) {
var separatorName = launchers.freeAvailableSeparatorName();
if (separatorName !== "") {
tasksExtendedManager.addLauncherToBeMoved(separatorName, Math.max(0,pos));
if (latteView && root.launchersGroup >= LatteCore.Types.LayoutLaunchers) {
latteView.layoutsManager.launchersSignals.addLauncher(root.viewLayoutName,
root.launchersGroup, separatorName);
} else {
tasksModel.requestAddLauncher(separatorName);
}
}
}
function activateTaskAtIndex(index) {
// This is called with Meta+number shortcuts by plasmashell when Tasks are in a plasma panel.
shortcuts.sglActivateEntryAtIndex(index);
}
function newInstanceForTaskAtIndex(index) {
// This is called with Meta+Alt+number shortcuts by plasmashell when Tasks are in a plasma panel.
shortcuts.sglNewInstanceForEntryAtIndex(index);
}
function getBadger(identifier) {
var ident1 = identifier;
var n = ident1.lastIndexOf('/');
var result = n>=0 ? ident1.substring(n + 1) : identifier;
for(var i=0; i= 0) {
return badgers[i];
}
}
}
function updateBadge(identifier, value) {
var tasks = icList.contentItem.children;
var identifierF = identifier.concat(".desktop");
for(var i=0; i= 0) {
task.badgeIndicator = value === "" ? 0 : Number(value);
var badge = getBadger(identifierF);
if (badge) {
badge.value = value;
} else {
badgers.push({id: identifierF, value: value});
}
}
}
}
function getLauncherList() {
return plasmoid.configuration.launchers59;
}
//! BEGIN ::: external launchers signals in order to update the tasks model
function extSignalAddLauncher(group, launcher) {
if (group === root.launchersGroup) {
tasksModel.requestAddLauncher(launcher);
launchersUpdatedFor(launcher);
tasksModel.syncLaunchers();
}
}
function extSignalRemoveLauncher(group, launcher) {
if (group === root.launchersGroup) {
root.launcherForRemoval = launcher;
tasksModel.requestRemoveLauncher(launcher);
launchersUpdatedFor(launcher);
tasksModel.syncLaunchers();
}
}
function extSignalAddLauncherToActivity(group, launcher, activity) {
if (group === root.launchersGroup) {
var launcherActivities = tasksModel.launcherActivities(launcher);
if (activity !== tasksModel.activity && (launcherActivities[0] === "00000000-0000-0000-0000-000000000000")) {
root.launcherForRemoval = launcher;
}
tasksModel.requestAddLauncherToActivity(launcher, activity);
launchersUpdatedFor(launcher);
tasksModel.syncLaunchers();
}
}
function extSignalRemoveLauncherFromActivity(group, launcher, activity) {
if (group === root.launchersGroup) {
if (activity === tasksModel.activity) {
root.launcherForRemoval = launcher;
}
tasksModel.requestRemoveLauncherFromActivity(launcher, activity);
launchersUpdatedFor(launcher);
tasksModel.syncLaunchers();
}
}
function extSignalUrlsDropped(group, urls) {
if (group === root.launchersGroup) {
mouseHandler.urlsDroppedOnArea(urls);
}
}
function extSignalMoveTask(group, from, to) {
if (group === root.launchersGroup && !root.dragSource) {
tasksModel.move(from, to);
tasksModel.syncLaunchers();
}
}
function extSignalValidateLaunchersOrder(group, launchers) {
if (group === root.launchersGroup && !root.dragSource) {
launchersOrderValidatorTimer.stop();
launchersOrderValidatorTimer.launchers = launchers;
launchersOrderValidatorTimer.start();
}
}
//! END ::: external launchers signals in order to update the tasks model
//! it is used to add the fake desktop file which represents
//! the separator (fake launcher)
function addSeparator(pos){
var separatorName = launchers.freeAvailableSeparatorName();
if (separatorName !== "") {
tasksExtendedManager.addLauncherToBeMoved(separatorName, Math.max(0,pos));
if (latteView && root.launchersGroup >= LatteCore.Types.LayoutLaunchers) {
latteView.layoutsManager.launchersSignals.addLauncher(root.launchersGroup, separatorName);
} else {
tasksModel.requestAddLauncher(separatorName);
}
}
}
function previewContainsMouse() {
return windowsPreviewDlg.containsMouse;
}
function containsMouse(){
//console.log("s1...");
if (disableRestoreZoom && (root.contextMenu || windowsPreviewDlg.visible)) {
return;
} else {
disableRestoreZoom = false;
}
//if (previewContainsMouse())
// windowsPreviewDlg.hide(4);
if (previewContainsMouse())
return true;
//console.log("s3...");
var tasks = icList.contentItem.children;
for(var i=0; i0) {
url = url.substring( 0, url.indexOf("?iconData=" ) );
}
var path = url;
var filename = path.split("/").pop();
tasksExtendedManager.addToBeAddedLauncher(filename);
tasksModel.requestAddLauncher(url);
launchersUpdatedFor(url);
tasksModel.syncLaunchers();
}
function resetDragSource() {
dragSource.z = 0;
dragSource = null;
}
///REMOVE
/*function createContextMenu(task) {
var menu = root.contextMenuComponent.createObject(task);
menu.visualParent = task;
menu.mpris2Source = mpris2Source;
menu.activitiesCount = activityModelInstance.count;
return menu;
}*/
function createContextMenu(rootTask, modelIndex, args) {
var initialArgs = args || {}
initialArgs.visualParent = rootTask;
initialArgs.modelIndex = modelIndex;
initialArgs.mpris2Source = mpris2Source;
initialArgs.backend = backend;
root.contextMenu = root.contextMenuComponent.createObject(rootTask, initialArgs);
return root.contextMenu;
}
Component.onCompleted: {
root.presentWindows.connect(backend.presentWindows);
root.windowsHovered.connect(backend.windowsHovered);
dragHelper.dropped.connect(resetDragSource);
}
Component.onDestruction: {
root.presentWindows.disconnect(backend.presentWindows);
root.windowsHovered.disconnect(backend.windowsHovered);
dragHelper.dropped.disconnect(resetDragSource);
}
//BEGIN states
// Alignments
// 0-Center, 1-Left, 2-Right, 3-Top, 4-Bottom
states: [
///Bottom Edge
State {
name: "bottomCenter"
when: (root.location===PlasmaCore.Types.BottomEdge && root.alignment===LatteCore.Types.Center)
AnchorChanges {
target: barLine
anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined}
}
AnchorChanges {
target: icList
anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined}
}
},
State {
name: "bottomLeft"
when: (root.location===PlasmaCore.Types.BottomEdge && root.alignment===LatteCore.Types.Left)
AnchorChanges {
target: barLine
anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined}
}
AnchorChanges {
target: icList
anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined}
}
},
State {
name: "bottomRight"
when: (root.location===PlasmaCore.Types.BottomEdge && root.alignment===LatteCore.Types.Right)
AnchorChanges {
target: barLine
anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined}
}
AnchorChanges {
target: icList
anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined}
}
},
///Top Edge
State {
name: "topCenter"
when: (root.location===PlasmaCore.Types.TopEdge && root.alignment===LatteCore.Types.Center)
AnchorChanges {
target: barLine
anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined}
}
AnchorChanges {
target: icList
anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined}
}
},
State {
name: "topLeft"
when: (root.location===PlasmaCore.Types.TopEdge && root.alignment===LatteCore.Types.Left)
AnchorChanges {
target: barLine
anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined}
}
AnchorChanges {
target: icList
anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined}
}
},
State {
name: "topRight"
when: (root.location===PlasmaCore.Types.TopEdge && root.alignment===LatteCore.Types.Right)
AnchorChanges {
target: barLine
anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined}
}
AnchorChanges {
target: icList
anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined}
}
},
////Left Edge
State {
name: "leftCenter"
when: (root.location===PlasmaCore.Types.LeftEdge && root.alignment===LatteCore.Types.Center)
AnchorChanges {
target: barLine
anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:parent.verticalCenter}
}
AnchorChanges {
target: icList
anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:parent.verticalCenter}
}
},
State {
name: "leftTop"
when: (root.location===PlasmaCore.Types.LeftEdge && root.alignment===LatteCore.Types.Top)
AnchorChanges {
target: barLine
anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined}
}
AnchorChanges {
target: icList
anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined}
}
},
State {
name: "leftBottom"
when: (root.location===PlasmaCore.Types.LeftEdge && root.alignment===LatteCore.Types.Bottom)
AnchorChanges {
target: barLine
anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined}
}
AnchorChanges {
target: icList
anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined}
}
},
///Right Edge
State {
name: "rightCenter"
when: (root.location===PlasmaCore.Types.RightEdge && root.alignment===LatteCore.Types.Center)
AnchorChanges {
target: barLine
anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:parent.verticalCenter}
}
AnchorChanges {
target: icList
anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:parent.verticalCenter}
}
},
State {
name: "rightTop"
when: (root.location===PlasmaCore.Types.RightEdge && root.alignment===LatteCore.Types.Top)
AnchorChanges {
target: barLine
anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined}
}
AnchorChanges {
target: icList
anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined}
}
},
State {
name: "rightBottom"
when: (root.location===PlasmaCore.Types.RightEdge && root.alignment===LatteCore.Types.Bottom)
AnchorChanges {
target: barLine
anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined}
}
AnchorChanges {
target: icList
anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined}
}
}
]
//END states
}
diff --git a/plasmoid/package/contents/ui/previews/ToolTipInstance.qml b/plasmoid/package/contents/ui/previews/ToolTipInstance.qml
index 81e3585b..a6724e24 100644
--- a/plasmoid/package/contents/ui/previews/ToolTipInstance.qml
+++ b/plasmoid/package/contents/ui/previews/ToolTipInstance.qml
@@ -1,490 +1,490 @@
/*
* Copyright 2013 by Sebastian Kügler
* Copyright 2014 by Martin Gräßlin
* Copyright 2016 by Kai Uwe Broulik
* Copyright 2017 by Roman Gilg
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA.
*/
import QtQuick 2.6
import QtQuick.Layouts 1.1
import QtGraphicalEffects 1.0
import QtQml.Models 2.2
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons
import org.kde.latte.core 0.2 as LatteCore
import org.kde.draganddrop 2.0
import org.kde.taskmanager 0.1 as TaskManager
Column {
id: instance
property var submodelIndex
property int flatIndex: isGroup && itemIndex>=0 ? itemIndex : 0
property bool isActive: (typeof model !== 'undefined') && (typeof model.IsActive !== 'undefined') ? IsActive : false
property bool isMinimized: (typeof model !== 'undefined') && (typeof model.IsMinimized !== 'undefined') ? IsMinimized : false
property int appPid: (typeof model !== 'undefined') && (typeof model.AppPid !== 'undefined') ? AppPid : -1
property int itemIndex: (typeof model !== 'undefined') && (typeof model.index !== 'undefined') ? index : 0
property int virtualDesktop: (typeof model !== 'undefined') && (typeof model.VirtualDesktop !== 'undefined') ? VirtualDesktop : 0
property var activities : (typeof model !== 'undefined') && (typeof model.Activities !== 'undefined') ? Activities : []
spacing: units.smallSpacing
readonly property string mprisSourceName: mpris2Source.sourceNameForLauncherUrl(toolTipDelegate.launcherUrl, isGroup ? appPid : pidParent)
readonly property var playerData: mprisSourceName != "" ? mpris2Source.data[mprisSourceName] : 0
readonly property bool hasPlayer: !!mprisSourceName && !!playerData
readonly property bool playing: hasPlayer && playerData.PlaybackStatus === "Playing"
readonly property bool canControl: hasPlayer && playerData.CanControl
readonly property bool canPlay: hasPlayer && playerData.CanPlay
readonly property bool canPause: hasPlayer && playerData.CanPause
readonly property bool canGoBack: hasPlayer && playerData.CanGoPrevious
readonly property bool canGoNext: hasPlayer && playerData.CanGoNext
readonly property bool canRaise: hasPlayer && playerData.CanRaise
readonly property var currentMetadata: hasPlayer ? playerData.Metadata : ({})
readonly property string track: {
var xesamTitle = currentMetadata["xesam:title"]
if (xesamTitle) {
return xesamTitle;
}
// if no track title is given, print out the file name
var xesamUrl = currentMetadata["xesam:url"] ? currentMetadata["xesam:url"].toString() : ""
if (!xesamUrl) {
return "";
}
var lastSlashPos = xesamUrl.lastIndexOf('/')
if (lastSlashPos < 0) {
return "";
}
var lastUrlPart = xesamUrl.substring(lastSlashPos + 1)
return decodeURIComponent(lastUrlPart);
}
readonly property string artist: currentMetadata["xesam:artist"] || ""
readonly property string albumArt: currentMetadata["mpris:artUrl"] || ""
//
function isTaskActive() {
return (isGroup ? isActive : (parentTask ? parentTask.isActive : false));
}
// launcher icon + text labels + close button
RowLayout {
id: header
Layout.minimumWidth: childrenRect.width
Layout.maximumWidth: Layout.minimumWidth
Layout.minimumHeight: childrenRect.height
Layout.maximumHeight: Layout.minimumHeight
anchors.horizontalCenter: parent.horizontalCenter
// launcher icon
PlasmaCore.IconItem {
Layout.preferredWidth: units.iconSizes.medium
Layout.preferredHeight: units.iconSizes.medium
source: icon
animated: false
usesPlasmaTheme: false
visible: !isWin
}
// all textlabels
Column {
PlasmaExtras.Heading {
level: 3
width: isWin ? textWidth : undefined
height: undefined
maximumLineCount: 1
elide: Text.ElideRight
text: appName
opacity: flatIndex == 0
textFormat: Text.PlainText
visible: text !== ""
}
// window title
PlasmaExtras.Heading {
id: winTitle
level: 5
width: isWin ? textWidth : undefined
height: undefined
maximumLineCount: 1
elide: Text.ElideRight
text: generateTitle()
textFormat: Text.PlainText
opacity: 0.75
visible: !hasPlayer
}
// subtext
PlasmaExtras.Heading {
level: 6
width: isWin ? textWidth : undefined
height: undefined
maximumLineCount: 1
elide: Text.ElideRight
text: isWin ? generateSubText() : ""
textFormat: Text.PlainText
opacity: 0.6
visible: text !== ""
}
}
// close button
PlasmaComponents.ToolButton {
id: closeButton
Layout.alignment: Qt.AlignRight | Qt.AlignTop
visible: isWin && !hideCloseButtons
iconSource: "window-close"
onClicked: {
backend.cancelHighlightWindows();
tasksModel.requestClose(submodelIndex);
}
}
}
// thumbnail container
Item {
id: thumbnail
+ anchors.horizontalCenter: parent.horizontalCenter
+
width: header.width
// similar to 0.5625 = 1 / (16:9) as most screens are
// round necessary, otherwise shadow mask for players has gap!
height: Math.round(0.5 * width) + (!winTitle.visible? Math.round(winTitle.height) : 0)
- anchors.horizontalCenter: parent.horizontalCenter
visible: isWin
Item {
id: thumbnailSourceItem
anchors.fill: parent
anchors.bottomMargin: 2
readonly property bool isMinimized: isGroup ? instance.isMinimized : mainToolTip.isMinimizedParent
// TODO: this causes XCB error message when being visible the first time
property int winId: isWin && windows[flatIndex] !== undefined ? windows[flatIndex] : 0
Loader{
id:previewThumbX11Loader
anchors.fill: parent
active: !LatteCore.WindowSystem.isPlatformWayland
visible: !albumArtImage.visible && !thumbnailSourceItem.isMinimized
sourceComponent: PlasmaCore.WindowThumbnail {
winId: thumbnailSourceItem.winId
}
}
ToolTipWindowMouseArea {
id: area2
anchors.fill: LatteCore.WindowSystem.isPlatformWayland ? parent : previewThumbX11Loader
rootTask: parentTask
modelIndex: submodelIndex
winId: thumbnailSourceItem.winId
}
Image {
id: albumArtBackground
source: albumArt
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
visible: albumArtImage.available
layer.enabled: true
opacity: 0.25
layer.effect: FastBlur {
source: albumArtBackground
anchors.fill: parent
radius: 30
}
}
Image {
id: albumArtImage
// also Image.Loading to prevent loading thumbnails just because the album art takes a split second to load
readonly property bool available: status === Image.Ready || status === Image.Loading
height: thumbnail.height - playbackLoader.realHeight
anchors.horizontalCenter: parent.horizontalCenter
sourceSize: Qt.size(parent.width, parent.height)
asynchronous: true
source: albumArt
fillMode: Image.PreserveAspectFit
visible: available
}
// when minimized, we don't have a preview, so show the icon
PlasmaCore.IconItem {
width: parent.width
height: thumbnail.height - playbackLoader.realHeight
anchors.horizontalCenter: parent.horizontalCenter
source: icon
animated: false
usesPlasmaTheme: false
visible: (thumbnailSourceItem.isMinimized && !albumArtImage.visible) //X11 case
|| (!previewThumbX11Loader.active && !albumArtImage.visible) //Wayland case
}
}
Loader {
id: playbackLoader
property real realHeight: item? item.realHeight : 0
anchors.fill: thumbnail
active: hasPlayer
sourceComponent: playerControlsComp
}
Component {
id: playerControlsComp
Item {
property real realHeight: playerControlsRow.height
anchors.fill: parent
// TODO: When could this really be the case? A not-launcher-task always has a window!?
// if there's no window associated with this task, we might still be able to raise the player
// MouseArea {
// id: raisePlayerArea
// anchors.fill: parent
// visible: !isWin || !windows[0] && canRaise
// onClicked: mpris2Source.raise(mprisSourceName)
// }
Item {
id: playerControlsFrostedGlass
anchors.fill: parent
visible: false // OpacityMask would render it
Rectangle {
width: parent.width
height: parent.height - playerControlsRow.height
opacity: 0
}
Rectangle {
anchors.bottom: parent.bottom
width: parent.width
height: playerControlsRow.height
color: theme.backgroundColor
opacity: 0.8
}
}
OpacityMask {
id: playerControlsOpacityMask
anchors.fill: parent
source: playerControlsFrostedGlass
maskSource: thumbnailSourceItem
}
// prevent accidental click-through when a control is disabled
MouseArea {
id: area3
anchors.fill: playerControlsRow
}
RowLayout {
id: playerControlsRow
anchors {
horizontalCenter: parent.horizontalCenter
bottom: parent.bottom
}
width: parent.width
spacing: 0
enabled: canControl
ColumnLayout {
Layout.margins: 2
Layout.fillWidth: true
spacing: 0
PlasmaComponents.Label {
Layout.fillWidth: true
lineHeight: 1
maximumLineCount: artistText.visible? 1 : 2
wrapMode: artistText.visible? Text.NoWrap : Text.Wrap
elide: Text.ElideRight
text: track || ""
}
PlasmaExtras.DescriptiveLabel {
id: artistText
Layout.fillWidth: true
wrapMode: Text.NoWrap
lineHeight: 1
elide: Text.ElideRight
text: artist || ""
visible: text != ""
font.pointSize: theme.smallestFont.pointSize
}
}
PlasmaComponents.ToolButton {
id: canGoBackButton
enabled: canGoBack
iconSource: LayoutMirroring.enabled ? "media-skip-forward" : "media-skip-backward"
onClicked: mpris2Source.goPrevious(mprisSourceName)
}
PlasmaComponents.ToolButton {
id: playingButton
enabled: playing ? canPause : canPlay
iconSource: playing ? "media-playback-pause" : "media-playback-start"
onClicked: {
if (!playing) {
mpris2Source.play(mprisSourceName);
} else {
mpris2Source.pause(mprisSourceName);
}
}
}
PlasmaComponents.ToolButton {
id: canGoNextButton
enabled: canGoNext
iconSource: LayoutMirroring.enabled ? "media-skip-backward" : "media-skip-forward"
onClicked: mpris2Source.goNext(mprisSourceName)
}
}
}
}
+ }
- //active window line
- Rectangle{
- width: parent.width
- height: 2
- color: isTaskActive() ? theme.buttonFocusColor : theme.buttonHoverColor
- anchors.bottom: parent.bottom
- visible: isTaskActive() || area2.containsMouse
- }
+ //active window line
+ Rectangle{
+ width: header.width
+ height: 3
+ opacity: isTaskActive() || area2.containsMouse ? 1 : 0 /*this way avoid trebbling when moving from task to task in groups*/
+ color: isTaskActive() ? theme.buttonFocusColor : theme.buttonHoverColor
}
function generateTitle() {
if (!isWin) {
return genericName != undefined ? genericName : "";
}
var text;
var modelExists = (typeof model !== 'undefined');
if (isGroup && modelExists) {
if (model.display === undefined) {
return "";
}
text = model.display.toString();
} else {
text = displayParent;
}
// KWin appends increasing integers in between pointy brackets to otherwise equal window titles.
// In this case save <#number> as counter and delete it at the end of text.
var counter = text.match(/<\d+>\W*$/);
text = text.replace(/\s*<\d+>\W*$/, "");
// Remove appName from the end of text.
var appNameRegex = new RegExp(appName + "$", "i");
text = text.replace(appNameRegex, "");
text = text.replace(/\s*(?:-|—)*\s*$/, "");
// Add counter back at the end.
if (counter !== null) {
if (text === "") {
text = counter;
} else {
text = text + " " + counter;
}
}
// In case the window title had only redundant information (i.e. appName), text is now empty.
// Add a hyphen to indicate that and avoid empty space.
if (text === "") {
text = "—";
}
return text.toString();
}
function generateSubText() {
if (activitiesParent === undefined) {
return "";
}
var subTextEntries = [];
var virtualDesktops = isGroup ? VirtualDesktops : virtualDesktopParent;
var virtualDesktopNameList = [];
for (var i = 0; i < virtualDesktops.length; ++i) {
virtualDesktopNameList.push(virtualDesktopInfo.desktopNames[virtualDesktops[i] - 1]);
}
if (!root.showOnlyCurrentDesktop
&& virtualDesktopInfo.numberOfDesktops > 1
&& (isGroup ? IsOnAllVirtualDesktops : isOnAllVirtualDesktopsParent) !== true
&& virtualDesktops.length > 0) {
subTextEntries.push(i18nc("Comma-separated list of desktops", "On %1", virtualDesktopNameList.join()));
}
var act = isGroup ? activities : activitiesParent;
if (act === undefined) {
return subTextEntries.join("\n");
}
if (act.length === 0 && activityInfo.numberOfRunningActivities > 1) {
subTextEntries.push(i18nc("Which virtual desktop a window is currently on",
"Available on all activities"));
} else if (act.length > 0) {
var activityNames = [];
for (var i = 0; i < act.length; i++) {
var activity = act[i];
var activityName = activityInfo.activityName(act[i]);
if (activityName === "") {
continue;
}
if (root.showOnlyCurrentActivity) {
if (activity !== activityInfo.currentActivity) {
activityNames.push(activityName);
}
} else if (activity !== activityInfo.currentActivity) {
activityNames.push(activityName);
}
}
if (root.showOnlyCurrentActivity) {
if (activityNames.length > 0) {
subTextEntries.push(i18nc("Activities a window is currently on (apart from the current one)",
"Also available on %1", activityNames.join(", ")));
}
} else if (activityNames.length > 0) {
subTextEntries.push(i18nc("Which activities a window is currently on",
"Available on %1", activityNames.join(", ")));
}
}
return subTextEntries.join("\n");
}
}
diff --git a/plasmoid/package/contents/ui/task/TaskItem.qml b/plasmoid/package/contents/ui/task/TaskItem.qml
index 4aa118d4..1bfa1205 100644
--- a/plasmoid/package/contents/ui/task/TaskItem.qml
+++ b/plasmoid/package/contents/ui/task/TaskItem.qml
@@ -1,1690 +1,1710 @@
/*
* Copyright 2016 Smith AR
* Michail Vourlakos
*
* This file is part of Latte-Dock
*
* Latte-Dock is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* Latte-Dock is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
import QtQuick 2.0
import QtQuick.Layouts 1.1
import QtGraphicalEffects 1.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet
import org.kde.latte.core 0.2 as LatteCore
import org.kde.latte.private.tasks 0.1 as LatteTasks
import "animations" as TaskAnimations
import "indicator" as Indicator
MouseArea{
id: taskItem
visible: false //true//(isStartup && animations.speedFactor.current !== 0) ? false : true
anchors.bottom: (root.location === PlasmaCore.Types.BottomEdge) ? parent.bottom : undefined
anchors.top: (root.location === PlasmaCore.Types.TopEdge) ? parent.top : undefined
anchors.left: (root.location === PlasmaCore.Types.LeftEdge) ? parent.left : undefined
anchors.right: (root.location === PlasmaCore.Types.RightEdge) ? parent.right : undefined
objectName: "TaskItem"
width: {
if (!visible)
return 0;
if (isSeparator) {
if (root.vertical) {
return taskItem.metrics.totals.thickness + taskItem.metrics.margin.screenEdge;
} else {
if (root.dragSource || !root.parabolicEffectEnabled) {
return LatteCore.Environment.separatorLength+2*taskItem.metrics.margin.length;
}
}
return 0;
}
if (root.vertical) {
return wrapper.width;
} else {
return hiddenSpacerLeft.width+wrapper.width+hiddenSpacerRight.width;
}
}
/*onWidthChanged: {
console.log("T: " + itemIndex + " - " + launcherUrl + " - " + width + " _ "+ hiddenSpacerLeft.width + " _ " + wrapper.width + " _ " + hiddenSpacerRight.width);
}*/
height: {
if (!visible)
return 0;
if (isSeparator) {
if (!root.vertical) {
return taskItem.metrics.totals.thickness + taskItem.metrics.margin.screenEdge;
} else {
if (root.dragSource || !root.parabolicEffectEnabled) {
return LatteCore.Environment.separatorLength+2*taskItem.metrics.margin.length;
}
}
return 0;
}
if (root.vertical) {
return hiddenSpacerLeft.height + wrapper.height + hiddenSpacerRight.height;
} else {
return wrapper.height;
}
}
acceptedButtons: Qt.LeftButton | Qt.MidButton | Qt.RightButton
hoverEnabled: visible && (!inAnimation) && (!IsStartup) && (!root.taskInAnimation)
&&(!inBouncingAnimation) && !isSeparator
// hoverEnabled: false
//opacity : isSeparator && (hiddenSpacerLeft.neighbourSeparator || hiddenSpacerRight.neighbourSeparator) ? 0 : 1
property bool buffersAreReady: false
property bool delayingRemove: ListView.delayRemove
property bool scalesUpdatedOnce: false
//states that exist in windows in a Group of windows
property bool hasActive: isActive
property bool hasMinimized: (IsGroupParent === true) ? subWindows.hasMinimized : isMinimized
property bool hasShown: (IsGroupParent === true) ? subWindows.hasShown : !isMinimized && isWindow
property bool inAttention: isDemandingAttention && plasmoid.status === PlasmaCore.Types.RequiresAttentionStatus ? true : false
/*animations flags*/
property bool inAnimation: true
property bool inAddRemoveAnimation: true
property bool inAttentionAnimation: false
property bool inBlockingAnimation: false
property bool inBouncingAnimation: false
property bool inFastRestoreAnimation: false
property bool inMimicParabolicAnimation: false
property bool inNewWindowAnimation: false
property real mimicParabolicScale: -1
property bool inPopup: false
property bool inRemoveStage: false
+ //! after clicking to show/hide preview enter events are trigerred even though the should not
+ property bool showPreviewsIsBlockedFromReleaseEvent: false
+
property bool isAbleToShowPreview: true
property bool isActive: (IsActive === true) ? true : false
property bool isDemandingAttention: (IsDemandingAttention === true) ? true : false
property bool isDragged: false
property bool isGroupable: (IsGroupable === true) ? true : false
property bool isGroupParent: (IsGroupParent === true) ? true : false
readonly property bool isHidden: !visible || isForcedHidden
property bool isForcedHidden: false
property bool isLauncher: (IsLauncher === true) ? true : false
property bool isMinimized: (IsMinimized === true) ? true : false
property bool isSeparator: false
property bool isStartup: (IsStartup === true) ? true : false
property bool isWindow: (IsWindow === true) ? true : false
property bool isZoomed: false
property bool canPublishGeometries: (isWindow || isStartup || isGroupParent) && visible && width>=taskItem.metrics.iconSize && height>=taskItem.metrics.iconSize
&& !taskItem.delayingRemove
&& (wrapper.mScale===1 || wrapper.mScale===taskItem.parabolic.factor.zoom) //don't publish during zoom animation
property bool hoveredFromDragging: (mouseHandler.hoveredItem === taskItem) || (mouseHandler.ignoredItem === taskItem)
property bool pressed: false
property bool wheelIsBlocked: false
property int animationTime: (taskItem.animations.active ? taskItem.animations.speedFactor.current : 2) * (1.2 *taskItem.animations.duration.small)
property int badgeIndicator: 0 //it is used from external apps
property int itemIndex: index
property int lastValidIndex: -1 //used for the removal animation
property int lastButtonClicked: -1;
property int pressX: -1
property int pressY: -1
property int resistanceDelay: 450
property int spacersMaxSize: Math.max(0,Math.ceil(0.55*taskItem.metrics.iconSize) - taskItem.metrics.totals.lengthEdges)
property int windowsCount: subWindows.windowsCount
property int windowsMinimizedCount: subWindows.windowsMinimized
//! are set by the indicator
property int iconOffsetX: 0
property int iconOffsetY: 0
property string activity: tasksModel.activity
readonly property var m: model
readonly property int pid: model && model.AppPid ? model.AppPid : -1
readonly property string appName: model && model.AppName ? model.AppName : ""
property string modelLauncherUrl: (LauncherUrlWithoutIcon && LauncherUrlWithoutIcon !== null) ? LauncherUrlWithoutIcon : ""
property string modelLauncherUrlWithIcon: (LauncherUrl && LauncherUrl !== null) ? LauncherUrl : ""
property string launcherUrl: ""
property string launcherUrlWithIcon: ""
property string launcherName: ""
property Item tooltipVisualParent: wrapper.titleTooltipVisualParent
property Item previewsVisualParent: wrapper.previewsTooltipVisualParent
property Item wrapperAlias: wrapper
//abilities
property Item animations: null
property Item indexer: null
property Item launchers: null
property Item metrics: null
property Item parabolic: null
property Item requires: null
property Item shortcuts: null
onModelLauncherUrlChanged: {
if (modelLauncherUrl !== ""){
launcherUrl = modelLauncherUrl;
//!extract the launcherName if possible
var nameStarts = launcherUrl.lastIndexOf("/");
if (nameStarts === -1){
nameStarts = launcherUrl.lastIndexOf(":");
}
var nameEnds = launcherUrl.lastIndexOf(".desktop");
if (nameStarts!==-1 && nameEnds!==-1 && nameStarts=0 && taskItem.indexer.hidden.indexOf(tail)>=0) {
tail = tail - 1;
}
var hasTailItemSeparator = taskItem.indexer.separators.indexOf(tail)>=0;
if (!hasTailItemSeparator && itemIndex === taskItem.indexer.firstVisibleItemIndex){
return taskItem.indexer.tailAppletIsSeparator;
}
return hasTailItemSeparator;
}
readonly property bool headItemIsSeparator: {
if (isSeparator || itemIndex < 0 ) {
return false;
}
var head = index + 1;
while(head>=0 && taskItem.indexer.hidden.indexOf(head)>=0) {
head = head + 1;
}
var hasHeadItemSeparator = taskItem.indexer.separators.indexOf(head)>=0;
if (!hasHeadItemSeparator && itemIndex === taskItem.indexer.lastVisibleItemIndex){
return taskItem.indexer.headAppletIsSeparator;
}
return hasHeadItemSeparator;
}
////// Audio streams //////
property Item audioStreamOverlay
property var audioStreams: []
readonly property bool hasAudioStream: root.showAudioBadge && audioStreams.length > 0 && !isLauncher
readonly property bool playingAudio: hasAudioStream && audioStreams.some(function (item) {
return !item.corked
})
readonly property bool muted: hasAudioStream && audioStreams.every(function (item) {
return item.muted
})
readonly property int volume: {
if (!hasAudioStream){
return 0;
}
var maxVolume = 0;
for (var i=0; i maxVolume)
maxVolume = audioStreams[i].volume;
}
return maxVolume;
}
//////
property QtObject contextMenu: null
property QtObject draggingResistaner: null
property QtObject hoveredTimerObj: null
signal groupWindowAdded();
signal groupWindowRemoved();
signal checkWindowsStates();
Behavior on opacity {
// NumberAnimation { duration: (IsStartup || (IsLauncher) ) ? 0 : 400 }
NumberAnimation { duration: taskItem.animations.speedFactor.current * taskItem.animations.duration.large }
}
Loader{
anchors.fill: parent
active: latteView && latteView.debugMode
sourceComponent: Rectangle{
anchors.fill: parent
color: "transparent"
border.color: "blue"
border.width: 1
}
}
SubWindows{
id: subWindows
property int previousCount: 0
onWindowsCountChanged: {
if (root.disableAllWindowsFunctionality) {
return;
}
if ((windowsCount >= 2)
&& (windowsCount > previousCount)
&& !(taskItem.containsMouse)
&& !root.dragSource ){
taskItem.groupWindowAdded();
} else if ((windowsCount >= 1)
- && (windowsCount < previousCount)
- && !root.dragSource
- && !taskItem.delayingRemove){
+ && (windowsCount < previousCount)
+ && !root.dragSource
+ && !taskItem.delayingRemove){
//sometimes this is triggered in dragging with no reason
taskItem.groupWindowRemoved();
}
if (windowsCount>=1) {
taskItem.slotPublishGeometries();
}
//! workaround in order to update correctly the previousCount
//! windowsCount can not return to zero because is such case
//! the window task is removed and the launcher is added from
//! libtaskmanager
if (windowsCount>=1) {
previousCount = windowsCount;
}
}
}
Loader {
id: isSeparatorRectangle
active: (opacityN>0)
width: taskItem.width
height: taskItem.height
anchors.centerIn: separatorItem
property real opacityN: isSeparator && root.contextMenu && root.contextMenu.visualParent === taskItem ? 1 : 0
Behavior on opacityN {
NumberAnimation { duration: taskItem.animations.speedFactor.current * taskItem.animations.duration.large }
}
sourceComponent: Rectangle{
anchors.fill: parent
opacity: isSeparatorRectangle.opacityN
radius: 3
property color tempColor: theme.highlightColor
color: tempColor
border.width: 1
border.color: theme.highlightColor
onTempColorChanged: tempColor.a = 0.35;
}
}
Item{
id:separatorItem
anchors.bottom: (root.location === PlasmaCore.Types.BottomEdge) ? parent.bottom : undefined
anchors.top: (root.location === PlasmaCore.Types.TopEdge) ? parent.top : undefined
anchors.left: (root.location === PlasmaCore.Types.LeftEdge) ? parent.left : undefined
anchors.right: (root.location === PlasmaCore.Types.RightEdge) ? parent.right : undefined
anchors.horizontalCenter: !root.vertical ? parent.horizontalCenter : undefined
anchors.verticalCenter: root.vertical ? parent.verticalCenter : undefined
anchors.bottomMargin: (root.location === PlasmaCore.Types.BottomEdge) ? margin : 0
anchors.topMargin: (root.location === PlasmaCore.Types.TopEdge) ? margin : 0
anchors.leftMargin: (root.location === PlasmaCore.Types.LeftEdge) ? margin : 0
anchors.rightMargin: (root.location === PlasmaCore.Types.RightEdge) ? margin : 0
opacity: (separatorShadow.active) || forceHiddenState ? 0 : 0.4
visible: taskItem.isSeparator
width: root.vertical ? taskItem.metrics.iconSize : ((root.dragSource || root.editMode) ? LatteCore.Environment.separatorLength+taskItem.metrics.totals.lengthEdges: 1)
height: !root.vertical ? taskItem.metrics.iconSize : ((root.dragSource || root.editMode) ? LatteCore.Environment.separatorLength+taskItem.metrics.totals.lengthEdges: 1)
property bool forceHiddenState: false
readonly property int margin: taskItem.metrics.margin.screenEdge + metrics.margin.thickness
Behavior on opacity {
NumberAnimation { duration: taskItem.animations.speedFactor.current * taskItem.animations.duration.large }
}
Connections{
target: root
//! During dock sliding-in because the parabolic effect isnt trigerred
//! immediately but we wait first the dock to go to its final normal
//! place we might miss the activation of the parabolic effect.
//! By catching that signal we are trying to solve this.
onDockIsShownCompletelyChanged: {
if (dockIsShownCompletely && taskItem.containsMouse) {
if (root.vertical) {
taskItem.mousePosChanged(taskItem.mouseY);
} else {
taskItem.mousePosChanged(taskItem.mouseX);
}
}
}
onDisableAllWindowsFunctionalityChanged: {
if (!root.editMode) {
return;
}
taskItem.updateVisibilityBasedOnLaunchers();
}
onShowWindowsOnlyFromLaunchersChanged: {
if (!root.editMode) {
return;
}
taskItem.updateVisibilityBasedOnLaunchers();
}
onInActivityChangeChanged: {
if ((root.showWindowsOnlyFromLaunchers || root.disableAllWindowsFunctionality) && !root.inActivityChange) {
taskItem.updateVisibilityBasedOnLaunchers();
}
}
}
Rectangle {
anchors.centerIn: parent
width: root.vertical ? taskItem.metrics.iconSize - 4 : 1
height: !root.vertical ? taskItem.metrics.iconSize - 4 : 1
color: enforceLattePalette ? latteBridge.palette.textColor : theme.textColor
}
}
///Shadow in tasks
Loader{
id: separatorShadow
anchors.fill: separatorItem
active: root.enableShadows && isSeparator && graphicsSystem.isAccelerated
opacity: separatorItem.forceHiddenState ? 0 : 0.4
Behavior on opacity {
NumberAnimation { duration: taskItem.animations.speedFactor.current * taskItem.animations.duration.large }
}
sourceComponent: DropShadow{
anchors.fill: parent
color: root.appShadowColor
fast: true
samples: 2 * radius
source: separatorItem
radius: root.appShadowSize
verticalOffset: 2
}
}
/* Rectangle{
anchors.fill: parent
color: "transparent"
border.width: 1
border.color: "blue"
} */
Flow{
id: taskFlow
width: parent.width
height: parent.height
// a hidden spacer for the first element to add stability
// IMPORTANT: hidden spacers must be tested on vertical !!!
HiddenSpacer{ id:hiddenSpacerLeft;}
Item{
width: wrapper.width
height: wrapper.height
Indicator.Bridge{
id: indicatorBridge
}
Indicator.Loader{
id: indicatorBackLayer
level: Indicator.LevelOptions {
id: backLevelOptions
isBackground: true
bridge: indicatorBridge
Binding {
target: taskItem
property: "iconOffsetX"
value: backLevelOptions.requested.iconOffsetX
}
Binding {
target: taskItem
property: "iconOffsetY"
value: backLevelOptions.requested.iconOffsetY
}
}
}
Wrapper{id: wrapper}
Indicator.Loader{
id: indicatorFrontLayer
level: Indicator.LevelOptions {
isForeground: true
bridge: indicatorBridge
}
}
}
// a hidden spacer on the right for the last item to add stability
HiddenSpacer{ id:hiddenSpacerRight; rightSpacer: true }
}// Flow with hidden spacers inside
Component {
id: taskInitComponent
Timer {
id: timer
interval: 800
repeat: false
onTriggered: {
// taskItem.hoverEnabled = true;
slotPublishGeometries();
if (latteView && latteView.debugModeTimers) {
console.log("plasmoid timer: taskInitComponentTimer called...");
}
timer.destroy();
}
Component.onCompleted: timer.start()
}
}
////// Values Changes /////
//restore scales when there is no zoom factor for that item or
//the mouse is out of the ListView
// onItemIndexChanged: {
// }
onAppNameChanged: updateAudioStreams()
onPidChanged: updateAudioStreams()
onHasAudioStreamChanged: updateAudioStreams()
onCanPublishGeometriesChanged: {
if (canPublishGeometries) {
slotPublishGeometries();
taskInitComponent.createObject(taskItem);
}
}
onItemIndexChanged: {
if (itemIndex>=0) {
lastValidTimer.start();
}
}
onIsDraggedChanged: {
if(isDragged && (!root.inConfigureAppletsMode)){
root.dragSource = taskItem;
dragHelper.startDrag(taskItem, model.MimeType, model.MimeData,
model.LauncherUrlWithoutIcon, model.decoration);
pressX = -1;
pressY = -1;
}
}
onIsMinimizedChanged: {
checkWindowsStates();
}
onIsActiveChanged: {
checkWindowsStates();
if (isActive) {
scrollableList.focusOn(taskItem);
}
}
onIsSeparatorChanged: {
if (isSeparator) {
if (tasksExtendedManager.isLauncherToBeMoved(launcherUrl) && itemIndex>=0) {
tasksExtendedManager.moveLauncherToCorrectPos(launcherUrl, itemIndex);
}
}
}
onLauncherUrlChanged: updateBadge();
////// End of Values Changes /////
///////////////// Mouse Area Events ///////////////////
onEntered: {
taskItem.parabolic.stopRestoreZoomTimer();
restoreAnimation.stop();
if ((taskItem.parabolic.local.lastIndex !== itemIndex) && isLauncher && windowsPreviewDlg.visible) {
windowsPreviewDlg.hide(1);
}
if (root.latteView && !root.showPreviews && root.titleTooltips){
showTitleTooltip();
}
//! show previews if enabled
- if(isAbleToShowPreview && ((root.showPreviews && windowsPreviewDlg.activeItem !== taskItem) || root.highlightWindows)){
+ if(isAbleToShowPreview && !showPreviewsIsBlockedFromReleaseEvent
+ && (((root.showPreviews || (windowsPreviewDlg.visible && !isLauncher))
+ && windowsPreviewDlg.activeItem !== taskItem)
+ || root.highlightWindows)){
if (hoveredTimerObj) {
//! don't delay showing preview in normal states,
//! that is when the dock wasn't hidden
if (!hoveredTimerObj.running) {
hoveredTimerObj.start();
}
} else {
if (!root.disableAllWindowsFunctionality) {
hoveredTimerObj = hoveredTimerComponent.createObject(taskItem);
}
}
}
+ showPreviewsIsBlockedFromReleaseEvent = false;
+
if (root.autoScrollTasksEnabled) {
scrollableList.autoScrollFor(taskItem, false);
}
if (root.latteView && root.latteView.isHalfShown) {
return;
}
}
// IMPORTANT: This must be improved ! even for small milliseconds it reduces performance
onExited: {
scalesUpdatedOnce = false;
isAbleToShowPreview = true;
if (root.latteView && (!root.showPreviews || (root.showPreviews && isLauncher))){
root.latteView.hideTooltipLabel();
}
if (root.showPreviews) {
root.hidePreview(17.5);
}
if (taskItem.parabolic.factor.zoom>1){
taskItem.parabolic.startRestoreZoomTimer();
}
}
//! mouseX-Y values are delayed to be updated onEntered events and at the same time
//! onPositionChanged signal may be delayed. we can fix this by don't delay at all
//! when mouseX-Y is updated based on the plasmoid formFactor
function mousePosChanged(mousePos) {
if (mousePos<0 ||
(inBlockingAnimation && !(inAttentionAnimation||inFastRestoreAnimation||inMimicParabolicAnimation)))
return;
if (root.latteView && root.latteView.isHalfShown) {
return;
}
if((inAnimation == false)&&(!root.taskInAnimation)&&(!root.disableRestoreZoom) && hoverEnabled){
var rapidMovement = taskItem.parabolic.local.lastIndex>=0 && Math.abs(taskItem.parabolic.local.lastIndex-itemIndex)>1;
if (rapidMovement) {
taskItem.parabolic.setDirectRenderingEnabled(true);
}
if( ((wrapper.mScale == 1 || wrapper.mScale === taskItem.parabolic.factor.zoom) && !taskItem.parabolic.directRenderingEnabled)
|| taskItem.parabolic.directRenderingEnabled || !scalesUpdatedOnce) {
if(root.dragSource == null){
var step = Math.abs(icList.currentSpot-mousePos);
if (step >= taskItem.animations.hoverPixelSensitivity){
icList.currentSpot = mousePos;
wrapper.calculateParabolicScales(mousePos);
}
}
}
}
}
onMouseXChanged: {
if (!root.vertical) {
mousePosChanged(mouseX);
}
}
onMouseYChanged: {
if (root.vertical) {
mousePosChanged(mouseY);
}
}
onPositionChanged: {
if ((inBlockingAnimation && !(inAttentionAnimation||inFastRestoreAnimation||inMimicParabolicAnimation)))
return;
if (root.latteView && root.latteView.isHalfShown) {
return;
}
if((inAnimation == false)&&(!root.taskInAnimation)&&(!root.disableRestoreZoom) && hoverEnabled){
// mouse.button is always 0 here, hence checking with mouse.buttons
if (pressX != -1 && mouse.buttons == Qt.LeftButton
&& isDragged
&& dragHelper.isDrag(pressX, pressY, mouse.x, mouse.y) ) {
root.dragSource = taskItem;
dragHelper.startDrag(taskItem, model.MimeType, model.MimeData,
model.LauncherUrlWithoutIcon, model.decoration);
pressX = -1;
pressY = -1;
}
}
}
onContainsMouseChanged:{
if(!containsMouse && !inAnimation) {
pressed=false;
}
////disable hover effect///
if (isWindow && root.highlightWindows && !containsMouse) {
root.windowsHovered( root.plasma515 ? model.WinIdList : model.LegacyWinIdList , false);
}
}
onPressed: {
//console.log("Pressed Task Delegate..");
if (LatteCore.WindowSystem.compositingActive && !LatteCore.WindowSystem.isPlatformWayland) {
if(root.leftClickAction !== LatteTasks.Types.PreviewWindows) {
isAbleToShowPreview = false;
windowsPreviewDlg.hide(2);
}
}
slotPublishGeometries();
var modAccepted = modifierAccepted(mouse);
if ((mouse.button == Qt.LeftButton)||(mouse.button == Qt.MidButton) || modAccepted) {
lastButtonClicked = mouse.button;
pressed = true;
pressX = mouse.x;
pressY = mouse.y;
if(draggingResistaner == null && !modAccepted)
draggingResistaner = resistanerTimerComponent.createObject(taskItem);
}
else if (mouse.button == Qt.RightButton && !modAccepted){
// When we're a launcher, there's no window controls, so we can show all
// places without the menu getting super huge.
if (model.IsLauncher === true && !isSeparator) {
showContextMenu({showAllPlaces: true})
} else {
showContextMenu();
}
}
}
onReleased: {
//console.log("Released Task Delegate...");
if (draggingResistaner != null){
draggingResistaner.destroy();
draggingResistaner = null;
}
if(pressed && (!inBlockingAnimation || inAttentionAnimation) && !isSeparator){
if (modifierAccepted(mouse) && !root.disableAllWindowsFunctionality){
if( !taskItem.isLauncher ){
if (root.modifierClickAction == LatteTasks.Types.NewInstance) {
tasksModel.requestNewInstance(modelIndex());
} else if (root.modifierClickAction == LatteTasks.Types.Close) {
tasksModel.requestClose(modelIndex());
} else if (root.modifierClickAction == LatteTasks.Types.ToggleMinimized) {
tasksModel.requestToggleMinimized(modelIndex());
} else if ( root.modifierClickAction == LatteTasks.Types.CycleThroughTasks) {
if (isGroupParent)
subWindows.activateNextTask();
else
activateTask();
} else if (root.modifierClickAction == LatteTasks.Types.ToggleGrouping) {
tasksModel.requestToggleGrouping(modelIndex());
}
} else {
activateTask();
}
} else if (mouse.button == Qt.MidButton && !root.disableAllWindowsFunctionality){
if( !taskItem.isLauncher ){
if (root.middleClickAction == LatteTasks.Types.NewInstance) {
tasksModel.requestNewInstance(modelIndex());
} else if (root.middleClickAction == LatteTasks.Types.Close) {
tasksModel.requestClose(modelIndex());
} else if (root.middleClickAction == LatteTasks.Types.ToggleMinimized) {
tasksModel.requestToggleMinimized(modelIndex());
} else if ( root.middleClickAction == LatteTasks.Types.CycleThroughTasks) {
if (isGroupParent)
subWindows.activateNextTask();
else
activateTask();
} else if (root.middleClickAction == LatteTasks.Types.ToggleGrouping) {
tasksModel.requestToggleGrouping(modelIndex());
}
} else {
activateTask();
}
} else if (mouse.button == Qt.LeftButton){
if( !taskItem.isLauncher && !root.disableAllWindowsFunctionality ){
if ( (root.leftClickAction === LatteTasks.Types.PreviewWindows && isGroupParent)
|| ( (LatteCore.WindowSystem.isPlatformWayland || !LatteCore.WindowSystem.compositingActive)
&& root.leftClickAction === LatteTasks.Types.PresentWindows
&& isGroupParent) ) {
if(windowsPreviewDlg.activeItem !== taskItem || !windowsPreviewDlg.visible){
showPreviewWindow();
} else {
- root.forcePreviewsHiding(21.1);
+ forceHidePreview(21.1);
}
} else if ( (root.leftClickAction === LatteTasks.Types.PresentWindows && !(isGroupParent && !LatteCore.WindowSystem.compositingActive))
|| ((root.leftClickAction === LatteTasks.Types.PreviewWindows && !isGroupParent)) ) {
activateTask();
} else if (root.leftClickAction === LatteTasks.Types.CycleThroughTasks) {
if (isGroupParent)
subWindows.activateNextTask();
else
activateTask();
}
} else {
activateTask();
}
}
backend.cancelHighlightWindows();
}
pressed = false;
}
onWheel: {
var wheelActionsEnabled = (root.taskScrollAction !== LatteTasks.Types.ScrollNone || manualScrollTasksEnabled);
if (isSeparator
|| wheelIsBlocked
|| !wheelActionsEnabled
|| inBouncingAnimation
|| (latteView && (latteView.dockIsHidden || latteView.inSlidingIn || latteView.inSlidingOut))){
return;
}
var angleVertical = wheel.angleDelta.y / 8;
var angleHorizontal = wheel.angleDelta.x / 8;
wheelIsBlocked = true;
scrollDelayer.start();
var verticalDirection = (Math.abs(angleVertical) > Math.abs(angleHorizontal));
var mainAngle = verticalDirection ? angleVertical : angleHorizontal;
var positiveDirection = (mainAngle > 12);
var negativeDirection = (mainAngle < -12);
var parallelScrolling = (verticalDirection && plasmoid.formFactor === PlasmaCore.Types.Vertical)
|| (!verticalDirection && plasmoid.formFactor === PlasmaCore.Types.Horizontal);
if (positiveDirection) {
slotPublishGeometries();
var overflowScrollingAccepted = (root.manualScrollTasksEnabled
&& scrollableList.contentsExceed
&& (root.manualScrollTasksType === LatteTasks.Types.ManualScrollVerticalHorizontal
|| (root.manualScrollTasksType === LatteTasks.Types.ManualScrollOnlyParallel && parallelScrolling)) );
if (overflowScrollingAccepted) {
scrollableList.decreasePos();
} else {
if (isLauncher || root.disableAllWindowsFunctionality) {
wrapper.runLauncherAnimation();
} else if (isGroupParent) {
subWindows.activateNextTask();
} else {
var taskIndex = modelIndex();
if (isMinimized) {
tasksModel.requestToggleMinimized(taskIndex);
}
tasksModel.requestActivate(taskIndex);
}
// hidePreviewWindow();
}
} else if (negativeDirection) {
slotPublishGeometries();
var overflowScrollingAccepted = (root.manualScrollTasksEnabled
&& scrollableList.contentsExceed
&& (root.manualScrollTasksType === LatteTasks.Types.ManualScrollVerticalHorizontal
|| (root.manualScrollTasksType === LatteTasks.Types.ManualScrollOnlyParallel && parallelScrolling)) );
if (overflowScrollingAccepted) {
scrollableList.increasePos();
} else {
if (isLauncher || root.disableAllWindowsFunctionality) {
// do nothing
} else if (isGroupParent) {
if (root.taskScrollAction === LatteTasks.Types.ScrollToggleMinimized) {
subWindows.minimizeTask();
} else {
subWindows.activatePreviousTask();
}
} else {
var taskIndex = modelIndex();
var hidingTask = (!isMinimized && root.taskScrollAction === LatteTasks.Types.ScrollToggleMinimized);
if (isMinimized || hidingTask) {
tasksModel.requestToggleMinimized(taskIndex);
}
if (!hidingTask) {
tasksModel.requestActivate(taskIndex);
}
}
// hidePreviewWindow();
}
}
}
//! A timer is needed in order to handle also touchpads that probably
//! send too many signals very fast. This way the signals per sec are limited.
//! The user needs to have a steady normal scroll in order to not
//! notice a annoying delay
Timer{
id: scrollDelayer
interval: 400
onTriggered: taskItem.wheelIsBlocked = false;
}
///////////////// End Of Mouse Area Events ///////////////////
///// Handlers for Signals /////
function animationStarted(){
// console.log("Animation started: " + index);
inAnimation = true;
}
function animationEnded(){
// console.log("Animation ended: " + index);
inAnimation = false;
}
function sltClearZoom(){
restoreAnimation.start();
}
function handlerDraggingFinished(){
isDragged = false;
}
///// End of Handlers //////
///// Helper functions /////
function activateNextTask() {
subWindows.activateNextTask();
}
function activateTask() {
if( taskItem.isLauncher || root.disableAllWindowsFunctionality){
if (LatteCore.WindowSystem.compositingActive) {
wrapper.runLauncherAnimation();
} else {
launcherAction();
}
- }
- else{
+ } else{
if (model.IsGroupParent) {
if (LatteCore.WindowSystem.compositingActive && backend.canPresentWindows()) {
root.presentWindows(root.plasma515 ? model.WinIdList: model.LegacyWinIdList );
}
} else {
+ if (windowsPreviewDlg.visible) {
+ forceHidePreview(8.3);
+ }
+
if (isMinimized) {
var i = modelIndex();
tasksModel.requestToggleMinimized(i);
tasksModel.requestActivate(i);
} else if (isActive) {
tasksModel.requestToggleMinimized(modelIndex());
} else {
tasksModel.requestActivate(modelIndex());
}
}
}
}
+ function forceHidePreview(debugtext) {
+ showPreviewsIsBlockedFromReleaseEvent = true;
+ if (hoveredTimerObj) {
+ hoveredTimerObj.stop();
+ }
+
+ root.forcePreviewsHiding(debugtext);
+ }
+
function showPreviewWindow() {
if (root.disableAllWindowsFunctionality || !isAbleToShowPreview) {
return;
}
if(windowsPreviewDlg.activeItem !== taskItem){
if (!root.latteView
|| (root.latteView && !root.latteView.isHalfShown && !root.latteView.inSlidingIn && !root.latteView.inSlidingOut)) {
if (root.latteView && root.titleTooltips) {
root.latteView.hideTooltipLabel();
}
taskItem.preparePreviewWindow(false);
windowsPreviewDlg.show(taskItem);
}
}
}
function showTitleTooltip() {
if (root.latteView && root.titleTooltips){
var displayText = isWindow ? model.display : model.AppName;
var maxCharacters = 80;
var fixedDisplayText = displayText.length>maxCharacters ? displayText.substring(0,maxCharacters-1) + "..." : displayText;
root.latteView.showTooltipLabel(taskItem, fixedDisplayText);
}
}
function hidePreviewWindow() {
if(windowsPreviewDlg.activeItem === taskItem){
windowsPreviewDlg.hide("14.1");
if (root.latteView && root.titleTooltips && containsMouse) {
showTitleTooltip();
}
}
}
function preparePreviewWindow(hideClose){
windowsPreviewDlg.visualParent = previewsVisualParent;
toolTipDelegate.parentTask = taskItem;
//! WORKAROUND, in order for toolTipDelegate to re-instantiate the previews model when
//! previews are changing from single instance preview to another single instance
toolTipDelegate.rootIndex = undefined;
toolTipDelegate.rootIndex = tasksModel.makeModelIndex(itemIndex, -1);
toolTipDelegate.hideCloseButtons = hideClose;
toolTipDelegate.appName = Qt.binding(function() {
return model.AppName;
});
if (!isLauncher) {
toolTipDelegate.pidParent = Qt.binding(function() {
return model.AppPid;
});
} else {
toolTipDelegate.pidParent = -1;
}
toolTipDelegate.windows = Qt.binding(function() {
return root.plasma515 ? model.WinIdList : model.LegacyWinIdList ;
});
toolTipDelegate.isGroup = Qt.binding(function() {
return model.IsGroupParent == true;
});
toolTipDelegate.icon = Qt.binding(function() {
return model.decoration;
});
toolTipDelegate.launcherUrl = Qt.binding(function() {
return model.LauncherUrlWithoutIcon;
});
toolTipDelegate.isLauncher = Qt.binding(function() {
return model.IsLauncher == true;
});
toolTipDelegate.isMinimizedParent = Qt.binding(function() {
return model.IsMinimized == true;
});
toolTipDelegate.displayParent = Qt.binding(function() {
return model.display;
});
toolTipDelegate.genericName = Qt.binding(function() {
return model.GenericName;
});
toolTipDelegate.virtualDesktopParent = Qt.binding(function() {
return (model.VirtualDesktops !== undefined && model.VirtualDesktops.length > 0) ? model.VirtualDesktops : [0];
});
toolTipDelegate.isOnAllVirtualDesktopsParent = Qt.binding(function() {
return model.IsOnAllVirtualDesktops == true;
});
toolTipDelegate.activitiesParent = Qt.binding(function() {
return model.Activities;
});
}
function launcherAction(){
// if ((lastButtonClicked == Qt.LeftButton)||(lastButtonClicked == Qt.MidButton)){
if (LatteCore.WindowSystem.compositingActive) {
inBouncingAnimation = true;
tasksExtendedManager.addWaitingLauncher(taskItem.launcherUrl);
}
if (root.disableAllWindowsFunctionality) {
tasksModel.requestNewInstance(modelIndex());
} else {
tasksModel.requestActivate(modelIndex());
}
}
///window previews///
function generateSubText(task) {
var subTextEntries = new Array();
if (!plasmoid.configuration.showOnlyCurrentDesktop
&& virtualDesktopInfo.numberOfDesktops > 1
&& model.IsOnAllVirtualDesktops !== true
&& model.VirtualDesktop != -1
&& model.VirtualDesktop != undefined) {
subTextEntries.push(i18n("On %1", virtualDesktopInfo.desktopNames[model.VirtualDesktop - 1]));
}
if (model.Activities == undefined) {
return subTextEntries.join("\n");
}
if (model.Activities.length == 0 && activityInfo.numberOfRunningActivities > 1) {
subTextEntries.push(i18nc("Which virtual desktop a window is currently on",
"Available on all activities"));
} else if (model.Activities.length > 0) {
var activityNames = new Array();
for (var i = 0; i < model.Activities.length; i++) {
var activity = model.Activities[i];
if (plasmoid.configuration.showOnlyCurrentActivity) {
if (activity != activityInfo.currentActivity) {
activityNames.push(activityInfo.activityName(model.Activities[i]));
}
} else if (activity != activityInfo.currentActivity) {
activityNames.push(activityInfo.activityName(model.Activities[i]));
}
}
if (plasmoid.configuration.showOnlyCurrentActivity) {
if (activityNames.length > 0) {
subTextEntries.push(i18nc("Activities a window is currently on (apart from the current one)",
"Also available on %1", activityNames.join(", ")));
}
} else if (activityNames.length > 0) {
subTextEntries.push(i18nc("Which activities a window is currently on",
"Available on %1", activityNames.join(", ")));
}
}
return subTextEntries.join("\n");
}
///window previews////
function modelIndex(){
return tasksModel.makeModelIndex(index);
}
function showContextMenu(args) {
if (isSeparator && !root.editMode)
return;
if (!root.contextMenu) {
contextMenu = root.createContextMenu(taskItem, modelIndex(), args);
contextMenu.show();
} else {
//! make sure that context menu isnt deleted multiple times and creates a crash
//! bug case: 397635
var cMenu = root.contextMenu;
root.contextMenu = null;
cMenu.destroy();
}
}
function modifierAccepted(mouse){
if (mouse.modifiers & root.modifierQt){
if ((mouse.button === Qt.LeftButton && root.modifierClick === LatteTasks.Types.LeftClick)
|| (mouse.button === Qt.MiddleButton && root.modifierClick === LatteTasks.Types.MiddleClick)
|| (mouse.button === Qt.RightButton && root.modifierClick === LatteTasks.Types.RightClick))
return true;
}
return false;
}
function setBlockingAnimation(value){
inBlockingAnimation = value;
}
function slotMimicEnterForParabolic(){
if (containsMouse) {
if (inMimicParabolicAnimation) {
mimicParabolicScale = taskItem.parabolic.factor.zoom;
}
wrapper.calculateParabolicScales(icList.currentSpot);
}
}
function slotShowPreviewForTasks(group) {
if (group === taskItem && !windowsPreviewDlg.visible) {
preparePreviewWindow(true);
windowsPreviewDlg.show(taskItem);
}
}
function slotPublishGeometries() {
//! this way we make sure that layouts that are in different activities that the current layout
//! don't publish their geometries
if ( canPublishGeometries && (!latteView || root.viewLayoutIsCurrent)) {
var globalChoords = backend.globalRect(wrapper.visualIconItem);
var limits = backend.globalRect(scrollableList);
//! Limit the published geometries boundaries at scrolling area boundaries
var adjX = Math.min(limits.x+limits.width, Math.max(limits.x, globalChoords.x));
var adjY = Math.min(limits.y+limits.height, Math.max(limits.y, globalChoords.y));
var length = taskItem.metrics.iconSize * wrapper.mScale;
var thickness = length;
//! Magic Lamp effect doesn't like coordinates outside the screen and
//! width,heights of zero value... So we now normalize the geometries
//! sent in order to avoid such circumstances
if (root.vertical) {
if (adjY !== globalChoords.y) {
if (((globalChoords.y+globalChoords.height) < limits.y) || (globalChoords.y)>(limits.y+limits.height)) {
//! totally out of boundaries
length = 4;
} else {
//! semi-part out of boundaries
length = Math.max(4, Math.abs(adjY - globalChoords.y));
}
globalChoords.height = length;
}
} else {
if (adjX !== globalChoords.x) {
if (((globalChoords.x+globalChoords.width) < limits.x) || (globalChoords.x)>(limits.x+limits.width)) {
//! totally out of boundaries
length = 4;
} else {
//! semi-part out of boundaries
length = Math.max(4, Math.abs(adjX - globalChoords.x));
}
globalChoords.width = length;
}
}
globalChoords.x = adjX;
globalChoords.y = adjY;
if (latteView && latteView.dockIsHidden) {
if (root.location === PlasmaCore.Types.BottomEdge) {
globalChoords.y = root.screenGeometry.y+root.screenGeometry.height-1;
globalChoords.height = 1;
} else if (root.location === PlasmaCore.Types.TopEdge) {
globalChoords.y = root.screenGeometry.y+1;
globalChoords.height = 1;
} else if (root.location === PlasmaCore.Types.LeftEdge) {
globalChoords.x = root.screenGeometry.x+1;
globalChoords.width = 1;
} else if (root.location === PlasmaCore.Types.RightEdge) {
globalChoords.x = root.screenGeometry.x+root.screenGeometry.width - 1;
globalChoords.width = 1;
}
}
tasksModel.requestPublishDelegateGeometry(taskItem.modelIndex(), globalChoords, taskItem);
}
}
function slotWaitingLauncherRemoved(launch) {
if ((isWindow || isStartup || isLauncher) && !visible && launch === launcherUrl) {
wrapper.mScale = 1;
visible = true;
}
}
function updateAudioStreams() {
if (root.dragSource !== null) {
audioStreams = [];
return;
}
var pa = pulseAudio.item;
if (!pa) {
audioStreams = [];
return;
}
var streams = pa.streamsForPid(taskItem.pid);
if (streams.length) {
pa.registerPidMatch(taskItem.appName);
} else {
// We only want to fall back to appName matching if we never managed to map
// a PID to an audio stream window. Otherwise if you have two instances of
// an application, one playing and the other not, it will look up appName
// for the non-playing instance and erroneously show an indicator on both.
if (!pa.hasPidMatch(taskItem.appName)) {
var streams_result;
streams_result = pa.streamsForAppName(taskItem.appName);
if (streams_result.length===0 && launcherName !== "") {
streams_result = pa.streamsForAppName(launcherName);
}
streams = streams_result;
}
}
// fix a binding loop concerning audiostreams, the audiostreams
// should be updated only when they have changed
var changed = false;
if (streams.length !== audioStreams.length) {
changed = true;
} else {
for(var i=0; i= 0){
taskItem.lastValidIndex = taskItem.itemIndex;
}
if (latteView && latteView.debugModeTimers) {
console.log("plasmoid timer: lastValidTimer called...");
}
}
}
///Item's Removal Animation
ListView.onRemove: TaskAnimations.RealRemovalAnimation{ id: taskRealRemovalAnimation }
}// main Item
diff --git a/shell/package/contents/configuration/pages/TasksConfig.qml b/shell/package/contents/configuration/pages/TasksConfig.qml
index f0998aa4..9b85db2d 100644
--- a/shell/package/contents/configuration/pages/TasksConfig.qml
+++ b/shell/package/contents/configuration/pages/TasksConfig.qml
@@ -1,741 +1,754 @@
/*
* Copyright 2016 Smith AR
* Michail Vourlakos
*
* This file is part of Latte-Dock
*
* Latte-Dock is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* Latte-Dock is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.plasma.plasmoid 2.0
import org.kde.latte.core 0.2 as LatteCore
import org.kde.latte.components 1.0 as LatteComponents
import org.kde.latte.private.tasks 0.1 as LatteTasks
PlasmaComponents.Page {
Layout.maximumWidth: content.width + content.Layout.leftMargin * 2
Layout.maximumHeight: content.height + units.smallSpacing * 2
property bool disableAllWindowsFunctionality: tasks.configuration.hideAllTasks
ColumnLayout {
id: content
width: (dialog.appliedWidth - units.smallSpacing * 2) - Layout.leftMargin * 2
spacing: dialog.subGroupSpacing
anchors.horizontalCenter: parent.horizontalCenter
Layout.leftMargin: units.smallSpacing * 2
Layout.rightMargin: units.smallSpacing * 2
//! BEGIN: Badges
ColumnLayout {
spacing: units.smallSpacing
Layout.topMargin: units.smallSpacing
visible: dialog.advancedLevel
LatteComponents.Header {
text: i18n("Badges")
}
LatteComponents.CheckBoxesColumn {
Layout.leftMargin: units.smallSpacing * 2
Layout.rightMargin: units.smallSpacing * 2
LatteComponents.CheckBox {
Layout.maximumWidth: dialog.optionsWidth
text: i18n("Notifications from tasks")
checked: tasks.configuration.showInfoBadge
tooltip: i18n("Show unread messages or notifications from tasks")
onClicked: {
tasks.configuration.showInfoBadge = checked
}
}
LatteComponents.CheckBox {
Layout.maximumWidth: dialog.optionsWidth
text: i18n("Progress information for tasks")
checked: tasks.configuration.showProgressBadge
tooltip: i18n("Show a progress animation for tasks e.g. when copying files with Dolphin")
onClicked: {
tasks.configuration.showProgressBadge = checked
}
}
LatteComponents.CheckBox {
Layout.maximumWidth: dialog.optionsWidth
text: i18n("Audio playing from tasks")
checked: tasks.configuration.showAudioBadge
tooltip: i18n("Show audio playing from tasks")
onClicked: {
tasks.configuration.showAudioBadge = checked
}
}
LatteComponents.CheckBox {
Layout.maximumWidth: dialog.optionsWidth
text: i18n("Prominent color for notification badge")
checked: tasks.configuration.infoBadgeProminentColorEnabled
enabled: tasks.configuration.showInfoBadge
tooltip: i18n("Notification badge uses a more prominent background which is usually red")
onClicked: {
tasks.configuration.infoBadgeProminentColorEnabled = !tasks.configuration.infoBadgeProminentColorEnabled;
}
}
LatteComponents.CheckBox {
Layout.maximumWidth: dialog.optionsWidth
text: i18n("Change volume when scrolling audio badge")
checked: tasks.configuration.audioBadgeActionsEnabled
enabled: tasks.configuration.showAudioBadge
tooltip: i18n("The user is able to mute/unmute with click or change the volume with mouse wheel")
onClicked: {
tasks.configuration.audioBadgeActionsEnabled = checked
}
}
}
}
//! END: Badges
//! BEGIN: Tasks Interaction
ColumnLayout {
Layout.topMargin: dialog.basicLevel ? units.smallSpacing : 0
spacing: units.smallSpacing
LatteComponents.Header {
text: i18n("Interaction")
}
LatteComponents.CheckBoxesColumn {
Layout.leftMargin: units.smallSpacing * 2
Layout.rightMargin: units.smallSpacing * 2
LatteComponents.CheckBox {
Layout.maximumWidth: dialog.optionsWidth
text: i18n("Add launchers only in the Tasks Area")
checked: plasmoid.configuration.addLaunchersInTaskManager
tooltip: i18n("Launchers are added only in the taskmanager and not as plasma applets")
enabled: latteView.extendedInterface.latteTasksModel.count === 1
&& latteView.extendedInterface.plasmaTasksModel.count === 0
onClicked: {
plasmoid.configuration.addLaunchersInTaskManager = checked;
}
}
LatteComponents.CheckBox {
id: windowActionsChk
Layout.maximumWidth: dialog.optionsWidth
text: i18n("Window actions in the context menu")
checked: tasks.configuration.showWindowActions
visible: dialog.advancedLevel
enabled: !disableAllWindowsFunctionality
onClicked: {
tasks.configuration.showWindowActions = checked
}
}
+ LatteComponents.CheckBox {
+ id: previewPopupChk
+ Layout.maximumWidth: dialog.optionsWidth
+ text: i18n("Preview window behaves as popup")
+ checked: tasks.configuration.previewWindowAsPopup
+ visible: dialog.advancedLevel
+ enabled: !disableAllWindowsFunctionality
+
+ onClicked: {
+ tasks.configuration.previewWindowAsPopup = checked;
+ }
+ }
+
LatteComponents.CheckBox {
id: unifyGlobalShortcutsChk
Layout.maximumWidth: dialog.optionsWidth
text: i18n("➊ Based on position shortcuts apply only on tasks")
// checked: tasks.configuration.isPreferredForPositionShortcuts //! Disabled because it was not updated between multiple Tasks
tooltip: i18n("Based on position global shortcuts are enabled only for tasks and not for applets")
visible: dialog.advancedLevel
enabled: latteView.isPreferredForShortcuts || (!latteView.layout.preferredForShortcutsTouched && latteView.isHighestPriorityView())
readonly property bool isPreferredForShotcuts: tasks.configuration.isPreferredForPositionShortcuts
onIsPreferredForShotcutsChanged: checked = isPreferredForShotcuts;
onClicked: {
tasks.configuration.isPreferredForPositionShortcuts = !tasks.configuration.isPreferredForPositionShortcuts;
}
}
}
}
//! END: Tasks Interaction
//! BEGIN: Tasks Filters
ColumnLayout {
spacing: units.smallSpacing
LatteComponents.Header {
text: i18n("Filters")
}
LatteComponents.CheckBoxesColumn {
Layout.leftMargin: units.smallSpacing * 2
Layout.rightMargin: units.smallSpacing * 2
LatteComponents.CheckBox {
Layout.maximumWidth: dialog.optionsWidth
text: i18n("Show only tasks from the current screen")
checked: tasks.configuration.showOnlyCurrentScreen
enabled: !disableAllWindowsFunctionality
onClicked: {
tasks.configuration.showOnlyCurrentScreen = checked
}
}
LatteComponents.CheckBox {
Layout.maximumWidth: dialog.optionsWidth
text: i18n("Show only tasks from the current desktop")
checked: tasks.configuration.showOnlyCurrentDesktop
enabled: !disableAllWindowsFunctionality
onClicked: {
tasks.configuration.showOnlyCurrentDesktop = checked
}
}
LatteComponents.CheckBox {
Layout.maximumWidth: dialog.optionsWidth
text: i18n("Show only tasks from the current activity")
checked: tasks.configuration.showOnlyCurrentActivity
enabled: !disableAllWindowsFunctionality
onClicked: {
tasks.configuration.showOnlyCurrentActivity = checked
}
}
LatteComponents.CheckBox {
Layout.maximumWidth: dialog.optionsWidth
text: i18n("Show only tasks from launchers")
checked: tasks.configuration.showWindowsOnlyFromLaunchers
visible: dialog.advancedLevel
enabled: !disableAllWindowsFunctionality
onClicked: {
tasks.configuration.showWindowsOnlyFromLaunchers = checked
}
}
LatteComponents.CheckBox {
Layout.maximumWidth: dialog.optionsWidth
text: i18n("Show only launchers and hide all tasks")
checked: tasks.configuration.hideAllTasks
tooltip: i18n("Tasks become hidden and only launchers are shown")
visible: dialog.advancedLevel
onClicked: {
tasks.configuration.hideAllTasks = checked
}
}
LatteComponents.CheckBox {
Layout.maximumWidth: dialog.optionsWidth
text: i18n("Show only grouped tasks for same application")
checked: tasks.configuration.groupTasksByDefault
tooltip: i18n("By default group tasks of the same application")
visible: dialog.advancedLevel
enabled: !disableAllWindowsFunctionality
onClicked: {
tasks.configuration.groupTasksByDefault = checked
}
}
}
}
//! END: Tasks Filters
//! BEGIN: Animations
ColumnLayout {
spacing: units.smallSpacing
enabled: plasmoid.configuration.animationsEnabled
visible: dialog.advancedLevel
LatteComponents.Header {
text: i18n("Animations")
}
LatteComponents.CheckBoxesColumn {
Layout.leftMargin: units.smallSpacing * 2
Layout.rightMargin: units.smallSpacing * 2
LatteComponents.CheckBox {
Layout.maximumWidth: dialog.optionsWidth
text: i18n("Bounce launchers when triggered")
checked: tasks.configuration.animationLauncherBouncing
onClicked: {
tasks.configuration.animationLauncherBouncing = !tasks.configuration.animationLauncherBouncing;
}
}
LatteComponents.CheckBox {
Layout.maximumWidth: dialog.optionsWidth
text: i18n("Bounce tasks that need attention")
checked: tasks.configuration.animationWindowInAttention
onClicked: {
tasks.configuration.animationWindowInAttention = !tasks.configuration.animationWindowInAttention;
}
}
LatteComponents.CheckBox {
Layout.maximumWidth: dialog.optionsWidth
text: i18n("Slide in and out single windows")
checked: tasks.configuration.animationNewWindowSliding
onClicked: {
tasks.configuration.animationNewWindowSliding = !tasks.configuration.animationNewWindowSliding;
}
}
LatteComponents.CheckBox {
Layout.maximumWidth: dialog.optionsWidth
text: i18n("Grouped tasks bounce their new windows")
checked: tasks.configuration.animationWindowAddedInGroup
onClicked: {
tasks.configuration.animationWindowAddedInGroup = !tasks.configuration.animationWindowAddedInGroup;
}
}
LatteComponents.CheckBox {
Layout.maximumWidth: dialog.optionsWidth
text: i18n("Grouped tasks slide out their closed windows")
checked: tasks.configuration.animationWindowRemovedFromGroup
onClicked: {
tasks.configuration.animationWindowRemovedFromGroup = !tasks.configuration.animationWindowRemovedFromGroup;
}
}
}
}
//! END: Animations
//! BEGIN: Launchers Group
ColumnLayout {
spacing: units.smallSpacing
LatteComponents.Header {
text: i18n("Launchers")
}
ColumnLayout {
Layout.leftMargin: units.smallSpacing * 2
Layout.rightMargin: units.smallSpacing * 2
spacing: 0
LatteComponents.SubHeader {
isFirstSubCategory: true
text: i18nc("launchers group", "Group");
}
RowLayout {
Layout.fillWidth: true
spacing: 2
property int group: tasks.configuration.launchersGroup
readonly property int buttonsCount: layoutGroupButton.visible ? 3 : 2
readonly property int buttonSize: (dialog.optionsWidth - (spacing * buttonsCount-1)) / buttonsCount
ExclusiveGroup {
id: launchersGroup
onCurrentChanged: {
if (current.checked) {
viewConfig.updateLaunchersForGroup(current.group);
tasks.configuration.launchersGroup = current.group;
}
}
}
PlasmaComponents.Button {
Layout.minimumWidth: parent.buttonSize
Layout.maximumWidth: Layout.minimumWidth
text: i18nc("unique launchers group","Unique")
checked: parent.group === group
checkable: true
exclusiveGroup: launchersGroup
tooltip: i18n("Use a unique set of launchers for this view which is independent from any other view")
readonly property int group: LatteCore.Types.UniqueLaunchers
}
PlasmaComponents.Button {
id: layoutGroupButton
Layout.minimumWidth: parent.buttonSize
Layout.maximumWidth: Layout.minimumWidth
text: i18nc("layout launchers group","Layout")
checked: parent.group === group
checkable: true
exclusiveGroup: launchersGroup
tooltip: i18n("Use the current layout set of launchers for this latteView. This group provides launchers synchronization between different views in the same layout")
//! it is shown only when the user has activated that option manually from the text layout file
visible: tasks.configuration.launchersGroup === group
readonly property int group: LatteCore.Types.LayoutLaunchers
}
PlasmaComponents.Button {
Layout.minimumWidth: parent.buttonSize
Layout.maximumWidth: Layout.minimumWidth
text: i18nc("global launchers group","Global")
checked: parent.group === group
checkable: true
exclusiveGroup: launchersGroup
tooltip: i18n("Use the global set of launchers for this latteView. This group provides launchers synchronization between different views and between different layouts")
readonly property int group: LatteCore.Types.GlobalLaunchers
}
}
}
}
//! END: Launchers Group
//! BEGIN: Scrolling
ColumnLayout {
spacing: units.smallSpacing
visible: dialog.advancedLevel
LatteComponents.HeaderSwitch {
id: scrollingHeader
Layout.minimumWidth: dialog.optionsWidth + 2 *units.smallSpacing
Layout.maximumWidth: Layout.minimumWidth
Layout.minimumHeight: implicitHeight
Layout.bottomMargin: units.smallSpacing
enabled: LatteCore.WindowSystem.compositingActive
checked: tasks.configuration.scrollTasksEnabled
text: i18n("Scrolling")
tooltip: i18n("Enable tasks scrolling when they overflow and exceed the available space");
onPressed: {
tasks.configuration.scrollTasksEnabled = !tasks.configuration.scrollTasksEnabled;;
}
}
ColumnLayout {
Layout.leftMargin: units.smallSpacing * 2
Layout.rightMargin: units.smallSpacing * 2
spacing: 0
enabled: scrollingHeader.checked
GridLayout {
columns: 2
Layout.minimumWidth: dialog.optionsWidth
Layout.maximumWidth: Layout.minimumWidth
Layout.topMargin: units.smallSpacing
PlasmaComponents.Label {
Layout.fillWidth: true
text: i18n("Manual")
}
LatteComponents.ComboBox {
id: manualScrolling
Layout.minimumWidth: leftClickAction.width
Layout.maximumWidth: leftClickAction.width
model: [i18nc("disabled manual scrolling", "Disabled scrolling"),
dialog.panelIsVertical ? i18n("Only vertical scrolling") : i18n("Only horizontal scrolling"),
i18n("Horizontal and vertical scrolling")]
currentIndex: tasks.configuration.manualScrollTasksType
onCurrentIndexChanged: tasks.configuration.manualScrollTasksType = currentIndex;
}
PlasmaComponents.Label {
id: autoScrollText
Layout.fillWidth: true
text: i18n("Automatic")
}
LatteComponents.ComboBox {
id: autoScrolling
Layout.minimumWidth: leftClickAction.width
Layout.maximumWidth: leftClickAction.width
model: [
i18n("Disabled"),
i18n("Enabled")
]
currentIndex: tasks.configuration.autoScrollTasksEnabled
onCurrentIndexChanged: {
if (currentIndex === 0) {
tasks.configuration.autoScrollTasksEnabled = false;
} else {
tasks.configuration.autoScrollTasksEnabled = true;
}
}
}
}
}
}
//! END: Scolling
//! BEGIN: Actions
ColumnLayout {
spacing: units.smallSpacing
visible: dialog.advancedLevel
LatteComponents.Header {
text: i18n("Actions")
}
ColumnLayout {
Layout.leftMargin: units.smallSpacing * 2
Layout.rightMargin: units.smallSpacing * 2
spacing: 0
GridLayout {
columns: 2
Layout.minimumWidth: dialog.optionsWidth
Layout.maximumWidth: Layout.minimumWidth
Layout.topMargin: units.smallSpacing
enabled: !disableAllWindowsFunctionality
PlasmaComponents.Label {
id: leftClickLbl
text: i18n("Left Click")
}
LatteComponents.ComboBox {
id: leftClickAction
Layout.fillWidth: true
model: [i18nc("present windows action", "Present Windows"),
i18n("Cycle Through Tasks"),
i18n("Preview Windows")]
currentIndex: {
switch(tasks.configuration.leftClickAction) {
case LatteTasks.Types.PresentWindows:
return 0;
case LatteTasks.Types.CycleThroughTasks:
return 1;
case LatteTasks.Types.PreviewWindows:
return 2;
}
return 0;
}
onCurrentIndexChanged: {
switch(currentIndex) {
case 0:
tasks.configuration.leftClickAction = LatteTasks.Types.PresentWindows;
break;
case 1:
tasks.configuration.leftClickAction = LatteTasks.Types.CycleThroughTasks;
break;
case 2:
tasks.configuration.leftClickAction = LatteTasks.Types.PreviewWindows;
break;
}
}
}
PlasmaComponents.Label {
id: middleClickText
text: i18n("Middle Click")
}
LatteComponents.ComboBox {
id: middleClickAction
Layout.fillWidth: true
model: [
i18nc("The click action", "None"),
i18n("Close Window or Group"),
i18n("New Instance"),
i18n("Minimize/Restore Window or Group"),
i18n("Cycle Through Tasks"),
i18n("Toggle Task Grouping")
]
currentIndex: tasks.configuration.middleClickAction
onCurrentIndexChanged: tasks.configuration.middleClickAction = currentIndex
}
PlasmaComponents.Label {
text: i18n("Hover")
}
LatteComponents.ComboBox {
id: hoverAction
Layout.fillWidth: true
model: [
i18nc("none action", "None"),
i18n("Preview Windows"),
i18n("Highlight Windows"),
i18n("Preview and Highlight Windows"),
]
currentIndex: {
switch(tasks.configuration.hoverAction) {
case LatteTasks.Types.NoneAction:
return 0;
case LatteTasks.Types.PreviewWindows:
return 1;
case LatteTasks.Types.HighlightWindows:
return 2;
case LatteTasks.Types.PreviewAndHighlightWindows:
return 3;
}
return 0;
}
onCurrentIndexChanged: {
switch(currentIndex) {
case 0:
tasks.configuration.hoverAction = LatteTasks.Types.NoneAction;
break;
case 1:
tasks.configuration.hoverAction = LatteTasks.Types.PreviewWindows;
break;
case 2:
tasks.configuration.hoverAction = LatteTasks.Types.HighlightWindows;
break;
case 3:
tasks.configuration.hoverAction = LatteTasks.Types.PreviewAndHighlightWindows;
break;
}
}
}
PlasmaComponents.Label {
text: i18n("Wheel")
}
LatteComponents.ComboBox {
id: wheelAction
Layout.fillWidth: true
model: [
i18nc("none action", "None"),
i18n("Cycle Through Tasks"),
i18n("Cycle And Minimize Tasks")
]
currentIndex: tasks.configuration.taskScrollAction
onCurrentIndexChanged: tasks.configuration.taskScrollAction = currentIndex
}
RowLayout {
spacing: units.smallSpacing
enabled: !disableAllWindowsFunctionality
Layout.minimumWidth: middleClickText.width
Layout.maximumWidth: middleClickText.width
LatteComponents.ComboBox {
id: modifier
Layout.fillWidth: true
model: ["Shift", "Ctrl", "Alt", "Meta"]
currentIndex: tasks.configuration.modifier
onCurrentIndexChanged: tasks.configuration.modifier = currentIndex
}
PlasmaComponents.Label {
text: "+"
}
}
RowLayout {
spacing: units.smallSpacing
enabled: !disableAllWindowsFunctionality
readonly property int maxSize: 0.4 * dialog.optionsWidth
LatteComponents.ComboBox {
id: modifierClick
Layout.preferredWidth: 0.7 * parent.maxSize
Layout.maximumWidth: parent.maxSize
model: [i18n("Left Click"), i18n("Middle Click"), i18n("Right Click")]
currentIndex: tasks.configuration.modifierClick
onCurrentIndexChanged: tasks.configuration.modifierClick = currentIndex
}
PlasmaComponents.Label {
text: "="
}
LatteComponents.ComboBox {
id: modifierClickAction
Layout.fillWidth: true
model: [i18nc("The click action", "None"), i18n("Close Window or Group"),
i18n("New Instance"), i18n("Minimize/Restore Window or Group"), i18n("Cycle Through Tasks"), i18n("Toggle Task Grouping")]
currentIndex: tasks.configuration.modifierClickAction
onCurrentIndexChanged: tasks.configuration.modifierClickAction = currentIndex
}
}
}
RowLayout {
Layout.minimumWidth: dialog.optionsWidth
Layout.maximumWidth: Layout.minimumWidth
Layout.topMargin: units.smallSpacing
spacing: units.smallSpacing
enabled: !disableAllWindowsFunctionality
}
}
}
//! END: Actions
//! BEGIN: Recycling
/* ColumnLayout {
spacing: units.smallSpacing
visible: dialog.advancedLevel
LatteComponents.Header {
text: i18n("Recycling")
}
PlasmaComponents.Button {
Layout.minimumWidth: dialog.optionsWidth
Layout.maximumWidth: Layout.minimumWidth
Layout.leftMargin: units.smallSpacing * 2
Layout.rightMargin: units.smallSpacing * 2
Layout.topMargin: units.smallSpacing
text: i18n("Remove Latte Tasks Applet")
enabled: latteView.latteTasksArePresent
tooltip: i18n("Remove Latte Tasks plasmoid")
onClicked: {
latteView.removeTasksPlasmoid();
}
}
}*/
}
}