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 <kstandarddirs.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 
113 using namespace KOrg;
114 
115 CalendarView::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 
291 CalendarView::~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 
303 void 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 
325 void 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 
346 Calendar *CalendarView::calendar()
347 {
348  if ( mCalendar ) return mCalendar;
349  else return CalendarNull::self();
350 }
351 
352 TQPair<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 
365 KOIncidenceEditor *CalendarView::editorDialog( Incidence *incidence ) const
366 {
367  if (mDialogList.find(incidence) != mDialogList.end ())
368  return mDialogList[incidence];
369  else return 0;
370 }
371 
372 TQDate 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 
409 TQDate CalendarView::startDate()
410 {
411  DateList dates = mDateNavigator->selectedDates();
412 
413  return dates.first();
414 }
415 
416 TQDate CalendarView::endDate()
417 {
418  DateList dates = mDateNavigator->selectedDates();
419 
420  return dates.last();
421 }
422 
423 
424 bool 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 
496 bool 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 
605 void 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 
642 void 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 
668 void CalendarView::goDate( const TQDate &date )
669 {
670  mDateNavigator->selectDate( date );
671 }
672 
673 void 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 
706 void 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 
746 void CalendarView::incidenceAdded( Incidence *incidence )
747 {
748  setModified( true );
749  history()->recordAdd( incidence );
750  changeIncidenceDisplay( incidence, KOGlobals::INCIDENCEADDED );
751  updateUnmanagedViews();
752  checkForFilteredChange( incidence );
753 }
754 
755 void 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 
820 void 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 
833 void CalendarView::incidenceDeleted( Incidence *incidence )
834 {
835  changeIncidenceDisplay( incidence, KOGlobals::INCIDENCEDELETED );
836  updateUnmanagedViews();
837 }
838 
839 void 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 
852 void CalendarView::startMultiModify( const TQString &text )
853 {
854  history()->startMultiModify( text );
855 }
856 
857 void CalendarView::endMultiModify()
858 {
859  history()->endMultiModify();
860 }
861 
862 
863 void CalendarView::changeIncidenceDisplay( Incidence *incidence, int action )
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 
880 void CalendarView::updateView(const TQDate &start, const TQDate &end)
881 {
882  mTodoList->updateView();
883  mViewManager->updateView(start, end);
884  mDateNavigatorContainer->updateView();
885 }
886 
887 void 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 
895 void CalendarView::updateUnmanagedViews()
896 {
897  mDateNavigatorContainer->updateDayMatrix();
898  updateView();
899 }
900 
901 int 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 
986 Incidence* 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 
1118 void 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 
1133 KOEventEditor *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 
1167 void CalendarView::newEvent( ResourceCalendar *res, const TQString &subRes )
1168 {
1169  kdDebug(5850) << "CalendarView::newEvent()" << endl;
1170  newEvent( res, subRes, TQDateTime(), TQDateTime() );
1171 }
1172 
1173 void 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 
1180 void CalendarView::newEvent( ResourceCalendar *res, const TQString &subRes,
1181  const TQDateTime &startDt )
1182 {
1183  newEvent( res, subRes, startDt, TQDateTime() );
1184 }
1185 
1186 void 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 
1195 void 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 
1209 void 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 
1240 void 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 
1258 void 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 
1269 void 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 
1283 void CalendarView::newJournal( ResourceCalendar *res, const TQString &subRes )
1284 {
1285  kdDebug(5850) << "CalendarView::newJournal()" << endl;
1286  newJournal( res, subRes, TQString(), TQDate() );
1287 }
1288 
1289 void CalendarView::newJournal( ResourceCalendar *res, const TQString &subRes,
1290  const TQDate &date)
1291 {
1292  newJournal( res, subRes, TQString(), date );
1293 }
1294 
1295 void 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 
1317 void CalendarView::newSubTodo(Todo *parentEvent)
1318 {
1319  KOTodoEditor *todoEditor = mDialogManager->getTodoEditor();
1320  connectIncidenceEditor( todoEditor );
1321  todoEditor->newTodo();
1322  todoEditor->setDates( TQDateTime(), false, parentEvent );
1323  todoEditor->show();
1324 }
1325 
1326 bool 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 
1369 void CalendarView::todo_unsub()
1370 {
1371  Todo *anTodo = selectedTodo();
1372  if( incidence_unsub ( anTodo ) ) {
1373  updateView();
1374  }
1375 }
1376 
1377 bool 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 
1430 bool 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 
1441 void 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 
1490 void 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 
1524 void 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 
1558 void 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 
1594 void CalendarView::schedule_request(Incidence *incidence)
1595 {
1596  schedule(Scheduler::Request,incidence);
1597 }
1598 
1599 void CalendarView::schedule_refresh(Incidence *incidence)
1600 {
1601  schedule(Scheduler::Refresh,incidence);
1602 }
1603 
1604 void CalendarView::schedule_cancel(Incidence *incidence)
1605 {
1606  schedule(Scheduler::Cancel,incidence);
1607 }
1608 
1609 void CalendarView::schedule_add(Incidence *incidence)
1610 {
1611  schedule(Scheduler::Add,incidence);
1612 }
1613 
1614 void CalendarView::schedule_reply(Incidence *incidence)
1615 {
1616  schedule(Scheduler::Reply,incidence);
1617 }
1618 
1619 void CalendarView::schedule_counter(Incidence *incidence)
1620 {
1621  schedule(Scheduler::Counter,incidence);
1622 }
1623 
1624 void CalendarView::schedule_declinecounter(Incidence *incidence)
1625 {
1626  schedule(Scheduler::Declinecounter,incidence);
1627 }
1628 
1629 void 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 
1670 void 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 
1698 void CalendarView::uploadFreeBusy()
1699 {
1700  KOGroupware::instance()->freeBusyManager()->publishFreeBusy();
1701 }
1702 
1703 void 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 
1743 void CalendarView::openAddressbook()
1744 {
1745  KRun::runCommand("kaddressbook");
1746 }
1747 
1748 void 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 
1761 void 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 
1857 void 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 
1879 void CalendarView::processMainViewSelection( Incidence *incidence, const TQDate &date )
1880 {
1881  if ( incidence ) mTodoList->clearSelection();
1882  processIncidenceSelection( incidence, date );
1883 }
1884 
1885 void CalendarView::processTodoListSelection( Incidence *incidence, const TQDate &date )
1886 {
1887  if ( incidence && mViewManager->currentView() ) {
1888  mViewManager->currentView()->clearSelection();
1889  }
1890  processIncidenceSelection( incidence, date );
1891 }
1892 
1893 void 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 
1947 void 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 
1959 void 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 
1999 void CalendarView::filterActivated( int filterNo )
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 
2048 void CalendarView::showIntro()
2049 {
2050  kdDebug(5850) << "To be implemented." << endl;
2051 }
2052 
2053 void CalendarView::showDateNavigator( bool show )
2054 {
2055  if( show )
2056  mDateNavigatorContainer->show();
2057  else
2058  mDateNavigatorContainer->hide();
2059 }
2060 
2061 void CalendarView::showTodoView( bool show )
2062 {
2063  if( show )
2064  mTodoList->show();
2065  else
2066  mTodoList->hide();
2067 }
2068 
2069 void CalendarView::showEventViewer( bool show )
2070 {
2071  if( show )
2072  mEventViewer->show();
2073  else
2074  mEventViewer->hide();
2075 }
2076 
2077 
2078 void CalendarView::addView(KOrg::BaseView *view)
2079 {
2080  mViewManager->addView(view);
2081 }
2082 
2084 {
2085  mViewManager->showView(view);
2086 }
2087 
2088 void CalendarView::addExtension( CalendarViewExtension::Factory *factory )
2089 {
2090  CalendarViewExtension *extension = factory->create( mLeftSplitter );
2091 
2092  mExtensions.append( extension );
2093 }
2094 
2095 void CalendarView::toggleExpand()
2096 {
2097  showLeftFrame( mLeftFrame->isHidden() );
2098 }
2099 
2100 void 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 
2111 void CalendarView::calendarModified( bool modified, Calendar * )
2112 {
2113  setModified( modified );
2114 }
2115 
2116 Todo *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 
2133 void 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 
2156 void CalendarView::showIncidence()
2157 {
2158  showIncidence( selectedIncidence(), activeIncidenceDate() );
2159 }
2160 
2161 void CalendarView::editIncidence()
2162 {
2163  editIncidence( selectedIncidence(), activeIncidenceDate() );
2164 }
2165 
2166 bool CalendarView::editIncidence( const TQString &uid )
2167 {
2168  return editIncidence( mCalendar->incidence( uid ), TQDate() );
2169 }
2170 
2171 bool CalendarView::editIncidence( const TQString &uid, const TQDate &date )
2172 {
2173  return editIncidence( mCalendar->incidence( uid ), date );
2174 }
2175 
2176 void 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 
2196 void 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 
2207 bool 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 
2313 void 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 
2357 void 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 
2473 void CalendarView::connectIncidenceEditor( KOIncidenceEditor *editor )
2474 {
2475  connect( this, TQ_SIGNAL( newIncidenceChanger( IncidenceChangerBase* ) ),
2476  editor, TQ_SLOT( setIncidenceChanger( IncidenceChangerBase* ) ) );
2477  editor->setIncidenceChanger( mChanger );
2478 }
2479 
2480 bool 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 
2511 void 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 
2540 void 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 
2550 void CalendarView::editCanceled( Incidence *incidence )
2551 {
2552  mCalendar->endChange( incidence );
2553 }
2554 
2555 void 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 
2576 void 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 
2620 void 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 
2668 void 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 
2785 void 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 
2796 void 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 kapp 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
const Attendee::List & attendees() const
TQString uid() const
Attendee * attendeeByMails(const TQStringList &, const TQString &email=TQString()) const
virtual TQDateTime dtStart() const
bool isReadOnly() const
void setReadOnly(bool readonly)
virtual Incidence * clone()=0
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 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.
ResourceCalendar * resourceCalendar()
Return resourceCalendar of this view.
Definition: baseview.h:100
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
interface for main calendar view widget
bool view(TQWidget *parent, Attachment *attachment)