Warning, /plasma/plasma-desktop/applets/kicker/package/contents/ui/ItemListDelegate.qml is written in an unsupported language. File is not indexed.

0001 /*
0002     SPDX-FileCopyrightText: 2013-2015 Eike Hein <hein@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 import QtQuick 2.15
0008 
0009 import org.kde.plasma.components 3.0 as PlasmaComponents3
0010 import org.kde.kirigami 2.20 as Kirigami
0011 import org.kde.ksvg 1.0 as KSvg
0012 
0013 import "code/tools.js" as Tools
0014 
0015 Item {
0016     id: item
0017 
0018     height: isSeparator ? separatorHeight : itemHeight
0019     width: ListView.view.width
0020 
0021     // if it's not disabled and is either a leaf node or a node with children
0022     enabled: !isSeparator && !model.disabled && (!isParent || (isParent && hasChildren))
0023 
0024     signal actionTriggered(string actionId, variant actionArgument)
0025     signal aboutToShowActionMenu(variant actionMenu)
0026 
0027     readonly property real fullTextWidth: Math.ceil(icon.width + label.implicitWidth + arrow.width + row.anchors.leftMargin + row.anchors.rightMargin + row.actualSpacing)
0028     property bool isSeparator: (model.isSeparator === true)
0029     property bool sorted: (model.sorted === true)
0030     property bool hasChildren: (model.hasChildren === true)
0031     property bool hasActionList: ((model.favoriteId !== null)
0032         || (("hasActionList" in model) && (model.hasActionList === true)))
0033     property QtObject childDialog: null
0034     property Item menu: actionMenu
0035     readonly property bool pressed: mouseArea.pressed
0036     readonly property bool iconAndLabelsShouldlookSelected: mouseArea.pressed && !hasChildren
0037 
0038     Accessible.role: isSeparator ? Accessible.Separator: Accessible.MenuItem
0039     Accessible.name: label.text
0040 
0041     onHasChildrenChanged: {
0042         if (!hasChildren && ListView.view.currentItem === item) {
0043             ListView.view.currentIndex = -1;
0044         }
0045     }
0046 
0047     onAboutToShowActionMenu: {
0048         var actionList = item.hasActionList ? model.actionList : [];
0049         Tools.fillActionMenu(i18n, actionMenu, actionList, ListView.view.model.favoritesModel, model.favoriteId);
0050     }
0051 
0052     onActionTriggered: {
0053         if (Tools.triggerAction(ListView.view.model, model.index, actionId, actionArgument) === true) {
0054             kicker.expanded = false;
0055         }
0056     }
0057 
0058     function openActionMenu(visualParent, x, y) {
0059         aboutToShowActionMenu(actionMenu);
0060         actionMenu.visualParent = visualParent;
0061         actionMenu.open(x, y);
0062     }
0063 
0064     ActionMenu {
0065         id: actionMenu
0066 
0067         onActionClicked: {
0068             item.actionTriggered(actionId, actionArgument);
0069         }
0070     }
0071 
0072     MouseArea {
0073         id: mouseArea
0074 
0075         anchors {
0076             left: parent.left
0077             right: parent.right
0078             verticalCenter: parent.verticalCenter
0079         }
0080 
0081         height: parent.height
0082 
0083         property int mouseCol
0084         property bool mousePressed: false
0085         property int pressX: -1
0086         property int pressY: -1
0087 
0088         hoverEnabled: true
0089         acceptedButtons: Qt.LeftButton | Qt.RightButton
0090 
0091         onPressed: mouse => {
0092             if (mouse.buttons & Qt.RightButton) {
0093                 if (item.hasActionList) {
0094                     item.openActionMenu(mouseArea, mouse.x, mouse.y);
0095                 }
0096             } else {
0097                 mousePressed = true;
0098                 pressX = mouse.x;
0099                 pressY = mouse.y;
0100             }
0101         }
0102 
0103         onReleased: mouse => {
0104             if (mousePressed && !item.hasChildren) {
0105                 item.ListView.view.model.trigger(index, "", null);
0106                 kicker.expanded = false;
0107             }
0108 
0109             mousePressed = false;
0110             pressX = -1;
0111             pressY = -1;
0112         }
0113 
0114         onPositionChanged: mouse => {
0115             if (pressX !== -1 && model.url && dragHelper.isDrag(pressX, pressY, mouse.x, mouse.y)) {
0116                 dragHelper.startDrag(kicker, model.url, model.decoration);
0117                 mousePressed = false;
0118                 pressX = -1;
0119                 pressY = -1;
0120 
0121                 return;
0122             }
0123 
0124             // FIXME: Correct escape angle calc for right screen edge.
0125             if (justOpenedTimer.running || !item.hasChildren) {
0126                 item.ListView.view.currentIndex = index;
0127             } else {
0128                 mouseCol = mouse.x;
0129 
0130                 if (index === item.ListView.view.currentIndex) {
0131                     updateCurrentItem();
0132                 } else if ((index === item.ListView.view.currentIndex - 1) && mouse.y < (itemHeight - 6)
0133                     || (index === item.ListView.view.currentIndex + 1) && mouse.y > 5) {
0134 
0135                     if ((item.childDialog && item.childDialog.facingLeft)
0136                         ? mouse.x > item.ListView.view.eligibleWidth - 5 : mouse.x < item.ListView.view.eligibleWidth + 5) {
0137                         updateCurrentItem();
0138                     }
0139                 } else if ((item.childDialog && item.childDialog.facingLeft)
0140                     ? mouse.x > item.ListView.view.eligibleWidth : mouse.x < item.ListView.view.eligibleWidth) {
0141                     updateCurrentItem();
0142                 }
0143 
0144                 updateCurrentItemTimer.start();
0145             }
0146         }
0147 
0148         onContainsMouseChanged: {
0149             if (!containsMouse) {
0150                 mousePressed = false;
0151                 pressX = -1;
0152                 pressY = -1;
0153                 updateCurrentItemTimer.stop();
0154             }
0155         }
0156 
0157         function updateCurrentItem() {
0158             item.ListView.view.currentIndex = index;
0159             item.ListView.view.eligibleWidth = Math.min(width, mouseCol);
0160         }
0161 
0162         Timer {
0163             id: updateCurrentItemTimer
0164 
0165             interval: 50
0166             repeat: false
0167 
0168             onTriggered: parent.updateCurrentItem()
0169         }
0170     }
0171 
0172     Row {
0173         id: row
0174 
0175         anchors.left: parent.left
0176         anchors.leftMargin: highlightItemSvg.margins.left
0177         anchors.right: parent.right
0178         anchors.rightMargin: highlightItemSvg.margins.right
0179 
0180         height: parent.height
0181 
0182         spacing: Kirigami.Units.smallSpacing * 2
0183         readonly property real actualSpacing: ((icon.visible ? 1 : 0) * spacing) + ((arrow.visible ? 1 : 0) * spacing)
0184 
0185         LayoutMirroring.enabled: (Qt.application.layoutDirection === Qt.RightToLeft)
0186 
0187         Kirigami.Icon {
0188             id: icon
0189 
0190             anchors.verticalCenter: parent.verticalCenter
0191 
0192             width: visible ? Kirigami.Units.iconSizes.small : 0
0193             height: width
0194 
0195             visible: iconsEnabled
0196 
0197             animated: false
0198             selected: item.iconAndLabelsShouldlookSelected
0199             source: model.decoration
0200         }
0201 
0202         PlasmaComponents3.Label {
0203             id: label
0204 
0205             enabled: !isParent || (isParent && item.hasChildren)
0206 
0207             anchors.verticalCenter: parent.verticalCenter
0208 
0209             width: parent.width - icon.width - arrow.width - parent.actualSpacing
0210 
0211             verticalAlignment: Text.AlignVCenter
0212 
0213             textFormat: Text.PlainText
0214             wrapMode: Text.NoWrap
0215             elide: Text.ElideRight
0216             color: item.iconAndLabelsShouldlookSelected ? Kirigami.Theme.highlightedTextColor : Kirigami.Theme.textColor
0217 
0218             text: model.display
0219         }
0220 
0221         Kirigami.Icon {
0222             id: arrow
0223 
0224             anchors.verticalCenter: parent.verticalCenter
0225 
0226             width: visible ? Kirigami.Units.iconSizes.small : 0
0227             height: width
0228 
0229             visible: item.hasChildren
0230             opacity: (item.ListView.view.currentIndex === index) ? 1.0 : 0.4
0231             selected: item.iconAndLabelsShouldlookSelected
0232             source: Qt.application.layoutDirection !== Qt.RightToLeft
0233                 ? "go-next-symbolic"
0234                 : "go-next-rtl-symbolic"
0235         }
0236     }
0237 
0238     Component {
0239         id: separatorComponent
0240 
0241         KSvg.SvgItem {
0242             width: parent.width
0243             height: lineSvg.horLineHeight
0244 
0245             svg: lineSvg
0246             elementId: "horizontal-line"
0247         }
0248     }
0249 
0250     Loader {
0251         id: separatorLoader
0252 
0253         anchors.left: parent.left
0254         anchors.leftMargin: highlightItemSvg.margins.left
0255         anchors.right: parent.right
0256         anchors.rightMargin: highlightItemSvg.margins.right
0257         anchors.verticalCenter: parent.verticalCenter
0258 
0259         // Separator positions don't make sense when sorting everything alphabetically
0260         active: item.isSeparator && !item.sorted
0261 
0262         asynchronous: false
0263         sourceComponent: separatorComponent
0264     }
0265 
0266     Keys.onPressed: {
0267         if (event.key === Qt.Key_Menu && item.hasActionList) {
0268             event.accepted = true;
0269             item.openActionMenu(mouseArea);
0270         } else if ((event.key === Qt.Key_Enter || event.key === Qt.Key_Return) && !item.hasChildren) {
0271             if (!item.hasChildren) {
0272                 event.accepted = true;
0273                 item.ListView.view.model.trigger(index, "", null);
0274                 kicker.expanded = false;
0275             }
0276         }
0277     }
0278 }