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