Add ability to edit results

This commit is contained in:
Gres 2020-03-29 11:09:55 +03:00
parent c9b2677bec
commit 1ff3fb1f1b
8 changed files with 249 additions and 41 deletions

View File

@ -42,6 +42,7 @@ HEADERS += \
src/ocr/recognizerworker.h \ src/ocr/recognizerworker.h \
src/ocr/tesseract.h \ src/ocr/tesseract.h \
src/represent/representer.h \ src/represent/representer.h \
src/represent/resulteditor.h \
src/represent/resultwidget.h \ src/represent/resultwidget.h \
src/service/apptranslator.h \ src/service/apptranslator.h \
src/service/debug.h \ src/service/debug.h \
@ -75,6 +76,7 @@ SOURCES += \
src/ocr/recognizerworker.cpp \ src/ocr/recognizerworker.cpp \
src/ocr/tesseract.cpp \ src/ocr/tesseract.cpp \
src/represent/representer.cpp \ src/represent/representer.cpp \
src/represent/resulteditor.cpp \
src/represent/resultwidget.cpp \ src/represent/resultwidget.cpp \
src/service/apptranslator.cpp \ src/service/apptranslator.cpp \
src/service/debug.cpp \ src/service/debug.cpp \

View File

@ -38,8 +38,8 @@ Manager::Manager()
recognizer_ = std::make_unique<Recognizer>(*this, *settings_); recognizer_ = std::make_unique<Recognizer>(*this, *settings_);
translator_ = std::make_unique<Translator>(*this, *settings_); translator_ = std::make_unique<Translator>(*this, *settings_);
corrector_ = std::make_unique<Corrector>(*this, *settings_); corrector_ = std::make_unique<Corrector>(*this, *settings_);
representer_ = std::make_unique<Representer>(*this, *tray_, *settings_); representer_ =
std::make_unique<Representer>(*this, *tray_, *settings_, *models_);
qRegisterMetaType<TaskPtr>(); qRegisterMetaType<TaskPtr>();
settings_->load(); settings_->load();

View File

@ -1,6 +1,8 @@
#include "representer.h" #include "representer.h"
#include "debug.h" #include "debug.h"
#include "geometryutils.h"
#include "manager.h" #include "manager.h"
#include "resulteditor.h"
#include "resultwidget.h" #include "resultwidget.h"
#include "settings.h" #include "settings.h"
#include "task.h" #include "task.h"
@ -8,15 +10,19 @@
#include <QApplication> #include <QApplication>
#include <QClipboard> #include <QClipboard>
#include <QScreen>
Representer::Representer(Manager &manager, TrayIcon &tray, Representer::Representer(Manager &manager, TrayIcon &tray,
const Settings &settings) const Settings &settings, const CommonModels &models)
: manager_(manager) : manager_(manager)
, tray_(tray) , tray_(tray)
, settings_(settings) , settings_(settings)
, models_(models)
{ {
} }
Representer::~Representer() = default;
void Representer::showLast() void Representer::showLast()
{ {
SOFT_ASSERT(widget_, return ); SOFT_ASSERT(widget_, return );
@ -27,18 +33,11 @@ void Representer::clipboardLast()
{ {
SOFT_ASSERT(widget_, return ); SOFT_ASSERT(widget_, return );
SOFT_ASSERT(widget_->task(), return ); SOFT_ASSERT(widget_->task(), return );
const auto task = widget_->task(); clipboardText(widget_->task());
QClipboard *clipboard = QApplication::clipboard();
auto text = task->recognized;
if (!task->translated.isEmpty())
text += QLatin1String(" - ") + task->translated;
clipboard->setText(text);
tray_.showInformation( tray_.showInformation(
QObject::tr("The last result was copied to the clipboard.")); QObject::tr("The last result was copied to the clipboard."));
} }
Representer::~Representer() = default;
void Representer::represent(const TaskPtr &task) void Representer::represent(const TaskPtr &task)
{ {
if (settings_.resultShowType == ResultMode::Tooltip) if (settings_.resultShowType == ResultMode::Tooltip)
@ -53,6 +52,41 @@ void Representer::updateSettings()
widget_->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<ResultEditor>(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) void Representer::showTooltip(const TaskPtr &task)
{ {
auto message = task->recognized + " - " + task->translated; auto message = task->recognized + " - " + task->translated;
@ -62,7 +96,7 @@ void Representer::showTooltip(const TaskPtr &task)
void Representer::showWidget(const TaskPtr &task) void Representer::showWidget(const TaskPtr &task)
{ {
if (!widget_) if (!widget_)
widget_ = std::make_unique<ResultWidget>(settings_); widget_ = std::make_unique<ResultWidget>(*this, settings_);
widget_->show(task); widget_->show(task);
} }

View File

@ -4,11 +4,13 @@
enum class ResultMode; enum class ResultMode;
class ResultWidget; class ResultWidget;
class ResultEditor;
class Representer class Representer
{ {
public: public:
Representer(Manager &manager, TrayIcon &tray, const Settings &settings); Representer(Manager &manager, TrayIcon &tray, const Settings &settings,
const CommonModels &models);
~Representer(); ~Representer();
void showLast(); void showLast();
@ -16,6 +18,10 @@ public:
void represent(const TaskPtr &task); void represent(const TaskPtr &task);
void updateSettings(); void updateSettings();
void clipboardText(const TaskPtr &task);
void clipboardImage(const TaskPtr &task);
void edit(const TaskPtr &task);
private: private:
void showTooltip(const TaskPtr &task); void showTooltip(const TaskPtr &task);
void showWidget(const TaskPtr &task); void showWidget(const TaskPtr &task);
@ -23,5 +29,7 @@ private:
Manager &manager_; Manager &manager_;
TrayIcon &tray_; TrayIcon &tray_;
const Settings &settings_; const Settings &settings_;
const CommonModels &models_;
std::unique_ptr<ResultWidget> widget_; std::unique_ptr<ResultWidget> widget_;
std::unique_ptr<ResultEditor> editor_;
}; };

View File

@ -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 <QComboBox>
#include <QGridLayout>
#include <QLabel>
#include <QPushButton>
#include <QTextEdit>
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();
}

View File

@ -0,0 +1,38 @@
#pragma once
#include "stfwd.h"
#include <QWidget>
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_;
};

View File

@ -1,5 +1,6 @@
#include "resultwidget.h" #include "resultwidget.h"
#include "debug.h" #include "debug.h"
#include "representer.h"
#include "settings.h" #include "settings.h"
#include "task.h" #include "task.h"
@ -7,14 +8,18 @@
#include <QBoxLayout> #include <QBoxLayout>
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QLabel> #include <QLabel>
#include <QMenu>
#include <QMouseEvent> #include <QMouseEvent>
ResultWidget::ResultWidget(const Settings &settings, QWidget *parent) ResultWidget::ResultWidget(Representer &representer, const Settings &settings,
QWidget *parent)
: QFrame(parent) : QFrame(parent)
, representer_(representer)
, settings_(settings) , settings_(settings)
, image_(new QLabel(this)) , image_(new QLabel(this))
, recognized_(new QLabel(this)) , recognized_(new QLabel(this))
, translated_(new QLabel(this)) , translated_(new QLabel(this))
, contextMenu_(new QMenu(this))
{ {
setWindowFlags(Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint | setWindowFlags(Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint |
Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint); Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
@ -33,6 +38,18 @@ ResultWidget::ResultWidget(const Settings &settings, QWidget *parent)
translated_->setAlignment(Qt::AlignCenter); translated_->setAlignment(Qt::AlignCenter);
translated_->setWordWrap(true); 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 = const auto styleSheet =
"#recognizeLabel, #translateLabel {" "#recognizeLabel, #translateLabel {"
"color: black;" "color: black;"
@ -120,36 +137,28 @@ bool ResultWidget::eventFilter(QObject *watched, QEvent *event)
{ {
if (event->type() == QEvent::MouseButtonPress) { if (event->type() == QEvent::MouseButtonPress) {
const auto button = static_cast<QMouseEvent *>(event)->button(); const auto button = static_cast<QMouseEvent *>(event)->button();
if (button == Qt::LeftButton) { if (button == Qt::RightButton) {
contextMenu_->exec(QCursor::pos());
} else {
hide(); hide();
} }
// else if (button == Qt::RightButton) {
// QAction *action = contextMenu_->exec(QCursor::pos());
// if (recognizeSubMenu_->findChildren<QAction *>().contains(action)) {
// ProcessingItem item = item_;
// task->translated = task->recognized = QString();
// task->ocrLanguage = dictionary_.ocrUiToCode(action->text());
// emit requestRecognize(item);
// } else if (translateSubMenu_->findChildren<QAction *>().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) { } else if (event->type() == QEvent::WindowDeactivate) {
hide(); hide();
} }
return QWidget::eventFilter(watched, event); return QWidget::eventFilter(watched, event);
} }
void ResultWidget::edit()
{
representer_.edit(task_);
}
void ResultWidget::copyText()
{
representer_.clipboardText(task_);
}
void ResultWidget::copyImage()
{
representer_.clipboardImage(task_);
}

View File

@ -5,12 +5,14 @@
#include <QFrame> #include <QFrame>
class QLabel; class QLabel;
class QMenu;
class ResultWidget : public QFrame class ResultWidget : public QFrame
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ResultWidget(const Settings& settings, QWidget* parent = nullptr); ResultWidget(Representer& representer, const Settings& settings,
QWidget* parent = nullptr);
const TaskPtr& task() const; const TaskPtr& task() const;
void show(const TaskPtr& task); void show(const TaskPtr& task);
@ -20,9 +22,15 @@ public:
bool eventFilter(QObject* watched, QEvent* event) override; bool eventFilter(QObject* watched, QEvent* event) override;
private: private:
void edit();
void copyImage();
void copyText();
Representer& representer_;
const Settings& settings_; const Settings& settings_;
TaskPtr task_; TaskPtr task_;
QLabel* image_; QLabel* image_;
QLabel* recognized_; QLabel* recognized_;
QLabel* translated_; QLabel* translated_;
QMenu* contextMenu_;
}; };