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