Akonadi

xmlwritejob.cpp
1 /*
2  SPDX-FileCopyrightText: 2009 Volker Krause <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "xmlwritejob.h"
8 #include "xmldocument.h"
9 #include "xmlwriter.h"
10 
11 #include "collectionfetchjob.h"
12 #include "item.h"
13 #include "itemfetchjob.h"
14 #include "itemfetchscope.h"
15 
16 #include <QDebug>
17 
18 #include <QDomElement>
19 #include <QStack>
20 
21 using namespace Akonadi;
22 
23 namespace Akonadi
24 {
25 class XmlWriteJobPrivate
26 {
27 public:
28  explicit XmlWriteJobPrivate(XmlWriteJob *parent)
29  : q(parent)
30  {
31  }
32 
33  XmlWriteJob *const q;
34  Collection::List roots;
35  QStack<Collection::List> pendingSiblings;
36  QStack<QDomElement> elementStack;
37  QString fileName;
38  XmlDocument document;
39 
40  void collectionFetchResult(KJob *job);
41  void processCollection();
42  void itemFetchResult(KJob *job);
43  void processItems();
44 };
45 
46 } // namespace Akonadi
47 
48 void XmlWriteJobPrivate::collectionFetchResult(KJob *job)
49 {
50  if (job->error()) {
51  return;
52  }
53  auto fetch = qobject_cast<CollectionFetchJob *>(job);
54  Q_ASSERT(fetch);
55  if (fetch->collections().isEmpty()) {
56  processItems();
57  } else {
58  pendingSiblings.push(fetch->collections());
59  processCollection();
60  }
61 }
62 
63 void XmlWriteJobPrivate::processCollection()
64 {
65  if (!pendingSiblings.isEmpty() && pendingSiblings.top().isEmpty()) {
66  pendingSiblings.pop();
67  if (pendingSiblings.isEmpty()) {
68  q->done();
69  return;
70  }
71  processItems();
72  return;
73  }
74 
75  if (pendingSiblings.isEmpty()) {
76  q->done();
77  return;
78  }
79 
80  const Collection current = pendingSiblings.top().first();
81  qDebug() << "Writing " << current.name() << "into" << elementStack.top().attribute(QStringLiteral("name"));
82  elementStack.push(XmlWriter::writeCollection(current, elementStack.top()));
83  auto subfetch = new CollectionFetchJob(current, CollectionFetchJob::FirstLevel, q);
84  q->connect(subfetch, &CollectionFetchJob::result, q, [this](KJob *job) {
85  collectionFetchResult(job);
86  });
87 }
88 
89 void XmlWriteJobPrivate::processItems()
90 {
91  const Collection collection = pendingSiblings.top().first();
92  auto fetch = new ItemFetchJob(collection, q);
93  fetch->fetchScope().fetchAllAttributes();
94  fetch->fetchScope().fetchFullPayload();
95  q->connect(fetch, &ItemFetchJob::result, q, [this](KJob *job) {
96  itemFetchResult(job);
97  });
98 }
99 
100 void XmlWriteJobPrivate::itemFetchResult(KJob *job)
101 {
102  if (job->error()) {
103  return;
104  }
105  auto fetch = qobject_cast<ItemFetchJob *>(job);
106  Q_ASSERT(fetch);
107  const Akonadi::Item::List lstItems = fetch->items();
108  for (const Item &item : lstItems) {
109  XmlWriter::writeItem(item, elementStack.top());
110  }
111  pendingSiblings.top().removeFirst();
112  elementStack.pop();
113  processCollection();
114 }
115 
116 XmlWriteJob::XmlWriteJob(const Collection &root, const QString &fileName, QObject *parent)
117  : Job(parent)
118  , d(new XmlWriteJobPrivate(this))
119 {
120  d->roots.append(root);
121  d->fileName = fileName;
122 }
123 
124 XmlWriteJob::XmlWriteJob(const Collection::List &roots, const QString &fileName, QObject *parent)
125  : Job(parent)
126  , d(new XmlWriteJobPrivate(this))
127 {
128  d->roots = roots;
129  d->fileName = fileName;
130 }
131 
132 XmlWriteJob::~XmlWriteJob() = default;
133 
135 {
136  d->elementStack.push(d->document.document().documentElement());
137  auto job = new CollectionFetchJob(d->roots, this);
138  connect(job, &CollectionFetchJob::result, this, [this](KJob *job) {
139  d->collectionFetchResult(job);
140  });
141 }
142 
143 void XmlWriteJob::done() // cannot be in the private class due to emitResult()
144 {
145  if (!d->document.writeToFile(d->fileName)) {
146  setError(Unknown);
147  setErrorText(d->document.lastError());
148  }
149  emitResult();
150 }
151 
152 #include "moc_xmlwritejob.cpp"
QString name() const
Returns the i18n&#39;ed name of the collection.
Definition: collection.cpp:209
Serializes a given Akonadi collection into a XML file.
Definition: xmlwritejob.h:24
Only list direct sub-collections of the base collection.
Represents a document of the KNUT XML serialization format for Akonadi objects.
Definition: xmldocument.h:26
Represents a collection of PIM items.
Definition: collection.h:61
Job that fetches collections from the Akonadi storage.
Base class for all actions in the Akonadi storage.
Definition: job.h:80
AKONADI_XML_EXPORT QDomElement writeCollection(const Collection &collection, QDomElement &parentElem)
Serializes the given collection into a DOM element with the given parent.
Definition: xmlwriter.cpp:69
void doStart() override
This method must be reimplemented in the concrete jobs.
AKONADI_XML_EXPORT QDomElement writeItem(const Item &item, QDomElement &parentElem)
Serializes the given item into a DOM element and attaches it to the given item.
Definition: xmlwriter.cpp:111
Helper integration between Akonadi and Qt.
Job that fetches items from the Akonadi storage.
Definition: itemfetchjob.h:69
void result(KJob *job)
Represents a PIM item stored in Akonadi storage.
Definition: item.h:104
int error() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Sat Jan 22 2022 23:08:46 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.