Browse Source

- 迁移天气API

- 添加统一版本控制的WidgetTemplate.qml
master
mashiros 2 years ago
parent
commit
cdb0b509bf
  1. BIN
      Images/Weather/Breezy.png
  2. BIN
      Images/Weather/Clear.png
  3. BIN
      Images/Weather/Cloudy.png
  4. BIN
      Images/Weather/Fog.png
  5. BIN
      Images/Weather/Hail.png
  6. BIN
      Images/Weather/Hurricane.png
  7. BIN
      Images/Weather/IceCrystals.png
  8. BIN
      Images/Weather/LightSleet.png
  9. BIN
      Images/Weather/LightSnow.png
  10. BIN
      Images/Weather/PartlyCloudy.png
  11. BIN
      Images/Weather/PartlyCloudyDay.png
  12. BIN
      Images/Weather/PartlyCloudyNight.png
  13. BIN
      Images/Weather/Sandstorm.png
  14. BIN
      Images/Weather/SnowShowers.png
  15. BIN
      Images/Weather/Sunny.png
  16. BIN
      Images/Weather/ThunderyHeavyRain.png
  17. BIN
      Images/Weather/ThunderyShowers.png
  18. BIN
      Images/Weather/Tornado.png
  19. BIN
      Images/Weather/Unknown.png
  20. BIN
      Locales/zh.qm
  21. 159
      Locales/zh.ts
  22. 2
      package.json
  23. 36
      qml/BottomUI.qml
  24. 125
      qml/TopUI.qml
  25. 255
      qml/WeatherWidget.qml
  26. 27
      qml/WidgetTemplate.qml
  27. 96
      qml/utils.js

BIN
Images/Weather/Breezy.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

BIN
Images/Weather/Clear.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
Images/Weather/Cloudy.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
Images/Weather/Fog.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
Images/Weather/Hail.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

BIN
Images/Weather/Hurricane.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
Images/Weather/IceCrystals.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
Images/Weather/LightSleet.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

BIN
Images/Weather/LightSnow.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
Images/Weather/PartlyCloudy.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

BIN
Images/Weather/PartlyCloudyDay.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
Images/Weather/PartlyCloudyNight.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

BIN
Images/Weather/Sandstorm.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
Images/Weather/SnowShowers.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
Images/Weather/Sunny.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
Images/Weather/ThunderyHeavyRain.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

BIN
Images/Weather/ThunderyShowers.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
Images/Weather/Tornado.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

BIN
Images/Weather/Unknown.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

BIN
Locales/zh.qm

Binary file not shown.

159
Locales/zh.ts

@ -4,48 +4,48 @@
<context>
<name>BottomUI</name>
<message>
<location filename="qml/BottomUI.qml" line="14"/>
<location filename="qml/BottomUI.qml" line="12"/>
<source>Ordinal Scale Bottom UI widget</source>
<translation>UI挂件</translation>
</message>
<message>
<location filename="qml/BottomUI.qml" line="90"/>
<location filename="qml/BottomUI.qml" line="100"/>
<location filename="qml/BottomUI.qml" line="104"/>
<location filename="qml/BottomUI.qml" line="114"/>
<source>Settings</source>
<translation></translation>
</message>
<message>
<location filename="qml/BottomUI.qml" line="116"/>
<location filename="qml/BottomUI.qml" line="130"/>
<source>UI Settings</source>
<translation>UI设置</translation>
</message>
<message>
<location filename="qml/BottomUI.qml" line="157"/>
<location filename="qml/BottomUI.qml" line="171"/>
<source>Configuration</source>
<translation></translation>
</message>
<message>
<location filename="qml/BottomUI.qml" line="165"/>
<location filename="qml/BottomUI.qml" line="179"/>
<source>Curve</source>
<translation>线</translation>
</message>
<message>
<location filename="qml/BottomUI.qml" line="171"/>
<location filename="qml/BottomUI.qml" line="185"/>
<source>Line Color</source>
<translation>线</translation>
</message>
<message>
<location filename="qml/BottomUI.qml" line="177"/>
<location filename="qml/BottomUI.qml" line="191"/>
<source>Line Width</source>
<translation>线</translation>
</message>
<message>
<location filename="qml/BottomUI.qml" line="187"/>
<location filename="qml/BottomUI.qml" line="201"/>
<source>Shadow Color</source>
<translation></translation>
</message>
<message>
<location filename="qml/BottomUI.qml" line="193"/>
<location filename="qml/BottomUI.qml" line="207"/>
<source>Shadow Size</source>
<translation></translation>
</message>
@ -53,123 +53,123 @@
<context>
<name>TopUI</name>
<message>
<location filename="qml/TopUI.qml" line="14"/>
<location filename="qml/TopUI.qml" line="12"/>
<source>Ordinal Scale Top UI widget</source>
<translation>UI挂件</translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="23"/>
<location filename="qml/TopUI.qml" line="54"/>
<source>Light</source>
<translation></translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="23"/>
<location filename="qml/TopUI.qml" line="54"/>
<source>Normal</source>
<translation></translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="23"/>
<location filename="qml/TopUI.qml" line="54"/>
<source>Bold</source>
<translation></translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="386"/>
<location filename="qml/TopUI.qml" line="396"/>
<location filename="qml/TopUI.qml" line="350"/>
<location filename="qml/TopUI.qml" line="360"/>
<source>Settings</source>
<translation></translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="412"/>
<location filename="qml/TopUI.qml" line="376"/>
<source>UI Settings</source>
<translation>UI设置</translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="451"/>
<location filename="qml/TopUI.qml" line="415"/>
<source>Configuration</source>
<translation></translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="506"/>
<location filename="qml/TopUI.qml" line="470"/>
<source>Circle Color</source>
<translation></translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="465"/>
<location filename="qml/TopUI.qml" line="429"/>
<source>Line Color</source>
<translation>线</translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="67"/>
<location filename="qml/TopUI.qml" line="64"/>
<source>Top Line Action</source>
<translation>UI动作</translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="82"/>
<location filename="qml/TopUI.qml" line="79"/>
<source>Command</source>
<translation></translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="83"/>
<location filename="qml/TopUI.qml" line="80"/>
<source>Toggle UI</source>
<translation>UI</translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="459"/>
<location filename="qml/TopUI.qml" line="423"/>
<source>Curve</source>
<translation>线</translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="471"/>
<location filename="qml/TopUI.qml" line="435"/>
<source>Line Width</source>
<translation>线</translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="481"/>
<location filename="qml/TopUI.qml" line="445"/>
<source>Shadow Color</source>
<translation></translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="487"/>
<location filename="qml/TopUI.qml" line="451"/>
<source>Shadow Size</source>
<translation></translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="500"/>
<location filename="qml/TopUI.qml" line="464"/>
<source>Battle UI</source>
<translation>UI</translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="516"/>
<location filename="qml/TopUI.qml" line="480"/>
<source>Clock Visible</source>
<translation></translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="524"/>
<location filename="qml/TopUI.qml" line="488"/>
<source>24 Hour Clock</source>
<translation>24</translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="532"/>
<location filename="qml/TopUI.qml" line="496"/>
<source>Font Color</source>
<translation></translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="540"/>
<location filename="qml/TopUI.qml" line="504"/>
<source>Font Size</source>
<translation></translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="552"/>
<location filename="qml/TopUI.qml" line="516"/>
<source>Font Style</source>
<translation></translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="562"/>
<location filename="qml/TopUI.qml" line="526"/>
<source>Font Weight</source>
<translation></translation>
</message>
<message>
<location filename="qml/TopUI.qml" line="572"/>
<location filename="qml/TopUI.qml" line="536"/>
<source>Text Vertical Offset</source>
<translation></translation>
</message>
@ -183,147 +183,160 @@
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="24"/>
<location filename="qml/WeatherWidget.qml" line="60"/>
<source>Light</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="24"/>
<location filename="qml/WeatherWidget.qml" line="60"/>
<source>Normal</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="24"/>
<location filename="qml/WeatherWidget.qml" line="60"/>
<source>Bold</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="219"/>
<location filename="qml/WeatherWidget.qml" line="234"/>
<location filename="qml/WeatherWidget.qml" line="250"/>
<location filename="qml/WeatherWidget.qml" line="229"/>
<location filename="qml/WeatherWidget.qml" line="244"/>
<source>Settings</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="224"/>
<source>Refresh</source>
<translation></translation>
<translation type="vanished"></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="291"/>
<location filename="qml/WeatherWidget.qml" line="283"/>
<source>Configuration</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="299"/>
<location filename="qml/WeatherWidget.qml" line="291"/>
<source>Location</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="300"/>
<source>Search address by location, latitude and longitude.</source>
<translation></translation>
<translation type="vanished"></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="294"/>
<source>Click to set location.</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="338"/>
<source>Search: country, city, district...</source>
<translation>...</translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="365"/>
<source>Location not found</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="305"/>
<location filename="qml/WeatherWidget.qml" line="393"/>
<source>Display Location</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="306"/>
<location filename="qml/WeatherWidget.qml" line="394"/>
<source>The location to display in widget.</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="311"/>
<location filename="qml/WeatherWidget.qml" line="400"/>
<source>Update Interval</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="313"/>
<location filename="qml/WeatherWidget.qml" line="329"/>
<location filename="qml/WeatherWidget.qml" line="402"/>
<location filename="qml/WeatherWidget.qml" line="418"/>
<source>Minutes</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="313"/>
<location filename="qml/WeatherWidget.qml" line="329"/>
<location filename="qml/WeatherWidget.qml" line="402"/>
<location filename="qml/WeatherWidget.qml" line="418"/>
<source>Hours</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="327"/>
<location filename="qml/WeatherWidget.qml" line="416"/>
<source>Unit</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="335"/>
<location filename="qml/WeatherWidget.qml" line="424"/>
<source>Background Color</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="341"/>
<location filename="qml/WeatherWidget.qml" line="430"/>
<source>Background Opacity</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="351"/>
<location filename="qml/WeatherWidget.qml" line="440"/>
<source>Area Opacity Difference</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="361"/>
<location filename="qml/WeatherWidget.qml" line="450"/>
<source>Icon Color</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="369"/>
<location filename="qml/WeatherWidget.qml" line="458"/>
<source>Temperature Text Settings</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="375"/>
<location filename="qml/WeatherWidget.qml" line="432"/>
<location filename="qml/WeatherWidget.qml" line="464"/>
<location filename="qml/WeatherWidget.qml" line="521"/>
<source>Font Color</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="381"/>
<location filename="qml/WeatherWidget.qml" line="438"/>
<location filename="qml/WeatherWidget.qml" line="470"/>
<location filename="qml/WeatherWidget.qml" line="527"/>
<source>Font Size</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="391"/>
<location filename="qml/WeatherWidget.qml" line="448"/>
<location filename="qml/WeatherWidget.qml" line="480"/>
<location filename="qml/WeatherWidget.qml" line="537"/>
<source>Font Style</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="398"/>
<location filename="qml/WeatherWidget.qml" line="455"/>
<location filename="qml/WeatherWidget.qml" line="487"/>
<location filename="qml/WeatherWidget.qml" line="544"/>
<source>Font Weight</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="405"/>
<location filename="qml/WeatherWidget.qml" line="462"/>
<location filename="qml/WeatherWidget.qml" line="494"/>
<location filename="qml/WeatherWidget.qml" line="551"/>
<source>X Offset</source>
<translation>X偏移量</translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="415"/>
<location filename="qml/WeatherWidget.qml" line="472"/>
<location filename="qml/WeatherWidget.qml" line="504"/>
<location filename="qml/WeatherWidget.qml" line="561"/>
<source>Y Offset</source>
<translation>Y偏移量</translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="426"/>
<location filename="qml/WeatherWidget.qml" line="515"/>
<source>Area Text Settings</source>
<translation></translation>
</message>
<message>
<location filename="qml/WeatherWidget.qml" line="482"/>
<location filename="qml/WeatherWidget.qml" line="571"/>
<source>Border Margin</source>
<translation></translation>
</message>

2
package.json

@ -1,6 +1,6 @@
{
"name": "top.mashiros.widget.ordinalscale",
"version": "1.0.0",
"version": "1.1.1",
"title": {
"en": "Ordinal Scale Widget Collections",

36
qml/BottomUI.qml

@ -7,21 +7,31 @@ import NERvGear.Controls 1.0
import NERvGear.Templates 1.0 as T
import NERvGear.Preferences 1.0 as P
T.Widget {
WidgetTemplate {
id: widget
solid: true
visible: true
title: qsTr("Ordinal Scale Bottom UI widget")
property real thour: 0
property real t12hour: 0
property real tmin: 0
editing: styleDialog.active
readonly property var defaultValues: {"Curve":true,"Circle Color":"#fffcf9","Line Color":"#fffcf9","Line Width":38,"Shadow Color":"#e0e0e0","Shadow Size":0.5,"Battle UI":false,"Clock Visible":true,"Full Clock":true,"Font Color":"#f5f5f5","Font Size":44,"Font Name":0,"Font Weight":0,"Text Vertical Offset":16}
readonly property var configs: widget.settings.styles
version: "1.0.1"
defaultValues: {
"Curve": true,
"Circle Color": "#fffcf9",
"Line Color": "#fffcf9",
"Line Width": 38,
"Shadow Color": "#e0e0e0",
"Shadow Size": 0.5,
"Battle UI": false,
"Clock Visible": true,
"Full Clock": true,
"Font Color": "#f5f5f5",
"Font Size": 44,
"Font Name": 0,
"Font Weight": 0,
"Text Vertical Offset": 16
}
property string line_color: configs["Line Color"]
property string shadowColor: configs["Shadow Color"]
property real shadowBlur: configs["Shadow Size"]
@ -30,6 +40,10 @@ T.Widget {
readonly property real w: widget.width
readonly property real r: (w**2+4*h**2)/2/h
onUpdated: {
widget.settings.styles = Object.assign(defaultValues, widget.settings.styles);
}
onConfigsChanged: {
line.requestPaint();
triangle.requestPaint();
@ -218,8 +232,4 @@ T.Widget {
}
}
}
Component.onCompleted: {
widget.settings.styles = widget.settings.styles ?? defaultValues;
}
}

125
qml/TopUI.qml

@ -7,22 +7,13 @@ import NERvGear.Controls 1.0
import NERvGear.Templates 1.0 as T
import NERvGear.Preferences 1.0 as P
T.Widget {
WidgetTemplate {
id: widget
solid: true
visible: true
title: qsTr("Ordinal Scale Top UI widget")
property real thour: 0
property real t12hour: 0
property real tmin: -1
editing: styleDialog.active
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 var defaultValues: {
version: "1.0.1"
defaultValues: {
"Curve": "true",
"Line Color": "#fffcf9",
"Line Width": 38,
@ -39,17 +30,9 @@ T.Widget {
"Text Vertical Offset": 16
}
readonly property var configs: widget.settings.styles
property string circle_color: configs["Circle Color"]
property string line_color: configs["Line Color"]
property string shadowColor: configs["Shadow Color"]
property real shadowBlur: configs["Shadow Size"]
readonly property real size: 155
readonly property real h: Math.min(widget.width, widget.height)
readonly property real w: widget.width
readonly property real r: (w**2+h**2)/4/h
onUpdated: {
widget.settings.styles = Object.assign(defaultValues, widget.settings.styles);
}
onConfigsChanged: {
line.requestPaint();
@ -61,6 +44,20 @@ T.Widget {
c5.requestPaint();
}
readonly property var configs: widget.settings.styles
property real thour: 0
property real t12hour: 0
property real tmin: -1
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 real size: 155
readonly property real h: Math.min(widget.width, widget.height)
readonly property real w: widget.width
readonly property real r: (w**2+h**2)/4/h
action: T.Action {
id: thiz
@ -132,17 +129,15 @@ T.Widget {
width: size
height: size
contextType: "2d"
renderTarget: Canvas.FramebufferObject
renderStrategy: Canvas.Cooperative
onPaint: {
context.reset();
context.clearRect(0,0,size,size);
context.shadowBlur = shadowBlur;
context.shadowColor = shadowColor;
context.lineWidth = size*0.04 - shadowBlur;
context.shadowBlur = configs["Shadow Size"];
context.shadowColor = configs["Shadow Color"];
context.lineWidth = size*0.04 - configs["Shadow Size"];
context.beginPath();
context.arc(size/2, size/2, size*0.38-shadowBlur/2, -Math.PI/6, -Math.PI/6+Math.PI*2/3 , true);
context.strokeStyle = circle_color;
context.arc(size/2, size/2, size*0.38-configs["Shadow Size"]/2, -Math.PI/6, -Math.PI/6+Math.PI*2/3 , true);
context.strokeStyle = configs["Circle Color"];
context.stroke();
}
rotation: -140
@ -171,17 +166,15 @@ T.Widget {
width: size
height: size
contextType: "2d"
renderTarget: Canvas.FramebufferObject
renderStrategy: Canvas.Cooperative
onPaint: {
context.reset();
context.clearRect(0,0,size,size);
context.shadowBlur = shadowBlur;
context.shadowColor = shadowColor;
context.lineWidth = size*0.08 - shadowBlur;
context.shadowBlur = configs["Shadow Size"];
context.shadowColor = configs["Shadow Color"];
context.lineWidth = size*0.08 - configs["Shadow Size"];
context.beginPath();
context.arc(size/2, size/2, size*0.30-shadowBlur/2, -Math.PI/6, -Math.PI/24+Math.PI*2/3 , true);
context.strokeStyle = circle_color;
context.arc(size/2, size/2, size*0.30-configs["Shadow Size"]/2, -Math.PI/6, -Math.PI/24+Math.PI*2/3 , true);
context.strokeStyle = configs["Circle Color"];
context.stroke();
}
rotation: 20
@ -201,17 +194,15 @@ T.Widget {
width: size
height: size
contextType: "2d"
renderTarget: Canvas.FramebufferObject
renderStrategy: Canvas.Cooperative
onPaint: {
context.reset();
context.clearRect(0,0,size,size);
context.shadowBlur = shadowBlur;
context.shadowColor = shadowColor;
context.lineWidth = size*0.03 - shadowBlur;
context.shadowBlur = configs["Shadow Size"];
context.shadowColor = configs["Shadow Color"];
context.lineWidth = size*0.03 - configs["Shadow Size"];
context.beginPath();
context.arc(size/2, size/2, size*0.23-shadowBlur/2, -Math.PI/6, Math.PI/12+Math.PI*2/3 , true);
context.strokeStyle = circle_color;
context.arc(size/2, size/2, size*0.23-configs["Shadow Size"]/2, -Math.PI/6, Math.PI/12+Math.PI*2/3 , true);
context.strokeStyle = configs["Circle Color"];
context.stroke();
}
rotation: 90
@ -231,17 +222,15 @@ T.Widget {
width: size
height: size
contextType: "2d"
renderTarget: Canvas.FramebufferObject
renderStrategy: Canvas.Cooperative
onPaint: {
context.reset();
context.clearRect(0,0,size,size);
context.shadowBlur = shadowBlur;
context.shadowColor = shadowColor;
context.lineWidth = size*0.06 - shadowBlur;
context.shadowBlur = configs["Shadow Size"];
context.shadowColor = configs["Shadow Color"];
context.lineWidth = size*0.06 - configs["Shadow Size"];
context.beginPath();
context.arc(size/2, size/2, size*0.17-shadowBlur/2, -Math.PI/6, Math.PI/4+Math.PI*2/3 , true);
context.strokeStyle = circle_color;
context.arc(size/2, size/2, size*0.17-configs["Shadow Size"]/2, -Math.PI/6, Math.PI/4+Math.PI*2/3 , true);
context.strokeStyle = configs["Circle Color"];
context.stroke();
}
rotation: -70
@ -270,17 +259,15 @@ T.Widget {
width: size
height: size
contextType: "2d"
renderTarget: Canvas.FramebufferObject
renderStrategy: Canvas.Cooperative
onPaint: {
context.reset();
context.clearRect(0,0,size,size);
context.shadowBlur = shadowBlur;
context.shadowColor = shadowColor;
context.lineWidth = size*0.1 - shadowBlur;
context.shadowBlur = configs["Shadow Size"];
context.shadowColor = configs["Shadow Color"];
context.lineWidth = size*0.1 - configs["Shadow Size"];
context.beginPath();
context.arc(size/2, size/2, size*0.05-shadowBlur/2, 0, -Math.PI*2 , true);
context.strokeStyle = circle_color;
context.arc(size/2, size/2, size*0.05-configs["Shadow Size"]/2, 0, -Math.PI*2 , true);
context.strokeStyle = configs["Circle Color"];
context.stroke();
}
}
@ -291,17 +278,15 @@ T.Widget {
width: size
height: size
contextType: "2d"
renderTarget: Canvas.FramebufferObject
renderStrategy: Canvas.Cooperative
onPaint: {
context.reset();
context.clearRect(0,0,size,size);
context.shadowBlur = shadowBlur;
context.shadowColor = shadowColor;
context.lineWidth = size*0.16 - shadowBlur;
context.shadowBlur = configs["Shadow Size"];
context.shadowColor = configs["Shadow Color"];
context.lineWidth = size*0.16 - configs["Shadow Size"];
context.beginPath();
context.arc(size/2, size/2, size*0.38-shadowBlur/2, 0, -Math.PI/3 , true);
context.strokeStyle = circle_color;
context.arc(size/2, size/2, size*0.38-configs["Shadow Size"]/2, 0, -Math.PI/3 , true);
context.strokeStyle = configs["Circle Color"];
context.stroke();
}
@ -325,10 +310,10 @@ T.Widget {
onPaint: {
context.reset();
context.clearRect(0,0,width,height);
context.shadowBlur = shadowBlur;
context.shadowColor = shadowColor;
context.shadowBlur = configs["Shadow Size"];
context.shadowColor = configs["Shadow Color"];
context.lineWidth = Math.max(0.08*configs["Line Width"], 0.1);
context.strokeStyle = line_color;
context.strokeStyle = configs["Line Color"];
let deg = Math.asin(w/2/r)*0.95;
context.beginPath();
if (configs["Curve"]) {
@ -578,8 +563,4 @@ T.Widget {
}
}
}
Component.onCompleted: {
widget.settings.styles = widget.settings.styles ?? defaultValues;
}
}

255
qml/WeatherWidget.qml

@ -11,22 +11,66 @@ 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
import "utils.js" as Utils
T.Widget {
WidgetTemplate {
id: widget
title: qsTr("Ordinal Scale Weather Widget")
solid: true
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
}
}
onUpdated: {
widget.settings.styles = Object.assign(defaultValues, widget.settings.styles);
}
readonly property var configs: widget.settings.styles
readonly property real w: widget.width
readonly property real h: 0.46*widget.width
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 var configs: widget.settings.styles ?? {"Location":"","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}}
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"}
}
readonly property real w: widget.width
readonly property real h: 0.46*widget.width
NVG.DataSourceRawOutput {
id: output
source: dataSource
}
Item {
id: main
@ -110,7 +154,7 @@ T.Widget {
anchors.centerIn: weather
autoTransform: true
visible: false
source: "../Images/Weather/Unknown.png"
source: "../Images/Weather/" + Utils.weather_codes[output.result?.iconCode ?? "44"] + ".png"
}
Rectangle {
@ -145,7 +189,7 @@ T.Widget {
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: ""
text: configs["Display Location"]
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"]]
@ -167,63 +211,18 @@ T.Widget {
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: "--°"
text: (output.result?.temperature ?? "--") + "°"
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"]]
}
}
function setWeather() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if(xhr.readyState === XMLHttpRequest.DONE) {
let data = xhr.responseText.toString();
if (data) {
let jdata = JSON.parse(data);
temperature.text = jdata["current_condition"][0]["temp_C"] + "°";
if (!configs["Display Location"] && !configs["Location"]) {
area.text = jdata["nearest_area"][0]["areaName"][0]["value"];
}
weather_mask.source = "../Images/Weather/" + Utils.weather_codes[jdata["current_condition"][0]["weatherCode"]] ?? "Unknown" + ".png";
} else {
weather_mask.source = "../Images/Weather/Unknown.png";
}
}
}
if (configs["Location"])
xhr.open("GET", 'https://wttr.in/'+configs["Location"]+'?format=j1');
else
xhr.open("GET", 'https://wttr.in/?format=j1');
xhr.send();
if (configs["Display Location"]) {
area.text = configs["Display Location"];
} else if (configs["Location"]) {
area.text = configs["Location"]
}
}
Timer {
id: timer
interval: 600000
running: widget.NVG.View.exposed
repeat: true
triggeredOnStart: true
onTriggered: {
setWeather();
}
}
menu: Menu {
Action {
text: qsTr("Settings") + "..."
onTriggered: styleDialog.active = true
}
Action {
text: qsTr("Refresh")
onTriggered: timer.restart()
}
}
Loader {
@ -243,7 +242,6 @@ T.Widget {
property var configuration
Page {
id: cfg_page
anchors.fill: parent
header: TitleBar {
@ -255,12 +253,10 @@ T.Widget {
configuration = rootPreference.save();
widget.settings.styles = configuration;
styleDialog.active = false;
timer.interval = 60000*configs["Update Interval"]["Value"]*(1+59*configs["Update Interval"]["Unit"])
setWeather();
}
onReset: {
rootPreference.load();
rootPreference.load({"Address": widget.settings.styles?.Address});
let cfg = rootPreference.save();
widget.settings.styles = cfg;
}
@ -294,16 +290,113 @@ T.Widget {
widget.settings.styles = rootPreference.save();
}
P.TextFieldPreference {
name: "Location"
P.DialogPreference {
id: rootPref
label: qsTr("Location")
message: qsTr("Search address by location, latitude and longitude.")
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
}
}
}
}
}
P.TextFieldPreference {
name: "Display Location"
label: qsTr("Display Location")
message: qsTr("The location to display in widget.")
defaultValue: defaultValues["Display Location"]
}
P.DialogPreference {
@ -318,14 +411,14 @@ T.Widget {
from: 1
to: 1440
editable: true
defaultValue: 1
defaultValue: defaultValues["Update Interval"]["Value"]
}
P.SelectPreference {
id: _cfg_update_interval_unit
name: "Unit"
label: qsTr("Unit")
defaultValue: 1
defaultValue: defaultValues["Update Interval"]["Unit"]
model: [qsTr("Minutes"), qsTr("Hours")]
}
}
@ -333,7 +426,7 @@ T.Widget {
P.ColorPreference {
name: "Background Color"
label: qsTr("Background Color")
defaultValue: "#ffa502"
defaultValue: defaultValues["Background Color"]
}
P.SliderPreference {
@ -342,7 +435,7 @@ T.Widget {
from: 0
to: 100
stepSize: 1
defaultValue: 60
defaultValue: defaultValues["Background Opacity"]
displayValue: value + "%"
}
@ -352,14 +445,14 @@ T.Widget {
from: 0
to: 100
stepSize: 1
defaultValue: 17
defaultValue: defaultValues["Area Opacity Difference"]
displayValue: value + "%"
}
P.ColorPreference {
name: "Icon Color"
label: qsTr("Icon Color")
defaultValue: "#fefefe"
defaultValue: defaultValues["Icon Color"]
}
P.Separator {}
@ -373,7 +466,7 @@ T.Widget {
P.ColorPreference {
name: "Font Color"
label: qsTr("Font Color")
defaultValue: "#f5f5f5"
defaultValue: defaultValues["Temperature Text Settings"]["Font Color"]
}
P.SliderPreference {
@ -382,21 +475,21 @@ T.Widget {
from: 1
to: 100
stepSize: 1
defaultValue: 90
defaultValue: defaultValues["Temperature Text Settings"]["Font Size"]
displayValue: value + "%"
}
P.SelectPreference {
name: "Font Name"
label: qsTr("Font Style")
defaultValue: fonts.length-1
defaultValue: defaultValues["Temperature Text Settings"]["Font Name"]
model: fonts
}
P.SelectPreference {
name: "Font Weight"
label: qsTr("Font Weight")
defaultValue: 1
defaultValue: defaultValues["Temperature Text Settings"]["Font Weight"]
model: sfontweight
}
@ -406,7 +499,7 @@ T.Widget {
from: -100
to: 100
stepSize: 1
defaultValue: 33
defaultValue: defaultValues["Temperature Text Settings"]["X Offset"]
displayValue: value + "%"
}
@ -416,7 +509,7 @@ T.Widget {
from: -100
to: 100
stepSize: 1
defaultValue: 32
defaultValue: defaultValues["Temperature Text Settings"]["Y Offset"]
displayValue: value + "%"
}
}
@ -430,7 +523,7 @@ T.Widget {
P.ColorPreference {
name: "Font Color"
label: qsTr("Font Color")
defaultValue: "#f5f5f5"
defaultValue: defaultValues["Area Text Settings"]["Font Color"]
}
P.SliderPreference {
@ -439,21 +532,21 @@ T.Widget {
from: 1
to: 100
stepSize: 1
defaultValue: 60
defaultValue: defaultValues["Area Text Settings"]["Font Size"]
displayValue: value + "%"
}
P.SelectPreference {
name: "Font Name"
label: qsTr("Font Style")
defaultValue: fonts.length-1
defaultValue: defaultValues["Area Text Settings"]["Font Name"]
model: fonts
}
P.SelectPreference {
name: "Font Weight"
label: qsTr("Font Weight")
defaultValue: 1
defaultValue: defaultValues["Area Text Settings"]["Font Weight"]
model: sfontweight
}
@ -463,7 +556,7 @@ T.Widget {
from: -100
to: 100
stepSize: 1
defaultValue: 0
defaultValue: defaultValues["Area Text Settings"]["X Offset"]
displayValue: value + "%"
}
@ -473,7 +566,7 @@ T.Widget {
from: -100
to: 100
stepSize: 1
defaultValue: -56
defaultValue: defaultValues["Area Text Settings"]["Y Offset"]
displayValue: value + "%"
}
@ -483,7 +576,7 @@ T.Widget {
from: 0
to: 100
stepSize: 1
defaultValue: 40
defaultValue: defaultValues["Area Text Settings"]["Border Margin"]
displayValue: value + "%"
}
}

27
qml/WidgetTemplate.qml

@ -0,0 +1,27 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import NERvGear 1.0 as NVG
import NERvGear.Templates 1.0 as T
T.Widget {
solid: true
visible: true
property string version: ""
property var defaultValues: {}
signal completed()
signal updated()
Component.onCompleted: {
if (!widget.settings.styles) {
widget.settings.styles = defaultValues;
widget.settings.version = version;
} else if (widget.settings.version !== version) {
updated();
widget.settings.version = version;
}
completed();
}
}

96
qml/utils.js

@ -2,52 +2,52 @@
// https://github.com/chubin/wttr.in/blob/master/lib/constants.py
var weather_codes = {
"113": "Sunny",
"116": "PartlyCloudy",
"119": "Cloudy",
"122": "VeryCloudy",
"143": "Fog",
"176": "Showers",
"179": "LightSleet",
"182": "LightSleet",
"185": "LightSleet",
"200": "ThunderyShowers",
"227": "LightSnow",
"230": "HeavySnow",
"248": "Fog",
"260": "Fog",
"263": "Showers",
"266": "LightRain",
"281": "LightSleet",
"284": "LightSleet",
"293": "LightRain",
"296": "LightRain",
"299": "Showers",
"302": "HeavyRain",
"305": "Showers",
"308": "HeavyRain",
"311": "LightSleet",
"314": "LightSleet",
"317": "LightSleet",
"320": "LightSnow",
"323": "SnowShowers",
"326": "SnowShowers",
"329": "HeavySnow",
"332": "HeavySnow",
"335": "SnowShowers",
"338": "HeavySnow",
"350": "LightSleet",
"353": "Showers",
"356": "Showers",
"359": "HeavyRain",
"362": "LightSleet",
"365": "LightSleet",
"368": "SnowShowers",
"371": "SnowShowers",
"374": "LightSleet",
"377": "LightSleet",
"386": "ThunderyShowers",
"389": "ThunderyHeavyRain",
"392": "SnowShowers",
"395": "SnowShowers"
"0": "Tornado",
"1": "Hurricane",
"2": "Hurricane",
"3": "ThunderyHeavyRain",
"4": "ThunderyHeavyRain",
"5": "LightSleet",
"6": "LightSleet",
"7": "LightSleet",
"8": "LightSleet",
"9": "Showers",
"10": "LightSleet",
"11": "LightRain",
"12": "HeavyRain",
"13": "SnowShowers",
"14": "LightSnow",
"15": "SnowShowers",
"16": "LightSnow",
"17": "Hail",
"18": "LightSleet",
"19": "Sandstorm",
"20": "Fog",
"21": "Fog",
"22": "Fog",
"23": "Breezy",
"24": "Breezy",
"25": "IceCrystals",
"26": "Cloudy",
"27": "VeryCloudy",
"28": "VeryCloudy",
"29": "PartlyCloudyNight",
"30": "PartlyCloudyDay",
"31": "Clear",
"32": "Sunny",
"33": "PartlyCloudyNight",
"34": "PartlyCloudyDay",
"35": "Hail",
"36": "Sunny",
"37": "ThunderyShowers",
"38": "ThunderyHeavyRain",
"39": "Showers",
"40": "HeavyRain",
"41": "SnowShowers",
"42": "HeavySnow",
"43": "HeavySnow",
"44": "Unknown",
"45": "Showers",
"46": "SnowShowers",
"47": "ThunderyShowers"
};
Loading…
Cancel
Save