Warning, /plasma/plasma-workspace/applets/digital-clock/package/contents/ui/DigitalClock.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 SPDX-FileCopyrightText: 2013 Heena Mahour <heena393@gmail.com> 0003 SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org> 0004 SPDX-FileCopyrightText: 2013 Martin Klapetek <mklapetek@kde.org> 0005 SPDX-FileCopyrightText: 2014 David Edmundson <davidedmundson@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 import QtQuick 0011 import QtQuick.Layouts 1.1 0012 import QtQuick.Window 2.2 0013 import org.kde.plasma.plasmoid 2.0 0014 import org.kde.plasma.core as PlasmaCore 0015 import org.kde.plasma.components 3.0 as Components 0016 import org.kde.plasma.private.digitalclock 1.0 0017 import org.kde.kirigami 2.20 as Kirigami 0018 0019 MouseArea { 0020 id: main 0021 objectName: "digital-clock-compactrepresentation" 0022 0023 property string timeFormat 0024 property string timeFormatWithSeconds 0025 0026 property bool showLocalTimezone: Plasmoid.configuration.showLocalTimezone 0027 property bool showDate: Plasmoid.configuration.showDate 0028 property bool localizeDate: Plasmoid.configuration.dateFormat === "longDate" || Plasmoid.configuration.dateFormat === "shortDate" 0029 property var dateFormat: { 0030 if (Plasmoid.configuration.dateFormat === "custom") { 0031 return Plasmoid.configuration.customDateFormat; // str 0032 } else if (Plasmoid.configuration.dateFormat === "longDate") { 0033 return Locale.LongFormat; // int 0034 } else if (Plasmoid.configuration.dateFormat === "isoDate") { 0035 return Qt.ISODate; // int 0036 } else { // "shortDate" 0037 return Locale.ShortFormat; // int 0038 } 0039 } 0040 0041 property string lastSelectedTimezone: Plasmoid.configuration.lastSelectedTimezone 0042 property int displayTimezoneFormat: Plasmoid.configuration.displayTimezoneFormat 0043 property int use24hFormat: Plasmoid.configuration.use24hFormat 0044 0045 property string lastDate: "" 0046 property int tzOffset 0047 0048 // This is the index in the list of user selected timezones 0049 property int tzIndex: 0 0050 0051 // if showing the date and the time in one line or 0052 // if the date/timezone cannot be fit with the smallest font to its designated space 0053 property bool oneLineMode: { 0054 if (Plasmoid.configuration.dateDisplayFormat === 1) { 0055 // BesideTime 0056 return true; 0057 } else if (Plasmoid.configuration.dateDisplayFormat === 2) { 0058 // BelowTime 0059 return false; 0060 } else { 0061 // Adaptive 0062 return Plasmoid.formFactor === PlasmaCore.Types.Horizontal && 0063 main.height <= 2 * Kirigami.Theme.smallFont.pixelSize && 0064 (main.showDate || timezoneLabel.visible); 0065 } 0066 } 0067 0068 property bool wasExpanded 0069 property int wheelDelta: 0 0070 0071 Accessible.role: Accessible.Button 0072 Accessible.onPressAction: main.clicked(null) 0073 0074 onDateFormatChanged: { 0075 setupLabels(); 0076 } 0077 0078 onDisplayTimezoneFormatChanged: { setupLabels(); } 0079 onStateChanged: { setupLabels(); } 0080 0081 onLastSelectedTimezoneChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) } 0082 onShowLocalTimezoneChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) } 0083 onShowDateChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) } 0084 onUse24hFormatChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) } 0085 0086 Connections { 0087 target: Plasmoid 0088 function onContextualActionsAboutToShow() { 0089 ClipboardMenu.secondsIncluded = (Plasmoid.configuration.showSeconds === 2); 0090 ClipboardMenu.currentDate = main.getCurrentTime(); 0091 } 0092 } 0093 0094 Connections { 0095 target: Plasmoid.configuration 0096 function onSelectedTimeZonesChanged() { 0097 // If the currently selected timezone was removed, 0098 // default to the first one in the list 0099 const lastSelectedTimezone = Plasmoid.configuration.lastSelectedTimezone; 0100 if (Plasmoid.configuration.selectedTimeZones.indexOf(lastSelectedTimezone) === -1) { 0101 Plasmoid.configuration.lastSelectedTimezone = Plasmoid.configuration.selectedTimeZones[0]; 0102 } 0103 0104 setupLabels(); 0105 setTimezoneIndex(); 0106 } 0107 } 0108 0109 function getCurrentTime() { 0110 // get the time for the given timezone from the dataengine 0111 var now = dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["DateTime"]; 0112 // get current UTC time 0113 var msUTC = now.getTime() + (now.getTimezoneOffset() * 60000); 0114 // add the dataengine TZ offset to it 0115 var currentTime = new Date(msUTC + (dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Offset"] * 1000)); 0116 return currentTime; 0117 } 0118 0119 function pointToPixel(pointSize) { 0120 var pixelsPerInch = Screen.pixelDensity * 25.4 0121 return Math.round(pointSize / 72 * pixelsPerInch) 0122 } 0123 0124 states: [ 0125 State { 0126 name: "horizontalPanel" 0127 when: Plasmoid.formFactor === PlasmaCore.Types.Horizontal && !main.oneLineMode 0128 0129 PropertyChanges { 0130 target: main 0131 Layout.fillHeight: true 0132 Layout.fillWidth: false 0133 Layout.minimumWidth: contentItem.width 0134 Layout.maximumWidth: Layout.minimumWidth 0135 } 0136 0137 PropertyChanges { 0138 target: contentItem 0139 0140 height: timeLabel.height + (main.showDate || timezoneLabel.visible ? 0.8 * timeLabel.height : 0) 0141 width: Math.max(timeLabel.width + (main.showDate ? timezoneLabel.paintedWidth : 0), 0142 timezoneLabel.paintedWidth, dateLabel.paintedWidth) + Kirigami.Units.largeSpacing 0143 } 0144 0145 PropertyChanges { 0146 target: labelsGrid 0147 0148 rows: main.showDate ? 1 : 2 0149 } 0150 0151 AnchorChanges { 0152 target: labelsGrid 0153 0154 anchors.horizontalCenter: contentItem.horizontalCenter 0155 } 0156 0157 PropertyChanges { 0158 target: timeLabel 0159 0160 height: sizehelper.height 0161 width: timeLabel.paintedWidth 0162 0163 font.pixelSize: timeLabel.height 0164 } 0165 0166 PropertyChanges { 0167 target: timezoneLabel 0168 0169 height: main.showDate ? 0.7 * timeLabel.height : 0.8 * timeLabel.height 0170 width: main.showDate ? timezoneLabel.paintedWidth : timeLabel.width 0171 0172 font.pixelSize: timezoneLabel.height 0173 } 0174 0175 PropertyChanges { 0176 target: dateLabel 0177 0178 height: 0.8 * timeLabel.height 0179 width: dateLabel.paintedWidth 0180 verticalAlignment: Text.AlignVCenter 0181 0182 font.pixelSize: dateLabel.height 0183 } 0184 0185 AnchorChanges { 0186 target: dateLabel 0187 0188 anchors.top: labelsGrid.bottom 0189 anchors.horizontalCenter: labelsGrid.horizontalCenter 0190 } 0191 0192 PropertyChanges { 0193 target: sizehelper 0194 0195 /* 0196 * The value 0.71 was picked by testing to give the clock the right 0197 * size (aligned with tray icons). 0198 * Value 0.56 seems to be chosen rather arbitrary as well such that 0199 * the time label is slightly larger than the date or timezone label 0200 * and still fits well into the panel with all the applied margins. 0201 */ 0202 height: Math.min(main.showDate || timezoneLabel.visible ? main.height * 0.56 : main.height * 0.71, 0203 fontHelper.font.pixelSize) 0204 0205 font.pixelSize: sizehelper.height 0206 } 0207 }, 0208 0209 State { 0210 name: "oneLineDate" 0211 // the one-line mode has no effect on a vertical panel because it would never fit 0212 when: Plasmoid.formFactor !== PlasmaCore.Types.Vertical && main.oneLineMode 0213 0214 PropertyChanges { 0215 target: main 0216 Layout.fillHeight: true 0217 Layout.fillWidth: false 0218 Layout.minimumWidth: contentItem.width 0219 Layout.maximumWidth: Layout.minimumWidth 0220 0221 } 0222 0223 PropertyChanges { 0224 target: contentItem 0225 0226 height: sizehelper.height 0227 width: dateLabel.width + dateLabel.anchors.rightMargin + labelsGrid.width 0228 } 0229 0230 AnchorChanges { 0231 target: labelsGrid 0232 0233 anchors.right: contentItem.right 0234 } 0235 0236 PropertyChanges { 0237 target: dateLabel 0238 0239 height: timeLabel.height 0240 width: dateLabel.paintedWidth 0241 0242 font.pixelSize: 1024 0243 verticalAlignment: Text.AlignVCenter 0244 anchors.rightMargin: labelsGrid.columnSpacing 0245 0246 fontSizeMode: Text.VerticalFit 0247 } 0248 0249 AnchorChanges { 0250 target: dateLabel 0251 0252 anchors.right: labelsGrid.left 0253 anchors.verticalCenter: labelsGrid.verticalCenter 0254 } 0255 0256 PropertyChanges { 0257 target: timeLabel 0258 0259 height: sizehelper.height 0260 width: timeLabel.paintedWidth 0261 0262 fontSizeMode: Text.VerticalFit 0263 } 0264 0265 PropertyChanges { 0266 target: timezoneLabel 0267 0268 height: 0.7 * timeLabel.height 0269 width: timezoneLabel.paintedWidth 0270 0271 fontSizeMode: Text.VerticalFit 0272 horizontalAlignment: Text.AlignHCenter 0273 } 0274 0275 PropertyChanges { 0276 target: sizehelper 0277 0278 height: Math.min(main.height, fontHelper.contentHeight) 0279 0280 fontSizeMode: Text.VerticalFit 0281 font.pixelSize: fontHelper.font.pixelSize 0282 } 0283 }, 0284 0285 State { 0286 name: "verticalPanel" 0287 when: Plasmoid.formFactor === PlasmaCore.Types.Vertical 0288 0289 PropertyChanges { 0290 target: main 0291 Layout.fillHeight: false 0292 Layout.fillWidth: true 0293 Layout.maximumHeight: contentItem.height 0294 Layout.minimumHeight: Layout.maximumHeight 0295 } 0296 0297 PropertyChanges { 0298 target: contentItem 0299 0300 height: main.showDate ? labelsGrid.height + dateLabel.contentHeight : labelsGrid.height 0301 width: main.width 0302 } 0303 0304 PropertyChanges { 0305 target: labelsGrid 0306 0307 rows: 2 0308 } 0309 0310 PropertyChanges { 0311 target: timeLabel 0312 0313 height: sizehelper.contentHeight 0314 width: main.width 0315 0316 font.pixelSize: Math.min(timeLabel.height, fontHelper.font.pixelSize) 0317 fontSizeMode: Text.VerticalFit 0318 } 0319 0320 PropertyChanges { 0321 target: timezoneLabel 0322 0323 height: Math.max(0.7 * timeLabel.height, minimumPixelSize) 0324 width: main.width 0325 0326 fontSizeMode: Text.Fit 0327 minimumPixelSize: dateLabel.minimumPixelSize 0328 elide: Text.ElideRight 0329 } 0330 0331 PropertyChanges { 0332 target: dateLabel 0333 0334 width: main.width 0335 //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 0336 height: Kirigami.Units.gridUnit * 10 0337 0338 fontSizeMode: Text.Fit 0339 verticalAlignment: Text.AlignTop 0340 // Those magic numbers are purely what looks nice as maximum size, here we have it the smallest 0341 // between slightly bigger than the default font (1.4 times) and a bit smaller than the time font 0342 font.pixelSize: Math.min(0.7 * timeLabel.height, Kirigami.Theme.defaultFont.pixelSize * 1.4) 0343 elide: Text.ElideRight 0344 wrapMode: Text.WordWrap 0345 } 0346 0347 AnchorChanges { 0348 target: dateLabel 0349 0350 anchors.top: labelsGrid.bottom 0351 anchors.horizontalCenter: labelsGrid.horizontalCenter 0352 } 0353 0354 PropertyChanges { 0355 target: sizehelper 0356 0357 width: main.width 0358 0359 fontSizeMode: Text.HorizontalFit 0360 font.pixelSize: fontHelper.font.pixelSize 0361 } 0362 }, 0363 0364 State { 0365 name: "other" 0366 when: Plasmoid.formFactor !== PlasmaCore.Types.Vertical && Plasmoid.formFactor !== PlasmaCore.Types.Horizontal 0367 0368 PropertyChanges { 0369 target: main 0370 Layout.fillHeight: false 0371 Layout.fillWidth: false 0372 Layout.minimumWidth: Kirigami.Units.gridUnit * 3 0373 Layout.minimumHeight: Kirigami.Units.gridUnit * 3 0374 } 0375 0376 PropertyChanges { 0377 target: contentItem 0378 0379 height: main.height 0380 width: main.width 0381 } 0382 0383 PropertyChanges { 0384 target: labelsGrid 0385 0386 rows: 2 0387 } 0388 0389 PropertyChanges { 0390 target: timeLabel 0391 0392 height: sizehelper.height 0393 width: main.width 0394 0395 fontSizeMode: Text.Fit 0396 } 0397 0398 PropertyChanges { 0399 target: timezoneLabel 0400 0401 height: 0.7 * timeLabel.height 0402 width: main.width 0403 0404 fontSizeMode: Text.Fit 0405 minimumPixelSize: 1 0406 } 0407 0408 PropertyChanges { 0409 target: dateLabel 0410 0411 height: 0.7 * timeLabel.height 0412 font.pixelSize: 1024 0413 width: Math.max(timeLabel.contentWidth, Kirigami.Units.gridUnit * 3) 0414 verticalAlignment: Text.AlignVCenter 0415 0416 fontSizeMode: Text.Fit 0417 minimumPixelSize: 1 0418 wrapMode: Text.WordWrap 0419 } 0420 0421 AnchorChanges { 0422 target: dateLabel 0423 0424 anchors.top: labelsGrid.bottom 0425 anchors.horizontalCenter: labelsGrid.horizontalCenter 0426 } 0427 0428 PropertyChanges { 0429 target: sizehelper 0430 0431 height: { 0432 if (main.showDate) { 0433 if (timezoneLabel.visible) { 0434 return 0.4 * main.height 0435 } 0436 return 0.56 * main.height 0437 } else if (timezoneLabel.visible) { 0438 return 0.59 * main.height 0439 } 0440 return main.height 0441 } 0442 width: main.width 0443 0444 fontSizeMode: Text.Fit 0445 font.pixelSize: 1024 0446 } 0447 } 0448 ] 0449 0450 onPressed: wasExpanded = root.expanded 0451 onClicked: root.expanded = !wasExpanded 0452 onWheel: wheel => { 0453 if (!Plasmoid.configuration.wheelChangesTimezone) { 0454 return; 0455 } 0456 0457 var delta = (wheel.inverted ? -1 : 1) * (wheel.angleDelta.y ? wheel.angleDelta.y : wheel.angleDelta.x); 0458 var newIndex = main.tzIndex; 0459 wheelDelta += delta; 0460 // magic number 120 for common "one click" 0461 // See: https://doc.qt.io/qt-5/qml-qtquick-wheelevent.html#angleDelta-prop 0462 while (wheelDelta >= 120) { 0463 wheelDelta -= 120; 0464 newIndex--; 0465 } 0466 while (wheelDelta <= -120) { 0467 wheelDelta += 120; 0468 newIndex++; 0469 } 0470 0471 if (newIndex >= Plasmoid.configuration.selectedTimeZones.length) { 0472 newIndex = 0; 0473 } else if (newIndex < 0) { 0474 newIndex = Plasmoid.configuration.selectedTimeZones.length - 1; 0475 } 0476 0477 if (newIndex !== main.tzIndex) { 0478 Plasmoid.configuration.lastSelectedTimezone = Plasmoid.configuration.selectedTimeZones[newIndex]; 0479 main.tzIndex = newIndex; 0480 0481 dataSource.dataChanged(); 0482 setupLabels(); 0483 } 0484 } 0485 0486 /* 0487 * Visible elements 0488 * 0489 */ 0490 Item { 0491 id: contentItem 0492 anchors.verticalCenter: main.verticalCenter 0493 0494 Grid { 0495 id: labelsGrid 0496 0497 rows: 1 0498 horizontalItemAlignment: Grid.AlignHCenter 0499 verticalItemAlignment: Grid.AlignVCenter 0500 0501 flow: Grid.TopToBottom 0502 columnSpacing: Kirigami.Units.smallSpacing 0503 0504 Components.Label { 0505 id: timeLabel 0506 0507 font { 0508 family: fontHelper.font.family 0509 weight: fontHelper.font.weight 0510 italic: fontHelper.font.italic 0511 pixelSize: 1024 0512 pointSize: -1 // Because we're setting the pixel size instead 0513 // TODO: remove once this label is ported to PC3 0514 } 0515 minimumPixelSize: 1 0516 0517 text: Qt.formatTime(main.getCurrentTime(), Plasmoid.configuration.showSeconds === 2 ? main.timeFormatWithSeconds : main.timeFormat) 0518 textFormat: Text.PlainText 0519 0520 verticalAlignment: Text.AlignVCenter 0521 horizontalAlignment: Text.AlignHCenter 0522 } 0523 0524 Components.Label { 0525 id: timezoneLabel 0526 0527 font.weight: timeLabel.font.weight 0528 font.italic: timeLabel.font.italic 0529 font.pixelSize: 1024 0530 font.pointSize: -1 // Because we're setting the pixel size instead 0531 // TODO: remove once this label is ported to PC3 0532 minimumPixelSize: 1 0533 0534 visible: text.length > 0 0535 horizontalAlignment: Text.AlignHCenter 0536 verticalAlignment: Text.AlignVCenter 0537 textFormat: Text.PlainText 0538 } 0539 } 0540 0541 Components.Label { 0542 id: dateLabel 0543 0544 visible: main.showDate 0545 0546 font.family: timeLabel.font.family 0547 font.weight: timeLabel.font.weight 0548 font.italic: timeLabel.font.italic 0549 font.pixelSize: 1024 0550 font.pointSize: -1 // Because we're setting the pixel size instead 0551 // TODO: remove once this label is ported to PC3 0552 minimumPixelSize: 1 0553 0554 horizontalAlignment: Text.AlignHCenter 0555 verticalAlignment: Text.AlignVCenter 0556 textFormat: Text.PlainText 0557 } 0558 } 0559 /* 0560 * end: Visible Elements 0561 * 0562 */ 0563 0564 Components.Label { 0565 id: sizehelper 0566 0567 font.family: timeLabel.font.family 0568 font.weight: timeLabel.font.weight 0569 font.italic: timeLabel.font.italic 0570 minimumPixelSize: 1 0571 0572 visible: false 0573 textFormat: Text.PlainText 0574 } 0575 0576 // To measure Label.height for maximum-sized font in VerticalFit mode 0577 Components.Label { 0578 id: fontHelper 0579 0580 height: 1024 0581 0582 font.family: (Plasmoid.configuration.autoFontAndSize || Plasmoid.configuration.fontFamily.length === 0) ? Kirigami.Theme.defaultFont.family : Plasmoid.configuration.fontFamily 0583 font.weight: Plasmoid.configuration.autoFontAndSize ? Kirigami.Theme.defaultFont.weight : Plasmoid.configuration.fontWeight 0584 font.italic: Plasmoid.configuration.autoFontAndSize ? Kirigami.Theme.defaultFont.italic : Plasmoid.configuration.italicText 0585 font.pixelSize: Plasmoid.configuration.autoFontAndSize ? 3 * Kirigami.Theme.defaultFont.pixelSize : pointToPixel(Plasmoid.configuration.fontSize) 0586 font.pointSize: -1 0587 fontSizeMode: Text.VerticalFit 0588 0589 visible: false 0590 textFormat: Text.PlainText 0591 } 0592 0593 FontMetrics { 0594 id: timeMetrics 0595 0596 font.family: timeLabel.font.family 0597 font.weight: timeLabel.font.weight 0598 font.italic: timeLabel.font.italic 0599 } 0600 0601 // Qt's QLocale does not offer any modular time creating like Klocale did 0602 // eg. no "gimme time with seconds" or "gimme time without seconds and with timezone". 0603 // QLocale supports only two formats - Long and Short. Long is unusable in many situations 0604 // and Short does not provide seconds. So if seconds are enabled, we need to add it here. 0605 // 0606 // What happens here is that it looks for the delimiter between "h" and "m", takes it 0607 // and appends it after "mm" and then appends "ss" for the seconds. 0608 function timeFormatCorrection(timeFormatString) { 0609 const regexp = /(hh*)(.+)(mm)/i 0610 const match = regexp.exec(timeFormatString); 0611 0612 const hours = match[1]; 0613 const delimiter = match[2]; 0614 const minutes = match[3] 0615 const seconds = "ss"; 0616 const amPm = "AP"; 0617 const uses24hFormatByDefault = timeFormatString.toLowerCase().indexOf("ap") === -1; 0618 0619 // because QLocale is incredibly stupid and does not convert 12h/24h clock format 0620 // when uppercase H is used for hours, needs to be h or hh, so toLowerCase() 0621 let result = hours.toLowerCase() + delimiter + minutes; 0622 0623 let result_sec = result + delimiter + seconds; 0624 0625 // add "AM/PM" either if the setting is the default and locale uses it OR if the user unchecked "use 24h format" 0626 if ((main.use24hFormat == Qt.PartiallyChecked && !uses24hFormatByDefault) || main.use24hFormat == Qt.Unchecked) { 0627 result += " " + amPm; 0628 result_sec += " " + amPm; 0629 } 0630 0631 main.timeFormat = result; 0632 main.timeFormatWithSeconds = result_sec; 0633 setupLabels(); 0634 } 0635 0636 function setupLabels() { 0637 const showTimezone = main.showLocalTimezone || (Plasmoid.configuration.lastSelectedTimezone !== "Local" 0638 && dataSource.data["Local"]["Timezone City"] !== dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Timezone City"]); 0639 0640 let timezoneString = ""; 0641 0642 if (showTimezone) { 0643 // format timezone as tz code, city or UTC offset 0644 if (displayTimezoneFormat === 0) { 0645 timezoneString = dataSource.data[lastSelectedTimezone]["Timezone Abbreviation"] 0646 } else if (displayTimezoneFormat === 1) { 0647 timezoneString = TimezonesI18n.i18nCity(dataSource.data[lastSelectedTimezone]["Timezone"]); 0648 } else if (displayTimezoneFormat === 2) { 0649 const lastOffset = dataSource.data[lastSelectedTimezone]["Offset"]; 0650 const symbol = lastOffset > 0 ? '+' : ''; 0651 const hours = Math.floor(lastOffset / 3600); 0652 const minutes = Math.floor(lastOffset % 3600 / 60); 0653 0654 timezoneString = "UTC" + symbol + hours.toString().padStart(2, '0') + ":" + minutes.toString().padStart(2, '0'); 0655 } 0656 0657 timezoneLabel.text = (main.showDate || main.oneLineMode) && Plasmoid.formFactor === PlasmaCore.Types.Horizontal ? "(" + timezoneString + ")" : timezoneString; 0658 } else { 0659 // this clears the label and that makes it hidden 0660 timezoneLabel.text = timezoneString; 0661 } 0662 0663 if (main.showDate) { 0664 if (main.localizeDate) { 0665 dateLabel.text = Qt.formatDate(main.getCurrentTime(), Qt.locale(), main.dateFormat); 0666 } else { 0667 dateLabel.text = Qt.formatDate(main.getCurrentTime(), main.dateFormat); 0668 } 0669 } else { 0670 // clear it so it doesn't take space in the layout 0671 dateLabel.text = ""; 0672 } 0673 0674 // find widest character between 0 and 9 0675 let maximumWidthNumber = 0; 0676 let maximumAdvanceWidth = 0; 0677 for (let i = 0; i <= 9; i++) { 0678 const advanceWidth = timeMetrics.advanceWidth(i); 0679 if (advanceWidth > maximumAdvanceWidth) { 0680 maximumAdvanceWidth = advanceWidth; 0681 maximumWidthNumber = i; 0682 } 0683 } 0684 // replace all placeholders with the widest number (two digits) 0685 const format = main.timeFormat.replace(/(h+|m+|s+)/g, "" + maximumWidthNumber + maximumWidthNumber); // make sure maximumWidthNumber is formatted as string 0686 // build the time string twice, once with an AM time and once with a PM time 0687 const date = new Date(2000, 0, 1, 1, 0, 0); 0688 const timeAm = Qt.formatTime(date, format); 0689 const advanceWidthAm = timeMetrics.advanceWidth(timeAm); 0690 date.setHours(13); 0691 const timePm = Qt.formatTime(date, format); 0692 const advanceWidthPm = timeMetrics.advanceWidth(timePm); 0693 // set the sizehelper's text to the widest time string 0694 if (advanceWidthAm > advanceWidthPm) { 0695 sizehelper.text = timeAm; 0696 } else { 0697 sizehelper.text = timePm; 0698 } 0699 fontHelper.text = sizehelper.text 0700 } 0701 0702 function dateTimeChanged() { 0703 let doCorrections = false; 0704 0705 if (main.showDate) { 0706 // If the date has changed, force size recalculation, because the day name 0707 // or the month name can now be longer/shorter, so we need to adjust applet size 0708 const currentDate = Qt.formatDateTime(main.getCurrentTime(), "yyyy-MM-dd"); 0709 if (main.lastDate !== currentDate) { 0710 doCorrections = true; 0711 main.lastDate = currentDate 0712 } 0713 } 0714 0715 const currentTZOffset = dataSource.data["Local"]["Offset"] / 60; 0716 if (currentTZOffset !== tzOffset) { 0717 doCorrections = true; 0718 tzOffset = currentTZOffset; 0719 Date.timeZoneUpdated(); // inform the QML JS engine about TZ change 0720 } 0721 0722 if (doCorrections) { 0723 timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)); 0724 } 0725 } 0726 0727 function setTimezoneIndex() { 0728 main.tzIndex = Plasmoid.configuration.selectedTimeZones.indexOf(Plasmoid.configuration.lastSelectedTimezone); 0729 } 0730 0731 Component.onCompleted: { 0732 // Sort the timezones according to their offset 0733 // Calling sort() directly on Plasmoid.configuration.selectedTimeZones 0734 // has no effect, so sort a copy and then assign the copy to it 0735 const sortedTimeZones = Plasmoid.configuration.selectedTimeZones; 0736 const byOffset = (a, b) => dataSource.data[a]["Offset"] - dataSource.data[b]["Offset"]; 0737 sortedTimeZones.sort(byOffset); 0738 Plasmoid.configuration.selectedTimeZones = sortedTimeZones; 0739 0740 setTimezoneIndex(); 0741 tzOffset = -(new Date().getTimezoneOffset()); 0742 dateTimeChanged(); 0743 timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)); 0744 dataSource.onDataChanged.connect(dateTimeChanged); 0745 } 0746 }