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

akonadi

  • sources
  • kde-4.12
  • kdepimlibs
  • akonadi
recursivemover.cpp
1 /*
2  Copyright (c) 2012 Volker Krause <vkrause@kde.org>
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 "recursivemover_p.h"
21 #include "collectionfetchjob.h"
22 #include "itemfetchjob.h"
23 #include "itemfetchscope.h"
24 #include "collectionfetchscope.h"
25 
26 using namespace Akonadi;
27 
28 RecursiveMover::RecursiveMover(AgentBasePrivate* parent): KCompositeJob(parent),
29  m_agentBase( parent ), m_currentAction( None ), m_runningJobs( 0 ), m_pendingReplay( false )
30 {
31 }
32 
33 void RecursiveMover::start()
34 {
35  Q_ASSERT( receivers(SIGNAL(result(KJob*))) );
36 
37  CollectionFetchJob *job = new CollectionFetchJob( m_movedCollection, CollectionFetchJob::Recursive, this );
38  connect( job, SIGNAL(finished(KJob*)), SLOT(collectionListResult(KJob*)) );
39  addSubjob( job );
40  ++m_runningJobs;
41 }
42 
43 void RecursiveMover::setCollection( const Collection &collection, const Collection &parentCollection )
44 {
45  m_movedCollection = collection;
46  m_collections.insert( collection.id(), m_movedCollection );
47  m_collections.insert( parentCollection.id(), parentCollection );
48 }
49 
50 void RecursiveMover::collectionListResult( KJob *job )
51 {
52  Q_ASSERT( m_pendingCollections.isEmpty() );
53  --m_runningJobs;
54 
55  if ( job->error() )
56  return; // error handling is in the base class
57 
58  // build a parent -> children map for the following topological sorting
59  // while we are iterating anyway, also fill m_collections here
60  CollectionFetchJob *fetchJob = qobject_cast<CollectionFetchJob*>( job );
61  QHash<Collection::Id, Collection::List> colTree;
62  foreach ( const Collection &col, fetchJob->collections() ) {
63  colTree[col.parentCollection().id()] << col;
64  m_collections.insert( col.id(), col );
65  }
66 
67  // topological sort; BFS traversal of the tree
68  m_pendingCollections.push_back( m_movedCollection );
69  QQueue<Collection> toBeProcessed;
70  toBeProcessed.enqueue( m_movedCollection );
71  while ( !toBeProcessed.isEmpty() ) {
72  const Collection col = toBeProcessed.dequeue();
73  const Collection::List children = colTree.value( col.id() );
74  if ( children.isEmpty() )
75  continue;
76  m_pendingCollections.append( children );
77  foreach ( const Collection &child, children )
78  toBeProcessed.enqueue( child );
79  }
80 
81  replayNextCollection();
82 }
83 
84 void RecursiveMover::collectionFetchResult( KJob *job )
85 {
86  Q_ASSERT( m_currentCollection.isValid() );
87  --m_runningJobs;
88 
89  if ( job->error() )
90  return; // error handling is in the base class
91 
92  CollectionFetchJob *fetchJob = qobject_cast<CollectionFetchJob*>( job );
93  if ( fetchJob->collections().size() == 1 ) {
94  m_currentCollection = fetchJob->collections().first();
95  m_currentCollection.setParentCollection( m_collections.value( m_currentCollection.parentCollection().id() ) );
96  m_collections.insert( m_currentCollection.id(), m_currentCollection );
97  } else {
98  // already deleted, move on
99  }
100 
101  if ( !m_runningJobs && m_pendingReplay )
102  replayNext();
103 }
104 
105 void RecursiveMover::itemListResult( KJob *job )
106 {
107  --m_runningJobs;
108 
109  if ( job->error() )
110  return; // error handling is in the base class
111 
112  foreach ( const Item &item, qobject_cast<ItemFetchJob*>( job )->items() ) {
113  if ( item.remoteId().isEmpty() )
114  m_pendingItems.push_back( item );
115  }
116 
117  if ( !m_runningJobs && m_pendingReplay )
118  replayNext();
119 }
120 
121 void RecursiveMover::itemFetchResult( KJob *job )
122 {
123  Q_ASSERT( m_currentAction == None );
124  --m_runningJobs;
125 
126  if ( job->error() )
127  return; // error handling is in the base class
128 
129  ItemFetchJob *fetchJob = qobject_cast<ItemFetchJob*>( job );
130  if ( fetchJob->items().size() == 1 ) {
131  m_currentAction = AddItem;
132  m_agentBase->itemAdded( fetchJob->items().first(), m_currentCollection );
133  } else {
134  // deleted since we started, skip
135  m_currentItem = Item();
136  replayNextItem();
137  }
138 }
139 
140 void RecursiveMover::replayNextCollection()
141 {
142  if ( !m_pendingCollections.isEmpty() ) {
143 
144  m_currentCollection = m_pendingCollections.takeFirst();
145  ItemFetchJob *job = new ItemFetchJob( m_currentCollection, this );
146  connect( job, SIGNAL(result(KJob*)), SLOT(itemListResult(KJob*)));
147  addSubjob( job );
148  ++m_runningJobs;
149 
150  if ( m_currentCollection.remoteId().isEmpty() ) {
151  Q_ASSERT( m_currentAction == None );
152  m_currentAction = AddCollection;
153  m_agentBase->collectionAdded( m_currentCollection, m_collections.value( m_currentCollection.parentCollection().id() ) );
154  return;
155  } else {
156  //replayNextItem(); - but waiting for the fetch job to finish first
157  m_pendingReplay = true;
158  return;
159  }
160  } else {
161  // nothing left to do
162  emitResult();
163  }
164 }
165 
166 void RecursiveMover::replayNextItem()
167 {
168  Q_ASSERT( m_currentCollection.isValid() );
169  if ( m_pendingItems.isEmpty() ) {
170  replayNextCollection(); // all items processed here
171  return;
172  } else {
173  Q_ASSERT( m_currentAction == None );
174  m_currentItem = m_pendingItems.takeFirst();
175  ItemFetchJob *job = new ItemFetchJob( m_currentItem, this );
176  job->fetchScope().fetchFullPayload();
177  connect( job, SIGNAL(result(KJob*)), SLOT(itemFetchResult(KJob*)) );
178  addSubjob( job );
179  ++m_runningJobs;
180  }
181 }
182 
183 void RecursiveMover::changeProcessed()
184 {
185  Q_ASSERT( m_currentAction != None );
186 
187  if ( m_currentAction == AddCollection ) {
188  Q_ASSERT( m_currentCollection.isValid() );
189  CollectionFetchJob *job = new CollectionFetchJob( m_currentCollection, CollectionFetchJob::Base, this );
190  job->fetchScope().setAncestorRetrieval( CollectionFetchScope::All );
191  connect( job, SIGNAL(result(KJob*)), SLOT(collectionFetchResult(KJob*)) );
192  addSubjob( job );
193  ++m_runningJobs;
194  }
195 
196  m_currentAction = None;
197 }
198 
199 void RecursiveMover::replayNext()
200 {
201  // wait for runnings jobs to finish before actually doing the replay
202  if ( m_runningJobs ) {
203  m_pendingReplay = true;
204  return;
205  }
206 
207  m_pendingReplay = false;
208 
209  if ( m_currentCollection.isValid() )
210  replayNextItem();
211  else
212  replayNextCollection();
213 }
214 
215 #include "moc_recursivemover_p.cpp"
Akonadi::CollectionFetchJob::collections
Collection::List collections() const
Returns the list of fetched collection.
Definition: collectionfetchjob.cpp:175
Akonadi::Collection
Represents a collection of PIM items.
Definition: collection.h:75
Akonadi::CollectionFetchJob
Job that fetches collections from the Akonadi storage.
Definition: collectionfetchjob.h:53
Akonadi::RecursiveMover::changeProcessed
void changeProcessed()
Call once the last replayed change has been processed.
Definition: recursivemover.cpp:183
Akonadi::Entity::setParentCollection
void setParentCollection(const Collection &parent)
Set the parent collection of this object.
Definition: entity.cpp:195
Akonadi::ItemFetchScope::fetchFullPayload
void fetchFullPayload(bool fetch=true)
Sets whether the full payload shall be fetched.
Definition: itemfetchscope.cpp:68
Akonadi::AgentBasePrivate
Definition: agentbase_p.h:38
Akonadi::ItemFetchJob::items
Item::List items() const
Returns the fetched items.
Definition: itemfetchjob.cpp:228
Akonadi::CollectionFetchJob::Base
Only fetch the base collection.
Definition: collectionfetchjob.h:62
Akonadi::ItemFetchJob::fetchScope
ItemFetchScope & fetchScope()
Returns the item fetch scope.
Definition: itemfetchjob.cpp:256
Akonadi::Entity::parentCollection
Collection parentCollection() const
Returns the parent collection of this object.
Definition: entity.cpp:186
Akonadi::Entity::remoteId
QString remoteId() const
Returns the remote id of the entity.
Definition: entity.cpp:82
Akonadi::CollectionFetchScope::All
Retrieve all ancestors, up to Collection::root()
Definition: collectionfetchscope.h:77
Akonadi::Entity::id
Id id() const
Returns the unique identifier of the entity.
Definition: entity.cpp:72
Akonadi::RecursiveMover::setCollection
void setCollection(const Akonadi::Collection &collection, const Akonadi::Collection &parentCollection)
Set the collection that is actually moved.
Definition: recursivemover.cpp:43
Akonadi::ItemFetchJob
Job that fetches items from the Akonadi storage.
Definition: itemfetchjob.h:82
Akonadi::Entity::isValid
bool isValid() const
Returns whether the entity is valid.
Definition: entity.cpp:97
Akonadi::RecursiveMover::replayNext
void replayNext()
Trigger the next change replay, will call emitResult() once everything has been replayed.
Definition: recursivemover.cpp:199
Akonadi::CollectionFetchJob::Recursive
List all sub-collections.
Definition: collectionfetchjob.h:64
Akonadi::Collection::List
QList< Collection > List
Describes a list of collections.
Definition: collection.h:81
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:00:27 by doxygen 1.8.7 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 API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kldap
  • kmbox
  • kmime
  • kpimidentities
  • kpimtextedit
  • kresources
  • ktnef
  • kxmlrpcclient
  • microblog

Search



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