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 "koeditoralarms.h"
00045 #include "koeditorrecurrence.h"
00046 #include "koeditordetails.h"
00047 #include "koeditorfreebusy.h"
00048 #include "kogroupware.h"
00049 #include "kodialogmanager.h"
00050 #include "incidencechanger.h"
00051 
00052 #include "koeventeditor.h"
00053 
00054 KOEventEditor::KOEventEditor( Calendar *calendar, QWidget *parent )
00055   : KOIncidenceEditor( QString::null, calendar, parent ),
00056     mEvent( 0 ), mCalendar( 0 ), mGeneral( 0 ), mRecurrence( 0 ), mFreeBusy( 0 )
00057 {
00058 }
00059 
00060 KOEventEditor::~KOEventEditor()
00061 {
00062   if ( !mIsCounter )
00063     emit dialogClose( mEvent );
00064 }
00065 
00066 void KOEventEditor::init()
00067 {
00068   setupGeneral();
00069 //  setupAlarmsTab();
00070   setupRecurrence();
00071   setupFreeBusy();
00072   setupDesignerTabs( "event" );
00073 
00074   // Propagate date time settings to recurrence tab
00075   connect( mGeneral, SIGNAL( dateTimesChanged( const QDateTime &, const QDateTime & ) ),
00076            mRecurrence, SLOT( setDateTimes( const QDateTime &, const QDateTime &) ) );
00077   connect( mGeneral, SIGNAL( dateTimeStrChanged( const QString & ) ),
00078            mRecurrence, SLOT( setDateTimeStr( const QString & ) ) );
00079   connect( mFreeBusy, SIGNAL( dateTimesChanged( const QDateTime &, const QDateTime & ) ),
00080            mRecurrence, SLOT( setDateTimes( const QDateTime &, const QDateTime & ) ) );
00081 
00082   // Propagate date time settings to gantt tab and back
00083   connect( mGeneral, SIGNAL( dateTimesChanged( const QDateTime &, const QDateTime & ) ),
00084            mFreeBusy, SLOT( slotUpdateGanttView( const QDateTime &, const QDateTime & ) ) );
00085   connect( mFreeBusy, SIGNAL( dateTimesChanged( const QDateTime &, const QDateTime & ) ),
00086            mGeneral, SLOT( setDateTimes( const QDateTime &, const QDateTime & ) ) );
00087 
00088   connect( mGeneral, SIGNAL( focusReceivedSignal() ),
00089            SIGNAL( focusReceivedSignal() ) );
00090 
00091   connect( mGeneral, SIGNAL( openCategoryDialog() ),
00092            SIGNAL( editCategories() ) );
00093   connect( this, SIGNAL( updateCategoryConfig() ),
00094            mGeneral, SIGNAL( updateCategoryConfig() ) );
00095 
00096   connect( mFreeBusy, SIGNAL(updateAttendeeSummary(int)),
00097            mGeneral, SLOT(updateAttendeeSummary(int)) );
00098 
00099   connect( mGeneral, SIGNAL(editRecurrence()),
00100            mRecurrenceDialog, SLOT(show()) );
00101   connect( mRecurrenceDialog, SIGNAL(okClicked()),
00102            SLOT(updateRecurrenceSummary()) );
00103 
00104   connect( mGeneral, SIGNAL(acceptInvitation()),
00105            mFreeBusy, SLOT(acceptForMe()) );
00106   connect( mGeneral, SIGNAL(declineInvitation()),
00107            mFreeBusy, SLOT(declineForMe()) );
00108 }
00109 
00110 void KOEventEditor::reload()
00111 {
00112   kdDebug(5850) << "KOEventEditor::reload()" << endl;
00113 
00114   if ( mEvent ) {
00115     readEvent( mEvent, mCalendar, QDate() );
00116   }
00117 }
00118 
00119 void KOEventEditor::setupGeneral()
00120 {
00121   mGeneral = new KOEditorGeneralEvent( this );
00122 
00123   if( KOPrefs::instance()->mCompactDialogs ) {
00124     QFrame *topFrame = addPage(i18n("General"));
00125     QWhatsThis::add( topFrame,
00126                      i18n("The General tab allows you to set the most common "
00127                           "options for the event.") );
00128 
00129     QBoxLayout *topLayout = new QVBoxLayout(topFrame);
00130     topLayout->setSpacing(spacingHint());
00131 
00132     mGeneral->initHeader( topFrame, topLayout );
00133     mGeneral->initTime(topFrame,topLayout);
00134 //    QBoxLayout *alarmLineLayout = new QHBoxLayout(topLayout);
00135     mGeneral->initAlarm(topFrame,topLayout);
00136     mGeneral->enableAlarm( false );
00137 
00138     topLayout->addStretch( 1 );
00139 
00140     QFrame *topFrame2 = addPage(i18n("Details"));
00141 
00142     QBoxLayout *topLayout2 = new QVBoxLayout(topFrame2);
00143     topLayout2->setSpacing(spacingHint());
00144 
00145     mGeneral->initClass(topFrame2,topLayout2);
00146     mGeneral->initSecrecy( topFrame2, topLayout2 );
00147     mGeneral->initDescription(topFrame2,topLayout2);
00148   } else {
00149     QFrame *topFrame = addPage(i18n("&General"));
00150     QWhatsThis::add( topFrame,
00151                      i18n("The General tab allows you to set the most common "
00152                           "options for the event.") );
00153 
00154     QBoxLayout *topLayout = new QVBoxLayout(topFrame);
00155     topLayout->setSpacing(spacingHint());
00156 
00157     mGeneral->initInvitationBar( topFrame, topLayout );
00158     mGeneral->initHeader( topFrame, topLayout );
00159     mGeneral->initTime(topFrame,topLayout);
00160     mGeneral->initDescription(topFrame,topLayout);
00161     mGeneral->initAttachments(topFrame,topLayout);
00162     connect( mGeneral, SIGNAL( openURL( const KURL& ) ),
00163              this, SLOT( openURL( const KURL& ) ) );
00164     connect( this, SIGNAL( signalAddAttachments( const QStringList&, const QStringList&, bool ) ),
00165              mGeneral, SLOT( addAttachments( const QStringList&, const QStringList&, bool ) ) );
00166   }
00167 
00168   mGeneral->finishSetup();
00169 }
00170 
00171 void KOEventEditor::modified()
00172 {
00173   // Play dumb, just reload the event. This dialog has become so complicated
00174   // that there is no point in trying to be smart here...
00175   reload();
00176 }
00177 
00178 void KOEventEditor::setupRecurrence()
00179 {
00180   mRecurrenceDialog = new KOEditorRecurrenceDialog( this );
00181   mRecurrenceDialog->hide();
00182   mRecurrence = mRecurrenceDialog->editor();
00183 }
00184 
00185 void KOEventEditor::setupFreeBusy()
00186 {
00187   QFrame *freeBusyPage = addPage( i18n("&Attendees") );
00188   QWhatsThis::add( freeBusyPage,
00189         i18n("The Free/Busy tab allows you to see whether "
00190        "other attendees are free or busy during your event.") );
00191 
00192   QBoxLayout *topLayout = new QVBoxLayout( freeBusyPage );
00193 
00194   mAttendeeEditor = mFreeBusy = new KOEditorFreeBusy( spacingHint(), freeBusyPage );
00195   topLayout->addWidget( mFreeBusy );
00196 }
00197 
00198 void KOEventEditor::editIncidence( Incidence *incidence,
00199                                    const QDate &date,
00200                                    Calendar *calendar )
00201 {
00202   Event*event = dynamic_cast<Event*>(incidence);
00203   if ( event ) {
00204     init();
00205 
00206     mEvent = event;
00207     mCalendar = calendar;
00208 
00209     const QDate &dt = mRecurIncidence && date.isValid() ? date : incidence->dtStart().date();
00210 kdDebug() << " date is valid = " << date.isValid() << " and date is " << date << " and inc start is "<< incidence->dtStart().date() << " and event dtstart is " << event->dtStart().date() << " and dt is valid" << dt.isValid()  << "\n";
00211     readEvent( mEvent, mCalendar, dt );
00212   }
00213 
00214   setCaption( i18n("Edit Event") );
00215 }
00216 
00217 void KOEventEditor::newEvent()
00218 {
00219   init();
00220   mEvent = 0;
00221   loadDefaults();
00222   setCaption( i18n("New Event") );
00223 }
00224 
00225 void KOEventEditor::setDates( const QDateTime &from, const QDateTime &to, bool allDay )
00226 {
00227   mGeneral->setDefaults( from, to, allDay );
00228   mRecurrence->setDefaults( from, to, allDay );
00229   if( mFreeBusy ) {
00230     if ( allDay )
00231       mFreeBusy->setDateTimes( from, to.addDays( 1 ) );
00232     else
00233       mFreeBusy->setDateTimes( from, to );
00234   }
00235 }
00236 
00237 void KOEventEditor::setTexts( const QString &summary, const QString &description )
00238 {
00239   if ( description.isEmpty() && summary.contains("\n") ) {
00240     mGeneral->setDescription( summary );
00241     int pos = summary.find( "\n" );
00242     mGeneral->setSummary( summary.left( pos ) );
00243   } else {
00244     mGeneral->setSummary( summary );
00245     mGeneral->setDescription( description );
00246   }
00247 }
00248 
00249 void KOEventEditor::loadDefaults()
00250 {
00251   QDateTime from( QDate::currentDate(), KOPrefs::instance()->mStartTime.time() );
00252   int addSecs = ( KOPrefs::instance()->mDefaultDuration.time().hour()*3600 ) +
00253                 ( KOPrefs::instance()->mDefaultDuration.time().minute()*60 );
00254   QDateTime to( from.addSecs( addSecs ) );
00255 
00256   setDates( from, to, false );
00257 }
00258 
00259 bool KOEventEditor::processInput()
00260 {
00261   kdDebug(5850) << "KOEventEditor::processInput()" << endl;
00262 
00263   if ( !validateInput() || !mChanger ) return false;
00264 
00265   QGuardedPtr<KOEditorFreeBusy> freeBusy( mFreeBusy );
00266 
00267   if ( mEvent ) {
00268     bool rc = true;
00269     Event *oldEvent = mEvent->clone();
00270     Event *event = mEvent->clone();
00271 
00272     kdDebug(5850) << "KOEventEditor::processInput() write event." << endl;
00273     writeEvent( event );
00274     kdDebug(5850) << "KOEventEditor::processInput() event written." << endl;
00275 
00276     if( *event == *mEvent ) {
00277       // Don't do anything
00278       kdDebug(5850) << "Event not changed\n";
00279       if ( mIsCounter )
00280         KMessageBox::information( this, i18n("You didn't change the event, thus no counter proposal has been sent to the organizer."), i18n("No changes") );
00281     } else {
00282       kdDebug(5850) << "Event changed\n";
00283       //IncidenceChanger::assignIncidence( mEvent, event );
00284       writeEvent( mEvent );
00285       if ( mIsCounter ) {
00286         KOGroupware::instance()->sendCounterProposal( mCalendar, oldEvent, mEvent );
00287         // add dummy event at the position of the counter proposal
00288         Event *event = mEvent->clone();
00289         event->clearAttendees();
00290         event->setSummary( i18n("My counter proposal for: %1").arg( mEvent->summary() ) );
00291         mChanger->addIncidence( event, 0, QString(), this );
00292       } else {
00293         if ( mRecurIncidence && mRecurIncidenceAfterDissoc ) {
00294           mChanger->addIncidence( mEvent, 0, QString(), this );
00295 
00296           mChanger->changeIncidence( mRecurIncidence, mRecurIncidenceAfterDissoc,
00297                                      KOGlobals::RECURRENCE_MODIFIED_ALL_FUTURE, this );
00298 
00299         } else {
00300           mChanger->changeIncidence( oldEvent, mEvent, KOGlobals::NOTHING_MODIFIED, this );
00301         }
00302       }
00303     }
00304     delete event;
00305     delete oldEvent;
00306     return rc;
00307   } else {
00308     mEvent = new Event;
00309     mEvent->setOrganizer( Person( KOPrefs::instance()->fullName(),
00310                           KOPrefs::instance()->email() ) );
00311     writeEvent( mEvent );
00312     // 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.
00313     if ( !mChanger->addIncidence( mEvent, mResource, mSubResource, this ) ) {
00314       delete mEvent;
00315       mEvent = 0;
00316       return false;
00317     }
00318   }
00319   // if "this" was deleted, freeBusy is 0 (being a guardedptr)
00320   if ( freeBusy ) freeBusy->cancelReload();
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 //  mAlarms->readIncidence( event );
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() ) return false;
00380   if ( !mDetails->validateInput() ) return false;
00381   if ( !mRecurrence->validateInput() ) return false;
00382 
00383   return true;
00384 }
00385 
00386 int KOEventEditor::msgItemDelete()
00387 {
00388   return KMessageBox::warningContinueCancel(this,
00389       i18n("This item will be permanently deleted."),
00390       i18n("KOrganizer Confirmation"),KGuiItem(i18n("Delete"),"editdelete"));
00391 }
00392 
00393 void KOEventEditor::loadTemplate( /*const*/ CalendarLocal& cal )
00394 {
00395   const Event::List events = cal.events();
00396   if ( events.count() == 0 ) {
00397     KMessageBox::error( this,
00398         i18n("Template does not contain a valid event.") );
00399   } else {
00400     kdDebug(5850) << "KOEventEditor::slotLoadTemplate(): readTemplate" << endl;
00401     readEvent( events.first(), 0, QDate(), true );
00402   }
00403 }
00404 
00405 QStringList& KOEventEditor::templates() const
00406 {
00407   return KOPrefs::instance()->mEventTemplates;
00408 }
00409 
00410 void KOEventEditor::slotSaveTemplate( const QString &templateName )
00411 {
00412   kdDebug(5006) << "SlotSaveTemplate" << endl;
00413   Event *event = new Event;
00414   writeEvent( event );
00415   saveAsTemplate( event, templateName );
00416 }
00417 
00418 QObject *KOEventEditor::typeAheadReceiver() const
00419 {
00420   return mGeneral->typeAheadReceiver();
00421 }
00422 
00423 void KOEventEditor::updateRecurrenceSummary()
00424 {
00425   Event *ev = new Event();
00426   writeEvent( ev );
00427   mGeneral->updateRecurrenceSummary( ev );
00428   delete ev;
00429 }
00430 
00431 void KOEventEditor::selectInvitationCounterProposal(bool enable)
00432 {
00433   KOIncidenceEditor::selectInvitationCounterProposal( enable );
00434   if ( enable )
00435     mGeneral->invitationBar()->hide();
00436 }
00437 
00438 #include "koeventeditor.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys