ScreenTranslator/src/correct/corrector.cpp

143 lines
3.3 KiB
C++
Raw Normal View History

2020-02-21 00:45:53 +07:00
#include "corrector.h"
2020-04-09 03:17:23 +07:00
#include "correctorworker.h"
2020-02-21 00:45:53 +07:00
#include "debug.h"
#include "languagecodes.h"
2020-02-21 00:45:53 +07:00
#include "manager.h"
2020-03-21 17:03:58 +07:00
#include "settings.h"
2020-02-21 00:45:53 +07:00
#include "task.h"
2020-04-09 03:17:23 +07:00
#include <QThread>
2020-03-21 17:03:58 +07:00
Corrector::Corrector(Manager &manager, const Settings &settings)
2020-02-21 00:45:53 +07:00
: manager_(manager)
2020-03-21 17:03:58 +07:00
, settings_(settings)
2020-04-09 03:17:23 +07:00
, workerThread_(new QThread(this))
{
auto worker = new CorrectorWorker;
connect(this, &Corrector::resetAuto, //
worker, &CorrectorWorker::reset);
connect(this, &Corrector::correctAuto, //
worker, &CorrectorWorker::handle);
connect(worker, &CorrectorWorker::finished, //
this, &Corrector::finishCorrection);
connect(workerThread_, &QThread::finished, //
worker, &QObject::deleteLater);
workerThread_->start();
worker->moveToThread(workerThread_);
}
Corrector::~Corrector()
2020-02-21 00:45:53 +07:00
{
2020-04-09 03:17:23 +07:00
workerThread_->quit();
const auto timeoutMs = 2000;
2020-05-01 19:20:21 +07:00
if (!workerThread_->wait(timeoutMs)) {
LTRACE() << "terminating hunspell thread";
2020-04-09 03:17:23 +07:00
workerThread_->terminate();
2020-05-01 19:20:21 +07:00
}
2020-02-21 00:45:53 +07:00
}
void Corrector::correct(const TaskPtr &task)
{
SOFT_ASSERT(task, return );
SOFT_ASSERT(task->isValid(), return );
queue_.push_back(task);
2020-03-09 15:47:40 +07:00
if (task->recognized.isEmpty()) {
finishCorrection(task);
2020-03-09 15:47:40 +07:00
return;
}
2020-04-09 03:17:23 +07:00
task->corrected = task->recognized;
2020-04-24 02:06:08 +07:00
if (!settings_.userSubstitutions.empty()) {
task->corrected = substituteUser(task->recognized, task->sourceLanguage);
2020-04-24 02:06:08 +07:00
LTRACE() << "Corrected with user data";
}
2020-02-21 00:45:53 +07:00
if (!task->useHunspell) {
finishCorrection(task);
2020-04-09 03:17:23 +07:00
return;
}
if (queue_.size() == 1)
processQueue();
}
void Corrector::processQueue()
{
if (queue_.empty())
return;
emit correctAuto(queue_.front());
2020-04-09 03:17:23 +07:00
}
void Corrector::updateSettings()
{
queue_.clear();
emit resetAuto(settings_.hunspellPath);
2020-04-09 03:17:23 +07:00
}
void Corrector::finishCorrection(const TaskPtr &task)
{
2020-02-21 00:45:53 +07:00
manager_.corrected(task);
SOFT_ASSERT(!queue_.empty(), return );
if (queue_.front() == task) {
queue_.pop_front();
} else {
LERROR() << "processed not first item in correction queue";
queue_.clear();
}
processQueue();
2020-02-21 00:45:53 +07:00
}
QString Corrector::substituteUser(const QString &source,
const LanguageId &language) const
{
auto result = source;
using It = Substitutions::const_iterator;
std::vector<std::pair<It, It>> ranges;
{
const auto range = settings_.userSubstitutions.equal_range(language);
if (range.first != settings_.userSubstitutions.cend())
ranges.push_back(range);
}
{
const auto anyId = LanguageCodes::anyLanguageId();
const auto range = settings_.userSubstitutions.equal_range(anyId);
if (range.first != settings_.userSubstitutions.cend())
ranges.push_back(range);
}
if (ranges.empty())
2020-02-21 00:45:53 +07:00
return result;
while (true) {
auto bestMatch = ranges.front().first;
2020-02-21 00:45:53 +07:00
auto bestMatchLen = 0;
for (const auto &range : ranges) {
for (auto it = range.first; it != range.second; ++it) {
const auto &sub = it->second;
if (!result.contains(sub.source))
continue;
const auto len = sub.source.length();
if (len > bestMatchLen) {
bestMatchLen = len;
bestMatch = it;
}
2020-02-21 00:45:53 +07:00
}
}
if (bestMatchLen < 1)
break;
result.replace(bestMatch->second.source, bestMatch->second.target);
}
return result;
}