20 #include "collectionfetchjob.h"
22 #include "imapparser_p.h"
24 #include "protocol_p.h"
25 #include "protocolhelper_p.h"
27 #include "collectionfetchscope.h"
28 #include "collectionutils_p.h"
33 #include <QtCore/QHash>
34 #include <QtCore/QStringList>
35 #include <QtCore/QTimer>
37 using namespace Akonadi;
39 class Akonadi::CollectionFetchJobPrivate :
public JobPrivate
43 :
JobPrivate( parent ), mEmitTimer( 0 ), mBasePrefetch( false )
50 mEmitTimer =
new QTimer( q_ptr );
51 mEmitTimer->setSingleShot(
true );
52 mEmitTimer->setInterval( 100 );
53 q_ptr->connect( mEmitTimer, SIGNAL(timeout()), q_ptr, SLOT(timeout()) );
54 q_ptr->connect( q_ptr, SIGNAL(result(KJob*)), q_ptr, SLOT(timeout()) );
74 if ( !mPendingCollections.isEmpty() ) {
76 emit q->collectionsReceived( mPendingCollections );
78 mPendingCollections.clear();
84 mPendingCollections += collections;
85 if ( !mEmitTimer->isActive() ) {
90 void flushIterativeResult()
94 if ( mPendingCollections.isEmpty() ) {
98 emit q->collectionsReceived( mPendingCollections );
99 mPendingCollections.clear();
104 :
Job( new CollectionFetchJobPrivate( this ), parent )
109 d->mBase = collection;
114 :
Job( new CollectionFetchJobPrivate( this ), parent )
119 Q_ASSERT( !cols.isEmpty() );
120 if ( cols.size() == 1 ) {
121 d->mBase = cols.first();
129 :
Job( new CollectionFetchJobPrivate( this ), parent )
134 Q_ASSERT( !cols.isEmpty() );
135 if ( cols.size() == 1 ) {
136 d->mBase = cols.first();
144 :
Job( new CollectionFetchJobPrivate( this ), parent )
149 Q_ASSERT( !cols.isEmpty() );
150 if ( cols.size() == 1 ) {
168 return d->mCollections;
175 if ( !d->mBaseList.isEmpty() ) {
182 d->mBasePrefetch =
true;
187 foreach (
const Collection &col, d->mBaseList ) {
194 foreach (
const Collection &col, d->mBaseList ) {
203 if ( !d->mBase.isValid() && d->mBase.remoteId().isEmpty() ) {
205 setErrorText( i18n(
"Invalid collection given." ) );
210 QByteArray command = d->newTag();
211 if ( !d->mBase.isValid() ) {
212 if ( CollectionUtils::hasValidHierarchicalRID( d->mBase ) ) {
215 command +=
" " AKONADI_CMD_RID;
218 if ( d->mScope.includeUnsubscribed() ) {
224 if ( d->mBase.isValid() ) {
225 command += QByteArray::number( d->mBase.id() );
226 }
else if ( CollectionUtils::hasValidHierarchicalRID( d->mBase ) ) {
229 command += ImapParser::quote( d->mBase.remoteId().toUtf8() );
233 switch ( d->mType ) {
247 QList<QByteArray> filter;
248 if ( !d->mScope.resource().isEmpty() ) {
249 filter.append(
"RESOURCE" );
251 filter.append( d->mScope.resource().toUtf8() );
254 if ( !d->mScope.contentMimeTypes().isEmpty() ) {
255 filter.append(
"MIMETYPE" );
256 QList<QByteArray> mts;
257 foreach (
const QString &mt, d->mScope.contentMimeTypes() ) {
259 mts.append( mt.toUtf8() );
261 filter.append(
'(' + ImapParser::join( mts,
" " ) +
')' );
264 QList<QByteArray> options;
265 if ( d->mScope.includeStatistics() ) {
266 options.append(
"STATISTICS" );
267 options.append(
"true" );
270 options.append(
"ANCESTORS" );
271 switch ( d->mScope.ancestorRetrieval() ) {
273 options.append(
"0" );
276 options.append(
"1" );
279 options.append(
"INF" );
286 command += ImapParser::join( filter,
" " ) +
") (" + ImapParser::join( options,
" " ) +
")\n";
287 d->writeData( command );
305 collection.d_ptr->resetChangeLog();
306 d->mCollections.append( collection );
307 d->mPendingCollections.append( collection );
308 if ( !d->mEmitTimer->isActive() ) {
309 d->mEmitTimer->start();
313 kDebug() <<
"Unhandled server response" << tag << data;
320 d->mScope.setResource( resource );
327 QVector<QList<Collection::Id> > ids;
328 foreach (
const Collection &collection, list ) {
329 QList<Collection::Id> ancestors;
331 ancestors << parent.
id();
335 QList<Collection::Id>::iterator i = qLowerBound( ancestors.begin(), ancestors.end(), parent.
id() );
336 ancestors.insert( i, parent.
id() );
342 QSet<Collection::Id> excludeList;
343 foreach (
const Collection &collection, list ) {
345 foreach (
const QList<Collection::Id> &ancestors, ids ) {
346 if ( qBinaryFind( ancestors, collection.
id() ) != ancestors.end() ) {
347 excludeList.insert( list.at( i ).id() );
353 foreach (
const Collection &collection, list ) {
354 if ( !excludeList.contains( collection.
id() ) ) {
355 result.append( collection );
362 void CollectionFetchJob::slotResult(KJob * job)
368 if ( d->mBasePrefetch ) {
369 d->mBasePrefetch =
false;
371 Job::slotResult( job );
372 Q_ASSERT( !hasSubjobs() );
373 if ( !job->error() ) {
383 Job::slotResult( job );
384 if ( !job->error() && !hasSubjobs() ) {
386 d->mPendingCollections += result;
387 d->mCollections = result;
388 d->flushIterativeResult();
396 list->d_func()->flushIterativeResult();
399 Job::slotResult( job );
400 if ( !job->error() && !hasSubjobs() ) {
410 d->mScope.setIncludeUnsubscribed( include );
417 d->mScope.setIncludeStatistics( include );
432 #include "moc_collectionfetchjob.cpp"