Warning, /plasma/kdeplasma-addons/applets/weather/package/contents/ui/config/ConfigWeatherStation.qml is written in an unsupported language. File is not indexed.
0001 /*
0002 * SPDX-FileCopyrightText: 2016, 2018 Friedrich W. H. Kossebau <kossebau@kde.org>
0003 * SPDX-FileCopyrightText: 2022 Ismael Asensio <isma.af@gmail.com>
0004 *
0005 * SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007
0008 import QtQuick
0009 import QtQuick.Controls as QQC2
0010 import QtQuick.Layouts
0011
0012 import org.kde.kirigami as Kirigami
0013 import org.kde.plasma.plasmoid
0014 import org.kde.plasma.private.weather
0015 import org.kde.kcmutils as KCM
0016
0017 KCM.ScrollViewKCM {
0018 id: weatherStationConfigPage
0019
0020 property string cfg_source
0021 property alias cfg_updateInterval: updateIntervalSpin.value
0022
0023 readonly property var providers: Plasmoid.providers
0024
0025 readonly property var sourceDetails: cfg_source ? cfg_source.split('|') : ""
0026 readonly property bool hasSource: sourceDetails.length > 2
0027 readonly property bool canSearch: !!searchStringEdit.text && Object.keys(providers).length
0028
0029 // The model property `isValidatingInput` doesn't account for the timer delay
0030 // We use a custom property to provide a more responsive feedback
0031 property bool isSearching: false
0032
0033 LocationListModel {
0034 id: locationListModel
0035 onLocationSearchDone: {
0036 isSearching = false;
0037 }
0038 }
0039
0040 header: ColumnLayout {
0041
0042 spacing: Kirigami.Units.smallSpacing
0043
0044 Kirigami.FormLayout {
0045 id: formLayout
0046
0047 QQC2.SpinBox {
0048 id: updateIntervalSpin
0049
0050 Kirigami.FormData.label: i18nc("@label:spinbox", "Update every:")
0051
0052 textFromValue: function(value) {
0053 return (i18np("%1 minute", "%1 minutes", value));
0054 }
0055 valueFromText: function(text) {
0056 return parseInt(text);
0057 }
0058
0059 from: 30
0060 to: 3600
0061 editable: true
0062 }
0063
0064 QQC2.Label {
0065 Kirigami.FormData.label: i18nc("@label", "Location:")
0066
0067 Layout.fillWidth: true
0068 elide: Text.ElideRight
0069 opacity: hasSource ? 1 : 0.7
0070
0071 text: hasSource ? sourceDetails[2] : i18nc("No location is currently selected", "None selected")
0072 textFormat: Text.PlainText
0073 }
0074
0075 QQC2.Label {
0076 Kirigami.FormData.label: hasSource ? i18nc("@label", "Provider:") : ""
0077
0078 Layout.fillWidth: true
0079 elide: Text.ElideRight
0080 // Keep it visible to avoid height changes which can confuse AppletConfigurationPage
0081 opacity: hasSource ? 1 : 0
0082
0083 text: hasSource ? providers[sourceDetails[0]] : ""
0084 textFormat: Text.PlainText
0085 }
0086
0087 Item {
0088 // This dummy item adds some spacing and makes the form layout less jumpy
0089 Kirigami.FormData.isSection: true
0090 implicitWidth: Math.min(Kirigami.Units.gridUnit * 15, weatherStationConfigPage.width - Kirigami.Units.gridUnit)
0091 }
0092 }
0093
0094 Kirigami.SearchField {
0095 id: searchStringEdit
0096
0097 Layout.fillWidth: true
0098
0099 focus: true
0100 enabled: Object.keys(providers).length > 0
0101 placeholderText: hasSource ? i18nc("@info:placeholder", "Enter new location") : i18nc("@info:placeholder", "Enter location")
0102
0103 Timer {
0104 id: searchDelayTimer
0105 interval: 500
0106 onTriggered: {
0107 if (!canSearch) {
0108 locationListModel.clear();
0109 return;
0110 }
0111 locationListModel.searchLocations(searchStringEdit.text, Object.keys(providers));
0112 }
0113 }
0114
0115 onTextChanged: {
0116 isSearching = text.length > 0
0117 searchDelayTimer.restart();
0118 }
0119
0120 Keys.onUpPressed: {
0121 if (locationListView.currentIndex != 0) {
0122 locationListView.currentIndex--;
0123 }
0124 event.accepted = true;
0125 }
0126 Keys.onDownPressed: {
0127 if (locationListView.currentIndex != locationListView.count - 1) {
0128 locationListView.currentIndex++;
0129 }
0130 event.accepted = true;
0131 }
0132 Keys.onEscapePressed: {
0133 if (searchStringEdit.text.length === 0) {
0134 event.accepted = false;
0135 return;
0136 }
0137 searchStringEdit.clear();
0138 event.accepted = true;
0139 }
0140 }
0141 }
0142
0143 view: ListView {
0144 id: locationListView
0145 model: locationListModel
0146 focus: true
0147 activeFocusOnTab: true
0148 keyNavigationEnabled: true
0149 enabled: Object.keys(providers).length > 0
0150
0151 onCurrentIndexChanged: {
0152 const source = locationListModel.valueForListIndex(locationListView.currentIndex);
0153 if (source) {
0154 weatherStationConfigPage.cfg_source = source;
0155 }
0156 }
0157
0158 delegate: QQC2.ItemDelegate {
0159 width: locationListView.width
0160 text: model.display
0161 highlighted: ListView.isCurrentItem
0162
0163 onClicked: {
0164 locationListView.forceActiveFocus();
0165 locationListView.currentIndex = index;
0166 }
0167 }
0168
0169 // To avoid start with a highlighted item on the next search
0170 onCountChanged: {
0171 if (count === 0) {
0172 currentIndex = -1;
0173 }
0174 }
0175
0176 Keys.forwardTo: searchStringEdit
0177
0178 Kirigami.PlaceholderMessage {
0179 id: listViewPlaceholder
0180 anchors.centerIn: parent
0181 width: parent.width - Kirigami.Units.gridUnit
0182 visible: locationListView.count === 0 && !isSearching
0183 text: {
0184 if (canSearch) { // There is a search text
0185 return i18nc("@info", "No weather stations found for '%1'", searchStringEdit.text);
0186 } else if (hasSource) {
0187 return i18nc("@info", "Search for a weather station to change your location");
0188 } else {
0189 return i18nc("@info", "Search for a weather station to set your location");
0190 }
0191 }
0192
0193 }
0194
0195 QQC2.BusyIndicator {
0196 id: busy
0197 anchors.centerIn: parent
0198 visible: locationListView.count === 0 && isSearching
0199 }
0200 }
0201 }