File indexing completed on 2024-11-10 04:40:49
0001 /* 0002 * SPDX-FileCopyrightText: 2009 Volker Krause <vkrause@kde.org> 0003 * SPDX-FileCopyrightText: 2015 Daniel Vrátil <dvratil@redhat.com> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "datastream_p_p.h" 0009 #include "scope_p.h" 0010 0011 #include <QJsonArray> 0012 #include <QJsonObject> 0013 #include <QStringList> 0014 0015 #include "imapset_p.h" 0016 0017 namespace Akonadi 0018 { 0019 class ScopePrivate : public QSharedData 0020 { 0021 public: 0022 ImapSet uidSet; 0023 QStringList ridSet; 0024 QList<Scope::HRID> hridChain; 0025 QStringList gidSet; 0026 Scope::SelectionScope scope = Scope::Invalid; 0027 }; 0028 0029 Scope::HRID::HRID() 0030 : id(-1) 0031 { 0032 } 0033 0034 Scope::HRID::HRID(qint64 id, const QString &remoteId) 0035 : id(id) 0036 , remoteId(remoteId) 0037 { 0038 } 0039 0040 Scope::HRID::HRID(const HRID &other) 0041 : id(other.id) 0042 , remoteId(other.remoteId) 0043 { 0044 } 0045 0046 Scope::HRID::HRID(HRID &&other) noexcept 0047 : id(other.id) 0048 { 0049 remoteId.swap(other.remoteId); 0050 } 0051 0052 Scope::HRID &Scope::HRID::operator=(const HRID &other) 0053 { 0054 if (*this == other) { 0055 return *this; 0056 } 0057 0058 id = other.id; 0059 remoteId = other.remoteId; 0060 return *this; 0061 } 0062 0063 Scope::HRID &Scope::HRID::operator=(HRID &&other) noexcept 0064 { 0065 if (*this == other) { 0066 return *this; 0067 } 0068 0069 id = other.id; 0070 remoteId.swap(other.remoteId); 0071 return *this; 0072 } 0073 0074 bool Scope::HRID::isEmpty() const 0075 { 0076 return id <= 0 && remoteId.isEmpty(); 0077 } 0078 0079 bool Scope::HRID::operator==(const HRID &other) const 0080 { 0081 return id == other.id && remoteId == other.remoteId; 0082 } 0083 0084 void Scope::HRID::toJson(QJsonObject &json) const 0085 { 0086 json[QStringLiteral("ID")] = id; 0087 json[QStringLiteral("RemoteID")] = remoteId; 0088 } 0089 0090 Scope::Scope() 0091 : d(new ScopePrivate) 0092 { 0093 } 0094 0095 Scope::Scope(qint64 id) 0096 : d(new ScopePrivate) 0097 { 0098 setUidSet(id); 0099 } 0100 0101 Scope::Scope(const ImapSet &set) 0102 : d(new ScopePrivate) 0103 { 0104 setUidSet(set); 0105 } 0106 0107 Scope::Scope(const ImapInterval &interval) 0108 : d(new ScopePrivate) 0109 { 0110 setUidSet(interval); 0111 } 0112 0113 Scope::Scope(const QList<qint64> &interval) 0114 : d(new ScopePrivate) 0115 { 0116 setUidSet(interval); 0117 } 0118 0119 Scope::Scope(SelectionScope scope, const QStringList &ids) 0120 : d(new ScopePrivate) 0121 { 0122 Q_ASSERT(scope == Rid || scope == Gid); 0123 if (scope == Rid) { 0124 d->scope = scope; 0125 d->ridSet = ids; 0126 } else if (scope == Gid) { 0127 d->scope = scope; 0128 d->gidSet = ids; 0129 } 0130 } 0131 0132 Scope::Scope(const QList<HRID> &hrid) 0133 : d(new ScopePrivate) 0134 { 0135 d->scope = HierarchicalRid; 0136 d->hridChain = hrid; 0137 } 0138 0139 Scope::Scope(const Scope &other) 0140 : d(other.d) 0141 { 0142 } 0143 0144 Scope::Scope(Scope &&other) noexcept 0145 { 0146 d.swap(other.d); 0147 } 0148 0149 Scope::~Scope() 0150 { 0151 } 0152 0153 Scope &Scope::operator=(const Scope &other) 0154 { 0155 d = other.d; 0156 return *this; 0157 } 0158 0159 Scope &Scope::operator=(Scope &&other) noexcept 0160 { 0161 d.swap(other.d); 0162 return *this; 0163 } 0164 0165 bool Scope::operator==(const Scope &other) const 0166 { 0167 if (d->scope != other.d->scope) { 0168 return false; 0169 } 0170 0171 switch (d->scope) { 0172 case Uid: 0173 return d->uidSet == other.d->uidSet; 0174 case Gid: 0175 return d->gidSet == other.d->gidSet; 0176 case Rid: 0177 return d->ridSet == other.d->ridSet; 0178 case HierarchicalRid: 0179 return d->hridChain == other.d->hridChain; 0180 case Invalid: 0181 return true; 0182 } 0183 0184 Q_ASSERT(false); 0185 return false; 0186 } 0187 0188 bool Scope::operator!=(const Scope &other) const 0189 { 0190 return !(*this == other); 0191 } 0192 0193 Scope::SelectionScope Scope::scope() const 0194 { 0195 return d->scope; 0196 } 0197 0198 bool Scope::isEmpty() const 0199 { 0200 switch (d->scope) { 0201 case Invalid: 0202 return true; 0203 case Uid: 0204 return d->uidSet.isEmpty(); 0205 case Rid: 0206 return d->ridSet.isEmpty(); 0207 case HierarchicalRid: 0208 return d->hridChain.isEmpty(); 0209 case Gid: 0210 return d->gidSet.isEmpty(); 0211 } 0212 0213 Q_ASSERT(false); 0214 return true; 0215 } 0216 0217 void Scope::setUidSet(const ImapSet &uidSet) 0218 { 0219 d->scope = Uid; 0220 d->uidSet = uidSet; 0221 } 0222 0223 ImapSet Scope::uidSet() const 0224 { 0225 return d->uidSet; 0226 } 0227 0228 void Scope::setRidSet(const QStringList &ridSet) 0229 { 0230 d->scope = Rid; 0231 d->ridSet = ridSet; 0232 } 0233 0234 QStringList Scope::ridSet() const 0235 { 0236 return d->ridSet; 0237 } 0238 0239 void Scope::setHRidChain(const QList<HRID> &hridChain) 0240 { 0241 d->scope = HierarchicalRid; 0242 d->hridChain = hridChain; 0243 } 0244 0245 QList<Scope::HRID> Scope::hridChain() const 0246 { 0247 return d->hridChain; 0248 } 0249 0250 void Scope::setGidSet(const QStringList &gidSet) 0251 { 0252 d->scope = Gid; 0253 d->gidSet = gidSet; 0254 } 0255 0256 QStringList Scope::gidSet() const 0257 { 0258 return d->gidSet; 0259 } 0260 0261 qint64 Scope::uid() const 0262 { 0263 if (d->uidSet.intervals().size() == 1 && d->uidSet.intervals().at(0).size() == 1) { 0264 return d->uidSet.intervals().at(0).begin(); 0265 } 0266 0267 // TODO: Error handling! 0268 return -1; 0269 } 0270 0271 QString Scope::rid() const 0272 { 0273 if (d->ridSet.size() != 1) { 0274 // TODO: Error handling! 0275 Q_ASSERT(d->ridSet.size() == 1); 0276 return QString(); 0277 } 0278 return d->ridSet.at(0); 0279 } 0280 0281 QString Scope::gid() const 0282 { 0283 if (d->gidSet.size() != 1) { 0284 // TODO: Error handling! 0285 Q_ASSERT(d->gidSet.size() == 1); 0286 return QString(); 0287 } 0288 return d->gidSet.at(0); 0289 } 0290 0291 void Scope::toJson(QJsonObject &json) const 0292 { 0293 switch (scope()) { 0294 case Scope::Uid: 0295 json[QStringLiteral("type")] = QStringLiteral("UID"); 0296 json[QStringLiteral("value")] = QString::fromUtf8(uidSet().toImapSequenceSet()); 0297 break; 0298 case Scope::Rid: 0299 json[QStringLiteral("type")] = QStringLiteral("RID"); 0300 json[QStringLiteral("value")] = QJsonArray::fromStringList(ridSet()); 0301 break; 0302 case Scope::Gid: 0303 json[QStringLiteral("type")] = QStringLiteral("GID"); 0304 json[QStringLiteral("value")] = QJsonArray::fromStringList(gidSet()); 0305 break; 0306 case Scope::HierarchicalRid: { 0307 const auto &chain = hridChain(); 0308 QJsonArray hridArray; 0309 for (const auto &hrid : chain) { 0310 QJsonObject obj; 0311 hrid.toJson(obj); 0312 hridArray.append(obj); 0313 } 0314 json[QStringLiteral("type")] = QStringLiteral("HRID"); 0315 json[QStringLiteral("value")] = hridArray; 0316 } break; 0317 default: 0318 json[QStringLiteral("type")] = QStringLiteral("invalid"); 0319 json[QStringLiteral("value")] = QJsonValue(static_cast<int>(scope())); 0320 } 0321 } 0322 0323 Protocol::DataStream &operator<<(Protocol::DataStream &stream, const Akonadi::Scope &scope) 0324 { 0325 stream << static_cast<quint8>(scope.d->scope); 0326 switch (scope.d->scope) { 0327 case Scope::Invalid: 0328 return stream; 0329 case Scope::Uid: 0330 stream << scope.d->uidSet; 0331 return stream; 0332 case Scope::Rid: 0333 stream << scope.d->ridSet; 0334 return stream; 0335 case Scope::HierarchicalRid: 0336 stream << scope.d->hridChain; 0337 return stream; 0338 case Scope::Gid: 0339 stream << scope.d->gidSet; 0340 return stream; 0341 } 0342 0343 return stream; 0344 } 0345 0346 Protocol::DataStream &operator<<(Protocol::DataStream &stream, const Akonadi::Scope::HRID &hrid) 0347 { 0348 return stream << hrid.id << hrid.remoteId; 0349 } 0350 0351 Protocol::DataStream &operator>>(Protocol::DataStream &stream, Akonadi::Scope::HRID &hrid) 0352 { 0353 return stream >> hrid.id >> hrid.remoteId; 0354 } 0355 0356 Protocol::DataStream &operator>>(Protocol::DataStream &stream, Akonadi::Scope &scope) 0357 { 0358 scope.d->uidSet = ImapSet(); 0359 scope.d->ridSet.clear(); 0360 scope.d->hridChain.clear(); 0361 scope.d->gidSet.clear(); 0362 0363 stream >> reinterpret_cast<quint8 &>(scope.d->scope); 0364 switch (scope.d->scope) { 0365 case Scope::Invalid: 0366 return stream; 0367 case Scope::Uid: 0368 stream >> scope.d->uidSet; 0369 return stream; 0370 case Scope::Rid: 0371 stream >> scope.d->ridSet; 0372 return stream; 0373 case Scope::HierarchicalRid: 0374 stream >> scope.d->hridChain; 0375 return stream; 0376 case Scope::Gid: 0377 stream >> scope.d->gidSet; 0378 return stream; 0379 } 0380 0381 return stream; 0382 } 0383 0384 } // namespace Akonadi 0385 0386 using namespace Akonadi; 0387 0388 QDebug operator<<(QDebug dbg, const Akonadi::Scope::HRID &hrid) 0389 { 0390 return dbg.nospace() << "(ID: " << hrid.id << ", RemoteID: " << hrid.remoteId << ")"; 0391 } 0392 0393 QDebug operator<<(QDebug dbg, const Akonadi::Scope &scope) 0394 { 0395 switch (scope.scope()) { 0396 case Scope::Uid: 0397 return dbg.nospace() << "UID " << scope.uidSet(); 0398 case Scope::Rid: 0399 return dbg.nospace() << "RID " << scope.ridSet(); 0400 case Scope::Gid: 0401 return dbg.nospace() << "GID " << scope.gidSet(); 0402 case Scope::HierarchicalRid: 0403 return dbg.nospace() << "HRID " << scope.hridChain(); 0404 default: 0405 return dbg.nospace() << "Invalid scope"; 0406 } 0407 }