From 6e85bfd7eb3499a45697339e923e7576be3153e2 Mon Sep 17 00:00:00 2001 From: Gres Date: Fri, 4 Apr 2014 18:39:49 +0400 Subject: [PATCH] Allow select ocr language in SelectionDialog. Support this in Recognizer and Translator. --- Recognizer.cpp | 38 ++++++++------ Recognizer.h | 2 +- SelectionDialog.cpp | 124 ++++++++++++++++++++++++++++++++++---------- SelectionDialog.h | 7 ++- Translator.cpp | 6 ++- 5 files changed, 130 insertions(+), 47 deletions(-) diff --git a/Recognizer.cpp b/Recognizer.cpp index a4689bd..910a978 100644 --- a/Recognizer.cpp +++ b/Recognizer.cpp @@ -31,28 +31,28 @@ void Recognizer::applySettings() imageScale_ = settings.value (settings_names::imageScale, settings_values::imageScale).toInt (); - initEngine (); + initEngine (engine_); } -bool Recognizer::initEngine() +bool Recognizer::initEngine(tesseract::TessBaseAPI *&engine) { if (tessDataDir_.isEmpty () || ocrLanguage_.isEmpty ()) { emit error (tr ("Неверные параметры для OCR")); return false; } - if (engine_ != NULL) + if (engine != NULL) { - delete engine_; + delete engine; } - engine_ = new tesseract::TessBaseAPI(); - int result = engine_->Init(qPrintable (tessDataDir_), qPrintable (ocrLanguage_), + 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; + delete engine; + engine = NULL; return false; } return true; @@ -61,9 +61,12 @@ bool Recognizer::initEngine() void Recognizer::recognize(ProcessingItem item) { Q_ASSERT (!item.source.isNull ()); - if (engine_ == NULL) + bool isCustomLanguage = (!item.ocrLanguage.isEmpty () && + item.ocrLanguage != ocrLanguage_); + tesseract::TessBaseAPI* engine = (isCustomLanguage) ? NULL : engine_; + if (engine == NULL) { - if (!initEngine ()) + if (!initEngine (engine)) { return; } @@ -71,12 +74,18 @@ void Recognizer::recognize(ProcessingItem item) Pix* image = prepareImage (item.source.toImage (), imageScale_); Q_ASSERT (image != NULL); - engine_->SetImage (image); - char* outText = engine_->GetUTF8Text(); - QString result = QString (outText).trimmed (); - engine_->Clear(); + engine->SetImage (image); + char* outText = engine->GetUTF8Text(); + engine->Clear(); cleanupImage (&image); + QString result = QString (outText).trimmed (); + delete [] outText; + if (isCustomLanguage) + { + delete engine; + } + if (!result.isEmpty ()) { item.recognized = result; @@ -86,5 +95,4 @@ void Recognizer::recognize(ProcessingItem item) { emit error (tr ("Текст не распознан.")); } - delete [] outText; } diff --git a/Recognizer.h b/Recognizer.h index cd01617..f78ee13 100644 --- a/Recognizer.h +++ b/Recognizer.h @@ -26,7 +26,7 @@ class Recognizer : public QObject void applySettings (); private: - bool initEngine (); + bool initEngine (tesseract::TessBaseAPI*&engine); private: tesseract::TessBaseAPI* engine_; diff --git a/SelectionDialog.cpp b/SelectionDialog.cpp index 7d5b69d..2237f82 100644 --- a/SelectionDialog.cpp +++ b/SelectionDialog.cpp @@ -1,13 +1,16 @@ #include "SelectionDialog.h" #include "ui_SelectionDialog.h" +#include "LanguageHelper.h" #include #include #include +#include -SelectionDialog::SelectionDialog(QWidget *parent) : +SelectionDialog::SelectionDialog(const LanguageHelper &dictionary, QWidget *parent) : QDialog(parent), - ui(new Ui::SelectionDialog) + ui(new Ui::SelectionDialog), dictionary_ (dictionary), + languageMenu_ (new QMenu) { ui->setupUi(this); setWindowFlags (Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint | @@ -15,6 +18,8 @@ SelectionDialog::SelectionDialog(QWidget *parent) : ui->label->setAutoFillBackground(false); ui->label->installEventFilter (this); + + updateMenu (); } SelectionDialog::~SelectionDialog() @@ -22,6 +27,49 @@ SelectionDialog::~SelectionDialog() delete ui; } +void SelectionDialog::updateMenu() +{ + Q_CHECK_PTR (languageMenu_); + languageMenu_->clear (); + QStringList languages = dictionary_.availableOcrLanguagesUi (); + if (languages.isEmpty ()) + { + return; + } + + const int max = 10; + + if (languages.size () <= max) + { + foreach (const QString& language, languages) + { + languageMenu_->addAction (language); + } + } + else + { + int subIndex = max; + QMenu* subMenu = NULL; + QString prevLetter; + foreach (const QString& language, languages) + { + QString curLetter = language.left (1); + if (++subIndex >= max && prevLetter != curLetter) + { + if (subMenu != NULL) + { + subMenu->setTitle (subMenu->title () + " - " + prevLetter); + } + subMenu = languageMenu_->addMenu (curLetter); + subIndex = 0; + } + prevLetter = curLetter; + subMenu->addAction (language); + } + subMenu->setTitle (subMenu->title () + " - " + prevLetter); + } +} + bool SelectionDialog::eventFilter(QObject* object, QEvent* event) { if (object != ui->label) @@ -29,41 +77,24 @@ bool SelectionDialog::eventFilter(QObject* object, QEvent* event) return QDialog::eventFilter (object, event); } - if (event->type () == QEvent::MouseButtonPress) + if (event->type () == QEvent::Show) + { + startSelectPos_ = currentSelectPos_ = QPoint (); + } + else if (event->type () == QEvent::MouseButtonPress) { QMouseEvent* mouseEvent = static_cast (event); - if (mouseEvent->button () == Qt::LeftButton) + if ((mouseEvent->button () == Qt::LeftButton || + mouseEvent->button () == Qt::RightButton) && startSelectPos_.isNull ()) { startSelectPos_ = mouseEvent->pos (); } } - else if (event->type () == QEvent::MouseButtonRelease) - { - QMouseEvent* mouseEvent = static_cast (event); - if (mouseEvent->button () == Qt::LeftButton) - { - if (startSelectPos_.isNull () || currentPixmap_.isNull ()) - { - QDialog::eventFilter (object, event); - } - QPoint endPos = mouseEvent->pos (); - QRect selection = QRect (startSelectPos_, endPos).normalized (); - startSelectPos_ = currentSelectPos_ = QPoint (); - QPixmap selectedPixmap = currentPixmap_.copy (selection); - if (!selectedPixmap.isNull ()) - { - ProcessingItem item; - item.source = selectedPixmap; - item.screenPos = selection.topLeft (); - emit selected (item); - accept (); - } - } - } else if (event->type () == QEvent::MouseMove) { QMouseEvent* mouseEvent = static_cast (event); - if (mouseEvent->buttons () & Qt::LeftButton) + if ((mouseEvent->buttons () & Qt::LeftButton || + mouseEvent->buttons () & Qt::RightButton) && !startSelectPos_.isNull ()) { currentSelectPos_ = mouseEvent->pos (); ui->label->repaint (); @@ -79,7 +110,44 @@ bool SelectionDialog::eventFilter(QObject* object, QEvent* event) painter.drawRect (selection); } } + else if (event->type () == QEvent::MouseButtonRelease) + { + QMouseEvent* mouseEvent = static_cast (event); + if (mouseEvent->button () == Qt::LeftButton || + mouseEvent->button () == Qt::RightButton) + { + if (startSelectPos_.isNull () || currentPixmap_.isNull ()) + { + return QDialog::eventFilter (object, event); + } + QPoint endPos = mouseEvent->pos (); + QRect selection = QRect (startSelectPos_, endPos).normalized (); + QPixmap selectedPixmap = currentPixmap_.copy (selection); + if (!selectedPixmap.isNull ()) + { + ProcessingItem item; + item.source = selectedPixmap; + item.screenPos = selection.topLeft (); + if (mouseEvent->button () == Qt::RightButton && + !languageMenu_->children ().isEmpty ()) + { + QAction* action = languageMenu_->exec (QCursor::pos ()); + if (action == NULL) + { + reject (); + return QDialog::eventFilter (object, event); + } + item.ocrLanguage = dictionary_.ocrUiToCode (action->text ()); + Q_ASSERT (!item.ocrLanguage.isEmpty ()); + item.sourceLanguage = dictionary_.translateForOcrCode (item.ocrLanguage); + Q_ASSERT (!item.sourceLanguage.isEmpty ()); + } + emit selected (item); + accept (); + } + } + } return QDialog::eventFilter (object, event); } diff --git a/SelectionDialog.h b/SelectionDialog.h index c0e2e59..18fa890 100644 --- a/SelectionDialog.h +++ b/SelectionDialog.h @@ -3,19 +3,21 @@ #include #include +#include #include "ProcessingItem.h" namespace Ui { class SelectionDialog; } +class LanguageHelper; class SelectionDialog : public QDialog { Q_OBJECT public: - explicit SelectionDialog(QWidget *parent = 0); + explicit SelectionDialog(const LanguageHelper& dictionary, QWidget *parent = 0); ~SelectionDialog(); bool eventFilter (QObject *object, QEvent *event); @@ -25,12 +27,15 @@ class SelectionDialog : public QDialog public slots: void setPixmap (QPixmap pixmap); + void updateMenu (); private: Ui::SelectionDialog *ui; + const LanguageHelper& dictionary_; QPoint startSelectPos_; QPoint currentSelectPos_; QPixmap currentPixmap_; + QMenu* languageMenu_; }; #endif // SELECTIONDIALOG_H diff --git a/Translator.cpp b/Translator.cpp index ac69e35..1c971fe 100644 --- a/Translator.cpp +++ b/Translator.cpp @@ -39,12 +39,14 @@ void Translator::applySettings() void Translator::translate(ProcessingItem item) { Q_ASSERT (!item.recognized.isEmpty ()); - if (translationLanguage_.isEmpty ()) + QString sourceLanguage = item.sourceLanguage.isEmpty () ? sourceLanguage_ : + item.sourceLanguage; + if (translationLanguage_.isEmpty () || sourceLanguage.isEmpty ()) { emit error (tr ("Неверные парметры для перевода.")); return; } - QUrl url (translateBaseUrl.arg (item.recognized, sourceLanguage_, translationLanguage_)); + QUrl url (translateBaseUrl.arg (item.recognized, sourceLanguage, translationLanguage_)); QNetworkReply* reply = network_.get (QNetworkRequest (url)); items_.insert (reply, item); }