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
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 );
77 mPendingCollections.clear();
83 mPendingCollections += collections;
84 if ( !mEmitTimer->isActive() )
88 void flushIterativeResult()
92 if ( mPendingCollections.isEmpty() )
95 emit q->collectionsReceived( mPendingCollections );
96 mPendingCollections.clear();
101 :
Job( new CollectionFetchJobPrivate( this ), parent )
106 d->mBase = collection;
111 :
Job( new CollectionFetchJobPrivate( this ), parent )
116 Q_ASSERT( !cols.isEmpty() );
117 if ( cols.size() == 1 ) {
118 d->mBase = cols.first();
126 :
Job( new CollectionFetchJobPrivate( this ), parent )
131 Q_ASSERT( !cols.isEmpty() );
132 if ( cols.size() == 1 ) {
133 d->mBase = cols.first();
141 :
Job( new CollectionFetchJobPrivate( this ), parent )
146 Q_ASSERT( !cols.isEmpty() );
147 if ( cols.size() == 1 ) {
164 return d->mCollections;
171 if ( !d->mBaseList.isEmpty() ) {
178 d->mBasePrefetch =
true;
183 foreach (
const Collection &col, d->mBaseList ) {
190 foreach (
const Collection &col, d->mBaseList ) {
199 if ( !d->mBase.isValid() && d->mBase.remoteId().isEmpty() ) {
201 setErrorText( i18n(
"Invalid collection given." ) );
206 QByteArray command = d->newTag();
207 if ( !d->mBase.isValid() ) {
208 if ( CollectionUtils::hasValidHierarchicalRID( d->mBase ) )
211 command +=
" " AKONADI_CMD_RID;
213 if ( d->mScope.includeUnsubscribed() )
218 if ( d->mBase.isValid() )
219 command += QByteArray::number( d->mBase.id() );
220 else if ( CollectionUtils::hasValidHierarchicalRID( d->mBase ) )
223 command += ImapParser::quote( d->mBase.remoteId().toUtf8() );
226 switch ( d->mType ) {
240 QList<QByteArray> filter;
241 if ( !d->mScope.resource().isEmpty() ) {
242 filter.append(
"RESOURCE" );
244 filter.append( d->mScope.resource().toUtf8() );
247 if ( !d->mScope.contentMimeTypes().isEmpty() ) {
248 filter.append(
"MIMETYPE" );
249 QList<QByteArray> mts;
250 foreach (
const QString &mt, d->mScope.contentMimeTypes() )
252 mts.append( mt.toUtf8() );
253 filter.append(
'(' + ImapParser::join( mts,
" " ) +
')' );
256 QList<QByteArray> options;
257 if ( d->mScope.includeStatistics() ) {
258 options.append(
"STATISTICS" );
259 options.append(
"true" );
262 options.append(
"ANCESTORS" );
263 switch ( d->mScope.ancestorRetrieval() ) {
265 options.append(
"0" );
268 options.append(
"1" );
271 options.append(
"INF" );
278 command += ImapParser::join( filter,
" " ) +
") (" + ImapParser::join( options,
" " ) +
")\n";
279 d->writeData( command );
295 collection.d_ptr->resetChangeLog();
296 d->mCollections.append( collection );
297 d->mPendingCollections.append( collection );
298 if ( !d->mEmitTimer->isActive() )
299 d->mEmitTimer->start();
302 kDebug() <<
"Unhandled server response" << tag << data;
309 d->mScope.setResource( resource );
316 QVector<QList<Collection::Id> > ids;
317 foreach(
const Collection &collection, list ) {
318 QList<Collection::Id> ancestors;
320 ancestors << parent.
id();
324 QList<Collection::Id>::iterator i = qLowerBound( ancestors.begin(), ancestors.end(), parent.
id() );
325 ancestors.insert( i, parent.
id() );
331 QSet<Collection::Id> excludeList;
332 foreach (
const Collection &collection, list ) {
334 foreach(
const QList<Collection::Id> &ancestors, ids ) {
335 if ( qBinaryFind( ancestors, collection.
id() ) != ancestors.end() ) {
336 excludeList.insert( list.at( i ).id() );
342 foreach (
const Collection &collection, list ) {
343 if ( !excludeList.contains( collection.
id() ) )
344 result.append( collection );
350 void CollectionFetchJob::slotResult(KJob * job)
356 if ( d->mBasePrefetch ) {
357 d->mBasePrefetch =
false;
359 Job::slotResult( job );
360 Q_ASSERT( !hasSubjobs() );
361 if ( !job->error() ) {
371 Job::slotResult( job );
372 if ( !job->error() && !hasSubjobs() ) {
374 d->mPendingCollections += result;
375 d->mCollections = result;
376 d->flushIterativeResult();
384 list->d_func()->flushIterativeResult();
387 Job::slotResult( job );
388 if ( !job->error() && !hasSubjobs() )
397 d->mScope.setIncludeUnsubscribed( include );
404 d->mScope.setIncludeStatistics( include );
419 #include "collectionfetchjob.moc"