2 This file is part of KOrganizer.
4 Copyright (c) 2001 Eitzenberger Thomas <thomas.eitzenberger@siemens.at>
5 Parts of the source code have been copied from kdpdatebutton.cpp
7 Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
8 Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License along
21 with this program; if not, write to the Free Software Foundation, Inc.,
22 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 As a special exception, permission is given to link this program
25 with any edition of Qt, and distribute the resulting executable,
26 without including the source code for Qt in the source distribution.
29 #include "kodaymatrix.h"
30 #include "koglobals.h"
31 #include "prefs/koprefs.h"
33 #include <CalendarSupport/Utils>
35 #include <AkonadiCore/ItemFetchJob>
36 #include <AkonadiCore/ItemFetchScope>
38 #include <KCalendarSystem>
43 #include <QMouseEvent>
47 #include <KLocalizedString>
50 // ============================================================================
51 // K O D A Y M A T R I X
52 // ============================================================================
54 const int KODayMatrix::NOSELECTION
= -1000;
55 const int KODayMatrix::NUMDAYS
= 42;
57 KODayMatrix::KODayMatrix(QWidget
*parent
)
58 : QFrame(parent
), mStartDate(), mPendingChanges(false)
60 // initialize dynamic arrays
61 mDays
= new QDate
[NUMDAYS
];
62 mDayLabels
= new QString
[NUMDAYS
];
64 mTodayMarginWidth
= 2;
65 mSelEnd
= mSelStart
= NOSELECTION
;
69 mHighlightEvents
= true;
70 mHighlightTodos
= false;
71 mHighlightJournals
= false;
74 void KODayMatrix::setCalendar(const Akonadi::ETMCalendar::Ptr
&calendar
)
77 mCalendar
->unregisterObserver(this);
78 mCalendar
->disconnect(this);
82 mCalendar
->registerObserver(this);
84 setAcceptDrops(mCalendar
!= Q_NULLPTR
);
88 QColor
KODayMatrix::getShadedColor(const QColor
&color
) const
94 color
.getHsv(&h
, &s
, &v
);
97 shaded
.setHsv(h
, s
, v
);
102 KODayMatrix::~KODayMatrix()
105 mCalendar
->unregisterObserver(this);
109 delete [] mDayLabels
;
112 void KODayMatrix::addSelectedDaysTo(KCalCore::DateList
&selDays
)
114 if (mSelStart
== NOSELECTION
) {
118 // cope with selection being out of matrix limits at top (< 0)
121 for (int i
= i0
; i
< 0; ++i
) {
122 selDays
.append(mDays
[0].addDays(i
));
127 // cope with selection being out of matrix limits at bottom (> NUMDAYS-1)
128 if (mSelEnd
> NUMDAYS
- 1) {
129 for (int i
= i0
; i
<= NUMDAYS
- 1; ++i
) {
130 selDays
.append(mDays
[i
]);
132 for (int i
= NUMDAYS
; i
< mSelEnd
; ++i
) {
133 selDays
.append(mDays
[0].addDays(i
));
136 // apply normal routine to selection being entirely within matrix limits
137 for (int i
= i0
; i
<= mSelEnd
; ++i
) {
138 selDays
.append(mDays
[i
]);
143 void KODayMatrix::setSelectedDaysFrom(const QDate
&start
, const QDate
&end
)
145 if (mStartDate
.isValid()) {
146 mSelStart
= mStartDate
.daysTo(start
);
147 mSelEnd
= mStartDate
.daysTo(end
);
151 void KODayMatrix::clearSelection()
153 mSelEnd
= mSelStart
= NOSELECTION
;
156 void KODayMatrix::recalculateToday()
158 if (!mStartDate
.isValid()) {
163 for (int i
= 0; i
< NUMDAYS
; ++i
) {
164 mDays
[i
] = mStartDate
.addDays(i
);
165 mDayLabels
[i
] = QString::number(KOGlobals::self()->calendarSystem()->day(mDays
[i
]));
167 // if today is in the currently displayed month, hilight today
168 if (mDays
[i
].year() == QDate::currentDate().year() &&
169 mDays
[i
].month() == QDate::currentDate().month() &&
170 mDays
[i
].day() == QDate::currentDate().day()) {
176 void KODayMatrix::updateView()
178 updateView(mStartDate
);
181 void KODayMatrix::setUpdateNeeded()
183 mPendingChanges
= true;
186 void KODayMatrix::updateView(const QDate
&actdate
)
188 if (!actdate
.isValid() || NUMDAYS
< 1) {
191 //flag to indicate if the starting day of the matrix has changed by this call
192 bool daychanged
= false;
194 // if a new startdate is to be set then apply Cornelius's calculation
195 // of the first day to be shown
196 if (actdate
!= mStartDate
) {
197 // reset index of selection according to shift of starting date from
198 // startdate to actdate.
199 if (mSelStart
!= NOSELECTION
) {
200 int tmp
= actdate
.daysTo(mStartDate
);
201 // shift selection if new one would be visible at least partly !
202 if (mSelStart
+ tmp
< NUMDAYS
&& mSelEnd
+ tmp
>= 0) {
203 // nested if required for next X display pushed from a different month
204 // correction required. otherwise, for month forward and backward,
205 // it must be avoided.
206 if (mSelStart
> NUMDAYS
|| mSelStart
< 0) {
207 mSelStart
= mSelStart
+ tmp
;
209 if (mSelEnd
> NUMDAYS
|| mSelEnd
< 0) {
210 mSelEnd
= mSelEnd
+ tmp
;
215 mStartDate
= actdate
;
223 // The calendar has not changed in the meantime and the selected range
224 // is still the same so we can save the expensive updateIncidences() call
225 if (!daychanged
&& !mPendingChanges
) {
229 // TODO_Recurrence: If we just change the selection, but not the data,
230 // there's no need to update the whole list of incidences... This is just a
231 // waste of computational power
233 QMap
<QDate
, QStringList
> holidaysByDate
= KOGlobals::self()->holiday(mDays
[0], mDays
[NUMDAYS
- 1]);
234 for (int i
= 0; i
< NUMDAYS
; ++i
) {
235 //if it is a holy day then draw it red. Sundays are consider holidays, too
236 QStringList holidays
= holidaysByDate
[mDays
[i
]];
239 if ((KOGlobals::self()->calendarSystem()->dayOfWeek(mDays
[i
]) ==
240 KLocale::global()->weekDayOfPray()) ||
241 !holidays
.isEmpty()) {
242 if (!holidays
.isEmpty()) {
243 holiStr
= holidays
.join(i18nc("delimiter for joining holiday names", ","));
245 if (holiStr
.isEmpty()) {
246 holiStr
= QStringLiteral("");
249 mHolidays
[i
] = holiStr
;
253 void KODayMatrix::updateIncidences()
261 if (mHighlightEvents
) {
265 if (mHighlightTodos
) {
269 if (mHighlightJournals
) {
273 mPendingChanges
= false;
276 void KODayMatrix::updateJournals()
278 const KCalCore::Incidence::List incidences
= mCalendar
->incidences();
280 foreach (const KCalCore::Incidence::Ptr
&inc
, incidences
) {
282 QDate d
= inc
->dtStart().toTimeSpec(mCalendar
->timeSpec()).date();
283 if (inc
->type() == KCalCore::Incidence::TypeJournal
&&
285 d
<= mDays
[NUMDAYS
- 1] &&
286 !mEvents
.contains(d
)) {
289 if (mEvents
.count() == NUMDAYS
) {
290 // No point in wasting cpu, all days are bold already
297 * Although updateTodos() is simpler it has some similarities with updateEvent()
298 * but don't bother refactoring them so they share code, there's a bigger fish:
299 * Try to refactor updateTodos(), updateEvent(), updateJournals(), monthview,
300 * agenda view, timespent view, timeline view, event list view and todo list view
301 * all these 9 places have incidence listing code in common, maybe it could go
302 * to kcal. Ah, and then there's kontact's summary view which still uses
303 * the old CPU consuming code.
305 void KODayMatrix::updateTodos()
307 const KCalCore::Todo::List incidences
= mCalendar
->todos();
309 foreach (const KCalCore::Todo::Ptr
&t
, incidences
) {
310 if (mEvents
.count() == NUMDAYS
) {
311 // No point in wasting cpu, all days are bold already
315 if (t
->hasDueDate()) {
316 ushort recurType
= t
->recurrenceType();
319 !(recurType
== KCalCore::Recurrence::rDaily
&& !KOPrefs::instance()->mDailyRecur
) &&
320 !(recurType
== KCalCore::Recurrence::rWeekly
&& !KOPrefs::instance()->mWeeklyRecur
)) {
322 // It's a recurring todo, find out in which days it occurs
323 KCalCore::DateTimeList timeDateList
=
324 t
->recurrence()->timesInInterval(
325 KDateTime(mDays
[0], mCalendar
->timeSpec()),
326 KDateTime(mDays
[NUMDAYS
- 1], mCalendar
->timeSpec()));
328 foreach (const KDateTime
&dt
, timeDateList
) {
329 d
= dt
.toTimeSpec(mCalendar
->timeSpec()).date();
330 if (!mEvents
.contains(d
)) {
336 d
= t
->dtDue().toTimeSpec(mCalendar
->timeSpec()).date();
337 if (d
>= mDays
[0] && d
<= mDays
[NUMDAYS
- 1] && !mEvents
.contains(d
)) {
345 void KODayMatrix::updateEvents()
347 if (mEvents
.count() == NUMDAYS
) {
348 mPendingChanges
= false;
349 // No point in wasting cpu, all days are bold already
352 KCalCore::Event::List eventlist
= mCalendar
->events(mDays
[0], mDays
[NUMDAYS
- 1],
353 mCalendar
->timeSpec());
355 Q_FOREACH (const KCalCore::Event::Ptr
&event
, eventlist
) {
356 if (mEvents
.count() == NUMDAYS
) {
357 // No point in wasting cpu, all days are bold already
362 const ushort recurType
= event
->recurrenceType();
363 const KDateTime dtStart
= event
->dtStart().toTimeSpec(mCalendar
->timeSpec());
365 // timed incidences occur in
366 // [dtStart(), dtEnd()[. All-day incidences occur in [dtStart(), dtEnd()]
367 // so we subtract 1 second in the timed case
368 const int secsToAdd
= event
->allDay() ? 0 : -1;
369 const KDateTime dtEnd
= event
->dtEnd().toTimeSpec(mCalendar
->timeSpec()).addSecs(secsToAdd
);
371 if (!(recurType
== KCalCore::Recurrence::rDaily
&& !KOPrefs::instance()->mDailyRecur
) &&
372 !(recurType
== KCalCore::Recurrence::rWeekly
&& !KOPrefs::instance()->mWeeklyRecur
)) {
374 KCalCore::DateTimeList timeDateList
;
375 const bool isRecurrent
= event
->recurs();
376 const int eventDuration
= dtStart
.daysTo(dtEnd
);
379 //Its a recurring event, find out in which days it occurs
380 timeDateList
= event
->recurrence()->timesInInterval(
381 KDateTime(mDays
[0], mCalendar
->timeSpec()),
382 KDateTime(mDays
[NUMDAYS
- 1], mCalendar
->timeSpec()));
384 if (dtStart
.date() >= mDays
[0]) {
385 timeDateList
.append(dtStart
);
387 // The event starts in another month (not visible))
388 timeDateList
.append(KDateTime(mDays
[0], mCalendar
->timeSpec()));
392 KCalCore::DateTimeList::iterator t
;
393 for (t
= timeDateList
.begin(); t
!= timeDateList
.end(); ++t
) {
394 //This could be a multiday event, so iterate from dtStart() to dtEnd()
395 QDate d
= t
->toTimeSpec(mCalendar
->timeSpec()).date();
400 occurrenceEnd
= d
.addDays(eventDuration
);
402 occurrenceEnd
= dtEnd
.date();
409 } while (d
<= occurrenceEnd
&& j
< NUMDAYS
);
413 mPendingChanges
= false;
416 const QDate
&KODayMatrix::getDate(int offset
) const
418 if (offset
< 0 || offset
> NUMDAYS
- 1) {
421 return mDays
[offset
];
424 QString
KODayMatrix::getHolidayLabel(int offset
) const
426 if (offset
< 0 || offset
> NUMDAYS
- 1) {
429 return mHolidays
[offset
];
432 int KODayMatrix::getDayIndexFrom(int x
, int y
) const
434 return 7 * (y
/ mDaySize
.height()) +
435 (KOGlobals::self()->reverseLayout() ?
436 6 - x
/ mDaySize
.width() : x
/ mDaySize
.width());
439 void KODayMatrix::calendarIncidenceAdded(const KCalCore::Incidence::Ptr
&incidence
)
442 mPendingChanges
= true;
445 void KODayMatrix::calendarIncidenceChanged(const KCalCore::Incidence::Ptr
&incidence
)
448 mPendingChanges
= true;
451 void KODayMatrix::calendarIncidenceDeleted(const KCalCore::Incidence::Ptr
&incidence
)
454 mPendingChanges
= true;
457 void KODayMatrix::setHighlightMode(bool highlightEvents
,
459 bool highlightJournals
)
462 // don't set mPendingChanges to true if nothing changed
463 if (highlightTodos
!= mHighlightTodos
||
464 highlightEvents
!= mHighlightEvents
||
465 highlightJournals
!= mHighlightJournals
) {
466 mHighlightEvents
= highlightEvents
;
467 mHighlightTodos
= highlightTodos
;
468 mHighlightJournals
= highlightJournals
;
469 mPendingChanges
= true;
473 void KODayMatrix::resourcesChanged()
475 mPendingChanges
= true;
478 // ----------------------------------------------------------------------------
479 // M O U S E E V E N T H A N D L I N G
480 // ----------------------------------------------------------------------------
482 bool KODayMatrix::event(QEvent
*event
)
484 if (KOPrefs::instance()->mEnableToolTips
&& event
->type() == QEvent::ToolTip
) {
485 QHelpEvent
*helpEvent
= static_cast<QHelpEvent
*>(event
);
487 // calculate which cell of the matrix the mouse is in
488 QRect sz
= frameRect();
489 int dheight
= sz
.height() * 7 / 42;
490 int dwidth
= sz
.width() / 7;
491 int row
= helpEvent
->pos().y() / dheight
;
492 int col
= helpEvent
->pos().x() / dwidth
;
494 // show holiday names only
495 QString tipText
= getHolidayLabel(col
+ row
* 7);
496 if (!tipText
.isEmpty()) {
497 QToolTip::showText(helpEvent
->globalPos(), tipText
);
499 QToolTip::hideText();
502 return QWidget::event(event
);
505 void KODayMatrix::mousePressEvent(QMouseEvent
*e
)
507 mSelStart
= getDayIndexFrom(e
->x(), e
->y());
508 if (e
->button() == Qt::RightButton
) {
509 popupMenu(mDays
[mSelStart
]);
510 } else if (e
->button() == Qt::LeftButton
) {
511 if (mSelStart
> NUMDAYS
- 1) {
512 mSelStart
= NUMDAYS
- 1;
514 mSelInit
= mSelStart
;
518 void KODayMatrix::popupMenu(const QDate
&date
)
521 popup
.setTitle(date
.toString());
522 QAction
*newEventAction
= popup
.addAction(
523 QIcon::fromTheme(QStringLiteral("appointment-new")), i18n("New E&vent..."));
524 QAction
*newTodoAction
= popup
.addAction(
525 QIcon::fromTheme(QStringLiteral("task-new")), i18n("New &To-do..."));
526 QAction
*newJournalAction
= popup
.addAction(
527 QIcon::fromTheme(QStringLiteral("journal-new")), i18n("New &Journal..."));
528 QAction
*ret
= popup
.exec(QCursor::pos());
529 if (ret
== newEventAction
) {
530 Q_EMIT
newEventSignal(date
);
531 } else if (ret
== newTodoAction
) {
532 Q_EMIT
newTodoSignal(date
);
533 } else if (ret
== newJournalAction
) {
534 Q_EMIT
newJournalSignal(date
);
538 void KODayMatrix::mouseReleaseEvent(QMouseEvent
*e
)
540 if (e
->button() != Qt::LeftButton
) {
544 int tmp
= getDayIndexFrom(e
->x(), e
->y());
545 if (tmp
> NUMDAYS
- 1) {
549 if (mSelInit
> tmp
) {
551 if (tmp
!= mSelStart
) {
556 mSelStart
= mSelInit
;
558 //repaint only if selection has changed
559 if (tmp
!= mSelEnd
) {
565 KCalCore::DateList daylist
;
569 daylist
.reserve(mSelEnd
- mSelStart
+ 1);
570 for (int i
= mSelStart
; i
<= mSelEnd
; ++i
) {
571 daylist
.append(mDays
[i
]);
573 Q_EMIT
selected(static_cast<const KCalCore::DateList
>(daylist
));
576 void KODayMatrix::mouseMoveEvent(QMouseEvent
*e
)
578 int tmp
= getDayIndexFrom(e
->x(), e
->y());
579 if (tmp
> NUMDAYS
- 1) {
583 if (mSelInit
> tmp
) {
585 if (tmp
!= mSelStart
) {
590 mSelStart
= mSelInit
;
592 //repaint only if selection has changed
593 if (tmp
!= mSelEnd
) {
600 // ----------------------------------------------------------------------------
601 // D R A G ' N D R O P H A N D L I N G
602 // ----------------------------------------------------------------------------
604 //-----------------------------------------------------------------------------
605 // Drag and Drop handling -- based on the Troll Tech dirview example
613 void KODayMatrix::dragEnterEvent(QDragEnterEvent
*e
)
615 e
->acceptProposedAction();
616 const QMimeData
*md
= e
->mimeData();
617 if (!CalendarSupport::canDecode(md
)) {
622 // some visual feedback
623 // oldPalette = palette();
624 // setPalette(my_HilitePalette);
628 void KODayMatrix::dragMoveEvent(QDragMoveEvent
*e
)
630 const QMimeData
*md
= e
->mimeData();
631 if (!CalendarSupport::canDecode(md
)) {
638 void KODayMatrix::dragLeaveEvent(QDragLeaveEvent
*dl
)
641 // setPalette(oldPalette);
645 void KODayMatrix::dropEvent(QDropEvent
*e
)
651 QList
<QUrl
> urls
= (e
->mimeData()->urls());
652 //qCDebug(KORGANIZER_LOG)<<" urls :"<<urls;
653 if (urls
.isEmpty()) {
658 //For the moment support 1 url
659 if (urls
.count() >= 1) {
660 QUrl res
= urls
.at(0);
662 Akonadi::ItemFetchJob
*job
= new Akonadi::ItemFetchJob(Akonadi::Item::fromUrl(res
));
663 job
->fetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::Parent
);
664 job
->fetchScope().fetchFullPayload();
665 Akonadi::Item::List items
;
667 items
= job
->items();
669 bool exist
= items
.at(0).isValid();
670 int action
= DRAG_CANCEL
;
672 Qt::KeyboardModifiers keyboardModifiers
= e
->keyboardModifiers();
674 if (keyboardModifiers
& Qt::ControlModifier
) {
676 } else if (keyboardModifiers
& Qt::ShiftModifier
) {
679 QAction
*copy
= Q_NULLPTR
, *move
= Q_NULLPTR
;
680 QMenu
*menu
= new QMenu(this);
682 move
= menu
->addAction(QIcon::fromTheme(QStringLiteral("edit-paste")), i18n("&Move"));
683 if (/*existingEvent*/1) {
684 copy
= menu
->addAction(QIcon::fromTheme(QStringLiteral("edit-copy")), i18n("&Copy"));
687 move
= menu
->addAction(QIcon::fromTheme(QStringLiteral("list-add")), i18n("&Add"));
689 menu
->addSeparator();
690 /*QAction *cancel =*/
691 menu
->addAction(QIcon::fromTheme(QStringLiteral("process-stop")), i18n("&Cancel"));
692 QAction
*a
= menu
->exec(QCursor::pos());
695 } else if (a
== move
) {
701 if (action
== DRAG_COPY
|| action
== DRAG_MOVE
) {
703 int idx
= getDayIndexFrom(e
->pos().x(), e
->pos().y());
705 if (action
== DRAG_COPY
) {
706 Q_EMIT
incidenceDropped(items
.at(0), mDays
[idx
]);
707 } else if (action
== DRAG_MOVE
) {
708 Q_EMIT
incidenceDroppedMove(items
.at(0), mDays
[idx
]);
714 // ----------------------------------------------------------------------------
715 // P A I N T E V E N T H A N D L I N G
716 // ----------------------------------------------------------------------------
718 void KODayMatrix::paintEvent(QPaintEvent
*)
721 const QRect rect
= frameRect();
722 const int dayHeight
= mDaySize
.height();
723 const int dayWidth
= mDaySize
.width();
725 int selectionWidth
, selectionHeight
;
726 const bool isRTL
= KOGlobals::self()->reverseLayout();
728 QPalette pal
= palette();
733 p
.fillRect(0, 0, rect
.width(), rect
.height(), QBrush(pal
.color(QPalette::Base
)));
735 // draw topleft frame
736 p
.setPen(pal
.color(QPalette::Mid
));
737 p
.drawRect(0, 0, rect
.width() - 1, rect
.height() - 1);
738 // don't paint over borders
741 // draw selected days with highlighted background color
742 if (mSelStart
!= NOSELECTION
) {
745 // fix larger selections starting in the previous month
746 if (row
< 0 && mSelEnd
> 0) {
749 column
= mSelStart
- row
* 7;
750 const QColor selectionColor
= KOPrefs::instance()->agendaGridHighlightColor();
752 if (row
< 6 && row
>= 0) {
753 if (row
== mSelEnd
/ 7) {
754 // Single row selection
756 (7 - (mSelEnd
- mSelStart
+ 1) - column
) * dayWidth
:
759 (mSelEnd
- mSelStart
+ 1) * dayWidth
, dayHeight
, selectionColor
);
761 // draw first row to the right
762 p
.fillRect(isRTL
? 0 : column
* dayWidth
, row
* dayHeight
,
763 (7 - column
) * dayWidth
, dayHeight
, selectionColor
);
764 // draw full block till last line
765 selectionHeight
= mSelEnd
/ 7 - row
;
766 if (selectionHeight
+ row
>= 6) {
767 selectionHeight
= 6 - row
;
769 if (selectionHeight
> 1) {
770 p
.fillRect(0, (row
+ 1) * dayHeight
, 7 * dayWidth
,
771 (selectionHeight
- 1) * dayHeight
, selectionColor
);
773 // draw last block from left to mSelEnd
774 if (mSelEnd
/ 7 < 6) {
775 selectionWidth
= mSelEnd
- 7 * (mSelEnd
/ 7) + 1;
777 (7 - selectionWidth
) * dayWidth
:
779 (row
+ selectionHeight
) * dayHeight
,
780 selectionWidth
* dayWidth
, dayHeight
, selectionColor
);
786 // iterate over all days in the matrix and draw the day label in appropriate colors
787 const QColor textColor
= pal
.color(QPalette::Text
);
788 const QColor textColorShaded
= getShadedColor(textColor
);
789 QColor actcol
= textColorShaded
;
793 const QList
<QDate
> workDays
= KOGlobals::self()->workDays(mDays
[0], mDays
[NUMDAYS
- 1]);
794 for (int i
= 0; i
< NUMDAYS
; ++i
) {
796 column
= isRTL
? 6 - (i
- row
* 7) : i
- row
* 7;
798 // if it is the first day of a month switch color from normal to shaded and vice versa
799 if (KOGlobals::self()->calendarSystem()->day(mDays
[i
]) == 1) {
800 if (actcol
== textColorShaded
) {
803 actcol
= textColorShaded
;
808 //Reset pen color after selected days block
809 if (i
== mSelEnd
+ 1) {
813 const bool holiday
= !workDays
.contains(mDays
[i
]);
815 const QColor holidayColorShaded
=
816 getShadedColor(KOPrefs::instance()->agendaHolidaysBackgroundColor());
818 // if today then draw rectangle around day
821 QPen
todayPen(p
.pen());
823 todayPen
.setWidth(mTodayMarginWidth
);
824 //draw red rectangle for holidays
826 if (actcol
== textColor
) {
827 todayPen
.setColor(KOPrefs::instance()->agendaHolidaysBackgroundColor());
829 todayPen
.setColor(holidayColorShaded
);
832 //draw gray rectangle for today if in selection
833 if (i
>= mSelStart
&& i
<= mSelEnd
) {
834 const QColor
grey(QStringLiteral("grey"));
835 todayPen
.setColor(grey
);
838 p
.drawRect(column
* dayWidth
, row
* dayHeight
, dayWidth
, dayHeight
);
842 // if any events are on that day then draw it using a bold font
843 if (mEvents
.contains(mDays
[i
])) {
844 QFont myFont
= font();
845 myFont
.setBold(true);
849 // if it is a holiday then use the default holiday color
851 if (actcol
== textColor
) {
852 p
.setPen(KOPrefs::instance()->agendaHolidaysBackgroundColor());
854 p
.setPen(holidayColorShaded
);
858 // draw selected days with special color
859 if (i
>= mSelStart
&& i
<= mSelEnd
&& !holiday
) {
863 p
.drawText(column
* dayWidth
, row
* dayHeight
, dayWidth
, dayHeight
,
864 Qt::AlignHCenter
| Qt::AlignVCenter
, mDayLabels
[i
]);
866 // reset color to actual color
870 // reset bold font to plain font
871 if (mEvents
.contains(mDays
[i
]) > 0) {
872 QFont myFont
= font();
873 myFont
.setBold(false);
880 // ----------------------------------------------------------------------------
881 // R E SI Z E E V E N T H A N D L I N G
882 // ----------------------------------------------------------------------------
884 void KODayMatrix::resizeEvent(QResizeEvent
*)
886 QRect sz
= frameRect();
887 mDaySize
.setHeight(sz
.height() * 7 / NUMDAYS
);
888 mDaySize
.setWidth(sz
.width() / 7);
892 QPair
<QDate
, QDate
> KODayMatrix::matrixLimits(const QDate
&month
)
894 const KCalendarSystem
*calSys
= KOGlobals::self()->calendarSystem();
896 calSys
->setDate(d
, calSys
->year(month
), calSys
->month(month
), 1);
898 const int dayOfWeek
= calSys
->dayOfWeek(d
);
899 const int weekstart
= QLocale().firstDayOfWeek();
901 d
= d
.addDays(-(7 + dayOfWeek
- weekstart
) % 7);
903 if (dayOfWeek
== weekstart
) {
904 d
= d
.addDays(-7); // Start on the second line
907 return qMakePair(d
, d
.addDays(NUMDAYS
- 1));