• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

korganizer

  • sources
  • kde-4.12
  • kdepim
  • korganizer
kodaymatrix.cpp
Go to the documentation of this file.
1 /*
2  This file is part of KOrganizer.
3 
4  Copyright (c) 2001 Eitzenberger Thomas <thomas.eitzenberger@siemens.at>
5  Parts of the source code have been copied from kdpdatebutton.cpp
6 
7  Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
8  Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
9 
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.
14 
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.
19 
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.
23 
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.
27 */
28 
29 #include "kodaymatrix.h"
30 #include "koglobals.h"
31 #include "koprefs.h"
32 
33 #include <calendarsupport/utils.h>
34 
35 #include <Akonadi/ItemFetchJob>
36 #include <Akonadi/ItemFetchScope>
37 
38 #include <KCalendarSystem>
39 #include <KIcon>
40 #include <KMenu>
41 
42 #include <QMouseEvent>
43 #include <QPainter>
44 #include <QToolTip>
45 
46 // ============================================================================
47 // K O D A Y M A T R I X
48 // ============================================================================
49 
50 const int KODayMatrix::NOSELECTION = -1000;
51 const int KODayMatrix::NUMDAYS = 42;
52 
53 KODayMatrix::KODayMatrix( QWidget *parent )
54  : QFrame( parent ), mStartDate(), mPendingChanges( false )
55 {
56  // initialize dynamic arrays
57  mDays = new QDate[NUMDAYS];
58  mDayLabels = new QString[NUMDAYS];
59 
60  mTodayMarginWidth = 2;
61  mSelEnd = mSelStart = NOSELECTION;
62 
63  recalculateToday();
64 
65  mHighlightEvents = true;
66  mHighlightTodos = false;
67  mHighlightJournals = false;
68 }
69 
70 void KODayMatrix::setCalendar( const Akonadi::ETMCalendar::Ptr &calendar )
71 {
72  if ( mCalendar ) {
73  mCalendar->unregisterObserver( this );
74  mCalendar->disconnect( this );
75  }
76 
77  mCalendar = calendar;
78  mCalendar->registerObserver( this );
79 
80  setAcceptDrops( mCalendar != 0 );
81  updateIncidences();
82 }
83 
84 QColor KODayMatrix::getShadedColor( const QColor &color ) const
85 {
86  QColor shaded;
87  int h = 0;
88  int s = 0;
89  int v = 0;
90  color.getHsv( &h, &s, &v );
91  s = s / 4;
92  v = 192 + v / 4;
93  shaded.setHsv( h, s, v );
94 
95  return shaded;
96 }
97 
98 KODayMatrix::~KODayMatrix()
99 {
100  if ( mCalendar ) {
101  mCalendar->unregisterObserver( this );
102  }
103 
104  delete [] mDays;
105  delete [] mDayLabels;
106 }
107 
108 void KODayMatrix::addSelectedDaysTo( KCalCore::DateList &selDays )
109 {
110  if ( mSelStart == NOSELECTION ) {
111  return;
112  }
113 
114  // cope with selection being out of matrix limits at top (< 0)
115  int i0 = mSelStart;
116  if ( i0 < 0 ) {
117  for ( int i = i0; i < 0; ++i ) {
118  selDays.append( mDays[0].addDays( i ) );
119  }
120  i0 = 0;
121  }
122 
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] );
127  }
128  for ( int i = NUMDAYS; i < mSelEnd; ++i ) {
129  selDays.append( mDays[0].addDays( i ) );
130  }
131  } else {
132  // apply normal routine to selection being entirely within matrix limits
133  for ( int i = i0; i <= mSelEnd; ++i ) {
134  selDays.append( mDays[i] );
135  }
136  }
137 }
138 
139 void KODayMatrix::setSelectedDaysFrom( const QDate &start, const QDate &end )
140 {
141  if ( mStartDate.isValid() ) {
142  mSelStart = mStartDate.daysTo( start );
143  mSelEnd = mStartDate.daysTo( end );
144  }
145 }
146 
147 void KODayMatrix::clearSelection()
148 {
149  mSelEnd = mSelStart = NOSELECTION;
150 }
151 
152 void KODayMatrix::recalculateToday()
153 {
154  if ( !mStartDate.isValid() ) {
155  return;
156  }
157 
158  mToday = -1;
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] ) );
162 
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() ) {
167  mToday = i;
168  }
169  }
170 }
171 
172 void KODayMatrix::updateView()
173 {
174  updateView( mStartDate );
175 }
176 
177 void KODayMatrix::setUpdateNeeded()
178 {
179  mPendingChanges = true;
180 }
181 
182 void KODayMatrix::updateView( const QDate &actdate )
183 {
184  if ( !actdate.isValid() || NUMDAYS < 1 ) {
185  return;
186  }
187  //flag to indicate if the starting day of the matrix has changed by this call
188  bool daychanged = false;
189 
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;
204  }
205  if ( mSelEnd > NUMDAYS || mSelEnd < 0 ) {
206  mSelEnd = mSelEnd + tmp;
207  }
208  }
209  }
210 
211  mStartDate = actdate;
212  daychanged = true;
213  }
214 
215  if ( daychanged ) {
216  recalculateToday();
217  }
218 
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 ) {
222  return;
223  }
224 
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
228  updateIncidences();
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]];
233  QString holiStr;
234 
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", "," ) );
240  }
241  if ( holiStr.isEmpty() ) {
242  holiStr = QLatin1String("");
243  }
244  }
245  mHolidays[i] = holiStr;
246  }
247 }
248 
249 void KODayMatrix::updateIncidences()
250 {
251  if ( !mCalendar ) {
252  return;
253  }
254 
255  mEvents.clear();
256 
257  if ( mHighlightEvents ) {
258  updateEvents();
259  }
260 
261  if ( mHighlightTodos ) {
262  updateTodos();
263  }
264 
265  if ( mHighlightJournals ) {
266  updateJournals();
267  }
268 
269  mPendingChanges = false;
270 }
271 
272 void KODayMatrix::updateJournals()
273 {
274  const KCalCore::Incidence::List incidences = mCalendar->incidences();
275 
276  foreach ( const KCalCore::Incidence::Ptr &inc, incidences ) {
277  Q_ASSERT( inc );
278  QDate d = inc->dtStart().toTimeSpec( mCalendar->timeSpec() ).date();
279  if ( inc->type() == KCalCore::Incidence::TypeJournal &&
280  d >= mDays[0] &&
281  d <= mDays[NUMDAYS-1] &&
282  !mEvents.contains( d ) ) {
283  mEvents.append( d );
284  }
285  if ( mEvents.count() == NUMDAYS ) {
286  // No point in wasting cpu, all days are bold already
287  break;
288  }
289  }
290 }
291 
301 void KODayMatrix::updateTodos()
302 {
303  const KCalCore::Todo::List incidences = mCalendar->todos();
304  QDate d;
305  foreach ( const KCalCore::Todo::Ptr &t, incidences ) {
306  if ( mEvents.count() == NUMDAYS ) {
307  // No point in wasting cpu, all days are bold already
308  break;
309  }
310  Q_ASSERT( t );
311  if ( t->hasDueDate() ) {
312  ushort recurType = t->recurrenceType();
313 
314  if ( t->recurs() &&
315  !( recurType == KCalCore::Recurrence::rDaily && !KOPrefs::instance()->mDailyRecur ) &&
316  !( recurType == KCalCore::Recurrence::rWeekly && !KOPrefs::instance()->mWeeklyRecur ) ) {
317 
318  // It's a recurring todo, find out in which days it occurs
319  KCalCore::DateTimeList timeDateList =
320  t->recurrence()->timesInInterval(
321  KDateTime( mDays[0], mCalendar->timeSpec() ),
322  KDateTime( mDays[NUMDAYS-1], mCalendar->timeSpec() ) );
323 
324  foreach ( const KDateTime &dt, timeDateList ) {
325  d = dt.toTimeSpec( mCalendar->timeSpec() ).date();
326  if ( !mEvents.contains( d ) ) {
327  mEvents.append( d );
328  }
329  }
330 
331  } else {
332  d = t->dtDue().toTimeSpec( mCalendar->timeSpec() ).date();
333  if ( d >= mDays[0] && d <= mDays[NUMDAYS-1] && !mEvents.contains( d ) ) {
334  mEvents.append( d );
335  }
336  }
337  }
338  }
339 }
340 
341 void KODayMatrix::updateEvents()
342 {
343  if ( mEvents.count() == NUMDAYS ) {
344  mPendingChanges = false;
345  // No point in wasting cpu, all days are bold already
346  return;
347  }
348  KCalCore::Event::List eventlist = mCalendar->events( mDays[0], mDays[NUMDAYS-1],
349  mCalendar->timeSpec() );
350 
351  Q_FOREACH ( const KCalCore::Event::Ptr &event, eventlist ) {
352  if ( mEvents.count() == NUMDAYS ) {
353  // No point in wasting cpu, all days are bold already
354  break;
355  }
356 
357  Q_ASSERT( event );
358  const ushort recurType = event->recurrenceType();
359  const KDateTime dtStart = event->dtStart().toTimeSpec( mCalendar->timeSpec() );
360 
361  // timed incidences occur in
362  // [dtStart(), dtEnd()[. All-day incidences occur in [dtStart(), dtEnd()]
363  // so we subtract 1 second in the timed case
364  const int secsToAdd = event->allDay() ? 0 : -1;
365  const KDateTime dtEnd = event->dtEnd().toTimeSpec( mCalendar->timeSpec() ).addSecs( secsToAdd );
366 
367  if ( !( recurType == KCalCore::Recurrence::rDaily && !KOPrefs::instance()->mDailyRecur ) &&
368  !( recurType == KCalCore::Recurrence::rWeekly && !KOPrefs::instance()->mWeeklyRecur ) ) {
369 
370  KCalCore::DateTimeList timeDateList;
371  const bool isRecurrent = event->recurs();
372  const int eventDuration = dtStart.daysTo( dtEnd );
373 
374  if ( isRecurrent ) {
375  //Its a recurring event, find out in which days it occurs
376  timeDateList = event->recurrence()->timesInInterval(
377  KDateTime( mDays[0], mCalendar->timeSpec() ),
378  KDateTime( mDays[NUMDAYS-1], mCalendar->timeSpec() ) );
379  } else {
380  if ( dtStart.date() >= mDays[0] ) {
381  timeDateList.append( dtStart );
382  } else {
383  // The event starts in another month (not visible))
384  timeDateList.append( KDateTime( mDays[0], mCalendar->timeSpec() ) );
385  }
386  }
387 
388  KCalCore::DateTimeList::iterator t;
389  for ( t=timeDateList.begin(); t != timeDateList.end(); ++t ) {
390  //This could be a multiday event, so iterate from dtStart() to dtEnd()
391  QDate d = t->toTimeSpec( mCalendar->timeSpec() ).date();
392  int j = 0;
393 
394  QDate occurrenceEnd;
395  if ( isRecurrent ) {
396  occurrenceEnd = d.addDays( eventDuration );
397  } else {
398  occurrenceEnd = dtEnd.date();
399  }
400 
401  do {
402  mEvents.append( d );
403  ++j;
404  d = d.addDays( 1 );
405  } while ( d <= occurrenceEnd && j < NUMDAYS );
406  }
407  }
408  }
409  mPendingChanges = false;
410 }
411 
412 const QDate &KODayMatrix::getDate( int offset ) const
413 {
414  if ( offset < 0 || offset > NUMDAYS - 1 ) {
415  return mDays[0];
416  }
417  return mDays[offset];
418 }
419 
420 QString KODayMatrix::getHolidayLabel( int offset ) const
421 {
422  if ( offset < 0 || offset > NUMDAYS - 1 ) {
423  return QString();
424  }
425  return mHolidays[offset];
426 }
427 
428 int KODayMatrix::getDayIndexFrom( int x, int y ) const
429 {
430  return 7 * ( y / mDaySize.height() ) +
431  ( KOGlobals::self()->reverseLayout() ?
432  6 - x / mDaySize.width() : x / mDaySize.width() );
433 }
434 
435 void KODayMatrix::calendarIncidenceAdded( const KCalCore::Incidence::Ptr &incidence )
436 {
437  Q_UNUSED( incidence );
438  mPendingChanges = true;
439 }
440 
441 void KODayMatrix::calendarIncidenceChanged( const KCalCore::Incidence::Ptr &incidence )
442 {
443  Q_UNUSED( incidence );
444  mPendingChanges = true;
445 }
446 
447 void KODayMatrix::calendarIncidenceDeleted( const KCalCore::Incidence::Ptr &incidence )
448 {
449  Q_UNUSED( incidence );
450  mPendingChanges = true;
451 }
452 
453 void KODayMatrix::setHighlightMode( bool highlightEvents,
454  bool highlightTodos,
455  bool highlightJournals ) {
456 
457  // don't set mPendingChanges to true if nothing changed
458  if ( highlightTodos != mHighlightTodos ||
459  highlightEvents != mHighlightEvents ||
460  highlightJournals != mHighlightJournals ) {
461  mHighlightEvents = highlightEvents;
462  mHighlightTodos = highlightTodos;
463  mHighlightJournals = highlightJournals;
464  mPendingChanges = true;
465  }
466 }
467 
468 void KODayMatrix::resourcesChanged()
469 {
470  mPendingChanges = true;
471 }
472 
473 // ----------------------------------------------------------------------------
474 // M O U S E E V E N T H A N D L I N G
475 // ----------------------------------------------------------------------------
476 
477 bool KODayMatrix::event( QEvent *event )
478 {
479  if ( KOPrefs::instance()->mEnableToolTips && event->type() == QEvent::ToolTip ) {
480  QHelpEvent *helpEvent = static_cast<QHelpEvent*>( event );
481 
482  // calculate which cell of the matrix the mouse is in
483  QRect sz = frameRect();
484  int dheight = sz.height() * 7 / 42;
485  int dwidth = sz.width() / 7;
486  int row = helpEvent->pos().y() / dheight;
487  int col = helpEvent->pos().x() / dwidth;
488 
489  // show holiday names only
490  QString tipText = getHolidayLabel( col + row * 7 );
491  if ( !tipText.isEmpty() ) {
492  QToolTip::showText( helpEvent->globalPos(), tipText );
493  } else {
494  QToolTip::hideText();
495  }
496  }
497  return QWidget::event( event );
498 }
499 
500 void KODayMatrix::mousePressEvent( QMouseEvent *e )
501 {
502  mSelStart = getDayIndexFrom( e->x(), e->y() );
503  if ( e->button() == Qt::RightButton ) {
504  popupMenu( mDays[mSelStart] ) ;
505  } else if ( e->button() == Qt::LeftButton ) {
506  if ( mSelStart > NUMDAYS - 1 ) {
507  mSelStart = NUMDAYS - 1;
508  }
509  mSelInit = mSelStart;
510  }
511 }
512 
513 void KODayMatrix::popupMenu( const QDate &date )
514 {
515  KMenu popup( this );
516  popup.addTitle( date.toString() );
517  QAction *newEventAction = popup.addAction(
518  KIcon( QLatin1String("appointment-new") ), i18n( "New E&vent..." ) );
519  QAction *newTodoAction = popup.addAction(
520  KIcon( QLatin1String("task-new") ), i18n( "New &To-do..." ) );
521  QAction *newJournalAction = popup.addAction(
522  KIcon( QLatin1String("journal-new") ), i18n( "New &Journal..." ) );
523  QAction *ret = popup.exec( QCursor::pos() );
524  if ( ret == newEventAction ) {
525  emit newEventSignal( date );
526  } else if ( ret == newTodoAction ) {
527  emit newTodoSignal( date );
528  } else if ( ret == newJournalAction ) {
529  emit newJournalSignal( date );
530  }
531 }
532 
533 void KODayMatrix::mouseReleaseEvent( QMouseEvent *e )
534 {
535  if ( e->button() != Qt::LeftButton ) {
536  return;
537  }
538 
539  int tmp = getDayIndexFrom( e->x(), e->y() );
540  if ( tmp > NUMDAYS - 1 ) {
541  tmp = NUMDAYS - 1;
542  }
543 
544  if ( mSelInit > tmp ) {
545  mSelEnd = mSelInit;
546  if ( tmp != mSelStart ) {
547  mSelStart = tmp;
548  update();
549  }
550  } else {
551  mSelStart = mSelInit;
552 
553  //repaint only if selection has changed
554  if ( tmp != mSelEnd ) {
555  mSelEnd = tmp;
556  update();
557  }
558  }
559 
560  KCalCore::DateList daylist;
561  if ( mSelStart < 0 ) {
562  mSelStart = 0;
563  }
564  for ( int i = mSelStart; i <= mSelEnd; ++i ) {
565  daylist.append( mDays[i] );
566  }
567  emit selected( static_cast<const KCalCore::DateList>(daylist) );
568 }
569 
570 void KODayMatrix::mouseMoveEvent( QMouseEvent *e )
571 {
572  int tmp = getDayIndexFrom( e->x(), e->y() );
573  if ( tmp > NUMDAYS - 1 ) {
574  tmp = NUMDAYS - 1;
575  }
576 
577  if ( mSelInit > tmp ) {
578  mSelEnd = mSelInit;
579  if ( tmp != mSelStart ) {
580  mSelStart = tmp;
581  update();
582  }
583  } else {
584  mSelStart = mSelInit;
585 
586  //repaint only if selection has changed
587  if ( tmp != mSelEnd ) {
588  mSelEnd = tmp;
589  update();
590  }
591  }
592 }
593 
594 // ----------------------------------------------------------------------------
595 // D R A G ' N D R O P H A N D L I N G
596 // ----------------------------------------------------------------------------
597 
598 //-----------------------------------------------------------------------------
599 // Drag and Drop handling -- based on the Troll Tech dirview example
600 
601 enum {
602  DRAG_COPY = 0,
603  DRAG_MOVE = 1,
604  DRAG_CANCEL = 2
605 };
606 
607 void KODayMatrix::dragEnterEvent( QDragEnterEvent *e )
608 {
609  e->acceptProposedAction();
610  const QMimeData *md = e->mimeData();
611  if ( !CalendarSupport::canDecode( md ) ) {
612  e->ignore();
613  return;
614  }
615 
616  // some visual feedback
617 // oldPalette = palette();
618 // setPalette(my_HilitePalette);
619 // update();
620 }
621 
622 void KODayMatrix::dragMoveEvent( QDragMoveEvent *e )
623 {
624  const QMimeData *md = e->mimeData();
625  if ( !CalendarSupport::canDecode( md ) ) {
626  e->ignore();
627  return;
628  }
629  e->accept();
630 }
631 
632 void KODayMatrix::dragLeaveEvent( QDragLeaveEvent *dl )
633 {
634  Q_UNUSED( dl );
635 // setPalette(oldPalette);
636 // update();
637 }
638 
639 void KODayMatrix::dropEvent( QDropEvent *e )
640 {
641  if ( !mCalendar ) {
642  e->ignore();
643  return;
644  }
645  QList<QUrl> urls = ( e->mimeData()->urls() );
646  //kDebug()<<" urls :"<<urls;
647  if ( urls.isEmpty() ) {
648  e->ignore();
649  return;
650  }
651  Akonadi::Item items;
652  //For the moment support 1 url
653  if ( urls.count() >= 1 ) {
654  KUrl res = urls.at( 0 );
655 
656  Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob( Akonadi::Item::fromUrl( res ) );
657  job->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
658  job->fetchScope().fetchFullPayload();
659  Akonadi::Item::List items;
660  if ( job->exec() ) {
661  items = job->items();
662  }
663  bool exist = items.at( 0 ).isValid();
664  int action = DRAG_CANCEL;
665 
666  Qt::KeyboardModifiers keyboardModifiers = e->keyboardModifiers();
667 
668  if ( keyboardModifiers & Qt::ControlModifier ) {
669  action = DRAG_COPY;
670  } else if ( keyboardModifiers & Qt::ShiftModifier ) {
671  action = DRAG_MOVE;
672  } else {
673  QAction *copy = 0, *move = 0;
674  KMenu *menu = new KMenu( this );
675  if ( exist ) {
676  move = menu->addAction( KOGlobals::self()->smallIcon( QLatin1String("edit-paste") ), i18n( "&Move" ) );
677  if ( /*existingEvent*/1 ) {
678  copy = menu->addAction( KOGlobals::self()->smallIcon( QLatin1String("edit-copy") ), i18n( "&Copy" ) );
679  }
680  } else {
681  move = menu->addAction( KOGlobals::self()->smallIcon( QLatin1String("list-add") ), i18n( "&Add" ) );
682  }
683  menu->addSeparator();
684  /*QAction *cancel =*/
685  menu->addAction( KOGlobals::self()->smallIcon( QLatin1String("process-stop") ), i18n( "&Cancel" ) );
686  QAction *a = menu->exec( QCursor::pos() );
687  if ( a == copy ) {
688  action = DRAG_COPY;
689  } else if ( a == move ) {
690  action = DRAG_MOVE;
691  }
692  delete menu;
693  }
694 
695  if ( action == DRAG_COPY || action == DRAG_MOVE ) {
696  e->accept();
697  int idx = getDayIndexFrom( e->pos().x(), e->pos().y() );
698 
699  if ( action == DRAG_COPY ) {
700  emit incidenceDropped( items.at( 0 ), mDays[idx] );
701  } else if ( action == DRAG_MOVE ) {
702  emit incidenceDroppedMove( items.at( 0 ), mDays[idx] );
703  }
704  }
705  }
706 }
707 
708 // ----------------------------------------------------------------------------
709 // P A I N T E V E N T H A N D L I N G
710 // ----------------------------------------------------------------------------
711 
712 void KODayMatrix::paintEvent( QPaintEvent * )
713 {
714  QPainter p;
715  const QRect rect = frameRect();
716  const int dayHeight = mDaySize.height();
717  const int dayWidth = mDaySize.width();
718  int row, column;
719  int selectionWidth, selectionHeight;
720  const bool isRTL = KOGlobals::self()->reverseLayout();
721 
722  QPalette pal = palette();
723 
724  p.begin( this );
725 
726  // draw background
727  p.fillRect( 0, 0, rect.width(), rect.height(), QBrush( pal.color( QPalette::Base ) ) );
728 
729  // draw topleft frame
730  p.setPen( pal.color( QPalette::Mid ) );
731  p.drawRect( 0, 0, rect.width() - 1, rect.height() - 1 );
732  // don't paint over borders
733  p.translate( 1, 1 );
734 
735  // draw selected days with highlighted background color
736  if ( mSelStart != NOSELECTION ) {
737 
738  row = mSelStart / 7;
739  // fix larger selections starting in the previous month
740  if ( row < 0 && mSelEnd > 0 ) {
741  row = 0;
742  }
743  column = mSelStart - row * 7;
744  const QColor selectionColor = KOPrefs::instance()->agendaGridHighlightColor();
745 
746  if ( row < 6 && row >= 0 ) {
747  if ( row == mSelEnd / 7 ) {
748  // Single row selection
749  p.fillRect( isRTL ?
750  ( 7 - ( mSelEnd - mSelStart + 1 ) - column ) * dayWidth :
751  column * dayWidth,
752  row * dayHeight,
753  ( mSelEnd - mSelStart + 1 ) * dayWidth, dayHeight, selectionColor );
754  } else {
755  // draw first row to the right
756  p.fillRect( isRTL ? 0 : column * dayWidth, row * dayHeight,
757  ( 7 - column ) * dayWidth, dayHeight, selectionColor );
758  // draw full block till last line
759  selectionHeight = mSelEnd / 7 - row;
760  if ( selectionHeight + row >= 6 ) {
761  selectionHeight = 6 - row;
762  }
763  if ( selectionHeight > 1 ) {
764  p.fillRect( 0, ( row + 1 ) * dayHeight, 7 * dayWidth,
765  ( selectionHeight - 1 ) * dayHeight, selectionColor );
766  }
767  // draw last block from left to mSelEnd
768  if ( mSelEnd / 7 < 6 ) {
769  selectionWidth = mSelEnd - 7 * ( mSelEnd / 7 ) + 1;
770  p.fillRect( isRTL ?
771  ( 7 - selectionWidth ) * dayWidth :
772  0,
773  ( row + selectionHeight ) * dayHeight,
774  selectionWidth * dayWidth, dayHeight, selectionColor );
775  }
776  }
777  }
778  }
779 
780  // iterate over all days in the matrix and draw the day label in appropriate colors
781  const QColor textColor = pal.color( QPalette::Text );
782  const QColor textColorShaded = getShadedColor( textColor );
783  QColor actcol = textColorShaded;
784  p.setPen( actcol );
785  QPen tmppen;
786 
787  const QList<QDate> workDays = KOGlobals::self()->workDays( mDays[0], mDays[NUMDAYS-1] );
788  for ( int i = 0; i < NUMDAYS; ++i ) {
789  row = i / 7;
790  column = isRTL ? 6 - ( i - row * 7 ) : i - row * 7;
791 
792  // if it is the first day of a month switch color from normal to shaded and vice versa
793  if ( KOGlobals::self()->calendarSystem()->day( mDays[i] ) == 1 ) {
794  if ( actcol == textColorShaded ) {
795  actcol = textColor;
796  } else {
797  actcol = textColorShaded;
798  }
799  p.setPen( actcol );
800  }
801 
802  //Reset pen color after selected days block
803  if ( i == mSelEnd + 1 ) {
804  p.setPen( actcol );
805  }
806 
807  const bool holiday = !workDays.contains( mDays[i] );
808 
809  const QColor holidayColorShaded =
810  getShadedColor( KOPrefs::instance()->agendaHolidaysBackgroundColor() );
811 
812  // if today then draw rectangle around day
813  if ( mToday == i ) {
814  tmppen = p.pen();
815  QPen todayPen( p.pen() );
816 
817  todayPen.setWidth( mTodayMarginWidth );
818  //draw red rectangle for holidays
819  if ( holiday ) {
820  if ( actcol == textColor ) {
821  todayPen.setColor( KOPrefs::instance()->agendaHolidaysBackgroundColor() );
822  } else {
823  todayPen.setColor( holidayColorShaded );
824  }
825  }
826  //draw gray rectangle for today if in selection
827  if ( i >= mSelStart && i <= mSelEnd ) {
828  const QColor grey(QLatin1String( "grey") );
829  todayPen.setColor( grey );
830  }
831  p.setPen( todayPen );
832  p.drawRect( column * dayWidth, row * dayHeight, dayWidth, dayHeight );
833  p.setPen( tmppen );
834  }
835 
836  // if any events are on that day then draw it using a bold font
837  if ( mEvents.contains( mDays[i] ) ) {
838  QFont myFont = font();
839  myFont.setBold( true );
840  p.setFont( myFont );
841  }
842 
843  // if it is a holiday then use the default holiday color
844  if ( holiday ) {
845  if ( actcol == textColor ) {
846  p.setPen( KOPrefs::instance()->agendaHolidaysBackgroundColor() );
847  } else {
848  p.setPen( holidayColorShaded );
849  }
850  }
851 
852  // draw selected days with special color
853  if ( i >= mSelStart && i <= mSelEnd && !holiday ) {
854  p.setPen( Qt::white );
855  }
856 
857  p.drawText( column * dayWidth, row * dayHeight, dayWidth, dayHeight,
858  Qt::AlignHCenter | Qt::AlignVCenter, mDayLabels[i]);
859 
860  // reset color to actual color
861  if ( holiday ) {
862  p.setPen( actcol );
863  }
864  // reset bold font to plain font
865  if ( mEvents.contains( mDays[i] ) > 0 ) {
866  QFont myFont = font();
867  myFont.setBold( false );
868  p.setFont( myFont );
869  }
870  }
871  p.end();
872 }
873 
874 // ----------------------------------------------------------------------------
875 // R E SI Z E E V E N T H A N D L I N G
876 // ----------------------------------------------------------------------------
877 
878 void KODayMatrix::resizeEvent( QResizeEvent * )
879 {
880  QRect sz = frameRect();
881  mDaySize.setHeight( sz.height() * 7 / NUMDAYS );
882  mDaySize.setWidth( sz.width() / 7 );
883 }
884 
885 /* static */
886 QPair<QDate,QDate> KODayMatrix::matrixLimits( const QDate &month )
887 {
888  const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
889  QDate d = month;
890  calSys->setDate( d, calSys->year( month ), calSys->month( month ), 1 );
891 
892  const int dayOfWeek = calSys->dayOfWeek( d );
893  const int weekstart = KGlobal::locale()->weekStartDay();
894 
895  d = d.addDays( -( 7 + dayOfWeek - weekstart ) % 7 );
896 
897  if ( dayOfWeek == weekstart ) {
898  d = d.addDays( -7 ); // Start on the second line
899  }
900 
901  return qMakePair( d, d.addDays( NUMDAYS-1 ) );
902 }
903 
904 #include "kodaymatrix.moc"
KODayMatrix::clearSelection
void clearSelection()
Clear all selections.
Definition: kodaymatrix.cpp:147
koglobals.h
KODayMatrix::~KODayMatrix
~KODayMatrix()
destructor that deallocates all dynamically allocated private members.
Definition: kodaymatrix.cpp:98
KODayMatrix::incidenceDropped
void incidenceDropped(const Akonadi::Item &item, const QDate &dt)
Emitted if the user has dropped an incidence (event or todo) inside the matrix.
KODayMatrix::matrixLimits
static QPair< QDate, QDate > matrixLimits(const QDate &month)
returns the first and last date of the 6*7 matrix that displays month
Definition: kodaymatrix.cpp:886
KODayMatrix::resizeEvent
void resizeEvent(QResizeEvent *)
Definition: kodaymatrix.cpp:878
KOGlobals::holiday
QMap< QDate, QStringList > holiday(const QDate &start, const QDate &end) const
Definition: koglobals.cpp:80
KODayMatrix::dragLeaveEvent
void dragLeaveEvent(QDragLeaveEvent *e)
Definition: kodaymatrix.cpp:632
KODayMatrix::newTodoSignal
void newTodoSignal(const QDate &date)
KODayMatrix::getDate
const QDate & getDate(int offset) const
Returns the QDate object associated with day indexed by the supplied offset.
Definition: kodaymatrix.cpp:412
QWidget
KODayMatrix::calendarIncidenceDeleted
void calendarIncidenceDeleted(const KCalCore::Incidence::Ptr &incidence)
Definition: kodaymatrix.cpp:447
kodaymatrix.h
KODayMatrix::dragEnterEvent
void dragEnterEvent(QDragEnterEvent *e)
Definition: kodaymatrix.cpp:607
DRAG_COPY
Definition: kodaymatrix.cpp:602
KOPrefsBase::agendaGridHighlightColor
QColor agendaGridHighlightColor() const
Get Highlight color.
Definition: koprefs_base.h:1677
KODayMatrix::setHighlightMode
void setHighlightMode(bool highlightEvents, bool highlightTodos, bool highlightJournals)
Sets which incidences should be highlighted.
Definition: kodaymatrix.cpp:453
KODayMatrix::event
bool event(QEvent *e)
Definition: kodaymatrix.cpp:477
KODayMatrix::calendarIncidenceAdded
void calendarIncidenceAdded(const KCalCore::Incidence::Ptr &incidence)
Reimplemented from Akonadi::ETMCalendar They set mPendingChanges to true.
Definition: kodaymatrix.cpp:435
KODayMatrix::updateIncidences
void updateIncidences()
Update incidence states of dates.
Definition: kodaymatrix.cpp:249
KOPrefsBase::mDailyRecur
bool mDailyRecur
Definition: koprefs_base.h:3140
koprefs.h
KODayMatrix::setSelectedDaysFrom
void setSelectedDaysFrom(const QDate &start, const QDate &end)
Sets the actual to be displayed selection in the day matrix starting from start and ending with end...
Definition: kodaymatrix.cpp:139
DRAG_CANCEL
Definition: kodaymatrix.cpp:604
KODayMatrix::getHolidayLabel
QString getHolidayLabel(int offset) const
Returns the official name of this holy day or 0 if there is no label for this day.
Definition: kodaymatrix.cpp:420
KODayMatrix::mouseReleaseEvent
void mouseReleaseEvent(QMouseEvent *e)
Definition: kodaymatrix.cpp:533
KODayMatrix::mousePressEvent
void mousePressEvent(QMouseEvent *e)
Definition: kodaymatrix.cpp:500
KODayMatrix::calendarIncidenceChanged
void calendarIncidenceChanged(const KCalCore::Incidence::Ptr &incidence)
Definition: kodaymatrix.cpp:441
KODayMatrix::updateView
void updateView()
Recalculates all the flags of the days in the matrix like holidays or events on a day (Actually calls...
Definition: kodaymatrix.cpp:172
KODayMatrix::selected
void selected(const KCalCore::DateList &daylist)
Emitted if the user selects a block of days with the mouse by dragging a rectangle inside the matrix...
KODayMatrix::dropEvent
void dropEvent(QDropEvent *e)
Definition: kodaymatrix.cpp:639
KODayMatrix::incidenceDroppedMove
void incidenceDroppedMove(const Akonadi::Item &item, const QDate &dt)
Emitted if the user has dropped an event inside the matrix and chose to move it instead of copy...
KODayMatrix::dragMoveEvent
void dragMoveEvent(QDragMoveEvent *e)
Definition: kodaymatrix.cpp:622
KODayMatrix::resourcesChanged
void resourcesChanged()
Handle resource changes.
Definition: kodaymatrix.cpp:468
KOGlobals::calendarSystem
const KCalendarSystem * calendarSystem() const
Definition: koglobals.cpp:65
KOGlobals::self
static KOGlobals * self()
Definition: koglobals.cpp:43
KOGlobals::workDays
QList< QDate > workDays(const QDate &start, const QDate &end) const
Returns a list containing work days between start and .
Definition: koglobals.cpp:96
KOGlobals::reverseLayout
static bool reverseLayout()
Definition: koglobals.cpp:70
KODayMatrix::setCalendar
void setCalendar(const Akonadi::ETMCalendar::Ptr &)
Associate a calendar with this day matrix.
Definition: kodaymatrix.cpp:70
KODayMatrix::paintEvent
void paintEvent(QPaintEvent *ev)
Definition: kodaymatrix.cpp:712
KOPrefsBase::mWeeklyRecur
bool mWeeklyRecur
Definition: koprefs_base.h:3141
KOPrefs::instance
static KOPrefs * instance()
Get instance of KOPrefs.
Definition: koprefs.cpp:68
KODayMatrix::addSelectedDaysTo
void addSelectedDaysTo(KCalCore::DateList &)
Adds all actual selected days from mSelStart to mSelEnd to the supplied DateList. ...
Definition: kodaymatrix.cpp:108
KODayMatrix::KODayMatrix
KODayMatrix(QWidget *parent)
constructor to create a day matrix widget.
Definition: kodaymatrix.cpp:53
KODayMatrix::setUpdateNeeded
void setUpdateNeeded()
Definition: kodaymatrix.cpp:177
DRAG_MOVE
Definition: kodaymatrix.cpp:603
KODayMatrix::newEventSignal
void newEventSignal(const QDate &date)
QFrame
KODayMatrix::recalculateToday
void recalculateToday()
Calculates which square in the matrix should be hiighted to indicate the square is on "today"...
Definition: kodaymatrix.cpp:152
KODayMatrix::mouseMoveEvent
void mouseMoveEvent(QMouseEvent *e)
Definition: kodaymatrix.cpp:570
KODayMatrix::newJournalSignal
void newJournalSignal(const QDate &date)
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:56:19 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

korganizer

Skip menu "korganizer"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal