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