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