From 63564d491f48c100c8ff487de5111d8aff306e1e Mon Sep 17 00:00:00 2001 From: Malin Ejdbo Date: Tue, 25 Jan 2022 16:00:08 +0100 Subject: [PATCH] Add log to the side of horizons dialog --- .../launcher/include/profile/horizonsdialog.h | 11 ++- .../launcher/src/profile/horizonsdialog.cpp | 83 +++++++++++++++++-- 2 files changed, 87 insertions(+), 7 deletions(-) diff --git a/apps/OpenSpace/ext/launcher/include/profile/horizonsdialog.h b/apps/OpenSpace/ext/launcher/include/profile/horizonsdialog.h index e60b54d997..b271e26ccc 100644 --- a/apps/OpenSpace/ext/launcher/include/profile/horizonsdialog.h +++ b/apps/OpenSpace/ext/launcher/include/profile/horizonsdialog.h @@ -36,6 +36,7 @@ class QDateTimeEdit; class QNetworkAccessManager; class QNetworkReply; class QLineEdit; +class QPlainTextEdit; using json = nlohmann::json; @@ -76,15 +77,22 @@ private: UnknownError }; + enum class LogLevel { + Error, + Warning, + Info + }; + void createWidgets(); bool handleRequest(); bool isValidInput(); std::string constructUrl(); HorizonsResult sendRequest(const std::string url); HorizonsResult handleReply(QNetworkReply* reply); - HorizonsResult isValidAnswer(const json& answer) const; + HorizonsResult isValidAnswer(const json& answer); HorizonsResult isValidHorizonsFile(const std::string& file) const; bool handleResult(HorizonsDialog::HorizonsResult& result); + void appendLog(const std::string& message, const LogLevel level); std::filesystem::path _horizonsFile; QNetworkAccessManager* _manager; @@ -104,6 +112,7 @@ private: QLineEdit* _stepEdit = nullptr; QComboBox* _timeTypeCombo = nullptr; QLabel* _downloadLabel = nullptr; + QPlainTextEdit* _log = nullptr; QLabel* _errorMsg = nullptr; }; diff --git a/apps/OpenSpace/ext/launcher/src/profile/horizonsdialog.cpp b/apps/OpenSpace/ext/launcher/src/profile/horizonsdialog.cpp index 02d5936b82..7d69708fc3 100644 --- a/apps/OpenSpace/ext/launcher/src/profile/horizonsdialog.cpp +++ b/apps/OpenSpace/ext/launcher/src/profile/horizonsdialog.cpp @@ -52,7 +52,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -273,6 +275,7 @@ std::filesystem::path HorizonsDialog::file() const { } void HorizonsDialog::createWidgets() { + QBoxLayout* wholeLayout = new QHBoxLayout(this); QBoxLayout* layout = new QVBoxLayout(this); { QLabel* generateLabel = new QLabel("Generate a new Horizons file:", this); @@ -402,6 +405,20 @@ void HorizonsDialog::createWidgets() { footer->addWidget(buttons); layout->addLayout(footer); } + wholeLayout->addLayout(layout); + { + _log = new QPlainTextEdit(this); + _log->setReadOnly(true); + + QPalette p = _log->palette(); + p.setColor(QPalette::All, QPalette::Base, Qt::black); + p.setColor(QPalette::All, QPalette::Text, Qt::white); + + _log->setPalette(p); + wholeLayout->addWidget(_log); + + appendLog("Horizons log messages:", HorizonsDialog::LogLevel::Info); + } } void HorizonsDialog::openFile() { @@ -424,6 +441,7 @@ bool HorizonsDialog::handleRequest() { if (!isValidInput()) { return false; } + _errorMsg->clear(); std::string url = constructUrl(); @@ -490,6 +508,7 @@ bool HorizonsDialog::isValidInput() { } _errorMsg->setText(message.c_str()); + appendLog(message, HorizonsDialog::LogLevel::Info); return isValid; } @@ -582,7 +601,10 @@ HorizonsDialog::HorizonsResult HorizonsDialog::sendRequest(const std::string url QEventLoop loop; auto status = QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); if (!status) { - std::cout << "Connection failed" << std::endl; + appendLog( + "Connection Failed", + HorizonsDialog::LogLevel::Error + ); return HorizonsDialog::HorizonsResult::ConnectionError; } @@ -593,18 +615,29 @@ HorizonsDialog::HorizonsResult HorizonsDialog::sendRequest(const std::string url HorizonsDialog::HorizonsResult HorizonsDialog::handleReply(QNetworkReply* reply) { if (reply->error()) { - std::cout << reply->errorString().toStdString(); + appendLog( + "Connection Error: " + reply->errorString().toStdString(), + HorizonsDialog::LogLevel::Error + ); reply->deleteLater(); return HorizonsDialog::HorizonsResult::ConnectionError; } QUrl redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); if (redirect.isValid() && reply->url() != redirect) { - std::cout << "Redirect has been requested" << std::endl; + appendLog( + "Redirect has been requested", + HorizonsDialog::LogLevel::Info + ); + return sendRequest(redirect.toString().toStdString()); } auto statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); if (statusCode.isValid() && statusCode != 200) { - std::cout << "HTTP status code '" << statusCode.toString().toStdString() << "' was returned" << std::endl; + appendLog( + "HTTP status code '" + statusCode.toString().toStdString() + "' was returned", + HorizonsDialog::LogLevel::Error + ); + reply->deleteLater(); return HorizonsDialog::HorizonsResult::ConnectionError; } @@ -649,11 +682,11 @@ HorizonsDialog::HorizonsResult HorizonsDialog::handleReply(QNetworkReply* reply) return isValidHorizonsFile(filePath); } -HorizonsDialog::HorizonsResult HorizonsDialog::isValidAnswer(const json& answer) const { +HorizonsDialog::HorizonsResult HorizonsDialog::isValidAnswer(const json& answer) { auto it = answer.find("error"); if (it != answer.end()) { // There was an error - std::cout << "Error: " << *it << std::endl; + appendLog(*it, HorizonsDialog::LogLevel::Error); return HorizonsDialog::HorizonsResult::UnknownError; } return HorizonsDialog::HorizonsResult::Valid; @@ -777,18 +810,22 @@ HorizonsDialog::HorizonsResult HorizonsDialog::isValidHorizonsFile(const std::st bool HorizonsDialog::handleResult(HorizonsDialog::HorizonsResult& result) { std::string message; + HorizonsDialog::LogLevel level; switch (result) { case HorizonsDialog::HorizonsResult::Valid: std::cout << "Valid result" << std::endl; return true; case HorizonsDialog::HorizonsResult::FileEmpty: message = "The received horizons file is empty"; + level = HorizonsDialog::LogLevel::Warning; break; case HorizonsDialog::HorizonsResult::FileAlreadyExist: message = "File already exist, try another filename"; + level = HorizonsDialog::LogLevel::Warning; break; case HorizonsDialog::HorizonsResult::ConnectionError: message = "Connection error"; + level = HorizonsDialog::LogLevel::Error; break; case HorizonsDialog::HorizonsResult::ErrorSize: @@ -796,10 +833,12 @@ bool HorizonsDialog::handleResult(HorizonsDialog::HorizonsResult& result) { "' with step size '" + _stepEdit->text().toStdString() + "' is too big, try to increase the step size and/or decrease " "the time range"; + level = HorizonsDialog::LogLevel::Error; break; case HorizonsDialog::HorizonsResult::ErrorTimeRange: { std::pair validTimeRange = parseValidTimeRange(_horizonsFile); + level = HorizonsDialog::LogLevel::Error; if (validTimeRange.first.empty()) { message = "Could not parse the valid time range"; break; @@ -812,29 +851,35 @@ bool HorizonsDialog::handleResult(HorizonsDialog::HorizonsResult& result) { case HorizonsDialog::HorizonsResult::ErrorNoObserver: message = "No match was found for observer '" + _observerName + "'. " "Use '@" + _observerName + "' as observer to list possible matches."; + level = HorizonsDialog::LogLevel::Error; break; case HorizonsDialog::HorizonsResult::ErrorObserverTargetSame: message = "The observer '" + _observerName + "' and target '" + _targetName + "' are the same. Please use another observer for the current target."; + level = HorizonsDialog::LogLevel::Error; break; case HorizonsDialog::HorizonsResult::ErrorNoData: message = "There is not enough data to compute the state of target '" + _targetName + "' in relation to the observer '" + _observerName + "' for the time range '" + _startTime + "' to '" + _endTime + "'. Try to use another observer for the current target or another time range."; + level = HorizonsDialog::LogLevel::Error; break; case HorizonsDialog::HorizonsResult::ErrorIncorrectObserver: message = "Incorrect observer type for '" + _observerName + "'. " "Use '@" + _observerName + "' as observer to search for alternatives."; + level = HorizonsDialog::LogLevel::Error; break; case HorizonsDialog::HorizonsResult::MultipleObserver: { message = "Multiple matches were found for observer '" + _observerName + "'"; + level = HorizonsDialog::LogLevel::Info; std::map matchingObservers = parseBodies(_horizonsFile); if (matchingObservers.empty()) { message += ". Could not parse the matching observers."; + level = HorizonsDialog::LogLevel::Error; break; } _chooseObserverCombo->clear(); @@ -851,6 +896,7 @@ bool HorizonsDialog::handleResult(HorizonsDialog::HorizonsResult& result) { } case HorizonsDialog::HorizonsResult::ErrorNoTarget: message = "No match was found for target '" + _targetName + "'"; + level = HorizonsDialog::LogLevel::Error; break; case HorizonsDialog::HorizonsResult::MultipleTarget: { // Case Small Bodies: @@ -864,10 +910,12 @@ bool HorizonsDialog::handleResult(HorizonsDialog::HorizonsResult& result) { // Line after data: Number of matches = X. Use ID# to make unique selection. message = "Multiple matches was found for target '" + _targetName + "'"; + level = HorizonsDialog::LogLevel::Info; std::map matchingTargets = parseBodies(_horizonsFile); if (matchingTargets.empty()) { message += ". Could not parse the matching targets"; + level = HorizonsDialog::LogLevel::Error; break; } _chooseTargetCombo->clear(); @@ -885,17 +933,40 @@ bool HorizonsDialog::handleResult(HorizonsDialog::HorizonsResult& result) { case HorizonsDialog::HorizonsResult::UnknownError: message = "An unknown error occured"; + level = HorizonsDialog::LogLevel::Error; break; default: message = "Unknown result type"; + level = HorizonsDialog::LogLevel::Error; break; } _errorMsg->setText(message.c_str()); + appendLog(message, level); std::filesystem::remove(_horizonsFile); return false; } +void HorizonsDialog::appendLog(const std::string& message, const LogLevel level) { + std::string htmlText; + switch (level) + { + case HorizonsDialog::LogLevel::Error: + htmlText = ""; + break; + case HorizonsDialog::LogLevel::Warning: + htmlText = ""; + break; + case HorizonsDialog::LogLevel::Info: + htmlText = ""; + break; + } + + htmlText += message + ""; + _log->appendHtml(htmlText.c_str()); + _log->verticalScrollBar()->setValue(_log->verticalScrollBar()->maximum()); +} + // When the user presses the 'Save' button void HorizonsDialog::approved() { _downloadLabel->show();