initial commit

This commit is contained in:
2025-05-04 23:56:04 +02:00
commit 4e10b4d2c2
354 changed files with 53348 additions and 0 deletions

View File

@@ -0,0 +1,373 @@
/*
* 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.4
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.calendar 2.0 as PlasmaCalendar
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
Item {
id: calendar
Layout.minimumWidth: _minimumWidth
Layout.minimumHeight: _minimumHeight
// The "sensible" values
property int _minimumWidth: (showAgenda ? agendaViewWidth : 0) + monthViewWidth
property int _minimumHeight: units.gridUnit * 14
Layout.preferredWidth: _minimumWidth
Layout.preferredHeight: _minimumHeight * 1.5
readonly property bool showAgenda: PlasmaCalendar.EventPluginsManager.enabledPlugins.length > 0
readonly property int agendaViewWidth: _minimumHeight * 1.5
readonly property int monthViewWidth: monthView.showWeekNumbers ? Math.round(_minimumHeight * 1.75) : Math.round(_minimumHeight * 1.5)
property int boxWidth: (agendaViewWidth + monthViewWidth - ((showAgenda ? 3 : 4) * spacing)) / 2
property int spacing: 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();
}
Item {
id: agenda
visible: calendar.showAgenda
width: boxWidth
anchors {
top: parent.top
left: parent.left
bottom: parent.bottom
leftMargin: spacing
topMargin: spacing
bottomMargin: spacing
}
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
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
onAgendaUpdated: {
// 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
onEnabledCalendarPluginsChanged: {
PlasmaCalendar.EventPluginsManager.enabledPlugins = plasmoid.configuration.enabledCalendarPlugins;
}
}
Binding {
target: plasmoid
property: "hideOnWindowDeactivate"
value: !plasmoid.configuration.pin
}
PlasmaComponents.Label {
id: dayLabel
anchors.left: parent.left
height: dayHeading.height + dateHeading.height
width: paintedWidth
font.pixelSize: height
font.weight: Font.Light
text: agenda.dateString("dd")
opacity: 0.6
}
PlasmaExtras.Heading {
id: dayHeading
anchors {
top: parent.top
left: dayLabel.right
right: parent.right
leftMargin: spacing / 2
}
level: 1
elide: Text.ElideRight
text: agenda.dateString("dddd")
}
PlasmaComponents.Label {
id: dateHeading
anchors {
top: dayHeading.bottom
left: dayLabel.right
right: parent.right
leftMargin: spacing / 2
}
elide: Text.ElideRight
text: Qt.locale().standaloneMonthName(monthView.currentDate.getMonth())
+ agenda.dateString(" yyyy")
}
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: theme.defaultFont
text: timeString.length > dateString.length ? timeString : dateString
}
PlasmaExtras.ScrollArea {
id: holidaysView
anchors {
top: dateHeading.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
}
flickableItem.boundsBehavior: Flickable.StopAtBounds
ListView {
id: holidaysList
delegate: PlasmaComponents.ListItem {
id: eventItem
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 {
width: parent.width
height: eventGrid.height
active: eventTitle.truncated || eventDescription.truncated
mainText: active ? eventTitle.text : ""
subText: active ? eventDescription.text : ""
GridLayout {
id: eventGrid
columns: 3
rows: 2
rowSpacing: 0
columnSpacing: 2 * units.smallSpacing
width: parent.width
Rectangle {
id: eventColor
Layout.row: 0
Layout.column: 0
Layout.rowSpan: 2
Layout.fillHeight: true
color: modelData.eventColor
width: 5 * units.devicePixelRatio
visible: modelData.eventColor !== ""
}
PlasmaComponents.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
}
PlasmaComponents.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
}
PlasmaComponents.Label {
id: eventTitle
readonly property bool wrap: eventDescription.text === ""
Layout.row: 0
Layout.rowSpan: wrap ? 2 : 1
Layout.column: 2
Layout.fillWidth: true
font.weight: Font.Bold
elide: Text.ElideRight
text: modelData.title
verticalAlignment: Text.AlignVCenter
maximumLineCount: 2
wrapMode: wrap ? Text.Wrap : Text.NoWrap
}
PlasmaComponents.Label {
id: eventDescription
Layout.row: 1
Layout.column: 2
Layout.fillWidth: true
elide: Text.ElideRight
text: modelData.description
verticalAlignment: Text.AlignVCenter
enabled: false
visible: text !== ""
}
}
}
}
section.property: "modelData.eventType"
section.delegate: PlasmaExtras.Heading {
level: 3
elide: Text.ElideRight
text: section
}
}
}
PlasmaExtras.Heading {
anchors.fill: holidaysView
anchors.leftMargin: units.largeSpacing
anchors.rightMargin: units.largeSpacing
text: monthView.isToday(monthView.currentDate) ? i18n("No events for today")
: i18n("No events for this day");
level: 3
opacity: 0.4
visible: holidaysList.count == 0
}
}
Item {
id: cal
width: boxWidth
anchors {
top: parent.top
right: parent.right
bottom: parent.bottom
margins: spacing
}
PlasmaCalendar.MonthView {
id: monthView
borderOpacity: plasmoid.configuration.showBorders ? 0.25 : 0
today: root.tzDate
showWeekNumbers: plasmoid.configuration.showWeekNumbers
anchors.fill: parent
}
}
// Allows the user to keep the calendar open for reference
PlasmaComponents.ToolButton {
anchors.right: parent.right
width: Math.round(units.gridUnit * 1.25)
height: width
checkable: true
iconSource: "window-pin"
checked: plasmoid.configuration.pin
onCheckedChanged: plasmoid.configuration.pin = checked
tooltip: i18n("Keep Open")
}
}

View File

@@ -0,0 +1,283 @@
/*
* 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.components 2.0 as Components
import org.kde.plasma.private.digitalclock 1.0
Item {
id: main
Layout.fillHeight: true
Layout.fillWidth: false
Layout.minimumWidth: paintArea.width
Layout.maximumWidth: Layout.minimumWidth
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 bool showSeparator: plasmoid.configuration.showSeparator
property bool fixedFont: plasmoid.configuration.fixedFont
property var dateFormat: {
if (plasmoid.configuration.dateFormat === "customDate") {
return plasmoid.configuration.customDateFormat;
} else if (plasmoid.configuration.dateFormat === "longDate") {
return Qt.SystemLocaleLongDate;
} else if (plasmoid.configuration.dateFormat === "isoDate") {
return Qt.ISODate;
} else if (plasmoid.configuration.dateFormat === "qtDate") {
return Qt.TextDate;
} else if (plasmoid.configuration.dateFormat === "rfcDate") {
return Qt.RFC2822Date;
} else {
return Qt.SystemLocaleShortDate; }}
property string lastSelectedTimezone: plasmoid.configuration.lastSelectedTimezone
property bool displayTimezoneAsCode: plasmoid.configuration.displayTimezoneAsCode
property int use24hFormat: plasmoid.configuration.use24hFormat
property int fontSize: plasmoid.configuration.fontSize
property string lastDate: ""
property int tzOffset
property int tzIndex: 0
readonly property bool oneLineMode: plasmoid.formFactor == PlasmaCore.Types.Horizontal &&
main.height <= 2 * theme.smallestFont.pixelSize &&
(main.showDate || timezoneLabel.visible)
onDateFormatChanged: { setupLabels(); }
onDisplayTimezoneAsCodeChanged: { 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
onContextualActionsAboutToShow: {
ClipboardMenu.secondsIncluded = main.showSeconds;
ClipboardMenu.currentDate = main.currentTime; }}
Connections {
target: plasmoid.configuration
onSelectedTimeZonesChanged: {
var lastSelectedTimezone = plasmoid.configuration.lastSelectedTimezone;
if (plasmoid.configuration.selectedTimeZones.indexOf(lastSelectedTimezone) == -1) {
plasmoid.configuration.lastSelectedTimezone = plasmoid.configuration.selectedTimeZones[0]; }
setupLabels();
setTimezoneIndex(); }}
MouseArea {
id: mouseArea
property int wheelDelta: 0
anchors.fill: parent
onClicked: plasmoid.expanded = !plasmoid.expanded
onWheel: {
if (!plasmoid.configuration.wheelChangesTimezone) {
return; }
var delta = wheel.angleDelta.y || wheel.angleDelta.x
var newIndex = main.tzIndex;
wheelDelta += delta;
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(); }}}
property font font: Qt.font({
family: plasmoid.configuration.fontFamily || theme.defaultFont.family,
weight: plasmoid.configuration.boldText ? Font.Bold : theme.defaultFont.weight,
italic: plasmoid.configuration.italicText,
pixelSize: fixedFont ? fontSize : 1024 })
// -------------
// BEGIN VISIBLE
Row {
id: paintArea
spacing: plasmoid.configuration.customSpacing * 2
leftPadding: spacing
rightPadding: spacing
anchors {
centerIn: parent
horizontalCenterOffset: plasmoid.configuration.customOffsetX - 50
verticalCenterOffset: -plasmoid.configuration.customOffsetY
}
Components.Label {
id: dateLabel
height: timeLabel.height
width: dateLabel.paintedWidth
font: main.font
fontSizeMode: fixedFont ? Text.FixedSize : Text.VerticalFit
minimumPixelSize: 1
visible: main.showDate
}
Components.Label {
id: separator
height: timeLabel.height
width: separator.paintedWidth
font: main.font
fontSizeMode: fixedFont ? Text.FixedSize : Text.VerticalFit
minimumPixelSize: 1
transform: Translate { y: separator.paintedHeight / -15 }
visible: dateLabel.visible && plasmoid.configuration.showSeparator
text: "|"
}
Components.Label {
id: timeLabel
height: sizehelper.height
width: timeLabel.paintedWidth
font: main.font
fontSizeMode: fixedFont ? Text.FixedSize : Text.VerticalFit
minimumPixelSize: 1
text: {
var now = dataSource.data[plasmoid.configuration.lastSelectedTimezone]["DateTime"];
var msUTC = now.getTime() + (now.getTimezoneOffset() * 60000);
var currentTime = new Date(msUTC + (dataSource.data[plasmoid.configuration.lastSelectedTimezone]["Offset"] * 1000));
main.currentTime = currentTime;
return Qt.formatTime(currentTime, main.timeFormat); }
}
Components.Label {
id: timezoneLabel
height: timeLabel.height
width: timezoneLabel.paintedWidth
font: main.font
fontSizeMode: fixedFont ? Text.FixedSize : Text.VerticalFit
minimumPixelSize: 1
visible: text.length > 0
}
}
// ENDOF VISIBLE
Components.Label {
id: sizehelper
height: Math.min(main.height, 2.5 * theme.defaultFont.pixelSize)
font.family: timeLabel.font.family
font.weight: timeLabel.font.weight
font.italic: timeLabel.font.italic
font.pixelSize: fixedFont ? fontSize : 2.5 * theme.defaultFont.pixelSize
fontSizeMode: fixedFont ? Text.FixedSize : Text.VerticalFit
minimumPixelSize: 1
visible: false }
FontMetrics {
id: timeMetrics
font.family: timeLabel.font.family
font.weight: timeLabel.font.weight
font.italic: timeLabel.font.italic }
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;
var result = hours.toLowerCase() + delimiter + minutes;
if (main.showSeconds) {
result += delimiter + seconds; }
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 = "(" + timezoneString + ")";
} else { timezoneLabel.text = timezoneString; }
if (main.showDate) { dateLabel.text = Qt.formatDate(main.currentTime, main.dateFormat);
} else { dateLabel.text = ""; }
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; }}
var format = main.timeFormat.replace(/(h+|m+|s+)/g, "" + maximumWidthNumber + maximumWidthNumber); // make sure maximumWidthNumber is formatted as string
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);
if (advanceWidthAm > advanceWidthPm) { sizehelper.text = timeAm;
} else { sizehelper.text = timePm; }}
function dateTimeChanged() {
var doCorrections = false;
if (main.showDate) {
var currentDate = Qt.formatDateTime(dataSource.data["Local"]["DateTime"], "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(); }
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: {
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); }
}

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,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,346 @@
/*
* 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.0
import QtQuick.Controls 2.3 as QtControls
import QtQuick.Layouts 1.0 as QtLayouts
import org.kde.plasma.calendar 2.0 as PlasmaCalendar
import org.kde.kirigami 2.5 as Kirigami
QtLayouts.ColumnLayout {
id: appearancePage
signal configurationChanged
property string cfg_fontFamily
property string cfg_timeFormat: ""
property string cfg_dateFormat: "shortDate"
property alias cfg_boldText: boldCheckBox.checked
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 alias cfg_showSeparator: showSeparator.checked
property alias cfg_customDateFormat: customDateFormat.text
property alias cfg_use24hFormat: use24hFormat.checkState
property alias cfg_customSpacing: customSpacing.value
property alias cfg_fixedFont: fixedFont.checked
property alias cfg_fontSize: fontSize.value
property alias cfg_customOffsetY: customOffsetY.value
property alias cfg_customOffsetX: customOffsetX.value
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)
}
}
Kirigami.FormLayout {
QtLayouts.Layout.fillWidth: true
QtControls.CheckBox {
id: showDate
Kirigami.FormData.label: i18n("Information:")
text: i18n("Show date")
}
QtControls.CheckBox {
id: showSeparator
enabled: cfg_showDate
text: i18n("Show Separator")
}
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")
tristate: true
}
QtControls.CheckBox {
id: showLocalTimezone
text: i18n("Show local time zone")
}
QtControls.CheckBox {
id: fixedFont
text: i18n("Use fixed font size")
}
QtLayouts.RowLayout {
QtLayouts.Layout.fillWidth: true
Kirigami.FormData.label: i18n("Font Size:")
Kirigami.FormData.buddyFor: fontSize
QtControls.SpinBox {
id: fontSize
enabled: cfg_fixedFont
from: 1
to: 60
editable: true
validator: IntValidator {
locale: control.locale.name
bottom: Math.min(control.from, control.to)
top: Math.max(control.from, control.to)
}
}
}
Item {
Kirigami.FormData.isSection: true
}
QtLayouts.ColumnLayout {
Kirigami.FormData.label: i18n("Display time zone as:")
Kirigami.FormData.buddyFor: timezoneCityRadio
QtControls.RadioButton {
id: timezoneCityRadio
text: i18n("Time zone city")
}
QtControls.RadioButton {
id: timezoneCodeRadio
text: i18n("Time zone code")
}
}
Item {
Kirigami.FormData.isSection: true
}
QtControls.ComboBox {
id: dateFormat
Kirigami.FormData.label: i18n("Date format:")
enabled: showDate.checked
// QtLayouts.Layout.fillWidth: cfg_dateFormat == "customDate" ? true : false
QtLayouts.Layout.fillWidth: true
textRole: "label"
model: [
{
'label': i18n("Long Date"),
'name': "longDate"
},
{
'label': i18n("Short Date"),
'name': "shortDate"
},
{
'label': i18n("ISO Date"),
'name': "isoDate"
},
{
'label': i18n("Qt Date"),
'name': "qtDate"
},
{
'label': i18n("RFC Date"),
'name': "rfcDate"
},
{
'label': i18nc("custom date format", "Custom Date"),
'name': "customDate"
}
]
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;
}
}
}
}
QtControls.TextField {
id: customDateFormat
QtLayouts.Layout.fillWidth: true
visible: cfg_dateFormat == "customDate"
}
QtControls.Label {
text: i18n("<a href=\"http://doc.qt.io/qt-5/qml-qtqml-qt.html#formatDateTime-method\">Time Format Documentation</a>")
visible: cfg_dateFormat == "customDate"
wrapMode: Text.Wrap
onLinkActivated: Qt.openUrlExternally(link)
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton // We don't want to eat clicks on the Label
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
Item {
Kirigami.FormData.isSection: true
}
QtLayouts.RowLayout {
QtLayouts.Layout.fillWidth: true
Kirigami.FormData.label: i18n("Font style:")
QtControls.ComboBox {
id: fontFamilyComboBox
QtLayouts.Layout.fillWidth: true
currentIndex: 0
// ComboBox's sizing is just utterly broken
QtLayouts.Layout.minimumWidth: units.gridUnit * 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
QtControls.ToolTip {
text: i18n("Bold text")
}
icon.name: "format-text-bold"
checkable: true
Accessible.name: tooltip
}
QtControls.Button {
id: italicCheckBox
QtControls.ToolTip {
text: i18n("Italic text")
}
icon.name: "format-text-italic"
checkable: true
Accessible.name: tooltip
}
}
Item {
Kirigami.FormData.isSection: true
}
QtLayouts.RowLayout {
QtLayouts.Layout.fillWidth: true
Kirigami.FormData.label: i18n("Spacing:")
Kirigami.FormData.buddyFor: customSpacing
QtControls.Slider {
id: customSpacing
from: 0
to: 10
QtLayouts.Layout.fillWidth: true
}
QtControls.Button {
id: resetCustomSpacing
text: i18n("Reset")
onClicked: customSpacing.value = 1
}
}
QtLayouts.RowLayout {
QtLayouts.Layout.fillWidth: true
Kirigami.FormData.label: i18n("Vertical Offset:")
Kirigami.FormData.buddyFor: customOffsetY
QtControls.SpinBox {
id: customOffsetY
from: -10
to: 10
editable: true
validator: IntValidator {
locale: customOffsetY.locale.name
bottom: Math.min(customOffsetY.from, customOffsetY.to)
top: Math.max(customOffsetY.from, customOffsetY.to)
}
}
}
QtLayouts.RowLayout {
QtLayouts.Layout.fillWidth: true
Kirigami.FormData.label: i18n("Horizontal Offset:")
Kirigami.FormData.buddyFor: customOffsetX
QtControls.Slider {
id: customOffsetX
from: 0
to: 100
QtLayouts.Layout.fillWidth: true
}
QtControls.Button {
id: resetOffsetX
text: i18n("Reset")
onClicked: customOffsetX.value = 50
}
}
}
Item {
QtLayouts.Layout.fillHeight: true
}
Component.onCompleted: {
if (plasmoid.configuration.displayTimezoneAsCode) {
timezoneCodeRadio.checked = true;
} else {
timezoneCityRadio.checked = true;
}
}
}

View File

@@ -0,0 +1,93 @@
/*
* 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 2.4 as QtControls
import QtQuick.Layouts 1.0 as QtLayouts
import org.kde.plasma.calendar 2.0 as PlasmaCalendar
import org.kde.kirigami 2.5 as Kirigami
Item {
id: calendarPage
width: childrenRect.width
height: childrenRect.height
signal configurationChanged
property alias cfg_showWeekNumbers: showWeekNumbers.checked
function saveConfig()
{
plasmoid.configuration.enabledCalendarPlugins = PlasmaCalendar.EventPluginsManager.enabledPlugins;
}
Kirigami.FormLayout {
anchors {
left: parent.left
right: parent.right
}
QtControls.CheckBox {
id: showWeekNumbers
Kirigami.FormData.label: i18n("General:")
text: i18n("Show week numbers")
}
Item {
Kirigami.FormData.isSection: true
}
QtControls.CheckBox {
id: showBorders
Kirigami.FormData.label: i18n("Visuals:")
text: i18n("Show borders")
}
Item {
Kirigami.FormData.isSection: true
}
QtLayouts.ColumnLayout {
Kirigami.FormData.label: i18n("Available Plugins:")
Kirigami.FormData.buddyFor: children[1] // 0 is the Repeater
Repeater {
id: calendarPluginsRepeater
model: PlasmaCalendar.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: {
PlasmaCalendar.EventPluginsManager.populateEnabledPluginsList(plasmoid.configuration.enabledCalendarPlugins);
}
}

View File

@@ -0,0 +1,209 @@
/*
* Copyright 2013 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.0
import QtQuick.Controls 1.2 as QtControls
import QtQuick.Layouts 1.0
import QtQuick.Dialogs 1.1
import org.kde.plasma.private.digitalclock 1.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
Item {
id: timeZonesPage
width: parent.width
height: parent.height
property alias cfg_selectedTimeZones: timeZones.selectedTimeZones
property alias cfg_wheelChangesTimezone: enableWheelCheckBox.checked
TimeZoneModel {
id: timeZones
onSelectedTimeZonesChanged: {
if (selectedTimeZones.length == 0) {
messageWidget.visible = true;
timeZones.selectLocalTimeZone();
}
}
}
// This is just for getting the column width
QtControls.CheckBox {
id: checkbox
visible: false
}
ColumnLayout {
anchors.fill: parent
Rectangle {
id: messageWidget
anchors {
left: parent.left
right: parent.right
margins: 1
}
height: 0
//TODO: This is the actual color KMessageWidget uses as its base color but here it gives
// a different color, figure out why
//property color gradBaseColor: Qt.rgba(0.69, 0.5, 0, 1)
gradient: Gradient {
GradientStop { position: 0.0; color: "#FFD86D" } //Qt.lighter(messageWidget.gradBaseColor, 1.1)
GradientStop { position: 0.1; color: "#EAC360" } // messageWidget.gradBaseColor
GradientStop { position: 1.0; color: "#CAB064" } //Qt.darker(messageWidget.gradBaseColor, 1.1)
}
radius: 5
border.width: 1
border.color: "#79735B"
visible: false
Behavior on visible {
ParallelAnimation {
PropertyAnimation {
target: messageWidget
property: "opacity"
to: messageWidget.visible ? 0 : 1.0
easing.type: Easing.Linear
}
PropertyAnimation {
target: messageWidget
property: "Layout.minimumHeight"
to: messageWidget.visible ? 0 : messageWidgetLabel.height + (2 *units.largeSpacing)
easing.type: Easing.Linear
}
}
}
RowLayout {
anchors.fill: parent
anchors.margins: units.largeSpacing
anchors.leftMargin: units.smallSpacing
anchors.rightMargin: units.smallSpacing
spacing: units.smallSpacing
PlasmaCore.IconItem {
anchors.verticalCenter: parent.verticalCenter
height: units.iconSizes.smallMedium
width: height
source: "dialog-warning"
}
QtControls.Label {
id: messageWidgetLabel
anchors.verticalCenter: parent.verticalCenter
Layout.fillWidth: true
text: i18n("At least one time zone needs to be enabled. 'Local' was enabled automatically.")
verticalAlignment: Text.AlignVCenter
wrapMode: Text.WordWrap
}
PlasmaComponents.ToolButton {
anchors.verticalCenter: parent.verticalCenter
iconName: "dialog-close"
flat: true
onClicked: {
messageWidget.visible = false;
}
}
}
}
QtControls.TextField {
id: filter
Layout.fillWidth: true
placeholderText: i18n("Search Time Zones")
}
QtControls.TableView {
id: timeZoneView
signal toggleCurrent
Layout.fillWidth: true
Layout.fillHeight: true
Keys.onSpacePressed: toggleCurrent()
model: TimeZoneFilterProxy {
sourceModel: timeZones
filterString: filter.text
}
QtControls.TableViewColumn {
role: "checked"
width: checkbox.width
delegate:
QtControls.CheckBox {
id: checkBox
anchors.centerIn: parent
checked: styleData.value
activeFocusOnTab: false // only let the TableView as a whole get focus
onClicked: {
//needed for model's setData to be called
model.checked = checked;
}
Connections {
target: timeZoneView
onToggleCurrent: {
if (styleData.row === timeZoneView.currentRow) {
model.checked = !checkBox.checked
}
}
}
}
resizable: false
movable: false
}
QtControls.TableViewColumn {
role: "city"
title: i18n("City")
}
QtControls.TableViewColumn {
role: "region"
title: i18n("Region")
}
QtControls.TableViewColumn {
role: "comment"
title: i18n("Comment")
}
}
RowLayout {
Layout.fillWidth: true
QtControls.CheckBox {
id: enableWheelCheckBox
text: i18n("Switch time zone with mouse wheel")
}
}
}
}

View File

@@ -0,0 +1,117 @@
/*
* 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.0
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.components 2.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.kquickcontrolsaddons 2.0
import org.kde.plasma.private.digitalclock 1.0
import org.kde.kquickcontrolsaddons 2.0
import org.kde.plasma.calendar 2.0 as PlasmaCalendar
Item {
id: root
width: units.gridUnit * 10
height: units.gridUnit * 4
property string dateFormatString: setDateFormatString()
property date tzDate: {
// 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
return new Date(msUTC + (dataSource.data[plasmoid.configuration.lastSelectedTimezone]["Offset"] * 1000));
}
function initTimezones() {
var tz = Array()
if (plasmoid.configuration.selectedTimeZones.indexOf("Local") === -1) {
tz.push("Local");
}
root.allTimezones = tz.concat(plasmoid.configuration.selectedTimeZones);
}
Plasmoid.preferredRepresentation: Plasmoid.compactRepresentation
Plasmoid.compactRepresentation: DigitalClock { }
Plasmoid.fullRepresentation: CalendarView { }
Plasmoid.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"
}
//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
onSelectedTimeZonesChanged: root.initTimezones();
}
PlasmaCore.DataSource {
id: dataSource
engine: "time"
connectedSources: allTimezones
interval: plasmoid.configuration.showSeconds ? 1000 : 60000
intervalAlignment: plasmoid.configuration.showSeconds ? PlasmaCore.Types.NoAlignment : PlasmaCore.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;
}
function action_clockkcm() {
KCMShell.open("clock");
}
function action_formatskcm() {
KCMShell.open("formats");
}
Component.onCompleted: {
plasmoid.setAction("clipboard", i18n("Copy to Clipboard"), "edit-copy");
ClipboardMenu.setupMenu(plasmoid.action("clipboard"));
root.initTimezones();
if (KCMShell.authorize("clock.desktop").length > 0) {
plasmoid.setAction("clockkcm", i18n("Adjust Date and Time..."), "preferences-system-time");
}
if (KCMShell.authorize("formats.desktop").length > 0) {
plasmoid.setAction("formatskcm", i18n("Set Time Format..."));
}
// Set the list of enabled plugins from config
// to the manager
PlasmaCalendar.EventPluginsManager.enabledPlugins = plasmoid.configuration.enabledCalendarPlugins;
}
}