QmlDesigner: EyeDropper use platform service

Task-number: QDS-12517
Change-Id: I1fdbdf3aa0992826d109d0e24e92d15c7576fb93
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Henning Gruendl
2024-09-03 16:46:37 +02:00
committed by Tim Jenssen
parent 04155ac5a1
commit 989eae1667
7 changed files with 254 additions and 183 deletions

View File

@@ -39,7 +39,7 @@ SecondColumnLayout {
property bool shapeGradients: false property bool shapeGradients: false
//for now, gradients on MCUs are limited to Basic and Shape Linear Gradient: // Gradients on MCUs are limited to Basic and Shape Linear Gradient.
property bool mcuGradients: false property bool mcuGradients: false
property color originalColor property color originalColor
@@ -91,9 +91,9 @@ SecondColumnLayout {
if (colorEditor.backendValue !== undefined) { if (colorEditor.backendValue !== undefined) {
if (colorEditor.isVector3D) if (colorEditor.isVector3D)
colorEditor.backendValue.value = Qt.vector3d( colorEditor.backendValue.value = Qt.vector3d(colorEditor.color.r,
colorEditor.color.r, colorEditor.color.g, colorEditor.color.g,
colorEditor.color.b) colorEditor.color.b)
else else
colorEditor.backendValue.value = colorEditor.color colorEditor.backendValue.value = colorEditor.color
} }
@@ -223,10 +223,8 @@ SecondColumnLayout {
function open() { function open() {
popupDialog.ensureLoader() popupDialog.ensureLoader()
popupDialog.show(preview) popupDialog.show(preview)
popupDialog.loaderItem.aboutToBeShown() // need it for now
popupDialog.loaderItem.aboutToBeShown() //need it for now
} }
function determineActiveColorMode() { function determineActiveColorMode() {

View File

@@ -12,10 +12,9 @@ import QtQuickDesignerColorPalette
Column { Column {
id: root id: root
// There seems to be an issue on Windows and MacOS with ColorPickers // There seems to be an issue on Windows and macOS with ColorPickers canvas not being painted
// Canvases not being painted on initialization // on initialization, because ColorEditorPopup is invisible at init time, so we use this signal
// because ColorEditorPopup is invisible at init time, // to explicitly pass visibility status.
// so we use this signal to explicitly pass visibility status
signal aboutToBeShown signal aboutToBeShown
property bool eyeDropperActive: ColorPaletteBackend.eyeDropperActive property bool eyeDropperActive: ColorPaletteBackend.eyeDropperActive
@@ -23,7 +22,7 @@ Column {
property bool supportGradient: false property bool supportGradient: false
property bool shapeGradients: false property bool shapeGradients: false
//for now, gradients on MCUs are limited to Basic and Shape Linear Gradient: // Gradients on MCUs are limited to Basic and Shape Linear Gradient.
property bool mcuGradients: false property bool mcuGradients: false
property alias gradientLine: gradientLine property alias gradientLine: gradientLine
@@ -188,7 +187,7 @@ Column {
icon: StudioTheme.Constants.eyeDropper icon: StudioTheme.Constants.eyeDropper
pixelSize: StudioTheme.Values.myIconFontSize * 1.4 pixelSize: StudioTheme.Values.myIconFontSize * 1.4
tooltip: qsTr("Eye Dropper") tooltip: qsTr("Eye Dropper")
onClicked: ColorPaletteBackend.eyeDropper() onClicked: ColorPaletteBackend.invokeEyeDropper()
} }
} }

View File

@@ -69,6 +69,8 @@ Item {
property QtObject loaderItem: loader.item property QtObject loaderItem: loader.item
keepOpen: loader.item?.eyeDropperActive ?? false
width: 260 width: 260
function ensureLoader() { function ensureLoader() {
@@ -91,6 +93,7 @@ Item {
id: popup id: popup
width: popupDialog.contentWidth width: popupDialog.contentWidth
visible: popupDialog.visible visible: popupDialog.visible
parentWindow: popupDialog.window
onActivateColor: function(color) { onActivateColor: function(color) {
colorBackend.activateColor(color) colorBackend.activateColor(color)

View File

@@ -12,9 +12,13 @@ import QtQuickDesignerColorPalette
Column { Column {
id: root id: root
property bool eyeDropperActive: ColorPaletteBackend.eyeDropperActive
property color color property color color
property color originalColor property color originalColor
property Window parentWindow: null
readonly property real twoColumnWidth: (colorColumn.width - StudioTheme.Values.controlGap) * 0.5 readonly property real twoColumnWidth: (colorColumn.width - StudioTheme.Values.controlGap) * 0.5
readonly property real fourColumnWidth: (colorColumn.width - (3 * StudioTheme.Values.controlGap)) * 0.25 readonly property real fourColumnWidth: (colorColumn.width - (3 * StudioTheme.Values.controlGap)) * 0.25
@@ -42,7 +46,7 @@ Column {
icon: StudioTheme.Constants.eyeDropper icon: StudioTheme.Constants.eyeDropper
pixelSize: StudioTheme.Values.myIconFontSize * 1.4 pixelSize: StudioTheme.Values.myIconFontSize * 1.4
toolTip: qsTr("Eye Dropper") toolTip: qsTr("Eye Dropper")
onClicked: ColorPaletteBackend.eyeDropper() onClicked: ColorPaletteBackend.invokeEyeDropper()
} }
} }

View File

@@ -53,7 +53,7 @@ add_qtc_plugin(QmlDesigner
PLUGIN_MANUAL_DEPENDS LicenseChecker ${IDE_VERSION} optional PLUGIN_MANUAL_DEPENDS LicenseChecker ${IDE_VERSION} optional
DEPENDS DEPENDS
QmlJS LanguageUtils QmlEditorWidgets AdvancedDockingSystem QmlJS LanguageUtils QmlEditorWidgets AdvancedDockingSystem
Qt::QuickWidgets Qt::CorePrivate Qt::Xml Qt::Svg Sqlite Zip Qt::QuickWidgets Qt::CorePrivate Qt::Xml Qt::Svg Sqlite Zip Qt::GuiPrivate
PUBLIC_DEPENDS PUBLIC_DEPENDS
QmlDesignerUtils QmlPuppetCommunication QmlDesignerCore QmlDesignerUtils QmlPuppetCommunication QmlDesignerCore
DEFINES DEFINES

View File

@@ -9,9 +9,14 @@
#include <QColorDialog> #include <QColorDialog>
#include <QDebug> #include <QDebug>
#include <QPainter> #include <QPainter>
#include <QPainterPath>
#include <QScreen> #include <QScreen>
#include <QTimer> #include <QTimer>
#include <private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformservices.h>
namespace QmlDesigner { namespace QmlDesigner {
QPointer<ColorPaletteBackend> ColorPaletteBackend::m_instance = nullptr; QPointer<ColorPaletteBackend> ColorPaletteBackend::m_instance = nullptr;
@@ -19,7 +24,7 @@ QPointer<ColorPaletteBackend> ColorPaletteBackend::m_instance = nullptr;
ColorPaletteBackend::ColorPaletteBackend() ColorPaletteBackend::ColorPaletteBackend()
: m_currentPalette() : m_currentPalette()
, m_data() , m_data()
, m_colorPickingEventFilter(nullptr) , m_eyeDropperEventFilter(nullptr)
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN32
, updateTimer(0) , updateTimer(0)
#endif #endif
@@ -43,6 +48,8 @@ ColorPaletteBackend::ColorPaletteBackend()
ColorPaletteBackend::~ColorPaletteBackend() ColorPaletteBackend::~ColorPaletteBackend()
{ {
//writePalettes(); // TODO crash on QtDS close //writePalettes(); // TODO crash on QtDS close
if (m_eyeDropperActive)
eyeDropperLeave(QCursor::pos(), EyeDropperEventFilter::LeaveReason::Default);
} }
void ColorPaletteBackend::readPalettes() void ColorPaletteBackend::readPalettes()
@@ -204,67 +211,129 @@ void ColorPaletteBackend::showDialog(QColor color)
QTimer::singleShot(0, [colorDialog](){ colorDialog->exec(); }); QTimer::singleShot(0, [colorDialog](){ colorDialog->exec(); });
} }
void ColorPaletteBackend::eyeDropper() void ColorPaletteBackend::invokeEyeDropper()
{ {
QWidget *widget = Core::ICore::mainWindow(); eyeDropperEnter();
if (!widget)
return;
m_eyeDropperActive = true;
emit eyeDropperActiveChanged();
if (!m_colorPickingEventFilter)
m_colorPickingEventFilter = new QColorPickingEventFilter(this);
widget->installEventFilter(m_colorPickingEventFilter);
#ifndef QT_NO_CURSOR
widget->grabMouse(/*Qt::CrossCursor*/);
#else
widget->grabMouse();
#endif
#ifdef Q_OS_WIN32 // excludes WinRT
// On Windows mouse tracking doesn't work over other processes's windows
updateTimer->start(30);
// HACK: Because mouse grabbing doesn't work across processes, we have to have a dummy,
// invisible window to catch the mouse click, otherwise we will click whatever we clicked
// and loose focus.
dummyTransparentWindow.show();
#endif
widget->grabKeyboard();
/* With setMouseTracking(true) the desired color can be more precisely picked up,
* and continuously pushing the mouse button is not necessary.
*/
widget->setMouseTracking(true);
QGuiApplication::setOverrideCursor(QCursor());
updateEyeDropperPosition(QCursor::pos());
} }
const int g_cursorWidth = 64; void ColorPaletteBackend::eyeDropperEnter()
const int g_cursorHeight = 64; {
const int g_screenGrabWidth = 7; if (m_eyeDropperActive)
const int g_screenGrabHeight = 7; return;
const int g_pixelX = 3;
const int g_pixelY = 3; QPointer<QWindow> window = Core::ICore::mainWindow()->windowHandle();
if (m_eyeDropperWindow.isNull()) {
if (window.isNull()) {
qWarning() << "No window found, cannot enter eyeDropperMode.";
return;
}
m_eyeDropperWindow = window;
}
if (auto *platformServices = QGuiApplicationPrivate::platformIntegration()->services();
platformServices
&& platformServices->hasCapability(QPlatformServices::Capability::ColorPicking)) {
if (auto *colorPickerService = platformServices->colorPicker(m_eyeDropperWindow)) {
connect(colorPickerService,
&QPlatformServiceColorPicker::colorPicked,
this,
[this, colorPickerService](const QColor &color) {
colorPickerService->deleteLater();
// When the service was canceled by pressing escape the color returned will
// be QColor(ARGB, 0, 0, 0, 0), so we test for alpha to avoid setting the color.
// https://codereview.qt-project.org/c/qt/qtbase/+/589113
if (color.alpha() != 0 || !color.isValid())
emit currentColorChanged(color);
m_eyeDropperActive = false;
emit eyeDropperActiveChanged();
});
m_eyeDropperActive = true;
emit eyeDropperActiveChanged();
colorPickerService->pickColor();
return;
}
}
m_eyeDropperPreviousColor = m_eyeDropperCurrentColor;
if (!bool(m_eyeDropperEventFilter))
m_eyeDropperEventFilter.reset(new EyeDropperEventFilter(
[this](QPoint pos, EyeDropperEventFilter::LeaveReason c) { eyeDropperLeave(pos, c); },
[this](QPoint pos) { eyeDropperPointerMoved(pos); }));
if (m_eyeDropperWindow->setMouseGrabEnabled(true)
&& m_eyeDropperWindow->setKeyboardGrabEnabled(true)) {
#if QT_CONFIG(cursor)
QGuiApplication::setOverrideCursor(QCursor());
updateEyeDropperPosition(QCursor::pos());
#endif
m_eyeDropperWindow->installEventFilter(m_eyeDropperEventFilter.get());
m_eyeDropperActive = true;
emit eyeDropperActiveChanged();
}
}
void ColorPaletteBackend::eyeDropperLeave(const QPoint &pos,
EyeDropperEventFilter::LeaveReason actionOnLeave)
{
if (!m_eyeDropperActive)
return;
if (!m_eyeDropperWindow) {
qWarning() << "Window not set, cannot leave eyeDropperMode.";
return;
}
if (actionOnLeave != EyeDropperEventFilter::LeaveReason::Cancel) {
m_eyeDropperCurrentColor = grabScreenColor(pos);
emit currentColorChanged(m_eyeDropperCurrentColor);
}
m_eyeDropperWindow->removeEventFilter(m_eyeDropperEventFilter.get());
m_eyeDropperWindow->setMouseGrabEnabled(false);
m_eyeDropperWindow->setKeyboardGrabEnabled(false);
#if QT_CONFIG(cursor)
QGuiApplication::restoreOverrideCursor();
#endif
m_eyeDropperActive = false;
emit eyeDropperActiveChanged();
m_eyeDropperWindow.clear();
}
void ColorPaletteBackend::eyeDropperPointerMoved(const QPoint &pos)
{
m_eyeDropperCurrentColor = grabScreenColor(pos);
updateEyeDropperPosition(pos);
}
const QSize g_cursorSize(64, 64);
const QSize g_halfCursorSize = g_cursorSize / 2;
const QSize g_screenGrabSize(11, 11);
const QSize g_previewSize(12, 12);
const QSize g_halfPreviewSize = g_previewSize / 2;
QColor ColorPaletteBackend::grabScreenColor(const QPoint &p) QColor ColorPaletteBackend::grabScreenColor(const QPoint &p)
{ {
return grabScreenRect(p).pixel(g_pixelX, g_pixelY); return grabScreenRect(QRect(p, QSize(1, 1))).pixel(0, 0);
} }
QImage ColorPaletteBackend::grabScreenRect(const QPoint &p) QImage ColorPaletteBackend::grabScreenRect(const QRect &r)
{ {
QScreen *screen = QGuiApplication::screenAt(p); QScreen *screen = QGuiApplication::screenAt(r.topLeft());
if (!screen) if (!screen)
screen = QGuiApplication::primaryScreen(); screen = QGuiApplication::primaryScreen();
const QRect screenRect = screen->geometry(); const QRect screenRect = screen->geometry();
const QPixmap pixmap = screen->grabWindow(0, const QPixmap pixmap = screen->grabWindow(0,
p.x() - screenRect.x(), r.x() - screenRect.x(),
p.y() - screenRect.y(), r.y() - screenRect.y(),
g_screenGrabWidth, r.width(),
g_screenGrabHeight); r.height());
return pixmap.toImage(); return pixmap.toImage();
} }
@@ -272,7 +341,7 @@ void ColorPaletteBackend::updateEyeDropper()
{ {
#ifndef QT_NO_CURSOR #ifndef QT_NO_CURSOR
static QPoint lastGlobalPos; static QPoint lastGlobalPos;
QPoint newGlobalPos = QCursor::pos(); const QPoint newGlobalPos = QCursor::pos();
if (lastGlobalPos == newGlobalPos) if (lastGlobalPos == newGlobalPos)
return; return;
@@ -287,102 +356,70 @@ void ColorPaletteBackend::updateEyeDropper()
void ColorPaletteBackend::updateEyeDropperPosition(const QPoint &globalPos) void ColorPaletteBackend::updateEyeDropperPosition(const QPoint &globalPos)
{ {
updateCursor(grabScreenRect(globalPos)); #if QT_CONFIG(cursor)
QPoint topLeft = globalPos - QPoint(g_halfCursorSize.width(), g_halfCursorSize.height());
updateCursor(grabScreenRect(QRect(topLeft, g_cursorSize)));
#endif
} }
void ColorPaletteBackend::updateCursor(const QImage &image) void ColorPaletteBackend::updateCursor(const QImage &image)
{ {
QWidget *widget = Core::ICore::mainWindow(); QWindow *window = Core::ICore::mainWindow()->windowHandle();
if (!widget) if (!window)
return; return;
QPixmap pixmap(QSize(g_cursorWidth, g_cursorHeight)); QPixmap pixmap(g_cursorSize);
pixmap.fill(Qt::transparent);
QPainter painter(&pixmap); QPainter painter(&pixmap);
painter.setRenderHint(QPainter::Antialiasing);
QPainterPath clipPath;
clipPath.addEllipse(QRect(QPoint(0, 0), g_cursorSize).adjusted(1, 1, -1, -1));
painter.setClipPath(clipPath, Qt::IntersectClip);
const QPoint topLeft = QPoint(g_halfCursorSize.width(), g_halfCursorSize.height())
- QPoint(qFloor(g_screenGrabSize.width() / 2),
qFloor(g_screenGrabSize.height() / 2));
const QColor topCenter = image.pixelColor(g_halfCursorSize.width(), 0);
const QColor bottomCenter = image.pixelColor(g_halfCursorSize.width(), g_cursorSize.height() - 1);
const QColor leftCenter = image.pixelColor(0, g_halfCursorSize.height());
const QColor rightCenter = image.pixelColor(g_cursorSize.width() - 1, g_halfCursorSize.height());
// Find the mean gray value of top, bottom, left and right center
int borderGray = (qGray(topCenter.rgb()) + qGray(bottomCenter.rgb()) + qGray(leftCenter.rgb())
+ qGray(rightCenter.rgb()))
/ 4;
// Draw the magnified image/screen grab // Draw the magnified image/screen grab
QRect r(QPoint(), pixmap.size()); const QRect r(QPoint(), pixmap.size());
painter.drawImage(r, image, QRect(0, 0, g_screenGrabWidth, g_screenGrabHeight)); painter.drawImage(r, image, QRect(topLeft, g_screenGrabSize));
const int pixelWidth = (g_cursorWidth - 1) / g_screenGrabWidth; painter.setClipping(false);
const int pixelHeight = (g_cursorHeight - 1) / g_screenGrabHeight;
// Draw the pixel lines
painter.setPen(QPen(QColor(192, 192, 192, 150), 1.0, Qt::SolidLine));
for (int i = 1; i != g_screenGrabWidth; ++i) {
int x = pixelWidth * i;
painter.drawLine(x, 0, x, g_cursorHeight);
}
for (int i = 1; i != g_screenGrabHeight; ++i) { QPen pen(borderGray < 128 ? Qt::white : Qt::black, 2.0, Qt::SolidLine);
int y = pixelHeight * i;
painter.drawLine(0, y, g_cursorWidth, y);
}
// Draw the sorounding border
painter.setPen(QPen(Qt::black, 1.0, Qt::SolidLine));
painter.drawRect(r.adjusted(0, 0, -1, -1));
const QColor color = image.pixel(g_pixelX, g_pixelY); // Draw the surrounding border
QRect centerRect = QRect(2 * pixelWidth, 2 * pixelHeight, 3 * pixelWidth, 3 * pixelHeight); painter.setPen(pen);
// Draw the center rectangle with the current eye dropper color painter.drawPath(clipPath);
painter.setBrush(QBrush(color, Qt::SolidPattern));
painter.drawRect(centerRect); pen.setWidth(1);
painter.setPen(pen);
const QRect previewRect(QPoint(g_halfCursorSize.width() - g_halfPreviewSize.width(),
g_halfCursorSize.height() - g_halfPreviewSize.height()),
g_previewSize);
painter.fillRect(previewRect, m_eyeDropperCurrentColor);
painter.drawRect(previewRect);
painter.end(); painter.end();
QGuiApplication::changeOverrideCursor(QCursor(pixmap)); QGuiApplication::changeOverrideCursor(QCursor(pixmap));
} }
void ColorPaletteBackend::releaseEyeDropper()
{
QWidget *widget = Core::ICore::mainWindow();
if (!widget)
return;
m_eyeDropperActive = false;
emit eyeDropperActiveChanged();
widget->removeEventFilter(m_colorPickingEventFilter);
widget->releaseMouse();
#ifdef Q_OS_WIN32
updateTimer->stop();
dummyTransparentWindow.setVisible(false);
#endif
widget->releaseKeyboard();
widget->setMouseTracking(false);
QGuiApplication::restoreOverrideCursor();
}
bool ColorPaletteBackend::handleEyeDropperMouseMove(QMouseEvent *e)
{
updateEyeDropperPosition(e->globalPosition().toPoint());
return true;
}
bool ColorPaletteBackend::handleEyeDropperMouseButtonRelease(QMouseEvent *e)
{
if (e->button() == Qt::LeftButton)
emit currentColorChanged(grabScreenColor(e->globalPosition().toPoint()));
else
emit eyeDropperRejected();
releaseEyeDropper();
return true;
}
bool ColorPaletteBackend::handleEyeDropperKeyPress(QKeyEvent *e)
{
#if QT_CONFIG(shortcut)
if (e->matches(QKeySequence::Cancel)) {
emit eyeDropperRejected();
releaseEyeDropper();
} //else
#endif
//if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
// emit currentColorChanged(grabScreenColor(e->globalPosition().toPoint()));
// releaseEyeDropper();
//}
e->accept();
return true;
}
bool ColorPaletteBackend::eyeDropperActive() const bool ColorPaletteBackend::eyeDropperActive() const
{ {
return m_eyeDropperActive; return m_eyeDropperActive;

View File

@@ -18,12 +18,62 @@
namespace QmlDesigner { namespace QmlDesigner {
class QColorPickingEventFilter;
const int g_maxPaletteSize = 8; const int g_maxPaletteSize = 8;
const QString g_recent = "Recent"; const QString g_recent = "Recent";
const QString g_favorite = "Favorite"; const QString g_favorite = "Favorite";
class EyeDropperEventFilter : public QObject
{
public:
enum class LeaveReason { Default, Cancel };
explicit EyeDropperEventFilter(std::function<void(QPoint, LeaveReason)> callOnLeave,
std::function<void(QPoint)> callOnUpdate)
: m_leave(callOnLeave)
, m_update(callOnUpdate)
{}
bool eventFilter(QObject *obj, QEvent *event) override
{
switch (event->type()) {
case QEvent::MouseMove: {
m_lastPosition = static_cast<QMouseEvent *>(event)->globalPosition().toPoint();
m_update(m_lastPosition);
return true;
}
case QEvent::MouseButtonRelease: {
m_lastPosition = static_cast<QMouseEvent *>(event)->globalPosition().toPoint();
m_leave(m_lastPosition, EyeDropperEventFilter::LeaveReason::Default);
return true;
}
case QEvent::MouseButtonPress:
return true;
case QEvent::KeyPress: {
auto keyEvent = static_cast<QKeyEvent *>(event);
#if QT_CONFIG(shortcut)
if (keyEvent->matches(QKeySequence::Cancel))
m_leave(m_lastPosition, EyeDropperEventFilter::LeaveReason::Cancel);
else
#endif
if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) {
m_leave(m_lastPosition, EyeDropperEventFilter::LeaveReason::Default);
} else if (keyEvent->key() == Qt::Key_Escape) {
m_leave(m_lastPosition, EyeDropperEventFilter::LeaveReason::Cancel);
}
keyEvent->accept();
return true;
}
default:
return QObject::eventFilter(obj, event);
}
}
private:
std::function<void(QPoint, LeaveReason)> m_leave;
std::function<void(QPoint)> m_update;
QPoint m_lastPosition;
};
struct Palette struct Palette
{ {
Palette() Palette()
@@ -100,20 +150,22 @@ public:
Q_INVOKABLE void showDialog(QColor color); Q_INVOKABLE void showDialog(QColor color);
Q_INVOKABLE void eyeDropper(); //Q_INVOKABLE void eyeDropper();
Q_INVOKABLE void invokeEyeDropper();
QColor grabScreenColor(const QPoint &p); QColor grabScreenColor(const QPoint &p);
QImage grabScreenRect(const QPoint &p); QImage grabScreenRect(const QRect &r);
void updateEyeDropper(); void updateEyeDropper();
void updateEyeDropperPosition(const QPoint &globalPos); void updateEyeDropperPosition(const QPoint &globalPos);
void updateCursor(const QImage &image); void updateCursor(const QImage &image);
void releaseEyeDropper(); //void releaseEyeDropper();
//
bool handleEyeDropperMouseMove(QMouseEvent *e); //bool handleEyeDropperMouseMove(QMouseEvent *e);
bool handleEyeDropperMouseButtonRelease(QMouseEvent *e); //bool handleEyeDropperMouseButtonRelease(QMouseEvent *e);
bool handleEyeDropperKeyPress(QKeyEvent *e); //bool handleEyeDropperKeyPress(QKeyEvent *e);
bool eyeDropperActive() const; bool eyeDropperActive() const;
@@ -134,13 +186,20 @@ signals:
private: private:
ColorPaletteBackend(); ColorPaletteBackend();
void eyeDropperEnter();
void eyeDropperLeave(const QPoint &pos, EyeDropperEventFilter::LeaveReason actionOnLeave);
void eyeDropperPointerMoved(const QPoint &pos);
private: private:
static QPointer<ColorPaletteBackend> m_instance; static QPointer<ColorPaletteBackend> m_instance;
QString m_currentPalette; QString m_currentPalette;
QStringList m_currentPaletteColors; QStringList m_currentPaletteColors;
QHash<QString, Palette> m_data; QHash<QString, Palette> m_data;
QColorPickingEventFilter *m_colorPickingEventFilter; std::unique_ptr<EyeDropperEventFilter> m_eyeDropperEventFilter;
QPointer<QWindow> m_eyeDropperWindow;
QColor m_eyeDropperCurrentColor;
QColor m_eyeDropperPreviousColor;
bool m_eyeDropperActive = false; bool m_eyeDropperActive = false;
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN32
QTimer *updateTimer; QTimer *updateTimer;
@@ -148,35 +207,6 @@ private:
#endif #endif
}; };
class QColorPickingEventFilter : public QObject {
public:
explicit QColorPickingEventFilter(ColorPaletteBackend *colorPalette)
: QObject(colorPalette)
, m_colorPalette(colorPalette)
{}
bool eventFilter(QObject *, QEvent *event) override
{
switch (event->type()) {
case QEvent::MouseMove:
return m_colorPalette->handleEyeDropperMouseMove(
static_cast<QMouseEvent *>(event));
case QEvent::MouseButtonRelease:
return m_colorPalette->handleEyeDropperMouseButtonRelease(
static_cast<QMouseEvent *>(event));
case QEvent::KeyPress:
return m_colorPalette->handleEyeDropperKeyPress(
static_cast<QKeyEvent *>(event));
default:
break;
}
return false;
}
private:
ColorPaletteBackend *m_colorPalette;
};
} // namespace QmlDesigner } // namespace QmlDesigner
QML_DECLARE_TYPE(QmlDesigner::ColorPaletteBackend) QML_DECLARE_TYPE(QmlDesigner::ColorPaletteBackend)