You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

601 lines
25 KiB

2 years ago
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import QtQuick.Shapes 1.1
import QtGraphicalEffects 1.12
import NERvGear 1.0 as NVG
import NERvGear.Controls 1.0
import NERvGear.Templates 1.0 as T
import NERvGear.Preferences 1.0 as P
import "qrc:/qml/com.gpbeta.data.weather" as Private
2 years ago
import "utils.js" as Utils
WidgetTemplate {
2 years ago
id: widget
title: qsTr("Ordinal Scale Weather Widget")
editing: styleDialog.active
version: "1.0.0"
defaultValues: {
"Display Location": "",
"Update Interval":
{
"Value": 1,
"Unit": 1
},
"Background Color": "#ffa502",
"Background Opacity": 60,
"Area Opacity Difference": 17,
"Icon Color": "#fefefe",
"Temperature Text Settings":
{
"Font Color": "#f5f5f5",
"Font Size": 90,
"Font Name": fonts.length - 1,
"Font Weight": 1,
"X Offset": 33,
"Y Offset": 32
},
"Area Text Settings":
{
"Font Color": "#f5f5f5",
"Font Size": 60,
"Font Name": fonts.length - 1,
"Font Weight": 1,
"X Offset": 0,
"Y Offset": -56,
"Border Margin": 40
}
}
2 years ago
readonly property var configs: widget.settings.styles
readonly property real w: widget.width
readonly property real h: 0.46*widget.width
2 years ago
readonly property var fonts: Qt.fontFamilies()
readonly property var fontweight: [Font.Light, Font.Normal, Font.Bold]
readonly property var sfontweight: [qsTr("Light"), qsTr("Normal"), qsTr("Bold")]
readonly property NVG.DataSource dataSource: NVG.DataSource {
configuration: {"mode":0,"unit":"","interval":60000*configs["Update Interval"]["Value"]*(1+59*configs["Update Interval"]["Unit"]),"update":configs["Address"],"source":"nvg://weather.data.gpbeta.com/data#raw","value":"current"}
}
2 years ago
NVG.DataSourceRawOutput {
id: output
source: dataSource
}
2 years ago
Item {
id: main
width: w
height: h
anchors.centerIn: parent
layer.enabled: true
layer.effect: OpacityMask{
maskSource: Rectangle {
width: w
height: h
color: "black"
radius: h/15
}
}
Rectangle {
id: weather_box
width: w
height: h
anchors.left: parent.left
anchors.top: parent.top
opacity: configs["Background Opacity"]/100
color: configs["Background Color"]
}
Item {
id: sdialog
width: h/8
height: h/8
anchors.left: parent.left
anchors.leftMargin: h/16
anchors.topMargin: h/14
anchors.top: parent.top
Shape {
anchors.fill: parent
ShapePath {
strokeWidth: parent.height/120
strokeColor: configs["Icon Color"]
startX: h/44; startY: h/800
PathLine { x: h*0.10227272727272727; y: h/800 }
}
ShapePath {
strokeWidth: parent.height/120
strokeColor: configs["Icon Color"]
startX: h/44; startY: h/800 + h/32
PathLine { x: h*0.10227272727272727; y: h/800 + h/32 }
}
ShapePath {
strokeWidth: parent.height/120
strokeColor: configs["Icon Color"]
startX: h/44; startY: h/800 + h/16
PathLine { x: h*0.10227272727272727; y: h/800 + h/16 }
}
}
MouseArea {
anchors.fill: parent
enabled: !styleDialog.active
onClicked: {
styleDialog.active = true;
}
}
}
Item {
id: weather
width: 0.655*w
height: h
anchors.left: parent.left
anchors.top: parent.top
Image {
id: weather_mask
anchors.centerIn: weather
autoTransform: true
visible: false
source: "../Images/Weather/" + Utils.weather_codes[output.result?.iconCode ?? "44"] + ".png"
2 years ago
}
Rectangle {
id: wcolor
width: h/1.1
height: h/1.1
anchors.centerIn: weather
visible: false
color: configs["Icon Color"]
}
OpacityMask {
anchors.fill: wcolor
source: wcolor
maskSource: weather_mask
}
}
Rectangle {
id: temper_box
width: 0.345*w
height: h
anchors.right: parent.right
anchors.top: parent.top
opacity: configs["Background Opacity"]*configs["Area Opacity Difference"]/10000
color: "black"
}
Text {
id: area
anchors.centerIn: temper_box
anchors.horizontalCenterOffset: temper_box.width*configs["Area Text Settings"]["X Offset"]/200
anchors.verticalCenterOffset: h*configs["Area Text Settings"]["Y Offset"]/200
color: configs["Area Text Settings"]["Font Color"]
text: configs["Display Location"]
2 years ago
font.pixelSize: w*0.0009*configs["Area Text Settings"]["Font Size"]
font.family: fonts[configs["Area Text Settings"]["Font Name"]]
font.weight: fontweight[configs["Area Text Settings"]["Font Weight"]]
Rectangle {
anchors.fill: parent
anchors.margins: -area.font.pixelSize*configs["Area Text Settings"]["Border Margin"]/100
color: "transparent"
border.color: configs["Area Text Settings"]["Font Color"]
border.width: area.font.pixelSize/15
radius: area.font.pixelSize/3.5
visible: Boolean(area.text)
}
}
Text {
id: temperature
anchors.centerIn: temper_box
anchors.horizontalCenterOffset: temper_box.width*configs["Temperature Text Settings"]["X Offset"]/200
anchors.verticalCenterOffset: h*configs["Temperature Text Settings"]["Y Offset"]/200
color: configs["Temperature Text Settings"]["Font Color"]
text: (output.result?.temperature ?? "--") + "°"
2 years ago
font.pixelSize: w*0.002*configs["Temperature Text Settings"]["Font Size"]
font.family: fonts[configs["Temperature Text Settings"]["Font Name"]]
font.weight: fontweight[configs["Temperature Text Settings"]["Font Weight"]]
}
}
menu: Menu {
Action {
text: qsTr("Settings") + "..."
onTriggered: styleDialog.active = true
}
}
Loader {
id: styleDialog
active: false
sourceComponent: NVG.Window {
id: window
title: qsTr("Settings")
visible: true
minimumWidth: 450
minimumHeight: 550
width: minimumWidth
height: minimumHeight
transientParent: widget.NVG.View.window
property var configuration
Page {
anchors.fill: parent
header: TitleBar {
text: qsTr("Ordinal Scale Weather Widget")
2 years ago
standardButtons: Dialog.Save | Dialog.Reset
onAccepted: {
configuration = rootPreference.save();
widget.settings.styles = configuration;
styleDialog.active = false;
}
onReset: {
rootPreference.load({"Address": widget.settings.styles?.Address});
2 years ago
let cfg = rootPreference.save();
widget.settings.styles = cfg;
}
}
ColumnLayout {
id: root
anchors.fill: parent
anchors.margins: 16
anchors.topMargin: 0
Flickable {
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
contentWidth: preferenceLayout.implicitWidth
contentHeight: preferenceLayout.implicitHeight
ColumnLayout {
id: preferenceLayout
width: root.width
P.PreferenceGroup {
id: rootPreference
Layout.fillWidth: true
label: qsTr("Configuration")
onPreferenceEdited: {
widget.settings.styles = rootPreference.save();
}
P.DialogPreference {
id: rootPref
2 years ago
label: qsTr("Location")
name: "Address"
displayValue: widget.settings.styles?.Address ? widget.settings.styles.Address.address : qsTr("Click to set location.")
load: function (newValue) {
errorLabel.visible = false;
queryField.text = "";
radioRepeater.model = newValue ? [ newValue ] : undefined;
if (radioRepeater.count)
radioColumn.children[0].checked = true;
}
save: function () {
return radioGroup.checkedButton ? radioGroup.checkedButton.location : undefined;
}
function searchLocation() {
if (!queryField.text)
return;
rootPref.enabled = false;
errorLabel.visible = false;
busyIndicator.running = true;
Private.Manager.searchLocation(queryField.text)
.then(function (result) {
radioRepeater.model = result;
if (radioRepeater.count)
radioColumn.children[0].checked = true;
}, function (err) {
console.warn(err);
errorLabel.visible = true;
radioRepeater.model = undefined;
})
.then(function () {
rootPref.enabled = true;
busyIndicator.running = false;
});
}
RowLayout {
TextField {
id: queryField
Layout.fillWidth: true
placeholderText: qsTr("Search: country, city, district...")
onAccepted: rootPref.searchLocation()
}
ToolButton {
icon.name: "regular:\uf002"
onClicked: rootPref.searchLocation()
}
}
Item {
implicitWidth: Math.max(busyIndicator.implicitWidth, radioColumn.implicitWidth)
implicitHeight: Math.max(busyIndicator.implicitHeight, radioColumn.implicitHeight)
BusyIndicator {
id: busyIndicator
anchors.centerIn: parent
running: false
}
Label {
id: errorLabel
anchors.centerIn: parent
enabled: false
visible: false
text: qsTr("Location not found")
}
ButtonGroup {
id: radioGroup
buttons: radioColumn.children
}
Column {
id: radioColumn
width: parent.width
Repeater {
id: radioRepeater
RadioButton {
readonly property var location: modelData
text: modelData.address
width: radioColumn.width
}
}
}
}
2 years ago
}
P.TextFieldPreference {
name: "Display Location"
label: qsTr("Display Location")
message: qsTr("The location to display in widget.")
defaultValue: defaultValues["Display Location"]
2 years ago
}
P.DialogPreference {
name: "Update Interval"
label: qsTr("Update Interval")
live: true
displayValue: _cfg_update_interval_value.value + " " + [qsTr("Minutes"), qsTr("Hours")][_cfg_update_interval_unit.value]
P.SpinPreference {
id: _cfg_update_interval_value
name: "Value"
from: 1
to: 1440
editable: true
defaultValue: defaultValues["Update Interval"]["Value"]
2 years ago
}
P.SelectPreference {
id: _cfg_update_interval_unit
name: "Unit"
label: qsTr("Unit")
defaultValue: defaultValues["Update Interval"]["Unit"]
2 years ago
model: [qsTr("Minutes"), qsTr("Hours")]
}
}
P.ColorPreference {
name: "Background Color"
label: qsTr("Background Color")
defaultValue: defaultValues["Background Color"]
2 years ago
}
P.SliderPreference {
name: "Background Opacity"
label: qsTr("Background Opacity")
from: 0
to: 100
stepSize: 1
defaultValue: defaultValues["Background Opacity"]
2 years ago
displayValue: value + "%"
}
P.SliderPreference {
name: "Area Opacity Difference"
label: qsTr("Area Opacity Difference")
from: 0
to: 100
stepSize: 1
defaultValue: defaultValues["Area Opacity Difference"]
2 years ago
displayValue: value + "%"
}
P.ColorPreference {
name: "Icon Color"
label: qsTr("Icon Color")
defaultValue: defaultValues["Icon Color"]
2 years ago
}
P.Separator {}
2 years ago
P.DialogPreference {
name: "Temperature Text Settings"
label: qsTr("Temperature Text Settings")
icon.name: "solid:\uf1fc"
live: true
P.ColorPreference {
name: "Font Color"
label: qsTr("Font Color")
defaultValue: defaultValues["Temperature Text Settings"]["Font Color"]
2 years ago
}
P.SliderPreference {
name: "Font Size"
label: qsTr("Font Size")
from: 1
to: 100
stepSize: 1
defaultValue: defaultValues["Temperature Text Settings"]["Font Size"]
2 years ago
displayValue: value + "%"
}
P.SelectPreference {
name: "Font Name"
label: qsTr("Font Style")
defaultValue: defaultValues["Temperature Text Settings"]["Font Name"]
2 years ago
model: fonts
}
P.SelectPreference {
name: "Font Weight"
label: qsTr("Font Weight")
defaultValue: defaultValues["Temperature Text Settings"]["Font Weight"]
2 years ago
model: sfontweight
}
P.SliderPreference {
name: "X Offset"
label: qsTr("X Offset")
from: -100
to: 100
stepSize: 1
defaultValue: defaultValues["Temperature Text Settings"]["X Offset"]
2 years ago
displayValue: value + "%"
}
P.SliderPreference {
name: "Y Offset"
label: qsTr("Y Offset")
from: -100
to: 100
stepSize: 1
defaultValue: defaultValues["Temperature Text Settings"]["Y Offset"]
2 years ago
displayValue: value + "%"
}
}
P.DialogPreference {
name: "Area Text Settings"
label: qsTr("Area Text Settings")
icon.name: "solid:\uf1fc"
live: true
P.ColorPreference {
name: "Font Color"
label: qsTr("Font Color")
defaultValue: defaultValues["Area Text Settings"]["Font Color"]
2 years ago
}
P.SliderPreference {
name: "Font Size"
label: qsTr("Font Size")
from: 1
to: 100
stepSize: 1
defaultValue: defaultValues["Area Text Settings"]["Font Size"]
2 years ago
displayValue: value + "%"
}
P.SelectPreference {
name: "Font Name"
label: qsTr("Font Style")
defaultValue: defaultValues["Area Text Settings"]["Font Name"]
2 years ago
model: fonts
}
P.SelectPreference {
name: "Font Weight"
label: qsTr("Font Weight")
defaultValue: defaultValues["Area Text Settings"]["Font Weight"]
2 years ago
model: sfontweight
}
P.SliderPreference {
name: "X Offset"
label: qsTr("X Offset")
from: -100
to: 100
stepSize: 1
defaultValue: defaultValues["Area Text Settings"]["X Offset"]
2 years ago
displayValue: value + "%"
}
P.SliderPreference {
name: "Y Offset"
label: qsTr("Y Offset")
from: -100
to: 100
stepSize: 1
defaultValue: defaultValues["Area Text Settings"]["Y Offset"]
2 years ago
displayValue: value + "%"
}
P.SliderPreference {
name: "Border Margin"
label: qsTr("Border Margin")
from: 0
to: 100
stepSize: 1
defaultValue: defaultValues["Area Text Settings"]["Border Margin"]
2 years ago
displayValue: value + "%"
}
}
Component.onCompleted: {
if(!widget.settings.styles) {
configuration = rootPreference.save();
widget.settings.styles = configuration;
}
rootPreference.load(widget.settings.styles);
configuration = widget.settings.styles;
}
}
}
}
}
}
onClosing: {
widget.settings.styles = configuration;
styleDialog.active = false;
}
}
}
}