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