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

kontact

  • sources
  • kde-4.14
  • kdepim
  • kontact
  • plugins
  • planner
planner.cpp
Go to the documentation of this file.
1 /*
2  This file is part of Kontact.
3 
4  Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
5  Copyright (c) 2006 Oral Timocin <oral.timocin@kdemail.net>
6  Copyright (c) 2008-2009 Allen Winter <winter@kde.org>
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 
22  As a special exception, permission is given to link this program
23  with any edition of Qt, and distribute the resulting executable,
24  without including the source code for Qt in the source distribution.
25 */
26 
27 #include "planner.h"
28 #include "plannerplugin.h"
29 #include "stdcalendar.h"
30 #include "korganizer/korganizerinterface.h"
31 
32 #include <Akonadi/Contact/ContactSearchJob>
33 
34 #include <KCal/Calendar>
35 #include <KCal/CalHelper>
36 #include <KCal/IncidenceFormatter>
37 
38 #include <KHolidays/Holidays>
39 
40 #include <KontactInterface/Core>
41 
42 #include <KConfig>
43 #include <KConfigGroup>
44 #include <KIconLoader>
45 #include <KLocalizedString>
46 #include <KMenu>
47 #include <KSystemTimeZones>
48 #include <KUrlLabel>
49 
50 #include <QEvent>
51 #include <QLabel>
52 #include <QVBoxLayout>
53 
54 enum SDIncidenceType {
55  IncidenceTypeContact,
56  IncidenceTypeEvent
57 };
58 
59 enum SDCategory {
60  CategoryBirthday,
61  CategoryAnniversary,
62  CategoryHoliday,
63  CategoryOther
64 };
65 
66 class SDEntry
67 {
68  public:
69  SDIncidenceType type;
70  SDCategory category;
71  int yearsOld;
72  int daysTo;
73  QDate date;
74  QString summary;
75  QString desc;
76  int span; // #days in the special occassion.
77  Addressee addressee;
78 
79  bool operator<( const SDEntry &entry ) const
80  {
81  return daysTo < entry.daysTo;
82  }
83 };
84 
85 Planner::Planner( KontactInterface::Plugin *plugin, QWidget *parent )
86  : KontactInterface::Summary( parent ), mPlugin( plugin ), mCalendar( 0 )
87 {
88  mLayout = new QVBoxLayout( this );
89  mLayout->setSpacing( 3 );
90  mLayout->setMargin( 3 );
91 
92  QWidget *header = createHeader( this, "view-pim-summary", i18n( "Planner" ) );
93  mLayout->addWidget( header );
94 
95  mCalendar = KOrg::StdCalendar::self();
96 #if 0 //sebsauer
97  mCalendar->load();
98 #endif
99 
100  connect( mCalendar, SIGNAL(calendarChanged()), SLOT(updateView()) );
101  connect( mPlugin->core(), SIGNAL(dayChanged(QDate)), SLOT(updateView()) );
102 
103  // Update Configuration
104  configUpdated();
105 }
106 
107 void Planner::configUpdated()
108 {
109  KConfig config( "plannerrc" );
110 
111  //Read general config
112  KConfigGroup group = config.group( "General" );
113  mShowRecurrence = group.readEntry( "ShowRecurrence", true );
114  mShowReminder = group.readEntry( "ShowReminder", true );
115  mUnderline = group.readEntry( "underlineLink", true );
116  mTodo = group.readEntry( "ShowTodo", true );
117  mSd = group.readEntry( "ShowSd", true );
118 
119  //Read Calendar config
120  group = config.group( "Calendar" );
121  mCustomDays = group.readEntry( "DaysToShow", 1 );
122 
123  //Read Todo config
124  group = config.group( "Hide" );
125  mHideCompleted = group.readEntry( "Completed", true );
126  mHideOpenEnded = group.readEntry( "OpenEnded", false );
127  mHideInProgress = group.readEntry( "InProgress", false );
128  mHideOverdue = group.readEntry( "Overdue", false );
129  mHideNotStarted = group.readEntry( "NotStarted", false );
130 
131  //Read Special Dates config
132  group = config.group( "SpecialDates" );
133 // mBirthdayCal = group.readEntry( "BirthdayCal", true );
134  mBirthdayConList = group.readEntry( "BirthdayConList", true );
135 // mAnniversariesCal = group.readEntry( "AnniversariesCal", true );
136  mAnniversariesConList = group.readEntry( "AnniversariesConList", true );
137  mHolidaysCal = group.readEntry( "HolidaysCal", true );
138  mSpecialOccasionsCal = group.readEntry( "SpecialOccasionsCal", true );
139 
140  //Read Groupware Config
141  group = config.group( "Groupware" );
142  mShowMyEventsOnly = group.readEntry( "ShowMyEventsOnly", false );
143  mShowMyTodosOnly = group.readEntry( "ShowMyTodosOnly", false );
144 
145  updateView();
146 }
147 
148 void Planner::updateView()
149 {
150  while ( !mLabels.isEmpty() ) {
151  delete mLabels.takeFirst();
152  }
153 
154  KIconLoader loader( "kdepim" );
155 
156  QLabel *label = 0;
157  int counter = -1;
158 
159  QDate dt;
160  QDate currentDate = QDate::currentDate();
161 
162  for ( dt = currentDate;
163  dt <= currentDate.addDays( mCustomDays - 1 );
164  dt = dt.addDays( 1 ) ) {
165 
166  //Initialize Todo List
167  initTodoList( dt );
168  //Initialize Event List
169  initEventList( dt );
170  //Initialize SD List
171  initSdList( dt );
172 
173  // Fill Appointment Pixmap Field
174  if ( !mEvents.empty() || ( !mTodos.empty() && mTodo ) || ( !mDates.empty() && mSd ) ) {
175 
176  // Fill Event Date Field
177  bool makeBold = false;
178  QString datestr;
179 
180  // Modify event date for printing
181  QDate sD = QDate( dt.year(), dt.month(), dt.day() );
182  if ( ( sD.month() == currentDate.month() ) && ( sD.day() == currentDate.day() ) ) {
183  datestr = i18nc( "today", "Today" );
184  makeBold = true;
185  } else if ( ( sD.month() == currentDate.addDays( 1 ).month() ) &&
186  ( sD.day() == currentDate.addDays( 1 ).day() ) ) {
187  datestr = i18nc( "tomorrow", "Tomorrow" );
188  } else {
189  datestr = KGlobal::locale()->formatDate( sD );
190  }
191 
192  label = new QLabel( datestr, this );
193  label->setAlignment( Qt::AlignLeft | Qt::AlignTop );
194  if ( makeBold ) {
195  QFont font = label->font();
196  font.setBold( true );
197  font.setItalic( true );
198  label->setFont( font );
199  } else {
200  QFont font = label->font();
201  font.setItalic( true );
202  label->setFont( font );
203  }
204 
205  mLayout->addWidget( label );
206  mLabels.append( label );
207 
208  ++counter;
209  QVBoxLayout *gridLayout = new QVBoxLayout();
210  mPlannerGrid = new QGridLayout();
211  gridLayout->addItem( mPlannerGrid );
212 
213  mLayout->addLayout( gridLayout );
214 
215  if ( !mDates.empty() && mSd ) {
216  counter = showSd( counter, dt );
217  }
218  if ( !mTodos.empty() && mTodo ) {
219  counter = showTodos( counter, dt );
220  }
221  if ( !mEvents.empty() ) {
222  counter = showEvents( counter, dt );
223  }
224  }
225  }
226 
227  if ( !counter ) {
228  QLabel *noEvents = new QLabel(
229  i18np( "No appointments pending within the next day",
230  "No appointments pending within the next %1 days", mCustomDays ), this );
231  noEvents->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
232  mLayout->addWidget( noEvents, 0, 0 );
233  mLabels.append( noEvents );
234  }
235 
236  Q_FOREACH ( label, mLabels ) { //krazy:exclude=foreach as label is a pointer
237  label->show();
238  }
239 }
240 
241 void Planner::initTodoList( const QDate &date )
242 {
243  mTodos.setAutoDelete( true );
244  mTodos.clear();
245  mTodos.setAutoDelete( false );
246  QDate currentDate = QDate::currentDate();
247 
248  Q_FOREACH ( Todo *todo, mCalendar->todos() ) {
249  // Optionally, show only my To-dos
250  if ( mShowMyTodosOnly && !CalHelper::isMyCalendarIncidence( mCalendar, todo ) ) {
251  continue;
252  }
253 
254  //Hide Overdue or not
255  if ( !mHideOverdue && overdue( todo ) && date != currentDate ) {
256  continue;
257  }
258  if ( mHideOverdue && overdue( todo ) ) {
259  continue;
260  }
261  //Hide in Progress or not
262  if ( !mHideInProgress && inProgress( todo ) && date != currentDate ) {
263  continue;
264  }
265  if ( mHideInProgress && inProgress( todo ) ) {
266  continue;
267  }
268  //Hide Completed or not
269  if ( !mHideCompleted && completed( todo ) && date != currentDate ) {
270  continue;
271  }
272  if ( mHideCompleted && completed( todo ) ) {
273  continue;
274  }
275  //Hide OpenEnded or not
276  if ( !mHideOpenEnded && openEnded( todo ) && date != currentDate ) {
277  continue;
278  }
279  if ( mHideOpenEnded && openEnded( todo ) ) {
280  continue;
281  }
282  //Hide NotStarted or not
283  if ( !mHideNotStarted && notStarted( todo ) && date != currentDate ) {
284  continue;
285  }
286  if ( mHideNotStarted && notStarted( todo ) ) {
287  continue;
288  }
289  if ( !overdue( todo ) && !inProgress( todo ) && !completed( todo ) && !openEnded( todo ) &&
290  !notStarted( todo ) && todo->hasDueDate() && todo->dtDue().date() != date ) {
291  continue;
292  }
293  mTodos.append( todo );
294  }
295 
296  if ( !mTodos.isEmpty() ) {
297  mTodos = Calendar::sortTodos( &mTodos,
298  TodoSortSummary,
299  SortDirectionAscending );
300  mTodos = Calendar::sortTodos( &mTodos,
301  TodoSortPriority,
302  SortDirectionAscending );
303  mTodos = Calendar::sortTodos( &mTodos,
304  TodoSortDueDate,
305  SortDirectionAscending );
306  }
307 }
308 
309 int Planner::showTodos( int counter, const QDate &date )
310 {
311  KIconLoader loader( "kdepim" );
312 
313  if ( !mTodos.empty() ) {
314 
315  ++counter;
316 
317  Q_FOREACH ( Todo *todo, mTodos ) {
318  QString stateText = initStateText ( todo, date );
319 
320  mPlannerGrid->setColumnMinimumWidth( 0, 40 );
321 
322  QPixmap todoPm = loader.loadIcon( "view-pim-tasks", KIconLoader::Small );
323  QLabel *label = new QLabel( this );
324  label->setPixmap( todoPm );
325  label->setMaximumWidth( label->minimumSizeHint().width() );
326  mPlannerGrid->addWidget( label, counter, 1 );
327  mLabels.append( label );
328 
329  mPlannerGrid->setColumnMinimumWidth( 2, 15 );
330 
331  QString percent = QString::number( todo->percentComplete() ) + '%';
332  KUrlLabel *urlLabel = new KUrlLabel( this );
333  urlLabel->setText( percent );
334  urlLabel->setUrl( todo->uid() );
335  if ( stateText == i18nc( "to-do is overdue", "overdue" ) ) {
336  urlLabel->setText( "<font color = red >" + percent + "</font>" );
337  }
338  urlLabel->setAlignment( Qt::AlignHCenter | Qt::AlignTop );
339  if ( !mUnderline ) {
340  urlLabel->setUnderline( false );
341  }
342  urlLabel->setWordWrap( true );
343  urlLabel->setMaximumWidth( urlLabel->minimumSizeHint().width() );
344  mPlannerGrid->addWidget( urlLabel, counter, 3 );
345  mLabels.append( urlLabel );
346 
347  connect( urlLabel, SIGNAL(rightClickedUrl(QString)),
348  this, SLOT(changePercentage(QString)) );
349 
350  QString string = todo->summary();
351  if ( todo->relatedTo() ) { // show parent only, not entire ancestry
352  string = todo->relatedTo()->summary() + ':' + todo->summary();
353  }
354 
355  mPlannerGrid->setColumnMinimumWidth( 4, 15 );
356 
357  KUrlLabel *urlLabel2 = new KUrlLabel( this );
358  urlLabel2->setText( string );
359  urlLabel2->setUrl( todo->uid() );
360  urlLabel2->installEventFilter( this );
361  urlLabel2->setAlignment( Qt::AlignLeft | Qt::AlignTop );
362  urlLabel2->setWordWrap( true );
363  if ( stateText == i18nc( "to-do is overdue", "overdue" ) ) {
364  urlLabel2->setText( "<font color = red >" + string + "</font>" );
365  }
366  if ( !mUnderline ) {
367  urlLabel2->setUnderline( false );
368  }
369  mPlannerGrid->addWidget( urlLabel2, counter, 5 );
370  mLabels.append( urlLabel2 );
371 
372  connect( urlLabel2, SIGNAL(leftClickedUrl(QString)),
373  this, SLOT(viewTodo(QString)) );
374  connect( urlLabel2, SIGNAL(rightClickedUrl(QString)),
375  this, SLOT(todoPopupMenu(QString)) );
376 
377  QString tipText( IncidenceFormatter::toolTipStr(
378  mCalendar, todo, date, true, KSystemTimeZones::local() ) );
379  if ( !tipText.isEmpty() ) {
380  urlLabel2->setToolTip( tipText );
381  }
382 
383  mPlannerGrid->setColumnMinimumWidth( 6, 15 );
384 
385  label = new QLabel( stateText, this );
386  if ( stateText == i18nc( "to-do is overdue", "overdue" ) ) {
387  label->setText( "<font color = red >" + stateText + " </font>" );
388  }
389  label->setAlignment( Qt::AlignLeft | Qt::AlignTop );
390  label->setMaximumWidth( label->minimumSizeHint().width() );
391  mPlannerGrid->addWidget( label, counter, 7 );
392  mLabels.append( label );
393 
394  mPlannerGrid->setColumnMinimumWidth( 8, 15 );
395 
396  if ( mShowReminder ) {
397  QPixmap alarm;
398  if ( todo->hasEnabledAlarms() ) {
399  alarm = loader.loadIcon( "task-reminder", KIconLoader::Small );
400  }
401  label = new QLabel( this );
402  label->setPixmap( alarm );
403  label->setMaximumWidth( label->minimumSizeHint().width() );
404  mPlannerGrid->addWidget( label, counter, 9 );
405  mLabels.append( label );
406  }
407 
408  mPlannerGrid->setColumnMinimumWidth( 10, 15 );
409 
410  if ( mShowRecurrence ) {
411  QPixmap recur;
412  if ( todo->hasEnabledAlarms() ) {
413  recur = loader.loadIcon( "task-recurring", KIconLoader::Small );
414  }
415  label = new QLabel( this );
416  label->setPixmap( recur );
417  label->setMaximumWidth( label->minimumSizeHint().width() );
418  mPlannerGrid->addWidget( label, counter, 11 );
419  mLabels.append( label );
420  }
421  counter++;
422  }
423  }
424  return counter;
425 }
426 //
427 void Planner::initEventList( const QDate &date )
428 {
429  mEvents.setAutoDelete( true );
430  mEvents.clear();
431  mEvents.setAutoDelete( false );
432 
433  Q_FOREACH ( Event *ev, mCalendar->events( date, mCalendar->timeSpec() ) ) {
434  // Optionally, show only my Events
435  if ( mShowMyEventsOnly && !CalHelper::isMyCalendarIncidence( mCalendar, ev ) ) {
436  continue;
437  }
438  mEvents.append( ev );
439  }
440 
441  // sort the events for this date by summary
442  mEvents = Calendar::sortEvents( &mEvents,
443  EventSortSummary,
444  SortDirectionAscending );
445  // sort the events for this date by start date
446  mEvents = Calendar::sortEvents( &mEvents,
447  EventSortStartDate,
448  SortDirectionAscending );
449 }
450 
451 int Planner::showEvents( int counter, const QDate &date )
452 {
453  KIconLoader loader( "kdepim" );
454 
455  if ( !mEvents.empty() ) {
456 
457  QDate currentDate = QDate::currentDate();
458  QString datestr;
459  QDate sD = date;
460  QLabel *label;
461 
462  ++counter;
463 
464  Q_FOREACH ( Event *ev, mEvents ) {
465  // Count number of days remaining in multiday event
466  int span = 1;
467  int dayof = 1;
468  if ( ev->isMultiDay() ) {
469  QDate d = ev->dtStart().date();
470  if ( d < currentDate ) {
471  d = currentDate;
472  }
473  while ( d < ev->dtEnd().date() ) {
474  if ( d < date ) {
475  dayof++;
476  }
477  span++;
478  d = d.addDays( 1 );
479  }
480  }
481 
482  // If this date is part of an allDay, multiday event, then we
483  // only make a print for the first day of the event.
484  if ( ev->isMultiDay() && ev->allDay() && dayof != 1 ) {
485  continue;
486  }
487 
488  mPlannerGrid->setColumnMinimumWidth( 0, 40 );
489 
490  //Show Event icon
491  QPixmap re = loader.loadIcon( "view-calendar-day", KIconLoader::Small );
492  label = new QLabel( this );
493  label->setPixmap( re );
494  label->setMaximumWidth( label->minimumSizeHint().width() );
495  label->setAlignment( Qt::AlignTop );
496  mPlannerGrid->addWidget( label, counter, 1 );
497  mLabels.append( label );
498 
499  mPlannerGrid->setColumnMinimumWidth( 2, 15 );
500 
501  // Print the date span for multiday, allDay events, for the
502  // first day of the event only.
503  KDateTime::Spec spec = KSystemTimeZones::local();
504  if ( ev->isMultiDay() && ev->allDay() && dayof == 1 && span > 1 ) {
505  KDateTime ksD( sD.addDays( span - 1 ), spec );
506  datestr = IncidenceFormatter::dateToString( ev->dtStart(), false, spec ) +
507  " -\n " +
508  IncidenceFormatter::dateToString( ksD, false, spec );
509  label = new QLabel( datestr, this );
510  label->setAlignment( Qt::AlignLeft | Qt::AlignTop );
511  mPlannerGrid->addWidget( label, counter, 3 );
512  mLabels.append( label );
513  }
514 
515  // Fill Event Time Range Field (only for non-allDay Events)
516  if ( !ev->allDay() ) {
517  QTime sST = ev->dtStart().toTimeSpec( spec ).time();
518  QTime sET = ev->dtEnd().toTimeSpec( spec ).time();
519  if ( ev->isMultiDay() ) {
520  if ( ev->dtStart().date() < date ) {
521  sST = QTime( 0, 0 );
522  }
523  if ( ev->dtEnd().date() > date ) {
524  sET = QTime( 23, 59 );
525  }
526  }
527 
528  datestr = i18nc( "Time from - to", "%1 - %2",
529  KGlobal::locale()->formatTime( sST ),
530  KGlobal::locale()->formatTime( sET ) );
531  label = new QLabel( datestr, this );
532  label->setAlignment( Qt::AlignLeft | Qt::AlignTop );
533  label->setMaximumWidth( label->minimumSizeHint().width() );
534  mPlannerGrid->addWidget( label, counter, 3 );
535  mLabels.append( label );
536  }
537 
538  mPlannerGrid->setColumnMinimumWidth( 4, 15 );
539 
540  // Fill Event Summary Field
541  QString newtext = ev->summary();
542  if ( ev->isMultiDay() && !ev->allDay() ) {
543  newtext.append( QString( " (%1/%2)" ).arg( dayof ).arg( span ) );
544  }
545  KUrlLabel *urlLabel = new KUrlLabel( this );
546  urlLabel->setText( newtext );
547  urlLabel->setUrl( ev->uid() );
548  urlLabel->installEventFilter( this );
549  urlLabel->setAlignment( Qt::AlignLeft | Qt::AlignTop );
550  urlLabel->setWordWrap( true );
551  if ( !mUnderline ) {
552  urlLabel->setUnderline( false );
553  }
554  mPlannerGrid->addWidget( urlLabel, counter, 5 );
555  mLabels.append( urlLabel );
556 
557  mPlannerGrid->setColumnMinimumWidth( 6, 15 );
558  mPlannerGrid->setColumnMinimumWidth( 7, 15 );
559  mPlannerGrid->setColumnMinimumWidth( 8, 15 );
560 
561  //Show icon if Alarm is enabled
562  if ( mShowReminder ) {
563  QPixmap alarm;
564  if ( ev->hasEnabledAlarms () ) {
565  alarm = loader.loadIcon( "task-reminder", KIconLoader::Small );
566  }
567  label = new QLabel( this );
568  label->setPixmap( alarm );
569  label->setMaximumWidth( label->minimumSizeHint().width() );
570  label->setAlignment( Qt::AlignTop );
571  mPlannerGrid->addWidget( label, counter, 9 );
572  mLabels.append( label );
573  } else {
574  mPlannerGrid->setColumnMinimumWidth( 9, 15 );
575  }
576 
577  mPlannerGrid->setColumnMinimumWidth( 10, 15 );
578 
579  //Show icon if Event recurs
580  if ( mShowRecurrence ) {
581  QPixmap recur;
582  if ( ev->recurs() ) {
583  recur = loader.loadIcon( "appointment-recurring", KIconLoader::Small );
584  }
585  label = new QLabel( this );
586  label->setPixmap( recur );
587  label->setMaximumWidth( label->minimumSizeHint().width() );
588  label->setAlignment( Qt::AlignTop );
589  mPlannerGrid->addWidget( label, counter, 11 );
590  mLabels.append( label );
591  }
592 
593  connect( urlLabel, SIGNAL(leftClickedUrl(QString)),
594  this, SLOT(viewEvent(QString)) );
595  connect( urlLabel, SIGNAL(rightClickedUrl(QString)),
596  this, SLOT(eventPopupMenu(QString)) );
597 
598  QString tipText( IncidenceFormatter::toolTipStr(
599  mCalendar, ev, date, true, KSystemTimeZones::local() ) );
600  if ( !tipText.isEmpty() ) {
601  urlLabel->setToolTip( tipText );
602  }
603 
604  counter++;
605  }
606  }
607  return counter;
608 }
609 
610 bool Planner::initHolidays()
611 {
612  KConfig _hconfig( "korganizerrc" );
613  KConfigGroup hconfig( &_hconfig, "Time & Date" );
614  QString location = hconfig.readEntry( "Holidays" );
615  if ( !location.isEmpty() ) {
616  mHolidays = new KHolidays::HolidayRegion( location );
617  return true;
618  }
619  return false;
620 }
621 
622 void Planner::initSdList( const QDate &date )
623 {
624  mDates.clear();
625 
626  Akonadi::ContactSearchJob *job = new Akonadi::ContactSearchJob( this );
627  job->exec();
628 
629  Q_FOREACH ( const Addressee &addressee, job->contacts() ) {
630  const QDate birthday = addressee.birthday().date();
631  if ( birthday.isValid() && mBirthdayConList &&
632  birthday.day() == date.day() && birthday.month() == date.month() ) {
633  SDEntry entry;
634  entry.type = IncidenceTypeContact;
635  entry.category = CategoryBirthday;
636  entry.date = birthday;
637  entry.addressee = addressee;
638  entry.yearsOld = QDate::currentDate().year() - birthday.year();
639  mDates.append( entry );
640  }
641 
642  QString anniversaryAsString = addressee.custom( "KADDRESSBOOK", "X-Anniversary" );
643  if ( !anniversaryAsString.isEmpty() ) {
644  QDate anniversary = QDate::fromString( anniversaryAsString, Qt::ISODate );
645  if ( anniversary.isValid() && mAnniversariesConList &&
646  anniversary.day() == date.day() && anniversary.month() == date.month() ) {
647  SDEntry entry;
648  entry.type = IncidenceTypeContact;
649  entry.category = CategoryAnniversary;
650  entry.date = anniversary;
651  entry.addressee = addressee;
652  entry.yearsOld = QDate::currentDate().year() - anniversary.year();
653  mDates.append( entry );
654  }
655  }
656  }
657 
658  if ( mHolidaysCal ) {
659  if ( initHolidays() ) {
660  Q_FOREACH ( const KHolidays::Holiday &holiday, mHolidays->holidays( date ) ) {
661  if ( !mSpecialOccasionsCal && holiday.dayType() != KHolidays::Holiday::NonWorkday ) {
662  continue;
663  }
664  SDEntry entry;
665  entry.type = IncidenceTypeEvent;
666  entry.category = ( holiday.dayType() == KHolidays::Holiday::NonWorkday )?
667  CategoryHoliday : CategoryOther;
668  entry.date = date;
669  entry.summary = holiday.text();
670  mDates.append( entry );
671  }
672  }
673  }
674 }
675 
676 int Planner::showSd( int counter, const QDate &date )
677 {
678  KIconLoader loader( "kdepim" );
679  Q_UNUSED( date );
680 // initSdList( date );
681 
682  QPixmap birthdayIcon =
683  loader.loadIcon( "view-calendar-birthday", KIconLoader::Small );
684  QPixmap anniversaryIcon =
685  loader.loadIcon( "view-calendar-wedding-anniversary", KIconLoader::Small );
686  QPixmap holidayIcon =
687  loader.loadIcon( "view-calendar-holiday", KIconLoader::Small );
688  QPixmap specialOccasionsIcon =
689  loader.loadIcon( "favorites", KIconLoader::Small );
690 
691  ++counter;
692  Q_FOREACH ( const SDEntry &entry, mDates ) {
693  mPlannerGrid->setColumnMinimumWidth( 0, 40 );
694 
695  //Show Sd icon
696  QLabel *label = new QLabel( this );
697  switch ( entry.category ) {
698  case CategoryBirthday:
699  label->setPixmap( birthdayIcon );
700  break;
701  case CategoryAnniversary:
702  label->setPixmap( anniversaryIcon );
703  break;
704  case CategoryHoliday:
705  label->setPixmap( holidayIcon );
706  break;
707  case CategoryOther:
708  label->setPixmap( specialOccasionsIcon );
709  break;
710  }
711  label->setMaximumWidth( label->minimumSizeHint().width() );
712  label->setAlignment( Qt::AlignTop );
713  mPlannerGrid->addWidget( label, counter, 1 );
714  mLabels.append( label );
715 
716  mPlannerGrid->setColumnMinimumWidth( 2, 15 );
717 
718  QString catName;
719  switch ( entry.category ) {
720  case CategoryBirthday:
721  catName = i18n( "Birthday" );
722  break;
723  case CategoryAnniversary:
724  catName = i18n( "Anniversary" );
725  break;
726  case CategoryHoliday:
727  catName = i18n( "Holiday" );
728  break;
729  case CategoryOther:
730  catName = i18n( "Special Occasion" );
731  break;
732  }
733  label = new QLabel( this );
734  label->setText( catName );
735  label->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
736  mPlannerGrid->addWidget( label, counter, 3 );
737  mLabels.append( label );
738 
739  mPlannerGrid->setColumnMinimumWidth( 4, 15 );
740 
741  if ( entry.type == IncidenceTypeContact ) {
742  KUrlLabel *urlLabel = new KUrlLabel( this );
743  urlLabel->installEventFilter( this );
744  urlLabel->setUrl( entry.addressee.uid() );
745  urlLabel->setText( entry.addressee.realName() );
746  urlLabel->setTextFormat( Qt::RichText );
747  urlLabel->setWordWrap( true );
748  if ( !mUnderline ) {
749  urlLabel->setUnderline( false );
750  }
751  mPlannerGrid->addWidget( urlLabel, counter, 5 );
752  mLabels.append( urlLabel );
753  } else {
754  label = new QLabel( this );
755  label->setText( entry.summary );
756  label->setTextFormat( Qt::RichText );
757  mPlannerGrid->addWidget( label, counter, 5 );
758  mLabels.append( label );
759  if ( !entry.desc.isEmpty() ) {
760  label->setToolTip( entry.desc );
761  }
762  }
763 
764  mPlannerGrid->setColumnMinimumWidth( 6, 15 );
765 
766  if ( entry.category == CategoryBirthday || entry.category == CategoryAnniversary ) {
767  label = new QLabel( this );
768  if ( entry.yearsOld <= 0 ) {
769  label->setText( "" );
770  } else {
771  label->setText( i18np( "one year", "%1 years", entry.yearsOld ) );
772  }
773  label->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
774  mPlannerGrid->addWidget( label, counter, 7 );
775  mLabels.append( label );
776  }
777 
778  counter++;
779  }
780  return counter;
781 }
782 
783 void Planner::viewEvent( const QString &uid )
784 {
785  mPlugin->core()->selectPlugin( "kontact_korganizerplugin" );
786  OrgKdeKorganizerKorganizerInterface korganizer(
787  "org.kde.korganizer", "/Korganizer", QDBusConnection::sessionBus() );
788  korganizer.editIncidence( uid );
789 }
790 
791 void Planner::removeEvent( const QString &uid )
792 {
793  mPlugin->core()->selectPlugin( "kontact_korganizerplugin" );
794  OrgKdeKorganizerKorganizerInterface korganizer(
795  "org.kde.korganizer", "/Korganizer", QDBusConnection::sessionBus() );
796  korganizer.deleteIncidence( uid, false );
797 }
798 
799 void Planner::eventPopupMenu( const QString &uid )
800 {
801  KMenu popup( this );
802  QAction *editIt = popup.addAction( i18n( "&Edit Appointment..." ) );
803  QAction *delIt = popup.addAction( i18n( "&Delete Appointment" ) );
804  delIt->setIcon( KIconLoader::global()->loadIcon( "edit-delete", KIconLoader::Small ) );
805 
806  const QAction *selectedAction = popup.exec( QCursor::pos() );
807  if ( selectedAction == editIt ) {
808  viewEvent( uid );
809  } else if ( selectedAction == delIt ) {
810  removeEvent( uid );
811  }
812 }
813 
814 bool Planner::eventFilter( QObject *obj, QEvent *e )
815 {
816  if ( obj->inherits( "KUrlLabel" ) ) {
817  KUrlLabel *label = static_cast<KUrlLabel*>( obj );
818  if ( e->type() == QEvent::Enter ) {
819  emit message( i18n( "Edit Appointment: \"%1\"", label->text() ) );
820  }
821  if ( e->type() == QEvent::Leave ) {
822  emit message( QString::null ); //krazy:exclude=nullstrassign for old broken gcc
823  }
824  }
825 
826  return KontactInterface::Summary::eventFilter( obj, e );
827 }
828 
829 QString Planner::initStateText( const Todo *todo, const QDate &date )
830 {
831  QDate currentDate = QDate::currentDate();
832  QString stateText;
833  // show uncomplete todos from the last days
834  if ( todo->hasDueDate() && !todo->isCompleted() &&
835  todo->dtDue().date() < currentDate ) {
836  stateText = i18nc( "to-do is overdue", "overdue" );
837  }
838 
839  // show todos which started somewhere in the past and has to be finished in future
840  if ( todo->hasStartDate() && todo->hasDueDate() &&
841  todo->dtStart().date() < date &&
842  date < todo->dtDue().date() ) {
843  stateText = i18nc( "work on to-do is in progress", "in progress" );
844  }
845 
846  // all todos which start today
847  if ( todo->hasStartDate() && todo->dtStart().date() == date ) {
848  stateText = i18nc( "to-do starts today", "starts today" );
849  }
850 
851  // all todos which are due today
852  if ( todo->hasDueDate() && todo->dtDue().date() == date && todo->dtDue().date() == currentDate ) {
853  stateText = i18nc( "to-do due today", "due today" );
854  }
855  if ( todo->isCompleted() ) {
856  stateText = i18nc( "to-do is completed", "completed" );
857  }
858  return stateText;
859 }
860 
861 void Planner::todoPopupMenu( const QString &uid )
862 {
863  KMenu popup( this );
864  QAction *editIt = popup.addAction( i18n( "&Edit To-do..." ) );
865  QAction *delIt = popup.addAction( i18n( "&Delete To-do" ) );
866  delIt->setIcon( KIconLoader::global()->loadIcon( "edit-delete", KIconLoader::Small ) );
867  QAction *doneIt = 0;
868  Todo *todo = mCalendar->todo( uid );
869  if ( !todo->isCompleted() ) {
870  doneIt = popup.addAction( i18n( "&Mark To-do Completed" ) );
871  doneIt->setIcon( KIconLoader::global()->loadIcon( "task-complete", KIconLoader::Small ) );
872  }
873  // TODO: add icons to the menu actions
874 
875  const QAction *selectedAction = popup.exec( QCursor::pos() );
876  if ( selectedAction == editIt ) {
877  viewTodo( uid );
878  } else if ( selectedAction == delIt ) {
879  removeTodo( uid );
880  } else if ( doneIt && selectedAction == doneIt ) {
881  completeTodo( uid );
882  }
883 }
884 
885 void Planner::viewTodo( const QString &uid )
886 {
887  mPlugin->core()->selectPlugin( "kontact_todoplugin" );
888  OrgKdeKorganizerKorganizerInterface korganizer(
889  "org.kde.korganizer", "/Korganizer", QDBusConnection::sessionBus() );
890  korganizer.editIncidence( uid );
891 }
892 
893 void Planner::removeTodo( const QString &uid )
894 {
895  mPlugin->core()->selectPlugin( "kontact_todoplugin" );
896  OrgKdeKorganizerKorganizerInterface korganizer(
897  "org.kde.korganizer", "/Korganizer", QDBusConnection::sessionBus() );
898  korganizer.deleteIncidence( uid, false );
899 }
900 
901 void Planner::completeTodo( const QString &uid )
902 {
903  Todo *todo = mCalendar->todo( uid );
904  if ( !todo->isReadOnly() ) {
905  todo->setCompleted( KDateTime::currentLocalDateTime() );
906  mCalendar->save();
907  updateView();
908  }
909 }
910 
911 void Planner::changePercentage( const QString &uid )
912 {
913  KMenu popup( this );
914  QAction *per00 = popup.addAction( i18n( "%1%", 0 ) );
915  QAction *per10 = popup.addAction( i18n( "%1%", 10 ) );
916  QAction *per20 = popup.addAction( i18n( "%1%", 20 ) );
917  QAction *per30 = popup.addAction( i18n( "%1%", 30 ) );
918  QAction *per40 = popup.addAction( i18n( "%1%", 40 ) );
919  QAction *per50 = popup.addAction( i18n( "%1%", 50 ) );
920  QAction *per60 = popup.addAction( i18n( "%1%", 60 ) );
921  QAction *per70 = popup.addAction( i18n( "%1%", 70 ) );
922  QAction *per80 = popup.addAction( i18n( "%1%", 80 ) );
923  QAction *per90 = popup.addAction( i18n( "%1%", 90 ) );
924  QAction *per100= popup.addAction( i18n( "%1%", 100 ) );
925 
926  Todo *todo = mCalendar->todo( uid );
927  if ( !todo->isReadOnly() && mCalendar->beginChange( todo ) ) {
928  const QAction *selectedAction = popup.exec( QCursor::pos() );
929  if ( selectedAction == per00 ) {
930  todo->setPercentComplete( 0 );
931  } else if ( selectedAction == per10 ) {
932  todo->setPercentComplete( 10 );
933  } else if ( selectedAction == per20 ) {
934  todo->setPercentComplete( 20 );
935  } else if ( selectedAction == per30 ) {
936  todo->setPercentComplete( 30 );
937  } else if ( selectedAction == per40 ) {
938  todo->setPercentComplete( 40 );
939  } else if ( selectedAction == per50 ) {
940  todo->setPercentComplete( 50 );
941  } else if ( selectedAction == per60 ) {
942  todo->setPercentComplete( 60 );
943  } else if ( selectedAction == per70 ) {
944  todo->setPercentComplete( 70 );
945  } else if ( selectedAction == per80 ) {
946  todo->setPercentComplete( 80 );
947  } else if ( selectedAction == per90 ) {
948  todo->setPercentComplete( 90 );
949  } else if ( selectedAction == per100 ) {
950  todo->setCompleted( true );
951  }
952  mCalendar->endChange( todo );
953  updateView();
954  }
955 }
956 
957 bool Planner::todoEventFilter( QObject *obj, QEvent *e )
958 {
959  if ( obj->inherits( "KUrlLabel" ) ) {
960  KUrlLabel *label = static_cast<KUrlLabel*>( obj );
961  if ( e->type() == QEvent::Enter ) {
962  emit message( i18n( "Edit To-do: \"%1\"", label->text() ) );
963  }
964  if ( e->type() == QEvent::Leave ) {
965  emit message( QString() );
966  }
967  }
968 
969  return KontactInterface::Summary::eventFilter( obj, e );
970 }
971 
972 QStringList Planner::configModules() const
973 {
974  return QStringList( "kcmplanner.desktop" );
975 }
976 
977 bool Planner::overdue( Todo *todo )
978 {
979  if ( todo->hasDueDate() && !todo->isCompleted() &&
980  todo->dtDue().date() < QDate::currentDate() ) {
981  return true;
982  }
983  return false;
984 }
985 
986 bool Planner::completed( Todo *todo )
987 {
988  return todo->isCompleted();
989 }
990 
991 bool Planner::openEnded( Todo *todo )
992 {
993  if ( !todo->hasDueDate() && !todo->isCompleted() ) {
994  return true;
995  }
996  return false;
997 }
998 
999 bool Planner::inProgress( Todo *todo )
1000 {
1001  if ( overdue( todo ) ) {
1002  return false;
1003  }
1004 
1005  if ( todo->percentComplete() > 0 ) {
1006  return true;
1007  }
1008 
1009  QDate currDate = QDate::currentDate();
1010  if ( todo->hasStartDate() && todo->hasDueDate() &&
1011  todo->dtStart().date() < currDate &&
1012  currDate < todo->dtDue().date() ) {
1013  return true;
1014  }
1015 
1016  return false;
1017 }
1018 
1019 bool Planner::notStarted( Todo *todo )
1020 {
1021  if ( todo->percentComplete() > 0 ) {
1022  return false;
1023  }
1024 
1025  if ( !todo->hasStartDate() ) {
1026  return false;
1027  }
1028 
1029  if ( todo->dtStart().date() >= QDate::currentDate() ) {
1030  return false;
1031  }
1032 
1033  return true;
1034 }
QList::clear
void clear()
QEvent
QWidget
QString::append
QString & append(QChar ch)
QEvent::type
Type type() const
stdcalendar.h
QSize::width
int width() const
Planner::configModules
QStringList configModules() const
Definition: planner.cpp:972
SDIncidenceType
SDIncidenceType
Definition: planner.cpp:54
QGridLayout::addWidget
void addWidget(QWidget *widget, int row, int column, QFlags< Qt::AlignmentFlag > alignment)
date
time_t date() const
QFont
CategoryAnniversary
Definition: planner.cpp:61
QLabel::setPixmap
void setPixmap(const QPixmap &)
QAction::setIcon
void setIcon(const QIcon &icon)
CategoryOther
Definition: planner.cpp:63
QLabel::setAlignment
void setAlignment(QFlags< Qt::AlignmentFlag >)
QDBusConnection::sessionBus
QDBusConnection sessionBus()
QGridLayout
QDate::month
int month() const
QTime
QFont::setBold
void setBold(bool enable)
QDate::fromString
QDate fromString(const QString &string, Qt::DateFormat format)
QBoxLayout::addWidget
void addWidget(QWidget *widget, int stretch, QFlags< Qt::AlignmentFlag > alignment)
QString::number
QString number(int n, int base)
QList::append
void append(const T &value)
Planner::Planner
Planner(KontactInterface::Plugin *plugin, QWidget *parent)
Definition: planner.cpp:85
QList::empty
bool empty() const
QObject::inherits
bool inherits(const char *className) const
QObject
QList::isEmpty
bool isEmpty() const
QBoxLayout::addItem
virtual void addItem(QLayoutItem *item)
Planner::configUpdated
void configUpdated()
Definition: planner.cpp:107
QString::isEmpty
bool isEmpty() const
QDate::day
int day() const
Planner::todoEventFilter
virtual bool todoEventFilter(QObject *obj, QEvent *e)
Definition: planner.cpp:957
QDate::isValid
bool isValid() const
QLabel::setTextFormat
void setTextFormat(Qt::TextFormat)
CategoryBirthday
Definition: planner.cpp:60
QVBoxLayout
QDate
IncidenceTypeContact
Definition: planner.cpp:55
QDate::year
int year() const
QLabel::setText
void setText(const QString &)
QString
QLayout::setMargin
void setMargin(int margin)
QStringList
CategoryHoliday
Definition: planner.cpp:62
QPixmap
KOrg::StdCalendar::self
static StdCalendar * self()
Definition: stdcalendar.cpp:36
QWidget::font
font
QFont::setItalic
void setItalic(bool enable)
SDCategory
SDCategory
Definition: planner.cpp:59
plannerplugin.h
QWidget::setMaximumWidth
void setMaximumWidth(int maxw)
QCursor::pos
QPoint pos()
QList::takeFirst
T takeFirst()
QDate::currentDate
QDate currentDate()
QAction
QGridLayout::setColumnMinimumWidth
void setColumnMinimumWidth(int column, int minSize)
QLabel::minimumSizeHint
virtual QSize minimumSizeHint() const
planner.h
QWidget::show
void show()
QDate::addDays
QDate addDays(int ndays) const
QWidget::setToolTip
void setToolTip(const QString &)
QLabel
IncidenceTypeEvent
Definition: planner.cpp:56
Planner::eventFilter
virtual bool eventFilter(QObject *obj, QEvent *e)
Definition: planner.cpp:814
QBoxLayout::setSpacing
void setSpacing(int spacing)
QBoxLayout::addLayout
void addLayout(QLayout *layout, int stretch)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:34:11 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kontact

Skip menu "kontact"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

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
  • pimprint

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