Commit 648648f1 authored by Bharadwaj Raju's avatar Bharadwaj Raju Committed by Nate Graham
Browse files

kcms/nightcolor: Add map to "manual location" mode

Most people don't have their latitude and longitude memorized. It is
*far* easier for people to point out their approximate location on a
map, than to look up their latitude and longitude online.

This also removes the need for a "Detect Location" button there.
parent 0baa8a97
Pipeline #215322 passed with stage
in 8 minutes and 55 seconds
......@@ -27,4 +27,6 @@ target_link_libraries(kcm_nightcolor
PW::LibColorCorrect
)
install(FILES worldmap.png DESTINATION ${KDE_INSTALL_DATADIR}/plasma/nightcolor)
kpackage_install_package(package kcm_nightcolor kcms)
......@@ -6,6 +6,9 @@
#include "kcm.h"
#include <QIcon>
#include <QStandardPaths>
#include <KLocalizedString>
#include <KPluginFactory>
......@@ -22,6 +25,8 @@ KCMNightColor::KCMNightColor(QObject *parent, const KPluginMetaData &data, const
qmlRegisterAnonymousType<NightColorSettings>("org.kde.private.kcms.nightcolor", 1);
qmlRegisterUncreatableMetaObject(ColorCorrect::staticMetaObject, "org.kde.private.kcms.nightcolor", 1, 0, "NightColorMode", "Error: only enums");
worldMapFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("plasma/nightcolor/worldmap.png"), QStandardPaths::LocateFile);
setButtons(Apply | Default);
}
......@@ -30,6 +35,12 @@ NightColorSettings *KCMNightColor::nightColorSettings() const
return m_data->settings();
}
// FIXME: This was added to work around the nonstandardness of the Breeze zoom icons
// remove once https://bugs.kde.org/show_bug.cgi?id=435671 is fixed
bool KCMNightColor::isIconThemeBreeze()
{
return QIcon::themeName().contains(QStringLiteral("breeze"));
}
}
#include "kcm.moc"
......@@ -18,14 +18,17 @@ class KCMNightColor : public KQuickAddons::ManagedConfigModule
Q_OBJECT
Q_PROPERTY(NightColorSettings *nightColorSettings READ nightColorSettings CONSTANT)
Q_PROPERTY(QString worldMapFile MEMBER worldMapFile CONSTANT)
public:
KCMNightColor(QObject *parent, const KPluginMetaData &data, const QVariantList &args);
~KCMNightColor() override = default;
NightColorSettings *nightColorSettings() const;
Q_INVOKABLE bool isIconThemeBreeze();
private:
NightColorData *const m_data;
QString worldMapFile;
};
}
......@@ -4,71 +4,275 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.1
import QtQuick 2.15
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.5 as QQC2
import org.kde.kirigami 2.5 as Kirigami
import QtQuick.Controls 2.15 as QQC2
import org.kde.kirigami 2.15 as Kirigami
import org.kde.kcm 1.5 as KCM
import QtGraphicalEffects 1.12
Kirigami.FormLayout {
twinFormLayouts: parentLayout
NumberField {
id: latitudeFixedField
// Match combobox width
Layout.minimumWidth: modeSwitcher.width
Layout.maximumWidth: modeSwitcher.width
Kirigami.FormData.label: i18n("Latitude:")
validator: DoubleValidator {bottom: -90; top: 90; decimals: 10}
backend: kcm.nightColorSettings.latitudeFixed
onBackendChanged: {
kcm.nightColorSettings.latitudeFixed = backend;
}
KCM.SettingStateBinding {
configObject: kcm.nightColorSettings
settingName: "LatitudeFixed"
extraEnabledConditions: kcm.nightColorSettings.active
}
/* Equirectangular projection maps (x, y) to (lat, long) cleanly */
function longitudeToX(lon) {
return (lon + 180) * (mapImage.width / 360);
}
function latitudeToY(lat) {
return (90 - lat) * (mapImage.height / 180);
}
function xToLongitude(x) {
return (x / (mapImage.width / 360)) - 180;
}
function yToLatitude(y) {
return 90 - (y / (mapImage.height / 180));
}
NumberField {
id: longitudeFixedField
// Match combobox width
Layout.minimumWidth: modeSwitcher.width
Layout.maximumWidth: modeSwitcher.width
Kirigami.FormData.label: i18n("Longitude:")
validator: DoubleValidator {bottom: -180; top: 180; decimals: 10}
backend: kcm.nightColorSettings.longitudeFixed
onBackendChanged: {
kcm.nightColorSettings.longitudeFixed = backend;
ColumnLayout {
QQC2.Label {
id: mapLabel
wrapMode: Text.Wrap
Layout.maximumWidth: mapRect.width
Layout.bottomMargin: Kirigami.Units.smallSpacing
Layout.alignment: Qt.AlignHCenter
text: Kirigami.Settings.tabletMode
? i18nc("@label:chooser Tap should be translated to mean touching using a touchscreen", "Tap to choose your location on the map.")
: i18nc("@label:chooser Click should be translated to mean clicking using a mouse", "Click to choose your location on the map.")
font: Kirigami.Theme.smallFont
}
KCM.SettingStateBinding {
configObject: kcm.nightColorSettings
settingName: "LongitudeFixed"
extraEnabledConditions: kcm.nightColorSettings.active
Kirigami.ShadowedRectangle {
id: mapRect
Layout.alignment: Qt.AlignHCenter
implicitWidth: Kirigami.Units.gridUnit * 30
Layout.maximumWidth: Kirigami.Units.gridUnit * 30
implicitHeight: Kirigami.Units.gridUnit * 15
Layout.maximumHeight: Kirigami.Units.gridUnit * 15
radius: Kirigami.Units.smallSpacing
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.View
color: Kirigami.Theme.backgroundColor
shadow.xOffset: 0
shadow.yOffset: 2
shadow.size: 10
shadow.color: Qt.rgba(0, 0, 0, 0.3)
property double zoomFactor: 1.2;
property double currentScale: 1.0;
/* Zoom in/out buttons */
RowLayout {
anchors {
right: parent.right
rightMargin: Kirigami.Units.smallSpacing*2
bottom: parent.bottom
bottomMargin: Kirigami.Units.smallSpacing*2
}
// Always show above thumbnail content
z: 9999
QQC2.Button {
// HACK: using list-add and list-remove for more obvious/standard zoom icons till we change the Breeze ones
// https://bugs.kde.org/show_bug.cgi?id=435671
text: i18n("Zoom in")
display: QQC2.AbstractButton.IconOnly
icon.name: kcm.isIconThemeBreeze() ? "list-add" : "zoom-in"
activeFocusOnTab: false
onClicked: {
if (mapRect.currentScale < 5) {
let centrePos = { x: mapImage.width / 2, y: mapImage.height / 2 };
var realX = centrePos.x * mapZoom.xScale
var realY = centrePos.y * mapZoom.yScale
mapFlick.contentX -= (1-mapRect.zoomFactor)*realX
mapFlick.contentY -= (1-mapRect.zoomFactor)*realY
mapRect.currentScale *= mapRect.zoomFactor;
}
}
onDoubleClicked: {
onClicked();
}
QQC2.ToolTip {
text: parent.text
}
}
QQC2.Button {
// HACK: using list-add and list-remove for more obvious/standard zoom icons till we change the Breeze ones
// https://bugs.kde.org/show_bug.cgi?id=435671
text: i18n("Zoom in")
display: QQC2.AbstractButton.IconOnly
icon.name: kcm.isIconThemeBreeze() ? "list-remove" : "zoom-out"
activeFocusOnTab: false
onClicked: {
if (mapRect.currentScale > 1) {
let centrePos = { x: mapImage.width / 2, y: mapImage.height / 2 };
var realX = centrePos.x * mapZoom.xScale
var realY = centrePos.y * mapZoom.yScale
mapFlick.contentX -= (1-(1/mapRect.zoomFactor))*realX
mapFlick.contentY -= (1-(1/mapRect.zoomFactor))*realY
mapRect.currentScale *= (1/mapRect.zoomFactor)
}
}
onDoubleClicked: {
onClicked();
}
QQC2.ToolTip {
text: parent.text
}
}
}
Flickable {
id: mapFlick
anchors {
fill: parent
margins: Kirigami.Units.smallSpacing
}
contentWidth: mapImage.width * mapRect.currentScale
contentHeight: mapImage.height * mapRect.currentScale
clip: true
Image {
id: mapImage
source: kcm.worldMapFile
transform: Scale {
id: mapZoom
xScale: mapRect.currentScale
yScale: mapRect.currentScale
}
Kirigami.Icon {
z: 9999
id: mapPin
property double rawX: longitudeToX(kcm.nightColorSettings.longitudeFixed)
property double rawY: latitudeToY(kcm.nightColorSettings.latitudeFixed)
x: rawX - (width/2)/mapRect.currentScale
y: rawY - (height - 4)/mapRect.currentScale
width: Kirigami.Units.iconSizes.medium
height: Kirigami.Units.iconSizes.medium
source: "mark-location"
color: "#232629"
transform: Scale {
xScale: 1/mapRect.currentScale
yScale: 1/mapRect.currentScale
}
}
Connections {
target: kcm.nightColorSettings
function onLatitudeFixedChanged() {
mapPin.rawY = latitudeToY(kcm.nightColorSettings.latitudeFixed);
}
function onLongitudeFixedChanged() {
mapPin.rawX = longitudeToX(kcm.nightColorSettings.longitudeFixed);
}
}
TapHandler {
onTapped: {
let clickPos = mapImage.mapFromItem(root, eventPoint.scenePosition);
mapPin.rawX = clickPos.x;
mapPin.rawY = clickPos.y;
kcm.nightColorSettings.latitudeFixed = yToLatitude(mapPin.rawY);
kcm.nightColorSettings.longitudeFixed = xToLongitude(mapPin.rawX);
}
}
WheelHandler {
acceptedModifiers: Qt.ControlModifier
onWheel: {
let wheelPos = mapImage.mapFromItem(root, point.scenePosition);
var realX = wheelPos.x * mapZoom.xScale
var realY = wheelPos.y * mapZoom.yScale
let clicks = event.angleDelta.y / 120;
if (clicks > 0 && mapRect.currentScale < 5) {
mapFlick.contentX -= (1-mapRect.zoomFactor)*realX
mapFlick.contentY -= (1-mapRect.zoomFactor)*realY
mapRect.currentScale *= mapRect.zoomFactor;
} else if (clicks < 0 && mapRect.currentScale > 1) {
mapFlick.contentX -= (1-(1/mapRect.zoomFactor))*realX
mapFlick.contentY -= (1-(1/mapRect.zoomFactor))*realY
mapRect.currentScale *= (1/(mapRect.zoomFactor));
}
}
}
Component.onCompleted: {
width = mapFlick.width;
height = mapFlick.height;
}
}
}
}
}
QQC2.Button {
text: i18n("Detect Location")
// Match combobox width
Layout.minimumWidth: modeSwitcher.width
icon.name: "find-location"
onClicked: {
startLocator();
latitudeFixedField.backend = locator.latitude;
longitudeFixedField.backend = locator.longitude;
TextEdit {
id: mapAttributionLabel
textFormat: TextEdit.RichText
wrapMode: Text.Wrap
readOnly: true
color: Kirigami.Theme.textColor
selectedTextColor: Kirigami.Theme.highlightedTextColor
selectionColor: Kirigami.Theme.highlightColor
font: Kirigami.Theme.smallFont
Layout.topMargin: Kirigami.Units.smallSpacing
Layout.maximumWidth: mapRect.width
Layout.alignment: Qt.AlignHCenter
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>")
onLinkActivated: (url) => Qt.openUrlExternally(url)
HoverHandler {
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
}
// Inform about geolocation access on clicking detect
QQC2.Label {
enabled: activator.checked
wrapMode: Text.Wrap
Layout.maximumWidth: modeSwitcher.width
text: i18n("The device's location will be detected using GPS (if available), or by sending network information to <a href=\"https://location.services.mozilla.com\">Mozilla Location Service</a>.")
onLinkActivated: { Qt.openUrlExternally("https://location.services.mozilla.com"); }
font: Kirigami.Theme.smallFont
RowLayout {
Layout.topMargin: Kirigami.Units.smallSpacing
Layout.alignment: Qt.AlignHCenter
QQC2.Label {
text: i18nc("@label: textbox", "Latitude:")
}
Connections {
target: kcm.nightColorSettings
function onLatitudeFixedChanged() {
latitudeFixedField.backend = kcm.nightColorSettings.latitudeFixed;
}
function onLongitudeFixedChanged() {
longitudeFixedField.backend = kcm.nightColorSettings.longitudeFixed;
}
}
NumberField {
id: latitudeFixedField
validator: DoubleValidator {bottom: -90; top: 90; decimals: 10}
backend: kcm.nightColorSettings.latitudeFixed
onBackendChanged: {
kcm.nightColorSettings.latitudeFixed = backend;
}
KCM.SettingStateBinding {
configObject: kcm.nightColorSettings
settingName: "LatitudeFixed"
extraEnabledConditions: kcm.nightColorSettings.active
}
}
QQC2.Label {
text: i18nc("@label: textbox", "Longitude:")
}
NumberField {
id: longitudeFixedField
validator: DoubleValidator {bottom: -180; top: 180; decimals: 10}
backend: kcm.nightColorSettings.longitudeFixed
onBackendChanged: {
kcm.nightColorSettings.longitudeFixed = backend;
}
KCM.SettingStateBinding {
configObject: kcm.nightColorSettings
settingName: "LongitudeFixed"
extraEnabledConditions: kcm.nightColorSettings.active
}
}
}
}
}
......@@ -187,10 +187,6 @@ KCM.SimpleKCM {
]
}
Item {
Kirigami.FormData.isSection: true
}
QQC2.ComboBox {
id: modeSwitcher
// Work around https://bugs.kde.org/show_bug.cgi?id=403153
......@@ -370,6 +366,7 @@ KCM.SimpleKCM {
// Show location chooser in manual location mode
LocationsFixedView {
visible: kcm.nightColorSettings.mode === NightColorMode.Location
Layout.alignment: Qt.AlignHCenter
enabled: activator.checked
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment