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