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

kontact

  • sources
  • kde-4.12
  • kdepim
  • kontact
  • plugins
  • korganizer
todosummarywidget.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) 2005-2006,2008-2009 Allen Winter <winter@kde.org>
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License along
18  with this program; if not, write to the Free Software Foundation, Inc.,
19  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 
21  As a special exception, permission is given to link this program
22  with any edition of Qt, and distribute the resulting executable,
23  without including the source code for Qt in the source distribution.
24 */
25 
26 #include "todosummarywidget.h"
27 #include "todoplugin.h"
28 #include "korganizer/korganizerinterface.h"
29 
30 #include <calendarsupport/utils.h>
31 #include <calendarsupport/calendarsingleton.h>
32 
33 #include <Akonadi/Collection>
34 #include <Akonadi/ItemFetchScope>
35 #include <Akonadi/Calendar/IncidenceChanger>
36 
37 #include <KCalUtils/IncidenceFormatter>
38 
39 #include <KontactInterface/Core>
40 
41 #include <KConfigGroup>
42 #include <KIconLoader>
43 #include <KLocale>
44 #include <KMenu>
45 #include <KSystemTimeZones>
46 #include <KUrlLabel>
47 
48 #include <QGridLayout>
49 #include <QLabel>
50 #include <QTextDocument> // for Qt::mightBeRichText
51 #include <QVBoxLayout>
52 
53 using namespace KCalUtils;
54 
55 TodoSummaryWidget::TodoSummaryWidget( TodoPlugin *plugin, QWidget *parent )
56  : KontactInterface::Summary( parent ), mPlugin( plugin )
57 {
58  QVBoxLayout *mainLayout = new QVBoxLayout( this );
59  mainLayout->setSpacing( 3 );
60  mainLayout->setMargin( 3 );
61 
62  QWidget *header = createHeader( this, QLatin1String("korg-todo"), i18n( "Pending To-dos" ) );
63  mainLayout->addWidget( header );
64 
65  mLayout = new QGridLayout();
66  mainLayout->addItem( mLayout );
67  mLayout->setSpacing( 3 );
68  mLayout->setRowStretch( 6, 1 );
69  mCalendar = CalendarSupport::calendarSingleton();
70 
71  mChanger = new Akonadi::IncidenceChanger( parent );
72 
73  connect( mCalendar.data(), SIGNAL(calendarChanged()), SLOT(updateView()) );
74  connect( mPlugin->core(), SIGNAL(dayChanged(QDate)), SLOT(updateView()) );
75 
76  updateView();
77 }
78 
79 TodoSummaryWidget::~TodoSummaryWidget()
80 {
81 }
82 
83 void TodoSummaryWidget::updateView()
84 {
85  qDeleteAll( mLabels );
86  mLabels.clear();
87 
88  KConfig config( QLatin1String("kcmtodosummaryrc") );
89  KConfigGroup group = config.group( "Days" );
90  int mDaysToGo = group.readEntry( "DaysToShow", 7 );
91 
92  group = config.group( "Hide" );
93  mHideInProgress = group.readEntry( "InProgress", false );
94  mHideOverdue = group.readEntry( "Overdue", false );
95  mHideCompleted = group.readEntry( "Completed", true );
96  mHideOpenEnded = group.readEntry( "OpenEnded", true );
97  mHideNotStarted = group.readEntry( "NotStarted", false );
98 
99  group = config.group( "Groupware" );
100  mShowMineOnly = group.readEntry( "ShowMineOnly", false );
101 
102  // for each todo,
103  // if it passes the filter, append to a list
104  // else continue
105  // sort todolist by summary
106  // sort todolist by priority
107  // sort todolist by due-date
108  // print todolist
109 
110  // the filter is created by the configuration summary options, but includes
111  // days to go before to-do is due
112  // which types of to-dos to hide
113 
114  KCalCore::Todo::List prList;
115 
116  const QDate currDate = QDate::currentDate();
117  KCalCore::Todo::List todos = mCalendar->todos();
118  Q_FOREACH ( const KCalCore::Todo::Ptr &todo, todos ) {
119  if ( todo->hasDueDate() ) {
120  const int daysTo = currDate.daysTo( todo->dtDue().date() );
121  if ( daysTo >= mDaysToGo ) {
122  continue;
123  }
124  }
125 
126  if ( mHideOverdue && todo->isOverdue() ) {
127  continue;
128  }
129  if ( mHideInProgress && todo->isInProgress( false ) ) {
130  continue;
131  }
132  if ( mHideCompleted && todo->isCompleted() ) {
133  continue;
134  }
135  if ( mHideOpenEnded && todo->isOpenEnded() ) {
136  continue;
137  }
138  if ( mHideNotStarted && todo->isNotStarted( false ) ) {
139  continue;
140  }
141 
142  prList.append( todo );
143  }
144  if ( !prList.isEmpty() ) {
145  prList = Akonadi::ETMCalendar::sortTodos( prList,
146  KCalCore::TodoSortSummary,
147  KCalCore::SortDirectionAscending );
148  prList = Akonadi::ETMCalendar::sortTodos( prList,
149  KCalCore::TodoSortPriority,
150  KCalCore::SortDirectionAscending );
151  prList = Akonadi::ETMCalendar::sortTodos( prList,
152  KCalCore::TodoSortDueDate,
153  KCalCore::SortDirectionAscending );
154  }
155 
156  // The to-do print consists of the following fields:
157  // icon:due date:days-to-go:priority:summary:status
158  // where,
159  // the icon is the typical to-do icon
160  // the due date it the to-do due date
161  // the days-to-go/past is the #days until/since the to-do is due
162  // this field is left blank if the to-do is open-ended
163  // the priority is the to-do priority
164  // the summary is the to-do summary
165  // the status is comma-separated list of:
166  // overdue
167  // in-progress (started, or >0% completed)
168  // complete (100% completed)
169  // open-ended
170  // not-started (no start date and 0% completed)
171 
172  int counter = 0;
173  QLabel *label = 0;
174 
175  if ( !prList.isEmpty() ) {
176 
177  KIconLoader loader( QLatin1String("korganizer") );
178  QPixmap pm = loader.loadIcon( QLatin1String("view-calendar-tasks"), KIconLoader::Small );
179 
180  QString str;
181 
182  Q_FOREACH ( const KCalCore::Todo::Ptr &todo, prList ) {
183  bool makeBold = false;
184  int daysTo = -1;
185 
186  // Optionally, show only my To-dos
187 /* if ( mShowMineOnly &&
188  !KCalCore::CalHelper::isMyCalendarIncidence( mCalendarAdaptor, todo.get() ) ) {
189  continue;
190  }
191 TODO: calhelper is deprecated, remove this?
192 */
193 
194  // Icon label
195  label = new QLabel( this );
196  label->setPixmap( pm );
197  label->setMaximumWidth( label->minimumSizeHint().width() );
198  mLayout->addWidget( label, counter, 0 );
199  mLabels.append( label );
200 
201  // Due date label
202  str.clear();
203  if ( todo->hasDueDate() && todo->dtDue().date().isValid() ) {
204  daysTo = currDate.daysTo( todo->dtDue().date() );
205 
206  if ( daysTo == 0 ) {
207  makeBold = true;
208  str = i18nc( "the to-do is due today", "Today" );
209  } else if ( daysTo == 1 ) {
210  str = i18nc( "the to-do is due tomorrow", "Tomorrow" );
211  } else {
212  str = KGlobal::locale()->formatDate( todo->dtDue().date(), KLocale::FancyLongDate );
213  }
214  }
215 
216  label = new QLabel( str, this );
217  label->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
218  mLayout->addWidget( label, counter, 1 );
219  mLabels.append( label );
220  if ( makeBold ) {
221  QFont font = label->font();
222  font.setBold( true );
223  label->setFont( font );
224  }
225 
226  // Days togo/ago label
227  str.clear();
228  if ( todo->hasDueDate() && todo->dtDue().date().isValid() ) {
229  if ( daysTo > 0 ) {
230  str = i18np( "in 1 day", "in %1 days", daysTo );
231  } else if ( daysTo < 0 ) {
232  str = i18np( "1 day ago", "%1 days ago", -daysTo );
233  } else {
234  str = i18nc( "the to-do is due", "due" );
235  }
236  }
237  label = new QLabel( str, this );
238  label->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
239  mLayout->addWidget( label, counter, 2 );
240  mLabels.append( label );
241 
242  // Priority label
243  str = QLatin1Char('[') + QString::number( todo->priority() ) + QLatin1Char(']');
244  label = new QLabel( str, this );
245  label->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
246  mLayout->addWidget( label, counter, 3 );
247  mLabels.append( label );
248 
249  // Summary label
250  str = todo->summary();
251  if ( !todo->relatedTo().isEmpty() ) { // show parent only, not entire ancestry
252  KCalCore::Incidence::Ptr inc = mCalendar->incidence( todo->relatedTo() );
253  if ( inc ) {
254  str = inc->summary() + QLatin1Char(':') + str;
255  }
256  }
257  if ( !Qt::mightBeRichText( str ) ) {
258  str = Qt::escape( str );
259  }
260 
261  KUrlLabel *urlLabel = new KUrlLabel( this );
262  urlLabel->setText( str );
263  urlLabel->setUrl( todo->uid() );
264  urlLabel->installEventFilter( this );
265  urlLabel->setTextFormat( Qt::RichText );
266  urlLabel->setWordWrap( true );
267  mLayout->addWidget( urlLabel, counter, 4 );
268  mLabels.append( urlLabel );
269 
270  connect( urlLabel, SIGNAL(leftClickedUrl(QString)),
271  this, SLOT(viewTodo(QString)) );
272  connect( urlLabel, SIGNAL(rightClickedUrl(QString)),
273  this, SLOT(popupMenu(QString)) );
274 
275  // where did the toolTipStr signature that takes a calendar went?
276  QString tipText( IncidenceFormatter::toolTipStr(
277  IncidenceFormatter::resourceString( mCalendar, todo ),
278  todo, currDate, true, KSystemTimeZones::local() ) );
279  if ( !tipText.isEmpty() ) {
280  urlLabel->setToolTip( tipText );
281  }
282 
283  // State text label
284  str = stateStr( todo );
285  label = new QLabel( str, this );
286  label->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
287  mLayout->addWidget( label, counter, 5 );
288  mLabels.append( label );
289 
290  counter++;
291  }
292  } //foreach
293 
294  if ( counter == 0 ) {
295  QLabel *noTodos = new QLabel(
296  i18np( "No pending to-dos due within the next day",
297  "No pending to-dos due within the next %1 days",
298  mDaysToGo ), this );
299  noTodos->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
300  mLayout->addWidget( noTodos, 0, 0 );
301  mLabels.append( noTodos );
302  }
303 
304  Q_FOREACH ( label, mLabels ) { //krazy:exclude=foreach as label is a pointer
305  label->show();
306  }
307 }
308 
309 void TodoSummaryWidget::viewTodo( const QString &uid )
310 {
311  Akonadi::Item::Id id = mCalendar->item( uid ).id();
312 
313  if ( id != -1 ) {
314  mPlugin->core()->selectPlugin(QLatin1String( "kontact_todoplugin") );//ensure loaded
315  OrgKdeKorganizerKorganizerInterface korganizer(
316  QLatin1String("org.kde.korganizer"), QLatin1String("/Korganizer"), QDBusConnection::sessionBus() );
317 
318  korganizer.editIncidence( QString::number( id ) );
319  }
320 }
321 
322 void TodoSummaryWidget::removeTodo( const Akonadi::Item &item )
323 {
324  mChanger->deleteIncidence( item );
325 }
326 
327 void TodoSummaryWidget::completeTodo( Akonadi::Item::Id id )
328 {
329  Akonadi::Item todoItem = mCalendar->item( id );
330 
331  if ( todoItem.isValid() ) {
332  KCalCore::Todo::Ptr todo = CalendarSupport::todo( todoItem );
333  if ( !todo->isReadOnly() ) {
334  KCalCore::Todo::Ptr oldTodo( todo->clone() );
335  todo->setCompleted( KDateTime::currentLocalDateTime() );
336  mChanger->modifyIncidence( todoItem, oldTodo );
337  updateView();
338  }
339  }
340 }
341 
342 void TodoSummaryWidget::popupMenu( const QString &uid )
343 {
344  KCalCore::Todo::Ptr todo = mCalendar->todo( uid );
345  if( !todo )
346  return;
347  Akonadi::Item item = mCalendar->item( uid );
348  KMenu popup( this );
349  QAction *editIt = popup.addAction( i18n( "&Edit To-do..." ) );
350  QAction *delIt = popup.addAction( i18n( "&Delete To-do" ) );
351  delIt->setIcon( KIconLoader::global()->loadIcon( QLatin1String("edit-delete"), KIconLoader::Small ) );
352 
353  QAction *doneIt = 0;
354  delIt->setEnabled( mCalendar->hasRight( item, Akonadi::Collection::CanDeleteItem ) );
355 
356  if ( !todo->isCompleted() ) {
357  doneIt = popup.addAction( i18n( "&Mark To-do Completed" ) );
358  doneIt->setIcon( KIconLoader::global()->loadIcon( QLatin1String("task-complete"), KIconLoader::Small ) );
359  doneIt->setEnabled( mCalendar->hasRight( item, Akonadi::Collection::CanChangeItem ) );
360  }
361  // TODO: add icons to the menu actions
362 
363  const QAction *selectedAction = popup.exec( QCursor::pos() );
364  if ( selectedAction == editIt ) {
365  viewTodo( uid );
366  } else if ( selectedAction == delIt ) {
367  removeTodo( item );
368  } else if ( doneIt && selectedAction == doneIt ) {
369  completeTodo( item.id() );
370  }
371 }
372 
373 bool TodoSummaryWidget::eventFilter( QObject *obj, QEvent *e )
374 {
375  if ( obj->inherits( "KUrlLabel" ) ) {
376  KUrlLabel* label = static_cast<KUrlLabel*>( obj );
377  if ( e->type() == QEvent::Enter ) {
378  emit message( i18n( "Edit To-do: \"%1\"", label->text() ) );
379  }
380  if ( e->type() == QEvent::Leave ) {
381  emit message( QString::null ); //krazy:exclude=nullstrassign for old broken gcc
382  }
383  }
384  return KontactInterface::Summary::eventFilter( obj, e );
385 }
386 
387 QStringList TodoSummaryWidget::configModules() const
388 {
389  return QStringList() << QLatin1String( "kcmtodosummary.desktop" );
390 }
391 
392 bool TodoSummaryWidget::startsToday( const KCalCore::Todo::Ptr &todo )
393 {
394  return todo->hasStartDate() &&
395  todo->dtStart().date() == QDate::currentDate();
396 }
397 
398 const QString TodoSummaryWidget::stateStr( const KCalCore::Todo::Ptr &todo )
399 {
400  QString str1, str2;
401 
402  if ( todo->isOpenEnded() ) {
403  str1 = i18n( "open-ended" );
404  } else if ( todo->isOverdue() ) {
405  str1 = QLatin1String("<font color=\"red\">") +
406  i18nc( "the to-do is overdue", "overdue" ) +
407  QLatin1String("</font>");
408  } else if ( startsToday( todo ) ) {
409  str1 = i18nc( "the to-do starts today", "starts today" );
410  }
411 
412  if ( todo->isNotStarted( false ) ) {
413  str2 += i18nc( "the to-do has not been started yet", "not-started" );
414  } else if ( todo->isCompleted() ) {
415  str2 += i18nc( "the to-do is completed", "completed" );
416  } else if ( todo->isInProgress( false ) ) {
417  str2 += i18nc( "the to-do is in-progress", "in-progress " );
418  str2 += QLatin1String(" (") + QString::number( todo->percentComplete() ) + QLatin1String("%)");
419  }
420 
421  if ( !str1.isEmpty() && !str2.isEmpty() ) {
422  str1 += i18nc( "Separator for status like this: overdue, completed", "," );
423  }
424 
425  return str1 + str2;
426 }
427 
428 #include "todosummarywidget.moc"
todoplugin.h
todosummarywidget.h
QWidget
QObject
TodoSummaryWidget::TodoSummaryWidget
TodoSummaryWidget(TodoPlugin *plugin, QWidget *parent)
Definition: todosummarywidget.cpp:55
TodoSummaryWidget::configModules
QStringList configModules() const
Definition: todosummarywidget.cpp:387
TodoSummaryWidget::~TodoSummaryWidget
~TodoSummaryWidget()
Definition: todosummarywidget.cpp:79
TodoPlugin
Definition: todoplugin.h:35
QLabel
TodoSummaryWidget::eventFilter
virtual bool eventFilter(QObject *obj, QEvent *e)
Definition: todosummarywidget.cpp:373
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:58:30 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

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