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