Redesign the Plasma Calendar applet

* Visually this removes the lines between the day delegates in the calendar
and make it use the correct highlighting component
* Use a SwipeView for switching between the month, year, and decade view
* Makes the header optional
* Improves the documentation of the MonthView

This patch is explicitely licensed under LGPL-2.0-or-later
This commit is contained in:
Carl Schwan 2021-04-23 17:35:27 +00:00
parent 799121e70b
commit 103d8b539a
5 changed files with 293 additions and 404 deletions

View File

@ -2,17 +2,21 @@
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.0
import org.kde.plasma.calendar 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as Components
import org.kde.plasma.components 2.0 as PlasmaComponents2 // For Highlight
import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.calendar 2.0
MouseArea {
PlasmaComponents3.AbstractButton {
id: dayStyle
hoverEnabled: true
@ -21,8 +25,8 @@ MouseArea {
readonly property date thisDate: new Date(yearNumber, typeof monthNumber !== "undefined" ? monthNumber - 1 : 0, typeof dayNumber !== "undefined" ? dayNumber : 1)
readonly property bool today: {
var today = root.today;
var result = true;
const today = root.today;
let result = true;
if (dateMatchingPrecision >= Calendar.MatchYear) {
result = result && today.getFullYear() === thisDate.getFullYear()
}
@ -35,8 +39,8 @@ MouseArea {
return result
}
readonly property bool selected: {
var current = root.currentDate;
var result = true;
const current = root.currentDate;
let result = true;
if (dateMatchingPrecision >= Calendar.MatchYear) {
result = result && current.getFullYear() === thisDate.getFullYear()
}
@ -49,43 +53,19 @@ MouseArea {
return result
}
onHeightChanged: {
// this is needed here as the text is first rendered, counting with the default root.cellHeight
// then root.cellHeight actually changes to whatever it should be, but the Label does not pick
// it up after that, so we need to change it explicitly after the cell size changes
label.font.pixelSize = Math.max(PlasmaCore.Theme.smallestFont.pixelSize, Math.floor(daysCalendar.cellHeight / 3))
}
Rectangle {
PlasmaComponents2.Highlight {
id: todayRect
anchors.fill: parent
opacity: {
if (selected && today) {
0.6
} else if (today) {
0.4
} else {
0
if (today) {
return 1;
} else if (selected) {
return 0.6;
} else if (dayStyle.hovered) {
return 0.3;
}
return 0;
}
color: PlasmaCore.Theme.textColor
}
Rectangle {
id: highlightDate
anchors.fill: todayRect
opacity: {
if (selected) {
0.6
} else if (dayStyle.containsMouse) {
0.4
} else {
0
}
}
visible: !today
color: PlasmaCore.Theme.highlightColor
z: todayRect.z - 1
}
Loader {
@ -97,12 +77,8 @@ MouseArea {
sourceComponent: eventsMarkerComponent
}
Components.Label {
contentItem: PlasmaExtras.Heading {
id: label
anchors {
fill: todayRect
margins: PlasmaCore.Units.smallSpacing
}
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: model.label || dayNumber
@ -110,11 +86,5 @@ MouseArea {
wrapMode: Text.NoWrap
elide: Text.ElideRight
fontSizeMode: Text.HorizontalFit
font.pixelSize: Math.max(PlasmaCore.Theme.smallestFont.pixelSize, Math.floor(daysCalendar.cellHeight / 3))
// Plasma component set point size, this code wants to set pixel size
// Setting both results in a warning
// -1 is an undocumented same as unset (see qquickvaluetypes)
font.pointSize: -1
color: today ? PlasmaCore.Theme.backgroundColor : PlasmaCore.Theme.textColor
}
}

View File

@ -2,6 +2,7 @@
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
*/
@ -12,7 +13,7 @@ import QtQuick.Controls 1.1 as QQC1
import org.kde.plasma.calendar 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as Components
import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.plasma.extras 2.0 as PlasmaExtras
Item {
@ -20,221 +21,27 @@ Item {
signal headerClicked
signal previous
signal next
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 alias previousLabel: previousButton.tooltip
property alias nextLabel: nextButton.tooltip
property int rows
property int columns
property bool showWeekNumbers
onShowWeekNumbersChanged: canvas.requestPaint()
// 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
property alias title: heading.text
// 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((stack.width - (daysCalendar.columns + 1) * root.borderWidth) / (daysCalendar.columns + (showWeekNumbers ? 1 : 0)))
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((stack.height - heading.height - calendarGrid.rows * root.borderWidth) / calendarGrid.rows)
property real transformScale: 1
property point transformOrigin: Qt.point(width / 2, height / 2)
transform: Scale {
xScale: daysCalendar.transformScale
yScale: xScale
origin.x: transformOrigin.x
origin.y: transformOrigin.y
}
Behavior on scale {
id: scaleBehavior
ScaleAnimator {
duration: PlasmaCore.Units.longDuration
}
}
QQC1.Stack.onStatusChanged: {
if (QQC1.Stack.status === QQC1.Stack.Inactive) {
daysCalendar.transformScale = 1
opacity = 1
}
}
RowLayout {
anchors {
top: parent.top
left: canvas.left
right: canvas.right
}
spacing: PlasmaCore.Units.smallSpacing
PlasmaExtras.Heading {
id: heading
Layout.fillWidth: true
level: 2
elide: Text.ElideRight
font.capitalization: Font.Capitalize
//SEE QTBUG-58307
//try to make all heights an even number, otherwise the layout engine gets confused
Layout.preferredHeight: implicitHeight + implicitHeight%2
MouseArea {
id: monthMouse
property int previousPixelDelta
anchors.fill: parent
onClicked: {
if (!stack.busy) {
daysCalendar.headerClicked()
}
}
onExited: previousPixelDelta = 0
onWheel: {
var delta = wheel.angleDelta.y || wheel.angleDelta.x
var pixelDelta = wheel.pixelDelta.y || wheel.pixelDelta.x
// For high-precision touchpad scrolling, we get a wheel event for basically every slightest
// finger movement. To prevent the view from suddenly ending up in the next century, we
// cumulate all the pixel deltas until they're larger than the label and then only change
// the month. Standard mouse wheel scrolling is unaffected since it's fine.
if (pixelDelta) {
if (Math.abs(previousPixelDelta) < monthMouse.height) {
previousPixelDelta += pixelDelta
return
}
}
if (delta >= 15) {
daysCalendar.previous()
} else if (delta <= -15) {
daysCalendar.next()
}
previousPixelDelta = 0
}
}
}
Components.ToolButton {
id: previousButton
property string tooltip
icon.name: Qt.application.layoutDirection === Qt.RightToLeft ? "go-next" : "go-previous"
onClicked: daysCalendar.previous()
Accessible.name: tooltip
Components.ToolTip { text: parent.tooltip }
//SEE QTBUG-58307
Layout.preferredHeight: implicitHeight + implicitHeight%2
}
Components.ToolButton {
icon.name: "go-jump-today"
property string tooltip
onClicked: root.resetToToday()
tooltip: i18ndc("libplasma5", "Reset calendar to today", "Today")
Accessible.name: tooltip
Accessible.description: i18nd("libplasma5", "Reset calendar to today")
Components.ToolTip { text: parent.tooltip }
//SEE QTBUG-58307
Layout.preferredHeight: implicitHeight + implicitHeight%2
}
Components.ToolButton {
id: nextButton
property string tooltip
icon.name: Qt.application.layoutDirection === Qt.RightToLeft ? "go-previous" : "go-next"
onClicked: daysCalendar.next()
Accessible.name: tooltip
Components.ToolTip { text: parent.tooltip }
//SEE QTBUG-58307
Layout.preferredHeight: implicitHeight + implicitHeight%2
}
}
// Paints the inner grid and the outer frame
Canvas {
id: canvas
anchors {
horizontalCenter: parent.horizontalCenter
bottom: parent.bottom
}
width: (daysCalendar.cellWidth + root.borderWidth) * gridColumns + root.borderWidth
height: (daysCalendar.cellHeight + root.borderWidth) * calendarGrid.rows + root.borderWidth
opacity: root.borderOpacity
antialiasing: false
clip: false
onPaint: {
var ctx = getContext("2d");
// this is needed as otherwise the canvas seems to have some sort of
// inner clip region which does not update on size changes
ctx.reset();
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.strokeStyle = PlasmaCore.Theme.textColor;
ctx.lineWidth = root.borderWidth
ctx.globalAlpha = 1.0;
ctx.beginPath();
// When line is more wide than 1px, it is painted with 1px line at the actual coords
// and then 1px lines are added first to the left of the middle then right (then left again)
// So all the lines need to be offset a bit to have their middle point in the center
// of the grid spacing rather than on the left most pixel, otherwise they will be painted
// over the days grid which will be visible on eg. mouse hover
var lineBasePoint = Math.floor(root.borderWidth / 2)
// horizontal lines
for (var i = 0; i < calendarGrid.rows + 1; i++) {
var lineY = lineBasePoint + (daysCalendar.cellHeight + root.borderWidth) * (i);
if (i == 0 || i == calendarGrid.rows) {
ctx.moveTo(0, lineY);
} else {
ctx.moveTo(showWeekNumbers ? daysCalendar.cellWidth + root.borderWidth : root.borderWidth, lineY);
}
ctx.lineTo(width, lineY);
}
// vertical lines
for (var i = 0; i < gridColumns + 1; i++) {
var lineX = lineBasePoint + (daysCalendar.cellWidth + root.borderWidth) * (i);
// Draw the outer vertical lines in full height so that it closes
// the outer rectangle
if (i == 0 || i == gridColumns || !daysCalendar.headerModel) {
ctx.moveTo(lineX, 0);
} else {
ctx.moveTo(lineX, root.borderWidth + daysCalendar.cellHeight);
}
ctx.lineTo(lineX, height);
}
ctx.closePath();
ctx.stroke();
ctx.restore();
}
}
readonly property int cellHeight: Math.floor((swipeView.height - heading.height - calendarGrid.rows * root.borderWidth) / calendarGrid.rows)
PlasmaCore.Svg {
id: calendarSvg
@ -251,20 +58,13 @@ Item {
}
}
Connections {
target: theme
function onTextColorChanged() {
canvas.requestPaint();
}
}
Column {
id: weeksColumn
visible: showWeekNumbers
anchors {
top: canvas.top
top: parent.top
left: parent.left
bottom: canvas.bottom
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
@ -275,7 +75,7 @@ Item {
Repeater {
model: showWeekNumbers ? calendarBackend.weeksModel : []
Components.Label {
PlasmaComponents3.Label {
height: daysCalendar.cellHeight
width: daysCalendar.cellWidth
horizontalAlignment: Text.AlignHCenter
@ -291,7 +91,8 @@ Item {
id: calendarGrid
anchors {
right: canvas.right
top: parent.top
right: parent.right
rightMargin: root.borderWidth
bottom: parent.bottom
bottomMargin: root.borderWidth
@ -301,13 +102,14 @@ Item {
rows: daysCalendar.rows + (daysCalendar.headerModel ? 1 : 0)
spacing: 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
Components.Label {
PlasmaComponents3.Label {
width: daysCalendar.cellWidth
height: daysCalendar.cellHeight
text: Qt.locale(Qt.locale().uiLanguages[0]).dayName(((calendarBackend.firstDayOfWeek + index) % days.count), Locale.ShortFormat)

View File

@ -2,25 +2,40 @@
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.0
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import org.kde.plasma.calendar 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
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
PinchArea {
PinchArea { // TODO KF6 switch to Item
id: root
anchors.fill: parent
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
@ -39,76 +54,129 @@ PinchArea {
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
onPinchStarted: stack.currentItem.transformOrigin = pinch.center
onPinchUpdated: {
var item = stack.currentItem
if (stack.depth < 3 && pinch.scale < 1) {
item.transformScale = pinch.scale
item.opacity = pinch.scale
} else if (stack.depth > 1 && pinch.scale > 1) {
item.transformScale = pinch.scale
item.opacity = (2 - pinch.scale / 2)
}
}
onPinchFinished: {
var item = stack.currentItem
if (item.transformScale < 0.7) {
item.headerClicked()
} else if (item.transformScale > 1.4) {
item.activateHighlightedItem()
} else {
item.transformScale = 1
item.opacity = 1
}
}
function isToday(date) {
if (date.toDateString() == new Date().toDateString()) {
return true;
}
return false;
return date.toDateString() === new Date().toDateString();
}
function eventDate(yearNumber,monthNumber,dayNumber) {
var d = new Date(yearNumber, monthNumber-1, 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;
stack.pop(null);
swipeView.currentIndex = 0;
}
function updateYearOverview() {
var date = calendarBackend.displayedDate;
var day = date.getDate();
var year = date.getFullYear();
const date = calendarBackend.displayedDate;
const day = date.getDate();
const year = date.getFullYear();
for (var i = 0, j = monthModel.count; i < j; ++i) {
for (let i = 0, j = monthModel.count; i < j; ++i) {
monthModel.setProperty(i, "yearNumber", year);
}
}
function updateDecadeOverview() {
var date = calendarBackend.displayedDate;
var day = date.getDate();
var month = date.getMonth() + 1;
var year = date.getFullYear();
var decade = year - year % 10;
const date = calendarBackend.displayedDate;
const day = date.getDate();
const month = date.getMonth() + 1;
const year = date.getFullYear();
const decade = year - year % 10;
for (var i = 0, j = yearModel.count; i < j; ++i) {
var label = decade - 1 + i;
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;
}
Calendar {
id: calendarBackend
@ -131,10 +199,11 @@ PinchArea {
id: monthModel
Component.onCompleted: {
for (var i = 0; i < 12; ++i) {
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
})
}
@ -146,8 +215,10 @@ PinchArea {
id: yearModel
Component.onCompleted: {
for (var i = 0; i < 12; ++i) {
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
})
}
@ -155,73 +226,117 @@ PinchArea {
}
}
// NOTE: this MouseArea is a workaround on a PinchArea quirk:
// When the pich is done spanning multiple child mouseareas it on't work:
// a MouseArea on top of all the child mouseareas that just refuses events makes the pincharea work.
// BUG: https://bugreports.qt.io/browse/QTBUG-76569
MouseArea {
anchors.fill: parent
z: 1
onPressed: mouse.accepted = false
}
ColumnLayout {
id: viewHeader
visible: !showCustomHeader
// Make sure the height of the invible item is zero, otherwise anchoring to the iten will
// include the height even if it is invisible.
height: !visible ? 0 : implicitHeight
width: parent.width
anchors {
top: parent.top
}
StackView {
id: stack
anchors.fill: parent
delegate: StackViewDelegate {
pushTransition: StackViewTransition {
NumberAnimation {
target: exitItem
duration: PlasmaCore.Units.longDuration
property: "opacity"
from: 1
to: 0
}
NumberAnimation {
target: enterItem
duration: PlasmaCore.Units.longDuration
property: "opacity"
from: 0
to: 1
}
NumberAnimation {
target: enterItem
duration: PlasmaCore.Units.longDuration
property: "transformScale"
from: 1.5
to: 1
}
RowLayout {
spacing: 0
PlasmaExtras.Heading {
id: heading
text: swipeView.currentIndex > 0 || root.selectedYear !== today.getFullYear() ? i18ndc("libplasma5", "Format: month year", "%1 %2", root.selectedMonth, root.selectedYear.toString()) : root.selectedMonth
level: 2
elide: Text.ElideRight
font.capitalization: Font.Capitalize
Layout.fillWidth: true
}
popTransition: StackViewTransition {
NumberAnimation {
target: exitItem
duration: PlasmaCore.Units.longDuration
property: "opacity"
from: 1
to: 0
PlasmaComponents3.ToolButton {
id: previousButton
property string tooltip: {
switch(root.calendarViewDisplayed) {
case MonthView.CalendarView.DayView:
return i18nd("libplasma5", "Previous Month")
case MonthView.CalendarView.MonthView:
return i18nd("libplasma5", "Previous Year")
case MonthView.CalendarView.YearView:
return i18nd("libplasma5", "Previous Decade")
default:
return "";
}
}
NumberAnimation {
target: exitItem
duration: PlasmaCore.Units.longDuration
property: "transformScale"
// so no matter how much you scaled, it would still fly towards you
to: exitItem.transformScale * 1.5
}
NumberAnimation {
target: enterItem
duration: PlasmaCore.Units.longDuration
property: "opacity"
from: 0
to: 1
icon.name: Qt.application.layoutDirection === Qt.RightToLeft ? "go-next" : "go-previous"
onClicked: root.previousView()
Accessible.name: tooltip
PlasmaComponents3.ToolTip { text: parent.tooltip }
}
PlasmaComponents3.ToolButton {
text: i18ndc("libplasma5", "Reset calendar to today", "Today")
Accessible.description: i18nd("libplasma5", "Reset calendar to today")
onClicked: root.resetToToday()
}
PlasmaComponents3.ToolButton {
id: nextButton
property string tooltip: {
switch(root.calendarViewDisplayed) {
case MonthView.CalendarView.DayView:
return i18nd("libplasma5", "Next Month")
case MonthView.CalendarView.MonthView:
return i18nd("libplasma5", "Next Year")
case MonthView.CalendarView.YearView:
return i18nd("libplasma5", "Next Decade")
default:
return "";
}
}
icon.name: Qt.application.layoutDirection === Qt.RightToLeft ? "go-previous" : "go-next"
PlasmaComponents3.ToolTip { text: parent.tooltip }
onClicked: root.nextView();
Accessible.name: tooltip
}
}
initialItem: DaysCalendar {
PlasmaComponents3.TabBar {
id: tabBar
currentIndex: swipeView.currentIndex
Layout.fillWidth: true
Layout.bottomMargin: PlasmaCore.Units.smallSpacing
PlasmaComponents3.TabButton {
text: i18nc("libplasma5", "Days");
onClicked: root.showMonthView();
display: PlasmaComponents3.AbstractButton.TextOnly
}
PlasmaComponents3.TabButton {
text: i18nd("libplasma5", "Months");
onClicked: root.showYearView();
display: PlasmaComponents3.AbstractButton.TextOnly
}
PlasmaComponents3.TabButton {
text: i18nd("libplasma5", "Years");
onClicked: root.showDecadeView();
display: PlasmaComponents3.AbstractButton.TextOnly
}
}
}
PlasmaComponents3.SwipeView {
id: swipeView
anchors {
top: viewHeader.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
}
clip: true
onCurrentIndexChanged: if (currentIndex > 1) {
updateDecadeOverview();
}
// MonthView
DaysCalendar {
id: mainDaysCalendar
title: calendarBackend.displayedDate.getFullYear() == new Date().getFullYear() ? root.selectedMonth : root.selectedMonth + ", " + root.selectedYear
columns: calendarBackend.days
rows: calendarBackend.weeks
@ -233,75 +348,43 @@ PinchArea {
dateMatchingPrecision: Calendar.MatchYearMonthAndDay
previousLabel: i18nd("libplasma5", "Previous Month")
nextLabel: i18nd("libplasma5", "Next Month")
onPrevious: calendarBackend.previousMonth()
onNext: calendarBackend.nextMonth()
onHeaderClicked: {
stack.push(yearOverview)
}
onActivated: {
var rowNumber = Math.floor(index / columns);
const rowNumber = Math.floor(index / columns);
week = 1 + calendarBackend.weeksModel[rowNumber];
root.currentDate = new Date(date.yearNumber, date.monthNumber - 1, date.dayNumber)
}
}
}
Component {
id: yearOverview
// YearView
DaysCalendar {
title: calendarBackend.displayedDate.getFullYear()
columns: 3
rows: 4
dateMatchingPrecision: Calendar.MatchYearAndMonth
gridModel: monthModel
previousLabel: i18nd("libplasma5", "Previous Year")
nextLabel: i18nd("libplasma5", "Next Year")
onPrevious: calendarBackend.previousYear()
onNext: calendarBackend.nextYear()
onHeaderClicked: {
updateDecadeOverview();
stack.push(decadeOverview)
}
onActivated: {
calendarBackend.goToMonth(date.monthNumber)
stack.pop()
calendarBackend.goToMonth(date.monthNumber);
swipeView.currentIndex = 0;
}
}
}
Component {
id: decadeOverview
// DecadeView
DaysCalendar {
readonly property int decade: {
var year = calendarBackend.displayedDate.getFullYear()
const year = calendarBackend.displayedDate.getFullYear()
return year - year % 10
}
title: decade + " " + (decade + 9)
columns: 3
rows: 4
dateMatchingPrecision: Calendar.MatchYear
gridModel: yearModel
previousLabel: i18nd("libplasma5", "Previous Decade")
nextLabel: i18nd("libplasma5", "Next Decade")
onPrevious: calendarBackend.previousDecade()
onNext: calendarBackend.nextDecade()
onActivated: {
calendarBackend.goToYear(date.yearNumber)
stack.pop()
calendarBackend.goToYear(date.yearNumber);
swipeView.currentIndex = 1;
}
}
}

View File

@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: 2016 Marco Martin <mart@kde.org>
// SPDX-License-Identifier: LGPL-2.0-or-later
import QtQuick 2.6
import QtQuick.Templates @QQC2_VERSION@ as T
T.SwipeView {
id: control
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding)
contentItem: ListView {
model: control.contentModel
interactive: control.interactive
currentIndex: control.currentIndex
focus: control.focus
spacing: control.spacing
orientation: control.orientation
snapMode: ListView.SnapOneItem
boundsBehavior: Flickable.StopAtBounds
highlightRangeMode: ListView.StrictlyEnforceRange
preferredHighlightBegin: 0
preferredHighlightEnd: 0
highlightMoveDuration: 250
maximumFlickVelocity: 4 * (control.orientation === Qt.Horizontal ? width : height)
}
}

View File

@ -27,6 +27,7 @@ ScrollBar 3.0 ScrollBar.qml
ScrollView 3.0 ScrollView.qml
Slider 3.0 Slider.qml
SpinBox 3.0 SpinBox.qml
SwipeView 3.0 SwipeView.qml
SwitchDelegate 3.0 SwitchDelegate.qml
Switch 3.0 Switch.qml
TabBar 3.0 TabBar.qml