Commit 1f7d1508 authored by Claudio Cambra's avatar Claudio Cambra
Browse files

Move todo display due date string construction to model



Signed-off-by: Claudio Cambra's avatarClaudio Cambra <claudio.cambra@gmail.com>
parent 38c20b70
Pipeline #236780 failed with stage
in 6 minutes and 19 seconds
......@@ -208,33 +208,6 @@ function getIncidenceLabelColor(background, darkMode) {
}
function todoDateTimeLabel(datetime, allDay, completed) {
if(!isNaN(datetime.getTime())) {
const now = new Date();
const dateFormat = datetime.getFullYear() == now.getFullYear() ? "dddd dd MMMM" : "dddd dd MMMM yyyy";
const dateString = datetime.toLocaleDateString(Qt.locale(), dateFormat);
const timeString = allDay === true ? " " :
i18nc("%1 is the time, spaces included to allow use of 'empty' string when an event is allday and has no time", " at %1 ", datetime.toLocaleTimeString(Qt.locale(), 1));
if(DateUtils.sameDay(datetime, now)) {
return datetime < now && !completed && !allDay ?
i18nc("No space since the %1 string, which includes the time (or not), includes this space", "Today%1(overdue)", timeString) :
i18nc("No space since the %1 string, which includes the time (or not), includes this space", "Today%1", timeString);
} else if(DateUtils.sameDay(DateUtils.addDaysToDate(datetime, - 1), now)) { // Tomorrow
return i18nc("No space since the %1 string, which includes the time (or not), includes this space", "Tomorrow%1", timeString);
} else if(DateUtils.sameDay(DateUtils.addDaysToDate(datetime, 1), now)) { // Yesterday
return !completed ?
i18nc("No space since the %1 string, which includes the time (or not), includes this space", "Yesterday%1(overdue)", timeString) :
i18nc("No space since the %1 string, which includes the time (or not), includes this space", "Yesterday");
}
const dateAndTime = dateString + timeString
return datetime < now && !completed ? dateAndTime + i18n("(overdue)") : dateAndTime;
} else {
return "";
}
}
function priorityString(priority) {
if(priority === 1) {
return i18nc("%1 is the priority level number", "%1 (Highest priority)", priority);
......
......@@ -78,8 +78,6 @@ TreeListView {
case Kalendar.TodoSortFilterProxyModel.PriorityColumn:
return section !== "--" ? i18n("Priority %1", section) : i18n("No set priority");
case Kalendar.TodoSortFilterProxyModel.DueDateColumn:
// We sometimes return non-date strings from the model for overdue/no set due date
return sectionDateValid ? LabelUtils.todoDateTimeLabel(sectionDate, true, false) : section;
case Kalendar.TodoSortFilterProxyModel.SummaryColumn:
default:
return section;
......@@ -314,17 +312,22 @@ TreeListView {
RowLayout {
id: occurrenceLayout
Layout.row: 1
Layout.column: 1
Layout.fillWidth: true
visible: !isNaN(model.endTime.getTime()) || model.recurs
visible: dateLabel.visible || recurIcon.visible
QQC2.Label {
id: dateLabel
text: LabelUtils.todoDateTimeLabel(model.endTime, model.allDay, model.checked)
readonly property bool validEndDt: !isNaN(model.endTime.getTime())
text: model.displayDueDate
color: model.isOverdue ? Kirigami.Theme.negativeTextColor : Kirigami.Theme.textColor
font: Kirigami.Theme.smallFont
visible: !isNaN(model.endTime.getTime())
visible: validEndDt
}
Kirigami.Icon {
id: recurIcon
......
......@@ -44,6 +44,7 @@ QHash<int, QByteArray> TodoSortFilterProxyModel::roleNames() const
roleNames[TodoModel::SummaryRole] = "text";
roleNames[Roles::StartTimeRole] = "startTime";
roleNames[Roles::EndTimeRole] = "endTime";
roleNames[Roles::DisplayDueDateRole] = "displayDueDate";
roleNames[Roles::LocationRole] = "location";
roleNames[Roles::AllDayRole] = "allDay";
roleNames[Roles::ColorRole] = "color";
......@@ -99,6 +100,8 @@ QVariant TodoSortFilterProxyModel::data(const QModelIndex &index, int role) cons
return todoPtr->dtStart();
} else if (role == Roles::EndTimeRole) {
return todoPtr->dtDue();
} else if (role == Roles::DisplayDueDateRole) {
return todoDueDateDisplayString(todoPtr, DisplayDateTimeAndIfOverdue);
} else if (role == Roles::LocationRole) {
return todoPtr->location();
} else if (role == Roles::AllDayRole) {
......@@ -164,17 +167,14 @@ QVariant TodoSortFilterProxyModel::data(const QModelIndex &index, int role) cons
return i18n("No set date");
}
const auto isOverdue =
(todo->allDay() && todo->dtDue().date() < QDate::currentDate()) || (!todo->allDay() && todo->dtDue() < QDateTime::currentDateTime());
if (isOverdue) {
if (todo->isOverdue()) {
return i18n("Overdue");
}
const auto dateInCurrentTZ = todo->dtDue().toLocalTime().date();
const auto isToday = dateInCurrentTZ == QDate::currentDate();
return isToday ? i18n("Today") : todo->dtDue().toString();
return isToday ? i18n("Today") : todoDueDateDisplayString(todo, DisplayDateOnly);
}
case TopMostParentPriority:
return todo->priority();
......@@ -183,6 +183,42 @@ QVariant TodoSortFilterProxyModel::data(const QModelIndex &index, int role) cons
return QSortFilterProxyModel::data(index, role);
}
QString TodoSortFilterProxyModel::todoDueDateDisplayString(const KCalendarCore::Todo::Ptr todo,
const TodoSortFilterProxyModel::DueDateDisplayFormat format) const
{
if (!todo || !todo->hasDueDate()) {
return {};
}
const auto systemLocale = QLocale::system();
const auto includeTime = !todo->allDay() && format != DisplayDateOnly;
const auto includeOverdue = todo->isOverdue() && format == DisplayDateTimeAndIfOverdue;
const auto todoDateTimeDue = todo->dtDue();
const auto todoDateDue = todoDateTimeDue.date();
const auto todoTimeDueString =
includeTime ? i18nc("Please retain space", " at %1", systemLocale.toString(todoDateTimeDue.time(), QLocale::NarrowFormat)) : QStringLiteral(" ");
const auto todoOverdueString = includeOverdue ? i18nc("Please retain parenthesis and space", " (overdue)") : QString();
const auto currentDate = QDate::currentDate();
const auto dateFormat = todoDateDue.year() == currentDate.year() ? QStringLiteral("dddd dd MMMM") : QStringLiteral("dddd dd MMMM yyyy");
static constexpr char translationExplainer[] =
"No spaces -- the (optional) %1 string, which includes the time, includes this space"
" as does the %2 string which is the overdue string (also optional!)";
if (currentDate == todoDateDue) {
return i18nc(translationExplainer, "Today%1%2", todoTimeDueString, todoOverdueString);
} else if (currentDate.daysTo(todoDateDue) == 1) {
return i18nc(translationExplainer, "Tomorrow%1%2", todoTimeDueString, todoOverdueString);
} else if (currentDate.daysTo(todoDateDue) == -1) {
return i18nc(translationExplainer, "Yesterday%1%2", todoTimeDueString, todoOverdueString);
}
const auto dateDueString = systemLocale.toString(todoDateDue, dateFormat);
return dateDueString + todoTimeDueString + todoOverdueString;
}
bool TodoSortFilterProxyModel::filterAcceptsRow(int row, const QModelIndex &sourceParent) const
{
if (filterAcceptsRowCheck(row, sourceParent)) {
......
......@@ -29,9 +29,10 @@ class TodoSortFilterProxyModel : public QSortFilterProxyModel
showCompletedSubtodosInIncompleteChanged)
public:
enum Roles { // Remember to update roles in todosortfilterproxymodel
enum Roles {
StartTimeRole = TodoModel::CalendarRole + 1,
EndTimeRole,
DisplayDueDateRole,
LocationRole,
AllDayRole,
CompletedRole,
......@@ -53,7 +54,7 @@ public:
TreeDepthRole,
TopMostParentSummary, // These three here are used to help us conserve the proper sections
TopMostParentDueDate, // in the Kirigami TreeListView, which otherwise will create new
TopMostParentPriority // sections for subtasks
TopMostParentPriority, // sections for subtasks
};
Q_ENUM(Roles)
......@@ -76,6 +77,12 @@ public:
};
Q_ENUM(ShowComplete)
enum DueDateDisplayFormat {
DisplayDateOnly,
DisplayDateTimeAndIfOverdue,
};
Q_ENUM(DueDateDisplayFormat)
explicit TodoSortFilterProxyModel(QObject *parent = nullptr);
~TodoSortFilterProxyModel() override;
......@@ -125,6 +132,8 @@ protected:
void loadColors();
private:
QString todoDueDateDisplayString(const KCalendarCore::Todo::Ptr todo, const DueDateDisplayFormat format) const;
int compareStartDates(const QModelIndex &left, const QModelIndex &right) const;
int compareDueDates(const QModelIndex &left, const QModelIndex &right) const;
int compareCompletedDates(const QModelIndex &left, const QModelIndex &right) const;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment