Warning, /utilities/kweather/src/qml/locationslist/LocationsListView.qml is written in an unsupported language. File is not indexed.

0001 /*
0002  * SPDX-FileCopyrightText: 2020 Han Young <hanyoung@protonmail.com>
0003  * SPDX-FileCopyrightText: 2020-2022 Devin Lin <espidev@gmail.com>
0004  * SPDX-FileCopyrightText: 2021 Nicolas Fella <nicolas.fella@gmx.de>
0005  *
0006  * SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 import QtQuick
0010 import QtQuick.Controls
0011 import QtQuick.Layouts
0012 import QtQml.Models
0013 
0014 import org.kde.kirigami as Kirigami
0015 
0016 import org.kde.kweather
0017 
0018 import org.kde.kweather.components
0019 
0020 ListView {
0021     id: root
0022     
0023     signal closeRequested()
0024     
0025     DelegateModel {
0026         id: visualModel
0027         model: WeatherLocationListModel
0028         delegate: delegateComponent
0029     }
0030     
0031     model: visualModel
0032     
0033     reuseItems: true
0034     currentIndex: -1 // no default highlight
0035 
0036     add: Transition {
0037         NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: Kirigami.Units.shortDuration }
0038     }
0039     remove: Transition {
0040         NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: Kirigami.Units.shortDuration }
0041     }
0042     displaced: Transition {
0043         NumberAnimation { properties: "x,y"; duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad}
0044     }
0045     moveDisplaced: Transition {
0046         YAnimator {
0047             duration: Kirigami.Units.longDuration
0048             easing.type: Easing.InOutQuad
0049         }
0050     }
0051     
0052     Connections {
0053         target: WeatherLocationListModel
0054         function onNetworkErrorCreating() {
0055             showPassiveNotification(i18n("Unable to fetch timezone information"));
0056         }
0057     }
0058 
0059     Kirigami.PlaceholderMessage {
0060         anchors.centerIn: parent
0061         anchors.left: parent.left
0062         anchors.right: parent.right
0063         anchors.margins: Kirigami.Units.largeSpacing
0064 
0065         icon.name: "globe"
0066         text: i18n("Add a location")
0067         visible: root.count == 0
0068         
0069         helpfulAction: Kirigami.Action {
0070             icon.name: "list-add"
0071             text: i18n("Add Location")
0072             onTriggered: applicationWindow().openAddLocation()
0073         }
0074     }
0075 
0076     Component {
0077         id: delegateComponent
0078         
0079         Item {
0080             id: dragParent
0081             width: listItem.width
0082             height: listItem.height
0083             
0084             property int visualIndex: DelegateModel.itemsIndex
0085             property bool held: false // whether it is being dragged
0086             z: held ? 1 : 0
0087             
0088             // logic for receiving drag events
0089             DropArea {
0090                 anchors.fill: parent
0091                 
0092                 onEntered: (drag) => {
0093                     let from = drag.source.visualIndex;
0094                     let to = dragParent.visualIndex;
0095                     
0096                     if (from !== undefined && to !== undefined && from !== to) {
0097                         visualModel.items.move(from, to);
0098                         WeatherLocationListModel.move(from, to);
0099                     }
0100                 }
0101             }
0102             
0103             ListDelegate {
0104                 id: listItem
0105                 width: root.width
0106                 
0107                 leftPadding: Kirigami.Units.largeSpacing
0108                 rightPadding: Kirigami.Units.largeSpacing
0109                 topPadding: Kirigami.Units.largeSpacing
0110                 bottomPadding: Kirigami.Units.largeSpacing
0111                 
0112                 onClicked: {
0113                     root.closeRequested();
0114                     applicationWindow().switchToPage(applicationWindow().getPage("Forecast"), 0);
0115                     applicationWindow().getPage("Forecast").switchPageIndex(index);
0116                 }
0117                 
0118                 function deleteItem() {
0119                     // if there are no locations left
0120                     if (WeatherLocationListModel.count === 1) {
0121                         root.closeRequested();
0122                     }
0123                     WeatherLocationListModel.remove(index);
0124                 }
0125                 
0126                 // drag logic
0127                 Drag.active: dragParent.held
0128                 Drag.source: dragHandle
0129                 Drag.hotSpot.x: width / 2
0130                 Drag.hotSpot.y: height / 2
0131                 
0132                 // remove anchors when dragging
0133                 anchors.horizontalCenter: parent.horizontalCenter
0134                 anchors.verticalCenter: parent.verticalCenter
0135                 states: [
0136                     State {
0137                         when: dragHandle.drag.active
0138                         ParentChange {
0139                             target: listItem
0140                             parent: root
0141                         }
0142                         
0143                         AnchorChanges {
0144                             target: listItem
0145                             anchors.horizontalCenter: undefined
0146                             anchors.verticalCenter: undefined
0147                         }
0148                     }
0149                 ]
0150 
0151                 // list delegate contents
0152                 contentItem: RowLayout {
0153                     spacing: 0
0154 
0155                     // handle for desktop users to drag
0156                     MouseArea {
0157                         id: dragHandle
0158                         implicitWidth: Kirigami.Units.iconSizes.smallMedium
0159                         implicitHeight: Kirigami.Units.iconSizes.smallMedium
0160                         cursorShape: pressed ? Qt.ClosedHandCursor : Qt.OpenHandCursor
0161                         preventStealing: true
0162                         
0163                         property int visualIndex: dragParent.visualIndex
0164                         
0165                         drag.target: dragParent.held ? listItem : undefined
0166                         drag.axis: Drag.YAxis
0167                         
0168                         onPressed: dragParent.held = true;
0169                         onReleased: dragParent.held = false;
0170                         
0171                         Kirigami.Icon {
0172                             anchors.fill: parent
0173                             source: "handle-sort"
0174                             opacity: dragHandle.pressed || (!Kirigami.Settings.tabletMode && dragHandle.hovered) ? 1 : 0.6
0175                         }
0176                     }
0177                     
0178                     // weather icon and temperature
0179                     ColumnLayout {
0180                         Layout.leftMargin: Kirigami.Units.largeSpacing * 2
0181                         Layout.rightMargin: Kirigami.Units.largeSpacing * 2
0182                         spacing: Kirigami.Units.smallSpacing
0183                         Kirigami.Icon {
0184                             Layout.alignment: Qt.AlignHCenter
0185                             source: model.location.hourForecasts[0] ? model.location.hourForecasts[0].weatherIcon : "weather-none-available"
0186                             Layout.maximumHeight: Kirigami.Units.iconSizes.sizeForLabels * 2
0187                             Layout.preferredWidth: height
0188                             Layout.preferredHeight: Kirigami.Units.iconSizes.sizeForLabels * 2
0189                         }
0190                         Label {
0191                             Layout.alignment: Qt.AlignHCenter
0192                             font.pointSize: Kirigami.Theme.defaultFont.pointSize * 1.3
0193                             text: Formatter.formatTemperatureRounded(model.location.hourForecasts[0].temperature, settingsModel.temperatureUnits)
0194                         }
0195                     }
0196         
0197                     // location name
0198                     Kirigami.Heading {
0199                         Layout.alignment: Qt.AlignLeft
0200                         Layout.fillWidth: true
0201                         
0202                         level: 2
0203                         text: model.location.name
0204                         elide: Text.ElideRight
0205                         maximumLineCount: 2
0206                         wrapMode: Text.Wrap
0207                     }
0208                     
0209                     ToolButton {
0210                         Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
0211                         Layout.leftMargin: Kirigami.Units.smallSpacing
0212                         
0213                         icon.name: "delete"
0214                         text: i18n("Delete")
0215                         onClicked: listItem.deleteItem();
0216                         display: AbstractButton.IconOnly
0217                         
0218                         ToolTip.delay: Kirigami.Units.toolTipDelay
0219                         ToolTip.timeout: 5000
0220                         ToolTip.visible: Kirigami.Settings.tabletMode ? pressed : hovered
0221                         ToolTip.text: text
0222                     }
0223                 }
0224             }
0225         }
0226     }
0227 
0228     delegate: delegateComponent
0229 }