Warning, /plasma/plasma-desktop/applets/taskmanager/package/contents/ui/GroupDialog.qml is written in an unsupported language. File is not indexed.
0001 /*
0002 SPDX-FileCopyrightText: 2012-2013 Eike Hein <hein@kde.org>
0003 SPDX-FileCopyrightText: 2021 Fushan Wen <qydwhotmail@gmail.com>
0004
0005 SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007
0008 import QtQuick 2.15
0009 // Deliberately imported after QtQuick to avoid missing restoreMode property in Binding. Fix in Qt 6.
0010 import QtQml 2.15
0011 import QtQml.Models 2.15
0012 import QtQuick.Window 2.15
0013
0014 import org.kde.plasma.core as PlasmaCore
0015 import org.kde.plasma.components 3.0 as PlasmaComponents3
0016 import org.kde.draganddrop 2.0
0017 import org.kde.kirigami 2.20 as Kirigami
0018 import org.kde.plasma.plasmoid 2.0
0019
0020 import "code/layout.js" as LayoutManager
0021
0022 PlasmaCore.Dialog {
0023 id: groupDialog
0024 visible: true
0025
0026 type: PlasmaCore.Dialog.PopupMenu
0027 flags: Qt.WindowStaysOnTopHint
0028 hideOnWindowDeactivate: true
0029 location: Plasmoid.location
0030
0031 readonly property real preferredWidth: Screen.width / (3 * Screen.devicePixelRatio)
0032 readonly property real preferredHeight: Screen.height / (2 * Screen.devicePixelRatio)
0033 readonly property real contentWidth: mainItem.width // No padding here to avoid text elide.
0034
0035 property alias overflowing: scrollView.overflowing
0036 property var _oldAppletStatus: PlasmaCore.Types.UnknownStatus
0037
0038 function findActiveTaskIndex() {
0039 if (!tasksModel.activeTask) {
0040 return;
0041 }
0042 for (let i = 0; i < groupListView.count; i++) {
0043 if (tasksModel.makeModelIndex(visualParent.index, i) === tasksModel.activeTask) {
0044 groupListView.positionViewAtIndex(i, ListView.Contain); // Prevent visual glitches
0045 groupListView.currentIndex = i;
0046 return;
0047 }
0048 }
0049 }
0050
0051 mainItem: MouseHandler {
0052 id: mouseHandler
0053 width: Math.min(groupDialog.preferredWidth, Math.max(groupListView.maxWidth, groupDialog.visualParent.width))
0054 height: Math.min(groupDialog.preferredHeight, groupListView.maxHeight)
0055
0056 target: groupListView
0057 handleWheelEvents: !scrollView.overflowing
0058 isGroupDialog: true
0059
0060 Keys.onEscapePressed: groupDialog.visible = false
0061
0062 function moveRow(event, insertAt) {
0063 if (!(event.modifiers & Qt.ControlModifier) || !(event.modifiers & Qt.ShiftModifier)) {
0064 event.accepted = false;
0065 return;
0066 } else if (insertAt < 0 || insertAt >= groupListView.count) {
0067 return;
0068 }
0069
0070 const parentModelIndex = tasksModel.makeModelIndex(groupDialog.visualParent.index);
0071 const status = tasksModel.move(groupListView.currentIndex, insertAt, parentModelIndex);
0072 if (!status) {
0073 return;
0074 }
0075
0076 groupListView.currentIndex = insertAt;
0077 }
0078
0079 PlasmaComponents3.ScrollView {
0080 id: scrollView
0081 anchors.fill: parent
0082 readonly property bool overflowing: leftPadding > 0 || rightPadding > 0 // Scrollbar is visible
0083
0084 ListView {
0085 id: groupListView
0086
0087 readonly property real maxWidth: groupFilter.maxTextWidth
0088 + LayoutManager.horizontalMargins()
0089 + Kirigami.Units.iconSizes.medium
0090 + 2 * (LayoutManager.labelMargin + LayoutManager.iconMargin)
0091 + scrollView.leftPadding + scrollView.rightPadding
0092 // Use groupFilter.count because sometimes count is not updated in time (BUG 446105)
0093 readonly property real maxHeight: groupFilter.count * (LayoutManager.verticalMargins() + Math.max(Kirigami.Units.iconSizes.sizeForLabels, Kirigami.Units.iconSizes.medium))
0094
0095 model: DelegateModel {
0096 id: groupFilter
0097
0098 readonly property TextMetrics textMetrics: TextMetrics {}
0099 property real maxTextWidth: 0
0100
0101 model: tasksModel
0102 rootIndex: tasksModel.makeModelIndex(groupDialog.visualParent.index)
0103 delegate: Task {
0104 width: groupListView.width
0105 visible: true
0106 inPopup: true
0107
0108 ListView.onRemove: Qt.callLater(groupFilter.updateMaxTextWidth)
0109 Connections {
0110 enabled: index < 20 // 20 is based on performance considerations.
0111
0112 function onLabelTextChanged() { // ListView.onAdd included
0113 if (groupFilter.maxTextWidth === 0) {
0114 // Update immediately to avoid shrinking
0115 groupFilter.updateMaxTextWidth();
0116 } else {
0117 Qt.callLater(groupFilter.updateMaxTextWidth);
0118 }
0119 }
0120 }
0121 }
0122
0123 function updateMaxTextWidth() {
0124 let tempMaxTextWidth = 0;
0125 // 20 is based on performance considerations.
0126 for (let i = 0; i < Math.min(count, 20); i++) {
0127 textMetrics.text = items.get(i).model.display;
0128 if (textMetrics.boundingRect.width > tempMaxTextWidth) {
0129 tempMaxTextWidth = textMetrics.boundingRect.width;
0130 }
0131 }
0132 maxTextWidth = tempMaxTextWidth;
0133 }
0134 }
0135
0136 reuseItems: false
0137
0138 Keys.onUpPressed: mouseHandler.moveRow(event, groupListView.currentIndex - 1);
0139 Keys.onDownPressed: mouseHandler.moveRow(event, groupListView.currentIndex + 1);
0140
0141 onCountChanged: {
0142 if (count > 0) {
0143 backend.cancelHighlightWindows()
0144 } else {
0145 groupDialog.visible = false;
0146 }
0147 }
0148 }
0149 }
0150 }
0151
0152 onVisibleChanged: {
0153 if (visible) {
0154 _oldAppletStatus = Plasmoid.status;
0155 Plasmoid.status = PlasmaCore.Types.RequiresAttentionStatus;
0156
0157 groupDialog.requestActivate();
0158 groupListView.forceActiveFocus(); // Active focus on ListView so keyboard navigation can work.
0159 Qt.callLater(findActiveTaskIndex);
0160 } else {
0161 Plasmoid.status = _oldAppletStatus;
0162 tasks.groupDialog = null;
0163 destroy();
0164 }
0165 }
0166 }