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       if ( mIsCounter ) {
00283         writeEvent( mEvent );
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           writeEvent( mEvent );
00293 
00294           mRecurIncidence->startUpdates();
00295           const bool success = mChanger->changeIncidence( mRecurIncidence, mRecurIncidenceAfterDissoc,
00296                                                           KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE, this, false );
00297           if ( success ) {
00298             mRecurIncidence->endUpdates();
00299             mChanger->addIncidence( mEvent, mResource, mSubResource, this, true );
00300           } else {
00301             mRecurIncidence->cancelUpdates();
00302           }
00303         } else {
00304           mEvent->startUpdates();
00305           writeEvent( mEvent );
00306           const bool success = mChanger->changeIncidence( oldEvent, mEvent, KOGlobals::NOTHING_MODIFIED, this );
00307           if ( success ) {
00308             mEvent->endUpdates();
00309           } else {
00310             mEvent->cancelUpdates();
00311           }
00312         }
00313       }
00314     }
00315     delete event;
00316     delete oldEvent;
00317     return rc;
00318   } else {
00319     mEvent = new Event;
00320     mEvent->setOrganizer( Person( KOPrefs::instance()->fullName(),
00321                           KOPrefs::instance()->email() ) );
00322     writeEvent( mEvent );
00323     // 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.
00324     if ( !mChanger->addIncidence( mEvent, mResource, mSubResource, this ) ) {
00325       delete mEvent;
00326       mEvent = 0;
00327       return false;
00328     }
00329   }
00330   // if "this" was deleted, freeBusy is 0 (being a guardedptr)
00331   if ( freeBusy ) {
00332     freeBusy->cancelReload();
00333   }
00334 
00335   return true;
00336 }
00337 
00338 void KOEventEditor::processCancel()
00339 {
00340   kdDebug(5850) << "KOEventEditor::processCancel()" << endl;
00341 
00342   if ( mFreeBusy ) mFreeBusy->cancelReload();
00343 
00344   if ( mRecurIncidence && mRecurIncidenceAfterDissoc ) {
00345     *mRecurIncidenceAfterDissoc = *mRecurIncidence;
00346   }
00347 
00348 }
00349 
00350 void KOEventEditor::deleteEvent()
00351 {
00352   kdDebug(5850) << "Delete event" << endl;
00353 
00354   if ( mEvent )
00355     emit deleteIncidenceSignal( mEvent );
00356   emit dialogClose( mEvent );
00357   reject();
00358 }
00359 
00360 void KOEventEditor::readEvent( Event *event, Calendar *calendar, const QDate &date, bool tmpl )
00361 {
00362   mGeneral->readEvent( event, calendar, date, tmpl );
00363   mRecurrence->readIncidence( event );
00364 
00365   if ( mFreeBusy ) {
00366     mFreeBusy->readEvent( event );
00367     mFreeBusy->triggerReload();
00368   }
00369 
00370   createEmbeddedURLPages( event );
00371   readDesignerFields( event );
00372 
00373   if ( mIsCounter )
00374     mGeneral->invitationBar()->hide();
00375 }
00376 
00377 void KOEventEditor::writeEvent( Event *event )
00378 {
00379   mGeneral->writeEvent( event );
00380   if ( mFreeBusy )
00381     mFreeBusy->writeEvent( event );
00382 
00383   cancelRemovedAttendees( event );
00384 
00385   mRecurrence->writeIncidence( event );
00386 
00387   writeDesignerFields( event );
00388 }
00389 
00390 bool KOEventEditor::validateInput()
00391 {
00392   Event *event = new Event();;
00393   writeEvent( event );
00394 
00395   if ( !mGeneral->validateInput() ||
00396        !mDetails->validateInput() ||
00397        !mRecurrence->validateInput( event ) ) {
00398     kdDebug(5850) << "ValidateInput returns false" << endl;
00399     return false;
00400   } else {
00401     return true;
00402   }
00403 }
00404 
00405 int KOEventEditor::msgItemDelete()
00406 {
00407   return KMessageBox::warningContinueCancel(this,
00408       i18n("This item will be permanently deleted."),
00409       i18n("KOrganizer Confirmation"),KGuiItem(i18n("Delete"),"editdelete"));
00410 }
00411 
00412 void KOEventEditor::loadTemplate( /*const*/ CalendarLocal& cal )
00413 {
00414   const Event::List events = cal.events();
00415   if ( events.count() == 0 ) {
00416     KMessageBox::error( this,
00417         i18n("Template does not contain a valid event.") );
00418   } else {
00419     kdDebug(5850) << "KOEventEditor::slotLoadTemplate(): readTemplate" << endl;
00420     readEvent( events.first(), 0, QDate(), true );
00421   }
00422 }
00423 
00424 QStringList& KOEventEditor::templates() const
00425 {
00426   return KOPrefs::instance()->mEventTemplates;
00427 }
00428 
00429 void KOEventEditor::slotSaveTemplate( const QString &templateName )
00430 {
00431   kdDebug(5006) << "SlotSaveTemplate" << endl;
00432   Event *event = new Event;
00433   writeEvent( event );
00434   saveAsTemplate( event, templateName );
00435 }
00436 
00437 QObject *KOEventEditor::typeAheadReceiver() const
00438 {
00439   return mGeneral->typeAheadReceiver();
00440 }
00441 
00442 void KOEventEditor::updateRecurrenceSummary()
00443 {
00444   Event *ev = new Event();
00445   writeEvent( ev );
00446   mGeneral->updateRecurrenceSummary( ev );
00447   delete ev;
00448 }
00449 
00450 void KOEventEditor::selectInvitationCounterProposal(bool enable)
00451 {
00452   KOIncidenceEditor::selectInvitationCounterProposal( enable );
00453   if ( enable )
00454     mGeneral->invitationBar()->hide();
00455 }
00456 
00457 #include "koeventeditor.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys