Akonadi

collectionpathresolver.cpp
1 /*
2  SPDX-FileCopyrightText: 2007 Volker Krause <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "collectionpathresolver.h"
8 
9 #include "collectionfetchjob.h"
10 #include "job_p.h"
11 
12 #include "akonadicore_debug.h"
13 
14 #include <KLocalizedString>
15 
16 #include <QStringList>
17 
18 using namespace Akonadi;
19 
20 /// @cond PRIVATE
21 
22 class Akonadi::CollectionPathResolverPrivate : public JobPrivate
23 {
24 public:
25  explicit CollectionPathResolverPrivate(CollectionPathResolver *parent)
26  : JobPrivate(parent)
27  {
28  }
29 
30  void init(const QString &path, const Collection &rootCollection)
31  {
33 
34  mPathToId = true;
35  mPath = path;
36  if (mPath.startsWith(q->pathDelimiter())) {
37  mPath = mPath.right(mPath.length() - q->pathDelimiter().length());
38  }
39  if (mPath.endsWith(q->pathDelimiter())) {
40  mPath = mPath.left(mPath.length() - q->pathDelimiter().length());
41  }
42 
43  mPathParts = splitPath(mPath);
44  mCurrentNode = rootCollection;
45  }
46 
47  void jobResult(KJob *job);
48 
49  QStringList splitPath(const QString &path)
50  {
51  if (path.isEmpty()) { // path is normalized, so non-empty means at least one hit
52  return QStringList();
53  }
54 
55  QStringList rv;
56  int begin = 0;
57  const int pathSize(path.size());
58  for (int i = 0; i < pathSize; ++i) {
59  if (path[i] == QLatin1Char('/')) {
60  QString pathElement = path.mid(begin, i - begin);
61  pathElement.replace(QLatin1String("\\/"), QLatin1String("/"));
62  rv.append(pathElement);
63  begin = i + 1;
64  }
65  if (i < path.size() - 2 && path[i] == QLatin1Char('\\') && path[i + 1] == QLatin1Char('/')) {
66  ++i;
67  }
68  }
69  QString pathElement = path.mid(begin);
70  pathElement.replace(QLatin1String("\\/"), QLatin1String("/"));
71  rv.append(pathElement);
72  return rv;
73  }
74 
75  Q_DECLARE_PUBLIC(CollectionPathResolver)
76 
77  Collection mCurrentNode;
78  QStringList mPathParts;
79  QString mPath;
80  Collection::Id mColId = -1;
81  bool mPathToId = false;
82 };
83 
84 void CollectionPathResolverPrivate::jobResult(KJob *job)
85 {
86  if (job->error()) {
87  return;
88  }
89 
91 
92  auto list = static_cast<CollectionFetchJob *>(job);
93  CollectionFetchJob *nextJob = nullptr;
94  const Collection::List cols = list->collections();
95  if (cols.isEmpty()) {
96  mColId = -1;
98  q->setErrorText(i18n("No such collection."));
99  q->emitResult();
100  return;
101  }
102 
103  if (mPathToId) {
104  const QString currentPart = mPathParts.takeFirst();
105  bool found = false;
106  for (const Collection &c : cols) {
107  if (c.name() == currentPart) {
108  mCurrentNode = c;
109  found = true;
110  break;
111  }
112  }
113  if (!found) {
114  qCWarning(AKONADICORE_LOG) << "No such collection" << currentPart << "with parent" << mCurrentNode.id();
115  mColId = -1;
116  q->setError(CollectionPathResolver::Unknown);
117  q->setErrorText(i18n("No such collection."));
118  q->emitResult();
119  return;
120  }
121  if (mPathParts.isEmpty()) {
122  mColId = mCurrentNode.id();
123  q->emitResult();
124  return;
125  }
126  nextJob = new CollectionFetchJob(mCurrentNode, CollectionFetchJob::FirstLevel, q);
127  } else {
128  Collection col = list->collections().at(0);
129  mCurrentNode = col.parentCollection();
130  mPathParts.prepend(col.name());
131  if (mCurrentNode == Collection::root()) {
132  q->emitResult();
133  return;
134  }
135  nextJob = new CollectionFetchJob(mCurrentNode, CollectionFetchJob::Base, q);
136  }
137  q->connect(nextJob, &CollectionFetchJob::result, q, [this](KJob *job) {
138  jobResult(job);
139  });
140 }
141 
143  : Job(new CollectionPathResolverPrivate(this), parent)
144 {
146  d->init(path, Collection::root());
147 }
148 
149 CollectionPathResolver::CollectionPathResolver(const QString &path, const Collection &parentCollection, QObject *parent)
150  : Job(new CollectionPathResolverPrivate(this), parent)
151 {
153  d->init(path, parentCollection);
154 }
155 
157  : Job(new CollectionPathResolverPrivate(this), parent)
158 {
160 
161  d->mPathToId = false;
162  d->mColId = collection.id();
163  d->mCurrentNode = collection;
164 }
165 
167 {
168 }
169 
171 {
173 
174  return d->mColId;
175 }
176 
178 {
180 
181  if (d->mPathToId) {
182  return d->mPath;
183  }
184  return d->mPathParts.join(pathDelimiter());
185 }
186 
188 {
189  return QStringLiteral("/");
190 }
191 
193 {
195 
196  CollectionFetchJob *job = nullptr;
197  if (d->mPathToId) {
198  if (d->mPath.isEmpty()) {
199  d->mColId = Collection::root().id();
200  emitResult();
201  return;
202  }
203  job = new CollectionFetchJob(d->mCurrentNode, CollectionFetchJob::FirstLevel, this);
204  } else {
205  if (d->mColId == 0) {
206  d->mColId = Collection::root().id();
207  emitResult();
208  return;
209  }
210  job = new CollectionFetchJob(d->mCurrentNode, CollectionFetchJob::Base, this);
211  }
212  connect(job, &CollectionFetchJob::result, this, [d](KJob *job) {
213  d->jobResult(job);
214  });
215 }
216 
217 /// @endcond
218 
219 #include "moc_collectionpathresolver.cpp"
void append(const T &value)
Collection::Id collection() const
Returns the collection id.
bool isEmpty() const const
void doStart() override
This method must be reimplemented in the concrete jobs.
@ Unknown
Unknown error.
Definition: job.h:102
int size() const const
void result(KJob *job)
QCA_EXPORT void init()
Represents a collection of PIM items.
Definition: collection.h:61
~CollectionPathResolver() override
Destroys the collection path resolver.
KIOFILEWIDGETS_EXPORT QStringList list(const QString &fileClass)
const QList< QKeySequence > & begin()
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Job that fetches collections from the Akonadi storage.
QString i18n(const char *text, const TYPE &arg...)
CollectionPathResolver(const QString &path, QObject *parent=nullptr)
Creates a new collection path resolver to convert a path into a id.
bool isEmpty() const const
static QString pathDelimiter()
Returns the path delimiter for collections.
const T & at(int i) const const
@ FirstLevel
Only list direct sub-collections of the base collection.
@ Base
Only fetch the base collection.
Base class for all actions in the Akonadi storage.
Definition: job.h:80
static Collection root()
Returns the root collection.
Definition: collection.cpp:287
QString & replace(int position, int n, QChar after)
Collection parentCollection() const
Returns the parent collection of this object.
Definition: collection.cpp:187
QString left(int n) const const
QString right(int n) const const
void emitResult()
int error() const
QString mid(int position, int n) const const
qint64 Id
Describes the unique id type.
Definition: collection.h:79
Q_D(Todo)
Helper integration between Akonadi and Qt.
QString path() const
Returns the collection path.
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Sat Jun 25 2022 06:00:31 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.