From f5038d539ad10b4a2499a35b7e96e365c7ea67be Mon Sep 17 00:00:00 2001 From: Martin Rotter Date: Mon, 27 Jan 2025 07:05:20 +0100 Subject: [PATCH] #1611 fixed --- .../gui/settings/settingslocalization.cpp | 173 +++++++++++------- .../gui/settings/settingslocalization.h | 12 ++ src/librssguard/network-web/downloader.cpp | 6 + src/librssguard/network-web/downloader.h | 1 + 4 files changed, 121 insertions(+), 71 deletions(-) diff --git a/src/librssguard/gui/settings/settingslocalization.cpp b/src/librssguard/gui/settings/settingslocalization.cpp index c7d3ebb08..1f6d71f94 100644 --- a/src/librssguard/gui/settings/settingslocalization.cpp +++ b/src/librssguard/gui/settings/settingslocalization.cpp @@ -15,7 +15,9 @@ #include SettingsLocalization::SettingsLocalization(Settings* settings, QWidget* parent) - : SettingsPanel(settings, parent), m_ui(new Ui::SettingsLocalization) { + : SettingsPanel(settings, parent), m_ui(new Ui::SettingsLocalization), + m_urlPercentages(QUrl(QSL("https://api.crowdin.com/api/v2/projects/608575/languages/progress?limit=100"))), + m_urlPeople(QUrl(QSL("https://api.crowdin.com/api/v2/projects/608575/members?limit=500"))) { m_ui->setupUi(this); m_ui->m_lblAuthors->label()->setWordWrap(true); m_ui->m_treeLanguages->setColumnCount(3); @@ -44,95 +46,124 @@ QIcon SettingsLocalization::icon() const { return qApp->icons()->fromTheme(QSL("text-x-gettext-translation")); } +void SettingsLocalization::langMetadataDownloaded(const QUrl& url, + QNetworkReply::NetworkError status, + int http_code, + QByteArray contents) { + auto* down = qobject_cast(sender()); + + if (url == m_urlPercentages) { + if (status == QNetworkReply::NetworkError::NoError) { + m_dataPercentages = contents; + down->downloadFile(m_urlPeople.toString(), + qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt()); + } + else { + qCriticalNN << LOGSEC_NETWORK << "Failed to download languages metadata."; + + if (down != nullptr) { + down->deleteLater(); + } + } + } + else { + if (status == QNetworkReply::NetworkError::NoError) { + m_dataPeople = contents; + + QMap percentages_langs; + QString all_translators; + + QJsonDocument stats_doc = QJsonDocument::fromJson(m_dataPercentages); + QJsonDocument people_doc = QJsonDocument::fromJson(m_dataPeople); + QJsonArray people_arr = people_doc.object()["data"].toArray(); + std::vector people_desc; + + std::transform(people_arr.begin(), people_arr.end(), std::back_inserter(people_desc), [](const QJsonValue& b) { + return b.toObject()["data"].toObject()["username"].toString(); + }); + + all_translators = std::accumulate(std::next(people_desc.begin()), + people_desc.end(), + people_desc.at(0), + [](const QString& lhs, const QString& rhs) { + return QString(lhs + ", " + rhs); + }); + + for (const QJsonValue& val_lang : stats_doc.object()["data"].toArray()) { + QString lang_id = val_lang.toObject()["data"].toObject()["languageId"].toString().replace(QSL("-"), QSL("_")); + int lang_completion = val_lang.toObject()["data"].toObject()["translationProgress"].toInt(); + + if (lang_id == QSL("es_ES")) { + lang_id = QSL("es"); + } + + if (lang_id == QSL("en_US")) { + lang_completion = 100; + } + + percentages_langs.insert(lang_id, lang_completion); + } + + if (all_translators.isEmpty()) { + m_ui->m_lblAuthors->setStatus(WidgetWithStatus::StatusType::Information, + tr("Big thanks to all translators!"), + tr("Big thanks to all translators!")); + } + else { + m_ui->m_lblAuthors->setStatus(WidgetWithStatus::StatusType::Information, + tr("Translations provided by: %1").arg(all_translators), + tr("Big thanks to all translators!")); + } + + for (int i = 0; i < m_ui->m_treeLanguages->topLevelItemCount(); i++) { + auto* it = m_ui->m_treeLanguages->topLevelItem(i); + int perc_translated = percentages_langs.value(it->text(1)); + QColor col_translated = QColor::fromHsv(perc_translated, 200, 230); + + it->setText(2, QSL("%1 %").arg(perc_translated > 0 ? QString::number(perc_translated) : QSL("?"))); + it->setIcon(2, IconFactory::generateIcon(col_translated)); + } + } + else { + qCriticalNN << LOGSEC_NETWORK << "Failed to download languages people metadata."; + } + + if (down != nullptr) { + down->deleteLater(); + } + } +} + void SettingsLocalization::loadSettings() { onBeginLoadSettings(); auto langs = qApp->localization()->installedLanguages(); + auto* downl = new Downloader(this); // Also, load statistics with restricted access token. QList> hdrs = { {"Authorization", "Bearer " "0fbcad4c39d21a55f63f8a1b6d07cc56bb1e2eb2047bfaf1ee22425e3edf1c2b217f4d13b3cebba9"}}; - QByteArray stats_out, people_out; - QMap percentages_langs; - QString all_translators; - NetworkResult stats_res = NetworkFactory:: - performNetworkOperation(QSL("https://api.crowdin.com/api/v2/projects/608575/languages/progress?limit=100"), - qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt(), - {}, - stats_out, - QNetworkAccessManager::Operation::GetOperation, - hdrs); - - NetworkResult people_res = - NetworkFactory::performNetworkOperation(QSL("https://api.crowdin.com/api/v2/projects/608575/members?limit=500"), - qApp->settings() - ->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)) - .toInt(), - {}, - people_out, - QNetworkAccessManager::Operation::GetOperation, - hdrs); - - if (stats_res.m_networkError == QNetworkReply::NetworkError::NoError && - people_res.m_networkError == QNetworkReply::NetworkError::NoError) { - QJsonDocument stats_doc = QJsonDocument::fromJson(stats_out); - QJsonDocument people_doc = QJsonDocument::fromJson(people_out); - QJsonArray people_arr = people_doc.object()["data"].toArray(); - std::vector people_desc; - - std::transform(people_arr.begin(), people_arr.end(), std::back_inserter(people_desc), [](const QJsonValue& b) { - return b.toObject()["data"].toObject()["username"].toString(); - }); - - all_translators = std::accumulate(std::next(people_desc.begin()), - people_desc.end(), - people_desc.at(0), - [](const QString& lhs, const QString& rhs) { - return QString(lhs + ", " + rhs); - }); - - for (const QJsonValue& val_lang : stats_doc.object()["data"].toArray()) { - QString lang_id = val_lang.toObject()["data"].toObject()["languageId"].toString().replace(QSL("-"), QSL("_")); - int lang_completion = val_lang.toObject()["data"].toObject()["translationProgress"].toInt(); - - if (lang_id == QSL("es_ES")) { - lang_id = QSL("es"); - } - - if (lang_id == QSL("en_US")) { - lang_completion = 100; - } - - percentages_langs.insert(lang_id, lang_completion); - } - } - - if (all_translators.isEmpty()) { - m_ui->m_lblAuthors->setStatus(WidgetWithStatus::StatusType::Information, - tr("Big thanks to all translators!"), - tr("Big thanks to all translators!")); - } - else { - m_ui->m_lblAuthors->setStatus(WidgetWithStatus::StatusType::Information, - tr("Translations provided by: %1").arg(all_translators), - tr("Big thanks to all translators!")); - } + downl->appendRawHeaders(hdrs); + connect(downl, + &Downloader::completed, + this, + &SettingsLocalization::langMetadataDownloaded, + Qt::ConnectionType::QueuedConnection); + downl->downloadFile(m_urlPercentages.toString(), + qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt()); for (const Language& language : std::as_const(langs)) { auto* item = new QTreeWidgetItem(m_ui->m_treeLanguages); - int perc_translated = percentages_langs.value(language.m_code); item->setText(0, language.m_name); item->setText(1, language.m_code); - item->setText(2, QSL("%1 %").arg(perc_translated >= 0 ? QString::number(perc_translated) : QSL("-"))); - - QColor col_translated = QColor::fromHsv(perc_translated, 200, 230); + item->setText(2, QSL("? %")); item->setIcon(0, qApp->icons()->miscIcon(QSL(FLAG_ICON_SUBFOLDER) + QDir::separator() + language.m_code)); - item->setIcon(2, IconFactory::generateIcon(col_translated)); + item->setIcon(2, IconFactory::generateIcon(Qt::GlobalColor::blue)); } m_ui->m_treeLanguages->sortByColumn(0, Qt::SortOrder::AscendingOrder); diff --git a/src/librssguard/gui/settings/settingslocalization.h b/src/librssguard/gui/settings/settingslocalization.h index b25af215a..bd01e5583 100644 --- a/src/librssguard/gui/settings/settingslocalization.h +++ b/src/librssguard/gui/settings/settingslocalization.h @@ -7,6 +7,8 @@ #include "ui_settingslocalization.h" +#include + class SettingsLocalization : public SettingsPanel { Q_OBJECT @@ -19,8 +21,18 @@ class SettingsLocalization : public SettingsPanel { virtual void loadSettings(); virtual void saveSettings(); + private slots: + void langMetadataDownloaded(const QUrl& url, + QNetworkReply::NetworkError status, + int http_code, + QByteArray contents); + private: Ui::SettingsLocalization* m_ui; + QUrl m_urlPercentages; + QUrl m_urlPeople; + QByteArray m_dataPercentages; + QByteArray m_dataPeople; }; inline QString SettingsLocalization::title() const { diff --git a/src/librssguard/network-web/downloader.cpp b/src/librssguard/network-web/downloader.cpp index 5eccbb0c9..35eda45fc 100644 --- a/src/librssguard/network-web/downloader.cpp +++ b/src/librssguard/network-web/downloader.cpp @@ -476,6 +476,12 @@ void Downloader::cancel() { } } +void Downloader::appendRawHeaders(const QList>& headers) { + for (const QPair& header : headers) { + appendRawHeader(header.first, header.second); + } +} + void Downloader::appendRawHeader(const QByteArray& name, const QByteArray& value) { if (!value.isEmpty()) { m_customHeaders.insert(name, value); diff --git a/src/librssguard/network-web/downloader.h b/src/librssguard/network-web/downloader.h index 3cae7c49b..7b109a2dc 100644 --- a/src/librssguard/network-web/downloader.h +++ b/src/librssguard/network-web/downloader.h @@ -39,6 +39,7 @@ class Downloader : public QObject { public slots: void cancel(); + void appendRawHeaders(const QList>& headers); void appendRawHeader(const QByteArray& name, const QByteArray& value); // Performs asynchronous download of given file. Redirections are handled.