diff --git a/mainwindow.cpp b/mainwindow.cpp index 191b09d..326dbeb 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -13,6 +13,8 @@ #include #include #include +#include +#include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) @@ -90,30 +92,20 @@ void MainWindow::on_languageCombo_currentTextChanged(const QString &selectedLang void MainWindow::populateTreeWidgetFromMap() { ui->treeWidget->clear(); - for (const auto &pair : fileContentsMap) { + 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); - QStringList blocks = pair.second.split("\n # "); - for (const QString &block : blocks) { - if (block.trimmed().isEmpty()) { - continue; - } - if (block.contains("\n old") && block.contains("\n new")) { - QStringList lines = block.trimmed().split('\n'); - if (lines.size() >= 3) { - QString lineNumber = lines[0].section(':', 1, 1).trimmed(); - QString originalText = lines[1].section('"', 1, 1).trimmed(); - QString newText = lines[2].section('"', 1, 1).trimmed(); - QTreeWidgetItem *blockItem = new QTreeWidgetItem(fileItem); - blockItem->setText(0, lineNumber); - blockItem->setText(1, originalText); - blockItem->setText(2, newText); - } - } + auto parsedBlocks = parseTextBlock(pair.second); + for (const auto& block : qAsConst(parsedBlocks)) { + QTreeWidgetItem *blockItem = new QTreeWidgetItem(fileItem); + blockItem->setText(0, QString::number(block.line)); + blockItem->setText(1, block.oldText); + blockItem->setText(2, block.newText); } } + ui->treeWidget->resizeColumnToContents(0); int firstColumnWidth = ui->treeWidget->columnWidth(0); int remainingWidth = ui->treeWidget->viewport()->width() - firstColumnWidth; @@ -123,6 +115,39 @@ void MainWindow::populateTreeWidgetFromMap() { countAndShowUntranslated(); } +QVector MainWindow::parseTextBlock(const QString& input) { + QVector blocks; + QStringList lines = input.split("\n", Qt::SkipEmptyParts); + int lineNumber = 0; + QString identifier, originalText, translatedText; + for (const QString& line : lines) { + if (line.contains("# game/")) { + QRegExp regExp("# game/.+:(\\d+)"); + if (regExp.indexIn(line.trimmed()) != -1) { + lineNumber = regExp.cap(1).toInt(); + } + } else if (line.startsWith(" # ") || line.startsWith(" old ")) { + originalText = line.mid(line.indexOf("\"") + 1).trimmed(); + originalText.chop(1); // Remove trailing quotation mark + } 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(); + } + translatedText.chop(1); + blocks.append(TranslationItem(lineNumber, identifier, originalText, translatedText)); + originalText.clear(); + translatedText.clear(); + } + } + 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(); @@ -196,7 +221,6 @@ void MainWindow::on_setAndNextAndAutoTranslate_clicked() void MainWindow::on_translationEdit_returnPressed() { - qDebug() << ui->enterActionCombo->currentIndex(); switch (ui->enterActionCombo->currentIndex()) { case 0: on_setAndNextAndAutoTranslate_clicked(); @@ -273,50 +297,55 @@ bool MainWindow::editAndSaveFile(QTreeWidgetItem *fileItem, const QString &backu return false; } } + qDebug() << "file created"; return true; } bool MainWindow::parseAndEditFile(QFile &backupFile, QTreeWidgetItem *fileItem, QStringList &lines, bool &changed) { QTextStream backupStream(&backupFile); - QString fileName = fileItem->text(0); - while (!backupStream.atEnd()) { - QString line = backupStream.readLine().trimmed(); // Trim the line before processing - if (line.startsWith("#") && line.contains(fileName)) { - QString originalIdentifierLine(line.trimmed()); - QString lineNumber = line.section(':', 1, 1).trimmed(); - QString nextLine = backupStream.readLine(); - - if (nextLine.trimmed().startsWith("old")) { - QString originalOldText = nextLine.section('"', 1, 1).trimmed(); - QString originalNewText = backupStream.readLine(); - QString newText = findNewText(fileItem, lineNumber, originalOldText); - if (newText.isEmpty()) { - newText = originalNewText.trimmed(); - } - lines.append(QString(" %1").arg(originalIdentifierLine)); - lines.append(QString(" old \"%1\"").arg(originalOldText)); - if (newText.isEmpty()) { - lines.append(" new \"\""); - } else { - lines.append(QString(" new \"%1\"").arg(newText)); - } - changed = true; - } else { - lines.append(line); - lines.append(nextLine); - } - } else { - lines.append(line); - } + QString content = backupStream.readAll(); + QString dummyVariable = "Ihr Ersatztext"; + 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) { +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) { + if (childItem->text(0) == lineNumber && childItem->text(1) == originalText && childItem->text(3) == speaker) { return childItem->text(2); } } @@ -472,3 +501,36 @@ void MainWindow::countAndShowUntranslated() 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() { + searchNext(); +} + +void MainWindow::searchInTree(QTreeWidgetItem *item, const QString &query) { + for (int i = 0; i < item->childCount(); ++i) { + QTreeWidgetItem *childItem = item->child(i); + for (int column = 1; column <= 2; ++column) { + if (childItem->text(column).contains(query, Qt::CaseInsensitive)) { + ui->treeWidget->setCurrentItem(childItem); + ui->treeWidget->scrollToItem(childItem); + return; + } + } + searchInTree(childItem, query); + } +} + +void MainWindow::searchNext() { + if (searchQuery.isEmpty()) return; + QTreeWidgetItem *startItem = ui->treeWidget->currentItem(); + if (!startItem) startItem = ui->treeWidget->topLevelItem(0); + searchInTree(startItem, searchQuery); +} diff --git a/mainwindow.h b/mainwindow.h index 5c1991e..dcff07c 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -37,12 +37,26 @@ private slots: void onDeeplTranslationPossibilitiesLoaded(QNetworkReply *reply); void on_deeplTranslateFrom_currentTextChanged(const QString &sourceLanguage); void on_autoTranslateButton_clicked(); + void on_searchButton_clicked(); + void on_searchNextButton_clicked(); private: + struct TranslationItem { + TranslationItem(int line_, QString character_, QString oldText_, QString newText_): + line(line_), + character(character_), + oldText(oldText_), + newText(newText_) {}; + int line; + QString character; + QString oldText; + QString newText; + }; Ui::MainWindow *ui; std::map fileContentsMap; std::map > translationsMap; const QString deeplAuthKey = "5f6bc5cc-1e5d-4c69-9ef0-eb3cc2c1ece5:fx"; + QString searchQuery; void crawlProject(); void populateTreeWidgetFromMap(); void saveFiles(QStringList &failedFiles); @@ -50,10 +64,13 @@ private: bool editAndSaveFile(QTreeWidgetItem *fileItem, const QString &backupFileName, const QString &fileName); bool saveToFile(const QString &backupFileName, const QStringList &lines); bool parseAndEditFile(QFile &backupFile, QTreeWidgetItem *fileItem, QStringList &lines, bool &changed); - QString findNewText(QTreeWidgetItem *fileItem, const QString &lineNumber, const QString &originalText); + QString findNewText(QTreeWidgetItem *fileItem, const QString &lineNumber, const QString &originalText, const QString &speaker); void loadDeeplTranslationPossibilities(); void renderDeeplSources(); void translationRequestFinished(QNetworkReply *reply); void countAndShowUntranslated(); + void searchNext(); + void searchInTree(QTreeWidgetItem *item, const QString &query); + QVector parseTextBlock(const QString &block); }; #endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui index a689b60..b69ab69 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -112,6 +112,11 @@ Translation + + + Speaker + + All items @@ -122,6 +127,9 @@ + + + @@ -173,6 +181,24 @@ + + + + + + Search + + + + + + + Next + + + + +