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