File indexing completed on 2024-05-12 05:21:22

0001 /*
0002   This file is part of KOrganizer.
0003   SPDX-FileCopyrightText: 2002 Cornelius Schumacher <schumacher@kde.org>
0004   SPDX-FileCopyrightText: 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
0005 
0006   SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
0007   SPDX-FileContributor: Sergio Martins <sergio@kdab.com>
0008 
0009   SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
0010 */
0011 
0012 #include "datenavigator.h"
0013 #include "koglobals.h"
0014 #include "korganizer_debug.h"
0015 
0016 DateNavigator::DateNavigator(QObject *parent)
0017     : QObject(parent)
0018 {
0019     mSelectedDates.append(QDate::currentDate());
0020 }
0021 
0022 DateNavigator::~DateNavigator() = default;
0023 
0024 KCalendarCore::DateList DateNavigator::selectedDates() const
0025 {
0026     return mSelectedDates;
0027 }
0028 
0029 int DateNavigator::datesCount() const
0030 {
0031     return mSelectedDates.count();
0032 }
0033 
0034 void DateNavigator::selectDates(const KCalendarCore::DateList &dateList, QDate preferredMonth)
0035 {
0036     if (!dateList.isEmpty()) {
0037         mSelectedDates = dateList;
0038         emitSelected(preferredMonth);
0039     }
0040 }
0041 
0042 void DateNavigator::selectDate(QDate date)
0043 {
0044     if (!date.isValid()) {
0045         qCDebug(KORGANIZER_LOG) << "an invalid date was passed as a parameter!";
0046         date = QDate::currentDate();
0047     }
0048     mSelectedDates.clear();
0049     mSelectedDates.append(date);
0050 
0051     emitSelected();
0052 }
0053 
0054 void DateNavigator::selectDates(int count)
0055 {
0056     count = qMin(count, static_cast<int>(MAX_SELECTABLE_DAYS));
0057     selectDates(mSelectedDates.first(), count);
0058 }
0059 
0060 void DateNavigator::selectDates(const QDate &d, int count, const QDate &preferredMonth)
0061 {
0062     KCalendarCore::DateList dates;
0063     dates.reserve(count);
0064 
0065     for (int i = 0; i < count; ++i) {
0066         dates.append(d.addDays(i));
0067     }
0068 
0069     mSelectedDates = dates;
0070     emitSelected(preferredMonth);
0071 }
0072 
0073 void DateNavigator::selectWeekByDay(int weekDay, QDate d, QDate preferredMonth)
0074 {
0075     const int dateCount = mSelectedDates.count();
0076     const bool weekStart = (weekDay == KOGlobals::self()->firstDayOfWeek());
0077     if (weekStart && dateCount == 7) {
0078         selectWeek(d, preferredMonth);
0079     } else {
0080         selectDates(d, dateCount, preferredMonth);
0081     }
0082 }
0083 
0084 void DateNavigator::selectWeek()
0085 {
0086     selectWeek(mSelectedDates.first());
0087 }
0088 
0089 void DateNavigator::selectWeek(const QDate &d, const QDate &preferredMonth)
0090 {
0091     const int dayOfWeek = d.dayOfWeek();
0092     const int weekStart = KOGlobals::self()->firstDayOfWeek();
0093 
0094     QDate firstDate = d.addDays(weekStart - dayOfWeek);
0095 
0096     if (weekStart != 1 && dayOfWeek < weekStart) {
0097         firstDate = firstDate.addDays(-7);
0098     }
0099 
0100     selectDates(firstDate, 7, preferredMonth);
0101 }
0102 
0103 void DateNavigator::selectWorkWeek()
0104 {
0105     selectWorkWeek(mSelectedDates.first());
0106 }
0107 
0108 void DateNavigator::selectWorkWeek(QDate d)
0109 {
0110     const int weekStart = KOGlobals::self()->firstDayOfWeek();
0111     const int dayOfWeek = d.dayOfWeek();
0112     QDate currentDate = d.addDays(weekStart - dayOfWeek);
0113 
0114     if (weekStart != 1 && dayOfWeek < weekStart) {
0115         currentDate = currentDate.addDays(-7);
0116     }
0117 
0118     mSelectedDates.clear();
0119     const int mask = KOGlobals::self()->getWorkWeekMask();
0120 
0121     for (int i = 0; i < 7; ++i) {
0122         if ((1 << ((i + weekStart + 6) % 7)) & (mask)) {
0123             mSelectedDates.append(currentDate.addDays(i));
0124         }
0125     }
0126 
0127     emitSelected(/* preferredMonth= */ d);
0128 }
0129 
0130 void DateNavigator::selectToday()
0131 {
0132     const QDate d = QDate::currentDate();
0133 
0134     const int dateCount = mSelectedDates.count();
0135 
0136     if (dateCount == 7) {
0137         selectWeek(d, /* preferredMonth= */ d);
0138     } else if (dateCount == 5) {
0139         selectWorkWeek(d);
0140     } else {
0141         selectDates(d, dateCount);
0142     }
0143 }
0144 
0145 void DateNavigator::selectPreviousYear()
0146 {
0147     QDate firstSelected = mSelectedDates.first();
0148     const int weekDay = firstSelected.dayOfWeek();
0149     firstSelected = firstSelected.addYears(-1);
0150 
0151     selectWeekByDay(weekDay, firstSelected);
0152 }
0153 
0154 void DateNavigator::selectPreviousMonth(const QDate &currentMonth, const QDate &selectionLowerLimit, const QDate &selectionUpperLimit)
0155 {
0156     shiftMonth(currentMonth, selectionLowerLimit, selectionUpperLimit, -1);
0157 }
0158 
0159 void DateNavigator::selectPreviousWeek()
0160 {
0161     QDate firstSelected = mSelectedDates.first();
0162     const int weekDay = firstSelected.dayOfWeek();
0163     firstSelected = firstSelected.addDays(-7);
0164 
0165     selectWeekByDay(weekDay, firstSelected);
0166 }
0167 
0168 void DateNavigator::selectNextWeek()
0169 {
0170     QDate firstSelected = mSelectedDates.first();
0171     const int weekDay = firstSelected.dayOfWeek();
0172 
0173     firstSelected = firstSelected.addDays(7);
0174 
0175     selectWeekByDay(weekDay, firstSelected);
0176 }
0177 
0178 void DateNavigator::shiftMonth(const QDate &currentMonth, const QDate &selectionLowerLimit, const QDate &selectionUpperLimit, int offset)
0179 {
0180     QDate firstSelected = mSelectedDates.first();
0181     const int weekDay = firstSelected.dayOfWeek();
0182     firstSelected = firstSelected.addMonths(offset);
0183 
0184     /* Don't trust firstSelected to calculate the nextMonth. firstSelected
0185        can belong to a month other than currentMonth because KDateNavigator
0186        displays 7*6 days. firstSelected should only be used for selection
0187        purposes */
0188     const QDate nextMonth = currentMonth.isValid() ? currentMonth.addMonths(offset) : firstSelected;
0189 
0190     /* When firstSelected doesn't belong to currentMonth it can happen
0191        that the new selection won't be visible on our KDateNavigators
0192        so we must adjust it */
0193     if (selectionLowerLimit.isValid() && firstSelected < selectionLowerLimit) {
0194         firstSelected = selectionLowerLimit;
0195     } else if (selectionUpperLimit.isValid() && firstSelected > selectionUpperLimit) {
0196         firstSelected = selectionUpperLimit.addDays(-6);
0197     }
0198 
0199     selectWeekByDay(weekDay, firstSelected, nextMonth);
0200 }
0201 
0202 void DateNavigator::selectNextMonth(const QDate &currentMonth, const QDate &selectionLowerLimit, const QDate &selectionUpperLimit)
0203 {
0204     shiftMonth(currentMonth, selectionLowerLimit, selectionUpperLimit, 1);
0205 }
0206 
0207 void DateNavigator::selectNextYear()
0208 {
0209     QDate firstSelected = mSelectedDates.first();
0210     int weekDay = firstSelected.dayOfWeek();
0211     firstSelected = firstSelected.addYears(1);
0212 
0213     selectWeekByDay(weekDay, firstSelected);
0214 }
0215 
0216 void DateNavigator::selectPrevious()
0217 {
0218     int offset = -7;
0219     if (datesCount() == 1) {
0220         offset = -1;
0221     }
0222 
0223     selectDates(mSelectedDates.first().addDays(offset), datesCount());
0224 }
0225 
0226 void DateNavigator::selectNext()
0227 {
0228     int offset = 7;
0229     if (datesCount() == 1) {
0230         offset = 1;
0231     }
0232 
0233     selectDates(mSelectedDates.first().addDays(offset), datesCount());
0234 }
0235 
0236 void DateNavigator::selectMonth(int month)
0237 {
0238     // always display starting at the first week of the specified month
0239     QDate firstSelected = QDate(mSelectedDates.first().year(), month, 1);
0240 
0241     int day = firstSelected.day();
0242     firstSelected.setDate(firstSelected.year(), month, 1);
0243     int days = firstSelected.daysInMonth();
0244     // As day we use either the selected date, or if the month has less days
0245     // than that, we use the max day of that month
0246     if (day > days) {
0247         day = days;
0248     }
0249     QDate requestedMonth;
0250     firstSelected.setDate(firstSelected.year(), month, day);
0251     requestedMonth.setDate(firstSelected.year(), month, 1);
0252 
0253     selectWeekByDay(1, firstSelected, requestedMonth);
0254 }
0255 
0256 void DateNavigator::selectYear(int year)
0257 {
0258     QDate firstSelected = mSelectedDates.first();
0259     const int deltaYear = year - firstSelected.year();
0260     firstSelected = firstSelected.addYears(deltaYear);
0261 
0262     const int weekDay = firstSelected.dayOfWeek();
0263     selectWeekByDay(weekDay, firstSelected);
0264 }
0265 
0266 void DateNavigator::emitSelected(const QDate &preferredMonth)
0267 {
0268     Q_EMIT datesSelected(mSelectedDates, preferredMonth);
0269 }
0270 
0271 #include "moc_datenavigator.cpp"