1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
#include "./internalerrorsdialog.h"
#include <c++utilities/io/ansiescapecodes.h>
#include <QHBoxLayout>
#include <QIcon>
#include <QLabel>
#include <QPushButton>
#include <QStringBuilder>
#include <QTextBrowser>
#include <QVBoxLayout>
#include <algorithm>
#include <iostream>
#include <limits>
using namespace std;
using namespace CppUtilities;
using namespace Data;
namespace QtGui {
InternalErrorsDialog *InternalErrorsDialog::s_instance = nullptr;
std::vector<InternalError> InternalErrorsDialog::s_internalErrors;
InternalErrorsDialog::InternalErrorsDialog()
: TextViewDialog(tr("Internal errors"))
, m_request(tr("Request URL:"))
, m_response(tr("Response:"))
, m_statusLabel(new QLabel(this))
{
if (!s_instance) {
s_instance = this;
}
// add layout to show status and additional buttons
auto *const buttonLayout = new QHBoxLayout;
buttonLayout->setContentsMargins(0, 0, 0, 0);
// add label for overall status
QFont boldFont(m_statusLabel->font());
boldFont.setBold(true);
m_statusLabel->setFont(boldFont);
buttonLayout->addWidget(m_statusLabel);
updateStatusLabel();
// add errors to text view
for (const InternalError &error : s_internalErrors) {
internalAddError(error);
}
// add a button for clearing errors
if (!s_internalErrors.empty()) {
auto *const clearButton = new QPushButton(this);
clearButton->setText(tr("Clear errors"));
clearButton->setIcon(QIcon::fromTheme(QStringLiteral("edit-clear")));
buttonLayout->setContentsMargins(0, 0, 0, 0);
buttonLayout->addItem(new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
buttonLayout->addWidget(clearButton);
connect(clearButton, &QPushButton::clicked, &InternalErrorsDialog::clearErrors);
connect(clearButton, &QPushButton::clicked, this, &InternalErrorsDialog::errorsCleared);
}
layout()->addItem(buttonLayout);
}
InternalErrorsDialog::~InternalErrorsDialog()
{
if (s_instance == this) {
s_instance = nullptr;
}
}
void InternalErrorsDialog::addError(InternalError &&newError)
{
s_internalErrors.emplace_back(newError);
if (s_instance) {
s_instance->internalAddError(s_internalErrors.back());
s_instance->updateStatusLabel();
}
}
void InternalErrorsDialog::addError(const QString &message, const QUrl &url, const QByteArray &response)
{
s_internalErrors.emplace_back(message, url, response);
if (s_instance) {
s_instance->internalAddError(s_internalErrors.back());
s_instance->updateStatusLabel();
}
}
void InternalErrorsDialog::internalAddError(const InternalError &error)
{
const QString url = error.url.toString();
auto *const b = browser();
b->append(QChar('[') % QString::fromUtf8(error.when.toString(DateTimeOutputFormat::Iso, true).data()) % QChar(']') % QChar(' ') % error.message);
if (!url.isEmpty()) {
b->append(m_request % QChar(' ') % url);
}
if (!error.response.isEmpty()) {
b->append(m_response % QChar('\n') % QString::fromLocal8Bit(error.response));
}
// also log errors to console
using namespace EscapeCodes;
cerr << Phrases::Error << error.message.toLocal8Bit().data() << Phrases::End;
if (!error.url.isEmpty()) {
cerr << "request URL: " << url.toLocal8Bit().data() << '\n';
}
if (!error.response.isEmpty()) {
cerr << "response: " << error.response.data() << '\n';
}
}
void InternalErrorsDialog::updateStatusLabel()
{
m_statusLabel->setText(tr("%1 error(s) occurred", nullptr, static_cast<int>(min<size_t>(s_internalErrors.size(), numeric_limits<int>::max())))
.arg(s_internalErrors.size()));
}
void InternalErrorsDialog::clearErrors()
{
s_internalErrors.clear();
if (s_instance) {
s_instance->updateStatusLabel();
s_instance->browser()->clear();
}
}
} // namespace QtGui
|