korganizer

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 Qt, and distribute the resulting executable,
00023     without including the source code for Qt in the source distribution.
00024 */
00025 
00026 #include <qtooltip.h>
00027 #include <qframe.h>
00028 #include <qpixmap.h>
00029 #include <qlayout.h>
00030 #include <qwidgetstack.h>
00031 #include <qwhatsthis.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, QWidget *parent )
00054   : KOIncidenceEditor( QString::null, 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, SIGNAL( dateTimesChanged( const QDateTime &, const QDateTime & ) ),
00074            mRecurrence, SLOT( setDateTimes( const QDateTime &, const QDateTime &) ) );
00075   connect( mGeneral, SIGNAL( dateTimeStrChanged( const QString & ) ),
00076            mRecurrence, SLOT( setDateTimeStr( const QString & ) ) );
00077   connect( mFreeBusy, SIGNAL( dateTimesChanged( const QDateTime &, const QDateTime & ) ),
00078            mRecurrence, SLOT( setDateTimes( const QDateTime &, const QDateTime & ) ) );
00079 
00080   // Propagate date time settings to gantt tab and back
00081   connect( mGeneral, SIGNAL( dateTimesChanged( const QDateTime &, const QDateTime & ) ),
00082            mFreeBusy, SLOT( slotUpdateGanttView( const QDateTime &, const QDateTime & ) ) );
00083   connect( mFreeBusy, SIGNAL( dateTimesChanged( const QDateTime &, const QDateTime & ) ),
00084            mGeneral, SLOT( setDateTimes( const QDateTime &, const QDateTime & ) ) );
00085 
00086   connect( mGeneral, SIGNAL( focusReceivedSignal() ),
00087            SIGNAL( focusReceivedSignal() ) );
00088 
00089   connect( mGeneral, SIGNAL( openCategoryDialog() ),
00090            SIGNAL( editCategories() ) );
00091   connect( this, SIGNAL( updateCategoryConfig() ),
00092            mGeneral, SIGNAL( updateCategoryConfig() ) );
00093 
00094   connect( mFreeBusy, SIGNAL(updateAttendeeSummary(int)),
00095            mGeneral, SLOT(updateAttendeeSummary(int)) );
00096 
00097   connect( mGeneral, SIGNAL(editRecurrence()),
00098            mRecurrenceDialog, SLOT(show()) );
00099   connect( mRecurrenceDialog, SIGNAL(okClicked()),
00100            SLOT(updateRecurrenceSummary()) );
00101 
00102   connect( mGeneral, SIGNAL(acceptInvitation()),
00103            mFreeBusy, SLOT(acceptForMe()) );
00104   connect( mGeneral, SIGNAL(declineInvitation()),
00105            mFreeBusy, SLOT(declineForMe()) );
00106 }
00107 
00108 void KOEventEditor::reload()
00109 {
00110   kdDebug(5850) << "KOEventEditor::reload()" << endl;
00111 
00112   if ( mEvent ) {
00113     readEvent( mEvent, mCalendar, QDate() );
00114   }
00115 }
00116 
00117 void KOEventEditor::setupGeneral()
00118 {
00119   mGeneral = new KOEditorGeneralEvent( this );
00120 
00121   if( KOPrefs::instance()->mCompactDialogs ) {
00122     QFrame *topFrame = addPage(i18n("General"));
00123     QWhatsThis::add( topFrame,
00124                      i18n("The General tab allows you to set the most common "
00125                           "options for the event.") );
00126 
00127     QBoxLayout *topLayout = new QVBoxLayout(topFrame);
00128     topLayout->setSpacing(spacingHint());
00129 
00130     mGeneral->initHeader( topFrame, topLayout );
00131     mGeneral->initTime(topFrame,topLayout);
00132 
00133     topLayout->addStretch( 1 );
00134 
00135     QFrame *topFrame2 = addPage(i18n("Details"));
00136 
00137     QBoxLayout *topLayout2 = new QVBoxLayout(topFrame2);
00138     topLayout2->setSpacing(spacingHint());
00139 
00140     mGeneral->initClass(topFrame2,topLayout2);
00141     mGeneral->initSecrecy( topFrame2, topLayout2 );
00142     mGeneral->initDescription(topFrame2,topLayout2);
00143   } else {
00144     QFrame *topFrame = addPage(i18n("&General"));
00145     QWhatsThis::add( topFrame,
00146                      i18n("The General tab allows you to set the most common "
00147                           "options for the event.") );
00148 
00149     QBoxLayout *topLayout = new QVBoxLayout(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, SIGNAL( openURL( const KURL& ) ),
00158              this, SLOT( openURL( const KURL& ) ) );
00159     connect( this, SIGNAL( signalAddAttachments( const QStringList&, const QStringList&, bool ) ),
00160              mGeneral, SLOT( addAttachments( const QStringList&, const QStringList&, 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   QFrame *freeBusyPage = addPage( i18n("&Attendees") );
00183   QWhatsThis::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   QBoxLayout *topLayout = new QVBoxLayout( freeBusyPage );
00188 
00189   mAttendeeEditor = mFreeBusy = new KOEditorFreeBusy( spacingHint(), freeBusyPage );
00190   topLayout->addWidget( mFreeBusy );
00191 }
00192 
00193 void KOEventEditor::editIncidence( Incidence *incidence,
00194                                    const QDate &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 QDate &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 QDateTime &from, const QDateTime &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 QString &summary, const QString &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   QDateTime from( QDate::currentDate(), KOPrefs::instance()->mStartTime.time() );
00246   int addSecs = ( KOPrefs::instance()->mDefaultDuration.time().hour()*3600 ) +
00247                 ( KOPrefs::instance()->mDefaultDuration.time().minute()*60 );
00248   QDateTime 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   QGuardedPtr<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, false );
00293 
00294           mChanger->changeIncidence( mRecurIncidence, mRecurIncidenceAfterDissoc,
00295                                      KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE, this, true );
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 QDate &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   Event *event = new Event();;
00380   writeEvent( event );
00381 
00382   if ( !mGeneral->validateInput() ||
00383        !mDetails->validateInput() ||
00384        !mRecurrence->validateInput( event ) ) {
00385     kdDebug(5850) << "ValidateInput returns false" << endl;
00386     return false;
00387   } else {
00388     return true;
00389   }
00390 }
00391 
00392 int KOEventEditor::msgItemDelete()
00393 {
00394   return KMessageBox::warningContinueCancel(this,
00395       i18n("This item will be permanently deleted."),
00396       i18n("KOrganizer Confirmation"),KGuiItem(i18n("Delete"),"editdelete"));
00397 }
00398 
00399 void KOEventEditor::loadTemplate( /*const*/ CalendarLocal& cal )
00400 {
00401   const Event::List events = cal.events();
00402   if ( events.count() == 0 ) {
00403     KMessageBox::error( this,
00404         i18n("Template does not contain a valid event.") );
00405   } else {
00406     kdDebug(5850) << "KOEventEditor::slotLoadTemplate(): readTemplate" << endl;
00407     readEvent( events.first(), 0, QDate(), true );
00408   }
00409 }
00410 
00411 QStringList& KOEventEditor::templates() const
00412 {
00413   return KOPrefs::instance()->mEventTemplates;
00414 }
00415 
00416 void KOEventEditor::slotSaveTemplate( const QString &templateName )
00417 {
00418   kdDebug(5006) << "SlotSaveTemplate" << endl;
00419   Event *event = new Event;
00420   writeEvent( event );
00421   saveAsTemplate( event, templateName );
00422 }
00423 
00424 QObject *KOEventEditor::typeAheadReceiver() const
00425 {
00426   return mGeneral->typeAheadReceiver();
00427 }
00428 
00429 void KOEventEditor::updateRecurrenceSummary()
00430 {
00431   Event *ev = new Event();
00432   writeEvent( ev );
00433   mGeneral->updateRecurrenceSummary( ev );
00434   delete ev;
00435 }
00436 
00437 void KOEventEditor::selectInvitationCounterProposal(bool enable)
00438 {
00439   KOIncidenceEditor::selectInvitationCounterProposal( enable );
00440   if ( enable )
00441     mGeneral->invitationBar()->hide();
00442 }
00443 
00444 #include "koeventeditor.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys