kolistview.cpp
00001 /* 00002 This file is part of KOrganizer. 00003 00004 Copyright (c) 1999 Preston Brown <pbrown@kde.org> 00005 Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> 00006 Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com> 00007 00008 This program is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 2 of the License, or 00011 (at your option) any later version. 00012 00013 This program is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with this program; if not, write to the Free Software 00020 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00021 00022 As a special exception, permission is given to link this program 00023 with any edition of TQt, and distribute the resulting executable, 00024 without including the source code for TQt in the source distribution. 00025 */ 00026 00027 #include <tqlistview.h> 00028 #include <tqlayout.h> 00029 #include <tqpopupmenu.h> 00030 #include <tqcursor.h> 00031 #include <tqstyle.h> 00032 00033 #include <klocale.h> 00034 #include <kdebug.h> 00035 #include <kiconloader.h> 00036 #include <kglobal.h> 00037 00038 #include <libkcal/calendar.h> 00039 #include <libkcal/incidenceformatter.h> 00040 00041 #include "koglobals.h" 00042 #include "koprefs.h" 00043 #include "koincidencetooltip.h" 00044 #include "koeventpopupmenu.h" 00045 00046 #include "kolistview.h" 00047 #include "kolistview.moc" 00048 00049 enum { 00050 Summary_Column = 0, 00051 Reminder_Column, 00052 Recurs_Column, 00053 StartDateTime_Column, 00054 EndDateTime_Column, 00055 Categories_Column 00056 }; 00057 00058 00059 KOListViewToolTip::KOListViewToolTip( TQWidget* parent, 00060 Calendar *calendar, 00061 KListView *lv ) 00062 :TQToolTip( parent ), mCalendar( calendar ) 00063 { 00064 eventlist = lv; 00065 } 00066 00067 void KOListViewToolTip::maybeTip( const TQPoint &pos ) 00068 { 00069 TQRect r; 00070 TQListViewItem *it = eventlist->itemAt( pos ); 00071 KOListViewItem *i = static_cast<KOListViewItem*>( it ); 00072 00073 if ( i && KOPrefs::instance()->mEnableToolTips ) { 00074 /* Calculate the rectangle. */ 00075 r = eventlist->itemRect( it ); 00076 /* Show the tip */ 00077 TQString tipText( IncidenceFormatter::toolTipStr( mCalendar, i->data() ) ); 00078 if ( !tipText.isEmpty() ) { 00079 tip( r, tipText ); 00080 } 00081 } 00082 } 00083 00088 class KOListView::ListItemVisitor : public IncidenceBase::Visitor 00089 { 00090 public: 00091 ListItemVisitor( KOListViewItem *item ) : mItem( item ) {} 00092 ~ListItemVisitor() {} 00093 00094 bool visit( Event * ); 00095 bool visit( Todo * ); 00096 bool visit( Journal * ); 00097 00098 private: 00099 KOListViewItem *mItem; 00100 }; 00101 00102 bool KOListView::ListItemVisitor::visit( Event *e ) 00103 { 00104 mItem->setText( Summary_Column, e->summary() ); 00105 if ( e->isAlarmEnabled() ) { 00106 static const TQPixmap alarmPxmp = KOGlobals::self()->smallIcon( "bell" ); 00107 mItem->setPixmap( Reminder_Column, alarmPxmp ); 00108 mItem->setSortKey( Reminder_Column, "1" ); 00109 } else { 00110 mItem->setSortKey( Reminder_Column, "0" ); 00111 } 00112 00113 if ( e->doesRecur() ) { 00114 static const TQPixmap recurPxmp = KOGlobals::self()->smallIcon( "recur" ); 00115 mItem->setPixmap( Recurs_Column, recurPxmp ); 00116 mItem->setSortKey( Recurs_Column, "1" ); 00117 } else { 00118 mItem->setSortKey( Recurs_Column, "0" ); 00119 } 00120 00121 TQPixmap eventPxmp; 00122 if ( e->customProperty( "KABC", "BIRTHDAY" ) == "YES" ) { 00123 if ( e->customProperty( "KABC", "ANNIVERSARY" ) == "YES" ) { 00124 eventPxmp = KOGlobals::self()->smallIcon( "calendaranniversary" ); 00125 } else { 00126 eventPxmp = KOGlobals::self()->smallIcon( "calendarbirthday" ); 00127 } 00128 } else { 00129 eventPxmp = KOGlobals::self()->smallIcon( "appointment" ); 00130 } 00131 00132 mItem->setPixmap( Summary_Column, eventPxmp ); 00133 00134 TQString startDateTime; 00135 TQString endDateTime; 00136 00137 mItem->setText( StartDateTime_Column, IncidenceFormatter::dateTimeToString( e->dtStart(), e->doesFloat() ) ); 00138 mItem->setSortKey( StartDateTime_Column, e->dtStart().toString( Qt::ISODate ) ); 00139 mItem->setText( EndDateTime_Column, IncidenceFormatter::dateTimeToString( e->dtEnd(), e->doesFloat() ) ); 00140 mItem->setSortKey( EndDateTime_Column, e->dtEnd().toString( Qt::ISODate ) ); 00141 mItem->setText( Categories_Column, e->categoriesStr() ); 00142 00143 return true; 00144 } 00145 00146 bool KOListView::ListItemVisitor::visit( Todo *t ) 00147 { 00148 static const TQPixmap todoPxmp = KOGlobals::self()->smallIcon( "todo" ); 00149 static const TQPixmap todoDonePxmp = KOGlobals::self()->smallIcon( "checkedbox" ); 00150 mItem->setPixmap(Summary_Column, t->isCompleted() ? todoDonePxmp : todoPxmp ); 00151 mItem->setText(Summary_Column, t->summary()); 00152 if ( t->isAlarmEnabled() ) { 00153 static const TQPixmap alarmPxmp = KOGlobals::self()->smallIcon( "bell" ); 00154 mItem->setPixmap( Reminder_Column, alarmPxmp ); 00155 mItem->setSortKey( Reminder_Column, "1" ); 00156 } else { 00157 mItem->setSortKey( Reminder_Column, "0" ); 00158 } 00159 00160 if ( t->doesRecur() ) { 00161 static const TQPixmap recurPxmp = KOGlobals::self()->smallIcon( "recur" ); 00162 mItem->setPixmap( Recurs_Column, recurPxmp ); 00163 mItem->setSortKey( Recurs_Column, "1" ); 00164 } else { 00165 mItem->setSortKey( Recurs_Column, "0" ); 00166 } 00167 00168 if ( t->hasStartDate() ) { 00169 mItem->setText( StartDateTime_Column, IncidenceFormatter::dateTimeToString( t->dtStart(), t->doesFloat() ) ); 00170 mItem->setSortKey( StartDateTime_Column, t->dtStart().toString( Qt::ISODate ) ); 00171 } else { 00172 mItem->setText( StartDateTime_Column, "---" ); 00173 } 00174 00175 if ( t->hasDueDate() ) { 00176 mItem->setText( EndDateTime_Column, IncidenceFormatter::dateTimeToString( t->dtDue(), t->doesFloat() ) ); 00177 mItem->setSortKey( EndDateTime_Column, t->dtDue().toString( Qt::ISODate ) ); 00178 } else { 00179 mItem->setText( EndDateTime_Column, "---" ); 00180 } 00181 mItem->setText( Categories_Column, t->categoriesStr() ); 00182 00183 return true; 00184 } 00185 00186 bool KOListView::ListItemVisitor::visit( Journal *j ) 00187 { 00188 static const TQPixmap jornalPxmp = KOGlobals::self()->smallIcon( "journal" ); 00189 mItem->setPixmap( Summary_Column, jornalPxmp ); 00190 // Just use the first line 00191 mItem->setText( Summary_Column, j->description().section( "\n", 0, 0 ) ); 00192 mItem->setText( StartDateTime_Column, IncidenceFormatter::dateTimeToString( j->dtStart(), j->doesFloat() ) ); 00193 mItem->setSortKey( StartDateTime_Column, j->dtStart().toString( Qt::ISODate ) ); 00194 00195 return true; 00196 } 00197 00198 KOListView::KOListView( Calendar *calendar, 00199 TQWidget *parent, 00200 const char *name, 00201 bool nonInteractive ) 00202 : KOEventView( calendar, parent, name ) 00203 { 00204 mActiveItem = 0; 00205 mIsNonInteractive = nonInteractive; 00206 00207 mListView = new KListView( this ); 00208 mListView->addColumn( i18n("Summary") ); 00209 mListView->addColumn( i18n("Reminder") ); // alarm set? 00210 mListView->setColumnAlignment( Reminder_Column, AlignHCenter ); 00211 00212 mListView->addColumn( i18n("Recurs") ); // recurs? 00213 mListView->setColumnAlignment( Recurs_Column, AlignHCenter ); 00214 00215 mListView->addColumn( i18n("Start Date/Time") ); 00216 mListView->setColumnAlignment( StartDateTime_Column, AlignHCenter ); 00217 00218 mListView->addColumn( i18n("End Date/Time") ); 00219 mListView->setColumnAlignment( EndDateTime_Column, AlignHCenter ); 00220 00221 mListView->addColumn( i18n("Categories") ); 00222 00223 TQBoxLayout *layoutTop = new TQVBoxLayout( this ); 00224 layoutTop->addWidget( mListView ); 00225 00226 mPopupMenu = eventPopup(); 00227 /* 00228 mPopupMenu->insertSeparator(); 00229 mPopupMenu->insertItem(i18n("Show Dates"), this, 00230 TQT_SLOT(showDates())); 00231 mPopupMenu->insertItem(i18n("Hide Dates"), this, 00232 TQT_SLOT(hideDates())); 00233 */ 00234 00235 connect( mListView, TQT_SIGNAL( doubleClicked( TQListViewItem * ) ), 00236 TQT_SLOT( defaultItemAction( TQListViewItem * ) ) ); 00237 connect( mListView, TQT_SIGNAL( returnPressed( TQListViewItem * ) ), 00238 TQT_SLOT( defaultItemAction( TQListViewItem * ) ) ); 00239 connect( mListView, TQT_SIGNAL( rightButtonClicked ( TQListViewItem *, 00240 const TQPoint &, 00241 int ) ), 00242 TQT_SLOT( popupMenu( TQListViewItem *, const TQPoint &, int ) ) ); 00243 connect( mListView, TQT_SIGNAL( selectionChanged() ), 00244 TQT_SLOT( processSelectionChange() ) ); 00245 00246 // setMinimumSize(100,100); 00247 mListView->restoreLayout( KOGlobals::self()->config(), "KOListView Layout" ); 00248 00249 new KOListViewToolTip( mListView->viewport(), calendar, mListView ); 00250 00251 mSelectedDates.append( TQDate::currentDate() ); 00252 } 00253 00254 KOListView::~KOListView() 00255 { 00256 delete mPopupMenu; 00257 } 00258 00259 int KOListView::maxDatesHint() 00260 { 00261 return 0; 00262 } 00263 00264 int KOListView::currentDateCount() 00265 { 00266 return mSelectedDates.count(); 00267 } 00268 00269 Incidence::List KOListView::selectedIncidences() 00270 { 00271 Incidence::List eventList; 00272 00273 TQListViewItem *item = mListView->selectedItem(); 00274 if ( item ) { 00275 eventList.append( static_cast<KOListViewItem *>( item )->data() ); 00276 } 00277 00278 return eventList; 00279 } 00280 00281 DateList KOListView::selectedIncidenceDates() 00282 { 00283 return mSelectedDates; 00284 } 00285 00286 void KOListView::showDates( bool show ) 00287 { 00288 // Shouldn't we set it to a value greater 0? When showDates is called with 00289 // show == true at first, then the columnwidths are set to zero. 00290 static int oldColWidth1 = 0; 00291 static int oldColWidth3 = 0; 00292 00293 if ( !show ) { 00294 oldColWidth1 = mListView->columnWidth( 1 ); 00295 oldColWidth3 = mListView->columnWidth( 3 ); 00296 mListView->setColumnWidth( 1, 0 ); 00297 mListView->setColumnWidth( 3, 0 ); 00298 } else { 00299 mListView->setColumnWidth( 1, oldColWidth1 ); 00300 mListView->setColumnWidth( 3, oldColWidth3 ); 00301 } 00302 mListView->repaint(); 00303 } 00304 00305 void KOListView::showDates() 00306 { 00307 showDates( true ); 00308 } 00309 00310 void KOListView::hideDates() 00311 { 00312 showDates( false ); 00313 } 00314 00315 void KOListView::updateView() 00316 { 00317 kdDebug(5850) << "KOListView::updateView() does nothing" << endl; 00318 } 00319 00320 void KOListView::showDates( const TQDate &start, const TQDate &end ) 00321 { 00322 clear(); 00323 00324 TQDate date = start; 00325 while( date <= end ) { 00326 addIncidences( calendar()->incidences( date ), date ); 00327 mSelectedDates.append( date ); 00328 date = date.addDays( 1 ); 00329 } 00330 00331 emit incidenceSelected( 0, TQDate() ); 00332 } 00333 00334 void KOListView::showAll() 00335 { 00336 Incidence::List incidenceList = calendar()->incidences(); 00337 00338 Incidence::List::ConstIterator it; 00339 for( it = incidenceList.begin(); it != incidenceList.end(); ++it ) { 00340 // we don't need the date, using showAll in non interactive mode for now 00341 addIncidence( *it, TQDate() ); 00342 } 00343 } 00344 00345 void KOListView::addIncidences( const Incidence::List &incidenceList, const TQDate &date ) 00346 { 00347 Incidence::List::ConstIterator it; 00348 for( it = incidenceList.begin(); it != incidenceList.end(); ++it ) { 00349 addIncidence( *it, date ); 00350 } 00351 } 00352 00353 void KOListView::addIncidence( Incidence *incidence, const TQDate &date ) 00354 { 00355 if ( mUidDict.find( incidence->uid() ) ) { 00356 return; 00357 } 00358 00359 mDateList[incidence->uid()] = date; 00360 mUidDict.insert( incidence->uid(), incidence ); 00361 00362 KOListViewItem *item = new KOListViewItem( incidence, mListView ); 00363 ListItemVisitor v( item ); 00364 if (incidence->accept( v ) ) { 00365 return; 00366 } else { 00367 delete item; 00368 } 00369 } 00370 00371 void KOListView::showIncidences( const Incidence::List &incidenceList, const TQDate &date ) 00372 { 00373 clear(); 00374 00375 addIncidences( incidenceList, date ); 00376 00377 // After new creation of list view no events are selected. 00378 emit incidenceSelected( 0, date ); 00379 } 00380 00381 void KOListView::changeIncidenceDisplay( Incidence *incidence, int action ) 00382 { 00383 KOListViewItem *item; 00384 TQDate f = mSelectedDates.first(); 00385 TQDate l = mSelectedDates.last(); 00386 00387 TQDate date; 00388 if ( incidence->type() == "Todo" ) { 00389 date = static_cast<Todo *>( incidence )->dtDue().date(); 00390 } else { 00391 date = incidence->dtStart().date(); 00392 } 00393 00394 switch( action ) { 00395 case KOGlobals::INCIDENCEADDED: { 00396 if ( date >= f && date <= l ) 00397 addIncidence( incidence, date ); 00398 break; 00399 } 00400 case KOGlobals::INCIDENCEEDITED: { 00401 item = getItemForIncidence( incidence ); 00402 if ( item ) { 00403 delete item; 00404 mUidDict.remove( incidence->uid() ); 00405 mDateList.remove( incidence->uid() ); 00406 } 00407 if ( date >= f && date <= l ) { 00408 addIncidence( incidence, date ); 00409 } 00410 } 00411 break; 00412 case KOGlobals::INCIDENCEDELETED: { 00413 item = getItemForIncidence( incidence ); 00414 if ( item ) { 00415 delete item; 00416 } 00417 break; 00418 } 00419 default: 00420 kdDebug(5850) << "KOListView::changeIncidenceDisplay(): Illegal action " << action << endl; 00421 } 00422 } 00423 00424 KOListViewItem *KOListView::getItemForIncidence( Incidence *incidence ) 00425 { 00426 KOListViewItem *item = static_cast<KOListViewItem *>( mListView->firstChild() ); 00427 while ( item ) { 00428 // kdDebug(5850) << "Item " << item->text(0) << " found" << endl; 00429 if ( item->data() == incidence ) { 00430 return item; 00431 } 00432 item = static_cast<KOListViewItem *>( item->nextSibling() ); 00433 } 00434 return 0; 00435 } 00436 00437 void KOListView::defaultItemAction( TQListViewItem *i ) 00438 { 00439 if ( !mIsNonInteractive ) { 00440 KOListViewItem *item = static_cast<KOListViewItem *>( i ); 00441 if ( item ) { 00442 defaultAction( item->data() ); 00443 } 00444 } 00445 } 00446 00447 void KOListView::popupMenu( TQListViewItem *item,const TQPoint &, int ) 00448 { 00449 if ( !mIsNonInteractive ) { 00450 mActiveItem = static_cast<KOListViewItem *>( item ); 00451 if ( mActiveItem ) { 00452 Incidence *incidence = mActiveItem->data(); 00453 // FIXME: For recurring incidences we don't know the date of this 00454 // occurrence, there's no reference to it at all! 00455 mPopupMenu->showIncidencePopup( calendar(), incidence, TQDate() ); 00456 } else { 00457 showNewEventPopup(); 00458 } 00459 } 00460 } 00461 00462 void KOListView::readSettings( KConfig *config ) 00463 { 00464 mListView->restoreLayout( config,"KOListView Layout" ); 00465 } 00466 00467 void KOListView::writeSettings( KConfig *config ) 00468 { 00469 mListView->saveLayout( config, "KOListView Layout" ); 00470 } 00471 00472 void KOListView::processSelectionChange() 00473 { 00474 if ( !mIsNonInteractive ) { 00475 kdDebug(5850) << "KOListView::processSelectionChange()" << endl; 00476 00477 KOListViewItem *item = 00478 static_cast<KOListViewItem *>( mListView->selectedItem() ); 00479 00480 if ( !item ) { 00481 emit incidenceSelected( 0, TQDate() ); 00482 } else { 00483 Incidence *incidence = static_cast<Incidence *>( item->data() ); 00484 emit incidenceSelected( incidence, mDateList[incidence->uid()] ); 00485 } 00486 } 00487 } 00488 00489 void KOListView::clearSelection() 00490 { 00491 mListView->selectAll( false ); 00492 } 00493 00494 void KOListView::clear() 00495 { 00496 mSelectedDates.clear(); 00497 mListView->clear(); 00498 mUidDict.clear(); 00499 mDateList.clear(); 00500 } 00501 00502 TQSize KOListView::sizeHint() const 00503 { 00504 const TQSize s = KOEventView::sizeHint(); 00505 return TQSize( s.width() + style().pixelMetric( TQStyle::PM_ScrollBarExtent ) + 1, 00506 s.height() ); 00507 }