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   QTime time( -1, -1 );// create an invalid time, that's what we want
00955   QDateTime endDT;     // null datetimes are invalid, that's what we want
00956   bool useEndTime = false;
00957 
00958   KOrg::BaseView *curView = mViewManager->currentView();
00959   if ( !curView ) {
00960     return;
00961   }
00962 
00963   KOAgendaView *aView = mViewManager->agendaView();
00964   KOMonthView *mView = mViewManager->monthView();
00965   if ( curView == mViewManager->multiAgendaView() ) {
00966     aView = mViewManager->multiAgendaView()->selectedAgendaView();
00967     curView = aView;
00968   }
00969 
00970   if ( curView == aView && aView->selectionStart().isValid() ) {
00971     date = aView->selectionStart().date();
00972     endDT = aView->selectionEnd();
00973     useEndTime = !aView->selectedIsSingleCell();
00974     if ( !aView->selectedIsAllDay() ) {
00975       time = aView->selectionStart().time();
00976     }
00977   } else if ( curView == mView && mView->selectionStart().isValid() ) {
00978     date = mView->selectionStart().date();
00979   } else if ( !mDateNavigator->selectedDates().isEmpty() &&
00980               curView->supportsDateNavigation() ) {
00981     // default to the selected date from the navigator
00982     date = mDateNavigator->selectedDates().first();
00983   }
00984 
00985   if ( !date.isValid() && curView->supportsDateNavigation() ) {
00986     KMessageBox::sorry(
00987       this,
00988       i18n( "Paste failed: unable to determine a valid target date." ) );
00989     return;
00990   }
00991 
00992   DndFactory factory( mCalendar );
00993   Incidence *pastedIncidence;
00994   if ( time.isValid() ) {
00995     pastedIncidence = factory.pasteIncidence( date, &time );
00996   } else {
00997     pastedIncidence = factory.pasteIncidence( date );
00998   }
00999   if ( !pastedIncidence ) {
01000     return;
01001   }
01002 
01003   QPair<ResourceCalendar *, QString>p = viewSubResourceCalendar();
01004 
01005   // FIXME: use a visitor here
01006   if ( pastedIncidence->type() == "Event" ) {
01007     Event *pastedEvent = static_cast<Event*>( pastedIncidence );
01008     // only use selected area if event is of the same type
01009     // (all-day or non-all-day) as the current selection is
01010     if ( aView && endDT.isValid() && useEndTime ) {
01011       if ( ( pastedEvent->doesFloat() && aView->selectedIsAllDay() ) ||
01012            ( !pastedEvent->doesFloat() && !aView->selectedIsAllDay() ) ) {
01013         pastedEvent->setDtEnd( endDT );
01014       }
01015     }
01016     mChanger->addIncidence( pastedEvent, p.first, p.second, this );
01017 
01018   } else if ( pastedIncidence->type() == "Todo" ) {
01019     Todo *pastedTodo = static_cast<Todo*>( pastedIncidence );
01020     Todo *_selectedTodo = selectedTodo();
01021     if ( _selectedTodo ) {
01022       pastedTodo->setRelatedTo( _selectedTodo );
01023     }
01024     mChanger->addIncidence( pastedTodo, p.first, p.second, this );
01025   }
01026 }
01027 
01028 void CalendarView::edit_options()
01029 {
01030   mDialogManager->showOptionsDialog();
01031 }
01032 
01033 void CalendarView::dateTimesForNewEvent( QDateTime &startDt, QDateTime &endDt, bool &allDay )
01034 {
01035   mViewManager->currentView()->eventDurationHint( startDt, endDt, allDay );
01036 
01037   if ( !startDt.isValid() || !endDt.isValid() ) {
01038     startDt.setDate( activeDate( true ) );
01039     startDt.setTime( KOPrefs::instance()->mStartTime.time() );
01040 
01041     int addSecs = ( KOPrefs::instance()->mDefaultDuration.time().hour() * 3600 ) +
01042                   ( KOPrefs::instance()->mDefaultDuration.time().minute() * 60 );
01043 
01044     endDt = startDt.addSecs( addSecs );
01045   }
01046 }
01047 
01048 KOEventEditor *CalendarView::newEventEditor( ResourceCalendar *res, const QString &subRes,
01049                                              const QDateTime &startDtParam,
01050                                              const QDateTime &endDtParam, bool allDayParam )
01051 {
01052   // let the current view change the default start/end datetime
01053   bool allDay = allDayParam;
01054   QDateTime startDt( startDtParam ), endDt( endDtParam );
01055   // Adjust the start/end date times (i.e. replace invalid values by defaults,
01056   // and let the view adjust the type.
01057   dateTimesForNewEvent( startDt, endDt, allDay );
01058 
01059   KOEventEditor *eventEditor = mDialogManager->getEventEditor();
01060   eventEditor->newEvent();
01061   connectIncidenceEditor( eventEditor );
01062   eventEditor->setResource( res, subRes );
01063   eventEditor->setDates( startDt, endDt, allDay );
01064   mDialogManager->connectTypeAhead( eventEditor, dynamic_cast<KOrg::AgendaView*>(viewManager()->currentView()) );
01065   return eventEditor;
01066 }
01067 
01068 void CalendarView::newEvent()
01069 {
01070   KOrg::BaseView *currentView = mViewManager->currentView();
01071   if ( currentView == mViewManager->multiAgendaView() ) {
01072     currentView = mViewManager->multiAgendaView()->selectedAgendaView();
01073   }
01074 
01075   newEvent( currentView->resourceCalendar(),
01076             currentView->subResourceCalendar() );
01077 }
01078 
01079 void CalendarView::newEvent( ResourceCalendar *res, const QString &subRes )
01080 {
01081   kdDebug(5850) << "CalendarView::newEvent()" << endl;
01082   newEvent( res, subRes, QDateTime(), QDateTime() );
01083 }
01084 
01085 void CalendarView::newEvent( ResourceCalendar *res, const QString &subRes,
01086                              const QDate &dt )
01087 {
01088   QDateTime startDt( dt, KOPrefs::instance()->mStartTime.time() );
01089   newEvent( res, subRes, QDateTime( dt ), QDateTime() );
01090 }
01091 
01092 void CalendarView::newEvent( ResourceCalendar *res, const QString &subRes,
01093                              const QDateTime &startDt )
01094 {
01095   newEvent( res, subRes, startDt, QDateTime() );
01096 }
01097 
01098 void CalendarView::newEvent( ResourceCalendar *res, const QString &subRes,
01099                              const QDateTime &startDt, const QDateTime &endDt,
01100                              bool allDay )
01101 {
01102   KOEventEditor *eventEditor = newEventEditor( res, subRes,
01103                                                startDt, endDt, allDay );
01104   eventEditor->show();
01105 }
01106 
01107 void CalendarView::newEvent( ResourceCalendar *res, const QString &subRes,
01108                              const QString &summary, const QString &description,
01109                              const QStringList &attachments, const QStringList &attendees,
01110                              const QStringList &attachmentMimetypes, bool inlineAttachment )
01111 {
01112   KOEventEditor *eventEditor = newEventEditor( res, subRes );
01113   eventEditor->setTexts( summary, description );
01114   // if attach or attendee list is empty, these methods don't do anything, so
01115   // it's safe to call them in every case
01116   eventEditor->addAttachments( attachments, attachmentMimetypes, inlineAttachment );
01117   eventEditor->addAttendees( attendees );
01118   eventEditor->show();
01119 }
01120 
01121 void CalendarView::newTodo( ResourceCalendar *res, const QString &subRes,
01122                             const QString &summary, const QString &description,
01123                             const QStringList &attachments, const QStringList &attendees,
01124                             const QStringList &attachmentMimetypes,
01125                             bool inlineAttachment, bool isTask )
01126 {
01127   kdDebug(5850) << k_funcinfo << endl;
01128   KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01129   connectIncidenceEditor( todoEditor );
01130   todoEditor->newTodo();
01131   todoEditor->setResource( res, subRes );
01132   todoEditor->setTexts( summary, description );
01133   todoEditor->addAttachments( attachments, attachmentMimetypes, inlineAttachment );
01134   todoEditor->addAttendees( attendees );
01135   todoEditor->selectCreateTask( isTask );
01136   todoEditor->show();
01137 }
01138 
01139 void CalendarView::newTodo()
01140 {
01141   KOrg::BaseView *currentView = mViewManager->currentView();
01142   if ( currentView == mViewManager->multiAgendaView() ) {
01143     currentView = mViewManager->multiAgendaView()->selectedAgendaView();
01144   }
01145 
01146   newTodo( currentView->resourceCalendar(),
01147            currentView->subResourceCalendar() );
01148 }
01149 
01150 void CalendarView::newTodo( ResourceCalendar *res, const QString &subRes )
01151 {
01152   kdDebug(5850) << k_funcinfo << endl;
01153   QDateTime dtDue;
01154   bool allday = true;
01155   KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01156   connectIncidenceEditor( todoEditor );
01157   todoEditor->newTodo();
01158   todoEditor->setResource( res, subRes );
01159   if ( mViewManager->currentView()->isEventView() ) {
01160     dtDue.setDate( mDateNavigator->selectedDates().first() );
01161     QDateTime dtDummy = QDateTime::currentDateTime();
01162     mViewManager->currentView()->eventDurationHint( dtDue, dtDummy, allday );
01163     todoEditor->setDates( dtDue, allday );
01164   }
01165   todoEditor->show();
01166 }
01167 
01168 void CalendarView::newTodo( ResourceCalendar *res, const QString &subRes,
01169                             const QDate &date )
01170 {
01171   KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01172   connectIncidenceEditor( todoEditor );
01173   todoEditor->newTodo();
01174   todoEditor->setResource( res, subRes );
01175   todoEditor->setDates( QDateTime( date, QTime::currentTime() ), true );
01176   todoEditor->show();
01177 }
01178 
01179 void CalendarView::newJournal()
01180 {
01181   KOrg::BaseView *currentView = mViewManager->currentView();
01182   if ( currentView == mViewManager->multiAgendaView() ) {
01183     currentView = mViewManager->multiAgendaView()->selectedAgendaView();
01184   }
01185 
01186   newJournal( currentView->resourceCalendar(),
01187               currentView->subResourceCalendar() );
01188 }
01189 
01190 void CalendarView::newJournal( ResourceCalendar *res, const QString &subRes )
01191 {
01192   kdDebug(5850) << "CalendarView::newJournal()" << endl;
01193   newJournal( res, subRes, QString::null, QDate() );
01194 }
01195 
01196 void CalendarView::newJournal( ResourceCalendar *res, const QString &subRes,
01197                                const QDate &date)
01198 {
01199   newJournal( res, subRes, QString::null, date );
01200 }
01201 
01202 void CalendarView::newJournal( ResourceCalendar *res, const QString &subRes,
01203                                const QString &text, const QDate &date )
01204 {
01205   KOJournalEditor *journalEditor = mDialogManager->getJournalEditor();
01206   connectIncidenceEditor( journalEditor );
01207   journalEditor->newJournal();
01208   journalEditor->setResource( res, subRes );
01209   journalEditor->setTexts( text );
01210   if ( !date.isValid() ) {
01211     journalEditor->setDate( mDateNavigator->selectedDates().first() );
01212   } else {
01213     journalEditor->setDate( date );
01214   }
01215   journalEditor->show();
01216 }
01217 
01218 void CalendarView::newSubTodo()
01219 {
01220   Todo *todo = selectedTodo();
01221   if ( todo ) newSubTodo( todo );
01222 }
01223 
01224 void CalendarView::newSubTodo(Todo *parentEvent)
01225 {
01226   KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01227   connectIncidenceEditor( todoEditor );
01228   todoEditor->newTodo();
01229   todoEditor->setDates( QDateTime(), false, parentEvent );
01230   todoEditor->show();
01231 }
01232 
01233 bool CalendarView::addIncidence( const QString &ical )
01234 {
01235   kdDebug(5850) << "CalendarView::addIncidence:\n" << ical << endl;
01236   ICalFormat format;
01237   format.setTimeZone( mCalendar->timeZoneId(), true );
01238   Incidence *incidence = format.fromString( ical );
01239   if ( !incidence ) return false;
01240   if ( !mChanger->addIncidence( incidence, 0, QString(), this ) ) {
01241     delete incidence;
01242     return false;
01243   }
01244   return true;
01245 }
01246 
01247 void CalendarView::appointment_show()
01248 {
01249   Incidence *incidence = selectedIncidence();
01250   if ( incidence ) {
01251     showIncidence( incidence, activeIncidenceDate() );
01252   } else {
01253     KNotifyClient::beep();
01254   }
01255 }
01256 
01257 void CalendarView::appointment_edit()
01258 {
01259   Incidence *incidence = selectedIncidence();
01260   if ( incidence ) {
01261     editIncidence( incidence, activeIncidenceDate() );
01262   } else {
01263     KNotifyClient::beep();
01264   }
01265 }
01266 
01267 void CalendarView::appointment_delete()
01268 {
01269   Incidence *incidence = selectedIncidence();
01270   if (incidence)
01271     deleteIncidence( incidence );
01272   else
01273     KNotifyClient::beep();
01274 }
01275 
01276 void CalendarView::todo_unsub()
01277 {
01278   Todo *anTodo = selectedTodo();
01279   if( todo_unsub (anTodo ) ) {
01280     updateView();
01281   }
01282 }
01283 
01284 bool CalendarView::todo_unsub( Todo *todo )
01285 {
01286   bool status= false;
01287   if ( !todo || !todo->relatedTo() ) return false;
01288 
01289   if ( mChanger->beginChange( todo, 0, QString() ) ) {
01290       Todo *oldTodo = todo->clone();
01291       todo->setRelatedTo(0);
01292       mChanger->changeIncidence( oldTodo, todo, KOGlobals::RELATION_MODIFIED, this );
01293       mChanger->endChange( todo, 0, QString() );
01294       delete oldTodo;
01295       setModified(true);
01296       status = true;
01297   }
01298   if ( ! status ) {
01299     KMessageBox::sorry( this, i18n("Unable to turn sub-to-do into a top-level "
01300         "to-do, because it cannot be locked.") );
01301   }
01302 
01303   return status;
01304 }
01305 
01306 bool CalendarView::makeSubTodosIndependents ( )
01307 {
01308   bool  status = false;
01309   Todo *anTodo = selectedTodo();
01310 
01311   if( makeSubTodosIndependents( anTodo ) ) {
01312     updateView();
01313     status = true;
01314   }
01315   return status;
01316 }
01317 
01318 bool CalendarView::makeSubTodosIndependents ( Todo *todo )
01319 {
01320   if( !todo || todo->relations().isEmpty() ) return false;
01321 
01322   startMultiModify ( i18n( "Make sub-to-dos independent" ) );
01323   Incidence::List subTodos( todo->relations() );
01324   Incidence::List::Iterator it;
01325   Incidence *aIncidence;
01326   Todo *aTodo;
01327 
01328   for ( it= subTodos.begin(); it != subTodos.end(); ++it ) {
01329     aIncidence = *it;
01330     if( aIncidence && aIncidence->type() == "Todo" ) {
01331       aTodo = static_cast<Todo*>( aIncidence );
01332       todo_unsub ( aTodo );
01333     }
01334   }
01335   endMultiModify();
01336   return true;
01337 }
01338 
01339 bool CalendarView::deleteIncidence( const QString &uid, bool force )
01340 {
01341   Incidence *inc = mCalendar->incidence( uid );
01342   if ( inc ) {
01343     deleteIncidence( inc, force );
01344     return true;
01345   } else {
01346     return false;
01347   }
01348 }
01349 
01350 void CalendarView::toggleAlarm( Incidence *incidence )
01351 {
01352   if ( !incidence || !mChanger ) {
01353     kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01354     return;
01355   }
01356   Incidence*oldincidence = incidence->clone();
01357   if ( !mChanger->beginChange( incidence, 0, QString() ) ) {
01358     kdDebug(5850) << "Unable to lock incidence " << endl;
01359     delete oldincidence;
01360     return;
01361   }
01362 
01363   Alarm::List alarms = incidence->alarms();
01364   Alarm::List::ConstIterator it;
01365   for( it = alarms.begin(); it != alarms.end(); ++it )
01366     (*it)->toggleAlarm();
01367   if (alarms.isEmpty()) {
01368     // Add an alarm if it didn't have one
01369     Alarm*alm = incidence->newAlarm();
01370     alm->setEnabled(true);
01371   }
01372   mChanger->changeIncidence( oldincidence, incidence, KOGlobals::ALARM_MODIFIED, this );
01373   mChanger->endChange( incidence, 0, QString() );
01374   delete oldincidence;
01375 
01376 //  mClickedItem->updateIcons();
01377 }
01378 
01379 void CalendarView::dissociateOccurrence( Incidence *incidence, const QDate &date )
01380 {
01381   if ( !incidence || !mChanger ) {
01382     kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01383     return;
01384   }
01385 
01386   QPair<ResourceCalendar *, QString>p =
01387     CalHelper::incSubResourceCalendar( calendar(), incidence );
01388 
01389   if ( !mChanger->beginChange( incidence, p.first, p.second ) ) {
01390     kdDebug(5850) << "Unable to lock incidence " << endl;
01391     return;
01392   }
01393   startMultiModify( i18n("Dissociate occurrence") );
01394   Incidence*oldincidence = incidence->clone();
01395 
01396   Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true );
01397 
01398   if ( newInc ) {
01399     mChanger->changeIncidence( oldincidence, incidence, KOGlobals::NOTHING_MODIFIED, this );
01400     mChanger->addIncidence( newInc, p.first, p.second, this );
01401   } else {
01402     KMessageBox::sorry( this, i18n("Dissociating the occurrence failed."),
01403       i18n("Dissociating Failed") );
01404   }
01405   mChanger->endChange( incidence, p.first, p.second );
01406   endMultiModify();
01407   delete oldincidence;
01408 }
01409 
01410 void CalendarView::dissociateFutureOccurrence( Incidence *incidence, const QDate &date )
01411 {
01412   if ( !incidence || !mChanger ) {
01413     kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01414     return;
01415   }
01416 
01417   QPair<ResourceCalendar *, QString>p =
01418     CalHelper::incSubResourceCalendar( calendar(), incidence );
01419 
01420   if ( !mChanger->beginChange( incidence, p.first, p.second ) ) {
01421     kdDebug(5850) << "Unable to lock incidence " << endl;
01422     return;
01423   }
01424   startMultiModify( i18n("Dissociate future occurrences") );
01425   Incidence*oldincidence = incidence->clone();
01426 
01427   Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true );
01428   if ( newInc ) {
01429     mChanger->changeIncidence( oldincidence, incidence, KOGlobals::NOTHING_MODIFIED, this );
01430     mChanger->addIncidence( newInc, p.first, p.second, this );
01431   } else {
01432     KMessageBox::sorry( this, i18n("Dissociating the future occurrences failed."),
01433       i18n("Dissociating Failed") );
01434   }
01435   endMultiModify();
01436   mChanger->endChange( incidence, p.first, p.second );
01437   delete oldincidence;
01438 }
01439 
01440 
01441 /*****************************************************************************/
01442 
01443 
01444 void CalendarView::schedule_publish(Incidence *incidence)
01445 {
01446   if (incidence == 0)
01447     incidence = selectedIncidence();
01448 
01449   if (!incidence) {
01450     KMessageBox::information( this, i18n("No item selected."),
01451                               "PublishNoEventSelected" );
01452     return;
01453   }
01454 
01455   PublishDialog *publishdlg = new PublishDialog();
01456   if (incidence->attendeeCount()>0) {
01457     Attendee::List attendees = incidence->attendees();
01458     Attendee::List::ConstIterator it;
01459     for( it = attendees.begin(); it != attendees.end(); ++it ) {
01460       publishdlg->addAttendee( *it );
01461     }
01462   }
01463   if ( publishdlg->exec() == QDialog::Accepted ) {
01464     Incidence *inc = incidence->clone();
01465     inc->registerObserver( 0 );
01466     inc->clearAttendees();
01467 
01468     // Send the mail
01469     KCal::MailScheduler scheduler( mCalendar );
01470     if ( scheduler.publish( incidence, publishdlg->addresses() ) ) {
01471       KMessageBox::information( this, i18n("The item information was successfully sent."),
01472                                 i18n("Publishing"), "IncidencePublishSuccess" );
01473     } else {
01474       KMessageBox::error( this, i18n("Unable to publish the item '%1'").arg( incidence->summary() ) );
01475     }
01476   }
01477   delete publishdlg;
01478 }
01479 
01480 void CalendarView::schedule_request(Incidence *incidence)
01481 {
01482   schedule(Scheduler::Request,incidence);
01483 }
01484 
01485 void CalendarView::schedule_refresh(Incidence *incidence)
01486 {
01487   schedule(Scheduler::Refresh,incidence);
01488 }
01489 
01490 void CalendarView::schedule_cancel(Incidence *incidence)
01491 {
01492   schedule(Scheduler::Cancel,incidence);
01493 }
01494 
01495 void CalendarView::schedule_add(Incidence *incidence)
01496 {
01497   schedule(Scheduler::Add,incidence);
01498 }
01499 
01500 void CalendarView::schedule_reply(Incidence *incidence)
01501 {
01502   schedule(Scheduler::Reply,incidence);
01503 }
01504 
01505 void CalendarView::schedule_counter(Incidence *incidence)
01506 {
01507   schedule(Scheduler::Counter,incidence);
01508 }
01509 
01510 void CalendarView::schedule_declinecounter(Incidence *incidence)
01511 {
01512   schedule(Scheduler::Declinecounter,incidence);
01513 }
01514 
01515 void CalendarView::schedule_forward( Incidence *incidence )
01516 {
01517   if ( !incidence ) {
01518     incidence = selectedIncidence();
01519   }
01520 
01521   if ( !incidence ) {
01522     KMessageBox::information(
01523       this,
01524       i18n( "No item selected." ),
01525       i18n( "Forwarding" ),
01526       "ForwardNoEventSelected" );
01527     return;
01528   }
01529 
01530   PublishDialog publishdlg;
01531   if ( publishdlg.exec() == QDialog::Accepted ) {
01532     QString recipients = publishdlg.addresses();
01533     if ( incidence->organizer().isEmpty() ) {
01534       incidence->setOrganizer( Person( KOPrefs::instance()->fullName(),
01535                                        KOPrefs::instance()->email() ) );
01536     }
01537 
01538     ICalFormat format;
01539     QString messageText = format.createScheduleMessage( incidence, Scheduler::Request );
01540     KOMailClient mailer;
01541     if ( mailer.mailTo( incidence, recipients, messageText ) ) {
01542       KMessageBox::information(
01543         this,
01544         i18n( "The item information was successfully sent." ),
01545         i18n( "Forwarding" ),
01546         "IncidenceForwardSuccess" );
01547     } else {
01548       KMessageBox::error(
01549         this,
01550         i18n( "Unable to forward the item '%1'" ).arg( incidence->summary() ),
01551         i18n( "Forwarding Error" ) );
01552     }
01553   }
01554 }
01555 
01556 void CalendarView::mailFreeBusy( int daysToPublish )
01557 {
01558   QDateTime start = QDateTime::currentDateTime();
01559   QDateTime end = start.addDays(daysToPublish);
01560 
01561   FreeBusy *freebusy = new FreeBusy(mCalendar, start, end);
01562   freebusy->setOrganizer( Person( KOPrefs::instance()->fullName(),
01563                       KOPrefs::instance()->email() ) );
01564 
01565   kdDebug(5850) << "calendarview: schedule_publish_freebusy: startDate: "
01566      << KGlobal::locale()->formatDateTime( start ) << " End Date: "
01567      << KGlobal::locale()->formatDateTime( end ) << endl;
01568 
01569   PublishDialog *publishdlg = new PublishDialog();
01570   if ( publishdlg->exec() == QDialog::Accepted ) {
01571     // Send the mail
01572     KCal::MailScheduler scheduler( mCalendar );
01573     if ( scheduler.publish( freebusy, publishdlg->addresses() ) ) {
01574       KMessageBox::information( this, i18n("The free/busy information was successfully sent."),
01575                                 i18n("Sending Free/Busy"), "FreeBusyPublishSuccess" );
01576     } else {
01577       KMessageBox::error( this, i18n("Unable to publish the free/busy data.") );
01578     }
01579   }
01580   delete freebusy;
01581   delete publishdlg;
01582 }
01583 
01584 void CalendarView::uploadFreeBusy()
01585 {
01586   KOGroupware::instance()->freeBusyManager()->publishFreeBusy();
01587 }
01588 
01589 void CalendarView::schedule(Scheduler::Method method, Incidence *incidence)
01590 {
01591   if ( !incidence ) {
01592     incidence = selectedIncidence();
01593   }
01594 
01595   if ( !incidence ) {
01596     KMessageBox::sorry( this, i18n("No item selected."),
01597                         "ScheduleNoEventSelected" );
01598     return;
01599   }
01600 
01601   if( incidence->attendeeCount() == 0 && method != Scheduler::Publish ) {
01602     KMessageBox::information( this, i18n("The item has no attendees."),
01603                               "ScheduleNoIncidences" );
01604     return;
01605   }
01606 
01607   Incidence *inc = incidence->clone();
01608   inc->registerObserver( 0 );
01609   inc->clearAttendees();
01610 
01611   // Send the mail
01612   KCal::MailScheduler scheduler( mCalendar );
01613   if ( scheduler.performTransaction( incidence, method ) ) {
01614     KMessageBox::information( this, i18n("The groupware message for item '%1'"
01615                                 "was successfully sent.\nMethod: %2")
01616                                 .arg( incidence->summary() )
01617                                 .arg( Scheduler::methodName( method ) ),
01618                               i18n("Sending Free/Busy"),
01619                               "FreeBusyPublishSuccess" );
01620   } else {
01621     KMessageBox::error( this, i18n("Groupware message sending failed. "
01622                         "%2 is request/reply/add/cancel/counter/etc.",
01623                         "Unable to send the item '%1'.\nMethod: %2")
01624                         .arg( incidence->summary() )
01625                         .arg( Scheduler::methodName( method ) ) );
01626   }
01627 }
01628 
01629 void CalendarView::openAddressbook()
01630 {
01631   KRun::runCommand("kaddressbook");
01632 }
01633 
01634 void CalendarView::setModified(bool modified)
01635 {
01636   if (mModified != modified) {
01637     mModified = modified;
01638     emit modifiedChanged(mModified);
01639   }
01640 }
01641 
01642 bool CalendarView::isReadOnly()
01643 {
01644   return mReadOnly;
01645 }
01646 
01647 void CalendarView::setReadOnly(bool readOnly)
01648 {
01649   if (mReadOnly != readOnly) {
01650     mReadOnly = readOnly;
01651     emit readOnlyChanged(mReadOnly);
01652   }
01653 }
01654 
01655 bool CalendarView::isModified()
01656 {
01657   return mModified;
01658 }
01659 
01660 void CalendarView::print()
01661 {
01662 #ifndef KORG_NOPRINTER
01663   KOCoreHelper helper;
01664   CalPrinter printer( this, mCalendar, &helper );
01665   connect( this, SIGNAL(configChanged()), &printer, SLOT(updateConfig()) );
01666 
01667   KOrg::BaseView *currentView = mViewManager->currentView();
01668 
01669   CalPrinterBase::PrintType printType = CalPrinterBase::Month;
01670   if ( currentView ) printType = currentView->printType();
01671 
01672   DateList tmpDateList = mDateNavigator->selectedDates();
01673   Incidence::List selectedIncidences;
01674   if ( mViewManager->currentView() ) {
01675     selectedIncidences = mViewManager->currentView()->selectedIncidences();
01676   }
01677   printer.print( printType, tmpDateList.first(), tmpDateList.last(), selectedIncidences );
01678 #endif
01679 }
01680 
01681 void CalendarView::exportWeb()
01682 {
01683   // FIXME: Get rid of the settings object. When can I delete it???
01684   HTMLExportSettings *settings = new HTMLExportSettings( "KOrganizer" );
01685   // Manually read in the config, because parametrized kconfigxt objects don't
01686   // seem to load the config theirselves
01687   if ( settings ) settings->readConfig();
01688   ExportWebDialog *dlg = new ExportWebDialog( settings, this );
01689   connect( dlg,  SIGNAL( exportHTML( HTMLExportSettings* ) ),
01690            this, SIGNAL( exportHTML( HTMLExportSettings* ) ) );
01691   dlg->show();
01692 }
01693 
01694 void CalendarView::exportICalendar()
01695 {
01696   QString filename = KFileDialog::getSaveFileName("icalout.ics",i18n("*.ics|ICalendars"),this);
01697   if ( !filename.isEmpty() )
01698   {
01699     // Force correct extension
01700     if (filename.right(4) != ".ics") filename += ".ics";
01701     if ( QFile( filename ).exists() ) {
01702       if ( KMessageBox::No == KMessageBox::warningYesNo(
01703              this,
01704              i18n( "Do you want to overwrite %1?").arg(filename) ) ) {
01705           return;
01706       }
01707     }
01708     FileStorage storage( mCalendar, filename, new ICalFormat );
01709     storage.save();
01710   }
01711 }
01712 
01713 void CalendarView::exportVCalendar()
01714 {
01715   if (mCalendar->journals().count() > 0) {
01716     int result = KMessageBox::warningContinueCancel(this,
01717         i18n("The journal entries can not be exported to a vCalendar file."),
01718         i18n("Data Loss Warning"),i18n("Proceed"),"dontaskVCalExport",
01719         true);
01720     if (result != KMessageBox::Continue) return;
01721   }
01722 
01723   QString filename = KFileDialog::getSaveFileName("vcalout.vcs",i18n("*.vcs|vCalendars"),this);
01724   if ( !filename.isEmpty() )
01725   {
01726     // TODO: I don't like forcing extensions:
01727     // Force correct extension
01728     if (filename.right(4) != ".vcs") filename += ".vcs";
01729     if ( QFile( filename ).exists() ) {
01730       if ( KMessageBox::No == KMessageBox::warningYesNo(
01731              this,
01732              i18n( "Do you want to overwrite %1?").arg(filename ) ) ) {
01733              return;
01734       }
01735     }
01736     FileStorage storage( mCalendar, filename, new VCalFormat );
01737     storage.save();
01738   }
01739 }
01740 
01741 void CalendarView::eventUpdated(Incidence *)
01742 {
01743   setModified();
01744   // Don't call updateView here. The code, which has caused the update of the
01745   // event is responsible for updating the view.
01746 //  updateView();
01747 }
01748 
01749 void CalendarView::adaptNavigationUnits()
01750 {
01751   if (mViewManager->currentView()->isEventView()) {
01752     int days = mViewManager->currentView()->currentDateCount();
01753     if (days == 1) {
01754       emit changeNavStringPrev(i18n("&Previous Day"));
01755       emit changeNavStringNext(i18n("&Next Day"));
01756     } else {
01757       emit changeNavStringPrev(i18n("&Previous Week"));
01758       emit changeNavStringNext(i18n("&Next Week"));
01759     }
01760   }
01761 }
01762 
01763 void CalendarView::processMainViewSelection( Incidence *incidence, const QDate &date )
01764 {
01765   if ( incidence ) mTodoList->clearSelection();
01766   processIncidenceSelection( incidence, date );
01767 }
01768 
01769 void CalendarView::processTodoListSelection( Incidence *incidence, const QDate &date )
01770 {
01771   if ( incidence && mViewManager->currentView() ) {
01772     mViewManager->currentView()->clearSelection();
01773   }
01774   processIncidenceSelection( incidence, date );
01775 }
01776 
01777 void CalendarView::processIncidenceSelection( Incidence *incidence, const QDate &date )
01778 {
01779   if ( incidence != mSelectedIncidence ) {
01780     // This signal also must be emitted if incidence is 0
01781     emit incidenceSelected( incidence, date );
01782   }
01783 
01784   if ( !incidence ) {
01785    mSelectedIncidence = incidence;
01786    return;
01787   }
01788   if ( incidence == mSelectedIncidence ) {
01789     if ( !incidence->doesRecur() || mSaveDate == date ) {
01790       return;
01791     }
01792   }
01793 
01794   mSelectedIncidence = incidence;
01795   mSaveDate = date;
01796 
01797   emit incidenceSelected( mSelectedIncidence, date );
01798   bool organizerEvents = false;
01799   bool groupEvents = false;
01800   bool todo = false;
01801   bool subtodo = false;
01802 
01803   organizerEvents = KOPrefs::instance()->thatIsMe( incidence->organizer().email() );
01804   groupEvents = incidence->attendeeByMails( KOPrefs::instance()->allEmails() );
01805 
01806   if ( incidence->type() == "Todo" ) {
01807     todo = true;
01808     subtodo = ( incidence->relatedTo() != 0 );
01809   }
01810 
01811   emit todoSelected( todo );
01812   emit subtodoSelected( subtodo );
01813   emit organizerEventsSelected( organizerEvents );
01814   emit groupEventsSelected( groupEvents );
01815 }
01816 
01817 
01818 void CalendarView::checkClipboard()
01819 {
01820 #ifndef KORG_NODND
01821   if (ICalDrag::canDecode(QApplication::clipboard()->data())) {
01822     kdDebug(5850) << "CalendarView::checkClipboard() true" << endl;
01823     emit pasteEnabled(true);
01824   } else {
01825     kdDebug(5850) << "CalendarView::checkClipboard() false" << endl;
01826     emit pasteEnabled(false);
01827   }
01828 #endif
01829 }
01830 
01831 void CalendarView::showDates(const DateList &selectedDates)
01832 {
01833 //  kdDebug(5850) << "CalendarView::selectDates()" << endl;
01834 
01835   if ( mViewManager->currentView() ) {
01836     updateView( selectedDates.first(), selectedDates.last() );
01837   } else {
01838     mViewManager->showAgendaView();
01839   }
01840 }
01841 
01842 void CalendarView::editFilters()
01843 {
01844   kdDebug(5850) << "CalendarView::editFilters()" << endl;
01845 
01846   CalFilter *filter = mFilters.first();
01847   while(filter) {
01848     kdDebug(5850) << " Filter: " << filter->name() << endl;
01849     filter = mFilters.next();
01850   }
01851 
01852   mDialogManager->showFilterEditDialog(&mFilters);
01853 }
01854 
01857 void CalendarView::updateFilter()
01858 {
01859   QStringList filters;
01860   CalFilter *filter;
01861 
01862   int pos = mFilters.find( mCurrentFilter );
01863   if ( pos < 0 ) {
01864     mCurrentFilter = 0;
01865   }
01866 
01867   filters << i18n("No filter");
01868   for ( filter = mFilters.first(); filter; filter = mFilters.next() ) {
01869     filters << filter->name();
01870   }
01871 
01872   emit newFilterListSignal( filters );
01873   // account for the additional "No filter" at the beginning! if the
01874   // filter is not in the list, pos == -1...
01875   emit selectFilterSignal( pos+1 );
01876   mCalendar->setFilter( mCurrentFilter );
01877   updateView();
01878 }
01879 
01882 void CalendarView::filterActivated( int filterNo )
01883 {
01884   CalFilter *newFilter = 0;
01885   if ( filterNo > 0 && filterNo <= int(mFilters.count()) ) {
01886     newFilter = mFilters.at( filterNo-1 );
01887   }
01888   if ( newFilter != mCurrentFilter ) {
01889     mCurrentFilter = newFilter;
01890     mCalendar->setFilter( mCurrentFilter );
01891     updateView();
01892   }
01893   emit filterChanged();
01894 }
01895 
01896 QString CalendarView::currentFilterName() const
01897 {
01898   if ( mCurrentFilter) {
01899     return mCurrentFilter->name();
01900   } else return i18n("No filter");
01901 }
01902 
01903 void CalendarView::takeOverEvent()
01904 {
01905   Incidence *incidence = currentSelection();
01906 
01907   if (!incidence) return;
01908 
01909   incidence->setOrganizer( Person( KOPrefs::instance()->fullName(),
01910                            KOPrefs::instance()->email() ) );
01911   incidence->recreate();
01912   incidence->setReadOnly(false);
01913 
01914   updateView();
01915 }
01916 
01917 void CalendarView::takeOverCalendar()
01918 {
01919   Incidence::List incidences = mCalendar->rawIncidences();
01920   Incidence::List::Iterator it;
01921 
01922   for ( it = incidences.begin(); it != incidences.end(); ++it ) {
01923     (*it)->setOrganizer( Person( KOPrefs::instance()->fullName(),
01924                          KOPrefs::instance()->email() ) );
01925     (*it)->recreate();
01926     (*it)->setReadOnly(false);
01927   }
01928   updateView();
01929 }
01930 
01931 void CalendarView::showIntro()
01932 {
01933   kdDebug(5850) << "To be implemented." << endl;
01934 }
01935 
01936 void CalendarView::showDateNavigator( bool show )
01937 {
01938   if( show )
01939     mDateNavigatorContainer->show();
01940   else
01941     mDateNavigatorContainer->hide();
01942 }
01943 
01944 void CalendarView::showTodoView( bool show )
01945 {
01946   if( show )
01947     mTodoList->show();
01948   else
01949     mTodoList->hide();
01950 }
01951 
01952 void CalendarView::showEventViewer( bool show )
01953 {
01954   if( show )
01955     mEventViewer->show();
01956   else
01957     mEventViewer->hide();
01958 }
01959 
01960 
01961 void CalendarView::addView(KOrg::BaseView *view)
01962 {
01963   mViewManager->addView(view);
01964 }
01965 
01966 void CalendarView::showView(KOrg::BaseView *view)
01967 {
01968   mViewManager->showView(view);
01969 }
01970 
01971 void CalendarView::addExtension( CalendarViewExtension::Factory *factory )
01972 {
01973   CalendarViewExtension *extension = factory->create( mLeftSplitter );
01974 
01975   mExtensions.append( extension );
01976 }
01977 
01978 void CalendarView::toggleExpand()
01979 {
01980   showLeftFrame( mLeftFrame->isHidden() );
01981 }
01982 
01983 void CalendarView::showLeftFrame(bool show)
01984 {
01985   if (show) {
01986     mLeftFrame->show();
01987     emit calendarViewExpanded( false );
01988   } else {
01989     mLeftFrame->hide();
01990     emit calendarViewExpanded( true );
01991   }
01992 }
01993 
01994 void CalendarView::calendarModified( bool modified, Calendar * )
01995 {
01996   setModified( modified );
01997 }
01998 
01999 Todo *CalendarView::selectedTodo()
02000 {
02001   Incidence *incidence = currentSelection();
02002   if ( incidence && incidence->type() == "Todo" ) {
02003     return static_cast<Todo *>( incidence );
02004   }
02005   incidence = 0;
02006 
02007   Incidence::List selectedIncidences = mTodoList->selectedIncidences();
02008   if ( !selectedIncidences.isEmpty() ) incidence = selectedIncidences.first();
02009   if ( incidence && incidence->type() == "Todo" ) {
02010     return static_cast<Todo *>( incidence );
02011   }
02012 
02013   return 0;
02014 }
02015 
02016 void CalendarView::dialogClosing( Incidence *in )
02017 {
02018   // FIXME: this doesn't work, because if it's a new incidence, it's not locked!
02019   mChanger->endChange( in, 0, QString() );
02020   mDialogList.remove( in );
02021 }
02022 
02023 Incidence *CalendarView::currentSelection()
02024 {
02025   return mViewManager->currentSelection();
02026 }
02027 
02028 Incidence* CalendarView::selectedIncidence()
02029 {
02030   Incidence *incidence = currentSelection();
02031   if ( !incidence ) {
02032     Incidence::List selectedIncidences = mTodoList->selectedIncidences();
02033     if ( !selectedIncidences.isEmpty() )
02034       incidence = selectedIncidences.first();
02035   }
02036   return incidence;
02037 }
02038 
02039 void CalendarView::showIncidence()
02040 {
02041   showIncidence( selectedIncidence(), activeIncidenceDate() );
02042 }
02043 
02044 void CalendarView::editIncidence()
02045 {
02046   editIncidence( selectedIncidence(), activeIncidenceDate() );
02047 }
02048 
02049 bool CalendarView::editIncidence( const QString &uid )
02050 {
02051   return editIncidence( mCalendar->incidence( uid ), QDate() );
02052 }
02053 
02054 bool CalendarView::editIncidence( const QString &uid, const QDate &date )
02055 {
02056   return editIncidence( mCalendar->incidence( uid ), date );
02057 }
02058 
02059 void CalendarView::deleteIncidence()
02060 {
02061   deleteIncidence( selectedIncidence() );
02062 }
02063 
02064 void CalendarView::cutIncidence(Incidence *)
02065 {
02066   edit_cut();
02067 }
02068 
02069 void CalendarView::copyIncidence(Incidence *)
02070 {
02071   edit_copy();
02072 }
02073 
02074 void CalendarView::pasteIncidence()
02075 {
02076   edit_paste();
02077 }
02078 
02079 void CalendarView::showIncidence( Incidence *incidence, const QDate &date )
02080 {
02081   KOEventViewerDialog *eventViewer = new KOEventViewerDialog( calendar(), this );
02082   eventViewer->setIncidence( incidence, date );
02083   eventViewer->show();
02084 }
02085 
02086 bool CalendarView::editIncidence( Incidence *incidence, const QDate &date, bool isCounter )
02087 {
02088   kdDebug(5850) << "CalendarView::editEvent()" << endl;
02089 
02090   CalendarResources *stdcal = dynamic_cast<CalendarResources *>( mCalendar );
02091   if( stdcal && !stdcal->hasCalendarResources() ) {
02092     KMessageBox::sorry(
02093       this,
02094       i18n( "No resources found. We can not edit the item." ) );
02095     return false;
02096   }
02097 
02098   // FIXME: This is a nasty hack, since we need to set a parent for the
02099   //        resource selection dialog. However, we don't have any UI methods
02100   //        in the calendar, only in the CalendarResources::DestinationPolicy
02101   //        So we need to type-cast it and extract it from the CalendarResources
02102   QWidget *tmpparent = 0;
02103   if ( stdcal ) {
02104     tmpparent = stdcal->dialogParentWidget();
02105     stdcal->setDialogParentWidget( this );
02106   }
02107 
02108   if ( !incidence ) {
02109     kdDebug(5850) << "Empty Incidence" << endl;
02110     KNotifyClient::beep();
02111     return false;
02112   }
02113 
02114   if ( !mChanger ) {
02115     kdDebug(5850) << "Empty Changer" << endl;
02116     KNotifyClient::beep();
02117     return false;
02118   }
02119 
02120   KOIncidenceEditor *tmp = editorDialog( incidence );
02121   if ( tmp ) {
02122     kdDebug(5850) << "CalendarView::editIncidence() in List" << endl;
02123     tmp->reload();
02124     tmp->raise();
02125     tmp->show();
02126     return true;
02127   }
02128 
02129   if ( incidence->isReadOnly() ) {
02130     showIncidence( incidence, date );
02131     return true;
02132   }
02133 
02134   QPair<ResourceCalendar *, QString>p =
02135     CalHelper::incSubResourceCalendar( calendar(), incidence );
02136 
02137   Incidence *savedIncidence = incidence->clone();
02138   Incidence *incToChange;
02139 
02140   if ( incidence->doesRecur() ) {
02141     KOGlobals::WhichOccurrences chosenOption;
02142     incToChange = singleOccurrenceOrAll( incidence, KOGlobals::EDIT, chosenOption, date );
02143   } else {
02144     incToChange = incidence;
02145   }
02146 
02147   // If the user pressed cancel incToChange is 0
02148   if ( incToChange ) {
02149     if ( !isCounter && !mChanger->beginChange( incToChange, p.first, p.second ) ) {
02150       warningChangeFailed( incToChange );
02151       showIncidence( incToChange, date );
02152 
02153       return false;
02154     }
02155 
02156     kdDebug(5850) << "CalendarView::editIncidence() new IncidenceEditor" << endl;
02157     KOIncidenceEditor *incidenceEditor = mDialogManager->getEditor( incToChange );
02158     connectIncidenceEditor( incidenceEditor );
02159 
02160     mDialogList.insert( incToChange, incidenceEditor );
02161     if ( incidence != incToChange ) {
02162       incidenceEditor->setRecurringIncidence( savedIncidence, incidence );
02163     }
02164     incidenceEditor->setResource( p.first, p.second );
02165     incidenceEditor->editIncidence( incToChange, date, mCalendar );
02166     incidenceEditor->show();
02167     return true;
02168   } else {
02169     return false;
02170   }
02171 }
02172 
02173 void CalendarView::deleteSubTodosIncidence ( Todo *todo )
02174 {
02175   if( !todo ) return;
02176 
02177   Incidence::List subTodos( todo->relations() );
02178   Incidence::List::Iterator it;
02179   Incidence *aIncidence;
02180   Todo *aTodo;
02181 
02182   for ( it= subTodos.begin(); it != subTodos.end(); ++it ) {
02183     aIncidence = *it;
02184     if( aIncidence && aIncidence->type() == "Todo" ) {
02185       aTodo = static_cast<Todo*>( aIncidence );
02186       deleteSubTodosIncidence ( aTodo );
02187     }
02188   }
02189   mChanger->deleteIncidence ( todo, this );
02190 }
02191 
02192 void CalendarView::deleteTodoIncidence ( Todo *todo, bool force )
02193 {
02194   if ( !todo ) return ;
02195 
02196   // it a simple todo, ask and delete it.
02197   if (todo->relations().isEmpty() ) {
02198     bool doDelete = true;
02199     if ( !force && KOPrefs::instance()->mConfirm ) {
02200       doDelete = ( msgItemDelete( todo ) == KMessageBox::Continue );
02201     }
02202     if ( doDelete )
02203       mChanger->deleteIncidence( todo, this );
02204     return;
02205   }
02206 
02207   /* Ok, this to-do has sub-to-dos, ask what to do */
02208   int km = KMessageBox::No;
02209   if ( !force ) {
02210     km = KMessageBox::questionYesNoCancel(
02211       this,
02212       i18n("The item \"%1\" has sub-to-dos. "
02213            "Do you want to delete just this item and "
02214            "make all its sub-to-dos independent, or "
02215            "delete the to-do with all its sub-to-dos?"
02216         ).arg( todo->summary() ),
02217       i18n("KOrganizer Confirmation"),
02218       i18n("Delete Only This"),
02219       i18n("Delete All"));
02220   }
02221   startMultiModify( i18n("Deleting sub-to-dos" ) );
02222   // Delete only the father
02223   if( km == KMessageBox::Yes ) {
02224 
02225     makeSubTodosIndependents ( todo );
02226     mChanger->deleteIncidence( todo, this );
02227   } else if ( km == KMessageBox::No ) {
02228     // Delete all
02229     // we have to hide the delete confirmation for each itemDate
02230     deleteSubTodosIncidence ( todo );
02231   }
02232   endMultiModify();
02233 }
02234 
02235 void CalendarView::deleteIncidence(Incidence *incidence, bool force)
02236 {
02237   if ( !incidence || !mChanger ) {
02238     if ( !force ) {
02239       KNotifyClient::beep();
02240     }
02241     return;
02242   }
02243   if ( incidence->isReadOnly() ) {
02244     if ( !force ) {
02245       KMessageBox::information( this, i18n("The item \"%1\" is marked read-only "
02246                                 "and cannot be deleted; it probably belongs to "
02247                                 "a read-only calendar resource.")
02248                                 .arg(incidence->summary()),
02249                                 i18n("Removing not possible"),
02250                                 "deleteReadOnlyIncidence" );
02251     }
02252     return;
02253   }
02254 
02255   CanDeleteIncidenceVisitor v;
02256 
02257   // Let the visitor do special things for special incidence types.
02258   // e.g. todos with children cannot be deleted, so act(..) returns false
02259   if ( !v.act( incidence, this ) )
02260     return;
02261   //If it is a todo, there are specific delete function
02262 
02263   if ( incidence && incidence->type()=="Todo" ) {
02264     deleteTodoIncidence( static_cast<Todo*>(incidence), force );
02265     return;
02266   }
02267 
02268   if ( incidence->doesRecur() ) {
02269     QDate itemDate = mViewManager->currentSelectionDate();
02270     kdDebug(5850) << "Recurrence-Date: " << itemDate.toString() << endl;
02271     int km = KMessageBox::Ok;
02272     if ( !force ) {
02273       if ( !itemDate.isValid() ) {
02274         kdDebug(5850) << "Date Not Valid" << endl;
02275         km = KMessageBox::warningContinueCancel(this,
02276           i18n("The calendar item \"%1\" recurs over multiple dates; "
02277                "are you sure you want to delete it "
02278                "and all its recurrences?").arg( incidence->summary() ),
02279                i18n("KOrganizer Confirmation"), i18n("Delete All") );
02280       } else {
02281         km = KOMessageBox::fourBtnMsgBox( this, QMessageBox::Warning,
02282           i18n("The calendar item \"%1\" recurs over multiple dates. "
02283                "Do you want to delete only the current one on %2, only all "
02284                "future recurrences, or all its recurrences?" )
02285                .arg( incidence->summary() )
02286                .arg( KGlobal::locale()->formatDate(itemDate)),
02287                i18n("KOrganizer Confirmation"), i18n("Delete C&urrent"),
02288                i18n("Delete &Future"),
02289                i18n("Delete &All"));
02290       }
02291     }
02292 
02293     QPair<ResourceCalendar *, QString>p =
02294       CalHelper::incSubResourceCalendar( calendar(), incidence );
02295 
02296     switch(km) {
02297       case KMessageBox::Ok: // Continue // all
02298       case KMessageBox::Continue:
02299         mChanger->deleteIncidence( incidence, this );
02300         break;
02301 
02302       case KMessageBox::Yes: // just this one
02303         if ( mChanger->beginChange( incidence, p.first, p.second ) ) {
02304           Incidence *oldIncidence = incidence->clone();
02305           incidence->recurrence()->addExDate( itemDate );
02306           mChanger->changeIncidence( oldIncidence, incidence,
02307                                      KOGlobals::RECURRENCE_MODIFIED_ONE_ONLY, this );
02308           mChanger->endChange( incidence, p.first, p.second );
02309           delete oldIncidence;
02310         }
02311         break;
02312       case KMessageBox::No: // all future items
02313         if ( mChanger->beginChange( incidence, p.first, p.second ) ) {
02314           Incidence *oldIncidence = incidence->clone();
02315           Recurrence *recur = incidence->recurrence();
02316           recur->setEndDate( itemDate.addDays(-1) );
02317           mChanger->changeIncidence( oldIncidence, incidence,
02318                                      KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE,  this );
02319           mChanger->endChange( incidence, p.first, p.second );
02320           delete oldIncidence;
02321         }
02322         break;
02323     }
02324   } else {
02325     bool doDelete = true;
02326     if ( !force && KOPrefs::instance()->mConfirm ) {
02327       doDelete = ( msgItemDelete( incidence ) == KMessageBox::Continue );
02328     }
02329     if ( doDelete ) {
02330       mChanger->deleteIncidence( incidence, this );
02331       processIncidenceSelection( 0, QDate() );
02332     }
02333   }
02334 }
02335 
02336 void CalendarView::connectIncidenceEditor( KOIncidenceEditor *editor )
02337 {
02338   connect( this, SIGNAL( newIncidenceChanger( IncidenceChangerBase* ) ),
02339            editor, SLOT( setIncidenceChanger( IncidenceChangerBase* ) ) );
02340   editor->setIncidenceChanger( mChanger );
02341 }
02342 
02343 bool CalendarView::purgeCompletedSubTodos( Todo* todo, bool &allPurged )
02344 {
02345   if ( !todo ) return true;
02346   bool deleteThisTodo = true;
02347   Incidence::List subTodos( todo->relations() );
02348   Incidence *aIncidence;
02349   Todo *aTodo;
02350   Incidence::List::Iterator it;
02351   for ( it = subTodos.begin(); it != subTodos.end(); ++it ) {
02352     aIncidence = *it;
02353     if ( aIncidence && aIncidence->type()=="Todo" ) {
02354       aTodo = static_cast<Todo*>( aIncidence );
02355       deleteThisTodo &= purgeCompletedSubTodos( aTodo, allPurged );
02356     }
02357   }
02358 
02359   if ( deleteThisTodo ) {
02360     if ( todo->isCompleted() ) {
02361       if ( !mChanger->deleteIncidence( todo, this ) )
02362         allPurged = false;
02363     } else {
02364       deleteThisTodo = false;
02365     }
02366   } else {
02367     if ( todo->isCompleted() ) {
02368       allPurged = false;
02369     }
02370   }
02371   return deleteThisTodo;
02372 }
02373 
02374 void CalendarView::purgeCompleted()
02375 {
02376   int result = KMessageBox::warningContinueCancel(this,
02377       i18n("Delete all completed to-dos?"),i18n("Purge To-dos"),i18n("Purge"));
02378 
02379   if (result == KMessageBox::Continue) {
02380     bool allDeleted = true;
02381     startMultiModify( i18n("Purging completed to-dos") );
02382     Todo::List todos = calendar()->rawTodos();
02383     Todo::List rootTodos;
02384     Todo::List::ConstIterator it;
02385     for ( it = todos.begin(); it != todos.end(); ++it ) {
02386       Todo *aTodo = *it;
02387       if ( aTodo && !aTodo->relatedTo() )
02388         rootTodos.append( aTodo );
02389     }
02390     // now that we have a list of all root todos, check them and their children
02391     for ( it = rootTodos.begin(); it != rootTodos.end(); ++it ) {
02392       purgeCompletedSubTodos( *it, allDeleted );
02393     }
02394     endMultiModify();
02395     if ( !allDeleted ) {
02396       KMessageBox::information( this, i18n("Unable to purge to-dos with "
02397                                 "uncompleted children."), i18n("Delete To-do"),
02398                                 "UncompletedChildrenPurgeTodos" );
02399     }
02400   }
02401 }
02402 
02403 void CalendarView::warningChangeFailed( Incidence *incidence )
02404 {
02405   if ( incidence ) {
02406     KMessageBox::sorry(
02407       this,
02408       i18n( "Unable to edit \"%1\" because it is locked by another process." ).
02409       arg( incidence->summary() ) );
02410   }
02411 }
02412 
02413 void CalendarView::editCanceled( Incidence *incidence )
02414 {
02415   mCalendar->endChange( incidence );
02416 }
02417 
02418 void CalendarView::showErrorMessage( const QString &msg )
02419 {
02420   KMessageBox::error( this, msg );
02421 }
02422 
02423 void CalendarView::updateCategories()
02424 {
02425   QStringList allCats( calendar()->categories() );
02426   allCats.sort();
02427   QStringList categories( KOPrefs::instance()->mCustomCategories );
02428   for ( QStringList::ConstIterator si = allCats.constBegin(); si != allCats.constEnd(); ++si ) {
02429     if ( categories.find( *si ) == categories.end() ) {
02430       categories.append( *si );
02431     }
02432   }
02433   KOPrefs::instance()->mCustomCategories = categories;
02434   KOPrefs::instance()->writeConfig();
02435   // Make the category editor update the list!
02436   emit categoriesChanged();
02437 }
02438 
02439 void CalendarView::addIncidenceOn( Incidence *incadd, const QDate &dt )
02440 {
02441   if ( !incadd || !mChanger ) {
02442     KMessageBox::sorry(this, i18n("Unable to copy the item to %1.")
02443                        .arg( dt.toString() ), i18n("Copying Failed") );
02444     return;
02445   }
02446   Incidence *incidence = mCalendar->incidence( incadd->uid() );
02447   if ( !incidence ) incidence = incadd;
02448   // Create a copy of the incidence, since the incadd doesn't belong to us.
02449   incidence = incidence->clone();
02450   incidence->recreate();
02451 
02452   if ( incidence->type() == "Event" ) {
02453     Event *event = static_cast<Event*>(incidence);
02454 
02455     // Adjust date
02456     QDateTime start = event->dtStart();
02457     QDateTime end = event->dtEnd();
02458 
02459     int duration = start.daysTo( end );
02460     start.setDate( dt );
02461     end.setDate( dt.addDays( duration ) );
02462 
02463     event->setDtStart( start );
02464     event->setDtEnd( end );
02465 
02466   } else if ( incidence->type() == "Todo" ) {
02467     Todo *todo = static_cast<Todo*>(incidence);
02468     QDateTime due = todo->dtDue();
02469     due.setDate( dt );
02470 
02471     todo->setDtDue( due );
02472     todo->setHasDueDate( true );
02473   }
02474 
02475   QPair<ResourceCalendar *, QString>p = viewSubResourceCalendar();
02476 
02477   if ( !mChanger->addIncidence( incidence, p.first, p.second, this ) ) {
02478     KODialogManager::errorSaveIncidence( this, incidence );
02479     delete incidence;
02480   }
02481 }
02482 
02483 void CalendarView::moveIncidenceTo( Incidence *incmove, const QDate &dt )
02484 {
02485   if ( !incmove || !mChanger ) {
02486     KMessageBox::sorry( this, i18n("Unable to move the item to %1.")
02487                         .arg( dt.toString() ), i18n("Moving Failed") );
02488     return;
02489   }
02490   Incidence *incidence = mCalendar->incidence( incmove->uid() );
02491   if ( !incidence ) {
02492     addIncidenceOn( incidence, dt );
02493     return;
02494   }
02495 
02496   Incidence *oldIncidence = incidence->clone();
02497   QPair<ResourceCalendar *, QString>p = viewSubResourceCalendar();
02498 
02499   if ( !mChanger->beginChange( incidence, p.first, p.second ) ) {
02500     delete oldIncidence;
02501     return;
02502   }
02503 
02504   if ( incidence->type() == "Event" ) {
02505     Event *event = static_cast<Event*>(incidence);
02506 
02507     // Adjust date
02508     QDateTime start = event->dtStart();
02509     QDateTime end = event->dtEnd();
02510 
02511     int duration = start.daysTo( end );
02512     start.setDate( dt );
02513     end.setDate( dt.addDays( duration ) );
02514 
02515     event->setDtStart( start );
02516     event->setDtEnd( end );
02517 
02518   } else if ( incidence->type() == "Todo" ) {
02519     Todo *todo = static_cast<Todo*>(incidence);
02520     QDateTime due = todo->dtDue();
02521     due.setDate( dt );
02522 
02523     todo->setDtDue( due );
02524     todo->setHasDueDate( true );
02525   }
02526   mChanger->changeIncidence( oldIncidence, incidence, KOGlobals::DATE_MODIFIED,this );
02527   mChanger->endChange( incidence, p.first, p.second );
02528   delete oldIncidence;
02529 }
02530 
02531 void CalendarView::resourcesChanged()
02532 {
02533   mViewManager->resourcesChanged();
02534   mDateNavigatorContainer->setUpdateNeeded();
02535   updateView();
02536 }
02537 
02538 Incidence* CalendarView::singleOccurrenceOrAll( Incidence *inc,
02539                                                 KOGlobals::OccurrenceAction userAction,
02540                                                 KOGlobals::WhichOccurrences &chosenOption,
02541                                                 const QDate &itemDate,
02542                                                 const bool commitToCalendar )
02543 {
02544 
02545   // temporary, until recurring to-dos are fixed
02546   if ( inc->type() != "Event" ) {
02547     chosenOption = KOGlobals::ALL;
02548     return inc;
02549   }
02550 
02551   Incidence *incToReturn = 0;
02552   Incidence *incSaved = 0;
02553   KOGlobals::WhatChanged whatChanged;
02554 
02555   bool dissociationOccurred = false;
02556   const QDate &dt = itemDate.isValid() ? itemDate : activeIncidenceDate();
02557 
02558   QString dialogTitle;
02559   QString dialogText;
02560 
02561   if ( userAction == KOGlobals::CUT ) {
02562     dialogTitle = i18n( "Cutting Recurring Item" );
02563 
02564     dialogText = i18n("The item you try to cut is a recurring item. Do you want to cut "
02565                        "only this single occurrence, only future items, "
02566                        "or all items in the recurrence?");
02567 
02568   } else if ( userAction == KOGlobals::COPY ) {
02569     dialogTitle = i18n( "Copying Recurring Item" );
02570 
02571     dialogText = i18n("The item you try to copy is a recurring item. Do you want to copy "
02572                        "only this single occurrence, only future items, "
02573                        "or all items in the recurrence?");
02574   } else {
02575     dialogTitle = i18n( "Changing Recurring Item" );
02576 
02577     dialogText = i18n( "The item you try to change is a recurring item. Shall the changes "
02578                        "be applied only to this single occurrence, only to the future items, "
02579                        "or to all items in the recurrence?" );
02580   }
02581 
02582   int res = KOMessageBox::fourBtnMsgBox( this, QMessageBox::Question,
02583             dialogText,
02584             dialogTitle,
02585             i18n("Only &This Item"), i18n("Only &Future Items"), i18n("&All Occurrences") );
02586   switch ( res ) {
02587     case KMessageBox::Ok: // All occurrences
02588       incToReturn = inc;
02589       chosenOption = KOGlobals::ALL;
02590       break;
02591     case KMessageBox::Yes: { // Just this occurrence
02592       // Dissociate this occurrence:
02593       // create clone of event, set relation to old event, set cloned event
02594       // for mActionItem, add exception date to old event, changeIncidence
02595       // for the old event, remove the recurrence from the new copy and then just
02596       // go on with the newly adjusted mActionItem and let the usual code take
02597       // care of the new time!
02598 
02599       chosenOption = KOGlobals::ONLY_THIS_ONE;
02600       whatChanged  = KOGlobals::RECURRENCE_MODIFIED_ONE_ONLY;
02601       startMultiModify( i18n("Dissociate event from recurrence") );
02602       incSaved = inc->clone();
02603       incToReturn = mCalendar->dissociateOccurrence( inc, dt );
02604       if ( incToReturn ) {
02605         dissociationOccurred = true;
02606       } else {
02607         KMessageBox::sorry( this, i18n("Unable to add the exception item to the "
02608             "calendar. No change will be done."), i18n("Error Occurred") );
02609         incToReturn = 0;
02610       }
02611 
02612       break; }
02613     case KMessageBox::No/*Future*/: { // All future occurrences
02614       // Dissociate this occurrence:
02615       // create clone of event, set relation to old event, set cloned event
02616       // for mActionItem, add recurrence end date to old event, changeIncidence
02617       // for the old event, adjust the recurrence for the new copy and then just
02618       // go on with the newly adjusted mActionItem and let the usual code take
02619       // care of the new time!
02620       chosenOption = KOGlobals::ONLY_FUTURE;
02621       whatChanged  = KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE;
02622       startMultiModify( i18n("Split future recurrences") );
02623       incSaved = inc->clone();
02624       incToReturn = mCalendar->dissociateOccurrence( inc, dt, false );
02625       if ( incToReturn ) {
02626         dissociationOccurred = true;
02627       } else {
02628         // por aqui controlo de erros
02629         KMessageBox::sorry( this, i18n("Unable to add the future items to the "
02630             "calendar. No change will be done."), i18n("Error Occurred") );
02631 
02632         incToReturn = 0;
02633       }
02634 
02635       break; }
02636     default:
02637       chosenOption = KOGlobals::NONE;
02638   }
02639 
02640   if ( dissociationOccurred && commitToCalendar ) {
02641     QPair<ResourceCalendar *, QString>p = viewSubResourceCalendar();
02642     mChanger->addIncidence( incToReturn, p.first, p.second, this );
02643     mChanger->changeIncidence( incSaved, inc, whatChanged, this );
02644   }
02645 
02646   return incToReturn;
02647 }
02648 
02649 void CalendarView::selectWeek( const QDate &date )
02650 {
02651   if ( KOPrefs::instance()->mWeekNumbersShowWork    &&
02652        mViewManager->agendaIsSelected()             &&
02653        mViewManager->agendaMode()  == KOViewManager::AGENDA_WORK_WEEK ) {
02654     mDateNavigator->selectWorkWeek( date );
02655   } else {
02656     mDateNavigator->selectWeek( date );
02657   }
02658 }
02659 
02660 #include "calendarview.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys