Warning, /plasma/plasma-desktop/applets/kicker/package/contents/ui/MenuRepresentation.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 import QtQuick.Layouts 1.15 0009 // Deliberately imported after QtQuick to avoid missing restoreMode property in Binding. Fix in Qt 6. 0010 import QtQml 2.15 0011 0012 import org.kde.plasma.core as PlasmaCore 0013 import org.kde.ksvg 1.0 as KSvg 0014 import org.kde.plasma.extras 2.0 as PlasmaExtras 0015 import org.kde.kirigami 2.20 as Kirigami 0016 import org.kde.plasma.plasmoid 2.0 0017 0018 FocusScope { 0019 id: root 0020 0021 focus: true 0022 0023 Layout.minimumWidth: (sideBar.width + (sideBar.width ? mainRow.spacing : 0) 0024 + Math.max(searchField.defaultWidth, runnerColumns.width)) 0025 Layout.maximumWidth: Math.max(mainRow.width, Layout.minimumWidth); // mainRow.width is constrained by rootList.maximumWidth 0026 0027 Layout.minimumHeight: Math.max(((rootModel.count - rootModel.separatorCount) * rootList.itemHeight) 0028 + (rootModel.separatorCount * rootList.separatorHeight) 0029 + searchField.height + (2 * Kirigami.Units.smallSpacing), sideBar.margins.top + sideBar.margins.bottom 0030 + favoriteApps.contentHeight + favoriteSystemActions.contentHeight + sidebarSeparator.height 0031 + (4 * Kirigami.Units.smallSpacing)) 0032 Layout.maximumHeight: Layout.minimumHeight 0033 0034 signal appendSearchText(string text) 0035 0036 function reset() { 0037 kicker.hideOnWindowDeactivate = true; 0038 0039 rootList.currentIndex = -1; 0040 0041 searchField.text = ""; 0042 searchField.focus = true; 0043 } 0044 0045 Row { 0046 id: mainRow 0047 0048 height: parent.height 0049 0050 spacing: Kirigami.Units.smallSpacing 0051 0052 LayoutMirroring.enabled: ((Plasmoid.location === PlasmaCore.Types.RightEdge) 0053 || (Qt.application.layoutDirection === Qt.RightToLeft && Plasmoid.location !== PlasmaCore.Types.LeftEdge)) 0054 0055 KSvg.FrameSvgItem { 0056 id: sideBar 0057 0058 visible: width > 0 0059 0060 width: (globalFavorites && systemFavorites 0061 && (globalFavorites.count + systemFavorites.count) 0062 ? Kirigami.Units.iconSizes.medium + margins.left + margins.right : 0) 0063 height: parent.height 0064 0065 imagePath: "widgets/frame" 0066 prefix: "plain" 0067 0068 SideBarSection { 0069 id: favoriteApps 0070 0071 anchors.top: parent.top 0072 anchors.topMargin: sideBar.margins.top 0073 0074 height: (sideBar.height - sideBar.margins.top - sideBar.margins.bottom 0075 - favoriteSystemActions.height - sidebarSeparator.height - (4 * Kirigami.Units.smallSpacing)) 0076 0077 model: globalFavorites 0078 0079 states: [ State { 0080 name: "top" 0081 when: (Plasmoid.location === PlasmaCore.Types.TopEdge) 0082 0083 AnchorChanges { 0084 target: favoriteApps 0085 anchors.top: undefined 0086 anchors.bottom: parent.bottom 0087 } 0088 0089 PropertyChanges { 0090 target: favoriteApps 0091 anchors.topMargin: undefined 0092 anchors.bottomMargin: sideBar.margins.bottom 0093 } 0094 }] 0095 0096 Binding { 0097 target: globalFavorites 0098 property: "iconSize" 0099 value: Kirigami.Units.iconSizes.medium 0100 restoreMode: Binding.RestoreBinding 0101 } 0102 } 0103 0104 KSvg.SvgItem { 0105 id: sidebarSeparator 0106 0107 anchors.bottom: favoriteSystemActions.top 0108 anchors.bottomMargin: (2 * Kirigami.Units.smallSpacing) 0109 anchors.horizontalCenter: parent.horizontalCenter 0110 0111 width: Kirigami.Units.iconSizes.medium 0112 height: lineSvg.horLineHeight 0113 0114 visible: (favoriteApps.model && favoriteApps.model.count 0115 && favoriteSystemActions.model && favoriteSystemActions.model.count) 0116 0117 svg: lineSvg 0118 elementId: "horizontal-line" 0119 0120 states: [ State { 0121 name: "top" 0122 when: (Plasmoid.location === PlasmaCore.Types.TopEdge) 0123 0124 AnchorChanges { 0125 target: sidebarSeparator 0126 anchors.top: favoriteSystemActions.bottom 0127 anchors.bottom: undefined 0128 0129 } 0130 0131 PropertyChanges { 0132 target: sidebarSeparator 0133 anchors.topMargin: (2 * Kirigami.Units.smallSpacing) 0134 anchors.bottomMargin: undefined 0135 } 0136 }] 0137 } 0138 0139 SideBarSection { 0140 id: favoriteSystemActions 0141 0142 anchors.bottom: parent.bottom 0143 anchors.bottomMargin: sideBar.margins.bottom 0144 0145 model: systemFavorites 0146 0147 states: [ State { 0148 name: "top" 0149 when: (Plasmoid.location === PlasmaCore.Types.TopEdge) 0150 0151 AnchorChanges { 0152 target: favoriteSystemActions 0153 anchors.top: parent.top 0154 anchors.bottom: undefined 0155 } 0156 0157 PropertyChanges { 0158 target: favoriteSystemActions 0159 anchors.topMargin: sideBar.margins.top 0160 anchors.bottomMargin: undefined 0161 } 0162 }] 0163 } 0164 } 0165 0166 ItemListView { 0167 id: rootList 0168 0169 anchors.top: parent.top 0170 0171 minimumWidth: root.Layout.minimumWidth - sideBar.width - mainRow.spacing 0172 height: ((rootModel.count - rootModel.separatorCount) * itemHeight) + (rootModel.separatorCount * separatorHeight) 0173 0174 visible: searchField.text === "" 0175 0176 iconsEnabled: Plasmoid.configuration.showIconsRootLevel 0177 0178 model: rootModel 0179 0180 onKeyNavigationAtListEnd: { 0181 searchField.focus = true; 0182 } 0183 0184 states: [ State { 0185 name: "top" 0186 when: (Plasmoid.location === PlasmaCore.Types.TopEdge) 0187 0188 AnchorChanges { 0189 target: rootList 0190 anchors.top: parent.top 0191 } 0192 }] 0193 0194 Component.onCompleted: { 0195 rootList.exited.connect(root.reset); 0196 } 0197 } 0198 0199 Row { 0200 id: runnerColumns 0201 0202 height: parent.height 0203 0204 signal focusChanged() 0205 0206 visible: searchField.text !== "" && runnerModel.count > 0 0207 0208 Repeater { 0209 id: runnerColumnsRepeater 0210 0211 model: runnerModel 0212 0213 delegate: RunnerResultsList { 0214 id: runnerMatches 0215 visible: runnerModel.modelForRow(index).count > 0 0216 0217 onKeyNavigationAtListEnd: { 0218 searchField.focus = true; 0219 } 0220 0221 onContainsMouseChanged: { 0222 if (containsMouse) { 0223 runnerMatches.focus = true; 0224 } 0225 } 0226 0227 onFocusChanged: { 0228 if (focus) { 0229 runnerColumns.focusChanged(); 0230 } 0231 } 0232 0233 function focusChanged() { 0234 if (!runnerMatches.focus && runnerMatches.currentIndex != -1) { 0235 runnerMatches.currentIndex = -1; 0236 } 0237 } 0238 0239 Keys.onPressed: event => { 0240 var target = null; 0241 0242 if (event.key === Qt.Key_Right) { 0243 var targets = new Array(); 0244 0245 for (var i = index + 1; i < runnerModel.count; ++i) { 0246 targets[targets.length] = i; 0247 } 0248 0249 for (var i = 0; i < index; ++i) { 0250 targets[targets.length] = i; 0251 } 0252 0253 for (var i = 0; i < targets.length; ++i) { 0254 if (runnerModel.modelForRow(targets[i]).count) { 0255 target = runnerColumnsRepeater.itemAt(targets[i]); 0256 break; 0257 } 0258 } 0259 } else if (event.key === Qt.Key_Left) { 0260 var targets = new Array(); 0261 0262 for (var i = index - 1; i >= 0; --i) { 0263 targets[targets.length] = i; 0264 } 0265 0266 for (var i = runnerModel.count - 1; i > index; --i) { 0267 targets[targets.length] = i; 0268 } 0269 0270 for (var i = 0; i < targets.length; ++i) { 0271 if (runnerModel.modelForRow(targets[i]).count) { 0272 target = runnerColumnsRepeater.itemAt(targets[i]); 0273 break; 0274 } 0275 } 0276 } 0277 0278 if (target) { 0279 event.accepted = true; 0280 currentIndex = -1; 0281 target.currentIndex = 0; 0282 target.focus = true; 0283 } 0284 } 0285 0286 Component.onCompleted: { 0287 runnerColumns.focusChanged.connect(focusChanged); 0288 } 0289 0290 Component.onDestruction: { 0291 runnerColumns.focusChanged.disconnect(focusChanged); 0292 } 0293 } 0294 } 0295 } 0296 } 0297 0298 PlasmaExtras.SearchField { 0299 id: searchField 0300 0301 anchors.bottom: mainRow.bottom 0302 anchors.left: parent.left 0303 anchors.leftMargin: sideBar.width + (sideBar.width ? mainRow.spacing : Kirigami.Units.smallSpacing) 0304 0305 readonly property real defaultWidth: Kirigami.Units.gridUnit * 14 0306 width: (runnerColumnsRepeater.count !== 0 ? runnerColumnsRepeater.itemAt(0).width 0307 : (rootList.visible ? rootList.width : defaultWidth)) 0308 0309 focus: !Kirigami.InputMethod.willShowOnActive 0310 0311 onTextChanged: { 0312 runnerModel.query = text; 0313 } 0314 0315 onFocusChanged: { 0316 if (focus) { 0317 // FIXME: Cleanup arbitration between rootList/runnerCols here and in Keys. 0318 if (rootList.visible) { 0319 rootList.currentIndex = -1; 0320 } 0321 0322 if (runnerColumns.visible) { 0323 runnerColumnsRepeater.itemAt(0).currentIndex = -1; 0324 } 0325 } 0326 } 0327 0328 states: [ State { 0329 name: "top" 0330 when: Plasmoid.location === PlasmaCore.Types.TopEdge 0331 0332 AnchorChanges { 0333 target: searchField 0334 anchors.top: undefined 0335 anchors.bottom: mainRow.bottom 0336 anchors.left: parent.left 0337 anchors.right: undefined 0338 } 0339 0340 PropertyChanges { 0341 target: searchField 0342 anchors.leftMargin: sideBar.width + mainRow.spacing + Kirigami.Units.smallSpacing 0343 anchors.rightMargin: undefined 0344 } 0345 }, 0346 State { 0347 name: "right" 0348 when: (Plasmoid.location === PlasmaCore.Types.RightEdge && Qt.application.layoutDirection === Qt.LeftToRight) 0349 || (Plasmoid.location === PlasmaCore.Types.LeftEdge && Qt.application.layoutDirection === Qt.RightToLeft) 0350 0351 AnchorChanges { 0352 target: searchField 0353 anchors.top: undefined 0354 anchors.bottom: mainRow.bottom 0355 anchors.left: undefined 0356 anchors.right: parent.right 0357 } 0358 0359 PropertyChanges { 0360 target: searchField 0361 anchors.leftMargin: undefined 0362 anchors.rightMargin: sideBar.width + mainRow.spacing + Kirigami.Units.smallSpacing 0363 } 0364 }] 0365 0366 Keys.onPressed: event => { 0367 if (event.key === Qt.Key_Up) { 0368 if (rootList.visible) { 0369 rootList.showChildDialogs = false; 0370 rootList.currentIndex = rootList.model.count - 1; 0371 rootList.forceActiveFocus(); 0372 rootList.showChildDialogs = true; 0373 } 0374 0375 if (runnerColumns.visible) { 0376 for (var i = 0; i < runnerModel.count; ++i) { 0377 if (runnerModel.modelForRow(i).count) { 0378 var targetList = runnerColumnsRepeater.itemAt(i); 0379 targetList.currentIndex = runnerModel.modelForRow(i).count - 1; 0380 targetList.forceActiveFocus(); 0381 break; 0382 } 0383 } 0384 } 0385 } else if (event.key === Qt.Key_Down) { 0386 if (rootList.visible) { 0387 rootList.showChildDialogs = false; 0388 rootList.currentIndex = Math.min(1, rootList.count); 0389 rootList.forceActiveFocus(); 0390 rootList.showChildDialogs = true; 0391 } 0392 0393 if (runnerColumns.visible) { 0394 for (var i = 0; i < runnerModel.count; ++i) { 0395 if (runnerModel.modelForRow(i).count) { 0396 var targetList = runnerColumnsRepeater.itemAt(i); 0397 targetList.currentIndex = Math.min(1, targetList.count); 0398 targetList.forceActiveFocus(); 0399 break; 0400 } 0401 } 0402 } 0403 } else if (event.key === Qt.Key_Left && cursorPosition === 0) { 0404 for (var i = runnerModel.count; i >= 0; --i) { 0405 if (runnerModel.modelForRow(i).count) { 0406 var targetList = runnerColumnsRepeater.itemAt(i); 0407 targetList.currentIndex = 0; 0408 targetList.forceActiveFocus(); 0409 break; 0410 } 0411 } 0412 } else if (event.key === Qt.Key_Right && cursorPosition === length) { 0413 for (var i = 1; i < runnerModel.count; ++i) { 0414 if (runnerModel.modelForRow(i).count) { 0415 var targetList = runnerColumnsRepeater.itemAt(i); 0416 targetList.currentIndex = 0; 0417 targetList.forceActiveFocus(); 0418 break; 0419 } 0420 } 0421 } else if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) { 0422 if (runnerColumns.visible && runnerModel.modelForRow(0).count) { 0423 runnerModel.modelForRow(0).trigger(0, "", null); 0424 kicker.expanded = false; 0425 } 0426 } 0427 } 0428 0429 function appendText(newText) { 0430 focus = true; 0431 text = text + newText; 0432 } 0433 } 0434 0435 Keys.onPressed: event => { 0436 if (event.key === Qt.Key_Escape) { 0437 kicker.expanded = false; 0438 } 0439 } 0440 0441 Component.onCompleted: { 0442 appendSearchText.connect(searchField.appendText); 0443 0444 kicker.reset.connect(reset); 0445 windowSystem.hidden.connect(reset); 0446 0447 rootModel.refresh(); 0448 } 0449 }