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"
31 #include <KLocalizedString>
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();
102 QString jobDebuggingString()
const
105 return QString::fromLatin1(
"Collection Id %1" ).arg( mBase.
id() );
106 }
else if ( CollectionUtils::hasValidHierarchicalRID( mBase ) ) {
109 return QString::fromLatin1(
"Collection RemoteId %1" ).arg( mBase.
remoteId() );
115 :
Job( new CollectionFetchJobPrivate( this ), parent )
120 d->mBase = collection;
125 :
Job( new CollectionFetchJobPrivate( this ), parent )
130 Q_ASSERT( !cols.isEmpty() );
131 if ( cols.size() == 1 ) {
132 d->mBase = cols.first();
140 :
Job( new CollectionFetchJobPrivate( this ), parent )
145 Q_ASSERT( !cols.isEmpty() );
146 if ( cols.size() == 1 ) {
147 d->mBase = cols.first();
155 :
Job( new CollectionFetchJobPrivate( this ), parent )
160 Q_ASSERT( !cols.isEmpty() );
161 if ( cols.size() == 1 ) {
179 return d->mCollections;
186 if ( !d->mBaseList.isEmpty() ) {
193 d->mBasePrefetch =
true;
198 foreach (
const Collection &col, d->mBaseList ) {
205 foreach (
const Collection &col, d->mBaseList ) {
214 if ( !d->mBase.isValid() && d->mBase.remoteId().isEmpty() ) {
216 setErrorText( i18n(
"Invalid collection given." ) );
221 QByteArray command = d->newTag();
222 if ( !d->mBase.isValid() ) {
223 if ( CollectionUtils::hasValidHierarchicalRID( d->mBase ) ) {
226 command +=
" " AKONADI_CMD_RID;
229 if ( d->mScope.includeUnsubscribed() ) {
235 if ( d->mBase.isValid() ) {
236 command += QByteArray::number( d->mBase.id() );
237 }
else if ( CollectionUtils::hasValidHierarchicalRID( d->mBase ) ) {
240 command += ImapParser::quote( d->mBase.remoteId().toUtf8() );
244 switch ( d->mType ) {
258 QList<QByteArray> filter;
259 if ( !d->mScope.resource().isEmpty() ) {
260 filter.append(
"RESOURCE" );
262 filter.append( d->mScope.resource().toUtf8() );
265 if ( !d->mScope.contentMimeTypes().isEmpty() ) {
266 filter.append(
"MIMETYPE" );
267 QList<QByteArray> mts;
268 foreach (
const QString &mt, d->mScope.contentMimeTypes() ) {
270 mts.append( mt.toUtf8() );
272 filter.append(
'(' + ImapParser::join( mts,
" " ) +
')' );
275 QList<QByteArray> options;
276 if ( d->mScope.includeStatistics() ) {
277 options.append(
"STATISTICS" );
278 options.append(
"true" );
281 options.append(
"ANCESTORS" );
282 switch ( d->mScope.ancestorRetrieval() ) {
284 options.append(
"0" );
287 options.append(
"1" );
290 options.append(
"INF" );
297 command += ImapParser::join( filter,
" " ) +
") (" + ImapParser::join( options,
" " ) +
")\n";
298 d->writeData( command );
316 collection.d_ptr->resetChangeLog();
317 d->mCollections.append( collection );
318 d->mPendingCollections.append( collection );
319 if ( !d->mEmitTimer->isActive() ) {
320 d->mEmitTimer->start();
324 kDebug() <<
"Unhandled server response" << tag << data;
331 d->mScope.setResource( resource );
338 QVector<QList<Collection::Id> > ids;
339 foreach (
const Collection &collection, list ) {
340 QList<Collection::Id> ancestors;
342 ancestors << parent.
id();
346 QList<Collection::Id>::iterator i = qLowerBound( ancestors.begin(), ancestors.end(), parent.
id() );
347 ancestors.insert( i, parent.
id() );
353 QSet<Collection::Id> excludeList;
354 foreach (
const Collection &collection, list ) {
356 foreach (
const QList<Collection::Id> &ancestors, ids ) {
357 if ( qBinaryFind( ancestors, collection.
id() ) != ancestors.end() ) {
358 excludeList.insert( list.at( i ).id() );
364 foreach (
const Collection &collection, list ) {
365 if ( !excludeList.contains( collection.
id() ) ) {
366 result.append( collection );
373 void CollectionFetchJob::slotResult(KJob * job)
379 if ( d->mBasePrefetch ) {
380 d->mBasePrefetch =
false;
382 Job::slotResult( job );
383 Q_ASSERT( !hasSubjobs() );
384 if ( !job->error() ) {
394 Job::slotResult( job );
395 if ( !job->error() && !hasSubjobs() ) {
397 d->mPendingCollections += result;
398 d->mCollections = result;
399 d->flushIterativeResult();
407 list->d_func()->flushIterativeResult();
410 Job::slotResult( job );
411 if ( !job->error() && !hasSubjobs() ) {
421 d->mScope.setIncludeUnsubscribed( include );
428 d->mScope.setIncludeStatistics( include );
443 #include "moc_collectionfetchjob.cpp"