Akonadi

scope.cpp
1 /*
2  * SPDX-FileCopyrightText: 2009 Volker Krause <[email protected]>
3  * SPDX-FileCopyrightText: 2015 Daniel Vrátil <[email protected]>
4  *
5  * SPDX-License-Identifier: LGPL-2.0-or-later
6  */
7 
8 #include "datastream_p_p.h"
9 #include "scope_p.h"
10 
11 #include <QJsonArray>
12 #include <QJsonObject>
13 #include <QStringList>
14 
15 #include "imapset_p.h"
16 
17 namespace Akonadi
18 {
19 class ScopePrivate : public QSharedData
20 {
21 public:
22  ImapSet uidSet;
23  QStringList ridSet;
24  QVector<Scope::HRID> hridChain;
25  QStringList gidSet;
26  Scope::SelectionScope scope = Scope::Invalid;
27 };
28 
29 Scope::HRID::HRID()
30  : id(-1)
31 {
32 }
33 
34 Scope::HRID::HRID(qint64 id, const QString &remoteId)
35  : id(id)
36  , remoteId(remoteId)
37 {
38 }
39 
40 Scope::HRID::HRID(const HRID &other)
41  : id(other.id)
42  , remoteId(other.remoteId)
43 {
44 }
45 
46 Scope::HRID::HRID(HRID &&other) noexcept
47  : id(other.id)
48 {
49  remoteId.swap(other.remoteId);
50 }
51 
52 Scope::HRID &Scope::HRID::operator=(const HRID &other)
53 {
54  if (*this == other) {
55  return *this;
56  }
57 
58  id = other.id;
59  remoteId = other.remoteId;
60  return *this;
61 }
62 
63 Scope::HRID &Scope::HRID::operator=(HRID &&other) noexcept
64 {
65  if (*this == other) {
66  return *this;
67  }
68 
69  id = other.id;
70  remoteId.swap(other.remoteId);
71  return *this;
72 }
73 
74 bool Scope::HRID::isEmpty() const
75 {
76  return id <= 0 && remoteId.isEmpty();
77 }
78 
79 bool Scope::HRID::operator==(const HRID &other) const
80 {
81  return id == other.id && remoteId == other.remoteId;
82 }
83 
84 void Scope::HRID::toJson(QJsonObject &json) const
85 {
86  json[QStringLiteral("ID")] = id;
87  json[QStringLiteral("RemoteID")] = remoteId;
88 }
89 
90 Scope::Scope()
91  : d(new ScopePrivate)
92 {
93 }
94 
95 Scope::Scope(qint64 id)
96  : d(new ScopePrivate)
97 {
98  setUidSet(id);
99 }
100 
101 Scope::Scope(const ImapSet &set)
102  : d(new ScopePrivate)
103 {
104  setUidSet(set);
105 }
106 
107 Scope::Scope(const ImapInterval &interval)
108  : d(new ScopePrivate)
109 {
110  setUidSet(interval);
111 }
112 
113 Scope::Scope(const QVector<qint64> &interval)
114  : d(new ScopePrivate)
115 {
116  setUidSet(interval);
117 }
118 
119 Scope::Scope(SelectionScope scope, const QStringList &ids)
120  : d(new ScopePrivate)
121 {
122  Q_ASSERT(scope == Rid || scope == Gid);
123  if (scope == Rid) {
124  d->scope = scope;
125  d->ridSet = ids;
126  } else if (scope == Gid) {
127  d->scope = scope;
128  d->gidSet = ids;
129  }
130 }
131 
132 Scope::Scope(const QVector<HRID> &hrid)
133  : d(new ScopePrivate)
134 {
135  d->scope = HierarchicalRid;
136  d->hridChain = hrid;
137 }
138 
139 Scope::Scope(const Scope &other)
140  : d(other.d)
141 {
142 }
143 
144 Scope::Scope(Scope &&other) noexcept
145 {
146  d.swap(other.d);
147 }
148 
149 Scope::~Scope()
150 {
151 }
152 
153 Scope &Scope::operator=(const Scope &other)
154 {
155  d = other.d;
156  return *this;
157 }
158 
159 Scope &Scope::operator=(Scope &&other) noexcept
160 {
161  d.swap(other.d);
162  return *this;
163 }
164 
165 bool Scope::operator==(const Scope &other) const
166 {
167  if (d->scope != other.d->scope) {
168  return false;
169  }
170 
171  switch (d->scope) {
172  case Uid:
173  return d->uidSet == other.d->uidSet;
174  case Gid:
175  return d->gidSet == other.d->gidSet;
176  case Rid:
177  return d->ridSet == other.d->ridSet;
178  case HierarchicalRid:
179  return d->hridChain == other.d->hridChain;
180  case Invalid:
181  return true;
182  }
183 
184  Q_ASSERT(false);
185  return false;
186 }
187 
188 bool Scope::operator!=(const Scope &other) const
189 {
190  return !(*this == other);
191 }
192 
193 Scope::SelectionScope Scope::scope() const
194 {
195  return d->scope;
196 }
197 
198 bool Scope::isEmpty() const
199 {
200  switch (d->scope) {
201  case Invalid:
202  return true;
203  case Uid:
204  return d->uidSet.isEmpty();
205  case Rid:
206  return d->ridSet.isEmpty();
207  case HierarchicalRid:
208  return d->hridChain.isEmpty();
209  case Gid:
210  return d->gidSet.isEmpty();
211  }
212 
213  Q_ASSERT(false);
214  return true;
215 }
216 
217 void Scope::setUidSet(const ImapSet &uidSet)
218 {
219  d->scope = Uid;
220  d->uidSet = uidSet;
221 }
222 
223 ImapSet Scope::uidSet() const
224 {
225  return d->uidSet;
226 }
227 
228 void Scope::setRidSet(const QStringList &ridSet)
229 {
230  d->scope = Rid;
231  d->ridSet = ridSet;
232 }
233 
234 QStringList Scope::ridSet() const
235 {
236  return d->ridSet;
237 }
238 
239 void Scope::setHRidChain(const QVector<HRID> &hridChain)
240 {
241  d->scope = HierarchicalRid;
242  d->hridChain = hridChain;
243 }
244 
245 QVector<Scope::HRID> Scope::hridChain() const
246 {
247  return d->hridChain;
248 }
249 
250 void Scope::setGidSet(const QStringList &gidSet)
251 {
252  d->scope = Gid;
253  d->gidSet = gidSet;
254 }
255 
256 QStringList Scope::gidSet() const
257 {
258  return d->gidSet;
259 }
260 
261 qint64 Scope::uid() const
262 {
263  if (d->uidSet.intervals().size() == 1 && d->uidSet.intervals().at(0).size() == 1) {
264  return d->uidSet.intervals().at(0).begin();
265  }
266 
267  // TODO: Error handling!
268  return -1;
269 }
270 
271 QString Scope::rid() const
272 {
273  if (d->ridSet.size() != 1) {
274  // TODO: Error handling!
275  Q_ASSERT(d->ridSet.size() == 1);
276  return QString();
277  }
278  return d->ridSet.at(0);
279 }
280 
281 QString Scope::gid() const
282 {
283  if (d->gidSet.size() != 1) {
284  // TODO: Error handling!
285  Q_ASSERT(d->gidSet.size() == 1);
286  return QString();
287  }
288  return d->gidSet.at(0);
289 }
290 
291 void Scope::toJson(QJsonObject &json) const
292 {
293  switch (scope()) {
294  case Scope::Uid:
295  json[QStringLiteral("type")] = QStringLiteral("UID");
296  json[QStringLiteral("value")] = QString::fromUtf8(uidSet().toImapSequenceSet());
297  break;
298  case Scope::Rid:
299  json[QStringLiteral("type")] = QStringLiteral("RID");
300  json[QStringLiteral("value")] = QJsonArray::fromStringList(ridSet());
301  break;
302  case Scope::Gid:
303  json[QStringLiteral("type")] = QStringLiteral("GID");
304  json[QStringLiteral("value")] = QJsonArray::fromStringList(gidSet());
305  break;
306  case Scope::HierarchicalRid: {
307  const auto &chain = hridChain();
308  QJsonArray hridArray;
309  for (const auto &hrid : chain) {
310  QJsonObject obj;
311  hrid.toJson(obj);
312  hridArray.append(obj);
313  }
314  json[QStringLiteral("type")] = QStringLiteral("HRID");
315  json[QStringLiteral("value")] = hridArray;
316  } break;
317  default:
318  json[QStringLiteral("type")] = QStringLiteral("invalid");
319  json[QStringLiteral("value")] = QJsonValue(static_cast<int>(scope()));
320  }
321 }
322 
323 Protocol::DataStream &operator<<(Protocol::DataStream &stream, const Akonadi::Scope &scope)
324 {
325  stream << static_cast<quint8>(scope.d->scope);
326  switch (scope.d->scope) {
327  case Scope::Invalid:
328  return stream;
329  case Scope::Uid:
330  stream << scope.d->uidSet;
331  return stream;
332  case Scope::Rid:
333  stream << scope.d->ridSet;
334  return stream;
335  case Scope::HierarchicalRid:
336  stream << scope.d->hridChain;
337  return stream;
338  case Scope::Gid:
339  stream << scope.d->gidSet;
340  return stream;
341  }
342 
343  return stream;
344 }
345 
346 Protocol::DataStream &operator<<(Protocol::DataStream &stream, const Akonadi::Scope::HRID &hrid)
347 {
348  return stream << hrid.id << hrid.remoteId;
349 }
350 
351 Protocol::DataStream &operator>>(Protocol::DataStream &stream, Akonadi::Scope::HRID &hrid)
352 {
353  return stream >> hrid.id >> hrid.remoteId;
354 }
355 
356 Protocol::DataStream &operator>>(Protocol::DataStream &stream, Akonadi::Scope &scope)
357 {
358  scope.d->uidSet = ImapSet();
359  scope.d->ridSet.clear();
360  scope.d->hridChain.clear();
361  scope.d->gidSet.clear();
362 
363  stream >> reinterpret_cast<quint8 &>(scope.d->scope);
364  switch (scope.d->scope) {
365  case Scope::Invalid:
366  return stream;
367  case Scope::Uid:
368  stream >> scope.d->uidSet;
369  return stream;
370  case Scope::Rid:
371  stream >> scope.d->ridSet;
372  return stream;
373  case Scope::HierarchicalRid:
374  stream >> scope.d->hridChain;
375  return stream;
376  case Scope::Gid:
377  stream >> scope.d->gidSet;
378  return stream;
379  }
380 
381  return stream;
382 }
383 
384 } // namespace Akonadi
385 
386 using namespace Akonadi;
387 
388 QDebug operator<<(QDebug dbg, const Akonadi::Scope::HRID &hrid)
389 {
390  return dbg.nospace() << "(ID: " << hrid.id << ", RemoteID: " << hrid.remoteId << ")";
391 }
392 
393 QDebug operator<<(QDebug dbg, const Akonadi::Scope &scope)
394 {
395  switch (scope.scope()) {
396  case Scope::Uid:
397  return dbg.nospace() << "UID " << scope.uidSet();
398  case Scope::Rid:
399  return dbg.nospace() << "RID " << scope.ridSet();
400  case Scope::Gid:
401  return dbg.nospace() << "GID " << scope.gidSet();
402  case Scope::HierarchicalRid:
403  return dbg.nospace() << "HRID " << scope.hridChain();
404  default:
405  return dbg.nospace() << "Invalid scope";
406  }
407 }
QString fromUtf8(const char *str, int size)
QDebug & nospace()
QDataStream & operator<<(QDataStream &out, const KDateTime &dateTime)
const T & at(int i) const const
QJsonArray fromStringList(const QStringList &list)
void append(const QJsonValue &value)
QDataStream & operator>>(QDataStream &in, KDateTime &dateTime)
Helper integration between Akonadi and Qt.
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon May 8 2023 03:52:16 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.