Warning, /plasma/plasma-mobile/components/mobileshell/qml/widgets/krunner/KRunnerWidget.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 * SPDX-FileCopyrightText: 2014 Aaron Seigo <aseigo@kde.org> 0003 * SPDX-FileCopyrightText: 2015 Marco Martin <notmart@gmail.com> 0004 * SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org> 0005 * 0006 * SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 import QtQuick 0010 import QtQuick.Effects 0011 import QtQuick.Controls as Controls 0012 import QtQuick.Layouts 0013 0014 import org.kde.plasma.core as PlasmaCore 0015 import org.kde.plasma.components 3.0 as PlasmaComponents 0016 import org.kde.plasma.extras 2.0 as PlasmaExtras 0017 0018 import org.kde.milou as Milou 0019 import org.kde.kirigami 2.19 as Kirigami 0020 0021 /** 0022 * Search widget that is embedded into the homescreen. The dimensions of 0023 * the root item is assumed to be the available screen area for applications. 0024 */ 0025 Item { 0026 id: root 0027 0028 // content margins (background ignores this) 0029 property real topMargin: 0 0030 property real bottomMargin: 0 0031 property real leftMargin: 0 0032 property real rightMargin: 0 0033 0034 function startGesture() { 0035 queryField.text = ""; 0036 flickable.contentY = closedContentY; 0037 } 0038 0039 function updateGestureOffset(yOffset) { 0040 flickable.contentY = Math.max(0, Math.min(closedContentY, flickable.contentY + yOffset)); 0041 } 0042 0043 // call when the touch gesture has let go 0044 function endGesture() { 0045 flickable.opening ? open() : close(); 0046 } 0047 0048 // open the search widget (animated) 0049 function open() { 0050 anim.to = openedContentY; 0051 anim.restart(); 0052 } 0053 0054 // close the search widget (animated) 0055 function close() { 0056 anim.to = closedContentY; 0057 anim.restart(); 0058 } 0059 0060 // emitted when an item on the ListView is triggered 0061 signal actionTriggered() 0062 0063 readonly property real closedContentY: Kirigami.Units.gridUnit * 5 0064 readonly property real openedContentY: 0 0065 readonly property real openFactor: Math.max(0, Math.min(1, 1 - flickable.contentY / closedContentY)) 0066 readonly property bool isOpen: openFactor != 0 0067 0068 Rectangle { 0069 anchors.fill: parent 0070 color: Qt.rgba(0, 0, 0, 0.3) 0071 opacity: root.openFactor 0072 } 0073 0074 onOpacityChanged: { 0075 if (opacity === 0) { 0076 close(); 0077 } 0078 } 0079 0080 Keys.onPressed: event => { 0081 if (event.key === Qt.Key_Down) { 0082 listView.forceActiveFocus(); 0083 } 0084 } 0085 0086 Flickable { 0087 id: flickable 0088 0089 anchors.fill: parent 0090 anchors.topMargin: root.topMargin 0091 anchors.bottomMargin: root.bottomMargin 0092 anchors.leftMargin: root.leftMargin 0093 anchors.rightMargin: root.rightMargin 0094 0095 contentHeight: flickable.height + root.closedContentY 0096 contentY: root.closedContentY 0097 property real oldContentY: contentY 0098 property bool opening: false 0099 0100 onContentYChanged: { 0101 opening = contentY < oldContentY; 0102 oldContentY = contentY; 0103 0104 if (contentY !== root.openedContentY) { 0105 queryField.focus = false; 0106 } 0107 } 0108 0109 onMovementEnded: root.endGesture() 0110 0111 onDraggingChanged: { 0112 if (!dragging) { 0113 root.endGesture(); 0114 } 0115 } 0116 0117 NumberAnimation on contentY { 0118 id: anim 0119 duration: Kirigami.Units.longDuration * 2 0120 easing.type: Easing.OutQuad 0121 running: false 0122 onFinished: { 0123 if (anim.to === root.openedContentY) { 0124 queryField.forceActiveFocus(); 0125 } 0126 } 0127 } 0128 0129 ColumnLayout { 0130 id: column 0131 height: flickable.height 0132 width: flickable.width 0133 0134 Controls.Control { 0135 opacity: root.openFactor 0136 Layout.fillWidth: true 0137 Layout.maximumWidth: Kirigami.Units.gridUnit * 30 0138 Layout.alignment: Qt.AlignHCenter 0139 Layout.topMargin: Kirigami.Units.gridUnit 0140 Layout.leftMargin: Kirigami.Units.gridUnit 0141 Layout.rightMargin: Kirigami.Units.gridUnit 0142 0143 leftPadding: Kirigami.Units.smallSpacing 0144 rightPadding: Kirigami.Units.smallSpacing 0145 topPadding: Kirigami.Units.smallSpacing 0146 bottomPadding: Kirigami.Units.smallSpacing 0147 0148 background: Item { 0149 0150 // shadow for search window 0151 MultiEffect { 0152 anchors.fill: parent 0153 source: rectBackground 0154 blurMax: 16 0155 shadowEnabled: true 0156 shadowVerticalOffset: 1 0157 shadowOpacity: 0.15 0158 } 0159 0160 Rectangle { 0161 id: rectBackground 0162 anchors.fill: parent 0163 color: Kirigami.Theme.backgroundColor 0164 radius: Kirigami.Units.smallSpacing 0165 } 0166 } 0167 0168 contentItem: RowLayout { 0169 Item { 0170 implicitHeight: queryField.height 0171 implicitWidth: height 0172 Kirigami.Icon { 0173 anchors.fill: parent 0174 anchors.margins: Math.round(Kirigami.Units.smallSpacing) 0175 source: "start-here-symbolic" 0176 } 0177 } 0178 PlasmaComponents.TextField { 0179 id: queryField 0180 Layout.fillWidth: true 0181 placeholderText: i18n("Search…") 0182 inputMethodHints: Qt.ImhNoPredictiveText // don't need to press "enter" to update text 0183 } 0184 } 0185 } 0186 0187 Controls.ScrollView { 0188 opacity: root.openFactor === 1 ? 1 : 0 0189 Behavior on opacity { 0190 NumberAnimation { duration: Kirigami.Units.shortDuration } 0191 } 0192 0193 Layout.fillWidth: true 0194 Layout.fillHeight: listView.contentHeight > availableHeight 0195 0196 Milou.ResultsListView { 0197 id: listView 0198 queryString: queryField.text 0199 clip: true 0200 Kirigami.Theme.colorSet: Kirigami.Theme.Window 0201 0202 highlight: activeFocus ? highlightComponent : null 0203 Component { 0204 id: highlightComponent 0205 0206 PlasmaExtras.Highlight {} 0207 } 0208 0209 onActivated: { 0210 root.close(); 0211 } 0212 onUpdateQueryString: { 0213 queryField.text = text 0214 queryField.cursorPosition = cursorPosition 0215 } 0216 0217 delegate: MouseArea { 0218 id: delegate 0219 height: rowLayout.height 0220 width: listView.width 0221 0222 onClicked: { 0223 listView.currentIndex = model.index; 0224 listView.runCurrentIndex(); 0225 0226 root.actionTriggered(); 0227 } 0228 hoverEnabled: true 0229 0230 function activateNextAction() { 0231 queryField.forceActiveFocus(); 0232 queryField.selectAll(); 0233 listView.currentIndex = -1; 0234 } 0235 0236 Rectangle { 0237 anchors.fill: parent 0238 color: delegate.pressed ? Qt.rgba(255, 255, 255, 0.2) : (delegate.containsMouse ? Qt.rgba(255, 255, 255, 0.05) : "transparent") 0239 Behavior on color { 0240 ColorAnimation { duration: Kirigami.Units.shortDuration } 0241 } 0242 } 0243 0244 RowLayout { 0245 id: rowLayout 0246 height: Kirigami.Units.gridUnit * 3 0247 anchors.top: parent.top 0248 anchors.left: parent.left 0249 anchors.right: parent.right 0250 anchors.leftMargin: Kirigami.Units.gridUnit 0251 anchors.rightMargin: Kirigami.Units.gridUnit 0252 0253 Kirigami.Icon { 0254 Layout.alignment: Qt.AlignVCenter 0255 source: model.decoration 0256 implicitWidth: Kirigami.Units.iconSizes.medium 0257 implicitHeight: Kirigami.Units.iconSizes.medium 0258 } 0259 0260 ColumnLayout { 0261 Layout.fillWidth: true 0262 Layout.alignment: Qt.AlignVCenter 0263 spacing: Kirigami.Units.smallSpacing 0264 0265 PlasmaComponents.Label { 0266 id: title 0267 Layout.fillWidth: true 0268 Layout.leftMargin: Kirigami.Units.smallSpacing * 2 0269 Layout.rightMargin: Kirigami.Units.gridUnit 0270 0271 maximumLineCount: 1 0272 elide: Text.ElideRight 0273 text: typeof modelData !== "undefined" ? modelData : model.display 0274 color: "white" 0275 0276 font.pointSize: Kirigami.Theme.defaultFont.pointSize 0277 } 0278 PlasmaComponents.Label { 0279 id: subtitle 0280 Layout.fillWidth: true 0281 Layout.leftMargin: Kirigami.Units.smallSpacing * 2 0282 Layout.rightMargin: Kirigami.Units.gridUnit 0283 0284 maximumLineCount: 1 0285 elide: Text.ElideRight 0286 text: model.subtext || "" 0287 color: "white" 0288 opacity: 0.8 0289 0290 font.pointSize: Math.round(Kirigami.Theme.defaultFont.pointSize * 0.8) 0291 } 0292 } 0293 0294 Repeater { 0295 id: actionsRepeater 0296 model: typeof actions !== "undefined" ? actions : [] 0297 0298 Controls.ToolButton { 0299 icon: modelData.icon || "" 0300 visible: modelData.visible || true 0301 enabled: modelData.enabled || true 0302 0303 Accessible.role: Accessible.Button 0304 Accessible.name: modelData.text 0305 checkable: checked 0306 checked: delegate.activeAction === index 0307 focus: delegate.activeAction === index 0308 onClicked: delegate.ListView.view.runAction(index) 0309 } 0310 } 0311 } 0312 } 0313 } 0314 } 0315 0316 MouseArea { 0317 Layout.fillWidth: true 0318 Layout.fillHeight: true 0319 0320 onClicked: close() 0321 } 0322 } 0323 } 0324 }