todosummarywidget.cpp
1 /*
2  This file is part of Kontact.
3  Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 
19  As a special exception, permission is given to link this program
20  with any edition of TQt, and distribute the resulting executable,
21  without including the source code for TQt in the source distribution.
22 */
23 
24 #include <tqcursor.h>
25 #include <tqlabel.h>
26 #include <tqlayout.h>
27 #include <tqtooltip.h>
28 
29 #include <kdialog.h>
30 #include <tdeglobal.h>
31 #include <kiconloader.h>
32 #include <tdelocale.h>
33 #include <tdeparts/part.h>
34 #include <tdepopupmenu.h>
35 #include <kstandarddirs.h>
36 #include <kurllabel.h>
37 #include <libkcal/resourcecalendar.h>
38 #include <libkcal/resourcelocal.h>
39 #include <libkcal/todo.h>
40 #include <libkcal/incidenceformatter.h>
41 #include <libtdepim/kpimprefs.h>
42 
43 #include "korganizeriface_stub.h"
44 
45 #include "core.h"
46 #include "plugin.h"
47 #include "todoplugin.h"
48 
49 #include "korganizer/stdcalendar.h"
50 #include "korganizer/koglobals.h"
51 #include "korganizer/incidencechanger.h"
52 
53 #include "todosummarywidget.h"
54 
55 TodoSummaryWidget::TodoSummaryWidget( TodoPlugin *plugin,
56  TQWidget *parent, const char *name )
57  : Kontact::Summary( parent, name ), mPlugin( plugin )
58 {
59  TQVBoxLayout *mainLayout = new TQVBoxLayout( this, 3, 3 );
60 
61  TQPixmap icon = TDEGlobal::iconLoader()->loadIcon( "kontact_todo",
62  TDEIcon::Desktop, TDEIcon::SizeMedium );
63  TQWidget *header = createHeader( this, icon, i18n( "To-do" ) );
64  mainLayout->addWidget( header );
65 
66  mLayout = new TQGridLayout( mainLayout, 7, 4, 3 );
67  mLayout->setRowStretch( 6, 1 );
68 
69  mCalendar = KOrg::StdCalendar::self();
70 
71  connect( mCalendar, TQ_SIGNAL( calendarChanged() ), TQ_SLOT( updateView() ) );
72  connect( mPlugin->core(), TQ_SIGNAL( dayChanged( const TQDate& ) ),
73  TQ_SLOT( updateView() ) );
74 
75  updateView();
76 }
77 
78 TodoSummaryWidget::~TodoSummaryWidget()
79 {
80 }
81 
82 void TodoSummaryWidget::updateView()
83 {
84  mLabels.setAutoDelete( true );
85  mLabels.clear();
86  mLabels.setAutoDelete( false );
87 
88  TDEConfig config( "kcmkorgsummaryrc" );
89  config.setGroup( "Todo" );
90  bool showAllTodos = config.readBoolEntry( "ShowAllTodos", false );
91 
92  TDEIconLoader loader( "tdepim" );
93 
94  TQLabel *label = 0;
95  int counter = 0;
96 
97  TQDate currentDate = TQDate::currentDate();
98  KCal::Todo::List todos = mCalendar->todos();
99  if ( todos.count() > 0 ) {
100  TQPixmap pm = loader.loadIcon( "todo", TDEIcon::Small );
101  KCal::Todo::List::ConstIterator it;
102  for ( it = todos.begin(); it != todos.end(); ++it ) {
103  KCal::Todo *todo = *it;
104 
105  bool accepted = false;
106  TQString stateText;
107 
108  // show all incomplete todos
109  if ( showAllTodos && !todo->isCompleted())
110  accepted = true;
111 
112  // show uncomplete todos from the last days
113  if ( todo->hasDueDate() && !todo->isCompleted() &&
114  todo->dtDue().date() < currentDate ) {
115  accepted = true;
116  stateText = i18n( "overdue" );
117  }
118 
119  // show todos which started somewhere in the past and has to be finished in future
120  if ( todo->hasStartDate() && todo->hasDueDate() &&
121  todo->dtStart().date() < currentDate &&
122  currentDate < todo->dtDue().date() ) {
123  accepted = true;
124  stateText = i18n( "in progress" );
125  }
126 
127  // all todos which start today
128  if ( todo->hasStartDate() && todo->dtStart().date() == currentDate ) {
129  accepted = true;
130  stateText = i18n( "starts today" );
131  }
132 
133  // all todos which end today
134  if ( todo->hasDueDate() && todo->dtDue().date() == currentDate ) {
135  accepted = true;
136  stateText = i18n( "ends today" );
137  }
138 
139  if ( !accepted )
140  continue;
141 
142  label = new TQLabel( this );
143  label->setPixmap( pm );
144  label->setSizePolicy( TQSizePolicy::Maximum, TQSizePolicy::Maximum );
145  mLayout->addWidget( label, counter, 0 );
146  mLabels.append( label );
147 
148  label = new TQLabel( TQString::number( todo->percentComplete() ) + "%", this );
149  label->setAlignment( AlignHCenter | AlignVCenter );
150  label->setSizePolicy( TQSizePolicy::Maximum, TQSizePolicy::Maximum );
151  mLayout->addWidget( label, counter, 1 );
152  mLabels.append( label );
153 
154  TQString sSummary = todo->summary();
155  if ( todo->relatedTo() ) { // show parent only, not entire ancestry
156  sSummary = todo->relatedTo()->summary() + ":" + todo->summary();
157  }
158  KURLLabel *urlLabel = new KURLLabel( this );
159  urlLabel->setText( sSummary );
160  urlLabel->setURL( todo->uid() );
161  urlLabel->installEventFilter( this );
162  urlLabel->setTextFormat( TQt::RichText );
163  mLayout->addWidget( urlLabel, counter, 2 );
164  mLabels.append( urlLabel );
165 
166  connect( urlLabel, TQ_SIGNAL( leftClickedURL( const TQString& ) ),
167  this, TQ_SLOT( viewTodo( const TQString& ) ) );
168  connect( urlLabel, TQ_SIGNAL( rightClickedURL( const TQString& ) ),
169  this, TQ_SLOT( popupMenu( const TQString& ) ) );
170 
171  TQString tipText( KCal::IncidenceFormatter::toolTipStr( mCalendar, todo, currentDate, true ) );
172  if ( !tipText.isEmpty() ) {
173  TQToolTip::add( urlLabel, tipText );
174  }
175 
176  label = new TQLabel( stateText, this );
177  label->setAlignment( AlignLeft | AlignVCenter );
178  label->setSizePolicy( TQSizePolicy::Maximum, TQSizePolicy::Maximum );
179  mLayout->addWidget( label, counter, 3 );
180  mLabels.append( label );
181 
182  counter++;
183  }
184  }
185 
186  if ( counter == 0 ) {
187  TQLabel *noTodos = new TQLabel( i18n( "No to-dos pending" ), this );
188  noTodos->setAlignment( AlignHCenter | AlignVCenter );
189  mLayout->addWidget( noTodos, 0, 1 );
190  mLabels.append( noTodos );
191  }
192 
193  for ( label = mLabels.first(); label; label = mLabels.next() )
194  label->show();
195 }
196 
197 void TodoSummaryWidget::viewTodo( const TQString &uid )
198 {
199  mPlugin->core()->selectPlugin( "kontact_todoplugin" );//ensure loaded
200  KOrganizerIface_stub iface( "korganizer", "KOrganizerIface" );
201  iface.editIncidence( uid );
202 }
203 
204 void TodoSummaryWidget::removeTodo( const TQString &uid )
205 {
206  mPlugin->core()->selectPlugin( "kontact_todoplugin" );//ensure loaded
207  KOrganizerIface_stub iface( "korganizer", "KOrganizerIface" );
208  iface.deleteIncidence( uid, false );
209 }
210 
211 void TodoSummaryWidget::completeTodo( const TQString &uid )
212 {
213  KCal::Todo *todo = mCalendar->todo( uid );
214  IncidenceChanger *changer = new IncidenceChanger( mCalendar, this );
215  if ( !todo->isReadOnly() && changer->beginChange( todo, 0, TQString() ) ) {
216  KCal::Todo *oldTodo = todo->clone();
217  todo->setCompleted( TQDateTime::currentDateTime() );
218  changer->changeIncidence( oldTodo, todo, KOGlobals::COMPLETION_MODIFIED, this );
219  changer->endChange( todo, 0, TQString() );
220  delete oldTodo;
221  updateView();
222  }
223 }
224 
225 void TodoSummaryWidget::popupMenu( const TQString &uid )
226 {
227  TDEPopupMenu popup( this );
228  TQToolTip::remove( this );
229  popup.insertItem( i18n( "&Edit To-do..." ), 0 );
230  popup.insertItem( TDEGlobal::iconLoader()->loadIcon( "edit-delete", TDEIcon::Small),
231  i18n( "&Delete To-do" ), 1 );
232  KCal::Todo *todo = mCalendar->todo( uid );
233  if ( !todo->isCompleted() ) {
234  popup.insertItem( TDEGlobal::iconLoader()->loadIcon( "checkedbox", TDEIcon::Small),
235  i18n( "&Mark To-do Completed" ), 2 );
236  }
237 
238  switch ( popup.exec( TQCursor::pos() ) ) {
239  case 0:
240  viewTodo( uid );
241  break;
242  case 1:
243  removeTodo( uid );
244  break;
245  case 2:
246  completeTodo( uid );
247  break;
248  }
249 }
250 
251 bool TodoSummaryWidget::eventFilter( TQObject *obj, TQEvent* e )
252 {
253  if ( obj->inherits( "KURLLabel" ) ) {
254  KURLLabel* label = static_cast<KURLLabel*>( obj );
255  if ( e->type() == TQEvent::Enter )
256  emit message( i18n( "Edit To-do: \"%1\"" ).arg( label->text() ) );
257  if ( e->type() == TQEvent::Leave )
258  emit message( TQString() );
259  }
260 
261  return Kontact::Summary::eventFilter( obj, e );
262 }
263 
264 TQStringList TodoSummaryWidget::configModules() const
265 {
266  return TQStringList( "kcmtodosummary.desktop" );
267 }
268 
269 #include "todosummarywidget.moc"
TQString uid() const
bool isReadOnly() const
Incidence * relatedTo() const
TQString summary() const
bool hasDueDate() const
bool isCompleted() const
bool hasStartDate() const
Todo * clone()
void setCompleted(bool completed)
TQDateTime dtStart(bool first=false) const
int percentComplete() const
TQDateTime dtDue(bool first=false) const