korganizer

kotodoview.cpp

00001 /*
00002     This file is part of KOrganizer.
00003 
00004     Copyright (c) 2000,2001,2003 Cornelius Schumacher <schumacher@kde.org>
00005     Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00006 
00007     This program is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or
00010     (at your option) any later version.
00011 
00012     This program is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020 
00021     As a special exception, permission is given to link this program
00022     with any edition of Qt, and distribute the resulting executable,
00023     without including the source code for Qt in the source distribution.
00024 */
00025 
00026 #include <qlayout.h>
00027 #include <qheader.h>
00028 #include <qcursor.h>
00029 #include <qlabel.h>
00030 #include <qtimer.h>
00031 
00032 #include <kdebug.h>
00033 #include <klocale.h>
00034 #include <kglobal.h>
00035 #include <kiconloader.h>
00036 #include <kmessagebox.h>
00037 
00038 #include <libkcal/calhelper.h>
00039 #include <libkcal/icaldrag.h>
00040 #include <libkcal/vcaldrag.h>
00041 #include <libkcal/dndfactory.h>
00042 #include <libkcal/calendarresources.h>
00043 #include <libkcal/resourcecalendar.h>
00044 #include <libkcal/calfilter.h>
00045 #include <libkcal/incidenceformatter.h>
00046 
00047 #include <libkdepim/clicklineedit.h>
00048 #include <libkdepim/kdatepickerpopup.h>
00049 
00050 #include <libemailfunctions/email.h>
00051 
00052 #include "docprefs.h"
00053 
00054 #include "koincidencetooltip.h"
00055 #include "kodialogmanager.h"
00056 #include "kotodoview.h"
00057 #include "koprefs.h"
00058 #include "koglobals.h"
00059 using namespace KOrg;
00060 #include "kotodoviewitem.h"
00061 #include "kotodoview.moc"
00062 #ifndef KORG_NOPRINTER
00063 #include "kocorehelper.h"
00064 #include "calprinter.h"
00065 #endif
00066 
00067 KOTodoListViewToolTip::KOTodoListViewToolTip (QWidget *parent,
00068                                               Calendar *calendar,
00069                                               KOTodoListView *lv )
00070   :QToolTip(parent), mCalendar( calendar )
00071 {
00072   todolist=lv;
00073 }
00074 
00075 void KOTodoListViewToolTip::maybeTip( const QPoint & pos)
00076 {
00077   QRect r;
00078   int headerPos;
00079   int col=todolist->header()->sectionAt(todolist->contentsX() + pos.x());
00080   KOTodoViewItem *i=(KOTodoViewItem *)todolist->itemAt(pos);
00081 
00082   /* Check wether a tooltip is necessary. */
00083   if( i && KOPrefs::instance()->mEnableToolTips )
00084   {
00085 
00086     /* Calculate the rectangle. */
00087     r=todolist->itemRect(i);
00088     headerPos = todolist->header()->sectionPos(col)-todolist->contentsX();
00089     r.setLeft( (headerPos < 0 ? 0 : headerPos) );
00090     r.setRight(headerPos + todolist->header()->sectionSize(col));
00091 
00092     /* Show the tip */
00093     QString tipText( IncidenceFormatter::toolTipStr( mCalendar, i->todo(), QDate(), true ) );;
00094     if ( !tipText.isEmpty() ) {
00095       tip(r, tipText);
00096     }
00097   }
00098 
00099 }
00100 
00101 
00102 
00103 KOTodoListView::KOTodoListView( QWidget *parent, const char *name )
00104   : KListView( parent, name ), mCalendar( 0 ), mChanger( 0 )
00105 {
00106   mOldCurrent = 0;
00107   mMousePressed = false;
00108 }
00109 
00110 KOTodoListView::~KOTodoListView()
00111 {
00112 }
00113 
00114 void KOTodoListView::setCalendar( Calendar *cal )
00115 {
00116   mCalendar = cal;
00117   setAcceptDrops( mCalendar );
00118   viewport()->setAcceptDrops( mCalendar );
00119 }
00120 
00121 bool KOTodoListView::event(QEvent *e)
00122 {
00123   int tmp=0;
00124   KOTodoViewItem *i;
00125 
00126   /* Checks for an ApplicationPaletteChange event and updates
00127    * the small Progress bars to make therm have the right colors. */
00128   if(e->type()==QEvent::ApplicationPaletteChange)
00129   {
00130 
00131     KListView::event(e);
00132     i=(KOTodoViewItem *)itemAtIndex(tmp);
00133 
00134     while(i!=0)
00135     {
00136       i->construct();
00137       tmp++;
00138       i=(KOTodoViewItem *)itemAtIndex(tmp);
00139     }
00140 
00141   }
00142 
00143   return (KListView::event(e) || e->type()==QEvent::ApplicationPaletteChange);
00144 }
00145 
00146 void KOTodoListView::contentsDragEnterEvent(QDragEnterEvent *e)
00147 {
00148 #ifndef KORG_NODND
00149 //  kdDebug(5850) << "KOTodoListView::contentsDragEnterEvent" << endl;
00150   if ( !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) &&
00151        !QTextDrag::canDecode( e ) ) {
00152     e->ignore();
00153     return;
00154   }
00155 
00156   mOldCurrent = currentItem();
00157 #endif
00158 }
00159 
00160 void KOTodoListView::contentsDragMoveEvent(QDragMoveEvent *e)
00161 {
00162 #ifndef KORG_NODND
00163 //  kdDebug(5850) << "KOTodoListView::contentsDragMoveEvent" << endl;
00164 
00165   if ( !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) &&
00166        !QTextDrag::canDecode( e ) ) {
00167     e->ignore();
00168     return;
00169   }
00170 
00171   e->accept();
00172 #endif
00173 }
00174 
00175 void KOTodoListView::contentsDragLeaveEvent( QDragLeaveEvent * )
00176 {
00177 #ifndef KORG_NODND
00178 //  kdDebug(5850) << "KOTodoListView::contentsDragLeaveEvent" << endl;
00179 
00180   setCurrentItem(mOldCurrent);
00181   setSelected(mOldCurrent,true);
00182 #endif
00183 }
00184 
00185 void KOTodoListView::contentsDropEvent( QDropEvent *e )
00186 {
00187 #ifndef KORG_NODND
00188   kdDebug(5850) << "KOTodoListView::contentsDropEvent" << endl;
00189 
00190   if ( !mCalendar || !mChanger ||
00191        ( !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) &&
00192          !QTextDrag::canDecode( e ) ) ) {
00193     e->ignore();
00194     return;
00195   }
00196 
00197   DndFactory factory( mCalendar );
00198   Todo *todo = factory.createDropTodo(e);
00199 
00200   if ( todo ) {
00201     e->acceptAction();
00202 
00203     KOTodoViewItem *destination =
00204         (KOTodoViewItem *)itemAt(contentsToViewport(e->pos()));
00205     Todo *destinationEvent = 0;
00206     if (destination) destinationEvent = destination->todo();
00207 
00208     Todo *existingTodo = mCalendar->todo(todo->uid());
00209 
00210     if( existingTodo ) {
00211        kdDebug(5850) << "Drop existing Todo " << existingTodo << " onto " << destinationEvent << endl;
00212       Incidence *to = destinationEvent;
00213       while(to) {
00214         if (to->uid() == todo->uid()) {
00215           KMessageBox::information(this,
00216               i18n("Cannot move to-do to itself or a child of itself."),
00217               i18n("Drop To-do"), "NoDropTodoOntoItself" );
00218           delete todo;
00219           return;
00220         }
00221         to = to->relatedTo();
00222       }
00223 
00224       Todo*oldTodo = existingTodo->clone();
00225       if ( mChanger->beginChange( existingTodo, 0, QString() ) ) {
00226         existingTodo->setRelatedTo( destinationEvent );
00227         mChanger->changeIncidence( oldTodo, existingTodo, KOGlobals::RELATION_MODIFIED, this );
00228         mChanger->endChange( existingTodo, 0, QString() );
00229       } else {
00230         KMessageBox::sorry( this, i18n("Unable to change to-do's parent, "
00231                             "because the to-do cannot be locked.") );
00232       }
00233       delete oldTodo;
00234       delete todo;
00235     } else {
00236 //      kdDebug(5850) << "Drop new Todo" << endl;
00237       todo->setRelatedTo(destinationEvent);
00238       if ( !mChanger->addIncidence( todo, 0, QString(), this ) ) {
00239         KODialogManager::errorSaveIncidence( this, todo );
00240         delete todo;
00241         return;
00242       }
00243     }
00244   } else {
00245     QString text;
00246     KOTodoViewItem *todoi = dynamic_cast<KOTodoViewItem *>(itemAt( contentsToViewport(e->pos()) ));
00247     if ( ! todoi ) {
00248       // Not dropped on a todo item:
00249       e->ignore();
00250       kdDebug( 5850 ) << "KOTodoListView::contentsDropEvent(): Not dropped on a todo item" << endl;
00251       kdDebug( 5850 ) << "TODO: Create a new todo with the given data" << endl;
00252       // FIXME: Create a new todo with the given text/contact/whatever
00253     } else if ( QTextDrag::decode(e, text) ) {
00254       //QListViewItem *qlvi = itemAt( contentsToViewport(e->pos()) );
00255       kdDebug(5850) << "Dropped : " << text << endl;
00256       Todo*todo = todoi->todo();
00257       if( mChanger->beginChange( todo, 0, QString() ) ) {
00258         Todo*oldtodo = todo->clone();
00259 
00260         if( text.startsWith( "file:" ) ) {
00261           todo->addAttachment( new Attachment( text ) );
00262         } else {
00263           QStringList emails = KPIM::splitEmailAddrList( text );
00264           for(QStringList::ConstIterator it = emails.begin();it!=emails.end();++it) {
00265             kdDebug(5850) << " Email: " << (*it) << endl;
00266             int pos = (*it).find("<");
00267             QString name = (*it).left(pos);
00268             QString email = (*it).mid(pos);
00269             if (!email.isEmpty() && todoi) {
00270               todo->addAttendee( new Attendee( name, email ) );
00271             }
00272           }
00273         }
00274         //FIXME: attendees or attachment added, so there is something modified
00275         mChanger->changeIncidence( oldtodo, todo, KOGlobals::NOTHING_MODIFIED, this );
00276         mChanger->endChange( todo, 0, QString() );
00277       } else {
00278         KMessageBox::sorry( this, i18n("Unable to add attendees to the to-do, "
00279             "because the to-do cannot be locked.") );
00280       }
00281     }
00282     else {
00283       kdDebug(5850) << "KOTodoListView::contentsDropEvent(): Todo from drop not decodable" << endl;
00284       e->ignore();
00285     }
00286   }
00287 #endif
00288 }
00289 
00290 void KOTodoListView::contentsMousePressEvent(QMouseEvent* e)
00291 {
00292   QListView::contentsMousePressEvent(e);
00293   QPoint p(contentsToViewport(e->pos()));
00294   QListViewItem *i = itemAt(p);
00295   if (i) {
00296     // if the user clicked into the root decoration of the item, don't
00297     // try to start a drag!
00298     if (p.x() > header()->sectionPos(header()->mapToIndex(0)) +
00299         treeStepSize() * (i->depth() + (rootIsDecorated() ? 1 : 0)) +
00300         itemMargin() ||
00301         p.x() < header()->sectionPos(header()->mapToIndex(0))) {
00302       if (e->button()==Qt::LeftButton) {
00303         mPressPos = e->pos();
00304         mMousePressed = true;
00305       }
00306     }
00307   }
00308 }
00309 
00310 void KOTodoListView::contentsMouseMoveEvent(QMouseEvent* e)
00311 {
00312 #ifndef KORG_NODND
00313 //  kdDebug(5850) << "KOTodoListView::contentsMouseMoveEvent()" << endl;
00314   QListView::contentsMouseMoveEvent(e);
00315   if (mMousePressed && (mPressPos - e->pos()).manhattanLength() >
00316       QApplication::startDragDistance()) {
00317     mMousePressed = false;
00318     QListViewItem *item = itemAt(contentsToViewport(mPressPos));
00319     if ( item && mCalendar ) {
00320 //      kdDebug(5850) << "Start Drag for item " << item->text(0) << endl;
00321       DndFactory factory( mCalendar );
00322       ICalDrag *vd = factory.createDrag(
00323                           ((KOTodoViewItem *)item)->todo(),viewport());
00324       if (vd->drag()) {
00325         kdDebug(5850) << "KOTodoListView::contentsMouseMoveEvent(): Delete drag source" << endl;
00326       }
00327 /*
00328       QString source = fullPath(item);
00329       if ( QFile::exists(source) ) {
00330         KURL url;
00331         url.setPath(source);
00332         KURLDrag* ud = KURLDrag::newDrag(KURL::List(url), viewport());
00333         if ( ud->drag() )
00334           QMessageBox::information( this, "Drag source",
00335                                     QString("Delete ")+source, "Not implemented" );
00336 */
00337     }
00338   }
00339 #endif
00340 }
00341 
00342 void KOTodoListView::contentsMouseReleaseEvent(QMouseEvent *e)
00343 {
00344   QListView::contentsMouseReleaseEvent(e);
00345   mMousePressed = false;
00346 }
00347 
00348 void KOTodoListView::contentsMouseDoubleClickEvent(QMouseEvent *e)
00349 {
00350   if (!e) return;
00351 
00352   QPoint vp = contentsToViewport(e->pos());
00353 
00354   QListViewItem *item = itemAt(vp);
00355 
00356   if (!item) return;
00357 
00358   emit doubleClicked(item,vp,0);
00359 }
00360 
00362 
00363 KOTodoView::KOTodoView( Calendar *calendar, QWidget *parent, const char* name)
00364   : KOrg::BaseView( calendar, parent, name )
00365 {
00366   QBoxLayout *topLayout = new QVBoxLayout( this );
00367 
00368   QLabel *title = new QLabel( i18n("To-dos:"), this );
00369   title->setFrameStyle( QFrame::Panel | QFrame::Raised );
00370   topLayout->addWidget( title );
00371 
00372   mQuickAdd = new KPIM::ClickLineEdit( this, i18n( "Click to add a new to-do" ) );
00373   mQuickAdd->setAcceptDrops( false );
00374   topLayout->addWidget( mQuickAdd );
00375 
00376   if ( !KOPrefs::instance()->mEnableQuickTodo ) mQuickAdd->hide();
00377 
00378   mTodoListView = new KOTodoListView( this );
00379   topLayout->addWidget( mTodoListView );
00380 
00381   mTodoListView->setRootIsDecorated( true );
00382   mTodoListView->setAllColumnsShowFocus( true );
00383 
00384   mTodoListView->setShowSortIndicator( true );
00385 
00386   mTodoListView->addColumn( i18n("Summary") );
00387   mTodoListView->addColumn( i18n("Recurs") );
00388   mTodoListView->addColumn( i18n("Priority") );
00389   mTodoListView->setColumnAlignment( ePriorityColumn, AlignHCenter );
00390   mTodoListView->addColumn( i18n("Complete") );
00391   mTodoListView->setColumnAlignment( ePercentColumn, AlignRight );
00392   mTodoListView->addColumn( i18n("Due Date/Time") );
00393   mTodoListView->setColumnAlignment( eDueDateColumn, AlignLeft );
00394   mTodoListView->addColumn( i18n("Categories") );
00395   mTodoListView->addColumn( i18n( "Calendar" ) );
00396 #if 0
00397   mTodoListView->addColumn( i18n("Sort Id") );
00398   mTodoListView->setColumnAlignment( 4, AlignHCenter );
00399 #endif
00400 
00401   mTodoListView->setMinimumHeight( 60 );
00402   mTodoListView->setItemsRenameable( true );
00403   mTodoListView->setRenameable( 0 );
00404 
00405   mTodoListView->setColumnWidthMode( eSummaryColumn, QListView::Manual );
00406   mTodoListView->setColumnWidthMode( eRecurColumn, QListView::Manual );
00407   mTodoListView->setColumnWidthMode( ePriorityColumn, QListView::Manual );
00408   mTodoListView->setColumnWidthMode( ePercentColumn, QListView::Manual );
00409   mTodoListView->setColumnWidthMode( eDueDateColumn, QListView::Manual );
00410   mTodoListView->setColumnWidthMode( eCategoriesColumn, QListView::Manual );
00411   mTodoListView->setColumnWidthMode( eFolderColumn, QListView::Manual );
00412 #if 0
00413   mTodoListView->setColumnWidthMode( eDescriptionColumn, QListView::Manual );
00414 #endif
00415 
00416   mPriorityPopupMenu = new QPopupMenu( this );
00417   mPriority[ mPriorityPopupMenu->insertItem( i18n("Unspecified priority", "unspecified") ) ] = 0;
00418   mPriority[ mPriorityPopupMenu->insertItem( i18n( "1 (highest)") ) ] = 1;
00419   mPriority[ mPriorityPopupMenu->insertItem( i18n( "2" ) ) ] = 2;
00420   mPriority[ mPriorityPopupMenu->insertItem( i18n( "3" ) ) ] = 3;
00421   mPriority[ mPriorityPopupMenu->insertItem( i18n( "4" ) ) ] = 4;
00422   mPriority[ mPriorityPopupMenu->insertItem( i18n( "5 (medium)" ) ) ] = 5;
00423   mPriority[ mPriorityPopupMenu->insertItem( i18n( "6" ) ) ] = 6;
00424   mPriority[ mPriorityPopupMenu->insertItem( i18n( "7" ) ) ] = 7;
00425   mPriority[ mPriorityPopupMenu->insertItem( i18n( "8" ) ) ] = 8;
00426   mPriority[ mPriorityPopupMenu->insertItem( i18n( "9 (lowest)" ) ) ] = 9;
00427   connect( mPriorityPopupMenu, SIGNAL( activated( int ) ),
00428            SLOT( setNewPriority( int ) ));
00429 
00430   mPercentageCompletedPopupMenu = new QPopupMenu(this);
00431   for (int i = 0; i <= 100; i+=10) {
00432     QString label = QString ("%1 %").arg (i);
00433     mPercentage[mPercentageCompletedPopupMenu->insertItem (label)] = i;
00434   }
00435   connect( mPercentageCompletedPopupMenu, SIGNAL( activated( int ) ),
00436            SLOT( setNewPercentage( int ) ) );
00437 
00438   mMovePopupMenu = new KDatePickerPopup(
00439                              KDatePickerPopup::NoDate |
00440                              KDatePickerPopup::DatePicker |
00441                              KDatePickerPopup::Words );
00442   mCopyPopupMenu = new KDatePickerPopup(
00443                              KDatePickerPopup::NoDate |
00444                              KDatePickerPopup::DatePicker |
00445                              KDatePickerPopup::Words );
00446 
00447 
00448   connect( mMovePopupMenu, SIGNAL( dateChanged( QDate )),
00449            SLOT( setNewDate( QDate ) ) );
00450   connect( mCopyPopupMenu, SIGNAL( dateChanged( QDate )),
00451            SLOT( copyTodoToDate( QDate ) ) );
00452 
00453   mItemPopupMenu = new QPopupMenu(this);
00454   mItemPopupMenu->insertItem(i18n("&Show"), this,
00455                              SLOT (showTodo()));
00456   mItemPopupMenu->insertItem(i18n("&Edit..."), this,
00457                              SLOT (editTodo()), 0, ePopupEdit );
00458 #ifndef KORG_NOPRINTER
00459   mItemPopupMenu->insertItem(KOGlobals::self()->smallIcon("printer1"), i18n("&Print..."), this, SLOT( printTodo() ) );
00460 #endif
00461   mItemPopupMenu->insertItem(KOGlobals::self()->smallIconSet("editdelete"), i18n("&Delete"), this,
00462                              SLOT (deleteTodo()), 0, ePopupDelete );
00463   mItemPopupMenu->insertSeparator();
00464   mItemPopupMenu->insertItem(KOGlobals::self()->smallIconSet("todo"), i18n("New &To-do..."), this,
00465                              SLOT (newTodo()) );
00466   mItemPopupMenu->insertItem(i18n("New Su&b-to-do..."), this,
00467                              SLOT (newSubTodo()));
00468   mItemPopupMenu->insertItem( i18n("&Make this To-do Independent"), this,
00469       SIGNAL( unSubTodoSignal() ), 0, ePopupUnSubTodo );
00470   mItemPopupMenu->insertItem( i18n("Make all Sub-to-dos &Independent"), this,
00471       SIGNAL( unAllSubTodoSignal() ), 0, ePopupUnAllSubTodo );
00472   mItemPopupMenu->insertSeparator();
00473   mItemPopupMenu->insertItem( i18n("&Copy To"), mCopyPopupMenu, ePopupCopyTo );
00474   mItemPopupMenu->insertItem(i18n("&Move To"), mMovePopupMenu, ePopupMoveTo );
00475   mItemPopupMenu->insertSeparator();
00476   mItemPopupMenu->insertItem(i18n("delete completed to-dos","Pur&ge Completed"),
00477                              this, SLOT( purgeCompleted() ) );
00478 
00479   connect( mMovePopupMenu, SIGNAL( dateChanged( QDate ) ),
00480            mItemPopupMenu, SLOT( hide() ) );
00481   connect( mCopyPopupMenu, SIGNAL( dateChanged( QDate ) ),
00482            mItemPopupMenu, SLOT( hide() ) );
00483 
00484   mPopupMenu = new QPopupMenu(this);
00485   mPopupMenu->insertItem(KOGlobals::self()->smallIconSet("todo"), i18n("&New To-do..."), this,
00486                          SLOT(newTodo()) );
00487   mPopupMenu->insertItem(i18n("delete completed to-dos","&Purge Completed"),
00488                          this, SLOT(purgeCompleted()));
00489 
00490   mDocPrefs = new DocPrefs( name );
00491 
00492   // Double clicking conflicts with opening/closing the subtree
00493   connect( mTodoListView, SIGNAL( doubleClicked( QListViewItem *,
00494                                                  const QPoint &, int ) ),
00495            SLOT( editItem( QListViewItem *, const QPoint &, int ) ) );
00496   connect( mTodoListView, SIGNAL( returnPressed( QListViewItem * ) ),
00497            SLOT( editItem( QListViewItem * ) ) );
00498   connect( mTodoListView, SIGNAL( contextMenuRequested( QListViewItem *,
00499                                                         const QPoint &, int ) ),
00500            SLOT( popupMenu( QListViewItem *, const QPoint &, int ) ) );
00501   connect( mTodoListView, SIGNAL( expanded( QListViewItem * ) ),
00502            SLOT( itemStateChanged( QListViewItem * ) ) );
00503   connect( mTodoListView, SIGNAL( collapsed( QListViewItem * ) ),
00504            SLOT( itemStateChanged( QListViewItem * ) ) );
00505 
00506 #if 0
00507   connect(mTodoListView,SIGNAL(selectionChanged(QListViewItem *)),
00508           SLOT(selectionChanged(QListViewItem *)));
00509   connect(mTodoListView,SIGNAL(clicked(QListViewItem *)),
00510           SLOT(selectionChanged(QListViewItem *)));
00511   connect(mTodoListView,SIGNAL(pressed(QListViewItem *)),
00512           SLOT(selectionChanged(QListViewItem *)));
00513 #endif
00514   connect( mTodoListView, SIGNAL(selectionChanged() ),
00515            SLOT( processSelectionChange() ) );
00516   connect( mQuickAdd, SIGNAL( returnPressed () ),
00517            SLOT( addQuickTodo() ) );
00518 
00519   new KOTodoListViewToolTip( mTodoListView->viewport(), calendar, mTodoListView );
00520 }
00521 
00522 KOTodoView::~KOTodoView()
00523 {
00524   delete mDocPrefs;
00525 }
00526 
00527 void KOTodoView::setCalendar( Calendar *cal )
00528 {
00529   BaseView::setCalendar( cal );
00530   mTodoListView->setCalendar( cal );
00531 }
00532 
00533 void KOTodoView::updateView()
00534 {
00535 //  kdDebug(5850) << "KOTodoView::updateView()" << endl;
00536   int oldPos = mTodoListView->contentsY();
00537   mItemsToDelete.clear();
00538   mTodoListView->clear();
00539 
00540   Todo::List todoList = calendar()->todos();
00541 
00542 /*
00543   kdDebug(5850) << "KOTodoView::updateView(): Todo List:" << endl;
00544   Event *t;
00545   for(t = todoList.first(); t; t = todoList.next()) {
00546     kdDebug(5850) << "  " << t->getSummary() << endl;
00547 
00548     if (t->getRelatedTo()) {
00549       kdDebug(5850) << "      (related to " << t->getRelatedTo()->getSummary() << ")" << endl;
00550     }
00551 
00552     QPtrList<Event> l = t->getRelations();
00553     Event *c;
00554     for(c=l.first();c;c=l.next()) {
00555       kdDebug(5850) << "    - relation: " << c->getSummary() << endl;
00556     }
00557   }
00558 */
00559 
00560   // Put for each Event a KOTodoViewItem in the list view. Don't rely on a
00561   // specific order of events. That means that we have to generate parent items
00562   // recursively for proper hierarchical display of Todos.
00563   mTodoMap.clear();
00564   Todo::List::ConstIterator it;
00565   for( it = todoList.begin(); it != todoList.end(); ++it ) {
00566     if ( !mTodoMap.contains( *it ) ) {
00567       insertTodoItem( *it );
00568     }
00569   }
00570 
00571   // Restore opened/closed state
00572   mTodoListView->blockSignals( true );
00573   if( mDocPrefs ) restoreItemState( mTodoListView->firstChild() );
00574   mTodoListView->blockSignals( false );
00575 
00576   mTodoListView->setContentsPos( 0, oldPos );
00577 
00578   processSelectionChange();
00579 }
00580 
00581 void KOTodoView::restoreItemState( QListViewItem *item )
00582 {
00583   while( item ) {
00584     KOTodoViewItem *todoItem = (KOTodoViewItem *)item;
00585     todoItem->setOpen( mDocPrefs->readBoolEntry( todoItem->todo()->uid() ) );
00586     if( item->childCount() > 0 ) restoreItemState( item->firstChild() );
00587     item = item->nextSibling();
00588   }
00589 }
00590 
00591 
00592 QMap<Todo *,KOTodoViewItem *>::ConstIterator
00593   KOTodoView::insertTodoItem(Todo *todo)
00594 {
00595 //  kdDebug(5850) << "KOTodoView::insertTodoItem(): " << todo->getSummary() << endl;
00596   Incidence *incidence = todo->relatedTo();
00597   if (incidence && incidence->type() == "Todo") {
00598     // Use dynamic_cast, because in the future the related item might also be an event
00599     Todo *relatedTodo = dynamic_cast<Todo *>(incidence);
00600 
00601     // just make sure we know we have this item already to avoid endless recursion (Bug 101696)
00602     mTodoMap.insert(todo,0);
00603 
00604 //    kdDebug(5850) << "  has Related" << endl;
00605     QMap<Todo *,KOTodoViewItem *>::ConstIterator itemIterator;
00606     itemIterator = mTodoMap.find(relatedTodo);
00607     if (itemIterator == mTodoMap.end()) {
00608 //      kdDebug(5850) << "    related not yet in list" << endl;
00609       itemIterator = insertTodoItem (relatedTodo);
00610     }
00611     // isn't this pretty stupid? We give one Todo  to the KOTodoViewItem
00612     // and one into the map. Sure finding is more easy but why? -zecke
00613     KOTodoViewItem *todoItem;
00614 
00615     // in case we found a related parent, which has no KOTodoViewItem yet, this must
00616     // be the case where 2 items refer to each other, therefore simply create item as root item
00617     if ( *itemIterator == 0 ) {
00618       todo->setRelatedTo(0);  // break the recursion, else we will have troubles later
00619       todoItem = new KOTodoViewItem(mTodoListView,todo,this);
00620     }
00621     else
00622       todoItem = new KOTodoViewItem(*itemIterator,todo,this);
00623 
00624     return mTodoMap.insert(todo,todoItem);
00625   } else {
00626 //    kdDebug(5850) << "  no Related" << endl;
00627       // see above -zecke
00628     KOTodoViewItem *todoItem = new KOTodoViewItem(mTodoListView,todo,this);
00629     return mTodoMap.insert(todo,todoItem);
00630   }
00631 }
00632 
00633 void KOTodoView::removeTodoItems()
00634 {
00635   KOTodoViewItem *item;
00636   for ( item = mItemsToDelete.first(); item; item = mItemsToDelete.next() ) {
00637     Todo *todo = item->todo();
00638     if ( todo && mTodoMap.contains( todo ) ) {
00639       mTodoMap.remove( todo );
00640     }
00641     delete item;
00642   }
00643   mItemsToDelete.clear();
00644 }
00645 
00646 
00647 bool KOTodoView::scheduleRemoveTodoItem( KOTodoViewItem *todoItem )
00648 {
00649   if ( todoItem ) {
00650     mItemsToDelete.append( todoItem );
00651     QTimer::singleShot( 0, this, SLOT( removeTodoItems() ) );
00652     return true;
00653   } else
00654     return false;
00655 }
00656 
00657 void KOTodoView::updateConfig()
00658 {
00659   mTodoListView->repaintContents();
00660 }
00661 
00662 Incidence::List KOTodoView::selectedIncidences()
00663 {
00664   Incidence::List selected;
00665 
00666   KOTodoViewItem *item = (KOTodoViewItem *)(mTodoListView->selectedItem());
00667 //  if (!item) item = mActiveItem;
00668   if (item) selected.append(item->todo());
00669 
00670   return selected;
00671 }
00672 
00673 Todo::List KOTodoView::selectedTodos()
00674 {
00675   Todo::List selected;
00676 
00677   KOTodoViewItem *item = (KOTodoViewItem *)(mTodoListView->selectedItem());
00678 //  if (!item) item = mActiveItem;
00679   if (item) selected.append(item->todo());
00680 
00681   return selected;
00682 }
00683 
00684 void KOTodoView::changeIncidenceDisplay(Incidence *incidence, int action)
00685 {
00686   // The todo view only displays todos, so exit on all other incidences
00687   if ( incidence->type() != "Todo" )
00688     return;
00689   CalFilter *filter = calendar()->filter();
00690   bool isFiltered = filter && !filter->filterIncidence( incidence );
00691   Todo *todo = static_cast<Todo *>(incidence);
00692   if ( todo ) {
00693     KOTodoViewItem *todoItem = 0;
00694     if ( mTodoMap.contains( todo ) ) {
00695       todoItem = mTodoMap[todo];
00696     }
00697     switch ( action ) {
00698       case KOGlobals::INCIDENCEADDED:
00699       case KOGlobals::INCIDENCEEDITED:
00700         // If it's already there, edit it, otherwise just add
00701         if ( todoItem ) {
00702           if ( isFiltered ) {
00703             scheduleRemoveTodoItem( todoItem );
00704           } else {
00705             // correctly update changes in relations
00706             Todo*parent = dynamic_cast<Todo*>( todo->relatedTo() );
00707             KOTodoViewItem*parentItem = 0;
00708             if ( parent && mTodoMap.contains(parent) ) {
00709               parentItem = mTodoMap[ parent ];
00710             }
00711             if ( todoItem->parent() != parentItem ) {
00712               // The relations changed
00713               if ( parentItem ) {
00714                 parentItem->insertItem( todoItem );
00715               } else {
00716                 mTodoListView->insertItem( todoItem );
00717               }
00718             }
00719             todoItem->construct();
00720           }
00721         } else {
00722           if ( !isFiltered ) {
00723             insertTodoItem( todo );
00724           }
00725         }
00726         mTodoListView->sort();
00727         break;
00728       case KOGlobals::INCIDENCEDELETED:
00729         if ( todoItem ) {
00730           scheduleRemoveTodoItem( todoItem );
00731         }
00732         break;
00733       default:
00734         QTimer::singleShot( 0, this, SLOT( updateView() ) );
00735     }
00736   } else {
00737     // use a QTimer here, because when marking todos finished using
00738     // the checkbox, this slot gets called, but we cannot update the views
00739     // because we're still inside KOTodoViewItem::stateChange
00740     QTimer::singleShot(0,this,SLOT(updateView()));
00741   }
00742 }
00743 
00744 void KOTodoView::showDates(const QDate &, const QDate &)
00745 {
00746 }
00747 
00748 void KOTodoView::showIncidences( const Incidence::List &, const QDate & )
00749 {
00750   kdDebug(5850) << "KOTodoView::showIncidences( const Incidence::List & ): not yet implemented" << endl;
00751 }
00752 
00753 CalPrinterBase::PrintType KOTodoView::printType()
00754 {
00755   return CalPrinterBase::Todolist;
00756 }
00757 
00758 void KOTodoView::editItem( QListViewItem *item )
00759 {
00760   if ( item ) {
00761     emit editIncidenceSignal( static_cast<KOTodoViewItem *>( item )->todo(), QDate () );
00762   }
00763 }
00764 
00765 void KOTodoView::editItem( QListViewItem *item, const QPoint &, int )
00766 {
00767   editItem( item );
00768 }
00769 
00770 void KOTodoView::showItem( QListViewItem *item )
00771 {
00772   if ( item ) {
00773     emit showIncidenceSignal( static_cast<KOTodoViewItem *>( item )->todo(), QDate() );
00774   }
00775 }
00776 
00777 void KOTodoView::showItem( QListViewItem *item, const QPoint &, int )
00778 {
00779   showItem( item );
00780 }
00781 
00782 void KOTodoView::popupMenu( QListViewItem *item, const QPoint &, int column )
00783 {
00784   mActiveItem = static_cast<KOTodoViewItem *>( item );
00785   if ( mActiveItem && mActiveItem->todo() &&
00786        !mActiveItem->todo()->isReadOnly() ) {
00787     bool editable = !mActiveItem->todo()->isReadOnly();
00788     mItemPopupMenu->setItemEnabled( ePopupEdit, editable );
00789     mItemPopupMenu->setItemEnabled( ePopupDelete, editable );
00790     mItemPopupMenu->setItemEnabled( ePopupMoveTo, editable );
00791     mItemPopupMenu->setItemEnabled( ePopupCopyTo, editable );
00792     mItemPopupMenu->setItemEnabled( ePopupUnSubTodo, editable );
00793     mItemPopupMenu->setItemEnabled( ePopupUnAllSubTodo, editable );
00794 
00795     if ( editable ) {
00796       QDate date = mActiveItem->todo()->dtDue().date();
00797       if ( mActiveItem->todo()->hasDueDate () ) {
00798         mMovePopupMenu->datePicker()->setDate( date );
00799       } else {
00800         mMovePopupMenu->datePicker()->setDate( QDate::currentDate() );
00801       }
00802       switch ( column ) {
00803         case ePriorityColumn:
00804           mPriorityPopupMenu->popup( QCursor::pos() );
00805           break;
00806         case ePercentColumn: {
00807           mPercentageCompletedPopupMenu->popup( QCursor::pos() );
00808           break;
00809         }
00810         case eDueDateColumn:
00811           mMovePopupMenu->popup( QCursor::pos() );
00812           break;
00813         case eCategoriesColumn:
00814           getCategoryPopupMenu( mActiveItem )->popup( QCursor::pos() );
00815           break;
00816         default:
00817           mCopyPopupMenu->datePicker()->setDate( date );
00818           mCopyPopupMenu->datePicker()->setDate( QDate::currentDate() );
00819           mItemPopupMenu->setItemEnabled( ePopupUnSubTodo,
00820                                           mActiveItem->todo()->relatedTo() );
00821           mItemPopupMenu->setItemEnabled( ePopupUnAllSubTodo,
00822                                           !mActiveItem->todo()->relations().isEmpty() );
00823           mItemPopupMenu->popup( QCursor::pos() );
00824       }
00825     } else {
00826       mItemPopupMenu->popup( QCursor::pos() );
00827     }
00828   } else mPopupMenu->popup( QCursor::pos() );
00829 }
00830 
00831 void KOTodoView::newTodo()
00832 {
00833   QString subResource = QString();
00834   ResourceCalendar * res = NULL;
00835   CalendarResources * calendarRes = dynamic_cast<CalendarResources*>( calendar() );
00836 
00837   kdDebug() << k_funcinfo << endl;
00838   if ( calendarRes ) {
00839     kdDebug(5850) << "Searching if resource / subresource is distinct for saving to CalendarResources" << endl;
00840     QPtrList<KRES::Resource> list;
00841     CalendarResourceManager::ActiveIterator it;
00842 
00843     // Same code as used for finding out the destination resource
00844     for ( it = calendarRes->resourceManager()->activeBegin();
00845           it != calendarRes->resourceManager()->activeEnd(); ++it ) {
00846       if ( !(*it)->readOnly() ) {
00847         //Insert the first the Standard resource to get be the default selected.
00848         if ( calendarRes->resourceManager()->standardResource() == *it )
00849           list.insert( 0, *it );
00850         else
00851           list.append( *it );
00852       }
00853     }
00854     if ( list.count() != 1 ) {
00855       kdDebug(5850) << "No distinct Tasks resource found" << endl;
00856     } else {
00857       res = static_cast<ResourceCalendar *> (list.first());
00858       CalendarResourceManager::ActiveIterator it;
00859       QStringList candidates;
00860       QStringList subresources = res->subresources();
00861 
00862       kdDebug(5850) << "Opening editor for new " << res->resourceName() << endl;
00863       for ( QStringList::Iterator subit = subresources.begin();
00864             subit != subresources.end(); ++subit ) {
00865         if ( res->subresourceType( *subit ) == "todo" &&
00866              res->subresourceWritable( *subit ) &&
00867              res->subresourceActive( *subit ) ) {
00868           candidates << *subit;
00869         }
00870       }
00871       if ( candidates.count() == 1 ) {
00872         // User has one Calendar and one active todo resource, we know where the
00873         // new ToDo should be created
00874         subResource = candidates.first();
00875         kdDebug(5850) << "Found distinct subresource: " << subResource << endl;
00876       } else {
00877         kdDebug(5850) << "Did not find a distinct subresource " << endl;
00878       }
00879     }
00880   }
00881   emit newTodoSignal( res, subResource, QDate::currentDate().addDays(7) );
00882 }
00883 
00884 void KOTodoView::newSubTodo()
00885 {
00886   if (mActiveItem) {
00887     emit newSubTodoSignal(mActiveItem->todo());
00888   }
00889 }
00890 
00891 void KOTodoView::editTodo()
00892 {
00893   editItem( mActiveItem );
00894 }
00895 
00896 void KOTodoView::showTodo()
00897 {
00898   showItem( mActiveItem );
00899 }
00900 
00901 void KOTodoView::printTodo()
00902 {
00903 #ifndef KORG_NOPRINTER
00904   KOCoreHelper helper;
00905   CalPrinter printer( this, BaseView::calendar(), &helper );
00906   connect( this, SIGNAL(configChanged()), &printer, SLOT(updateConfig()) );
00907 
00908   Incidence::List selectedIncidences;
00909   selectedIncidences.append( mActiveItem->todo() );
00910 
00911   QDateTime todoDate;
00912   if ( mActiveItem->todo() && mActiveItem->todo()->hasStartDate() ) {
00913     todoDate = mActiveItem->todo()->dtStart();
00914   } else {
00915     todoDate = mActiveItem->todo()->dtDue();
00916   }
00917 
00918   printer.print( KOrg::CalPrinterBase::Incidence,
00919                  todoDate.date(), todoDate.date(), selectedIncidences );
00920 #endif
00921 }
00922 
00923 void KOTodoView::deleteTodo()
00924 {
00925   if (mActiveItem) {
00926     emit deleteIncidenceSignal( mActiveItem->todo() );
00927   }
00928 }
00929 
00930 void KOTodoView::setNewPriority(int index)
00931 {
00932   if ( !mActiveItem || !mChanger ) return;
00933   Todo *todo = mActiveItem->todo();
00934   if ( !todo->isReadOnly () &&
00935        mChanger->beginChange( todo, 0, QString() ) ) {
00936     Todo *oldTodo = todo->clone();
00937     todo->setPriority(mPriority[index]);
00938     mActiveItem->construct();
00939 
00940     mChanger->changeIncidence( oldTodo, todo, KOGlobals::PRIORITY_MODIFIED, this );
00941     mChanger->endChange( todo, 0, QString() );
00942     delete oldTodo;
00943   }
00944 }
00945 
00946 void KOTodoView::setNewPercentage( KOTodoViewItem *item, int percentage )
00947 {
00948   kdDebug(5850) << "KOTodoView::setNewPercentage( " << percentage << "), item = " << item << endl;
00949   if ( !item || !mChanger  ) return;
00950   Todo *todo = item->todo();
00951   if ( !todo ) return;
00952 
00953   if ( !todo->isReadOnly () &&
00954        mChanger->beginChange( todo, 0, QString() ) ) {
00955     Todo *oldTodo = todo->clone();
00956 
00957 /*  Old code to make sub-items's percentage related to this one's:
00958     QListViewItem *myChild = firstChild();
00959     KOTodoViewItem *item;
00960     while( myChild ) {
00961       item = static_cast<KOTodoViewItem*>(myChild);
00962       item->stateChange(state);
00963       myChild = myChild->nextSibling();
00964     }*/
00965     if ( percentage == 100 ) {
00966       todo->setCompleted( QDateTime::currentDateTime() );
00967       // If the todo does recur, it doesn't get set as completed. However, the
00968       // item is still checked. Uncheck it again.
00969       if ( !todo->isCompleted() ) {
00970         item->setState( QCheckListItem::Off );
00971       }
00972     } else {
00973       todo->setPercentComplete( percentage );
00974     }
00975     item->construct();
00976     if ( todo->doesRecur() && percentage == 100 )
00977       mChanger->changeIncidence( oldTodo, todo,
00978                                  KOGlobals::COMPLETION_MODIFIED_WITH_RECURRENCE, this );
00979     else
00980       mChanger->changeIncidence( oldTodo, todo,
00981                                  KOGlobals::COMPLETION_MODIFIED, this );
00982     mChanger->endChange( todo, 0, QString() );
00983     delete oldTodo;
00984   } else {
00985     item->construct();
00986     kdDebug(5850) << "No active item, active item is read-only, or locking failed" << endl;
00987   }
00988 }
00989 
00990 void KOTodoView::setNewPercentage( int index )
00991 {
00992   setNewPercentage( mActiveItem, mPercentage[index] );
00993 }
00994 
00995 void KOTodoView::setNewDate( QDate date )
00996 {
00997   if ( !mActiveItem || !mChanger ) return;
00998   Todo *todo = mActiveItem->todo();
00999   if ( !todo ) return;
01000 
01001   if ( !todo->isReadOnly() && mChanger->beginChange( todo, 0, QString() ) ) {
01002     Todo *oldTodo = todo->clone();
01003 
01004     QDateTime dt;
01005     dt.setDate( date );
01006 
01007     if ( !todo->doesFloat() ) {
01008       dt.setTime( todo->dtDue().time() );
01009     }
01010 
01011     todo->setHasDueDate( !date.isNull() );
01012     todo->setDtDue( dt );
01013 
01014     mActiveItem->construct();
01015     mChanger->changeIncidence( oldTodo, todo, KOGlobals::COMPLETION_MODIFIED, this );
01016     mChanger->endChange( todo, 0, QString() );
01017     delete oldTodo;
01018   } else {
01019     kdDebug(5850) << "No active item, active item is read-only, or locking failed" << endl;
01020   }
01021 }
01022 
01023 void KOTodoView::copyTodoToDate( QDate date )
01024 {
01025   QDateTime dt( date );
01026 
01027   if ( mActiveItem && mChanger ) {
01028     Todo *oldTodo = mActiveItem->todo();
01029     Todo *newTodo = oldTodo->clone();
01030     newTodo->recreate();
01031 
01032     newTodo->setHasDueDate( !date.isNull() );
01033 
01034     if ( oldTodo->hasDueDate() && !oldTodo->doesFloat() ) {
01035       dt.setTime( oldTodo->dtDue().time() );
01036     }
01037 
01038     newTodo->setDtDue( dt );
01039     newTodo->setPercentComplete( 0 );
01040 
01041     QPair<ResourceCalendar *, QString>p =
01042       CalHelper::incSubResourceCalendar( calendar(), mActiveItem->todo() );
01043 
01044     mChanger->addIncidence( newTodo, p.first, p.second, this );
01045   }
01046 }
01047 
01048 QPopupMenu *KOTodoView::getCategoryPopupMenu( KOTodoViewItem *todoItem )
01049 {
01050   QPopupMenu *tempMenu = new QPopupMenu( this );
01051   QStringList checkedCategories = todoItem->todo()->categories();
01052 
01053   tempMenu->setCheckable( true );
01054   QStringList::Iterator it;
01055   for ( it = KOPrefs::instance()->mCustomCategories.begin();
01056         it != KOPrefs::instance()->mCustomCategories.end();
01057         ++it ) {
01058     int index = tempMenu->insertItem( *it );
01059     mCategory[ index ] = *it;
01060     if ( checkedCategories.find( *it ) != checkedCategories.end() )
01061       tempMenu->setItemChecked( index, true );
01062   }
01063 
01064   connect ( tempMenu, SIGNAL( activated( int ) ),
01065             SLOT( changedCategories( int ) ) );
01066   return tempMenu;
01067 }
01068 
01069 void KOTodoView::changedCategories(int index)
01070 {
01071   if ( !mActiveItem || !mChanger ) return;
01072   Todo *todo = mActiveItem->todo();
01073   if ( !todo ) return;
01074 
01075   if ( !todo->isReadOnly() && mChanger->beginChange( todo, 0, QString() ) ) {
01076     Todo *oldTodo = todo->clone();
01077 
01078     QStringList categories = todo->categories ();
01079     if ( categories.find( mCategory[index] ) != categories.end() )
01080       categories.remove( mCategory[index] );
01081     else
01082       categories.insert( categories.end(), mCategory[index] );
01083     categories.sort();
01084     todo->setCategories( categories );
01085     mActiveItem->construct();
01086     mChanger->changeIncidence( oldTodo, todo, KOGlobals::CATEGORY_MODIFIED, this );
01087     mChanger->endChange( todo, 0, QString() );
01088     delete oldTodo;
01089   } else {
01090     kdDebug(5850) << "No active item, active item is read-only, or locking failed" << endl;
01091   }
01092 }
01093 
01094 void KOTodoView::setDocumentId( const QString &id )
01095 {
01096   kdDebug(5850) << "KOTodoView::setDocumentId()" << endl;
01097 
01098   mDocPrefs->setDoc( id );
01099 }
01100 
01101 void KOTodoView::itemStateChanged( QListViewItem *item )
01102 {
01103   if (!item) return;
01104 
01105   KOTodoViewItem *todoItem = (KOTodoViewItem *)item;
01106 
01107 //  kdDebug(5850) << "KOTodoView::itemStateChanged(): " << todoItem->todo()->summary() << endl;
01108 
01109   if( mDocPrefs ) mDocPrefs->writeEntry( todoItem->todo()->uid(), todoItem->isOpen() );
01110 }
01111 
01112 void KOTodoView::setNewPercentageDelayed( KOTodoViewItem *item, int percentage )
01113 {
01114   mPercentChangedMap.append( qMakePair( item, percentage ) );
01115 
01116   QTimer::singleShot( 0, this, SLOT( processDelayedNewPercentage() ) );
01117 }
01118 
01119 void KOTodoView::processDelayedNewPercentage()
01120 {
01121   QValueList< QPair< KOTodoViewItem *, int> >::Iterator it;
01122   for ( it = mPercentChangedMap.begin(); it != mPercentChangedMap.end(); ++it )
01123     setNewPercentage( (*it).first, (*it).second );
01124 
01125   mPercentChangedMap.clear();
01126 }
01127 
01128 void KOTodoView::saveLayout(KConfig *config, const QString &group) const
01129 {
01130   mTodoListView->saveLayout(config,group);
01131 }
01132 
01133 void KOTodoView::restoreLayout(KConfig *config, const QString &group)
01134 {
01135   mTodoListView->restoreLayout(config,group);
01136 }
01137 
01138 void KOTodoView::processSelectionChange()
01139 {
01140 //  kdDebug(5850) << "KOTodoView::processSelectionChange()" << endl;
01141 
01142   KOTodoViewItem *item =
01143     static_cast<KOTodoViewItem *>( mTodoListView->selectedItem() );
01144 
01145   if ( !item ) {
01146     emit incidenceSelected( 0, QDate() );
01147   } else {
01148     if ( selectedIncidenceDates().isEmpty() ) {
01149       emit incidenceSelected( item->todo(), QDate() );
01150     } else {
01151       emit incidenceSelected( item->todo(), selectedIncidenceDates().first() );
01152     }
01153   }
01154 }
01155 
01156 void KOTodoView::clearSelection()
01157 {
01158   mTodoListView->selectAll( false );
01159 }
01160 
01161 void KOTodoView::purgeCompleted()
01162 {
01163   emit purgeCompletedSignal();
01164 }
01165 
01166 void KOTodoView::addQuickTodo()
01167 {
01168   if ( ! mQuickAdd->text().stripWhiteSpace().isEmpty() ) {
01169     Todo *todo = new Todo();
01170     todo->setSummary( mQuickAdd->text() );
01171     todo->setOrganizer( Person( KOPrefs::instance()->fullName(),
01172                         KOPrefs::instance()->email() ) );
01173     if ( !mChanger->addIncidence( todo, 0, QString(), this ) ) {
01174       delete todo;
01175       return;
01176     }
01177     mQuickAdd->setText( QString::null );
01178   }
01179 }
01180 
01181 void KOTodoView::setIncidenceChanger( IncidenceChangerBase *changer )
01182 {
01183   mChanger = changer;
01184   mTodoListView->setIncidenceChanger( changer );
01185 }
KDE Home | KDE Accessibility Home | Description of Access Keys