• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.8.3 API Reference
  • KDE Home
  • Contact Us
 

akonadi

specialcollectionsrequestjob.cpp
00001 /*
00002     Copyright (c) 2009 Constantin Berzan <exit3219@gmail.com>
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 "specialcollectionsrequestjob.h"
00021 
00022 #include "specialcollectionattribute_p.h"
00023 #include "specialcollections.h"
00024 #include "specialcollections_p.h"
00025 #include "specialcollectionshelperjobs_p.h"
00026 
00027 #include "akonadi/agentmanager.h"
00028 #include "akonadi/collectioncreatejob.h"
00029 #include "akonadi/entitydisplayattribute.h"
00030 
00031 #include <KDebug>
00032 
00033 #include <QtCore/QVariant>
00034 
00035 using namespace Akonadi;
00036 
00040 class Akonadi::SpecialCollectionsRequestJobPrivate
00041 {
00042   public:
00043     SpecialCollectionsRequestJobPrivate( SpecialCollections *collections, SpecialCollectionsRequestJob *qq );
00044 
00045     bool isEverythingReady();
00046     void lockResult( KJob *job ); // slot
00047     void releaseLock(); // slot
00048     void nextResource();
00049     void resourceScanResult( KJob *job ); // slot
00050     void createRequestedFolders( ResourceScanJob *job, QHash<QByteArray, bool> &requestedFolders );
00051     void collectionCreateResult( KJob *job ); // slot
00052 
00053     SpecialCollectionsRequestJob *q;
00054     SpecialCollections *mSpecialCollections;
00055     int mPendingCreateJobs;
00056 
00057     QByteArray mRequestedType;
00058     AgentInstance mRequestedResource;
00059 
00060     // Input:
00061     QHash<QByteArray, bool> mDefaultFolders;
00062     bool mRequestingDefaultFolders;
00063     QHash< QString, QHash<QByteArray, bool> > mFoldersForResource;
00064     QString mDefaultResourceType;
00065     QVariantMap mDefaultResourceOptions;
00066     QList<QByteArray> mKnownTypes;
00067     QMap<QByteArray, QString> mNameForTypeMap;
00068     QMap<QByteArray, QString> mIconForTypeMap;
00069 
00070     // Output:
00071     QStringList mToForget;
00072     QVector< QPair<Collection, QByteArray> > mToRegister;
00073 };
00074 
00075 
00076 
00077 SpecialCollectionsRequestJobPrivate::SpecialCollectionsRequestJobPrivate( SpecialCollections *collections,
00078                                                                           SpecialCollectionsRequestJob *qq )
00079   : q( qq ),
00080     mSpecialCollections( collections ),
00081     mPendingCreateJobs( 0 ),
00082     mRequestingDefaultFolders( false )
00083 {
00084 }
00085 
00086 bool SpecialCollectionsRequestJobPrivate::isEverythingReady()
00087 {
00088   // check if all requested folders are known already
00089   if ( mRequestingDefaultFolders ) {
00090     QHashIterator<QByteArray, bool> it( mDefaultFolders );
00091     while ( it.hasNext() ) {
00092       it.next();
00093       if ( it.value() && !mSpecialCollections->hasDefaultCollection( it.key() ) )
00094         return false;
00095     }
00096   }
00097 
00098   const QStringList resourceIds = mFoldersForResource.keys();
00099   QHashIterator< QString, QHash<QByteArray, bool> > resourceIt( mFoldersForResource );
00100   while ( resourceIt.hasNext() ) {
00101     resourceIt.next();
00102 
00103     const QHash<QByteArray, bool> &requested = resourceIt.value();
00104     QHashIterator<QByteArray, bool> it( requested );
00105     while ( it.hasNext() ) {
00106       it.next();
00107       if ( it.value() && !mSpecialCollections->hasCollection( it.key(), AgentManager::self()->instance( resourceIt.key() ) ) )
00108         return false;
00109     }
00110   }
00111 
00112   return true;
00113 }
00114 
00115 void SpecialCollectionsRequestJobPrivate::lockResult( KJob *job )
00116 {
00117   if ( job->error() ) {
00118     kWarning() << "Failed to get lock:" << job->errorString();
00119     q->setError( job->error() );
00120     q->setErrorText( job->errorString() );
00121     q->emitResult();
00122     return;
00123   }
00124 
00125   if ( mRequestingDefaultFolders ) {
00126     // If default folders are requested, deal with that first.
00127     DefaultResourceJob *resjob = new DefaultResourceJob( mSpecialCollections->d->mSettings, q );
00128     resjob->setDefaultResourceType( mDefaultResourceType );
00129     resjob->setDefaultResourceOptions( mDefaultResourceOptions );
00130     resjob->setTypes( mKnownTypes );
00131     resjob->setNameForTypeMap( mNameForTypeMap );
00132     resjob->setIconForTypeMap( mIconForTypeMap );
00133     QObject::connect( resjob, SIGNAL(result(KJob*)), q, SLOT(resourceScanResult(KJob*)) );
00134   } else {
00135     // If no default folders are requested, go straight to the next step.
00136     nextResource();
00137   }
00138 }
00139 
00140 void SpecialCollectionsRequestJobPrivate::releaseLock()
00141 {
00142   const bool ok = Akonadi::releaseLock();
00143   if ( !ok ) {
00144     kWarning() << "WTF, can't release lock.";
00145   }
00146 }
00147 
00148 void SpecialCollectionsRequestJobPrivate::nextResource()
00149 {
00150   if ( mFoldersForResource.isEmpty() ) {
00151     kDebug() << "All done! Comitting.";
00152 
00153     mSpecialCollections->d->beginBatchRegister();
00154 
00155     // Forget everything we knew before about these resources.
00156     foreach ( const QString &resourceId, mToForget ) {
00157       mSpecialCollections->d->forgetFoldersForResource( resourceId );
00158     }
00159 
00160     // Register all the collections that we fetched / created.
00161     typedef QPair<Collection, QByteArray> RegisterPair;
00162     foreach ( const RegisterPair &pair, mToRegister ) {
00163       const bool ok = mSpecialCollections->registerCollection( pair.second, pair.first );
00164       Q_ASSERT( ok );
00165       Q_UNUSED( ok );
00166     }
00167 
00168     mSpecialCollections->d->endBatchRegister();
00169 
00170     // Release the lock once the transaction has been committed.
00171     QObject::connect( q, SIGNAL(result(KJob*)), q, SLOT(releaseLock()) );
00172 
00173     // We are done!
00174     q->commit();
00175 
00176   } else {
00177     const QString resourceId = mFoldersForResource.keys().first();
00178     kDebug() << "A resource is done," << mFoldersForResource.count()
00179              << "more to do. Now doing resource" << resourceId;
00180     ResourceScanJob *resjob = new ResourceScanJob( resourceId, mSpecialCollections->d->mSettings, q );
00181     QObject::connect( resjob, SIGNAL(result(KJob*)), q, SLOT(resourceScanResult(KJob*)) );
00182   }
00183 }
00184 
00185 void SpecialCollectionsRequestJobPrivate::resourceScanResult( KJob *job )
00186 {
00187   ResourceScanJob *resjob = qobject_cast<ResourceScanJob*>( job );
00188   Q_ASSERT( resjob );
00189 
00190   const QString resourceId = resjob->resourceId();
00191   kDebug() << "resourceId" << resourceId;
00192 
00193   if ( job->error() ) {
00194     kWarning() << "Failed to request resource" << resourceId << ":" << job->errorString();
00195     return;
00196   }
00197 
00198   if ( qobject_cast<DefaultResourceJob*>( job ) ) {
00199     // This is the default resource.
00200     if ( resourceId != mSpecialCollections->d->defaultResourceId() ) {
00201       kError() << "Resource id's don't match: " << resourceId
00202                << mSpecialCollections->d->defaultResourceId();
00203       Q_ASSERT( false );
00204     }
00205     //mToForget.append( mSpecialCollections->defaultResourceId() );
00206     createRequestedFolders( resjob, mDefaultFolders );
00207   } else {
00208     // This is not the default resource.
00209     QHash<QByteArray, bool> requestedFolders = mFoldersForResource[ resourceId ];
00210     mFoldersForResource.remove( resourceId );
00211     createRequestedFolders( resjob, requestedFolders );
00212   }
00213 }
00214 
00215 void SpecialCollectionsRequestJobPrivate::createRequestedFolders( ResourceScanJob *scanJob,
00216                                                                   QHash<QByteArray, bool> &requestedFolders )
00217 {
00218   // Remove from the request list the folders which already exist.
00219   foreach ( const Collection &collection, scanJob->specialCollections() ) {
00220     Q_ASSERT( collection.hasAttribute<SpecialCollectionAttribute>() );
00221     const SpecialCollectionAttribute *attr = collection.attribute<SpecialCollectionAttribute>();
00222     const QByteArray type = attr->collectionType();
00223 
00224     if ( !type.isEmpty() ) {
00225       mToRegister.append( qMakePair( collection, type ) );
00226       requestedFolders.insert( type, false );
00227     }
00228   }
00229   mToForget.append( scanJob->resourceId() );
00230 
00231   // Folders left in the request list must be created.
00232   Q_ASSERT( mPendingCreateJobs == 0 );
00233   Q_ASSERT( scanJob->rootResourceCollection().isValid() );
00234 
00235   QHashIterator<QByteArray, bool> it( requestedFolders );
00236   while ( it.hasNext() ) {
00237     it.next();
00238 
00239     if ( it.value() ) {
00240       Collection collection;
00241       collection.setParentCollection( scanJob->rootResourceCollection() );
00242       collection.setName( mNameForTypeMap.value( it.key() ) );
00243 
00244       setCollectionAttributes( collection, it.key(), mNameForTypeMap, mIconForTypeMap );
00245 
00246       CollectionCreateJob *createJob = new CollectionCreateJob( collection, q );
00247       createJob->setProperty( "type", it.key() );
00248       QObject::connect( createJob, SIGNAL(result(KJob*)), q, SLOT(collectionCreateResult(KJob*)) );
00249 
00250       mPendingCreateJobs++;
00251     }
00252   }
00253 
00254   if ( mPendingCreateJobs == 0 )
00255     nextResource();
00256 }
00257 
00258 void SpecialCollectionsRequestJobPrivate::collectionCreateResult( KJob *job )
00259 {
00260   if ( job->error() ) {
00261     kWarning() << "Failed CollectionCreateJob." << job->errorString();
00262     return;
00263   }
00264 
00265   CollectionCreateJob *createJob = qobject_cast<CollectionCreateJob*>( job );
00266   Q_ASSERT( createJob );
00267 
00268   const Collection collection = createJob->collection();
00269   mToRegister.append( qMakePair( collection, createJob->property( "type" ).toByteArray() ) );
00270 
00271   Q_ASSERT( mPendingCreateJobs > 0 );
00272   mPendingCreateJobs--;
00273   kDebug() << "mPendingCreateJobs now" << mPendingCreateJobs;
00274 
00275   if ( mPendingCreateJobs == 0 )
00276     nextResource();
00277 }
00278 
00279 
00280 
00281 // TODO KDE5: do not inherit from TransactionSequence
00282 SpecialCollectionsRequestJob::SpecialCollectionsRequestJob( SpecialCollections *collections, QObject *parent )
00283   : TransactionSequence( parent ),
00284     d( new SpecialCollectionsRequestJobPrivate( collections, this ) )
00285 {
00286   setProperty( "transactionsDisabled", true );
00287 }
00288 
00289 SpecialCollectionsRequestJob::~SpecialCollectionsRequestJob()
00290 {
00291   delete d;
00292 }
00293 
00294 void SpecialCollectionsRequestJob::requestDefaultCollection( const QByteArray &type )
00295 {
00296   d->mDefaultFolders[ type ] = true;
00297   d->mRequestingDefaultFolders = true;
00298   d->mRequestedType = type;
00299 }
00300 
00301 void SpecialCollectionsRequestJob::requestCollection( const QByteArray &type, const AgentInstance &instance )
00302 {
00303   if ( !d->mFoldersForResource.contains( instance.identifier() ) ) {
00304     // This resource was previously unknown.
00305     d->mFoldersForResource[ instance.identifier() ] = QHash<QByteArray, bool>();
00306   }
00307   d->mFoldersForResource[ instance.identifier() ][ type ] = true;
00308 
00309   d->mRequestedType = type;
00310   d->mRequestedResource = instance;
00311 }
00312 
00313 Akonadi::Collection SpecialCollectionsRequestJob::collection() const
00314 {
00315   if ( d->mRequestedResource.isValid() )
00316     return d->mSpecialCollections->collection( d->mRequestedType, d->mRequestedResource );
00317   else
00318     return d->mSpecialCollections->defaultCollection( d->mRequestedType );
00319 }
00320 
00321 void SpecialCollectionsRequestJob::setDefaultResourceType( const QString &type )
00322 {
00323   d->mDefaultResourceType = type;
00324 }
00325 
00326 void SpecialCollectionsRequestJob::setDefaultResourceOptions( const QVariantMap &options )
00327 {
00328   d->mDefaultResourceOptions = options;
00329 }
00330 
00331 void SpecialCollectionsRequestJob::setTypes( const QList<QByteArray> &types )
00332 {
00333   d->mKnownTypes = types;
00334 }
00335 
00336 void SpecialCollectionsRequestJob::setNameForTypeMap( const QMap<QByteArray, QString> &map )
00337 {
00338   d->mNameForTypeMap = map;
00339 }
00340 
00341 void SpecialCollectionsRequestJob::setIconForTypeMap( const QMap<QByteArray, QString> &map )
00342 {
00343   d->mIconForTypeMap = map;
00344 }
00345 
00346 void SpecialCollectionsRequestJob::doStart()
00347 {
00348   if ( d->isEverythingReady() ) {
00349     emitResult();
00350   } else {
00351     GetLockJob *lockJob = new GetLockJob( this );
00352     connect( lockJob, SIGNAL(result(KJob*)), this, SLOT(lockResult(KJob*)) );
00353     lockJob->start();
00354   }
00355 }
00356 
00357 void SpecialCollectionsRequestJob::slotResult( KJob *job )
00358 {
00359   if ( job->error() ) {
00360     // If we failed, let others try.
00361     kWarning() << "Failed SpecialCollectionsRequestJob::slotResult" << job->errorString();
00362 
00363     d->releaseLock();
00364   }
00365   TransactionSequence::slotResult( job );
00366 }
00367 
00368 #include "specialcollectionsrequestjob.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon May 14 2012 04:53:00 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi

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

kdepimlibs-4.8.3 API Reference

Skip menu "kdepimlibs-4.8.3 API Reference"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal