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/calhelper.h>
00069 #include <libkcal/vcaldrag.h>
00070 #include <libkcal/icaldrag.h>
00071 #include <libkcal/icalformat.h>
00072 #include <libkcal/vcalformat.h>
00073 #include <libkcal/scheduler.h>
00074 #include <libkcal/calendarlocal.h>
00075 #include <libkcal/journal.h>
00076 #include <libkcal/calfilter.h>
00077 #include <libkcal/attendee.h>
00078 #include <libkcal/dndfactory.h>
00079 #include <libkcal/freebusy.h>
00080 #include <libkcal/filestorage.h>
00081 #include <libkcal/calendarresources.h>
00082 #include <libkcal/calendarnull.h>
00083 #include <libkcal/htmlexportsettings.h>
00084 
00085 #include <kglobal.h>
00086 #include <kdebug.h>
00087 #include <kstandarddirs.h>
00088 #include <kfiledialog.h>
00089 #include <kmessagebox.h>
00090 #include <knotifyclient.h>
00091 #include <kconfig.h>
00092 #include <krun.h>
00093 #include <kdirwatch.h>
00094 
00095 #include <qapplication.h>
00096 #include <qclipboard.h>
00097 #include <qcursor.h>
00098 #include <qmultilineedit.h>
00099 #include <qtimer.h>
00100 #include <qwidgetstack.h>
00101 #include <qptrlist.h>
00102 #include <qfile.h>
00103 #include <qlayout.h>
00104 #ifndef KORG_NOSPLITTER
00105 #include <qsplitter.h>
00106 #endif
00107 #include <qvbox.h>
00108 #include <qwhatsthis.h>
00109 
00110 #include <stdlib.h>
00111 #include <assert.h>
00112 
00113 using namespace KOrg;
00114 
00115 CalendarView::CalendarView( QWidget *parent, const char *name )
00116   : CalendarViewBase( parent, name ),
00117     mHistory( 0 ),
00118     mCalendar( CalendarNull::self() ),
00119     mChanger( 0 )
00120 {
00121   kdDebug(5850) << "CalendarView::CalendarView( Calendar )" << endl;
00122 
00123   mViewManager = new KOViewManager( this );
00124   mDialogManager = new KODialogManager( this );
00125 
00126   mModified = false;
00127   mReadOnly = false;
00128   mSelectedIncidence = 0;
00129 
00130   mFilters.setAutoDelete( true );
00131 
00132   mExtensions.setAutoDelete( true );
00133 
00134   mDateNavigator = new DateNavigator( this );
00135   mDateChecker = new DateChecker( this );
00136 
00137   QBoxLayout *topLayout = new QVBoxLayout( this );
00138 
00139 #ifndef KORG_NOSPLITTER
00140   // create the main layout frames.
00141   mPanner = new QSplitter( QSplitter::Horizontal, this,
00142                            "CalendarView::Panner" );
00143   topLayout->addWidget( mPanner );
00144 
00145   mLeftSplitter = new QSplitter( QSplitter::Vertical, mPanner,
00146                                  "CalendarView::LeftFrame" );
00147 //  mPanner->setResizeMode( mLeftSplitter, QSplitter::Stretch );
00148 
00149   mDateNavigatorContainer = new DateNavigatorContainer( mLeftSplitter,
00150                                                "CalendarView::DateNavigator" );
00151 
00152 //  mLeftSplitter->setResizeMode( mDateNavigatorContainer, QSplitter::Stretch );
00153   mLeftSplitter->setCollapsible( mDateNavigatorContainer, true );
00154   mTodoList = new KOTodoView( CalendarNull::self(), mLeftSplitter, "todolist" );
00155 
00156   mEventViewer = new KOEventViewer( CalendarNull::self(), mLeftSplitter,"EventViewer" );
00157 
00158   QVBox *rightBox = new QVBox( mPanner );
00159   mNavigatorBar = new NavigatorBar( rightBox );
00160   mRightFrame = new QWidgetStack( rightBox );
00161   rightBox->setStretchFactor( mRightFrame, 1 );
00162 
00163   mLeftFrame = mLeftSplitter;
00164 #else
00165   QWidget *mainBox;
00166   QWidget *leftFrame;
00167 
00168   if ( KOPrefs::instance()->mVerticalScreen ) {
00169     mainBox = new QVBox( this );
00170     leftFrame = new QHBox( mainBox );
00171   } else {
00172     mainBox = new QHBox( this );
00173     leftFrame = new QVBox( mainBox );
00174   }
00175 
00176   topLayout->addWidget( mainBox );
00177 
00178   mDateNavigatorContainer = new KDateNavigator( leftFrame, true,
00179                                        "CalendarView::DateNavigator",
00180                                        QDate::currentDate() );
00181   mTodoList = new KOTodoView( CalendarNull::self(), leftFrame, "todolist" );
00182 
00183   mEventViewer = new KOEventViewer ( CalendarNull::self(), leftFrame, "EventViewer" );
00184 
00185   QWidget *rightBox = new QWidget( mainBox );
00186   QBoxLayout *rightLayout = new QVBoxLayout( rightBox );
00187 
00188   mNavigatorBar = new NavigatorBar( QDate::currentDate(), rightBox );
00189   rightLayout->addWidget( mNavigatorBar );
00190 
00191   mRightFrame = new QWidgetStack( rightBox );
00192   rightLayout->addWidget( mRightFrame );
00193 
00194   mLeftFrame = leftFrame;
00195 
00196   if ( KOPrefs::instance()->mVerticalScreen ) {
00197     // mTodoList->setFixedHeight( 60 );
00198     mTodoList->setFixedHeight( mDateNavigatorContainer->sizeHint().height() );
00199   }
00200 #endif
00201 
00202   // Signals emited by mDateNavigator
00203   connect( mDateNavigator, SIGNAL( datesSelected( const KCal::DateList &, const QDate & ) ),
00204            SLOT( showDates( const KCal::DateList &, const QDate & ) ) );
00205 
00206   // Signals emited by mNavigatorBar
00207   connect( mNavigatorBar, SIGNAL( prevYearClicked() ),
00208            mDateNavigator, SLOT( selectPreviousYear() ) );
00209   connect( mNavigatorBar, SIGNAL( nextYearClicked() ),
00210            mDateNavigator, SLOT( selectNextYear() ) );
00211   connect( mNavigatorBar, SIGNAL( prevMonthClicked() ),
00212            mDateNavigator, SLOT( selectPreviousMonth() ) );
00213   connect( mNavigatorBar, SIGNAL( nextMonthClicked() ),
00214            mDateNavigator, SLOT( selectNextMonth() ) );
00215   connect( mNavigatorBar, SIGNAL( monthSelected(int) ),
00216            mDateNavigator, SLOT( selectMonth(int) ) );
00217   connect( mNavigatorBar, SIGNAL( yearSelected(int)),
00218            mDateNavigator, SLOT(selectYear(int)) );
00219 
00220 
00221   // Signals emited by mDateNavigatorContainer
00222   connect( mDateNavigatorContainer, SIGNAL( weekClicked( const QDate & ) ),
00223            this, SLOT( selectWeek( const QDate & ) ) );
00224   connect( mDateNavigatorContainer, SIGNAL( prevMonthClicked(const QDate &, const QDate &, const QDate &) ),
00225            mDateNavigator, SLOT( selectPreviousMonth(const QDate &, const QDate &, const QDate &) ) );
00226   connect( mDateNavigatorContainer, SIGNAL( nextMonthClicked(const QDate &, const QDate &, const QDate &) ),
00227            mDateNavigator, SLOT( selectNextMonth(const QDate &, const QDate &, const QDate &) ) );
00228   connect( mDateNavigatorContainer, SIGNAL( prevYearClicked() ),
00229            mDateNavigator, SLOT( selectPreviousYear() ) );
00230   connect( mDateNavigatorContainer, SIGNAL( nextYearClicked() ),
00231            mDateNavigator, SLOT( selectNextYear() ) );
00232   connect( mDateNavigatorContainer, SIGNAL( monthSelected(int) ),
00233            mDateNavigator, SLOT( selectMonth(int) ) );
00234   connect( mDateNavigatorContainer, SIGNAL(yearSelected(int)),
00235            mDateNavigator, SLOT(selectYear(int)) );
00236   connect( mDateNavigatorContainer, SIGNAL( goPrevious() ),
00237            mDateNavigator, SLOT( selectPrevious() ) );
00238   connect( mDateNavigatorContainer, SIGNAL( goNext() ),
00239            mDateNavigator, SLOT( selectNext() ) );
00240 
00241   connect( mDateNavigatorContainer, SIGNAL( datesSelected( const KCal::DateList & ) ),
00242            mDateNavigator, SLOT( selectDates( const KCal::DateList & ) ) );
00243 
00244   connect( mDateNavigatorContainer, SIGNAL(incidenceDropped(Incidence*, const QDate&)),
00245            SLOT( addIncidenceOn( Incidence *, const QDate & ) ) );
00246   connect( mDateNavigatorContainer, SIGNAL(incidenceDroppedMove(Incidence*,const QDate&)),
00247            SLOT( moveIncidenceTo( Incidence *, const QDate & ) ) );
00248 
00249   connect( mDateChecker, SIGNAL( dayPassed( const QDate & ) ),
00250            mTodoList, SLOT( dayPassed( const QDate & ) ) );
00251   connect( mDateChecker, SIGNAL( dayPassed( const QDate & ) ),
00252            SIGNAL( dayPassed( const QDate & ) ) );
00253   connect( mDateChecker, SIGNAL( dayPassed( const QDate & ) ),
00254            mDateNavigatorContainer, SLOT( updateToday() ) );
00255 
00256   connect( this, SIGNAL( configChanged() ),
00257            mDateNavigatorContainer, SLOT( updateConfig() ) );
00258 
00259   connect( this, SIGNAL( incidenceSelected(Incidence *, const QDate &) ),
00260            mEventViewer, SLOT ( setIncidence (Incidence *, const QDate &) ) );
00261 
00262   //TODO: do a pretty Summary,
00263   QString s;
00264   s = i18n( "<p><em>No Item Selected</em></p>"
00265            "<p>Select an event, to-do or journal entry to view its details "
00266            "here.</p>");
00267 
00268   mEventViewer->setDefaultText( s );
00269   QWhatsThis::add( mEventViewer,
00270                    i18n( "View the details of events, journal entries or to-dos "
00271                          "selected in KOrganizer's main view here." ) );
00272   mEventViewer->setIncidence( 0, QDate() );
00273 
00274   mViewManager->connectTodoView( mTodoList );
00275   mViewManager->connectView( mTodoList );
00276 
00277   KOGlobals::self()->
00278       setHolidays( new KHolidays( KOPrefs::instance()->mHolidays ) );
00279 
00280   connect( QApplication::clipboard(), SIGNAL( dataChanged() ),
00281            SLOT( checkClipboard() ) );
00282 
00283   connect( mTodoList, SIGNAL( incidenceSelected( Incidence *,const QDate & ) ),
00284            SLOT( processTodoListSelection( Incidence *,const QDate & ) ) );
00285   disconnect( mTodoList, SIGNAL( incidenceSelected( Incidence *,const QDate & ) ),
00286            this, SLOT( processMainViewSelection( Incidence *,const QDate & ) ) );
00287 
00288   kdDebug(5850) << "CalendarView::CalendarView() done" << endl;
00289 }
00290 
00291 CalendarView::~CalendarView()
00292 {
00293   kdDebug(5850) << "~CalendarView()" << endl;
00294 
00295   mCalendar->unregisterObserver( this );
00296 
00297   delete mDialogManager;
00298   delete mViewManager;
00299   delete mEventViewer;
00300   kdDebug(5850) << "~CalendarView() done" << endl;
00301 }
00302 
00303 void CalendarView::setCalendar( Calendar *cal )
00304 {
00305   kdDebug(5850)<<"CalendarView::setCalendar"<<endl;
00306   mCalendar = cal;
00307 
00308   delete mHistory;
00309   mHistory = new History( mCalendar );
00310   connect( mHistory, SIGNAL( undone() ), SLOT( updateView() ) );
00311   connect( mHistory, SIGNAL( redone() ), SLOT( updateView() ) );
00312 
00313   if ( mChanger ) delete mChanger;
00314   setIncidenceChanger( new IncidenceChanger( mCalendar, this ) );
00315 
00316   mCalendar->registerObserver( this );
00317 
00318   mDateNavigatorContainer->setCalendar( mCalendar );
00319 
00320   mTodoList->setCalendar( mCalendar );
00321 
00322   mEventViewer->setCalendar( mCalendar );
00323 }
00324 
00325 void CalendarView::setIncidenceChanger( IncidenceChangerBase *changer )
00326 {
00327   mChanger = changer;
00328   emit newIncidenceChanger( mChanger );
00329   connect( mChanger, SIGNAL( incidenceAdded( Incidence* ) ),
00330            this, SLOT( incidenceAdded( Incidence* ) ) );
00331   connect( mChanger, SIGNAL( incidenceChanged( Incidence*, Incidence*, KOGlobals::WhatChanged ) ),
00332            this, SLOT( incidenceChanged( Incidence*, Incidence*, KOGlobals::WhatChanged ) ) );
00333   connect( mChanger, SIGNAL( incidenceToBeDeleted( Incidence * ) ),
00334            this, SLOT( incidenceToBeDeleted( Incidence * ) ) );
00335   connect( mChanger, SIGNAL( incidenceDeleted( Incidence * ) ),
00336            this, SLOT( incidenceDeleted( Incidence * ) ) );
00337 
00338   connect( mChanger, SIGNAL( schedule( Scheduler::Method, Incidence*) ),
00339            this, SLOT( schedule( Scheduler::Method, Incidence*) ) );
00340 }
00341 
00342 Calendar *CalendarView::calendar()
00343 {
00344   if ( mCalendar ) return mCalendar;
00345   else return CalendarNull::self();
00346 }
00347 
00348 QPair<ResourceCalendar *, QString> CalendarView::viewSubResourceCalendar()
00349 {
00350   QPair<ResourceCalendar *, QString> p( 0, QString() );
00351   KOrg::BaseView *cV = mViewManager->currentView();
00352   if ( cV && cV == mViewManager->multiAgendaView() ) {
00353     cV = mViewManager->multiAgendaView()->selectedAgendaView();
00354   }
00355   if ( cV ) {
00356     p = qMakePair( cV->resourceCalendar(), cV->subResourceCalendar() );
00357   }
00358   return p;
00359 }
00360 
00361 KOIncidenceEditor *CalendarView::editorDialog( Incidence *incidence ) const
00362 {
00363   if (mDialogList.find(incidence) != mDialogList.end ())
00364     return mDialogList[incidence];
00365   else return 0;
00366 }
00367 
00368 QDate CalendarView::activeDate( bool fallbackToToday )
00369 {
00370   KOrg::BaseView *curView = mViewManager->currentView();
00371   if ( curView ) {
00372     if ( curView->selectionStart().isValid() ) {
00373       return curView->selectionStart().date();
00374     }
00375 
00376     // Try the view's selectedDates()
00377     if ( !curView->selectedIncidenceDates().isEmpty() ) {
00378       if ( curView->selectedIncidenceDates().first().isValid() ) {
00379         return curView->selectedIncidenceDates().first();
00380       }
00381     }
00382   }
00383 
00384   // When all else fails, use the navigator start date, or today.
00385   if ( fallbackToToday ) {
00386     return QDate::currentDate();
00387   } else {
00388     return mDateNavigator->selectedDates().first();
00389   }
00390 }
00391 
00392 QDate CalendarView::activeIncidenceDate()
00393 {
00394   KOrg::BaseView *curView = mViewManager->currentView();
00395   if ( curView ) {
00396     DateList dates = curView->selectedIncidenceDates();
00397     if ( !dates.isEmpty() ) {
00398       return dates.first();
00399     }
00400   }
00401 
00402   return QDate();
00403 }
00404 
00405 QDate CalendarView::startDate()
00406 {
00407   DateList dates = mDateNavigator->selectedDates();
00408 
00409   return dates.first();
00410 }
00411 
00412 QDate CalendarView::endDate()
00413 {
00414   DateList dates = mDateNavigator->selectedDates();
00415 
00416   return dates.last();
00417 }
00418 
00419 
00420 bool CalendarView::openCalendar(const QString& filename, bool merge)
00421 {
00422   kdDebug(5850) << "CalendarView::openCalendar(): " << filename << endl;
00423 
00424   if (filename.isEmpty()) {
00425     kdDebug(5850) << "CalendarView::openCalendar(): Error! Empty filename." << endl;
00426     return false;
00427   }
00428 
00429   if (!QFile::exists(filename)) {
00430     kdDebug(5850) << "CalendarView::openCalendar(): Error! File '" << filename
00431               << "' doesn't exist." << endl;
00432   }
00433 
00434   bool loadedSuccesfully = true;
00435   if ( !merge ) {
00436     mCalendar->close();
00437     CalendarLocal *cl = dynamic_cast<CalendarLocal*>( mCalendar );
00438     if ( cl ) {
00439       loadedSuccesfully = cl->load( filename );
00440     } else {
00441       CalendarResources *cr = dynamic_cast<CalendarResources*>( mCalendar );
00442       assert( cr ); // otherwise something is majorly wrong
00443       // openCalendar called without merge and a filename, what should we do?
00444       return false;
00445     }
00446   } else {
00447     // merge in a file
00448     CalendarResources *cl = dynamic_cast<CalendarResources *>( mCalendar );
00449     if ( cl && !cl->hasCalendarResources() ) {
00450       KMessageBox::sorry(
00451         this,
00452         i18n( "No calendars found, unable to merge the file into your calendar." ) );
00453       return false;
00454     }
00455     // FIXME: This is a nasty hack, since we need to set a parent for the
00456     //        resource selection dialog. However, we don't have any UI methods
00457     //        in the calendar, only in the CalendarResources::DestinationPolicy
00458     //        So we need to type-cast it and extract it from the CalendarResources
00459     QWidget *tmpparent = 0;
00460     if ( cl ) {
00461       tmpparent = cl->dialogParentWidget();
00462       cl->setDialogParentWidget( this );
00463     }
00464 
00465     FileStorage storage( mCalendar );
00466     storage.setFileName( filename );
00467     loadedSuccesfully = storage.load();
00468   }
00469 
00470   if ( loadedSuccesfully ) {
00471     if ( merge )
00472       setModified( true );
00473     else {
00474       setModified( false );
00475       mViewManager->setDocumentId( filename );
00476       mTodoList->setDocumentId( filename );
00477     }
00478     updateCategories();
00479     updateView();
00480     return true;
00481   } else {
00482     // while failing to load, the calendar object could
00483     // have become partially populated.  Clear it out.
00484     if ( !merge ) mCalendar->close();
00485 
00486     KMessageBox::error(this,i18n("Could not load calendar '%1'.").arg(filename));
00487 
00488     return false;
00489   }
00490 }
00491 
00492 bool CalendarView::saveCalendar( const QString& filename )
00493 {
00494   kdDebug(5850) << "CalendarView::saveCalendar(): " << filename << endl;
00495 
00496   // Store back all unsaved data into calendar object
00497   mViewManager->currentView()->flushView();
00498 
00499   FileStorage storage( mCalendar );
00500   storage.setFileName( filename );
00501   storage.setSaveFormat( new ICalFormat );
00502 
00503   bool success = storage.save();
00504 
00505   if ( !success ) {
00506     return false;
00507   }
00508 
00509   return true;
00510 }
00511 
00512 void CalendarView::closeCalendar()
00513 {
00514   kdDebug(5850) << "CalendarView::closeCalendar()" << endl;
00515 
00516   // child windows no longer valid
00517   emit closingDown();
00518 
00519   mCalendar->close();
00520   setModified( false );
00521   updateView();
00522 }
00523 
00524 void CalendarView::archiveCalendar()
00525 {
00526   mDialogManager->showArchiveDialog();
00527 }
00528 
00529 
00530 void CalendarView::readSettings()
00531 {
00532 //  kdDebug(5850) << "CalendarView::readSettings()" << endl;
00533 
00534   QString str;
00535 
00536   // read settings from the KConfig, supplying reasonable
00537   // defaults where none are to be found
00538 
00539   KConfig *config = KOGlobals::self()->config();
00540 
00541 #ifndef KORG_NOSPLITTER
00542   config->setGroup( "KOrganizer Geometry" );
00543 
00544   QValueList<int> sizes = config->readIntListEntry( "Separator1" );
00545   if ( sizes.count() != 2 ) {
00546     sizes << mDateNavigatorContainer->minimumSizeHint().width();
00547     sizes << 300;
00548   }
00549   mPanner->setSizes( sizes );
00550 
00551   sizes = config->readIntListEntry( "Separator2" );
00552   mLeftSplitter->setSizes( sizes );
00553 #endif
00554 
00555   mEventViewer->readSettings( config );
00556 
00557   mViewManager->readSettings( config );
00558   mTodoList->restoreLayout( config, QString( "Todo Layout" ) );
00559 
00560   readFilterSettings( config );
00561 
00562   config->setGroup( "Views" );
00563   const int dateCount = config->readNumEntry( "ShownDatesCount", 7 );
00564   if ( dateCount == 7 ) {
00565     mDateNavigator->selectWeek();
00566   } else {
00567     mDateNavigator->selectDates( mDateNavigator->selectedDates().first(), dateCount );
00568   }
00569 }
00570 
00571 
00572 void CalendarView::writeSettings()
00573 {
00574 //  kdDebug(5850) << "CalendarView::writeSettings" << endl;
00575 
00576   KConfig *config = KOGlobals::self()->config();
00577 
00578 #ifndef KORG_NOSPLITTER
00579   config->setGroup( "KOrganizer Geometry" );
00580 
00581   QValueList<int> list = mPanner->sizes();
00582   config->writeEntry( "Separator1", list );
00583 
00584   list = mLeftSplitter->sizes();
00585   config->writeEntry( "Separator2", list );
00586 #endif
00587   mEventViewer->writeSettings( config );
00588   mViewManager->writeSettings( config );
00589   mTodoList->saveLayout( config, QString( "Todo Layout" ) );
00590 
00591   KOPrefs::instance()->writeConfig();
00592 
00593   writeFilterSettings( config );
00594 
00595   config->setGroup( "Views" );
00596   config->writeEntry( "ShownDatesCount", mDateNavigator->selectedDates().count() );
00597 
00598   config->sync();
00599 }
00600 
00601 void CalendarView::readFilterSettings( KConfig *config )
00602 {
00603 //  kdDebug(5850) << "CalendarView::readFilterSettings()" << endl;
00604 
00605   mFilters.clear();
00606 
00607   config->setGroup( "General" );
00608   // FIXME: Move the filter loading and saving to the CalFilter class in libkcal
00609   QStringList filterList = config->readListEntry ("CalendarFilters" );
00610   QString currentFilter = config->readEntry( "Current Filter" );
00611 
00612   QStringList::ConstIterator it = filterList.begin();
00613   QStringList::ConstIterator end = filterList.end();
00614   while( it != end ) {
00615 //    kdDebug(5850) << "  filter: " << (*it) << endl;
00616     CalFilter *filter;
00617     filter = new CalFilter( *it );
00618     config->setGroup( "Filter_" + (*it) );
00619     filter->setCriteria( config->readNumEntry( "Criteria", 0 ) );
00620     filter->setCategoryList( config->readListEntry( "CategoryList" ) );
00621     if ( filter->criteria() & KCal::CalFilter::HideTodosWithoutAttendeeInEmailList )
00622       filter->setEmailList( KOPrefs::instance()->allEmails() );
00623     filter->setCompletedTimeSpan( config->readNumEntry( "HideTodoDays", 0 ) );
00624     mFilters.append( filter );
00625 
00626     ++it;
00627   }
00628 
00629   config->setGroup( "General" );
00630   int pos = filterList.findIndex( currentFilter );
00631   mCurrentFilter = 0;
00632   if ( pos>=0 ) {
00633     mCurrentFilter = mFilters.at( pos );
00634   }
00635   updateFilter();
00636 }
00637 
00638 void CalendarView::writeFilterSettings( KConfig *config )
00639 {
00640 //  kdDebug(5850) << "CalendarView::writeFilterSettings()" << endl;
00641 
00642   QStringList filterList;
00643 
00644   CalFilter *filter = mFilters.first();
00645   while( filter ) {
00646 //    kdDebug(5850) << " fn: " << filter->name() << endl;
00647     filterList << filter->name();
00648     config->setGroup( "Filter_" + filter->name() );
00649     config->writeEntry( "Criteria", filter->criteria() );
00650     config->writeEntry( "CategoryList", filter->categoryList() );
00651     config->writeEntry( "HideTodoDays", filter->completedTimeSpan() );
00652     filter = mFilters.next();
00653   }
00654   config->setGroup( "General" );
00655   config->writeEntry( "CalendarFilters", filterList );
00656   if ( mCurrentFilter ) {
00657     config->writeEntry( "Current Filter", mCurrentFilter->name() );
00658   } else {
00659     config->writeEntry( "Current Filter", QString::null );
00660   }
00661 }
00662 
00663 
00664 void CalendarView::goDate( const QDate &date )
00665 {
00666   mDateNavigator->selectDate( date );
00667 }
00668 
00669 void CalendarView::showDate( const QDate &date )
00670 {
00671   int dateCount = mDateNavigator->datesCount();
00672   if ( dateCount == 7 ) {
00673     mDateNavigator->selectWeek( date );
00674   } else {
00675     mDateNavigator->selectDates( date, dateCount );
00676   }
00677 }
00678 
00679 void CalendarView::goToday()
00680 {
00681   mDateNavigator->selectToday();
00682 }
00683 
00684 void CalendarView::goNext()
00685 {
00686   if ( dynamic_cast<KOMonthView*>( mViewManager->currentView() ) ) {
00687     mDateNavigator->selectNextMonth();
00688   } else {
00689     mDateNavigator->selectNext();
00690   }
00691 }
00692 
00693 void CalendarView::goPrevious()
00694 {
00695   if ( dynamic_cast<KOMonthView*>( mViewManager->currentView() ) ) {
00696     mDateNavigator->selectPreviousMonth();
00697   } else {
00698     mDateNavigator->selectPrevious();
00699   }
00700 }
00701 
00702 void CalendarView::updateConfig( const QCString& receiver)
00703 {
00704   if ( receiver != "korganizer" ) return;
00705   kdDebug(5850) << "CalendarView::updateConfig()" << endl;
00706 
00707   KOGlobals::self()->
00708     setHolidays( new KHolidays( KOPrefs::instance()->mHolidays ) );
00709 
00710   QString tz(  mCalendar->timeZoneId() );
00711   // Only set a new time zone if it changed. This prevents the window
00712   // from being modified on start
00713   if ( tz != KOPrefs::instance()->mTimeZoneId ) {
00714 
00715     const QString question( i18n("The timezone setting was changed. Do you want to keep the absolute time of "
00716                                 "the items in your calendar, which will show them to be at a different time than "
00717                                 "before, or move them to be at the old time also in the new timezone?") );
00718     int rc = KMessageBox::questionYesNo( this, question,
00719                               i18n("Keep Absolute Times?"),
00720                               KGuiItem(i18n("Keep Times")),
00721                               KGuiItem(i18n("Move Times")),
00722                               "calendarKeepAbsoluteTimes");
00723     if ( rc == KMessageBox::Yes ) {
00724       // user wants us to shift
00725       mCalendar->setTimeZoneIdViewOnly( KOPrefs::instance()->mTimeZoneId );
00726     } else {
00727       // only set the new timezone, wihtout shifting events, they will be
00728       // interpreted as being in the new timezone now
00729       mCalendar->setTimeZoneId( KOPrefs::instance()->mTimeZoneId );
00730     }
00731   }
00732   emit configChanged();
00733 
00734   //switch beetween merged, side by side and tabbed agenda if needed
00735   mViewManager->updateMultiCalendarDisplay();
00736 
00737   // To make the "fill window" configurations work
00738   mViewManager->raiseCurrentView();
00739 }
00740 
00741 
00742 void CalendarView::incidenceAdded( Incidence *incidence )
00743 {
00744   setModified( true );
00745   history()->recordAdd( incidence );
00746   changeIncidenceDisplay( incidence, KOGlobals::INCIDENCEADDED );
00747   updateUnmanagedViews();
00748   checkForFilteredChange( incidence );
00749 }
00750 
00751 void CalendarView::incidenceChanged( Incidence *oldIncidence,
00752                                      Incidence *newIncidence,
00753                                      KOGlobals::WhatChanged modification )
00754 {
00755   KOIncidenceEditor *tmp = editorDialog( newIncidence );
00756   if ( tmp ) {
00757     kdDebug(5850) << "Incidence modified and open" << endl;
00758     tmp->modified();
00759   }
00760   setModified( true );
00761   history()->recordEdit( oldIncidence, newIncidence );
00762 
00763   // Record completed todos in journals, if enabled. we should to this here in
00764   // favour of the todolist. users can mark a task as completed in an editor
00765   // as well.
00766   if ( newIncidence->type() == "Todo" &&
00767        KOPrefs::instance()->recordTodosInJournals() &&
00768        ( modification == KOGlobals::COMPLETION_MODIFIED ||
00769          modification == KOGlobals::COMPLETION_MODIFIED_WITH_RECURRENCE ) ) {
00770 
00771       Todo *todo = static_cast<Todo *>(newIncidence);
00772       if ( todo->isCompleted() ||
00773            modification == KOGlobals::COMPLETION_MODIFIED_WITH_RECURRENCE ) {
00774         QString timeStr = KGlobal::locale()->formatTime( QTime::currentTime() );
00775         QString description = i18n( "To-do completed: %1 (%2)" ).arg(
00776           newIncidence->summary() ).arg( timeStr );
00777 
00778         Journal::List journals = calendar()->journals( QDate::currentDate() );
00779         Journal *journal;
00780 
00781         if ( journals.isEmpty() ) {
00782           journal = new Journal();
00783           journal->setDtStart( QDateTime::currentDateTime() );
00784 
00785           QString dateStr = KGlobal::locale()->formatDate( QDate::currentDate() );
00786           journal->setSummary( i18n("Journal of %1").arg( dateStr ) );
00787           journal->setDescription( description );
00788 
00789           //TODO: recorded to-dos should save into the standard resource always
00790           if ( !mChanger->addIncidence( journal, 0, QString(), this ) ) {
00791             KODialogManager::errorSaveIncidence( this, journal );
00792             delete journal;
00793             return;
00794           }
00795 
00796         } else { // journal list is not empty
00797           journal = *(journals.at(0));
00798           Journal *oldJournal = journal->clone();
00799           journal->setDescription( journal->description().append( "\n" + description ) );
00800 
00801           if ( !mChanger->changeIncidence( oldJournal, journal,
00802                                            KOGlobals::DESCRIPTION_MODIFIED, this ) ) {
00803             KODialogManager::errorSaveIncidence( this, journal );
00804             delete journal;
00805             return;
00806           }
00807         }
00808       }
00809   }
00810 
00811   changeIncidenceDisplay( newIncidence, KOGlobals::INCIDENCEEDITED );
00812   updateUnmanagedViews();
00813   checkForFilteredChange( newIncidence );
00814 }
00815 
00816 void CalendarView::incidenceToBeDeleted( Incidence *incidence )
00817 {
00818   KOIncidenceEditor *tmp = editorDialog( incidence );
00819   if (tmp) {
00820     kdDebug(5850) << "Incidence to be deleted and open in editor" << endl;
00821     tmp->delayedDestruct();
00822   }
00823   setModified( true );
00824   history()->recordDelete( incidence );
00825 //  changeIncidenceDisplay( incidence, KOGlobals::INCIDENCEDELETED );
00826   updateUnmanagedViews();
00827 }
00828 
00829 void CalendarView::incidenceDeleted( Incidence *incidence )
00830 {
00831   changeIncidenceDisplay( incidence, KOGlobals::INCIDENCEDELETED );
00832   updateUnmanagedViews();
00833 }
00834 
00835 void CalendarView::checkForFilteredChange( Incidence *incidence )
00836 {
00837   CalFilter *filter = calendar()->filter();
00838   if ( filter && !filter->filterIncidence( incidence ) ) {
00839     // Incidence is filtered and thus not shown in the view, tell the
00840     // user so that he isn't surprised if his new event doesn't show up
00841     KMessageBox::information( this, i18n("The item \"%1\" is filtered by "
00842                  "your current filter rules, so it will be hidden and not "
00843                  "appear in the view.").arg( incidence->summary() ),
00844                  i18n("Filter Applied"), "ChangedIncidenceFiltered" );
00845   }
00846 }
00847 
00848 void CalendarView::startMultiModify( const QString &text )
00849 {
00850   history()->startMultiModify( text );
00851 }
00852 
00853 void CalendarView::endMultiModify()
00854 {
00855   history()->endMultiModify();
00856 }
00857 
00858 
00859 void CalendarView::changeIncidenceDisplay( Incidence *incidence, int action )
00860 {
00861   mDateNavigatorContainer->updateView();
00862   mDialogManager->updateSearchDialog();
00863 
00864   if ( incidence ) {
00865     // If there is an event view visible update the display
00866     mViewManager->currentView()->changeIncidenceDisplay( incidence, action );
00867     if ( mTodoList ) mTodoList->changeIncidenceDisplay( incidence, action );
00868     mEventViewer->changeIncidenceDisplay( incidence, activeDate( true ), action );
00869   } else {
00870     mViewManager->currentView()->updateView();
00871     if ( mTodoList ) mTodoList->updateView();
00872   }
00873 }
00874 
00875 
00876 void CalendarView::updateView(const QDate &start, const QDate &end)
00877 {
00878   mTodoList->updateView();
00879   mViewManager->updateView(start, end);
00880   mDateNavigatorContainer->updateView();
00881 }
00882 
00883 void CalendarView::updateView()
00884 {
00885   DateList tmpList = mDateNavigator->selectedDates();
00886 
00887   // We assume that the navigator only selects consecutive days.
00888   updateView( tmpList.first(), tmpList.last() );
00889 }
00890 
00891 void CalendarView::updateUnmanagedViews()
00892 {
00893   mDateNavigatorContainer->updateDayMatrix();
00894 }
00895 
00896 int CalendarView::msgItemDelete( Incidence *incidence )
00897 {
00898   return KMessageBox::warningContinueCancel(this,
00899       i18n("The item \"%1\" will be permanently deleted.").arg( incidence->summary() ),
00900       i18n("KOrganizer Confirmation"), KGuiItem(i18n("&Delete"),"editdelete"));
00901 }
00902 
00903 
00904 void CalendarView::edit_cut()
00905 {
00906   Incidence *incidence = incToSendToClipboard( true );
00907 
00908   if ( !incidence || !mChanger ) {
00909     KNotifyClient::beep();
00910     return;
00911   }
00912 
00913   Incidence::List incidences;
00914   int km = KMessageBox::Yes;
00915 
00916   if ( !incidence->relations().isEmpty() &&
00917        incidence->type() == "Todo" ) { // Only todos (yet?)
00918     km = KMessageBox::questionYesNoCancel( this,
00919                                            i18n("The item \"%1\" has sub-to-dos. "
00920                                                 "Do you want to cut just this item and "
00921                                                 "make all its sub-to-dos independent, or "
00922                                                 "cut the to-do with all its sub-to-dos?"
00923                                              ).arg( incidence->summary() ),
00924                                            i18n("KOrganizer Confirmation"),
00925                                            i18n("Cut Only This"),
00926                                            i18n("Cut All"));
00927   }
00928 
00929   if ( km == KMessageBox::Yes ) { // only one
00930     incidences.append( incidence );
00931     makeChildrenIndependent( incidence );
00932   } else if ( km == KMessageBox::No ) { // all
00933     // load incidence + children + grandchildren...
00934     getIncidenceHierarchy( incidence, incidences );
00935   }
00936 
00937   if ( km != KMessageBox::Cancel ) {
00938     mChanger->cutIncidences( incidences, this );
00939   }
00940 }
00941 
00942 void CalendarView::edit_copy()
00943 {
00944   Incidence *incidence = incToSendToClipboard( false );
00945 
00946   if ( !incidence ) {
00947     KNotifyClient::beep();
00948     return;
00949   }
00950 
00951   Incidence::List incidences;
00952   int km = KMessageBox::Yes;
00953 
00954   if ( !incidence->relations().isEmpty() &&
00955        incidence->type() == "Todo" ) { // only todos.
00956     km = KMessageBox::questionYesNoCancel( this,
00957                                            i18n("The item \"%1\" has sub-to-dos. "
00958                                                 "Do you want to copy just this item or "
00959                                                 "copy the to-do with all its sub-to-dos?"
00960                                              ).arg( incidence->summary() ),
00961                                            i18n("KOrganizer Confirmation"),
00962                                            i18n("Copy Only This"),
00963                                            i18n("Copy All"));
00964   }
00965 
00966   if ( km == KMessageBox::Yes ) { // only one
00967     incidences.append( incidence );
00968   } else if ( km == KMessageBox::No ) { // all
00969     // load incidence + children + grandchildren...
00970     getIncidenceHierarchy( incidence, incidences );
00971   }
00972 
00973   if ( km != KMessageBox::Cancel ) {
00974     DndFactory factory( mCalendar );
00975     if ( !factory.copyIncidences( incidences ) ) {
00976       KNotifyClient::beep();
00977     }
00978   }
00979 }
00980 
00981 Incidence* CalendarView::incToSendToClipboard( bool cut )
00982 {
00983   Incidence *originalInc = selectedIncidence();
00984 
00985   if ( originalInc && originalInc->doesRecur() &&
00986        originalInc->type() == "Event" ) { // temporary, until recurring to-dos are fixed
00987 
00988     Incidence *inc;
00989     KOGlobals::WhichOccurrences chosenOption;
00990     if ( cut ) {
00991       inc = singleOccurrenceOrAll( originalInc, KOGlobals::CUT, chosenOption, QDate(), true );
00992     } else {
00993       // The user is copying, the original incidence can't be changed
00994       // we can only dissociate a copy
00995       Incidence *originalIncSaved = originalInc->clone();
00996       inc = singleOccurrenceOrAll( originalIncSaved, KOGlobals::COPY, chosenOption, QDate(), false );
00997 
00998       // no dissociation, no need to leak our clone
00999       if ( chosenOption == KOGlobals::ALL ) {
01000         inc = originalInc;
01001         delete originalIncSaved;
01002       }
01003 
01004       // no need to leak our clone
01005       if ( chosenOption == KOGlobals::NONE ) {
01006         delete originalIncSaved;
01007       }
01008     }
01009 
01010     return inc;
01011   } else {
01012     return originalInc;
01013   }
01014 }
01015 
01016 void CalendarView::edit_paste()
01017 {
01018 // If in agenda and month view, use the selected time and date from there.
01019 // In all other cases, use the navigator's selected date.
01020 
01021   QDate date;          // null dates are invalid, that's what we want
01022   bool timeSet = false;// flag denoting if the time has been set.
01023   QTime time;          // null dates are valid, so rely on the timeSet flag
01024   QDateTime endDT;     // null datetimes are invalid, that's what we want
01025   bool useEndTime = false;
01026 
01027   KOrg::BaseView *curView = mViewManager->currentView();
01028 
01029   KOAgendaView *aView = mViewManager->agendaView();
01030   KOMonthView *mView = mViewManager->monthView();
01031   if ( curView == mViewManager->multiAgendaView() ) {
01032     aView = mViewManager->multiAgendaView()->selectedAgendaView();
01033     curView = aView;
01034   }
01035 
01036   if ( !curView ) {
01037     return;
01038   }
01039 
01040   if ( curView == aView && aView->selectionStart().isValid() ) {
01041     date = aView->selectionStart().date();
01042     endDT = aView->selectionEnd();
01043     useEndTime = !aView->selectedIsSingleCell();
01044     if ( !aView->selectedIsAllDay() ) {
01045       time = aView->selectionStart().time();
01046       timeSet = true;
01047     }
01048   } else if ( curView == mView && mView->selectionStart().isValid() ) {
01049     date = mView->selectionStart().date();
01050   } else if ( !mDateNavigator->selectedDates().isEmpty() &&
01051               curView->supportsDateNavigation() ) {
01052     // default to the selected date from the navigator
01053     date = mDateNavigator->selectedDates().first();
01054   }
01055 
01056   if ( !date.isValid() && curView->supportsDateNavigation() ) {
01057     KMessageBox::sorry(
01058       this,
01059       i18n( "Paste failed: unable to determine a valid target date." ) );
01060     return;
01061   }
01062 
01063   DndFactory factory( mCalendar );
01064   Incidence::List pastedIncidences;
01065   if ( timeSet && time.isValid() ) {
01066     pastedIncidences = factory.pasteIncidences( date, &time );
01067   } else {
01068     pastedIncidences = factory.pasteIncidences( date );
01069   }
01070 
01071   Incidence::List::Iterator it;
01072   for ( it = pastedIncidences.begin(); it != pastedIncidences.end(); ++it ) {
01073     QPair<ResourceCalendar *, QString>p = viewSubResourceCalendar();
01074 
01075     // FIXME: use a visitor here
01076     if ( ( *it )->type() == "Event" ) {
01077       Event *pastedEvent = static_cast<Event*>( *it );
01078       // only use selected area if event is of the same type
01079       // (all-day or non-all-day) as the current selection is
01080       if ( aView && endDT.isValid() && useEndTime ) {
01081         if ( ( pastedEvent->doesFloat() && aView->selectedIsAllDay() ) ||
01082              ( !pastedEvent->doesFloat() && !aView->selectedIsAllDay() ) ) {
01083           pastedEvent->setDtEnd( endDT );
01084         }
01085       }
01086 
01087       // KCal supports events with relations, but korganizer doesn't
01088       // so unset it. It can even come from other application.
01089       pastedEvent->setRelatedTo( 0 );
01090       pastedEvent->setRelatedToUid( QString() );
01091 
01092       mChanger->addIncidence( pastedEvent, p.first, p.second, this );
01093 
01094     } else if ( ( *it )->type() == "Todo" ) {
01095       Todo *pastedTodo = static_cast<Todo*>( *it );
01096       Todo *_selectedTodo = selectedTodo();
01097 
01098       // if we are cutting a hierarchy only the root
01099       // should be son of _selectedTodo
01100       if ( _selectedTodo && !pastedTodo->relatedTo() ) {
01101         pastedTodo->setRelatedTo( _selectedTodo );
01102       }
01103       mChanger->addIncidence( pastedTodo, p.first, p.second, this );
01104     }
01105   }
01106 }
01107 
01108 void CalendarView::edit_options()
01109 {
01110   mDialogManager->showOptionsDialog();
01111 }
01112 
01113 void CalendarView::dateTimesForNewEvent( QDateTime &startDt, QDateTime &endDt, bool &allDay )
01114 {
01115   mViewManager->currentView()->eventDurationHint( startDt, endDt, allDay );
01116 
01117   if ( !startDt.isValid() || !endDt.isValid() ) {
01118     startDt.setDate( activeDate( true ) );
01119     startDt.setTime( KOPrefs::instance()->mStartTime.time() );
01120 
01121     int addSecs = ( KOPrefs::instance()->mDefaultDuration.time().hour() * 3600 ) +
01122                   ( KOPrefs::instance()->mDefaultDuration.time().minute() * 60 );
01123 
01124     endDt = startDt.addSecs( addSecs );
01125   }
01126 }
01127 
01128 KOEventEditor *CalendarView::newEventEditor( ResourceCalendar *res, const QString &subRes,
01129                                              const QDateTime &startDtParam,
01130                                              const QDateTime &endDtParam, bool allDayParam )
01131 {
01132   // let the current view change the default start/end datetime
01133   bool allDay = allDayParam;
01134   QDateTime startDt( startDtParam ), endDt( endDtParam );
01135   // Adjust the start/end date times (i.e. replace invalid values by defaults,
01136   // and let the view adjust the type.
01137   dateTimesForNewEvent( startDt, endDt, allDay );
01138 
01139   KOEventEditor *eventEditor = mDialogManager->getEventEditor();
01140   eventEditor->newEvent();
01141   connectIncidenceEditor( eventEditor );
01142   eventEditor->setResource( res, subRes );
01143   eventEditor->setDates( startDt, endDt, allDay );
01144   mDialogManager->connectTypeAhead( eventEditor, dynamic_cast<KOrg::AgendaView*>(viewManager()->currentView()) );
01145   return eventEditor;
01146 }
01147 
01148 void CalendarView::newEvent()
01149 {
01150   KOrg::BaseView *currentView = mViewManager->currentView();
01151 
01152   if ( currentView == mViewManager->multiAgendaView() ) {
01153     currentView = mViewManager->multiAgendaView()->selectedAgendaView();
01154   }
01155 
01156   if ( currentView ) {
01157     newEvent( currentView->resourceCalendar(),
01158               currentView->subResourceCalendar() );
01159   }
01160 }
01161 
01162 void CalendarView::newEvent( ResourceCalendar *res, const QString &subRes )
01163 {
01164   kdDebug(5850) << "CalendarView::newEvent()" << endl;
01165   newEvent( res, subRes, QDateTime(), QDateTime() );
01166 }
01167 
01168 void CalendarView::newEvent( ResourceCalendar *res, const QString &subRes,
01169                              const QDate &dt )
01170 {
01171   QDateTime startDt( dt, KOPrefs::instance()->mStartTime.time() );
01172   newEvent( res, subRes, QDateTime( dt ), QDateTime() );
01173 }
01174 
01175 void CalendarView::newEvent( ResourceCalendar *res, const QString &subRes,
01176                              const QDateTime &startDt )
01177 {
01178   newEvent( res, subRes, startDt, QDateTime() );
01179 }
01180 
01181 void CalendarView::newEvent( ResourceCalendar *res, const QString &subRes,
01182                              const QDateTime &startDt, const QDateTime &endDt,
01183                              bool allDay )
01184 {
01185   KOEventEditor *eventEditor = newEventEditor( res, subRes,
01186                                                startDt, endDt, allDay );
01187   eventEditor->show();
01188 }
01189 
01190 void CalendarView::newEvent( ResourceCalendar *res, const QString &subRes,
01191                              const QString &summary, const QString &description,
01192                              const QStringList &attachments, const QStringList &attendees,
01193                              const QStringList &attachmentMimetypes, bool inlineAttachment )
01194 {
01195   KOEventEditor *eventEditor = newEventEditor( res, subRes );
01196   eventEditor->setTexts( summary, description );
01197   // if attach or attendee list is empty, these methods don't do anything, so
01198   // it's safe to call them in every case
01199   eventEditor->addAttachments( attachments, attachmentMimetypes, inlineAttachment );
01200   eventEditor->addAttendees( attendees );
01201   eventEditor->show();
01202 }
01203 
01204 void CalendarView::newTodo( ResourceCalendar *res, const QString &subRes,
01205                             const QString &summary, const QString &description,
01206                             const QStringList &attachments, const QStringList &attendees,
01207                             const QStringList &attachmentMimetypes,
01208                             bool inlineAttachment, bool isTask )
01209 {
01210   kdDebug(5850) << k_funcinfo << endl;
01211   KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01212   connectIncidenceEditor( todoEditor );
01213   todoEditor->newTodo();
01214   todoEditor->setResource( res, subRes );
01215   todoEditor->setTexts( summary, description );
01216   todoEditor->addAttachments( attachments, attachmentMimetypes, inlineAttachment );
01217   todoEditor->addAttendees( attendees );
01218   todoEditor->selectCreateTask( isTask );
01219   todoEditor->show();
01220 }
01221 
01222 void CalendarView::newTodo()
01223 {
01224   KOrg::BaseView *currentView = mViewManager->currentView();
01225 
01226   if ( currentView == mViewManager->multiAgendaView() ) {
01227     currentView = mViewManager->multiAgendaView()->selectedAgendaView();
01228   }
01229   if ( currentView ) {
01230     newTodo( currentView->resourceCalendar(),
01231              currentView->subResourceCalendar() );
01232   }
01233 }
01234 
01235 void CalendarView::newTodo( ResourceCalendar *res, const QString &subRes )
01236 {
01237   kdDebug(5850) << k_funcinfo << endl;
01238   QDateTime dtDue;
01239   bool allday = true;
01240   KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01241   connectIncidenceEditor( todoEditor );
01242   todoEditor->newTodo();
01243   todoEditor->setResource( res, subRes );
01244   if ( mViewManager->currentView()->isEventView() ) {
01245     dtDue.setDate( mDateNavigator->selectedDates().first() );
01246     QDateTime dtDummy = QDateTime::currentDateTime();
01247     mViewManager->currentView()->eventDurationHint( dtDue, dtDummy, allday );
01248     todoEditor->setDates( dtDue, allday );
01249   }
01250   todoEditor->show();
01251 }
01252 
01253 void CalendarView::newTodo( ResourceCalendar *res, const QString &subRes,
01254                             const QDate &date )
01255 {
01256   KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01257   connectIncidenceEditor( todoEditor );
01258   todoEditor->newTodo();
01259   todoEditor->setResource( res, subRes );
01260   todoEditor->setDates( QDateTime( date, QTime::currentTime() ), true );
01261   todoEditor->show();
01262 }
01263 
01264 void CalendarView::newJournal()
01265 {
01266   KOrg::BaseView *currentView = mViewManager->currentView();
01267 
01268   if ( currentView == mViewManager->multiAgendaView() ) {
01269     currentView = mViewManager->multiAgendaView()->selectedAgendaView();
01270   }
01271 
01272   if ( currentView ) {
01273     newJournal( currentView->resourceCalendar(),
01274                 currentView->subResourceCalendar() );
01275   }
01276 }
01277 
01278 void CalendarView::newJournal( ResourceCalendar *res, const QString &subRes )
01279 {
01280   kdDebug(5850) << "CalendarView::newJournal()" << endl;
01281   newJournal( res, subRes, QString::null, QDate() );
01282 }
01283 
01284 void CalendarView::newJournal( ResourceCalendar *res, const QString &subRes,
01285                                const QDate &date)
01286 {
01287   newJournal( res, subRes, QString::null, date );
01288 }
01289 
01290 void CalendarView::newJournal( ResourceCalendar *res, const QString &subRes,
01291                                const QString &text, const QDate &date )
01292 {
01293   KOJournalEditor *journalEditor = mDialogManager->getJournalEditor();
01294   connectIncidenceEditor( journalEditor );
01295   journalEditor->newJournal();
01296   journalEditor->setResource( res, subRes );
01297   journalEditor->setTexts( text );
01298   if ( !date.isValid() ) {
01299     journalEditor->setDate( mDateNavigator->selectedDates().first() );
01300   } else {
01301     journalEditor->setDate( date );
01302   }
01303   journalEditor->show();
01304 }
01305 
01306 void CalendarView::newSubTodo()
01307 {
01308   Todo *todo = selectedTodo();
01309   if ( todo ) newSubTodo( todo );
01310 }
01311 
01312 void CalendarView::newSubTodo(Todo *parentEvent)
01313 {
01314   KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01315   connectIncidenceEditor( todoEditor );
01316   todoEditor->newTodo();
01317   todoEditor->setDates( QDateTime(), false, parentEvent );
01318   todoEditor->show();
01319 }
01320 
01321 bool CalendarView::addIncidence( const QString &ical )
01322 {
01323   kdDebug(5850) << "CalendarView::addIncidence:\n" << ical << endl;
01324   ICalFormat format;
01325   format.setTimeZone( mCalendar->timeZoneId(), true );
01326   Incidence *incidence = format.fromString( ical );
01327   if ( !incidence ) return false;
01328   if ( !mChanger->addIncidence( incidence, 0, QString(), this ) ) {
01329     delete incidence;
01330     return false;
01331   }
01332   return true;
01333 }
01334 
01335 void CalendarView::appointment_show()
01336 {
01337   Incidence *incidence = selectedIncidence();
01338   if ( incidence ) {
01339     showIncidence( incidence, activeIncidenceDate() );
01340   } else {
01341     KNotifyClient::beep();
01342   }
01343 }
01344 
01345 void CalendarView::appointment_edit()
01346 {
01347   Incidence *incidence = selectedIncidence();
01348   if ( incidence ) {
01349     editIncidence( incidence, activeIncidenceDate() );
01350   } else {
01351     KNotifyClient::beep();
01352   }
01353 }
01354 
01355 void CalendarView::appointment_delete()
01356 {
01357   Incidence *incidence = selectedIncidence();
01358   if (incidence)
01359     deleteIncidence( incidence );
01360   else
01361     KNotifyClient::beep();
01362 }
01363 
01364 void CalendarView::todo_unsub()
01365 {
01366   Todo *anTodo = selectedTodo();
01367   if( incidence_unsub ( anTodo ) ) {
01368     updateView();
01369   }
01370 }
01371 
01372 bool CalendarView::incidence_unsub( Incidence *inc )
01373 {
01374   bool status = false;
01375   if ( !inc || !inc->relatedTo() ) {
01376     return false;
01377   }
01378 
01379   if ( mChanger->beginChange( inc, 0, QString() ) ) {
01380       Incidence *oldInc = inc->clone();
01381       inc->setRelatedTo( 0 );
01382       mChanger->changeIncidence( oldInc, inc, KOGlobals::RELATION_MODIFIED, this );
01383       mChanger->endChange( inc, 0, QString() );
01384       delete oldInc;
01385       setModified(true);
01386       status = true;
01387   }
01388   if ( ! status ) {
01389     KMessageBox::sorry( this, i18n("Unable to turn sub-to-do into a top-level "
01390         "to-do, because it cannot be locked.") );
01391   }
01392 
01393   return status;
01394 }
01395 
01396 bool CalendarView::makeSubTodosIndependent ( )
01397 {
01398   bool  status = false;
01399   Todo *aTodo = selectedTodo();
01400 
01401   if ( makeChildrenIndependent( aTodo ) ) {
01402     updateView();
01403     status = true;
01404   }
01405   return status;
01406 }
01407 
01408 bool CalendarView::makeChildrenIndependent ( Incidence *inc )
01409 {
01410   if ( !inc || inc->relations().isEmpty() ) {
01411     return false;
01412   }
01413 
01414   startMultiModify ( i18n( "Make sub-to-dos independent" ) );
01415   Incidence::List subIncs( inc->relations() );
01416   Incidence::List::Iterator it;
01417 
01418   for ( it= subIncs.begin(); it != subIncs.end(); ++it ) {
01419     incidence_unsub ( *it );
01420   }
01421   endMultiModify();
01422   return true;
01423 }
01424 
01425 bool CalendarView::deleteIncidence( const QString &uid, bool force )
01426 {
01427   Incidence *inc = mCalendar->incidence( uid );
01428   if ( inc ) {
01429     deleteIncidence( inc, force );
01430     return true;
01431   } else {
01432     return false;
01433   }
01434 }
01435 
01436 void CalendarView::toggleAlarm( Incidence *incidence )
01437 {
01438   if ( !incidence || !mChanger ) {
01439     kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01440     return;
01441   }
01442   Incidence*oldincidence = incidence->clone();
01443   if ( !mChanger->beginChange( incidence, 0, QString() ) ) {
01444     kdDebug(5850) << "Unable to lock incidence " << endl;
01445     delete oldincidence;
01446     return;
01447   }
01448 
01449   Alarm::List alarms = incidence->alarms();
01450   Alarm::List::ConstIterator it;
01451   for ( it = alarms.begin(); it != alarms.end(); ++it ) {
01452     (*it)->toggleAlarm();
01453   }
01454   if ( alarms.isEmpty() ) {
01455     // Add an alarm if it didn't have one
01456     Alarm *alm = incidence->newAlarm();
01457     alm->setType( Alarm::Display );
01458     alm->setEnabled( true );
01459     int duration; // in secs
01460     switch( KOPrefs::instance()->mReminderTimeUnits ) {
01461     default:
01462     case 0: // mins
01463       duration = KOPrefs::instance()->mReminderTime * 60;
01464       break;
01465     case 1: // hours
01466       duration = KOPrefs::instance()->mReminderTime * 60 * 60;
01467       break;
01468     case 2: // days
01469       duration = KOPrefs::instance()->mReminderTime * 60 * 60 * 24;
01470       break;
01471     }
01472     if ( incidence->type() == "Event" ) {
01473       alm->setStartOffset( KCal::Duration( -duration ) );
01474     } else {
01475       alm->setEndOffset( KCal::Duration( -duration ) );
01476     }
01477   }
01478   mChanger->changeIncidence( oldincidence, incidence, KOGlobals::ALARM_MODIFIED, this );
01479   mChanger->endChange( incidence, 0, QString() );
01480   delete oldincidence;
01481 
01482 //  mClickedItem->updateIcons();
01483 }
01484 
01485 void CalendarView::dissociateOccurrence( Incidence *incidence, const QDate &date )
01486 {
01487   if ( !incidence || !mChanger ) {
01488     kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01489     return;
01490   }
01491 
01492   QPair<ResourceCalendar *, QString>p =
01493     CalHelper::incSubResourceCalendar( calendar(), incidence );
01494 
01495   if ( !mChanger->beginChange( incidence, p.first, p.second ) ) {
01496     kdDebug(5850) << "Unable to lock incidence " << endl;
01497     return;
01498   }
01499   startMultiModify( i18n("Dissociate occurrence") );
01500   Incidence*oldincidence = incidence->clone();
01501 
01502   Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true );
01503 
01504   if ( newInc ) {
01505     mChanger->changeIncidence( oldincidence, incidence, KOGlobals::NOTHING_MODIFIED, this );
01506     mChanger->addIncidence( newInc, p.first, p.second, this );
01507   } else {
01508     KMessageBox::sorry( this, i18n("Dissociating the occurrence failed."),
01509       i18n("Dissociating Failed") );
01510   }
01511   mChanger->endChange( incidence, p.first, p.second );
01512   endMultiModify();
01513   delete oldincidence;
01514 }
01515 
01516 void CalendarView::dissociateFutureOccurrence( Incidence *incidence, const QDate &date )
01517 {
01518   if ( !incidence || !mChanger ) {
01519     kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01520     return;
01521   }
01522 
01523   QPair<ResourceCalendar *, QString>p =
01524     CalHelper::incSubResourceCalendar( calendar(), incidence );
01525 
01526   if ( !mChanger->beginChange( incidence, p.first, p.second ) ) {
01527     kdDebug(5850) << "Unable to lock incidence " << endl;
01528     return;
01529   }
01530   startMultiModify( i18n("Dissociate future occurrences") );
01531   Incidence*oldincidence = incidence->clone();
01532 
01533   Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true );
01534   if ( newInc ) {
01535     mChanger->changeIncidence( oldincidence, incidence, KOGlobals::NOTHING_MODIFIED, this );
01536     mChanger->addIncidence( newInc, p.first, p.second, this );
01537   } else {
01538     KMessageBox::sorry( this, i18n("Dissociating the future occurrences failed."),
01539       i18n("Dissociating Failed") );
01540   }
01541   endMultiModify();
01542   mChanger->endChange( incidence, p.first, p.second );
01543   delete oldincidence;
01544 }
01545 
01546 
01547 /*****************************************************************************/
01548 
01549 
01550 void CalendarView::schedule_publish(Incidence *incidence)
01551 {
01552   if (incidence == 0)
01553     incidence = selectedIncidence();
01554 
01555   if (!incidence) {
01556     KMessageBox::information( this, i18n("No item selected."),
01557                               "PublishNoEventSelected" );
01558     return;
01559   }
01560 
01561   PublishDialog *publishdlg = new PublishDialog();
01562   if (incidence->attendeeCount()>0) {
01563     Attendee::List attendees = incidence->attendees();
01564     Attendee::List::ConstIterator it;
01565     for( it = attendees.begin(); it != attendees.end(); ++it ) {
01566       publishdlg->addAttendee( *it );
01567     }
01568   }
01569   if ( publishdlg->exec() == QDialog::Accepted ) {
01570     Incidence *inc = incidence->clone();
01571     inc->registerObserver( 0 );
01572     inc->clearAttendees();
01573 
01574     // Send the mail
01575     KCal::MailScheduler scheduler( mCalendar );
01576     if ( scheduler.publish( incidence, publishdlg->addresses() ) ) {
01577       KMessageBox::information( this, i18n("The item information was successfully sent."),
01578                                 i18n("Publishing"), "IncidencePublishSuccess" );
01579     } else {
01580       KMessageBox::error( this, i18n("Unable to publish the item '%1'").arg( incidence->summary() ) );
01581     }
01582   }
01583   delete publishdlg;
01584 }
01585 
01586 void CalendarView::schedule_request(Incidence *incidence)
01587 {
01588   schedule(Scheduler::Request,incidence);
01589 }
01590 
01591 void CalendarView::schedule_refresh(Incidence *incidence)
01592 {
01593   schedule(Scheduler::Refresh,incidence);
01594 }
01595 
01596 void CalendarView::schedule_cancel(Incidence *incidence)
01597 {
01598   schedule(Scheduler::Cancel,incidence);
01599 }
01600 
01601 void CalendarView::schedule_add(Incidence *incidence)
01602 {
01603   schedule(Scheduler::Add,incidence);
01604 }
01605 
01606 void CalendarView::schedule_reply(Incidence *incidence)
01607 {
01608   schedule(Scheduler::Reply,incidence);
01609 }
01610 
01611 void CalendarView::schedule_counter(Incidence *incidence)
01612 {
01613   schedule(Scheduler::Counter,incidence);
01614 }
01615 
01616 void CalendarView::schedule_declinecounter(Incidence *incidence)
01617 {
01618   schedule(Scheduler::Declinecounter,incidence);
01619 }
01620 
01621 void CalendarView::schedule_forward( Incidence *incidence )
01622 {
01623   if ( !incidence ) {
01624     incidence = selectedIncidence();
01625   }
01626 
01627   if ( !incidence ) {
01628     KMessageBox::information(
01629       this,
01630       i18n( "No item selected." ),
01631       i18n( "Forwarding" ),
01632       "ForwardNoEventSelected" );
01633     return;
01634   }
01635 
01636   PublishDialog publishdlg;
01637   if ( publishdlg.exec() == QDialog::Accepted ) {
01638     QString recipients = publishdlg.addresses();
01639     if ( incidence->organizer().isEmpty() ) {
01640       incidence->setOrganizer( Person( KOPrefs::instance()->fullName(),
01641                                        KOPrefs::instance()->email() ) );
01642     }
01643 
01644     ICalFormat format;
01645     format.setTimeZone( mCalendar->timeZoneId(), true );
01646     const QString messageText = format.createScheduleMessage( incidence, Scheduler::Request );
01647 
01648     KOMailClient mailer;
01649     if ( mailer.mailTo( incidence, recipients, messageText ) ) {
01650       KMessageBox::information(
01651         this,
01652         i18n( "The item information was successfully sent." ),
01653         i18n( "Forwarding" ),
01654         "IncidenceForwardSuccess" );
01655     } else {
01656       KMessageBox::error(
01657         this,
01658         i18n( "Unable to forward the item '%1'" ).arg( incidence->summary() ),
01659         i18n( "Forwarding Error" ) );
01660     }
01661   }
01662 }
01663 
01664 void CalendarView::mailFreeBusy( int daysToPublish )
01665 {
01666   QDateTime start = QDateTime::currentDateTime();
01667   QDateTime end = start.addDays(daysToPublish);
01668 
01669   FreeBusy *freebusy = new FreeBusy(mCalendar, start, end);
01670   freebusy->setOrganizer( Person( KOPrefs::instance()->fullName(),
01671                       KOPrefs::instance()->email() ) );
01672 
01673   kdDebug(5850) << "calendarview: schedule_publish_freebusy: startDate: "
01674      << KGlobal::locale()->formatDateTime( start ) << " End Date: "
01675      << KGlobal::locale()->formatDateTime( end ) << endl;
01676 
01677   PublishDialog *publishdlg = new PublishDialog();
01678   if ( publishdlg->exec() == QDialog::Accepted ) {
01679     // Send the mail
01680     KCal::MailScheduler scheduler( mCalendar );
01681     if ( scheduler.publish( freebusy, publishdlg->addresses() ) ) {
01682       KMessageBox::information( this, i18n("The free/busy information was successfully sent."),
01683                                 i18n("Sending Free/Busy"), "FreeBusyPublishSuccess" );
01684     } else {
01685       KMessageBox::error( this, i18n("Unable to publish the free/busy data.") );
01686     }
01687   }
01688   delete freebusy;
01689   delete publishdlg;
01690 }
01691 
01692 void CalendarView::uploadFreeBusy()
01693 {
01694   KOGroupware::instance()->freeBusyManager()->publishFreeBusy();
01695 }
01696 
01697 void CalendarView::schedule(Scheduler::Method method, Incidence *incidence)
01698 {
01699   if ( !incidence ) {
01700     incidence = selectedIncidence();
01701   }
01702 
01703   if ( !incidence ) {
01704     KMessageBox::sorry( this, i18n("No item selected."),
01705                         "ScheduleNoEventSelected" );
01706     return;
01707   }
01708 
01709   if( incidence->attendeeCount() == 0 && method != Scheduler::Publish ) {
01710     KMessageBox::information( this, i18n("The item has no attendees."),
01711                               "ScheduleNoIncidences" );
01712     return;
01713   }
01714 
01715   Incidence *inc = incidence->clone();
01716   inc->registerObserver( 0 );
01717   inc->clearAttendees();
01718 
01719   // Send the mail
01720   KCal::MailScheduler scheduler( mCalendar );
01721   if ( scheduler.performTransaction( incidence, method ) ) {
01722     KMessageBox::information( this, i18n("The groupware message for item '%1'"
01723                                 "was successfully sent.\nMethod: %2")
01724                                 .arg( incidence->summary() )
01725                                 .arg( Scheduler::methodName( method ) ),
01726                               i18n("Sending Free/Busy"),
01727                               "FreeBusyPublishSuccess" );
01728   } else {
01729     KMessageBox::error( this, i18n("Groupware message sending failed. "
01730                         "%2 is request/reply/add/cancel/counter/etc.",
01731                         "Unable to send the item '%1'.\nMethod: %2")
01732                         .arg( incidence->summary() )
01733                         .arg( Scheduler::methodName( method ) ) );
01734   }
01735 }
01736 
01737 void CalendarView::openAddressbook()
01738 {
01739   KRun::runCommand("kaddressbook");
01740 }
01741 
01742 void CalendarView::setModified(bool modified)
01743 {
01744   if (mModified != modified) {
01745     mModified = modified;
01746     emit modifiedChanged(mModified);
01747   }
01748 }
01749 
01750 bool CalendarView::isReadOnly()
01751 {
01752   return mReadOnly;
01753 }
01754 
01755 void CalendarView::setReadOnly(bool readOnly)
01756 {
01757   if (mReadOnly != readOnly) {
01758     mReadOnly = readOnly;
01759     emit readOnlyChanged(mReadOnly);
01760   }
01761 }
01762 
01763 bool CalendarView::isModified()
01764 {
01765   return mModified;
01766 }
01767 
01768 void CalendarView::print()
01769 {
01770 #ifndef KORG_NOPRINTER
01771   KOCoreHelper helper;
01772   CalPrinter printer( this, mCalendar, &helper );
01773   connect( this, SIGNAL(configChanged()), &printer, SLOT(updateConfig()) );
01774 
01775   KOrg::BaseView *currentView = mViewManager->currentView();
01776 
01777   CalPrinterBase::PrintType printType = CalPrinterBase::Month;
01778   if ( currentView ) {
01779     printType = currentView->printType();
01780   }
01781 
01782   DateList tmpDateList = mDateNavigator->selectedDates();
01783   Incidence::List selectedIncidences;
01784   if ( mViewManager->currentView() ) {
01785     selectedIncidences = mViewManager->currentView()->selectedIncidences();
01786   }
01787   printer.print( printType, tmpDateList.first(), tmpDateList.last(), selectedIncidences );
01788 #endif
01789 }
01790 
01791 void CalendarView::exportWeb()
01792 {
01793   // FIXME: Get rid of the settings object. When can I delete it???
01794   HTMLExportSettings *settings = new HTMLExportSettings( "KOrganizer" );
01795   // Manually read in the config, because parametrized kconfigxt objects don't
01796   // seem to load the config theirselves
01797   if ( settings ) settings->readConfig();
01798   ExportWebDialog *dlg = new ExportWebDialog( settings, this );
01799   connect( dlg,  SIGNAL( exportHTML( HTMLExportSettings* ) ),
01800            this, SIGNAL( exportHTML( HTMLExportSettings* ) ) );
01801   dlg->show();
01802 }
01803 
01804 void CalendarView::exportICalendar()
01805 {
01806   QString filename = KFileDialog::getSaveFileName("icalout.ics",i18n("*.ics|ICalendars"),this);
01807   if ( !filename.isEmpty() )
01808   {
01809     // Force correct extension
01810     if (filename.right(4) != ".ics") filename += ".ics";
01811     if ( QFile( filename ).exists() ) {
01812       if ( KMessageBox::No == KMessageBox::warningYesNo(
01813              this,
01814              i18n( "Do you want to overwrite %1?").arg(filename) ) ) {
01815           return;
01816       }
01817     }
01818     FileStorage storage( mCalendar, filename, new ICalFormat );
01819     storage.save();
01820   }
01821 }
01822 
01823 void CalendarView::exportVCalendar()
01824 {
01825   if (mCalendar->journals().count() > 0) {
01826     int result = KMessageBox::warningContinueCancel(this,
01827         i18n("The journal entries can not be exported to a vCalendar file."),
01828         i18n("Data Loss Warning"),i18n("Proceed"),"dontaskVCalExport",
01829         true);
01830     if (result != KMessageBox::Continue) return;
01831   }
01832 
01833   QString filename = KFileDialog::getSaveFileName("vcalout.vcs",i18n("*.vcs|vCalendars"),this);
01834   if ( !filename.isEmpty() )
01835   {
01836     // TODO: I don't like forcing extensions:
01837     // Force correct extension
01838     if (filename.right(4) != ".vcs") filename += ".vcs";
01839     if ( QFile( filename ).exists() ) {
01840       if ( KMessageBox::No == KMessageBox::warningYesNo(
01841              this,
01842              i18n( "Do you want to overwrite %1?").arg(filename ) ) ) {
01843              return;
01844       }
01845     }
01846     FileStorage storage( mCalendar, filename, new VCalFormat );
01847     storage.save();
01848   }
01849 }
01850 
01851 void CalendarView::eventUpdated(Incidence *)
01852 {
01853   setModified();
01854   // Don't call updateView here. The code, which has caused the update of the
01855   // event is responsible for updating the view.
01856 //  updateView();
01857 }
01858 
01859 void CalendarView::adaptNavigationUnits()
01860 {
01861   if (mViewManager->currentView()->isEventView()) {
01862     int days = mViewManager->currentView()->currentDateCount();
01863     if (days == 1) {
01864       emit changeNavStringPrev(i18n("&Previous Day"));
01865       emit changeNavStringNext(i18n("&Next Day"));
01866     } else {
01867       emit changeNavStringPrev(i18n("&Previous Week"));
01868       emit changeNavStringNext(i18n("&Next Week"));
01869     }
01870   }
01871 }
01872 
01873 void CalendarView::processMainViewSelection( Incidence *incidence, const QDate &date )
01874 {
01875   if ( incidence ) mTodoList->clearSelection();
01876   processIncidenceSelection( incidence, date );
01877 }
01878 
01879 void CalendarView::processTodoListSelection( Incidence *incidence, const QDate &date )
01880 {
01881   if ( incidence && mViewManager->currentView() ) {
01882     mViewManager->currentView()->clearSelection();
01883   }
01884   processIncidenceSelection( incidence, date );
01885 }
01886 
01887 void CalendarView::processIncidenceSelection( Incidence *incidence, const QDate &date )
01888 {
01889   if ( incidence != mSelectedIncidence ) {
01890     // This signal also must be emitted if incidence is 0
01891     emit incidenceSelected( incidence, date );
01892   }
01893 
01894   if ( !incidence ) {
01895    mSelectedIncidence = incidence;
01896    return;
01897   }
01898   if ( incidence == mSelectedIncidence ) {
01899     if ( !incidence->doesRecur() || mSaveDate == date ) {
01900       return;
01901     }
01902   }
01903 
01904   mSelectedIncidence = incidence;
01905   mSaveDate = date;
01906 
01907   emit incidenceSelected( mSelectedIncidence, date );
01908   bool organizerEvents = false;
01909   bool groupEvents = false;
01910   bool todo = false;
01911   bool subtodo = false;
01912 
01913   organizerEvents = KOPrefs::instance()->thatIsMe( incidence->organizer().email() );
01914   groupEvents = incidence->attendeeByMails( KOPrefs::instance()->allEmails() );
01915 
01916   if ( incidence->type() == "Todo" ) {
01917     todo = true;
01918     subtodo = ( incidence->relatedTo() != 0 );
01919   }
01920 
01921   emit todoSelected( todo );
01922   emit subtodoSelected( subtodo );
01923   emit organizerEventsSelected( organizerEvents );
01924   emit groupEventsSelected( groupEvents );
01925 }
01926 
01927 
01928 void CalendarView::checkClipboard()
01929 {
01930 #ifndef KORG_NODND
01931   if (ICalDrag::canDecode(QApplication::clipboard()->data())) {
01932     kdDebug(5850) << "CalendarView::checkClipboard() true" << endl;
01933     emit pasteEnabled(true);
01934   } else {
01935     kdDebug(5850) << "CalendarView::checkClipboard() false" << endl;
01936     emit pasteEnabled(false);
01937   }
01938 #endif
01939 }
01940 
01941 void CalendarView::showDates( const DateList &selectedDates, const QDate &preferredMonth )
01942 {
01943   mDateNavigatorContainer->selectDates( selectedDates, preferredMonth );
01944   mNavigatorBar->selectDates( selectedDates );
01945 
01946   if ( mViewManager->currentView() ) {
01947     updateView( selectedDates.first(), selectedDates.last() );
01948   } else {
01949     mViewManager->showAgendaView();
01950   }
01951 }
01952 
01953 void CalendarView::editFilters()
01954 {
01955   kdDebug(5850) << "CalendarView::editFilters()" << endl;
01956 
01957   CalFilter *filter = mFilters.first();
01958   while( filter ) {
01959     kdDebug(5850) << " Filter: " << filter->name() << endl;
01960     filter = mFilters.next();
01961   }
01962 
01963   mDialogManager->showFilterEditDialog(&mFilters);
01964 }
01965 
01968 void CalendarView::updateFilter()
01969 {
01970   QStringList filters;
01971   CalFilter *filter;
01972 
01973   int pos = mFilters.find( mCurrentFilter );
01974   if ( pos < 0 ) {
01975     mCurrentFilter = 0;
01976   }
01977 
01978   filters << i18n("No filter");
01979   for ( filter = mFilters.first(); filter; filter = mFilters.next() ) {
01980     filters << filter->name();
01981   }
01982 
01983   emit newFilterListSignal( filters );
01984   // account for the additional "No filter" at the beginning! if the
01985   // filter is not in the list, pos == -1...
01986   emit selectFilterSignal( pos+1 );
01987   mCalendar->setFilter( mCurrentFilter );
01988   updateView();
01989 }
01990 
01993 void CalendarView::filterActivated( int filterNo )
01994 {
01995   CalFilter *newFilter = 0;
01996   if ( filterNo > 0 && filterNo <= int(mFilters.count()) ) {
01997     newFilter = mFilters.at( filterNo-1 );
01998   }
01999   if ( newFilter != mCurrentFilter ) {
02000     mCurrentFilter = newFilter;
02001     mCalendar->setFilter( mCurrentFilter );
02002     updateView();
02003   }
02004   emit filterChanged();
02005 }
02006 
02007 QString CalendarView::currentFilterName() const
02008 {
02009   if ( mCurrentFilter) {
02010     return mCurrentFilter->name();
02011   } else return i18n("No filter");
02012 }
02013 
02014 void CalendarView::takeOverEvent()
02015 {
02016   Incidence *incidence = currentSelection();
02017 
02018   if (!incidence) return;
02019 
02020   incidence->setOrganizer( Person( KOPrefs::instance()->fullName(),
02021                            KOPrefs::instance()->email() ) );
02022   incidence->recreate();
02023   incidence->setReadOnly(false);
02024 
02025   updateView();
02026 }
02027 
02028 void CalendarView::takeOverCalendar()
02029 {
02030   Incidence::List incidences = mCalendar->rawIncidences();
02031   Incidence::List::Iterator it;
02032 
02033   for ( it = incidences.begin(); it != incidences.end(); ++it ) {
02034     (*it)->setOrganizer( Person( KOPrefs::instance()->fullName(),
02035                          KOPrefs::instance()->email() ) );
02036     (*it)->recreate();
02037     (*it)->setReadOnly(false);
02038   }
02039   updateView();
02040 }
02041 
02042 void CalendarView::showIntro()
02043 {
02044   kdDebug(5850) << "To be implemented." << endl;
02045 }
02046 
02047 void CalendarView::showDateNavigator( bool show )
02048 {
02049   if( show )
02050     mDateNavigatorContainer->show();
02051   else
02052     mDateNavigatorContainer->hide();
02053 }
02054 
02055 void CalendarView::showTodoView( bool show )
02056 {
02057   if( show )
02058     mTodoList->show();
02059   else
02060     mTodoList->hide();
02061 }
02062 
02063 void CalendarView::showEventViewer( bool show )
02064 {
02065   if( show )
02066     mEventViewer->show();
02067   else
02068     mEventViewer->hide();
02069 }
02070 
02071 
02072 void CalendarView::addView(KOrg::BaseView *view)
02073 {
02074   mViewManager->addView(view);
02075 }
02076 
02077 void CalendarView::showView(KOrg::BaseView *view)
02078 {
02079   mViewManager->showView(view);
02080 }
02081 
02082 void CalendarView::addExtension( CalendarViewExtension::Factory *factory )
02083 {
02084   CalendarViewExtension *extension = factory->create( mLeftSplitter );
02085 
02086   mExtensions.append( extension );
02087 }
02088 
02089 void CalendarView::toggleExpand()
02090 {
02091   showLeftFrame( mLeftFrame->isHidden() );
02092 }
02093 
02094 void CalendarView::showLeftFrame(bool show)
02095 {
02096   if (show) {
02097     mLeftFrame->show();
02098     emit calendarViewExpanded( false );
02099   } else {
02100     mLeftFrame->hide();
02101     emit calendarViewExpanded( true );
02102   }
02103 }
02104 
02105 void CalendarView::calendarModified( bool modified, Calendar * )
02106 {
02107   setModified( modified );
02108 }
02109 
02110 Todo *CalendarView::selectedTodo()
02111 {
02112   Incidence *incidence = currentSelection();
02113   if ( incidence && incidence->type() == "Todo" ) {
02114     return static_cast<Todo *>( incidence );
02115   }
02116   incidence = 0;
02117 
02118   Incidence::List selectedIncidences = mTodoList->selectedIncidences();
02119   if ( !selectedIncidences.isEmpty() ) incidence = selectedIncidences.first();
02120   if ( incidence && incidence->type() == "Todo" ) {
02121     return static_cast<Todo *>( incidence );
02122   }
02123 
02124   return 0;
02125 }
02126 
02127 void CalendarView::dialogClosing( Incidence *in )
02128 {
02129   // FIXME: this doesn't work, because if it's a new incidence, it's not locked!
02130   mChanger->endChange( in, 0, QString() );
02131   mDialogList.remove( in );
02132 }
02133 
02134 Incidence *CalendarView::currentSelection()
02135 {
02136   return mViewManager->currentSelection();
02137 }
02138 
02139 Incidence* CalendarView::selectedIncidence()
02140 {
02141   Incidence *incidence = currentSelection();
02142   if ( !incidence ) {
02143     Incidence::List selectedIncidences = mTodoList->selectedIncidences();
02144     if ( !selectedIncidences.isEmpty() )
02145       incidence = selectedIncidences.first();
02146   }
02147   return incidence;
02148 }
02149 
02150 void CalendarView::showIncidence()
02151 {
02152   showIncidence( selectedIncidence(), activeIncidenceDate() );
02153 }
02154 
02155 void CalendarView::editIncidence()
02156 {
02157   editIncidence( selectedIncidence(), activeIncidenceDate() );
02158 }
02159 
02160 bool CalendarView::editIncidence( const QString &uid )
02161 {
02162   return editIncidence( mCalendar->incidence( uid ), QDate() );
02163 }
02164 
02165 bool CalendarView::editIncidence( const QString &uid, const QDate &date )
02166 {
02167   return editIncidence( mCalendar->incidence( uid ), date );
02168 }
02169 
02170 void CalendarView::deleteIncidence()
02171 {
02172   deleteIncidence( selectedIncidence() );
02173 }
02174 
02175 void CalendarView::cutIncidence(Incidence *)
02176 {
02177   edit_cut();
02178 }
02179 
02180 void CalendarView::copyIncidence(Incidence *)
02181 {
02182   edit_copy();
02183 }
02184 
02185 void CalendarView::pasteIncidence()
02186 {
02187   edit_paste();
02188 }
02189 
02190 void CalendarView::showIncidence( Incidence *incidence, const QDate &date )
02191 {
02192   if ( !incidence ) {
02193     return;
02194   }
02195 
02196   KOEventViewerDialog *eventViewer = new KOEventViewerDialog( calendar(), this );
02197   eventViewer->setIncidence( incidence, date );
02198   eventViewer->show();
02199 }
02200 
02201 bool CalendarView::editIncidence( Incidence *incidence, const QDate &date, bool isCounter )
02202 {
02203   kdDebug(5850) << "CalendarView::editEvent()" << endl;
02204 
02205   CalendarResources *stdcal = dynamic_cast<CalendarResources *>( mCalendar );
02206   if( stdcal && !stdcal->hasCalendarResources() ) {
02207     KMessageBox::sorry(
02208       this,
02209       i18n( "No resources found. We can not edit the item." ) );
02210     return false;
02211   }
02212 
02213   // FIXME: This is a nasty hack, since we need to set a parent for the
02214   //        resource selection dialog. However, we don't have any UI methods
02215   //        in the calendar, only in the CalendarResources::DestinationPolicy
02216   //        So we need to type-cast it and extract it from the CalendarResources
02217   QWidget *tmpparent = 0;
02218   if ( stdcal ) {
02219     tmpparent = stdcal->dialogParentWidget();
02220     stdcal->setDialogParentWidget( this );
02221   }
02222 
02223   if ( !incidence ) {
02224     kdDebug(5850) << "Empty Incidence" << endl;
02225     KNotifyClient::beep();
02226     return false;
02227   }
02228 
02229   if ( !mChanger ) {
02230     kdDebug(5850) << "Empty Changer" << endl;
02231     KNotifyClient::beep();
02232     return false;
02233   }
02234 
02235   KOIncidenceEditor *tmp = editorDialog( incidence );
02236   if ( tmp ) {
02237     kdDebug(5850) << "CalendarView::editIncidence() in List" << endl;
02238     tmp->reload();
02239     tmp->raise();
02240     tmp->show();
02241     return true;
02242   }
02243 
02244   if ( incidence->isReadOnly() ) {
02245     showIncidence( incidence, date );
02246     return true;
02247   }
02248 
02249   QPair<ResourceCalendar *, QString>p =
02250     CalHelper::incSubResourceCalendar( calendar(), incidence );
02251 
02252   Incidence *savedIncidence = incidence->clone();
02253   Incidence *incToChange;
02254 
02255   if ( incidence->doesRecur() ) {
02256     KOGlobals::WhichOccurrences chosenOption;
02257     incToChange = singleOccurrenceOrAll( incidence, KOGlobals::EDIT, chosenOption, date );
02258   } else {
02259     incToChange = incidence;
02260   }
02261 
02262   // If the user pressed cancel incToChange is 0
02263   if ( incToChange ) {
02264     if ( !isCounter && !mChanger->beginChange( incToChange, p.first, p.second ) ) {
02265       warningChangeFailed( incToChange );
02266       showIncidence( incToChange, date );
02267 
02268       return false;
02269     }
02270 
02271     kdDebug(5850) << "CalendarView::editIncidence() new IncidenceEditor" << endl;
02272     KOIncidenceEditor *incidenceEditor = mDialogManager->getEditor( incToChange );
02273     connectIncidenceEditor( incidenceEditor );
02274 
02275     mDialogList.insert( incToChange, incidenceEditor );
02276     if ( incidence != incToChange ) {
02277       incidenceEditor->setRecurringIncidence( savedIncidence, incidence );
02278     }
02279     incidenceEditor->setResource( p.first, p.second );
02280     incidenceEditor->editIncidence( incToChange, date, mCalendar );
02281     incidenceEditor->show();
02282     return true;
02283   } else {
02284     return false;
02285   }
02286 }
02287 
02288 void CalendarView::deleteSubTodosIncidence ( Todo *todo )
02289 {
02290   if( !todo ) return;
02291 
02292   Incidence::List subTodos( todo->relations() );
02293   Incidence::List::Iterator it;
02294   Incidence *aIncidence;
02295   Todo *aTodo;
02296 
02297   for ( it= subTodos.begin(); it != subTodos.end(); ++it ) {
02298     aIncidence = *it;
02299     if( aIncidence && aIncidence->type() == "Todo" ) {
02300       aTodo = static_cast<Todo*>( aIncidence );
02301       deleteSubTodosIncidence ( aTodo );
02302     }
02303   }
02304   mChanger->deleteIncidence ( todo, this );
02305 }
02306 
02307 void CalendarView::deleteTodoIncidence ( Todo *todo, bool force )
02308 {
02309   if ( !todo ) return ;
02310 
02311   // it a simple todo, ask and delete it.
02312   if (todo->relations().isEmpty() ) {
02313     bool doDelete = true;
02314     if ( !force && KOPrefs::instance()->mConfirm ) {
02315       doDelete = ( msgItemDelete( todo ) == KMessageBox::Continue );
02316     }
02317     if ( doDelete )
02318       mChanger->deleteIncidence( todo, this );
02319     return;
02320   }
02321 
02322   /* Ok, this to-do has sub-to-dos, ask what to do */
02323   int km = KMessageBox::No;
02324   if ( !force ) {
02325     km = KMessageBox::questionYesNoCancel(
02326       this,
02327       i18n("The item \"%1\" has sub-to-dos. "
02328            "Do you want to delete just this item and "
02329            "make all its sub-to-dos independent, or "
02330            "delete the to-do with all its sub-to-dos?"
02331         ).arg( todo->summary() ),
02332       i18n("KOrganizer Confirmation"),
02333       i18n("Delete Only This"),
02334       i18n("Delete All"));
02335   }
02336   startMultiModify( i18n("Deleting sub-to-dos" ) );
02337   // Delete only the father
02338   if( km == KMessageBox::Yes ) {
02339     // Instead of making a subto-do independent, why not relate
02340     // it to it's dead father's parent?
02341     makeChildrenIndependent ( todo );
02342     mChanger->deleteIncidence( todo, this );
02343   } else if ( km == KMessageBox::No ) {
02344     // Delete all
02345     // we have to hide the delete confirmation for each itemDate
02346     deleteSubTodosIncidence ( todo );
02347   }
02348   endMultiModify();
02349 }
02350 
02351 void CalendarView::deleteIncidence(Incidence *incidence, bool force)
02352 {
02353   if ( !incidence || !mChanger ) {
02354     if ( !force ) {
02355       KNotifyClient::beep();
02356     }
02357     return;
02358   }
02359   if ( incidence->isReadOnly() ) {
02360     if ( !force ) {
02361       KMessageBox::information( this, i18n("The item \"%1\" is marked read-only "
02362                                 "and cannot be deleted; it probably belongs to "
02363                                 "a read-only calendar resource.")
02364                                 .arg(incidence->summary()),
02365                                 i18n("Removing not possible"),
02366                                 "deleteReadOnlyIncidence" );
02367     }
02368     return;
02369   }
02370 
02371   CanDeleteIncidenceVisitor v;
02372 
02373   // Let the visitor do special things for special incidence types.
02374   // e.g. todos with children cannot be deleted, so act(..) returns false
02375   if ( !v.act( incidence, this ) )
02376     return;
02377   //If it is a todo, there are specific delete function
02378 
02379   if ( incidence && incidence->type()=="Todo" ) {
02380     deleteTodoIncidence( static_cast<Todo*>(incidence), force );
02381     return;
02382   }
02383 
02384   if ( incidence->doesRecur() ) {
02385     QDate itemDate = mViewManager->currentSelectionDate();
02386     kdDebug(5850) << "Recurrence-Date: " << itemDate.toString() << endl;
02387     int km = KMessageBox::Ok;
02388     if ( !force ) {
02389       if ( !itemDate.isValid() ) {
02390         kdDebug(5850) << "Date Not Valid" << endl;
02391         km = KMessageBox::warningContinueCancel(this,
02392           i18n("The calendar item \"%1\" recurs over multiple dates; "
02393                "are you sure you want to delete it "
02394                "and all its recurrences?").arg( incidence->summary() ),
02395                i18n("KOrganizer Confirmation"), i18n("Delete All") );
02396       } else {
02397         km = KOMessageBox::fourBtnMsgBox( this, QMessageBox::Warning,
02398           i18n("The calendar item \"%1\" recurs over multiple dates. "
02399                "Do you want to delete only the current one on %2, only all "
02400                "future recurrences, or all its recurrences?" )
02401                .arg( incidence->summary() )
02402                .arg( KGlobal::locale()->formatDate(itemDate)),
02403                i18n("KOrganizer Confirmation"), i18n("Delete C&urrent"),
02404                i18n("Delete &Future"),
02405                i18n("Delete &All"));
02406       }
02407     }
02408 
02409     QPair<ResourceCalendar *, QString>p =
02410       CalHelper::incSubResourceCalendar( calendar(), incidence );
02411 
02412     switch(km) {
02413       case KMessageBox::Ok: // Continue // all
02414       case KMessageBox::Continue:
02415         mChanger->deleteIncidence( incidence, this );
02416         break;
02417 
02418       case KMessageBox::Yes: // just this one
02419         if ( mChanger->beginChange( incidence, p.first, p.second ) ) {
02420           Incidence *oldIncidence = incidence->clone();
02421           incidence->recurrence()->addExDate( itemDate );
02422           mChanger->changeIncidence( oldIncidence, incidence,
02423                                      KOGlobals::RECURRENCE_MODIFIED_ONE_ONLY, this );
02424           mChanger->endChange( incidence, p.first, p.second );
02425           delete oldIncidence;
02426         }
02427         break;
02428       case KMessageBox::No: // all future items
02429         if ( mChanger->beginChange( incidence, p.first, p.second ) ) {
02430           Incidence *oldIncidence = incidence->clone();
02431           Recurrence *recur = incidence->recurrence();
02432           recur->setEndDate( itemDate.addDays(-1) );
02433           mChanger->changeIncidence( oldIncidence, incidence,
02434                                      KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE,  this );
02435           mChanger->endChange( incidence, p.first, p.second );
02436           delete oldIncidence;
02437         }
02438         break;
02439     }
02440   } else {
02441     bool doDelete = true;
02442     if ( !force && KOPrefs::instance()->mConfirm ) {
02443       doDelete = ( msgItemDelete( incidence ) == KMessageBox::Continue );
02444     }
02445     if ( doDelete ) {
02446       mChanger->deleteIncidence( incidence, this );
02447       processIncidenceSelection( 0, QDate() );
02448     }
02449   }
02450 }
02451 
02452 void CalendarView::connectIncidenceEditor( KOIncidenceEditor *editor )
02453 {
02454   connect( this, SIGNAL( newIncidenceChanger( IncidenceChangerBase* ) ),
02455            editor, SLOT( setIncidenceChanger( IncidenceChangerBase* ) ) );
02456   editor->setIncidenceChanger( mChanger );
02457 }
02458 
02459 bool CalendarView::purgeCompletedSubTodos( Todo* todo, bool &allPurged )
02460 {
02461   if ( !todo ) return true;
02462   bool deleteThisTodo = true;
02463   Incidence::List subTodos( todo->relations() );
02464   Incidence *aIncidence;
02465   Todo *aTodo;
02466   Incidence::List::Iterator it;
02467   for ( it = subTodos.begin(); it != subTodos.end(); ++it ) {
02468     aIncidence = *it;
02469     if ( aIncidence && aIncidence->type()=="Todo" ) {
02470       aTodo = static_cast<Todo*>( aIncidence );
02471       deleteThisTodo &= purgeCompletedSubTodos( aTodo, allPurged );
02472     }
02473   }
02474 
02475   if ( deleteThisTodo ) {
02476     if ( todo->isCompleted() ) {
02477       if ( !mChanger->deleteIncidence( todo, this ) )
02478         allPurged = false;
02479     } else {
02480       deleteThisTodo = false;
02481     }
02482   } else {
02483     if ( todo->isCompleted() ) {
02484       allPurged = false;
02485     }
02486   }
02487   return deleteThisTodo;
02488 }
02489 
02490 void CalendarView::purgeCompleted()
02491 {
02492   int result = KMessageBox::warningContinueCancel(this,
02493       i18n("Delete all completed to-dos?"),i18n("Purge To-dos"),i18n("Purge"));
02494 
02495   if (result == KMessageBox::Continue) {
02496     bool allDeleted = true;
02497     startMultiModify( i18n("Purging completed to-dos") );
02498     Todo::List todos = calendar()->rawTodos();
02499     Todo::List rootTodos;
02500     Todo::List::ConstIterator it;
02501     for ( it = todos.begin(); it != todos.end(); ++it ) {
02502       Todo *aTodo = *it;
02503       if ( aTodo && !aTodo->relatedTo() )
02504         rootTodos.append( aTodo );
02505     }
02506     // now that we have a list of all root todos, check them and their children
02507     for ( it = rootTodos.begin(); it != rootTodos.end(); ++it ) {
02508       purgeCompletedSubTodos( *it, allDeleted );
02509     }
02510     endMultiModify();
02511     if ( !allDeleted ) {
02512       KMessageBox::information( this, i18n("Unable to purge to-dos with "
02513                                 "uncompleted children."), i18n("Delete To-do"),
02514                                 "UncompletedChildrenPurgeTodos" );
02515     }
02516   }
02517 }
02518 
02519 void CalendarView::warningChangeFailed( Incidence *incidence )
02520 {
02521   if ( incidence ) {
02522     KMessageBox::sorry(
02523       this,
02524       i18n( "Unable to edit \"%1\" because it is locked by another process." ).
02525       arg( incidence->summary() ) );
02526   }
02527 }
02528 
02529 void CalendarView::editCanceled( Incidence *incidence )
02530 {
02531   mCalendar->endChange( incidence );
02532 }
02533 
02534 void CalendarView::showErrorMessage( const QString &msg )
02535 {
02536   KMessageBox::error( this, msg );
02537 }
02538 
02539 void CalendarView::updateCategories()
02540 {
02541   QStringList allCats( calendar()->categories() );
02542   allCats.sort();
02543   QStringList categories( KOPrefs::instance()->mCustomCategories );
02544   for ( QStringList::ConstIterator si = allCats.constBegin(); si != allCats.constEnd(); ++si ) {
02545     if ( categories.find( *si ) == categories.end() ) {
02546       categories.append( *si );
02547     }
02548   }
02549   KOPrefs::instance()->mCustomCategories = categories;
02550   KOPrefs::instance()->writeConfig();
02551   // Make the category editor update the list!
02552   emit categoriesChanged();
02553 }
02554 
02555 void CalendarView::addIncidenceOn( Incidence *incadd, const QDate &dt )
02556 {
02557   if ( !incadd || !mChanger ) {
02558     KMessageBox::sorry(this, i18n("Unable to copy the item to %1.")
02559                        .arg( dt.toString() ), i18n("Copying Failed") );
02560     return;
02561   }
02562   Incidence *incidence = mCalendar->incidence( incadd->uid() );
02563   if ( !incidence ) incidence = incadd;
02564   // Create a copy of the incidence, since the incadd doesn't belong to us.
02565   incidence = incidence->clone();
02566   incidence->recreate();
02567 
02568   if ( incidence->type() == "Event" ) {
02569     Event *event = static_cast<Event*>(incidence);
02570 
02571     // Adjust date
02572     QDateTime start = event->dtStart();
02573     QDateTime end = event->dtEnd();
02574 
02575     int duration = start.daysTo( end );
02576     start.setDate( dt );
02577     end.setDate( dt.addDays( duration ) );
02578 
02579     event->setDtStart( start );
02580     event->setDtEnd( end );
02581 
02582   } else if ( incidence->type() == "Todo" ) {
02583     Todo *todo = static_cast<Todo*>(incidence);
02584     QDateTime due = todo->dtDue();
02585     due.setDate( dt );
02586 
02587     todo->setDtDue( due );
02588     todo->setHasDueDate( true );
02589   }
02590 
02591   QPair<ResourceCalendar *, QString>p = viewSubResourceCalendar();
02592 
02593   if ( !mChanger->addIncidence( incidence, p.first, p.second, this ) ) {
02594     KODialogManager::errorSaveIncidence( this, incidence );
02595     delete incidence;
02596   }
02597 }
02598 
02599 void CalendarView::moveIncidenceTo( Incidence *incmove, const QDate &dt )
02600 {
02601   if ( !incmove || !mChanger ) {
02602     KMessageBox::sorry( this, i18n("Unable to move the item to %1.")
02603                         .arg( dt.toString() ), i18n("Moving Failed") );
02604     return;
02605   }
02606   Incidence *incidence = mCalendar->incidence( incmove->uid() );
02607   if ( !incidence ) {
02608     addIncidenceOn( incidence, dt );
02609     return;
02610   }
02611 
02612   Incidence *oldIncidence = incidence->clone();
02613   QPair<ResourceCalendar *, QString>p = viewSubResourceCalendar();
02614 
02615   if ( !mChanger->beginChange( incidence, p.first, p.second ) ) {
02616     delete oldIncidence;
02617     return;
02618   }
02619 
02620   if ( incidence->type() == "Event" ) {
02621     Event *event = static_cast<Event*>(incidence);
02622 
02623     // Adjust date
02624     QDateTime start = event->dtStart();
02625     QDateTime end = event->dtEnd();
02626 
02627     int duration = start.daysTo( end );
02628     start.setDate( dt );
02629     end.setDate( dt.addDays( duration ) );
02630 
02631     event->setDtStart( start );
02632     event->setDtEnd( end );
02633 
02634   } else if ( incidence->type() == "Todo" ) {
02635     Todo *todo = static_cast<Todo*>(incidence);
02636     QDateTime due = todo->dtDue();
02637     due.setDate( dt );
02638 
02639     todo->setDtDue( due );
02640     todo->setHasDueDate( true );
02641   }
02642   mChanger->changeIncidence( oldIncidence, incidence, KOGlobals::DATE_MODIFIED,this );
02643   mChanger->endChange( incidence, p.first, p.second );
02644   delete oldIncidence;
02645 }
02646 
02647 void CalendarView::resourcesChanged()
02648 {
02649   mViewManager->resourcesChanged();
02650   mDateNavigatorContainer->setUpdateNeeded();
02651   updateView();
02652 }
02653 
02654 Incidence* CalendarView::singleOccurrenceOrAll( Incidence *inc,
02655                                                 KOGlobals::OccurrenceAction userAction,
02656                                                 KOGlobals::WhichOccurrences &chosenOption,
02657                                                 const QDate &itemDate,
02658                                                 const bool commitToCalendar )
02659 {
02660 
02661   // temporary, until recurring to-dos are fixed
02662   if ( inc->type() != "Event" ) {
02663     chosenOption = KOGlobals::ALL;
02664     return inc;
02665   }
02666 
02667   Incidence *incToReturn = 0;
02668   Incidence *incSaved = 0;
02669   KOGlobals::WhatChanged whatChanged;
02670 
02671   bool dissociationOccurred = false;
02672   const QDate &dt = itemDate.isValid() ? itemDate : activeIncidenceDate();
02673 
02674   QString dialogTitle;
02675   QString dialogText;
02676 
02677   if ( userAction == KOGlobals::CUT ) {
02678     dialogTitle = i18n( "Cutting Recurring Item" );
02679 
02680     dialogText = i18n("The item you try to cut is a recurring item. Do you want to cut "
02681                        "only this single occurrence, only future items, "
02682                        "or all items in the recurrence?");
02683 
02684   } else if ( userAction == KOGlobals::COPY ) {
02685     dialogTitle = i18n( "Copying Recurring Item" );
02686 
02687     dialogText = i18n("The item you try to copy is a recurring item. Do you want to copy "
02688                        "only this single occurrence, only future items, "
02689                        "or all items in the recurrence?");
02690   } else {
02691     dialogTitle = i18n( "Changing Recurring Item" );
02692 
02693     dialogText = i18n( "The item you try to change is a recurring item. Shall the changes "
02694                        "be applied only to this single occurrence, only to the future items, "
02695                        "or to all items in the recurrence?" );
02696   }
02697 
02698   int res = KOMessageBox::fourBtnMsgBox( this, QMessageBox::Question,
02699             dialogText,
02700             dialogTitle,
02701             i18n("Only &This Item"), i18n("Only &Future Items"), i18n("&All Occurrences") );
02702   switch ( res ) {
02703     case KMessageBox::Ok: // All occurrences
02704       incToReturn = inc;
02705       chosenOption = KOGlobals::ALL;
02706       break;
02707     case KMessageBox::Yes: { // Just this occurrence
02708       // Dissociate this occurrence:
02709       // create clone of event, set relation to old event, set cloned event
02710       // for mActionItem, add exception date to old event, changeIncidence
02711       // for the old event, remove the recurrence from the new copy and then just
02712       // go on with the newly adjusted mActionItem and let the usual code take
02713       // care of the new time!
02714 
02715       chosenOption = KOGlobals::ONLY_THIS_ONE;
02716       whatChanged  = KOGlobals::RECURRENCE_MODIFIED_ONE_ONLY;
02717       startMultiModify( i18n("Dissociate event from recurrence") );
02718       incSaved = inc->clone();
02719       incToReturn = mCalendar->dissociateOccurrence( inc, dt );
02720       kdDebug() << "Incidence to return has startDate = " << incToReturn->dtStart()
02721                 << "; dt is " << dt << endl;
02722       if ( incToReturn ) {
02723         dissociationOccurred = true;
02724       } else {
02725         KMessageBox::sorry( this, i18n("Unable to add the exception item to the "
02726             "calendar. No change will be done."), i18n("Error Occurred") );
02727         incToReturn = 0;
02728       }
02729 
02730       break; }
02731     case KMessageBox::No/*Future*/: { // All future occurrences
02732       // Dissociate this occurrence:
02733       // create clone of event, set relation to old event, set cloned event
02734       // for mActionItem, add recurrence end date to old event, changeIncidence
02735       // for the old event, adjust the recurrence for the new copy and then just
02736       // go on with the newly adjusted mActionItem and let the usual code take
02737       // care of the new time!
02738       chosenOption = KOGlobals::ONLY_FUTURE;
02739       whatChanged  = KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE;
02740       startMultiModify( i18n("Split future recurrences") );
02741       incSaved = inc->clone();
02742       incToReturn = mCalendar->dissociateOccurrence( inc, dt, false );
02743       if ( incToReturn ) {
02744         dissociationOccurred = true;
02745       } else {
02746         KMessageBox::sorry( this, i18n("Unable to add the future items to the "
02747             "calendar. No change will be done."), i18n("Error Occurred") );
02748 
02749         incToReturn = 0;
02750       }
02751 
02752       break; }
02753     default:
02754       chosenOption = KOGlobals::NONE;
02755   }
02756 
02757   if ( dissociationOccurred && commitToCalendar ) {
02758     QPair<ResourceCalendar *, QString>p = viewSubResourceCalendar();
02759     mChanger->addIncidence( incToReturn, p.first, p.second, this, false );
02760     mChanger->changeIncidence( incSaved, inc, whatChanged, this, true );
02761   }
02762 
02763   return incToReturn;
02764 }
02765 
02766 void CalendarView::selectWeek( const QDate &date )
02767 {
02768   if ( KOPrefs::instance()->mWeekNumbersShowWork    &&
02769        mViewManager->agendaIsSelected()             &&
02770        mViewManager->agendaMode()  == KOViewManager::AGENDA_WORK_WEEK ) {
02771     mDateNavigator->selectWorkWeek( date );
02772   } else {
02773     mDateNavigator->selectWeek( date );
02774   }
02775 }
02776 
02777 void CalendarView::getIncidenceHierarchy( Incidence *inc,
02778                                           Incidence::List &children )
02779 {
02780   // protecion against looping hierarchies
02781   if ( inc && !children.contains( inc ) ) {
02782     Incidence::List::ConstIterator it;
02783     Incidence::List immediateChildren = inc->relations();
02784     for ( it = immediateChildren.constBegin(); it != immediateChildren.constEnd(); ++it ) {
02785       getIncidenceHierarchy( *it, children );
02786     }
02787     children.append( inc );
02788   }
02789 }
02790 
02791 #include "calendarview.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys