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