korganizer

calendarview.cpp
1/*
2 This file is part of KOrganizer.
3
4 Copyright (c) 1997, 1998, 1999
5 Preston Brown (preston.brown@yale.edu)
6 Fester Zigterman (F.J.F.ZigtermanRustenburg@student.utwente.nl)
7 Ian Dawes (iadawes@globalserve.net)
8 Laszlo Boloni (boloni@cs.purdue.edu)
9
10 Copyright (c) 2000, 2001, 2002, 2003, 2004
11 Cornelius Schumacher <schumacher@kde.org>
12 Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27
28 As a special exception, permission is given to link this program
29 with any edition of TQt, and distribute the resulting executable,
30 without including the source code for TQt in the source distribution.
31*/
32
33#include "calendarview.h"
34
35#ifndef KORG_NOPRINTER
36#include "calprinter.h"
37#endif
38#include "koeventeditor.h"
39#include "kotodoeditor.h"
40#include "kojournaleditor.h"
41#include "koprefs.h"
42#include "koeventviewerdialog.h"
43#include "publishdialog.h"
44#include "koglobals.h"
45#include "koviewmanager.h"
46#include "koagendaview.h"
47#include "kodialogmanager.h"
48#include "statusdialog.h"
49#include "datenavigatorcontainer.h"
50#include "kotodoview.h"
51#include "datenavigator.h"
52#include "resourceview.h"
53#include "navigatorbar.h"
54#include "history.h"
55#include "kogroupware.h"
56#include "freebusymanager.h"
57#include "komonthview.h"
58#include "datechecker.h"
59#include "komessagebox.h"
60#include "exportwebdialog.h"
61#include "kocorehelper.h"
62#include "incidencechanger.h"
63#include "kholidays.h"
64#include "mailscheduler.h"
65#include "komailclient.h"
66#include "multiagendaview.h"
67
68#include <libkcal/calhelper.h>
69#include <libkcal/vcaldrag.h>
70#include <libkcal/icaldrag.h>
71#include <libkcal/icalformat.h>
72#include <libkcal/vcalformat.h>
73#include <libkcal/scheduler.h>
74#include <libkcal/calendarlocal.h>
75#include <libkcal/journal.h>
76#include <libkcal/calfilter.h>
77#include <libkcal/attendee.h>
78#include <libkcal/dndfactory.h>
79#include <libkcal/freebusy.h>
80#include <libkcal/filestorage.h>
82#include <libkcal/calendarnull.h>
83#include <libkcal/htmlexportsettings.h>
84
85#include <tdeglobal.h>
86#include <kdebug.h>
87#include <tdestandarddirs.h>
88#include <tdefiledialog.h>
89#include <tdemessagebox.h>
90#include <knotifyclient.h>
91#include <tdeconfig.h>
92#include <krun.h>
93#include <kdirwatch.h>
94
95#include <tqapplication.h>
96#include <tqclipboard.h>
97#include <tqcursor.h>
98#include <tqmultilineedit.h>
99#include <tqtimer.h>
100#include <tqwidgetstack.h>
101#include <tqptrlist.h>
102#include <tqfile.h>
103#include <tqlayout.h>
104#ifndef KORG_NOSPLITTER
105#include <tqsplitter.h>
106#endif
107#include <tqvbox.h>
108#include <tqwhatsthis.h>
109
110#include <stdlib.h>
111#include <assert.h>
112
113using namespace KOrg;
114
115CalendarView::CalendarView( TQWidget *parent, const char *name )
116 : CalendarViewBase( parent, name ),
117 mHistory( 0 ),
118 mCalendar( CalendarNull::self() ),
119 mChanger( 0 )
120{
121 kdDebug(5850) << "CalendarView::CalendarView( Calendar )" << endl;
122
123 mViewManager = new KOViewManager( this );
124 mDialogManager = new KODialogManager( this );
125
126 mModified = false;
127 mReadOnly = false;
128 mSelectedIncidence = 0;
129
130 mFilters.setAutoDelete( true );
131
132 mExtensions.setAutoDelete( true );
133
134 mDateNavigator = new DateNavigator( this );
135 mDateChecker = new DateChecker( this );
136
137 TQBoxLayout *topLayout = new TQVBoxLayout( this );
138
139#ifndef KORG_NOSPLITTER
140 // create the main layout frames.
141 mPanner = new TQSplitter( TQt::Horizontal, this,
142 "CalendarView::Panner" );
143 topLayout->addWidget( mPanner );
144
145 mLeftSplitter = new TQSplitter( TQt::Vertical, mPanner,
146 "CalendarView::LeftFrame" );
147// mPanner->setResizeMode( mLeftSplitter, TQSplitter::Stretch );
148
149 mDateNavigatorContainer = new DateNavigatorContainer( mLeftSplitter,
150 "CalendarView::DateNavigator" );
151
152// mLeftSplitter->setResizeMode( mDateNavigatorContainer, TQSplitter::Stretch );
153 mLeftSplitter->setCollapsible( mDateNavigatorContainer, true );
154 mTodoList = new KOTodoView( CalendarNull::self(), mLeftSplitter, "todolist" );
155
156 mEventViewer = new KOEventViewer( CalendarNull::self(), mLeftSplitter,"EventViewer" );
157
158 TQVBox *rightBox = new TQVBox( mPanner );
159 mNavigatorBar = new NavigatorBar( rightBox );
160 mRightFrame = new TQWidgetStack( rightBox );
161 rightBox->setStretchFactor( mRightFrame, 1 );
162
163 mLeftFrame = mLeftSplitter;
164#else
165 TQWidget *mainBox;
166 TQWidget *leftFrame;
167
168 if ( KOPrefs::instance()->mVerticalScreen ) {
169 mainBox = new TQVBox( this );
170 leftFrame = new TQHBox( mainBox );
171 } else {
172 mainBox = new TQHBox( this );
173 leftFrame = new TQVBox( mainBox );
174 }
175
176 topLayout->addWidget( mainBox );
177
178 mDateNavigatorContainer = new KDateNavigator( leftFrame, true,
179 "CalendarView::DateNavigator",
180 TQDate::currentDate() );
181 mTodoList = new KOTodoView( CalendarNull::self(), leftFrame, "todolist" );
182
183 mEventViewer = new KOEventViewer ( CalendarNull::self(), leftFrame, "EventViewer" );
184
185 TQWidget *rightBox = new TQWidget( mainBox );
186 TQBoxLayout *rightLayout = new TQVBoxLayout( rightBox );
187
188 mNavigatorBar = new NavigatorBar( TQDate::currentDate(), rightBox );
189 rightLayout->addWidget( mNavigatorBar );
190
191 mRightFrame = new TQWidgetStack( rightBox );
192 rightLayout->addWidget( mRightFrame );
193
194 mLeftFrame = leftFrame;
195
196 if ( KOPrefs::instance()->mVerticalScreen ) {
197 // mTodoList->setFixedHeight( 60 );
198 mTodoList->setFixedHeight( mDateNavigatorContainer->sizeHint().height() );
199 }
200#endif
201
202 // Signals emited by mDateNavigator
203 connect( mDateNavigator, TQ_SIGNAL( datesSelected( const KCal::DateList &, const TQDate & ) ),
204 TQ_SLOT( showDates( const KCal::DateList &, const TQDate & ) ) );
205
206 // Signals emited by mNavigatorBar
207 connect( mNavigatorBar, TQ_SIGNAL( prevYearClicked() ),
208 mDateNavigator, TQ_SLOT( selectPreviousYear() ) );
209 connect( mNavigatorBar, TQ_SIGNAL( nextYearClicked() ),
210 mDateNavigator, TQ_SLOT( selectNextYear() ) );
211 connect( mNavigatorBar, TQ_SIGNAL( prevMonthClicked() ),
212 mDateNavigator, TQ_SLOT( selectPreviousMonth() ) );
213 connect( mNavigatorBar, TQ_SIGNAL( nextMonthClicked() ),
214 mDateNavigator, TQ_SLOT( selectNextMonth() ) );
215 connect( mNavigatorBar, TQ_SIGNAL( monthSelected(int) ),
216 mDateNavigator, TQ_SLOT( selectMonth(int) ) );
217 connect( mNavigatorBar, TQ_SIGNAL( yearSelected(int)),
218 mDateNavigator, TQ_SLOT(selectYear(int)) );
219
220
221 // Signals emited by mDateNavigatorContainer
222 connect( mDateNavigatorContainer, TQ_SIGNAL( weekClicked( const TQDate & ) ),
223 this, TQ_SLOT( selectWeek( const TQDate & ) ) );
224 connect( mDateNavigatorContainer, TQ_SIGNAL( prevMonthClicked(const TQDate &, const TQDate &, const TQDate &) ),
225 mDateNavigator, TQ_SLOT( selectPreviousMonth(const TQDate &, const TQDate &, const TQDate &) ) );
226 connect( mDateNavigatorContainer, TQ_SIGNAL( nextMonthClicked(const TQDate &, const TQDate &, const TQDate &) ),
227 mDateNavigator, TQ_SLOT( selectNextMonth(const TQDate &, const TQDate &, const TQDate &) ) );
228 connect( mDateNavigatorContainer, TQ_SIGNAL( prevYearClicked() ),
229 mDateNavigator, TQ_SLOT( selectPreviousYear() ) );
230 connect( mDateNavigatorContainer, TQ_SIGNAL( nextYearClicked() ),
231 mDateNavigator, TQ_SLOT( selectNextYear() ) );
232 connect( mDateNavigatorContainer, TQ_SIGNAL( monthSelected(int) ),
233 mDateNavigator, TQ_SLOT( selectMonth(int) ) );
234 connect( mDateNavigatorContainer, TQ_SIGNAL(yearSelected(int)),
235 mDateNavigator, TQ_SLOT(selectYear(int)) );
236 connect( mDateNavigatorContainer, TQ_SIGNAL( goPrevious() ),
237 mDateNavigator, TQ_SLOT( selectPrevious() ) );
238 connect( mDateNavigatorContainer, TQ_SIGNAL( goNext() ),
239 mDateNavigator, TQ_SLOT( selectNext() ) );
240
241 connect( mDateNavigatorContainer, TQ_SIGNAL( datesSelected( const KCal::DateList & ) ),
242 mDateNavigator, TQ_SLOT( selectDates( const KCal::DateList & ) ) );
243
244 connect( mDateNavigatorContainer, TQ_SIGNAL(incidenceDropped(Incidence*, const TQDate&)),
245 TQ_SLOT( addIncidenceOn( Incidence *, const TQDate & ) ) );
246 connect( mDateNavigatorContainer, TQ_SIGNAL(incidenceDroppedMove(Incidence*,const TQDate&)),
247 TQ_SLOT( moveIncidenceTo( Incidence *, const TQDate & ) ) );
248
249 connect( mDateChecker, TQ_SIGNAL( dayPassed( const TQDate & ) ),
250 mTodoList, TQ_SLOT( dayPassed( const TQDate & ) ) );
251 connect( mDateChecker, TQ_SIGNAL( dayPassed( const TQDate & ) ),
252 TQ_SIGNAL( dayPassed( const TQDate & ) ) );
253 connect( mDateChecker, TQ_SIGNAL( dayPassed( const TQDate & ) ),
254 mDateNavigatorContainer, TQ_SLOT( updateToday() ) );
255
256 connect( this, TQ_SIGNAL( configChanged() ),
257 mDateNavigatorContainer, TQ_SLOT( updateConfig() ) );
258
259 connect( this, TQ_SIGNAL( incidenceSelected(Incidence *, const TQDate &) ),
260 mEventViewer, TQ_SLOT ( setIncidence (Incidence *, const TQDate &) ) );
261
262 //TODO: do a pretty Summary,
263 TQString s;
264 s = i18n( "<p><em>No Item Selected</em></p>"
265 "<p>Select an event, to-do or journal entry to view its details "
266 "here.</p>");
267
268 mEventViewer->setDefaultText( s );
269 TQWhatsThis::add( mEventViewer,
270 i18n( "View the details of events, journal entries or to-dos "
271 "selected in KOrganizer's main view here." ) );
272 mEventViewer->setIncidence( 0, TQDate() );
273
274 mViewManager->connectTodoView( mTodoList );
275 mViewManager->connectView( mTodoList );
276
277 KOGlobals::self()->
278 setHolidays( new KHolidays( KOPrefs::instance()->mHolidays ) );
279
280 connect( TQApplication::clipboard(), TQ_SIGNAL( dataChanged() ),
281 TQ_SLOT( checkClipboard() ) );
282
283 connect( mTodoList, TQ_SIGNAL( incidenceSelected( Incidence *,const TQDate & ) ),
284 TQ_SLOT( processTodoListSelection( Incidence *,const TQDate & ) ) );
285 disconnect( mTodoList, TQ_SIGNAL( incidenceSelected( Incidence *,const TQDate & ) ),
286 this, TQ_SLOT( processMainViewSelection( Incidence *,const TQDate & ) ) );
287
288 kdDebug(5850) << "CalendarView::CalendarView() done" << endl;
289}
290
291CalendarView::~CalendarView()
292{
293 kdDebug(5850) << "~CalendarView()" << endl;
294
295 mCalendar->unregisterObserver( this );
296
297 delete mDialogManager;
298 delete mViewManager;
299 delete mEventViewer;
300 kdDebug(5850) << "~CalendarView() done" << endl;
301}
302
303void CalendarView::setCalendar( Calendar *cal )
304{
305 kdDebug(5850)<<"CalendarView::setCalendar"<<endl;
306 mCalendar = cal;
307
308 delete mHistory;
309 mHistory = new History( mCalendar );
310 connect( mHistory, TQ_SIGNAL( undone() ), TQ_SLOT( updateView() ) );
311 connect( mHistory, TQ_SIGNAL( redone() ), TQ_SLOT( updateView() ) );
312
313 if ( mChanger ) delete mChanger;
314 setIncidenceChanger( new IncidenceChanger( mCalendar, this ) );
315
316 mCalendar->registerObserver( this );
317
318 mDateNavigatorContainer->setCalendar( mCalendar );
319
320 mTodoList->setCalendar( mCalendar );
321
322 mEventViewer->setCalendar( mCalendar );
323}
324
325void CalendarView::setIncidenceChanger( IncidenceChangerBase *changer )
326{
327 mChanger = changer;
328 emit newIncidenceChanger( mChanger );
329 connect( mChanger, TQ_SIGNAL( incidenceAdded( Incidence* ) ),
330 this, TQ_SLOT( incidenceAdded( Incidence* ) ) );
331 connect( mChanger, TQ_SIGNAL( incidenceChanged( Incidence*, Incidence*, KOGlobals::WhatChanged ) ),
332 this, TQ_SLOT( incidenceChanged( Incidence*, Incidence*, KOGlobals::WhatChanged ) ) );
333 connect( mChanger, TQ_SIGNAL( incidenceToBeDeleted( Incidence * ) ),
334 this, TQ_SLOT( incidenceToBeDeleted( Incidence * ) ) );
335 connect( mChanger, TQ_SIGNAL( incidenceDeleted( Incidence * ) ),
336 this, TQ_SLOT( incidenceDeleted( Incidence * ) ) );
337
338 connect( mChanger, TQ_SIGNAL( schedule( Scheduler::Method, Incidence*) ),
339 this, TQ_SLOT( schedule( Scheduler::Method, Incidence*) ) );
340
341
342 connect( this, TQ_SIGNAL( cancelAttendees( Incidence * ) ),
343 mChanger, TQ_SLOT( cancelAttendees( Incidence * ) ) );
344}
345
346Calendar *CalendarView::calendar()
347{
348 if ( mCalendar ) return mCalendar;
349 else return CalendarNull::self();
350}
351
352TQPair<ResourceCalendar *, TQString> CalendarView::viewSubResourceCalendar()
353{
354 TQPair<ResourceCalendar *, TQString> p( 0, TQString() );
355 KOrg::BaseView *cV = mViewManager->currentView();
356 if ( cV && cV == mViewManager->multiAgendaView() ) {
357 cV = mViewManager->multiAgendaView()->selectedAgendaView();
358 }
359 if ( cV ) {
360 p = qMakePair( cV->resourceCalendar(), cV->subResourceCalendar() );
361 }
362 return p;
363}
364
365KOIncidenceEditor *CalendarView::editorDialog( Incidence *incidence ) const
366{
367 if (mDialogList.find(incidence) != mDialogList.end ())
368 return mDialogList[incidence];
369 else return 0;
370}
371
372TQDate CalendarView::activeDate( bool fallbackToToday )
373{
374 KOrg::BaseView *curView = mViewManager->currentView();
375 if ( curView ) {
376 if ( curView->selectionStart().isValid() ) {
377 return curView->selectionStart().date();
378 }
379
380 // Try the view's selectedDates()
381 if ( !curView->selectedIncidenceDates().isEmpty() ) {
382 if ( curView->selectedIncidenceDates().first().isValid() ) {
383 return curView->selectedIncidenceDates().first();
384 }
385 }
386 }
387
388 // When all else fails, use the navigator start date, or today.
389 if ( fallbackToToday ) {
390 return TQDate::currentDate();
391 } else {
392 return mDateNavigator->selectedDates().first();
393 }
394}
395
397{
398 KOrg::BaseView *curView = mViewManager->currentView();
399 if ( curView ) {
400 DateList dates = curView->selectedIncidenceDates();
401 if ( !dates.isEmpty() ) {
402 return dates.first();
403 }
404 }
405
406 return TQDate();
407}
408
409TQDate CalendarView::startDate()
410{
411 DateList dates = mDateNavigator->selectedDates();
412
413 return dates.first();
414}
415
416TQDate CalendarView::endDate()
417{
418 DateList dates = mDateNavigator->selectedDates();
419
420 return dates.last();
421}
422
423
424bool CalendarView::openCalendar(const TQString& filename, bool merge)
425{
426 kdDebug(5850) << "CalendarView::openCalendar(): " << filename << endl;
427
428 if (filename.isEmpty()) {
429 kdDebug(5850) << "CalendarView::openCalendar(): Error! Empty filename." << endl;
430 return false;
431 }
432
433 if (!TQFile::exists(filename)) {
434 kdDebug(5850) << "CalendarView::openCalendar(): Error! File '" << filename
435 << "' doesn't exist." << endl;
436 }
437
438 bool loadedSuccesfully = true;
439 if ( !merge ) {
440 mCalendar->close();
441 CalendarLocal *cl = dynamic_cast<CalendarLocal*>( mCalendar );
442 if ( cl ) {
443 loadedSuccesfully = cl->load( filename );
444 } else {
445 CalendarResources *cr = dynamic_cast<CalendarResources*>( mCalendar );
446 assert( cr ); // otherwise something is majorly wrong
447 // openCalendar called without merge and a filename, what should we do?
448 return false;
449 }
450 } else {
451 // merge in a file
452 CalendarResources *cl = dynamic_cast<CalendarResources *>( mCalendar );
453 if ( cl && !cl->hasCalendarResources() ) {
454 KMessageBox::sorry(
455 this,
456 i18n( "No calendars found, unable to merge the file into your calendar." ) );
457 return false;
458 }
459 // FIXME: This is a nasty hack, since we need to set a parent for the
460 // resource selection dialog. However, we don't have any UI methods
461 // in the calendar, only in the CalendarResources::DestinationPolicy
462 // So we need to type-cast it and extract it from the CalendarResources
463 TQWidget *tmpparent = 0;
464 if ( cl ) {
465 tmpparent = cl->dialogParentWidget();
466 cl->setDialogParentWidget( this );
467 }
468
469 FileStorage storage( mCalendar );
470 storage.setFileName( filename );
471 loadedSuccesfully = storage.load();
472 }
473
474 if ( loadedSuccesfully ) {
475 if ( merge )
476 setModified( true );
477 else {
478 setModified( false );
479 mViewManager->setDocumentId( filename );
480 mTodoList->setDocumentId( filename );
481 }
483 updateView();
484 return true;
485 } else {
486 // while failing to load, the calendar object could
487 // have become partially populated. Clear it out.
488 if ( !merge ) mCalendar->close();
489
490 KMessageBox::error(this,i18n("Could not load calendar '%1'.").arg(filename));
491
492 return false;
493 }
494}
495
496bool CalendarView::saveCalendar( const TQString& filename )
497{
498 kdDebug(5850) << "CalendarView::saveCalendar(): " << filename << endl;
499
500 // Store back all unsaved data into calendar object
501 mViewManager->currentView()->flushView();
502
503 FileStorage storage( mCalendar );
504 storage.setFileName( filename );
505 storage.setSaveFormat( new ICalFormat );
506
507 bool success = storage.save();
508
509 if ( !success ) {
510 return false;
511 }
512
513 return true;
514}
515
517{
518 kdDebug(5850) << "CalendarView::closeCalendar()" << endl;
519
520 // child windows no longer valid
521 emit closingDown();
522
523 mCalendar->close();
524 setModified( false );
525 updateView();
526}
527
529{
530 mDialogManager->showArchiveDialog();
531}
532
533
535{
536// kdDebug(5850) << "CalendarView::readSettings()" << endl;
537
538 TQString str;
539
540 // read settings from the TDEConfig, supplying reasonable
541 // defaults where none are to be found
542
543 TDEConfig *config = KOGlobals::self()->config();
544
545#ifndef KORG_NOSPLITTER
546 config->setGroup( "KOrganizer Geometry" );
547
548 TQValueList<int> sizes = config->readIntListEntry( "Separator1" );
549 if ( sizes.count() != 2 ) {
550 sizes << mDateNavigatorContainer->minimumSizeHint().width();
551 sizes << 300;
552 }
553 mPanner->setSizes( sizes );
554
555 sizes = config->readIntListEntry( "Separator2" );
556 mLeftSplitter->setSizes( sizes );
557#endif
558
559 mEventViewer->readSettings( config );
560
561 mViewManager->readSettings( config );
562 mTodoList->restoreLayout( config, TQString( "Todo Layout" ) );
563
564 readFilterSettings( config );
565
566 config->setGroup( "Views" );
567 const int dateCount = config->readNumEntry( "ShownDatesCount", 7 );
568 if ( dateCount == 7 ) {
569 mDateNavigator->selectWeek();
570 } else {
571 mDateNavigator->selectDates( mDateNavigator->selectedDates().first(), dateCount );
572 }
573}
574
575
577{
578// kdDebug(5850) << "CalendarView::writeSettings" << endl;
579
580 TDEConfig *config = KOGlobals::self()->config();
581
582#ifndef KORG_NOSPLITTER
583 config->setGroup( "KOrganizer Geometry" );
584
585 TQValueList<int> list = mPanner->sizes();
586 config->writeEntry( "Separator1", list );
587
588 list = mLeftSplitter->sizes();
589 config->writeEntry( "Separator2", list );
590#endif
591 mEventViewer->writeSettings( config );
592 mViewManager->writeSettings( config );
593 mTodoList->saveLayout( config, TQString( "Todo Layout" ) );
594
595 KOPrefs::instance()->writeConfig();
596
597 writeFilterSettings( config );
598
599 config->setGroup( "Views" );
600 config->writeEntry( "ShownDatesCount", mDateNavigator->selectedDates().count() );
601
602 config->sync();
603}
604
605void CalendarView::readFilterSettings( TDEConfig *config )
606{
607// kdDebug(5850) << "CalendarView::readFilterSettings()" << endl;
608
609 mFilters.clear();
610
611 config->setGroup( "General" );
612 // FIXME: Move the filter loading and saving to the CalFilter class in libkcal
613 TQStringList filterList = config->readListEntry ("CalendarFilters" );
614 TQString currentFilter = config->readEntry( "Current Filter" );
615
616 TQStringList::ConstIterator it = filterList.begin();
617 TQStringList::ConstIterator end = filterList.end();
618 while( it != end ) {
619// kdDebug(5850) << " filter: " << (*it) << endl;
620 CalFilter *filter;
621 filter = new CalFilter( *it );
622 config->setGroup( "Filter_" + (*it) );
623 filter->setCriteria( config->readNumEntry( "Criteria", 0 ) );
624 filter->setCategoryList( config->readListEntry( "CategoryList" ) );
625 if ( filter->criteria() & KCal::CalFilter::HideTodosWithoutAttendeeInEmailList )
626 filter->setEmailList( KOPrefs::instance()->allEmails() );
627 filter->setCompletedTimeSpan( config->readNumEntry( "HideTodoDays", 0 ) );
628 mFilters.append( filter );
629
630 ++it;
631 }
632
633 config->setGroup( "General" );
634 int pos = filterList.findIndex( currentFilter );
635 mCurrentFilter = 0;
636 if ( pos>=0 ) {
637 mCurrentFilter = mFilters.at( pos );
638 }
639 updateFilter();
640}
641
642void CalendarView::writeFilterSettings( TDEConfig *config )
643{
644// kdDebug(5850) << "CalendarView::writeFilterSettings()" << endl;
645
646 TQStringList filterList;
647
648 CalFilter *filter = mFilters.first();
649 while( filter ) {
650// kdDebug(5850) << " fn: " << filter->name() << endl;
651 filterList << filter->name();
652 config->setGroup( "Filter_" + filter->name() );
653 config->writeEntry( "Criteria", filter->criteria() );
654 config->writeEntry( "CategoryList", filter->categoryList() );
655 config->writeEntry( "HideTodoDays", filter->completedTimeSpan() );
656 filter = mFilters.next();
657 }
658 config->setGroup( "General" );
659 config->writeEntry( "CalendarFilters", filterList );
660 if ( mCurrentFilter ) {
661 config->writeEntry( "Current Filter", mCurrentFilter->name() );
662 } else {
663 config->writeEntry( "Current Filter", TQString() );
664 }
665}
666
667
668void CalendarView::goDate( const TQDate &date )
669{
670 mDateNavigator->selectDate( date );
671}
672
673void CalendarView::showDate( const TQDate &date )
674{
675 int dateCount = mDateNavigator->datesCount();
676 if ( dateCount == 7 ) {
677 mDateNavigator->selectWeek( date );
678 } else {
679 mDateNavigator->selectDates( date, dateCount );
680 }
681}
682
684{
685 mDateNavigator->selectToday();
686}
687
689{
690 if ( dynamic_cast<KOMonthView*>( mViewManager->currentView() ) ) {
691 mDateNavigator->selectNextMonth();
692 } else {
693 mDateNavigator->selectNext();
694 }
695}
696
698{
699 if ( dynamic_cast<KOMonthView*>( mViewManager->currentView() ) ) {
700 mDateNavigator->selectPreviousMonth();
701 } else {
702 mDateNavigator->selectPrevious();
703 }
704}
705
706void CalendarView::updateConfig( const TQCString& receiver)
707{
708 if ( receiver != "korganizer" ) return;
709 kdDebug(5850) << "CalendarView::updateConfig()" << endl;
710
711 KOGlobals::self()->
712 setHolidays( new KHolidays( KOPrefs::instance()->mHolidays ) );
713
714 TQString tz( mCalendar->timeZoneId() );
715 // Only set a new time zone if it changed. This prevents the window
716 // from being modified on start
717 if ( tz != KOPrefs::instance()->mTimeZoneId ) {
718
719 const TQString question( i18n("The timezone setting was changed. Do you want to keep the absolute time of "
720 "the items in your calendar, which will show them to be at a different time than "
721 "before, or move them to be at the old time also in the new timezone?") );
722 int rc = KMessageBox::questionYesNo( this, question,
723 i18n("Keep Absolute Times?"),
724 KGuiItem(i18n("Keep Times")),
725 KGuiItem(i18n("Move Times")),
726 "calendarKeepAbsoluteTimes");
727 if ( rc == KMessageBox::Yes ) {
728 // user wants us to shift
729 mCalendar->setTimeZoneIdViewOnly( KOPrefs::instance()->mTimeZoneId );
730 } else {
731 // only set the new timezone, wihtout shifting events, they will be
732 // interpreted as being in the new timezone now
733 mCalendar->setTimeZoneId( KOPrefs::instance()->mTimeZoneId );
734 }
735 }
736 emit configChanged();
737
738 //switch beetween merged, side by side and tabbed agenda if needed
739 mViewManager->updateMultiCalendarDisplay();
740
741 // To make the "fill window" configurations work
742 mViewManager->raiseCurrentView();
743}
744
745
746void CalendarView::incidenceAdded( Incidence *incidence )
747{
748 setModified( true );
749 history()->recordAdd( incidence );
750 changeIncidenceDisplay( incidence, KOGlobals::INCIDENCEADDED );
751 updateUnmanagedViews();
752 checkForFilteredChange( incidence );
753}
754
755void CalendarView::incidenceChanged( Incidence *oldIncidence,
756 Incidence *newIncidence,
757 KOGlobals::WhatChanged modification )
758{
759 KOIncidenceEditor *tmp = editorDialog( newIncidence );
760 if ( tmp ) {
761 kdDebug(5850) << "Incidence modified and open" << endl;
762 tmp->modified();
763 }
764 setModified( true );
765 history()->recordEdit( oldIncidence, newIncidence );
766
767 // Record completed todos in journals, if enabled. we should to this here in
768 // favour of the todolist. users can mark a task as completed in an editor
769 // as well.
770 if ( newIncidence->type() == "Todo" &&
771 KOPrefs::instance()->recordTodosInJournals() &&
772 ( modification == KOGlobals::COMPLETION_MODIFIED ||
773 modification == KOGlobals::COMPLETION_MODIFIED_WITH_RECURRENCE ) ) {
774
775 Todo *todo = static_cast<Todo *>(newIncidence);
776 if ( todo->isCompleted() ||
777 modification == KOGlobals::COMPLETION_MODIFIED_WITH_RECURRENCE ) {
778 TQString timeStr = TDEGlobal::locale()->formatTime( TQTime::currentTime() );
779 TQString description = i18n( "To-do completed: %1 (%2)" ).arg(
780 newIncidence->summary() ).arg( timeStr );
781
782 Journal::List journals = calendar()->journals( TQDate::currentDate() );
783 Journal *journal;
784
785 if ( journals.isEmpty() ) {
786 journal = new Journal();
787 journal->setDtStart( TQDateTime::currentDateTime() );
788
789 TQString dateStr = TDEGlobal::locale()->formatDate( TQDate::currentDate() );
790 journal->setSummary( i18n("Journal of %1").arg( dateStr ) );
791 journal->setDescription( description );
792
793 //TODO: recorded to-dos should save into the standard resource always
794 if ( !mChanger->addIncidence( journal, 0, TQString(), this ) ) {
795 KODialogManager::errorSaveIncidence( this, journal );
796 delete journal;
797 return;
798 }
799
800 } else { // journal list is not empty
801 journal = *(journals.at(0));
802 Journal *oldJournal = journal->clone();
803 journal->setDescription( journal->description().append( "\n" + description ) );
804
805 if ( !mChanger->changeIncidence( oldJournal, journal,
806 KOGlobals::DESCRIPTION_MODIFIED, this ) ) {
807 KODialogManager::errorSaveIncidence( this, journal );
808 delete journal;
809 return;
810 }
811 }
812 }
813 }
814
815 changeIncidenceDisplay( newIncidence, KOGlobals::INCIDENCEEDITED );
816 updateUnmanagedViews();
817 checkForFilteredChange( newIncidence );
818}
819
820void CalendarView::incidenceToBeDeleted( Incidence *incidence )
821{
822 KOIncidenceEditor *tmp = editorDialog( incidence );
823 if (tmp) {
824 kdDebug(5850) << "Incidence to be deleted and open in editor" << endl;
825 tmp->delayedDestruct();
826 }
827 setModified( true );
828 history()->recordDelete( incidence );
829// changeIncidenceDisplay( incidence, KOGlobals::INCIDENCEDELETED );
830 updateUnmanagedViews();
831}
832
833void CalendarView::incidenceDeleted( Incidence *incidence )
834{
835 changeIncidenceDisplay( incidence, KOGlobals::INCIDENCEDELETED );
836 updateUnmanagedViews();
837}
838
839void CalendarView::checkForFilteredChange( Incidence *incidence )
840{
841 CalFilter *filter = calendar()->filter();
842 if ( filter && !filter->filterIncidence( incidence ) ) {
843 // Incidence is filtered and thus not shown in the view, tell the
844 // user so that he isn't surprised if his new event doesn't show up
845 KMessageBox::information( this, i18n("The item \"%1\" is filtered by "
846 "your current filter rules, so it will be hidden and not "
847 "appear in the view.").arg( incidence->summary() ),
848 i18n("Filter Applied"), "ChangedIncidenceFiltered" );
849 }
850}
851
852void CalendarView::startMultiModify( const TQString &text )
853{
854 history()->startMultiModify( text );
855}
856
857void CalendarView::endMultiModify()
858{
859 history()->endMultiModify();
860}
861
862
864{
865 mDateNavigatorContainer->updateView();
866 mDialogManager->updateSearchDialog();
867
868 if ( incidence ) {
869 // If there is an event view visible update the display
870 mViewManager->currentView()->changeIncidenceDisplay( incidence, action );
871 if ( mTodoList ) mTodoList->changeIncidenceDisplay( incidence, action );
872 mEventViewer->changeIncidenceDisplay( incidence, activeDate( true ), action );
873 } else {
874 mViewManager->currentView()->updateView();
875 if ( mTodoList ) mTodoList->updateView();
876 }
877}
878
879
880void CalendarView::updateView(const TQDate &start, const TQDate &end)
881{
882 mTodoList->updateView();
883 mViewManager->updateView(start, end);
884 mDateNavigatorContainer->updateView();
885}
886
887void CalendarView::updateView()
888{
889 DateList tmpList = mDateNavigator->selectedDates();
890
891 // We assume that the navigator only selects consecutive days.
892 updateView( tmpList.first(), tmpList.last() );
893}
894
895void CalendarView::updateUnmanagedViews()
896{
897 mDateNavigatorContainer->updateDayMatrix();
898 updateView();
899}
900
901int CalendarView::msgItemDelete( Incidence *incidence )
902{
903 return KMessageBox::warningContinueCancel(this,
904 i18n("The item \"%1\" will be permanently deleted.").arg( incidence->summary() ),
905 i18n("KOrganizer Confirmation"), KGuiItem(i18n("&Delete"),"edit-delete"));
906}
907
908
910{
911 Incidence *incidence = incToSendToClipboard( true );
912
913 if ( !incidence || !mChanger ) {
914 KNotifyClient::beep();
915 return;
916 }
917
918 Incidence::List incidences;
919 int km = KMessageBox::Yes;
920
921 if ( !incidence->relations().isEmpty() &&
922 incidence->type() == "Todo" ) { // Only todos (yet?)
923 km = KMessageBox::questionYesNoCancel( this,
924 i18n("The item \"%1\" has sub-to-dos. "
925 "Do you want to cut just this item and "
926 "make all its sub-to-dos independent, or "
927 "cut the to-do with all its sub-to-dos?"
928 ).arg( incidence->summary() ),
929 i18n("KOrganizer Confirmation"),
930 i18n("Cut Only This"),
931 i18n("Cut All"));
932 }
933
934 if ( km == KMessageBox::Yes ) { // only one
935 incidences.append( incidence );
936 makeChildrenIndependent( incidence );
937 } else if ( km == KMessageBox::No ) { // all
938 // load incidence + children + grandchildren...
939 getIncidenceHierarchy( incidence, incidences );
940 }
941
942 if ( km != KMessageBox::Cancel ) {
943 mChanger->cutIncidences( incidences, this );
944 }
945}
946
948{
949 Incidence *incidence = incToSendToClipboard( false );
950
951 if ( !incidence ) {
952 KNotifyClient::beep();
953 return;
954 }
955
956 Incidence::List incidences;
957 int km = KMessageBox::Yes;
958
959 if ( !incidence->relations().isEmpty() &&
960 incidence->type() == "Todo" ) { // only todos.
961 km = KMessageBox::questionYesNoCancel( this,
962 i18n("The item \"%1\" has sub-to-dos. "
963 "Do you want to copy just this item or "
964 "copy the to-do with all its sub-to-dos?"
965 ).arg( incidence->summary() ),
966 i18n("KOrganizer Confirmation"),
967 i18n("Copy Only This"),
968 i18n("Copy All"));
969 }
970
971 if ( km == KMessageBox::Yes ) { // only one
972 incidences.append( incidence );
973 } else if ( km == KMessageBox::No ) { // all
974 // load incidence + children + grandchildren...
975 getIncidenceHierarchy( incidence, incidences );
976 }
977
978 if ( km != KMessageBox::Cancel ) {
979 DndFactory factory( mCalendar );
980 if ( !factory.copyIncidences( incidences ) ) {
981 KNotifyClient::beep();
982 }
983 }
984}
985
986Incidence* CalendarView::incToSendToClipboard( bool cut )
987{
988 Incidence *originalInc = selectedIncidence();
989
990 if ( originalInc && originalInc->doesRecur() &&
991 originalInc->type() == "Event" ) { // temporary, until recurring to-dos are fixed
992
993 Incidence *inc;
994 KOGlobals::WhichOccurrences chosenOption;
995 if ( cut ) {
996 inc = singleOccurrenceOrAll( originalInc, KOGlobals::CUT, chosenOption, TQDate(), true );
997 } else {
998 // The user is copying, the original incidence can't be changed
999 // we can only dissociate a copy
1000 Incidence *originalIncSaved = originalInc->clone();
1001 inc = singleOccurrenceOrAll( originalIncSaved, KOGlobals::COPY, chosenOption, TQDate(), false );
1002
1003 // no dissociation, no need to leak our clone
1004 if ( chosenOption == KOGlobals::ALL ) {
1005 inc = originalInc;
1006 delete originalIncSaved;
1007 }
1008
1009 // no need to leak our clone
1010 if ( chosenOption == KOGlobals::NONE ) {
1011 delete originalIncSaved;
1012 }
1013 }
1014
1015 return inc;
1016 } else {
1017 return originalInc;
1018 }
1019}
1020
1022{
1023// If in agenda and month view, use the selected time and date from there.
1024// In all other cases, use the navigator's selected date.
1025
1026 TQDate date; // null dates are invalid, that's what we want
1027 bool timeSet = false;// flag denoting if the time has been set.
1028 TQTime time; // null dates are valid, so rely on the timeSet flag
1029 TQDateTime endDT; // null datetimes are invalid, that's what we want
1030 bool useEndTime = false;
1031
1032 KOrg::BaseView *curView = mViewManager->currentView();
1033
1034 KOAgendaView *aView = mViewManager->agendaView();
1035 KOMonthView *mView = mViewManager->monthView();
1036 if ( curView == mViewManager->multiAgendaView() ) {
1037 aView = mViewManager->multiAgendaView()->selectedAgendaView();
1038 curView = aView;
1039 }
1040
1041 if ( !curView ) {
1042 return;
1043 }
1044
1045 if ( curView == aView && aView->selectionStart().isValid() ) {
1046 date = aView->selectionStart().date();
1047 endDT = aView->selectionEnd();
1048 useEndTime = !aView->selectedIsSingleCell();
1049 if ( !aView->selectedIsAllDay() ) {
1050 time = aView->selectionStart().time();
1051 timeSet = true;
1052 }
1053 } else if ( curView == mView && mView->selectionStart().isValid() ) {
1054 date = mView->selectionStart().date();
1055 } else if ( !mDateNavigator->selectedDates().isEmpty() &&
1056 curView->supportsDateNavigation() ) {
1057 // default to the selected date from the navigator
1058 date = mDateNavigator->selectedDates().first();
1059 }
1060
1061 if ( !date.isValid() && curView->supportsDateNavigation() ) {
1062 KMessageBox::sorry(
1063 this,
1064 i18n( "Paste failed: unable to determine a valid target date." ) );
1065 return;
1066 }
1067
1068 DndFactory factory( mCalendar );
1069 Incidence::List pastedIncidences;
1070 if ( timeSet && time.isValid() ) {
1071 pastedIncidences = factory.pasteIncidences( date, &time );
1072 } else {
1073 pastedIncidences = factory.pasteIncidences( date );
1074 }
1075
1076 Incidence::List::Iterator it;
1077 for ( it = pastedIncidences.begin(); it != pastedIncidences.end(); ++it ) {
1078 TQPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar();
1079
1080 // FIXME: use a visitor here
1081 if ( ( *it )->type() == "Event" ) {
1082 Event *pastedEvent = static_cast<Event*>( *it );
1083 // only use selected area if event is of the same type
1084 // (all-day or non-all-day) as the current selection is
1085 if ( aView && endDT.isValid() && useEndTime ) {
1086 if ( ( pastedEvent->doesFloat() && aView->selectedIsAllDay() ) ||
1087 ( !pastedEvent->doesFloat() && !aView->selectedIsAllDay() ) ) {
1088 pastedEvent->setDtEnd( endDT );
1089 }
1090 }
1091
1092 // KCal supports events with relations, but korganizer doesn't
1093 // so unset it. It can even come from other application.
1094 pastedEvent->setRelatedTo( 0 );
1095 pastedEvent->setRelatedToUid( TQString() );
1096
1097 mChanger->addIncidence( pastedEvent, p.first, p.second, this );
1098
1099 } else if ( ( *it )->type() == "Todo" ) {
1100 Todo *pastedTodo = static_cast<Todo*>( *it );
1101 Todo *_selectedTodo = selectedTodo();
1102
1103 // if we are cutting a hierarchy only the root
1104 // should be son of _selectedTodo
1105 if ( _selectedTodo && !pastedTodo->relatedTo() ) {
1106 pastedTodo->setRelatedTo( _selectedTodo );
1107 }
1108 mChanger->addIncidence( pastedTodo, p.first, p.second, this );
1109 }
1110 }
1111}
1112
1114{
1115 mDialogManager->showOptionsDialog();
1116}
1117
1118void CalendarView::dateTimesForNewEvent( TQDateTime &startDt, TQDateTime &endDt, bool &allDay )
1119{
1120 mViewManager->currentView()->eventDurationHint( startDt, endDt, allDay );
1121
1122 if ( !startDt.isValid() || !endDt.isValid() ) {
1123 startDt.setDate( activeDate( true ) );
1124 startDt.setTime( KOPrefs::instance()->mStartTime.time() );
1125
1126 int addSecs = ( KOPrefs::instance()->mDefaultDuration.time().hour() * 3600 ) +
1127 ( KOPrefs::instance()->mDefaultDuration.time().minute() * 60 );
1128
1129 endDt = startDt.addSecs( addSecs );
1130 }
1131}
1132
1133KOEventEditor *CalendarView::newEventEditor( ResourceCalendar *res, const TQString &subRes,
1134 const TQDateTime &startDtParam,
1135 const TQDateTime &endDtParam, bool allDayParam )
1136{
1137 // let the current view change the default start/end datetime
1138 bool allDay = allDayParam;
1139 TQDateTime startDt( startDtParam ), endDt( endDtParam );
1140 // Adjust the start/end date times (i.e. replace invalid values by defaults,
1141 // and let the view adjust the type.
1142 dateTimesForNewEvent( startDt, endDt, allDay );
1143
1144 KOEventEditor *eventEditor = mDialogManager->getEventEditor();
1145 eventEditor->newEvent();
1146 connectIncidenceEditor( eventEditor );
1147 eventEditor->setResource( res, subRes );
1148 eventEditor->setDates( startDt, endDt, allDay );
1149 mDialogManager->connectTypeAhead( eventEditor, dynamic_cast<KOrg::AgendaView*>(viewManager()->currentView()) );
1150 return eventEditor;
1151}
1152
1154{
1155 KOrg::BaseView *currentView = mViewManager->currentView();
1156
1157 if ( currentView == mViewManager->multiAgendaView() ) {
1158 currentView = mViewManager->multiAgendaView()->selectedAgendaView();
1159 }
1160
1161 if ( currentView ) {
1162 newEvent( currentView->resourceCalendar(),
1163 currentView->subResourceCalendar() );
1164 }
1165}
1166
1167void CalendarView::newEvent( ResourceCalendar *res, const TQString &subRes )
1168{
1169 kdDebug(5850) << "CalendarView::newEvent()" << endl;
1170 newEvent( res, subRes, TQDateTime(), TQDateTime() );
1171}
1172
1173void CalendarView::newEvent( ResourceCalendar *res, const TQString &subRes,
1174 const TQDate &dt )
1175{
1176 TQDateTime startDt( dt, KOPrefs::instance()->mStartTime.time() );
1177 newEvent( res, subRes, TQDateTime( dt ), TQDateTime() );
1178}
1179
1180void CalendarView::newEvent( ResourceCalendar *res, const TQString &subRes,
1181 const TQDateTime &startDt )
1182{
1183 newEvent( res, subRes, startDt, TQDateTime() );
1184}
1185
1186void CalendarView::newEvent( ResourceCalendar *res, const TQString &subRes,
1187 const TQDateTime &startDt, const TQDateTime &endDt,
1188 bool allDay )
1189{
1190 KOEventEditor *eventEditor = newEventEditor( res, subRes,
1191 startDt, endDt, allDay );
1192 eventEditor->show();
1193}
1194
1195void CalendarView::newEvent( ResourceCalendar *res, const TQString &subRes,
1196 const TQString &summary, const TQString &description,
1197 const TQStringList &attachments, const TQStringList &attendees,
1198 const TQStringList &attachmentMimetypes, bool inlineAttachment )
1199{
1200 KOEventEditor *eventEditor = newEventEditor( res, subRes );
1201 eventEditor->setTexts( summary, description );
1202 // if attach or attendee list is empty, these methods don't do anything, so
1203 // it's safe to call them in every case
1204 eventEditor->addAttachments( attachments, attachmentMimetypes, inlineAttachment );
1205 eventEditor->addAttendees( attendees );
1206 eventEditor->show();
1207}
1208
1209void CalendarView::newTodo( ResourceCalendar *res, const TQString &subRes,
1210 const TQString &summary, const TQString &description,
1211 const TQStringList &attachments, const TQStringList &attendees,
1212 const TQStringList &attachmentMimetypes,
1213 bool inlineAttachment, bool isTask )
1214{
1215 kdDebug(5850) << k_funcinfo << endl;
1216 KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
1217 connectIncidenceEditor( todoEditor );
1218 todoEditor->newTodo();
1219 todoEditor->setResource( res, subRes );
1220 todoEditor->setTexts( summary, description );
1221 todoEditor->addAttachments( attachments, attachmentMimetypes, inlineAttachment );
1222 todoEditor->addAttendees( attendees );
1223 todoEditor->selectCreateTask( isTask );
1224 todoEditor->show();
1225}
1226
1228{
1229 KOrg::BaseView *currentView = mViewManager->currentView();
1230
1231 if ( currentView == mViewManager->multiAgendaView() ) {
1232 currentView = mViewManager->multiAgendaView()->selectedAgendaView();
1233 }
1234 if ( currentView ) {
1235 newTodo( currentView->resourceCalendar(),
1236 currentView->subResourceCalendar() );
1237 }
1238}
1239
1240void CalendarView::newTodo( ResourceCalendar *res, const TQString &subRes )
1241{
1242 kdDebug(5850) << k_funcinfo << endl;
1243 TQDateTime dtDue;
1244 bool allday = true;
1245 KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
1246 connectIncidenceEditor( todoEditor );
1247 todoEditor->newTodo();
1248 todoEditor->setResource( res, subRes );
1249 if ( mViewManager->currentView()->isEventView() ) {
1250 dtDue.setDate( mDateNavigator->selectedDates().first() );
1251 TQDateTime dtDummy = TQDateTime::currentDateTime();
1252 mViewManager->currentView()->eventDurationHint( dtDue, dtDummy, allday );
1253 todoEditor->setDates( dtDue, allday );
1254 }
1255 todoEditor->show();
1256}
1257
1258void CalendarView::newTodo( ResourceCalendar *res, const TQString &subRes,
1259 const TQDate &date )
1260{
1261 KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
1262 connectIncidenceEditor( todoEditor );
1263 todoEditor->newTodo();
1264 todoEditor->setResource( res, subRes );
1265 todoEditor->setDates( TQDateTime( date, TQTime::currentTime() ), true );
1266 todoEditor->show();
1267}
1268
1269void CalendarView::newJournal()
1270{
1271 KOrg::BaseView *currentView = mViewManager->currentView();
1272
1273 if ( currentView == mViewManager->multiAgendaView() ) {
1274 currentView = mViewManager->multiAgendaView()->selectedAgendaView();
1275 }
1276
1277 if ( currentView ) {
1278 newJournal( currentView->resourceCalendar(),
1279 currentView->subResourceCalendar() );
1280 }
1281}
1282
1283void CalendarView::newJournal( ResourceCalendar *res, const TQString &subRes )
1284{
1285 kdDebug(5850) << "CalendarView::newJournal()" << endl;
1286 newJournal( res, subRes, TQString(), TQDate() );
1287}
1288
1289void CalendarView::newJournal( ResourceCalendar *res, const TQString &subRes,
1290 const TQDate &date)
1291{
1292 newJournal( res, subRes, TQString(), date );
1293}
1294
1295void CalendarView::newJournal( ResourceCalendar *res, const TQString &subRes,
1296 const TQString &text, const TQDate &date )
1297{
1298 KOJournalEditor *journalEditor = mDialogManager->getJournalEditor();
1299 connectIncidenceEditor( journalEditor );
1300 journalEditor->newJournal();
1301 journalEditor->setResource( res, subRes );
1302 journalEditor->setTexts( text );
1303 if ( !date.isValid() ) {
1304 journalEditor->setDate( mDateNavigator->selectedDates().first() );
1305 } else {
1306 journalEditor->setDate( date );
1307 }
1308 journalEditor->show();
1309}
1310
1312{
1313 Todo *todo = selectedTodo();
1314 if ( todo ) newSubTodo( todo );
1315}
1316
1318{
1319 KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
1320 connectIncidenceEditor( todoEditor );
1321 todoEditor->newTodo();
1322 todoEditor->setDates( TQDateTime(), false, parentEvent );
1323 todoEditor->show();
1324}
1325
1326bool CalendarView::addIncidence( const TQString &ical )
1327{
1328 kdDebug(5850) << "CalendarView::addIncidence:\n" << ical << endl;
1329 ICalFormat format;
1330 format.setTimeZone( mCalendar->timeZoneId(), true );
1331 Incidence *incidence = format.fromString( ical );
1332 if ( !incidence ) return false;
1333 if ( !mChanger->addIncidence( incidence, 0, TQString(), this ) ) {
1334 delete incidence;
1335 return false;
1336 }
1337 return true;
1338}
1339
1341{
1342 Incidence *incidence = selectedIncidence();
1343 if ( incidence ) {
1344 showIncidence( incidence, activeIncidenceDate() );
1345 } else {
1346 KNotifyClient::beep();
1347 }
1348}
1349
1351{
1352 Incidence *incidence = selectedIncidence();
1353 if ( incidence ) {
1354 editIncidence( incidence, activeIncidenceDate() );
1355 } else {
1356 KNotifyClient::beep();
1357 }
1358}
1359
1361{
1362 Incidence *incidence = selectedIncidence();
1363 if (incidence)
1364 deleteIncidence( incidence );
1365 else
1366 KNotifyClient::beep();
1367}
1368
1369void CalendarView::todo_unsub()
1370{
1371 Todo *anTodo = selectedTodo();
1372 if( incidence_unsub ( anTodo ) ) {
1373 updateView();
1374 }
1375}
1376
1377bool CalendarView::incidence_unsub( Incidence *inc )
1378{
1379 bool status = false;
1380 if ( !inc || !inc->relatedTo() ) {
1381 return false;
1382 }
1383
1384 if ( mChanger->beginChange( inc, 0, TQString() ) ) {
1385 Incidence *oldInc = inc->clone();
1386 inc->setRelatedTo( 0 );
1387 mChanger->changeIncidence( oldInc, inc, KOGlobals::RELATION_MODIFIED, this );
1388 mChanger->endChange( inc, 0, TQString() );
1389 delete oldInc;
1390 setModified(true);
1391 status = true;
1392 }
1393 if ( ! status ) {
1394 KMessageBox::sorry( this, i18n("Unable to turn sub-to-do into a top-level "
1395 "to-do, because it cannot be locked.") );
1396 }
1397
1398 return status;
1399}
1400
1402{
1403 bool status = false;
1404 Todo *aTodo = selectedTodo();
1405
1406 if ( makeChildrenIndependent( aTodo ) ) {
1407 updateView();
1408 status = true;
1409 }
1410 return status;
1411}
1412
1414{
1415 if ( !inc || inc->relations().isEmpty() ) {
1416 return false;
1417 }
1418
1419 startMultiModify ( i18n( "Make sub-to-dos independent" ) );
1420 Incidence::List subIncs( inc->relations() );
1421 Incidence::List::Iterator it;
1422
1423 for ( it= subIncs.begin(); it != subIncs.end(); ++it ) {
1424 incidence_unsub ( *it );
1425 }
1426 endMultiModify();
1427 return true;
1428}
1429
1430bool CalendarView::deleteIncidence( const TQString &uid, bool force )
1431{
1432 Incidence *inc = mCalendar->incidence( uid );
1433 if ( inc ) {
1434 deleteIncidence( inc, force );
1435 return true;
1436 } else {
1437 return false;
1438 }
1439}
1440
1441void CalendarView::toggleAlarm( Incidence *incidence )
1442{
1443 if ( !incidence || !mChanger ) {
1444 kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
1445 return;
1446 }
1447 Incidence*oldincidence = incidence->clone();
1448 if ( !mChanger->beginChange( incidence, 0, TQString() ) ) {
1449 kdDebug(5850) << "Unable to lock incidence " << endl;
1450 delete oldincidence;
1451 return;
1452 }
1453
1454 Alarm::List alarms = incidence->alarms();
1455 Alarm::List::ConstIterator it;
1456 for ( it = alarms.begin(); it != alarms.end(); ++it ) {
1457 (*it)->toggleAlarm();
1458 }
1459 if ( alarms.isEmpty() ) {
1460 // Add an alarm if it didn't have one
1461 Alarm *alm = incidence->newAlarm();
1462 alm->setType( Alarm::Display );
1463 alm->setEnabled( true );
1464 int duration; // in secs
1465 switch( KOPrefs::instance()->mReminderTimeUnits ) {
1466 default:
1467 case 0: // mins
1468 duration = KOPrefs::instance()->mReminderTime * 60;
1469 break;
1470 case 1: // hours
1471 duration = KOPrefs::instance()->mReminderTime * 60 * 60;
1472 break;
1473 case 2: // days
1474 duration = KOPrefs::instance()->mReminderTime * 60 * 60 * 24;
1475 break;
1476 }
1477 if ( incidence->type() == "Event" ) {
1478 alm->setStartOffset( KCal::Duration( -duration ) );
1479 } else {
1480 alm->setEndOffset( KCal::Duration( -duration ) );
1481 }
1482 }
1483 mChanger->changeIncidence( oldincidence, incidence, KOGlobals::ALARM_MODIFIED, this );
1484 mChanger->endChange( incidence, 0, TQString() );
1485 delete oldincidence;
1486
1487// mClickedItem->updateIcons();
1488}
1489
1490void CalendarView::dissociateOccurrence( Incidence *incidence, const TQDate &date )
1491{
1492 if ( !incidence || !mChanger ) {
1493 kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
1494 return;
1495 }
1496
1497 TQPair<ResourceCalendar *, TQString>p =
1498 CalHelper::incSubResourceCalendar( calendar(), incidence );
1499
1500 if ( !mChanger->beginChange( incidence, p.first, p.second ) ) {
1501 kdDebug(5850) << "Unable to lock incidence " << endl;
1502 return;
1503 }
1504 startMultiModify( i18n("Dissociate occurrence") );
1505 Incidence*oldincidence = incidence->clone();
1506
1507 Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true );
1508
1509 if ( newInc ) {
1510 // TODO [FIXME]: Use the same resource instead of asking again!
1511 // See also koagenda.cpp: endItemAction()
1512 bool success = mChanger->addIncidence( newInc, p.first, p.second, this );
1513 if ( success )
1514 mChanger->changeIncidence( oldincidence, incidence, KOGlobals::NOTHING_MODIFIED, this );
1515 } else {
1516 KMessageBox::sorry( this, i18n("Dissociating the occurrence failed."),
1517 i18n("Dissociating Failed") );
1518 }
1519 mChanger->endChange( incidence, p.first, p.second );
1520 endMultiModify();
1521 delete oldincidence;
1522}
1523
1524void CalendarView::dissociateFutureOccurrence( Incidence *incidence, const TQDate &date )
1525{
1526 if ( !incidence || !mChanger ) {
1527 kdDebug(5850) << "CalendarView::toggleAlarm() called without having a clicked item" << endl;
1528 return;
1529 }
1530
1531 TQPair<ResourceCalendar *, TQString>p =
1532 CalHelper::incSubResourceCalendar( calendar(), incidence );
1533
1534 if ( !mChanger->beginChange( incidence, p.first, p.second ) ) {
1535 kdDebug(5850) << "Unable to lock incidence " << endl;
1536 return;
1537 }
1538 startMultiModify( i18n("Dissociate future occurrences") );
1539 Incidence*oldincidence = incidence->clone();
1540
1541 Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true );
1542 if ( newInc ) {
1543 mChanger->changeIncidence( oldincidence, incidence, KOGlobals::NOTHING_MODIFIED, this );
1544 mChanger->addIncidence( newInc, p.first, p.second, this );
1545 } else {
1546 KMessageBox::sorry( this, i18n("Dissociating the future occurrences failed."),
1547 i18n("Dissociating Failed") );
1548 }
1549 endMultiModify();
1550 mChanger->endChange( incidence, p.first, p.second );
1551 delete oldincidence;
1552}
1553
1554
1555/*****************************************************************************/
1556
1557
1558void CalendarView::schedule_publish(Incidence *incidence)
1559{
1560 if (incidence == 0)
1561 incidence = selectedIncidence();
1562
1563 if (!incidence) {
1564 KMessageBox::information( this, i18n("No item selected."),
1565 "PublishNoEventSelected" );
1566 return;
1567 }
1568
1569 PublishDialog *publishdlg = new PublishDialog();
1570 if (incidence->attendeeCount()>0) {
1571 Attendee::List attendees = incidence->attendees();
1572 Attendee::List::ConstIterator it;
1573 for( it = attendees.begin(); it != attendees.end(); ++it ) {
1574 publishdlg->addAttendee( *it );
1575 }
1576 }
1577 if ( publishdlg->exec() == TQDialog::Accepted ) {
1578 Incidence *inc = incidence->clone();
1579 inc->registerObserver( 0 );
1580 inc->clearAttendees();
1581
1582 // Send the mail
1583 KCal::MailScheduler scheduler( mCalendar );
1584 if ( scheduler.publish( incidence, publishdlg->addresses() ) ) {
1585 KMessageBox::information( this, i18n("The item information was successfully sent."),
1586 i18n("Publishing"), "IncidencePublishSuccess" );
1587 } else {
1588 KMessageBox::error( this, i18n("Unable to publish the item '%1'").arg( incidence->summary() ) );
1589 }
1590 }
1591 delete publishdlg;
1592}
1593
1594void CalendarView::schedule_request(Incidence *incidence)
1595{
1596 schedule(Scheduler::Request,incidence);
1597}
1598
1599void CalendarView::schedule_refresh(Incidence *incidence)
1600{
1601 schedule(Scheduler::Refresh,incidence);
1602}
1603
1604void CalendarView::schedule_cancel(Incidence *incidence)
1605{
1606 schedule(Scheduler::Cancel,incidence);
1607}
1608
1609void CalendarView::schedule_add(Incidence *incidence)
1610{
1611 schedule(Scheduler::Add,incidence);
1612}
1613
1614void CalendarView::schedule_reply(Incidence *incidence)
1615{
1616 schedule(Scheduler::Reply,incidence);
1617}
1618
1619void CalendarView::schedule_counter(Incidence *incidence)
1620{
1621 schedule(Scheduler::Counter,incidence);
1622}
1623
1624void CalendarView::schedule_declinecounter(Incidence *incidence)
1625{
1626 schedule(Scheduler::Declinecounter,incidence);
1627}
1628
1629void CalendarView::schedule_forward( Incidence *incidence )
1630{
1631 if ( !incidence ) {
1632 incidence = selectedIncidence();
1633 }
1634
1635 if ( !incidence ) {
1636 KMessageBox::information(
1637 this,
1638 i18n( "No item selected." ),
1639 i18n( "Forwarding" ),
1640 "ForwardNoEventSelected" );
1641 return;
1642 }
1643
1644 PublishDialog publishdlg;
1645 if ( publishdlg.exec() == TQDialog::Accepted ) {
1646 TQString recipients = publishdlg.addresses();
1647 if ( incidence->organizer().isEmpty() ) {
1648 incidence->setOrganizer( Person( KOPrefs::instance()->fullName(),
1649 KOPrefs::instance()->email() ) );
1650 }
1651
1652 ICalFormat format;
1653 TQString messageText = format.createScheduleMessage( incidence, Scheduler::Request );
1654 KOMailClient mailer;
1655 if ( mailer.mailTo( incidence, recipients, messageText ) ) {
1656 KMessageBox::information(
1657 this,
1658 i18n( "The item information was successfully sent." ),
1659 i18n( "Forwarding" ),
1660 "IncidenceForwardSuccess" );
1661 } else {
1662 KMessageBox::error(
1663 this,
1664 i18n( "Unable to forward the item '%1'" ).arg( incidence->summary() ),
1665 i18n( "Forwarding Error" ) );
1666 }
1667 }
1668}
1669
1670void CalendarView::mailFreeBusy( int daysToPublish )
1671{
1672 TQDateTime start = TQDateTime::currentDateTime();
1673 TQDateTime end = start.addDays(daysToPublish);
1674
1675 FreeBusy *freebusy = new FreeBusy(mCalendar, start, end);
1676 freebusy->setOrganizer( Person( KOPrefs::instance()->fullName(),
1677 KOPrefs::instance()->email() ) );
1678
1679 kdDebug(5850) << "calendarview: schedule_publish_freebusy: startDate: "
1680 << TDEGlobal::locale()->formatDateTime( start ) << " End Date: "
1681 << TDEGlobal::locale()->formatDateTime( end ) << endl;
1682
1683 PublishDialog *publishdlg = new PublishDialog();
1684 if ( publishdlg->exec() == TQDialog::Accepted ) {
1685 // Send the mail
1686 KCal::MailScheduler scheduler( mCalendar );
1687 if ( scheduler.publish( freebusy, publishdlg->addresses() ) ) {
1688 KMessageBox::information( this, i18n("The free/busy information was successfully sent."),
1689 i18n("Sending Free/Busy"), "FreeBusyPublishSuccess" );
1690 } else {
1691 KMessageBox::error( this, i18n("Unable to publish the free/busy data.") );
1692 }
1693 }
1694 delete freebusy;
1695 delete publishdlg;
1696}
1697
1698void CalendarView::uploadFreeBusy()
1699{
1700 KOGroupware::instance()->freeBusyManager()->publishFreeBusy();
1701}
1702
1703void CalendarView::schedule(Scheduler::Method method, Incidence *incidence)
1704{
1705 if ( !incidence ) {
1706 incidence = selectedIncidence();
1707 }
1708
1709 if ( !incidence ) {
1710 KMessageBox::sorry( this, i18n("No item selected."),
1711 "ScheduleNoEventSelected" );
1712 return;
1713 }
1714
1715 if( incidence->attendeeCount() == 0 && method != Scheduler::Publish ) {
1716 KMessageBox::information( this, i18n("The item has no attendees."),
1717 "ScheduleNoIncidences" );
1718 return;
1719 }
1720
1721 Incidence *inc = incidence->clone();
1722 inc->registerObserver( 0 );
1723 inc->clearAttendees();
1724
1725 // Send the mail
1726 KCal::MailScheduler scheduler( mCalendar );
1727 if ( scheduler.performTransaction( incidence, method ) ) {
1728 KMessageBox::information( this, i18n("The groupware message for item '%1'"
1729 "was successfully sent.\nMethod: %2")
1730 .arg( incidence->summary() )
1731 .arg( Scheduler::methodName( method ) ),
1732 i18n("Sending Free/Busy"),
1733 "FreeBusyPublishSuccess" );
1734 } else {
1735 KMessageBox::error( this, i18n("Groupware message sending failed. "
1736 "%2 is request/reply/add/cancel/counter/etc.",
1737 "Unable to send the item '%1'.\nMethod: %2")
1738 .arg( incidence->summary() )
1739 .arg( Scheduler::methodName( method ) ) );
1740 }
1741}
1742
1743void CalendarView::openAddressbook()
1744{
1745 KRun::runCommand("kaddressbook");
1746}
1747
1748void CalendarView::setModified(bool modified)
1749{
1750 if (mModified != modified) {
1751 mModified = modified;
1752 emit modifiedChanged(mModified);
1753 }
1754}
1755
1757{
1758 return mReadOnly;
1759}
1760
1761void CalendarView::setReadOnly(bool readOnly)
1762{
1763 if (mReadOnly != readOnly) {
1764 mReadOnly = readOnly;
1765 emit readOnlyChanged(mReadOnly);
1766 }
1767}
1768
1770{
1771 return mModified;
1772}
1773
1775{
1776#ifndef KORG_NOPRINTER
1777 KOCoreHelper helper;
1778 CalPrinter printer( this, mCalendar, &helper );
1779 connect( this, TQ_SIGNAL(configChanged()), &printer, TQ_SLOT(updateConfig()) );
1780
1781 KOrg::BaseView *currentView = mViewManager->currentView();
1782
1783 CalPrinterBase::PrintType printType = CalPrinterBase::Month;
1784 if ( currentView ) {
1785 printType = currentView->printType();
1786 }
1787
1788 DateList tmpDateList = mDateNavigator->selectedDates();
1789 Incidence::List selectedIncidences;
1790 if ( mViewManager->currentView() ) {
1791 selectedIncidences = mViewManager->currentView()->selectedIncidences();
1792 }
1793 printer.print( printType, tmpDateList.first(), tmpDateList.last(), selectedIncidences );
1794#endif
1795}
1796
1798{
1799 // FIXME: Get rid of the settings object. When can I delete it???
1800 HTMLExportSettings *settings = new HTMLExportSettings( "KOrganizer" );
1801 // Manually read in the config, because parametrized tdeconfigxt objects don't
1802 // seem to load the config theirselves
1803 if ( settings ) settings->readConfig();
1804 ExportWebDialog *dlg = new ExportWebDialog( settings, this );
1805 connect( dlg, TQ_SIGNAL( exportHTML( HTMLExportSettings* ) ),
1806 this, TQ_SIGNAL( exportHTML( HTMLExportSettings* ) ) );
1807 dlg->show();
1808}
1809
1811{
1812 TQString filename = KFileDialog::getSaveFileName("icalout.ics",i18n("*.ics|ICalendars"),this);
1813 if ( !filename.isEmpty() )
1814 {
1815 // Force correct extension
1816 if (filename.right(4) != ".ics") filename += ".ics";
1817 if ( TQFile( filename ).exists() ) {
1818 if ( KMessageBox::No == KMessageBox::warningYesNo(
1819 this,
1820 i18n( "Do you want to overwrite %1?").arg(filename) ) ) {
1821 return;
1822 }
1823 }
1824 FileStorage storage( mCalendar, filename, new ICalFormat );
1825 storage.save();
1826 }
1827}
1828
1830{
1831 if (mCalendar->journals().count() > 0) {
1832 int result = KMessageBox::warningContinueCancel(this,
1833 i18n("The journal entries can not be exported to a vCalendar file."),
1834 i18n("Data Loss Warning"),i18n("Proceed"),"dontaskVCalExport",
1835 true);
1836 if (result != KMessageBox::Continue) return;
1837 }
1838
1839 TQString filename = KFileDialog::getSaveFileName("vcalout.vcs",i18n("*.vcs|vCalendars"),this);
1840 if ( !filename.isEmpty() )
1841 {
1842 // TODO: I don't like forcing extensions:
1843 // Force correct extension
1844 if (filename.right(4) != ".vcs") filename += ".vcs";
1845 if ( TQFile( filename ).exists() ) {
1846 if ( KMessageBox::No == KMessageBox::warningYesNo(
1847 this,
1848 i18n( "Do you want to overwrite %1?").arg(filename ) ) ) {
1849 return;
1850 }
1851 }
1852 FileStorage storage( mCalendar, filename, new VCalFormat );
1853 storage.save();
1854 }
1855}
1856
1857void CalendarView::eventUpdated(Incidence *)
1858{
1859 setModified();
1860 // Don't call updateView here. The code, which has caused the update of the
1861 // event is responsible for updating the view.
1862// updateView();
1863}
1864
1866{
1867 if (mViewManager->currentView()->isEventView()) {
1868 int days = mViewManager->currentView()->currentDateCount();
1869 if (days == 1) {
1870 emit changeNavStringPrev(i18n("&Previous Day"));
1871 emit changeNavStringNext(i18n("&Next Day"));
1872 } else {
1873 emit changeNavStringPrev(i18n("&Previous Week"));
1874 emit changeNavStringNext(i18n("&Next Week"));
1875 }
1876 }
1877}
1878
1879void CalendarView::processMainViewSelection( Incidence *incidence, const TQDate &date )
1880{
1881 if ( incidence ) mTodoList->clearSelection();
1882 processIncidenceSelection( incidence, date );
1883}
1884
1885void CalendarView::processTodoListSelection( Incidence *incidence, const TQDate &date )
1886{
1887 if ( incidence && mViewManager->currentView() ) {
1888 mViewManager->currentView()->clearSelection();
1889 }
1890 processIncidenceSelection( incidence, date );
1891}
1892
1893void CalendarView::processIncidenceSelection( Incidence *incidence, const TQDate &date )
1894{
1895 if ( incidence != mSelectedIncidence ) {
1896 // This signal also must be emitted if incidence is 0
1897 emit incidenceSelected( incidence, date );
1898 }
1899
1900 if ( !incidence ) {
1901 mSelectedIncidence = incidence;
1902 return;
1903 }
1904 if ( incidence == mSelectedIncidence ) {
1905 if ( !incidence->doesRecur() || mSaveDate == date ) {
1906 return;
1907 }
1908 }
1909
1910 mSelectedIncidence = incidence;
1911 mSaveDate = date;
1912
1913 emit incidenceSelected( mSelectedIncidence, date );
1914 bool organizerEvents = false;
1915 bool groupEvents = false;
1916 bool todo = false;
1917 bool subtodo = false;
1918
1919 organizerEvents = KOPrefs::instance()->thatIsMe( incidence->organizer().email() );
1920 groupEvents = incidence->attendeeByMails( KOPrefs::instance()->allEmails() );
1921
1922 if ( incidence->type() == "Todo" ) {
1923 todo = true;
1924 subtodo = ( incidence->relatedTo() != 0 );
1925 }
1926
1927 emit todoSelected( todo );
1928 emit subtodoSelected( subtodo );
1929 emit organizerEventsSelected( organizerEvents );
1930 emit groupEventsSelected( groupEvents );
1931}
1932
1933
1935{
1936#ifndef KORG_NODND
1937 if (ICalDrag::canDecode(TQApplication::clipboard()->data())) {
1938 kdDebug(5850) << "CalendarView::checkClipboard() true" << endl;
1939 emit pasteEnabled(true);
1940 } else {
1941 kdDebug(5850) << "CalendarView::checkClipboard() false" << endl;
1942 emit pasteEnabled(false);
1943 }
1944#endif
1945}
1946
1947void CalendarView::showDates( const DateList &selectedDates, const TQDate &preferredMonth )
1948{
1949 mDateNavigatorContainer->selectDates( selectedDates, preferredMonth );
1950 mNavigatorBar->selectDates( selectedDates );
1951
1952 if ( mViewManager->currentView() ) {
1953 updateView( selectedDates.first(), selectedDates.last() );
1954 } else {
1955 mViewManager->showAgendaView();
1956 }
1957}
1958
1959void CalendarView::editFilters()
1960{
1961 kdDebug(5850) << "CalendarView::editFilters()" << endl;
1962
1963 CalFilter *filter = mFilters.first();
1964 while( filter ) {
1965 kdDebug(5850) << " Filter: " << filter->name() << endl;
1966 filter = mFilters.next();
1967 }
1968
1969 mDialogManager->showFilterEditDialog(&mFilters);
1970}
1971
1975{
1976 TQStringList filters;
1977 CalFilter *filter;
1978
1979 int pos = mFilters.find( mCurrentFilter );
1980 if ( pos < 0 ) {
1981 mCurrentFilter = 0;
1982 }
1983
1984 filters << i18n("No filter");
1985 for ( filter = mFilters.first(); filter; filter = mFilters.next() ) {
1986 filters << filter->name();
1987 }
1988
1989 emit newFilterListSignal( filters );
1990 // account for the additional "No filter" at the beginning! if the
1991 // filter is not in the list, pos == -1...
1992 emit selectFilterSignal( pos+1 );
1993 mCalendar->setFilter( mCurrentFilter );
1994 updateView();
1995}
1996
2000{
2001 CalFilter *newFilter = 0;
2002 if ( filterNo > 0 && filterNo <= int(mFilters.count()) ) {
2003 newFilter = mFilters.at( filterNo-1 );
2004 }
2005 if ( newFilter != mCurrentFilter ) {
2006 mCurrentFilter = newFilter;
2007 mCalendar->setFilter( mCurrentFilter );
2008 updateView();
2009 }
2010 emit filterChanged();
2011}
2012
2014{
2015 if ( mCurrentFilter) {
2016 return mCurrentFilter->name();
2017 } else return i18n("No filter");
2018}
2019
2021{
2022 Incidence *incidence = currentSelection();
2023
2024 if (!incidence) return;
2025
2026 incidence->setOrganizer( Person( KOPrefs::instance()->fullName(),
2027 KOPrefs::instance()->email() ) );
2028 incidence->recreate();
2029 incidence->setReadOnly(false);
2030
2031 updateView();
2032}
2033
2035{
2036 Incidence::List incidences = mCalendar->rawIncidences();
2037 Incidence::List::Iterator it;
2038
2039 for ( it = incidences.begin(); it != incidences.end(); ++it ) {
2040 (*it)->setOrganizer( Person( KOPrefs::instance()->fullName(),
2041 KOPrefs::instance()->email() ) );
2042 (*it)->recreate();
2043 (*it)->setReadOnly(false);
2044 }
2045 updateView();
2046}
2047
2048void CalendarView::showIntro()
2049{
2050 kdDebug(5850) << "To be implemented." << endl;
2051}
2052
2053void CalendarView::showDateNavigator( bool show )
2054{
2055 if( show )
2056 mDateNavigatorContainer->show();
2057 else
2058 mDateNavigatorContainer->hide();
2059}
2060
2061void CalendarView::showTodoView( bool show )
2062{
2063 if( show )
2064 mTodoList->show();
2065 else
2066 mTodoList->hide();
2067}
2068
2069void CalendarView::showEventViewer( bool show )
2070{
2071 if( show )
2072 mEventViewer->show();
2073 else
2074 mEventViewer->hide();
2075}
2076
2077
2078void CalendarView::addView(KOrg::BaseView *view)
2079{
2080 mViewManager->addView(view);
2081}
2082
2084{
2085 mViewManager->showView(view);
2086}
2087
2088void CalendarView::addExtension( CalendarViewExtension::Factory *factory )
2089{
2090 CalendarViewExtension *extension = factory->create( mLeftSplitter );
2091
2092 mExtensions.append( extension );
2093}
2094
2095void CalendarView::toggleExpand()
2096{
2097 showLeftFrame( mLeftFrame->isHidden() );
2098}
2099
2100void CalendarView::showLeftFrame(bool show)
2101{
2102 if (show) {
2103 mLeftFrame->show();
2104 emit calendarViewExpanded( false );
2105 } else {
2106 mLeftFrame->hide();
2107 emit calendarViewExpanded( true );
2108 }
2109}
2110
2111void CalendarView::calendarModified( bool modified, Calendar * )
2112{
2113 setModified( modified );
2114}
2115
2116Todo *CalendarView::selectedTodo()
2117{
2118 Incidence *incidence = currentSelection();
2119 if ( incidence && incidence->type() == "Todo" ) {
2120 return static_cast<Todo *>( incidence );
2121 }
2122 incidence = 0;
2123
2124 Incidence::List selectedIncidences = mTodoList->selectedIncidences();
2125 if ( !selectedIncidences.isEmpty() ) incidence = selectedIncidences.first();
2126 if ( incidence && incidence->type() == "Todo" ) {
2127 return static_cast<Todo *>( incidence );
2128 }
2129
2130 return 0;
2131}
2132
2133void CalendarView::dialogClosing( Incidence *in )
2134{
2135 // FIXME: this doesn't work, because if it's a new incidence, it's not locked!
2136 mChanger->endChange( in, 0, TQString() );
2137 mDialogList.remove( in );
2138}
2139
2141{
2142 return mViewManager->currentSelection();
2143}
2144
2146{
2147 Incidence *incidence = currentSelection();
2148 if ( !incidence ) {
2149 Incidence::List selectedIncidences = mTodoList->selectedIncidences();
2150 if ( !selectedIncidences.isEmpty() )
2151 incidence = selectedIncidences.first();
2152 }
2153 return incidence;
2154}
2155
2156void CalendarView::showIncidence()
2157{
2158 showIncidence( selectedIncidence(), activeIncidenceDate() );
2159}
2160
2161void CalendarView::editIncidence()
2162{
2163 editIncidence( selectedIncidence(), activeIncidenceDate() );
2164}
2165
2166bool CalendarView::editIncidence( const TQString &uid )
2167{
2168 return editIncidence( mCalendar->incidence( uid ), TQDate() );
2169}
2170
2171bool CalendarView::editIncidence( const TQString &uid, const TQDate &date )
2172{
2173 return editIncidence( mCalendar->incidence( uid ), date );
2174}
2175
2176void CalendarView::deleteIncidence()
2177{
2178 deleteIncidence( selectedIncidence() );
2179}
2180
2182{
2183 edit_cut();
2184}
2185
2187{
2188 edit_copy();
2189}
2190
2192{
2193 edit_paste();
2194}
2195
2196void CalendarView::showIncidence( Incidence *incidence, const TQDate &date )
2197{
2198 if ( !incidence ) {
2199 return;
2200 }
2201
2202 KOEventViewerDialog *eventViewer = new KOEventViewerDialog( calendar(), this );
2203 eventViewer->setIncidence( incidence, date );
2204 eventViewer->show();
2205}
2206
2207bool CalendarView::editIncidence( Incidence *incidence, const TQDate &date, bool isCounter )
2208{
2209 kdDebug(5850) << "CalendarView::editEvent()" << endl;
2210
2211 CalendarResources *stdcal = dynamic_cast<CalendarResources *>( mCalendar );
2212 if( stdcal && !stdcal->hasCalendarResources() ) {
2213 KMessageBox::sorry(
2214 this,
2215 i18n( "No resources found. We can not edit the item." ) );
2216 return false;
2217 }
2218
2219 // FIXME: This is a nasty hack, since we need to set a parent for the
2220 // resource selection dialog. However, we don't have any UI methods
2221 // in the calendar, only in the CalendarResources::DestinationPolicy
2222 // So we need to type-cast it and extract it from the CalendarResources
2223 TQWidget *tmpparent = 0;
2224 if ( stdcal ) {
2225 tmpparent = stdcal->dialogParentWidget();
2226 stdcal->setDialogParentWidget( this );
2227 }
2228
2229 if ( !incidence ) {
2230 kdDebug(5850) << "Empty Incidence" << endl;
2231 KNotifyClient::beep();
2232 return false;
2233 }
2234
2235 if ( !mChanger ) {
2236 kdDebug(5850) << "Empty Changer" << endl;
2237 KNotifyClient::beep();
2238 return false;
2239 }
2240
2241 KOIncidenceEditor *tmp = editorDialog( incidence );
2242 if ( tmp ) {
2243 kdDebug(5850) << "CalendarView::editIncidence() in List" << endl;
2244 tmp->reload();
2245 tmp->raise();
2246 tmp->show();
2247 return true;
2248 }
2249
2250 if ( incidence->isReadOnly() ) {
2251 showIncidence( incidence, date );
2252 return true;
2253 }
2254
2255 TQPair<ResourceCalendar *, TQString>p =
2256 CalHelper::incSubResourceCalendar( calendar(), incidence );
2257
2258 Incidence *savedIncidence = incidence->clone();
2259 Incidence *incToChange;
2260
2261 if ( incidence->doesRecur() ) {
2262 KOGlobals::WhichOccurrences chosenOption;
2263 incToChange = singleOccurrenceOrAll( incidence, KOGlobals::EDIT, chosenOption, date );
2264 } else {
2265 incToChange = incidence;
2266 }
2267
2268 // If the user pressed cancel incToChange is 0
2269 if ( incToChange ) {
2270 if ( !isCounter && !mChanger->beginChange( incToChange, p.first, p.second ) ) {
2271 warningChangeFailed( incToChange );
2272 showIncidence( incToChange, date );
2273
2274 return false;
2275 }
2276
2277 kdDebug(5850) << "CalendarView::editIncidence() new IncidenceEditor" << endl;
2278 KOIncidenceEditor *incidenceEditor = mDialogManager->getEditor( incToChange );
2279 connectIncidenceEditor( incidenceEditor );
2280
2281 mDialogList.insert( incToChange, incidenceEditor );
2282 if ( incidence != incToChange ) {
2283 incidenceEditor->setRecurringIncidence( savedIncidence, incidence );
2284 }
2285 incidenceEditor->setResource( p.first, p.second );
2286 incidenceEditor->editIncidence( incToChange, date, mCalendar );
2287 incidenceEditor->show();
2288 return true;
2289 } else {
2290 return false;
2291 }
2292}
2293
2295{
2296 if( !todo ) return;
2297
2298 Incidence::List subTodos( todo->relations() );
2299 Incidence::List::Iterator it;
2300 Incidence *aIncidence;
2301 Todo *aTodo;
2302
2303 for ( it= subTodos.begin(); it != subTodos.end(); ++it ) {
2304 aIncidence = *it;
2305 if( aIncidence && aIncidence->type() == "Todo" ) {
2306 aTodo = static_cast<Todo*>( aIncidence );
2307 deleteSubTodosIncidence ( aTodo );
2308 }
2309 }
2310 mChanger->deleteIncidence ( todo, this );
2311}
2312
2313void CalendarView::deleteTodoIncidence ( Todo *todo, bool force )
2314{
2315 if ( !todo ) return ;
2316
2317 // it a simple todo, ask and delete it.
2318 if (todo->relations().isEmpty() ) {
2319 bool doDelete = true;
2320 if ( !force && KOPrefs::instance()->mConfirm ) {
2321 doDelete = ( msgItemDelete( todo ) == KMessageBox::Continue );
2322 }
2323 if ( doDelete )
2324 mChanger->deleteIncidence( todo, this );
2325 return;
2326 }
2327
2328 /* Ok, this to-do has sub-to-dos, ask what to do */
2329 int km = KMessageBox::No;
2330 if ( !force ) {
2331 km = KMessageBox::questionYesNoCancel(
2332 this,
2333 i18n("The item \"%1\" has sub-to-dos. "
2334 "Do you want to delete just this item and "
2335 "make all its sub-to-dos independent, or "
2336 "delete the to-do with all its sub-to-dos?"
2337 ).arg( todo->summary() ),
2338 i18n("KOrganizer Confirmation"),
2339 i18n("Delete Only This"),
2340 i18n("Delete All"));
2341 }
2342 startMultiModify( i18n("Deleting sub-to-dos" ) );
2343 // Delete only the father
2344 if( km == KMessageBox::Yes ) {
2345 // Instead of making a subto-do independent, why not relate
2346 // it to it's dead father's parent?
2347 makeChildrenIndependent ( todo );
2348 mChanger->deleteIncidence( todo, this );
2349 } else if ( km == KMessageBox::No ) {
2350 // Delete all
2351 // we have to hide the delete confirmation for each itemDate
2352 deleteSubTodosIncidence ( todo );
2353 }
2354 endMultiModify();
2355}
2356
2357void CalendarView::deleteIncidence(Incidence *incidence, bool force)
2358{
2359 if ( !incidence || !mChanger ) {
2360 if ( !force ) {
2361 KNotifyClient::beep();
2362 }
2363 return;
2364 }
2365 if ( incidence->isReadOnly() ) {
2366 if ( !force ) {
2367 KMessageBox::information( this, i18n("The item \"%1\" is marked read-only "
2368 "and cannot be deleted; it probably belongs to "
2369 "a read-only calendar resource.")
2370 .arg(incidence->summary()),
2371 i18n("Removing not possible"),
2372 "deleteReadOnlyIncidence" );
2373 }
2374 return;
2375 }
2376
2377 CanDeleteIncidenceVisitor v;
2378
2379 // Let the visitor do special things for special incidence types.
2380 // e.g. todos with children cannot be deleted, so act(..) returns false
2381 if ( !v.act( incidence, this ) )
2382 return;
2383 //If it is a todo, there are specific delete function
2384
2385 if ( incidence && incidence->type()=="Todo" ) {
2386 deleteTodoIncidence( static_cast<Todo*>(incidence), force );
2387 return;
2388 }
2389
2390 if ( incidence->doesRecur() ) {
2391 TQDate itemDate = mViewManager->currentSelectionDate();
2392 kdDebug(5850) << "Recurrence-Date: " << TQString(itemDate.toString()) << endl;
2393 int km = KMessageBox::Ok;
2394 if ( !force ) {
2395 if ( !itemDate.isValid() ) {
2396 kdDebug(5850) << "Date Not Valid" << endl;
2397 km = KMessageBox::warningContinueCancel(this,
2398 i18n("The calendar item \"%1\" recurs over multiple dates; "
2399 "are you sure you want to delete it "
2400 "and all its recurrences?").arg( incidence->summary() ),
2401 i18n("KOrganizer Confirmation"), i18n("Delete All") );
2402 } else {
2403 km = KOMessageBox::fourBtnMsgBox( this, TQMessageBox::Warning,
2404 i18n("The calendar item \"%1\" recurs over multiple dates. "
2405 "Do you want to delete only the current one on %2, only all "
2406 "future recurrences, or all its recurrences?" )
2407 .arg( incidence->summary() )
2408 .arg( TDEGlobal::locale()->formatDate(itemDate)),
2409 i18n("KOrganizer Confirmation"), i18n("Delete C&urrent"),
2410 i18n("Delete &Future"),
2411 i18n("Delete &All"));
2412 }
2413 }
2414
2415 TQPair<ResourceCalendar *, TQString>p =
2416 CalHelper::incSubResourceCalendar( calendar(), incidence );
2417
2418 switch(km) {
2419 case KMessageBox::Ok: // Continue // all
2420 case KMessageBox::Continue:
2421 mChanger->deleteIncidence( incidence, this );
2422 break;
2423
2424 case KMessageBox::Yes: // just this one
2425 if ( mChanger->beginChange( incidence, p.first, p.second ) ) {
2426 Incidence *oldIncidence = incidence->clone();
2427 if (incidence->recurrence()->startDate() == itemDate) {
2428 // Moving the first in a series...don't bother with the nonstandard exclusion list
2429 Recurrence *recur = incidence->recurrence();
2430 Event* thisevent = static_cast<Event*>(incidence);
2431 TQDateTime newEnd;
2432 TQDateTime newRecurEnd;
2433 newRecurEnd = recur->endDateTime();
2434 newEnd.setTime_t( incidence->dtEnd().toTime_t() + ( recur->getNextDateTime( recur->startDateTime() ).toTime_t() - recur->startDateTime().toTime_t() ) );
2435 thisevent->setDtEnd( newEnd );
2436 incidence->setDtStart( recur->getNextDateTime( recur->startDateTime() ) );
2437 recur->setEndDateTime(newRecurEnd);
2438 }
2439 else {
2440 // No choice but to use the exclusion list
2441 incidence->recurrence()->addExDate( itemDate );
2442 }
2443 mChanger->changeIncidence( oldIncidence, incidence, KOGlobals::RECURRENCE_MODIFIED_ONE_ONLY, this );
2444 mChanger->endChange( incidence, p.first, p.second );
2445 delete oldIncidence;
2446 }
2447 break;
2448 case KMessageBox::No: // all future items
2449 if ( mChanger->beginChange( incidence, p.first, p.second ) ) {
2450 Incidence *oldIncidence = incidence->clone();
2451 Recurrence *recur = incidence->recurrence();
2452 recur->setEndDate( itemDate.addDays(-1) );
2453 mChanger->changeIncidence( oldIncidence, incidence, KOGlobals::RECURRENCE_MODIFIED_ONE_ONLY, this );
2454 mChanger->endChange( incidence, p.first, p.second );
2455 delete oldIncidence;
2456 }
2457 break;
2458 }
2459 } else {
2460 bool doDelete = true;
2461 if ( !force && KOPrefs::instance()->mConfirm ) {
2462 doDelete = ( msgItemDelete( incidence ) == KMessageBox::Continue );
2463 }
2464 if ( doDelete ) {
2465 mChanger->deleteIncidence( incidence, this );
2466 processIncidenceSelection( 0, TQDate() );
2467 }
2468 }
2469
2470 updateView();
2471}
2472
2473void CalendarView::connectIncidenceEditor( KOIncidenceEditor *editor )
2474{
2475 connect( this, TQ_SIGNAL( newIncidenceChanger( IncidenceChangerBase* ) ),
2476 editor, TQ_SLOT( setIncidenceChanger( IncidenceChangerBase* ) ) );
2477 editor->setIncidenceChanger( mChanger );
2478}
2479
2480bool CalendarView::purgeCompletedSubTodos( Todo* todo, bool &allPurged )
2481{
2482 if ( !todo ) return true;
2483 bool deleteThisTodo = true;
2484 Incidence::List subTodos( todo->relations() );
2485 Incidence *aIncidence;
2486 Todo *aTodo;
2487 Incidence::List::Iterator it;
2488 for ( it = subTodos.begin(); it != subTodos.end(); ++it ) {
2489 aIncidence = *it;
2490 if ( aIncidence && aIncidence->type()=="Todo" ) {
2491 aTodo = static_cast<Todo*>( aIncidence );
2492 deleteThisTodo &= purgeCompletedSubTodos( aTodo, allPurged );
2493 }
2494 }
2495
2496 if ( deleteThisTodo ) {
2497 if ( todo->isCompleted() ) {
2498 if ( !mChanger->deleteIncidence( todo, this ) )
2499 allPurged = false;
2500 } else {
2501 deleteThisTodo = false;
2502 }
2503 } else {
2504 if ( todo->isCompleted() ) {
2505 allPurged = false;
2506 }
2507 }
2508 return deleteThisTodo;
2509}
2510
2511void CalendarView::purgeCompleted()
2512{
2513 int result = KMessageBox::warningContinueCancel(this,
2514 i18n("Delete all completed to-dos?"),i18n("Purge To-dos"),i18n("Purge"));
2515
2516 if (result == KMessageBox::Continue) {
2517 bool allDeleted = true;
2518 startMultiModify( i18n("Purging completed to-dos") );
2519 Todo::List todos = calendar()->rawTodos();
2520 Todo::List rootTodos;
2521 Todo::List::ConstIterator it;
2522 for ( it = todos.begin(); it != todos.end(); ++it ) {
2523 Todo *aTodo = *it;
2524 if ( aTodo && !aTodo->relatedTo() )
2525 rootTodos.append( aTodo );
2526 }
2527 // now that we have a list of all root todos, check them and their children
2528 for ( it = rootTodos.begin(); it != rootTodos.end(); ++it ) {
2529 purgeCompletedSubTodos( *it, allDeleted );
2530 }
2531 endMultiModify();
2532 if ( !allDeleted ) {
2533 KMessageBox::information( this, i18n("Unable to purge to-dos with "
2534 "uncompleted children."), i18n("Delete To-do"),
2535 "UncompletedChildrenPurgeTodos" );
2536 }
2537 }
2538}
2539
2540void CalendarView::warningChangeFailed( Incidence *incidence )
2541{
2542 if ( incidence ) {
2543 KMessageBox::sorry(
2544 this,
2545 i18n( "Unable to edit \"%1\" because it is locked by another process." ).
2546 arg( incidence->summary() ) );
2547 }
2548}
2549
2550void CalendarView::editCanceled( Incidence *incidence )
2551{
2552 mCalendar->endChange( incidence );
2553}
2554
2555void CalendarView::showErrorMessage( const TQString &msg )
2556{
2557 KMessageBox::error( this, msg );
2558}
2559
2561{
2562 TQStringList allCats( calendar()->categories() );
2563 allCats.sort();
2564 TQStringList categories( KOPrefs::instance()->mCustomCategories );
2565 for ( TQStringList::ConstIterator si = allCats.constBegin(); si != allCats.constEnd(); ++si ) {
2566 if ( categories.find( *si ) == categories.end() ) {
2567 categories.append( *si );
2568 }
2569 }
2570 KOPrefs::instance()->mCustomCategories = categories;
2571 KOPrefs::instance()->writeConfig();
2572 // Make the category editor update the list!
2573 emit categoriesChanged();
2574}
2575
2576void CalendarView::addIncidenceOn( Incidence *incadd, const TQDate &dt )
2577{
2578 if ( !incadd || !mChanger ) {
2579 KMessageBox::sorry(this, i18n("Unable to copy the item to %1.")
2580 .arg( dt.toString() ), i18n("Copying Failed") );
2581 return;
2582 }
2583 Incidence *incidence = mCalendar->incidence( incadd->uid() );
2584 if ( !incidence ) incidence = incadd;
2585 // Create a copy of the incidence, since the incadd doesn't belong to us.
2586 incidence = incidence->clone();
2587 incidence->recreate();
2588
2589 if ( incidence->type() == "Event" ) {
2590 Event *event = static_cast<Event*>(incidence);
2591
2592 // Adjust date
2593 TQDateTime start = event->dtStart();
2594 TQDateTime end = event->dtEnd();
2595
2596 int duration = start.daysTo( end );
2597 start.setDate( dt );
2598 end.setDate( dt.addDays( duration ) );
2599
2600 event->setDtStart( start );
2601 event->setDtEnd( end );
2602
2603 } else if ( incidence->type() == "Todo" ) {
2604 Todo *todo = static_cast<Todo*>(incidence);
2605 TQDateTime due = todo->dtDue();
2606 due.setDate( dt );
2607
2608 todo->setDtDue( due );
2609 todo->setHasDueDate( true );
2610 }
2611
2612 TQPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar();
2613
2614 if ( !mChanger->addIncidence( incidence, p.first, p.second, this ) ) {
2615 KODialogManager::errorSaveIncidence( this, incidence );
2616 delete incidence;
2617 }
2618}
2619
2620void CalendarView::moveIncidenceTo( Incidence *incmove, const TQDate &dt )
2621{
2622 if ( !incmove || !mChanger ) {
2623 KMessageBox::sorry( this, i18n("Unable to move the item to %1.")
2624 .arg( dt.toString() ), i18n("Moving Failed") );
2625 return;
2626 }
2627 Incidence *incidence = mCalendar->incidence( incmove->uid() );
2628 if ( !incidence ) {
2629 addIncidenceOn( incidence, dt );
2630 return;
2631 }
2632
2633 Incidence *oldIncidence = incidence->clone();
2634 TQPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar();
2635
2636 if ( !mChanger->beginChange( incidence, p.first, p.second ) ) {
2637 delete oldIncidence;
2638 return;
2639 }
2640
2641 if ( incidence->type() == "Event" ) {
2642 Event *event = static_cast<Event*>(incidence);
2643
2644 // Adjust date
2645 TQDateTime start = event->dtStart();
2646 TQDateTime end = event->dtEnd();
2647
2648 int duration = start.daysTo( end );
2649 start.setDate( dt );
2650 end.setDate( dt.addDays( duration ) );
2651
2652 event->setDtStart( start );
2653 event->setDtEnd( end );
2654
2655 } else if ( incidence->type() == "Todo" ) {
2656 Todo *todo = static_cast<Todo*>(incidence);
2657 TQDateTime due = todo->dtDue();
2658 due.setDate( dt );
2659
2660 todo->setDtDue( due );
2661 todo->setHasDueDate( true );
2662 }
2663 mChanger->changeIncidence( oldIncidence, incidence, KOGlobals::DATE_MODIFIED,this );
2664 mChanger->endChange( incidence, p.first, p.second );
2665 delete oldIncidence;
2666}
2667
2668void CalendarView::resourcesChanged()
2669{
2670 mViewManager->resourcesChanged();
2671 mDateNavigatorContainer->setUpdateNeeded();
2672 updateView();
2673}
2674
2676 KOGlobals::OccurrenceAction userAction,
2677 KOGlobals::WhichOccurrences &chosenOption,
2678 const TQDate &itemDate,
2679 const bool commitToCalendar )
2680{
2681
2682 // temporary, until recurring to-dos are fixed
2683 if ( inc->type() != "Event" ) {
2684 chosenOption = KOGlobals::ALL;
2685 return inc;
2686 }
2687
2688 Incidence *incToReturn = 0;
2689 Incidence *incSaved = 0;
2690 KOGlobals::WhatChanged whatChanged;
2691
2692 bool dissociationOccurred = false;
2693 const TQDate &dt = itemDate.isValid() ? itemDate : activeIncidenceDate();
2694
2695 TQString dialogTitle;
2696 TQString dialogText;
2697
2698 if ( userAction == KOGlobals::CUT ) {
2699 dialogTitle = i18n( "Cutting Recurring Item" );
2700
2701 dialogText = i18n("The item you try to cut is a recurring item. Do you want to cut "
2702 "only this single occurrence, only future items, "
2703 "or all items in the recurrence?");
2704
2705 } else if ( userAction == KOGlobals::COPY ) {
2706 dialogTitle = i18n( "Copying Recurring Item" );
2707
2708 dialogText = i18n("The item you try to copy is a recurring item. Do you want to copy "
2709 "only this single occurrence, only future items, "
2710 "or all items in the recurrence?");
2711 } else {
2712 dialogTitle = i18n( "Changing Recurring Item" );
2713
2714 dialogText = i18n( "The item you try to change is a recurring item. Shall the changes "
2715 "be applied only to this single occurrence, only to the future items, "
2716 "or to all items in the recurrence?" );
2717 }
2718
2719 int res = KOMessageBox::fourBtnMsgBox( this, TQMessageBox::Question,
2720 dialogText,
2721 dialogTitle,
2722 i18n("Only &This Item"), i18n("Only &Future Items"), i18n("&All Occurrences") );
2723 switch ( res ) {
2724 case KMessageBox::Ok: // All occurrences
2725 incToReturn = inc;
2726 chosenOption = KOGlobals::ALL;
2727 break;
2728 case KMessageBox::Yes: { // Just this occurrence
2729 // Dissociate this occurrence:
2730 // create clone of event, set relation to old event, set cloned event
2731 // for mActionItem, add exception date to old event, changeIncidence
2732 // for the old event, remove the recurrence from the new copy and then just
2733 // go on with the newly adjusted mActionItem and let the usual code take
2734 // care of the new time!
2735
2736 chosenOption = KOGlobals::ONLY_THIS_ONE;
2737 whatChanged = KOGlobals::RECURRENCE_MODIFIED_ONE_ONLY;
2738 startMultiModify( i18n("Dissociate event from recurrence") );
2739 incSaved = inc->clone();
2740 incToReturn = mCalendar->dissociateOccurrence( inc, dt );
2741 if ( incToReturn ) {
2742 dissociationOccurred = true;
2743 } else {
2744 KMessageBox::sorry( this, i18n("Unable to add the exception item to the "
2745 "calendar. No change will be done."), i18n("Error Occurred") );
2746 incToReturn = 0;
2747 }
2748
2749 break; }
2750 case KMessageBox::No/*Future*/: { // All future occurrences
2751 // Dissociate this occurrence:
2752 // create clone of event, set relation to old event, set cloned event
2753 // for mActionItem, add recurrence end date to old event, changeIncidence
2754 // for the old event, adjust the recurrence for the new copy and then just
2755 // go on with the newly adjusted mActionItem and let the usual code take
2756 // care of the new time!
2757 chosenOption = KOGlobals::ONLY_FUTURE;
2758 whatChanged = KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE;
2759 startMultiModify( i18n("Split future recurrences") );
2760 incSaved = inc->clone();
2761 incToReturn = mCalendar->dissociateOccurrence( inc, dt, false );
2762 if ( incToReturn ) {
2763 dissociationOccurred = true;
2764 } else {
2765 KMessageBox::sorry( this, i18n("Unable to add the future items to the "
2766 "calendar. No change will be done."), i18n("Error Occurred") );
2767
2768 incToReturn = 0;
2769 }
2770
2771 break; }
2772 default:
2773 chosenOption = KOGlobals::NONE;
2774 }
2775
2776 if ( dissociationOccurred && commitToCalendar ) {
2777 TQPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar();
2778 mChanger->addIncidence( incToReturn, p.first, p.second, this );
2779 mChanger->changeIncidence( incSaved, inc, whatChanged, this );
2780 }
2781
2782 return incToReturn;
2783}
2784
2785void CalendarView::selectWeek( const TQDate &date )
2786{
2787 if ( KOPrefs::instance()->mWeekNumbersShowWork &&
2788 mViewManager->agendaIsSelected() &&
2789 mViewManager->agendaMode() == KOViewManager::AGENDA_WORK_WEEK ) {
2790 mDateNavigator->selectWorkWeek( date );
2791 } else {
2792 mDateNavigator->selectWeek( date );
2793 }
2794}
2795
2796void CalendarView::getIncidenceHierarchy( Incidence *inc,
2797 Incidence::List &children )
2798{
2799 // protecion against looping hierarchies
2800 if ( inc && !children.contains( inc ) ) {
2801 Incidence::List::ConstIterator it;
2802 Incidence::List immediateChildren = inc->relations();
2803 for ( it = immediateChildren.constBegin(); it != immediateChildren.constEnd(); ++it ) {
2804 getIncidenceHierarchy( *it, children );
2805 }
2806 children.append( inc );
2807 }
2808}
2809
2810#include "calendarview.moc"
CalPrinter is a class for printing Calendars.
Definition: calprinter.h:54
void appointment_delete()
pop up dialog confirming deletion of currently selected event in the View.
void newSubTodo()
create new todo with a parent todo
void updateCategories()
Calendar configuration was changed, so refresh categories list.
void readFilterSettings(TDEConfig *config)
read settings for calendar filters
void groupEventsSelected(bool)
Emitted when state of events selection has changed and user is attendee.
void setReadOnly(bool readOnly=true)
set state of calendar to read-only
void exportWeb()
Export as HTML file.
bool openCalendar(const TQString &filename, bool merge=false)
Load calendar from file filename.
void cutIncidence(Incidence *)
Cuts the selected incidence using the edit_cut() method.
void updateFilter()
Filter configuration changed.
bool makeSubTodosIndependent()
Make all sub-to-dos of the selected todo independent, update the view.
void dayPassed(const TQDate &)
Emitted, when a day changed (i.e.
TQDate activeDate(bool fallbackToToday=false)
Returns the best guess at the current active date in the view.
CalendarView(TQWidget *parent=0, const char *name=0)
Constructs a new calendar view widget.
void readSettings()
Using the TDEConfig associated with the tdeApp variable, read in the settings from the config file.
void pasteEnabled(bool)
Emitted, when clipboard content changes.
void changeIncidenceDisplay(Incidence *, int)
passes on the message that an event has changed to the currently activated view so that it can make a...
void appointment_edit()
pop up an Appointment Dialog to edit an existing appointment.
void takeOverCalendar()
Take ownership of all events in calendar.
void deleteSubTodosIncidence(Todo *todo)
Delete the supplied todo and all sub-todos.
TQDate activeIncidenceDate()
Returns the date of the selected incidence.
void edit_cut()
cut the current appointment to the clipboard
void modifiedChanged(bool)
Emitted when state of modified flag changes.
void goNext()
Move to the next date(s) in the current view.
void deleteTodoIncidence(Todo *todo, bool force=false)
Delete the todo incidence, and its sub-to-dos.
void pasteIncidence()
Pastes the curren incidence using the edit_paste() method.
void selectWeek(const TQDate &)
The user clicked on a week number in the date navigator.
void cancelAttendees(Incidence *)
Attendees were removed from this incidence.
bool addIncidence(const TQString &ical)
Add an incidence to the active calendar.
void newEvent()
create new event without having a date hint.
Incidence * singleOccurrenceOrAll(Incidence *inc, KOGlobals::OccurrenceAction userAction, KOGlobals::WhichOccurrences &chosenOption, const TQDate &itemDate=TQDate(), const bool commitToCalendar=false)
Asks the user if he wants to edit only this occurrence, all occurrences or only future occurrences,...
void writeSettings()
write current state to config file.
void print()
Functions for printing, previewing a print, and setting up printing parameters.
void edit_paste()
paste the current vobject(s) in the clipboard buffer into calendar
void organizerEventsSelected(bool)
Emitted when state of events selection has changed and user is organizer.
void filterActivated(int filterNum)
A different filter was selected.
void exportVCalendar()
Export as vCalendar file.
void copyIncidence(Incidence *)
Copies the selected incidence using the edit_copy() method.
void goToday()
Move the current view date to today.
void incidenceSelected(Incidence *incidence, const TQDate &date)
Emitted when an incidence gets selected.
void checkClipboard()
Check if clipboard contains vCalendar event.
bool isModified()
query whether or not the calendar is "dirty".
bool isReadOnly()
query if the calendar is read-only.
void showDates(const KCal::DateList &, const TQDate &preferredMonth=TQDate())
Select a view or adapt the current view to display the specified dates.
TQString currentFilterName() const
Returns the name of the current filter.
bool makeChildrenIndependent(Incidence *inc)
Make all children of incidence independent, not update the view Works with any incidence type,...
void dateTimesForNewEvent(TQDateTime &startDt, TQDateTime &endDt, bool &allDay)
Adjust the given date/times by valid defaults (selection or configured defaults, if invalid values ar...
void showDate(const TQDate &date)
Show the given date without changing date selection length.
void updateConfig(const TQCString &)
options dialog made a changed to the configuration.
void writeFilterSettings(TDEConfig *config)
write settings for calendar filters
void showView(KOrg::BaseView *)
changes the view to be the currently selected view
void takeOverEvent()
Take ownership of selected event.
void edit_options()
edit viewing and configuration options.
void adaptNavigationUnits()
Adapt navigation units corresponding to step size of navigation of the current view.
void addExtension(CalendarViewExtension::Factory *)
Add calendar view extension widget.
void exportICalendar()
Export as iCalendar file.
void edit_copy()
copy the current appointment(s) to the clipboard
void newTodo()
create new todo
Incidence * selectedIncidence()
Return a pointer to the incidence selected in the current view.
void configChanged()
when change is made to options dialog, the topwidget will catch this and emit this signal which notif...
void changeNavStringPrev(const TQString &)
Emitted when the unit of navigation changes.
void readOnlyChanged(bool)
Emitted when state of read-only flag changes.
void closeCalendar()
Close calendar.
void setModified(bool modified=true)
set the state of calendar.
void archiveCalendar()
Archive old events of calendar.
void appointment_show()
pop up a dialog to show an existing appointment.
Incidence * currentSelection()
currentSelection() returns a pointer to the incidence selected in the current view
void goPrevious()
Move to the previous date(s) in the current view.
void goDate(const TQDate &date)
Move the current view date to the specified date.
void categoriesChanged()
Emitted when the categories were updated, and thus the categories editor dialog needs to reload the l...
void closingDown()
emitted when the topwidget is closing down, so that any attached child windows can also close.
void todoSelected(bool)
Emitted, when a todoitem is selected or deselected.
bool saveCalendar(const TQString &filename)
Save calendar data to file.
This class controls date navigation.
Definition: datenavigator.h:37
ExportWebDialog is a class that provides the dialog and functions to export a calendar as web page.
void setEnabled(bool enable)
void setEndOffset(const Duration &)
void setStartOffset(const Duration &)
void setType(Type type)
void setCompletedTimeSpan(int timespan)
TQStringList categoryList() const
TQString name() const
void setCategoryList(const TQStringList &)
int criteria() const
bool filterIncidence(Incidence *) const
void setCriteria(int)
void setEmailList(const TQStringList &)
int completedTimeSpan() const
bool load(const TQString &fileName, CalFormat *format=0)
void setDialogParentWidget(TQWidget *parent)
TQWidget * dialogParentWidget()
Incidence * dissociateOccurrence(Incidence *incidence, TQDate date, bool single=true)
void setTimeZoneId(const TQString &timeZoneId)
virtual void setTimeZoneIdViewOnly(const TQString &timeZoneId)=0
virtual Incidence::List rawIncidences()
void registerObserver(Observer *observer)
void setFilter(CalFilter *filter)
void unregisterObserver(Observer *observer)
CalFilter * filter()
virtual bool endChange(Incidence *incidence)
TQString timeZoneId() const
virtual Journal::List journals(JournalSortField sortField=JournalSortUnsorted, SortDirection sortDirection=SortDirectionAscending)
virtual Todo::List rawTodos(TodoSortField sortField=TodoSortUnsorted, SortDirection sortDirection=SortDirectionAscending)=0
virtual void close()=0
Incidence * incidence(const TQString &uid)
bool copyIncidences(const Incidence::List &incidences)
Incidence::List pasteIncidences(const TQDate &newDate=TQDate(), const TQTime *newTime=0)
void setDtEnd(const TQDateTime &dtEnd)
void setSaveFormat(CalFormat *)
void setTimeZone(const TQString &id, bool utc)
bool fromString(Calendar *calendar, const TQString &)
TQString createScheduleMessage(IncidenceBase *e, Scheduler::Method m)
void setOrganizer(const Person &o)
int attendeeCount() const
void registerObserver(Observer *)
bool doesFloat() const
TQString uid() const
Attendee * attendeeByMails(const TQStringList &, const TQString &email=TQString()) const
const Attendee::List & attendees() const
virtual TQDateTime dtStart() const
bool isReadOnly() const
void setReadOnly(bool readonly)
virtual TQDateTime dtEnd() const
const Alarm::List & alarms() const
void setSummary(const TQString &summary)
Alarm * newAlarm()
void setRelatedTo(Incidence *relatedTo)
TQString description() const
Incidence * relatedTo() const
void setDescription(const TQString &description)
void setRelatedToUid(const TQString &)
bool doesRecur() const
virtual Incidence * clone()=0
virtual void setDtStart(const TQDateTime &dtStart)
Incidence::List relations() const
TQString summary() const
Recurrence * recurrence() const
Journal * clone()
TQDateTime endDateTime() const
void setEndDateTime(const TQDateTime &endDateTime)
TQDate startDate() const
TQDateTime startDateTime() const
void setEndDate(const TQDate &endDate)
TQDateTime getNextDateTime(const TQDateTime &preDateTime) const
bool isCompleted() const
void setDtDue(const TQDateTime &dtDue, bool first=false)
TQDateTime dtDue(bool first=false) const
void setHasDueDate(bool hasDueDate)
KOAgendaView is the agenda-like view used to display events in a single one or multi-day view.
Definition: koagendaview.h:109
bool selectedIsSingleCell()
returns if only a single cell is selected, or a range of cells
TQDateTime selectionEnd()
end-datetime of selection
Definition: koagendaview.h:143
TQDateTime selectionStart()
start-datetime of selection
Definition: koagendaview.h:141
bool selectedIsAllDay()
returns true if selection is for whole day
Definition: koagendaview.h:145
This class manages the dialogs used by the calendar view.
KOJournalEditor * getJournalEditor()
Get an editor dialog for a Journal.
KOIncidenceEditor * getEditor(Incidence *)
Get the appropriate editor for the given incidence.
KOEventEditor * getEventEditor()
Get an editor dialog for an Event.
KOTodoEditor * getTodoEditor()
Get an editor dialog for a Todo.
This class provides a dialog for editing an event.
Definition: koeventeditor.h:49
void setDates(const TQDateTime &from, const TQDateTime &to, bool allDay)
Set widgets to the given date/time values.
void setTexts(const TQString &summary, const TQString &description=TQString())
Sets the given summary and description.
void newEvent()
Clear event win for new event.
Viewer dialog for events.
Viewer widget for events.
Definition: koeventviewer.h:41
void setIncidence(Incidence *incidence, const TQDate &date)
Show given incidence in viewer.
void setCalendar(Calendar *calendar)
Set the Calendar associated with this viewer.
void setDefaultText(const TQString &text)
Set the default text that is showed when there aren't a incidence to show.
This is the base class for the calendar component editors.
virtual void modified()
This incidence has been modified externally.
void setRecurringIncidence(Incidence *originalIncidence, Incidence *incAfterDissociation)
This should be called when editing only one occurrence of a recurring incidence, before showing the e...
void addAttendees(const TQStringList &attendees)
Adds attendees to the editor.
void addAttachments(const TQStringList &attachments, const TQStringList &mimeTypes=TQStringList(), bool inlineAttachment=false)
Adds attachments to the editor.
virtual void editIncidence(Incidence *, const TQDate &, Calendar *)=0
Edit an existing todo.
This class provides a dialog for editing a Journal.
void newJournal()
Clear editor for new Journal.
void setDate(const TQDate &date)
Set widgets to default values.
void setTexts(const TQString &summary, const TQString &description=TQString())
Sets the given summary and description.
The class KOMonthView represents the monthly view in KOrganizer.
Definition: komonthview.h:246
virtual TQDateTime selectionStart()
Returns the start of the selection, or an invalid TQDateTime if there is no selection or the view doe...
This class provides a dialog for editing a Todo.
Definition: kotodoeditor.h:38
void setTexts(const TQString &summary, const TQString &description=TQString())
Sets the given summary and description.
void setDates(const TQDateTime &due, bool allDay=true, Todo *relatedTodo=0)
Set widgets to default values.
void newTodo()
Edit new todo.
This class provides a multi-column list view of todo events.
Definition: kotodoview.h:114
Incidence::List selectedIncidences()
Definition: kotodoview.cpp:662
This class manages the views of the calendar.
Definition: koviewmanager.h:53
AgendaMode agendaMode() const
If the agenda view is selected it returns the current range mode: week, work week,...
void showView(KOrg::BaseView *)
changes the view to be the currently selected view
Base class for single/multi agenda views.
Definition: agendaview.h:28
This class provides an interface for all views being displayed within the main calendar view.
Definition: baseview.h:60
virtual void flushView()
Write all unsaved data back to calendar store.
Definition: baseview.h:186
virtual bool eventDurationHint(TQDateTime &, TQDateTime &, bool &)
Set the default start/end date/time for new events.
Definition: baseview.h:207
virtual TQDateTime selectionStart()
Returns the start of the selection, or an invalid TQDateTime if there is no selection or the view doe...
Definition: baseview.h:125
virtual void changeIncidenceDisplay(Incidence *, int)=0
Updates the current display to reflect the changes to one particular incidence.
virtual void updateView()=0
Updates the current display to reflect changes that may have happened in the calendar since the last ...
virtual void clearSelection()
Clear selection.
Definition: baseview.h:202
virtual int currentDateCount()=0
Return number of currently shown dates.
TQString subResourceCalendar() const
Return subResourceCalendar of this view.
Definition: baseview.h:105
virtual DateList selectedIncidenceDates()=0
virtual bool isEventView()
Return if this view is a view for displaying events.
Definition: baseview.h:144
virtual Incidence::List selectedIncidences()=0
virtual bool supportsDateNavigation() const
Returns true if the view supports navigation through the date navigator ( selecting a date range,...
Definition: baseview.h:149
ResourceCalendar * resourceCalendar()
Return resourceCalendar of this view.
Definition: baseview.h:100
interface for main calendar view widget
bool view(TQWidget *parent, Attachment *attachment)