diff --git a/applets/taskmanager/package/contents/config/main.xml b/applets/taskmanager/package/contents/config/main.xml index 0e104bd15..4c0c7d1d3 100644 --- a/applets/taskmanager/package/contents/config/main.xml +++ b/applets/taskmanager/package/contents/config/main.xml @@ -1,99 +1,107 @@ false false true false 1 true true 2 true 2 1 false true true false 0 true true + + + true + + + + 0 + diff --git a/applets/taskmanager/package/contents/ui/Task.qml b/applets/taskmanager/package/contents/ui/Task.qml index 331ba8b08..fdc739298 100644 --- a/applets/taskmanager/package/contents/ui/Task.qml +++ b/applets/taskmanager/package/contents/ui/Task.qml @@ -1,554 +1,556 @@ /*************************************************************************** * Copyright (C) 2012-2013 by Eike Hein * * * * This program 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. * * * * 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ import QtQuick 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.draganddrop 2.0 import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet import "../code/layout.js" as LayoutManager import "../code/tools.js" as TaskTools MouseArea { id: task width: groupDialog.contentWidth height: Math.max(theme.mSize(theme.defaultFont).height, units.iconSizes.medium) + LayoutManager.verticalMargins() visible: false LayoutMirroring.enabled: (Qt.application.layoutDirection == Qt.RightToLeft) LayoutMirroring.childrenInherit: (Qt.application.layoutDirection == Qt.RightToLeft) readonly property var m: model readonly property int pid: model.AppPid readonly property string appName: model.AppName property int itemIndex: index property bool inPopup: false property bool isWindow: model.IsWindow === true property int childCount: model.ChildCount != undefined ? model.ChildCount : 0 property int previousChildCount: 0 property alias labelText: label.text property bool pressed: false property int pressX: -1 property int pressY: -1 property QtObject contextMenu: null property int wheelDelta: 0 readonly property bool smartLauncherEnabled: plasmoid.configuration.smartLaunchersEnabled && !inPopup && model.IsStartup !== true property QtObject smartLauncherItem: null property Item audioStreamOverlay property var audioStreams: [] readonly property bool hasAudioStream: plasmoid.configuration.indicateAudioStreams && audioStreams.length > 0 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 bool highlighted: (inPopup && activeFocus) || (!inPopup && containsMouse) function hideToolTipTemporarily() { toolTipArea.hideToolTip(); } acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MidButton onPidChanged: updateAudioStreams() onAppNameChanged: updateAudioStreams() onIsWindowChanged: { if (isWindow) { taskInitComponent.createObject(task); } } onChildCountChanged: { if (containsMouse) { groupDialog.activeTask = null; } if (childCount > previousChildCount) { tasksModel.requestPublishDelegateGeometry(modelIndex(), backend.globalRect(task), task); } previousChildCount = childCount; } onItemIndexChanged: { hideToolTipTemporarily(); if (!inPopup && !tasks.vertical && (LayoutManager.calculateStripes() > 1 || !plasmoid.configuration.separateLaunchers)) { tasks.requestLayout(); } } onContainsMouseChanged: { if (containsMouse) { if (inPopup) { forceActiveFocus(); } } else { pressed = false; } if (model.IsWindow === true) { tasks.windowsHovered(model.LegacyWinIdList, containsMouse); } } onPressed: { if (mouse.button == Qt.LeftButton || mouse.button == Qt.MidButton) { pressed = true; pressX = mouse.x; pressY = mouse.y; } else if (mouse.button == Qt.RightButton) { // 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) { showContextMenu({showAllPlaces: true}) } else { showContextMenu(); } } } onReleased: { if (pressed) { if (mouse.button == Qt.MidButton) { if (plasmoid.configuration.middleClickAction == TaskManagerApplet.Backend.NewInstance) { tasksModel.requestNewInstance(modelIndex()); } else if (plasmoid.configuration.middleClickAction == TaskManagerApplet.Backend.Close) { tasksModel.requestClose(modelIndex()); } else if (plasmoid.configuration.middleClickAction == TaskManagerApplet.Backend.ToggleMinimized) { tasksModel.requestToggleMinimized(modelIndex()); } } else if (mouse.button == Qt.LeftButton) { TaskTools.activateTask(modelIndex(), model, mouse.modifiers, task); if (plasmoid.configuration.showToolTips) { hideToolTipTemporarily(); } } backend.cancelHighlightWindows(); } pressed = false; pressX = -1; pressY = -1; } onPositionChanged: { // mouse.button is always 0 here, hence checking with mouse.buttons if (pressX != -1 && mouse.buttons == Qt.LeftButton && dragHelper.isDrag(pressX, pressY, mouse.x, mouse.y)) { tasks.dragSource = task; dragHelper.startDrag(task, model.MimeType, model.MimeData, model.LauncherUrlWithoutIcon, model.decoration); pressX = -1; pressY = -1; return; } } onWheel: { if (plasmoid.configuration.wheelEnabled && (!inPopup || !groupDialog.overflowing)) { wheelDelta = TaskTools.wheelActivateNextPrevTask(task, wheelDelta, wheel.angleDelta.y); } else { wheel.accepted = false; } } onSmartLauncherEnabledChanged: { if (smartLauncherEnabled && !smartLauncherItem) { var smartLauncher = Qt.createQmlObject(" import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet; TaskManagerApplet.SmartLauncherItem { }", task); smartLauncher.launcherUrl = Qt.binding(function() { return model.LauncherUrlWithoutIcon; }); smartLauncherItem = smartLauncher; } } onHasAudioStreamChanged: { if (hasAudioStream) { audioStreamIconLoader.active = true } } Keys.onReturnPressed: TaskTools.activateTask(modelIndex(), model, event.modifiers, task) Keys.onEnterPressed: Keys.onReturnPressed(event); function modelIndex() { return (inPopup ? tasksModel.makeModelIndex(groupDialog.visualParent.itemIndex, index) : tasksModel.makeModelIndex(index)); } function showContextMenu(args) { tasks.createContextMenu(task, modelIndex(), args).show(); } function updateAudioStreams() { var pa = pulseAudio.item; if (!pa) { task.audioStreams = []; return; } var streams = pa.streamsForPid(task.pid); if (streams.length) { pa.registerPidMatch(task.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(task.appName)) { streams = pa.streamsForAppName(task.appName); } } task.audioStreams = streams; } function toggleMuted() { if (muted) { task.audioStreams.forEach(function (item) { item.unmute(); }); } else { task.audioStreams.forEach(function (item) { item.mute(); }); } } Connections { target: pulseAudio.item ignoreUnknownSignals: true // Plasma-PA might not be available onStreamsChanged: task.updateAudioStreams() } Component { id: taskInitComponent Timer { id: timer interval: units.longDuration * 2 repeat: false onTriggered: { parent.hoverEnabled = true; if (parent.isWindow) { tasksModel.requestPublishDelegateGeometry(parent.modelIndex(), backend.globalRect(parent), parent); } timer.destroy(); } Component.onCompleted: timer.start() } } PlasmaCore.FrameSvgItem { id: frame anchors { fill: parent topMargin: (!tasks.vertical && taskList.rows > 1) ? units.smallSpacing / 4 : 0 bottomMargin: (!tasks.vertical && taskList.rows > 1) ? units.smallSpacing / 4 : 0 leftMargin: ((inPopup || tasks.vertical) && taskList.columns > 1) ? units.smallSpacing / 4 : 0 rightMargin: ((inPopup || tasks.vertical) && taskList.columns > 1) ? units.smallSpacing / 4 : 0 } imagePath: "widgets/tasks" property string basePrefix: "normal" prefix: TaskTools.taskPrefix(basePrefix) onRepaintNeeded: updatePrefix() function updatePrefix() { prefix = Qt.binding(function() { return TaskTools.taskPrefix(basePrefix); }); } PlasmaCore.ToolTipArea { id: toolTipArea anchors.fill: parent location: plasmoid.location active: !inPopup && !groupDialog.visible && plasmoid.configuration.showToolTips interactive: true mainItem: toolTipDelegate onContainsMouseChanged: { if (containsMouse) { toolTipDelegate.parentTask = task; toolTipDelegate.parentIndex = itemIndex; toolTipDelegate.appName = Qt.binding(function() { return model.AppName; }); toolTipDelegate.pidParent = Qt.binding(function() { return model.AppPid; }); toolTipDelegate.windows = Qt.binding(function() { return 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.VirtualDesktop != undefined ? model.VirtualDesktop : 0; }); toolTipDelegate.isOnAllVirtualDesktopsParent = Qt.binding(function() { return model.IsOnAllVirtualDesktops == true; }); toolTipDelegate.activitiesParent = Qt.binding(function() { return model.Activities; }); } } } } Loader { anchors.fill: frame asynchronous: true source: "TaskProgressOverlay.qml" active: plasmoid.configuration.smartLaunchersEnabled && task.smartLauncherItem && task.smartLauncherItem.progressVisible } Item { id: iconBox anchors { left: parent.left leftMargin: adjustMargin(true, parent.width, taskFrame.margins.left) top: parent.top topMargin: adjustMargin(false, parent.height, taskFrame.margins.top) } width: height height: (parent.height - adjustMargin(false, parent.height, taskFrame.margins.top) - adjustMargin(false, parent.height, taskFrame.margins.bottom)) function adjustMargin(vert, size, margin) { if (!size) { return margin; } var margins = vert ? LayoutManager.horizontalMargins() : LayoutManager.verticalMargins(); if ((size - margins) < units.iconSizes.small) { return Math.ceil((margin * (units.iconSizes.small / size)) / 2); } return margin; } //width: inPopup ? units.iconSizes.small : Math.min(height, parent.width - LayoutManager.horizontalMargins()) PlasmaCore.IconItem { id: icon anchors.fill: parent active: task.highlighted || (task.contextMenu && task.contextMenu.status == PlasmaComponents.DialogStatus.Open) enabled: true usesPlasmaTheme: false source: model.decoration } Loader { // QTBUG anchors.fill in conjunction with the Loader doesn't reliably work on creation: // have a window with a badge, move it from one screen to another, the new task item on the // other screen will now have a glitched out badge mask. width: parent.width height: parent.height asynchronous: true source: "TaskBadgeOverlay.qml" active: plasmoid.configuration.smartLaunchersEnabled && height >= units.iconSizes.small && task.smartLauncherItem && task.smartLauncherItem.countVisible } states: [ // Using a state transition avoids a binding loop between label.visible and // the text label margin, which derives from the icon width. State { name: "standalone" when: !label.visible && !audioStreamIconLoader.shown AnchorChanges { target: iconBox anchors.left: undefined anchors.horizontalCenter: parent.horizontalCenter } PropertyChanges { target: iconBox anchors.leftMargin: 0 width: parent.width - adjustMargin(true, task.width, taskFrame.margins.left) - adjustMargin(true, task.width, taskFrame.margins.right) } } ] Loader { anchors.fill: parent active: model.IsStartup === true sourceComponent: busyIndicator } Component { id: busyIndicator PlasmaComponents.BusyIndicator { anchors.fill: parent } } } Loader { id: audioStreamIconLoader readonly property bool shown: item && item.visible source: "AudioStream.qml" width: units.roundToIconSize(Math.min(Math.min(iconBox.width, iconBox.height), units.iconSizes.smallMedium)) height: width anchors { right: parent.right rightMargin: iconBox.adjustMargin(true, parent.width, taskFrame.margins.right) verticalCenter: parent.verticalCenter } } PlasmaComponents.Label { id: label visible: (inPopup || !iconsOnly && model.IsLauncher !== true && (parent.width - iconBox.height - units.smallSpacing) >= (theme.mSize(theme.defaultFont).width * 5)) anchors { fill: parent leftMargin: taskFrame.margins.left + iconBox.width + units.smallSpacing topMargin: taskFrame.margins.top rightMargin: taskFrame.margins.right + (audioStreamIconLoader.shown ? (audioStreamIconLoader.width + units.smallSpacing) : 0) bottomMargin: taskFrame.margins.bottom } text: model.display wrapMode: Text.Wrap elide: Text.ElideRight textFormat: Text.PlainText verticalAlignment: Text.AlignVCenter + maximumLineCount: plasmoid.configuration.maxTextLines || undefined } states: [ State { name: "launcher" when: model.IsLauncher === true PropertyChanges { target: frame basePrefix: "" } }, State { name: "hovered" - when: task.highlighted || (contextMenu.status == PlasmaComponents.DialogStatus.Open && contextMenu.visualParent == task) + when: ((task.highlighted && frame.hasElementPrefix("hover") && plasmoid.configuration.taskHoverEffect) + || (contextMenu.status == PlasmaComponents.DialogStatus.Open && contextMenu.visualParent == task)) PropertyChanges { target: frame basePrefix: "hover" } }, State { name: "attention" when: model.IsDemandingAttention === true || (task.smartLauncherItem && task.smartLauncherItem.urgent) PropertyChanges { target: frame basePrefix: "attention" } }, State { name: "minimized" when: model.IsMinimized === true && !(groupDialog.visible && groupDialog.visualParent == task) PropertyChanges { target: frame basePrefix: "minimized" } }, State { name: "active" when: model.IsActive === true || groupDialog.visible && groupDialog.visualParent == task PropertyChanges { target: frame basePrefix: "focus" } } ] Component.onCompleted: { if (!inPopup && model.IsWindow === true) { var component = Qt.createComponent("GroupExpanderOverlay.qml"); component.createObject(task); } if (!inPopup && model.IsWindow !== true) { taskInitComponent.createObject(task); } updateAudioStreams() } } diff --git a/containments/desktop/package/contents/config/main.xml b/containments/desktop/package/contents/config/main.xml index 26f2ca99e..6830fb026 100644 --- a/containments/desktop/package/contents/config/main.xml +++ b/containments/desktop/package/contents/config/main.xml @@ -1,144 +1,148 @@ folder false topleft desktop:/ 1 0 0 false 0 false true false true true true imagethumbnail,jpegthumbnail 0 4 2 white + + + true + * 0 all/all true true true true diff --git a/containments/desktop/package/contents/ui/FolderItemDelegate.qml b/containments/desktop/package/contents/ui/FolderItemDelegate.qml index 1f3e9c058..cf4a374f0 100644 --- a/containments/desktop/package/contents/ui/FolderItemDelegate.qml +++ b/containments/desktop/package/contents/ui/FolderItemDelegate.qml @@ -1,423 +1,423 @@ /*************************************************************************** * Copyright (C) 2014-2015 by Eike Hein * * * * This program 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. * * * * 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ import QtQuick 2.4 import QtGraphicalEffects 1.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 Item { id: main property int index: model.index property string name: model.blank ? "" : model.display property bool blank: model.blank property bool isDir: loader.item ? loader.item.isDir : false property QtObject popupDialog: loader.item ? loader.item.popupDialog : null property Item iconArea: loader.item ? loader.item.iconArea : null property Item label: loader.item ? loader.item.label : null property Item labelArea: loader.item ? loader.item.labelArea : null property Item actionsOverlay: loader.item ? loader.item.actionsOverlay : null property Item hoverArea: loader.item ? loader.item.hoverArea : null property Item toolTip: loader.item ? loader.item.toolTip : null function openPopup() { if (isDir) { loader.item.openPopup(); } } Loader { id: loader anchors.fill: parent visible: status === Loader.Ready active: !model.blank sourceComponent: delegateImplementation asynchronous: true } Component { id: delegateImplementation Item { id: impl anchors.fill: parent property bool blank: model.blank property bool selected: model.blank ? false : model.selected property bool isDir: model.blank ? false : model.isDir property bool hovered: (main.GridView.view.hoveredItem == main) property QtObject popupDialog: null property Item iconArea: icon property Item label: label property Item labelArea: frameLoader.textShadow || label property Item actionsOverlay: actions property Item hoverArea: toolTip property Item toolTip: toolTip property Item selectionButton: null property Item popupButton: null onSelectedChanged: { if (selected && !blank) { frameLoader.grabToImage(function(result) { dir.addItemDragImage(positioner.map(index), main.x + frameLoader.x, main.y + frameLoader.y, frameLoader.width, frameLoader.height, result.image); }); } } onHoveredChanged: { if (hovered) { if (plasmoid.configuration.selectionMarkers && Qt.styleHints.singleClickActivation) { selectionButton = selectionButtonComponent.createObject(actions); } if (model.isDir) { if (!main.GridView.view.isRootView || root.containsDrag) { hoverActivateTimer.restart(); } if (plasmoid.configuration.popups && !root.useListViewMode) { popupButton = popupButtonComponent.createObject(actions); } } } else if (!hovered) { hoverActivateTimer.stop(); if (popupDialog != null) { popupDialog.requestDestroy(); popupDialog = null; } if (selectionButton) { selectionButton.destroy(); selectionButton = null; } if (popupButton) { popupButton.destroy(); popupButton = null; } } } function openPopup() { if (folderViewDialogComponent.status == Component.Ready) { impl.popupDialog = folderViewDialogComponent.createObject(impl); impl.popupDialog.visualParent = icon; impl.popupDialog.url = model.linkDestinationUrl; impl.popupDialog.visible = true; } } PlasmaCore.ToolTipArea { id: toolTip x: frameLoader.x + Math.min(icon.x, label.x) y: frameLoader.y + icon.y width: Math.max(icon.width, label.width) height: (label.y + label.paintedHeight) active: (plasmoid.configuration.toolTips && popupDialog == null && !model.blank) interactive: false location: root.useListViewMode ? (plasmoid.location == PlasmaCore.Types.LeftEdge ? PlasmaCore.Types.LeftEdge : PlasmaCore.Types.RightEdge) : plasmoid.location onContainsMouseChanged: { if (containsMouse && !model.blank) { toolTip.icon = model.decoration; toolTip.mainText = model.display; if (model.size != undefined) { toolTip.subText = model.type + "\n" + model.size; } else { toolTip.subText = model.type; } main.GridView.view.hoveredItem = main; } } } Loader { id: frameLoader x: root.useListViewMode ? 0 : units.smallSpacing y: root.useListViewMode ? 0 : units.smallSpacing property Item textShadow: null property string prefix: "" sourceComponent: frameComponent active: state !== "" asynchronous: true width: { if (root.useListViewMode) { if (main.GridView.view.overflowing) { return parent.width - units.smallSpacing; } else { return parent.width; } } return parent.width - (units.smallSpacing * 2); } height: { if (root.useListViewMode) { return parent.height; } return (icon.height + (2 * units.smallSpacing) + (label.lineCount * theme.mSize(theme.defaultFont).height) + (2 * units.largeSpacing)); } PlasmaCore.IconItem { id: icon z: 2 states: [ State { // icon view when: !root.useListViewMode AnchorChanges { target: icon anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter } }, State { // list view when: root.useListViewMode AnchorChanges { target: icon anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter } } ] anchors { topMargin: units.largeSpacing leftMargin: units.smallSpacing } width: root.useListViewMode ? main.GridView.view.iconSize : (parent.width - 2 * units.smallSpacing) height: main.GridView.view.iconSize opacity: root.useListViewMode && selectionButton ? 0.3 : 1.0 animated: false usesPlasmaTheme: false source: model.decoration overlays: model.overlays } PlasmaComponents.Label { id: label z: 2 // So we can position a textShadowComponent below if needed. states: [ State { // icon view when: !root.useListViewMode AnchorChanges { target: label anchors.top: icon.bottom anchors.horizontalCenter: parent.horizontalCenter } PropertyChanges { target: label anchors.topMargin: 2 * units.smallSpacing width: Math.min(label.implicitWidth + units.smallSpacing, parent.width - units.smallSpacing * 8) maximumLineCount: plasmoid.configuration.textLines horizontalAlignment: Text.AlignHCenter } }, State { // list view when: root.useListViewMode AnchorChanges { target: label anchors.left: icon.right anchors.verticalCenter: parent.verticalCenter } PropertyChanges { target: label anchors.leftMargin: units.smallSpacing * 2 anchors.rightMargin: units.smallSpacing * 2 width: parent.width - icon.width - (units.smallSpacing * 4) maximumLineCount: 1 horizontalAlignment: Text.AlignLeft } } ] height: undefined // Unset PlasmaComponents.Label's default. textFormat: Text.PlainText wrapMode: Text.Wrap elide: Text.ElideRight color: (frameLoader.textShadow && frameLoader.textShadow.visible ? "#fff" : PlasmaCore.ColorScope.textColor) text: model.blank ? "" : model.display font.italic: model.isLink } Column { id: actions visible: { if (main.GridView.view.isRootView && root.containsDrag) { return false; } if (!main.GridView.view.isRootView && dialog.containsDrag) { return false; } if (popupDialog) { return false; } return true; } x: units.smallSpacing * 3 y: units.smallSpacing * 3 z: 3 anchors { centerIn: root.useListViewMode ? icon : undefined } width: implicitWidth height: implicitHeight } Component { id: frameComponent PlasmaCore.FrameSvgItem { prefix: frameLoader.prefix imagePath: "widgets/viewitem" } } Component { id: selectionButtonComponent FolderItemActionButton { element: model.selected ? "remove" : "add" onClicked: dir.toggleSelected(positioner.map(index)) } } Component { id: popupButtonComponent FolderItemActionButton { visible: popupDialog == null element: "open" onClicked: openPopup() } } Component { id: textShadowComponent DropShadow { anchors.fill: label z: 1 horizontalOffset: 2 verticalOffset: 2 radius: 9.0 samples: 18 spread: 0.15 color: "black" source: label } } states: [ State { name: "selected" when: model.selected PropertyChanges { target: frameLoader prefix: "selected" } }, State { name: "hover" - when: hovered && !model.selected + when: hovered && !model.selected && plasmoid.configuration.iconHoverEffect PropertyChanges { target: frameLoader prefix: "hover" } }, State { name: "selected+hover" - when: hovered && model.selected + when: hovered && model.selected && plasmoid.configuration.iconHoverEffect PropertyChanges { target: frameLoader prefix: "selected+hover" } } ] } Component.onCompleted: { if (root.isContainment && main.GridView.view.isRootView) { frameLoader.textShadow = textShadowComponent.createObject(frameLoader); } } } } }