harvesterplugins/messaging/email/qtemailfetcher/qtemailfetcher.cpp
changeset 2 208a4ba3894c
child 3 6832643895f7
equal deleted inserted replaced
0:ccd0fd43f247 2:208a4ba3894c
       
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: Utility class for fetching email.
       
    15 *
       
    16 */
       
    17 
       
    18 #include "qtemailfetcher.h"
       
    19 #include <csearchdocument.h>
       
    20 #include <cpixmaindefs.h>
       
    21 //#include <QThread> //If we happen to use QThread::yieldCurrentThread()
       
    22 
       
    23 //Symbian specific details; picked up from cemailplugin.cpp. 
       
    24 //Refactor it to cpixmaindefs.h
       
    25 _LIT(KMsgBaseAppClassGeneric, "root msg email");
       
    26 
       
    27 _LIT(KMsgSubject, "Subject");
       
    28 _LIT(KMsgRecipients, "Recipients");
       
    29 _LIT(KMsgBody, "Body");
       
    30 _LIT(KMimeTypeField, CPIX_MIMETYPE_FIELD);
       
    31 _LIT(KMimeTypeMsg, "Messages");
       
    32 
       
    33 //------------------------------------------------------------------------------
       
    34 QEmailFetcher::QEmailFetcher( MEmailItemObserver& aObserver )
       
    35     :iEmailObserver( aObserver ), 
       
    36      iEmailEventNotifier( NULL ),
       
    37      iEmailService( NULL ),
       
    38      iMailBoxListings( NULL ), 
       
    39      iMailFolderList( NULL ),
       
    40      iEnvelopeListing( NULL )
       
    41     {
       
    42     }
       
    43 
       
    44 //------------------------------------------------------------------------------
       
    45 QEmailFetcher::~QEmailFetcher()
       
    46     {
       
    47     delete iEmailEventNotifier;
       
    48     delete iEmailService;
       
    49     delete iMailBoxListings;
       
    50     delete iMailFolderList;
       
    51     }
       
    52 
       
    53 //------------------------------------------------------------------------------
       
    54 QEmailFetcher* QEmailFetcher::newInstance( MEmailItemObserver& aObserver ){
       
    55     QEmailFetcher* emailFetcher = NULL;
       
    56     
       
    57     //Leak free init.
       
    58     try{
       
    59         QEmailFetcher* emailFetcher = new QEmailFetcher( aObserver );
       
    60         //Uncomment 'this' once the actual APIs are ready.
       
    61         emailFetcher->iEmailService = new NmEmailService( emailFetcher );
       
    62         emailFetcher->iEmailEventNotifier =  new NmEventNotifier( emailFetcher );
       
    63         emailFetcher->iMailBoxListings = new NmMailboxListing( emailFetcher );
       
    64     }catch(...){ //cleanup.
       
    65         delete emailFetcher; 
       
    66         delete emailFetcher->iEmailService;
       
    67         delete emailFetcher->iEmailEventNotifier;
       
    68         delete emailFetcher->iMailBoxListings;
       
    69         emailFetcher->iEmailService = NULL;
       
    70         emailFetcher->iEmailEventNotifier = NULL;
       
    71         emailFetcher->iMailBoxListings = NULL;
       
    72         throw; //rethrow the exception to caller.
       
    73     }
       
    74     initialize( emailFetcher ); //Do the rest of the init.
       
    75     return emailFetcher; //returns only if not null.
       
    76 }
       
    77 
       
    78 //------------------------------------------------------------------------------
       
    79 void QEmailFetcher::initialize( QEmailFetcher* aThis ){
       
    80     //The use of 'aThis' is because the current function is static.
       
    81     connect( aThis->iEmailService, SIGNAL(initialized(bool)), 
       
    82              aThis, SLOT(emailServiceIntialized(bool)) );
       
    83     aThis->iEmailService->initialise();
       
    84     aThis->connect( aThis->iEmailEventNotifier, 
       
    85                     SIGNAL(messageEvent(MessageEvent, quint64, quint64, QList<quint64>)),
       
    86                     aThis, 
       
    87                     SLOT(handleMessageEvent(MessageEvent, quint64, quint64, QList<quint64>)) );
       
    88 }
       
    89 
       
    90 //------------------------------------------------------------------------------
       
    91 void QEmailFetcher::emailServiceIntialized(bool aAllOk){
       
    92     if( aAllOk ){
       
    93         connect( iMailBoxListings, SIGNAL(mailboxesListed(int)), this, SLOT(handleMailboxesListed(int)) );
       
    94     }
       
    95 }
       
    96 
       
    97 //------------------------------------------------------------------------------
       
    98 void QEmailFetcher::StartHarvesting(){
       
    99     iMailBoxListings->start();
       
   100 }
       
   101 
       
   102 //------------------------------------------------------------------------------
       
   103 namespace {
       
   104 
       
   105 // Taken from qt/src/corelib/kernel/qcore_symbian_p.cpp, as recomended in
       
   106 // http://qt.nokia.com/files/pdf/whitepaper-using-qt-and-symbian-c-together, page 34.
       
   107 // URL last accessed on April 6th, 2010.
       
   108 
       
   109 // Returned TPtrC is valid as long as the given parameter is valid and unmodified
       
   110 static inline TPtrC qt_QString2TPtrC( const QString& string )
       
   111 {
       
   112     return TPtrC16(static_cast<const TUint16*>(string.utf16()), string.length());
       
   113 }
       
   114 
       
   115 //------------------------------------------------------------------------------
       
   116 // TODO Remove this code if qt_QString2TPtrC works.
       
   117 // TODO If this function is used, remember to release memory.
       
   118 // Ownership with caller.
       
   119 //HBufC* qt_QString2HBufC(const QString& aString)
       
   120 //{
       
   121 //    HBufC *buffer;
       
   122 //#ifdef QT_NO_UNICODE
       
   123 //    TPtrC8 ptr(reinterpret_cast<const TUint8*>(aString.toLocal8Bit().constData()));
       
   124 //#else
       
   125 //    TPtrC16 ptr(qt_QString2TPtrC(aString));
       
   126 //#endif
       
   127 //    buffer = q_check_ptr(HBufC::New(ptr.Length()));
       
   128 //    buffer->Des().Copy(ptr);
       
   129 //    return buffer;
       
   130 //}
       
   131 
       
   132 //------------------------------------------------------------------------------
       
   133 //Private free function creates CSearchDocument from EMailMessageEnvelope.
       
   134 CSearchDocument* getSearchDocument( const NmMessageEnvelope& aEnvelope ){
       
   135     QList<NmEmailAddress> toList;
       
   136     //Need to cast away const-ness since the get method is unfortunately not const.
       
   137     const_cast<NmMessageEnvelope&>(aEnvelope).getToRecipients( toList );
       
   138 
       
   139     //We need ALL the recipients in a SINGLE field.
       
   140     QString recipients = "";
       
   141     for( int i=0; i<toList.length(); i++ )
       
   142         recipients += toList.at( i ).displayName() + " "; //or should we get address?
       
   143 
       
   144     NmMessageBody body;
       
   145     //Cast away const-ness since the get method is unfortunately not const.
       
   146     //Returns void. Cannot check for success/failure.
       
   147     const_cast<NmMessageEnvelope&>(aEnvelope).getPlainTextBody( body ); 
       
   148     QString msgBody = body.content();
       
   149 
       
   150     CSearchDocument* doc = 0;
       
   151     QT_TRAP_THROWING(
       
   152     //Use qt_Qstring2TPtrC since we are working with <b>const</b> EmailMessageEnvelope.
       
   153     doc = CSearchDocument::NewL( qt_QString2TPtrC( QString().setNum( aEnvelope.id() ) ), 
       
   154                                  KMsgBaseAppClassGeneric );
       
   155     doc->AddFieldL( KMimeTypeField, KMimeTypeMsg, CDocumentField::EStoreYes | CDocumentField::EIndexUnTokenized);
       
   156     doc->AddFieldL( KMsgSubject, qt_QString2TPtrC( aEnvelope.subject() ), CDocumentField::EStoreYes | CDocumentField::EIndexTokenized );
       
   157     doc->AddFieldL( KMsgRecipients, qt_QString2TPtrC( recipients ), CDocumentField::EStoreYes | CDocumentField::EIndexTokenized );
       
   158     doc->AddFieldL( KMsgBody, qt_QString2TPtrC( msgBody ), CDocumentField::EStoreYes | CDocumentField::EIndexTokenized );
       
   159     //TODO: What should go in here?
       
   160     doc->AddExcerptL( KNullDesC );
       
   161     );
       
   162     return doc;
       
   163 }
       
   164 } //anonymous namespace
       
   165 
       
   166 //------------------------------------------------------------------------------
       
   167 //Options to make async (like other plugins' Asynchronizer):
       
   168 //1. Use http://doc.trolltech.com/4.6/qtimer.html and connect timeout() signal to something?
       
   169 //Downside: 
       
   170 //Have to save the state of the function and resume. Achievable via static members. 
       
   171 //Remeber to reset counters.
       
   172 //2. Use timer; unlike above, have handleMailboxesListed() simply trigger a  
       
   173 //Timer controlled function.
       
   174 //3. Use QThread::currentThread()->yieldCurrentThread();
       
   175 //Downside: Not tested.
       
   176 //4. As recommended by the email API documentation, use SingleShotTimer:
       
   177 //QTimer::singleShot(nsecs,nmFolderListing,SLOT(start());
       
   178 //
       
   179 //Recommendation: Use option 4.
       
   180 
       
   181 void QEmailFetcher::handleMailboxesListed(int aCount){
       
   182     QList<NmMailbox> mailBoxes;
       
   183     if( aCount>0 && iMailBoxListings->getMailboxes( mailBoxes ) ){
       
   184         for( int i=0; i<aCount; i++ ){
       
   185             //Already set to NULL in constructor, so safe to call delete first time.
       
   186             delete iMailFolderList; iMailFolderList = NULL;
       
   187             iMailFolderList = new NmFolderListing( this, mailBoxes.at( i ).id() );
       
   188             connect( iMailFolderList, SIGNAL(foldersListed()), this, SLOT(mailFoldersListed()) );
       
   189             const int waitForSeconds = 30; //TODO Move this constant out of here if needed elsewhere
       
   190             QTimer::singleShot( waitForSeconds, iMailFolderList, SLOT( start()) );
       
   191         }
       
   192     }
       
   193 }
       
   194 
       
   195 //------------------------------------------------------------------------------
       
   196 void QEmailFetcher::mailFoldersListed(int aCount){
       
   197     if( aCount == NmFolderListing::FolderListingFailed ) return; //silently.
       
   198     QList<NmFolder> folders;
       
   199     if ( aCount && iMailFolderList->getFolders( folders ) ) {
       
   200         for( int i=0; i<aCount; i++ ){
       
   201             //Already set to NULL in constructor, so safe to call delete first time.
       
   202             delete iEnvelopeListing; iEnvelopeListing = NULL; 
       
   203             iEnvelopeListing = new NmEnvelopeListing( this, folders.at( i ).id(), 0 );
       
   204             connect(iEnvelopeListing, SIGNAL(envelopesListed(int)),this,SLOT(processMessages(int)));
       
   205             iEnvelopeListing->start();
       
   206         }
       
   207     }
       
   208 }
       
   209 
       
   210 //------------------------------------------------------------------------------
       
   211 void QEmailFetcher::processMessages(int aCount){
       
   212     if( aCount == NmMailboxListing::MailboxListingFailed ) return; //silently.
       
   213     QList<NmMessageEnvelope> envelopes;
       
   214     if ( aCount > 0 && iEnvelopeListing->getEnvelopes(envelopes) ) {
       
   215         for( int i=0; i<envelopes.count(); i++ ) {
       
   216         const NmMessageEnvelope &envelope = envelopes.at( i );
       
   217         //Create document and call back observer.
       
   218         QT_TRAP_THROWING( iEmailObserver.HandleDocumentL( getSearchDocument( envelope ), ECPixAddAction ) );
       
   219         }
       
   220     }
       
   221 }
       
   222 
       
   223 //------------------------------------------------------------------------------
       
   224 void QEmailFetcher::handleMessageEvent( const MessageEvent aEvent, quint64 aMailboxId, quint64 aFolderId, QList<quint64> aMessageList){
       
   225     NmMessageEnvelope envelope;
       
   226     const int messageCount = aMessageList.count();
       
   227     if( messageCount>0 ){
       
   228     if( aEvent == MessageCreated || aEvent == MessageChanged ){
       
   229         for( int i=0; i<messageCount; i++ ){
       
   230             if( iEmailService->getEnvelope( aMailboxId, aFolderId, aMessageList.at( i ), envelope ) ){
       
   231                 QT_TRAP_THROWING( 
       
   232                    iEmailObserver.HandleDocumentL( getSearchDocument( envelope ), 
       
   233                            //Doing this simply avoids *duplicate* code for update action.
       
   234                            aEvent == MessageCreated ? ECPixAddAction : ECPixUpdateAction ) );
       
   235             }
       
   236         }
       
   237     }
       
   238     else if( aEvent == MessageDeleted ) {
       
   239         //TODO We can do better. For delete, we dont have to create full document. Just the ID should be enough.
       
   240         //We can have another function called getPartialSearchDocument so deletes will be faster.
       
   241         for( int i=0; i<messageCount; i++ ){
       
   242             if( iEmailService->getEnvelope( aMailboxId, aFolderId, aMessageList.at( i ), envelope ) ){
       
   243                 QT_TRAP_THROWING( 
       
   244                 iEmailObserver.HandleDocumentL( getSearchDocument( envelope ), ECPixRemoveAction ) );
       
   245             }
       
   246         }
       
   247     }
       
   248     }
       
   249 }