From cfd3031cf9f36123df713c4e6046cc45114a8e8b Mon Sep 17 00:00:00 2001 From: Bent Witthold Date: Fri, 13 Feb 2026 20:24:48 +0100 Subject: [PATCH] Bidding round control communicating with the server. --- UIs/BeetRoundWidgets/mainwindow.cpp | 7 ++ .../widgets/biddingroundcontrol.cpp | 16 +++- .../widgets/biddingroundcontrol.h | 3 + libs/BeetRoundCore/genericcore.h | 10 ++ libs/BeetRoundCore/model/metadata.h | 7 +- libs/BeetRoundCore/network/apiroutes.h | 6 ++ .../network/servercommunicator.cpp | 93 ++++++++++++++++++- .../network/servercommunicator.h | 18 +++- 8 files changed, 149 insertions(+), 11 deletions(-) diff --git a/UIs/BeetRoundWidgets/mainwindow.cpp b/UIs/BeetRoundWidgets/mainwindow.cpp index d783106..5487c98 100644 --- a/UIs/BeetRoundWidgets/mainwindow.cpp +++ b/UIs/BeetRoundWidgets/mainwindow.cpp @@ -574,6 +574,13 @@ void MainWindow::setupEventTab() { m_biddingRoundControl = make_unique(); containerLayout->addWidget(m_biddingRoundControl.get()); + /// requests + connect(m_biddingRoundControl.get(), &BiddingRoundControl::sendGetRequest, m_core.get(), + &GenericCore::sendGetRequest); + + /// responses + connect(m_core.get(), &GenericCore::currentBiddingRoundChanged, m_biddingRoundControl.get(), + &BiddingRoundControl::onCurrentBiddingRoundChanged); ui->tabWidget->insertTab(0, containerWidget, "Event (&1)"); } diff --git a/UIs/BeetRoundWidgets/widgets/biddingroundcontrol.cpp b/UIs/BeetRoundWidgets/widgets/biddingroundcontrol.cpp index 9c4bffc..71dfbe1 100644 --- a/UIs/BeetRoundWidgets/widgets/biddingroundcontrol.cpp +++ b/UIs/BeetRoundWidgets/widgets/biddingroundcontrol.cpp @@ -27,11 +27,11 @@ BiddingRoundControl::BiddingRoundControl(QWidget* parent) m_layout->addWidget(m_refreshRoundButton); connect(m_newRoundButton, &QPushButton::clicked, this, - &BiddingRoundControl::triggerStartNewRound); + &BiddingRoundControl::onStartNewRoundTriggered); connect(m_restartRoundButton, &QPushButton::clicked, this, - &BiddingRoundControl::triggerRestartLastRound); + &BiddingRoundControl::onRestartLastRoundTriggered); connect(m_stopRoundButton, &QPushButton::clicked, this, - &BiddingRoundControl::triggerStopCurrentRound); + &BiddingRoundControl::onStopCurrentRoundTriggered); connect(m_refreshRoundButton, &QPushButton::clicked, this, &BiddingRoundControl::onRefreshCurrentRoundTriggered); } @@ -40,6 +40,16 @@ void BiddingRoundControl::onRefreshCurrentRoundTriggered() { emit sendGetRequest(GetCurrentBiddingRound); } +void BiddingRoundControl::onStartNewRoundTriggered() { emit sendGetRequest(StartNewBiddingRound); } + +void BiddingRoundControl::onRestartLastRoundTriggered() { + emit sendGetRequest(RestartLastBiddingRound); +} + +void BiddingRoundControl::onStopCurrentRoundTriggered() { + emit sendGetRequest(StopCurrentBiddingRound); +} + void BiddingRoundControl::onCurrentBiddingRoundChanged(int roundNumber, bool isActive) { QString text = QString::number(roundNumber); if (isActive) { diff --git a/UIs/BeetRoundWidgets/widgets/biddingroundcontrol.h b/UIs/BeetRoundWidgets/widgets/biddingroundcontrol.h index 3b54c74..ef03c47 100644 --- a/UIs/BeetRoundWidgets/widgets/biddingroundcontrol.h +++ b/UIs/BeetRoundWidgets/widgets/biddingroundcontrol.h @@ -23,6 +23,9 @@ class BiddingRoundControl : public QWidget { public slots: /// button slots void onRefreshCurrentRoundTriggered(); + void onStartNewRoundTriggered(); + void onRestartLastRoundTriggered(); + void onStopCurrentRoundTriggered(); /// event slots void onCurrentBiddingRoundChanged(int roundNumber, bool isActive); diff --git a/libs/BeetRoundCore/genericcore.h b/libs/BeetRoundCore/genericcore.h index 4bf30ea..87cc867 100644 --- a/libs/BeetRoundCore/genericcore.h +++ b/libs/BeetRoundCore/genericcore.h @@ -3,6 +3,8 @@ #include +#include "model/metadata.h" + class QUndoStack; class QAbstractItemModel; class QAbstractItemModelTester; @@ -48,6 +50,14 @@ class GenericCore : public QObject { signals: void displayStatusMessage(QString message); + + /// *** server communication *** + /// request signals + void sendGetRequest(GetRequestTypes type); + /// response signals + void currentBiddingRoundChanged(int round, bool isRunning); + + /// deprecated signals void fetchItemsFromServer(); void postItemToServer(const QByteArray& jsonData); void deleteItemFromServer(const QString& id); diff --git a/libs/BeetRoundCore/model/metadata.h b/libs/BeetRoundCore/model/metadata.h index 0e8dd84..5b8c471 100644 --- a/libs/BeetRoundCore/model/metadata.h +++ b/libs/BeetRoundCore/model/metadata.h @@ -83,7 +83,12 @@ static const QString ITEM_KEY_STRING = "item"; static const QString ITEMS_FILE_NAME = ITEMS_KEY_STRING + ".json"; /// server communication -enum GetRequestTypes { GetCurrentBiddingRound }; +enum GetRequestTypes { + GetCurrentBiddingRound, + StartNewBiddingRound, + RestartLastBiddingRound, + StopCurrentBiddingRound +}; /// functions static UserRoles GET_ROLE_FOR_COLUMN(const int column) { diff --git a/libs/BeetRoundCore/network/apiroutes.h b/libs/BeetRoundCore/network/apiroutes.h index e89da3a..1f54111 100644 --- a/libs/BeetRoundCore/network/apiroutes.h +++ b/libs/BeetRoundCore/network/apiroutes.h @@ -9,4 +9,10 @@ static const QString apiPrefix = "/api/"; static const QString ROUTE_ITEMS = apiPrefix + "items"; +static const QString ROUTE_BIDDINGROUNDS = apiPrefix + "bidding_rounds"; +static const QString ROUTE_CURRENT_BIDDINGROUND = ROUTE_BIDDINGROUNDS + "/get_current"; +static const QString ROUTE_START_BIDDINGROUND = ROUTE_BIDDINGROUNDS + "/start_new"; +static const QString ROUTE_RESTART_BIDDINGROUND = ROUTE_BIDDINGROUNDS + "/restart"; +static const QString ROUTE_STOP_BIDDINGROUND = ROUTE_BIDDINGROUNDS + "/stop"; + #endif // APIROUTES_H diff --git a/libs/BeetRoundCore/network/servercommunicator.cpp b/libs/BeetRoundCore/network/servercommunicator.cpp index 7545e2e..4ff6237 100644 --- a/libs/BeetRoundCore/network/servercommunicator.cpp +++ b/libs/BeetRoundCore/network/servercommunicator.cpp @@ -1,21 +1,27 @@ #include "servercommunicator.h" -#include "apiroutes.h" #include -#include #include +#include #include +#include "../genericcore.h" +#include "apiroutes.h" + using namespace Qt::StringLiterals; -ServerCommunicator::ServerCommunicator(QObject* parent) - : QObject{parent} { +ServerCommunicator::ServerCommunicator(GenericCore* core) + : m_core(core) + , QObject{core} { m_netManager.setAutoDeleteReplies(true); m_restManager = std::make_shared(&m_netManager); m_serviceApi = std::make_shared(); + + connect(m_core, &GenericCore::sendGetRequest, this, + &ServerCommunicator::onSendGetRequestTriggered); } -bool ServerCommunicator::sslSupported() { +bool ServerCommunicator::sslSupported() const { #if QT_CONFIG(ssl) return QSslSocket::supportsSsl(); #else @@ -104,3 +110,80 @@ void ServerCommunicator::setServerConfiguration(const QString url, m_email = email; m_password = password; } + +void ServerCommunicator::onSendGetRequestTriggered(const GetRequestTypes type) { + QString path; + switch (type) { + case GetCurrentBiddingRound: + path = ROUTE_CURRENT_BIDDINGROUND; + break; + case StartNewBiddingRound: + path = ROUTE_START_BIDDINGROUND; + break; + case RestartLastBiddingRound: + path = ROUTE_RESTART_BIDDINGROUND; + break; + case StopCurrentBiddingRound: + path = ROUTE_STOP_BIDDINGROUND; + break; + default: + qWarning() << "No route found for GetRequestType:" << type; + break; + } + + // TODO move into default case of switch statement? + if (path.isEmpty()) { + qDebug() << "Empty path -> Not sending a request."; + return; + } + + const QNetworkRequest request = m_serviceApi->createRequest(path); + + m_restManager->get(request, this, [this, type](QRestReply& reply) { + if (reply.isSuccess()) { + qInfo() << "Request successful."; + const QJsonDocument doc = reply.readJson().value(); + onGetReplySuccessful(type, doc); + } else { + if (reply.hasError()) { + const QString errorString = reply.errorString(); + qWarning() << "Network error:" << errorString; + onGetReplyFailure(type, errorString); + } else { + int statusCode = reply.httpStatus(); + qWarning() << "Request not successful:" << statusCode; + onGetReplyFailure(type, QString("HTTP status code: %1").arg(statusCode)); + } + } + }); +} + +void ServerCommunicator::onGetReplySuccessful(const GetRequestTypes type, const QJsonDocument doc) { + switch (type) { + case GetCurrentBiddingRound: + case StartNewBiddingRound: + case RestartLastBiddingRound: + case StopCurrentBiddingRound: + currentBiddingRoundChangedReply(doc); + break; + default: + qWarning() << "Can't match request type:" << type; + break; + } +} + +void ServerCommunicator::onGetReplyFailure(const GetRequestTypes type, const QString errorString) { + const QString message = + QString("Request of type %1 returned: %2").arg(QString::number(type), errorString); + m_core->displayStatusMessage(message); +} + +void ServerCommunicator::currentBiddingRoundChangedReply(const QJsonDocument jsonDoc) { + qInfo() << "Current bidding round received."; + const QJsonObject rootObject = jsonDoc["data"].toObject(); + const int roundNumber = rootObject["round_number"].toInt(); + const bool stopped = rootObject["stopped"].toBool(); + const bool isActive = !stopped; + + emit m_core->currentBiddingRoundChanged(roundNumber, isActive); +} diff --git a/libs/BeetRoundCore/network/servercommunicator.h b/libs/BeetRoundCore/network/servercommunicator.h index 3107604..30b971e 100644 --- a/libs/BeetRoundCore/network/servercommunicator.h +++ b/libs/BeetRoundCore/network/servercommunicator.h @@ -1,17 +1,22 @@ #ifndef SERVERCOMMUNICATOR_H #define SERVERCOMMUNICATOR_H +#include #include #include #include #include +#include "../model/metadata.h" + +class GenericCore; + class ServerCommunicator : public QObject { Q_OBJECT public: - explicit ServerCommunicator(QObject* parent = nullptr); + explicit ServerCommunicator(GenericCore* core); - bool sslSupported(); + bool sslSupported() const; QUrl url() const; void setUrl(const QUrl& url); @@ -19,6 +24,10 @@ class ServerCommunicator : public QObject { void setServerConfiguration(const QString url, const QString email, const QString password); public slots: + void onSendGetRequestTriggered(const GetRequestTypes type); + void onGetReplySuccessful(const GetRequestTypes type, const QJsonDocument doc); + void onGetReplyFailure(const GetRequestTypes type, const QString errorString); + void fetchItems(); void postItems(const QByteArray& jsonData); void deleteItem(const QString& id); @@ -34,6 +43,8 @@ class ServerCommunicator : public QObject { void deleteRequestFailure(const QString errorString); private: + GenericCore* m_core = nullptr; + QNetworkAccessManager m_netManager; std::shared_ptr m_restManager; std::shared_ptr m_serviceApi; @@ -41,6 +52,9 @@ class ServerCommunicator : public QObject { QString m_email; QString m_password; // QString m_authToken; + + /// reply parser + void currentBiddingRoundChangedReply(const QJsonDocument jsonDoc); }; #endif // SERVERCOMMUNICATOR_H