This commit is contained in:
msn 2013-11-24 16:43:37 +04:00
parent 7f15cabdf0
commit ff43ab624b
15 changed files with 667 additions and 100 deletions

View File

@ -32,6 +32,10 @@ void GlobalActionHelper::init()
bool GlobalActionHelper::makeGlobal(QAction* action) bool GlobalActionHelper::makeGlobal(QAction* action)
{ {
QKeySequence hotKey = action->shortcut (); QKeySequence hotKey = action->shortcut ();
if (hotKey.isEmpty ())
{
return true;
}
Qt::KeyboardModifiers allMods = Qt::ShiftModifier | Qt::ControlModifier | Qt::KeyboardModifiers allMods = Qt::ShiftModifier | Qt::ControlModifier |
Qt::AltModifier | Qt::MetaModifier; Qt::AltModifier | Qt::MetaModifier;
Qt::Key key = hotKey.isEmpty() ? Qt::Key key = hotKey.isEmpty() ?
@ -50,6 +54,35 @@ bool GlobalActionHelper::makeGlobal(QAction* action)
return res; return res;
} }
bool GlobalActionHelper::removeGlobal(QAction *action)
{
QKeySequence hotKey = action->shortcut ();
if (hotKey.isEmpty ())
{
return true;
}
Qt::KeyboardModifiers allMods = Qt::ShiftModifier | Qt::ControlModifier |
Qt::AltModifier | Qt::MetaModifier;
Qt::Key key = hotKey.isEmpty() ?
Qt::Key(0) :
Qt::Key((hotKey[0] ^ allMods) & hotKey[0]);
Qt::KeyboardModifiers mods = hotKey.isEmpty() ?
Qt::KeyboardModifiers(0) :
Qt::KeyboardModifiers(hotKey[0] & allMods);
const quint32 nativeKey = nativeKeycode(key);
const quint32 nativeMods = nativeModifiers(mods);
if (!actions_.contains (qMakePair(nativeKey, nativeMods)))
{
return true;
}
const bool res = unregisterHotKey(nativeKey, nativeMods);
if (res)
actions_.remove (qMakePair(nativeKey, nativeMods));
else
qWarning() << "Failed to unregister global hotkey:" << hotKey.toString();
return res;
}
quint32 GlobalActionHelper::nativeKeycode(Qt::Key key) quint32 GlobalActionHelper::nativeKeycode(Qt::Key key)
{ {
switch (key) switch (key)
@ -227,7 +260,6 @@ quint32 GlobalActionHelper::nativeModifiers(Qt::KeyboardModifiers modifiers)
native |= MOD_ALT; native |= MOD_ALT;
if (modifiers & Qt::MetaModifier) if (modifiers & Qt::MetaModifier)
native |= MOD_WIN; native |= MOD_WIN;
// TODO: resolve these?
//if (modifiers & Qt::KeypadModifier) //if (modifiers & Qt::KeypadModifier)
//if (modifiers & Qt::GroupSwitchModifier) //if (modifiers & Qt::GroupSwitchModifier)
return native; return native;

View File

@ -14,6 +14,7 @@ class GlobalActionHelper : public QAbstractNativeEventFilter
static void init (); static void init ();
static bool makeGlobal (QAction* action); static bool makeGlobal (QAction* action);
static bool removeGlobal (QAction* action);
private: private:
static QHash<QPair<quint32, quint32>, QAction*> actions_; static QHash<QPair<quint32, quint32>, QAction*> actions_;

View File

@ -7,7 +7,9 @@
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QScreen> #include <QScreen>
#include <QThread> #include <QThread>
#include <QSettings>
#include "Settings.h"
#include "SettingsEditor.h" #include "SettingsEditor.h"
#include "SelectionDialog.h" #include "SelectionDialog.h"
#include "GlobalActionHelper.h" #include "GlobalActionHelper.h"
@ -17,7 +19,8 @@
Manager::Manager(QObject *parent) : Manager::Manager(QObject *parent) :
QObject(parent), QObject(parent),
trayIcon_ (new QSystemTrayIcon (QIcon (":/images/icon.png"), this)), trayIcon_ (new QSystemTrayIcon (QIcon (":/images/icon.png"), this)),
selection_ (new SelectionDialog) selection_ (new SelectionDialog),
captureAction_ (NULL)
{ {
GlobalActionHelper::init (); GlobalActionHelper::init ();
@ -28,6 +31,8 @@ Manager::Manager(QObject *parent) :
Recognizer* recognizer = new Recognizer; Recognizer* recognizer = new Recognizer;
connect (selection_, SIGNAL (selected (QPixmap)), connect (selection_, SIGNAL (selected (QPixmap)),
recognizer, SLOT (recognize (QPixmap))); recognizer, SLOT (recognize (QPixmap)));
connect (recognizer, SIGNAL (error (QString)),
SLOT (showError (QString)));
QThread* recognizerThread = new QThread (this); QThread* recognizerThread = new QThread (this);
recognizer->moveToThread (recognizerThread); recognizer->moveToThread (recognizerThread);
recognizerThread->start (); recognizerThread->start ();
@ -35,6 +40,8 @@ Manager::Manager(QObject *parent) :
Translator* translator = new Translator; Translator* translator = new Translator;
connect (recognizer, SIGNAL (recognized (QString)), connect (recognizer, SIGNAL (recognized (QString)),
translator, SLOT (translate (QString))); translator, SLOT (translate (QString)));
connect (translator, SIGNAL (error (QString)),
SLOT (showError (QString)));
QThread* translatorThread = new QThread (this); QThread* translatorThread = new QThread (this);
translator->moveToThread (translatorThread); translator->moveToThread (translatorThread);
translatorThread->start (); translatorThread->start ();
@ -42,25 +49,43 @@ Manager::Manager(QObject *parent) :
connect (translator, SIGNAL (translated (QString, QString)), connect (translator, SIGNAL (translated (QString, QString)),
SLOT (showTranslation (QString, QString))); SLOT (showTranslation (QString, QString)));
connect (this, SIGNAL (settingsEdited ()), this, SLOT (applySettings ()));
connect (this, SIGNAL (settingsEdited ()), recognizer, SLOT (applySettings ()));
connect (this, SIGNAL (settingsEdited ()), translator, SLOT (applySettings ()));
trayIcon_->setContextMenu (trayContextMenu ()); trayIcon_->setContextMenu (trayContextMenu ());
trayIcon_->show (); trayIcon_->show ();
}
Manager::~Manager() applySettings ();
{
} }
QMenu*Manager::trayContextMenu() QMenu*Manager::trayContextMenu()
{ {
QMenu* menu = new QMenu (); QMenu* menu = new QMenu ();
QAction* capture = menu->addAction (tr ("Захват"), this, SLOT (capture ()), captureAction_ = menu->addAction (tr ("Захват"), this, SLOT (capture ()));
tr ("Ctrl+Alt+Z"));
GlobalActionHelper::makeGlobal (capture);
menu->addAction (tr ("Настройки"), this, SLOT (settings ())); menu->addAction (tr ("Настройки"), this, SLOT (settings ()));
menu->addAction (tr ("Выход"), this, SLOT (close ())); menu->addAction (tr ("Выход"), this, SLOT (close ()));
return menu; return menu;
} }
void Manager::applySettings()
{
QSettings settings;
settings.beginGroup (settings_names::guiGroup);
QString captureHotkey = settings.value (settings_names::captureHotkey,
settings_values::captureHotkey).
toString ();
Q_CHECK_PTR (captureAction_);
GlobalActionHelper::removeGlobal (captureAction_);
captureAction_->setShortcut (captureHotkey);
GlobalActionHelper::makeGlobal (captureAction_);
}
Manager::~Manager()
{
}
void Manager::capture() void Manager::capture()
{ {
QList<QScreen*> screens = QApplication::screens (); QList<QScreen*> screens = QApplication::screens ();
@ -77,6 +102,7 @@ void Manager::settings()
{ {
SettingsEditor editor; SettingsEditor editor;
editor.setWindowIcon (trayIcon_->icon ()); editor.setWindowIcon (trayIcon_->icon ());
connect (&editor, SIGNAL (settingsEdited ()), SIGNAL (settingsEdited ()));
editor.exec (); editor.exec ();
} }
@ -87,5 +113,13 @@ void Manager::close()
void Manager::showTranslation(QString sourceText, QString translatedText) void Manager::showTranslation(QString sourceText, QString translatedText)
{ {
QString message = sourceText + " - " + translatedText;
qDebug () << sourceText << translatedText;
trayIcon_->showMessage (tr ("Перевод"), message, QSystemTrayIcon::Information);
}
void Manager::showError(QString text)
{
qCritical () << text;
trayIcon_->showMessage (tr ("Ошибка"), text, QSystemTrayIcon::Critical);
} }

View File

@ -4,6 +4,7 @@
#include <QObject> #include <QObject>
#include <QPixmap> #include <QPixmap>
class QAction;
class QMenu; class QMenu;
class QSystemTrayIcon; class QSystemTrayIcon;
@ -19,13 +20,17 @@ class Manager : public QObject
signals: signals:
void showPixmap (QPixmap pixmap); void showPixmap (QPixmap pixmap);
void recognize (QPixmap pixmap); void recognize (QPixmap pixmap);
void settingsEdited ();
private slots: private slots:
void capture (); void capture ();
void settings (); void settings ();
void close (); void close ();
void applySettings ();
void showTranslation (QString sourceText, QString translatedText); void showTranslation (QString sourceText, QString translatedText);
void showError (QString text);
private: private:
QMenu* trayContextMenu (); QMenu* trayContextMenu ();
@ -33,6 +38,7 @@ class Manager : public QObject
private: private:
QSystemTrayIcon* trayIcon_; QSystemTrayIcon* trayIcon_;
SelectionDialog* selection_; SelectionDialog* selection_;
QAction* captureAction_;
}; };

View File

@ -1,11 +1,92 @@
#include "Recognizer.h" #include "Recognizer.h"
#include <tesseract/baseapi.h>
#include <QDebug>
#include <QSettings>
#include "Settings.h"
Recognizer::Recognizer(QObject *parent) : Recognizer::Recognizer(QObject *parent) :
QObject(parent) QObject(parent),
engine_ (NULL), imageScale_ (0)
{ {
applySettings ();
}
void Recognizer::applySettings()
{
QSettings settings;
settings.beginGroup (settings_names::recogntionGroup);
tessDataDir_ = settings.value (settings_names::tessDataPlace,
settings_values::tessDataPlace).toString ();
ocrLanguage_ = settings.value (settings_names::ocrLanguage,
settings_values::ocrLanguage).toString ();
imageScale_ = settings.value (settings_names::imageScale,
settings_values::imageScale).toInt ();
initEngine ();
}
bool Recognizer::initEngine()
{
if (tessDataDir_.isEmpty () || ocrLanguage_.isEmpty ())
{
emit error (tr ("Неверные параметры для OCR"));
return false;
}
if (engine_ != NULL)
{
delete engine_;
}
engine_ = new tesseract::TessBaseAPI();
int result = engine_->Init(qPrintable (tessDataDir_), qPrintable (ocrLanguage_),
tesseract::OEM_DEFAULT);
if (result != 0)
{
emit error (tr ("Ошибка инициализации OCR: %1").arg (result));
delete engine_;
engine_ = NULL;
return false;
}
return true;
} }
void Recognizer::recognize(QPixmap pixmap) void Recognizer::recognize(QPixmap pixmap)
{ {
Q_ASSERT (!pixmap.isNull ());
if (engine_ == NULL)
{
if (!initEngine ())
{
return;
}
}
QPixmap scaled = pixmap;
if (imageScale_ > 0)
{
scaled = pixmap.scaledToHeight (pixmap.height () * imageScale_,
Qt::SmoothTransformation);
}
QImage image = scaled.toImage ();
const int bytesPerPixel = image.depth () / 8;
engine_->SetImage (image.bits (), image.width (), image.height (),
bytesPerPixel, image.bytesPerLine ());
char* outText = engine_->GetUTF8Text();
engine_->Clear();
QString result (outText);
result = result.trimmed();
if (!result.isEmpty ())
{
emit recognized (result);
}
else
{
emit error (tr ("Текст не распознан."));
}
delete [] outText;
} }

View File

@ -4,6 +4,12 @@
#include <QObject> #include <QObject>
#include "QPixmap" #include "QPixmap"
namespace tesseract
{
class TessBaseAPI;
}
class Recognizer : public QObject class Recognizer : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -12,9 +18,21 @@ class Recognizer : public QObject
signals: signals:
void recognized (QString text); void recognized (QString text);
void error (QString text);
public slots: public slots:
void recognize (QPixmap pixmap); void recognize (QPixmap pixmap);
void applySettings ();
private:
bool initEngine ();
private:
tesseract::TessBaseAPI* engine_;
QString tessDataDir_;
QString ocrLanguage_;
int imageScale_;
}; };

View File

@ -4,13 +4,16 @@
# #
#------------------------------------------------- #-------------------------------------------------
QT += core gui QT += core gui network webkitwidgets
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = ScreenTranslator TARGET = ScreenTranslator
TEMPLATE = app TEMPLATE = app
INCLUDEPATH += C:/build/include
LIBS += -LC:/build/bin -ltesseract
SOURCES += main.cpp\ SOURCES += main.cpp\
Manager.cpp \ Manager.cpp \
@ -26,7 +29,8 @@ HEADERS += \
SelectionDialog.h \ SelectionDialog.h \
GlobalActionHelper.h \ GlobalActionHelper.h \
Recognizer.h \ Recognizer.h \
Translator.h Translator.h \
Settings.h
FORMS += \ FORMS += \
SettingsEditor.ui \ SettingsEditor.ui \

View File

@ -50,10 +50,13 @@ bool SelectionDialog::eventFilter(QObject* object, QEvent* event)
QRect selection = QRect (startSelectPos_, endPos).normalized (); QRect selection = QRect (startSelectPos_, endPos).normalized ();
startSelectPos_ = currentSelectPos_ = QPoint (); startSelectPos_ = currentSelectPos_ = QPoint ();
QPixmap selectedPixmap = currentPixmap_.copy (selection); QPixmap selectedPixmap = currentPixmap_.copy (selection);
if (!selectedPixmap.isNull ())
{
emit selected (selectedPixmap); emit selected (selectedPixmap);
accept (); accept ();
} }
} }
}
else if (event->type () == QEvent::MouseMove) else if (event->type () == QEvent::MouseMove)
{ {
QMouseEvent* mouseEvent = static_cast <QMouseEvent*> (event); QMouseEvent* mouseEvent = static_cast <QMouseEvent*> (event);
@ -64,12 +67,15 @@ bool SelectionDialog::eventFilter(QObject* object, QEvent* event)
} }
} }
else if (event->type () == QEvent::Paint) else if (event->type () == QEvent::Paint)
{
QRect selection = QRect (startSelectPos_, currentSelectPos_).normalized ();
if (selection.isValid ())
{ {
QPainter painter (ui->label); QPainter painter (ui->label);
painter.setPen (Qt::red); painter.setPen (Qt::red);
QRect selection = QRect (startSelectPos_, currentSelectPos_).normalized ();
painter.drawRect (selection); painter.drawRect (selection);
} }
}
return QDialog::eventFilter (object, event); return QDialog::eventFilter (object, event);
} }

42
Settings.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef SETTINGS_H
#define SETTINGS_H
#include <QString>
namespace settings_names
{
//! UI
const QString guiGroup = "GUI";
const QString geometry = "geometry";
const QString captureHotkey = "captureHotkey";
//! Recognition
const QString recogntionGroup = "Recognition";
const QString tessDataPlace = "tessdata_dir";
const QString ocrLanguage = "language";
const QString imageScale = "image_scale";
//! Translation
const QString translationGroup = "Translation";
const QString translationLanguage = "translation_language";
}
namespace settings_values
{
const QString appName = "ScreenTranslator";
const QString companyName = "Gres";
//! UI
const QString captureHotkey = "Ctrl+Alt+Z";
//! Recognition
const QString tessDataPlace = "./";
const QString ocrLanguage = "eng";
const int imageScale = 5;
//! Translation
const QString translationLanguage = "ru";
}
#endif // SETTINGS_H

View File

@ -1,14 +1,203 @@
#include "SettingsEditor.h" #include "SettingsEditor.h"
#include "ui_SettingsEditor.h" #include "ui_SettingsEditor.h"
#include <QSettings>
#include <QFileDialog>
#include "Settings.h"
SettingsEditor::SettingsEditor(QWidget *parent) : SettingsEditor::SettingsEditor(QWidget *parent) :
QDialog(parent), QDialog(parent),
ui(new Ui::SettingsEditor) ui(new Ui::SettingsEditor)
{ {
ui->setupUi(this); ui->setupUi(this);
connect (ui->tessdataButton, SIGNAL (clicked ()), SLOT (openTessdataDialog ()));
connect (ui->tessdataEdit, SIGNAL (textChanged (const QString&)),
SLOT (initOcrLangCombo ()));
initTranslateLangCombo ();
loadSettings ();
loadState ();
} }
SettingsEditor::~SettingsEditor() SettingsEditor::~SettingsEditor()
{ {
saveState ();
delete ui; delete ui;
} }
void SettingsEditor::done(int result)
{
if (result == QDialog::Accepted)
{
saveSettings ();
emit settingsEdited ();
}
QDialog::done (result);
}
void SettingsEditor::saveSettings() const
{
QSettings settings;
settings.beginGroup (settings_names::guiGroup);
settings.setValue (settings_names::captureHotkey, ui->captureEdit->text ());
settings.endGroup ();
settings.beginGroup (settings_names::recogntionGroup);
settings.setValue (settings_names::tessDataPlace, ui->tessdataEdit->text ());
settings.setValue (settings_names::ocrLanguage, ui->ocrLangCombo->currentText ());
settings.setValue (settings_names::imageScale, ui->imageScaleSpin->value ());
settings.endGroup ();
settings.beginGroup (settings_names::translationGroup);
settings.setValue (settings_names::translationLanguage,
ui->translateLangCombo->currentText ());
settings.endGroup ();
}
void SettingsEditor::openTessdataDialog()
{
QString path = QFileDialog::getExistingDirectory (this, tr ("Путь к tessdata"));
if (path.isEmpty ())
{
return;
}
QDir dir (path);
if (dir.dirName () == QString ("tessdata"))
{
dir.cdUp ();
}
ui->tessdataEdit->setText (dir.path ());
}
void SettingsEditor::loadSettings()
{
QSettings settings;
settings.beginGroup (settings_names::guiGroup);
QString captureHotkey = settings.value (settings_names::captureHotkey,
settings_values::captureHotkey).toString ();
ui->captureEdit->setText (captureHotkey);
settings.endGroup ();
settings.beginGroup (settings_names::recogntionGroup);
QString tessDataPlace = settings.value (settings_names::tessDataPlace,
settings_values::tessDataPlace).toString ();
ui->tessdataEdit->setText (tessDataPlace);
QString ocrLang = settings.value (settings_names::ocrLanguage,
settings_values::ocrLanguage).toString ();
ui->ocrLangCombo->setCurrentText (ocrLang);
int imageScale = settings.value (settings_names::imageScale,
settings_values::imageScale).toInt ();
ui->imageScaleSpin->setValue (imageScale);
settings.endGroup ();
settings.beginGroup (settings_names::translationGroup);
QString translationLanguage = settings.value (settings_names::translationLanguage,
settings_values::translationLanguage).toString ();
ui->translateLangCombo->setCurrentText (translationLanguage);
settings.endGroup ();
}
void SettingsEditor::saveState() const
{
QSettings settings;
settings.beginGroup (settings_names::guiGroup);
settings.setValue (objectName () + "_" + settings_names::geometry, saveGeometry ());
}
void SettingsEditor::loadState()
{
QSettings settings;
settings.beginGroup (settings_names::guiGroup);
restoreGeometry (settings.value (objectName () + "_" + settings_names::geometry).toByteArray ());
}
void SettingsEditor::initOcrLangCombo()
{
ui->ocrLangCombo->clear ();
QString tessdataDir = ui->tessdataEdit->text ();
QDir dir (tessdataDir + "tessdata/");
if (!dir.exists ())
{
return;
}
QStringList files = dir.entryList (QStringList () << "*.traineddata", QDir::Files);
QStringList languages;
foreach (const QString& file, files)
{
QString lang = file.left (file.indexOf ("."));
languages << lang;
}
ui->ocrLangCombo->addItems (languages);
}
void SettingsEditor::initTranslateLangCombo()
{
QHash<QString, QString> gtLang;
gtLang.insert("Afrikaans","af");
gtLang.insert("Albanian","sq");
gtLang.insert("Arabic","ar");
gtLang.insert("Armenian","hy");
gtLang.insert("Azerbaijani","az");
gtLang.insert("Basque","eu");
gtLang.insert("Belarusian","be");
gtLang.insert("Bulgarian","bg");
gtLang.insert("Catalan","ca");
gtLang.insert("Chinese (Simplified)","zh-CN");
gtLang.insert("Chinese (Traditional)","zh-TW");
gtLang.insert("Croatian","hr");
gtLang.insert("Czech","cs");
gtLang.insert("Danish","da");
gtLang.insert("Dutch","nl");
gtLang.insert("English","en");
gtLang.insert("Estonian","et");
gtLang.insert("Filipino","tl");
gtLang.insert("Finnish","fi");
gtLang.insert("French","fr");
gtLang.insert("Galician","gl");
gtLang.insert("Georgian","ka");
gtLang.insert("German","de");
gtLang.insert("Greek","el");
gtLang.insert("Haitian Creole","ht");
gtLang.insert("Hebrew","iw");
gtLang.insert("Hindi","hi");
gtLang.insert("Hungarian","hu");
gtLang.insert("Icelandic","is");
gtLang.insert("Indonesian","id");
gtLang.insert("Irish","ga");
gtLang.insert("Italian","it");
gtLang.insert("Japanese","ja");
gtLang.insert("Korean","ko");
gtLang.insert("Latvian","lv");
gtLang.insert("Lithuanian","lt");
gtLang.insert("Macedonian","mk");
gtLang.insert("Malay","ms");
gtLang.insert("Maltese","mt");
gtLang.insert("Norwegian","no");
gtLang.insert("Persian","fa");
gtLang.insert("Polish","pl");
gtLang.insert("Portuguese","pt");
gtLang.insert("Romanian","ro");
gtLang.insert("Russian","ru");
gtLang.insert("Serbian","sr");
gtLang.insert("Slovak","sk");
gtLang.insert("Slovenian","sl");
gtLang.insert("Spanish","es");
gtLang.insert("Swahili","sw");
gtLang.insert("Swedish","sv");
gtLang.insert("Thai","th");
gtLang.insert("Turkish","tr");
gtLang.insert("Ukrainian","uk");
gtLang.insert("Urdu","ur");
gtLang.insert("Vietnamese","vi");
gtLang.insert("Welsh","cy");
gtLang.insert("Yiddish","yi");
ui->translateLangCombo->addItems (gtLang.values ());
}

View File

@ -15,6 +15,23 @@ class SettingsEditor : public QDialog
explicit SettingsEditor(QWidget *parent = 0); explicit SettingsEditor(QWidget *parent = 0);
~SettingsEditor(); ~SettingsEditor();
signals:
void settingsEdited ();
public slots:
void done (int result);
private slots:
void saveSettings () const;
void openTessdataDialog ();
void initOcrLangCombo ();
private:
void loadSettings ();
void saveState () const;
void loadState ();
void initTranslateLangCombo ();
private: private:
Ui::SettingsEditor *ui; Ui::SettingsEditor *ui;
}; };

View File

@ -6,22 +6,126 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>400</width> <width>456</width>
<height>300</height> <height>165</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Dialog</string> <string>Настройки</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Горячие клавиши</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Захват</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="captureEdit"/>
</item>
</layout>
</widget>
</item>
<item row="0" column="1" rowspan="2">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Распознавание</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Путь к tessdata</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="tessdataEdit"/>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="tessdataButton">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Язык распознавания</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Увеличение масштаба</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QComboBox" name="ocrLangCombo"/>
</item>
<item row="2" column="1" colspan="2">
<widget class="QSpinBox" name="imageScaleSpin"/>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Перевод</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Язык результата</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="translateLangCombo"/>
</item>
</layout>
</widget>
</item>
<item row="1" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>24</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>37</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0" colspan="3">
<widget class="QDialogButtonBox" name="buttonBox"> <widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>30</x>
<y>240</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
@ -29,65 +133,8 @@
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property> </property>
</widget> </widget>
<widget class="QLabel" name="label"> </item>
<property name="geometry"> </layout>
<rect>
<x>50</x>
<y>40</y>
<width>46</width>
<height>13</height>
</rect>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>40</x>
<y>80</y>
<width>46</width>
<height>13</height>
</rect>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>50</x>
<y>120</y>
<width>46</width>
<height>13</height>
</rect>
</property>
<property name="text">
<string>One time select</string>
</property>
</widget>
<widget class="QComboBox" name="comboBox">
<property name="geometry">
<rect>
<x>160</x>
<y>80</y>
<width>69</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QComboBox" name="comboBox_2">
<property name="geometry">
<rect>
<x>160</x>
<y>40</y>
<width>69</width>
<height>22</height>
</rect>
</property>
</widget>
</widget> </widget>
<resources/> <resources/>
<connections> <connections>

View File

@ -1,11 +1,89 @@
#include "Translator.h" #include "Translator.h"
Translator::Translator(QObject *parent) : #include <QDebug>
QObject(parent) #include <QNetworkRequest>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonParseError>
#include <QSettings>
#include "Settings.h"
namespace
{ {
const QString translateBaseUrl = "http://translate.google.com/translate_a/"
"t?client=t&text=%1&sl=auto&tl=%2";
}
Translator::Translator(QObject *parent) :
QObject(parent),
network_ (this)
{
connect (&network_, SIGNAL (finished (QNetworkReply*)),
SLOT (replyFinished (QNetworkReply*)));
applySettings ();
}
void Translator::applySettings()
{
QSettings settings;
settings.beginGroup (settings_names::translationGroup);
translationLanguage_ = settings.value (settings_names::translationLanguage,
settings_values::translationLanguage).
toString ();
} }
void Translator::translate(QString text) void Translator::translate(QString text)
{ {
Q_ASSERT (!text.isEmpty ());
if (translationLanguage_.isEmpty ())
{
emit error (tr ("Неверные парметры для перевода."));
return;
}
QUrl url (translateBaseUrl.arg (text, translationLanguage_));
network_.get (QNetworkRequest (url));
}
void Translator::replyFinished(QNetworkReply* reply)
{
Q_ASSERT (reply->isFinished ());
if (reply->error () != QNetworkReply::NoError)
{
emit error (tr ("Ошибка перевода: %1").arg (reply->errorString ()));
reply->deleteLater ();
return;
}
QByteArray data = reply->readAll ();
reply->deleteLater ();
while (data.indexOf (",,") != -1)//make json valid
{
data.replace (",,", ",");
}
QJsonParseError parseError;
QJsonDocument document = QJsonDocument::fromJson (data, &parseError);
if (document.isEmpty ())
{
emit error (tr ("Ошибка разбора перевода: %1 (%2)").
arg (parseError.errorString ()).arg (parseError.offset));
return;
}
QJsonArray answerArray = document.array ();
QJsonArray fullTranslation = answerArray.first ().toArray ();
QString source = "";
QString translation = "";
foreach (QJsonValue part, fullTranslation)
{
QJsonArray partTranslation = part.toArray ();
if (partTranslation.isEmpty ())
{
continue;
}
translation += partTranslation.at (0).toString ();
source += partTranslation.at (1).toString ();
}
emit translated (source, translation);
} }

View File

@ -1,7 +1,7 @@
#ifndef TRANSLATOR_H #ifndef TRANSLATOR_H
#define TRANSLATOR_H #define TRANSLATOR_H
#include <QObject> #include <QNetworkAccessManager>
class Translator : public QObject class Translator : public QObject
{ {
@ -11,9 +11,18 @@ class Translator : public QObject
signals: signals:
void translated (QString sourceText, QString translatedText); void translated (QString sourceText, QString translatedText);
void error (QString text);
public slots: public slots:
void translate (QString text); void translate (QString text);
void applySettings ();
private slots:
void replyFinished (QNetworkReply* reply);
private:
QNetworkAccessManager network_;
QString translationLanguage_;
}; };

View File

@ -1,11 +1,14 @@
#include <QApplication> #include <QApplication>
#include <Manager.h> #include <Manager.h>
#include <Settings.h>
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QApplication a(argc, argv); QApplication a(argc, argv);
// a.setQuitOnLastWindowClosed (false);//DEBUG a.setQuitOnLastWindowClosed (false);//DEBUG
a.setApplicationName (settings_values::appName);
a.setOrganizationName (settings_values::companyName);
Manager manager; Manager manager;