korganizer

calendarview.cpp

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