From a2520bae3677be9df0abcef7681a138a6c4ad849 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 14 Jun 2020 17:23:54 +0200 Subject: quotient_common.h for common namespace things The two main cases for this header file are: * namespace QMatrixClient = Quotient should occur exactly once, to respect ODR. * Q_NAMESPACE for namespace Quotient (to enable Q_ENUM_NS, particularly) must be defined exactly once, for the same reason. --- lib/quotient_common.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 lib/quotient_common.h (limited to 'lib/quotient_common.h') diff --git a/lib/quotient_common.h b/lib/quotient_common.h new file mode 100644 index 00000000..44541b42 --- /dev/null +++ b/lib/quotient_common.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +namespace Quotient { +Q_NAMESPACE + +/** Enumeration with flags defining the network job running policy + * So far only background/foreground flags are available. + * + * \sa Connection::callApi, Connection::run + */ +enum RunningPolicy { ForegroundRequest = 0x0, BackgroundRequest = 0x1 }; + +Q_ENUM_NS(RunningPolicy) + +enum ResourceResolveResult : short { + StillResolving = -1, + Resolved = 0, + UnknownMatrixId, + MalformedMatrixId, + NoAccount, + EmptyMatrixId +}; +Q_ENUM_NS(ResourceResolveResult) + +} // namespace Quotient +/// \deprecated Use namespace Quotient instead +namespace QMatrixClient = Quotient; -- cgit v1.2.3 From 4dd51859c9ada4660e2a9cd16c3d0a99ad13761f Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 17 Jun 2020 22:13:53 +0200 Subject: class MatrixUri; support action=join and via= --- lib/quotient_common.h | 8 +- lib/resourceresolver.cpp | 275 +++++++++++++++++++++++++++++++++++------------ lib/resourceresolver.h | 172 +++++++++++++++++++---------- tests/quotest.cpp | 65 +++++++---- 4 files changed, 372 insertions(+), 148 deletions(-) (limited to 'lib/quotient_common.h') diff --git a/lib/quotient_common.h b/lib/quotient_common.h index 44541b42..446f628b 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -14,15 +14,15 @@ enum RunningPolicy { ForegroundRequest = 0x0, BackgroundRequest = 0x1 }; Q_ENUM_NS(RunningPolicy) -enum ResourceResolveResult : short { +enum UriResolveResult : short { StillResolving = -1, - Resolved = 0, + UriResolved = 0, UnknownMatrixId, - MalformedMatrixId, + MalformedUri, NoAccount, EmptyMatrixId }; -Q_ENUM_NS(ResourceResolveResult) +Q_ENUM_NS(UriResolveResult) } // namespace Quotient /// \deprecated Use namespace Quotient instead diff --git a/lib/resourceresolver.cpp b/lib/resourceresolver.cpp index 0d5c5a20..e7820061 100644 --- a/lib/resourceresolver.cpp +++ b/lib/resourceresolver.cpp @@ -1,97 +1,236 @@ #include "resourceresolver.h" -#include "settings.h" +#include "connection.h" +#include "logging.h" #include using namespace Quotient; -QString ResourceResolver::toMatrixId(const QString& uriOrId, - QStringList uriServers) +struct ReplacePair { QByteArray uriString; char sigil; }; +static const auto replacePairs = { ReplacePair { "user/", '@' }, + { "roomid/", '!' }, + { "room/", '#' } }; + +MatrixUri::MatrixUri(QByteArray primaryId, QByteArray secondaryId, QString query) { - auto id = QUrl::fromPercentEncoding(uriOrId.toUtf8()); - const auto MatrixScheme = "matrix:"_ls; - if (id.startsWith(MatrixScheme)) { - id.remove(0, MatrixScheme.size()); - for (const auto& p: { std::pair { "user/"_ls, '@' }, - { "roomid/"_ls, '!' }, - { "room/"_ls, '#' } }) - if (id.startsWith(p.first)) { - id.replace(0, p.first.size(), p.second); + if (primaryId.isEmpty()) + primaryType_ = Empty; + else { + setScheme("matrix"); + QString pathToBe; + primaryType_ = Invalid; + for (const auto& p: replacePairs) + if (primaryId[0] == p.sigil) { + primaryType_ = Type(p.sigil); + pathToBe = p.uriString + primaryId.mid(1); break; } - // The below assumes that /event/ cannot show up in normal Matrix ids. - id.replace("/event/"_ls, "/$"_ls); - } else { - const auto MatrixTo_ServerName = QStringLiteral("matrix.to"); - if (!uriServers.contains(MatrixTo_ServerName)) - uriServers.push_back(MatrixTo_ServerName); - id.remove( - QRegularExpression("^https://(" + uriServers.join('|') + ")/?#/")); + if (!secondaryId.isEmpty()) + pathToBe += "/event/" + secondaryId.mid(1); + setPath(pathToBe); } - return id; + setQuery(std::move(query)); } -ResourceResolver::Result ResourceResolver::visitResource( - Connection* account, const QString& identifier, - std::function userHandler, - std::function roomEventHandler) +MatrixUri::MatrixUri(QUrl url) : QUrl(std::move(url)) { - const auto& normalizedId = toMatrixId(identifier); - auto&& [sigil, mainId, secondaryId] = parseIdentifier(normalizedId); - Room* room = nullptr; - switch (sigil) { - case char(-1): - return MalformedMatrixId; - case char(0): - return EmptyMatrixId; - case '@': - if (auto* user = account->user(mainId)) { - userHandler(user); - return Success; - } - return MalformedMatrixId; - case '!': - if ((room = account->room(mainId))) - break; - return UnknownMatrixId; - case '#': - if ((room = account->roomByAlias(mainId))) + // NB: url is moved from and empty by now + if (isEmpty()) + return; // primaryType_ == None + + primaryType_ = Invalid; + if (!QUrl::isValid()) // MatrixUri::isValid() checks primaryType_ + return; + + if (scheme() == "matrix") { + // Check sanity as per https://github.com/matrix-org/matrix-doc/pull/2312 + const auto& urlPath = path(); + const auto& splitPath = urlPath.splitRef('/'); + switch (splitPath.size()) { + case 2: + break; + case 4: + if (splitPath[2] == "event") break; [[fallthrough]]; default: - return UnknownMatrixId; + return; // Invalid + } + + for (const auto& p: replacePairs) + if (urlPath.startsWith(p.uriString)) { + primaryType_ = Type(p.sigil); + return; // The only valid return path for matrix: URIs + } + qCWarning(MAIN) << "Invalid matrix: URI passed to MatrixUri"; + } + if (scheme() == "https" && authority() == "matrix.to") { + // See https://matrix.org/docs/spec/appendices#matrix-to-navigation + static const QRegularExpression MatrixToUrlRE { + R"(^/(?
[^/?]+)(/(?[^?]+))?(\?(?.+))?$)" + }; + // matrix.to accepts both literal sigils (as well as & and ? used in + // its "query" substitute) and their %-encoded forms; + // so force QUrl to decode everything. + auto f = fragment(QUrl::FullyDecoded); + if (auto&& m = MatrixToUrlRE.match(f); m.hasMatch()) + *this = MatrixUri { m.captured("main").toUtf8(), + m.captured("sec").toUtf8(), + m.captured("query") }; } - roomEventHandler(room, secondaryId); - return Success; } -ResourceResolver::IdentifierParts -ResourceResolver::parseIdentifier(const QString& identifier) +MatrixUri::MatrixUri(const QString &uriOrId) + : MatrixUri(fromUserInput(uriOrId)) +{ } + +MatrixUri MatrixUri::fromUserInput(const QString& uriOrId) { - if (identifier.isEmpty()) + if (uriOrId.isEmpty()) + return {}; // type() == None + + // A quick check if uriOrId is a plain Matrix id + if (QStringLiteral("!@#+").contains(uriOrId[0])) + return MatrixUri { uriOrId.toUtf8() }; + + // Bare event ids cannot be resolved without a room scope but are treated as + // valid anyway; in the future we might expose them as, say, + // matrix:event/eventid + if (uriOrId[0] == '$') + return MatrixUri { "", uriOrId.toUtf8() }; + + return MatrixUri { QUrl::fromUserInput(uriOrId) }; +} + +MatrixUri::Type MatrixUri::type() const { return primaryType_; } + +MatrixUri::SecondaryType MatrixUri::secondaryType() const +{ + return path().section('/', 2, 2) == "event" ? EventId : NoSecondaryId; +} + +QUrl MatrixUri::toUrl(UriForm form) const +{ + if (!isValid()) return {}; - - // The regex is quick and dirty, only intending to triage the id. - static const QRegularExpression IdRE { - "^(?
(?.)([^/]+))(/(?[^?]+))?" - }; - auto dissectedId = IdRE.match(identifier); - if (!dissectedId.hasMatch()) - return { char(-1) }; - - const auto sigil = dissectedId.captured("sigil"); - return { sigil.size() != 1 ? char(-1) : sigil[0].toLatin1(), - dissectedId.captured("main"), dissectedId.captured("sec") }; + + if (form == CanonicalUri) + return *this; + + QUrl url; + url.setScheme("https"); + url.setHost("matrix.to"); + url.setPath("/"); + auto fragment = primaryId(); + if (const auto& secId = secondaryId(); !secId.isEmpty()) + fragment += '/' + secId; + if (const auto& q = query(); !q.isEmpty()) + fragment += '?' + q; + url.setFragment(fragment); + return url; +} + +QString MatrixUri::toDisplayString(MatrixUri::UriForm form) const +{ + return toUrl(form).toDisplayString(); } -ResourceResolver::Result +QString MatrixUri::primaryId() const +{ + if (primaryType_ == Empty || primaryType_ == Invalid) + return {}; + + const auto& idStem = path().section('/', 1, 1); + return idStem.isEmpty() ? idStem : primaryType_ + idStem; +} + +QString MatrixUri::secondaryId() const +{ + const auto& idStem = path().section('/', 3); + return idStem.isEmpty() ? idStem : secondaryType() + idStem; +} + +QString MatrixUri::action() const +{ + return QUrlQuery { query() }.queryItemValue("action"); +} + +QStringList MatrixUri::viaServers() const +{ + return QUrlQuery { query() }.allQueryItemValues(QStringLiteral("via"), + QUrl::EncodeReserved); +} + +bool MatrixUri::isValid() const +{ + return primaryType_ != Empty && primaryType_ != Invalid; +} + +UriResolveResult Quotient::visitResource( + Connection* account, const MatrixUri& uri, + std::function userHandler, + std::function roomEventHandler, + std::function joinHandler) +{ + Q_ASSERT_X(account != nullptr, __FUNCTION__, + "The Connection argument passed to visit/openResource must not " + "be nullptr"); + if (uri.action() == "join") { + if (uri.type() != MatrixUri::RoomAlias + && uri.type() != MatrixUri::RoomId) + return MalformedUri; + + joinHandler(account, uri.primaryId(), uri.viaServers()); + return UriResolved; + } + + Room* room = nullptr; + switch (uri.type()) { + case MatrixUri::Invalid: + return MalformedUri; + case MatrixUri::Empty: + return EmptyMatrixId; + case MatrixUri::UserId: + if (auto* user = account->user(uri.primaryId())) { + userHandler(user); + return UriResolved; + } + return MalformedUri; + case MatrixUri::RoomId: + if ((room = account->room(uri.primaryId()))) + break; + return UnknownMatrixId; + case MatrixUri::RoomAlias: + if ((room = account->roomByAlias(uri.primaryId()))) + break; + [[fallthrough]]; + default: + return UnknownMatrixId; + } + roomEventHandler(room, uri.secondaryId()); + return UriResolved; +} + +UriResolveResult ResourceResolver::openResource(Connection* account, const QString& identifier, const QString& action) { - return visitResource(account, identifier, - [this, &action](User* u) { emit userAction(u, action); }, - [this, &action](Room* room, const QString& eventId) { - emit roomAction(room, eventId, action); + return openResource(account, MatrixUri(identifier), action); +} + +UriResolveResult ResourceResolver::openResource(Connection* account, + const MatrixUri& uri, + const QString& overrideAction) +{ + return visitResource( + account, uri, + [this, &overrideAction](User* u) { emit userAction(u, overrideAction); }, + [this, &overrideAction](Room* room, const QString& eventId) { + emit roomAction(room, eventId, overrideAction); + }, + [this](Connection* account, const QString& roomAliasOrId, + const QStringList& viaServers) { + emit joinAction(account, roomAliasOrId, viaServers); }); } diff --git a/lib/resourceresolver.h b/lib/resourceresolver.h index 794b7796..fea07e97 100644 --- a/lib/resourceresolver.h +++ b/lib/resourceresolver.h @@ -1,10 +1,118 @@ #pragma once -#include "connection.h" +#include "quotient_common.h" + +#include +#include +#include #include namespace Quotient { +class Connection; +class Room; +class User; + +/*! \brief A wrapper around a Matrix URI or identifier + * + * This class encapsulates a Matrix resource identifier, passed in either of + * 3 forms: a plain Matrix identifier (sigil, localpart, serverpart or, for + * modern event ids, sigil and base64 hash); an MSC2312 URI (aka matrix: URI); + * or a matrix.to URL. The input can be either encoded (serverparts with + * punycode, the rest with percent-encoding) or unencoded (in this case it is + * the caller's responsibility to resolve all possible ambiguities). + * + * The class provides functions to check the validity of the identifier, + * its type, and obtain components, also in either unencoded (for displaying) + * or encoded (for APIs) form. + */ +class MatrixUri : private QUrl { + Q_GADGET + Q_PROPERTY(QString primaryId READ primaryId CONSTANT) + Q_PROPERTY(QString secondaryId READ secondaryId CONSTANT) +// Q_PROPERTY(QUrlQuery query READ query CONSTANT) + Q_PROPERTY(QString action READ action CONSTANT) +// Q_PROPERTY(QStringList viaServers READ viaServers CONSTANT) +public: + enum Type : char { + Invalid = char(-1), + Empty = 0x0, + UserId = '@', + RoomId = '!', + RoomAlias = '#', + Group = '+' + }; + Q_ENUM(Type) + enum SecondaryType : char { + NoSecondaryId = 0x0, + EventId = '$' + }; + + enum UriForm : short { CanonicalUri, MatrixToUri }; + Q_ENUM(UriForm) + + /// Construct an empty Matrix URI + MatrixUri() = default; + /*! \brief Decode a user input string to a Matrix identifier + * + * Accepts plain Matrix ids, MSC2312 URIs (aka matrix: URIs) and + * matrix.to URLs. In case of URIs/URLs, it uses QUrl's TolerantMode + * parser to decode common mistakes/irregularities (see QUrl documentation + * for more details). + */ + MatrixUri(const QString& uriOrId); + + /// Construct a Matrix URI from components + explicit MatrixUri(QByteArray primaryId, QByteArray secondaryId = {}, + QString query = {}); + /// Construct a Matrix URI from matrix.to or MSC2312 (matrix:) URI + explicit MatrixUri(QUrl url); + + static MatrixUri fromUserInput(const QString& uriOrId); + static MatrixUri fromUrl(QUrl url); + + /// Get the primary type of the Matrix URI (user id, room id or alias) + /*! Note that this does not include an event as a separate type, since + * events can only be addressed inside of rooms, which, in turn, are + * addressed either by id or alias. If you need to check whether the URI + * is specifically an event URI, use secondaryType() instead. + */ + Type type() const; + SecondaryType secondaryType() const; + QUrl toUrl(UriForm form = CanonicalUri) const; + QString toDisplayString(UriForm form = CanonicalUri) const; + QString primaryId() const; + QString secondaryId() const; + QString action() const; + QStringList viaServers() const; + bool isValid() const; + using QUrl::isEmpty, QUrl::path, QUrl::query, QUrl::fragment; + +private: + + Type primaryType_ = Empty; +}; + +/*! \brief Resolve the resource and invoke an action on it, visitor style + * + * This template function encapsulates the logic of resolving a Matrix + * identifier or URI into a Quotient object (or objects) and applying an + * appropriate action handler from the set provided by the caller to it. + * A typical use case for that is opening a room or mentioning a user in + * response to clicking on a Matrix URI or identifier. + * + * \param account The connection used as a context to resolve the identifier + * + * \param uri The Matrix identifier or URI; MSC2312 URIs and classic Matrix IDs + * are supported + * + * \sa ResourceResolver + */ +UriResolveResult +visitResource(Connection* account, const MatrixUri& uri, + std::function userHandler, + std::function roomEventHandler, + std::function joinHandler); /*! \brief Matrix resource resolver * TODO: rewrite @@ -22,51 +130,9 @@ namespace Quotient { class ResourceResolver : public QObject { Q_OBJECT public: - enum Result : short { - StillResolving = -1, - Success = 0, - UnknownMatrixId, - MalformedMatrixId, - NoAccount, - EmptyMatrixId - }; - Q_ENUM(Result) - explicit ResourceResolver(QObject* parent = nullptr) : QObject(parent) { } - /*! \brief Decode a URI to a Matrix identifier (or a room/event pair) - * - * This accepts plain Matrix ids, MSC2312 URIs (aka matrix: URIs) and - * matrix.to URIs. - * - * \return a Matrix identifier as defined by the common identifier grammars - * or a slash separated pair of Matrix identifiers if the original - * uri/id pointed to an event in a room - */ - static QString toMatrixId(const QString& uriOrId, - QStringList uriServers = {}); - - /*! \brief Resolve the resource and invoke an action on it, visitor style - * - * This template function encapsulates the logic of resolving a Matrix - * identifier or URI into a Quotient object (or objects) and applying an - * appropriate action handler from the set provided by the caller to it. - * A typical use case for that is opening a room or mentioning a user in - * response to clicking on a Matrix URI or identifier. - * - * \param account The connection used as a context to resolve the identifier - * - * \param identifier The Matrix identifier or URI. MSC2312 URIs and classic - * Matrix ID scheme are supported. - * - * \sa ResourceResolver - */ - static Result - visitResource(Connection* account, const QString& identifier, - std::function userHandler, - std::function roomEventHandler); - /*! \brief Resolve the resource and request an action on it, signal style * * This method: @@ -91,9 +157,12 @@ public: * and also connect to ResourceFuture::ready() signal in order to process * the result of resolving and action. */ - Q_INVOKABLE Result openResource(Connection* account, - const QString& identifier, - const QString& action = {}); + Q_INVOKABLE UriResolveResult openResource(Connection* account, + const QString& identifier, + const QString& action = {}); + Q_INVOKABLE UriResolveResult + openResource(Connection* account, const MatrixUri& uri, + const QString& overrideAction = {}); signals: /// An action on a user has been requested @@ -102,14 +171,9 @@ signals: /// An action on a room has been requested, with optional event id void roomAction(Quotient::Room* room, QString eventId, QString action); -private: - struct IdentifierParts { - char sigil; - QString mainId {}; - QString secondaryId = {}; - }; - - static IdentifierParts parseIdentifier(const QString& identifier); + /// A join action has been requested, with optional 'via' servers + void joinAction(Quotient::Connection* account, QString roomAliasOrId, + QStringList viaServers); }; } // namespace Quotient diff --git a/tests/quotest.cpp b/tests/quotest.cpp index 19aa5b85..f9e25284 100644 --- a/tests/quotest.cpp +++ b/tests/quotest.cpp @@ -627,13 +627,15 @@ TEST_IMPL(visitResources) // This lambda returns true in case of error, false if it's fine so far auto testResourceResolver = [this, thisTest](const QStringList& uris, auto signal, auto* target, - const QString& eventId = {}) { + QVariantList otherArgs = {}) { int r = qRegisterMetaType(); Q_ASSERT(r != 0); QSignalSpy spy(&rr, signal); - for (const auto& uri: uris) { - clog << "Resolving uri " << uri.toStdString() << endl; - rr.openResource(connection(), uri, "action"); + for (const auto& uriString: uris) { + MatrixUri uri { uriString }; + clog << "Checking " << uriString.toStdString() + << " -> " << uri.toDisplayString().toStdString() << endl; + rr.openResource(connection(), uri); if (spy.count() != 1) { clog << "Wrong number of signal emissions (" << spy.count() << ')' << endl; @@ -642,21 +644,19 @@ TEST_IMPL(visitResources) const auto& emission = spy.front(); Q_ASSERT(emission.count() >= 2); if (emission.front().value() != target) { - clog << "Action on an incorrect target called" << endl; + clog << "Signal emitted with an incorrect target" << endl; FAIL_TEST(); } - if (emission.back() != "action") { - clog << "Action wasn't passed" << endl; - FAIL_TEST(); - } - if (!eventId.isEmpty()) { - const auto passedEvtId = (emission.cend() - 2)->toString(); - if (passedEvtId != eventId) { - clog << "Event passed incorrectly (received " - << passedEvtId.toStdString() << " instead of " - << eventId.toStdString() << ')' << endl; + if (!otherArgs.empty()) { + if (emission.size() < otherArgs.size() + 1) { + clog << "Emission doesn't include all arguments" << endl; FAIL_TEST(); } + for (auto i = 0; i < otherArgs.size(); ++i) + if (otherArgs[i] != emission[i + 1]) { + clog << "Mismatch in argument #" << i + 1 << endl; + FAIL_TEST(); + } } spy.clear(); } @@ -674,13 +674,10 @@ TEST_IMPL(visitResources) Q_ASSERT(!eventId.isEmpty()); const QStringList roomUris { - roomId, - "matrix:roomid/" + roomId.mid(1), - "https://matrix.to/#/" + roomId, - roomAlias, - "matrix:room/" + roomAlias.mid(1), + roomId, "matrix:roomid/" + roomId.mid(1), + "https://matrix.to/#/%21" + roomId.mid(1), + roomAlias, "matrix:room/" + roomAlias.mid(1), "https://matrix.to/#/" + roomAlias, - "https://matrix.to#/" + roomAlias, // Just in case }; const QStringList userUris { userId, "matrix:user/" + userId.mid(1), "https://matrix.to/#/" + userId }; @@ -688,13 +685,37 @@ TEST_IMPL(visitResources) "matrix:room/" + roomAlias.mid(1) + "/event/" + eventId.mid(1), "https://matrix.to/#/" + roomId + '/' + eventId }; + // The following URIs are not supposed to be actually joined (and even + // exist, as yet) - only to be syntactically correct + static const auto& joinRoomAlias = + QStringLiteral("unjoined:example.org"); // # will be added below + QString joinQuery { "?action=join" }; + static const QStringList joinByAliasUris { + "matrix:room/" + joinRoomAlias + joinQuery, + "https://matrix.to/#/%23"/*`#`*/ + joinRoomAlias + joinQuery + }; + static const auto& joinRoomId = QStringLiteral("!anyid:example.org"); + static const QStringList viaServers { "matrix.org", "example.org" }; + static const auto viaQuery = + std::accumulate(viaServers.cbegin(), viaServers.cend(), joinQuery, + [](QString q, const QString& s) { + return q + "&via=" + s; + }); + static const QStringList joinByIdUris { + "matrix:roomid/" + joinRoomId.mid(1) + viaQuery, + "https://matrix.to/#/" + joinRoomId + viaQuery + }; // If any test breaks, the breaking call will return true, and further // execution will be cut by ||'s short-circuiting if (testResourceResolver(roomUris, &ResourceResolver::roomAction, room()) || testResourceResolver(userUris, &ResourceResolver::userAction, connection()->user()) || testResourceResolver(eventUris, &ResourceResolver::roomAction, - room(), eventId)) + room(), { eventId }) + || testResourceResolver(joinByAliasUris, &ResourceResolver::joinAction, + connection(), { '#' + joinRoomAlias }) + || testResourceResolver(joinByIdUris, &ResourceResolver::joinAction, + connection(), { joinRoomId, viaServers })) return true; // TODO: negative cases FINISH_TEST(true); -- cgit v1.2.3 From af329351289606f3cb1ef865cb0cbe61c1d1711b Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 19 Jul 2020 16:12:09 +0200 Subject: MatrixUri->Uri: Extend to non-Matrix URIs --- CMakeLists.txt | 3 +- lib/quotient_common.h | 8 +- lib/resourceresolver.cpp | 236 ----------------------------------------------- lib/resourceresolver.h | 181 ------------------------------------ lib/uri.cpp | 181 ++++++++++++++++++++++++++++++++++++ lib/uri.h | 85 +++++++++++++++++ lib/uriresolver.cpp | 110 ++++++++++++++++++++++ lib/uriresolver.h | 162 ++++++++++++++++++++++++++++++++ libquotient.pri | 6 +- tests/quotest.cpp | 24 ++--- 10 files changed, 560 insertions(+), 436 deletions(-) delete mode 100644 lib/resourceresolver.cpp delete mode 100644 lib/resourceresolver.h create mode 100644 lib/uri.cpp create mode 100644 lib/uri.h create mode 100644 lib/uriresolver.cpp create mode 100644 lib/uriresolver.h (limited to 'lib/quotient_common.h') diff --git a/CMakeLists.txt b/CMakeLists.txt index 83075196..808899ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -149,7 +149,8 @@ set(lib_SRCS lib/room.cpp lib/user.cpp lib/avatar.cpp - lib/resourceresolver.cpp + lib/uri.cpp + lib/uriresolver.cpp lib/syncdata.cpp lib/settings.cpp lib/networksettings.cpp diff --git a/lib/quotient_common.h b/lib/quotient_common.h index 446f628b..bb05af05 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -17,10 +17,10 @@ Q_ENUM_NS(RunningPolicy) enum UriResolveResult : short { StillResolving = -1, UriResolved = 0, - UnknownMatrixId, - MalformedUri, - NoAccount, - EmptyMatrixId + CouldNotResolve, + IncorrectAction, + InvalidUri, + NoAccount }; Q_ENUM_NS(UriResolveResult) diff --git a/lib/resourceresolver.cpp b/lib/resourceresolver.cpp deleted file mode 100644 index e7820061..00000000 --- a/lib/resourceresolver.cpp +++ /dev/null @@ -1,236 +0,0 @@ -#include "resourceresolver.h" - -#include "connection.h" -#include "logging.h" - -#include - -using namespace Quotient; - -struct ReplacePair { QByteArray uriString; char sigil; }; -static const auto replacePairs = { ReplacePair { "user/", '@' }, - { "roomid/", '!' }, - { "room/", '#' } }; - -MatrixUri::MatrixUri(QByteArray primaryId, QByteArray secondaryId, QString query) -{ - if (primaryId.isEmpty()) - primaryType_ = Empty; - else { - setScheme("matrix"); - QString pathToBe; - primaryType_ = Invalid; - for (const auto& p: replacePairs) - if (primaryId[0] == p.sigil) { - primaryType_ = Type(p.sigil); - pathToBe = p.uriString + primaryId.mid(1); - break; - } - if (!secondaryId.isEmpty()) - pathToBe += "/event/" + secondaryId.mid(1); - setPath(pathToBe); - } - setQuery(std::move(query)); -} - -MatrixUri::MatrixUri(QUrl url) : QUrl(std::move(url)) -{ - // NB: url is moved from and empty by now - if (isEmpty()) - return; // primaryType_ == None - - primaryType_ = Invalid; - if (!QUrl::isValid()) // MatrixUri::isValid() checks primaryType_ - return; - - if (scheme() == "matrix") { - // Check sanity as per https://github.com/matrix-org/matrix-doc/pull/2312 - const auto& urlPath = path(); - const auto& splitPath = urlPath.splitRef('/'); - switch (splitPath.size()) { - case 2: - break; - case 4: - if (splitPath[2] == "event") - break; - [[fallthrough]]; - default: - return; // Invalid - } - - for (const auto& p: replacePairs) - if (urlPath.startsWith(p.uriString)) { - primaryType_ = Type(p.sigil); - return; // The only valid return path for matrix: URIs - } - qCWarning(MAIN) << "Invalid matrix: URI passed to MatrixUri"; - } - if (scheme() == "https" && authority() == "matrix.to") { - // See https://matrix.org/docs/spec/appendices#matrix-to-navigation - static const QRegularExpression MatrixToUrlRE { - R"(^/(?
[^/?]+)(/(?[^?]+))?(\?(?.+))?$)" - }; - // matrix.to accepts both literal sigils (as well as & and ? used in - // its "query" substitute) and their %-encoded forms; - // so force QUrl to decode everything. - auto f = fragment(QUrl::FullyDecoded); - if (auto&& m = MatrixToUrlRE.match(f); m.hasMatch()) - *this = MatrixUri { m.captured("main").toUtf8(), - m.captured("sec").toUtf8(), - m.captured("query") }; - } -} - -MatrixUri::MatrixUri(const QString &uriOrId) - : MatrixUri(fromUserInput(uriOrId)) -{ } - -MatrixUri MatrixUri::fromUserInput(const QString& uriOrId) -{ - if (uriOrId.isEmpty()) - return {}; // type() == None - - // A quick check if uriOrId is a plain Matrix id - if (QStringLiteral("!@#+").contains(uriOrId[0])) - return MatrixUri { uriOrId.toUtf8() }; - - // Bare event ids cannot be resolved without a room scope but are treated as - // valid anyway; in the future we might expose them as, say, - // matrix:event/eventid - if (uriOrId[0] == '$') - return MatrixUri { "", uriOrId.toUtf8() }; - - return MatrixUri { QUrl::fromUserInput(uriOrId) }; -} - -MatrixUri::Type MatrixUri::type() const { return primaryType_; } - -MatrixUri::SecondaryType MatrixUri::secondaryType() const -{ - return path().section('/', 2, 2) == "event" ? EventId : NoSecondaryId; -} - -QUrl MatrixUri::toUrl(UriForm form) const -{ - if (!isValid()) - return {}; - - if (form == CanonicalUri) - return *this; - - QUrl url; - url.setScheme("https"); - url.setHost("matrix.to"); - url.setPath("/"); - auto fragment = primaryId(); - if (const auto& secId = secondaryId(); !secId.isEmpty()) - fragment += '/' + secId; - if (const auto& q = query(); !q.isEmpty()) - fragment += '?' + q; - url.setFragment(fragment); - return url; -} - -QString MatrixUri::toDisplayString(MatrixUri::UriForm form) const -{ - return toUrl(form).toDisplayString(); -} - -QString MatrixUri::primaryId() const -{ - if (primaryType_ == Empty || primaryType_ == Invalid) - return {}; - - const auto& idStem = path().section('/', 1, 1); - return idStem.isEmpty() ? idStem : primaryType_ + idStem; -} - -QString MatrixUri::secondaryId() const -{ - const auto& idStem = path().section('/', 3); - return idStem.isEmpty() ? idStem : secondaryType() + idStem; -} - -QString MatrixUri::action() const -{ - return QUrlQuery { query() }.queryItemValue("action"); -} - -QStringList MatrixUri::viaServers() const -{ - return QUrlQuery { query() }.allQueryItemValues(QStringLiteral("via"), - QUrl::EncodeReserved); -} - -bool MatrixUri::isValid() const -{ - return primaryType_ != Empty && primaryType_ != Invalid; -} - -UriResolveResult Quotient::visitResource( - Connection* account, const MatrixUri& uri, - std::function userHandler, - std::function roomEventHandler, - std::function joinHandler) -{ - Q_ASSERT_X(account != nullptr, __FUNCTION__, - "The Connection argument passed to visit/openResource must not " - "be nullptr"); - if (uri.action() == "join") { - if (uri.type() != MatrixUri::RoomAlias - && uri.type() != MatrixUri::RoomId) - return MalformedUri; - - joinHandler(account, uri.primaryId(), uri.viaServers()); - return UriResolved; - } - - Room* room = nullptr; - switch (uri.type()) { - case MatrixUri::Invalid: - return MalformedUri; - case MatrixUri::Empty: - return EmptyMatrixId; - case MatrixUri::UserId: - if (auto* user = account->user(uri.primaryId())) { - userHandler(user); - return UriResolved; - } - return MalformedUri; - case MatrixUri::RoomId: - if ((room = account->room(uri.primaryId()))) - break; - return UnknownMatrixId; - case MatrixUri::RoomAlias: - if ((room = account->roomByAlias(uri.primaryId()))) - break; - [[fallthrough]]; - default: - return UnknownMatrixId; - } - roomEventHandler(room, uri.secondaryId()); - return UriResolved; -} - -UriResolveResult -ResourceResolver::openResource(Connection* account, const QString& identifier, - const QString& action) -{ - return openResource(account, MatrixUri(identifier), action); -} - -UriResolveResult ResourceResolver::openResource(Connection* account, - const MatrixUri& uri, - const QString& overrideAction) -{ - return visitResource( - account, uri, - [this, &overrideAction](User* u) { emit userAction(u, overrideAction); }, - [this, &overrideAction](Room* room, const QString& eventId) { - emit roomAction(room, eventId, overrideAction); - }, - [this](Connection* account, const QString& roomAliasOrId, - const QStringList& viaServers) { - emit joinAction(account, roomAliasOrId, viaServers); - }); -} diff --git a/lib/resourceresolver.h b/lib/resourceresolver.h deleted file mode 100644 index fea07e97..00000000 --- a/lib/resourceresolver.h +++ /dev/null @@ -1,181 +0,0 @@ -#pragma once - -#include "quotient_common.h" - -#include -#include -#include - -#include - -namespace Quotient { -class Connection; -class Room; -class User; - -/*! \brief A wrapper around a Matrix URI or identifier - * - * This class encapsulates a Matrix resource identifier, passed in either of - * 3 forms: a plain Matrix identifier (sigil, localpart, serverpart or, for - * modern event ids, sigil and base64 hash); an MSC2312 URI (aka matrix: URI); - * or a matrix.to URL. The input can be either encoded (serverparts with - * punycode, the rest with percent-encoding) or unencoded (in this case it is - * the caller's responsibility to resolve all possible ambiguities). - * - * The class provides functions to check the validity of the identifier, - * its type, and obtain components, also in either unencoded (for displaying) - * or encoded (for APIs) form. - */ -class MatrixUri : private QUrl { - Q_GADGET - Q_PROPERTY(QString primaryId READ primaryId CONSTANT) - Q_PROPERTY(QString secondaryId READ secondaryId CONSTANT) -// Q_PROPERTY(QUrlQuery query READ query CONSTANT) - Q_PROPERTY(QString action READ action CONSTANT) -// Q_PROPERTY(QStringList viaServers READ viaServers CONSTANT) -public: - enum Type : char { - Invalid = char(-1), - Empty = 0x0, - UserId = '@', - RoomId = '!', - RoomAlias = '#', - Group = '+' - }; - Q_ENUM(Type) - enum SecondaryType : char { - NoSecondaryId = 0x0, - EventId = '$' - }; - - enum UriForm : short { CanonicalUri, MatrixToUri }; - Q_ENUM(UriForm) - - /// Construct an empty Matrix URI - MatrixUri() = default; - /*! \brief Decode a user input string to a Matrix identifier - * - * Accepts plain Matrix ids, MSC2312 URIs (aka matrix: URIs) and - * matrix.to URLs. In case of URIs/URLs, it uses QUrl's TolerantMode - * parser to decode common mistakes/irregularities (see QUrl documentation - * for more details). - */ - MatrixUri(const QString& uriOrId); - - /// Construct a Matrix URI from components - explicit MatrixUri(QByteArray primaryId, QByteArray secondaryId = {}, - QString query = {}); - /// Construct a Matrix URI from matrix.to or MSC2312 (matrix:) URI - explicit MatrixUri(QUrl url); - - static MatrixUri fromUserInput(const QString& uriOrId); - static MatrixUri fromUrl(QUrl url); - - /// Get the primary type of the Matrix URI (user id, room id or alias) - /*! Note that this does not include an event as a separate type, since - * events can only be addressed inside of rooms, which, in turn, are - * addressed either by id or alias. If you need to check whether the URI - * is specifically an event URI, use secondaryType() instead. - */ - Type type() const; - SecondaryType secondaryType() const; - QUrl toUrl(UriForm form = CanonicalUri) const; - QString toDisplayString(UriForm form = CanonicalUri) const; - QString primaryId() const; - QString secondaryId() const; - QString action() const; - QStringList viaServers() const; - bool isValid() const; - using QUrl::isEmpty, QUrl::path, QUrl::query, QUrl::fragment; - -private: - - Type primaryType_ = Empty; -}; - -/*! \brief Resolve the resource and invoke an action on it, visitor style - * - * This template function encapsulates the logic of resolving a Matrix - * identifier or URI into a Quotient object (or objects) and applying an - * appropriate action handler from the set provided by the caller to it. - * A typical use case for that is opening a room or mentioning a user in - * response to clicking on a Matrix URI or identifier. - * - * \param account The connection used as a context to resolve the identifier - * - * \param uri The Matrix identifier or URI; MSC2312 URIs and classic Matrix IDs - * are supported - * - * \sa ResourceResolver - */ -UriResolveResult -visitResource(Connection* account, const MatrixUri& uri, - std::function userHandler, - std::function roomEventHandler, - std::function joinHandler); - -/*! \brief Matrix resource resolver - * TODO: rewrite - * Similar to visitResource(), this class encapsulates the logic of resolving - * a Matrix identifier or a URI into Quotient object(s) and applying an action - * to the resolved object(s). Instead of using a C++ visitor pattern, it - * announces the request through Qt's signals passing the resolved object(s) - * through those (still in a typesafe way). - * - * This class is aimed primarily at clients where invoking the resolving/action - * and handling the action are happening in decoupled parts of the code; it's - * also useful to operate on Matrix identifiers and URIs from QML/JS code - * that cannot call visitResource due to QML/C++ interface limitations. - */ -class ResourceResolver : public QObject { - Q_OBJECT -public: - explicit ResourceResolver(QObject* parent = nullptr) : QObject(parent) - { } - - /*! \brief Resolve the resource and request an action on it, signal style - * - * This method: - * 1. Resolves \p identifier into an actual object (Room or User), with - * possible additional data such as event id, in the context of - * \p account. - * 2. If the resolving is successful, depending on the type of the object, - * emits the respective signal to which the client must connect in order - * to apply the action to the resource (open a room, mention a user etc.). - * 3. Returns the result of resolving the resource. - * - * Note that the action can be applied either synchronously or entirely - * asynchronously; ResourceResolver does not restrain the client code - * to use either method. The resource resolving part is entirely synchronous - * though. If the synchronous operation is chosen, only - * direct connections to ResourceResolver signals must be used, and - * the caller should check the future's state immediately after calling - * openResource() to process any feedback from the resolver and/or action - * handler. If asynchronous operation is needed then either direct or queued - * connections to ResourceResolver's signals can be used and the caller - * must both check the ResourceFuture state right after calling openResource - * and also connect to ResourceFuture::ready() signal in order to process - * the result of resolving and action. - */ - Q_INVOKABLE UriResolveResult openResource(Connection* account, - const QString& identifier, - const QString& action = {}); - Q_INVOKABLE UriResolveResult - openResource(Connection* account, const MatrixUri& uri, - const QString& overrideAction = {}); - -signals: - /// An action on a user has been requested - void userAction(Quotient::User* user, QString action); - - /// An action on a room has been requested, with optional event id - void roomAction(Quotient::Room* room, QString eventId, QString action); - - /// A join action has been requested, with optional 'via' servers - void joinAction(Quotient::Connection* account, QString roomAliasOrId, - QStringList viaServers); -}; - -} // namespace Quotient - - diff --git a/lib/uri.cpp b/lib/uri.cpp new file mode 100644 index 00000000..e81933dc --- /dev/null +++ b/lib/uri.cpp @@ -0,0 +1,181 @@ +#include "uri.h" + +#include "logging.h" + +#include + +using namespace Quotient; + +struct ReplacePair { QByteArray uriString; char sigil; }; +static const auto replacePairs = { ReplacePair { "user/", '@' }, + { "roomid/", '!' }, + { "room/", '#' }, + // The notation for bare event ids is not + // proposed in MSC2312 (and anywhere, as yet) + { "event/", '$' } }; + +Uri::Uri(QByteArray primaryId, QByteArray secondaryId, QString query) +{ + if (primaryId.isEmpty()) + primaryType_ = Empty; + else { + setScheme("matrix"); + QString pathToBe; + primaryType_ = Invalid; + for (const auto& p: replacePairs) + if (primaryId[0] == p.sigil) { + primaryType_ = Type(p.sigil); + pathToBe = p.uriString + primaryId.mid(1); + break; + } + if (!secondaryId.isEmpty()) + pathToBe += "/event/" + secondaryId.mid(1); + setPath(pathToBe); + } + setQuery(std::move(query)); +} + +Uri::Uri(QUrl url) : QUrl(std::move(url)) +{ + // NB: don't try to use `url` from here on, it's moved-from and empty + if (isEmpty()) + return; // primaryType_ == Empty + + if (!QUrl::isValid()) { // MatrixUri::isValid() checks primaryType_ + primaryType_ = Invalid; + return; + } + + if (scheme() == "matrix") { + // Check sanity as per https://github.com/matrix-org/matrix-doc/pull/2312 + const auto& urlPath = path(); + const auto& splitPath = urlPath.splitRef('/'); + switch (splitPath.size()) { + case 2: + break; + case 4: + if (splitPath[2] == "event") + break; + [[fallthrough]]; + default: + return; // Invalid + } + + for (const auto& p: replacePairs) + if (urlPath.startsWith(p.uriString)) { + primaryType_ = Type(p.sigil); + return; // The only valid return path for matrix: URIs + } + qCDebug(MAIN) << "The matrix: URI is not recognised:" + << toDisplayString(); + return; + } + + primaryType_ = NonMatrix; // Default, unless overridden by the code below + if (scheme() == "https" && authority() == "matrix.to") { + // See https://matrix.org/docs/spec/appendices#matrix-to-navigation + static const QRegularExpression MatrixToUrlRE { + R"(^/(?
[^/?]+)(/(?[^?]+))?(\?(?.+))?$)" + }; + // matrix.to accepts both literal sigils (as well as & and ? used in + // its "query" substitute) and their %-encoded forms; + // so force QUrl to decode everything. + auto f = fragment(QUrl::FullyDecoded); + if (auto&& m = MatrixToUrlRE.match(f); m.hasMatch()) + *this = Uri { m.captured("main").toUtf8(), + m.captured("sec").toUtf8(), m.captured("query") }; + } +} + +Uri::Uri(const QString& uriOrId) : Uri(fromUserInput(uriOrId)) {} + +Uri Uri::fromUserInput(const QString& uriOrId) +{ + if (uriOrId.isEmpty()) + return {}; // type() == None + + // A quick check if uriOrId is a plain Matrix id + // Bare event ids cannot be resolved without a room scope as per the current + // spec but there's a movement towards making them navigable (see, e.g., + // https://github.com/matrix-org/matrix-doc/pull/2644) - so treat them + // as valid + if (QStringLiteral("!@#+$").contains(uriOrId[0])) + return Uri { uriOrId.toUtf8() }; + + return Uri { QUrl::fromUserInput(uriOrId) }; +} + +Uri::Type Uri::type() const { return primaryType_; } + +Uri::SecondaryType Uri::secondaryType() const +{ + return path().section('/', 2, 2) == "event" ? EventId : NoSecondaryId; +} + +QUrl Uri::toUrl(UriForm form) const +{ + if (!isValid()) + return {}; + + if (form == CanonicalUri || type() == NonMatrix) + return *this; + + QUrl url; + url.setScheme("https"); + url.setHost("matrix.to"); + url.setPath("/"); + auto fragment = primaryId(); + if (const auto& secId = secondaryId(); !secId.isEmpty()) + fragment += '/' + secId; + if (const auto& q = query(); !q.isEmpty()) + fragment += '?' + q; + url.setFragment(fragment); + return url; +} + +QString Uri::primaryId() const +{ + if (primaryType_ == Empty || primaryType_ == Invalid) + return {}; + + const auto& idStem = path().section('/', 1, 1); + return idStem.isEmpty() ? idStem : primaryType_ + idStem; +} + +QString Uri::secondaryId() const +{ + const auto& idStem = path().section('/', 3); + return idStem.isEmpty() ? idStem : secondaryType() + idStem; +} + +static const auto ActionKey = QStringLiteral("action"); + +QString Uri::action() const +{ + return type() == NonMatrix || !isValid() + ? QString() + : QUrlQuery { query() }.queryItemValue(ActionKey); +} + +void Uri::setAction(const QString& newAction) +{ + if (!isValid()) { + qCWarning(MAIN) << "Cannot set an action on an invalid Quotient::Uri"; + return; + } + QUrlQuery q { query() }; + q.removeQueryItem(ActionKey); + q.addQueryItem(ActionKey, newAction); + setQuery(q); +} + +QStringList Uri::viaServers() const +{ + return QUrlQuery { query() }.allQueryItemValues(QStringLiteral("via"), + QUrl::EncodeReserved); +} + +bool Uri::isValid() const +{ + return primaryType_ != Empty && primaryType_ != Invalid; +} diff --git a/lib/uri.h b/lib/uri.h new file mode 100644 index 00000000..270766dd --- /dev/null +++ b/lib/uri.h @@ -0,0 +1,85 @@ +#pragma once + +#include "quotient_common.h" + +#include +#include + +namespace Quotient { + +/*! \brief A wrapper around a Matrix URI or identifier + * + * This class encapsulates a Matrix resource identifier, passed in either of + * 3 forms: a plain Matrix identifier (sigil, localpart, serverpart or, for + * modern event ids, sigil and base64 hash); an MSC2312 URI (aka matrix: URI); + * or a matrix.to URL. The input can be either encoded (serverparts with + * punycode, the rest with percent-encoding) or unencoded (in this case it is + * the caller's responsibility to resolve all possible ambiguities). + * + * The class provides functions to check the validity of the identifier, + * its type, and obtain components, also in either unencoded (for displaying) + * or encoded (for APIs) form. + */ +class Uri : private QUrl { + Q_GADGET +public: + enum Type : char { + Invalid = char(-1), + Empty = 0x0, + UserId = '@', + RoomId = '!', + RoomAlias = '#', + Group = '+', + BareEventId = '$', // https://github.com/matrix-org/matrix-doc/pull/2644 + NonMatrix = ':' + }; + Q_ENUM(Type) + enum SecondaryType : char { NoSecondaryId = 0x0, EventId = '$' }; + Q_ENUM(SecondaryType) + + enum UriForm : short { CanonicalUri, MatrixToUri }; + Q_ENUM(UriForm) + + /// Construct an empty Matrix URI + Uri() = default; + /*! \brief Decode a user input string to a Matrix identifier + * + * Accepts plain Matrix ids, MSC2312 URIs (aka matrix: URIs) and + * matrix.to URLs. In case of URIs/URLs, it uses QUrl's TolerantMode + * parser to decode common mistakes/irregularities (see QUrl documentation + * for more details). + */ + Uri(const QString& uriOrId); + + /// Construct a Matrix URI from components + explicit Uri(QByteArray primaryId, QByteArray secondaryId = {}, + QString query = {}); + /// Construct a Matrix URI from matrix.to or MSC2312 (matrix:) URI + explicit Uri(QUrl url); + + static Uri fromUserInput(const QString& uriOrId); + static Uri fromUrl(QUrl url); + + /// Get the primary type of the Matrix URI (user id, room id or alias) + /*! Note that this does not include an event as a separate type, since + * events can only be addressed inside of rooms, which, in turn, are + * addressed either by id or alias. If you need to check whether the URI + * is specifically an event URI, use secondaryType() instead. + */ + Q_INVOKABLE Type type() const; + Q_INVOKABLE SecondaryType secondaryType() const; + Q_INVOKABLE QUrl toUrl(UriForm form = CanonicalUri) const; + Q_INVOKABLE QString primaryId() const; + Q_INVOKABLE QString secondaryId() const; + Q_INVOKABLE QString action() const; + Q_INVOKABLE void setAction(const QString& newAction); + Q_INVOKABLE QStringList viaServers() const; + Q_INVOKABLE bool isValid() const; + using QUrl::path, QUrl::query, QUrl::fragment; + using QUrl::isEmpty, QUrl::toDisplayString; + +private: + Type primaryType_ = Empty; +}; + +} diff --git a/lib/uriresolver.cpp b/lib/uriresolver.cpp new file mode 100644 index 00000000..5052890b --- /dev/null +++ b/lib/uriresolver.cpp @@ -0,0 +1,110 @@ +#include "uriresolver.h" + +#include "connection.h" +#include "user.h" + +using namespace Quotient; + +UriResolveResult UriResolverBase::visitResource(Connection* account, + const Uri& uri) +{ + switch (uri.type()) { + case Uri::NonMatrix: + return visitNonMatrix(uri.toUrl()) ? UriResolved : CouldNotResolve; + case Uri::Invalid: + case Uri::Empty: + return InvalidUri; + default:; + } + + if (!account) + return NoAccount; + + switch (uri.type()) { + case Uri::UserId: { + if (uri.action() == "join") + return IncorrectAction; + auto* user = account->user(uri.primaryId()); + Q_ASSERT(user != nullptr); + visitUser(user, uri.action()); + return UriResolved; + } + case Uri::RoomId: + case Uri::RoomAlias: { + auto* room = uri.type() == Uri::RoomId + ? account->room(uri.primaryId()) + : account->roomByAlias(uri.primaryId()); + if (room != nullptr) { + visitRoom(room, uri.secondaryId()); + return UriResolved; + } + if (uri.action() == "join") { + joinRoom(account, uri.primaryId(), uri.viaServers()); + return UriResolved; + } + [[fallthrough]]; + } + default: + return CouldNotResolve; + } +} + +template +class StaticUriDispatcher : public UriResolverBase { +public: + StaticUriDispatcher(const FnTs&... fns) : fns_(fns...) {} + +private: + void visitUser(User* user, const QString& action) override + { + std::get<0>(fns_)(user, action); + } + void visitRoom(Room* room, const QString& eventId) override + { + std::get<1>(fns_)(room, eventId); + } + void joinRoom(Connection* account, const QString& roomAliasOrId, + const QStringList& viaServers = {}) override + { + std::get<2>(fns_)(account, roomAliasOrId, viaServers); + } + bool visitNonMatrix(const QUrl& url) override + { + return std::get<3>(fns_)(url); + } + + std::tuple fns_; +}; + +UriResolveResult Quotient::visitResource( + Connection* account, const Uri& uri, + std::function userHandler, + std::function roomEventHandler, + std::function joinHandler, + std::function nonMatrixHandler) +{ + return StaticUriDispatcher(userHandler, roomEventHandler, joinHandler, + nonMatrixHandler) + .visitResource(account, uri); +} + +void UriDispatcher::visitUser(User *user, const QString &action) +{ + emit userAction(user, action); +} + +void UriDispatcher::visitRoom(Room *room, const QString &eventId) +{ + emit roomAction(room, eventId); +} + +void UriDispatcher::joinRoom(Connection *account, const QString &roomAliasOrId, const QStringList &viaServers) +{ + emit joinAction(account, roomAliasOrId, viaServers); +} + +bool UriDispatcher::visitNonMatrix(const QUrl &url) +{ + emit nonMatrixAction(url); + return true; +} diff --git a/lib/uriresolver.h b/lib/uriresolver.h new file mode 100644 index 00000000..914ddf02 --- /dev/null +++ b/lib/uriresolver.h @@ -0,0 +1,162 @@ +#pragma once + +#include "uri.h" + +#include + +#include + +namespace Quotient { +class Connection; +class Room; +class User; + +/*! \brief Abstract class to resolve the resource and act on it + * + * This class encapsulates the logic of resolving a Matrix identifier or URI + * into a Quotient object (or objects) and calling an appropriate handler on it. + * It is a type-safe way of handling a URI with no prior context on its type + * in cases like, e.g., when a user clicks on a URI in the application. + * + * This class provides empty "handlers" for each type of URI to facilitate + * gradual implementation. Derived classes are encouraged to override as many + * of them as possible. + */ +class UriResolverBase { +public: + /*! \brief Resolve the resource and dispatch an action depending on its type + * + * This method: + * 1. Resolves \p uri into an actual object (e.g., Room or User), + * with possible additional data such as event id, in the context of + * \p account. + * 2. If the resolving is successful, depending on the type of the object, + * calls the appropriate virtual function (defined in a derived + * concrete class) to perform an action on the resource (open a room, + * mention a user etc.). + * 3. Returns the result of resolving the resource. + */ + UriResolveResult visitResource(Connection* account, const Uri& uri); + +protected: + /// Called by visitResource() when the passed URI identifies a Matrix user + virtual void visitUser(User* user, const QString& action) {} + /// Called by visitResource() when the passed URI identifies a room or + /// an event in a room + virtual void visitRoom(Room* room, const QString& eventId) {} + /// Called by visitResource() when the passed URI has `action() == "join"` + /// and identifies a room that the user defined by the Connection argument + /// is not a member of + virtual void joinRoom(Connection* account, const QString& roomAliasOrId, + const QStringList& viaServers = {}) + {} + /// Called by visitResource() when the passed URI has `type() == NonMatrix` + /*! + * Should return true if the URI is considered resolved, false otherwise. + * A basic implementation in a graphical client can look like + * `return QDesktopServices::openUrl(url);` but it's strongly advised to + * ask for a user confirmation beforehand. + */ + virtual bool visitNonMatrix(const QUrl& url) { return false; } +}; + +/*! \brief Resolve the resource and invoke an action on it, via function objects + * + * This function encapsulates the logic of resolving a Matrix identifier or URI + * into a Quotient object (or objects) and calling an appropriate handler on it. + * Unlike UriResolverBase it accepts the list of handlers from + * the caller; internally it's uses a minimal UriResolverBase class + * + * \param account The connection used as a context to resolve the identifier + * + * \param uri A URI that can represent a Matrix entity + * + * \param userHandler Called when the passed URI identifies a Matrix user + * + * \param roomEventHandler Called when the passed URI identifies a room or + * an event in a room + * + * \param joinHandler Called when the passed URI has `action() == "join"` and + * identifies a room that the user defined by + * the Connection argument is not a member of + * + * \param nonMatrixHandler Called when the passed URI has `type() == NonMatrix`; + * should return true if the URI is considered resolved, + * false otherwise + * + * \sa UriResolverBase, UriDispatcher + */ +UriResolveResult +visitResource(Connection* account, const Uri& uri, + std::function userHandler, + std::function roomEventHandler, + std::function joinHandler, + std::function nonMatrixHandler); + +/*! \brief Check that the resource is resolvable with no action on it */ +inline UriResolveResult checkResource(Connection* account, + const Uri& uri) +{ + return visitResource( + account, uri, [](auto, auto) {}, [](auto, auto) {}, + [](auto, auto, auto) {}, [](auto) { return false; }); +} + +/*! \brief Resolve the resource and invoke an action on it, via Qt signals + * + * This is an implementation of UriResolverBase that is based on + * QObject and uses Qt signals instead of virtual functions to provide an + * open-ended interface for visitors. + * + * This class is aimed primarily at clients where invoking the resolving/action + * and handling the action are happening in decoupled parts of the code; it's + * also useful to operate on Matrix identifiers and URIs from QML/JS code + * that cannot call resolveResource() due to QML/C++ interface limitations. + * + * This class does not restrain the client code to a certain type of + * connections: both direct and queued (or a mix) will work fine. One limitation + * caused by that is there's no way to indicate if a non-Matrix URI has been + * successfully resolved - a signal always returns void. + * + * Note that in case of using (non-blocking) queued connections the code that + * calls resolveResource() should not expect the action to be performed + * synchronously - the returned value is the result of resolving the URI, + * not acting on it. + */ +class UriDispatcher : public QObject, public UriResolverBase { + Q_OBJECT +public: + explicit UriDispatcher(QObject* parent = nullptr) : QObject(parent) {} + + // It's actually UriResolverBase::visitResource() but with Q_INVOKABLE + Q_INVOKABLE UriResolveResult resolveResource(Connection* account, + const Uri& uri) + { + return UriResolverBase::visitResource(account, uri); + } + +signals: + /// An action on a user has been requested + void userAction(Quotient::User* user, QString action); + + /// An action on a room has been requested, with optional event id + void roomAction(Quotient::Room* room, QString eventId); + + /// A join action has been requested, with optional 'via' servers + void joinAction(Quotient::Connection* account, QString roomAliasOrId, + QStringList viaServers); + + /// An action on a non-Matrix URL has been requested + void nonMatrixAction(QUrl url); + +private: + void visitUser(User* user, const QString& action) override; + void visitRoom(Room* room, const QString& eventId) override; + void joinRoom(Connection* account, const QString& roomAliasOrId, + const QStringList& viaServers = {}) override; + bool visitNonMatrix(const QUrl& url) override; +}; + +} // namespace Quotient + + diff --git a/libquotient.pri b/libquotient.pri index f0057712..98fe3b03 100644 --- a/libquotient.pri +++ b/libquotient.pri @@ -34,7 +34,8 @@ HEADERS += \ $$SRCPATH/room.h \ $$SRCPATH/user.h \ $$SRCPATH/avatar.h \ - $$SRCPATH/resourceresolver.h \ + $$SRCPATH/uri.h \ + $$SRCPATH/uriresolver.h \ $$SRCPATH/syncdata.h \ $$SRCPATH/quotient_common.h \ $$SRCPATH/util.h \ @@ -91,7 +92,8 @@ SOURCES += \ $$SRCPATH/room.cpp \ $$SRCPATH/user.cpp \ $$SRCPATH/avatar.cpp \ - $$SRCPATH/resourceresolver.cpp \ + $$SRCPATH/uri.cpp \ + $$SRCPATH/uriresolver.cpp \ $$SRCPATH/syncdata.cpp \ $$SRCPATH/util.cpp \ $$SRCPATH/events/event.cpp \ diff --git a/tests/quotest.cpp b/tests/quotest.cpp index 52915454..c2c50df2 100644 --- a/tests/quotest.cpp +++ b/tests/quotest.cpp @@ -2,7 +2,7 @@ #include "connection.h" #include "room.h" #include "user.h" -#include "resourceresolver.h" +#include "uriresolver.h" #include "csapi/joining.h" #include "csapi/leaving.h" @@ -622,7 +622,7 @@ TEST_IMPL(visitResources) // assumes that ResourceResolver::openResource is implemented in terms // of ResourceResolver::visitResource, so the latter doesn't need a // separate test. - static ResourceResolver rr; + static UriDispatcher ud; // This lambda returns true in case of error, false if it's fine so far auto testResourceResolver = [this, thisTest](const QStringList& uris, @@ -630,12 +630,12 @@ TEST_IMPL(visitResources) QVariantList otherArgs = {}) { int r = qRegisterMetaType(); Q_ASSERT(r != 0); - QSignalSpy spy(&rr, signal); + QSignalSpy spy(&ud, signal); for (const auto& uriString: uris) { - MatrixUri uri { uriString }; + Uri uri { uriString }; clog << "Checking " << uriString.toStdString() << " -> " << uri.toDisplayString().toStdString() << endl; - rr.openResource(connection(), uriString); + ud.visitResource(connection(), uriString); if (spy.count() != 1) { clog << "Wrong number of signal emissions (" << spy.count() << ')' << endl; @@ -666,7 +666,7 @@ TEST_IMPL(visitResources) // Basic tests QUrl invalidUrl { "https://" }; invalidUrl.setAuthority("---:@@@"); - const MatrixUri emptyUri {}, uriFromEmptyUrl {}, + const Uri emptyUri {}, uriFromEmptyUrl {}, invalidMatrixUri { QStringLiteral("matrix:&invalid@") }, matrixUriFromInvalidUrl { invalidUrl }; @@ -710,7 +710,7 @@ TEST_IMPL(visitResources) // exist, as yet) - only to be syntactically correct static const auto& joinRoomAlias = QStringLiteral("unjoined:example.org"); // # will be added below - QString joinQuery { "?action=join" }; + static const QString joinQuery { "?action=join" }; static const QStringList joinByAliasUris { "matrix:room/" + joinRoomAlias + joinQuery, "https://matrix.to/#/%23"/*`#`*/ + joinRoomAlias + joinQuery @@ -728,14 +728,14 @@ TEST_IMPL(visitResources) }; // If any test breaks, the breaking call will return true, and further // execution will be cut by ||'s short-circuiting - if (testResourceResolver(roomUris, &ResourceResolver::roomAction, room()) - || testResourceResolver(userUris, &ResourceResolver::userAction, + if (testResourceResolver(roomUris, &UriDispatcher::roomAction, room()) + || testResourceResolver(userUris, &UriDispatcher::userAction, connection()->user()) - || testResourceResolver(eventUris, &ResourceResolver::roomAction, + || testResourceResolver(eventUris, &UriDispatcher::roomAction, room(), { eventId }) - || testResourceResolver(joinByAliasUris, &ResourceResolver::joinAction, + || testResourceResolver(joinByAliasUris, &UriDispatcher::joinAction, connection(), { '#' + joinRoomAlias }) - || testResourceResolver(joinByIdUris, &ResourceResolver::joinAction, + || testResourceResolver(joinByIdUris, &UriDispatcher::joinAction, connection(), { joinRoomId, viaServers })) return true; // TODO: negative cases -- cgit v1.2.3 From 78cfde52d8f3ff04a07031a87a0c7218a3b0079f Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Sun, 27 Dec 2020 18:07:30 +0100 Subject: more :) --- lib/events/encryptedevent.cpp | 4 ++++ lib/events/encryptedevent.h | 4 ++++ lib/events/redactionevent.cpp | 4 ++++ lib/quotient_common.h | 4 ++++ 4 files changed, 16 insertions(+) (limited to 'lib/quotient_common.h') diff --git a/lib/events/encryptedevent.cpp b/lib/events/encryptedevent.cpp index 117aae37..dc9eaf2d 100644 --- a/lib/events/encryptedevent.cpp +++ b/lib/events/encryptedevent.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2019 Alexey Andreyev +// +// SPDX-License-Identifier: LGPL-2.1-or-later + #include "encryptedevent.h" using namespace Quotient; diff --git a/lib/events/encryptedevent.h b/lib/events/encryptedevent.h index 235b2aa4..9de08b00 100644 --- a/lib/events/encryptedevent.h +++ b/lib/events/encryptedevent.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2019 Alexey Andreyev +// +// SPDX-License-Identifier: LGPL-2.1-or-later + #pragma once #include "e2ee.h" diff --git a/lib/events/redactionevent.cpp b/lib/events/redactionevent.cpp index bf467718..5889773c 100644 --- a/lib/events/redactionevent.cpp +++ b/lib/events/redactionevent.cpp @@ -1 +1,5 @@ +// SPDX-FileCopyrightText: 2019 Kitsune Ral +// +// SPDX-License-Identifier: CC0-1.0 + #include "redactionevent.h" diff --git a/lib/quotient_common.h b/lib/quotient_common.h index bb05af05..e2384f12 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2019 Kitsune Ral +// +// SPDX-License-Identifier: LGPL-2.1-or-later + #pragma once #include -- cgit v1.2.3 From 0a775d9b3209be15dea8b8915fc0a1c8e0046ba6 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sat, 16 Jan 2021 18:19:45 +0100 Subject: Updated copyright statements upon Git audit After going through all the files and the history of commits on them it was clear that some copyright statements are obsolete (the code has been overwritten since) and some are missing. This commit tries best to remedy that, along with adding SPDX tags where they were still not used. Also, a minimal SPDX convention is documented for further contributions. Closes #426. --- .clang-format | 8 ++++---- CONTRIBUTING.md | 14 ++++++++++++-- gtad/data.h.mustache | 4 ++++ gtad/operation.cpp.mustache | 4 ++++ gtad/operation.h.mustache | 4 ++++ lib/avatar.cpp | 7 ++----- lib/avatar.h | 9 +++------ lib/connection.cpp | 10 +++++----- lib/connection.h | 9 ++++----- lib/connectiondata.cpp | 8 +++----- lib/connectiondata.h | 8 +++----- lib/converters.cpp | 7 ++----- lib/converters.h | 7 ++----- lib/e2ee.h | 1 - lib/encryptionmanager.cpp | 1 - lib/encryptionmanager.h | 1 - lib/eventitem.cpp | 7 ++----- lib/eventitem.h | 7 ++----- lib/events/accountdataevents.h | 7 ++----- lib/events/callanswerevent.cpp | 8 +++----- lib/events/callanswerevent.h | 8 +++----- lib/events/callcandidatesevent.cpp | 8 +++----- lib/events/callcandidatesevent.h | 9 ++++----- lib/events/callhangupevent.cpp | 1 + lib/events/callhangupevent.h | 8 +++----- lib/events/callinviteevent.cpp | 8 +++----- lib/events/callinviteevent.h | 8 +++----- lib/events/directchatevent.cpp | 7 ++----- lib/events/directchatevent.h | 7 ++----- lib/events/encryptedevent.cpp | 1 - lib/events/encryptedevent.h | 1 - lib/events/encryptionevent.cpp | 4 ++++ lib/events/encryptionevent.h | 8 +++----- lib/events/event.cpp | 7 ++----- lib/events/event.h | 7 ++----- lib/events/eventcontent.cpp | 7 ++----- lib/events/eventcontent.h | 7 ++----- lib/events/eventloader.h | 7 ++----- lib/events/reactionevent.cpp | 7 ++----- lib/events/reactionevent.h | 7 ++----- lib/events/receiptevent.cpp | 7 ++----- lib/events/receiptevent.h | 7 ++----- lib/events/redactionevent.cpp | 5 ----- lib/events/redactionevent.h | 7 ++----- lib/events/roomavatarevent.h | 7 ++----- lib/events/roomcanonicalaliasevent.h | 8 +++----- lib/events/roomcreateevent.cpp | 7 ++----- lib/events/roomcreateevent.h | 7 ++----- lib/events/roomevent.cpp | 7 ++----- lib/events/roomevent.h | 7 ++----- lib/events/roomkeyevent.cpp | 3 +++ lib/events/roomkeyevent.h | 3 +++ lib/events/roommemberevent.cpp | 8 +++----- lib/events/roommemberevent.h | 9 ++++----- lib/events/roommessageevent.cpp | 9 ++++----- lib/events/roommessageevent.h | 9 ++++----- lib/events/roompowerlevelsevent.cpp | 3 +++ lib/events/roompowerlevelsevent.h | 3 +++ lib/events/roomtombstoneevent.cpp | 7 ++----- lib/events/roomtombstoneevent.h | 7 ++----- lib/events/simplestateevents.h | 7 ++----- lib/events/stateevent.cpp | 7 ++----- lib/events/stateevent.h | 7 ++----- lib/events/typingevent.cpp | 7 ++----- lib/events/typingevent.h | 7 ++----- lib/jobs/basejob.cpp | 8 +++----- lib/jobs/basejob.h | 8 +++----- lib/jobs/downloadfilejob.cpp | 3 +++ lib/jobs/downloadfilejob.h | 3 +++ lib/jobs/mediathumbnailjob.cpp | 7 ++----- lib/jobs/mediathumbnailjob.h | 7 ++----- lib/jobs/requestdata.cpp | 3 +++ lib/jobs/requestdata.h | 7 ++----- lib/jobs/syncjob.cpp | 7 ++----- lib/jobs/syncjob.h | 7 ++----- lib/joinstate.h | 7 ++----- lib/logging.cpp | 8 +++----- lib/logging.h | 8 +++----- lib/networkaccessmanager.cpp | 7 ++----- lib/networkaccessmanager.h | 7 ++----- lib/networksettings.cpp | 7 ++----- lib/networksettings.h | 7 ++----- lib/qt_connection_util.h | 7 ++----- lib/quotient_common.h | 1 - lib/room.cpp | 13 ++++++++----- lib/room.h | 13 ++++++++----- lib/settings.cpp | 3 +++ lib/settings.h | 7 ++----- lib/ssosession.cpp | 3 +++ lib/ssosession.h | 3 +++ lib/syncdata.cpp | 7 ++----- lib/syncdata.h | 7 ++----- lib/uri.cpp | 3 +++ lib/uri.h | 3 +++ lib/uriresolver.cpp | 3 +++ lib/uriresolver.h | 3 +++ lib/user.cpp | 8 +++----- lib/user.h | 8 +++----- lib/util.cpp | 8 +++----- lib/util.h | 8 +++----- tests/quotest.cpp | 2 ++ 101 files changed, 266 insertions(+), 378 deletions(-) delete mode 100644 lib/events/redactionevent.cpp (limited to 'lib/quotient_common.h') diff --git a/.clang-format b/.clang-format index 4df5ae84..4510d46e 100644 --- a/.clang-format +++ b/.clang-format @@ -1,7 +1,7 @@ -# Copyright (C) 2019 Project Quotient -# -# You may use this file under the terms of the LGPL-2.1 license -# See the file LICENSE from this package for details. +# SPDX-FileCopyrightText: 2019 Kitsune Ral +# SPDX-FileCopyrightText: 2019 Marc Deop + +# SPDX-License-Identifier: LGPL-2.1-or-later # This is the clang-format configuration style to be used by libQuotient. # Inspired by: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bda004df..f09b1529 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -96,8 +96,18 @@ All new contributed material that is not executable, including all text when not --> Any components proposed for reuse should have a license that permits releasing -a derivative work under *LGPL v2.1 or later* or LGPL v3. Moreover, the license of -a proposed component should be approved by OSI, no exceptions. +a derivative work under *LGPL v3 or later* (that includes licenses permitting +*LGPL v2.1 or later* but not *LGPL v2.1 only*). In any case, the component +should be redistributable under a license from +[the list approved by OSI](https://opensource.org/licenses), no exceptions. + +We use [SPDX](https://spdx.dev) conventions for copyright statements. Please +follow them when making a sizable contribution: add your name and year to +the top of the file. New files should begin with the following preamble: +```cpp +// SPDX-FileCopyrightText: 2021 Your Name +// SPDX-License-Identifier: LGPL-2.1-or-later +``` ## Vulnerability reporting (security issues) - see [SECURITY.md](./SECURITY.md) diff --git a/gtad/data.h.mustache b/gtad/data.h.mustache index 32ea85ee..a2193380 100644 --- a/gtad/data.h.mustache +++ b/gtad/data.h.mustache @@ -1,3 +1,7 @@ +{{! +SPDX-FileCopyrightText: 2020 Kitsune Ral +SPDX-License-Identifier: LGPL-2.1-or-later +}} {{>preamble}} #pragma once diff --git a/gtad/operation.cpp.mustache b/gtad/operation.cpp.mustache index 3c3396e9..1d0ae476 100644 --- a/gtad/operation.cpp.mustache +++ b/gtad/operation.cpp.mustache @@ -1,3 +1,7 @@ +{{! +SPDX-FileCopyrightText: 2020 Kitsune Ral +SPDX-License-Identifier: LGPL-2.1-or-later +}} {{>preamble}} #include "{{filenameBase}}.h" diff --git a/gtad/operation.h.mustache b/gtad/operation.h.mustache index 36963b9a..135eee55 100644 --- a/gtad/operation.h.mustache +++ b/gtad/operation.h.mustache @@ -1,3 +1,7 @@ +{{! +SPDX-FileCopyrightText: 2020 Kitsune Ral +SPDX-License-Identifier: LGPL-2.1-or-later +}} {{>preamble}} #pragma once diff --git a/lib/avatar.cpp b/lib/avatar.cpp index 0573df5d..77648562 100644 --- a/lib/avatar.cpp +++ b/lib/avatar.cpp @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "avatar.h" diff --git a/lib/avatar.h b/lib/avatar.h index 111f565d..be125c17 100644 --- a/lib/avatar.h +++ b/lib/avatar.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once @@ -46,4 +43,4 @@ private: }; } // namespace Quotient /// \deprecated Use namespace Quotient instead -namespace QMatrixClient = Quotient; \ No newline at end of file +namespace QMatrixClient = Quotient; diff --git a/lib/connection.cpp b/lib/connection.cpp index 015e73c9..d773f0d8 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -1,8 +1,8 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2015 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-FileCopyrightText: 2017 Roman Plášil +// SPDX-FileCopyrightText: 2019 Ville Ranki +// SPDX-FileCopyrightText: 2019 Alexey Andreyev +// SPDX-License-Identifier: LGPL-2.1-or-later #include "connection.h" diff --git a/lib/connection.h b/lib/connection.h index f3d7d725..4f949641 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -1,8 +1,7 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2015 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-FileCopyrightText: 2017 Roman Plášil +// SPDX-FileCopyrightText: 2019 Alexey Andreyev +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/connectiondata.cpp b/lib/connectiondata.cpp index 25ab775a..e54d909b 100644 --- a/lib/connectiondata.cpp +++ b/lib/connectiondata.cpp @@ -1,8 +1,6 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2015 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2015 Felix Rohrbach +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "connectiondata.h" diff --git a/lib/connectiondata.h b/lib/connectiondata.h index a3b2d39b..7dd96f26 100644 --- a/lib/connectiondata.h +++ b/lib/connectiondata.h @@ -1,8 +1,6 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2015 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2015 Felix Rohrbach +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/converters.cpp b/lib/converters.cpp index 0df880a0..4338e8ed 100644 --- a/lib/converters.cpp +++ b/lib/converters.cpp @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2018 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "converters.h" diff --git a/lib/converters.h b/lib/converters.h index d4f19b60..e07b6ee4 100644 --- a/lib/converters.h +++ b/lib/converters.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/e2ee.h b/lib/e2ee.h index 5f1857b6..4044aa02 100644 --- a/lib/e2ee.h +++ b/lib/e2ee.h @@ -1,6 +1,5 @@ // SPDX-FileCopyrightText: 2019 Alexey Andreyev // SPDX-FileCopyrightText: 2019 Kitsune Ral -// // SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/encryptionmanager.cpp b/lib/encryptionmanager.cpp index 8d241eb2..37f3b7c3 100644 --- a/lib/encryptionmanager.cpp +++ b/lib/encryptionmanager.cpp @@ -1,6 +1,5 @@ // SPDX-FileCopyrightText: 2019 Alexey Andreyev // SPDX-FileCopyrightText: 2019 Kitsune Ral -// // SPDX-License-Identifier: LGPL-2.1-or-later #ifdef Quotient_E2EE_ENABLED diff --git a/lib/encryptionmanager.h b/lib/encryptionmanager.h index 0f507337..714f95fd 100644 --- a/lib/encryptionmanager.h +++ b/lib/encryptionmanager.h @@ -1,5 +1,4 @@ // SPDX-FileCopyrightText: 2019 Alexey Andreyev -// // SPDX-License-Identifier: LGPL-2.1-or-later #ifdef Quotient_E2EE_ENABLED diff --git a/lib/eventitem.cpp b/lib/eventitem.cpp index 9c47e50d..4f1595bc 100644 --- a/lib/eventitem.cpp +++ b/lib/eventitem.cpp @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2018 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "eventitem.h" diff --git a/lib/eventitem.h b/lib/eventitem.h index 2d3d9ef6..1986ba77 100644 --- a/lib/eventitem.h +++ b/lib/eventitem.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2018 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/accountdataevents.h b/lib/events/accountdataevents.h index d0abf577..8cea0ec8 100644 --- a/lib/events/accountdataevents.h +++ b/lib/events/accountdataevents.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2018 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/callanswerevent.cpp b/lib/events/callanswerevent.cpp index f3d0a9a0..be83d9d0 100644 --- a/lib/events/callanswerevent.cpp +++ b/lib/events/callanswerevent.cpp @@ -1,8 +1,6 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Marius Gripsgard - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Marius Gripsgard +// SPDX-FileCopyrightText: 2018 Josip Delic +// SPDX-License-Identifier: LGPL-2.1-or-later #include "callanswerevent.h" diff --git a/lib/events/callanswerevent.h b/lib/events/callanswerevent.h index d7214468..6132cb44 100644 --- a/lib/events/callanswerevent.h +++ b/lib/events/callanswerevent.h @@ -1,8 +1,6 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Marius Gripsgard - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Marius Gripsgard +// SPDX-FileCopyrightText: 2018 Josip Delic +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/callcandidatesevent.cpp b/lib/events/callcandidatesevent.cpp index 9b765064..b87c8e9b 100644 --- a/lib/events/callcandidatesevent.cpp +++ b/lib/events/callcandidatesevent.cpp @@ -1,8 +1,6 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Marius Gripsgard - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Marius Gripsgard +// SPDX-FileCopyrightText: 2018 Josip Delic +// SPDX-License-Identifier: LGPL-2.1-or-later #include "callcandidatesevent.h" diff --git a/lib/events/callcandidatesevent.h b/lib/events/callcandidatesevent.h index ae3bb150..b9de7556 100644 --- a/lib/events/callcandidatesevent.h +++ b/lib/events/callcandidatesevent.h @@ -1,8 +1,7 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Marius Gripsgard - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Marius Gripsgard +// SPDX-FileCopyrightText: 2018 Josip Delic +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/callhangupevent.cpp b/lib/events/callhangupevent.cpp index 45b84cd4..43bc4db0 100644 --- a/lib/events/callhangupevent.cpp +++ b/lib/events/callhangupevent.cpp @@ -1,5 +1,6 @@ /****************************************************************************** * SPDX-FileCopyrightText: 2017 Marius Gripsgard + * SPDX-FileCopyrightText: 2018 Josip Delic * * SPDX-License-Identifier: LGPL-2.1-or-later */ diff --git a/lib/events/callhangupevent.h b/lib/events/callhangupevent.h index 432f72f5..24382ac2 100644 --- a/lib/events/callhangupevent.h +++ b/lib/events/callhangupevent.h @@ -1,8 +1,6 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Marius Gripsgard - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Marius Gripsgard +// SPDX-FileCopyrightText: 2018 Josip Delic +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/callinviteevent.cpp b/lib/events/callinviteevent.cpp index 86478ada..5ea54662 100644 --- a/lib/events/callinviteevent.cpp +++ b/lib/events/callinviteevent.cpp @@ -1,8 +1,6 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Marius Gripsgard - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Marius Gripsgard +// SPDX-FileCopyrightText: 2018 Josip Delic +// SPDX-License-Identifier: LGPL-2.1-or-later #include "callinviteevent.h" diff --git a/lib/events/callinviteevent.h b/lib/events/callinviteevent.h index 304c89ac..d3454c4f 100644 --- a/lib/events/callinviteevent.h +++ b/lib/events/callinviteevent.h @@ -1,8 +1,6 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Marius Gripsgard - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Marius Gripsgard +// SPDX-FileCopyrightText: 2018 Josip Delic +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/directchatevent.cpp b/lib/events/directchatevent.cpp index 39d11072..0ee1f7b0 100644 --- a/lib/events/directchatevent.cpp +++ b/lib/events/directchatevent.cpp @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2018 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "directchatevent.h" diff --git a/lib/events/directchatevent.h b/lib/events/directchatevent.h index 373e36dc..e2143779 100644 --- a/lib/events/directchatevent.h +++ b/lib/events/directchatevent.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2018 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/encryptedevent.cpp b/lib/events/encryptedevent.cpp index dc9eaf2d..0290f973 100644 --- a/lib/events/encryptedevent.cpp +++ b/lib/events/encryptedevent.cpp @@ -1,5 +1,4 @@ // SPDX-FileCopyrightText: 2019 Alexey Andreyev -// // SPDX-License-Identifier: LGPL-2.1-or-later #include "encryptedevent.h" diff --git a/lib/events/encryptedevent.h b/lib/events/encryptedevent.h index 9de08b00..eb7123eb 100644 --- a/lib/events/encryptedevent.h +++ b/lib/events/encryptedevent.h @@ -1,5 +1,4 @@ // SPDX-FileCopyrightText: 2019 Alexey Andreyev -// // SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/encryptionevent.cpp b/lib/events/encryptionevent.cpp index f1bde621..490a5e8a 100644 --- a/lib/events/encryptionevent.cpp +++ b/lib/events/encryptionevent.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2017 Kitsune Ral +// SPDX-FileCopyrightText: 2019 Alexey Andreyev +// SPDX-License-Identifier: LGPL-2.1-or-later + #include "encryptionevent.h" #include "e2ee.h" diff --git a/lib/events/encryptionevent.h b/lib/events/encryptionevent.h index 3431ddd8..f9bbab12 100644 --- a/lib/events/encryptionevent.h +++ b/lib/events/encryptionevent.h @@ -1,8 +1,6 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Kitsune Ral +// SPDX-FileCopyrightText: 2019 Alexey Andreyev +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/event.cpp b/lib/events/event.cpp index 97edb4e0..3d66ab55 100644 --- a/lib/events/event.cpp +++ b/lib/events/event.cpp @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2015 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "event.h" diff --git a/lib/events/event.h b/lib/events/event.h index c5752a7a..f8f8311d 100644 --- a/lib/events/event.h +++ b/lib/events/event.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2015 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/eventcontent.cpp b/lib/events/eventcontent.cpp index 18b1b94b..b249b160 100644 --- a/lib/events/eventcontent.cpp +++ b/lib/events/eventcontent.cpp @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "eventcontent.h" diff --git a/lib/events/eventcontent.h b/lib/events/eventcontent.h index e247adbf..60d1f7b7 100644 --- a/lib/events/eventcontent.h +++ b/lib/events/eventcontent.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/eventloader.h b/lib/events/eventloader.h index 0d95daf5..978668f2 100644 --- a/lib/events/eventloader.h +++ b/lib/events/eventloader.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2018 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/reactionevent.cpp b/lib/events/reactionevent.cpp index 9b43e372..b53fffd6 100644 --- a/lib/events/reactionevent.cpp +++ b/lib/events/reactionevent.cpp @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2019 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2019 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "reactionevent.h" diff --git a/lib/events/reactionevent.h b/lib/events/reactionevent.h index 09166b24..777905f2 100644 --- a/lib/events/reactionevent.h +++ b/lib/events/reactionevent.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2019 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2019 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/receiptevent.cpp b/lib/events/receiptevent.cpp index b6f0fcdd..4185d92d 100644 --- a/lib/events/receiptevent.cpp +++ b/lib/events/receiptevent.cpp @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2016 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later /* Example of a Receipt Event: diff --git a/lib/events/receiptevent.h b/lib/events/receiptevent.h index ec297a6c..4feec9ea 100644 --- a/lib/events/receiptevent.h +++ b/lib/events/receiptevent.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2016 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/redactionevent.cpp b/lib/events/redactionevent.cpp deleted file mode 100644 index 5889773c..00000000 --- a/lib/events/redactionevent.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// SPDX-FileCopyrightText: 2019 Kitsune Ral -// -// SPDX-License-Identifier: CC0-1.0 - -#include "redactionevent.h" diff --git a/lib/events/redactionevent.h b/lib/events/redactionevent.h index 320db6f2..ed560331 100644 --- a/lib/events/redactionevent.h +++ b/lib/events/redactionevent.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/roomavatarevent.h b/lib/events/roomavatarevent.h index 649412e8..a4257895 100644 --- a/lib/events/roomavatarevent.h +++ b/lib/events/roomavatarevent.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/roomcanonicalaliasevent.h b/lib/events/roomcanonicalaliasevent.h index eda94d2d..bb8654e5 100644 --- a/lib/events/roomcanonicalaliasevent.h +++ b/lib/events/roomcanonicalaliasevent.h @@ -1,8 +1,6 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2020 QMatrixClient project - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2020 Ram Nad +// SPDX-FileCopyrightText: 2020 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/roomcreateevent.cpp b/lib/events/roomcreateevent.cpp index 3d9ec4a3..6558bade 100644 --- a/lib/events/roomcreateevent.cpp +++ b/lib/events/roomcreateevent.cpp @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2019 QMatrixClient project - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2019 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "roomcreateevent.h" diff --git a/lib/events/roomcreateevent.h b/lib/events/roomcreateevent.h index 8328d38a..05e623ed 100644 --- a/lib/events/roomcreateevent.h +++ b/lib/events/roomcreateevent.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2019 QMatrixClient project - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2019 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/roomevent.cpp b/lib/events/roomevent.cpp index 2b6ac2be..4fec9d2b 100644 --- a/lib/events/roomevent.cpp +++ b/lib/events/roomevent.cpp @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2018 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "roomevent.h" diff --git a/lib/events/roomevent.h b/lib/events/roomevent.h index 3fafecfd..fea509c0 100644 --- a/lib/events/roomevent.h +++ b/lib/events/roomevent.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2018 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/roomkeyevent.cpp b/lib/events/roomkeyevent.cpp index 66580430..332be3f7 100644 --- a/lib/events/roomkeyevent.cpp +++ b/lib/events/roomkeyevent.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2019 Alexey Andreyev +// SPDX-License-Identifier: LGPL-2.1-or-later + #include "roomkeyevent.h" using namespace Quotient; diff --git a/lib/events/roomkeyevent.h b/lib/events/roomkeyevent.h index b8cd2eae..14e80324 100644 --- a/lib/events/roomkeyevent.h +++ b/lib/events/roomkeyevent.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2019 Alexey Andreyev +// SPDX-License-Identifier: LGPL-2.1-or-later + #pragma once #include "event.h" diff --git a/lib/events/roommemberevent.cpp b/lib/events/roommemberevent.cpp index d093286c..9634ca3a 100644 --- a/lib/events/roommemberevent.cpp +++ b/lib/events/roommemberevent.cpp @@ -1,8 +1,6 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2015 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Kitsune Ral +// SPDX-FileCopyrightText: 2019 Karol Kosek +// SPDX-License-Identifier: LGPL-2.1-or-later #include "roommemberevent.h" diff --git a/lib/events/roommemberevent.h b/lib/events/roommemberevent.h index b7a7c9df..f2fbe689 100644 --- a/lib/events/roommemberevent.h +++ b/lib/events/roommemberevent.h @@ -1,8 +1,7 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2015 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2015 Felix Rohrbach +// SPDX-FileCopyrightText: 2017 Kitsune Ral +// SPDX-FileCopyrightText: 2019 Karol Kosek +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/roommessageevent.cpp b/lib/events/roommessageevent.cpp index 19d460b8..14824277 100644 --- a/lib/events/roommessageevent.cpp +++ b/lib/events/roommessageevent.cpp @@ -1,8 +1,7 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2015 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2015 Felix Rohrbach +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-FileCopyrightText: 2017 Roman Plášil +// SPDX-License-Identifier: LGPL-2.1-or-later #include "roommessageevent.h" diff --git a/lib/events/roommessageevent.h b/lib/events/roommessageevent.h index ebc9d564..8303ce4e 100644 --- a/lib/events/roommessageevent.h +++ b/lib/events/roommessageevent.h @@ -1,8 +1,7 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2015 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2015 Felix Rohrbach +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-FileCopyrightText: 2017 Roman Plášil +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/roompowerlevelsevent.cpp b/lib/events/roompowerlevelsevent.cpp index 0a401752..8d262ddf 100644 --- a/lib/events/roompowerlevelsevent.cpp +++ b/lib/events/roompowerlevelsevent.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2019 Black Hat +// SPDX-License-Identifier: LGPL-2.1-or-later + #include "roompowerlevelsevent.h" #include diff --git a/lib/events/roompowerlevelsevent.h b/lib/events/roompowerlevelsevent.h index b832230e..0346fc0d 100644 --- a/lib/events/roompowerlevelsevent.h +++ b/lib/events/roompowerlevelsevent.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2019 Black Hat +// SPDX-License-Identifier: LGPL-2.1-or-later + #pragma once #include "eventcontent.h" diff --git a/lib/events/roomtombstoneevent.cpp b/lib/events/roomtombstoneevent.cpp index 163e1d3a..080d269c 100644 --- a/lib/events/roomtombstoneevent.cpp +++ b/lib/events/roomtombstoneevent.cpp @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2019 QMatrixClient project - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2019 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "roomtombstoneevent.h" diff --git a/lib/events/roomtombstoneevent.h b/lib/events/roomtombstoneevent.h index 8d50aba0..30e53738 100644 --- a/lib/events/roomtombstoneevent.h +++ b/lib/events/roomtombstoneevent.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2019 QMatrixClient project - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2019 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/simplestateevents.h b/lib/events/simplestateevents.h index 58ba3b5a..d6261a8f 100644 --- a/lib/events/simplestateevents.h +++ b/lib/events/simplestateevents.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/stateevent.cpp b/lib/events/stateevent.cpp index 7bde12bb..42fc9054 100644 --- a/lib/events/stateevent.cpp +++ b/lib/events/stateevent.cpp @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2018 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "stateevent.h" diff --git a/lib/events/stateevent.h b/lib/events/stateevent.h index 0db37767..1415f709 100644 --- a/lib/events/stateevent.h +++ b/lib/events/stateevent.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2018 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/events/typingevent.cpp b/lib/events/typingevent.cpp index 7d3f71e5..e97e978f 100644 --- a/lib/events/typingevent.cpp +++ b/lib/events/typingevent.cpp @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2015 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "typingevent.h" diff --git a/lib/events/typingevent.h b/lib/events/typingevent.h index 8ca4f8e4..7456100a 100644 --- a/lib/events/typingevent.h +++ b/lib/events/typingevent.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2015 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index a0c88581..48c2996d 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -1,8 +1,6 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2015 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2015 Felix Rohrbach +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "basejob.h" diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 3165edd3..ca91a781 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -1,8 +1,6 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2015 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2015 Felix Rohrbach +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp index 0011a97c..0b0531ad 100644 --- a/lib/jobs/downloadfilejob.cpp +++ b/lib/jobs/downloadfilejob.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later + #include "downloadfilejob.h" #include diff --git a/lib/jobs/downloadfilejob.h b/lib/jobs/downloadfilejob.h index e00fd9e4..0752af89 100644 --- a/lib/jobs/downloadfilejob.h +++ b/lib/jobs/downloadfilejob.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later + #pragma once #include "csapi/content-repo.h" diff --git a/lib/jobs/mediathumbnailjob.cpp b/lib/jobs/mediathumbnailjob.cpp index fbea8797..7dbf4ab3 100644 --- a/lib/jobs/mediathumbnailjob.cpp +++ b/lib/jobs/mediathumbnailjob.cpp @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2016 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "mediathumbnailjob.h" diff --git a/lib/jobs/mediathumbnailjob.h b/lib/jobs/mediathumbnailjob.h index cb55a0b0..3183feb1 100644 --- a/lib/jobs/mediathumbnailjob.h +++ b/lib/jobs/mediathumbnailjob.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2016 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/jobs/requestdata.cpp b/lib/jobs/requestdata.cpp index cec15954..047e2920 100644 --- a/lib/jobs/requestdata.cpp +++ b/lib/jobs/requestdata.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later + #include "requestdata.h" #include diff --git a/lib/jobs/requestdata.h b/lib/jobs/requestdata.h index 2a227646..4958e0f9 100644 --- a/lib/jobs/requestdata.h +++ b/lib/jobs/requestdata.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2018 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/jobs/syncjob.cpp b/lib/jobs/syncjob.cpp index beb0a535..59a34ef3 100644 --- a/lib/jobs/syncjob.cpp +++ b/lib/jobs/syncjob.cpp @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2016 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "syncjob.h" diff --git a/lib/jobs/syncjob.h b/lib/jobs/syncjob.h index a7d10ed8..830a7c71 100644 --- a/lib/jobs/syncjob.h +++ b/lib/jobs/syncjob.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2016 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/joinstate.h b/lib/joinstate.h index 1a7b1add..805ce73a 100644 --- a/lib/joinstate.h +++ b/lib/joinstate.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2015 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/logging.cpp b/lib/logging.cpp index 3f757393..af229684 100644 --- a/lib/logging.cpp +++ b/lib/logging.cpp @@ -1,8 +1,6 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Elvis Angelaccio - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Elvis Angelaccio +// SPDX-FileCopyrightText: 2017 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "logging.h" diff --git a/lib/logging.h b/lib/logging.h index 21d05d8b..432ed16f 100644 --- a/lib/logging.h +++ b/lib/logging.h @@ -1,8 +1,6 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Elvis Angelaccio +// SPDX-FileCopyrightText: 2017 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp index 43a8287a..a94ead34 100644 --- a/lib/networkaccessmanager.cpp +++ b/lib/networkaccessmanager.cpp @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2018 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "networkaccessmanager.h" diff --git a/lib/networkaccessmanager.h b/lib/networkaccessmanager.h index 6075767a..47729a1b 100644 --- a/lib/networkaccessmanager.h +++ b/lib/networkaccessmanager.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2018 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/networksettings.cpp b/lib/networksettings.cpp index db16034a..ce46ce5f 100644 --- a/lib/networksettings.cpp +++ b/lib/networksettings.cpp @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "networksettings.h" diff --git a/lib/networksettings.h b/lib/networksettings.h index 31602734..df11a9c8 100644 --- a/lib/networksettings.h +++ b/lib/networksettings.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2017 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2017 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/qt_connection_util.h b/lib/qt_connection_util.h index 158d7a40..c6fa037a 100644 --- a/lib/qt_connection_util.h +++ b/lib/qt_connection_util.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2019 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2019 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/quotient_common.h b/lib/quotient_common.h index e2384f12..22fdbe94 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -1,5 +1,4 @@ // SPDX-FileCopyrightText: 2019 Kitsune Ral -// // SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/room.cpp b/lib/room.cpp index bc89464d..2e8641aa 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -1,8 +1,11 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2015 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-FileCopyrightText: 2017 Roman Plášil +// SPDX-FileCopyrightText: 2017 Marius Gripsgard +// SPDX-FileCopyrightText: 2018 Josip Delic +// SPDX-FileCopyrightText: 2018 Black Hat +// SPDX-FileCopyrightText: 2019 Alexey Andreyev +// SPDX-FileCopyrightText: 2020 Ram Nad +// SPDX-License-Identifier: LGPL-2.1-or-later #include "room.h" diff --git a/lib/room.h b/lib/room.h index c9205e9c..a8275ce9 100644 --- a/lib/room.h +++ b/lib/room.h @@ -1,8 +1,11 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2015 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-FileCopyrightText: 2017 Roman Plášil +// SPDX-FileCopyrightText: 2017 Marius Gripsgard +// SPDX-FileCopyrightText: 2018 Josip Delic +// SPDX-FileCopyrightText: 2018 Black Hat +// SPDX-FileCopyrightText: 2019 Alexey Andreyev +// SPDX-FileCopyrightText: 2020 Ram Nad +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/settings.cpp b/lib/settings.cpp index dd086d9c..703f4320 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later + #include "settings.h" #include "logging.h" diff --git a/lib/settings.h b/lib/settings.h index badabec2..84c54802 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2016 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/ssosession.cpp b/lib/ssosession.cpp index 3c6ec48b..a1d27504 100644 --- a/lib/ssosession.cpp +++ b/lib/ssosession.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2020 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later + #include "ssosession.h" #include "connection.h" diff --git a/lib/ssosession.h b/lib/ssosession.h index 5845cd4d..72dd60c4 100644 --- a/lib/ssosession.h +++ b/lib/ssosession.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2020 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later + #pragma once #include diff --git a/lib/syncdata.cpp b/lib/syncdata.cpp index f67ab6c7..adcba5cd 100644 --- a/lib/syncdata.cpp +++ b/lib/syncdata.cpp @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2018 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "syncdata.h" diff --git a/lib/syncdata.h b/lib/syncdata.h index d9868e46..e69bac17 100644 --- a/lib/syncdata.h +++ b/lib/syncdata.h @@ -1,8 +1,5 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2018 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/uri.cpp b/lib/uri.cpp index e0912eb6..4b171e79 100644 --- a/lib/uri.cpp +++ b/lib/uri.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2020 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later + #include "uri.h" #include "logging.h" diff --git a/lib/uri.h b/lib/uri.h index 270766dd..d8b892b6 100644 --- a/lib/uri.h +++ b/lib/uri.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2020 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later + #pragma once #include "quotient_common.h" diff --git a/lib/uriresolver.cpp b/lib/uriresolver.cpp index 27360bcc..287e0552 100644 --- a/lib/uriresolver.cpp +++ b/lib/uriresolver.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2020 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later + #include "uriresolver.h" #include "connection.h" diff --git a/lib/uriresolver.h b/lib/uriresolver.h index 428ce04c..f290e58b 100644 --- a/lib/uriresolver.h +++ b/lib/uriresolver.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2020 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later + #pragma once #include "uri.h" diff --git a/lib/user.cpp b/lib/user.cpp index 9c2b76b5..bed7be3a 100644 --- a/lib/user.cpp +++ b/lib/user.cpp @@ -1,8 +1,6 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2015 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2015 Felix Rohrbach +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "user.h" diff --git a/lib/user.h b/lib/user.h index d5c892ed..f831865e 100644 --- a/lib/user.h +++ b/lib/user.h @@ -1,8 +1,6 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2015 Felix Rohrbach - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2015 Felix Rohrbach +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/lib/util.cpp b/lib/util.cpp index 14492ba6..904bfd5a 100644 --- a/lib/util.cpp +++ b/lib/util.cpp @@ -1,8 +1,6 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2018 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-FileCopyrightText: 2019 Alexey Andreyev +// SPDX-License-Identifier: LGPL-2.1-or-later #include "util.h" diff --git a/lib/util.h b/lib/util.h index 7547a75a..cb0ff44a 100644 --- a/lib/util.h +++ b/lib/util.h @@ -1,8 +1,6 @@ -/****************************************************************************** - * SPDX-FileCopyrightText: 2016 Kitsune Ral - * - * SPDX-License-Identifier: LGPL-2.1-or-later - */ +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-FileCopyrightText: 2019 Alexey Andreyev +// SPDX-License-Identifier: LGPL-2.1-or-later #pragma once diff --git a/tests/quotest.cpp b/tests/quotest.cpp index 98c01cfc..5098bc02 100644 --- a/tests/quotest.cpp +++ b/tests/quotest.cpp @@ -1,3 +1,5 @@ +// SPDX-FileCopyrightText: 2016 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later #include "connection.h" #include "room.h" -- cgit v1.2.3 From c05b5c2b79f9ab301fee587ee781b9c8e18b8a2f Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Fri, 16 Jul 2021 20:03:06 +0200 Subject: MembershipType -> Membership, also used for JoinState Instead of being defined independently, JoinState now uses values from the Membership enumeration (former MemberEventContent::MembershipType) that was moved to quotient_common.h for that purpose. Both enumerations gained a Q_FLAG_NS decoration and operator<< overrides that strip "Quotient::" prefix when dumping member/join state values to the log - obviating toCString(JoinState) along the way. Quotient::MembershipType alias is deprecated from now. --- CMakeLists.txt | 6 +--- lib/connection.cpp | 4 +-- lib/connection.h | 1 - lib/events/roommemberevent.cpp | 65 ++++++++++++++++++++-------------------- lib/events/roommemberevent.h | 26 ++++++++-------- lib/joinstate.h | 32 -------------------- lib/quotient_common.cpp | 45 ++++++++++++++++++++++++++++ lib/quotient_common.h | 67 +++++++++++++++++++++++++++++++++++++----- lib/room.cpp | 49 ++++++++++++++++-------------- lib/room.h | 9 +++++- lib/syncdata.h | 2 +- lib/user.cpp | 2 +- 12 files changed, 190 insertions(+), 118 deletions(-) delete mode 100644 lib/joinstate.h create mode 100644 lib/quotient_common.cpp (limited to 'lib/quotient_common.h') diff --git a/CMakeLists.txt b/CMakeLists.txt index deb50aea..49105389 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,11 +122,7 @@ endif () # Set up source files list(APPEND lib_SRCS - # This .h is special in that it declares a Q_NAMESPACE but has no .cpp - # where staticMetaObject for that namespace would be defined; passing it - # to add_library (see below) puts it on the automoc radar, producing - # a compilation unit with the needed definition. - lib/quotient_common.h + lib/quotient_common.cpp lib/networkaccessmanager.cpp lib/connectiondata.cpp lib/connection.cpp diff --git a/lib/connection.cpp b/lib/connection.cpp index e076957a..7dd04aaa 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -640,7 +640,7 @@ void Connection::Private::consumeRoomData(SyncDataList&& roomDataList, } qWarning(MAIN) << "Room" << roomData.roomId << "has just been forgotten but /sync returned it in" - << toCString(roomData.joinState) + << roomData.joinState << "state - suspiciously fast turnaround"; } if (auto* r = q->provideRoom(roomData.roomId, roomData.joinState)) { @@ -1356,7 +1356,7 @@ void Connection::Private::removeRoom(const QString& roomId) for (auto f : { false, true }) if (auto r = roomMap.take({ roomId, f })) { qCDebug(MAIN) << "Room" << r->objectName() << "in state" - << toCString(r->joinState()) << "will be deleted"; + << r->joinState() << "will be deleted"; emit r->beforeDestruction(r); r->deleteLater(); } diff --git a/lib/connection.h b/lib/connection.h index 0d22d01f..a7a071f3 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -6,7 +6,6 @@ #pragma once #include "ssosession.h" -#include "joinstate.h" #include "qt_connection_util.h" #include "quotient_common.h" diff --git a/lib/events/roommemberevent.cpp b/lib/events/roommemberevent.cpp index 9634ca3a..8a6bddd8 100644 --- a/lib/events/roommemberevent.cpp +++ b/lib/events/roommemberevent.cpp @@ -7,27 +7,26 @@ #include "converters.h" #include "logging.h" -#include - -static const std::array membershipStrings = { - { QStringLiteral("invite"), QStringLiteral("join"), QStringLiteral("knock"), - QStringLiteral("leave"), QStringLiteral("ban") } -}; +#include namespace Quotient { template <> -struct JsonConverter { - static MembershipType load(const QJsonValue& jv) +struct JsonConverter { + static Membership load(const QJsonValue& jv) { - const auto& membershipString = jv.toString(); - for (auto it = membershipStrings.begin(); it != membershipStrings.end(); - ++it) - if (membershipString == *it) - return MembershipType(it - membershipStrings.begin()); - - if (!membershipString.isEmpty()) - qCWarning(EVENTS) << "Unknown MembershipType: " << membershipString; - return MembershipType::Undefined; + const auto& ms = jv.toString(); + if (ms.isEmpty()) + { + qCWarning(EVENTS) << "Empty member state:" << ms; + return Membership::Invalid; + } + const auto it = + std::find(MembershipStrings.begin(), MembershipStrings.end(), ms); + if (it != MembershipStrings.end()) + return Membership(1U << (it - MembershipStrings.begin())); + + qCWarning(EVENTS) << "Unknown Membership value: " << ms; + return Membership::Invalid; } }; } // namespace Quotient @@ -35,7 +34,7 @@ struct JsonConverter { using namespace Quotient; MemberEventContent::MemberEventContent(const QJsonObject& json) - : membership(fromJson(json["membership"_ls])) + : membership(fromJson(json["membership"_ls])) , isDirect(json["is_direct"_ls].toBool()) , displayName(fromJson>(json["displayname"_ls])) , avatarUrl(fromJson>(json["avatar_url"_ls])) @@ -48,10 +47,12 @@ MemberEventContent::MemberEventContent(const QJsonObject& json) void MemberEventContent::fillJson(QJsonObject* o) const { Q_ASSERT(o); - Q_ASSERT_X(membership != MembershipType::Undefined, __FUNCTION__, - "The key 'membership' must be explicit in MemberEventContent"); - if (membership != MembershipType::Undefined) - o->insert(QStringLiteral("membership"), membershipStrings[membership]); + if (membership != Membership::Invalid) + o->insert( + QStringLiteral("membership"), + MembershipStrings[qCountTrailingZeroBits( + std::underlying_type_t(membership)) + + 1]); if (displayName) o->insert(QStringLiteral("displayname"), *displayName); if (avatarUrl && avatarUrl->isValid()) @@ -67,37 +68,37 @@ bool RoomMemberEvent::changesMembership() const bool RoomMemberEvent::isInvite() const { - return membership() == MembershipType::Invite && changesMembership(); + return membership() == Membership::Invite && changesMembership(); } bool RoomMemberEvent::isRejectedInvite() const { - return membership() == MembershipType::Leave && prevContent() - && prevContent()->membership == MembershipType::Invite; + return membership() == Membership::Leave && prevContent() + && prevContent()->membership == Membership::Invite; } bool RoomMemberEvent::isJoin() const { - return membership() == MembershipType::Join && changesMembership(); + return membership() == Membership::Join && changesMembership(); } bool RoomMemberEvent::isLeave() const { - return membership() == MembershipType::Leave && prevContent() + return membership() == Membership::Leave && prevContent() && prevContent()->membership != membership() - && prevContent()->membership != MembershipType::Ban - && prevContent()->membership != MembershipType::Invite; + && prevContent()->membership != Membership::Ban + && prevContent()->membership != Membership::Invite; } bool RoomMemberEvent::isBan() const { - return membership() == MembershipType::Ban && changesMembership(); + return membership() == Membership::Ban && changesMembership(); } bool RoomMemberEvent::isUnban() const { - return membership() == MembershipType::Leave && prevContent() - && prevContent()->membership == MembershipType::Ban; + return membership() == Membership::Leave && prevContent() + && prevContent()->membership == Membership::Ban; } bool RoomMemberEvent::isRename() const diff --git a/lib/events/roommemberevent.h b/lib/events/roommemberevent.h index f2fbe689..f3047159 100644 --- a/lib/events/roommemberevent.h +++ b/lib/events/roommemberevent.h @@ -7,23 +7,21 @@ #include "eventcontent.h" #include "stateevent.h" +#include "quotient_common.h" namespace Quotient { class MemberEventContent : public EventContent::Base { public: - enum MembershipType : unsigned char { - Invite = 0, - Join, - Knock, - Leave, - Ban, - Undefined - }; + using MembershipType + [[deprecated("Use Quotient::Membership instead")]] = Membership; - explicit MemberEventContent(MembershipType mt = Join) : membership(mt) {} + explicit MemberEventContent(Membership ms = Membership::Join) + : membership(ms) + {} explicit MemberEventContent(const QJsonObject& json); - MembershipType membership; + Membership membership; + /// (Only for invites) Whether the invite is to a direct chat bool isDirect = false; Omittable displayName; Omittable avatarUrl; @@ -33,15 +31,15 @@ protected: void fillJson(QJsonObject* o) const override; }; -using MembershipType = MemberEventContent::MembershipType; +using MembershipType [[deprecated("Use Membership instead")]] = Membership; class RoomMemberEvent : public StateEvent { Q_GADGET public: DEFINE_EVENT_TYPEID("m.room.member", RoomMemberEvent) - using MembershipType = MemberEventContent::MembershipType; - Q_ENUM(MembershipType) + using MembershipType + [[deprecated("Use Quotient::Membership instead")]] = Membership; explicit RoomMemberEvent(const QJsonObject& obj) : StateEvent(typeId(), obj) {} @@ -65,7 +63,7 @@ public: : StateEvent(type, fullJson) {} - MembershipType membership() const { return content().membership; } + Membership membership() const { return content().membership; } QString userId() const { return stateKey(); } bool isDirect() const { return content().isDirect; } Omittable newDisplayName() const { return content().displayName; } diff --git a/lib/joinstate.h b/lib/joinstate.h deleted file mode 100644 index 805ce73a..00000000 --- a/lib/joinstate.h +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-FileCopyrightText: 2016 Kitsune Ral -// SPDX-License-Identifier: LGPL-2.1-or-later - -#pragma once - -#include - -#include - -namespace Quotient { -enum class JoinState : unsigned int { - Join = 0x1, - Invite = 0x2, - Leave = 0x4, -}; - -Q_DECLARE_FLAGS(JoinStates, JoinState) - -// We cannot use Q_ENUM outside of a Q_OBJECT and besides, we want -// to use strings that match respective JSON keys. -static const std::array JoinStateStrings { { "join", "invite", - "leave" } }; - -inline const char* toCString(JoinState js) -{ - size_t state = size_t(js), index = 0; - while (state >>= 1u) - ++index; - return JoinStateStrings[index]; -} -} // namespace Quotient -Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::JoinStates) diff --git a/lib/quotient_common.cpp b/lib/quotient_common.cpp new file mode 100644 index 00000000..805070d1 --- /dev/null +++ b/lib/quotient_common.cpp @@ -0,0 +1,45 @@ +#include "quotient_common.h" + +#include + +using namespace Quotient; + +template +inline QDebug suppressScopeAndDump(QDebug dbg, Enum e) +{ + // Suppress "Quotient::" prefix + QDebugStateSaver _dss(dbg); + dbg.setVerbosity(QDebug::MinimumVerbosity); + return qt_QMetaEnum_debugOperator(dbg, std::underlying_type_t(e), + qt_getEnumMetaObject(e), + qt_getEnumName(e)); +} + +template +inline QDebug suppressScopeAndDump(QDebug dbg, const QFlags& f) +{ + // Suppress "Quotient::" prefix + QDebugStateSaver _dss(dbg); + dbg.setVerbosity(QDebug::MinimumVerbosity); + return qt_QMetaEnum_flagDebugOperator_helper(dbg, f); +} + +QDebug operator<<(QDebug dbg, Membership m) +{ + return suppressScopeAndDump(dbg, m); +} + +QDebug operator<<(QDebug dbg, MembershipMask mm) +{ + return suppressScopeAndDump(dbg, mm) << ")"; +} + +QDebug operator<<(QDebug dbg, JoinState js) +{ + return suppressScopeAndDump(dbg, js); +} + +QDebug operator<<(QDebug dbg, JoinStates jss) +{ + return suppressScopeAndDump(dbg, jss) << ")"; +} diff --git a/lib/quotient_common.h b/lib/quotient_common.h index 22fdbe94..789128cf 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -8,15 +8,62 @@ namespace Quotient { Q_NAMESPACE -/** Enumeration with flags defining the network job running policy - * So far only background/foreground flags are available. - * - * \sa Connection::callApi, Connection::run - */ +// TODO: code like this should be generated from the CS API definition + +//! \brief Membership states +//! +//! These are used for member events. The names here are case-insensitively +//! equal to state names used on the wire. +//! \sa MemberEventContent, RoomMemberEvent +enum class Membership : unsigned int { + // Specific power-of-2 values (1,2,4,...) are important here as syncdata.cpp + // depends on that, as well as Join being the first in line + Invalid = 0x0, + Join = 0x1, + Leave = 0x2, + Invite = 0x4, + Knock = 0x8, + Ban = 0x10, + Undefined = Invalid +}; +Q_DECLARE_FLAGS(MembershipMask, Membership) +Q_FLAG_NS(MembershipMask) + +constexpr inline std::array MembershipStrings = { + // The order MUST be the same as the order in the original enum + "join", "leave", "invite", "knock", "ban" +}; + +//! \brief Local user join-state names +//! +//! This represents a subset of Membership values that may arrive as the local +//! user's state grouping for the sync response. +//! \sa SyncData +enum class JoinState : std::underlying_type_t { + Invalid = std::underlying_type_t(Membership::Invalid), + Join = std::underlying_type_t(Membership::Join), + Leave = std::underlying_type_t(Membership::Leave), + Invite = std::underlying_type_t(Membership::Invite), + Knock = std::underlying_type_t(Membership::Knock), +}; +Q_DECLARE_FLAGS(JoinStates, JoinState) +Q_FLAG_NS(JoinStates) + +constexpr inline std::array JoinStateStrings { + MembershipStrings[0], MembershipStrings[1], MembershipStrings[2], + MembershipStrings[3] /* same as MembershipStrings, sans "ban" */ +}; + +//! \brief Network job running policy flags +//! +//! So far only background/foreground flags are available. +//! \sa Connection::callApi, Connection::run enum RunningPolicy { ForegroundRequest = 0x0, BackgroundRequest = 0x1 }; Q_ENUM_NS(RunningPolicy) +//! \brief The result of URI resolution using UriResolver +//! \sa UriResolver enum UriResolveResult : short { StillResolving = -1, UriResolved = 0, @@ -28,5 +75,11 @@ enum UriResolveResult : short { Q_ENUM_NS(UriResolveResult) } // namespace Quotient -/// \deprecated Use namespace Quotient instead -namespace QMatrixClient = Quotient; +Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::MembershipMask) +Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::JoinStates) + +class QDebug; +QDebug operator<<(QDebug dbg, Quotient::Membership m); +QDebug operator<<(QDebug dbg, Quotient::MembershipMask m); +QDebug operator<<(QDebug dbg, Quotient::JoinState js); +QDebug operator<<(QDebug dbg, Quotient::JoinStates js); diff --git a/lib/room.cpp b/lib/room.cpp index 6b729b8f..54c67c2f 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -460,7 +460,7 @@ Room::Room(Connection* connection, QString id, JoinState initialJoinState) emit baseStateLoaded(); return this == r; // loadedRoomState fires only once per room }); - qCDebug(STATE) << "New" << toCString(initialJoinState) << "Room:" << id; + qCDebug(STATE) << "New" << initialJoinState << "Room:" << id; } Room::~Room() { delete d; } @@ -603,6 +603,11 @@ JoinState Room::memberJoinState(User* user) const : JoinState::Leave; } +Membership Room::memberState(User* user) const +{ + return d->getCurrentState(user->id())->membership(); +} + JoinState Room::joinState() const { return d->joinState; } void Room::setJoinState(JoinState state) @@ -611,8 +616,8 @@ void Room::setJoinState(JoinState state) if (state == oldState) return; d->joinState = state; - qCDebug(STATE) << "Room" << id() << "changed state: " << int(oldState) - << "->" << int(state); + qCDebug(STATE) << "Room" << id() << "changed state: " << oldState + << "->" << state; emit changed(Change::JoinStateChange); emit joinStateChanged(oldState, state); } @@ -2513,16 +2518,16 @@ Room::Changes Room::processStateEvent(const RoomEvent& e) return false; // Stay low and hope for the best... } const auto prevMembership = oldRme ? oldRme->membership() - : MembershipType::Leave; + : Membership::Leave; switch (prevMembership) { - case MembershipType::Invite: + case Membership::Invite: if (rme.membership() != prevMembership) { d->usersInvited.removeOne(u); Q_ASSERT(!d->usersInvited.contains(u)); } break; - case MembershipType::Join: - if (rme.membership() == MembershipType::Join) { + case Membership::Join: + if (rme.membership() == Membership::Join) { // rename/avatar change or no-op if (rme.newDisplayName()) { emit memberAboutToRename(u, *rme.newDisplayName()); @@ -2536,7 +2541,7 @@ Room::Changes Room::processStateEvent(const RoomEvent& e) return false; } } else { - if (rme.membership() == MembershipType::Invite) + if (rme.membership() == Membership::Invite) qCWarning(MAIN) << "Membership change from Join to Invite:" << rme; // whatever the new membership, it's no more Join @@ -2544,16 +2549,16 @@ Room::Changes Room::processStateEvent(const RoomEvent& e) emit userRemoved(u); } break; - case MembershipType::Ban: - case MembershipType::Knock: - case MembershipType::Leave: - if (rme.membership() == MembershipType::Invite - || rme.membership() == MembershipType::Join) { + case Membership::Ban: + case Membership::Knock: + case Membership::Leave: + if (rme.membership() == Membership::Invite + || rme.membership() == Membership::Join) { d->membersLeft.removeOne(u); Q_ASSERT(!d->membersLeft.contains(u)); } break; - case MembershipType::Undefined: + case Membership::Undefined: ; // A warning will be dropped in the post-processing block below } return true; @@ -2636,10 +2641,10 @@ Room::Changes Room::processStateEvent(const RoomEvent& e) static_cast(oldStateEvent); const auto prevMembership = oldMemberEvent ? oldMemberEvent->membership() - : MembershipType::Leave; + : Membership::Leave; switch (evt.membership()) { - case MembershipType::Join: - if (prevMembership != MembershipType::Join) { + case Membership::Join: + if (prevMembership != Membership::Join) { d->insertMemberIntoMap(u); emit userAdded(u); } else { @@ -2651,19 +2656,19 @@ Room::Changes Room::processStateEvent(const RoomEvent& e) emit memberAvatarChanged(u); } break; - case MembershipType::Invite: + case Membership::Invite: if (!d->usersInvited.contains(u)) d->usersInvited.push_back(u); if (u == localUser() && evt.isDirect()) connection()->addToDirectChats(this, user(evt.senderId())); break; - case MembershipType::Knock: - case MembershipType::Ban: - case MembershipType::Leave: + case Membership::Knock: + case Membership::Ban: + case Membership::Leave: if (!d->membersLeft.contains(u)) d->membersLeft.append(u); break; - case MembershipType::Undefined: + case Membership::Undefined: qCWarning(MEMBERS) << "Ignored undefined membership type"; } return MembersChange; diff --git a/lib/room.h b/lib/room.h index d71bff9c..cdbfe58f 100644 --- a/lib/room.h +++ b/lib/room.h @@ -11,7 +11,7 @@ #include "connection.h" #include "eventitem.h" -#include "joinstate.h" +#include "quotient_common.h" #include "csapi/message_pagination.h" @@ -245,6 +245,8 @@ public: /** * \brief Check the join state of a given user in this room * + * \deprecated Use memberState and check against a mask + * * \note Banned and invited users are not tracked separately for now (Leave * will be returned for them). * @@ -252,6 +254,11 @@ public: */ Q_INVOKABLE Quotient::JoinState memberJoinState(Quotient::User* user) const; + //! \brief Check the join state of a given user in this room + //! + //! \return the given user's state with respect to the room + Q_INVOKABLE Quotient::Membership memberState(User* user) const; + //! \brief Get a display name (without disambiguation) for the given member //! //! \sa safeMemberName, htmlSafeMemberName diff --git a/lib/syncdata.h b/lib/syncdata.h index e69bac17..0153bfd6 100644 --- a/lib/syncdata.h +++ b/lib/syncdata.h @@ -3,7 +3,7 @@ #pragma once -#include "joinstate.h" +#include "quotient_common.h" #include "events/stateevent.h" diff --git a/lib/user.cpp b/lib/user.cpp index 6cc9e161..c97e33a4 100644 --- a/lib/user.cpp +++ b/lib/user.cpp @@ -123,7 +123,7 @@ void User::rename(const QString& newName, const Room* r) } // #481: take the current state and update it with the new name auto evtC = r->getCurrentState(id())->content(); - Q_ASSERT_X(evtC.membership == MembershipType::Join, __FUNCTION__, + Q_ASSERT_X(evtC.membership == Membership::Join, __FUNCTION__, "Attempt to rename a user that's not a room member"); evtC.displayName = sanitized(newName); r->setState(id(), move(evtC)); -- cgit v1.2.3 From 3c28d13c1a61999e7c3141f3ca08b5b734bd160c Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 18 Jul 2021 19:00:07 +0200 Subject: Introduce to_array() to fix building on macOS A previous incarnation, make_array, existed in basejob.cpp before. The new direction taken by C++20 is to either deduce the array (but the used Apple standard library doesn't have deduction guides yet) or to use to_array() that converts a C array to std::array. This latter option is taken here, with to_array() defined in quotient_common.h until we move over to C++20. --- lib/jobs/basejob.cpp | 13 +++---------- lib/quotient_common.h | 27 ++++++++++++++++++++++----- 2 files changed, 25 insertions(+), 15 deletions(-) (limited to 'lib/quotient_common.h') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 9a7b9b5e..400a9243 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -5,6 +5,7 @@ #include "basejob.h" #include "connectiondata.h" +#include "quotient_common.h" #include #include @@ -15,8 +16,6 @@ #include #include -#include - using namespace Quotient; using std::chrono::seconds, std::chrono::milliseconds; using namespace std::chrono_literals; @@ -63,12 +62,6 @@ QDebug BaseJob::Status::dumpToLog(QDebug dbg) const return dbg << ": " << message; } -template -constexpr auto make_array(Ts&&... items) -{ - return std::array, sizeof...(Ts)>({items...}); -} - class BaseJob::Private { public: struct JobTimeoutConfig { @@ -163,8 +156,8 @@ public: { // FIXME: use std::array {} when Apple stdlib gets deduction guides for it static const auto verbs = - make_array(QStringLiteral("GET"), QStringLiteral("PUT"), - QStringLiteral("POST"), QStringLiteral("DELETE")); + to_array({ QStringLiteral("GET"), QStringLiteral("PUT"), + QStringLiteral("POST"), QStringLiteral("DELETE") }); const auto verbWord = verbs.at(size_t(verb)); return verbWord % ' ' % (reply ? reply->url().toString(QUrl::RemoveQuery) diff --git a/lib/quotient_common.h b/lib/quotient_common.h index 789128cf..037d5ded 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -8,6 +8,24 @@ namespace Quotient { Q_NAMESPACE +namespace impl { + template + constexpr std::array, N> + to_array_impl(T (&&a)[N], std::index_sequence) + { + return { {std::move(a[I])...} }; + } +} +// std::array {} needs explicit template parameters on macOS because +// Apple stdlib doesn't have deduction guides for std::array; to alleviate that, +// to_array() is borrowed from C++20 (thanks to cppreference for the possible +// implementation: https://en.cppreference.com/w/cpp/container/array/to_array) +template +constexpr auto to_array(T (&& items)[N]) +{ + return impl::to_array_impl(std::move(items), std::make_index_sequence{}); +} + // TODO: code like this should be generated from the CS API definition //! \brief Membership states @@ -29,10 +47,9 @@ enum class Membership : unsigned int { Q_DECLARE_FLAGS(MembershipMask, Membership) Q_FLAG_NS(MembershipMask) -constexpr inline std::array MembershipStrings = { +constexpr inline auto MembershipStrings = to_array( // The order MUST be the same as the order in the original enum - "join", "leave", "invite", "knock", "ban" -}; + { "join", "leave", "invite", "knock", "ban" }); //! \brief Local user join-state names //! @@ -49,10 +66,10 @@ enum class JoinState : std::underlying_type_t { Q_DECLARE_FLAGS(JoinStates, JoinState) Q_FLAG_NS(JoinStates) -constexpr inline std::array JoinStateStrings { +constexpr inline auto JoinStateStrings = to_array({ MembershipStrings[0], MembershipStrings[1], MembershipStrings[2], MembershipStrings[3] /* same as MembershipStrings, sans "ban" */ -}; +}); //! \brief Network job running policy flags //! -- cgit v1.2.3 From 2187f26ebdc9edf7b3cbfa1d208c03c4384f4135 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 18 Jul 2021 20:56:33 +0200 Subject: Add a missing #include Without this, it compiles on Linux but on macOS and Windows. --- lib/quotient_common.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/quotient_common.h') diff --git a/lib/quotient_common.h b/lib/quotient_common.h index 037d5ded..d225ad63 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -5,6 +5,8 @@ #include +#include + namespace Quotient { Q_NAMESPACE -- cgit v1.2.3 From c813a084b6dc8206a9c7305bbb236e23edcb49e5 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Tue, 24 Aug 2021 18:38:45 +0200 Subject: Fix building with MSVC Turned out it was broken, and I was looking the other way. --- lib/jobs/basejob.cpp | 4 ++-- lib/quotient_common.h | 31 +++++++++++++------------------ 2 files changed, 15 insertions(+), 20 deletions(-) (limited to 'lib/quotient_common.h') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 239cef28..6346db9d 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -156,8 +156,8 @@ public: { // FIXME: use std::array {} when Apple stdlib gets deduction guides for it static const auto verbs = - to_array({ QStringLiteral("GET"), QStringLiteral("PUT"), - QStringLiteral("POST"), QStringLiteral("DELETE") }); + make_array(QStringLiteral("GET"), QStringLiteral("PUT"), + QStringLiteral("POST"), QStringLiteral("DELETE")); const auto verbWord = verbs.at(size_t(verb)); return verbWord % ' ' % (reply ? reply->url().toString(QUrl::RemoveQuery) diff --git a/lib/quotient_common.h b/lib/quotient_common.h index d225ad63..bb2e6a6b 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -10,22 +10,17 @@ namespace Quotient { Q_NAMESPACE -namespace impl { - template - constexpr std::array, N> - to_array_impl(T (&&a)[N], std::index_sequence) - { - return { {std::move(a[I])...} }; - } -} // std::array {} needs explicit template parameters on macOS because -// Apple stdlib doesn't have deduction guides for std::array; to alleviate that, -// to_array() is borrowed from C++20 (thanks to cppreference for the possible -// implementation: https://en.cppreference.com/w/cpp/container/array/to_array) -template -constexpr auto to_array(T (&& items)[N]) +// Apple stdlib doesn't have deduction guides for std::array. C++20 has +// to_array() but that can't be borrowed, this time because of MSVC: +// https://developercommunity.visualstudio.com/t/vc-ice-p1-initc-line-3652-from-stdto-array/1464038 +// Therefore a simpler (but also slightly more wobbly - it resolves the element +// type using std::common_type<>) make_array facility is implemented here. +template +constexpr auto make_array(Ts&&... items) { - return impl::to_array_impl(std::move(items), std::make_index_sequence{}); + return std::array, sizeof...(items)>( + { std::forward(items)... }); } // TODO: code like this should be generated from the CS API definition @@ -49,9 +44,9 @@ enum class Membership : unsigned int { Q_DECLARE_FLAGS(MembershipMask, Membership) Q_FLAG_NS(MembershipMask) -constexpr inline auto MembershipStrings = to_array( +constexpr inline auto MembershipStrings = make_array( // The order MUST be the same as the order in the original enum - { "join", "leave", "invite", "knock", "ban" }); + "join", "leave", "invite", "knock", "ban"); //! \brief Local user join-state names //! @@ -68,10 +63,10 @@ enum class JoinState : std::underlying_type_t { Q_DECLARE_FLAGS(JoinStates, JoinState) Q_FLAG_NS(JoinStates) -constexpr inline auto JoinStateStrings = to_array({ +constexpr inline auto JoinStateStrings = make_array( MembershipStrings[0], MembershipStrings[1], MembershipStrings[2], MembershipStrings[3] /* same as MembershipStrings, sans "ban" */ -}); +); //! \brief Network job running policy flags //! -- cgit v1.2.3 From 59c9ca720093f2931c2eee1c0d5806d7e2e0c85f Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Mon, 13 Sep 2021 16:05:46 +0200 Subject: Add room types to RoomCreateEvent --- lib/events/roomcreateevent.cpp | 21 +++++++++++++++++++++ lib/events/roomcreateevent.h | 2 ++ lib/quotient_common.h | 10 ++++++++++ 3 files changed, 33 insertions(+) (limited to 'lib/quotient_common.h') diff --git a/lib/events/roomcreateevent.cpp b/lib/events/roomcreateevent.cpp index 6558bade..ff93041c 100644 --- a/lib/events/roomcreateevent.cpp +++ b/lib/events/roomcreateevent.cpp @@ -5,6 +5,22 @@ using namespace Quotient; +template <> +struct Quotient::JsonConverter { + static RoomType load(const QJsonValue& jv) + { + const auto& roomTypeString = jv.toString(); + for (auto it = RoomTypeStrings.begin(); it != RoomTypeStrings.end(); + ++it) + if (roomTypeString == *it) + return RoomType(it - RoomTypeStrings.begin()); + + if (!roomTypeString.isEmpty()) + qCWarning(EVENTS) << "Unknown Room Type: " << roomTypeString; + return RoomType::Undefined; + } +}; + bool RoomCreateEvent::isFederated() const { return fromJson(contentJson()["m.federate"_ls]); @@ -26,3 +42,8 @@ bool RoomCreateEvent::isUpgrade() const { return contentJson().contains("predecessor"_ls); } + +RoomType RoomCreateEvent::roomType() const +{ + return fromJson(contentJson()["type"_ls]); +} diff --git a/lib/events/roomcreateevent.h b/lib/events/roomcreateevent.h index 05e623ed..b3ad287c 100644 --- a/lib/events/roomcreateevent.h +++ b/lib/events/roomcreateevent.h @@ -4,6 +4,7 @@ #pragma once #include "stateevent.h" +#include "quotient_common.h" namespace Quotient { class RoomCreateEvent : public StateEventBase { @@ -24,6 +25,7 @@ public: QString version() const; Predecessor predecessor() const; bool isUpgrade() const; + RoomType roomType() const; }; REGISTER_EVENT_TYPE(RoomCreateEvent) } // namespace Quotient diff --git a/lib/quotient_common.h b/lib/quotient_common.h index bb2e6a6b..4444a111 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -88,6 +88,16 @@ enum UriResolveResult : short { }; Q_ENUM_NS(UriResolveResult) +enum RoomType { + Space, + Undefined, +}; +Q_ENUM_NS(RoomType); + +constexpr inline auto RoomTypeStrings = make_array( + "m.space" +); + } // namespace Quotient Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::MembershipMask) Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::JoinStates) -- cgit v1.2.3 From 73c1c8747b0c00524239724bb7cf00776448c5c7 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 4 Oct 2021 09:54:45 +0200 Subject: quotient_common.h: remove a stray semicolon --- lib/quotient_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/quotient_common.h') diff --git a/lib/quotient_common.h b/lib/quotient_common.h index 4444a111..13bf7246 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -92,7 +92,7 @@ enum RoomType { Space, Undefined, }; -Q_ENUM_NS(RoomType); +Q_ENUM_NS(RoomType) constexpr inline auto RoomTypeStrings = make_array( "m.space" -- cgit v1.2.3 From de164d60f2561fb0ad142b5d4fd31ff9817c2725 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Tue, 12 Oct 2021 19:17:42 +0200 Subject: Make sure to expose both the flags type and the underlying enum See also https://bugreports.qt.io/browse/QTBUG-82295. --- lib/quotient_common.h | 22 ++++++++++++++++++---- lib/room.h | 3 +-- 2 files changed, 19 insertions(+), 6 deletions(-) (limited to 'lib/quotient_common.h') diff --git a/lib/quotient_common.h b/lib/quotient_common.h index 13bf7246..e1e14a14 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -7,6 +7,22 @@ #include +// See https://bugreports.qt.io/browse/QTBUG-82295 - despite the comment that +// Q_FLAG[_NS] "should" be applied to the enum only, Qt doesn't allow to wrap +// a flag type into a QVariant then. The macros below define Q_FLAG_NS and on +// top of that add a part of Q_ENUM() that enables the metatype data but goes +// under the moc radar to avoid double registration of the same data in the map +// defined in moc_*.cpp +#define QUO_DECLARE_FLAGS(Flags, Enum) \ + Q_DECLARE_FLAGS(Flags, Enum) \ + Q_ENUM_IMPL(Enum) \ + Q_FLAG(Flags) + +#define QUO_DECLARE_FLAGS_NS(Flags, Enum) \ + Q_DECLARE_FLAGS(Flags, Enum) \ + Q_ENUM_NS_IMPL(Enum) \ + Q_FLAG_NS(Flags) + namespace Quotient { Q_NAMESPACE @@ -41,8 +57,7 @@ enum class Membership : unsigned int { Ban = 0x10, Undefined = Invalid }; -Q_DECLARE_FLAGS(MembershipMask, Membership) -Q_FLAG_NS(MembershipMask) +QUO_DECLARE_FLAGS_NS(MembershipMask, Membership) constexpr inline auto MembershipStrings = make_array( // The order MUST be the same as the order in the original enum @@ -60,8 +75,7 @@ enum class JoinState : std::underlying_type_t { Invite = std::underlying_type_t(Membership::Invite), Knock = std::underlying_type_t(Membership::Knock), }; -Q_DECLARE_FLAGS(JoinStates, JoinState) -Q_FLAG_NS(JoinStates) +QUO_DECLARE_FLAGS_NS(JoinStates, JoinState) constexpr inline auto JoinStateStrings = make_array( MembershipStrings[0], MembershipStrings[1], MembershipStrings[2], diff --git a/lib/room.h b/lib/room.h index c4d94c02..b43217ae 100644 --- a/lib/room.h +++ b/lib/room.h @@ -148,8 +148,7 @@ public: OtherChange = 0x8000, AnyChange = 0xFFFF }; - Q_DECLARE_FLAGS(Changes, Change) - Q_FLAG(Changes) + QUO_DECLARE_FLAGS(Changes, Change) Room(Connection* connection, QString id, JoinState initialJoinState); ~Room() override; -- cgit v1.2.3 From 65bb0b5fcf029df7a9bfa0b7b7b7e3203fd7862f Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Tue, 9 Nov 2021 13:59:47 +0100 Subject: DECL_DEPRECATED_ENUMERATOR A handy macro that introduces an enumerator with a respective Q_DECL_DEPRECATED_X recommending the substitution. --- lib/jobs/basejob.h | 6 +++--- lib/quotient_common.h | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'lib/quotient_common.h') diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 119d7cce..ddf243ed 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -7,6 +7,7 @@ #include "requestdata.h" #include "../logging.h" #include "../converters.h" +#include "../quotient_common.h" #include #include @@ -33,9 +34,8 @@ class BaseJob : public QObject { } public: -#define WITH_DEPRECATED_ERROR_VERSION(Recommended) \ - Recommended, Recommended##Error Q_DECL_ENUMERATOR_DEPRECATED_X( \ - "Use " #Recommended) = Recommended +#define WITH_DEPRECATED_ERROR_VERSION(Recommended) \ + Recommended, DECL_DEPRECATED_ENUMERATOR(Recommended##Error, Recommended) /*! The status code of a job * diff --git a/lib/quotient_common.h b/lib/quotient_common.h index e1e14a14..3d8ace67 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -23,6 +23,9 @@ Q_ENUM_NS_IMPL(Enum) \ Q_FLAG_NS(Flags) +#define DECL_DEPRECATED_ENUMERATOR(Deprecated, Recommended) \ + Deprecated Q_DECL_ENUMERATOR_DEPRECATED_X("Use " #Recommended) = Recommended + namespace Quotient { Q_NAMESPACE -- cgit v1.2.3 From d6cf6b32cdd2843c40fc696accd8a6456f1ea15c Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Fri, 19 Nov 2021 12:45:50 +0100 Subject: Make enum values logging more terse() By default enum class values are logged along with the qualifier; this may or may not be desirable in a given setting. For JoinState(s) and Membership(Mask) operator<< was overloaded to implicitly suppress qualification; however, this is both overly sweeping and uses Qt's internal API for the backend. Instead, a new QDebug manipulator, terse(), is introduced, that does the same as those operator<< overloads but on a per-invocation basis. This makes it slightly more verbose to log enums but makes the QDebug reconfiguration explicit and doesn't require to produce new overloads every time a new enum ends up in logs. And it's built entirely on the published Qt API, reusing the QDebugManip framework that Quotient already has. Also: operator<<(QDebug, QDebugManip) has been moved out of the namespace to fix lookup issues when there's no prior `using namespace Quotient`. --- CMakeLists.txt | 2 +- lib/connection.cpp | 4 ++-- lib/logging.h | 31 +++++++++++++++++++++---------- lib/quotient_common.cpp | 45 --------------------------------------------- lib/quotient_common.h | 6 ------ lib/room.cpp | 4 ++-- 6 files changed, 26 insertions(+), 66 deletions(-) delete mode 100644 lib/quotient_common.cpp (limited to 'lib/quotient_common.h') diff --git a/CMakeLists.txt b/CMakeLists.txt index 34200548..3814bc7e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,7 +124,7 @@ endif () # Set up source files list(APPEND lib_SRCS - lib/quotient_common.cpp + lib/quotient_common.h lib/networkaccessmanager.cpp lib/connectiondata.cpp lib/connection.cpp diff --git a/lib/connection.cpp b/lib/connection.cpp index 75966731..e65fdac4 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -636,7 +636,7 @@ void Connection::Private::consumeRoomData(SyncDataList&& roomDataList, } qWarning(MAIN) << "Room" << roomData.roomId << "has just been forgotten but /sync returned it in" - << roomData.joinState + << terse << roomData.joinState << "state - suspiciously fast turnaround"; } if (auto* r = q->provideRoom(roomData.roomId, roomData.joinState)) { @@ -1341,7 +1341,7 @@ void Connection::Private::removeRoom(const QString& roomId) { for (auto f : { false, true }) if (auto r = roomMap.take({ roomId, f })) { - qCDebug(MAIN) << "Room" << r->objectName() << "in state" + qCDebug(MAIN) << "Room" << r->objectName() << "in state" << terse << r->joinState() << "will be deleted"; emit r->beforeDestruction(r); r->deleteLater(); diff --git a/lib/logging.h b/lib/logging.h index 5a3ef6ea..5bf050a9 100644 --- a/lib/logging.h +++ b/lib/logging.h @@ -40,17 +40,15 @@ inline QDebug formatJson(QDebug debug_object) return debug_object.noquote(); } -/** - * @brief A helper operator to facilitate usage of formatJson (and possibly - * other manipulators) - * - * @param debug_object to output the json to - * @param qdm a QDebug manipulator - * @return a copy of debug_object that has its mode altered by qdm - */ -inline QDebug operator<<(QDebug debug_object, QDebugManip qdm) +//! Suppress full qualification of enums/QFlags when logging +inline QDebug terse(QDebug dbg) { - return qdm(debug_object); + return +#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0) + dbg.setVerbosity(0), dbg; +#else + dbg.verbosity(QDebug::MinimumVerbosity); +#endif } inline qint64 profilerMinNsecs() @@ -65,6 +63,19 @@ inline qint64 profilerMinNsecs() } } // namespace Quotient +/** + * @brief A helper operator to facilitate usage of formatJson (and possibly + * other manipulators) + * + * @param debug_object to output the json to + * @param qdm a QDebug manipulator + * @return a copy of debug_object that has its mode altered by qdm + */ +inline QDebug operator<<(QDebug debug_object, Quotient::QDebugManip qdm) +{ + return qdm(debug_object); +} + inline QDebug operator<<(QDebug debug_object, const QElapsedTimer& et) { auto val = et.nsecsElapsed() / 1000; diff --git a/lib/quotient_common.cpp b/lib/quotient_common.cpp deleted file mode 100644 index 5d7a3027..00000000 --- a/lib/quotient_common.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "quotient_common.h" - -#include - -using namespace Quotient; - -template -inline QDebug suppressScopeAndDump(QDebug dbg, Enum e) -{ - // Suppress "Quotient::" prefix - QDebugStateSaver _dss(dbg); - dbg.setVerbosity(0 /* QDebug::MinimumVerbosity since Qt 5.13 */); - return qt_QMetaEnum_debugOperator(dbg, std::underlying_type_t(e), - qt_getEnumMetaObject(e), - qt_getEnumName(e)); -} - -template -inline QDebug suppressScopeAndDump(QDebug dbg, const QFlags& f) -{ - // Suppress "Quotient::" prefix - QDebugStateSaver _dss(dbg); - dbg.setVerbosity(0 /* QDebug::MinimumVerbosity since Qt 5.13 */); - return qt_QMetaEnum_flagDebugOperator_helper(dbg, f); -} - -QDebug operator<<(QDebug dbg, Membership m) -{ - return suppressScopeAndDump(dbg, m); -} - -QDebug operator<<(QDebug dbg, MembershipMask mm) -{ - return suppressScopeAndDump(dbg, mm) << ")"; -} - -QDebug operator<<(QDebug dbg, JoinState js) -{ - return suppressScopeAndDump(dbg, js); -} - -QDebug operator<<(QDebug dbg, JoinStates jss) -{ - return suppressScopeAndDump(dbg, jss) << ")"; -} diff --git a/lib/quotient_common.h b/lib/quotient_common.h index 3d8ace67..969ebe90 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -118,9 +118,3 @@ constexpr inline auto RoomTypeStrings = make_array( } // namespace Quotient Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::MembershipMask) Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::JoinStates) - -class QDebug; -QDebug operator<<(QDebug dbg, Quotient::Membership m); -QDebug operator<<(QDebug dbg, Quotient::MembershipMask m); -QDebug operator<<(QDebug dbg, Quotient::JoinState js); -QDebug operator<<(QDebug dbg, Quotient::JoinStates js); diff --git a/lib/room.cpp b/lib/room.cpp index a376238e..a2ec228a 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -461,7 +461,7 @@ Room::Room(Connection* connection, QString id, JoinState initialJoinState) emit baseStateLoaded(); return this == r; // loadedRoomState fires only once per room }); - qCDebug(STATE) << "New" << initialJoinState << "Room:" << id; + qCDebug(STATE) << "New" << terse << initialJoinState << "Room:" << id; } Room::~Room() { delete d; } @@ -612,7 +612,7 @@ void Room::setJoinState(JoinState state) if (state == oldState) return; d->joinState = state; - qCDebug(STATE) << "Room" << id() << "changed state: " << oldState + qCDebug(STATE) << "Room" << id() << "changed state: " << terse << oldState << "->" << state; emit joinStateChanged(oldState, state); } -- cgit v1.2.3 From 52e640bce5a8931330fa6d653212e524e7baa2eb Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 20 Nov 2021 11:42:21 +0100 Subject: Minor brushup in the comment to QUO_DECLARE_FLAGS [skip ci] --- lib/quotient_common.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/quotient_common.h') diff --git a/lib/quotient_common.h b/lib/quotient_common.h index 969ebe90..d91c3d17 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -9,10 +9,10 @@ // See https://bugreports.qt.io/browse/QTBUG-82295 - despite the comment that // Q_FLAG[_NS] "should" be applied to the enum only, Qt doesn't allow to wrap -// a flag type into a QVariant then. The macros below define Q_FLAG_NS and on -// top of that add a part of Q_ENUM() that enables the metatype data but goes -// under the moc radar to avoid double registration of the same data in the map -// defined in moc_*.cpp +// a flag type into a QVariant then. The macros below define Q_FLAG[_NS] and on +// top of that add Q_ENUM[_NS]_IMPL which is a part of Q_ENUM() macro that +// enables the metatype data but goes under the moc radar to avoid double +// registration of the same data in the map defined in moc_*.cpp #define QUO_DECLARE_FLAGS(Flags, Enum) \ Q_DECLARE_FLAGS(Flags, Enum) \ Q_ENUM_IMPL(Enum) \ -- cgit v1.2.3 From f6155d62740a88b020273ba623c816f7b9805772 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Fri, 26 Nov 2021 13:44:39 +0100 Subject: Drop Q_GADGET from most uncopyable classes; other minor cleanup Q_GADGET is generally used to enable two things outside of QObject: Q_PROPERTY/Q_INVOKABLE and Q_ENUM/Q_FLAG. While the latter can be used in its own right in QML, the former requires Q_GADGET instances to be passed to QML by value, which is not really possible with uncopyable/unassignable classes. Bottom line is that Q_PROPERTY in anything derived from Quotient::Event is not viable, making Q_GADGET macro useless unless there's a Q_ENUM/Q_FLAG (as is the case with RoomMessageEvent, e.g.). --- lib/eventitem.h | 5 +---- lib/events/encryptedevent.h | 2 -- lib/events/event.h | 3 --- lib/events/roomevent.h | 41 +++++++++++++---------------------------- lib/events/roommessageevent.h | 4 ---- lib/events/stateevent.h | 2 -- lib/quotient_common.h | 1 - 7 files changed, 14 insertions(+), 44 deletions(-) (limited to 'lib/quotient_common.h') diff --git a/lib/eventitem.h b/lib/eventitem.h index a70a3c3e..0ab1a01d 100644 --- a/lib/eventitem.h +++ b/lib/eventitem.h @@ -9,7 +9,6 @@ #include namespace Quotient { -class StateEventBase; namespace EventStatus { Q_NAMESPACE @@ -31,8 +30,7 @@ namespace EventStatus { Replaced = 0x10, //< The event has been replaced Hidden = 0x100, //< The event should not be shown in the timeline }; - Q_DECLARE_FLAGS(Status, Code) - Q_FLAG_NS(Status) + Q_ENUM_NS(Code) } // namespace EventStatus class EventItemBase { @@ -106,7 +104,6 @@ inline const CallEventBase* EventItemBase::viewAs() const } class PendingEventItem : public EventItemBase { - Q_GADGET public: using EventItemBase::EventItemBase; diff --git a/lib/events/encryptedevent.h b/lib/events/encryptedevent.h index eb7123eb..598829cd 100644 --- a/lib/events/encryptedevent.h +++ b/lib/events/encryptedevent.h @@ -7,7 +7,6 @@ #include "roomevent.h" namespace Quotient { -class Room; /* * While the specification states: * @@ -27,7 +26,6 @@ class Room; * one and doesn't add new restrictions, just provides additional features. */ class EncryptedEvent : public RoomEvent { - Q_GADGET public: DEFINE_EVENT_TYPEID("m.room.encrypted", EncryptedEvent) diff --git a/lib/events/event.h b/lib/events/event.h index 78853ced..2ed5de5d 100644 --- a/lib/events/event.h +++ b/lib/events/event.h @@ -195,9 +195,6 @@ inline auto registerEventType() // === Event === class Event { - Q_GADGET - Q_PROPERTY(Type type READ type CONSTANT) - Q_PROPERTY(QJsonObject contentJson READ contentJson CONSTANT) public: using Type = event_type_t; using factory_t = EventFactory; diff --git a/lib/events/roomevent.h b/lib/events/roomevent.h index 3174764f..a6cd84ca 100644 --- a/lib/events/roomevent.h +++ b/lib/events/roomevent.h @@ -12,16 +12,6 @@ class RedactionEvent; /** This class corresponds to m.room.* events */ class RoomEvent : public Event { - Q_GADGET - Q_PROPERTY(QString id READ id) - //! \deprecated Use originTimestamp instead - Q_PROPERTY(QDateTime timestamp READ originTimestamp CONSTANT) - Q_PROPERTY(QDateTime originTimestamp READ originTimestamp CONSTANT) - Q_PROPERTY(QString roomId READ roomId CONSTANT) - Q_PROPERTY(QString senderId READ senderId CONSTANT) - Q_PROPERTY(QString redactionReason READ redactionReason) - Q_PROPERTY(bool isRedacted READ isRedacted) - Q_PROPERTY(QString transactionId READ transactionId WRITE setTransactionId) public: using factory_t = EventFactory; @@ -51,28 +41,23 @@ public: QString transactionId() const; QString stateKey() const; + //! \brief Fill the pending event object with the room id void setRoomId(const QString& roomId); + //! \brief Fill the pending event object with the sender id void setSender(const QString& senderId); - - /** - * Sets the transaction id for locally created events. This should be - * done before the event is exposed to any code using the respective - * Q_PROPERTY. - * - * \param txnId - transaction id, normally obtained from - * Connection::generateTxnId() - */ + //! \brief Fill the pending event object with the transaction id + //! \param txnId - transaction id, normally obtained from + //! Connection::generateTxnId() void setTransactionId(const QString& txnId); - /** - * Sets event id for locally created events - * - * When a new event is created locally, it has no server id yet. - * This function allows to add the id once the confirmation from - * the server is received. There should be no id set previously - * in the event. It's the responsibility of the code calling addId() - * to notify clients that use Q_PROPERTY(id) about its change - */ + //! \brief Add an event id to locally created events after they are sent + //! + //! When a new event is created locally, it has no id; the homeserver + //! assigns it once the event is sent. This function allows to add the id + //! once the confirmation from the server is received. There should be no id + //! set previously in the event. It's the responsibility of the code calling + //! addId() to notify clients about the change; there's no signal or + //! callback for that in RoomEvent. void addId(const QString& newId); protected: diff --git a/lib/events/roommessageevent.h b/lib/events/roommessageevent.h index 88d3b74c..56597ddc 100644 --- a/lib/events/roommessageevent.h +++ b/lib/events/roommessageevent.h @@ -18,10 +18,6 @@ namespace MessageEventContent = EventContent; // Back-compatibility */ class RoomMessageEvent : public RoomEvent { Q_GADGET - Q_PROPERTY(QString msgType READ rawMsgtype CONSTANT) - Q_PROPERTY(QString plainBody READ plainBody CONSTANT) - Q_PROPERTY(QMimeType mimeType READ mimeType STORED false CONSTANT) - Q_PROPERTY(const EventContent::TypedBase* content READ content CONSTANT) public: DEFINE_EVENT_TYPEID("m.room.message", RoomMessageEvent) diff --git a/lib/events/stateevent.h b/lib/events/stateevent.h index bc414a5f..b0aa9907 100644 --- a/lib/events/stateevent.h +++ b/lib/events/stateevent.h @@ -18,8 +18,6 @@ inline QJsonObject basicStateEventJson(const QString& matrixTypeId, } class StateEventBase : public RoomEvent { - Q_GADGET - Q_PROPERTY(QString stateKey READ stateKey CONSTANT) public: using factory_t = EventFactory; diff --git a/lib/quotient_common.h b/lib/quotient_common.h index d91c3d17..0e3e2a40 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -90,7 +90,6 @@ constexpr inline auto JoinStateStrings = make_array( //! So far only background/foreground flags are available. //! \sa Connection::callApi, Connection::run enum RunningPolicy { ForegroundRequest = 0x0, BackgroundRequest = 0x1 }; - Q_ENUM_NS(RunningPolicy) //! \brief The result of URI resolution using UriResolver -- cgit v1.2.3 From 7350fe82953cf6274b8845a890eafb21a09b9931 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Wed, 29 Dec 2021 15:59:58 +0100 Subject: Add QUOTIENT_API throughout non-generated code This include all (hopefully) classes/structures and functions that have non-inline definitions, as well as namespaces with Q_NAMESPACE since those have non-inline (as of Qt 5.15) QMetaObject - for that a new macro, QUO_NAMESPACE, has been devised to accommodate the lack of Q_NAMESPACE_EXPORT in Qt before 5.14. --- lib/accountregistry.h | 4 +++- lib/avatar.h | 4 +++- lib/connection.h | 2 +- lib/converters.h | 6 +++--- lib/eventitem.cpp | 4 ++++ lib/eventitem.h | 9 +++++---- lib/events/accountdataevents.h | 2 +- lib/events/callanswerevent.h | 3 +-- lib/events/callhangupevent.h | 2 +- lib/events/callinviteevent.h | 2 +- lib/events/directchatevent.h | 2 +- lib/events/encryptedevent.h | 2 +- lib/events/encryptionevent.h | 5 ++--- lib/events/event.h | 23 +++++++++++++---------- lib/events/eventcontent.h | 19 ++++++++++--------- lib/events/reactionevent.h | 6 +++--- lib/events/receiptevent.h | 2 +- lib/events/roomavatarevent.h | 3 ++- lib/events/roomcreateevent.h | 2 +- lib/events/roomevent.h | 4 ++-- lib/events/roomkeyevent.h | 2 +- lib/events/roommemberevent.h | 5 ++--- lib/events/roommessageevent.h | 8 ++++---- lib/events/roompowerlevelsevent.h | 8 +++----- lib/events/roomtombstoneevent.h | 2 +- lib/events/simplestateevents.h | 3 ++- lib/events/stateevent.h | 2 +- lib/events/stickerevent.h | 2 +- lib/events/typingevent.h | 2 +- lib/eventstats.h | 4 ++-- lib/jobs/basejob.h | 4 ++-- lib/jobs/downloadfilejob.h | 2 +- lib/jobs/mediathumbnailjob.h | 2 +- lib/jobs/requestdata.h | 4 +++- lib/mxcreply.h | 4 +++- lib/networkaccessmanager.h | 4 +++- lib/networksettings.h | 2 +- lib/quotient_common.h | 17 ++++++++++++++++- lib/room.h | 8 ++++---- lib/settings.h | 8 +++++--- lib/ssosession.h | 4 +++- lib/syncdata.h | 2 +- lib/uri.h | 2 +- lib/uriresolver.h | 6 +++--- lib/user.h | 3 ++- lib/util.h | 22 ++++++++++++---------- 46 files changed, 138 insertions(+), 100 deletions(-) (limited to 'lib/quotient_common.h') diff --git a/lib/accountregistry.h b/lib/accountregistry.h index 5efda459..f7a864df 100644 --- a/lib/accountregistry.h +++ b/lib/accountregistry.h @@ -4,6 +4,8 @@ #pragma once +#include "quotient_export.h" + #include #include #include @@ -11,7 +13,7 @@ namespace Quotient { class Connection; -class AccountRegistry : public QAbstractListModel { +class QUOTIENT_API AccountRegistry : public QAbstractListModel { Q_OBJECT public: enum EventRoles { diff --git a/lib/avatar.h b/lib/avatar.h index d4634aea..93f43948 100644 --- a/lib/avatar.h +++ b/lib/avatar.h @@ -3,6 +3,8 @@ #pragma once +#include "quotient_export.h" + #include #include @@ -12,7 +14,7 @@ namespace Quotient { class Connection; -class Avatar { +class QUOTIENT_API Avatar { public: explicit Avatar(); explicit Avatar(QUrl url); diff --git a/lib/connection.h b/lib/connection.h index 0713af16..d669462e 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -105,7 +105,7 @@ using DirectChatsMap = QMultiHash; using DirectChatUsersMap = QMultiHash; using IgnoredUsersList = IgnoredUsersEvent::content_type; -class Connection : public QObject { +class QUOTIENT_API Connection : public QObject { Q_OBJECT Q_PROPERTY(User* localUser READ user NOTIFY stateChanged) diff --git a/lib/converters.h b/lib/converters.h index 9c3d5749..a6028f1b 100644 --- a/lib/converters.h +++ b/lib/converters.h @@ -183,7 +183,7 @@ struct JsonConverter { }; template <> -struct JsonConverter { +struct QUOTIENT_API JsonConverter { static QJsonValue dump(const QVariant& v); static QVariant load(const QJsonValue& jv); }; @@ -281,9 +281,9 @@ template struct JsonObjectConverter> : public HashMapFromJson> {}; -QJsonObject toJson(const QVariantHash& vh); +QJsonObject QUOTIENT_API toJson(const QVariantHash& vh); template <> -QVariantHash fromJson(const QJsonValue& jv); +QVariantHash QUOTIENT_API fromJson(const QJsonValue& jv); // Conditional insertion into a QJsonObject diff --git a/lib/eventitem.cpp b/lib/eventitem.cpp index 4f1595bc..a2d65d8d 100644 --- a/lib/eventitem.cpp +++ b/lib/eventitem.cpp @@ -25,3 +25,7 @@ void PendingEventItem::setFileUploaded(const QUrl& remoteUrl) } setStatus(EventStatus::FileUploaded); } + +// Not exactly sure why but this helps with the linker not finding +// Quotient::EventStatus::staticMetaObject when building Quaternion +#include "moc_eventitem.cpp" diff --git a/lib/eventitem.h b/lib/eventitem.h index 0ab1a01d..2f1e72cc 100644 --- a/lib/eventitem.h +++ b/lib/eventitem.h @@ -4,6 +4,7 @@ #pragma once #include "events/stateevent.h" +#include "quotient_common.h" #include #include @@ -11,7 +12,7 @@ namespace Quotient { namespace EventStatus { - Q_NAMESPACE + QUO_NAMESPACE /** Special marks an event can assume * @@ -33,7 +34,7 @@ namespace EventStatus { Q_ENUM_NS(Code) } // namespace EventStatus -class EventItemBase { +class QUOTIENT_API EventItemBase { public: explicit EventItemBase(RoomEventPtr&& e) : evt(std::move(e)) { @@ -74,7 +75,7 @@ private: std::any data; }; -class TimelineItem : public EventItemBase { +class QUOTIENT_API TimelineItem : public EventItemBase { public: // For compatibility with Qt containers, even though we use // a std:: container now for the room timeline @@ -103,7 +104,7 @@ inline const CallEventBase* EventItemBase::viewAs() const return evt->isCallEvent() ? weakPtrCast(evt) : nullptr; } -class PendingEventItem : public EventItemBase { +class QUOTIENT_API PendingEventItem : public EventItemBase { public: using EventItemBase::EventItemBase; diff --git a/lib/events/accountdataevents.h b/lib/events/accountdataevents.h index 9cf77be3..c0f2202d 100644 --- a/lib/events/accountdataevents.h +++ b/lib/events/accountdataevents.h @@ -50,7 +50,7 @@ struct JsonObjectConverter { using TagsMap = QHash; #define DEFINE_SIMPLE_EVENT(_Name, _TypeId, _ContentType, _ContentKey) \ - class _Name : public Event { \ + class QUOTIENT_API _Name : public Event { \ public: \ using content_type = _ContentType; \ DEFINE_EVENT_TYPEID(_TypeId, _Name) \ diff --git a/lib/events/callanswerevent.h b/lib/events/callanswerevent.h index 4c01c941..8ffe60f2 100644 --- a/lib/events/callanswerevent.h +++ b/lib/events/callanswerevent.h @@ -7,7 +7,7 @@ #include "roomevent.h" namespace Quotient { -class CallAnswerEvent : public CallEventBase { +class QUOTIENT_API CallAnswerEvent : public CallEventBase { public: DEFINE_EVENT_TYPEID("m.call.answer", CallAnswerEvent) @@ -26,6 +26,5 @@ public: return contentPart("answer"_ls).value("sdp"_ls).toString(); } }; - REGISTER_EVENT_TYPE(CallAnswerEvent) } // namespace Quotient diff --git a/lib/events/callhangupevent.h b/lib/events/callhangupevent.h index f3f82833..b0017c59 100644 --- a/lib/events/callhangupevent.h +++ b/lib/events/callhangupevent.h @@ -7,7 +7,7 @@ #include "roomevent.h" namespace Quotient { -class CallHangupEvent : public CallEventBase { +class QUOTIENT_API CallHangupEvent : public CallEventBase { public: DEFINE_EVENT_TYPEID("m.call.hangup", CallHangupEvent) diff --git a/lib/events/callinviteevent.h b/lib/events/callinviteevent.h index 80b7d651..47362b5c 100644 --- a/lib/events/callinviteevent.h +++ b/lib/events/callinviteevent.h @@ -7,7 +7,7 @@ #include "roomevent.h" namespace Quotient { -class CallInviteEvent : public CallEventBase { +class QUOTIENT_API CallInviteEvent : public CallEventBase { public: DEFINE_EVENT_TYPEID("m.call.invite", CallInviteEvent) diff --git a/lib/events/directchatevent.h b/lib/events/directchatevent.h index e2143779..2018d3d6 100644 --- a/lib/events/directchatevent.h +++ b/lib/events/directchatevent.h @@ -6,7 +6,7 @@ #include "event.h" namespace Quotient { -class DirectChatEvent : public Event { +class QUOTIENT_API DirectChatEvent : public Event { public: DEFINE_EVENT_TYPEID("m.direct", DirectChatEvent) diff --git a/lib/events/encryptedevent.h b/lib/events/encryptedevent.h index de89a7c6..81343a29 100644 --- a/lib/events/encryptedevent.h +++ b/lib/events/encryptedevent.h @@ -25,7 +25,7 @@ namespace Quotient { * in general. It's possible, because RoomEvent interface is similar to Event's * one and doesn't add new restrictions, just provides additional features. */ -class EncryptedEvent : public RoomEvent { +class QUOTIENT_API EncryptedEvent : public RoomEvent { public: DEFINE_EVENT_TYPEID("m.room.encrypted", EncryptedEvent) diff --git a/lib/events/encryptionevent.h b/lib/events/encryptionevent.h index 14439fcc..dfb28b2f 100644 --- a/lib/events/encryptionevent.h +++ b/lib/events/encryptionevent.h @@ -8,7 +8,7 @@ #include "stateevent.h" namespace Quotient { -class EncryptionEventContent : public EventContent::Base { +class QUOTIENT_API EncryptionEventContent : public EventContent::Base { public: enum EncryptionType : size_t { MegolmV1AesSha2 = 0, Undefined }; @@ -26,7 +26,7 @@ protected: using EncryptionType = EncryptionEventContent::EncryptionType; -class EncryptionEvent : public StateEvent { +class QUOTIENT_API EncryptionEvent : public StateEvent { Q_GADGET public: DEFINE_EVENT_TYPEID("m.room.encryption", EncryptionEvent) @@ -51,6 +51,5 @@ public: int rotationPeriodMs() const { return content().rotationPeriodMs; } int rotationPeriodMsgs() const { return content().rotationPeriodMsgs; } }; - REGISTER_EVENT_TYPE(EncryptionEvent) } // namespace Quotient diff --git a/lib/events/event.h b/lib/events/event.h index 8f62872d..8a0076d0 100644 --- a/lib/events/event.h +++ b/lib/events/event.h @@ -60,14 +60,14 @@ inline QJsonObject basicEventJson(const QString& matrixType, using event_type_t = size_t; using event_mtype_t = const char*; -class EventTypeRegistry { +class QUOTIENT_API EventTypeRegistry { public: ~EventTypeRegistry() = default; static event_type_t initializeTypeId(event_mtype_t matrixTypeId); template - static inline event_type_t initializeTypeId() + static event_type_t initializeTypeId() { return initializeTypeId(EventT::matrixTypeId()); } @@ -190,7 +190,7 @@ namespace _impl { // === Event === -class Event { +class QUOTIENT_API Event { public: using Type = event_type_t; static inline _impl::EventFactory factory { "Event" }; @@ -243,7 +243,7 @@ public: return fromJson(unsignedJson()[std::forward(key)]); } - friend QDebug operator<<(QDebug dbg, const Event& e) + friend QUOTIENT_API QDebug operator<<(QDebug dbg, const Event& e) { QDebugStateSaver _dss { dbg }; dbg.noquote().nospace() << e.matrixType() << '(' << e.type() << "): "; @@ -272,17 +272,20 @@ using Events = EventsArray; // This macro should be used in a public section of an event class to // provide matrixTypeId() and typeId(). -#define DEFINE_EVENT_TYPEID(_Id, _Type) \ - static constexpr event_mtype_t matrixTypeId() { return _Id; } \ - static auto typeId() { return Quotient::typeId<_Type>(); } \ +#define DEFINE_EVENT_TYPEID(_Id, _Type) \ + static QUOTIENT_EXPORT constexpr event_mtype_t matrixTypeId() \ + { \ + return _Id; \ + } \ + static QUOTIENT_EXPORT auto typeId() { return Quotient::typeId<_Type>(); } \ // End of macro // This macro should be put after an event class definition (in .h or .cpp) // to enable its deserialisation from a /sync and other // polymorphic event arrays -#define REGISTER_EVENT_TYPE(_Type) \ - [[maybe_unused]] inline const auto _factoryAdded##_Type = \ - _Type::factory.addMethod<_Type>(); \ +#define REGISTER_EVENT_TYPE(_Type) \ + [[maybe_unused]] QUOTIENT_API inline const auto _factoryAdded##_Type = \ + _Type::factory.addMethod<_Type>(); \ // End of macro // === Event loading === diff --git a/lib/events/eventcontent.h b/lib/events/eventcontent.h index f609a603..bfa7d926 100644 --- a/lib/events/eventcontent.h +++ b/lib/events/eventcontent.h @@ -6,14 +6,15 @@ // This file contains generic event content definitions, applicable to room // message events as well as other events (e.g., avatars). +#include "encryptedfile.h" +#include "quotient_export.h" + #include #include #include #include #include -#include "encryptedfile.h" - class QFileInfo; namespace Quotient { @@ -28,7 +29,7 @@ namespace EventContent { * assumed but not required that a content object can also be created * from plain data. */ - class Base { + class QUOTIENT_API Base { public: explicit Base(QJsonObject o = {}) : originalJson(std::move(o)) {} virtual ~Base() = default; @@ -76,7 +77,7 @@ namespace EventContent { * * This class is not polymorphic. */ - class FileInfo { + class QUOTIENT_API FileInfo { public: FileInfo() = default; explicit FileInfo(const QFileInfo& fi); @@ -121,7 +122,7 @@ namespace EventContent { /** * A content info class for image content types: image, thumbnail, video */ - class ImageInfo : public FileInfo { + class QUOTIENT_API ImageInfo : public FileInfo { public: ImageInfo() = default; explicit ImageInfo(const QFileInfo& fi, QSize imageSize = {}); @@ -146,7 +147,7 @@ namespace EventContent { * the JSON representation of event content; namely, * "info/thumbnail_url" and "info/thumbnail_info" fields are used. */ - class Thumbnail : public ImageInfo { + class QUOTIENT_API Thumbnail : public ImageInfo { public: Thumbnail() = default; // Allow empty thumbnails Thumbnail(const QJsonObject& infoJson, const Omittable &file = none); @@ -160,7 +161,7 @@ namespace EventContent { void fillInfoJson(QJsonObject* infoJson) const; }; - class TypedBase : public Base { + class QUOTIENT_API TypedBase : public Base { public: virtual QMimeType type() const = 0; virtual const FileInfo* fileInfo() const { return nullptr; } @@ -183,7 +184,7 @@ namespace EventContent { * \tparam InfoT base info class */ template - class UrlBasedContent : public TypedBase, public InfoT { + class QUOTIENT_API UrlBasedContent : public TypedBase, public InfoT { public: using InfoT::InfoT; explicit UrlBasedContent(const QJsonObject& json) @@ -215,7 +216,7 @@ namespace EventContent { }; template - class UrlWithThumbnailContent : public UrlBasedContent { + class QUOTIENT_API UrlWithThumbnailContent : public UrlBasedContent { public: // NB: when using inherited constructors, thumbnail has to be // initialised separately diff --git a/lib/events/reactionevent.h b/lib/events/reactionevent.h index 5a2b98c4..ce11eaed 100644 --- a/lib/events/reactionevent.h +++ b/lib/events/reactionevent.h @@ -7,7 +7,7 @@ namespace Quotient { -struct EventRelation { +struct QUOTIENT_API EventRelation { using reltypeid_t = const char*; static constexpr reltypeid_t Reply() { return "m.in_reply_to"; } static constexpr reltypeid_t Annotation() { return "m.annotation"; } @@ -31,12 +31,12 @@ struct EventRelation { } }; template <> -struct JsonObjectConverter { +struct QUOTIENT_API JsonObjectConverter { static void dumpTo(QJsonObject& jo, const EventRelation& pod); static void fillFrom(const QJsonObject& jo, EventRelation& pod); }; -class ReactionEvent : public RoomEvent { +class QUOTIENT_API ReactionEvent : public RoomEvent { public: DEFINE_EVENT_TYPEID("m.reaction", ReactionEvent) diff --git a/lib/events/receiptevent.h b/lib/events/receiptevent.h index 9683deef..5e077e47 100644 --- a/lib/events/receiptevent.h +++ b/lib/events/receiptevent.h @@ -19,7 +19,7 @@ struct ReceiptsForEvent { }; using EventsWithReceipts = QVector; -class ReceiptEvent : public Event { +class QUOTIENT_API ReceiptEvent : public Event { public: DEFINE_EVENT_TYPEID("m.receipt", ReceiptEvent) explicit ReceiptEvent(const EventsWithReceipts& ewrs); diff --git a/lib/events/roomavatarevent.h b/lib/events/roomavatarevent.h index 8618ba31..c54b5801 100644 --- a/lib/events/roomavatarevent.h +++ b/lib/events/roomavatarevent.h @@ -7,7 +7,8 @@ #include "stateevent.h" namespace Quotient { -class RoomAvatarEvent : public StateEvent { +class QUOTIENT_API RoomAvatarEvent + : public StateEvent { // It's a bit of an overkill to use a full-fledged ImageContent // because in reality m.room.avatar usually only has a single URL, // without a thumbnail. But The Spec says there be thumbnails, and diff --git a/lib/events/roomcreateevent.h b/lib/events/roomcreateevent.h index b3ad287c..016855b9 100644 --- a/lib/events/roomcreateevent.h +++ b/lib/events/roomcreateevent.h @@ -7,7 +7,7 @@ #include "quotient_common.h" namespace Quotient { -class RoomCreateEvent : public StateEventBase { +class QUOTIENT_API RoomCreateEvent : public StateEventBase { public: DEFINE_EVENT_TYPEID("m.room.create", RoomCreateEvent) diff --git a/lib/events/roomevent.h b/lib/events/roomevent.h index 8be58481..3fbb247e 100644 --- a/lib/events/roomevent.h +++ b/lib/events/roomevent.h @@ -11,7 +11,7 @@ namespace Quotient { class RedactionEvent; /** This class corresponds to m.room.* events */ -class RoomEvent : public Event { +class QUOTIENT_API RoomEvent : public Event { public: static inline _impl::EventFactory factory { "RoomEvent" }; @@ -70,7 +70,7 @@ using RoomEventPtr = event_ptr_tt; using RoomEvents = EventsArray; using RoomEventsRange = Range; -class CallEventBase : public RoomEvent { +class QUOTIENT_API CallEventBase : public RoomEvent { public: CallEventBase(Type type, event_mtype_t matrixType, const QString& callId, int version, const QJsonObject& contentJson = {}); diff --git a/lib/events/roomkeyevent.h b/lib/events/roomkeyevent.h index d021fbec..c4df7936 100644 --- a/lib/events/roomkeyevent.h +++ b/lib/events/roomkeyevent.h @@ -6,7 +6,7 @@ #include "event.h" namespace Quotient { -class RoomKeyEvent : public Event +class QUOTIENT_API RoomKeyEvent : public Event { public: DEFINE_EVENT_TYPEID("m.room_key", RoomKeyEvent) diff --git a/lib/events/roommemberevent.h b/lib/events/roommemberevent.h index 0fb464d4..5e446dbe 100644 --- a/lib/events/roommemberevent.h +++ b/lib/events/roommemberevent.h @@ -10,7 +10,7 @@ #include "quotient_common.h" namespace Quotient { -class MemberEventContent : public EventContent::Base { +class QUOTIENT_API MemberEventContent : public EventContent::Base { public: using MembershipType [[deprecated("Use Quotient::Membership instead")]] = Membership; @@ -33,7 +33,7 @@ protected: using MembershipType [[deprecated("Use Membership instead")]] = Membership; -class RoomMemberEvent : public StateEvent { +class QUOTIENT_API RoomMemberEvent : public StateEvent { Q_GADGET public: DEFINE_EVENT_TYPEID("m.room.member", RoomMemberEvent) @@ -95,6 +95,5 @@ doLoadEvent(const QJsonObject& json, const QString& matrixType) return makeEvent(json); return makeEvent(unknownEventTypeId(), json); } - REGISTER_EVENT_TYPE(RoomMemberEvent) } // namespace Quotient diff --git a/lib/events/roommessageevent.h b/lib/events/roommessageevent.h index 56597ddc..0c901b7a 100644 --- a/lib/events/roommessageevent.h +++ b/lib/events/roommessageevent.h @@ -16,7 +16,7 @@ namespace MessageEventContent = EventContent; // Back-compatibility /** * The event class corresponding to m.room.message events */ -class RoomMessageEvent : public RoomEvent { +class QUOTIENT_API RoomMessageEvent : public RoomEvent { Q_GADGET public: DEFINE_EVENT_TYPEID("m.room.message", RoomMessageEvent) @@ -120,7 +120,7 @@ namespace EventContent { * Available fields: mimeType, body. The body can be either rich text * or plain text, depending on what mimeType specifies. */ - class TextContent : public TypedBase { + class QUOTIENT_API TextContent : public TypedBase { public: TextContent(QString text, const QString& contentType, Omittable relatesTo = none); @@ -149,7 +149,7 @@ namespace EventContent { * - thumbnail.mimeType * - thumbnail.imageSize */ - class LocationContent : public TypedBase { + class QUOTIENT_API LocationContent : public TypedBase { public: LocationContent(const QString& geoUri, const Thumbnail& thumbnail = {}); explicit LocationContent(const QJsonObject& json); @@ -168,7 +168,7 @@ namespace EventContent { * A base class for info types that include duration: audio and video */ template - class PlayableContent : public ContentT { + class QUOTIENT_API PlayableContent : public ContentT { public: using ContentT::ContentT; PlayableContent(const QJsonObject& json) diff --git a/lib/events/roompowerlevelsevent.h b/lib/events/roompowerlevelsevent.h index 0346fc0d..80e27048 100644 --- a/lib/events/roompowerlevelsevent.h +++ b/lib/events/roompowerlevelsevent.h @@ -7,7 +7,7 @@ #include "stateevent.h" namespace Quotient { -class PowerLevelsEventContent : public EventContent::Base { +class QUOTIENT_API PowerLevelsEventContent : public EventContent::Base { public: struct Notifications { int room; @@ -34,7 +34,8 @@ protected: void fillJson(QJsonObject* o) const override; }; -class RoomPowerLevelsEvent : public StateEvent { +class QUOTIENT_API RoomPowerLevelsEvent + : public StateEvent { Q_GADGET public: DEFINE_EVENT_TYPEID("m.room.power_levels", RoomPowerLevelsEvent) @@ -61,9 +62,6 @@ public: int powerLevelForEvent(const QString& eventId) const; int powerLevelForState(const QString& eventId) const; int powerLevelForUser(const QString& userId) const; - -private: }; - REGISTER_EVENT_TYPE(RoomPowerLevelsEvent) } // namespace Quotient diff --git a/lib/events/roomtombstoneevent.h b/lib/events/roomtombstoneevent.h index 30e53738..e336c448 100644 --- a/lib/events/roomtombstoneevent.h +++ b/lib/events/roomtombstoneevent.h @@ -6,7 +6,7 @@ #include "stateevent.h" namespace Quotient { -class RoomTombstoneEvent : public StateEventBase { +class QUOTIENT_API RoomTombstoneEvent : public StateEventBase { public: DEFINE_EVENT_TYPEID("m.room.tombstone", RoomTombstoneEvent) diff --git a/lib/events/simplestateevents.h b/lib/events/simplestateevents.h index 9ce78609..d6557012 100644 --- a/lib/events/simplestateevents.h +++ b/lib/events/simplestateevents.h @@ -30,7 +30,8 @@ namespace EventContent { } // namespace EventContent #define DEFINE_SIMPLE_STATE_EVENT(_Name, _TypeId, _ValueType, _ContentKey) \ - class _Name : public StateEvent> { \ + class QUOTIENT_API _Name \ + : public StateEvent> { \ public: \ using value_type = content_type::value_type; \ DEFINE_EVENT_TYPEID(_TypeId, _Name) \ diff --git a/lib/events/stateevent.h b/lib/events/stateevent.h index c37965aa..6095d628 100644 --- a/lib/events/stateevent.h +++ b/lib/events/stateevent.h @@ -17,7 +17,7 @@ inline QJsonObject basicStateEventJson(const QString& matrixTypeId, { ContentKey, content } }; } -class StateEventBase : public RoomEvent { +class QUOTIENT_API StateEventBase : public RoomEvent { public: static inline _impl::EventFactory factory { "StateEvent" }; diff --git a/lib/events/stickerevent.h b/lib/events/stickerevent.h index 93671086..0957dca3 100644 --- a/lib/events/stickerevent.h +++ b/lib/events/stickerevent.h @@ -11,7 +11,7 @@ namespace Quotient { /// Sticker messages are specialised image messages that are displayed without /// controls (e.g. no "download" link, or light-box view on click, as would be /// displayed for for m.image events). -class StickerEvent : public RoomEvent +class QUOTIENT_API StickerEvent : public RoomEvent { public: DEFINE_EVENT_TYPEID("m.sticker", StickerEvent) diff --git a/lib/events/typingevent.h b/lib/events/typingevent.h index 7456100a..522f7e42 100644 --- a/lib/events/typingevent.h +++ b/lib/events/typingevent.h @@ -6,7 +6,7 @@ #include "event.h" namespace Quotient { -class TypingEvent : public Event { +class QUOTIENT_API TypingEvent : public Event { public: DEFINE_EVENT_TYPEID("m.typing", TypingEvent) diff --git a/lib/eventstats.h b/lib/eventstats.h index 77c661a7..a10c81fb 100644 --- a/lib/eventstats.h +++ b/lib/eventstats.h @@ -16,7 +16,7 @@ namespace Quotient { //! \note It's just a simple grouping of counters and is not automatically //! updated from the room as subsequent syncs arrive. //! \sa Room::unreadStats, Room::partiallyReadStats, Room::isEventNotable -struct EventStats { +struct QUOTIENT_API EventStats { Q_GADGET Q_PROPERTY(qsizetype notableCount MEMBER notableCount CONSTANT) Q_PROPERTY(qsizetype highlightCount MEMBER highlightCount CONSTANT) @@ -109,6 +109,6 @@ public: bool isValidFor(const Room* room, const marker_t& marker) const; }; -QDebug operator<<(QDebug dbg, const EventStats& es); +QUOTIENT_API QDebug operator<<(QDebug dbg, const EventStats& es); } diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index ddf243ed..f41fc63c 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -20,7 +20,7 @@ class ConnectionData; enum class HttpVerb { Get, Put, Post, Delete }; -class BaseJob : public QObject { +class QUOTIENT_API BaseJob : public QObject { Q_OBJECT Q_PROPERTY(QUrl requestUrl READ requestUrl CONSTANT) Q_PROPERTY(int maxRetries READ maxRetries WRITE setMaxRetries) @@ -470,7 +470,7 @@ private: QScopedPointer d; }; -inline bool isJobPending(BaseJob* job) +inline bool QUOTIENT_API isJobPending(BaseJob* job) { return job && job->error() == BaseJob::Pending; } diff --git a/lib/jobs/downloadfilejob.h b/lib/jobs/downloadfilejob.h index 0752af89..d9f3b686 100644 --- a/lib/jobs/downloadfilejob.h +++ b/lib/jobs/downloadfilejob.h @@ -6,7 +6,7 @@ #include "csapi/content-repo.h" namespace Quotient { -class DownloadFileJob : public GetContentJob { +class QUOTIENT_API DownloadFileJob : public GetContentJob { public: using GetContentJob::makeRequestUrl; static QUrl makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri); diff --git a/lib/jobs/mediathumbnailjob.h b/lib/jobs/mediathumbnailjob.h index 3183feb1..c9f6da35 100644 --- a/lib/jobs/mediathumbnailjob.h +++ b/lib/jobs/mediathumbnailjob.h @@ -8,7 +8,7 @@ #include namespace Quotient { -class MediaThumbnailJob : public GetContentThumbnailJob { +class QUOTIENT_API MediaThumbnailJob : public GetContentThumbnailJob { public: using GetContentThumbnailJob::makeRequestUrl; static QUrl makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri, diff --git a/lib/jobs/requestdata.h b/lib/jobs/requestdata.h index 4f05e5ff..41ad833a 100644 --- a/lib/jobs/requestdata.h +++ b/lib/jobs/requestdata.h @@ -3,6 +3,8 @@ #pragma once +#include "quotient_export.h" + #include #include @@ -19,7 +21,7 @@ namespace Quotient { * as well as JSON (and possibly other structures in the future) to * a QByteArray consumed by QNetworkAccessManager request methods. */ -class RequestData { +class QUOTIENT_API RequestData { public: RequestData(const QByteArray& a = {}); RequestData(const QJsonObject& jo); diff --git a/lib/mxcreply.h b/lib/mxcreply.h index efaf01c6..23049b7d 100644 --- a/lib/mxcreply.h +++ b/lib/mxcreply.h @@ -3,13 +3,15 @@ #pragma once +#include "quotient_export.h" + #include #include namespace Quotient { class Room; -class MxcReply : public QNetworkReply +class QUOTIENT_API MxcReply : public QNetworkReply { public: explicit MxcReply(); diff --git a/lib/networkaccessmanager.h b/lib/networkaccessmanager.h index 87bc12a1..d06f9736 100644 --- a/lib/networkaccessmanager.h +++ b/lib/networkaccessmanager.h @@ -3,6 +3,8 @@ #pragma once +#include "quotient_export.h" + #include #include @@ -10,7 +12,7 @@ namespace Quotient { class Room; class Connection; -class NetworkAccessManager : public QNetworkAccessManager { +class QUOTIENT_API NetworkAccessManager : public QNetworkAccessManager { Q_OBJECT public: NetworkAccessManager(QObject* parent = nullptr); diff --git a/lib/networksettings.h b/lib/networksettings.h index df11a9c8..c1446355 100644 --- a/lib/networksettings.h +++ b/lib/networksettings.h @@ -10,7 +10,7 @@ Q_DECLARE_METATYPE(QNetworkProxy::ProxyType) namespace Quotient { -class NetworkSettings : public SettingsGroup { +class QUOTIENT_API NetworkSettings : public SettingsGroup { Q_OBJECT QTNT_DECLARE_SETTING(QNetworkProxy::ProxyType, proxyType, setProxyType) QTNT_DECLARE_SETTING(QString, proxyHostName, setProxyHostName) diff --git a/lib/quotient_common.h b/lib/quotient_common.h index 0e3e2a40..a5926e8c 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -3,6 +3,8 @@ #pragma once +#include "quotient_export.h" + #include #include @@ -26,8 +28,21 @@ #define DECL_DEPRECATED_ENUMERATOR(Deprecated, Recommended) \ Deprecated Q_DECL_ENUMERATOR_DEPRECATED_X("Use " #Recommended) = Recommended +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) +// The first line is a usual way to indicate a namespace to moc; +// the second line redeclares the namespace static metaobject with +// QUOTIENT_API so that dynamically linked clients could serialise +// flag/enum values from the namespace. +#define QUO_NAMESPACE \ +Q_NAMESPACE \ +extern QUOTIENT_API const QMetaObject staticMetaObject; +#else +// Since Qt 5.14.0, it's all packed in a single macro +#define QUO_NAMESPACE Q_NAMESPACE_EXPORT(QUOTIENT_API) +#endif + namespace Quotient { -Q_NAMESPACE +QUO_NAMESPACE // std::array {} needs explicit template parameters on macOS because // Apple stdlib doesn't have deduction guides for std::array. C++20 has diff --git a/lib/room.h b/lib/room.h index 85c51a87..63a4aaea 100644 --- a/lib/room.h +++ b/lib/room.h @@ -45,7 +45,7 @@ class RedactEventJob; * This is specifically tuned to work with QML exposing all traits as * Q_PROPERTY values. */ -class FileTransferInfo { +class QUOTIENT_API FileTransferInfo { Q_GADGET Q_PROPERTY(bool isUpload MEMBER isUpload CONSTANT) Q_PROPERTY(bool active READ active CONSTANT) @@ -73,7 +73,7 @@ public: //! \brief Data structure for a room member's read receipt //! \sa Room::lastReadReceipt -class ReadReceipt { +class QUOTIENT_API ReadReceipt { Q_GADGET Q_PROPERTY(QString eventId MEMBER eventId CONSTANT) Q_PROPERTY(QDateTime timestamp MEMBER timestamp CONSTANT) @@ -110,7 +110,7 @@ private: Q_PROPERTY(Type type MEMBER type CONSTANT) }; -class Room : public QObject { +class QUOTIENT_API Room : public QObject { Q_OBJECT Q_PROPERTY(Connection* connection READ connection CONSTANT) Q_PROPERTY(User* localUser READ localUser CONSTANT) @@ -1037,7 +1037,7 @@ private: void setJoinState(JoinState state); }; -class MemberSorter { +class QUOTIENT_API MemberSorter { public: explicit MemberSorter(const Room* r) : room(r) {} diff --git a/lib/settings.h b/lib/settings.h index efd0d714..b66879c5 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -3,6 +3,8 @@ #pragma once +#include "quotient_export.h" + #include #include #include @@ -11,7 +13,7 @@ class QVariant; namespace Quotient { -class Settings : public QSettings { +class QUOTIENT_API Settings : public QSettings { Q_OBJECT public: /// Add a legacy organisation/application name to migrate settings from @@ -76,7 +78,7 @@ protected: QSettings legacySettings { legacyOrganizationName, legacyApplicationName }; }; -class SettingsGroup : public Settings { +class QUOTIENT_API SettingsGroup : public Settings { public: explicit SettingsGroup(QString path, QObject* parent = nullptr) : Settings(parent) @@ -124,7 +126,7 @@ private: setValue(QStringLiteral(qsettingname), std::move(newValue)); \ } -class AccountSettings : public SettingsGroup { +class QUOTIENT_API AccountSettings : public SettingsGroup { Q_OBJECT Q_PROPERTY(QString userId READ userId CONSTANT) QTNT_DECLARE_SETTING(QString, deviceId, setDeviceId) diff --git a/lib/ssosession.h b/lib/ssosession.h index 72dd60c4..a658c043 100644 --- a/lib/ssosession.h +++ b/lib/ssosession.h @@ -3,6 +3,8 @@ #pragma once +#include "quotient_export.h" + #include #include @@ -29,7 +31,7 @@ class Connection; * connection->prepareForSso(initialDeviceName)->ssoUrl()); * \endcode */ -class SsoSession : public QObject { +class QUOTIENT_API SsoSession : public QObject { Q_OBJECT Q_PROPERTY(QUrl ssoUrl READ ssoUrl CONSTANT) Q_PROPERTY(QUrl callbackUrl READ callbackUrl CONSTANT) diff --git a/lib/syncdata.h b/lib/syncdata.h index 36d2e0bf..e29540c2 100644 --- a/lib/syncdata.h +++ b/lib/syncdata.h @@ -22,7 +22,7 @@ constexpr auto HighlightCountKey = "highlight_count"_ls; * means that nothing has come from the server; heroes.value().isEmpty() * means a peculiar case of a room with the only member - the current user. */ -struct RoomSummary { +struct QUOTIENT_API RoomSummary { Omittable joinedMemberCount; Omittable invitedMemberCount; Omittable heroes; //< mxids of users to take part in the room diff --git a/lib/uri.h b/lib/uri.h index d8b892b6..78cd27c8 100644 --- a/lib/uri.h +++ b/lib/uri.h @@ -23,7 +23,7 @@ namespace Quotient { * its type, and obtain components, also in either unencoded (for displaying) * or encoded (for APIs) form. */ -class Uri : private QUrl { +class QUOTIENT_API Uri : private QUrl { Q_GADGET public: enum Type : char { diff --git a/lib/uriresolver.h b/lib/uriresolver.h index ff97324a..9140046c 100644 --- a/lib/uriresolver.h +++ b/lib/uriresolver.h @@ -25,7 +25,7 @@ class User; * gradual implementation. Derived classes are encouraged to override as many * of them as possible. */ -class UriResolverBase { +class QUOTIENT_API UriResolverBase { public: /*! \brief Resolve the resource and dispatch an action depending on its type * @@ -105,7 +105,7 @@ protected: * * \sa UriResolverBase, UriDispatcher */ -UriResolveResult +QUOTIENT_API UriResolveResult visitResource(Connection* account, const Uri& uri, std::function userHandler, std::function roomEventHandler, @@ -141,7 +141,7 @@ inline UriResolveResult checkResource(Connection* account, const Uri& uri) * synchronously - the returned value is the result of resolving the URI, * not acting on it. */ -class UriDispatcher : public QObject, public UriResolverBase { +class QUOTIENT_API UriDispatcher : public QObject, public UriResolverBase { Q_OBJECT public: explicit UriDispatcher(QObject* parent = nullptr) : QObject(parent) {} diff --git a/lib/user.h b/lib/user.h index 78b72bf2..435304ce 100644 --- a/lib/user.h +++ b/lib/user.h @@ -5,6 +5,7 @@ #pragma once #include "avatar.h" +#include "quotient_export.h" #include @@ -13,7 +14,7 @@ class Connection; class Room; class RoomMemberEvent; -class User : public QObject { +class QUOTIENT_API User : public QObject { Q_OBJECT Q_PROPERTY(QString id READ id CONSTANT) Q_PROPERTY(bool isGuest READ isGuest CONSTANT) diff --git a/lib/util.h b/lib/util.h index 97f0ecbc..399f93c2 100644 --- a/lib/util.h +++ b/lib/util.h @@ -4,6 +4,8 @@ #pragma once +#include "quotient_export.h" + #include #include @@ -244,26 +246,26 @@ inline std::pair findFirstOf(InputIt first, InputIt last, } /** Convert what looks like a URL or a Matrix ID to an HTML hyperlink */ -void linkifyUrls(QString& htmlEscapedText); +QUOTIENT_API void linkifyUrls(QString& htmlEscapedText); /** Sanitize the text before showing in HTML * * This does toHtmlEscaped() and removes Unicode BiDi marks. */ -QString sanitized(const QString& plainText); +QUOTIENT_API QString sanitized(const QString& plainText); /** Pretty-print plain text into HTML * * This includes HTML escaping of <,>,",& and calling linkifyUrls() */ -QString prettyPrint(const QString& plainText); +QUOTIENT_API QString prettyPrint(const QString& plainText); /** Return a path to cache directory after making sure that it exists * * The returned path has a trailing slash, clients don't need to append it. * \param dir path to cache directory relative to the standard cache path */ -QString cacheLocation(const QString& dirName); +QUOTIENT_API QString cacheLocation(const QString& dirName); /** Hue color component of based of the hash of the string. * @@ -272,13 +274,13 @@ QString cacheLocation(const QString& dirName); * Naming and range are the same as QColor's hueF method: * https://doc.qt.io/qt-5/qcolor.html#integer-vs-floating-point-precision */ -qreal stringToHueF(const QString& s); +QUOTIENT_API qreal stringToHueF(const QString& s); /** Extract the serverpart from MXID */ -QString serverPart(const QString& mxId); +QUOTIENT_API QString serverPart(const QString& mxId); -QString versionString(); -int majorVersion(); -int minorVersion(); -int patchVersion(); +QUOTIENT_API QString versionString(); +QUOTIENT_API int majorVersion(); +QUOTIENT_API int minorVersion(); +QUOTIENT_API int patchVersion(); } // namespace Quotient -- cgit v1.2.3 From 5b8ea1a0d419fda1729aaa81e34ad20e0dacef44 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Thu, 30 Dec 2021 10:40:07 +0100 Subject: Try to fix building with MSVC with Qt pre-5.14 MSVC is quite picky to redeclaration with __declspec(dllexport), judging it as changing the class of storage. This commit tries to reorder declarations so that MSVC is made aware of dllexport attribute on the first encounter rather than the second one. --- lib/quotient_common.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'lib/quotient_common.h') diff --git a/lib/quotient_common.h b/lib/quotient_common.h index a5926e8c..3d38ce1f 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -29,13 +29,13 @@ Deprecated Q_DECL_ENUMERATOR_DEPRECATED_X("Use " #Recommended) = Recommended #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) -// The first line is a usual way to indicate a namespace to moc; -// the second line redeclares the namespace static metaobject with -// QUOTIENT_API so that dynamically linked clients could serialise -// flag/enum values from the namespace. +// The first line forward-declares the namespace static metaobject with +// QUOTIENT_API so that dynamically linked clients could serialise flag/enum +// values from the namespace; Qt before 5.14 doesn't help with that. The second +// line is needed for moc to do its job on the namespace. #define QUO_NAMESPACE \ -Q_NAMESPACE \ -extern QUOTIENT_API const QMetaObject staticMetaObject; + extern QUOTIENT_API const QMetaObject staticMetaObject; \ + Q_NAMESPACE #else // Since Qt 5.14.0, it's all packed in a single macro #define QUO_NAMESPACE Q_NAMESPACE_EXPORT(QUOTIENT_API) -- cgit v1.2.3 From bd280a087ecab30f94f7937513ee298c233fcba1 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Tue, 18 Jan 2022 08:54:52 +0100 Subject: Revise inline keyword usage - Templates and constexpr imply inline - A function called from a single site better be inlined. --- lib/events/event.h | 2 +- lib/jobs/basejob.h | 2 +- lib/quotient_common.h | 8 +++----- lib/uri.cpp | 2 +- lib/util.h | 8 ++++---- 5 files changed, 10 insertions(+), 12 deletions(-) (limited to 'lib/quotient_common.h') diff --git a/lib/events/event.h b/lib/events/event.h index 858972da..f10f6a8d 100644 --- a/lib/events/event.h +++ b/lib/events/event.h @@ -311,7 +311,7 @@ inline auto switchOnType(const BaseEventT& event, FnT&& fn) namespace _impl { // Using bool instead of auto below because auto apparently upsets MSVC template - inline constexpr bool needs_downcast = + constexpr bool needs_downcast = std::is_base_of_v>> && !std::is_same_v>>; } diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 1567e635..9ed58ba8 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -28,7 +28,7 @@ class QUOTIENT_API BaseJob : public QObject { static QByteArray encodeIfParam(const QString& paramPart); template - static inline auto encodeIfParam(const char (&constPart)[N]) + static auto encodeIfParam(const char (&constPart)[N]) { return constPart; } diff --git a/lib/quotient_common.h b/lib/quotient_common.h index 3d38ce1f..af3e2730 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -77,7 +77,7 @@ enum class Membership : unsigned int { }; QUO_DECLARE_FLAGS_NS(MembershipMask, Membership) -constexpr inline auto MembershipStrings = make_array( +constexpr auto MembershipStrings = make_array( // The order MUST be the same as the order in the original enum "join", "leave", "invite", "knock", "ban"); @@ -95,7 +95,7 @@ enum class JoinState : std::underlying_type_t { }; QUO_DECLARE_FLAGS_NS(JoinStates, JoinState) -constexpr inline auto JoinStateStrings = make_array( +constexpr auto JoinStateStrings = make_array( MembershipStrings[0], MembershipStrings[1], MembershipStrings[2], MembershipStrings[3] /* same as MembershipStrings, sans "ban" */ ); @@ -125,9 +125,7 @@ enum RoomType { }; Q_ENUM_NS(RoomType) -constexpr inline auto RoomTypeStrings = make_array( - "m.space" -); +constexpr auto RoomTypeStrings = make_array("m.space"); } // namespace Quotient Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::MembershipMask) diff --git a/lib/uri.cpp b/lib/uri.cpp index c8843dda..3ce81a21 100644 --- a/lib/uri.cpp +++ b/lib/uri.cpp @@ -75,7 +75,7 @@ static auto decodeFragmentPart(QStringView part) return QUrl::fromPercentEncoding(part.toLatin1()).toUtf8(); } -static auto matrixToUrlRegexInit() +static inline auto matrixToUrlRegexInit() { // See https://matrix.org/docs/spec/appendices#matrix-to-navigation const QRegularExpression MatrixToUrlRE { diff --git a/lib/util.h b/lib/util.h index 66db0ece..3505b62f 100644 --- a/lib/util.h +++ b/lib/util.h @@ -54,9 +54,9 @@ using UnorderedMap = std::unordered_map>; namespace _impl { template - constexpr inline auto IsOmittableValue = false; + constexpr auto IsOmittableValue = false; template - constexpr inline auto IsOmittable = IsOmittableValue>; + constexpr auto IsOmittable = IsOmittableValue>; } constexpr auto none = std::nullopt; @@ -165,7 +165,7 @@ Omittable(T&&) -> Omittable; namespace _impl { template - constexpr inline auto IsOmittableValue> = true; + constexpr auto IsOmittableValue> = true; } template @@ -191,7 +191,7 @@ inline auto merge(T1& lhs, const Omittable& rhs) return true; } -inline constexpr auto operator"" _ls(const char* s, std::size_t size) +constexpr auto operator"" _ls(const char* s, std::size_t size) { return QLatin1String(s, int(size)); } -- cgit v1.2.3 From b17b629df44dbc888f6b6bee79d0d13d662371cf Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Tue, 18 Jan 2022 08:55:10 +0100 Subject: Add [[maybe_unused]] to things the lib doesn't use --- lib/function_traits.cpp | 2 +- lib/quotient_common.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/quotient_common.h') diff --git a/lib/function_traits.cpp b/lib/function_traits.cpp index 20bcf30e..6542101a 100644 --- a/lib/function_traits.cpp +++ b/lib/function_traits.cpp @@ -47,7 +47,7 @@ static_assert(std::is_same_v, int>, "Test fn_arg_t defaulting to first argument"); template -static void ft(const std::vector&); +[[maybe_unused]] static void ft(const std::vector&); static_assert( std::is_same)>, const std::vector&>(), "Test function templates"); diff --git a/lib/quotient_common.h b/lib/quotient_common.h index af3e2730..02a9f0cd 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -95,7 +95,7 @@ enum class JoinState : std::underlying_type_t { }; QUO_DECLARE_FLAGS_NS(JoinStates, JoinState) -constexpr auto JoinStateStrings = make_array( +[[maybe_unused]] constexpr auto JoinStateStrings = make_array( MembershipStrings[0], MembershipStrings[1], MembershipStrings[2], MembershipStrings[3] /* same as MembershipStrings, sans "ban" */ ); @@ -125,7 +125,7 @@ enum RoomType { }; Q_ENUM_NS(RoomType) -constexpr auto RoomTypeStrings = make_array("m.space"); +[[maybe_unused]] constexpr auto RoomTypeStrings = make_array("m.space"); } // namespace Quotient Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::MembershipMask) -- cgit v1.2.3 From 1747575321cda4fc11f90c2ffb2148a69d0d9946 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Fri, 28 Jan 2022 17:08:10 +0100 Subject: QUO_IMPLICIT Because Apple Clang choked on `explicit(false)`. --- lib/events/encryptionevent.h | 3 ++- lib/events/roommemberevent.h | 2 +- lib/quotient_common.h | 7 +++++++ 3 files changed, 10 insertions(+), 2 deletions(-) (limited to 'lib/quotient_common.h') diff --git a/lib/events/encryptionevent.h b/lib/events/encryptionevent.h index 56913393..124ced33 100644 --- a/lib/events/encryptionevent.h +++ b/lib/events/encryptionevent.h @@ -6,13 +6,14 @@ #include "eventcontent.h" #include "stateevent.h" +#include "quotient_common.h" namespace Quotient { class QUOTIENT_API EncryptionEventContent : public EventContent::Base { public: enum EncryptionType : size_t { MegolmV1AesSha2 = 0, Undefined }; - explicit(false) EncryptionEventContent(EncryptionType et); + QUO_IMPLICIT EncryptionEventContent(EncryptionType et); [[deprecated("This constructor will require explicit EncryptionType soon")]] // explicit EncryptionEventContent() : EncryptionEventContent(Undefined) diff --git a/lib/events/roommemberevent.h b/lib/events/roommemberevent.h index 3296ae22..ceb7826b 100644 --- a/lib/events/roommemberevent.h +++ b/lib/events/roommemberevent.h @@ -15,7 +15,7 @@ public: using MembershipType [[deprecated("Use Quotient::Membership instead")]] = Membership; - explicit(false) MemberEventContent(Membership ms) : membership(ms) {} + QUO_IMPLICIT MemberEventContent(Membership ms) : membership(ms) {} explicit MemberEventContent(const QJsonObject& json); Membership membership; diff --git a/lib/quotient_common.h b/lib/quotient_common.h index 02a9f0cd..b3fb3efa 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -25,6 +25,13 @@ Q_ENUM_NS_IMPL(Enum) \ Q_FLAG_NS(Flags) +// Apple Clang hasn't caught up with explicit(bool) yet +#if __cpp_conditional_explicit >= 201806L +#define QUO_IMPLICIT explicit(false) +#else +#define QUO_IMPLICIT +#endif + #define DECL_DEPRECATED_ENUMERATOR(Deprecated, Recommended) \ Deprecated Q_DECL_ENUMERATOR_DEPRECATED_X("Use " #Recommended) = Recommended -- cgit v1.2.3 From 4f581f22d707fd226a56400817c9e47e54116589 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Fri, 11 Feb 2022 14:21:25 +0100 Subject: Better documentation for QUO_DECLARE_FLAGS[_NS] --- lib/quotient_common.h | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'lib/quotient_common.h') diff --git a/lib/quotient_common.h b/lib/quotient_common.h index b3fb3efa..2b785a39 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -9,17 +9,33 @@ #include -// See https://bugreports.qt.io/browse/QTBUG-82295 - despite the comment that -// Q_FLAG[_NS] "should" be applied to the enum only, Qt doesn't allow to wrap -// a flag type into a QVariant then. The macros below define Q_FLAG[_NS] and on -// top of that add Q_ENUM[_NS]_IMPL which is a part of Q_ENUM() macro that -// enables the metatype data but goes under the moc radar to avoid double -// registration of the same data in the map defined in moc_*.cpp + +//! \brief Quotient replacement for the Q_FLAG/Q_DECLARE_FLAGS combination +//! +//! Although the comment in QTBUG-82295 says that Q_FLAG[_NS] "should" be +//! applied to the enum type only, Qt then doesn't allow to wrap the +//! corresponding flag type (defined with Q_DECLARE_FLAGS) into a QVariant. +//! This macro defines Q_FLAG and on top of that adds Q_ENUM_IMPL which is +//! a part of Q_ENUM() macro that enables the metatype data but goes under +//! the moc radar to avoid double registration of the same data in the map +//! defined in moc_*.cpp. +//! +//! Simply put, instead of using Q_FLAG/Q_DECLARE_FLAGS combo (and struggling +//! to figure out what you should pass to Q_FLAG if you want to make it +//! wrappable in a QVariant) use the macro below, and things will just work. +//! +//! \sa https://bugreports.qt.io/browse/QTBUG-82295 #define QUO_DECLARE_FLAGS(Flags, Enum) \ Q_DECLARE_FLAGS(Flags, Enum) \ Q_ENUM_IMPL(Enum) \ Q_FLAG(Flags) +//! \brief Quotient replacement for the Q_FLAG_NS/Q_DECLARE_FLAGS combination +//! +//! This is the equivalent of QUO_DECLARE_FLAGS for enums declared at the +//! namespace level (be sure to provide Q_NAMESPACE _in the same file_ +//! as the enum definition and this macro). +//! \sa QUO_DECLARE_FLAGS #define QUO_DECLARE_FLAGS_NS(Flags, Enum) \ Q_DECLARE_FLAGS(Flags, Enum) \ Q_ENUM_NS_IMPL(Enum) \ -- cgit v1.2.3 From 6b355d1aa87072143e09ea5269e8cf465318a64f Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 18 Jun 2022 21:26:43 +0200 Subject: Drop pre-Qt 5.15 code --- lib/connection.cpp | 16 ---------------- lib/converters.h | 10 +--------- lib/eventitem.h | 2 +- lib/jobs/basejob.cpp | 8 +------- lib/logging.h | 7 +------ lib/mxcreply.cpp | 8 +------- lib/networkaccessmanager.cpp | 15 +-------------- lib/quotient_common.h | 15 +-------------- lib/room.cpp | 7 ++----- lib/syncdata.cpp | 7 +------ 10 files changed, 10 insertions(+), 85 deletions(-) (limited to 'lib/quotient_common.h') diff --git a/lib/connection.cpp b/lib/connection.cpp index c390cc05..2319a38a 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -49,10 +49,6 @@ # include #endif -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) -# include -#endif - #include #include #include @@ -1826,16 +1822,10 @@ void Connection::saveRoomState(Room* r) const QFile outRoomFile { stateCacheDir().filePath( SyncData::fileNameForRoom(r->id())) }; if (outRoomFile.open(QFile::WriteOnly)) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) const auto data = d->cacheToBinary ? QCborValue::fromJsonValue(r->toJson()).toCbor() : QJsonDocument(r->toJson()).toJson(QJsonDocument::Compact); -#else - QJsonDocument json { r->toJson() }; - const auto data = d->cacheToBinary ? json.toBinaryData() - : json.toJson(QJsonDocument::Compact); -#endif outRoomFile.write(data.data(), data.size()); qCDebug(MAIN) << "Room state cache saved to" << outRoomFile.fileName(); } else { @@ -1905,15 +1895,9 @@ void Connection::saveState() const } #endif -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) const auto data = d->cacheToBinary ? QCborValue::fromJsonValue(rootObj).toCbor() : QJsonDocument(rootObj).toJson(QJsonDocument::Compact); -#else - QJsonDocument json { rootObj }; - const auto data = d->cacheToBinary ? json.toBinaryData() - : json.toJson(QJsonDocument::Compact); -#endif qCDebug(PROFILER) << "Cache for" << userId() << "generated in" << et; outFile.write(data.data(), data.size()); diff --git a/lib/converters.h b/lib/converters.h index da30cae6..c985fd60 100644 --- a/lib/converters.h +++ b/lib/converters.h @@ -188,15 +188,7 @@ inline QDateTime fromJson(const QJsonValue& jv) return QDateTime::fromMSecsSinceEpoch(fromJson(jv), Qt::UTC); } -inline QJsonValue toJson(const QDate& val) { - return toJson( -#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) - QDateTime(val) -#else - val.startOfDay() -#endif - ); -} +inline QJsonValue toJson(const QDate& val) { return toJson(val.startOfDay()); } template <> inline QDate fromJson(const QJsonValue& jv) { diff --git a/lib/eventitem.h b/lib/eventitem.h index 5e001d88..e476c66c 100644 --- a/lib/eventitem.h +++ b/lib/eventitem.h @@ -14,7 +14,7 @@ namespace Quotient { namespace EventStatus { - QUO_NAMESPACE + Q_NAMESPACE_EXPORT(QUOTIENT_API) /** Special marks an event can assume * diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index b6858b5a..fe70911e 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -301,16 +301,10 @@ void BaseJob::Private::sendRequest() QNetworkRequest::NoLessSafeRedirectPolicy); req.setMaximumRedirectsAllowed(10); req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); - req.setAttribute( -#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) - QNetworkRequest::Http2AllowedAttribute -#else - QNetworkRequest::HTTP2AllowedAttribute -#endif // Qt doesn't combine HTTP2 with SSL quite right, occasionally crashing at // what seems like an attempt to write to a closed channel. If/when that // changes, false should be turned to true below. - , false); + req.setAttribute(QNetworkRequest::Http2AllowedAttribute, false); Q_ASSERT(req.url().isValid()); for (auto it = requestHeaders.cbegin(); it != requestHeaders.cend(); ++it) req.setRawHeader(it.key(), it.value()); diff --git a/lib/logging.h b/lib/logging.h index fc0a4c99..c8d17210 100644 --- a/lib/logging.h +++ b/lib/logging.h @@ -44,12 +44,7 @@ inline QDebug formatJson(QDebug debug_object) //! Suppress full qualification of enums/QFlags when logging inline QDebug terse(QDebug dbg) { - return -#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0) - dbg.setVerbosity(0), dbg; -#else - dbg.verbosity(QDebug::MinimumVerbosity); -#endif + return dbg.verbosity(QDebug::MinimumVerbosity); } inline qint64 profilerMinNsecs() diff --git a/lib/mxcreply.cpp b/lib/mxcreply.cpp index 4174cfd8..c7547be8 100644 --- a/lib/mxcreply.cpp +++ b/lib/mxcreply.cpp @@ -71,12 +71,6 @@ MxcReply::MxcReply(QNetworkReply* reply, Room* room, const QString &eventId) #endif } -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) -#define ERROR_SIGNAL errorOccurred -#else -#define ERROR_SIGNAL error -#endif - MxcReply::MxcReply() : d(ZeroImpl()) { @@ -88,7 +82,7 @@ MxcReply::MxcReply() setError(QNetworkReply::ProtocolInvalidOperationError, BadRequestPhrase); setFinished(true); - emit ERROR_SIGNAL(QNetworkReply::ProtocolInvalidOperationError); + emit errorOccurred(QNetworkReply::ProtocolInvalidOperationError); emit finished(); }, Qt::QueuedConnection); } diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp index f4e7b1af..38ab07cc 100644 --- a/lib/networkaccessmanager.cpp +++ b/lib/networkaccessmanager.cpp @@ -68,24 +68,11 @@ void NetworkAccessManager::clearIgnoredSslErrors() d->ignoredSslErrors.clear(); } -static NetworkAccessManager* createNam() -{ - auto nam = new NetworkAccessManager(); -#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0)) - // See #109; in newer Qt, bearer management is deprecated altogether - NetworkAccessManager::connect(nam, - &QNetworkAccessManager::networkAccessibleChanged, [nam] { - nam->setNetworkAccessible(QNetworkAccessManager::Accessible); - }); -#endif - return nam; -} - NetworkAccessManager* NetworkAccessManager::instance() { static QThreadStorage storage; if(!storage.hasLocalData()) { - storage.setLocalData(createNam()); + storage.setLocalData(new NetworkAccessManager()); } return storage.localData(); } diff --git a/lib/quotient_common.h b/lib/quotient_common.h index 2b785a39..8bcd5ca6 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -51,21 +51,8 @@ #define DECL_DEPRECATED_ENUMERATOR(Deprecated, Recommended) \ Deprecated Q_DECL_ENUMERATOR_DEPRECATED_X("Use " #Recommended) = Recommended -#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) -// The first line forward-declares the namespace static metaobject with -// QUOTIENT_API so that dynamically linked clients could serialise flag/enum -// values from the namespace; Qt before 5.14 doesn't help with that. The second -// line is needed for moc to do its job on the namespace. -#define QUO_NAMESPACE \ - extern QUOTIENT_API const QMetaObject staticMetaObject; \ - Q_NAMESPACE -#else -// Since Qt 5.14.0, it's all packed in a single macro -#define QUO_NAMESPACE Q_NAMESPACE_EXPORT(QUOTIENT_API) -#endif - namespace Quotient { -QUO_NAMESPACE +Q_NAMESPACE_EXPORT(QUOTIENT_API) // std::array {} needs explicit template parameters on macOS because // Apple stdlib doesn't have deduction guides for std::array. C++20 has diff --git a/lib/room.cpp b/lib/room.cpp index f692c354..e07de123 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -1974,11 +1974,8 @@ void Room::Private::postprocessChanges(Changes changes, bool saveState) if (changes & Change::Highlights) emit q->highlightCountChanged(); - qCDebug(MAIN) << terse << changes << "= hex" << -#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) - Qt:: -#endif - hex << uint(changes) << "in" << q->objectName(); + qCDebug(MAIN) << terse << changes << "= hex" << Qt::hex << uint(changes) + << "in" << q->objectName(); emit q->changed(changes); if (saveState) connection->saveRoomState(q); diff --git a/lib/syncdata.cpp b/lib/syncdata.cpp index 95d3c7e4..ff3dc0c2 100644 --- a/lib/syncdata.cpp +++ b/lib/syncdata.cpp @@ -179,12 +179,7 @@ QJsonObject SyncData::loadJson(const QString& fileName) const auto json = data.startsWith('{') ? QJsonDocument::fromJson(data).object() -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) - : QCborValue::fromCbor(data).toJsonValue().toObject() -#else - : QJsonDocument::fromBinaryData(data).object() -#endif - ; + : QCborValue::fromCbor(data).toJsonValue().toObject(); if (json.isEmpty()) { qCWarning(MAIN) << "State cache in" << fileName << "is broken or empty, discarding"; -- cgit v1.2.3 From 5a63f8a18645d612decdcc853335df0682c41d03 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 18 Jun 2022 21:29:27 +0200 Subject: Drop make_array(); use std::to_array() where needed make_array() has been introduced to cover for shortcomings on macOS and Windows. These shortcomings are no more there, so we can just use the standardrlibrary. --- lib/e2ee/e2ee.h | 5 +++-- lib/events/encryptionevent.cpp | 4 +--- lib/jobs/basejob.cpp | 20 ++++++++++---------- lib/quotient_common.h | 27 +++++++-------------------- 4 files changed, 21 insertions(+), 35 deletions(-) (limited to 'lib/quotient_common.h') diff --git a/lib/e2ee/e2ee.h b/lib/e2ee/e2ee.h index f97eb27a..1efd0f16 100644 --- a/lib/e2ee/e2ee.h +++ b/lib/e2ee/e2ee.h @@ -37,8 +37,9 @@ constexpr auto MegolmV1AesSha2AlgoKey = "m.megolm.v1.aes-sha2"_ls; inline bool isSupportedAlgorithm(const QString& algorithm) { - static constexpr auto SupportedAlgorithms = - make_array(OlmV1Curve25519AesSha2AlgoKey, MegolmV1AesSha2AlgoKey); + static constexpr std::array SupportedAlgorithms { + OlmV1Curve25519AesSha2AlgoKey, MegolmV1AesSha2AlgoKey + }; return std::find(SupportedAlgorithms.cbegin(), SupportedAlgorithms.cend(), algorithm) != SupportedAlgorithms.cend(); diff --git a/lib/events/encryptionevent.cpp b/lib/events/encryptionevent.cpp index 6e994cd4..eb15f38e 100644 --- a/lib/events/encryptionevent.cpp +++ b/lib/events/encryptionevent.cpp @@ -9,9 +9,7 @@ #include namespace Quotient { -static const std::array encryptionStrings = { - { MegolmV1AesSha2AlgoKey } -}; +static constexpr std::array encryptionStrings { MegolmV1AesSha2AlgoKey }; template <> struct JsonConverter { diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index fe70911e..da645a2d 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -138,9 +138,8 @@ public: QTimer timer; QTimer retryTimer; - static constexpr std::array errorStrategy { - { { 90s, 5s }, { 90s, 10s }, { 120s, 30s } } - }; + static constexpr auto errorStrategy = std::to_array( + { { 90s, 5s }, { 90s, 10s }, { 120s, 30s } }); int maxRetries = int(errorStrategy.size()); int retriesTaken = 0; @@ -152,10 +151,8 @@ public: [[nodiscard]] QString dumpRequest() const { - // FIXME: use std::array {} when Apple stdlib gets deduction guides for it - static const auto verbs = - make_array(QStringLiteral("GET"), QStringLiteral("PUT"), - QStringLiteral("POST"), QStringLiteral("DELETE")); + static const std::array verbs { "GET"_ls, "PUT"_ls, "POST"_ls, + "DELETE"_ls }; const auto verbWord = verbs.at(size_t(verb)); return verbWord % ' ' % (reply ? reply->url().toString(QUrl::RemoveQuery) @@ -748,11 +745,14 @@ QString BaseJob::statusCaption() const } } -int BaseJob::error() const { return d->status.code; } +int BaseJob::error() const { + return d->status.code; } -QString BaseJob::errorString() const { return d->status.message; } +QString BaseJob::errorString() const { + return d->status.message; } -QUrl BaseJob::errorUrl() const { return d->errorUrl; } +QUrl BaseJob::errorUrl() const { + return d->errorUrl; } void BaseJob::setStatus(Status s) { diff --git a/lib/quotient_common.h b/lib/quotient_common.h index 8bcd5ca6..136e9f79 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -41,7 +41,6 @@ Q_ENUM_NS_IMPL(Enum) \ Q_FLAG_NS(Flags) -// Apple Clang hasn't caught up with explicit(bool) yet #if __cpp_conditional_explicit >= 201806L #define QUO_IMPLICIT explicit(false) #else @@ -54,19 +53,6 @@ namespace Quotient { Q_NAMESPACE_EXPORT(QUOTIENT_API) -// std::array {} needs explicit template parameters on macOS because -// Apple stdlib doesn't have deduction guides for std::array. C++20 has -// to_array() but that can't be borrowed, this time because of MSVC: -// https://developercommunity.visualstudio.com/t/vc-ice-p1-initc-line-3652-from-stdto-array/1464038 -// Therefore a simpler (but also slightly more wobbly - it resolves the element -// type using std::common_type<>) make_array facility is implemented here. -template -constexpr auto make_array(Ts&&... items) -{ - return std::array, sizeof...(items)>( - { std::forward(items)... }); -} - // TODO: code like this should be generated from the CS API definition //! \brief Membership states @@ -87,9 +73,10 @@ enum class Membership : unsigned int { }; QUO_DECLARE_FLAGS_NS(MembershipMask, Membership) -constexpr auto MembershipStrings = make_array( - // The order MUST be the same as the order in the original enum - "join", "leave", "invite", "knock", "ban"); +constexpr std::array MembershipStrings { + // The order MUST be the same as the order in the Membership enum + "join", "leave", "invite", "knock", "ban" +}; //! \brief Local user join-state names //! @@ -105,10 +92,10 @@ enum class JoinState : std::underlying_type_t { }; QUO_DECLARE_FLAGS_NS(JoinStates, JoinState) -[[maybe_unused]] constexpr auto JoinStateStrings = make_array( +[[maybe_unused]] constexpr std::array JoinStateStrings { MembershipStrings[0], MembershipStrings[1], MembershipStrings[2], MembershipStrings[3] /* same as MembershipStrings, sans "ban" */ -); +}; //! \brief Network job running policy flags //! @@ -135,7 +122,7 @@ enum RoomType { }; Q_ENUM_NS(RoomType) -[[maybe_unused]] constexpr auto RoomTypeStrings = make_array("m.space"); +[[maybe_unused]] constexpr std::array RoomTypeStrings { "m.space" }; } // namespace Quotient Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::MembershipMask) -- cgit v1.2.3 From 7ef84728ab3744192583eb587a4585c576f5a176 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 18 Jun 2022 21:39:42 +0200 Subject: Move C++-only macros to util.h This pertains to QUO_IMPLICIT and DECL_DEPRECATED_ENUMERATOR - both can be used with no connection to Qt meta-type system (which is what quotient_common.h is for). --- lib/e2ee/e2ee.h | 3 +-- lib/events/encryptionevent.cpp | 2 -- lib/events/encryptionevent.h | 1 - lib/quotient_common.h | 9 --------- lib/util.h | 9 +++++++++ 5 files changed, 10 insertions(+), 14 deletions(-) (limited to 'lib/quotient_common.h') diff --git a/lib/e2ee/e2ee.h b/lib/e2ee/e2ee.h index 1efd0f16..9501b263 100644 --- a/lib/e2ee/e2ee.h +++ b/lib/e2ee/e2ee.h @@ -8,7 +8,6 @@ #include "converters.h" #include "expected.h" #include "qolmerrors.h" -#include "quotient_common.h" #include #include @@ -71,7 +70,7 @@ struct IdentityKeys }; //! Struct representing the one-time keys. -struct QUOTIENT_API UnsignedOneTimeKeys +struct UnsignedOneTimeKeys { QHash> keys; diff --git a/lib/events/encryptionevent.cpp b/lib/events/encryptionevent.cpp index eb15f38e..1654d6f3 100644 --- a/lib/events/encryptionevent.cpp +++ b/lib/events/encryptionevent.cpp @@ -6,8 +6,6 @@ #include "e2ee/e2ee.h" -#include - namespace Quotient { static constexpr std::array encryptionStrings { MegolmV1AesSha2AlgoKey }; diff --git a/lib/events/encryptionevent.h b/lib/events/encryptionevent.h index 5b5420ec..c73e5598 100644 --- a/lib/events/encryptionevent.h +++ b/lib/events/encryptionevent.h @@ -5,7 +5,6 @@ #pragma once #include "stateevent.h" -#include "quotient_common.h" namespace Quotient { class QUOTIENT_API EncryptionEventContent { diff --git a/lib/quotient_common.h b/lib/quotient_common.h index 136e9f79..e087e7d3 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -41,15 +41,6 @@ Q_ENUM_NS_IMPL(Enum) \ Q_FLAG_NS(Flags) -#if __cpp_conditional_explicit >= 201806L -#define QUO_IMPLICIT explicit(false) -#else -#define QUO_IMPLICIT -#endif - -#define DECL_DEPRECATED_ENUMERATOR(Deprecated, Recommended) \ - Deprecated Q_DECL_ENUMERATOR_DEPRECATED_X("Use " #Recommended) = Recommended - namespace Quotient { Q_NAMESPACE_EXPORT(QUOTIENT_API) diff --git a/lib/util.h b/lib/util.h index 5dd69d74..d1623881 100644 --- a/lib/util.h +++ b/lib/util.h @@ -37,6 +37,15 @@ static_assert(false, "Use Q_DISABLE_MOVE instead; Quotient enables it across all QT_WARNING_POP #endif +#if __cpp_conditional_explicit >= 201806L +#define QUO_IMPLICIT explicit(false) +#else +#define QUO_IMPLICIT +#endif + +#define DECL_DEPRECATED_ENUMERATOR(Deprecated, Recommended) \ + Deprecated Q_DECL_ENUMERATOR_DEPRECATED_X("Use " #Recommended) = Recommended + /// \brief Copy an object with slicing /// /// Unintended slicing is bad, which why there's a C++ Core Guideline that -- cgit v1.2.3 From 04db5b6d853f3084660612c1d2db91d54ec63691 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Wed, 22 Jun 2022 02:15:51 +0200 Subject: Use fixed width types for enums --- lib/quotient_common.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/quotient_common.h') diff --git a/lib/quotient_common.h b/lib/quotient_common.h index e087e7d3..233bcaa1 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -51,7 +51,7 @@ Q_NAMESPACE_EXPORT(QUOTIENT_API) //! These are used for member events. The names here are case-insensitively //! equal to state names used on the wire. //! \sa MemberEventContent, RoomMemberEvent -enum class Membership : unsigned int { +enum class Membership : uint16_t { // Specific power-of-2 values (1,2,4,...) are important here as syncdata.cpp // depends on that, as well as Join being the first in line Invalid = 0x0, @@ -97,7 +97,7 @@ Q_ENUM_NS(RunningPolicy) //! \brief The result of URI resolution using UriResolver //! \sa UriResolver -enum UriResolveResult : short { +enum UriResolveResult : int8_t { StillResolving = -1, UriResolved = 0, CouldNotResolve, -- cgit v1.2.3 From 44aeb57e196bcd9e041c498a212f17b0dcd1244f Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Wed, 22 Jun 2022 02:52:35 +0200 Subject: Refactor things around EncryptionEvent[Content] EncryptionEvent was marked as Q_GADGET only for the sake of defining EncryptionType inside of it as Q_ENUM, with aliases also available under Quotient:: and EncryptionEventContent. This is a legacy from pre-Q_ENUM_NS times. However, event types are not really made to be proper Q_GADGETs: Q_GADGET implies access by value or reference but event types are uncopyable for the former and QML is ill-equipped for the latter. This commit moves EncryptionType definition to where other such enumerations reside - on the namespace level in quotient_common.h; and the other two places are now deprecated; and EncryptionEvent is no more Q_GADGET. With fromJson/toJson refactored in the previous commit there's no more need to specialise JsonConverter<>: specialising fromJson() is just enough. Moving EncryptionType to quotient_common.h exposed the clash of two Undefined enumerators (in RoomType and EncryptionType), warranting both enumerations to become scoped (which they ought to be, anyway). And while we're at it, the base type of enumerations is specified explicitly, as MSVC apparently uses a signed base type (int?) by default, unlike other compilers, and the upcoming enum converters will assume an unsigned base type. Finally, using fillFromJson() instead of fromJson() in the EncryptionEventContent constructor allowed to make default values explicit in the header file, rather than buried in the initialisation code. --- lib/events/encryptionevent.cpp | 50 ++++++++++++++++++++---------------------- lib/events/encryptionevent.h | 35 ++++++++++++----------------- lib/quotient_common.h | 12 +++++++--- lib/room.cpp | 4 ++-- 4 files changed, 49 insertions(+), 52 deletions(-) (limited to 'lib/quotient_common.h') diff --git a/lib/events/encryptionevent.cpp b/lib/events/encryptionevent.cpp index 1654d6f3..8872447b 100644 --- a/lib/events/encryptionevent.cpp +++ b/lib/events/encryptionevent.cpp @@ -6,47 +6,45 @@ #include "e2ee/e2ee.h" -namespace Quotient { +using namespace Quotient; + static constexpr std::array encryptionStrings { MegolmV1AesSha2AlgoKey }; template <> -struct JsonConverter { - static EncryptionType load(const QJsonValue& jv) - { - const auto& encryptionString = jv.toString(); - for (auto it = encryptionStrings.begin(); it != encryptionStrings.end(); - ++it) - if (encryptionString == *it) - return EncryptionType(it - encryptionStrings.begin()); - - if (!encryptionString.isEmpty()) - qCWarning(EVENTS) << "Unknown EncryptionType: " << encryptionString; - return EncryptionType::Undefined; - } -}; -} // namespace Quotient - -using namespace Quotient; +EncryptionType Quotient::fromJson(const QJsonValue& jv) +{ + const auto& encryptionString = jv.toString(); + for (auto it = encryptionStrings.begin(); it != encryptionStrings.end(); + ++it) + if (encryptionString == *it) + return EncryptionType(it - encryptionStrings.begin()); + + if (!encryptionString.isEmpty()) + qCWarning(EVENTS) << "Unknown EncryptionType: " << encryptionString; + return EncryptionType::Undefined; +} EncryptionEventContent::EncryptionEventContent(const QJsonObject& json) - : encryption(fromJson(json[AlgorithmKeyL])) + : encryption(fromJson(json[AlgorithmKeyL])) , algorithm(sanitized(json[AlgorithmKeyL].toString())) - , rotationPeriodMs(json[RotationPeriodMsKeyL].toInt(604800000)) - , rotationPeriodMsgs(json[RotationPeriodMsgsKeyL].toInt(100)) -{} +{ + // NB: fillFromJson only fills the variable if the JSON key exists + fillFromJson(json[RotationPeriodMsKeyL], rotationPeriodMs); + fillFromJson(json[RotationPeriodMsgsKeyL], rotationPeriodMsgs); +} -EncryptionEventContent::EncryptionEventContent(EncryptionType et) +EncryptionEventContent::EncryptionEventContent(Quotient::EncryptionType et) : encryption(et) { - if(encryption != Undefined) { - algorithm = encryptionStrings[encryption]; + if(encryption != Quotient::EncryptionType::Undefined) { + algorithm = encryptionStrings[static_cast(encryption)]; } } QJsonObject EncryptionEventContent::toJson() const { QJsonObject o; - if (encryption != EncryptionType::Undefined) + if (encryption != Quotient::EncryptionType::Undefined) o.insert(AlgorithmKey, algorithm); o.insert(RotationPeriodMsKey, rotationPeriodMs); o.insert(RotationPeriodMsgsKey, rotationPeriodMsgs); diff --git a/lib/events/encryptionevent.h b/lib/events/encryptionevent.h index 945b17e7..91452c3f 100644 --- a/lib/events/encryptionevent.h +++ b/lib/events/encryptionevent.h @@ -4,51 +4,44 @@ #pragma once +#include "quotient_common.h" #include "stateevent.h" namespace Quotient { class QUOTIENT_API EncryptionEventContent { public: - enum EncryptionType : size_t { MegolmV1AesSha2 = 0, Undefined }; + using EncryptionType + [[deprecated("Use Quotient::EncryptionType instead")]] = + Quotient::EncryptionType; - QUO_IMPLICIT EncryptionEventContent(EncryptionType et); - [[deprecated("This constructor will require explicit EncryptionType soon")]] // - explicit EncryptionEventContent() - : EncryptionEventContent(Undefined) - {} + // NOLINTNEXTLINE(google-explicit-constructor) + QUO_IMPLICIT EncryptionEventContent(Quotient::EncryptionType et); explicit EncryptionEventContent(const QJsonObject& json); QJsonObject toJson() const; - EncryptionType encryption; - QString algorithm; - int rotationPeriodMs; - int rotationPeriodMsgs; + Quotient::EncryptionType encryption; + QString algorithm {}; + int rotationPeriodMs = 604'800'000; + int rotationPeriodMsgs = 100; }; -using EncryptionType = EncryptionEventContent::EncryptionType; - class QUOTIENT_API EncryptionEvent : public StateEvent { - Q_GADGET public: DEFINE_EVENT_TYPEID("m.room.encryption", EncryptionEvent) - using EncryptionType = EncryptionEventContent::EncryptionType; - Q_ENUM(EncryptionType) + using EncryptionType + [[deprecated("Use Quotient::EncryptionType instead")]] = + Quotient::EncryptionType; explicit EncryptionEvent(const QJsonObject& obj) : StateEvent(typeId(), obj) {} - [[deprecated("This constructor will require an explicit parameter soon")]] // -// explicit EncryptionEvent() -// : EncryptionEvent(QJsonObject()) -// {} explicit EncryptionEvent(EncryptionEventContent&& content) : StateEvent(typeId(), matrixTypeId(), QString(), std::move(content)) {} - EncryptionType encryption() const { return content().encryption; } - + Quotient::EncryptionType encryption() const { return content().encryption; } QString algorithm() const { return content().algorithm; } int rotationPeriodMs() const { return content().rotationPeriodMs; } int rotationPeriodMsgs() const { return content().rotationPeriodMsgs; } diff --git a/lib/quotient_common.h b/lib/quotient_common.h index 233bcaa1..7fec9274 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -107,14 +107,20 @@ enum UriResolveResult : int8_t { }; Q_ENUM_NS(UriResolveResult) -enum RoomType { - Space, - Undefined, +enum class RoomType : uint8_t { + Space = 0, + Undefined = 0xFF, }; Q_ENUM_NS(RoomType) [[maybe_unused]] constexpr std::array RoomTypeStrings { "m.space" }; +enum class EncryptionType : uint8_t { + MegolmV1AesSha2 = 0, + Undefined = 0xFF, +}; +Q_ENUM_NS(EncryptionType) + } // namespace Quotient Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::MembershipMask) Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::JoinStates) diff --git a/lib/room.cpp b/lib/room.cpp index 2625105c..f67451ce 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -3062,7 +3062,7 @@ Room::Changes Room::processStateEvent(const RoomEvent& e) return false; } if (oldEncEvt - && oldEncEvt->encryption() != EncryptionEventContent::Undefined) { + && oldEncEvt->encryption() != EncryptionType::Undefined) { qCWarning(STATE) << "The room is already encrypted but a new" " room encryption event arrived - ignoring"; return false; @@ -3508,5 +3508,5 @@ void Room::activateEncryption() qCWarning(E2EE) << "Room" << objectName() << "is already encrypted"; return; } - setState(EncryptionEventContent::MegolmV1AesSha2); + setState(EncryptionType::MegolmV1AesSha2); } -- cgit v1.2.3