Color grabber zoom preview (#1869)

* Add ColorGrabWidget

The new widget aims to decouple color grabbing from the SidePanelWidget.

* Refactor SidePanelWidget to use ColorGrabWidget

- All color grabbing functionality is now moved to ColorGrabWidget
- SidePanelWidget now uses a more organized sigslot approach
- Removed QColorPickingEventFilter

* Fix bug and complete implementation

Timer not yet implemented.

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Add 0.5s timer

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix failing builds

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Add hex color editor

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Add right mouse button instant preview

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Make zoom widget toggle-able

* Implement OverlayMessage class

* Make Right click do the same as Space

* Unzoom widget when mouse leaves it

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix some small issues

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Toggle panel when grabbing color

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Show with timer even if magnifier active

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Reduce timer delay

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix OverlayMessage bug

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>
This commit is contained in:
Haris Gušić
2021-09-13 16:09:25 +02:00
committed by GitHub
parent 327e42d842
commit aca0db963b
10 changed files with 547 additions and 204 deletions

View File

@@ -2,57 +2,33 @@
// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
#include "sidepanelwidget.h"
#include "colorgrabwidget.h"
#include "src/core/qguiappcurrentscreen.h"
#include "src/utils/colorutils.h"
#include "src/utils/pathinfo.h"
#include "utilitypanel.h"
#include <QApplication>
#include <QDebug> // TODO remove
#include <QFormLayout>
#include <QKeyEvent>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QShortcut>
#include <QSlider>
#include <QVBoxLayout>
#if defined(Q_OS_MACOS)
#include <QScreen>
#endif
class QColorPickingEventFilter : public QObject
{
public:
explicit QColorPickingEventFilter(SidePanelWidget* pw,
QObject* parent = nullptr)
: QObject(parent)
, m_pw(pw)
{}
bool eventFilter(QObject*, QEvent* event) override
{
event->accept();
switch (event->type()) {
case QEvent::MouseMove:
return m_pw->handleMouseMove(static_cast<QMouseEvent*>(event));
case QEvent::MouseButtonPress:
return m_pw->handleMouseButtonPressed(
static_cast<QMouseEvent*>(event));
case QEvent::KeyPress:
return m_pw->handleKeyPress(static_cast<QKeyEvent*>(event));
default:
break;
}
return false;
}
private:
SidePanelWidget* m_pw;
};
////////////////////////
SidePanelWidget::SidePanelWidget(QPixmap* p, QWidget* parent)
: QWidget(parent)
, m_pixmap(p)
, m_eventFilter(nullptr)
{
m_layout = new QVBoxLayout(this);
if (parent) {
parent->installEventFilter(this);
}
QFormLayout* colorForm = new QFormLayout();
m_thicknessSlider = new QSlider(Qt::Horizontal);
@@ -64,6 +40,23 @@ SidePanelWidget::SidePanelWidget(QPixmap* p, QWidget* parent)
colorForm->addRow(tr("Active color:"), m_colorLabel);
m_layout->addLayout(colorForm);
m_colorWheel = new color_widgets::ColorWheel(this);
m_colorWheel->setColor(m_color);
m_colorHex = new QLineEdit(this);
m_colorHex->setAlignment(Qt::AlignCenter);
QColor background = this->palette().window().color();
bool isDark = ColorUtils::colorIsDark(background);
QString modifier =
isDark ? PathInfo::whiteIconPath() : PathInfo::blackIconPath();
QIcon grabIcon(modifier + "colorize.svg");
m_colorGrabButton = new QPushButton(grabIcon, tr("Grab Color"));
m_layout->addWidget(m_colorGrabButton);
m_layout->addWidget(m_colorWheel);
m_layout->addWidget(m_colorHex);
// thickness sigslots
connect(m_thicknessSlider,
&QSlider::sliderMoved,
this,
@@ -72,22 +65,20 @@ SidePanelWidget::SidePanelWidget(QPixmap* p, QWidget* parent)
&SidePanelWidget::thicknessChanged,
this,
&SidePanelWidget::updateThickness);
QColor background = this->palette().window().color();
bool isDark = ColorUtils::colorIsDark(background);
QString modifier =
isDark ? PathInfo::whiteIconPath() : PathInfo::blackIconPath();
QIcon grabIcon(modifier + "colorize.svg");
m_colorGrabButton = new QPushButton(grabIcon, QLatin1String(""));
updateGrabButton(false);
// color hex editor sigslots
connect(m_colorHex, &QLineEdit::editingFinished, this, [=]() {
if (!QColor::isValidColor(m_colorHex->text())) {
m_colorHex->setText(m_color.name(QColor::HexRgb));
} else {
updateColor(m_colorHex->text());
}
});
// color grab button sigslots
connect(m_colorGrabButton,
&QPushButton::pressed,
this,
&SidePanelWidget::colorGrabberActivated);
m_layout->addWidget(m_colorGrabButton);
m_colorWheel = new color_widgets::ColorWheel(this);
m_colorWheel->setColor(m_color);
&SidePanelWidget::startColorGrab);
// color wheel sigslots
connect(m_colorWheel,
&color_widgets::ColorWheel::mouseReleaseOnColor,
this,
@@ -96,15 +87,20 @@ SidePanelWidget::SidePanelWidget(QPixmap* p, QWidget* parent)
&color_widgets::ColorWheel::colorChanged,
this,
&SidePanelWidget::updateColorNoWheel);
m_layout->addWidget(m_colorWheel);
}
void SidePanelWidget::updateColor(const QColor& c)
{
m_color = c;
updateColorNoWheel(c);
m_colorWheel->setColor(c);
}
void SidePanelWidget::updateColorNoWheel(const QColor& c)
{
m_colorLabel->setStyleSheet(
QStringLiteral("QLabel { background-color : %1; }").arg(c.name()));
m_colorWheel->setColor(m_color);
m_colorHex->setText(c.name(QColor::HexRgb));
}
void SidePanelWidget::updateThickness(const int& t)
@@ -113,95 +109,70 @@ void SidePanelWidget::updateThickness(const int& t)
m_thicknessSlider->setValue(m_thickness);
}
void SidePanelWidget::updateColorNoWheel(const QColor& c)
void SidePanelWidget::startColorGrab()
{
m_color = c;
m_colorLabel->setStyleSheet(
QStringLiteral("QLabel { background-color : %1; }").arg(c.name()));
m_revertColor = m_color;
m_colorGrabber = new ColorGrabWidget(m_pixmap);
connect(m_colorGrabber,
&ColorGrabWidget::colorUpdated,
this,
&SidePanelWidget::onColorUpdated);
connect(m_colorGrabber,
&ColorGrabWidget::colorGrabbed,
this,
&SidePanelWidget::onColorGrabFinished);
connect(m_colorGrabber,
&ColorGrabWidget::grabAborted,
this,
&SidePanelWidget::onColorGrabAborted);
emit togglePanel();
m_colorGrabber->startGrabbing();
}
void SidePanelWidget::colorGrabberActivated()
void SidePanelWidget::onColorGrabFinished()
{
grabKeyboard();
grabMouse(Qt::CrossCursor);
setMouseTracking(true);
m_colorBackup = m_color;
if (!m_eventFilter) {
m_eventFilter = new QColorPickingEventFilter(this, this);
}
installEventFilter(m_eventFilter);
updateGrabButton(true);
}
void SidePanelWidget::releaseColorGrab()
{
setMouseTracking(false);
removeEventFilter(m_eventFilter);
releaseMouse();
releaseKeyboard();
setFocus();
updateGrabButton(false);
}
QColor SidePanelWidget::grabPixmapColor(const QPoint& p)
{
QColor c;
if (m_pixmap) {
#if defined(Q_OS_MACOS)
QScreen* currentScreen = QGuiAppCurrentScreen().currentScreen();
QPoint point = p;
if (currentScreen) {
point = QPoint((p.x() - currentScreen->geometry().x()) *
currentScreen->devicePixelRatio(),
(p.y() - currentScreen->geometry().y()) *
currentScreen->devicePixelRatio());
}
QPixmap pixel = m_pixmap->copy(QRect(point, point));
#else
QPixmap pixel = m_pixmap->copy(QRect(p, p));
#endif
c = pixel.toImage().pixel(0, 0);
}
return c;
}
bool SidePanelWidget::handleKeyPress(QKeyEvent* e)
{
if (e->key() == Qt::Key_Escape) {
releaseColorGrab();
updateColor(m_colorBackup);
} else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
updateColor(grabPixmapColor(QCursor::pos()));
releaseColorGrab();
emit colorChanged(m_color);
}
return true;
}
bool SidePanelWidget::handleMouseButtonPressed(QMouseEvent* e)
{
if (m_colorGrabButton->geometry().contains(e->pos()) ||
e->button() == Qt::RightButton) {
updateColorNoWheel(m_colorBackup);
} else if (e->button() == Qt::LeftButton) {
updateColor(grabPixmapColor(QCursor::pos()));
}
releaseColorGrab();
finalizeGrab();
m_color = m_colorGrabber->color();
emit colorChanged(m_color);
return true;
}
bool SidePanelWidget::handleMouseMove(QMouseEvent* e)
void SidePanelWidget::onColorGrabAborted()
{
updateColorNoWheel(grabPixmapColor(e->globalPos()));
return true;
finalizeGrab();
// Restore color that was selected before we started grabbing
updateColor(m_revertColor);
}
void SidePanelWidget::updateGrabButton(const bool activated)
void SidePanelWidget::onColorUpdated(const QColor& color)
{
if (activated) {
m_colorGrabButton->setText(tr("Press ESC to cancel"));
} else {
m_colorGrabButton->setText(tr("Grab Color"));
updateColorNoWheel(color);
}
void SidePanelWidget::finalizeGrab()
{
emit togglePanel();
}
bool SidePanelWidget::eventFilter(QObject* obj, QEvent* event)
{
if (event->type() == QEvent::ShortcutOverride) {
// Override Escape shortcut from CaptureWidget
auto* e = static_cast<QKeyEvent*>(event);
if (e->key() == Qt::Key_Escape && m_colorHex->hasFocus()) {
m_colorHex->clearFocus();
e->accept();
return true;
}
} else if (event->type() == QEvent::MouseButtonPress) {
// Clicks outside of the Color Hex editor
m_colorHex->clearFocus();
}
return QWidget::eventFilter(obj, event);
}
void SidePanelWidget::hideEvent(QHideEvent* event)
{
QWidget::hideEvent(event);
m_colorHex->clearFocus();
}