Warning, /plasma/plasma-workspace/applets/systemtray/package/contents/ui/main.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 SPDX-FileCopyrightText: 2011 Marco Martin <mart@kde.org> 0003 SPDX-FileCopyrightText: 2020 Konrad Materka <materka@gmail.com> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 import QtQuick 2.5 0009 import QtQuick.Layouts 1.1 0010 import QtQuick.Window 2.15 0011 import org.kde.plasma.core as PlasmaCore 0012 import org.kde.ksvg 1.0 as KSvg 0013 import org.kde.plasma.plasmoid 2.0 0014 import org.kde.draganddrop 2.0 as DnD 0015 import org.kde.kirigami 2.5 as Kirigami // For Settings.tabletMode 0016 import org.kde.kitemmodels 1.0 as KItemModels 0017 0018 import "items" 0019 0020 ContainmentItem { 0021 id: root 0022 0023 readonly property bool vertical: Plasmoid.formFactor === PlasmaCore.Types.Vertical 0024 0025 Layout.minimumWidth: vertical ? Kirigami.Units.iconSizes.small : mainLayout.implicitWidth + Kirigami.Units.smallSpacing 0026 Layout.minimumHeight: vertical ? mainLayout.implicitHeight + Kirigami.Units.smallSpacing : Kirigami.Units.iconSizes.small 0027 0028 LayoutMirroring.enabled: !vertical && Qt.application.layoutDirection === Qt.RightToLeft 0029 LayoutMirroring.childrenInherit: true 0030 0031 readonly property alias systemTrayState: systemTrayState 0032 readonly property alias itemSize: tasksGrid.itemSize 0033 readonly property alias visibleLayout: tasksGrid 0034 readonly property alias hiddenLayout: expandedRepresentation.hiddenLayout 0035 readonly property bool oneRowOrColumn: tasksGrid.rowsOrColumns === 1 0036 0037 MouseArea { 0038 anchors.fill: parent 0039 0040 onWheel: { 0041 // Don't propagate unhandled wheel events 0042 wheel.accepted = true; 0043 } 0044 0045 SystemTrayState { 0046 id: systemTrayState 0047 } 0048 0049 //being there forces the items to fully load, and they will be reparented in the popup one by one, this item is *never* visible 0050 Item { 0051 id: preloadedStorage 0052 visible: false 0053 } 0054 0055 CurrentItemHighLight { 0056 location: Plasmoid.location 0057 parent: root 0058 } 0059 0060 DnD.DropArea { 0061 anchors.fill: parent 0062 0063 preventStealing: true 0064 0065 /** Extracts the name of the system tray applet in the drag data if present 0066 * otherwise returns null*/ 0067 function systemTrayAppletName(event) { 0068 if (event.mimeData.formats.indexOf("text/x-plasmoidservicename") < 0) { 0069 return null; 0070 } 0071 const plasmoidId = event.mimeData.getDataAsByteArray("text/x-plasmoidservicename"); 0072 0073 if (!Plasmoid.isSystemTrayApplet(plasmoidId)) { 0074 return null; 0075 } 0076 return plasmoidId; 0077 } 0078 0079 onDragEnter: { 0080 if (!systemTrayAppletName(event)) { 0081 event.ignore(); 0082 } 0083 } 0084 0085 onDrop: { 0086 const plasmoidId = systemTrayAppletName(event); 0087 if (!plasmoidId) { 0088 event.ignore(); 0089 return; 0090 } 0091 0092 if (Plasmoid.configuration.extraItems.indexOf(plasmoidId) < 0) { 0093 const extraItems = Plasmoid.configuration.extraItems; 0094 extraItems.push(plasmoidId); 0095 Plasmoid.configuration.extraItems = extraItems; 0096 } 0097 } 0098 } 0099 0100 0101 //Main Layout 0102 GridLayout { 0103 id: mainLayout 0104 0105 rowSpacing: 0 0106 columnSpacing: 0 0107 anchors.fill: parent 0108 0109 flow: vertical ? GridLayout.TopToBottom : GridLayout.LeftToRight 0110 0111 GridView { 0112 id: tasksGrid 0113 0114 Layout.alignment: Qt.AlignCenter 0115 0116 interactive: false //disable features we don't need 0117 flow: vertical ? GridView.LeftToRight : GridView.TopToBottom 0118 0119 // The icon size to display when not using the auto-scaling setting 0120 readonly property int smallIconSize: Kirigami.Units.iconSizes.smallMedium 0121 0122 // Automatically use autoSize setting when in tablet mode, if it's 0123 // not already being used 0124 readonly property bool autoSize: Plasmoid.configuration.scaleIconsToFit || Kirigami.Settings.tabletMode 0125 0126 readonly property int gridThickness: root.vertical ? root.width : root.height 0127 // Should change to 2 rows/columns on a 56px panel (in standard DPI) 0128 readonly property int rowsOrColumns: autoSize ? 1 : Math.max(1, Math.min(count, Math.floor(gridThickness / (smallIconSize + Kirigami.Units.smallSpacing)))) 0129 0130 // Add margins only if the panel is larger than a small icon (to avoid large gaps between tiny icons) 0131 readonly property int cellSpacing: Kirigami.Units.smallSpacing * (Kirigami.Settings.tabletMode ? 6 : Plasmoid.configuration.iconSpacing) 0132 readonly property int smallSizeCellLength: gridThickness < smallIconSize ? smallIconSize : smallIconSize + cellSpacing 0133 0134 cellHeight: { 0135 if (root.vertical) { 0136 return autoSize ? itemSize + (gridThickness < itemSize ? 0 : cellSpacing) : smallSizeCellLength 0137 } else { 0138 return autoSize ? root.height : Math.floor(root.height / rowsOrColumns) 0139 } 0140 } 0141 cellWidth: { 0142 if (root.vertical) { 0143 return autoSize ? root.width : Math.floor(root.width / rowsOrColumns) 0144 } else { 0145 return autoSize ? itemSize + (gridThickness < itemSize ? 0 : cellSpacing) : smallSizeCellLength 0146 } 0147 } 0148 0149 //depending on the form factor, we are calculating only one dimension, second is always the same as root/parent 0150 implicitHeight: root.vertical ? cellHeight * Math.ceil(count / rowsOrColumns) : root.height 0151 implicitWidth: !root.vertical ? cellWidth * Math.ceil(count / rowsOrColumns) : root.width 0152 0153 readonly property int itemSize: { 0154 if (autoSize) { 0155 return Kirigami.Units.iconSizes.roundedIconSize(Math.min(Math.min(root.width, root.height) / rowsOrColumns, Kirigami.Units.iconSizes.enormous)) 0156 } else { 0157 return smallIconSize 0158 } 0159 } 0160 0161 model: KItemModels.KSortFilterProxyModel { 0162 sourceModel: Plasmoid.systemTrayModel 0163 filterRoleName: "effectiveStatus" 0164 filterRowCallback: (sourceRow, sourceParent) => { 0165 let value = sourceModel.data(sourceModel.index(sourceRow, 0, sourceParent), filterRole); 0166 return value === PlasmaCore.Types.ActiveStatus; 0167 } 0168 } 0169 0170 delegate: ItemLoader { 0171 id: delegate 0172 0173 width: tasksGrid.cellWidth 0174 height: tasksGrid.cellHeight 0175 minLabelHeight: 0 0176 0177 // We need to recalculate the stacking order of the z values due to how keyboard navigation works 0178 // the tab order depends exclusively from this, so we redo it as the position in the list 0179 // ensuring tab navigation focuses the expected items 0180 Component.onCompleted: { 0181 let item = tasksGrid.itemAtIndex(index - 1); 0182 if (item) { 0183 Plasmoid.stackItemBefore(delegate, item) 0184 } else { 0185 item = tasksGrid.itemAtIndex(index + 1); 0186 } 0187 if (item) { 0188 Plasmoid.stackItemAfter(delegate, item) 0189 } 0190 } 0191 } 0192 0193 add: Transition { 0194 enabled: itemSize > 0 && Component.status == Component.Ready 0195 0196 NumberAnimation { 0197 property: "scale" 0198 from: 0 0199 to: 1 0200 easing.type: Easing.InOutQuad 0201 duration: Kirigami.Units.longDuration 0202 } 0203 } 0204 0205 displaced: Transition { 0206 //ensure scale value returns to 1.0 0207 //https://doc.qt.io/qt-5/qml-qtquick-viewtransition.html#handling-interrupted-animations 0208 enabled: Component.status == Component.Ready 0209 NumberAnimation { 0210 property: "scale" 0211 to: 1 0212 easing.type: Easing.InOutQuad 0213 duration: Kirigami.Units.longDuration 0214 } 0215 } 0216 0217 move: Transition { 0218 NumberAnimation { 0219 properties: "x,y" 0220 easing.type: Easing.InOutQuad 0221 duration: Kirigami.Units.longDuration 0222 } 0223 } 0224 } 0225 0226 ExpanderArrow { 0227 id: expander 0228 Layout.fillWidth: vertical 0229 Layout.fillHeight: !vertical 0230 Layout.alignment: vertical ? Qt.AlignVCenter : Qt.AlignHCenter 0231 iconSize: tasksGrid.itemSize 0232 visible: root.hiddenLayout.itemCount > 0 0233 } 0234 } 0235 0236 Timer { 0237 id: expandedSync 0238 interval: 100 0239 onTriggered: systemTrayState.expanded = dialog.visible; 0240 } 0241 0242 //Main popup 0243 PlasmaCore.AppletPopup { 0244 id: dialog 0245 objectName: "popupWindow" 0246 visualParent: root 0247 popupDirection: switch (Plasmoid.location) { 0248 case PlasmaCore.Types.TopEdge: 0249 return Qt.BottomEdge 0250 case PlasmaCore.Types.LeftEdge: 0251 return Qt.RightEdge 0252 case PlasmaCore.Types.RightEdge: 0253 return Qt.LeftEdge 0254 default: 0255 return Qt.TopEdge 0256 } 0257 margin: (Plasmoid.containmentDisplayHints & PlasmaCore.Types.ContainmentPrefersFloatingApplets) ? Kirigami.Units.largeSpacing : 0 0258 0259 floating: Plasmoid.location == PlasmaCore.Desktop 0260 0261 removeBorderStrategy: Plasmoid.location === PlasmaCore.Types.Floating 0262 ? PlasmaCore.AppletPopup.AtScreenEdges 0263 : PlasmaCore.AppletPopup.AtScreenEdges | PlasmaCore.AppletPopup.AtPanelEdges 0264 0265 0266 hideOnWindowDeactivate: !Plasmoid.configuration.pin 0267 visible: systemTrayState.expanded 0268 appletInterface: root 0269 0270 backgroundHints: (Plasmoid.containmentDisplayHints & PlasmaCore.Types.ContainmentPrefersOpaqueBackground) ? PlasmaCore.AppletPopup.SolidBackground : PlasmaCore.AppletPopup.StandardBackground 0271 0272 onVisibleChanged: { 0273 if (!visible) { 0274 expandedSync.restart(); 0275 } else { 0276 if (expandedRepresentation.plasmoidContainer.visible) { 0277 expandedRepresentation.plasmoidContainer.forceActiveFocus(); 0278 } else if (expandedRepresentation.hiddenLayout.visible) { 0279 expandedRepresentation.hiddenLayout.forceActiveFocus(); 0280 } 0281 } 0282 } 0283 mainItem: ExpandedRepresentation { 0284 id: expandedRepresentation 0285 0286 Keys.onEscapePressed: { 0287 systemTrayState.expanded = false 0288 } 0289 0290 // Draws a line between the applet dialog and the panel 0291 KSvg.SvgItem { 0292 id: separator 0293 // Only draw for popups of panel applets, not desktop applets 0294 visible: [PlasmaCore.Types.TopEdge, PlasmaCore.Types.LeftEdge, PlasmaCore.Types.RightEdge, PlasmaCore.Types.BottomEdge] 0295 .includes(Plasmoid.location) && !dialog.margin 0296 anchors { 0297 topMargin: -dialog.topMargin 0298 leftMargin: -dialog.leftMargin 0299 rightMargin: -dialog.rightMargin 0300 bottomMargin: -dialog.bottomMargin 0301 } 0302 z: 999 /* Draw the line on top of the applet */ 0303 elementId: (Plasmoid.location === PlasmaCore.Types.TopEdge || Plasmoid.location === PlasmaCore.Types.BottomEdge) ? "horizontal-line" : "vertical-line" 0304 imagePath: "widgets/line" 0305 // Use states instead of bindings to work around https://bugreports.qt.io/browse/QTBUG-120464 0306 states: [ 0307 State { 0308 when: Plasmoid.location === PlasmaCore.Types.TopEdge 0309 AnchorChanges { 0310 target: separator 0311 anchors { 0312 top: separator.parent.top 0313 left: separator.parent.left 0314 right: separator.parent.right 0315 } 0316 } 0317 PropertyChanges { 0318 target: separator 0319 height: 1 0320 } 0321 }, 0322 State { 0323 when: Plasmoid.location === PlasmaCore.Types.LeftEdge 0324 AnchorChanges { 0325 target: separator 0326 anchors { 0327 left: separator.parent.left 0328 top: separator.parent.top 0329 bottom: separator.parent.bottom 0330 } 0331 } 0332 PropertyChanges { 0333 target: separator 0334 width: 1 0335 } 0336 }, 0337 State { 0338 when: Plasmoid.location === PlasmaCore.Types.RightEdge 0339 AnchorChanges { 0340 target: separator 0341 anchors { 0342 top: separator.parent.top 0343 right: separator.parent.right 0344 bottom: separator.parent.bottom 0345 } 0346 } 0347 PropertyChanges { 0348 target: separator 0349 width: 1 0350 } 0351 }, 0352 State { 0353 when: Plasmoid.location === PlasmaCore.Types.BottomEdge 0354 AnchorChanges { 0355 target: separator 0356 anchors { 0357 left: separator.parent.left 0358 right: separator.parent.right 0359 bottom: separator.parent.bottom 0360 } 0361 } 0362 PropertyChanges { 0363 target: separator 0364 height: 1 0365 } 0366 } 0367 ] 0368 } 0369 0370 LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft 0371 LayoutMirroring.childrenInherit: true 0372 } 0373 } 0374 } 0375 }