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