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->setDates( QDateTime(), false );
01019   todoEditor->setTexts( summary, description );
01020   todoEditor->addAttachments( attachments, attachmentMimetypes, inlineAttachment );
01021   todoEditor->addAttendees( attendees );
01022   todoEditor->show();
01023 }
01024 
01025 void CalendarView::newTodo()
01026 {
01027   kdDebug(5850) << k_funcinfo << endl;
01028   QDateTime dtDue;
01029   bool allday = true;
01030   KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01031   connectIncidenceEditor( todoEditor );
01032   todoEditor->newTodo();
01033   if ( mViewManager->currentView()->isEventView() ) {
01034     dtDue.setDate( mNavigator->selectedDates().first() );
01035     QDateTime dtDummy = QDateTime::currentDateTime();
01036     mViewManager->currentView()->
01037       eventDurationHint( dtDue, dtDummy, allday );
01038     todoEditor->setDates( dtDue, allday );
01039   }
01040   todoEditor->show();
01041 }
01042 
01043 void CalendarView::newTodo( const QDate &date )
01044 {
01045   KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01046   connectIncidenceEditor( todoEditor );
01047   todoEditor->newTodo();
01048   todoEditor->setDates( QDateTime( date, QTime::currentTime() ), true );
01049   todoEditor->show();
01050 }
01051 
01052 void CalendarView::newJournal()
01053 {
01054   kdDebug(5850) << "CalendarView::newJournal()" << endl;
01055   newJournal( QString::null, QDate() );
01056 }
01057 
01058 void CalendarView::newJournal( const QDate &date)
01059 {
01060   newJournal( QString::null, date );
01061 }
01062 
01063 void CalendarView::newJournal( const QString &text, const QDate &date )
01064 {
01065   KOJournalEditor *journalEditor = mDialogManager->getJournalEditor();
01066   connectIncidenceEditor( journalEditor );
01067   journalEditor->newJournal();
01068   journalEditor->setTexts( text );
01069   if ( !date.isValid() ) {
01070     journalEditor->setDate( mNavigator->selectedDates().first() );
01071   } else {
01072     journalEditor->setDate( date );
01073   }
01074   journalEditor->show();
01075 }
01076 
01077 void CalendarView::newSubTodo()
01078 {
01079   Todo *todo = selectedTodo();
01080   if ( todo ) newSubTodo( todo );
01081 }
01082 
01083 void CalendarView::newSubTodo(Todo *parentEvent)
01084 {
01085   KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01086   connectIncidenceEditor( todoEditor );
01087   todoEditor->newTodo();
01088   todoEditor->setDates( QDateTime(), false, parentEvent );
01089   todoEditor->show();
01090 }
01091 
01092 void CalendarView::newFloatingEvent()
01093 {
01094   DateList tmpList = mNavigator->selectedDates();
01095   QDate date = tmpList.first();
01096 
01097   newEvent( QDateTime( date, QTime( 12, 0, 0 ) ),
01098             QDateTime( date, QTime( 12, 0, 0 ) ), true );
01099 }
01100 
01101 bool CalendarView::addIncidence( const QString &ical )
01102 {
01103   kdDebug(5850) << "CalendarView::addIncidence:\n" << ical << endl;
01104   ICalFormat format;
01105   format.setTimeZone( mCalendar->timeZoneId(), true );
01106   Incidence *incidence = format.fromString( ical );
01107   if ( !incidence ) return false;
01108   if ( !mChanger->addIncidence( incidence, this ) ) {
01109     delete incidence;
01110     return false;
01111   }
01112   return true;
01113 }
01114 
01115 void CalendarView::appointment_show()
01116 {
01117   Incidence *incidence = selectedIncidence();
01118   if (incidence)
01119     showIncidence( incidence );
01120   else
01121     KNotifyClient::beep();
01122 }
01123 
01124 void CalendarView::appointment_edit()
01125 {
01126   Incidence *incidence = selectedIncidence();
01127   if (incidence)
01128     editIncidence( incidence );
01129   else
01130     KNotifyClient::beep();
01131 }
01132 
01133 void CalendarView::appointment_delete()
01134 {
01135   Incidence *incidence = selectedIncidence();
01136   if (incidence)
01137     deleteIncidence( incidence );
01138   else
01139     KNotifyClient::beep();
01140 }
01141 
01142 void CalendarView::todo_unsub()
01143 {
01144   Todo *anTodo = selectedTodo();
01145   if( todo_unsub (anTodo ) ) {
01146     updateView();
01147   }
01148 }
01149 
01150 bool CalendarView::todo_unsub( Todo *todo )
01151 {
01152   bool status= false;
01153   if ( !todo || !todo->relatedTo() ) return false;
01154 
01155   if ( mChanger->beginChange( todo ) ) {
01156       Todo *oldTodo = todo->clone();
01157       todo->setRelatedTo(0);
01158       mChanger->changeIncidence( oldTodo, todo, KOGlobals::RELATION_MODIFIED );
01159       mChanger->endChange( todo );
01160       delete oldTodo;
01161       setModified(true);
01162       status = true;
01163   }
01164   if ( ! status ) {
01165     KMessageBox::sorry( this, i18n("Unable to turn sub-to-do into a top-level "
01166         "to-do, because it cannot be locked.") );
01167   }
01168 
01169   return status;
01170 }
01171 
01172 bool CalendarView::makeSubTodosIndependents ( )
01173 {
01174   bool  status = false;
01175   Todo *anTodo = selectedTodo();
01176 
01177   if( makeSubTodosIndependents( anTodo ) ) {
01178     updateView();
01179     status = true;
01180   }
01181   return status;
01182 }
01183 
01184 bool CalendarView::makeSubTodosIndependents ( Todo *todo )
01185 {
01186   if( !todo || todo->relations().isEmpty() ) return false;
01187 
01188   startMultiModify ( i18n( "Make sub-to-dos independent" ) );
01189   Incidence::List subTodos( todo->relations() );
01190   Incidence::List::Iterator it;
01191   Incidence *aIncidence;
01192   Todo *aTodo;
01193 
01194   for ( it= subTodos.begin(); it != subTodos.end(); ++it ) {
01195     aIncidence = *it;
01196     if( aIncidence && aIncidence->type() == "Todo" ) {
01197       aTodo = static_cast<Todo*>( aIncidence );
01198       todo_unsub ( aTodo );
01199     }
01200   }
01201   endMultiModify();
01202   return true;
01203 }
01204 
01205 bool CalendarView::deleteIncidence( const QString &uid, bool force )
01206 {
01207   Incidence *inc = mCalendar->incidence( uid );
01208   if ( inc ) {
01209     deleteIncidence( inc, force );
01210     return true;
01211   } else {
01212     return false;
01213   }
01214 }
01215 
01216 void CalendarView::toggleAlarm( Incidence *incidence )
01217 {
01218   if ( !incidence || !mChanger ) {
01219     kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01220     return;
01221   }
01222   Incidence*oldincidence = incidence->clone();
01223   if ( !mChanger->beginChange( incidence ) ) {
01224     kdDebug(5850) << "Unable to lock incidence " << endl;
01225     delete oldincidence;
01226     return;
01227   }
01228 
01229   Alarm::List alarms = incidence->alarms();
01230   Alarm::List::ConstIterator it;
01231   for( it = alarms.begin(); it != alarms.end(); ++it )
01232     (*it)->toggleAlarm();
01233   if (alarms.isEmpty()) {
01234     // Add an alarm if it didn't have one
01235     Alarm*alm = incidence->newAlarm();
01236     alm->setEnabled(true);
01237   }
01238   mChanger->changeIncidence( oldincidence, incidence, KOGlobals::ALARM_MODIFIED );
01239   mChanger->endChange( incidence );
01240   delete oldincidence;
01241 
01242 //  mClickedItem->updateIcons();
01243 }
01244 
01245 void CalendarView::dissociateOccurrence( Incidence *incidence, const QDate &date )
01246 {
01247   if ( !incidence || !mChanger ) {
01248     kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01249     return;
01250   }
01251   if ( !mChanger->beginChange( incidence ) ) {
01252     kdDebug(5850) << "Unable to lock incidence " << endl;
01253     return;
01254   }
01255   startMultiModify( i18n("Dissociate occurrence") );
01256   Incidence*oldincidence = incidence->clone();
01257 
01258   Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true );
01259 
01260   if ( newInc ) {
01261     // TODO: Use the same resource instead of asking again!
01262     mChanger->changeIncidence( oldincidence, incidence );
01263     mChanger->addIncidence( newInc, this );
01264   } else {
01265     KMessageBox::sorry( this, i18n("Dissociating the occurrence failed."),
01266       i18n("Dissociating Failed") );
01267   }
01268   mChanger->endChange( incidence );
01269   endMultiModify();
01270   delete oldincidence;
01271 }
01272 
01273 void CalendarView::dissociateFutureOccurrence( Incidence *incidence, const QDate &date )
01274 {
01275   if ( !incidence || !mChanger ) {
01276     kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01277     return;
01278   }
01279   if ( !mChanger->beginChange( incidence ) ) {
01280     kdDebug(5850) << "Unable to lock incidence " << endl;
01281     return;
01282   }
01283   startMultiModify( i18n("Dissociate future occurrences") );
01284   Incidence*oldincidence = incidence->clone();
01285 
01286   Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true );
01287   if ( newInc ) {
01288     // TODO: Use the same resource instead of asking again!
01289     mChanger->changeIncidence( oldincidence, incidence );
01290     mChanger->addIncidence( newInc, this );
01291   } else {
01292     KMessageBox::sorry( this, i18n("Dissociating the future occurrences failed."),
01293       i18n("Dissociating Failed") );
01294   }
01295   endMultiModify();
01296   mChanger->endChange( incidence );
01297   delete oldincidence;
01298 }
01299 
01300 
01301 /*****************************************************************************/
01302 
01303 
01304 void CalendarView::schedule_publish(Incidence *incidence)
01305 {
01306   if (incidence == 0)
01307     incidence = selectedIncidence();
01308 
01309   if (!incidence) {
01310     KMessageBox::information( this, i18n("No item selected."),
01311                               "PublishNoEventSelected" );
01312     return;
01313   }
01314 
01315   PublishDialog *publishdlg = new PublishDialog();
01316   if (incidence->attendeeCount()>0) {
01317     Attendee::List attendees = incidence->attendees();
01318     Attendee::List::ConstIterator it;
01319     for( it = attendees.begin(); it != attendees.end(); ++it ) {
01320       publishdlg->addAttendee( *it );
01321     }
01322   }
01323   if ( publishdlg->exec() == QDialog::Accepted ) {
01324     Incidence *inc = incidence->clone();
01325     inc->registerObserver( 0 );
01326     inc->clearAttendees();
01327 
01328     // Send the mail
01329     KCal::MailScheduler scheduler( mCalendar );
01330     if ( scheduler.publish( incidence, publishdlg->addresses() ) ) {
01331       KMessageBox::information( this, i18n("The item information was successfully sent."),
01332                                 i18n("Publishing"), "IncidencePublishSuccess" );
01333     } else {
01334       KMessageBox::error( this, i18n("Unable to publish the item '%1'").arg( incidence->summary() ) );
01335     }
01336   }
01337   delete publishdlg;
01338 }
01339 
01340 void CalendarView::schedule_request(Incidence *incidence)
01341 {
01342   schedule(Scheduler::Request,incidence);
01343 }
01344 
01345 void CalendarView::schedule_refresh(Incidence *incidence)
01346 {
01347   schedule(Scheduler::Refresh,incidence);
01348 }
01349 
01350 void CalendarView::schedule_cancel(Incidence *incidence)
01351 {
01352   schedule(Scheduler::Cancel,incidence);
01353 }
01354 
01355 void CalendarView::schedule_add(Incidence *incidence)
01356 {
01357   schedule(Scheduler::Add,incidence);
01358 }
01359 
01360 void CalendarView::schedule_reply(Incidence *incidence)
01361 {
01362   schedule(Scheduler::Reply,incidence);
01363 }
01364 
01365 void CalendarView::schedule_counter(Incidence *incidence)
01366 {
01367   schedule(Scheduler::Counter,incidence);
01368 }
01369 
01370 void CalendarView::schedule_declinecounter(Incidence *incidence)
01371 {
01372   schedule(Scheduler::Declinecounter,incidence);
01373 }
01374 
01375 void CalendarView::schedule_forward(Incidence * incidence)
01376 {
01377   if (incidence == 0)
01378     incidence = selectedIncidence();
01379 
01380   if (!incidence) {
01381     KMessageBox::information( this, i18n("No item selected."),
01382                               "ForwardNoEventSelected" );
01383     return;
01384   }
01385 
01386   PublishDialog publishdlg;
01387   if ( publishdlg.exec() == QDialog::Accepted ) {
01388     QString recipients = publishdlg.addresses();
01389     ICalFormat format;
01390     QString messageText = format.createScheduleMessage( incidence, Scheduler::Request );
01391     KOMailClient mailer;
01392     if ( mailer.mailTo( incidence, recipients, messageText ) ) {
01393 
01394       KMessageBox::information( this, i18n("The item information was successfully sent."),
01395                                 i18n("Forwarding"), "IncidenceForwardSuccess" );
01396     } else {
01397       KMessageBox::error( this, i18n("Unable to forward the item '%1'").arg( incidence->summary() ) );
01398     }
01399   }
01400 }
01401 
01402 void CalendarView::mailFreeBusy( int daysToPublish )
01403 {
01404   QDateTime start = QDateTime::currentDateTime();
01405   QDateTime end = start.addDays(daysToPublish);
01406 
01407   FreeBusy *freebusy = new FreeBusy(mCalendar, start, end);
01408   freebusy->setOrganizer( Person( KOPrefs::instance()->fullName(),
01409                       KOPrefs::instance()->email() ) );
01410 
01411   kdDebug(5850) << "calendarview: schedule_publish_freebusy: startDate: "
01412      << KGlobal::locale()->formatDateTime( start ) << " End Date: "
01413      << KGlobal::locale()->formatDateTime( end ) << endl;
01414 
01415   PublishDialog *publishdlg = new PublishDialog();
01416   if ( publishdlg->exec() == QDialog::Accepted ) {
01417     // Send the mail
01418     KCal::MailScheduler scheduler( mCalendar );
01419     if ( scheduler.publish( freebusy, publishdlg->addresses() ) ) {
01420       KMessageBox::information( this, i18n("The free/busy information was successfully sent."),
01421                                 i18n("Sending Free/Busy"), "FreeBusyPublishSuccess" );
01422     } else {
01423       KMessageBox::error( this, i18n("Unable to publish the free/busy data.") );
01424     }
01425   }
01426   delete freebusy;
01427   delete publishdlg;
01428 }
01429 
01430 void CalendarView::uploadFreeBusy()
01431 {
01432   KOGroupware::instance()->freeBusyManager()->publishFreeBusy();
01433 }
01434 
01435 void CalendarView::schedule(Scheduler::Method method, Incidence *incidence)
01436 {
01437   if ( !incidence ) {
01438     incidence = selectedIncidence();
01439   }
01440 
01441   if ( !incidence ) {
01442     KMessageBox::sorry( this, i18n("No item selected."),
01443                         "ScheduleNoEventSelected" );
01444     return;
01445   }
01446 
01447   if( incidence->attendeeCount() == 0 && method != Scheduler::Publish ) {
01448     KMessageBox::information( this, i18n("The item has no attendees."),
01449                               "ScheduleNoIncidences" );
01450     return;
01451   }
01452 
01453   Incidence *inc = incidence->clone();
01454   inc->registerObserver( 0 );
01455   inc->clearAttendees();
01456 
01457   // Send the mail
01458   KCal::MailScheduler scheduler( mCalendar );
01459   if ( !scheduler.performTransaction( incidence, method ) ) {
01460     KMessageBox::information( this, i18n("The groupware message for item '%1'"
01461                                 "was successfully sent.\nMethod: %2")
01462                                 .arg( incidence->summary() )
01463                                 .arg( Scheduler::methodName( method ) ),
01464                               i18n("Sending Free/Busy"),
01465                               "FreeBusyPublishSuccess" );
01466   } else {
01467     KMessageBox::error( this, i18n("Groupware message sending failed. "
01468                         "%2 is request/reply/add/cancel/counter/etc.",
01469                         "Unable to send the item '%1'.\nMethod: %2")
01470                         .arg( incidence->summary() )
01471                         .arg( Scheduler::methodName( method ) ) );
01472   }
01473 }
01474 
01475 void CalendarView::openAddressbook()
01476 {
01477   KRun::runCommand("kaddressbook");
01478 }
01479 
01480 void CalendarView::setModified(bool modified)
01481 {
01482   if (mModified != modified) {
01483     mModified = modified;
01484     emit modifiedChanged(mModified);
01485   }
01486 }
01487 
01488 bool CalendarView::isReadOnly()
01489 {
01490   return mReadOnly;
01491 }
01492 
01493 void CalendarView::setReadOnly(bool readOnly)
01494 {
01495   if (mReadOnly != readOnly) {
01496     mReadOnly = readOnly;
01497     emit readOnlyChanged(mReadOnly);
01498   }
01499 }
01500 
01501 bool CalendarView::isModified()
01502 {
01503   return mModified;
01504 }
01505 
01506 void CalendarView::print()
01507 {
01508 #ifndef KORG_NOPRINTER
01509   KOCoreHelper helper;
01510   CalPrinter printer( this, mCalendar, &helper );
01511   connect( this, SIGNAL(configChanged()), &printer, SLOT(updateConfig()) );
01512 
01513   KOrg::BaseView *currentView = mViewManager->currentView();
01514 
01515   CalPrinterBase::PrintType printType = CalPrinterBase::Month;
01516   if ( currentView ) printType = currentView->printType();
01517 
01518   DateList tmpDateList = mNavigator->selectedDates();
01519   Incidence::List selectedIncidences;
01520   if ( mViewManager->currentView() ) {
01521     selectedIncidences = mViewManager->currentView()->selectedIncidences();
01522   }
01523   printer.print( printType, tmpDateList.first(), tmpDateList.last(), selectedIncidences );
01524 #endif
01525 }
01526 
01527 void CalendarView::exportWeb()
01528 {
01529   // FIXME: Get rid of the settings object. When can I delete it???
01530   HTMLExportSettings *settings = new HTMLExportSettings( "KOrganizer" );
01531   // Manually read in the config, because parametrized kconfigxt objects don't
01532   // seem to load the config theirselves
01533   if ( settings ) settings->readConfig();
01534   ExportWebDialog *dlg = new ExportWebDialog( settings, this );
01535   connect( dlg,  SIGNAL( exportHTML( HTMLExportSettings* ) ),
01536            this, SIGNAL( exportHTML( HTMLExportSettings* ) ) );
01537   dlg->show();
01538 }
01539 
01540 void CalendarView::exportICalendar()
01541 {
01542   QString filename = KFileDialog::getSaveFileName("icalout.ics",i18n("*.ics|ICalendars"),this);
01543 
01544   // Force correct extension
01545   if (filename.right(4) != ".ics") filename += ".ics";
01546 
01547   FileStorage storage( mCalendar, filename, new ICalFormat );
01548   storage.save();
01549 }
01550 
01551 void CalendarView::exportVCalendar()
01552 {
01553   if (mCalendar->journals().count() > 0) {
01554     int result = KMessageBox::warningContinueCancel(this,
01555         i18n("The journal entries can not be exported to a vCalendar file."),
01556         i18n("Data Loss Warning"),i18n("Proceed"),"dontaskVCalExport",
01557         true);
01558     if (result != KMessageBox::Continue) return;
01559   }
01560 
01561   QString filename = KFileDialog::getSaveFileName("vcalout.vcs",i18n("*.vcs|vCalendars"),this);
01562 
01563     // TODO: I don't like forcing extensions:
01564   // Force correct extension
01565   if (filename.right(4) != ".vcs") filename += ".vcs";
01566 
01567   FileStorage storage( mCalendar, filename, new VCalFormat );
01568   storage.save();
01569 }
01570 
01571 void CalendarView::eventUpdated(Incidence *)
01572 {
01573   setModified();
01574   // Don't call updateView here. The code, which has caused the update of the
01575   // event is responsible for updating the view.
01576 //  updateView();
01577 }
01578 
01579 void CalendarView::adaptNavigationUnits()
01580 {
01581   if (mViewManager->currentView()->isEventView()) {
01582     int days = mViewManager->currentView()->currentDateCount();
01583     if (days == 1) {
01584       emit changeNavStringPrev(i18n("&Previous Day"));
01585       emit changeNavStringNext(i18n("&Next Day"));
01586     } else {
01587       emit changeNavStringPrev(i18n("&Previous Week"));
01588       emit changeNavStringNext(i18n("&Next Week"));
01589     }
01590   }
01591 }
01592 
01593 void CalendarView::processMainViewSelection( Incidence *incidence )
01594 {
01595   if ( incidence ) mTodoList->clearSelection();
01596   processIncidenceSelection( incidence );
01597 }
01598 
01599 void CalendarView::processTodoListSelection( Incidence *incidence )
01600 {
01601   if ( incidence && mViewManager->currentView() ) {
01602     mViewManager->currentView()->clearSelection();
01603   }
01604   processIncidenceSelection( incidence );
01605 }
01606 
01607 void CalendarView::processIncidenceSelection( Incidence *incidence )
01608 {
01609   if ( incidence == mSelectedIncidence ) return;
01610 
01611   mSelectedIncidence = incidence;
01612 
01613   emit incidenceSelected( mSelectedIncidence );
01614   bool organizerEvents = false;
01615   bool groupEvents = false;
01616   bool todo = false;
01617   bool subtodo = false;
01618 
01619   if ( incidence ) {
01620     organizerEvents = KOPrefs::instance()->thatIsMe( incidence->organizer().email() );
01621     groupEvents = incidence->attendeeByMails( KOPrefs::instance()->allEmails() );
01622 
01623     if ( incidence && incidence->type() == "Todo" ) {
01624       todo = true;
01625       subtodo = ( incidence->relatedTo() != 0 );
01626     }
01627   }
01628   emit todoSelected( todo );
01629   emit subtodoSelected( subtodo );
01630   emit organizerEventsSelected( organizerEvents );
01631   emit groupEventsSelected( groupEvents );
01632 }
01633 
01634 
01635 void CalendarView::checkClipboard()
01636 {
01637 #ifndef KORG_NODND
01638   if (ICalDrag::canDecode(QApplication::clipboard()->data())) {
01639     kdDebug(5850) << "CalendarView::checkClipboard() true" << endl;
01640     emit pasteEnabled(true);
01641   } else {
01642     kdDebug(5850) << "CalendarView::checkClipboard() false" << endl;
01643     emit pasteEnabled(false);
01644   }
01645 #endif
01646 }
01647 
01648 void CalendarView::showDates(const DateList &selectedDates)
01649 {
01650 //  kdDebug(5850) << "CalendarView::selectDates()" << endl;
01651 
01652   if ( mViewManager->currentView() ) {
01653     updateView( selectedDates.first(), selectedDates.last() );
01654   } else {
01655     mViewManager->showAgendaView();
01656   }
01657 }
01658 
01659 void CalendarView::editFilters()
01660 {
01661   kdDebug(5850) << "CalendarView::editFilters()" << endl;
01662 
01663   CalFilter *filter = mFilters.first();
01664   while(filter) {
01665     kdDebug(5850) << " Filter: " << filter->name() << endl;
01666     filter = mFilters.next();
01667   }
01668 
01669   mDialogManager->showFilterEditDialog(&mFilters);
01670 }
01671 
01674 void CalendarView::updateFilter()
01675 {
01676   QStringList filters;
01677   CalFilter *filter;
01678 
01679   int pos = mFilters.find( mCurrentFilter );
01680   if ( pos < 0 ) {
01681     mCurrentFilter = 0;
01682   }
01683 
01684   filters << i18n("No filter");
01685   for ( filter = mFilters.first(); filter; filter = mFilters.next() ) {
01686     filters << filter->name();
01687   }
01688 
01689   emit newFilterListSignal( filters );
01690   // account for the additional "No filter" at the beginning! if the
01691   // filter is not in the list, pos == -1...
01692   emit selectFilterSignal( pos+1 );
01693   mCalendar->setFilter( mCurrentFilter );
01694   updateView();
01695 }
01696 
01699 void CalendarView::filterActivated( int filterNo )
01700 {
01701   CalFilter *newFilter = 0;
01702   if ( filterNo > 0 && filterNo <= int(mFilters.count()) ) {
01703     newFilter = mFilters.at( filterNo-1 );
01704   }
01705   if ( newFilter != mCurrentFilter ) {
01706     mCurrentFilter = newFilter;
01707     mCalendar->setFilter( mCurrentFilter );
01708     updateView();
01709   }
01710   emit filterChanged();
01711 }
01712 
01713 QString CalendarView::currentFilterName() const
01714 {
01715   if ( mCurrentFilter) {
01716     return mCurrentFilter->name();
01717   } else return i18n("No filter");
01718 }
01719 
01720 void CalendarView::takeOverEvent()
01721 {
01722   Incidence *incidence = currentSelection();
01723 
01724   if (!incidence) return;
01725 
01726   incidence->setOrganizer( Person( KOPrefs::instance()->fullName(),
01727                            KOPrefs::instance()->email() ) );
01728   incidence->recreate();
01729   incidence->setReadOnly(false);
01730 
01731   updateView();
01732 }
01733 
01734 void CalendarView::takeOverCalendar()
01735 {
01736   Incidence::List incidences = mCalendar->rawIncidences();
01737   Incidence::List::Iterator it;
01738 
01739   for ( it = incidences.begin(); it != incidences.end(); ++it ) {
01740     (*it)->setOrganizer( Person( KOPrefs::instance()->fullName(),
01741                          KOPrefs::instance()->email() ) );
01742     (*it)->recreate();
01743     (*it)->setReadOnly(false);
01744   }
01745   updateView();
01746 }
01747 
01748 void CalendarView::showIntro()
01749 {
01750   kdDebug(5850) << "To be implemented." << endl;
01751 }
01752 
01753 void CalendarView::showDateNavigator( bool show )
01754 {
01755   if( show )
01756     mDateNavigator->show();
01757   else
01758     mDateNavigator->hide();
01759 }
01760 
01761 void CalendarView::showTodoView( bool show )
01762 {
01763   if( show )
01764     mTodoList->show();
01765   else
01766     mTodoList->hide();
01767 }
01768 
01769 void CalendarView::showEventViewer( bool show )
01770 {
01771   if( show )
01772     mEventViewer->show();
01773   else
01774     mEventViewer->hide();
01775 }
01776 
01777 
01778 void CalendarView::addView(KOrg::BaseView *view)
01779 {
01780   mViewManager->addView(view);
01781 }
01782 
01783 void CalendarView::showView(KOrg::BaseView *view)
01784 {
01785   mViewManager->showView(view);
01786 }
01787 
01788 void CalendarView::addExtension( CalendarViewExtension::Factory *factory )
01789 {
01790   CalendarViewExtension *extension = factory->create( mLeftSplitter );
01791 
01792   mExtensions.append( extension );
01793 }
01794 
01795 void CalendarView::toggleExpand()
01796 {
01797   showLeftFrame( mLeftFrame->isHidden() );
01798 }
01799 
01800 void CalendarView::showLeftFrame(bool show)
01801 {
01802   if (show) {
01803     mLeftFrame->show();
01804     emit calendarViewExpanded( false );
01805   } else {
01806     mLeftFrame->hide();
01807     emit calendarViewExpanded( true );
01808   }
01809 }
01810 
01811 void CalendarView::calendarModified( bool modified, Calendar * )
01812 {
01813   setModified( modified );
01814 }
01815 
01816 Todo *CalendarView::selectedTodo()
01817 {
01818   Incidence *incidence = currentSelection();
01819   if ( incidence && incidence->type() == "Todo" ) {
01820     return static_cast<Todo *>( incidence );
01821   }
01822   incidence = 0;
01823 
01824   Incidence::List selectedIncidences = mTodoList->selectedIncidences();
01825   if ( !selectedIncidences.isEmpty() ) incidence = selectedIncidences.first();
01826   if ( incidence && incidence->type() == "Todo" ) {
01827     return static_cast<Todo *>( incidence );
01828   }
01829 
01830   return 0;
01831 }
01832 
01833 void CalendarView::dialogClosing( Incidence *in )
01834 {
01835   // FIXME: this doesn't work, because if it's a new incidence, it's not locked!
01836   mChanger->endChange( in );
01837   mDialogList.remove( in );
01838 }
01839 
01840 Incidence *CalendarView::currentSelection()
01841 {
01842   return mViewManager->currentSelection();
01843 }
01844 
01845 Incidence* CalendarView::selectedIncidence()
01846 {
01847   Incidence *incidence = currentSelection();
01848   if ( !incidence ) {
01849     Incidence::List selectedIncidences = mTodoList->selectedIncidences();
01850     if ( !selectedIncidences.isEmpty() )
01851       incidence = selectedIncidences.first();
01852   }
01853   return incidence;
01854 }
01855 
01856 void CalendarView::showIncidence()
01857 {
01858   showIncidence( selectedIncidence() );
01859 }
01860 
01861 void CalendarView::editIncidence()
01862 {
01863   editIncidence( selectedIncidence() );
01864 }
01865 
01866 bool CalendarView::editIncidence( const QString& uid )
01867 {
01868   kdDebug(5850) << "CalendarView::editIncidence()" << endl;
01869   return editIncidence( mCalendar->incidence( uid ) );
01870 }
01871 
01872 void CalendarView::deleteIncidence()
01873 {
01874   deleteIncidence( selectedIncidence() );
01875 }
01876 
01877 void CalendarView::cutIncidence(Incidence *)
01878 {
01879   edit_cut();
01880 }
01881 
01882 void CalendarView::copyIncidence(Incidence *)
01883 {
01884   edit_copy();
01885 }
01886 
01887 void CalendarView::showIncidence( Incidence *incidence )
01888 {
01889   KOEventViewerDialog *eventViewer = new KOEventViewerDialog( this );
01890   eventViewer->setIncidence( incidence );
01891   eventViewer->show();
01892 }
01893 
01894 bool CalendarView::editIncidence( Incidence *incidence )
01895 {
01896   kdDebug(5850) << "CalendarView::editEvent()" << endl;
01897 
01898   if ( !incidence || !mChanger ) {
01899     KNotifyClient::beep();
01900     return false;
01901   }
01902   KOIncidenceEditor *tmp = editorDialog( incidence );
01903   if ( tmp ) {
01904     kdDebug(5850) << "CalendarView::editIncidence() in List" << endl;
01905     tmp->reload();
01906     tmp->raise();
01907     tmp->show();
01908     return true;
01909   }
01910 
01911   if ( incidence->isReadOnly() ) {
01912     showIncidence( incidence );
01913     return true;
01914   }
01915 
01916   if ( !mChanger->beginChange( incidence ) ) {
01917     warningChangeFailed( incidence );
01918     showIncidence( incidence );
01919     return false;
01920   }
01921 
01922   kdDebug(5850) << "CalendarView::editIncidence() new IncidenceEditor" << endl;
01923   KOIncidenceEditor *incidenceEditor = mDialogManager->getEditor( incidence );
01924   connectIncidenceEditor( incidenceEditor );
01925 
01926   mDialogList.insert( incidence, incidenceEditor );
01927   incidenceEditor->editIncidence( incidence );
01928   incidenceEditor->show();
01929   return true;
01930 }
01931 
01932 void CalendarView::deleteSubTodosIncidence ( Todo *todo )
01933 {
01934   if( !todo ) return;
01935 
01936   Incidence::List subTodos( todo->relations() );
01937   Incidence::List::Iterator it;
01938   Incidence *aIncidence;
01939   Todo *aTodo;
01940 
01941   for ( it= subTodos.begin(); it != subTodos.end(); ++it ) {
01942     aIncidence = *it;
01943     if( aIncidence && aIncidence->type() == "Todo" ) {
01944       aTodo = static_cast<Todo*>( aIncidence );
01945       deleteSubTodosIncidence ( aTodo );
01946     }
01947   }
01948   mChanger->deleteIncidence ( todo );
01949 }
01950 
01951 void CalendarView::deleteTodoIncidence ( Todo *todo, bool force )
01952 {
01953   if ( !todo ) return ;
01954 
01955   // it a simple todo, ask and delete it.
01956   if (todo->relations().isEmpty() ) {
01957     bool doDelete = true;
01958     if ( !force && KOPrefs::instance()->mConfirm ) {
01959       doDelete = ( msgItemDelete( todo ) == KMessageBox::Continue );
01960     }
01961     if ( doDelete )
01962       mChanger->deleteIncidence( todo );
01963     return;
01964   }
01965 
01966   /* Ok, this to-do has sub-to-dos, ask what to do */
01967   int km = KMessageBox::No;
01968   if ( !force ) {
01969     km=KMessageBox::questionYesNoCancel( this,
01970                                 i18n("The item \"%1\" has sub-to-dos. "
01971                                      "Do you want to delete just this item and "
01972                                      "make all its sub-to-dos independent, or "
01973                                      "delete the to-do with all its sub-to-dos?"
01974                                 ).arg( todo->summary() ),
01975                                 i18n("KOrganizer Confirmation"),
01976                                 i18n("Delete Only This"),
01977                                 i18n("Delete All"));
01978   }
01979   startMultiModify( i18n("Deleting sub-to-dos" ) );
01980   // Delete only the father
01981   if( km == KMessageBox::Yes ) {
01982 
01983     makeSubTodosIndependents ( todo );
01984     mChanger->deleteIncidence( todo );
01985   } else if ( km == KMessageBox::No ) {
01986     // Delete all
01987     // we have to hide the delete confirmation for each itemDate
01988     deleteSubTodosIncidence ( todo );
01989   }
01990   endMultiModify();
01991 }
01992 
01993 void CalendarView::deleteIncidence(Incidence *incidence, bool force)
01994 {
01995   if ( !incidence || !mChanger ) {
01996     if ( !force ) {
01997       KNotifyClient::beep();
01998     }
01999     return;
02000   }
02001   if ( incidence->isReadOnly() ) {
02002     if ( !force ) {
02003       KMessageBox::information( this, i18n("The item \"%1\" is marked read-only "
02004                                 "and cannot be deleted; it probably belongs to "
02005                                 "a read-only calendar resource.")
02006                                 .arg(incidence->summary()),
02007                                 i18n("Removing not possible"),
02008                                 "deleteReadOnlyIncidence" );
02009     }
02010     return;
02011   }
02012 
02013   CanDeleteIncidenceVisitor v;
02014 
02015   // Let the visitor do special things for special incidence types.
02016   // e.g. todos with children cannot be deleted, so act(..) returns false
02017   if ( !v.act( incidence, this ) )
02018     return;
02019   //If it is a todo, there are specific delete function
02020 
02021   if ( incidence && incidence->type()=="Todo" ) {
02022     deleteTodoIncidence( static_cast<Todo*>(incidence), force );
02023     return;
02024   }
02025 
02026   if ( incidence->doesRecur() ) {
02027     QDate itemDate = mViewManager->currentSelectionDate();
02028     kdDebug(5850) << "Recurrence-Date: " << itemDate.toString() << endl;
02029     int km = KMessageBox::Ok;
02030     if ( !force ) {
02031       if ( !itemDate.isValid() ) {
02032         kdDebug(5850) << "Date Not Valid" << endl;
02033         km = KMessageBox::warningContinueCancel(this,
02034           i18n("The calendar item \"%1\" recurs over multiple dates; "
02035                "are you sure you want to delete it "
02036                "and all its recurrences?").arg( incidence->summary() ),
02037                i18n("KOrganizer Confirmation"), i18n("Delete All") );
02038       } else {
02039         km = KOMessageBox::fourBtnMsgBox( this, QMessageBox::Warning,
02040           i18n("The calendar item \"%1\" recurs over multiple dates. "
02041                "Do you want to delete only the current one on %2, only all "
02042                "future recurrences, or all its recurrences?" )
02043                .arg( incidence->summary() )
02044                .arg( KGlobal::locale()->formatDate(itemDate)),
02045                i18n("KOrganizer Confirmation"), i18n("Delete C&urrent"),
02046                i18n("Delete &Future"),
02047                i18n("Delete &All"));
02048       }
02049     }
02050     switch(km) {
02051       case KMessageBox::Ok: // Continue // all
02052       case KMessageBox::Continue:
02053         mChanger->deleteIncidence( incidence );
02054         break;
02055 
02056       case KMessageBox::Yes: // just this one
02057         if ( mChanger->beginChange( incidence ) ) {
02058           Incidence *oldIncidence = incidence->clone();
02059           incidence->recurrence()->addExDate( itemDate );
02060           mChanger->changeIncidence( oldIncidence, incidence );
02061           mChanger->endChange( incidence );
02062           delete oldIncidence;
02063         }
02064         break;
02065       case KMessageBox::No: // all future items
02066         if ( mChanger->beginChange( incidence ) ) {
02067           Incidence *oldIncidence = incidence->clone();
02068           Recurrence *recur = incidence->recurrence();
02069           recur->setEndDate( itemDate.addDays(-1) );
02070           mChanger->changeIncidence( oldIncidence, incidence );
02071           mChanger->endChange( incidence );
02072           delete oldIncidence;
02073         }
02074         break;
02075     }
02076   } else {
02077     bool doDelete = true;
02078     if ( !force && KOPrefs::instance()->mConfirm ) {
02079       doDelete = ( msgItemDelete( incidence ) == KMessageBox::Continue );
02080     }
02081     if ( doDelete ) {
02082       mChanger->deleteIncidence( incidence );
02083       processIncidenceSelection( 0 );
02084     }
02085   }
02086 }
02087 
02088 void CalendarView::connectIncidenceEditor( KOIncidenceEditor *editor )
02089 {
02090   connect( this, SIGNAL( newIncidenceChanger( IncidenceChangerBase* ) ),
02091            editor, SLOT( setIncidenceChanger( IncidenceChangerBase* ) ) );
02092   editor->setIncidenceChanger( mChanger );
02093 }
02094 
02095 bool CalendarView::purgeCompletedSubTodos( Todo* todo, bool &allPurged )
02096 {
02097   if ( !todo ) return true;
02098   bool deleteThisTodo = true;
02099   Incidence::List subTodos( todo->relations() );
02100   Incidence *aIncidence;
02101   Todo *aTodo;
02102   Incidence::List::Iterator it;
02103   for ( it = subTodos.begin(); it != subTodos.end(); ++it ) {
02104     aIncidence = *it;
02105     if ( aIncidence && aIncidence->type()=="Todo" ) {
02106       aTodo = static_cast<Todo*>( aIncidence );
02107       deleteThisTodo &= purgeCompletedSubTodos( aTodo, allPurged );
02108     }
02109   }
02110 
02111   if ( deleteThisTodo ) {
02112     if ( todo->isCompleted() ) {
02113       if ( !mChanger->deleteIncidence( todo ) )
02114         allPurged = false;
02115     } else {
02116       deleteThisTodo = false;
02117     }
02118   } else {
02119     if ( todo->isCompleted() ) {
02120       allPurged = false;
02121     }
02122   }
02123   return deleteThisTodo;
02124 }
02125 
02126 void CalendarView::purgeCompleted()
02127 {
02128   int result = KMessageBox::warningContinueCancel(this,
02129       i18n("Delete all completed to-dos?"),i18n("Purge To-dos"),i18n("Purge"));
02130 
02131   if (result == KMessageBox::Continue) {
02132     bool allDeleted = true;
02133     startMultiModify( i18n("Purging completed to-dos") );
02134     Todo::List todos = calendar()->rawTodos();
02135     Todo::List rootTodos;
02136     Todo::List::ConstIterator it;
02137     for ( it = todos.begin(); it != todos.end(); ++it ) {
02138       Todo *aTodo = *it;
02139       if ( aTodo && !aTodo->relatedTo() )
02140         rootTodos.append( aTodo );
02141     }
02142     // now that we have a list of all root todos, check them and their children
02143     for ( it = rootTodos.begin(); it != rootTodos.end(); ++it ) {
02144       purgeCompletedSubTodos( *it, allDeleted );
02145     }
02146     endMultiModify();
02147     if ( !allDeleted ) {
02148       KMessageBox::information( this, i18n("Unable to purge to-dos with "
02149                                 "uncompleted children."), i18n("Delete To-do"),
02150                                 "UncompletedChildrenPurgeTodos" );
02151     }
02152   }
02153 }
02154 
02155 void CalendarView::slotCalendarChanged()
02156 {
02157   kdDebug(5850) << "CalendarView::slotCalendarChanged()" << endl;
02158 
02159   updateView();
02160 }
02161 
02162 void CalendarView::warningChangeFailed( Incidence * )
02163 {
02164   KMessageBox::sorry( this, i18n("Unable to edit item: "
02165                                  "it is locked by another process.") );
02166 }
02167 
02168 void CalendarView::editCanceled( Incidence *i )
02169 {
02170   mCalendar->endChange( i );
02171 }
02172 
02173 void CalendarView::showErrorMessage( const QString &msg )
02174 {
02175   KMessageBox::error( this, msg );
02176 }
02177 
02178 void CalendarView::updateCategories()
02179 {
02180   QStringList allCats( calendar()->categories() );
02181   allCats.sort();
02182   QStringList categories( KOPrefs::instance()->mCustomCategories );
02183   for ( QStringList::ConstIterator si = allCats.constBegin(); si != allCats.constEnd(); ++si ) {
02184     if ( categories.find( *si ) == categories.end() ) {
02185       categories.append( *si );
02186     }
02187   }
02188   KOPrefs::instance()->mCustomCategories = categories;
02189   KOPrefs::instance()->writeConfig();
02190   // Make the category editor update the list!
02191   emit categoriesChanged();
02192 }
02193 
02194 void CalendarView::addIncidenceOn( Incidence *incadd, const QDate &dt )
02195 {
02196   if ( !incadd || !mChanger ) {
02197     KMessageBox::sorry(this, i18n("Unable to copy the item to %1.")
02198                        .arg( dt.toString() ), i18n("Copying Failed") );
02199     return;
02200   }
02201   Incidence *incidence = mCalendar->incidence( incadd->uid() );
02202   if ( !incidence ) incidence = incadd;
02203   // Create a copy of the incidence, since the incadd doesn't belong to us.
02204   incidence = incidence->clone();
02205   incidence->recreate();
02206 
02207   if ( incidence->type() == "Event" ) {
02208     Event *event = static_cast<Event*>(incidence);
02209 
02210     // Adjust date
02211     QDateTime start = event->dtStart();
02212     QDateTime end = event->dtEnd();
02213 
02214     int duration = start.daysTo( end );
02215     start.setDate( dt );
02216     end.setDate( dt.addDays( duration ) );
02217 
02218     event->setDtStart( start );
02219     event->setDtEnd( end );
02220 
02221   } else if ( incidence->type() == "Todo" ) {
02222     Todo *todo = static_cast<Todo*>(incidence);
02223     QDateTime due = todo->dtDue();
02224     due.setDate( dt );
02225 
02226     todo->setDtDue( due );
02227     todo->setHasDueDate( true );
02228   }
02229 
02230   if ( !mChanger->addIncidence( incidence, this ) ) {
02231     KODialogManager::errorSaveIncidence( this, incidence );
02232     delete incidence;
02233   }
02234 }
02235 
02236 void CalendarView::moveIncidenceTo( Incidence *incmove, const QDate &dt )
02237 {
02238   if ( !incmove || !mChanger ) {
02239     KMessageBox::sorry( this, i18n("Unable to move the item to %1.")
02240                         .arg( dt.toString() ), i18n("Moving Failed") );
02241     return;
02242   }
02243   Incidence *incidence = mCalendar->incidence( incmove->uid() );
02244   if ( !incidence ) {
02245     addIncidenceOn( incidence, dt );
02246     return;
02247   }
02248   Incidence *oldIncidence = incidence->clone();
02249   if ( !mChanger->beginChange( incidence ) ) {
02250     delete oldIncidence;
02251     return;
02252   }
02253 
02254   if ( incidence->type() == "Event" ) {
02255     Event *event = static_cast<Event*>(incidence);
02256 
02257     // Adjust date
02258     QDateTime start = event->dtStart();
02259     QDateTime end = event->dtEnd();
02260 
02261     int duration = start.daysTo( end );
02262     start.setDate( dt );
02263     end.setDate( dt.addDays( duration ) );
02264 
02265     event->setDtStart( start );
02266     event->setDtEnd( end );
02267 
02268   } else if ( incidence->type() == "Todo" ) {
02269     Todo *todo = static_cast<Todo*>(incidence);
02270     QDateTime due = todo->dtDue();
02271     due.setDate( dt );
02272 
02273     todo->setDtDue( due );
02274     todo->setHasDueDate( true );
02275   }
02276   mChanger->changeIncidence( oldIncidence, incidence );
02277   mChanger->endChange( incidence );
02278   delete oldIncidence;
02279 }
02280 
02281 #include "calendarview.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys