QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgscolorbutton.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscolorbutton.cpp - Button which displays a color
3  --------------------------------------
4  Date : 12-Dec-2006
5  Copyright : (C) 2006 by Tom Elwertowski
6  Email : telwertowski at users dot sourceforge dot net
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgscolorbutton.h"
17 #include "qgscolordialog.h"
18 #include "qgsapplication.h"
19 #include "qgslogger.h"
20 #include "qgssymbollayerutils.h"
21 #include "qgscolorswatchgrid.h"
22 #include "qgscolorschemeregistry.h"
23 #include "qgscolorwidgets.h"
24 #include "qgssettings.h"
25 #include "qgsproject.h"
26 #include "qgsguiutils.h"
27 #include "qgsgui.h"
28 
29 #include <QPainter>
30 #include <QMouseEvent>
31 #include <QMenu>
32 #include <QClipboard>
33 #include <QDrag>
34 #include <QStyle>
35 #include <QStyleOptionToolButton>
36 #include <QWidgetAction>
37 #include <QScreen>
38 #include <QLabel>
39 #include <QGridLayout>
40 #include <QPushButton>
41 #include <QBuffer>
42 
43 QgsColorButton::QgsColorButton( QWidget *parent, const QString &cdt, QgsColorSchemeRegistry *registry )
44  : QToolButton( parent )
45  , mColorDialogTitle( cdt.isEmpty() ? tr( "Select Color" ) : cdt )
46  , mNoColorString( tr( "No color" ) )
47 {
48  //if a color scheme registry was specified, use it, otherwise use the global instance
49  mColorSchemeRegistry = registry ? registry : QgsApplication::colorSchemeRegistry();
50 
51  setAcceptDrops( true );
52  setMinimumSize( QSize( 24, 16 ) );
53  connect( this, &QAbstractButton::clicked, this, &QgsColorButton::buttonClicked );
54 
55  //setup drop-down menu
56  mMenu = new QMenu( this );
57  connect( mMenu, &QMenu::aboutToShow, this, &QgsColorButton::prepareMenu );
58  setMenu( mMenu );
59  setPopupMode( QToolButton::MenuButtonPopup );
60 
61 #ifdef Q_OS_WIN
62  mMinimumSize = QSize( 120, 22 );
63 #else
64  mMinimumSize = QSize( 120, 28 );
65 #endif
66 
67  mMinimumSize.setHeight( std::max( static_cast<int>( Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 1.1 ), mMinimumSize.height() ) );
68 
69  // If project colors change, we need to redraw the button, as it may be set to follow a project color
71  {
73  } );
74 }
75 
77 {
78  return mMinimumSize;
79 }
80 
82 {
83  return mMinimumSize;
84 }
85 
87 {
88  static QPixmap sTranspBkgrd;
89 
90  if ( sTranspBkgrd.isNull() )
91  sTranspBkgrd = QgsApplication::getThemePixmap( QStringLiteral( "/transp-background_8x8.png" ) );
92 
93  return sTranspBkgrd;
94 }
95 
96 void QgsColorButton::showColorDialog()
97 {
99  if ( panel && panel->dockMode() )
100  {
101  const QColor currentColor = color();
103  colorWidget->setPanelTitle( mColorDialogTitle );
104  colorWidget->setAllowOpacity( mAllowOpacity );
105 
106  if ( currentColor.isValid() )
107  {
108  colorWidget->setPreviousColor( currentColor );
109  }
110 
111  connect( colorWidget, &QgsCompoundColorWidget::currentColorChanged, this, &QgsColorButton::setValidTemporaryColor );
112  panel->openPanel( colorWidget );
113  return;
114  }
115 
116  QColor newColor;
117  const QgsSettings settings;
118 
119  // first check if we need to use the limited native dialogs
120  const bool useNative = settings.value( QStringLiteral( "qgis/native_color_dialogs" ), false ).toBool();
121  if ( useNative )
122  {
123  // why would anyone want this? who knows.... maybe the limited nature of native dialogs helps ease the transition for MapInfo users?
124  newColor = QColorDialog::getColor( color(), this, mColorDialogTitle, mAllowOpacity ? QColorDialog::ShowAlphaChannel : ( QColorDialog::ColorDialogOption )0 );
125  }
126  else
127  {
128  QgsColorDialog dialog( this, Qt::WindowFlags(), color() );
129  dialog.setTitle( mColorDialogTitle );
130  dialog.setAllowOpacity( mAllowOpacity );
131 
132  if ( dialog.exec() )
133  {
134  newColor = dialog.color();
135  }
136  }
137 
138  if ( newColor.isValid() )
139  {
140  setValidColor( newColor );
141  }
142 
143  // reactivate button's window
144  activateWindow();
145 }
146 
148 {
149  if ( !mDefaultColor.isValid() )
150  {
151  return;
152  }
153 
154  setColor( mDefaultColor );
155 }
156 
158 {
159  setColor( QColor() );
160  emit cleared();
161 }
162 
164 {
165  linkToProjectColor( QString() );
166  emit unlinked();
167 }
168 
169 bool QgsColorButton::event( QEvent *e )
170 {
171  if ( e->type() == QEvent::ToolTip )
172  {
173  QColor c = linkedProjectColor();
174  const bool isProjectColor = c.isValid();
175  if ( !isProjectColor )
176  c = mColor;
177 
178  const QString name = c.name();
179  const int hue = c.hue();
180  const int value = c.value();
181  const int saturation = c.saturation();
182 
183  // create very large preview swatch
184  const int width = static_cast< int >( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 23 );
185  const int height = static_cast< int >( width / 1.61803398875 ); // golden ratio
186 
187  const int margin = static_cast< int >( height * 0.1 );
188  QImage icon = QImage( width + 2 * margin, height + 2 * margin, QImage::Format_ARGB32 );
189  icon.fill( Qt::transparent );
190 
191  QPainter p;
192  p.begin( &icon );
193 
194  //start with checkboard pattern
195  const QBrush checkBrush = QBrush( transparentBackground() );
196  p.setPen( Qt::NoPen );
197  p.setBrush( checkBrush );
198  p.drawRect( margin, margin, width, height );
199 
200  //draw color over pattern
201  p.setBrush( QBrush( c ) );
202 
203  //draw border
204  p.setPen( QColor( 197, 197, 197 ) );
205  p.drawRect( margin, margin, width, height );
206  p.end();
207 
208  QByteArray data;
209  QBuffer buffer( &data );
210  icon.save( &buffer, "PNG", 100 );
211 
212  const QString info = ( isProjectColor ? QStringLiteral( "<p>%1: %2</p>" ).arg( tr( "Linked color" ), mLinkedColorName ) : QString() )
213  + QStringLiteral( "<b>HEX</b> %1<br>"
214  "<b>RGB</b> %2<br>"
215  "<b>HSV</b> %3,%4,%5<p>"
216  "<img src='data:image/png;base64, %0'>" ).arg( QString( data.toBase64() ), name,
218  .arg( hue ).arg( saturation ).arg( value );
219  setToolTip( info );
220  }
221  return QToolButton::event( e );
222 }
223 
225 {
226  QColor noColor = QColor( mColor );
227  noColor.setAlpha( 0 );
228  setColor( noColor );
229 }
230 
231 void QgsColorButton::mousePressEvent( QMouseEvent *e )
232 {
233  if ( mPickingColor )
234  {
235  //don't show dialog if in color picker mode
236  e->accept();
237  return;
238  }
239 
240  if ( e->button() == Qt::RightButton )
241  {
242  QToolButton::showMenu();
243  return;
244  }
245  else if ( e->button() == Qt::LeftButton )
246  {
247  mDragStartPosition = e->pos();
248  }
249  QToolButton::mousePressEvent( e );
250 }
251 
252 bool QgsColorButton::colorFromMimeData( const QMimeData *mimeData, QColor &resultColor )
253 {
254  bool hasAlpha = false;
255  QColor mimeColor = QgsSymbolLayerUtils::colorFromMimeData( mimeData, hasAlpha );
256 
257  if ( mimeColor.isValid() )
258  {
259  if ( !mAllowOpacity )
260  {
261  //remove alpha channel
262  mimeColor.setAlpha( 255 );
263  }
264  else if ( !hasAlpha )
265  {
266  //mime color has no explicit alpha component, so keep existing alpha
267  mimeColor.setAlpha( mColor.alpha() );
268  }
269  resultColor = mimeColor;
270  return true;
271  }
272 
273  //could not get color from mime data
274  return false;
275 }
276 
277 void QgsColorButton::mouseMoveEvent( QMouseEvent *e )
278 {
279  if ( mPickingColor )
280  {
281  setButtonBackground( QgsGui::sampleColor( e->globalPos() ) );
282  e->accept();
283  return;
284  }
285 
286  //handle dragging colors from button
287  QColor c = linkedProjectColor();
288  if ( !c.isValid() )
289  c = mColor;
290 
291  if ( !( e->buttons() & Qt::LeftButton ) || !c.isValid() )
292  {
293  //left button not depressed or no color set, so not a drag
294  QToolButton::mouseMoveEvent( e );
295  return;
296  }
297 
298  if ( ( e->pos() - mDragStartPosition ).manhattanLength() < QApplication::startDragDistance() )
299  {
300  //mouse not moved, so not a drag
301  QToolButton::mouseMoveEvent( e );
302  return;
303  }
304 
305  //user is dragging color
306  QDrag *drag = new QDrag( this );
307  drag->setMimeData( QgsSymbolLayerUtils::colorToMimeData( c ) );
308  drag->setPixmap( QgsColorWidget::createDragIcon( c ) );
309  drag->exec( Qt::CopyAction );
310  setDown( false );
311 }
312 
313 void QgsColorButton::mouseReleaseEvent( QMouseEvent *e )
314 {
315  if ( mPickingColor )
316  {
317  //end color picking operation by sampling the color under cursor
318  stopPicking( e->globalPos() );
319  e->accept();
320  return;
321  }
322 
323  QToolButton::mouseReleaseEvent( e );
324 }
325 
326 void QgsColorButton::stopPicking( QPoint eventPos, bool samplingColor )
327 {
328  //release mouse and keyboard, and reset cursor
329  releaseMouse();
330  releaseKeyboard();
331  QgsApplication::restoreOverrideCursor();
332  setMouseTracking( false );
333  mPickingColor = false;
334 
335  if ( !samplingColor )
336  {
337  //not sampling color, restore old color
339  return;
340  }
341 
342  setColor( QgsGui::sampleColor( eventPos ) );
343  addRecentColor( mColor );
344 }
345 
346 QColor QgsColorButton::linkedProjectColor() const
347 {
348  QList<QgsProjectColorScheme *> projectSchemes;
349  QgsApplication::colorSchemeRegistry()->schemes( projectSchemes );
350  if ( projectSchemes.length() > 0 )
351  {
352  QgsProjectColorScheme *scheme = projectSchemes.at( 0 );
353  const QgsNamedColorList colors = scheme->fetchColors();
354  for ( const auto &color : colors )
355  {
356  if ( color.second.isEmpty() )
357  continue;
358 
359  if ( color.second == mLinkedColorName )
360  {
361  return color.first;
362  }
363  }
364  }
365  return QColor();
366 }
367 
368 void QgsColorButton::keyPressEvent( QKeyEvent *e )
369 {
370  if ( !mPickingColor )
371  {
372  //if not picking a color, use default tool button behavior
373  QToolButton::keyPressEvent( e );
374  return;
375  }
376 
377  //cancel picking, sampling the color if space was pressed
378  stopPicking( QCursor::pos(), e->key() == Qt::Key_Space );
379 }
380 
381 void QgsColorButton::dragEnterEvent( QDragEnterEvent *e )
382 {
383  const bool isProjectColor = linkedProjectColor().isValid();
384  if ( isProjectColor )
385  return;
386 
387  //is dragged data valid color data?
388  QColor mimeColor;
389  if ( colorFromMimeData( e->mimeData(), mimeColor ) )
390  {
391  //if so, we accept the drag, and temporarily change the button's color
392  //to match the dragged color. This gives immediate feedback to the user
393  //that colors can be dropped here
394  e->acceptProposedAction();
395  setButtonBackground( mimeColor );
396  }
397 }
398 
399 void QgsColorButton::dragLeaveEvent( QDragLeaveEvent *e )
400 {
401  Q_UNUSED( e )
402  //reset button color
404 }
405 
406 void QgsColorButton::dropEvent( QDropEvent *e )
407 {
408  const bool isProjectColor = linkedProjectColor().isValid();
409  if ( isProjectColor )
410  return;
411 
412  //is dropped data valid color data?
413  QColor mimeColor;
414  if ( colorFromMimeData( e->mimeData(), mimeColor ) )
415  {
416  //accept drop and set new color
417  e->acceptProposedAction();
418  setColor( mimeColor );
419  addRecentColor( mimeColor );
420  }
421 }
422 
423 void QgsColorButton::wheelEvent( QWheelEvent *event )
424 {
425  if ( mAllowOpacity && isEnabled() && !isNull() )
426  {
427  const double increment = ( ( event->modifiers() & Qt::ControlModifier ) ? 0.01 : 0.1 ) *
428  ( event->angleDelta().y() > 0 ? 1 : -1 );
429  const double alpha = std::min( std::max( 0.0, mColor.alphaF() + increment ), 1.0 );
430  mColor.setAlphaF( alpha );
431 
433  emit colorChanged( mColor );
434  event->accept();
435  }
436  else
437  {
438  QToolButton::wheelEvent( event );
439  }
440 }
441 
442 void QgsColorButton::setValidColor( const QColor &newColor )
443 {
444  if ( newColor.isValid() )
445  {
446  setColor( newColor );
447  addRecentColor( newColor );
448  }
449 }
450 
451 void QgsColorButton::setValidTemporaryColor( const QColor &newColor )
452 {
453  if ( newColor.isValid() )
454  {
455  setColor( newColor );
456  }
457 }
458 
459 QPixmap QgsColorButton::createMenuIcon( const QColor &color, const bool showChecks )
460 {
461  const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
462 
463  //create an icon pixmap
464  QPixmap pixmap( iconSize, iconSize );
465  pixmap.fill( Qt::transparent );
466 
467  QPainter p;
468  p.begin( &pixmap );
469 
470  //start with checkboard pattern
471  if ( showChecks )
472  {
473  const QBrush checkBrush = QBrush( transparentBackground() );
474  p.setPen( Qt::NoPen );
475  p.setBrush( checkBrush );
476  p.drawRect( 0, 0, iconSize - 1, iconSize - 1 );
477  }
478 
479  //draw color over pattern
480  p.setBrush( QBrush( color ) );
481 
482  //draw border
483  p.setPen( QColor( 197, 197, 197 ) );
484  p.drawRect( 0, 0, iconSize - 1, iconSize - 1 );
485  p.end();
486  return pixmap;
487 }
488 
489 void QgsColorButton::buttonClicked()
490 {
491  if ( linkedProjectColor().isValid() )
492  {
493  QToolButton::showMenu();
494  }
495  else
496  {
497  switch ( mBehavior )
498  {
499  case ShowDialog:
500  showColorDialog();
501  return;
502  case SignalOnly:
503  emit colorClicked( mColor );
504  return;
505  }
506  }
507 }
508 
509 void QgsColorButton::prepareMenu()
510 {
511  //we need to tear down and rebuild this menu every time it is shown. Otherwise the space allocated to any
512  //QgsColorSwatchGridAction is not recalculated by Qt and the swatch grid may not be the correct size
513  //for the number of colors shown in the grid. Note that we MUST refresh color swatch grids every time this
514  //menu is opened, otherwise color schemes like the recent color scheme grid are meaningless
515  mMenu->clear();
516 
517  const bool isProjectColor = linkedProjectColor().isValid();
518 
519  if ( !isProjectColor )
520  {
521  if ( mShowNull )
522  {
523  QAction *nullAction = new QAction( mNullColorString.isEmpty() ? tr( "Clear Color" ) : mNullColorString, this );
524  nullAction->setIcon( createMenuIcon( Qt::transparent, false ) );
525  mMenu->addAction( nullAction );
526  connect( nullAction, &QAction::triggered, this, &QgsColorButton::setToNull );
527  }
528 
529  //show default color option if set
530  if ( mDefaultColor.isValid() )
531  {
532  QAction *defaultColorAction = new QAction( tr( "Default Color" ), this );
533  defaultColorAction->setIcon( createMenuIcon( mDefaultColor ) );
534  mMenu->addAction( defaultColorAction );
535  connect( defaultColorAction, &QAction::triggered, this, &QgsColorButton::setToDefaultColor );
536  }
537 
538  if ( mShowNoColorOption )
539  {
540  QAction *noColorAction = new QAction( mNoColorString, this );
541  noColorAction->setIcon( createMenuIcon( Qt::transparent, false ) );
542  mMenu->addAction( noColorAction );
543  connect( noColorAction, &QAction::triggered, this, &QgsColorButton::setToNoColor );
544  }
545 
546  mMenu->addSeparator();
547  QgsColorWheel *colorWheel = new QgsColorWheel( mMenu );
548  colorWheel->setColor( color() );
549  QgsColorWidgetAction *colorAction = new QgsColorWidgetAction( colorWheel, mMenu, mMenu );
550  colorAction->setDismissOnColorSelection( false );
551  connect( colorAction, &QgsColorWidgetAction::colorChanged, this, &QgsColorButton::setColor );
552  mMenu->addAction( colorAction );
553  if ( mAllowOpacity )
554  {
556  alphaRamp->setColor( color() );
557  QgsColorWidgetAction *alphaAction = new QgsColorWidgetAction( alphaRamp, mMenu, mMenu );
558  alphaAction->setDismissOnColorSelection( false );
559  connect( alphaAction, &QgsColorWidgetAction::colorChanged, this, &QgsColorButton::setColor );
560  connect( alphaAction, &QgsColorWidgetAction::colorChanged, colorWheel, [colorWheel]( const QColor & color ) { colorWheel->setColor( color, false ); }
561  );
562  connect( colorAction, &QgsColorWidgetAction::colorChanged, alphaRamp, [alphaRamp]( const QColor & color ) { alphaRamp->setColor( color, false ); }
563  );
564  mMenu->addAction( alphaAction );
565  }
566 
567  if ( mColorSchemeRegistry )
568  {
569  //get schemes with ShowInColorButtonMenu flag set
570  QList< QgsColorScheme * > schemeList = mColorSchemeRegistry->schemes( QgsColorScheme::ShowInColorButtonMenu );
571  QList< QgsColorScheme * >::iterator it = schemeList.begin();
572  for ( ; it != schemeList.end(); ++it )
573  {
574  QgsColorSwatchGridAction *colorAction = new QgsColorSwatchGridAction( *it, mMenu, mContext, this );
575  colorAction->setBaseColor( mColor );
576  mMenu->addAction( colorAction );
577  connect( colorAction, &QgsColorSwatchGridAction::colorChanged, this, &QgsColorButton::setValidColor );
578  connect( colorAction, &QgsColorSwatchGridAction::colorChanged, this, &QgsColorButton::addRecentColor );
579  }
580  }
581 
582  mMenu->addSeparator();
583  }
584 
585  if ( isProjectColor )
586  {
587  QAction *unlinkAction = new QAction( tr( "Unlink Color" ), mMenu );
588  mMenu->addAction( unlinkAction );
589  connect( unlinkAction, &QAction::triggered, this, &QgsColorButton::unlink );
590  }
591 
592  QAction *copyColorAction = new QAction( tr( "Copy Color" ), this );
593  mMenu->addAction( copyColorAction );
594  connect( copyColorAction, &QAction::triggered, this, &QgsColorButton::copyColor );
595 
596  if ( !isProjectColor )
597  {
598  QAction *pasteColorAction = new QAction( tr( "Paste Color" ), this );
599  //enable or disable paste action based on current clipboard contents. We always show the paste
600  //action, even if it's disabled, to give hint to the user that pasting colors is possible
601  QColor clipColor;
602  if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor ) )
603  {
604  pasteColorAction->setIcon( createMenuIcon( clipColor ) );
605  }
606  else
607  {
608  pasteColorAction->setEnabled( false );
609  }
610  mMenu->addAction( pasteColorAction );
611  connect( pasteColorAction, &QAction::triggered, this, &QgsColorButton::pasteColor );
612 
613  QAction *pickColorAction = new QAction( tr( "Pick Color" ), this );
614  mMenu->addAction( pickColorAction );
615  connect( pickColorAction, &QAction::triggered, this, &QgsColorButton::activatePicker );
616 
617  QAction *chooseColorAction = new QAction( tr( "Choose Color…" ), this );
618  mMenu->addAction( chooseColorAction );
619  connect( chooseColorAction, &QAction::triggered, this, &QgsColorButton::showColorDialog );
620  }
621 }
622 
624 {
625  if ( e->type() == QEvent::EnabledChange )
626  {
628  }
629  QToolButton::changeEvent( e );
630 }
631 
632 #if 0 // causes too many cyclical updates, but may be needed on some platforms
633 void QgsColorButton::paintEvent( QPaintEvent *e )
634 {
635  QToolButton::paintEvent( e );
636 
637  if ( !mBackgroundSet )
638  {
640  }
641 }
642 #endif
643 
644 void QgsColorButton::showEvent( QShowEvent *e )
645 {
647  QToolButton::showEvent( e );
648 }
649 
650 void QgsColorButton::resizeEvent( QResizeEvent *event )
651 {
652  QToolButton::resizeEvent( event );
653  //recalculate icon size and redraw icon
654  mIconSize = QSize();
656 }
657 
658 void QgsColorButton::setColor( const QColor &color )
659 {
660  const QColor oldColor = mColor;
661  mColor = color;
662 
663  // handle when initially set color is same as default (Qt::black); consider it a color change
664  if ( oldColor != mColor || ( mColor == QColor( Qt::black ) && !mColorSet ) )
665  {
667  if ( isEnabled() )
668  {
669  // TODO: May be beneficial to have the option to set color without emitting this signal.
670  // Now done by blockSignals( bool ) where button is used
671  emit colorChanged( mColor );
672  }
673  }
674  mColorSet = true;
675 }
676 
677 void QgsColorButton::addRecentColor( const QColor &color )
678 {
680 }
681 
682 void QgsColorButton::setButtonBackground( const QColor &color )
683 {
684  QColor backgroundColor = color;
685  bool isProjectColor = false;
686  if ( !backgroundColor.isValid() && !mLinkedColorName.isEmpty() )
687  {
688  backgroundColor = linkedProjectColor();
689  isProjectColor = backgroundColor.isValid();
690  if ( !isProjectColor )
691  {
692  mLinkedColorName.clear(); //color has been deleted, renamed, etc...
693  emit unlinked();
694  }
695  }
696  if ( !backgroundColor.isValid() )
697  {
698  backgroundColor = mColor;
699  }
700 
701  QSize currentIconSize;
702  //icon size is button size with a small margin
703  if ( menu() )
704  {
705  if ( !mIconSize.isValid() )
706  {
707  //calculate size of push button part of widget (ie, without the menu drop-down button part)
708  QStyleOptionToolButton opt;
709  initStyleOption( &opt );
710  const QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton,
711  this );
712  //make sure height of icon looks good under different platforms
713 #ifdef Q_OS_WIN
714  mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
715 #else
716  mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
717 #endif
718  }
719  currentIconSize = mIconSize;
720  }
721  else
722  {
723  //no menu
724 #ifdef Q_OS_WIN
725  currentIconSize = QSize( width() - 10, height() - 6 );
726 #else
727  currentIconSize = QSize( width() - 10, height() - 12 );
728 #endif
729  }
730 
731  if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
732  {
733  return;
734  }
735 
736  //create an icon pixmap
737  QPixmap pixmap( currentIconSize );
738  pixmap.fill( Qt::transparent );
739 
740  if ( backgroundColor.isValid() )
741  {
742  const QRect rect( 0, 0, currentIconSize.width(), currentIconSize.height() );
743  QPainter p;
744  p.begin( &pixmap );
745  p.setRenderHint( QPainter::Antialiasing );
746  p.setPen( Qt::NoPen );
747  if ( mAllowOpacity && backgroundColor.alpha() < 255 )
748  {
749  //start with checkboard pattern
750  const QBrush checkBrush = QBrush( transparentBackground() );
751  p.setBrush( checkBrush );
752  p.drawRoundedRect( rect, 3, 3 );
753  }
754 
755  //draw semi-transparent color on top
756  p.setBrush( backgroundColor );
757  p.drawRoundedRect( rect, 3, 3 );
758  p.end();
759  }
760 
761  setIconSize( currentIconSize );
762  setIcon( pixmap );
763 }
764 
766 {
767  //copy color
768  QColor c = linkedProjectColor();
769  if ( !c.isValid() )
770  c = mColor;
771  QApplication::clipboard()->setMimeData( QgsSymbolLayerUtils::colorToMimeData( c ) );
772 }
773 
775 {
776  QColor clipColor;
777  if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor ) )
778  {
779  //paste color
780  setColor( clipColor );
781  addRecentColor( clipColor );
782  }
783 }
784 
786 {
787  //activate picker color
788  // Store current color
789  mCurrentColor = mColor;
790  QApplication::setOverrideCursor( QgsApplication::getThemeCursor( QgsApplication::Cursor::Sampler ) );
791  grabMouse();
792  grabKeyboard();
793  mPickingColor = true;
794  setMouseTracking( true );
795 }
796 
797 QColor QgsColorButton::color() const
798 {
799  QColor c = linkedProjectColor();
800  if ( !c.isValid() )
801  c = mColor;
802  return c;
803 }
804 
805 void QgsColorButton::setAllowOpacity( const bool allow )
806 {
807  mAllowOpacity = allow;
808 }
809 
810 void QgsColorButton::setColorDialogTitle( const QString &title )
811 {
812  mColorDialogTitle = title;
813 }
814 
815 QString QgsColorButton::colorDialogTitle() const
816 {
817  return mColorDialogTitle;
818 }
819 
820 void QgsColorButton::setShowMenu( const bool showMenu )
821 {
822  mShowMenu = showMenu;
823  setMenu( showMenu ? mMenu : nullptr );
824  setPopupMode( showMenu ? QToolButton::MenuButtonPopup : QToolButton::DelayedPopup );
825  //force recalculation of icon size
826  mIconSize = QSize();
828 }
829 
831 {
832  mBehavior = behavior;
833 }
834 
835 void QgsColorButton::setDefaultColor( const QColor &color )
836 {
837  mDefaultColor = color;
838 }
839 
840 void QgsColorButton::setShowNull( bool showNull, const QString &nullString )
841 {
842  mShowNull = showNull;
843  mNullColorString = nullString;
844 }
845 
847 {
848  return mShowNull;
849 }
850 
852 {
853  return !mColor.isValid();
854 }
855 
856 void QgsColorButton::linkToProjectColor( const QString &name )
857 {
858  mLinkedColorName = name;
860 }
861 
QgsColorButton::SignalOnly
@ SignalOnly
Emit colorClicked signal only, no dialog.
Definition: qgscolorbutton.h:67
QgsColorButton::dropEvent
void dropEvent(QDropEvent *e) override
Reimplemented to accept dropped colors.
Definition: qgscolorbutton.cpp:406
QgsCompoundColorWidget::setAllowOpacity
void setAllowOpacity(bool allowOpacity)
Sets whether opacity modification (transparency) is permitted for the color dialog.
Definition: qgscompoundcolorwidget.cpp:303
qgscolorbutton.h
QgsColorButton::setButtonBackground
void setButtonBackground(const QColor &color=QColor())
Sets the background pixmap for the button based upon color and transparency.
Definition: qgscolorbutton.cpp:682
QgsSymbolLayerUtils::encodeColor
static QString encodeColor(const QColor &color)
Definition: qgssymbollayerutils.cpp:64
QgsSymbolLayerUtils::colorToMimeData
static QMimeData * colorToMimeData(const QColor &color)
Creates mime data from a color.
Definition: qgssymbollayerutils.cpp:3497
QgsColorRampWidget::Horizontal
@ Horizontal
Horizontal ramp.
Definition: qgscolorwidgets.h:495
QgsColorButton::dragEnterEvent
void dragEnterEvent(QDragEnterEvent *e) override
Reimplemented to accept dragged colors.
Definition: qgscolorbutton.cpp:381
QgsGui::sampleColor
static QColor sampleColor(QPoint point)
Samples the color on screen at the specified global point (pixel).
Definition: qgsgui.cpp:237
QgsSettings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Definition: qgssettings.cpp:161
QgsColorButton::isNull
bool isNull() const
Returns true if the current color is null.
Definition: qgscolorbutton.cpp:851
QgsPanelWidget::findParentPanel
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
Definition: qgspanelwidget.cpp:54
QgsColorButton::setBehavior
void setBehavior(Behavior behavior)
Sets the behavior for when the button is clicked.
Definition: qgscolorbutton.cpp:830
QgsColorButton::keyPressEvent
void keyPressEvent(QKeyEvent *e) override
Reimplemented to allow canceling color pick via keypress, and sample via space bar press.
Definition: qgscolorbutton.cpp:368
QgsColorSwatchGridAction
A color swatch grid which can be embedded into a menu.
Definition: qgscolorswatchgrid.h:189
qgscolorswatchgrid.h
QgsColorButton::setColor
void setColor(const QColor &color)
Sets the current color for the button.
Definition: qgscolorbutton.cpp:658
qgsgui.h
QgsColorSwatchGridAction::setBaseColor
void setBaseColor(const QColor &baseColor)
Sets the base color for the color grid.
Definition: qgscolorswatchgrid.cpp:413
QgsApplication::getThemeCursor
static QCursor getThemeCursor(Cursor cursor)
Helper to get a theme cursor.
Definition: qgsapplication.cpp:762
qgssymbollayerutils.h
QgsNamedColorList
QList< QPair< QColor, QString > > QgsNamedColorList
List of colors paired with a friendly display name identifying the color.
Definition: qgscolorscheme.h:34
QgsPanelWidget::openPanel
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
Definition: qgspanelwidget.cpp:84
QgsColorButton::unlink
void unlink()
Unlinks the button from a project color.
Definition: qgscolorbutton.cpp:163
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:480
QgsApplication::colorSchemeRegistry
static QgsColorSchemeRegistry * colorSchemeRegistry()
Returns the application's color scheme registry, used for managing color schemes.
Definition: qgsapplication.cpp:2310
QgsProjectColorScheme
A color scheme which contains project specific colors set through project properties dialog.
Definition: qgscolorscheme.h:299
QgsColorButton::unlinked
void unlinked()
Emitted when the color is unlinked, e.g.
QgsSettings
This class is a composition of two QSettings instances:
Definition: qgssettings.h:61
QgsColorDialog
A custom QGIS dialog for selecting a color. Has many improvements over the standard Qt color picker d...
Definition: qgscolordialog.h:36
QgsColorButton::setDefaultColor
void setDefaultColor(const QColor &color)
Sets the default color for the button, which is shown in the button's drop-down menu for the "default...
Definition: qgscolorbutton.cpp:835
qgscolorwidgets.h
QgsColorRampWidget
A color ramp widget. This widget consists of an interactive box filled with a color which varies alon...
Definition: qgscolorwidgets.h:484
QgsColorButton::showMenu
bool showMenu
Definition: qgscolorbutton.h:52
QgsSymbolLayerUtils::colorFromMimeData
static QColor colorFromMimeData(const QMimeData *data, bool &hasAlpha)
Attempts to parse mime data as a color.
Definition: qgssymbollayerutils.cpp:3507
QgsPanelWidget::dockMode
bool dockMode()
Returns the dock mode state.
Definition: qgspanelwidget.h:93
QgsColorButton::Behavior
Behavior
Specifies the behavior when the button is clicked.
Definition: qgscolorbutton.h:64
QgsColorButton::event
bool event(QEvent *e) override
Definition: qgscolorbutton.cpp:169
QgsCompoundColorWidget::setPreviousColor
void setPreviousColor(const QColor &color)
Sets the color to show in an optional "previous color" section.
Definition: qgscompoundcolorwidget.cpp:732
QgsColorButton::wheelEvent
void wheelEvent(QWheelEvent *event) override
Definition: qgscolorbutton.cpp:423
QgsColorButton::mouseReleaseEvent
void mouseReleaseEvent(QMouseEvent *e) override
Reimplemented to allow color picking.
Definition: qgscolorbutton.cpp:313
QgsColorButton::QgsColorButton
QgsColorButton(QWidget *parent=nullptr, const QString &cdt=QString(), QgsColorSchemeRegistry *registry=nullptr)
Construct a new color ramp button.
Definition: qgscolorbutton.cpp:43
QgsGuiUtils::iconSize
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
Definition: qgsguiutils.cpp:264
QgsColorScheme::ShowInColorButtonMenu
@ ShowInColorButtonMenu
Show scheme in color button drop-down menu.
Definition: qgscolorscheme.h:74
QgsColorButton::colorChanged
void colorChanged(const QColor &color)
Emitted whenever a new color is set for the button.
QgsColorButton::resizeEvent
void resizeEvent(QResizeEvent *event) override
Definition: qgscolorbutton.cpp:650
QgsColorButton::mouseMoveEvent
void mouseMoveEvent(QMouseEvent *e) override
Reimplemented to allow dragging colors from button.
Definition: qgscolorbutton.cpp:277
QgsApplication::getThemePixmap
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.
Definition: qgsapplication.cpp:827
qgsapplication.h
QgsCompoundColorWidget
A custom QGIS widget for selecting a color, including options for selecting colors via hue wheel,...
Definition: qgscompoundcolorwidget.h:33
QgsCompoundColorWidget::LayoutVertical
@ LayoutVertical
Use a narrower, vertically stacked layout.
Definition: qgscompoundcolorwidget.h:44
QgsColorButton::setAllowOpacity
void setAllowOpacity(bool allowOpacity)
Sets whether opacity modification (transparency) is permitted for the color.
Definition: qgscolorbutton.cpp:805
QgsColorButton::linkToProjectColor
void linkToProjectColor(const QString &name)
Sets the button to link to an existing project color, by color name.
Definition: qgscolorbutton.cpp:856
QgsCompoundColorWidget::currentColorChanged
void currentColorChanged(const QColor &color)
Emitted when the dialog's color changes.
QgsColorButton::behavior
Behavior behavior
Definition: qgscolorbutton.h:53
QgsColorWidget::setColor
virtual void setColor(const QColor &color, bool emitSignals=false)
Sets the color for the widget.
Definition: qgscolorwidgets.cpp:347
QgsPanelWidget
Base class for any widget that can be shown as a inline panel.
Definition: qgspanelwidget.h:29
QgsColorWidgetAction::setDismissOnColorSelection
void setDismissOnColorSelection(bool dismiss)
Sets whether the parent menu should be dismissed and closed when a color is selected from the action'...
Definition: qgscolorwidgets.h:240
QgsColorWheel
A color wheel widget. This widget consists of an outer ring which allows for hue selection,...
Definition: qgscolorwidgets.h:289
QgsColorButton::createMenuIcon
static QPixmap createMenuIcon(const QColor &color, bool showChecks=true)
Creates an icon for displaying a color in a drop-down menu.
Definition: qgscolorbutton.cpp:459
QgsProject::projectColorsChanged
void projectColorsChanged()
Emitted whenever the project's color scheme has been changed.
QgsColorWidget::Alpha
@ Alpha
Alpha component (opacity) of color.
Definition: qgscolorwidgets.h:57
QgsColorButton::color
QColor color
Definition: qgscolorbutton.h:50
QgsColorButton::setToDefaultColor
void setToDefaultColor()
Sets color to the button's default color, if set.
Definition: qgscolorbutton.cpp:147
QgsColorButton::sizeHint
QSize sizeHint() const override
Definition: qgscolorbutton.cpp:81
QgsColorWidgetAction
An action containing a color widget, which can be embedded into a menu.
Definition: qgscolorwidgets.h:213
QgsColorWheel::setColor
void setColor(const QColor &color, bool emitSignals=false) override
Definition: qgscolorwidgets.cpp:483
QgsColorButton::changeEvent
void changeEvent(QEvent *e) override
Definition: qgscolorbutton.cpp:623
Qgis::UI_SCALE_FACTOR
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition: qgis.h:2043
QgsColorButton::pasteColor
void pasteColor()
Pastes a color from the clipboard to the color button.
Definition: qgscolorbutton.cpp:774
QgsColorButton::colorClicked
void colorClicked(const QColor &color)
Emitted when the button is clicked, if the button's behavior is set to SignalOnly.
QgsPanelWidget::setPanelTitle
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
Definition: qgspanelwidget.h:44
QgsColorButton::dragLeaveEvent
void dragLeaveEvent(QDragLeaveEvent *e) override
Reimplemented to reset button appearance after drag leave.
Definition: qgscolorbutton.cpp:399
QgsColorSchemeRegistry
Registry of color schemes.
Definition: qgscolorschemeregistry.h:34
QgsColorButton::setToNoColor
void setToNoColor()
Sets color to a totally transparent color.
Definition: qgscolorbutton.cpp:224
QgsColorButton::transparentBackground
static const QPixmap & transparentBackground()
Returns a checkboard pattern pixmap for use as a background to transparent colors.
Definition: qgscolorbutton.cpp:86
qgscolordialog.h
QgsColorButton::setShowNull
void setShowNull(bool showNull, const QString &nullString=QString())
Sets whether a set to null (clear) option is shown in the button's drop-down menu.
Definition: qgscolorbutton.cpp:840
QgsColorButton::colorDialogTitle
QString colorDialogTitle
Definition: qgscolorbutton.h:49
c
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
Definition: porting_processing.dox:1
QgsColorButton::minimumSizeHint
QSize minimumSizeHint() const override
Definition: qgscolorbutton.cpp:76
QgsColorSchemeRegistry::schemes
QList< QgsColorScheme * > schemes() const
Returns all color schemes in the registry.
Definition: qgscolorschemeregistry.cpp:88
QgsRecentColorScheme::addRecentColor
static void addRecentColor(const QColor &color)
Adds a color to the list of recent colors.
Definition: qgscolorscheme.cpp:68
QgsColorSwatchGridAction::colorChanged
void colorChanged(const QColor &color)
Emitted when a color has been selected from the widget.
qgssettings.h
qgscolorschemeregistry.h
QgsColorWidgetAction::colorChanged
void colorChanged(const QColor &color)
Emitted when a color has been selected from the widget.
QgsProjectColorScheme::fetchColors
QgsNamedColorList fetchColors(const QString &context=QString(), const QColor &baseColor=QColor()) override
Gets a list of colors from the scheme.
Definition: qgscolorscheme.cpp:194
QgsColorButton::copyColor
void copyColor()
Copies the current color to the clipboard.
Definition: qgscolorbutton.cpp:765
QgsColorButton::cleared
void cleared()
Emitted when the color is cleared (set to null).
QgsColorButton::setShowMenu
void setShowMenu(bool showMenu)
Sets whether the drop-down menu should be shown for the button.
Definition: qgscolorbutton.cpp:820
QgsColorButton::setToNull
void setToNull()
Sets color to null.
Definition: qgscolorbutton.cpp:157
qgslogger.h
qgsguiutils.h
QgsGuiUtils::scaleIconSize
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
Definition: qgsguiutils.cpp:259
QgsColorButton::showEvent
void showEvent(QShowEvent *e) override
Definition: qgscolorbutton.cpp:644
QgsColorButton::ShowDialog
@ ShowDialog
Show a color picker dialog when clicked.
Definition: qgscolorbutton.h:66
QgsColorButton::showNull
bool showNull() const
Returns whether the set to null (clear) option is shown in the button's drop-down menu.
Definition: qgscolorbutton.cpp:846
qgsproject.h
QgsColorButton::mousePressEvent
void mousePressEvent(QMouseEvent *e) override
Reimplemented to detect right mouse button clicks on the color button and allow dragging colors.
Definition: qgscolorbutton.cpp:231
QgsColorButton::activatePicker
void activatePicker()
Activates the color picker tool, which allows for sampling a color from anywhere on the screen.
Definition: qgscolorbutton.cpp:785
QgsColorButton::setColorDialogTitle
void setColorDialogTitle(const QString &title)
Set the title for the color chooser dialog window.
Definition: qgscolorbutton.cpp:810
QgsColorWidget::createDragIcon
static QPixmap createDragIcon(const QColor &color)
Create an icon for dragging colors.
Definition: qgscolorwidgets.cpp:61