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   }
01429   if ( alarms.isEmpty() ) {
01430     // Add an alarm if it didn't have one
01431     Alarm *alm = incidence->newAlarm();
01432     alm->setType( Alarm::Display );
01433     alm->setEnabled( true );
01434     int duration; // in secs
01435     switch( KOPrefs::instance()->mReminderTimeUnits ) {
01436     default:
01437     case 0: // mins
01438       duration = KOPrefs::instance()->mReminderTime * 60;
01439       break;
01440     case 1: // hours
01441       duration = KOPrefs::instance()->mReminderTime * 60 * 60;
01442       break;
01443     case 2: // days
01444       duration = KOPrefs::instance()->mReminderTime * 60 * 60 * 24;
01445       break;
01446     }
01447     if ( incidence->type() == "Event" ) {
01448       alm->setStartOffset( KCal::Duration( -duration ) );
01449     } else {
01450       alm->setEndOffset( KCal::Duration( -duration ) );
01451     }
01452   }
01453   mChanger->changeIncidence( oldincidence, incidence, KOGlobals::ALARM_MODIFIED, this );
01454   mChanger->endChange( incidence, 0, QString() );
01455   delete oldincidence;
01456 
01457 //  mClickedItem->updateIcons();
01458 }
01459 
01460 void CalendarView::dissociateOccurrence( Incidence *incidence, const QDate &date )
01461 {
01462   if ( !incidence || !mChanger ) {
01463     kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01464     return;
01465   }
01466 
01467   QPair<ResourceCalendar *, QString>p =
01468     CalHelper::incSubResourceCalendar( calendar(), incidence );
01469 
01470   if ( !mChanger->beginChange( incidence, p.first, p.second ) ) {
01471     kdDebug(5850) << "Unable to lock incidence " << endl;
01472     return;
01473   }
01474   startMultiModify( i18n("Dissociate occurrence") );
01475   Incidence*oldincidence = incidence->clone();
01476 
01477   Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true );
01478 
01479   if ( newInc ) {
01480     mChanger->changeIncidence( oldincidence, incidence, KOGlobals::NOTHING_MODIFIED, this );
01481     mChanger->addIncidence( newInc, p.first, p.second, this );
01482   } else {
01483     KMessageBox::sorry( this, i18n("Dissociating the occurrence failed."),
01484       i18n("Dissociating Failed") );
01485   }
01486   mChanger->endChange( incidence, p.first, p.second );
01487   endMultiModify();
01488   delete oldincidence;
01489 }
01490 
01491 void CalendarView::dissociateFutureOccurrence( Incidence *incidence, const QDate &date )
01492 {
01493   if ( !incidence || !mChanger ) {
01494     kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01495     return;
01496   }
01497 
01498   QPair<ResourceCalendar *, QString>p =
01499     CalHelper::incSubResourceCalendar( calendar(), incidence );
01500 
01501   if ( !mChanger->beginChange( incidence, p.first, p.second ) ) {
01502     kdDebug(5850) << "Unable to lock incidence " << endl;
01503     return;
01504   }
01505   startMultiModify( i18n("Dissociate future occurrences") );
01506   Incidence*oldincidence = incidence->clone();
01507 
01508   Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true );
01509   if ( newInc ) {
01510     mChanger->changeIncidence( oldincidence, incidence, KOGlobals::NOTHING_MODIFIED, this );
01511     mChanger->addIncidence( newInc, p.first, p.second, this );
01512   } else {
01513     KMessageBox::sorry( this, i18n("Dissociating the future occurrences failed."),
01514       i18n("Dissociating Failed") );
01515   }
01516   endMultiModify();
01517   mChanger->endChange( incidence, p.first, p.second );
01518   delete oldincidence;
01519 }
01520 
01521 
01522 /*****************************************************************************/
01523 
01524 
01525 void CalendarView::schedule_publish(Incidence *incidence)
01526 {
01527   if (incidence == 0)
01528     incidence = selectedIncidence();
01529 
01530   if (!incidence) {
01531     KMessageBox::information( this, i18n("No item selected."),
01532                               "PublishNoEventSelected" );
01533     return;
01534   }
01535 
01536   PublishDialog *publishdlg = new PublishDialog();
01537   if (incidence->attendeeCount()>0) {
01538     Attendee::List attendees = incidence->attendees();
01539     Attendee::List::ConstIterator it;
01540     for( it = attendees.begin(); it != attendees.end(); ++it ) {
01541       publishdlg->addAttendee( *it );
01542     }
01543   }
01544   if ( publishdlg->exec() == QDialog::Accepted ) {
01545     Incidence *inc = incidence->clone();
01546     inc->registerObserver( 0 );
01547     inc->clearAttendees();
01548 
01549     // Send the mail
01550     KCal::MailScheduler scheduler( mCalendar );
01551     if ( scheduler.publish( incidence, publishdlg->addresses() ) ) {
01552       KMessageBox::information( this, i18n("The item information was successfully sent."),
01553                                 i18n("Publishing"), "IncidencePublishSuccess" );
01554     } else {
01555       KMessageBox::error( this, i18n("Unable to publish the item '%1'").arg( incidence->summary() ) );
01556     }
01557   }
01558   delete publishdlg;
01559 }
01560 
01561 void CalendarView::schedule_request(Incidence *incidence)
01562 {
01563   schedule(Scheduler::Request,incidence);
01564 }
01565 
01566 void CalendarView::schedule_refresh(Incidence *incidence)
01567 {
01568   schedule(Scheduler::Refresh,incidence);
01569 }
01570 
01571 void CalendarView::schedule_cancel(Incidence *incidence)
01572 {
01573   schedule(Scheduler::Cancel,incidence);
01574 }
01575 
01576 void CalendarView::schedule_add(Incidence *incidence)
01577 {
01578   schedule(Scheduler::Add,incidence);
01579 }
01580 
01581 void CalendarView::schedule_reply(Incidence *incidence)
01582 {
01583   schedule(Scheduler::Reply,incidence);
01584 }
01585 
01586 void CalendarView::schedule_counter(Incidence *incidence)
01587 {
01588   schedule(Scheduler::Counter,incidence);
01589 }
01590 
01591 void CalendarView::schedule_declinecounter(Incidence *incidence)
01592 {
01593   schedule(Scheduler::Declinecounter,incidence);
01594 }
01595 
01596 void CalendarView::schedule_forward( Incidence *incidence )
01597 {
01598   if ( !incidence ) {
01599     incidence = selectedIncidence();
01600   }
01601 
01602   if ( !incidence ) {
01603     KMessageBox::information(
01604       this,
01605       i18n( "No item selected." ),
01606       i18n( "Forwarding" ),
01607       "ForwardNoEventSelected" );
01608     return;
01609   }
01610 
01611   PublishDialog publishdlg;
01612   if ( publishdlg.exec() == QDialog::Accepted ) {
01613     QString recipients = publishdlg.addresses();
01614     if ( incidence->organizer().isEmpty() ) {
01615       incidence->setOrganizer( Person( KOPrefs::instance()->fullName(),
01616                                        KOPrefs::instance()->email() ) );
01617     }
01618 
01619     ICalFormat format;
01620     QString messageText = format.createScheduleMessage( incidence, Scheduler::Request );
01621     KOMailClient mailer;
01622     if ( mailer.mailTo( incidence, recipients, messageText ) ) {
01623       KMessageBox::information(
01624         this,
01625         i18n( "The item information was successfully sent." ),
01626         i18n( "Forwarding" ),
01627         "IncidenceForwardSuccess" );
01628     } else {
01629       KMessageBox::error(
01630         this,
01631         i18n( "Unable to forward the item '%1'" ).arg( incidence->summary() ),
01632         i18n( "Forwarding Error" ) );
01633     }
01634   }
01635 }
01636 
01637 void CalendarView::mailFreeBusy( int daysToPublish )
01638 {
01639   QDateTime start = QDateTime::currentDateTime();
01640   QDateTime end = start.addDays(daysToPublish);
01641 
01642   FreeBusy *freebusy = new FreeBusy(mCalendar, start, end);
01643   freebusy->setOrganizer( Person( KOPrefs::instance()->fullName(),
01644                       KOPrefs::instance()->email() ) );
01645 
01646   kdDebug(5850) << "calendarview: schedule_publish_freebusy: startDate: "
01647      << KGlobal::locale()->formatDateTime( start ) << " End Date: "
01648      << KGlobal::locale()->formatDateTime( end ) << endl;
01649 
01650   PublishDialog *publishdlg = new PublishDialog();
01651   if ( publishdlg->exec() == QDialog::Accepted ) {
01652     // Send the mail
01653     KCal::MailScheduler scheduler( mCalendar );
01654     if ( scheduler.publish( freebusy, publishdlg->addresses() ) ) {
01655       KMessageBox::information( this, i18n("The free/busy information was successfully sent."),
01656                                 i18n("Sending Free/Busy"), "FreeBusyPublishSuccess" );
01657     } else {
01658       KMessageBox::error( this, i18n("Unable to publish the free/busy data.") );
01659     }
01660   }
01661   delete freebusy;
01662   delete publishdlg;
01663 }
01664 
01665 void CalendarView::uploadFreeBusy()
01666 {
01667   KOGroupware::instance()->freeBusyManager()->publishFreeBusy();
01668 }
01669 
01670 void CalendarView::schedule(Scheduler::Method method, Incidence *incidence)
01671 {
01672   if ( !incidence ) {
01673     incidence = selectedIncidence();
01674   }
01675 
01676   if ( !incidence ) {
01677     KMessageBox::sorry( this, i18n("No item selected."),
01678                         "ScheduleNoEventSelected" );
01679     return;
01680   }
01681 
01682   if( incidence->attendeeCount() == 0 && method != Scheduler::Publish ) {
01683     KMessageBox::information( this, i18n("The item has no attendees."),
01684                               "ScheduleNoIncidences" );
01685     return;
01686   }
01687 
01688   Incidence *inc = incidence->clone();
01689   inc->registerObserver( 0 );
01690   inc->clearAttendees();
01691 
01692   // Send the mail
01693   KCal::MailScheduler scheduler( mCalendar );
01694   if ( scheduler.performTransaction( incidence, method ) ) {
01695     KMessageBox::information( this, i18n("The groupware message for item '%1'"
01696                                 "was successfully sent.\nMethod: %2")
01697                                 .arg( incidence->summary() )
01698                                 .arg( Scheduler::methodName( method ) ),
01699                               i18n("Sending Free/Busy"),
01700                               "FreeBusyPublishSuccess" );
01701   } else {
01702     KMessageBox::error( this, i18n("Groupware message sending failed. "
01703                         "%2 is request/reply/add/cancel/counter/etc.",
01704                         "Unable to send the item '%1'.\nMethod: %2")
01705                         .arg( incidence->summary() )
01706                         .arg( Scheduler::methodName( method ) ) );
01707   }
01708 }
01709 
01710 void CalendarView::openAddressbook()
01711 {
01712   KRun::runCommand("kaddressbook");
01713 }
01714 
01715 void CalendarView::setModified(bool modified)
01716 {
01717   if (mModified != modified) {
01718     mModified = modified;
01719     emit modifiedChanged(mModified);
01720   }
01721 }
01722 
01723 bool CalendarView::isReadOnly()
01724 {
01725   return mReadOnly;
01726 }
01727 
01728 void CalendarView::setReadOnly(bool readOnly)
01729 {
01730   if (mReadOnly != readOnly) {
01731     mReadOnly = readOnly;
01732     emit readOnlyChanged(mReadOnly);
01733   }
01734 }
01735 
01736 bool CalendarView::isModified()
01737 {
01738   return mModified;
01739 }
01740 
01741 void CalendarView::print()
01742 {
01743 #ifndef KORG_NOPRINTER
01744   KOCoreHelper helper;
01745   CalPrinter printer( this, mCalendar, &helper );
01746   connect( this, SIGNAL(configChanged()), &printer, SLOT(updateConfig()) );
01747 
01748   KOrg::BaseView *currentView = mViewManager->currentView();
01749 
01750   CalPrinterBase::PrintType printType = CalPrinterBase::Month;
01751   if ( currentView ) printType = currentView->printType();
01752 
01753   DateList tmpDateList = mDateNavigator->selectedDates();
01754   Incidence::List selectedIncidences;
01755   if ( mViewManager->currentView() ) {
01756     selectedIncidences = mViewManager->currentView()->selectedIncidences();
01757   }
01758   printer.print( printType, tmpDateList.first(), tmpDateList.last(), selectedIncidences );
01759 #endif
01760 }
01761 
01762 void CalendarView::exportWeb()
01763 {
01764   // FIXME: Get rid of the settings object. When can I delete it???
01765   HTMLExportSettings *settings = new HTMLExportSettings( "KOrganizer" );
01766   // Manually read in the config, because parametrized kconfigxt objects don't
01767   // seem to load the config theirselves
01768   if ( settings ) settings->readConfig();
01769   ExportWebDialog *dlg = new ExportWebDialog( settings, this );
01770   connect( dlg,  SIGNAL( exportHTML( HTMLExportSettings* ) ),
01771            this, SIGNAL( exportHTML( HTMLExportSettings* ) ) );
01772   dlg->show();
01773 }
01774 
01775 void CalendarView::exportICalendar()
01776 {
01777   QString filename = KFileDialog::getSaveFileName("icalout.ics",i18n("*.ics|ICalendars"),this);
01778   if ( !filename.isEmpty() )
01779   {
01780     // Force correct extension
01781     if (filename.right(4) != ".ics") filename += ".ics";
01782     if ( QFile( filename ).exists() ) {
01783       if ( KMessageBox::No == KMessageBox::warningYesNo(
01784              this,
01785              i18n( "Do you want to overwrite %1?").arg(filename) ) ) {
01786           return;
01787       }
01788     }
01789     FileStorage storage( mCalendar, filename, new ICalFormat );
01790     storage.save();
01791   }
01792 }
01793 
01794 void CalendarView::exportVCalendar()
01795 {
01796   if (mCalendar->journals().count() > 0) {
01797     int result = KMessageBox::warningContinueCancel(this,
01798         i18n("The journal entries can not be exported to a vCalendar file."),
01799         i18n("Data Loss Warning"),i18n("Proceed"),"dontaskVCalExport",
01800         true);
01801     if (result != KMessageBox::Continue) return;
01802   }
01803 
01804   QString filename = KFileDialog::getSaveFileName("vcalout.vcs",i18n("*.vcs|vCalendars"),this);
01805   if ( !filename.isEmpty() )
01806   {
01807     // TODO: I don't like forcing extensions:
01808     // Force correct extension
01809     if (filename.right(4) != ".vcs") filename += ".vcs";
01810     if ( QFile( filename ).exists() ) {
01811       if ( KMessageBox::No == KMessageBox::warningYesNo(
01812              this,
01813              i18n( "Do you want to overwrite %1?").arg(filename ) ) ) {
01814              return;
01815       }
01816     }
01817     FileStorage storage( mCalendar, filename, new VCalFormat );
01818     storage.save();
01819   }
01820 }
01821 
01822 void CalendarView::eventUpdated(Incidence *)
01823 {
01824   setModified();
01825   // Don't call updateView here. The code, which has caused the update of the
01826   // event is responsible for updating the view.
01827 //  updateView();
01828 }
01829 
01830 void CalendarView::adaptNavigationUnits()
01831 {
01832   if (mViewManager->currentView()->isEventView()) {
01833     int days = mViewManager->currentView()->currentDateCount();
01834     if (days == 1) {
01835       emit changeNavStringPrev(i18n("&Previous Day"));
01836       emit changeNavStringNext(i18n("&Next Day"));
01837     } else {
01838       emit changeNavStringPrev(i18n("&Previous Week"));
01839       emit changeNavStringNext(i18n("&Next Week"));
01840     }
01841   }
01842 }
01843 
01844 void CalendarView::processMainViewSelection( Incidence *incidence, const QDate &date )
01845 {
01846   if ( incidence ) mTodoList->clearSelection();
01847   processIncidenceSelection( incidence, date );
01848 }
01849 
01850 void CalendarView::processTodoListSelection( Incidence *incidence, const QDate &date )
01851 {
01852   if ( incidence && mViewManager->currentView() ) {
01853     mViewManager->currentView()->clearSelection();
01854   }
01855   processIncidenceSelection( incidence, date );
01856 }
01857 
01858 void CalendarView::processIncidenceSelection( Incidence *incidence, const QDate &date )
01859 {
01860   if ( incidence != mSelectedIncidence ) {
01861     // This signal also must be emitted if incidence is 0
01862     emit incidenceSelected( incidence, date );
01863   }
01864 
01865   if ( !incidence ) {
01866    mSelectedIncidence = incidence;
01867    return;
01868   }
01869   if ( incidence == mSelectedIncidence ) {
01870     if ( !incidence->doesRecur() || mSaveDate == date ) {
01871       return;
01872     }
01873   }
01874 
01875   mSelectedIncidence = incidence;
01876   mSaveDate = date;
01877 
01878   emit incidenceSelected( mSelectedIncidence, date );
01879   bool organizerEvents = false;
01880   bool groupEvents = false;
01881   bool todo = false;
01882   bool subtodo = false;
01883 
01884   organizerEvents = KOPrefs::instance()->thatIsMe( incidence->organizer().email() );
01885   groupEvents = incidence->attendeeByMails( KOPrefs::instance()->allEmails() );
01886 
01887   if ( incidence->type() == "Todo" ) {
01888     todo = true;
01889     subtodo = ( incidence->relatedTo() != 0 );
01890   }
01891 
01892   emit todoSelected( todo );
01893   emit subtodoSelected( subtodo );
01894   emit organizerEventsSelected( organizerEvents );
01895   emit groupEventsSelected( groupEvents );
01896 }
01897 
01898 
01899 void CalendarView::checkClipboard()
01900 {
01901 #ifndef KORG_NODND
01902   if (ICalDrag::canDecode(QApplication::clipboard()->data())) {
01903     kdDebug(5850) << "CalendarView::checkClipboard() true" << endl;
01904     emit pasteEnabled(true);
01905   } else {
01906     kdDebug(5850) << "CalendarView::checkClipboard() false" << endl;
01907     emit pasteEnabled(false);
01908   }
01909 #endif
01910 }
01911 
01912 void CalendarView::showDates( const DateList &selectedDates, const QDate &preferredMonth )
01913 {
01914   mDateNavigatorContainer->selectDates( selectedDates, preferredMonth );
01915   mNavigatorBar->selectDates( selectedDates );
01916 
01917   if ( mViewManager->currentView() ) {
01918     updateView( selectedDates.first(), selectedDates.last() );
01919   } else {
01920     mViewManager->showAgendaView();
01921   }
01922 }
01923 
01924 void CalendarView::editFilters()
01925 {
01926   kdDebug(5850) << "CalendarView::editFilters()" << endl;
01927 
01928   CalFilter *filter = mFilters.first();
01929   while( filter ) {
01930     kdDebug(5850) << " Filter: " << filter->name() << endl;
01931     filter = mFilters.next();
01932   }
01933 
01934   mDialogManager->showFilterEditDialog(&mFilters);
01935 }
01936 
01939 void CalendarView::updateFilter()
01940 {
01941   QStringList filters;
01942   CalFilter *filter;
01943 
01944   int pos = mFilters.find( mCurrentFilter );
01945   if ( pos < 0 ) {
01946     mCurrentFilter = 0;
01947   }
01948 
01949   filters << i18n("No filter");
01950   for ( filter = mFilters.first(); filter; filter = mFilters.next() ) {
01951     filters << filter->name();
01952   }
01953 
01954   emit newFilterListSignal( filters );
01955   // account for the additional "No filter" at the beginning! if the
01956   // filter is not in the list, pos == -1...
01957   emit selectFilterSignal( pos+1 );
01958   mCalendar->setFilter( mCurrentFilter );
01959   updateView();
01960 }
01961 
01964 void CalendarView::filterActivated( int filterNo )
01965 {
01966   CalFilter *newFilter = 0;
01967   if ( filterNo > 0 && filterNo <= int(mFilters.count()) ) {
01968     newFilter = mFilters.at( filterNo-1 );
01969   }
01970   if ( newFilter != mCurrentFilter ) {
01971     mCurrentFilter = newFilter;
01972     mCalendar->setFilter( mCurrentFilter );
01973     updateView();
01974   }
01975   emit filterChanged();
01976 }
01977 
01978 QString CalendarView::currentFilterName() const
01979 {
01980   if ( mCurrentFilter) {
01981     return mCurrentFilter->name();
01982   } else return i18n("No filter");
01983 }
01984 
01985 void CalendarView::takeOverEvent()
01986 {
01987   Incidence *incidence = currentSelection();
01988 
01989   if (!incidence) return;
01990 
01991   incidence->setOrganizer( Person( KOPrefs::instance()->fullName(),
01992                            KOPrefs::instance()->email() ) );
01993   incidence->recreate();
01994   incidence->setReadOnly(false);
01995 
01996   updateView();
01997 }
01998 
01999 void CalendarView::takeOverCalendar()
02000 {
02001   Incidence::List incidences = mCalendar->rawIncidences();
02002   Incidence::List::Iterator it;
02003 
02004   for ( it = incidences.begin(); it != incidences.end(); ++it ) {
02005     (*it)->setOrganizer( Person( KOPrefs::instance()->fullName(),
02006                          KOPrefs::instance()->email() ) );
02007     (*it)->recreate();
02008     (*it)->setReadOnly(false);
02009   }
02010   updateView();
02011 }
02012 
02013 void CalendarView::showIntro()
02014 {
02015   kdDebug(5850) << "To be implemented." << endl;
02016 }
02017 
02018 void CalendarView::showDateNavigator( bool show )
02019 {
02020   if( show )
02021     mDateNavigatorContainer->show();
02022   else
02023     mDateNavigatorContainer->hide();
02024 }
02025 
02026 void CalendarView::showTodoView( bool show )
02027 {
02028   if( show )
02029     mTodoList->show();
02030   else
02031     mTodoList->hide();
02032 }
02033 
02034 void CalendarView::showEventViewer( bool show )
02035 {
02036   if( show )
02037     mEventViewer->show();
02038   else
02039     mEventViewer->hide();
02040 }
02041 
02042 
02043 void CalendarView::addView(KOrg::BaseView *view)
02044 {
02045   mViewManager->addView(view);
02046 }
02047 
02048 void CalendarView::showView(KOrg::BaseView *view)
02049 {
02050   mViewManager->showView(view);
02051 }
02052 
02053 void CalendarView::addExtension( CalendarViewExtension::Factory *factory )
02054 {
02055   CalendarViewExtension *extension = factory->create( mLeftSplitter );
02056 
02057   mExtensions.append( extension );
02058 }
02059 
02060 void CalendarView::toggleExpand()
02061 {
02062   showLeftFrame( mLeftFrame->isHidden() );
02063 }
02064 
02065 void CalendarView::showLeftFrame(bool show)
02066 {
02067   if (show) {
02068     mLeftFrame->show();
02069     emit calendarViewExpanded( false );
02070   } else {
02071     mLeftFrame->hide();
02072     emit calendarViewExpanded( true );
02073   }
02074 }
02075 
02076 void CalendarView::calendarModified( bool modified, Calendar * )
02077 {
02078   setModified( modified );
02079 }
02080 
02081 Todo *CalendarView::selectedTodo()
02082 {
02083   Incidence *incidence = currentSelection();
02084   if ( incidence && incidence->type() == "Todo" ) {
02085     return static_cast<Todo *>( incidence );
02086   }
02087   incidence = 0;
02088 
02089   Incidence::List selectedIncidences = mTodoList->selectedIncidences();
02090   if ( !selectedIncidences.isEmpty() ) incidence = selectedIncidences.first();
02091   if ( incidence && incidence->type() == "Todo" ) {
02092     return static_cast<Todo *>( incidence );
02093   }
02094 
02095   return 0;
02096 }
02097 
02098 void CalendarView::dialogClosing( Incidence *in )
02099 {
02100   // FIXME: this doesn't work, because if it's a new incidence, it's not locked!
02101   mChanger->endChange( in, 0, QString() );
02102   mDialogList.remove( in );
02103 }
02104 
02105 Incidence *CalendarView::currentSelection()
02106 {
02107   return mViewManager->currentSelection();
02108 }
02109 
02110 Incidence* CalendarView::selectedIncidence()
02111 {
02112   Incidence *incidence = currentSelection();
02113   if ( !incidence ) {
02114     Incidence::List selectedIncidences = mTodoList->selectedIncidences();
02115     if ( !selectedIncidences.isEmpty() )
02116       incidence = selectedIncidences.first();
02117   }
02118   return incidence;
02119 }
02120 
02121 void CalendarView::showIncidence()
02122 {
02123   showIncidence( selectedIncidence(), activeIncidenceDate() );
02124 }
02125 
02126 void CalendarView::editIncidence()
02127 {
02128   editIncidence( selectedIncidence(), activeIncidenceDate() );
02129 }
02130 
02131 bool CalendarView::editIncidence( const QString &uid )
02132 {
02133   return editIncidence( mCalendar->incidence( uid ), QDate() );
02134 }
02135 
02136 bool CalendarView::editIncidence( const QString &uid, const QDate &date )
02137 {
02138   return editIncidence( mCalendar->incidence( uid ), date );
02139 }
02140 
02141 void CalendarView::deleteIncidence()
02142 {
02143   deleteIncidence( selectedIncidence() );
02144 }
02145 
02146 void CalendarView::cutIncidence(Incidence *)
02147 {
02148   edit_cut();
02149 }
02150 
02151 void CalendarView::copyIncidence(Incidence *)
02152 {
02153   edit_copy();
02154 }
02155 
02156 void CalendarView::pasteIncidence()
02157 {
02158   edit_paste();
02159 }
02160 
02161 void CalendarView::showIncidence( Incidence *incidence, const QDate &date )
02162 {
02163   if ( !incidence ) {
02164     return;
02165   }
02166 
02167   KOEventViewerDialog *eventViewer = new KOEventViewerDialog( calendar(), this );
02168   eventViewer->setIncidence( incidence, date );
02169   eventViewer->show();
02170 }
02171 
02172 bool CalendarView::editIncidence( Incidence *incidence, const QDate &date, bool isCounter )
02173 {
02174   kdDebug(5850) << "CalendarView::editEvent()" << endl;
02175 
02176   CalendarResources *stdcal = dynamic_cast<CalendarResources *>( mCalendar );
02177   if( stdcal && !stdcal->hasCalendarResources() ) {
02178     KMessageBox::sorry(
02179       this,
02180       i18n( "No resources found. We can not edit the item." ) );
02181     return false;
02182   }
02183 
02184   // FIXME: This is a nasty hack, since we need to set a parent for the
02185   //        resource selection dialog. However, we don't have any UI methods
02186   //        in the calendar, only in the CalendarResources::DestinationPolicy
02187   //        So we need to type-cast it and extract it from the CalendarResources
02188   QWidget *tmpparent = 0;
02189   if ( stdcal ) {
02190     tmpparent = stdcal->dialogParentWidget();
02191     stdcal->setDialogParentWidget( this );
02192   }
02193 
02194   if ( !incidence ) {
02195     kdDebug(5850) << "Empty Incidence" << endl;
02196     KNotifyClient::beep();
02197     return false;
02198   }
02199 
02200   if ( !mChanger ) {
02201     kdDebug(5850) << "Empty Changer" << endl;
02202     KNotifyClient::beep();
02203     return false;
02204   }
02205 
02206   KOIncidenceEditor *tmp = editorDialog( incidence );
02207   if ( tmp ) {
02208     kdDebug(5850) << "CalendarView::editIncidence() in List" << endl;
02209     tmp->reload();
02210     tmp->raise();
02211     tmp->show();
02212     return true;
02213   }
02214 
02215   if ( incidence->isReadOnly() ) {
02216     showIncidence( incidence, date );
02217     return true;
02218   }
02219 
02220   QPair<ResourceCalendar *, QString>p =
02221     CalHelper::incSubResourceCalendar( calendar(), incidence );
02222 
02223   Incidence *savedIncidence = incidence->clone();
02224   Incidence *incToChange;
02225 
02226   if ( incidence->doesRecur() ) {
02227     KOGlobals::WhichOccurrences chosenOption;
02228     incToChange = singleOccurrenceOrAll( incidence, KOGlobals::EDIT, chosenOption, date );
02229   } else {
02230     incToChange = incidence;
02231   }
02232 
02233   // If the user pressed cancel incToChange is 0
02234   if ( incToChange ) {
02235     if ( !isCounter && !mChanger->beginChange( incToChange, p.first, p.second ) ) {
02236       warningChangeFailed( incToChange );
02237       showIncidence( incToChange, date );
02238 
02239       return false;
02240     }
02241 
02242     kdDebug(5850) << "CalendarView::editIncidence() new IncidenceEditor" << endl;
02243     KOIncidenceEditor *incidenceEditor = mDialogManager->getEditor( incToChange );
02244     connectIncidenceEditor( incidenceEditor );
02245 
02246     mDialogList.insert( incToChange, incidenceEditor );
02247     if ( incidence != incToChange ) {
02248       incidenceEditor->setRecurringIncidence( savedIncidence, incidence );
02249     }
02250     incidenceEditor->setResource( p.first, p.second );
02251     incidenceEditor->editIncidence( incToChange, date, mCalendar );
02252     incidenceEditor->show();
02253     return true;
02254   } else {
02255     return false;
02256   }
02257 }
02258 
02259 void CalendarView::deleteSubTodosIncidence ( Todo *todo )
02260 {
02261   if( !todo ) return;
02262 
02263   Incidence::List subTodos( todo->relations() );
02264   Incidence::List::Iterator it;
02265   Incidence *aIncidence;
02266   Todo *aTodo;
02267 
02268   for ( it= subTodos.begin(); it != subTodos.end(); ++it ) {
02269     aIncidence = *it;
02270     if( aIncidence && aIncidence->type() == "Todo" ) {
02271       aTodo = static_cast<Todo*>( aIncidence );
02272       deleteSubTodosIncidence ( aTodo );
02273     }
02274   }
02275   mChanger->deleteIncidence ( todo, this );
02276 }
02277 
02278 void CalendarView::deleteTodoIncidence ( Todo *todo, bool force )
02279 {
02280   if ( !todo ) return ;
02281 
02282   // it a simple todo, ask and delete it.
02283   if (todo->relations().isEmpty() ) {
02284     bool doDelete = true;
02285     if ( !force && KOPrefs::instance()->mConfirm ) {
02286       doDelete = ( msgItemDelete( todo ) == KMessageBox::Continue );
02287     }
02288     if ( doDelete )
02289       mChanger->deleteIncidence( todo, this );
02290     return;
02291   }
02292 
02293   /* Ok, this to-do has sub-to-dos, ask what to do */
02294   int km = KMessageBox::No;
02295   if ( !force ) {
02296     km = KMessageBox::questionYesNoCancel(
02297       this,
02298       i18n("The item \"%1\" has sub-to-dos. "
02299            "Do you want to delete just this item and "
02300            "make all its sub-to-dos independent, or "
02301            "delete the to-do with all its sub-to-dos?"
02302         ).arg( todo->summary() ),
02303       i18n("KOrganizer Confirmation"),
02304       i18n("Delete Only This"),
02305       i18n("Delete All"));
02306   }
02307   startMultiModify( i18n("Deleting sub-to-dos" ) );
02308   // Delete only the father
02309   if( km == KMessageBox::Yes ) {
02310     // Instead of making a subto-do independent, why not relate
02311     // it to it's dead father's parent?
02312     makeChildrenIndependent ( todo );
02313     mChanger->deleteIncidence( todo, this );
02314   } else if ( km == KMessageBox::No ) {
02315     // Delete all
02316     // we have to hide the delete confirmation for each itemDate
02317     deleteSubTodosIncidence ( todo );
02318   }
02319   endMultiModify();
02320 }
02321 
02322 void CalendarView::deleteIncidence(Incidence *incidence, bool force)
02323 {
02324   if ( !incidence || !mChanger ) {
02325     if ( !force ) {
02326       KNotifyClient::beep();
02327     }
02328     return;
02329   }
02330   if ( incidence->isReadOnly() ) {
02331     if ( !force ) {
02332       KMessageBox::information( this, i18n("The item \"%1\" is marked read-only "
02333                                 "and cannot be deleted; it probably belongs to "
02334                                 "a read-only calendar resource.")
02335                                 .arg(incidence->summary()),
02336                                 i18n("Removing not possible"),
02337                                 "deleteReadOnlyIncidence" );
02338     }
02339     return;
02340   }
02341 
02342   CanDeleteIncidenceVisitor v;
02343 
02344   // Let the visitor do special things for special incidence types.
02345   // e.g. todos with children cannot be deleted, so act(..) returns false
02346   if ( !v.act( incidence, this ) )
02347     return;
02348   //If it is a todo, there are specific delete function
02349 
02350   if ( incidence && incidence->type()=="Todo" ) {
02351     deleteTodoIncidence( static_cast<Todo*>(incidence), force );
02352     return;
02353   }
02354 
02355   if ( incidence->doesRecur() ) {
02356     QDate itemDate = mViewManager->currentSelectionDate();
02357     kdDebug(5850) << "Recurrence-Date: " << itemDate.toString() << endl;
02358     int km = KMessageBox::Ok;
02359     if ( !force ) {
02360       if ( !itemDate.isValid() ) {
02361         kdDebug(5850) << "Date Not Valid" << endl;
02362         km = KMessageBox::warningContinueCancel(this,
02363           i18n("The calendar item \"%1\" recurs over multiple dates; "
02364                "are you sure you want to delete it "
02365                "and all its recurrences?").arg( incidence->summary() ),
02366                i18n("KOrganizer Confirmation"), i18n("Delete All") );
02367       } else {
02368         km = KOMessageBox::fourBtnMsgBox( this, QMessageBox::Warning,
02369           i18n("The calendar item \"%1\" recurs over multiple dates. "
02370                "Do you want to delete only the current one on %2, only all "
02371                "future recurrences, or all its recurrences?" )
02372                .arg( incidence->summary() )
02373                .arg( KGlobal::locale()->formatDate(itemDate)),
02374                i18n("KOrganizer Confirmation"), i18n("Delete C&urrent"),
02375                i18n("Delete &Future"),
02376                i18n("Delete &All"));
02377       }
02378     }
02379 
02380     QPair<ResourceCalendar *, QString>p =
02381       CalHelper::incSubResourceCalendar( calendar(), incidence );
02382 
02383     switch(km) {
02384       case KMessageBox::Ok: // Continue // all
02385       case KMessageBox::Continue:
02386         mChanger->deleteIncidence( incidence, this );
02387         break;
02388 
02389       case KMessageBox::Yes: // just this one
02390         if ( mChanger->beginChange( incidence, p.first, p.second ) ) {
02391           Incidence *oldIncidence = incidence->clone();
02392           incidence->recurrence()->addExDate( itemDate );
02393           mChanger->changeIncidence( oldIncidence, incidence,
02394                                      KOGlobals::RECURRENCE_MODIFIED_ONE_ONLY, this );
02395           mChanger->endChange( incidence, p.first, p.second );
02396           delete oldIncidence;
02397         }
02398         break;
02399       case KMessageBox::No: // all future items
02400         if ( mChanger->beginChange( incidence, p.first, p.second ) ) {
02401           Incidence *oldIncidence = incidence->clone();
02402           Recurrence *recur = incidence->recurrence();
02403           recur->setEndDate( itemDate.addDays(-1) );
02404           mChanger->changeIncidence( oldIncidence, incidence,
02405                                      KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE,  this );
02406           mChanger->endChange( incidence, p.first, p.second );
02407           delete oldIncidence;
02408         }
02409         break;
02410     }
02411   } else {
02412     bool doDelete = true;
02413     if ( !force && KOPrefs::instance()->mConfirm ) {
02414       doDelete = ( msgItemDelete( incidence ) == KMessageBox::Continue );
02415     }
02416     if ( doDelete ) {
02417       mChanger->deleteIncidence( incidence, this );
02418       processIncidenceSelection( 0, QDate() );
02419     }
02420   }
02421 }
02422 
02423 void CalendarView::connectIncidenceEditor( KOIncidenceEditor *editor )
02424 {
02425   connect( this, SIGNAL( newIncidenceChanger( IncidenceChangerBase* ) ),
02426            editor, SLOT( setIncidenceChanger( IncidenceChangerBase* ) ) );
02427   editor->setIncidenceChanger( mChanger );
02428 }
02429 
02430 bool CalendarView::purgeCompletedSubTodos( Todo* todo, bool &allPurged )
02431 {
02432   if ( !todo ) return true;
02433   bool deleteThisTodo = true;
02434   Incidence::List subTodos( todo->relations() );
02435   Incidence *aIncidence;
02436   Todo *aTodo;
02437   Incidence::List::Iterator it;
02438   for ( it = subTodos.begin(); it != subTodos.end(); ++it ) {
02439     aIncidence = *it;
02440     if ( aIncidence && aIncidence->type()=="Todo" ) {
02441       aTodo = static_cast<Todo*>( aIncidence );
02442       deleteThisTodo &= purgeCompletedSubTodos( aTodo, allPurged );
02443     }
02444   }
02445 
02446   if ( deleteThisTodo ) {
02447     if ( todo->isCompleted() ) {
02448       if ( !mChanger->deleteIncidence( todo, this ) )
02449         allPurged = false;
02450     } else {
02451       deleteThisTodo = false;
02452     }
02453   } else {
02454     if ( todo->isCompleted() ) {
02455       allPurged = false;
02456     }
02457   }
02458   return deleteThisTodo;
02459 }
02460 
02461 void CalendarView::purgeCompleted()
02462 {
02463   int result = KMessageBox::warningContinueCancel(this,
02464       i18n("Delete all completed to-dos?"),i18n("Purge To-dos"),i18n("Purge"));
02465 
02466   if (result == KMessageBox::Continue) {
02467     bool allDeleted = true;
02468     startMultiModify( i18n("Purging completed to-dos") );
02469     Todo::List todos = calendar()->rawTodos();
02470     Todo::List rootTodos;
02471     Todo::List::ConstIterator it;
02472     for ( it = todos.begin(); it != todos.end(); ++it ) {
02473       Todo *aTodo = *it;
02474       if ( aTodo && !aTodo->relatedTo() )
02475         rootTodos.append( aTodo );
02476     }
02477     // now that we have a list of all root todos, check them and their children
02478     for ( it = rootTodos.begin(); it != rootTodos.end(); ++it ) {
02479       purgeCompletedSubTodos( *it, allDeleted );
02480     }
02481     endMultiModify();
02482     if ( !allDeleted ) {
02483       KMessageBox::information( this, i18n("Unable to purge to-dos with "
02484                                 "uncompleted children."), i18n("Delete To-do"),
02485                                 "UncompletedChildrenPurgeTodos" );
02486     }
02487   }
02488 }
02489 
02490 void CalendarView::warningChangeFailed( Incidence *incidence )
02491 {
02492   if ( incidence ) {
02493     KMessageBox::sorry(
02494       this,
02495       i18n( "Unable to edit \"%1\" because it is locked by another process." ).
02496       arg( incidence->summary() ) );
02497   }
02498 }
02499 
02500 void CalendarView::editCanceled( Incidence *incidence )
02501 {
02502   mCalendar->endChange( incidence );
02503 }
02504 
02505 void CalendarView::showErrorMessage( const QString &msg )
02506 {
02507   KMessageBox::error( this, msg );
02508 }
02509 
02510 void CalendarView::updateCategories()
02511 {
02512   QStringList allCats( calendar()->categories() );
02513   allCats.sort();
02514   QStringList categories( KOPrefs::instance()->mCustomCategories );
02515   for ( QStringList::ConstIterator si = allCats.constBegin(); si != allCats.constEnd(); ++si ) {
02516     if ( categories.find( *si ) == categories.end() ) {
02517       categories.append( *si );
02518     }
02519   }
02520   KOPrefs::instance()->mCustomCategories = categories;
02521   KOPrefs::instance()->writeConfig();
02522   // Make the category editor update the list!
02523   emit categoriesChanged();
02524 }
02525 
02526 void CalendarView::addIncidenceOn( Incidence *incadd, const QDate &dt )
02527 {
02528   if ( !incadd || !mChanger ) {
02529     KMessageBox::sorry(this, i18n("Unable to copy the item to %1.")
02530                        .arg( dt.toString() ), i18n("Copying Failed") );
02531     return;
02532   }
02533   Incidence *incidence = mCalendar->incidence( incadd->uid() );
02534   if ( !incidence ) incidence = incadd;
02535   // Create a copy of the incidence, since the incadd doesn't belong to us.
02536   incidence = incidence->clone();
02537   incidence->recreate();
02538 
02539   if ( incidence->type() == "Event" ) {
02540     Event *event = static_cast<Event*>(incidence);
02541 
02542     // Adjust date
02543     QDateTime start = event->dtStart();
02544     QDateTime end = event->dtEnd();
02545 
02546     int duration = start.daysTo( end );
02547     start.setDate( dt );
02548     end.setDate( dt.addDays( duration ) );
02549 
02550     event->setDtStart( start );
02551     event->setDtEnd( end );
02552 
02553   } else if ( incidence->type() == "Todo" ) {
02554     Todo *todo = static_cast<Todo*>(incidence);
02555     QDateTime due = todo->dtDue();
02556     due.setDate( dt );
02557 
02558     todo->setDtDue( due );
02559     todo->setHasDueDate( true );
02560   }
02561 
02562   QPair<ResourceCalendar *, QString>p = viewSubResourceCalendar();
02563 
02564   if ( !mChanger->addIncidence( incidence, p.first, p.second, this ) ) {
02565     KODialogManager::errorSaveIncidence( this, incidence );
02566     delete incidence;
02567   }
02568 }
02569 
02570 void CalendarView::moveIncidenceTo( Incidence *incmove, const QDate &dt )
02571 {
02572   if ( !incmove || !mChanger ) {
02573     KMessageBox::sorry( this, i18n("Unable to move the item to %1.")
02574                         .arg( dt.toString() ), i18n("Moving Failed") );
02575     return;
02576   }
02577   Incidence *incidence = mCalendar->incidence( incmove->uid() );
02578   if ( !incidence ) {
02579     addIncidenceOn( incidence, dt );
02580     return;
02581   }
02582 
02583   Incidence *oldIncidence = incidence->clone();
02584   QPair<ResourceCalendar *, QString>p = viewSubResourceCalendar();
02585 
02586   if ( !mChanger->beginChange( incidence, p.first, p.second ) ) {
02587     delete oldIncidence;
02588     return;
02589   }
02590 
02591   if ( incidence->type() == "Event" ) {
02592     Event *event = static_cast<Event*>(incidence);
02593 
02594     // Adjust date
02595     QDateTime start = event->dtStart();
02596     QDateTime end = event->dtEnd();
02597 
02598     int duration = start.daysTo( end );
02599     start.setDate( dt );
02600     end.setDate( dt.addDays( duration ) );
02601 
02602     event->setDtStart( start );
02603     event->setDtEnd( end );
02604 
02605   } else if ( incidence->type() == "Todo" ) {
02606     Todo *todo = static_cast<Todo*>(incidence);
02607     QDateTime due = todo->dtDue();
02608     due.setDate( dt );
02609 
02610     todo->setDtDue( due );
02611     todo->setHasDueDate( true );
02612   }
02613   mChanger->changeIncidence( oldIncidence, incidence, KOGlobals::DATE_MODIFIED,this );
02614   mChanger->endChange( incidence, p.first, p.second );
02615   delete oldIncidence;
02616 }
02617 
02618 void CalendarView::resourcesChanged()
02619 {
02620   mViewManager->resourcesChanged();
02621   mDateNavigatorContainer->setUpdateNeeded();
02622   updateView();
02623 }
02624 
02625 Incidence* CalendarView::singleOccurrenceOrAll( Incidence *inc,
02626                                                 KOGlobals::OccurrenceAction userAction,
02627                                                 KOGlobals::WhichOccurrences &chosenOption,
02628                                                 const QDate &itemDate,
02629                                                 const bool commitToCalendar )
02630 {
02631 
02632   // temporary, until recurring to-dos are fixed
02633   if ( inc->type() != "Event" ) {
02634     chosenOption = KOGlobals::ALL;
02635     return inc;
02636   }
02637 
02638   Incidence *incToReturn = 0;
02639   Incidence *incSaved = 0;
02640   KOGlobals::WhatChanged whatChanged;
02641 
02642   bool dissociationOccurred = false;
02643   const QDate &dt = itemDate.isValid() ? itemDate : activeIncidenceDate();
02644 
02645   QString dialogTitle;
02646   QString dialogText;
02647 
02648   if ( userAction == KOGlobals::CUT ) {
02649     dialogTitle = i18n( "Cutting Recurring Item" );
02650 
02651     dialogText = i18n("The item you try to cut is a recurring item. Do you want to cut "
02652                        "only this single occurrence, only future items, "
02653                        "or all items in the recurrence?");
02654 
02655   } else if ( userAction == KOGlobals::COPY ) {
02656     dialogTitle = i18n( "Copying Recurring Item" );
02657 
02658     dialogText = i18n("The item you try to copy is a recurring item. Do you want to copy "
02659                        "only this single occurrence, only future items, "
02660                        "or all items in the recurrence?");
02661   } else {
02662     dialogTitle = i18n( "Changing Recurring Item" );
02663 
02664     dialogText = i18n( "The item you try to change is a recurring item. Shall the changes "
02665                        "be applied only to this single occurrence, only to the future items, "
02666                        "or to all items in the recurrence?" );
02667   }
02668 
02669   int res = KOMessageBox::fourBtnMsgBox( this, QMessageBox::Question,
02670             dialogText,
02671             dialogTitle,
02672             i18n("Only &This Item"), i18n("Only &Future Items"), i18n("&All Occurrences") );
02673   switch ( res ) {
02674     case KMessageBox::Ok: // All occurrences
02675       incToReturn = inc;
02676       chosenOption = KOGlobals::ALL;
02677       break;
02678     case KMessageBox::Yes: { // Just this occurrence
02679       // Dissociate this occurrence:
02680       // create clone of event, set relation to old event, set cloned event
02681       // for mActionItem, add exception date to old event, changeIncidence
02682       // for the old event, remove the recurrence from the new copy and then just
02683       // go on with the newly adjusted mActionItem and let the usual code take
02684       // care of the new time!
02685 
02686       chosenOption = KOGlobals::ONLY_THIS_ONE;
02687       whatChanged  = KOGlobals::RECURRENCE_MODIFIED_ONE_ONLY;
02688       startMultiModify( i18n("Dissociate event from recurrence") );
02689       incSaved = inc->clone();
02690       incToReturn = mCalendar->dissociateOccurrence( inc, dt );
02691       if ( incToReturn ) {
02692         dissociationOccurred = true;
02693       } else {
02694         KMessageBox::sorry( this, i18n("Unable to add the exception item to the "
02695             "calendar. No change will be done."), i18n("Error Occurred") );
02696         incToReturn = 0;
02697       }
02698 
02699       break; }
02700     case KMessageBox::No/*Future*/: { // All future occurrences
02701       // Dissociate this occurrence:
02702       // create clone of event, set relation to old event, set cloned event
02703       // for mActionItem, add recurrence end date to old event, changeIncidence
02704       // for the old event, adjust the recurrence for the new copy and then just
02705       // go on with the newly adjusted mActionItem and let the usual code take
02706       // care of the new time!
02707       chosenOption = KOGlobals::ONLY_FUTURE;
02708       whatChanged  = KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE;
02709       startMultiModify( i18n("Split future recurrences") );
02710       incSaved = inc->clone();
02711       incToReturn = mCalendar->dissociateOccurrence( inc, dt, false );
02712       if ( incToReturn ) {
02713         dissociationOccurred = true;
02714       } else {
02715         KMessageBox::sorry( this, i18n("Unable to add the future items to the "
02716             "calendar. No change will be done."), i18n("Error Occurred") );
02717 
02718         incToReturn = 0;
02719       }
02720 
02721       break; }
02722     default:
02723       chosenOption = KOGlobals::NONE;
02724   }
02725 
02726   if ( dissociationOccurred && commitToCalendar ) {
02727     QPair<ResourceCalendar *, QString>p = viewSubResourceCalendar();
02728     mChanger->addIncidence( incToReturn, p.first, p.second, this );
02729     mChanger->changeIncidence( incSaved, inc, whatChanged, this );
02730   }
02731 
02732   return incToReturn;
02733 }
02734 
02735 void CalendarView::selectWeek( const QDate &date )
02736 {
02737   if ( KOPrefs::instance()->mWeekNumbersShowWork    &&
02738        mViewManager->agendaIsSelected()             &&
02739        mViewManager->agendaMode()  == KOViewManager::AGENDA_WORK_WEEK ) {
02740     mDateNavigator->selectWorkWeek( date );
02741   } else {
02742     mDateNavigator->selectWeek( date );
02743   }
02744 }
02745 
02746 void CalendarView::getIncidenceHierarchy( Incidence *inc,
02747                                           Incidence::List &children )
02748 {
02749   // protecion against looping hierarchies
02750   if ( inc && !children.contains( inc ) ) {
02751     Incidence::List::ConstIterator it;
02752     Incidence::List immediateChildren = inc->relations();
02753     for ( it = immediateChildren.constBegin(); it != immediateChildren.constEnd(); ++it ) {
02754       getIncidenceHierarchy( *it, children );
02755     }
02756     children.append( inc );
02757   }
02758 }
02759 
02760 #include "calendarview.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys