Very early KDE 6 release.

This commit is contained in:
wackyideas 2024-08-09 03:20:25 +02:00
parent 7cc4ccabbc
commit 686046d4f7
6272 changed files with 140920 additions and 529657 deletions

View file

@ -0,0 +1,71 @@
/*
* Copyright 2013 Bhushan Shah <bhush94@gmail.com>
* Copyright 2015 Martin Klapetek <mklapetek@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
import QtQuick 2.0
import QtQml 2.2
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.configuration 2.0
import org.kde.plasma.workspace.calendar 2.0 as PlasmaCalendar
ConfigModel {
id: configModel
ConfigCategory {
name: i18n("Appearance")
icon: "preferences-desktop-color"
source: "configAppearance.qml"
}
ConfigCategory {
name: i18n("Calendar")
icon: "preferences-system-time"
source: "configCalendar.qml"
}
ConfigCategory {
name: i18n("Time Zones")
icon: "preferences-desktop-locale"
source: "configTimeZones.qml"
}
property QtObject eventPluginsManager: PlasmaCalendar.EventPluginsManager {
Component.onCompleted: {
populateEnabledPluginsList(Plasmoid.configuration.enabledCalendarPlugins);
}
}
property Instantiator __eventPlugins: Instantiator {
model: eventPluginsManager.model
delegate: ConfigCategory {
name: model.display
icon: { console.log(model.decoration); return model.decoration }
source: model.configUi
includeMargins: false
visible: Plasmoid.configuration.enabledCalendarPlugins.indexOf(model.pluginId) > -1
}
onObjectAdded: (index, object) => configModel.appendCategory(object)
onObjectRemoved: (index, object) => configModel.removeCategory(object)
//onObjectAdded: configModel.appendCategory(object)
//onObjectRemoved: configModel.removeCategory(object)
}
}

View file

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile name=""/>
<group name="Appearance">
<entry name="showLocalTimezone" type="Bool">
<label>Whether the timezone should be displayed when the clock is showing the local timezone.</label>
<default>false</default>
</entry>
<entry name="showSeconds" type="Bool">
<label>Whether seconds should be shown in the clock.</label>
<default>false</default>
</entry>
<entry name="showDate" type="Bool">
<label>Whether the date should be shown next to the clock.</label>
<default>false</default>
</entry>
<entry name="dateFormat" type="string">
<label>The date format to display. Options are: shortDate, longDate or isoDate.</label>
<default>shortDate</default>
</entry>
<entry name="fontFamily" type="string">
<label>Font family. e.g "arial". The system font is used if this is not set.</label>
<default></default>
</entry>
<entry name="fontSize" type="Int">
<label>Font size described in pixels.</label>
<default>9</default>
</entry>
<entry name="boldText" type="Bool">
<label>Sets the font to bold.</label>
<default>false</default>
</entry>
<entry name="italicText" type="Bool">
<label>Sets the font to italic.</label>
<default>false</default>
</entry>
<entry name="timeFormat" type="string">
<default>default</default>
</entry>
<entry name="selectedTimeZones" type="StringList">
<label>A list of the time zones available on mouse wheel. Requires wheelChangesTimezone to be true. Format is "Europe/London". Special entry "Local" indicates system time zone.</label>
<default>Local</default>
</entry>
<entry name="lastSelectedTimezone" type="String">
<label>When multiple time zones are configured, this is the one shown on widget restore.</label>
<default>Local</default>
</entry>
<entry name="wheelChangesTimezone" type="Bool">
<label>Whether the mouse wheel switches between the timezones configured in selectedTimeZones.</label>
<default>false</default>
</entry>
<entry name="displayTimezoneAsCode" type="Bool">
<label>Whether the timezone is displayed as a code i.e. "GMT" or full text i.e. "London".</label>
<default>true</default>
</entry>
<entry name="showWeekNumbers" type="Bool">
<label>Whether the calendar should show week numbers.</label>
<default>false</default>
</entry>
<entry name="firstDayOfWeek" type="Int">
<label>Force the calendar to use a specific week day as first day of a week. -1 means follow user locale, 0 is Sunday, 1 is Monday, etc.</label>
<default>-1</default>
</entry>
<entry name="use24hFormat" type="UInt">
<label>Force the clock to use 12/24 hour time, instead of following the user locale.</label>
<default>1</default>
</entry>
<entry name="enabledCalendarPlugins" type="StringList">
<label>A list of plugins where additional calendar event data can be sourced.</label>
<default></default>
</entry>
<entry name="pin" type="Bool">
<label>Whether the popup should remain open when another window is activated</label>
<default>false</default>
</entry>
<entry name="checkUpdateStartup" type="Bool">
<label>Notify for update on startup</label>
<default>true</default>
</entry>
</group>
</kcfg>

View file

@ -0,0 +1,586 @@
/*
* Copyright 2013 Sebastian Kügler <sebas@kde.org>
* Copyright 2015 Martin Klapetek <mklapetek@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.15
import QtQuick.Layouts 1.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.workspace.calendar 2.0 as PlasmaCalendar
import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.ksvg 1.0 as KSvg
import org.kde.kirigami 2.20 as Kirigami
import Qt5Compat.GraphicalEffects
PlasmaCore.Dialog {
id: calendar
objectName: "popupWindow"
flags: Qt.WindowStaysOnTopHint
location: PlasmaCore.Types.Floating //To make the dialog float in the corner of the screen
hideOnWindowDeactivate: !plasmoid.configuration.pin
//Used for reading margin values
KSvg.FrameSvgItem {
id : panelSvg
visible: false
imagePath: "widgets/panel-background"
}
KSvg.FrameSvgItem {
id : dialogSvg
visible: false
imagePath: "solid/dialogs/background"
}
onVisibleChanged: {
popupPosition();
monthView.resetToToday();
holidaysList.model = null;
holidaysList.model = monthView.daysModel.eventsForDate(monthView.currentDate);
}
onHeightChanged: {
popupPosition();
}
property int flyoutMargin: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing/2
onWidthChanged: {
popupPosition();
}
function popupPosition() {
var pos = root.mapToGlobal(root.x, root.y);
var availScreen = Plasmoid.containment.availableScreenRect;
x = pos.x - calendar.width / 2 + root.width / 2
y = pos.y - calendar.height;
if(x <= 0) x += flyoutMargin;
if(x + calendar.width >= availScreen.width) {
x = availScreen.width - calendar.width - flyoutMargin;
}
if(y <= 0) y += flyoutMargin;
if(y + calendar.height >= availScreen.height) {
y = availScreen.height - calendar.height - flyoutMargin;
}
}
readonly property bool showAgenda: Plasmoid.configuration.enabledCalendarPlugins.length > 0
property int _minimumWidth: 336//(showAgenda ? agendaViewWidth : Kirigami.Units.largeSpacing) + monthViewWidth
property int _minimumHeight: 247
readonly property int agendaViewWidth: _minimumHeight
readonly property int monthViewWidth: monthView.showWeekNumbers ? Math.round(_minimumHeight * 1.25) : Math.round(_minimumHeight * 1.125)
property int boxWidth: (agendaViewWidth + monthViewWidth - ((showAgenda ? 3 : 4) * spacing)) / 2
property int spacing: Kirigami.Units.largeSpacing
property alias borderWidth: monthView.borderWidth
property alias monthView: monthView
property bool debug: false
property bool isExpanded: Plasmoid.expanded
onIsExpandedChanged: {
// clear all the selections when the plasmoid is showing/hiding
monthView.resetToToday();
}
FocusScope {
Kirigami.Theme.colorSet: Kirigami.Theme.View
Kirigami.Theme.inherit: false
Layout.minimumWidth: _minimumWidth
Layout.minimumHeight: _minimumHeight
Layout.maximumWidth: _minimumWidth
Layout.maximumHeight: _minimumHeight
Layout.preferredWidth: _minimumWidth
Layout.preferredHeight: _minimumHeight
//colorGroup: PlasmaCore.Theme.ToolTipColorGroup
anchors.fill: parent
//This is the long date that appears on top of the dialog, pressing on it will set the calendar to the current day.
ColumnLayout {
anchors {
top: parent.top
left: parent.left
right: parent.right
bottom: plasmoidFooter.top
topMargin: dialogSvg.margins.top + Kirigami.Units.mediumSpacing*2
leftMargin: dialogSvg.margins.left + Kirigami.Units.mediumSpacing*2
bottomMargin: Kirigami.Units.mediumSpacing*2
rightMargin: dialogSvg.margins.right + Kirigami.Units.mediumSpacing*2
}
PlasmaExtras.Heading {
id: longDateLabel
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
/*anchors {
left: parent.left
right: parent.right
top: parent.top
topMargin: Kirigami.Units.smallSpacing*2
}*/
width: paintedWidth
horizontalAlignment: Text.AlignHCenter
text: agenda.todayDateString("dddd") + ", " + Qt.locale().standaloneMonthName(monthView.today.getMonth()) + agenda.todayDateString(" dd") + ", " + agenda.todayDateString("yyyy")
color: "#0066cc" //heading_ma.containsPress ? "#90e7ff" : (heading_ma.containsMouse ? "#b6ffff" : Kirigami.Theme.textColor)
font.underline: heading_ma.containsMouse
level: 5
MouseArea {
id: heading_ma
anchors.fill: parent
hoverEnabled: true
onClicked: monthView.resetToToday()
cursorShape: Qt.PointingHandCursor
z: 5
}
}
RowLayout {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 0
//The calendar itself, on the left side of the dialog
Item {
id: cal
Layout.preferredWidth: 168
Layout.preferredHeight: 150
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
Layout.topMargin: Kirigami.Units.largeSpacing + Kirigami.Units.mediumSpacing
CustomMonthView {
id: monthView
today: root.tzDate
showWeekNumbers: Plasmoid.configuration.showWeekNumbers
firstDayOfWeek: Plasmoid.configuration.firstDayOfWeek
anchors.fill: parent
}
}
Item {
id: testRect
visible: !calendar.showAgenda
Layout.fillWidth: true
Layout.fillHeight: true
Layout.bottomMargin: Kirigami.Units.mediumSpacing
Clock {
id: clockWidget
//anchors.fill: parent
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenterOffset: Kirigami.Units.largeSpacing
anchors.verticalCenterOffset: -Kirigami.Units.largeSpacing
width: 128
height: 128
//Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
//Layout.leftMargin: Kirigami.Units.largeSpacing
}
DropShadow {
anchors.fill: clockWidget
horizontalOffset: 2
verticalOffset: 2
radius: 3.0
color: "#10000000"
source: clockWidget
}
Text {
id: clockTime
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing*2
//anchors.bottomMargin: Kirigami.Units.mediumSpacing
horizontalAlignment: Text.AlignHCenter
text: Qt.formatTime(clockWidget.currentDate, main.use24hFormat ? "hh:mm:ss" : "h:mm:ss AP")
}
}
//This is the side panel that appears on the right of the calendar view, showing holidays, events, reminders, etc. in a list.
//Replaces the large graphical clock on the right on Windows 7's equivalent panel.
Item {
id: agenda
visible: calendar.showAgenda
Layout.fillWidth: true
Layout.fillHeight: true
Layout.leftMargin: Kirigami.Units.largeSpacing
function todayDateString(format) {
return Qt.formatDate(monthView.today, format);
}
function dateString(format) {
return Qt.formatDate(monthView.currentDate, format);
}
function formatDateWithoutYear(date) {
// Unfortunatelly Qt overrides ECMA's Date.toLocaleDateString(),
// which is able to return locale-specific date-and-month-only date
// formats, with its dumb version that only supports Qt::DateFormat
// enum subset. So to get a day-and-month-only date format string we
// must resort to this magic and hope there are no locales that use
// other separators...
var format = Qt.locale().dateFormat(Locale.ShortFormat).replace(/[./ ]*Y{2,4}[./ ]*/i, '');
return Qt.formatDate(date, format);
}
Connections {
target: monthView
function onCurrentDateChanged() {
// Apparently this is needed because this is a simple QList being
// returned and if the list for the current day has 1 event and the
// user clicks some other date which also has 1 event, QML sees the
// sizes match and does not update the labels with the content.
// Resetting the model to null first clears it and then correct data
// are displayed.
holidaysList.model = null;
holidaysList.model = monthView.daysModel.eventsForDate(monthView.currentDate);
}
}
Connections {
target: monthView.daysModel
function onAgendaUpdated(updatedDate) {
// Checks if the dates are the same, comparing the date objects
// directly won't work and this does a simple integer subtracting
// so should be fastest. One of the JS weirdness.
if (updatedDate - monthView.currentDate === 0) {
holidaysList.model = null;
holidaysList.model = monthView.daysModel.eventsForDate(monthView.currentDate);
}
}
}
Connections {
target: Plasmoid.configuration
function onEnabledCalendarPluginsChanged() {
PlasmaCalendar.EventPluginsManager.enabledPlugins = Plasmoid.configuration.enabledCalendarPlugins;
eventPluginsManager.enabledPlugins = Plasmoid.configuration.enabledCalendarPlugins;
//console.log(PlasmaCalendar.EventPluginsManager.enabledPlugins);
//console.log(eventPluginsManager.enabledPlugins);
}
}
/*Binding {
target: Plasmoid
property: "hideOnWindowDeactivate"
value: !Plasmoid.configuration.pin
}*/
TextMetrics {
id: dateLabelMetrics
// Date/time are arbitrary values with all parts being two-digit
readonly property string timeString: Qt.formatTime(new Date(2000, 12, 12, 12, 12, 12, 12))
readonly property string dateString: agenda.formatDateWithoutYear(new Date(2000, 12, 12, 12, 12, 12))
font: Kirigami.Theme.defaultFont
text: timeString.length > dateString.length ? timeString : dateString
}
PlasmaComponents3.ScrollView {
id: holidaysView
anchors {
fill: parent
topMargin: Kirigami.Units.largeSpacing
}
ListView {
id: holidaysList
spacing: Kirigami.Units.smallSpacing
highlightFollowsCurrentItem: false
highlight: Item {
opacity: 0
}
delegate: PlasmaComponents3.ItemDelegate {
id: eventItem
width: parent.width
height: eventGrid.height
property bool hasTime: {
// Explicitly all-day event
if (modelData.isAllDay) {
return false;
}
// Multi-day event which does not start or end today (so
// is all-day from today's point of view)
if (modelData.startDateTime - monthView.currentDate < 0 &&
modelData.endDateTime - monthView.currentDate > 86400000) { // 24hrs in ms
return false;
}
// Non-explicit all-day event
var startIsMidnight = modelData.startDateTime.getHours() == 0
&& modelData.startDateTime.getMinutes() == 0;
var endIsMidnight = modelData.endDateTime.getHours() == 0
&& modelData.endDateTime.getMinutes() == 0;
var sameDay = modelData.startDateTime.getDate() == modelData.endDateTime.getDate()
&& modelData.startDateTime.getDay() == modelData.endDateTime.getDay()
if (startIsMidnight && endIsMidnight && sameDay) {
return false
}
return true;
}
PlasmaCore.ToolTipArea {
//anchors.fill: parent
width: parent.width
height: eventGrid.height
active: eventTitle.truncated || eventDescription.truncated
mainText: active ? eventTitle.text : ""
subText: active ? eventDescription.text : ""
textFormat: Text.RichText
GridLayout {
id: eventGrid
columns: 3
rows: 2
rowSpacing: 0
columnSpacing: Kirigami.Units.smallSpacing
width: parent.width
Rectangle {
id: eventColor
Layout.row: 0
Layout.column: 0
Layout.rowSpan: 2
Layout.fillHeight: true
color: modelData.eventColor
width: 3
visible: modelData.eventColor !== ""
}
PlasmaComponents3.Label {
id: startTimeLabel
readonly property bool startsToday: modelData.startDateTime - monthView.currentDate >= 0
readonly property bool startedYesterdayLessThan12HoursAgo: modelData.startDateTime - monthView.currentDate >= -43200000 //12hrs in ms
Layout.row: 0
Layout.column: 1
Layout.minimumWidth: dateLabelMetrics.width
text: startsToday || startedYesterdayLessThan12HoursAgo
? Qt.formatTime(modelData.startDateTime)
: agenda.formatDateWithoutYear(modelData.startDateTime)
horizontalAlignment: Qt.AlignRight
visible: eventItem.hasTime
}
PlasmaComponents3.Label {
id: endTimeLabel
readonly property bool endsToday: modelData.endDateTime - monthView.currentDate <= 86400000 // 24hrs in ms
readonly property bool endsTomorrowInLessThan12Hours: modelData.endDateTime - monthView.currentDate <= 86400000 + 43200000 // 36hrs in ms
Layout.row: 1
Layout.column: 1
Layout.minimumWidth: dateLabelMetrics.width
text: endsToday || endsTomorrowInLessThan12Hours
? Qt.formatTime(modelData.endDateTime)
: agenda.formatDateWithoutYear(modelData.endDateTime)
horizontalAlignment: Qt.AlignRight
enabled: false
visible: eventItem.hasTime
}
PlasmaComponents3.Label {
id: eventTitle
readonly property bool wrap: eventDescription.text === ""
Layout.row: 0
Layout.rowSpan: wrap ? 2 : 1
Layout.column: 2
Layout.fillWidth: true
elide: Text.ElideRight
text: modelData.title
verticalAlignment: Text.AlignVCenter
maximumLineCount: 2
wrapMode: wrap ? Text.Wrap : Text.NoWrap
}
TextEdit {
id: descriptionHelper
visible: false
text: modelData.description
textFormat: Text.RichText
}
PlasmaComponents3.Label {
id: eventDescription
Layout.row: 1
Layout.column: 2
Layout.fillWidth: true
elide: Text.ElideRight
text: descriptionHelper.getText(0, descriptionHelper.length)
verticalAlignment: Text.AlignVCenter
enabled: false
textFormat: Text.PlainText
maximumLineCount: 1
visible: text !== ""
}
}
}
}
section.property: "eventType"
section.delegate:
PlasmaExtras.Heading {
width: holidaysList.width
bottomPadding: Kirigami.Units.smallSpacing
level: 5
elide: Text.ElideRight
text: section
font.weight: Font.Bold
}
}
}
PlasmaExtras.Heading {
anchors.fill: holidaysView
horizontalAlignment: Text.AlignHCenter
//anchors.rightMargin: Kirigami.Units.largeSpacing
text: monthView.isToday(monthView.currentDate) ? i18n("No events for today") + "\n"
: i18n("No events for this day") + "\n";
level: 5
opacity: 0.8
visible: holidaysList.count == 0
}
}
}
}
Rectangle {
id: plasmoidFooter
anchors {
bottom: parent.bottom
left: parent.left
right: parent.right
leftMargin: dialogSvg.margins.left
rightMargin: dialogSvg.margins.right
bottomMargin: dialogSvg.margins.bottom
}
//visible: container.appletHasFooter
height: 40 + Kirigami.Units.smallSpacing / 2 //+ container.footerHeight + Kirigami.Units.smallSpacing
//height: trayHeading.height + container.headingHeight + (container.headingHeight === 0 ? 0 : Kirigami.Units.smallSpacing/2)
color: "#f1f5fb"
Rectangle {
id: plasmoidFooterBorder
anchors {
top: parent.top
left: parent.left
right: parent.right
}
gradient: Gradient {
GradientStop { position: 0.0; color: "#ccd9ea" }
GradientStop { position: 1.0; color: "#f1f5fb" }
}
height: Kirigami.Units.smallSpacing
}
PlasmaExtras.Heading {
id: settingsLink
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
horizontalAlignment: Text.AlignHCenter
text: "Change date and time settings..."
color: "#0066cc" //heading_ma.containsPress ? "#90e7ff" : (heading_ma.containsMouse ? "#b6ffff" : Kirigami.Theme.textColor)
font.underline: link_ma.containsMouse
level: 5
MouseArea {
id: link_ma
anchors.fill: parent
hoverEnabled: true
onClicked: Plasmoid.internalAction("configure").trigger()
cursorShape: Qt.PointingHandCursor
z: 5
}
}
z: -9999
}
ToolButton {
id: pinButton
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.rightMargin: dialogSvg.margins.right + Kirigami.Units.mediumSpacing + 2
anchors.bottomMargin: dialogSvg.margins.bottom + Kirigami.Units.mediumSpacing + 2
width: Kirigami.Units.iconSizes.small+1;
height: Kirigami.Units.iconSizes.small;
checkable: true
checked: Plasmoid.configuration.pin
onClicked: (mouse) => {
Plasmoid.configuration.pin = !Plasmoid.configuration.pin;
}
buttonIcon: "pin"
z: 9999
}
}
Component.onCompleted: {
calendar.backgroundHints = 2; //Sets the background type to 'Solid' in order to make use of the alternative dialog style.
//The same is done to the system tray, giving the two plasmoids a consistent look and feel.
popupPosition();
//x = pos.x;
//y = pos.y;
}
}

View file

@ -0,0 +1,117 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts 1.1
import QtQuick.Window 2.15
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.plasmoid 2.0
import org.kde.ksvg 1.0 as KSvg
import org.kde.kirigami 2.5 as Kirigami // For Settings.tabletMode
Item {
id: clockItem
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
property date currentDate: {
// get the time for the given timezone from the dataengine
var now = dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["DateTime"];
// get current UTC time
var msUTC = now.getTime() + (now.getTimezoneOffset() * 60000);
// add the dataengine TZ offset to it
var currentTime = new Date(msUTC + (dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Offset"] * 1000));
return currentTime
}
KSvg.SvgItem {
id: clockface
svg: clockSvg
elementId: "clockface"
anchors.fill: parent
/*anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter*/
}
// Rects
Rectangle {
id: secondHand
color: "#bf546770"
width: 1
height: 65
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: 15
anchors.horizontalCenterOffset: 1
antialiasing: true
transform: Rotation {
origin.x: 0
origin.y: 18
angle: 360 * (currentDate.getSeconds() / 60) + 180
}
}
Rectangle {
id: minuteHand
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 0; color: "#df5c6c74" }
GradientStop { position: 0.5; color: "#ef5c6c74" }
GradientStop { position: 1; color: "#df5c6c74" }
}
radius: 1
//color: "#bf546770"
width: 2
height: 47
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: minuteHand.height/2
anchors.horizontalCenterOffset: currentDate.getMinutes() > 45 || currentDate.getMinutes() <= 15 ? 2 : 0
antialiasing: true
transform: Rotation {
origin.x: 0
origin.y: 0
angle: 360 * (currentDate.getMinutes() / 60) + 180
}
}
Rectangle {
id: hourHand
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 0; color: "#df5c6c74" }
GradientStop { position: 0.5; color: "#ef5c6c74" }
GradientStop { position: 1; color: "#df5c6c74" }
}
radius: 1
//color: "#bf546770"
width: 2
height: 36
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: hourHand.height/2
anchors.horizontalCenterOffset: 1
antialiasing: true
transform: Rotation {
origin.x: 0
origin.y: 0
angle: 360 * ((currentDate.getHours() % 12) / 12 + currentDate.getMinutes() / (12*60)) + 180
}
}
KSvg.SvgItem {
id: clockdot
svg: clockSvg
elementId: "clockdot"
width: 5
height: 5
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
KSvg.SvgItem {
id: clockshine
svg: clockSvg
elementId: "clockshine"
anchors.fill: parent
}
}

View file

@ -0,0 +1,379 @@
/*
SPDX-FileCopyrightText: 2013 Heena Mahour <heena393@gmail.com>
SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org>
SPDX-FileCopyrightText: 2015 Kai Uwe Broulik <kde@privat.broulik.de>
SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.15
import QtQuick.Layouts 1.1
import org.kde.plasma.workspace.calendar 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.kirigami as Kirigami
Item { // TODO KF6 switch to Item
id: root
//anchors.fill: parent // TODO KF6 don't use anchors
//enabled: false
/**
* Currently selected month name.
* \property string MonthView::selectedMonth
*/
property alias selectedMonth: calendarBackend.monthName
/**
* Currently selected month year.
* \property int MonthView::selectedYear
*/
property alias selectedYear: calendarBackend.year
/**
* The start day of a week.
* \property int MonthView::firstDayOfWeek
* \sa Calendar::firstDayOfWeek
*/
property alias firstDayOfWeek: calendarBackend.firstDayOfWeek
property QtObject date
property date currentDate
property date showDate: new Date()
property int borderWidth: 1
property real borderOpacity: 0.4
property int columns: calendarBackend.days
property int rows: calendarBackend.weeks
property Item selectedItem
property int week;
property int firstDay: new Date(showDate.getFullYear(), showDate.getMonth(), 1).getDay()
property alias today: calendarBackend.today
property bool showWeekNumbers: false
property bool showCustomHeader: false
/**
* SwipeView currentIndex needed for binding a TabBar to the MonthView.
*/
property int currentIndex: swipeView.currentIndex
property alias cellHeight: mainDaysCalendar.cellHeight
property QtObject daysModel: calendarBackend.daysModel
function isToday(date) {
return date.toDateString() === new Date().toDateString();
}
function eventDate(yearNumber,monthNumber,dayNumber) {
const d = new Date(yearNumber, monthNumber-1, dayNumber);
return Qt.formatDate(d, "dddd dd MMM yyyy");
}
/**
* Move calendar to month view showing today's date.
*/
function resetToToday() {
calendarBackend.resetToToday();
root.currentDate = root.today;
swipeView.currentIndex = 0;
}
function updateYearOverview() {
const date = calendarBackend.displayedDate;
const day = date.getDate();
const year = date.getFullYear();
for (let i = 0, j = monthModel.count; i < j; ++i) {
monthModel.setProperty(i, "yearNumber", year);
}
}
function updateDecadeOverview() {
const date = calendarBackend.displayedDate;
const day = date.getDate();
const month = date.getMonth() + 1;
const year = date.getFullYear();
const decade = year - year % 10;
for (let i = 0, j = yearModel.count; i < j; ++i) {
const label = decade - 1 + i;
yearModel.setProperty(i, "yearNumber", label);
yearModel.setProperty(i, "label", label);
}
}
/**
* Possible calendar views
*/
enum CalendarView {
DayView,
MonthView,
YearView
}
/**
* Go to the next month/year/decade depending on the current
* calendar view displayed.
*/
function nextView() {
if (swipeView.currentIndex === 0) {
calendarBackend.nextMonth();
} else if (swipeView.currentIndex === 1) {
calendarBackend.nextYear();
} else if (swipeView.currentIndex === 2) {
calendarBackend.nextDecade();
}
}
/**
* Go to the previous month/year/decade depending on the current
* calendar view displayed.
*/
function previousView() {
if (swipeView.currentIndex === 0) {
calendarBackend.previousMonth();
} else if (swipeView.currentIndex === 1) {
calendarBackend.previousYear();
} else if (swipeView.currentIndex === 2) {
calendarBackend.previousDecade();
}
}
/**
* \return CalendarView
*/
readonly property var calendarViewDisplayed: {
if (swipeView.currentIndex === 0) {
return MonthView.CalendarView.DayView;
} else if (swipeView.currentIndex === 1) {
return MonthView.CalendarView.MonthView;
} else if (swipeView.currentIndex === 2) {
return MonthView.CalendarView.YearView;
}
}
/**
* Show month view.
*/
function showMonthView() {
swipeView.currentIndex = 0;
}
/**
* Show year view.
*/
function showYearView() {
swipeView.currentIndex = 1;
}
/**
* Show month view.
*/
function showDecadeView() {
swipeView.currentIndex = 2;
}
//property QtObject eventPluginsManager: EventPluginsManager {}
Calendar {
id: calendarBackend
days: 7
weeks: 6
firstDayOfWeek: Qt.locale().firstDayOfWeek
today: root.today
Component.onCompleted: {
daysModel.setPluginsManager(eventPluginsManager);
}
onYearChanged: {
updateYearOverview()
updateDecadeOverview()
}
}
ListModel {
id: monthModel
Component.onCompleted: {
for (let i = 0; i < 12; ++i) {
append({
label: Qt.locale(Qt.locale().uiLanguages[0]).standaloneMonthName(i, Locale.LongFormat),
monthNumber: i + 1,
yearNumber: 2050,
isCurrent: true
})
}
updateYearOverview()
}
}
ListModel {
id: yearModel
Component.onCompleted: {
for (let i = 0; i < 12; ++i) {
append({
label: 2050, // this value will be overwritten, but it set the type of the property to int
yearNumber: 2050,
isCurrent: (i > 0 && i < 11) // first and last year are outside the decade
})
}
updateDecadeOverview()
}
}
ColumnLayout {
id: viewHeader
visible: !showCustomHeader
// Make sure the height of the invisible item is zero, otherwise anchoring to the item will
// include the height even if it is invisible.
height: !visible ? 0 : implicitHeight
width: parent.width
anchors {
top: parent.top
}
RowLayout {
spacing: 0
ToolButton {
id: previousButton
flat: true
buttonIcon: (previousButton.containsMouse && !previousButton.containsPress) ? "left-active" : "left"
onClicked: root.previousView()
Layout.leftMargin: Kirigami.Units.smallSpacing
}
PlasmaExtras.Heading {
id: heading
text: {
if(swipeView.currentIndex == 0)
return i18ndc("libplasma5", "Format: month year", "%1, %2", root.selectedMonth, root.selectedYear.toString());
else if(swipeView.currentIndex == 1)
return i18ndc("libplasma5", "Format: year", "%1", root.selectedYear.toString());
else if(swipeView.currentIndex == 2) {
var decade = root.selectedYear - root.selectedYear % 10;
var nextDecade = decade+9;
return i18ndc("libplasma5", "Format: year-year", "%1-%2", decade.toString(), nextDecade.toString());
}
}
level: 5
font.capitalization: Font.Capitalize
horizontalAlignment: Text.AlignHCenter
Layout.fillWidth: true
color: heading_ma.containsMouse && !heading_ma.containsPress ? "#0066cc" : Kirigami.Theme.textColor
MouseArea {
id: heading_ma
anchors.fill: parent
hoverEnabled: true
onClicked: if(swipeView.currentIndex != 2) swipeView.currentIndex++;
//cursorShape: Qt.PointingHandCursor
z: 5
}
}
ToolButton {
id: nextButton
flat: true
buttonIcon: (nextButton.containsMouse && !nextButton.containsPress) ? "right-active" : "right"
onClicked: root.nextView()
}
}
}
PlasmaComponents3.SwipeView {
id: swipeView
anchors {
top: viewHeader.bottom
topMargin: Kirigami.Units.mediumSpacing
left: parent.left
right: parent.right
bottom: parent.bottom
}
clip: true
onCurrentIndexChanged: if (currentIndex > 1) {
updateDecadeOverview();
}
// MonthView
DaysCalendar {
id: mainDaysCalendar
columns: calendarBackend.days
rows: calendarBackend.weeks
showWeekNumbers: root.showWeekNumbers
headerModel: calendarBackend.days
gridModel: calendarBackend.daysModel
dateMatchingPrecision: Calendar.MatchYearMonthAndDay
onActivated: (index, date) => {
const rowNumber = Math.floor(index / columns);
week = 1 + calendarBackend.weeksModel[rowNumber];
root.currentDate = new Date(date.yearNumber, date.monthNumber - 1, date.dayNumber)
}
onScrollUp: root.nextView()
onScrollDown: root.previousView()
}
// YearView
DaysCalendar {
columns: 4
rows: 3
dateMatchingPrecision: Calendar.MatchYearAndMonth
gridModel: monthModel
onActivated: (index, date, item) => {
calendarBackend.goToMonth(date.monthNumber);
swipeView.currentIndex = 0;
}
onScrollUp: calendarBackend.nextYear()
onScrollDown: calendarBackend.previousYear()
}
// DecadeView
DaysCalendar {
readonly property int decade: {
const year = calendarBackend.displayedDate.getFullYear()
return year - year % 10
}
columns: 4
rows: 3
dateMatchingPrecision: Calendar.MatchYear
gridModel: yearModel
onActivated: (index, date, item) => {
calendarBackend.goToYear(date.yearNumber);
swipeView.currentIndex = 1;
}
onScrollUp: calendarBackend.nextDecade()
onScrollDown: calendarBackend.previousDecade()
}
}
Component.onCompleted: {
root.currentDate = calendarBackend.today
}
}

View file

@ -0,0 +1,113 @@
/*
SPDX-FileCopyrightText: 2013 Heena Mahour <heena393@gmail.com>
SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org>
SPDX-FileCopyrightText: 2015 Kai Uwe Broulik <kde@privat.broulik.de>
SPDX-FileCopyrightText: 2021 Jan Blackquill <uhhadd@gmail.com>
SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.2
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.plasma.extras 2.0 as PlasmaExtras
import QtQml.Models 2.15
import Qt5Compat.GraphicalEffects
import org.kde.kirigami as Kirigami
import org.kde.ksvg as KSvg
import org.kde.plasma.workspace.calendar 2.0
PlasmaComponents3.AbstractButton {
id: dayStyle
hoverEnabled: true
property var dayModel: null
signal activated
readonly property date thisDate: new Date(yearNumber, typeof monthNumber !== "undefined" ? monthNumber - 1 : 0, typeof dayNumber !== "undefined" ? dayNumber : 1)
readonly property bool today: {
const today = root.today;
let result = true;
if (dateMatchingPrecision >= Calendar.MatchYear) {
result = result && today.getFullYear() === thisDate.getFullYear()
}
if (dateMatchingPrecision >= Calendar.MatchYearAndMonth) {
result = result && today.getMonth() === thisDate.getMonth()
}
if (dateMatchingPrecision >= Calendar.MatchYearMonthAndDay) {
result = result && today.getDate() === thisDate.getDate()
}
return result
}
readonly property bool selected: {
const current = root.currentDate;
let result = true;
if (dateMatchingPrecision >= Calendar.MatchYear) {
result = result && current.getFullYear() === thisDate.getFullYear()
}
if (dateMatchingPrecision >= Calendar.MatchYearAndMonth) {
result = result && current.getMonth() === thisDate.getMonth()
}
if (dateMatchingPrecision >= Calendar.MatchYearMonthAndDay) {
result = result && current.getDate() === thisDate.getDate()
}
return result
}
PlasmaExtras.Highlight {
id: todayRect
anchors.fill: parent
hovered: true
opacity: {
if (today && !dayStyle.hovered && !selected) {
return 0;
} else if (selected) {
return 0.8;
} else if (dayStyle.pressed) {
return 0.3;
} else if (dayStyle.hovered) {
return 0.6;
}
return 0;
}
z: -1;
}
Rectangle {
id: currentDayRect
anchors.fill: parent
visible: today
radius: 2
border.color: "#0066cc"
color: "transparent"
}
contentItem: PlasmaExtras.Heading {
id: label
horizontalAlignment: dateMatchingPrecision != Calendar.MatchYearMonthAndDay ? Text.AlignHCenter: Text.AlignRight
verticalAlignment: Text.AlignVCenter
bottomPadding: dateMatchingPrecision != Calendar.MatchYearMonthAndDay ? 0 : 1
rightPadding: dateMatchingPrecision != Calendar.MatchYearMonthAndDay ? 0 : Kirigami.Units.smallSpacing+1
wrapMode: Text.NoWrap
elide: Text.ElideRight
font.bold: calendar.showAgenda && model.eventCount !== undefined && model.eventCount > 0
fontSizeMode: Text.Fit
color: today || (!dayStyle.pressed && dayStyle.hovered) ? "#0066cc" : Kirigami.Theme.textColor
text: {
if(model.label) {
if(dateMatchingPrecision == Calendar.MatchYearAndMonth) return model.label.substring(0, 3);
return model.label;
}
return dayNumber;
}
opacity: isCurrent ? 1.0 : 0.5
level: 5
}
}

View file

@ -0,0 +1,152 @@
/*
SPDX-FileCopyrightText: 2013 Heena Mahour <heena393@gmail.com>
SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org>
SPDX-FileCopyrightText: 2015, 2016 Kai Uwe Broulik <kde@privat.broulik.de>
SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls as QQC1
import org.kde.plasma.workspace.calendar 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.ksvg as KSvg
import org.kde.kirigami as Kirigami
Item {
id: daysCalendar
signal headerClicked
signal scrollUp
signal scrollDown
signal activated(int index, var date, var item)
// so it forwards it to the delegate which then emits activated with all the necessary data
signal activateHighlightedItem
readonly property int gridColumns: showWeekNumbers ? calendarGrid.columns + 1 : calendarGrid.columns
property int rows
property int columns
property bool showWeekNumbers
// how precise date matching should be, 3 = day+month+year, 2 = month+year, 1 = just year
property int dateMatchingPrecision
property alias headerModel: days.model
property alias gridModel: repeater.model
// Take the calendar width, subtract the inner and outer spacings and divide by number of columns (==days in week)
readonly property int cellWidth: Math.floor((swipeView.width - (daysCalendar.columns + 1) * root.borderWidth) / (daysCalendar.columns + (showWeekNumbers ? 1 : 0)))
// Take the calendar height, subtract the inner spacings and divide by number of rows (root.weeks + one row for day names)
readonly property int cellHeight: Math.floor((swipeView.height - heading.height - calendarGrid.rows * root.borderWidth) / calendarGrid.rows)
KSvg.Svg {
id: calendarSvg
imagePath: "widgets/calendar"
}
Column {
id: weeksColumn
visible: showWeekNumbers
anchors {
top: parent.top
left: parent.left
bottom: parent.bottom
// The borderWidth needs to be counted twice here because it goes
// in fact through two lines - the topmost one (the outer edge)
// and then the one below weekday strings
topMargin: daysCalendar.cellHeight + root.borderWidth + root.borderWidth
}
spacing: root.borderWidth
Repeater {
model: showWeekNumbers ? calendarBackend.weeksModel : []
PlasmaComponents3.Label {
height: daysCalendar.cellHeight
width: daysCalendar.cellWidth
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
opacity: 0.4
text: modelData
font.pixelSize: Math.max(Kirigami.Theme.smallestFont.pixelSize, daysCalendar.cellHeight / 3)
}
}
}
Rectangle {
visible: days.count > 0
anchors.top: calendarGrid.top
anchors.topMargin: daysCalendar.cellHeight
height: 1
anchors.left: calendarGrid.left
anchors.right: calendarGrid.right
color: "#f5f5f5"
}
Grid {
id: calendarGrid
anchors {
top: parent.top
right: parent.right
rightMargin: root.borderWidth
bottom: parent.bottom
bottomMargin: root.borderWidth
}
columns: daysCalendar.columns
rows: daysCalendar.rows + (daysCalendar.headerModel ? 1 : 0)
spacing: 0//root.borderWidth
columnSpacing: parent.squareCell ? (daysCalendar.width - daysCalendar.columns * (daysCalendar.cellWidth - root.borderWidth)) / daysCalendar.columns : root.borderWidth
property bool containsEventItems: false // FIXME
property bool containsTodoItems: false // FIXME
Repeater {
id: days
PlasmaComponents3.Label {
width: daysCalendar.cellWidth
height: daysCalendar.cellHeight
text: (Qt.locale(Qt.locale().uiLanguages[0]).dayName(((calendarBackend.firstDayOfWeek + index) % days.count), Locale.ShortFormat)).substring(0, 2);
font.pixelSize: Math.max(Kirigami.Theme.smallestFont.pixelSize, daysCalendar.cellHeight / 3)
//opacity: 0.8
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
fontSizeMode: Text.HorizontalFit
}
}
Repeater {
id: repeater
DayDelegate {
id: delegate
width: daysCalendar.cellWidth
height: daysCalendar.cellHeight
dayModel: repeater.model
Connections {
target: daysCalendar
function onActivateHighlightedItem(delegate) {
if (delegate.containsMouse) {
delegate.clicked(null)
}
}
}
onClicked: {
daysCalendar.activated(index, model, delegate);
}
}
}
}
}

View file

@ -0,0 +1,788 @@
/*
* Copyright 2013 Heena Mahour <heena393@gmail.com>
* Copyright 2013 Sebastian Kügler <sebas@kde.org>
* Copyright 2013 Martin Klapetek <mklapetek@kde.org>
* Copyright 2014 David Edmundson <davidedmundson@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.6
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.plasmoid
import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.plasma.private.digitalclock 1.0
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.ksvg as KSvg
import org.kde.kirigami as Kirigami
Item {
id: main
property string timeFormat
property date currentTime
property bool showSeconds: Plasmoid.configuration.showSeconds
property bool showLocalTimezone: Plasmoid.configuration.showLocalTimezone
property bool showDate: Plasmoid.configuration.showDate
property int dateFormat: {
if (Plasmoid.configuration.dateFormat === "longDate") {
return Qt.SystemLocaleLongDate;
} else if (Plasmoid.configuration.dateFormat === "isoDate") {
return Qt.ISODate;
}
return Qt.SystemLocaleShortDate;
}
property string lastSelectedTimezone: Plasmoid.configuration.lastSelectedTimezone
property bool displayTimezoneAsCode: Plasmoid.configuration.displayTimezoneAsCode
property int use24hFormat: Plasmoid.configuration.use24hFormat
property string lastDate: ""
property int tzOffset
// This is the index in the list of user selected timezones
property int tzIndex: 0
// if the date/timezone cannot be fit with the smallest font to its designated space
readonly property bool oneLineMode: Plasmoid.formFactor == PlasmaCore.Types.Horizontal &&
main.height <= 2 * Kirigami.Theme.smallestFont.pixelSize &&
(main.showDate || timezoneLabel.visible)
property QtObject dashWindow: null
function getCurrentTime(): date {
const data = dataSource.data[Plasmoid.configuration.lastSelectedTimezone];
// The order of signal propagation is unspecified, so we might get
// here before the dataSource has updated. Alternatively, a buggy
// configuration view might set lastSelectedTimezone to a new time
// zone before applying the new list, or it may just be set to
// something invalid in the config file.
if (data === undefined) {
return new Date();
}
// get the time for the given time zone from the dataengine
const now = data["DateTime"];
// get current UTC time
const msUTC = now.getTime() + (now.getTimezoneOffset() * 60000);
// add the dataengine TZ offset to it
const currentTime = new Date(msUTC + (data["Offset"] * 1000));
return currentTime;
}
onDateFormatChanged: {
setupLabels();
}
onDisplayTimezoneAsCodeChanged: { setupLabels(); }
onStateChanged: { setupLabels(); }
onLastSelectedTimezoneChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) }
onShowSecondsChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) }
onShowLocalTimezoneChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) }
onShowDateChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) }
onUse24hFormatChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) }
Connections {
target: Plasmoid.configuration
function onSelectedTimeZonesChanged() {
// If the currently selected timezone was removed,
// default to the first one in the list
var lastSelectedTimezone = Plasmoid.configuration.lastSelectedTimezone;
if (Plasmoid.configuration.selectedTimeZones.indexOf(lastSelectedTimezone) == -1) {
Plasmoid.configuration.lastSelectedTimezone = Plasmoid.configuration.selectedTimeZones[0];
}
setupLabels();
setTimezoneIndex();
}
}
states: [
State {
name: "horizontalPanel"
when: Plasmoid.formFactor == PlasmaCore.Types.Horizontal && !main.oneLineMode
PropertyChanges {
target: main
Layout.fillHeight: true
Layout.fillWidth: false
Layout.minimumWidth: contentItem.width + 2
Layout.maximumWidth: Layout.minimumWidth
}
PropertyChanges {
target: contentItem
height: timeLabel.height + (main.showDate || timezoneLabel.visible ? 0.8 * timeLabel.height : 0)
width: Math.max(labelsGrid.width, timezoneLabel.paintedWidth, dateLabel.paintedWidth)
}
PropertyChanges {
target: labelsGrid
rows: main.showDate ? 1 : 2
}
AnchorChanges {
target: labelsGrid
anchors.horizontalCenter: contentItem.horizontalCenter
}
PropertyChanges {
target: timeLabel
height: sizehelper.height
//width: sizehelper.contentWidth
font.pointSize: Math.min(Plasmoid.configuration.fontSize || Kirigami.Theme.defaultFont.pointSize, Math.round(timeLabel.height * 72 / 96))
}
PropertyChanges {
target: timezoneLabel
//height: main.showDate ? 0.7 * timeLabel.height : 0.8 * timeLabel.height
//width: main.showDate ? timezoneLabel.paintedWidth : timeLabel.width
font.pointSize: Math.min(Plasmoid.configuration.fontSize || Kirigami.Theme.defaultFont.pointSize, Math.round(timezoneLabel.height * 72 / 96))
}
PropertyChanges {
target: dateLabel
height: 0.8 * timeLabel.height
width: dateLabel.paintedWidth
font.pointSize: Math.min(Plasmoid.configuration.fontSize || Kirigami.Theme.defaultFont.pointSize, Math.round(dateLabel.height * 72 / 96))
}
AnchorChanges {
target: dateLabel
anchors.top: labelsGrid.bottom
anchors.horizontalCenter: labelsGrid.horizontalCenter
}
PropertyChanges {
target: sizehelper
/*
* The value 0.71 was picked by testing to give the clock the right
* size (aligned with tray icons).
* Value 0.56 seems to be chosen rather arbitrary as well such that
* the time label is slightly larger than the date or timezone label
* and still fits well into the panel with all the applied margins.
*/
height: Math.min(main.showDate || timezoneLabel.visible ? main.height * 0.56 : main.height * 0.71,
3 * Kirigami.Theme.defaultFont.pixelSize)
font.pixelSize: sizehelper.height
}
},
State {
name: "horizontalPanelSmall"
when: Plasmoid.formFactor == PlasmaCore.Types.Horizontal && main.oneLineMode
PropertyChanges {
target: main
Layout.fillHeight: true
Layout.fillWidth: false
Layout.minimumWidth: contentItem.width
Layout.maximumWidth: Layout.minimumWidth
}
PropertyChanges {
target: contentItem
height: sizehelper.height
width: dateLabel.width + dateLabel.anchors.rightMargin + labelsGrid.width
}
AnchorChanges {
target: labelsGrid
anchors.right: contentItem.right
}
PropertyChanges {
target: dateLabel
height: timeLabel.height
width: dateLabel.paintedWidth
anchors.rightMargin: labelsGrid.columnSpacing
fontSizeMode: Text.VerticalFit
}
AnchorChanges {
target: dateLabel
anchors.right: labelsGrid.left
anchors.verticalCenter: labelsGrid.verticalCenter
}
PropertyChanges {
target: timeLabel
height: sizehelper.height
width: sizehelper.contentWidth
fontSizeMode: Text.VerticalFit
}
PropertyChanges {
target: timezoneLabel
height: 0.7 * timeLabel.height
width: timezoneLabel.paintedWidth
fontSizeMode: Text.VerticalFit
horizontalAlignment: Text.AlignHCenter
}
PropertyChanges {
target: sizehelper
height: Math.min(main.height, 3 * Kirigami.Theme.defaultFont.pixelSize)
fontSizeMode: Text.VerticalFit
font.pixelSize: 3 * Kirigami.Theme.defaultFont.pixelSize
}
},
State {
name: "verticalPanel"
when: Plasmoid.formFactor == PlasmaCore.Types.Vertical
PropertyChanges {
target: main
Layout.fillHeight: false
Layout.fillWidth: true
Layout.maximumHeight: contentItem.height
Layout.minimumHeight: Layout.maximumHeight
}
PropertyChanges {
target: contentItem
height: main.showDate ? labelsGrid.height + dateLabel.height : labelsGrid.height
width: main.width
}
PropertyChanges {
target: labelsGrid
rows: 2
}
PropertyChanges {
target: timeLabel
height: sizehelper.contentHeight
width: main.width
fontSizeMode: Text.HorizontalFit
}
PropertyChanges {
target: timezoneLabel
height: Math.max(0.7 * timeLabel.height, minimumPixelSize)
width: main.width
fontSizeMode: Text.Fit
minimumPixelSize: dateLabel.minimumPixelSize
elide: Text.ElideRight
}
PropertyChanges {
target: dateLabel
// this can be marginal bigger than contentHeight because of the horizontal fit
height: Math.max(0.8 * timeLabel.height, minimumPixelSize)
width: main.width
fontSizeMode: Text.Fit
minimumPixelSize: Math.min(0.7 * Kirigami.Theme.smallestFont.pixelSize, timeLabel.height)
elide: Text.ElideRight
}
AnchorChanges {
target: dateLabel
anchors.top: labelsGrid.bottom
anchors.horizontalCenter: labelsGrid.horizontalCenter
}
PropertyChanges {
target: sizehelper
width: main.width
fontSizeMode: Text.HorizontalFit
font.pixelSize: 3 * Kirigami.Theme.defaultFont.pixelSize
}
},
State {
name: "other"
when: Plasmoid.formFactor != PlasmaCore.Types.Vertical && Plasmoid.formFactor != PlasmaCore.Types.Horizontal
PropertyChanges {
target: main
Layout.fillHeight: false
Layout.fillWidth: false
Layout.minimumWidth: Kirigami.Units.iconSizes.small * 3
Layout.minimumHeight: Kirigami.Units.iconSizes.small * 3
}
PropertyChanges {
target: contentItem
height: main.height
width: main.width
}
PropertyChanges {
target: labelsGrid
rows: 2
}
PropertyChanges {
target: timeLabel
height: sizehelper.height
width: main.width
fontSizeMode: Text.Fit
}
PropertyChanges {
target: timezoneLabel
height: 0.7 * timeLabel.height
width: main.width
fontSizeMode: Text.Fit
minimumPixelSize: 1
}
PropertyChanges {
target: dateLabel
height: 0.8 * timeLabel.height
width: Math.max(timeLabel.contentWidth, Kirigami.Units.iconSizes.small * 3)
fontSizeMode: Text.Fit
minimumPixelSize: 1
}
AnchorChanges {
target: dateLabel
anchors.top: labelsGrid.bottom
anchors.horizontalCenter: labelsGrid.horizontalCenter
}
PropertyChanges {
target: sizehelper
height: {
if (main.showDate) {
if (timezoneLabel.visible) {
return 0.4 * main.height
}
return 0.56 * main.height
} else if (timezoneLabel.visible) {
return 0.59 * main.height
}
return main.height
}
width: main.width
fontSizeMode: Text.Fit
font.pixelSize: 1024
}
}
]
Timer {
id: tooltipTimer
interval: 750
repeat: false
running: false
onTriggered: if(!dashWindow.visible) timeToolTip.showToolTip();
}
MouseArea {
id: mouseArea
property int wheelDelta: 0
hoverEnabled: true
anchors.fill: parent
onClicked: {
Plasmoid.expanded = !Plasmoid.expanded
dashWindow.visible = !dashWindow.visible;
if(dashWindow.visible) timeToolTip.hideImmediately();
}
onEntered: {
tooltipTimer.start();
}
onExited: {
tooltipTimer.stop();
timeToolTip.hideToolTip();
}
onWheel: {
if (!Plasmoid.configuration.wheelChangesTimezone) {
return;
}
var delta = wheel.angleDelta.y || wheel.angleDelta.x
var newIndex = main.tzIndex;
wheelDelta += delta;
// magic number 120 for common "one click"
// See: http://qt-project.org/doc/qt-5/qml-qtquick-wheelevent.html#angleDelta-prop
while (wheelDelta >= 120) {
wheelDelta -= 120;
newIndex--;
}
while (wheelDelta <= -120) {
wheelDelta += 120;
newIndex++;
}
if (newIndex >= Plasmoid.configuration.selectedTimeZones.length) {
newIndex = 0;
} else if (newIndex < 0) {
newIndex = Plasmoid.configuration.selectedTimeZones.length - 1;
}
if (newIndex != main.tzIndex) {
Plasmoid.configuration.lastSelectedTimezone = Plasmoid.configuration.selectedTimeZones[newIndex];
main.tzIndex = newIndex;
dataSource.dataChanged();
setupLabels();
}
}
PlasmaCore.ToolTipArea {
id: timeToolTip
mainText: {
var now = dataSource.data[plasmoid.configuration.lastSelectedTimezone]["DateTime"];
return Qt.formatDate(now, "dddd, MMMM dd, yyyy");
}
}
}
/*
* Visible elements
*
*/
//This FrameSvgItem uses a non-standard variant of the tabbar SVG file that includes a "pressed" state
KSvg.FrameSvgItem {
id: hoverIndicator
imagePath: Qt.resolvedUrl("svgs/tabbar.svgz")
visible: mouseArea.containsMouse || dashWindow.visible
anchors.fill: parent
anchors.leftMargin: -Kirigami.Units.smallSpacing
anchors.rightMargin: -Kirigami.Units.smallSpacing+2
z: -1
prefix: mouseArea.containsPress ? "pressed-tab" : "active-tab";
}
Item {
id: contentItem
anchors.verticalCenter: main.verticalCenter
Grid {
id: labelsGrid
rows: 1
horizontalItemAlignment: Grid.AlignHCenter
verticalItemAlignment: Grid.AlignVCenter
flow: Grid.TopToBottom
columnSpacing: Kirigami.Units.smallSpacing
Rectangle {
height: 0.8 * sizehelper.height
width: 1
visible: main.showDate && main.oneLineMode
color: Kirigami.Theme.textColor
opacity: 0.4
}
PlasmaComponents3.Label {
id: timeLabel
renderType: Text.NativeRendering
font {
family: Plasmoid.configuration.fontFamily || Kirigami.Theme.defaultFont.family
weight: Plasmoid.configuration.boldText ? Font.Bold : Kirigami.Theme.defaultFont.weight
italic: Plasmoid.configuration.italicText
pointSize: Plasmoid.configuration.fontSize || Kirigami.Theme.defaultFont.pointSize
hintingPreference: Font.PreferFullHinting
}
minimumPixelSize: 1
style: Text.Outline
styleColor: "transparent"
text: {
// get the time for the given timezone from the dataengine
var now = dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["DateTime"];
// get current UTC time
var msUTC = now.getTime() + (now.getTimezoneOffset() * 60000);
// add the dataengine TZ offset to it
var currentTime = new Date(msUTC + (dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Offset"] * 1000));
main.currentTime = currentTime;
var showTimezone = main.showLocalTimezone || (plasmoid.configuration.lastSelectedTimezone != "Local"
&& dataSource.data["Local"]["Timezone City"] != dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Timezone City"]);
var timezoneString = "";
var timezoneResult = "";
if (showTimezone) {
timezoneString = Plasmoid.configuration.displayTimezoneAsCode ? dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Timezone Abbreviation"]
: TimezonesI18n.i18nCity(dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Timezone City"]);
timezoneResult = (main.showDate || main.oneLineMode) && Plasmoid.formFactor == PlasmaCore.Types.Horizontal ? timezoneString : timezoneString;
} else {
// this clears the label and that makes it hidden
timezoneResult = timezoneString;
}
return Qt.formatTime(currentTime, main.timeFormat) + (showTimezone ? (" " + timezoneResult) : "");
}
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
PlasmaComponents3.Label {
id: timezoneLabel
renderType: Text.NativeRendering
font.weight: timeLabel.font.weight
font.italic: timeLabel.font.italic
font.pixelSize: timeLabel.font.pixelSize
font.hintingPreference: Font.PreferFullHinting
minimumPixelSize: 1
style: Text.Outline
styleColor: "transparent"
visible: false
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
PlasmaComponents3.Label {
id: dateLabel
visible: main.showDate
renderType: Text.NativeRendering
font.family: timeLabel.font.family
font.weight: timeLabel.font.weight
font.italic: timeLabel.font.italic
font.pixelSize: timeLabel.font.pixelSize
font.hintingPreference: Font.PreferFullHinting
minimumPixelSize: 1
style: Text.Outline
styleColor: "transparent"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
/*
* end: Visible Elements
*
*/
PlasmaComponents3.Label {
id: sizehelper
font.family: timeLabel.font.family
font.weight: timeLabel.font.weight
font.italic: timeLabel.font.italic
minimumPixelSize: 1
visible: false
}
FontMetrics {
id: timeMetrics
font.family: timeLabel.font.family
font.weight: timeLabel.font.weight
font.italic: timeLabel.font.italic
}
// Qt's QLocale does not offer any modular time creating like Klocale did
// eg. no "gimme time with seconds" or "gimme time without seconds and with timezone".
// QLocale supports only two formats - Long and Short. Long is unusable in many situations
// and Short does not provide seconds. So if seconds are enabled, we need to add it here.
//
// What happens here is that it looks for the delimiter between "h" and "m", takes it
// and appends it after "mm" and then appends "ss" for the seconds.
function timeFormatCorrection(timeFormatString) {
var regexp = /(hh*)(.+)(mm)/i
var match = regexp.exec(timeFormatString);
var hours = match[1];
var delimiter = match[2];
var minutes = match[3]
var seconds = "ss";
var amPm = "AP";
var uses24hFormatByDefault = timeFormatString.toLowerCase().indexOf("ap") == -1;
// because QLocale is incredibly stupid and does not convert 12h/24h clock format
// when uppercase H is used for hours, needs to be h or hh, so toLowerCase()
var result = hours.toLowerCase() + delimiter + minutes;
if (main.showSeconds) {
result += delimiter + seconds;
}
// add "AM/PM" either if the setting is the default and locale uses it OR if the user unchecked "use 24h format"
if ((main.use24hFormat == Qt.PartiallyChecked && !uses24hFormatByDefault) || main.use24hFormat == Qt.Unchecked) {
result += " " + amPm;
}
main.timeFormat = result;
setupLabels();
}
function setupLabels() {
/*var showTimezone = main.showLocalTimezone || (plasmoid.configuration.lastSelectedTimezone != "Local"
&& dataSource.data["Local"]["Timezone City"] != dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Timezone City"]);
var timezoneString = "";
if (showTimezone) {
timezoneString = Plasmoid.configuration.displayTimezoneAsCode ? dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Timezone Abbreviation"]
: TimezonesI18n.i18nCity(dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Timezone City"]);
timezoneLabel.text = (main.showDate || main.oneLineMode) && Plasmoid.formFactor == PlasmaCore.Types.Horizontal ? "(" + timezoneString + ")" : timezoneString;
} else {
// this clears the label and that makes it hidden
timezoneLabel.text = timezoneString;
}*/
if (main.showDate) {
dateLabel.text = Qt.formatDate(main.currentTime, main.dateFormat);
} else {
// clear it so it doesn't take space in the layout
dateLabel.text = "";
}
// find widest character between 0 and 9
var maximumWidthNumber = 0;
var maximumAdvanceWidth = 0;
for (var i = 0; i <= 9; i++) {
var advanceWidth = timeMetrics.advanceWidth(i);
if (advanceWidth > maximumAdvanceWidth) {
maximumAdvanceWidth = advanceWidth;
maximumWidthNumber = i;
}
}
// replace all placeholders with the widest number (two digits)
var format = main.timeFormat.replace(/(h+|m+|s+)/g, "" + maximumWidthNumber + maximumWidthNumber); // make sure maximumWidthNumber is formatted as string
// build the time string twice, once with an AM time and once with a PM time
var date = new Date(2000, 0, 1, 1, 0, 0);
var timeAm = Qt.formatTime(date, format);
var advanceWidthAm = timeMetrics.advanceWidth(timeAm);
date.setHours(13);
var timePm = Qt.formatTime(date, format);
var advanceWidthPm = timeMetrics.advanceWidth(timePm);
// set the sizehelper's text to the widest time string
if (advanceWidthAm > advanceWidthPm) {
sizehelper.text = timeAm;
} else {
sizehelper.text = timePm;
}
}
function dateTimeChanged()
{
var doCorrections = false;
if (main.showDate) {
// If the date has changed, force size recalculation, because the day name
// or the month name can now be longer/shorter, so we need to adjust applet size
var currentDate = Qt.formatDateTime(getCurrentTime(), "yyyy-mm-dd");
if (main.lastDate != currentDate) {
doCorrections = true;
main.lastDate = currentDate
}
}
var currentTZOffset = dataSource.data["Local"]["Offset"] / 60;
if (currentTZOffset != tzOffset) {
doCorrections = true;
tzOffset = currentTZOffset;
Date.timeZoneUpdated(); // inform the QML JS engine about TZ change
}
if (doCorrections) {
timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat));
}
}
function setTimezoneIndex() {
for (var i = 0; i < Plasmoid.configuration.selectedTimeZones.length; i++) {
if (Plasmoid.configuration.selectedTimeZones[i] == Plasmoid.configuration.lastSelectedTimezone) {
main.tzIndex = i;
break;
}
}
}
Component.onCompleted: {
root.initTimezones();
// Sort the timezones according to their offset
// Calling sort() directly on plasmoid.configuration.selectedTimeZones
// has no effect, so sort a copy and then assign the copy to it
var sortArray = Plasmoid.configuration.selectedTimeZones;
sortArray.sort(function(a, b) {
return dataSource.data[a]["Offset"] - dataSource.data[b]["Offset"];
});
Plasmoid.configuration.selectedTimeZones = sortArray;
setTimezoneIndex();
tzOffset = -(new Date().getTimezoneOffset());
dateTimeChanged();
timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat));
dataSource.onDataChanged.connect(dateTimeChanged);
dashWindow = Qt.createQmlObject("CalendarView {}", root);
}
}

View file

@ -0,0 +1,802 @@
/*
SPDX-FileCopyrightText: 2013 Heena Mahour <heena393@gmail.com>
SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org>
SPDX-FileCopyrightText: 2013 Martin Klapetek <mklapetek@kde.org>
SPDX-FileCopyrightText: 2014 David Edmundson <davidedmundson@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components 3.0 as Components
import org.kde.plasma.private.digitalclock 1.0
import org.kde.kirigami 2.20 as Kirigami
import org.kde.ksvg as KSvg
MouseArea {
id: main
objectName: "digital-clock-compactrepresentation"
hoverEnabled: true
property QtObject dashWindow: null
onClicked: {
Plasmoid.expanded = !Plasmoid.expanded
dashWindow.visible = !dashWindow.visible;
}
onEntered: {
tooltipTimer.start();
}
onExited: {
tooltipTimer.stop();
timeToolTip.hideToolTip();
}
Timer {
id: tooltipTimer
interval: 750
repeat: false
running: false
onTriggered: if(!dashWindow.visible) timeToolTip.showToolTip();
}
PlasmaCore.ToolTipArea {
id: timeToolTip
mainText: {
var now = dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["DateTime"];
return Qt.formatDate(now, "dddd, MMMM dd, yyyy");
}
/*mainItem: PlasmaExtras.Heading {
* level: 5
* elide: Text.ElideRight
* wrapMode: Text.Wrap
* text: {
* var now = dataSource.data[plasmoid.configuration.lastSelectedTimezone]["DateTime"];
* return Qt.formatDate(now, "dddd, MMMM yyyy");
}
textFormat: Text.PlainText
}*/
}
property string timeFormat
property string timeFormatWithSeconds
property bool showLocalTimezone: Plasmoid.configuration.showLocalTimezone
property bool showDate: Plasmoid.configuration.showDate
// This is quite convoluted in Qt 6:
// Qt.formatDate with locale only accepts Locale.FormatType as format type,
// no Qt.DateFormat (ISODate) and no format string.
// Locale.toString on the other hand only formats a date *with* time...
property var dateFormatter: {
if (Plasmoid.configuration.dateFormat === "custom") {
Plasmoid.configuration.customDateFormat; // create a binding dependency on this property.
return (d) => {
return Qt.locale().toString(d, Plasmoid.configuration.customDateFormat);
};
} else if (Plasmoid.configuration.dateFormat === "isoDate") {
return (d) => {
return Qt.formatDate(d, Qt.ISODate);
};
} else if (Plasmoid.configuration.dateFormat === "longDate") {
return (d) => {
return Qt.formatDate(d, Qt.locale(), Locale.LongFormat);
};
} else {
return (d) => {
return Qt.formatDate(d, Qt.locale(), Locale.ShortFormat);
};
}
}
property string lastSelectedTimezone: Plasmoid.configuration.lastSelectedTimezone
property int displayTimezoneFormat: Plasmoid.configuration.displayTimezoneFormat
property int use24hFormat: Plasmoid.configuration.use24hFormat
property string lastDate: ""
property int tzOffset
// This is the index in the list of user selected timezones
property int tzIndex: 0
// if showing the date and the time in one line or
// if the date/timezone cannot be fit with the smallest font to its designated space
property bool oneLineMode: {
if (Plasmoid.configuration.dateDisplayFormat === 1) {
// BesideTime
return true;
} else if (Plasmoid.configuration.dateDisplayFormat === 2) {
// BelowTime
return false;
} else {
// Adaptive
return Plasmoid.formFactor === PlasmaCore.Types.Horizontal &&
main.height <= 2 * Kirigami.Theme.smallFont.pixelSize &&
(main.showDate || timezoneLabel.visible);
}
}
property bool wasExpanded
property int wheelDelta: 0
Accessible.role: Accessible.Button
Accessible.onPressAction: main.clicked(null)
onDateFormatterChanged: {
setupLabels();
}
onDisplayTimezoneFormatChanged: { setupLabels(); }
onStateChanged: { setupLabels(); }
onLastSelectedTimezoneChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) }
onShowLocalTimezoneChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) }
onShowDateChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) }
onUse24hFormatChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) }
Connections {
target: Plasmoid
function onContextualActionsAboutToShow() {
ClipboardMenu.secondsIncluded = (Plasmoid.configuration.showSeconds === 2);
ClipboardMenu.currentDate = main.getCurrentTime();
}
}
Connections {
target: Plasmoid.configuration
function onSelectedTimeZonesChanged() {
// If the currently selected timezone was removed,
// default to the first one in the list
const lastSelectedTimezone = Plasmoid.configuration.lastSelectedTimezone;
if (Plasmoid.configuration.selectedTimeZones.indexOf(lastSelectedTimezone) === -1) {
Plasmoid.configuration.lastSelectedTimezone = Plasmoid.configuration.selectedTimeZones[0];
}
setupLabels();
setTimezoneIndex();
}
}
function getCurrentTime() {
// get the time for the given timezone from the dataengine
var now = dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["DateTime"];
// get current UTC time
var msUTC = now.getTime() + (now.getTimezoneOffset() * 60000);
// add the dataengine TZ offset to it
var currentTime = new Date(msUTC + (dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Offset"] * 1000));
return currentTime;
}
function pointToPixel(pointSize) {
var pixelsPerInch = Screen.pixelDensity * 25.4
return Math.round(pointSize / 72 * pixelsPerInch)
}
states: [
State {
name: "horizontalPanel"
when: Plasmoid.formFactor === PlasmaCore.Types.Horizontal && !main.oneLineMode
PropertyChanges {
target: main
Layout.fillHeight: true
Layout.fillWidth: false
Layout.minimumWidth: contentItem.width
Layout.maximumWidth: Layout.minimumWidth
}
PropertyChanges {
target: contentItem
height: timeLabel.height + (main.showDate || timezoneLabel.visible ? 0.8 * timeLabel.height : 0)
width: Math.max(timeLabel.width + (main.showDate ? timezoneLabel.paintedWidth : 0),
timezoneLabel.paintedWidth, dateLabel.paintedWidth) + Kirigami.Units.largeSpacing
}
PropertyChanges {
target: labelsGrid
rows: main.showDate ? 1 : 2
}
AnchorChanges {
target: labelsGrid
anchors.horizontalCenter: contentItem.horizontalCenter
}
PropertyChanges {
target: timeLabel
height: sizehelper.height
width: timeLabel.paintedWidth
font.pixelSize: timeLabel.height
}
PropertyChanges {
target: timezoneLabel
height: main.showDate ? 0.7 * timeLabel.height : 0.8 * timeLabel.height
width: main.showDate ? timezoneLabel.paintedWidth : timeLabel.width
font.pixelSize: timezoneLabel.height
}
PropertyChanges {
target: dateLabel
height: 0.8 * timeLabel.height
width: dateLabel.paintedWidth
verticalAlignment: Text.AlignVCenter
font.pixelSize: dateLabel.height
}
AnchorChanges {
target: dateLabel
anchors.top: labelsGrid.bottom
anchors.horizontalCenter: labelsGrid.horizontalCenter
}
PropertyChanges {
target: sizehelper
/*
* The value 0.71 was picked by testing to give the clock the right
* size (aligned with tray icons).
* Value 0.56 seems to be chosen rather arbitrary as well such that
* the time label is slightly larger than the date or timezone label
* and still fits well into the panel with all the applied margins.
*/
height: Math.min(main.showDate || timezoneLabel.visible ? main.height * 0.56 : main.height * 0.71,
fontHelper.font.pixelSize)
font.pixelSize: sizehelper.height
}
},
State {
name: "oneLineDate"
// the one-line mode has no effect on a vertical panel because it would never fit
when: Plasmoid.formFactor !== PlasmaCore.Types.Vertical && main.oneLineMode
PropertyChanges {
target: main
Layout.fillHeight: true
Layout.fillWidth: false
Layout.minimumWidth: contentItem.width
Layout.maximumWidth: Layout.minimumWidth
}
PropertyChanges {
target: contentItem
height: sizehelper.height
width: dateLabel.width + dateLabel.anchors.rightMargin + labelsGrid.width
}
AnchorChanges {
target: labelsGrid
anchors.right: contentItem.right
}
PropertyChanges {
target: dateLabel
height: timeLabel.height
width: dateLabel.paintedWidth
font.pixelSize: 1024
verticalAlignment: Text.AlignVCenter
anchors.rightMargin: labelsGrid.columnSpacing
fontSizeMode: Text.VerticalFit
}
AnchorChanges {
target: dateLabel
anchors.right: labelsGrid.left
anchors.verticalCenter: labelsGrid.verticalCenter
}
PropertyChanges {
target: timeLabel
height: sizehelper.height
width: timeLabel.paintedWidth
fontSizeMode: Text.VerticalFit
}
PropertyChanges {
target: timezoneLabel
height: 0.7 * timeLabel.height
width: timezoneLabel.paintedWidth
fontSizeMode: Text.VerticalFit
horizontalAlignment: Text.AlignHCenter
}
PropertyChanges {
target: sizehelper
height: Math.min(main.height, fontHelper.contentHeight)
fontSizeMode: Text.VerticalFit
font.pixelSize: fontHelper.font.pixelSize
}
},
State {
name: "verticalPanel"
when: Plasmoid.formFactor === PlasmaCore.Types.Vertical
PropertyChanges {
target: main
Layout.fillHeight: false
Layout.fillWidth: true
Layout.maximumHeight: contentItem.height
Layout.minimumHeight: Layout.maximumHeight
}
PropertyChanges {
target: contentItem
height: main.showDate ? labelsGrid.height + dateLabel.contentHeight : labelsGrid.height
width: main.width
}
PropertyChanges {
target: labelsGrid
rows: 2
}
PropertyChanges {
target: timeLabel
height: sizehelper.contentHeight
width: main.width
font.pixelSize: Math.min(timeLabel.height, fontHelper.font.pixelSize)
fontSizeMode: Text.VerticalFit
}
PropertyChanges {
target: timezoneLabel
height: Math.max(0.7 * timeLabel.height, minimumPixelSize)
width: main.width
fontSizeMode: Text.Fit
minimumPixelSize: dateLabel.minimumPixelSize
elide: Text.ElideRight
}
PropertyChanges {
target: dateLabel
width: main.width
//NOTE: in order for Text.Fit to work as intended, the actual height needs to be quite big, in order for the font to enlarge as much it needs for the available width, and then request a sensible height, for which contentHeight will need to be considered as opposed to height
height: Kirigami.Units.iconSizes.small * 10
fontSizeMode: Text.Fit
verticalAlignment: Text.AlignTop
// Those magic numbers are purely what looks nice as maximum size, here we have it the smallest
// between slightly bigger than the default font (1.4 times) and a bit smaller than the time font
font.pixelSize: Math.min(0.7 * timeLabel.height, Kirigami.Theme.defaultFont.pixelSize * 1.4)
elide: Text.ElideRight
wrapMode: Text.WordWrap
}
AnchorChanges {
target: dateLabel
anchors.top: labelsGrid.bottom
anchors.horizontalCenter: labelsGrid.horizontalCenter
}
PropertyChanges {
target: sizehelper
width: main.width
fontSizeMode: Text.HorizontalFit
font.pixelSize: fontHelper.font.pixelSize
}
},
State {
name: "other"
when: Plasmoid.formFactor !== PlasmaCore.Types.Vertical && Plasmoid.formFactor !== PlasmaCore.Types.Horizontal
PropertyChanges {
target: main
Layout.fillHeight: false
Layout.fillWidth: false
Layout.minimumWidth: Kirigami.Units.iconSizes.small * 3
Layout.minimumHeight: Kirigami.Units.iconSizes.small * 3
}
PropertyChanges {
target: contentItem
height: main.height
width: main.width
}
PropertyChanges {
target: labelsGrid
rows: 2
}
PropertyChanges {
target: timeLabel
height: sizehelper.height
width: main.width
fontSizeMode: Text.Fit
}
PropertyChanges {
target: timezoneLabel
height: 0.7 * timeLabel.height
width: main.width
fontSizeMode: Text.Fit
minimumPixelSize: 1
}
PropertyChanges {
target: dateLabel
height: 0.7 * timeLabel.height
font.pixelSize: 1024
width: Math.max(timeLabel.contentWidth, Kirigami.Units.iconSizes.small * 3)
verticalAlignment: Text.AlignVCenter
fontSizeMode: Text.Fit
minimumPixelSize: 1
wrapMode: Text.WordWrap
}
AnchorChanges {
target: dateLabel
anchors.top: labelsGrid.bottom
anchors.horizontalCenter: labelsGrid.horizontalCenter
}
PropertyChanges {
target: sizehelper
height: {
if (main.showDate) {
if (timezoneLabel.visible) {
return 0.4 * main.height
}
return 0.56 * main.height
} else if (timezoneLabel.visible) {
return 0.59 * main.height
}
return main.height
}
width: main.width
fontSizeMode: Text.Fit
font.pixelSize: 1024
}
}
]
//onPressed: wasExpanded = root.expanded
//onClicked: root.expanded = !wasExpanded
onWheel: wheel => {
if (!Plasmoid.configuration.wheelChangesTimezone) {
return;
}
var delta = (wheel.inverted ? -1 : 1) * (wheel.angleDelta.y ? wheel.angleDelta.y : wheel.angleDelta.x);
var newIndex = main.tzIndex;
wheelDelta += delta;
// magic number 120 for common "one click"
// See: https://doc.qt.io/qt-5/qml-qtquick-wheelevent.html#angleDelta-prop
while (wheelDelta >= 120) {
wheelDelta -= 120;
newIndex--;
}
while (wheelDelta <= -120) {
wheelDelta += 120;
newIndex++;
}
if (newIndex >= Plasmoid.configuration.selectedTimeZones.length) {
newIndex = 0;
} else if (newIndex < 0) {
newIndex = Plasmoid.configuration.selectedTimeZones.length - 1;
}
if (newIndex !== main.tzIndex) {
Plasmoid.configuration.lastSelectedTimezone = Plasmoid.configuration.selectedTimeZones[newIndex];
main.tzIndex = newIndex;
dataSource.dataChanged();
setupLabels();
}
}
/*
* Visible elements
*
*/
KSvg.FrameSvgItem {
id: hoverIndicator
imagePath: Qt.resolvedUrl("svgs/tabbar.svgz")
visible: main.containsMouse || dashWindow.visible
anchors.fill: parent
anchors.leftMargin: main.showSeconds ? 0 : -Kirigami.Units.smallSpacing //To compensate for the shorter width of the clock when seconds are disabled
anchors.rightMargin:main.showSeconds ? 0 : -Kirigami.Units.smallSpacing
z: -1
prefix: main.containsPress ? "pressed-tab" : "active-tab";
}
Item {
id: contentItem
anchors.verticalCenter: main.verticalCenter
Grid {
id: labelsGrid
rows: 1
horizontalItemAlignment: Grid.AlignHCenter
verticalItemAlignment: Grid.AlignVCenter
flow: Grid.TopToBottom
columnSpacing: Kirigami.Units.smallSpacing
Components.Label {
id: timeLabel
font {
family: fontHelper.font.family
weight: fontHelper.font.weight
italic: fontHelper.font.italic
pixelSize: 1024
pointSize: -1 // Because we're setting the pixel size instead
// TODO: remove once this label is ported to PC3
}
minimumPixelSize: 1
text: Qt.formatTime(main.getCurrentTime(), Plasmoid.configuration.showSeconds === 2 ? main.timeFormatWithSeconds : main.timeFormat)
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
Components.Label {
id: timezoneLabel
font.weight: timeLabel.font.weight
font.italic: timeLabel.font.italic
font.pixelSize: 1024
font.pointSize: -1 // Because we're setting the pixel size instead
// TODO: remove once this label is ported to PC3
minimumPixelSize: 1
visible: text.length > 0
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
Components.Label {
id: dateLabel
visible: main.showDate
font.family: timeLabel.font.family
font.weight: timeLabel.font.weight
font.italic: timeLabel.font.italic
font.pixelSize: 1024
font.pointSize: -1 // Because we're setting the pixel size instead
// TODO: remove once this label is ported to PC3
minimumPixelSize: 1
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
/*
* end: Visible Elements
*
*/
Components.Label {
id: sizehelper
font.family: timeLabel.font.family
font.weight: timeLabel.font.weight
font.italic: timeLabel.font.italic
minimumPixelSize: 1
visible: false
}
// To measure Label.height for maximum-sized font in VerticalFit mode
Components.Label {
id: fontHelper
height: 1024
font.family: (Plasmoid.configuration.autoFontAndSize || Plasmoid.configuration.fontFamily.length === 0) ? Kirigami.Theme.defaultFont.family : Plasmoid.configuration.fontFamily
font.weight: Plasmoid.configuration.autoFontAndSize ? Kirigami.Theme.defaultFont.weight : Plasmoid.configuration.fontWeight
font.italic: Plasmoid.configuration.autoFontAndSize ? Kirigami.Theme.defaultFont.italic : Plasmoid.configuration.italicText
font.pixelSize: Plasmoid.configuration.autoFontAndSize ? 3 * Kirigami.Theme.defaultFont.pixelSize : pointToPixel(Plasmoid.configuration.fontSize)
font.pointSize: -1
fontSizeMode: Text.VerticalFit
visible: false
}
FontMetrics {
id: timeMetrics
font.family: timeLabel.font.family
font.weight: timeLabel.font.weight
font.italic: timeLabel.font.italic
}
// Qt's QLocale does not offer any modular time creating like Klocale did
// eg. no "gimme time with seconds" or "gimme time without seconds and with timezone".
// QLocale supports only two formats - Long and Short. Long is unusable in many situations
// and Short does not provide seconds. So if seconds are enabled, we need to add it here.
//
// What happens here is that it looks for the delimiter between "h" and "m", takes it
// and appends it after "mm" and then appends "ss" for the seconds.
function timeFormatCorrection(timeFormatString) {
const regexp = /(hh*)(.+)(mm)/i
const match = regexp.exec(timeFormatString);
const hours = match[1];
const delimiter = match[2];
const minutes = match[3]
const seconds = "ss";
const amPm = "AP";
const uses24hFormatByDefault = timeFormatString.toLowerCase().indexOf("ap") === -1;
// because QLocale is incredibly stupid and does not convert 12h/24h clock format
// when uppercase H is used for hours, needs to be h or hh, so toLowerCase()
let result = hours.toLowerCase() + delimiter + minutes;
let result_sec = result + delimiter + seconds;
// add "AM/PM" either if the setting is the default and locale uses it OR if the user unchecked "use 24h format"
if ((main.use24hFormat == Qt.PartiallyChecked && !uses24hFormatByDefault) || main.use24hFormat == Qt.Unchecked) {
result += " " + amPm;
result_sec += " " + amPm;
}
main.timeFormat = result;
main.timeFormatWithSeconds = result_sec;
setupLabels();
}
function setupLabels() {
const showTimezone = main.showLocalTimezone || (Plasmoid.configuration.lastSelectedTimezone !== "Local"
&& dataSource.data["Local"]["Timezone City"] !== dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Timezone City"]);
let timezoneString = "";
if (showTimezone) {
// format timezone as tz code, city or UTC offset
if (displayTimezoneFormat === 0) {
timezoneString = dataSource.data[lastSelectedTimezone]["Timezone Abbreviation"]
} else if (displayTimezoneFormat === 1) {
timezoneString = TimezonesI18n.i18nCity(dataSource.data[lastSelectedTimezone]["Timezone"]);
} else if (displayTimezoneFormat === 2) {
const lastOffset = dataSource.data[lastSelectedTimezone]["Offset"];
const symbol = lastOffset > 0 ? '+' : '';
const hours = Math.floor(lastOffset / 3600);
const minutes = Math.floor(lastOffset % 3600 / 60);
timezoneString = "UTC" + symbol + hours.toString().padStart(2, '0') + ":" + minutes.toString().padStart(2, '0');
}
timezoneLabel.text = (main.showDate || main.oneLineMode) && Plasmoid.formFactor === PlasmaCore.Types.Horizontal ? "(" + timezoneString + ")" : timezoneString;
} else {
// this clears the label and that makes it hidden
timezoneLabel.text = timezoneString;
}
if (main.showDate) {
dateLabel.text = main.dateFormatter(main.getCurrentTime());
} else {
// clear it so it doesn't take space in the layout
dateLabel.text = "";
}
// find widest character between 0 and 9
let maximumWidthNumber = 0;
let maximumAdvanceWidth = 0;
for (let i = 0; i <= 9; i++) {
const advanceWidth = timeMetrics.advanceWidth(i);
if (advanceWidth > maximumAdvanceWidth) {
maximumAdvanceWidth = advanceWidth;
maximumWidthNumber = i;
}
}
// replace all placeholders with the widest number (two digits)
const format = main.timeFormat.replace(/(h+|m+|s+)/g, "" + maximumWidthNumber + maximumWidthNumber); // make sure maximumWidthNumber is formatted as string
// build the time string twice, once with an AM time and once with a PM time
const date = new Date(2000, 0, 1, 1, 0, 0);
const timeAm = Qt.formatTime(date, format);
const advanceWidthAm = timeMetrics.advanceWidth(timeAm);
date.setHours(13);
const timePm = Qt.formatTime(date, format);
const advanceWidthPm = timeMetrics.advanceWidth(timePm);
// set the sizehelper's text to the widest time string
if (advanceWidthAm > advanceWidthPm) {
sizehelper.text = timeAm;
} else {
sizehelper.text = timePm;
}
fontHelper.text = sizehelper.text
}
function dateTimeChanged() {
let doCorrections = false;
if (main.showDate) {
// If the date has changed, force size recalculation, because the day name
// or the month name can now be longer/shorter, so we need to adjust applet size
const currentDate = Qt.formatDateTime(main.getCurrentTime(), "yyyy-MM-dd");
if (main.lastDate !== currentDate) {
doCorrections = true;
main.lastDate = currentDate
}
}
const currentTZOffset = dataSource.data["Local"]["Offset"] / 60;
if (currentTZOffset !== tzOffset) {
doCorrections = true;
tzOffset = currentTZOffset;
Date.timeZoneUpdated(); // inform the QML JS engine about TZ change
}
if (doCorrections) {
timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat));
}
}
function setTimezoneIndex() {
main.tzIndex = Plasmoid.configuration.selectedTimeZones.indexOf(Plasmoid.configuration.lastSelectedTimezone);
}
Component.onCompleted: {
// Sort the timezones according to their offset
// Calling sort() directly on Plasmoid.configuration.selectedTimeZones
// has no effect, so sort a copy and then assign the copy to it
const sortedTimeZones = Plasmoid.configuration.selectedTimeZones;
const byOffset = (a, b) => dataSource.data[a]["Offset"] - dataSource.data[b]["Offset"];
sortedTimeZones.sort(byOffset);
Plasmoid.configuration.selectedTimeZones = sortedTimeZones;
setTimezoneIndex();
tzOffset = -(new Date().getTimezoneOffset());
dateTimeChanged();
timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat));
dataSource.onDataChanged.connect(dateTimeChanged);
dashWindow = Qt.createQmlObject("CalendarView {}", root);
}
}

View file

@ -0,0 +1,20 @@
/*
* Copyright 2013 Sebastian Kügler <sebas@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.0
import org.kde.plasma.calendar 2.0 as PlasmaCalendar
PlasmaCalendar.MonthMenu { }

View file

@ -0,0 +1,58 @@
/*import QtQuick 2.6
import QtQuick.Layouts 1.1
import QtGraphicalEffects 1.0
import QtQml.Models 2.2
import org.kde.plasma.core 2.0 as PlasmaCore
// for Highlight
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons
*/
import QtQuick 2.5
import QtQuick.Layouts 1.1
import QtQuick.Window 2.15
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.plasmoid 2.0
import org.kde.ksvg 1.0 as KSvg
import org.kde.kirigami 2.5 as Kirigami // For Settings.tabletMode
MouseArea {
id: toolButton
Layout.maximumWidth: Kirigami.Units.iconSizes.small+1;
Layout.maximumHeight: Kirigami.Units.iconSizes.small;
Layout.preferredWidth: Kirigami.Units.iconSizes.small+1;
Layout.preferredHeight: Kirigami.Units.iconSizes.small;
//signal clicked
property string buttonIcon: ""
property bool checkable: false
property bool checked: false
property bool flat: false
hoverEnabled: true
KSvg.FrameSvgItem {
id: normalButton
imagePath: Qt.resolvedUrl("svgs/button.svgz")
anchors.fill: parent
prefix: {
if(parent.containsPress || (checkable && checked)) return "toolbutton-pressed";
else return "toolbutton-hover";
}
visible: (parent.containsMouse || (checkable && checked)) && !flat
}
KSvg.SvgItem {
id: buttonIconSvg
svg: buttonIcons
elementId: buttonIcon
width: 10;
height: 10;
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}

View file

@ -0,0 +1,145 @@
/*
* Copyright 2015 by Martin Klapetek <mklapetek@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA.
*/
import QtQuick 2.0
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.private.digitalclock 1.0
Item {
id: tooltipContentItem
property int preferredTextWidth: units.gridUnit * 20
width: childrenRect.width + units.gridUnit
height: childrenRect.height + units.gridUnit
LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
LayoutMirroring.childrenInherit: true
function timeForZone(zone) {
var compactRepresentationItem = plasmoid.compactRepresentationItem;
if (!compactRepresentationItem) {
return "";
}
// get the time for the given timezone from the dataengine
var now = dataSource.data[zone]["DateTime"];
// get current UTC time
var msUTC = now.getTime() + (now.getTimezoneOffset() * 60000);
// add the dataengine TZ offset to it
var dateTime = new Date(msUTC + (dataSource.data[zone]["Offset"] * 1000));
var formattedTime = Qt.formatTime(dateTime, compactRepresentationItem.timeFormat);
if (dateTime.getDay() != dataSource.data["Local"]["DateTime"].getDay()) {
formattedTime += " (" + Qt.formatDate(dateTime, compactRepresentationItem.dateFormat) + ")";
}
return formattedTime;
}
function nameForZone(zone) {
// add the timezone string to the clock
var timezoneString = plasmoid.configuration.displayTimezoneAsCode ? dataSource.data[zone]["Timezone Abbreviation"]
: TimezonesI18n.i18nCity(dataSource.data[zone]["Timezone City"]);
return timezoneString;
}
RowLayout {
anchors {
left: parent.left
top: parent.top
margins: units.gridUnit / 2
}
spacing: units.largeSpacing
PlasmaCore.IconItem {
id: tooltipIcon
source: "preferences-system-time"
Layout.alignment: Qt.AlignTop
visible: true
implicitWidth: units.iconSizes.medium
Layout.preferredWidth: implicitWidth
Layout.preferredHeight: implicitWidth
}
ColumnLayout {
PlasmaExtras.Heading {
id: tooltipMaintext
level: 3
Layout.minimumWidth: Math.min(implicitWidth, preferredTextWidth)
Layout.maximumWidth: preferredTextWidth
elide: Text.ElideRight
text: Qt.formatDate(tzDate,"dddd")
}
PlasmaComponents.Label {
id: tooltipSubtext
Layout.minimumWidth: Math.min(implicitWidth, preferredTextWidth)
Layout.maximumWidth: preferredTextWidth
text: Qt.formatDate(tzDate, dateFormatString)
opacity: 0.6
}
GridLayout {
Layout.minimumWidth: Math.min(implicitWidth, preferredTextWidth)
Layout.maximumWidth: preferredTextWidth
Layout.maximumHeight: childrenRect.height
columns: 2
visible: plasmoid.configuration.selectedTimeZones.length > 1
Repeater {
model: {
// The timezones need to be duplicated in the array
// because we need their data twice - once for the name
// and once for the time and the Repeater delegate cannot
// be one Item with two Labels because that wouldn't work
// in a grid then
var timezones = [];
for (var i = 0; i < plasmoid.configuration.selectedTimeZones.length; i++) {
timezones.push(plasmoid.configuration.selectedTimeZones[i]);
timezones.push(plasmoid.configuration.selectedTimeZones[i]);
}
return timezones;
}
PlasmaComponents.Label {
id: timezone
// Layout.fillWidth is buggy here
Layout.alignment: index % 2 === 0 ? Qt.AlignRight : Qt.AlignLeft
wrapMode: Text.NoWrap
text: index % 2 == 0 ? nameForZone(modelData) : timeForZone(modelData)
font.weight: modelData === plasmoid.configuration.lastSelectedTimezone ? Font.Bold : Font.Normal
height: paintedHeight
elide: Text.ElideNone
opacity: 0.6
}
}
}
}
}
}

View file

@ -0,0 +1,288 @@
/*
* Copyright 2013 Bhushan Shah <bhush94@gmail.com>
* Copyright 2013 Sebastian Kügler <sebas@kde.org>
* Copyright 2015 Kai Uwe Broulik <kde@privat.broulik.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
import QtQuick 2.15
import QtQuick.Controls as QtControls
import QtQuick.Layouts 1.15 as QtLayouts
import QtQuick.Dialogs 6.3 as QtDialogs
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core as PlasmaCore
import org.kde.kcmutils // For KCMLauncher
import org.kde.config // For KAuthorized
import org.kde.kirigami 2.20 as Kirigami
import org.kde.plasma.workspace.calendar 2.0 as PlasmaCalendar
SimpleKCM {
id: appearancePage
width: childrenRect.width
height: childrenRect.height
signal configurationChanged
property string cfg_fontFamily
property string cfg_fontSize
property alias cfg_boldText: boldCheckBox.checked
property string cfg_timeFormat: ""
property alias cfg_italicText: italicCheckBox.checked
property alias cfg_showLocalTimezone: showLocalTimezone.checked
property alias cfg_displayTimezoneAsCode: timezoneCodeRadio.checked
property alias cfg_showSeconds: showSeconds.checked
property alias cfg_showDate: showDate.checked
property string cfg_dateFormat: "shortDate"
property alias cfg_use24hFormat: use24hFormat.checkState
onCfg_fontFamilyChanged: {
// HACK by the time we populate our model and/or the ComboBox is finished the value is still undefined
if (cfg_fontFamily) {
for (var i = 0, j = fontsModel.count; i < j; ++i) {
if (fontsModel.get(i).value == cfg_fontFamily) {
fontFamilyComboBox.currentIndex = i
break
}
}
}
}
ListModel {
id: fontsModel
Component.onCompleted: {
var arr = [] // use temp array to avoid constant binding stuff
arr.push({text: i18nc("Use default font", "Default"), value: ""})
var fonts = Qt.fontFamilies()
var foundIndex = 0
for (var i = 0, j = fonts.length; i < j; ++i) {
arr.push({text: fonts[i], value: fonts[i]})
}
append(arr)
}
}
ListModel {
id: fontSizesModel
Component.onCompleted: {
var arr = [] // use temp array to avoid constant binding stuff
arr.push({text: i18n("Use default font size"), value: ""})
var sizes = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '14', '16', '18', '20', '22', '24', '26', '28', '36', '48', '72']
for (var i = 0, j = sizes.length; i < j; ++i) {
arr.push({text: sizes[i], value: sizes[i]})
}
append(arr)
}
}
QtLayouts.ColumnLayout {
anchors.left: parent.left
QtControls.GroupBox {
QtLayouts.Layout.fillWidth: true
title: i18n("Information")
//flat: true
QtLayouts.ColumnLayout {
QtControls.CheckBox {
id: showDate
text: i18n("Show date")
}
QtControls.CheckBox {
id: showSeconds
text: i18n("Show seconds")
}
QtControls.CheckBox {
id: use24hFormat
text: i18nc("Checkbox label; means 24h clock format, without am/pm", "Use 24-hour Clock")
}
QtControls.CheckBox {
id: showLocalTimezone
text: i18n("Show local time zone")
}
/*QtControls.Label {
text: i18n("Display time zone as:")
}*/
QtControls.ButtonGroup {
buttons: timezoneColumn.children
}
QtControls.GroupBox {
QtLayouts.Layout.fillWidth: true
visible: false
//flat: true
QtLayouts.ColumnLayout {
id: timezoneColumn
//QtControls.ExclusiveGroup { id: timezoneDisplayType }
QtControls.RadioButton {
id: timezoneCityRadio
text: i18n("Time zone city")
//exclusiveGroup: timezoneDisplayType
}
QtControls.RadioButton {
id: timezoneCodeRadio
text: i18n("Time zone code")
//exclusiveGroup: timezoneDisplayType
}
}
}
QtLayouts.RowLayout {
QtControls.Label {
text: i18n("Date format:")
}
QtControls.ComboBox {
id: dateFormat
enabled: showDate.checked
textRole: "label"
model: [
{
'label': i18n("Long Date"),
'name': "longDate"
},
{
'label': i18n("Short Date"),
'name': "shortDate"
},
{
'label': i18n("ISO Date"),
'name': "isoDate"
}
]
onCurrentIndexChanged: cfg_dateFormat = model[currentIndex]["name"]
Component.onCompleted: {
for (var i = 0; i < model.length; i++) {
if (model[i]["name"] == Plasmoid.configuration.dateFormat) {
dateFormat.currentIndex = i;
}
}
}
}
}
}
}
QtLayouts.RowLayout {
QtLayouts.Layout.fillWidth: true
QtControls.Label {
text: i18n(" Font size px: ")
}
QtControls.ComboBox {
id: fontSizeComboBox
QtLayouts.Layout.fillWidth: true
// ComboBox's sizing is just utterly broken
QtLayouts.Layout.minimumWidth: Kirigami.Units.iconSizes.small * 10
model: fontSizesModel
// doesn't autodeduce from model because we manually populate it
textRole: "text"
onCurrentIndexChanged: {
var current = model.get(currentIndex)
if (current) {
cfg_fontSize = current.value
appearancePage.configurationChanged()
}
}
}
}
QtLayouts.RowLayout {
QtLayouts.Layout.fillWidth: true
QtControls.Label {
text: i18n(" Font style:")
}
QtControls.ComboBox {
id: fontFamilyComboBox
QtLayouts.Layout.fillWidth: true
// ComboBox's sizing is just utterly broken
QtLayouts.Layout.minimumWidth: Kirigami.Units.iconSizes.small * 10
model: fontsModel
// doesn't autodeduce from model because we manually populate it
textRole: "text"
onCurrentIndexChanged: {
var current = model.get(currentIndex)
if (current) {
cfg_fontFamily = current.value
appearancePage.configurationChanged()
}
}
}
QtControls.Button {
id: boldCheckBox
//tooltip: i18n("Bold text")
icon.name: "format-text-bold"
checkable: true
//Accessible.name: tooltip
}
QtControls.Button {
id: italicCheckBox
//tooltip: i18n("Italic text")
icon.name: "format-text-italic"
checkable: true
//Accessible.name: tooltip
}
}
}
Component.onCompleted: {
if (Plasmoid.configuration.displayTimezoneAsCode) {
timezoneCodeRadio.checked = true;
} else {
timezoneCityRadio.checked = true;
}
for(var i = 0; i < fontsModel.count; i++) {
if(fontsModel.get(i).value == Plasmoid.configuration.fontFamily) {
fontFamilyComboBox.currentIndex = i;
break;
}
}
for(var i = 0; i < fontSizesModel.count; i++) {
if(fontSizesModel.get(i).value == Plasmoid.configuration.fontSize) {
fontSizeComboBox.currentIndex = i;
break;
}
}
boldCheckBox.checked = Plasmoid.configuration.boldText;
italicCheckBox.checked = Plasmoid.configuration.italicText;
}
}

View file

@ -0,0 +1,106 @@
/*
* Copyright 2015 Martin Klapetek <mklapetek@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
import QtQuick 2.0
import QtQuick.Controls as QtControls
import QtQuick.Layouts 1.0 as QtLayouts
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.workspace.calendar 2.0 as PlasmaCalendar
import org.kde.kcmutils as KCM
import org.kde.kirigami 2.20 as Kirigami
KCM.SimpleKCM {
id: calendarPage
width: childrenRect.width
height: childrenRect.height
signal configurationChanged()
property alias cfg_showWeekNumbers: showWeekNumbers.checked
property int cfg_firstDayOfWeek
PlasmaCalendar.EventPluginsManager {
id: eventPluginsManager
Component.onCompleted: {
populateEnabledPluginsList(Plasmoid.configuration.enabledCalendarPlugins);
}
}
function saveConfig()
{
Plasmoid.configuration.enabledCalendarPlugins = eventPluginsManager.enabledPlugins;
}
QtLayouts.ColumnLayout {
anchors.left: parent.left
QtControls.CheckBox {
id: showWeekNumbers
text: i18n("Show week numbers in Calendar")
}
QtLayouts.RowLayout {
QtLayouts.Layout.fillWidth: true
Text {
text: i18n("First day of week:")
}
//Kirigami.FormData.label: i18n("First day of week:")
QtControls.ComboBox {
id: firstDayOfWeekCombo
textRole: "text"
model: [-1, 0, 1, 5, 6].map(day => ({
day,
text: day === -1 ? i18n("Use Region Defaults") : Qt.locale().dayName(day),
}))
onActivated: cfg_firstDayOfWeek = model[index].day
currentIndex: model.findIndex(item => item.day === cfg_firstDayOfWeek)
}
}
QtControls.GroupBox {
QtLayouts.Layout.fillWidth: true
title: i18n("Available Calendar Plugins")
//flat: true
QtLayouts.ColumnLayout {
Repeater {
id: calendarPluginsRepeater
model: eventPluginsManager.model
delegate: QtLayouts.RowLayout {
QtControls.CheckBox {
text: model.display
checked: model.checked
onClicked: {
//needed for model's setData to be called
model.checked = checked;
calendarPage.configurationChanged();
}
}
}
}
}
}
}
Component.onCompleted: {
eventPluginsManager.populateEnabledPluginsList(Plasmoid.configuration.enabledCalendarPlugins);
}
}

View file

@ -0,0 +1,251 @@
/*
* SPDX-FileCopyrightText: 2013 Kai Uwe Broulik <kde@privat.broulik.de>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
import QtQuick
import QtQuick.Controls 2.15 as QQC2
import QtQuick.Layouts 1.15
import org.kde.kquickcontrolsaddons 2.0 // For kcmshell
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.private.digitalclock 1.0
import org.kde.kirigami as Kirigami
import org.kde.kcmutils as KCMUtils
import org.kde.config // KAuthorized
KCMUtils.ScrollViewKCM {
id: timeZonesPage
property alias cfg_selectedTimeZones: timeZones.selectedTimeZones
property alias cfg_wheelChangesTimezone: enableWheelCheckBox.checked
TimeZoneModel {
id: timeZones
onSelectedTimeZonesChanged: {
if (selectedTimeZones.length === 0) {
// Don't let the user remove all time zones
messageWidget.visible = true;
timeZones.selectLocalTimeZone();
}
}
}
header: ColumnLayout {
spacing: Kirigami.Units.smallSpacing
QQC2.Label {
Layout.fillWidth: true
text: i18n("Tip: if you travel frequently, add your home time zone to this list. It will only appear when you change the systemwide time zone to something else.")
wrapMode: Text.Wrap
}
}
view: ListView {
id: configuredTimezoneList
clip: true // Avoid visual glitches
focus: true // keyboard navigation
activeFocusOnTab: true // keyboard navigation
model: TimeZoneFilterProxy {
sourceModel: timeZones
onlyShowChecked: true
}
// We have no concept of selection in this list, so don't pre-select
// the first item
currentIndex: -1
delegate: Kirigami.RadioSubtitleDelegate {
id: timeZoneListItem
readonly property bool isCurrent: Plasmoid.configuration.lastSelectedTimezone === model.timeZoneId
readonly property bool isIdenticalToLocal: !model.isLocalTimeZone && model.city === timeZones.localTimeZoneCity()
width: ListView.view.width
font.bold: isCurrent
// Stripes help the eye line up the text on the left and the button on the right
Kirigami.Theme.useAlternateBackgroundColor: true
text: model.city
subtitle: {
if (configuredTimezoneList.count > 1) {
if (isCurrent) {
return i18n("Clock is currently using this time zone");
} else if (isIdenticalToLocal) {
return i18nc("@label This list item shows a time zone city name that is identical to the local time zone's city, and will be hidden in the timezone display in the plasmoid's popup", "Hidden while this is the local time zone's city");
}
}
return "";
}
checked: isCurrent
onToggled: Plasmoid.configuration.lastSelectedTimezone = model.timeZoneId
contentItem: RowLayout {
spacing: Kirigami.Units.smallSpacing
Kirigami.TitleSubtitle {
Layout.fillWidth: true
opacity: timeZoneListItem.isIdenticalToLocal ? 0.6 : 1.0
title: timeZoneListItem.text
subtitle: timeZoneListItem.subtitle
reserveSpaceForSubtitle: true
}
QQC2.Button {
visible: model.isLocalTimeZone && KAuthorized.authorizeControlModule("kcm_clock.desktop")
text: i18n("Switch Systemwide Time Zone…")
icon.name: "preferences-system-time"
font.bold: false
onClicked: KCMUtils.KCMLauncher.openSystemSettings("kcm_clock")
}
QQC2.Button {
visible: !model.isLocalTimeZone && configuredTimezoneList.count > 1
icon.name: "edit-delete"
font.bold: false
onClicked: model.checked = false;
QQC2.ToolTip {
text: i18n("Remove this time zone")
}
}
}
}
section {
property: "isLocalTimeZone"
delegate: Kirigami.ListSectionHeader {
width: configuredTimezoneList.width
label: section === "true" ? i18n("Systemwide Time Zone") : i18n("Additional Time Zones")
}
}
Kirigami.PlaceholderMessage {
visible: configuredTimezoneList.count === 1
anchors {
top: parent.verticalCenter // Visual offset for system timezone and header
left: parent.left
right: parent.right
leftMargin: Kirigami.Units.largeSpacing * 6
rightMargin: Kirigami.Units.largeSpacing * 6
}
text: i18n("Add more time zones to display all of them in the applet's pop-up, or use one of them for the clock itself")
}
}
footer: ColumnLayout {
spacing: Kirigami.Units.smallSpacing
QQC2.Button {
Layout.alignment: Qt.AlignLeft // Explicitly set so it gets reversed for LTR mode
text: i18n("Add Time Zones…")
icon.name: "list-add"
onClicked: timezoneSheet.open()
}
QQC2.CheckBox {
id: enableWheelCheckBox
enabled: configuredTimezoneList.count > 1
Layout.fillWidth: true
Layout.topMargin: Kirigami.Units.largeSpacing
text: i18n("Switch displayed time zone by scrolling over clock applet")
}
QQC2.Label {
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.largeSpacing * 2
Layout.rightMargin: Kirigami.Units.largeSpacing * 2
text: i18n("Using this feature does not change the systemwide time zone. When you travel, switch the systemwide time zone instead.")
font: Kirigami.Theme.smallFont
wrapMode: Text.Wrap
}
}
Kirigami.OverlaySheet {
id: timezoneSheet
parent: timeZonesPage.QQC2.Overlay.overlay
onVisibleChanged: {
filter.text = "";
messageWidget.visible = false;
if (visible) {
filter.forceActiveFocus()
}
}
header: ColumnLayout {
Kirigami.Heading {
Layout.fillWidth: true
text: i18n("Add More Timezones")
wrapMode: Text.Wrap
}
Kirigami.SearchField {
id: filter
Layout.fillWidth: true
}
Kirigami.InlineMessage {
id: messageWidget
Layout.fillWidth: true
type: Kirigami.MessageType.Warning
text: i18n("At least one time zone needs to be enabled. Your local timezone was enabled automatically.")
showCloseButton: true
}
}
footer: QQC2.DialogButtonBox {
standardButtons: QQC2.DialogButtonBox.Ok
onAccepted: timezoneSheet.close()
}
ListView {
focus: true // keyboard navigation
activeFocusOnTab: true // keyboard navigation
clip: true
implicitWidth: Math.max(timeZonesPage.width/2, Kirigami.Units.iconSizes.small * 25)
model: TimeZoneFilterProxy {
sourceModel: timeZones
filterString: filter.text
}
delegate: QQC2.CheckDelegate {
required property int index
required property var model
required checked
required property string city
required property string comment
required property string region
width: ListView.view.width
focus: true // keyboard navigation
text: {
if (!city || city.indexOf("UTC") === 0) {
return comment;
} else if (comment) {
return i18n("%1, %2 (%3)", city, region, comment);
} else {
return i18n("%1, %2", city, region)
}
}
onToggled: {
model.checked = checked
ListView.view.currentIndex = index // highlight
ListView.view.forceActiveFocus() // keyboard navigation
}
highlighted: ListView.isCurrentItem
}
}
}
}

View file

@ -0,0 +1,55 @@
/*
* Copyright (C) 2019 by intika <intika@librefox.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
import QtQuick 2.5
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4
Item {
id: configPageUpdater
property alias cfg_checkUpdateStartup: checkUpdateStartupBox.checked
ColumnLayout {
GroupBox {
flat: true
ColumnLayout {
Label {
text: i18n("\nUpdater")
font.weight: Font.Bold
}
Label {
text: i18n("Plasmoid: Digital Clock Lite\n")
}
Label {
text: i18n("Version: 5.5")
}
Label {
text: i18n("Author: Intika")
}
TextField {
Layout.minimumWidth: 450
text: 'https://github.com/Intika-Linux-Plasmoid/plasmoid-digital-clock-lite'
}
CheckBox {
id: checkUpdateStartupBox
text: i18n("Notify for update on startup (checked once on github, 5 min after startup)")
}
}
}
}
}

View file

@ -0,0 +1,165 @@
/*
* Copyright 2013 Heena Mahour <heena393@gmail.com>
* Copyright 2013 Sebastian Kügler <sebas@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.15
import QtQuick.Layouts 1.1
import org.kde.plasma.plasmoid
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.plasma5support as P5Support
import org.kde.kirigami 2.20 as Kirigami
import org.kde.plasma.private.digitalclock 1.0
import org.kde.kquickcontrolsaddons 2.0
import org.kde.plasma.workspace.calendar 2.0 as PlasmaCalendar
import org.kde.ksvg 1.0 as KSvg
import org.kde.kcmutils // KCMLauncher
import org.kde.config // KAuthorized
//import org.kde.plasma.components 2.0 as PlasmaComponents
//import org.kde.plasma.extras 2.0 as PlasmaExtras
//import org.kde.plasma.calendar 2.0 as PlasmaCalendar
PlasmoidItem {
id: root
anchors.fill: parent
width: Kirigami.Units.iconSizes.small * 10
height: Kirigami.Units.iconSizes.small * 4
property string dateFormatString: setDateFormatString()
property date tzDate: {
const data = dataSource.data[Plasmoid.configuration.lastSelectedTimezone];
if (data === undefined) {
return new Date();
}
// get the time for the given timezone from the dataengine
const now = data["DateTime"];
// get current UTC time
const msUTC = now.getTime() + (now.getTimezoneOffset() * 60000);
// add the dataengine TZ offset to it
return new Date(msUTC + (data["Offset"] * 1000));
}
function initTimezones() {
const tz = []
if (Plasmoid.configuration.selectedTimeZones.indexOf("Local") === -1) {
tz.push("Local");
}
root.allTimezones = tz.concat(Plasmoid.configuration.selectedTimeZones);
dataSource.connectedSources = root.allTimezones;
}
//This is done to better control how the plasmoid should look and feel in a panel.
//preferredRepresentation: fullRepresentation
//compactRepresentation: null
//fullRepresentation: smallRepresentation
preferredRepresentation: fullRepresentation
compactRepresentation: null
fullRepresentation: smallRepresentation
/*toolTipItem: Loader {
id: tooltipLoader
Layout.minimumWidth: item ? item.width : 0
Layout.maximumWidth: item ? item.width : 0
Layout.minimumHeight: item ? item.height : 0
Layout.maximumHeight: item ? item.height : 0
source: "Tooltip.qml"
}*/
KSvg.Svg {
id: buttonIcons
imagePath: Qt.resolvedUrl("svgs/icons.svg");
}
KSvg.Svg {
id: clockSvg
imagePath: Qt.resolvedUrl("svgs/clock.svg");
}
//We need Local to be *always* present, even if not disaplayed as
//it's used for formatting in ToolTip.dateTimeChanged()
property var allTimezones
Connections {
target: Plasmoid.configuration
function onSelectedTimeZonesChanged() { root.initTimezones(); }
}
Component {
id: mainRepresentation
CalendarView {
}
}
Component {
id: smallRepresentation
DigitalClock
{}
}
hideOnWindowDeactivate: !Plasmoid.configuration.pin
P5Support.DataSource {
id: dataSource
engine: "time"
connectedSources: allTimezones
interval: Plasmoid.configuration.showSeconds ? 1000 : 60000
intervalAlignment: Plasmoid.configuration.showSeconds ? P5Support.Types.NoAlignment : P5Support.Types.AlignToMinute
}
function setDateFormatString() {
// remove "dddd" from the locale format string
// /all/ locales in LongFormat have "dddd" either
// at the beginning or at the end. so we just
// remove it + the delimiter and space
var format = Qt.locale().dateFormat(Locale.LongFormat);
format = format.replace(/(^dddd.?\s)|(,?\sdddd$)/, "");
return format;
}
Plasmoid.contextualActions: [
PlasmaCore.Action {
text: i18n("Adjust Date and Time…")
icon.name: "clock"
visible: KAuthorized.authorize("kcm_clock")
onTriggered: KCMLauncher.openSystemSettings("kcm_clock")
},
PlasmaCore.Action {
text: i18n("Set Time Format…")
icon.name: "gnumeric-format-thousand-separator"
visible: KAuthorized.authorizeControlModule("kcm_regionandlang")
onTriggered: KCMLauncher.openSystemSettings("kcm_regionandlang")
}
]
PlasmaCalendar.EventPluginsManager {
id: eventPluginsManager
enabledPlugins: Plasmoid.configuration.enabledCalendarPlugins
}
Component.onCompleted: {
root.initTimezones();
// Set the list of enabled plugins from config
// to the manager
eventPluginsManager.enabledPlugins = Plasmoid.configuration.enabledCalendarPlugins;
}
}

View file

@ -0,0 +1,701 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="129"
height="129"
viewBox="0 0 129 129"
fill="none"
version="1.1"
id="svg63"
sodipodi:docname="clock.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview63"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="5.6568543"
inkscape:cx="78.400464"
inkscape:cy="70.799066"
inkscape:window-width="1880"
inkscape:window-height="1032"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg63"
showgrid="false"
showguides="true"><inkscape:grid
id="grid42"
units="px"
originx="0"
originy="0"
spacingx="1"
spacingy="1"
empcolor="#0099e5"
empopacity="0.30196078"
color="#e50000"
opacity="0.14901961"
empspacing="1"
dotted="false"
gridanglex="30"
gridanglez="30"
visible="true"
snapvisiblegridlinesonly="true" /></sodipodi:namedview><g
filter="url(#filter0_d_3_129)"
id="clockface"
style="display:inline"><mask
id="path-1-inside-1_3_129"
fill="#ffffff"><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 63.5,0 C 28.9822,0 1,27.9822 1,62.5 1,97.0178 28.9822,125 63.5,125 98.0178,125 126,97.0178 126,62.5 126,27.9822 98.0178,0 63.5,0 Z m 0,4 C 31.1913,4 5,30.1913 5,62.5 5,94.8087 31.1913,121 63.5,121 95.8087,121 122,94.8087 122,62.5 122,30.1913 95.8087,4 63.5,4 Z"
id="path1" /></mask><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 63.5,0 C 28.9822,0 1,27.9822 1,62.5 1,97.0178 28.9822,125 63.5,125 98.0178,125 126,97.0178 126,62.5 126,27.9822 98.0178,0 63.5,0 Z m 0,4 C 31.1913,4 5,30.1913 5,62.5 5,94.8087 31.1913,121 63.5,121 95.8087,121 122,94.8087 122,62.5 122,30.1913 95.8087,4 63.5,4 Z"
fill="url(#paint0_linear_3_129)"
id="path2"
style="display:inline;fill:url(#paint0_linear_3_129)" /><path
d="M 2,62.5 C 2,28.5345 29.5345,1 63.5,1 V -1 C 28.4299,-1 0,27.4299 0,62.5 Z M 63.5,124 C 29.5345,124 2,96.4655 2,62.5 H 0 C 0,97.5701 28.4299,126 63.5,126 Z M 125,62.5 C 125,96.4655 97.4655,124 63.5,124 v 2 C 98.5701,126 127,97.5701 127,62.5 Z M 63.5,1 C 97.4655,1 125,28.5345 125,62.5 h 2 C 127,27.4299 98.5701,-1 63.5,-1 Z M 6,62.5 C 6,30.7436 31.7436,5 63.5,5 V 3 C 30.6391,3 4,29.6391 4,62.5 Z M 63.5,120 C 31.7436,120 6,94.2564 6,62.5 H 4 C 4,95.3609 30.6391,122 63.5,122 Z M 121,62.5 C 121,94.2564 95.2564,120 63.5,120 v 2 C 96.3609,122 123,95.3609 123,62.5 Z M 63.5,5 C 95.2564,5 121,30.7436 121,62.5 h 2 C 123,29.6391 96.3609,3 63.5,3 Z"
fill="#798183"
mask="url(#path-1-inside-1_3_129)"
id="path3"
style="display:inline" /><g
filter="url(#filter1_i_3_129)"
id="g3"
style="display:inline"><circle
cx="63.5"
cy="62.5"
r="58.5"
fill="url(#paint1_linear_3_129)"
id="circle3"
style="display:inline" /></g><g
filter="url(#filter2_f_3_129)"
id="g4"><circle
cx="63.5"
cy="62.5"
r="56"
stroke="url(#paint2_linear_3_129)"
stroke-opacity="0.3"
id="circle4"
style="display:inline;stroke:url(#paint2_linear_3_129)" /></g><mask
id="mask0_3_129"
maskUnits="userSpaceOnUse"
x="11"
y="10"
width="105"
height="105"><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 63.5,115 C 92.4949,115 116,91.4949 116,62.5 116,33.5051 92.4949,10 63.5,10 34.5051,10 11,33.5051 11,62.5 11,91.4949 34.5051,115 63.5,115 Z m 0,-8 C 88.0767,107 108,87.0767 108,62.5 108,37.9233 88.0767,18 63.5,18 38.9233,18 19,37.9233 19,62.5 19,87.0767 38.9233,107 63.5,107 Z"
fill="#d9d9d9"
id="path4" /></mask><g
mask="url(#mask0_3_129)"
id="g10"
style="display:inline"><path
d="M 64,10 V 115"
stroke="#4b6b6e"
stroke-width="2"
id="path5" /><path
d="m 37.75,17.0337 52.5,90.9323"
stroke="#4b6b6e"
stroke-width="2"
id="path6" /><path
d="m 18.5337,36.25 90.9323,52.5"
stroke="#4b6b6e"
stroke-width="2"
id="path7" /><path
d="m 11.5,62.5 h 105"
stroke="#4b6b6e"
stroke-width="2"
id="path8" /><path
d="M 18.5337,88.75 109.466,36.25"
stroke="#4b6b6e"
stroke-width="2"
id="path9"
style="display:inline" /><path
d="M 37.75,107.966 90.25,17.0337"
stroke="#4b6b6e"
stroke-width="2"
id="path10"
style="display:inline" /></g><g
filter="url(#filter3_di_3_129)"
id="g42"
style="display:inline"><mask
id="mask1_3_129"
maskUnits="userSpaceOnUse"
x="10"
y="9"
width="107"
height="107"><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 68.9895,114.712 C 97.8255,111.68 118.744,85.8466 115.712,57.0106 112.68,28.1746 86.8466,7.25606 58.0106,10.2878 29.1745,13.3195 8.25605,39.1535 11.2878,67.9895 14.3195,96.8255 40.1534,117.744 68.9895,114.712 Z M 68.692,111.883 C 95.9656,109.016 115.751,84.5816 112.883,57.308 110.016,30.0344 85.5816,10.2493 58.308,13.1168 31.0344,15.9843 11.2493,40.4184 14.1168,67.692 c 2.8675,27.2736 27.3016,47.059 54.5752,44.191 z"
fill="#d9d9d9"
id="path11" /></mask><g
mask="url(#mask1_3_129)"
id="g41"
style="display:inline"><path
d="M 58.5078,10.2355 69.4867,114.66"
stroke="#4b6b6e"
id="path12" /><path
d="M 33.1371,19.9753 94.8574,104.92"
stroke="#4b6b6e"
id="path13" /><path
d="M 16.0354,41.0956 111.959,83.7998"
stroke="#4b6b6e"
id="path14" /><path
d="M 11.785,67.9372 116.209,56.9583"
stroke="#4b6b6e"
id="path15" /><path
d="M 21.5249,93.3078 106.47,31.5876"
stroke="#4b6b6e"
id="path16" /><path
d="M 42.6451,110.41 85.3494,14.4859"
stroke="#4b6b6e"
id="path17" /><path
d="M 58.5078,10.2355 69.4867,114.66"
stroke="#4b6b6e"
id="path18" /><path
d="M 33.1371,19.9753 94.8574,104.92"
stroke="#4b6b6e"
id="path19" /><path
d="M 16.0354,41.0956 111.959,83.7998"
stroke="#4b6b6e"
id="path20" /><path
d="M 11.785,67.9372 116.209,56.9583"
stroke="#4b6b6e"
id="path21" /><path
d="M 21.5249,93.3078 106.47,31.5876"
stroke="#4b6b6e"
id="path22" /><path
d="M 42.6451,110.41 85.3494,14.4859"
stroke="#4b6b6e"
id="path23" /><path
d="M 53.0737,11.0433 74.9045,113.749"
stroke="#4b6b6e"
id="path24" /><path
d="m 28.8597,23.381 70.2587,78.03"
stroke="#4b6b6e"
id="path25" /><path
d="M 14.0586,46.1727 113.92,78.6194"
stroke="#4b6b6e"
id="path26" /><path
d="M 12.6364,73.3114 115.342,51.4807"
stroke="#4b6b6e"
id="path27" /><path
d="m 24.974,97.5254 78.03,-70.2587"
stroke="#4b6b6e"
id="path28" /><path
d="M 47.7657,112.327 80.2125,12.4656"
stroke="#4b6b6e"
id="path29" /><path
d="m 47.7521,12.415 32.4468,99.861"
stroke="#4b6b6e"
id="path30" /><path
d="M 24.9604,27.2161 102.991,97.4749"
stroke="#4b6b6e"
id="path31" /><path
d="M 12.6228,51.4301 115.328,73.2609"
stroke="#4b6b6e"
id="path32" /><path
d="M 14.0451,78.5689 113.906,46.1221"
stroke="#4b6b6e"
id="path33" /><path
d="M 28.8462,101.361 99.1049,23.3304"
stroke="#4b6b6e"
id="path34" /><path
d="M 53.0602,113.698 74.8909,10.9928"
stroke="#4b6b6e"
id="path35" /><path
d="M 42.6031,14.3355 85.3105,110.258"
stroke="#4b6b6e"
id="path36" /><path
d="M 21.4834,31.4379 106.43,93.1554"
stroke="#4b6b6e"
id="path37" /><path
d="M 11.7444,56.8089 116.169,67.7844"
stroke="#4b6b6e"
id="path38" /><path
d="M 15.9956,83.6503 111.918,40.943"
stroke="#4b6b6e"
id="path39" /><path
d="M 33.0981,104.77 94.8155,19.8232"
stroke="#4b6b6e"
id="path40" /><path
d="M 58.4691,114.509 69.4446,10.0842"
stroke="#4b6b6e"
id="path41" /></g></g></g><g
style="display:inline;fill:none"
id="g44"
transform="translate(4,3)"><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 119,59.5 C 119,92.3609 92.3609,119 59.5,119 43.1967,119 28.4249,112.443 17.6779,101.822 7.05708,91.0751 0.5,76.3033 0.5,60 0.5,27.1391 27.1391,0.5 60,0.5 76.3033,0.5 91.0751,7.05708 101.822,17.6779 112.443,28.4249 119,43.1967 119,59.5 Z M 118.5,60 C 118.5,92.3087 92.3087,118.5 60,118.5 27.6913,118.5 1.5,92.3087 1.5,60 1.5,27.6913 27.6913,1.5 60,1.5 c 32.3087,0 58.5,26.1913 58.5,58.5 z"
fill="#b3b6bc"
id="path1-3" /><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 59.5,118 C 91.8087,118 118,91.8087 118,59.5 118,27.1913 91.8087,1 59.5,1 27.1913,1 1,27.1913 1,59.5 1,91.8087 27.1913,118 59.5,118 Z m 0,1 C 92.3609,119 119,92.3609 119,59.5 119,26.6391 92.3609,0 59.5,0 26.6391,0 0,26.6391 0,59.5 0,92.3609 26.6391,119 59.5,119 Z"
fill="#8892a3"
id="path2-7" /></g><defs
id="defs63"><filter
id="filter0_d_3_129"
x="0"
y="0"
width="129"
height="129"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood43" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix43" /><feOffset
dx="1"
dy="2"
id="feOffset43" /><feGaussianBlur
stdDeviation="1"
id="feGaussianBlur43" /><feComposite
in2="hardAlpha"
operator="out"
id="feComposite43" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
id="feColorMatrix44" /><feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_129"
id="feBlend44" /><feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_129"
result="shape"
id="feBlend45" /></filter><filter
id="filter1_i_3_129"
x="5"
y="4"
width="117"
height="117"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood45" /><feBlend
mode="normal"
in="SourceGraphic"
in2="BackgroundImageFix"
result="shape"
id="feBlend46" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix46" /><feOffset
id="feOffset46" /><feGaussianBlur
stdDeviation="1.5"
id="feGaussianBlur46" /><feComposite
in2="hardAlpha"
operator="arithmetic"
k2="-1"
k3="1"
id="feComposite46" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"
id="feColorMatrix47" /><feBlend
mode="normal"
in2="shape"
result="effect1_innerShadow_3_129"
id="feBlend47" /></filter><filter
id="filter2_f_3_129"
x="6"
y="5"
width="115"
height="115"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood47" /><feBlend
mode="normal"
in="SourceGraphic"
in2="BackgroundImageFix"
result="shape"
id="feBlend48" /><feGaussianBlur
stdDeviation="0.5"
result="effect1_foregroundBlur_3_129"
id="feGaussianBlur48" /></filter><filter
id="filter3_di_3_129"
x="10.8921"
y="9.23197"
width="105.312"
height="105.68"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood48" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix48" /><feOffset
dx="-0.8"
dy="-0.8"
id="feOffset48" /><feComposite
in2="hardAlpha"
operator="out"
id="feComposite48" /><feColorMatrix
type="matrix"
values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"
id="feColorMatrix49" /><feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_129"
id="feBlend49" /><feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_129"
result="shape"
id="feBlend50" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix50" /><feOffset
dx="0.2"
dy="0.2"
id="feOffset50" /><feGaussianBlur
stdDeviation="0.25"
id="feGaussianBlur50" /><feComposite
in2="hardAlpha"
operator="arithmetic"
k2="-1"
k3="1"
id="feComposite50" /><feColorMatrix
type="matrix"
values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"
id="feColorMatrix51" /><feBlend
mode="normal"
in2="shape"
result="effect2_innerShadow_3_129"
id="feBlend51" /></filter><linearGradient
id="paint0_linear_3_129"
x1="9.2331963"
y1="19.919386"
x2="86.97599"
y2="68.179153"
gradientUnits="userSpaceOnUse"><stop
stop-color="#F8FEFF"
id="stop51" /><stop
offset="0.486626"
stop-color="#E1E3E7"
id="stop52" /><stop
offset="0.782747"
stop-color="#C2C6C7"
id="stop53" /></linearGradient><linearGradient
id="paint1_linear_3_129"
x1="19.5"
y1="18.5"
x2="107.5"
y2="106.5"
gradientUnits="userSpaceOnUse"><stop
stop-color="#E2EBEF"
id="stop54" /><stop
offset="0.23"
stop-color="#ECF0F1"
id="stop55" /><stop
offset="0.38"
stop-color="#D7E0E2"
id="stop56" /><stop
offset="0.5"
stop-color="#CDD8DB"
id="stop57" /><stop
offset="0.63"
stop-color="#D6DFE2"
id="stop58" /><stop
offset="0.91"
stop-color="#FCFEFF"
id="stop59" /></linearGradient><linearGradient
id="paint2_linear_3_129"
x1="47.008453"
y1="30.222439"
x2="82.889488"
y2="91.564278"
gradientUnits="userSpaceOnUse"><stop
stop-color="#26444E"
id="stop60" /><stop
offset="0.5"
stop-color="#26444E"
stop-opacity="0"
id="stop61" /></linearGradient><radialGradient
id="paint3_radial_3_129"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(62.5 61.5) rotate(45) scale(3.53553)"><stop
offset="0.025"
stop-color="#579FA4"
id="stop62" /><stop
offset="0.64"
stop-color="#213C3E"
id="stop63" /></radialGradient><filter
id="filter1_df_3_182"
x="2"
y="2"
width="117.681"
height="97.7024"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood4" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix4" /><feOffset
dy="4"
id="feOffset4" /><feGaussianBlur
stdDeviation="1"
id="feGaussianBlur5" /><feComposite
in2="hardAlpha"
operator="out"
id="feComposite5" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"
id="feColorMatrix5" /><feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_182"
id="feBlend5" /><feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_182"
result="shape"
id="feBlend6" /><feGaussianBlur
stdDeviation="1"
result="effect2_foregroundBlur_3_182"
id="feGaussianBlur6" /></filter><linearGradient
id="paint1_linear_3_182"
x1="37"
y1="10.5"
x2="67"
y2="72.5"
gradientUnits="userSpaceOnUse"><stop
stop-color="white"
stop-opacity="0"
id="stop8" /><stop
offset="1"
stop-color="white"
id="stop9" /></linearGradient><filter
id="filter0_df_3_182"
x="2"
y="3"
width="114.604"
height="110.884"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood2" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix2" /><feOffset
dy="4"
id="feOffset2" /><feGaussianBlur
stdDeviation="1"
id="feGaussianBlur2" /><feComposite
in2="hardAlpha"
operator="out"
id="feComposite2" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"
id="feColorMatrix3" /><feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_182"
id="feBlend3" /><feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_182"
result="shape"
id="feBlend4" /><feGaussianBlur
stdDeviation="0.5"
result="effect2_foregroundBlur_3_182"
id="feGaussianBlur4" /></filter><filter
id="filter1_df_3_182-3"
x="2"
y="2"
width="117.681"
height="97.7024"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood4-6" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix4-7" /><feOffset
dy="4"
id="feOffset4-5" /><feGaussianBlur
stdDeviation="1"
id="feGaussianBlur5-3" /><feComposite
in2="hardAlpha"
operator="out"
id="feComposite5-5" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"
id="feColorMatrix5-6" /><feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_182"
id="feBlend5-2" /><feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_182"
result="shape"
id="feBlend6-9" /><feGaussianBlur
stdDeviation="1"
result="effect2_foregroundBlur_3_182"
id="feGaussianBlur6-1" /></filter><filter
id="filter0_df_3_182-0"
x="2"
y="3"
width="114.604"
height="110.884"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood2-9" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix2-3" /><feOffset
dy="4"
id="feOffset2-6" /><feGaussianBlur
stdDeviation="1"
id="feGaussianBlur2-0" /><feComposite
in2="hardAlpha"
operator="out"
id="feComposite2-6" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"
id="feColorMatrix3-2" /><feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_182"
id="feBlend3-6" /><feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_182"
result="shape"
id="feBlend4-1" /><feGaussianBlur
stdDeviation="0.5"
result="effect2_foregroundBlur_3_182"
id="feGaussianBlur4-8" /></filter><linearGradient
inkscape:collect="always"
xlink:href="#paint1_linear_3_182"
id="linearGradient1"
gradientUnits="userSpaceOnUse"
x1="37"
y1="10.5"
x2="67"
y2="72.5" /><linearGradient
inkscape:collect="always"
xlink:href="#paint1_linear_3_182"
id="linearGradient2"
gradientUnits="userSpaceOnUse"
x1="37"
y1="10.5"
x2="67"
y2="72.5" /><filter
id="filter1_i_3_129-2"
x="5"
y="4"
width="117"
height="117"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood45-0" /><feBlend
mode="normal"
in="SourceGraphic"
in2="BackgroundImageFix"
result="shape"
id="feBlend46-2" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix46-3" /><feOffset
id="feOffset46-7" /><feGaussianBlur
stdDeviation="1.5"
id="feGaussianBlur46-5" /><feComposite
in2="hardAlpha"
operator="arithmetic"
k2="-1"
k3="1"
id="feComposite46-9"
k1="0"
k4="0" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"
id="feColorMatrix47-2" /><feBlend
mode="normal"
in2="shape"
result="effect1_innerShadow_3_129"
id="feBlend47-2" /></filter></defs><circle
cx="63.5"
cy="62.5"
r="2.5"
fill="url(#paint3_radial_3_129)"
id="clockdot" /><g
id="clockshine"><g
opacity="0.14"
filter="url(#filter0_df_3_182)"
id="g2"
style="filter:url(#filter0_df_3_182-0)"><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 114.604,35.8755 C 98.6369,29.2336 73.1157,37.2154 52.1952,56.76 35.0872,72.7428 25.4849,92.3203 25.5839,107.884 12.4127,97.1568 4,80.8109 4,62.5 4,30.1913 30.1913,4 62.5,4 c 22.7201,0 42.415,12.9521 52.104,31.8755 z"
fill="url(#paint0_linear_3_182)"
shape-rendering="crispEdges"
id="path1-7"
style="fill:url(#linearGradient1)" /></g><g
opacity="0.6"
filter="url(#filter1_df_3_182)"
id="g3-9"
style="filter:url(#filter1_df_3_182-3)"><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 117.681,43.0287 C 104.615,41.2781 88.9173,42.3436 72.6911,46.6914 39.2424,55.6539 14.7141,75.572 13.0071,93.7024 7.30188,84.6718 4,73.9715 4,62.5 4,30.1913 30.1913,4 62.5,4 c 25.482,0 47.159,16.2924 55.181,39.0287 z"
fill="url(#paint1_linear_3_182)"
shape-rendering="crispEdges"
id="path2-2"
style="fill:url(#linearGradient2)" /></g><rect
style="opacity:0;fill:#2c2c2c;stroke:#2c2c2c;stroke-width:0;stroke-opacity:0.984036"
id="rect5"
width="129"
height="129"
x="0"
y="0" /></g></svg>

After

Width:  |  Height:  |  Size: 24 KiB

View file

@ -0,0 +1,809 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="129"
height="129"
viewBox="0 0 129 129"
fill="none"
version="1.1"
id="svg63"
sodipodi:docname="clock.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview63"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="5.4983399"
inkscape:cx="83.388806"
inkscape:cy="82.206631"
inkscape:window-width="1600"
inkscape:window-height="838"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="clockface" />
<g
filter="url(#filter0_d_3_129)"
id="clockface">
<mask
id="path-1-inside-1_3_129"
fill="white">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M63.5 0C28.9822 0 1 27.9822 1 62.5C1 97.0178 28.9822 125 63.5 125C98.0178 125 126 97.0178 126 62.5C126 27.9822 98.0178 0 63.5 0ZM63.5 4C31.1913 4 5 30.1913 5 62.5C5 94.8087 31.1913 121 63.5 121C95.8087 121 122 94.8087 122 62.5C122 30.1913 95.8087 4 63.5 4Z"
id="path1" />
</mask>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M63.5 0C28.9822 0 1 27.9822 1 62.5C1 97.0178 28.9822 125 63.5 125C98.0178 125 126 97.0178 126 62.5C126 27.9822 98.0178 0 63.5 0ZM63.5 4C31.1913 4 5 30.1913 5 62.5C5 94.8087 31.1913 121 63.5 121C95.8087 121 122 94.8087 122 62.5C122 30.1913 95.8087 4 63.5 4Z"
fill="url(#paint0_linear_3_129)"
id="path2" />
<path
d="M2 62.5C2 28.5345 29.5345 1 63.5 1V-1C28.4299 -1 0 27.4299 0 62.5H2ZM63.5 124C29.5345 124 2 96.4655 2 62.5H0C0 97.5701 28.4299 126 63.5 126V124ZM125 62.5C125 96.4655 97.4655 124 63.5 124V126C98.5701 126 127 97.5701 127 62.5H125ZM63.5 1C97.4655 1 125 28.5345 125 62.5H127C127 27.4299 98.5701 -1 63.5 -1V1ZM6 62.5C6 30.7436 31.7436 5 63.5 5V3C30.6391 3 4 29.6391 4 62.5H6ZM63.5 120C31.7436 120 6 94.2564 6 62.5H4C4 95.3609 30.6391 122 63.5 122V120ZM121 62.5C121 94.2564 95.2564 120 63.5 120V122C96.3609 122 123 95.3609 123 62.5H121ZM63.5 5C95.2564 5 121 30.7436 121 62.5H123C123 29.6391 96.3609 3 63.5 3V5Z"
fill="#798183"
mask="url(#path-1-inside-1_3_129)"
id="path3" />
<g
filter="url(#filter1_i_3_129)"
id="g3">
<circle
cx="63.5"
cy="62.5"
r="58.5"
fill="url(#paint1_linear_3_129)"
id="circle3" />
</g>
<g
filter="url(#filter2_f_3_129)"
id="g4">
<circle
cx="63.5"
cy="62.5"
r="56"
stroke="url(#paint2_linear_3_129)"
stroke-opacity="0.3"
id="circle4" />
</g>
<mask
id="mask0_3_129"
maskUnits="userSpaceOnUse"
x="11"
y="10"
width="105"
height="105"
style="mask-type:alpha">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M63.5 115C92.4949 115 116 91.4949 116 62.5C116 33.5051 92.4949 10 63.5 10C34.5051 10 11 33.5051 11 62.5C11 91.4949 34.5051 115 63.5 115ZM63.5 107C88.0767 107 108 87.0767 108 62.5C108 37.9233 88.0767 18 63.5 18C38.9233 18 19 37.9233 19 62.5C19 87.0767 38.9233 107 63.5 107Z"
fill="#D9D9D9"
id="path4" />
</mask>
<g
mask="url(#mask0_3_129)"
id="g10">
<path
d="M64 10V115"
stroke="#4B6B6E"
stroke-width="2"
id="path5" />
<path
d="M37.75 17.0337L90.25 107.966"
stroke="#4B6B6E"
stroke-width="2"
id="path6" />
<path
d="M18.5337 36.25L109.466 88.75"
stroke="#4B6B6E"
stroke-width="2"
id="path7" />
<path
d="M11.5 62.5L116.5 62.5"
stroke="#4B6B6E"
stroke-width="2"
id="path8" />
<path
d="M18.5337 88.75L109.466 36.25"
stroke="#4B6B6E"
stroke-width="2"
id="path9" />
<path
d="M37.75 107.966L90.25 17.0337"
stroke="#4B6B6E"
stroke-width="2"
id="path10" />
</g>
<g
filter="url(#filter3_di_3_129)"
id="g42">
<mask
id="mask1_3_129"
maskUnits="userSpaceOnUse"
x="10"
y="9"
width="107"
height="107"
style="mask-type:alpha">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M68.9895 114.712C97.8255 111.68 118.744 85.8466 115.712 57.0106C112.68 28.1746 86.8466 7.25606 58.0106 10.2878C29.1745 13.3195 8.25605 39.1535 11.2878 67.9895C14.3195 96.8255 40.1534 117.744 68.9895 114.712ZM68.692 111.883C95.9656 109.016 115.751 84.5816 112.883 57.308C110.016 30.0344 85.5816 10.2493 58.308 13.1168C31.0344 15.9843 11.2493 40.4184 14.1168 67.692C16.9843 94.9656 41.4184 114.751 68.692 111.883Z"
fill="#D9D9D9"
id="path11" />
</mask>
<g
mask="url(#mask1_3_129)"
id="g41">
<path
d="M58.5078 10.2355L69.4867 114.66"
stroke="#4B6B6E"
id="path12" />
<path
d="M33.1371 19.9753L94.8574 104.92"
stroke="#4B6B6E"
id="path13" />
<path
d="M16.0354 41.0956L111.959 83.7998"
stroke="#4B6B6E"
id="path14" />
<path
d="M11.785 67.9372L116.209 56.9583"
stroke="#4B6B6E"
id="path15" />
<path
d="M21.5249 93.3078L106.47 31.5876"
stroke="#4B6B6E"
id="path16" />
<path
d="M42.6451 110.41L85.3494 14.4859"
stroke="#4B6B6E"
id="path17" />
<path
d="M58.5078 10.2355L69.4867 114.66"
stroke="#4B6B6E"
id="path18" />
<path
d="M33.1371 19.9753L94.8574 104.92"
stroke="#4B6B6E"
id="path19" />
<path
d="M16.0354 41.0956L111.959 83.7998"
stroke="#4B6B6E"
id="path20" />
<path
d="M11.785 67.9372L116.209 56.9583"
stroke="#4B6B6E"
id="path21" />
<path
d="M21.5249 93.3078L106.47 31.5876"
stroke="#4B6B6E"
id="path22" />
<path
d="M42.6451 110.41L85.3494 14.4859"
stroke="#4B6B6E"
id="path23" />
<path
d="M53.0737 11.0433L74.9045 113.749"
stroke="#4B6B6E"
id="path24" />
<path
d="M28.8597 23.381L99.1184 101.411"
stroke="#4B6B6E"
id="path25" />
<path
d="M14.0586 46.1727L113.92 78.6194"
stroke="#4B6B6E"
id="path26" />
<path
d="M12.6364 73.3114L115.342 51.4807"
stroke="#4B6B6E"
id="path27" />
<path
d="M24.974 97.5254L103.004 27.2667"
stroke="#4B6B6E"
id="path28" />
<path
d="M47.7657 112.327L80.2125 12.4656"
stroke="#4B6B6E"
id="path29" />
<path
d="M47.7521 12.415L80.1989 112.276"
stroke="#4B6B6E"
id="path30" />
<path
d="M24.9604 27.2161L102.991 97.4749"
stroke="#4B6B6E"
id="path31" />
<path
d="M12.6228 51.4301L115.328 73.2609"
stroke="#4B6B6E"
id="path32" />
<path
d="M14.0451 78.5689L113.906 46.1221"
stroke="#4B6B6E"
id="path33" />
<path
d="M28.8462 101.361L99.1049 23.3304"
stroke="#4B6B6E"
id="path34" />
<path
d="M53.0602 113.698L74.8909 10.9928"
stroke="#4B6B6E"
id="path35" />
<path
d="M42.6031 14.3355L85.3105 110.258"
stroke="#4B6B6E"
id="path36" />
<path
d="M21.4834 31.4379L106.43 93.1554"
stroke="#4B6B6E"
id="path37" />
<path
d="M11.7444 56.8089L116.169 67.7844"
stroke="#4B6B6E"
id="path38" />
<path
d="M15.9956 83.6503L111.918 40.943"
stroke="#4B6B6E"
id="path39" />
<path
d="M33.0981 104.77L94.8155 19.8232"
stroke="#4B6B6E"
id="path40" />
<path
d="M58.4691 114.509L69.4446 10.0842"
stroke="#4B6B6E"
id="path41" />
</g>
</g>
</g>
<defs
id="defs63">
<filter
id="filter0_d_3_129"
x="0"
y="0"
width="129"
height="129"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood43" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix43" />
<feOffset
dx="1"
dy="2"
id="feOffset43" />
<feGaussianBlur
stdDeviation="1"
id="feGaussianBlur43" />
<feComposite
in2="hardAlpha"
operator="out"
id="feComposite43" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
id="feColorMatrix44" />
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_129"
id="feBlend44" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_129"
result="shape"
id="feBlend45" />
</filter>
<filter
id="filter1_i_3_129"
x="5"
y="4"
width="117"
height="117"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood45" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="BackgroundImageFix"
result="shape"
id="feBlend46" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix46" />
<feOffset
id="feOffset46" />
<feGaussianBlur
stdDeviation="1.5"
id="feGaussianBlur46" />
<feComposite
in2="hardAlpha"
operator="arithmetic"
k2="-1"
k3="1"
id="feComposite46" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"
id="feColorMatrix47" />
<feBlend
mode="normal"
in2="shape"
result="effect1_innerShadow_3_129"
id="feBlend47" />
</filter>
<filter
id="filter2_f_3_129"
x="6"
y="5"
width="115"
height="115"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood47" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="BackgroundImageFix"
result="shape"
id="feBlend48" />
<feGaussianBlur
stdDeviation="0.5"
result="effect1_foregroundBlur_3_129"
id="feGaussianBlur48" />
</filter>
<filter
id="filter3_di_3_129"
x="10.8921"
y="9.23197"
width="105.312"
height="105.68"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood48" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix48" />
<feOffset
dx="-0.8"
dy="-0.8"
id="feOffset48" />
<feComposite
in2="hardAlpha"
operator="out"
id="feComposite48" />
<feColorMatrix
type="matrix"
values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"
id="feColorMatrix49" />
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_129"
id="feBlend49" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_129"
result="shape"
id="feBlend50" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix50" />
<feOffset
dx="0.2"
dy="0.2"
id="feOffset50" />
<feGaussianBlur
stdDeviation="0.25"
id="feGaussianBlur50" />
<feComposite
in2="hardAlpha"
operator="arithmetic"
k2="-1"
k3="1"
id="feComposite50" />
<feColorMatrix
type="matrix"
values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"
id="feColorMatrix51" />
<feBlend
mode="normal"
in2="shape"
result="effect2_innerShadow_3_129"
id="feBlend51" />
</filter>
<linearGradient
id="paint0_linear_3_129"
x1="1.08514"
y1="50.7284"
x2="124.915"
y2="73.2716"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#F8FEFF"
id="stop51" />
<stop
offset="0.486626"
stop-color="#E1E3E7"
id="stop52" />
<stop
offset="0.782747"
stop-color="#C2C6C7"
id="stop53" />
</linearGradient>
<linearGradient
id="paint1_linear_3_129"
x1="19.5"
y1="18.5"
x2="107.5"
y2="106.5"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#E2EBEF"
id="stop54" />
<stop
offset="0.23"
stop-color="#ECF0F1"
id="stop55" />
<stop
offset="0.38"
stop-color="#D7E0E2"
id="stop56" />
<stop
offset="0.5"
stop-color="#CDD8DB"
id="stop57" />
<stop
offset="0.63"
stop-color="#D6DFE2"
id="stop58" />
<stop
offset="0.91"
stop-color="#FCFEFF"
id="stop59" />
</linearGradient>
<linearGradient
id="paint2_linear_3_129"
x1="19"
y1="18"
x2="89"
y2="88"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#26444E"
id="stop60" />
<stop
offset="0.5"
stop-color="#26444E"
stop-opacity="0"
id="stop61" />
</linearGradient>
<radialGradient
id="paint3_radial_3_129"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(62.5 61.5) rotate(45) scale(3.53553)">
<stop
offset="0.025"
stop-color="#579FA4"
id="stop62" />
<stop
offset="0.64"
stop-color="#213C3E"
id="stop63" />
</radialGradient>
<filter
id="filter1_df_3_182"
x="2"
y="2"
width="117.681"
height="97.7024"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood4" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix4" />
<feOffset
dy="4"
id="feOffset4" />
<feGaussianBlur
stdDeviation="1"
id="feGaussianBlur5" />
<feComposite
in2="hardAlpha"
operator="out"
id="feComposite5" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"
id="feColorMatrix5" />
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_182"
id="feBlend5" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_182"
result="shape"
id="feBlend6" />
<feGaussianBlur
stdDeviation="1"
result="effect2_foregroundBlur_3_182"
id="feGaussianBlur6" />
</filter>
<linearGradient
id="paint1_linear_3_182"
x1="37"
y1="10.5"
x2="67"
y2="72.5"
gradientUnits="userSpaceOnUse">
<stop
stop-color="white"
stop-opacity="0"
id="stop8" />
<stop
offset="1"
stop-color="white"
id="stop9" />
</linearGradient>
<filter
id="filter0_df_3_182"
x="2"
y="3"
width="114.604"
height="110.884"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood2" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix2" />
<feOffset
dy="4"
id="feOffset2" />
<feGaussianBlur
stdDeviation="1"
id="feGaussianBlur2" />
<feComposite
in2="hardAlpha"
operator="out"
id="feComposite2" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"
id="feColorMatrix3" />
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_182"
id="feBlend3" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_182"
result="shape"
id="feBlend4" />
<feGaussianBlur
stdDeviation="0.5"
result="effect2_foregroundBlur_3_182"
id="feGaussianBlur4" />
</filter>
<filter
id="filter1_df_3_182-3"
x="2"
y="2"
width="117.681"
height="97.7024"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood4-6" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix4-7" />
<feOffset
dy="4"
id="feOffset4-5" />
<feGaussianBlur
stdDeviation="1"
id="feGaussianBlur5-3" />
<feComposite
in2="hardAlpha"
operator="out"
id="feComposite5-5" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"
id="feColorMatrix5-6" />
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_182"
id="feBlend5-2" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_182"
result="shape"
id="feBlend6-9" />
<feGaussianBlur
stdDeviation="1"
result="effect2_foregroundBlur_3_182"
id="feGaussianBlur6-1" />
</filter>
<filter
id="filter0_df_3_182-0"
x="2"
y="3"
width="114.604"
height="110.884"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood2-9" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix2-3" />
<feOffset
dy="4"
id="feOffset2-6" />
<feGaussianBlur
stdDeviation="1"
id="feGaussianBlur2-0" />
<feComposite
in2="hardAlpha"
operator="out"
id="feComposite2-6" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"
id="feColorMatrix3-2" />
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_182"
id="feBlend3-6" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_182"
result="shape"
id="feBlend4-1" />
<feGaussianBlur
stdDeviation="0.5"
result="effect2_foregroundBlur_3_182"
id="feGaussianBlur4-8" />
</filter>
<linearGradient
inkscape:collect="always"
xlink:href="#paint1_linear_3_182"
id="linearGradient1"
gradientUnits="userSpaceOnUse"
x1="37"
y1="10.5"
x2="67"
y2="72.5" />
<linearGradient
inkscape:collect="always"
xlink:href="#paint1_linear_3_182"
id="linearGradient2"
gradientUnits="userSpaceOnUse"
x1="37"
y1="10.5"
x2="67"
y2="72.5" />
</defs>
<circle
cx="63.5"
cy="62.5"
r="2.5"
fill="url(#paint3_radial_3_129)"
id="clockdot" />
<g
id="clockshine">
<g
opacity="0.14"
filter="url(#filter0_df_3_182)"
id="g2"
style="filter:url(#filter0_df_3_182-0)">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 114.604,35.8755 C 98.6369,29.2336 73.1157,37.2154 52.1952,56.76 35.0872,72.7428 25.4849,92.3203 25.5839,107.884 12.4127,97.1568 4,80.8109 4,62.5 4,30.1913 30.1913,4 62.5,4 c 22.7201,0 42.415,12.9521 52.104,31.8755 z"
fill="url(#paint0_linear_3_182)"
shape-rendering="crispEdges"
id="path1-7"
style="fill:url(#linearGradient1)" />
</g>
<g
opacity="0.6"
filter="url(#filter1_df_3_182)"
id="g3-9"
style="filter:url(#filter1_df_3_182-3)">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 117.681,43.0287 C 104.615,41.2781 88.9173,42.3436 72.6911,46.6914 39.2424,55.6539 14.7141,75.572 13.0071,93.7024 7.30188,84.6718 4,73.9715 4,62.5 4,30.1913 30.1913,4 62.5,4 c 25.482,0 47.159,16.2924 55.181,39.0287 z"
fill="url(#paint1_linear_3_182)"
shape-rendering="crispEdges"
id="path2-2"
style="fill:url(#linearGradient2)" />
</g>
<rect
style="opacity:0;fill:#2c2c2c;stroke:#2c2c2c;stroke-width:0;stroke-opacity:0.984036"
id="rect5"
width="129"
height="129"
x="0"
y="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 12 KiB