Warning, /plasma/plasma-workspace/kcms/nightcolor/ui/LocationsFixedView.qml is written in an unsupported language. File is not indexed.

0001 /*
0002     SPDX-FileCopyrightText: 2017 Roman Gilg <subdiff@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 import QtQuick 2.15
0008 import QtQuick.Layouts 1.1
0009 import QtQuick.Controls 2.15 as QQC2
0010 import org.kde.kirigami 2.15 as Kirigami
0011 import org.kde.kcmutils as KCM
0012 import Qt5Compat.GraphicalEffects
0013 
0014 Kirigami.FormLayout {
0015 
0016     /* Equirectangular projection maps (x, y) to (lat, long) cleanly */
0017     function longitudeToX(lon) {
0018         return (lon + 180) * (mapImage.width  / 360);
0019     }
0020     function latitudeToY(lat) {
0021         return (90 - lat) * (mapImage.height / 180);
0022     }
0023 
0024     function xToLongitude(x) {
0025         return (x / (mapImage.width  / 360)) - 180;
0026     }
0027     function yToLatitude(y) {
0028         return 90 - (y / (mapImage.height / 180));
0029     }
0030 
0031     ColumnLayout {
0032         QQC2.Label {
0033             id: mapLabel
0034             wrapMode: Text.Wrap
0035             Layout.maximumWidth: mapRect.width
0036             Layout.bottomMargin: Kirigami.Units.smallSpacing
0037             Layout.alignment: Qt.AlignHCenter
0038             text: Kirigami.Settings.tabletMode
0039                 ? i18nc("@label:chooser Tap should be translated to mean touching using a touchscreen", "Tap to choose your location on the map.")
0040                 : i18nc("@label:chooser Click should be translated to mean clicking using a mouse", "Click to choose your location on the map.")
0041             textFormat: Text.PlainText
0042             font: Kirigami.Theme.smallFont
0043         }
0044 
0045         Kirigami.ShadowedRectangle {
0046             id: mapRect
0047             Layout.alignment: Qt.AlignHCenter
0048             implicitWidth: Kirigami.Units.gridUnit * 30
0049             Layout.maximumWidth: Kirigami.Units.gridUnit * 30
0050             implicitHeight: Kirigami.Units.gridUnit * 15
0051             Layout.maximumHeight: Kirigami.Units.gridUnit * 15
0052             radius: Kirigami.Units.smallSpacing
0053             Kirigami.Theme.inherit: false
0054             Kirigami.Theme.colorSet: Kirigami.Theme.View
0055             color: Kirigami.Theme.backgroundColor
0056             shadow.xOffset: 0
0057             shadow.yOffset: 2
0058             shadow.size: 10
0059             shadow.color: Qt.rgba(0, 0, 0, 0.3)
0060 
0061             property double zoomFactor: 1.2;
0062             property double currentScale: 1.0;
0063 
0064             /* Zoom in/out buttons */
0065             RowLayout {
0066                 anchors {
0067                     right: parent.right
0068                     rightMargin: Kirigami.Units.smallSpacing*2
0069                     bottom: parent.bottom
0070                     bottomMargin: Kirigami.Units.smallSpacing*2
0071                 }
0072 
0073                 // Always show above thumbnail content
0074                 z: 9999
0075 
0076                 QQC2.Button {
0077                     // HACK: using list-add and list-remove for more obvious/standard zoom icons till we change the Breeze ones
0078                     // https://bugs.kde.org/show_bug.cgi?id=435671
0079                     text: i18n("Zoom in")
0080                     display: QQC2.AbstractButton.IconOnly
0081                     icon.name: kcm.isIconThemeBreeze() ? "list-add" : "zoom-in"
0082                     activeFocusOnTab: false
0083                     onClicked: {
0084                         if (mapRect.currentScale < 5) {
0085                             let centrePos = { x: mapImage.width / 2, y: mapImage.height / 2 };
0086                             var realX = centrePos.x * mapZoom.xScale
0087                             var realY = centrePos.y * mapZoom.yScale
0088                             mapFlick.contentX -= (1-mapRect.zoomFactor)*realX
0089                             mapFlick.contentY -= (1-mapRect.zoomFactor)*realY
0090                             mapRect.currentScale *= mapRect.zoomFactor;
0091                         }
0092                     }
0093                     onDoubleClicked: {
0094                         onClicked();
0095                     }
0096                     QQC2.ToolTip {
0097                         text: parent.text
0098                     }
0099                 }
0100 
0101                 QQC2.Button {
0102                     // HACK: using list-add and list-remove for more obvious/standard zoom icons till we change the Breeze ones
0103                     // https://bugs.kde.org/show_bug.cgi?id=435671
0104                     text: i18n("Zoom in")
0105                     display: QQC2.AbstractButton.IconOnly
0106                     icon.name: kcm.isIconThemeBreeze() ? "list-remove" : "zoom-out"
0107                     activeFocusOnTab: false
0108                     onClicked: {
0109                         if (mapRect.currentScale > 1) {
0110                             let centrePos = { x: mapImage.width / 2, y: mapImage.height / 2 };
0111                             var realX = centrePos.x * mapZoom.xScale
0112                             var realY = centrePos.y * mapZoom.yScale
0113                             mapFlick.contentX -= (1-(1/mapRect.zoomFactor))*realX
0114                             mapFlick.contentY -= (1-(1/mapRect.zoomFactor))*realY
0115                             mapRect.currentScale *= (1/mapRect.zoomFactor)
0116                         }
0117                     }
0118                     onDoubleClicked: {
0119                         onClicked();
0120                     }
0121                     QQC2.ToolTip {
0122                         text: parent.text
0123                     }
0124                 }
0125             }
0126 
0127             Flickable {
0128                 id: mapFlick
0129                 anchors {
0130                     fill: parent
0131                     margins: Kirigami.Units.smallSpacing
0132                 }
0133                 contentWidth: mapImage.width * mapRect.currentScale
0134                 contentHeight: mapImage.height * mapRect.currentScale
0135 
0136                 clip: true
0137                 Image {
0138                     id: mapImage
0139                     source: "worldmap.png" // loaded using QRC
0140                     transform: Scale {
0141                         id: mapZoom
0142                         xScale: mapRect.currentScale
0143                         yScale: mapRect.currentScale
0144                     }
0145 
0146                     Kirigami.Icon {
0147                         z: 9999
0148                         readonly property double rawX: longitudeToX(kcm.nightColorSettings.longitudeFixed)
0149                         readonly property double rawY: latitudeToY(kcm.nightColorSettings.latitudeFixed)
0150                         x: rawX - (width/2)/mapRect.currentScale
0151                         y: rawY - (height - 4)/mapRect.currentScale
0152                         width: Kirigami.Units.iconSizes.medium
0153                         height: Kirigami.Units.iconSizes.medium
0154                         source: "mark-location"
0155                         color: "#232629"
0156                         transform: Scale {
0157                             xScale: 1/mapRect.currentScale
0158                             yScale: 1/mapRect.currentScale
0159                         }
0160                     }
0161 
0162                     TapHandler {
0163                         onTapped: event => {
0164                             const clickPos = event.position;
0165                             kcm.nightColorSettings.longitudeFixed = xToLongitude(clickPos.x);
0166                             kcm.nightColorSettings.latitudeFixed = yToLatitude(clickPos.y);
0167                         }
0168                     }
0169 
0170                     WheelHandler {
0171                         acceptedModifiers: Qt.ControlModifier
0172                         onWheel: event => {
0173                             let wheelPos = mapImage.mapFromItem(root, point.scenePosition);
0174                             var realX = wheelPos.x * mapZoom.xScale
0175                             var realY = wheelPos.y * mapZoom.yScale
0176                             let clicks = event.angleDelta.y / 120;
0177                             if (clicks > 0 && mapRect.currentScale < 5) {
0178                                 mapFlick.contentX -= (1-mapRect.zoomFactor)*realX
0179                                 mapFlick.contentY -= (1-mapRect.zoomFactor)*realY
0180                                 mapRect.currentScale *= mapRect.zoomFactor;
0181                             } else if (clicks < 0 && mapRect.currentScale > 1) {
0182                                 mapFlick.contentX -= (1-(1/mapRect.zoomFactor))*realX
0183                                 mapFlick.contentY -= (1-(1/mapRect.zoomFactor))*realY
0184                                 mapRect.currentScale *= (1/(mapRect.zoomFactor));
0185                             }
0186                         }
0187                     }
0188 
0189                     Component.onCompleted: {
0190                         width = mapFlick.width;
0191                         height = mapFlick.height;
0192                     }
0193 
0194                 }
0195             }
0196         }
0197 
0198         TextEdit {
0199             id: mapAttributionLabel
0200             textFormat: TextEdit.RichText
0201             wrapMode: Text.Wrap
0202             readOnly: true
0203             color: Kirigami.Theme.textColor
0204             selectedTextColor: Kirigami.Theme.highlightedTextColor
0205             selectionColor: Kirigami.Theme.highlightColor
0206             font: Kirigami.Theme.smallFont
0207             Layout.topMargin: Kirigami.Units.smallSpacing
0208             Layout.maximumWidth: mapRect.width
0209             Layout.alignment: Qt.AlignHCenter
0210             text: xi18nc("@info", "Modified from <link url='https://commons.wikimedia.org/wiki/File:World_location_map_(equirectangular_180).svg'>World location map</link> by TUBS / Wikimedia Commons / <link url='https://creativecommons.org/licenses/by-sa/3.0'>CC BY-SA 3.0</link>")
0211             onLinkActivated: (url) => Qt.openUrlExternally(url)
0212             HoverHandler {
0213                 acceptedButtons: Qt.NoButton
0214                 cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
0215             }
0216         }
0217 
0218         RowLayout {
0219             Layout.topMargin: Kirigami.Units.smallSpacing
0220             Layout.alignment: Qt.AlignHCenter
0221 
0222             QQC2.Label {
0223                 text: i18nc("@label: textbox", "Latitude:")
0224                 textFormat: Text.PlainText
0225             }
0226             Connections {
0227                 target: kcm.nightColorSettings
0228                 function onLatitudeFixedChanged() {
0229                     latitudeFixedField.backend = kcm.nightColorSettings.latitudeFixed;
0230                 }
0231                 function onLongitudeFixedChanged() {
0232                     longitudeFixedField.backend = kcm.nightColorSettings.longitudeFixed;
0233                 }
0234             }
0235             NumberField {
0236                 id: latitudeFixedField
0237                 validator: DoubleValidator {bottom: -90; top: 90; decimals: 10}
0238                 backend: kcm.nightColorSettings.latitudeFixed
0239                 onBackendChanged: {
0240                     kcm.nightColorSettings.latitudeFixed = backend;
0241                 }
0242                 KCM.SettingStateBinding {
0243                     configObject: kcm.nightColorSettings
0244                     settingName: "LatitudeFixed"
0245                     extraEnabledConditions: kcm.nightColorSettings.active
0246                 }
0247             }
0248 
0249             QQC2.Label {
0250                 text: i18nc("@label: textbox", "Longitude:")
0251                 textFormat: Text.PlainText
0252             }
0253             NumberField {
0254                 id: longitudeFixedField
0255                 validator: DoubleValidator {bottom: -180; top: 180; decimals: 10}
0256                 backend: kcm.nightColorSettings.longitudeFixed
0257                 onBackendChanged: {
0258                     kcm.nightColorSettings.longitudeFixed = backend;
0259                 }
0260                 KCM.SettingStateBinding {
0261                     configObject: kcm.nightColorSettings
0262                     settingName: "LongitudeFixed"
0263                     extraEnabledConditions: kcm.nightColorSettings.active
0264                 }
0265             }
0266         }
0267     }
0268 }