• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

akonadi

itemfetchjob.cpp

00001 /*
00002     Copyright (c) 2006 - 2007 Volker Krause <vkrause@kde.org>
00003 
00004     This library is free software; you can redistribute it and/or modify it
00005     under the terms of the GNU Library General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or (at your
00007     option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful, but WITHOUT
00010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00012     License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to the
00016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017     02110-1301, USA.
00018 */
00019 
00020 #include "itemfetchjob.h"
00021 
00022 #include "attributefactory.h"
00023 #include "collection.h"
00024 #include "collectionselectjob.h"
00025 #include "imapparser_p.h"
00026 #include "itemfetchscope.h"
00027 #include "itemserializer.h"
00028 #include "itemserializerplugin.h"
00029 #include "job_p.h"
00030 #include "entity_p.h"
00031 #include "protocol_p.h"
00032 #include "protocolhelper.h"
00033 
00034 #include <kdebug.h>
00035 
00036 #include <QtCore/QDateTime>
00037 #include <QtCore/QStringList>
00038 #include <QtCore/QTimer>
00039 
00040 using namespace Akonadi;
00041 
00042 class Akonadi::ItemFetchJobPrivate : public JobPrivate
00043 {
00044   public:
00045     ItemFetchJobPrivate( ItemFetchJob *parent )
00046       : JobPrivate( parent )
00047     {
00048     }
00049 
00050     void timeout()
00051     {
00052       Q_Q( ItemFetchJob );
00053 
00054       mEmitTimer->stop(); // in case we are called by result()
00055       if ( !mPendingItems.isEmpty() ) {
00056         emit q->itemsReceived( mPendingItems );
00057         mPendingItems.clear();
00058       }
00059     }
00060 
00061     void startFetchJob();
00062     void selectDone( KJob * job );
00063 
00064     Q_DECLARE_PUBLIC( ItemFetchJob )
00065 
00066     Collection mCollection;
00067     Item mItem;
00068     Item::List mItems;
00069     ItemFetchScope mFetchScope;
00070     Item::List mPendingItems; // items pending for emitting itemsReceived()
00071     QTimer* mEmitTimer;
00072 };
00073 
00074 void ItemFetchJobPrivate::startFetchJob()
00075 {
00076   QByteArray command = newTag();
00077   if ( !mItem.isValid() )
00078     command += " " AKONADI_CMD_ITEMFETCH " 1:*";
00079   else
00080     command += " " AKONADI_CMD_UID " " AKONADI_CMD_ITEMFETCH " " + QByteArray::number( mItem.id() );
00081 
00082   if ( mFetchScope.fullPayload() )
00083     command += " " AKONADI_PARAM_FULLPAYLOAD;
00084   if ( mFetchScope.allAttributes() )
00085     command += " " AKONADI_PARAM_ALLATTRIBUTES;
00086   if ( mFetchScope.cacheOnly() )
00087     command += " " AKONADI_PARAM_CACHEONLY;
00088 
00089   command += " (UID REMOTEID FLAGS SIZE DATETIME";
00090   foreach ( const QByteArray &part, mFetchScope.payloadParts() )
00091     command += ' ' + ProtocolHelper::encodePartIdentifier( ProtocolHelper::PartPayload, part );
00092   foreach ( const QByteArray &part, mFetchScope.attributes() )
00093     command += ' ' + ProtocolHelper::encodePartIdentifier( ProtocolHelper::PartAttribute, part );
00094   command += ")\n";
00095 
00096   writeData( command );
00097 }
00098 
00099 void ItemFetchJobPrivate::selectDone( KJob * job )
00100 {
00101   if ( !job->error() )
00102     // the collection is now selected, fetch the message(s)
00103     startFetchJob();
00104 }
00105 
00106 ItemFetchJob::ItemFetchJob( const Collection &collection, QObject * parent )
00107   : Job( new ItemFetchJobPrivate( this ), parent )
00108 {
00109   Q_D( ItemFetchJob );
00110 
00111   d->mEmitTimer = new QTimer( this );
00112   d->mEmitTimer->setSingleShot( true );
00113   d->mEmitTimer->setInterval( 100 );
00114   connect( d->mEmitTimer, SIGNAL(timeout()), this, SLOT(timeout()) );
00115   connect( this, SIGNAL(result(KJob*)), this, SLOT(timeout()) );
00116 
00117   d->mCollection = collection;
00118 }
00119 
00120 ItemFetchJob::ItemFetchJob( const Item & item, QObject * parent)
00121   : Job( new ItemFetchJobPrivate( this ), parent )
00122 {
00123   Q_D( ItemFetchJob );
00124 
00125   d->mEmitTimer = new QTimer( this );
00126   d->mEmitTimer->setSingleShot( true );
00127   d->mEmitTimer->setInterval( 100 );
00128   connect( d->mEmitTimer, SIGNAL(timeout()), this, SLOT(timeout()) );
00129   connect( this, SIGNAL(result(KJob*)), this, SLOT(timeout()) );
00130 
00131   d->mCollection = Collection::root();
00132   d->mItem = item;
00133 }
00134 
00135 ItemFetchJob::~ItemFetchJob()
00136 {
00137 }
00138 
00139 void ItemFetchJob::doStart()
00140 {
00141   Q_D( ItemFetchJob );
00142 
00143   if ( !d->mItem.isValid() ) { // collection content listing
00144     if ( d->mCollection == Collection::root() ) {
00145       setErrorText( QLatin1String("Cannot list root collection.") );
00146       setError( Unknown );
00147       emitResult();
00148     }
00149     CollectionSelectJob *job = new CollectionSelectJob( d->mCollection, this );
00150     connect( job, SIGNAL(result(KJob*)), SLOT(selectDone(KJob*)) );
00151     addSubjob( job );
00152   } else
00153     d->startFetchJob();
00154 }
00155 
00156 void ItemFetchJob::doHandleResponse( const QByteArray & tag, const QByteArray & data )
00157 {
00158   Q_D( ItemFetchJob );
00159 
00160   if ( tag == "*" ) {
00161     int begin = data.indexOf( "FETCH" );
00162     if ( begin >= 0 ) {
00163 
00164       // split fetch response into key/value pairs
00165       QList<QByteArray> fetchResponse;
00166       ImapParser::parseParenthesizedList( data, fetchResponse, begin + 6 );
00167 
00168       // create a new item object
00169       Item::Id uid = -1;
00170       int rev = -1;
00171       QString rid;
00172       QString mimeType;
00173 
00174       for ( int i = 0; i < fetchResponse.count() - 1; i += 2 ) {
00175         const QByteArray key = fetchResponse.value( i );
00176         const QByteArray value = fetchResponse.value( i + 1 );
00177 
00178         if ( key == "UID" )
00179           uid = value.toLongLong();
00180         else if ( key == "REV" )
00181           rev = value.toInt();
00182         else if ( key == "REMOTEID" )
00183           rid = QString::fromUtf8( value );
00184         else if ( key == "MIMETYPE" )
00185           mimeType = QString::fromLatin1( value );
00186       }
00187 
00188       if ( uid < 0 || rev < 0 || mimeType.isEmpty() ) {
00189         kWarning( 5250 ) << "Broken fetch response: UID, RID, REV or MIMETYPE missing!";
00190         return;
00191       }
00192 
00193       Item item( uid );
00194       item.setRemoteId( rid );
00195       item.setRevision( rev );
00196       item.setMimeType( mimeType );
00197       if ( !item.isValid() )
00198         return;
00199 
00200       // parse fetch response fields
00201       for ( int i = 0; i < fetchResponse.count() - 1; i += 2 ) {
00202         const QByteArray key = fetchResponse.value( i );
00203         // skip stuff we dealt with already
00204         if ( key == "UID" || key == "REV" || key == "REMOTEID" || key == "MIMETYPE" )
00205           continue;
00206         // flags
00207         if ( key == "FLAGS" ) {
00208           QList<QByteArray> flags;
00209           ImapParser::parseParenthesizedList( fetchResponse[i + 1], flags );
00210           foreach ( const QByteArray &flag, flags ) {
00211             item.setFlag( flag );
00212           }
00213         } else if ( key == "SIZE" ) {
00214           const quint64 size = fetchResponse[i + 1].toLongLong();
00215           item.setSize( size );
00216         } else if ( key == "DATETIME" ) {
00217           QDateTime datetime;
00218           ImapParser::parseDateTime( fetchResponse[i + 1], datetime );
00219           item.setModificationTime( datetime );
00220         } else {
00221           int version = 0;
00222           QByteArray plainKey( key );
00223           ProtocolHelper::PartNamespace ns;
00224 
00225           ImapParser::splitVersionedKey( key, plainKey, version );
00226           plainKey = ProtocolHelper::decodePartIdentifier( plainKey, ns );
00227 
00228           switch ( ns ) {
00229             case ProtocolHelper::PartPayload:
00230               ItemSerializer::deserialize( item, plainKey, fetchResponse.value( i + 1 ), version );
00231               break;
00232             case ProtocolHelper::PartAttribute:
00233             {
00234               Attribute* attr = AttributeFactory::createAttribute( plainKey );
00235               Q_ASSERT( attr );
00236               attr->deserialize( fetchResponse.value( i + 1 ) );
00237               item.addAttribute( attr );
00238               break;
00239             }
00240             case ProtocolHelper::PartGlobal:
00241             default:
00242               kWarning() << "Unknown item part type:" << key;
00243           }
00244         }
00245       }
00246 
00247       item.d_ptr->resetChangeLog();
00248       d->mItems.append( item );
00249       d->mPendingItems.append( item );
00250       if ( !d->mEmitTimer->isActive() )
00251         d->mEmitTimer->start();
00252       return;
00253     }
00254   }
00255   kDebug( 5250 ) << "Unhandled response: " << tag << data;
00256 }
00257 
00258 Item::List ItemFetchJob::items() const
00259 {
00260   Q_D( const ItemFetchJob );
00261 
00262   return d->mItems;
00263 }
00264 
00265 void ItemFetchJob::setFetchScope( ItemFetchScope &fetchScope )
00266 {
00267   Q_D( ItemFetchJob );
00268 
00269   d->mFetchScope = fetchScope;
00270 }
00271 
00272 ItemFetchScope &ItemFetchJob::fetchScope()
00273 {
00274   Q_D( ItemFetchJob );
00275 
00276   return d->mFetchScope;
00277 }
00278 
00279 #include "itemfetchjob.moc"

akonadi

Skip menu "akonadi"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  • kabc
  • kblog
  • kcal
  • kimap
  • kioslave
  •   imap4
  •   mbox
  • kldap
  • kmime
  • kpimidentities
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.5.6
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal