File indexing completed on 2024-11-17 04:49:18
0001 /* 0002 This file is part of KOrganizer. 0003 0004 SPDX-FileCopyrightText: 2001, 2002, 2003 Cornelius Schumacher <schumacher@kde.org> 0005 SPDX-FileCopyrightText: 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0 0008 */ 0009 0010 #include "kdatenavigator.h" 0011 #include "kodaymatrix.h" 0012 #include "koglobals.h" 0013 #include "widgets/navigatorbar.h" 0014 0015 #include <KLocalizedString> 0016 #include <QEvent> 0017 #include <QFontDatabase> 0018 #include <QGridLayout> 0019 #include <QLabel> 0020 #include <QLocale> 0021 #include <QWheelEvent> 0022 0023 KDateNavigator::KDateNavigator(QWidget *parent) 0024 : QFrame(parent) 0025 , mNavigatorBar(new NavigatorBar(this)) 0026 , mBaseDate(1970, 1, 1) 0027 { 0028 auto topLayout = new QGridLayout(this); 0029 topLayout->setContentsMargins({}); 0030 topLayout->setSpacing(0); 0031 0032 topLayout->addWidget(mNavigatorBar, 0, 0, 1, 8); 0033 0034 connect(mNavigatorBar, &NavigatorBar::prevYearClicked, this, &KDateNavigator::prevYearClicked); 0035 connect(mNavigatorBar, &NavigatorBar::prevMonthClicked, this, &KDateNavigator::prevMonthClicked); 0036 connect(mNavigatorBar, &NavigatorBar::nextMonthClicked, this, &KDateNavigator::nextMonthClicked); 0037 connect(mNavigatorBar, &NavigatorBar::nextYearClicked, this, &KDateNavigator::nextYearClicked); 0038 connect(mNavigatorBar, &NavigatorBar::monthSelected, this, &KDateNavigator::monthSelected); 0039 connect(mNavigatorBar, &NavigatorBar::yearSelected, this, &KDateNavigator::yearSelected); 0040 0041 QString generalFont = QFontDatabase::systemFont(QFontDatabase::GeneralFont).family(); 0042 0043 // Set up the heading fields. 0044 for (int i = 0; i < 7; ++i) { 0045 mHeadings[i] = new QLabel(this); 0046 mHeadings[i]->setFont(QFont(generalFont, 10, QFont::Bold)); 0047 mHeadings[i]->setAlignment(Qt::AlignCenter); 0048 0049 topLayout->addWidget(mHeadings[i], 1, i + 1); 0050 } 0051 0052 // Create the weeknumber labels 0053 for (int i = 0; i < 6; ++i) { 0054 mWeeknos[i] = new QLabel(this); 0055 mWeeknos[i]->setAlignment(Qt::AlignCenter); 0056 mWeeknos[i]->setFont(QFont(generalFont, 10)); 0057 mWeeknos[i]->installEventFilter(this); 0058 0059 topLayout->addWidget(mWeeknos[i], i + 2, 0); 0060 } 0061 0062 mDayMatrix = new KODayMatrix(this); 0063 mDayMatrix->setObjectName(QLatin1StringView("KDateNavigator::dayMatrix")); 0064 0065 connect(mDayMatrix, &KODayMatrix::selected, this, &KDateNavigator::datesSelected); 0066 0067 connect(mDayMatrix, &KODayMatrix::incidenceDropped, this, &KDateNavigator::incidenceDropped); 0068 connect(mDayMatrix, &KODayMatrix::incidenceDroppedMove, this, &KDateNavigator::incidenceDroppedMove); 0069 0070 connect(mDayMatrix, &KODayMatrix::newEventSignal, this, &KDateNavigator::newEventSignal); 0071 connect(mDayMatrix, &KODayMatrix::newTodoSignal, this, &KDateNavigator::newTodoSignal); 0072 connect(mDayMatrix, &KODayMatrix::newJournalSignal, this, &KDateNavigator::newJournalSignal); 0073 0074 topLayout->addWidget(mDayMatrix, 2, 1, 6, 7); 0075 0076 // read settings from configuration file. 0077 updateConfig(); 0078 } 0079 0080 KDateNavigator::~KDateNavigator() = default; 0081 0082 void KDateNavigator::addCalendar(const Akonadi::CollectionCalendar::Ptr &calendar) 0083 { 0084 mDayMatrix->addCalendar(calendar); 0085 } 0086 0087 void KDateNavigator::removeCalendar(const Akonadi::CollectionCalendar::Ptr &calendar) 0088 { 0089 mDayMatrix->removeCalendar(calendar); 0090 } 0091 0092 void KDateNavigator::setBaseDate(const QDate &date) 0093 { 0094 if (date != mBaseDate) { 0095 mBaseDate = date; 0096 0097 updateDates(); 0098 updateView(); 0099 0100 // Use the base date to show the monthname and year in the header 0101 KCalendarCore::DateList dates; 0102 dates.append(date); 0103 mNavigatorBar->selectDates(dates); 0104 0105 update(); 0106 mDayMatrix->update(); 0107 } 0108 } 0109 0110 QSizePolicy KDateNavigator::sizePolicy() const 0111 { 0112 return {QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding}; 0113 } 0114 0115 void KDateNavigator::updateToday() 0116 { 0117 mDayMatrix->recalculateToday(); 0118 mDayMatrix->update(); 0119 } 0120 0121 QDate KDateNavigator::startDate() const 0122 { 0123 // Find the first day of the week of the current month. 0124 QDate dayone(mBaseDate.year(), mBaseDate.month(), mBaseDate.day()); 0125 const int d2 = dayone.day(); 0126 dayone = dayone.addDays(-d2 + 1); 0127 0128 const int m_fstDayOfWkCalsys = dayone.dayOfWeek(); 0129 const int weekstart = KOGlobals::self()->firstDayOfWeek(); 0130 0131 // If month begins on Monday and Monday is first day of week, 0132 // month should begin on second line. Sunday doesn't have this problem. 0133 const int nextLine = m_fstDayOfWkCalsys <= weekstart ? 7 : 0; 0134 0135 // update the matrix dates 0136 const int index = weekstart - m_fstDayOfWkCalsys - nextLine; 0137 0138 dayone = dayone.addDays(index); 0139 0140 return dayone; 0141 } 0142 0143 QDate KDateNavigator::endDate() const 0144 { 0145 return startDate().addDays(6 * 7); 0146 } 0147 0148 void KDateNavigator::setHighlightMode(bool highlightEvents, bool highlightTodos, bool highlightJournals) const 0149 { 0150 mDayMatrix->setHighlightMode(highlightEvents, highlightTodos, highlightJournals); 0151 } 0152 0153 void KDateNavigator::updateDates() 0154 { 0155 QDate dayone = startDate(); 0156 0157 mDayMatrix->updateView(dayone); 0158 0159 // set the week numbers. 0160 for (int i = 0; i < 6; ++i) { 0161 // Use QDate's weekNumber method to determine the week number! 0162 QDate dtStart = mDayMatrix->getDate(i * 7); 0163 QDate dtEnd = mDayMatrix->getDate((i + 1) * 7 - 1); 0164 const int weeknumstart = dtStart.weekNumber(); 0165 const int weeknumend = dtEnd.weekNumber(); 0166 QString weeknum; 0167 0168 if (weeknumstart != weeknumend) { 0169 weeknum = i18nc("start/end week number of line in date picker", "%1/%2", weeknumstart, weeknumend); 0170 } else { 0171 weeknum.setNum(weeknumstart); 0172 } 0173 mWeeknos[i]->setText(weeknum); 0174 mWeeknos[i]->setToolTip(i18n("Scroll to week number %1", weeknum)); 0175 mWeeknos[i]->setWhatsThis( 0176 i18n("Click here to scroll the display to week number %1 " 0177 "of the currently displayed year.", 0178 weeknum)); 0179 } 0180 0181 // each updateDates is followed by an updateView -> repaint is issued there ! 0182 // mDayMatrix->repaint(); 0183 } 0184 0185 void KDateNavigator::updateDayMatrix() 0186 { 0187 mDayMatrix->updateView(); 0188 mDayMatrix->update(); 0189 } 0190 0191 void KDateNavigator::setUpdateNeeded() 0192 { 0193 mDayMatrix->setUpdateNeeded(); 0194 } 0195 0196 QDate KDateNavigator::month() const 0197 { 0198 QDate firstCell = startDate(); 0199 0200 if (firstCell.day() == 1) { 0201 return firstCell; 0202 } else { 0203 firstCell.setDate(firstCell.year(), firstCell.month(), 1); 0204 return firstCell.addMonths(1); 0205 } 0206 } 0207 0208 void KDateNavigator::updateView() 0209 { 0210 updateDayMatrix(); 0211 update(); 0212 } 0213 0214 void KDateNavigator::updateConfig() 0215 { 0216 int weekstart = KOGlobals::self()->firstDayOfWeek(); 0217 for (int i = 0; i < 7; ++i) { 0218 const int day = weekstart + i <= 7 ? weekstart + i : (weekstart + i) % 7; 0219 QString dayName = QLocale().dayName(day, QLocale::ShortFormat); 0220 QString longDayName = QLocale().dayName(day, QLocale::LongFormat); 0221 mHeadings[i]->setText(dayName); 0222 mHeadings[i]->setToolTip(i18n("%1", longDayName)); 0223 mHeadings[i]->setWhatsThis(i18n("A column header of the %1 dates in the month.", longDayName)); 0224 } 0225 mDayMatrix->setUpdateNeeded(); 0226 updateDayMatrix(); 0227 update(); 0228 // FIXME: Use actual config setting here 0229 // setShowWeekNums( true ); 0230 } 0231 0232 void KDateNavigator::setShowWeekNums(bool enabled) 0233 { 0234 for (int i = 0; i < 6; ++i) { 0235 if (enabled) { 0236 mWeeknos[i]->show(); 0237 } else { 0238 mWeeknos[i]->hide(); 0239 } 0240 } 0241 } 0242 0243 void KDateNavigator::selectMonthHelper(int monthDifference) 0244 { 0245 QDate baseDateNextMonth = mBaseDate.addMonths(monthDifference); 0246 0247 KCalendarCore::DateList newSelection = mSelectedDates; 0248 for (int i = 0; i < mSelectedDates.count(); ++i) { 0249 newSelection[i] = newSelection[i].addMonths(monthDifference); 0250 } 0251 0252 setBaseDate(baseDateNextMonth); 0253 mSelectedDates = newSelection; 0254 mDayMatrix->setSelectedDaysFrom(*(newSelection.begin()), *(--newSelection.end())); 0255 updateView(); 0256 } 0257 0258 void KDateNavigator::selectNextMonth() 0259 { 0260 selectMonthHelper(1); 0261 } 0262 0263 void KDateNavigator::selectPreviousMonth() 0264 { 0265 selectMonthHelper(-1); 0266 } 0267 0268 void KDateNavigator::selectDates(const KCalendarCore::DateList &dateList) 0269 { 0270 if (!dateList.isEmpty()) { 0271 mSelectedDates = dateList; 0272 0273 updateDates(); 0274 0275 mDayMatrix->setSelectedDaysFrom(*(dateList.begin()), *(--dateList.end())); 0276 0277 updateView(); 0278 } 0279 } 0280 0281 void KDateNavigator::wheelEvent(QWheelEvent *e) 0282 { 0283 if (e->angleDelta().y() > 0) { 0284 Q_EMIT goPrevious(); 0285 } else { 0286 Q_EMIT goNext(); 0287 } 0288 e->accept(); 0289 } 0290 0291 bool KDateNavigator::eventFilter(QObject *o, QEvent *e) 0292 { 0293 if (e->type() == QEvent::MouseButtonPress) { 0294 int i; 0295 for (i = 0; i < 6; ++i) { 0296 if (o == mWeeknos[i]) { 0297 const QDate weekstart = mDayMatrix->getDate(i * 7); 0298 Q_EMIT weekClicked(weekstart, month()); 0299 break; 0300 } 0301 } 0302 return true; 0303 } else { 0304 return false; 0305 } 0306 } 0307 0308 #include "moc_kdatenavigator.cpp"