#include "reportissuedialog.h" #include "ui_reportissuedialog.h" #include #include #include #include #include #include namespace { const QString GITEA_BASE_URL = "https://code.redline.llc"; const QString REPO_OWNER = "njohnson"; const QString REPO_NAME = "XPlor"; } ReportIssueDialog::ReportIssueDialog(QWidget *parent) : QDialog(parent) , ui(new Ui::ReportIssueDialog) , mNetworkManager(new QNetworkAccessManager(this)) { ui->setupUi(this); #ifdef GITEA_ACCESS_TOKEN mAccessToken = GITEA_ACCESS_TOKEN; #endif connect(ui->buttonSend, &QPushButton::clicked, this, &ReportIssueDialog::onSendClicked); connect(ui->buttonCancel, &QPushButton::clicked, this, &ReportIssueDialog::onCancelClicked); connect(mNetworkManager, &QNetworkAccessManager::finished, this, &ReportIssueDialog::onNetworkReplyFinished); } ReportIssueDialog::~ReportIssueDialog() { delete ui; } bool ReportIssueDialog::isValidEmail(const QString &email) { static QRegularExpression emailRegex( R"(^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$)" ); return emailRegex.match(email).hasMatch(); } bool ReportIssueDialog::validateFields() { QString summary = ui->lineEditSummary->text().trimmed(); QString details = ui->textEditDetails->toPlainText().trimmed(); QString email = ui->lineEditEmail->text().trimmed(); if (summary.isEmpty()) { QMessageBox::warning(this, tr("Required Field"), tr("Please enter a summary for the issue.")); ui->lineEditSummary->setFocus(); return false; } if (details.isEmpty()) { QMessageBox::warning(this, tr("Required Field"), tr("Please describe the issue in detail.")); ui->textEditDetails->setFocus(); return false; } if (email.isEmpty()) { QMessageBox::warning(this, tr("Required Field"), tr("Please enter your email address.")); ui->lineEditEmail->setFocus(); return false; } if (!isValidEmail(email)) { QMessageBox::warning(this, tr("Invalid Email"), tr("Please enter a valid email address.")); ui->lineEditEmail->setFocus(); return false; } return true; } void ReportIssueDialog::onSendClicked() { if (!validateFields()) { return; } QString title = ui->lineEditSummary->text().trimmed(); QString details = ui->textEditDetails->toPlainText().trimmed(); QString email = ui->lineEditEmail->text().trimmed(); QString body = details + QString("\n\n---\nContact: %1").arg(email); ui->buttonSend->setEnabled(false); ui->buttonSend->setText(tr("Sending...")); sendIssueReport(title, body, email); } void ReportIssueDialog::onCancelClicked() { reject(); } void ReportIssueDialog::sendIssueReport(const QString &title, const QString &body, const QString &/*email*/) { QUrl url(QString("%1/api/v1/repos/%2/%3/issues") .arg(GITEA_BASE_URL, REPO_OWNER, REPO_NAME)); QNetworkRequest request(url); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); if (!mAccessToken.isEmpty()) { request.setRawHeader("Authorization", "token " + mAccessToken.toUtf8()); } QJsonObject json; json["title"] = title; json["body"] = body; json["labels"] = QJsonArray{12}; mNetworkManager->post(request, QJsonDocument(json).toJson()); } void ReportIssueDialog::onNetworkReplyFinished(QNetworkReply *reply) { ui->buttonSend->setEnabled(true); ui->buttonSend->setText(tr("Send Report")); QByteArray responseData = reply->readAll(); QString responseStr = QString::fromUtf8(responseData); if (reply->error() != QNetworkReply::NoError) { QString errorStr = reply->errorString(); if (errorStr.isEmpty()) { errorStr = "Unknown network error"; } QMessageBox::critical(this, tr("Error"), tr("Failed to send issue report:\n%1").arg(errorStr)); } else { int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if (status == 201) { QMessageBox::information(this, tr("Success"), tr("Issue reported successfully. Thank you for your feedback!")); accept(); } else { QMessageBox::warning(this, tr("Failed"), tr("Unexpected response from server (status %1).").arg(status)); } } reply->deleteLater(); }