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