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