summaryrefslogtreecommitdiffabout
path: root/korganizer/kotodoview.cpp
Side-by-side diff
Diffstat (limited to 'korganizer/kotodoview.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--korganizer/kotodoview.cpp1028
1 files changed, 1028 insertions, 0 deletions
diff --git a/korganizer/kotodoview.cpp b/korganizer/kotodoview.cpp
new file mode 100644
index 0000000..0708a69
--- a/dev/null
+++ b/korganizer/kotodoview.cpp
@@ -0,0 +1,1028 @@
+/*
+ This file is part of KOrganizer.
+ Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <qlayout.h>
+#include <qheader.h>
+#include <qcursor.h>
+
+#include <qvbox.h>
+#include <kdebug.h>
+#include "koprefs.h"
+#include <klocale.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+
+#include <libkcal/icaldrag.h>
+#include <libkcal/vcaldrag.h>
+#include <libkcal/calfilter.h>
+#include <libkcal/dndfactory.h>
+#include <libkcal/calendarresources.h>
+#include <libkcal/resourcecalendar.h>
+#include <kresources/resourceselectdialog.h>
+#ifndef DESKTOP_VERSION
+#include <qpe/qpeapplication.h>
+#else
+#include <qapplication.h>
+#endif
+#ifndef KORG_NOPRINTER
+#include "calprinter.h"
+#endif
+#include "docprefs.h"
+
+#include "kotodoview.h"
+using namespace KOrg;
+#include "kotodoview.moc"
+
+KOTodoListView::KOTodoListView(Calendar *calendar,QWidget *parent,
+ const char *name) :
+ KListView(parent,name)
+{
+ mCalendar = calendar;
+#ifndef DESKTOP_VERSION
+ QPEApplication::setStylusOperation(viewport(), QPEApplication::RightOnHold );
+#endif
+ mOldCurrent = 0;
+ mMousePressed = false;
+
+ setAcceptDrops(true);
+ viewport()->setAcceptDrops(true);
+ int size = 16;
+ if (qApp->desktop()->width() < 300 )
+ size = 12;
+ setTreeStepSize( size + 6 );
+
+}
+
+void KOTodoListView::contentsDragEnterEvent(QDragEnterEvent *e)
+{
+#ifndef KORG_NODND
+// kdDebug() << "KOTodoListView::contentsDragEnterEvent" << endl;
+ if ( !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) &&
+ !QTextDrag::canDecode( e ) ) {
+ e->ignore();
+ return;
+ }
+
+ mOldCurrent = currentItem();
+#endif
+}
+
+
+void KOTodoListView::contentsDragMoveEvent(QDragMoveEvent *e)
+{
+#ifndef KORG_NODND
+// kdDebug() << "KOTodoListView::contentsDragMoveEvent" << endl;
+
+ if ( !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) &&
+ !QTextDrag::canDecode( e ) ) {
+ e->ignore();
+ return;
+ }
+
+ e->accept();
+#endif
+}
+
+void KOTodoListView::contentsDragLeaveEvent(QDragLeaveEvent *)
+{
+#ifndef KORG_NODND
+// kdDebug() << "KOTodoListView::contentsDragLeaveEvent" << endl;
+
+ setCurrentItem(mOldCurrent);
+ setSelected(mOldCurrent,true);
+#endif
+}
+
+void KOTodoListView::contentsDropEvent(QDropEvent *e)
+{
+#ifndef KORG_NODND
+// kdDebug() << "KOTodoListView::contentsDropEvent" << endl;
+
+ if ( !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) &&
+ !QTextDrag::canDecode( e ) ) {
+ e->ignore();
+ return;
+ }
+
+ DndFactory factory( mCalendar );
+ Todo *todo = factory.createDropTodo(e);
+
+ if (todo) {
+ e->acceptAction();
+
+ KOTodoViewItem *destination =
+ (KOTodoViewItem *)itemAt(contentsToViewport(e->pos()));
+ Todo *destinationEvent = 0;
+ if (destination) destinationEvent = destination->todo();
+
+ Todo *existingTodo = mCalendar->todo(todo->uid());
+
+ if(existingTodo) {
+// kdDebug() << "Drop existing Todo" << endl;
+ Incidence *to = destinationEvent;
+ while(to) {
+ if (to->uid() == todo->uid()) {
+ KMessageBox::sorry(this,
+ i18n("Cannot move To-Do to itself or a child of itself"),
+ i18n("Drop To-Do"));
+ delete todo;
+ return;
+ }
+ to = to->relatedTo();
+ }
+ existingTodo->setRelatedTo(destinationEvent);
+ emit todoDropped(todo);
+ delete todo;
+ } else {
+// kdDebug() << "Drop new Todo" << endl;
+ todo->setRelatedTo(destinationEvent);
+ mCalendar->addTodo(todo);
+
+ emit todoDropped(todo);
+ }
+ }
+ else {
+ QString text;
+ if (QTextDrag::decode(e,text)) {
+ //QListViewItem *qlvi = itemAt( contentsToViewport(e->pos()) );
+ KOTodoViewItem *todoi = static_cast<KOTodoViewItem *>(itemAt( contentsToViewport(e->pos()) ));
+ kdDebug() << "Dropped : " << text << endl;
+ QStringList emails = QStringList::split(",",text);
+ for(QStringList::ConstIterator it = emails.begin();it!=emails.end();++it) {
+ kdDebug() << " Email: " << (*it) << endl;
+ int pos = (*it).find("<");
+ QString name = (*it).left(pos);
+ QString email = (*it).mid(pos);
+ if (!email.isEmpty() && todoi) {
+ todoi->todo()->addAttendee(new Attendee(name,email));
+ }
+ }
+ }
+ else {
+ kdDebug() << "KOTodoListView::contentsDropEvent(): Todo from drop not decodable" << endl;
+ e->ignore();
+ }
+ }
+#endif
+}
+
+void KOTodoListView::contentsMousePressEvent(QMouseEvent* e)
+{
+ QListView::contentsMousePressEvent(e);
+#ifndef KORG_NODND
+ QPoint p(contentsToViewport(e->pos()));
+ QListViewItem *i = itemAt(p);
+ if (i) {
+ // if the user clicked into the root decoration of the item, don't
+ // try to start a drag!
+ if (p.x() > header()->sectionPos(header()->mapToIndex(0)) +
+ treeStepSize() * (i->depth() + (rootIsDecorated() ? 1 : 0)) +
+ itemMargin() ||
+ p.x() < header()->sectionPos(header()->mapToIndex(0))) {
+ if (e->button()==Qt::LeftButton) {
+ mPressPos = e->pos();
+ mMousePressed = true;
+ }
+ }
+ }
+#endif
+}
+
+void KOTodoListView::contentsMouseMoveEvent(QMouseEvent* e)
+{
+#ifndef KORG_NODND
+// kdDebug() << "KOTodoListView::contentsMouseMoveEvent()" << endl;
+ QListView::contentsMouseMoveEvent(e);
+ if (mMousePressed && (mPressPos - e->pos()).manhattanLength() >
+ QApplication::startDragDistance()) {
+ mMousePressed = false;
+ QListViewItem *item = itemAt(contentsToViewport(mPressPos));
+ if (item) {
+// kdDebug() << "Start Drag for item " << item->text(0) << endl;
+ DndFactory factory( mCalendar );
+ ICalDrag *vd = factory.createDragTodo(
+ ((KOTodoViewItem *)item)->todo(),viewport());
+ if (vd->drag()) {
+ kdDebug() << "KOTodoListView::contentsMouseMoveEvent(): Delete drag source" << endl;
+ }
+/*
+ QString source = fullPath(item);
+ if ( QFile::exists(source) ) {
+ QUriDrag* ud = new QUriDrag(viewport());
+ ud->setFilenames( source );
+ if ( ud->drag() )
+ QMessageBox::information( this, "Drag source",
+ QString("Delete ")+source, "Not implemented" );
+*/
+ }
+ }
+#endif
+}
+void KOTodoListView::keyPressEvent ( QKeyEvent * e )
+{
+
+ QListViewItem* cn;
+ if ( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter ) {
+ cn = currentItem();
+ if ( cn ) {
+ KOTodoViewItem* ci = (KOTodoViewItem*)( cn );
+ if ( ci ){
+ if ( e->state() == ShiftButton )
+ ci->setOn( false );
+ else
+ ci->setOn( true );
+ cn = cn->nextSibling();
+ if ( cn ) {
+ setCurrentItem ( cn );
+ ensureItemVisible ( cn );
+ }
+
+ }
+ }
+
+ return;
+ }
+
+ // qDebug("KOTodoListView::keyPressEvent ");
+ if ( e->state() == Qt::ControlButton || e->state() == Qt::ShiftButton || ( height() > 150 && width() > 200 ) ) {
+ switch ( e->key() ) {
+ case Qt::Key_Down:
+ case Qt::Key_Up:
+ QListView::keyPressEvent ( e );
+ break;
+ default:
+ e->ignore();
+ break;
+ }
+ return;
+ }
+ e->ignore();
+}
+void KOTodoListView::contentsMouseReleaseEvent(QMouseEvent *e)
+{
+ QListView::contentsMouseReleaseEvent(e);
+ mMousePressed = false;
+}
+
+void KOTodoListView::contentsMouseDoubleClickEvent(QMouseEvent *e)
+{
+ if (!e) return;
+
+ QPoint vp = contentsToViewport(e->pos());
+
+ QListViewItem *item = itemAt(vp);
+
+ emit double_Clicked(item);
+ if (!item) return;
+
+ emit doubleClicked(item,vp,0);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+KOQuickTodo::KOQuickTodo(QWidget *parent) :
+ QLineEdit(parent)
+{
+ setText(i18n("Click to add a new Todo"));
+}
+
+void KOQuickTodo::focusInEvent(QFocusEvent *ev)
+{
+ if ( text()==i18n("Click to add a new Todo") )
+ setText("");
+ QLineEdit::focusInEvent(ev);
+}
+
+void KOQuickTodo::focusOutEvent(QFocusEvent *ev)
+{
+ setText(i18n("Click to add a new Todo"));
+ QLineEdit::focusOutEvent(ev);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+KOTodoView::KOTodoView(Calendar *calendar,QWidget* parent,const char* name) :
+ KOrg::BaseView(calendar,parent,name)
+{
+ QBoxLayout *topLayout = new QVBoxLayout(this);
+ mName = QString ( name );
+ mBlockUpdate = false;
+ mQuickAdd = new KOQuickTodo(this);
+ topLayout->addWidget(mQuickAdd);
+
+ if ( !KOPrefs::instance()->mEnableQuickTodo ) mQuickAdd->hide();
+
+ mTodoListView = new KOTodoListView(calendar,this);
+ topLayout->addWidget(mTodoListView);
+ //mTodoListView->header()->setMaximumHeight(30);
+ mTodoListView->setRootIsDecorated(true);
+ mTodoListView->setAllColumnsShowFocus(true);
+
+ mTodoListView->setShowSortIndicator(true);
+
+ mTodoListView->addColumn(i18n("Todo"));
+ mTodoListView->addColumn(i18n("Prio"));
+ mTodoListView->setColumnAlignment(1,AlignHCenter);
+ mTodoListView->addColumn(i18n("Complete"));
+ mTodoListView->setColumnAlignment(2,AlignHCenter);
+ mTodoListView->addColumn(i18n("Due Date"));
+ mTodoListView->setColumnAlignment(3,AlignLeft);
+ mTodoListView->addColumn(i18n("Due Time"));
+ mTodoListView->setColumnAlignment(4,AlignHCenter);
+ mTodoListView->addColumn(i18n("Cancelled"));
+ mTodoListView->addColumn(i18n("Categories"));
+#if 0
+ mTodoListView->addColumn(i18n("Sort Id"));
+ mTodoListView->setColumnAlignment(4,AlignHCenter);
+#endif
+
+ mTodoListView->setMinimumHeight( 60 );
+ mTodoListView->setItemsRenameable( true );
+ mTodoListView->setRenameable( 0 );
+ mTodoListView->setColumnWidth( 0, 120 );
+ mTodoListView->setColumnWidthMode(0, QListView::Manual);
+ mTodoListView->setColumnWidthMode(1, QListView::Manual);
+ mTodoListView->setColumnWidthMode(2, QListView::Manual);
+ mTodoListView->setColumnWidthMode(3, QListView::Manual);
+ mTodoListView->setColumnWidthMode(4, QListView::Manual);
+ mTodoListView->setColumnWidthMode(5, QListView::Manual);
+ mTodoListView->setColumnAlignment( 2, AlignCenter );
+#if 0
+ mTodoListView->setColumnWidthMode(6, QListView::Manual);
+#endif
+
+ mPriorityPopupMenu = new QPopupMenu(this);
+ for (int i = 1; i <= 5; i++) {
+ QString label = QString ("%1").arg (i);
+ mPriority[mPriorityPopupMenu->insertItem (label)] = i;
+ }
+ connect (mPriorityPopupMenu, SIGNAL(activated (int)), SLOT (setNewPriority(int)));
+
+ mPercentageCompletedPopupMenu = new QPopupMenu(this);
+ for (int i = 0; i <= 100; i+=20) {
+ QString label = QString ("%1 %").arg (i);
+ mPercentage[mPercentageCompletedPopupMenu->insertItem (label)] = i;
+ }
+ connect (mPercentageCompletedPopupMenu, SIGNAL (activated (int)), SLOT (setNewPercentage (int)));
+
+
+
+ mItemPopupMenu = new QPopupMenu(this);
+ mItemPopupMenu->insertItem(i18n("Show..."), this,
+ SLOT (showTodo()));
+ mItemPopupMenu->insertItem(i18n("Edit..."), this,
+ SLOT (editTodo()));
+ mItemPopupMenu->insertItem( i18n("Delete"), this,
+ SLOT (deleteTodo()));
+ mItemPopupMenu->insertItem( i18n("Clone..."), this,
+ SLOT (cloneTodo()));
+ mItemPopupMenu->insertItem( i18n("Move..."), this,
+ SLOT (moveTodo()));
+ mItemPopupMenu->insertItem( i18n("Beam..."), this,
+ SLOT (beamTodo()));
+ mItemPopupMenu->insertItem( i18n("Toggle Cancel"), this,
+ SLOT (cancelTodo()));
+ mItemPopupMenu->insertSeparator();
+
+ mItemPopupMenu->insertItem( i18n("New Todo..."), this,
+ SLOT (newTodo()));
+ mItemPopupMenu->insertItem(i18n("New Sub-Todo..."), this,
+ SLOT (newSubTodo()));
+ mItemPopupMenu->insertItem(i18n("Unparent Todo"), this,
+ SLOT (unparentTodo()));
+ mItemPopupMenu->insertSeparator();
+ mItemPopupMenu->insertItem(i18n("Delete completed To-Dos","Purge Completed"),
+ this, SLOT( purgeCompleted() ) );
+ mItemPopupMenu->insertItem(i18n("toggle completed To-Dos","Show Completed"),
+ this, SLOT( toggleCompleted() ),0, 33 );
+ mItemPopupMenu->insertItem(i18n("toggle quick todo","Show Quick Todo"),
+ this, SLOT( toggleQuickTodo() ),0, 34 );
+
+ mPopupMenu = new QPopupMenu(this);
+ mPopupMenu->insertItem(SmallIconSet("todo"), i18n("New Todo..."), this,
+ SLOT (newTodo()),0,1);
+ mPopupMenu->insertItem(i18n("delete completed To-Dos","Purge Completed"),
+ this, SLOT(purgeCompleted()),0,2);
+ mPopupMenu->insertItem(i18n("Show Completed"),
+ this, SLOT( toggleCompleted() ),0,3 );
+ mPopupMenu->insertItem(i18n("toggle quick todo","Show Quick Todo"),
+ this, SLOT( toggleQuickTodo() ),0,4 );
+ mDocPrefs = new DocPrefs( name );
+
+ mPopupMenu->setCheckable( true );
+ mItemPopupMenu->setCheckable( true );
+ // Double clicking conflicts with opening/closing the subtree
+ connect( mTodoListView, SIGNAL( doubleClicked( QListViewItem *) ),
+ SLOT( editItem( QListViewItem *) ) );
+ connect( mTodoListView, SIGNAL( rightButtonClicked ( QListViewItem *,
+ const QPoint &,int ) ),
+ SLOT( popupMenu( QListViewItem *, const QPoint & ,int) ) );
+ connect( mTodoListView, SIGNAL( clicked( QListViewItem * ) ),
+ SLOT( itemClicked( QListViewItem * ) ) );
+ connect( mTodoListView, SIGNAL( double_Clicked( QListViewItem * ) ),
+ SLOT( itemDoubleClicked( QListViewItem * ) ) );
+ connect( mTodoListView, SIGNAL( todoDropped( Todo * ) ),
+ SLOT( updateView() ) );
+ connect( mTodoListView, SIGNAL( expanded( QListViewItem * ) ),
+ SLOT( itemStateChanged( QListViewItem * ) ) );
+ connect( mTodoListView, SIGNAL( collapsed( QListViewItem * ) ),
+ SLOT( itemStateChanged( QListViewItem * ) ) );
+
+#if 0
+ connect(mTodoListView,SIGNAL(selectionChanged(QListViewItem *)),
+ SLOT(selectionChanged(QListViewItem *)));
+ connect(mTodoListView,SIGNAL(clicked(QListViewItem *)),
+ SLOT(selectionChanged(QListViewItem *)));
+ connect(mTodoListView,SIGNAL(pressed(QListViewItem *)),
+ SLOT(selectionChanged(QListViewItem *)));
+#endif
+ connect( mTodoListView, SIGNAL(selectionChanged() ),
+ SLOT( processSelectionChange() ) );
+ connect( mQuickAdd, SIGNAL( returnPressed () ),
+ SLOT( addQuickTodo() ) );
+// if ( QApplication::desktop()->width() < 480 ) {
+// setNarrow();
+ // mTodoListView->setColumnWidth( 0, 100 );
+
+ // }
+
+}
+
+KOTodoView::~KOTodoView()
+{
+ delete mDocPrefs;
+}
+
+void KOTodoView::jumpToDate ()
+{
+ // if (mActiveItem) {
+// mActiveItem->todo());
+// if ( mActiveItem->todo()->hasDueDate() )
+// emit mActiveItem->todo()jumpToTime( mTodo->dtDue().date() );
+}
+
+void KOTodoView::setNarrow()
+{
+ //mTodoListView->setColumnWidth( 0, 120 );
+ mTodoListView->setColumnWidth( 1, 35 );
+ mTodoListView->setColumnWidth( 2, 40 );
+ mTodoListView->setColumnWidth( 3, 80 );
+ mTodoListView->setColumnWidth( 4, 40 );
+ mTodoListView->setColumnWidth( 5, 90 );
+
+}
+void KOTodoView::updateView()
+{
+// kdDebug() << "KOTodoView::updateView()" << endl;
+ QFont fo = KOPrefs::instance()->mTodoViewFont;
+ mTodoListView->clear();
+ if ( mName == "todolistsmall" ) {
+ if ( KOPrefs::instance()->mTodoViewUsesSmallFont ) {
+ int ps = fo.pointSize() -2;
+ if ( ps > 12 )
+ ps -= 2;
+ fo.setPointSize( ps );
+ }
+ }
+
+ mTodoListView->setFont( fo );
+ // QFontMetrics fm ( KOPrefs::instance()->mTodoViewFont );
+ //mTodoListView->header()->setMaximumHeight(fm.height());
+ QPtrList<Todo> todoList = calendar()->todos();
+
+/*
+ kdDebug() << "KOTodoView::updateView(): Todo List:" << endl;
+ Event *t;
+ for(t = todoList.first(); t; t = todoList.next()) {
+ kdDebug() << " " << t->getSummary() << endl;
+
+ if (t->getRelatedTo()) {
+ kdDebug() << " (related to " << t->getRelatedTo()->getSummary() << ")" << endl;
+ }
+
+ QPtrList<Event> l = t->getRelations();
+ Event *c;
+ for(c=l.first();c;c=l.next()) {
+ kdDebug() << " - relation: " << c->getSummary() << endl;
+ }
+ }
+*/
+
+ // Put for each Event a KOTodoViewItem in the list view. Don't rely on a
+ // specific order of events. That means that we have to generate parent items
+ // recursively for proper hierarchical display of Todos.
+ mTodoMap.clear();
+ Todo *todo;
+ todo = todoList.first();// todo; todo = todoList.next()) {
+ while ( todo ) {
+ bool next = true;
+ // qDebug("todo %s ", todo->summary().latin1());
+ Incidence *incidence = todo->relatedTo();
+ while ( incidence ) {
+ if ( incidence->type() == "Todo") {
+ //qDebug("related %s ",incidence->summary().latin1() );
+ if ( !(todoList.contains ( ((Todo* )incidence ) ) )) {
+ //qDebug("related not found ");
+ todoList.remove( );
+ todo = todoList.current();
+ next = false;
+ incidence = 0;
+
+ } else {
+ //qDebug("related found ");
+ incidence = incidence->relatedTo();
+ }
+ } else
+ incidence = 0;
+ }
+ if ( next )
+ todo = todoList.next();
+ }
+// qDebug("again .... ");
+// for(todo = todoList.first(); todo; todo = todoList.next()) {
+
+// qDebug("yytodo %s ", todo->summary().latin1());
+// }
+ //qDebug("for ");
+ for(todo = todoList.first(); todo; todo = todoList.next()) {
+ if (!mTodoMap.contains(todo) && ( KOPrefs::instance()->mShowCompletedTodo || !todo->isCompleted() ) )
+ {
+ insertTodoItem(todo);
+ }
+ }
+ //qDebug("for end ");
+ // Restore opened/closed state
+ mTodoListView->blockSignals( true );
+ if( mDocPrefs ) restoreItemState( mTodoListView->firstChild() );
+ mTodoListView->blockSignals( false );
+ mTodoListView->setFocus();
+ processSelectionChange();
+}
+
+void KOTodoView::restoreItemState( QListViewItem *item )
+{
+ while( item ) {
+ KOTodoViewItem *todoItem = (KOTodoViewItem *)item;
+ todoItem->setOpen( mDocPrefs->readBoolEntry( todoItem->todo()->uid() ) );
+ if( item->childCount() > 0 ) restoreItemState( item->firstChild() );
+ item = item->nextSibling();
+ }
+}
+
+
+QMap<Todo *,KOTodoViewItem *>::ConstIterator
+ KOTodoView::insertTodoItem(Todo *todo)
+{
+// kdDebug() << "KOTodoView::insertTodoItem(): " << todo->getSummary() << endl;
+ // TODO: Check, if dynmaic cast is necessary
+
+
+ Incidence *incidence = todo->relatedTo();
+ if (incidence && incidence->type() == "Todo") {
+ Todo *relatedTodo = static_cast<Todo *>(incidence);
+
+// kdDebug() << " has Related" << endl;
+ QMap<Todo *,KOTodoViewItem *>::ConstIterator itemIterator;
+ itemIterator = mTodoMap.find(relatedTodo);
+ if (itemIterator == mTodoMap.end()) {
+// kdDebug() << " related not yet in list" << endl;
+ itemIterator = insertTodoItem (relatedTodo);
+ }
+ // isn't this pretty stupid? We give one Todo to the KOTodoViewItem
+ // and one into the map. Sure finding is more easy but why? -zecke
+ KOTodoViewItem *todoItem = new KOTodoViewItem(*itemIterator,todo,this);
+ return mTodoMap.insert(todo,todoItem);
+ } else {
+// kdDebug() << " no Related" << endl;
+ // see above -zecke
+ KOTodoViewItem *todoItem = new KOTodoViewItem(mTodoListView,todo,this);
+ return mTodoMap.insert(todo,todoItem);
+ }
+}
+
+
+void KOTodoView::updateConfig()
+{
+ updateView();
+ mTodoListView->repaintContents();
+}
+
+QPtrList<Incidence> KOTodoView::selectedIncidences()
+{
+ QPtrList<Incidence> selected;
+
+ KOTodoViewItem *item = (KOTodoViewItem *)(mTodoListView->selectedItem());
+// if (!item) item = mActiveItem;
+ if (item) selected.append(item->todo());
+
+ return selected;
+}
+
+QPtrList<Todo> KOTodoView::selectedTodos()
+{
+ QPtrList<Todo> selected;
+
+ KOTodoViewItem *item = (KOTodoViewItem *)(mTodoListView->selectedItem());
+// if (!item) item = mActiveItem;
+ if (item) selected.append(item->todo());
+
+ return selected;
+}
+
+void KOTodoView::changeEventDisplay(Event *, int)
+{
+ updateView();
+}
+
+void KOTodoView::showDates(const QDate &, const QDate &)
+{
+}
+
+void KOTodoView::showEvents(QPtrList<Event>)
+{
+ kdDebug() << "KOTodoView::selectEvents(): not yet implemented" << endl;
+}
+
+void KOTodoView::printPreview(CalPrinter *calPrinter, const QDate &fd,
+ const QDate &td)
+{
+#ifndef KORG_NOPRINTER
+ calPrinter->preview(CalPrinter::Todolist, fd, td);
+#endif
+}
+
+void KOTodoView::editItem(QListViewItem *item )
+{
+ // qDebug("editItem(QListViewItem *item ) ");
+ emit editTodoSignal(((KOTodoViewItem *)item)->todo());
+}
+
+void KOTodoView::showItem(QListViewItem *item,const QPoint &,int)
+{
+ emit showTodoSignal(((KOTodoViewItem *)item)->todo());
+}
+
+void KOTodoView::popupMenu(QListViewItem *item,const QPoint &,int column)
+{
+
+ mActiveItem = (KOTodoViewItem *)item;
+ if (item) {
+ switch (column){
+ case 1:
+ mPriorityPopupMenu->popup(QCursor::pos ()); break;
+ case 2:
+ mPercentageCompletedPopupMenu->popup(QCursor::pos ()); break;
+ case 3:
+ moveTodo();
+ break;
+ case 6:
+ getCategoryPopupMenu((KOTodoViewItem *)item)->popup(QCursor::pos ()); break;
+ default:
+ mItemPopupMenu->popup(QCursor::pos());
+ }
+ } else mPopupMenu->popup(QCursor::pos());
+}
+void KOTodoView::newTodo()
+{
+ emit newTodoSignal();
+}
+
+void KOTodoView::newSubTodo()
+{
+ if (mActiveItem) {
+ emit newSubTodoSignal(mActiveItem->todo());
+ }
+}
+void KOTodoView::unparentTodo()
+{
+ if (mActiveItem) {
+ emit unparentTodoSignal(mActiveItem->todo());
+ }
+}
+void KOTodoView::editTodo()
+{
+ if (mActiveItem) {
+ emit editTodoSignal(mActiveItem->todo());
+ }
+}
+void KOTodoView::cloneTodo()
+{
+ if (mActiveItem) {
+ emit cloneTodoSignal((Incidence*)mActiveItem->todo());
+ }
+}
+void KOTodoView::cancelTodo()
+{
+ if (mActiveItem) {
+ emit cancelTodoSignal((Incidence*)mActiveItem->todo());
+ }
+}
+void KOTodoView::moveTodo()
+{
+ if (mActiveItem) {
+ emit moveTodoSignal((Incidence*)mActiveItem->todo());
+ }
+}
+void KOTodoView::beamTodo()
+{
+ if (mActiveItem) {
+ emit beamTodoSignal((Incidence*)mActiveItem->todo());
+ }
+}
+
+
+void KOTodoView::showTodo()
+{
+ if (mActiveItem) {
+ emit showTodoSignal(mActiveItem->todo());
+ }
+}
+
+void KOTodoView::deleteTodo()
+{
+ if (mActiveItem) {
+ if (mActiveItem->childCount()) {
+ KMessageBox::sorry(this,i18n("Cannot delete To-Do which has children."),
+ i18n("Delete To-Do"));
+ } else {
+ emit deleteTodoSignal(mActiveItem->todo());
+ }
+ }
+}
+
+void KOTodoView::setNewPriority(int index)
+{
+ if (mActiveItem && !mActiveItem->todo()->isReadOnly ()) {
+ mActiveItem->todo()->setPriority(mPriority[index]);
+ mActiveItem->construct();
+ todoModified (mActiveItem->todo(), KOGlobals::PRIORITY_MODIFIED);
+ mActiveItem->todo()->setRevision( mActiveItem->todo()->revision()+1 );
+ }
+}
+
+void KOTodoView::setNewPercentage(int index)
+{
+ if (mActiveItem && !mActiveItem->todo()->isReadOnly ()) {
+ if (mPercentage[index] == 100) {
+ mActiveItem->todo()->setCompleted(QDateTime::currentDateTime());
+ } else {
+ mActiveItem->todo()->setCompleted(false);
+ }
+ mActiveItem->todo()->setPercentComplete(mPercentage[index]);
+ mActiveItem->construct();
+ todoModified (mActiveItem->todo (), KOGlobals::COMPLETION_MODIFIED);
+ mActiveItem->todo()->setRevision( mActiveItem->todo()->revision()+1 );
+ }
+}
+
+
+QPopupMenu * KOTodoView::getCategoryPopupMenu (KOTodoViewItem *todoItem)
+{
+ QPopupMenu* tempMenu = new QPopupMenu (this);
+ QStringList checkedCategories = todoItem->todo()->categories ();
+
+ tempMenu->setCheckable (true);
+ for (QStringList::Iterator it = KOPrefs::instance()->mCustomCategories.begin ();
+ it != KOPrefs::instance()->mCustomCategories.end ();
+ ++it) {
+ int index = tempMenu->insertItem (*it);
+ mCategory[index] = *it;
+ if (checkedCategories.find (*it) != checkedCategories.end ()) tempMenu->setItemChecked (index, true);
+ }
+
+ connect (tempMenu, SIGNAL (activated (int)), SLOT (changedCategories (int)));
+ return tempMenu;
+
+
+}
+void KOTodoView::changedCategories(int index)
+{
+ if (mActiveItem && !mActiveItem->todo()->isReadOnly ()) {
+ QStringList categories = mActiveItem->todo()->categories ();
+ if (categories.find (mCategory[index]) != categories.end ())
+ categories.remove (mCategory[index]);
+ else
+ categories.insert (categories.end(), mCategory[index]);
+ categories.sort ();
+ mActiveItem->todo()->setCategories (categories);
+ mActiveItem->construct();
+ mActiveItem->todo()->setRevision( mActiveItem->todo()->revision()+1 );
+ todoModified (mActiveItem->todo (), KOGlobals::CATEGORY_MODIFIED);
+ }
+}
+void KOTodoView::itemDoubleClicked(QListViewItem *item)
+{
+ if (!item) {
+ newTodo();
+ return;
+ }
+ if ( KOPrefs::instance()->mEditOnDoubleClick )
+ editItem( item );
+ else
+ showItem( item , QPoint(), 0 );
+}
+void KOTodoView::itemClicked(QListViewItem *item)
+{
+ if (!item) {
+ return;
+ }
+
+ KOTodoViewItem *todoItem = (KOTodoViewItem *)item;
+ int completed = todoItem->todo()->isCompleted(); // Completed or not?
+
+ if (todoItem->isOn()) {
+ if (!completed) {
+ todoItem->todo()->setCompleted(QDateTime::currentDateTime());
+ }
+ } else {
+ if (completed) {
+ todoItem->todo()->setCompleted(false);
+ }
+ }
+}
+
+void KOTodoView::setDocumentId( const QString &id )
+{
+ kdDebug() << "KOTodoView::setDocumentId()" << endl;
+
+ mDocPrefs->setDoc( id );
+}
+
+void KOTodoView::itemStateChanged( QListViewItem *item )
+{
+ if (!item) return;
+
+ KOTodoViewItem *todoItem = (KOTodoViewItem *)item;
+
+// kdDebug() << "KOTodoView::itemStateChanged(): " << todoItem->todo()->summary() << endl;
+
+ if( mDocPrefs ) mDocPrefs->writeEntry( todoItem->todo()->uid(), todoItem->isOpen() );
+}
+
+void KOTodoView::saveLayout(KConfig *config, const QString &group) const
+{
+ mTodoListView->saveLayout(config,group);
+}
+
+void KOTodoView::restoreLayout(KConfig *config, const QString &group)
+{
+ mTodoListView->restoreLayout(config,group);
+}
+
+void KOTodoView::processSelectionChange()
+{
+// kdDebug() << "KOTodoView::processSelectionChange()" << endl;
+
+ KOTodoViewItem *item =
+ static_cast<KOTodoViewItem *>( mTodoListView->selectedItem() );
+
+ if ( !item ) {
+ emit incidenceSelected( 0 );
+ } else {
+ emit incidenceSelected( item->todo() );
+ }
+}
+
+void KOTodoView::modified(bool b)
+{
+ emit isModified(b);
+}
+void KOTodoView::setTodoModified( Todo* todo )
+{
+ todoModified( todo, KOGlobals::UNKNOWN_MODIFIED );
+}
+void KOTodoView::clearSelection()
+{
+ mTodoListView->selectAll( false );
+}
+
+void KOTodoView::purgeCompleted()
+{
+ emit purgeCompletedSignal();
+}
+void KOTodoView::toggleQuickTodo()
+{
+ if ( mQuickAdd->isVisible() ) {
+ mQuickAdd->hide();
+ KOPrefs::instance()->mEnableQuickTodo = false;
+ }
+ else {
+ mQuickAdd->show();
+ KOPrefs::instance()->mEnableQuickTodo = true;
+ }
+ mPopupMenu->setItemChecked(4,KOPrefs::instance()->mEnableQuickTodo);
+ mItemPopupMenu->setItemChecked( 34 , KOPrefs::instance()->mEnableQuickTodo );
+}
+void KOTodoView::toggleCompleted()
+{
+ KOPrefs::instance()->mShowCompletedTodo = !KOPrefs::instance()->mShowCompletedTodo;
+ mPopupMenu->setItemChecked( 3,KOPrefs::instance()->mShowCompletedTodo );
+ mItemPopupMenu->setItemChecked( 33 , KOPrefs::instance()->mShowCompletedTodo );
+ updateView();
+}
+
+void KOTodoView::addQuickTodo()
+{
+ Todo *todo = new Todo();
+ todo->setSummary(mQuickAdd->text());
+ todo->setOrganizer(KOPrefs::instance()->email());
+ CalFilter * cf = mCalendar->filter();
+ if ( cf ) {
+ if ( cf->isEnabled()&& cf->showCategories()) {
+ todo->setCategories(cf->categoryList());
+ }
+ if ( cf->isEnabled() )
+ todo->setSecrecy( cf->getSecrecy());
+ }
+ mCalendar->addTodo(todo);
+ mQuickAdd->setText("");
+ todoModified (todo, KOGlobals::EVENTADDED );
+ updateView();
+}
+void KOTodoView::keyPressEvent ( QKeyEvent * e )
+{
+ // e->ignore();
+ //return;
+ switch ( e->key() ) {
+ case Qt::Key_Down:
+ QWidget::keyPressEvent ( e );
+ break;
+
+ case Qt::Key_Up:
+ QWidget::keyPressEvent ( e );
+ break;
+ case Qt::Key_Q:
+ toggleQuickTodo();
+ break;
+
+ default:
+ e->ignore();
+ }
+
+ if ( e->state() == Qt::ControlButton || e->state() == Qt::ShiftButton || ( height() > 150 && width() > 200 ) ) {
+ if ( e->key() == Qt::Key_I ) {
+ KOTodoViewItem*cn = (KOTodoViewItem*)mTodoListView->currentItem();
+ if ( cn ) {
+ mActiveItem = cn;
+ KOTodoViewItem* ci = (KOTodoViewItem*)( cn );
+ if ( ci ){
+ showTodo();
+ cn = (KOTodoViewItem*)cn->itemBelow();
+ if ( cn ) {
+ mTodoListView->setCurrentItem ( cn );
+ mTodoListView->ensureItemVisible ( cn );
+ }
+
+ }
+ }
+ e->accept();
+
+ }
+
+ }
+
+}
+void KOTodoView::updateTodo( Todo * t, int type )
+{
+ if ( mBlockUpdate)
+ return;
+
+ QMap<Todo *,KOTodoViewItem *>::ConstIterator itemIterator;
+ itemIterator = mTodoMap.find(t);
+ if (itemIterator != mTodoMap.end()) {
+ (*itemIterator)->construct();
+ } else {
+ if ( type == KOGlobals::EVENTADDED ) {
+ insertTodoItem( t );
+ }
+ }
+
+}
+
+void KOTodoView::todoModified(Todo * t , int p )
+{
+ mBlockUpdate = true;
+ emit todoModifiedSignal ( t, p );
+ mBlockUpdate = false;
+}