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 }