ScreenTranslator/src/manager.cpp

396 lines
9.8 KiB
C++
Raw Normal View History

2020-01-27 02:01:08 +07:00
#include "manager.h"
2020-02-21 00:45:53 +07:00
#include "capturer.h"
#include "corrector.h"
#include "debug.h"
#include "recognizer.h"
#include "representer.h"
#include "settingseditor.h"
#include "task.h"
#include "translator.h"
#include "trayicon.h"
2020-03-15 18:10:26 +07:00
#include "updates.h"
2013-11-23 13:48:34 +07:00
#include <QApplication>
2020-04-04 00:47:49 +07:00
#include <QDesktopServices>
2020-04-05 18:31:10 +07:00
#include <QFileInfo>
2020-04-04 00:47:49 +07:00
#include <QMessageBox>
2020-03-07 00:53:53 +07:00
#include <QNetworkProxy>
#include <QThread>
2013-11-23 13:48:34 +07:00
2020-03-15 18:10:26 +07:00
namespace
{
#ifdef DEVELOP
const auto updatesUrl = "http://localhost:8081/updates.json";
#else
const auto updatesUrl =
"https://raw.githubusercontent.com/OneMoreGres/ScreenTranslator/master/"
"updates.json";
#endif
2020-04-06 22:22:02 +07:00
const auto resultHideWaitUs = 300'000;
2020-03-15 18:10:26 +07:00
} // namespace
2020-04-08 00:54:42 +07:00
using Loader = update::Loader;
2020-03-15 18:10:26 +07:00
2020-02-21 00:45:53 +07:00
Manager::Manager()
2020-05-23 01:35:55 +07:00
: models_(std::make_unique<CommonModels>())
, settings_(std::make_unique<Settings>())
2020-04-08 00:54:42 +07:00
, updater_(std::make_unique<Loader>(Loader::Urls{{updatesUrl}}))
2020-04-05 18:34:47 +07:00
, updateAutoChecker_(std::make_unique<update::AutoChecker>(*updater_))
2020-02-21 00:45:53 +07:00
{
2020-03-21 17:03:58 +07:00
SOFT_ASSERT(settings_, return );
2020-04-11 17:57:37 +07:00
// updater components
(void)QT_TRANSLATE_NOOP("QObject", "app");
(void)QT_TRANSLATE_NOOP("QObject", "recognizers");
2020-07-12 19:12:56 +07:00
(void)QT_TRANSLATE_NOOP("QObject", "correction");
2020-04-11 17:57:37 +07:00
(void)QT_TRANSLATE_NOOP("QObject", "translators");
2020-03-21 17:03:58 +07:00
tray_ = std::make_unique<TrayIcon>(*this, *settings_);
2020-03-28 18:26:05 +07:00
capturer_ = std::make_unique<Capturer>(*this, *settings_, *models_);
2020-03-21 17:03:58 +07:00
recognizer_ = std::make_unique<Recognizer>(*this, *settings_);
translator_ = std::make_unique<Translator>(*this, *settings_);
corrector_ = std::make_unique<Corrector>(*this, *settings_);
2020-03-29 15:09:55 +07:00
representer_ =
std::make_unique<Representer>(*this, *tray_, *settings_, *models_);
2020-02-21 00:45:53 +07:00
qRegisterMetaType<TaskPtr>();
2013-11-23 13:48:34 +07:00
2020-03-21 17:03:58 +07:00
settings_->load();
updateSettings();
2020-03-09 15:29:51 +07:00
2020-03-21 17:03:58 +07:00
if (settings_->showMessageOnStart)
2020-03-09 15:29:51 +07:00
tray_->showInformation(QObject::tr("Screen translator started"));
2020-03-15 18:10:26 +07:00
2020-04-05 18:31:10 +07:00
warnIfOutdated();
2020-03-15 18:10:26 +07:00
QObject::connect(updater_.get(), &update::Loader::error, //
tray_.get(), &TrayIcon::showError);
QObject::connect(updater_.get(), &update::Loader::updated, //
tray_.get(), [this] {
tray_->showInformation(QObject::tr("Update completed"));
});
2020-03-17 01:44:33 +07:00
QObject::connect(updater_.get(), &update::Loader::updatesAvailable, //
tray_.get(), [this] {
tray_->showInformation(QObject::tr("Updates available"));
});
}
2020-03-18 01:32:36 +07:00
Manager::~Manager()
{
2020-03-21 17:03:58 +07:00
SOFT_ASSERT(settings_, return );
if (updateAutoChecker_ && updateAutoChecker_->isLastCheckDateChanged()) {
settings_->lastUpdateCheck = updateAutoChecker_->lastCheckDate();
settings_->saveLastUpdateCheck();
2020-05-01 19:20:21 +07:00
LTRACE() << "saved last update time";
2020-03-21 17:03:58 +07:00
}
2020-03-18 01:32:36 +07:00
}
2013-11-24 19:43:37 +07:00
2020-04-05 18:31:10 +07:00
void Manager::warnIfOutdated()
{
const auto now = QDateTime::currentDateTime();
const auto binaryInfo = QFileInfo(QApplication::applicationFilePath());
const auto date = binaryInfo.fileTime(QFile::FileTime::FileBirthTime);
const auto deadlineDays = 90;
if (date.daysTo(now) < deadlineDays)
return;
const auto updateDate = settings_->lastUpdateCheck;
if (updateDate.isValid() && updateDate.daysTo(now) < deadlineDays)
return;
tray_->showInformation(
QObject::tr("Current version might be outdated.\n"
"Check for updates to silence this warning"));
}
2020-03-21 17:03:58 +07:00
void Manager::updateSettings()
2020-02-21 00:45:53 +07:00
{
LTRACE() << "updateSettings";
2020-03-21 17:03:58 +07:00
SOFT_ASSERT(settings_, return );
2020-05-09 17:16:25 +07:00
tray_->resetFatalError();
tray_->setTaskActionsEnabled(false);
2020-04-26 18:06:01 +07:00
settings_->writeTrace = setupTrace(settings_->writeTrace);
2020-03-21 17:03:58 +07:00
setupProxy(*settings_);
setupUpdates(*settings_);
2020-03-15 18:10:26 +07:00
2020-03-28 18:26:05 +07:00
models_->update(settings_->tessdataPath);
2020-03-21 17:03:58 +07:00
tray_->updateSettings();
capturer_->updateSettings();
recognizer_->updateSettings();
2020-04-09 03:17:23 +07:00
corrector_->updateSettings();
2020-03-21 17:03:58 +07:00
translator_->updateSettings();
representer_->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"));
}
2020-02-21 00:45:53 +07:00
}
2020-03-07 00:53:53 +07:00
void Manager::setupProxy(const Settings &settings)
{
if (settings.proxyType == ProxyType::System) {
QNetworkProxyFactory::setUseSystemConfiguration(true);
return;
}
QNetworkProxyFactory::setUseSystemConfiguration(false);
if (settings.proxyType == ProxyType::Disabled) {
QNetworkProxy::setApplicationProxy({});
return;
}
QNetworkProxy proxy;
using T = QNetworkProxy::ProxyType;
proxy.setType(settings.proxyType == ProxyType::Socks5 ? T::Socks5Proxy
: T::HttpProxy);
proxy.setHostName(settings.proxyHostName);
proxy.setPort(settings.proxyPort);
proxy.setUser(settings.proxyUser);
proxy.setPassword(settings.proxyPassword);
QNetworkProxy::setApplicationProxy(proxy);
}
void Manager::setupUpdates(const Settings &settings)
{
updater_->model()->setExpansions({
{"$translators$", settings.translatorsDir},
{"$tessdata$", settings.tessdataPath},
2020-04-09 03:17:23 +07:00
{"$hunspell$", settings.hunspellDir},
2020-04-15 01:59:36 +07:00
{"$appdir$", QApplication::applicationDirPath()},
});
2020-04-05 18:34:47 +07:00
SOFT_ASSERT(updateAutoChecker_, return );
updateAutoChecker_->setLastCheckDate(settings.lastUpdateCheck);
updateAutoChecker_->setCheckIntervalDays(settings.autoUpdateIntervalDays);
}
2020-04-26 18:06:01 +07:00
bool Manager::setupTrace(bool isOn)
2020-04-04 00:47:49 +07:00
{
const auto oldFile = debug::traceFileName();
if (!isOn) {
debug::setTraceFileName({});
2020-04-10 00:58:20 +07:00
debug::isTrace = qEnvironmentVariableIsSet("TRACE");
2020-04-04 00:47:49 +07:00
if (!oldFile.isEmpty())
QDesktopServices::openUrl(QUrl::fromLocalFile(oldFile));
2020-04-26 18:06:01 +07:00
return false;
2020-04-04 00:47:49 +07:00
}
if (!oldFile.isEmpty())
2020-04-26 18:06:01 +07:00
return true;
2020-04-04 00:47:49 +07:00
const auto traceFile =
QStandardPaths::writableLocation(QStandardPaths::TempLocation) +
2020-04-16 01:01:59 +07:00
QLatin1String("/screen-translator-") +
2020-04-04 00:47:49 +07:00
QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss");
if (!debug::setTraceFileName(traceFile)) {
QMessageBox::warning(
2020-04-11 17:57:37 +07:00
nullptr, {}, QObject::tr("Failed to set log file: %1").arg(traceFile));
2020-04-26 18:06:01 +07:00
return false;
2020-04-04 00:47:49 +07:00
}
debug::isTrace = true;
QMessageBox::information(
nullptr, {}, QObject::tr("Started logging to file: %1").arg(traceFile));
2020-04-26 18:06:01 +07:00
return true;
2020-04-04 00:47:49 +07:00
}
2020-02-21 00:45:53 +07:00
void Manager::finishTask(const TaskPtr &task)
{
SOFT_ASSERT(task, return );
2020-04-11 17:48:44 +07:00
LTRACE() << "finishTask" << task;
2020-02-21 00:45:53 +07:00
--activeTaskCount_;
tray_->setActiveTaskCount(activeTaskCount_);
2020-02-21 00:45:53 +07:00
if (!task->isValid()) {
tray_->showError(task->error);
tray_->setTaskActionsEnabled(false);
2020-02-21 00:45:53 +07:00
return;
2015-10-10 18:45:57 +07:00
}
2020-02-21 00:45:53 +07:00
tray_->showSuccess();
}
2014-04-04 21:39:10 +07:00
2020-02-21 00:45:53 +07:00
void Manager::captured(const TaskPtr &task)
{
tray_->setCaptureLockedEnabled(capturer_->canCaptureLocked());
2020-02-21 00:45:53 +07:00
tray_->blockActions(false);
2020-02-21 00:45:53 +07:00
SOFT_ASSERT(task, return );
2020-04-11 17:48:44 +07:00
LTRACE() << "captured" << task;
2020-02-21 00:45:53 +07:00
++activeTaskCount_;
tray_->setActiveTaskCount(activeTaskCount_);
2013-11-24 20:06:19 +07:00
2020-02-21 00:45:53 +07:00
if (!task->isValid()) {
finishTask(task);
return;
}
2020-02-21 00:45:53 +07:00
recognizer_->recognize(task);
}
2020-02-21 00:45:53 +07:00
void Manager::captureCanceled()
{
tray_->setCaptureLockedEnabled(capturer_->canCaptureLocked());
2020-02-21 00:45:53 +07:00
tray_->blockActions(false);
2013-11-24 19:43:37 +07:00
}
2020-02-21 00:45:53 +07:00
void Manager::recognized(const TaskPtr &task)
{
SOFT_ASSERT(task, return );
2020-04-11 17:48:44 +07:00
LTRACE() << "recognized" << task;
2020-02-21 00:45:53 +07:00
if (!task->isValid()) {
finishTask(task);
return;
}
2020-02-21 00:45:53 +07:00
corrector_->correct(task);
}
2020-02-21 00:45:53 +07:00
void Manager::corrected(const TaskPtr &task)
{
SOFT_ASSERT(task, return );
2020-04-11 17:48:44 +07:00
LTRACE() << "corrected" << task;
2020-02-21 00:45:53 +07:00
if (!task->isValid()) {
finishTask(task);
return;
}
2013-11-23 13:48:34 +07:00
2020-02-21 00:45:53 +07:00
if (!task->targetLanguage.isEmpty())
translator_->translate(task);
else
translated(task);
2013-11-23 13:48:34 +07:00
}
2020-02-21 00:45:53 +07:00
void Manager::translated(const TaskPtr &task)
{
SOFT_ASSERT(task, return );
2020-04-11 17:48:44 +07:00
LTRACE() << "translated" << task;
2013-11-23 13:48:34 +07:00
2020-02-21 00:45:53 +07:00
finishTask(task);
2013-11-24 20:06:19 +07:00
2020-02-21 00:45:53 +07:00
representer_->represent(task);
2020-03-28 16:45:13 +07:00
tray_->setTaskActionsEnabled(!task->isNull());
}
void Manager::applySettings(const Settings &settings)
{
2020-03-21 17:03:58 +07:00
SOFT_ASSERT(settings_, return );
2020-04-05 18:34:47 +07:00
const auto lastUpdate = settings_->lastUpdateCheck; // not handled in editor
2020-03-21 17:03:58 +07:00
*settings_ = settings;
2020-04-05 18:34:47 +07:00
settings_->lastUpdateCheck = lastUpdate;
2020-03-21 17:03:58 +07:00
settings_->save();
updateSettings();
}
2020-02-21 00:45:53 +07:00
void Manager::fatalError(const QString &text)
{
tray_->blockActions(false);
tray_->showFatalError(text);
}
2020-02-21 00:45:53 +07:00
void Manager::capture()
{
SOFT_ASSERT(capturer_, return );
2020-04-06 22:22:02 +07:00
2020-02-21 00:45:53 +07:00
tray_->blockActions(true);
2020-04-06 22:22:02 +07:00
if (representer_->isVisible()) {
representer_->hide();
QThread::usleep(resultHideWaitUs);
}
2020-02-21 00:45:53 +07:00
capturer_->capture();
tray_->setRepeatCaptureEnabled(true);
}
2020-02-21 00:45:53 +07:00
void Manager::repeatCapture()
{
SOFT_ASSERT(capturer_, return );
tray_->blockActions(true);
capturer_->repeatCapture();
}
void Manager::captureLocked()
{
SOFT_ASSERT(capturer_, return );
if (representer_->isVisible()) {
representer_->hide();
2020-04-06 22:22:02 +07:00
QThread::usleep(resultHideWaitUs);
}
capturer_->captureLocked();
}
2020-02-21 00:45:53 +07:00
void Manager::settings()
{
SettingsEditor editor(*this, *updater_);
2020-02-21 00:45:53 +07:00
2020-03-21 17:03:58 +07:00
SOFT_ASSERT(settings_, return );
editor.setSettings(*settings_);
2020-02-21 00:45:53 +07:00
tray_->blockActions(true);
auto result = editor.exec();
tray_->blockActions(false);
if (result != QDialog::Accepted)
return;
2020-02-21 00:45:53 +07:00
tray_->resetFatalError();
2020-03-21 17:03:58 +07:00
const auto edited = editor.settings();
applySettings(edited);
2013-11-24 19:43:37 +07:00
}
2013-11-23 13:48:34 +07:00
void Manager::showLast()
2020-02-21 00:45:53 +07:00
{
SOFT_ASSERT(representer_, return );
representer_->showLast();
}
2020-02-21 00:45:53 +07:00
void Manager::showTranslator()
{
SOFT_ASSERT(translator_, return );
translator_->show();
}
void Manager::copyLastToClipboard()
{
SOFT_ASSERT(representer_, return );
representer_->clipboardLast();
2013-11-23 13:48:34 +07:00
}
2020-02-21 00:45:53 +07:00
void Manager::quit()
{
QApplication::quit();
}