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

akonadi

  • akonadi
specialcollectionsrequestjob.cpp
1 /*
2  Copyright (c) 2009 Constantin Berzan <exit3219@gmail.com>
3 
4  This library is free software; you can redistribute it and/or modify it
5  under the terms of the GNU Library General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or (at your
7  option) any later version.
8 
9  This library is distributed in the hope that it will be useful, but WITHOUT
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12  License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to the
16  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  02110-1301, USA.
18 */
19 
20 #include "specialcollectionsrequestjob.h"
21 
22 #include "specialcollectionattribute_p.h"
23 #include "specialcollections.h"
24 #include "specialcollections_p.h"
25 #include "specialcollectionshelperjobs_p.h"
26 
27 #include "akonadi/agentmanager.h"
28 #include "akonadi/collectioncreatejob.h"
29 #include "akonadi/entitydisplayattribute.h"
30 
31 #include <KDebug>
32 
33 #include <QtCore/QVariant>
34 
35 using namespace Akonadi;
36 
40 class Akonadi::SpecialCollectionsRequestJobPrivate
41 {
42  public:
43  SpecialCollectionsRequestJobPrivate( SpecialCollections *collections, SpecialCollectionsRequestJob *qq );
44 
45  bool isEverythingReady();
46  void lockResult( KJob *job ); // slot
47  void releaseLock(); // slot
48  void nextResource();
49  void resourceScanResult( KJob *job ); // slot
50  void createRequestedFolders( ResourceScanJob *job, QHash<QByteArray, bool> &requestedFolders );
51  void collectionCreateResult( KJob *job ); // slot
52 
53  SpecialCollectionsRequestJob *q;
54  SpecialCollections *mSpecialCollections;
55  int mPendingCreateJobs;
56 
57  QByteArray mRequestedType;
58  AgentInstance mRequestedResource;
59 
60  // Input:
61  QHash<QByteArray, bool> mDefaultFolders;
62  bool mRequestingDefaultFolders;
63  QHash< QString, QHash<QByteArray, bool> > mFoldersForResource;
64  QString mDefaultResourceType;
65  QVariantMap mDefaultResourceOptions;
66  QList<QByteArray> mKnownTypes;
67  QMap<QByteArray, QString> mNameForTypeMap;
68  QMap<QByteArray, QString> mIconForTypeMap;
69 
70  // Output:
71  QStringList mToForget;
72  QVector< QPair<Collection, QByteArray> > mToRegister;
73 };
74 
75 
76 
77 SpecialCollectionsRequestJobPrivate::SpecialCollectionsRequestJobPrivate( SpecialCollections *collections,
78  SpecialCollectionsRequestJob *qq )
79  : q( qq ),
80  mSpecialCollections( collections ),
81  mPendingCreateJobs( 0 ),
82  mRequestingDefaultFolders( false )
83 {
84 }
85 
86 bool SpecialCollectionsRequestJobPrivate::isEverythingReady()
87 {
88  // check if all requested folders are known already
89  if ( mRequestingDefaultFolders ) {
90  QHashIterator<QByteArray, bool> it( mDefaultFolders );
91  while ( it.hasNext() ) {
92  it.next();
93  if ( it.value() && !mSpecialCollections->hasDefaultCollection( it.key() ) )
94  return false;
95  }
96  }
97 
98  const QStringList resourceIds = mFoldersForResource.keys();
99  QHashIterator< QString, QHash<QByteArray, bool> > resourceIt( mFoldersForResource );
100  while ( resourceIt.hasNext() ) {
101  resourceIt.next();
102 
103  const QHash<QByteArray, bool> &requested = resourceIt.value();
104  QHashIterator<QByteArray, bool> it( requested );
105  while ( it.hasNext() ) {
106  it.next();
107  if ( it.value() && !mSpecialCollections->hasCollection( it.key(), AgentManager::self()->instance( resourceIt.key() ) ) )
108  return false;
109  }
110  }
111 
112  return true;
113 }
114 
115 void SpecialCollectionsRequestJobPrivate::lockResult( KJob *job )
116 {
117  if ( job->error() ) {
118  kWarning() << "Failed to get lock:" << job->errorString();
119  q->setError( job->error() );
120  q->setErrorText( job->errorString() );
121  q->emitResult();
122  return;
123  }
124 
125  if ( mRequestingDefaultFolders ) {
126  // If default folders are requested, deal with that first.
127  DefaultResourceJob *resjob = new DefaultResourceJob( mSpecialCollections->d->mSettings, q );
128  resjob->setDefaultResourceType( mDefaultResourceType );
129  resjob->setDefaultResourceOptions( mDefaultResourceOptions );
130  resjob->setTypes( mKnownTypes );
131  resjob->setNameForTypeMap( mNameForTypeMap );
132  resjob->setIconForTypeMap( mIconForTypeMap );
133  QObject::connect( resjob, SIGNAL(result(KJob*)), q, SLOT(resourceScanResult(KJob*)) );
134  } else {
135  // If no default folders are requested, go straight to the next step.
136  nextResource();
137  }
138 }
139 
140 void SpecialCollectionsRequestJobPrivate::releaseLock()
141 {
142  const bool ok = Akonadi::releaseLock();
143  if ( !ok ) {
144  kWarning() << "WTF, can't release lock.";
145  }
146 }
147 
148 void SpecialCollectionsRequestJobPrivate::nextResource()
149 {
150  if ( mFoldersForResource.isEmpty() ) {
151  kDebug() << "All done! Comitting.";
152 
153  mSpecialCollections->d->beginBatchRegister();
154 
155  // Forget everything we knew before about these resources.
156  foreach ( const QString &resourceId, mToForget ) {
157  mSpecialCollections->d->forgetFoldersForResource( resourceId );
158  }
159 
160  // Register all the collections that we fetched / created.
161  typedef QPair<Collection, QByteArray> RegisterPair;
162  foreach ( const RegisterPair &pair, mToRegister ) {
163  const bool ok = mSpecialCollections->registerCollection( pair.second, pair.first );
164  Q_ASSERT( ok );
165  Q_UNUSED( ok );
166  }
167 
168  mSpecialCollections->d->endBatchRegister();
169 
170  // Release the lock once the transaction has been committed.
171  QObject::connect( q, SIGNAL(result(KJob*)), q, SLOT(releaseLock()) );
172 
173  // We are done!
174  q->commit();
175 
176  } else {
177  const QString resourceId = mFoldersForResource.keys().first();
178  kDebug() << "A resource is done," << mFoldersForResource.count()
179  << "more to do. Now doing resource" << resourceId;
180  ResourceScanJob *resjob = new ResourceScanJob( resourceId, mSpecialCollections->d->mSettings, q );
181  QObject::connect( resjob, SIGNAL(result(KJob*)), q, SLOT(resourceScanResult(KJob*)) );
182  }
183 }
184 
185 void SpecialCollectionsRequestJobPrivate::resourceScanResult( KJob *job )
186 {
187  ResourceScanJob *resjob = qobject_cast<ResourceScanJob*>( job );
188  Q_ASSERT( resjob );
189 
190  const QString resourceId = resjob->resourceId();
191  kDebug() << "resourceId" << resourceId;
192 
193  if ( job->error() ) {
194  kWarning() << "Failed to request resource" << resourceId << ":" << job->errorString();
195  return;
196  }
197 
198  if ( qobject_cast<DefaultResourceJob*>( job ) ) {
199  // This is the default resource.
200  if ( resourceId != mSpecialCollections->d->defaultResourceId() ) {
201  kError() << "Resource id's don't match: " << resourceId
202  << mSpecialCollections->d->defaultResourceId();
203  Q_ASSERT( false );
204  }
205  //mToForget.append( mSpecialCollections->defaultResourceId() );
206  createRequestedFolders( resjob, mDefaultFolders );
207  } else {
208  // This is not the default resource.
209  QHash<QByteArray, bool> requestedFolders = mFoldersForResource[ resourceId ];
210  mFoldersForResource.remove( resourceId );
211  createRequestedFolders( resjob, requestedFolders );
212  }
213 }
214 
215 void SpecialCollectionsRequestJobPrivate::createRequestedFolders( ResourceScanJob *scanJob,
216  QHash<QByteArray, bool> &requestedFolders )
217 {
218  // Remove from the request list the folders which already exist.
219  foreach ( const Collection &collection, scanJob->specialCollections() ) {
220  Q_ASSERT( collection.hasAttribute<SpecialCollectionAttribute>() );
221  const SpecialCollectionAttribute *attr = collection.attribute<SpecialCollectionAttribute>();
222  const QByteArray type = attr->collectionType();
223 
224  if ( !type.isEmpty() ) {
225  mToRegister.append( qMakePair( collection, type ) );
226  requestedFolders.insert( type, false );
227  }
228  }
229  mToForget.append( scanJob->resourceId() );
230 
231  // Folders left in the request list must be created.
232  Q_ASSERT( mPendingCreateJobs == 0 );
233  Q_ASSERT( scanJob->rootResourceCollection().isValid() );
234 
235  QHashIterator<QByteArray, bool> it( requestedFolders );
236  while ( it.hasNext() ) {
237  it.next();
238 
239  if ( it.value() ) {
240  Collection collection;
241  collection.setParentCollection( scanJob->rootResourceCollection() );
242  collection.setName( mNameForTypeMap.value( it.key() ) );
243 
244  setCollectionAttributes( collection, it.key(), mNameForTypeMap, mIconForTypeMap );
245 
246  CollectionCreateJob *createJob = new CollectionCreateJob( collection, q );
247  createJob->setProperty( "type", it.key() );
248  QObject::connect( createJob, SIGNAL(result(KJob*)), q, SLOT(collectionCreateResult(KJob*)) );
249 
250  mPendingCreateJobs++;
251  }
252  }
253 
254  if ( mPendingCreateJobs == 0 )
255  nextResource();
256 }
257 
258 void SpecialCollectionsRequestJobPrivate::collectionCreateResult( KJob *job )
259 {
260  if ( job->error() ) {
261  kWarning() << "Failed CollectionCreateJob." << job->errorString();
262  return;
263  }
264 
265  CollectionCreateJob *createJob = qobject_cast<CollectionCreateJob*>( job );
266  Q_ASSERT( createJob );
267 
268  const Collection collection = createJob->collection();
269  mToRegister.append( qMakePair( collection, createJob->property( "type" ).toByteArray() ) );
270 
271  Q_ASSERT( mPendingCreateJobs > 0 );
272  mPendingCreateJobs--;
273  kDebug() << "mPendingCreateJobs now" << mPendingCreateJobs;
274 
275  if ( mPendingCreateJobs == 0 )
276  nextResource();
277 }
278 
279 
280 
281 // TODO KDE5: do not inherit from TransactionSequence
282 SpecialCollectionsRequestJob::SpecialCollectionsRequestJob( SpecialCollections *collections, QObject *parent )
283  : TransactionSequence( parent ),
284  d( new SpecialCollectionsRequestJobPrivate( collections, this ) )
285 {
286  setProperty( "transactionsDisabled", true );
287 }
288 
289 SpecialCollectionsRequestJob::~SpecialCollectionsRequestJob()
290 {
291  delete d;
292 }
293 
294 void SpecialCollectionsRequestJob::requestDefaultCollection( const QByteArray &type )
295 {
296  d->mDefaultFolders[ type ] = true;
297  d->mRequestingDefaultFolders = true;
298  d->mRequestedType = type;
299 }
300 
301 void SpecialCollectionsRequestJob::requestCollection( const QByteArray &type, const AgentInstance &instance )
302 {
303  d->mFoldersForResource[ instance.identifier() ][ type ] = true;
304  d->mRequestedType = type;
305  d->mRequestedResource = instance;
306 }
307 
308 Akonadi::Collection SpecialCollectionsRequestJob::collection() const
309 {
310  if ( d->mRequestedResource.isValid() )
311  return d->mSpecialCollections->collection( d->mRequestedType, d->mRequestedResource );
312  else
313  return d->mSpecialCollections->defaultCollection( d->mRequestedType );
314 }
315 
316 void SpecialCollectionsRequestJob::setDefaultResourceType( const QString &type )
317 {
318  d->mDefaultResourceType = type;
319 }
320 
321 void SpecialCollectionsRequestJob::setDefaultResourceOptions( const QVariantMap &options )
322 {
323  d->mDefaultResourceOptions = options;
324 }
325 
326 void SpecialCollectionsRequestJob::setTypes( const QList<QByteArray> &types )
327 {
328  d->mKnownTypes = types;
329 }
330 
331 void SpecialCollectionsRequestJob::setNameForTypeMap( const QMap<QByteArray, QString> &map )
332 {
333  d->mNameForTypeMap = map;
334 }
335 
336 void SpecialCollectionsRequestJob::setIconForTypeMap( const QMap<QByteArray, QString> &map )
337 {
338  d->mIconForTypeMap = map;
339 }
340 
341 void SpecialCollectionsRequestJob::doStart()
342 {
343  if ( d->isEverythingReady() ) {
344  emitResult();
345  } else {
346  GetLockJob *lockJob = new GetLockJob( this );
347  connect( lockJob, SIGNAL(result(KJob*)), this, SLOT(lockResult(KJob*)) );
348  lockJob->start();
349  }
350 }
351 
352 void SpecialCollectionsRequestJob::slotResult( KJob *job )
353 {
354  if ( job->error() ) {
355  // If we failed, let others try.
356  kWarning() << "Failed SpecialCollectionsRequestJob::slotResult" << job->errorString();
357 
358  d->releaseLock();
359  }
360  TransactionSequence::slotResult( job );
361 }
362 
363 #include "moc_specialcollectionsrequestjob.cpp"
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Sat Jul 13 2013 01:27:41 by doxygen 1.8.3.1 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.10.5 API Reference

Skip menu "kdepimlibs-4.10.5 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • 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