koeventeditor.cpp
00001 /* 00002 This file is part of KOrganizer. 00003 00004 Copyright (c) 2001, 2002, 2003 Cornelius Schumacher <schumacher@kde.org> 00005 Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com> 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 2 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program; if not, write to the Free Software 00019 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00020 00021 As a special exception, permission is given to link this program 00022 with any edition of TQt, and distribute the resulting executable, 00023 without including the source code for TQt in the source distribution. 00024 */ 00025 00026 #include <tqtooltip.h> 00027 #include <tqframe.h> 00028 #include <tqpixmap.h> 00029 #include <tqlayout.h> 00030 #include <tqwidgetstack.h> 00031 #include <tqwhatsthis.h> 00032 00033 #include <kiconloader.h> 00034 #include <kdebug.h> 00035 #include <klocale.h> 00036 #include <kmessagebox.h> 00037 #include <libkcal/calendarresources.h> 00038 #include <libkcal/resourcecalendar.h> 00039 #include <libkcal/incidenceformatter.h> 00040 #include <libkcal/calendarlocal.h> 00041 00042 #include "koprefs.h" 00043 #include "koeditorgeneralevent.h" 00044 #include "koeditorrecurrence.h" 00045 #include "koeditordetails.h" 00046 #include "koeditorfreebusy.h" 00047 #include "kogroupware.h" 00048 #include "kodialogmanager.h" 00049 #include "incidencechanger.h" 00050 00051 #include "koeventeditor.h" 00052 00053 KOEventEditor::KOEventEditor( Calendar *calendar, TQWidget *parent ) 00054 : KOIncidenceEditor( TQString(), calendar, parent ), 00055 mEvent( 0 ), mCalendar( 0 ), mGeneral( 0 ), mRecurrence( 0 ), mFreeBusy( 0 ) 00056 { 00057 } 00058 00059 KOEventEditor::~KOEventEditor() 00060 { 00061 if ( !mIsCounter ) 00062 emit dialogClose( mEvent ); 00063 } 00064 00065 void KOEventEditor::init() 00066 { 00067 setupGeneral(); 00068 setupRecurrence(); 00069 setupFreeBusy(); 00070 setupDesignerTabs( "event" ); 00071 00072 // Propagate date time settings to recurrence tab 00073 connect( mGeneral, TQT_SIGNAL( dateTimesChanged( const TQDateTime &, const TQDateTime & ) ), 00074 mRecurrence, TQT_SLOT( setDateTimes( const TQDateTime &, const TQDateTime &) ) ); 00075 connect( mGeneral, TQT_SIGNAL( dateTimeStrChanged( const TQString & ) ), 00076 mRecurrence, TQT_SLOT( setDateTimeStr( const TQString & ) ) ); 00077 connect( mFreeBusy, TQT_SIGNAL( dateTimesChanged( const TQDateTime &, const TQDateTime & ) ), 00078 mRecurrence, TQT_SLOT( setDateTimes( const TQDateTime &, const TQDateTime & ) ) ); 00079 00080 // Propagate date time settings to gantt tab and back 00081 connect( mGeneral, TQT_SIGNAL( dateTimesChanged( const TQDateTime &, const TQDateTime & ) ), 00082 mFreeBusy, TQT_SLOT( slotUpdateGanttView( const TQDateTime &, const TQDateTime & ) ) ); 00083 connect( mFreeBusy, TQT_SIGNAL( dateTimesChanged( const TQDateTime &, const TQDateTime & ) ), 00084 mGeneral, TQT_SLOT( setDateTimes( const TQDateTime &, const TQDateTime & ) ) ); 00085 00086 connect( mGeneral, TQT_SIGNAL( focusReceivedSignal() ), 00087 TQT_SIGNAL( focusReceivedSignal() ) ); 00088 00089 connect( mGeneral, TQT_SIGNAL( openCategoryDialog() ), 00090 TQT_SIGNAL( editCategories() ) ); 00091 connect( this, TQT_SIGNAL( updateCategoryConfig() ), 00092 mGeneral, TQT_SIGNAL( updateCategoryConfig() ) ); 00093 00094 connect( mFreeBusy, TQT_SIGNAL(updateAttendeeSummary(int)), 00095 mGeneral, TQT_SLOT(updateAttendeeSummary(int)) ); 00096 00097 connect( mGeneral, TQT_SIGNAL(editRecurrence()), 00098 mRecurrenceDialog, TQT_SLOT(show()) ); 00099 connect( mRecurrenceDialog, TQT_SIGNAL(okClicked()), 00100 TQT_SLOT(updateRecurrenceSummary()) ); 00101 00102 connect( mGeneral, TQT_SIGNAL(acceptInvitation()), 00103 mFreeBusy, TQT_SLOT(acceptForMe()) ); 00104 connect( mGeneral, TQT_SIGNAL(declineInvitation()), 00105 mFreeBusy, TQT_SLOT(declineForMe()) ); 00106 } 00107 00108 void KOEventEditor::reload() 00109 { 00110 kdDebug(5850) << "KOEventEditor::reload()" << endl; 00111 00112 if ( mEvent ) { 00113 readEvent( mEvent, mCalendar, TQDate() ); 00114 } 00115 } 00116 00117 void KOEventEditor::setupGeneral() 00118 { 00119 mGeneral = new KOEditorGeneralEvent( TQT_TQOBJECT(this) ); 00120 00121 if( KOPrefs::instance()->mCompactDialogs ) { 00122 TQFrame *topFrame = addPage(i18n("General")); 00123 TQWhatsThis::add( topFrame, 00124 i18n("The General tab allows you to set the most common " 00125 "options for the event.") ); 00126 00127 TQBoxLayout *topLayout = new TQVBoxLayout(topFrame); 00128 topLayout->setSpacing(spacingHint()); 00129 00130 mGeneral->initHeader( topFrame, topLayout ); 00131 mGeneral->initTime(topFrame,topLayout); 00132 00133 topLayout->addStretch( 1 ); 00134 00135 TQFrame *topFrame2 = addPage(i18n("Details")); 00136 00137 TQBoxLayout *topLayout2 = new TQVBoxLayout(topFrame2); 00138 topLayout2->setSpacing(spacingHint()); 00139 00140 mGeneral->initClass(topFrame2,topLayout2); 00141 mGeneral->initSecrecy( topFrame2, topLayout2 ); 00142 mGeneral->initDescription(topFrame2,topLayout2); 00143 } else { 00144 TQFrame *topFrame = addPage(i18n("&General")); 00145 TQWhatsThis::add( topFrame, 00146 i18n("The General tab allows you to set the most common " 00147 "options for the event.") ); 00148 00149 TQBoxLayout *topLayout = new TQVBoxLayout(topFrame); 00150 topLayout->setSpacing(spacingHint()); 00151 00152 mGeneral->initInvitationBar( topFrame, topLayout ); 00153 mGeneral->initHeader( topFrame, topLayout ); 00154 mGeneral->initTime(topFrame,topLayout); 00155 mGeneral->initDescription(topFrame,topLayout); 00156 mGeneral->initAttachments(topFrame,topLayout); 00157 connect( mGeneral, TQT_SIGNAL( openURL( const KURL& ) ), 00158 this, TQT_SLOT( openURL( const KURL& ) ) ); 00159 connect( this, TQT_SIGNAL( signalAddAttachments( const TQStringList&, const TQStringList&, bool ) ), 00160 mGeneral, TQT_SLOT( addAttachments( const TQStringList&, const TQStringList&, bool ) ) ); 00161 } 00162 00163 mGeneral->finishSetup(); 00164 } 00165 00166 void KOEventEditor::modified() 00167 { 00168 // Play dumb, just reload the event. This dialog has become so complicated 00169 // that there is no point in trying to be smart here... 00170 reload(); 00171 } 00172 00173 void KOEventEditor::setupRecurrence() 00174 { 00175 mRecurrenceDialog = new KOEditorRecurrenceDialog( this ); 00176 mRecurrenceDialog->hide(); 00177 mRecurrence = mRecurrenceDialog->editor(); 00178 } 00179 00180 void KOEventEditor::setupFreeBusy() 00181 { 00182 TQFrame *freeBusyPage = addPage( i18n("&Attendees") ); 00183 TQWhatsThis::add( freeBusyPage, 00184 i18n("The Free/Busy tab allows you to see whether " 00185 "other attendees are free or busy during your event.") ); 00186 00187 TQBoxLayout *topLayout = new TQVBoxLayout( freeBusyPage ); 00188 00189 mAttendeeEditor = mFreeBusy = new KOEditorFreeBusy( spacingHint(), freeBusyPage ); 00190 topLayout->addWidget( mFreeBusy ); 00191 } 00192 00193 void KOEventEditor::editIncidence( Incidence *incidence, 00194 const TQDate &date, 00195 Calendar *calendar ) 00196 { 00197 Event*event = dynamic_cast<Event*>(incidence); 00198 if ( event ) { 00199 init(); 00200 00201 mEvent = event; 00202 mCalendar = calendar; 00203 00204 const TQDate &dt = mRecurIncidence && date.isValid() ? date : incidence->dtStart().date(); 00205 readEvent( mEvent, mCalendar, dt ); 00206 } 00207 00208 setCaption( i18n("Edit Event") ); 00209 } 00210 00211 void KOEventEditor::newEvent() 00212 { 00213 init(); 00214 mEvent = 0; 00215 loadDefaults(); 00216 setCaption( i18n("New Event") ); 00217 } 00218 00219 void KOEventEditor::setDates( const TQDateTime &from, const TQDateTime &to, bool allDay ) 00220 { 00221 mGeneral->setDefaults( from, to, allDay ); 00222 mRecurrence->setDefaults( from, to, allDay ); 00223 if( mFreeBusy ) { 00224 if ( allDay ) 00225 mFreeBusy->setDateTimes( from, to.addDays( 1 ) ); 00226 else 00227 mFreeBusy->setDateTimes( from, to ); 00228 } 00229 } 00230 00231 void KOEventEditor::setTexts( const TQString &summary, const TQString &description ) 00232 { 00233 if ( description.isEmpty() && summary.contains("\n") ) { 00234 mGeneral->setDescription( summary ); 00235 int pos = summary.find( "\n" ); 00236 mGeneral->setSummary( summary.left( pos ) ); 00237 } else { 00238 mGeneral->setSummary( summary ); 00239 mGeneral->setDescription( description ); 00240 } 00241 } 00242 00243 void KOEventEditor::loadDefaults() 00244 { 00245 TQDateTime from( TQDate::currentDate(), KOPrefs::instance()->mStartTime.time() ); 00246 int addSecs = ( KOPrefs::instance()->mDefaultDuration.time().hour()*3600 ) + 00247 ( KOPrefs::instance()->mDefaultDuration.time().minute()*60 ); 00248 TQDateTime to( from.addSecs( addSecs ) ); 00249 00250 setDates( from, to, false ); 00251 } 00252 00253 bool KOEventEditor::processInput() 00254 { 00255 kdDebug(5850) << "KOEventEditor::processInput(); event is " << mEvent << endl; 00256 00257 if ( !validateInput() || !mChanger ) { 00258 kdDebug(5850) << " mChanger is " << mChanger << endl; 00259 return false; 00260 } 00261 00262 TQGuardedPtr<KOEditorFreeBusy> freeBusy( mFreeBusy ); 00263 00264 if ( mEvent ) { 00265 bool rc = true; 00266 Event *oldEvent = mEvent->clone(); 00267 Event *event = mEvent->clone(); 00268 00269 kdDebug(5850) << "KOEventEditor::processInput() write event." << endl; 00270 writeEvent( event ); 00271 kdDebug(5850) << "KOEventEditor::processInput() event written." << endl; 00272 00273 if( *event == *mEvent ) { 00274 // Don't do anything 00275 kdDebug(5850) << "Event not changed" << endl; 00276 if ( mIsCounter ) { 00277 KMessageBox::information( this, i18n("You didn't change the event, thus no counter proposal has been sent to the organizer."), i18n("No changes") ); 00278 } 00279 } else { 00280 kdDebug(5850) << "Event changed" << endl; 00281 //IncidenceChanger::assignIncidence( mEvent, event ); 00282 writeEvent( mEvent ); 00283 if ( mIsCounter ) { 00284 KOGroupware::instance()->sendCounterProposal( mCalendar, oldEvent, mEvent ); 00285 // add dummy event at the position of the counter proposal 00286 Event *event = mEvent->clone(); 00287 event->clearAttendees(); 00288 event->setSummary( i18n("My counter proposal for: %1").arg( mEvent->summary() ) ); 00289 mChanger->addIncidence( event, mResource, mSubResource, this ); 00290 } else { 00291 if ( mRecurIncidence && mRecurIncidenceAfterDissoc ) { 00292 mChanger->addIncidence( mEvent, mResource, mSubResource, this ); 00293 00294 mChanger->changeIncidence( mRecurIncidence, mRecurIncidenceAfterDissoc, 00295 KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE, this ); 00296 00297 } else { 00298 mChanger->changeIncidence( oldEvent, mEvent, KOGlobals::NOTHING_MODIFIED, this ); 00299 } 00300 } 00301 } 00302 delete event; 00303 delete oldEvent; 00304 return rc; 00305 } else { 00306 mEvent = new Event; 00307 mEvent->setOrganizer( Person( KOPrefs::instance()->fullName(), 00308 KOPrefs::instance()->email() ) ); 00309 writeEvent( mEvent ); 00310 // 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. 00311 if ( !mChanger->addIncidence( mEvent, mResource, mSubResource, this ) ) { 00312 delete mEvent; 00313 mEvent = 0; 00314 return false; 00315 } 00316 } 00317 // if "this" was deleted, freeBusy is 0 (being a guardedptr) 00318 if ( freeBusy ) { 00319 freeBusy->cancelReload(); 00320 } 00321 00322 return true; 00323 } 00324 00325 void KOEventEditor::processCancel() 00326 { 00327 kdDebug(5850) << "KOEventEditor::processCancel()" << endl; 00328 00329 if ( mFreeBusy ) mFreeBusy->cancelReload(); 00330 00331 if ( mRecurIncidence && mRecurIncidenceAfterDissoc ) { 00332 *mRecurIncidenceAfterDissoc = *mRecurIncidence; 00333 } 00334 00335 } 00336 00337 void KOEventEditor::deleteEvent() 00338 { 00339 kdDebug(5850) << "Delete event" << endl; 00340 00341 if ( mEvent ) 00342 emit deleteIncidenceSignal( mEvent ); 00343 emit dialogClose( mEvent ); 00344 reject(); 00345 } 00346 00347 void KOEventEditor::readEvent( Event *event, Calendar *calendar, const TQDate &date, bool tmpl ) 00348 { 00349 mGeneral->readEvent( event, calendar, date, tmpl ); 00350 mRecurrence->readIncidence( event ); 00351 00352 if ( mFreeBusy ) { 00353 mFreeBusy->readEvent( event ); 00354 mFreeBusy->triggerReload(); 00355 } 00356 00357 createEmbeddedURLPages( event ); 00358 readDesignerFields( event ); 00359 00360 if ( mIsCounter ) 00361 mGeneral->invitationBar()->hide(); 00362 } 00363 00364 void KOEventEditor::writeEvent( Event *event ) 00365 { 00366 mGeneral->writeEvent( event ); 00367 if ( mFreeBusy ) 00368 mFreeBusy->writeEvent( event ); 00369 00370 cancelRemovedAttendees( event ); 00371 00372 mRecurrence->writeIncidence( event ); 00373 00374 writeDesignerFields( event ); 00375 } 00376 00377 bool KOEventEditor::validateInput() 00378 { 00379 if ( !mGeneral->validateInput() || 00380 !mDetails->validateInput() || 00381 !mRecurrence->validateInput() ) { 00382 kdDebug(5850) << "ValidateInput returns false" << endl; 00383 return false; 00384 } else { 00385 return true; 00386 } 00387 } 00388 00389 int KOEventEditor::msgItemDelete() 00390 { 00391 return KMessageBox::warningContinueCancel(this, 00392 i18n("This item will be permanently deleted."), 00393 i18n("KOrganizer Confirmation"),KGuiItem(i18n("Delete"),"editdelete")); 00394 } 00395 00396 void KOEventEditor::loadTemplate( /*const*/ CalendarLocal& cal ) 00397 { 00398 const Event::List events = cal.events(); 00399 if ( events.count() == 0 ) { 00400 KMessageBox::error( this, 00401 i18n("Template does not contain a valid event.") ); 00402 } else { 00403 kdDebug(5850) << "KOEventEditor::slotLoadTemplate(): readTemplate" << endl; 00404 readEvent( events.first(), 0, TQDate(), true ); 00405 } 00406 } 00407 00408 TQStringList& KOEventEditor::templates() const 00409 { 00410 return KOPrefs::instance()->mEventTemplates; 00411 } 00412 00413 void KOEventEditor::slotSaveTemplate( const TQString &templateName ) 00414 { 00415 kdDebug(5006) << "SlotSaveTemplate" << endl; 00416 Event *event = new Event; 00417 writeEvent( event ); 00418 saveAsTemplate( event, templateName ); 00419 } 00420 00421 TQObject *KOEventEditor::typeAheadReceiver() const 00422 { 00423 return mGeneral->typeAheadReceiver(); 00424 } 00425 00426 void KOEventEditor::updateRecurrenceSummary() 00427 { 00428 Event *ev = new Event(); 00429 writeEvent( ev ); 00430 mGeneral->updateRecurrenceSummary( ev ); 00431 delete ev; 00432 } 00433 00434 void KOEventEditor::selectInvitationCounterProposal(bool enable) 00435 { 00436 KOIncidenceEditor::selectInvitationCounterProposal( enable ); 00437 if ( enable ) 00438 mGeneral->invitationBar()->hide(); 00439 } 00440 00441 #include "koeventeditor.moc"