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