korganizer

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 Qt, and distribute the resulting executable,
00024     without including the source code for Qt in the source distribution.
00025 */
00026 
00027 #include <qlistview.h>
00028 #include <qlayout.h>
00029 #include <qpopupmenu.h>
00030 #include <qcursor.h>
00031 
00032 #include <klocale.h>
00033 #include <kdebug.h>
00034 #include <kiconloader.h>
00035 #include <kglobal.h>
00036 
00037 #include <libkcal/calendar.h>
00038 #include <libkcal/incidenceformatter.h>
00039 
00040 #include "koglobals.h"
00041 #include "koprefs.h"
00042 #include "koincidencetooltip.h"
00043 #include "koeventpopupmenu.h"
00044 
00045 #include "kolistview.h"
00046 #include "kolistview.moc"
00047 
00048 
00049 KOListViewToolTip::KOListViewToolTip( QWidget* parent,
00050                                       KListView* lv )
00051   :QToolTip(parent)
00052 {
00053   eventlist=lv;
00054 }
00055 
00056 void KOListViewToolTip::maybeTip( const QPoint & pos)
00057 {
00058   QRect r;
00059   QListViewItem *it = eventlist->itemAt(pos);
00060   KOListViewItem *i = static_cast<KOListViewItem*>(it);
00061 
00062   if( i && KOPrefs::instance()->mEnableToolTips ) {
00063     /* Calculate the rectangle. */
00064     r=eventlist->itemRect( it );
00065     /* Show the tip */
00066     QString tipText( IncidenceFormatter::toolTipString( i->data() ) );
00067     if ( !tipText.isEmpty() ) {
00068       tip(r, tipText);
00069     }
00070   }
00071 
00072 }
00073 
00078 class KOListView::ListItemVisitor : public IncidenceBase::Visitor
00079 {
00080   public:
00081     ListItemVisitor( KOListViewItem *item ) : mItem( item ) {}
00082     ~ListItemVisitor() {}
00083 
00084     bool visit( Event * );
00085     bool visit( Todo * );
00086     bool visit( Journal * );
00087 
00088   private:
00089     KOListViewItem *mItem;
00090 };
00091 
00092 bool KOListView::ListItemVisitor::visit( Event *e )
00093 {
00094   mItem->setText(0,e->summary());
00095   if ( e->isAlarmEnabled() ) {
00096     static const QPixmap alarmPxmp = KOGlobals::self()->smallIcon( "bell" );
00097     mItem->setPixmap(1,alarmPxmp);
00098     mItem->setSortKey(1,"1");
00099   }
00100   else
00101     mItem->setSortKey(1,"0");
00102 
00103   if ( e->doesRecur() ) {
00104     static const QPixmap recurPxmp = KOGlobals::self()->smallIcon( "recur" );
00105     mItem->setPixmap(2,recurPxmp);
00106     mItem->setSortKey(2,"1");
00107   }
00108   else
00109     mItem->setSortKey(2,"0");
00110 
00111   static const QPixmap eventPxmp = KOGlobals::self()->smallIcon( "appointment" );
00112   mItem->setPixmap(0, eventPxmp);
00113 
00114   mItem->setText( 3,e->dtStartDateStr());
00115   mItem->setSortKey( 3, e->dtStart().toString(Qt::ISODate));
00116   if (e->doesFloat()) mItem->setText(4, "---"); else {
00117     mItem->setText( 4, e->dtStartTimeStr() );
00118     mItem->setSortKey( 4,e->dtStart().time().toString(Qt::ISODate));
00119   }
00120   mItem->setText( 5,e->dtEndDateStr());
00121   mItem->setSortKey( 5, e->dtEnd().toString(Qt::ISODate));
00122   if (e->doesFloat()) mItem->setText(6, "---"); else {
00123     mItem->setText( 6, e->dtEndTimeStr() );
00124     mItem->setSortKey( 6, e->dtEnd().time().toString(Qt::ISODate));
00125   }
00126   mItem->setText( 7,e->categoriesStr());
00127 
00128   return true;
00129 }
00130 
00131 bool KOListView::ListItemVisitor::visit(Todo *t)
00132 {
00133   static const QPixmap todoPxmp = KOGlobals::self()->smallIcon( "todo" );
00134   static const QPixmap todoDonePxmp = KOGlobals::self()->smallIcon( "checkedbox" );
00135   mItem->setPixmap(0, t->isCompleted() ? todoDonePxmp : todoPxmp );
00136   mItem->setText(0,t->summary());
00137   if ( t->isAlarmEnabled() ) {
00138     static const QPixmap alarmPxmp = KOGlobals::self()->smallIcon( "bell" );
00139     mItem->setPixmap(1,alarmPxmp);
00140     mItem->setSortKey(1, "1");
00141   }
00142   else
00143     mItem->setSortKey(1, "0");
00144 
00145   if ( t->doesRecur() ) {
00146     static const QPixmap recurPxmp = KOGlobals::self()->smallIcon( "recur" );
00147     mItem->setPixmap(2,recurPxmp);
00148     mItem->setSortKey(2, "1");
00149   }
00150   else
00151     mItem->setSortKey(2, "0");
00152 
00153   if (t->hasStartDate()) {
00154     mItem->setText(3,t->dtStartDateStr());
00155     mItem->setSortKey(3,t->dtStart().toString(Qt::ISODate));
00156     if (t->doesFloat()) {
00157       mItem->setText(4,"---");
00158     } else {
00159       mItem->setText(4,t->dtStartTimeStr());
00160       mItem->setSortKey( 4, t->dtStart().time().toString(Qt::ISODate) );
00161     }
00162   } else {
00163     mItem->setText(3,"---");
00164     mItem->setText(4,"---");
00165   }
00166 
00167   if (t->hasDueDate()) {
00168     mItem->setText(5,t->dtDueDateStr());
00169     mItem->setSortKey( 5, t->dtDue().toString(Qt::ISODate) );
00170     if (t->doesFloat()) {
00171       mItem->setText(6,"---");
00172     } else {
00173       mItem->setText(6,t->dtDueTimeStr());
00174       mItem->setSortKey( 6, t->dtDue().time().toString(Qt::ISODate) );
00175     }
00176   } else {
00177     mItem->setText(5,"---");
00178     mItem->setText(6,"---");
00179   }
00180   mItem->setText(7,t->categoriesStr());
00181 
00182 
00183   return true;
00184 }
00185 
00186 bool KOListView::ListItemVisitor::visit(Journal *t)
00187 {
00188   static const QPixmap jrnalPxmp = KOGlobals::self()->smallIcon( "journal" );
00189   mItem->setPixmap(0,jrnalPxmp);
00190   // Just use the first line
00191   mItem->setText( 0, t->description().section( "\n", 0, 0 ) );
00192   mItem->setText( 3, t->dtStartDateStr() );
00193   mItem->setSortKey( 3, t->dtStart().toString(Qt::ISODate) );
00194 
00195   return true;
00196 }
00197 
00198 KOListView::KOListView( Calendar *calendar, QWidget *parent,
00199                         const char *name)
00200   : KOEventView(calendar, parent, name)
00201 {
00202   mActiveItem = 0;
00203 
00204   mListView = new KListView(this);
00205   mListView->addColumn(i18n("Summary"));
00206   mListView->addColumn(i18n("Reminder")); // alarm set?
00207   mListView->addColumn(i18n("Recurs")); // recurs?
00208   mListView->addColumn(i18n("Start Date"));
00209   mListView->setColumnAlignment(3,AlignHCenter);
00210   mListView->addColumn(i18n("Start Time"));
00211   mListView->setColumnAlignment(4,AlignHCenter);
00212   mListView->addColumn(i18n("End Date"));
00213   mListView->setColumnAlignment(5,AlignHCenter);
00214   mListView->addColumn(i18n("End Time"));
00215   mListView->setColumnAlignment(6,AlignHCenter);
00216   mListView->addColumn(i18n("Categories"));
00217 
00218   QBoxLayout *layoutTop = new QVBoxLayout(this);
00219   layoutTop->addWidget(mListView);
00220 
00221   mPopupMenu = eventPopup();
00222 /*
00223   mPopupMenu->insertSeparator();
00224   mPopupMenu->insertItem(i18n("Show Dates"), this,
00225                       SLOT(showDates()));
00226   mPopupMenu->insertItem(i18n("Hide Dates"), this,
00227                       SLOT(hideDates()));
00228 */
00229 
00230   QObject::connect( mListView, SIGNAL( doubleClicked( QListViewItem * ) ),
00231                     SLOT( defaultItemAction( QListViewItem * ) ) );
00232   QObject::connect( mListView, SIGNAL( returnPressed( QListViewItem * ) ),
00233                     SLOT( defaultItemAction( QListViewItem * ) ) );
00234   QObject::connect( mListView, SIGNAL( rightButtonClicked ( QListViewItem *,
00235                                                             const QPoint &,
00236                                                             int ) ),
00237                     SLOT( popupMenu( QListViewItem *, const QPoint &, int ) ) );
00238   QObject::connect( mListView, SIGNAL( selectionChanged() ),
00239                     SLOT( processSelectionChange() ) );
00240 
00241 //  setMinimumSize(100,100);
00242   mListView->restoreLayout(KOGlobals::self()->config(),"KOListView Layout");
00243 
00244   new KOListViewToolTip( mListView->viewport(), mListView );
00245 
00246   mSelectedDates.append( QDate::currentDate() );
00247 }
00248 
00249 KOListView::~KOListView()
00250 {
00251   delete mPopupMenu;
00252 }
00253 
00254 int KOListView::maxDatesHint()
00255 {
00256   return 0;
00257 }
00258 
00259 int KOListView::currentDateCount()
00260 {
00261   return mSelectedDates.count();
00262 }
00263 
00264 Incidence::List KOListView::selectedIncidences()
00265 {
00266   Incidence::List eventList;
00267 
00268   QListViewItem *item = mListView->selectedItem();
00269   if (item) eventList.append(((KOListViewItem *)item)->data());
00270 
00271   return eventList;
00272 }
00273 
00274 DateList KOListView::selectedDates()
00275 {
00276   return mSelectedDates;
00277 }
00278 
00279 void KOListView::showDates(bool show)
00280 {
00281   // Shouldn't we set it to a value greater 0? When showDates is called with
00282   // show == true at first, then the columnwidths are set to zero.
00283   static int oldColWidth1 = 0;
00284   static int oldColWidth3 = 0;
00285 
00286   if (!show) {
00287     oldColWidth1 = mListView->columnWidth(1);
00288     oldColWidth3 = mListView->columnWidth(3);
00289     mListView->setColumnWidth(1, 0);
00290     mListView->setColumnWidth(3, 0);
00291   } else {
00292     mListView->setColumnWidth(1, oldColWidth1);
00293     mListView->setColumnWidth(3, oldColWidth3);
00294   }
00295   mListView->repaint();
00296 }
00297 
00298 void KOListView::showDates()
00299 {
00300   showDates(true);
00301 }
00302 
00303 void KOListView::hideDates()
00304 {
00305   showDates(false);
00306 }
00307 
00308 void KOListView::updateView()
00309 {
00310   kdDebug(5850) << "KOListView::updateView() does nothing" << endl;
00311 }
00312 
00313 void KOListView::showDates(const QDate &start, const QDate &end)
00314 {
00315   clear();
00316 
00317   QDate date = start;
00318   while( date <= end ) {
00319     addIncidences( calendar()->incidences(date) );
00320     mSelectedDates.append( date );
00321     date = date.addDays( 1 );
00322   }
00323 
00324   emit incidenceSelected( 0 );
00325 }
00326 
00327 void KOListView::addIncidences( const Incidence::List &incidenceList )
00328 {
00329   Incidence::List::ConstIterator it;
00330   for( it = incidenceList.begin(); it != incidenceList.end(); ++it ) {
00331     addIncidence( *it );
00332   }
00333 }
00334 
00335 void KOListView::addIncidence(Incidence *incidence)
00336 {
00337   if ( mUidDict.find( incidence->uid() ) ) return;
00338 
00339   mUidDict.insert( incidence->uid(), incidence );
00340 
00341   KOListViewItem *item = new KOListViewItem( incidence, mListView );
00342   ListItemVisitor v(item);
00343   if (incidence->accept(v)) return;
00344   else delete item;
00345 }
00346 
00347 void KOListView::showIncidences( const Incidence::List &incidenceList )
00348 {
00349   clear();
00350 
00351   addIncidences( incidenceList );
00352 
00353   // After new creation of list view no events are selected.
00354   emit incidenceSelected( 0 );
00355 }
00356 
00357 void KOListView::changeIncidenceDisplay(Incidence *incidence, int action)
00358 {
00359   KOListViewItem *item;
00360   QDate f = mSelectedDates.first();
00361   QDate l = mSelectedDates.last();
00362 
00363   QDate date;
00364   if ( incidence->type() == "Todo" )
00365     date = static_cast<Todo *>(incidence)->dtDue().date();
00366   else
00367     date = incidence->dtStart().date();
00368 
00369   switch(action) {
00370     case KOGlobals::INCIDENCEADDED: {
00371       if ( date >= f && date <= l )
00372         addIncidence( incidence );
00373       break;
00374     }
00375     case KOGlobals::INCIDENCEEDITED: {
00376       item = getItemForIncidence(incidence);
00377       if (item) {
00378         delete item;
00379         mUidDict.remove( incidence->uid() );
00380       }
00381       if ( date >= f && date <= l )
00382         addIncidence( incidence );
00383     }
00384     break;
00385     case KOGlobals::INCIDENCEDELETED: {
00386       item = getItemForIncidence(incidence);
00387       if (item)
00388         delete item;
00389       break;
00390     }
00391     default:
00392       kdDebug(5850) << "KOListView::changeIncidenceDisplay(): Illegal action " << action << endl;
00393   }
00394 }
00395 
00396 KOListViewItem *KOListView::getItemForIncidence(Incidence *incidence)
00397 {
00398   KOListViewItem *item = (KOListViewItem *)mListView->firstChild();
00399   while (item) {
00400 //    kdDebug(5850) << "Item " << item->text(0) << " found" << endl;
00401     if (item->data() == incidence) return item;
00402     item = (KOListViewItem *)item->nextSibling();
00403   }
00404   return 0;
00405 }
00406 
00407 void KOListView::defaultItemAction(QListViewItem *i)
00408 {
00409   KOListViewItem *item = static_cast<KOListViewItem *>( i );
00410   if ( item ) defaultAction( item->data() );
00411 }
00412 
00413 void KOListView::popupMenu(QListViewItem *item,const QPoint &,int)
00414 {
00415   mActiveItem = (KOListViewItem *)item;
00416   if (mActiveItem) {
00417     Incidence *incidence = mActiveItem->data();
00418     // FIXME: For recurring incidences we don't know the date of this
00419     // occurrence, there's no reference to it at all!
00420     mPopupMenu->showIncidencePopup( incidence, QDate() );
00421   }
00422   else {
00423     showNewEventPopup();
00424   }
00425 }
00426 
00427 void KOListView::readSettings(KConfig *config)
00428 {
00429   mListView->restoreLayout(config,"KOListView Layout");
00430 }
00431 
00432 void KOListView::writeSettings(KConfig *config)
00433 {
00434   mListView->saveLayout(config,"KOListView Layout");
00435 }
00436 
00437 void KOListView::processSelectionChange()
00438 {
00439   kdDebug(5850) << "KOListView::processSelectionChange()" << endl;
00440 
00441   KOListViewItem *item =
00442     static_cast<KOListViewItem *>( mListView->selectedItem() );
00443 
00444   if ( !item ) {
00445     emit incidenceSelected( 0 );
00446   } else {
00447     emit incidenceSelected( item->data() );
00448   }
00449 }
00450 
00451 void KOListView::clearSelection()
00452 {
00453   mListView->selectAll( false );
00454 }
00455 
00456 void KOListView::clear()
00457 {
00458   mSelectedDates.clear();
00459   mListView->clear();
00460   mUidDict.clear();
00461 }