Add ability to edit selected rect
This commit is contained in:
parent
cc815f4245
commit
e1c2defd71
@ -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 \
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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_;
|
||||
|
62
src/capture/captureareaeditor.cpp
Normal file
62
src/capture/captureareaeditor.cpp
Normal 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());
|
||||
}
|
29
src/capture/captureareaeditor.h
Normal file
29
src/capture/captureareaeditor.h
Normal 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_;
|
||||
};
|
@ -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();
|
||||
}
|
||||
|
@ -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_;
|
||||
};
|
||||
|
@ -17,6 +17,7 @@ class Corrector;
|
||||
class Recognizer;
|
||||
class CaptureArea;
|
||||
class CaptureAreaSelector;
|
||||
class CaptureAreaEditor;
|
||||
|
||||
namespace update
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user