Changeset View
Changeset View
Standalone View
Standalone View
applets/weather/package/contents/ui/config/WeatherStationPicker.qml
Show All 11 Lines | |||||
12 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. | ||
13 | * | 13 | * | ||
14 | * You should have received a copy of the GNU General Public License | 14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | 16 | */ | ||
17 | 17 | | |||
18 | import QtQuick 2.9 | 18 | import QtQuick 2.9 | ||
19 | 19 | | |||
20 | import QtQuick.Controls 1.4 as QQC1 | | |||
21 | import QtQuick.Controls 2.5 as QQC2 | 20 | import QtQuick.Controls 2.5 as QQC2 | ||
22 | import QtQuick.Layouts 1.3 | 21 | import QtQuick.Layouts 1.3 | ||
22 | import org.kde.kirigami 2.8 as Kirigami | ||||
23 | 23 | | |||
24 | import org.kde.plasma.private.weather 1.0 | 24 | import org.kde.plasma.private.weather 1.0 | ||
25 | 25 | | |||
26 | 26 | | |||
27 | ColumnLayout { | 27 | ColumnLayout { | ||
28 | id: root | 28 | id: root | ||
29 | 29 | | |||
30 | property alias selectedServices: serviceListModel.selectedServices | 30 | property alias selectedServices: serviceListModel.selectedServices | ||
31 | property string source | 31 | property string source | ||
32 | readonly property bool canSearch: !!searchStringEdit.text && selectedServices.length | 32 | readonly property bool canSearch: !!searchStringEdit.text && selectedServices.length | ||
33 | readonly property bool handlesEnterKey: canSearch && searchStringEdit.activeFocus | 33 | readonly property bool handlesEnterKey: canSearch && searchStringEdit.activeFocus | ||
34 | 34 | | |||
35 | function searchLocation() { | 35 | function searchLocation() { | ||
36 | if (!canSearch) { | 36 | if (!canSearch) { | ||
37 | return; | 37 | return; | ||
38 | } | 38 | } | ||
39 | | ||||
40 | // avoid automatic selection once model is refilled | | |||
41 | locationListView.currentRow = -1; | | |||
42 | locationListView.selection.clear(); | | |||
43 | noSearchResultReport.visible = false; | 39 | noSearchResultReport.visible = false; | ||
44 | source = ""; | 40 | source = ""; | ||
45 | locationListView.forceActiveFocus(); | | |||
46 | | ||||
47 | locationListModel.searchLocations(searchStringEdit.text, selectedServices); | 41 | locationListModel.searchLocations(searchStringEdit.text, selectedServices); | ||
broulik: You no longer hide the `noSearchResultsReport` label when a new query starts, awkwardly… | |||||
48 | } | 42 | } | ||
49 | 43 | | |||
50 | function handleLocationSearchDone(success, searchString) { | 44 | LocationListModel { | ||
Given the item is hidden anyway, you can probably assign this as a binding right away broulik: Given the item is hidden anyway, you can probably assign this as a binding right away | |||||
45 | id: locationListModel | ||||
46 | onLocationSearchDone: { | ||||
51 | if (!success) { | 47 | if (!success) { | ||
52 | noSearchResultReport.text = i18nc("@info", "No weather stations found for '%1'", searchString); | 48 | noSearchResultReport.text = i18nc("@info", "No weather stations found for '%1'", searchString); | ||
53 | noSearchResultReport.visible = true; | 49 | noSearchResultReport.visible = true; | ||
50 | } else { | ||||
51 | // If we got any results, pre-select the top item to potentially | ||||
52 | // save the user a step | ||||
53 | locationListView.currentIndex = 0; | ||||
54 | locationListView.forceActiveFocus(); | ||||
55 | noSearchResultReport.visible = false; | ||||
54 | } | 56 | } | ||
55 | } | 57 | } | ||
56 | | ||||
57 | LocationListModel { | | |||
58 | id: locationListModel | | |||
59 | onLocationSearchDone: handleLocationSearchDone(success, searchString); | | |||
60 | } | 58 | } | ||
61 | 59 | | |||
62 | ServiceListModel { | 60 | ServiceListModel { | ||
63 | id: serviceListModel | 61 | id: serviceListModel | ||
64 | } | 62 | } | ||
65 | 63 | | |||
66 | QQC2.Menu { | 64 | QQC2.Menu { | ||
67 | id: serviceSelectionMenu | 65 | id: serviceSelectionMenu | ||
Show All 15 Lines | 67 | Instantiator { | |||
83 | onObjectRemoved: serviceSelectionMenu.removeItem(object) | 81 | onObjectRemoved: serviceSelectionMenu.removeItem(object) | ||
84 | } | 82 | } | ||
85 | 83 | | |||
86 | } | 84 | } | ||
87 | 85 | | |||
88 | RowLayout { | 86 | RowLayout { | ||
89 | Layout.fillWidth: true | 87 | Layout.fillWidth: true | ||
90 | 88 | | |||
91 | QQC2.TextField { | 89 | Kirigami.SearchField { | ||
92 | id: searchStringEdit | 90 | id: searchStringEdit | ||
93 | 91 | | |||
94 | Layout.fillWidth: true | 92 | Layout.fillWidth: true | ||
95 | Layout.minimumWidth: implicitWidth | 93 | Layout.minimumWidth: implicitWidth | ||
94 | focus: true | ||||
Maybe explicitly focus this it when the dialog opens again otherwise on subsequent opening of the dialog it will instead have whatever item was focused previously? broulik: Maybe explicitly focus this it when the dialog opens again otherwise on subsequent opening of… | |||||
96 | placeholderText: i18nc("@info:placeholder", "Enter location") | 95 | placeholderText: i18nc("@info:placeholder", "Enter location") | ||
97 | onAccepted: { | 96 | onAccepted: { | ||
98 | searchLocation(); | 97 | searchLocation(); | ||
99 | } | 98 | } | ||
100 | } | 99 | } | ||
101 | 100 | | |||
102 | QQC2.Button { | 101 | QQC2.Button { | ||
103 | id: serviceSelectionButton | 102 | id: serviceSelectionButton | ||
Show All 18 Lines | 116 | QQC2.Button { | |||
122 | enabled: canSearch | 121 | enabled: canSearch | ||
123 | 122 | | |||
124 | onClicked: { | 123 | onClicked: { | ||
125 | searchLocation(); | 124 | searchLocation(); | ||
126 | } | 125 | } | ||
127 | } | 126 | } | ||
128 | } | 127 | } | ||
129 | 128 | | |||
130 | QQC1.TableView { | 129 | QQC2.ScrollView { | ||
131 | id: locationListView | | |||
132 | | ||||
133 | function tableItemActivated() { | | |||
134 | if (locationListView.row !== -1 && locationListView.rowCount) { | | |||
135 | source = locationListModel.valueForListIndex(locationListView.row); | | |||
136 | } | | |||
137 | } | | |||
138 | | ||||
139 | Layout.minimumWidth: implicitWidth | | |||
140 | Layout.minimumHeight: implicitHeight | | |||
141 | Layout.fillWidth: true | 130 | Layout.fillWidth: true | ||
142 | Layout.fillHeight: true | 131 | Layout.fillHeight: true | ||
143 | 132 | | |||
144 | headerVisible: false | 133 | Component.onCompleted: { | ||
134 | background.visible = true; | ||||
135 | } | ||||
Does focus: true on the TextField instead of the ListView make this redundant? broulik: Does `focus: true` on the `TextField` instead of the `ListView` make this redundant? | |||||
136 | | ||||
137 | ListView { | ||||
138 | id: locationListView | ||||
145 | model: locationListModel | 139 | model: locationListModel | ||
140 | clip: true | ||||
141 | focus: true | ||||
142 | activeFocusOnTab: true | ||||
143 | keyNavigationEnabled: true | ||||
146 | 144 | | |||
broulik: This is unlike any other list we have in settings? | |||||
ngraham: I copied it from the notifications KCM :) | |||||
broulik: The notifications KCM doesn't wrap, though? | |||||
147 | onActivated: tableItemActivated(); | 145 | onCurrentItemChanged: { | ||
148 | onClicked: { | 146 | source = locationListModel.valueForListIndex(locationListView.currentIndex); | ||
broulik: Unused `id` | |||||
149 | locationListView.forceActiveFocus; | | |||
150 | tableItemActivated(); | | |||
151 | } | 147 | } | ||
152 | 148 | | |||
153 | QQC1.TableViewColumn { | 149 | delegate: QQC2.ItemDelegate { | ||
154 | id: locationListViewStationColumn | 150 | width: locationListView.width | ||
151 | text: model.display | ||||
152 | highlighted: ListView.isCurrentItem | ||||
155 | 153 | | |||
156 | movable: false | 154 | onClicked: { | ||
157 | resizable: false | 155 | locationListView.forceActiveFocus(); | ||
158 | role: "display" | 156 | locationListView.currentIndex = index; | ||
157 | } | ||||
159 | } | 158 | } | ||
160 | 159 | | |||
161 | QQC2.Label { | 160 | QQC2.Label { | ||
162 | id: noSearchResultReport | 161 | id: noSearchResultReport | ||
163 | 162 | | |||
164 | anchors.fill: parent | 163 | anchors.fill: parent | ||
165 | horizontalAlignment: Text.AlignHCenter | 164 | horizontalAlignment: Text.AlignHCenter | ||
166 | verticalAlignment: Text.AlignVCenter | 165 | verticalAlignment: Text.AlignVCenter | ||
167 | wrapMode: Text.WordWrap | 166 | wrapMode: Text.WordWrap | ||
This should be set programatically when the query finishes like before instead of a binding. Otherwise you'll end up in the weird situation where it says "Nothing found for foo" and then you start typing a new query and it live updates to "Nothing found for bar" even though you didn't actually launch a new query broulik: This should be set programatically when the query finishes like before instead of a binding. | |||||
168 | visible: false | 167 | visible: false | ||
You're constantly breaking this binding by assigning to it elsewhere programmatically. broulik: You're constantly breaking this binding by assigning to it elsewhere programmatically. | |||||
168 | enabled: false | ||||
169 | } | 169 | } | ||
170 | 170 | | |||
171 | QQC2.BusyIndicator { | 171 | QQC2.BusyIndicator { | ||
172 | id: busy | 172 | id: busy | ||
173 | 173 | | |||
174 | anchors.centerIn: parent | 174 | anchors.centerIn: parent | ||
175 | 175 | | |||
176 | visible: locationListModel.validatingInput | 176 | visible: locationListModel.validatingInput | ||
177 | } | 177 | } | ||
178 | } | 178 | } | ||
179 | } | ||||
179 | 180 | | |||
180 | Component.onCompleted: { | 181 | Component.onCompleted: { | ||
181 | searchStringEdit.forceActiveFocus(); | 182 | searchStringEdit.forceActiveFocus(); | ||
182 | } | 183 | } | ||
183 | } | 184 | } |
You no longer hide the noSearchResultsReport label when a new query starts, awkwardly overlapping the busy indicator until the new one completes.