korganizer

calendarview.cpp

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