5#include "ui_machinetranslationdialog.h"
8#include "auto-translation/machinetranslator.h"
10#include <QtWidgets/qmessagebox.h>
12using namespace Qt::Literals::StringLiterals;
16MachineTranslationDialog::MachineTranslationDialog(QWidget *parent)
18 m_ui(std::make_unique<Ui::MachineTranslationDialog>()),
19 m_translator(std::make_unique<MachineTranslator>())
22 m_ui->statusLabel->setWordWrap(
true);
23 m_ui->statusLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
24 connect(m_ui->translateButton, &QPushButton::clicked,
this,
25 &MachineTranslationDialog::translateSelection);
26 connect(m_ui->filesComboBox, &QComboBox::currentIndexChanged,
this, [
this] {
27 m_ui->filterComboBox->setCurrentIndex(0);
30 connect(m_translator.get(), &MachineTranslator::batchTranslated,
this,
31 &MachineTranslationDialog::onBatchTranslated);
32 connect(m_translator.get(), &MachineTranslator::translationFailed,
this,
33 &MachineTranslationDialog::onTranslationFailed);
34 connect(m_ui->groupComboBox, &QComboBox::currentIndexChanged,
this, [
this] { updateStatus(); });
35 connect(m_ui->doneButton, &QPushButton::clicked,
this, [
this] {
36 if (discardTranslations())
39 connect(m_ui->cancelButton, &QPushButton::clicked,
this, [
this] {
40 if (discardTranslations())
43 connect(m_ui->applyButton, &QPushButton::clicked,
this,
44 &MachineTranslationDialog::applyTranslations);
46 connect(m_ui->stopButton, &QToolButton::clicked,
this, &MachineTranslationDialog::stop);
47 connect(m_ui->connectButton, &QPushButton::clicked,
this,
48 &MachineTranslationDialog::connectToOllama);
49 connect(m_translator.get(), &MachineTranslator::modelsReceived,
this,
50 [
this](
const QStringList &models) {
51 m_ui->modelComboBox->clear();
52 m_ui->modelComboBox->addItems(models);
54 connect(
this, &QDialog::finished, m_translator.get(), &MachineTranslator::stop);
55 connect(m_ui->filterComboBox, &QComboBox::currentIndexChanged,
this,
56 &MachineTranslationDialog::onFilterChanged);
68 m_ui->filesComboBox->clear();
69 m_ui->filesComboBox->addItems(m_dataModel->srcFileNames());
70 m_ui->filesComboBox->setCurrentIndex(0);
71 m_ui->translationLog->setText(tr(
"Translation Log"));
72 m_ui->translateButton->setEnabled(
true);
73 m_ui->stopButton->setEnabled(
false);
77 m_failedTranslations = 0;
78 m_receivedTranslations.clear();
79 m_ongoingTranslations.clear();
80 m_ui->applyButton->setEnabled(
false);
81 m_ui->progressBar->setVisible(
false);
82 m_translator->start();
87 const qsizetype receivedCount = m_receivedTranslations.size();
88 m_ui->statusLabel->setText(
89 tr(
"Translation status: %1/%2 source texts translated, %3/%2 failed.")
92 .arg(m_failedTranslations));
93 m_ui->progressBar->setValue((receivedCount + m_failedTranslations) * 100 / m_sentTexts);
95 QString html =
"<hr/><table cellpadding=\"4\""
100 for (
const QStringList &row : table) {
102 for (
const QString &col : row)
103 html +=
"<td>%1</td>"_L1.arg(col);
106 html +=
"</table>"_L1;
107 m_ui->translationLog->append(html);
110 if (receivedCount + m_failedTranslations == m_sentTexts) {
111 m_ui->translationLog->append(
112 tr(
"<hr/><b>Translation completed: %1/%2 translated, %3/%2 failed.</b>")
115 .arg(m_failedTranslations));
116 m_ui->translateButton->setEnabled(
true);
117 m_ui->stopButton->setEnabled(
false);
118 m_ui->applyButton->setEnabled(
true);
119 m_ui->progressBar->setVisible(
false);
121 m_ui->translateButton->setEnabled(
false);
122 m_ui->stopButton->setEnabled(
true);
123 m_ui->progressBar->setVisible(
true);
129 m_ui->translationLog->append(
"<hr/>"_L1);
130 m_ui->translationLog->append(info);
135 m_ui->translationLog->append(
"<hr/>"_L1);
136 m_ui->translationLog->append(
137 "<span style=\"color:red; font-weight: bold; \">%1</span>"_L1.arg(error));
142 return (m_receivedTranslations.empty()
143 || QMessageBox::warning(
144 this, tr(
"Qt Linguist"),
145 tr(
"The already %n translated item(s) will be discarded. Continue?", 0,
146 m_receivedTranslations.size()),
147 QMessageBox::Yes | QMessageBox::No)
148 == QMessageBox::Yes);
153 m_translator->stop();
154 m_ui->stopButton->setEnabled(
false);
155 m_ui->translateButton->setEnabled(
true);
157 logError(tr(
"Translation Stopped."));
162 const QString model = m_ui->modelComboBox->currentText();
163 const int id = m_ui->filesComboBox->currentIndex();
164 if (model.isEmpty()) {
165 logError(tr(
"Please verify the service URL is valid, "
166 "then select a translation model."));
170 logError(tr(
"Please select a file for translation."));
173 if (!discardTranslations())
177 const int filter = m_ui->filterComboBox->currentIndex();
178 const int group = m_ui->groupComboBox->currentIndex();
182 QMutexLocker lock(&m_mutex);
185 if (tm->translation().isEmpty()) {
186 messages.items.append(tm);
187 m_ongoingTranslations[tm] =
188 MultiDataIndex{ it.translationType(), id, it.group(), it.message() };
193 if (tm->translation().isEmpty()) {
194 messages.items.append(tm);
195 m_ongoingTranslations[tm] =
196 MultiDataIndex{ it.translationType(), id, it.group(), it.message() };
200 QMutexLocker lock(&m_mutex);
205 if (tm->translation().isEmpty()) {
206 messages.items.append(tm);
207 m_ongoingTranslations[tm] = MultiDataIndex{ type, id, group, i };
211 messages.srcLang = QLocale::languageToString(dm->sourceLanguage());
212 messages.tgtLang = QLocale::languageToString(dm->language());
213 m_sentTexts += messages.items.size();
214 m_translator->activateTranslationModel(model);
215 m_translator->translate(messages, m_ui->contextEdit->toPlainText().trimmed());
216 logInfo(tr(
"Translation Started"));
221 QHash<
const TranslatorMessage *, QString> translations)
223 QList<QStringList> log;
224 log.reserve(translations.size());
225 QMutexLocker lock(&m_mutex);
226 for (
const auto &[msg, translation] : translations.asKeyValueRange()) {
227 log.append({ msg->sourceText().simplified(), translation.simplified() });
228 m_receivedTranslations.append(std::make_pair(m_ongoingTranslations.take(msg), translation));
230 logInfo(tr(
"Translation Batch:"));
236 m_ui->groupLabel->setEnabled(id != 0);
237 m_ui->groupComboBox->setEnabled(id != 0);
238 m_ui->groupComboBox->clear();
239 int modelId = m_ui->filesComboBox->currentIndex();
244 for (
int i = 0; i < m_dataModel->model(modelId)->contextCount(); i++)
245 m_ui->groupComboBox->addItem(
246 m_dataModel->model(modelId)->groupItem(i, TEXTBASED)->group());
247 }
else if (id == 2) {
248 for (
int i = 0; i < m_dataModel->model(modelId)->labelCount(); i++)
249 m_ui->groupComboBox->addItem(
250 m_dataModel->model(modelId)->groupItem(i, IDBASED)->group());
252 m_ui->groupComboBox->setCurrentIndex(0);
257 QMutexLocker lock(&m_mutex);
258 for (
const auto &[item, translation] : std::as_const(m_receivedTranslations))
259 m_dataModel->setTranslation(item, translation);
261 logInfo(tr(
"Translations Applied."));
266 QList<QStringList> log;
267 log.reserve(failed.size() + 1);
269 QMutexLocker lock(&m_mutex);
270 m_failedTranslations += failed.size();
271 for (
const TranslatorMessage *m : failed) {
272 log << QStringList{ m->sourceText().simplified() };
273 m_ongoingTranslations.remove(m);
275 logError(tr(
"Failed Translation(s):"));
281 const int model = m_ui->filesComboBox->currentIndex();
282 const int filter = m_ui->filterComboBox->currentIndex();
283 const int group = m_ui->groupComboBox->currentIndex();
284 if (model < 0 || filter < 0 || (filter > 0 && group < 0)) {
285 m_ui->statusLabel->setText(tr(
"Translation status: -"));
286 }
else if (filter == 0) {
295 m_ui->statusLabel->setText(tr(
"Translation status: %n item(s). For best results, "
296 "translate in Context / Label batches.",
298 }
else if (group >= 0) {
305 m_ui->statusLabel->setText(tr(
"Translation status: %n item(s).", 0, count));
311 if (m_ui->serverText->text().isEmpty())
313 m_translator->setUrl(m_ui->serverText->text());
314 m_translator->requestModels();
DataModelIterator(TranslationType type, const DataModel *model=0, int groupNo=0, int messageNo=0)
MessageItem * current() const
GroupItem * groupItem(int index, TranslationType type) const
MessageItem * messageItem(int i) const
~MachineTranslationDialog()
void setDataModel(MultiDataModel *dm)
const TranslatorMessage & message() const