// Copyright (c) 2023 Proton AG // // This file is part of Proton Mail Bridge. // // Proton Mail Bridge is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Proton Mail Bridge is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Proton Mail Bridge. If not, see . #include "BugReportFlow.h" namespace { QString const currentFormatVersion = "1.0.0"; } namespace bridgepp { //**************************************************************************************************************************************************** // //**************************************************************************************************************************************************** BugReportFlow::BugReportFlow() { } //**************************************************************************************************************************************************** /// \param[in] filepath The path of the file to parse. /// \return True iff the file can be properly parsed. //**************************************************************************************************************************************************** bool BugReportFlow::parse(const QString& filepath) { if (!QFile(filepath).exists()) return false; this->filepath_ = filepath; return parseFile(); } //**************************************************************************************************************************************************** /// \return The value for the 'bugCategories' property. //**************************************************************************************************************************************************** QVariantList BugReportFlow::categories() const { return categories_; } //**************************************************************************************************************************************************** /// \return The value for the 'bugQuestions' property. //**************************************************************************************************************************************************** QVariantList BugReportFlow::questions() const { return questions_; } //**************************************************************************************************************************************************** /// \param[in] categoryId The id of the bug category. /// \return Set of question for this category. //**************************************************************************************************************************************************** QVariantList BugReportFlow::questionSet(quint8 categoryId) const { if (categoryId > questionsSet_.count() - 1) return QVariantList(); return questionsSet_[categoryId]; }; //**************************************************************************************************************************************************** /// \param[in] questionId The id of the question. /// \param[in] answer The answer to that question. /// \return true iff questionId match an existing question. //**************************************************************************************************************************************************** bool BugReportFlow::setAnswer(quint8 questionId, QString const &answer) { if (questionId > questions_.count() - 1) return false; this->answers_[questionId] = answer; return true; } //**************************************************************************************************************************************************** /// \param[in] questionId The id of the question. /// \return answer the given question. //**************************************************************************************************************************************************** QString BugReportFlow::getCategory(quint8 categoryId) const { QString category; if (categoryId <= categories_.count() - 1) { category = categories_[categoryId].toMap()["name"].toString(); } return category; } //**************************************************************************************************************************************************** /// \param[in] questionId The id of the question. /// \return answer the given question. //**************************************************************************************************************************************************** QString BugReportFlow::getAnswer(quint8 questionId) const { QString answer; if (questionId <= questions_.count() - 1) { answer = answers_[questionId]; } return answer; } //**************************************************************************************************************************************************** /// \param[in] categoryId The id of the question set. /// \return concatenate answers for set of questions. //**************************************************************************************************************************************************** QString BugReportFlow::collectAnswers(quint8 categoryId) const { QString answers; if (categoryId > categories_.count() - 1) return answers; QVariantList sets = this->questionSet(categoryId); for (QVariant const &var: sets) { const QString& answer = getAnswer(var.toInt()); if (answer.isEmpty()) continue; answers += " > " + questions_[var.toInt()].toMap()["text"].toString() + "\n\r"; answers += answer + "\n\r"; } return answers; } //**************************************************************************************************************************************************** // //**************************************************************************************************************************************************** void BugReportFlow::clearAnswers() { answers_.clear(); } //**************************************************************************************************************************************************** /// \return true iff parsing succeed. //**************************************************************************************************************************************************** bool BugReportFlow::parseFile() { reset(); QJsonObject data = getJsonDataObj(getJsonRootObj()); QJsonArray categoriesJson = data.value("categories").toArray(); for (const QJsonValueRef &v : categoriesJson) { QVariantMap cat; cat["name"] = v.toObject()["name"].toString(); cat["hint"] = v.toObject()["hint"].toString(); categories_.append(cat); questionsSet_.append(v.toObject()["questions"].toArray().toVariantList()); } questions_ = data.value("questions").toArray().toVariantList(); return true; } //**************************************************************************************************************************************************** // //**************************************************************************************************************************************************** void BugReportFlow::reset() { categories_.clear(); questions_.clear(); questionsSet_.clear(); answers_.clear(); } //**************************************************************************************************************************************************** // //**************************************************************************************************************************************************** QJsonObject BugReportFlow::getJsonRootObj() const { QFile file(filepath_); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return QJsonObject(); const QString& val = file.readAll(); file.close(); QJsonDocument d = QJsonDocument::fromJson(val.toUtf8()); return d.object(); } //**************************************************************************************************************************************************** // //**************************************************************************************************************************************************** QJsonObject BugReportFlow::getJsonDataObj(const QJsonObject& root) const { QString version = getJsonVersion(root); if (version.isEmpty()) return QJsonObject(); QJsonValue data = root.value(QString("data_v%1").arg(version)); if (data == QJsonValue::Undefined || !data.isObject()) return QJsonObject(); return migrateData(data.toObject(), version); } //**************************************************************************************************************************************************** // //**************************************************************************************************************************************************** QString BugReportFlow::getJsonVersion(const QJsonObject& root) const{ QJsonValue metadata = root.value("metadata"); if (metadata == QJsonValue::Undefined || !metadata.isObject()) { return QString(); } QJsonValue version = metadata.toObject().value("version"); if (version == QJsonValue::Undefined || !version.isString()) { return QString(); } return version.toString(); } //**************************************************************************************************************************************************** // //**************************************************************************************************************************************************** QJsonObject BugReportFlow::migrateData(const QJsonObject& data, const QString& version) const{ if (version != currentFormatVersion) return QJsonObject(); // nothing to migrate now but migration should be done here. return data; } } // namespace bridgepp