00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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 mDateNavigator = new DateNavigator( this );
00135 mDateChecker = new DateChecker( this );
00136
00137 QBoxLayout *topLayout = new QVBoxLayout( this );
00138
00139 #ifndef KORG_NOSPLITTER
00140
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
00148
00149 mDateNavigatorContainer = new DateNavigatorContainer( mLeftSplitter,
00150 "CalendarView::DateNavigator" );
00151
00152
00153 mLeftSplitter->setCollapsible( mDateNavigatorContainer, 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 mDateNavigatorContainer = 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
00198 mTodoList->setFixedHeight( mDateNavigatorContainer->sizeHint().height() );
00199 }
00200 #endif
00201
00202 connect( mDateNavigator, SIGNAL( datesSelected( const KCal::DateList & ) ),
00203 SLOT( showDates( const KCal::DateList & ) ) );
00204 connect( mDateNavigator, SIGNAL( datesSelected( const KCal::DateList & ) ),
00205 mDateNavigatorContainer, SLOT( selectDates( const KCal::DateList & ) ) );
00206
00207 connect( mNavigatorBar, SIGNAL( goPrevYear() ),
00208 mDateNavigator, SLOT( selectPreviousYear() ) );
00209 connect( mNavigatorBar, SIGNAL( goNextYear() ),
00210 mDateNavigator, SLOT( selectNextYear() ) );
00211 connect( mNavigatorBar, SIGNAL( goPrevMonth() ),
00212 mDateNavigator, SLOT( selectPreviousMonth() ) );
00213 connect( mNavigatorBar, SIGNAL( goNextMonth() ),
00214 mDateNavigator, SLOT( selectNextMonth() ) );
00215 connect( mNavigatorBar, SIGNAL( goMonth(int) ),
00216 mDateNavigator, SLOT( selectMonth(int) ) );
00217 connect( mNavigatorBar, SIGNAL(goYear(int)),
00218 mDateNavigator, SLOT(selectYear(int)) );
00219
00220 connect( mDateNavigator, SIGNAL( datesSelected( const KCal::DateList & ) ),
00221 mNavigatorBar, SLOT( selectDates( const KCal::DateList & ) ) );
00222
00223 connect( mDateNavigatorContainer, SIGNAL( weekClicked( const QDate & ) ),
00224 this, SLOT( selectWeek( const QDate & ) ) );
00225
00226 connect( mDateNavigatorContainer, SIGNAL( goPrevYear() ),
00227 mDateNavigator, SLOT( selectPreviousYear() ) );
00228 connect( mDateNavigatorContainer, SIGNAL( goNextYear() ),
00229 mDateNavigator, SLOT( selectNextYear() ) );
00230 connect( mDateNavigatorContainer, SIGNAL( goPrevMonth() ),
00231 mDateNavigator, SLOT( selectPreviousMonth() ) );
00232 connect( mDateNavigatorContainer, SIGNAL( goNextMonth() ),
00233 mDateNavigator, SLOT( selectNextMonth() ) );
00234 connect( mDateNavigatorContainer, SIGNAL( goMonth(int) ),
00235 mDateNavigator, SLOT( selectMonth(int) ) );
00236 connect( mDateNavigatorContainer, SIGNAL(goYear(int)),
00237 mDateNavigator, SLOT(selectYear(int)) );
00238
00239 connect( mDateNavigatorContainer, SIGNAL( goPrevious() ),
00240 mDateNavigator, SLOT( selectPrevious() ) );
00241 connect( mDateNavigatorContainer, SIGNAL( goNext() ),
00242 mDateNavigator, SLOT( selectNext() ) );
00243
00244 connect( mDateNavigatorContainer, SIGNAL( datesSelected( const KCal::DateList & ) ),
00245 mDateNavigator, SLOT( selectDates( const KCal::DateList & ) ) );
00246
00247 connect( mDateNavigatorContainer, SIGNAL(incidenceDropped(Incidence*, const QDate&)),
00248 SLOT( addIncidenceOn( Incidence *, const QDate & ) ) );
00249 connect( mDateNavigatorContainer, SIGNAL(incidenceDroppedMove(Incidence*,const QDate&)),
00250 SLOT( moveIncidenceTo( Incidence *, const QDate & ) ) );
00251
00252 connect( mDateChecker, SIGNAL( dayPassed( const QDate & ) ),
00253 mTodoList, SLOT( dayPassed( const QDate & ) ) );
00254 connect( mDateChecker, SIGNAL( dayPassed( const QDate & ) ),
00255 SIGNAL( dayPassed( const QDate & ) ) );
00256 connect( mDateChecker, SIGNAL( dayPassed( const QDate & ) ),
00257 mDateNavigatorContainer, SLOT( updateToday() ) );
00258
00259 connect( this, SIGNAL( configChanged() ),
00260 mDateNavigatorContainer, SLOT( updateConfig() ) );
00261
00262 connect( this, SIGNAL( incidenceSelected(Incidence *, const QDate &) ),
00263 mEventViewer, SLOT ( setIncidence (Incidence *, const QDate &) ) );
00264
00265
00266 QString s;
00267 s = i18n( "<p><em>No Item Selected</em></p>"
00268 "<p>Select an event, to-do or journal entry to view its details "
00269 "here.</p>");
00270
00271 mEventViewer->setDefaultText( s );
00272 QWhatsThis::add( mEventViewer,
00273 i18n( "View the details of events, journal entries or to-dos "
00274 "selected in KOrganizer's main view here." ) );
00275 mEventViewer->setIncidence( 0, QDate() );
00276
00277 mViewManager->connectTodoView( mTodoList );
00278 mViewManager->connectView( mTodoList );
00279
00280 KOGlobals::self()->
00281 setHolidays( new KHolidays( KOPrefs::instance()->mHolidays ) );
00282
00283 connect( QApplication::clipboard(), SIGNAL( dataChanged() ),
00284 SLOT( checkClipboard() ) );
00285
00286 connect( mTodoList, SIGNAL( incidenceSelected( Incidence *,const QDate & ) ),
00287 SLOT( processTodoListSelection( Incidence *,const QDate & ) ) );
00288 disconnect( mTodoList, SIGNAL( incidenceSelected( Incidence *,const QDate & ) ),
00289 this, SLOT( processMainViewSelection( Incidence *,const QDate & ) ) );
00290
00291 kdDebug(5850) << "CalendarView::CalendarView() done" << endl;
00292 }
00293
00294 CalendarView::~CalendarView()
00295 {
00296 kdDebug(5850) << "~CalendarView()" << endl;
00297
00298 mCalendar->unregisterObserver( this );
00299
00300 delete mDialogManager;
00301 delete mViewManager;
00302 delete mEventViewer;
00303 kdDebug(5850) << "~CalendarView() done" << endl;
00304 }
00305
00306 void CalendarView::setCalendar( Calendar *cal )
00307 {
00308 kdDebug(5850)<<"CalendarView::setCalendar"<<endl;
00309 mCalendar = cal;
00310
00311 delete mHistory;
00312 mHistory = new History( mCalendar );
00313 connect( mHistory, SIGNAL( undone() ), SLOT( updateView() ) );
00314 connect( mHistory, SIGNAL( redone() ), SLOT( updateView() ) );
00315
00316 if ( mChanger ) delete mChanger;
00317 setIncidenceChanger( new IncidenceChanger( mCalendar, this ) );
00318
00319 mCalendar->registerObserver( this );
00320
00321 mDateNavigatorContainer->setCalendar( mCalendar );
00322
00323 mTodoList->setCalendar( mCalendar );
00324
00325 mEventViewer->setCalendar( mCalendar );
00326 }
00327
00328 void CalendarView::setIncidenceChanger( IncidenceChangerBase *changer )
00329 {
00330 mChanger = changer;
00331 emit newIncidenceChanger( mChanger );
00332 connect( mChanger, SIGNAL( incidenceAdded( Incidence* ) ),
00333 this, SLOT( incidenceAdded( Incidence* ) ) );
00334 connect( mChanger, SIGNAL( incidenceChanged( Incidence*, Incidence*, KOGlobals::WhatChanged ) ),
00335 this, SLOT( incidenceChanged( Incidence*, Incidence*, KOGlobals::WhatChanged ) ) );
00336 connect( mChanger, SIGNAL( incidenceToBeDeleted( Incidence * ) ),
00337 this, SLOT( incidenceToBeDeleted( Incidence * ) ) );
00338 connect( mChanger, SIGNAL( incidenceDeleted( Incidence * ) ),
00339 this, SLOT( incidenceDeleted( Incidence * ) ) );
00340
00341 connect( mChanger, SIGNAL( schedule( Scheduler::Method, Incidence*) ),
00342 this, SLOT( schedule( Scheduler::Method, Incidence*) ) );
00343
00344
00345 connect( this, SIGNAL( cancelAttendees( Incidence * ) ),
00346 mChanger, SLOT( cancelAttendees( Incidence * ) ) );
00347 }
00348
00349 Calendar *CalendarView::calendar()
00350 {
00351 if ( mCalendar ) return mCalendar;
00352 else return CalendarNull::self();
00353 }
00354
00355 QPair<ResourceCalendar *, QString> CalendarView::viewSubResourceCalendar()
00356 {
00357 QPair<ResourceCalendar *, QString> p( 0, QString() );
00358 KOrg::BaseView *cV = mViewManager->currentView();
00359 if ( cV && cV == mViewManager->multiAgendaView() ) {
00360 cV = mViewManager->multiAgendaView()->selectedAgendaView();
00361 }
00362 if ( cV ) {
00363 p = qMakePair( cV->resourceCalendar(), cV->subResourceCalendar() );
00364 }
00365 return p;
00366 }
00367
00368 KOIncidenceEditor *CalendarView::editorDialog( Incidence *incidence ) const
00369 {
00370 if (mDialogList.find(incidence) != mDialogList.end ())
00371 return mDialogList[incidence];
00372 else return 0;
00373 }
00374
00375 QDate CalendarView::activeDate( bool fallbackToToday )
00376 {
00377 KOrg::BaseView *curView = mViewManager->currentView();
00378 if ( curView ) {
00379 if ( curView->selectionStart().isValid() ) {
00380 return curView->selectionStart().date();
00381 }
00382
00383
00384 if ( !curView->selectedIncidenceDates().isEmpty() ) {
00385 if ( curView->selectedIncidenceDates().first().isValid() ) {
00386 return curView->selectedIncidenceDates().first();
00387 }
00388 }
00389 }
00390
00391
00392 if ( fallbackToToday ) {
00393 return QDate::currentDate();
00394 } else {
00395 return mDateNavigator->selectedDates().first();
00396 }
00397 }
00398
00399 QDate CalendarView::activeIncidenceDate()
00400 {
00401 KOrg::BaseView *curView = mViewManager->currentView();
00402 if ( curView ) {
00403 DateList dates = curView->selectedIncidenceDates();
00404 if ( !dates.isEmpty() ) {
00405 return dates.first();
00406 }
00407 }
00408
00409 return QDate();
00410 }
00411
00412 QDate CalendarView::startDate()
00413 {
00414 DateList dates = mDateNavigator->selectedDates();
00415
00416 return dates.first();
00417 }
00418
00419 QDate CalendarView::endDate()
00420 {
00421 DateList dates = mDateNavigator->selectedDates();
00422
00423 return dates.last();
00424 }
00425
00426
00427 bool CalendarView::openCalendar(const QString& filename, bool merge)
00428 {
00429 kdDebug(5850) << "CalendarView::openCalendar(): " << filename << endl;
00430
00431 if (filename.isEmpty()) {
00432 kdDebug(5850) << "CalendarView::openCalendar(): Error! Empty filename." << endl;
00433 return false;
00434 }
00435
00436 if (!QFile::exists(filename)) {
00437 kdDebug(5850) << "CalendarView::openCalendar(): Error! File '" << filename
00438 << "' doesn't exist." << endl;
00439 }
00440
00441 bool loadedSuccesfully = true;
00442 if ( !merge ) {
00443 mCalendar->close();
00444 CalendarLocal *cl = dynamic_cast<CalendarLocal*>( mCalendar );
00445 if ( cl ) {
00446 loadedSuccesfully = cl->load( filename );
00447 } else {
00448 CalendarResources *cr = dynamic_cast<CalendarResources*>( mCalendar );
00449 assert( cr );
00450
00451 return false;
00452 }
00453 } else {
00454
00455 FileStorage storage( mCalendar );
00456 storage.setFileName( filename );
00457 loadedSuccesfully = storage.load();
00458 }
00459
00460 if ( loadedSuccesfully ) {
00461 if ( merge )
00462 setModified( true );
00463 else {
00464 setModified( false );
00465 mViewManager->setDocumentId( filename );
00466 mTodoList->setDocumentId( filename );
00467 }
00468 updateCategories();
00469 updateView();
00470 return true;
00471 } else {
00472
00473
00474 if ( !merge ) mCalendar->close();
00475
00476 KMessageBox::error(this,i18n("Could not load calendar '%1'.").arg(filename));
00477
00478 return false;
00479 }
00480 }
00481
00482 bool CalendarView::saveCalendar( const QString& filename )
00483 {
00484 kdDebug(5850) << "CalendarView::saveCalendar(): " << filename << endl;
00485
00486
00487 mViewManager->currentView()->flushView();
00488
00489 FileStorage storage( mCalendar );
00490 storage.setFileName( filename );
00491 storage.setSaveFormat( new ICalFormat );
00492
00493 bool success = storage.save();
00494
00495 if ( !success ) {
00496 return false;
00497 }
00498
00499 return true;
00500 }
00501
00502 void CalendarView::closeCalendar()
00503 {
00504 kdDebug(5850) << "CalendarView::closeCalendar()" << endl;
00505
00506
00507 emit closingDown();
00508
00509 mCalendar->close();
00510 setModified( false );
00511 updateView();
00512 }
00513
00514 void CalendarView::archiveCalendar()
00515 {
00516 mDialogManager->showArchiveDialog();
00517 }
00518
00519
00520 void CalendarView::readSettings()
00521 {
00522
00523
00524 QString str;
00525
00526
00527
00528
00529 KConfig *config = KOGlobals::self()->config();
00530
00531 #ifndef KORG_NOSPLITTER
00532 config->setGroup( "KOrganizer Geometry" );
00533
00534 QValueList<int> sizes = config->readIntListEntry( "Separator1" );
00535 if ( sizes.count() != 2 ) {
00536 sizes << mDateNavigatorContainer->minimumSizeHint().width();
00537 sizes << 300;
00538 }
00539 mPanner->setSizes( sizes );
00540
00541 sizes = config->readIntListEntry( "Separator2" );
00542 mLeftSplitter->setSizes( sizes );
00543 #endif
00544
00545 mEventViewer->readSettings( config );
00546
00547 mViewManager->readSettings( config );
00548 mTodoList->restoreLayout( config, QString( "Todo Layout" ) );
00549
00550 readFilterSettings( config );
00551
00552 config->setGroup( "Views" );
00553 int dateCount = config->readNumEntry( "ShownDatesCount", 7 );
00554 if ( dateCount == 7 ) mDateNavigator->selectWeek();
00555 else mDateNavigator->selectDates( mDateNavigator->selectedDates().first(), dateCount );
00556 }
00557
00558
00559 void CalendarView::writeSettings()
00560 {
00561
00562
00563 KConfig *config = KOGlobals::self()->config();
00564
00565 #ifndef KORG_NOSPLITTER
00566 config->setGroup( "KOrganizer Geometry" );
00567
00568 QValueList<int> list = mPanner->sizes();
00569 config->writeEntry( "Separator1", list );
00570
00571 list = mLeftSplitter->sizes();
00572 config->writeEntry( "Separator2", list );
00573 #endif
00574 mEventViewer->writeSettings( config );
00575 mViewManager->writeSettings( config );
00576 mTodoList->saveLayout( config, QString( "Todo Layout" ) );
00577
00578 KOPrefs::instance()->writeConfig();
00579
00580 writeFilterSettings( config );
00581
00582 config->setGroup( "Views" );
00583 config->writeEntry( "ShownDatesCount", mDateNavigator->selectedDates().count() );
00584
00585 config->sync();
00586 }
00587
00588 void CalendarView::readFilterSettings( KConfig *config )
00589 {
00590
00591
00592 mFilters.clear();
00593
00594 config->setGroup( "General" );
00595
00596 QStringList filterList = config->readListEntry ("CalendarFilters" );
00597 QString currentFilter = config->readEntry( "Current Filter" );
00598
00599 QStringList::ConstIterator it = filterList.begin();
00600 QStringList::ConstIterator end = filterList.end();
00601 while( it != end ) {
00602
00603 CalFilter *filter;
00604 filter = new CalFilter( *it );
00605 config->setGroup( "Filter_" + (*it) );
00606 filter->setCriteria( config->readNumEntry( "Criteria", 0 ) );
00607 filter->setCategoryList( config->readListEntry( "CategoryList" ) );
00608 if ( filter->criteria() & KCal::CalFilter::HideTodosWithoutAttendeeInEmailList )
00609 filter->setEmailList( KOPrefs::instance()->allEmails() );
00610 filter->setCompletedTimeSpan( config->readNumEntry( "HideTodoDays", 0 ) );
00611 mFilters.append( filter );
00612
00613 ++it;
00614 }
00615
00616 config->setGroup( "General" );
00617 int pos = filterList.findIndex( currentFilter );
00618 mCurrentFilter = 0;
00619 if ( pos>=0 ) {
00620 mCurrentFilter = mFilters.at( pos );
00621 }
00622 updateFilter();
00623 }
00624
00625 void CalendarView::writeFilterSettings( KConfig *config )
00626 {
00627
00628
00629 QStringList filterList;
00630
00631 CalFilter *filter = mFilters.first();
00632 while( filter ) {
00633
00634 filterList << filter->name();
00635 config->setGroup( "Filter_" + filter->name() );
00636 config->writeEntry( "Criteria", filter->criteria() );
00637 config->writeEntry( "CategoryList", filter->categoryList() );
00638 config->writeEntry( "HideTodoDays", filter->completedTimeSpan() );
00639 filter = mFilters.next();
00640 }
00641 config->setGroup( "General" );
00642 config->writeEntry( "CalendarFilters", filterList );
00643 if ( mCurrentFilter ) {
00644 config->writeEntry( "Current Filter", mCurrentFilter->name() );
00645 } else {
00646 config->writeEntry( "Current Filter", QString::null );
00647 }
00648 }
00649
00650
00651 void CalendarView::goDate( const QDate &date )
00652 {
00653 mDateNavigator->selectDate( date );
00654 }
00655
00656 void CalendarView::showDate( const QDate &date )
00657 {
00658 int dateCount = mDateNavigator->datesCount();
00659 if ( dateCount == 7 ) {
00660 mDateNavigator->selectWeek( date );
00661 } else {
00662 mDateNavigator->selectDates( date, dateCount );
00663 }
00664 }
00665
00666 void CalendarView::goToday()
00667 {
00668 mDateNavigator->selectToday();
00669 }
00670
00671 void CalendarView::goNext()
00672 {
00673 if ( dynamic_cast<KOMonthView*>( mViewManager->currentView() ) ) {
00674 mDateNavigator->selectNextMonth();
00675 } else {
00676 mDateNavigator->selectNext();
00677 }
00678 }
00679
00680 void CalendarView::goPrevious()
00681 {
00682 if ( dynamic_cast<KOMonthView*>( mViewManager->currentView() ) ) {
00683 mDateNavigator->selectPreviousMonth();
00684 } else {
00685 mDateNavigator->selectPrevious();
00686 }
00687 }
00688
00689 void CalendarView::updateConfig( const QCString& receiver)
00690 {
00691 if ( receiver != "korganizer" ) return;
00692 kdDebug(5850) << "CalendarView::updateConfig()" << endl;
00693
00694 KOGlobals::self()->
00695 setHolidays( new KHolidays( KOPrefs::instance()->mHolidays ) );
00696
00697 QString tz( mCalendar->timeZoneId() );
00698
00699
00700 if ( tz != KOPrefs::instance()->mTimeZoneId ) {
00701
00702 const QString question( i18n("The timezone setting was changed. Do you want to keep the absolute time of "
00703 "the items in your calendar, which will show them to be at a different time than "
00704 "before, or move them to be at the old time also in the new timezone?") );
00705 int rc = KMessageBox::questionYesNo( this, question,
00706 i18n("Keep Absolute Times?"),
00707 KGuiItem(i18n("Keep Times")),
00708 KGuiItem(i18n("Move Times")),
00709 "calendarKeepAbsoluteTimes");
00710 if ( rc == KMessageBox::Yes ) {
00711
00712 mCalendar->setTimeZoneIdViewOnly( KOPrefs::instance()->mTimeZoneId );
00713 } else {
00714
00715
00716 mCalendar->setTimeZoneId( KOPrefs::instance()->mTimeZoneId );
00717 }
00718 }
00719 emit configChanged();
00720
00721
00722 mViewManager->updateMultiCalendarDisplay();
00723
00724
00725 mViewManager->raiseCurrentView();
00726 }
00727
00728
00729 void CalendarView::incidenceAdded( Incidence *incidence )
00730 {
00731 setModified( true );
00732 history()->recordAdd( incidence );
00733 changeIncidenceDisplay( incidence, KOGlobals::INCIDENCEADDED );
00734 updateUnmanagedViews();
00735 checkForFilteredChange( incidence );
00736 }
00737
00738 void CalendarView::incidenceChanged( Incidence *oldIncidence,
00739 Incidence *newIncidence,
00740 KOGlobals::WhatChanged modification )
00741 {
00742 KOIncidenceEditor *tmp = editorDialog( newIncidence );
00743 if ( tmp ) {
00744 kdDebug(5850) << "Incidence modified and open" << endl;
00745 tmp->modified();
00746 }
00747 setModified( true );
00748 history()->recordEdit( oldIncidence, newIncidence );
00749
00750
00751
00752
00753 if ( newIncidence->type() == "Todo" &&
00754 KOPrefs::instance()->recordTodosInJournals() &&
00755 ( modification == KOGlobals::COMPLETION_MODIFIED ||
00756 modification == KOGlobals::COMPLETION_MODIFIED_WITH_RECURRENCE ) ) {
00757
00758 Todo *todo = static_cast<Todo *>(newIncidence);
00759 if ( todo->isCompleted() ||
00760 modification == KOGlobals::COMPLETION_MODIFIED_WITH_RECURRENCE ) {
00761 QString timeStr = KGlobal::locale()->formatTime( QTime::currentTime() );
00762 QString description = i18n( "To-do completed: %1 (%2)" ).arg(
00763 newIncidence->summary() ).arg( timeStr );
00764
00765 Journal::List journals = calendar()->journals( QDate::currentDate() );
00766 Journal *journal;
00767
00768 if ( journals.isEmpty() ) {
00769 journal = new Journal();
00770 journal->setDtStart( QDateTime::currentDateTime() );
00771
00772 QString dateStr = KGlobal::locale()->formatDate( QDate::currentDate() );
00773 journal->setSummary( i18n("Journal of %1").arg( dateStr ) );
00774 journal->setDescription( description );
00775
00776
00777 if ( !mChanger->addIncidence( journal, 0, QString(), this ) ) {
00778 KODialogManager::errorSaveIncidence( this, journal );
00779 delete journal;
00780 return;
00781 }
00782
00783 } else {
00784 journal = *(journals.at(0));
00785 Journal *oldJournal = journal->clone();
00786 journal->setDescription( journal->description().append( "\n" + description ) );
00787
00788 if ( !mChanger->changeIncidence( oldJournal, journal,
00789 KOGlobals::DESCRIPTION_MODIFIED, this ) ) {
00790 KODialogManager::errorSaveIncidence( this, journal );
00791 delete journal;
00792 return;
00793 }
00794 }
00795 }
00796 }
00797
00798 changeIncidenceDisplay( newIncidence, KOGlobals::INCIDENCEEDITED );
00799 updateUnmanagedViews();
00800 checkForFilteredChange( newIncidence );
00801 }
00802
00803 void CalendarView::incidenceToBeDeleted( Incidence *incidence )
00804 {
00805 KOIncidenceEditor *tmp = editorDialog( incidence );
00806 if (tmp) {
00807 kdDebug(5850) << "Incidence to be deleted and open in editor" << endl;
00808 tmp->delayedDestruct();
00809 }
00810 setModified( true );
00811 history()->recordDelete( incidence );
00812
00813 updateUnmanagedViews();
00814 }
00815
00816 void CalendarView::incidenceDeleted( Incidence *incidence )
00817 {
00818 changeIncidenceDisplay( incidence, KOGlobals::INCIDENCEDELETED );
00819 updateUnmanagedViews();
00820 }
00821
00822 void CalendarView::checkForFilteredChange( Incidence *incidence )
00823 {
00824 CalFilter *filter = calendar()->filter();
00825 if ( filter && !filter->filterIncidence( incidence ) ) {
00826
00827
00828 KMessageBox::information( this, i18n("The item \"%1\" is filtered by "
00829 "your current filter rules, so it will be hidden and not "
00830 "appear in the view.").arg( incidence->summary() ),
00831 i18n("Filter Applied"), "ChangedIncidenceFiltered" );
00832 }
00833 }
00834
00835 void CalendarView::startMultiModify( const QString &text )
00836 {
00837 history()->startMultiModify( text );
00838 }
00839
00840 void CalendarView::endMultiModify()
00841 {
00842 history()->endMultiModify();
00843 }
00844
00845
00846 void CalendarView::changeIncidenceDisplay( Incidence *incidence, int action )
00847 {
00848 mDateNavigatorContainer->updateView();
00849 mDialogManager->updateSearchDialog();
00850
00851 if ( incidence ) {
00852
00853 mViewManager->currentView()->changeIncidenceDisplay( incidence, action );
00854 if ( mTodoList ) mTodoList->changeIncidenceDisplay( incidence, action );
00855 mEventViewer->changeIncidenceDisplay( incidence, activeDate( true ), action );
00856 } else {
00857 mViewManager->currentView()->updateView();
00858 if ( mTodoList ) mTodoList->updateView();
00859 }
00860 }
00861
00862
00863 void CalendarView::updateView(const QDate &start, const QDate &end)
00864 {
00865 mTodoList->updateView();
00866 mViewManager->updateView(start, end);
00867 mDateNavigatorContainer->updateView();
00868 }
00869
00870 void CalendarView::updateView()
00871 {
00872 DateList tmpList = mDateNavigator->selectedDates();
00873
00874
00875 updateView( tmpList.first(), tmpList.last() );
00876 }
00877
00878 void CalendarView::updateUnmanagedViews()
00879 {
00880 mDateNavigatorContainer->updateDayMatrix();
00881 }
00882
00883 int CalendarView::msgItemDelete( Incidence *incidence )
00884 {
00885 return KMessageBox::warningContinueCancel(this,
00886 i18n("The item \"%1\" will be permanently deleted.").arg( incidence->summary() ),
00887 i18n("KOrganizer Confirmation"), KGuiItem(i18n("&Delete"),"editdelete"));
00888 }
00889
00890
00891 void CalendarView::edit_cut()
00892 {
00893 Incidence *incidence = incToSendToClipboard( true );
00894
00895 if ( !incidence || !mChanger ) {
00896 KNotifyClient::beep();
00897 return;
00898 }
00899 mChanger->cutIncidence( incidence, this );
00900 }
00901
00902 void CalendarView::edit_copy()
00903 {
00904 Incidence *incidence = incToSendToClipboard( false );
00905
00906 if (!incidence) {
00907 KNotifyClient::beep();
00908 return;
00909 }
00910 DndFactory factory( mCalendar );
00911 if ( !factory.copyIncidence( incidence ) ) {
00912 KNotifyClient::beep();
00913 }
00914 }
00915
00916 Incidence* CalendarView::incToSendToClipboard( bool cut )
00917 {
00918 Incidence *originalInc = selectedIncidence();
00919
00920 if ( originalInc && originalInc->doesRecur() &&
00921 originalInc->type() == "Event" ) {
00922
00923 Incidence *inc;
00924 KOGlobals::WhichOccurrences chosenOption;
00925 if ( cut ) {
00926 inc = singleOccurrenceOrAll( originalInc, KOGlobals::CUT, chosenOption, QDate(), true );
00927 } else {
00928
00929
00930 Incidence *originalIncSaved = originalInc->clone();
00931 inc = singleOccurrenceOrAll( originalIncSaved, KOGlobals::COPY, chosenOption, QDate(), false );
00932
00933
00934 if ( chosenOption == KOGlobals::ALL ) {
00935 inc = originalInc;
00936 delete originalIncSaved;
00937 }
00938
00939
00940 if ( chosenOption == KOGlobals::NONE ) {
00941 delete originalIncSaved;
00942 }
00943 }
00944
00945 return inc;
00946 } else {
00947 return originalInc;
00948 }
00949 }
00950
00951 void CalendarView::edit_paste()
00952 {
00953
00954
00955
00956 QDate date;
00957 bool timeSet = false;
00958 QTime time;
00959 QDateTime endDT;
00960 bool useEndTime = false;
00961
00962 KOrg::BaseView *curView = mViewManager->currentView();
00963 if ( !curView ) {
00964 return;
00965 }
00966
00967 KOAgendaView *aView = mViewManager->agendaView();
00968 KOMonthView *mView = mViewManager->monthView();
00969 if ( curView == mViewManager->multiAgendaView() ) {
00970 aView = mViewManager->multiAgendaView()->selectedAgendaView();
00971 curView = aView;
00972 }
00973
00974 if ( curView == aView && aView->selectionStart().isValid() ) {
00975 date = aView->selectionStart().date();
00976 endDT = aView->selectionEnd();
00977 useEndTime = !aView->selectedIsSingleCell();
00978 if ( !aView->selectedIsAllDay() ) {
00979 time = aView->selectionStart().time();
00980 timeSet = true;
00981 }
00982 } else if ( curView == mView && mView->selectionStart().isValid() ) {
00983 date = mView->selectionStart().date();
00984 } else if ( !mDateNavigator->selectedDates().isEmpty() &&
00985 curView->supportsDateNavigation() ) {
00986
00987 date = mDateNavigator->selectedDates().first();
00988 }
00989
00990 if ( !date.isValid() && curView->supportsDateNavigation() ) {
00991 KMessageBox::sorry(
00992 this,
00993 i18n( "Paste failed: unable to determine a valid target date." ) );
00994 return;
00995 }
00996
00997 DndFactory factory( mCalendar );
00998 Incidence *pastedIncidence;
00999 if ( timeSet && time.isValid() ) {
01000 pastedIncidence = factory.pasteIncidence( date, &time );
01001 } else {
01002 pastedIncidence = factory.pasteIncidence( date );
01003 }
01004 if ( !pastedIncidence ) {
01005 return;
01006 }
01007
01008 QPair<ResourceCalendar *, QString>p = viewSubResourceCalendar();
01009
01010
01011 if ( pastedIncidence->type() == "Event" ) {
01012 Event *pastedEvent = static_cast<Event*>( pastedIncidence );
01013
01014
01015 if ( aView && endDT.isValid() && useEndTime ) {
01016 if ( ( pastedEvent->doesFloat() && aView->selectedIsAllDay() ) ||
01017 ( !pastedEvent->doesFloat() && !aView->selectedIsAllDay() ) ) {
01018 pastedEvent->setDtEnd( endDT );
01019 }
01020 }
01021 mChanger->addIncidence( pastedEvent, p.first, p.second, this );
01022
01023 } else if ( pastedIncidence->type() == "Todo" ) {
01024 Todo *pastedTodo = static_cast<Todo*>( pastedIncidence );
01025 Todo *_selectedTodo = selectedTodo();
01026 if ( _selectedTodo ) {
01027 pastedTodo->setRelatedTo( _selectedTodo );
01028 } else {
01029
01030 pastedTodo->setRelatedTo( 0 );
01031 pastedTodo->setRelatedToUid( QString() );
01032 }
01033 mChanger->addIncidence( pastedTodo, p.first, p.second, this );
01034 }
01035 }
01036
01037 void CalendarView::edit_options()
01038 {
01039 mDialogManager->showOptionsDialog();
01040 }
01041
01042 void CalendarView::dateTimesForNewEvent( QDateTime &startDt, QDateTime &endDt, bool &allDay )
01043 {
01044 mViewManager->currentView()->eventDurationHint( startDt, endDt, allDay );
01045
01046 if ( !startDt.isValid() || !endDt.isValid() ) {
01047 startDt.setDate( activeDate( true ) );
01048 startDt.setTime( KOPrefs::instance()->mStartTime.time() );
01049
01050 int addSecs = ( KOPrefs::instance()->mDefaultDuration.time().hour() * 3600 ) +
01051 ( KOPrefs::instance()->mDefaultDuration.time().minute() * 60 );
01052
01053 endDt = startDt.addSecs( addSecs );
01054 }
01055 }
01056
01057 KOEventEditor *CalendarView::newEventEditor( ResourceCalendar *res, const QString &subRes,
01058 const QDateTime &startDtParam,
01059 const QDateTime &endDtParam, bool allDayParam )
01060 {
01061
01062 bool allDay = allDayParam;
01063 QDateTime startDt( startDtParam ), endDt( endDtParam );
01064
01065
01066 dateTimesForNewEvent( startDt, endDt, allDay );
01067
01068 KOEventEditor *eventEditor = mDialogManager->getEventEditor();
01069 eventEditor->newEvent();
01070 connectIncidenceEditor( eventEditor );
01071 eventEditor->setResource( res, subRes );
01072 eventEditor->setDates( startDt, endDt, allDay );
01073 mDialogManager->connectTypeAhead( eventEditor, dynamic_cast<KOrg::AgendaView*>(viewManager()->currentView()) );
01074 return eventEditor;
01075 }
01076
01077 void CalendarView::newEvent()
01078 {
01079 KOrg::BaseView *currentView = mViewManager->currentView();
01080 if ( currentView == mViewManager->multiAgendaView() ) {
01081 currentView = mViewManager->multiAgendaView()->selectedAgendaView();
01082 }
01083
01084 newEvent( currentView->resourceCalendar(),
01085 currentView->subResourceCalendar() );
01086 }
01087
01088 void CalendarView::newEvent( ResourceCalendar *res, const QString &subRes )
01089 {
01090 kdDebug(5850) << "CalendarView::newEvent()" << endl;
01091 newEvent( res, subRes, QDateTime(), QDateTime() );
01092 }
01093
01094 void CalendarView::newEvent( ResourceCalendar *res, const QString &subRes,
01095 const QDate &dt )
01096 {
01097 QDateTime startDt( dt, KOPrefs::instance()->mStartTime.time() );
01098 newEvent( res, subRes, QDateTime( dt ), QDateTime() );
01099 }
01100
01101 void CalendarView::newEvent( ResourceCalendar *res, const QString &subRes,
01102 const QDateTime &startDt )
01103 {
01104 newEvent( res, subRes, startDt, QDateTime() );
01105 }
01106
01107 void CalendarView::newEvent( ResourceCalendar *res, const QString &subRes,
01108 const QDateTime &startDt, const QDateTime &endDt,
01109 bool allDay )
01110 {
01111 KOEventEditor *eventEditor = newEventEditor( res, subRes,
01112 startDt, endDt, allDay );
01113 eventEditor->show();
01114 }
01115
01116 void CalendarView::newEvent( ResourceCalendar *res, const QString &subRes,
01117 const QString &summary, const QString &description,
01118 const QStringList &attachments, const QStringList &attendees,
01119 const QStringList &attachmentMimetypes, bool inlineAttachment )
01120 {
01121 KOEventEditor *eventEditor = newEventEditor( res, subRes );
01122 eventEditor->setTexts( summary, description );
01123
01124
01125 eventEditor->addAttachments( attachments, attachmentMimetypes, inlineAttachment );
01126 eventEditor->addAttendees( attendees );
01127 eventEditor->show();
01128 }
01129
01130 void CalendarView::newTodo( ResourceCalendar *res, const QString &subRes,
01131 const QString &summary, const QString &description,
01132 const QStringList &attachments, const QStringList &attendees,
01133 const QStringList &attachmentMimetypes,
01134 bool inlineAttachment, bool isTask )
01135 {
01136 kdDebug(5850) << k_funcinfo << endl;
01137 KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01138 connectIncidenceEditor( todoEditor );
01139 todoEditor->newTodo();
01140 todoEditor->setResource( res, subRes );
01141 todoEditor->setTexts( summary, description );
01142 todoEditor->addAttachments( attachments, attachmentMimetypes, inlineAttachment );
01143 todoEditor->addAttendees( attendees );
01144 todoEditor->selectCreateTask( isTask );
01145 todoEditor->show();
01146 }
01147
01148 void CalendarView::newTodo()
01149 {
01150 KOrg::BaseView *currentView = mViewManager->currentView();
01151 if ( currentView == mViewManager->multiAgendaView() ) {
01152 currentView = mViewManager->multiAgendaView()->selectedAgendaView();
01153 }
01154
01155 newTodo( currentView->resourceCalendar(),
01156 currentView->subResourceCalendar() );
01157 }
01158
01159 void CalendarView::newTodo( ResourceCalendar *res, const QString &subRes )
01160 {
01161 kdDebug(5850) << k_funcinfo << endl;
01162 QDateTime dtDue;
01163 bool allday = true;
01164 KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01165 connectIncidenceEditor( todoEditor );
01166 todoEditor->newTodo();
01167 todoEditor->setResource( res, subRes );
01168 if ( mViewManager->currentView()->isEventView() ) {
01169 dtDue.setDate( mDateNavigator->selectedDates().first() );
01170 QDateTime dtDummy = QDateTime::currentDateTime();
01171 mViewManager->currentView()->eventDurationHint( dtDue, dtDummy, allday );
01172 todoEditor->setDates( dtDue, allday );
01173 }
01174 todoEditor->show();
01175 }
01176
01177 void CalendarView::newTodo( ResourceCalendar *res, const QString &subRes,
01178 const QDate &date )
01179 {
01180 KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01181 connectIncidenceEditor( todoEditor );
01182 todoEditor->newTodo();
01183 todoEditor->setResource( res, subRes );
01184 todoEditor->setDates( QDateTime( date, QTime::currentTime() ), true );
01185 todoEditor->show();
01186 }
01187
01188 void CalendarView::newJournal()
01189 {
01190 KOrg::BaseView *currentView = mViewManager->currentView();
01191 if ( currentView == mViewManager->multiAgendaView() ) {
01192 currentView = mViewManager->multiAgendaView()->selectedAgendaView();
01193 }
01194
01195 newJournal( currentView->resourceCalendar(),
01196 currentView->subResourceCalendar() );
01197 }
01198
01199 void CalendarView::newJournal( ResourceCalendar *res, const QString &subRes )
01200 {
01201 kdDebug(5850) << "CalendarView::newJournal()" << endl;
01202 newJournal( res, subRes, QString::null, QDate() );
01203 }
01204
01205 void CalendarView::newJournal( ResourceCalendar *res, const QString &subRes,
01206 const QDate &date)
01207 {
01208 newJournal( res, subRes, QString::null, date );
01209 }
01210
01211 void CalendarView::newJournal( ResourceCalendar *res, const QString &subRes,
01212 const QString &text, const QDate &date )
01213 {
01214 KOJournalEditor *journalEditor = mDialogManager->getJournalEditor();
01215 connectIncidenceEditor( journalEditor );
01216 journalEditor->newJournal();
01217 journalEditor->setResource( res, subRes );
01218 journalEditor->setTexts( text );
01219 if ( !date.isValid() ) {
01220 journalEditor->setDate( mDateNavigator->selectedDates().first() );
01221 } else {
01222 journalEditor->setDate( date );
01223 }
01224 journalEditor->show();
01225 }
01226
01227 void CalendarView::newSubTodo()
01228 {
01229 Todo *todo = selectedTodo();
01230 if ( todo ) newSubTodo( todo );
01231 }
01232
01233 void CalendarView::newSubTodo(Todo *parentEvent)
01234 {
01235 KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
01236 connectIncidenceEditor( todoEditor );
01237 todoEditor->newTodo();
01238 todoEditor->setDates( QDateTime(), false, parentEvent );
01239 todoEditor->show();
01240 }
01241
01242 bool CalendarView::addIncidence( const QString &ical )
01243 {
01244 kdDebug(5850) << "CalendarView::addIncidence:\n" << ical << endl;
01245 ICalFormat format;
01246 format.setTimeZone( mCalendar->timeZoneId(), true );
01247 Incidence *incidence = format.fromString( ical );
01248 if ( !incidence ) return false;
01249 if ( !mChanger->addIncidence( incidence, 0, QString(), this ) ) {
01250 delete incidence;
01251 return false;
01252 }
01253 return true;
01254 }
01255
01256 void CalendarView::appointment_show()
01257 {
01258 Incidence *incidence = selectedIncidence();
01259 if ( incidence ) {
01260 showIncidence( incidence, activeIncidenceDate() );
01261 } else {
01262 KNotifyClient::beep();
01263 }
01264 }
01265
01266 void CalendarView::appointment_edit()
01267 {
01268 Incidence *incidence = selectedIncidence();
01269 if ( incidence ) {
01270 editIncidence( incidence, activeIncidenceDate() );
01271 } else {
01272 KNotifyClient::beep();
01273 }
01274 }
01275
01276 void CalendarView::appointment_delete()
01277 {
01278 Incidence *incidence = selectedIncidence();
01279 if (incidence)
01280 deleteIncidence( incidence );
01281 else
01282 KNotifyClient::beep();
01283 }
01284
01285 void CalendarView::todo_unsub()
01286 {
01287 Todo *anTodo = selectedTodo();
01288 if( todo_unsub (anTodo ) ) {
01289 updateView();
01290 }
01291 }
01292
01293 bool CalendarView::todo_unsub( Todo *todo )
01294 {
01295 bool status= false;
01296 if ( !todo || !todo->relatedTo() ) return false;
01297
01298 if ( mChanger->beginChange( todo, 0, QString() ) ) {
01299 Todo *oldTodo = todo->clone();
01300 todo->setRelatedTo(0);
01301 mChanger->changeIncidence( oldTodo, todo, KOGlobals::RELATION_MODIFIED, this );
01302 mChanger->endChange( todo, 0, QString() );
01303 delete oldTodo;
01304 setModified(true);
01305 status = true;
01306 }
01307 if ( ! status ) {
01308 KMessageBox::sorry( this, i18n("Unable to turn sub-to-do into a top-level "
01309 "to-do, because it cannot be locked.") );
01310 }
01311
01312 return status;
01313 }
01314
01315 bool CalendarView::makeSubTodosIndependents ( )
01316 {
01317 bool status = false;
01318 Todo *anTodo = selectedTodo();
01319
01320 if( makeSubTodosIndependents( anTodo ) ) {
01321 updateView();
01322 status = true;
01323 }
01324 return status;
01325 }
01326
01327 bool CalendarView::makeSubTodosIndependents ( Todo *todo )
01328 {
01329 if( !todo || todo->relations().isEmpty() ) return false;
01330
01331 startMultiModify ( i18n( "Make sub-to-dos independent" ) );
01332 Incidence::List subTodos( todo->relations() );
01333 Incidence::List::Iterator it;
01334 Incidence *aIncidence;
01335 Todo *aTodo;
01336
01337 for ( it= subTodos.begin(); it != subTodos.end(); ++it ) {
01338 aIncidence = *it;
01339 if( aIncidence && aIncidence->type() == "Todo" ) {
01340 aTodo = static_cast<Todo*>( aIncidence );
01341 todo_unsub ( aTodo );
01342 }
01343 }
01344 endMultiModify();
01345 return true;
01346 }
01347
01348 bool CalendarView::deleteIncidence( const QString &uid, bool force )
01349 {
01350 Incidence *inc = mCalendar->incidence( uid );
01351 if ( inc ) {
01352 deleteIncidence( inc, force );
01353 return true;
01354 } else {
01355 return false;
01356 }
01357 }
01358
01359 void CalendarView::toggleAlarm( Incidence *incidence )
01360 {
01361 if ( !incidence || !mChanger ) {
01362 kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01363 return;
01364 }
01365 Incidence*oldincidence = incidence->clone();
01366 if ( !mChanger->beginChange( incidence, 0, QString() ) ) {
01367 kdDebug(5850) << "Unable to lock incidence " << endl;
01368 delete oldincidence;
01369 return;
01370 }
01371
01372 Alarm::List alarms = incidence->alarms();
01373 Alarm::List::ConstIterator it;
01374 for( it = alarms.begin(); it != alarms.end(); ++it )
01375 (*it)->toggleAlarm();
01376 if (alarms.isEmpty()) {
01377
01378 Alarm*alm = incidence->newAlarm();
01379 alm->setEnabled(true);
01380 }
01381 mChanger->changeIncidence( oldincidence, incidence, KOGlobals::ALARM_MODIFIED, this );
01382 mChanger->endChange( incidence, 0, QString() );
01383 delete oldincidence;
01384
01385
01386 }
01387
01388 void CalendarView::dissociateOccurrence( Incidence *incidence, const QDate &date )
01389 {
01390 if ( !incidence || !mChanger ) {
01391 kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01392 return;
01393 }
01394
01395 QPair<ResourceCalendar *, QString>p =
01396 CalHelper::incSubResourceCalendar( calendar(), incidence );
01397
01398 if ( !mChanger->beginChange( incidence, p.first, p.second ) ) {
01399 kdDebug(5850) << "Unable to lock incidence " << endl;
01400 return;
01401 }
01402 startMultiModify( i18n("Dissociate occurrence") );
01403 Incidence*oldincidence = incidence->clone();
01404
01405 Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true );
01406
01407 if ( newInc ) {
01408 mChanger->changeIncidence( oldincidence, incidence, KOGlobals::NOTHING_MODIFIED, this );
01409 mChanger->addIncidence( newInc, p.first, p.second, this );
01410 } else {
01411 KMessageBox::sorry( this, i18n("Dissociating the occurrence failed."),
01412 i18n("Dissociating Failed") );
01413 }
01414 mChanger->endChange( incidence, p.first, p.second );
01415 endMultiModify();
01416 delete oldincidence;
01417 }
01418
01419 void CalendarView::dissociateFutureOccurrence( Incidence *incidence, const QDate &date )
01420 {
01421 if ( !incidence || !mChanger ) {
01422 kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01423 return;
01424 }
01425
01426 QPair<ResourceCalendar *, QString>p =
01427 CalHelper::incSubResourceCalendar( calendar(), incidence );
01428
01429 if ( !mChanger->beginChange( incidence, p.first, p.second ) ) {
01430 kdDebug(5850) << "Unable to lock incidence " << endl;
01431 return;
01432 }
01433 startMultiModify( i18n("Dissociate future occurrences") );
01434 Incidence*oldincidence = incidence->clone();
01435
01436 Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true );
01437 if ( newInc ) {
01438 mChanger->changeIncidence( oldincidence, incidence, KOGlobals::NOTHING_MODIFIED, this );
01439 mChanger->addIncidence( newInc, p.first, p.second, this );
01440 } else {
01441 KMessageBox::sorry( this, i18n("Dissociating the future occurrences failed."),
01442 i18n("Dissociating Failed") );
01443 }
01444 endMultiModify();
01445 mChanger->endChange( incidence, p.first, p.second );
01446 delete oldincidence;
01447 }
01448
01449
01450
01451
01452
01453 void CalendarView::schedule_publish(Incidence *incidence)
01454 {
01455 if (incidence == 0)
01456 incidence = selectedIncidence();
01457
01458 if (!incidence) {
01459 KMessageBox::information( this, i18n("No item selected."),
01460 "PublishNoEventSelected" );
01461 return;
01462 }
01463
01464 PublishDialog *publishdlg = new PublishDialog();
01465 if (incidence->attendeeCount()>0) {
01466 Attendee::List attendees = incidence->attendees();
01467 Attendee::List::ConstIterator it;
01468 for( it = attendees.begin(); it != attendees.end(); ++it ) {
01469 publishdlg->addAttendee( *it );
01470 }
01471 }
01472 if ( publishdlg->exec() == QDialog::Accepted ) {
01473 Incidence *inc = incidence->clone();
01474 inc->registerObserver( 0 );
01475 inc->clearAttendees();
01476
01477
01478 KCal::MailScheduler scheduler( mCalendar );
01479 if ( scheduler.publish( incidence, publishdlg->addresses() ) ) {
01480 KMessageBox::information( this, i18n("The item information was successfully sent."),
01481 i18n("Publishing"), "IncidencePublishSuccess" );
01482 } else {
01483 KMessageBox::error( this, i18n("Unable to publish the item '%1'").arg( incidence->summary() ) );
01484 }
01485 }
01486 delete publishdlg;
01487 }
01488
01489 void CalendarView::schedule_request(Incidence *incidence)
01490 {
01491 schedule(Scheduler::Request,incidence);
01492 }
01493
01494 void CalendarView::schedule_refresh(Incidence *incidence)
01495 {
01496 schedule(Scheduler::Refresh,incidence);
01497 }
01498
01499 void CalendarView::schedule_cancel(Incidence *incidence)
01500 {
01501 schedule(Scheduler::Cancel,incidence);
01502 }
01503
01504 void CalendarView::schedule_add(Incidence *incidence)
01505 {
01506 schedule(Scheduler::Add,incidence);
01507 }
01508
01509 void CalendarView::schedule_reply(Incidence *incidence)
01510 {
01511 schedule(Scheduler::Reply,incidence);
01512 }
01513
01514 void CalendarView::schedule_counter(Incidence *incidence)
01515 {
01516 schedule(Scheduler::Counter,incidence);
01517 }
01518
01519 void CalendarView::schedule_declinecounter(Incidence *incidence)
01520 {
01521 schedule(Scheduler::Declinecounter,incidence);
01522 }
01523
01524 void CalendarView::schedule_forward( Incidence *incidence )
01525 {
01526 if ( !incidence ) {
01527 incidence = selectedIncidence();
01528 }
01529
01530 if ( !incidence ) {
01531 KMessageBox::information(
01532 this,
01533 i18n( "No item selected." ),
01534 i18n( "Forwarding" ),
01535 "ForwardNoEventSelected" );
01536 return;
01537 }
01538
01539 PublishDialog publishdlg;
01540 if ( publishdlg.exec() == QDialog::Accepted ) {
01541 QString recipients = publishdlg.addresses();
01542 if ( incidence->organizer().isEmpty() ) {
01543 incidence->setOrganizer( Person( KOPrefs::instance()->fullName(),
01544 KOPrefs::instance()->email() ) );
01545 }
01546
01547 ICalFormat format;
01548 QString messageText = format.createScheduleMessage( incidence, Scheduler::Request );
01549 KOMailClient mailer;
01550 if ( mailer.mailTo( incidence, recipients, messageText ) ) {
01551 KMessageBox::information(
01552 this,
01553 i18n( "The item information was successfully sent." ),
01554 i18n( "Forwarding" ),
01555 "IncidenceForwardSuccess" );
01556 } else {
01557 KMessageBox::error(
01558 this,
01559 i18n( "Unable to forward the item '%1'" ).arg( incidence->summary() ),
01560 i18n( "Forwarding Error" ) );
01561 }
01562 }
01563 }
01564
01565 void CalendarView::mailFreeBusy( int daysToPublish )
01566 {
01567 QDateTime start = QDateTime::currentDateTime();
01568 QDateTime end = start.addDays(daysToPublish);
01569
01570 FreeBusy *freebusy = new FreeBusy(mCalendar, start, end);
01571 freebusy->setOrganizer( Person( KOPrefs::instance()->fullName(),
01572 KOPrefs::instance()->email() ) );
01573
01574 kdDebug(5850) << "calendarview: schedule_publish_freebusy: startDate: "
01575 << KGlobal::locale()->formatDateTime( start ) << " End Date: "
01576 << KGlobal::locale()->formatDateTime( end ) << endl;
01577
01578 PublishDialog *publishdlg = new PublishDialog();
01579 if ( publishdlg->exec() == QDialog::Accepted ) {
01580
01581 KCal::MailScheduler scheduler( mCalendar );
01582 if ( scheduler.publish( freebusy, publishdlg->addresses() ) ) {
01583 KMessageBox::information( this, i18n("The free/busy information was successfully sent."),
01584 i18n("Sending Free/Busy"), "FreeBusyPublishSuccess" );
01585 } else {
01586 KMessageBox::error( this, i18n("Unable to publish the free/busy data.") );
01587 }
01588 }
01589 delete freebusy;
01590 delete publishdlg;
01591 }
01592
01593 void CalendarView::uploadFreeBusy()
01594 {
01595 KOGroupware::instance()->freeBusyManager()->publishFreeBusy();
01596 }
01597
01598 void CalendarView::schedule(Scheduler::Method method, Incidence *incidence)
01599 {
01600 if ( !incidence ) {
01601 incidence = selectedIncidence();
01602 }
01603
01604 if ( !incidence ) {
01605 KMessageBox::sorry( this, i18n("No item selected."),
01606 "ScheduleNoEventSelected" );
01607 return;
01608 }
01609
01610 if( incidence->attendeeCount() == 0 && method != Scheduler::Publish ) {
01611 KMessageBox::information( this, i18n("The item has no attendees."),
01612 "ScheduleNoIncidences" );
01613 return;
01614 }
01615
01616 Incidence *inc = incidence->clone();
01617 inc->registerObserver( 0 );
01618 inc->clearAttendees();
01619
01620
01621 KCal::MailScheduler scheduler( mCalendar );
01622 if ( scheduler.performTransaction( incidence, method ) ) {
01623 KMessageBox::information( this, i18n("The groupware message for item '%1'"
01624 "was successfully sent.\nMethod: %2")
01625 .arg( incidence->summary() )
01626 .arg( Scheduler::methodName( method ) ),
01627 i18n("Sending Free/Busy"),
01628 "FreeBusyPublishSuccess" );
01629 } else {
01630 KMessageBox::error( this, i18n("Groupware message sending failed. "
01631 "%2 is request/reply/add/cancel/counter/etc.",
01632 "Unable to send the item '%1'.\nMethod: %2")
01633 .arg( incidence->summary() )
01634 .arg( Scheduler::methodName( method ) ) );
01635 }
01636 }
01637
01638 void CalendarView::openAddressbook()
01639 {
01640 KRun::runCommand("kaddressbook");
01641 }
01642
01643 void CalendarView::setModified(bool modified)
01644 {
01645 if (mModified != modified) {
01646 mModified = modified;
01647 emit modifiedChanged(mModified);
01648 }
01649 }
01650
01651 bool CalendarView::isReadOnly()
01652 {
01653 return mReadOnly;
01654 }
01655
01656 void CalendarView::setReadOnly(bool readOnly)
01657 {
01658 if (mReadOnly != readOnly) {
01659 mReadOnly = readOnly;
01660 emit readOnlyChanged(mReadOnly);
01661 }
01662 }
01663
01664 bool CalendarView::isModified()
01665 {
01666 return mModified;
01667 }
01668
01669 void CalendarView::print()
01670 {
01671 #ifndef KORG_NOPRINTER
01672 KOCoreHelper helper;
01673 CalPrinter printer( this, mCalendar, &helper );
01674 connect( this, SIGNAL(configChanged()), &printer, SLOT(updateConfig()) );
01675
01676 KOrg::BaseView *currentView = mViewManager->currentView();
01677
01678 CalPrinterBase::PrintType printType = CalPrinterBase::Month;
01679 if ( currentView ) printType = currentView->printType();
01680
01681 DateList tmpDateList = mDateNavigator->selectedDates();
01682 Incidence::List selectedIncidences;
01683 if ( mViewManager->currentView() ) {
01684 selectedIncidences = mViewManager->currentView()->selectedIncidences();
01685 }
01686 printer.print( printType, tmpDateList.first(), tmpDateList.last(), selectedIncidences );
01687 #endif
01688 }
01689
01690 void CalendarView::exportWeb()
01691 {
01692
01693 HTMLExportSettings *settings = new HTMLExportSettings( "KOrganizer" );
01694
01695
01696 if ( settings ) settings->readConfig();
01697 ExportWebDialog *dlg = new ExportWebDialog( settings, this );
01698 connect( dlg, SIGNAL( exportHTML( HTMLExportSettings* ) ),
01699 this, SIGNAL( exportHTML( HTMLExportSettings* ) ) );
01700 dlg->show();
01701 }
01702
01703 void CalendarView::exportICalendar()
01704 {
01705 QString filename = KFileDialog::getSaveFileName("icalout.ics",i18n("*.ics|ICalendars"),this);
01706 if ( !filename.isEmpty() )
01707 {
01708
01709 if (filename.right(4) != ".ics") filename += ".ics";
01710 if ( QFile( filename ).exists() ) {
01711 if ( KMessageBox::No == KMessageBox::warningYesNo(
01712 this,
01713 i18n( "Do you want to overwrite %1?").arg(filename) ) ) {
01714 return;
01715 }
01716 }
01717 FileStorage storage( mCalendar, filename, new ICalFormat );
01718 storage.save();
01719 }
01720 }
01721
01722 void CalendarView::exportVCalendar()
01723 {
01724 if (mCalendar->journals().count() > 0) {
01725 int result = KMessageBox::warningContinueCancel(this,
01726 i18n("The journal entries can not be exported to a vCalendar file."),
01727 i18n("Data Loss Warning"),i18n("Proceed"),"dontaskVCalExport",
01728 true);
01729 if (result != KMessageBox::Continue) return;
01730 }
01731
01732 QString filename = KFileDialog::getSaveFileName("vcalout.vcs",i18n("*.vcs|vCalendars"),this);
01733 if ( !filename.isEmpty() )
01734 {
01735
01736
01737 if (filename.right(4) != ".vcs") filename += ".vcs";
01738 if ( QFile( filename ).exists() ) {
01739 if ( KMessageBox::No == KMessageBox::warningYesNo(
01740 this,
01741 i18n( "Do you want to overwrite %1?").arg(filename ) ) ) {
01742 return;
01743 }
01744 }
01745 FileStorage storage( mCalendar, filename, new VCalFormat );
01746 storage.save();
01747 }
01748 }
01749
01750 void CalendarView::eventUpdated(Incidence *)
01751 {
01752 setModified();
01753
01754
01755
01756 }
01757
01758 void CalendarView::adaptNavigationUnits()
01759 {
01760 if (mViewManager->currentView()->isEventView()) {
01761 int days = mViewManager->currentView()->currentDateCount();
01762 if (days == 1) {
01763 emit changeNavStringPrev(i18n("&Previous Day"));
01764 emit changeNavStringNext(i18n("&Next Day"));
01765 } else {
01766 emit changeNavStringPrev(i18n("&Previous Week"));
01767 emit changeNavStringNext(i18n("&Next Week"));
01768 }
01769 }
01770 }
01771
01772 void CalendarView::processMainViewSelection( Incidence *incidence, const QDate &date )
01773 {
01774 if ( incidence ) mTodoList->clearSelection();
01775 processIncidenceSelection( incidence, date );
01776 }
01777
01778 void CalendarView::processTodoListSelection( Incidence *incidence, const QDate &date )
01779 {
01780 if ( incidence && mViewManager->currentView() ) {
01781 mViewManager->currentView()->clearSelection();
01782 }
01783 processIncidenceSelection( incidence, date );
01784 }
01785
01786 void CalendarView::processIncidenceSelection( Incidence *incidence, const QDate &date )
01787 {
01788 if ( incidence != mSelectedIncidence ) {
01789
01790 emit incidenceSelected( incidence, date );
01791 }
01792
01793 if ( !incidence ) {
01794 mSelectedIncidence = incidence;
01795 return;
01796 }
01797 if ( incidence == mSelectedIncidence ) {
01798 if ( !incidence->doesRecur() || mSaveDate == date ) {
01799 return;
01800 }
01801 }
01802
01803 mSelectedIncidence = incidence;
01804 mSaveDate = date;
01805
01806 emit incidenceSelected( mSelectedIncidence, date );
01807 bool organizerEvents = false;
01808 bool groupEvents = false;
01809 bool todo = false;
01810 bool subtodo = false;
01811
01812 organizerEvents = KOPrefs::instance()->thatIsMe( incidence->organizer().email() );
01813 groupEvents = incidence->attendeeByMails( KOPrefs::instance()->allEmails() );
01814
01815 if ( incidence->type() == "Todo" ) {
01816 todo = true;
01817 subtodo = ( incidence->relatedTo() != 0 );
01818 }
01819
01820 emit todoSelected( todo );
01821 emit subtodoSelected( subtodo );
01822 emit organizerEventsSelected( organizerEvents );
01823 emit groupEventsSelected( groupEvents );
01824 }
01825
01826
01827 void CalendarView::checkClipboard()
01828 {
01829 #ifndef KORG_NODND
01830 if (ICalDrag::canDecode(QApplication::clipboard()->data())) {
01831 kdDebug(5850) << "CalendarView::checkClipboard() true" << endl;
01832 emit pasteEnabled(true);
01833 } else {
01834 kdDebug(5850) << "CalendarView::checkClipboard() false" << endl;
01835 emit pasteEnabled(false);
01836 }
01837 #endif
01838 }
01839
01840 void CalendarView::showDates( const DateList &selectedDates )
01841 {
01842
01843
01844 if ( mViewManager->currentView() ) {
01845 updateView( selectedDates.first(), selectedDates.last() );
01846 } else {
01847 mViewManager->showAgendaView();
01848 }
01849 }
01850
01851 void CalendarView::editFilters()
01852 {
01853 kdDebug(5850) << "CalendarView::editFilters()" << endl;
01854
01855 CalFilter *filter = mFilters.first();
01856 while( filter ) {
01857 kdDebug(5850) << " Filter: " << filter->name() << endl;
01858 filter = mFilters.next();
01859 }
01860
01861 mDialogManager->showFilterEditDialog(&mFilters);
01862 }
01863
01866 void CalendarView::updateFilter()
01867 {
01868 QStringList filters;
01869 CalFilter *filter;
01870
01871 int pos = mFilters.find( mCurrentFilter );
01872 if ( pos < 0 ) {
01873 mCurrentFilter = 0;
01874 }
01875
01876 filters << i18n("No filter");
01877 for ( filter = mFilters.first(); filter; filter = mFilters.next() ) {
01878 filters << filter->name();
01879 }
01880
01881 emit newFilterListSignal( filters );
01882
01883
01884 emit selectFilterSignal( pos+1 );
01885 mCalendar->setFilter( mCurrentFilter );
01886 updateView();
01887 }
01888
01891 void CalendarView::filterActivated( int filterNo )
01892 {
01893 CalFilter *newFilter = 0;
01894 if ( filterNo > 0 && filterNo <= int(mFilters.count()) ) {
01895 newFilter = mFilters.at( filterNo-1 );
01896 }
01897 if ( newFilter != mCurrentFilter ) {
01898 mCurrentFilter = newFilter;
01899 mCalendar->setFilter( mCurrentFilter );
01900 updateView();
01901 }
01902 emit filterChanged();
01903 }
01904
01905 QString CalendarView::currentFilterName() const
01906 {
01907 if ( mCurrentFilter) {
01908 return mCurrentFilter->name();
01909 } else return i18n("No filter");
01910 }
01911
01912 void CalendarView::takeOverEvent()
01913 {
01914 Incidence *incidence = currentSelection();
01915
01916 if (!incidence) return;
01917
01918 incidence->setOrganizer( Person( KOPrefs::instance()->fullName(),
01919 KOPrefs::instance()->email() ) );
01920 incidence->recreate();
01921 incidence->setReadOnly(false);
01922
01923 updateView();
01924 }
01925
01926 void CalendarView::takeOverCalendar()
01927 {
01928 Incidence::List incidences = mCalendar->rawIncidences();
01929 Incidence::List::Iterator it;
01930
01931 for ( it = incidences.begin(); it != incidences.end(); ++it ) {
01932 (*it)->setOrganizer( Person( KOPrefs::instance()->fullName(),
01933 KOPrefs::instance()->email() ) );
01934 (*it)->recreate();
01935 (*it)->setReadOnly(false);
01936 }
01937 updateView();
01938 }
01939
01940 void CalendarView::showIntro()
01941 {
01942 kdDebug(5850) << "To be implemented." << endl;
01943 }
01944
01945 void CalendarView::showDateNavigator( bool show )
01946 {
01947 if( show )
01948 mDateNavigatorContainer->show();
01949 else
01950 mDateNavigatorContainer->hide();
01951 }
01952
01953 void CalendarView::showTodoView( bool show )
01954 {
01955 if( show )
01956 mTodoList->show();
01957 else
01958 mTodoList->hide();
01959 }
01960
01961 void CalendarView::showEventViewer( bool show )
01962 {
01963 if( show )
01964 mEventViewer->show();
01965 else
01966 mEventViewer->hide();
01967 }
01968
01969
01970 void CalendarView::addView(KOrg::BaseView *view)
01971 {
01972 mViewManager->addView(view);
01973 }
01974
01975 void CalendarView::showView(KOrg::BaseView *view)
01976 {
01977 mViewManager->showView(view);
01978 }
01979
01980 void CalendarView::addExtension( CalendarViewExtension::Factory *factory )
01981 {
01982 CalendarViewExtension *extension = factory->create( mLeftSplitter );
01983
01984 mExtensions.append( extension );
01985 }
01986
01987 void CalendarView::toggleExpand()
01988 {
01989 showLeftFrame( mLeftFrame->isHidden() );
01990 }
01991
01992 void CalendarView::showLeftFrame(bool show)
01993 {
01994 if (show) {
01995 mLeftFrame->show();
01996 emit calendarViewExpanded( false );
01997 } else {
01998 mLeftFrame->hide();
01999 emit calendarViewExpanded( true );
02000 }
02001 }
02002
02003 void CalendarView::calendarModified( bool modified, Calendar * )
02004 {
02005 setModified( modified );
02006 }
02007
02008 Todo *CalendarView::selectedTodo()
02009 {
02010 Incidence *incidence = currentSelection();
02011 if ( incidence && incidence->type() == "Todo" ) {
02012 return static_cast<Todo *>( incidence );
02013 }
02014 incidence = 0;
02015
02016 Incidence::List selectedIncidences = mTodoList->selectedIncidences();
02017 if ( !selectedIncidences.isEmpty() ) incidence = selectedIncidences.first();
02018 if ( incidence && incidence->type() == "Todo" ) {
02019 return static_cast<Todo *>( incidence );
02020 }
02021
02022 return 0;
02023 }
02024
02025 void CalendarView::dialogClosing( Incidence *in )
02026 {
02027
02028 mChanger->endChange( in, 0, QString() );
02029 mDialogList.remove( in );
02030 }
02031
02032 Incidence *CalendarView::currentSelection()
02033 {
02034 return mViewManager->currentSelection();
02035 }
02036
02037 Incidence* CalendarView::selectedIncidence()
02038 {
02039 Incidence *incidence = currentSelection();
02040 if ( !incidence ) {
02041 Incidence::List selectedIncidences = mTodoList->selectedIncidences();
02042 if ( !selectedIncidences.isEmpty() )
02043 incidence = selectedIncidences.first();
02044 }
02045 return incidence;
02046 }
02047
02048 void CalendarView::showIncidence()
02049 {
02050 showIncidence( selectedIncidence(), activeIncidenceDate() );
02051 }
02052
02053 void CalendarView::editIncidence()
02054 {
02055 editIncidence( selectedIncidence(), activeIncidenceDate() );
02056 }
02057
02058 bool CalendarView::editIncidence( const QString &uid )
02059 {
02060 return editIncidence( mCalendar->incidence( uid ), QDate() );
02061 }
02062
02063 bool CalendarView::editIncidence( const QString &uid, const QDate &date )
02064 {
02065 return editIncidence( mCalendar->incidence( uid ), date );
02066 }
02067
02068 void CalendarView::deleteIncidence()
02069 {
02070 deleteIncidence( selectedIncidence() );
02071 }
02072
02073 void CalendarView::cutIncidence(Incidence *)
02074 {
02075 edit_cut();
02076 }
02077
02078 void CalendarView::copyIncidence(Incidence *)
02079 {
02080 edit_copy();
02081 }
02082
02083 void CalendarView::pasteIncidence()
02084 {
02085 edit_paste();
02086 }
02087
02088 void CalendarView::showIncidence( Incidence *incidence, const QDate &date )
02089 {
02090 KOEventViewerDialog *eventViewer = new KOEventViewerDialog( calendar(), this );
02091 eventViewer->setIncidence( incidence, date );
02092 eventViewer->show();
02093 }
02094
02095 bool CalendarView::editIncidence( Incidence *incidence, const QDate &date, bool isCounter )
02096 {
02097 kdDebug(5850) << "CalendarView::editEvent()" << endl;
02098
02099 CalendarResources *stdcal = dynamic_cast<CalendarResources *>( mCalendar );
02100 if( stdcal && !stdcal->hasCalendarResources() ) {
02101 KMessageBox::sorry(
02102 this,
02103 i18n( "No resources found. We can not edit the item." ) );
02104 return false;
02105 }
02106
02107
02108
02109
02110
02111 QWidget *tmpparent = 0;
02112 if ( stdcal ) {
02113 tmpparent = stdcal->dialogParentWidget();
02114 stdcal->setDialogParentWidget( this );
02115 }
02116
02117 if ( !incidence ) {
02118 kdDebug(5850) << "Empty Incidence" << endl;
02119 KNotifyClient::beep();
02120 return false;
02121 }
02122
02123 if ( !mChanger ) {
02124 kdDebug(5850) << "Empty Changer" << endl;
02125 KNotifyClient::beep();
02126 return false;
02127 }
02128
02129 KOIncidenceEditor *tmp = editorDialog( incidence );
02130 if ( tmp ) {
02131 kdDebug(5850) << "CalendarView::editIncidence() in List" << endl;
02132 tmp->reload();
02133 tmp->raise();
02134 tmp->show();
02135 return true;
02136 }
02137
02138 if ( incidence->isReadOnly() ) {
02139 showIncidence( incidence, date );
02140 return true;
02141 }
02142
02143 QPair<ResourceCalendar *, QString>p =
02144 CalHelper::incSubResourceCalendar( calendar(), incidence );
02145
02146 Incidence *savedIncidence = incidence->clone();
02147 Incidence *incToChange;
02148
02149 if ( incidence->doesRecur() ) {
02150 KOGlobals::WhichOccurrences chosenOption;
02151 incToChange = singleOccurrenceOrAll( incidence, KOGlobals::EDIT, chosenOption, date );
02152 } else {
02153 incToChange = incidence;
02154 }
02155
02156
02157 if ( incToChange ) {
02158 if ( !isCounter && !mChanger->beginChange( incToChange, p.first, p.second ) ) {
02159 warningChangeFailed( incToChange );
02160 showIncidence( incToChange, date );
02161
02162 return false;
02163 }
02164
02165 kdDebug(5850) << "CalendarView::editIncidence() new IncidenceEditor" << endl;
02166 KOIncidenceEditor *incidenceEditor = mDialogManager->getEditor( incToChange );
02167 connectIncidenceEditor( incidenceEditor );
02168
02169 mDialogList.insert( incToChange, incidenceEditor );
02170 if ( incidence != incToChange ) {
02171 incidenceEditor->setRecurringIncidence( savedIncidence, incidence );
02172 }
02173 incidenceEditor->setResource( p.first, p.second );
02174 incidenceEditor->editIncidence( incToChange, date, mCalendar );
02175 incidenceEditor->show();
02176 return true;
02177 } else {
02178 return false;
02179 }
02180 }
02181
02182 void CalendarView::deleteSubTodosIncidence ( Todo *todo )
02183 {
02184 if( !todo ) return;
02185
02186 Incidence::List subTodos( todo->relations() );
02187 Incidence::List::Iterator it;
02188 Incidence *aIncidence;
02189 Todo *aTodo;
02190
02191 for ( it= subTodos.begin(); it != subTodos.end(); ++it ) {
02192 aIncidence = *it;
02193 if( aIncidence && aIncidence->type() == "Todo" ) {
02194 aTodo = static_cast<Todo*>( aIncidence );
02195 deleteSubTodosIncidence ( aTodo );
02196 }
02197 }
02198 mChanger->deleteIncidence ( todo, this );
02199 }
02200
02201 void CalendarView::deleteTodoIncidence ( Todo *todo, bool force )
02202 {
02203 if ( !todo ) return ;
02204
02205
02206 if (todo->relations().isEmpty() ) {
02207 bool doDelete = true;
02208 if ( !force && KOPrefs::instance()->mConfirm ) {
02209 doDelete = ( msgItemDelete( todo ) == KMessageBox::Continue );
02210 }
02211 if ( doDelete )
02212 mChanger->deleteIncidence( todo, this );
02213 return;
02214 }
02215
02216
02217 int km = KMessageBox::No;
02218 if ( !force ) {
02219 km = KMessageBox::questionYesNoCancel(
02220 this,
02221 i18n("The item \"%1\" has sub-to-dos. "
02222 "Do you want to delete just this item and "
02223 "make all its sub-to-dos independent, or "
02224 "delete the to-do with all its sub-to-dos?"
02225 ).arg( todo->summary() ),
02226 i18n("KOrganizer Confirmation"),
02227 i18n("Delete Only This"),
02228 i18n("Delete All"));
02229 }
02230 startMultiModify( i18n("Deleting sub-to-dos" ) );
02231
02232 if( km == KMessageBox::Yes ) {
02233
02234 makeSubTodosIndependents ( todo );
02235 mChanger->deleteIncidence( todo, this );
02236 } else if ( km == KMessageBox::No ) {
02237
02238
02239 deleteSubTodosIncidence ( todo );
02240 }
02241 endMultiModify();
02242 }
02243
02244 void CalendarView::deleteIncidence(Incidence *incidence, bool force)
02245 {
02246 if ( !incidence || !mChanger ) {
02247 if ( !force ) {
02248 KNotifyClient::beep();
02249 }
02250 return;
02251 }
02252 if ( incidence->isReadOnly() ) {
02253 if ( !force ) {
02254 KMessageBox::information( this, i18n("The item \"%1\" is marked read-only "
02255 "and cannot be deleted; it probably belongs to "
02256 "a read-only calendar resource.")
02257 .arg(incidence->summary()),
02258 i18n("Removing not possible"),
02259 "deleteReadOnlyIncidence" );
02260 }
02261 return;
02262 }
02263
02264 CanDeleteIncidenceVisitor v;
02265
02266
02267
02268 if ( !v.act( incidence, this ) )
02269 return;
02270
02271
02272 if ( incidence && incidence->type()=="Todo" ) {
02273 deleteTodoIncidence( static_cast<Todo*>(incidence), force );
02274 return;
02275 }
02276
02277 if ( incidence->doesRecur() ) {
02278 QDate itemDate = mViewManager->currentSelectionDate();
02279 kdDebug(5850) << "Recurrence-Date: " << itemDate.toString() << endl;
02280 int km = KMessageBox::Ok;
02281 if ( !force ) {
02282 if ( !itemDate.isValid() ) {
02283 kdDebug(5850) << "Date Not Valid" << endl;
02284 km = KMessageBox::warningContinueCancel(this,
02285 i18n("The calendar item \"%1\" recurs over multiple dates; "
02286 "are you sure you want to delete it "
02287 "and all its recurrences?").arg( incidence->summary() ),
02288 i18n("KOrganizer Confirmation"), i18n("Delete All") );
02289 } else {
02290 km = KOMessageBox::fourBtnMsgBox( this, QMessageBox::Warning,
02291 i18n("The calendar item \"%1\" recurs over multiple dates. "
02292 "Do you want to delete only the current one on %2, only all "
02293 "future recurrences, or all its recurrences?" )
02294 .arg( incidence->summary() )
02295 .arg( KGlobal::locale()->formatDate(itemDate)),
02296 i18n("KOrganizer Confirmation"), i18n("Delete C&urrent"),
02297 i18n("Delete &Future"),
02298 i18n("Delete &All"));
02299 }
02300 }
02301
02302 QPair<ResourceCalendar *, QString>p =
02303 CalHelper::incSubResourceCalendar( calendar(), incidence );
02304
02305 switch(km) {
02306 case KMessageBox::Ok:
02307 case KMessageBox::Continue:
02308 mChanger->deleteIncidence( incidence, this );
02309 break;
02310
02311 case KMessageBox::Yes:
02312 if ( mChanger->beginChange( incidence, p.first, p.second ) ) {
02313 Incidence *oldIncidence = incidence->clone();
02314 incidence->recurrence()->addExDate( itemDate );
02315 mChanger->changeIncidence( oldIncidence, incidence,
02316 KOGlobals::RECURRENCE_MODIFIED_ONE_ONLY, this );
02317 mChanger->endChange( incidence, p.first, p.second );
02318 delete oldIncidence;
02319 }
02320 break;
02321 case KMessageBox::No:
02322 if ( mChanger->beginChange( incidence, p.first, p.second ) ) {
02323 Incidence *oldIncidence = incidence->clone();
02324 Recurrence *recur = incidence->recurrence();
02325 recur->setEndDate( itemDate.addDays(-1) );
02326 mChanger->changeIncidence( oldIncidence, incidence,
02327 KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE, this );
02328 mChanger->endChange( incidence, p.first, p.second );
02329 delete oldIncidence;
02330 }
02331 break;
02332 }
02333 } else {
02334 bool doDelete = true;
02335 if ( !force && KOPrefs::instance()->mConfirm ) {
02336 doDelete = ( msgItemDelete( incidence ) == KMessageBox::Continue );
02337 }
02338 if ( doDelete ) {
02339 mChanger->deleteIncidence( incidence, this );
02340 processIncidenceSelection( 0, QDate() );
02341 }
02342 }
02343 }
02344
02345 void CalendarView::connectIncidenceEditor( KOIncidenceEditor *editor )
02346 {
02347 connect( this, SIGNAL( newIncidenceChanger( IncidenceChangerBase* ) ),
02348 editor, SLOT( setIncidenceChanger( IncidenceChangerBase* ) ) );
02349 editor->setIncidenceChanger( mChanger );
02350 }
02351
02352 bool CalendarView::purgeCompletedSubTodos( Todo* todo, bool &allPurged )
02353 {
02354 if ( !todo ) return true;
02355 bool deleteThisTodo = true;
02356 Incidence::List subTodos( todo->relations() );
02357 Incidence *aIncidence;
02358 Todo *aTodo;
02359 Incidence::List::Iterator it;
02360 for ( it = subTodos.begin(); it != subTodos.end(); ++it ) {
02361 aIncidence = *it;
02362 if ( aIncidence && aIncidence->type()=="Todo" ) {
02363 aTodo = static_cast<Todo*>( aIncidence );
02364 deleteThisTodo &= purgeCompletedSubTodos( aTodo, allPurged );
02365 }
02366 }
02367
02368 if ( deleteThisTodo ) {
02369 if ( todo->isCompleted() ) {
02370 if ( !mChanger->deleteIncidence( todo, this ) )
02371 allPurged = false;
02372 } else {
02373 deleteThisTodo = false;
02374 }
02375 } else {
02376 if ( todo->isCompleted() ) {
02377 allPurged = false;
02378 }
02379 }
02380 return deleteThisTodo;
02381 }
02382
02383 void CalendarView::purgeCompleted()
02384 {
02385 int result = KMessageBox::warningContinueCancel(this,
02386 i18n("Delete all completed to-dos?"),i18n("Purge To-dos"),i18n("Purge"));
02387
02388 if (result == KMessageBox::Continue) {
02389 bool allDeleted = true;
02390 startMultiModify( i18n("Purging completed to-dos") );
02391 Todo::List todos = calendar()->rawTodos();
02392 Todo::List rootTodos;
02393 Todo::List::ConstIterator it;
02394 for ( it = todos.begin(); it != todos.end(); ++it ) {
02395 Todo *aTodo = *it;
02396 if ( aTodo && !aTodo->relatedTo() )
02397 rootTodos.append( aTodo );
02398 }
02399
02400 for ( it = rootTodos.begin(); it != rootTodos.end(); ++it ) {
02401 purgeCompletedSubTodos( *it, allDeleted );
02402 }
02403 endMultiModify();
02404 if ( !allDeleted ) {
02405 KMessageBox::information( this, i18n("Unable to purge to-dos with "
02406 "uncompleted children."), i18n("Delete To-do"),
02407 "UncompletedChildrenPurgeTodos" );
02408 }
02409 }
02410 }
02411
02412 void CalendarView::warningChangeFailed( Incidence *incidence )
02413 {
02414 if ( incidence ) {
02415 KMessageBox::sorry(
02416 this,
02417 i18n( "Unable to edit \"%1\" because it is locked by another process." ).
02418 arg( incidence->summary() ) );
02419 }
02420 }
02421
02422 void CalendarView::editCanceled( Incidence *incidence )
02423 {
02424 mCalendar->endChange( incidence );
02425 }
02426
02427 void CalendarView::showErrorMessage( const QString &msg )
02428 {
02429 KMessageBox::error( this, msg );
02430 }
02431
02432 void CalendarView::updateCategories()
02433 {
02434 QStringList allCats( calendar()->categories() );
02435 allCats.sort();
02436 QStringList categories( KOPrefs::instance()->mCustomCategories );
02437 for ( QStringList::ConstIterator si = allCats.constBegin(); si != allCats.constEnd(); ++si ) {
02438 if ( categories.find( *si ) == categories.end() ) {
02439 categories.append( *si );
02440 }
02441 }
02442 KOPrefs::instance()->mCustomCategories = categories;
02443 KOPrefs::instance()->writeConfig();
02444
02445 emit categoriesChanged();
02446 }
02447
02448 void CalendarView::addIncidenceOn( Incidence *incadd, const QDate &dt )
02449 {
02450 if ( !incadd || !mChanger ) {
02451 KMessageBox::sorry(this, i18n("Unable to copy the item to %1.")
02452 .arg( dt.toString() ), i18n("Copying Failed") );
02453 return;
02454 }
02455 Incidence *incidence = mCalendar->incidence( incadd->uid() );
02456 if ( !incidence ) incidence = incadd;
02457
02458 incidence = incidence->clone();
02459 incidence->recreate();
02460
02461 if ( incidence->type() == "Event" ) {
02462 Event *event = static_cast<Event*>(incidence);
02463
02464
02465 QDateTime start = event->dtStart();
02466 QDateTime end = event->dtEnd();
02467
02468 int duration = start.daysTo( end );
02469 start.setDate( dt );
02470 end.setDate( dt.addDays( duration ) );
02471
02472 event->setDtStart( start );
02473 event->setDtEnd( end );
02474
02475 } else if ( incidence->type() == "Todo" ) {
02476 Todo *todo = static_cast<Todo*>(incidence);
02477 QDateTime due = todo->dtDue();
02478 due.setDate( dt );
02479
02480 todo->setDtDue( due );
02481 todo->setHasDueDate( true );
02482 }
02483
02484 QPair<ResourceCalendar *, QString>p = viewSubResourceCalendar();
02485
02486 if ( !mChanger->addIncidence( incidence, p.first, p.second, this ) ) {
02487 KODialogManager::errorSaveIncidence( this, incidence );
02488 delete incidence;
02489 }
02490 }
02491
02492 void CalendarView::moveIncidenceTo( Incidence *incmove, const QDate &dt )
02493 {
02494 if ( !incmove || !mChanger ) {
02495 KMessageBox::sorry( this, i18n("Unable to move the item to %1.")
02496 .arg( dt.toString() ), i18n("Moving Failed") );
02497 return;
02498 }
02499 Incidence *incidence = mCalendar->incidence( incmove->uid() );
02500 if ( !incidence ) {
02501 addIncidenceOn( incidence, dt );
02502 return;
02503 }
02504
02505 Incidence *oldIncidence = incidence->clone();
02506 QPair<ResourceCalendar *, QString>p = viewSubResourceCalendar();
02507
02508 if ( !mChanger->beginChange( incidence, p.first, p.second ) ) {
02509 delete oldIncidence;
02510 return;
02511 }
02512
02513 if ( incidence->type() == "Event" ) {
02514 Event *event = static_cast<Event*>(incidence);
02515
02516
02517 QDateTime start = event->dtStart();
02518 QDateTime end = event->dtEnd();
02519
02520 int duration = start.daysTo( end );
02521 start.setDate( dt );
02522 end.setDate( dt.addDays( duration ) );
02523
02524 event->setDtStart( start );
02525 event->setDtEnd( end );
02526
02527 } else if ( incidence->type() == "Todo" ) {
02528 Todo *todo = static_cast<Todo*>(incidence);
02529 QDateTime due = todo->dtDue();
02530 due.setDate( dt );
02531
02532 todo->setDtDue( due );
02533 todo->setHasDueDate( true );
02534 }
02535 mChanger->changeIncidence( oldIncidence, incidence, KOGlobals::DATE_MODIFIED,this );
02536 mChanger->endChange( incidence, p.first, p.second );
02537 delete oldIncidence;
02538 }
02539
02540 void CalendarView::resourcesChanged()
02541 {
02542 mViewManager->resourcesChanged();
02543 mDateNavigatorContainer->setUpdateNeeded();
02544 updateView();
02545 }
02546
02547 Incidence* CalendarView::singleOccurrenceOrAll( Incidence *inc,
02548 KOGlobals::OccurrenceAction userAction,
02549 KOGlobals::WhichOccurrences &chosenOption,
02550 const QDate &itemDate,
02551 const bool commitToCalendar )
02552 {
02553
02554
02555 if ( inc->type() != "Event" ) {
02556 chosenOption = KOGlobals::ALL;
02557 return inc;
02558 }
02559
02560 Incidence *incToReturn = 0;
02561 Incidence *incSaved = 0;
02562 KOGlobals::WhatChanged whatChanged;
02563
02564 bool dissociationOccurred = false;
02565 const QDate &dt = itemDate.isValid() ? itemDate : activeIncidenceDate();
02566
02567 QString dialogTitle;
02568 QString dialogText;
02569
02570 if ( userAction == KOGlobals::CUT ) {
02571 dialogTitle = i18n( "Cutting Recurring Item" );
02572
02573 dialogText = i18n("The item you try to cut is a recurring item. Do you want to cut "
02574 "only this single occurrence, only future items, "
02575 "or all items in the recurrence?");
02576
02577 } else if ( userAction == KOGlobals::COPY ) {
02578 dialogTitle = i18n( "Copying Recurring Item" );
02579
02580 dialogText = i18n("The item you try to copy is a recurring item. Do you want to copy "
02581 "only this single occurrence, only future items, "
02582 "or all items in the recurrence?");
02583 } else {
02584 dialogTitle = i18n( "Changing Recurring Item" );
02585
02586 dialogText = i18n( "The item you try to change is a recurring item. Shall the changes "
02587 "be applied only to this single occurrence, only to the future items, "
02588 "or to all items in the recurrence?" );
02589 }
02590
02591 int res = KOMessageBox::fourBtnMsgBox( this, QMessageBox::Question,
02592 dialogText,
02593 dialogTitle,
02594 i18n("Only &This Item"), i18n("Only &Future Items"), i18n("&All Occurrences") );
02595 switch ( res ) {
02596 case KMessageBox::Ok:
02597 incToReturn = inc;
02598 chosenOption = KOGlobals::ALL;
02599 break;
02600 case KMessageBox::Yes: {
02601
02602
02603
02604
02605
02606
02607
02608 chosenOption = KOGlobals::ONLY_THIS_ONE;
02609 whatChanged = KOGlobals::RECURRENCE_MODIFIED_ONE_ONLY;
02610 startMultiModify( i18n("Dissociate event from recurrence") );
02611 incSaved = inc->clone();
02612 incToReturn = mCalendar->dissociateOccurrence( inc, dt );
02613 if ( incToReturn ) {
02614 dissociationOccurred = true;
02615 } else {
02616 KMessageBox::sorry( this, i18n("Unable to add the exception item to the "
02617 "calendar. No change will be done."), i18n("Error Occurred") );
02618 incToReturn = 0;
02619 }
02620
02621 break; }
02622 case KMessageBox::No: {
02623
02624
02625
02626
02627
02628
02629 chosenOption = KOGlobals::ONLY_FUTURE;
02630 whatChanged = KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE;
02631 startMultiModify( i18n("Split future recurrences") );
02632 incSaved = inc->clone();
02633 incToReturn = mCalendar->dissociateOccurrence( inc, dt, false );
02634 if ( incToReturn ) {
02635 dissociationOccurred = true;
02636 } else {
02637
02638 KMessageBox::sorry( this, i18n("Unable to add the future items to the "
02639 "calendar. No change will be done."), i18n("Error Occurred") );
02640
02641 incToReturn = 0;
02642 }
02643
02644 break; }
02645 default:
02646 chosenOption = KOGlobals::NONE;
02647 }
02648
02649 if ( dissociationOccurred && commitToCalendar ) {
02650 QPair<ResourceCalendar *, QString>p = viewSubResourceCalendar();
02651 mChanger->addIncidence( incToReturn, p.first, p.second, this );
02652 mChanger->changeIncidence( incSaved, inc, whatChanged, this );
02653 }
02654
02655 return incToReturn;
02656 }
02657
02658 void CalendarView::selectWeek( const QDate &date )
02659 {
02660 if ( KOPrefs::instance()->mWeekNumbersShowWork &&
02661 mViewManager->agendaIsSelected() &&
02662 mViewManager->agendaMode() == KOViewManager::AGENDA_WORK_WEEK ) {
02663 mDateNavigator->selectWorkWeek( date );
02664 } else {
02665 mDateNavigator->selectWeek( date );
02666 }
02667 }
02668
02669 #include "calendarview.moc"