1/*
2    SPDX-FileCopyrightText: 2012 Viranch Mehta <viranch.mehta@gmail.com>
3    SPDX-FileCopyrightText: 2012 Marco Martin <mart@kde.org>
4    SPDX-FileCopyrightText: 2013 David Edmundson <davidedmundson@kde.org>
5
6    SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
9import QtQuick 2.0
10import org.kde.plasma.plasmoid 2.0
11import org.kde.plasma.calendar 2.0 as PlasmaCalendar
12import QtQuick.Layouts 1.1
13
14import org.kde.plasma.core 2.0 as PlasmaCore
15import org.kde.plasma.components 3.0 as PlasmaComponents
16
17Item {
18    id: analogclock
19
20    width: PlasmaCore.Units.gridUnit * 15
21    height: PlasmaCore.Units.gridUnit * 15
22    property int hours
23    property int minutes
24    property int seconds
25    property bool showSecondsHand: plasmoid.configuration.showSecondHand
26    property bool showTimezone: plasmoid.configuration.showTimezoneString
27    property int tzOffset
28
29    Plasmoid.backgroundHints: "NoBackground";
30    Plasmoid.preferredRepresentation: Plasmoid.compactRepresentation
31
32    Plasmoid.toolTipMainText: Qt.formatDate(dataSource.data["Local"]["DateTime"],"dddd")
33    Plasmoid.toolTipSubText: Qt.formatTime(dataSource.data["Local"]["DateTime"],  Qt.locale().timeFormat(Locale.LongFormat)) + "\n" +
34        Qt.formatDate(dataSource.data["Local"]["DateTime"], Qt.locale().dateFormat(Locale.LongFormat).replace(/(^dddd.?\s)|(,?\sdddd$)/, ""))
35
36    PlasmaCore.DataSource {
37        id: dataSource
38        engine: "time"
39        connectedSources: "Local"
40        interval: showSecondsHand ? 1000 : 30000
41        onDataChanged: {
42            var date = new Date(data["Local"]["DateTime"]);
43            hours = date.getHours();
44            minutes = date.getMinutes();
45            seconds = date.getSeconds();
46        }
47        Component.onCompleted: {
48            onDataChanged();
49        }
50    }
51
52    function dateTimeChanged()
53    {
54        //console.log("Date/time changed!");
55
56        var currentTZOffset = dataSource.data["Local"]["Offset"] / 60;
57        if (currentTZOffset !== tzOffset) {
58            tzOffset = currentTZOffset;
59            //console.log("TZ offset changed: " + tzOffset);
60            Date.timeZoneUpdated(); // inform the QML JS engine about TZ change
61        }
62    }
63
64    Component.onCompleted: {
65        tzOffset = new Date().getTimezoneOffset();
66        //console.log("Initial TZ offset: " + tzOffset);
67        dataSource.onDataChanged.connect(dateTimeChanged);
68    }
69
70    Plasmoid.compactRepresentation: Item {
71        id: representation
72        Layout.minimumWidth: plasmoid.formFactor !== PlasmaCore.Types.Vertical ? representation.height : PlasmaCore.Units.gridUnit
73        Layout.minimumHeight: plasmoid.formFactor === PlasmaCore.Types.Vertical ? representation.width : PlasmaCore.Units.gridUnit
74
75        MouseArea {
76            anchors.fill: parent
77            onClicked: plasmoid.expanded = !plasmoid.expanded
78        }
79
80
81        PlasmaCore.Svg {
82            id: clockSvg
83            imagePath: "widgets/clock"
84            function estimateHorizontalHandShadowOffset() {
85                var id = "hint-hands-shadow-offset-to-west";
86                if (hasElement(id)) {
87                    return -elementSize(id).width;
88                }
89                id = "hint-hands-shadows-offset-to-east";
90                if (hasElement(id)) {
91                    return elementSize(id).width;
92                }
93                return 0;
94            }
95            function estimateVerticalHandShadowOffset() {
96                var id = "hint-hands-shadow-offset-to-north";
97                if (hasElement(id)) {
98                    return -elementSize(id).height;
99                }
100                id = "hint-hands-shadow-offset-to-south";
101                if (hasElement(id)) {
102                    return elementSize(id).height;
103                }
104                return 0;
105            }
106            property double naturalHorizontalHandShadowOffset: estimateHorizontalHandShadowOffset()
107            property double naturalVerticalHandShadowOffset: estimateVerticalHandShadowOffset()
108            onRepaintNeeded: {
109                naturalHorizontalHandShadowOffset = estimateHorizontalHandShadowOffset();
110                naturalVerticalHandShadowOffset = estimateVerticalHandShadowOffset();
111            }
112        }
113
114        Item {
115            id: clock
116            width: parent.width
117            anchors {
118                top: parent.top
119                bottom: showTimezone ? timezoneBg.top : parent.bottom
120            }
121            readonly property double svgScale: face.width / face.naturalSize.width
122            readonly property double horizontalShadowOffset:
123                Math.round(clockSvg.naturalHorizontalHandShadowOffset * svgScale) + Math.round(clockSvg.naturalHorizontalHandShadowOffset * svgScale) % 2
124            readonly property double verticalShadowOffset:
125                Math.round(clockSvg.naturalVerticalHandShadowOffset * svgScale) + Math.round(clockSvg.naturalVerticalHandShadowOffset * svgScale) % 2
126
127            PlasmaCore.SvgItem {
128                id: face
129                anchors.centerIn: parent
130                width: Math.min(parent.width, parent.height)
131                height: Math.min(parent.width, parent.height)
132                svg: clockSvg
133                elementId: "ClockFace"
134            }
135
136            Hand {
137                elementId: "HourHandShadow"
138                rotationCenterHintId: "hint-hourhandshadow-rotation-center-offset"
139                horizontalRotationOffset: clock.horizontalShadowOffset
140                verticalRotationOffset: clock.verticalShadowOffset
141                rotation: 180 + hours * 30 + (minutes/2)
142                svgScale: clock.svgScale
143
144            }
145            Hand {
146                elementId: "HourHand"
147                rotationCenterHintId: "hint-hourhand-rotation-center-offset"
148                rotation: 180 + hours * 30 + (minutes/2)
149                svgScale: clock.svgScale
150            }
151
152            Hand {
153                elementId: "MinuteHandShadow"
154                rotationCenterHintId: "hint-minutehandshadow-rotation-center-offset"
155                horizontalRotationOffset: clock.horizontalShadowOffset
156                verticalRotationOffset: clock.verticalShadowOffset
157                rotation: 180 + minutes * 6
158                svgScale: clock.svgScale
159            }
160            Hand {
161                elementId: "MinuteHand"
162                rotationCenterHintId: "hint-minutehand-rotation-center-offset"
163                rotation: 180 + minutes * 6
164                svgScale: clock.svgScale
165            }
166
167            Hand {
168                elementId: "SecondHandShadow"
169                rotationCenterHintId: "hint-secondhandshadow-rotation-center-offset"
170                horizontalRotationOffset: clock.horizontalShadowOffset
171                verticalRotationOffset: clock.verticalShadowOffset
172                rotation: 180 + seconds * 6
173                visible: showSecondsHand
174                svgScale: clock.svgScale
175            }
176            Hand {
177                elementId: "SecondHand"
178                rotationCenterHintId: "hint-secondhand-rotation-center-offset"
179                rotation: 180 + seconds * 6
180                visible: showSecondsHand
181                svgScale: clock.svgScale
182            }
183
184            PlasmaCore.SvgItem {
185                id: center
186                width: naturalSize.width * clock.svgScale
187                height: naturalSize.height * clock.svgScale
188                anchors.centerIn: clock
189                svg: clockSvg
190                elementId: "HandCenterScrew"
191                z: 1000
192            }
193
194            PlasmaCore.SvgItem {
195                anchors.fill: face
196                svg: clockSvg
197                elementId: "Glass"
198                width: naturalSize.width * clock.svgScale
199                height: naturalSize.height * clock.svgScale
200            }
201        }
202
203        PlasmaCore.FrameSvgItem {
204            id: timezoneBg
205            anchors {
206                horizontalCenter: parent.horizontalCenter
207                bottom: parent.bottom
208                bottomMargin: 10
209            }
210            imagePath: "widgets/background"
211            width: childrenRect.width + margins.right + margins.left
212            height: childrenRect.height + margins.top + margins.bottom
213            visible: showTimezone
214            PlasmaComponents.Label {
215                id: timezoneText
216                x: timezoneBg.margins.left
217                y: timezoneBg.margins.top
218                text: dataSource.data["Local"]["Timezone"]
219            }
220        }
221    }
222    Plasmoid.fullRepresentation: PlasmaCalendar.MonthView {
223        Layout.minimumWidth: PlasmaCore.Units.gridUnit * 20
224        Layout.minimumHeight: PlasmaCore.Units.gridUnit * 20
225
226        today: dataSource.data["Local"]["DateTime"]
227    }
228
229}
230