korganizer

koincidenceeditor.cpp

00001 /*
00002     This file is part of KOrganizer.
00003 
00004     Copyright (c) 2001 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     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019 
00020     As a special exception, permission is given to link this program
00021     with any edition of Qt, and distribute the resulting executable,
00022     without including the source code for Qt in the source distribution.
00023 */
00024 
00025 #include <qtooltip.h>
00026 #include <qframe.h>
00027 #include <qguardedptr.h>
00028 #include <qpixmap.h>
00029 #include <qlayout.h>
00030 #include <qwidgetstack.h>
00031 #include <qdatetime.h>
00032 #include <qwhatsthis.h>
00033 
00034 #include <kdebug.h>
00035 #include <klocale.h>
00036 #include <kstandarddirs.h>
00037 #include <kmessagebox.h>
00038 #include <kinputdialog.h>
00039 #include <kio/netaccess.h>
00040 #include <kabc/addressee.h>
00041 
00042 #include <libkdepim/designerfields.h>
00043 #include <libkdepim/embeddedurlpage.h>
00044 
00045 #include <libkcal/calendarlocal.h>
00046 #include <libkcal/incidence.h>
00047 #include <libkcal/icalformat.h>
00048 
00049 #include "koprefs.h"
00050 #include "koglobals.h"
00051 #include "koeditordetails.h"
00052 #include "koeditoralarms.h"
00053 #include "urihandler.h"
00054 #include "koincidenceeditor.h"
00055 #include "templatemanagementdialog.h"
00056 
00057 KOIncidenceEditor::KOIncidenceEditor( const QString &caption,
00058                                       Calendar *calendar, QWidget *parent )
00059   : KDialogBase( Tabbed, caption, Ok | Apply | Cancel | Default, Ok,
00060                  parent, 0, false, false ),
00061     mAttendeeEditor( 0 ), mIsCounter( false )
00062 {
00063   // Set this to be the group leader for all subdialogs - this means
00064   // modal subdialogs will only affect this dialog, not the other windows
00065   setWFlags( getWFlags() | WGroupLeader );
00066 
00067   mCalendar = calendar;
00068 
00069   if ( KOPrefs::instance()->mCompactDialogs ) {
00070     showButton( Apply, false );
00071     showButton( Default, false );
00072   } else {
00073     setButtonText( Default, i18n("&Templates...") );
00074   }
00075 
00076   connect( this, SIGNAL( defaultClicked() ), SLOT( slotManageTemplates() ) );
00077   connect( this, SIGNAL( finished() ), SLOT( delayedDestruct() ) );
00078 }
00079 
00080 KOIncidenceEditor::~KOIncidenceEditor()
00081 {
00082 }
00083 
00084 void KOIncidenceEditor::setupAttendeesTab()
00085 {
00086   QFrame *topFrame = addPage( i18n("Atte&ndees") );
00087   QWhatsThis::add( topFrame,
00088                    i18n("The Attendees tab allows you to Add or Remove "
00089                         "Attendees to/from this event or to-do.") );
00090 
00091   QBoxLayout *topLayout = new QVBoxLayout( topFrame );
00092 
00093   mAttendeeEditor = mDetails = new KOEditorDetails( spacingHint(), topFrame );
00094   topLayout->addWidget( mDetails );
00095 }
00096 
00097 void KOIncidenceEditor::slotApply()
00098 {
00099   processInput();
00100 }
00101 
00102 void KOIncidenceEditor::slotOk()
00103 {
00104   // "this" can be deleted before processInput() returns (processInput() opens
00105   // a non-modal dialog when Kolab is used). So accept should only be executed
00106   // when "this" is still valid
00107   QGuardedPtr<QWidget> ptr( this );
00108   if ( processInput() && ptr ) accept();
00109 }
00110 
00111 void KOIncidenceEditor::slotCancel()
00112 {
00113   processCancel();
00114   reject();
00115 }
00116 
00117 void KOIncidenceEditor::cancelRemovedAttendees( Incidence *incidence )
00118 {
00119   if ( !incidence ) return;
00120 
00121   // cancelAttendeeEvent removes all attendees from the incidence,
00122   // and then only adds those that need to be cancelled (i.e. a mail needs to be sent to them).
00123   if ( KOPrefs::instance()->thatIsMe( incidence->organizer().email() ) ) {
00124     Incidence *ev = incidence->clone();
00125     ev->registerObserver( 0 );
00126     mAttendeeEditor->cancelAttendeeEvent( ev );
00127     if ( ev->attendeeCount() > 0 ) {
00128       emit deleteAttendee( ev );
00129     }
00130     delete( ev );
00131   }
00132 
00133 }
00134 
00135 void KOIncidenceEditor::slotManageTemplates()
00136 {
00137   kdDebug(5850) << "KOIncidenceEditor::manageTemplates()" << endl;
00138 
00139   TemplateManagementDialog * const d = new TemplateManagementDialog( this, templates() );
00140   connect( d, SIGNAL( loadTemplate( const QString& ) ),
00141            this, SLOT( slotLoadTemplate( const QString& ) ) );
00142   connect( d, SIGNAL( templatesChanged( const QStringList& ) ),
00143            this, SLOT( slotTemplatesChanged( const QStringList& ) ) );
00144   connect( d, SIGNAL( saveTemplate( const QString& ) ),
00145            this, SLOT( slotSaveTemplate( const QString& ) ) );
00146   d->exec();
00147   return;
00148 }
00149 
00150 void KOIncidenceEditor::saveAsTemplate( Incidence *incidence,
00151                                         const QString &templateName )
00152 {
00153   if ( !incidence || templateName.isEmpty() ) return;
00154 
00155   QString fileName = "templates/" + incidence->type();
00156   fileName.append( "/" + templateName );
00157   fileName = locateLocal( "data", "korganizer/" + fileName );
00158 
00159   CalendarLocal cal( KOPrefs::instance()->mTimeZoneId );
00160   cal.addIncidence( incidence );
00161   ICalFormat format;
00162   format.save( &cal, fileName );
00163 }
00164 
00165 void KOIncidenceEditor::slotLoadTemplate( const QString& templateName )
00166 {
00167   CalendarLocal cal( KOPrefs::instance()->mTimeZoneId );
00168   QString fileName = locateLocal( "data", "korganizer/templates/" + type() + "/" +
00169       templateName );
00170 
00171   if ( fileName.isEmpty() ) {
00172     KMessageBox::error( this, i18n("Unable to find template '%1'.")
00173         .arg( fileName ) );
00174   } else {
00175     ICalFormat format;
00176     if ( !format.load( &cal, fileName ) ) {
00177       KMessageBox::error( this, i18n("Error loading template file '%1'.")
00178           .arg( fileName ) );
00179       return;
00180     }
00181   }
00182   loadTemplate( cal );
00183 }
00184 
00185 void KOIncidenceEditor::slotTemplatesChanged( const QStringList& newTemplates )
00186 {
00187   templates() = newTemplates;
00188 }
00189 
00190 void KOIncidenceEditor::setupDesignerTabs( const QString &type )
00191 {
00192   QStringList activePages = KOPrefs::instance()->activeDesignerFields();
00193 
00194   QStringList list = KGlobal::dirs()->findAllResources( "data",
00195     "korganizer/designer/" + type + "/*.ui", true, true );
00196   for ( QStringList::iterator it = list.begin(); it != list.end(); ++it ) {
00197     const QString &fn = (*it).mid( (*it).findRev('/') + 1 );
00198     if ( activePages.find( fn ) != activePages.end() ) {
00199       addDesignerTab( *it );
00200     }
00201   }
00202 }
00203 
00204 QWidget *KOIncidenceEditor::addDesignerTab( const QString &uifile )
00205 {
00206   kdDebug(5850) << "Designer tab: " << uifile << endl;
00207 
00208   KPIM::DesignerFields *wid = new KPIM::DesignerFields( uifile, 0 );
00209   mDesignerFields.append( wid );
00210 
00211   QFrame *topFrame = addPage( wid->title() );
00212 
00213   QBoxLayout *topLayout = new QVBoxLayout( topFrame );
00214 
00215   wid->reparent( topFrame, 0, QPoint() );
00216   topLayout->addWidget( wid );
00217   mDesignerFieldForWidget[ topFrame ] = wid;
00218 
00219   return topFrame;
00220 }
00221 
00222 class KCalStorage : public KPIM::DesignerFields::Storage
00223 {
00224   public:
00225     KCalStorage( Incidence *incidence )
00226       : mIncidence( incidence )
00227     {
00228     }
00229 
00230     QStringList keys()
00231     {
00232       QStringList keys;
00233 
00234       QMap<QCString, QString> props = mIncidence->customProperties();
00235       QMap<QCString, QString>::ConstIterator it;
00236       for( it = props.begin(); it != props.end(); ++it ) {
00237         QString customKey = it.key();
00238         QStringList parts = QStringList::split( "-", customKey );
00239         if ( parts.count() != 4 ) continue;
00240         if ( parts[ 2 ] != "KORGANIZER" ) continue;
00241         keys.append( parts[ 3 ] );
00242       }
00243 
00244       return keys;
00245     }
00246 
00247     QString read( const QString &key )
00248     {
00249       return mIncidence->customProperty( "KORGANIZER", key.utf8() );
00250     }
00251 
00252     void write( const QString &key, const QString &value )
00253     {
00254       mIncidence->setCustomProperty( "KORGANIZER", key.utf8(), value );
00255     }
00256 
00257   private:
00258     Incidence *mIncidence;
00259 };
00260 
00261 void KOIncidenceEditor::readDesignerFields( Incidence *i )
00262 {
00263   KCalStorage storage( i );
00264   KPIM::DesignerFields *fields;
00265   for( fields = mDesignerFields.first(); fields;
00266        fields = mDesignerFields.next() ) {
00267     fields->load( &storage );
00268   }
00269 }
00270 
00271 void KOIncidenceEditor::writeDesignerFields( Incidence *i )
00272 {
00273   kdDebug(5850) << "KOIncidenceEditor::writeDesignerFields()" << endl;
00274 
00275   KCalStorage storage( i );
00276   KPIM::DesignerFields *fields;
00277   for( fields = mDesignerFields.first(); fields;
00278        fields = mDesignerFields.next() ) {
00279     kdDebug(5850) << "Write Field " << fields->title() << endl;
00280     fields->save( &storage );
00281   }
00282 }
00283 
00284 
00285 void KOIncidenceEditor::setupEmbeddedURLPage( const QString &label,
00286                                  const QString &url, const QString &mimetype )
00287 {
00288   kdDebug(5850) << "KOIncidenceEditor::setupEmbeddedURLPage()" << endl;
00289   kdDebug(5850) << "label=" << label << ", url=" << url << ", mimetype=" << mimetype << endl;
00290   QFrame *topFrame = addPage( label );
00291   QBoxLayout *topLayout = new QVBoxLayout( topFrame );
00292 
00293   KPIM::EmbeddedURLPage *wid = new KPIM::EmbeddedURLPage( url, mimetype,
00294                                                           topFrame );
00295   topLayout->addWidget( wid );
00296   mEmbeddedURLPages.append( topFrame );
00297   connect( wid, SIGNAL( openURL( const KURL & ) ) ,
00298            this, SLOT( openURL( const KURL & ) ) );
00299   // TODO: Call this method only when the tab is actually activated!
00300   wid->loadContents();
00301 }
00302 
00303 void KOIncidenceEditor::createEmbeddedURLPages( Incidence *i )
00304 {
00305   kdDebug(5850) << "KOIncidenceEditor::createEmbeddedURLPages()" << endl;
00306 
00307   if ( !i ) return;
00308   if ( !mEmbeddedURLPages.isEmpty() ) {
00309     kdDebug(5850) << "mEmbeddedURLPages are not empty, clearing it!" << endl;
00310     mEmbeddedURLPages.setAutoDelete( true );
00311     mEmbeddedURLPages.clear();
00312     mEmbeddedURLPages.setAutoDelete( false );
00313   }
00314   if ( !mAttachedDesignerFields.isEmpty() ) {
00315     for ( QPtrList<QWidget>::Iterator it = mAttachedDesignerFields.begin();
00316           it != mAttachedDesignerFields.end(); ++it ) {
00317       if ( mDesignerFieldForWidget.contains( *it ) ) {
00318         mDesignerFields.remove( mDesignerFieldForWidget[ *it ] );
00319       }
00320     }
00321     mAttachedDesignerFields.setAutoDelete( true );
00322     mAttachedDesignerFields.clear();
00323     mAttachedDesignerFields.setAutoDelete( false );
00324   }
00325 
00326   Attachment::List att = i->attachments();
00327   for ( Attachment::List::Iterator it = att.begin(); it != att.end(); ++it ) {
00328     Attachment *a = (*it);
00329     kdDebug(5850) << "Iterating over the attachments " << endl;
00330     kdDebug(5850) << "label=" << a->label() << ", url=" << a->uri() << ", mimetype=" << a->mimeType() << endl;
00331     if ( a && a->showInline() && a->isUri() ) {
00332       // TODO: Allow more mime-types, but add security checks!
00333 /*      if ( a->mimeType() == "application/x-designer" ) {
00334         QString tmpFile;
00335         if ( KIO::NetAccess::download( a->uri(), tmpFile, this ) ) {
00336           mAttachedDesignerFields.append( addDesignerTab( tmpFile ) );
00337           KIO::NetAccess::removeTempFile( tmpFile );
00338         }
00339       } else*/
00340       // TODO: Enable that check again!
00341       if ( a->mimeType() == "text/html" )
00342       {
00343         setupEmbeddedURLPage( a->label(), a->uri(), a->mimeType() );
00344       }
00345     }
00346   }
00347 }
00348 
00349 void KOIncidenceEditor::openURL( const KURL &url )
00350 {
00351   QString uri = url.url();
00352   UriHandler::process( uri );
00353 }
00354 
00355 void KOIncidenceEditor::addAttachments( const QStringList &attachments,
00356                                         const QStringList &mimeTypes,
00357                                         bool inlineAttachments )
00358 {
00359     emit signalAddAttachments( attachments, mimeTypes, inlineAttachments );
00360 }
00361 
00362 void KOIncidenceEditor::addAttendees( const QStringList &attendees )
00363 {
00364   QStringList::ConstIterator it;
00365   for ( it = attendees.begin(); it != attendees.end(); ++it ) {
00366     QString name, email;
00367     KABC::Addressee::parseEmailAddress( *it, name, email );
00368     mAttendeeEditor->insertAttendee( new Attendee( name, email ) );
00369   }
00370 }
00371 
00372 void KOIncidenceEditor::selectInvitationCounterProposal(bool enable)
00373 {
00374   mIsCounter = enable;
00375   if ( mIsCounter ) {
00376     setCaption( i18n( "Counter proposal" ) );
00377     setButtonOK( i18n( "Counter proposal" ) );
00378     enableButtonApply( false );
00379   }
00380 }
00381 
00382 
00383 #include "koincidenceeditor.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys