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     if ( incidence->organizer().isEmpty() ) {
01391       incidence->setOrganizer( Person( KOPrefs::instance()->fullName(),
01392                                        KOPrefs::instance()->email() ) );
01393     }
01394 
01395     ICalFormat format;
01396     QString messageText = format.createScheduleMessage( incidence, Scheduler::Request );
01397     KOMailClient mailer;
01398     if ( mailer.mailTo( incidence, recipients, messageText ) ) {
01399 
01400       KMessageBox::information( this, i18n("The item information was successfully sent."),
01401                                 i18n("Forwarding"), "IncidenceForwardSuccess" );
01402     } else {
01403       KMessageBox::error( this, i18n("Unable to forward the item '%1'").arg( incidence->summary() ) );
01404     }
01405   }
01406 }
01407 
01408 void CalendarView::mailFreeBusy( int daysToPublish )
01409 {
01410   QDateTime start = QDateTime::currentDateTime();
01411   QDateTime end = start.addDays(daysToPublish);
01412 
01413   FreeBusy *freebusy = new FreeBusy(mCalendar, start, end);
01414   freebusy->setOrganizer( Person( KOPrefs::instance()->fullName(),
01415                       KOPrefs::instance()->email() ) );
01416 
01417   kdDebug(5850) << "calendarview: schedule_publish_freebusy: startDate: "
01418      << KGlobal::locale()->formatDateTime( start ) << " End Date: "
01419      << KGlobal::locale()->formatDateTime( end ) << endl;
01420 
01421   PublishDialog *publishdlg = new PublishDialog();
01422   if ( publishdlg->exec() == QDialog::Accepted ) {
01423     // Send the mail
01424     KCal::MailScheduler scheduler( mCalendar );
01425     if ( scheduler.publish( freebusy, publishdlg->addresses() ) ) {
01426       KMessageBox::information( this, i18n("The free/busy information was successfully sent."),
01427                                 i18n("Sending Free/Busy"), "FreeBusyPublishSuccess" );
01428     } else {
01429       KMessageBox::error( this, i18n("Unable to publish the free/busy data.") );
01430     }
01431   }
01432   delete freebusy;
01433   delete publishdlg;
01434 }
01435 
01436 void CalendarView::uploadFreeBusy()
01437 {
01438   KOGroupware::instance()->freeBusyManager()->publishFreeBusy();
01439 }
01440 
01441 void CalendarView::schedule(Scheduler::Method method, Incidence *incidence)
01442 {
01443   if ( !incidence ) {
01444     incidence = selectedIncidence();
01445   }
01446 
01447   if ( !incidence ) {
01448     KMessageBox::sorry( this, i18n("No item selected."),
01449                         "ScheduleNoEventSelected" );
01450     return;
01451   }
01452 
01453   if( incidence->attendeeCount() == 0 && method != Scheduler::Publish ) {
01454     KMessageBox::information( this, i18n("The item has no attendees."),
01455                               "ScheduleNoIncidences" );
01456     return;
01457   }
01458 
01459   Incidence *inc = incidence->clone();
01460   inc->registerObserver( 0 );
01461   inc->clearAttendees();
01462 
01463   // Send the mail
01464   KCal::MailScheduler scheduler( mCalendar );
01465   if ( scheduler.performTransaction( incidence, method ) ) {
01466     KMessageBox::information( this, i18n("The groupware message for item '%1'"
01467                                 "was successfully sent.\nMethod: %2")
01468                                 .arg( incidence->summary() )
01469                                 .arg( Scheduler::methodName( method ) ),
01470                               i18n("Sending Free/Busy"),
01471                               "FreeBusyPublishSuccess" );
01472   } else {
01473     KMessageBox::error( this, i18n("Groupware message sending failed. "
01474                         "%2 is request/reply/add/cancel/counter/etc.",
01475                         "Unable to send the item '%1'.\nMethod: %2")
01476                         .arg( incidence->summary() )
01477                         .arg( Scheduler::methodName( method ) ) );
01478   }
01479 }
01480 
01481 void CalendarView::openAddressbook()
01482 {
01483   KRun::runCommand("kaddressbook");
01484 }
01485 
01486 void CalendarView::setModified(bool modified)
01487 {
01488   if (mModified != modified) {
01489     mModified = modified;
01490     emit modifiedChanged(mModified);
01491   }
01492 }
01493 
01494 bool CalendarView::isReadOnly()
01495 {
01496   return mReadOnly;
01497 }
01498 
01499 void CalendarView::setReadOnly(bool readOnly)
01500 {
01501   if (mReadOnly != readOnly) {
01502     mReadOnly = readOnly;
01503     emit readOnlyChanged(mReadOnly);
01504   }
01505 }
01506 
01507 bool CalendarView::isModified()
01508 {
01509   return mModified;
01510 }
01511 
01512 void CalendarView::print()
01513 {
01514 #ifndef KORG_NOPRINTER
01515   KOCoreHelper helper;
01516   CalPrinter printer( this, mCalendar, &helper );
01517   connect( this, SIGNAL(configChanged()), &printer, SLOT(updateConfig()) );
01518 
01519   KOrg::BaseView *currentView = mViewManager->currentView();
01520 
01521   CalPrinterBase::PrintType printType = CalPrinterBase::Month;
01522   if ( currentView ) printType = currentView->printType();
01523 
01524   DateList tmpDateList = mNavigator->selectedDates();
01525   Incidence::List selectedIncidences;
01526   if ( mViewManager->currentView() ) {
01527     selectedIncidences = mViewManager->currentView()->selectedIncidences();
01528   }
01529   printer.print( printType, tmpDateList.first(), tmpDateList.last(), selectedIncidences );
01530 #endif
01531 }
01532 
01533 void CalendarView::exportWeb()
01534 {
01535   // FIXME: Get rid of the settings object. When can I delete it???
01536   HTMLExportSettings *settings = new HTMLExportSettings( "KOrganizer" );
01537   // Manually read in the config, because parametrized kconfigxt objects don't
01538   // seem to load the config theirselves
01539   if ( settings ) settings->readConfig();
01540   ExportWebDialog *dlg = new ExportWebDialog( settings, this );
01541   connect( dlg,  SIGNAL( exportHTML( HTMLExportSettings* ) ),
01542            this, SIGNAL( exportHTML( HTMLExportSettings* ) ) );
01543   dlg->show();
01544 }
01545 
01546 void CalendarView::exportICalendar()
01547 {
01548   QString filename = KFileDialog::getSaveFileName("icalout.ics",i18n("*.ics|ICalendars"),this);
01549   if ( !filename.isEmpty() )
01550   {
01551     // Force correct extension
01552     if (filename.right(4) != ".ics") filename += ".ics";
01553     if ( QFile( filename ).exists() ) {
01554       if ( KMessageBox::No == KMessageBox::warningYesNo(
01555              this,
01556              i18n( "Do you want to overwrite %1?").arg(filename) ) ) {
01557           return;
01558       }
01559     }
01560     FileStorage storage( mCalendar, filename, new ICalFormat );
01561     storage.save();
01562   }
01563 }
01564 
01565 void CalendarView::exportVCalendar()
01566 {
01567   if (mCalendar->journals().count() > 0) {
01568     int result = KMessageBox::warningContinueCancel(this,
01569         i18n("The journal entries can not be exported to a vCalendar file."),
01570         i18n("Data Loss Warning"),i18n("Proceed"),"dontaskVCalExport",
01571         true);
01572     if (result != KMessageBox::Continue) return;
01573   }
01574 
01575   QString filename = KFileDialog::getSaveFileName("vcalout.vcs",i18n("*.vcs|vCalendars"),this);
01576   if ( !filename.isEmpty() )
01577   {
01578     // TODO: I don't like forcing extensions:
01579     // Force correct extension
01580     if (filename.right(4) != ".vcs") filename += ".vcs";
01581     if ( QFile( filename ).exists() ) {
01582       if ( KMessageBox::No == KMessageBox::warningYesNo(
01583              this,
01584              i18n( "Do you want to overwrite %1?").arg(filename ) ) ) {
01585              return;
01586       }
01587     }
01588     FileStorage storage( mCalendar, filename, new VCalFormat );
01589     storage.save();
01590   }
01591 }
01592 
01593 void CalendarView::eventUpdated(Incidence *)
01594 {
01595   setModified();
01596   // Don't call updateView here. The code, which has caused the update of the
01597   // event is responsible for updating the view.
01598 //  updateView();
01599 }
01600 
01601 void CalendarView::adaptNavigationUnits()
01602 {
01603   if (mViewManager->currentView()->isEventView()) {
01604     int days = mViewManager->currentView()->currentDateCount();
01605     if (days == 1) {
01606       emit changeNavStringPrev(i18n("&Previous Day"));
01607       emit changeNavStringNext(i18n("&Next Day"));
01608     } else {
01609       emit changeNavStringPrev(i18n("&Previous Week"));
01610       emit changeNavStringNext(i18n("&Next Week"));
01611     }
01612   }
01613 }
01614 
01615 void CalendarView::processMainViewSelection( Incidence *incidence )
01616 {
01617   if ( incidence ) mTodoList->clearSelection();
01618   processIncidenceSelection( incidence );
01619 }
01620 
01621 void CalendarView::processTodoListSelection( Incidence *incidence )
01622 {
01623   if ( incidence && mViewManager->currentView() ) {
01624     mViewManager->currentView()->clearSelection();
01625   }
01626   processIncidenceSelection( incidence );
01627 }
01628 
01629 void CalendarView::processIncidenceSelection( Incidence *incidence )
01630 {
01631   if ( incidence == mSelectedIncidence ) return;
01632 
01633   mSelectedIncidence = incidence;
01634 
01635   emit incidenceSelected( mSelectedIncidence );
01636   bool organizerEvents = false;
01637   bool groupEvents = false;
01638   bool todo = false;
01639   bool subtodo = false;
01640 
01641   if ( incidence ) {
01642     organizerEvents = KOPrefs::instance()->thatIsMe( incidence->organizer().email() );
01643     groupEvents = incidence->attendeeByMails( KOPrefs::instance()->allEmails() );
01644 
01645     if ( incidence && incidence->type() == "Todo" ) {
01646       todo = true;
01647       subtodo = ( incidence->relatedTo() != 0 );
01648     }
01649   }
01650   emit todoSelected( todo );
01651   emit subtodoSelected( subtodo );
01652   emit organizerEventsSelected( organizerEvents );
01653   emit groupEventsSelected( groupEvents );
01654 }
01655 
01656 
01657 void CalendarView::checkClipboard()
01658 {
01659 #ifndef KORG_NODND
01660   if (ICalDrag::canDecode(QApplication::clipboard()->data())) {
01661     kdDebug(5850) << "CalendarView::checkClipboard() true" << endl;
01662     emit pasteEnabled(true);
01663   } else {
01664     kdDebug(5850) << "CalendarView::checkClipboard() false" << endl;
01665     emit pasteEnabled(false);
01666   }
01667 #endif
01668 }
01669 
01670 void CalendarView::showDates(const DateList &selectedDates)
01671 {
01672 //  kdDebug(5850) << "CalendarView::selectDates()" << endl;
01673 
01674   if ( mViewManager->currentView() ) {
01675     updateView( selectedDates.first(), selectedDates.last() );
01676   } else {
01677     mViewManager->showAgendaView();
01678   }
01679 }
01680 
01681 void CalendarView::editFilters()
01682 {
01683   kdDebug(5850) << "CalendarView::editFilters()" << endl;
01684 
01685   CalFilter *filter = mFilters.first();
01686   while(filter) {
01687     kdDebug(5850) << " Filter: " << filter->name() << endl;
01688     filter = mFilters.next();
01689   }
01690 
01691   mDialogManager->showFilterEditDialog(&mFilters);
01692 }
01693 
01696 void CalendarView::updateFilter()
01697 {
01698   QStringList filters;
01699   CalFilter *filter;
01700 
01701   int pos = mFilters.find( mCurrentFilter );
01702   if ( pos < 0 ) {
01703     mCurrentFilter = 0;
01704   }
01705 
01706   filters << i18n("No filter");
01707   for ( filter = mFilters.first(); filter; filter = mFilters.next() ) {
01708     filters << filter->name();
01709   }
01710 
01711   emit newFilterListSignal( filters );
01712   // account for the additional "No filter" at the beginning! if the
01713   // filter is not in the list, pos == -1...
01714   emit selectFilterSignal( pos+1 );
01715   mCalendar->setFilter( mCurrentFilter );
01716   updateView();
01717 }
01718 
01721 void CalendarView::filterActivated( int filterNo )
01722 {
01723   CalFilter *newFilter = 0;
01724   if ( filterNo > 0 && filterNo <= int(mFilters.count()) ) {
01725     newFilter = mFilters.at( filterNo-1 );
01726   }
01727   if ( newFilter != mCurrentFilter ) {
01728     mCurrentFilter = newFilter;
01729     mCalendar->setFilter( mCurrentFilter );
01730     updateView();
01731   }
01732   emit filterChanged();
01733 }
01734 
01735 QString CalendarView::currentFilterName() const
01736 {
01737   if ( mCurrentFilter) {
01738     return mCurrentFilter->name();
01739   } else return i18n("No filter");
01740 }
01741 
01742 void CalendarView::takeOverEvent()
01743 {
01744   Incidence *incidence = currentSelection();
01745 
01746   if (!incidence) return;
01747 
01748   incidence->setOrganizer( Person( KOPrefs::instance()->fullName(),
01749                            KOPrefs::instance()->email() ) );
01750   incidence->recreate();
01751   incidence->setReadOnly(false);
01752 
01753   updateView();
01754 }
01755 
01756 void CalendarView::takeOverCalendar()
01757 {
01758   Incidence::List incidences = mCalendar->rawIncidences();
01759   Incidence::List::Iterator it;
01760 
01761   for ( it = incidences.begin(); it != incidences.end(); ++it ) {
01762     (*it)->setOrganizer( Person( KOPrefs::instance()->fullName(),
01763                          KOPrefs::instance()->email() ) );
01764     (*it)->recreate();
01765     (*it)->setReadOnly(false);
01766   }
01767   updateView();
01768 }
01769 
01770 void CalendarView::showIntro()
01771 {
01772   kdDebug(5850) << "To be implemented." << endl;
01773 }
01774 
01775 void CalendarView::showDateNavigator( bool show )
01776 {
01777   if( show )
01778     mDateNavigator->show();
01779   else
01780     mDateNavigator->hide();
01781 }
01782 
01783 void CalendarView::showTodoView( bool show )
01784 {
01785   if( show )
01786     mTodoList->show();
01787   else
01788     mTodoList->hide();
01789 }
01790 
01791 void CalendarView::showEventViewer( bool show )
01792 {
01793   if( show )
01794     mEventViewer->show();
01795   else
01796     mEventViewer->hide();
01797 }
01798 
01799 
01800 void CalendarView::addView(KOrg::BaseView *view)
01801 {
01802   mViewManager->addView(view);
01803 }
01804 
01805 void CalendarView::showView(KOrg::BaseView *view)
01806 {
01807   mViewManager->showView(view);
01808 }
01809 
01810 void CalendarView::addExtension( CalendarViewExtension::Factory *factory )
01811 {
01812   CalendarViewExtension *extension = factory->create( mLeftSplitter );
01813 
01814   mExtensions.append( extension );
01815 }
01816 
01817 void CalendarView::toggleExpand()
01818 {
01819   showLeftFrame( mLeftFrame->isHidden() );
01820 }
01821 
01822 void CalendarView::showLeftFrame(bool show)
01823 {
01824   if (show) {
01825     mLeftFrame->show();
01826     emit calendarViewExpanded( false );
01827   } else {
01828     mLeftFrame->hide();
01829     emit calendarViewExpanded( true );
01830   }
01831 }
01832 
01833 void CalendarView::calendarModified( bool modified, Calendar * )
01834 {
01835   setModified( modified );
01836 }
01837 
01838 Todo *CalendarView::selectedTodo()
01839 {
01840   Incidence *incidence = currentSelection();
01841   if ( incidence && incidence->type() == "Todo" ) {
01842     return static_cast<Todo *>( incidence );
01843   }
01844   incidence = 0;
01845 
01846   Incidence::List selectedIncidences = mTodoList->selectedIncidences();
01847   if ( !selectedIncidences.isEmpty() ) incidence = selectedIncidences.first();
01848   if ( incidence && incidence->type() == "Todo" ) {
01849     return static_cast<Todo *>( incidence );
01850   }
01851 
01852   return 0;
01853 }
01854 
01855 void CalendarView::dialogClosing( Incidence *in )
01856 {
01857   // FIXME: this doesn't work, because if it's a new incidence, it's not locked!
01858   mChanger->endChange( in );
01859   mDialogList.remove( in );
01860 }
01861 
01862 Incidence *CalendarView::currentSelection()
01863 {
01864   return mViewManager->currentSelection();
01865 }
01866 
01867 Incidence* CalendarView::selectedIncidence()
01868 {
01869   Incidence *incidence = currentSelection();
01870   if ( !incidence ) {
01871     Incidence::List selectedIncidences = mTodoList->selectedIncidences();
01872     if ( !selectedIncidences.isEmpty() )
01873       incidence = selectedIncidences.first();
01874   }
01875   return incidence;
01876 }
01877 
01878 void CalendarView::showIncidence()
01879 {
01880   showIncidence( selectedIncidence() );
01881 }
01882 
01883 void CalendarView::editIncidence()
01884 {
01885   editIncidence( selectedIncidence() );
01886 }
01887 
01888 bool CalendarView::editIncidence( const QString& uid )
01889 {
01890   kdDebug(5850) << "CalendarView::editIncidence()" << endl;
01891   return editIncidence( mCalendar->incidence( uid ) );
01892 }
01893 
01894 void CalendarView::deleteIncidence()
01895 {
01896   deleteIncidence( selectedIncidence() );
01897 }
01898 
01899 void CalendarView::cutIncidence(Incidence *)
01900 {
01901   edit_cut();
01902 }
01903 
01904 void CalendarView::copyIncidence(Incidence *)
01905 {
01906   edit_copy();
01907 }
01908 
01909 void CalendarView::pasteIncidence()
01910 {
01911   edit_paste();
01912 }
01913 
01914 void CalendarView::showIncidence( Incidence *incidence )
01915 {
01916   KOEventViewerDialog *eventViewer = new KOEventViewerDialog( this );
01917   eventViewer->setIncidence( incidence );
01918   eventViewer->show();
01919 }
01920 
01921 bool CalendarView::editIncidence( Incidence *incidence, bool isCounter )
01922 {
01923   kdDebug(5850) << "CalendarView::editEvent()" << endl;
01924 
01925   if ( !incidence || !mChanger ) {
01926     KNotifyClient::beep();
01927     return false;
01928   }
01929   KOIncidenceEditor *tmp = editorDialog( incidence );
01930   if ( tmp ) {
01931     kdDebug(5850) << "CalendarView::editIncidence() in List" << endl;
01932     tmp->reload();
01933     tmp->raise();
01934     tmp->show();
01935     return true;
01936   }
01937 
01938   if ( incidence->isReadOnly() ) {
01939     showIncidence( incidence );
01940     return true;
01941   }
01942 
01943   if ( !isCounter && !mChanger->beginChange( incidence ) ) {
01944     warningChangeFailed( incidence );
01945     showIncidence( incidence );
01946     return false;
01947   }
01948 
01949   kdDebug(5850) << "CalendarView::editIncidence() new IncidenceEditor" << endl;
01950   KOIncidenceEditor *incidenceEditor = mDialogManager->getEditor( incidence );
01951   connectIncidenceEditor( incidenceEditor );
01952 
01953   mDialogList.insert( incidence, incidenceEditor );
01954   incidenceEditor->editIncidence( incidence, mCalendar );
01955   incidenceEditor->show();
01956   return true;
01957 }
01958 
01959 void CalendarView::deleteSubTodosIncidence ( Todo *todo )
01960 {
01961   if( !todo ) return;
01962 
01963   Incidence::List subTodos( todo->relations() );
01964   Incidence::List::Iterator it;
01965   Incidence *aIncidence;
01966   Todo *aTodo;
01967 
01968   for ( it= subTodos.begin(); it != subTodos.end(); ++it ) {
01969     aIncidence = *it;
01970     if( aIncidence && aIncidence->type() == "Todo" ) {
01971       aTodo = static_cast<Todo*>( aIncidence );
01972       deleteSubTodosIncidence ( aTodo );
01973     }
01974   }
01975   mChanger->deleteIncidence ( todo );
01976 }
01977 
01978 void CalendarView::deleteTodoIncidence ( Todo *todo, bool force )
01979 {
01980   if ( !todo ) return ;
01981 
01982   // it a simple todo, ask and delete it.
01983   if (todo->relations().isEmpty() ) {
01984     bool doDelete = true;
01985     if ( !force && KOPrefs::instance()->mConfirm ) {
01986       doDelete = ( msgItemDelete( todo ) == KMessageBox::Continue );
01987     }
01988     if ( doDelete )
01989       mChanger->deleteIncidence( todo );
01990     return;
01991   }
01992 
01993   /* Ok, this to-do has sub-to-dos, ask what to do */
01994   int km = KMessageBox::No;
01995   if ( !force ) {
01996     km=KMessageBox::questionYesNoCancel( this,
01997                                 i18n("The item \"%1\" has sub-to-dos. "
01998                                      "Do you want to delete just this item and "
01999                                      "make all its sub-to-dos independent, or "
02000                                      "delete the to-do with all its sub-to-dos?"
02001                                 ).arg( todo->summary() ),
02002                                 i18n("KOrganizer Confirmation"),
02003                                 i18n("Delete Only This"),
02004                                 i18n("Delete All"));
02005   }
02006   startMultiModify( i18n("Deleting sub-to-dos" ) );
02007   // Delete only the father
02008   if( km == KMessageBox::Yes ) {
02009 
02010     makeSubTodosIndependents ( todo );
02011     mChanger->deleteIncidence( todo );
02012   } else if ( km == KMessageBox::No ) {
02013     // Delete all
02014     // we have to hide the delete confirmation for each itemDate
02015     deleteSubTodosIncidence ( todo );
02016   }
02017   endMultiModify();
02018 }
02019 
02020 void CalendarView::deleteIncidence(Incidence *incidence, bool force)
02021 {
02022   if ( !incidence || !mChanger ) {
02023     if ( !force ) {
02024       KNotifyClient::beep();
02025     }
02026     return;
02027   }
02028   if ( incidence->isReadOnly() ) {
02029     if ( !force ) {
02030       KMessageBox::information( this, i18n("The item \"%1\" is marked read-only "
02031                                 "and cannot be deleted; it probably belongs to "
02032                                 "a read-only calendar resource.")
02033                                 .arg(incidence->summary()),
02034                                 i18n("Removing not possible"),
02035                                 "deleteReadOnlyIncidence" );
02036     }
02037     return;
02038   }
02039 
02040   CanDeleteIncidenceVisitor v;
02041 
02042   // Let the visitor do special things for special incidence types.
02043   // e.g. todos with children cannot be deleted, so act(..) returns false
02044   if ( !v.act( incidence, this ) )
02045     return;
02046   //If it is a todo, there are specific delete function
02047 
02048   if ( incidence && incidence->type()=="Todo" ) {
02049     deleteTodoIncidence( static_cast<Todo*>(incidence), force );
02050     return;
02051   }
02052 
02053   if ( incidence->doesRecur() ) {
02054     QDate itemDate = mViewManager->currentSelectionDate();
02055     kdDebug(5850) << "Recurrence-Date: " << itemDate.toString() << endl;
02056     int km = KMessageBox::Ok;
02057     if ( !force ) {
02058       if ( !itemDate.isValid() ) {
02059         kdDebug(5850) << "Date Not Valid" << endl;
02060         km = KMessageBox::warningContinueCancel(this,
02061           i18n("The calendar item \"%1\" recurs over multiple dates; "
02062                "are you sure you want to delete it "
02063                "and all its recurrences?").arg( incidence->summary() ),
02064                i18n("KOrganizer Confirmation"), i18n("Delete All") );
02065       } else {
02066         km = KOMessageBox::fourBtnMsgBox( this, QMessageBox::Warning,
02067           i18n("The calendar item \"%1\" recurs over multiple dates. "
02068                "Do you want to delete only the current one on %2, only all "
02069                "future recurrences, or all its recurrences?" )
02070                .arg( incidence->summary() )
02071                .arg( KGlobal::locale()->formatDate(itemDate)),
02072                i18n("KOrganizer Confirmation"), i18n("Delete C&urrent"),
02073                i18n("Delete &Future"),
02074                i18n("Delete &All"));
02075       }
02076     }
02077     switch(km) {
02078       case KMessageBox::Ok: // Continue // all
02079       case KMessageBox::Continue:
02080         mChanger->deleteIncidence( incidence );
02081         break;
02082 
02083       case KMessageBox::Yes: // just this one
02084         if ( mChanger->beginChange( incidence ) ) {
02085           Incidence *oldIncidence = incidence->clone();
02086           incidence->recurrence()->addExDate( itemDate );
02087           mChanger->changeIncidence( oldIncidence, incidence );
02088           mChanger->endChange( incidence );
02089           delete oldIncidence;
02090         }
02091         break;
02092       case KMessageBox::No: // all future items
02093         if ( mChanger->beginChange( incidence ) ) {
02094           Incidence *oldIncidence = incidence->clone();
02095           Recurrence *recur = incidence->recurrence();
02096           recur->setEndDate( itemDate.addDays(-1) );
02097           mChanger->changeIncidence( oldIncidence, incidence );
02098           mChanger->endChange( incidence );
02099           delete oldIncidence;
02100         }
02101         break;
02102     }
02103   } else {
02104     bool doDelete = true;
02105     if ( !force && KOPrefs::instance()->mConfirm ) {
02106       doDelete = ( msgItemDelete( incidence ) == KMessageBox::Continue );
02107     }
02108     if ( doDelete ) {
02109       mChanger->deleteIncidence( incidence );
02110       processIncidenceSelection( 0 );
02111     }
02112   }
02113 }
02114 
02115 void CalendarView::connectIncidenceEditor( KOIncidenceEditor *editor )
02116 {
02117   connect( this, SIGNAL( newIncidenceChanger( IncidenceChangerBase* ) ),
02118            editor, SLOT( setIncidenceChanger( IncidenceChangerBase* ) ) );
02119   editor->setIncidenceChanger( mChanger );
02120 }
02121 
02122 bool CalendarView::purgeCompletedSubTodos( Todo* todo, bool &allPurged )
02123 {
02124   if ( !todo ) return true;
02125   bool deleteThisTodo = true;
02126   Incidence::List subTodos( todo->relations() );
02127   Incidence *aIncidence;
02128   Todo *aTodo;
02129   Incidence::List::Iterator it;
02130   for ( it = subTodos.begin(); it != subTodos.end(); ++it ) {
02131     aIncidence = *it;
02132     if ( aIncidence && aIncidence->type()=="Todo" ) {
02133       aTodo = static_cast<Todo*>( aIncidence );
02134       deleteThisTodo &= purgeCompletedSubTodos( aTodo, allPurged );
02135     }
02136   }
02137 
02138   if ( deleteThisTodo ) {
02139     if ( todo->isCompleted() ) {
02140       if ( !mChanger->deleteIncidence( todo ) )
02141         allPurged = false;
02142     } else {
02143       deleteThisTodo = false;
02144     }
02145   } else {
02146     if ( todo->isCompleted() ) {
02147       allPurged = false;
02148     }
02149   }
02150   return deleteThisTodo;
02151 }
02152 
02153 void CalendarView::purgeCompleted()
02154 {
02155   int result = KMessageBox::warningContinueCancel(this,
02156       i18n("Delete all completed to-dos?"),i18n("Purge To-dos"),i18n("Purge"));
02157 
02158   if (result == KMessageBox::Continue) {
02159     bool allDeleted = true;
02160     startMultiModify( i18n("Purging completed to-dos") );
02161     Todo::List todos = calendar()->rawTodos();
02162     Todo::List rootTodos;
02163     Todo::List::ConstIterator it;
02164     for ( it = todos.begin(); it != todos.end(); ++it ) {
02165       Todo *aTodo = *it;
02166       if ( aTodo && !aTodo->relatedTo() )
02167         rootTodos.append( aTodo );
02168     }
02169     // now that we have a list of all root todos, check them and their children
02170     for ( it = rootTodos.begin(); it != rootTodos.end(); ++it ) {
02171       purgeCompletedSubTodos( *it, allDeleted );
02172     }
02173     endMultiModify();
02174     if ( !allDeleted ) {
02175       KMessageBox::information( this, i18n("Unable to purge to-dos with "
02176                                 "uncompleted children."), i18n("Delete To-do"),
02177                                 "UncompletedChildrenPurgeTodos" );
02178     }
02179   }
02180 }
02181 
02182 void CalendarView::warningChangeFailed( Incidence * )
02183 {
02184   KMessageBox::sorry( this, i18n("Unable to edit item: "
02185                                  "it is locked by another process.") );
02186 }
02187 
02188 void CalendarView::editCanceled( Incidence *i )
02189 {
02190   mCalendar->endChange( i );
02191 }
02192 
02193 void CalendarView::showErrorMessage( const QString &msg )
02194 {
02195   KMessageBox::error( this, msg );
02196 }
02197 
02198 void CalendarView::updateCategories()
02199 {
02200   QStringList allCats( calendar()->categories() );
02201   allCats.sort();
02202   QStringList categories( KOPrefs::instance()->mCustomCategories );
02203   for ( QStringList::ConstIterator si = allCats.constBegin(); si != allCats.constEnd(); ++si ) {
02204     if ( categories.find( *si ) == categories.end() ) {
02205       categories.append( *si );
02206     }
02207   }
02208   KOPrefs::instance()->mCustomCategories = categories;
02209   KOPrefs::instance()->writeConfig();
02210   // Make the category editor update the list!
02211   emit categoriesChanged();
02212 }
02213 
02214 void CalendarView::addIncidenceOn( Incidence *incadd, const QDate &dt )
02215 {
02216   if ( !incadd || !mChanger ) {
02217     KMessageBox::sorry(this, i18n("Unable to copy the item to %1.")
02218                        .arg( dt.toString() ), i18n("Copying Failed") );
02219     return;
02220   }
02221   Incidence *incidence = mCalendar->incidence( incadd->uid() );
02222   if ( !incidence ) incidence = incadd;
02223   // Create a copy of the incidence, since the incadd doesn't belong to us.
02224   incidence = incidence->clone();
02225   incidence->recreate();
02226 
02227   if ( incidence->type() == "Event" ) {
02228     Event *event = static_cast<Event*>(incidence);
02229 
02230     // Adjust date
02231     QDateTime start = event->dtStart();
02232     QDateTime end = event->dtEnd();
02233 
02234     int duration = start.daysTo( end );
02235     start.setDate( dt );
02236     end.setDate( dt.addDays( duration ) );
02237 
02238     event->setDtStart( start );
02239     event->setDtEnd( end );
02240 
02241   } else if ( incidence->type() == "Todo" ) {
02242     Todo *todo = static_cast<Todo*>(incidence);
02243     QDateTime due = todo->dtDue();
02244     due.setDate( dt );
02245 
02246     todo->setDtDue( due );
02247     todo->setHasDueDate( true );
02248   }
02249 
02250   if ( !mChanger->addIncidence( incidence, this ) ) {
02251     KODialogManager::errorSaveIncidence( this, incidence );
02252     delete incidence;
02253   }
02254 }
02255 
02256 void CalendarView::moveIncidenceTo( Incidence *incmove, const QDate &dt )
02257 {
02258   if ( !incmove || !mChanger ) {
02259     KMessageBox::sorry( this, i18n("Unable to move the item to %1.")
02260                         .arg( dt.toString() ), i18n("Moving Failed") );
02261     return;
02262   }
02263   Incidence *incidence = mCalendar->incidence( incmove->uid() );
02264   if ( !incidence ) {
02265     addIncidenceOn( incidence, dt );
02266     return;
02267   }
02268   Incidence *oldIncidence = incidence->clone();
02269   if ( !mChanger->beginChange( incidence ) ) {
02270     delete oldIncidence;
02271     return;
02272   }
02273 
02274   if ( incidence->type() == "Event" ) {
02275     Event *event = static_cast<Event*>(incidence);
02276 
02277     // Adjust date
02278     QDateTime start = event->dtStart();
02279     QDateTime end = event->dtEnd();
02280 
02281     int duration = start.daysTo( end );
02282     start.setDate( dt );
02283     end.setDate( dt.addDays( duration ) );
02284 
02285     event->setDtStart( start );
02286     event->setDtEnd( end );
02287 
02288   } else if ( incidence->type() == "Todo" ) {
02289     Todo *todo = static_cast<Todo*>(incidence);
02290     QDateTime due = todo->dtDue();
02291     due.setDate( dt );
02292 
02293     todo->setDtDue( due );
02294     todo->setHasDueDate( true );
02295   }
02296   mChanger->changeIncidence( oldIncidence, incidence );
02297   mChanger->endChange( incidence );
02298   delete oldIncidence;
02299 }
02300 
02301 void CalendarView::resourcesChanged()
02302 {
02303   mViewManager->resourcesChanged();
02304   updateView();
02305 }
02306 
02307 #include "calendarview.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys