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
00218 connect( mDateNavigator, SIGNAL( datesSelected( const KCal::DateList & ) ),
00219 mNavigatorBar, SLOT( selectDates( const KCal::DateList & ) ) );
00220
00221 connect( mDateNavigatorContainer, SIGNAL( weekClicked( const QDate & ) ),
00222 this, SLOT( selectWeek( const QDate & ) ) );
00223
00224 connect( mDateNavigatorContainer, SIGNAL( goPrevYear() ),
00225 mDateNavigator, SLOT( selectPreviousYear() ) );
00226 connect( mDateNavigatorContainer, SIGNAL( goNextYear() ),
00227 mDateNavigator, SLOT( selectNextYear() ) );
00228 connect( mDateNavigatorContainer, SIGNAL( goPrevMonth() ),
00229 mDateNavigator, SLOT( selectPreviousMonth() ) );
00230 connect( mDateNavigatorContainer, SIGNAL( goNextMonth() ),
00231 mDateNavigator, SLOT( selectNextMonth() ) );
00232 connect( mDateNavigatorContainer, SIGNAL( goMonth(int) ),
00233 mDateNavigator, SLOT( selectMonth(int) ) );
00234
00235 connect( mDateNavigatorContainer, SIGNAL( goPrevious() ),
00236 mDateNavigator, SLOT( selectPrevious() ) );
00237 connect( mDateNavigatorContainer, SIGNAL( goNext() ),
00238 mDateNavigator, SLOT( selectNext() ) );
00239
00240 connect( mDateNavigatorContainer, SIGNAL( datesSelected( const KCal::DateList & ) ),
00241 mDateNavigator, SLOT( selectDates( const KCal::DateList & ) ) );
00242
00243 connect( mDateNavigatorContainer, SIGNAL(incidenceDropped(Incidence*, const QDate&)),
00244 SLOT( addIncidenceOn( Incidence *, const QDate & ) ) );
00245 connect( mDateNavigatorContainer, 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 mDateNavigatorContainer, SLOT( updateToday() ) );
00254
00255 connect( this, SIGNAL( configChanged() ),
00256 mDateNavigatorContainer, 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 mDateNavigatorContainer->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 mDateNavigator->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 = mDateNavigator->selectedDates();
00411
00412 return dates.first();
00413 }
00414
00415 QDate CalendarView::endDate()
00416 {
00417 DateList dates = mDateNavigator->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 << mDateNavigatorContainer->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 ) mDateNavigator->selectWeek();
00551 else mDateNavigator->selectDates( mDateNavigator->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", mDateNavigator->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 mDateNavigator->selectDate( date );
00650 }
00651
00652 void CalendarView::showDate(const QDate & date)
00653 {
00654 int dateCount = mDateNavigator->datesCount();
00655 if ( dateCount == 7 )
00656 mDateNavigator->selectWeek( date );
00657 else
00658 mDateNavigator->selectDates( date, dateCount );
00659 }
00660
00661 void CalendarView::goToday()
00662 {
00663 mDateNavigator->selectToday();
00664 }
00665
00666 void CalendarView::goNext()
00667 {
00668 if ( dynamic_cast<KOMonthView*>( mViewManager->currentView() ) )
00669 mDateNavigator->selectNextMonth();
00670 else
00671 mDateNavigator->selectNext();
00672 }
00673
00674 void CalendarView::goPrevious()
00675 {
00676 if ( dynamic_cast<KOMonthView*>( mViewManager->currentView() ) )
00677 mDateNavigator->selectPreviousMonth();
00678 else
00679 mDateNavigator->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 mDateNavigatorContainer->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 mDateNavigatorContainer->updateView();
00861 }
00862
00863 void CalendarView::updateView()
00864 {
00865 DateList tmpList = mDateNavigator->selectedDates();
00866
00867
00868 updateView( tmpList.first(), tmpList.last() );
00869 }
00870
00871 void CalendarView::updateUnmanagedViews()
00872 {
00873 mDateNavigatorContainer->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 ( !mDateNavigator->selectedDates().isEmpty() ) {
00978 date = mDateNavigator->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( mDateNavigator->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( mDateNavigator->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, 0, QString() ) ) {
01286 Todo *oldTodo = todo->clone();
01287 todo->setRelatedTo(0);
01288 mChanger->changeIncidence( oldTodo, todo, KOGlobals::RELATION_MODIFIED, this );
01289 mChanger->endChange( todo, 0, QString() );
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, 0, QString() ) ) {
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, 0, QString() );
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
01382 QPair<ResourceCalendar *, QString>p =
01383 CalHelper::incSubResourceCalendar( calendar(), incidence );
01384
01385 if ( !mChanger->beginChange( incidence, p.first, p.second ) ) {
01386 kdDebug(5850) << "Unable to lock incidence " << endl;
01387 return;
01388 }
01389 startMultiModify( i18n("Dissociate occurrence") );
01390 Incidence*oldincidence = incidence->clone();
01391
01392 Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true );
01393
01394 if ( newInc ) {
01395 mChanger->changeIncidence( oldincidence, incidence, KOGlobals::NOTHING_MODIFIED, this );
01396 mChanger->addIncidence( newInc, p.first, p.second, this );
01397 } else {
01398 KMessageBox::sorry( this, i18n("Dissociating the occurrence failed."),
01399 i18n("Dissociating Failed") );
01400 }
01401 mChanger->endChange( incidence, p.first, p.second );
01402 endMultiModify();
01403 delete oldincidence;
01404 }
01405
01406 void CalendarView::dissociateFutureOccurrence( Incidence *incidence, const QDate &date )
01407 {
01408 if ( !incidence || !mChanger ) {
01409 kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
01410 return;
01411 }
01412
01413 QPair<ResourceCalendar *, QString>p =
01414 CalHelper::incSubResourceCalendar( calendar(), incidence );
01415
01416 if ( !mChanger->beginChange( incidence, p.first, p.second ) ) {
01417 kdDebug(5850) << "Unable to lock incidence " << endl;
01418 return;
01419 }
01420 startMultiModify( i18n("Dissociate future occurrences") );
01421 Incidence*oldincidence = incidence->clone();
01422
01423 Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true );
01424 if ( newInc ) {
01425 mChanger->changeIncidence( oldincidence, incidence, KOGlobals::NOTHING_MODIFIED, this );
01426 mChanger->addIncidence( newInc, p.first, p.second, this );
01427 } else {
01428 KMessageBox::sorry( this, i18n("Dissociating the future occurrences failed."),
01429 i18n("Dissociating Failed") );
01430 }
01431 endMultiModify();
01432 mChanger->endChange( incidence, p.first, p.second );
01433 delete oldincidence;
01434 }
01435
01436
01437
01438
01439
01440 void CalendarView::schedule_publish(Incidence *incidence)
01441 {
01442 if (incidence == 0)
01443 incidence = selectedIncidence();
01444
01445 if (!incidence) {
01446 KMessageBox::information( this, i18n("No item selected."),
01447 "PublishNoEventSelected" );
01448 return;
01449 }
01450
01451 PublishDialog *publishdlg = new PublishDialog();
01452 if (incidence->attendeeCount()>0) {
01453 Attendee::List attendees = incidence->attendees();
01454 Attendee::List::ConstIterator it;
01455 for( it = attendees.begin(); it != attendees.end(); ++it ) {
01456 publishdlg->addAttendee( *it );
01457 }
01458 }
01459 if ( publishdlg->exec() == QDialog::Accepted ) {
01460 Incidence *inc = incidence->clone();
01461 inc->registerObserver( 0 );
01462 inc->clearAttendees();
01463
01464
01465 KCal::MailScheduler scheduler( mCalendar );
01466 if ( scheduler.publish( incidence, publishdlg->addresses() ) ) {
01467 KMessageBox::information( this, i18n("The item information was successfully sent."),
01468 i18n("Publishing"), "IncidencePublishSuccess" );
01469 } else {
01470 KMessageBox::error( this, i18n("Unable to publish the item '%1'").arg( incidence->summary() ) );
01471 }
01472 }
01473 delete publishdlg;
01474 }
01475
01476 void CalendarView::schedule_request(Incidence *incidence)
01477 {
01478 schedule(Scheduler::Request,incidence);
01479 }
01480
01481 void CalendarView::schedule_refresh(Incidence *incidence)
01482 {
01483 schedule(Scheduler::Refresh,incidence);
01484 }
01485
01486 void CalendarView::schedule_cancel(Incidence *incidence)
01487 {
01488 schedule(Scheduler::Cancel,incidence);
01489 }
01490
01491 void CalendarView::schedule_add(Incidence *incidence)
01492 {
01493 schedule(Scheduler::Add,incidence);
01494 }
01495
01496 void CalendarView::schedule_reply(Incidence *incidence)
01497 {
01498 schedule(Scheduler::Reply,incidence);
01499 }
01500
01501 void CalendarView::schedule_counter(Incidence *incidence)
01502 {
01503 schedule(Scheduler::Counter,incidence);
01504 }
01505
01506 void CalendarView::schedule_declinecounter(Incidence *incidence)
01507 {
01508 schedule(Scheduler::Declinecounter,incidence);
01509 }
01510
01511 void CalendarView::schedule_forward( Incidence *incidence )
01512 {
01513 if ( !incidence ) {
01514 incidence = selectedIncidence();
01515 }
01516
01517 if ( !incidence ) {
01518 KMessageBox::information(
01519 this,
01520 i18n( "No item selected." ),
01521 i18n( "Forwarding" ),
01522 "ForwardNoEventSelected" );
01523 return;
01524 }
01525
01526 PublishDialog publishdlg;
01527 if ( publishdlg.exec() == QDialog::Accepted ) {
01528 QString recipients = publishdlg.addresses();
01529 if ( incidence->organizer().isEmpty() ) {
01530 incidence->setOrganizer( Person( KOPrefs::instance()->fullName(),
01531 KOPrefs::instance()->email() ) );
01532 }
01533
01534 ICalFormat format;
01535 QString messageText = format.createScheduleMessage( incidence, Scheduler::Request );
01536 KOMailClient mailer;
01537 if ( mailer.mailTo( incidence, recipients, messageText ) ) {
01538 KMessageBox::information(
01539 this,
01540 i18n( "The item information was successfully sent." ),
01541 i18n( "Forwarding" ),
01542 "IncidenceForwardSuccess" );
01543 } else {
01544 KMessageBox::error(
01545 this,
01546 i18n( "Unable to forward the item '%1'" ).arg( incidence->summary() ),
01547 i18n( "Forwarding Error" ) );
01548 }
01549 }
01550 }
01551
01552 void CalendarView::mailFreeBusy( int daysToPublish )
01553 {
01554 QDateTime start = QDateTime::currentDateTime();
01555 QDateTime end = start.addDays(daysToPublish);
01556
01557 FreeBusy *freebusy = new FreeBusy(mCalendar, start, end);
01558 freebusy->setOrganizer( Person( KOPrefs::instance()->fullName(),
01559 KOPrefs::instance()->email() ) );
01560
01561 kdDebug(5850) << "calendarview: schedule_publish_freebusy: startDate: "
01562 << KGlobal::locale()->formatDateTime( start ) << " End Date: "
01563 << KGlobal::locale()->formatDateTime( end ) << endl;
01564
01565 PublishDialog *publishdlg = new PublishDialog();
01566 if ( publishdlg->exec() == QDialog::Accepted ) {
01567
01568 KCal::MailScheduler scheduler( mCalendar );
01569 if ( scheduler.publish( freebusy, publishdlg->addresses() ) ) {
01570 KMessageBox::information( this, i18n("The free/busy information was successfully sent."),
01571 i18n("Sending Free/Busy"), "FreeBusyPublishSuccess" );
01572 } else {
01573 KMessageBox::error( this, i18n("Unable to publish the free/busy data.") );
01574 }
01575 }
01576 delete freebusy;
01577 delete publishdlg;
01578 }
01579
01580 void CalendarView::uploadFreeBusy()
01581 {
01582 KOGroupware::instance()->freeBusyManager()->publishFreeBusy();
01583 }
01584
01585 void CalendarView::schedule(Scheduler::Method method, Incidence *incidence)
01586 {
01587 if ( !incidence ) {
01588 incidence = selectedIncidence();
01589 }
01590
01591 if ( !incidence ) {
01592 KMessageBox::sorry( this, i18n("No item selected."),
01593 "ScheduleNoEventSelected" );
01594 return;
01595 }
01596
01597 if( incidence->attendeeCount() == 0 && method != Scheduler::Publish ) {
01598 KMessageBox::information( this, i18n("The item has no attendees."),
01599 "ScheduleNoIncidences" );
01600 return;
01601 }
01602
01603 Incidence *inc = incidence->clone();
01604 inc->registerObserver( 0 );
01605 inc->clearAttendees();
01606
01607
01608 KCal::MailScheduler scheduler( mCalendar );
01609 if ( scheduler.performTransaction( incidence, method ) ) {
01610 KMessageBox::information( this, i18n("The groupware message for item '%1'"
01611 "was successfully sent.\nMethod: %2")
01612 .arg( incidence->summary() )
01613 .arg( Scheduler::methodName( method ) ),
01614 i18n("Sending Free/Busy"),
01615 "FreeBusyPublishSuccess" );
01616 } else {
01617 KMessageBox::error( this, i18n("Groupware message sending failed. "
01618 "%2 is request/reply/add/cancel/counter/etc.",
01619 "Unable to send the item '%1'.\nMethod: %2")
01620 .arg( incidence->summary() )
01621 .arg( Scheduler::methodName( method ) ) );
01622 }
01623 }
01624
01625 void CalendarView::openAddressbook()
01626 {
01627 KRun::runCommand("kaddressbook");
01628 }
01629
01630 void CalendarView::setModified(bool modified)
01631 {
01632 if (mModified != modified) {
01633 mModified = modified;
01634 emit modifiedChanged(mModified);
01635 }
01636 }
01637
01638 bool CalendarView::isReadOnly()
01639 {
01640 return mReadOnly;
01641 }
01642
01643 void CalendarView::setReadOnly(bool readOnly)
01644 {
01645 if (mReadOnly != readOnly) {
01646 mReadOnly = readOnly;
01647 emit readOnlyChanged(mReadOnly);
01648 }
01649 }
01650
01651 bool CalendarView::isModified()
01652 {
01653 return mModified;
01654 }
01655
01656 void CalendarView::print()
01657 {
01658 #ifndef KORG_NOPRINTER
01659 KOCoreHelper helper;
01660 CalPrinter printer( this, mCalendar, &helper );
01661 connect( this, SIGNAL(configChanged()), &printer, SLOT(updateConfig()) );
01662
01663 KOrg::BaseView *currentView = mViewManager->currentView();
01664
01665 CalPrinterBase::PrintType printType = CalPrinterBase::Month;
01666 if ( currentView ) printType = currentView->printType();
01667
01668 DateList tmpDateList = mDateNavigator->selectedDates();
01669 Incidence::List selectedIncidences;
01670 if ( mViewManager->currentView() ) {
01671 selectedIncidences = mViewManager->currentView()->selectedIncidences();
01672 }
01673 printer.print( printType, tmpDateList.first(), tmpDateList.last(), selectedIncidences );
01674 #endif
01675 }
01676
01677 void CalendarView::exportWeb()
01678 {
01679
01680 HTMLExportSettings *settings = new HTMLExportSettings( "KOrganizer" );
01681
01682
01683 if ( settings ) settings->readConfig();
01684 ExportWebDialog *dlg = new ExportWebDialog( settings, this );
01685 connect( dlg, SIGNAL( exportHTML( HTMLExportSettings* ) ),
01686 this, SIGNAL( exportHTML( HTMLExportSettings* ) ) );
01687 dlg->show();
01688 }
01689
01690 void CalendarView::exportICalendar()
01691 {
01692 QString filename = KFileDialog::getSaveFileName("icalout.ics",i18n("*.ics|ICalendars"),this);
01693 if ( !filename.isEmpty() )
01694 {
01695
01696 if (filename.right(4) != ".ics") filename += ".ics";
01697 if ( QFile( filename ).exists() ) {
01698 if ( KMessageBox::No == KMessageBox::warningYesNo(
01699 this,
01700 i18n( "Do you want to overwrite %1?").arg(filename) ) ) {
01701 return;
01702 }
01703 }
01704 FileStorage storage( mCalendar, filename, new ICalFormat );
01705 storage.save();
01706 }
01707 }
01708
01709 void CalendarView::exportVCalendar()
01710 {
01711 if (mCalendar->journals().count() > 0) {
01712 int result = KMessageBox::warningContinueCancel(this,
01713 i18n("The journal entries can not be exported to a vCalendar file."),
01714 i18n("Data Loss Warning"),i18n("Proceed"),"dontaskVCalExport",
01715 true);
01716 if (result != KMessageBox::Continue) return;
01717 }
01718
01719 QString filename = KFileDialog::getSaveFileName("vcalout.vcs",i18n("*.vcs|vCalendars"),this);
01720 if ( !filename.isEmpty() )
01721 {
01722
01723
01724 if (filename.right(4) != ".vcs") filename += ".vcs";
01725 if ( QFile( filename ).exists() ) {
01726 if ( KMessageBox::No == KMessageBox::warningYesNo(
01727 this,
01728 i18n( "Do you want to overwrite %1?").arg(filename ) ) ) {
01729 return;
01730 }
01731 }
01732 FileStorage storage( mCalendar, filename, new VCalFormat );
01733 storage.save();
01734 }
01735 }
01736
01737 void CalendarView::eventUpdated(Incidence *)
01738 {
01739 setModified();
01740
01741
01742
01743 }
01744
01745 void CalendarView::adaptNavigationUnits()
01746 {
01747 if (mViewManager->currentView()->isEventView()) {
01748 int days = mViewManager->currentView()->currentDateCount();
01749 if (days == 1) {
01750 emit changeNavStringPrev(i18n("&Previous Day"));
01751 emit changeNavStringNext(i18n("&Next Day"));
01752 } else {
01753 emit changeNavStringPrev(i18n("&Previous Week"));
01754 emit changeNavStringNext(i18n("&Next Week"));
01755 }
01756 }
01757 }
01758
01759 void CalendarView::processMainViewSelection( Incidence *incidence, const QDate &date )
01760 {
01761 if ( incidence ) mTodoList->clearSelection();
01762 processIncidenceSelection( incidence, date );
01763 }
01764
01765 void CalendarView::processTodoListSelection( Incidence *incidence, const QDate &date )
01766 {
01767 if ( incidence && mViewManager->currentView() ) {
01768 mViewManager->currentView()->clearSelection();
01769 }
01770 processIncidenceSelection( incidence, date );
01771 }
01772
01773 void CalendarView::processIncidenceSelection( Incidence *incidence, const QDate &date )
01774 {
01775 if ( incidence != mSelectedIncidence ) {
01776
01777 emit incidenceSelected( incidence, date );
01778 }
01779
01780 if ( !incidence ) {
01781 mSelectedIncidence = incidence;
01782 return;
01783 }
01784 if ( incidence == mSelectedIncidence ) {
01785 if ( !incidence->doesRecur() || mSaveDate == date ) {
01786 return;
01787 }
01788 }
01789
01790 mSelectedIncidence = incidence;
01791 mSaveDate = date;
01792
01793 emit incidenceSelected( mSelectedIncidence, date );
01794 bool organizerEvents = false;
01795 bool groupEvents = false;
01796 bool todo = false;
01797 bool subtodo = false;
01798
01799 organizerEvents = KOPrefs::instance()->thatIsMe( incidence->organizer().email() );
01800 groupEvents = incidence->attendeeByMails( KOPrefs::instance()->allEmails() );
01801
01802 if ( incidence->type() == "Todo" ) {
01803 todo = true;
01804 subtodo = ( incidence->relatedTo() != 0 );
01805 }
01806
01807 emit todoSelected( todo );
01808 emit subtodoSelected( subtodo );
01809 emit organizerEventsSelected( organizerEvents );
01810 emit groupEventsSelected( groupEvents );
01811 }
01812
01813
01814 void CalendarView::checkClipboard()
01815 {
01816 #ifndef KORG_NODND
01817 if (ICalDrag::canDecode(QApplication::clipboard()->data())) {
01818 kdDebug(5850) << "CalendarView::checkClipboard() true" << endl;
01819 emit pasteEnabled(true);
01820 } else {
01821 kdDebug(5850) << "CalendarView::checkClipboard() false" << endl;
01822 emit pasteEnabled(false);
01823 }
01824 #endif
01825 }
01826
01827 void CalendarView::showDates(const DateList &selectedDates)
01828 {
01829
01830
01831 if ( mViewManager->currentView() ) {
01832 updateView( selectedDates.first(), selectedDates.last() );
01833 } else {
01834 mViewManager->showAgendaView();
01835 }
01836 }
01837
01838 void CalendarView::editFilters()
01839 {
01840 kdDebug(5850) << "CalendarView::editFilters()" << endl;
01841
01842 CalFilter *filter = mFilters.first();
01843 while(filter) {
01844 kdDebug(5850) << " Filter: " << filter->name() << endl;
01845 filter = mFilters.next();
01846 }
01847
01848 mDialogManager->showFilterEditDialog(&mFilters);
01849 }
01850
01853 void CalendarView::updateFilter()
01854 {
01855 QStringList filters;
01856 CalFilter *filter;
01857
01858 int pos = mFilters.find( mCurrentFilter );
01859 if ( pos < 0 ) {
01860 mCurrentFilter = 0;
01861 }
01862
01863 filters << i18n("No filter");
01864 for ( filter = mFilters.first(); filter; filter = mFilters.next() ) {
01865 filters << filter->name();
01866 }
01867
01868 emit newFilterListSignal( filters );
01869
01870
01871 emit selectFilterSignal( pos+1 );
01872 mCalendar->setFilter( mCurrentFilter );
01873 updateView();
01874 }
01875
01878 void CalendarView::filterActivated( int filterNo )
01879 {
01880 CalFilter *newFilter = 0;
01881 if ( filterNo > 0 && filterNo <= int(mFilters.count()) ) {
01882 newFilter = mFilters.at( filterNo-1 );
01883 }
01884 if ( newFilter != mCurrentFilter ) {
01885 mCurrentFilter = newFilter;
01886 mCalendar->setFilter( mCurrentFilter );
01887 updateView();
01888 }
01889 emit filterChanged();
01890 }
01891
01892 QString CalendarView::currentFilterName() const
01893 {
01894 if ( mCurrentFilter) {
01895 return mCurrentFilter->name();
01896 } else return i18n("No filter");
01897 }
01898
01899 void CalendarView::takeOverEvent()
01900 {
01901 Incidence *incidence = currentSelection();
01902
01903 if (!incidence) return;
01904
01905 incidence->setOrganizer( Person( KOPrefs::instance()->fullName(),
01906 KOPrefs::instance()->email() ) );
01907 incidence->recreate();
01908 incidence->setReadOnly(false);
01909
01910 updateView();
01911 }
01912
01913 void CalendarView::takeOverCalendar()
01914 {
01915 Incidence::List incidences = mCalendar->rawIncidences();
01916 Incidence::List::Iterator it;
01917
01918 for ( it = incidences.begin(); it != incidences.end(); ++it ) {
01919 (*it)->setOrganizer( Person( KOPrefs::instance()->fullName(),
01920 KOPrefs::instance()->email() ) );
01921 (*it)->recreate();
01922 (*it)->setReadOnly(false);
01923 }
01924 updateView();
01925 }
01926
01927 void CalendarView::showIntro()
01928 {
01929 kdDebug(5850) << "To be implemented." << endl;
01930 }
01931
01932 void CalendarView::showDateNavigator( bool show )
01933 {
01934 if( show )
01935 mDateNavigatorContainer->show();
01936 else
01937 mDateNavigatorContainer->hide();
01938 }
01939
01940 void CalendarView::showTodoView( bool show )
01941 {
01942 if( show )
01943 mTodoList->show();
01944 else
01945 mTodoList->hide();
01946 }
01947
01948 void CalendarView::showEventViewer( bool show )
01949 {
01950 if( show )
01951 mEventViewer->show();
01952 else
01953 mEventViewer->hide();
01954 }
01955
01956
01957 void CalendarView::addView(KOrg::BaseView *view)
01958 {
01959 mViewManager->addView(view);
01960 }
01961
01962 void CalendarView::showView(KOrg::BaseView *view)
01963 {
01964 mViewManager->showView(view);
01965 }
01966
01967 void CalendarView::addExtension( CalendarViewExtension::Factory *factory )
01968 {
01969 CalendarViewExtension *extension = factory->create( mLeftSplitter );
01970
01971 mExtensions.append( extension );
01972 }
01973
01974 void CalendarView::toggleExpand()
01975 {
01976 showLeftFrame( mLeftFrame->isHidden() );
01977 }
01978
01979 void CalendarView::showLeftFrame(bool show)
01980 {
01981 if (show) {
01982 mLeftFrame->show();
01983 emit calendarViewExpanded( false );
01984 } else {
01985 mLeftFrame->hide();
01986 emit calendarViewExpanded( true );
01987 }
01988 }
01989
01990 void CalendarView::calendarModified( bool modified, Calendar * )
01991 {
01992 setModified( modified );
01993 }
01994
01995 Todo *CalendarView::selectedTodo()
01996 {
01997 Incidence *incidence = currentSelection();
01998 if ( incidence && incidence->type() == "Todo" ) {
01999 return static_cast<Todo *>( incidence );
02000 }
02001 incidence = 0;
02002
02003 Incidence::List selectedIncidences = mTodoList->selectedIncidences();
02004 if ( !selectedIncidences.isEmpty() ) incidence = selectedIncidences.first();
02005 if ( incidence && incidence->type() == "Todo" ) {
02006 return static_cast<Todo *>( incidence );
02007 }
02008
02009 return 0;
02010 }
02011
02012 void CalendarView::dialogClosing( Incidence *in )
02013 {
02014
02015 mChanger->endChange( in, 0, QString() );
02016 mDialogList.remove( in );
02017 }
02018
02019 Incidence *CalendarView::currentSelection()
02020 {
02021 return mViewManager->currentSelection();
02022 }
02023
02024 Incidence* CalendarView::selectedIncidence()
02025 {
02026 Incidence *incidence = currentSelection();
02027 if ( !incidence ) {
02028 Incidence::List selectedIncidences = mTodoList->selectedIncidences();
02029 if ( !selectedIncidences.isEmpty() )
02030 incidence = selectedIncidences.first();
02031 }
02032 return incidence;
02033 }
02034
02035 void CalendarView::showIncidence()
02036 {
02037 showIncidence( selectedIncidence() );
02038 }
02039
02040 void CalendarView::editIncidence()
02041 {
02042 editIncidence( selectedIncidence(), activeIncidenceDate() );
02043 }
02044
02045 bool CalendarView::editIncidence( const QString &uid )
02046 {
02047 return editIncidence( mCalendar->incidence( uid ), QDate() );
02048 }
02049
02050 bool CalendarView::editIncidence( const QString &uid, const QDate &date )
02051 {
02052 return editIncidence( mCalendar->incidence( uid ), date );
02053 }
02054
02055 void CalendarView::deleteIncidence()
02056 {
02057 deleteIncidence( selectedIncidence() );
02058 }
02059
02060 void CalendarView::cutIncidence(Incidence *)
02061 {
02062 edit_cut();
02063 }
02064
02065 void CalendarView::copyIncidence(Incidence *)
02066 {
02067 edit_copy();
02068 }
02069
02070 void CalendarView::pasteIncidence()
02071 {
02072 edit_paste();
02073 }
02074
02075 void CalendarView::showIncidence( Incidence *incidence )
02076 {
02077 KOEventViewerDialog *eventViewer = new KOEventViewerDialog( calendar(), this );
02078 eventViewer->setIncidence( incidence, QDate() );
02079 eventViewer->show();
02080 }
02081
02082 bool CalendarView::editIncidence( Incidence *incidence )
02083 {
02084 return editIncidence( incidence, QDate(), false );
02085 }
02086
02087 bool CalendarView::editIncidence( Incidence *incidence, const QDate &date, bool isCounter )
02088 {
02089 kdDebug(5850) << "CalendarView::editEvent()" << endl;
02090
02091 CalendarResources *stdcal = dynamic_cast<CalendarResources *>( mCalendar );
02092 if( stdcal && !stdcal->hasCalendarResources() ) {
02093 KMessageBox::sorry(
02094 this,
02095 i18n( "No resources found. We can not edit the item." ) );
02096 return false;
02097 }
02098
02099
02100
02101
02102
02103 QWidget *tmpparent = 0;
02104 if ( stdcal ) {
02105 tmpparent = stdcal->dialogParentWidget();
02106 stdcal->setDialogParentWidget( this );
02107 }
02108
02109 if ( !incidence ) {
02110 kdDebug(5850) << "Empty Incidence" << endl;
02111 KNotifyClient::beep();
02112 return false;
02113 }
02114
02115 if ( !mChanger ) {
02116 kdDebug(5850) << "Empty Changer" << endl;
02117 KNotifyClient::beep();
02118 return false;
02119 }
02120
02121 KOIncidenceEditor *tmp = editorDialog( incidence );
02122 if ( tmp ) {
02123 kdDebug(5850) << "CalendarView::editIncidence() in List" << endl;
02124 tmp->reload();
02125 tmp->raise();
02126 tmp->show();
02127 return true;
02128 }
02129
02130 if ( incidence->isReadOnly() ) {
02131 showIncidence( incidence );
02132 return true;
02133 }
02134
02135 QPair<ResourceCalendar *, QString>p =
02136 CalHelper::incSubResourceCalendar( calendar(), incidence );
02137
02138 Incidence *savedIncidence = incidence->clone();
02139 Incidence *incToChange;
02140
02141 if ( incidence->doesRecur() ) {
02142 KOGlobals::WhichOccurrences chosenOption;
02143 incToChange = singleOccurrenceOrAll( incidence, KOGlobals::EDIT, chosenOption, date );
02144 } else {
02145 incToChange = incidence;
02146 }
02147
02148
02149 if ( incToChange ) {
02150 if ( !isCounter && !mChanger->beginChange( incToChange, p.first, p.second ) ) {
02151 warningChangeFailed( incToChange );
02152 showIncidence( incToChange );
02153
02154 return false;
02155 }
02156
02157 kdDebug(5850) << "CalendarView::editIncidence() new IncidenceEditor" << endl;
02158 KOIncidenceEditor *incidenceEditor = mDialogManager->getEditor( incToChange );
02159 connectIncidenceEditor( incidenceEditor );
02160
02161 mDialogList.insert( incToChange, incidenceEditor );
02162 if ( incidence != incToChange ) {
02163 incidenceEditor->setRecurringIncidence( savedIncidence, incidence );
02164 }
02165 incidenceEditor->setResource( p.first, p.second );
02166 incidenceEditor->editIncidence( incToChange, date, mCalendar );
02167 incidenceEditor->show();
02168 return true;
02169 } else {
02170 return false;
02171 }
02172 }
02173
02174 void CalendarView::deleteSubTodosIncidence ( Todo *todo )
02175 {
02176 if( !todo ) return;
02177
02178 Incidence::List subTodos( todo->relations() );
02179 Incidence::List::Iterator it;
02180 Incidence *aIncidence;
02181 Todo *aTodo;
02182
02183 for ( it= subTodos.begin(); it != subTodos.end(); ++it ) {
02184 aIncidence = *it;
02185 if( aIncidence && aIncidence->type() == "Todo" ) {
02186 aTodo = static_cast<Todo*>( aIncidence );
02187 deleteSubTodosIncidence ( aTodo );
02188 }
02189 }
02190 mChanger->deleteIncidence ( todo, this );
02191 }
02192
02193 void CalendarView::deleteTodoIncidence ( Todo *todo, bool force )
02194 {
02195 if ( !todo ) return ;
02196
02197
02198 if (todo->relations().isEmpty() ) {
02199 bool doDelete = true;
02200 if ( !force && KOPrefs::instance()->mConfirm ) {
02201 doDelete = ( msgItemDelete( todo ) == KMessageBox::Continue );
02202 }
02203 if ( doDelete )
02204 mChanger->deleteIncidence( todo, this );
02205 return;
02206 }
02207
02208
02209 int km = KMessageBox::No;
02210 if ( !force ) {
02211 km = KMessageBox::questionYesNoCancel(
02212 this,
02213 i18n("The item \"%1\" has sub-to-dos. "
02214 "Do you want to delete just this item and "
02215 "make all its sub-to-dos independent, or "
02216 "delete the to-do with all its sub-to-dos?"
02217 ).arg( todo->summary() ),
02218 i18n("KOrganizer Confirmation"),
02219 i18n("Delete Only This"),
02220 i18n("Delete All"));
02221 }
02222 startMultiModify( i18n("Deleting sub-to-dos" ) );
02223
02224 if( km == KMessageBox::Yes ) {
02225
02226 makeSubTodosIndependents ( todo );
02227 mChanger->deleteIncidence( todo, this );
02228 } else if ( km == KMessageBox::No ) {
02229
02230
02231 deleteSubTodosIncidence ( todo );
02232 }
02233 endMultiModify();
02234 }
02235
02236 void CalendarView::deleteIncidence(Incidence *incidence, bool force)
02237 {
02238 if ( !incidence || !mChanger ) {
02239 if ( !force ) {
02240 KNotifyClient::beep();
02241 }
02242 return;
02243 }
02244 if ( incidence->isReadOnly() ) {
02245 if ( !force ) {
02246 KMessageBox::information( this, i18n("The item \"%1\" is marked read-only "
02247 "and cannot be deleted; it probably belongs to "
02248 "a read-only calendar resource.")
02249 .arg(incidence->summary()),
02250 i18n("Removing not possible"),
02251 "deleteReadOnlyIncidence" );
02252 }
02253 return;
02254 }
02255
02256 CanDeleteIncidenceVisitor v;
02257
02258
02259
02260 if ( !v.act( incidence, this ) )
02261 return;
02262
02263
02264 if ( incidence && incidence->type()=="Todo" ) {
02265 deleteTodoIncidence( static_cast<Todo*>(incidence), force );
02266 return;
02267 }
02268
02269 if ( incidence->doesRecur() ) {
02270 QDate itemDate = mViewManager->currentSelectionDate();
02271 kdDebug(5850) << "Recurrence-Date: " << itemDate.toString() << endl;
02272 int km = KMessageBox::Ok;
02273 if ( !force ) {
02274 if ( !itemDate.isValid() ) {
02275 kdDebug(5850) << "Date Not Valid" << endl;
02276 km = KMessageBox::warningContinueCancel(this,
02277 i18n("The calendar item \"%1\" recurs over multiple dates; "
02278 "are you sure you want to delete it "
02279 "and all its recurrences?").arg( incidence->summary() ),
02280 i18n("KOrganizer Confirmation"), i18n("Delete All") );
02281 } else {
02282 km = KOMessageBox::fourBtnMsgBox( this, QMessageBox::Warning,
02283 i18n("The calendar item \"%1\" recurs over multiple dates. "
02284 "Do you want to delete only the current one on %2, only all "
02285 "future recurrences, or all its recurrences?" )
02286 .arg( incidence->summary() )
02287 .arg( KGlobal::locale()->formatDate(itemDate)),
02288 i18n("KOrganizer Confirmation"), i18n("Delete C&urrent"),
02289 i18n("Delete &Future"),
02290 i18n("Delete &All"));
02291 }
02292 }
02293
02294 QPair<ResourceCalendar *, QString>p =
02295 CalHelper::incSubResourceCalendar( calendar(), incidence );
02296
02297 switch(km) {
02298 case KMessageBox::Ok:
02299 case KMessageBox::Continue:
02300 mChanger->deleteIncidence( incidence, this );
02301 break;
02302
02303 case KMessageBox::Yes:
02304 if ( mChanger->beginChange( incidence, p.first, p.second ) ) {
02305 Incidence *oldIncidence = incidence->clone();
02306 incidence->recurrence()->addExDate( itemDate );
02307 mChanger->changeIncidence( oldIncidence, incidence,
02308 KOGlobals::RECURRENCE_MODIFIED_ONE_ONLY, this );
02309 mChanger->endChange( incidence, p.first, p.second );
02310 delete oldIncidence;
02311 }
02312 break;
02313 case KMessageBox::No:
02314 if ( mChanger->beginChange( incidence, p.first, p.second ) ) {
02315 Incidence *oldIncidence = incidence->clone();
02316 Recurrence *recur = incidence->recurrence();
02317 recur->setEndDate( itemDate.addDays(-1) );
02318 mChanger->changeIncidence( oldIncidence, incidence,
02319 KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE, this );
02320 mChanger->endChange( incidence, p.first, p.second );
02321 delete oldIncidence;
02322 }
02323 break;
02324 }
02325 } else {
02326 bool doDelete = true;
02327 if ( !force && KOPrefs::instance()->mConfirm ) {
02328 doDelete = ( msgItemDelete( incidence ) == KMessageBox::Continue );
02329 }
02330 if ( doDelete ) {
02331 mChanger->deleteIncidence( incidence, this );
02332 processIncidenceSelection( 0, QDate() );
02333 }
02334 }
02335 }
02336
02337 void CalendarView::connectIncidenceEditor( KOIncidenceEditor *editor )
02338 {
02339 connect( this, SIGNAL( newIncidenceChanger( IncidenceChangerBase* ) ),
02340 editor, SLOT( setIncidenceChanger( IncidenceChangerBase* ) ) );
02341 editor->setIncidenceChanger( mChanger );
02342 }
02343
02344 bool CalendarView::purgeCompletedSubTodos( Todo* todo, bool &allPurged )
02345 {
02346 if ( !todo ) return true;
02347 bool deleteThisTodo = true;
02348 Incidence::List subTodos( todo->relations() );
02349 Incidence *aIncidence;
02350 Todo *aTodo;
02351 Incidence::List::Iterator it;
02352 for ( it = subTodos.begin(); it != subTodos.end(); ++it ) {
02353 aIncidence = *it;
02354 if ( aIncidence && aIncidence->type()=="Todo" ) {
02355 aTodo = static_cast<Todo*>( aIncidence );
02356 deleteThisTodo &= purgeCompletedSubTodos( aTodo, allPurged );
02357 }
02358 }
02359
02360 if ( deleteThisTodo ) {
02361 if ( todo->isCompleted() ) {
02362 if ( !mChanger->deleteIncidence( todo, this ) )
02363 allPurged = false;
02364 } else {
02365 deleteThisTodo = false;
02366 }
02367 } else {
02368 if ( todo->isCompleted() ) {
02369 allPurged = false;
02370 }
02371 }
02372 return deleteThisTodo;
02373 }
02374
02375 void CalendarView::purgeCompleted()
02376 {
02377 int result = KMessageBox::warningContinueCancel(this,
02378 i18n("Delete all completed to-dos?"),i18n("Purge To-dos"),i18n("Purge"));
02379
02380 if (result == KMessageBox::Continue) {
02381 bool allDeleted = true;
02382 startMultiModify( i18n("Purging completed to-dos") );
02383 Todo::List todos = calendar()->rawTodos();
02384 Todo::List rootTodos;
02385 Todo::List::ConstIterator it;
02386 for ( it = todos.begin(); it != todos.end(); ++it ) {
02387 Todo *aTodo = *it;
02388 if ( aTodo && !aTodo->relatedTo() )
02389 rootTodos.append( aTodo );
02390 }
02391
02392 for ( it = rootTodos.begin(); it != rootTodos.end(); ++it ) {
02393 purgeCompletedSubTodos( *it, allDeleted );
02394 }
02395 endMultiModify();
02396 if ( !allDeleted ) {
02397 KMessageBox::information( this, i18n("Unable to purge to-dos with "
02398 "uncompleted children."), i18n("Delete To-do"),
02399 "UncompletedChildrenPurgeTodos" );
02400 }
02401 }
02402 }
02403
02404 void CalendarView::warningChangeFailed( Incidence *incidence )
02405 {
02406 if ( incidence ) {
02407 KMessageBox::sorry(
02408 this,
02409 i18n( "Unable to edit \"%1\" because it is locked by another process." ).
02410 arg( incidence->summary() ) );
02411 }
02412 }
02413
02414 void CalendarView::editCanceled( Incidence *incidence )
02415 {
02416 mCalendar->endChange( incidence );
02417 }
02418
02419 void CalendarView::showErrorMessage( const QString &msg )
02420 {
02421 KMessageBox::error( this, msg );
02422 }
02423
02424 void CalendarView::updateCategories()
02425 {
02426 QStringList allCats( calendar()->categories() );
02427 allCats.sort();
02428 QStringList categories( KOPrefs::instance()->mCustomCategories );
02429 for ( QStringList::ConstIterator si = allCats.constBegin(); si != allCats.constEnd(); ++si ) {
02430 if ( categories.find( *si ) == categories.end() ) {
02431 categories.append( *si );
02432 }
02433 }
02434 KOPrefs::instance()->mCustomCategories = categories;
02435 KOPrefs::instance()->writeConfig();
02436
02437 emit categoriesChanged();
02438 }
02439
02440 void CalendarView::addIncidenceOn( Incidence *incadd, const QDate &dt )
02441 {
02442 if ( !incadd || !mChanger ) {
02443 KMessageBox::sorry(this, i18n("Unable to copy the item to %1.")
02444 .arg( dt.toString() ), i18n("Copying Failed") );
02445 return;
02446 }
02447 Incidence *incidence = mCalendar->incidence( incadd->uid() );
02448 if ( !incidence ) incidence = incadd;
02449
02450 incidence = incidence->clone();
02451 incidence->recreate();
02452
02453 if ( incidence->type() == "Event" ) {
02454 Event *event = static_cast<Event*>(incidence);
02455
02456
02457 QDateTime start = event->dtStart();
02458 QDateTime end = event->dtEnd();
02459
02460 int duration = start.daysTo( end );
02461 start.setDate( dt );
02462 end.setDate( dt.addDays( duration ) );
02463
02464 event->setDtStart( start );
02465 event->setDtEnd( end );
02466
02467 } else if ( incidence->type() == "Todo" ) {
02468 Todo *todo = static_cast<Todo*>(incidence);
02469 QDateTime due = todo->dtDue();
02470 due.setDate( dt );
02471
02472 todo->setDtDue( due );
02473 todo->setHasDueDate( true );
02474 }
02475
02476 QPair<ResourceCalendar *, QString>p = viewSubResourceCalendar();
02477
02478 if ( !mChanger->addIncidence( incidence, p.first, p.second, this ) ) {
02479 KODialogManager::errorSaveIncidence( this, incidence );
02480 delete incidence;
02481 }
02482 }
02483
02484 void CalendarView::moveIncidenceTo( Incidence *incmove, const QDate &dt )
02485 {
02486 if ( !incmove || !mChanger ) {
02487 KMessageBox::sorry( this, i18n("Unable to move the item to %1.")
02488 .arg( dt.toString() ), i18n("Moving Failed") );
02489 return;
02490 }
02491 Incidence *incidence = mCalendar->incidence( incmove->uid() );
02492 if ( !incidence ) {
02493 addIncidenceOn( incidence, dt );
02494 return;
02495 }
02496
02497 Incidence *oldIncidence = incidence->clone();
02498 QPair<ResourceCalendar *, QString>p = viewSubResourceCalendar();
02499
02500 if ( !mChanger->beginChange( incidence, p.first, p.second ) ) {
02501 delete oldIncidence;
02502 return;
02503 }
02504
02505 if ( incidence->type() == "Event" ) {
02506 Event *event = static_cast<Event*>(incidence);
02507
02508
02509 QDateTime start = event->dtStart();
02510 QDateTime end = event->dtEnd();
02511
02512 int duration = start.daysTo( end );
02513 start.setDate( dt );
02514 end.setDate( dt.addDays( duration ) );
02515
02516 event->setDtStart( start );
02517 event->setDtEnd( end );
02518
02519 } else if ( incidence->type() == "Todo" ) {
02520 Todo *todo = static_cast<Todo*>(incidence);
02521 QDateTime due = todo->dtDue();
02522 due.setDate( dt );
02523
02524 todo->setDtDue( due );
02525 todo->setHasDueDate( true );
02526 }
02527 mChanger->changeIncidence( oldIncidence, incidence, KOGlobals::DATE_MODIFIED,this );
02528 mChanger->endChange( incidence, p.first, p.second );
02529 delete oldIncidence;
02530 }
02531
02532 void CalendarView::resourcesChanged()
02533 {
02534 mViewManager->resourcesChanged();
02535 mDateNavigatorContainer->setUpdateNeeded();
02536 updateView();
02537 }
02538
02539 Incidence* CalendarView::singleOccurrenceOrAll( Incidence *inc,
02540 KOGlobals::OccurrenceAction userAction,
02541 KOGlobals::WhichOccurrences &chosenOption,
02542 const QDate &itemDate,
02543 const bool commitToCalendar )
02544 {
02545
02546
02547 if ( inc->type() != "Event" ) {
02548 chosenOption = KOGlobals::ALL;
02549 return inc;
02550 }
02551
02552 Incidence *incToReturn = 0;
02553 Incidence *incSaved = 0;
02554 KOGlobals::WhatChanged whatChanged;
02555
02556 bool dissociationOccurred = false;
02557 const QDate &dt = itemDate.isValid() ? itemDate : activeIncidenceDate();
02558
02559 QString dialogTitle;
02560 QString dialogText;
02561
02562 if ( userAction == KOGlobals::CUT ) {
02563 dialogTitle = i18n( "Cutting Recurring Item" );
02564
02565 dialogText = i18n("The item you try to cut is a recurring item. Do you want to cut "
02566 "only this single occurrence, only future items, "
02567 "or all items in the recurrence?");
02568
02569 } else if ( userAction == KOGlobals::COPY ) {
02570 dialogTitle = i18n( "Copying Recurring Item" );
02571
02572 dialogText = i18n("The item you try to copy is a recurring item. Do you want to copy "
02573 "only this single occurrence, only future items, "
02574 "or all items in the recurrence?");
02575 } else {
02576 dialogTitle = i18n( "Changing Recurring Item" );
02577
02578 dialogText = i18n( "The item you try to change is a recurring item. Shall the changes "
02579 "be applied only to this single occurrence, only to the future items, "
02580 "or to all items in the recurrence?" );
02581 }
02582
02583 int res = KOMessageBox::fourBtnMsgBox( this, QMessageBox::Question,
02584 dialogText,
02585 dialogTitle,
02586 i18n("Only &This Item"), i18n("Only &Future Items"), i18n("&All Occurrences") );
02587 switch ( res ) {
02588 case KMessageBox::Ok:
02589 incToReturn = inc;
02590 chosenOption = KOGlobals::ALL;
02591 break;
02592 case KMessageBox::Yes: {
02593
02594
02595
02596
02597
02598
02599
02600 chosenOption = KOGlobals::ONLY_THIS_ONE;
02601 whatChanged = KOGlobals::RECURRENCE_MODIFIED_ONE_ONLY;
02602 startMultiModify( i18n("Dissociate event from recurrence") );
02603 incSaved = inc->clone();
02604 incToReturn = mCalendar->dissociateOccurrence( inc, dt );
02605 if ( incToReturn ) {
02606 dissociationOccurred = true;
02607 } else {
02608 KMessageBox::sorry( this, i18n("Unable to add the exception item to the "
02609 "calendar. No change will be done."), i18n("Error Occurred") );
02610 incToReturn = 0;
02611 }
02612
02613 break; }
02614 case KMessageBox::No: {
02615
02616
02617
02618
02619
02620
02621 chosenOption = KOGlobals::ONLY_FUTURE;
02622 whatChanged = KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE;
02623 startMultiModify( i18n("Split future recurrences") );
02624 incSaved = inc->clone();
02625 incToReturn = mCalendar->dissociateOccurrence( inc, dt, false );
02626 if ( incToReturn ) {
02627 dissociationOccurred = true;
02628 } else {
02629
02630 KMessageBox::sorry( this, i18n("Unable to add the future items to the "
02631 "calendar. No change will be done."), i18n("Error Occurred") );
02632
02633 incToReturn = 0;
02634 }
02635
02636 break; }
02637 default:
02638 chosenOption = KOGlobals::NONE;
02639 }
02640
02641 if ( dissociationOccurred && commitToCalendar ) {
02642 QPair<ResourceCalendar *, QString>p = viewSubResourceCalendar();
02643 mChanger->addIncidence( incToReturn, p.first, p.second, this );
02644 mChanger->changeIncidence( incSaved, inc, whatChanged, this );
02645 }
02646
02647 return incToReturn;
02648 }
02649
02650 void CalendarView::selectWeek( const QDate &date )
02651 {
02652 if ( KOPrefs::instance()->mWeekNumbersShowWork &&
02653 mViewManager->currentView() == mViewManager->agendaView() &&
02654 mViewManager->agendaMode() == KOViewManager::AGENDA_WORK_WEEK ) {
02655 mDateNavigator->selectWorkWeek( date );
02656 } else {
02657 mDateNavigator->selectWeek( date );
02658 }
02659 }
02660
02661 #include "calendarview.moc"