From e1c2defd71287486444022fcf814667c9820f666 Mon Sep 17 00:00:00 2001 From: Gres Date: Tue, 24 Mar 2020 22:05:45 +0300 Subject: [PATCH] Add ability to edit selected rect --- screen-translator.pro | 2 + src/capture/capturearea.cpp | 17 ++++- src/capture/capturearea.h | 6 ++ src/capture/captureareaeditor.cpp | 62 ++++++++++++++++ src/capture/captureareaeditor.h | 29 ++++++++ src/capture/captureareaselector.cpp | 110 ++++++++++++++++++++++++---- src/capture/captureareaselector.h | 8 ++ src/stfwd.h | 1 + 8 files changed, 220 insertions(+), 15 deletions(-) create mode 100644 src/capture/captureareaeditor.cpp create mode 100644 src/capture/captureareaeditor.h diff --git a/screen-translator.pro b/screen-translator.pro index c8eca0b..0a45dac 100644 --- a/screen-translator.pro +++ b/screen-translator.pro @@ -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 \ diff --git a/src/capture/capturearea.cpp b/src/capture/capturearea.cpp index 4e3deef..3580ebf 100644 --- a/src/capture/capturearea.cpp +++ b/src/capture/capturearea.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(); @@ -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; +} diff --git a/src/capture/capturearea.h b/src/capture/capturearea.h index 6137fb7..4294cef 100644 --- a/src/capture/capturearea.h +++ b/src/capture/capturearea.h @@ -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_; diff --git a/src/capture/captureareaeditor.cpp b/src/capture/captureareaeditor.cpp new file mode 100644 index 0000000..7da40b6 --- /dev/null +++ b/src/capture/captureareaeditor.cpp @@ -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 +#include +#include +#include + +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()) + , targetLanguageModel_(std::make_unique()) +{ + 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()); +} diff --git a/src/capture/captureareaeditor.h b/src/capture/captureareaeditor.h new file mode 100644 index 0000000..0c7423c --- /dev/null +++ b/src/capture/captureareaeditor.h @@ -0,0 +1,29 @@ +#pragma once + +#include "stfwd.h" + +#include + +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 sourceLanguageModel_; + std::unique_ptr targetLanguageModel_; +}; diff --git a/src/capture/captureareaselector.cpp b/src/capture/captureareaselector.cpp index 2daef86..ad60161 100644 --- a/src/capture/captureareaselector.cpp +++ b/src/capture/captureareaselector.cpp @@ -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(*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(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(); } diff --git a/src/capture/captureareaselector.h b/src/capture/captureareaselector.h index 188288c..89e014a 100644 --- a/src/capture/captureareaselector.h +++ b/src/capture/captureareaselector.h @@ -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 &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 helpRects_; + std::unique_ptr area_; + std::unique_ptr editor_; }; diff --git a/src/stfwd.h b/src/stfwd.h index 07a203d..6fdc23e 100644 --- a/src/stfwd.h +++ b/src/stfwd.h @@ -17,6 +17,7 @@ class Corrector; class Recognizer; class CaptureArea; class CaptureAreaSelector; +class CaptureAreaEditor; namespace update {