mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
[FEATURE] Color picker option in color button context menu, which allows for sampling a color from anywhere on the screen. Supports holding the left mouse button to continuously sample. Pressing space also triggers a sample for Windows, where mouse clicks outside the QGIS window are unavoidably propagated onward.
This commit is contained in:
parent
e1e0b15798
commit
33b5e8ce1b
@ -88,14 +88,14 @@ class QgsColorButton: QPushButton
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* Sets the background pixmap for the button based upon set color and transparency.
|
||||
* Sets the background pixmap for the button based upon color and transparency.
|
||||
* Call directly to update background after adding/removing QColorDialog::ShowAlphaChannel option
|
||||
* but the color has not changed, i.e. setColor() wouldn't update button and
|
||||
* you want the button to retain the set color's alpha component regardless
|
||||
*
|
||||
* @param color Color for button background
|
||||
* @note added in 1.9
|
||||
*/
|
||||
void setButtonBackground();
|
||||
void setButtonBackground( QColor color = QColor() );
|
||||
|
||||
signals:
|
||||
/**
|
||||
@ -112,7 +112,7 @@ class QgsColorButton: QPushButton
|
||||
void showEvent( QShowEvent* e );
|
||||
static const QPixmap& transpBkgrd();
|
||||
|
||||
/**
|
||||
/**
|
||||
* Reimplemented to detect right mouse button clicks on the color button and allow dragging colors
|
||||
*/
|
||||
void mousePressEvent( QMouseEvent* e );
|
||||
@ -122,6 +122,16 @@ class QgsColorButton: QPushButton
|
||||
*/
|
||||
void mouseMoveEvent( QMouseEvent *e );
|
||||
|
||||
/**
|
||||
* Reimplemented to allow color picking
|
||||
*/
|
||||
void mouseReleaseEvent( QMouseEvent *e );
|
||||
|
||||
/**
|
||||
* Reimplemented to allow cancelling color pick via keypress, and sample via space bar press
|
||||
*/
|
||||
void keyPressEvent( QKeyEvent *e );
|
||||
|
||||
/**
|
||||
* Reimplemented to accept dragged colors
|
||||
*/
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "qgsapplication.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgssymbollayerv2utils.h"
|
||||
#include "qgscursors.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QSettings>
|
||||
@ -26,6 +27,7 @@
|
||||
#include <QMenu>
|
||||
#include <QClipboard>
|
||||
#include <QDrag>
|
||||
#include <QDesktopWidget>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <windows.h>
|
||||
@ -70,6 +72,7 @@ QgsColorButton::QgsColorButton( QWidget *parent, QString cdt, QColorDialog::Colo
|
||||
, mAcceptLiveUpdates( true )
|
||||
, mTempPNG( NULL )
|
||||
, mColorSet( false )
|
||||
, mPickingColor( false )
|
||||
{
|
||||
setAcceptDrops( true );
|
||||
connect( this, SIGNAL( clicked() ), this, SLOT( onButtonClicked() ) );
|
||||
@ -114,6 +117,13 @@ void QgsColorButton::onButtonClicked()
|
||||
|
||||
void QgsColorButton::mousePressEvent( QMouseEvent *e )
|
||||
{
|
||||
if ( mPickingColor )
|
||||
{
|
||||
//don't show dialog if in color picker mode
|
||||
e->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( e->button() == Qt::RightButton )
|
||||
{
|
||||
showContextMenu( e );
|
||||
@ -174,6 +184,23 @@ bool QgsColorButton::colorFromMimeData( const QMimeData * mimeData, QColor& resu
|
||||
|
||||
void QgsColorButton::mouseMoveEvent( QMouseEvent *e )
|
||||
{
|
||||
if ( mPickingColor )
|
||||
{
|
||||
//currently in color picker mode
|
||||
if ( e->buttons() & Qt::LeftButton )
|
||||
{
|
||||
//if left button depressed, sample color under cursor and temporarily update button color
|
||||
//to give feedback to user
|
||||
QPixmap snappedPixmap = QPixmap::grabWindow( QApplication::desktop()->winId(), e->globalPos().x(), e->globalPos().y(), 1, 1 );
|
||||
QImage snappedImage = snappedPixmap.toImage();
|
||||
QColor hoverColor = snappedImage.pixel( 0, 0 );
|
||||
setButtonBackground( hoverColor );
|
||||
}
|
||||
e->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
//handle dragging colors from button
|
||||
if ( !( e->buttons() & Qt::LeftButton ) )
|
||||
{
|
||||
QPushButton::mouseMoveEvent( e );
|
||||
@ -209,6 +236,52 @@ void QgsColorButton::mouseMoveEvent( QMouseEvent *e )
|
||||
setDown( false );
|
||||
}
|
||||
|
||||
void QgsColorButton::mouseReleaseEvent( QMouseEvent *e )
|
||||
{
|
||||
if ( mPickingColor )
|
||||
{
|
||||
//end color picking operation by sampling the color under cursor
|
||||
stopPicking( e->globalPos() );
|
||||
e->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
QPushButton::mouseReleaseEvent( e );
|
||||
}
|
||||
|
||||
void QgsColorButton::stopPicking( QPointF eventPos, bool sampleColor )
|
||||
{
|
||||
//release mouse and reset cursor
|
||||
releaseMouse();
|
||||
unsetCursor();
|
||||
mPickingColor = false;
|
||||
|
||||
if ( !sampleColor )
|
||||
{
|
||||
//not sampling color, nothing more to do
|
||||
return;
|
||||
}
|
||||
|
||||
//grab snapshot of pixel under mouse cursor
|
||||
QPixmap snappedPixmap = QPixmap::grabWindow( QApplication::desktop()->winId(), eventPos.x(), eventPos.y(), 1, 1 );
|
||||
QImage snappedImage = snappedPixmap.toImage();
|
||||
//extract color from pixel and set color
|
||||
setColor( snappedImage.pixel( 0, 0 ) );
|
||||
}
|
||||
|
||||
void QgsColorButton::keyPressEvent( QKeyEvent *e )
|
||||
{
|
||||
if ( !mPickingColor )
|
||||
{
|
||||
//if not picking a color, use default push button behaviour
|
||||
QPushButton::keyPressEvent( e );
|
||||
return;
|
||||
}
|
||||
|
||||
//cancel picking, sampling the color if space was pressed
|
||||
stopPicking( QCursor::pos(), e->key() == Qt::Key_Space );
|
||||
}
|
||||
|
||||
void QgsColorButton::dragEnterEvent( QDragEnterEvent *e )
|
||||
{
|
||||
//is dragged data valid color data?
|
||||
@ -238,8 +311,10 @@ void QgsColorButton::showContextMenu( QMouseEvent *event )
|
||||
colorContextMenu.addAction( copyColorAction );
|
||||
QAction* pasteColorAction = new QAction( tr( "Paste color" ), 0 );
|
||||
pasteColorAction->setEnabled( false );
|
||||
colorContextMenu.addSeparator();
|
||||
colorContextMenu.addAction( pasteColorAction );
|
||||
QAction* pickColorAction = new QAction( tr( "Pick color" ), 0 );
|
||||
colorContextMenu.addSeparator();
|
||||
colorContextMenu.addAction( pickColorAction );
|
||||
|
||||
QColor clipColor;
|
||||
if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor ) )
|
||||
@ -258,9 +333,18 @@ void QgsColorButton::showContextMenu( QMouseEvent *event )
|
||||
//paste color
|
||||
setColor( clipColor );
|
||||
}
|
||||
else if ( selectedAction == pickColorAction )
|
||||
{
|
||||
//pick color
|
||||
QPixmap samplerPixmap = QPixmap(( const char ** ) sampler_cursor );
|
||||
setCursor( QCursor( samplerPixmap, 0, 0 ) );
|
||||
grabMouse();
|
||||
mPickingColor = true;
|
||||
}
|
||||
|
||||
delete copyColorAction;
|
||||
delete pasteColorAction;
|
||||
delete pickColorAction;
|
||||
}
|
||||
|
||||
void QgsColorButton::setValidColor( const QColor& newColor )
|
||||
@ -321,8 +405,12 @@ void QgsColorButton::setColor( const QColor &color )
|
||||
mColorSet = true;
|
||||
}
|
||||
|
||||
void QgsColorButton::setButtonBackground()
|
||||
void QgsColorButton::setButtonBackground( QColor color )
|
||||
{
|
||||
if ( !color.isValid() )
|
||||
{
|
||||
color = mColor;
|
||||
}
|
||||
if ( !text().isEmpty() )
|
||||
{
|
||||
// generate icon pixmap for regular pushbutton
|
||||
@ -355,11 +443,11 @@ void QgsColorButton::setButtonBackground()
|
||||
p.setRenderHint( QPainter::Antialiasing );
|
||||
p.setClipPath( roundRect );
|
||||
p.setPen( Qt::NoPen );
|
||||
if ( mColor.alpha() < 255 )
|
||||
if ( color.alpha() < 255 )
|
||||
{
|
||||
p.drawTiledPixmap( rect, transpBkgrd() );
|
||||
}
|
||||
p.setBrush( mColor );
|
||||
p.setBrush( color );
|
||||
p.drawRect( rect );
|
||||
p.end();
|
||||
|
||||
@ -381,12 +469,12 @@ void QgsColorButton::setButtonBackground()
|
||||
//QgsDebugMsg( QString( "%1 margin: %2" ).arg( objectName() ).arg( margin ) );
|
||||
|
||||
QString bkgrd = QString( " background-color: rgba(%1,%2,%3,%4);" )
|
||||
.arg( mColor.red() )
|
||||
.arg( mColor.green() )
|
||||
.arg( mColor.blue() )
|
||||
.arg( useAlpha ? mColor.alpha() : 255 );
|
||||
.arg( color.red() )
|
||||
.arg( color.green() )
|
||||
.arg( color.blue() )
|
||||
.arg( useAlpha ? color.alpha() : 255 );
|
||||
|
||||
if ( useAlpha && mColor.alpha() < 255 )
|
||||
if ( useAlpha && color.alpha() < 255 )
|
||||
{
|
||||
QPixmap pixmap = transpBkgrd();
|
||||
QRect rect( 0, 0, pixmap.width(), pixmap.height() );
|
||||
|
@ -113,14 +113,14 @@ class GUI_EXPORT QgsColorButton: public QPushButton
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* Sets the background pixmap for the button based upon set color and transparency.
|
||||
* Sets the background pixmap for the button based upon color and transparency.
|
||||
* Call directly to update background after adding/removing QColorDialog::ShowAlphaChannel option
|
||||
* but the color has not changed, i.e. setColor() wouldn't update button and
|
||||
* you want the button to retain the set color's alpha component regardless
|
||||
*
|
||||
* @param color Color for button background
|
||||
* @note added in 1.9
|
||||
*/
|
||||
void setButtonBackground();
|
||||
void setButtonBackground( QColor color = QColor() );
|
||||
|
||||
signals:
|
||||
/**
|
||||
@ -147,6 +147,16 @@ class GUI_EXPORT QgsColorButton: public QPushButton
|
||||
*/
|
||||
void mouseMoveEvent( QMouseEvent *e );
|
||||
|
||||
/**
|
||||
* Reimplemented to allow color picking
|
||||
*/
|
||||
void mouseReleaseEvent( QMouseEvent *e );
|
||||
|
||||
/**
|
||||
* Reimplemented to allow cancelling color pick via keypress, and sample via space bar press
|
||||
*/
|
||||
void keyPressEvent( QKeyEvent *e );
|
||||
|
||||
/**
|
||||
* Reimplemented to accept dragged colors
|
||||
*/
|
||||
@ -166,6 +176,7 @@ class GUI_EXPORT QgsColorButton: public QPushButton
|
||||
bool mColorSet; // added in QGIS 2.1
|
||||
|
||||
QPoint mDragStartPosition;
|
||||
bool mPickingColor;
|
||||
|
||||
/**
|
||||
* Shows the color button context menu and handles copying and pasting color values.
|
||||
@ -201,6 +212,15 @@ class GUI_EXPORT QgsColorButton: public QPushButton
|
||||
QString fullPath( const QString &path );
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Ends a color picking operation
|
||||
* @param eventPos global position of pixel to sample color from
|
||||
* @param sampleColor set to true to actually sample the color, false to just cancel
|
||||
* the color picking operation
|
||||
* @note added in 2.5
|
||||
*/
|
||||
void stopPicking( QPointF eventPos, bool sampleColor = true );
|
||||
|
||||
private slots:
|
||||
void onButtonClicked();
|
||||
|
||||
|
@ -180,3 +180,26 @@ const char *cross_hair_cursor[] =
|
||||
" +.+ "
|
||||
};
|
||||
|
||||
const char *sampler_cursor[] =
|
||||
{
|
||||
"16 16 3 1",
|
||||
" » c None",
|
||||
".» c #000000",
|
||||
"+» c #FFFFFF",
|
||||
".. ",
|
||||
".+. ",
|
||||
" .+.. ",
|
||||
" .++. ",
|
||||
" .+++. ",
|
||||
" .+++. ",
|
||||
" .+++. ",
|
||||
" .+++... ",
|
||||
" .++... ",
|
||||
" ...... ",
|
||||
" ....... ",
|
||||
" ........ ",
|
||||
" .......",
|
||||
" ......",
|
||||
" .....",
|
||||
" ... "
|
||||
};
|
||||
|
1
src/gui/qgscursors.h
Normal file → Executable file
1
src/gui/qgscursors.h
Normal file → Executable file
@ -31,6 +31,7 @@ extern GUI_EXPORT const char *capture_point_cursor[];
|
||||
extern GUI_EXPORT const char *select_cursor[];
|
||||
extern GUI_EXPORT const char *identify_cursor[];
|
||||
extern GUI_EXPORT const char *cross_hair_cursor[];
|
||||
extern GUI_EXPORT const char *sampler_cursor[];
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user