Add ability to edit selected rect

This commit is contained in:
Gres 2020-03-24 22:05:45 +03:00
parent cc815f4245
commit e1c2defd71
8 changed files with 220 additions and 15 deletions

View File

@ -31,6 +31,7 @@ INCLUDEPATH += src src/service src/capture src/ocr \
HEADERS += \
src/capture/capturearea.h \
src/capture/captureareaeditor.h \
src/capture/captureareaselector.h \
src/capture/capturer.h \
src/correct/corrector.h \
@ -60,6 +61,7 @@ HEADERS += \
SOURCES += \
src/capture/capturearea.cpp \
src/capture/captureareaeditor.cpp \
src/capture/captureareaselector.cpp \
src/capture/capturer.cpp \
src/correct/corrector.cpp \

View File

@ -13,7 +13,7 @@ CaptureArea::CaptureArea(const QRect &rect, const Settings &settings)
TaskPtr CaptureArea::task(const QPixmap &pixmap) const
{
if (pixmap.isNull() || rect_.width() < 3 || rect_.height() < 3)
if (pixmap.isNull() || !isValid())
return {};
auto task = std::make_shared<Task>();
@ -27,3 +27,18 @@ TaskPtr CaptureArea::task(const QPixmap &pixmap) const
return task;
}
bool CaptureArea::isValid() const
{
return !(rect_.width() < 3 || rect_.height() < 3);
}
const QRect &CaptureArea::rect() const
{
return rect_;
}
void CaptureArea::setRect(const QRect &rect)
{
rect_ = rect;
}

View File

@ -13,7 +13,13 @@ public:
CaptureArea(const QRect& rect, const Settings& settings);
TaskPtr task(const QPixmap& pixmap) const;
bool isValid() const;
const QRect& rect() const;
void setRect(const QRect& rect);
private:
friend class CaptureAreaEditor;
QRect rect_;
bool doTranslation_;
LanguageId sourceLanguage_;

View File

@ -0,0 +1,62 @@
#include "captureareaeditor.h"
#include "capturearea.h"
#include "captureareaselector.h"
#include "debug.h"
#include "languagecodes.h"
#include "settings.h"
#include "tesseract.h"
#include "translator.h"
#include <QCheckBox>
#include <QComboBox>
#include <QFormLayout>
#include <QStringListModel>
CaptureAreaEditor::CaptureAreaEditor(CaptureAreaSelector &selector)
: QWidget(&selector)
, selector_(selector)
, doTranslation_(new QCheckBox(tr("Translate"), this))
, sourceLanguage_(new QComboBox(this))
, targetLanguage_(new QComboBox(this))
, sourceLanguageModel_(std::make_unique<QStringListModel>())
, targetLanguageModel_(std::make_unique<QStringListModel>())
{
setCursor(Qt::CursorShape::ArrowCursor);
auto layout = new QFormLayout(this);
layout->addRow(doTranslation_);
layout->addRow(tr("Recognition language"), sourceLanguage_);
layout->addRow(tr("Translation language"), targetLanguage_);
sourceLanguage_->setModel(sourceLanguageModel_.get());
targetLanguage_->setModel(targetLanguageModel_.get());
targetLanguage_->setEnabled(doTranslation_->isChecked());
connect(doTranslation_, &QCheckBox::toggled, //
targetLanguage_, &QComboBox::setEnabled);
}
CaptureAreaEditor::~CaptureAreaEditor() = default;
void CaptureAreaEditor::updateSettings(const Settings &settings)
{
sourceLanguageModel_->setStringList(
Tesseract::availableLanguageNames(settings.tessdataPath));
targetLanguageModel_->setStringList(Translator::availableLanguageNames());
}
void CaptureAreaEditor::set(const CaptureArea &area)
{
doTranslation_->setChecked(area.doTranslation_);
sourceLanguage_->setCurrentText(LanguageCodes::name(area.sourceLanguage_));
targetLanguage_->setCurrentText(LanguageCodes::name(area.targetLanguage_));
}
void CaptureAreaEditor::apply(CaptureArea &area) const
{
area.doTranslation_ = doTranslation_->isChecked();
area.sourceLanguage_ =
LanguageCodes::idForName(sourceLanguage_->currentText());
area.targetLanguage_ =
LanguageCodes::idForName(targetLanguage_->currentText());
}

View File

@ -0,0 +1,29 @@
#pragma once
#include "stfwd.h"
#include <QWidget>
class QCheckBox;
class QComboBox;
class QStringListModel;
class CaptureAreaEditor : public QWidget
{
Q_OBJECT
public:
explicit CaptureAreaEditor(CaptureAreaSelector& selector);
~CaptureAreaEditor();
void set(const CaptureArea& area);
void apply(CaptureArea& area) const;
void updateSettings(const Settings& settings);
private:
CaptureAreaSelector& selector_;
QCheckBox* doTranslation_;
QComboBox* sourceLanguage_;
QComboBox* targetLanguage_;
std::unique_ptr<QStringListModel> sourceLanguageModel_;
std::unique_ptr<QStringListModel> targetLanguageModel_;
};

View File

@ -1,6 +1,8 @@
#include "captureareaselector.h"
#include "capturearea.h"
#include "captureareaeditor.h"
#include "capturer.h"
#include "debug.h"
#include "languagecodes.h"
#include "settings.h"
@ -13,6 +15,7 @@ CaptureAreaSelector::CaptureAreaSelector(Capturer &capturer,
: capturer_(capturer)
, settings_(settings)
, pixmap_(pixmap)
, editor_(std::make_unique<CaptureAreaEditor>(*this))
{
setWindowFlags(Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint |
Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
@ -21,6 +24,8 @@ CaptureAreaSelector::CaptureAreaSelector(Capturer &capturer,
setAttribute(Qt::WA_OpaquePaintEvent);
}
CaptureAreaSelector::~CaptureAreaSelector() = default;
void CaptureAreaSelector::activate()
{
setGeometry(pixmap_.rect());
@ -51,19 +56,15 @@ void CaptureAreaSelector::updateSettings()
const auto translationState = settings_.doTranslation ? tr("on") : tr("off");
help_ = tr(R"(Recognition language: %1
Translation language: %2 (%3))")
Translation language: %2 (%3)
Right click on selection - customize
Left click on selection - process)")
.arg(sourceName, targetName, translationState);
}
void CaptureAreaSelector::showEvent(QShowEvent * /*event*/)
{
startSelectPos_ = currentSelectPos_ = QPoint();
}
area_.reset();
void CaptureAreaSelector::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Escape)
capturer_.canceled();
SOFT_ASSERT(editor_, return );
editor_->updateSettings(settings_);
}
void CaptureAreaSelector::paintEvent(QPaintEvent * /*event*/)
@ -73,6 +74,15 @@ void CaptureAreaSelector::paintEvent(QPaintEvent * /*event*/)
for (const auto &rect : helpRects_) drawHelpRects(painter, rect);
if (area_)
drawCaptureArea(painter, *area_);
if (editor_->isVisible()) {
painter.setBrush(QBrush(QColor(200, 200, 200, 200)));
painter.setPen(Qt::NoPen);
painter.drawRect(editor_->geometry());
}
auto selection = QRect(startSelectPos_, currentSelectPos_).normalized();
if (!selection.isValid())
return;
@ -116,8 +126,54 @@ void CaptureAreaSelector::drawHelpRects(QPainter &painter,
painter.drawText(rect.current, Qt::AlignCenter, help_);
}
void CaptureAreaSelector::drawCaptureArea(QPainter &painter,
const CaptureArea &area) const
{
painter.setBrush(QBrush(QColor(200, 200, 200, 50)));
painter.setPen(Qt::NoPen);
painter.drawRect(area.rect());
painter.setBrush({});
painter.setPen(Qt::red);
painter.drawRect(area.rect());
}
void CaptureAreaSelector::showEvent(QShowEvent * /*event*/)
{
editor_->hide();
area_.reset();
startSelectPos_ = currentSelectPos_ = QPoint();
}
void CaptureAreaSelector::hideEvent(QHideEvent * /*event*/)
{
editor_->hide();
}
void CaptureAreaSelector::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Escape)
capturer_.canceled();
}
void CaptureAreaSelector::mousePressEvent(QMouseEvent *event)
{
SOFT_ASSERT(editor_, return );
if (editor_->isVisible()) {
if (editor_->geometry().contains(event->pos()))
return;
applyEditor();
}
if (area_ && area_->rect().contains(event->pos())) {
if (event->button() == Qt::LeftButton) {
capturer_.selected(*area_);
} else if (event->button() == Qt::RightButton) {
customize(*area_);
}
return;
}
if (startSelectPos_.isNull())
startSelectPos_ = event->pos();
}
@ -137,10 +193,8 @@ void CaptureAreaSelector::mouseMoveEvent(QMouseEvent *event)
void CaptureAreaSelector::mouseReleaseEvent(QMouseEvent *event)
{
if (startSelectPos_.isNull() || pixmap_.isNull()) {
capturer_.canceled();
if (startSelectPos_.isNull())
return;
}
const auto endPos = event->pos();
const auto selection = QRect(startSelectPos_, endPos).normalized();
@ -148,5 +202,33 @@ void CaptureAreaSelector::mouseReleaseEvent(QMouseEvent *event)
startSelectPos_ = currentSelectPos_ = {};
const auto area = CaptureArea(selection, settings_);
capturer_.selected(area);
if (!area.isValid()) {
capturer_.canceled();
return;
}
if (event->button() != Qt::RightButton) {
capturer_.selected(area);
} else {
area_ = std::make_unique<CaptureArea>(area);
customize(*area_);
}
}
void CaptureAreaSelector::customize(const CaptureArea &area)
{
SOFT_ASSERT(editor_, return );
editor_->set(area);
editor_->move(QCursor::pos());
editor_->show();
update();
}
void CaptureAreaSelector::applyEditor()
{
SOFT_ASSERT(editor_, return );
if (!editor_->isVisible() || !area_)
return;
editor_->apply(*area_);
editor_->hide();
}

View File

@ -11,6 +11,7 @@ class CaptureAreaSelector : public QWidget
public:
CaptureAreaSelector(Capturer &capturer, const Settings &settings,
const QPixmap &pixmap);
~CaptureAreaSelector();
void activate();
void setScreenRects(const std::vector<QRect> &screens);
@ -18,6 +19,7 @@ public:
protected:
void showEvent(QShowEvent *event) override;
void hideEvent(QHideEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
@ -33,6 +35,10 @@ private:
bool updateCurrentHelpRects();
void drawHelpRects(QPainter &painter, const HelpRect &rect) const;
void customize(const CaptureArea &area);
void applyEditor();
void drawCaptureArea(QPainter &painter, const CaptureArea &area) const;
Capturer &capturer_;
const Settings &settings_;
const QPixmap &pixmap_;
@ -40,4 +46,6 @@ private:
QPoint currentSelectPos_;
QString help_;
std::vector<HelpRect> helpRects_;
std::unique_ptr<CaptureArea> area_;
std::unique_ptr<CaptureAreaEditor> editor_;
};

View File

@ -17,6 +17,7 @@ class Corrector;
class Recognizer;
class CaptureArea;
class CaptureAreaSelector;
class CaptureAreaEditor;
namespace update
{