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

akonadi

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

kdepimlibs-4.14.10 API Reference

Skip menu "kdepimlibs-4.14.10 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