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