Verified Commit 3a44ac83 authored by Fushan Wen's avatar Fushan Wen 💬
Browse files

calendar: move calendar plugin from plasma-framework to plasma-workspace

The calendar plugin should not exist in plasma-framework as it uses GPL
license, not LGPL license.

The only change in this commit is org.kde.plasma.calendar is renamed to
org.kde.plasma.workspace.calendar
parent 0f19f7fb
......@@ -7,3 +7,4 @@ add_subdirectory(shellprivate)
add_subdirectory(keyboardlayout)
add_subdirectory(sessionsprivate)
add_subdirectory(lookandfeelqml)
add_subdirectory(calendar)
add_library(calendarplugin SHARED)
target_sources(calendarplugin PRIVATE
calendarplugin.cpp
#incidencemodifier.cpp
calendar.cpp
calendardata.cpp
#calendardayhelper.cpp
#calendarroleproxymodel.cpp
#datetimerangefiltermodel.cpp
daysmodel.cpp
eventdatadecorator.cpp
eventpluginsmanager.cpp
)
target_link_libraries(calendarplugin
Qt${QT_MAJOR_VERSION}::Core
Qt${QT_MAJOR_VERSION}::Quick
Qt${QT_MAJOR_VERSION}::Qml
Qt${QT_MAJOR_VERSION}::Gui
KF5::I18n
KF5::CalendarEvents
KF5::CoreAddons
)
install(TARGETS calendarplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/workspace/calendar)
install(DIRECTORY qml/ DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/workspace/calendar)
ecm_generate_qmltypes(org.kde.plasma.workspace.calendar 2.0 DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/workspace/calendar)
/*
SPDX-FileCopyrightText: 2013 Mark Gaiser <markg85@gmail.com>
SPDX-FileCopyrightText: 2016 Martin Klapetek <mklapetek@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <QDebug>
#include "calendar.h"
Calendar::Calendar(QObject *parent)
: QObject(parent)
, m_types(Holiday | Event | Todo | Journal)
, m_dayList()
, m_weekList()
, m_days(0)
, m_weeks(0)
, m_firstDayOfWeek(QLocale::system().firstDayOfWeek())
, m_errorMessage()
{
m_daysModel = new DaysModel(this);
m_daysModel->setSourceData(&m_dayList);
// m_dayHelper = new CalendarDayHelper(this);
// connect(m_dayHelper, SIGNAL(calendarChanged()), this, SLOT(updateData()));
}
QDateTime Calendar::displayedDate() const
{
return m_displayedDate.startOfDay();
}
void Calendar::setDisplayedDate(const QDate &dateTime)
{
if (m_displayedDate == dateTime) {
return;
}
const int oldMonth = m_displayedDate.month();
const int oldYear = m_displayedDate.year();
m_displayedDate = dateTime;
// m_dayHelper->setDate(m_displayedDate.year(), m_displayedDate.month());
updateData();
Q_EMIT displayedDateChanged();
if (oldMonth != m_displayedDate.month()) {
Q_EMIT monthNameChanged();
}
if (oldYear != m_displayedDate.year()) {
Q_EMIT yearChanged();
}
}
void Calendar::setDisplayedDate(const QDateTime &dateTime)
{
setDisplayedDate(dateTime.date());
}
QDateTime Calendar::today() const
{
return m_today.startOfDay();
}
void Calendar::setToday(const QDateTime &dateTime)
{
QDate date = dateTime.date();
if (date == m_today) {
return;
}
m_today = date;
if (m_displayedDate.isNull()) {
resetToToday();
} else {
// the else is to prevent calling updateData() twice
// if the resetToToday() was called
updateData();
}
Q_EMIT todayChanged();
}
void Calendar::resetToToday()
{
setDisplayedDate(m_today);
updateData();
}
int Calendar::types() const
{
return m_types;
}
void Calendar::setTypes(int types)
{
if (m_types == static_cast<Types>(types)) {
return;
}
// m_types = static_cast<Types>(types);
// updateTypes();
Q_EMIT typesChanged();
}
int Calendar::days()
{
return m_days;
}
void Calendar::setDays(int days)
{
if (m_days != days) {
m_days = days;
updateData();
Q_EMIT daysChanged();
}
}
int Calendar::weeks() const
{
return m_weeks;
}
void Calendar::setWeeks(int weeks)
{
if (m_weeks != weeks) {
m_weeks = weeks;
updateData();
Q_EMIT weeksChanged();
}
}
int Calendar::firstDayOfWeek() const
{
// QML has Sunday as 0, so we need to accommodate here
return m_firstDayOfWeek == 7 ? 0 : m_firstDayOfWeek;
}
void Calendar::setFirstDayOfWeek(int day)
{
if (day > 7) {
return;
}
if (m_firstDayOfWeek != day) {
// QML has Sunday as 0, so we need to accommodate here
// for QDate functions which have Sunday as 7
if (day == 0) {
m_firstDayOfWeek = 7;
} else {
m_firstDayOfWeek = day;
}
updateData();
Q_EMIT firstDayOfWeekChanged();
}
}
QString Calendar::errorMessage() const
{
return m_errorMessage;
}
int Calendar::currentWeek() const
{
QDate date(QDate::currentDate());
return date.weekNumber();
}
QString Calendar::dayName(int weekday) const
{
return QLocale::system().dayName(weekday, QLocale::ShortFormat);
}
QString Calendar::monthName() const
{
// Simple QDate::longMonthName won't do the job as it
// will return the month name using LC_DATE locale which is used
// for date formatting etc. So for example, in en_US locale
// and cs_CZ LC_DATE, it would return Czech month names while
// it should return English ones. So here we force the LANG
// locale and take the month name from that.
//
// See https://bugs.kde.org/show_bug.cgi?id=353715
QLocale langLocale;
if (QLocale().uiLanguages().length() > 0) {
langLocale = QLocale(QLocale().uiLanguages().at(0));
}
return langLocale.standaloneMonthName(m_displayedDate.month());
}
int Calendar::year() const
{
return m_displayedDate.year();
}
QAbstractItemModel *Calendar::daysModel() const
{
return m_daysModel;
}
QJsonArray Calendar::weeksModel() const
{
return m_weekList;
}
void Calendar::updateData()
{
if (m_days == 0 || m_weeks == 0) {
return;
}
m_dayList.clear();
m_weekList = QJsonArray();
int totalDays = m_days * m_weeks;
int daysBeforeCurrentMonth = 0;
int daysAfterCurrentMonth = 0;
QDate firstDay(m_displayedDate.year(), m_displayedDate.month(), 1);
// If the first day is the same as the starting day then we add a complete row before it.
if (m_firstDayOfWeek < firstDay.dayOfWeek()) {
daysBeforeCurrentMonth = firstDay.dayOfWeek() - m_firstDayOfWeek;
} else {
daysBeforeCurrentMonth = days() - (m_firstDayOfWeek - firstDay.dayOfWeek());
}
int daysThusFar = daysBeforeCurrentMonth + m_displayedDate.daysInMonth();
if (daysThusFar < totalDays) {
daysAfterCurrentMonth = totalDays - daysThusFar;
}
if (daysBeforeCurrentMonth > 0) {
QDate previousMonth = m_displayedDate.addMonths(-1);
// QDate previousMonth(m_displayedDate.year(), m_displayedDate.month() - 1, 1);
for (int i = 0; i < daysBeforeCurrentMonth; i++) {
DayData day;
day.isCurrent = false;
day.dayNumber = previousMonth.daysInMonth() - (daysBeforeCurrentMonth - (i + 1));
day.monthNumber = previousMonth.month();
day.yearNumber = previousMonth.year();
// day.containsEventItems = false;
m_dayList << day;
}
}
for (int i = 0; i < m_displayedDate.daysInMonth(); i++) {
DayData day;
day.isCurrent = true;
day.dayNumber = i + 1; // +1 to go form 0 based index to 1 based calendar dates
// day.containsEventItems = m_dayHelper->containsEventItems(i + 1);
day.monthNumber = m_displayedDate.month();
day.yearNumber = m_displayedDate.year();
m_dayList << day;
}
if (daysAfterCurrentMonth > 0) {
for (int i = 0; i < daysAfterCurrentMonth; i++) {
DayData day;
day.isCurrent = false;
day.dayNumber = i + 1; // +1 to go form 0 based index to 1 based calendar dates
// day.containsEventItems = false;
day.monthNumber = m_displayedDate.addMonths(1).month();
day.yearNumber = m_displayedDate.addMonths(1).year();
m_dayList << day;
}
}
const int numOfDaysInCalendar = m_dayList.count();
// Week numbers are always counted from Mondays
// so find which index is Monday
int mondayOffset = 0;
if (!m_dayList.isEmpty()) {
const DayData &data = m_dayList.at(0);
QDate firstDay(data.yearNumber, data.monthNumber, data.dayNumber);
// If the first day is not already Monday, get offset for Monday
if (firstDay.dayOfWeek() != 1) {
mondayOffset = 8 - firstDay.dayOfWeek();
}
}
// Fill weeksModel with the week numbers
for (int i = mondayOffset; i < numOfDaysInCalendar; i += 7) {
const DayData &data = m_dayList.at(i);
m_weekList.append(QDate(data.yearNumber, data.monthNumber, data.dayNumber).weekNumber());
}
Q_EMIT weeksModelChanged();
m_daysModel->update();
// qDebug() << "---------------------------------------------------------------";
// qDebug() << "Date obj: " << m_displayedDate;
// qDebug() << "Month: " << m_displayedDate.month();
// qDebug() << "m_days: " << m_days;
// qDebug() << "m_weeks: " << m_weeks;
// qDebug() << "Days before this month: " << daysBeforeCurrentMonth;
// qDebug() << "Days after this month: " << daysAfterCurrentMonth;
// qDebug() << "Days in current month: " << m_displayedDate.daysInMonth();
// qDebug() << "m_dayList size: " << m_dayList.count();
// qDebug() << "---------------------------------------------------------------";
}
void Calendar::nextDecade()
{
setDisplayedDate(m_displayedDate.addYears(10));
}
void Calendar::previousDecade()
{
// Negative years don't make sense
if (m_displayedDate.year() >= 10) {
setDisplayedDate(m_displayedDate.addYears(-10));
}
}
void Calendar::nextYear()
{
setDisplayedDate(m_displayedDate.addYears(1));
}
void Calendar::previousYear()
{
// Negative years don't make sense
if (m_displayedDate.year() >= 1) {
setDisplayedDate(m_displayedDate.addYears(-1));
}
}
void Calendar::nextMonth()
{
setDisplayedDate(m_displayedDate.addMonths(1));
}
void Calendar::previousMonth()
{
setDisplayedDate(m_displayedDate.addMonths(-1));
}
void Calendar::goToMonth(int month)
{
setDisplayedDate(QDate(m_displayedDate.year(), month, 1));
}
void Calendar::goToYear(int year)
{
setDisplayedDate(QDate(year, m_displayedDate.month(), 1));
}
/*
SPDX-FileCopyrightText: 2013 Mark Gaiser <markg85@gmail.com>
SPDX-FileCopyrightText: 2016 Martin Klapetek <mklapetek@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef CALENDAR_H
#define CALENDAR_H
#include <QDate>
#include <QJsonArray>
#include <QObject>
#include "daydata.h"
#include "daysmodel.h"
class QAbstractItemModel;
class Calendar : public QObject
{
Q_OBJECT
/* The conversion between QDate and JS Date is broken. The specification says that a date
* is represented by the start of the UTC day, but for negative to UTC timezones this results
* in wrong dates: Jan 2 in C++ -> Jan 2 (00:00) UTC -> Jan 1 (23:00) UTC-1 in JS.
* So use QDateTime for interfacing to always carry a timezone around.
* https://bugreports.qt.io/browse/QTBUG-29328 */
/**
* This property is used to determine which data from which month to show, it ensures
* the day passed in the QDate is visible
*/
Q_PROPERTY(QDateTime displayedDate READ displayedDate WRITE setDisplayedDate NOTIFY displayedDateChanged)
/**
* This property is used to determine which data from which month to show, it ensures
* the day passed in the QDate is visible
*/
Q_PROPERTY(QDateTime today READ today WRITE setToday NOTIFY todayChanged)
/**
* This determines which kind of data types should be contained in
* selectedDayModel and upcomingEventsModel. By default all types are included.
* NOTE: Only the Event type is fully implemented.
* TODO: Fully implement the other data types throughout this code.
*/
Q_PROPERTY(int types READ types WRITE setTypes NOTIFY typesChanged)
/**
* This model contains the week numbers for the given date grid.
*/
Q_PROPERTY(QJsonArray weeksModel READ weeksModel NOTIFY weeksModelChanged)
/**
* The number of days a week contains.
* TODO: perhaps this one can just be removed. A week is 7 days by definition.
* However, i don't know if that's also the case in other more exotic calendars.
*/
Q_PROPERTY(int days READ days WRITE setDays NOTIFY daysChanged)
/**
* The number of weeks that the model property should contain.
*/
Q_PROPERTY(int weeks READ weeks WRITE setWeeks NOTIFY weeksChanged)
/**
* The start day of a week. By default this follows current Locale. It can be
* changed. One then needs to use the numbers in the Qt DayOfWeek enum:
*
* Monday = 1
* Tuesday = 2
* Wednesday = 3
* Thursday = 4
* Friday = 5
* Saturday = 6
* Sunday = 7
*
* This value doesn't do anything to other data structures, but helps you
* visualizing the data.
*
* WARNING: QML has different enum values for week days - Sunday is 0, this function
* automatically converts that on READ and WRITE and it's stored as QDate format
* (ie. the one above). So firstDayOfWeek() call from QML would return 0 for Sunday
* while internally it's 7 and vice-versa.
*/
Q_PROPERTY(int firstDayOfWeek READ firstDayOfWeek WRITE setFirstDayOfWeek NOTIFY firstDayOfWeekChanged)
/**
* The full year in a numeric value. For example 2013, not 13.
*/
Q_PROPERTY(int year READ year NOTIFY yearChanged)
/**
* If an error occurred, it will be set in this string as human readable text.
*/
Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorMessageChanged)
/**
* This is the human readable long month name. So not "Feb" but "February".
* TODO: this should either be done in QML using javascript or by making a
* function available because this is limiting. There are places
* where you would want the short month name.
*/
Q_PROPERTY(QString monthName READ monthName NOTIFY monthNameChanged)
/**
* This model contains the actual grid data of days. For example, if you had set:
* - days = 7 (7 days in one week)
* - weeks = 6 (6 weeks in one month view)
* then this model will contain 42 entries (days * weeks). Each entry contains
* metadata about the current day. The exact metadata can be found in "daysmodel.cpp"
* where the exact names usable in QML are being set.
*/
Q_PROPERTY(QAbstractItemModel *daysModel READ daysModel CONSTANT)
public:
enum Type {
Holiday = 1,
Event = 2,
Todo = 4,
Journal = 8,
};
Q_ENUM(Type)
Q_DECLARE_FLAGS(Types, Type)
enum DateMatchingPrecision {
MatchYear,
MatchYearAndMonth,
MatchYearMonthAndDay,
};
Q_ENUM(DateMatchingPrecision)
explicit Calendar(QObject *parent = nullptr);
// Displayed date
QDateTime displayedDate() const;
void setDisplayedDate(const QDate &dateTime);
void setDisplayedDate(const QDateTime &dateTime);
// The day that represents "today"
QDateTime today() const;
void setToday(const QDateTime &dateTime);
// Types
int types() const;
void setTypes(int types);
// Days
int days();
void setDays(int days);
// Weeks
int weeks() const;
void setWeeks(int weeks);
// Start day
int firstDayOfWeek() const;
void setFirstDayOfWeek(int day);
// Error message
QString errorMessage() const;
// Month name
QString monthName() const;
int year() const;
// Models
QAbstractItemModel *daysModel() const;
QJsonArray weeksModel() const;
// QML invokables
Q_INVOKABLE void nextMonth();
Q_INVOKABLE void previousMonth();
Q_INVOKABLE void nextYear();
Q_INVOKABLE void previousYear();
Q_INVOKABLE void nextDecade();
Q_INVOKABLE void previousDecade();
Q_INVOKABLE QString dayName(int weekday) const;
Q_INVOKABLE int currentWeek() const;
Q_INVOKABLE void resetToToday();
Q_INVOKABLE void goToMonth(int month);
Q_INVOKABLE void goToYear(int year);
Q_SIGNALS:
void displayedDateChanged();
void todayChanged();
void typesChanged();
void daysChanged();
void weeksChanged();
void firstDayOfWeekChanged();
void errorMessageChanged();
void monthNameChanged();
void yearChanged();
void weeksModelChanged();
public Q_SLOTS:
void updateData();
private:
QDate m_displayedDate;
QDate m_today;
Types m_types;
QList<DayData> m_dayList;
DaysModel *m_daysModel;
QJsonArray m_weekList;
int m_days;
int m_weeks;
int m_firstDayOfWeek;
QString m_errorMessage;
};
#endif // CALENDAR_H
/*
SPDX-FileCopyrightText: 2013 Mark Gaiser <markg85@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "calendardata.h"
CalendarData::CalendarData(QObject *parent)
: QObject(parent)
, m_types(Holiday | Event | Todo | Journal)
{
// m_etmCalendar = new ETMCalendar();
// m_etmCalendar->setParent(this); //TODO: hit sergio