kmail Library API Documentation

kmgroupware.cpp

00001 /* 00002 kmgroupware.cpp 00003 00004 This file is part of KMail. 00005 00006 Copyright (c) 2003 - 2004 Bo Thorsen <bo@klaralvdalens-datakonsult.se> 00007 Copyright (c) 2002 Karl-Heinz Zimmer <khz@klaralvdalens-datakonsult.se> 00008 Copyright (c) 2003 Steffen Hansen <steffen@klaralvdalens-datakonsult.se> 00009 00010 This library is free software; you can redistribute it and/or 00011 modify it under the terms of the GNU Library General Public 00012 License as published by the Free Software Foundation; either 00013 version 2 of the License, or (at your option) any later version. 00014 00015 This library is distributed in the hope that it will be useful, 00016 but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 Library General Public License for more details. 00019 00020 You should have received a copy of the GNU Library General Public License 00021 along with this library; see the file COPYING.LIB. If not, write to 00022 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00023 Boston, MA 02111-1307, USA. 00024 00025 In addition, as a special exception, the copyright holders give 00026 permission to link the code of this program with any edition of 00027 the Qt library by Trolltech AS, Norway (or with modified versions 00028 of Qt that use the same license as Qt), and distribute linked 00029 combinations including the two. You must obey the GNU General 00030 Public License in all respects for all of the code used other than 00031 Qt. If you modify this file, you may extend this exception to 00032 your version of the file, but you are not obligated to do so. If 00033 you do not wish to do so, delete this exception statement from 00034 your version. 00035 */ 00036 00037 #include "kmgroupware.h" 00038 00039 #include "kmmainwin.h" 00040 #include "kmmainwidget.h" 00041 #include "kmfoldertree.h" 00042 #include "kmcomposewin.h" 00043 #include <libkpimidentities/identity.h> 00044 #include <libkpimidentities/identitymanager.h> 00045 #include <libkdepim/email.h> 00046 #include "kmkernel.h" 00047 00048 #include <kurl.h> 00049 #include <kmessagebox.h> 00050 #include <dcopclient.h> 00051 #include <kdcopservicestarter.h> 00052 #include <kconfig.h> 00053 #include <kapplication.h> 00054 #include <kinputdialog.h> 00055 #include <kdebug.h> 00056 #include <qregexp.h> 00057 00058 #include <mimelib/enum.h> 00059 00060 #include <assert.h> 00061 00062 #include "korganizeriface_stub.h" 00063 00064 00065 // Handle KOrganizer connection 00066 static bool connectToKOrganizer(); 00067 static KOrganizerIface_stub* mKOrganizerIfaceStub; 00068 00069 00070 //----------------------------------------------------------------------------- 00071 KMGroupware::KMGroupware( QObject* parent, const char* name ) 00072 : QObject( parent, name ), mUseGroupware( false ) 00073 { 00074 // Make the connection to KOrganizer ready 00075 mKOrganizerIfaceStub = 0; 00076 kapp->dcopClient()->setNotifications( true ); 00077 connect( kapp->dcopClient(), SIGNAL( applicationRemoved( const QCString& ) ), 00078 this, SLOT( unregisteredFromDCOP( const QCString& ) ) ); 00079 00080 // Listen to config changes 00081 connect( kmkernel, SIGNAL( configChanged() ), this, SLOT( readConfig() ) ); 00082 } 00083 00084 //----------------------------------------------------------------------------- 00085 KMGroupware::~KMGroupware() 00086 { 00087 kapp->dcopClient()->setNotifications( false ); 00088 delete mKOrganizerIfaceStub; 00089 } 00090 00091 void KMGroupware::readConfig() 00092 { 00093 KConfigGroup options( KMKernel::config(), "Groupware" ); 00094 mUseGroupware = options.readBoolEntry( "Enabled", false ); 00095 } 00096 00097 bool KMGroupware::vPartFoundAndDecoded( KMMessage* msg, QString& s ) 00098 { 00099 assert( msg ); 00100 00101 if( ( DwMime::kTypeText == msg->type() && ( DwMime::kSubtypeVCal == msg->subtype() || 00102 DwMime::kSubtypeXVCard == msg->subtype() ) ) || 00103 ( DwMime::kTypeApplication == msg->type() && 00104 DwMime::kSubtypeOctetStream == msg->subtype() ) ) 00105 { 00106 s = QString::fromUtf8( msg->bodyDecoded() ); 00107 return true; 00108 } else if( DwMime::kTypeMultipart == msg->type() && 00109 (DwMime::kSubtypeMixed == msg->subtype() ) || 00110 (DwMime::kSubtypeAlternative == msg->subtype() )) 00111 { 00112 // kdDebug(5006) << "KMGroupware looking for TNEF data" << endl; 00113 DwBodyPart* dwPart = msg->findDwBodyPart( DwMime::kTypeApplication, 00114 DwMime::kSubtypeMsTNEF ); 00115 if( !dwPart ) 00116 dwPart = msg->findDwBodyPart( DwMime::kTypeApplication, 00117 DwMime::kSubtypeOctetStream ); 00118 if( dwPart ){ 00119 // kdDebug(5006) << "KMGroupware analyzing TNEF data" << endl; 00120 KMMessagePart msgPart; 00121 KMMessage::bodyPart(dwPart, &msgPart); 00122 if ( !connectToKOrganizer() ) 00123 kdError() << "DCOP error during KMGroupware::vPartFoundAndDecoded()\n"; 00124 else { 00125 s = mKOrganizerIfaceStub->msTNEFToVPart( msgPart.bodyDecodedBinary() ); 00126 return !s.isEmpty(); 00127 } 00128 } else { 00129 dwPart = msg->findDwBodyPart( DwMime::kTypeText, DwMime::kSubtypeVCal ); 00130 if (dwPart) { 00131 KMMessagePart msgPart; 00132 KMMessage::bodyPart(dwPart, &msgPart); 00133 s = msgPart.body(); 00134 return true; 00135 } 00136 } 00137 }else if( DwMime::kTypeMultipart == msg->type() && 00138 DwMime::kSubtypeMixed == msg->subtype() ) { 00139 // TODO: Something? 00140 } 00141 00142 return false; 00143 } 00144 00145 /* 00146 * Message part formatting 00147 */ 00148 00149 QString KMGroupware::vPartToHTML( const QString& /*iCal*/ ) 00150 { 00151 return "<b>This is an iCalendar attachment handled by the wrong bodypart" 00152 "formatterplugin.</b><p/>"; 00153 #if 0 00154 QString html; 00155 00156 if( mUseGroupware ) { 00157 // Call KOrganizer and make that format the mail 00158 if ( !connectToKOrganizer() ) { 00159 kdError() << "DCOP error during KMGroupware::processVCalRequest()\n"; 00160 } else { 00161 html = mKOrganizerIfaceStub->formatICal( iCal ); 00162 kdDebug(5006) << "KOrganizer call succeeded, html = " << html << endl; 00163 } 00164 } 00165 00166 return html; 00167 #endif 00168 } 00169 00170 QString KMGroupware::msTNEFToHTML( const QByteArray& tnef ) 00171 { 00172 QString html; 00173 00174 if( mUseGroupware ) { 00175 // Call KOrganizer and make that format the mail 00176 if ( !connectToKOrganizer() ) { 00177 kdError() << "DCOP error during KMGroupware::processVCalRequest()\n"; 00178 } else { 00179 html = mKOrganizerIfaceStub->formatTNEF( tnef ); 00180 kdDebug(5006) << "KOrganizer call succeeded, html = " << html << endl; 00181 } 00182 } 00183 00184 return html; 00185 } 00186 00187 /* 00188 * Groupware URL handling 00189 */ 00190 00191 static void iCalRequest( const QString& receiver, const QString& iCal, 00192 const QString& choice ) 00193 { 00194 #if 0 00195 // FIXME: Reinstate Outlook workaround 00196 // If we are in legacy mode, and there is more than one receiver, we 00197 // need to ask the user which address to use 00198 KMMessage* msgOld = mMainWidget->headers()->currentMsg(); 00199 KConfigGroup options( KMKernel::config(), "Groupware" ); 00200 QString fromAddress; // this variable is only used in legacy mode 00201 if( options.readBoolEntry( "LegacyMangleFromToHeaders", false ) ) { 00202 QStringList toAddresses = KPIM::splitEmailAddrList( msgOld->to() ); 00203 if( toAddresses.count() <= 1 ) 00204 // only one address: no problem, we can spare the user the dialog 00205 // and just take the from address 00206 fromAddress = msgOld->to(); 00207 else { 00208 // We have more than one To: address and are in legacy mode. Next 00209 // try is to search the identities for one of the email addresses 00210 // in the toAddresses list. 00211 for( QStringList::Iterator sit = toAddresses.begin(); 00212 sit != toAddresses.end(); ++sit ) { 00213 if( KPIM::getEmailAddr( *sit ) == 00214 kmkernel->identityManager()->defaultIdentity().emailAddr().local8Bit() ) { 00215 // our default identity was contained in the To: list, 00216 // copy that from To: to From: 00217 fromAddress = *sit; 00218 break; // We are done 00219 } 00220 } 00221 00222 // If we still haven't found anything, we have to ask the user 00223 // what to do. 00224 if( fromAddress.isEmpty() ) { 00225 bool bOk; 00226 fromAddress = KInputDialog::getItem( i18n( "Select Address" ), 00227 i18n( "In order to let Outlook recognize you as the receiver, you need to indicate which one of the following addresses is your email address:" ), 00228 toAddresses, 0, false, &bOk, 00229 kmkernel->mainWin() ); 00230 if( !bOk ) 00231 // If the user didn't select anything, just take the 00232 // first one so that we have something at all. 00233 fromAddress = toAddresses.first(); 00234 } 00235 } 00236 } 00237 #endif 00238 00239 if ( !connectToKOrganizer() ) 00240 kdError() << "DCOP error during KMGroupware::processVCalRequest()\n"; 00241 else { 00242 bool rc = mKOrganizerIfaceStub->eventRequest( choice, receiver, iCal ); 00243 kdDebug(5006) << "KOrganizer call succeeded, rc = " << rc << endl; 00244 00245 #if 0 00246 // TODO(bo): We need to delete the msg somehow 00247 if( rc && mMainWidget ) mMainWidget->slotTrashMsg(); 00248 #endif 00249 } 00250 } 00251 00252 static void iCalReply( const QString& iCal ) 00253 { 00254 bool event; 00255 if( iCal.find( QRegExp( "BEGIN:\\s*VEVENT" ) ) != -1 ) 00256 event = true; 00257 else if( iCal.find( QRegExp( "BEGIN:\\s*VTODO" ) ) != -1 ) 00258 event = false; 00259 else { 00260 kdDebug(5006) << "processVCalReply called with something that is not a iCal\n"; 00261 return; 00262 } 00263 00264 // Step 1: call Organizer 00265 if ( !connectToKOrganizer() ) 00266 kdError() << "DCOP error during KMGroupware::processVCalReply()\n"; 00267 else { 00268 bool rc = mKOrganizerIfaceStub->eventReply( iCal ); 00269 kdDebug(5006) << "KOrganizer call succeeded, rc = " << rc << endl; 00270 00271 // step 2: inform user that Organizer was updated 00272 KMessageBox::information( kmkernel->mainWin(), 00273 (event ? 00274 i18n("The answer was registered in your calendar.") : 00275 i18n("The answer was registered in your task list.")), 00276 QString::null, "groupwareBox"); 00277 00278 #if 0 00279 // An answer was saved, so trash the message 00280 if( mMainWidget ) mMainWidget->slotTrashMsg(); 00281 #endif 00282 } 00283 } 00284 00285 static void iCalCancel( const QString& iCal ) 00286 { 00287 if ( !connectToKOrganizer() ) 00288 kdError() << "DCOP error during KMGroupware::iCalCancel()\n"; 00289 else { 00290 bool rc = mKOrganizerIfaceStub->cancelEvent( iCal ); 00291 kdDebug(5006) << "KOrganizer call succeeded, rc = " << rc << endl; 00292 00293 #if 0 00294 // An answer was saved, so trash the message 00295 if( mMainWidget ) mMainWidget->slotTrashMsg(); 00296 #endif 00297 } 00298 } 00299 00300 // Return the part up until the first '_' or '#', or all of it 00301 // Chop off the used part of the string 00302 static QString urlPart( QString& aUrl ) 00303 { 00304 QString result; 00305 int i = aUrl.find( '_' ); 00306 if( i < 0 ) i = aUrl.find( '#' ); 00307 if( i < 0 ) { 00308 // Just take the remaining part 00309 result = aUrl; 00310 aUrl.truncate( 0 ); 00311 } else { 00312 result = aUrl.left( i ); 00313 aUrl = aUrl.mid( i + 1 ); 00314 } 00315 return result; 00316 } 00317 00318 bool KMGroupware::handleLink( const KURL &url, KMMessage* msg ) 00319 { 00320 QString aUrl = url.path(); 00321 if( urlPart( aUrl ) != "groupware" ) return false; 00322 QString gwAction = urlPart( aUrl ); 00323 00324 // Find the part of the message with the iCal 00325 QString iCal; 00326 if( !vPartFoundAndDecoded( msg, iCal ) ) { 00327 kdDebug(5006) << "Could not find the iCal for this link\n"; 00328 return false; 00329 } 00330 00331 if( gwAction == "request" ) { 00332 // Find the receiver if we can 00333 QString receiver; 00334 if( msg ) { 00335 KPIM::Identity ident = 00336 kmkernel->identityManager()->identityForAddress( msg->to() ); 00337 if( ident != KPIM::Identity::null ) { 00338 receiver = ident.emailAddr(); 00339 } else { 00340 QStringList addrs = KPIM::splitEmailAddrList( msg->to() ); 00341 if( addrs.count() == 1 ) 00342 // Don't ask the user to choose between 1 items 00343 receiver = addrs[0]; 00344 else { 00345 bool ok; 00346 receiver = KInputDialog:: 00347 getItem( i18n("Select Address"), 00348 i18n("None of your identities match the receiver " 00349 "of this message,<br> please choose which of " 00350 "the following addresses is yours:"), 00351 addrs, 0, FALSE, &ok, kmkernel->mainWin() ); 00352 if( !ok ) return false; 00353 } 00354 } 00355 } 00356 iCalRequest( receiver, iCal, urlPart( aUrl ) ); 00357 } else if( gwAction == "reply" ) 00358 iCalReply( iCal ); 00359 else if( gwAction == "cancel" ) 00360 iCalCancel( iCal ); 00361 else { 00362 // What what what? 00363 kdDebug(5006) << "Unknown groupware action " << gwAction << endl; 00364 return false; 00365 } 00366 00367 return true; 00368 } 00369 00370 /* 00371 * Handle connection to KOrganizer. 00372 */ 00373 00374 static const QCString dcopObjectId = "KOrganizerIface"; 00375 00376 static bool connectToKOrganizer() 00377 { 00378 if ( !mKOrganizerIfaceStub ) { 00379 QString error; 00380 QCString dcopService; 00381 int result = KDCOPServiceStarter::self()-> 00382 findServiceFor( "DCOP/Organizer", QString::null, 00383 QString::null, &error, &dcopService ); 00384 if ( result != 0 ) { 00385 kdDebug(5800) << "Could not connect to KOrganizer\n"; 00386 // TODO: You might want to show "error" (if not empty) here, 00387 // using e.g. KMessageBox 00388 return false; 00389 } 00390 00391 QCString dummy; 00392 // OK, so korganizer (or kontact) is running. Now ensure the object we want is available. 00393 if ( !kapp->dcopClient()->findObject( dcopService, dcopObjectId, "", QByteArray(), dcopService, dummy ) ) { 00394 KDCOPServiceStarter::self()->startServiceFor( "DCOP/Organizer", QString::null, 00395 QString::null, &error, &dcopService ); 00396 if( !kapp->dcopClient()->findObject( dcopService, dcopObjectId, "", QByteArray(), dcopService, dummy ) ) 00397 return false; 00398 } 00399 00400 mKOrganizerIfaceStub = new KOrganizerIface_stub( kapp->dcopClient(), 00401 dcopService, 00402 dcopObjectId ); 00403 } 00404 00405 return ( mKOrganizerIfaceStub != 0 ); 00406 } 00407 00408 void KMGroupware::unregisteredFromDCOP( const QCString& appId ) 00409 { 00410 if ( mKOrganizerIfaceStub && mKOrganizerIfaceStub->app() == appId ) { 00411 // Delete the stub so that the next time we need the organizer, 00412 // we'll know that we need to start a new one. 00413 delete mKOrganizerIfaceStub; 00414 mKOrganizerIfaceStub = 0; 00415 } 00416 } 00417 00418 00419 #include "kmgroupware.moc"
KDE Logo
This file is part of the documentation for kmail Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Oct 1 15:19:21 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003