kmail Library API Documentation

kmailicalifaceimpl.cpp

00001 /* 00002 This file is part of KMail. 00003 00004 Copyright (c) 2003 Steffen Hansen <steffen@klaralvdalens-datakonsult.se> 00005 Copyright (c) 2003 - 2004 Bo Thorsen <bo@klaralvdalens-datakonsult.se> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public License 00018 along with this library; see the file COPYING.LIB. If not, write to 00019 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00020 Boston, MA 02111-1307, USA. 00021 00022 In addition, as a special exception, the copyright holders give 00023 permission to link the code of this program with any edition of 00024 the Qt library by Trolltech AS, Norway (or with modified versions 00025 of Qt that use the same license as Qt), and distribute linked 00026 combinations including the two. You must obey the GNU General 00027 Public License in all respects for all of the code used other than 00028 Qt. If you modify this file, you may extend this exception to 00029 your version of the file, but you are not obligated to do so. If 00030 you do not wish to do so, delete this exception statement from 00031 your version. 00032 */ 00033 00034 #ifdef HAVE_CONFIG_H 00035 #include <config.h> 00036 #endif 00037 00038 #include "kmailicalifaceimpl.h" 00039 #include "kmfoldertree.h" 00040 #include "kmfolderdir.h" 00041 #include "kmgroupware.h" 00042 #include "kmfoldermgr.h" 00043 #include "kmcommands.h" 00044 #include "kmfolderindex.h" 00045 #include "kmmsgdict.h" 00046 #include "kmfolderimap.h" 00047 #include "globalsettings.h" 00048 #include "kmacctmgr.h" 00049 00050 #include <mimelib/enum.h> 00051 00052 #include <kdebug.h> 00053 #include <kiconloader.h> 00054 #include <dcopclient.h> 00055 #include <kmessagebox.h> 00056 #include <kconfig.h> 00057 #include <qmap.h> 00058 00059 // Local helper methods 00060 static void vPartMicroParser( const QString& str, QString& s ); 00061 static void reloadFolderTree(); 00062 00063 // The index in this array is the KMail::FolderContentsType enum 00064 static const struct { 00065 const char* contentsTypeStr; // the string used in the DCOP interface 00066 } s_folderContentsType[] = { 00067 { "Mail" }, 00068 { "Calendar" }, 00069 { "Contact" }, 00070 { "Note" }, 00071 { "Task" }, 00072 { "Journal" } 00073 }; 00074 00075 static QString folderContentsType( KMail::FolderContentsType type ) 00076 { 00077 return s_folderContentsType[type].contentsTypeStr; 00078 } 00079 00080 static KMail::FolderContentsType folderContentsType( const QString& type ) 00081 { 00082 for ( uint i = 0 ; i < sizeof s_folderContentsType / sizeof *s_folderContentsType; ++i ) 00083 if ( type == s_folderContentsType[i].contentsTypeStr ) 00084 return static_cast<KMail::FolderContentsType>( i ); 00085 return KMail::ContentsTypeMail; 00086 } 00087 00088 /* 00089 This interface have three parts to it - libkcal interface; 00090 kmail interface; and helper functions. 00091 00092 The libkcal interface and the kmail interface have the same three 00093 methods: add, delete and refresh. The only difference is that the 00094 libkcal interface is used from the IMAP resource in libkcal and 00095 the kmail interface is used from the groupware object in kmail. 00096 */ 00097 00098 KMailICalIfaceImpl::KMailICalIfaceImpl() 00099 : DCOPObject( "KMailICalIface" ), QObject( 0, "KMailICalIfaceImpl" ), 00100 mContacts( 0 ), mCalendar( 0 ), mNotes( 0 ), mTasks( 0 ), mJournals( 0 ), 00101 mFolderLanguage( 0 ), mUseResourceIMAP( false ), mHideFolders( true ) 00102 { 00103 // Listen to config changes 00104 connect( kmkernel, SIGNAL( configChanged() ), this, SLOT( readConfig() ) ); 00105 00106 mExtraFolders.setAutoDelete( true ); 00107 mAccumulators.setAutoDelete( true ); 00108 } 00109 00110 // Receive an iCal or vCard from the resource 00111 bool KMailICalIfaceImpl::addIncidence( const QString& type, 00112 const QString& folder, 00113 const QString& uid, 00114 const QString& ical ) 00115 { 00116 kdDebug(5006) << "KMailICalIfaceImpl::addIncidence( " << type << ", " 00117 << uid << ", " << ical << " )" << endl; 00118 00119 if( !mUseResourceIMAP ) 00120 return false; 00121 00122 bool rc = false; 00123 00124 if ( !mInTransit.contains( uid ) ) { 00125 mInTransit.insert( uid, true ); 00126 } 00127 00128 // Find the folder 00129 KMFolder* f = folderFromType( type, folder ); 00130 if( f ) { 00131 // Make a new message for the incidence 00132 KMMessage* msg = new KMMessage(); 00133 msg->initHeader(); 00134 msg->setType( DwMime::kTypeText ); 00135 if( f == mContacts ) { 00136 msg->setSubtype( DwMime::kSubtypeXVCard ); 00137 msg->setHeaderField( "Content-Type", "Text/X-VCard; charset=\"utf-8\"" ); 00138 msg->setSubject( "vCard " + uid ); 00139 } else { 00140 msg->setSubtype( DwMime::kSubtypeVCal ); 00141 msg->setHeaderField("Content-Type", 00142 "text/calendar; method=REQUEST; charset=\"utf-8\""); 00143 msg->setSubject( "iCal " + uid ); 00144 } 00145 msg->setBodyEncoded( ical.utf8() ); 00146 00147 // Mark the message as read and store it in the folder 00148 msg->touch(); 00149 f->addMsg( msg ); 00150 rc = true; 00151 } else 00152 kdError(5006) << "Not an IMAP resource folder" << endl; 00153 00154 return rc; 00155 } 00156 00157 // The resource orders a deletion 00158 bool KMailICalIfaceImpl::deleteIncidence( const QString& type, 00159 const QString& folder, 00160 const QString& uid ) 00161 { 00162 if( !mUseResourceIMAP ) 00163 return false; 00164 00165 kdDebug(5006) << "KMailICalIfaceImpl::deleteIncidence( " << type << ", " 00166 << uid << " )" << endl; 00167 00168 bool rc = false; 00169 00170 // Find the folder and the incidence in it 00171 KMFolder* f = folderFromType( type, folder ); 00172 if( f ) { 00173 KMMessage* msg = findMessageByUID( uid, f ); 00174 if( msg ) { 00175 // Message found - delete it and return happy 00176 deleteMsg( msg ); 00177 rc = true; 00178 mUIDToSerNum.remove( uid ); 00179 } else 00180 kdDebug(5006) << type << " not found, cannot remove uid " << uid << endl; 00181 } else 00182 kdError(5006) << "Not an IMAP resource folder" << endl; 00183 00184 return rc; 00185 } 00186 00187 // The resource asks for a full list of incidences 00188 QStringList KMailICalIfaceImpl::incidences( const QString& type, 00189 const QString& folder ) 00190 { 00191 if( !mUseResourceIMAP ) 00192 return QStringList(); 00193 00194 kdDebug(5006) << "KMailICalIfaceImpl::incidences( " << type << ", " 00195 << folder << " )" << endl; 00196 QStringList ilist; 00197 00198 KMFolder* f = folderFromType( type, folder ); 00199 if ( f ) { 00200 f->open(); 00201 QString s; 00202 for( int i=0; i<f->count(); ++i ) { 00203 bool unget = !f->isMessage(i); 00204 KMMessage *msg = f->getMsg( i ); 00205 Q_ASSERT( msg ); 00206 if( msg->isComplete() ) { 00207 if( KMGroupware::vPartFoundAndDecoded( msg, s ) ) { 00208 QString uid( "UID" ); 00209 vPartMicroParser( s, uid ); 00210 const Q_UINT32 sernum = msg->getMsgSerNum(); 00211 kdDebug(5006) << "Insert uid: " << uid << endl; 00212 mUIDToSerNum.insert( uid, sernum ); 00213 ilist << s; 00214 } 00215 if( unget ) f->unGetMsg(i); 00216 } else { 00217 // message needs to be gotten first, once it arrives, we'll 00218 // accumulate it and add it to the resource 00219 if ( !mAccumulators[ folder ] ) 00220 mAccumulators.insert( folder, new Accumulator( type, folder, f->count() )); 00221 if ( unget ) mTheUnGetMes.insert( msg->getMsgSerNum(), true ); 00222 FolderJob *job = msg->parent()->createJob( msg ); 00223 connect( job, SIGNAL( messageRetrieved( KMMessage* ) ), 00224 this, SLOT( slotMessageRetrieved( KMMessage* ) ) ); 00225 job->start(); 00226 } 00227 } 00228 } 00229 return ilist; 00230 } 00231 00232 void KMailICalIfaceImpl::slotMessageRetrieved( KMMessage* msg ) 00233 { 00234 if( !msg ) return; 00235 00236 KMFolder *parent = msg->parent(); 00237 Q_ASSERT( parent ); 00238 Q_UINT32 sernum = msg->getMsgSerNum(); 00239 00240 // do we have an accumulator for this folder? 00241 Accumulator *ac = mAccumulators.find( parent->location() ); 00242 if( ac ) { 00243 QString s; 00244 if ( !KMGroupware::vPartFoundAndDecoded( msg, s ) ) return; 00245 QString uid( "UID" ); 00246 vPartMicroParser( s, uid ); 00247 const Q_UINT32 sernum = msg->getMsgSerNum(); 00248 mUIDToSerNum.insert( uid, sernum ); 00249 ac->add( s ); 00250 if( ac->isFull() ) { 00251 /* if this was the last one we were waiting for, tell the resource 00252 * about the new incidences and clean up. */ 00253 asyncLoadResult( ac->incidences, ac->type, ac->folder ); 00254 mAccumulators.remove( ac->folder ); // autodelete 00255 } 00256 } else { 00257 /* We are not accumulating for this folder, so this one was added 00258 * by KMail. Do your thang. */ 00259 slotIncidenceAdded( msg->parent(), msg->getMsgSerNum() ); 00260 } 00261 00262 if ( mTheUnGetMes.contains( sernum ) ) { 00263 mTheUnGetMes.remove( sernum ); 00264 int i = 0; 00265 KMFolder* folder = 0; 00266 kmkernel->msgDict()->getLocation( sernum, &folder, &i ); 00267 folder->unGetMsg( i ); 00268 } 00269 } 00270 00271 QStringList KMailICalIfaceImpl::subresources( const QString& type ) 00272 { 00273 QStringList lst; 00274 00275 // Add the default one 00276 KMFolder* f = folderFromType( type, QString::null ); 00277 if ( f ) 00278 lst << f->location(); 00279 00280 // Add the extra folders 00281 KMail::FolderContentsType t = folderContentsType( type ); 00282 QDictIterator<ExtraFolder> it( mExtraFolders ); 00283 for ( ; it.current(); ++it ) 00284 if ( it.current()->type == t ) 00285 lst << it.current()->folder->location(); 00286 00287 return lst; 00288 } 00289 00290 bool KMailICalIfaceImpl::isWritableFolder( const QString& type, 00291 const QString& resource ) 00292 { 00293 KMFolder* f = folderFromType( type, resource ); 00294 if ( !f ) 00295 // Definitely not writable 00296 return false; 00297 00298 return !f->isReadOnly(); 00299 } 00300 00301 bool KMailICalIfaceImpl::update( const QString& type, const QString& folder, 00302 const QStringList& entries ) 00303 { 00304 if( !mUseResourceIMAP ) 00305 return false; 00306 00307 if( entries.count() & 2 == 1 ) 00308 // Something is wrong - an odd amount of strings should not happen 00309 return false; 00310 00311 QStringList::ConstIterator it = entries.begin(); 00312 while( true ) { 00313 // Read them in pairs and call the single update method 00314 QString uid, entry; 00315 if( it == entries.end() ) 00316 break; 00317 uid = *it; 00318 ++it; 00319 if( it == entries.end() ) 00320 break; 00321 entry = *it; 00322 ++it; 00323 00324 if( !update( type, folder, uid, entry ) ) 00325 // Some error happened 00326 return false; 00327 } 00328 00329 return true; 00330 } 00331 00332 bool KMailICalIfaceImpl::update( const QString& type, const QString& folder, 00333 const QString& uid, const QString& entry ) 00334 { 00335 if( !mUseResourceIMAP ) 00336 return false; 00337 00338 kdDebug(5006) << "Update( " << type << ", " << folder << ", " << uid << ")\n"; 00339 bool rc = true; 00340 00341 if ( !mInTransit.contains( uid ) ) { 00342 mInTransit.insert( uid, true ); 00343 } else { 00344 // this is reentrant, if a new update comes in, we'll just 00345 // replace older ones 00346 mPendingUpdates.insert( uid, entry ); 00347 return rc; 00348 } 00349 00350 // Find the folder and the incidence in it 00351 KMFolder* f = folderFromType( type, folder ); 00352 if( f ) { 00353 KMMessage* msg = findMessageByUID( uid, f ); 00354 if( msg ) { 00355 // Message found - update it 00356 deleteMsg( msg ); 00357 mUIDToSerNum.remove( uid ); 00358 } else { 00359 kdDebug(5006) << type << " not found, cannot update uid " << uid << endl; 00360 } 00361 addIncidence( type, folder, uid, entry ); 00362 } else { 00363 kdError(5006) << "Not an IMAP resource folder" << endl; 00364 rc = false; 00365 } 00366 return rc; 00367 } 00368 00369 // KMail added a file to one of the groupware folders 00370 void KMailICalIfaceImpl::slotIncidenceAdded( KMFolder* folder, 00371 Q_UINT32 sernum ) 00372 { 00373 if( !mUseResourceIMAP ) 00374 return; 00375 00376 QString type = icalFolderType( folder ); 00377 if( !type.isEmpty() ) { 00378 // Get the index of the mail 00379 int i = 0; 00380 KMFolder* aFolder = 0; 00381 kmkernel->msgDict()->getLocation( sernum, &aFolder, &i ); 00382 assert( folder == aFolder ); 00383 00384 // Read the iCal or vCard 00385 bool unget = !folder->isMessage( i ); 00386 QString s; 00387 KMMessage *msg = folder->getMsg( i ); 00388 if( !msg ) return; 00389 if( msg->isComplete() ) { 00390 if ( !KMGroupware::vPartFoundAndDecoded( msg, s ) ) return; 00391 kdDebug(5006) << "Emitting DCOP signal incidenceAdded( " << type 00392 << ", " << folder->location() << ", " << s << " )" << endl; 00393 QString uid( "UID" ); 00394 vPartMicroParser( s, uid ); 00395 const Q_UINT32 sernum = msg->getMsgSerNum(); 00396 kdDebug(5006) << "Insert uid: " << uid << endl; 00397 mUIDToSerNum.insert( uid, sernum ); 00398 // tell the resource if we didn't trigger this ourselves 00399 if( !mInTransit.contains( uid ) ) 00400 incidenceAdded( type, folder->location(), s ); 00401 else 00402 mInTransit.remove( uid ); 00403 00404 // Check if new updates have since arrived, if so, trigger them 00405 if ( mPendingUpdates.contains( uid ) ) { 00406 kdDebug(5006) << "KMailICalIfaceImpl::slotIncidenceAdded - Pending Update" << endl; 00407 QString entry = mPendingUpdates[ uid ]; 00408 mPendingUpdates.remove( uid ); 00409 update( type, folder->location(), uid, entry ); 00410 } 00411 } else { 00412 // go get the rest of it, then try again 00413 if ( unget ) mTheUnGetMes.insert( msg->getMsgSerNum(), true ); 00414 FolderJob *job = msg->parent()->createJob( msg ); 00415 connect( job, SIGNAL( messageRetrieved( KMMessage* ) ), 00416 this, SLOT( slotMessageRetrieved( KMMessage* ) ) ); 00417 job->start(); 00418 return; 00419 } 00420 if( unget ) folder->unGetMsg(i); 00421 } else 00422 kdError(5006) << "Not an IMAP resource folder" << endl; 00423 } 00424 00425 // KMail deleted a file 00426 void KMailICalIfaceImpl::slotIncidenceDeleted( KMFolder* folder, 00427 Q_UINT32 sernum ) 00428 { 00429 if( !mUseResourceIMAP ) 00430 return; 00431 00432 QString type = icalFolderType( folder ); 00433 if( !type.isEmpty() ) { 00434 // Get the index of the mail 00435 int i = 0; 00436 KMFolder* aFolder = 0; 00437 kmkernel->msgDict()->getLocation( sernum, &aFolder, &i ); 00438 assert( folder == aFolder ); 00439 00440 // Read the iCal or vCard 00441 bool unget = !folder->isMessage( i ); 00442 QString s; 00443 if( KMGroupware::vPartFoundAndDecoded( folder->getMsg( i ), s ) ) { 00444 QString uid( "UID" ); 00445 vPartMicroParser( s, uid ); 00446 kdDebug(5006) << "Emitting DCOP signal incidenceDeleted( " 00447 << type << ", " << folder->location() << ", " << uid 00448 << " )" << endl; 00449 if( !mInTransit.contains( uid ) ) // we didn't delete it ourselves 00450 incidenceDeleted( type, folder->location(), uid ); 00451 } 00452 if( unget ) folder->unGetMsg(i); 00453 } else 00454 kdError(5006) << "Not a groupware folder" << endl; 00455 } 00456 00457 // KMail orders a refresh 00458 void KMailICalIfaceImpl::slotRefresh( const QString& type ) 00459 { 00460 if( mUseResourceIMAP ) { 00461 signalRefresh( type, QString::null /* PENDING(bo) folder->location() */ ); 00462 kdDebug(5006) << "Emitting DCOP signal signalRefresh( " << type << " )" << endl; 00463 } 00464 } 00465 00466 00467 /**************************** 00468 * The folder and message stuff code 00469 */ 00470 00471 KMFolder* KMailICalIfaceImpl::folderFromType( const QString& type, 00472 const QString& folder ) 00473 { 00474 if( mUseResourceIMAP ) { 00475 KMFolder* f = extraFolder( type, folder ); 00476 if ( f ) 00477 return f; 00478 00479 if( type == "Calendar" ) f = mCalendar; 00480 else if( type == "Contact" ) f = mContacts; 00481 else if( type == "Note" ) f = mNotes; 00482 else if( type == "Task" || type == "Todo" ) f = mTasks; 00483 else if( type == "Journal" ) f = mJournals; 00484 00485 if ( f && ( folder.isEmpty() || folder == f->location() ) ) 00486 return f; 00487 00488 kdError(5006) << "No folder ( " << type << ", " << folder << " )\n"; 00489 } 00490 00491 return 0; 00492 } 00493 00494 00495 // Returns true if folder is a resource folder. If the resource isn't enabled 00496 // this always returns false 00497 bool KMailICalIfaceImpl::isResourceImapFolder( KMFolder* folder ) const 00498 { 00499 return mUseResourceIMAP && folder && 00500 ( folder == mCalendar || folder == mTasks || folder == mJournals || 00501 folder == mNotes || folder == mContacts ); 00502 } 00503 00504 bool KMailICalIfaceImpl::hideResourceImapFolder( KMFolder* folder ) const 00505 { 00506 return mHideFolders && isResourceImapFolder( folder ); 00507 } 00508 00509 KFolderTreeItem::Type KMailICalIfaceImpl::folderType( KMFolder* folder ) const 00510 { 00511 if( mUseResourceIMAP && folder ) { 00512 if( folder == mCalendar ) 00513 return KFolderTreeItem::Calendar; 00514 else if( folder == mContacts ) 00515 return KFolderTreeItem::Contacts; 00516 else if( folder == mNotes ) 00517 return KFolderTreeItem::Notes; 00518 else if( folder == mTasks ) 00519 return KFolderTreeItem::Tasks; 00520 else if( folder == mJournals ) 00521 return KFolderTreeItem::Journals; 00522 } 00523 00524 return KFolderTreeItem::Other; 00525 } 00526 00527 00528 QString KMailICalIfaceImpl::icalFolderType( KMFolder* folder ) const 00529 { 00530 if( mUseResourceIMAP && folder ) { 00531 if( folder == mCalendar ) 00532 return "Calendar"; 00533 else if( folder == mContacts ) 00534 return "Contact"; 00535 else if( folder == mNotes ) 00536 return "Note"; 00537 else if( folder == mTasks ) 00538 return "Task"; 00539 else if( folder == mJournals ) 00540 return "Journal"; 00541 else { 00542 ExtraFolder* ef = mExtraFolders.find( folder->location() ); 00543 if ( ef != 0 ) 00544 return folderContentsType( ef->type ); 00545 } 00546 } 00547 00548 return QString::null; 00549 } 00550 00551 00552 // Global tables of foldernames is different languages 00553 // For now: 0->English, 1->German, 2->French, 3->Dutch 00554 static QMap<KFolderTreeItem::Type,QString> folderNames[4]; 00555 QString KMailICalIfaceImpl::folderName( KFolderTreeItem::Type type, int language ) const 00556 { 00557 static bool folderNamesSet = false; 00558 if( !folderNamesSet ) { 00559 folderNamesSet = true; 00560 /* NOTE: If you add something here, you also need to update 00561 GroupwarePage in configuredialog.cpp */ 00562 00563 // English 00564 folderNames[0][KFolderTreeItem::Calendar] = QString::fromLatin1("Calendar"); 00565 folderNames[0][KFolderTreeItem::Tasks] = QString::fromLatin1("Tasks"); 00566 folderNames[0][KFolderTreeItem::Journals] = QString::fromLatin1("Journal"); 00567 folderNames[0][KFolderTreeItem::Contacts] = QString::fromLatin1("Contacts"); 00568 folderNames[0][KFolderTreeItem::Notes] = QString::fromLatin1("Notes"); 00569 00570 // German 00571 folderNames[1][KFolderTreeItem::Calendar] = QString::fromLatin1("Kalender"); 00572 folderNames[1][KFolderTreeItem::Tasks] = QString::fromLatin1("Aufgaben"); 00573 folderNames[1][KFolderTreeItem::Journals] = QString::fromLatin1("Journal"); 00574 folderNames[1][KFolderTreeItem::Contacts] = QString::fromLatin1("Kontakte"); 00575 folderNames[1][KFolderTreeItem::Notes] = QString::fromLatin1("Notizen"); 00576 00577 // French 00578 folderNames[2][KFolderTreeItem::Calendar] = QString::fromLatin1("Calendrier"); 00579 folderNames[2][KFolderTreeItem::Tasks] = QString::fromLatin1("Tāches"); 00580 folderNames[2][KFolderTreeItem::Journals] = QString::fromLatin1("Journal"); 00581 folderNames[2][KFolderTreeItem::Contacts] = QString::fromLatin1("Contacts"); 00582 folderNames[2][KFolderTreeItem::Notes] = QString::fromLatin1("Notes"); 00583 00584 // Dutch 00585 folderNames[3][KFolderTreeItem::Calendar] = QString::fromLatin1("Agenda"); 00586 folderNames[3][KFolderTreeItem::Tasks] = QString::fromLatin1("Taken"); 00587 folderNames[3][KFolderTreeItem::Journals] = QString::fromLatin1("Logboek"); 00588 folderNames[3][KFolderTreeItem::Contacts] = QString::fromLatin1("Contactpersonen"); 00589 folderNames[3][KFolderTreeItem::Notes] = QString::fromLatin1("Notities"); 00590 } 00591 00592 if( language < 0 || language > 3 ) { 00593 return folderNames[mFolderLanguage][type]; 00594 } 00595 else { 00596 return folderNames[language][type]; 00597 } 00598 } 00599 00600 00601 // Find message matching a given UID 00602 KMMessage *KMailICalIfaceImpl::findMessageByUID( const QString& uid, KMFolder* folder ) 00603 { 00604 if( !folder || !mUIDToSerNum.contains( uid ) ) return 0; 00605 int i; 00606 KMFolder *aFolder; 00607 kmkernel->msgDict()->getLocation( mUIDToSerNum[uid], &aFolder, &i ); 00608 Q_ASSERT( aFolder == folder ); 00609 return folder->getMsg( i ); 00610 } 00611 00612 void KMailICalIfaceImpl::deleteMsg( KMMessage *msg ) 00613 { 00614 if( !msg ) return; 00615 // Commands are now delayed; can't use that anymore, we need immediate deletion 00616 //( new KMDeleteMsgCommand( msg->parent(), msg ) )->start(); 00617 KMFolder *srcFolder = msg->parent(); 00618 int idx = srcFolder->find(msg); 00619 assert(idx != -1); 00620 srcFolder->removeMsg(idx); 00621 delete msg; 00622 } 00623 00624 void KMailICalIfaceImpl::folderContentsTypeChanged( KMFolder* folder, 00625 KMail::FolderContentsType contentsType ) 00626 { 00627 kdDebug(5006) << "folderContentsTypeChanged( " << folder->name() 00628 << ", " << contentsType << ")\n"; 00629 00630 // Find previous type of this folder 00631 ExtraFolder* ef = mExtraFolders.find( folder->location() ); 00632 if ( ( ef && ef->type == contentsType ) || ( !ef && contentsType == 0 ) ) 00633 // Nothing to tell! 00634 return; 00635 00636 if ( ef ) { 00637 // Notify that the old folder resource is no longer available 00638 subresourceDeleted(folderContentsType( ef->type ), folder->location() ); 00639 00640 if ( contentsType == 0 ) { 00641 // Delete the old entry, stop listening and stop here 00642 mExtraFolders.remove( folder->location() ); 00643 folder->disconnect( this ); 00644 return; 00645 } 00646 00647 // So the type changed to another groupware type. 00648 // Set the entry to the new type 00649 ef->type = contentsType; 00650 } else { 00651 // Make a new entry for the list 00652 ef = new ExtraFolder( folder, contentsType ); 00653 mExtraFolders.insert( folder->location(), ef ); 00654 00655 // avoid multiple connections 00656 disconnect( folder, SIGNAL( msgAdded( KMFolder*, Q_UINT32 ) ), 00657 this, SLOT( slotIncidenceAdded( KMFolder*, Q_UINT32 ) ) ); 00658 disconnect( folder, SIGNAL( msgRemoved( KMFolder*, Q_UINT32 ) ), 00659 this, SLOT( slotIncidenceDeleted( KMFolder*, Q_UINT32 ) ) ); 00660 00661 // And listen to changes from it 00662 connect( folder, SIGNAL( msgAdded( KMFolder*, Q_UINT32 ) ), 00663 this, SLOT( slotIncidenceAdded( KMFolder*, Q_UINT32 ) ) ); 00664 connect( folder, SIGNAL( msgRemoved( KMFolder*, Q_UINT32 ) ), 00665 this, SLOT( slotIncidenceDeleted( KMFolder*, Q_UINT32 ) ) ); 00666 } 00667 00668 // Tell about the new resource 00669 subresourceAdded( folderContentsType( contentsType ), folder->location() ); 00670 } 00671 00672 KMFolder* KMailICalIfaceImpl::extraFolder( const QString& type, 00673 const QString& folder ) 00674 { 00675 // If an extra folder exists that match the type and folder location, 00676 // use that 00677 int t = folderContentsType( type ); 00678 if ( t < 1 || t > 5 ) 00679 return 0; 00680 00681 QDictIterator<ExtraFolder> it( mExtraFolders ); 00682 for ( ; it.current(); ++it ) 00683 if ( it.current()->type == t && 00684 it.current()->folder->location() == folder ) 00685 return it.current()->folder; 00686 00687 return 0; 00688 } 00689 00690 00691 /**************************** 00692 * The config stuff 00693 */ 00694 00695 void KMailICalIfaceImpl::readConfig() 00696 { 00697 bool enabled = GlobalSettings::theIMAPResourceEnabled(); 00698 00699 if( !enabled ) { 00700 if( mUseResourceIMAP == true ) { 00701 // Shutting down 00702 mUseResourceIMAP = false; 00703 cleanup(); 00704 reloadFolderTree(); 00705 } 00706 return; 00707 } 00708 00709 // Read remaining options 00710 const bool hideFolders = GlobalSettings::hideGroupwareFolders(); 00711 unsigned int folderLanguage = GlobalSettings::theIMAPResourceFolderLanguage(); 00712 if( folderLanguage > 3 ) folderLanguage = 0; 00713 QString parentName = GlobalSettings::theIMAPResourceFolderParent(); 00714 00715 // Find the folder parent 00716 KMFolderDir* folderParentDir; 00717 KMFolderType folderType; 00718 KMFolder* folderParent = kmkernel->findFolderById( parentName ); 00719 if( folderParent == 0 ) { 00720 // Parent folder not found. It was probably deleted. The user will have to 00721 // configure things again. 00722 kdDebug(5006) << "Groupware folder " << parentName << " not found. Groupware functionality disabled" << endl; 00723 // Or maybe the inbox simply wasn't created on the first startup 00724 KMAccount* account = kmkernel->acctMgr()->find( GlobalSettings::theIMAPResourceAccount() ); 00725 Q_ASSERT( account ); 00726 if ( account ) { 00727 // just in case we were connected already 00728 disconnect( account, SIGNAL( finishedCheck( bool, CheckStatus ) ), 00729 this, SLOT( slotCheckDone() ) ); 00730 connect( account, SIGNAL( finishedCheck( bool, CheckStatus ) ), 00731 this, SLOT( slotCheckDone() ) ); 00732 } 00733 mUseResourceIMAP = false; 00734 return; 00735 } else { 00736 folderParentDir = folderParent->createChildFolder(); 00737 folderType = folderParent->folderType(); 00738 } 00739 00740 // Make sure the folder parent has the subdirs 00741 bool makeSubFolders = false; 00742 KMFolderNode* node; 00743 node = folderParentDir->hasNamedFolder( folderName( KFolderTreeItem::Calendar, folderLanguage ) ); 00744 if( !node || node->isDir() ) { 00745 makeSubFolders = true; 00746 mCalendar = 0; 00747 } 00748 node = folderParentDir->hasNamedFolder( folderName( KFolderTreeItem::Tasks, folderLanguage ) ); 00749 if( !node || node->isDir() ) { 00750 makeSubFolders = true; 00751 mTasks = 0; 00752 } 00753 node = folderParentDir->hasNamedFolder( folderName( KFolderTreeItem::Journals, folderLanguage ) ); 00754 if( !node || node->isDir() ) { 00755 makeSubFolders = true; 00756 mJournals = 0; 00757 } 00758 node = folderParentDir->hasNamedFolder( folderName( KFolderTreeItem::Contacts, folderLanguage ) ); 00759 if( !node || node->isDir() ) { 00760 makeSubFolders = true; 00761 mContacts = 0; 00762 } 00763 node = folderParentDir->hasNamedFolder( folderName( KFolderTreeItem::Notes, folderLanguage ) ); 00764 if( !node || node->isDir() ) { 00765 makeSubFolders = true; 00766 mNotes = 0; 00767 } 00768 if( makeSubFolders ) { 00769 // Not all subfolders were there, so ask if we can make them 00770 if( KMessageBox::questionYesNo( 0, i18n("KMail will now create the required folders for the IMAP resource" 00771 " as subfolders of %1; if you do not want this, press \"No\"," 00772 " and the IMAP resource will be disabled").arg(folderParent!=0?folderParent->name():folderParentDir->name()), 00773 i18n("IMAP Resource Folders") ) == KMessageBox::No ) { 00774 00775 GlobalSettings::setTheIMAPResourceEnabled( false ); 00776 mUseResourceIMAP = false; 00777 mFolderParentDir = 0; 00778 mFolderParent = 0; 00779 reloadFolderTree(); 00780 return; 00781 } 00782 } 00783 00784 // Check if something changed 00785 if( mUseResourceIMAP && !makeSubFolders && mFolderParentDir == folderParentDir 00786 && mFolderType == folderType ) { 00787 // Nothing changed 00788 if ( hideFolders != mHideFolders ) { 00789 // Well, the folder hiding has changed 00790 mHideFolders = hideFolders; 00791 reloadFolderTree(); 00792 } 00793 return; 00794 } 00795 00796 // Make the new settings work 00797 mUseResourceIMAP = true; 00798 mFolderLanguage = folderLanguage; 00799 mFolderParentDir = folderParentDir; 00800 mFolderParent = folderParent; 00801 mFolderType = folderType; 00802 mHideFolders = hideFolders; 00803 00804 // Close the previous folders 00805 cleanup(); 00806 00807 // Set the new folders 00808 mCalendar = initFolder( KFolderTreeItem::Calendar, "GCa" ); 00809 mTasks = initFolder( KFolderTreeItem::Tasks, "GTa" ); 00810 mJournals = initFolder( KFolderTreeItem::Journals, "GTa" ); 00811 mContacts = initFolder( KFolderTreeItem::Contacts, "GCo" ); 00812 mNotes = initFolder( KFolderTreeItem::Notes, "GNo" ); 00813 00814 // Connect the expunged signal 00815 connect( mCalendar, SIGNAL( expunged() ), this, SLOT( slotRefreshCalendar() ) ); 00816 connect( mTasks, SIGNAL( expunged() ), this, SLOT( slotRefreshTasks() ) ); 00817 connect( mJournals, SIGNAL( expunged() ), this, SLOT( slotRefreshJournals() ) ); 00818 connect( mContacts, SIGNAL( expunged() ), this, SLOT( slotRefreshContacts() ) ); 00819 connect( mNotes, SIGNAL( expunged() ), this, SLOT( slotRefreshNotes() ) ); 00820 00821 // Bad hack 00822 connect( mNotes, SIGNAL( changed() ), this, SLOT( slotRefreshNotes() ) ); 00823 00824 // Make KOrganizer re-read everything 00825 slotRefresh( "Calendar" ); 00826 slotRefresh( "Task" ); 00827 slotRefresh( "Journal" ); 00828 slotRefresh( "Contact" ); 00829 slotRefresh( "Notes" ); 00830 00831 reloadFolderTree(); 00832 } 00833 00834 void KMailICalIfaceImpl::slotCheckDone() 00835 { 00836 QString parentName = GlobalSettings::theIMAPResourceFolderParent(); 00837 KMFolder* folderParent = kmkernel->findFolderById( parentName ); 00838 if ( folderParent ) // cool it exists now 00839 { 00840 KMAccount* account = kmkernel->acctMgr()->find( GlobalSettings::theIMAPResourceAccount() ); 00841 if ( account ) 00842 disconnect( account, SIGNAL( finishedCheck( bool, CheckStatus ) ), 00843 this, SLOT( slotCheckDone() ) ); 00844 readConfig(); 00845 } 00846 } 00847 00848 void KMailICalIfaceImpl::slotRefreshCalendar() { slotRefresh( "Calendar" ); } 00849 void KMailICalIfaceImpl::slotRefreshTasks() { slotRefresh( "Task" ); } 00850 void KMailICalIfaceImpl::slotRefreshJournals() { slotRefresh( "Journal" ); } 00851 void KMailICalIfaceImpl::slotRefreshContacts() { slotRefresh( "Contact" ); } 00852 void KMailICalIfaceImpl::slotRefreshNotes() { slotRefresh( "Notes" ); } 00853 00854 KMFolder* KMailICalIfaceImpl::initFolder( KFolderTreeItem::Type itemType, 00855 const char* typeString ) 00856 { 00857 // Figure out what type of folder this is supposed to be 00858 KMFolderType type = mFolderType; 00859 if( type == KMFolderTypeUnknown ) type = KMFolderTypeMaildir; 00860 00861 // Find the folder 00862 KMFolder* folder = 0; 00863 KMFolderNode* node = mFolderParentDir->hasNamedFolder( folderName( itemType ) ); 00864 if( node && !node->isDir() ) folder = static_cast<KMFolder*>(node); 00865 if( !folder ) { 00866 // The folder isn't there yet - create it 00867 folder = 00868 mFolderParentDir->createFolder( folderName( itemType ), false, type ); 00869 if( mFolderType == KMFolderTypeImap ) { 00870 KMFolderImap* parentFolder = static_cast<KMFolderImap*>( mFolderParent->storage() ); 00871 parentFolder->createFolder( folderName( itemType ) ); 00872 static_cast<KMFolderImap*>( folder->storage() )->setAccount( parentFolder->account() ); 00873 } 00874 } 00875 00876 if( folder->canAccess() != 0 ) { 00877 KMessageBox::sorry(0, i18n("You do not have read/write permission to your %1 folder.") 00878 .arg( folderName( itemType ) ) ); 00879 return 0; 00880 } 00881 folder->setType( typeString ); 00882 folder->setSystemFolder( true ); 00883 folder->open(); 00884 // avoid multiple connections 00885 disconnect( folder, SIGNAL( msgAdded( KMFolder*, Q_UINT32 ) ), 00886 this, SLOT( slotIncidenceAdded( KMFolder*, Q_UINT32 ) ) ); 00887 disconnect( folder, SIGNAL( msgRemoved( KMFolder*, Q_UINT32 ) ), 00888 this, SLOT( slotIncidenceDeleted( KMFolder*, Q_UINT32 ) ) ); 00889 // Setup the signals to listen for changes 00890 connect( folder, SIGNAL( msgAdded( KMFolder*, Q_UINT32 ) ), 00891 this, SLOT( slotIncidenceAdded( KMFolder*, Q_UINT32 ) ) ); 00892 connect( folder, SIGNAL( msgRemoved( KMFolder*, Q_UINT32 ) ), 00893 this, SLOT( slotIncidenceDeleted( KMFolder*, Q_UINT32 ) ) ); 00894 00895 return folder; 00896 } 00897 00898 static void cleanupFolder( KMFolder* folder, KMailICalIfaceImpl* _this ) 00899 { 00900 if( folder ) { 00901 folder->setType( "plain" ); 00902 folder->setSystemFolder( false ); 00903 folder->disconnect( _this ); 00904 folder->close(); 00905 } 00906 } 00907 00908 void KMailICalIfaceImpl::cleanup() 00909 { 00910 cleanupFolder( mContacts, this ); 00911 cleanupFolder( mCalendar, this ); 00912 cleanupFolder( mNotes, this ); 00913 cleanupFolder( mTasks, this ); 00914 cleanupFolder( mJournals, this ); 00915 00916 mContacts = mCalendar = mNotes = mTasks = mJournals = 0; 00917 } 00918 00919 void KMailICalIfaceImpl::loadPixmaps() const 00920 { 00921 static bool pixmapsLoaded = false; 00922 00923 if( mUseResourceIMAP && !pixmapsLoaded ) { 00924 pixmapsLoaded = true; 00925 pixContacts = new QPixmap( UserIcon("kmgroupware_folder_contacts")); 00926 pixCalendar = new QPixmap( UserIcon("kmgroupware_folder_calendar")); 00927 pixNotes = new QPixmap( UserIcon("kmgroupware_folder_notes")); 00928 pixTasks = new QPixmap( UserIcon("kmgroupware_folder_tasks")); 00929 pixJournals = new QPixmap( UserIcon("kmgroupware_folder_journals")); 00930 } 00931 } 00932 00933 QString KMailICalIfaceImpl::folderPixmap( KFolderTreeItem::Type type ) const 00934 { 00935 if( !mUseResourceIMAP ) 00936 return QString::null; 00937 00938 if( type == KFolderTreeItem::Contacts ) 00939 return QString::fromLatin1( "kmgroupware_folder_contacts" ); 00940 else if( type == KFolderTreeItem::Calendar ) 00941 return QString::fromLatin1( "kmgroupware_folder_calendar" ); 00942 else if( type == KFolderTreeItem::Notes ) 00943 return QString::fromLatin1( "kmgroupware_folder_notes" ); 00944 else if( type == KFolderTreeItem::Tasks ) 00945 return QString::fromLatin1( "kmgroupware_folder_tasks" ); 00946 else if( type == KFolderTreeItem::Journals ) 00947 return QString::fromLatin1( "kmgroupware_folder_journals" ); 00948 00949 return QString::null; 00950 } 00951 00952 QPixmap* KMailICalIfaceImpl::pixContacts; 00953 QPixmap* KMailICalIfaceImpl::pixCalendar; 00954 QPixmap* KMailICalIfaceImpl::pixNotes; 00955 QPixmap* KMailICalIfaceImpl::pixTasks; 00956 QPixmap* KMailICalIfaceImpl::pixJournals; 00957 00958 static void reloadFolderTree() 00959 { 00960 // Make the folder tree show the icons or not 00961 kmkernel->folderMgr()->contentsChanged(); 00962 } 00963 00964 // This is a very light-weight and fast 'parser' to retrieve 00965 // a data entry from a vCal taking continuation lines 00966 // into account 00967 static void vPartMicroParser( const QString& str, QString& s ) 00968 { 00969 QString line; 00970 uint len = str.length(); 00971 00972 for( uint i=0; i<len; ++i){ 00973 if( str[i] == '\r' || str[i] == '\n' ){ 00974 if( str[i] == '\r' ) 00975 ++i; 00976 if( i+1 < len && str[i+1] == ' ' ){ 00977 // found a continuation line, skip it's leading blanc 00978 ++i; 00979 }else{ 00980 // found a logical line end, process the line 00981 if( line.startsWith( s ) ) { 00982 s = line.mid( s.length() + 1 ); 00983 return; 00984 } 00985 line = ""; 00986 } 00987 } else { 00988 line += str[i]; 00989 } 00990 } 00991 00992 // Not found. Clear it 00993 s.truncate(0); 00994 } 00995 00996 00997 #include "kmailicalifaceimpl.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:17 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003