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 }