presentation/QuickCalendarModel.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "QuickCalendarModel.h" | ||
| 2 | #include <algorithm> | ||
| 3 | #include "data/CalendarModels.h" | ||
| 4 | #include "data/CalendarStore.h" | ||
| 5 | #include "data/RecurrenceExpansion.h" | ||
| 6 | #include "CalendarSearch.h" | ||
| 7 | #include "CalendarBirthdayLayer.h" | ||
| 8 | #include "CalendarTaskLayer.h" | ||
| 9 | #include <QLocale> | ||
| 10 | #include <QMetaObject> | ||
| 11 | #include <QRegularExpression> | ||
| 12 | |||
| 13 | namespace { | ||
| 14 | |||
| 15 | 892 | bool validMode(const QString &mode) { | |
| 16 |
4/4✓ Branch 7 → 8 taken 827 times.
✓ Branch 7 → 17 taken 35 times.
✓ Branch 10 → 11 taken 37 times.
✓ Branch 10 → 17 taken 790 times.
|
2581 | return mode == QLatin1String("day") || mode == QLatin1String("week") || |
| 17 |
6/6✓ Branch 4 → 5 taken 862 times.
✓ Branch 4 → 17 taken 30 times.
✓ Branch 13 → 14 taken 22 times.
✓ Branch 13 → 17 taken 15 times.
✓ Branch 16 → 17 taken 21 times.
✓ Branch 16 → 18 taken 1 time.
|
2603 | mode == QLatin1String("month") || mode == QLatin1String("year") || |
| 18 | 914 | mode == QLatin1String("agenda"); | |
| 19 | } | ||
| 20 | |||
| 21 | // The locale's long date without weekday and year ("d. MMMM", "MMMM d"). | ||
| 22 | 49 | QString dayMonthFormat() { | |
| 23 |
2/2✓ Branch 2 → 3 taken 49 times.
✓ Branch 3 → 4 taken 49 times.
|
49 | QString format = QLocale().dateFormat(QLocale::LongFormat); |
| 24 |
2/2✓ Branch 9 → 10 taken 49 times.
✓ Branch 10 → 11 taken 49 times.
|
49 | format.remove(QRegularExpression(QStringLiteral("d{4}[,.]?\\s*"))); |
| 25 |
2/2✓ Branch 18 → 19 taken 49 times.
✓ Branch 19 → 20 taken 49 times.
|
49 | format.remove(QRegularExpression(QStringLiteral("[,\\s]*y+[.\\s]*"))); |
| 26 |
1/1✓ Branch 23 → 24 taken 49 times.
|
49 | format = format.trimmed(); |
| 27 |
2/3✓ Branch 30 → 31 taken 49 times.
✗ Branch 31 → 27 not taken.
✓ Branch 31 → 32 taken 49 times.
|
49 | while (format.endsWith(QLatin1Char(','))) |
| 28 | ✗ | format.chop(1); | |
| 29 |
2/4✗ Branch 33 → 34 not taken.
✓ Branch 33 → 37 taken 49 times.
✗ Branch 39 → 40 not taken.
✓ Branch 39 → 41 taken 49 times.
|
98 | return format.isEmpty() ? QStringLiteral("d MMMM") : format; |
| 30 | 49 | } | |
| 31 | |||
| 32 | // "7.–11. September 2026" / "September 7 – 11, 2026" (P-03 period title). | ||
| 33 | 49 | QString rangeLabel(const QDate &first, const QDate &last) { | |
| 34 |
1/1✓ Branch 2 → 3 taken 49 times.
|
49 | const QLocale locale; |
| 35 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 7 taken 49 times.
|
49 | if (first == last) |
| 36 | ✗ | return locale.toString(first, QLocale::LongFormat); | |
| 37 |
1/1✓ Branch 7 → 8 taken 49 times.
|
49 | const QString dayMonth = dayMonthFormat(); |
| 38 |
1/1✓ Branch 9 → 10 taken 49 times.
|
49 | const bool monthFirst = dayMonth.indexOf(QLatin1String("MMMM")) < dayMonth.indexOf(QLatin1Char('d')); |
| 39 |
7/7✓ Branch 14 → 15 taken 49 times.
✓ Branch 15 → 16 taken 12 times.
✓ Branch 15 → 19 taken 37 times.
✓ Branch 22 → 23 taken 37 times.
✓ Branch 22 → 24 taken 12 times.
✓ Branch 24 → 25 taken 12 times.
✓ Branch 24 → 26 taken 37 times.
|
98 | const QString dayOnly = dayMonth.contains(QLatin1String("d.")) ? QStringLiteral("d.") : QStringLiteral("d"); |
| 40 |
2/2✓ Branch 26 → 27 taken 49 times.
✓ Branch 27 → 28 taken 49 times.
|
49 | const QString year = QString::number(last.year()); |
| 41 |
9/10✓ Branch 28 → 29 taken 49 times.
✓ Branch 29 → 30 taken 49 times.
✓ Branch 30 → 31 taken 49 times.
✗ Branch 30 → 35 not taken.
✓ Branch 31 → 32 taken 49 times.
✓ Branch 32 → 33 taken 49 times.
✓ Branch 33 → 34 taken 48 times.
✓ Branch 33 → 35 taken 1 time.
✓ Branch 36 → 37 taken 48 times.
✓ Branch 36 → 86 taken 1 time.
|
49 | if (first.year() == last.year() && first.month() == last.month()) { |
| 42 |
1/2✗ Branch 37 → 38 not taken.
✓ Branch 37 → 66 taken 48 times.
|
48 | if (monthFirst) |
| 43 | ✗ | return locale.toString(first, dayMonth) + QStringLiteral(" – ") + locale.toString(last, QStringLiteral("d")) + | |
| 44 | ✗ | QStringLiteral(", ") + year; | |
| 45 |
4/4✓ Branch 68 → 69 taken 48 times.
✓ Branch 72 → 73 taken 48 times.
✓ Branch 73 → 74 taken 48 times.
✓ Branch 74 → 75 taken 48 times.
|
144 | return locale.toString(first, dayOnly) + QStringLiteral("–") + locale.toString(last, dayMonth) + |
| 46 |
2/2✓ Branch 75 → 76 taken 48 times.
✓ Branch 76 → 77 taken 48 times.
|
144 | QLatin1Char(' ') + year; |
| 47 | } | ||
| 48 |
1/1✓ Branch 95 → 96 taken 1 time.
|
2 | const QString firstText = locale.toString(first, dayMonth) + |
| 49 |
5/12✓ Branch 86 → 87 taken 1 time.
✓ Branch 87 → 88 taken 1 time.
✗ Branch 88 → 89 not taken.
✓ Branch 88 → 94 taken 1 time.
✗ Branch 89 → 90 not taken.
✗ Branch 90 → 91 not taken.
✗ Branch 93 → 95 not taken.
✓ Branch 96 → 97 taken 1 time.
✗ Branch 99 → 100 not taken.
✓ Branch 99 → 101 taken 1 time.
✗ Branch 213 → 214 not taken.
✗ Branch 213 → 215 not taken.
|
3 | (first.year() != last.year() ? QLatin1Char(' ') + QString::number(first.year()) : QString()); |
| 50 |
1/2✗ Branch 101 → 102 not taken.
✓ Branch 101 → 123 taken 1 time.
|
1 | if (monthFirst) |
| 51 | ✗ | return firstText + QStringLiteral(" – ") + locale.toString(last, dayMonth) + QStringLiteral(", ") + year; | |
| 52 |
5/5✓ Branch 125 → 126 taken 1 time.
✓ Branch 129 → 130 taken 1 time.
✓ Branch 130 → 131 taken 1 time.
✓ Branch 131 → 132 taken 1 time.
✓ Branch 132 → 133 taken 1 time.
|
2 | return firstText + QStringLiteral(" – ") + locale.toString(last, dayMonth) + QLatin1Char(' ') + year; |
| 53 | 49 | } | |
| 54 | |||
| 55 | } // namespace | ||
| 56 | |||
| 57 | 3403 | QVector<CalendarOccurrence> calendarOccurrencesFor(const CalendarStore &store, const QDate &start, | |
| 58 | const QDate &end, const QStringList &hiddenCalendars, | ||
| 59 | const QSet<QString> &unlimitedSeries) { | ||
| 60 | 3403 | QHash<QString, CalendarInfoLookup> calendars; | |
| 61 |
5/5✓ Branch 2 → 3 taken 3403 times.
✓ Branch 3 → 4 taken 3403 times.
✓ Branch 4 → 5 taken 3403 times.
✓ Branch 14 → 6 taken 4385 times.
✓ Branch 14 → 15 taken 3403 times.
|
7788 | for (const CalendarInfo &calendar : store.allCalendars()) |
| 62 |
1/1✓ Branch 9 → 10 taken 4385 times.
|
4385 | calendars.insert(calendarSelectionKey(calendar.accountId, calendar.path), |
| 63 | 3403 | {calendar.displayName, calendar.readOnly}); | |
| 64 | // One day of margin: all-day dates and zone offsets around the edges. | ||
| 65 |
3/3✓ Branch 19 → 20 taken 3403 times.
✓ Branch 20 → 21 taken 3403 times.
✓ Branch 21 → 22 taken 3403 times.
|
6806 | const auto events = store.eventsForDateRange(QDateTime(start.addDays(-1), QTime(0, 0)), |
| 66 |
4/4✓ Branch 16 → 17 taken 3403 times.
✓ Branch 17 → 18 taken 3403 times.
✓ Branch 18 → 19 taken 3403 times.
✓ Branch 22 → 23 taken 3403 times.
|
10209 | QDateTime(end.addDays(1), QTime(23, 59, 59))); |
| 67 | 3403 | QVector<CalendarOccurrence> occurrences; | |
| 68 | 3403 | for (const CalendarEvent &event : | |
| 69 |
5/5✓ Branch 26 → 27 taken 3403 times.
✓ Branch 28 → 29 taken 3403 times.
✓ Branch 29 → 30 taken 3403 times.
✓ Branch 52 → 31 taken 25288 times.
✓ Branch 52 → 53 taken 3403 times.
|
32094 | expandEventsForDisplay(events, start, end, false, {kDisplayOccurrencesPerSeries, unlimitedSeries})) { |
| 70 |
3/3✓ Branch 32 → 33 taken 25288 times.
✓ Branch 35 → 36 taken 17 times.
✓ Branch 35 → 37 taken 25271 times.
|
25288 | if (hiddenCalendars.contains(calendarSelectionKey(event.accountId, event.calendarPath))) |
| 71 | 17 | continue; | |
| 72 |
1/1✓ Branch 37 → 38 taken 25271 times.
|
25271 | const CalendarOccurrence occurrence = CalendarLayout::fromEvent(event, calendars); |
| 73 |
3/6✓ Branch 40 → 41 taken 25271 times.
✗ Branch 40 → 45 not taken.
✓ Branch 43 → 44 taken 25271 times.
✗ Branch 43 → 45 not taken.
✓ Branch 46 → 47 taken 25271 times.
✗ Branch 46 → 48 not taken.
|
25271 | if (occurrence.lastDay >= start && occurrence.firstDay <= end) |
| 74 |
1/1✓ Branch 47 → 48 taken 25271 times.
|
25271 | occurrences.append(occurrence); |
| 75 | 28674 | } | |
| 76 | 3403 | return occurrences; | |
| 77 | 11191 | } | |
| 78 | |||
| 79 | 909 | QString QuickCalendarModel::navigatorTitle() const { | |
| 80 |
3/3✓ Branch 6 → 7 taken 909 times.
✓ Branch 7 → 8 taken 909 times.
✓ Branch 8 → 9 taken 909 times.
|
1818 | return QLocale().standaloneMonthName(m_navigatorMonth.month(), QLocale::LongFormat) + |
| 81 |
4/4✓ Branch 2 → 3 taken 909 times.
✓ Branch 3 → 4 taken 909 times.
✓ Branch 9 → 10 taken 909 times.
✓ Branch 10 → 11 taken 909 times.
|
2727 | QLatin1Char(' ') + QString::number(m_navigatorMonth.year()); |
| 82 | } | ||
| 83 | |||
| 84 | ✗ | void QuickCalendarModel::shiftNavigator(int months) { | |
| 85 | ✗ | const QDate target = m_navigatorMonth.addMonths(months); | |
| 86 | ✗ | if (!target.isValid()) return; | |
| 87 | ✗ | m_navigatorMonth = target; | |
| 88 | ✗ | notifyPeriodChanged(); | |
| 89 | } | ||
| 90 | |||
| 91 | 808 | QuickCalendarModel::QuickCalendarModel(QString databasePath, QObject *parent) | |
| 92 | 808 | : QAbstractListModel(parent), m_databasePath(std::move(databasePath)), | |
| 93 |
15/15✓ Branch 7 → 8 taken 808 times.
✓ Branch 13 → 14 taken 808 times.
✓ Branch 14 → 15 taken 808 times.
✓ Branch 20 → 21 taken 808 times.
✓ Branch 26 → 27 taken 808 times.
✓ Branch 27 → 28 taken 808 times.
✓ Branch 34 → 35 taken 808 times.
✓ Branch 35 → 36 taken 808 times.
✓ Branch 39 → 40 taken 808 times.
✓ Branch 40 → 41 taken 808 times.
✓ Branch 41 → 42 taken 808 times.
✓ Branch 42 → 43 taken 808 times.
✓ Branch 43 → 44 taken 808 times.
✓ Branch 54 → 55 taken 808 times.
✓ Branch 55 → 56 taken 808 times.
|
4848 | m_firstDayOfWeek(int(QLocale().firstDayOfWeek())) { |
| 94 |
1/1✓ Branch 57 → 58 taken 808 times.
|
808 | m_pool.setMaxThreadCount(1); |
| 95 |
1/1✓ Branch 58 → 59 taken 808 times.
|
808 | m_midnight.setSingleShot(true); |
| 96 |
1/1✓ Branch 59 → 60 taken 808 times.
|
808 | connect(&m_midnight, &QTimer::timeout, this, [this] { |
| 97 | ✗ | emit monthChanged(); // todayIso | |
| 98 | ✗ | reload(); | |
| 99 | ✗ | armMidnight(); | |
| 100 | ✗ | }); | |
| 101 |
1/1✓ Branch 61 → 62 taken 808 times.
|
808 | armMidnight(); |
| 102 |
1/1✓ Branch 62 → 63 taken 808 times.
|
808 | showCurrentMonth(); |
| 103 | 808 | } | |
| 104 | |||
| 105 | 808 | void QuickCalendarModel::armMidnight() { | |
| 106 |
1/1✓ Branch 2 → 3 taken 808 times.
|
808 | const QDateTime now = QDateTime::currentDateTime(); |
| 107 |
4/4✓ Branch 3 → 4 taken 808 times.
✓ Branch 4 → 5 taken 808 times.
✓ Branch 5 → 6 taken 808 times.
✓ Branch 6 → 7 taken 808 times.
|
808 | const QDateTime next(now.date().addDays(1), QTime(0, 0, 1)); |
| 108 |
3/3✓ Branch 7 → 8 taken 808 times.
✓ Branch 8 → 9 taken 808 times.
✓ Branch 9 → 10 taken 808 times.
|
808 | m_midnight.start(int(std::clamp<qint64>(now.msecsTo(next), 1000, 25LL * 3600 * 1000))); |
| 109 | 808 | } | |
| 110 | |||
| 111 | 814 | QuickCalendarModel::~QuickCalendarModel() { | |
| 112 | // F4: an explicit join makes the worker lifetime deterministic against | ||
| 113 | // future captures; the worker body only touches its own locals. | ||
| 114 | 808 | m_pool.waitForDone(); | |
| 115 | 814 | } | |
| 116 | |||
| 117 | 1349 | QHash<int, QByteArray> QuickCalendarModel::roleNames() const { | |
| 118 | ✗ | return {{DayNumber, "dayNumber"}, {InMonth, "inMonth"}, {IsToday, "isToday"}, | |
| 119 | ✗ | {DateIso, "dateIso"}, {Events, "dayEvents"}, {MonthDays, "monthDays"}, | |
| 120 |
2/4✓ Branch 13 → 14 taken 12141 times.
✓ Branch 13 → 15 taken 1349 times.
✗ Branch 18 → 19 not taken.
✗ Branch 18 → 20 not taken.
|
13490 | {WeekNumber, "weekNumber"}, {IsWeekend, "isWeekend"}, {WeekdayName, "weekdayName"}}; |
| 121 | 1349 | } | |
| 122 | |||
| 123 | 66823 | int QuickCalendarModel::rowCount(const QModelIndex &parent) const { | |
| 124 |
2/2✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 66822 times.
|
66823 | return parent.isValid() ? 0 : m_days.size(); |
| 125 | } | ||
| 126 | |||
| 127 | 48233 | QVariant QuickCalendarModel::data(const QModelIndex &index, int role) const { | |
| 128 |
5/6✓ Branch 3 → 4 taken 48231 times.
✓ Branch 3 → 7 taken 2 times.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 48231 times.
✓ Branch 9 → 10 taken 2 times.
✓ Branch 9 → 11 taken 48231 times.
|
48233 | if (index.row() < 0 || index.row() >= m_days.size()) return {}; |
| 129 | 48231 | const DayCell &cell = m_days[index.row()]; | |
| 130 |
1/1✓ Branch 13 → 14 taken 48231 times.
|
48231 | const QDate today = QDate::currentDate(); |
| 131 |
10/10✓ Branch 14 → 15 taken 7023 times.
✓ Branch 14 → 17 taken 6638 times.
✓ Branch 14 → 18 taken 7646 times.
✓ Branch 14 → 34 taken 8633 times.
✓ Branch 14 → 38 taken 143 times.
✓ Branch 14 → 39 taken 1 time.
✓ Branch 14 → 41 taken 7023 times.
✓ Branch 14 → 43 taken 387 times.
✓ Branch 14 → 50 taken 10736 times.
✓ Branch 14 → 66 taken 1 time.
|
48231 | switch (role) { |
| 132 |
1/1✓ Branch 15 → 16 taken 7023 times.
|
7023 | case DayNumber: return cell.date.day(); |
| 133 | 6638 | case InMonth: return cell.inMonth; | |
| 134 | 15292 | case IsToday: return m_viewMode == QLatin1String("year") | |
| 135 |
7/8✓ Branch 21 → 22 taken 139 times.
✓ Branch 22 → 23 taken 139 times.
✓ Branch 23 → 24 taken 139 times.
✗ Branch 23 → 28 not taken.
✓ Branch 24 → 25 taken 139 times.
✓ Branch 25 → 26 taken 139 times.
✓ Branch 26 → 27 taken 10 times.
✓ Branch 26 → 28 taken 129 times.
|
139 | ? cell.date.year() == today.year() && cell.date.month() == today.month() |
| 136 |
2/2✓ Branch 20 → 21 taken 139 times.
✓ Branch 20 → 30 taken 7507 times.
|
7785 | : cell.date == today; |
| 137 |
1/1✓ Branch 34 → 35 taken 8633 times.
|
8633 | case DateIso: return cell.date.toString(Qt::ISODate); |
| 138 | 143 | case MonthDays: return cell.monthDays; | |
| 139 |
1/1✓ Branch 39 → 40 taken 1 time.
|
1 | case WeekNumber: return cell.date.weekNumber(); |
| 140 |
1/1✓ Branch 41 → 42 taken 7023 times.
|
7023 | case IsWeekend: return cell.date.dayOfWeek() >= 6; |
| 141 |
3/3✓ Branch 43 → 44 taken 387 times.
✓ Branch 44 → 45 taken 387 times.
✓ Branch 45 → 46 taken 387 times.
|
387 | case WeekdayName: return QLocale().dayName(cell.date.dayOfWeek(), QLocale::ShortFormat); |
| 142 | 10736 | case Events: { | |
| 143 | 10736 | QVariantList list; | |
| 144 |
1/1✓ Branch 51 → 52 taken 10736 times.
|
10736 | list.reserve(cell.events.size()); |
| 145 |
2/2✓ Branch 62 → 54 taken 18698 times.
✓ Branch 62 → 63 taken 10736 times.
|
29434 | for (const auto &occurrence : cell.events) |
| 146 |
2/2✓ Branch 55 → 56 taken 18698 times.
✓ Branch 57 → 58 taken 18698 times.
|
18698 | list.append(CalendarLayout::toVariant(occurrence)); |
| 147 | 10736 | return list; | |
| 148 | 10736 | } | |
| 149 | 1 | default: return {}; | |
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 153 | 148 | QString QuickCalendarModel::monthLabel() const { | |
| 154 |
3/3✓ Branch 5 → 6 taken 148 times.
✓ Branch 6 → 7 taken 148 times.
✓ Branch 7 → 8 taken 148 times.
|
296 | return QLocale().standaloneMonthName(m_month, QLocale::LongFormat) + QLatin1Char(' ') + |
| 155 |
2/2✓ Branch 2 → 3 taken 148 times.
✓ Branch 8 → 9 taken 148 times.
|
444 | QString::number(m_year); |
| 156 | } | ||
| 157 | |||
| 158 | 1886 | QDate QuickCalendarModel::gridStartFor(int year, int month) const { | |
| 159 | // Six-week grid starting on the configured first day: always 42 cells. | ||
| 160 |
2/2✓ Branch 2 → 3 taken 1886 times.
✓ Branch 3 → 4 taken 1886 times.
|
1886 | return CalendarLayout::weekStart(QDate(year, month, 1), m_firstDayOfWeek); |
| 161 | } | ||
| 162 | |||
| 163 | 1 | int QuickCalendarModel::visibleDays() const { | |
| 164 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 1 time.
|
1 | if (m_viewMode == QLatin1String("day")) return 1; |
| 165 |
2/4✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 13 not taken.
✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 11 not taken.
|
1 | if (m_viewMode == QLatin1String("week")) return m_workWeek ? 5 : 7; |
| 166 | ✗ | return 7; | |
| 167 | } | ||
| 168 | |||
| 169 | 266 | QString QuickCalendarModel::periodLabel() const { | |
| 170 |
4/4✓ Branch 3 → 4 taken 18 times.
✓ Branch 3 → 9 taken 248 times.
✓ Branch 4 → 5 taken 18 times.
✓ Branch 6 → 7 taken 18 times.
|
284 | if (!m_searchQuery.isEmpty()) return tr("Search: \u201C%1\u201D").arg(m_searchQuery); |
| 171 |
2/2✓ Branch 11 → 12 taken 13 times.
✓ Branch 11 → 13 taken 235 times.
|
248 | if (m_viewMode == QLatin1String("year")) return QString::number(m_year); |
| 172 |
4/4✓ Branch 15 → 16 taken 26 times.
✓ Branch 15 → 21 taken 209 times.
✓ Branch 16 → 17 taken 26 times.
✓ Branch 17 → 18 taken 26 times.
|
235 | if (m_viewMode == QLatin1String("day")) return QLocale().toString(m_anchorDate, QLocale::LongFormat); |
| 173 |
2/2✓ Branch 23 → 24 taken 49 times.
✓ Branch 23 → 25 taken 160 times.
|
209 | if (m_viewMode == QLatin1String("week")) return rangeLabel(m_gridStart, m_gridEnd); |
| 174 |
2/2✓ Branch 27 → 28 taken 13 times.
✓ Branch 27 → 38 taken 147 times.
|
160 | if (m_viewMode == QLatin1String("agenda")) |
| 175 |
4/4✓ Branch 28 → 29 taken 13 times.
✓ Branch 30 → 31 taken 13 times.
✓ Branch 31 → 32 taken 13 times.
✓ Branch 32 → 33 taken 13 times.
|
26 | return tr("From %1").arg(QLocale().toString(m_anchorDate, QLocale::LongFormat)); |
| 176 | 147 | return monthLabel(); | |
| 177 | } | ||
| 178 | |||
| 179 | 266 | QString QuickCalendarModel::weekLabel() const { | |
| 180 |
2/2✓ Branch 3 → 4 taken 17 times.
✓ Branch 3 → 5 taken 249 times.
|
266 | if (!m_searchQuery.isEmpty()) return {}; |
| 181 |
6/6✓ Branch 7 → 8 taken 199 times.
✓ Branch 7 → 12 taken 50 times.
✓ Branch 10 → 11 taken 173 times.
✓ Branch 10 → 12 taken 26 times.
✓ Branch 13 → 14 taken 173 times.
✓ Branch 13 → 15 taken 76 times.
|
249 | if (m_viewMode != QLatin1String("week") && m_viewMode != QLatin1String("day")) |
| 182 | 173 | return {}; | |
| 183 | // ISO weeks start on Monday: name the week by the Monday inside the range. | ||
| 184 |
2/2✓ Branch 15 → 16 taken 76 times.
✓ Branch 16 → 17 taken 76 times.
|
76 | const QDate monday = m_gridStart.addDays((8 - m_gridStart.dayOfWeek()) % 7); |
| 185 |
5/5✓ Branch 17 → 18 taken 76 times.
✓ Branch 21 → 22 taken 26 times.
✓ Branch 21 → 23 taken 50 times.
✓ Branch 24 → 25 taken 76 times.
✓ Branch 25 → 26 taken 76 times.
|
152 | return tr("Week %1").arg((m_viewMode == QLatin1String("day") ? m_anchorDate : monday).weekNumber()); |
| 186 | } | ||
| 187 | |||
| 188 | 898 | QStringList QuickCalendarModel::weekdayNames(bool shortNames) const { | |
| 189 | 898 | QStringList names; | |
| 190 |
2/2✓ Branch 12 → 3 taken 6286 times.
✓ Branch 12 → 13 taken 898 times.
|
7184 | for (int i = 0; i < 7; ++i) |
| 191 |
4/5✓ Branch 3 → 4 taken 6286 times.
✓ Branch 4 → 5 taken 6286 times.
✗ Branch 4 → 6 not taken.
✓ Branch 7 → 8 taken 6286 times.
✓ Branch 8 → 9 taken 6286 times.
|
6286 | names.append(QLocale().dayName((m_firstDayOfWeek - 1 + i) % 7 + 1, |
| 192 | shortNames ? QLocale::ShortFormat : QLocale::LongFormat)); | ||
| 193 | 898 | return names; | |
| 194 | ✗ | } | |
| 195 | |||
| 196 | 1386 | int QuickCalendarModel::weekNumber(const QString &dateIso) const { | |
| 197 |
2/2✓ Branch 2 → 3 taken 1386 times.
✓ Branch 3 → 4 taken 1386 times.
|
1386 | return QDate::fromString(dateIso, Qt::ISODate).weekNumber(); |
| 198 | } | ||
| 199 | |||
| 200 | 814 | void QuickCalendarModel::showCurrentMonth() { | |
| 201 |
1/1✓ Branch 2 → 3 taken 814 times.
|
814 | leaveSearch(); |
| 202 |
1/1✓ Branch 3 → 4 taken 814 times.
|
814 | const QDate today = QDate::currentDate(); |
| 203 | 814 | m_anchorDate = today; | |
| 204 |
1/1✓ Branch 4 → 5 taken 814 times.
|
814 | m_year = today.year(); |
| 205 |
1/1✓ Branch 5 → 6 taken 814 times.
|
814 | m_month = today.month(); |
| 206 | 814 | m_agendaDays = 30; | |
| 207 |
1/1✓ Branch 6 → 7 taken 814 times.
|
814 | notifyPeriodChanged(); |
| 208 |
1/1✓ Branch 7 → 8 taken 814 times.
|
814 | emit todayShown(); |
| 209 | 814 | } | |
| 210 | |||
| 211 | 9 | void QuickCalendarModel::shiftMonths(int delta) { | |
| 212 |
1/1✓ Branch 2 → 3 taken 9 times.
|
9 | const QDate target = m_anchorDate.addMonths(delta); |
| 213 |
2/3✓ Branch 3 → 4 taken 9 times.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 9 times.
|
9 | if (!target.isValid()) return; |
| 214 | 9 | m_anchorDate = target; | |
| 215 |
1/1✓ Branch 6 → 7 taken 9 times.
|
9 | m_year = target.year(); |
| 216 |
1/1✓ Branch 7 → 8 taken 9 times.
|
9 | m_month = target.month(); |
| 217 |
1/1✓ Branch 8 → 9 taken 9 times.
|
9 | notifyPeriodChanged(); |
| 218 | } | ||
| 219 | |||
| 220 | // Choosing a view or a date ends a search (the agenda of results). | ||
| 221 | 1705 | void QuickCalendarModel::leaveSearch() { | |
| 222 |
1/2✓ Branch 3 → 4 taken 1705 times.
✗ Branch 3 → 5 not taken.
|
1705 | if (m_searchQuery.isEmpty()) return; |
| 223 | ✗ | m_searchQuery.clear(); | |
| 224 | ✗ | m_modeBeforeSearch.clear(); | |
| 225 | ✗ | emit searchQueryChanged(); | |
| 226 | } | ||
| 227 | |||
| 228 | 839 | void QuickCalendarModel::setViewMode(const QString &mode) { | |
| 229 |
2/2✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 838 times.
|
839 | if (!validMode(mode)) return; |
| 230 | 838 | const bool searching = !m_searchQuery.isEmpty(); | |
| 231 | 838 | leaveSearch(); | |
| 232 |
5/6✓ Branch 8 → 9 taken 776 times.
✓ Branch 8 → 11 taken 62 times.
✓ Branch 9 → 10 taken 776 times.
✗ Branch 9 → 11 not taken.
✓ Branch 12 → 13 taken 776 times.
✓ Branch 12 → 14 taken 62 times.
|
838 | if (mode == m_viewMode && !searching) return; |
| 233 | 62 | m_viewMode = mode; | |
| 234 | 62 | m_agendaDays = 30; | |
| 235 | 62 | notifyPeriodChanged(); | |
| 236 | } | ||
| 237 | |||
| 238 | 5 | void QuickCalendarModel::setFirstDayOfWeek(int day) { | |
| 239 |
4/6✓ Branch 2 → 3 taken 5 times.
✗ Branch 2 → 5 not taken.
✓ Branch 3 → 4 taken 5 times.
✗ Branch 3 → 5 not taken.
✓ Branch 4 → 5 taken 3 times.
✓ Branch 4 → 6 taken 2 times.
|
5 | if (day < 1 || day > 7 || day == m_firstDayOfWeek) return; |
| 240 | 2 | m_firstDayOfWeek = day; | |
| 241 | 2 | notifyPeriodChanged(); | |
| 242 | } | ||
| 243 | |||
| 244 | 781 | void QuickCalendarModel::setWorkWeek(bool workWeek) { | |
| 245 |
2/2✓ Branch 2 → 3 taken 765 times.
✓ Branch 2 → 4 taken 16 times.
|
781 | if (workWeek == m_workWeek) return; |
| 246 | 16 | m_workWeek = workWeek; | |
| 247 | 16 | notifyPeriodChanged(); | |
| 248 | } | ||
| 249 | |||
| 250 | 54 | void QuickCalendarModel::showDate(const QString &dateIso, const QString &mode) { | |
| 251 |
1/1✓ Branch 2 → 3 taken 54 times.
|
54 | const auto date = QDate::fromString(dateIso, Qt::ISODate); |
| 252 |
6/7✓ Branch 3 → 4 taken 54 times.
✓ Branch 4 → 5 taken 53 times.
✓ Branch 4 → 7 taken 1 time.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 53 times.
✓ Branch 9 → 10 taken 1 time.
✓ Branch 9 → 11 taken 53 times.
|
54 | if (!date.isValid() || !validMode(mode)) return; |
| 253 |
1/1✓ Branch 11 → 12 taken 53 times.
|
53 | leaveSearch(); |
| 254 | 53 | m_anchorDate = date; | |
| 255 |
2/2✓ Branch 12 → 13 taken 53 times.
✓ Branch 13 → 14 taken 53 times.
|
53 | m_year = date.year(); m_month = date.month(); m_viewMode = mode; |
| 256 | 53 | m_agendaDays = 30; | |
| 257 |
1/1✓ Branch 15 → 16 taken 53 times.
|
53 | notifyPeriodChanged(); |
| 258 | } | ||
| 259 | |||
| 260 | 40 | void QuickCalendarModel::loadMoreAgenda() { | |
| 261 |
7/8✓ Branch 4 → 5 taken 37 times.
✓ Branch 4 → 8 taken 3 times.
✓ Branch 5 → 6 taken 37 times.
✗ Branch 5 → 8 not taken.
✓ Branch 7 → 8 taken 3 times.
✓ Branch 7 → 9 taken 34 times.
✓ Branch 10 → 11 taken 6 times.
✓ Branch 10 → 12 taken 34 times.
|
40 | if (m_viewMode != QLatin1String("agenda") || m_agendaDays >= 366 || !m_searchQuery.isEmpty()) return; |
| 262 | 34 | m_agendaDays += 30; | |
| 263 | 34 | reload(); | |
| 264 | } | ||
| 265 | |||
| 266 | 5 | void QuickCalendarModel::shiftPeriod(int delta) { | |
| 267 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 5 times.
|
5 | if (!m_searchQuery.isEmpty()) return; // a search result has no period |
| 268 |
1/3✗ Branch 7 → 8 not taken.
✓ Branch 7 → 10 taken 5 times.
✗ Branch 8 → 9 not taken.
|
5 | if (m_viewMode == QLatin1String("month")) { shiftMonths(delta); return; } |
| 269 |
2/2✓ Branch 12 → 13 taken 4 times.
✓ Branch 12 → 14 taken 1 time.
|
6 | const int days = m_viewMode == QLatin1String("week") ? 7 |
| 270 |
1/2✗ Branch 16 → 17 not taken.
✓ Branch 16 → 18 taken 1 time.
|
1 | : m_viewMode == QLatin1String("agenda") ? 30 : 1; |
| 271 |
3/3✓ Branch 22 → 23 taken 1 time.
✓ Branch 22 → 24 taken 4 times.
✓ Branch 23 → 25 taken 1 time.
|
5 | const auto target = m_viewMode == QLatin1String("year") ? m_anchorDate.addYears(delta) |
| 272 |
1/1✓ Branch 24 → 25 taken 4 times.
|
4 | : m_anchorDate.addDays(qint64(delta) * days); |
| 273 |
2/3✓ Branch 25 → 26 taken 5 times.
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 28 taken 5 times.
|
5 | if (!target.isValid()) return; |
| 274 | 5 | m_anchorDate = target; | |
| 275 |
1/1✓ Branch 28 → 29 taken 5 times.
|
5 | m_year = target.year(); |
| 276 |
1/1✓ Branch 29 → 30 taken 5 times.
|
5 | m_month = target.month(); |
| 277 |
1/1✓ Branch 30 → 31 taken 5 times.
|
5 | notifyPeriodChanged(); |
| 278 | } | ||
| 279 | |||
| 280 | 2283 | void QuickCalendarModel::computeRange() { | |
| 281 | // The navigator follows the anchor unless it was browsed away from it. | ||
| 282 |
6/6✓ Branch 3 → 4 taken 1475 times.
✓ Branch 3 → 6 taken 808 times.
✓ Branch 5 → 6 taken 38 times.
✓ Branch 5 → 7 taken 1437 times.
✓ Branch 8 → 9 taken 846 times.
✓ Branch 8 → 13 taken 1437 times.
|
2283 | if (!m_navigatorMonth.isValid() || m_navigatorAnchor != m_anchorDate) { |
| 283 |
3/3✓ Branch 9 → 10 taken 846 times.
✓ Branch 10 → 11 taken 846 times.
✓ Branch 11 → 12 taken 846 times.
|
846 | m_navigatorMonth = QDate(m_anchorDate.year(), m_anchorDate.month(), 1); |
| 284 | 846 | m_navigatorAnchor = m_anchorDate; | |
| 285 | } | ||
| 286 |
2/2✓ Branch 15 → 16 taken 86 times.
✓ Branch 15 → 17 taken 2197 times.
|
2283 | if (m_viewMode == QLatin1String("day")) { |
| 287 | 86 | m_gridStart = m_gridEnd = m_anchorDate; | |
| 288 |
2/2✓ Branch 19 → 20 taken 143 times.
✓ Branch 19 → 28 taken 2054 times.
|
2197 | } else if (m_viewMode == QLatin1String("week")) { |
| 289 | // The work week is Monday–Friday whatever the first day of the week is. | ||
| 290 |
2/2✓ Branch 20 → 21 taken 21 times.
✓ Branch 20 → 22 taken 122 times.
|
143 | m_gridStart = CalendarLayout::weekStart(m_anchorDate, m_workWeek ? 1 : m_firstDayOfWeek); |
| 291 |
2/2✓ Branch 24 → 25 taken 21 times.
✓ Branch 24 → 26 taken 122 times.
|
143 | m_gridEnd = m_gridStart.addDays(m_workWeek ? 4 : 6); |
| 292 |
2/2✓ Branch 30 → 31 taken 38 times.
✓ Branch 30 → 34 taken 2016 times.
|
2054 | } else if (m_viewMode == QLatin1String("year")) { |
| 293 |
1/1✓ Branch 31 → 32 taken 38 times.
|
38 | m_gridStart = QDate(m_year, 1, 1); |
| 294 |
1/1✓ Branch 32 → 33 taken 38 times.
|
38 | m_gridEnd = QDate(m_year, 12, 31); |
| 295 |
2/2✓ Branch 36 → 37 taken 130 times.
✓ Branch 36 → 38 taken 1886 times.
|
2016 | } else if (m_viewMode == QLatin1String("agenda")) { |
| 296 | 130 | m_gridStart = m_anchorDate; | |
| 297 | 130 | m_gridEnd = m_anchorDate.addDays(m_agendaDays - 1); | |
| 298 | } else { | ||
| 299 | 1886 | m_gridStart = gridStartFor(m_year, m_month); | |
| 300 | 1886 | m_gridEnd = m_gridStart.addDays(41); | |
| 301 | } | ||
| 302 | 2283 | } | |
| 303 | |||
| 304 | // S93.5.5: the agenda cells of a search — days with matches, in order. | ||
| 305 | 13 | QVector<QuickCalendarModel::DayCell> QuickCalendarModel::searchCells(const LoadRequest &request) { | |
| 306 |
1/1✓ Branch 2 → 3 taken 13 times.
|
13 | CalendarStore store; |
| 307 |
2/3✓ Branch 3 → 4 taken 13 times.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 13 times.
|
13 | if (!store.open(request.databasePath)) return {}; |
| 308 | 13 | QVector<DayCell> cells; | |
| 309 | 13 | QList<CalendarOccurrence> found = CalendarSearch::matches(store, request.searchWords, request.hiddenCalendars, | |
| 310 |
2/2✓ Branch 6 → 7 taken 13 times.
✓ Branch 7 → 8 taken 13 times.
|
13 | QDate::currentDate(), request.unlimitedSeries); |
| 311 |
2/2✓ Branch 8 → 9 taken 13 times.
✓ Branch 9 → 10 taken 13 times.
|
13 | CalendarLayout::attachPeople(found, store.namedPeopleByEvent()); // S103.6.1 |
| 312 |
2/2✓ Branch 30 → 14 taken 7 times.
✓ Branch 30 → 31 taken 13 times.
|
20 | for (const CalendarOccurrence &occurrence : std::as_const(found)) { |
| 313 |
7/7✓ Branch 16 → 17 taken 3 times.
✓ Branch 16 → 20 taken 4 times.
✓ Branch 17 → 18 taken 3 times.
✓ Branch 19 → 20 taken 1 time.
✓ Branch 19 → 21 taken 2 times.
✓ Branch 22 → 23 taken 5 times.
✓ Branch 22 → 26 taken 2 times.
|
7 | if (cells.isEmpty() || cells.last().date != occurrence.firstDay) { |
| 314 | 5 | DayCell cell; | |
| 315 | 5 | cell.date = occurrence.firstDay; | |
| 316 | 5 | cell.inMonth = true; | |
| 317 |
1/1✓ Branch 23 → 24 taken 5 times.
|
5 | cells.append(cell); |
| 318 | 5 | } | |
| 319 |
2/2✓ Branch 26 → 27 taken 7 times.
✓ Branch 27 → 28 taken 7 times.
|
7 | cells.last().events.append(occurrence); |
| 320 | } | ||
| 321 | 13 | return cells; | |
| 322 | 13 | } | |
| 323 | |||
| 324 | 1124 | QuickCalendarModel::LoadResult QuickCalendarModel::load(const LoadRequest &request) { | |
| 325 | 1124 | LoadResult result; | |
| 326 | 1124 | result.mode = request.mode; | |
| 327 | // The worker's own store connection (WAL: the GUI thread has one too). | ||
| 328 |
1/1✓ Branch 3 → 4 taken 1124 times.
|
1124 | CalendarStore store; |
| 329 |
1/1✓ Branch 4 → 5 taken 1124 times.
|
1124 | const bool opened = store.open(request.databasePath); |
| 330 | // Appointments (each series bounded, counted from `first`), tasks, birthdays. | ||
| 331 | 1313 | const auto occurrencesBetween = [&](const QDate &first, const QDate &last) { | |
| 332 | 1313 | QVector<CalendarOccurrence> occurrences; | |
| 333 |
1/2✓ Branch 2 → 3 taken 1313 times.
✗ Branch 2 → 12 not taken.
|
1313 | if (opened) { |
| 334 |
1/1✓ Branch 3 → 4 taken 1313 times.
|
1313 | occurrences = calendarOccurrencesFor(store, first, last, request.hiddenCalendars, request.unlimitedSeries); |
| 335 |
2/2✓ Branch 6 → 7 taken 6 times.
✓ Branch 6 → 12 taken 1307 times.
|
1313 | if (request.showTasks) // S93.5.7 |
| 336 |
3/3✓ Branch 7 → 8 taken 6 times.
✓ Branch 8 → 9 taken 6 times.
✓ Branch 9 → 10 taken 6 times.
|
6 | occurrences += CalendarTaskLayer::occurrences(store, first, last, QDate::currentDate(), request.hiddenCalendars); |
| 337 | } | ||
| 338 |
2/2✓ Branch 12 → 13 taken 1313 times.
✓ Branch 13 → 14 taken 1313 times.
|
1313 | occurrences += CalendarBirthdayLayer::occurrences(request.birthdays, first, last); // S97.5.10 |
| 339 |
1/1✓ Branch 17 → 18 taken 1313 times.
|
2626 | return QList<CalendarOccurrence>(occurrences.cbegin(), occurrences.cend()); |
| 340 | 1313 | }; | |
| 341 | // S106-881: view and navigator month expand separately — one expansion | ||
| 342 | // over both let a frequent series spend its bound in the navigator's first | ||
| 343 | // days, and a later day or week showed none of it (nor "Show all"). | ||
| 344 |
1/1✓ Branch 5 → 6 taken 1124 times.
|
1124 | const QDate navigatorFirst = CalendarLayout::weekStart(request.navigatorMonth, request.firstDayOfWeek); |
| 345 |
1/1✓ Branch 6 → 7 taken 1124 times.
|
1124 | const QDate navigatorLast = navigatorFirst.addDays(41); |
| 346 |
1/1✓ Branch 7 → 8 taken 1124 times.
|
1124 | const QList<CalendarOccurrence> all = occurrencesBetween(request.start, request.end); |
| 347 |
1/2✓ Branch 11 → 12 taken 935 times.
✗ Branch 11 → 13 not taken.
|
2059 | const auto navigator = navigatorFirst == request.start && navigatorLast == request.end |
| 348 |
3/3✓ Branch 9 → 10 taken 935 times.
✓ Branch 9 → 13 taken 189 times.
✓ Branch 13 → 14 taken 189 times.
|
2059 | ? all : occurrencesBetween(navigatorFirst, navigatorLast); |
| 349 |
2/2✓ Branch 15 → 16 taken 1124 times.
✓ Branch 16 → 17 taken 1124 times.
|
2248 | result.navigatorDays = CalendarLayout::monthDayMaps(navigatorFirst, request.navigatorMonth.month(), |
| 350 |
1/1✓ Branch 14 → 15 taken 1124 times.
|
3372 | CalendarLayout::rangeSummary(navigator, navigatorFirst, navigatorLast)); |
| 351 |
2/2✓ Branch 21 → 22 taken 13 times.
✓ Branch 21 → 26 taken 1111 times.
|
1124 | if (!request.searchWords.isEmpty()) { |
| 352 |
1/1✓ Branch 22 → 23 taken 13 times.
|
13 | result.cells = searchCells(request); |
| 353 | 13 | return result; | |
| 354 | } | ||
| 355 | 1111 | QList<CalendarOccurrence> list; | |
| 356 |
2/2✓ Branch 41 → 28 taken 6390 times.
✓ Branch 41 → 42 taken 1111 times.
|
7501 | for (const CalendarOccurrence &occurrence : all) |
| 357 |
3/6✓ Branch 31 → 32 taken 6390 times.
✗ Branch 31 → 36 not taken.
✓ Branch 34 → 35 taken 6390 times.
✗ Branch 34 → 36 not taken.
✓ Branch 37 → 38 taken 6390 times.
✗ Branch 37 → 39 not taken.
|
6390 | if (occurrence.lastDay >= request.start && occurrence.firstDay <= request.end) |
| 358 |
1/1✓ Branch 38 → 39 taken 6390 times.
|
6390 | list.append(occurrence); |
| 359 |
5/6✓ Branch 42 → 43 taken 1111 times.
✗ Branch 42 → 47 not taken.
✓ Branch 45 → 46 taken 44 times.
✓ Branch 45 → 47 taken 1067 times.
✓ Branch 48 → 49 taken 44 times.
✓ Branch 48 → 53 taken 1067 times.
|
1111 | if (opened && request.mode == QLatin1String("agenda")) |
| 360 |
2/2✓ Branch 49 → 50 taken 44 times.
✓ Branch 50 → 51 taken 44 times.
|
44 | CalendarLayout::attachPeople(list, store.namedPeopleByEvent()); // S103.6.1: the agenda's avatars |
| 361 |
2/2✓ Branch 55 → 56 taken 17 times.
✓ Branch 55 → 88 taken 1094 times.
|
1111 | if (request.mode == QLatin1String("year")) { |
| 362 |
1/1✓ Branch 56 → 57 taken 17 times.
|
17 | const auto summaries = CalendarLayout::yearSummary(list, request.gridYear); |
| 363 |
2/2✓ Branch 85 → 58 taken 204 times.
✓ Branch 85 → 86 taken 17 times.
|
221 | for (int month = 1; month <= 12; ++month) { |
| 364 | 204 | DayCell cell; | |
| 365 |
1/1✓ Branch 58 → 59 taken 204 times.
|
204 | cell.date = QDate(request.gridYear, month, 1); |
| 366 | 204 | cell.inMonth = true; | |
| 367 |
2/2✓ Branch 59 → 60 taken 204 times.
✓ Branch 60 → 61 taken 204 times.
|
204 | const QDate last(request.gridYear, month, cell.date.daysInMonth()); |
| 368 | // A multi-day occurrence appears once in each covered month. | ||
| 369 |
4/4✓ Branch 61 → 62 taken 204 times.
✓ Branch 62 → 63 taken 204 times.
✓ Branch 77 → 64 taken 5340 times.
✓ Branch 77 → 78 taken 204 times.
|
5544 | for (const CalendarOccurrence &occurrence : list) |
| 370 |
6/6✓ Branch 67 → 68 taken 1987 times.
✓ Branch 67 → 72 taken 3353 times.
✓ Branch 70 → 71 taken 446 times.
✓ Branch 70 → 72 taken 1541 times.
✓ Branch 73 → 74 taken 446 times.
✓ Branch 73 → 75 taken 4894 times.
|
5340 | if (occurrence.lastDay >= cell.date && occurrence.firstDay <= last) |
| 371 |
1/1✓ Branch 74 → 75 taken 446 times.
|
446 | cell.events.append(occurrence); |
| 372 |
2/2✓ Branch 78 → 79 taken 204 times.
✓ Branch 79 → 80 taken 204 times.
|
408 | cell.monthDays = CalendarLayout::monthDayMaps(CalendarLayout::weekStart(cell.date, request.firstDayOfWeek), |
| 373 | 204 | month, summaries); | |
| 374 |
1/1✓ Branch 82 → 83 taken 204 times.
|
204 | result.cells.append(cell); |
| 375 | 204 | } | |
| 376 | 17 | return result; | |
| 377 | 17 | } | |
| 378 |
1/1✓ Branch 88 → 89 taken 1094 times.
|
1094 | const int days = int(request.start.daysTo(request.end)) + 1; |
| 379 |
1/1✓ Branch 89 → 90 taken 1094 times.
|
1094 | const auto buckets = CalendarLayout::bucketByDay(list, request.start, days); |
| 380 |
2/2✓ Branch 124 → 91 taken 42495 times.
✓ Branch 124 → 125 taken 1094 times.
|
43589 | for (int i = 0; i < days; ++i) { |
| 381 | 42495 | DayCell cell; | |
| 382 |
1/1✓ Branch 91 → 92 taken 42495 times.
|
42495 | cell.date = request.start.addDays(i); |
| 383 |
2/2✓ Branch 94 → 95 taken 39270 times.
✓ Branch 94 → 99 taken 3225 times.
|
81765 | cell.inMonth = request.mode != QLatin1String("month") || |
| 384 |
5/6✓ Branch 95 → 96 taken 39270 times.
✓ Branch 96 → 97 taken 28980 times.
✓ Branch 96 → 100 taken 10290 times.
✓ Branch 97 → 98 taken 28980 times.
✓ Branch 98 → 99 taken 28980 times.
✗ Branch 98 → 100 not taken.
|
39270 | (cell.date.month() == request.gridMonth && cell.date.year() == request.gridYear); |
| 385 | 42495 | cell.events = buckets.at(i); | |
| 386 |
1/1✓ Branch 103 → 104 taken 42495 times.
|
42495 | CalendarLayout::assignLanes(cell.events); |
| 387 | // The agenda lists only days with appointments (and always today). | ||
| 388 |
4/4✓ Branch 106 → 107 taken 2700 times.
✓ Branch 106 → 113 taken 39795 times.
✓ Branch 108 → 109 taken 2472 times.
✓ Branch 108 → 113 taken 228 times.
|
44967 | if (request.mode == QLatin1String("agenda") && cell.events.isEmpty() && |
| 389 |
5/5✓ Branch 109 → 110 taken 2472 times.
✓ Branch 111 → 112 taken 2456 times.
✓ Branch 111 → 113 taken 16 times.
✓ Branch 114 → 115 taken 2456 times.
✓ Branch 114 → 116 taken 40039 times.
|
44967 | cell.date != QDate::currentDate()) |
| 390 | 2456 | continue; | |
| 391 |
1/1✓ Branch 116 → 117 taken 40039 times.
|
40039 | result.cells.append(cell); |
| 392 | 42495 | } | |
| 393 |
2/2✓ Branch 127 → 128 taken 44 times.
✓ Branch 127 → 129 taken 1050 times.
|
1094 | if (request.mode == QLatin1String("agenda")) |
| 394 | 44 | return result; | |
| 395 |
2/2✓ Branch 131 → 132 taken 935 times.
✓ Branch 131 → 133 taken 115 times.
|
1050 | const int rowDays = request.mode == QLatin1String("month") ? 7 : days; |
| 396 |
2/2✓ Branch 155 → 135 taken 5725 times.
✓ Branch 155 → 156 taken 1050 times.
|
6775 | for (int row = 0; row * rowDays < days; ++row) { |
| 397 | 5725 | QVariantList spans; | |
| 398 |
6/6✓ Branch 135 → 136 taken 5725 times.
✓ Branch 136 → 137 taken 5725 times.
✓ Branch 137 → 138 taken 5725 times.
✓ Branch 138 → 139 taken 5725 times.
✓ Branch 148 → 140 taken 120 times.
✓ Branch 148 → 149 taken 5725 times.
|
5845 | for (const CalendarSpan &span : CalendarLayout::spanRow(list, request.start.addDays(row * rowDays), rowDays)) |
| 399 |
2/2✓ Branch 141 → 142 taken 120 times.
✓ Branch 143 → 144 taken 120 times.
|
5845 | spans.append(CalendarLayout::toVariant(span)); |
| 400 |
1/1✓ Branch 151 → 152 taken 5725 times.
|
5725 | result.weekSpans.append(QVariant(spans)); |
| 401 | 5725 | } | |
| 402 | 1050 | return result; | |
| 403 | 1124 | } | |
| 404 | |||
| 405 | // The range is part of what monthChanged() announces (periodLabel, | ||
| 406 | // rangeStart/End): compute it before notifying. | ||
| 407 | 989 | void QuickCalendarModel::notifyPeriodChanged() { | |
| 408 | 989 | computeRange(); | |
| 409 | 989 | emit monthChanged(); | |
| 410 | 989 | reload(); | |
| 411 | 989 | } | |
| 412 | |||
| 413 | 1294 | void QuickCalendarModel::reload() { | |
| 414 |
1/1✓ Branch 2 → 3 taken 1294 times.
|
1294 | computeRange(); |
| 415 | 1294 | ++m_generation; | |
| 416 |
5/6✓ Branch 4 → 5 taken 1294 times.
✗ Branch 4 → 6 not taken.
✓ Branch 5 → 6 taken 170 times.
✓ Branch 5 → 7 taken 1124 times.
✓ Branch 8 → 9 taken 170 times.
✓ Branch 8 → 10 taken 1124 times.
|
1294 | if (m_databasePath.isEmpty() || m_loading) return; |
| 417 | 1124 | const quint64 generation = m_generation; | |
| 418 | // Captured per load: the worker must not read mutable members. | ||
| 419 | 3372 | LoadRequest request{m_databasePath, m_viewMode, m_gridStart, m_gridEnd, m_year, m_month, | |
| 420 | 1124 | m_firstDayOfWeek, m_workWeek, m_hiddenCalendars, m_navigatorMonth, | |
| 421 | 2248 | CalendarSearch::words(m_searchQuery), m_showTasks, | |
| 422 |
3/9✓ Branch 13 → 14 taken 1124 times.
✓ Branch 14 → 15 taken 1 time.
✓ Branch 14 → 16 taken 1123 times.
✗ Branch 26 → 27 not taken.
✗ Branch 26 → 28 not taken.
✗ Branch 29 → 30 not taken.
✗ Branch 29 → 31 not taken.
✗ Branch 32 → 33 not taken.
✗ Branch 32 → 34 not taken.
|
1124 | m_showBirthdays ? m_contactsDatabasePath : QString(), m_unlimitedSeries}; |
| 423 | 1124 | m_loading = true; | |
| 424 |
1/1✓ Branch 18 → 19 taken 1124 times.
|
1124 | emit loadingChanged(); |
| 425 |
1/1✓ Branch 20 → 21 taken 1124 times.
|
1124 | m_pool.start([this, generation, request] { |
| 426 |
1/1✓ Branch 2 → 3 taken 1124 times.
|
1124 | LoadResult result = load(request); |
| 427 |
1/1✓ Branch 5 → 6 taken 1124 times.
|
1124 | QMetaObject::invokeMethod(this, [this, generation, result = std::move(result)]() mutable { |
| 428 |
2/2✓ Branch 2 → 3 taken 64 times.
✓ Branch 2 → 5 taken 958 times.
|
1022 | if (generation != m_generation) { |
| 429 | 64 | m_loading = false; | |
| 430 | 64 | reload(); | |
| 431 | 64 | return; | |
| 432 | } | ||
| 433 |
2/2✓ Branch 6 → 7 taken 126 times.
✓ Branch 6 → 13 taken 832 times.
|
958 | if (result.mode != m_dataMode) { |
| 434 | // Hand over between views: the old one empties, the new one binds | ||
| 435 | // to an empty model and builds once from the reset below. | ||
| 436 | 126 | beginResetModel(); | |
| 437 | 126 | m_days.clear(); | |
| 438 | 126 | m_weekSpans.clear(); | |
| 439 | 126 | endResetModel(); | |
| 440 | 126 | m_dataMode = result.mode; | |
| 441 | 126 | emit dataModeChanged(); | |
| 442 | } | ||
| 443 | // CAL-PERIOD-REBUILD: a step in the same view (same cell count) rebinds the delegates in place. | ||
| 444 |
4/4✓ Branch 14 → 15 taken 122 times.
✓ Branch 14 → 19 taken 836 times.
✓ Branch 17 → 18 taken 114 times.
✓ Branch 17 → 19 taken 8 times.
|
958 | const bool inPlace = !m_days.isEmpty() && result.cells.size() == m_days.size(); |
| 445 |
2/2✓ Branch 20 → 21 taken 844 times.
✓ Branch 20 → 22 taken 114 times.
|
958 | if (!inPlace) beginResetModel(); |
| 446 | 958 | m_days = std::move(result.cells); | |
| 447 | 958 | m_weekSpans = std::move(result.weekSpans); | |
| 448 | 958 | const bool navigatorChanged = m_navigatorDays != result.navigatorDays; | |
| 449 |
2/2✓ Branch 27 → 28 taken 794 times.
✓ Branch 27 → 30 taken 164 times.
|
958 | if (navigatorChanged) m_navigatorDays = std::move(result.navigatorDays); |
| 450 |
5/5✓ Branch 30 → 31 taken 114 times.
✓ Branch 30 → 40 taken 844 times.
✓ Branch 34 → 35 taken 114 times.
✓ Branch 36 → 37 taken 114 times.
✓ Branch 37 → 38 taken 114 times.
|
958 | if (inPlace) emit dataChanged(index(0), index(int(m_days.size()) - 1)); |
| 451 | 844 | else endResetModel(); | |
| 452 | 958 | m_loading = false; | |
| 453 | 958 | emit layoutChanged(); | |
| 454 |
2/2✓ Branch 42 → 43 taken 794 times.
✓ Branch 42 → 44 taken 164 times.
|
958 | if (navigatorChanged) emit navigatorDaysChanged(); |
| 455 | 958 | emit loadingChanged(); | |
| 456 | }, Qt::QueuedConnection); | ||
| 457 | 1124 | }); | |
| 458 | 1124 | } | |
| 459 | |||
| 460 | 40 | void QuickCalendarModel::setSearchQuery(const QString &query) { | |
| 461 |
2/2✓ Branch 2 → 3 taken 40 times.
✓ Branch 3 → 4 taken 40 times.
|
40 | const QString trimmed = query.left(256).trimmed(); |
| 462 |
2/2✓ Branch 6 → 7 taken 12 times.
✓ Branch 6 → 8 taken 28 times.
|
40 | if (trimmed == m_searchQuery) return; |
| 463 |
5/6✓ Branch 9 → 10 taken 11 times.
✓ Branch 9 → 13 taken 17 times.
✓ Branch 11 → 12 taken 11 times.
✗ Branch 11 → 13 not taken.
✓ Branch 14 → 15 taken 11 times.
✓ Branch 14 → 16 taken 17 times.
|
28 | if (m_searchQuery.isEmpty() && !trimmed.isEmpty()) m_modeBeforeSearch = m_viewMode; |
| 464 | 28 | m_searchQuery = trimmed; | |
| 465 |
1/1✓ Branch 17 → 18 taken 28 times.
|
28 | emit searchQueryChanged(); |
| 466 |
2/2✓ Branch 19 → 20 taken 17 times.
✓ Branch 19 → 27 taken 11 times.
|
28 | if (!m_searchQuery.isEmpty()) { |
| 467 | 17 | m_viewMode = QStringLiteral("agenda"); | |
| 468 |
1/2✓ Branch 28 → 29 taken 11 times.
✗ Branch 28 → 31 not taken.
|
11 | } else if (!m_modeBeforeSearch.isEmpty()) { |
| 469 | 11 | m_viewMode = m_modeBeforeSearch; | |
| 470 | 11 | m_modeBeforeSearch.clear(); | |
| 471 | } | ||
| 472 |
1/1✓ Branch 31 → 32 taken 28 times.
|
28 | notifyPeriodChanged(); |
| 473 | 40 | } | |
| 474 | |||
| 475 | 799 | void QuickCalendarModel::setHiddenCalendars(const QStringList &keys) { | |
| 476 |
2/2✓ Branch 3 → 4 taken 789 times.
✓ Branch 3 → 5 taken 10 times.
|
799 | if (keys == m_hiddenCalendars) return; |
| 477 | 10 | m_hiddenCalendars = keys; | |
| 478 | 10 | emit hiddenCalendarsChanged(); | |
| 479 | 10 | reload(); | |
| 480 | } | ||
| 481 |