korganizer

calendarview.cpp

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