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 
01547     FileStorage storage( mCalendar, filename, new ICalFormat );
01548     storage.save();
01549   }
01550 }
01551 
01552 void CalendarView::exportVCalendar()
01553 {
01554   if (mCalendar->journals().count() > 0) {
01555     int result = KMessageBox::warningContinueCancel(this,
01556         i18n("The journal entries can not be exported to a vCalendar file."),
01557         i18n("Data Loss Warning"),i18n("Proceed"),"dontaskVCalExport",
01558         true);
01559     if (result != KMessageBox::Continue) return;
01560   }
01561 
01562   QString filename = KFileDialog::getSaveFileName("vcalout.vcs",i18n("*.vcs|vCalendars"),this);
01563   if ( !filename.isEmpty() )
01564   {
01565     // TODO: I don't like forcing extensions:
01566     // Force correct extension
01567     if (filename.right(4) != ".vcs") filename += ".vcs";
01568 
01569     FileStorage storage( mCalendar, filename, new VCalFormat );
01570     storage.save();
01571   }
01572 }
01573 
01574 void CalendarView::eventUpdated(Incidence *)
01575 {
01576   setModified();
01577   // Don't call updateView here. The code, which has caused the update of the
01578   // event is responsible for updating the view.
01579 //  updateView();
01580 }
01581 
01582 void CalendarView::adaptNavigationUnits()
01583 {
01584   if (mViewManager->currentView()->isEventView()) {
01585     int days = mViewManager->currentView()->currentDateCount();
01586     if (days == 1) {
01587       emit changeNavStringPrev(i18n("&Previous Day"));
01588       emit changeNavStringNext(i18n("&Next Day"));
01589     } else {
01590       emit changeNavStringPrev(i18n("&Previous Week"));
01591       emit changeNavStringNext(i18n("&Next Week"));
01592     }
01593   }
01594 }
01595 
01596 void CalendarView::processMainViewSelection( Incidence *incidence )
01597 {
01598   if ( incidence ) mTodoList->clearSelection();
01599   processIncidenceSelection( incidence );
01600 }
01601 
01602 void CalendarView::processTodoListSelection( Incidence *incidence )
01603 {
01604   if ( incidence && mViewManager->currentView() ) {
01605     mViewManager->currentView()->clearSelection();
01606   }
01607   processIncidenceSelection( incidence );
01608 }
01609 
01610 void CalendarView::processIncidenceSelection( Incidence *incidence )
01611 {
01612   if ( incidence == mSelectedIncidence ) return;
01613 
01614   mSelectedIncidence = incidence;
01615 
01616   emit incidenceSelected( mSelectedIncidence );
01617   bool organizerEvents = false;
01618   bool groupEvents = false;
01619   bool todo = false;
01620   bool subtodo = false;
01621 
01622   if ( incidence ) {
01623     organizerEvents = KOPrefs::instance()->thatIsMe( incidence->organizer().email() );
01624     groupEvents = incidence->attendeeByMails( KOPrefs::instance()->allEmails() );
01625 
01626     if ( incidence && incidence->type() == "Todo" ) {
01627       todo = true;
01628       subtodo = ( incidence->relatedTo() != 0 );
01629     }
01630   }
01631   emit todoSelected( todo );
01632   emit subtodoSelected( subtodo );
01633   emit organizerEventsSelected( organizerEvents );
01634   emit groupEventsSelected( groupEvents );
01635 }
01636 
01637 
01638 void CalendarView::checkClipboard()
01639 {
01640 #ifndef KORG_NODND
01641   if (ICalDrag::canDecode(QApplication::clipboard()->data())) {
01642     kdDebug(5850) << "CalendarView::checkClipboard() true" << endl;
01643     emit pasteEnabled(true);
01644   } else {
01645     kdDebug(5850) << "CalendarView::checkClipboard() false" << endl;
01646     emit pasteEnabled(false);
01647   }
01648 #endif
01649 }
01650 
01651 void CalendarView::showDates(const DateList &selectedDates)
01652 {
01653 //  kdDebug(5850) << "CalendarView::selectDates()" << endl;
01654 
01655   if ( mViewManager->currentView() ) {
01656     updateView( selectedDates.first(), selectedDates.last() );
01657   } else {
01658     mViewManager->showAgendaView();
01659   }
01660 }
01661 
01662 void CalendarView::editFilters()
01663 {
01664   kdDebug(5850) << "CalendarView::editFilters()" << endl;
01665 
01666   CalFilter *filter = mFilters.first();
01667   while(filter) {
01668     kdDebug(5850) << " Filter: " << filter->name() << endl;
01669     filter = mFilters.next();
01670   }
01671 
01672   mDialogManager->showFilterEditDialog(&mFilters);
01673 }
01674 
01677 void CalendarView::updateFilter()
01678 {
01679   QStringList filters;
01680   CalFilter *filter;
01681 
01682   int pos = mFilters.find( mCurrentFilter );
01683   if ( pos < 0 ) {
01684     mCurrentFilter = 0;
01685   }
01686 
01687   filters << i18n("No filter");
01688   for ( filter = mFilters.first(); filter; filter = mFilters.next() ) {
01689     filters << filter->name();
01690   }
01691 
01692   emit newFilterListSignal( filters );
01693   // account for the additional "No filter" at the beginning! if the
01694   // filter is not in the list, pos == -1...
01695   emit selectFilterSignal( pos+1 );
01696   mCalendar->setFilter( mCurrentFilter );
01697   updateView();
01698 }
01699 
01702 void CalendarView::filterActivated( int filterNo )
01703 {
01704   CalFilter *newFilter = 0;
01705   if ( filterNo > 0 && filterNo <= int(mFilters.count()) ) {
01706     newFilter = mFilters.at( filterNo-1 );
01707   }
01708   if ( newFilter != mCurrentFilter ) {
01709     mCurrentFilter = newFilter;
01710     mCalendar->setFilter( mCurrentFilter );
01711     updateView();
01712   }
01713   emit filterChanged();
01714 }
01715 
01716 QString CalendarView::currentFilterName() const
01717 {
01718   if ( mCurrentFilter) {
01719     return mCurrentFilter->name();
01720   } else return i18n("No filter");
01721 }
01722 
01723 void CalendarView::takeOverEvent()
01724 {
01725   Incidence *incidence = currentSelection();
01726 
01727   if (!incidence) return;
01728 
01729   incidence->setOrganizer( Person( KOPrefs::instance()->fullName(),
01730                            KOPrefs::instance()->email() ) );
01731   incidence->recreate();
01732   incidence->setReadOnly(false);
01733 
01734   updateView();
01735 }
01736 
01737 void CalendarView::takeOverCalendar()
01738 {
01739   Incidence::List incidences = mCalendar->rawIncidences();
01740   Incidence::List::Iterator it;
01741 
01742   for ( it = incidences.begin(); it != incidences.end(); ++it ) {
01743     (*it)->setOrganizer( Person( KOPrefs::instance()->fullName(),
01744                          KOPrefs::instance()->email() ) );
01745     (*it)->recreate();
01746     (*it)->setReadOnly(false);
01747   }
01748   updateView();
01749 }
01750 
01751 void CalendarView::showIntro()
01752 {
01753   kdDebug(5850) << "To be implemented." << endl;
01754 }
01755 
01756 void CalendarView::showDateNavigator( bool show )
01757 {
01758   if( show )
01759     mDateNavigator->show();
01760   else
01761     mDateNavigator->hide();
01762 }
01763 
01764 void CalendarView::showTodoView( bool show )
01765 {
01766   if( show )
01767     mTodoList->show();
01768   else
01769     mTodoList->hide();
01770 }
01771 
01772 void CalendarView::showEventViewer( bool show )
01773 {
01774   if( show )
01775     mEventViewer->show();
01776   else
01777     mEventViewer->hide();
01778 }
01779 
01780 
01781 void CalendarView::addView(KOrg::BaseView *view)
01782 {
01783   mViewManager->addView(view);
01784 }
01785 
01786 void CalendarView::showView(KOrg::BaseView *view)
01787 {
01788   mViewManager->showView(view);
01789 }
01790 
01791 void CalendarView::addExtension( CalendarViewExtension::Factory *factory )
01792 {
01793   CalendarViewExtension *extension = factory->create( mLeftSplitter );
01794 
01795   mExtensions.append( extension );
01796 }
01797 
01798 void CalendarView::toggleExpand()
01799 {
01800   showLeftFrame( mLeftFrame->isHidden() );
01801 }
01802 
01803 void CalendarView::showLeftFrame(bool show)
01804 {
01805   if (show) {
01806     mLeftFrame->show();
01807     emit calendarViewExpanded( false );
01808   } else {
01809     mLeftFrame->hide();
01810     emit calendarViewExpanded( true );
01811   }
01812 }
01813 
01814 void CalendarView::calendarModified( bool modified, Calendar * )
01815 {
01816   setModified( modified );
01817 }
01818 
01819 Todo *CalendarView::selectedTodo()
01820 {
01821   Incidence *incidence = currentSelection();
01822   if ( incidence && incidence->type() == "Todo" ) {
01823     return static_cast<Todo *>( incidence );
01824   }
01825   incidence = 0;
01826 
01827   Incidence::List selectedIncidences = mTodoList->selectedIncidences();
01828   if ( !selectedIncidences.isEmpty() ) incidence = selectedIncidences.first();
01829   if ( incidence && incidence->type() == "Todo" ) {
01830     return static_cast<Todo *>( incidence );
01831   }
01832 
01833   return 0;
01834 }
01835 
01836 void CalendarView::dialogClosing( Incidence *in )
01837 {
01838   // FIXME: this doesn't work, because if it's a new incidence, it's not locked!
01839   mChanger->endChange( in );
01840   mDialogList.remove( in );
01841 }
01842 
01843 Incidence *CalendarView::currentSelection()
01844 {
01845   return mViewManager->currentSelection();
01846 }
01847 
01848 Incidence* CalendarView::selectedIncidence()
01849 {
01850   Incidence *incidence = currentSelection();
01851   if ( !incidence ) {
01852     Incidence::List selectedIncidences = mTodoList->selectedIncidences();
01853     if ( !selectedIncidences.isEmpty() )
01854       incidence = selectedIncidences.first();
01855   }
01856   return incidence;
01857 }
01858 
01859 void CalendarView::showIncidence()
01860 {
01861   showIncidence( selectedIncidence() );
01862 }
01863 
01864 void CalendarView::editIncidence()
01865 {
01866   editIncidence( selectedIncidence() );
01867 }
01868 
01869 bool CalendarView::editIncidence( const QString& uid )
01870 {
01871   kdDebug(5850) << "CalendarView::editIncidence()" << endl;
01872   return editIncidence( mCalendar->incidence( uid ) );
01873 }
01874 
01875 void CalendarView::deleteIncidence()
01876 {
01877   deleteIncidence( selectedIncidence() );
01878 }
01879 
01880 void CalendarView::cutIncidence(Incidence *)
01881 {
01882   edit_cut();
01883 }
01884 
01885 void CalendarView::copyIncidence(Incidence *)
01886 {
01887   edit_copy();
01888 }
01889 
01890 void CalendarView::pasteIncidence()
01891 {
01892   edit_paste();
01893 }
01894 
01895 void CalendarView::showIncidence( Incidence *incidence )
01896 {
01897   KOEventViewerDialog *eventViewer = new KOEventViewerDialog( this );
01898   eventViewer->setIncidence( incidence );
01899   eventViewer->show();
01900 }
01901 
01902 bool CalendarView::editIncidence( Incidence *incidence, bool isCounter )
01903 {
01904   kdDebug(5850) << "CalendarView::editEvent()" << endl;
01905 
01906   if ( !incidence || !mChanger ) {
01907     KNotifyClient::beep();
01908     return false;
01909   }
01910   KOIncidenceEditor *tmp = editorDialog( incidence );
01911   if ( tmp ) {
01912     kdDebug(5850) << "CalendarView::editIncidence() in List" << endl;
01913     tmp->reload();
01914     tmp->raise();
01915     tmp->show();
01916     return true;
01917   }
01918 
01919   if ( incidence->isReadOnly() ) {
01920     showIncidence( incidence );
01921     return true;
01922   }
01923 
01924   if ( !isCounter && !mChanger->beginChange( incidence ) ) {
01925     warningChangeFailed( incidence );
01926     showIncidence( incidence );
01927     return false;
01928   }
01929 
01930   kdDebug(5850) << "CalendarView::editIncidence() new IncidenceEditor" << endl;
01931   KOIncidenceEditor *incidenceEditor = mDialogManager->getEditor( incidence );
01932   connectIncidenceEditor( incidenceEditor );
01933 
01934   mDialogList.insert( incidence, incidenceEditor );
01935   incidenceEditor->editIncidence( incidence, mCalendar );
01936   incidenceEditor->show();
01937   return true;
01938 }
01939 
01940 void CalendarView::deleteSubTodosIncidence ( Todo *todo )
01941 {
01942   if( !todo ) return;
01943 
01944   Incidence::List subTodos( todo->relations() );
01945   Incidence::List::Iterator it;
01946   Incidence *aIncidence;
01947   Todo *aTodo;
01948 
01949   for ( it= subTodos.begin(); it != subTodos.end(); ++it ) {
01950     aIncidence = *it;
01951     if( aIncidence && aIncidence->type() == "Todo" ) {
01952       aTodo = static_cast<Todo*>( aIncidence );
01953       deleteSubTodosIncidence ( aTodo );
01954     }
01955   }
01956   mChanger->deleteIncidence ( todo );
01957 }
01958 
01959 void CalendarView::deleteTodoIncidence ( Todo *todo, bool force )
01960 {
01961   if ( !todo ) return ;
01962 
01963   // it a simple todo, ask and delete it.
01964   if (todo->relations().isEmpty() ) {
01965     bool doDelete = true;
01966     if ( !force && KOPrefs::instance()->mConfirm ) {
01967       doDelete = ( msgItemDelete( todo ) == KMessageBox::Continue );
01968     }
01969     if ( doDelete )
01970       mChanger->deleteIncidence( todo );
01971     return;
01972   }
01973 
01974   /* Ok, this to-do has sub-to-dos, ask what to do */
01975   int km = KMessageBox::No;
01976   if ( !force ) {
01977     km=KMessageBox::questionYesNoCancel( this,
01978                                 i18n("The item \"%1\" has sub-to-dos. "
01979                                      "Do you want to delete just this item and "
01980                                      "make all its sub-to-dos independent, or "
01981                                      "delete the to-do with all its sub-to-dos?"
01982                                 ).arg( todo->summary() ),
01983                                 i18n("KOrganizer Confirmation"),
01984                                 i18n("Delete Only This"),
01985                                 i18n("Delete All"));
01986   }
01987   startMultiModify( i18n("Deleting sub-to-dos" ) );
01988   // Delete only the father
01989   if( km == KMessageBox::Yes ) {
01990 
01991     makeSubTodosIndependents ( todo );
01992     mChanger->deleteIncidence( todo );
01993   } else if ( km == KMessageBox::No ) {
01994     // Delete all
01995     // we have to hide the delete confirmation for each itemDate
01996     deleteSubTodosIncidence ( todo );
01997   }
01998   endMultiModify();
01999 }
02000 
02001 void CalendarView::deleteIncidence(Incidence *incidence, bool force)
02002 {
02003   if ( !incidence || !mChanger ) {
02004     if ( !force ) {
02005       KNotifyClient::beep();
02006     }
02007     return;
02008   }
02009   if ( incidence->isReadOnly() ) {
02010     if ( !force ) {
02011       KMessageBox::information( this, i18n("The item \"%1\" is marked read-only "
02012                                 "and cannot be deleted; it probably belongs to "
02013                                 "a read-only calendar resource.")
02014                                 .arg(incidence->summary()),
02015                                 i18n("Removing not possible"),
02016                                 "deleteReadOnlyIncidence" );
02017     }
02018     return;
02019   }
02020 
02021   CanDeleteIncidenceVisitor v;
02022 
02023   // Let the visitor do special things for special incidence types.
02024   // e.g. todos with children cannot be deleted, so act(..) returns false
02025   if ( !v.act( incidence, this ) )
02026     return;
02027   //If it is a todo, there are specific delete function
02028 
02029   if ( incidence && incidence->type()=="Todo" ) {
02030     deleteTodoIncidence( static_cast<Todo*>(incidence), force );
02031     return;
02032   }
02033 
02034   if ( incidence->doesRecur() ) {
02035     QDate itemDate = mViewManager->currentSelectionDate();
02036     kdDebug(5850) << "Recurrence-Date: " << itemDate.toString() << endl;
02037     int km = KMessageBox::Ok;
02038     if ( !force ) {
02039       if ( !itemDate.isValid() ) {
02040         kdDebug(5850) << "Date Not Valid" << endl;
02041         km = KMessageBox::warningContinueCancel(this,
02042           i18n("The calendar item \"%1\" recurs over multiple dates; "
02043                "are you sure you want to delete it "
02044                "and all its recurrences?").arg( incidence->summary() ),
02045                i18n("KOrganizer Confirmation"), i18n("Delete All") );
02046       } else {
02047         km = KOMessageBox::fourBtnMsgBox( this, QMessageBox::Warning,
02048           i18n("The calendar item \"%1\" recurs over multiple dates. "
02049                "Do you want to delete only the current one on %2, only all "
02050                "future recurrences, or all its recurrences?" )
02051                .arg( incidence->summary() )
02052                .arg( KGlobal::locale()->formatDate(itemDate)),
02053                i18n("KOrganizer Confirmation"), i18n("Delete C&urrent"),
02054                i18n("Delete &Future"),
02055                i18n("Delete &All"));
02056       }
02057     }
02058     switch(km) {
02059       case KMessageBox::Ok: // Continue // all
02060       case KMessageBox::Continue:
02061         mChanger->deleteIncidence( incidence );
02062         break;
02063 
02064       case KMessageBox::Yes: // just this one
02065         if ( mChanger->beginChange( incidence ) ) {
02066           Incidence *oldIncidence = incidence->clone();
02067           incidence->recurrence()->addExDate( itemDate );
02068           mChanger->changeIncidence( oldIncidence, incidence );
02069           mChanger->endChange( incidence );
02070           delete oldIncidence;
02071         }
02072         break;
02073       case KMessageBox::No: // all future items
02074         if ( mChanger->beginChange( incidence ) ) {
02075           Incidence *oldIncidence = incidence->clone();
02076           Recurrence *recur = incidence->recurrence();
02077           recur->setEndDate( itemDate.addDays(-1) );
02078           mChanger->changeIncidence( oldIncidence, incidence );
02079           mChanger->endChange( incidence );
02080           delete oldIncidence;
02081         }
02082         break;
02083     }
02084   } else {
02085     bool doDelete = true;
02086     if ( !force && KOPrefs::instance()->mConfirm ) {
02087       doDelete = ( msgItemDelete( incidence ) == KMessageBox::Continue );
02088     }
02089     if ( doDelete ) {
02090       mChanger->deleteIncidence( incidence );
02091       processIncidenceSelection( 0 );
02092     }
02093   }
02094 }
02095 
02096 void CalendarView::connectIncidenceEditor( KOIncidenceEditor *editor )
02097 {
02098   connect( this, SIGNAL( newIncidenceChanger( IncidenceChangerBase* ) ),
02099            editor, SLOT( setIncidenceChanger( IncidenceChangerBase* ) ) );
02100   editor->setIncidenceChanger( mChanger );
02101 }
02102 
02103 bool CalendarView::purgeCompletedSubTodos( Todo* todo, bool &allPurged )
02104 {
02105   if ( !todo ) return true;
02106   bool deleteThisTodo = true;
02107   Incidence::List subTodos( todo->relations() );
02108   Incidence *aIncidence;
02109   Todo *aTodo;
02110   Incidence::List::Iterator it;
02111   for ( it = subTodos.begin(); it != subTodos.end(); ++it ) {
02112     aIncidence = *it;
02113     if ( aIncidence && aIncidence->type()=="Todo" ) {
02114       aTodo = static_cast<Todo*>( aIncidence );
02115       deleteThisTodo &= purgeCompletedSubTodos( aTodo, allPurged );
02116     }
02117   }
02118 
02119   if ( deleteThisTodo ) {
02120     if ( todo->isCompleted() ) {
02121       if ( !mChanger->deleteIncidence( todo ) )
02122         allPurged = false;
02123     } else {
02124       deleteThisTodo = false;
02125     }
02126   } else {
02127     if ( todo->isCompleted() ) {
02128       allPurged = false;
02129     }
02130   }
02131   return deleteThisTodo;
02132 }
02133 
02134 void CalendarView::purgeCompleted()
02135 {
02136   int result = KMessageBox::warningContinueCancel(this,
02137       i18n("Delete all completed to-dos?"),i18n("Purge To-dos"),i18n("Purge"));
02138 
02139   if (result == KMessageBox::Continue) {
02140     bool allDeleted = true;
02141     startMultiModify( i18n("Purging completed to-dos") );
02142     Todo::List todos = calendar()->rawTodos();
02143     Todo::List rootTodos;
02144     Todo::List::ConstIterator it;
02145     for ( it = todos.begin(); it != todos.end(); ++it ) {
02146       Todo *aTodo = *it;
02147       if ( aTodo && !aTodo->relatedTo() )
02148         rootTodos.append( aTodo );
02149     }
02150     // now that we have a list of all root todos, check them and their children
02151     for ( it = rootTodos.begin(); it != rootTodos.end(); ++it ) {
02152       purgeCompletedSubTodos( *it, allDeleted );
02153     }
02154     endMultiModify();
02155     if ( !allDeleted ) {
02156       KMessageBox::information( this, i18n("Unable to purge to-dos with "
02157                                 "uncompleted children."), i18n("Delete To-do"),
02158                                 "UncompletedChildrenPurgeTodos" );
02159     }
02160   }
02161 }
02162 
02163 void CalendarView::warningChangeFailed( Incidence * )
02164 {
02165   KMessageBox::sorry( this, i18n("Unable to edit item: "
02166                                  "it is locked by another process.") );
02167 }
02168 
02169 void CalendarView::editCanceled( Incidence *i )
02170 {
02171   mCalendar->endChange( i );
02172 }
02173 
02174 void CalendarView::showErrorMessage( const QString &msg )
02175 {
02176   KMessageBox::error( this, msg );
02177 }
02178 
02179 void CalendarView::updateCategories()
02180 {
02181   QStringList allCats( calendar()->categories() );
02182   allCats.sort();
02183   QStringList categories( KOPrefs::instance()->mCustomCategories );
02184   for ( QStringList::ConstIterator si = allCats.constBegin(); si != allCats.constEnd(); ++si ) {
02185     if ( categories.find( *si ) == categories.end() ) {
02186       categories.append( *si );
02187     }
02188   }
02189   KOPrefs::instance()->mCustomCategories = categories;
02190   KOPrefs::instance()->writeConfig();
02191   // Make the category editor update the list!
02192   emit categoriesChanged();
02193 }
02194 
02195 void CalendarView::addIncidenceOn( Incidence *incadd, const QDate &dt )
02196 {
02197   if ( !incadd || !mChanger ) {
02198     KMessageBox::sorry(this, i18n("Unable to copy the item to %1.")
02199                        .arg( dt.toString() ), i18n("Copying Failed") );
02200     return;
02201   }
02202   Incidence *incidence = mCalendar->incidence( incadd->uid() );
02203   if ( !incidence ) incidence = incadd;
02204   // Create a copy of the incidence, since the incadd doesn't belong to us.
02205   incidence = incidence->clone();
02206   incidence->recreate();
02207 
02208   if ( incidence->type() == "Event" ) {
02209     Event *event = static_cast<Event*>(incidence);
02210 
02211     // Adjust date
02212     QDateTime start = event->dtStart();
02213     QDateTime end = event->dtEnd();
02214 
02215     int duration = start.daysTo( end );
02216     start.setDate( dt );
02217     end.setDate( dt.addDays( duration ) );
02218 
02219     event->setDtStart( start );
02220     event->setDtEnd( end );
02221 
02222   } else if ( incidence->type() == "Todo" ) {
02223     Todo *todo = static_cast<Todo*>(incidence);
02224     QDateTime due = todo->dtDue();
02225     due.setDate( dt );
02226 
02227     todo->setDtDue( due );
02228     todo->setHasDueDate( true );
02229   }
02230 
02231   if ( !mChanger->addIncidence( incidence, this ) ) {
02232     KODialogManager::errorSaveIncidence( this, incidence );
02233     delete incidence;
02234   }
02235 }
02236 
02237 void CalendarView::moveIncidenceTo( Incidence *incmove, const QDate &dt )
02238 {
02239   if ( !incmove || !mChanger ) {
02240     KMessageBox::sorry( this, i18n("Unable to move the item to %1.")
02241                         .arg( dt.toString() ), i18n("Moving Failed") );
02242     return;
02243   }
02244   Incidence *incidence = mCalendar->incidence( incmove->uid() );
02245   if ( !incidence ) {
02246     addIncidenceOn( incidence, dt );
02247     return;
02248   }
02249   Incidence *oldIncidence = incidence->clone();
02250   if ( !mChanger->beginChange( incidence ) ) {
02251     delete oldIncidence;
02252     return;
02253   }
02254 
02255   if ( incidence->type() == "Event" ) {
02256     Event *event = static_cast<Event*>(incidence);
02257 
02258     // Adjust date
02259     QDateTime start = event->dtStart();
02260     QDateTime end = event->dtEnd();
02261 
02262     int duration = start.daysTo( end );
02263     start.setDate( dt );
02264     end.setDate( dt.addDays( duration ) );
02265 
02266     event->setDtStart( start );
02267     event->setDtEnd( end );
02268 
02269   } else if ( incidence->type() == "Todo" ) {
02270     Todo *todo = static_cast<Todo*>(incidence);
02271     QDateTime due = todo->dtDue();
02272     due.setDate( dt );
02273 
02274     todo->setDtDue( due );
02275     todo->setHasDueDate( true );
02276   }
02277   mChanger->changeIncidence( oldIncidence, incidence );
02278   mChanger->endChange( incidence );
02279   delete oldIncidence;
02280 }
02281 
02282 void CalendarView::resourcesChanged()
02283 {
02284   mViewManager->resourcesChanged();
02285   updateView();
02286 }
02287 
02288 #include "calendarview.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys