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@sonofthor.dk>
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( 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 ( !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 ( !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( 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 void KMailICalIfaceImpl::slotRefreshFolder( KMFolder* folder )
00467 {
00468   const QString type = icalFolderType( folder );
00469   if ( !type.isEmpty() )
00470     slotRefresh( type );
00471 }
00472 
00473 
00474 /****************************
00475  * The folder and message stuff code
00476  */
00477 
00478 KMFolder* KMailICalIfaceImpl::folderFromType( const QString& type,
00479                                               const QString& folder )
00480 {
00481   if( mUseResourceIMAP ) {
00482     KMFolder* f = extraFolder( type, folder );
00483     if ( f )
00484       return f;
00485 
00486     if( type == "Calendar" ) f = mCalendar;
00487     else if( type == "Contact" ) f = mContacts;
00488     else if( type == "Note" ) f = mNotes;
00489     else if( type == "Task" || type == "Todo" ) f = mTasks;
00490     else if( type == "Journal" ) f = mJournals;
00491 
00492     if ( f && ( folder.isEmpty() || folder == f->location() ) )
00493       return f;
00494 
00495     kdError(5006) << "No folder ( " << type << ", " << folder << " )\n";
00496   }
00497 
00498   return 0;
00499 }
00500 
00501 
00502 // Returns true if folder is a resource folder. If the resource isn't enabled
00503 // this always returns false
00504 bool KMailICalIfaceImpl::isResourceImapFolder( KMFolder* folder ) const
00505 {
00506   return mUseResourceIMAP && folder &&
00507     ( folder == mCalendar || folder == mTasks || folder == mJournals ||
00508       folder == mNotes || folder == mContacts );
00509 }
00510 
00511 bool KMailICalIfaceImpl::hideResourceImapFolder( KMFolder* folder ) const
00512 {
00513   return mHideFolders && isResourceImapFolder( folder );
00514 }
00515 
00516 KFolderTreeItem::Type KMailICalIfaceImpl::folderType( KMFolder* folder ) const
00517 {
00518   if( mUseResourceIMAP && folder ) {
00519     if( folder == mCalendar )
00520       return KFolderTreeItem::Calendar;
00521     else if( folder == mContacts )
00522       return KFolderTreeItem::Contacts;
00523     else if( folder == mNotes )
00524       return KFolderTreeItem::Notes;
00525     else if( folder == mTasks )
00526       return KFolderTreeItem::Tasks;
00527     else if( folder == mJournals )
00528       return KFolderTreeItem::Journals;
00529   }
00530 
00531   return KFolderTreeItem::Other;
00532 }
00533 
00534 
00535 QString KMailICalIfaceImpl::icalFolderType( KMFolder* folder ) const
00536 {
00537   if( mUseResourceIMAP && folder ) {
00538     if( folder == mCalendar )
00539       return "Calendar";
00540     else if( folder == mContacts )
00541       return "Contact";
00542     else if( folder == mNotes )
00543       return "Note";
00544     else if( folder == mTasks )
00545       return "Task";
00546     else if( folder == mJournals )
00547       return "Journal";
00548     else {
00549       ExtraFolder* ef = mExtraFolders.find( folder->location() );
00550       if ( ef != 0 )
00551         return folderContentsType( ef->type );
00552     }
00553   }
00554 
00555   return QString::null;
00556 }
00557 
00558 
00559 // Global tables of foldernames is different languages
00560 // For now: 0->English, 1->German, 2->French, 3->Dutch
00561 static QMap<KFolderTreeItem::Type,QString> folderNames[4];
00562 QString KMailICalIfaceImpl::folderName( KFolderTreeItem::Type type, int language ) const
00563 {
00564   static bool folderNamesSet = false;
00565   if( !folderNamesSet ) {
00566     folderNamesSet = true;
00567     /* NOTE: If you add something here, you also need to update
00568        GroupwarePage in configuredialog.cpp */
00569 
00570     // English
00571     folderNames[0][KFolderTreeItem::Calendar] = QString::fromLatin1("Calendar");
00572     folderNames[0][KFolderTreeItem::Tasks] = QString::fromLatin1("Tasks");
00573     folderNames[0][KFolderTreeItem::Journals] = QString::fromLatin1("Journal");
00574     folderNames[0][KFolderTreeItem::Contacts] = QString::fromLatin1("Contacts");
00575     folderNames[0][KFolderTreeItem::Notes] = QString::fromLatin1("Notes");
00576 
00577     // German
00578     folderNames[1][KFolderTreeItem::Calendar] = QString::fromLatin1("Kalender");
00579     folderNames[1][KFolderTreeItem::Tasks] = QString::fromLatin1("Aufgaben");
00580     folderNames[1][KFolderTreeItem::Journals] = QString::fromLatin1("Journal");
00581     folderNames[1][KFolderTreeItem::Contacts] = QString::fromLatin1("Kontakte");
00582     folderNames[1][KFolderTreeItem::Notes] = QString::fromLatin1("Notizen");
00583 
00584     // French
00585     folderNames[2][KFolderTreeItem::Calendar] = QString::fromLatin1("Calendrier");
00586     folderNames[2][KFolderTreeItem::Tasks] = QString::fromLatin1("Tāches");
00587     folderNames[2][KFolderTreeItem::Journals] = QString::fromLatin1("Journal");
00588     folderNames[2][KFolderTreeItem::Contacts] = QString::fromLatin1("Contacts");
00589     folderNames[2][KFolderTreeItem::Notes] = QString::fromLatin1("Notes");
00590 
00591     // Dutch
00592     folderNames[3][KFolderTreeItem::Calendar] = QString::fromLatin1("Agenda");
00593     folderNames[3][KFolderTreeItem::Tasks] = QString::fromLatin1("Taken");
00594     folderNames[3][KFolderTreeItem::Journals] = QString::fromLatin1("Logboek");
00595     folderNames[3][KFolderTreeItem::Contacts] = QString::fromLatin1("Contactpersonen");
00596     folderNames[3][KFolderTreeItem::Notes] = QString::fromLatin1("Notities");
00597   }
00598 
00599   if( language < 0 || language > 3 ) {
00600     return folderNames[mFolderLanguage][type];
00601   }
00602   else {
00603     return folderNames[language][type];
00604   }
00605 }
00606 
00607 
00608 // Find message matching a given UID
00609 KMMessage *KMailICalIfaceImpl::findMessageByUID( const QString& uid, KMFolder* folder )
00610 {
00611   if( !folder || !mUIDToSerNum.contains( uid ) ) return 0;
00612   int i;
00613   KMFolder *aFolder;
00614   kmkernel->msgDict()->getLocation( mUIDToSerNum[uid], &aFolder, &i );
00615   Q_ASSERT( aFolder == folder );
00616   return folder->getMsg( i );
00617 }
00618 
00619 void KMailICalIfaceImpl::deleteMsg( KMMessage *msg )
00620 {
00621   if( !msg ) return;
00622   // Commands are now delayed; can't use that anymore, we need immediate deletion
00623   //( new KMDeleteMsgCommand( msg->parent(), msg ) )->start();
00624   KMFolder *srcFolder = msg->parent();
00625   int idx = srcFolder->find(msg);
00626   assert(idx != -1);
00627   srcFolder->removeMsg(idx);
00628   delete msg;
00629 }
00630 
00631 void KMailICalIfaceImpl::folderContentsTypeChanged( KMFolder* folder,
00632                                                     KMail::FolderContentsType contentsType )
00633 {
00634   kdDebug(5006) << "folderContentsTypeChanged( " << folder->name()
00635                 << ", " << contentsType << ")\n";
00636 
00637   // Find previous type of this folder
00638   ExtraFolder* ef = mExtraFolders.find( folder->location() );
00639   if ( ( ef && ef->type == contentsType ) || ( !ef && contentsType == 0 ) )
00640     // Nothing to tell!
00641     return;
00642 
00643   if ( ef ) {
00644     // Notify that the old folder resource is no longer available
00645     subresourceDeleted(folderContentsType( ef->type ), folder->location() );
00646 
00647     if ( contentsType == 0 ) {
00648       // Delete the old entry, stop listening and stop here
00649       mExtraFolders.remove( folder->location() );
00650       folder->disconnect( this );
00651       return;
00652     }
00653 
00654     // So the type changed to another groupware type.
00655     // Set the entry to the new type
00656     ef->type = contentsType;
00657   } else {
00658     // Make a new entry for the list
00659     ef = new ExtraFolder( folder, contentsType );
00660     mExtraFolders.insert( folder->location(), ef );
00661 
00662     // avoid multiple connections
00663     disconnect( folder, SIGNAL( msgAdded( KMFolder*, Q_UINT32 ) ),
00664                 this, SLOT( slotIncidenceAdded( KMFolder*, Q_UINT32 ) ) );
00665     disconnect( folder, SIGNAL( msgRemoved( KMFolder*, Q_UINT32 ) ),
00666                 this, SLOT( slotIncidenceDeleted( KMFolder*, Q_UINT32 ) ) );
00667     disconnect( folder, SIGNAL( expunged( KMFolder* ) ),
00668                 this, SLOT( slotRefreshFolder( KMFolder* ) ) );
00669 
00670     // And listen to changes from it
00671     connect( folder, SIGNAL( msgAdded( KMFolder*, Q_UINT32 ) ),
00672              this, SLOT( slotIncidenceAdded( KMFolder*, Q_UINT32 ) ) );
00673     connect( folder, SIGNAL( msgRemoved( KMFolder*, Q_UINT32 ) ),
00674              this, SLOT( slotIncidenceDeleted( KMFolder*, Q_UINT32 ) ) );
00675     connect( folder, SIGNAL( expunged( KMFolder* ) ),
00676              this, SLOT( slotRefreshFolder( KMFolder* ) ) );
00677   }
00678 
00679   // Tell about the new resource
00680   subresourceAdded( folderContentsType( contentsType ), folder->location() );
00681 }
00682 
00683 KMFolder* KMailICalIfaceImpl::extraFolder( const QString& type,
00684                                            const QString& folder )
00685 {
00686   // If an extra folder exists that match the type and folder location,
00687   // use that
00688   int t = folderContentsType( type );
00689   if ( t < 1 || t > 5 )
00690     return 0;
00691 
00692   QDictIterator<ExtraFolder> it( mExtraFolders );
00693   for ( ; it.current(); ++it )
00694     if ( it.current()->type == t &&
00695          it.current()->folder->location() == folder )
00696       return it.current()->folder;
00697 
00698   return 0;
00699 }
00700 
00701 
00702 /****************************
00703  * The config stuff
00704  */
00705 
00706 void KMailICalIfaceImpl::readConfig()
00707 {
00708   bool enabled = GlobalSettings::theIMAPResourceEnabled();
00709 
00710   if( !enabled ) {
00711     if( mUseResourceIMAP == true ) {
00712       // Shutting down
00713       mUseResourceIMAP = false;
00714       cleanup();
00715       reloadFolderTree();
00716     }
00717     return;
00718   }
00719 
00720   // Read remaining options
00721   const bool hideFolders = GlobalSettings::hideGroupwareFolders();
00722   unsigned int folderLanguage = GlobalSettings::theIMAPResourceFolderLanguage();
00723   if( folderLanguage > 3 ) folderLanguage = 0;
00724   QString parentName = GlobalSettings::theIMAPResourceFolderParent();
00725 
00726   // Find the folder parent
00727   KMFolderDir* folderParentDir;
00728   KMFolderType folderType;
00729   KMFolder* folderParent = kmkernel->findFolderById( parentName );
00730   if( folderParent == 0 ) {
00731     // Parent folder not found. It was probably deleted. The user will have to
00732     // configure things again.
00733     kdDebug(5006) << "Groupware folder " << parentName << " not found. Groupware functionality disabled" << endl;
00734     // Or maybe the inbox simply wasn't created on the first startup
00735     KMAccount* account = kmkernel->acctMgr()->find( GlobalSettings::theIMAPResourceAccount() );
00736     Q_ASSERT( account );
00737     if ( account ) {
00738       // just in case we were connected already
00739       disconnect( account, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00740                this, SLOT( slotCheckDone() ) );
00741       connect( account, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00742                this, SLOT( slotCheckDone() ) );
00743     }
00744     mUseResourceIMAP = false;
00745     return;
00746   } else {
00747     folderParentDir = folderParent->createChildFolder();
00748     folderType = folderParent->folderType();
00749   }
00750 
00751   // Make sure the folder parent has the subdirs
00752   bool makeSubFolders = false;
00753   KMFolderNode* node;
00754   node = folderParentDir->hasNamedFolder( folderName( KFolderTreeItem::Calendar, folderLanguage ) );
00755   if( !node || node->isDir() ) {
00756     makeSubFolders = true;
00757     mCalendar = 0;
00758   }
00759   node = folderParentDir->hasNamedFolder( folderName( KFolderTreeItem::Tasks, folderLanguage ) );
00760   if( !node || node->isDir() ) {
00761     makeSubFolders = true;
00762     mTasks = 0;
00763   }
00764   node = folderParentDir->hasNamedFolder( folderName( KFolderTreeItem::Journals, folderLanguage ) );
00765   if( !node || node->isDir() ) {
00766     makeSubFolders = true;
00767     mJournals = 0;
00768   }
00769   node = folderParentDir->hasNamedFolder( folderName( KFolderTreeItem::Contacts, folderLanguage ) );
00770   if( !node || node->isDir() ) {
00771     makeSubFolders = true;
00772     mContacts = 0;
00773   }
00774   node = folderParentDir->hasNamedFolder( folderName( KFolderTreeItem::Notes, folderLanguage ) );
00775   if( !node || node->isDir() ) {
00776     makeSubFolders = true;
00777     mNotes = 0;
00778   }
00779   if( makeSubFolders ) {
00780     // Not all subfolders were there, so ask if we can make them
00781     if( KMessageBox::questionYesNo( 0, i18n("KMail will now create the required folders for the IMAP resource"
00782                                             " as subfolders of %1; if you do not want this, press \"No\","
00783                                             " and the IMAP resource will be disabled").arg(folderParent!=0?folderParent->name():folderParentDir->name()),
00784                                     i18n("IMAP Resource Folders") ) == KMessageBox::No ) {
00785 
00786       GlobalSettings::setTheIMAPResourceEnabled( false );
00787       mUseResourceIMAP = false;
00788       mFolderParentDir = 0;
00789       mFolderParent = 0;
00790       reloadFolderTree();
00791       return;
00792     }
00793   }
00794 
00795   // Check if something changed
00796   if( mUseResourceIMAP && !makeSubFolders && mFolderParentDir == folderParentDir
00797       && mFolderType == folderType ) {
00798     // Nothing changed
00799     if ( hideFolders != mHideFolders ) {
00800       // Well, the folder hiding has changed
00801       mHideFolders = hideFolders;
00802       reloadFolderTree();
00803     }
00804     return;
00805   }
00806 
00807   // Make the new settings work
00808   mUseResourceIMAP = true;
00809   mFolderLanguage = folderLanguage;
00810   mFolderParentDir = folderParentDir;
00811   mFolderParent = folderParent;
00812   mFolderType = folderType;
00813   mHideFolders = hideFolders;
00814 
00815   // Close the previous folders
00816   cleanup();
00817 
00818   // Set the new folders
00819   mCalendar = initFolder( KFolderTreeItem::Calendar, "GCa" );
00820   mTasks    = initFolder( KFolderTreeItem::Tasks, "GTa" );
00821   mJournals = initFolder( KFolderTreeItem::Journals, "GTa" );
00822   mContacts = initFolder( KFolderTreeItem::Contacts, "GCo" );
00823   mNotes    = initFolder( KFolderTreeItem::Notes, "GNo" );
00824 
00825   // Make KOrganizer re-read everything
00826   slotRefresh( "Calendar" );
00827   slotRefresh( "Task" );
00828   slotRefresh( "Journal" );
00829   slotRefresh( "Contact" );
00830   slotRefresh( "Notes" );
00831 
00832   reloadFolderTree();
00833 }
00834 
00835 void KMailICalIfaceImpl::slotCheckDone()
00836 {
00837   QString parentName = GlobalSettings::theIMAPResourceFolderParent();
00838   KMFolder* folderParent = kmkernel->findFolderById( parentName );
00839   if ( folderParent )  // cool it exists now
00840   {
00841     KMAccount* account = kmkernel->acctMgr()->find( GlobalSettings::theIMAPResourceAccount() );
00842     if ( account )
00843       disconnect( account, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00844                   this, SLOT( slotCheckDone() ) );
00845     readConfig();
00846   }
00847 }
00848 
00849 KMFolder* KMailICalIfaceImpl::initFolder( KFolderTreeItem::Type itemType,
00850                                           const char* typeString )
00851 {
00852   // Figure out what type of folder this is supposed to be
00853   KMFolderType type = mFolderType;
00854   if( type == KMFolderTypeUnknown ) type = KMFolderTypeMaildir;
00855 
00856   // Find the folder
00857   KMFolder* folder = 0;
00858   KMFolderNode* node = mFolderParentDir->hasNamedFolder( folderName( itemType ) );
00859   if( node && !node->isDir() ) folder = static_cast<KMFolder*>(node);
00860   if( !folder ) {
00861     // The folder isn't there yet - create it
00862     folder =
00863       mFolderParentDir->createFolder( folderName( itemType ), false, type );
00864     if( mFolderType == KMFolderTypeImap ) {
00865       KMFolderImap* parentFolder = static_cast<KMFolderImap*>( mFolderParent->storage() );
00866       parentFolder->createFolder( folderName( itemType ) );
00867       static_cast<KMFolderImap*>( folder->storage() )->setAccount( parentFolder->account() );
00868     }
00869   }
00870 
00871   if( folder->canAccess() != 0 ) {
00872     KMessageBox::sorry(0, i18n("You do not have read/write permission to your %1 folder.")
00873                        .arg( folderName( itemType ) ) );
00874     return 0;
00875   }
00876   folder->setType( typeString );
00877   folder->setSystemFolder( true );
00878   folder->open();
00879   // avoid multiple connections
00880   disconnect( folder, SIGNAL( msgAdded( KMFolder*, Q_UINT32 ) ),
00881               this, SLOT( slotIncidenceAdded( KMFolder*, Q_UINT32 ) ) );
00882   disconnect( folder, SIGNAL( msgRemoved( KMFolder*, Q_UINT32 ) ),
00883               this, SLOT( slotIncidenceDeleted( KMFolder*, Q_UINT32 ) ) );
00884   disconnect( folder, SIGNAL( expunged( KMFolder* ) ),
00885               this, SLOT( slotRefreshFolder( KMFolder* ) ) );
00886   // Setup the signals to listen for changes
00887   connect( folder, SIGNAL( msgAdded( KMFolder*, Q_UINT32 ) ),
00888            this, SLOT( slotIncidenceAdded( KMFolder*, Q_UINT32 ) ) );
00889   connect( folder, SIGNAL( msgRemoved( KMFolder*, Q_UINT32 ) ),
00890            this, SLOT( slotIncidenceDeleted( KMFolder*, Q_UINT32 ) ) );
00891   connect( folder, SIGNAL( expunged( KMFolder* ) ),
00892            this, SLOT( slotRefreshFolder( KMFolder* ) ) );
00893 
00894   return folder;
00895 }
00896 
00897 static void cleanupFolder( KMFolder* folder, KMailICalIfaceImpl* _this )
00898 {
00899   if( folder ) {
00900     folder->setType( "plain" );
00901     folder->setSystemFolder( false );
00902     folder->disconnect( _this );
00903     folder->close();
00904   }
00905 }
00906 
00907 void KMailICalIfaceImpl::cleanup()
00908 {
00909   cleanupFolder( mContacts, this );
00910   cleanupFolder( mCalendar, this );
00911   cleanupFolder( mNotes, this );
00912   cleanupFolder( mTasks, this );
00913   cleanupFolder( mJournals, this );
00914 
00915   mContacts = mCalendar = mNotes = mTasks = mJournals = 0;
00916 }
00917 
00918 void KMailICalIfaceImpl::loadPixmaps() const
00919 {
00920   static bool pixmapsLoaded = false;
00921 
00922   if( mUseResourceIMAP && !pixmapsLoaded ) {
00923     pixmapsLoaded = true;
00924     pixContacts = new QPixmap( UserIcon("kmgroupware_folder_contacts"));
00925     pixCalendar = new QPixmap( UserIcon("kmgroupware_folder_calendar"));
00926     pixNotes    = new QPixmap( UserIcon("kmgroupware_folder_notes"));
00927     pixTasks    = new QPixmap( UserIcon("kmgroupware_folder_tasks"));
00928     pixJournals = new QPixmap( UserIcon("kmgroupware_folder_journals"));
00929   }
00930 }
00931 
00932 QString KMailICalIfaceImpl::folderPixmap( KFolderTreeItem::Type type ) const
00933 {
00934   if( !mUseResourceIMAP )
00935     return QString::null;
00936 
00937   if( type == KFolderTreeItem::Contacts )
00938     return QString::fromLatin1( "kmgroupware_folder_contacts" );
00939   else if( type == KFolderTreeItem::Calendar )
00940     return QString::fromLatin1( "kmgroupware_folder_calendar" );
00941   else if( type == KFolderTreeItem::Notes )
00942     return QString::fromLatin1( "kmgroupware_folder_notes" );
00943   else if( type == KFolderTreeItem::Tasks )
00944     return QString::fromLatin1( "kmgroupware_folder_tasks" );
00945   else if( type == KFolderTreeItem::Journals )
00946     return QString::fromLatin1( "kmgroupware_folder_journals" );
00947 
00948   return QString::null;
00949 }
00950 
00951 QPixmap* KMailICalIfaceImpl::pixContacts;
00952 QPixmap* KMailICalIfaceImpl::pixCalendar;
00953 QPixmap* KMailICalIfaceImpl::pixNotes;
00954 QPixmap* KMailICalIfaceImpl::pixTasks;
00955 QPixmap* KMailICalIfaceImpl::pixJournals;
00956 
00957 static void reloadFolderTree()
00958 {
00959   // Make the folder tree show the icons or not
00960   kmkernel->folderMgr()->contentsChanged();
00961 }
00962 
00963 // This is a very light-weight and fast 'parser' to retrieve
00964 // a data entry from a vCal taking continuation lines
00965 // into account
00966 static void vPartMicroParser( const QString& str, QString& s )
00967 {
00968   QString line;
00969   uint len = str.length();
00970 
00971   for( uint i=0; i<len; ++i){
00972     if( str[i] == '\r' || str[i] == '\n' ){
00973       if( str[i] == '\r' )
00974         ++i;
00975       if( i+1 < len && str[i+1] == ' ' ){
00976         // found a continuation line, skip it's leading blanc
00977         ++i;
00978       }else{
00979         // found a logical line end, process the line
00980         if( line.startsWith( s ) ) {
00981           s = line.mid( s.length() + 1 );
00982           return;
00983         }
00984         line = "";
00985       }
00986     } else {
00987       line += str[i];
00988     }
00989   }
00990 
00991   // Not found. Clear it
00992   s.truncate(0);
00993 }
00994 
00995 
00996 #include "kmailicalifaceimpl.moc"
KDE Logo
This file is part of the documentation for kmail Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Apr 4 04:48:24 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003