Verbessere die Benutzeroberfläche und die Leistung beim Laden von Übersetzungen mit Fortschrittsanzeigen und Fehlerbehandlung
This commit is contained in:
121
mainwindow.cpp
121
mainwindow.cpp
@@ -17,6 +17,8 @@
|
|||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QCoreApplication>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
@@ -26,8 +28,10 @@
|
|||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QPlainTextEdit>
|
#include <QPlainTextEdit>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
#include <QProgressDialog>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
#include <QSignalBlocker>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
@@ -168,10 +172,27 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
on_translationProviderCombo_currentIndexChanged(ui->translationProviderCombo->currentIndex());
|
on_translationProviderCombo_currentIndexChanged(ui->translationProviderCombo->currentIndex());
|
||||||
if (configuration.contains("last-dir") && (QDir()).exists(configuration["last-dir"].toString())) {
|
if (configuration.contains("last-dir") && (QDir()).exists(configuration["last-dir"].toString())) {
|
||||||
ui->projectDir->setText(configuration["last-dir"].toString());
|
ui->projectDir->setText(configuration["last-dir"].toString());
|
||||||
|
// Let the main window become visible before scanning potentially large projects.
|
||||||
|
QTimer::singleShot(0, this, [this] {
|
||||||
|
const QString savedLanguage = configuration.value("last-language").toString();
|
||||||
|
QProgressDialog startupProgress(tr("Projekt wird vorbereitet …"), QString(), 0, 2, this);
|
||||||
|
startupProgress.setWindowTitle(tr("Bitte warten"));
|
||||||
|
startupProgress.setCancelButton(nullptr);
|
||||||
|
startupProgress.setMinimumDuration(0);
|
||||||
|
startupProgress.setWindowModality(Qt::ApplicationModal);
|
||||||
|
startupProgress.show();
|
||||||
|
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||||
crawlProject();
|
crawlProject();
|
||||||
if (configuration.contains("last-language") && ui->languageCombo->findText(configuration["last-language"].toString()) >= 0) {
|
startupProgress.setValue(1);
|
||||||
ui->languageCombo->setCurrentText(configuration["last-language"].toString());
|
startupProgress.setLabelText(tr("Letzte Sprache und Übersetzungsdateien werden geladen …"));
|
||||||
|
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||||
|
if (!savedLanguage.isEmpty() && ui->languageCombo->findText(savedLanguage) >= 0) {
|
||||||
|
const QSignalBlocker blockLanguageSelection(ui->languageCombo);
|
||||||
|
ui->languageCombo->setCurrentText(savedLanguage);
|
||||||
|
on_languageCombo_currentTextChanged(savedLanguage);
|
||||||
}
|
}
|
||||||
|
startupProgress.setValue(2);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
noConfigChange = false;
|
noConfigChange = false;
|
||||||
}
|
}
|
||||||
@@ -270,6 +291,7 @@ void MainWindow::crawlProject() {
|
|||||||
QMessageBox::information(this, tr("Information"), tr("No translations available."));
|
QMessageBox::information(this, tr("Information"), tr("No translations available."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const QSignalBlocker blockLanguageSelection(ui->languageCombo);
|
||||||
ui->languageCombo->clear();
|
ui->languageCombo->clear();
|
||||||
ui->languageCombo->addItems(languageDirs);
|
ui->languageCombo->addItems(languageDirs);
|
||||||
ui->languageCombo->setCurrentIndex(-1);
|
ui->languageCombo->setCurrentIndex(-1);
|
||||||
@@ -286,17 +308,39 @@ void MainWindow::on_languageCombo_currentTextChanged(const QString &selectedLang
|
|||||||
QString projectDir = ui->projectDir->text();
|
QString projectDir = ui->projectDir->text();
|
||||||
QString languageDirPath = QDir::cleanPath(projectDir + QDir::separator() + "game" + QDir::separator() + "tl" + QDir::separator() + selectedLanguage);
|
QString languageDirPath = QDir::cleanPath(projectDir + QDir::separator() + "game" + QDir::separator() + "tl" + QDir::separator() + selectedLanguage);
|
||||||
QDirIterator it(languageDirPath, QStringList() << "*.rpy", QDir::Files, QDirIterator::Subdirectories);
|
QDirIterator it(languageDirPath, QStringList() << "*.rpy", QDir::Files, QDirIterator::Subdirectories);
|
||||||
|
QStringList filePaths;
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
QString filePath = it.next();
|
filePaths.append(it.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
QProgressDialog progress(tr("Übersetzungsdateien werden geladen …"), QString(), 0, filePaths.size(), this);
|
||||||
|
progress.setWindowTitle(tr("Bitte warten"));
|
||||||
|
progress.setCancelButton(nullptr);
|
||||||
|
progress.setMinimumDuration(0);
|
||||||
|
progress.setWindowModality(Qt::ApplicationModal);
|
||||||
|
progress.show();
|
||||||
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||||
|
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||||
|
|
||||||
|
for (int fileIndex = 0; fileIndex < filePaths.size(); ++fileIndex) {
|
||||||
|
const QString &filePath = filePaths.at(fileIndex);
|
||||||
QFile file(filePath);
|
QFile file(filePath);
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
progress.setValue(fileIndex + 1);
|
||||||
|
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
QTextStream in(&file);
|
QTextStream in(&file);
|
||||||
QString fileContent = in.readAll();
|
QString fileContent = in.readAll();
|
||||||
file.close();
|
file.close();
|
||||||
fileContentsMap[filePath] = fileContent;
|
fileContentsMap[filePath] = fileContent;
|
||||||
populateTreeWidgetFromMap();
|
progress.setValue(fileIndex + 1);
|
||||||
|
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||||
}
|
}
|
||||||
|
progress.setLabelText(tr("Übersetzungsliste wird vorbereitet …"));
|
||||||
|
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||||
|
populateTreeWidgetFromMap();
|
||||||
|
QApplication::restoreOverrideCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::populateTreeWidgetFromMap() {
|
void MainWindow::populateTreeWidgetFromMap() {
|
||||||
@@ -344,22 +388,23 @@ QVector<MainWindow::TranslationItem> MainWindow::parseTextBlock(const QString& i
|
|||||||
lineNumber = match.captured(1).toInt();
|
lineNumber = match.captured(1).toInt();
|
||||||
}
|
}
|
||||||
} else if (line.startsWith(" # ") || line.startsWith(" old ")) {
|
} else if (line.startsWith(" # ") || line.startsWith(" old ")) {
|
||||||
originalText = line.mid(line.indexOf("\"") + 1).trimmed();
|
const int firstQuote = line.indexOf('"');
|
||||||
originalText.chop(1);
|
const int lastQuote = line.lastIndexOf('"');
|
||||||
|
originalText = firstQuote >= 0 && lastQuote > firstQuote
|
||||||
|
? line.mid(firstQuote + 1, lastQuote - firstQuote - 1)
|
||||||
|
: QString();
|
||||||
identifier = "";
|
identifier = "";
|
||||||
} else if ((line.startsWith(" ") && !line.startsWith(" # ")) || line.startsWith(" new ")) {
|
} else if ((line.startsWith(" ") && !line.startsWith(" # ")) || line.startsWith(" new ")) {
|
||||||
translatedText = line.mid(4).trimmed();
|
const QString translationLine = line.startsWith(" ") ? line.mid(4) : line;
|
||||||
if (translatedText.startsWith("new \"")) {
|
const int firstQuote = translationLine.indexOf('"');
|
||||||
translatedText = translatedText.mid(5).trimmed();
|
const int lastQuote = translationLine.lastIndexOf('"');
|
||||||
} else if (translatedText.startsWith("\"")) {
|
if (firstQuote < 0 || lastQuote <= firstQuote) {
|
||||||
translatedText = translatedText.mid(1).trimmed();
|
continue;
|
||||||
} 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);
|
identifier = translationLine.startsWith("new ") || translationLine.startsWith('"')
|
||||||
|
? QString()
|
||||||
|
: translationLine.left(firstQuote).trimmed();
|
||||||
|
translatedText = translationLine.mid(firstQuote + 1, lastQuote - firstQuote - 1);
|
||||||
blocks.append(TranslationItem(lineNumber, identifier, originalText, translatedText));
|
blocks.append(TranslationItem(lineNumber, identifier, originalText, translatedText));
|
||||||
originalText.clear();
|
originalText.clear();
|
||||||
translatedText.clear();
|
translatedText.clear();
|
||||||
@@ -382,7 +427,25 @@ void MainWindow::on_reloadTranslationsButton_clicked()
|
|||||||
|
|
||||||
void MainWindow::on_reloadFilesButton_clicked()
|
void MainWindow::on_reloadFilesButton_clicked()
|
||||||
{
|
{
|
||||||
populateTreeWidgetFromMap();
|
if (ui->languageCombo->currentIndex() < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bool hasUnsavedChanges = false;
|
||||||
|
for (int index = 0; index < ui->treeWidget->topLevelItemCount(); ++index) {
|
||||||
|
if (ui->treeWidget->topLevelItem(index)->data(0, Qt::UserRole).toBool()) {
|
||||||
|
hasUnsavedChanges = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasUnsavedChanges && QMessageBox::warning(
|
||||||
|
this,
|
||||||
|
tr("Ungespeicherte Änderungen"),
|
||||||
|
tr("Durch das Neuladen werden ungespeicherte Änderungen verworfen. Fortfahren?"),
|
||||||
|
QMessageBox::Yes | QMessageBox::Cancel,
|
||||||
|
QMessageBox::Cancel) != QMessageBox::Yes) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
on_languageCombo_currentTextChanged(ui->languageCombo->currentText());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_nextUntranslatedButton_clicked() {
|
void MainWindow::on_nextUntranslatedButton_clicked() {
|
||||||
@@ -563,7 +626,9 @@ bool MainWindow::parseAndEditFile(QFile &backupFile, QTreeWidgetItem *fileItem,
|
|||||||
QString replacement = QString("\"%1\"").arg(replacedText.isEmpty() ? newText : replacedText);
|
QString replacement = QString("\"%1\"").arg(replacedText.isEmpty() ? newText : replacedText);
|
||||||
auto replacedBlock = block.replace(toReplace, replacement);
|
auto replacedBlock = block.replace(toReplace, replacement);
|
||||||
content.replace(match.capturedStart(0), match.capturedLength(0), replacedBlock);
|
content.replace(match.capturedStart(0), match.capturedLength(0), replacedBlock);
|
||||||
offset = match.capturedEnd(0);
|
// The replacement can have a different length. Continue after the new
|
||||||
|
// block, otherwise later translations in this file may be skipped.
|
||||||
|
offset = match.capturedStart(0) + replacedBlock.size();
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
offset = 0;
|
offset = 0;
|
||||||
@@ -577,7 +642,7 @@ bool MainWindow::parseAndEditFile(QFile &backupFile, QTreeWidgetItem *fileItem,
|
|||||||
QString replacement = QString("\"%1\"").arg(replacedText.isEmpty() ? newText : replacedText);
|
QString replacement = QString("\"%1\"").arg(replacedText.isEmpty() ? newText : replacedText);
|
||||||
auto replacedBlock = block.replace(toReplace, replacement);
|
auto replacedBlock = block.replace(toReplace, replacement);
|
||||||
content.replace(match.capturedStart(0), match.capturedLength(0), replacedBlock);
|
content.replace(match.capturedStart(0), match.capturedLength(0), replacedBlock);
|
||||||
offset = match.capturedEnd(0);
|
offset = match.capturedStart(0) + replacedBlock.size();
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
lines.append(content.split("\n"));
|
lines.append(content.split("\n"));
|
||||||
@@ -988,6 +1053,7 @@ void MainWindow::showBulkTranslationDialog()
|
|||||||
const bool dialogUsesLibreTranslate = bulkUsesLibreTranslate;
|
const bool dialogUsesLibreTranslate = bulkUsesLibreTranslate;
|
||||||
const QString dialogSourceLanguage = ui->deeplTranslateFrom->currentText();
|
const QString dialogSourceLanguage = ui->deeplTranslateFrom->currentText();
|
||||||
const QString dialogTargetLanguage = ui->deeplTranslateTo->currentText();
|
const QString dialogTargetLanguage = ui->deeplTranslateTo->currentText();
|
||||||
|
QSet<QTreeWidgetItem *> savedBulkFiles;
|
||||||
edits.reserve(bulkTranslations.size());
|
edits.reserve(bulkTranslations.size());
|
||||||
QTreeWidgetItem *currentFile = nullptr;
|
QTreeWidgetItem *currentFile = nullptr;
|
||||||
QVBoxLayout *fileLayout = nullptr;
|
QVBoxLayout *fileLayout = nullptr;
|
||||||
@@ -1086,9 +1152,12 @@ void MainWindow::showBulkTranslationDialog()
|
|||||||
scrollArea->setWidget(content);
|
scrollArea->setWidget(content);
|
||||||
layout->addWidget(scrollArea);
|
layout->addWidget(scrollArea);
|
||||||
|
|
||||||
auto applyTranslations = [this, &edits] {
|
auto applyTranslations = [this, &edits, &savedBulkFiles] {
|
||||||
for (int index = 0; index < bulkTranslations.size(); ++index) {
|
for (int index = 0; index < bulkTranslations.size(); ++index) {
|
||||||
QTreeWidgetItem *item = bulkTranslations[index].item;
|
QTreeWidgetItem *item = bulkTranslations[index].item;
|
||||||
|
if (savedBulkFiles.contains(item->parent())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
item->setText(3, edits[index]->toPlainText());
|
item->setText(3, edits[index]->toPlainText());
|
||||||
if (QTreeWidgetItem *parent = item->parent()) {
|
if (QTreeWidgetItem *parent = item->parent()) {
|
||||||
parent->setData(0, Qt::UserRole, true);
|
parent->setData(0, Qt::UserRole, true);
|
||||||
@@ -1100,7 +1169,7 @@ void MainWindow::showBulkTranslationDialog()
|
|||||||
int currentFileSection = 0;
|
int currentFileSection = 0;
|
||||||
QSet<QTreeWidgetItem *> promptedFiles;
|
QSet<QTreeWidgetItem *> promptedFiles;
|
||||||
connect(scrollArea->verticalScrollBar(), &QScrollBar::valueChanged, &dialog,
|
connect(scrollArea->verticalScrollBar(), &QScrollBar::valueChanged, &dialog,
|
||||||
[this, &fileSections, ¤tFileSection, &promptedFiles, applyTranslations](int scrollPosition) {
|
[this, &fileSections, ¤tFileSection, &promptedFiles, &savedBulkFiles, applyTranslations](int scrollPosition) {
|
||||||
int visibleFileSection = currentFileSection;
|
int visibleFileSection = currentFileSection;
|
||||||
for (int index = 0; index < fileSections.size(); ++index) {
|
for (int index = 0; index < fileSections.size(); ++index) {
|
||||||
if (fileSections[index].first->y() <= scrollPosition + 12) {
|
if (fileSections[index].first->y() <= scrollPosition + 12) {
|
||||||
@@ -1113,7 +1182,8 @@ void MainWindow::showBulkTranslationDialog()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QTreeWidgetItem *completedFile = fileSections[currentFileSection].second;
|
const int completedFileSection = currentFileSection;
|
||||||
|
QTreeWidgetItem *completedFile = fileSections[completedFileSection].second;
|
||||||
currentFileSection = visibleFileSection;
|
currentFileSection = visibleFileSection;
|
||||||
if (promptedFiles.contains(completedFile)) {
|
if (promptedFiles.contains(completedFile)) {
|
||||||
return;
|
return;
|
||||||
@@ -1131,6 +1201,9 @@ void MainWindow::showBulkTranslationDialog()
|
|||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
if (!saveFile(completedFile, errorMessage)) {
|
if (!saveFile(completedFile, errorMessage)) {
|
||||||
QMessageBox::critical(this, tr("Error"), errorMessage);
|
QMessageBox::critical(this, tr("Error"), errorMessage);
|
||||||
|
} else {
|
||||||
|
savedBulkFiles.insert(completedFile);
|
||||||
|
fileSections[completedFileSection].first->hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user