From 989eae166774b73eb90d91b89a1ce24f0112b741 Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Tue, 3 Sep 2024 16:46:37 +0200 Subject: [PATCH] QmlDesigner: EyeDropper use platform service Task-number: QDS-12517 Change-Id: I1fdbdf3aa0992826d109d0e24e92d15c7576fb93 Reviewed-by: Tim Jenssen --- .../imports/HelperWidgets/ColorEditor.qml | 12 +- .../HelperWidgets/ColorEditorPopup.qml | 11 +- .../imports/StudioControls/ColorEditor.qml | 3 + .../StudioControls/impl/ColorEditorPopup.qml | 6 +- src/plugins/qmldesigner/CMakeLists.txt | 2 +- .../propertyeditor/colorpalettebackend.cpp | 295 ++++++++++-------- .../propertyeditor/colorpalettebackend.h | 108 ++++--- 7 files changed, 254 insertions(+), 183 deletions(-) diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml index cc8247d7063..1a7291a441d 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml @@ -39,7 +39,7 @@ SecondColumnLayout { 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 color originalColor @@ -91,9 +91,9 @@ SecondColumnLayout { if (colorEditor.backendValue !== undefined) { if (colorEditor.isVector3D) - colorEditor.backendValue.value = Qt.vector3d( - colorEditor.color.r, colorEditor.color.g, - colorEditor.color.b) + colorEditor.backendValue.value = Qt.vector3d(colorEditor.color.r, + colorEditor.color.g, + colorEditor.color.b) else colorEditor.backendValue.value = colorEditor.color } @@ -223,10 +223,8 @@ SecondColumnLayout { function open() { popupDialog.ensureLoader() - popupDialog.show(preview) - - popupDialog.loaderItem.aboutToBeShown() //need it for now + popupDialog.loaderItem.aboutToBeShown() // need it for now } function determineActiveColorMode() { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditorPopup.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditorPopup.qml index bced56a89dc..126b9a0dac2 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditorPopup.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditorPopup.qml @@ -12,10 +12,9 @@ import QtQuickDesignerColorPalette Column { id: root - // There seems to be an issue on Windows and MacOS with ColorPickers - // Canvases not being painted on initialization - // because ColorEditorPopup is invisible at init time, - // so we use this signal to explicitly pass visibility status + // There seems to be an issue on Windows and macOS with ColorPickers canvas not being painted + // on initialization, because ColorEditorPopup is invisible at init time, so we use this signal + // to explicitly pass visibility status. signal aboutToBeShown property bool eyeDropperActive: ColorPaletteBackend.eyeDropperActive @@ -23,7 +22,7 @@ Column { property bool supportGradient: 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 alias gradientLine: gradientLine @@ -188,7 +187,7 @@ Column { icon: StudioTheme.Constants.eyeDropper pixelSize: StudioTheme.Values.myIconFontSize * 1.4 tooltip: qsTr("Eye Dropper") - onClicked: ColorPaletteBackend.eyeDropper() + onClicked: ColorPaletteBackend.invokeEyeDropper() } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ColorEditor.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ColorEditor.qml index 640f21de9e2..4100ecf934c 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ColorEditor.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ColorEditor.qml @@ -69,6 +69,8 @@ Item { property QtObject loaderItem: loader.item + keepOpen: loader.item?.eyeDropperActive ?? false + width: 260 function ensureLoader() { @@ -91,6 +93,7 @@ Item { id: popup width: popupDialog.contentWidth visible: popupDialog.visible + parentWindow: popupDialog.window onActivateColor: function(color) { colorBackend.activateColor(color) diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/impl/ColorEditorPopup.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/impl/ColorEditorPopup.qml index 4f46b356f3a..0674a156a0a 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/impl/ColorEditorPopup.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/impl/ColorEditorPopup.qml @@ -12,9 +12,13 @@ import QtQuickDesignerColorPalette Column { id: root + property bool eyeDropperActive: ColorPaletteBackend.eyeDropperActive + property color color property color originalColor + property Window parentWindow: null + readonly property real twoColumnWidth: (colorColumn.width - StudioTheme.Values.controlGap) * 0.5 readonly property real fourColumnWidth: (colorColumn.width - (3 * StudioTheme.Values.controlGap)) * 0.25 @@ -42,7 +46,7 @@ Column { icon: StudioTheme.Constants.eyeDropper pixelSize: StudioTheme.Values.myIconFontSize * 1.4 toolTip: qsTr("Eye Dropper") - onClicked: ColorPaletteBackend.eyeDropper() + onClicked: ColorPaletteBackend.invokeEyeDropper() } } diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index cc9243d84b4..0f0a0c70414 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -53,7 +53,7 @@ add_qtc_plugin(QmlDesigner PLUGIN_MANUAL_DEPENDS LicenseChecker ${IDE_VERSION} optional DEPENDS 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 QmlDesignerUtils QmlPuppetCommunication QmlDesignerCore DEFINES diff --git a/src/plugins/qmldesigner/components/propertyeditor/colorpalettebackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/colorpalettebackend.cpp index fc5b9c6ebb3..7ca01e3d2bd 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/colorpalettebackend.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/colorpalettebackend.cpp @@ -9,9 +9,14 @@ #include #include #include +#include #include #include +#include +#include +#include + namespace QmlDesigner { QPointer ColorPaletteBackend::m_instance = nullptr; @@ -19,7 +24,7 @@ QPointer ColorPaletteBackend::m_instance = nullptr; ColorPaletteBackend::ColorPaletteBackend() : m_currentPalette() , m_data() - , m_colorPickingEventFilter(nullptr) + , m_eyeDropperEventFilter(nullptr) #ifdef Q_OS_WIN32 , updateTimer(0) #endif @@ -43,6 +48,8 @@ ColorPaletteBackend::ColorPaletteBackend() ColorPaletteBackend::~ColorPaletteBackend() { //writePalettes(); // TODO crash on QtDS close + if (m_eyeDropperActive) + eyeDropperLeave(QCursor::pos(), EyeDropperEventFilter::LeaveReason::Default); } void ColorPaletteBackend::readPalettes() @@ -204,67 +211,129 @@ void ColorPaletteBackend::showDialog(QColor color) QTimer::singleShot(0, [colorDialog](){ colorDialog->exec(); }); } -void ColorPaletteBackend::eyeDropper() +void ColorPaletteBackend::invokeEyeDropper() { - QWidget *widget = Core::ICore::mainWindow(); - 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()); + eyeDropperEnter(); } -const int g_cursorWidth = 64; -const int g_cursorHeight = 64; -const int g_screenGrabWidth = 7; -const int g_screenGrabHeight = 7; -const int g_pixelX = 3; -const int g_pixelY = 3; +void ColorPaletteBackend::eyeDropperEnter() +{ + if (m_eyeDropperActive) + return; + + QPointer 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) { - 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) screen = QGuiApplication::primaryScreen(); const QRect screenRect = screen->geometry(); const QPixmap pixmap = screen->grabWindow(0, - p.x() - screenRect.x(), - p.y() - screenRect.y(), - g_screenGrabWidth, - g_screenGrabHeight); + r.x() - screenRect.x(), + r.y() - screenRect.y(), + r.width(), + r.height()); + return pixmap.toImage(); } @@ -272,7 +341,7 @@ void ColorPaletteBackend::updateEyeDropper() { #ifndef QT_NO_CURSOR static QPoint lastGlobalPos; - QPoint newGlobalPos = QCursor::pos(); + const QPoint newGlobalPos = QCursor::pos(); if (lastGlobalPos == newGlobalPos) return; @@ -287,102 +356,70 @@ void ColorPaletteBackend::updateEyeDropper() 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) { - QWidget *widget = Core::ICore::mainWindow(); - if (!widget) + QWindow *window = Core::ICore::mainWindow()->windowHandle(); + if (!window) return; - QPixmap pixmap(QSize(g_cursorWidth, g_cursorHeight)); + QPixmap pixmap(g_cursorSize); + pixmap.fill(Qt::transparent); + 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 - QRect r(QPoint(), pixmap.size()); - painter.drawImage(r, image, QRect(0, 0, g_screenGrabWidth, g_screenGrabHeight)); + const QRect r(QPoint(), pixmap.size()); + painter.drawImage(r, image, QRect(topLeft, g_screenGrabSize)); - const int pixelWidth = (g_cursorWidth - 1) / g_screenGrabWidth; - 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); - } + painter.setClipping(false); - for (int i = 1; i != g_screenGrabHeight; ++i) { - 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)); + QPen pen(borderGray < 128 ? Qt::white : Qt::black, 2.0, Qt::SolidLine); - const QColor color = image.pixel(g_pixelX, g_pixelY); - QRect centerRect = QRect(2 * pixelWidth, 2 * pixelHeight, 3 * pixelWidth, 3 * pixelHeight); - // Draw the center rectangle with the current eye dropper color - painter.setBrush(QBrush(color, Qt::SolidPattern)); - painter.drawRect(centerRect); + // Draw the surrounding border + painter.setPen(pen); + painter.drawPath(clipPath); + + 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(); + 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 { return m_eyeDropperActive; diff --git a/src/plugins/qmldesigner/components/propertyeditor/colorpalettebackend.h b/src/plugins/qmldesigner/components/propertyeditor/colorpalettebackend.h index 9ab60d7c9e6..1d88fd4de39 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/colorpalettebackend.h +++ b/src/plugins/qmldesigner/components/propertyeditor/colorpalettebackend.h @@ -18,12 +18,62 @@ namespace QmlDesigner { -class QColorPickingEventFilter; - const int g_maxPaletteSize = 8; const QString g_recent = "Recent"; const QString g_favorite = "Favorite"; +class EyeDropperEventFilter : public QObject +{ +public: + enum class LeaveReason { Default, Cancel }; + + explicit EyeDropperEventFilter(std::function callOnLeave, + std::function callOnUpdate) + : m_leave(callOnLeave) + , m_update(callOnUpdate) + {} + + bool eventFilter(QObject *obj, QEvent *event) override + { + switch (event->type()) { + case QEvent::MouseMove: { + m_lastPosition = static_cast(event)->globalPosition().toPoint(); + m_update(m_lastPosition); + return true; + } + case QEvent::MouseButtonRelease: { + m_lastPosition = static_cast(event)->globalPosition().toPoint(); + m_leave(m_lastPosition, EyeDropperEventFilter::LeaveReason::Default); + return true; + } + case QEvent::MouseButtonPress: + return true; + case QEvent::KeyPress: { + auto keyEvent = static_cast(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 m_leave; + std::function m_update; + QPoint m_lastPosition; +}; + struct Palette { Palette() @@ -100,20 +150,22 @@ public: Q_INVOKABLE void showDialog(QColor color); - Q_INVOKABLE void eyeDropper(); + //Q_INVOKABLE void eyeDropper(); + + Q_INVOKABLE void invokeEyeDropper(); QColor grabScreenColor(const QPoint &p); - QImage grabScreenRect(const QPoint &p); + QImage grabScreenRect(const QRect &r); void updateEyeDropper(); void updateEyeDropperPosition(const QPoint &globalPos); void updateCursor(const QImage &image); - void releaseEyeDropper(); - - bool handleEyeDropperMouseMove(QMouseEvent *e); - bool handleEyeDropperMouseButtonRelease(QMouseEvent *e); - bool handleEyeDropperKeyPress(QKeyEvent *e); + //void releaseEyeDropper(); + // + //bool handleEyeDropperMouseMove(QMouseEvent *e); + //bool handleEyeDropperMouseButtonRelease(QMouseEvent *e); + //bool handleEyeDropperKeyPress(QKeyEvent *e); bool eyeDropperActive() const; @@ -134,13 +186,20 @@ signals: private: ColorPaletteBackend(); + void eyeDropperEnter(); + void eyeDropperLeave(const QPoint &pos, EyeDropperEventFilter::LeaveReason actionOnLeave); + void eyeDropperPointerMoved(const QPoint &pos); + private: static QPointer m_instance; QString m_currentPalette; QStringList m_currentPaletteColors; QHash m_data; - QColorPickingEventFilter *m_colorPickingEventFilter; + std::unique_ptr m_eyeDropperEventFilter; + QPointer m_eyeDropperWindow; + QColor m_eyeDropperCurrentColor; + QColor m_eyeDropperPreviousColor; bool m_eyeDropperActive = false; #ifdef Q_OS_WIN32 QTimer *updateTimer; @@ -148,35 +207,6 @@ private: #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(event)); - case QEvent::MouseButtonRelease: - return m_colorPalette->handleEyeDropperMouseButtonRelease( - static_cast(event)); - case QEvent::KeyPress: - return m_colorPalette->handleEyeDropperKeyPress( - static_cast(event)); - default: - break; - } - return false; - } - -private: - ColorPaletteBackend *m_colorPalette; -}; - } // namespace QmlDesigner QML_DECLARE_TYPE(QmlDesigner::ColorPaletteBackend)