korganizer Library API Documentation

kotodoview.cpp

00001 /* 00002 This file is part of KOrganizer. 00003 00004 Copyright (c) 2000,2001,2003 Cornelius Schumacher <schumacher@kde.org> 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00019 00020 As a special exception, permission is given to link this program 00021 with any edition of Qt, and distribute the resulting executable, 00022 without including the source code for Qt in the source distribution. 00023 */ 00024 00025 #include <qlayout.h> 00026 #include <qheader.h> 00027 #include <qcursor.h> 00028 #include <qlabel.h> 00029 #include <qtimer.h> 00030 00031 #include <kdebug.h> 00032 #include <klocale.h> 00033 #include <kglobal.h> 00034 #include <kiconloader.h> 00035 #include <kmessagebox.h> 00036 00037 #include <libkcal/icaldrag.h> 00038 #include <libkcal/vcaldrag.h> 00039 #include <libkcal/dndfactory.h> 00040 #include <libkcal/calendarresources.h> 00041 #include <libkcal/resourcecalendar.h> 00042 #include <libkcal/calfilter.h> 00043 00044 #include <libkdepim/clicklineedit.h> 00045 #include <libkdepim/kdatepickerpopup.h> 00046 00047 #ifndef KORG_NOPRINTER 00048 #include "calprinter.h" 00049 #endif 00050 #include "docprefs.h" 00051 00052 #include "koincidencetooltip.h" 00053 #include "kodialogmanager.h" 00054 #include "kotodoview.h" 00055 #include "koprefs.h" 00056 #include "koglobals.h" 00057 using namespace KOrg; 00058 #include "kotodoviewitem.h" 00059 #include "kotodoview.moc" 00060 00061 const int KOTodoView::POPUP_UNSUBTODO=1234; 00062 00063 KOTodoListViewToolTip::KOTodoListViewToolTip (QWidget* parent, 00064 KOTodoListView* lv ) 00065 :QToolTip(parent) 00066 { 00067 todolist=lv; 00068 } 00069 00070 void KOTodoListViewToolTip::maybeTip( const QPoint & pos) 00071 { 00072 QRect r; 00073 int headerPos; 00074 int col=todolist->header()->sectionAt(todolist->contentsX() + pos.x()); 00075 KOTodoViewItem *i=(KOTodoViewItem *)todolist->itemAt(pos); 00076 00077 /* Check wether a tooltip is necessary. */ 00078 if( i && KOPrefs::instance()->mEnableToolTips ) 00079 { 00080 00081 /* Calculate the rectangle. */ 00082 r=todolist->itemRect(i); 00083 headerPos = todolist->header()->sectionPos(col)-todolist->contentsX(); 00084 r.setLeft( (headerPos < 0 ? 0 : headerPos) ); 00085 r.setRight(headerPos + todolist->header()->sectionSize(col)); 00086 00087 /* Show the tip */ 00088 QString tipText; 00089 ToolTipVisitor v; 00090 if (v.act(i->todo(), &tipText, true)) { 00091 tip(r, tipText); 00092 } 00093 } 00094 00095 } 00096 00097 00098 00099 KOTodoListView::KOTodoListView( QWidget *parent, const char *name ) 00100 : KListView( parent, name ), mCalendar( 0 ) 00101 { 00102 mOldCurrent = 0; 00103 mMousePressed = false; 00104 00105 /* Create a Tooltip */ 00106 tooltip = new KOTodoListViewToolTip( viewport(), this ); 00107 } 00108 00109 KOTodoListView::~KOTodoListView() 00110 { 00111 delete tooltip; 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 00161 void KOTodoListView::contentsDragMoveEvent(QDragMoveEvent *e) 00162 { 00163 #ifndef KORG_NODND 00164 // kdDebug(5850) << "KOTodoListView::contentsDragMoveEvent" << endl; 00165 00166 if ( !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) && 00167 !QTextDrag::canDecode( e ) ) { 00168 e->ignore(); 00169 return; 00170 } 00171 00172 e->accept(); 00173 #endif 00174 } 00175 00176 void KOTodoListView::contentsDragLeaveEvent( QDragLeaveEvent * ) 00177 { 00178 #ifndef KORG_NODND 00179 // kdDebug(5850) << "KOTodoListView::contentsDragLeaveEvent" << endl; 00180 00181 setCurrentItem(mOldCurrent); 00182 setSelected(mOldCurrent,true); 00183 #endif 00184 } 00185 00186 void KOTodoListView::contentsDropEvent( QDropEvent *e ) 00187 { 00188 #ifndef KORG_NODND 00189 // kdDebug(5850) << "KOTodoListView::contentsDropEvent" << endl; 00190 00191 if ( !mCalendar || 00192 ( !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) && 00193 !QTextDrag::canDecode( e ) ) ) { 00194 e->ignore(); 00195 return; 00196 } 00197 00198 DndFactory factory( mCalendar ); 00199 Todo *todo = factory.createDropTodo(e); 00200 00201 if (todo) { 00202 e->acceptAction(); 00203 00204 KOTodoViewItem *destination = 00205 (KOTodoViewItem *)itemAt(contentsToViewport(e->pos())); 00206 Todo *destinationEvent = 0; 00207 if (destination) destinationEvent = destination->todo(); 00208 00209 Todo *existingTodo = mCalendar->todo(todo->uid()); 00210 00211 if(existingTodo) { 00212 // kdDebug(5850) << "Drop existing Todo " << existingTodo << " onto " << destinationEvent << endl; 00213 Incidence *to = destinationEvent; 00214 while(to) { 00215 if (to->uid() == todo->uid()) { 00216 KMessageBox::sorry(this, 00217 i18n("Cannot move To-Do to itself or a child of itself."), 00218 i18n("Drop To-Do")); 00219 delete todo; 00220 return; 00221 } 00222 to = to->relatedTo(); 00223 } 00224 Todo*oldTodo = existingTodo->clone(); 00225 existingTodo->setRelatedTo(destinationEvent); 00226 00227 emit incidenceChanged( oldTodo, existingTodo ); 00228 delete oldTodo; 00229 delete todo; 00230 } else { 00231 // kdDebug(5850) << "Drop new Todo" << endl; 00232 todo->setRelatedTo(destinationEvent); 00233 if ( !mCalendar->addTodo( todo ) ) { 00234 KODialogManager::errorSaveTodo( this ); 00235 return; 00236 } 00237 00238 emit incidenceAdded( todo ); 00239 } 00240 } 00241 else { 00242 QString text; 00243 KOTodoViewItem *todoi = dynamic_cast<KOTodoViewItem *>(itemAt( contentsToViewport(e->pos()) )); 00244 if ( ! todoi ) { 00245 // Not dropped on a todo item: 00246 e->ignore(); 00247 kdDebug( 5850 ) << "KOTodoListView::contentsDropEvent(): Not dropped on a todo item" << endl; 00248 kdDebug( 5850 ) << "TODO: Create a new todo with the given data" << endl; 00249 // TODO: Create a new todo with the given text/contact/whatever 00250 } else if ( QTextDrag::decode(e, text) ) { 00251 //QListViewItem *qlvi = itemAt( contentsToViewport(e->pos()) ); 00252 kdDebug(5850) << "Dropped : " << text << endl; 00253 QStringList emails = QStringList::split(",",text); 00254 Todo*newtodo = todoi->todo(); 00255 Todo*oldtodo = newtodo->clone(); 00256 for(QStringList::ConstIterator it = emails.begin();it!=emails.end();++it) { 00257 kdDebug(5850) << " Email: " << (*it) << endl; 00258 int pos = (*it).find("<"); 00259 QString name = (*it).left(pos); 00260 QString email = (*it).mid(pos); 00261 if (!email.isEmpty() && todoi) { 00262 newtodo->addAttendee(new Attendee(name,email)); 00263 } 00264 } 00265 emit incidenceChanged( oldtodo, newtodo ); 00266 } 00267 else { 00268 kdDebug(5850) << "KOTodoListView::contentsDropEvent(): Todo from drop not decodable" << endl; 00269 e->ignore(); 00270 } 00271 } 00272 #endif 00273 } 00274 00275 void KOTodoListView::contentsMousePressEvent(QMouseEvent* e) 00276 { 00277 QListView::contentsMousePressEvent(e); 00278 QPoint p(contentsToViewport(e->pos())); 00279 QListViewItem *i = itemAt(p); 00280 if (i) { 00281 // if the user clicked into the root decoration of the item, don't 00282 // try to start a drag! 00283 if (p.x() > header()->sectionPos(header()->mapToIndex(0)) + 00284 treeStepSize() * (i->depth() + (rootIsDecorated() ? 1 : 0)) + 00285 itemMargin() || 00286 p.x() < header()->sectionPos(header()->mapToIndex(0))) { 00287 if (e->button()==Qt::LeftButton) { 00288 mPressPos = e->pos(); 00289 mMousePressed = true; 00290 } 00291 } 00292 } 00293 } 00294 00295 void KOTodoListView::contentsMouseMoveEvent(QMouseEvent* e) 00296 { 00297 #ifndef KORG_NODND 00298 // kdDebug(5850) << "KOTodoListView::contentsMouseMoveEvent()" << endl; 00299 QListView::contentsMouseMoveEvent(e); 00300 if (mMousePressed && (mPressPos - e->pos()).manhattanLength() > 00301 QApplication::startDragDistance()) { 00302 mMousePressed = false; 00303 QListViewItem *item = itemAt(contentsToViewport(mPressPos)); 00304 if ( item && mCalendar ) { 00305 // kdDebug(5850) << "Start Drag for item " << item->text(0) << endl; 00306 DndFactory factory( mCalendar ); 00307 ICalDrag *vd = factory.createDrag( 00308 ((KOTodoViewItem *)item)->todo(),viewport()); 00309 if (vd->drag()) { 00310 kdDebug(5850) << "KOTodoListView::contentsMouseMoveEvent(): Delete drag source" << endl; 00311 } 00312 /* 00313 QString source = fullPath(item); 00314 if ( QFile::exists(source) ) { 00315 KURL url; 00316 url.setPath(source); 00317 KURLDrag* ud = KURLDrag::newDrag(KURL::List(url), viewport()); 00318 if ( ud->drag() ) 00319 QMessageBox::information( this, "Drag source", 00320 QString("Delete ")+source, "Not implemented" ); 00321 */ 00322 } 00323 } 00324 #endif 00325 } 00326 00327 void KOTodoListView::contentsMouseReleaseEvent(QMouseEvent *e) 00328 { 00329 QListView::contentsMouseReleaseEvent(e); 00330 mMousePressed = false; 00331 } 00332 00333 void KOTodoListView::contentsMouseDoubleClickEvent(QMouseEvent *e) 00334 { 00335 if (!e) return; 00336 00337 QPoint vp = contentsToViewport(e->pos()); 00338 00339 QListViewItem *item = itemAt(vp); 00340 00341 if (!item) return; 00342 00343 emit doubleClicked(item,vp,0); 00344 } 00345 00347 00348 KOTodoView::KOTodoView( Calendar *calendar, QWidget *parent, const char* name) 00349 : KOrg::BaseView( calendar, parent, name ) 00350 { 00351 QBoxLayout *topLayout = new QVBoxLayout( this ); 00352 00353 QLabel *title = new QLabel( i18n("To-do items:"), this ); 00354 title->setFrameStyle( QFrame::Panel | QFrame::Raised ); 00355 topLayout->addWidget( title ); 00356 00357 mQuickAdd = new KPIM::ClickLineEdit( this, i18n( "Click to add a new Todo" ) ); 00358 topLayout->addWidget( mQuickAdd ); 00359 00360 if ( !KOPrefs::instance()->mEnableQuickTodo ) mQuickAdd->hide(); 00361 00362 mTodoListView = new KOTodoListView( this ); 00363 topLayout->addWidget( mTodoListView ); 00364 00365 mTodoListView->setRootIsDecorated( true ); 00366 mTodoListView->setAllColumnsShowFocus( true ); 00367 00368 mTodoListView->setShowSortIndicator( true ); 00369 00370 mTodoListView->addColumn( i18n("Summary") ); 00371 mTodoListView->addColumn( i18n("Recurs") ); 00372 mTodoListView->addColumn( i18n("Priority") ); 00373 mTodoListView->setColumnAlignment( 2, AlignHCenter ); 00374 mTodoListView->addColumn( i18n("Complete") ); 00375 mTodoListView->setColumnAlignment( 3, AlignRight ); 00376 mTodoListView->addColumn( i18n("Due Date/Time") ); 00377 mTodoListView->setColumnAlignment( 4, AlignLeft ); 00378 mTodoListView->addColumn( i18n("Categories") ); 00379 #if 0 00380 mTodoListView->addColumn( i18n("Sort Id") ); 00381 mTodoListView->setColumnAlignment( 4, AlignHCenter ); 00382 #endif 00383 00384 mTodoListView->setMinimumHeight( 60 ); 00385 mTodoListView->setItemsRenameable( true ); 00386 mTodoListView->setRenameable( 0 ); 00387 00388 mTodoListView->setColumnWidthMode( 0, QListView::Manual ); 00389 mTodoListView->setColumnWidthMode( 1, QListView::Manual ); 00390 mTodoListView->setColumnWidthMode( 2, QListView::Manual ); 00391 mTodoListView->setColumnWidthMode( 3, QListView::Manual ); 00392 mTodoListView->setColumnWidthMode( 4, QListView::Manual ); 00393 mTodoListView->setColumnWidthMode( 5, QListView::Manual ); 00394 #if 0 00395 mTodoListView->setColumnWidthMode( 6, QListView::Manual ); 00396 #endif 00397 00398 mPriorityPopupMenu = new QPopupMenu( this ); 00399 for ( int i = 1; i <= 5; i++ ) { 00400 QString label = QString ("%1").arg( i ); 00401 mPriority[ mPriorityPopupMenu->insertItem( label ) ] = i; 00402 } 00403 connect( mPriorityPopupMenu, SIGNAL( activated( int ) ), 00404 SLOT( setNewPriority( int ) )); 00405 00406 mPercentageCompletedPopupMenu = new QPopupMenu(this); 00407 for (int i = 0; i <= 100; i+=10) { 00408 QString label = QString ("%1 %").arg (i); 00409 mPercentage[mPercentageCompletedPopupMenu->insertItem (label)] = i; 00410 } 00411 connect( mPercentageCompletedPopupMenu, SIGNAL( activated( int ) ), 00412 SLOT( setNewPercentage( int ) ) ); 00413 00414 mMovePopupMenu = new KDatePickerPopup( 00415 KDatePickerPopup::NoDate | 00416 KDatePickerPopup::DatePicker | 00417 KDatePickerPopup::Words ); 00418 mCopyPopupMenu = new KDatePickerPopup( 00419 KDatePickerPopup::NoDate | 00420 KDatePickerPopup::DatePicker | 00421 KDatePickerPopup::Words ); 00422 00423 00424 connect( mMovePopupMenu, SIGNAL( dateChanged( QDate )), 00425 SLOT( setNewDate( QDate ) ) ); 00426 connect( mCopyPopupMenu, SIGNAL( dateChanged( QDate )), 00427 SLOT( copyTodoToDate( QDate ) ) ); 00428 00429 mItemPopupMenu = new QPopupMenu(this); 00430 mItemPopupMenu->insertItem(i18n("Show"), this, 00431 SLOT (showTodo())); 00432 mItemPopupMenu->insertItem(i18n("Edit..."), this, 00433 SLOT (editTodo())); 00434 mItemPopupMenu->insertItem(KOGlobals::self()->smallIconSet("editdelete"), i18n("Delete"), this, 00435 SLOT (deleteTodo())); 00436 mItemPopupMenu->insertSeparator(); 00437 mItemPopupMenu->insertItem(KOGlobals::self()->smallIconSet("todo"), i18n("New To-Do..."), this, 00438 SLOT (newTodo())); 00439 mItemPopupMenu->insertItem(i18n("New Sub-To-Do..."), this, 00440 SLOT (newSubTodo())); 00441 mItemPopupMenu->insertItem( i18n("Make Sub-To-Do Independent"), this, 00442 SIGNAL( unSubTodoSignal() ), 0, POPUP_UNSUBTODO ); 00443 mItemPopupMenu->insertSeparator(); 00444 mItemPopupMenu->insertItem( i18n("Copy To"), mCopyPopupMenu ); 00445 mItemPopupMenu->insertItem(i18n("Move To"), mMovePopupMenu); 00446 mItemPopupMenu->insertSeparator(); 00447 mItemPopupMenu->insertItem(i18n("delete completed To-Dos","Purge Completed"), 00448 this, SLOT( purgeCompleted() ) ); 00449 00450 connect( mMovePopupMenu, SIGNAL( dateChanged( QDate ) ), 00451 mItemPopupMenu, SLOT( hide() ) ); 00452 connect( mCopyPopupMenu, SIGNAL( dateChanged( QDate ) ), 00453 mItemPopupMenu, SLOT( hide() ) ); 00454 00455 mPopupMenu = new QPopupMenu(this); 00456 mPopupMenu->insertItem(KOGlobals::self()->smallIconSet("todo"), i18n("New To-Do..."), this, 00457 SLOT (newTodo())); 00458 mPopupMenu->insertItem(i18n("delete completed To-Dos","Purge Completed"), 00459 this, SLOT(purgeCompleted())); 00460 00461 mDocPrefs = new DocPrefs( name ); 00462 00463 // Double clicking conflicts with opening/closing the subtree 00464 connect( mTodoListView, SIGNAL( doubleClicked( QListViewItem *, 00465 const QPoint &, int ) ), 00466 SLOT( editItem( QListViewItem *, const QPoint &, int ) ) ); 00467 connect( mTodoListView, SIGNAL( returnPressed( QListViewItem * ) ), 00468 SLOT( editItem( QListViewItem * ) ) ); 00469 connect( mTodoListView, SIGNAL( contextMenuRequested( QListViewItem *, 00470 const QPoint &, int ) ), 00471 SLOT( popupMenu( QListViewItem *, const QPoint &, int ) ) ); 00472 connect( mTodoListView, SIGNAL( expanded( QListViewItem * ) ), 00473 SLOT( itemStateChanged( QListViewItem * ) ) ); 00474 connect( mTodoListView, SIGNAL( collapsed( QListViewItem * ) ), 00475 SLOT( itemStateChanged( QListViewItem * ) ) ); 00476 00477 #if 0 00478 connect(mTodoListView,SIGNAL(selectionChanged(QListViewItem *)), 00479 SLOT(selectionChanged(QListViewItem *))); 00480 connect(mTodoListView,SIGNAL(clicked(QListViewItem *)), 00481 SLOT(selectionChanged(QListViewItem *))); 00482 connect(mTodoListView,SIGNAL(pressed(QListViewItem *)), 00483 SLOT(selectionChanged(QListViewItem *))); 00484 #endif 00485 connect( mTodoListView, SIGNAL(selectionChanged() ), 00486 SLOT( processSelectionChange() ) ); 00487 connect( mQuickAdd, SIGNAL( returnPressed () ), 00488 SLOT( addQuickTodo() ) ); 00489 00490 connect( mTodoListView, SIGNAL( incidenceAdded( Incidence* ) ), 00491 SIGNAL( incidenceAdded( Incidence* ) ) ); 00492 connect( mTodoListView, SIGNAL( incidenceChanged( Incidence*, Incidence* ) ), 00493 SIGNAL( incidenceChanged( Incidence*, Incidence* ) ) ); 00494 connect( mTodoListView, SIGNAL( incidenceToBeDeleted( Incidence* ) ), 00495 SIGNAL( incidenceToBeDeleted( Incidence* ) ) ); 00496 connect( mTodoListView, SIGNAL( incidenceDeleted( Incidence* ) ), 00497 SIGNAL( incidenceDeleted( Incidence* ) ) ); 00498 } 00499 00500 KOTodoView::~KOTodoView() 00501 { 00502 delete mDocPrefs; 00503 } 00504 00505 void KOTodoView::setCalendar( Calendar *cal ) 00506 { 00507 BaseView::setCalendar( cal ); 00508 mTodoListView->setCalendar( cal ); 00509 } 00510 00511 void KOTodoView::updateView() 00512 { 00513 // kdDebug(5850) << "KOTodoView::updateView()" << endl; 00514 int oldPos = mTodoListView->contentsY(); 00515 mItemsToDelete.clear(); 00516 mTodoListView->clear(); 00517 00518 Todo::List todoList = calendar()->todos(); 00519 00520 /* 00521 kdDebug(5850) << "KOTodoView::updateView(): Todo List:" << endl; 00522 Event *t; 00523 for(t = todoList.first(); t; t = todoList.next()) { 00524 kdDebug(5850) << " " << t->getSummary() << endl; 00525 00526 if (t->getRelatedTo()) { 00527 kdDebug(5850) << " (related to " << t->getRelatedTo()->getSummary() << ")" << endl; 00528 } 00529 00530 QPtrList<Event> l = t->getRelations(); 00531 Event *c; 00532 for(c=l.first();c;c=l.next()) { 00533 kdDebug(5850) << " - relation: " << c->getSummary() << endl; 00534 } 00535 } 00536 */ 00537 00538 // Put for each Event a KOTodoViewItem in the list view. Don't rely on a 00539 // specific order of events. That means that we have to generate parent items 00540 // recursively for proper hierarchical display of Todos. 00541 mTodoMap.clear(); 00542 Todo::List::ConstIterator it; 00543 for( it = todoList.begin(); it != todoList.end(); ++it ) { 00544 if ( !mTodoMap.contains( *it ) ) { 00545 insertTodoItem( *it ); 00546 } 00547 } 00548 00549 // Restore opened/closed state 00550 mTodoListView->blockSignals( true ); 00551 if( mDocPrefs ) restoreItemState( mTodoListView->firstChild() ); 00552 mTodoListView->blockSignals( false ); 00553 00554 mTodoListView->setContentsPos( 0, oldPos ); 00555 00556 processSelectionChange(); 00557 } 00558 00559 void KOTodoView::restoreItemState( QListViewItem *item ) 00560 { 00561 while( item ) { 00562 KOTodoViewItem *todoItem = (KOTodoViewItem *)item; 00563 todoItem->setOpen( mDocPrefs->readBoolEntry( todoItem->todo()->uid() ) ); 00564 if( item->childCount() > 0 ) restoreItemState( item->firstChild() ); 00565 item = item->nextSibling(); 00566 } 00567 } 00568 00569 00570 QMap<Todo *,KOTodoViewItem *>::ConstIterator 00571 KOTodoView::insertTodoItem(Todo *todo) 00572 { 00573 // kdDebug(5850) << "KOTodoView::insertTodoItem(): " << todo->getSummary() << endl; 00574 Incidence *incidence = todo->relatedTo(); 00575 if (incidence && incidence->type() == "Todo") { 00576 // Use dynamic_cast, because in the future the related item might also be an event 00577 Todo *relatedTodo = dynamic_cast<Todo *>(incidence); 00578 00579 // kdDebug(5850) << " has Related" << endl; 00580 QMap<Todo *,KOTodoViewItem *>::ConstIterator itemIterator; 00581 itemIterator = mTodoMap.find(relatedTodo); 00582 if (itemIterator == mTodoMap.end()) { 00583 // kdDebug(5850) << " related not yet in list" << endl; 00584 itemIterator = insertTodoItem (relatedTodo); 00585 } 00586 // isn't this pretty stupid? We give one Todo to the KOTodoViewItem 00587 // and one into the map. Sure finding is more easy but why? -zecke 00588 KOTodoViewItem *todoItem = new KOTodoViewItem(*itemIterator,todo,this); 00589 return mTodoMap.insert(todo,todoItem); 00590 } else { 00591 // kdDebug(5850) << " no Related" << endl; 00592 // see above -zecke 00593 KOTodoViewItem *todoItem = new KOTodoViewItem(mTodoListView,todo,this); 00594 return mTodoMap.insert(todo,todoItem); 00595 } 00596 } 00597 00598 void KOTodoView::removeTodoItems() 00599 { 00600 KOTodoViewItem *item; 00601 for ( item = mItemsToDelete.first(); item; item = mItemsToDelete.next() ) { 00602 Todo *todo = item->todo(); 00603 if ( todo && mTodoMap.contains( todo ) ) { 00604 mTodoMap.remove( todo ); 00605 } 00606 delete item; 00607 } 00608 mItemsToDelete.clear(); 00609 } 00610 00611 00612 bool KOTodoView::scheduleRemoveTodoItem( KOTodoViewItem *todoItem ) 00613 { 00614 if ( todoItem ) { 00615 mItemsToDelete.append( todoItem ); 00616 QTimer::singleShot( 0, this, SLOT( removeTodoItems() ) ); 00617 return true; 00618 } else 00619 return false; 00620 } 00621 00622 void KOTodoView::updateConfig() 00623 { 00624 mTodoListView->repaintContents(); 00625 } 00626 00627 Incidence::List KOTodoView::selectedIncidences() 00628 { 00629 Incidence::List selected; 00630 00631 KOTodoViewItem *item = (KOTodoViewItem *)(mTodoListView->selectedItem()); 00632 // if (!item) item = mActiveItem; 00633 if (item) selected.append(item->todo()); 00634 00635 return selected; 00636 } 00637 00638 Todo::List KOTodoView::selectedTodos() 00639 { 00640 Todo::List selected; 00641 00642 KOTodoViewItem *item = (KOTodoViewItem *)(mTodoListView->selectedItem()); 00643 // if (!item) item = mActiveItem; 00644 if (item) selected.append(item->todo()); 00645 00646 return selected; 00647 } 00648 00649 void KOTodoView::changeIncidenceDisplay(Incidence *incidence, int action) 00650 { 00651 // The todo view only displays todos, so exit on all other incidences 00652 if ( incidence->type() != "Todo" ) 00653 return; 00654 bool isFiltered = !calendar()->filter()->filterIncidence( incidence ); 00655 Todo *todo = static_cast<Todo *>(incidence); 00656 if ( todo ) { 00657 KOTodoViewItem *todoItem = 0; 00658 if ( mTodoMap.contains( todo ) ) { 00659 todoItem = mTodoMap[todo]; 00660 } 00661 switch ( action ) { 00662 case KOGlobals::INCIDENCEADDED: 00663 case KOGlobals::INCIDENCEEDITED: 00664 // If it's already there, edit it, otherwise just add 00665 if ( todoItem ) { 00666 if ( isFiltered ) { 00667 scheduleRemoveTodoItem( todoItem ); 00668 } else { 00669 // correctly update changes in relations 00670 Todo*parent = dynamic_cast<Todo*>( todo->relatedTo() ); 00671 KOTodoViewItem*parentItem = 0; 00672 if ( parent && mTodoMap.contains(parent) ) { 00673 parentItem = mTodoMap[ parent ]; 00674 } 00675 if ( todoItem->parent() != parentItem ) { 00676 // The relations changed 00677 if ( parentItem ) { 00678 parentItem->insertItem( todoItem ); 00679 } else { 00680 mTodoListView->insertItem( todoItem ); 00681 } 00682 } 00683 todoItem->construct(); 00684 } 00685 } else { 00686 if ( !isFiltered ) { 00687 insertTodoItem( todo ); 00688 } 00689 } 00690 break; 00691 case KOGlobals::INCIDENCEDELETED: 00692 if ( todoItem ) { 00693 scheduleRemoveTodoItem( todoItem ); 00694 } 00695 break; 00696 default: 00697 QTimer::singleShot( 0, this, SLOT( updateView() ) ); 00698 } 00699 } else { 00700 // use a QTimer here, because when marking todos finished using 00701 // the checkbox, this slot gets called, but we cannot update the views 00702 // because we're still inside KOTodoViewItem::stateChange 00703 QTimer::singleShot(0,this,SLOT(updateView())); 00704 } 00705 } 00706 00707 void KOTodoView::showDates(const QDate &, const QDate &) 00708 { 00709 } 00710 00711 void KOTodoView::showIncidences( const Incidence::List & ) 00712 { 00713 kdDebug(5850) << "KOTodoView::showIncidences( const Incidence::List & ): not yet implemented" << endl; 00714 } 00715 00716 void KOTodoView::printPreview(CalPrinter *calPrinter, const QDate &fd, 00717 const QDate &td) 00718 { 00719 #ifndef KORG_NOPRINTER 00720 calPrinter->preview(CalPrinter::Todolist, fd, td); 00721 #endif 00722 } 00723 00724 CalPrinter::PrintType KOTodoView::printType() 00725 { 00726 return CalPrinter::Todolist; 00727 } 00728 00729 void KOTodoView::editItem( QListViewItem *item ) 00730 { 00731 if (item) 00732 emit editIncidenceSignal( static_cast<KOTodoViewItem *>( item )->todo() ); 00733 } 00734 00735 void KOTodoView::editItem( QListViewItem *item, const QPoint &, int ) 00736 { 00737 editItem( item ); 00738 } 00739 00740 void KOTodoView::showItem( QListViewItem *item ) 00741 { 00742 if (item) 00743 emit showIncidenceSignal( static_cast<KOTodoViewItem *>( item )->todo() ); 00744 } 00745 00746 void KOTodoView::showItem( QListViewItem *item, const QPoint &, int ) 00747 { 00748 showItem( item ); 00749 } 00750 00751 void KOTodoView::popupMenu( QListViewItem *item, const QPoint &, int column ) 00752 { 00753 mActiveItem = static_cast<KOTodoViewItem *>( item ); 00754 if ( item ) { 00755 QDate date = mActiveItem->todo()->dtDue().date(); 00756 if ( mActiveItem->todo()->hasDueDate () ) { 00757 mMovePopupMenu->datePicker()->setDate( date ); 00758 } else { 00759 mMovePopupMenu->datePicker()->setDate( QDate::currentDate() ); 00760 } 00761 switch ( column ) { 00762 case 2: 00763 mPriorityPopupMenu->popup( QCursor::pos() ); 00764 break; 00765 case 3: { 00766 mPercentageCompletedPopupMenu->popup( QCursor::pos() ); 00767 break; 00768 } 00769 case 4: 00770 mMovePopupMenu->popup( QCursor::pos() ); 00771 break; 00772 case 5: 00773 getCategoryPopupMenu( mActiveItem )->popup( QCursor::pos() ); 00774 break; 00775 default: 00776 mCopyPopupMenu->datePicker()->setDate( date ); 00777 mCopyPopupMenu->datePicker()->setDate( QDate::currentDate() ); 00778 mItemPopupMenu->setItemEnabled( POPUP_UNSUBTODO, 00779 mActiveItem->todo()->relatedTo() ); 00780 mItemPopupMenu->popup( QCursor::pos() ); 00781 } 00782 } else mPopupMenu->popup( QCursor::pos() ); 00783 } 00784 00785 void KOTodoView::newTodo() 00786 { 00787 emit newTodoSignal( QDate::currentDate().addDays(7) ); 00788 } 00789 00790 void KOTodoView::newSubTodo() 00791 { 00792 if (mActiveItem) { 00793 emit newSubTodoSignal(mActiveItem->todo()); 00794 } 00795 } 00796 00797 void KOTodoView::editTodo() 00798 { 00799 editItem( mActiveItem ); 00800 } 00801 00802 void KOTodoView::showTodo() 00803 { 00804 showItem( mActiveItem ); 00805 } 00806 00807 void KOTodoView::deleteTodo() 00808 { 00809 if (mActiveItem) { 00810 if (mActiveItem->childCount()) { 00811 KMessageBox::sorry(this,i18n("Cannot delete To-Do which has children."), 00812 i18n("Delete To-Do")); 00813 } else { 00814 emit deleteIncidenceSignal(mActiveItem->todo()); 00815 } 00816 } 00817 } 00818 00819 void KOTodoView::setNewPriority(int index) 00820 { 00821 if (mActiveItem && !mActiveItem->todo()->isReadOnly ()) { 00822 Todo *todo = mActiveItem->todo(); 00823 Todo *oldTodo = todo->clone(); 00824 todo->setPriority(mPriority[index]); 00825 mActiveItem->construct(); 00826 emit incidenceChanged( oldTodo, todo, KOGlobals::PRIORITY_MODIFIED ); 00827 delete oldTodo; 00828 } 00829 } 00830 00831 void KOTodoView::setNewPercentage(int index) 00832 { 00833 if ( mActiveItem && !mActiveItem->todo()->isReadOnly () ) { 00834 Todo *todo = mActiveItem->todo(); 00835 Todo *oldTodo = todo->clone(); 00836 00837 if (mPercentage[index] == 100) { 00838 emit todoCompleted( todo ); 00839 } else { 00840 todo->setCompleted(false); 00841 } 00842 todo->setPercentComplete(mPercentage[index]); 00843 mActiveItem->construct(); 00844 emit incidenceChanged( oldTodo, todo, KOGlobals::COMPLETION_MODIFIED ); 00845 delete oldTodo; 00846 } 00847 } 00848 00849 void KOTodoView::setNewDate(QDate date) 00850 { 00851 if ( mActiveItem && !mActiveItem->todo()->isReadOnly()) { 00852 Todo *todo = mActiveItem->todo(); 00853 00854 QDateTime dt; 00855 dt.setDate( date ); 00856 00857 if ( !todo->doesFloat() ) 00858 dt.setTime( todo->dtDue().time() ); 00859 00860 Todo *oldTodo = todo->clone(); 00861 00862 if ( date.isNull() ) 00863 todo->setHasDueDate( false ); 00864 else if ( !todo->hasDueDate() ) 00865 todo->setHasDueDate( true ); 00866 todo->setDtDue( dt ); 00867 todo->setRevision( todo->revision() + 1 ); 00868 00869 mActiveItem->construct(); 00870 emit incidenceChanged( oldTodo, todo, KOGlobals::DATE_MODIFIED ); 00871 delete oldTodo; 00872 } 00873 } 00874 00875 void KOTodoView::copyTodoToDate( QDate date ) 00876 { 00877 QDateTime dt; 00878 dt.setDate( date ); 00879 00880 if ( mActiveItem ) { 00881 Todo *newTodo = mActiveItem->todo()->clone(); 00882 newTodo->recreate(); 00883 00884 if ( date.isNull() ) 00885 newTodo->setHasDueDate( false ); 00886 newTodo->setDtDue( dt ); 00887 newTodo->setPercentComplete( 0 ); 00888 00889 // avoid forking 00890 if ( newTodo->doesRecur() ) 00891 newTodo->recurrence()->unsetRecurs(); 00892 00893 calendar()->addTodo( newTodo ); 00894 emit incidenceAdded( newTodo ); 00895 } 00896 } 00897 00898 QPopupMenu *KOTodoView::getCategoryPopupMenu( KOTodoViewItem *todoItem ) 00899 { 00900 QPopupMenu *tempMenu = new QPopupMenu( this ); 00901 QStringList checkedCategories = todoItem->todo()->categories(); 00902 00903 tempMenu->setCheckable( true ); 00904 QStringList::Iterator it; 00905 for ( it = KOPrefs::instance()->mCustomCategories.begin(); 00906 it != KOPrefs::instance()->mCustomCategories.end(); 00907 ++it ) { 00908 int index = tempMenu->insertItem( *it ); 00909 mCategory[ index ] = *it; 00910 if ( checkedCategories.find( *it ) != checkedCategories.end() ) 00911 tempMenu->setItemChecked( index, true ); 00912 } 00913 00914 connect ( tempMenu, SIGNAL( activated( int ) ), 00915 SLOT( changedCategories( int ) ) ); 00916 return tempMenu; 00917 } 00918 00919 void KOTodoView::changedCategories(int index) 00920 { 00921 if (mActiveItem && !mActiveItem->todo()->isReadOnly ()) { 00922 Todo*todo = mActiveItem->todo(); 00923 Todo*oldTodo = todo->clone(); 00924 QStringList categories = todo->categories (); 00925 if (categories.find (mCategory[index]) != categories.end ()) 00926 categories.remove (mCategory[index]); 00927 else 00928 categories.insert (categories.end(), mCategory[index]); 00929 categories.sort (); 00930 todo->setCategories (categories); 00931 mActiveItem->construct(); 00932 emit incidenceChanged( oldTodo, todo, KOGlobals::CATEGORY_MODIFIED); 00933 delete oldTodo; 00934 } 00935 } 00936 00937 void KOTodoView::setDocumentId( const QString &id ) 00938 { 00939 kdDebug(5850) << "KOTodoView::setDocumentId()" << endl; 00940 00941 mDocPrefs->setDoc( id ); 00942 } 00943 00944 void KOTodoView::itemStateChanged( QListViewItem *item ) 00945 { 00946 if (!item) return; 00947 00948 KOTodoViewItem *todoItem = (KOTodoViewItem *)item; 00949 00950 // kdDebug(5850) << "KOTodoView::itemStateChanged(): " << todoItem->todo()->summary() << endl; 00951 00952 if( mDocPrefs ) mDocPrefs->writeEntry( todoItem->todo()->uid(), todoItem->isOpen() ); 00953 } 00954 00955 void KOTodoView::saveLayout(KConfig *config, const QString &group) const 00956 { 00957 mTodoListView->saveLayout(config,group); 00958 } 00959 00960 void KOTodoView::restoreLayout(KConfig *config, const QString &group) 00961 { 00962 mTodoListView->restoreLayout(config,group); 00963 } 00964 00965 void KOTodoView::processSelectionChange() 00966 { 00967 // kdDebug(5850) << "KOTodoView::processSelectionChange()" << endl; 00968 00969 KOTodoViewItem *item = 00970 static_cast<KOTodoViewItem *>( mTodoListView->selectedItem() ); 00971 00972 if ( !item ) { 00973 emit incidenceSelected( 0 ); 00974 } else { 00975 emit incidenceSelected( item->todo() ); 00976 } 00977 } 00978 00979 void KOTodoView::clearSelection() 00980 { 00981 mTodoListView->selectAll( false ); 00982 } 00983 00984 void KOTodoView::purgeCompleted() 00985 { 00986 emit purgeCompletedSignal(); 00987 } 00988 00989 void KOTodoView::addQuickTodo() 00990 { 00991 Todo *todo = new Todo(); 00992 todo->setSummary( mQuickAdd->text() ); 00993 todo->setOrganizer( KOPrefs::instance()->email() ); 00994 if ( !calendar()->addTodo( todo ) ) { 00995 KODialogManager::errorSaveTodo( this ); 00996 return; 00997 } 00998 mQuickAdd->setText( QString::null ); 00999 emit incidenceAdded( todo ); 01000 updateView(); 01001 } 01002 01003 void KOTodoView::emitCompletedSignal( Todo *todo ) 01004 { 01005 emit todoCompleted( todo ); 01006 }
KDE Logo
This file is part of the documentation for korganizer Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Oct 1 15:19:32 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003