00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "itemfetchjob.h"
00021
00022 #include "attributefactory.h"
00023 #include "collection.h"
00024 #include "collectionselectjob_p.h"
00025 #include "imapparser_p.h"
00026 #include "itemfetchscope.h"
00027 #include "job_p.h"
00028 #include "protocol_p.h"
00029 #include "protocolhelper_p.h"
00030
00031 #include <kdebug.h>
00032 #include <KLocale>
00033
00034 #include <QtCore/QStringList>
00035 #include <QtCore/QTimer>
00036
00037 using namespace Akonadi;
00038
00039 class Akonadi::ItemFetchJobPrivate : public JobPrivate
00040 {
00041 public:
00042 ItemFetchJobPrivate( ItemFetchJob *parent )
00043 : JobPrivate( parent ),
00044 mValuePool( 0 )
00045 {
00046 mCollection = Collection::root();
00047 }
00048
00049 ~ItemFetchJobPrivate()
00050 {
00051 delete mValuePool;
00052 }
00053
00054 void init()
00055 {
00056 Q_Q( ItemFetchJob );
00057 mEmitTimer = new QTimer( q );
00058 mEmitTimer->setSingleShot( true );
00059 mEmitTimer->setInterval( 100 );
00060 q->connect( mEmitTimer, SIGNAL( timeout() ), q, SLOT( timeout() ) );
00061 q->connect( q, SIGNAL( result( KJob* ) ), q, SLOT( timeout() ) );
00062 }
00063
00064 void timeout()
00065 {
00066 Q_Q( ItemFetchJob );
00067
00068 mEmitTimer->stop();
00069 if ( !mPendingItems.isEmpty() ) {
00070 if ( !q->error() )
00071 emit q->itemsReceived( mPendingItems );
00072 mPendingItems.clear();
00073 }
00074 }
00075
00076 void startFetchJob();
00077 void selectDone( KJob * job );
00078
00079 Q_DECLARE_PUBLIC( ItemFetchJob )
00080
00081 Collection mCollection;
00082 Item::List mRequestedItems;
00083 Item::List mResultItems;
00084 ItemFetchScope mFetchScope;
00085 Item::List mPendingItems;
00086 QTimer* mEmitTimer;
00087 ProtocolHelperValuePool *mValuePool;
00088 };
00089
00090 void ItemFetchJobPrivate::startFetchJob()
00091 {
00092 Q_Q( ItemFetchJob );
00093 QByteArray command = newTag();
00094 if ( mRequestedItems.isEmpty() ) {
00095 command += " " AKONADI_CMD_ITEMFETCH " 1:*";
00096 } else {
00097 try {
00098 command += ProtocolHelper::entitySetToByteArray( mRequestedItems, AKONADI_CMD_ITEMFETCH );
00099 } catch ( const Exception &e ) {
00100 q->setError( Job::Unknown );
00101 q->setErrorText( QString::fromUtf8( e.what() ) );
00102 q->emitResult();
00103 return;
00104 }
00105 }
00106
00107 command += ProtocolHelper::itemFetchScopeToByteArray( mFetchScope );
00108
00109 writeData( command );
00110 }
00111
00112 void ItemFetchJobPrivate::selectDone( KJob * job )
00113 {
00114 if ( !job->error() )
00115
00116 startFetchJob();
00117 }
00118
00119 ItemFetchJob::ItemFetchJob( const Collection &collection, QObject * parent )
00120 : Job( new ItemFetchJobPrivate( this ), parent )
00121 {
00122 Q_D( ItemFetchJob );
00123
00124 d->init();
00125 d->mCollection = collection;
00126 d->mValuePool = new ProtocolHelperValuePool;
00127 }
00128
00129 ItemFetchJob::ItemFetchJob( const Item & item, QObject * parent)
00130 : Job( new ItemFetchJobPrivate( this ), parent )
00131 {
00132 Q_D( ItemFetchJob );
00133
00134 d->init();
00135 d->mRequestedItems.append( item );
00136 }
00137
00138 ItemFetchJob::ItemFetchJob(const Akonadi::Item::List& items, QObject* parent)
00139 : Job( new ItemFetchJobPrivate( this ), parent )
00140 {
00141 Q_D( ItemFetchJob );
00142
00143 d->init();
00144 d->mRequestedItems = items;
00145 }
00146
00147
00148 ItemFetchJob::~ItemFetchJob()
00149 {
00150 }
00151
00152 void ItemFetchJob::doStart()
00153 {
00154 Q_D( ItemFetchJob );
00155
00156 if ( d->mRequestedItems.isEmpty() ) {
00157 if ( d->mCollection == Collection::root() ) {
00158 setErrorText( i18n( "Cannot list root collection." ) );
00159 setError( Unknown );
00160 emitResult();
00161 }
00162 CollectionSelectJob *job = new CollectionSelectJob( d->mCollection, this );
00163 connect( job, SIGNAL( result( KJob* ) ), SLOT( selectDone( KJob* ) ) );
00164 addSubjob( job );
00165 } else
00166 d->startFetchJob();
00167 }
00168
00169 void ItemFetchJob::doHandleResponse( const QByteArray & tag, const QByteArray & data )
00170 {
00171 Q_D( ItemFetchJob );
00172
00173 if ( tag == "*" ) {
00174 int begin = data.indexOf( "FETCH" );
00175 if ( begin >= 0 ) {
00176
00177
00178 QList<QByteArray> fetchResponse;
00179 ImapParser::parseParenthesizedList( data, fetchResponse, begin + 6 );
00180
00181 Item item;
00182 ProtocolHelper::parseItemFetchResult( fetchResponse, item, d->mValuePool );
00183 if ( !item.isValid() )
00184 return;
00185
00186 d->mResultItems.append( item );
00187 d->mPendingItems.append( item );
00188 if ( !d->mEmitTimer->isActive() )
00189 d->mEmitTimer->start();
00190 return;
00191 }
00192 }
00193 kDebug() << "Unhandled response: " << tag << data;
00194 }
00195
00196 Item::List ItemFetchJob::items() const
00197 {
00198 Q_D( const ItemFetchJob );
00199
00200 return d->mResultItems;
00201 }
00202
00203 void ItemFetchJob::setFetchScope( ItemFetchScope &fetchScope )
00204 {
00205 Q_D( ItemFetchJob );
00206
00207 d->mFetchScope = fetchScope;
00208 }
00209
00210 void ItemFetchJob::setFetchScope( const ItemFetchScope &fetchScope )
00211 {
00212 Q_D( ItemFetchJob );
00213
00214 d->mFetchScope = fetchScope;
00215 }
00216
00217 ItemFetchScope &ItemFetchJob::fetchScope()
00218 {
00219 Q_D( ItemFetchJob );
00220
00221 return d->mFetchScope;
00222 }
00223
00224 void ItemFetchJob::setCollection(const Akonadi::Collection& collection)
00225 {
00226 Q_D( ItemFetchJob );
00227
00228 d->mCollection = collection;
00229 }
00230
00231
00232 #include "itemfetchjob.moc"