Skip to content

Commit

Permalink
#1611 fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
martinrotter committed Jan 27, 2025
1 parent 12ac668 commit f5038d5
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 71 deletions.
173 changes: 102 additions & 71 deletions src/librssguard/gui/settings/settingslocalization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
#include <QJsonObject>

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);
Expand Down Expand Up @@ -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<Downloader*>(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<QString, int> 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<QString> 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<QPair<QByteArray, QByteArray>> hdrs = {
{"Authorization",
"Bearer "
"0fbcad4c39d21a55f63f8a1b6d07cc56bb1e2eb2047bfaf1ee22425e3edf1c2b217f4d13b3cebba9"}};
QByteArray stats_out, people_out;
QMap<QString, int> 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<QString> 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);
Expand Down
12 changes: 12 additions & 0 deletions src/librssguard/gui/settings/settingslocalization.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#include "ui_settingslocalization.h"

#include <QNetworkReply>

class SettingsLocalization : public SettingsPanel {
Q_OBJECT

Expand All @@ -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 {
Expand Down
6 changes: 6 additions & 0 deletions src/librssguard/network-web/downloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,12 @@ void Downloader::cancel() {
}
}

void Downloader::appendRawHeaders(const QList<QPair<QByteArray, QByteArray>>& headers) {
for (const QPair<QByteArray, QByteArray>& header : headers) {
appendRawHeader(header.first, header.second);
}
}

void Downloader::appendRawHeader(const QByteArray& name, const QByteArray& value) {
if (!value.isEmpty()) {
m_customHeaders.insert(name, value);
Expand Down
1 change: 1 addition & 0 deletions src/librssguard/network-web/downloader.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class Downloader : public QObject {
public slots:
void cancel();

void appendRawHeaders(const QList<QPair<QByteArray, QByteArray>>& headers);
void appendRawHeader(const QByteArray& name, const QByteArray& value);

// Performs asynchronous download of given file. Redirections are handled.
Expand Down

0 comments on commit f5038d5

Please sign in to comment.