forked from qt-creator/qt-creator
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:
committed by
Tim Jenssen
parent
04155ac5a1
commit
989eae1667
@@ -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() {
|
||||||
|
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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)
|
||||||
|
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
|
@@ -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)
|
||||||
|
Reference in New Issue
Block a user