diff options
-rw-r--r-- | jobs/basejob.cpp | 76 | ||||
-rw-r--r-- | jobs/basejob.h | 101 | ||||
-rw-r--r-- | jobs/checkauthmethods.cpp | 2 | ||||
-rw-r--r-- | jobs/checkauthmethods.h | 2 | ||||
-rw-r--r-- | jobs/joinroomjob.cpp | 15 | ||||
-rw-r--r-- | jobs/joinroomjob.h | 2 | ||||
-rw-r--r-- | jobs/mediathumbnailjob.cpp | 4 | ||||
-rw-r--r-- | jobs/mediathumbnailjob.h | 2 | ||||
-rw-r--r-- | jobs/passwordlogin.cpp | 6 | ||||
-rw-r--r-- | jobs/passwordlogin.h | 2 | ||||
-rw-r--r-- | jobs/postmessagejob.cpp | 15 | ||||
-rw-r--r-- | jobs/postmessagejob.h | 2 | ||||
-rw-r--r-- | jobs/roommembersjob.cpp | 7 | ||||
-rw-r--r-- | jobs/roommembersjob.h | 4 | ||||
-rw-r--r-- | jobs/roommessagesjob.cpp | 4 | ||||
-rw-r--r-- | jobs/roommessagesjob.h | 2 | ||||
-rw-r--r-- | jobs/syncjob.cpp | 5 | ||||
-rw-r--r-- | jobs/syncjob.h | 2 |
18 files changed, 118 insertions, 135 deletions
diff --git a/jobs/basejob.cpp b/jobs/basejob.cpp index 9ab43087..3a0e1d3f 100644 --- a/jobs/basejob.cpp +++ b/jobs/basejob.cpp @@ -42,16 +42,16 @@ class BaseJob::Private { public: Private(ConnectionData* c, JobHttpType t, bool nt) - : connection(c), reply(nullptr), type(t), needsToken(nt), errorCode(NoError) + : connection(c), type(t), needsToken(nt) + , reply(nullptr), status(NoError) {} ConnectionData* connection; - QScopedPointer<QNetworkReply, NetworkReplyDeleter> reply; JobHttpType type; bool needsToken; - int errorCode; - QString errorText; + QScopedPointer<QNetworkReply, NetworkReplyDeleter> reply; + Status status; }; BaseJob::BaseJob(ConnectionData* connection, JobHttpType type, QString name, bool needsToken) @@ -117,47 +117,45 @@ void BaseJob::start() void BaseJob::gotReply() { - if (checkReply(d->reply.data())) - parseReply(d->reply->readAll()); - // FIXME: we should not hold parseReply()/parseJson() responsible for - // emitting the result; it should be done here instead. + setStatus(checkReply(d->reply.data())); + if (status().good()) + setStatus(parseReply(d->reply->readAll())); + + finishJob(true); } -bool BaseJob::checkReply(QNetworkReply* reply) +BaseJob::Status BaseJob::checkReply(QNetworkReply* reply) const { switch( reply->error() ) { case QNetworkReply::NoError: - return true; + return NoError; case QNetworkReply::AuthenticationRequiredError: case QNetworkReply::ContentAccessDenied: case QNetworkReply::ContentOperationNotPermittedError: qDebug() << "Content access error, Qt error code:" << reply->error(); - fail( ContentAccessError, reply->errorString() ); - return false; + return { ContentAccessError, reply->errorString() }; default: qDebug() << "NetworkError, Qt error code:" << reply->error(); - fail( NetworkError, reply->errorString() ); - return false; + return { NetworkError, reply->errorString() }; } } -void BaseJob::parseReply(QByteArray data) +BaseJob::Status BaseJob::parseReply(QByteArray data) { QJsonParseError error; QJsonDocument json = QJsonDocument::fromJson(data, &error); if( error.error == QJsonParseError::NoError ) - parseJson(json); + return parseJson(json); else - fail( JsonParseError, error.errorString() ); + return { JsonParseError, error.errorString() }; } -void BaseJob::parseJson(const QJsonDocument&) +BaseJob::Status BaseJob::parseJson(const QJsonDocument&) { - // Do nothing by default - emitResult(); + return Success; } void BaseJob::finishJob(bool emitResult) @@ -165,7 +163,7 @@ void BaseJob::finishJob(bool emitResult) if (!d->reply) { qWarning() << objectName() - << ": empty network reply (finish() called more than once?)"; + << ": empty network reply (finishJob() called more than once?)"; return; } @@ -184,29 +182,34 @@ void BaseJob::finishJob(bool emitResult) deleteLater(); } -int BaseJob::error() const +BaseJob::Status BaseJob::status() const { - return d->errorCode; + return d->status; } -QString BaseJob::errorString() const +int BaseJob::error() const { - return d->errorText; + return d->status.code; } -void BaseJob::setError(int errorCode) +QString BaseJob::errorString() const { - d->errorCode = errorCode; + return d->status.message; } -void BaseJob::setErrorText(QString errorText) +void BaseJob::setStatus(Status s) { - d->errorText = errorText; + d->status = s; + if (!s.good()) + { + qWarning() << QString("Job %1 status: %2, code %3") + .arg(objectName()).arg(s.message).arg(s.code); + } } -void BaseJob::emitResult() +void BaseJob::setStatus(int code, QString message) { - finishJob(true); + setStatus({ code, message }); } void BaseJob::abandon() @@ -214,17 +217,10 @@ void BaseJob::abandon() finishJob(false); } -void BaseJob::fail(int errorCode, QString errorString) -{ - setError( errorCode ); - setErrorText( errorString ); - qWarning() << "Job" << objectName() << "failed:" << errorString; - emitResult(); -} - void BaseJob::timeout() { - fail( TimeoutError, "The job has timed out" ); + setStatus( TimeoutError, "The job has timed out" ); + finishJob(true); } void BaseJob::sslErrors(const QList<QSslError>& errors) diff --git a/jobs/basejob.h b/jobs/basejob.h index 8e17e18e..07b1f1dd 100644 --- a/jobs/basejob.h +++ b/jobs/basejob.h @@ -40,10 +40,38 @@ namespace QMatrixClient public: /* Just in case, the values are compatible with KJob * (which BaseJob used to inherit from). */ - enum ErrorCode { NoError = 0, NetworkError = 100, - JsonParseError, TimeoutError, ContentAccessError, - UserDefinedError = 512 }; + enum StatusCode { NoError = 0 // To be compatible with Qt conventions + , Success = 0 + , ErrorLevel = 100 // Errors have codes starting from this + , NetworkError = 100 + , JsonParseError + , TimeoutError + , ContentAccessError + , UserDefinedError = 200 + }; + /** + * This structure stores the status of a server call job. The status consists + * of a code, that is described (but not delimited) by the respective enum, + * and a freeform message. + * + * To extend the list of error codes, define an (anonymous) enum + * along the lines of StatusCode, with additional values + * starting at UserDefinedError + */ + class Status + { + public: + Status(StatusCode c) : code(c) { } + Status(int c, QString m) : code(c), message(m) { } + + bool good() const { return code < ErrorLevel; } + + int code; + QString message; + }; + + public: BaseJob(ConnectionData* connection, JobHttpType type, QString name, bool needsToken=true); virtual ~BaseJob(); @@ -59,6 +87,7 @@ namespace QMatrixClient */ void abandon(); + Status status() const; int error() const; virtual QString errorString() const; @@ -115,74 +144,40 @@ namespace QMatrixClient virtual QJsonObject data() const; /** - * Checks the received reply for sanity; calls setError/setErrorText - * respectively. setError() with any argument except NoError prevents - * further parseReply()/parseJson() invocations. + * Used by gotReply() slot to check the received reply for general + * issues such as network errors or access denial. + * Returning anything except NoError/Success prevents + * further parseReply()/parseJson() invocation. * * @param reply the reply received from the server + * @return the result of checking the reply + * + * @see gotReply */ - virtual bool checkReply(QNetworkReply* reply); + virtual Status checkReply(QNetworkReply* reply) const; /** * Processes the reply. By default, parses the reply into * a QJsonDocument and calls parseJson() if it's a valid JSON. - * Overrides MUST ensure that fail() or emitResult() is called - * on every execution path exactly once. * * @param data raw contents of a HTTP reply from the server (without headers) + * + * @see gotReply, parseJson */ - virtual void parseReply(QByteArray data); + virtual Status parseReply(QByteArray data); /** * Processes the JSON document received from the Matrix server. - * By default emits a successful result without analysing the JSON. - * Overrides MUST ensure that fail() or emitResult() is called - * on every execution path exactly once. + * By default returns succesful status without analysing the JSON. * * @param json valid JSON document received from the server - */ - virtual void parseJson(const QJsonDocument&); - - /** - * Sets the error code. * - * It should be called when an error is encountered in the job, - * just before calling emitResult(). Normally you might want to - * use fail() instead - it sets error code, error text, makes sure - * the job has finished and invokes emitResult after that. - * - * To extend the list of error codes, define an (anonymous) enum - * with additional values starting at BaseJob::UserDefinedError - * - * @param errorCode the error code - * @see emitResult(), fail() - */ - void setError(int errorCode); - /** - * Sets the error text. Usually is combined with a setError() call - * before it, as setErrorText() alone does not indicate the error status. - */ - void setErrorText(QString errorText); - - /** - * Emits the result signal, and suicides this job. - * It first notifies the observers to hide the progress for this job - * using the finished() signal. - * - * @note: Deletes this job using deleteLater(). - * - * @see result() - * @see finished() - */ - void emitResult(); - - /** - * Same as emitResult() but calls setError() and setErrorText() - * with respective arguments passed to it. Use it as a shortcut to - * finish the job with a failure status. + * @see parseReply */ - void fail( int errorCode, QString errorString ); + virtual Status parseJson(const QJsonDocument&); + void setStatus(Status s); + void setStatus(int code, QString message); protected slots: void timeout(); diff --git a/jobs/checkauthmethods.cpp b/jobs/checkauthmethods.cpp index 55d8632a..f471c135 100644 --- a/jobs/checkauthmethods.cpp +++ b/jobs/checkauthmethods.cpp @@ -57,7 +57,7 @@ QString CheckAuthMethods::apiPath() const return "_matrix/client/r0/login"; } -void CheckAuthMethods::parseJson(const QJsonDocument& data) +BaseJob::Status CheckAuthMethods::parseJson(const QJsonDocument& data) { // TODO } diff --git a/jobs/checkauthmethods.h b/jobs/checkauthmethods.h index 2951e27f..36eaa01a 100644 --- a/jobs/checkauthmethods.h +++ b/jobs/checkauthmethods.h @@ -35,7 +35,7 @@ namespace QMatrixClient protected: QString apiPath() const override; - void parseJson(const QJsonDocument& data) override; + Status parseJson(const QJsonDocument& data) override; private: class Private; diff --git a/jobs/joinroomjob.cpp b/jobs/joinroomjob.cpp index 799d4926..8848aa70 100644 --- a/jobs/joinroomjob.cpp +++ b/jobs/joinroomjob.cpp @@ -54,18 +54,15 @@ QString JoinRoomJob::apiPath() const return QString("_matrix/client/r0/join/%1").arg(d->roomAlias); } -void JoinRoomJob::parseJson(const QJsonDocument& data) +BaseJob::Status JoinRoomJob::parseJson(const QJsonDocument& data) { QJsonObject json = data.object(); - if( !json.contains("room_id") ) - { - fail( BaseJob::UserDefinedError, "Something went wrong..." ); - qDebug() << data; - return; - } - else + if( json.contains("room_id") ) { d->roomId = json.value("room_id").toString(); + return Success; } - emitResult(); + + qDebug() << data; + return { UserDefinedError, "No room_id in the JSON response" }; } diff --git a/jobs/joinroomjob.h b/jobs/joinroomjob.h index 1329ca56..a6f4af21 100644 --- a/jobs/joinroomjob.h +++ b/jobs/joinroomjob.h @@ -35,7 +35,7 @@ namespace QMatrixClient protected: QString apiPath() const override; - void parseJson(const QJsonDocument& data) override; + Status parseJson(const QJsonDocument& data) override; private: class Private; diff --git a/jobs/mediathumbnailjob.cpp b/jobs/mediathumbnailjob.cpp index 3f5f9ebf..1e434fbc 100644 --- a/jobs/mediathumbnailjob.cpp +++ b/jobs/mediathumbnailjob.cpp @@ -70,11 +70,11 @@ QUrlQuery MediaThumbnailJob::query() const return query; } -void MediaThumbnailJob::parseReply(QByteArray data) +BaseJob::Status MediaThumbnailJob::parseReply(QByteArray data) { if( !d->thumbnail.loadFromData(data) ) { qDebug() << "MediaThumbnailJob: could not read image data"; } - emitResult(); + return Success; } diff --git a/jobs/mediathumbnailjob.h b/jobs/mediathumbnailjob.h index 1af8ecd4..3babf845 100644 --- a/jobs/mediathumbnailjob.h +++ b/jobs/mediathumbnailjob.h @@ -40,7 +40,7 @@ namespace QMatrixClient QString apiPath() const override; QUrlQuery query() const override; - virtual void parseReply(QByteArray data) override; + Status parseReply(QByteArray data) override; private: class Private; diff --git a/jobs/passwordlogin.cpp b/jobs/passwordlogin.cpp index 231dcce5..c85e4c13 100644 --- a/jobs/passwordlogin.cpp +++ b/jobs/passwordlogin.cpp @@ -80,15 +80,15 @@ QJsonObject PasswordLogin::data() const return json; } -void PasswordLogin::parseJson(const QJsonDocument& data) +BaseJob::Status PasswordLogin::parseJson(const QJsonDocument& data) { QJsonObject json = data.object(); if( !json.contains("access_token") || !json.contains("home_server") || !json.contains("user_id") ) { - fail( BaseJob::UserDefinedError, "Unexpected data" ); + return { UserDefinedError, "No expected data" }; } d->returned_token = json.value("access_token").toString(); d->returned_server = json.value("home_server").toString(); d->returned_id = json.value("user_id").toString(); - emitResult(); + return Success; } diff --git a/jobs/passwordlogin.h b/jobs/passwordlogin.h index 75a45cae..d7e42725 100644 --- a/jobs/passwordlogin.h +++ b/jobs/passwordlogin.h @@ -38,7 +38,7 @@ namespace QMatrixClient protected: QString apiPath() const override; QJsonObject data() const override; - void parseJson(const QJsonDocument& data) override; + Status parseJson(const QJsonDocument& data) override; private: class Private; diff --git a/jobs/postmessagejob.cpp b/jobs/postmessagejob.cpp index cf9b94fd..0a38da62 100644 --- a/jobs/postmessagejob.cpp +++ b/jobs/postmessagejob.cpp @@ -61,14 +61,11 @@ QJsonObject PostMessageJob::data() const return json; } -void PostMessageJob::parseJson(const QJsonDocument& data) +BaseJob::Status PostMessageJob::parseJson(const QJsonDocument& data) { - QJsonObject json = data.object(); - if( !json.contains("event_id") ) - { - fail( BaseJob::UserDefinedError, "Something went wrong..." ); - qDebug() << data; - return; - } - emitResult(); + if( data.object().contains("event_id") ) + return Success; + + qDebug() << data; + return { UserDefinedError, "No event_id in the JSON response" }; } diff --git a/jobs/postmessagejob.h b/jobs/postmessagejob.h index 9d354240..73d72020 100644 --- a/jobs/postmessagejob.h +++ b/jobs/postmessagejob.h @@ -35,7 +35,7 @@ namespace QMatrixClient protected: QString apiPath() const override; QJsonObject data() const override; - void parseJson(const QJsonDocument& data) override; + Status parseJson(const QJsonDocument& data) override; private: class Private; diff --git a/jobs/roommembersjob.cpp b/jobs/roommembersjob.cpp index 002be75b..7fc44c63 100644 --- a/jobs/roommembersjob.cpp +++ b/jobs/roommembersjob.cpp @@ -56,10 +56,9 @@ QString RoomMembersJob::apiPath() const return QString("_matrix/client/r0/rooms/%1/members").arg(d->room->id()); } -void RoomMembersJob::parseJson(const QJsonDocument& data) +BaseJob::Status RoomMembersJob::parseJson(const QJsonDocument& data) { - QJsonObject obj = data.object(); - QJsonArray chunk = obj.value("chunk").toArray(); + QJsonArray chunk = data.object().value("chunk").toArray(); for( const QJsonValue& val : chunk ) { State* state = State::fromJson(val.toObject()); @@ -67,5 +66,5 @@ void RoomMembersJob::parseJson(const QJsonDocument& data) d->states.append(state); } qDebug() << "States: " << d->states.count(); - emitResult(); + return Success; } diff --git a/jobs/roommembersjob.h b/jobs/roommembersjob.h index ffae4309..04803d67 100644 --- a/jobs/roommembersjob.h +++ b/jobs/roommembersjob.h @@ -35,8 +35,8 @@ namespace QMatrixClient QList<State*> states(); protected: - virtual QString apiPath() const override; - virtual void parseJson(const QJsonDocument& data) override; + QString apiPath() const override; + Status parseJson(const QJsonDocument& data) override; private: class Private; diff --git a/jobs/roommessagesjob.cpp b/jobs/roommessagesjob.cpp index f1943d2c..ba075007 100644 --- a/jobs/roommessagesjob.cpp +++ b/jobs/roommessagesjob.cpp @@ -81,10 +81,10 @@ QUrlQuery RoomMessagesJob::query() const return query; } -void RoomMessagesJob::parseJson(const QJsonDocument& data) +BaseJob::Status RoomMessagesJob::parseJson(const QJsonDocument& data) { QJsonObject obj = data.object(); d->events = eventListFromJson(obj.value("chunk").toArray()); d->end = obj.value("end").toString(); - emitResult(); + return Success; } diff --git a/jobs/roommessagesjob.h b/jobs/roommessagesjob.h index c068f235..52a72f70 100644 --- a/jobs/roommessagesjob.h +++ b/jobs/roommessagesjob.h @@ -40,7 +40,7 @@ namespace QMatrixClient protected: QString apiPath() const override; QUrlQuery query() const override; - void parseJson(const QJsonDocument& data) override; + Status parseJson(const QJsonDocument& data) override; private: class Private; diff --git a/jobs/syncjob.cpp b/jobs/syncjob.cpp index 3a7573bc..3bd1f0c8 100644 --- a/jobs/syncjob.cpp +++ b/jobs/syncjob.cpp @@ -110,7 +110,7 @@ QUrlQuery SyncJob::query() const return query; } -void SyncJob::parseJson(const QJsonDocument& data) +BaseJob::Status SyncJob::parseJson(const QJsonDocument& data) { QJsonObject json = data.object(); d->nextBatch = json.value("next_batch").toString(); @@ -134,8 +134,7 @@ void SyncJob::parseJson(const QJsonDocument& data) } } - emitResult(); - qDebug() << objectName() << ": processing complete"; + return Success; } void SyncRoomData::EventList::fromJson(const QJsonObject& roomContents) diff --git a/jobs/syncjob.h b/jobs/syncjob.h index 95d7aacb..51d07944 100644 --- a/jobs/syncjob.h +++ b/jobs/syncjob.h @@ -73,7 +73,7 @@ namespace QMatrixClient protected: QString apiPath() const override; QUrlQuery query() const override; - void parseJson(const QJsonDocument& data) override; + Status parseJson(const QJsonDocument& data) override; private: class Private; |