diff options
Diffstat (limited to 'api/logic/translations')
-rw-r--r-- | api/logic/translations/POTranslator.cpp | 373 | ||||
-rw-r--r-- | api/logic/translations/POTranslator.h | 16 | ||||
-rw-r--r-- | api/logic/translations/TranslationsModel.cpp | 653 | ||||
-rw-r--r-- | api/logic/translations/TranslationsModel.h | 65 |
4 files changed, 0 insertions, 1107 deletions
diff --git a/api/logic/translations/POTranslator.cpp b/api/logic/translations/POTranslator.cpp deleted file mode 100644 index 1ffcb9a4..00000000 --- a/api/logic/translations/POTranslator.cpp +++ /dev/null @@ -1,373 +0,0 @@ -#include "POTranslator.h" - -#include <QDebug> -#include "FileSystem.h" - -struct POEntry -{ - QString text; - bool fuzzy; -}; - -struct POTranslatorPrivate -{ - QString filename; - QHash<QByteArray, POEntry> mapping; - QHash<QByteArray, POEntry> mapping_disambiguatrion; - bool loaded = false; - - void reload(); -}; - -class ParserArray : public QByteArray -{ -public: - ParserArray(const QByteArray &in) : QByteArray(in) - { - } - bool chomp(const char * data, int length) - { - if(startsWith(data)) - { - remove(0, length); - return true; - } - return false; - } - bool chompString(QByteArray & appendHere) - { - QByteArray msg; - bool escape = false; - if(size() < 2) - { - qDebug() << "String fragment is too short"; - return false; - } - if(!startsWith('"')) - { - qDebug() << "String fragment does not start with \""; - return false; - } - if(!endsWith('"')) - { - qDebug() << "String fragment does not end with \", instead, there is" << at(size() - 1); - return false; - } - for(int i = 1; i < size() - 1; i++) - { - char c = operator[](i); - if(escape) - { - switch(c) - { - case 'r': - msg += '\r'; - break; - case 'n': - msg += '\n'; - break; - case 't': - msg += '\t'; - break; - case 'v': - msg += '\v'; - break; - case 'a': - msg += '\a'; - break; - case 'b': - msg += '\b'; - break; - case 'f': - msg += '\f'; - break; - case '"': - msg += '"'; - break; - case '\\': - msg.append('\\'); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - { - int octal_start = i; - while ((c = operator[](i)) >= '0' && c <= '7') - { - i++; - if (i == length() - 1) - { - qDebug() << "Something went bad while parsing an octal escape string..."; - return false; - } - } - msg += mid(octal_start, i - octal_start).toUInt(0, 8); - break; - } - case 'x': - { - // chomp the 'x' - i++; - int hex_start = i; - while (isxdigit(operator[](i))) - { - i++; - if (i == length() - 1) - { - qDebug() << "Something went bad while parsing a hex escape string..."; - return false; - } - } - msg += mid(hex_start, i - hex_start).toUInt(0, 16); - break; - } - default: - { - qDebug() << "Invalid escape sequence character:" << c; - return false; - } - } - escape = false; - } - else if(c == '\\') - { - escape = true; - } - else - { - msg += c; - } - } - if(escape) - { - qDebug() << "Unterminated escape sequence..."; - return false; - } - appendHere += msg; - return true; - } -}; - -void POTranslatorPrivate::reload() -{ - QFile file(filename); - if(!file.open(QFile::OpenMode::enum_type::ReadOnly | QFile::OpenMode::enum_type::Text)) - { - qDebug() << "Failed to open PO file:" << filename; - return; - } - - QByteArray context; - QByteArray disambiguation; - QByteArray id; - QByteArray str; - bool fuzzy = false; - bool nextFuzzy = false; - - enum class Mode - { - First, - MessageContext, - MessageId, - MessageString - } mode = Mode::First; - - int lineNumber = 0; - QHash<QByteArray, POEntry> newMapping; - QHash<QByteArray, POEntry> newMapping_disambiguation; - auto endEntry = [&]() { - auto strStr = QString::fromUtf8(str); - // NOTE: PO header has empty id. We skip it. - if(!id.isEmpty()) - { - auto normalKey = context + "|" + id; - newMapping.insert(normalKey, {strStr, fuzzy}); - if(!disambiguation.isEmpty()) - { - auto disambiguationKey = context + "|" + id + "@" + disambiguation; - newMapping_disambiguation.insert(disambiguationKey, {strStr, fuzzy}); - } - } - context.clear(); - disambiguation.clear(); - id.clear(); - str.clear(); - fuzzy = nextFuzzy; - nextFuzzy = false; - }; - while (!file.atEnd()) - { - ParserArray line = file.readLine(); - if(line.endsWith('\n')) - { - line.resize(line.size() - 1); - } - if(line.endsWith('\r')) - { - line.resize(line.size() - 1); - } - - if(!line.size()) - { - // NIL - } - else if(line[0] == '#') - { - if(line.contains(", fuzzy")) - { - nextFuzzy = true; - } - } - else if(line.startsWith('"')) - { - QByteArray temp; - QByteArray *out = &temp; - - switch(mode) - { - case Mode::First: - qDebug() << "Unexpected escaped string during initial state... line:" << lineNumber; - return; - case Mode::MessageString: - out = &str; - break; - case Mode::MessageContext: - out = &context; - break; - case Mode::MessageId: - out = &id; - break; - } - if(!line.chompString(*out)) - { - qDebug() << "Badly formatted string on line:" << lineNumber; - return; - } - } - else if(line.chomp("msgctxt ", 8)) - { - switch(mode) - { - case Mode::First: - break; - case Mode::MessageString: - endEntry(); - break; - case Mode::MessageContext: - case Mode::MessageId: - qDebug() << "Unexpected msgctxt line:" << lineNumber; - return; - } - if(line.chompString(context)) - { - auto parts = context.split('|'); - context = parts[0]; - if(parts.size() > 1 && !parts[1].isEmpty()) - { - disambiguation = parts[1]; - } - mode = Mode::MessageContext; - } - } - else if (line.chomp("msgid ", 6)) - { - switch(mode) - { - case Mode::MessageContext: - case Mode::First: - break; - case Mode::MessageString: - endEntry(); - break; - case Mode::MessageId: - qDebug() << "Unexpected msgid line:" << lineNumber; - return; - } - if(line.chompString(id)) - { - mode = Mode::MessageId; - } - } - else if (line.chomp("msgstr ", 7)) - { - switch(mode) - { - case Mode::First: - case Mode::MessageString: - case Mode::MessageContext: - qDebug() << "Unexpected msgstr line:" << lineNumber; - return; - case Mode::MessageId: - break; - } - if(line.chompString(str)) - { - mode = Mode::MessageString; - } - } - else - { - qDebug() << "I did not understand line: " << lineNumber << ":" << QString::fromUtf8(line); - } - lineNumber++; - } - endEntry(); - mapping = std::move(newMapping); - mapping_disambiguatrion = std::move(newMapping_disambiguation); - loaded = true; -} - -POTranslator::POTranslator(const QString& filename, QObject* parent) : QTranslator(parent) -{ - d = new POTranslatorPrivate; - d->filename = filename; - d->reload(); -} - -QString POTranslator::translate(const char* context, const char* sourceText, const char* disambiguation, int n) const -{ - if(disambiguation) - { - auto disambiguationKey = QByteArray(context) + "|" + QByteArray(sourceText) + "@" + QByteArray(disambiguation); - auto iter = d->mapping_disambiguatrion.find(disambiguationKey); - if(iter != d->mapping_disambiguatrion.end()) - { - auto & entry = *iter; - if(entry.text.isEmpty()) - { - qDebug() << "Translation entry has no content:" << disambiguationKey; - } - if(entry.fuzzy) - { - qDebug() << "Translation entry is fuzzy:" << disambiguationKey << "->" << entry.text; - } - return entry.text; - } - } - auto key = QByteArray(context) + "|" + QByteArray(sourceText); - auto iter = d->mapping.find(key); - if(iter != d->mapping.end()) - { - auto & entry = *iter; - if(entry.text.isEmpty()) - { - qDebug() << "Translation entry has no content:" << key; - } - if(entry.fuzzy) - { - qDebug() << "Translation entry is fuzzy:" << key << "->" << entry.text; - } - return entry.text; - } - return QString(); -} - -bool POTranslator::isEmpty() const -{ - return !d->loaded; -} diff --git a/api/logic/translations/POTranslator.h b/api/logic/translations/POTranslator.h deleted file mode 100644 index 6d518560..00000000 --- a/api/logic/translations/POTranslator.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include <QTranslator> - -struct POTranslatorPrivate; - -class POTranslator : public QTranslator -{ - Q_OBJECT -public: - explicit POTranslator(const QString& filename, QObject * parent = nullptr); - QString translate(const char * context, const char * sourceText, const char * disambiguation, int n) const override; - bool isEmpty() const override; -private: - POTranslatorPrivate * d; -}; diff --git a/api/logic/translations/TranslationsModel.cpp b/api/logic/translations/TranslationsModel.cpp deleted file mode 100644 index 29a952b0..00000000 --- a/api/logic/translations/TranslationsModel.cpp +++ /dev/null @@ -1,653 +0,0 @@ -#include "TranslationsModel.h" - -#include <QCoreApplication> -#include <QTranslator> -#include <QLocale> -#include <QDir> -#include <QLibraryInfo> -#include <QDebug> -#include <FileSystem.h> -#include <net/NetJob.h> -#include <net/ChecksumValidator.h> -#include <Env.h> -#include <BuildConfig.h> -#include "Json.h" - -#include "POTranslator.h" - -const static QLatin1Literal defaultLangCode("en_US"); - -enum class FileType -{ - NONE, - QM, - PO -}; - -struct Language -{ - Language() - { - updated = true; - } - Language(const QString & _key) - { - key = _key; - locale = QLocale(key); - updated = (key == defaultLangCode); - } - - float percentTranslated() const - { - if (total == 0) - { - return 100.0f; - } - return 100.0f * float(translated) / float(total); - } - - void setTranslationStats(unsigned _translated, unsigned _untranslated, unsigned _fuzzy) - { - translated = _translated; - untranslated = _untranslated; - fuzzy = _fuzzy; - total = translated + untranslated + fuzzy; - } - - bool isOfSameNameAs(const Language& other) const - { - return key == other.key; - } - - bool isIdenticalTo(const Language& other) const - { - return - ( - key == other.key && - file_name == other.file_name && - file_size == other.file_size && - file_sha1 == other.file_sha1 && - translated == other.translated && - fuzzy == other.fuzzy && - total == other.fuzzy && - localFileType == other.localFileType - ); - } - - Language & apply(Language & other) - { - if(!isOfSameNameAs(other)) - { - return *this; - } - file_name = other.file_name; - file_size = other.file_size; - file_sha1 = other.file_sha1; - translated = other.translated; - fuzzy = other.fuzzy; - total = other.total; - localFileType = other.localFileType; - return *this; - } - - QString key; - QLocale locale; - bool updated; - - QString file_name = QString(); - std::size_t file_size = 0; - QString file_sha1 = QString(); - - unsigned translated = 0; - unsigned untranslated = 0; - unsigned fuzzy = 0; - unsigned total = 0; - - FileType localFileType = FileType::NONE; -}; - - - -struct TranslationsModel::Private -{ - QDir m_dir; - - // initial state is just english - QVector<Language> m_languages = {Language (defaultLangCode)}; - - QString m_selectedLanguage = defaultLangCode; - std::unique_ptr<QTranslator> m_qt_translator; - std::unique_ptr<QTranslator> m_app_translator; - - std::shared_ptr<Net::Download> m_index_task; - QString m_downloadingTranslation; - NetJobPtr m_dl_job; - NetJobPtr m_index_job; - QString m_nextDownload; - - std::unique_ptr<POTranslator> m_po_translator; - QFileSystemWatcher *watcher; -}; - -TranslationsModel::TranslationsModel(QString path, QObject* parent): QAbstractListModel(parent) -{ - d.reset(new Private); - d->m_dir.setPath(path); - FS::ensureFolderPathExists(path); - reloadLocalFiles(); - - d->watcher = new QFileSystemWatcher(this); - connect(d->watcher, &QFileSystemWatcher::directoryChanged, this, &TranslationsModel::translationDirChanged); - d->watcher->addPath(d->m_dir.canonicalPath()); -} - -TranslationsModel::~TranslationsModel() -{ -} - -void TranslationsModel::translationDirChanged(const QString& path) -{ - qDebug() << "Dir changed:" << path; - reloadLocalFiles(); - selectLanguage(selectedLanguage()); -} - -void TranslationsModel::indexReceived() -{ - qDebug() << "Got translations index!"; - d->m_index_job.reset(); - if(d->m_selectedLanguage != defaultLangCode) - { - downloadTranslation(d->m_selectedLanguage); - } -} - -namespace { -void readIndex(const QString & path, QMap<QString, Language>& languages) -{ - QByteArray data; - try - { - data = FS::read(path); - } - catch (const Exception &e) - { - qCritical() << "Translations Download Failed: index file not readable"; - return; - } - - int index = 1; - try - { - auto toplevel_doc = Json::requireDocument(data); - auto doc = Json::requireObject(toplevel_doc); - auto file_type = Json::requireString(doc, "file_type"); - if(file_type != "MMC-TRANSLATION-INDEX") - { - qCritical() << "Translations Download Failed: index file is of unknown file type" << file_type; - return; - } - auto version = Json::requireInteger(doc, "version"); - if(version > 2) - { - qCritical() << "Translations Download Failed: index file is of unknown format version" << file_type; - return; - } - auto langObjs = Json::requireObject(doc, "languages"); - for(auto iter = langObjs.begin(); iter != langObjs.end(); iter++) - { - Language lang(iter.key()); - - auto langObj = Json::requireObject(iter.value()); - lang.setTranslationStats( - Json::ensureInteger(langObj, "translated", 0), - Json::ensureInteger(langObj, "untranslated", 0), - Json::ensureInteger(langObj, "fuzzy", 0) - ); - lang.file_name = Json::requireString(langObj, "file"); - lang.file_sha1 = Json::requireString(langObj, "sha1"); - lang.file_size = Json::requireInteger(langObj, "size"); - - languages.insert(lang.key, lang); - index++; - } - } - catch (Json::JsonException & e) - { - qCritical() << "Translations Download Failed: index file could not be parsed as json"; - } -} -} - -void TranslationsModel::reloadLocalFiles() -{ - QMap<QString, Language> languages = {{defaultLangCode, Language(defaultLangCode)}}; - - readIndex(d->m_dir.absoluteFilePath("index_v2.json"), languages); - auto entries = d->m_dir.entryInfoList({"mmc_*.qm", "*.po"}, QDir::Files | QDir::NoDotAndDotDot); - for(auto & entry: entries) - { - auto completeSuffix = entry.completeSuffix(); - QString langCode; - FileType fileType = FileType::NONE; - if(completeSuffix == "qm") - { - langCode = entry.baseName().remove(0,4); - fileType = FileType::QM; - } - else if(completeSuffix == "po") - { - langCode = entry.baseName(); - fileType = FileType::PO; - } - else - { - continue; - } - - auto langIter = languages.find(langCode); - if(langIter != languages.end()) - { - auto & language = *langIter; - if(int(fileType) > int(language.localFileType)) - { - language.localFileType = fileType; - } - } - else - { - if(fileType == FileType::PO) - { - Language localFound(langCode); - localFound.localFileType = FileType::PO; - languages.insert(langCode, localFound); - } - } - } - - // changed and removed languages - for(auto iter = d->m_languages.begin(); iter != d->m_languages.end();) - { - auto &language = *iter; - auto row = iter - d->m_languages.begin(); - - auto updatedLanguageIter = languages.find(language.key); - if(updatedLanguageIter != languages.end()) - { - if(language.isIdenticalTo(*updatedLanguageIter)) - { - languages.remove(language.key); - } - else - { - language.apply(*updatedLanguageIter); - emit dataChanged(index(row), index(row)); - languages.remove(language.key); - } - iter++; - } - else - { - beginRemoveRows(QModelIndex(), row, row); - iter = d->m_languages.erase(iter); - endRemoveRows(); - } - } - // added languages - if(languages.isEmpty()) - { - return; - } - beginInsertRows(QModelIndex(), 0, d->m_languages.size() + languages.size() - 1); - for(auto & language: languages) - { - d->m_languages.append(language); - } - std::sort(d->m_languages.begin(), d->m_languages.end(), [](const Language& a, const Language& b) { - return a.key.compare(b.key) < 0; - }); - endInsertRows(); -} - -namespace { -enum class Column -{ - Language, - Completeness -}; -} - - -QVariant TranslationsModel::data(const QModelIndex& index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - int row = index.row(); - auto column = static_cast<Column>(index.column()); - - if (row < 0 || row >= d->m_languages.size()) - return QVariant(); - - auto & lang = d->m_languages[row]; - switch (role) - { - case Qt::DisplayRole: - { - switch(column) - { - case Column::Language: - { - return lang.locale.nativeLanguageName(); - } - case Column::Completeness: - { - QString text; - text.sprintf("%3.1f %%", lang.percentTranslated()); - return text; - } - } - } - case Qt::ToolTipRole: - { - return tr("%1:\n%2 translated\n%3 fuzzy\n%4 total").arg(lang.key, QString::number(lang.translated), QString::number(lang.fuzzy), QString::number(lang.total)); - } - case Qt::UserRole: - return lang.key; - default: - return QVariant(); - } -} - -QVariant TranslationsModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - auto column = static_cast<Column>(section); - if(role == Qt::DisplayRole) - { - switch(column) - { - case Column::Language: - { - return tr("Language"); - } - case Column::Completeness: - { - return tr("Completeness"); - } - } - } - else if(role == Qt::ToolTipRole) - { - switch(column) - { - case Column::Language: - { - return tr("The native language name."); - } - case Column::Completeness: - { - return tr("Completeness is the percentage of fully translated strings, not counting automatically guessed ones."); - } - } - } - return QAbstractListModel::headerData(section, orientation, role); -} - -int TranslationsModel::rowCount(const QModelIndex& parent) const -{ - return d->m_languages.size(); -} - -int TranslationsModel::columnCount(const QModelIndex& parent) const -{ - return 2; -} - -Language * TranslationsModel::findLanguage(const QString& key) -{ - auto found = std::find_if(d->m_languages.begin(), d->m_languages.end(), [&](Language & lang) - { - return lang.key == key; - }); - if(found == d->m_languages.end()) - { - return nullptr; - } - else - { - return found; - } -} - -bool TranslationsModel::selectLanguage(QString key) -{ - QString &langCode = key; - auto langPtr = findLanguage(key); - if(!langPtr) - { - qWarning() << "Selected invalid language" << key << ", defaulting to" << defaultLangCode; - langCode = defaultLangCode; - } - else - { - langCode = langPtr->key; - } - - // uninstall existing translators if there are any - if (d->m_app_translator) - { - QCoreApplication::removeTranslator(d->m_app_translator.get()); - d->m_app_translator.reset(); - } - if (d->m_qt_translator) - { - QCoreApplication::removeTranslator(d->m_qt_translator.get()); - d->m_qt_translator.reset(); - } - - /* - * FIXME: potential source of crashes: - * In a multithreaded application, the default locale should be set at application startup, before any non-GUI threads are created. - * This function is not reentrant. - */ - QLocale locale = QLocale(langCode); - QLocale::setDefault(locale); - - // if it's the default UI language, finish - if(langCode == defaultLangCode) - { - d->m_selectedLanguage = langCode; - return true; - } - - // otherwise install new translations - bool successful = false; - // FIXME: this is likely never present. FIX IT. - d->m_qt_translator.reset(new QTranslator()); - if (d->m_qt_translator->load("qt_" + langCode, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) - { - qDebug() << "Loading Qt Language File for" << langCode.toLocal8Bit().constData() << "..."; - if (!QCoreApplication::installTranslator(d->m_qt_translator.get())) - { - qCritical() << "Loading Qt Language File failed."; - d->m_qt_translator.reset(); - } - else - { - successful = true; - } - } - else - { - d->m_qt_translator.reset(); - } - - if(langPtr->localFileType == FileType::PO) - { - qDebug() << "Loading Application Language File for" << langCode.toLocal8Bit().constData() << "..."; - auto poTranslator = new POTranslator(FS::PathCombine(d->m_dir.path(), langCode + ".po")); - if(!poTranslator->isEmpty()) - { - if (!QCoreApplication::installTranslator(poTranslator)) - { - delete poTranslator; - qCritical() << "Installing Application Language File failed."; - } - else - { - d->m_app_translator.reset(poTranslator); - successful = true; - } - } - else - { - qCritical() << "Loading Application Language File failed."; - d->m_app_translator.reset(); - } - } - else if(langPtr->localFileType == FileType::QM) - { - d->m_app_translator.reset(new QTranslator()); - if (d->m_app_translator->load("mmc_" + langCode, d->m_dir.path())) - { - qDebug() << "Loading Application Language File for" << langCode.toLocal8Bit().constData() << "..."; - if (!QCoreApplication::installTranslator(d->m_app_translator.get())) - { - qCritical() << "Installing Application Language File failed."; - d->m_app_translator.reset(); - } - else - { - successful = true; - } - } - else - { - d->m_app_translator.reset(); - } - } - else - { - d->m_app_translator.reset(); - } - d->m_selectedLanguage = langCode; - return successful; -} - -QModelIndex TranslationsModel::selectedIndex() -{ - auto found = findLanguage(d->m_selectedLanguage); - if(found) - { - // QVector iterator freely converts to pointer to contained type - return index(found - d->m_languages.begin(), 0, QModelIndex()); - } - return QModelIndex(); -} - -QString TranslationsModel::selectedLanguage() -{ - return d->m_selectedLanguage; -} - -void TranslationsModel::downloadIndex() -{ - if(d->m_index_job || d->m_dl_job) - { - return; - } - qDebug() << "Downloading Translations Index..."; - d->m_index_job.reset(new NetJob("Translations Index")); - MetaEntryPtr entry = ENV.metacache()->resolveEntry("translations", "index_v2.json"); - entry->setStale(true); - d->m_index_task = Net::Download::makeCached(QUrl("https://files.multimc.org/translations/index_v2.json"), entry); - d->m_index_job->addNetAction(d->m_index_task); - connect(d->m_index_job.get(), &NetJob::failed, this, &TranslationsModel::indexFailed); - connect(d->m_index_job.get(), &NetJob::succeeded, this, &TranslationsModel::indexReceived); - d->m_index_job->start(); -} - -void TranslationsModel::updateLanguage(QString key) -{ - if(key == defaultLangCode) - { - qWarning() << "Cannot update builtin language" << key; - return; - } - auto found = findLanguage(key); - if(!found) - { - qWarning() << "Cannot update invalid language" << key; - return; - } - if(!found->updated) - { - downloadTranslation(key); - } -} - -void TranslationsModel::downloadTranslation(QString key) -{ - if(d->m_dl_job) - { - d->m_nextDownload = key; - return; - } - auto lang = findLanguage(key); - if(!lang) - { - qWarning() << "Will not download an unknown translation" << key; - return; - } - - d->m_downloadingTranslation = key; - MetaEntryPtr entry = ENV.metacache()->resolveEntry("translations", "mmc_" + key + ".qm"); - entry->setStale(true); - - auto dl = Net::Download::makeCached(QUrl(BuildConfig.TRANSLATIONS_BASE_URL + lang->file_name), entry); - auto rawHash = QByteArray::fromHex(lang->file_sha1.toLatin1()); - dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawHash)); - dl->m_total_progress = lang->file_size; - - d->m_dl_job.reset(new NetJob("Translation for " + key)); - d->m_dl_job->addNetAction(dl); - - connect(d->m_dl_job.get(), &NetJob::succeeded, this, &TranslationsModel::dlGood); - connect(d->m_dl_job.get(), &NetJob::failed, this, &TranslationsModel::dlFailed); - - d->m_dl_job->start(); -} - -void TranslationsModel::downloadNext() -{ - if(!d->m_nextDownload.isEmpty()) - { - downloadTranslation(d->m_nextDownload); - d->m_nextDownload.clear(); - } -} - -void TranslationsModel::dlFailed(QString reason) -{ - qCritical() << "Translations Download Failed:" << reason; - d->m_dl_job.reset(); - downloadNext(); -} - -void TranslationsModel::dlGood() -{ - qDebug() << "Got translation:" << d->m_downloadingTranslation; - - if(d->m_downloadingTranslation == d->m_selectedLanguage) - { - selectLanguage(d->m_selectedLanguage); - } - d->m_dl_job.reset(); - downloadNext(); -} - -void TranslationsModel::indexFailed(QString reason) -{ - qCritical() << "Translations Index Download Failed:" << reason; - d->m_index_job.reset(); -} diff --git a/api/logic/translations/TranslationsModel.h b/api/logic/translations/TranslationsModel.h deleted file mode 100644 index 17e5b124..00000000 --- a/api/logic/translations/TranslationsModel.h +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright 2013-2021 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include <QAbstractListModel> -#include <memory> -#include "multimc_logic_export.h" - -struct Language; - -class MULTIMC_LOGIC_EXPORT TranslationsModel : public QAbstractListModel -{ - Q_OBJECT -public: - explicit TranslationsModel(QString path, QObject *parent = 0); - virtual ~TranslationsModel(); - - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - int columnCount(const QModelIndex & parent) const override; - - bool selectLanguage(QString key); - void updateLanguage(QString key); - QModelIndex selectedIndex(); - QString selectedLanguage(); - - void downloadIndex(); - -private: - Language *findLanguage(const QString & key); - void reloadLocalFiles(); - void downloadTranslation(QString key); - void downloadNext(); - - // hide copy constructor - TranslationsModel(const TranslationsModel &) = delete; - // hide assign op - TranslationsModel &operator=(const TranslationsModel &) = delete; - -private slots: - void indexReceived(); - void indexFailed(QString reason); - void dlFailed(QString reason); - void dlGood(); - void translationDirChanged(const QString &path); - - -private: /* data */ - struct Private; - std::unique_ptr<Private> d; -}; |