21 #include <QMouseEvent>
25 #define NUMBER_COLORS_PER_ROW 10
31 , mDrawBoxDepressed( false )
32 , mCurrentHoverBox( -1 )
34 , mCurrentFocusBox( 0 )
35 , mPressedOnWidget( false )
38 setMouseTracking(
true );
40 setFocusPolicy( Qt::StrongFocus );
41 setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
46 mSwatchOutlineSize = std::max( fontMetrics().horizontalAdvance(
'.' ) * 0.4, 1.0 );
48 mSwatchSpacing = mSwatchSize * 0.3;
49 mSwatchMargin = mLabelMargin;
59 return QSize( mWidth, calculateHeight() );
64 return QSize( mWidth, calculateHeight() );
82 mColors = mScheme->
fetchColors( mContext, mBaseColor );
92 QPainter painter(
this );
100 int newBox = swatchForPosition( event->pos() );
102 mDrawBoxDepressed =
event->buttons() & Qt::LeftButton;
103 if ( newBox != mCurrentHoverBox )
106 mCurrentHoverBox = newBox;
109 updateTooltip( newBox );
115 void QgsColorSwatchGrid::updateTooltip(
const int colorIdx )
117 if ( colorIdx >= 0 && colorIdx < mColors.length() )
119 QColor color = mColors.at( colorIdx ).first;
122 QString colorName = mColors.at( colorIdx ).second;
125 int width =
static_cast< int >(
Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance(
'X' ) * 23 );
126 int height =
static_cast< int >( width / 1.61803398875 );
127 int margin =
static_cast< int >( height * 0.1 );
128 QImage icon = QImage( width + 2 * margin, height + 2 * margin, QImage::Format_ARGB32 );
129 icon.fill( Qt::transparent );
135 QBrush checkBrush = QBrush( transparentBackground() );
136 p.setPen( Qt::NoPen );
137 p.setBrush( checkBrush );
138 p.drawRect( margin, margin, width, height );
141 p.setBrush( QBrush( mColors.at( colorIdx ).first ) );
144 p.setPen( QColor( 197, 197, 197 ) );
145 p.drawRect( margin, margin, width, height );
149 QBuffer buffer( &data );
150 icon.save( &buffer,
"PNG", 100 );
153 if ( !colorName.isEmpty() )
154 info += QStringLiteral(
"<h3>%1</h3><p>" ).arg( colorName );
156 info += QStringLiteral(
"<b>HEX</b> %1<br>"
158 "<b>HSV</b> %3,%4,%5<p>" ).arg( color.name(),
160 .arg( color.hue() ).arg( color.saturation() ).arg( color.value() );
161 info += QStringLiteral(
"<img src='data:image/png;base64, %0'>" ).arg( QString( data.toBase64() ) );
169 setToolTip( QString() );
175 if ( !mDrawBoxDepressed && event->buttons() & Qt::LeftButton )
177 mCurrentHoverBox = swatchForPosition( event->pos() );
178 mDrawBoxDepressed =
true;
181 mPressedOnWidget =
true;
186 if ( ! mPressedOnWidget )
191 int box = swatchForPosition( event->pos() );
192 if ( mDrawBoxDepressed && event->button() == Qt::LeftButton )
194 mCurrentHoverBox = box;
195 mDrawBoxDepressed =
false;
199 if ( box >= 0 && box < mColors.length() && event->button() == Qt::LeftButton )
209 if ( event->key() == Qt::Key_Right )
211 mCurrentFocusBox = std::min( mCurrentFocusBox + 1, mColors.length() - 1 );
213 else if ( event->key() == Qt::Key_Left )
215 mCurrentFocusBox = std::max( mCurrentFocusBox - 1, 0 );
217 else if ( event->key() == Qt::Key_Up )
223 if ( currentRow >= 0 )
230 focusPreviousChild();
233 else if ( event->key() == Qt::Key_Down )
240 if ( box < mColors.length() )
242 mCurrentFocusBox = box;
250 else if ( event->key() == Qt::Key_Enter || event->key() == Qt::Key_Space )
253 emit
colorChanged( mColors.at( mCurrentFocusBox ).first );
258 QWidget::keyPressEvent( event );
279 int QgsColorSwatchGrid::calculateHeight()
const
282 return numberRows * ( mSwatchSize ) + ( numberRows - 1 ) * mSwatchSpacing + mSwatchMargin + mLabelHeight + 0.5 * mLabelMargin + mSwatchMargin;
285 void QgsColorSwatchGrid::draw( QPainter &painter )
287 QPalette
pal = QPalette( qApp->palette() );
288 QColor headerBgColor =
pal.color( QPalette::Mid );
289 QColor headerTextColor =
pal.color( QPalette::BrightText );
290 QColor highlight =
pal.color( QPalette::Highlight );
293 painter.setBrush( headerBgColor );
294 painter.setPen( Qt::NoPen );
295 painter.drawRect( QRect( 0, 0, width(), mLabelHeight + 0.5 * mLabelMargin ) );
298 painter.setPen( headerTextColor );
299 painter.drawText( QRect( mLabelMargin, 0.25 * mLabelMargin, width() - 2 * mLabelMargin, mLabelHeight ),
300 Qt::AlignLeft | Qt::AlignVCenter, mScheme->
schemeName() );
303 QgsNamedColorList::const_iterator colorIt = mColors.constBegin();
305 for ( ; colorIt != mColors.constEnd(); ++colorIt )
310 QRect swatchRect = QRect( column * ( mSwatchSize + mSwatchSpacing ) + mSwatchMargin,
311 row * ( mSwatchSize + mSwatchSpacing ) + mSwatchMargin + mLabelHeight + 0.5 * mLabelMargin,
312 mSwatchSize, mSwatchSize );
314 if ( mCurrentHoverBox == index )
317 swatchRect.adjust( -1, -1, 1, 1 );
321 if ( ( *colorIt ).first.alpha() != 255 )
323 QBrush checkBrush = QBrush( transparentBackground() );
324 painter.setPen( Qt::NoPen );
325 painter.setBrush( checkBrush );
326 painter.drawRect( swatchRect );
329 if ( mCurrentHoverBox == index )
331 if ( mDrawBoxDepressed )
333 painter.setPen( QPen( QColor( 100, 100, 100 ), mSwatchOutlineSize ) );
338 painter.setPen( QPen( QColor( 220, 220, 220 ), mSwatchOutlineSize ) );
341 else if ( mFocused && index == mCurrentFocusBox )
343 painter.setPen( highlight );
345 else if ( ( *colorIt ).first.name() == mBaseColor.name() )
348 painter.setPen( QPen( QColor( 75, 75, 75 ), mSwatchOutlineSize ) );
352 painter.setPen( QPen( QColor( 197, 197, 197 ), mSwatchOutlineSize ) );
355 painter.setBrush( ( *colorIt ).first );
356 painter.drawRect( swatchRect );
362 QPixmap QgsColorSwatchGrid::transparentBackground()
364 static QPixmap sTranspBkgrd;
366 if ( sTranspBkgrd.isNull() )
372 int QgsColorSwatchGrid::swatchForPosition( QPoint position )
const
376 int column = ( position.x() - mSwatchMargin ) / ( mSwatchSize + mSwatchSpacing );
377 int xRem = ( position.x() - mSwatchMargin ) % ( mSwatchSize + mSwatchSpacing );
378 int row = ( position.y() - mSwatchMargin - mLabelHeight ) / ( mSwatchSize + mSwatchSpacing );
379 int yRem = ( position.y() - mSwatchMargin - mLabelHeight ) % ( mSwatchSize + mSwatchSpacing );
396 : QWidgetAction( parent )
398 , mSuppressRecurse( false )
399 , mDismissOnColorSelection( true )
403 setDefaultWidget( mColorSwatchGrid );
406 connect(
this, &QAction::hovered,
this, &QgsColorSwatchGridAction::onHover );
410 setVisible( !mColorSwatchGrid->
colors()->isEmpty() );
425 return mColorSwatchGrid->
context();
437 setVisible( !mColorSwatchGrid->
colors()->isEmpty() );
440 void QgsColorSwatchGridAction::setColor(
const QColor &color )
444 if ( mMenu && mDismissOnColorSelection )
450 void QgsColorSwatchGridAction::onHover()
454 if ( mSuppressRecurse )
461 mSuppressRecurse =
true;
462 mMenu->setActiveAction(
this );
463 mSuppressRecurse =
false;
static const double UI_SCALE_FACTOR
UI scaling factor.
static QPixmap getThemePixmap(const QString &name, const QColor &foreColor=QColor(), const QColor &backColor=QColor(), int size=16)
Helper to get a theme icon as a pixmap.
Abstract base class for color schemes.
virtual QString schemeName() const =0
Gets the name for the color scheme.
virtual QgsNamedColorList fetchColors(const QString &context=QString(), const QColor &baseColor=QColor())=0
Gets a list of colors from the scheme.
void setBaseColor(const QColor &baseColor)
Sets the base color for the color grid.
QString context() const
Gets the current context for the color grid.
void colorChanged(const QColor &color)
Emitted when a color has been selected from the widget.
QgsColorSwatchGridAction(QgsColorScheme *scheme, QMenu *menu=nullptr, const QString &context=QString(), QWidget *parent=nullptr)
Construct a new color swatch grid action.
void refreshColors()
Reload colors from scheme and redraws the widget.
QColor baseColor() const
Gets the base color for the color grid.
void setContext(const QString &context)
Sets the current context for the color grid.
A grid of color swatches, which allows for user selection.
void mouseMoveEvent(QMouseEvent *event) override
QgsNamedColorList * colors()
Gets the list of colors shown in the grid.
void mousePressEvent(QMouseEvent *event) override
QColor baseColor() const
Gets the base color for the widget.
QgsColorSwatchGrid(QgsColorScheme *scheme, const QString &context=QString(), QWidget *parent=nullptr)
Construct a new color swatch grid.
void paintEvent(QPaintEvent *event) override
void colorChanged(const QColor &color)
Emitted when a color has been selected from the widget.
void setBaseColor(const QColor &baseColor)
Sets the base color for the widget.
QSize minimumSizeHint() const override
void mouseReleaseEvent(QMouseEvent *event) override
QSize sizeHint() const override
void refreshColors()
Reload colors from scheme and redraws the widget.
void focusInEvent(QFocusEvent *event) override
void keyPressEvent(QKeyEvent *event) override
void focusOutEvent(QFocusEvent *event) override
void hovered()
Emitted when mouse hovers over widget.
void setContext(const QString &context)
Sets the current context for the grid.
QString context() const
Gets the current context for the grid.
static QString encodeColor(const QColor &color)
#define NUMBER_COLORS_PER_ROW