diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt index b37ae43f3..97fc94a37 100644 --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -1,2 +1,2 @@ add_subdirectory(private) -add_subdirectory(server) \ No newline at end of file +add_subdirectory(server) diff --git a/autotests/server/fakeakonadiserver.h b/autotests/server/fakeakonadiserver.h index ccc789aa2..2f4b32ec1 100644 --- a/autotests/server/fakeakonadiserver.h +++ b/autotests/server/fakeakonadiserver.h @@ -1,145 +1,145 @@ /* * Copyright (C) 2014 Daniel Vrátil * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef FAKEAKONADISERVER_H #define FAKEAKONADISERVER_H #include "akonadi.h" #include "exception.h" #include #include #include #include #include #include class QLocalServer; class QEventLoop; namespace Akonadi { namespace Server { class FakeSearchManager; class FakeDataStore; class FakeConnection; class FakeClient; class TestScenario { public: typedef QList List; enum Action { ServerCmd, ClientCmd, Wait, Quit, Ignore }; Action action; QByteArray data; static TestScenario create(qint64 tag, Action action, const Protocol::Command &response); static TestScenario wait(int timeout) { return TestScenario { Wait, QByteArray::number(timeout) }; } static TestScenario quit() { return TestScenario { Quit, QByteArray() }; } static TestScenario ignore(int count) { return TestScenario { Ignore, QByteArray::number(count) }; } }; /** - * A fake server used for testing. Losely based on KIMAP::FakeServer + * A fake server used for testing. Loosely based on KIMAP::FakeServer */ class FakeAkonadiServer : public AkonadiServer { Q_OBJECT public: static FakeAkonadiServer *instance(); ~FakeAkonadiServer(); /* Reimpl */ bool init(); /* Reimpl */ bool quit(); FakeDataStore *dataStore() const; static QString basePath(); static QString socketFile(); static QString instanceName(); static TestScenario::List loginScenario(const QByteArray &sessionId = QByteArray()); static TestScenario::List selectCollectionScenario(const QString &name); static TestScenario::List selectResourceScenario(const QString &name); void setScenarios(const TestScenario::List &scenarios); void runTest(); QSignalSpy *notificationSpy() const; void setPopulateDb(bool populate); protected: /* Reimpl */ void incomingConnection(quintptr socketDescriptor); private: explicit FakeAkonadiServer(); bool deleteDirectory(const QString &path); FakeDataStore *mDataStore; FakeSearchManager *mSearchManager; FakeConnection *mConnection; FakeClient *mClient; QEventLoop *mServerLoop; QSignalSpy *mNotificationSpy; bool mPopulateDb; static FakeAkonadiServer *sInstance; }; AKONADI_EXCEPTION_MAKE_INSTANCE(FakeAkonadiServerException); } } Q_DECLARE_METATYPE(Akonadi::Server::TestScenario) Q_DECLARE_METATYPE(Akonadi::Server::TestScenario::List) #endif // FAKEAKONADISERVER_H diff --git a/src/private/datastream_p.cpp b/src/private/datastream_p.cpp index 55621fabb..6d4c72181 100644 --- a/src/private/datastream_p.cpp +++ b/src/private/datastream_p.cpp @@ -1,92 +1,92 @@ /* * Copyright (C) 2015 Daniel Vrátil * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "datastream_p_p.h" using namespace Akonadi; using namespace Akonadi::Protocol; DataStream::DataStream() : mDev(Q_NULLPTR) , mWaitTimeout(30000) { } DataStream::DataStream(QIODevice *device) : mDev(device) , mWaitTimeout(30000) { } DataStream::~DataStream() { } QIODevice *DataStream::device() const { return mDev; } void DataStream::setDevice(QIODevice *device) { mDev = device; } int DataStream::waitTimeout() const { return mWaitTimeout; } void DataStream::setWaitTimeout(int timeout) { mWaitTimeout = timeout; } void DataStream::waitForData(quint32 size) { while (mDev->bytesAvailable() < size) { if (!mDev->waitForReadyRead(mWaitTimeout)) { throw ProtocolException("Timeout while waiting for data"); } } } void DataStream::writeRawData(const char *data, int len) { Q_ASSERT(mDev); int ret = mDev->write(data, len); if (ret != len) { // TODO: Try to write data again unless ret is -1? throw ProtocolException("Failed to write all data"); } } void DataStream::writeBytes(const char *bytes, int len) { *this << (quint32) len; if (len) { writeRawData(bytes, len); } } int DataStream::readRawData(char *buffer, int len) { Q_ASSERT(mDev); return mDev->read(buffer, len); -} \ No newline at end of file +} diff --git a/src/private/protocol.cpp b/src/private/protocol.cpp index b5272272e..93f36fa90 100644 --- a/src/private/protocol.cpp +++ b/src/private/protocol.cpp @@ -1,8587 +1,8587 @@ /* * Copyright (c) 2015 Daniel Vrátil * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include "protocol_p.h" #include "scope_p.h" #include "imapset_p.h" #include "datastream_p_p.h" #include #include #include #include #include #include #include #include #undef AKONADI_DECLARE_PRIVATE #define AKONADI_DECLARE_PRIVATE(Class) \ inline Class##Private* Class::d_func() {\ return reinterpret_cast(d_ptr.data()); \ } \ inline const Class##Private* Class::d_func() const {\ return reinterpret_cast(d_ptr.constData()); \ } #define COMPARE(prop) \ (prop == ((decltype(this)) other)->prop) namespace Akonadi { namespace Protocol { int version() { return 52; } } } QDebug operator<<(QDebug _dbg, Akonadi::Protocol::Command::Type type) { QDebug dbg(_dbg.noquote()); switch (type) { case Akonadi::Protocol::Command::Invalid: return dbg << "Invalid"; case Akonadi::Protocol::Command::Hello: return dbg << "Hello"; case Akonadi::Protocol::Command::Login: return dbg << "Login"; case Akonadi::Protocol::Command::Logout: return dbg << "Logout"; case Akonadi::Protocol::Command::Transaction: return dbg << "Transaction"; case Akonadi::Protocol::Command::CreateItem: return dbg << "CreateItem"; case Akonadi::Protocol::Command::CopyItems: return dbg << "CopyItems"; case Akonadi::Protocol::Command::DeleteItems: return dbg << "DeleteItems"; case Akonadi::Protocol::Command::FetchItems: return dbg << "FetchItems"; case Akonadi::Protocol::Command::LinkItems: return dbg << "LinkItems"; case Akonadi::Protocol::Command::ModifyItems: return dbg << "ModifyItems"; case Akonadi::Protocol::Command::MoveItems: return dbg << "MoveItems"; case Akonadi::Protocol::Command::CreateCollection: return dbg << "CreateCollection"; case Akonadi::Protocol::Command::CopyCollection: return dbg << "CopyCollection"; case Akonadi::Protocol::Command::DeleteCollection: return dbg << "DeleteCollection"; case Akonadi::Protocol::Command::FetchCollections: return dbg << "FetchCollections"; case Akonadi::Protocol::Command::FetchCollectionStats: return dbg << "FetchCollectionStats"; case Akonadi::Protocol::Command::ModifyCollection: return dbg << "ModifyCollection"; case Akonadi::Protocol::Command::MoveCollection: return dbg << "MoveCollection"; case Akonadi::Protocol::Command::Search: return dbg << "Search"; case Akonadi::Protocol::Command::SearchResult: return dbg << "SearchResult"; case Akonadi::Protocol::Command::StoreSearch: return dbg << "StoreSearch"; case Akonadi::Protocol::Command::CreateTag: return dbg << "CreateTag"; case Akonadi::Protocol::Command::DeleteTag: return dbg << "DeleteTag"; case Akonadi::Protocol::Command::FetchTags: return dbg << "FetchTags"; case Akonadi::Protocol::Command::ModifyTag: return dbg << "ModifyTag"; case Akonadi::Protocol::Command::FetchRelations: return dbg << "FetchRelations"; case Akonadi::Protocol::Command::ModifyRelation: return dbg << "ModifyRelation"; case Akonadi::Protocol::Command::RemoveRelations: return dbg << "RemoveRelations"; case Akonadi::Protocol::Command::SelectResource: return dbg << "SelectResource"; case Akonadi::Protocol::Command::StreamPayload: return dbg << "StreamPayload"; case Akonadi::Protocol::Command::ChangeNotification: return dbg << "ChangeNotification"; case Akonadi::Protocol::Command::_ResponseBit: Q_ASSERT(false); return dbg; } Q_ASSERT(false); return dbg; } namespace Akonadi { namespace Protocol { class DebugBlock { public: DebugBlock(QDebug &dbg) : mIndent(0) , mDbg(dbg) { beginBlock(); } ~DebugBlock() { endBlock(); } void beginBlock(const QByteArray &name = QByteArray()) { mDbg << "\n"; if (!name.isNull()) { mBlocks.push(name.size() + 4); mDbg << QStringLiteral(" ").repeated(mIndent) << name << ": { "; mIndent += mBlocks.top(); } else { mBlocks.push(2); mDbg << QStringLiteral(" ").repeated(mIndent) << "{ "; } mBlockInit.push(false); } void endBlock() { mDbg << " }"; mIndent -= mBlocks.pop(); mBlockInit.pop(); } template void write(const char *name, const T &val) { if (mBlockInit.top()) { mDbg.noquote() << QByteArray("\n"); mDbg << QStringLiteral(" ").repeated(mIndent); } else { mBlockInit.top() = true; } mDbg << name << ": \"" << val << "\""; } private: Q_DISABLE_COPY(DebugBlock) QStack mBlocks; QStack mBlockInit; int mIndent; QDebug &mDbg; }; } } /******************************************************************************/ namespace Akonadi { namespace Protocol { class CommandPrivate : public QSharedData { public: CommandPrivate(quint8 type) : QSharedData() , commandType(type) {} CommandPrivate(const CommandPrivate &other) : QSharedData(other) , commandType(other.commandType) {} virtual ~CommandPrivate() {} virtual bool compare(const CommandPrivate *other) const { return typeid(*this) == typeid(*other) && COMPARE(commandType); } virtual DataStream &serialize(DataStream &stream) const { return stream << commandType; } virtual DataStream &deserialize(DataStream &stream) { return stream >> commandType; } virtual CommandPrivate *clone() const { return new CommandPrivate(*this); } virtual void debugString(DebugBlock &blck) const { blck.write("Command", static_cast(commandType)); } quint8 commandType; }; } } template <> Akonadi::Protocol::CommandPrivate *QSharedDataPointer::clone() { return d->clone(); } namespace Akonadi { namespace Protocol { AKONADI_DECLARE_PRIVATE(Command) Command::Command() : d_ptr(new CommandPrivate(Invalid)) { } Command::Command(CommandPrivate *dd) : d_ptr(dd) { } Command::Command(Command &&other) { d_ptr.swap(other.d_ptr); } Command::Command(const Command &other) : d_ptr(other.d_ptr) { } Command::~Command() { } Command& Command::operator=(Command &&other) { d_ptr.swap(other.d_ptr); return *this; } Command& Command::operator=(const Command &other) { d_ptr = other.d_ptr; return *this; } bool Command::operator==(const Command &other) const { return d_ptr == other.d_ptr || d_ptr->compare(other.d_ptr.constData()); } bool Command::operator!=(const Command &other) const { return d_ptr != other.d_ptr && !d_ptr->compare(other.d_ptr.constData()); } Command::Type Command::type() const { return static_cast(d_func()->commandType & ~_ResponseBit); } bool Command::isValid() const { return type() != Invalid; } bool Command::isResponse() const { return d_func()->commandType & _ResponseBit; } QString Command::debugString() const { QString out; QDebug dbg(&out); DebugBlock blck(dbg.noquote().nospace()); d_func()->debugString(blck); return out; } QString Command::debugString(DebugBlock &blck) const { d_func()->debugString(blck); return QString(); } DataStream &operator<<(DataStream &stream, const Akonadi::Protocol::Command &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, Akonadi::Protocol::Command &command) { return command.d_func()->deserialize(stream); } /******************************************************************************/ class ResponsePrivate : public CommandPrivate { public: ResponsePrivate(Command::Type type) : CommandPrivate(type | Command::_ResponseBit) , errorCode(0) {} ResponsePrivate(const ResponsePrivate &other) : CommandPrivate(other) , errorMsg(other.errorMsg) , errorCode(other.errorCode) {} virtual ~ResponsePrivate() Q_DECL_OVERRIDE {} virtual bool compare(const CommandPrivate *other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(errorMsg) && COMPARE(errorCode); } virtual DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << errorCode << errorMsg; } virtual DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> errorCode >> errorMsg; } virtual CommandPrivate *clone() const Q_DECL_OVERRIDE { return new ResponsePrivate(*this); } virtual void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { blck.write("Response", static_cast(commandType & ~Command::_ResponseBit)); blck.write("Error Code", errorCode); blck.write("Error Msg", errorMsg); } QString errorMsg; int errorCode; }; AKONADI_DECLARE_PRIVATE(Response) Response::Response() : Command(new ResponsePrivate(Protocol::Command::Invalid)) { } Response::Response(ResponsePrivate *dd) : Command(dd) { } Response::Response(const Command &command) : Command(command) { } void Response::setError(int code, const QString &message) { d_func()->errorCode = code; d_func()->errorMsg = message; } bool Response::isError() const { return d_func()->errorCode; } int Response::errorCode() const { return d_func()->errorCode; } QString Response::errorMessage() const { return d_func()->errorMsg; } DataStream &operator<<(DataStream &stream, const Response &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, Response &command) { return command.d_func()->deserialize(stream); } /******************************************************************************/ class FactoryPrivate { public: typedef Command (*CommandFactoryFunc)(); typedef Response (*ResponseFactoryFunc)(); FactoryPrivate() { // Session management registerType(); registerType(); registerType(); // Transactions registerType(); // Items registerType(); registerType(); registerType(); registerType(); registerType(); registerType(); registerType(); // Collections registerType(); registerType(); registerType(); registerType(); registerType(); registerType(); registerType(); // Search registerType(); registerType(); registerType(); // Tag registerType(); registerType(); registerType(); registerType(); // Relation registerType(); registerType(); registerType(); // Resources registerType(); // Other...? registerType(); registerType(); } // clang has problem resolving the right qHash() overload for Command::Type, // so use its underlying integer type instead QHash::type, QPair> registrar; private: template static Command commandFactoryFunc() { return T(); } template static Response responseFactoryFunc() { return T(); } template void registerType() { CommandFactoryFunc cmdFunc = &commandFactoryFunc; ResponseFactoryFunc respFunc = &responseFactoryFunc; registrar.insert(T, qMakePair(cmdFunc, respFunc)); } }; Q_GLOBAL_STATIC(FactoryPrivate, sFactoryPrivate) Command Factory::command(Command::Type type) { auto iter = sFactoryPrivate->registrar.constFind(type); if (iter == sFactoryPrivate->registrar.constEnd()) { return Command(); } return iter.value().first(); } Response Factory::response(Command::Type type) { auto iter = sFactoryPrivate->registrar.constFind(type); if (iter == sFactoryPrivate->registrar.constEnd()) { return Response(); } return iter.value().second(); } /******************************************************************************/ void serialize(QIODevice *device, const Command &command) { DataStream stream(device); stream << command; #if 0 QLocalSocket *socket if ((socket == qobject_cast(device))) { socket->flush(); } #endif } Command deserialize(QIODevice *device) { DataStream stream(device); stream.waitForData(sizeof(Command::Type)); Command::Type cmdType; if (device->peek((char *) &cmdType, sizeof(Command::Type)) != sizeof(Command::Type)) { throw ProtocolException("Failed to peek command type"); } Command cmd; if (cmdType & Command::_ResponseBit) { cmd = Factory::response(Command::Type(cmdType & ~Command::_ResponseBit)); } else { cmd = Factory::command(cmdType); } stream >> cmd; return cmd; } /******************************************************************************/ class FetchScopePrivate : public QSharedData { public: FetchScopePrivate() : fetchFlags(FetchScope::None) , ancestorDepth(Ancestor::NoAncestor) {} FetchScope::FetchFlags fetchFlags; QVector requestedParts; QDateTime changedSince; QSet tagFetchScope; Ancestor::Depth ancestorDepth; }; FetchScope::FetchScope() : d(new FetchScopePrivate) { } FetchScope::FetchScope(FetchScope &&other) { d.swap(other.d); } FetchScope::FetchScope(const FetchScope &other) : d(other.d) { } FetchScope::~FetchScope() { } FetchScope &FetchScope::operator=(FetchScope &&other) { d.swap(other.d); return *this; } FetchScope &FetchScope::operator=(const FetchScope &other) { d = other.d; return *this; } bool FetchScope::operator==(const FetchScope &other) const { return (d == other.d) || (d->requestedParts == other.d->requestedParts && d->changedSince == other.d->changedSince && d->tagFetchScope == other.d->tagFetchScope && d->ancestorDepth == other.d->ancestorDepth && d->fetchFlags == other.d->fetchFlags); } bool FetchScope::operator!=(const FetchScope &other) const { return !(*this == other); } void FetchScope::setRequestedParts(const QVector &requestedParts) { d->requestedParts = requestedParts; } QVector FetchScope::requestedParts() const { return d->requestedParts; } QVector FetchScope::requestedPayloads() const { QVector rv; std::copy_if(d->requestedParts.begin(), d->requestedParts.end(), std::back_inserter(rv), [](const QByteArray &ba) { return ba.startsWith("PLD:"); }); return rv; } void FetchScope::setChangedSince(const QDateTime &changedSince) { d->changedSince = changedSince; } QDateTime FetchScope::changedSince() const { return d->changedSince; } void FetchScope::setTagFetchScope(const QSet &tagFetchScope) { d->tagFetchScope = tagFetchScope; } QSet FetchScope::tagFetchScope() const { return d->tagFetchScope; } void FetchScope::setAncestorDepth(Ancestor::Depth depth) { d->ancestorDepth = depth; } Ancestor::Depth FetchScope::ancestorDepth() const { return d->ancestorDepth; } bool FetchScope::cacheOnly() const { return d->fetchFlags & CacheOnly; } bool FetchScope::checkCachedPayloadPartsOnly() const { return d->fetchFlags & CheckCachedPayloadPartsOnly; } bool FetchScope::fullPayload() const { return d->fetchFlags & FullPayload; } bool FetchScope::allAttributes() const { return d->fetchFlags & AllAttributes; } bool FetchScope::fetchSize() const { return d->fetchFlags & Size; } bool FetchScope::fetchMTime() const { return d->fetchFlags & MTime; } bool FetchScope::fetchRemoteRevision() const { return d->fetchFlags & RemoteRevision; } bool FetchScope::ignoreErrors() const { return d->fetchFlags & IgnoreErrors; } bool FetchScope::fetchFlags() const { return d->fetchFlags & Flags; } bool FetchScope::fetchRemoteId() const { return d->fetchFlags & RemoteID; } bool FetchScope::fetchGID() const { return d->fetchFlags & GID; } bool FetchScope::fetchTags() const { return d->fetchFlags & Tags; } bool FetchScope::fetchRelations() const { return d->fetchFlags & Relations; } bool FetchScope::fetchVirtualReferences() const { return d->fetchFlags & VirtReferences; } void FetchScope::setFetch(FetchFlags attributes, bool fetch) { if (fetch) { d->fetchFlags |= attributes; if (attributes & FullPayload) { if (!d->requestedParts.contains(AKONADI_PARAM_PLD_RFC822)) { d->requestedParts << AKONADI_PARAM_PLD_RFC822; } } } else { d->fetchFlags &= ~attributes; } } bool FetchScope::fetch(FetchFlags flags) const { if (flags == None) { return d->fetchFlags == None; } else { return d->fetchFlags & flags; } } void FetchScope::debugString(DebugBlock &blck) const { blck.write("Fetch Flags", d->fetchFlags); blck.write("Tag Fetch Scope", d->tagFetchScope); blck.write("Changed Since", d->changedSince); blck.write("Ancestor Depth", d->ancestorDepth); blck.write("Requested Parts", d->requestedParts); } DataStream &operator<<(DataStream &stream, const FetchScope &scope) { return stream << scope.d->requestedParts << scope.d->changedSince << scope.d->tagFetchScope << scope.d->ancestorDepth << scope.d->fetchFlags; } DataStream &operator>>(DataStream &stream, FetchScope &scope) { return stream >> scope.d->requestedParts >> scope.d->changedSince >> scope.d->tagFetchScope >> scope.d->ancestorDepth >> scope.d->fetchFlags; } /******************************************************************************/ class ScopeContextPrivate : public QSharedData { public: ScopeContextPrivate(ScopeContext::Type type = ScopeContext::Collection, const QVariant &ctx = QVariant()) { if (type == ScopeContext::Tag) { tagCtx = ctx; } else if (type == ScopeContext::Collection) { collectionCtx = ctx; } } ScopeContextPrivate(const ScopeContextPrivate &other) : QSharedData(other) , collectionCtx(other.collectionCtx) , tagCtx(other.tagCtx) {} QVariant ctx(ScopeContext::Type type) const { switch (type) { case ScopeContext::Collection: return collectionCtx; case ScopeContext::Tag: return tagCtx; case ScopeContext::Any: return QVariant(); } return QVariant(); } void setCtx(ScopeContext::Type type, const QVariant &val) { switch (type) { case ScopeContext::Collection: collectionCtx = val; break; case ScopeContext::Tag: tagCtx = val; break; case ScopeContext::Any: break; } } QVariant collectionCtx; QVariant tagCtx; }; ScopeContext::ScopeContext() : d(new ScopeContextPrivate) { } ScopeContext::ScopeContext(Type type, qint64 id) : d(new ScopeContextPrivate(type, id)) { } ScopeContext::ScopeContext(Type type, const QString &rid) : d(new ScopeContextPrivate(type, rid)) { } ScopeContext::ScopeContext(const ScopeContext &other) : d(other.d) { } ScopeContext::ScopeContext(ScopeContext &&other) { d.swap(other.d); } ScopeContext::~ScopeContext() { } ScopeContext &ScopeContext::operator=(const ScopeContext &other) { d = other.d; return *this; } ScopeContext &ScopeContext::operator=(ScopeContext &&other) { d.swap(other.d); return *this; } bool ScopeContext::operator==(const ScopeContext &other) const { return d == other.d || (d->collectionCtx == other.d->collectionCtx && d->tagCtx == other.d->tagCtx); } bool ScopeContext::operator!=(const ScopeContext &other) const { return !(*this == other); } bool ScopeContext::isEmpty() const { return d->collectionCtx.isNull() && d->tagCtx.isNull(); } void ScopeContext::setContext(Type type, qint64 id) { d->setCtx(type, id); } void ScopeContext::setContext(Type type, const QString &rid) { d->setCtx(type, rid); } void ScopeContext::clearContext(Type type) { d->setCtx(type, QVariant()); } bool ScopeContext::hasContextId(Type type) const { return d->ctx(type).type() == QVariant::LongLong; } qint64 ScopeContext::contextId(Type type) const { return hasContextId(type) ? d->ctx(type).toLongLong() : 0; } bool ScopeContext::hasContextRID(Type type) const { return d->ctx(type).type() == QVariant::String; } QString ScopeContext::contextRID(Type type) const { return hasContextRID(type) ? d->ctx(type).toString() : QString(); } void ScopeContext::debugString(DebugBlock &blck) const { blck.write("Tag", d->tagCtx); blck.write("Collection", d->collectionCtx); } DataStream &operator<<(DataStream &stream, const ScopeContext &context) { // We don't have a custom generic DataStream streaming operator for QVariant // because it's very hard, esp. without access to QVariant private // stuff, so we have have to decompose it manually here. QVariant::Type vType = context.d->collectionCtx.type(); stream << vType; if (vType == QVariant::LongLong) { stream << context.d->collectionCtx.toLongLong(); } else if (vType == QVariant::String) { stream << context.d->collectionCtx.toString(); } vType = context.d->tagCtx.type(); stream << vType; if (vType == QVariant::LongLong) { stream << context.d->tagCtx.toLongLong(); } else if (vType == QVariant::String) { stream << context.d->tagCtx.toString(); } return stream; } DataStream &operator>>(DataStream &stream, ScopeContext &context) { QVariant::Type vType; qint64 id; QString rid; for (ScopeContext::Type type : { ScopeContext::Collection, ScopeContext::Tag }) { stream >> vType; if (vType == QVariant::LongLong) { stream >> id; context.setContext(type, id); } else if (vType == QVariant::String) { stream >> rid; context.setContext(type, rid); } } return stream; } #undef CTX /******************************************************************************/ class PartMetaDataPrivate : public QSharedData { public: PartMetaDataPrivate(const QByteArray &name = QByteArray(), qint64 size = 0, int version = 0, bool external = false) : QSharedData() , name(name) , size(size) , version(version) , external(external) {} PartMetaDataPrivate(const PartMetaDataPrivate &other) : QSharedData(other) , name(other.name) , size(other.size) , version(other.version) , external(other.external) {} QByteArray name; qint64 size; int version; bool external; }; PartMetaData::PartMetaData() : d(new PartMetaDataPrivate) { } PartMetaData::PartMetaData(const QByteArray &name, qint64 size, int version, bool external) : d(new PartMetaDataPrivate(name, size, version, external)) { } PartMetaData::PartMetaData(PartMetaData &&other) { d.swap(other.d); } PartMetaData::PartMetaData(const PartMetaData &other) { d = other.d; } PartMetaData::~PartMetaData() { } PartMetaData &PartMetaData::operator=(PartMetaData &&other) { d.swap(other.d); return *this; } PartMetaData &PartMetaData::operator=(const PartMetaData &other) { d = other.d; return *this; } bool PartMetaData::operator==(const PartMetaData &other) const { return (d == other.d) || (d->name == other.d->name && d->size == other.d->size && d->version == other.d->version && d->external == other.d->external); } bool PartMetaData::operator!=(const PartMetaData &other) const { return !(*this == other); } bool PartMetaData::operator<(const PartMetaData &other) const { return d->name < other.d->name; } void PartMetaData::setName(const QByteArray &name) { d->name = name; } QByteArray PartMetaData::name() const { return d->name; } void PartMetaData::setSize(qint64 size) { d->size = size; } qint64 PartMetaData::size() const { return d->size; } void PartMetaData::setVersion(int version) { d->version = version; } int PartMetaData::version() const { return d->version; } void PartMetaData::setIsExternal(bool external) { d->external = external; } bool PartMetaData::isExternal() const { return d->external; } DataStream &operator<<(DataStream &stream, const PartMetaData &part) { return stream << part.d->name << part.d->size << part.d->version << part.d->external; } DataStream &operator>>(DataStream &stream, PartMetaData &part) { return stream >> part.d->name >> part.d->size >> part.d->version >> part.d->external; } /******************************************************************************/ class CachePolicyPrivate : public QSharedData { public: CachePolicyPrivate() : syncOnDemand(false) , inherit(true) , interval(-1) , cacheTimeout(-1) {} bool syncOnDemand; bool inherit; QStringList localParts; int interval; int cacheTimeout; }; CachePolicy::CachePolicy() : d(new CachePolicyPrivate) { } CachePolicy::CachePolicy(CachePolicy &&other) { d.swap(other.d); } CachePolicy::CachePolicy(const CachePolicy &other) : d(other.d) { } CachePolicy::~CachePolicy() { } CachePolicy &CachePolicy::operator=(CachePolicy &&other) { d.swap(other.d); return *this; } CachePolicy &CachePolicy::operator=(const CachePolicy &other) { d = other.d; return *this; } bool CachePolicy::operator==(const CachePolicy &other) const { return (d == other.d) || (d->localParts == other.d->localParts && d->interval == other.d->interval && d->cacheTimeout == other.d->cacheTimeout && d->syncOnDemand == other.d->syncOnDemand && d->inherit == other.d->inherit); } bool CachePolicy::operator!=(const CachePolicy &other) const { return !(*this == other); } void CachePolicy::setInherit(bool inherit) { d->inherit = inherit; } bool CachePolicy::inherit() const { return d->inherit; } void CachePolicy::setCheckInterval(int interval) { d->interval = interval; } int CachePolicy::checkInterval() const { return d->interval; } void CachePolicy::setCacheTimeout(int timeout) { d->cacheTimeout = timeout; } int CachePolicy::cacheTimeout() const { return d->cacheTimeout; } void CachePolicy::setSyncOnDemand(bool onDemand) { d->syncOnDemand = onDemand; } bool CachePolicy::syncOnDemand() const { return d->syncOnDemand; } void CachePolicy::setLocalParts(const QStringList &localParts) { d->localParts = localParts; } QStringList CachePolicy::localParts() const { return d->localParts; } void CachePolicy::debugString(DebugBlock &blck) const { blck.write("Inherit", d->inherit); blck.write("Interval", d->interval); blck.write("Cache Timeout", d->cacheTimeout); blck.write("Sync on Demand", d->syncOnDemand); blck.write("Local Parts", d->localParts); } DataStream &operator<<(DataStream &stream, const CachePolicy &policy) { return stream << policy.d->inherit << policy.d->interval << policy.d->cacheTimeout << policy.d->syncOnDemand << policy.d->localParts; } DataStream &operator>>(DataStream &stream, CachePolicy &policy) { return stream >> policy.d->inherit >> policy.d->interval >> policy.d->cacheTimeout >> policy.d->syncOnDemand >> policy.d->localParts; } /******************************************************************************/ class AncestorPrivate : public QSharedData { public: AncestorPrivate(qint64 id = -1, const QString &remoteId = QString()) : id(id) , remoteId(remoteId) {} qint64 id; QString remoteId; QString name; Attributes attrs; }; Ancestor::Ancestor() : d(new AncestorPrivate) { } Ancestor::Ancestor(qint64 id) : d(new AncestorPrivate(id)) { } Ancestor::Ancestor(qint64 id, const QString &remoteId) : d(new AncestorPrivate(id, remoteId)) { } Ancestor::Ancestor(Ancestor &&other) { d.swap(other.d); } Ancestor::Ancestor(const Ancestor &other) : d(other.d) { } Ancestor::~Ancestor() { } Ancestor &Ancestor::operator=(Ancestor &&other) { d.swap(other.d); return *this; } Ancestor &Ancestor::operator=(const Ancestor &other) { d = other.d; return *this; } bool Ancestor::operator==(const Ancestor &other) const { return (d == other.d) || (d->id == other.d->id && d->remoteId == other.d->remoteId && d->name == other.d->name && d->attrs == other.d->attrs); } bool Ancestor::operator!=(const Ancestor &other) const { return !(*this == other); } void Ancestor::setId(qint64 id) { d->id = id; } qint64 Ancestor::id() const { return d->id; } void Ancestor::setRemoteId(const QString &remoteId) { d->remoteId = remoteId; } QString Ancestor::remoteId() const { return d->remoteId; } void Ancestor::setName(const QString &name) { d->name = name; } QString Ancestor::name() const { return d->name; } void Ancestor::setAttributes(const Attributes &attributes) { d->attrs = attributes; } Attributes Ancestor::attributes() const { return d->attrs; } void Ancestor::debugString(DebugBlock &blck) const { blck.write("ID", d->id); blck.write("Remote ID", d->remoteId); blck.write("Name", d->name); blck.write("Attributes", d->attrs); } DataStream &operator<<(DataStream &stream, const Ancestor &ancestor) { return stream << ancestor.d->id << ancestor.d->remoteId << ancestor.d->name << ancestor.d->attrs; } DataStream &operator>>(DataStream &stream, Ancestor &ancestor) { return stream >> ancestor.d->id >> ancestor.d->remoteId >> ancestor.d->name >> ancestor.d->attrs; } /******************************************************************************/ class HelloResponsePrivate : public ResponsePrivate { public: HelloResponsePrivate() : ResponsePrivate(Command::Hello) , protocol(0) {} HelloResponsePrivate(const QString &server, const QString &message, int protocol) : ResponsePrivate(Command::Hello) , server(server) , message(message) , protocol(protocol) {} HelloResponsePrivate(const HelloResponsePrivate &other) : ResponsePrivate(other) , server(other.server) , message(other.message) , protocol(other.protocol) {} bool compare(const CommandPrivate *other) const Q_DECL_OVERRIDE { return ResponsePrivate::compare(other) && COMPARE(server) && COMPARE(message) && COMPARE(protocol); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return ResponsePrivate::serialize(stream) << server << message << protocol; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return ResponsePrivate::deserialize(stream) >> server >> message >> protocol; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { ResponsePrivate::debugString(blck); blck.write("Server", server); blck.write("Protocol Version", protocol); blck.write("Message", message); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new HelloResponsePrivate(*this); } QString server; QString message; int protocol; }; #define checkCopyInvariant(_cmdType) \ if (std::is_base_of::type>::value) { \ assert(d_func()->commandType == Command::Invalid || d_func()->commandType == (_cmdType | Command::_ResponseBit)); \ } else { \ assert(d_func()->commandType == Command::Invalid || d_func()->commandType == _cmdType); \ } AKONADI_DECLARE_PRIVATE(HelloResponse) HelloResponse::HelloResponse(const QString &server, const QString &message, int protocol) : Response(new HelloResponsePrivate(server, message, protocol)) { } HelloResponse::HelloResponse() : Response(new HelloResponsePrivate) { } HelloResponse::HelloResponse(const Command &command) : Response(command) { checkCopyInvariant(Command::Hello); } void HelloResponse::setServerName(const QString &server) { d_func()->server = server; } QString HelloResponse::serverName() const { return d_func()->server; } void HelloResponse::setMessage(const QString &message) { d_func()->message = message; } QString HelloResponse::message() const { return d_func()->message; } void HelloResponse::setProtocolVersion(int protocolVersion) { d_func()->protocol = protocolVersion; } int HelloResponse::protocolVersion() const { return d_func()->protocol; } DataStream &operator<<(DataStream &stream, const HelloResponse &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, HelloResponse &command) { return command.d_func()->deserialize(stream); } /******************************************************************************/ class LoginCommandPrivate : public CommandPrivate { public: LoginCommandPrivate(const QByteArray &sessionId = QByteArray(), LoginCommand::SessionMode mode = LoginCommand::CommandMode) : CommandPrivate(Command::Login) , sessionId(sessionId) , sessionMode(mode) {} LoginCommandPrivate(const LoginCommandPrivate &other) : CommandPrivate(other) , sessionId(other.sessionId) , sessionMode(other.sessionMode) {} bool compare(const CommandPrivate *other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(sessionId) && COMPARE(sessionMode); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << sessionId << sessionMode; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> sessionId >> sessionMode; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Session ID", sessionId); blck.write("Session mode", [this]() -> QString { switch (sessionMode) { case LoginCommand::CommandMode: return QStringLiteral("CommandMode"); case LoginCommand::NotificationBus: return QStringLiteral("NotificationBus"); } Q_ASSERT(false); return QString(); }()); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new LoginCommandPrivate(*this); } QByteArray sessionId; LoginCommand::SessionMode sessionMode; }; AKONADI_DECLARE_PRIVATE(LoginCommand) LoginCommand::LoginCommand() : Command(new LoginCommandPrivate) { } LoginCommand::LoginCommand(const QByteArray &sessionId, SessionMode mode) : Command(new LoginCommandPrivate(sessionId, mode)) { } LoginCommand::LoginCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::Login); } void LoginCommand::setSessionId(const QByteArray &sessionId) { d_func()->sessionId = sessionId; } QByteArray LoginCommand::sessionId() const { return d_func()->sessionId; } void LoginCommand::setSessionMode(SessionMode mode) { d_func()->sessionMode = mode; } LoginCommand::SessionMode LoginCommand::sessionMode() const { return d_func()->sessionMode; } DataStream &operator<<(DataStream &stream, const LoginCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, LoginCommand &command) { return command.d_func()->deserialize(stream); } /******************************************************************************/ LoginResponse::LoginResponse() : Response(new ResponsePrivate(Command::Login)) { } LoginResponse::LoginResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::Login); } /******************************************************************************/ LogoutCommand::LogoutCommand() : Command(new CommandPrivate(Command::Logout)) { } LogoutCommand::LogoutCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::Logout); } /******************************************************************************/ LogoutResponse::LogoutResponse() : Response(new ResponsePrivate(Command::Logout)) { } LogoutResponse::LogoutResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::Logout); } /******************************************************************************/ class TransactionCommandPrivate : public CommandPrivate { public: TransactionCommandPrivate(TransactionCommand::Mode mode = TransactionCommand::Invalid) : CommandPrivate(Command::Transaction) , mode(mode) {} TransactionCommandPrivate(const TransactionCommandPrivate &other) : CommandPrivate(other) , mode(other.mode) {} void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Mode", [this]() -> const char* { switch (mode) { case TransactionCommand::Begin: return "Begin"; case TransactionCommand::Commit: return "Commit"; case TransactionCommand::Rollback: return "Rollback"; default: return "Invalid"; } }()); } bool compare(const CommandPrivate *other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(mode); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << mode; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> mode; } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new TransactionCommandPrivate(*this); } TransactionCommand::Mode mode; }; AKONADI_DECLARE_PRIVATE(TransactionCommand) TransactionCommand::TransactionCommand() : Command(new TransactionCommandPrivate) { } TransactionCommand::TransactionCommand(TransactionCommand::Mode mode) : Command(new TransactionCommandPrivate(mode)) { } TransactionCommand::TransactionCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::Transaction); } void TransactionCommand::setMode(Mode mode) { d_func()->mode = mode; } TransactionCommand::Mode TransactionCommand::mode() const { return d_func()->mode; } DataStream &operator<<(DataStream &stream, const TransactionCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, TransactionCommand &command) { return command.d_func()->deserialize(stream); } /******************************************************************************/ TransactionResponse::TransactionResponse() : Response(new ResponsePrivate(Command::Transaction)) { } TransactionResponse::TransactionResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::Transaction); } /******************************************************************************/ class CreateItemCommandPrivate : public CommandPrivate { public: CreateItemCommandPrivate() : CommandPrivate(Command::CreateItem) , mergeMode(CreateItemCommand::None) , itemSize(0) {} CreateItemCommandPrivate(const CreateItemCommandPrivate &other) : CommandPrivate(other) , collection(other.collection) , mimeType(other.mimeType) , gid(other.gid) , remoteId(other.remoteId) , remoteRev(other.remoteRev) , dateTime(other.dateTime) , tags(other.tags) , addedTags(other.addedTags) , removedTags(other.removedTags) , flags(other.flags) , addedFlags(other.addedFlags) , removedFlags(other.removedFlags) , parts(other.parts) , attributes(other.attributes) , mergeMode(other.mergeMode) , itemSize(other.itemSize) {} bool compare(const CommandPrivate *other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(mergeMode) && COMPARE(itemSize) && COMPARE(collection) && COMPARE(mimeType) && COMPARE(gid) && COMPARE(remoteId) && COMPARE(remoteRev) && COMPARE(dateTime) && COMPARE(tags) && COMPARE(addedTags) && COMPARE(removedTags) && COMPARE(flags) && COMPARE(addedFlags) && COMPARE(removedFlags) && COMPARE(attributes) && COMPARE(parts); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << mergeMode << collection << itemSize << mimeType << gid << remoteId << remoteRev << dateTime << flags << addedFlags << removedFlags << tags << addedTags << removedTags << attributes << parts; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> mergeMode >> collection >> itemSize >> mimeType >> gid >> remoteId >> remoteRev >> dateTime >> flags >> addedFlags >> removedFlags >> tags >> addedTags >> removedTags >> attributes >> parts; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Merge mode", [this]() { QStringList mm; if (mergeMode == CreateItemCommand::None) { mm << QStringLiteral("None"); } else { if (mergeMode & CreateItemCommand::GID) { mm << QStringLiteral("GID"); } if (mergeMode & CreateItemCommand::RemoteID) { mm << QStringLiteral("Remote ID"); } if (mergeMode & CreateItemCommand::Silent) { mm << QStringLiteral("Silent"); } } return mm; }()); blck.write("Collection", collection); blck.write("MimeType", mimeType); blck.write("GID", gid); blck.write("Remote ID", remoteId); blck.write("Remote Revision", remoteRev); blck.write("Size", itemSize); blck.write("Time", dateTime); blck.write("Tags", tags); blck.write("Added Tags", addedTags); blck.write("Removed Tags", removedTags); blck.write("Flags", flags); blck.write("Added Flags", addedFlags); blck.write("Removed Flags", removedFlags); blck.beginBlock("Attributes"); for (auto iter = attributes.constBegin(); iter != attributes.constEnd(); ++iter) { blck.write(iter.key().constData(), iter.value()); } blck.endBlock(); blck.write("Parts", parts); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new CreateItemCommandPrivate(*this); } Scope collection; QString mimeType; QString gid; QString remoteId; QString remoteRev; QDateTime dateTime; Scope tags; Scope addedTags; Scope removedTags; QSet flags; QSet addedFlags; QSet removedFlags; QSet parts; Attributes attributes; CreateItemCommand::MergeModes mergeMode; qint64 itemSize; }; AKONADI_DECLARE_PRIVATE(CreateItemCommand) CreateItemCommand::CreateItemCommand() : Command(new CreateItemCommandPrivate) { } CreateItemCommand::CreateItemCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::CreateItem); } void CreateItemCommand::setMergeModes(const MergeModes &mode) { d_func()->mergeMode = mode; } CreateItemCommand::MergeModes CreateItemCommand::mergeModes() const { return d_func()->mergeMode; } void CreateItemCommand::setCollection(const Scope &collection) { d_func()->collection = collection; } Scope CreateItemCommand::collection() const { return d_func()->collection; } void CreateItemCommand::setItemSize(qint64 size) { d_func()->itemSize = size; } qint64 CreateItemCommand::itemSize() const { return d_func()->itemSize; } void CreateItemCommand::setMimeType(const QString &mimeType) { d_func()->mimeType = mimeType; } QString CreateItemCommand::mimeType() const { return d_func()->mimeType; } void CreateItemCommand::setGID(const QString &gid) { d_func()->gid = gid; } QString CreateItemCommand::gid() const { return d_func()->gid; } void CreateItemCommand::setRemoteId(const QString &remoteId) { d_func()->remoteId = remoteId; } QString CreateItemCommand::remoteId() const { return d_func()->remoteId; } void CreateItemCommand::setRemoteRevision(const QString &remoteRevision) { d_func()->remoteRev = remoteRevision; } QString CreateItemCommand::remoteRevision() const { return d_func()->remoteRev; } void CreateItemCommand::setDateTime(const QDateTime &dateTime) { d_func()->dateTime = dateTime; } QDateTime CreateItemCommand::dateTime() const { return d_func()->dateTime; } void CreateItemCommand::setFlags(const QSet &flags) { d_func()->flags = flags; } QSet CreateItemCommand::flags() const { return d_func()->flags; } void CreateItemCommand::setAddedFlags(const QSet &flags) { d_func()->addedFlags = flags; } QSet CreateItemCommand::addedFlags() const { return d_func()->addedFlags; } void CreateItemCommand::setRemovedFlags(const QSet &flags) { d_func()->removedFlags = flags; } QSet CreateItemCommand::removedFlags() const { return d_func()->removedFlags; } void CreateItemCommand::setTags(const Scope &tags) { d_func()->tags = tags; } Scope CreateItemCommand::tags() const { return d_func()->tags; } void CreateItemCommand::setAddedTags(const Scope &tags) { d_func()->addedTags = tags; } Scope CreateItemCommand::addedTags() const { return d_func()->addedTags; } void CreateItemCommand::setRemovedTags(const Scope &tags) { d_func()->removedTags = tags; } Scope CreateItemCommand::removedTags() const { return d_func()->removedTags; } void CreateItemCommand::setAttributes(const Attributes &attrs) { d_func()->attributes = attrs; } Attributes CreateItemCommand::attributes() const { return d_func()->attributes; } void CreateItemCommand::setParts(const QSet &parts) { d_func()->parts = parts; } QSet CreateItemCommand::parts() const { return d_func()->parts; } DataStream &operator<<(DataStream &stream, const CreateItemCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, CreateItemCommand &command) { return command.d_func()->deserialize(stream); } /******************************************************************************/ CreateItemResponse::CreateItemResponse() : Response(new ResponsePrivate(Command::CreateItem)) { } CreateItemResponse::CreateItemResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::CreateItem); } /******************************************************************************/ class CopyItemsCommandPrivate : public CommandPrivate { public: CopyItemsCommandPrivate() : CommandPrivate(Command::CopyItems) {} CopyItemsCommandPrivate(const Scope &items, const Scope &dest) : CommandPrivate(Command::CopyItems) , items(items) , dest(dest) {} CopyItemsCommandPrivate(const CopyItemsCommandPrivate &other) : CommandPrivate(other) , items(other.items) , dest(other.dest) {} bool compare(const CommandPrivate *other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(items) && COMPARE(dest); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << items << dest; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> items >> dest; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Items", items); blck.write("Destination", dest); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new CopyItemsCommandPrivate(*this); } Scope items; Scope dest; }; AKONADI_DECLARE_PRIVATE(CopyItemsCommand) CopyItemsCommand::CopyItemsCommand() : Command(new CopyItemsCommandPrivate) { } CopyItemsCommand::CopyItemsCommand(const Scope &items, const Scope &dest) : Command(new CopyItemsCommandPrivate(items, dest)) { } CopyItemsCommand::CopyItemsCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::CopyItems); } void CopyItemsCommand::setItems(const Scope &items) { d_func()->items = items; } Scope CopyItemsCommand::items() const { return d_func()->items; } void CopyItemsCommand::setDestination(const Scope &dest) { d_func()->dest = dest; } Scope CopyItemsCommand::destination() const { return d_func()->dest; } DataStream &operator<<(DataStream &stream, const CopyItemsCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, CopyItemsCommand &command) { return command.d_func()->deserialize(stream); } /******************************************************************************/ CopyItemsResponse::CopyItemsResponse() : Response(new ResponsePrivate(Command::CopyItems)) { } CopyItemsResponse::CopyItemsResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::CopyItems); } /******************************************************************************/ class DeleteItemsCommandPrivate : public CommandPrivate { public: DeleteItemsCommandPrivate(const Scope &items = Scope(), const ScopeContext &context = ScopeContext()) : CommandPrivate(Command::DeleteItems) , items(items) , context(context) {} bool compare(const CommandPrivate *other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(items) && COMPARE(context); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << items << context; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> items >> context; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Items", items); blck.beginBlock("Context"); context.debugString(blck); blck.endBlock(); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new DeleteItemsCommandPrivate(*this); } Scope items; ScopeContext context; }; AKONADI_DECLARE_PRIVATE(DeleteItemsCommand) DeleteItemsCommand::DeleteItemsCommand() : Command(new DeleteItemsCommandPrivate) { } DeleteItemsCommand::DeleteItemsCommand(const Scope &items, const ScopeContext &context) : Command(new DeleteItemsCommandPrivate(items, context)) { } DeleteItemsCommand::DeleteItemsCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::DeleteItems); } Scope DeleteItemsCommand::items() const { return d_func()->items; } ScopeContext DeleteItemsCommand::scopeContext() const { return d_func()->context; } DataStream &operator<<(DataStream &stream, const DeleteItemsCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, DeleteItemsCommand &command) { return command.d_func()->deserialize(stream); } /******************************************************************************/ DeleteItemsResponse::DeleteItemsResponse() : Response(new ResponsePrivate(Command::DeleteItems)) { } DeleteItemsResponse::DeleteItemsResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::DeleteItems); } /******************************************************************************/ class FetchRelationsCommandPrivate : public CommandPrivate { public: FetchRelationsCommandPrivate(qint64 left = -1, qint64 right = -1, qint64 side = -1, const QVector &types = QVector(), const QString &resource = QString()) : CommandPrivate(Command::FetchRelations) , left(left) , right(right) , side(side) , types(types) , resource(resource) {} FetchRelationsCommandPrivate(const FetchRelationsCommandPrivate &other) : CommandPrivate(other) , left(other.left) , right(other.right) , side(other.side) , types(other.types) , resource(other.resource) {} bool compare(const CommandPrivate *other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(left) && COMPARE(right) && COMPARE(side) && COMPARE(types) && COMPARE(resource); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << left << right << side << types << resource; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> left >> right >> side >> types >> resource; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Left", left); blck.write("Right", right); blck.write("Side", side); blck.write("Types", types); blck.write("Resource", resource); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new FetchRelationsCommandPrivate(*this); } qint64 left; qint64 right; qint64 side; QVector types; QString resource; }; AKONADI_DECLARE_PRIVATE(FetchRelationsCommand) FetchRelationsCommand::FetchRelationsCommand() : Command(new FetchRelationsCommandPrivate) { } FetchRelationsCommand::FetchRelationsCommand(qint64 side, const QVector &types, const QString &resource) : Command(new FetchRelationsCommandPrivate(-1, -1, side, types, resource)) { } FetchRelationsCommand::FetchRelationsCommand(qint64 left, qint64 right, const QVector &types, const QString &resource) : Command(new FetchRelationsCommandPrivate(left, right, -1, types, resource)) { } FetchRelationsCommand::FetchRelationsCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::FetchRelations); } void FetchRelationsCommand::setLeft(qint64 left) { d_func()->left = left; } qint64 FetchRelationsCommand::left() const { return d_func()->left; } void FetchRelationsCommand::setRight(qint64 right) { d_func()->right = right; } qint64 FetchRelationsCommand::right() const { return d_func()->right; } void FetchRelationsCommand::setSide(qint64 side) { d_func()->side = side; } qint64 FetchRelationsCommand::side() const { return d_func()->side; } void FetchRelationsCommand::setTypes(const QVector &types) { d_func()->types = types; } QVector FetchRelationsCommand::types() const { return d_func()->types; } void FetchRelationsCommand::setResource(const QString &resource) { d_func()->resource = resource; } QString FetchRelationsCommand::resource() const { return d_func()->resource; } DataStream &operator<<(DataStream &stream, const FetchRelationsCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, FetchRelationsCommand &command) { return command.d_func()->deserialize(stream); } /*****************************************************************************/ class FetchRelationsResponsePrivate : public ResponsePrivate { public: FetchRelationsResponsePrivate(qint64 left = -1, qint64 right = -1, const QByteArray &type = QByteArray(), const QByteArray &remoteId = QByteArray()) : ResponsePrivate(Command::FetchRelations) , left(left) , right(right) , type(type) , remoteId(remoteId) {} FetchRelationsResponsePrivate(const FetchRelationsResponsePrivate &other) : ResponsePrivate(other) , left(other.left) , right(other.right) , type(other.type) , remoteId(other.remoteId) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return ResponsePrivate::compare(other) && COMPARE(left) && COMPARE(right) && COMPARE(type) && COMPARE(remoteId); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return ResponsePrivate::serialize(stream) << left << right << type << remoteId; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return ResponsePrivate::deserialize(stream) >> left >> right >> type >> remoteId; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { ResponsePrivate::debugString(blck); blck.write("Left", left); blck.write("Right", right); blck.write("Type", type); blck.write("Remote ID", remoteId); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new FetchRelationsResponsePrivate(*this); } qint64 left; qint64 right; QByteArray type; QByteArray remoteId; }; AKONADI_DECLARE_PRIVATE(FetchRelationsResponse) FetchRelationsResponse::FetchRelationsResponse() : Response(new FetchRelationsResponsePrivate) { } FetchRelationsResponse::FetchRelationsResponse(qint64 left, qint64 right, const QByteArray &type, const QByteArray &remoteId) : Response(new FetchRelationsResponsePrivate(left, right, type, remoteId)) { } FetchRelationsResponse::FetchRelationsResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::FetchRelations); } qint64 FetchRelationsResponse::left() const { return d_func()->left; } qint64 FetchRelationsResponse::right() const { return d_func()->right; } QByteArray FetchRelationsResponse::type() const { return d_func()->type; } void FetchRelationsResponse::setRemoteId(const QByteArray &remoteId) { d_func()->remoteId = remoteId; } QByteArray FetchRelationsResponse::remoteId() const { return d_func()->remoteId; } DataStream &operator<<(DataStream &stream, const FetchRelationsResponse &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, FetchRelationsResponse &command) { return command.d_func()->deserialize(stream); } /******************************************************************************/ class FetchTagsCommandPrivate : public CommandPrivate { public: FetchTagsCommandPrivate(const Scope &scope = Scope()) : CommandPrivate(Command::FetchTags) , scope(scope) , idOnly(false) {} FetchTagsCommandPrivate(const FetchTagsCommandPrivate &other) : CommandPrivate(other) , scope(other.scope) , attributes(other.attributes) , idOnly(other.idOnly) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(idOnly) && COMPARE(scope) && COMPARE(attributes); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << scope << attributes << idOnly; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> scope >> attributes >> idOnly; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Tags", scope); blck.write("Attributes", attributes); blck.write("ID only", idOnly); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new FetchTagsCommandPrivate(*this); } Scope scope; QSet attributes; bool idOnly; }; AKONADI_DECLARE_PRIVATE(FetchTagsCommand) FetchTagsCommand::FetchTagsCommand() : Command(new FetchTagsCommandPrivate) { } FetchTagsCommand::FetchTagsCommand(const Scope &scope) : Command(new FetchTagsCommandPrivate(scope)) { } FetchTagsCommand::FetchTagsCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::FetchTags); } Scope FetchTagsCommand::scope() const { return d_func()->scope; } void FetchTagsCommand::setAttributes(const QSet &attributes) { d_func()->attributes = attributes; } QSet FetchTagsCommand::attributes() const { return d_func()->attributes; } void FetchTagsCommand::setIdOnly(bool idOnly) { d_func()->idOnly = idOnly; } bool FetchTagsCommand::idOnly() const { return d_func()->idOnly; } DataStream &operator<<(DataStream &stream, const FetchTagsCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, FetchTagsCommand &command) { return command.d_func()->deserialize(stream); } /*****************************************************************************/ class FetchTagsResponsePrivate : public ResponsePrivate { public: FetchTagsResponsePrivate(qint64 id = -1, const QByteArray &gid = QByteArray(), const QByteArray &type = QByteArray(), const QByteArray &remoteId = QByteArray(), qint64 parentId = -1, const Attributes &attrs = Attributes()) : ResponsePrivate(Command::FetchTags) , id(id) , parentId(parentId) , gid(gid) , type(type) , remoteId(remoteId) , attributes(attrs) {} FetchTagsResponsePrivate(const FetchTagsResponsePrivate &other) : ResponsePrivate(other) , id(other.id) , parentId(other.parentId) , gid(other.gid) , type(other.type) , remoteId(other.remoteId) , attributes(other.attributes) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return ResponsePrivate::compare(other) && COMPARE(id) && COMPARE(parentId) && COMPARE(gid) && COMPARE(type) && COMPARE(remoteId) && COMPARE(attributes); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return ResponsePrivate::serialize(stream) << id << parentId << gid << type << remoteId << attributes; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return ResponsePrivate::deserialize(stream) >> id >> parentId >> gid >> type >> remoteId >> attributes; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { ResponsePrivate::debugString(blck); blck.write("ID", id); blck.write("Parent ID", parentId); blck.write("GID", gid); blck.write("Type", type); blck.write("Remote ID", remoteId); blck.write("Attributes", attributes); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new FetchTagsResponsePrivate(*this); } qint64 id; qint64 parentId; QByteArray gid; QByteArray type; QByteArray remoteId; Attributes attributes; }; AKONADI_DECLARE_PRIVATE(FetchTagsResponse) FetchTagsResponse::FetchTagsResponse() : Response(new FetchTagsResponsePrivate) { } FetchTagsResponse::FetchTagsResponse(qint64 id) : Response(new FetchTagsResponsePrivate(id)) { } FetchTagsResponse::FetchTagsResponse(qint64 id, const QByteArray &gid, const QByteArray &type, const QByteArray &remoteId, qint64 parentId, const Attributes &attrs) : Response(new FetchTagsResponsePrivate(id, gid, type, remoteId, parentId, attrs)) { } FetchTagsResponse::FetchTagsResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::FetchTags); } qint64 FetchTagsResponse::id() const { return d_func()->id; } void FetchTagsResponse::setParentId(qint64 parentId) { d_func()->parentId = parentId; } qint64 FetchTagsResponse::parentId() const { return d_func()->parentId; } void FetchTagsResponse::setGid(const QByteArray &gid) { d_func()->gid = gid; } QByteArray FetchTagsResponse::gid() const { return d_func()->gid; } void FetchTagsResponse::setType(const QByteArray &type) { d_func()->type = type; } QByteArray FetchTagsResponse::type() const { return d_func()->type; } void FetchTagsResponse::setRemoteId(const QByteArray &remoteId) { d_func()->remoteId = remoteId; } QByteArray FetchTagsResponse::remoteId() const { return d_func()->remoteId; } void FetchTagsResponse::setAttributes(const Attributes &attributes) { d_func()->attributes = attributes; } Attributes FetchTagsResponse::attributes() const { return d_func()->attributes; } DataStream &operator<<(DataStream &stream, const FetchTagsResponse &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, FetchTagsResponse &command) { return command.d_func()->deserialize(stream); } /*****************************************************************************/ class FetchItemsCommandPrivate : public CommandPrivate { public: FetchItemsCommandPrivate(const Scope &scope = Scope(), const ScopeContext &context = ScopeContext(), const FetchScope &fetchScope = FetchScope()) : CommandPrivate(Command::FetchItems) , scope(scope) , scopeContext(context) , fetchScope(fetchScope) {} FetchItemsCommandPrivate(const FetchItemsCommandPrivate &other) : CommandPrivate(other) , scope(other.scope) , scopeContext(other.scopeContext) , fetchScope(other.fetchScope) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(scope) && COMPARE(scopeContext) && COMPARE(fetchScope); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << scope << scopeContext << fetchScope; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> scope >> scopeContext >> fetchScope; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Items", scope); blck.beginBlock("Scope Context"); scopeContext.debugString(blck); blck.endBlock(); blck.beginBlock("Fetch Scope"); fetchScope.debugString(blck); blck.endBlock(); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new FetchItemsCommandPrivate(*this); } Scope scope; ScopeContext scopeContext; FetchScope fetchScope; }; AKONADI_DECLARE_PRIVATE(FetchItemsCommand) FetchItemsCommand::FetchItemsCommand() : Command(new FetchItemsCommandPrivate) { } FetchItemsCommand::FetchItemsCommand(const Scope &scope, const FetchScope &fetchScope) : Command(new FetchItemsCommandPrivate(scope, ScopeContext(), fetchScope)) { } FetchItemsCommand::FetchItemsCommand(const Scope &scope, const ScopeContext &context, const FetchScope &fetchScope) : Command(new FetchItemsCommandPrivate(scope, context, fetchScope)) { } FetchItemsCommand::FetchItemsCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::FetchItems); } Scope FetchItemsCommand::scope() const { return d_func()->scope; } ScopeContext FetchItemsCommand::scopeContext() const { return d_func()->scopeContext; } FetchScope FetchItemsCommand::fetchScope() const { return d_func()->fetchScope; } FetchScope &FetchItemsCommand::fetchScope() { return d_func()->fetchScope; } DataStream &operator<<(DataStream &stream, const FetchItemsCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, FetchItemsCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ class FetchItemsResponsePrivate : public ResponsePrivate { public: FetchItemsResponsePrivate(qint64 id = -1) : ResponsePrivate(Command::FetchItems) , id(id) , collectionId(-1) , size(0) , revision(0) {} FetchItemsResponsePrivate(const FetchItemsResponsePrivate &other) : ResponsePrivate(other) , remoteId(other.remoteId) , remoteRev(other.remoteRev) , gid(other.gid) , mimeType(other.mimeType) , time(other.time) , flags(other.flags) , tags(other.tags) , virtRefs(other.virtRefs) , relations(other.relations) , ancestors(other.ancestors) , parts(other.parts) , cachedParts(other.cachedParts) , id(other.id) , collectionId(other.collectionId) , size(other.size) , revision(other.revision) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return ResponsePrivate::compare(other) && COMPARE(id) && COMPARE(collectionId) && COMPARE(size) && COMPARE(revision) && COMPARE(remoteId) && COMPARE(remoteRev) && COMPARE(gid) && COMPARE(mimeType) && COMPARE(time) && COMPARE(flags) && COMPARE(tags) && COMPARE(virtRefs) && COMPARE(relations) && COMPARE(ancestors) && COMPARE(parts) && COMPARE(cachedParts); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return ResponsePrivate::serialize(stream) << id << revision << collectionId << remoteId << remoteRev << gid << size << mimeType << time << flags << tags << virtRefs << relations << ancestors << parts << cachedParts; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return ResponsePrivate::deserialize(stream) >> id >> revision >> collectionId >> remoteId >> remoteRev >> gid >> size >> mimeType >> time >> flags >> tags >> virtRefs >> relations >> ancestors >> parts >> cachedParts; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { ResponsePrivate::debugString(blck); blck.write("ID", id); blck.write("Revision", revision); blck.write("Collection ID", collectionId); blck.write("Remote ID", remoteId); blck.write("Remote Revision", remoteRev); blck.write("GID", gid); blck.write("Size", size); blck.write("Mimetype", mimeType); blck.write("Time", time); blck.write("Flags", flags); blck.beginBlock("Tags"); Q_FOREACH (const FetchTagsResponse &tag, tags) { blck.beginBlock(); tag.debugString(blck); blck.endBlock(); } blck.endBlock(); blck.beginBlock("Relations"); Q_FOREACH (const FetchRelationsResponse &rel, relations) { blck.beginBlock(); rel.debugString(blck); blck.endBlock(); } blck.endBlock(); blck.write("Virtual References", virtRefs); blck.beginBlock("Ancestors"); Q_FOREACH (const Ancestor &anc, ancestors) { blck.beginBlock(); anc.debugString(blck); blck.endBlock(); } blck.endBlock(); blck.write("Cached Parts", cachedParts); blck.beginBlock("Parts"); Q_FOREACH (const StreamPayloadResponse &part, parts) { blck.beginBlock(part.payloadName()); blck.write("Size", part.metaData().size()); blck.write("External", part.metaData().isExternal()); blck.write("Version", part.metaData().version()); blck.write("Data", part.data()); blck.endBlock(); } blck.endBlock(); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new FetchItemsResponsePrivate(*this); } QString remoteId; QString remoteRev; QString gid; QString mimeType; QDateTime time; QVector flags; QVector tags; QVector virtRefs; QVector relations; QVector ancestors; QVector parts; QVector cachedParts; qint64 id; qint64 collectionId; qint64 size; int revision; }; AKONADI_DECLARE_PRIVATE(FetchItemsResponse) FetchItemsResponse::FetchItemsResponse() : Response(new FetchItemsResponsePrivate) { } FetchItemsResponse::FetchItemsResponse(qint64 id) : Response(new FetchItemsResponsePrivate(id)) { } FetchItemsResponse::FetchItemsResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::FetchItems); } qint64 FetchItemsResponse::id() const { return d_func()->id; } void FetchItemsResponse::setRevision(int revision) { d_func()->revision = revision; } int FetchItemsResponse::revision() const { return d_func()->revision; } void FetchItemsResponse::setParentId(qint64 parentId) { d_func()->collectionId = parentId; } qint64 FetchItemsResponse::parentId() const { return d_func()->collectionId; } void FetchItemsResponse::setRemoteId(const QString &remoteId) { d_func()->remoteId = remoteId; } QString FetchItemsResponse::remoteId() const { return d_func()->remoteId; } void FetchItemsResponse::setRemoteRevision(const QString &remoteRevision) { d_func()->remoteRev = remoteRevision; } QString FetchItemsResponse::remoteRevision() const { return d_func()->remoteRev; } void FetchItemsResponse::setGid(const QString &gid) { d_func()->gid = gid; } QString FetchItemsResponse::gid() const { return d_func()->gid; } void FetchItemsResponse::setSize(qint64 size) { d_func()->size = size; } qint64 FetchItemsResponse::size() const { return d_func()->size; } void FetchItemsResponse::setMimeType(const QString &mimeType) { d_func()->mimeType = mimeType; } QString FetchItemsResponse::mimeType() const { return d_func()->mimeType; } void FetchItemsResponse::setMTime(const QDateTime &mtime) { d_func()->time = mtime; } QDateTime FetchItemsResponse::MTime() const { return d_func()->time; } void FetchItemsResponse::setFlags(const QVector &flags) { d_func()->flags = flags; } QVector FetchItemsResponse::flags() const { return d_func()->flags; } void FetchItemsResponse::setTags(const QVector &tags) { d_func()->tags = tags; } QVector FetchItemsResponse::tags() const { return d_func()->tags; } void FetchItemsResponse::setVirtualReferences(const QVector &refs) { d_func()->virtRefs = refs; } QVector FetchItemsResponse::virtualReferences() const { return d_func()->virtRefs; } void FetchItemsResponse::setRelations(const QVector &relations) { d_func()->relations = relations; } QVector FetchItemsResponse::relations() const { return d_func()->relations; } void FetchItemsResponse::setAncestors(const QVector &ancestors) { d_func()->ancestors = ancestors; } QVector FetchItemsResponse::ancestors() const { return d_func()->ancestors; } void FetchItemsResponse::setParts(const QVector &parts) { d_func()->parts = parts; } QVector FetchItemsResponse::parts() const { return d_func()->parts; } void FetchItemsResponse::setCachedParts(const QVector &cachedParts) { d_func()->cachedParts = cachedParts; } QVector FetchItemsResponse::cachedParts() const { return d_func()->cachedParts; } DataStream &operator<<(DataStream &stream, const FetchItemsResponse &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, FetchItemsResponse &command) { return command.d_func()->deserialize(stream); } /*****************************************************************************/ class LinkItemsCommandPrivate : public CommandPrivate { public: LinkItemsCommandPrivate(LinkItemsCommand::Action action = LinkItemsCommand::Link, const Scope &items = Scope(), const Scope &dest = Scope()) : CommandPrivate(Command::LinkItems) , items(items) , dest(dest) , action(action) {} LinkItemsCommandPrivate(const LinkItemsCommandPrivate &other) : CommandPrivate(other) , items(other.items) , dest(other.dest) , action(other.action) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(action) && COMPARE(items) && COMPARE(dest); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << action << items << dest; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> action >> items >> dest; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Action", (action == LinkItemsCommand::Link ? "Link" : "Unlink")); blck.write("Items", items); blck.write("Destination", dest); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new LinkItemsCommandPrivate(*this); } Scope items; Scope dest; LinkItemsCommand::Action action; }; AKONADI_DECLARE_PRIVATE(LinkItemsCommand) LinkItemsCommand::LinkItemsCommand() : Command(new LinkItemsCommandPrivate) { } LinkItemsCommand::LinkItemsCommand(Action action, const Scope &items, const Scope &dest) : Command(new LinkItemsCommandPrivate(action, items, dest)) { } LinkItemsCommand::LinkItemsCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::LinkItems); } LinkItemsCommand::Action LinkItemsCommand::action() const { return d_func()->action; } Scope LinkItemsCommand::items() const { return d_func()->items; } Scope LinkItemsCommand::destination() const { return d_func()->dest; } DataStream &operator<<(DataStream &stream, const LinkItemsCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, LinkItemsCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ LinkItemsResponse::LinkItemsResponse() : Response(new ResponsePrivate(Command::LinkItems)) { } LinkItemsResponse::LinkItemsResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::LinkItems); } /****************************************************************************/ class ModifyItemsCommandPrivate : public CommandPrivate { public: ModifyItemsCommandPrivate(const Scope &items = Scope()) : CommandPrivate(Command::ModifyItems) , items(items) , size(0) , oldRevision(-1) , dirty(true) , invalidate(false) , noResponse(false) , notify(true) , modifiedParts(ModifyItemsCommand::None) {} ModifyItemsCommandPrivate(const ModifyItemsCommandPrivate &other) : CommandPrivate(other) , items(other.items) , flags(other.flags) , addedFlags(other.addedFlags) , removedFlags(other.removedFlags) , tags(other.tags) , addedTags(other.addedTags) , removedTags(other.removedTags) , remoteId(other.remoteId) , remoteRev(other.remoteRev) , gid(other.gid) , removedParts(other.removedParts) , parts(other.parts) , attributes(other.attributes) , size(other.size) , oldRevision(other.oldRevision) , dirty(other.dirty) , invalidate(other.invalidate) , noResponse(other.noResponse) , notify(other.notify) , modifiedParts(other.modifiedParts) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(modifiedParts) && COMPARE(size) && COMPARE(oldRevision) && COMPARE(dirty) && COMPARE(invalidate) && COMPARE(noResponse) && COMPARE(notify) && COMPARE(items) && COMPARE(flags) && COMPARE(addedFlags) && COMPARE(removedFlags) && COMPARE(tags) && COMPARE(addedTags) && COMPARE(removedTags) && COMPARE(remoteId) && COMPARE(remoteRev) && COMPARE(gid) && COMPARE(removedParts) && COMPARE(parts) && COMPARE(attributes); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { CommandPrivate::serialize(stream) << items << oldRevision << modifiedParts << dirty << invalidate << noResponse << notify; if (modifiedParts & ModifyItemsCommand::Flags) { stream << flags; } if (modifiedParts & ModifyItemsCommand::AddedFlags) { stream << addedFlags; } if (modifiedParts & ModifyItemsCommand::RemovedFlags) { stream << removedFlags; } if (modifiedParts & ModifyItemsCommand::Tags) { stream << tags; } if (modifiedParts & ModifyItemsCommand::AddedTags) { stream << addedTags; } if (modifiedParts & ModifyItemsCommand::RemovedTags) { stream << removedTags; } if (modifiedParts & ModifyItemsCommand::RemoteID) { stream << remoteId; } if (modifiedParts & ModifyItemsCommand::RemoteRevision) { stream << remoteRev; } if (modifiedParts & ModifyItemsCommand::GID) { stream << gid; } if (modifiedParts & ModifyItemsCommand::Size) { stream << size; } if (modifiedParts & ModifyItemsCommand::Parts) { stream << parts; } if (modifiedParts & ModifyItemsCommand::RemovedParts) { stream << removedParts; } if (modifiedParts & ModifyItemsCommand::Attributes) { stream << attributes; } return stream; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { CommandPrivate::deserialize(stream) >> items >> oldRevision >> modifiedParts >> dirty >> invalidate >> noResponse >> notify; if (modifiedParts & ModifyItemsCommand::Flags) { stream >> flags; } if (modifiedParts & ModifyItemsCommand::AddedFlags) { stream >> addedFlags; } if (modifiedParts & ModifyItemsCommand::RemovedFlags) { stream >> removedFlags; } if (modifiedParts & ModifyItemsCommand::Tags) { stream >> tags; } if (modifiedParts & ModifyItemsCommand::AddedTags) { stream >> addedTags; } if (modifiedParts & ModifyItemsCommand::RemovedTags) { stream >> removedTags; } if (modifiedParts & ModifyItemsCommand::RemoteID) { stream >> remoteId; } if (modifiedParts & ModifyItemsCommand::RemoteRevision) { stream >> remoteRev; } if (modifiedParts & ModifyItemsCommand::GID) { stream >> gid; } if (modifiedParts & ModifyItemsCommand::Size) { stream >> size; } if (modifiedParts & ModifyItemsCommand::Parts) { stream >> parts; } if (modifiedParts & ModifyItemsCommand::RemovedParts) { stream >> removedParts; } if (modifiedParts & ModifyItemsCommand::Attributes) { stream >> attributes; } return stream; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { QStringList mps; if (modifiedParts & ModifyItemsCommand::Flags) { mps << QStringLiteral("Flags"); } if (modifiedParts & ModifyItemsCommand::AddedFlags) { mps << QStringLiteral("Added Flags"); } if (modifiedParts & ModifyItemsCommand::RemovedFlags) { mps << QStringLiteral("Removed Flags"); } if (modifiedParts & ModifyItemsCommand::Tags) { mps << QStringLiteral("Tags"); } if (modifiedParts & ModifyItemsCommand::AddedTags) { mps << QStringLiteral("Added Tags"); } if (modifiedParts & ModifyItemsCommand::RemovedTags) { mps << QStringLiteral("Removed Tags"); } if (modifiedParts & ModifyItemsCommand::RemoteID) { mps << QStringLiteral("Remote ID"); } if (modifiedParts & ModifyItemsCommand::RemoteRevision) { mps << QStringLiteral("Remote Revision"); } if (modifiedParts & ModifyItemsCommand::GID) { mps << QStringLiteral("GID"); } if (modifiedParts & ModifyItemsCommand::Size) { mps << QStringLiteral("Size"); } if (modifiedParts & ModifyItemsCommand::Parts) { mps << QStringLiteral("Parts"); } if (modifiedParts & ModifyItemsCommand::RemovedParts) { mps << QStringLiteral("Removed Parts"); } if (modifiedParts & ModifyItemsCommand::Attributes) { mps << QStringLiteral("Attributes"); } CommandPrivate::debugString(blck); blck.write("Modified PartS", mps); blck.write("Items", items); blck.write("Old Revision", oldRevision); blck.write("Dirty", dirty); blck.write("Invalidate Cache", invalidate); blck.write("No Response", noResponse); blck.write("Notify", notify); if (modifiedParts & ModifyItemsCommand::Flags) { blck.write("Flags", flags); } if (modifiedParts & ModifyItemsCommand::AddedFlags) { blck.write("Added Flags", addedFlags); } if (modifiedParts & ModifyItemsCommand::RemovedFlags) { blck.write("Removed Flags", removedFlags); } if (modifiedParts & ModifyItemsCommand::Tags) { blck.write("Tags", tags); } if (modifiedParts & ModifyItemsCommand::AddedTags) { blck.write("Added Tags", addedTags); } if (modifiedParts & ModifyItemsCommand::RemovedTags) { blck.write("Removed Tags", removedTags); } if (modifiedParts & ModifyItemsCommand::RemoteID) { blck.write("Remote ID", remoteId); } if (modifiedParts & ModifyItemsCommand::RemoteRevision) { blck.write("Remote Revision", remoteRev); } if (modifiedParts & ModifyItemsCommand::GID) { blck.write("GID", gid); } if (modifiedParts & ModifyItemsCommand::Size) { blck.write("Size", size); } if (modifiedParts & ModifyItemsCommand::Parts) { blck.write("Parts", parts); } if (modifiedParts & ModifyItemsCommand::RemovedParts) { blck.write("Removed Parts", removedParts); } if (modifiedParts & ModifyItemsCommand::Attributes) { blck.beginBlock("Attributes"); for (auto iter = attributes.constBegin(); iter != attributes.constEnd(); ++iter) { blck.write(iter.key().constData(), iter.value()); } blck.endBlock(); } } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new ModifyItemsCommandPrivate(*this); } Scope items; QSet flags; QSet addedFlags; QSet removedFlags; Scope tags; Scope addedTags; Scope removedTags; QString remoteId; QString remoteRev; QString gid; QSet removedParts; QSet parts; Attributes attributes; qint64 size; int oldRevision; bool dirty; bool invalidate; bool noResponse; bool notify; ModifyItemsCommand::ModifiedParts modifiedParts; }; AKONADI_DECLARE_PRIVATE(ModifyItemsCommand) ModifyItemsCommand::ModifyItemsCommand() : Command(new ModifyItemsCommandPrivate) { } ModifyItemsCommand::ModifyItemsCommand(const Scope &items) : Command(new ModifyItemsCommandPrivate(items)) { } ModifyItemsCommand::ModifyItemsCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::ModifyItems); } ModifyItemsCommand::ModifiedParts ModifyItemsCommand::modifiedParts() const { return d_func()->modifiedParts; } void ModifyItemsCommand::setItems(const Scope &items) { d_func()->items = items; } Scope ModifyItemsCommand::items() const { return d_func()->items; } void ModifyItemsCommand::setOldRevision(int oldRevision) { d_func()->oldRevision = oldRevision; } int ModifyItemsCommand::oldRevision() const { return d_func()->oldRevision; } void ModifyItemsCommand::setFlags(const QSet &flags) { d_func()->modifiedParts |= Flags; d_func()->flags = flags; } QSet ModifyItemsCommand::flags() const { return d_func()->flags; } void ModifyItemsCommand::setAddedFlags(const QSet &addedFlags) { d_func()->modifiedParts |= AddedFlags; d_func()->addedFlags = addedFlags; } QSet ModifyItemsCommand::addedFlags() const { return d_func()->addedFlags; } void ModifyItemsCommand::setRemovedFlags(const QSet &removedFlags) { d_func()->modifiedParts |= RemovedFlags; d_func()->removedFlags = removedFlags; } QSet ModifyItemsCommand::removedFlags() const { return d_func()->removedFlags; } void ModifyItemsCommand::setTags(const Scope &tags) { d_func()->modifiedParts |= Tags; d_func()->tags = tags; } Scope ModifyItemsCommand::tags() const { return d_func()->tags; } void ModifyItemsCommand::setAddedTags(const Scope &addedTags) { d_func()->modifiedParts |= AddedTags; d_func()->addedTags = addedTags; } Scope ModifyItemsCommand::addedTags() const { return d_func()->addedTags; } void ModifyItemsCommand::setRemovedTags(const Scope &removedTags) { d_func()->modifiedParts |= RemovedTags; d_func()->removedTags = removedTags; } Scope ModifyItemsCommand::removedTags() const { return d_func()->removedTags; } void ModifyItemsCommand::setRemoteId(const QString &remoteId) { d_func()->modifiedParts |= RemoteID; d_func()->remoteId = remoteId; } QString ModifyItemsCommand::remoteId() const { return d_func()->remoteId; } void ModifyItemsCommand::setRemoteRevision(const QString &remoteRevision) { d_func()->modifiedParts |= RemoteRevision; d_func()->remoteRev = remoteRevision; } QString ModifyItemsCommand::remoteRevision() const { return d_func()->remoteRev; } void ModifyItemsCommand::setGid(const QString &gid) { d_func()->modifiedParts |= GID; d_func()->gid = gid; } QString ModifyItemsCommand::gid() const { return d_func()->gid; } void ModifyItemsCommand::setDirty(bool dirty) { d_func()->dirty = dirty; } bool ModifyItemsCommand::dirty() const { return d_func()->dirty; } void ModifyItemsCommand::setInvalidateCache(bool invalidate) { d_func()->invalidate = invalidate; } bool ModifyItemsCommand::invalidateCache() const { return d_func()->invalidate; } void ModifyItemsCommand::setNoResponse(bool noResponse) { d_func()->noResponse = noResponse; } bool ModifyItemsCommand::noResponse() const { return d_func()->noResponse; } void ModifyItemsCommand::setNotify(bool notify) { d_func()->notify = notify; } bool ModifyItemsCommand::notify() const { return d_func()->notify; } void ModifyItemsCommand::setItemSize(qint64 size) { d_func()->modifiedParts |= Size; d_func()->size = size; } qint64 ModifyItemsCommand::itemSize() const { return d_func()->size; } void ModifyItemsCommand::setRemovedParts(const QSet &removedParts) { d_func()->modifiedParts |= RemovedParts; d_func()->removedParts = removedParts; } QSet ModifyItemsCommand::removedParts() const { return d_func()->removedParts; } void ModifyItemsCommand::setParts(const QSet &parts) { d_func()->modifiedParts |= Parts; d_func()->parts = parts; } QSet ModifyItemsCommand::parts() const { return d_func()->parts; } void ModifyItemsCommand::setAttributes(const Protocol::Attributes &attributes) { d_func()->modifiedParts |= Attributes; d_func()->attributes = attributes; } Attributes ModifyItemsCommand::attributes() const { return d_func()->attributes; } DataStream &operator<<(DataStream &stream, const ModifyItemsCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, ModifyItemsCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ class ModifyItemsResponsePrivate : public ResponsePrivate { public: ModifyItemsResponsePrivate(qint64 id = -1, int newRevision = -1, const QDateTime &modifyDt = QDateTime()) : ResponsePrivate(Command::ModifyItems) , id(id) , newRevision(newRevision) , modificationDt(modifyDt) {} ModifyItemsResponsePrivate(const ModifyItemsResponsePrivate &other) : ResponsePrivate(other) , id(other.id) , newRevision(other.newRevision) , modificationDt(other.modificationDt) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return ResponsePrivate::compare(other) && COMPARE(id) && COMPARE(newRevision) && COMPARE(modificationDt); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return ResponsePrivate::serialize(stream) << id << newRevision << modificationDt; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return ResponsePrivate::deserialize(stream) >> id >> newRevision >> modificationDt; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { ResponsePrivate::debugString(blck); blck.write("ID", id); blck.write("New Revision", newRevision); blck.write("Modification datetime", modificationDt); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new ModifyItemsResponsePrivate(*this); } qint64 id; int newRevision; QDateTime modificationDt; }; AKONADI_DECLARE_PRIVATE(ModifyItemsResponse) ModifyItemsResponse::ModifyItemsResponse() : Response(new ModifyItemsResponsePrivate) { } ModifyItemsResponse::ModifyItemsResponse(qint64 id, int newRevision) : Response(new ModifyItemsResponsePrivate(id, newRevision)) { } ModifyItemsResponse::ModifyItemsResponse(const QDateTime &modificationDt) : Response(new ModifyItemsResponsePrivate(-1, -1, modificationDt)) { } ModifyItemsResponse::ModifyItemsResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::ModifyItems); } qint64 ModifyItemsResponse::id() const { return d_func()->id; } int ModifyItemsResponse::newRevision() const { return d_func()->newRevision; } QDateTime ModifyItemsResponse::modificationDateTime() const { return d_func()->modificationDt; } DataStream &operator<<(DataStream &stream, const ModifyItemsResponse &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, ModifyItemsResponse &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ class MoveItemsCommandPrivate : public CommandPrivate { public: MoveItemsCommandPrivate(const Scope &items = Scope(), const ScopeContext &context = ScopeContext(), const Scope &dest = Scope()) : CommandPrivate(Command::MoveItems) , items(items) , dest(dest) , context(context) {} MoveItemsCommandPrivate(const MoveItemsCommandPrivate &other) : CommandPrivate(other) , items(other.items) , dest(other.dest) , context(other.context) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(items) && COMPARE(dest) && COMPARE(context); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << items << dest << context; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> items >> dest >> context; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Items", items); blck.beginBlock("Context"); context.debugString(blck); blck.endBlock(); blck.write("Destination", dest); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new MoveItemsCommandPrivate(*this); } Scope items; Scope dest; ScopeContext context; }; AKONADI_DECLARE_PRIVATE(MoveItemsCommand) MoveItemsCommand::MoveItemsCommand() : Command(new MoveItemsCommandPrivate) { } MoveItemsCommand::MoveItemsCommand(const Scope &items, const Scope &dest) : Command(new MoveItemsCommandPrivate(items, ScopeContext(), dest)) { } MoveItemsCommand::MoveItemsCommand(const Scope &items, const ScopeContext &ctx, const Scope &dest) : Command(new MoveItemsCommandPrivate(items, ctx, dest)) { } MoveItemsCommand::MoveItemsCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::MoveItems); } Scope MoveItemsCommand::items() const { return d_func()->items; } ScopeContext MoveItemsCommand::itemsContext() const { return d_func()->context; } Scope MoveItemsCommand::destination() const { return d_func()->dest; } DataStream &operator<<(DataStream &stream, const MoveItemsCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, MoveItemsCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ MoveItemsResponse::MoveItemsResponse() : Response(new ResponsePrivate(Command::MoveItems)) { } MoveItemsResponse::MoveItemsResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::MoveItems); } /****************************************************************************/ class CreateCollectionCommandPrivate : public CommandPrivate { public: CreateCollectionCommandPrivate() : CommandPrivate(Command::CreateCollection) , sync(Tristate::Undefined) , display(Tristate::Undefined) , index(Tristate::Undefined) , enabled(true) , isVirtual(false) {} CreateCollectionCommandPrivate(const CreateCollectionCommandPrivate &other) : CommandPrivate(other) , parent(other.parent) , name(other.name) , remoteId(other.remoteId) , remoteRev(other.remoteRev) , mimeTypes(other.mimeTypes) , cachePolicy(other.cachePolicy) , attributes(other.attributes) , sync(other.sync) , display(other.display) , index(other.index) , enabled(other.enabled) , isVirtual(other.isVirtual) {} DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << parent << name << remoteId << remoteRev << mimeTypes << cachePolicy << attributes << enabled << sync << display << index << isVirtual; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> parent >> name >> remoteId >> remoteRev >> mimeTypes >> cachePolicy >> attributes >> enabled >> sync >> display >> index >> isVirtual; } bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(sync) && COMPARE(display) && COMPARE(index) && COMPARE(enabled) && COMPARE(isVirtual) && COMPARE(parent) && COMPARE(name) && COMPARE(remoteId) && COMPARE(remoteRev) && COMPARE(mimeTypes) && COMPARE(cachePolicy) && COMPARE(attributes); } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Name", name); blck.write("Parent", parent); blck.write("Remote ID", remoteId); blck.write("Remote Revision", remoteRev); blck.write("Mimetypes", mimeTypes); blck.write("Sync", sync); blck.write("Display", display); blck.write("Index", index); blck.write("Enabled", enabled); blck.write("Virtual", isVirtual); blck.beginBlock("CachePolicy"); cachePolicy.debugString(blck); blck.endBlock(); blck.write("Attributes", attributes); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new CreateCollectionCommandPrivate(*this); } Scope parent; QString name; QString remoteId; QString remoteRev; QStringList mimeTypes; CachePolicy cachePolicy; Attributes attributes; Tristate sync; Tristate display; Tristate index; bool enabled; bool isVirtual; }; AKONADI_DECLARE_PRIVATE(CreateCollectionCommand) CreateCollectionCommand::CreateCollectionCommand() : Command(new CreateCollectionCommandPrivate) { } CreateCollectionCommand::CreateCollectionCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::CreateCollection); } void CreateCollectionCommand::setParent(const Scope &parent) { d_func()->parent = parent; } Scope CreateCollectionCommand::parent() const { return d_func()->parent; } void CreateCollectionCommand::setName(const QString &name) { d_func()->name = name; } QString CreateCollectionCommand::name() const { return d_func()->name; } void CreateCollectionCommand::setRemoteId(const QString &remoteId) { d_func()->remoteId = remoteId; } QString CreateCollectionCommand::remoteId() const { return d_func()->remoteId; } void CreateCollectionCommand::setRemoteRevision(const QString &remoteRevision) { d_func()->remoteRev = remoteRevision; } QString CreateCollectionCommand::remoteRevision() const { return d_func()->remoteRev; } void CreateCollectionCommand::setMimeTypes(const QStringList &mimeTypes) { d_func()->mimeTypes = mimeTypes; } QStringList CreateCollectionCommand::mimeTypes() const { return d_func()->mimeTypes; } void CreateCollectionCommand::setCachePolicy(const CachePolicy &cachePolicy) { d_func()->cachePolicy = cachePolicy; } CachePolicy CreateCollectionCommand::cachePolicy() const { return d_func()->cachePolicy; } void CreateCollectionCommand::setAttributes(const Attributes &attributes) { d_func()->attributes = attributes; } Attributes CreateCollectionCommand::attributes() const { return d_func()->attributes; } void CreateCollectionCommand::setIsVirtual(bool isVirtual) { d_func()->isVirtual = isVirtual; } bool CreateCollectionCommand::isVirtual() const { return d_func()->isVirtual; } void CreateCollectionCommand::setEnabled(bool enabled) { d_func()->enabled = enabled; } bool CreateCollectionCommand::enabled() const { return d_func()->enabled; } void CreateCollectionCommand::setSyncPref(Tristate sync) { d_func()->sync = sync; } Tristate CreateCollectionCommand::syncPref() const { return d_func()->sync; } void CreateCollectionCommand::setDisplayPref(Tristate display) { d_func()->display = display; } Tristate CreateCollectionCommand::displayPref() const { return d_func()->display; } void CreateCollectionCommand::setIndexPref(Tristate index) { d_func()->index = index; } Tristate CreateCollectionCommand::indexPref() const { return d_func()->index; } DataStream &operator<<(DataStream &stream, const CreateCollectionCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, CreateCollectionCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ CreateCollectionResponse::CreateCollectionResponse() : Response(new ResponsePrivate(Command::CreateCollection)) { } CreateCollectionResponse::CreateCollectionResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::CreateCollection); } /****************************************************************************/ class CopyCollectionCommandPrivate : public CommandPrivate { public: CopyCollectionCommandPrivate(const Scope &collection = Scope(), const Scope &dest = Scope()) : CommandPrivate(Command::CopyCollection) , collection(collection) , dest(dest) {} CopyCollectionCommandPrivate(const CopyCollectionCommandPrivate &other) : CommandPrivate(other) , collection(other.collection) , dest(other.dest) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(collection) && COMPARE(dest); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << collection << dest; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> collection >> dest; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Collection", collection); blck.write("Destination", dest); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new CopyCollectionCommandPrivate(*this); } Scope collection; Scope dest; }; AKONADI_DECLARE_PRIVATE(CopyCollectionCommand) CopyCollectionCommand::CopyCollectionCommand() : Command(new CopyCollectionCommandPrivate) { } CopyCollectionCommand::CopyCollectionCommand(const Scope &collection, const Scope &destination) : Command(new CopyCollectionCommandPrivate(collection, destination)) { } CopyCollectionCommand::CopyCollectionCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::CopyCollection); } Scope CopyCollectionCommand::collection() const { return d_func()->collection; } Scope CopyCollectionCommand::destination() const { return d_func()->dest; } DataStream &operator<<(DataStream &stream, const CopyCollectionCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, CopyCollectionCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ CopyCollectionResponse::CopyCollectionResponse() : Response(new ResponsePrivate(Command::CopyCollection)) { } CopyCollectionResponse::CopyCollectionResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::CopyCollection); } /****************************************************************************/ class DeleteCollectionCommandPrivate : public CommandPrivate { public: DeleteCollectionCommandPrivate(const Scope &col = Scope()) : CommandPrivate(Command::DeleteCollection) , collection(col) {} DeleteCollectionCommandPrivate(const DeleteCollectionCommandPrivate &other) : CommandPrivate(other) , collection(other.collection) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(collection); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << collection; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> collection; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Collection", collection); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new DeleteCollectionCommandPrivate(*this); } Scope collection; }; AKONADI_DECLARE_PRIVATE(DeleteCollectionCommand) DeleteCollectionCommand::DeleteCollectionCommand() : Command(new DeleteCollectionCommandPrivate) { } DeleteCollectionCommand::DeleteCollectionCommand(const Scope &collection) : Command(new DeleteCollectionCommandPrivate(collection)) { } DeleteCollectionCommand::DeleteCollectionCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::DeleteCollection); } Scope DeleteCollectionCommand::collection() const { return d_func()->collection; } DataStream &operator<<(DataStream &stream, const DeleteCollectionCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, DeleteCollectionCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ DeleteCollectionResponse::DeleteCollectionResponse() : Response(new ResponsePrivate(Command::DeleteCollection)) { } DeleteCollectionResponse::DeleteCollectionResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::DeleteCollection); } /****************************************************************************/ class FetchCollectionStatsCommandPrivate : public CommandPrivate { public: FetchCollectionStatsCommandPrivate(const Scope &collection = Scope()) : CommandPrivate(Command::FetchCollectionStats) , collection(collection) {} FetchCollectionStatsCommandPrivate(const FetchCollectionStatsCommandPrivate &other) : CommandPrivate(other) , collection(other.collection) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(collection); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << collection; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> collection; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Collection", collection); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new FetchCollectionStatsCommandPrivate(*this); } Scope collection; }; AKONADI_DECLARE_PRIVATE(FetchCollectionStatsCommand) FetchCollectionStatsCommand::FetchCollectionStatsCommand() : Command(new FetchCollectionStatsCommandPrivate) { } FetchCollectionStatsCommand::FetchCollectionStatsCommand(const Scope &collection) : Command(new FetchCollectionStatsCommandPrivate(collection)) { } FetchCollectionStatsCommand::FetchCollectionStatsCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::FetchCollectionStats); } Scope FetchCollectionStatsCommand::collection() const { return d_func()->collection; } DataStream &operator<<(DataStream &stream, const FetchCollectionStatsCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, FetchCollectionStatsCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ class FetchCollectionStatsResponsePrivate : public ResponsePrivate { public: FetchCollectionStatsResponsePrivate(qint64 count = -1, qint64 unseen = -1, qint64 size = -1) : ResponsePrivate(Command::FetchCollectionStats) , count(count) , unseen(unseen) , size(size) {} FetchCollectionStatsResponsePrivate(const FetchCollectionStatsResponsePrivate &other) : ResponsePrivate(other) , count(other.count) , unseen(other.unseen) , size(other.size) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return ResponsePrivate::compare(other) && COMPARE(count) && COMPARE(unseen) && COMPARE(size); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return ResponsePrivate::serialize(stream) << count << unseen << size; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return ResponsePrivate::deserialize(stream) >> count >> unseen >> size; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { ResponsePrivate::debugString(blck); blck.write("Count", count); blck.write("Unseen", unseen); blck.write("Size", size); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new FetchCollectionStatsResponsePrivate(*this); } qint64 count; qint64 unseen; qint64 size; }; AKONADI_DECLARE_PRIVATE(FetchCollectionStatsResponse) FetchCollectionStatsResponse::FetchCollectionStatsResponse() : Response(new FetchCollectionStatsResponsePrivate) { } FetchCollectionStatsResponse::FetchCollectionStatsResponse(qint64 count, qint64 unseen, qint64 size) : Response(new FetchCollectionStatsResponsePrivate(count, unseen, size)) { } FetchCollectionStatsResponse::FetchCollectionStatsResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::FetchCollectionStats); } qint64 FetchCollectionStatsResponse::count() const { return d_func()->count; } qint64 FetchCollectionStatsResponse::unseen() const { return d_func()->unseen; } qint64 FetchCollectionStatsResponse::size() const { return d_func()->size; } DataStream &operator<<(DataStream &stream, const FetchCollectionStatsResponse &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, FetchCollectionStatsResponse &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ class FetchCollectionsCommandPrivate : public CommandPrivate { public: FetchCollectionsCommandPrivate(const Scope &collections = Scope()) : CommandPrivate(Command::FetchCollections) , collections(collections) , depth(FetchCollectionsCommand::BaseCollection) , ancestorsDepth(Ancestor::NoAncestor) , enabled(false) , sync(false) , display(false) , index(false) , stats(false) {} FetchCollectionsCommandPrivate(const FetchCollectionsCommandPrivate &other) : CommandPrivate(other) , collections(other.collections) , resource(other.resource) , mimeTypes(other.mimeTypes) , ancestorsAttributes(other.ancestorsAttributes) , depth(other.depth) , ancestorsDepth(other.ancestorsDepth) , enabled(other.enabled) , sync(other.sync) , display(other.display) , index(other.index) , stats(other.stats) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(depth) && COMPARE(ancestorsDepth) && COMPARE(enabled) && COMPARE(sync) && COMPARE(display) && COMPARE(index) && COMPARE(stats) && COMPARE(collections) && COMPARE(resource) && COMPARE(mimeTypes) && COMPARE(ancestorsAttributes); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << collections << resource << mimeTypes << depth << ancestorsDepth << ancestorsAttributes << enabled << sync << display << index << stats; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> collections >> resource >> mimeTypes >> depth >> ancestorsDepth >> ancestorsAttributes >> enabled >> sync >> display >> index >> stats; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Collections", collections); blck.write("Depth", depth); blck.write("Resource", resource); blck.write("Mimetypes", mimeTypes); blck.write("Ancestors Depth", ancestorsDepth); blck.write("Ancestors Attributes", ancestorsAttributes); blck.write("Enabled", enabled); blck.write("Sync", sync); blck.write("Display", display); blck.write("Index", index); blck.write("Status", stats); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new FetchCollectionsCommandPrivate(*this); } Scope collections; QString resource; QStringList mimeTypes; QSet ancestorsAttributes; FetchCollectionsCommand::Depth depth; Ancestor::Depth ancestorsDepth; bool enabled; bool sync; bool display; bool index; bool stats; }; AKONADI_DECLARE_PRIVATE(FetchCollectionsCommand) FetchCollectionsCommand::FetchCollectionsCommand() : Command(new FetchCollectionsCommandPrivate) { } FetchCollectionsCommand::FetchCollectionsCommand(const Scope &collections) : Command(new FetchCollectionsCommandPrivate(collections)) { } FetchCollectionsCommand::FetchCollectionsCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::FetchCollections); } Scope FetchCollectionsCommand::collections() const { return d_func()->collections; } void FetchCollectionsCommand::setDepth(Depth depth) { d_func()->depth = depth; } FetchCollectionsCommand::Depth FetchCollectionsCommand::depth() const { return d_func()->depth; } void FetchCollectionsCommand::setResource(const QString &resourceId) { d_func()->resource = resourceId; } QString FetchCollectionsCommand::resource() const { return d_func()->resource; } void FetchCollectionsCommand::setMimeTypes(const QStringList &mimeTypes) { d_func()->mimeTypes = mimeTypes; } QStringList FetchCollectionsCommand::mimeTypes() const { return d_func()->mimeTypes; } void FetchCollectionsCommand::setAncestorsDepth(Ancestor::Depth depth) { d_func()->ancestorsDepth = depth; } Ancestor::Depth FetchCollectionsCommand::ancestorsDepth() const { return d_func()->ancestorsDepth; } void FetchCollectionsCommand::setAncestorsAttributes(const QSet &attributes) { d_func()->ancestorsAttributes = attributes; } QSet FetchCollectionsCommand::ancestorsAttributes() const { return d_func()->ancestorsAttributes; } void FetchCollectionsCommand::setEnabled(bool enabled) { d_func()->enabled = enabled; } bool FetchCollectionsCommand::enabled() const { return d_func()->enabled; } void FetchCollectionsCommand::setSyncPref(bool sync) { d_func()->sync = sync; } bool FetchCollectionsCommand::syncPref() const { return d_func()->sync; } void FetchCollectionsCommand::setDisplayPref(bool display) { d_func()->display = display; } bool FetchCollectionsCommand::displayPref() const { return d_func()->display; } void FetchCollectionsCommand::setIndexPref(bool index) { d_func()->index = index; } bool FetchCollectionsCommand::indexPref() const { return d_func()->index; } void FetchCollectionsCommand::setFetchStats(bool stats) { d_func()->stats = stats; } bool FetchCollectionsCommand::fetchStats() const { return d_func()->stats; } DataStream &operator<<(DataStream &stream, const FetchCollectionsCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, FetchCollectionsCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ class FetchCollectionsResponsePrivate : public ResponsePrivate { public: FetchCollectionsResponsePrivate(qint64 id = -1) : ResponsePrivate(Command::FetchCollections) , id(id) , parentId(-1) , display(Tristate::Undefined) , sync(Tristate::Undefined) , index(Tristate::Undefined) , isVirtual(false) , referenced(false) , enabled(true) {} FetchCollectionsResponsePrivate(const FetchCollectionsResponsePrivate &other) : ResponsePrivate(other) , name(other.name) , remoteId(other.remoteId) , remoteRev(other.remoteRev) , resource(other.resource) , mimeTypes(other.mimeTypes) , stats(other.stats) , searchQuery(other.searchQuery) , searchCols(other.searchCols) , ancestors(other.ancestors) , cachePolicy(other.cachePolicy) , attributes(other.attributes) , id(other.id) , parentId(other.parentId) , display(other.display) , sync(other.sync) , index(other.index) , isVirtual(other.isVirtual) , referenced(other.referenced) , enabled(other.enabled) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return ResponsePrivate::compare(other) && COMPARE(id) && COMPARE(parentId) && COMPARE(display) && COMPARE(sync) && COMPARE(index) && COMPARE(isVirtual) && COMPARE(referenced) && COMPARE(enabled) && COMPARE(name) && COMPARE(remoteId) && COMPARE(remoteRev) && COMPARE(resource) && COMPARE(mimeTypes) && COMPARE(stats) && COMPARE(searchQuery) && COMPARE(searchCols) && COMPARE(ancestors) && COMPARE(cachePolicy) && COMPARE(attributes); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return ResponsePrivate::serialize(stream) << id << parentId << name << mimeTypes << remoteId << remoteRev << resource << stats << searchQuery << searchCols << ancestors << cachePolicy << attributes << display << sync << index << isVirtual << referenced << enabled; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return ResponsePrivate::deserialize(stream) >> id >> parentId >> name >> mimeTypes >> remoteId >> remoteRev >> resource >> stats >> searchQuery >> searchCols >> ancestors >> cachePolicy >> attributes >> display >> sync >> index >> isVirtual >> referenced >> enabled; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { ResponsePrivate::debugString(blck); blck.write("ID", id); blck.write("Name", name); blck.write("Parent ID", parentId); blck.write("Remote ID", remoteId); blck.write("Remote Revision", remoteRev); blck.write("Resource", resource); blck.write("Mimetypes", mimeTypes); blck.beginBlock("Statistics"); blck.write("Count", stats.count()); blck.write("Unseen", stats.unseen()); blck.write("Size", stats.size()); blck.endBlock(); blck.write("Search Query", searchQuery); blck.write("Search Collections", searchCols); blck.beginBlock("Cache Policy"); cachePolicy.debugString(blck); blck.endBlock(); blck.beginBlock("Ancestors"); Q_FOREACH (const Ancestor &anc, ancestors) { blck.beginBlock(); anc.debugString(blck); blck.endBlock(); } blck.endBlock(); blck.write("Attributes", attributes); blck.write("Display", display); blck.write("Sync", sync); blck.write("Index", index); blck.write("Enabled", enabled); blck.write("Virtual", isVirtual); blck.write("Referenced", referenced); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new FetchCollectionsResponsePrivate(*this); } QString name; QString remoteId; QString remoteRev; QString resource; QStringList mimeTypes; FetchCollectionStatsResponse stats; QString searchQuery; QVector searchCols; QVector ancestors; CachePolicy cachePolicy; Attributes attributes; qint64 id; qint64 parentId; Tristate display; Tristate sync; Tristate index; bool isVirtual; bool referenced; bool enabled; }; AKONADI_DECLARE_PRIVATE(FetchCollectionsResponse) FetchCollectionsResponse::FetchCollectionsResponse() : Response(new FetchCollectionsResponsePrivate) { } FetchCollectionsResponse::FetchCollectionsResponse(qint64 id) : Response(new FetchCollectionsResponsePrivate(id)) { } FetchCollectionsResponse::FetchCollectionsResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::FetchCollections); } qint64 FetchCollectionsResponse::id() const { return d_func()->id; } void FetchCollectionsResponse::setParentId(qint64 parentId) { d_func()->parentId = parentId; } qint64 FetchCollectionsResponse::parentId() const { return d_func()->parentId; } void FetchCollectionsResponse::setName(const QString &name) { d_func()->name = name; } QString FetchCollectionsResponse::name() const { return d_func()->name; } void FetchCollectionsResponse::setMimeTypes(const QStringList &mimeTypes) { d_func()->mimeTypes = mimeTypes; } QStringList FetchCollectionsResponse::mimeTypes() const { return d_func()->mimeTypes; } void FetchCollectionsResponse::setRemoteId(const QString &remoteId) { d_func()->remoteId = remoteId; } QString FetchCollectionsResponse::remoteId() const { return d_func()->remoteId; } void FetchCollectionsResponse::setRemoteRevision(const QString &remoteRevision) { d_func()->remoteRev = remoteRevision; } QString FetchCollectionsResponse::remoteRevision() const { return d_func()->remoteRev; } void FetchCollectionsResponse::setResource(const QString &resourceId) { d_func()->resource = resourceId; } QString FetchCollectionsResponse::resource() const { return d_func()->resource; } void FetchCollectionsResponse::setStatistics(const FetchCollectionStatsResponse &stats) { d_func()->stats = stats; } FetchCollectionStatsResponse FetchCollectionsResponse::statistics() const { return d_func()->stats; } void FetchCollectionsResponse::setSearchQuery(const QString &query) { d_func()->searchQuery = query; } QString FetchCollectionsResponse::searchQuery() const { return d_func()->searchQuery; } void FetchCollectionsResponse::setSearchCollections(const QVector &searchCols) { d_func()->searchCols = searchCols; } QVector FetchCollectionsResponse::searchCollections() const { return d_func()->searchCols; } void FetchCollectionsResponse::setAncestors(const QVector &ancestors) { d_func()->ancestors = ancestors; } QVector FetchCollectionsResponse::ancestors() const { return d_func()->ancestors; } void FetchCollectionsResponse::setCachePolicy(const CachePolicy &cachePolicy) { d_func()->cachePolicy = cachePolicy; } CachePolicy FetchCollectionsResponse::cachePolicy() const { return d_func()->cachePolicy; } CachePolicy &FetchCollectionsResponse::cachePolicy() { return d_func()->cachePolicy; } void FetchCollectionsResponse::setAttributes(const Attributes &attrs) { d_func()->attributes = attrs; } Attributes FetchCollectionsResponse::attributes() const { return d_func()->attributes; } void FetchCollectionsResponse::setEnabled(bool enabled) { d_func()->enabled = enabled; } bool FetchCollectionsResponse::enabled() const { return d_func()->enabled; } void FetchCollectionsResponse::setDisplayPref(Tristate display) { d_func()->display = display; } Tristate FetchCollectionsResponse::displayPref() const { return d_func()->display; } void FetchCollectionsResponse::setSyncPref(Tristate sync) { d_func()->sync = sync; } Tristate FetchCollectionsResponse::syncPref() const { return d_func()->sync; } void FetchCollectionsResponse::setIndexPref(Tristate index) { d_func()->index = index; } Tristate FetchCollectionsResponse::indexPref() const { return d_func()->index; } void FetchCollectionsResponse::setReferenced(bool referenced) { d_func()->referenced = referenced; } bool FetchCollectionsResponse::referenced() const { return d_func()->referenced; } void FetchCollectionsResponse::setIsVirtual(bool isVirtual) { d_func()->isVirtual = isVirtual; } bool FetchCollectionsResponse::isVirtual() const { return d_func()->isVirtual; } DataStream &operator<<(DataStream &stream, const FetchCollectionsResponse &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, FetchCollectionsResponse &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ class ModifyCollectionCommandPrivate : public CommandPrivate { public: ModifyCollectionCommandPrivate(const Scope &collection = Scope()) : CommandPrivate(Command::ModifyCollection) , collection(collection) , parentId(-1) , sync(Tristate::Undefined) , display(Tristate::Undefined) , index(Tristate::Undefined) , enabled(true) , referenced(false) , persistentSearchRemote(false) , persistentSearchRecursive(false) , modifiedParts(ModifyCollectionCommand::None) {} ModifyCollectionCommandPrivate(const ModifyCollectionCommandPrivate &other) : CommandPrivate(other) , collection(other.collection) , mimeTypes(other.mimeTypes) , cachePolicy(other.cachePolicy) , name(other.name) , remoteId(other.remoteId) , remoteRev(other.remoteRev) , persistentSearchQuery(other.persistentSearchQuery) , persistentSearchCols(other.persistentSearchCols) , removedAttributes(other.removedAttributes) , attributes(other.attributes) , parentId(other.parentId) , sync(other.sync) , display(other.display) , index(other.index) , enabled(other.enabled) , referenced(other.referenced) , persistentSearchRemote(other.persistentSearchRemote) , persistentSearchRecursive(other.persistentSearchRecursive) , modifiedParts(other.modifiedParts) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(modifiedParts) && COMPARE(parentId) && COMPARE(sync) && COMPARE(display) && COMPARE(index) && COMPARE(enabled) && COMPARE(referenced) && COMPARE(persistentSearchRemote) && COMPARE(persistentSearchRecursive) && COMPARE(collection) && COMPARE(mimeTypes) && COMPARE(cachePolicy) && COMPARE(name) && COMPARE(remoteId) && COMPARE(remoteRev) && COMPARE(persistentSearchQuery) && COMPARE(persistentSearchCols) && COMPARE(removedAttributes) && COMPARE(attributes); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { CommandPrivate::serialize(stream) << collection << modifiedParts; if (modifiedParts & ModifyCollectionCommand::Name) { stream << name; } if (modifiedParts & ModifyCollectionCommand::RemoteID) { stream << remoteId; } if (modifiedParts & ModifyCollectionCommand::RemoteRevision) { stream << remoteRev; } if (modifiedParts & ModifyCollectionCommand::ParentID) { stream << parentId; } if (modifiedParts & ModifyCollectionCommand::MimeTypes) { stream << mimeTypes; } if (modifiedParts & ModifyCollectionCommand::CachePolicy) { stream << cachePolicy; } if (modifiedParts & ModifyCollectionCommand::PersistentSearch) { stream << persistentSearchQuery << persistentSearchCols << persistentSearchRemote << persistentSearchRecursive; } if (modifiedParts & ModifyCollectionCommand::RemovedAttributes) { stream << removedAttributes; } if (modifiedParts & ModifyCollectionCommand::Attributes) { stream << attributes; } if (modifiedParts & ModifyCollectionCommand::ListPreferences) { stream << enabled << sync << display << index; } if (modifiedParts & ModifyCollectionCommand::Referenced) { stream << referenced; } return stream; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { CommandPrivate::deserialize(stream) >> collection >> modifiedParts; if (modifiedParts & ModifyCollectionCommand::Name) { stream >> name; } if (modifiedParts & ModifyCollectionCommand::RemoteID) { stream >> remoteId; } if (modifiedParts & ModifyCollectionCommand::RemoteRevision) { stream >> remoteRev; } if (modifiedParts & ModifyCollectionCommand::ParentID) { stream >> parentId; } if (modifiedParts & ModifyCollectionCommand::MimeTypes) { stream >> mimeTypes; } if (modifiedParts & ModifyCollectionCommand::CachePolicy) { stream >> cachePolicy; } if (modifiedParts & ModifyCollectionCommand::PersistentSearch) { stream >> persistentSearchQuery >> persistentSearchCols >> persistentSearchRemote >> persistentSearchRecursive; } if (modifiedParts & ModifyCollectionCommand::RemovedAttributes) { stream >> removedAttributes; } if (modifiedParts & ModifyCollectionCommand::Attributes) { stream >> attributes; } if (modifiedParts & ModifyCollectionCommand::ListPreferences) { stream >> enabled >> sync >> display >> index; } if (modifiedParts & ModifyCollectionCommand::Referenced) { stream >> referenced; } return stream; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { QStringList mps; if (modifiedParts & ModifyCollectionCommand::Name) { mps << QStringLiteral("Name"); } if (modifiedParts & ModifyCollectionCommand::RemoteID) { mps << QStringLiteral("Remote ID"); } if (modifiedParts & ModifyCollectionCommand::RemoteRevision) { mps << QStringLiteral("Remote Revision"); } if (modifiedParts & ModifyCollectionCommand::ParentID) { mps << QStringLiteral("Parent ID"); } if (modifiedParts & ModifyCollectionCommand::MimeTypes) { mps << QStringLiteral("Mimetypes"); } if (modifiedParts & ModifyCollectionCommand::CachePolicy) { mps << QStringLiteral("Cache Policy"); } if (modifiedParts & ModifyCollectionCommand::PersistentSearch) { mps << QStringLiteral("Persistent Search"); } if (modifiedParts & ModifyCollectionCommand::RemovedAttributes) { mps << QStringLiteral("Remote Attributes"); } if (modifiedParts & ModifyCollectionCommand::Attributes) { mps << QStringLiteral("Attributes"); } if (modifiedParts & ModifyCollectionCommand::ListPreferences) { mps << QStringLiteral("List Preferences"); } if (modifiedParts & ModifyCollectionCommand::Referenced) { mps << QStringLiteral("Referenced"); } CommandPrivate::debugString(blck); blck.write("Collection", collection); blck.write("Modified Parts", mps); if (modifiedParts & ModifyCollectionCommand::Name) { blck.write("Name", name); } if (modifiedParts & ModifyCollectionCommand::RemoteID) { blck.write("Remote ID", remoteId); } if (modifiedParts & ModifyCollectionCommand::RemoteRevision) { blck.write("Remote Revision", remoteRev); } if (modifiedParts & ModifyCollectionCommand::ParentID) { blck.write("Parent ID", parentId); } if (modifiedParts & ModifyCollectionCommand::MimeTypes) { blck.write("Mimetypes", mimeTypes); } if (modifiedParts & ModifyCollectionCommand::CachePolicy) { blck.beginBlock("Cache Policy"); cachePolicy.debugString(blck); blck.endBlock(); } if (modifiedParts & ModifyCollectionCommand::PersistentSearch) { blck.beginBlock("Persistent Search"); blck.write("Query", persistentSearchQuery); blck.write("Cols", persistentSearchCols); blck.write("Remote", persistentSearchRemote); blck.write("Recursive", persistentSearchRecursive); blck.endBlock(); } if (modifiedParts & ModifyCollectionCommand::RemovedAttributes) { blck.write("Removed Attributes", removedAttributes); } if (modifiedParts & ModifyCollectionCommand::Attributes) { blck.write("Attributes", attributes); } if (modifiedParts & ModifyCollectionCommand::ListPreferences) { blck.write("Sync", sync); blck.write("Display", display); blck.write("Index", index); blck.write("Enabled", enabled); } if (modifiedParts & ModifyCollectionCommand::Referenced) { blck.write("Referenced", referenced); } } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new ModifyCollectionCommandPrivate(*this); } Scope collection; QStringList mimeTypes; Protocol::CachePolicy cachePolicy; QString name; QString remoteId; QString remoteRev; QString persistentSearchQuery; QVector persistentSearchCols; QSet removedAttributes; Attributes attributes; qint64 parentId; Tristate sync; Tristate display; Tristate index; bool enabled; bool referenced; bool persistentSearchRemote; bool persistentSearchRecursive; ModifyCollectionCommand::ModifiedParts modifiedParts; }; AKONADI_DECLARE_PRIVATE(ModifyCollectionCommand) ModifyCollectionCommand::ModifyCollectionCommand() : Command(new ModifyCollectionCommandPrivate) { } ModifyCollectionCommand::ModifyCollectionCommand(const Scope &collection) : Command(new ModifyCollectionCommandPrivate(collection)) { } ModifyCollectionCommand::ModifyCollectionCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::ModifyCollection); } Scope ModifyCollectionCommand::collection() const { return d_func()->collection; } ModifyCollectionCommand::ModifiedParts ModifyCollectionCommand::modifiedParts() const { return d_func()->modifiedParts; } void ModifyCollectionCommand::setParentId(qint64 parentId) { d_func()->parentId = parentId; } qint64 ModifyCollectionCommand::parentId() const { return d_func()->parentId; } void ModifyCollectionCommand::setMimeTypes(const QStringList &mimeTypes) { d_func()->modifiedParts |= MimeTypes; d_func()->modifiedParts |= PersistentSearch; d_func()->mimeTypes = mimeTypes; } QStringList ModifyCollectionCommand::mimeTypes() const { return d_func()->mimeTypes; } void ModifyCollectionCommand::setCachePolicy(const Protocol::CachePolicy &cachePolicy) { d_func()->modifiedParts |= CachePolicy; d_func()->cachePolicy = cachePolicy; } Protocol::CachePolicy ModifyCollectionCommand::cachePolicy() const { return d_func()->cachePolicy; } void ModifyCollectionCommand::setName(const QString &name) { d_func()->modifiedParts |= Name; d_func()->name = name; } QString ModifyCollectionCommand::name() const { return d_func()->name; } void ModifyCollectionCommand::setRemoteId(const QString &remoteId) { d_func()->modifiedParts |= RemoteID; d_func()->remoteId = remoteId; } QString ModifyCollectionCommand::remoteId() const { return d_func()->remoteId; } void ModifyCollectionCommand::setRemoteRevision(const QString &remoteRevision) { d_func()->modifiedParts |= RemoteRevision; d_func()->remoteRev = remoteRevision; } QString ModifyCollectionCommand::remoteRevision() const { return d_func()->remoteRev; } void ModifyCollectionCommand::setPersistentSearchQuery(const QString &query) { d_func()->modifiedParts |= PersistentSearch; d_func()->persistentSearchQuery = query; } QString ModifyCollectionCommand::persistentSearchQuery() const { return d_func()->persistentSearchQuery; } void ModifyCollectionCommand::setPersistentSearchCollections(const QVector &cols) { d_func()->modifiedParts |= PersistentSearch; d_func()->persistentSearchCols = cols; } QVector ModifyCollectionCommand::persistentSearchCollections() const { return d_func()->persistentSearchCols; } void ModifyCollectionCommand::setPersistentSearchRemote(bool remote) { d_func()->modifiedParts |= PersistentSearch; d_func()->persistentSearchRemote = remote; } bool ModifyCollectionCommand::persistentSearchRemote() const { return d_func()->persistentSearchRemote; } void ModifyCollectionCommand::setPersistentSearchRecursive(bool recursive) { d_func()->modifiedParts |= PersistentSearch; d_func()->persistentSearchRecursive = recursive; } bool ModifyCollectionCommand::persistentSearchRecursive() const { return d_func()->persistentSearchRecursive; } void ModifyCollectionCommand::setRemovedAttributes(const QSet &removedAttrs) { d_func()->modifiedParts |= RemovedAttributes; d_func()->removedAttributes = removedAttrs; } QSet ModifyCollectionCommand::removedAttributes() const { return d_func()->removedAttributes; } void ModifyCollectionCommand::setAttributes(const Protocol::Attributes &attributes) { d_func()->modifiedParts |= Attributes; d_func()->attributes = attributes; } Attributes ModifyCollectionCommand::attributes() const { return d_func()->attributes; } void ModifyCollectionCommand::setEnabled(bool enabled) { d_func()->modifiedParts |= ListPreferences; d_func()->enabled = enabled; } bool ModifyCollectionCommand::enabled() const { return d_func()->enabled; } void ModifyCollectionCommand::setSyncPref(Tristate sync) { d_func()->modifiedParts |= ListPreferences; d_func()->sync = sync; } Tristate ModifyCollectionCommand::syncPref() const { return d_func()->sync; } void ModifyCollectionCommand::setDisplayPref(Tristate display) { d_func()->modifiedParts |= ListPreferences; d_func()->display = display; } Tristate ModifyCollectionCommand::displayPref() const { return d_func()->display; } void ModifyCollectionCommand::setIndexPref(Tristate index) { d_func()->modifiedParts |= ListPreferences; d_func()->index = index; } Tristate ModifyCollectionCommand::indexPref() const { return d_func()->index; } void ModifyCollectionCommand::setReferenced(bool referenced) { d_func()->modifiedParts |= Referenced; d_func()->referenced = referenced; } bool ModifyCollectionCommand::referenced() const { return d_func()->referenced; } DataStream &operator<<(DataStream &stream, const ModifyCollectionCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, ModifyCollectionCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ ModifyCollectionResponse::ModifyCollectionResponse() : Response(new ResponsePrivate(Command::ModifyCollection)) { } ModifyCollectionResponse::ModifyCollectionResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::ModifyCollection); } /****************************************************************************/ class MoveCollectionCommandPrivate : public CommandPrivate { public: MoveCollectionCommandPrivate(const Scope &collection = Scope(), const Scope &dest = Scope()) : CommandPrivate(Command::MoveCollection) , collection(collection) , dest(dest) {} MoveCollectionCommandPrivate(const MoveCollectionCommandPrivate &other) : CommandPrivate(other) , collection(other.collection) , dest(other.dest) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(collection) && COMPARE(dest); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << collection << dest; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> collection >> dest; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Collection", collection); blck.write("Destination", dest); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new MoveCollectionCommandPrivate(*this); } Scope collection; Scope dest; }; AKONADI_DECLARE_PRIVATE(MoveCollectionCommand) MoveCollectionCommand::MoveCollectionCommand() : Command(new MoveCollectionCommandPrivate) { } MoveCollectionCommand::MoveCollectionCommand(const Scope &collection, const Scope &destination) : Command(new MoveCollectionCommandPrivate(collection, destination)) { } MoveCollectionCommand::MoveCollectionCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::MoveCollection); } Scope MoveCollectionCommand::collection() const { return d_func()->collection; } Scope MoveCollectionCommand::destination() const { return d_func()->dest; } DataStream &operator<<(DataStream &stream, const MoveCollectionCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, MoveCollectionCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ MoveCollectionResponse::MoveCollectionResponse() : Response(new ResponsePrivate(Command::MoveCollection)) { } MoveCollectionResponse::MoveCollectionResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::MoveCollection); } /****************************************************************************/ class SearchCommandPrivate : public CommandPrivate { public: SearchCommandPrivate() : CommandPrivate(Command::Search) , recursive(false) , remote(false) {} SearchCommandPrivate(const SearchCommandPrivate &other) : CommandPrivate(other) , mimeTypes(other.mimeTypes) , collections(other.collections) , query(other.query) , fetchScope(other.fetchScope) , recursive(other.recursive) , remote(other.remote) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(recursive) && COMPARE(remote) && COMPARE(mimeTypes) && COMPARE(collections) && COMPARE(query) && COMPARE(fetchScope); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << mimeTypes << collections << query << fetchScope << recursive << remote; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> mimeTypes >> collections >> query >> fetchScope >> recursive >> remote; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Query", query); blck.write("Collections", collections); blck.write("Mimetypes", mimeTypes); blck.beginBlock("Fetch Scope"); fetchScope.debugString(blck); blck.endBlock(); blck.write("Recursive", recursive); blck.write("Remote", remote); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new SearchCommandPrivate(*this); } QStringList mimeTypes; QVector collections; QString query; FetchScope fetchScope; bool recursive; bool remote; }; AKONADI_DECLARE_PRIVATE(SearchCommand) SearchCommand::SearchCommand() : Command(new SearchCommandPrivate) { } SearchCommand::SearchCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::Search); } void SearchCommand::setMimeTypes(const QStringList &mimeTypes) { d_func()->mimeTypes = mimeTypes; } QStringList SearchCommand::mimeTypes() const { return d_func()->mimeTypes; } void SearchCommand::setCollections(const QVector &collections) { d_func()->collections = collections; } QVector SearchCommand::collections() const { return d_func()->collections; } void SearchCommand::setQuery(const QString &query) { d_func()->query = query; } QString SearchCommand::query() const { return d_func()->query; } void SearchCommand::setFetchScope(const FetchScope &fetchScope) { d_func()->fetchScope = fetchScope; } FetchScope SearchCommand::fetchScope() const { return d_func()->fetchScope; } void SearchCommand::setRecursive(bool recursive) { d_func()->recursive = recursive; } bool SearchCommand::recursive() const { return d_func()->recursive; } void SearchCommand::setRemote(bool remote) { d_func()->remote = remote; } bool SearchCommand::remote() const { return d_func()->remote; } DataStream &operator<<(DataStream &stream, const SearchCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, SearchCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ SearchResponse::SearchResponse() : Response(new ResponsePrivate(Command::Search)) { } SearchResponse::SearchResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::Search); } /****************************************************************************/ class SearchResultCommandPrivate : public CommandPrivate { public: SearchResultCommandPrivate(const QByteArray &searchId = QByteArray(), qint64 collectionId = -1, const Scope &result = Scope()) : CommandPrivate(Command::SearchResult) , searchId(searchId) , result(result) , collectionId(collectionId) {} SearchResultCommandPrivate(const SearchResultCommandPrivate &other) : CommandPrivate(other) , searchId(other.searchId) , result(other.result) , collectionId(other.collectionId) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(searchId) && COMPARE(collectionId) && COMPARE(result); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << searchId << collectionId << result; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> searchId >> collectionId >> result; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Search ID", searchId); blck.write("Collection ID", collectionId); blck.write("Result", result); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new SearchResultCommandPrivate(*this); } QByteArray searchId; Scope result; qint64 collectionId; }; AKONADI_DECLARE_PRIVATE(SearchResultCommand) SearchResultCommand::SearchResultCommand() : Command(new SearchResultCommandPrivate) { } SearchResultCommand::SearchResultCommand(const QByteArray &searchId, qint64 collectionId, const Scope &result) : Command(new SearchResultCommandPrivate(searchId, collectionId, result)) { } SearchResultCommand::SearchResultCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::SearchResult); } QByteArray SearchResultCommand::searchId() const { return d_func()->searchId; } qint64 SearchResultCommand::collectionId() const { return d_func()->collectionId; } Scope SearchResultCommand::result() const { return d_func()->result; } DataStream &operator<<(DataStream &stream, const SearchResultCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, SearchResultCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ SearchResultResponse::SearchResultResponse() : Response(new ResponsePrivate(Command::SearchResult)) { } SearchResultResponse::SearchResultResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::SearchResult); } /****************************************************************************/ class StoreSearchCommandPrivate : public CommandPrivate { public: StoreSearchCommandPrivate() : CommandPrivate(Command::StoreSearch) , remote(false) , recursive(false) {} StoreSearchCommandPrivate(const StoreSearchCommandPrivate &other) : CommandPrivate(other) , name(other.name) , query(other.query) , mimeTypes(other.mimeTypes) , queryCols(other.queryCols) , remote(other.remote) , recursive(other.recursive) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(remote) && COMPARE(recursive) && COMPARE(name) && COMPARE(query) && COMPARE(mimeTypes) && COMPARE(queryCols); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << name << query << mimeTypes << queryCols << remote << recursive; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> name >> query >> mimeTypes >> queryCols >> remote >> recursive; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Name", name); blck.write("Query", query); blck.write("Mimetypes", mimeTypes); blck.write("Query Collections", queryCols); blck.write("Remote", remote); blck.write("Recursive", recursive); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new StoreSearchCommandPrivate(*this); } QString name; QString query; QStringList mimeTypes; QVector queryCols; bool remote; bool recursive; }; AKONADI_DECLARE_PRIVATE(StoreSearchCommand) StoreSearchCommand::StoreSearchCommand() : Command(new StoreSearchCommandPrivate) { } StoreSearchCommand::StoreSearchCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::StoreSearch); } void StoreSearchCommand::setName(const QString &name) { d_func()->name = name; } QString StoreSearchCommand::name() const { return d_func()->name; } void StoreSearchCommand::setQuery(const QString &query) { d_func()->query = query; } QString StoreSearchCommand::query() const { return d_func()->query; } void StoreSearchCommand::setMimeTypes(const QStringList &mimeTypes) { d_func()->mimeTypes = mimeTypes; } QStringList StoreSearchCommand::mimeTypes() const { return d_func()->mimeTypes; } void StoreSearchCommand::setQueryCollections(const QVector &queryCols) { d_func()->queryCols = queryCols; } QVector StoreSearchCommand::queryCollections() const { return d_func()->queryCols; } void StoreSearchCommand::setRemote(bool remote) { d_func()->remote = remote; } bool StoreSearchCommand::remote() const { return d_func()->remote; } void StoreSearchCommand::setRecursive(bool recursive) { d_func()->recursive = recursive; } bool StoreSearchCommand::recursive() const { return d_func()->recursive; } DataStream &operator<<(DataStream &stream, const StoreSearchCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, StoreSearchCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ StoreSearchResponse::StoreSearchResponse() : Response(new ResponsePrivate(Command::StoreSearch)) { } StoreSearchResponse::StoreSearchResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::StoreSearch); } /****************************************************************************/ class CreateTagCommandPrivate : public CommandPrivate { public: CreateTagCommandPrivate() : CommandPrivate(Command::CreateTag) , parentId(-1) , merge(false) {} CreateTagCommandPrivate(const CreateTagCommandPrivate &other) : CommandPrivate(other) , gid(other.gid) , remoteId(other.remoteId) , type(other.type) , attributes(other.attributes) , parentId(other.parentId) , merge(other.merge) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(parentId) && COMPARE(merge) && COMPARE(gid) && COMPARE(remoteId) && COMPARE(type) && COMPARE(attributes); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << gid << remoteId << type << attributes << parentId << merge; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> gid >> remoteId >> type >> attributes >> parentId >> merge; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Merge", merge); blck.write("GID", gid); blck.write("Remote ID", remoteId); - blck.write("Parnet ID", parentId); + blck.write("Parent ID", parentId); blck.write("Type", type); blck.write("Attributes", attributes); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new CreateTagCommandPrivate(*this); } QByteArray gid; QByteArray remoteId; QByteArray type; Attributes attributes; qint64 parentId; bool merge; }; AKONADI_DECLARE_PRIVATE(CreateTagCommand) CreateTagCommand::CreateTagCommand() : Command(new CreateTagCommandPrivate) { } CreateTagCommand::CreateTagCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::CreateTag); } void CreateTagCommand::setGid(const QByteArray &gid) { d_func()->gid = gid; } QByteArray CreateTagCommand::gid() const { return d_func()->gid; } void CreateTagCommand::setRemoteId(const QByteArray &remoteId) { d_func()->remoteId = remoteId; } QByteArray CreateTagCommand::remoteId() const { return d_func()->remoteId; } void CreateTagCommand::setType(const QByteArray &type) { d_func()->type = type; } QByteArray CreateTagCommand::type() const { return d_func()->type; } void CreateTagCommand::setParentId(qint64 parentId) { d_func()->parentId = parentId; } qint64 CreateTagCommand::parentId() const { return d_func()->parentId; } void CreateTagCommand::setMerge(bool merge) { d_func()->merge = merge; } bool CreateTagCommand::merge() const { return d_func()->merge; } void CreateTagCommand::setAttributes(const Attributes &attributes) { d_func()->attributes = attributes; } Attributes CreateTagCommand::attributes() const { return d_func()->attributes; } DataStream &operator<<(DataStream &stream, const CreateTagCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, CreateTagCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ CreateTagResponse::CreateTagResponse() : Response(new ResponsePrivate(Command::CreateTag)) { } CreateTagResponse::CreateTagResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::CreateTag); } /****************************************************************************/ class DeleteTagCommandPrivate : public CommandPrivate { public: DeleteTagCommandPrivate(const Scope &tag = Scope()) : CommandPrivate(Command::DeleteTag) , tag(tag) {} DeleteTagCommandPrivate(const DeleteTagCommandPrivate &other) : CommandPrivate(other) , tag(other.tag) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(tag); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << tag; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> tag; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Tag", tag); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new DeleteTagCommandPrivate(*this); } Scope tag; }; AKONADI_DECLARE_PRIVATE(DeleteTagCommand) DeleteTagCommand::DeleteTagCommand() : Command(new DeleteTagCommandPrivate) { } DeleteTagCommand::DeleteTagCommand(const Scope &tag) : Command(new DeleteTagCommandPrivate(tag)) { } DeleteTagCommand::DeleteTagCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::DeleteTag); } Scope DeleteTagCommand::tag() const { return d_func()->tag; } DataStream &operator<<(DataStream &stream, const DeleteTagCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, DeleteTagCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ DeleteTagResponse::DeleteTagResponse() : Response(new ResponsePrivate(Command::DeleteTag)) { } DeleteTagResponse::DeleteTagResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::DeleteTag); } /****************************************************************************/ class ModifyTagCommandPrivate : public CommandPrivate { public: ModifyTagCommandPrivate(qint64 tagId = -1) : CommandPrivate(Command::ModifyTag) , tagId(tagId) , parentId(-1) , modifiedParts(ModifyTagCommand::None) {} ModifyTagCommandPrivate(const ModifyTagCommandPrivate &other) : CommandPrivate(other) , type(other.type) , remoteId(other.remoteId) , removedAttributes(other.removedAttributes) , attributes(other.attributes) , tagId(other.tagId) , parentId(other.parentId) , modifiedParts(other.modifiedParts) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(modifiedParts) && COMPARE(parentId) && COMPARE(tagId) && COMPARE(type) && COMPARE(remoteId) && COMPARE(removedAttributes); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { CommandPrivate::serialize(stream) << tagId << modifiedParts; if (modifiedParts & ModifyTagCommand::ParentId) { stream << parentId; } if (modifiedParts & ModifyTagCommand::Type) { stream << type; } if (modifiedParts & ModifyTagCommand::RemoteId) { stream << remoteId; } if (modifiedParts & ModifyTagCommand::RemovedAttributes) { stream << removedAttributes; } if (modifiedParts & ModifyTagCommand::Attributes) { stream << attributes; } return stream; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { CommandPrivate::deserialize(stream) >> tagId >> modifiedParts; if (modifiedParts & ModifyTagCommand::ParentId) { stream >> parentId; } if (modifiedParts & ModifyTagCommand::Type) { stream >> type; } if (modifiedParts & ModifyTagCommand::RemoteId) { stream >> remoteId; } if (modifiedParts & ModifyTagCommand::RemovedAttributes) { stream >> removedAttributes; } if (modifiedParts & ModifyTagCommand::Attributes) { stream >> attributes; } return stream; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { QStringList mps; if (modifiedParts & ModifyTagCommand::ParentId) { mps << QStringLiteral("Parent ID"); } if (modifiedParts & ModifyTagCommand::Type) { mps << QStringLiteral("Type"); } if (modifiedParts & ModifyTagCommand::RemoteId) { mps << QStringLiteral("Remote ID"); } if (modifiedParts & ModifyTagCommand::RemovedAttributes) { mps << QStringLiteral("Removed Attributes"); } if (modifiedParts & ModifyTagCommand::Attributes) { mps << QStringLiteral("Attributes"); } CommandPrivate::debugString(blck); blck.write("Tag ID", tagId); blck.write("Modified Parts", mps); if (modifiedParts & ModifyTagCommand::ParentId) { blck.write("Parent ID", parentId); } if (modifiedParts & ModifyTagCommand::Type) { blck.write("Type", type); } if (modifiedParts & ModifyTagCommand::RemoteId) { blck.write("Remote ID", remoteId); } if (modifiedParts & ModifyTagCommand::RemovedAttributes) { blck.write("Removed Attributes", removedAttributes); } if (modifiedParts & ModifyTagCommand::Attributes) { blck.write("Attributes", attributes); } } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new ModifyTagCommandPrivate(*this); } QByteArray type; QByteArray remoteId; QSet removedAttributes; Attributes attributes; qint64 tagId; qint64 parentId; ModifyTagCommand::ModifiedParts modifiedParts; }; AKONADI_DECLARE_PRIVATE(ModifyTagCommand) ModifyTagCommand::ModifyTagCommand() : Command(new ModifyTagCommandPrivate) { } ModifyTagCommand::ModifyTagCommand(qint64 id) : Command(new ModifyTagCommandPrivate(id)) { } ModifyTagCommand::ModifyTagCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::ModifyTag); } qint64 ModifyTagCommand::tagId() const { return d_func()->tagId; } ModifyTagCommand::ModifiedParts ModifyTagCommand::modifiedParts() const { return d_func()->modifiedParts; } void ModifyTagCommand::setParentId(qint64 parentId) { d_func()->modifiedParts |= ParentId; d_func()->parentId = parentId; } qint64 ModifyTagCommand::parentId() const { return d_func()->parentId; } void ModifyTagCommand::setType(const QByteArray &type) { d_func()->modifiedParts |= Type; d_func()->type = type; } QByteArray ModifyTagCommand::type() const { return d_func()->type; } void ModifyTagCommand::setRemoteId(const QByteArray &remoteId) { d_func()->modifiedParts |= RemoteId; d_func()->remoteId = remoteId; } QByteArray ModifyTagCommand::remoteId() const { return d_func()->remoteId; } void ModifyTagCommand::setRemovedAttributes(const QSet &removed) { d_func()->modifiedParts |= RemovedAttributes; d_func()->removedAttributes = removed; } QSet ModifyTagCommand::removedAttributes() const { return d_func()->removedAttributes; } void ModifyTagCommand::setAttributes(const Protocol::Attributes &attributes) { d_func()->modifiedParts |= Attributes; d_func()->attributes = attributes; } Attributes ModifyTagCommand::attributes() const { return d_func()->attributes; } DataStream &operator<<(DataStream &stream, const ModifyTagCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, ModifyTagCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ ModifyTagResponse::ModifyTagResponse() : Response(new ResponsePrivate(Command::ModifyTag)) { } ModifyTagResponse::ModifyTagResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::ModifyTag); } /****************************************************************************/ class ModifyRelationCommandPrivate : public CommandPrivate { public: ModifyRelationCommandPrivate(qint64 left = -1, qint64 right = -1, const QByteArray &type = QByteArray(), const QByteArray &remoteId = QByteArray()) : CommandPrivate(Command::ModifyRelation) , type(type) , remoteId(remoteId) , left(left) , right(right) {} ModifyRelationCommandPrivate(const ModifyRelationCommandPrivate &other) : CommandPrivate(other) , type(other.type) , remoteId(other.remoteId) , left(other.left) , right(other.right) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(left) && COMPARE(right) && COMPARE(type) && COMPARE(remoteId); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << left << right << type << remoteId; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> left >> right >> type >> remoteId; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Left", left); blck.write("Right", right); blck.write("Type", type); blck.write("Remote ID", remoteId); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new ModifyRelationCommandPrivate(*this); } QByteArray type; QByteArray remoteId; qint64 left; qint64 right; }; AKONADI_DECLARE_PRIVATE(ModifyRelationCommand) ModifyRelationCommand::ModifyRelationCommand() : Command(new ModifyRelationCommandPrivate) { } ModifyRelationCommand::ModifyRelationCommand(qint64 left, qint64 right, const QByteArray &type, const QByteArray &remoteId) : Command(new ModifyRelationCommandPrivate(left, right, type, remoteId)) { } ModifyRelationCommand::ModifyRelationCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::ModifyRelation); } void ModifyRelationCommand::setLeft(qint64 left) { d_func()->left = left; } qint64 ModifyRelationCommand::left() const { return d_func()->left; } void ModifyRelationCommand::setRight(qint64 right) { d_func()->right = right; } qint64 ModifyRelationCommand::right() const { return d_func()->right; } void ModifyRelationCommand::setType(const QByteArray &type) { d_func()->type = type; } QByteArray ModifyRelationCommand::type() const { return d_func()->type; } void ModifyRelationCommand::setRemoteId(const QByteArray &remoteId) { d_func()->remoteId = remoteId; } QByteArray ModifyRelationCommand::remoteId() const { return d_func()->remoteId; } DataStream &operator<<(DataStream &stream, const ModifyRelationCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, ModifyRelationCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ ModifyRelationResponse::ModifyRelationResponse() : Response(new ResponsePrivate(Command::ModifyRelation)) { } ModifyRelationResponse::ModifyRelationResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::ModifyRelation); } /****************************************************************************/ class RemoveRelationsCommandPrivate : public CommandPrivate { public: RemoveRelationsCommandPrivate(qint64 left = -1, qint64 right = -1, const QByteArray &type = QByteArray()) : CommandPrivate(Command::RemoveRelations) , left(left) , right(right) , type(type) {} RemoveRelationsCommandPrivate(const RemoveRelationsCommandPrivate &other) : CommandPrivate(other) , left(other.left) , right(other.right) , type(other.type) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(left) && COMPARE(right) && COMPARE(type); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << left << right << type; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> left >> right >> type; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Left", left); blck.write("Right", right); blck.write("Type", type); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new RemoveRelationsCommandPrivate(*this); } qint64 left; qint64 right; QByteArray type; }; AKONADI_DECLARE_PRIVATE(RemoveRelationsCommand) RemoveRelationsCommand::RemoveRelationsCommand() : Command(new RemoveRelationsCommandPrivate) { } RemoveRelationsCommand::RemoveRelationsCommand(qint64 left, qint64 right, const QByteArray &type) : Command(new RemoveRelationsCommandPrivate(left, right, type)) { } RemoveRelationsCommand::RemoveRelationsCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::RemoveRelations); } void RemoveRelationsCommand::setLeft(qint64 left) { d_func()->left = left; } qint64 RemoveRelationsCommand::left() const { return d_func()->left; } void RemoveRelationsCommand::setRight(qint64 right) { d_func()->right = right; } qint64 RemoveRelationsCommand::right() const { return d_func()->right; } void RemoveRelationsCommand::setType(const QByteArray &type) { d_func()->type = type; } QByteArray RemoveRelationsCommand::type() const { return d_func()->type; } DataStream &operator<<(DataStream &stream, const RemoveRelationsCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, RemoveRelationsCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ RemoveRelationsResponse::RemoveRelationsResponse() : Response(new ResponsePrivate(Command::RemoveRelations)) { } RemoveRelationsResponse::RemoveRelationsResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::RemoveRelations); } /****************************************************************************/ class SelectResourceCommandPrivate : public CommandPrivate { public: SelectResourceCommandPrivate(const QString &resourceId = QString()) : CommandPrivate(Command::SelectResource) , resourceId(resourceId) {} SelectResourceCommandPrivate(const SelectResourceCommandPrivate &other) : CommandPrivate(other) , resourceId(other.resourceId) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(resourceId); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << resourceId; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> resourceId; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Resource ID", resourceId); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new SelectResourceCommandPrivate(*this); } QString resourceId; }; AKONADI_DECLARE_PRIVATE(SelectResourceCommand) SelectResourceCommand::SelectResourceCommand() : Command(new SelectResourceCommandPrivate) { } SelectResourceCommand::SelectResourceCommand(const QString &resourceId) : Command(new SelectResourceCommandPrivate(resourceId)) { } SelectResourceCommand::SelectResourceCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::SelectResource); } QString SelectResourceCommand::resourceId() const { return d_func()->resourceId; } DataStream &operator<<(DataStream &stream, const SelectResourceCommand &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, SelectResourceCommand &command) { return command.d_func()->deserialize(stream); } /****************************************************************************/ SelectResourceResponse::SelectResourceResponse() : Response(new ResponsePrivate(Command::SelectResource)) { } SelectResourceResponse::SelectResourceResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::SelectResource); } /****************************************************************************/ class StreamPayloadCommandPrivate : public CommandPrivate { public: StreamPayloadCommandPrivate(const QByteArray &name = QByteArray(), StreamPayloadCommand::Request request = StreamPayloadCommand::MetaData, const QString &dest = QString()) : CommandPrivate(Command::StreamPayload) , payloadName(name) , dest(dest) , request(request) {} StreamPayloadCommandPrivate(const StreamPayloadCommandPrivate &other) : CommandPrivate(other) , payloadName(other.payloadName) , dest(other.dest) , request(other.request) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(request) && COMPARE(payloadName) && COMPARE(dest); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << payloadName << request << dest; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> payloadName >> request >> dest; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { CommandPrivate::debugString(blck); blck.write("Payload Name", payloadName); blck.write("Request", request); blck.write("Destination", dest); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new StreamPayloadCommandPrivate(*this); } QByteArray payloadName; QString dest; StreamPayloadCommand::Request request; }; AKONADI_DECLARE_PRIVATE(StreamPayloadCommand) StreamPayloadCommand::StreamPayloadCommand() : Command(new StreamPayloadCommandPrivate) { } StreamPayloadCommand::StreamPayloadCommand(const QByteArray &name, Request request, const QString &dest) : Command(new StreamPayloadCommandPrivate(name, request, dest)) { } StreamPayloadCommand::StreamPayloadCommand(const Command &other) : Command(other) { checkCopyInvariant(Command::StreamPayload); } void StreamPayloadCommand::setPayloadName(const QByteArray &name) { d_func()->payloadName = name; } QByteArray StreamPayloadCommand::payloadName() const { return d_func()->payloadName; } void StreamPayloadCommand::setRequest(Request request) { d_func()->request = request; } StreamPayloadCommand::Request StreamPayloadCommand::request() const { return d_func()->request; } void StreamPayloadCommand::setDestination(const QString &dest) { d_func()->dest = dest; } QString StreamPayloadCommand::destination() const { return d_func()->dest; } DataStream &operator<<(DataStream &stream, const StreamPayloadCommand &command) { return command.d_func()->serialize(stream); return stream; } DataStream &operator>>(DataStream &stream, StreamPayloadCommand &command) { return command.d_func()->deserialize(stream); return stream; } /****************************************************************************/ class StreamPayloadResponsePrivate : public ResponsePrivate { public: StreamPayloadResponsePrivate(const QByteArray &payloadName = QByteArray(), const PartMetaData &metaData = PartMetaData(), const QByteArray &data = QByteArray()) : ResponsePrivate(Command::StreamPayload) , payloadName(payloadName) , data(data) , metaData(metaData) {} StreamPayloadResponsePrivate(const StreamPayloadResponsePrivate &other) : ResponsePrivate(other) , payloadName(other.payloadName) , data(other.data) , metaData(other.metaData) {} bool compare(const CommandPrivate* other) const Q_DECL_OVERRIDE { return ResponsePrivate::compare(other) && COMPARE(metaData) && COMPARE(payloadName) && COMPARE(data); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return ResponsePrivate::serialize(stream) << payloadName << metaData << data; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return ResponsePrivate::deserialize(stream) >> payloadName >> metaData >> data; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { ResponsePrivate::debugString(blck); blck.beginBlock("MetaData"); blck.write("Name", metaData.name()); blck.write("Size", metaData.size()); blck.write("Version", metaData.version()); blck.endBlock(); blck.write("Data", data); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new StreamPayloadResponsePrivate(*this); } QByteArray payloadName; QByteArray data; PartMetaData metaData; }; AKONADI_DECLARE_PRIVATE(StreamPayloadResponse) StreamPayloadResponse::StreamPayloadResponse() : Response(new StreamPayloadResponsePrivate) { } StreamPayloadResponse::StreamPayloadResponse(const QByteArray &payloadName, const PartMetaData &metaData) : Response(new StreamPayloadResponsePrivate(payloadName, metaData)) { } StreamPayloadResponse::StreamPayloadResponse(const QByteArray &payloadName, const QByteArray &data) : Response(new StreamPayloadResponsePrivate(payloadName, PartMetaData(), data)) { } StreamPayloadResponse::StreamPayloadResponse(const QByteArray &payloadName, const PartMetaData &metaData, const QByteArray &data) : Response(new StreamPayloadResponsePrivate(payloadName, metaData, data)) { } StreamPayloadResponse::StreamPayloadResponse(const Command &other) : Response(other) { checkCopyInvariant(Command::StreamPayload); } void StreamPayloadResponse::setPayloadName(const QByteArray &payloadName) { d_func()->payloadName = payloadName; } QByteArray StreamPayloadResponse::payloadName() const { return d_func()->payloadName; } void StreamPayloadResponse::setMetaData(const PartMetaData &metaData) { d_func()->metaData = metaData; } PartMetaData StreamPayloadResponse::metaData() const { return d_func()->metaData; } void StreamPayloadResponse::setData(const QByteArray &data) { d_func()->data = data; } QByteArray StreamPayloadResponse::data() const { return d_func()->data; } DataStream &operator<<(DataStream &stream, const StreamPayloadResponse &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, StreamPayloadResponse &command) { return command.d_func()->deserialize(stream); } /******************************************************************************/ class ChangeNotificationPrivate : public CommandPrivate { public: ChangeNotificationPrivate() : CommandPrivate(Command::ChangeNotification) , parentCollection(-1) , parentDestCollection(-1) , type(ChangeNotification::InvalidType) , operation(ChangeNotification::InvalidOp) {} ChangeNotificationPrivate(const ChangeNotificationPrivate &other) : CommandPrivate(other) , sessionId(other.sessionId) , items(other.items) , resource(other.resource) , destResource(other.destResource) , parts(other.parts) , addedFlags(other.addedFlags) , removedFlags(other.removedFlags) , addedTags(other.addedTags) , removedTags(other.removedTags) , metadata(other.metadata) , parentCollection(other.parentCollection) , parentDestCollection(other.parentDestCollection) , type(other.type) , operation(other.operation) {} bool compareWithoutOpAndParts(const ChangeNotificationPrivate *other) const { return type == other->type && items == other->items && sessionId == other->sessionId && resource == other->resource && destResource == other->destResource && parentCollection == other->parentCollection && parentDestCollection == other->parentDestCollection; } bool compare(const CommandPrivate *other) const Q_DECL_OVERRIDE { return CommandPrivate::compare(other) && COMPARE(operation) && COMPARE(parts) && COMPARE(addedFlags) && COMPARE(removedFlags) && COMPARE(addedTags) && COMPARE(removedTags) && compareWithoutOpAndParts(static_cast(other)); } CommandPrivate *clone() const Q_DECL_OVERRIDE { return new ChangeNotificationPrivate(*this); } DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE { return CommandPrivate::serialize(stream) << type << operation << sessionId << items << resource << destResource << parts << addedFlags << removedFlags << addedTags << removedTags << parentCollection << parentDestCollection; } DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE { return CommandPrivate::deserialize(stream) >> type >> operation >> sessionId >> items >> resource >> destResource >> parts >> addedFlags >> removedFlags >> addedTags >> removedTags >> parentCollection >> parentDestCollection; } void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE { blck.write("Type", [this]() -> QString { switch (type) { case ChangeNotification::Items: return QStringLiteral("Items"); case ChangeNotification::Collections: return QStringLiteral("Collections"); case ChangeNotification::Tags: return QStringLiteral("Tags"); case ChangeNotification::Relations: return QStringLiteral("Relations"); case ChangeNotification::InvalidType: return QStringLiteral("*INVALID TYPE*"); } Q_ASSERT(false); return QString(); }()); blck.write("Operation", [this]() -> QString { switch (operation) { case ChangeNotification::Add: return QStringLiteral("Add"); case ChangeNotification::Modify: return QStringLiteral("Modify"); case ChangeNotification::ModifyFlags: return QStringLiteral("ModifyFlags"); case ChangeNotification::ModifyTags: return QStringLiteral("ModifyTags"); case ChangeNotification::ModifyRelations: return QStringLiteral("ModifyRelations"); case ChangeNotification::Move: return QStringLiteral("Move"); case ChangeNotification::Remove: return QStringLiteral("Remove"); case ChangeNotification::Link: return QStringLiteral("Link"); case ChangeNotification::Unlink: return QStringLiteral("Unlink"); case ChangeNotification::Subscribe: return QStringLiteral("Subscribe"); case ChangeNotification::Unsubscribe: return QStringLiteral("Unsubscribe"); case ChangeNotification::InvalidOp: return QStringLiteral("*INVALID OPERATION*"); } Q_ASSERT(false); return QString(); }()); blck.beginBlock("Items"); Q_FOREACH (const ChangeNotification::Entity &item, items) { blck.beginBlock(); blck.write("ID", item.id); blck.write("RemoteID", item.remoteId); blck.write("Remote Revision", item.remoteRevision); blck.write("Mime Type", item.mimeType); blck.endBlock(); } blck.endBlock(); blck.write("Session", sessionId); blck.write("Resource", resource); blck.write("Destination Resource", destResource); blck.write("Parent Collection", parentCollection); blck.write("Parent Destination Collection", parentDestCollection); blck.write("Parts", parts); blck.write("Added Flags", addedFlags); blck.write("Removed Flags", removedFlags); blck.write("Added Tags", addedTags); blck.write("Removed Tags", removedTags); } QByteArray sessionId; QMap items; QByteArray resource; QByteArray destResource; QSet parts; QSet addedFlags; QSet removedFlags; QSet addedTags; QSet removedTags; // For internal use only: Akonadi server can add some additional information // that might be useful when evaluating the notification for example, but - // it is never transfered to clients + // it is never transferred to clients QVector metadata; qint64 parentCollection; qint64 parentDestCollection; ChangeNotification::Type type; ChangeNotification::Operation operation; }; AKONADI_DECLARE_PRIVATE(ChangeNotification) ChangeNotification::ChangeNotification() : Command(new ChangeNotificationPrivate) { } ChangeNotification::ChangeNotification(const Command &other) : Command(other) { checkCopyInvariant(Command::ChangeNotification); } bool ChangeNotification::isValid() const { Q_D(const ChangeNotification); return d->commandType == Command::ChangeNotification && d->type != InvalidType && d->operation != InvalidOp; } void ChangeNotification::addEntity(Id id, const QString &remoteId, const QString &remoteRevision, const QString &mimeType) { d_func()->items.insert(id, Entity(id, remoteId, remoteRevision, mimeType)); } void ChangeNotification::setEntities(const QVector &entities) { Q_D(ChangeNotification); clearEntities(); Q_FOREACH (const Entity &entity, entities) { d->items.insert(entity.id, entity); } } void ChangeNotification::clearEntities() { d_func()->items.clear(); } QMap ChangeNotification::entities() const { return d_func()->items; } ChangeNotification::Entity ChangeNotification::entity(const Id id) const { return d_func()->items.value(id); } QList ChangeNotification::uids() const { return d_func()->items.keys(); } QByteArray ChangeNotification::sessionId() const { return d_func()->sessionId; } void ChangeNotification::setSessionId(const QByteArray &sessionId) { d_func()->sessionId = sessionId; } ChangeNotification::Type ChangeNotification::type() const { return d_func()->type; } void ChangeNotification::setType(Type type) { d_func()->type = type; } ChangeNotification::Operation ChangeNotification::operation() const { return d_func()->operation; } void ChangeNotification::setOperation(Operation operation) { d_func()->operation = operation; } QByteArray ChangeNotification::resource() const { return d_func()->resource; } void ChangeNotification::setResource(const QByteArray &resource) { d_func()->resource = resource; } qint64 ChangeNotification::parentCollection() const { return d_func()->parentCollection; } qint64 ChangeNotification::parentDestCollection() const { return d_func()->parentDestCollection; } void ChangeNotification::setParentCollection(Id parent) { d_func()->parentCollection = parent; } void ChangeNotification::setParentDestCollection(Id parent) { d_func()->parentDestCollection = parent; } void ChangeNotification::setDestinationResource(const QByteArray &destResource) { d_func()->destResource = destResource; } QByteArray ChangeNotification::destinationResource() const { return d_func()->destResource; } QSet ChangeNotification::itemParts() const { return d_func()->parts; } void ChangeNotification::setItemParts(const QSet &parts) { d_func()->parts = parts; } QSet ChangeNotification::addedFlags() const { return d_func()->addedFlags; } void ChangeNotification::setAddedFlags(const QSet &addedFlags) { d_func()->addedFlags = addedFlags; } QSet ChangeNotification::removedFlags() const { return d_func()->removedFlags; } void ChangeNotification::setRemovedFlags(const QSet &removedFlags) { d_func()->removedFlags = removedFlags; } QSet ChangeNotification::addedTags() const { return d_func()->addedTags; } void ChangeNotification::setAddedTags(const QSet &addedTags) { d_func()->addedTags = addedTags; } QSet ChangeNotification::removedTags() const { return d_func()->removedTags; } void ChangeNotification::setRemovedTags(const QSet &removedTags) { d_func()->removedTags = removedTags; } void ChangeNotification::addMetadata(const QByteArray &metadata) { d_func()->metadata.append(metadata); } void ChangeNotification::removeMetadata(const QByteArray &metadata) { d_func()->metadata.removeAll(metadata); } QVector ChangeNotification::metadata() const { return d_func()->metadata; } bool ChangeNotification::appendAndCompress(ChangeNotification::List &list, const ChangeNotification &msg) { //It is likely that compressable notifications are within the last few notifications, so avoid searching a list that is potentially huge static const int maxCompressionSearchLength = 10; int searchCounter = 0; // There are often multiple Collection Modify notifications in the queue, // so we optimize for this case. if (msg.type() == ChangeNotification::Collections && msg.operation() == ChangeNotification::Modify) { typename List::Iterator iter, begin; // We are iterating from end, since there's higher probability of finding // matching notification for (iter = list.end(), begin = list.begin(); iter != begin; ) { --iter; if (msg.d_func()->compareWithoutOpAndParts((*iter).d_func())) { // both are modifications, merge them together and drop the new one if (msg.operation() == ChangeNotification::Modify && iter->operation() == ChangeNotification::Modify) { iter->setItemParts(iter->itemParts() + msg.itemParts()); return false; } // we found Add notification, which means we can drop this modification if (iter->operation() == ChangeNotification::Add) { return false; } } searchCounter++; if (searchCounter >= maxCompressionSearchLength) { break; } } } // All other cases are just append, as the compression becomes too expensive in large batches list.append(msg); return true; } DataStream &operator<<(DataStream &stream, const Akonadi::Protocol::ChangeNotification::Entity &entity) { return stream << entity.id << entity.remoteId << entity.remoteRevision << entity.mimeType; } DataStream &operator>>(DataStream &stream, Akonadi::Protocol::ChangeNotification::Entity &entity) { return stream >> entity.id >> entity.remoteId >> entity.remoteRevision >> entity.mimeType; } DataStream &operator<<(DataStream &stream, const Akonadi::Protocol::ChangeNotification &command) { return command.d_func()->serialize(stream); } DataStream &operator>>(DataStream &stream, Akonadi::Protocol::ChangeNotification &command) { return command.d_func()->deserialize(stream); } } // namespace Protocol } // namespace Akonadi diff --git a/src/private/protocol_exception_p.h b/src/private/protocol_exception_p.h index d0b848043..54858a1ca 100644 --- a/src/private/protocol_exception_p.h +++ b/src/private/protocol_exception_p.h @@ -1,49 +1,49 @@ /* Copyright (c) 2015 Daniel Vrátil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef AKONADI_PROTOCOLEXCEPTION_P_H #define AKONADI_PROTOCOLEXCEPTION_P_H #include "akonadiprivate_export.h" #include #include namespace Akonadi { class AKONADIPRIVATE_EXPORT ProtocolException : public std::exception { public: ProtocolException(const char *what) : std::exception() , mWhat(what) {} const char *what() const throw() { return mWhat.constData(); } private: QByteArray mWhat; }; } // namespace Akonadi -#endif \ No newline at end of file +#endif diff --git a/src/server/handler/copy.h b/src/server/handler/copy.h index 438c2e946..7a637c1c2 100644 --- a/src/server/handler/copy.h +++ b/src/server/handler/copy.h @@ -1,70 +1,70 @@ /* Copyright (c) 2008 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef AKONADI_COPY_H #define AKONADI_COPY_H #include "handler.h" #include "entities.h" namespace Akonadi { namespace Server { /** @ingroup akonadi_server_handler Handler for the COPY command. This command is used to copy a set of items into the specific collection. It is syntactically identical to the IMAP COPY command. The copied items differ in the following points from the originals: - new unique id - empty remote id - possible located in a different collection (and thus resource)

Syntax

Request: @verbatim - request = tag " COPY " seqeunce-set " " collection-id + request = tag " COPY " sequence-set " " collection-id @endverbatim There is only the usual status response indicating success or failure of the COPY command */ class Copy : public Handler { Q_OBJECT public: bool parseStream(); protected: /** Copy the given item and all its parts into the @p target. The changes mentioned above are applied. */ bool copyItem(const PimItem &item, const Collection &target); }; } // namespace Server } // namespace Akonadi #endif diff --git a/src/server/handler/list.cpp b/src/server/handler/list.cpp index c24a55e50..ecd3f7396 100644 --- a/src/server/handler/list.cpp +++ b/src/server/handler/list.cpp @@ -1,606 +1,606 @@ /* Copyright (c) 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "list.h" #include "akonadiserver_debug.h" #include "connection.h" #include "handlerhelper.h" #include "collectionreferencemanager.h" #include "storage/datastore.h" #include "storage/selectquerybuilder.h" #include "storage/collectionqueryhelper.h" #include using namespace Akonadi; using namespace Akonadi::Server; template static bool intersect(const QVector &l1, const QVector &l2) { Q_FOREACH (const T &e2, l2) { if (l1.contains(e2.id())) { return true; } } return false; } List::List() : Handler() , mAncestorDepth(0) , mIncludeStatistics(false) , mEnabledCollections(false) , mCollectionsToDisplay(false) , mCollectionsToSynchronize(false) , mCollectionsToIndex(false) { } QStack List::ancestorsForCollection(const Collection &col) { if (mAncestorDepth <= 0) { return QStack(); } QStack ancestors; Collection parent = col; for (int i = 0; i < mAncestorDepth; ++i) { if (parent.parentId() == 0) { break; } if (mAncestors.contains(parent.parentId())) { parent = mAncestors.value(parent.parentId()); } else { parent = mCollections.value(parent.parentId()); } if (!parent.isValid()) { qCWarning(AKONADISERVER_LOG) << col.id(); throw HandlerException("Found invalid parent in ancestors"); } ancestors.prepend(parent); } return ancestors; } CollectionAttribute::List List::getAttributes(const Collection &col, const QSet &filter) { CollectionAttribute::List attributes; auto it = mCollectionAttributes.find(col.id()); while (it != mCollectionAttributes.end() && it.key() == col.id()) { if (filter.isEmpty() || filter.contains(it.value().type())) { attributes << it.value(); } ++it; } return attributes; } void List::listCollection(const Collection &root, const QStack &ancestors, const QStringList &mimeTypes, const CollectionAttribute::List &attributes) { const bool isReferencedFromSession = connection()->collectionReferenceManager()->isReferenced(root.id(), connection()->sessionId()); //We always expose referenced collections to the resource as referenced (although it's a different session) //Otherwise syncing wouldn't work. const bool resourceIsSynchronizing = root.referenced() && mCollectionsToSynchronize && connection()->context()->resource().isValid(); QStack ancestorAttributes; - //backwards compatibilty, collectionToByteArray will automatically fall-back to id + remoteid + //backwards compatibility, collectionToByteArray will automatically fall-back to id + remoteid if (!mAncestorAttributes.isEmpty()) { ancestorAttributes.reserve(ancestors.size()); Q_FOREACH (const Collection &col, ancestors) { ancestorAttributes.push(getAttributes(col, mAncestorAttributes)); } } // write out collection details Collection dummy = root; DataStore *db = connection()->storageBackend(); db->activeCachePolicy(dummy); sendResponse(HandlerHelper::fetchCollectionsResponse(dummy, attributes, mIncludeStatistics, mAncestorDepth, ancestors, ancestorAttributes, isReferencedFromSession || resourceIsSynchronizing, mimeTypes)); } static Query::Condition filterCondition(const QString &column) { Query::Condition orCondition(Query::Or); orCondition.addValueCondition(column, Query::Equals, (int)Tristate::True); Query::Condition andCondition(Query::And); andCondition.addValueCondition(column, Query::Equals, (int)Tristate::Undefined); andCondition.addValueCondition(Collection::enabledFullColumnName(), Query::Equals, true); orCondition.addCondition(andCondition); orCondition.addValueCondition(Collection::referencedFullColumnName(), Query::Equals, true); return orCondition; } bool List::checkFilterCondition(const Collection &col) const { //Don't include the collection when only looking for enabled collections if (mEnabledCollections && !col.enabled()) { return false; } //Don't include the collection when only looking for collections to display/index/sync if (mCollectionsToDisplay && (((col.displayPref() == Tristate::Undefined) && !col.enabled()) || (col.displayPref() == Tristate::False))) { return false; } if (mCollectionsToIndex && (((col.indexPref() == Tristate::Undefined) && !col.enabled()) || (col.indexPref() == Tristate::False))) { return false; } //Single collection sync will still work since that is using a base fetch if (mCollectionsToSynchronize && (((col.syncPref() == Tristate::Undefined) && !col.enabled()) || (col.syncPref() == Tristate::False))) { return false; } return true; } static QSqlQuery getAttributeQuery(const QVariantList &ids, const QSet &requestedAttributes) { QueryBuilder qb(CollectionAttribute::tableName()); qb.addValueCondition(CollectionAttribute::collectionIdFullColumnName(), Query::In, ids); qb.addColumn(CollectionAttribute::collectionIdFullColumnName()); qb.addColumn(CollectionAttribute::typeFullColumnName()); qb.addColumn(CollectionAttribute::valueFullColumnName()); if (!requestedAttributes.isEmpty()) { QVariantList attributes; attributes.reserve(requestedAttributes.size()); Q_FOREACH (const QByteArray &type, requestedAttributes) { attributes << type; } qb.addValueCondition(CollectionAttribute::typeFullColumnName(), Query::In, attributes); } qb.addSortColumn(CollectionAttribute::collectionIdFullColumnName(), Query::Ascending); if (!qb.exec()) { throw HandlerException("Unable to retrieve attributes for listing"); } return qb.query(); } void List::retrieveAttributes(const QVariantList &collectionIds) { //We are querying for the attributes in batches because something can't handle WHERE IN queries with sets larger than 999 int start = 0; const int size = 999; while (start < collectionIds.size()) { const QVariantList ids = collectionIds.mid(start, size); QSqlQuery attributeQuery = getAttributeQuery(ids, mAncestorAttributes); while (attributeQuery.next()) { CollectionAttribute attr; attr.setType(attributeQuery.value(1).toByteArray()); attr.setValue(attributeQuery.value(2).toByteArray()); // qCDebug(AKONADISERVER_LOG) << "found attribute " << attr.type() << attr.value(); mCollectionAttributes.insert(attributeQuery.value(0).toLongLong(), attr); } start += size; } } static QSqlQuery getMimeTypeQuery(const QVariantList &ids) { QueryBuilder qb(CollectionMimeTypeRelation::tableName()); qb.addJoin(QueryBuilder::LeftJoin, MimeType::tableName(), MimeType::idFullColumnName(), CollectionMimeTypeRelation::rightFullColumnName()); qb.addValueCondition(CollectionMimeTypeRelation::leftFullColumnName(), Query::In, ids); qb.addColumn(CollectionMimeTypeRelation::leftFullColumnName()); qb.addColumn(CollectionMimeTypeRelation::rightFullColumnName()); qb.addColumn(MimeType::nameFullColumnName()); qb.addSortColumn(CollectionMimeTypeRelation::leftFullColumnName(), Query::Ascending); if (!qb.exec()) { throw HandlerException("Unable to retrieve mimetypes for listing"); } return qb.query(); } void List::retrieveCollections(const Collection &topParent, int depth) { /* * Retrieval of collections: * The aim is to reduce the amount of queries as much as possible, as this has the largest performance impact for large queries. * * First all collections that match the given criteria are queried * * We then filter the false positives: * ** all collections out that are not part of the tree we asked for are filtered * ** all collections that are referenced but not by this session or by the owning resource are filtered * * Finally we complete the tree by adding missing collections * * Mimetypes and attributes are also retrieved in single queries to avoid spawning two queries per collection (the N+1 problem). * Note that we're not querying attributes and mimetypes for the collections that are only included to complete the tree, * this results in no items being queried for those collections. */ const qint64 parentId = topParent.isValid() ? topParent.id() : 0; { SelectQueryBuilder qb; if (depth == 0) { qb.addValueCondition(Collection::idFullColumnName(), Query::Equals, parentId); } else if (depth == 1) { if (topParent.isValid()) { qb.addValueCondition(Collection::parentIdFullColumnName(), Query::Equals, parentId); } else { qb.addValueCondition(Collection::parentIdFullColumnName(), Query::Is, QVariant()); } } else { if (topParent.isValid()) { qb.addValueCondition(Collection::resourceIdFullColumnName(), Query::Equals, topParent.resourceId()); } else { // Gimme gimme gimme...everything! } } //Base listings should succeed always if (depth != 0) { if (mCollectionsToSynchronize) { qb.addCondition(filterCondition(Collection::syncPrefFullColumnName())); } else if (mCollectionsToDisplay) { qCDebug(AKONADISERVER_LOG) << "only display"; qb.addCondition(filterCondition(Collection::displayPrefFullColumnName())); } else if (mCollectionsToIndex) { qb.addCondition(filterCondition(Collection::indexPrefFullColumnName())); } else if (mEnabledCollections) { Query::Condition orCondition(Query::Or); orCondition.addValueCondition(Collection::enabledFullColumnName(), Query::Equals, true); orCondition.addValueCondition(Collection::referencedFullColumnName(), Query::Equals, true); qb.addCondition(orCondition); } if (mResource.isValid()) { qb.addValueCondition(Collection::resourceIdFullColumnName(), Query::Equals, mResource.id()); } if (!mMimeTypes.isEmpty()) { qb.addJoin(QueryBuilder::LeftJoin, CollectionMimeTypeRelation::tableName(), CollectionMimeTypeRelation::leftColumn(), Collection::idFullColumnName()); QVariantList mimeTypeFilter; mimeTypeFilter.reserve(mMimeTypes.size()); Q_FOREACH(MimeType::Id mtId, mMimeTypes) { mimeTypeFilter << mtId; } qb.addValueCondition(CollectionMimeTypeRelation::rightColumn(), Query::In, mimeTypeFilter); qb.addGroupColumn(Collection::idFullColumnName()); } } if (!qb.exec()) { throw HandlerException("Unable to retrieve collection for listing"); } Q_FOREACH (const Collection &col, qb.result()) { mCollections.insert(col.id(), col); } } //Post filtering that we couldn't do as part of the sql query if (depth > 0) { auto it = mCollections.begin(); while (it != mCollections.end()) { if (topParent.isValid()) { //Check that each collection is linked to the root collection bool foundParent = false; //We iterate over parents to link it to topParent if possible Collection::Id id = it->parentId(); while (id > 0) { if (id == parentId) { foundParent = true; break; } Collection col = mCollections.value(id); if (!col.isValid()) { col = Collection::retrieveById(id); } id = col.parentId(); } if (!foundParent) { it = mCollections.erase(it); continue; } } - //If we matched referenced collecions we need to ensure the collection was referenced from this session + //If we matched referenced collections we need to ensure the collection was referenced from this session const bool isReferencedFromSession = connection()->collectionReferenceManager()->isReferenced(it->id(), connection()->sessionId()); //The collection is referenced, but not from this session. We need to reevaluate the filter condition if (it->referenced() && !isReferencedFromSession) { //Don't include the collection when only looking for enabled collections. //However, a referenced collection should be still synchronized by the resource, so we exclude this case. if (!checkFilterCondition(*it) && !(mCollectionsToSynchronize && connection()->context()->resource().isValid())) { it = mCollections.erase(it); continue; } } ++it; } } QVariantList mimeTypeIds; QVariantList attributeIds; mimeTypeIds.reserve(mCollections.size()); attributeIds.reserve(mCollections.size()); for (auto it = mCollections.cbegin(), end = mCollections.cend(); it != end; ++it) { mimeTypeIds << it.key(); attributeIds << it.key(); } QVariantList ancestorIds; //We'd only require the non-leaf collections, but we don't know which those are, so we take all. ancestorIds.reserve(mCollections.size()); for (auto it = mCollections.cbegin(), end = mCollections.cend(); it != end; ++it) { ancestorIds << it.key(); } if (mAncestorDepth > 0 && topParent.isValid()) { //unless depth is 0 the base collection is not part of the listing mAncestors.insert(topParent.id(), topParent); ancestorIds << topParent.id(); //We need to retrieve additional ancestors to what we already have in the tree Collection parent = topParent; for (int i = 0; i < mAncestorDepth; ++i) { if (parent.parentId() == 0) { break; } parent = parent.parent(); mAncestors.insert(parent.id(), parent); //We also require the attributes ancestorIds << parent.id(); } } QSet missingCollections; if (depth > 0) { Q_FOREACH (const Collection &col, mCollections) { if (col.parentId() != parentId && !mCollections.contains(col.parentId())) { missingCollections.insert(col.parentId()); } } } /* QSet knownIds; for (const Collection &col : mCollections) { knownIds.insert(col.id()); } qCDebug(AKONADISERVER_LOG) << "HAS:" << knownIds; qCDebug(AKONADISERVER_LOG) << "MISSING:" << missingCollections; */ //Fetch missing collections that are part of the tree while (!missingCollections.isEmpty()) { SelectQueryBuilder qb; QVariantList ids; ids.reserve(missingCollections.size()); Q_FOREACH (qint64 id, missingCollections) { ids << id; } qb.addValueCondition(Collection::idFullColumnName(), Query::In, ids); if (!qb.exec()) { throw HandlerException("Unable to retrieve collections for listing"); } missingCollections.clear(); Q_FOREACH (const Collection &missingCol, qb.result()) { mCollections.insert(missingCol.id(), missingCol); ancestorIds << missingCol.id(); attributeIds << missingCol.id(); //We have to do another round if the parents parent is missing if (missingCol.parentId() != parentId && !mCollections.contains(missingCol.parentId())) { missingCollections.insert(missingCol.parentId()); } } } //Since we don't know when we'll need the ancestor attributes, we have to fetch them all together. //The alternative would be to query for each collection which would reintroduce the N+1 query performance problem. if (!mAncestorAttributes.isEmpty()) { retrieveAttributes(ancestorIds); } //We are querying in batches because something can't handle WHERE IN queries with sets larger than 999 const int querySizeLimit = 999; int mimetypeQueryStart = 0; int attributeQueryStart = 0; QSqlQuery mimeTypeQuery; QSqlQuery attributeQuery; auto it = mCollections.begin(); while (it != mCollections.end()) { const Collection col = it.value(); // qCDebug(AKONADISERVER_LOG) << "col " << col.id(); QStringList mimeTypes; { //Get new query if necessary if (!mimeTypeQuery.isValid() && mimetypeQueryStart < mimeTypeIds.size()) { const QVariantList ids = mimeTypeIds.mid(mimetypeQueryStart, querySizeLimit); mimetypeQueryStart += querySizeLimit; mimeTypeQuery = getMimeTypeQuery(ids); mimeTypeQuery.next(); //place at first record } // qCDebug(AKONADISERVER_LOG) << mimeTypeQuery.isValid() << mimeTypeQuery.value(0).toLongLong(); while (mimeTypeQuery.isValid() && mimeTypeQuery.value(0).toLongLong() < col.id()) { qCDebug(AKONADISERVER_LOG) << "skipped: " << mimeTypeQuery.value(0).toLongLong() << mimeTypeQuery.value(2).toString(); if (!mimeTypeQuery.next()) { break; } } //Advance query while a mimetype for this collection is returned while (mimeTypeQuery.isValid() && mimeTypeQuery.value(0).toLongLong() == col.id()) { mimeTypes << mimeTypeQuery.value(2).toString(); if (!mimeTypeQuery.next()) { break; } } } CollectionAttribute::List attributes; { //Get new query if necessary if (!attributeQuery.isValid() && attributeQueryStart < attributeIds.size()) { const QVariantList ids = attributeIds.mid(attributeQueryStart, querySizeLimit); attributeQueryStart += querySizeLimit; attributeQuery = getAttributeQuery(ids, QSet()); attributeQuery.next(); //place at first record } // qCDebug(AKONADISERVER_LOG) << attributeQuery.isValid() << attributeQuery.value(0).toLongLong(); while (attributeQuery.isValid() && attributeQuery.value(0).toLongLong() < col.id()) { qCDebug(AKONADISERVER_LOG) << "skipped: " << attributeQuery.value(0).toLongLong() << attributeQuery.value(1).toByteArray(); if (!attributeQuery.next()) { break; } } //Advance query while a mimetype for this collection is returned while (attributeQuery.isValid() && attributeQuery.value(0).toLongLong() == col.id()) { CollectionAttribute attr; attr.setType(attributeQuery.value(1).toByteArray()); attr.setValue(attributeQuery.value(2).toByteArray()); attributes << attr; if (!attributeQuery.next()) { break; } } } listCollection(col, ancestorsForCollection(col), mimeTypes, attributes); it++; } } bool List::parseStream() { Protocol::FetchCollectionsCommand cmd(m_command); if (!cmd.resource().isEmpty()) { mResource = Resource::retrieveByName(cmd.resource()); if (!mResource.isValid()) { return failureResponse("Unknown resource"); } } Q_FOREACH (const QString &mtName, cmd.mimeTypes()) { const MimeType mt = MimeType::retrieveByName(mtName); if (mt.isValid()) { mMimeTypes.append(mt.id()); } else { MimeType mt(mtName); if (!mt.insert()) { return failureResponse("Failed to create mimetype record"); } mMimeTypes.append(mt.id()); } } mEnabledCollections = cmd.enabled(); mCollectionsToSynchronize = cmd.syncPref(); mCollectionsToDisplay = cmd.displayPref(); mCollectionsToIndex = cmd.indexPref(); mIncludeStatistics = cmd.fetchStats(); int depth = 0; switch (cmd.depth()) { case Protocol::FetchCollectionsCommand::BaseCollection: depth = 0; break; case Protocol::FetchCollectionsCommand::ParentCollection: depth = 1; break; case Protocol::FetchCollectionsCommand::AllCollections: depth = INT_MAX; break; } switch (cmd.ancestorsDepth()) { case Protocol::Ancestor::NoAncestor: mAncestorDepth = 0; break; case Protocol::Ancestor::ParentAncestor: mAncestorDepth = 1; break; case Protocol::Ancestor::AllAncestors: mAncestorDepth = INT_MAX; break; } mAncestorAttributes = cmd.ancestorsAttributes(); Scope scope = cmd.collections(); if (!scope.isEmpty()) { // not root Collection col; if (scope.scope() == Scope::Uid) { col = Collection::retrieveById(scope.uid()); } else if (scope.scope() == Scope::Rid) { SelectQueryBuilder qb; qb.addValueCondition(Collection::remoteIdFullColumnName(), Query::Equals, scope.rid()); qb.addJoin(QueryBuilder::InnerJoin, Resource::tableName(), Collection::resourceIdFullColumnName(), Resource::idFullColumnName()); if (mCollectionsToSynchronize) { qb.addCondition(filterCondition(Collection::syncPrefFullColumnName())); } else if (mCollectionsToDisplay) { qb.addCondition(filterCondition(Collection::displayPrefFullColumnName())); } else if (mCollectionsToIndex) { qb.addCondition(filterCondition(Collection::indexPrefFullColumnName())); } if (mResource.isValid()) { qb.addValueCondition(Resource::idFullColumnName(), Query::Equals, mResource.id()); } else if (connection()->context()->resource().isValid()) { qb.addValueCondition(Resource::idFullColumnName(), Query::Equals, connection()->context()->resource().id()); } else { return failureResponse("Cannot retrieve collection based on remote identifier without a resource context"); } if (!qb.exec()) { return failureResponse("Unable to retrieve collection for listing"); } Collection::List results = qb.result(); if (results.count() != 1) { return failureResponse(QString::number(results.count()) + QStringLiteral(" collections found")); } col = results.first(); } else if (scope.scope() == Scope::HierarchicalRid) { if (!connection()->context()->resource().isValid()) { return failureResponse("Cannot retrieve collection based on hierarchical remote identifier without a resource context"); } col = CollectionQueryHelper::resolveHierarchicalRID(scope.hridChain(), connection()->context()->resource().id()); } else { return failureResponse("Unexpected error"); } if (!col.isValid()) { return failureResponse("Collection does not exist"); } retrieveCollections(col, depth); } else { //Root folder listing if (depth != 0) { retrieveCollections(Collection(), depth); } } return successResponse(); } diff --git a/src/server/handler/store.h b/src/server/handler/store.h index a68e87f4b..17d673127 100644 --- a/src/server/handler/store.h +++ b/src/server/handler/store.h @@ -1,113 +1,113 @@ /*************************************************************************** * Copyright (C) 2006 by Tobias Koenig * * Copyright (C) 2009 by Volker Krause * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef AKONADISTORE_H #define AKONADISTORE_H #include "handler.h" #include "entities.h" namespace Akonadi { namespace Server { /** @ingroup akonadi_server_handler Handler for the item modification command.

Syntax

One of the following three: @verbatim STORE UID MOVE [] RID MOVE [] @endverbatim @c revision-check is one of the following and allowed iff one item was selected for modification: @verbatim NOREV REV @endverbatim @c modifcations is a parenthesized list containing any of the following: @verbatim SIZE [+-]FLAGS REMOTEID REMOTEREVISION GID DIRTY false INVALIDATECACHE @endverbatim

Semantics

Modifies the selected items. Item selection can happen within the usual three scopes: - based on a uid set relative to the currently selected collection - based on a uid set (UID) - based on a list of remote identifiers within the currently selected collection (RID) - The following item properties can be mofidied: + The following item properties can be modified: - the remote identifier (@c REMOTEID) - the remote revision (@c REMOTEREVISION) - the global identifier (@c GID) - resetting the dirty flag indication local changes not yet replicated to the backend (@c DIRTY) - adding/deleting/setting item flags (@c FLAGS) - setting the item size hint (@c SIZE) - changing item attributes - changing item payload parts If multiple items are selected only the following operations are valid: - adding flags - removing flags - settings flags The following operations are only allowed by resources: - resetting the dirty flag - invalidating the cache - modifying the remote identifier - modifying the remote revision Conflict detection: - only available when modifying a single item - requires the previous item revision to be provided (@c REV) */ class Store : public Handler { Q_OBJECT public: bool parseStream(); private: bool replaceFlags(const PimItem::List &items, const QSet &flags, bool &flagsChanged); bool addFlags(const PimItem::List &items, const QSet &flags, bool &flagsChanged); bool deleteFlags(const PimItem::List &items, const QSet &flags, bool &flagsChanged); bool replaceTags(const PimItem::List &items, const Scope &tags, bool &tagsChanged); bool addTags(const PimItem::List &items, const Scope &tags, bool &tagsChanged); bool deleteTags(const PimItem::List &items, const Scope &tags, bool &tagsChanged); }; } // namespace Server } // namespace Akonadi #endif diff --git a/src/server/handlerhelper.h b/src/server/handlerhelper.h index 812b2255c..000548144 100644 --- a/src/server/handlerhelper.h +++ b/src/server/handlerhelper.h @@ -1,128 +1,128 @@ /*************************************************************************** * Copyright (C) 2006 by Tobias Koenig * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef AKONADIHANDLERHELPER_H #define AKONADIHANDLERHELPER_H #include "entities.h" #include #include #include #include namespace Akonadi { class Scope; class ImapSet; namespace Protocol { class Ancestor; class CachePolicy; class FetchCollectionsResponse; class FetchTagsResponse; class FetchRelationsResponse; } namespace Server { class CommandContext; class Connection; /** Helper functions for command handlers. */ class HandlerHelper { public: /** Returns the collection identified by the given id or path. */ static Collection collectionFromIdOrName(const QByteArray &id); /** Returns the full path for the given collection. */ static QString pathForCollection(const Collection &col); /** Returns the protocol representation of the cache policy of the given Collection object. */ static Protocol::CachePolicy cachePolicyResponse(const Collection &col); /** Returns the protocol representation of the given collection. Make sure DataStore::activeCachePolicy() has been called before to include the effective cache policy */ static Protocol::FetchCollectionsResponse fetchCollectionsResponse(const Collection &col); /** Returns the protocol representation of the given collection. Make sure DataStore::activeCachePolicy() has been called before to include the effective cache policy */ static Protocol::FetchCollectionsResponse fetchCollectionsResponse(const Collection &col, const CollectionAttribute::List &attributeList, bool includeStatistics = false, int ancestorDepth = 0, const QStack &ancestors = QStack(), const QStack &ancestorAttributes = QStack(), bool isReferenced = false, const QStringList &mimeTypes = QStringList()); /** Returns the protocol representation of a collection ancestor chain. */ static QVector ancestorsResponse(int ancestorDepth, const QStack &ancestors, const QStack &_ancestorsAttributes = QStack()); static Protocol::FetchTagsResponse fetchTagsResponse(const Tag &tag, bool withRID = false, Connection *connection = Q_NULLPTR); static Protocol::FetchRelationsResponse fetchRelationsResponse(const Relation &relation); /** Converts a bytearray list of flag names into flag records. - @throws HandlerException on errors during datbase operations + @throws HandlerException on errors during database operations */ static Flag::List resolveFlags(const QSet &flagNames); /** Converts a imap set of tags into tag records. - @throws HandlerException on errors during datbase operations + @throws HandlerException on errors during database operations */ static Tag::List resolveTagsByUID(const ImapSet &tags); static Tag::List resolveTagsByGID(const QStringList &tagsGIDs); static Tag::List resolveTagsByRID(const QStringList &tagsRIDs, CommandContext *context); static Collection collectionFromScope(const Scope &scope, Connection *connection); static Tag::List tagsFromScope(const Scope &scope, Connection *connection); }; } // namespace Server } // namespace Akonadi #endif diff --git a/src/server/notificationmanager.cpp b/src/server/notificationmanager.cpp index b9004573b..7af478c2a 100644 --- a/src/server/notificationmanager.cpp +++ b/src/server/notificationmanager.cpp @@ -1,239 +1,238 @@ /* Copyright (c) 2006 - 2007 Volker Krause Copyright (c) 2010 Michael Jansen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "notificationmanager.h" #include "notificationmanageradaptor.h" #include "notificationsource.h" #include "tracer.h" #include "storage/datastore.h" #include "connection.h" #include #include #include #include #include #include using namespace Akonadi; using namespace Akonadi::Server; NotificationManager *NotificationManager::mSelf = 0; Q_DECLARE_METATYPE(QVector) NotificationManager::NotificationManager() : QObject(0) , mDebug(false) { qRegisterMetaType>(); qDBusRegisterMetaType>(); qRegisterMetaType(); qDBusRegisterMetaType(); qRegisterMetaType>(); qDBusRegisterMetaType>(); new NotificationManagerAdaptor(this); QDBusConnection::sessionBus().registerObject(QStringLiteral("/notifications"), this, QDBusConnection::ExportAdaptors); QDBusConnection::sessionBus().registerObject(QStringLiteral("/notifications/debug"), this, QDBusConnection::ExportScriptableSlots | QDBusConnection::ExportScriptableSignals); const QString serverConfigFile = StandardDirs::serverConfigFile(XdgBaseDirs::ReadWrite); QSettings settings(serverConfigFile, QSettings::IniFormat); mTimer.setInterval(settings.value(QStringLiteral("NotificationManager/Interval"), 50).toInt()); mTimer.setSingleShot(true); connect(&mTimer, &QTimer::timeout, this, &NotificationManager::emitPendingNotifications); } NotificationManager::~NotificationManager() { } NotificationManager *NotificationManager::self() { if (!mSelf) { mSelf = new NotificationManager(); } return mSelf; } void NotificationManager::connectNotificationCollector(NotificationCollector *collector) { connect(collector, &NotificationCollector::notify, this, &NotificationManager::slotNotify); } void NotificationManager::registerConnection(Connection *connection) { QMutexLocker locker(&mSourcesLock); auto source = std::find_if(mNotificationSources.cbegin(), mNotificationSources.cend(), [connection](NotificationSource *source) { return connection->sessionId() == source->dbusPath().path().toLatin1(); }); if (source == mNotificationSources.cend()) { qWarning() << "Received request to register Notification bus connection, but there's no such subscriber"; return; } connect(const_cast(*source), &NotificationSource::notify, connection, static_cast(&Connection::sendResponse), Qt::QueuedConnection); } void NotificationManager::unregisterConnection(Connection *connection) { QMutexLocker locker(&mSourcesLock); auto source = std::find_if(mNotificationSources.cbegin(), mNotificationSources.cend(), [connection](NotificationSource *source) { return connection->sessionId() == source->dbusPath().path().toLatin1(); }); if (source != mNotificationSources.cend()) { (*source)->disconnect(connection); } } void NotificationManager::slotNotify(const Akonadi::Protocol::ChangeNotification::List &msgs) { //akDebug() << Q_FUNC_INFO << "Appending" << msgs.count() << "notifications to current list of " << mNotifications.count() << "notifications"; Q_FOREACH (const Protocol::ChangeNotification &msg, msgs) { Protocol::ChangeNotification::appendAndCompress(mNotifications, msg); } //akDebug() << Q_FUNC_INFO << "We have" << mNotifications.count() << "notifications queued in total after appendAndCompress()"; if (!mTimer.isActive()) { mTimer.start(); } } void NotificationManager::emitPendingNotifications() { if (mNotifications.isEmpty()) { return; } if (mDebug) { QVector bas; bas.reserve(mNotifications.size()); QBuffer buffer; buffer.open(QIODevice::WriteOnly); Q_FOREACH (const Protocol::ChangeNotification ¬ification, mNotifications) { Tracer::self()->signal("NotificationManager::notify", notification.debugString()); Protocol::serialize(&buffer, notification); bas << buffer.data(); buffer.buffer().clear(); buffer.seek(0); } Q_EMIT debugNotify(bas); } else { Q_FOREACH (const Protocol::ChangeNotification ¬ification, mNotifications) { Tracer::self()->signal("NotificationManager::notify", notification.debugString()); } } Q_FOREACH (NotificationSource *source, mNotificationSources) { Protocol::ChangeNotification::List acceptedNotifications; Q_FOREACH (const Protocol::ChangeNotification ¬ification, mNotifications) { if (source->acceptsNotification(notification)) { acceptedNotifications << notification; } } if (!acceptedNotifications.isEmpty()) { source->emitNotification(acceptedNotifications); } } mNotifications.clear(); } QDBusObjectPath NotificationManager::subscribe(const QString &identifier, bool exclusive) { akDebug() << Q_FUNC_INFO << this << identifier << exclusive; NotificationSource *source = mNotificationSources.value(identifier); if (source) { akDebug() << "Known subscriber" << identifier << "subscribes again"; source->addClientServiceName(message().service()); } else { source = new NotificationSource(identifier, message().service(), this); } registerSource(source); source->setExclusive(exclusive); // FIXME KF5: Emit the QDBusObjectPath instead of the identifier Q_EMIT subscribed(source->dbusPath()); return source->dbusPath(); } void NotificationManager::registerSource(NotificationSource *source) { // Protect write operations because of registerConnection() QMutexLocker locker(&mSourcesLock); mNotificationSources.insert(source->identifier(), source); } void NotificationManager::unsubscribe(const QString &identifier) { NotificationSource *source = mNotificationSources.value(identifier); if (source) { unregisterSource(source); source->deleteLater(); Q_EMIT unsubscribed(source->dbusPath()); } else { akDebug() << "Attempt to unsubscribe unknown subscriber" << identifier; } } void NotificationManager::unregisterSource(NotificationSource *source) { // Protect write operations because of registerConnection() QMutexLocker locker(&mSourcesLock); mNotificationSources.remove(source->identifier()); } QList NotificationManager::subscribers() const { QList identifiers; identifiers.reserve(mNotificationSources.count()); Q_FOREACH (NotificationSource *source, mNotificationSources) { identifiers << source->dbusPath(); } return identifiers; } void NotificationManager::enableDebug(bool enable) { mDebug = enable; } bool NotificationManager::debugEnabled() const { return mDebug; } - diff --git a/src/server/preprocessorinstance.h b/src/server/preprocessorinstance.h index 85b3f4eeb..669a3359e 100644 --- a/src/server/preprocessorinstance.h +++ b/src/server/preprocessorinstance.h @@ -1,199 +1,199 @@ /****************************************************************************** * * File : preprocessorinstance.h * Creation date : Sat 18 Jul 2009 02:50:39 * * Copyright (c) 2009 Szymon Stefanek * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA, 02110-1301, USA. * *****************************************************************************/ #ifndef AKONADI_PREPROCESSORINSTANCE_H #define AKONADI_PREPROCESSORINSTANCE_H #include #include #include class OrgFreedesktopAkonadiPreprocessorInterface; namespace Akonadi { namespace Server { class AgentInstance; /** * A single preprocessor (agent) instance. * * Most of the interface of this class is protected and is exposed only * to PreprocessorManager (singleton). * - * This class is NOT thread safe. The caller is responsable of protecting + * This class is NOT thread safe. The caller is responsible of protecting * agains concurrent access. */ class PreprocessorInstance : public QObject { friend class PreprocessorManager; Q_OBJECT protected: /** * Create an instance of a PreprocessorInstance descriptor. */ PreprocessorInstance(const QString &id); public: // This is public only for qDeleteAll() called from PreprocessorManager // ...for some reason couldn't convince gcc to have it as friend... /** * Destroy this instance of the PreprocessorInstance descriptor. */ ~PreprocessorInstance(); private: /** * The internal queue if item identifiers. * The head item in the queue is the one currently being processed. * The other ones are waiting. */ std::deque< qint64 > mItemQueue; /** * Is this processor busy ? * This, in fact, *should* be equivalent to "mItemQueue.count() > 0" * as the head item in the queue is the one being processed now. */ bool mBusy; /** * The date-time at that we have started processing the current * item in the queue. This is used to compute the processing time * and eventually spot a "dead" preprocessor (which takes longer * than N minutes to process an item). */ QDateTime mItemProcessingStartDateTime; /** * The id of this preprocessor instance. This is actually * the AgentInstance identifier. */ QString mId; /** * The preprocessor D-Bus interface. Owned. */ OrgFreedesktopAkonadiPreprocessorInterface *mInterface; protected: /** * This is called by PreprocessorManager just after the construction * in order to connect to the preprocessor instance via D-Bus. * In case of failure this object should be destroyed as it can't * operate properly. The error message is printed via Tracer. */ bool init(); /** * Returns true if this preprocessor instance is currently processing an item. * That is: if we have called "processItem()" on it and it hasn't emitted * itemProcessed() yet. */ bool isBusy() const { return mBusy; } /** * Returns the time in seconds elapsed since the current item was submitted * to the slave preprocessor instance. If no item is currently being * processed then this function returns -1; */ int currentProcessingTime(); /** * Returns the id of this preprocessor. This is actually * the AgentInstance identifier but it's not a requirement. */ const QString &id() const { return mId; } /** * Returns a pointer to the internal preprocessor instance * item queue. Don't mess with it unless you *really* know * what you're doing. Use enqueueItem() to add an item * to the queue. This method is provided to the PreprocessorManager * to take over the item queue of a dying preprocessor. * * The returned pointer is granted to be non null. */ std::deque< qint64 > *itemQueue() { return &mItemQueue; } /** * This is called by PreprocessorManager to enqueue a PimItem * for processing by this preprocessor instance. */ void enqueueItem(qint64 itemId); /** * Attempts to abort the processing of the current item. * May be called only if isBusy() returns true and an assertion * will remind you of that. * Returns true if the abort request was successfully sent * (but not necessarily handled by the slave) and false * if the request couldn't be sent for some reason. */ bool abortProcessing(); /** * Attempts to invoke the preprocessor slave restart via * AgentManager. This is the "last resort" action before * starting to ignore the preprocessor (after it misbehaved). */ bool invokeRestart(); private: /** * This function starts processing of the first item in mItemQueue. * It's only used internally. */ void processHeadItem(); private Q_SLOTS: /** * This is invoked to signal that the processing of the current (head) * item has terminated and the next item should be processed. */ void itemProcessed(qlonglong id); }; // class PreprocessorInstance } // namespace Server } // namespace Akonadi #endif //!_PREPROCESSORINSTANCE_H_ diff --git a/src/server/preprocessormanager.h b/src/server/preprocessormanager.h index 3f5b645da..b22cde99e 100644 --- a/src/server/preprocessormanager.h +++ b/src/server/preprocessormanager.h @@ -1,313 +1,313 @@ /****************************************************************************** * * File : preprocessormanager.h * Creation date : Sat 18 Jul 2009 01:58:50 * * Copyright (c) 2009 Szymon Stefanek * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA, 02110-1301, USA. * *****************************************************************************/ #ifndef AKONADI_PREPROCESSORMANAGER_H #define AKONADI_PREPROCESSORMANAGER_H #include #include #include #include class QTimer; class QMutex; #include "preprocessorinstance.h" namespace Akonadi { namespace Server { class PimItem; class DataStore; /** * \class PreprocessorManager * \brief The manager for preprocessor agents * * This class takes care of synchronizing the preprocessor agents. * * The preprocessors see the incoming PimItem objects before the user * can see them (as long as the UI applications honor the hidden attribute). * The items are marked as hidden (by the Append and AkAppend * handlers) and then enqueued to the preprocessor chain via this class. * Once all the preprocessors have done their work the item is unhidden again. * * Preprocessing isn't designed for critical tasks. There may * be circumstances under that the Akonadi server fails to push an item * to all the preprocessors. Most notably after a server restart all * the items for that preprocessing was interrupted are just unhidden * without any attempt to resume the preprocessor jobs. * * The enqueue requests may or may not arrive from "inside" a database * transaction. The uncommitted transaction would "hide" the newly created items * from the preprocessor instances (which are separate processes). * This class, then, takes care of holding the newly arrived items * in a wait queue until their transaction is committed (or rolled back). */ class PreprocessorManager : public QObject { friend class PreprocessorInstance; Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Akonadi.PreprocessorManager") protected: /** * Creates an instance of PreprocessorManager */ PreprocessorManager(); /** * Destroys the instance of PreprocessorManager * and frees all the relevant resources */ ~PreprocessorManager(); protected: /** * The one and only instance pointer for the class PreprocessorManager */ static PreprocessorManager *mSelf; /** * The hashtable of transaction wait queues. There is one wait * queue for each DataStore that is currently in a transaction. */ QHash< const DataStore *, std::deque< qint64 > *> mTransactionWaitQueueHash; /** * The preprocessor chain. * The pointers inside the list are owned. * * In all the algorithms we assume that this list is actually very short * (say 3-4 elements) and reverse lookup (pointer->index) is really fast. */ QList< PreprocessorInstance *> mPreprocessorChain; /** - * Is preprocessing enabled at all in ths Akonad server instance ? + * Is preprocessing enabled at all in this Akonadi server instance? * This is true by default and can be set via setEnabled(). * Mainly used to disable preprocessing via configuration file. */ bool mEnabled; /** * The mutex used to protect the internals of this class (mainly * the mPreprocessorChain member). */ QMutex *mMutex; /** * The heartbeat timer. Used mainly to expire preprocessor jobs. */ QTimer *mHeartbeatTimer; public: /** * Returns the one and only instance pointer for the class PreprocessorManager - * The returned pointer is valid only after a succesfull call to init(). + * The returned pointer is valid only after a successful call to init(). * * \sa init() * \sa done() */ static PreprocessorManager *instance() { return mSelf; } /** * Initializes this class singleton by creating its one and only instance. * This is actually called in the AkonadiServer constructor. * * The instance is later available via the static instance() method. * You must call done() when you've finished using this class services. - * Returns true upon succesfull initialisation and false when the initialization fails. + * Returns true upon successful initialisation and false when the initialization fails. * * \sa done() */ static bool init(); /** * Deinitializes this class singleton (if it was initialized at all). * This is actually called in the AkonadiServer::quit() method. * * \sa init() */ static void done(); /** * Returns true if preprocessing is active in this Akonadi server. * This means that we have at least one active preprocessor and * preprocessing hasn't been explicitly disabled via configuration * (so if isActive() returns true then also isEnabled() will return true). * * This function is thread-safe. */ bool isActive(); /** * Returns true if this preprocessor hasn't been explicitly disabled * via setEnabled( false ). This is used to disable preprocessing * via configuration even if we have a valid chain of preprocessors. * * Please note that this flag doesn't tell if we actually have * some registered preprocessors and thus we can do some meaningful job. * You should use isActive() for this purpose. */ bool isEnabled() const { return mEnabled; } /** * Explicitly enables or disables the preprocessing in this Akonadi server. * The PreprocessorManager starts in enabled state but can be disabled * at a later stage: this is mainly used to disable preprocessing via * configuration. * * Please note that setting this to true doesn't interrupt the currently * running preprocessing jobs. Anything that was enqueued will be processed * anyway. However, in Akonadi this is only invoked very early, * when no preprocessors are alive yet. */ void setEnabled(bool enabled) { mEnabled = enabled; } /** * Trigger the preprocessor chain for the specified item. * The item should have been added to the Akonadi database via * the specified DataStore object. If the DataStore is in a * transaction then this class will put the item in a wait * queue until the transaction is committed. If the transaction * is rolled back the whole wait queue will be discarded. * If the DataStore is not in a transaction then the item * will be pushed directly to the preprocessing chain. * * You should make sure that the preprocessor chain isActive() * before calling this method. The items you pass to this method, * also, should have the hidden attribute set. * * This function is thread-safe. */ void beginHandleItem(const PimItem &item, const DataStore *dataStore); /** * This is called via D-Bus from AgentManager to register a preprocessor instance. * * This function is thread-safe. */ void registerInstance(const QString &id); /** * This is called via D-Bus from AgentManager to unregister a preprocessor instance. * * This function is thread-safe. */ void unregisterInstance(const QString &id); protected: /** * This is called by PreprocessorInstance to signal that a certain preprocessor has finished * handling an item. * * This function is thread-safe. */ void preProcessorFinishedHandlingItem(PreprocessorInstance *preProcessor, qint64 itemId); private: /** * Finds the preprocessor instance by its identifier. * * This must be called with mMutex locked. */ PreprocessorInstance *lockedFindInstance(const QString &id); /** * Pushes the specified item to the first preprocessor. * The caller *MUST* make sure that there is at least one preprocessor in the chain. */ void lockedActivateFirstPreprocessor(qint64 itemId); /** * This is called internally to terminate the pre-processing * chain for the specified Item. All the preprocessors have * been triggered for it. * * This must be called with mMutex locked. */ void lockedEndHandleItem(qint64 itemId); /** * This is the unprotected core of the unregisterInstance() function above. */ void lockedUnregisterInstance(const QString &id); /** * Kill the wait queue for the specific DataStore object. */ void lockedKillWaitQueue(const DataStore *dataStore, bool disconnectSlots); private Q_SLOTS: /** * Connected to the mHeartbeatTimer. Triggered every minute or something like that :D * Mainly used to expire preprocessor jobs. */ void heartbeat(); /** * This is used to handle database transactions and wait queues. * The call to this slot usually comes from a queued signal/slot connection * (i.e. from the *Append handler thread). */ void dataStoreDestroyed(); /** * This is used to handle database transactions and wait queues. * The call to this slot usually comes from a queued signal/slot connection * (i.e. from the *Append handler thread). */ void dataStoreTransactionCommitted(); /** * This is used to handle database transactions and wait queues. * The call to this slot usually comes from a queued signal/slot connection * (i.e. from the *Append handler thread). */ void dataStoreTransactionRolledBack(); }; // class PreprocessorManager } // namespace Server } // namespace Akonadi #endif //!_PREPROCESSORMANAGER_H_ diff --git a/src/server/search/searchmanager.h b/src/server/search/searchmanager.h index 4cd46e8dc..29f71ea48 100644 --- a/src/server/search/searchmanager.h +++ b/src/server/search/searchmanager.h @@ -1,147 +1,147 @@ /* Copyright (c) 2010 Volker Krause Copyright (c) 2013 Daniel Vrátil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef SEARCHMANAGER_H #define SEARCHMANAGER_H #include #include #include #include #include class QSemaphore; class QTimer; class QPluginLoader; namespace Akonadi { class AbstractSearchPlugin; namespace Server { class NotificationCollector; class AbstractSearchEngine; class Collection; class SearchManagerThread : public QThread { public: SearchManagerThread(const QStringList &searchEngines, QObject *parent = 0); ~SearchManagerThread(); void run(); private: void loadSearchPlugins(); QList mPluginLoaders; QStringList mSearchEngines; }; /** * SearchManager creates and deletes persistent searches for all currently * active search engines. */ class SearchManager : public QObject { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Akonadi.SearchManager") friend class SearchManagerThread; public: /** Create a new search manager with the given @p searchEngines. */ explicit SearchManager(QObject *parent = 0); ~SearchManager(); /** * Returns a global instance of the search manager. */ static SearchManager *instance(); /** * This is called via D-Bus from AgentManager to register an agent with * search interface. */ virtual void registerInstance(const QString &id); /** * This is called via D-Bus from AgentManager to unregister an agent with * search interface. */ virtual void unregisterInstance(const QString &id); /** * Updates the search query asynchronously. Returns immediately */ virtual void updateSearchAsync(const Collection &collection); /** * Updates the search query synchronously. */ virtual void updateSearch(const Collection &collection); /** * Returns currently available search plugins. */ virtual QVector searchPlugins() const; public Q_SLOTS: virtual void scheduleSearchUpdate(); private Q_SLOTS: void searchUpdateTimeout(); void searchUpdateResultsAvailable(const QSet &results); /** * Actual implementation of search updates. * * Since caller invokes this method from a different thread, they use * QMetaObject::invokeMethod(). To still make it possible for callers to behave - * synchrounously, we can pass in a QWaitCondition that the code will wake up + * synchronously, we can pass in a QWaitCondition that the code will wake up * once the search update is completed. */ void updateSearchImpl(const Collection &collection, QSemaphore *cond); protected: void init(const QStringList &searchEngines, const QList &loaders); private: // Runs in SearchManagerThread void initSearchPlugins(const QList &loaders); static SearchManager *sInstance; QVector mEngines; QVector mPlugins; QTimer *mSearchUpdateTimer; QMutex mLock; QSet mUpdatingCollections; }; } // namespace Server } // namespace Akonadi #endif diff --git a/src/server/storage/collectionqueryhelper.h b/src/server/storage/collectionqueryhelper.h index b9e9fc5b7..20321692b 100644 --- a/src/server/storage/collectionqueryhelper.h +++ b/src/server/storage/collectionqueryhelper.h @@ -1,78 +1,78 @@ /* Copyright (c) 2009 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef AKONADI_COLLECTIONQUERYHELPER_H #define AKONADI_COLLECTIONQUERYHELPER_H #include "entities.h" #include namespace Akonadi { class ImapSet; namespace Server { class Connection; class QueryBuilder; /** Helper methods to generate WHERE clauses for collection queries based on a Scope object. */ namespace CollectionQueryHelper { /** Add conditions to @p qb for the given remote identifier @p rid. The rid context is taken from @p connection. */ void remoteIdToQuery(const QStringList &rids, Connection *connection, QueryBuilder &qb); /** Add conditions to @p qb for the given collection operation scope @p scope. The rid context is taken from @p connection, if none is specified an exception is thrown. */ void scopeToQuery(const Scope &scope, Connection *connection, QueryBuilder &qb); /** Checks if a collection could exist in the given parent folder with the given name. */ bool hasAllowedName(const Collection &collection, const QString &name, Collection::Id parent); /** Checks if a collection could be moved from its current parent into the given one. */ bool canBeMovedTo(const Collection &collection, const Collection &parent); /** Retrieve the collection referred to by the given hierarchical RID chain. */ Collection resolveHierarchicalRID(const QVector &hridChain, Resource::Id resId); /** Returns an existing collection specified by the given scope. If that does not - specify exactly one valid collection, an exception is thrwon. + specify exactly one valid collection, an exception is thrown. */ Collection singleCollectionFromScope(const Scope &scope, Connection *connection); } } // namespace Server } // namespace Akonadi #endif diff --git a/src/server/storage/datastore.h b/src/server/storage/datastore.h index 016e6d10e..e4c387c6b 100644 --- a/src/server/storage/datastore.h +++ b/src/server/storage/datastore.h @@ -1,367 +1,367 @@ /*************************************************************************** * Copyright (C) 2006 by Andreas Gungl * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef DATASTORE_H #define DATASTORE_H #include #include #include #include #include #include #include class QSqlQuery; class QTimer; #include "entities.h" #include "notificationcollector.h" namespace Akonadi { namespace Server { class NotificationCollector; /** This class handles all the database access.

Database configuration

You can select between various database backends during runtime using the @c $HOME/.config/akonadi/akonadiserverrc configuration file. Example: @verbatim [%General] Driver=QMYSQL [QMYSQL_EMBEDDED] Name=akonadi Options=SERVER_DATADIR=/home/foo/.local/share/akonadi/db_data [QMYSQL] Name=akonadi Host=localhost User=foo Password=***** #Options=UNIX_SOCKET=/home/foo/.local/share/akonadi/socket-bar/mysql.socket StartServer=true ServerPath=/usr/sbin/mysqld [QSQLITE] Name=/home/foo/.local/share/akonadi/akonadi.db @endverbatim - Use @c General/Driver to select the QSql driver to use for databse + Use @c General/Driver to select the QSql driver to use for database access. The following drivers are currently supported, other might work but are untested: - QMYSQL - QMYSQL_EMBEDDED - QSQLITE The options for each driver are read from the corresponding group. The following options are supported, dependent on the driver not all of them might have an effect: - Name: Database name, for sqlite that's the file name of the database. - Host: Hostname of the database server - User: Username for the database server - Password: Password for the database server - Options: Additional options, format is driver-dependent - StartServer: Start the database locally just for Akonadi instead of using an existing one - ServerPath: Path to the server executable */ class DataStore : public QObject { Q_OBJECT public: /** Closes the database connection and destroys the DataStore object. */ virtual ~DataStore(); /** Opens the database connection. */ virtual void open(); /** - Closes the databse connection. + Closes the database connection. */ virtual void close(); /** Initializes the database. Should be called during startup by the main thread. */ virtual bool init(); /** Per thread singleton. */ static DataStore *self(); /** * Returns whether per thread DataStore has been created. */ static bool hasDataStore(); /* --- ItemFlags ----------------------------------------------------- */ virtual bool setItemsFlags(const PimItem::List &items, const QVector &flags, bool *flagsChanged = 0, const Collection &col = Collection(), bool silent = false); virtual bool appendItemsFlags(const PimItem::List &items, const QVector &flags, bool *flagsChanged = 0, bool checkIfExists = true, const Collection &col = Collection(), bool silent = false); virtual bool removeItemsFlags(const PimItem::List &items, const QVector &flags, bool *tagsChanged = 0, const Collection &collection = Collection(), bool silent = false); /* --- ItemTags ----------------------------------------------------- */ virtual bool setItemsTags(const PimItem::List &items, const Tag::List &tags, bool *tagsChanged = 0, bool silent = false); virtual bool appendItemsTags(const PimItem::List &items, const Tag::List &tags, bool *tagsChanged = 0, bool checkIfExists = true, const Collection &col = Collection(), bool silent = false); virtual bool removeItemsTags(const PimItem::List &items, const Tag::List &tags, bool *tagsChanged = 0, bool silent = false); virtual bool removeTags( const Tag::List &tags, bool silent = false ); /* --- ItemParts ----------------------------------------------------- */ virtual bool removeItemParts(const PimItem &item, const QSet &parts); // removes all payload parts for this item. virtual bool invalidateItemCache(const PimItem &item); /* --- Collection ------------------------------------------------------ */ virtual bool appendCollection(Collection &collection); /// removes the given collection and all its content virtual bool cleanupCollection(Collection &collection); /// same as the above but for database backends without working referential actions on foreign keys virtual bool cleanupCollection_slow(Collection &collection); /// moves the collection @p collection to @p newParent. virtual bool moveCollection(Collection &collection, const Collection &newParent); virtual bool appendMimeTypeForCollection(qint64 collectionId, const QStringList &mimeTypes); static QString collectionDelimiter() { return QStringLiteral("/"); } /** Determines the active cache policy for this Collection. The active cache policy is set in the corresponding Collection fields. */ virtual void activeCachePolicy(Collection &col); /// Returns all virtual collections the @p item is linked to QVector virtualCollections(const PimItem &item); QMap< Server::Entity::Id, QList< PimItem > > virtualCollections(const Akonadi::Server::PimItem::List &items); /* --- MimeType ------------------------------------------------------ */ virtual bool appendMimeType(const QString &mimetype, qint64 *insertId = 0); /* --- PimItem ------------------------------------------------------- */ virtual bool appendPimItem(QVector &parts, const MimeType &mimetype, const Collection &collection, const QDateTime &dateTime, const QString &remote_id, const QString &remoteRevision, const QString &gid, PimItem &pimItem); /** * Removes the pim item and all referenced data ( e.g. flags ) */ virtual bool cleanupPimItems(const PimItem::List &items); /** * Unhides the specified PimItem. Emits the itemAdded() notification as * the hidden flag is assumed to have been set by appendPimItem() before * pushing the item to the preprocessor chain. The hidden item had his * notifications disabled until now (so for the clients the "unhide" operation * is actually a new item arrival). * * This function does NOT verify if the item was *really* hidden: this is * responsibility of the caller. */ virtual bool unhidePimItem(PimItem &pimItem); /** * Unhides all the items which have the "hidden" flag set. * This function doesn't emit any notification about the items * being unhidden so it's meant to be called only in rare circumstances. * The most notable call to this function is at server startup * when we attempt to restore a clean state of the database. */ virtual bool unhideAllPimItems(); /* --- Collection attributes ------------------------------------------ */ virtual bool addCollectionAttribute(const Collection &col, const QByteArray &key, const QByteArray &value); /** * Removes the given collection attribute for @p col. * @throws HandlerException on database errors * @returns @c true if the attribute existed, @c false otherwise */ virtual bool removeCollectionAttribute(const Collection &col, const QByteArray &key); /* --- Helper functions ---------------------------------------------- */ /** Begins a transaction. No changes will be written to the database and no notification signal will be emitted unless you call commitTransaction(). @return @c true if successful. */ virtual bool beginTransaction(); /** Reverts all changes within the current transaction. */ virtual bool rollbackTransaction(); /** Commits all changes within the current transaction and emits all collected notfication signals. If committing fails, the transaction will be rolled back. */ virtual bool commitTransaction(); /** Returns true if there is a transaction in progress. */ virtual bool inTransaction() const; /** Returns the notification collector of this DataStore object. Use this to listen to change notification signals. */ virtual NotificationCollector *notificationCollector(); /** Returns the QSqlDatabase object. Use this for generating queries yourself. */ QSqlDatabase database() const { return m_database; } /** Sets the current session id. */ void setSessionId(const QByteArray &sessionId) { mSessionId = sessionId; } Q_SIGNALS: /** Emitted if a transaction has been successfully committed. */ void transactionCommitted(); /** Emitted if a transaction has been aborted. */ void transactionRolledBack(); protected: /** Creates a new DataStore object and opens it. */ DataStore(); void debugLastDbError(const char *actionDescription) const; void debugLastQueryError(const QSqlQuery &query, const char *actionDescription) const; private: bool doAppendItemsFlag(const PimItem::List &items, const Flag &flag, const QSet &existing, const Collection &col, bool silent); bool doAppendItemsTag(const PimItem::List &items, const Tag &tag, const QSet &existing, const Collection &col, bool silent); /** Converts the given date/time to the database format, i.e. "YYYY-MM-DD HH:MM:SS". @param dateTime the date/time in UTC @return the date/time in database format @see dateTimeToQDateTime */ static QString dateTimeFromQDateTime(const QDateTime &dateTime); /** Converts the given date/time from database format to QDateTime. @param dateTime the date/time in database format @return the date/time as QDateTime @see dateTimeFromQDateTime */ static QDateTime dateTimeToQDateTime(const QByteArray &dateTime); /** * Adds the @p query to current transaction, so that it can be replayed in * case the transaction deadlocks or timeouts. * * When DataStore is not in transaction or SQLite is configured, this method * does nothing. * * All queries will automatically be removed when transaction is committed. * * This method should only be used by QueryBuilder. */ void addQueryToTransaction(const QSqlQuery &query, bool isBatch); /** * Tries to execute all queries from last transaction again. If any of the * queries fails, the entire transaction is rolled back and fails. * * This method can only be used by QueryBuilder when database rolls back * transaction due to deadlock or timeout. * * @return Returns an invalid query when error occurs, or the last replayed * query on success. */ QSqlQuery retryLastTransaction(bool rollbackFirst); private Q_SLOTS: void sendKeepAliveQuery(); protected: static QThreadStorage sInstances; QString m_connectionName; QSqlDatabase m_database; bool m_dbOpened; uint m_transactionLevel; QVector > m_transactionQueries; QByteArray mSessionId; NotificationCollector *mNotificationCollector; QTimer *m_keepAliveTimer; static bool s_hasForeignKeyConstraints; // Gives QueryBuilder access to addQueryToTransaction() and retryLastTransaction() friend class QueryBuilder; }; } // namespace Server } // namespace Akonadi #endif diff --git a/src/server/storage/dbintrospector.h b/src/server/storage/dbintrospector.h index d3f08543f..97c00b10c 100644 --- a/src/server/storage/dbintrospector.h +++ b/src/server/storage/dbintrospector.h @@ -1,124 +1,124 @@ /* Copyright (C) 2006 by Tobias Koenig Copyright (c) 2012 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef DBINTROSPECTOR_H #define DBINTROSPECTOR_H #include #include #include #include class DbIntrospectorTest; namespace Akonadi { namespace Server { /** * Methods for introspecting the current state of a database schema. * I.e. this is about the structure of a database, not its content. */ class DbIntrospector { public: typedef QSharedPointer Ptr; /** A structure describing an existing foreign key. */ class ForeignKey { public: QString name; QString column; QString refTable; QString refColumn; QString onUpdate; // TODO use same enum as DbInitializer QString onDelete; // dito }; /** * Returns an introspector instance for a given database. */ static DbIntrospector::Ptr createInstance(const QSqlDatabase &database); virtual ~DbIntrospector(); /** * Returns @c true if table @p tableName exists. * The default implementation relies on QSqlDatabase::tables(). Usually this * does not need to be reimplemented. */ virtual bool hasTable(const QString &tableName); /** * Returns @c true of the given table has an index with the given name. * The default implementation performs the query returned by hasIndexQuery(). * @see hasIndexQuery() * @throws DbException on database errors. */ virtual bool hasIndex(const QString &tableName, const QString &indexName); /** * Check whether table @p tableName has a column named @p columnName. - * The default implemention should work with all backends. + * The default implementation should work with all backends. */ virtual bool hasColumn(const QString &tableName, const QString &columnName); /** * Check whether table @p tableName is empty, ie. does not contain any rows. * The default implementation should work for all backends. * @throws DbException on database errors. */ virtual bool isTableEmpty(const QString &tableName); /** * Returns the foreign key constraints on table @p tableName. * The default implementation returns an empty list, so any backend supporting - * referential integrity should reimplment this. + * referential integrity should reimplement this. */ virtual QVector foreignKeyConstraints(const QString &tableName); protected: /** * Creates a new database introspector, call from subclass. * * @param database The database to introspect. */ DbIntrospector(const QSqlDatabase &database); /** * Returns a query string to determine if @p tableName has an index @p indexName. * The query is expected to have one boolean result row/column. * This is used by the default implementation of hasIndex() only, thus reimplmentation * is not necessary if you reimplement hasIndex() * The default implementation asserts. */ virtual QString hasIndexQuery(const QString &tableName, const QString &indexName); /** The database connection we are introspecting. */ QSqlDatabase m_database; private: friend class ::DbIntrospectorTest; QHash m_columnCache; // avoids extra db roundtrips }; } // namespace Server } // namespace Akonadi #endif // DBINTROSPECTOR_H diff --git a/src/server/storage/dbtype.h b/src/server/storage/dbtype.h index 0927640e5..573a51909 100644 --- a/src/server/storage/dbtype.h +++ b/src/server/storage/dbtype.h @@ -1,52 +1,52 @@ /* Copyright (c) 2012 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef DBTYPE_H #define DBTYPE_H #include namespace Akonadi { namespace Server { /** Helper methods for checking the database system we are dealing with. */ namespace DbType { /** Supported database types. */ enum Type { Unknown, Sqlite, MySQL, PostgreSQL }; -/** Returns the type of the given databse object. */ +/** Returns the type of the given database object. */ Type type(const QSqlDatabase &db); /** Returns the type for the given driver name. */ Type typeForDriverName(const QString &driverName); /** Returns true when using QSQLITE driver shipped with Qt, FALSE otherwise */ bool isSystemSQLite(const QSqlDatabase &db); } // namespace DbType } // namespace Server } // namespace Akonadi #endif // DBTYPE_H diff --git a/src/server/storage/notificationcollector.h b/src/server/storage/notificationcollector.h index 551becfbd..3f139015f 100644 --- a/src/server/storage/notificationcollector.h +++ b/src/server/storage/notificationcollector.h @@ -1,268 +1,268 @@ /* Copyright (c) 2006 - 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef AKONADI_NOTIFICATIONCOLLECTOR_H #define AKONADI_NOTIFICATIONCOLLECTOR_H #include "entities.h" #include #include #include #include #include namespace Akonadi { namespace Server { class DataStore; /** Part of the DataStore, collects change notifications and emits them after the current transaction has been successfully committed. Where possible, notifications are compressed. */ class NotificationCollector : public QObject { Q_OBJECT public: /** Create a new notification collector that is not attached to a DataStore and just collects notifications until you emit them manually. */ NotificationCollector(QObject *parent = 0); /** Create a new notification collector for the given DataStore @p db. @param db The datastore using this notification collector. */ NotificationCollector(DataStore *db); /** Destroys this notification collector. */ ~NotificationCollector(); /** Sets the identifier of the session causing the changes. */ void setSessionId(const QByteArray &sessionId); /** Notify about an added item. Provide as many parameters as you have at hand currently, everything that is missing will be looked up in the database later. */ void itemAdded(const PimItem &item, const Collection &collection = Collection(), const QByteArray &resource = QByteArray()); /** Notify about a changed item. Provide as many parameters as you have at hand currently, everything that is missing will be looked up in the database later. */ void itemChanged(const PimItem &item, const QSet &changedParts, const Collection &collection = Collection(), const QByteArray &resource = QByteArray()); /** Notify about changed items flags Provide as many parameters as you have at hand currently, everything that is missing will be looked up in the database later. */ void itemsFlagsChanged(const PimItem::List &items, const QSet &addedFlags, const QSet &removedFlags, const Collection &collection = Collection(), const QByteArray &resource = QByteArray()); /** Notify about changed items tags **/ void itemsTagsChanged(const PimItem::List &items, const QSet &addedTags, const QSet &removedTags, const Collection &collection = Collection(), const QByteArray &resource = QByteArray()); /** Notify about changed items relations **/ void itemsRelationsChanged(const PimItem::List &items, const Relation::List &addedRelations, const Relation::List &removedRelations, const Collection &collection = Collection(), const QByteArray &resource = QByteArray()); /** Notify about moved items Provide as many parameters as you have at hand currently, everything that is missing will be looked up in the database later. */ void itemsMoved(const PimItem::List &items, const Collection &collectionSrc = Collection(), const Collection &collectionDest = Collection(), const QByteArray &sourceResource = QByteArray()); /** Notify about removed items. Make sure you either provide all parameters or call this function before actually removing the item from database. */ void itemsRemoved(const PimItem::List &items, const Collection &collection = Collection(), const QByteArray &resource = QByteArray()); /** * Notify about linked items */ void itemsLinked(const PimItem::List &items, const Collection &collection); /** * Notify about unlinked items. */ void itemsUnlinked(const PimItem::List &items, const Collection &collection); /** Notify about a added collection. Provide as many parameters as you have at hand currently, everything that is missing will be looked up in the database later. */ void collectionAdded(const Collection &collection, const QByteArray &resource = QByteArray()); /** Notify about a changed collection. Provide as many parameters as you have at hand currently, everything that is missing will be looked up in the database later. */ void collectionChanged(const Collection &collection, const QList &changes, const QByteArray &resource = QByteArray()); /** Notify about a moved collection. Provide as many parameters as you have at hand currently, everything - missing will be lookeded up on demand in the database later. + missing will be looked up on demand in the database later. */ void collectionMoved(const Collection &collection, const Collection &source, const QByteArray &resource = QByteArray(), const QByteArray &destResource = QByteArray()); /** Notify about a removed collection. Make sure you either provide all parameters or call this function before actually removing the item from database. */ void collectionRemoved(const Collection &collection, const QByteArray &resource = QByteArray()); /** * Notify about a collection subscription. */ void collectionSubscribed(const Collection &collection, const QByteArray &resource = QByteArray()); /** * Notify about a collection unsubscription */ void collectionUnsubscribed(const Collection &collection, const QByteArray &resource = QByteArray()); /** Notify about an added tag. */ void tagAdded(const Tag &tag); /** Notify about a changed tag. */ void tagChanged(const Tag &tag); /** Notify about a removed tag. */ void tagRemoved(const Tag &tag, const QByteArray &resource, const QString &remoteId); /** Notify about an added relation. */ void relationAdded(const Relation &relation); /** Notify about a removed relation. */ void relationRemoved(const Relation &relation); /** Trigger sending of collected notifications. */ void dispatchNotifications(); Q_SIGNALS: void notify(const Akonadi::Protocol::ChangeNotification::List &msgs); private: void itemNotification(Protocol::ChangeNotification::Operation op, const PimItem::List &items, const Collection &collection, const Collection &collectionDest, const QByteArray &resource, const QSet &parts = QSet(), const QSet &addedFlags = QSet(), const QSet &removedFlags = QSet(), const QSet &addedTags = QSet(), const QSet &removedTags = QSet(), const Relation::List &addedRelations = Relation::List(), const Relation::List &removedRelations = Relation::List() ); void itemNotification(Protocol::ChangeNotification::Operation op, const PimItem &item, const Collection &collection, const Collection &collectionDest, const QByteArray &resource, const QSet &parts = QSet()); void collectionNotification(Protocol::ChangeNotification::Operation op, const Collection &collection, Collection::Id source, Collection::Id destination, const QByteArray &resource, const QSet &changes = QSet(), const QByteArray &destResource = QByteArray()); void tagNotification(Protocol::ChangeNotification::Operation op, const Tag &tag, const QByteArray &resource = QByteArray(), const QString &remoteId = QString()); void relationNotification(Protocol::ChangeNotification::Operation op, const Relation &relation); void dispatchNotification(const Protocol::ChangeNotification &msg); void clear(); private Q_SLOTS: void transactionCommitted(); void transactionRolledBack(); private: DataStore *mDb; QByteArray mSessionId; Protocol::ChangeNotification::List mNotifications; }; } // namespace Server } // namespace Akonadi #endif diff --git a/src/server/storage/parthelper.h b/src/server/storage/parthelper.h index 14fceed2a..9d217669a 100644 --- a/src/server/storage/parthelper.h +++ b/src/server/storage/parthelper.h @@ -1,83 +1,83 @@ /*************************************************************************** * Copyright (C) 2009 by Andras Mantia * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef PARTHELPER_H #define PARTHELPER_H #include #include "entities.h" #include "../exception.h" class QString; class QVariant; class QFile; namespace Akonadi { namespace Server { AKONADI_EXCEPTION_MAKE_INSTANCE(PartHelperException); /** * Helper methods that store data in a file instead of the database. * * @author Andras Mantia * * @todo Use exceptions for error handling in all these methods. Requires that all callers * can handle that first though. */ namespace PartHelper { /** * Update payload of an existing part @p part to @p data and size @p dataSize. - * Automatically decides whether or not the data should be stored in the databse + * Automatically decides whether or not the data should be stored in the database * or the file system. * @throw PartHelperException if file operations failed */ void update(Part *part, const QByteArray &data, qint64 dataSize); /** * Adds a new part to the database and if necessary to the filesystem. * @p part must not be in the database yet (ie. valid() == false) and must have * a data size set. */ bool insert(Part *part, qint64 *insertId = 0); /** Deletes @p part from the database and also removes existing filesystem data if needed. */ bool remove(Part *part); /** Deletes all parts which match the given constraint, including all corresponding filesystem data. */ bool remove(const QString &column, const QVariant &value); /** Returns the payload data. */ QByteArray translateData(const QByteArray &data, bool isExternal); /** Convenience overload of the above. */ QByteArray translateData(const Part &part); /** Truncate the payload of @p part and update filesystem/database accordingly. * This is more efficient than using update since it does not require the data to be loaded. */ bool truncate(Part &part); /** Verifies and if necessary fixes the external reference of this part. */ bool verify(Part &part); } // namespace PartHelper } // namespace Server } // namespace Akonadi #endif diff --git a/src/server/storage/parttypehelper.h b/src/server/storage/parttypehelper.h index f3e1cde65..18ae041a4 100644 --- a/src/server/storage/parttypehelper.h +++ b/src/server/storage/parttypehelper.h @@ -1,103 +1,103 @@ /* Copyright (c) 2011 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef PARTTYPEHELPER_H #define PARTTYPEHELPER_H #include "exception.h" #include "query.h" namespace Akonadi { namespace Server { class PartType; AKONADI_EXCEPTION_MAKE_INSTANCE(PartTypeException); /** * Methods for dealing with the PartType table. */ namespace PartTypeHelper { /** * Retrieve (or create) PartType for the given fully qualified name. * @param fqName Fully qualified name (NS:NAME). * @throws PartTypeException */ PartType fromFqName(const QString &fqName); /** * Convenience overload of the above. */ PartType fromFqName(const QByteArray &fqName); /** * Retrieve (or create) PartType for the given namespace and type name. * @param ns Namespace * @param typeName Part type name. * @throws PartTypeException */ PartType fromFqName(const QString &ns, const QString &typeName); /** * Returns a query condition that matches the given part. * @param fqName fully-qualified part type name * @throws PartTypeException */ Query::Condition conditionFromFqName(const QString &fqName); /** - * Returns a query condition that mathes the given part type list. + * Returns a query condition that matches the given part type list. * @param fqNames fully qualified part type name list * @throws PartTypeException */ Query::Condition conditionFromFqNames(const QStringList &fqNames); /** * Convenience overload for the above. */ template class T> Query::Condition conditionFromFqNames(const T &fqNames) { Query::Condition c; c.setSubQueryMode(Query::Or); Q_FOREACH (const QByteArray &fqName, fqNames) { c.addCondition(conditionFromFqName(QLatin1String(fqName))); } return c; } /** * Parses a fully qualified part type name into namespace/name. * @param fqName fully-qualified part type name * @throws PartTypeException if @p fqName does not match the NS:NAME schema * @internal */ QPair parseFqName(const QString &fqName); /** * Returns full part name */ QString fullName(const PartType &type); } // namespace PartTypeHelper } // namespace Server } // namespace Akonadi #endif diff --git a/src/server/storage/transaction.h b/src/server/storage/transaction.h index 68267f7b0..27eb79f4c 100644 --- a/src/server/storage/transaction.h +++ b/src/server/storage/transaction.h @@ -1,73 +1,73 @@ /* Copyright (c) 2006 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef AKONADI_TRANSACTION_H #define AKONADI_TRANSACTION_H #include namespace Akonadi { namespace Server { class DataStore; /** Helper class for DataStore transaction handling. Works similar to QMutexLocker. Supports command-local and session-global transactions. */ class Transaction { public: /** Starts a new transaction. The transaction will automatically rolled back on destruction if it hasn't been committed explicitly before. If there is already a global transaction in progress, this one will be used instead of creating a new one. @param db The corresponding DataStore. You must not delete @p db during the lifetime of a Transaction object. - @param beginTransaction if false, the transaction won't be started, until begin is eplicitely called. The default is to begin the transaction right away. + @param beginTransaction if false, the transaction won't be started, until begin is explicitly called. The default is to begin the transaction right away. */ explicit Transaction(DataStore *db, bool beginTransaction = true); /** Rolls back the transaction if it hasn't been committed explicitly. This also happens if a global transaction is used. */ ~Transaction(); /** Commits the transaction. Returns true on success. If a global transaction is used, nothing happens, global transactions have to be committed explicitly. */ bool commit(); void begin(); private: Q_DISABLE_COPY(Transaction) DataStore *mDb; bool mCommitted; }; } // namespace Server } // namespace Akonadi #endif