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/jobs/basejob.h | 4 ++-- lib/jobs/downloadfilejob.h | 2 +- lib/jobs/mediathumbnailjob.h | 2 +- lib/jobs/requestdata.h | 4 +++- 4 files changed, 7 insertions(+), 5 deletions(-) (limited to 'lib/jobs') 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); -- cgit v1.2.3 From a5a261b2c0dc60f99c8caa4729683d2780677f88 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Thu, 30 Dec 2021 12:46:50 +0100 Subject: Define destructors out-of-line when unique/scoped ptr are involved Once visibility kicks in, MSVC changes its ways and tries to instantiate Private classes wrapped in smart pointers upon their occurence in the header file - which leads to build breakage because of a missing destructor. Usually making the outer class destructor out-of-line helps to fix this (see RoomEvent, for one example). --- lib/jobs/downloadfilejob.cpp | 2 ++ lib/jobs/downloadfilejob.h | 1 + 2 files changed, 3 insertions(+) (limited to 'lib/jobs') diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp index 0b0531ad..6bf221cb 100644 --- a/lib/jobs/downloadfilejob.cpp +++ b/lib/jobs/downloadfilejob.cpp @@ -37,6 +37,8 @@ DownloadFileJob::DownloadFileJob(const QString& serverName, setObjectName(QStringLiteral("DownloadFileJob")); } +DownloadFileJob::~DownloadFileJob() = default; + QString DownloadFileJob::targetFileName() const { return (d->targetFile ? d->targetFile : d->tempFile)->fileName(); diff --git a/lib/jobs/downloadfilejob.h b/lib/jobs/downloadfilejob.h index d9f3b686..9e807fe7 100644 --- a/lib/jobs/downloadfilejob.h +++ b/lib/jobs/downloadfilejob.h @@ -13,6 +13,7 @@ public: DownloadFileJob(const QString& serverName, const QString& mediaId, const QString& localFilename = {}); + ~DownloadFileJob() override; QString targetFileName() const; -- cgit v1.2.3 From 7d37d296f942ac993d041b4576ed52265170c4a8 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 2 Jan 2022 06:03:26 +0100 Subject: Add ImplPtr and makeImpl The original (more complex and comprehensive) solution belongs to https://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html - this commit only provides a small wrapper for non-copyable Private class implementations common throughout libQuotient. Unlike the original, default initialisation is made explicit - you have to pass ZeroImpl() instead (and I firmly believe it's a good thing: normally pointers to Private should not remain nullptr). The reason ZeroImpl<> is not a template variable is quite simple: unique_ptr is non-copyable and so cannot be initialised from; while a template function will initialise the value in-place thanks to copy elision. --- lib/jobs/basejob.cpp | 4 ++-- lib/jobs/basejob.h | 2 +- lib/jobs/downloadfilejob.cpp | 5 ++--- lib/jobs/downloadfilejob.h | 3 +-- 4 files changed, 6 insertions(+), 8 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 971fea7b..f518a1b0 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -194,8 +194,8 @@ BaseJob::BaseJob(HttpVerb verb, const QString& name, QByteArray endpoint, BaseJob::BaseJob(HttpVerb verb, const QString& name, QByteArray endpoint, const QUrlQuery& query, RequestData&& data, bool needsToken) - : d(new Private(verb, std::move(endpoint), query, std::move(data), - needsToken)) + : d(makeImpl(verb, std::move(endpoint), query, std::move(data), + needsToken)) { setObjectName(name); connect(&d->timer, &QTimer::timeout, this, &BaseJob::timeout); diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index f41fc63c..c899170d 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -467,7 +467,7 @@ private: void finishJob(); class Private; - QScopedPointer d; + ImplPtr d; }; inline bool QUOTIENT_API isJobPending(BaseJob* job) diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp index 6bf221cb..4a507ebd 100644 --- a/lib/jobs/downloadfilejob.cpp +++ b/lib/jobs/downloadfilejob.cpp @@ -32,13 +32,12 @@ DownloadFileJob::DownloadFileJob(const QString& serverName, const QString& mediaId, const QString& localFilename) : GetContentJob(serverName, mediaId) - , d(localFilename.isEmpty() ? new Private : new Private(localFilename)) + , d(localFilename.isEmpty() ? makeImpl() + : makeImpl(localFilename)) { setObjectName(QStringLiteral("DownloadFileJob")); } -DownloadFileJob::~DownloadFileJob() = default; - QString DownloadFileJob::targetFileName() const { return (d->targetFile ? d->targetFile : d->tempFile)->fileName(); diff --git a/lib/jobs/downloadfilejob.h b/lib/jobs/downloadfilejob.h index 9e807fe7..f8c62e4b 100644 --- a/lib/jobs/downloadfilejob.h +++ b/lib/jobs/downloadfilejob.h @@ -13,13 +13,12 @@ public: DownloadFileJob(const QString& serverName, const QString& mediaId, const QString& localFilename = {}); - ~DownloadFileJob() override; QString targetFileName() const; private: class Private; - QScopedPointer d; + ImplPtr d; void doPrepare() override; void onSentRequest(QNetworkReply* reply) override; -- cgit v1.2.3 From c483ef95bd3e5effd6dd08c6d0ea0f83d0aec051 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Wed, 5 Jan 2022 15:14:33 +0100 Subject: Fully-qualify types passed to slots --- lib/jobs/basejob.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index c899170d..1567e635 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -248,7 +248,7 @@ public: } public Q_SLOTS: - void initiate(ConnectionData* connData, bool inBackground); + void initiate(Quotient::ConnectionData* connData, bool inBackground); /** * Abandons the result of this job, arrived or unarrived. -- 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/jobs/basejob.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/jobs') 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; } -- cgit v1.2.3 From 29775218e0c8b6c176015dd3128a0d545906ae6f Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Thu, 2 Dec 2021 20:54:39 +0100 Subject: Cleanup some #includes --- lib/jobs/basejob.cpp | 2 -- lib/jobs/basejob.h | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index f518a1b0..b6858b5a 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -5,11 +5,9 @@ #include "basejob.h" #include "connectiondata.h" -#include "quotient_common.h" #include #include -#include #include #include #include diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 9ed58ba8..555c602b 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -5,9 +5,9 @@ #pragma once #include "requestdata.h" -#include "../logging.h" -#include "../converters.h" -#include "../quotient_common.h" +#include "logging.h" +#include "converters.h" // Common for csapi/ headers even though not used here +#include "quotient_common.h" // For DECL_DEPRECATED_ENUMERATOR #include #include -- cgit v1.2.3 From 350f40d07943a32319182bac6a21adf456642075 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 29 Jan 2022 16:12:22 +0100 Subject: SyncData: expect self-contained /sync response SyncData can load room objects out-of-line. This is only expected when loading data from the cache (and since quite long ago, the cache always saves room objects out of line, avoiding too large JSON payloads that Qt parser chokes on). However, the code processed /sync response in the same way; in particular, this meant that SyncData filled the vector of unresolved room ids even when it came from /sync. SyncJob then looked at this vector and entered an error state if it was not empty. Well, payloads from the wire can be weird and it ultimately came to pass that a homeserver returned a non-object against a given room key, triggering the unresolved rooms branch in SyncJob - and stalling the whole sync loop as a result (https://invent.kde.org/network/neochat/-/issues/500). With this commit SyncData only fills unresolvedRoomIds when loading rooms from the cache (with the implied fallback of discarding the cache and loading from /sync anew instead). Respectively, SyncJob must never end up with SyncData that has unresolved rooms (even if those occur in the actual payload like in the mentioned issue, those rooms will be completely empty instead); the added assertion only guards for internal consistency. --- lib/jobs/syncjob.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/syncjob.cpp b/lib/jobs/syncjob.cpp index 9b1b46f0..f5c632bf 100644 --- a/lib/jobs/syncjob.cpp +++ b/lib/jobs/syncjob.cpp @@ -37,10 +37,12 @@ SyncJob::SyncJob(const QString& since, const Filter& filter, int timeout, BaseJob::Status SyncJob::prepareResult() { d.parseJson(jsonData()); - if (d.unresolvedRooms().isEmpty()) + if (Q_LIKELY(d.unresolvedRooms().isEmpty())) return Success; - qCCritical(MAIN).noquote() << "Incomplete sync response, missing rooms:" + Q_ASSERT(d.unresolvedRooms().isEmpty()); + qCCritical(MAIN).noquote() << "Rooms missing after processing sync " + "response, possibly a bug in SyncData: " << d.unresolvedRooms().join(','); return IncorrectResponse; } -- cgit v1.2.3