Added WebTranslator class.
This commit is contained in:
parent
f3c4f1c5b5
commit
01d969968e
@ -37,6 +37,7 @@ SOURCES += main.cpp\
|
|||||||
ProcessingItem.cpp \
|
ProcessingItem.cpp \
|
||||||
ImageProcessing.cpp \
|
ImageProcessing.cpp \
|
||||||
LanguageHelper.cpp \
|
LanguageHelper.cpp \
|
||||||
|
WebTranslator.cpp \
|
||||||
GoogleWebTranslator.cpp
|
GoogleWebTranslator.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
@ -51,6 +52,7 @@ HEADERS += \
|
|||||||
ResultDialog.h \
|
ResultDialog.h \
|
||||||
ImageProcessing.h \
|
ImageProcessing.h \
|
||||||
LanguageHelper.h \
|
LanguageHelper.h \
|
||||||
|
WebTranslator.h \
|
||||||
GoogleWebTranslator.h \
|
GoogleWebTranslator.h \
|
||||||
StAssert.h
|
StAssert.h
|
||||||
|
|
||||||
@ -71,4 +73,5 @@ OTHER_FILES += \
|
|||||||
images/icon.ico \
|
images/icon.ico \
|
||||||
README.md \
|
README.md \
|
||||||
uncrustify.cfg\
|
uncrustify.cfg\
|
||||||
|
translators/google.js \
|
||||||
TODO.md
|
TODO.md
|
||||||
|
@ -24,6 +24,7 @@ namespace settings_names {
|
|||||||
const QString doTranslation = "doTranslation";
|
const QString doTranslation = "doTranslation";
|
||||||
const QString sourceLanguage = "source_language";
|
const QString sourceLanguage = "source_language";
|
||||||
const QString translationLanguage = "translation_language";
|
const QString translationLanguage = "translation_language";
|
||||||
|
const QString translationTimeout = "translation_timeout";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,6 +48,7 @@ namespace settings_values {
|
|||||||
const bool doTranslation = true;
|
const bool doTranslation = true;
|
||||||
const QString sourceLanguage = "auto";
|
const QString sourceLanguage = "auto";
|
||||||
const QString translationLanguage = "ru";
|
const QString translationLanguage = "ru";
|
||||||
|
const int translationTimeout = 15; // secs
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SETTINGS_H
|
#endif // SETTINGS_H
|
||||||
|
@ -64,6 +64,7 @@ void SettingsEditor::saveSettings () const {
|
|||||||
settings.setValue (translationLanguage, trLanguage);
|
settings.setValue (translationLanguage, trLanguage);
|
||||||
QString sourceLanguage = dictionary_.translateForOcrCode (ocrLanguage);
|
QString sourceLanguage = dictionary_.translateForOcrCode (ocrLanguage);
|
||||||
settings.setValue (sourceLanguage, sourceLanguage);
|
settings.setValue (sourceLanguage, sourceLanguage);
|
||||||
|
settings.setValue (translationTimeout, ui->translateTimeoutSpin->value ());
|
||||||
settings.endGroup ();
|
settings.endGroup ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +105,7 @@ void SettingsEditor::loadSettings () {
|
|||||||
ui->doTranslationCombo->setChecked (GET (doTranslation).toBool ());
|
ui->doTranslationCombo->setChecked (GET (doTranslation).toBool ());
|
||||||
QString trLanguage = dictionary_.translateCodeToUi (GET (translationLanguage).toString ());
|
QString trLanguage = dictionary_.translateCodeToUi (GET (translationLanguage).toString ());
|
||||||
ui->translateLangCombo->setCurrentText (trLanguage);
|
ui->translateLangCombo->setCurrentText (trLanguage);
|
||||||
|
ui->translateTimeoutSpin->setValue (GET (translationTimeout).toInt ());
|
||||||
settings.endGroup ();
|
settings.endGroup ();
|
||||||
#undef GET
|
#undef GET
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>603</width>
|
<width>603</width>
|
||||||
<height>269</height>
|
<height>296</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -194,7 +194,7 @@
|
|||||||
<string>Перевод</string>
|
<string>Перевод</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
<item row="0" column="0" colspan="2">
|
<item row="0" column="0" colspan="3">
|
||||||
<widget class="QCheckBox" name="doTranslationCombo">
|
<widget class="QCheckBox" name="doTranslationCombo">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Необходимо ли переводить (вкл) распознанный текст.</p></body></html></string>
|
<string><html><head/><body><p>Необходимо ли переводить (вкл) распознанный текст.</p></body></html></string>
|
||||||
@ -204,20 +204,37 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0" colspan="2">
|
||||||
|
<widget class="QLabel" name="label_9">
|
||||||
|
<property name="whatsThis">
|
||||||
|
<string><html><head/><body><p>Максимальное время, которое может быть затрачено на перевод, чтобы он не считался &quot;зависшим&quot;.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Максимальное время перевода:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QSpinBox" name="translateTimeoutSpin">
|
||||||
|
<property name="suffix">
|
||||||
|
<string> сек.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="label_6">
|
<widget class="QLabel" name="label_6">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Язык, на который осуществляется перевод.</p></body></html></string>
|
<string><html><head/><body><p>Язык, на который осуществляется перевод.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Язык результата</string>
|
<string>Язык результата:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>translateLangCombo</cstring>
|
<cstring>translateLangCombo</cstring>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="2" column="1" colspan="2">
|
||||||
<widget class="QComboBox" name="translateLangCombo"/>
|
<widget class="QComboBox" name="translateLangCombo"/>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
124
WebTranslator.cpp
Normal file
124
WebTranslator.cpp
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
#include <QWebView>
|
||||||
|
#include <QWebFrame>
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QFile>
|
||||||
|
|
||||||
|
#include "WebTranslator.h"
|
||||||
|
#include "ProcessingItem.h"
|
||||||
|
#include "Settings.h"
|
||||||
|
#include "StAssert.h"
|
||||||
|
#include "WebTranslatorProxy.h"
|
||||||
|
|
||||||
|
WebTranslator::WebTranslator ()
|
||||||
|
: QObject (),
|
||||||
|
proxy_ (new WebTranslatorProxy (this)), view_ (new QWebView), isReady_ (true) {
|
||||||
|
|
||||||
|
view_->settings ()->setAttribute (QWebSettings::AutoLoadImages, false);
|
||||||
|
view_->settings ()->setAttribute (QWebSettings::DeveloperExtrasEnabled, true);
|
||||||
|
|
||||||
|
connect (view_, SIGNAL (loadFinished (bool)), SLOT (loadFinished (bool)));
|
||||||
|
connect (view_->page ()->mainFrame (), SIGNAL (javaScriptWindowObjectCleared ()),
|
||||||
|
this, SLOT (addProxyToView ()));
|
||||||
|
connect (view_->page ()->networkAccessManager (), SIGNAL (finished (QNetworkReply *)),
|
||||||
|
this, SLOT (replyFinished (QNetworkReply *)));
|
||||||
|
|
||||||
|
translationTimeout_.setSingleShot (true);
|
||||||
|
connect (&translationTimeout_, SIGNAL (timeout ()), SLOT (abortTranslation ()));
|
||||||
|
|
||||||
|
connect (proxy_, SIGNAL (error (QString)), SLOT (proxyError (QString)));
|
||||||
|
connect (proxy_, SIGNAL (translated (QString)), SLOT (proxyTranslated (QString)));
|
||||||
|
|
||||||
|
applySettings ();
|
||||||
|
}
|
||||||
|
|
||||||
|
WebTranslator::~WebTranslator () {
|
||||||
|
delete view_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebTranslator::addProxyToView () {
|
||||||
|
view_->page ()->mainFrame ()->addToJavaScriptWindowObject ("st_wtp", proxy_);
|
||||||
|
view_->page ()->mainFrame ()->evaluateJavaScript (script_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebTranslator::translate (ProcessingItem item) {
|
||||||
|
queue_.push_back (item);
|
||||||
|
translateQueued ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebTranslator::translateQueued () {
|
||||||
|
if (isReady_ && !script_.isEmpty () && !queue_.isEmpty ()) {
|
||||||
|
isReady_ = false;
|
||||||
|
runScriptForItem (queue_.first ());
|
||||||
|
translationTimeout_.start ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebTranslator::runScriptForItem (const ProcessingItem &item) {
|
||||||
|
ST_ASSERT (!script_.isEmpty ());
|
||||||
|
proxy_->setItem (item);
|
||||||
|
view_->page ()->mainFrame ()->evaluateJavaScript ("translate();");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebTranslator::proxyError (const QString &message) {
|
||||||
|
emit error (message);
|
||||||
|
finishTranslation ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebTranslator::proxyTranslated (const QString &text) {
|
||||||
|
if (!queue_.isEmpty () && queue_.first ().recognized == proxy_->sourceText ()) {
|
||||||
|
ProcessingItem &item = queue_.first ();
|
||||||
|
item.translated = text;
|
||||||
|
emit translated (item);
|
||||||
|
}
|
||||||
|
finishTranslation ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebTranslator::abortTranslation () {
|
||||||
|
emit error (tr ("Перевод отменен по таймауту."));
|
||||||
|
finishTranslation ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebTranslator::loadFinished (bool ok) {
|
||||||
|
if (!ok) {
|
||||||
|
QString url = view_->url ().toString ();
|
||||||
|
emit error (tr ("Ошибка загрузки страницы (%1) для перевода.").arg (url));
|
||||||
|
finishTranslation ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebTranslator::finishTranslation () {
|
||||||
|
translationTimeout_.stop ();
|
||||||
|
if (!queue_.isEmpty ()) {
|
||||||
|
queue_.pop_front ();
|
||||||
|
}
|
||||||
|
isReady_ = true;
|
||||||
|
translateQueued ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebTranslator::replyFinished (QNetworkReply *reply) {
|
||||||
|
emit proxy_->resourceLoaded (reply->url ().toString ());
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebTranslator::applySettings () {
|
||||||
|
QSettings settings;
|
||||||
|
settings.beginGroup (settings_names::translationGroup);
|
||||||
|
#define GET(NAME) settings.value (settings_names::NAME, settings_values::NAME)
|
||||||
|
translationTimeout_.setInterval (GET (translationTimeout).toInt () * 1000);
|
||||||
|
#undef GET
|
||||||
|
|
||||||
|
QFile f ("translators/google.js");
|
||||||
|
if (f.open (QFile::ReadOnly)) {
|
||||||
|
script_ = QString::fromUtf8 (f.readAll ());
|
||||||
|
if (script_.isEmpty ()) {
|
||||||
|
emit error (tr ("Пустой сценарий для перевода. Перевод недоступен."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
emit error (tr ("Не считан сценарий для перевода. Перевод недоступен."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebTranslator::setDebugMode (bool isOn) {
|
||||||
|
view_->setVisible (isOn);
|
||||||
|
}
|
53
WebTranslator.h
Normal file
53
WebTranslator.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#ifndef WEBTRANSLATOR_H
|
||||||
|
#define WEBTRANSLATOR_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include "ProcessingItem.h"
|
||||||
|
|
||||||
|
class QWebView;
|
||||||
|
class QNetworkReply;
|
||||||
|
|
||||||
|
class WebTranslatorProxy;
|
||||||
|
|
||||||
|
class WebTranslator : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit WebTranslator ();
|
||||||
|
~WebTranslator ();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void translated (ProcessingItem item);
|
||||||
|
void error (QString text);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void translate (ProcessingItem item);
|
||||||
|
void applySettings ();
|
||||||
|
void setDebugMode (bool isOn);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void loadFinished (bool ok);
|
||||||
|
void replyFinished (QNetworkReply *reply);
|
||||||
|
void addProxyToView ();
|
||||||
|
void abortTranslation ();
|
||||||
|
void proxyError (const QString &message);
|
||||||
|
void proxyTranslated (const QString &text);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void translateQueued ();
|
||||||
|
void runScriptForItem (const ProcessingItem &item);
|
||||||
|
void finishTranslation ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
WebTranslatorProxy *proxy_;
|
||||||
|
QWebView *view_;
|
||||||
|
QVector<ProcessingItem> queue_;
|
||||||
|
bool isReady_;
|
||||||
|
QString script_;
|
||||||
|
QTimer translationTimeout_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WEBTRANSLATOR_H
|
25
WebTranslatorProxy.cpp
Normal file
25
WebTranslatorProxy.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#include "WebTranslatorProxy.h"
|
||||||
|
#include "ProcessingItem.h"
|
||||||
|
|
||||||
|
WebTranslatorProxy::WebTranslatorProxy (QObject *parent)
|
||||||
|
: QObject (parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebTranslatorProxy::setItem (const ProcessingItem &item) {
|
||||||
|
sourceText_ = item.recognized;
|
||||||
|
sourceLanguage_ = item.ocrLanguage;
|
||||||
|
resultLanguage_ = item.translateLanguage;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &WebTranslatorProxy::sourceText () const {
|
||||||
|
return sourceText_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &WebTranslatorProxy::sourceLanguage () const {
|
||||||
|
return sourceLanguage_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &WebTranslatorProxy::resultLanguage () const {
|
||||||
|
return resultLanguage_;
|
||||||
|
}
|
||||||
|
|
38
WebTranslatorProxy.h
Normal file
38
WebTranslatorProxy.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#ifndef WEBTRANSLATORPROXY_H
|
||||||
|
#define WEBTRANSLATORPROXY_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class ProcessingItem;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Proxy class between WebTranslator and QWebView.
|
||||||
|
*/
|
||||||
|
class WebTranslatorProxy : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY (QString sourceText READ sourceText)
|
||||||
|
Q_PROPERTY (QString sourceLanguage READ sourceLanguage)
|
||||||
|
Q_PROPERTY (QString resultLanguage READ resultLanguage)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit WebTranslatorProxy (QObject *parent = 0);
|
||||||
|
|
||||||
|
void setItem (const ProcessingItem &item);
|
||||||
|
|
||||||
|
const QString &sourceText () const;
|
||||||
|
const QString &sourceLanguage () const;
|
||||||
|
const QString &resultLanguage () const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void translated (const QString &text);
|
||||||
|
void error (const QString &message);
|
||||||
|
|
||||||
|
void resourceLoaded (const QString &url);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString sourceText_;
|
||||||
|
QString sourceLanguage_;
|
||||||
|
QString resultLanguage_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WEBTRANSLATORPROXY_H
|
31
translators/google.js
Normal file
31
translators/google.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
var isPageLoaded = false;
|
||||||
|
var isTranslationFinished = false; // async translation request
|
||||||
|
|
||||||
|
function checkFinished () {
|
||||||
|
if (!isPageLoaded || !isTranslationFinished) return;
|
||||||
|
setTimeout(function () {
|
||||||
|
var spans = [].slice.call (document.querySelectorAll ('#result_box > span'));
|
||||||
|
var text = spans.reduce (function (res, i) {
|
||||||
|
return res + ' ' + i.innerText;
|
||||||
|
}, '');
|
||||||
|
st_wtp.translated (text);
|
||||||
|
}, 500); // wait for gui fill
|
||||||
|
}
|
||||||
|
function onResourceLoad (url) {
|
||||||
|
if (url.indexOf ('/translate_a/single') > -1) {
|
||||||
|
isTranslationFinished = true;
|
||||||
|
checkFinished ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
st_wtp.resourceLoaded.connect (onResourceLoad);
|
||||||
|
function onPageLoad () {
|
||||||
|
isPageLoaded = true;
|
||||||
|
checkFinished ();
|
||||||
|
}
|
||||||
|
window.onload = onPageLoad();
|
||||||
|
|
||||||
|
function translate (){
|
||||||
|
var url = 'https://translate.google.com/#auto/' +
|
||||||
|
st_wtp.resultLanguage + '/' + st_wtp.sourceText;
|
||||||
|
window.location = url;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user