korganizer

calendarview.cpp

00001 /*
00002     This file is part of KOrganizer.
00003 
00004     Copyright (c) 1997, 1998, 1999
00005     Preston Brown (preston.brown@yale.edu)
00006     Fester Zigterman (F.J.F.ZigtermanRustenburg@student.utwente.nl)
00007     Ian Dawes (iadawes@globalserve.net)
00008     Laszlo Boloni (boloni@cs.purdue.edu)
00009 
00010     Copyright (c) 2000, 2001, 2002, 2003, 2004
00011     Cornelius Schumacher <schumacher@kde.org>
00012     Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00013 
00014     This program is free software; you can redistribute it and/or modify
00015     it under the terms of the GNU General Public License as published by
00016     the Free Software Foundation; either version 2 of the License, or
00017     (at your option) any later version.
00018 
00019     This program is distributed in the hope that it will be useful,
00020     but WITHOUT ANY WARRANTY; without even the implied warranty of
00021     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00022     GNU General Public License for more details.
00023 
00024     You should have received a copy of the GNU General Public License
00025     along with this program; if not, write to the Free Software
00026     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00027 
00028     As a special exception, permission is given to link this program
00029     with any edition of Qt, and distribute the resulting executable,
00030     without including the source code for Qt in the source distribution.
00031 */
00032 
00033 #include "calendarview.h"
00034 
00035 #ifndef KORG_NOPRINTER
00036 #include "calprinter.h"
00037 #endif
00038 #include "koeventeditor.h"
00039 #include "kotodoeditor.h"
00040 #include "kojournaleditor.h"
00041 #include "koprefs.h"
00042 #include "koeventviewerdialog.h"
00043 #include "publishdialog.h"
00044 #include "koglobals.h"
00045 #include "koviewmanager.h"
00046 #include "koagendaview.h"
00047 #include "kodialogmanager.h"
00048 #include "statusdialog.h"
00049 #include "datenavigatorcontainer.h"
00050 #include "kotodoview.h"
00051 #include "datenavigator.h"
00052 #include "resourceview.h"
00053 #include "navigatorbar.h"
00054 #include "history.h"
00055 #include "kogroupware.h"
00056 #include "freebusymanager.h"
00057 #include "komonthview.h"
00058 #include "datechecker.h"
00059 #include "komessagebox.h"
00060 #include "exportwebdialog.h"
00061 #include "kocorehelper.h"
00062 #include "incidencechanger.h"
00063 #include "kholidays.h"
00064 #include "mailscheduler.h"
00065 #include "komailclient.h"
00066 #include "multiagendaview.h"
00067 
00068 #include <libkcal/vcaldrag.h>
00069 #include <libkcal/icaldrag.h>
00070 #include <libkcal/icalformat.h>
00071 #include <libkcal/vcalformat.h>
00072 #include <libkcal/scheduler.h>
00073 #include <libkcal/calendarlocal.h>
00074 #include <libkcal/journal.h>
00075 #include <libkcal/calfilter.h>
00076 #include <libkcal/attendee.h>
00077 #include <libkcal/dndfactory.h>
00078 #include <libkcal/freebusy.h>
00079 #include <libkcal/filestorage.h>
00080 #include <libkcal/calendarresources.h>
00081 #include <libkcal/calendarnull.h>
00082 #include <libkcal/htmlexportsettings.h>
00083 
00084 #include <kglobal.h>
00085 #include <kdebug.h>
00086 #include <kstandarddirs.h>
00087 #include <kfiledialog.h>
00088 #include <kmessagebox.h>
00089 #include <knotifyclient.h>
00090 #include <kconfig.h>
00091 #include <krun.h>
00092 #include <kdirwatch.h>
00093 
00094 #include <qapplication.h>
00095 #include <qclipboard.h>
00096 #include <qcursor.h>
00097 #include <qmultilineedit.h>
00098 #include <qtimer.h>
00099 #include <qwidgetstack.h>
00100 #include <qptrlist.h>
00101 #include <qfile.h>
00102 #include <qlayout.h>
00103 #ifndef KORG_NOSPLITTER
00104 #include <qsplitter.h>
00105 #endif
00106 #include <qvbox.h>
00107 #include <qwhatsthis.h>
00108 
00109 #include <stdlib.h>
00110 #include <assert.h>
00111 
00112 using namespace KOrg;
00113 
00114 CalendarView::CalendarView( QWidget *parent, const char *name )
00115   : CalendarViewBase( parent, name ),
00116     mHistory( 0 ),
00117     mCalendar( CalendarNull::self() ),
00118     mChanger( 0 )
00119 {
00120   kdDebug(5850) << "CalendarView::CalendarView( Calendar )" << endl;
00121 
00122   mViewManager = new KOViewManager( this );
00123   mDialogManager = new KODialogManager( this );
00124 
00125   mModified = false;
00126   mReadOnly = false;
00127   mSelectedIncidence = 0;
00128 
00129   mFilters.setAutoDelete( true );
00130 
00131   mExtensions.setAutoDelete( true );
00132 
00133   mNavigator = new DateNavigator( this );
00134   mDateChecker = new DateChecker( this );
00135 
00136   QBoxLayout *topLayout = new QVBoxLayout( this );
00137 
00138 #ifndef KORG_NOSPLITTER
00139   // create the main layout frames.
00140   mPanner = new QSplitter( QSplitter::Horizontal, this,
00141                            "CalendarView::Panner" );
00142   topLayout->addWidget( mPanner );
00143 
00144   mLeftSplitter = new QSplitter( QSplitter::Vertical, mPanner,
00145                                  "CalendarView::LeftFrame" );
00146 //  mPanner->setResizeMode( mLeftSplitter, QSplitter::Stretch );
00147 
00148   mDateNavigator = new DateNavigatorContainer( mLeftSplitter,
00149                                                "CalendarView::DateNavigator" );
00150 
00151 //  mLeftSplitter->setResizeMode( mDateNavigator, QSplitter::Stretch );
00152   mLeftSplitter->setCollapsible( mDateNavigator, true );
00153   mTodoList = new KOTodoView( CalendarNull::self(), mLeftSplitter, "todolist" );
00154 
00155   mEventViewer = new KOEventViewer( CalendarNull::self(), mLeftSplitter,"EventViewer" );
00156 
00157   QVBox *rightBox = new QVBox( mPanner );
00158   mNavigatorBar = new NavigatorBar( rightBox );
00159   mRightFrame = new QWidgetStack( rightBox );
00160   rightBox->setStretchFactor( mRightFrame, 1 );
00161 
00162   mLeftFrame = mLeftSplitter;
00163 #else
00164   QWidget *mainBox;
00165   QWidget *leftFrame;
00166 
00167   if ( KOPrefs::instance()->mVerticalScreen ) {
00168     mainBox = new QVBox( this );
00169     leftFrame = new QHBox( mainBox );
00170   } else {
00171     mainBox = new QHBox( this );
00172     leftFrame = new QVBox( mainBox );
00173   }
00174 
00175   topLayout->addWidget( mainBox );
00176 
00177   mDateNavigator = new KDateNavigator( leftFrame, true,
00178                                        "CalendarView::DateNavigator",
00179                                        QDate::currentDate() );
00180   mTodoList = new KOTodoView( CalendarNull::self(), leftFrame, "todolist" );
00181 
00182   mEventViewer = new KOEventViewer ( CalendarNull::self(), leftFrame, "EventViewer" );
00183 
00184   QWidget *rightBox = new QWidget( mainBox );
00185   QBoxLayout *rightLayout = new QVBoxLayout( rightBox );
00186 
00187   mNavigatorBar = new NavigatorBar( QDate::currentDate(), rightBox );
00188   rightLayout->addWidget( mNavigatorBar );
00189 
00190   mRightFrame = new QWidgetStack( rightBox );
00191   rightLayout->addWidget( mRightFrame );
00192 
00193   mLeftFrame = leftFrame;
00194 
00195   if ( KOPrefs::instance()->mVerticalScreen ) {
00196 //    mTodoList->setFixedHeight( 60 );
00197     mTodoList->setFixedHeight( mDateNavigator->sizeHint().height() );
00198   }
00199 #endif
00200 
00201   connect( mNavigator, SIGNAL( datesSelected( const KCal::DateList & ) ),
00202            SLOT( showDates( const KCal::DateList & ) ) );
00203   connect( mNavigator, SIGNAL( datesSelected( const KCal::DateList & ) ),
00204            mDateNavigator, SLOT( selectDates( const KCal::DateList & ) ) );
00205 
00206   connect( mNavigatorBar, SIGNAL( goPrevYear() ),
00207            mNavigator, SLOT( selectPreviousYear() ) );
00208   connect( mNavigatorBar, SIGNAL( goNextYear() ),
00209            mNavigator, SLOT( selectNextYear() ) );
00210   connect( mNavigatorBar, SIGNAL( goPrevMonth() ),
00211            mNavigator, SLOT( selectPreviousMonth() ) );
00212   connect( mNavigatorBar, SIGNAL( goNextMonth() ),
00213            mNavigator, SLOT( selectNextMonth() ) );
00214   connect( mNavigatorBar, SIGNAL( goMonth(int) ),
00215            mNavigator, SLOT( selectMonth(int) ) );
00216 
00217   connect( mNavigator, SIGNAL( datesSelected( const KCal::DateList & ) ),
00218            mNavigatorBar, SLOT( selectDates( const KCal::DateList & ) ) );
00219 
00220   connect( mDateNavigator, SIGNAL( weekClicked( const QDate & ) ),
00221            mNavigator, SLOT( selectWeek( const QDate & ) ) );
00222 
00223   connect( mDateNavigator, SIGNAL( goPrevYear() ),
00224            mNavigator, SLOT( selectPreviousYear() ) );
00225   connect( mDateNavigator, SIGNAL( goNextYear() ),
00226            mNavigator, SLOT( selectNextYear() ) );
00227   connect( mDateNavigator, SIGNAL( goPrevMonth() ),
00228            mNavigator, SLOT( selectPreviousMonth() ) );
00229   connect( mDateNavigator, SIGNAL( goNextMonth() ),
00230            mNavigator, SLOT( selectNextMonth() ) );
00231   connect( mDateNavigator, SIGNAL( goMonth(int) ),
00232            mNavigator, SLOT( selectMonth(int) ) );
00233 
00234   connect( mDateNavigator, SIGNAL( goPrevious() ),
00235            mNavigator, SLOT( selectPrevious() ) );
00236   connect( mDateNavigator, SIGNAL( goNext() ),
00237            mNavigator, SLOT( selectNext() ) );
00238 
00239   connect( mDateNavigator, SIGNAL( datesSelected( const KCal::DateList & ) ),
00240            mNavigator, SLOT( selectDates( const KCal::DateList & ) ) );
00241 
00242   connect( mDateNavigator, SIGNAL(incidenceDropped(Incidence*, const QDate&)),
00243            SLOT( addIncidenceOn( Incidence *, const QDate & ) ) );
00244   connect( mDateNavigator, SIGNAL(incidenceDroppedMove(Incidence*,const QDate&)),
00245            SLOT( moveIncidenceTo( Incidence *, const QDate & ) ) );
00246 
00247   connect( mDateChecker, SIGNAL( dayPassed( const QDate & ) ),
00248            mTodoList, SLOT( dayPassed( const QDate & ) ) );
00249   connect( mDateChecker, SIGNAL( dayPassed( const QDate & ) ),
00250            SIGNAL( dayPassed( const QDate & ) ) );
00251   connect( mDateChecker, SIGNAL( dayPassed( const QDate & ) ),
00252            mDateNavigator, SLOT( updateToday() ) );
00253 
00254   connect( this, SIGNAL( configChanged() ),
00255            mDateNavigator, SLOT( updateConfig() ) );
00256 
00257   connect( this, SIGNAL( incidenceSelected(Incidence *, const QDate &) ),
00258            mEventViewer, SLOT ( setIncidence (Incidence *, const QDate &) ) );
00259 
00260   //TODO: do a pretty Summary,
00261   QString s;
00262   s = i18n( "<p><em>No Item Selected</em></p>"
00263            "<p>Select an event, to-do or journal entry to view its details "
00264            "here.</p>");
00265 
00266   mEventViewer->setDefaultText( s );
00267   QWhatsThis::add( mEventViewer,
00268                    i18n( "View the details of events, journal entries or to-dos "
00269                          "selected in KOrganizer's main view here." ) );
00270   mEventViewer->setIncidence( 0, QDate() );
00271 
00272   mViewManager->connectTodoView( mTodoList );
00273   mViewManager->connectView( mTodoList );
00274 
00275   KOGlobals::self()->
00276       setHolidays( new KHolidays( KOPrefs::instance()->mHolidays ) );
00277 
00278   connect( QApplication::clipboard(), SIGNAL( dataChanged() ),
00279            SLOT( checkClipboard() ) );
00280 
00281   connect( mTodoList, SIGNAL( incidenceSelected( Incidence *,const QDate & ) ),
00282            SLOT( processTodoListSelection( Incidence *,const QDate & ) ) );
00283   disconnect( mTodoList, SIGNAL( incidenceSelected( Incidence *,const QDate & ) ),
00284            this, SLOT( processMainViewSelection( Incidence *,const QDate & ) ) );
00285 
00286   kdDebug(5850) << "CalendarView::CalendarView() done" << endl;
00287 }
00288 
00289 CalendarView::~CalendarView()
00290 {
00291   kdDebug(5850) << "~CalendarView()" << endl;
00292 
00293   mCalendar->unregisterObserver( this );
00294 
00295   delete mDialogManager;
00296   delete mViewManager;
00297   delete mEventViewer;
00298   kdDebug(5850) << "~CalendarView() done" << endl;
00299 }
00300 
00301 void CalendarView::setCalendar( Calendar *cal )
00302 {
00303   kdDebug(5850)<<"CalendarView::setCalendar"<<endl;
00304   mCalendar = cal;
00305 
00306   delete mHistory;
00307   mHistory = new History( mCalendar );
00308   connect( mHistory, SIGNAL( undone() ), SLOT( updateView() ) );
00309   connect( mHistory, SIGNAL( redone() ), SLOT( updateView() ) );
00310 
00311   if ( mChanger ) delete mChanger;
00312   setIncidenceChanger( new IncidenceChanger( mCalendar, this ) );
00313 
00314   mCalendar->registerObserver( this );
00315 
00316   mDateNavigator->setCalendar( mCalendar );
00317 
00318   mTodoList->setCalendar( mCalendar );
00319 
00320   mEventViewer->setCalendar( mCalendar );
00321 }
00322 
00323 void CalendarView::setIncidenceChanger( IncidenceChangerBase *changer )
00324 {
00325   mChanger = changer;
00326   emit newIncidenceChanger( mChanger );
00327   connect( mChanger, SIGNAL( incidenceAdded( Incidence* ) ),
00328            this, SLOT( incidenceAdded( Incidence* ) ) );
00329   connect( mChanger, SIGNAL( incidenceChanged( Incidence*, Incidence*, KOGlobals::WhatChanged ) ),
00330            this, SLOT( incidenceChanged( Incidence*, Incidence*, KOGlobals::WhatChanged ) ) );
00331   connect( mChanger, SIGNAL( incidenceToBeDeleted( Incidence * ) ),
00332            this, SLOT( incidenceToBeDeleted( Incidence * ) ) );
00333   connect( mChanger, SIGNAL( incidenceDeleted( Incidence * ) ),
00334            this, SLOT( incidenceDeleted( Incidence * ) ) );
00335 
00336   connect( mChanger, SIGNAL( schedule( Scheduler::Method, Incidence*) ),
00337            this, SLOT( schedule( Scheduler::Method, Incidence*) ) );
00338 
00339 
00340   connect( this, SIGNAL( cancelAttendees( Incidence * ) ),
00341            mChanger, SLOT( cancelAttendees( Incidence * ) ) );
00342 }
00343 
00344 Calendar *CalendarView::calendar()
00345 {
00346   if ( mCalendar ) return mCalendar;
00347   else return CalendarNull::self();
00348 }
00349 
00350 KOIncidenceEditor *CalendarView::editorDialog( Incidence *incidence ) const
00351 {
00352   if (mDialogList.find(incidence) != mDialogList.end ())
00353     return mDialogList[incidence];
00354   else return 0;
00355 }
00356 
00357 QDate CalendarView::activeDate( bool fallbackToToday )
00358 {
00359   KOrg::BaseView *curView = mViewManager->currentView();
00360   if ( curView ) {
00361     // Try the view's selectedDates()
00362     if ( !curView->selectedDates().isEmpty() ) {
00363       if ( curView->selectedDates().first().isValid() ) {
00364         return curView->selectedDates().first();
00365       }
00366     }
00367   }
00368 
00369   // When all else fails, use the navigator start date, or today.
00370   if ( fallbackToToday ) {
00371     return QDate::currentDate();
00372   } else {
00373     return QDate();
00374     //mDateNavigator->selectedDates().first();
00375   }
00376 }
00377 
00378 QDate CalendarView::startDate()
00379 {
00380   DateList dates = mNavigator->selectedDates();
00381 
00382   return dates.first();
00383 }
00384 
00385 QDate CalendarView::endDate()
00386 {
00387   DateList dates = mNavigator->selectedDates();
00388 
00389   return dates.last();
00390 }
00391 
00392 
00393 bool CalendarView::openCalendar(const QString& filename, bool merge)
00394 {
00395   kdDebug(5850) << "CalendarView::openCalendar(): " << filename << endl;
00396 
00397   if (filename.isEmpty()) {
00398     kdDebug(5850) << "CalendarView::openCalendar(): Error! Empty filename." << endl;
00399     return false;
00400   }
00401 
00402   if (!QFile::exists(filename)) {
00403     kdDebug(5850) << "CalendarView::openCalendar(): Error! File '" << filename
00404               << "' doesn't exist." << endl;
00405   }
00406 
00407   bool loadedSuccesfully = true;
00408   if ( !merge ) {
00409     mCalendar->close();
00410     CalendarLocal *cl = dynamic_cast<CalendarLocal*>( mCalendar );
00411     if ( cl ) {
00412       loadedSuccesfully = cl->load( filename );
00413     } else {
00414       CalendarResources *cr = dynamic_cast<CalendarResources*>( mCalendar );
00415       assert( cr ); // otherwise something is majorly wrong
00416       // openCalendar called without merge and a filename, what should we do?
00417       return false;
00418     }
00419   } else {
00420     // merge in a file
00421     FileStorage storage( mCalendar );
00422     storage.setFileName( filename );
00423     loadedSuccesfully = storage.load();
00424   }
00425 
00426   if ( loadedSuccesfully ) {
00427     if ( merge )
00428       setModified( true );
00429     else {
00430       setModified( false );
00431       mViewManager->setDocumentId( filename );
00432       mTodoList->setDocumentId( filename );
00433     }
00434     updateCategories();
00435     updateView();
00436     return true;
00437   } else {
00438     // while failing to load, the calendar object could
00439     // have become partially populated.  Clear it out.
00440     if ( !merge ) mCalendar->close();
00441 
00442     KMessageBox::error(this,i18n("Could not load calendar '%1'.").arg(filename));
00443 
00444     return false;
00445   }
00446 }
00447 
00448 bool CalendarView::saveCalendar( const QString& filename )
00449 {
00450   kdDebug(5850) << "CalendarView::saveCalendar(): " << filename << endl;
00451 
00452   // Store back all unsaved data into calendar object
00453   mViewManager->currentView()->flushView();
00454 
00455   FileStorage storage( mCalendar );
00456   storage.setFileName( filename );
00457   storage.setSaveFormat( new ICalFormat );
00458 
00459   bool success = storage.save();
00460 
00461   if ( !success ) {
00462     return false;
00463   }
00464 
00465   return true;
00466 }
00467 
00468 void CalendarView::closeCalendar()
00469 {
00470   kdDebug(5850) << "CalendarView::closeCalendar()" << endl;
00471 
00472   // child windows no longer valid
00473   emit closingDown();
00474 
00475   mCalendar->close();
00476   setModified( false );
00477   updateView();
00478 }
00479 
00480 void CalendarView::archiveCalendar()
00481 {
00482   mDialogManager->showArchiveDialog();
00483 }
00484 
00485 
00486 void CalendarView::readSettings()
00487 {
00488 //  kdDebug(5850) << "CalendarView::readSettings()" << endl;
00489 
00490   QString str;
00491 
00492   // read settings from the KConfig, supplying reasonable
00493   // defaults where none are to be found
00494 
00495   KConfig *config = KOGlobals::self()->config();
00496 
00497 #ifndef KORG_NOSPLITTER
00498   config->setGroup( "KOrganizer Geometry" );
00499 
00500   QValueList<int> sizes = config->readIntListEntry( "Separator1" );
00501   if ( sizes.count() != 2 ) {
00502     sizes << mDateNavigator->minimumSizeHint().width();
00503     sizes << 300;
00504   }
00505   mPanner->setSizes( sizes );
00506 
00507   sizes = config->readIntListEntry( "Separator2" );
00508   mLeftSplitter->setSizes( sizes );
00509 #endif
00510 
00511   mEventViewer->readSettings( config );
00512 
00513   mViewManager->readSettings( config );
00514   mTodoList->restoreLayout( config, QString( "Todo Layout" ) );
00515 
00516   readFilterSettings( config );
00517 
00518   config->setGroup( "Views" );
00519   int dateCount = config->readNumEntry( "ShownDatesCount", 7 );
00520   if ( dateCount == 7 ) mNavigator->selectWeek();
00521   else mNavigator->selectDates( mNavigator->selectedDates().first(), dateCount );
00522 }
00523 
00524 
00525 void CalendarView::writeSettings()
00526 {
00527 //  kdDebug(5850) << "CalendarView::writeSettings" << endl;
00528 
00529   KConfig *config = KOGlobals::self()->config();
00530 
00531 #ifndef KORG_NOSPLITTER
00532   config->setGroup( "KOrganizer Geometry" );
00533 
00534   QValueList<int> list = mPanner->sizes();
00535   config->writeEntry( "Separator1", list );
00536 
00537   list = mLeftSplitter->sizes();
00538   config->writeEntry( "Separator2", list );
00539 #endif
00540   mEventViewer->writeSettings( config );
00541   mViewManager->writeSettings( config );
00542   mTodoList->saveLayout( config, QString( "Todo Layout" ) );
00543 
00544   KOPrefs::instance()->writeConfig();
00545 
00546   writeFilterSettings( config );
00547 
00548   config->setGroup( "Views" );
00549   config->writeEntry( "ShownDatesCount", mNavigator->selectedDates().count() );
00550 
00551   config->sync();
00552 }
00553 
00554 void CalendarView::readFilterSettings( KConfig *config )
00555 {
00556 //  kdDebug(5850) << "CalendarView::readFilterSettings()" << endl;
00557 
00558   mFilters.clear();
00559 
00560   config->setGroup( "General" );
00561   // FIXME: Move the filter loading and saving to the CalFilter class in libkcal
00562   QStringList filterList = config->readListEntry ("CalendarFilters" );
00563   QString currentFilter = config->readEntry( "Current Filter" );
00564 
00565   QStringList::ConstIterator it = filterList.begin();
00566   QStringList::ConstIterator end = filterList.end();
00567   while( it != end ) {
00568 //    kdDebug(5850) << "  filter: " << (*it) << endl;
00569     CalFilter *filter;
00570     filter = new CalFilter( *it );
00571     config->setGroup( "Filter_" + (*it) );
00572     filter->setCriteria( config->readNumEntry( "Criteria", 0 ) );
00573     filter->setCategoryList( config->readListEntry( "CategoryList" ) );
00574     if ( filter->criteria() & KCal::CalFilter::HideTodosWithoutAttendeeInEmailList )
00575       filter->setEmailList( KOPrefs::instance()->allEmails() );
00576     filter->setCompletedTimeSpan( config->readNumEntry( "HideTodoDays", 0 ) );
00577     mFilters.append( filter );
00578 
00579     ++it;
00580   }
00581 
00582   config->setGroup( "General" );
00583   int pos = filterList.findIndex( currentFilter );
00584   mCurrentFilter = 0;
00585   if ( pos>=0 ) {
00586     mCurrentFilter = mFilters.at( pos );
00587   }
00588   updateFilter();
00589 }
00590 
00591 void CalendarView::writeFilterSettings( KConfig *config )
00592 {
00593 //  kdDebug(5850) << "CalendarView::writeFilterSettings()" << endl;
00594 
00595   QStringList filterList;
00596 
00597   CalFilter *filter = mFilters.first();
00598   while( filter ) {
00599 //    kdDebug(5850) << " fn: " << filter->name() << endl;
00600     filterList << filter->name();
00601     config->setGroup( "Filter_" + filter->name() );
00602     config->writeEntry( "Criteria", filter->criteria() );
00603     config->writeEntry( "CategoryList", filter->categoryList() );
00604     config->writeEntry( "HideTodoDays", filter->completedTimeSpan() );
00605     filter = mFilters.next();
00606   }
00607   config->setGroup( "General" );
00608   config->writeEntry( "CalendarFilters", filterList );
00609   if ( mCurrentFilter ) {
00610     config->writeEntry( "Current Filter", mCurrentFilter->name() );
00611   } else {
00612     config->writeEntry( "Current Filter", QString::null );
00613   }
00614 }
00615 
00616 
00617 void CalendarView::goDate( const QDate& date )
00618 {
00619   mNavigator->selectDate( date );
00620 }
00621 
00622 void CalendarView::showDate(const QDate & date)
00623 {
00624   int dateCount = mNavigator->datesCount();
00625   if ( dateCount == 7 )
00626     mNavigator->selectWeek( date );
00627   else
00628     mNavigator->selectDates( date, dateCount );
00629 }
00630 
00631 void CalendarView::goToday()
00632 {
00633   mNavigator->selectToday();
00634 }
00635 
00636 void CalendarView::goNext()
00637 {
00638   if ( dynamic_cast<KOMonthView*>( mViewManager->currentView() ) )
00639     mNavigator->selectNextMonth();
00640   else
00641     mNavigator->selectNext();
00642 }
00643 
00644 void CalendarView::goPrevious()
00645 {
00646   if ( dynamic_cast<KOMonthView*>( mViewManager->currentView() ) )
00647     mNavigator->selectPreviousMonth();
00648   else
00649     mNavigator->selectPrevious();
00650 }
00651 
00652 void CalendarView::updateConfig( const QCString& receiver)
00653 {
00654   if ( receiver != "korganizer" ) return;
00655   kdDebug(5850) << "CalendarView::updateConfig()" << endl;
00656 
00657   KOGlobals::self()->
00658     setHolidays( new KHolidays( KOPrefs::instance()->mHolidays ) );
00659 
00660   QString tz(  mCalendar->timeZoneId() );
00661   // Only set a new time zone if it changed. This prevents the window
00662   // from being modified on start
00663   if ( tz != KOPrefs::instance()->mTimeZoneId ) {
00664 
00665     const QString question( i18n("The timezone setting was changed. Do you want to keep the absolute time of "
00666                                 "the items in your calendar, which will show them to be at a different time than "
00667                                 "before, or move them to be at the old time also in the new timezone?") );
00668     int rc = KMessageBox::questionYesNo( this, question,
00669                               i18n("Keep Absolute Times?"),
00670                               KGuiItem(i18n("Keep Times")),
00671                               KGuiItem(i18n("Move Times")),
00672                               "calendarKeepAbsoluteTimes");
00673     if ( rc == KMessageBox::Yes ) {
00674       // user wants us to shift
00675       mCalendar->setTimeZoneIdViewOnly( KOPrefs::instance()->mTimeZoneId );
00676     } else {
00677       // only set the new timezone, wihtout shifting events, they will be
00678       // interpreted as being in the new timezone now
00679       mCalendar->setTimeZoneId( KOPrefs::instance()->mTimeZoneId );
00680     }
00681   }
00682   emit configChanged();
00683 
00684   // force reload and handle agenda view type switch
00685   const bool showMerged = KOPrefs::instance()->agendaViewCalendarDisplay() == KOPrefs::CalendarsMerged;
00686   const bool showSideBySide = KOPrefs::instance()->agendaViewCalendarDisplay() == KOPrefs::CalendarsSideBySide;
00687   KOrg::BaseView *view = mViewManager->currentView();
00688   mViewManager->showAgendaView();
00689   if ( view == mViewManager->agendaView() && showSideBySide )
00690     view = mViewManager->multiAgendaView();
00691   else if ( view == mViewManager->multiAgendaView() && showMerged )
00692     view = mViewManager->agendaView();
00693   mViewManager->showView( view );
00694 
00695   // To make the "fill window" configurations work
00696   mViewManager->raiseCurrentView();
00697 }
00698 
00699 
00700 void CalendarView::incidenceAdded( Incidence *incidence )
00701 {
00702   setModified( true );
00703   history()->recordAdd( incidence );
00704   changeIncidenceDisplay( incidence, KOGlobals::INCIDENCEADDED );
00705   updateUnmanagedViews();
00706   checkForFilteredChange( incidence );
00707 }
00708 
00709 void CalendarView::incidenceChanged( Incidence *oldIncidence,
00710                                      Incidence *newIncidence,
00711                                      KOGlobals::WhatChanged modification )
00712 {
00713   KOIncidenceEditor *tmp = editorDialog( newIncidence );
00714   if ( tmp ) {
00715     kdDebug(5850) << "Incidence modified and open" << endl;
00716     tmp->modified();
00717   }
00718   setModified( true );
00719   history()->recordEdit( oldIncidence, newIncidence );
00720 
00721   // Record completed todos in journals, if enabled. we should to this here in
00722   // favour of the todolist. users can mark a task as completed in an editor
00723   // as well.
00724   if ( newIncidence->type() == "Todo" &&
00725        KOPrefs::instance()->recordTodosInJournals() &&
00726        ( modification == KOGlobals::COMPLETION_MODIFIED ||
00727          modification == KOGlobals::COMPLETION_MODIFIED_WITH_RECURRENCE ) ) {
00728 
00729       Todo *todo = static_cast<Todo *>(newIncidence);
00730       if ( todo->isCompleted() ||
00731            modification == KOGlobals::COMPLETION_MODIFIED_WITH_RECURRENCE ) {
00732         QString timeStr = KGlobal::locale()->formatTime( QTime::currentTime() );
00733         QString description = i18n( "To-do completed: %1 (%2)" ).arg(
00734           newIncidence->summary() ).arg( timeStr );
00735 
00736         Journal::List journals = calendar()->journals( QDate::currentDate() );
00737         Journal *journal;
00738 
00739         if ( journals.isEmpty() ) {
00740           journal = new Journal();
00741           journal->setDtStart( QDateTime::currentDateTime() );
00742 
00743           QString dateStr = KGlobal::locale()->formatDate( QDate::currentDate() );
00744           journal->setSummary( i18n("Journal of %1").arg( dateStr ) );
00745           journal->setDescription( description );
00746 
00747           if ( !mChanger->addIncidence( journal, this ) ) {
00748             KODialogManager::errorSaveIncidence( this, journal );
00749             delete journal;
00750             return;
00751           }
00752 
00753         } else { // journal list is not empty
00754           journal = *(journals.at(0));
00755           Journal *oldJournal = journal->clone();
00756           journal->setDescription( journal->description().append( "\n" + description ) );
00757 
00758           if ( !mChanger->changeIncidence( oldJournal, journal,
00759                                            KOGlobals::DESCRIPTION_MODIFIED, this ) ) {
00760             KODialogManager::errorSaveIncidence( this, journal );
00761             delete journal;
00762             return;
00763           }
00764         }
00765       }
00766   }
00767 
00768   changeIncidenceDisplay( newIncidence, KOGlobals::INCIDENCEEDITED );
00769   updateUnmanagedViews();
00770   checkForFilteredChange( newIncidence );
00771 }
00772 
00773 void CalendarView::incidenceToBeDeleted( Incidence *incidence )
00774 {
00775   KOIncidenceEditor *tmp = editorDialog( incidence );
00776   if (tmp) {
00777     kdDebug(5850) << "Incidence to be deleted and open in editor" << endl;
00778     tmp->delayedDestruct();
00779   }
00780   setModified( true );
00781   history()->recordDelete( incidence );
00782 //  changeIncidenceDisplay( incidence, KOGlobals::INCIDENCEDELETED );
00783   updateUnmanagedViews();
00784 }
00785 
00786 void CalendarView::incidenceDeleted( Incidence *incidence )
00787 {
00788   changeIncidenceDisplay( incidence, KOGlobals::INCIDENCEDELETED );
00789   updateUnmanagedViews();
00790 }
00791 
00792 void CalendarView::checkForFilteredChange( Incidence *incidence )
00793 {
00794   CalFilter *filter = calendar()->filter();
00795   if ( filter && !filter->filterIncidence( incidence ) ) {
00796     // Incidence is filtered and thus not shown in the view, tell the
00797     // user so that he isn't surprised if his new event doesn't show up
00798     KMessageBox::information( this, i18n("The item \"%1\" is filtered by "
00799                  "your current filter rules, so it will be hidden and not "
00800                  "appear in the view.").arg( incidence->summary() ),
00801                  i18n("Filter Applied"), "ChangedIncidenceFiltered" );
00802   }
00803 }
00804 
00805 void CalendarView::startMultiModify( const QString &text )
00806 {
00807   history()->startMultiModify( text );
00808 }
00809 
00810 void CalendarView::endMultiModify()
00811 {
00812   history()->endMultiModify();
00813 }
00814 
00815 
00816 void CalendarView::changeIncidenceDisplay( Incidence *incidence, int action )
00817 {
00818   mDateNavigator->updateView();
00819   mDialogManager->updateSearchDialog();
00820 
00821   if ( incidence ) {
00822     // If there is an event view visible update the display
00823     mViewManager->currentView()->changeIncidenceDisplay( incidence, action );
00824     if ( mTodoList ) mTodoList->changeIncidenceDisplay( incidence, action );
00825     mEventViewer->changeIncidenceDisplay( incidence, activeDate( true ), action );
00826   } else {
00827     mViewManager->currentView()->updateView();
00828     if ( mTodoList ) mTodoList->updateView();
00829   }
00830 }
00831 
00832 
00833 void CalendarView::updateView(const QDate &start, const QDate &end)
00834 {
00835   mTodoList->updateView();
00836   mViewManager->updateView(start, end);
00837   mDateNavigator->updateView();
00838 }
00839 
00840 void CalendarView::updateView()
00841 {
00842   DateList tmpList = mNavigator->selectedDates();
00843 
00844   // We assume that the navigator only selects consecutive days.
00845   updateView( tmpList.first(), tmpList.last() );
00846 }
00847 
00848 void CalendarView::updateUnmanagedViews()
00849 {
00850   mDateNavigator->updateDayMatrix();
00851 }
00852 
00853 int CalendarView::msgItemDelete( Incidence *incidence )
00854 {
00855   return KMessageBox::warningContinueCancel(this,
00856       i18n("The item \"%1\" will be permanently deleted.").arg( incidence->summary() ),
00857       i18n("KOrganizer Confirmation"), KGuiItem(i18n("&Delete"),"editdelete"));
00858 }
00859 
00860 
00861 void CalendarView::edit_cut()
00862 {
00863   Incidence *incidence = selectedIncidence();
00864 
00865   if ( !incidence || !mChanger ) {
00866     KNotifyClient::beep();
00867     return;
00868   }
00869   mChanger->cutIncidence( incidence, this );
00870 }
00871 
00872 void CalendarView::edit_copy()
00873 {
00874   Incidence *incidence = selectedIncidence();
00875 
00876   if (!incidence) {
00877     KNotifyClient::beep();
00878     return;
00879   }
00880   DndFactory factory( mCalendar );
00881   if ( !factory.copyIncidence( incidence ) ) {
00882     KNotifyClient::beep();
00883   }
00884 }
00885 
00886 void CalendarView::edit_paste()
00887 {
00888 // If in agenda view, use the selected time and date from there.
00889 // In all other cases, paste the event on the first day of the
00890 // selection in the day matrix on the left
00891 
00892   QDate date;
00893   // create an invalid time to check if we got a new time for the eevent
00894   QTime time(-1,-1);
00895   QDateTime startDT, endDT;
00896   bool useEndTime = false;
00897 
00898   KOAgendaView *aView = mViewManager->agendaView();
00899   if (aView && aView->selectionStart().isValid()) {
00900       date = aView->selectionStart().date();
00901     startDT = aView->selectionStart();
00902     endDT = aView->selectionEnd();
00903     useEndTime = !aView->selectedIsSingleCell();
00904     if (!aView->selectedIsAllDay()) {
00905         time = aView->selectionStart().time();
00906     }
00907 
00908   } else {
00909     date = mNavigator->selectedDates().first();
00910   }
00911 
00912   DndFactory factory( mCalendar );
00913   Incidence *pastedIncidence;
00914   if (time.isValid())
00915     pastedIncidence = factory.pasteIncidence( date, &time );
00916   else
00917     pastedIncidence = factory.pasteIncidence( date );
00918   if ( !pastedIncidence ) return;
00919 
00920   // FIXME: use a visitor here
00921   if (pastedIncidence->type() == "Event" ) {
00922 
00923     Event* pastedEvent = static_cast<Event*>(pastedIncidence);
00924     // only use selected area if event is of the same type (all-day or non-all-day
00925     // as the current selection is
00926     if ( aView && endDT.isValid() && useEndTime ) {
00927       if ( (pastedEvent->doesFloat() && aView->selectedIsAllDay()) ||
00928            (!pastedEvent->doesFloat() && ! aView->selectedIsAllDay()) ) {
00929         pastedEvent->setDtEnd(endDT);
00930       }
00931     }
00932     mChanger->addIncidence( pastedEvent, this );
00933 
00934   } else if ( pastedIncidence->type() == "Todo" ) {
00935     Todo* pastedTodo = static_cast<Todo*>(pastedIncidence);
00936     Todo* _selectedTodo = selectedTodo();
00937     if ( _selectedTodo )
00938       pastedTodo->setRelatedTo( _selectedTodo );
00939     mChanger->addIncidence( pastedTodo, this );
00940   }
00941 }
00942 
00943 void CalendarView::edit_options()
00944 {
00945   mDialogManager->showOptionsDialog();
00946 }
00947 
00948 void CalendarView::dateTimesForNewEvent( QDateTime &startDt, QDateTime &endDt, bool &allDay )
00949 {
00950   if ( !startDt.isValid() ) {
00951     // Default start is the first selected date with the preferred time as set
00952     // in the config dlg.
00953     if ( !startDt.date().isValid() ) {
00954       startDt.setDate( mNavigator->selectedDates().first() );
00955     }
00956     if ( !startDt.time().isValid() ) {
00957       startDt.setTime( KOPrefs::instance()->mStartTime.time() );
00958     }
00959   }
00960   if ( !endDt.isValid() ) {
00961     int addSecs = ( KOPrefs::instance()->mDefaultDuration.time().hour()*3600 ) +
00962                   ( KOPrefs::instance()->mDefaultDuration.time().minute()*60 );
00963     endDt = startDt.addSecs( addSecs );
00964   }
00965   mViewManager->currentView()->eventDurationHint( startDt, endDt, allDay );
00966 }
00967 
00968 KOEventEditor *CalendarView::newEventEditor( const QDateTime &startDtParam,
00969      const QDateTime &endDtParam, bool allDayParam)
00970 {
00971   // let the current view change the default start/end datetime
00972   bool allDay = allDayParam;
00973   QDateTime startDt( startDtParam ), endDt( endDtParam );
00974   // Adjust the start/end date times (i.e. replace invalid values by defaults,
00975   // and let the view adjust the type.
00976   dateTimesForNewEvent( startDt, endDt, allDay );
00977 
00978   KOEventEditor *eventEditor = mDialogManager->getEventEditor();
00979   eventEditor->newEvent();
00980   connectIncidenceEditor( eventEditor );
00981   eventEditor->setDates( startDt, endDt, allDay );
00982   mDialogManager->connectTypeAhead( eventEditor, dynamic_cast<KOrg::AgendaView*>(viewManager()->currentView()) );
00983   return eventEditor;
00984 }
00985 
00986 
00987 
00988 
00989 void CalendarView::newEvent()
00990 {
00991   kdDebug(5850) << "CalendarView::newEvent()" << endl;
00992   newEvent( QDateTime(), QDateTime() );
00993 }
00994 
00995 void CalendarView::newEvent( const QDate &dt )
00996 {
00997   QDateTime startDt( dt, KOPrefs::instance()->mStartTime.time() );
00998   return newEvent( QDateTime( dt ), QDateTime() );
00999 }
01000 
01001 void CalendarView::newEvent( const QDateTime &startDt )
01002 {
01003   return newEvent( startDt, QDateTime() );
01004 }
01005 
01006 void CalendarView::newEvent( const QDateTime &startDt, const QDateTime &endDt,
01007                              bool allDay )
01008 {
01009   KOEventEditor *eventEditor = newEventEditor( startDt, endDt, allDay );
01010   eventEditor->show();
01011 }
01012 
01013 void CalendarView::newEvent( const QString &summary, const QString &description,
01014                              const QStringList &attachments, const QStringList &attendees,
01015                              const QStringList &attachmentMimetypes, bool inlineAttachment )
01016 {
01017   KOEventEditor *eventEditor = newEventEditor();
01018   eventEditor->setTexts( summary, description );
01019   // if attach or attendee list is empty, these methods don't do anything, so
01020   // it's save to call them in every case
01021   eventEditor->addAttachments( attachments, attachmentMimetypes, inlineAttachment );
01022   eventEditor->addAttendees( attendees );
01023   eventEditor->show();
01024 }
01025 
01026 void CalendarView::newTodo( const QString &summary, const QString &description,
01027                             const QStringList &attachments, const QStringList &attendees,
01028                             const QStringList &attachmentMimetypes,
01029                             bool inlineAttachment, bool isTask )
01030 {
01031   kdDebug(5850) << k_funcinfo << endl;
01032   KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01033   connectIncidenceEditor( todoEditor );
01034   todoEditor->newTodo();
01035   todoEditor->setTexts( summary, description );
01036   todoEditor->addAttachments( attachments, attachmentMimetypes, inlineAttachment );
01037   todoEditor->addAttendees( attendees );
01038   todoEditor->selectCreateTask( isTask );
01039   todoEditor->show();
01040 }
01041 
01042 void CalendarView::newTodo()
01043 {
01044   kdDebug(5850) << k_funcinfo << endl;
01045   QDateTime dtDue;
01046   bool allday = true;
01047   KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01048   connectIncidenceEditor( todoEditor );
01049   todoEditor->newTodo();
01050   if ( mViewManager->currentView()->isEventView() ) {
01051     dtDue.setDate( mNavigator->selectedDates().first() );
01052     QDateTime dtDummy = QDateTime::currentDateTime();
01053     mViewManager->currentView()->
01054       eventDurationHint( dtDue, dtDummy, allday );
01055     todoEditor->setDates( dtDue, allday );
01056   }
01057   todoEditor->show();
01058 }
01059 
01060 void CalendarView::newTodo( const QDate &date )
01061 {
01062   KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01063   connectIncidenceEditor( todoEditor );
01064   todoEditor->newTodo();
01065   todoEditor->setDates( QDateTime( date, QTime::currentTime() ), true );
01066   todoEditor->show();
01067 }
01068 
01069 void CalendarView::newJournal()
01070 {
01071   kdDebug(5850) << "CalendarView::newJournal()" << endl;
01072   newJournal( QString::null, QDate() );
01073 }
01074 
01075 void CalendarView::newJournal( const QDate &date)
01076 {
01077   newJournal( QString::null, date );
01078 }
01079 
01080 void CalendarView::newJournal( const QString &text, const QDate &date )
01081 {
01082   KOJournalEditor *journalEditor = mDialogManager->getJournalEditor();
01083   connectIncidenceEditor( journalEditor );
01084   journalEditor->newJournal();
01085   journalEditor->setTexts( text );
01086   if ( !date.isValid() ) {
01087     journalEditor->setDate( mNavigator->selectedDates().first() );
01088   } else {
01089     journalEditor->setDate( date );
01090   }
01091   journalEditor->show();
01092 }
01093 
01094 void CalendarView::newSubTodo()
01095 {
01096   Todo *todo = selectedTodo();
01097   if ( todo ) newSubTodo( todo );
01098 }
01099 
01100 void CalendarView::newSubTodo(Todo *parentEvent)
01101 {
01102   KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01103   connectIncidenceEditor( todoEditor );
01104   todoEditor->newTodo();
01105   todoEditor->setDates( QDateTime(), false, parentEvent );
01106   todoEditor->show();
01107 }
01108 
01109 void CalendarView::newFloatingEvent()
01110 {
01111   DateList tmpList = mNavigator->selectedDates();
01112   QDate date = tmpList.first();
01113 
01114   newEvent( QDateTime( date, QTime( 12, 0, 0 ) ),
01115             QDateTime( date, QTime( 12, 0, 0 ) ), true );
01116 }
01117 
01118 bool CalendarView::addIncidence( const QString &ical )
01119 {
01120   kdDebug(5850) << "CalendarView::addIncidence:\n" << ical << endl;
01121   ICalFormat format;
01122   format.setTimeZone( mCalendar->timeZoneId(), true );
01123   Incidence *incidence = format.fromString( ical );
01124   if ( !incidence ) return false;
01125   if ( !mChanger->addIncidence( incidence, this ) ) {
01126     delete incidence;
01127     return false;
01128   }
01129   return true;
01130 }
01131 
01132 void CalendarView::appointment_show()
01133 {
01134   Incidence *incidence = selectedIncidence();
01135   if (incidence)
01136     showIncidence( incidence );
01137   else
01138     KNotifyClient::beep();
01139 }
01140 
01141 void CalendarView::appointment_edit()
01142 {
01143   Incidence *incidence = selectedIncidence();
01144   if (incidence)
01145     editIncidence( incidence );
01146   else
01147     KNotifyClient::beep();
01148 }
01149 
01150 void CalendarView::appointment_delete()
01151 {
01152   Incidence *incidence = selectedIncidence();
01153   if (incidence)
01154     deleteIncidence( incidence );
01155   else
01156     KNotifyClient::beep();
01157 }
01158 
01159 void CalendarView::todo_unsub()
01160 {
01161   Todo *anTodo = selectedTodo();
01162   if( todo_unsub (anTodo ) ) {
01163     updateView();
01164   }
01165 }
01166 
01167 bool CalendarView::todo_unsub( Todo *todo )
01168 {
01169   bool status= false;
01170   if ( !todo || !todo->relatedTo() ) return false;
01171 
01172   if ( mChanger->beginChange( todo ) ) {
01173       Todo *oldTodo = todo->clone();
01174       todo->setRelatedTo(0);
01175       mChanger->changeIncidence( oldTodo, todo, KOGlobals::RELATION_MODIFIED, this );
01176       mChanger->endChange( todo );
01177       delete oldTodo;
01178       setModified(true);
01179       status = true;
01180   }
01181   if ( ! status ) {
01182     KMessageBox::sorry( this, i18n("Unable to turn sub-to-do into a top-level "
01183         "to-do, because it cannot be locked.") );
01184   }
01185 
01186   return status;
01187 }
01188 
01189 bool CalendarView::makeSubTodosIndependents ( )
01190 {
01191   bool  status = false;
01192   Todo *anTodo = selectedTodo();
01193 
01194   if( makeSubTodosIndependents( anTodo ) ) {
01195     updateView();
01196     status = true;
01197   }
01198   return status;
01199 }
01200 
01201 bool CalendarView::makeSubTodosIndependents ( Todo *todo )
01202 {
01203   if( !todo || todo->relations().isEmpty() ) return false;
01204 
01205   startMultiModify ( i18n( "Make sub-to-dos independent" ) );
01206   Incidence::List subTodos( todo->relations() );
01207   Incidence::List::Iterator it;
01208   Incidence *aIncidence;
01209   Todo *aTodo;
01210 
01211   for ( it= subTodos.begin(); it != subTodos.end(); ++it ) {
01212     aIncidence = *it;
01213     if( aIncidence && aIncidence->type() == "Todo" ) {
01214       aTodo = static_cast<Todo*>( aIncidence );
01215       todo_unsub ( aTodo );
01216     }
01217   }
01218   endMultiModify();
01219   return true;
01220 }
01221 
01222 bool CalendarView::deleteIncidence( const QString &uid, bool force )
01223 {
01224   Incidence *inc = mCalendar->incidence( uid );
01225   if ( inc ) {
01226     deleteIncidence( inc, force );
01227     return true;
01228   } else {
01229     return false;
01230   }
01231 }
01232 
01233 void CalendarView::toggleAlarm( Incidence *incidence )
01234 {
01235   if ( !incidence || !mChanger ) {
01236     kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01237     return;
01238   }
01239   Incidence*oldincidence = incidence->clone();
01240   if ( !mChanger->beginChange( incidence ) ) {
01241     kdDebug(5850) << "Unable to lock incidence " << endl;
01242     delete oldincidence;
01243     return;
01244   }
01245 
01246   Alarm::List alarms = incidence->alarms();
01247   Alarm::List::ConstIterator it;
01248   for( it = alarms.begin(); it != alarms.end(); ++it )
01249     (*it)->toggleAlarm();
01250   if (alarms.isEmpty()) {
01251     // Add an alarm if it didn't have one
01252     Alarm*alm = incidence->newAlarm();
01253     alm->setEnabled(true);
01254   }
01255   mChanger->changeIncidence( oldincidence, incidence, KOGlobals::ALARM_MODIFIED, this );
01256   mChanger->endChange( incidence );
01257   delete oldincidence;
01258 
01259 //  mClickedItem->updateIcons();
01260 }
01261 
01262 void CalendarView::dissociateOccurrence( Incidence *incidence, const QDate &date )
01263 {
01264   if ( !incidence || !mChanger ) {
01265     kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01266     return;
01267   }
01268   if ( !mChanger->beginChange( incidence ) ) {
01269     kdDebug(5850) << "Unable to lock incidence " << endl;
01270     return;
01271   }
01272   startMultiModify( i18n("Dissociate occurrence") );
01273   Incidence*oldincidence = incidence->clone();
01274 
01275   Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true );
01276 
01277   if ( newInc ) {
01278     // TODO: Use the same resource instead of asking again!
01279     mChanger->changeIncidence( oldincidence, incidence, KOGlobals::NOTHING_MODIFIED, this );
01280     mChanger->addIncidence( newInc, this );
01281   } else {
01282     KMessageBox::sorry( this, i18n("Dissociating the occurrence failed."),
01283       i18n("Dissociating Failed") );
01284   }
01285   mChanger->endChange( incidence );
01286   endMultiModify();
01287   delete oldincidence;
01288 }
01289 
01290 void CalendarView::dissociateFutureOccurrence( Incidence *incidence, const QDate &date )
01291 {
01292   if ( !incidence || !mChanger ) {
01293     kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01294     return;
01295   }
01296   if ( !mChanger->beginChange( incidence ) ) {
01297     kdDebug(5850) << "Unable to lock incidence " << endl;
01298     return;
01299   }
01300   startMultiModify( i18n("Dissociate future occurrences") );
01301   Incidence*oldincidence = incidence->clone();
01302 
01303   Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true );
01304   if ( newInc ) {
01305     // TODO: Use the same resource instead of asking again!
01306     mChanger->changeIncidence( oldincidence, incidence, KOGlobals::NOTHING_MODIFIED, this );
01307     mChanger->addIncidence( newInc, this );
01308   } else {
01309     KMessageBox::sorry( this, i18n("Dissociating the future occurrences failed."),
01310       i18n("Dissociating Failed") );
01311   }
01312   endMultiModify();
01313   mChanger->endChange( incidence );
01314   delete oldincidence;
01315 }
01316 
01317 
01318 /*****************************************************************************/
01319 
01320 
01321 void CalendarView::schedule_publish(Incidence *incidence)
01322 {
01323   if (incidence == 0)
01324     incidence = selectedIncidence();
01325 
01326   if (!incidence) {
01327     KMessageBox::information( this, i18n("No item selected."),
01328                               "PublishNoEventSelected" );
01329     return;
01330   }
01331 
01332   PublishDialog *publishdlg = new PublishDialog();
01333   if (incidence->attendeeCount()>0) {
01334     Attendee::List attendees = incidence->attendees();
01335     Attendee::List::ConstIterator it;
01336     for( it = attendees.begin(); it != attendees.end(); ++it ) {
01337       publishdlg->addAttendee( *it );
01338     }
01339   }
01340   if ( publishdlg->exec() == QDialog::Accepted ) {
01341     Incidence *inc = incidence->clone();
01342     inc->registerObserver( 0 );
01343     inc->clearAttendees();
01344 
01345     // Send the mail
01346     KCal::MailScheduler scheduler( mCalendar );
01347     if ( scheduler.publish( incidence, publishdlg->addresses() ) ) {
01348       KMessageBox::information( this, i18n("The item information was successfully sent."),
01349                                 i18n("Publishing"), "IncidencePublishSuccess" );
01350     } else {
01351       KMessageBox::error( this, i18n("Unable to publish the item '%1'").arg( incidence->summary() ) );
01352     }
01353   }
01354   delete publishdlg;
01355 }
01356 
01357 void CalendarView::schedule_request(Incidence *incidence)
01358 {
01359   schedule(Scheduler::Request,incidence);
01360 }
01361 
01362 void CalendarView::schedule_refresh(Incidence *incidence)
01363 {
01364   schedule(Scheduler::Refresh,incidence);
01365 }
01366 
01367 void CalendarView::schedule_cancel(Incidence *incidence)
01368 {
01369   schedule(Scheduler::Cancel,incidence);
01370 }
01371 
01372 void CalendarView::schedule_add(Incidence *incidence)
01373 {
01374   schedule(Scheduler::Add,incidence);
01375 }
01376 
01377 void CalendarView::schedule_reply(Incidence *incidence)
01378 {
01379   schedule(Scheduler::Reply,incidence);
01380 }
01381 
01382 void CalendarView::schedule_counter(Incidence *incidence)
01383 {
01384   schedule(Scheduler::Counter,incidence);
01385 }
01386 
01387 void CalendarView::schedule_declinecounter(Incidence *incidence)
01388 {
01389   schedule(Scheduler::Declinecounter,incidence);
01390 }
01391 
01392 void CalendarView::schedule_forward(Incidence * incidence)
01393 {
01394   if (incidence == 0)
01395     incidence = selectedIncidence();
01396 
01397   if (!incidence) {
01398     KMessageBox::information( this, i18n("No item selected."),
01399                               "ForwardNoEventSelected" );
01400     return;
01401   }
01402 
01403   PublishDialog publishdlg;
01404   if ( publishdlg.exec() == QDialog::Accepted ) {
01405     QString recipients = publishdlg.addresses();
01406     if ( incidence->organizer().isEmpty() ) {
01407       incidence->setOrganizer( Person( KOPrefs::instance()->fullName(),
01408                                        KOPrefs::instance()->email() ) );
01409     }
01410 
01411     ICalFormat format;
01412     QString messageText = format.createScheduleMessage( incidence, Scheduler::Request );
01413     KOMailClient mailer;
01414     if ( mailer.mailTo( incidence, recipients, messageText ) ) {
01415 
01416       KMessageBox::information( this, i18n("The item information was successfully sent."),
01417                                 i18n("Forwarding"), "IncidenceForwardSuccess" );
01418     } else {
01419       KMessageBox::error( this, i18n("Unable to forward the item '%1'").arg( incidence->summary() ) );
01420     }
01421   }
01422 }
01423 
01424 void CalendarView::mailFreeBusy( int daysToPublish )
01425 {
01426   QDateTime start = QDateTime::currentDateTime();
01427   QDateTime end = start.addDays(daysToPublish);
01428 
01429   FreeBusy *freebusy = new FreeBusy(mCalendar, start, end);
01430   freebusy->setOrganizer( Person( KOPrefs::instance()->fullName(),
01431                       KOPrefs::instance()->email() ) );
01432 
01433   kdDebug(5850) << "calendarview: schedule_publish_freebusy: startDate: "
01434      << KGlobal::locale()->formatDateTime( start ) << " End Date: "
01435      << KGlobal::locale()->formatDateTime( end ) << endl;
01436 
01437   PublishDialog *publishdlg = new PublishDialog();
01438   if ( publishdlg->exec() == QDialog::Accepted ) {
01439     // Send the mail
01440     KCal::MailScheduler scheduler( mCalendar );
01441     if ( scheduler.publish( freebusy, publishdlg->addresses() ) ) {
01442       KMessageBox::information( this, i18n("The free/busy information was successfully sent."),
01443                                 i18n("Sending Free/Busy"), "FreeBusyPublishSuccess" );
01444     } else {
01445       KMessageBox::error( this, i18n("Unable to publish the free/busy data.") );
01446     }
01447   }
01448   delete freebusy;
01449   delete publishdlg;
01450 }
01451 
01452 void CalendarView::uploadFreeBusy()
01453 {
01454   KOGroupware::instance()->freeBusyManager()->publishFreeBusy();
01455 }
01456 
01457 void CalendarView::schedule(Scheduler::Method method, Incidence *incidence)
01458 {
01459   if ( !incidence ) {
01460     incidence = selectedIncidence();
01461   }
01462 
01463   if ( !incidence ) {
01464     KMessageBox::sorry( this, i18n("No item selected."),
01465                         "ScheduleNoEventSelected" );
01466     return;
01467   }
01468 
01469   if( incidence->attendeeCount() == 0 && method != Scheduler::Publish ) {
01470     KMessageBox::information( this, i18n("The item has no attendees."),
01471                               "ScheduleNoIncidences" );
01472     return;
01473   }
01474 
01475   Incidence *inc = incidence->clone();
01476   inc->registerObserver( 0 );
01477   inc->clearAttendees();
01478 
01479   // Send the mail
01480   KCal::MailScheduler scheduler( mCalendar );
01481   if ( scheduler.performTransaction( incidence, method ) ) {
01482     KMessageBox::information( this, i18n("The groupware message for item '%1'"
01483                                 "was successfully sent.\nMethod: %2")
01484                                 .arg( incidence->summary() )
01485                                 .arg( Scheduler::methodName( method ) ),
01486                               i18n("Sending Free/Busy"),
01487                               "FreeBusyPublishSuccess" );
01488   } else {
01489     KMessageBox::error( this, i18n("Groupware message sending failed. "
01490                         "%2 is request/reply/add/cancel/counter/etc.",
01491                         "Unable to send the item '%1'.\nMethod: %2")
01492                         .arg( incidence->summary() )
01493                         .arg( Scheduler::methodName( method ) ) );
01494   }
01495 }
01496 
01497 void CalendarView::openAddressbook()
01498 {
01499   KRun::runCommand("kaddressbook");
01500 }
01501 
01502 void CalendarView::setModified(bool modified)
01503 {
01504   if (mModified != modified) {
01505     mModified = modified;
01506     emit modifiedChanged(mModified);
01507   }
01508 }
01509 
01510 bool CalendarView::isReadOnly()
01511 {
01512   return mReadOnly;
01513 }
01514 
01515 void CalendarView::setReadOnly(bool readOnly)
01516 {
01517   if (mReadOnly != readOnly) {
01518     mReadOnly = readOnly;
01519     emit readOnlyChanged(mReadOnly);
01520   }
01521 }
01522 
01523 bool CalendarView::isModified()
01524 {
01525   return mModified;
01526 }
01527 
01528 void CalendarView::print()
01529 {
01530 #ifndef KORG_NOPRINTER
01531   KOCoreHelper helper;
01532   CalPrinter printer( this, mCalendar, &helper );
01533   connect( this, SIGNAL(configChanged()), &printer, SLOT(updateConfig()) );
01534 
01535   KOrg::BaseView *currentView = mViewManager->currentView();
01536 
01537   CalPrinterBase::PrintType printType = CalPrinterBase::Month;
01538   if ( currentView ) printType = currentView->printType();
01539 
01540   DateList tmpDateList = mNavigator->selectedDates();
01541   Incidence::List selectedIncidences;
01542   if ( mViewManager->currentView() ) {
01543     selectedIncidences = mViewManager->currentView()->selectedIncidences();
01544   }
01545   printer.print( printType, tmpDateList.first(), tmpDateList.last(), selectedIncidences );
01546 #endif
01547 }
01548 
01549 void CalendarView::exportWeb()
01550 {
01551   // FIXME: Get rid of the settings object. When can I delete it???
01552   HTMLExportSettings *settings = new HTMLExportSettings( "KOrganizer" );
01553   // Manually read in the config, because parametrized kconfigxt objects don't
01554   // seem to load the config theirselves
01555   if ( settings ) settings->readConfig();
01556   ExportWebDialog *dlg = new ExportWebDialog( settings, this );
01557   connect( dlg,  SIGNAL( exportHTML( HTMLExportSettings* ) ),
01558            this, SIGNAL( exportHTML( HTMLExportSettings* ) ) );
01559   dlg->show();
01560 }
01561 
01562 void CalendarView::exportICalendar()
01563 {
01564   QString filename = KFileDialog::getSaveFileName("icalout.ics",i18n("*.ics|ICalendars"),this);
01565   if ( !filename.isEmpty() )
01566   {
01567     // Force correct extension
01568     if (filename.right(4) != ".ics") filename += ".ics";
01569     if ( QFile( filename ).exists() ) {
01570       if ( KMessageBox::No == KMessageBox::warningYesNo(
01571              this,
01572              i18n( "Do you want to overwrite %1?").arg(filename) ) ) {
01573           return;
01574       }
01575     }
01576     FileStorage storage( mCalendar, filename, new ICalFormat );
01577     storage.save();
01578   }
01579 }
01580 
01581 void CalendarView::exportVCalendar()
01582 {
01583   if (mCalendar->journals().count() > 0) {
01584     int result = KMessageBox::warningContinueCancel(this,
01585         i18n("The journal entries can not be exported to a vCalendar file."),
01586         i18n("Data Loss Warning"),i18n("Proceed"),"dontaskVCalExport",
01587         true);
01588     if (result != KMessageBox::Continue) return;
01589   }
01590 
01591   QString filename = KFileDialog::getSaveFileName("vcalout.vcs",i18n("*.vcs|vCalendars"),this);
01592   if ( !filename.isEmpty() )
01593   {
01594     // TODO: I don't like forcing extensions:
01595     // Force correct extension
01596     if (filename.right(4) != ".vcs") filename += ".vcs";
01597     if ( QFile( filename ).exists() ) {
01598       if ( KMessageBox::No == KMessageBox::warningYesNo(
01599              this,
01600              i18n( "Do you want to overwrite %1?").arg(filename ) ) ) {
01601              return;
01602       }
01603     }
01604     FileStorage storage( mCalendar, filename, new VCalFormat );
01605     storage.save();
01606   }
01607 }
01608 
01609 void CalendarView::eventUpdated(Incidence *)
01610 {
01611   setModified();
01612   // Don't call updateView here. The code, which has caused the update of the
01613   // event is responsible for updating the view.
01614 //  updateView();
01615 }
01616 
01617 void CalendarView::adaptNavigationUnits()
01618 {
01619   if (mViewManager->currentView()->isEventView()) {
01620     int days = mViewManager->currentView()->currentDateCount();
01621     if (days == 1) {
01622       emit changeNavStringPrev(i18n("&Previous Day"));
01623       emit changeNavStringNext(i18n("&Next Day"));
01624     } else {
01625       emit changeNavStringPrev(i18n("&Previous Week"));
01626       emit changeNavStringNext(i18n("&Next Week"));
01627     }
01628   }
01629 }
01630 
01631 void CalendarView::processMainViewSelection( Incidence *incidence, const QDate &date )
01632 {
01633   if ( incidence ) mTodoList->clearSelection();
01634   processIncidenceSelection( incidence, date );
01635 }
01636 
01637 void CalendarView::processTodoListSelection( Incidence *incidence, const QDate &date )
01638 {
01639   if ( incidence && mViewManager->currentView() ) {
01640     mViewManager->currentView()->clearSelection();
01641   }
01642   processIncidenceSelection( incidence, date );
01643 }
01644 
01645 void CalendarView::processIncidenceSelection( Incidence *incidence, const QDate &date )
01646 {
01647   if ( !incidence || incidence == mSelectedIncidence ) return;
01648 
01649   mSelectedIncidence = incidence;
01650 
01651   emit incidenceSelected( mSelectedIncidence, date );
01652   bool organizerEvents = false;
01653   bool groupEvents = false;
01654   bool todo = false;
01655   bool subtodo = false;
01656 
01657   if ( incidence ) {
01658     organizerEvents = KOPrefs::instance()->thatIsMe( incidence->organizer().email() );
01659     groupEvents = incidence->attendeeByMails( KOPrefs::instance()->allEmails() );
01660 
01661     if ( incidence && incidence->type() == "Todo" ) {
01662       todo = true;
01663       subtodo = ( incidence->relatedTo() != 0 );
01664     }
01665   }
01666   emit todoSelected( todo );
01667   emit subtodoSelected( subtodo );
01668   emit organizerEventsSelected( organizerEvents );
01669   emit groupEventsSelected( groupEvents );
01670 }
01671 
01672 
01673 void CalendarView::checkClipboard()
01674 {
01675 #ifndef KORG_NODND
01676   if (ICalDrag::canDecode(QApplication::clipboard()->data())) {
01677     kdDebug(5850) << "CalendarView::checkClipboard() true" << endl;
01678     emit pasteEnabled(true);
01679   } else {
01680     kdDebug(5850) << "CalendarView::checkClipboard() false" << endl;
01681     emit pasteEnabled(false);
01682   }
01683 #endif
01684 }
01685 
01686 void CalendarView::showDates(const DateList &selectedDates)
01687 {
01688 //  kdDebug(5850) << "CalendarView::selectDates()" << endl;
01689 
01690   if ( mViewManager->currentView() ) {
01691     updateView( selectedDates.first(), selectedDates.last() );
01692   } else {
01693     mViewManager->showAgendaView();
01694   }
01695 }
01696 
01697 void CalendarView::editFilters()
01698 {
01699   kdDebug(5850) << "CalendarView::editFilters()" << endl;
01700 
01701   CalFilter *filter = mFilters.first();
01702   while(filter) {
01703     kdDebug(5850) << " Filter: " << filter->name() << endl;
01704     filter = mFilters.next();
01705   }
01706 
01707   mDialogManager->showFilterEditDialog(&mFilters);
01708 }
01709 
01712 void CalendarView::updateFilter()
01713 {
01714   QStringList filters;
01715   CalFilter *filter;
01716 
01717   int pos = mFilters.find( mCurrentFilter );
01718   if ( pos < 0 ) {
01719     mCurrentFilter = 0;
01720   }
01721 
01722   filters << i18n("No filter");
01723   for ( filter = mFilters.first(); filter; filter = mFilters.next() ) {
01724     filters << filter->name();
01725   }
01726 
01727   emit newFilterListSignal( filters );
01728   // account for the additional "No filter" at the beginning! if the
01729   // filter is not in the list, pos == -1...
01730   emit selectFilterSignal( pos+1 );
01731   mCalendar->setFilter( mCurrentFilter );
01732   updateView();
01733 }
01734 
01737 void CalendarView::filterActivated( int filterNo )
01738 {
01739   CalFilter *newFilter = 0;
01740   if ( filterNo > 0 && filterNo <= int(mFilters.count()) ) {
01741     newFilter = mFilters.at( filterNo-1 );
01742   }
01743   if ( newFilter != mCurrentFilter ) {
01744     mCurrentFilter = newFilter;
01745     mCalendar->setFilter( mCurrentFilter );
01746     updateView();
01747   }
01748   emit filterChanged();
01749 }
01750 
01751 QString CalendarView::currentFilterName() const
01752 {
01753   if ( mCurrentFilter) {
01754     return mCurrentFilter->name();
01755   } else return i18n("No filter");
01756 }
01757 
01758 void CalendarView::takeOverEvent()
01759 {
01760   Incidence *incidence = currentSelection();
01761 
01762   if (!incidence) return;
01763 
01764   incidence->setOrganizer( Person( KOPrefs::instance()->fullName(),
01765                            KOPrefs::instance()->email() ) );
01766   incidence->recreate();
01767   incidence->setReadOnly(false);
01768 
01769   updateView();
01770 }
01771 
01772 void CalendarView::takeOverCalendar()
01773 {
01774   Incidence::List incidences = mCalendar->rawIncidences();
01775   Incidence::List::Iterator it;
01776 
01777   for ( it = incidences.begin(); it != incidences.end(); ++it ) {
01778     (*it)->setOrganizer( Person( KOPrefs::instance()->fullName(),
01779                          KOPrefs::instance()->email() ) );
01780     (*it)->recreate();
01781     (*it)->setReadOnly(false);
01782   }
01783   updateView();
01784 }
01785 
01786 void CalendarView::showIntro()
01787 {
01788   kdDebug(5850) << "To be implemented." << endl;
01789 }
01790 
01791 void CalendarView::showDateNavigator( bool show )
01792 {
01793   if( show )
01794     mDateNavigator->show();
01795   else
01796     mDateNavigator->hide();
01797 }
01798 
01799 void CalendarView::showTodoView( bool show )
01800 {
01801   if( show )
01802     mTodoList->show();
01803   else
01804     mTodoList->hide();
01805 }
01806 
01807 void CalendarView::showEventViewer( bool show )
01808 {
01809   if( show )
01810     mEventViewer->show();
01811   else
01812     mEventViewer->hide();
01813 }
01814 
01815 
01816 void CalendarView::addView(KOrg::BaseView *view)
01817 {
01818   mViewManager->addView(view);
01819 }
01820 
01821 void CalendarView::showView(KOrg::BaseView *view)
01822 {
01823   mViewManager->showView(view);
01824 }
01825 
01826 void CalendarView::addExtension( CalendarViewExtension::Factory *factory )
01827 {
01828   CalendarViewExtension *extension = factory->create( mLeftSplitter );
01829 
01830   mExtensions.append( extension );
01831 }
01832 
01833 void CalendarView::toggleExpand()
01834 {
01835   showLeftFrame( mLeftFrame->isHidden() );
01836 }
01837 
01838 void CalendarView::showLeftFrame(bool show)
01839 {
01840   if (show) {
01841     mLeftFrame->show();
01842     emit calendarViewExpanded( false );
01843   } else {
01844     mLeftFrame->hide();
01845     emit calendarViewExpanded( true );
01846   }
01847 }
01848 
01849 void CalendarView::calendarModified( bool modified, Calendar * )
01850 {
01851   setModified( modified );
01852 }
01853 
01854 Todo *CalendarView::selectedTodo()
01855 {
01856   Incidence *incidence = currentSelection();
01857   if ( incidence && incidence->type() == "Todo" ) {
01858     return static_cast<Todo *>( incidence );
01859   }
01860   incidence = 0;
01861 
01862   Incidence::List selectedIncidences = mTodoList->selectedIncidences();
01863   if ( !selectedIncidences.isEmpty() ) incidence = selectedIncidences.first();
01864   if ( incidence && incidence->type() == "Todo" ) {
01865     return static_cast<Todo *>( incidence );
01866   }
01867 
01868   return 0;
01869 }
01870 
01871 void CalendarView::dialogClosing( Incidence *in )
01872 {
01873   // FIXME: this doesn't work, because if it's a new incidence, it's not locked!
01874   mChanger->endChange( in );
01875   mDialogList.remove( in );
01876 }
01877 
01878 Incidence *CalendarView::currentSelection()
01879 {
01880   return mViewManager->currentSelection();
01881 }
01882 
01883 Incidence* CalendarView::selectedIncidence()
01884 {
01885   Incidence *incidence = currentSelection();
01886   if ( !incidence ) {
01887     Incidence::List selectedIncidences = mTodoList->selectedIncidences();
01888     if ( !selectedIncidences.isEmpty() )
01889       incidence = selectedIncidences.first();
01890   }
01891   return incidence;
01892 }
01893 
01894 void CalendarView::showIncidence()
01895 {
01896   showIncidence( selectedIncidence() );
01897 }
01898 
01899 void CalendarView::editIncidence()
01900 {
01901   editIncidence( selectedIncidence() );
01902 }
01903 
01904 bool CalendarView::editIncidence( const QString& uid )
01905 {
01906   kdDebug(5850) << "CalendarView::editIncidence()" << endl;
01907   return editIncidence( mCalendar->incidence( uid ) );
01908 }
01909 
01910 void CalendarView::deleteIncidence()
01911 {
01912   deleteIncidence( selectedIncidence() );
01913 }
01914 
01915 void CalendarView::cutIncidence(Incidence *)
01916 {
01917   edit_cut();
01918 }
01919 
01920 void CalendarView::copyIncidence(Incidence *)
01921 {
01922   edit_copy();
01923 }
01924 
01925 void CalendarView::pasteIncidence()
01926 {
01927   edit_paste();
01928 }
01929 
01930 void CalendarView::showIncidence( Incidence *incidence )
01931 {
01932   KOEventViewerDialog *eventViewer = new KOEventViewerDialog( calendar(), this );
01933   eventViewer->setIncidence( incidence, QDate() );
01934   eventViewer->show();
01935 }
01936 
01937 bool CalendarView::editIncidence( Incidence *incidence, bool isCounter )
01938 {
01939   kdDebug(5850) << "CalendarView::editEvent()" << endl;
01940 
01941   if ( !incidence ) {
01942     kdDebug(5850) << "Empty Incidence" << endl;
01943     KNotifyClient::beep();
01944     return false;
01945   }
01946 
01947   if ( !mChanger ) {
01948     kdDebug(5850) << "Empty Changer" << endl;
01949     KNotifyClient::beep();
01950     return false;
01951   }
01952 
01953   KOIncidenceEditor *tmp = editorDialog( incidence );
01954   if ( tmp ) {
01955     kdDebug(5850) << "CalendarView::editIncidence() in List" << endl;
01956     tmp->reload();
01957     tmp->raise();
01958     tmp->show();
01959     return true;
01960   }
01961 
01962   if ( incidence->isReadOnly() ) {
01963     showIncidence( incidence );
01964     return true;
01965   }
01966 
01967   if ( !isCounter && !mChanger->beginChange( incidence ) ) {
01968     warningChangeFailed( incidence );
01969     showIncidence( incidence );
01970     return false;
01971   }
01972 
01973   kdDebug(5850) << "CalendarView::editIncidence() new IncidenceEditor" << endl;
01974   KOIncidenceEditor *incidenceEditor = mDialogManager->getEditor( incidence );
01975   connectIncidenceEditor( incidenceEditor );
01976 
01977   mDialogList.insert( incidence, incidenceEditor );
01978   incidenceEditor->editIncidence( incidence, activeDate(), mCalendar );
01979   incidenceEditor->show();
01980   return true;
01981 }
01982 
01983 void CalendarView::deleteSubTodosIncidence ( Todo *todo )
01984 {
01985   if( !todo ) return;
01986 
01987   Incidence::List subTodos( todo->relations() );
01988   Incidence::List::Iterator it;
01989   Incidence *aIncidence;
01990   Todo *aTodo;
01991 
01992   for ( it= subTodos.begin(); it != subTodos.end(); ++it ) {
01993     aIncidence = *it;
01994     if( aIncidence && aIncidence->type() == "Todo" ) {
01995       aTodo = static_cast<Todo*>( aIncidence );
01996       deleteSubTodosIncidence ( aTodo );
01997     }
01998   }
01999   mChanger->deleteIncidence ( todo, this );
02000 }
02001 
02002 void CalendarView::deleteTodoIncidence ( Todo *todo, bool force )
02003 {
02004   if ( !todo ) return ;
02005 
02006   // it a simple todo, ask and delete it.
02007   if (todo->relations().isEmpty() ) {
02008     bool doDelete = true;
02009     if ( !force && KOPrefs::instance()->mConfirm ) {
02010       doDelete = ( msgItemDelete( todo ) == KMessageBox::Continue );
02011     }
02012     if ( doDelete )
02013       mChanger->deleteIncidence( todo, this );
02014     return;
02015   }
02016 
02017   /* Ok, this to-do has sub-to-dos, ask what to do */
02018   int km = KMessageBox::No;
02019   if ( !force ) {
02020     km = KMessageBox::questionYesNoCancel(
02021       this,
02022       i18n("The item \"%1\" has sub-to-dos. "
02023            "Do you want to delete just this item and "
02024            "make all its sub-to-dos independent, or "
02025            "delete the to-do with all its sub-to-dos?"
02026         ).arg( todo->summary() ),
02027       i18n("KOrganizer Confirmation"),
02028       i18n("Delete Only This"),
02029       i18n("Delete All"));
02030   }
02031   startMultiModify( i18n("Deleting sub-to-dos" ) );
02032   // Delete only the father
02033   if( km == KMessageBox::Yes ) {
02034 
02035     makeSubTodosIndependents ( todo );
02036     mChanger->deleteIncidence( todo, this );
02037   } else if ( km == KMessageBox::No ) {
02038     // Delete all
02039     // we have to hide the delete confirmation for each itemDate
02040     deleteSubTodosIncidence ( todo );
02041   }
02042   endMultiModify();
02043 }
02044 
02045 void CalendarView::deleteIncidence(Incidence *incidence, bool force)
02046 {
02047   if ( !incidence || !mChanger ) {
02048     if ( !force ) {
02049       KNotifyClient::beep();
02050     }
02051     return;
02052   }
02053   if ( incidence->isReadOnly() ) {
02054     if ( !force ) {
02055       KMessageBox::information( this, i18n("The item \"%1\" is marked read-only "
02056                                 "and cannot be deleted; it probably belongs to "
02057                                 "a read-only calendar resource.")
02058                                 .arg(incidence->summary()),
02059                                 i18n("Removing not possible"),
02060                                 "deleteReadOnlyIncidence" );
02061     }
02062     return;
02063   }
02064 
02065   CanDeleteIncidenceVisitor v;
02066 
02067   // Let the visitor do special things for special incidence types.
02068   // e.g. todos with children cannot be deleted, so act(..) returns false
02069   if ( !v.act( incidence, this ) )
02070     return;
02071   //If it is a todo, there are specific delete function
02072 
02073   if ( incidence && incidence->type()=="Todo" ) {
02074     deleteTodoIncidence( static_cast<Todo*>(incidence), force );
02075     return;
02076   }
02077 
02078   if ( incidence->doesRecur() ) {
02079     QDate itemDate = mViewManager->currentSelectionDate();
02080     kdDebug(5850) << "Recurrence-Date: " << itemDate.toString() << endl;
02081     int km = KMessageBox::Ok;
02082     if ( !force ) {
02083       if ( !itemDate.isValid() ) {
02084         kdDebug(5850) << "Date Not Valid" << endl;
02085         km = KMessageBox::warningContinueCancel(this,
02086           i18n("The calendar item \"%1\" recurs over multiple dates; "
02087                "are you sure you want to delete it "
02088                "and all its recurrences?").arg( incidence->summary() ),
02089                i18n("KOrganizer Confirmation"), i18n("Delete All") );
02090       } else {
02091         km = KOMessageBox::fourBtnMsgBox( this, QMessageBox::Warning,
02092           i18n("The calendar item \"%1\" recurs over multiple dates. "
02093                "Do you want to delete only the current one on %2, only all "
02094                "future recurrences, or all its recurrences?" )
02095                .arg( incidence->summary() )
02096                .arg( KGlobal::locale()->formatDate(itemDate)),
02097                i18n("KOrganizer Confirmation"), i18n("Delete C&urrent"),
02098                i18n("Delete &Future"),
02099                i18n("Delete &All"));
02100       }
02101     }
02102     switch(km) {
02103       case KMessageBox::Ok: // Continue // all
02104       case KMessageBox::Continue:
02105         mChanger->deleteIncidence( incidence, this );
02106         break;
02107 
02108       case KMessageBox::Yes: // just this one
02109         if ( mChanger->beginChange( incidence ) ) {
02110           Incidence *oldIncidence = incidence->clone();
02111           incidence->recurrence()->addExDate( itemDate );
02112           mChanger->changeIncidence( oldIncidence, incidence,
02113                                      KOGlobals::RECURRENCE_MODIFIED_ONE_ONLY, this );
02114           mChanger->endChange( incidence );
02115           delete oldIncidence;
02116         }
02117         break;
02118       case KMessageBox::No: // all future items
02119         if ( mChanger->beginChange( incidence ) ) {
02120           Incidence *oldIncidence = incidence->clone();
02121           Recurrence *recur = incidence->recurrence();
02122           recur->setEndDate( itemDate.addDays(-1) );
02123           mChanger->changeIncidence( oldIncidence, incidence,
02124                                      KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE,  this );
02125           mChanger->endChange( incidence );
02126           delete oldIncidence;
02127         }
02128         break;
02129     }
02130   } else {
02131     bool doDelete = true;
02132     if ( !force && KOPrefs::instance()->mConfirm ) {
02133       doDelete = ( msgItemDelete( incidence ) == KMessageBox::Continue );
02134     }
02135     if ( doDelete ) {
02136       mChanger->deleteIncidence( incidence, this );
02137       processIncidenceSelection( 0, QDate() );
02138     }
02139   }
02140 }
02141 
02142 void CalendarView::connectIncidenceEditor( KOIncidenceEditor *editor )
02143 {
02144   connect( this, SIGNAL( newIncidenceChanger( IncidenceChangerBase* ) ),
02145            editor, SLOT( setIncidenceChanger( IncidenceChangerBase* ) ) );
02146   editor->setIncidenceChanger( mChanger );
02147 }
02148 
02149 bool CalendarView::purgeCompletedSubTodos( Todo* todo, bool &allPurged )
02150 {
02151   if ( !todo ) return true;
02152   bool deleteThisTodo = true;
02153   Incidence::List subTodos( todo->relations() );
02154   Incidence *aIncidence;
02155   Todo *aTodo;
02156   Incidence::List::Iterator it;
02157   for ( it = subTodos.begin(); it != subTodos.end(); ++it ) {
02158     aIncidence = *it;
02159     if ( aIncidence && aIncidence->type()=="Todo" ) {
02160       aTodo = static_cast<Todo*>( aIncidence );
02161       deleteThisTodo &= purgeCompletedSubTodos( aTodo, allPurged );
02162     }
02163   }
02164 
02165   if ( deleteThisTodo ) {
02166     if ( todo->isCompleted() ) {
02167       if ( !mChanger->deleteIncidence( todo, this ) )
02168         allPurged = false;
02169     } else {
02170       deleteThisTodo = false;
02171     }
02172   } else {
02173     if ( todo->isCompleted() ) {
02174       allPurged = false;
02175     }
02176   }
02177   return deleteThisTodo;
02178 }
02179 
02180 void CalendarView::purgeCompleted()
02181 {
02182   int result = KMessageBox::warningContinueCancel(this,
02183       i18n("Delete all completed to-dos?"),i18n("Purge To-dos"),i18n("Purge"));
02184 
02185   if (result == KMessageBox::Continue) {
02186     bool allDeleted = true;
02187     startMultiModify( i18n("Purging completed to-dos") );
02188     Todo::List todos = calendar()->rawTodos();
02189     Todo::List rootTodos;
02190     Todo::List::ConstIterator it;
02191     for ( it = todos.begin(); it != todos.end(); ++it ) {
02192       Todo *aTodo = *it;
02193       if ( aTodo && !aTodo->relatedTo() )
02194         rootTodos.append( aTodo );
02195     }
02196     // now that we have a list of all root todos, check them and their children
02197     for ( it = rootTodos.begin(); it != rootTodos.end(); ++it ) {
02198       purgeCompletedSubTodos( *it, allDeleted );
02199     }
02200     endMultiModify();
02201     if ( !allDeleted ) {
02202       KMessageBox::information( this, i18n("Unable to purge to-dos with "
02203                                 "uncompleted children."), i18n("Delete To-do"),
02204                                 "UncompletedChildrenPurgeTodos" );
02205     }
02206   }
02207 }
02208 
02209 void CalendarView::warningChangeFailed( Incidence *incidence )
02210 {
02211   if ( incidence ) {
02212     KMessageBox::sorry(
02213       this,
02214       i18n( "Unable to edit \"%1\" because it is locked by another process." ).
02215       arg( incidence->summary() ) );
02216   }
02217 }
02218 
02219 void CalendarView::editCanceled( Incidence *incidence )
02220 {
02221   mCalendar->endChange( incidence );
02222 }
02223 
02224 void CalendarView::showErrorMessage( const QString &msg )
02225 {
02226   KMessageBox::error( this, msg );
02227 }
02228 
02229 void CalendarView::updateCategories()
02230 {
02231   QStringList allCats( calendar()->categories() );
02232   allCats.sort();
02233   QStringList categories( KOPrefs::instance()->mCustomCategories );
02234   for ( QStringList::ConstIterator si = allCats.constBegin(); si != allCats.constEnd(); ++si ) {
02235     if ( categories.find( *si ) == categories.end() ) {
02236       categories.append( *si );
02237     }
02238   }
02239   KOPrefs::instance()->mCustomCategories = categories;
02240   KOPrefs::instance()->writeConfig();
02241   // Make the category editor update the list!
02242   emit categoriesChanged();
02243 }
02244 
02245 void CalendarView::addIncidenceOn( Incidence *incadd, const QDate &dt )
02246 {
02247   if ( !incadd || !mChanger ) {
02248     KMessageBox::sorry(this, i18n("Unable to copy the item to %1.")
02249                        .arg( dt.toString() ), i18n("Copying Failed") );
02250     return;
02251   }
02252   Incidence *incidence = mCalendar->incidence( incadd->uid() );
02253   if ( !incidence ) incidence = incadd;
02254   // Create a copy of the incidence, since the incadd doesn't belong to us.
02255   incidence = incidence->clone();
02256   incidence->recreate();
02257 
02258   if ( incidence->type() == "Event" ) {
02259     Event *event = static_cast<Event*>(incidence);
02260 
02261     // Adjust date
02262     QDateTime start = event->dtStart();
02263     QDateTime end = event->dtEnd();
02264 
02265     int duration = start.daysTo( end );
02266     start.setDate( dt );
02267     end.setDate( dt.addDays( duration ) );
02268 
02269     event->setDtStart( start );
02270     event->setDtEnd( end );
02271 
02272   } else if ( incidence->type() == "Todo" ) {
02273     Todo *todo = static_cast<Todo*>(incidence);
02274     QDateTime due = todo->dtDue();
02275     due.setDate( dt );
02276 
02277     todo->setDtDue( due );
02278     todo->setHasDueDate( true );
02279   }
02280 
02281   if ( !mChanger->addIncidence( incidence, this ) ) {
02282     KODialogManager::errorSaveIncidence( this, incidence );
02283     delete incidence;
02284   }
02285 }
02286 
02287 void CalendarView::moveIncidenceTo( Incidence *incmove, const QDate &dt )
02288 {
02289   if ( !incmove || !mChanger ) {
02290     KMessageBox::sorry( this, i18n("Unable to move the item to %1.")
02291                         .arg( dt.toString() ), i18n("Moving Failed") );
02292     return;
02293   }
02294   Incidence *incidence = mCalendar->incidence( incmove->uid() );
02295   if ( !incidence ) {
02296     addIncidenceOn( incidence, dt );
02297     return;
02298   }
02299   Incidence *oldIncidence = incidence->clone();
02300   if ( !mChanger->beginChange( incidence ) ) {
02301     delete oldIncidence;
02302     return;
02303   }
02304 
02305   if ( incidence->type() == "Event" ) {
02306     Event *event = static_cast<Event*>(incidence);
02307 
02308     // Adjust date
02309     QDateTime start = event->dtStart();
02310     QDateTime end = event->dtEnd();
02311 
02312     int duration = start.daysTo( end );
02313     start.setDate( dt );
02314     end.setDate( dt.addDays( duration ) );
02315 
02316     event->setDtStart( start );
02317     event->setDtEnd( end );
02318 
02319   } else if ( incidence->type() == "Todo" ) {
02320     Todo *todo = static_cast<Todo*>(incidence);
02321     QDateTime due = todo->dtDue();
02322     due.setDate( dt );
02323 
02324     todo->setDtDue( due );
02325     todo->setHasDueDate( true );
02326   }
02327   mChanger->changeIncidence( oldIncidence, incidence, KOGlobals::DATE_MODIFIED,this );
02328   mChanger->endChange( incidence );
02329   delete oldIncidence;
02330 }
02331 
02332 void CalendarView::resourcesChanged()
02333 {
02334   mViewManager->resourcesChanged();
02335   updateView();
02336 }
02337 
02338 #include "calendarview.moc"