From 1ff3fb1f1bc83475d35517c7160b32eb29a9bac0 Mon Sep 17 00:00:00 2001 From: Gres Date: Sun, 29 Mar 2020 11:09:55 +0300 Subject: [PATCH] Add ability to edit results --- screen-translator.pro | 2 + src/manager.cpp | 4 +- src/represent/representer.cpp | 54 +++++++++++++--- src/represent/representer.h | 10 ++- src/represent/resulteditor.cpp | 109 +++++++++++++++++++++++++++++++++ src/represent/resulteditor.h | 38 ++++++++++++ src/represent/resultwidget.cpp | 63 +++++++++++-------- src/represent/resultwidget.h | 10 ++- 8 files changed, 249 insertions(+), 41 deletions(-) create mode 100644 src/represent/resulteditor.cpp create mode 100644 src/represent/resulteditor.h diff --git a/screen-translator.pro b/screen-translator.pro index 0b8efd6..f1fbaec 100644 --- a/screen-translator.pro +++ b/screen-translator.pro @@ -42,6 +42,7 @@ HEADERS += \ src/ocr/recognizerworker.h \ src/ocr/tesseract.h \ src/represent/representer.h \ + src/represent/resulteditor.h \ src/represent/resultwidget.h \ src/service/apptranslator.h \ src/service/debug.h \ @@ -75,6 +76,7 @@ SOURCES += \ src/ocr/recognizerworker.cpp \ src/ocr/tesseract.cpp \ src/represent/representer.cpp \ + src/represent/resulteditor.cpp \ src/represent/resultwidget.cpp \ src/service/apptranslator.cpp \ src/service/debug.cpp \ diff --git a/src/manager.cpp b/src/manager.cpp index 1463825..c74d185 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -38,8 +38,8 @@ Manager::Manager() recognizer_ = std::make_unique(*this, *settings_); translator_ = std::make_unique(*this, *settings_); corrector_ = std::make_unique(*this, *settings_); - representer_ = std::make_unique(*this, *tray_, *settings_); - + representer_ = + std::make_unique(*this, *tray_, *settings_, *models_); qRegisterMetaType(); settings_->load(); diff --git a/src/represent/representer.cpp b/src/represent/representer.cpp index 2edd782..c7c1f0d 100644 --- a/src/represent/representer.cpp +++ b/src/represent/representer.cpp @@ -1,6 +1,8 @@ #include "representer.h" #include "debug.h" +#include "geometryutils.h" #include "manager.h" +#include "resulteditor.h" #include "resultwidget.h" #include "settings.h" #include "task.h" @@ -8,15 +10,19 @@ #include #include +#include Representer::Representer(Manager &manager, TrayIcon &tray, - const Settings &settings) + const Settings &settings, const CommonModels &models) : manager_(manager) , tray_(tray) , settings_(settings) + , models_(models) { } +Representer::~Representer() = default; + void Representer::showLast() { SOFT_ASSERT(widget_, return ); @@ -27,18 +33,11 @@ void Representer::clipboardLast() { SOFT_ASSERT(widget_, return ); SOFT_ASSERT(widget_->task(), return ); - const auto task = widget_->task(); - QClipboard *clipboard = QApplication::clipboard(); - auto text = task->recognized; - if (!task->translated.isEmpty()) - text += QLatin1String(" - ") + task->translated; - clipboard->setText(text); + clipboardText(widget_->task()); tray_.showInformation( QObject::tr("The last result was copied to the clipboard.")); } -Representer::~Representer() = default; - void Representer::represent(const TaskPtr &task) { if (settings_.resultShowType == ResultMode::Tooltip) @@ -53,6 +52,41 @@ void Representer::updateSettings() widget_->updateSettings(); } +void Representer::clipboardText(const TaskPtr &task) +{ + if (!task) + return; + + QClipboard *clipboard = QApplication::clipboard(); + auto text = task->recognized; + if (!task->translated.isEmpty()) + text += QLatin1String(" - ") + task->translated; + clipboard->setText(text); +} + +void Representer::clipboardImage(const TaskPtr &task) +{ + if (!task) + return; + + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setPixmap(task->captured); +} + +void Representer::edit(const TaskPtr &task) +{ + if (!editor_) + editor_ = std::make_unique(manager_, models_, settings_); + + editor_->show(task); + + const auto cursor = QCursor::pos(); + const auto screen = QApplication::screenAt(cursor); + SOFT_ASSERT(screen, return ); + editor_->move(service::geometry::cornerAtPoint(cursor, editor_->size(), + screen->geometry())); +} + void Representer::showTooltip(const TaskPtr &task) { auto message = task->recognized + " - " + task->translated; @@ -62,7 +96,7 @@ void Representer::showTooltip(const TaskPtr &task) void Representer::showWidget(const TaskPtr &task) { if (!widget_) - widget_ = std::make_unique(settings_); + widget_ = std::make_unique(*this, settings_); widget_->show(task); } diff --git a/src/represent/representer.h b/src/represent/representer.h index 094528e..f900af1 100644 --- a/src/represent/representer.h +++ b/src/represent/representer.h @@ -4,11 +4,13 @@ enum class ResultMode; class ResultWidget; +class ResultEditor; class Representer { public: - Representer(Manager &manager, TrayIcon &tray, const Settings &settings); + Representer(Manager &manager, TrayIcon &tray, const Settings &settings, + const CommonModels &models); ~Representer(); void showLast(); @@ -16,6 +18,10 @@ public: void represent(const TaskPtr &task); void updateSettings(); + void clipboardText(const TaskPtr &task); + void clipboardImage(const TaskPtr &task); + void edit(const TaskPtr &task); + private: void showTooltip(const TaskPtr &task); void showWidget(const TaskPtr &task); @@ -23,5 +29,7 @@ private: Manager &manager_; TrayIcon &tray_; const Settings &settings_; + const CommonModels &models_; std::unique_ptr widget_; + std::unique_ptr editor_; }; diff --git a/src/represent/resulteditor.cpp b/src/represent/resulteditor.cpp new file mode 100644 index 0000000..2d2fef1 --- /dev/null +++ b/src/represent/resulteditor.cpp @@ -0,0 +1,109 @@ +#include "resulteditor.h" +#include "commonmodels.h" +#include "debug.h" +#include "languagecodes.h" +#include "manager.h" +#include "settings.h" +#include "task.h" + +#include +#include +#include +#include +#include + +ResultEditor::ResultEditor(Manager &manager, const CommonModels &models, + const Settings &settings, QWidget *parent) + : QWidget(parent) + , manager_(manager) + , settings_(settings) + , image_(new QLabel(this)) + , recognizedEdit_(new QTextEdit(this)) + , sourceLanguage_(new QComboBox(this)) + , targetLanguage_(new QComboBox(this)) + , recognizeOnly_(new QPushButton(tr("Recognize"), this)) + , recognizeAndTranslate_(new QPushButton(tr("Recognize and translate"), this)) + , translateOnly_(new QPushButton(tr("Translate"), this)) +{ + image_->setAlignment(Qt::AlignCenter); + + sourceLanguage_->setModel(models.sourceLanguageModel()); + targetLanguage_->setModel(models.targetLanguageModel()); + + connect(recognizeOnly_, &QPushButton::clicked, // + this, &ResultEditor::recognize); + connect(recognizeAndTranslate_, &QPushButton::clicked, // + this, &ResultEditor::recognizeAndTranslate); + connect(translateOnly_, &QPushButton::clicked, // + this, &ResultEditor::translate); + + auto layout = new QGridLayout(this); + auto row = 0; + layout->addWidget(image_, row, 0, 1, 2); + + ++row; + layout->addWidget(new QLabel(tr("Recognize:")), row, 0); + layout->addWidget(sourceLanguage_, row, 1); + + ++row; + layout->addWidget(new QLabel(tr("Translate:")), row, 0); + layout->addWidget(targetLanguage_, row, 1); + + ++row; + layout->addWidget(recognizedEdit_, row, 0, 1, 2); + + ++row; + auto box = new QHBoxLayout; + layout->addLayout(box, row, 0, 1, 2); + box->addWidget(recognizeOnly_); + box->addWidget(recognizeAndTranslate_); + box->addWidget(translateOnly_); +} + +void ResultEditor::show(const TaskPtr &task) +{ + SOFT_ASSERT(task, return ); + task_ = task; + + image_->setPixmap(task->captured); + recognizedEdit_->setText(task->recognized); + + const auto target = task->targetLanguage.isEmpty() ? settings_.targetLanguage + : task->targetLanguage; + targetLanguage_->setCurrentText(LanguageCodes::name(target)); + sourceLanguage_->setCurrentText(LanguageCodes::name(task->sourceLanguage)); + + QWidget::show(); +} + +void ResultEditor::recognize() +{ + task_->sourceLanguage = + LanguageCodes::idForName(sourceLanguage_->currentText()); + task_->targetLanguage.clear(); + manager_.captured(task_); + close(); + task_.reset(); +} + +void ResultEditor::recognizeAndTranslate() +{ + task_->sourceLanguage = + LanguageCodes::idForName(sourceLanguage_->currentText()); + task_->targetLanguage = + LanguageCodes::idForName(targetLanguage_->currentText()); + task_->translators = settings_.translators; + manager_.captured(task_); + close(); + task_.reset(); +} + +void ResultEditor::translate() +{ + task_->targetLanguage = + LanguageCodes::idForName(targetLanguage_->currentText()); + task_->translators = settings_.translators; + manager_.corrected(task_); + close(); + task_.reset(); +} diff --git a/src/represent/resulteditor.h b/src/represent/resulteditor.h new file mode 100644 index 0000000..86a0b67 --- /dev/null +++ b/src/represent/resulteditor.h @@ -0,0 +1,38 @@ +#pragma once + +#include "stfwd.h" + +#include + +class QLabel; +class QMenu; +class QTextEdit; +class QComboBox; +class QPushButton; + +class ResultEditor : public QWidget +{ + Q_OBJECT +public: + ResultEditor(Manager& manager, const CommonModels& models, + const Settings& settings, QWidget* parent = nullptr); + + void show(const TaskPtr& task); + using QWidget::show; + +private: + void recognize(); + void recognizeAndTranslate(); + void translate(); + + Manager& manager_; + const Settings& settings_; + TaskPtr task_; + QLabel* image_; + QTextEdit* recognizedEdit_; + QComboBox* sourceLanguage_; + QComboBox* targetLanguage_; + QPushButton* recognizeOnly_; + QPushButton* recognizeAndTranslate_; + QPushButton* translateOnly_; +}; diff --git a/src/represent/resultwidget.cpp b/src/represent/resultwidget.cpp index 51eade0..b2e82ac 100644 --- a/src/represent/resultwidget.cpp +++ b/src/represent/resultwidget.cpp @@ -1,5 +1,6 @@ #include "resultwidget.h" #include "debug.h" +#include "representer.h" #include "settings.h" #include "task.h" @@ -7,14 +8,18 @@ #include #include #include +#include #include -ResultWidget::ResultWidget(const Settings &settings, QWidget *parent) +ResultWidget::ResultWidget(Representer &representer, const Settings &settings, + QWidget *parent) : QFrame(parent) + , representer_(representer) , settings_(settings) , image_(new QLabel(this)) , recognized_(new QLabel(this)) , translated_(new QLabel(this)) + , contextMenu_(new QMenu(this)) { setWindowFlags(Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint); @@ -33,6 +38,18 @@ ResultWidget::ResultWidget(const Settings &settings, QWidget *parent) translated_->setAlignment(Qt::AlignCenter); translated_->setWordWrap(true); + { + auto clipboardText = contextMenu_->addAction(tr("Copy text")); + connect(clipboardText, &QAction::triggered, // + this, &ResultWidget::copyText); + auto clipboardImage = contextMenu_->addAction(tr("Copy image")); + connect(clipboardImage, &QAction::triggered, // + this, &ResultWidget::copyImage); + auto edit = contextMenu_->addAction(tr("Edit...")); + connect(edit, &QAction::triggered, // + this, &ResultWidget::edit); + } + const auto styleSheet = "#recognizeLabel, #translateLabel {" "color: black;" @@ -120,36 +137,28 @@ bool ResultWidget::eventFilter(QObject *watched, QEvent *event) { if (event->type() == QEvent::MouseButtonPress) { const auto button = static_cast(event)->button(); - if (button == Qt::LeftButton) { + if (button == Qt::RightButton) { + contextMenu_->exec(QCursor::pos()); + } else { hide(); } - // else if (button == Qt::RightButton) { - // QAction *action = contextMenu_->exec(QCursor::pos()); - // if (recognizeSubMenu_->findChildren().contains(action)) { - // ProcessingItem item = item_; - // task->translated = task->recognized = QString(); - // task->ocrLanguage = dictionary_.ocrUiToCode(action->text()); - // emit requestRecognize(item); - // } else if (translateSubMenu_->findChildren().contains( - // action)) { - // ProcessingItem item = item_; - // task->translated.clear(); - // task->translateLanguage = - // dictionary_.translateUiToCode(action->text()); emit - // requestTranslate(item); - // } else if (action == clipboardAction_) { - // emit requestClipboard(); - // } else if (action == imageClipboardAction_) { - // emit requestImageClipboard(); - // } else if (action == correctAction_) { - // emit requestEdition(item_); - // // Return because Manager calls showResult() before hide() - // otherwise.return QWidget::eventFilter(watched, event); - // } - // } - // hide(); } else if (event->type() == QEvent::WindowDeactivate) { hide(); } return QWidget::eventFilter(watched, event); } + +void ResultWidget::edit() +{ + representer_.edit(task_); +} + +void ResultWidget::copyText() +{ + representer_.clipboardText(task_); +} + +void ResultWidget::copyImage() +{ + representer_.clipboardImage(task_); +} diff --git a/src/represent/resultwidget.h b/src/represent/resultwidget.h index d31ea81..f4212e8 100644 --- a/src/represent/resultwidget.h +++ b/src/represent/resultwidget.h @@ -5,12 +5,14 @@ #include class QLabel; +class QMenu; class ResultWidget : public QFrame { Q_OBJECT public: - explicit ResultWidget(const Settings& settings, QWidget* parent = nullptr); + ResultWidget(Representer& representer, const Settings& settings, + QWidget* parent = nullptr); const TaskPtr& task() const; void show(const TaskPtr& task); @@ -20,9 +22,15 @@ public: bool eventFilter(QObject* watched, QEvent* event) override; private: + void edit(); + void copyImage(); + void copyText(); + + Representer& representer_; const Settings& settings_; TaskPtr task_; QLabel* image_; QLabel* recognized_; QLabel* translated_; + QMenu* contextMenu_; };