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
, const KCalCore::Calendar
*calendar
)
455 mPendingChanges
= true;
458 void KODayMatrix::setHighlightMode(bool highlightEvents
,
460 bool highlightJournals
)
463 // don't set mPendingChanges to true if nothing changed
464 if (highlightTodos
!= mHighlightTodos
||
465 highlightEvents
!= mHighlightEvents
||
466 highlightJournals
!= mHighlightJournals
) {
467 mHighlightEvents
= highlightEvents
;
468 mHighlightTodos
= highlightTodos
;
469 mHighlightJournals
= highlightJournals
;
470 mPendingChanges
= true;
474 void KODayMatrix::resourcesChanged()
476 mPendingChanges
= true;
479 // ----------------------------------------------------------------------------
480 // M O U S E E V E N T H A N D L I N G
481 // ----------------------------------------------------------------------------
483 bool KODayMatrix::event(QEvent
*event
)
485 if (KOPrefs::instance()->mEnableToolTips
&& event
->type() == QEvent::ToolTip
) {
486 QHelpEvent
*helpEvent
= static_cast<QHelpEvent
*>(event
);
488 // calculate which cell of the matrix the mouse is in
489 QRect sz
= frameRect();
490 int dheight
= sz
.height() * 7 / 42;
491 int dwidth
= sz
.width() / 7;
492 int row
= helpEvent
->pos().y() / dheight
;
493 int col
= helpEvent
->pos().x() / dwidth
;
495 // show holiday names only
496 QString tipText
= getHolidayLabel(col
+ row
* 7);
497 if (!tipText
.isEmpty()) {
498 QToolTip::showText(helpEvent
->globalPos(), tipText
);
500 QToolTip::hideText();
503 return QWidget::event(event
);
506 void KODayMatrix::mousePressEvent(QMouseEvent
*e
)
508 mSelStart
= getDayIndexFrom(e
->x(), e
->y());
509 if (e
->button() == Qt::RightButton
) {
510 popupMenu(mDays
[mSelStart
]);
511 } else if (e
->button() == Qt::LeftButton
) {
512 if (mSelStart
> NUMDAYS
- 1) {
513 mSelStart
= NUMDAYS
- 1;
515 mSelInit
= mSelStart
;
519 void KODayMatrix::popupMenu(const QDate
&date
)
522 popup
.setTitle(date
.toString());
523 QAction
*newEventAction
= popup
.addAction(
524 QIcon::fromTheme(QStringLiteral("appointment-new")), i18n("New E&vent..."));
525 QAction
*newTodoAction
= popup
.addAction(
526 QIcon::fromTheme(QStringLiteral("task-new")), i18n("New &To-do..."));
527 QAction
*newJournalAction
= popup
.addAction(
528 QIcon::fromTheme(QStringLiteral("journal-new")), i18n("New &Journal..."));
529 QAction
*ret
= popup
.exec(QCursor::pos());
530 if (ret
== newEventAction
) {
531 Q_EMIT
newEventSignal(date
);
532 } else if (ret
== newTodoAction
) {
533 Q_EMIT
newTodoSignal(date
);
534 } else if (ret
== newJournalAction
) {
535 Q_EMIT
newJournalSignal(date
);
539 void KODayMatrix::mouseReleaseEvent(QMouseEvent
*e
)
541 if (e
->button() != Qt::LeftButton
) {
545 int tmp
= getDayIndexFrom(e
->x(), e
->y());
546 if (tmp
> NUMDAYS
- 1) {
550 if (mSelInit
> tmp
) {
552 if (tmp
!= mSelStart
) {
557 mSelStart
= mSelInit
;
559 //repaint only if selection has changed
560 if (tmp
!= mSelEnd
) {
566 KCalCore::DateList daylist
;
570 daylist
.reserve(mSelEnd
- mSelStart
+ 1);
571 for (int i
= mSelStart
; i
<= mSelEnd
; ++i
) {
572 daylist
.append(mDays
[i
]);
574 Q_EMIT
selected(static_cast<const KCalCore::DateList
>(daylist
));
577 void KODayMatrix::mouseMoveEvent(QMouseEvent
*e
)
579 int tmp
= getDayIndexFrom(e
->x(), e
->y());
580 if (tmp
> NUMDAYS
- 1) {
584 if (mSelInit
> tmp
) {
586 if (tmp
!= mSelStart
) {
591 mSelStart
= mSelInit
;
593 //repaint only if selection has changed
594 if (tmp
!= mSelEnd
) {
601 // ----------------------------------------------------------------------------
602 // D R A G ' N D R O P H A N D L I N G
603 // ----------------------------------------------------------------------------
605 //-----------------------------------------------------------------------------
606 // Drag and Drop handling -- based on the Troll Tech dirview example
614 void KODayMatrix::dragEnterEvent(QDragEnterEvent
*e
)
616 e
->acceptProposedAction();
617 const QMimeData
*md
= e
->mimeData();
618 if (!CalendarSupport::canDecode(md
)) {
623 // some visual feedback
624 // oldPalette = palette();
625 // setPalette(my_HilitePalette);
629 void KODayMatrix::dragMoveEvent(QDragMoveEvent
*e
)
631 const QMimeData
*md
= e
->mimeData();
632 if (!CalendarSupport::canDecode(md
)) {
639 void KODayMatrix::dragLeaveEvent(QDragLeaveEvent
*dl
)
642 // setPalette(oldPalette);
646 void KODayMatrix::dropEvent(QDropEvent
*e
)
652 QList
<QUrl
> urls
= (e
->mimeData()->urls());
653 //qCDebug(KORGANIZER_LOG)<<" urls :"<<urls;
654 if (urls
.isEmpty()) {
659 //For the moment support 1 url
660 if (urls
.count() >= 1) {
661 QUrl res
= urls
.at(0);
663 Akonadi::ItemFetchJob
*job
= new Akonadi::ItemFetchJob(Akonadi::Item::fromUrl(res
));
664 job
->fetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::Parent
);
665 job
->fetchScope().fetchFullPayload();
666 Akonadi::Item::List items
;
668 items
= job
->items();
670 bool exist
= items
.at(0).isValid();
671 int action
= DRAG_CANCEL
;
673 Qt::KeyboardModifiers keyboardModifiers
= e
->keyboardModifiers();
675 if (keyboardModifiers
& Qt::ControlModifier
) {
677 } else if (keyboardModifiers
& Qt::ShiftModifier
) {
680 QAction
*copy
= Q_NULLPTR
, *move
= Q_NULLPTR
;
681 QMenu
*menu
= new QMenu(this);
683 move
= menu
->addAction(QIcon::fromTheme(QStringLiteral("edit-paste")), i18n("&Move"));
684 if (/*existingEvent*/1) {
685 copy
= menu
->addAction(QIcon::fromTheme(QStringLiteral("edit-copy")), i18n("&Copy"));
688 move
= menu
->addAction(QIcon::fromTheme(QStringLiteral("list-add")), i18n("&Add"));
690 menu
->addSeparator();
691 /*QAction *cancel =*/
692 menu
->addAction(QIcon::fromTheme(QStringLiteral("process-stop")), i18n("&Cancel"));
693 QAction
*a
= menu
->exec(QCursor::pos());
696 } else if (a
== move
) {
702 if (action
== DRAG_COPY
|| action
== DRAG_MOVE
) {
704 int idx
= getDayIndexFrom(e
->pos().x(), e
->pos().y());
706 if (action
== DRAG_COPY
) {
707 Q_EMIT
incidenceDropped(items
.at(0), mDays
[idx
]);
708 } else if (action
== DRAG_MOVE
) {
709 Q_EMIT
incidenceDroppedMove(items
.at(0), mDays
[idx
]);
715 // ----------------------------------------------------------------------------
716 // P A I N T E V E N T H A N D L I N G
717 // ----------------------------------------------------------------------------
719 void KODayMatrix::paintEvent(QPaintEvent
*)
722 const QRect rect
= frameRect();
723 const int dayHeight
= mDaySize
.height();
724 const int dayWidth
= mDaySize
.width();
726 int selectionWidth
, selectionHeight
;
727 const bool isRTL
= KOGlobals::self()->reverseLayout();
729 QPalette pal
= palette();
734 p
.fillRect(0, 0, rect
.width(), rect
.height(), QBrush(pal
.color(QPalette::Base
)));
736 // draw topleft frame
737 p
.setPen(pal
.color(QPalette::Mid
));
738 p
.drawRect(0, 0, rect
.width() - 1, rect
.height() - 1);
739 // don't paint over borders
742 // draw selected days with highlighted background color
743 if (mSelStart
!= NOSELECTION
) {
746 // fix larger selections starting in the previous month
747 if (row
< 0 && mSelEnd
> 0) {
750 column
= mSelStart
- row
* 7;
751 const QColor selectionColor
= KOPrefs::instance()->agendaGridHighlightColor();
753 if (row
< 6 && row
>= 0) {
754 if (row
== mSelEnd
/ 7) {
755 // Single row selection
757 (7 - (mSelEnd
- mSelStart
+ 1) - column
) * dayWidth
:
760 (mSelEnd
- mSelStart
+ 1) * dayWidth
, dayHeight
, selectionColor
);
762 // draw first row to the right
763 p
.fillRect(isRTL
? 0 : column
* dayWidth
, row
* dayHeight
,
764 (7 - column
) * dayWidth
, dayHeight
, selectionColor
);
765 // draw full block till last line
766 selectionHeight
= mSelEnd
/ 7 - row
;
767 if (selectionHeight
+ row
>= 6) {
768 selectionHeight
= 6 - row
;
770 if (selectionHeight
> 1) {
771 p
.fillRect(0, (row
+ 1) * dayHeight
, 7 * dayWidth
,
772 (selectionHeight
- 1) * dayHeight
, selectionColor
);
774 // draw last block from left to mSelEnd
775 if (mSelEnd
/ 7 < 6) {
776 selectionWidth
= mSelEnd
- 7 * (mSelEnd
/ 7) + 1;
778 (7 - selectionWidth
) * dayWidth
:
780 (row
+ selectionHeight
) * dayHeight
,
781 selectionWidth
* dayWidth
, dayHeight
, selectionColor
);
787 // iterate over all days in the matrix and draw the day label in appropriate colors
788 const QColor textColor
= pal
.color(QPalette::Text
);
789 const QColor textColorShaded
= getShadedColor(textColor
);
790 QColor actcol
= textColorShaded
;
794 const QList
<QDate
> workDays
= KOGlobals::self()->workDays(mDays
[0], mDays
[NUMDAYS
- 1]);
795 for (int i
= 0; i
< NUMDAYS
; ++i
) {
797 column
= isRTL
? 6 - (i
- row
* 7) : i
- row
* 7;
799 // if it is the first day of a month switch color from normal to shaded and vice versa
800 if (KOGlobals::self()->calendarSystem()->day(mDays
[i
]) == 1) {
801 if (actcol
== textColorShaded
) {
804 actcol
= textColorShaded
;
809 //Reset pen color after selected days block
810 if (i
== mSelEnd
+ 1) {
814 const bool holiday
= !workDays
.contains(mDays
[i
]);
816 const QColor holidayColorShaded
=
817 getShadedColor(KOPrefs::instance()->agendaHolidaysBackgroundColor());
819 // if today then draw rectangle around day
822 QPen
todayPen(p
.pen());
824 todayPen
.setWidth(mTodayMarginWidth
);
825 //draw red rectangle for holidays
827 if (actcol
== textColor
) {
828 todayPen
.setColor(KOPrefs::instance()->agendaHolidaysBackgroundColor());
830 todayPen
.setColor(holidayColorShaded
);
833 //draw gray rectangle for today if in selection
834 if (i
>= mSelStart
&& i
<= mSelEnd
) {
835 const QColor
grey(QStringLiteral("grey"));
836 todayPen
.setColor(grey
);
839 p
.drawRect(column
* dayWidth
, row
* dayHeight
, dayWidth
, dayHeight
);
843 // if any events are on that day then draw it using a bold font
844 if (mEvents
.contains(mDays
[i
])) {
845 QFont myFont
= font();
846 myFont
.setBold(true);
850 // if it is a holiday then use the default holiday color
852 if (actcol
== textColor
) {
853 p
.setPen(KOPrefs::instance()->agendaHolidaysBackgroundColor());
855 p
.setPen(holidayColorShaded
);
859 // draw selected days with special color
860 if (i
>= mSelStart
&& i
<= mSelEnd
&& !holiday
) {
864 p
.drawText(column
* dayWidth
, row
* dayHeight
, dayWidth
, dayHeight
,
865 Qt::AlignHCenter
| Qt::AlignVCenter
, mDayLabels
[i
]);
867 // reset color to actual color
871 // reset bold font to plain font
872 if (mEvents
.contains(mDays
[i
]) > 0) {
873 QFont myFont
= font();
874 myFont
.setBold(false);
881 // ----------------------------------------------------------------------------
882 // R E SI Z E E V E N T H A N D L I N G
883 // ----------------------------------------------------------------------------
885 void KODayMatrix::resizeEvent(QResizeEvent
*)
887 QRect sz
= frameRect();
888 mDaySize
.setHeight(sz
.height() * 7 / NUMDAYS
);
889 mDaySize
.setWidth(sz
.width() / 7);
893 QPair
<QDate
, QDate
> KODayMatrix::matrixLimits(const QDate
&month
)
895 const KCalendarSystem
*calSys
= KOGlobals::self()->calendarSystem();
897 calSys
->setDate(d
, calSys
->year(month
), calSys
->month(month
), 1);
899 const int dayOfWeek
= calSys
->dayOfWeek(d
);
900 const int weekstart
= QLocale().firstDayOfWeek();
902 d
= d
.addDays(-(7 + dayOfWeek
- weekstart
) % 7);
904 if (dayOfWeek
== weekstart
) {
905 d
= d
.addDays(-7); // Start on the second line
908 return qMakePair(d
, d
.addDays(NUMDAYS
- 1));