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