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