From 718bb7314b2390ea0edb9fcb35800da569ea51ee Mon Sep 17 00:00:00 2001 From: Gres Date: Thu, 15 Apr 2021 21:08:16 +0300 Subject: [PATCH] Show settings page info and error --- screen-translator.pro | 2 + share/translations/screentranslator_ru.ts | 240 ++-- src/manager.cpp | 25 +- src/settings.cpp | 3 +- src/settingseditor.cpp | 243 +++- src/settingseditor.h | 19 +- src/settingseditor.ui | 1410 +++++++++++---------- src/settingsvalidator.cpp | 46 + src/settingsvalidator.h | 21 + 9 files changed, 1150 insertions(+), 859 deletions(-) create mode 100644 src/settingsvalidator.cpp create mode 100644 src/settingsvalidator.h diff --git a/screen-translator.pro b/screen-translator.pro index 71e038c..7f044d0 100644 --- a/screen-translator.pro +++ b/screen-translator.pro @@ -59,6 +59,7 @@ HEADERS += \ src/service/widgetstate.h \ src/settings.h \ src/settingseditor.h \ + src/settingsvalidator.h \ src/stfwd.h \ src/substitutionstable.h \ src/task.h \ @@ -95,6 +96,7 @@ SOURCES += \ src/service/widgetstate.cpp \ src/settings.cpp \ src/settingseditor.cpp \ + src/settingsvalidator.cpp \ src/substitutionstable.cpp \ src/translate/translator.cpp \ src/translate/webpage.cpp \ diff --git a/share/translations/screentranslator_ru.ts b/share/translations/screentranslator_ru.ts index 680e629..1f806e1 100644 --- a/share/translations/screentranslator_ru.ts +++ b/share/translations/screentranslator_ru.ts @@ -616,69 +616,54 @@ Ctrl - продолжить выделять Любой язык - + app приложение - + recognizers распознавание - + correction коррекция - + translators перевод - + Screen translator started Экранный переводчик запущен - + Updates available Доступны обновления - + Current version might be outdated. Check for updates to silence this warning Текущая версия может быть устаревшей. Проверьте обновления, чтобы отключить это сообщение - - No recognition languages available. Install some via Settings->Updates - Нет доступных языков распознавания. Установите нужные через Настройки->Обновление + + Incorrect settings found. Go to Settings + Обнвружены некорректные настройки. Перейдите в Настройки - - Recognition language not set. Go to Settings->Recognition and set it - Язык распознавания не задан. Задайте его в Настройки->Распознавание - - - - No translators enabled. Go to Settings->Translation and select some - Не выбран ни один переводчик. Активируйте хотя бы один в Настройки->Перевод - - - - Translation language not set. Go to Settings->Translation and set it - Язык перевода не задан. Задайте его в Настройки->Перевод - - - + Failed to set log file: %1 Ошибка установки лог-файла: %1 - + Started logging to file: %1 Начата запись в лог-файл: %1 @@ -727,35 +712,60 @@ in %1 Не восстанавливать интерфейс пользователя (размер и положения окна и т.д.) - + <p>Optical character recognition (OCR) and translation tool</p> <p>Инструмент оптического распознавания текста (OCR) и перевода</p> - + <p>Version: %1</p> <p>Версия: %1</p> - + <p>Changelog: <a href="%1">%2</a></p> <p>Список изменений: <a href="%1">%2</a></p> - + <p>License: <a href="%3">MIT</a></p> <p>Лицензия: <a href="%3">MIT</a></p> - + <p>Author: Gres (<a href="mailto:%1">%1</a>)</p> <p>Автор: Gres (<a href="mailto:%1">%1</a>)</p> - + <p>Issues: <a href="%1">%1</a></p> <p>Поддержка: <a href="%1">%1</a></p> + + + No recognizers installed + Нет установленных языков распознавания + + + + Recognition language not set + Не задан язык распознавания по умолчанию + + + + No translators installed + Нет установленных переводчиков + + + + No translators enabled (selected) + Нет активированных (выделенных) переводчиков + + + + Translation language not set + Не задан язык перевода + RecognizeWorker @@ -839,112 +849,112 @@ in %1 SettingsEditor - + Shortcuts Горячие клавиши - + Capture Захват - + Repeat capture Повторить захват - + Show last result Показать последний результат - + Copy result to clipboard Скопировать в буфер обмена - + Capture saved areas Захват сохраненных зон - + Proxy Прокси - + Type: Тип: - + User: Пользователь: - + Address: Адрес: - + Password: Пароль: - + Port: Порт: - + save password (unsafe) сохранять пароль (небезопасно) - + Library version Версия - + User substitutions Пользовательская коррекция - + Use auto corrections (hunspell) Использовать автокоррекцию (hunspell) - + Use user substitutions Использовать пользовательскую коррекцию - + Hunspell dictionaries path: Путь к словарям Hunspell: - + Language: Язык: - + secs сек - + Ignore SSL errors Игнорировать ошибки SSL - + Show message on program start Показать сообщения при старте @@ -954,202 +964,238 @@ in %1 Настройки - + Run at system start Добавить в автозапуск - + Portable (store data in same folder) Portable (хранить данные в папке с программой) - + Write trace file Писать логи в файл (отладка) - + Default language: Язык по умолчанию: - + Tessdata path: Путь к языкам (tessdata): - + \\ for \ symbol, \n for newline \\ для символа \ , \n для символа новой строки - + Translators path: Путь к переводчикам: - + Translators Переводчики - + Result window Окно результата - + Font: Шрифт: - + Font size: Размер шрифта: - + Font color: Цвет шрифта: - + Background: Фон: - + Show image Показывать изображение - + Show recognized Показывать распознанное - + Update check interval (days): Интервал проверки обновления (дней): - + 0 - disabled - отключено - + Translate text Переводить текст - + Single translator timeout: Переходить к следующему переводчику после: - + Result type Тип результата - + Tray Трей - + Window Окно - + Check now Проверить сейчас - + General Основное - + + This page contains general program settings + Эта страница содержит общие настройки программы + + + Recognition Распознавание - + + This page contains text recognition settings. It shows the available languages that program can convert from image to text + Эта страница содержит настройки распознавания текста. На ней представлены языки, которые программа может преобразовать из изображения в текст + + + Correction Коррекция - + + This page contains recognized text correction settings. It allows to fix some errors after recognition. +Hunspell searches for words that are similar to recognized ones in its dictionary. +User correction allows to manually fix some frequently happening mistakes. +User correction occurs before hunspell correction if both are enabled + Эта страница содаржит настройки исправления распознанного текста. Это позволяет исправить некоторые ошибки в результатах распознавания. +Hunspell ищет в своем словаре слова, похожие на распознанные. +Пользовательская коррекция позволяет вручную изменить частые ошибки. +Пользовательская коррекция выполняется до коррекции hunspell, если они обе активированы + + + Translation Перевод - + + This page contains settings, related to translation of the recognized text. Translation is done via enabled (checked) translation services. If one fails, then second one will be used and so on. If translator hangs it will be treated as failed after given timeout + Эта страница содержит настройки перевода распознанного текста. Перевод выполняется через активированные (выделенные) сервисы перевода. Если один переводчик не может перевести тест, то используется следующие и т.д. Если переводчик не отвечает в течение заданного времени, то также выполняется переход к следующему + + + Representation Отображение - + + This page contains result representation settings + Эта страница содержит настройки отображения результатов + + + Update Обновление - + + This page allow to install/update/remove program resources + Эта страница позволяет устанавливать,обновлять и удалять ресурсы, используемые программой + + + Help Помощь - + Disabled Отключен - + System Системный - + SOCKS 5 SOCKS 5 - + HTTP HTTP - + Optimized Оптимизированная - + Compatible Совместимая - + Use compatible version if you are experiencing crashes during recognition Используйте совместимую версию если программа неожиданно завершается во время распознавания - + <b>NOTE! Some translators might require the translation window to be visible. You can make it using the "Show translator" entry in the tray icon's context menu</b> <b>ПРИМЕЧАНИЕ! Для работы некоторых переводчиков может потребоваться активное окно перевода. Его можно отобразить при помощи пункта "Показать окно перевода" контекстного меню иконки в трее</b> - + Sample text Текст для проверки - + The program workflow consists of the following steps: 1. Selection on the screen area 2. Recognition of the selected area @@ -1172,9 +1218,9 @@ Then set default recognition and translation languages, enable some (or all) tra Далее установите языки распознавания и перевода по умолчанию, активируйте некоторые (или все) переводчики и настройку "переводить текст", если нужно. - + Portable changed. Apply settings first - Portable режиме изменени. Сначала применить настройки + Portable режим изменен. Сначала примените настройки diff --git a/src/manager.cpp b/src/manager.cpp index 6df8547..8d31b15 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -5,6 +5,7 @@ #include "recognizer.h" #include "representer.h" #include "settingseditor.h" +#include "settingsvalidator.h" #include "task.h" #include "translator.h" #include "trayicon.h" @@ -119,25 +120,11 @@ void Manager::updateSettings() tray_->setCaptureLockedEnabled(capturer_->canCaptureLocked()); - if (models_->sourceLanguageModel()->rowCount() == 0) { - fatalError( - QObject::tr("No recognition languages available. Install some via " - "Settings->Updates")); - } - if (settings_->sourceLanguage.isEmpty()) { - fatalError( - QObject::tr("Recognition language not set. Go to Settings->Recognition " - "and set it")); - } - if (settings_->doTranslation && settings_->translators.isEmpty()) { - fatalError(QObject::tr( - "No translators enabled. Go to Settings->Translation and select some")); - } - if (settings_->doTranslation && settings_->targetLanguage.isEmpty()) { - fatalError( - QObject::tr("Translation language not set. Go to Settings->Translation " - "and set it")); - } + const auto errors = SettingsValidator().check(*settings_, *models_); + if (errors.isEmpty()) + return; + + fatalError(QObject::tr("Incorrect settings found. Go to Settings")); } void Manager::setupProxy(const Settings &settings) diff --git a/src/settings.cpp b/src/settings.cpp index d9f138f..9711580 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -100,8 +100,7 @@ Substitutions loadLegacySubstitutions() const auto data = f.readAll(); - const auto lines = - QString::fromUtf8(data).split('\n', QString::SkipEmptyParts); + const auto lines = QString::fromUtf8(data).split('\n', Qt::SkipEmptyParts); for (const auto& line : lines) { const auto parts = line.mid(1, line.size() - 2).split("\",\""); // remove " if (parts.size() < 3) diff --git a/src/settingseditor.cpp b/src/settingseditor.cpp index 6292dde..3826768 100644 --- a/src/settingseditor.cpp +++ b/src/settingseditor.cpp @@ -1,18 +1,37 @@ #include "settingseditor.h" +#include "debug.h" #include "languagecodes.h" #include "manager.h" #include "runatsystemstart.h" +#include "settingsvalidator.h" #include "translator.h" #include "ui_settingseditor.h" #include "updates.h" #include "widgetstate.h" #include +#include + +namespace +{ +enum class Page { // order must match ui->pagesView + General, + Recognition, + Correction, + Translation, + Representation, + Update, + Help, + Count +}; +enum class PageColumn { Name, Description, Error, Count }; +} // namespace SettingsEditor::SettingsEditor(Manager &manager, update::Updater &updater) : ui(new Ui::SettingsEditor) , manager_(manager) , updater_(updater) + , pageModel_(new QStandardItemModel(this)) { ui->setupUi(this); @@ -20,19 +39,70 @@ SettingsEditor::SettingsEditor(Manager &manager, update::Updater &updater) this, &SettingsEditor::handleButtonBoxClicked); connect(ui->portable, &QCheckBox::toggled, // - this, &SettingsEditor::handlePortableChanged); + this, &SettingsEditor::updateState); ui->runAtSystemStart->setEnabled(service::RunAtSystemStart::isAvailable()); { - auto model = new QStringListModel(this); - model->setStringList({tr("General"), tr("Recognition"), tr("Correction"), - tr("Translation"), tr("Representation"), tr("Update"), - tr("Help")}); - ui->pagesList->setModel(model); + struct Info { + QString title; + QString description; + }; + + QMap names{ + {Page::General, + {tr("General"), tr("This page contains general program settings")}}, + + {Page::Recognition, + {tr("Recognition"), + tr("This page contains text recognition settings. " + "It shows the available languages that program can convert from " + "image to text")}}, + + {Page::Correction, + {tr("Correction"), + tr("This page contains recognized text correction settings. " + "It allows to fix some errors after recognition.\n" + "Hunspell searches for words that are similar to recognized ones " + "in its dictionary.\n" + "User correction allows to manually fix some frequently " + "happening mistakes.\n" + "User correction occurs before hunspell correction if both " + "are enabled")}}, + + {Page::Translation, + {tr("Translation"), + tr("This page contains settings, related to translation of the " + "recognized text. " + "Translation is done via enabled (checked) translation services. " + "If one fails, then second one will be used and so on. " + "If translator hangs it will be treated as failed after " + "given timeout")}}, + + {Page::Representation, + {tr("Representation"), + tr("This page contains result representation settings")}}, + + {Page::Update, + {tr("Update"), + tr("This page allow to install/update/remove program resources")}}, + + {Page::Help, {tr("Help"), tr("")}}, + }; + + for (const auto &i : names) { + const auto error = QString(); + pageModel_->appendRow({new QStandardItem(i.title), + new QStandardItem(i.description), + new QStandardItem(error)}); + } + ui->pagesList->setModel(pageModel_); + ui->pagesList->setModelColumn(int(PageColumn::Name)); auto selection = ui->pagesList->selectionModel(); connect(selection, &QItemSelectionModel::currentRowChanged, // this, &SettingsEditor::updateCurrentPage); + selection->select(pageModel_->index(0, 0), + QItemSelectionModel::SelectCurrent); } { @@ -89,16 +159,13 @@ SettingsEditor::SettingsEditor(Manager &manager, update::Updater &updater) connect(ui->fontColor, &QPushButton::clicked, // this, [this] { pickColor(ColorContext::Font); }); connect(ui->backgroundColor, &QPushButton::clicked, // - this, [this] { pickColor(ColorContext::Bagkround); }); + this, [this] { pickColor(ColorContext::Background); }); // updates ui->updatesView->header()->setObjectName("updatesHeader"); updater_.initView(ui->updatesView); - adjustUpdatesView(); - connect(&updater_, &update::Updater::checkedForUpdates, // - this, &SettingsEditor::adjustUpdatesView); connect(&updater_, &update::Updater::updated, // - this, &SettingsEditor::adjustUpdatesView); + this, &SettingsEditor::updateState); connect(ui->checkUpdates, &QPushButton::clicked, // &updater_, &update::Updater::checkForUpdates); @@ -198,13 +265,7 @@ Settings SettingsEditor::settings() const std::chrono::seconds(ui->translateTimeoutSpin->value()); settings.targetLanguage = LanguageCodes::idForName(ui->translateLangCombo->currentText()); - - settings.translators.clear(); - for (auto i = 0, end = ui->translatorList->count(); i < end; ++i) { - auto item = ui->translatorList->item(i); - if (item->checkState() == Qt::Checked) - settings.translators.append(item->text()); - } + settings.translators = enabledTranslators(); settings.resultShowType = ui->trayRadio->isChecked() ? ResultMode::Tooltip : ResultMode::Widget; @@ -223,11 +284,10 @@ Settings SettingsEditor::settings() const void SettingsEditor::setSettings(const Settings &settings) { - if (settings.isPortable() == ui->portable->isChecked()) - updateModels(settings.tessdataPath); - wasPortable_ = settings.isPortable(); + ui->portable->blockSignals(true); ui->portable->setChecked(settings.isPortable()); + ui->portable->blockSignals(false); ui->runAtSystemStart->setChecked(settings.runAtSystemStart); @@ -248,6 +308,7 @@ void SettingsEditor::setSettings(const Settings &settings) ui->proxySaveCheck->setChecked(settings.proxySavePassword); ui->tessdataPath->setText(settings.tessdataPath); + updateModels(); ui->tesseractLangCombo->setCurrentText( LanguageCodes::name(settings.sourceLanguage)); ui->tesseractVersion->setCurrentIndex(int(settings.tesseractVersion)); @@ -261,10 +322,9 @@ void SettingsEditor::setSettings(const Settings &settings) ui->ignoreSslCheck->setChecked(settings.ignoreSslErrors); ui->translateTimeoutSpin->setValue(settings.translationTimeout.count()); ui->translatorsPath->setText(settings.translatorsDir); - enabledTranslators_ = settings.translators; - updateTranslators(); ui->translateLangCombo->setCurrentText( LanguageCodes::name(settings.targetLanguage)); + updateTranslators(settings.translators); ui->trayRadio->setChecked(settings.resultShowType == ResultMode::Tooltip); ui->dialogRadio->setChecked(settings.resultShowType == ResultMode::Widget); @@ -282,19 +342,52 @@ void SettingsEditor::setSettings(const Settings &settings) ui->showCaptured->setChecked(settings.showCaptured); ui->autoUpdateInterval->setValue(settings.autoUpdateIntervalDays); + + updateState(); +} + +void SettingsEditor::updateState() +{ + Settings settings; + settings.setPortable(ui->portable->isChecked()); + ui->tessdataPath->setText(settings.tessdataPath); + ui->translatorsPath->setText(settings.translatorsDir); + ui->hunspellDir->setText(settings.hunspellDir); + + updateModels(); + updateTranslators(enabledTranslators()); + validateSettings(); + updateCurrentPage(); + + const auto portableChanged = wasPortable_ != settings.isPortable(); + ui->pageUpdate->setEnabled(!portableChanged); + ui->pageUpdate->setToolTip(portableChanged + ? tr("Portable changed. Apply settings first") + : QString()); } void SettingsEditor::updateCurrentPage() { - ui->pagesView->setCurrentIndex(ui->pagesList->currentIndex().row()); + const auto row = ui->pagesList->currentIndex().row(); + + const auto description = pageModel_->index(row, int(PageColumn::Description)); + ui->pageInfoLabel->setText(description.data().toString()); + ui->pageInfoLabel->setVisible(!ui->pageInfoLabel->text().isEmpty()); + + const auto error = pageModel_->index(row, int(PageColumn::Error)); + ui->pageErrorLabel->setText(error.data().toString()); + ui->pageErrorLabel->setVisible(!ui->pageErrorLabel->text().isEmpty()); + + ui->pagesView->setCurrentIndex(row); if (ui->pagesView->currentWidget() != ui->pageUpdate) return; + if (ui->updatesView->model()->rowCount() == 0) updater_.checkForUpdates(); } -void SettingsEditor::updateTranslators() +void SettingsEditor::updateTranslators(const QStringList &translators) { ui->translatorList->clear(); @@ -304,30 +397,15 @@ void SettingsEditor::updateTranslators() std::sort(names.begin(), names.end()); - if (!enabledTranslators_.isEmpty()) { - for (const auto &name : enabledTranslators_) names.removeOne(name); - names = enabledTranslators_ + names; - } - ui->translatorList->addItems(names); for (auto i = 0, end = ui->translatorList->count(); i < end; ++i) { auto item = ui->translatorList->item(i); - item->setCheckState(enabledTranslators_.contains(item->text()) - ? Qt::Checked - : Qt::Unchecked); + item->setCheckState(translators.contains(item->text()) ? Qt::Checked + : Qt::Unchecked); } } -void SettingsEditor::adjustUpdatesView() -{ - if (ui->tessdataPath->text().isEmpty()) // not inited yet - return; - - updateModels(ui->tessdataPath->text()); - updateTranslators(); -} - void SettingsEditor::handleButtonBoxClicked(QAbstractButton *button) { if (!button) @@ -344,31 +422,12 @@ void SettingsEditor::handleButtonBoxClicked(QAbstractButton *button) if (button == ui->buttonBox->button(QDialogButtonBox::Apply)) { const auto settings = this->settings(); manager_.applySettings(settings); - if (settings.isPortable() != wasPortable_) { - wasPortable_ = settings.isPortable(); - handlePortableChanged(); - } + wasPortable_ = ui->portable->isChecked(); + updateState(); return; } } -void SettingsEditor::handlePortableChanged() -{ - Settings settings; - settings.setPortable(ui->portable->isChecked()); - ui->tessdataPath->setText(settings.tessdataPath); - ui->translatorsPath->setText(settings.translatorsDir); - ui->hunspellDir->setText(settings.hunspellDir); - updateModels(settings.tessdataPath); - updateTranslators(); - - const auto portableChanged = wasPortable_ != settings.isPortable(); - ui->pageUpdate->setEnabled(!portableChanged); - ui->pageUpdate->setToolTip(portableChanged - ? tr("Portable changed. Apply settings first") - : QString()); -} - void SettingsEditor::updateResultFont() { auto font = ui->resultFont->currentFont(); @@ -376,10 +435,21 @@ void SettingsEditor::updateResultFont() ui->resultFont->setFont(font); } -void SettingsEditor::updateModels(const QString &tessdataPath) +QStringList SettingsEditor::enabledTranslators() const +{ + QStringList result; + for (auto i = 0, end = ui->translatorList->count(); i < end; ++i) { + auto item = ui->translatorList->item(i); + if (item->checkState() == Qt::Checked) + result.append(item->text()); + } + return result; +} + +void SettingsEditor::updateModels() { const auto source = ui->tesseractLangCombo->currentText(); - models_.update(tessdataPath); + models_.update(ui->tessdataPath->text()); if (!source.isEmpty()) { ui->tesseractLangCombo->setCurrentText(source); } else if (ui->tesseractLangCombo->count() > 0) { @@ -401,7 +471,7 @@ void SettingsEditor::pickColor(ColorContext context) palette.setColor(QPalette::Button, color); widget->setPalette(palette); - if (context == ColorContext::Bagkround) + if (context == ColorContext::Background) return; palette = ui->backgroundColor->palette(); @@ -409,3 +479,44 @@ void SettingsEditor::pickColor(ColorContext context) ui->backgroundColor->setPalette(palette); ui->backgroundColor->update(); } + +void SettingsEditor::validateSettings() +{ + for (auto i = 0, end = pageModel_->rowCount(); i < end; ++i) { + const auto name = pageModel_->index(i, int(PageColumn::Name)); + pageModel_->setData(name, QBrush(Qt::black), Qt::ForegroundRole); + + const auto error = pageModel_->index(i, int(PageColumn::Error)); + pageModel_->setData(error, {}); + } + + SettingsValidator validator; + const auto errors = validator.check(settings(), models_); + if (errors.isEmpty()) + return; + + using E = SettingsValidator::Error; + QMap errorToPage{ + {E::NoSourceInstalled, Page::Update}, + {E::NoSourceSet, Page::Recognition}, + {E::NoTranslatorInstalled, Page::Update}, + {E::NoTranslatorSet, Page::Translation}, + {E::NoTargetSet, Page::Translation}, + }; + + QMap summary; + for (const auto err : errors) { + SOFT_ASSERT(errorToPage.contains(err), continue); + auto page = errorToPage[err]; + summary[page].push_back(validator.toString(err)); + } + + for (auto it = summary.cbegin(), end = summary.cend(); it != end; ++it) { + const auto row = int(it.key()); + const auto index = pageModel_->index(row, int(PageColumn::Name)); + pageModel_->setData(index, QBrush(Qt::red), Qt::ForegroundRole); + + const auto error = pageModel_->index(row, int(PageColumn::Error)); + pageModel_->setData(error, it.value().join('\n')); + } +} diff --git a/src/settingseditor.h b/src/settingseditor.h index 168eaae..7d11f59 100644 --- a/src/settingseditor.h +++ b/src/settingseditor.h @@ -10,6 +10,7 @@ namespace Ui class SettingsEditor; } class QAbstractButton; +class QStandardItemModel; class SettingsEditor : public QDialog { @@ -23,20 +24,22 @@ public: void setSettings(const Settings &settings); private: - enum ColorContext { Font, Bagkround }; - void updateCurrentPage(); - void updateTranslators(); - void adjustUpdatesView(); + enum ColorContext { Font, Background }; void handleButtonBoxClicked(QAbstractButton *button); - void handlePortableChanged(); - void updateResultFont(); - void updateModels(const QString &tessdataPath); void pickColor(ColorContext context); + void updateResultFont(); + QStringList enabledTranslators() const; + + void updateState(); + void updateCurrentPage(); + void updateTranslators(const QStringList &translators); + void updateModels(); + void validateSettings(); Ui::SettingsEditor *ui; Manager &manager_; update::Updater &updater_; CommonModels models_; - QStringList enabledTranslators_; bool wasPortable_{false}; + QStandardItemModel *pageModel_; }; diff --git a/src/settingseditor.ui b/src/settingseditor.ui index 5b2bf06..6d0f417 100644 --- a/src/settingseditor.ui +++ b/src/settingseditor.ui @@ -7,23 +7,13 @@ 0 0 889 - 553 + 611 Settings - - - - Qt::Horizontal - - - QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - @@ -37,664 +27,750 @@ - - - - - 0 - 0 - - - + + + 0 - - - - - - Shortcuts - - - - - - - - - Repeat capture - - - - - - - - - - Show last result - - - - - - - - - - Copy result to clipboard - - - - - - - - - - Capture - - - - - - - Capture saved areas - - - - - - - - - - - - - Proxy - - - - - - Type: - - - - - - - - - - User: - - - - - - - - - - Address: - - - - - - - - - - Password: - - - - - - - - - - Port: - - - - - - - 1 - - - 65535 - - - - - - - save password (unsafe) - - - - - - - - - - Show message on program start - - - - - - - Run at system start - - - - - - - Portable (store data in same folder) - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Write trace file - - - - - - - - - - - Qt::Vertical - - - - 17 - 410 - - - - - - - - - - - true - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - - 0 - 0 - - - - Tessdata path: - - - - - - - - 0 - 0 - - - - Default language: - - - tesseractLangCombo - - - - - - - - - - Library version - - - - - - - - - - - - - - User substitutions - - - Qt::AlignCenter - - - - - - - \\ for \ symbol, \n for newline - - - QAbstractItemView::SelectRows - - - true - - - - - - - Use auto corrections (hunspell) - - - - - - - Use user substitutions - - - - - - - Hunspell dictionaries path: - - - - - - - - - - true - - - - - - - - - - - Translators path: - - - - - - - Translators - - - Qt::AlignCenter - - - - - - - Ignore SSL errors - - - - - - - - - - Translate text - - - - - - - Single translator timeout: - - - - - - - Language: - - - translateLangCombo - - - - - - - - - - true - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - QAbstractItemView::NoEditTriggers - - - QAbstractItemView::InternalMove - - - Qt::MoveAction - - - - - - - secs - - - - - - - - - - true - - - - - - - - - - - - 0 - 0 - - - - Result type - - - - - - - 0 - 0 - - - - Tray - - - - - - - - 0 - 0 - - - - Window - - - true - - - - - - - - - - Result window - - - - - - Font: - - - - - - - - - - Font size: - - - - - - - 6 - - - 24 - - - - - - - Font color: - - - - - - - - - - true - - - - - - - Background: - - - - - - - - - - true - - - - - - - Show image - - - - - - - Show recognized - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - true - - - - - - - - - - Update check interval (days): - - - - - - - 0 - disabled - - - 360 - - - - - - - - 0 - 0 - - - - Check now - - - - - - - - - - - - - - - - - true - - - - - - - - - - true - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - + + + + + 0 + + + 0 + + + + + + + + true + + + + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 118 + 118 + 118 + + + + + + + + + + + true + + + + + + + + + + + 0 + 0 + + + + 0 + + + + + + + Proxy + + + + + + Type: + + + + + + + + + + User: + + + + + + + + + + Address: + + + + + + + + + + Password: + + + + + + + + + + Port: + + + + + + + 1 + + + 65535 + + + + + + + save password (unsafe) + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Write trace file + + + + + + + Run at system start + + + + + + + Shortcuts + + + + + + + + + Repeat capture + + + + + + + + + + Show last result + + + + + + + + + + Copy result to clipboard + + + + + + + + + + Capture + + + + + + + Capture saved areas + + + + + + + + + + + + + Show message on program start + + + + + + + Portable (store data in same folder) + + + + + + + + + + + Qt::Vertical + + + + 17 + 410 + + + + + + + + + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + 0 + 0 + + + + Tessdata path: + + + + + + + + 0 + 0 + + + + Default language: + + + tesseractLangCombo + + + + + + + + + + Library version + + + + + + + + + + + + + + User substitutions + + + Qt::AlignCenter + + + + + + + \\ for \ symbol, \n for newline + + + QAbstractItemView::SelectRows + + + true + + + + + + + Use auto corrections (hunspell) + + + + + + + Use user substitutions + + + + + + + Hunspell dictionaries path: + + + + + + + + + + true + + + + + + + + + + + Translators path: + + + + + + + Translators + + + Qt::AlignCenter + + + + + + + Ignore SSL errors + + + + + + + + + + Translate text + + + + + + + Single translator timeout: + + + + + + + Language: + + + translateLangCombo + + + + + + + + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::InternalMove + + + Qt::MoveAction + + + + + + + secs + + + + + + + + + + true + + + + + + + + + + + + 0 + 0 + + + + Result type + + + + + + + 0 + 0 + + + + Tray + + + + + + + + 0 + 0 + + + + Window + + + true + + + + + + + + + + Result window + + + + + + Font: + + + + + + + + + + Font size: + + + + + + + 6 + + + 24 + + + + + + + Font color: + + + + + + + + + + true + + + + + + + Background: + + + + + + + + + + true + + + + + + + Show image + + + + + + + Show recognized + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + true + + + + + + + + + + Update check interval (days): + + + + + + + 0 - disabled + + + 360 + + + + + + + + 0 + 0 + + + + Check now + + + + + + + + + + + + + + + + + true + + + + + + + + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok + diff --git a/src/settingsvalidator.cpp b/src/settingsvalidator.cpp new file mode 100644 index 0000000..57acf78 --- /dev/null +++ b/src/settingsvalidator.cpp @@ -0,0 +1,46 @@ +#include "settingsvalidator.h" + +#include +#include + +QVector SettingsValidator::check( + const Settings &settings, const CommonModels &models) const +{ + QVector result; + + if (models.sourceLanguageModel()->rowCount() == 0) + result.append(Error::NoSourceInstalled); + + if (settings.sourceLanguage.isEmpty()) + result.append(Error::NoSourceSet); + + if (settings.doTranslation && models.targetLanguageModel()->rowCount() == 0) + result.append(Error::NoTranslatorInstalled); + + if (settings.doTranslation && settings.translators.isEmpty()) + result.append(Error::NoTranslatorSet); + + if (settings.doTranslation && settings.targetLanguage.isEmpty()) + result.append(Error::NoTargetSet); + + return result; +} + +QString SettingsValidator::toString(Error error) const +{ + switch (error) { + case Error::NoSourceInstalled: + return QObject::tr("No recognizers installed"); + + case Error::NoSourceSet: return QObject::tr("Recognition language not set"); + + case Error::NoTranslatorInstalled: + return QObject::tr("No translators installed"); + + case Error::NoTranslatorSet: + return QObject::tr("No translators enabled (selected)"); + + case Error::NoTargetSet: return QObject::tr("Translation language not set"); + } + return {}; +} diff --git a/src/settingsvalidator.h b/src/settingsvalidator.h new file mode 100644 index 0000000..bfb1af9 --- /dev/null +++ b/src/settingsvalidator.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +#include + +class SettingsValidator +{ +public: + enum class Error { + NoSourceInstalled, + NoSourceSet, + NoTranslatorSet, + NoTranslatorInstalled, + NoTargetSet + }; + + QVector check(const Settings& settings, + const CommonModels& models) const; + QString toString(Error error) const; +};