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 <tdestandarddirs.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
55TodoSummaryWidget::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
78TodoSummaryWidget::~TodoSummaryWidget()
79{
80}
81
82void 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
197void 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
204void 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
211void 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
225void 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
251bool 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
264TQStringList 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