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.

465 lines
14 KiB

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 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
WidgetTemplate {
id: widget
title: qsTr("Round Clock")
editing: styleDialog.active
resizable: true
version: "1.0.0"
defaultValues: {
"Sec Continue": true,
"BG Color": "#2196f3",
"BG Alpha": 50,
"HGRID Color": "#ffffff",
"MGRID Color": "#ffffff",
"Hhand Color": "#ffffff",
"Mhand Color": "#ffffff",
"Shand Color": "#f3a829"
}
property real maxr: Math.min(width/2, height/2) -10
property real thour: 0
property real tmin: 0
property real tsec: 0
property var configs: widget.settings.styles
onConfigsChanged: {
background.requestPaint();
hour.requestPaint();
min.requestPaint();
sec.requestPaint();
sec_tail.requestPaint();
sec_center.requestPaint();
}
function colorToRGBA(color, alpha) {
var color1, color2, color3;
color = ""+color;
if (typeof color !== "string") return;
if (color.charAt(0) === "#") {
color = color.substring(1);
}
var not16num = color.split("").filter(function (item, index) {
return isNaN(parseInt(item, 16))
});
if(not16num.length) return;
switch (color.length) {
case 3:
color1 = color.substr(0,1);
color2 = color.substr(1,1);
color3 = color.substr(2,1);
color1 = color1 + color1;
color2 = color2 + color2;
color3 = color3 + color3;
break;
case 6:
color1 = color.substr(0,2);
color2 = color.substr(2,2);
color3 = color.substr(4,2);
break;
default:
return false;
}
color1 = parseInt(color1, 16);
color2 = parseInt(color2, 16);
color3 = parseInt(color3, 16);
return "rgba("+color1+","+color2+","+color3+","+alpha+")";
}
Timer {
interval: configs["Sec Continue"] ? 50 : 250
running: widget.NVG.View.exposed
repeat: true
onTriggered: {
var now = new Date();
tsec = now.getSeconds() + (configs["Sec Continue"] ? now.getMilliseconds()/1000 : 0);
tmin = now.getMinutes();
thour = now.getHours();
thour = thour % 12;
}
}
Canvas {
id: background
width: widget.width;
height: widget.height;
contextType: "2d";
renderTarget: Canvas.FramebufferObject
renderStrategy: Canvas.Cooperative
onWidthChanged: {
requestPaint();
}
onHeightChanged: {
requestPaint();
}
onPaint: {
context.resetTransform();
context.clearRect(0,0,widget.width,widget.height);
context.translate(width/2, height/2); //将坐标原点移到画布中心
context.rotate(-Math.PI/2); //将坐标轴逆时针旋转90度,x轴正方向对准12点方向
context.fillStyle = colorToRGBA(configs["BG Color"], configs["BG Alpha"]/100);
context.beginPath();
context.arc(0, 0, maxr, 0, Math.PI * 2, true);
context.fill();
context.strokeStyle = configs["HGRID Color"];
context.lineWidth = maxr*0.04;
context.lineCap = "round";
for (var i = 0; i < 12; i++) {
context.beginPath();
context.rotate(Math.PI / 6);
context.moveTo(maxr*0.92, 0);
context.lineTo(maxr*0.78, 0);
context.stroke();
}
context.strokeStyle = configs["MGRID Color"];
context.lineWidth = maxr*0.015;
for (i = 0; i < 60; i++) {
if (i % 5 !== 0) { //去掉与小时刻度重叠的部分
context.beginPath();
context.moveTo(maxr*0.92, 0);
context.lineTo(maxr*0.86, 0);
context.stroke();
}
context.rotate(Math.PI / 30);
}
}
}
Canvas {
id: hour
width: widget.width;
height: widget.height;
contextType: "2d";
renderTarget: Canvas.FramebufferObject
renderStrategy: Canvas.Cooperative
rotation: thour*30+tmin*0.5+tsec*0.01
onWidthChanged: {
requestPaint();
}
onHeightChanged: {
requestPaint();
}
onPaint: {
context.resetTransform();
context.clearRect(0,0,widget.width,widget.height);
context.translate(width/2, height/2);
context.shadowColor = 'rgba(0,0,0,.5)';
context.shadowBlur = maxr*0.03;
context.lineCap = "round";
context.strokeStyle = configs["Hhand Color"];
context.lineWidth = maxr*0.08;
context.beginPath();
context.moveTo(0,0);
context.lineTo(0, -maxr*0.56);
context.stroke();
}
}
Canvas {
id: min
width: widget.width;
height: widget.height;
contextType: "2d";
renderTarget: Canvas.FramebufferObject
renderStrategy: Canvas.Cooperative
rotation: tmin*6+tsec*0.1
onWidthChanged: {
requestPaint();
}
onHeightChanged: {
requestPaint();
}
onPaint: {
context.resetTransform();
context.clearRect(0,0,widget.width,widget.height);
context.translate(width/2, height/2);
context.shadowColor = 'rgba(0,0,0,.5)';
context.shadowBlur = maxr*0.04;
context.lineCap = "round";
context.strokeStyle = configs["Mhand Color"];
context.lineWidth = maxr*0.045;
context.beginPath();
context.moveTo(0,0);
context.lineTo(0, -maxr*0.82);
context.stroke();
}
}
Canvas {
id: sec
width: widget.width;
height: widget.height;
contextType: "2d";
renderTarget: Canvas.FramebufferObject
renderStrategy: Canvas.Cooperative
rotation: widget.tsec*6
onWidthChanged: {
requestPaint();
}
onHeightChanged: {
requestPaint();
}
onPaint: {
context.resetTransform();
context.clearRect(0,0,widget.width,widget.height);
context.translate(width/2, height/2);
context.shadowColor = 'rgba(0,0,0,.5)';
context.shadowBlur = maxr*0.05;
context.lineCap = "round";
context.strokeStyle = configs["Shand Color"];
context.lineWidth = maxr*0.016;
context.beginPath();
context.moveTo(0,0);
context.lineTo(0, -maxr*0.9);
context.stroke();
}
}
Canvas {
id: sec_tail
width: widget.width;
height: widget.height;
contextType: "2d";
renderTarget: Canvas.FramebufferObject
renderStrategy: Canvas.Cooperative
rotation: widget.tsec*6
onWidthChanged: {
requestPaint();
}
onHeightChanged: {
requestPaint();
}
onPaint: {
context.resetTransform();
context.clearRect(0,0,widget.width,widget.height);
context.translate(width/2, height/2);
context.shadowColor = 'rgba(0,0,0,.5)';
context.shadowBlur = maxr*0.05;
context.lineCap = "round";
context.strokeStyle = configs["Shand Color"];
context.beginPath();
context.moveTo(0,0);
context.lineTo(0, maxr*0.07);
context.lineWidth = maxr*0.07;
context.stroke();
}
}
Canvas {
id: sec_center
width: widget.width;
height: widget.height;
contextType: "2d";
renderTarget: Canvas.FramebufferObject
renderStrategy: Canvas.Cooperative
onWidthChanged: {
requestPaint();
}
onHeightChanged: {
requestPaint();
}
onPaint: {
context.resetTransform();
context.clearRect(0,0,widget.width,widget.height);
context.translate(width/2, height/2);
context.shadowColor = 'rgba(0,0,0,.5)';
context.shadowBlur = maxr*0.1;
context.shadowOffsetX = maxr*0.05/2.5;
context.shadowOffsetY = maxr*0.05/2.5;
context.beginPath();
context.arc(0, 0, maxr*0.07, 0, Math.PI * 2, true);
context.fillStyle = configs["Shand Color"];
context.fill();
}
}
menu: Menu {
Action {
text: qsTr("Settings") + "..."
onTriggered: styleDialog.active = true
}
}
Loader {
id: styleDialog
active: false
sourceComponent: NVG.Window {
id: window
title: qsTr("Clock Settings")
visible: true
minimumWidth: 380
minimumHeight: 540
width: minimumWidth
height: minimumHeight
transientParent: widget.NVG.View.window
property var configuration
Page {
id: cfg_page
anchors.fill: parent
header: TitleBar {
text: qsTr("Round Clock")
standardButtons: Dialog.Save | Dialog.Reset
onAccepted: {
configuration = rootPreference.save();
widget.settings.styles = configuration;
styleDialog.active = false;
}
onReset: {
rootPreference.load();
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.SwitchPreference {
name: "Sec Continue"
label: qsTr("Continuous Second Hand")
defaultValue: defaultValues["Sec Continue"]
}
P.Separator {}
P.ColorPreference {
name: "BG Color"
label: qsTr("Background Color")
defaultValue: defaultValues["BG Color"]
}
P.SliderPreference {
name: "BG Alpha"
label: qsTr("Background transparency")
from: 0
to: 100
stepSize: 1
defaultValue: defaultValues["BG Alpha"]
displayValue: value + "%"
}
P.Separator {}
P.ColorPreference {
name: "HGRID Color"
label: qsTr("Hour Scale Color")
defaultValue: defaultValues["HGRID Color"]
}
P.ColorPreference {
name: "MGRID Color"
label: qsTr("Minute Scale Color")
defaultValue: defaultValues["MGRID Color"]
}
P.Separator {}
P.ColorPreference {
name: "Hhand Color"
label: qsTr("Hour Hand Color")
defaultValue: defaultValues["Hhand Color"]
}
P.ColorPreference {
name: "Mhand Color"
label: qsTr("Minute Hand Color")
defaultValue: defaultValues["Mhand Color"]
}
P.ColorPreference {
name: "Shand Color"
label: qsTr("Second Hand Color")
defaultValue: defaultValues["Shand Color"]
}
Component.onCompleted: {
rootPreference.load(widget.settings.styles);
configuration = widget.settings.styles;
}
}
}
}
}
}
onClosing: {
widget.settings.styles = configuration;
styleDialog.active = false;
}
}
}
}