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"
33 #include <calendarsupport/utils.h>
35 #include <Akonadi/ItemFetchJob>
36 #include <Akonadi/ItemFetchScope>
38 #include <KCalendarSystem>
42 #include <QMouseEvent>
46 // ============================================================================
47 // K O D A Y M A T R I X
48 // ============================================================================
50 const int KODayMatrix::NOSELECTION
= -1000;
51 const int KODayMatrix::NUMDAYS
= 42;
53 KODayMatrix::KODayMatrix( QWidget
*parent
)
54 : QFrame( parent
), mCalendar( 0 ), mStartDate(), mPendingChanges( false )
56 // initialize dynamic arrays
57 mDays
= new QDate
[NUMDAYS
];
58 mDayLabels
= new QString
[NUMDAYS
];
60 mTodayMarginWidth
= 2;
61 mSelEnd
= mSelStart
= NOSELECTION
;
65 mHighlightEvents
= true;
66 mHighlightTodos
= false;
67 mHighlightJournals
= false;
70 void KODayMatrix::setCalendar( CalendarSupport::Calendar
*cal
)
73 mCalendar
->unregisterObserver( this );
74 mCalendar
->disconnect( this );
78 mCalendar
->registerObserver( this );
80 setAcceptDrops( mCalendar
!= 0 );
84 QColor
KODayMatrix::getShadedColor( const QColor
&color
) const
90 color
.getHsv( &h
, &s
, &v
);
93 shaded
.setHsv( h
, s
, v
);
98 KODayMatrix::~KODayMatrix()
101 mCalendar
->unregisterObserver( this );
105 delete [] mDayLabels
;
108 void KODayMatrix::addSelectedDaysTo( KCalCore::DateList
&selDays
)
110 if ( mSelStart
== NOSELECTION
) {
114 // cope with selection being out of matrix limits at top (< 0)
117 for ( int i
= i0
; i
< 0; i
++ ) {
118 selDays
.append( mDays
[0].addDays( i
) );
123 // cope with selection being out of matrix limits at bottom (> NUMDAYS-1)
124 if ( mSelEnd
> NUMDAYS
-1 ) {
125 for ( int i
= i0
; i
<= NUMDAYS
- 1; i
++ ) {
126 selDays
.append( mDays
[i
] );
128 for ( int i
= NUMDAYS
; i
< mSelEnd
; i
++ ) {
129 selDays
.append( mDays
[0].addDays( i
) );
132 // apply normal routine to selection being entirely within matrix limits
133 for ( int i
= i0
; i
<= mSelEnd
; i
++ ) {
134 selDays
.append( mDays
[i
] );
139 void KODayMatrix::setSelectedDaysFrom( const QDate
&start
, const QDate
&end
)
141 if ( mStartDate
.isValid() ) {
142 mSelStart
= mStartDate
.daysTo( start
);
143 mSelEnd
= mStartDate
.daysTo( end
);
147 void KODayMatrix::clearSelection()
149 mSelEnd
= mSelStart
= NOSELECTION
;
152 void KODayMatrix::recalculateToday()
154 if ( !mStartDate
.isValid() ) {
159 for ( int i
= 0; i
< NUMDAYS
; i
++ ) {
160 mDays
[i
] = mStartDate
.addDays( i
);
161 mDayLabels
[i
] = QString::number( KOGlobals::self()->calendarSystem()->day( mDays
[i
] ) );
163 // if today is in the currently displayed month, hilight today
164 if ( mDays
[i
].year() == QDate::currentDate().year() &&
165 mDays
[i
].month() == QDate::currentDate().month() &&
166 mDays
[i
].day() == QDate::currentDate().day() ) {
172 void KODayMatrix::updateView()
174 updateView( mStartDate
);
177 void KODayMatrix::setUpdateNeeded()
179 mPendingChanges
= true;
182 void KODayMatrix::updateView( const QDate
&actdate
)
184 if ( !actdate
.isValid() || NUMDAYS
< 1 ) {
187 //flag to indicate if the starting day of the matrix has changed by this call
188 bool daychanged
= false;
190 // if a new startdate is to be set then apply Cornelius's calculation
191 // of the first day to be shown
192 if ( actdate
!= mStartDate
) {
193 // reset index of selection according to shift of starting date from
194 // startdate to actdate.
195 if ( mSelStart
!= NOSELECTION
) {
196 int tmp
= actdate
.daysTo( mStartDate
);
197 // shift selection if new one would be visible at least partly !
198 if ( mSelStart
+ tmp
< NUMDAYS
&& mSelEnd
+ tmp
>= 0 ) {
199 // nested if required for next X display pushed from a different month
200 // correction required. otherwise, for month forward and backward,
201 // it must be avoided.
202 if ( mSelStart
> NUMDAYS
|| mSelStart
< 0 ) {
203 mSelStart
= mSelStart
+ tmp
;
205 if ( mSelEnd
> NUMDAYS
|| mSelEnd
< 0 ) {
206 mSelEnd
= mSelEnd
+ tmp
;
211 mStartDate
= actdate
;
219 // The calendar has not changed in the meantime and the selected range
220 // is still the same so we can save the expensive updateIncidences() call
221 if ( !daychanged
&& !mPendingChanges
) {
225 // TODO_Recurrence: If we just change the selection, but not the data,
226 // there's no need to update the whole list of incidences... This is just a
227 // waste of computational power
229 QMap
<QDate
,QStringList
> holidaysByDate
= KOGlobals::self()->holiday( mDays
[0], mDays
[NUMDAYS
-1] );
230 for ( int i
= 0; i
< NUMDAYS
; i
++ ) {
231 //if it is a holy day then draw it red. Sundays are consider holidays, too
232 QStringList holidays
= holidaysByDate
[mDays
[i
]];
235 if ( ( KOGlobals::self()->calendarSystem()->dayOfWeek( mDays
[i
] ) ==
236 KGlobal::locale()->weekDayOfPray() ) ||
237 !holidays
.isEmpty() ) {
238 if ( !holidays
.isEmpty() ) {
239 holiStr
= holidays
.join( i18nc( "delimiter for joining holiday names", "," ) );
241 if ( holiStr
.isEmpty() ) {
245 mHolidays
[i
] = holiStr
;
249 void KODayMatrix::updateIncidences()
257 if ( mHighlightEvents
) {
261 if ( mHighlightTodos
) {
265 if ( mHighlightJournals
) {
269 mPendingChanges
= false;
272 void KODayMatrix::updateJournals()
274 const Akonadi::Item::List items
= mCalendar
->incidences();
276 foreach ( const Akonadi::Item
& item
, items
) {
277 KCalCore::Incidence::Ptr inc
= CalendarSupport::incidence( item
);
279 QDate d
= inc
->dtStart().toTimeSpec( mCalendar
->timeSpec() ).date();
280 if ( inc
->type() == KCalCore::Incidence::TypeJournal
&&
282 d
<= mDays
[NUMDAYS
-1] &&
283 !mEvents
.contains( d
) ) {
286 if ( mEvents
.count() == NUMDAYS
) {
287 // No point in wasting cpu, all days are bold already
294 * Although updateTodos() is simpler it has some similarities with updateEvent()
295 * but don't bother refactoring them so they share code, there's a bigger fish:
296 * Try to refactor updateTodos(), updateEvent(), updateJournals(), monthview,
297 * agenda view, timespent view, timeline view, event list view and todo list view
298 * all these 9 places have incidence listing code in common, maybe it could go
299 * to kcal. Ah, and then there's kontact's summary view which still uses
300 * the old CPU consuming code.
302 void KODayMatrix::updateTodos()
304 const Akonadi::Item::List items
= mCalendar
->todos();
306 foreach ( const Akonadi::Item
&item
, items
) {
307 if ( mEvents
.count() == NUMDAYS
) {
308 // No point in wasting cpu, all days are bold already
311 const KCalCore::Todo::Ptr t
= CalendarSupport::todo( item
);
313 if ( t
->hasDueDate() ) {
314 ushort recurType
= t
->recurrenceType();
317 !( recurType
== KCalCore::Recurrence::rDaily
&& !KOPrefs::instance()->mDailyRecur
) &&
318 !( recurType
== KCalCore::Recurrence::rWeekly
&& !KOPrefs::instance()->mWeeklyRecur
) ) {
320 // It's a recurring todo, find out in which days it occurs
321 KCalCore::DateTimeList timeDateList
=
322 t
->recurrence()->timesInInterval(
323 KDateTime( mDays
[0], mCalendar
->timeSpec() ),
324 KDateTime( mDays
[NUMDAYS
-1], mCalendar
->timeSpec() ) );
326 foreach ( const KDateTime
&dt
, timeDateList
) {
327 d
= dt
.toTimeSpec( mCalendar
->timeSpec() ).date();
328 if ( !mEvents
.contains( d
) ) {
334 d
= t
->dtDue().toTimeSpec( mCalendar
->timeSpec() ).date();
335 if ( d
>= mDays
[0] && d
<= mDays
[NUMDAYS
-1] && !mEvents
.contains( d
) ) {
343 void KODayMatrix::updateEvents()
345 if ( mEvents
.count() == NUMDAYS
) {
346 mPendingChanges
= false;
347 // No point in wasting cpu, all days are bold already
350 Akonadi::Item::List eventlist
= mCalendar
->events( mDays
[0], mDays
[NUMDAYS
-1],
351 mCalendar
->timeSpec() );
353 Q_FOREACH ( const Akonadi::Item
& item
, eventlist
) {
354 if ( mEvents
.count() == NUMDAYS
) {
355 // No point in wasting cpu, all days are bold already
358 const KCalCore::Event::Ptr event
= CalendarSupport::event( item
);
360 const ushort recurType
= event
->recurrenceType();
362 const KDateTime dtStart
= event
->dtStart().toTimeSpec( mCalendar
->timeSpec() );
364 // timed incidences occur in
365 // [dtStart(), dtEnd()[. All-day incidences occur in [dtStart(), dtEnd()]
366 // so we subtract 1 second in the timed case
367 const int secsToAdd
= event
->allDay() ? 0 : -1;
368 const KDateTime dtEnd
= event
->dtEnd().toTimeSpec( mCalendar
->timeSpec() ).addSecs( secsToAdd
);
370 if ( !( recurType
== KCalCore::Recurrence::rDaily
&& !KOPrefs::instance()->mDailyRecur
) &&
371 !( recurType
== KCalCore::Recurrence::rWeekly
&& !KOPrefs::instance()->mWeeklyRecur
) ) {
373 KCalCore::DateTimeList timeDateList
;
374 const bool isRecurrent
= event
->recurs();
375 const int eventDuration
= dtStart
.daysTo( dtEnd
);
378 //Its a recurring event, find out in which days it occurs
379 timeDateList
= event
->recurrence()->timesInInterval(
380 KDateTime( mDays
[0], mCalendar
->timeSpec() ),
381 KDateTime( mDays
[NUMDAYS
-1], mCalendar
->timeSpec() ) );
383 if ( dtStart
.date() >= mDays
[0] ) {
384 timeDateList
.append( dtStart
);
386 // The event starts in another month (not visible))
387 timeDateList
.append( KDateTime( mDays
[0], mCalendar
->timeSpec() ) );
391 KCalCore::DateTimeList::iterator t
;
392 for ( t
=timeDateList
.begin(); t
!= timeDateList
.end(); ++t
) {
393 //This could be a multiday event, so iterate from dtStart() to dtEnd()
394 QDate d
= t
->toTimeSpec( mCalendar
->timeSpec() ).date();
399 occurrenceEnd
= d
.addDays( eventDuration
);
401 occurrenceEnd
= dtEnd
.date();
408 } while ( d
<= occurrenceEnd
&& j
< NUMDAYS
);
412 mPendingChanges
= false;
415 const QDate
&KODayMatrix::getDate( int offset
) const
417 if ( offset
< 0 || offset
> NUMDAYS
- 1 ) {
420 return mDays
[offset
];
423 QString
KODayMatrix::getHolidayLabel( int offset
) const
425 if ( offset
< 0 || offset
> NUMDAYS
- 1 ) {
428 return mHolidays
[offset
];
431 int KODayMatrix::getDayIndexFrom( int x
, int y
) const
433 return 7 * ( y
/ mDaySize
.height() ) +
434 ( KOGlobals::self()->reverseLayout() ?
435 6 - x
/ mDaySize
.width() : x
/ mDaySize
.width() );
438 void KODayMatrix::calendarIncidenceAdded( const Akonadi::Item
&incidence
)
440 Q_UNUSED( incidence
);
441 mPendingChanges
= true;
444 void KODayMatrix::calendarIncidenceChanged( const Akonadi::Item
&incidence
)
446 Q_UNUSED( incidence
);
447 mPendingChanges
= true;
450 void KODayMatrix::calendarIncidenceDeleted( const Akonadi::Item
&incidence
)
452 Q_UNUSED( incidence
);
453 mPendingChanges
= true;
456 void KODayMatrix::setHighlightMode( bool highlightEvents
,
458 bool highlightJournals
) {
460 // don't set mPendingChanges to true if nothing changed
461 if ( highlightTodos
!= mHighlightTodos
||
462 highlightEvents
!= mHighlightEvents
||
463 highlightJournals
!= mHighlightJournals
) {
464 mHighlightEvents
= highlightEvents
;
465 mHighlightTodos
= highlightTodos
;
466 mHighlightJournals
= highlightJournals
;
467 mPendingChanges
= true;
471 void KODayMatrix::resourcesChanged()
473 mPendingChanges
= true;
476 // ----------------------------------------------------------------------------
477 // M O U S E E V E N T H A N D L I N G
478 // ----------------------------------------------------------------------------
480 bool KODayMatrix::event( QEvent
*event
)
482 if ( KOPrefs::instance()->mEnableToolTips
&& event
->type() == QEvent::ToolTip
) {
483 QHelpEvent
*helpEvent
= static_cast<QHelpEvent
*>( event
);
485 // calculate which cell of the matrix the mouse is in
486 QRect sz
= frameRect();
487 int dheight
= sz
.height() * 7 / 42;
488 int dwidth
= sz
.width() / 7;
489 int row
= helpEvent
->pos().y() / dheight
;
490 int col
= helpEvent
->pos().x() / dwidth
;
492 // show holiday names only
493 QString tipText
= getHolidayLabel( col
+ row
* 7 );
494 if ( !tipText
.isEmpty() ) {
495 QToolTip::showText( helpEvent
->globalPos(), tipText
);
497 QToolTip::hideText();
500 return QWidget::event( event
);
503 void KODayMatrix::mousePressEvent( QMouseEvent
*e
)
505 mSelStart
= getDayIndexFrom( e
->x(), e
->y() );
506 if ( e
->button() == Qt::RightButton
) {
507 popupMenu( mDays
[mSelStart
] ) ;
508 } else if ( e
->button() == Qt::LeftButton
) {
509 if ( mSelStart
> NUMDAYS
- 1 ) {
510 mSelStart
= NUMDAYS
- 1;
512 mSelInit
= mSelStart
;
516 void KODayMatrix::popupMenu( const QDate
&date
)
519 popup
.addTitle( date
.toString() );
520 QAction
*newEventAction
= popup
.addAction(
521 KIcon( "appointment-new" ), i18n( "New E&vent..." ) );
522 QAction
*newTodoAction
= popup
.addAction(
523 KIcon( "task-new" ), i18n( "New &To-do..." ) );
524 QAction
*newJournalAction
= popup
.addAction(
525 KIcon( "journal-new" ), i18n( "New &Journal..." ) );
526 QAction
*ret
= popup
.exec( QCursor::pos() );
527 if ( ret
== newEventAction
) {
528 emit
newEventSignal( date
);
529 } else if ( ret
== newTodoAction
) {
530 emit
newTodoSignal( date
);
531 } else if ( ret
== newJournalAction
) {
532 emit
newJournalSignal( date
);
536 void KODayMatrix::mouseReleaseEvent( QMouseEvent
*e
)
538 if ( e
->button() != Qt::LeftButton
) {
542 int tmp
= getDayIndexFrom( e
->x(), e
->y() );
543 if ( tmp
> NUMDAYS
- 1 ) {
547 if ( mSelInit
> tmp
) {
549 if ( tmp
!= mSelStart
) {
554 mSelStart
= mSelInit
;
556 //repaint only if selection has changed
557 if ( tmp
!= mSelEnd
) {
563 KCalCore::DateList daylist
;
564 if ( mSelStart
< 0 ) {
567 for ( int i
= mSelStart
; i
<= mSelEnd
; ++i
) {
568 daylist
.append( mDays
[i
] );
570 emit
selected( static_cast<const KCalCore::DateList
>(daylist
) );
573 void KODayMatrix::mouseMoveEvent( QMouseEvent
*e
)
575 int tmp
= getDayIndexFrom( e
->x(), e
->y() );
576 if ( tmp
> NUMDAYS
- 1 ) {
580 if ( mSelInit
> tmp
) {
582 if ( tmp
!= mSelStart
) {
587 mSelStart
= mSelInit
;
589 //repaint only if selection has changed
590 if ( tmp
!= mSelEnd
) {
597 // ----------------------------------------------------------------------------
598 // D R A G ' N D R O P H A N D L I N G
599 // ----------------------------------------------------------------------------
601 //-----------------------------------------------------------------------------
602 // Drag and Drop handling -- based on the Troll Tech dirview example
610 void KODayMatrix::dragEnterEvent( QDragEnterEvent
*e
)
612 e
->acceptProposedAction();
613 const QMimeData
*md
= e
->mimeData();
614 if ( !CalendarSupport::canDecode( md
) ) {
619 // some visual feedback
620 // oldPalette = palette();
621 // setPalette(my_HilitePalette);
625 void KODayMatrix::dragMoveEvent( QDragMoveEvent
*e
)
627 const QMimeData
*md
= e
->mimeData();
628 if ( !CalendarSupport::canDecode( md
) ) {
635 void KODayMatrix::dragLeaveEvent( QDragLeaveEvent
*dl
)
638 // setPalette(oldPalette);
642 void KODayMatrix::dropEvent( QDropEvent
*e
)
648 QList
<QUrl
> urls
= ( e
->mimeData()->urls() );
649 //kDebug()<<" urls :"<<urls;
650 if ( urls
.isEmpty() ) {
655 //For the moment support 1 url
656 if ( urls
.count() >= 1 ) {
657 KUrl res
= urls
.at( 0 );
659 Akonadi::ItemFetchJob
*job
= new Akonadi::ItemFetchJob( Akonadi::Item::fromUrl( res
) );
660 job
->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent
);
661 job
->fetchScope().fetchFullPayload();
662 Akonadi::Item::List items
;
664 items
= job
->items();
666 bool exist
= items
.at( 0 ).isValid();
667 int action
= DRAG_CANCEL
;
669 Qt::KeyboardModifiers keyboardModifiers
= e
->keyboardModifiers();
671 if ( keyboardModifiers
& Qt::ControlModifier
) {
673 } else if ( keyboardModifiers
& Qt::ShiftModifier
) {
676 QAction
*copy
= 0, *move
= 0;
677 KMenu
*menu
= new KMenu( this );
679 move
= menu
->addAction( KOGlobals::self()->smallIcon( "edit-paste" ), i18n( "&Move" ) );
680 if ( /*existingEvent*/1 ) {
681 copy
= menu
->addAction( KOGlobals::self()->smallIcon( "edit-copy" ), i18n( "&Copy" ) );
684 move
= menu
->addAction( KOGlobals::self()->smallIcon( "list-add" ), i18n( "&Add" ) );
686 menu
->addSeparator();
687 /*QAction *cancel =*/
688 menu
->addAction( KOGlobals::self()->smallIcon( "process-stop" ), i18n( "&Cancel" ) );
689 QAction
*a
= menu
->exec( QCursor::pos() );
692 } else if ( a
== move
) {
697 if ( action
== DRAG_COPY
|| action
== DRAG_MOVE
) {
699 int idx
= getDayIndexFrom( e
->pos().x(), e
->pos().y() );
701 if ( action
== DRAG_COPY
) {
702 emit
incidenceDropped( items
.at( 0 ), mDays
[idx
] );
703 } else if ( action
== DRAG_MOVE
) {
704 emit
incidenceDroppedMove( items
.at( 0 ), mDays
[idx
] );
710 // ----------------------------------------------------------------------------
711 // P A I N T E V E N T H A N D L I N G
712 // ----------------------------------------------------------------------------
714 void KODayMatrix::paintEvent( QPaintEvent
* )
717 const QRect rect
= frameRect();
718 const int dayHeight
= mDaySize
.height();
719 const int dayWidth
= mDaySize
.width();
721 int selectionWidth
, selectionHeight
;
722 const bool isRTL
= KOGlobals::self()->reverseLayout();
724 QPalette pal
= palette();
729 p
.fillRect( 0, 0, rect
.width(), rect
.height(), QBrush( pal
.color( QPalette::Base
) ) );
731 // draw topleft frame
732 p
.setPen( pal
.color( QPalette::Mid
) );
733 p
.drawRect( 0, 0, rect
.width() - 1, rect
.height() - 1 );
734 // don't paint over borders
737 // draw selected days with highlighted background color
738 if ( mSelStart
!= NOSELECTION
) {
741 // fix larger selections starting in the previous month
742 if ( row
< 0 && mSelEnd
> 0 ) {
745 column
= mSelStart
- row
* 7;
746 const QColor selectionColor
= KOPrefs::instance()->agendaGridHighlightColor();
748 if ( row
< 6 && row
>= 0 ) {
749 if ( row
== mSelEnd
/ 7 ) {
750 // Single row selection
752 ( 7 - ( mSelEnd
- mSelStart
+ 1 ) - column
) * dayWidth
:
755 ( mSelEnd
- mSelStart
+ 1 ) * dayWidth
, dayHeight
, selectionColor
);
757 // draw first row to the right
758 p
.fillRect( isRTL
? 0 : column
* dayWidth
, row
* dayHeight
,
759 ( 7 - column
) * dayWidth
, dayHeight
, selectionColor
);
760 // draw full block till last line
761 selectionHeight
= mSelEnd
/ 7 - row
;
762 if ( selectionHeight
+ row
>= 6 ) {
763 selectionHeight
= 6 - row
;
765 if ( selectionHeight
> 1 ) {
766 p
.fillRect( 0, ( row
+ 1 ) * dayHeight
, 7 * dayWidth
,
767 ( selectionHeight
- 1 ) * dayHeight
, selectionColor
);
769 // draw last block from left to mSelEnd
770 if ( mSelEnd
/ 7 < 6 ) {
771 selectionWidth
= mSelEnd
- 7 * ( mSelEnd
/ 7 ) + 1;
773 ( 7 - selectionWidth
) * dayWidth
:
775 ( row
+ selectionHeight
) * dayHeight
,
776 selectionWidth
* dayWidth
, dayHeight
, selectionColor
);
782 // iterate over all days in the matrix and draw the day label in appropriate colors
783 const QColor textColor
= pal
.color( QPalette::Text
);
784 const QColor textColorShaded
= getShadedColor( textColor
);
785 QColor actcol
= textColorShaded
;
789 const QList
<QDate
> workDays
= KOGlobals::self()->workDays( mDays
[0], mDays
[NUMDAYS
-1] );
790 for ( int i
= 0; i
< NUMDAYS
; ++i
) {
792 column
= isRTL
? 6 - ( i
- row
* 7 ) : i
- row
* 7;
794 // if it is the first day of a month switch color from normal to shaded and vice versa
795 if ( KOGlobals::self()->calendarSystem()->day( mDays
[i
] ) == 1 ) {
796 if ( actcol
== textColorShaded
) {
799 actcol
= textColorShaded
;
804 //Reset pen color after selected days block
805 if ( i
== mSelEnd
+ 1 ) {
809 const bool holiday
= !workDays
.contains( mDays
[i
] );
811 const QColor holidayColorShaded
=
812 getShadedColor( KOPrefs::instance()->agendaHolidaysBackgroundColor() );
814 // if today then draw rectangle around day
817 QPen
todayPen( p
.pen() );
819 todayPen
.setWidth( mTodayMarginWidth
);
820 //draw red rectangle for holidays
822 if ( actcol
== textColor
) {
823 todayPen
.setColor( KOPrefs::instance()->agendaHolidaysBackgroundColor() );
825 todayPen
.setColor( holidayColorShaded
);
828 //draw gray rectangle for today if in selection
829 if ( i
>= mSelStart
&& i
<= mSelEnd
) {
830 const QColor
grey( "grey" );
831 todayPen
.setColor( grey
);
833 p
.setPen( todayPen
);
834 p
.drawRect( column
* dayWidth
, row
* dayHeight
, dayWidth
, dayHeight
);
838 // if any events are on that day then draw it using a bold font
839 if ( mEvents
.contains( mDays
[i
] ) ) {
840 QFont myFont
= font();
841 myFont
.setBold( true );
845 // if it is a holiday then use the default holiday color
847 if ( actcol
== textColor
) {
848 p
.setPen( KOPrefs::instance()->agendaHolidaysBackgroundColor() );
850 p
.setPen( holidayColorShaded
);
854 // draw selected days with special color
855 if ( i
>= mSelStart
&& i
<= mSelEnd
&& !holiday
) {
856 p
.setPen( Qt::white
);
859 p
.drawText( column
* dayWidth
, row
* dayHeight
, dayWidth
, dayHeight
,
860 Qt::AlignHCenter
| Qt::AlignVCenter
, mDayLabels
[i
]);
862 // reset color to actual color
866 // reset bold font to plain font
867 if ( mEvents
.contains( mDays
[i
] ) > 0 ) {
868 QFont myFont
= font();
869 myFont
.setBold( false );
876 // ----------------------------------------------------------------------------
877 // R E SI Z E E V E N T H A N D L I N G
878 // ----------------------------------------------------------------------------
880 void KODayMatrix::resizeEvent( QResizeEvent
* )
882 QRect sz
= frameRect();
883 mDaySize
.setHeight( sz
.height() * 7 / NUMDAYS
);
884 mDaySize
.setWidth( sz
.width() / 7 );
888 QPair
<QDate
,QDate
> KODayMatrix::matrixLimits( const QDate
&month
)
890 const KCalendarSystem
*calSys
= KOGlobals::self()->calendarSystem();
892 calSys
->setDate( d
, calSys
->year( month
), calSys
->month( month
), 1 );
894 const int dayOfWeek
= calSys
->dayOfWeek( d
);
895 const int weekstart
= KGlobal::locale()->weekStartDay();
897 d
= d
.addDays( -( 7 + dayOfWeek
- weekstart
) % 7 );
899 if ( dayOfWeek
== weekstart
) {
900 d
= d
.addDays( -7 ); // Start on the second line
903 return qMakePair( d
, d
.addDays( NUMDAYS
-1 ) );
906 #include "kodaymatrix.moc"