korganizer

kolistview.cpp
1/*
2 This file is part of KOrganizer.
3
4 Copyright (c) 1999 Preston Brown <pbrown@kde.org>
5 Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
6 Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
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 TQt, and distribute the resulting executable,
24 without including the source code for TQt in the source distribution.
25*/
26
27#include <tqlistview.h>
28#include <tqlayout.h>
29#include <tqpopupmenu.h>
30#include <tqcursor.h>
31#include <tqstyle.h>
32
33#include <tdelocale.h>
34#include <kdebug.h>
35#include <kiconloader.h>
36#include <tdeglobal.h>
37
38#include <libkcal/calendar.h>
39#include <libkcal/incidenceformatter.h>
40
41#include "koglobals.h"
42#include "koprefs.h"
43#include "koincidencetooltip.h"
44#include "koeventpopupmenu.h"
45
46#include "kolistview.h"
47#include "kolistview.moc"
48
49enum {
50 Summary_Column = 0,
51 Reminder_Column,
52 Recurs_Column,
53 StartDateTime_Column,
54 EndDateTime_Column,
55 Categories_Column
56};
57
58
59KOListViewToolTip::KOListViewToolTip( TQWidget* parent,
60 Calendar *calendar,
61 TDEListView *lv )
62 :TQToolTip( parent ), mCalendar( calendar )
63{
64 eventlist = lv;
65}
66
67void KOListViewToolTip::maybeTip( const TQPoint &pos )
68{
69 TQRect r;
70 TQListViewItem *it = eventlist->itemAt( pos );
71 KOListViewItem *i = static_cast<KOListViewItem*>( it );
72
73 if ( i && KOPrefs::instance()->mEnableToolTips ) {
74 /* Calculate the rectangle. */
75 r = eventlist->itemRect( it );
76 /* Show the tip */
77 TQString tipText( IncidenceFormatter::toolTipStr( mCalendar, i->data() ) );
78 if ( !tipText.isEmpty() ) {
79 tip( r, tipText );
80 }
81 }
82}
83
88class KOListView::ListItemVisitor : public IncidenceBase::Visitor
89{
90 public:
91 ListItemVisitor( KOListViewItem *item ) : mItem( item ) {}
92 ~ListItemVisitor() {}
93
94 bool visit( Event * );
95 bool visit( Todo * );
96 bool visit( Journal * );
97
98 private:
99 KOListViewItem *mItem;
100};
101
103{
104 mItem->setText( Summary_Column, e->summary() );
105 if ( e->isAlarmEnabled() ) {
106 static const TQPixmap alarmPxmp = KOGlobals::self()->smallIcon( "bell" );
107 mItem->setPixmap( Reminder_Column, alarmPxmp );
108 mItem->setSortKey( Reminder_Column, "1" );
109 } else {
110 mItem->setSortKey( Reminder_Column, "0" );
111 }
112
113 if ( e->doesRecur() ) {
114 static const TQPixmap recurPxmp = KOGlobals::self()->smallIcon( "recur" );
115 mItem->setPixmap( Recurs_Column, recurPxmp );
116 mItem->setSortKey( Recurs_Column, "1" );
117 } else {
118 mItem->setSortKey( Recurs_Column, "0" );
119 }
120
121 TQPixmap eventPxmp;
122 if ( e->customProperty( "KABC", "BIRTHDAY" ) == "YES" ) {
123 if ( e->customProperty( "KABC", "ANNIVERSARY" ) == "YES" ) {
124 eventPxmp = KOGlobals::self()->smallIcon( "calendaranniversary" );
125 } else {
126 eventPxmp = KOGlobals::self()->smallIcon( "calendarbirthday" );
127 }
128 } else {
129 eventPxmp = KOGlobals::self()->smallIcon( "appointment" );
130 }
131
132 mItem->setPixmap( Summary_Column, eventPxmp );
133
134 TQString startDateTime;
135 TQString endDateTime;
136
137 mItem->setText( StartDateTime_Column, IncidenceFormatter::dateTimeToString( e->dtStart(), e->doesFloat() ) );
138 mItem->setSortKey( StartDateTime_Column, e->dtStart().toString( TQt::ISODate ) );
139 mItem->setText( EndDateTime_Column, IncidenceFormatter::dateTimeToString( e->dtEnd(), e->doesFloat() ) );
140 mItem->setSortKey( EndDateTime_Column, e->dtEnd().toString( TQt::ISODate ) );
141 mItem->setText( Categories_Column, e->categoriesStr() );
142
143 return true;
144}
145
147{
148 static const TQPixmap todoPxmp = KOGlobals::self()->smallIcon( "todo" );
149 static const TQPixmap todoDonePxmp = KOGlobals::self()->smallIcon( "checkedbox" );
150 mItem->setPixmap(Summary_Column, t->isCompleted() ? todoDonePxmp : todoPxmp );
151 mItem->setText(Summary_Column, t->summary());
152 if ( t->isAlarmEnabled() ) {
153 static const TQPixmap alarmPxmp = KOGlobals::self()->smallIcon( "bell" );
154 mItem->setPixmap( Reminder_Column, alarmPxmp );
155 mItem->setSortKey( Reminder_Column, "1" );
156 } else {
157 mItem->setSortKey( Reminder_Column, "0" );
158 }
159
160 if ( t->doesRecur() ) {
161 static const TQPixmap recurPxmp = KOGlobals::self()->smallIcon( "recur" );
162 mItem->setPixmap( Recurs_Column, recurPxmp );
163 mItem->setSortKey( Recurs_Column, "1" );
164 } else {
165 mItem->setSortKey( Recurs_Column, "0" );
166 }
167
168 if ( t->hasStartDate() ) {
169 mItem->setText( StartDateTime_Column, IncidenceFormatter::dateTimeToString( t->dtStart(), t->doesFloat() ) );
170 mItem->setSortKey( StartDateTime_Column, t->dtStart().toString( TQt::ISODate ) );
171 } else {
172 mItem->setText( StartDateTime_Column, "---" );
173 }
174
175 if ( t->hasDueDate() ) {
176 mItem->setText( EndDateTime_Column, IncidenceFormatter::dateTimeToString( t->dtDue(), t->doesFloat() ) );
177 mItem->setSortKey( EndDateTime_Column, t->dtDue().toString( TQt::ISODate ) );
178 } else {
179 mItem->setText( EndDateTime_Column, "---" );
180 }
181 mItem->setText( Categories_Column, t->categoriesStr() );
182
183 return true;
184}
185
187{
188 static const TQPixmap jornalPxmp = KOGlobals::self()->smallIcon( "journal" );
189 mItem->setPixmap( Summary_Column, jornalPxmp );
190 // Just use the first line
191 mItem->setText( Summary_Column, j->description().section( "\n", 0, 0 ) );
192 mItem->setText( StartDateTime_Column, IncidenceFormatter::dateTimeToString( j->dtStart(), j->doesFloat() ) );
193 mItem->setSortKey( StartDateTime_Column, j->dtStart().toString( TQt::ISODate ) );
194
195 return true;
196}
197
198KOListView::KOListView( Calendar *calendar,
199 TQWidget *parent,
200 const char *name,
201 bool nonInteractive )
202 : KOEventView( calendar, parent, name )
203{
204 mActiveItem = 0;
205 mIsNonInteractive = nonInteractive;
206
207 mListView = new TDEListView( this );
208 mListView->addColumn( i18n("Summary") );
209 mListView->addColumn( i18n("Reminder") ); // alarm set?
210 mListView->setColumnAlignment( Reminder_Column, AlignHCenter );
211
212 mListView->addColumn( i18n("Recurs") ); // recurs?
213 mListView->setColumnAlignment( Recurs_Column, AlignHCenter );
214
215 mListView->addColumn( i18n("Start Date/Time") );
216 mListView->setColumnAlignment( StartDateTime_Column, AlignHCenter );
217
218 mListView->addColumn( i18n("End Date/Time") );
219 mListView->setColumnAlignment( EndDateTime_Column, AlignHCenter );
220
221 mListView->addColumn( i18n("Categories") );
222
223 TQBoxLayout *layoutTop = new TQVBoxLayout( this );
224 layoutTop->addWidget( mListView );
225
226 mPopupMenu = eventPopup();
227/*
228 mPopupMenu->insertSeparator();
229 mPopupMenu->insertItem(i18n("Show Dates"), this,
230 TQ_SLOT(showDates()));
231 mPopupMenu->insertItem(i18n("Hide Dates"), this,
232 TQ_SLOT(hideDates()));
233*/
234
235 connect( mListView, TQ_SIGNAL( doubleClicked( TQListViewItem * ) ),
236 TQ_SLOT( defaultItemAction( TQListViewItem * ) ) );
237 connect( mListView, TQ_SIGNAL( returnPressed( TQListViewItem * ) ),
238 TQ_SLOT( defaultItemAction( TQListViewItem * ) ) );
239 connect( mListView, TQ_SIGNAL( rightButtonClicked ( TQListViewItem *,
240 const TQPoint &,
241 int ) ),
242 TQ_SLOT( popupMenu( TQListViewItem *, const TQPoint &, int ) ) );
243 connect( mListView, TQ_SIGNAL( selectionChanged() ),
244 TQ_SLOT( processSelectionChange() ) );
245
246// setMinimumSize(100,100);
247 mListView->restoreLayout( KOGlobals::self()->config(), "KOListView Layout" );
248
249 new KOListViewToolTip( mListView->viewport(), calendar, mListView );
250
251 mSelectedDates.append( TQDate::currentDate() );
252}
253
254KOListView::~KOListView()
255{
256 delete mPopupMenu;
257}
258
260{
261 return 0;
262}
263
265{
266 return mSelectedDates.count();
267}
268
270{
271 Incidence::List eventList;
272
273 TQListViewItem *item = mListView->selectedItem();
274 if ( item ) {
275 eventList.append( static_cast<KOListViewItem *>( item )->data() );
276 }
277
278 return eventList;
279}
280
282{
283 return mSelectedDates;
284}
285
286void KOListView::showDates( bool show )
287{
288 // Shouldn't we set it to a value greater 0? When showDates is called with
289 // show == true at first, then the columnwidths are set to zero.
290 static int oldColWidth1 = 0;
291 static int oldColWidth3 = 0;
292
293 if ( !show ) {
294 oldColWidth1 = mListView->columnWidth( 1 );
295 oldColWidth3 = mListView->columnWidth( 3 );
296 mListView->setColumnWidth( 1, 0 );
297 mListView->setColumnWidth( 3, 0 );
298 } else {
299 mListView->setColumnWidth( 1, oldColWidth1 );
300 mListView->setColumnWidth( 3, oldColWidth3 );
301 }
302 mListView->repaint();
303}
304
305void KOListView::showDates()
306{
307 showDates( true );
308}
309
310void KOListView::hideDates()
311{
312 showDates( false );
313}
314
315void KOListView::updateView()
316{
317 kdDebug(5850) << "KOListView::updateView() does nothing" << endl;
318}
319
320void KOListView::showDates( const TQDate &start, const TQDate &end )
321{
322 clear();
323
324 TQDate date = start;
325 while( date <= end ) {
326 addIncidences( calendar()->incidences( date ), date );
327 mSelectedDates.append( date );
328 date = date.addDays( 1 );
329 }
330
331 emit incidenceSelected( 0, TQDate() );
332}
333
334void KOListView::showAll()
335{
336 Incidence::List incidenceList = calendar()->incidences();
337
338 Incidence::List::ConstIterator it;
339 for( it = incidenceList.begin(); it != incidenceList.end(); ++it ) {
340 // we don't need the date, using showAll in non interactive mode for now
341 addIncidence( *it, TQDate() );
342 }
343}
344
345void KOListView::addIncidences( const Incidence::List &incidenceList, const TQDate &date )
346{
347 Incidence::List::ConstIterator it;
348 for( it = incidenceList.begin(); it != incidenceList.end(); ++it ) {
349 addIncidence( *it, date );
350 }
351}
352
353void KOListView::addIncidence( Incidence *incidence, const TQDate &date )
354{
355 if ( mUidDict.find( incidence->uid() ) ) {
356 return;
357 }
358
359 mDateList[incidence->uid()] = date;
360 mUidDict.insert( incidence->uid(), incidence );
361
362 KOListViewItem *item = new KOListViewItem( incidence, mListView );
363 ListItemVisitor v( item );
364 if (incidence->accept( v ) ) {
365 return;
366 } else {
367 delete item;
368 }
369}
370
371void KOListView::showIncidences( const Incidence::List &incidenceList, const TQDate &date )
372{
373 clear();
374
375 addIncidences( incidenceList, date );
376
377 // After new creation of list view no events are selected.
378 emit incidenceSelected( 0, date );
379}
380
381void KOListView::changeIncidenceDisplay( Incidence *incidence, int action )
382{
383 KOListViewItem *item;
384 TQDate f = mSelectedDates.first();
385 TQDate l = mSelectedDates.last();
386
387 TQDate date;
388 if ( incidence->type() == "Todo" ) {
389 date = static_cast<Todo *>( incidence )->dtDue().date();
390 } else {
391 date = incidence->dtStart().date();
392 }
393
394 switch( action ) {
395 case KOGlobals::INCIDENCEADDED: {
396 if ( date >= f && date <= l )
397 addIncidence( incidence, date );
398 break;
399 }
400 case KOGlobals::INCIDENCEEDITED: {
401 item = getItemForIncidence( incidence );
402 if ( item ) {
403 delete item;
404 mUidDict.remove( incidence->uid() );
405 mDateList.remove( incidence->uid() );
406 }
407 if ( date >= f && date <= l ) {
408 addIncidence( incidence, date );
409 }
410 }
411 break;
412 case KOGlobals::INCIDENCEDELETED: {
413 item = getItemForIncidence( incidence );
414 if ( item ) {
415 delete item;
416 }
417 break;
418 }
419 default:
420 kdDebug(5850) << "KOListView::changeIncidenceDisplay(): Illegal action " << action << endl;
421 }
422}
423
424KOListViewItem *KOListView::getItemForIncidence( Incidence *incidence )
425{
426 KOListViewItem *item = static_cast<KOListViewItem *>( mListView->firstChild() );
427 while ( item ) {
428// kdDebug(5850) << "Item " << item->text(0) << " found" << endl;
429 if ( item->data() == incidence ) {
430 return item;
431 }
432 item = static_cast<KOListViewItem *>( item->nextSibling() );
433 }
434 return 0;
435}
436
437void KOListView::defaultItemAction( TQListViewItem *i )
438{
439 if ( !mIsNonInteractive ) {
440 KOListViewItem *item = static_cast<KOListViewItem *>( i );
441 if ( item ) {
442 defaultAction( item->data() );
443 }
444 }
445}
446
447void KOListView::popupMenu( TQListViewItem *item,const TQPoint &, int )
448{
449 if ( !mIsNonInteractive ) {
450 mActiveItem = static_cast<KOListViewItem *>( item );
451 if ( mActiveItem ) {
452 Incidence *incidence = mActiveItem->data();
453 // FIXME: For recurring incidences we don't know the date of this
454 // occurrence, there's no reference to it at all!
455 mPopupMenu->showIncidencePopup( calendar(), incidence, TQDate() );
456 } else {
457 showNewEventPopup();
458 }
459 }
460}
461
462void KOListView::readSettings( TDEConfig *config )
463{
464 mListView->restoreLayout( config,"KOListView Layout" );
465}
466
467void KOListView::writeSettings( TDEConfig *config )
468{
469 mListView->saveLayout( config, "KOListView Layout" );
470}
471
472void KOListView::processSelectionChange()
473{
474 if ( !mIsNonInteractive ) {
475 kdDebug(5850) << "KOListView::processSelectionChange()" << endl;
476
477 KOListViewItem *item =
478 static_cast<KOListViewItem *>( mListView->selectedItem() );
479
480 if ( !item ) {
481 emit incidenceSelected( 0, TQDate() );
482 } else {
483 Incidence *incidence = static_cast<Incidence *>( item->data() );
484 emit incidenceSelected( incidence, mDateList[incidence->uid()] );
485 }
486 }
487}
488
489void KOListView::clearSelection()
490{
491 mListView->selectAll( false );
492}
493
494void KOListView::clear()
495{
496 mSelectedDates.clear();
497 mListView->clear();
498 mUidDict.clear();
499 mDateList.clear();
500}
501
502TQSize KOListView::sizeHint() const
503{
504 const TQSize s = KOEventView::sizeHint();
505 return TQSize( s.width() + style().pixelMetric( TQStyle::PM_ScrollBarExtent ) + 1,
506 s.height() );
507}
virtual Incidence::List incidences()
TQString customProperty(const TQCString &app, const TQCString &key) const
virtual TQDateTime dtEnd() const
virtual bool visit(FreeBusy *)
virtual bool visit(Event *)
bool doesFloat() const
TQString uid() const
virtual TQDateTime dtStart() const
virtual bool accept(Visitor &)
TQString description() const
bool doesRecur() const
bool isAlarmEnabled() const
TQString categoriesStr() const
TQString summary() const
bool hasDueDate() const
bool isCompleted() const
bool hasStartDate() const
TQDateTime dtStart(bool first=false) const
TQDateTime dtDue(bool first=false) const
KOEventView is the abstract base class from which all other calendar views for event data are derived...
Definition: koeventview.h:56
void defaultAction(Incidence *)
Perform the default action for an incidence, e.g.
virtual int currentDateCount()
Return number of currently shown dates.
Definition: kolistview.cpp:264
virtual DateList selectedIncidenceDates()
Definition: kolistview.cpp:281
virtual int maxDatesHint()
provides a hint back to the caller on the maximum number of dates that the view supports.
Definition: kolistview.cpp:259
virtual Incidence::List selectedIncidences()
Definition: kolistview.cpp:269
virtual Calendar * calendar()
Return calendar object of this view.
Definition: baseview.h:89