Warning, /plasma/milou/lib/qml/ResultsView.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 * This file is part of the KDE Milou Project 0003 * SPDX-FileCopyrightText: 2013-2014 Vishesh Handa <me@vhanda.in> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0006 * 0007 */ 0008 0009 import QtQuick 2.1 0010 0011 import org.kde.plasma.components 2.0 as PlasmaComponents // for Highlight 0012 import org.kde.plasma.core 2.0 as PlasmaCore 0013 import org.kde.milou 0.3 as Milou 0014 0015 ListView { 0016 id: listView 0017 property alias queryString: resultModel.queryString 0018 property alias runner: resultModel.runner 0019 property alias runnerManager: resultModel.runnerManager 0020 0021 property alias runnerName: resultModel.runnerName 0022 property alias runnerIcon: resultModel.runnerIcon 0023 property alias querying: resultModel.querying 0024 property alias limit: resultModel.limit 0025 property bool reversed 0026 signal activated 0027 signal updateQueryString(string text, int cursorPosition) 0028 0029 // NOTE this also flips increment/decrementCurrentIndex (Bug 360789) 0030 verticalLayoutDirection: reversed ? ListView.BottomToTop : ListView.TopToBottom 0031 keyNavigationWraps: true 0032 highlight: PlasmaComponents.Highlight {} 0033 highlightMoveDuration: 0 0034 activeFocusOnTab: true 0035 Accessible.role: Accessible.List 0036 0037 section { 0038 criteria: ViewSection.FullString 0039 property: "category" 0040 } 0041 0042 // This is used to keep track if the user has pressed enter before 0043 // the first result has been shown, in the case the first result should 0044 // be run when the model is populated 0045 property bool runAutomatically 0046 0047 // This is used to disable mouse selection if the user interacts only with keyboard 0048 property bool moved: false 0049 property point savedMousePosition: Milou.MouseHelper.globalMousePosition() 0050 function mouseMovedGlobally() { 0051 return savedMousePosition != Milou.MouseHelper.globalMousePosition(); 0052 } 0053 0054 Milou.DragHelper { 0055 id: dragHelper 0056 dragIconSize: units.iconSizes.medium 0057 } 0058 0059 model: Milou.ResultsModel { 0060 id: resultModel 0061 limit: 15 0062 onQueryStringChangeRequested: { 0063 listView.updateQueryString(queryString, pos) 0064 } 0065 Component.onCompleted: { 0066 if (typeof runnerWindow !== "undefined") { 0067 runnerWindow.runnerManager = runnerManager 0068 } 0069 } 0070 onQueryStringChanged: () => { 0071 resetView(); 0072 // Do not run the results automatically, if the query changed since we pressed enter 0073 // BUG: 459859 0074 runAutomatically = false; 0075 } 0076 onModelReset: resetView() 0077 0078 onRowsInserted: { 0079 // Keep the selection at the top as items inserted to the beginning will shift it downwards 0080 // ListView will update its view after this signal is processed and then our callLater will set it back 0081 if (listView.currentIndex === 0) { 0082 Qt.callLater(function() { 0083 listView.currentIndex = 0; 0084 }); 0085 } 0086 0087 if (runAutomatically) { 0088 // This needs to be delayed as running a result may close the window and clear the query 0089 // having us reset the model whilst in the middle of processing the insertion. 0090 // The proxy model chain that comes after us really doesn't like this. 0091 Qt.callLater(function() { 0092 resultModel.run(resultModel.index(0, 0)); 0093 listView.activated(); 0094 }); 0095 0096 runAutomatically = false; 0097 } 0098 } 0099 0100 function resetView() { 0101 listView.currentIndex = 0; 0102 listView.moved = false; 0103 listView.savedMousePosition = Milou.MouseHelper.globalMousePosition(); 0104 } 0105 } 0106 0107 delegate: ResultDelegate { 0108 id: resultDelegate 0109 width: listView.width 0110 reversed: listView.reversed 0111 } 0112 0113 // 0114 // vHanda: Ideally this should have gotten handled in the delagte's onReturnPressed 0115 // code, but the ListView doesn't seem forward keyboard events to the delgate when 0116 // it is not in activeFocus. Even manually adding Keys.forwardTo: resultDelegate 0117 // doesn't make any difference! 0118 Keys.onReturnPressed: runCurrentIndex(event); 0119 Keys.onEnterPressed: runCurrentIndex(event); 0120 0121 function runCurrentIndex(event) { 0122 if (!currentItem) { 0123 runAutomatically = true 0124 return; 0125 } else { 0126 // If user presses Shift+Return to invoke an action, invoke the first runner action 0127 if (event && event.modifiers === Qt.ShiftModifier 0128 && currentItem.additionalActions && currentItem.additionalActions.length > 0) { 0129 runAction(0) 0130 return 0131 } 0132 0133 if (currentItem.activeAction > -1) { 0134 runAction(currentItem.activeAction) 0135 return 0136 } 0137 0138 if (resultModel.run(resultModel.index(currentIndex, 0))) { 0139 activated() 0140 } 0141 runAutomatically = false 0142 } 0143 } 0144 0145 function runAction(index) { 0146 if (resultModel.runAction(resultModel.index(currentIndex, 0), index)) { 0147 activated() 0148 } 0149 } 0150 0151 onActiveFocusChanged: { 0152 if (!activeFocus && currentIndex == listView.count-1) { 0153 currentIndex = 0; 0154 } 0155 } 0156 0157 Keys.onTabPressed: { 0158 if (!currentItem || !currentItem.activateNextAction()) { 0159 if (reversed) { 0160 if (currentIndex == 0) { 0161 listView.nextItemInFocusChain(false).forceActiveFocus(); 0162 return; 0163 } 0164 decrementCurrentIndex() 0165 } else { 0166 if (currentIndex == listView.count-1) { 0167 listView.nextItemInFocusChain(true).forceActiveFocus(); 0168 return; 0169 } 0170 incrementCurrentIndex() 0171 } 0172 } 0173 } 0174 Keys.onBacktabPressed: { 0175 if (!currentItem || !currentItem.activatePreviousAction()) { 0176 if (reversed) { 0177 if (currentIndex == listView.count-1) { 0178 listView.nextItemInFocusChain(true).forceActiveFocus(); 0179 return; 0180 } 0181 incrementCurrentIndex() 0182 } else { 0183 if (currentIndex == 0) { 0184 listView.nextItemInFocusChain(false).forceActiveFocus(); 0185 return; 0186 } 0187 decrementCurrentIndex() 0188 } 0189 0190 // activate previous action cannot know whether we want to back tab from an action 0191 // to the main result or back tab from another search result, so we explicitly highlight 0192 // the last action here to provide a consistent navigation experience 0193 if (currentItem) { 0194 currentItem.activateLastAction() 0195 } 0196 } 0197 } 0198 Keys.onUpPressed: reversed ? incrementCurrentIndex() : decrementCurrentIndex(); 0199 Keys.onDownPressed: reversed ? decrementCurrentIndex() : incrementCurrentIndex(); 0200 0201 boundsBehavior: Flickable.StopAtBounds 0202 0203 function loadSettings() { 0204 resultModel.loadSettings() 0205 } 0206 0207 function setQueryString(queryString) { 0208 resultModel.queryString = queryString 0209 runAutomatically = false 0210 } 0211 }