korganizer

koeventeditor.cpp
1 /*
2  This file is part of KOrganizer.
3 
4  Copyright (c) 2001, 2002, 2003 Cornelius Schumacher <schumacher@kde.org>
5  Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 
21  As a special exception, permission is given to link this program
22  with any edition of TQt, and distribute the resulting executable,
23  without including the source code for TQt in the source distribution.
24 */
25 
26 #include <tqtooltip.h>
27 #include <tqframe.h>
28 #include <tqpixmap.h>
29 #include <tqlayout.h>
30 #include <tqwidgetstack.h>
31 #include <tqwhatsthis.h>
32 
33 #include <kiconloader.h>
34 #include <kdebug.h>
35 #include <tdelocale.h>
36 #include <tdemessagebox.h>
38 #include <libkcal/resourcecalendar.h>
39 #include <libkcal/incidenceformatter.h>
40 #include <libkcal/calendarlocal.h>
41 
42 #include "koprefs.h"
43 #include "koeditorgeneralevent.h"
44 #include "koeditorrecurrence.h"
45 #include "koeditordetails.h"
46 #include "koeditorfreebusy.h"
47 #include "kogroupware.h"
48 #include "kodialogmanager.h"
49 #include "incidencechanger.h"
50 
51 #include "koeventeditor.h"
52 
53 KOEventEditor::KOEventEditor( Calendar *calendar, TQWidget *parent )
54  : KOIncidenceEditor( TQString(), calendar, parent ),
55  mEvent( 0 ), mCalendar( 0 ), mGeneral( 0 ), mRecurrence( 0 ), mFreeBusy( 0 )
56 {
57 }
58 
59 KOEventEditor::~KOEventEditor()
60 {
61  if ( !mIsCounter )
62  emit dialogClose( mEvent );
63 }
64 
66 {
67  setupGeneral();
68  setupRecurrence();
69  setupFreeBusy();
70  setupDesignerTabs( "event" );
71 
72  // Propagate date time settings to recurrence tab
73  connect( mGeneral, TQ_SIGNAL( dateTimesChanged( const TQDateTime &, const TQDateTime & ) ),
74  mRecurrence, TQ_SLOT( setDateTimes( const TQDateTime &, const TQDateTime &) ) );
75  connect( mGeneral, TQ_SIGNAL( dateTimeStrChanged( const TQString & ) ),
76  mRecurrence, TQ_SLOT( setDateTimeStr( const TQString & ) ) );
77  connect( mFreeBusy, TQ_SIGNAL( dateTimesChanged( const TQDateTime &, const TQDateTime & ) ),
78  mRecurrence, TQ_SLOT( setDateTimes( const TQDateTime &, const TQDateTime & ) ) );
79 
80  // Propagate date time settings to gantt tab and back
81  connect( mGeneral, TQ_SIGNAL( dateTimesChanged( const TQDateTime &, const TQDateTime & ) ),
82  mFreeBusy, TQ_SLOT( slotUpdateGanttView( const TQDateTime &, const TQDateTime & ) ) );
83  connect( mFreeBusy, TQ_SIGNAL( dateTimesChanged( const TQDateTime &, const TQDateTime & ) ),
84  mGeneral, TQ_SLOT( setDateTimes( const TQDateTime &, const TQDateTime & ) ) );
85 
86  connect( mGeneral, TQ_SIGNAL( focusReceivedSignal() ),
87  TQ_SIGNAL( focusReceivedSignal() ) );
88 
89  connect( mGeneral, TQ_SIGNAL( openCategoryDialog() ),
90  TQ_SIGNAL( editCategories() ) );
91  connect( this, TQ_SIGNAL( updateCategoryConfig() ),
92  mGeneral, TQ_SIGNAL( updateCategoryConfig() ) );
93 
94  connect( mFreeBusy, TQ_SIGNAL(updateAttendeeSummary(int)),
95  mGeneral, TQ_SLOT(updateAttendeeSummary(int)) );
96 
97  connect( mGeneral, TQ_SIGNAL(editRecurrence()),
98  mRecurrenceDialog, TQ_SLOT(show()) );
99  connect( mRecurrenceDialog, TQ_SIGNAL(okClicked()),
100  TQ_SLOT(updateRecurrenceSummary()) );
101 
102  connect( mGeneral, TQ_SIGNAL(acceptInvitation()),
103  mFreeBusy, TQ_SLOT(acceptForMe()) );
104  connect( mGeneral, TQ_SIGNAL(declineInvitation()),
105  mFreeBusy, TQ_SLOT(declineForMe()) );
106 }
107 
108 void KOEventEditor::reload()
109 {
110  kdDebug(5850) << "KOEventEditor::reload()" << endl;
111 
112  if ( mEvent ) {
113  readEvent( mEvent, mCalendar, TQDate() );
114  }
115 }
116 
117 void KOEventEditor::setupGeneral()
118 {
119  mGeneral = new KOEditorGeneralEvent( this );
120 
121  if( KOPrefs::instance()->mCompactDialogs ) {
122  TQFrame *topFrame = addPage(i18n("General"));
123  TQWhatsThis::add( topFrame,
124  i18n("The General tab allows you to set the most common "
125  "options for the event.") );
126 
127  TQBoxLayout *topLayout = new TQVBoxLayout(topFrame);
128  topLayout->setSpacing(spacingHint());
129 
130  mGeneral->initHeader( topFrame, topLayout );
131  mGeneral->initTime(topFrame,topLayout);
132 
133  topLayout->addStretch( 1 );
134 
135  TQFrame *topFrame2 = addPage(i18n("Details"));
136 
137  TQBoxLayout *topLayout2 = new TQVBoxLayout(topFrame2);
138  topLayout2->setSpacing(spacingHint());
139 
140  mGeneral->initClass(topFrame2,topLayout2);
141  mGeneral->initSecrecy( topFrame2, topLayout2 );
142  mGeneral->initDescription(topFrame2,topLayout2);
143  } else {
144  TQFrame *topFrame = addPage(i18n("&General"));
145  TQWhatsThis::add( topFrame,
146  i18n("The General tab allows you to set the most common "
147  "options for the event.") );
148 
149  TQBoxLayout *topLayout = new TQVBoxLayout(topFrame);
150  topLayout->setSpacing(spacingHint());
151 
152  mGeneral->initInvitationBar( topFrame, topLayout );
153  mGeneral->initHeader( topFrame, topLayout );
154  mGeneral->initTime(topFrame,topLayout);
155  mGeneral->initDescription(topFrame,topLayout);
156  mGeneral->initAttachments(topFrame,topLayout);
157  connect( mGeneral, TQ_SIGNAL( openURL( const KURL& ) ),
158  this, TQ_SLOT( openURL( const KURL& ) ) );
159  connect( this, TQ_SIGNAL( signalAddAttachments( const TQStringList&, const TQStringList&, bool ) ),
160  mGeneral, TQ_SLOT( addAttachments( const TQStringList&, const TQStringList&, bool ) ) );
161  }
162 
163  mGeneral->finishSetup();
164 }
165 
167 {
168  // Play dumb, just reload the event. This dialog has become so complicated
169  // that there is no point in trying to be smart here...
170  reload();
171 }
172 
173 void KOEventEditor::setupRecurrence()
174 {
175  mRecurrenceDialog = new KOEditorRecurrenceDialog( this );
176  mRecurrenceDialog->hide();
177  mRecurrence = mRecurrenceDialog->editor();
178 }
179 
180 void KOEventEditor::setupFreeBusy()
181 {
182  TQFrame *freeBusyPage = addPage( i18n("&Attendees") );
183  TQWhatsThis::add( freeBusyPage,
184  i18n("The Free/Busy tab allows you to see whether "
185  "other attendees are free or busy during your event.") );
186 
187  TQBoxLayout *topLayout = new TQVBoxLayout( freeBusyPage );
188 
189  mAttendeeEditor = mFreeBusy = new KOEditorFreeBusy( spacingHint(), freeBusyPage );
190  topLayout->addWidget( mFreeBusy );
191 }
192 
194  const TQDate &date,
195  Calendar *calendar )
196 {
197  Event*event = dynamic_cast<Event*>(incidence);
198  if ( event ) {
199  init();
200 
201  mEvent = event;
202  mCalendar = calendar;
203 
204  const TQDate &dt = mRecurIncidence && date.isValid() ? date : incidence->dtStart().date();
205  readEvent( mEvent, mCalendar, dt );
206  }
207 
208  setCaption( i18n("Edit Event") );
209 }
210 
212 {
213  init();
214  mEvent = 0;
215  loadDefaults();
216  setCaption( i18n("New Event") );
217 }
218 
219 void KOEventEditor::setDates( const TQDateTime &from, const TQDateTime &to, bool allDay )
220 {
221  mGeneral->setDefaults( from, to, allDay );
222  mRecurrence->setDefaults( from, to, allDay );
223  if( mFreeBusy ) {
224  if ( allDay )
225  mFreeBusy->setDateTimes( from, to.addDays( 1 ) );
226  else
227  mFreeBusy->setDateTimes( from, to );
228  }
229 }
230 
231 void KOEventEditor::setTexts( const TQString &summary, const TQString &description )
232 {
233  if ( description.isEmpty() && summary.contains("\n") ) {
234  mGeneral->setDescription( summary );
235  int pos = summary.find( "\n" );
236  mGeneral->setSummary( summary.left( pos ) );
237  } else {
238  mGeneral->setSummary( summary );
239  mGeneral->setDescription( description );
240  }
241 }
242 
243 void KOEventEditor::loadDefaults()
244 {
245  TQDateTime from( TQDate::currentDate(), KOPrefs::instance()->mStartTime.time() );
246  int addSecs = ( KOPrefs::instance()->mDefaultDuration.time().hour()*3600 ) +
247  ( KOPrefs::instance()->mDefaultDuration.time().minute()*60 );
248  TQDateTime to( from.addSecs( addSecs ) );
249 
250  setDates( from, to, false );
251 }
252 
254 {
255  kdDebug(5850) << "KOEventEditor::processInput(); event is " << mEvent << endl;
256 
257  if ( !validateInput() || !mChanger ) {
258  kdDebug(5850) << " mChanger is " << mChanger << endl;
259  return false;
260  }
261 
262  TQGuardedPtr<KOEditorFreeBusy> freeBusy( mFreeBusy );
263 
264  if ( mEvent ) {
265  bool rc = true;
266  Event *oldEvent = mEvent->clone();
267  Event *event = mEvent->clone();
268 
269  kdDebug(5850) << "KOEventEditor::processInput() write event." << endl;
270  writeEvent( event );
271  kdDebug(5850) << "KOEventEditor::processInput() event written." << endl;
272 
273  if( *event == *mEvent ) {
274  // Don't do anything
275  kdDebug(5850) << "Event not changed" << endl;
276  if ( mIsCounter ) {
277  KMessageBox::information( this, i18n("You didn't change the event, thus no counter proposal has been sent to the organizer."), i18n("No changes") );
278  }
279  } else {
280  kdDebug(5850) << "Event changed" << endl;
281  //IncidenceChanger::assignIncidence( mEvent, event );
282  writeEvent( mEvent );
283  if ( mIsCounter ) {
284  KOGroupware::instance()->sendCounterProposal( mCalendar, oldEvent, mEvent );
285  // add dummy event at the position of the counter proposal
286  Event *event = mEvent->clone();
287  event->clearAttendees();
288  event->setSummary( i18n("My counter proposal for: %1").arg( mEvent->summary() ) );
289  mChanger->addIncidence( event, mResource, mSubResource, this );
290  } else {
291  if ( mRecurIncidence && mRecurIncidenceAfterDissoc ) {
292  mChanger->addIncidence( mEvent, mResource, mSubResource, this );
293 
294  mChanger->changeIncidence( mRecurIncidence, mRecurIncidenceAfterDissoc,
295  KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE, this );
296 
297  } else {
298  mChanger->changeIncidence( oldEvent, mEvent, KOGlobals::NOTHING_MODIFIED, this );
299  }
300  }
301  }
302  delete event;
303  delete oldEvent;
304  return rc;
305  } else {
306  mEvent = new Event;
307  mEvent->setOrganizer( Person( KOPrefs::instance()->fullName(),
308  KOPrefs::instance()->email() ) );
309  writeEvent( mEvent );
310  // NOTE: triggered by addIncidence, the kolab resource might open a non-modal dialog (parent is not available in the resource) to select a resource folder. Thus the user can close this dialog before addIncidence() returns.
311  if ( !mChanger->addIncidence( mEvent, mResource, mSubResource, this ) ) {
312  delete mEvent;
313  mEvent = 0;
314  return false;
315  }
316  }
317  // if "this" was deleted, freeBusy is 0 (being a guardedptr)
318  if ( freeBusy ) {
319  freeBusy->cancelReload();
320  }
321 
322  return true;
323 }
324 
325 void KOEventEditor::processCancel()
326 {
327  kdDebug(5850) << "KOEventEditor::processCancel()" << endl;
328 
329  if ( mFreeBusy ) mFreeBusy->cancelReload();
330 
331  if ( mRecurIncidence && mRecurIncidenceAfterDissoc ) {
332  *mRecurIncidenceAfterDissoc = *mRecurIncidence;
333  }
334 
335 }
336 
337 void KOEventEditor::deleteEvent()
338 {
339  kdDebug(5850) << "Delete event" << endl;
340 
341  if ( mEvent )
342  emit deleteIncidenceSignal( mEvent );
343  emit dialogClose( mEvent );
344  reject();
345 }
346 
347 void KOEventEditor::readEvent( Event *event, Calendar *calendar, const TQDate &date, bool tmpl )
348 {
349  mGeneral->readEvent( event, calendar, date, tmpl );
350  mRecurrence->readIncidence( event );
351 
352  if ( mFreeBusy ) {
353  mFreeBusy->readEvent( event );
354  mFreeBusy->triggerReload();
355  }
356 
357  createEmbeddedURLPages( event );
358  readDesignerFields( event );
359 
360  if ( mIsCounter )
361  mGeneral->invitationBar()->hide();
362 }
363 
365 {
366  mGeneral->writeEvent( event );
367  if ( mFreeBusy )
368  mFreeBusy->writeEvent( event );
369 
370  cancelRemovedAttendees( event );
371 
372  mRecurrence->writeIncidence( event );
373 
374  writeDesignerFields( event );
375 }
376 
378 {
379  if ( !mGeneral->validateInput() ||
380  !mDetails->validateInput() ||
381  !mRecurrence->validateInput() ) {
382  kdDebug(5850) << "ValidateInput returns false" << endl;
383  return false;
384  } else {
385  return true;
386  }
387 }
388 
389 int KOEventEditor::msgItemDelete()
390 {
391  return KMessageBox::warningContinueCancel(this,
392  i18n("This item will be permanently deleted."),
393  i18n("KOrganizer Confirmation"),KGuiItem(i18n("Delete"),"edit-delete"));
394 }
395 
396 void KOEventEditor::loadTemplate( /*const*/ CalendarLocal& cal )
397 {
398  const Event::List events = cal.events();
399  if ( events.count() == 0 ) {
400  KMessageBox::error( this,
401  i18n("Template does not contain a valid event.") );
402  } else {
403  kdDebug(5850) << "KOEventEditor::slotLoadTemplate(): readTemplate" << endl;
404  readEvent( events.first(), 0, TQDate(), true );
405  }
406 }
407 
408 TQStringList& KOEventEditor::templates() const
409 {
410  return KOPrefs::instance()->mEventTemplates;
411 }
412 
413 void KOEventEditor::slotSaveTemplate( const TQString &templateName )
414 {
415  kdDebug(5006) << "SlotSaveTemplate" << endl;
416  Event *event = new Event;
417  writeEvent( event );
418  saveAsTemplate( event, templateName );
419 }
420 
421 TQObject *KOEventEditor::typeAheadReceiver() const
422 {
423  return mGeneral->typeAheadReceiver();
424 }
425 
426 void KOEventEditor::updateRecurrenceSummary()
427 {
428  Event *ev = new Event();
429  writeEvent( ev );
430  mGeneral->updateRecurrenceSummary( ev );
431  delete ev;
432 }
433 
434 void KOEventEditor::selectInvitationCounterProposal(bool enable)
435 {
436  KOIncidenceEditor::selectInvitationCounterProposal( enable );
437  if ( enable )
438  mGeneral->invitationBar()->hide();
439 }
440 
441 #include "koeventeditor.moc"
virtual Event::List events(EventSortField sortField=EventSortUnsorted, SortDirection sortDirection=SortDirectionAscending)
Event * clone()
void setOrganizer(const Person &o)
virtual TQDateTime dtStart() const
TQString summary() const
bool validateInput()
Check if the input is valid.
void modified()
This event has been modified externally.
void setDates(const TQDateTime &from, const TQDateTime &to, bool allDay)
Set widgets to the given date/time values.
void writeEvent(Event *)
Write event settings to event object.
void init()
Initialize editor.
void setTexts(const TQString &summary, const TQString &description=TQString())
Sets the given summary and description.
bool processInput()
Process user input and create or update event.
void readEvent(Event *event, Calendar *calendar, const TQDate &date, bool tmpl=false)
Read event object and setup widgets accordingly.
KOEventEditor(Calendar *calendar, TQWidget *parent)
Construct new event editor.
void newEvent()
Clear event win for new event.
void editIncidence(Incidence *incidence, const TQDate &date, Calendar *calendar)
Edit an existing event.
This is the base class for the calendar component editors.
void addAttachments(const TQStringList &attachments, const TQStringList &mimeTypes=TQStringList(), bool inlineAttachment=false)
Adds attachments to the editor.