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