605 lines
23 KiB
C++
605 lines
23 KiB
C++
#include "mainwindow.h"
|
|
#include "./ui_mainwindow.h"
|
|
#include <utility>
|
|
#include <QFileDialog>
|
|
#include <QMessageBox>
|
|
#include <QDir>
|
|
#include <QDirIterator>
|
|
#include <QFile>
|
|
#include <QTextStream>
|
|
#include <QDebug>
|
|
#include <QDateTime>
|
|
#include <QtNetwork/QNetworkAccessManager>
|
|
#include <QtNetwork/QNetworkReply>
|
|
#include <QJsonDocument>
|
|
#include <QJsonArray>
|
|
#include <QJsonObject>
|
|
#include <QDialogButtonBox>
|
|
#include <QInputDialog>
|
|
|
|
MainWindow::MainWindow(QWidget *parent)
|
|
: QMainWindow(parent)
|
|
, ui(new Ui::MainWindow)
|
|
{
|
|
noConfigChange = true;
|
|
ui->setupUi(this);
|
|
loadDeeplTranslationPossibilities();
|
|
QString configPath = QDir::homePath() + "/.renpytranslate.conf";
|
|
QFile configFile(configPath);
|
|
if (configFile.exists()) {
|
|
if (configFile.open(QIODevice::ReadOnly)) {
|
|
QByteArray data = configFile.readAll();
|
|
QJsonDocument doc = QJsonDocument::fromJson(data);
|
|
if (!doc.isNull()) {
|
|
configuration = doc.object();
|
|
} else {
|
|
}
|
|
configFile.close();
|
|
}
|
|
}
|
|
if (configuration.contains("deepl-key")) {
|
|
ui->deeplApiKey->setText(configuration["deepl-key"].toString());
|
|
loadDeeplTranslationPossibilities();
|
|
}
|
|
if (configuration.contains("last-dir") && (QDir()).exists(configuration["last-dir"].toString())) {
|
|
ui->projectDir->setText(configuration["last-dir"].toString());
|
|
crawlProject();
|
|
if (configuration.contains("last-language") && ui->languageCombo->findText(configuration["last-language"].toString()) >= 0) {
|
|
ui->languageCombo->setCurrentText(configuration["last-language"].toString());
|
|
}
|
|
}
|
|
noConfigChange = false;
|
|
}
|
|
|
|
MainWindow::~MainWindow()
|
|
{
|
|
delete ui;
|
|
}
|
|
|
|
|
|
void MainWindow::on_selectProjectDirButton_clicked()
|
|
{
|
|
auto dir = configuration.contains("last-dir") && (QDir()).exists(configuration["last-dir"].toString())
|
|
? configuration["last-dir"].toString()
|
|
: QDir::homePath();
|
|
QString selectedDir = QFileDialog::getExistingDirectory(this, tr("Verzeichnis auswählen"), dir);
|
|
if (!selectedDir.isEmpty()) {
|
|
setConfigValue("last-dir", selectedDir);
|
|
ui->projectDir->setText(selectedDir);
|
|
crawlProject();
|
|
}
|
|
}
|
|
|
|
void MainWindow::crawlProject() {
|
|
QString projectDir = ui->projectDir->text();
|
|
QDir dir(projectDir);
|
|
if (!dir.exists()) {
|
|
QMessageBox::critical(this, tr("Error"), tr("The project directory does not exist!"));
|
|
return;
|
|
}
|
|
QString tlDirPath = QDir::cleanPath(projectDir + QDir::separator() + "game" + QDir::separator() + "tl");
|
|
if (!QDir(tlDirPath).exists()) {
|
|
QMessageBox::information(this, tr("Information"), tr("No translations available."));
|
|
return;
|
|
}
|
|
QStringList languageDirs = QDir(tlDirPath).entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
|
if (languageDirs.isEmpty()) {
|
|
QMessageBox::information(this, tr("Information"), tr("No translations available."));
|
|
return;
|
|
}
|
|
ui->languageCombo->clear();
|
|
ui->languageCombo->addItems(languageDirs);
|
|
ui->languageCombo->setCurrentIndex(-1);
|
|
}
|
|
|
|
void MainWindow::on_languageCombo_currentTextChanged(const QString &selectedLanguage)
|
|
{
|
|
setConfigValue("last-language", selectedLanguage);
|
|
fileContentsMap.clear();
|
|
ui->treeWidget->clear();
|
|
if (ui->languageCombo->currentIndex() == -1) {
|
|
return;
|
|
}
|
|
QString projectDir = ui->projectDir->text();
|
|
QString languageDirPath = QDir::cleanPath(projectDir + QDir::separator() + "game" + QDir::separator() + "tl" + QDir::separator() + selectedLanguage);
|
|
QDirIterator it(languageDirPath, QStringList() << "*.rpy", QDir::Files, QDirIterator::Subdirectories);
|
|
while (it.hasNext()) {
|
|
QString filePath = it.next();
|
|
QFile file(filePath);
|
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
|
continue;
|
|
QTextStream in(&file);
|
|
QString fileContent = in.readAll();
|
|
file.close();
|
|
fileContentsMap[filePath] = fileContent;
|
|
populateTreeWidgetFromMap();
|
|
}
|
|
}
|
|
|
|
void MainWindow::populateTreeWidgetFromMap() {
|
|
ui->treeWidget->clear();
|
|
foreach (const auto &pair, fileContentsMap) {
|
|
QTreeWidgetItem *fileItem = new QTreeWidgetItem(ui->treeWidget);
|
|
QString fileName = QFileInfo(pair.first).fileName();
|
|
fileItem->setText(0, fileName);
|
|
fileItem->setData(0, Qt::UserRole, false);
|
|
auto parsedBlocks = parseTextBlock(pair.second);
|
|
for (const auto& block : std::as_const(parsedBlocks)) {
|
|
QTreeWidgetItem *blockItem = new QTreeWidgetItem(fileItem);
|
|
blockItem->setText(0, QString::number(block.line));
|
|
blockItem->setText(1, block.oldText);
|
|
blockItem->setText(2, block.newText);
|
|
blockItem->setText(3, block.character);
|
|
}
|
|
}
|
|
|
|
ui->treeWidget->resizeColumnToContents(0);
|
|
int firstColumnWidth = ui->treeWidget->columnWidth(0);
|
|
int remainingWidth = ui->treeWidget->viewport()->width() - firstColumnWidth;
|
|
int columnWidth = remainingWidth / 2;
|
|
ui->treeWidget->setColumnWidth(1, columnWidth);
|
|
ui->treeWidget->setColumnWidth(2, columnWidth);
|
|
countAndShowUntranslated();
|
|
}
|
|
|
|
QVector<MainWindow::TranslationItem> MainWindow::parseTextBlock(const QString& input) {
|
|
QVector<TranslationItem> blocks;
|
|
QStringList lines = input.split("\n", Qt::SkipEmptyParts);
|
|
int lineNumber = 0;
|
|
QString identifier, originalText, translatedText;
|
|
for (const QString& line : std::as_const(lines)) {
|
|
if (line.contains("# game/")) {
|
|
QRegularExpression regExp("# game/.+:(\\d+)");
|
|
QRegularExpressionMatch match = regExp.match(line.trimmed());
|
|
if (match.hasMatch()) {
|
|
lineNumber = match.captured(1).toInt();
|
|
}
|
|
} else if (line.startsWith(" # ") || line.startsWith(" old ")) {
|
|
originalText = line.mid(line.indexOf("\"") + 1).trimmed();
|
|
originalText.chop(1);
|
|
identifier = "";
|
|
} else if ((line.startsWith(" ") && !line.startsWith(" # ")) || line.startsWith(" new ")) {
|
|
translatedText = line.mid(4).trimmed();
|
|
if (translatedText.startsWith("new \"")) {
|
|
translatedText = translatedText.mid(5).trimmed();
|
|
} else if (translatedText.startsWith("\"")) {
|
|
translatedText = translatedText.mid(1).trimmed();
|
|
} else {
|
|
int firstQuoteIndex = translatedText.indexOf("\"");
|
|
int lastQuoteIndex = translatedText.lastIndexOf("\"");
|
|
identifier = translatedText.mid(0, firstQuoteIndex).trimmed();
|
|
translatedText = translatedText.mid(firstQuoteIndex + 1, lastQuoteIndex - firstQuoteIndex).trimmed();
|
|
}
|
|
translatedText.chop(1);
|
|
blocks.append(TranslationItem(lineNumber, identifier, originalText, translatedText));
|
|
originalText.clear();
|
|
translatedText.clear();
|
|
}
|
|
}
|
|
blocks.erase(std::remove_if(blocks.begin(), blocks.end(), [](const TranslationItem& item) {
|
|
return item.oldText.trimmed().isEmpty(); // Prüft nun, ob oldText leer oder nur aus Leerzeichen besteht
|
|
}), blocks.end());
|
|
std::sort(blocks.begin(), blocks.end(), [](const TranslationItem& a, const TranslationItem& b) {
|
|
return a.line < b.line;
|
|
});
|
|
return blocks;
|
|
}
|
|
|
|
void MainWindow::on_reloadTranslationsButton_clicked()
|
|
{
|
|
crawlProject();
|
|
}
|
|
|
|
|
|
void MainWindow::on_reloadFilesButton_clicked()
|
|
{
|
|
populateTreeWidgetFromMap();
|
|
}
|
|
|
|
void MainWindow::on_nextUntranslatedButton_clicked()
|
|
{
|
|
for (int i = 0; i < ui->treeWidget->topLevelItemCount(); ++i) {
|
|
QTreeWidgetItem *topLevelItem = ui->treeWidget->topLevelItem(i);
|
|
for (int j = 0; j < topLevelItem->childCount(); ++j) {
|
|
QTreeWidgetItem *childItem = topLevelItem->child(j);
|
|
if (childItem->text(2).isEmpty()) {
|
|
ui->originalTextEdit->setText(childItem->text(1));
|
|
ui->translationEdit->clear();
|
|
ui->treeWidget->scrollToItem(childItem);
|
|
ui->treeWidget->setCurrentItem(childItem);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
QMessageBox::information(this, tr("Information"), tr("No untranslated item found."));
|
|
}
|
|
|
|
void MainWindow::on_treeWidget_itemSelectionChanged()
|
|
{
|
|
QTreeWidgetItem *selectedItem = ui->treeWidget->currentItem();
|
|
if (selectedItem) {
|
|
if (selectedItem->treeWidget()->indexOfTopLevelItem(selectedItem) < 0) {
|
|
ui->originalTextEdit->setText(selectedItem->text(1));
|
|
ui->translationEdit->setText(selectedItem->text(2));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void MainWindow::on_setTranslationButton_clicked()
|
|
{
|
|
QTreeWidgetItem *selectedItem = ui->treeWidget->currentItem();
|
|
if (selectedItem) {
|
|
if (selectedItem->treeWidget()->indexOfTopLevelItem(selectedItem) < 0) {
|
|
selectedItem->setText(2, ui->translationEdit->text());
|
|
QTreeWidgetItem *parentItem = selectedItem->parent();
|
|
if (parentItem) {
|
|
parentItem->setData(0, Qt::UserRole, true);
|
|
}
|
|
}
|
|
}
|
|
countAndShowUntranslated();
|
|
}
|
|
|
|
|
|
void MainWindow::on_setTranslationAndJumpNextButton_clicked()
|
|
{
|
|
on_setTranslationButton_clicked();
|
|
on_nextUntranslatedButton_clicked();
|
|
}
|
|
|
|
|
|
void MainWindow::on_setAndNextAndAutoTranslate_clicked()
|
|
{
|
|
on_setTranslationAndJumpNextButton_clicked();
|
|
on_autoTranslateButton_clicked();
|
|
}
|
|
|
|
|
|
void MainWindow::on_translationEdit_returnPressed()
|
|
{
|
|
switch (ui->enterActionCombo->currentIndex()) {
|
|
case 0:
|
|
on_setAndNextAndAutoTranslate_clicked();
|
|
break;
|
|
case 1:
|
|
on_setTranslationAndJumpNextButton_clicked();
|
|
break;
|
|
case 2:
|
|
on_setTranslationButton_clicked();
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void MainWindow::on_saveButton_clicked()
|
|
{
|
|
QStringList failedFiles;
|
|
saveFiles(failedFiles);
|
|
if (!failedFiles.isEmpty()) {
|
|
QString errorMessage = "Failed to save the following files:\n\n";
|
|
errorMessage += failedFiles.join("\n");
|
|
QMessageBox::critical(this, tr("Error"), errorMessage);
|
|
} else {
|
|
QMessageBox::information(this, "Information", "The translations were saved succesfully.");
|
|
}
|
|
}
|
|
|
|
void MainWindow::saveFiles(QStringList &failedFiles) {
|
|
auto projectDir = ui->projectDir->text();
|
|
for (int i = 0; i < ui->treeWidget->topLevelItemCount(); ++i) {
|
|
QTreeWidgetItem *fileItem = ui->treeWidget->topLevelItem(i);
|
|
if (fileItem->data(0, Qt::UserRole).toBool()) {
|
|
QString fileName = fileItem->text(0);
|
|
QString filePath = QString("%1/game/tl/%2/%3").arg(projectDir, ui->languageCombo->currentText(), fileName);
|
|
QString backupFileName = QString("%1/game/tl/%2/%3.bak.%4")
|
|
.arg(projectDir, ui->languageCombo->currentText(), fileName, QDateTime::currentDateTime().toString("yyyyMMddHHmmss"));
|
|
if (!createBackup(filePath, backupFileName)) {
|
|
failedFiles << filePath + ": Failed to create backup";
|
|
continue;
|
|
}
|
|
if (!editAndSaveFile(fileItem, backupFileName, filePath)) {
|
|
failedFiles << filePath + ": Failed to edit and save file";
|
|
}
|
|
fileItem->setData(0, Qt::UserRole, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool MainWindow::createBackup(const QString &filePath, const QString &backupFileName) {
|
|
if (!QFile::rename(filePath, backupFileName)) {
|
|
qDebug() << "Failed to create backup file: " << backupFileName;
|
|
qDebug() << "Original name: " << filePath;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool MainWindow::editAndSaveFile(QTreeWidgetItem *fileItem, const QString &backupFileName, const QString &fileName) {
|
|
QFile backupFile(backupFileName);
|
|
if (!backupFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
qDebug() << "Failed to open backup file for reading: " << backupFileName;
|
|
return false;
|
|
}
|
|
QStringList lines;
|
|
bool changed = false;
|
|
if (!parseAndEditFile(backupFile, fileItem, lines, changed)) {
|
|
qDebug() << "Failed to parse and edit file: " << backupFileName;
|
|
return false;
|
|
}
|
|
backupFile.close();
|
|
if (changed) {
|
|
if (!saveToFile(fileName, lines)) {
|
|
qDebug() << "Failed to save file: " << backupFileName;
|
|
return false;
|
|
}
|
|
}
|
|
qDebug() << fileName << " created";
|
|
return true;
|
|
}
|
|
|
|
bool MainWindow::parseAndEditFile(QFile &backupFile, QTreeWidgetItem *fileItem, QStringList &lines, bool &changed) {
|
|
QTextStream backupStream(&backupFile);
|
|
QString content = backupStream.readAll();
|
|
static QRegularExpression translateRegex(R"(# game\/(.+):(\d+)\ntranslate german (.*?)\n\n\s*#.*?\"(.*?)\"\s*\n\s*(.*?)\s*\"(.*?)\")");
|
|
static QRegularExpression oldNewRegex(R"(\n\s*#\s*game\/(.+?):(\d+?)\n\s*old\s*\"(.+?)\"\n\s*new\s*\"(.*?)\")");
|
|
QRegularExpressionMatch match;
|
|
int offset = 0;
|
|
while ((match = translateRegex.match(content, offset)).hasMatch()) {
|
|
auto block = match.captured(0);
|
|
auto lineNumber = match.captured(2);
|
|
auto speaker = match.captured(5);
|
|
auto oldText = match.captured(4);
|
|
auto newText = match.captured(6);
|
|
auto replacedText = findNewText(fileItem, lineNumber, oldText, speaker);
|
|
QString toReplace = QString("\"%1\"").arg(newText);
|
|
QString replacement = QString("\"%1\"").arg(replacedText.isEmpty() ? newText : replacedText);
|
|
auto replacedBlock = block.replace(toReplace, replacement);
|
|
content.replace(match.capturedStart(0), match.capturedLength(0), replacedBlock);
|
|
offset = match.capturedEnd(0);
|
|
changed = true;
|
|
}
|
|
offset = 0;
|
|
while ((match = oldNewRegex.match(content, offset)).hasMatch()) {
|
|
auto block = match.captured(0);
|
|
auto lineNumber = match.captured(2);
|
|
auto oldText = match.captured(3);
|
|
auto newText = match.captured(4);
|
|
auto replacedText = findNewText(fileItem, lineNumber, oldText, "");
|
|
QString toReplace = QString("\"%1\"").arg(newText);
|
|
QString replacement = QString("\"%1\"").arg(replacedText.isEmpty() ? newText : replacedText);
|
|
auto replacedBlock = block.replace(toReplace, replacement);
|
|
content.replace(match.capturedStart(0), match.capturedLength(0), replacedBlock);
|
|
offset = match.capturedEnd(0);
|
|
changed = true;
|
|
}
|
|
lines.append(content.split("\n"));
|
|
return true;
|
|
}
|
|
|
|
|
|
QString MainWindow::findNewText(QTreeWidgetItem *fileItem, const QString &lineNumber, const QString &originalText, const QString &speaker) {
|
|
for (int i = 0; i < fileItem->childCount(); ++i) {
|
|
QTreeWidgetItem *childItem = fileItem->child(i);
|
|
if (childItem->text(0) == lineNumber && childItem->text(1) == originalText && childItem->text(3) == speaker) {
|
|
return childItem->text(2);
|
|
}
|
|
}
|
|
return QString();
|
|
}
|
|
|
|
void MainWindow::loadDeeplTranslationPossibilities() {
|
|
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
|
|
connect(manager, &QNetworkAccessManager::finished, this, &MainWindow::onDeeplTranslationPossibilitiesLoaded);
|
|
QNetworkRequest request(QUrl("https://api-free.deepl.com/v2/glossary-language-pairs"));
|
|
request.setRawHeader("Authorization", "DeepL-Auth-Key " + ui->deeplApiKey->text().toUtf8());
|
|
manager->get(request);
|
|
}
|
|
|
|
void MainWindow::renderDeeplSources()
|
|
{
|
|
ui->deeplTranslateFrom->clear();
|
|
for (const auto& pair : translationsMap) {
|
|
ui->deeplTranslateFrom->addItem(pair.first);
|
|
}
|
|
}
|
|
|
|
void MainWindow::onDeeplTranslationPossibilitiesLoaded(QNetworkReply *reply) {
|
|
if (reply->error() == QNetworkReply::NoError) {
|
|
QByteArray responseData = reply->readAll();
|
|
QJsonDocument jsonResponse = QJsonDocument::fromJson(responseData);
|
|
if (jsonResponse.isObject()) {
|
|
QJsonObject jsonResponseObject = jsonResponse.object();
|
|
if (jsonResponseObject["supported_languages"].isArray()) {
|
|
QJsonArray languagePairsArray = jsonResponseObject["supported_languages"].toArray();
|
|
for (const QJsonValue &value : languagePairsArray) {
|
|
QJsonObject languagePair = value.toObject();
|
|
QString sourceLang = languagePair["source_lang"].toString();
|
|
QString targetLang = languagePair["target_lang"].toString();
|
|
translationsMap[sourceLang].push_back(targetLang);
|
|
}
|
|
renderDeeplSources();
|
|
} else {
|
|
qDebug() << "Invalid JSON format: Data not found";
|
|
qDebug() << responseData;
|
|
}
|
|
} else {
|
|
qDebug() << "Invalid JSON format: Response is not an object";
|
|
}
|
|
} else {
|
|
qDebug() << "Network error:" << reply->errorString();
|
|
}
|
|
reply->deleteLater();
|
|
}
|
|
|
|
bool MainWindow::saveToFile(const QString &backupFileName, const QStringList &lines) {
|
|
QFile backupFile(backupFileName);
|
|
if (!backupFile.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
|
|
qDebug() << "Failed to open backup file for writing: " << backupFileName;
|
|
return false;
|
|
}
|
|
|
|
QTextStream out(&backupFile);
|
|
out << lines.join("\n") << Qt::endl;
|
|
backupFile.close();
|
|
return true;
|
|
}
|
|
|
|
void MainWindow::on_cleanupButton_clicked()
|
|
{
|
|
QString projectDir = ui->projectDir->text();
|
|
QString language = ui->languageCombo->currentText();
|
|
QString tlDirPath = QDir::cleanPath(projectDir + QDir::separator() + "game" + QDir::separator() + "tl" + QDir::separator() + language);
|
|
QDir tlDir(tlDirPath);
|
|
QStringList filters;
|
|
filters << "*.bak.*";
|
|
tlDir.setNameFilters(filters);
|
|
QStringList fileList = tlDir.entryList(QDir::Files);
|
|
for (int i = 0; i < fileList.size(); ++i) {
|
|
const QString &fileName = fileList.at(i);
|
|
if (!tlDir.remove(fileName)) {
|
|
qDebug() << "Failed to remove" << fileName;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void MainWindow::on_cleanupAndSaveButton_clicked()
|
|
{
|
|
on_cleanupButton_clicked();
|
|
on_saveButton_clicked();
|
|
}
|
|
|
|
|
|
void MainWindow::on_deeplTranslateFrom_currentTextChanged(const QString &sourceLanguage)
|
|
{
|
|
ui->deeplTranslateTo->clear();
|
|
auto it = translationsMap.find(sourceLanguage);
|
|
if (it != translationsMap.end()) {
|
|
for (QString& targetLang : it->second) {
|
|
targetLang.replace("\"", "'");
|
|
ui->deeplTranslateTo->addItem(targetLang);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_autoTranslateButton_clicked() {
|
|
if (ui->deeplApiKey->text().isEmpty()) {
|
|
QMessageBox::information(this, "Deepl error", "For auto translation, you need to add a deepl API key.");
|
|
return;
|
|
}
|
|
QString originalText = ui->originalTextEdit->text();
|
|
QString sourceLang = ui->deeplTranslateFrom->currentText();
|
|
QString targetLang = ui->deeplTranslateTo->currentText();
|
|
QJsonObject jsonData;
|
|
jsonData["text"] = QJsonArray::fromStringList({originalText});
|
|
jsonData["source_lang"] = sourceLang;
|
|
jsonData["target_lang"] = targetLang;
|
|
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
|
|
connect(manager, &QNetworkAccessManager::finished, this, &MainWindow::translationRequestFinished);
|
|
QUrl url("https://api-free.deepl.com/v2/translate");
|
|
QNetworkRequest request(url);
|
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
|
request.setRawHeader("Authorization", "DeepL-Auth-Key " + ui->deeplApiKey->text().toUtf8());
|
|
manager->post(request, QJsonDocument(jsonData).toJson());
|
|
}
|
|
|
|
void MainWindow::translationRequestFinished(QNetworkReply *reply) {
|
|
if (reply->error() == QNetworkReply::NoError) {
|
|
QByteArray responseData = reply->readAll();
|
|
QJsonDocument jsonResponse = QJsonDocument::fromJson(responseData);
|
|
if (!jsonResponse.isNull() && jsonResponse.isObject()) {
|
|
QJsonObject jsonObject = jsonResponse.object();
|
|
QJsonArray translationsArray = jsonObject["translations"].toArray();
|
|
if (!translationsArray.isEmpty()) {
|
|
QJsonObject translationObject = translationsArray[0].toObject();
|
|
QString translatedText = translationObject["text"].toString();
|
|
translatedText.replace("\"", "'");
|
|
ui->translationEdit->setText(translatedText);
|
|
}
|
|
}
|
|
} else {
|
|
qDebug() << "Translation request failed:" << reply->errorString();
|
|
}
|
|
reply->deleteLater();
|
|
}
|
|
|
|
void MainWindow::countAndShowUntranslated()
|
|
{
|
|
int untranslatedCount = 0;
|
|
std::function<void(QTreeWidgetItem *)> countUntranslated = [&](QTreeWidgetItem *parentItem) {
|
|
for (int i = 0; i < parentItem->childCount(); ++i) {
|
|
QTreeWidgetItem *childItem = parentItem->child(i);
|
|
if (!childItem->text(1).isEmpty() && childItem->text(2).isEmpty()) {
|
|
untranslatedCount++;
|
|
}
|
|
countUntranslated(childItem);
|
|
}
|
|
};
|
|
for (int i = 0; i < ui->treeWidget->topLevelItemCount(); ++i) {
|
|
QTreeWidgetItem *topLevelItem = ui->treeWidget->topLevelItem(i);
|
|
countUntranslated(topLevelItem);
|
|
}
|
|
ui->untranslatedLabel->setText(QString("%1").arg(untranslatedCount));
|
|
}
|
|
|
|
void MainWindow::on_searchButton_clicked() {
|
|
bool ok;
|
|
QString query = QInputDialog::getText(this, "Search", "Search for:", QLineEdit::Normal, "", &ok);
|
|
if (ok && !query.isEmpty()) {
|
|
searchQuery = query;
|
|
ui->treeWidget->setCurrentItem(NULL);
|
|
searchNext();
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_searchNextButton_clicked() {
|
|
if (searchQuery.isEmpty()) {
|
|
return;
|
|
}
|
|
qDebug() << "clicked";
|
|
searchNext();
|
|
}
|
|
|
|
void MainWindow::searchNext() {
|
|
auto currentItem = ui->treeWidget->currentItem();
|
|
for (int fileItemPos = 0; fileItemPos < ui->treeWidget->invisibleRootItem()->childCount(); ++fileItemPos) {
|
|
auto fileItem {ui->treeWidget->invisibleRootItem()->child(fileItemPos)};
|
|
for (int linePos = 0; linePos < fileItem->childCount(); ++linePos) {
|
|
auto line {fileItem->child(linePos)};
|
|
if (currentItem == NULL && (line->text(1).contains(searchQuery, Qt::CaseInsensitive)
|
|
|| line->text(2).contains(searchQuery, Qt::CaseInsensitive))) {
|
|
ui->treeWidget->setCurrentItem(line);
|
|
ui->treeWidget->scrollToItem(line);
|
|
return;
|
|
}
|
|
if (currentItem == line) {
|
|
currentItem = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::setConfigValue(const QString &key, const QString &value) {
|
|
if (noConfigChange) {
|
|
return;
|
|
}
|
|
configuration[key] = value;
|
|
QString configPath = QDir::homePath() + "/.renpytranslate.conf";
|
|
QJsonDocument doc(configuration);
|
|
QFile configFile(configPath);
|
|
if (configFile.open(QIODevice::WriteOnly)) {
|
|
configFile.write(doc.toJson());
|
|
configFile.close();
|
|
} else {
|
|
qWarning() << "Failed to open config file for writing:" << configPath;
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_deeplApiKey_editingFinished()
|
|
{
|
|
setConfigValue("deepl-key", ui->deeplApiKey->text());
|
|
loadDeeplTranslationPossibilities();
|
|
}
|
|
|