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/vcaldrag.h>
00069 #include <libkcal/icaldrag.h>
00070 #include <libkcal/icalformat.h>
00071 #include <libkcal/vcalformat.h>
00072 #include <libkcal/scheduler.h>
00073 #include <libkcal/calendarlocal.h>
00074 #include <libkcal/journal.h>
00075 #include <libkcal/calfilter.h>
00076 #include <libkcal/attendee.h>
00077 #include <libkcal/dndfactory.h>
00078 #include <libkcal/freebusy.h>
00079 #include <libkcal/filestorage.h>
00080 #include <libkcal/calendarresources.h>
00081 #include <libkcal/calendarnull.h>
00082 #include <libkcal/htmlexportsettings.h>
00083 
00084 #include <kglobal.h>
00085 #include <kdebug.h>
00086 #include <kstandarddirs.h>
00087 #include <kfiledialog.h>
00088 #include <kmessagebox.h>
00089 #include <knotifyclient.h>
00090 #include <kconfig.h>
00091 #include <krun.h>
00092 #include <kdirwatch.h>
00093 
00094 #include <qapplication.h>
00095 #include <qclipboard.h>
00096 #include <qcursor.h>
00097 #include <qmultilineedit.h>
00098 #include <qtimer.h>
00099 #include <qwidgetstack.h>
00100 #include <qptrlist.h>
00101 #include <qfile.h>
00102 #include <qlayout.h>
00103 #ifndef KORG_NOSPLITTER
00104 #include <qsplitter.h>
00105 #endif
00106 #include <qvbox.h>
00107 #include <qwhatsthis.h>
00108 
00109 #include <stdlib.h>
00110 #include <assert.h>
00111 
00112 using namespace KOrg;
00113 
00114 CalendarView::CalendarView( QWidget *parent, const char *name )
00115   : CalendarViewBase( parent, name ),
00116     mHistory( 0 ),
00117     mCalendar( CalendarNull::self() ),
00118     mChanger( 0 )
00119 {
00120   kdDebug(5850) << "CalendarView::CalendarView( Calendar )" << endl;
00121 
00122   mViewManager = new KOViewManager( this );
00123   mDialogManager = new KODialogManager( this );
00124 
00125   mModified = false;
00126   mReadOnly = false;
00127   mSelectedIncidence = 0;
00128 
00129   mFilters.setAutoDelete( true );
00130 
00131   mExtensions.setAutoDelete( true );
00132 
00133   mNavigator = new DateNavigator( this );
00134   mDateChecker = new DateChecker( this );
00135 
00136   QBoxLayout *topLayout = new QVBoxLayout( this );
00137 
00138 #ifndef KORG_NOSPLITTER
00139   // create the main layout frames.
00140   mPanner = new QSplitter( QSplitter::Horizontal, this,
00141                            "CalendarView::Panner" );
00142   topLayout->addWidget( mPanner );
00143 
00144   mLeftSplitter = new QSplitter( QSplitter::Vertical, mPanner,
00145                                  "CalendarView::LeftFrame" );
00146 //  mPanner->setResizeMode( mLeftSplitter, QSplitter::Stretch );
00147 
00148   mDateNavigator = new DateNavigatorContainer( mLeftSplitter,
00149                                                "CalendarView::DateNavigator" );
00150 
00151 //  mLeftSplitter->setResizeMode( mDateNavigator, QSplitter::Stretch );
00152   mLeftSplitter->setCollapsible( mDateNavigator, true );
00153   mTodoList = new KOTodoView( CalendarNull::self(), mLeftSplitter, "todolist" );
00154 
00155   mEventViewer = new KOEventViewer( mLeftSplitter,"EventViewer" );
00156 
00157   QVBox *rightBox = new QVBox( mPanner );
00158   mNavigatorBar = new NavigatorBar( rightBox );
00159   mRightFrame = new QWidgetStack( rightBox );
00160   rightBox->setStretchFactor( mRightFrame, 1 );
00161 
00162   mLeftFrame = mLeftSplitter;
00163 #else
00164   QWidget *mainBox;
00165   QWidget *leftFrame;
00166 
00167   if ( KOPrefs::instance()->mVerticalScreen ) {
00168     mainBox = new QVBox( this );
00169     leftFrame = new QHBox( mainBox );
00170   } else {
00171     mainBox = new QHBox( this );
00172     leftFrame = new QVBox( mainBox );
00173   }
00174 
00175   topLayout->addWidget( mainBox );
00176 
00177   mDateNavigator = new KDateNavigator( leftFrame, true,
00178                                        "CalendarView::DateNavigator",
00179                                        QDate::currentDate() );
00180   mTodoList = new KOTodoView( CalendarNull::self(), leftFrame, "todolist" );
00181 
00182   mEventViewer = new KOEventViewer ( leftFrame, "EventViewer" );
00183 
00184   QWidget *rightBox = new QWidget( mainBox );
00185   QBoxLayout *rightLayout = new QVBoxLayout( rightBox );
00186 
00187   mNavigatorBar = new NavigatorBar( QDate::currentDate(), rightBox );
00188   rightLayout->addWidget( mNavigatorBar );
00189 
00190   mRightFrame = new QWidgetStack( rightBox );
00191   rightLayout->addWidget( mRightFrame );
00192 
00193   mLeftFrame = leftFrame;
00194 
00195   if ( KOPrefs::instance()->mVerticalScreen ) {
00196 //    mTodoList->setFixedHeight( 60 );
00197     mTodoList->setFixedHeight( mDateNavigator->sizeHint().height() );
00198   }
00199 #endif
00200 
00201   connect( mNavigator, SIGNAL( datesSelected( const KCal::DateList & ) ),
00202            SLOT( showDates( const KCal::DateList & ) ) );
00203   connect( mNavigator, SIGNAL( datesSelected( const KCal::DateList & ) ),
00204            mDateNavigator, SLOT( selectDates( const KCal::DateList & ) ) );
00205 
00206   connect( mNavigatorBar, SIGNAL( goPrevYear() ),
00207            mNavigator, SLOT( selectPreviousYear() ) );
00208   connect( mNavigatorBar, SIGNAL( goNextYear() ),
00209            mNavigator, SLOT( selectNextYear() ) );
00210   connect( mNavigatorBar, SIGNAL( goPrevMonth() ),
00211            mNavigator, SLOT( selectPreviousMonth() ) );
00212   connect( mNavigatorBar, SIGNAL( goNextMonth() ),
00213            mNavigator, SLOT( selectNextMonth() ) );
00214   connect( mNavigatorBar, SIGNAL( goMonth(int) ),
00215            mNavigator, SLOT( selectMonth(int) ) );
00216 
00217   connect( mNavigator, SIGNAL( datesSelected( const KCal::DateList & ) ),
00218            mNavigatorBar, SLOT( selectDates( const KCal::DateList & ) ) );
00219 
00220   connect( mDateNavigator, SIGNAL( weekClicked( const QDate & ) ),
00221            mNavigator, SLOT( selectWeek( const QDate & ) ) );
00222 
00223   connect( mDateNavigator, SIGNAL( goPrevYear() ),
00224            mNavigator, SLOT( selectPreviousYear() ) );
00225   connect( mDateNavigator, SIGNAL( goNextYear() ),
00226            mNavigator, SLOT( selectNextYear() ) );
00227   connect( mDateNavigator, SIGNAL( goPrevMonth() ),
00228            mNavigator, SLOT( selectPreviousMonth() ) );
00229   connect( mDateNavigator, SIGNAL( goNextMonth() ),
00230            mNavigator, SLOT( selectNextMonth() ) );
00231   connect( mDateNavigator, SIGNAL( goMonth(int) ),
00232            mNavigator, SLOT( selectMonth(int) ) );
00233 
00234   connect( mDateNavigator, SIGNAL( goPrevious() ),
00235            mNavigator, SLOT( selectPrevious() ) );
00236   connect( mDateNavigator, SIGNAL( goNext() ),
00237            mNavigator, SLOT( selectNext() ) );
00238 
00239   connect( mDateNavigator, SIGNAL( datesSelected( const KCal::DateList & ) ),
00240            mNavigator, SLOT( selectDates( const KCal::DateList & ) ) );
00241 
00242   connect( mDateNavigator, SIGNAL(incidenceDropped(Incidence*, const QDate&)),
00243            SLOT( addIncidenceOn( Incidence *, const QDate & ) ) );
00244   connect( mDateNavigator, SIGNAL(incidenceDroppedMove(Incidence*,const QDate&)),
00245            SLOT( moveIncidenceTo( Incidence *, const QDate & ) ) );
00246 
00247   connect( mDateChecker, SIGNAL( dayPassed( const QDate & ) ),
00248            mTodoList, SLOT( dayPassed( const QDate & ) ) );
00249   connect( mDateChecker, SIGNAL( dayPassed( const QDate & ) ),
00250            SIGNAL( dayPassed( const QDate & ) ) );
00251   connect( mDateChecker, SIGNAL( dayPassed( const QDate & ) ),
00252            mDateNavigator, SLOT( updateToday() ) );
00253 
00254   connect( this, SIGNAL( configChanged() ),
00255            mDateNavigator, SLOT( updateConfig() ) );
00256 
00257   connect( this, SIGNAL( incidenceSelected(Incidence *) ),
00258            mEventViewer, SLOT ( setIncidence (Incidence *) ) );
00259 
00260   //TODO: do a pretty Summary,
00261   QString s;
00262   s = i18n( "<p><em>No Item Selected</em></p>"
00263            "<p>Select an event, to-do or journal entry to view its details "
00264            "here.</p>");
00265 
00266   mEventViewer->setDefaultText( s );
00267   QWhatsThis::add( mEventViewer,
00268                    i18n( "View the details of events, journal entries or to-dos "
00269                          "selected in KOrganizer's main view here." ) );
00270   mEventViewer->setIncidence( 0 );
00271 
00272   mViewManager->connectTodoView( mTodoList );
00273   mViewManager->connectView( mTodoList );
00274 
00275   KOGlobals::self()->
00276       setHolidays( new KHolidays( KOPrefs::instance()->mHolidays ) );
00277 
00278   connect( QApplication::clipboard(), SIGNAL( dataChanged() ),
00279            SLOT( checkClipboard() ) );
00280 
00281   connect( mTodoList, SIGNAL( incidenceSelected( Incidence * ) ),
00282            SLOT( processTodoListSelection( Incidence * ) ) );
00283   disconnect( mTodoList, SIGNAL( incidenceSelected( Incidence * ) ),
00284            this, SLOT( processMainViewSelection( Incidence * ) ) );
00285 
00286   kdDebug(5850) << "CalendarView::CalendarView() done" << endl;
00287 }
00288 
00289 CalendarView::~CalendarView()
00290 {
00291   kdDebug(5850) << "~CalendarView()" << endl;
00292 
00293   mCalendar->unregisterObserver( this );
00294 
00295   delete mDialogManager;
00296   delete mViewManager;
00297   delete mEventViewer;
00298   kdDebug(5850) << "~CalendarView() done" << endl;
00299 }
00300 
00301 void CalendarView::setCalendar( Calendar *cal )
00302 {
00303   kdDebug(5850)<<"CalendarView::setCalendar"<<endl;
00304   mCalendar = cal;
00305 
00306   delete mHistory;
00307   mHistory = new History( mCalendar );
00308   connect( mHistory, SIGNAL( undone() ), SLOT( updateView() ) );
00309   connect( mHistory, SIGNAL( redone() ), SLOT( updateView() ) );
00310 
00311   if ( mChanger ) delete mChanger;
00312   setIncidenceChanger( new IncidenceChanger( mCalendar, this ) );
00313 
00314   mCalendar->registerObserver( this );
00315 
00316   mDateNavigator->setCalendar( mCalendar );
00317 
00318   mTodoList->setCalendar( mCalendar );
00319 }
00320 
00321 void CalendarView::setIncidenceChanger( IncidenceChangerBase *changer )
00322 {
00323   mChanger = changer;
00324   emit newIncidenceChanger( mChanger );
00325   connect( mChanger, SIGNAL( incidenceAdded( Incidence* ) ),
00326            this, SLOT( incidenceAdded( Incidence* ) ) );
00327   connect( mChanger, SIGNAL( incidenceChanged( Incidence*, Incidence*, int ) ),
00328            this, SLOT( incidenceChanged( Incidence*, Incidence*, int ) ) );
00329   connect( mChanger, SIGNAL( incidenceChanged( Incidence*, Incidence* ) ),
00330            this, SLOT( incidenceChanged( Incidence*, Incidence* ) ) );
00331   connect( mChanger, SIGNAL( incidenceToBeDeleted( Incidence * ) ),
00332            this, SLOT( incidenceToBeDeleted( Incidence * ) ) );
00333   connect( mChanger, SIGNAL( incidenceDeleted( Incidence * ) ),
00334            this, SLOT( incidenceDeleted( Incidence * ) ) );
00335 
00336   connect( mChanger, SIGNAL( schedule( Scheduler::Method, Incidence*) ),
00337            this, SLOT( schedule( Scheduler::Method, Incidence*) ) );
00338 
00339 
00340   connect( this, SIGNAL( cancelAttendees( Incidence * ) ),
00341            mChanger, SLOT( cancelAttendees( Incidence * ) ) );
00342 }
00343 
00344 Calendar *CalendarView::calendar()
00345 {
00346   if ( mCalendar ) return mCalendar;
00347   else return CalendarNull::self();
00348 }
00349 
00350 KOIncidenceEditor *CalendarView::editorDialog( Incidence *incidence ) const
00351 {
00352   if (mDialogList.find(incidence) != mDialogList.end ())
00353     return mDialogList[incidence];
00354   else return 0;
00355 }
00356 
00357 QDate CalendarView::startDate()
00358 {
00359   DateList dates = mNavigator->selectedDates();
00360 
00361   return dates.first();
00362 }
00363 
00364 QDate CalendarView::endDate()
00365 {
00366   DateList dates = mNavigator->selectedDates();
00367 
00368   return dates.last();
00369 }
00370 
00371 
00372 bool CalendarView::openCalendar(const QString& filename, bool merge)
00373 {
00374   kdDebug(5850) << "CalendarView::openCalendar(): " << filename << endl;
00375 
00376   if (filename.isEmpty()) {
00377     kdDebug(5850) << "CalendarView::openCalendar(): Error! Empty filename." << endl;
00378     return false;
00379   }
00380 
00381   if (!QFile::exists(filename)) {
00382     kdDebug(5850) << "CalendarView::openCalendar(): Error! File '" << filename
00383               << "' doesn't exist." << endl;
00384   }
00385 
00386   bool loadedSuccesfully = true;
00387   if ( !merge ) {
00388     mCalendar->close();
00389     CalendarLocal *cl = dynamic_cast<CalendarLocal*>( mCalendar );
00390     if ( cl ) {
00391       loadedSuccesfully = cl->load( filename );
00392     } else {
00393       CalendarResources *cr = dynamic_cast<CalendarResources*>( mCalendar );
00394       assert( cr ); // otherwise something is majorly wrong
00395       // openCalendar called without merge and a filename, what should we do?
00396       return false;
00397     }
00398   } else {
00399     // merge in a file
00400     FileStorage storage( mCalendar );
00401     storage.setFileName( filename );
00402     loadedSuccesfully = storage.load();
00403   }
00404 
00405   if ( loadedSuccesfully ) {
00406     if ( merge )
00407       setModified( true );
00408     else {
00409       setModified( false );
00410       mViewManager->setDocumentId( filename );
00411       mTodoList->setDocumentId( filename );
00412     }
00413     updateCategories();
00414     updateView();
00415     return true;
00416   } else {
00417     // while failing to load, the calendar object could
00418     // have become partially populated.  Clear it out.
00419     if ( !merge ) mCalendar->close();
00420 
00421     KMessageBox::error(this,i18n("Could not load calendar '%1'.").arg(filename));
00422 
00423     return false;
00424   }
00425 }
00426 
00427 bool CalendarView::saveCalendar( const QString& filename )
00428 {
00429   kdDebug(5850) << "CalendarView::saveCalendar(): " << filename << endl;
00430 
00431   // Store back all unsaved data into calendar object
00432   mViewManager->currentView()->flushView();
00433 
00434   FileStorage storage( mCalendar );
00435   storage.setFileName( filename );
00436   storage.setSaveFormat( new ICalFormat );
00437 
00438   bool success = storage.save();
00439 
00440   if ( !success ) {
00441     return false;
00442   }
00443 
00444   return true;
00445 }
00446 
00447 void CalendarView::closeCalendar()
00448 {
00449   kdDebug(5850) << "CalendarView::closeCalendar()" << endl;
00450 
00451   // child windows no longer valid
00452   emit closingDown();
00453 
00454   mCalendar->close();
00455   setModified( false );
00456   updateView();
00457 }
00458 
00459 void CalendarView::archiveCalendar()
00460 {
00461   mDialogManager->showArchiveDialog();
00462 }
00463 
00464 
00465 void CalendarView::readSettings()
00466 {
00467 //  kdDebug(5850) << "CalendarView::readSettings()" << endl;
00468 
00469   QString str;
00470 
00471   // read settings from the KConfig, supplying reasonable
00472   // defaults where none are to be found
00473 
00474   KConfig *config = KOGlobals::self()->config();
00475 
00476 #ifndef KORG_NOSPLITTER
00477   config->setGroup( "KOrganizer Geometry" );
00478 
00479   QValueList<int> sizes = config->readIntListEntry( "Separator1" );
00480   if ( sizes.count() != 2 ) {
00481     sizes << mDateNavigator->minimumSizeHint().width();
00482     sizes << 300;
00483   }
00484   mPanner->setSizes( sizes );
00485 
00486   sizes = config->readIntListEntry( "Separator2" );
00487   mLeftSplitter->setSizes( sizes );
00488 #endif
00489 
00490   mEventViewer->readSettings( config );
00491 
00492   mViewManager->readSettings( config );
00493   mTodoList->restoreLayout( config, QString( "Todo Layout" ) );
00494 
00495   readFilterSettings( config );
00496 
00497   config->setGroup( "Views" );
00498   int dateCount = config->readNumEntry( "ShownDatesCount", 7 );
00499   if ( dateCount == 7 ) mNavigator->selectWeek();
00500   else mNavigator->selectDates( mNavigator->selectedDates().first(), dateCount );
00501 }
00502 
00503 
00504 void CalendarView::writeSettings()
00505 {
00506 //  kdDebug(5850) << "CalendarView::writeSettings" << endl;
00507 
00508   KConfig *config = KOGlobals::self()->config();
00509 
00510 #ifndef KORG_NOSPLITTER
00511   config->setGroup( "KOrganizer Geometry" );
00512 
00513   QValueList<int> list = mPanner->sizes();
00514   config->writeEntry( "Separator1", list );
00515 
00516   list = mLeftSplitter->sizes();
00517   config->writeEntry( "Separator2", list );
00518 #endif
00519   mEventViewer->writeSettings( config );
00520   mViewManager->writeSettings( config );
00521   mTodoList->saveLayout( config, QString( "Todo Layout" ) );
00522 
00523   KOPrefs::instance()->writeConfig();
00524 
00525   writeFilterSettings( config );
00526 
00527   config->setGroup( "Views" );
00528   config->writeEntry( "ShownDatesCount", mNavigator->selectedDates().count() );
00529 
00530   config->sync();
00531 }
00532 
00533 void CalendarView::readFilterSettings( KConfig *config )
00534 {
00535 //  kdDebug(5850) << "CalendarView::readFilterSettings()" << endl;
00536 
00537   mFilters.clear();
00538 
00539   config->setGroup( "General" );
00540   // FIXME: Move the filter loading and saving to the CalFilter class in libkcal
00541   QStringList filterList = config->readListEntry ("CalendarFilters" );
00542   QString currentFilter = config->readEntry( "Current Filter" );
00543 
00544   QStringList::ConstIterator it = filterList.begin();
00545   QStringList::ConstIterator end = filterList.end();
00546   while( it != end ) {
00547 //    kdDebug(5850) << "  filter: " << (*it) << endl;
00548     CalFilter *filter;
00549     filter = new CalFilter( *it );
00550     config->setGroup( "Filter_" + (*it) );
00551     filter->setCriteria( config->readNumEntry( "Criteria", 0 ) );
00552     filter->setCategoryList( config->readListEntry( "CategoryList" ) );
00553     if ( filter->criteria() & KCal::CalFilter::HideTodosWithoutAttendeeInEmailList )
00554       filter->setEmailList( KOPrefs::instance()->allEmails() );
00555     filter->setCompletedTimeSpan( config->readNumEntry( "HideTodoDays", 0 ) );
00556     mFilters.append( filter );
00557 
00558     ++it;
00559   }
00560 
00561   config->setGroup( "General" );
00562   int pos = filterList.findIndex( currentFilter );
00563   mCurrentFilter = 0;
00564   if ( pos>=0 ) {
00565     mCurrentFilter = mFilters.at( pos );
00566   }
00567   updateFilter();
00568 }
00569 
00570 void CalendarView::writeFilterSettings( KConfig *config )
00571 {
00572 //  kdDebug(5850) << "CalendarView::writeFilterSettings()" << endl;
00573 
00574   QStringList filterList;
00575 
00576   CalFilter *filter = mFilters.first();
00577   while( filter ) {
00578 //    kdDebug(5850) << " fn: " << filter->name() << endl;
00579     filterList << filter->name();
00580     config->setGroup( "Filter_" + filter->name() );
00581     config->writeEntry( "Criteria", filter->criteria() );
00582     config->writeEntry( "CategoryList", filter->categoryList() );
00583     config->writeEntry( "HideTodoDays", filter->completedTimeSpan() );
00584     filter = mFilters.next();
00585   }
00586   config->setGroup( "General" );
00587   config->writeEntry( "CalendarFilters", filterList );
00588   if ( mCurrentFilter ) {
00589     config->writeEntry( "Current Filter", mCurrentFilter->name() );
00590   } else {
00591     config->writeEntry( "Current Filter", QString::null );
00592   }
00593 }
00594 
00595 
00596 void CalendarView::goDate( const QDate& date )
00597 {
00598   mNavigator->selectDate( date );
00599 }
00600 
00601 void CalendarView::showDate(const QDate & date)
00602 {
00603   int dateCount = mNavigator->datesCount();
00604   if ( dateCount == 7 )
00605     mNavigator->selectWeek( date );
00606   else
00607     mNavigator->selectDates( date, dateCount );
00608 }
00609 
00610 void CalendarView::goToday()
00611 {
00612   mNavigator->selectToday();
00613 }
00614 
00615 void CalendarView::goNext()
00616 {
00617   if ( dynamic_cast<KOMonthView*>( mViewManager->currentView() ) )
00618     mNavigator->selectNextMonth();
00619   else
00620     mNavigator->selectNext();
00621 }
00622 
00623 void CalendarView::goPrevious()
00624 {
00625   if ( dynamic_cast<KOMonthView*>( mViewManager->currentView() ) )
00626     mNavigator->selectPreviousMonth();
00627   else
00628     mNavigator->selectPrevious();
00629 }
00630 
00631 void CalendarView::updateConfig( const QCString& receiver)
00632 {
00633   if ( receiver != "korganizer" ) return;
00634   kdDebug(5850) << "CalendarView::updateConfig()" << endl;
00635 
00636   KOGlobals::self()->
00637     setHolidays( new KHolidays( KOPrefs::instance()->mHolidays ) );
00638 
00639   QString tz(  mCalendar->timeZoneId() );
00640   // Only set a new time zone if it changed. This prevents the window
00641   // from being modified on start
00642   if ( tz != KOPrefs::instance()->mTimeZoneId ) {
00643 
00644     const QString question( i18n("The timezone setting was changed. Do you want to keep the absolute time of "
00645                                 "the items in your calendar, which will show them to be at a different time than "
00646                                 "before, or move them to be at the old time also in the new timezone?") );
00647     int rc = KMessageBox::questionYesNo( this, question,
00648                               i18n("Keep Absolute Times?"),
00649                               KGuiItem(i18n("Keep Times")),
00650                               KGuiItem(i18n("Move Times")),
00651                               "calendarKeepAbsoluteTimes");
00652     if ( rc == KMessageBox::Yes ) {
00653       // user wants us to shift
00654       mCalendar->setTimeZoneIdViewOnly( KOPrefs::instance()->mTimeZoneId );
00655     } else {
00656       // only set the new timezone, wihtout shifting events, they will be
00657       // interpreted as being in the new timezone now
00658       mCalendar->setTimeZoneId( KOPrefs::instance()->mTimeZoneId );
00659     }
00660   }
00661   emit configChanged();
00662 
00663   // force reload and handle agenda view type switch
00664   const bool showMerged = KOPrefs::instance()->agendaViewCalendarDisplay() == KOPrefs::CalendarsMerged;
00665   const bool showSideBySide = KOPrefs::instance()->agendaViewCalendarDisplay() == KOPrefs::CalendarsSideBySide;
00666   KOrg::BaseView *view = mViewManager->currentView();
00667   mViewManager->showAgendaView();
00668   if ( view == mViewManager->agendaView() && showSideBySide )
00669     view = mViewManager->multiAgendaView();
00670   else if ( view == mViewManager->multiAgendaView() && showMerged )
00671     view = mViewManager->agendaView();
00672   mViewManager->showView( view );
00673 
00674   // To make the "fill window" configurations work
00675   mViewManager->raiseCurrentView();
00676 }
00677 
00678 
00679 void CalendarView::incidenceAdded( Incidence *incidence )
00680 {
00681   setModified( true );
00682   history()->recordAdd( incidence );
00683   changeIncidenceDisplay( incidence, KOGlobals::INCIDENCEADDED );
00684   updateUnmanagedViews();
00685   checkForFilteredChange( incidence );
00686 }
00687 
00688 void CalendarView::incidenceChanged( Incidence *oldIncidence,
00689                                      Incidence *newIncidence )
00690 {
00691   incidenceChanged( oldIncidence, newIncidence, KOGlobals::UNKNOWN_MODIFIED );
00692 }
00693 
00694 void CalendarView::incidenceChanged( Incidence *oldIncidence,
00695                                      Incidence *newIncidence, int what )
00696 {
00697   // FIXME: Make use of the what flag, which indicates which parts of the incidence have changed!
00698   KOIncidenceEditor *tmp = editorDialog( newIncidence );
00699   if ( tmp ) {
00700     kdDebug(5850) << "Incidence modified and open" << endl;
00701     tmp->modified( what );
00702   }
00703   setModified( true );
00704   history()->recordEdit( oldIncidence, newIncidence );
00705 
00706   // Record completed todos in journals, if enabled. we should to this here in
00707   // favour of the todolist. users can mark a task as completed in an editor
00708   // as well.
00709   if ( newIncidence->type() == "Todo"
00710     && KOPrefs::instance()->recordTodosInJournals()
00711     &&  ( what == KOGlobals::COMPLETION_MODIFIED
00712     || what == KOGlobals::COMPLETION_MODIFIED_WITH_RECURRENCE ) ) {
00713 
00714       Todo *todo = static_cast<Todo *>(newIncidence);
00715       if ( todo->isCompleted()
00716       || what == KOGlobals::COMPLETION_MODIFIED_WITH_RECURRENCE ) {
00717         QString timeStr = KGlobal::locale()->formatTime( QTime::currentTime() );
00718         QString description = i18n( "To-do completed: %1 (%2)" ).arg(
00719           newIncidence->summary() ).arg( timeStr );
00720 
00721         Journal::List journals = calendar()->journals( QDate::currentDate() );
00722         Journal *journal;
00723 
00724         if ( journals.isEmpty() ) {
00725           journal = new Journal();
00726           journal->setDtStart( QDateTime::currentDateTime() );
00727 
00728           QString dateStr = KGlobal::locale()->formatDate( QDate::currentDate() );
00729           journal->setSummary( i18n("Journal of %1").arg( dateStr ) );
00730           journal->setDescription( description );
00731 
00732           if ( !mChanger->addIncidence( journal, this ) ) {
00733             KODialogManager::errorSaveIncidence( this, journal );
00734             delete journal;
00735             return;
00736           }
00737 
00738         } else { // journal list is not empty
00739           journal = *(journals.at(0));
00740           Journal *oldJournal = journal->clone();
00741           journal->setDescription( journal->description().append( "\n" + description ) );
00742 
00743           if ( !mChanger->changeIncidence( oldJournal, journal ) ) {
00744             KODialogManager::errorSaveIncidence( this, journal );
00745             delete journal;
00746             return;
00747           }
00748         }
00749       }
00750   }
00751 
00752   changeIncidenceDisplay( newIncidence, KOGlobals::INCIDENCEEDITED );
00753   updateUnmanagedViews();
00754   checkForFilteredChange( newIncidence );
00755 }
00756 
00757 void CalendarView::incidenceToBeDeleted( Incidence *incidence )
00758 {
00759   KOIncidenceEditor *tmp = editorDialog( incidence );
00760   if (tmp) {
00761     kdDebug(5850) << "Incidence to be deleted and open in editor" << endl;
00762     tmp->delayedDestruct();
00763   }
00764   setModified( true );
00765   history()->recordDelete( incidence );
00766 //  changeIncidenceDisplay( incidence, KOGlobals::INCIDENCEDELETED );
00767   updateUnmanagedViews();
00768 }
00769 
00770 void CalendarView::incidenceDeleted( Incidence *incidence )
00771 {
00772   changeIncidenceDisplay( incidence, KOGlobals::INCIDENCEDELETED );
00773   updateUnmanagedViews();
00774 }
00775 
00776 void CalendarView::checkForFilteredChange( Incidence *incidence )
00777 {
00778   CalFilter *filter = calendar()->filter();
00779   if ( filter && !filter->filterIncidence( incidence ) ) {
00780     // Incidence is filtered and thus not shown in the view, tell the
00781     // user so that he isn't surprised if his new event doesn't show up
00782     KMessageBox::information( this, i18n("The item \"%1\" is filtered by "
00783                  "your current filter rules, so it will be hidden and not "
00784                  "appear in the view.").arg( incidence->summary() ),
00785                  i18n("Filter Applied"), "ChangedIncidenceFiltered" );
00786   }
00787 }
00788 
00789 void CalendarView::startMultiModify( const QString &text )
00790 {
00791   history()->startMultiModify( text );
00792 }
00793 
00794 void CalendarView::endMultiModify()
00795 {
00796   history()->endMultiModify();
00797 }
00798 
00799 
00800 void CalendarView::changeIncidenceDisplay( Incidence *incidence, int action )
00801 {
00802   mDateNavigator->updateView();
00803   mDialogManager->updateSearchDialog();
00804 
00805   if ( incidence ) {
00806     // If there is an event view visible update the display
00807     mViewManager->currentView()->changeIncidenceDisplay( incidence, action );
00808     if ( mTodoList ) mTodoList->changeIncidenceDisplay( incidence, action );
00809     mEventViewer->changeIncidenceDisplay( incidence, action );
00810   } else {
00811     mViewManager->currentView()->updateView();
00812     if ( mTodoList ) mTodoList->updateView();
00813   }
00814 }
00815 
00816 
00817 void CalendarView::updateView(const QDate &start, const QDate &end)
00818 {
00819   mTodoList->updateView();
00820   mViewManager->updateView(start, end);
00821   mDateNavigator->updateView();
00822 }
00823 
00824 void CalendarView::updateView()
00825 {
00826   DateList tmpList = mNavigator->selectedDates();
00827 
00828   // We assume that the navigator only selects consecutive days.
00829   updateView( tmpList.first(), tmpList.last() );
00830 }
00831 
00832 void CalendarView::updateUnmanagedViews()
00833 {
00834   mDateNavigator->updateDayMatrix();
00835 }
00836 
00837 int CalendarView::msgItemDelete( Incidence *incidence )
00838 {
00839   return KMessageBox::warningContinueCancel(this,
00840       i18n("The item \"%1\" will be permanently deleted.").arg( incidence->summary() ),
00841       i18n("KOrganizer Confirmation"), KGuiItem(i18n("&Delete"),"editdelete"));
00842 }
00843 
00844 
00845 void CalendarView::edit_cut()
00846 {
00847   Incidence *incidence = selectedIncidence();
00848 
00849   if ( !incidence || !mChanger ) {
00850     KNotifyClient::beep();
00851     return;
00852   }
00853   mChanger->cutIncidence( incidence );
00854 }
00855 
00856 void CalendarView::edit_copy()
00857 {
00858   Incidence *incidence = selectedIncidence();
00859 
00860   if (!incidence) {
00861     KNotifyClient::beep();
00862     return;
00863   }
00864   DndFactory factory( mCalendar );
00865   if ( !factory.copyIncidence( incidence ) ) {
00866     KNotifyClient::beep();
00867   }
00868 }
00869 
00870 void CalendarView::edit_paste()
00871 {
00872 // If in agenda view, use the selected time and date from there.
00873 // In all other cases, paste the event on the first day of the
00874 // selection in the day matrix on the left
00875 
00876   QDate date;
00877   // create an invalid time to check if we got a new time for the eevent
00878   QTime time(-1,-1);
00879   QDateTime startDT, endDT;
00880   bool useEndTime = false;
00881 
00882   KOAgendaView *aView = mViewManager->agendaView();
00883   if (aView && aView->selectionStart().isValid()) {
00884       date = aView->selectionStart().date();
00885     startDT = aView->selectionStart();
00886     endDT = aView->selectionEnd();
00887     useEndTime = !aView->selectedIsSingleCell();
00888     if (!aView->selectedIsAllDay()) {
00889         time = aView->selectionStart().time();
00890     }
00891 
00892   } else {
00893     date = mNavigator->selectedDates().first();
00894   }
00895 
00896   DndFactory factory( mCalendar );
00897   Incidence *pastedIncidence;
00898   if (time.isValid())
00899     pastedIncidence = factory.pasteIncidence( date, &time );
00900   else
00901     pastedIncidence = factory.pasteIncidence( date );
00902   if ( !pastedIncidence ) return;
00903 
00904   // FIXME: use a visitor here
00905   if (pastedIncidence->type() == "Event" ) {
00906 
00907     Event* pastedEvent = static_cast<Event*>(pastedIncidence);
00908     // only use selected area if event is of the same type (all-day or non-all-day
00909     // as the current selection is
00910     if ( aView && endDT.isValid() && useEndTime ) {
00911       if ( (pastedEvent->doesFloat() && aView->selectedIsAllDay()) ||
00912            (!pastedEvent->doesFloat() && ! aView->selectedIsAllDay()) ) {
00913         pastedEvent->setDtEnd(endDT);
00914       }
00915     }
00916     mChanger->addIncidence( pastedEvent, this );
00917 
00918   } else if ( pastedIncidence->type() == "Todo" ) {
00919     Todo* pastedTodo = static_cast<Todo*>(pastedIncidence);
00920     Todo* _selectedTodo = selectedTodo();
00921     if ( _selectedTodo )
00922       pastedTodo->setRelatedTo( _selectedTodo );
00923     mChanger->addIncidence( pastedTodo, this );
00924   }
00925 }
00926 
00927 void CalendarView::edit_options()
00928 {
00929   mDialogManager->showOptionsDialog();
00930 }
00931 
00932 void CalendarView::dateTimesForNewEvent( QDateTime &startDt, QDateTime &endDt, bool &allDay )
00933 {
00934   if ( !startDt.isValid() ) {
00935     // Default start is the first selected date with the preferred time as set
00936     // in the config dlg.
00937     if ( !startDt.date().isValid() ) {
00938       startDt.setDate( mNavigator->selectedDates().first() );
00939     }
00940     if ( !startDt.time().isValid() ) {
00941       startDt.setTime( KOPrefs::instance()->mStartTime.time() );
00942     }
00943   }
00944   if ( !endDt.isValid() ) {
00945     int addSecs = ( KOPrefs::instance()->mDefaultDuration.time().hour()*3600 ) +
00946                   ( KOPrefs::instance()->mDefaultDuration.time().minute()*60 );
00947     endDt = startDt.addSecs( addSecs );
00948   }
00949   mViewManager->currentView()->eventDurationHint( startDt, endDt, allDay );
00950 }
00951 
00952 KOEventEditor *CalendarView::newEventEditor( const QDateTime &startDtParam,
00953      const QDateTime &endDtParam, bool allDayParam)
00954 {
00955   // let the current view change the default start/end datetime
00956   bool allDay = allDayParam;
00957   QDateTime startDt( startDtParam ), endDt( endDtParam );
00958   // Adjust the start/end date times (i.e. replace invalid values by defaults,
00959   // and let the view adjust the type.
00960   dateTimesForNewEvent( startDt, endDt, allDay );
00961 
00962   KOEventEditor *eventEditor = mDialogManager->getEventEditor();
00963   eventEditor->newEvent();
00964   connectIncidenceEditor( eventEditor );
00965   eventEditor->setDates( startDt, endDt, allDay );
00966   mDialogManager->connectTypeAhead( eventEditor, dynamic_cast<KOrg::AgendaView*>(viewManager()->currentView()) );
00967   return eventEditor;
00968 }
00969 
00970 
00971 
00972 
00973 void CalendarView::newEvent()
00974 {
00975   kdDebug(5850) << "CalendarView::newEvent()" << endl;
00976   newEvent( QDateTime(), QDateTime() );
00977 }
00978 
00979 void CalendarView::newEvent( const QDate &dt )
00980 {
00981   QDateTime startDt( dt, KOPrefs::instance()->mStartTime.time() );
00982   return newEvent( QDateTime( dt ), QDateTime() );
00983 }
00984 
00985 void CalendarView::newEvent( const QDateTime &startDt )
00986 {
00987   return newEvent( startDt, QDateTime() );
00988 }
00989 
00990 void CalendarView::newEvent( const QDateTime &startDt, const QDateTime &endDt,
00991                              bool allDay )
00992 {
00993   KOEventEditor *eventEditor = newEventEditor( startDt, endDt, allDay );
00994   eventEditor->show();
00995 }
00996 
00997 void CalendarView::newEvent( const QString &summary, const QString &description,
00998                              const QStringList &attachments, const QStringList &attendees,
00999                              const QStringList &attachmentMimetypes, bool inlineAttachment )
01000 {
01001   KOEventEditor *eventEditor = newEventEditor();
01002   eventEditor->setTexts( summary, description );
01003   // if attach or attendee list is empty, these methods don't do anything, so
01004   // it's save to call them in every case
01005   eventEditor->addAttachments( attachments, attachmentMimetypes, inlineAttachment );
01006   eventEditor->addAttendees( attendees );
01007   eventEditor->show();
01008 }
01009 
01010 void CalendarView::newTodo( const QString &summary, const QString &description,
01011                             const QStringList &attachments, const QStringList &attendees,
01012                             const QStringList &attachmentMimetypes, bool inlineAttachment )
01013 {
01014   kdDebug(5850) << k_funcinfo << endl;
01015   KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01016   connectIncidenceEditor( todoEditor );
01017   todoEditor->newTodo();
01018   todoEditor->setTexts( summary, description );
01019   todoEditor->addAttachments( attachments, attachmentMimetypes, inlineAttachment );
01020   todoEditor->addAttendees( attendees );
01021   todoEditor->show();
01022 }
01023 
01024 void CalendarView::newTodo()
01025 {
01026   kdDebug(5850) << k_funcinfo << endl;
01027   QDateTime dtDue;
01028   bool allday = true;
01029   KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01030   connectIncidenceEditor( todoEditor );
01031   todoEditor->newTodo();
01032   if ( mViewManager->currentView()->isEventView() ) {
01033     dtDue.setDate( mNavigator->selectedDates().first() );
01034     QDateTime dtDummy = QDateTime::currentDateTime();
01035     mViewManager->currentView()->
01036       eventDurationHint( dtDue, dtDummy, allday );
01037     todoEditor->setDates( dtDue, allday );
01038   }
01039   todoEditor->show();
01040 }
01041 
01042 void CalendarView::newTodo( const QDate &date )
01043 {
01044   KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01045   connectIncidenceEditor( todoEditor );
01046   todoEditor->newTodo();
01047   todoEditor->setDates( QDateTime( date, QTime::currentTime() ), true );
01048   todoEditor->show();
01049 }
01050 
01051 void CalendarView::newJournal()
01052 {
01053   kdDebug(5850) << "CalendarView::newJournal()" << endl;
01054   newJournal( QString::null, QDate() );
01055 }
01056 
01057 void CalendarView::newJournal( const QDate &date)
01058 {
01059   newJournal( QString::null, date );
01060 }
01061 
01062 void CalendarView::newJournal( const QString &text, const QDate &date )
01063 {
01064   KOJournalEditor *journalEditor = mDialogManager->getJournalEditor();
01065   connectIncidenceEditor( journalEditor );
01066   journalEditor->newJournal();
01067   journalEditor->setTexts( text );
01068   if ( !date.isValid() ) {
01069     journalEditor->setDate( mNavigator->selectedDates().first() );
01070   } else {
01071     journalEditor->setDate( date );
01072   }
01073   journalEditor->show();
01074 }
01075 
01076 void CalendarView::newSubTodo()
01077 {
01078   Todo *todo = selectedTodo();
01079   if ( todo ) newSubTodo( todo );
01080 }
01081 
01082 void CalendarView::newSubTodo(Todo *parentEvent)
01083 {
01084   KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01085   connectIncidenceEditor( todoEditor );
01086   todoEditor->newTodo();
01087   todoEditor->setDates( QDateTime(), false, parentEvent );
01088   todoEditor->show();
01089 }
01090 
01091 void CalendarView::newFloatingEvent()
01092 {
01093   DateList tmpList = mNavigator->selectedDates();
01094   QDate date = tmpList.first();
01095 
01096   newEvent( QDateTime( date, QTime( 12, 0, 0 ) ),
01097             QDateTime( date, QTime( 12, 0, 0 ) ), true );
01098 }
01099 
01100 bool CalendarView::addIncidence( const QString &ical )
01101 {
01102   kdDebug(5850) << "CalendarView::addIncidence:\n" << ical << endl;
01103   ICalFormat format;
01104   format.setTimeZone( mCalendar->timeZoneId(), true );
01105   Incidence *incidence = format.fromString( ical );
01106   if ( !incidence ) return false;
01107   if ( !mChanger->addIncidence( incidence, this ) ) {
01108     delete incidence;
01109     return false;
01110   }
01111   return true;
01112 }
01113 
01114 void CalendarView::appointment_show()
01115 {
01116   Incidence *incidence = selectedIncidence();
01117   if (incidence)
01118     showIncidence( incidence );
01119   else
01120     KNotifyClient::beep();
01121 }
01122 
01123 void CalendarView::appointment_edit()
01124 {
01125   Incidence *incidence = selectedIncidence();
01126   if (incidence)
01127     editIncidence( incidence );
01128   else
01129     KNotifyClient::beep();
01130 }
01131 
01132 void CalendarView::appointment_delete()
01133 {
01134   Incidence *incidence = selectedIncidence();
01135   if (incidence)
01136     deleteIncidence( incidence );
01137   else
01138     KNotifyClient::beep();
01139 }
01140 
01141 void CalendarView::todo_unsub()
01142 {
01143   Todo *anTodo = selectedTodo();
01144   if( todo_unsub (anTodo ) ) {
01145     updateView();
01146   }
01147 }
01148 
01149 bool CalendarView::todo_unsub( Todo *todo )
01150 {
01151   bool status= false;
01152   if ( !todo || !todo->relatedTo() ) return false;
01153 
01154   if ( mChanger->beginChange( todo ) ) {
01155       Todo *oldTodo = todo->clone();
01156       todo->setRelatedTo(0);
01157       mChanger->changeIncidence( oldTodo, todo, KOGlobals::RELATION_MODIFIED );
01158       mChanger->endChange( todo );
01159       delete oldTodo;
01160       setModified(true);
01161       status = true;
01162   }
01163   if ( ! status ) {
01164     KMessageBox::sorry( this, i18n("Unable to turn sub-to-do into a top-level "
01165         "to-do, because it cannot be locked.") );
01166   }
01167 
01168   return status;
01169 }
01170 
01171 bool CalendarView::makeSubTodosIndependents ( )
01172 {
01173   bool  status = false;
01174   Todo *anTodo = selectedTodo();
01175 
01176   if( makeSubTodosIndependents( anTodo ) ) {
01177     updateView();
01178     status = true;
01179   }
01180   return status;
01181 }
01182 
01183 bool CalendarView::makeSubTodosIndependents ( Todo *todo )
01184 {
01185   if( !todo || todo->relations().isEmpty() ) return false;
01186 
01187   startMultiModify ( i18n( "Make sub-to-dos independent" ) );
01188   Incidence::List subTodos( todo->relations() );
01189   Incidence::List::Iterator it;
01190   Incidence *aIncidence;
01191   Todo *aTodo;
01192 
01193   for ( it= subTodos.begin(); it != subTodos.end(); ++it ) {
01194     aIncidence = *it;
01195     if( aIncidence && aIncidence->type() == "Todo" ) {
01196       aTodo = static_cast<Todo*>( aIncidence );
01197       todo_unsub ( aTodo );
01198     }
01199   }
01200   endMultiModify();
01201   return true;
01202 }
01203 
01204 bool CalendarView::deleteIncidence( const QString &uid, bool force )
01205 {
01206   Incidence *inc = mCalendar->incidence( uid );
01207   if ( inc ) {
01208     deleteIncidence( inc, force );
01209     return true;
01210   } else {
01211     return false;
01212   }
01213 }
01214 
01215 void CalendarView::toggleAlarm( Incidence *incidence )
01216 {
01217   if ( !incidence || !mChanger ) {
01218     kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01219     return;
01220   }
01221   Incidence*oldincidence = incidence->clone();
01222   if ( !mChanger->beginChange( incidence ) ) {
01223     kdDebug(5850) << "Unable to lock incidence " << endl;
01224     delete oldincidence;
01225     return;
01226   }
01227 
01228   Alarm::List alarms = incidence->alarms();
01229   Alarm::List::ConstIterator it;
01230   for( it = alarms.begin(); it != alarms.end(); ++it )
01231     (*it)->toggleAlarm();
01232   if (alarms.isEmpty()) {
01233     // Add an alarm if it didn't have one
01234     Alarm*alm = incidence->newAlarm();
01235     alm->setEnabled(true);
01236   }
01237   mChanger->changeIncidence( oldincidence, incidence, KOGlobals::ALARM_MODIFIED );
01238   mChanger->endChange( incidence );
01239   delete oldincidence;
01240 
01241 //  mClickedItem->updateIcons();
01242 }
01243 
01244 void CalendarView::dissociateOccurrence( Incidence *incidence, const QDate &date )
01245 {
01246   if ( !incidence || !mChanger ) {
01247     kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01248     return;
01249   }
01250   if ( !mChanger->beginChange( incidence ) ) {
01251     kdDebug(5850) << "Unable to lock incidence " << endl;
01252     return;
01253   }
01254   startMultiModify( i18n("Dissociate occurrence") );
01255   Incidence*oldincidence = incidence->clone();
01256 
01257   Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true );
01258 
01259   if ( newInc ) {
01260     // TODO: Use the same resource instead of asking again!
01261     mChanger->changeIncidence( oldincidence, incidence );
01262     mChanger->addIncidence( newInc, this );
01263   } else {
01264     KMessageBox::sorry( this, i18n("Dissociating the occurrence failed."),
01265       i18n("Dissociating Failed") );
01266   }
01267   mChanger->endChange( incidence );
01268   endMultiModify();
01269   delete oldincidence;
01270 }
01271 
01272 void CalendarView::dissociateFutureOccurrence( Incidence *incidence, const QDate &date )
01273 {
01274   if ( !incidence || !mChanger ) {
01275     kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01276     return;
01277   }
01278   if ( !mChanger->beginChange( incidence ) ) {
01279     kdDebug(5850) << "Unable to lock incidence " << endl;
01280     return;
01281   }
01282   startMultiModify( i18n("Dissociate future occurrences") );
01283   Incidence*oldincidence = incidence->clone();
01284 
01285   Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true );
01286   if ( newInc ) {
01287     // TODO: Use the same resource instead of asking again!
01288     mChanger->changeIncidence( oldincidence, incidence );
01289     mChanger->addIncidence( newInc, this );
01290   } else {
01291     KMessageBox::sorry( this, i18n("Dissociating the future occurrences failed."),
01292       i18n("Dissociating Failed") );
01293   }
01294   endMultiModify();
01295   mChanger->endChange( incidence );
01296   delete oldincidence;
01297 }
01298 
01299 
01300 /*****************************************************************************/
01301 
01302 
01303 void CalendarView::schedule_publish(Incidence *incidence)
01304 {
01305   if (incidence == 0)
01306     incidence = selectedIncidence();
01307 
01308   if (!incidence) {
01309     KMessageBox::information( this, i18n("No item selected."),
01310                               "PublishNoEventSelected" );
01311     return;
01312   }
01313 
01314   PublishDialog *publishdlg = new PublishDialog();
01315   if (incidence->attendeeCount()>0) {
01316     Attendee::List attendees = incidence->attendees();
01317     Attendee::List::ConstIterator it;
01318     for( it = attendees.begin(); it != attendees.end(); ++it ) {
01319       publishdlg->addAttendee( *it );
01320     }
01321   }
01322   if ( publishdlg->exec() == QDialog::Accepted ) {
01323     Incidence *inc = incidence->clone();
01324     inc->registerObserver( 0 );
01325     inc->clearAttendees();
01326 
01327     // Send the mail
01328     KCal::MailScheduler scheduler( mCalendar );
01329     if ( scheduler.publish( incidence, publishdlg->addresses() ) ) {
01330       KMessageBox::information( this, i18n("The item information was successfully sent."),
01331                                 i18n("Publishing"), "IncidencePublishSuccess" );
01332     } else {
01333       KMessageBox::error( this, i18n("Unable to publish the item '%1'").arg( incidence->summary() ) );
01334     }
01335   }
01336   delete publishdlg;
01337 }
01338 
01339 void CalendarView::schedule_request(Incidence *incidence)
01340 {
01341   schedule(Scheduler::Request,incidence);
01342 }
01343 
01344 void CalendarView::schedule_refresh(Incidence *incidence)
01345 {
01346   schedule(Scheduler::Refresh,incidence);
01347 }
01348 
01349 void CalendarView::schedule_cancel(Incidence *incidence)
01350 {
01351   schedule(Scheduler::Cancel,incidence);
01352 }
01353 
01354 void CalendarView::schedule_add(Incidence *incidence)
01355 {
01356   schedule(Scheduler::Add,incidence);
01357 }
01358 
01359 void CalendarView::schedule_reply(Incidence *incidence)
01360 {
01361   schedule(Scheduler::Reply,incidence);
01362 }
01363 
01364 void CalendarView::schedule_counter(Incidence *incidence)
01365 {
01366   schedule(Scheduler::Counter,incidence);
01367 }
01368 
01369 void CalendarView::schedule_declinecounter(Incidence *incidence)
01370 {
01371   schedule(Scheduler::Declinecounter,incidence);
01372 }
01373 
01374 void CalendarView::schedule_forward(Incidence * incidence)
01375 {
01376   if (incidence == 0)
01377     incidence = selectedIncidence();
01378 
01379   if (!incidence) {
01380     KMessageBox::information( this, i18n("No item selected."),
01381                               "ForwardNoEventSelected" );
01382     return;
01383   }
01384 
01385   PublishDialog publishdlg;
01386   if ( publishdlg.exec() == QDialog::Accepted ) {
01387     QString recipients = publishdlg.addresses();
01388     ICalFormat format;
01389     QString messageText = format.createScheduleMessage( incidence, Scheduler::Request );
01390     KOMailClient mailer;
01391     if ( mailer.mailTo( incidence, recipients, messageText ) ) {
01392 
01393       KMessageBox::information( this, i18n("The item information was successfully sent."),
01394                                 i18n("Forwarding"), "IncidenceForwardSuccess" );
01395     } else {
01396       KMessageBox::error( this, i18n("Unable to forward the item '%1'").arg( incidence->summary() ) );
01397     }
01398   }
01399 }
01400 
01401 void CalendarView::mailFreeBusy( int daysToPublish )
01402 {
01403   QDateTime start = QDateTime::currentDateTime();
01404   QDateTime end = start.addDays(daysToPublish);
01405 
01406   FreeBusy *freebusy = new FreeBusy(mCalendar, start, end);
01407   freebusy->setOrganizer( Person( KOPrefs::instance()->fullName(),
01408                       KOPrefs::instance()->email() ) );
01409 
01410   kdDebug(5850) << "calendarview: schedule_publish_freebusy: startDate: "
01411      << KGlobal::locale()->formatDateTime( start ) << " End Date: "
01412      << KGlobal::locale()->formatDateTime( end ) << endl;
01413 
01414   PublishDialog *publishdlg = new PublishDialog();
01415   if ( publishdlg->exec() == QDialog::Accepted ) {
01416     // Send the mail
01417     KCal::MailScheduler scheduler( mCalendar );
01418     if ( scheduler.publish( freebusy, publishdlg->addresses() ) ) {
01419       KMessageBox::information( this, i18n("The free/busy information was successfully sent."),
01420                                 i18n("Sending Free/Busy"), "FreeBusyPublishSuccess" );
01421     } else {
01422       KMessageBox::error( this, i18n("Unable to publish the free/busy data.") );
01423     }
01424   }
01425   delete freebusy;
01426   delete publishdlg;
01427 }
01428 
01429 void CalendarView::uploadFreeBusy()
01430 {
01431   KOGroupware::instance()->freeBusyManager()->publishFreeBusy();
01432 }
01433 
01434 void CalendarView::schedule(Scheduler::Method method, Incidence *incidence)
01435 {
01436   if ( !incidence ) {
01437     incidence = selectedIncidence();
01438   }
01439 
01440   if ( !incidence ) {
01441     KMessageBox::sorry( this, i18n("No item selected."),
01442                         "ScheduleNoEventSelected" );
01443     return;
01444   }
01445 
01446   if( incidence->attendeeCount() == 0 && method != Scheduler::Publish ) {
01447     KMessageBox::information( this, i18n("The item has no attendees."),
01448                               "ScheduleNoIncidences" );
01449     return;
01450   }
01451 
01452   Incidence *inc = incidence->clone();
01453   inc->registerObserver( 0 );
01454   inc->clearAttendees();
01455 
01456   // Send the mail
01457   KCal::MailScheduler scheduler( mCalendar );
01458   if ( !scheduler.performTransaction( incidence, method ) ) {
01459     KMessageBox::information( this, i18n("The groupware message for item '%1'"
01460                                 "was successfully sent.\nMethod: %2")
01461                                 .arg( incidence->summary() )
01462                                 .arg( Scheduler::methodName( method ) ),
01463                               i18n("Sending Free/Busy"),
01464                               "FreeBusyPublishSuccess" );
01465   } else {
01466     KMessageBox::error( this, i18n("Groupware message sending failed. "
01467                         "%2 is request/reply/add/cancel/counter/etc.",
01468                         "Unable to send the item '%1'.\nMethod: %2")
01469                         .arg( incidence->summary() )
01470                         .arg( Scheduler::methodName( method ) ) );
01471   }
01472 }
01473 
01474 void CalendarView::openAddressbook()
01475 {
01476   KRun::runCommand("kaddressbook");
01477 }
01478 
01479 void CalendarView::setModified(bool modified)
01480 {
01481   if (mModified != modified) {
01482     mModified = modified;
01483     emit modifiedChanged(mModified);
01484   }
01485 }
01486 
01487 bool CalendarView::isReadOnly()
01488 {
01489   return mReadOnly;
01490 }
01491 
01492 void CalendarView::setReadOnly(bool readOnly)
01493 {
01494   if (mReadOnly != readOnly) {
01495     mReadOnly = readOnly;
01496     emit readOnlyChanged(mReadOnly);
01497   }
01498 }
01499 
01500 bool CalendarView::isModified()
01501 {
01502   return mModified;
01503 }
01504 
01505 void CalendarView::print()
01506 {
01507 #ifndef KORG_NOPRINTER
01508   KOCoreHelper helper;
01509   CalPrinter printer( this, mCalendar, &helper );
01510   connect( this, SIGNAL(configChanged()), &printer, SLOT(updateConfig()) );
01511 
01512   KOrg::BaseView *currentView = mViewManager->currentView();
01513 
01514   CalPrinterBase::PrintType printType = CalPrinterBase::Month;
01515   if ( currentView ) printType = currentView->printType();
01516 
01517   DateList tmpDateList = mNavigator->selectedDates();
01518   Incidence::List selectedIncidences;
01519   if ( mViewManager->currentView() ) {
01520     selectedIncidences = mViewManager->currentView()->selectedIncidences();
01521   }
01522   printer.print( printType, tmpDateList.first(), tmpDateList.last(), selectedIncidences );
01523 #endif
01524 }
01525 
01526 void CalendarView::exportWeb()
01527 {
01528   // FIXME: Get rid of the settings object. When can I delete it???
01529   HTMLExportSettings *settings = new HTMLExportSettings( "KOrganizer" );
01530   // Manually read in the config, because parametrized kconfigxt objects don't
01531   // seem to load the config theirselves
01532   if ( settings ) settings->readConfig();
01533   ExportWebDialog *dlg = new ExportWebDialog( settings, this );
01534   connect( dlg,  SIGNAL( exportHTML( HTMLExportSettings* ) ),
01535            this, SIGNAL( exportHTML( HTMLExportSettings* ) ) );
01536   dlg->show();
01537 }
01538 
01539 void CalendarView::exportICalendar()
01540 {
01541   QString filename = KFileDialog::getSaveFileName("icalout.ics",i18n("*.ics|ICalendars"),this);
01542 
01543   // Force correct extension
01544   if (filename.right(4) != ".ics") filename += ".ics";
01545 
01546   FileStorage storage( mCalendar, filename, new ICalFormat );
01547   storage.save();
01548 }
01549 
01550 void CalendarView::exportVCalendar()
01551 {
01552   if (mCalendar->journals().count() > 0) {
01553     int result = KMessageBox::warningContinueCancel(this,
01554         i18n("The journal entries can not be exported to a vCalendar file."),
01555         i18n("Data Loss Warning"),i18n("Proceed"),"dontaskVCalExport",
01556         true);
01557     if (result != KMessageBox::Continue) return;
01558   }
01559 
01560   QString filename = KFileDialog::getSaveFileName("vcalout.vcs",i18n("*.vcs|vCalendars"),this);
01561 
01562     // TODO: I don't like forcing extensions:
01563   // Force correct extension
01564   if (filename.right(4) != ".vcs") filename += ".vcs";
01565 
01566   FileStorage storage( mCalendar, filename, new VCalFormat );
01567   storage.save();
01568 }
01569 
01570 void CalendarView::eventUpdated(Incidence *)
01571 {
01572   setModified();
01573   // Don't call updateView here. The code, which has caused the update of the
01574   // event is responsible for updating the view.
01575 //  updateView();
01576 }
01577 
01578 void CalendarView::adaptNavigationUnits()
01579 {
01580   if (mViewManager->currentView()->isEventView()) {
01581     int days = mViewManager->currentView()->currentDateCount();
01582     if (days == 1) {
01583       emit changeNavStringPrev(i18n("&Previous Day"));
01584       emit changeNavStringNext(i18n("&Next Day"));
01585     } else {
01586       emit changeNavStringPrev(i18n("&Previous Week"));
01587       emit changeNavStringNext(i18n("&Next Week"));
01588     }
01589   }
01590 }
01591 
01592 void CalendarView::processMainViewSelection( Incidence *incidence )
01593 {
01594   if ( incidence ) mTodoList->clearSelection();
01595   processIncidenceSelection( incidence );
01596 }
01597 
01598 void CalendarView::processTodoListSelection( Incidence *incidence )
01599 {
01600   if ( incidence && mViewManager->currentView() ) {
01601     mViewManager->currentView()->clearSelection();
01602   }
01603   processIncidenceSelection( incidence );
01604 }
01605 
01606 void CalendarView::processIncidenceSelection( Incidence *incidence )
01607 {
01608   if ( incidence == mSelectedIncidence ) return;
01609 
01610   mSelectedIncidence = incidence;
01611 
01612   emit incidenceSelected( mSelectedIncidence );
01613   bool organizerEvents = false;
01614   bool groupEvents = false;
01615   bool todo = false;
01616   bool subtodo = false;
01617 
01618   if ( incidence ) {
01619     organizerEvents = KOPrefs::instance()->thatIsMe( incidence->organizer().email() );
01620     groupEvents = incidence->attendeeByMails( KOPrefs::instance()->allEmails() );
01621 
01622     if ( incidence && incidence->type() == "Todo" ) {
01623       todo = true;
01624       subtodo = ( incidence->relatedTo() != 0 );
01625     }
01626   }
01627   emit todoSelected( todo );
01628   emit subtodoSelected( subtodo );
01629   emit organizerEventsSelected( organizerEvents );
01630   emit groupEventsSelected( groupEvents );
01631 }
01632 
01633 
01634 void CalendarView::checkClipboard()
01635 {
01636 #ifndef KORG_NODND
01637   if (ICalDrag::canDecode(QApplication::clipboard()->data())) {
01638     kdDebug(5850) << "CalendarView::checkClipboard() true" << endl;
01639     emit pasteEnabled(true);
01640   } else {
01641     kdDebug(5850) << "CalendarView::checkClipboard() false" << endl;
01642     emit pasteEnabled(false);
01643   }
01644 #endif
01645 }
01646 
01647 void CalendarView::showDates(const DateList &selectedDates)
01648 {
01649 //  kdDebug(5850) << "CalendarView::selectDates()" << endl;
01650 
01651   if ( mViewManager->currentView() ) {
01652     updateView( selectedDates.first(), selectedDates.last() );
01653   } else {
01654     mViewManager->showAgendaView();
01655   }
01656 }
01657 
01658 void CalendarView::editFilters()
01659 {
01660   kdDebug(5850) << "CalendarView::editFilters()" << endl;
01661 
01662   CalFilter *filter = mFilters.first();
01663   while(filter) {
01664     kdDebug(5850) << " Filter: " << filter->name() << endl;
01665     filter = mFilters.next();
01666   }
01667 
01668   mDialogManager->showFilterEditDialog(&mFilters);
01669 }
01670 
01673 void CalendarView::updateFilter()
01674 {
01675   QStringList filters;
01676   CalFilter *filter;
01677 
01678   int pos = mFilters.find( mCurrentFilter );
01679   if ( pos < 0 ) {
01680     mCurrentFilter = 0;
01681   }
01682 
01683   filters << i18n("No filter");
01684   for ( filter = mFilters.first(); filter; filter = mFilters.next() ) {
01685     filters << filter->name();
01686   }
01687 
01688   emit newFilterListSignal( filters );
01689   // account for the additional "No filter" at the beginning! if the
01690   // filter is not in the list, pos == -1...
01691   emit selectFilterSignal( pos+1 );
01692   mCalendar->setFilter( mCurrentFilter );
01693   updateView();
01694 }
01695 
01698 void CalendarView::filterActivated( int filterNo )
01699 {
01700   CalFilter *newFilter = 0;
01701   if ( filterNo > 0 && filterNo <= int(mFilters.count()) ) {
01702     newFilter = mFilters.at( filterNo-1 );
01703   }
01704   if ( newFilter != mCurrentFilter ) {
01705     mCurrentFilter = newFilter;
01706     mCalendar->setFilter( mCurrentFilter );
01707     updateView();
01708   }
01709   emit filterChanged();
01710 }
01711 
01712 QString CalendarView::currentFilterName() const
01713 {
01714   if ( mCurrentFilter) {
01715     return mCurrentFilter->name();
01716   } else return i18n("No filter");
01717 }
01718 
01719 void CalendarView::takeOverEvent()
01720 {
01721   Incidence *incidence = currentSelection();
01722 
01723   if (!incidence) return;
01724 
01725   incidence->setOrganizer( Person( KOPrefs::instance()->fullName(),
01726                            KOPrefs::instance()->email() ) );
01727   incidence->recreate();
01728   incidence->setReadOnly(false);
01729 
01730   updateView();
01731 }
01732 
01733 void CalendarView::takeOverCalendar()
01734 {
01735   Incidence::List incidences = mCalendar->rawIncidences();
01736   Incidence::List::Iterator it;
01737 
01738   for ( it = incidences.begin(); it != incidences.end(); ++it ) {
01739     (*it)->setOrganizer( Person( KOPrefs::instance()->fullName(),
01740                          KOPrefs::instance()->email() ) );
01741     (*it)->recreate();
01742     (*it)->setReadOnly(false);
01743   }
01744   updateView();
01745 }
01746 
01747 void CalendarView::showIntro()
01748 {
01749   kdDebug(5850) << "To be implemented." << endl;
01750 }
01751 
01752 void CalendarView::showDateNavigator( bool show )
01753 {
01754   if( show )
01755     mDateNavigator->show();
01756   else
01757     mDateNavigator->hide();
01758 }
01759 
01760 void CalendarView::showTodoView( bool show )
01761 {
01762   if( show )
01763     mTodoList->show();
01764   else
01765     mTodoList->hide();
01766 }
01767 
01768 void CalendarView::showEventViewer( bool show )
01769 {
01770   if( show )
01771     mEventViewer->show();
01772   else
01773     mEventViewer->hide();
01774 }
01775 
01776 
01777 void CalendarView::addView(KOrg::BaseView *view)
01778 {
01779   mViewManager->addView(view);
01780 }
01781 
01782 void CalendarView::showView(KOrg::BaseView *view)
01783 {
01784   mViewManager->showView(view);
01785 }
01786 
01787 void CalendarView::addExtension( CalendarViewExtension::Factory *factory )
01788 {
01789   CalendarViewExtension *extension = factory->create( mLeftSplitter );
01790 
01791   mExtensions.append( extension );
01792 }
01793 
01794 void CalendarView::toggleExpand()
01795 {
01796   showLeftFrame( mLeftFrame->isHidden() );
01797 }
01798 
01799 void CalendarView::showLeftFrame(bool show)
01800 {
01801   if (show) {
01802     mLeftFrame->show();
01803     emit calendarViewExpanded( false );
01804   } else {
01805     mLeftFrame->hide();
01806     emit calendarViewExpanded( true );
01807   }
01808 }
01809 
01810 void CalendarView::calendarModified( bool modified, Calendar * )
01811 {
01812   setModified( modified );
01813 }
01814 
01815 Todo *CalendarView::selectedTodo()
01816 {
01817   Incidence *incidence = currentSelection();
01818   if ( incidence && incidence->type() == "Todo" ) {
01819     return static_cast<Todo *>( incidence );
01820   }
01821   incidence = 0;
01822 
01823   Incidence::List selectedIncidences = mTodoList->selectedIncidences();
01824   if ( !selectedIncidences.isEmpty() ) incidence = selectedIncidences.first();
01825   if ( incidence && incidence->type() == "Todo" ) {
01826     return static_cast<Todo *>( incidence );
01827   }
01828 
01829   return 0;
01830 }
01831 
01832 void CalendarView::dialogClosing( Incidence *in )
01833 {
01834   // FIXME: this doesn't work, because if it's a new incidence, it's not locked!
01835   mChanger->endChange( in );
01836   mDialogList.remove( in );
01837 }
01838 
01839 Incidence *CalendarView::currentSelection()
01840 {
01841   return mViewManager->currentSelection();
01842 }
01843 
01844 Incidence* CalendarView::selectedIncidence()
01845 {
01846   Incidence *incidence = currentSelection();
01847   if ( !incidence ) {
01848     Incidence::List selectedIncidences = mTodoList->selectedIncidences();
01849     if ( !selectedIncidences.isEmpty() )
01850       incidence = selectedIncidences.first();
01851   }
01852   return incidence;
01853 }
01854 
01855 void CalendarView::showIncidence()
01856 {
01857   showIncidence( selectedIncidence() );
01858 }
01859 
01860 void CalendarView::editIncidence()
01861 {
01862   editIncidence( selectedIncidence() );
01863 }
01864 
01865 bool CalendarView::editIncidence( const QString& uid )
01866 {
01867   kdDebug(5850) << "CalendarView::editIncidence()" << endl;
01868   return editIncidence( mCalendar->incidence( uid ) );
01869 }
01870 
01871 void CalendarView::deleteIncidence()
01872 {
01873   deleteIncidence( selectedIncidence() );
01874 }
01875 
01876 void CalendarView::cutIncidence(Incidence *)
01877 {
01878   edit_cut();
01879 }
01880 
01881 void CalendarView::copyIncidence(Incidence *)
01882 {
01883   edit_copy();
01884 }
01885 
01886 void CalendarView::pasteIncidence()
01887 {
01888   edit_paste();
01889 }
01890 
01891 void CalendarView::showIncidence( Incidence *incidence )
01892 {
01893   KOEventViewerDialog *eventViewer = new KOEventViewerDialog( this );
01894   eventViewer->setIncidence( incidence );
01895   eventViewer->show();
01896 }
01897 
01898 bool CalendarView::editIncidence( Incidence *incidence, bool isCounter )
01899 {
01900   kdDebug(5850) << "CalendarView::editEvent()" << endl;
01901 
01902   if ( !incidence || !mChanger ) {
01903     KNotifyClient::beep();
01904     return false;
01905   }
01906   KOIncidenceEditor *tmp = editorDialog( incidence );
01907   if ( tmp ) {
01908     kdDebug(5850) << "CalendarView::editIncidence() in List" << endl;
01909     tmp->reload();
01910     tmp->raise();
01911     tmp->show();
01912     return true;
01913   }
01914 
01915   if ( incidence->isReadOnly() ) {
01916     showIncidence( incidence );
01917     return true;
01918   }
01919 
01920   if ( !isCounter && !mChanger->beginChange( incidence ) ) {
01921     warningChangeFailed( incidence );
01922     showIncidence( incidence );
01923     return false;
01924   }
01925 
01926   kdDebug(5850) << "CalendarView::editIncidence() new IncidenceEditor" << endl;
01927   KOIncidenceEditor *incidenceEditor = mDialogManager->getEditor( incidence );
01928   connectIncidenceEditor( incidenceEditor );
01929 
01930   mDialogList.insert( incidence, incidenceEditor );
01931   incidenceEditor->editIncidence( incidence, mCalendar );
01932   incidenceEditor->show();
01933   return true;
01934 }
01935 
01936 void CalendarView::deleteSubTodosIncidence ( Todo *todo )
01937 {
01938   if( !todo ) return;
01939 
01940   Incidence::List subTodos( todo->relations() );
01941   Incidence::List::Iterator it;
01942   Incidence *aIncidence;
01943   Todo *aTodo;
01944 
01945   for ( it= subTodos.begin(); it != subTodos.end(); ++it ) {
01946     aIncidence = *it;
01947     if( aIncidence && aIncidence->type() == "Todo" ) {
01948       aTodo = static_cast<Todo*>( aIncidence );
01949       deleteSubTodosIncidence ( aTodo );
01950     }
01951   }
01952   mChanger->deleteIncidence ( todo );
01953 }
01954 
01955 void CalendarView::deleteTodoIncidence ( Todo *todo, bool force )
01956 {
01957   if ( !todo ) return ;
01958 
01959   // it a simple todo, ask and delete it.
01960   if (todo->relations().isEmpty() ) {
01961     bool doDelete = true;
01962     if ( !force && KOPrefs::instance()->mConfirm ) {
01963       doDelete = ( msgItemDelete( todo ) == KMessageBox::Continue );
01964     }
01965     if ( doDelete )
01966       mChanger->deleteIncidence( todo );
01967     return;
01968   }
01969 
01970   /* Ok, this to-do has sub-to-dos, ask what to do */
01971   int km = KMessageBox::No;
01972   if ( !force ) {
01973     km=KMessageBox::questionYesNoCancel( this,
01974                                 i18n("The item \"%1\" has sub-to-dos. "
01975                                      "Do you want to delete just this item and "
01976                                      "make all its sub-to-dos independent, or "
01977                                      "delete the to-do with all its sub-to-dos?"
01978                                 ).arg( todo->summary() ),
01979                                 i18n("KOrganizer Confirmation"),
01980                                 i18n("Delete Only This"),
01981                                 i18n("Delete All"));
01982   }
01983   startMultiModify( i18n("Deleting sub-to-dos" ) );
01984   // Delete only the father
01985   if( km == KMessageBox::Yes ) {
01986 
01987     makeSubTodosIndependents ( todo );
01988     mChanger->deleteIncidence( todo );
01989   } else if ( km == KMessageBox::No ) {
01990     // Delete all
01991     // we have to hide the delete confirmation for each itemDate
01992     deleteSubTodosIncidence ( todo );
01993   }
01994   endMultiModify();
01995 }
01996 
01997 void CalendarView::deleteIncidence(Incidence *incidence, bool force)
01998 {
01999   if ( !incidence || !mChanger ) {
02000     if ( !force ) {
02001       KNotifyClient::beep();
02002     }
02003     return;
02004   }
02005   if ( incidence->isReadOnly() ) {
02006     if ( !force ) {
02007       KMessageBox::information( this, i18n("The item \"%1\" is marked read-only "
02008                                 "and cannot be deleted; it probably belongs to "
02009                                 "a read-only calendar resource.")
02010                                 .arg(incidence->summary()),
02011                                 i18n("Removing not possible"),
02012                                 "deleteReadOnlyIncidence" );
02013     }
02014     return;
02015   }
02016 
02017   CanDeleteIncidenceVisitor v;
02018 
02019   // Let the visitor do special things for special incidence types.
02020   // e.g. todos with children cannot be deleted, so act(..) returns false
02021   if ( !v.act( incidence, this ) )
02022     return;
02023   //If it is a todo, there are specific delete function
02024 
02025   if ( incidence && incidence->type()=="Todo" ) {
02026     deleteTodoIncidence( static_cast<Todo*>(incidence), force );
02027     return;
02028   }
02029 
02030   if ( incidence->doesRecur() ) {
02031     QDate itemDate = mViewManager->currentSelectionDate();
02032     kdDebug(5850) << "Recurrence-Date: " << itemDate.toString() << endl;
02033     int km = KMessageBox::Ok;
02034     if ( !force ) {
02035       if ( !itemDate.isValid() ) {
02036         kdDebug(5850) << "Date Not Valid" << endl;
02037         km = KMessageBox::warningContinueCancel(this,
02038           i18n("The calendar item \"%1\" recurs over multiple dates; "
02039                "are you sure you want to delete it "
02040                "and all its recurrences?").arg( incidence->summary() ),
02041                i18n("KOrganizer Confirmation"), i18n("Delete All") );
02042       } else {
02043         km = KOMessageBox::fourBtnMsgBox( this, QMessageBox::Warning,
02044           i18n("The calendar item \"%1\" recurs over multiple dates. "
02045                "Do you want to delete only the current one on %2, only all "
02046                "future recurrences, or all its recurrences?" )
02047                .arg( incidence->summary() )
02048                .arg( KGlobal::locale()->formatDate(itemDate)),
02049                i18n("KOrganizer Confirmation"), i18n("Delete C&urrent"),
02050                i18n("Delete &Future"),
02051                i18n("Delete &All"));
02052       }
02053     }
02054     switch(km) {
02055       case KMessageBox::Ok: // Continue // all
02056       case KMessageBox::Continue:
02057         mChanger->deleteIncidence( incidence );
02058         break;
02059 
02060       case KMessageBox::Yes: // just this one
02061         if ( mChanger->beginChange( incidence ) ) {
02062           Incidence *oldIncidence = incidence->clone();
02063           incidence->recurrence()->addExDate( itemDate );
02064           mChanger->changeIncidence( oldIncidence, incidence );
02065           mChanger->endChange( incidence );
02066           delete oldIncidence;
02067         }
02068         break;
02069       case KMessageBox::No: // all future items
02070         if ( mChanger->beginChange( incidence ) ) {
02071           Incidence *oldIncidence = incidence->clone();
02072           Recurrence *recur = incidence->recurrence();
02073           recur->setEndDate( itemDate.addDays(-1) );
02074           mChanger->changeIncidence( oldIncidence, incidence );
02075           mChanger->endChange( incidence );
02076           delete oldIncidence;
02077         }
02078         break;
02079     }
02080   } else {
02081     bool doDelete = true;
02082     if ( !force && KOPrefs::instance()->mConfirm ) {
02083       doDelete = ( msgItemDelete( incidence ) == KMessageBox::Continue );
02084     }
02085     if ( doDelete ) {
02086       mChanger->deleteIncidence( incidence );
02087       processIncidenceSelection( 0 );
02088     }
02089   }
02090 }
02091 
02092 void CalendarView::connectIncidenceEditor( KOIncidenceEditor *editor )
02093 {
02094   connect( this, SIGNAL( newIncidenceChanger( IncidenceChangerBase* ) ),
02095            editor, SLOT( setIncidenceChanger( IncidenceChangerBase* ) ) );
02096   editor->setIncidenceChanger( mChanger );
02097 }
02098 
02099 bool CalendarView::purgeCompletedSubTodos( Todo* todo, bool &allPurged )
02100 {
02101   if ( !todo ) return true;
02102   bool deleteThisTodo = true;
02103   Incidence::List subTodos( todo->relations() );
02104   Incidence *aIncidence;
02105   Todo *aTodo;
02106   Incidence::List::Iterator it;
02107   for ( it = subTodos.begin(); it != subTodos.end(); ++it ) {
02108     aIncidence = *it;
02109     if ( aIncidence && aIncidence->type()=="Todo" ) {
02110       aTodo = static_cast<Todo*>( aIncidence );
02111       deleteThisTodo &= purgeCompletedSubTodos( aTodo, allPurged );
02112     }
02113   }
02114 
02115   if ( deleteThisTodo ) {
02116     if ( todo->isCompleted() ) {
02117       if ( !mChanger->deleteIncidence( todo ) )
02118         allPurged = false;
02119     } else {
02120       deleteThisTodo = false;
02121     }
02122   } else {
02123     if ( todo->isCompleted() ) {
02124       allPurged = false;
02125     }
02126   }
02127   return deleteThisTodo;
02128 }
02129 
02130 void CalendarView::purgeCompleted()
02131 {
02132   int result = KMessageBox::warningContinueCancel(this,
02133       i18n("Delete all completed to-dos?"),i18n("Purge To-dos"),i18n("Purge"));
02134 
02135   if (result == KMessageBox::Continue) {
02136     bool allDeleted = true;
02137     startMultiModify( i18n("Purging completed to-dos") );
02138     Todo::List todos = calendar()->rawTodos();
02139     Todo::List rootTodos;
02140     Todo::List::ConstIterator it;
02141     for ( it = todos.begin(); it != todos.end(); ++it ) {
02142       Todo *aTodo = *it;
02143       if ( aTodo && !aTodo->relatedTo() )
02144         rootTodos.append( aTodo );
02145     }
02146     // now that we have a list of all root todos, check them and their children
02147     for ( it = rootTodos.begin(); it != rootTodos.end(); ++it ) {
02148       purgeCompletedSubTodos( *it, allDeleted );
02149     }
02150     endMultiModify();
02151     if ( !allDeleted ) {
02152       KMessageBox::information( this, i18n("Unable to purge to-dos with "
02153                                 "uncompleted children."), i18n("Delete To-do"),
02154                                 "UncompletedChildrenPurgeTodos" );
02155     }
02156   }
02157 }
02158 
02159 void CalendarView::slotCalendarChanged()
02160 {
02161   kdDebug(5850) << "CalendarView::slotCalendarChanged()" << endl;
02162 
02163   updateView();
02164 }
02165 
02166 void CalendarView::warningChangeFailed( Incidence * )
02167 {
02168   KMessageBox::sorry( this, i18n("Unable to edit item: "
02169                                  "it is locked by another process.") );
02170 }
02171 
02172 void CalendarView::editCanceled( Incidence *i )
02173 {
02174   mCalendar->endChange( i );
02175 }
02176 
02177 void CalendarView::showErrorMessage( const QString &msg )
02178 {
02179   KMessageBox::error( this, msg );
02180 }
02181 
02182 void CalendarView::updateCategories()
02183 {
02184   QStringList allCats( calendar()->categories() );
02185   allCats.sort();
02186   QStringList categories( KOPrefs::instance()->mCustomCategories );
02187   for ( QStringList::ConstIterator si = allCats.constBegin(); si != allCats.constEnd(); ++si ) {
02188     if ( categories.find( *si ) == categories.end() ) {
02189       categories.append( *si );
02190     }
02191   }
02192   KOPrefs::instance()->mCustomCategories = categories;
02193   KOPrefs::instance()->writeConfig();
02194   // Make the category editor update the list!
02195   emit categoriesChanged();
02196 }
02197 
02198 void CalendarView::addIncidenceOn( Incidence *incadd, const QDate &dt )
02199 {
02200   if ( !incadd || !mChanger ) {
02201     KMessageBox::sorry(this, i18n("Unable to copy the item to %1.")
02202                        .arg( dt.toString() ), i18n("Copying Failed") );
02203     return;
02204   }
02205   Incidence *incidence = mCalendar->incidence( incadd->uid() );
02206   if ( !incidence ) incidence = incadd;
02207   // Create a copy of the incidence, since the incadd doesn't belong to us.
02208   incidence = incidence->clone();
02209   incidence->recreate();
02210 
02211   if ( incidence->type() == "Event" ) {
02212     Event *event = static_cast<Event*>(incidence);
02213 
02214     // Adjust date
02215     QDateTime start = event->dtStart();
02216     QDateTime end = event->dtEnd();
02217 
02218     int duration = start.daysTo( end );
02219     start.setDate( dt );
02220     end.setDate( dt.addDays( duration ) );
02221 
02222     event->setDtStart( start );
02223     event->setDtEnd( end );
02224 
02225   } else if ( incidence->type() == "Todo" ) {
02226     Todo *todo = static_cast<Todo*>(incidence);
02227     QDateTime due = todo->dtDue();
02228     due.setDate( dt );
02229 
02230     todo->setDtDue( due );
02231     todo->setHasDueDate( true );
02232   }
02233 
02234   if ( !mChanger->addIncidence( incidence, this ) ) {
02235     KODialogManager::errorSaveIncidence( this, incidence );
02236     delete incidence;
02237   }
02238 }
02239 
02240 void CalendarView::moveIncidenceTo( Incidence *incmove, const QDate &dt )
02241 {
02242   if ( !incmove || !mChanger ) {
02243     KMessageBox::sorry( this, i18n("Unable to move the item to %1.")
02244                         .arg( dt.toString() ), i18n("Moving Failed") );
02245     return;
02246   }
02247   Incidence *incidence = mCalendar->incidence( incmove->uid() );
02248   if ( !incidence ) {
02249     addIncidenceOn( incidence, dt );
02250     return;
02251   }
02252   Incidence *oldIncidence = incidence->clone();
02253   if ( !mChanger->beginChange( incidence ) ) {
02254     delete oldIncidence;
02255     return;
02256   }
02257 
02258   if ( incidence->type() == "Event" ) {
02259     Event *event = static_cast<Event*>(incidence);
02260 
02261     // Adjust date
02262     QDateTime start = event->dtStart();
02263     QDateTime end = event->dtEnd();
02264 
02265     int duration = start.daysTo( end );
02266     start.setDate( dt );
02267     end.setDate( dt.addDays( duration ) );
02268 
02269     event->setDtStart( start );
02270     event->setDtEnd( end );
02271 
02272   } else if ( incidence->type() == "Todo" ) {
02273     Todo *todo = static_cast<Todo*>(incidence);
02274     QDateTime due = todo->dtDue();
02275     due.setDate( dt );
02276 
02277     todo->setDtDue( due );
02278     todo->setHasDueDate( true );
02279   }
02280   mChanger->changeIncidence( oldIncidence, incidence );
02281   mChanger->endChange( incidence );
02282   delete oldIncidence;
02283 }
02284 
02285 #include "calendarview.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys