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