File indexing completed on 2024-05-12 05:21:22
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-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net> 0008 SPDX-FileContributor: Sergio Martins <sergio@kdab.com> 0009 0010 SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0 0011 */ 0012 0013 #include "datenavigatorcontainer.h" 0014 #include "kodaymatrix.h" 0015 #include "koglobals.h" 0016 #include "widgets/kdatenavigator.h" 0017 #include "widgets/navigatorbar.h" 0018 0019 #include <KLocalizedString> 0020 0021 #include <QTimer> 0022 0023 DateNavigatorContainer::DateNavigatorContainer(QWidget *parent) 0024 : QFrame(parent) 0025 , mNavigatorView(new KDateNavigator(this)) 0026 { 0027 mNavigatorView->setWhatsThis( 0028 i18n("<qt><p>Select the dates you want to " 0029 "display in KOrganizer's main view here. Hold the " 0030 "mouse button to select more than one day.</p>" 0031 "<p>Press the top buttons to browse to the next " 0032 "/ previous months or years.</p>" 0033 "<p>Each line shows a week. The number in the left " 0034 "column is the number of the week in the year. " 0035 "Press it to select the whole week.</p>" 0036 "</qt>")); 0037 0038 connectNavigatorView(mNavigatorView); 0039 } 0040 0041 DateNavigatorContainer::~DateNavigatorContainer() 0042 { 0043 qDeleteAll(mExtraViews); 0044 } 0045 0046 void DateNavigatorContainer::connectNavigatorView(KDateNavigator *v) 0047 { 0048 connect(v, &KDateNavigator::datesSelected, this, &DateNavigatorContainer::handleDatesSelectedSignal); 0049 0050 connect(v, &KDateNavigator::incidenceDropped, this, &DateNavigatorContainer::incidenceDropped); 0051 connect(v, &KDateNavigator::incidenceDroppedMove, this, &DateNavigatorContainer::incidenceDroppedMove); 0052 0053 connect(v, &KDateNavigator::newEventSignal, this, &DateNavigatorContainer::newEventSignal); 0054 connect(v, &KDateNavigator::newTodoSignal, this, &DateNavigatorContainer::newTodoSignal); 0055 connect(v, &KDateNavigator::newJournalSignal, this, &DateNavigatorContainer::newJournalSignal); 0056 0057 connect(v, &KDateNavigator::weekClicked, this, &DateNavigatorContainer::handleWeekClickedSignal); 0058 0059 connect(v, &KDateNavigator::goPrevious, this, &DateNavigatorContainer::goPrevious); 0060 connect(v, &KDateNavigator::goNext, this, &DateNavigatorContainer::goNext); 0061 0062 connect(v, &KDateNavigator::nextYearClicked, this, &DateNavigatorContainer::nextYearClicked); 0063 connect(v, &KDateNavigator::prevYearClicked, this, &DateNavigatorContainer::prevYearClicked); 0064 0065 connect(v, &KDateNavigator::prevMonthClicked, this, &DateNavigatorContainer::goPrevMonth); 0066 connect(v, &KDateNavigator::nextMonthClicked, this, &DateNavigatorContainer::goNextMonth); 0067 0068 connect(v, &KDateNavigator::monthSelected, this, &DateNavigatorContainer::monthSelected); 0069 connect(v, &KDateNavigator::yearSelected, this, &DateNavigatorContainer::yearSelected); 0070 } 0071 0072 void DateNavigatorContainer::addCalendar(const Akonadi::CollectionCalendar::Ptr &calendar) 0073 { 0074 mNavigatorView->addCalendar(calendar); 0075 for (KDateNavigator *n : std::as_const(mExtraViews)) { 0076 if (n) { 0077 n->addCalendar(calendar); 0078 } 0079 } 0080 mCalendars.push_back(calendar); 0081 } 0082 0083 void DateNavigatorContainer::removeCalendar(const Akonadi::CollectionCalendar::Ptr &calendar) 0084 { 0085 mNavigatorView->removeCalendar(calendar); 0086 for (KDateNavigator *n : std::as_const(mExtraViews)) { 0087 if (n) { 0088 n->removeCalendar(calendar); 0089 } 0090 } 0091 mCalendars.removeOne(calendar); 0092 } 0093 0094 // TODO_Recurrence: let the navigators update just once, and tell them that 0095 // if data has changed or just the selection (because then the list of dayss 0096 // with events doesn't have to be updated if the month stayed the same 0097 void DateNavigatorContainer::updateDayMatrix() 0098 { 0099 mNavigatorView->updateDayMatrix(); 0100 for (KDateNavigator *n : std::as_const(mExtraViews)) { 0101 if (n) { 0102 n->updateDayMatrix(); 0103 } 0104 } 0105 } 0106 0107 void DateNavigatorContainer::updateToday() 0108 { 0109 mNavigatorView->updateToday(); 0110 for (KDateNavigator *n : std::as_const(mExtraViews)) { 0111 if (n) { 0112 n->updateToday(); 0113 } 0114 } 0115 } 0116 0117 void DateNavigatorContainer::setUpdateNeeded() 0118 { 0119 mNavigatorView->setUpdateNeeded(); 0120 for (KDateNavigator *n : std::as_const(mExtraViews)) { 0121 if (n) { 0122 n->setUpdateNeeded(); 0123 } 0124 } 0125 } 0126 0127 void DateNavigatorContainer::updateView() 0128 { 0129 mNavigatorView->updateView(); 0130 for (KDateNavigator *n : std::as_const(mExtraViews)) { 0131 if (n) { 0132 n->setUpdateNeeded(); 0133 } 0134 } 0135 } 0136 0137 void DateNavigatorContainer::updateConfig() 0138 { 0139 mNavigatorView->updateConfig(); 0140 for (KDateNavigator *n : std::as_const(mExtraViews)) { 0141 if (n) { 0142 n->updateConfig(); 0143 } 0144 } 0145 } 0146 0147 void DateNavigatorContainer::selectDates(const KCalendarCore::DateList &dateList, const QDate &preferredMonth) 0148 { 0149 if (!dateList.isEmpty()) { 0150 QDate start(dateList.first()); 0151 QDate end(dateList.last()); 0152 QDate navfirst(mNavigatorView->startDate()); 0153 QDate navsecond; // start of the second shown month if existent 0154 QDate navlast; 0155 if (!mExtraViews.isEmpty()) { 0156 navlast = mExtraViews.last()->endDate(); 0157 navsecond = mExtraViews.first()->startDate(); 0158 } else { 0159 navlast = mNavigatorView->endDate(); 0160 navsecond = navfirst; 0161 } 0162 0163 // If the datelist crosses months we won't know which month to show 0164 // so we read what's in preferredMonth 0165 const bool changingMonth = preferredMonth.isValid() && mNavigatorView->month().month() != preferredMonth.month(); 0166 0167 if (start < navfirst // <- start should always be visible 0168 || // end is not visible and we have a spare month at the beginning: 0169 (end > navlast && start >= navsecond) || changingMonth) { 0170 if (preferredMonth.isValid()) { 0171 setBaseDates(preferredMonth); 0172 } else { 0173 setBaseDates(start); 0174 } 0175 } 0176 0177 if (!mIgnoreNavigatorUpdates) { 0178 mNavigatorView->selectDates(dateList); 0179 for (KDateNavigator *n : std::as_const(mExtraViews)) { 0180 if (n) { 0181 n->selectDates(dateList); 0182 } 0183 } 0184 } 0185 } 0186 } 0187 0188 void DateNavigatorContainer::setBaseDates(const QDate &start) 0189 { 0190 QDate baseDate = start; 0191 if (!mIgnoreNavigatorUpdates) { 0192 mNavigatorView->setBaseDate(baseDate); 0193 } 0194 0195 for (KDateNavigator *n : std::as_const(mExtraViews)) { 0196 baseDate = baseDate.addMonths(1); 0197 if (!mIgnoreNavigatorUpdates) { 0198 n->setBaseDate(baseDate); 0199 } 0200 } 0201 } 0202 0203 void DateNavigatorContainer::resizeEvent(QResizeEvent *) 0204 { 0205 #if 0 0206 qCDebug(KORGANIZER_LOG) << "DateNavigatorContainer::resizeEvent()"; 0207 qCDebug(KORGANIZER_LOG) << " CURRENT SIZE:" << size(); 0208 qCDebug(KORGANIZER_LOG) << " MINIMUM SIZEHINT:" << minimumSizeHint(); 0209 qCDebug(KORGANIZER_LOG) << " SIZEHINT:" << sizeHint(); 0210 qCDebug(KORGANIZER_LOG) << " MINIMUM SIZE:" << minimumSize(); 0211 #endif 0212 QTimer::singleShot(0, this, &DateNavigatorContainer::resizeAllContents); 0213 } 0214 0215 void DateNavigatorContainer::resizeAllContents() 0216 { 0217 QSize minSize = mNavigatorView->minimumSizeHint(); 0218 0219 // qCDebug(KORGANIZER_LOG) << " NAVIGATORVIEW minimumSizeHint:" << minSize; 0220 0221 int verticalCount = size().height() / minSize.height(); 0222 int horizontalCount = size().width() / minSize.width(); 0223 0224 if (horizontalCount != mHorizontalCount || verticalCount != mVerticalCount) { 0225 int count = horizontalCount * verticalCount; 0226 if (count == 0) { 0227 return; 0228 } 0229 0230 while (count > (mExtraViews.count() + 1)) { 0231 auto n = new KDateNavigator(this); 0232 mExtraViews.append(n); 0233 for (const auto &calendar : mCalendars) { 0234 n->addCalendar(calendar); 0235 } 0236 connectNavigatorView(n); 0237 } 0238 0239 while (count < (mExtraViews.count() + 1)) { 0240 delete (mExtraViews.last()); 0241 mExtraViews.removeLast(); 0242 } 0243 0244 mHorizontalCount = horizontalCount; 0245 mVerticalCount = verticalCount; 0246 const KCalendarCore::DateList dates = mNavigatorView->selectedDates(); 0247 if (!dates.isEmpty()) { 0248 setBaseDates(dates.first()); 0249 selectDates(dates); 0250 for (KDateNavigator *n : std::as_const(mExtraViews)) { 0251 if (n) { 0252 n->show(); 0253 } 0254 } 0255 } 0256 } 0257 0258 int height = size().height() / verticalCount; 0259 int width = size().width() / horizontalCount; 0260 0261 NavigatorBar *bar = mNavigatorView->navigatorBar(); 0262 if (horizontalCount > 1) { 0263 bar->showButtons(true, false); 0264 } else { 0265 bar->showButtons(true, true); 0266 } 0267 0268 mNavigatorView->setGeometry((((KOGlobals::self()->reverseLayout()) ? (horizontalCount - 1) : 0) * width), 0, width, height); 0269 for (int i = 0; i < mExtraViews.count(); ++i) { 0270 int x = (i + 1) % horizontalCount; 0271 int y = (i + 1) / horizontalCount; 0272 0273 KDateNavigator *view = mExtraViews.at(i); 0274 bar = view->navigatorBar(); 0275 if (y > 0) { 0276 bar->showButtons(false, false); 0277 } else { 0278 if (x + 1 == horizontalCount) { 0279 bar->showButtons(false, true); 0280 } else { 0281 bar->showButtons(false, false); 0282 } 0283 } 0284 view->setGeometry((((KOGlobals::self()->reverseLayout()) ? (horizontalCount - 1 - x) : x) * width), y * height, width, height); 0285 } 0286 } 0287 0288 QSize DateNavigatorContainer::minimumSizeHint() const 0289 { 0290 return mNavigatorView->minimumSizeHint(); 0291 } 0292 0293 QSize DateNavigatorContainer::sizeHint() const 0294 { 0295 return mNavigatorView->sizeHint(); 0296 } 0297 0298 void DateNavigatorContainer::setHighlightMode(bool highlightEvents, bool highlightTodos, bool highlightJournals) const 0299 { 0300 mNavigatorView->setHighlightMode(highlightEvents, highlightTodos, highlightJournals); 0301 0302 for (KDateNavigator *n : std::as_const(mExtraViews)) { 0303 if (n) { 0304 n->setHighlightMode(highlightEvents, highlightTodos, highlightJournals); 0305 } 0306 } 0307 } 0308 0309 void DateNavigatorContainer::goNextMonth() 0310 { 0311 const QPair<QDate, QDate> p = dateLimits(1); 0312 0313 Q_EMIT nextMonthClicked(mNavigatorView->month(), p.first, p.second); 0314 } 0315 0316 void DateNavigatorContainer::goPrevMonth() 0317 { 0318 const QPair<QDate, QDate> p = dateLimits(-1); 0319 0320 Q_EMIT prevMonthClicked(mNavigatorView->month(), p.first, p.second); 0321 } 0322 0323 QPair<QDate, QDate> DateNavigatorContainer::dateLimits(int offset) const 0324 { 0325 QDate firstMonth; 0326 QDate lastMonth; 0327 if (mExtraViews.isEmpty()) { 0328 lastMonth = mNavigatorView->month(); 0329 } else { 0330 lastMonth = mExtraViews.last()->month(); 0331 } 0332 0333 firstMonth = mNavigatorView->month().addMonths(offset); 0334 lastMonth = lastMonth.addMonths(offset); 0335 0336 QPair<QDate, QDate> firstMonthBoundary = KODayMatrix::matrixLimits(firstMonth); 0337 QPair<QDate, QDate> lastMonthBoundary = KODayMatrix::matrixLimits(lastMonth); 0338 0339 return qMakePair(firstMonthBoundary.first, lastMonthBoundary.second); 0340 } 0341 0342 QDate DateNavigatorContainer::monthOfNavigator(int navigatorIndex) const 0343 { 0344 if (navigatorIndex == 0) { 0345 return mNavigatorView->month(); 0346 } 0347 0348 if (navigatorIndex <= mExtraViews.count() && navigatorIndex >= 0) { 0349 return mExtraViews[navigatorIndex - 1]->month(); 0350 } else { 0351 return {}; 0352 } 0353 } 0354 0355 void DateNavigatorContainer::handleDatesSelectedSignal(const KCalendarCore::DateList &dateList) 0356 { 0357 Q_ASSERT(sender()); 0358 // When we have more than one KDateNavigator, both can have the 0359 // same selection ( because they can share weeks ) 0360 // The month that we send in the datesSelected() signal should be 0361 // the one belonging to the KDatenavigator with the earliest month 0362 const QDate firstDate = dateList.first(); 0363 KDateNavigator *navigator = firstNavigatorForDate(firstDate); 0364 navigator = navigator ? navigator : qobject_cast<KDateNavigator *>(sender()); 0365 0366 Q_EMIT datesSelected(dateList, navigator->month()); 0367 } 0368 0369 void DateNavigatorContainer::handleWeekClickedSignal(const QDate &week, const QDate &) 0370 { 0371 Q_ASSERT(sender()); 0372 KDateNavigator *navigator = firstNavigatorForDate(week); 0373 navigator = navigator ? navigator : qobject_cast<KDateNavigator *>(sender()); 0374 0375 Q_EMIT weekClicked(week, navigator->month()); 0376 } 0377 0378 KDateNavigator *DateNavigatorContainer::firstNavigatorForDate(const QDate &date) const 0379 { 0380 KDateNavigator *navigator = nullptr; 0381 if (date.isValid()) { 0382 QPair<QDate, QDate> limits = KODayMatrix::matrixLimits(mNavigatorView->month()); 0383 0384 if (date >= limits.first && date <= limits.second) { 0385 // The date is in the first navigator 0386 navigator = mNavigatorView; 0387 } else { 0388 for (KDateNavigator *nav : std::as_const(mExtraViews)) { 0389 if (nav) { 0390 limits = KODayMatrix::matrixLimits(nav->month()); 0391 if (date >= limits.first && date <= limits.second) { 0392 navigator = nav; 0393 break; 0394 } 0395 } 0396 } 0397 } 0398 } 0399 0400 return navigator; 0401 } 0402 0403 #include "moc_datenavigatorcontainer.cpp"