QGIS API Documentation  3.13.0-Master (740be229cb)
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, nullptr, 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 
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 
803 QString QgsColorButton::colorDialogTitle() const
804 {
805  return mColorDialogTitle;
806 }
807 
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 
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 
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
A color swatch grid which can be embedded into a menu.
void setToNoColor()
Sets color to a totally transparent color.
void keyPressEvent(QKeyEvent *e) override
Reimplemented to allow canceling color pick via keypress, and sample via space bar press...
static QPixmap createMenuIcon(const QColor &color, bool showChecks=true)
Creates an icon for displaying a color in a drop-down menu.
QgsColorButton(QWidget *parent=nullptr, const QString &cdt=QString(), QgsColorSchemeRegistry *registry=nullptr)
Construct a new color ramp button.
bool isNull() const
Returns true if the current color is null.
void cleared()
Emitted when the color is cleared (set to null).
Emit colorClicked signal only, no dialog.
void setButtonBackground(const QColor &color=QColor())
Sets the background pixmap for the button based upon color and transparency.
QColor color() const
Returns the currently selected color.
bool dockMode()
Returns the dock mode state.
A color scheme which contains project specific colors set through project properties dialog...
Registry of color schemes.
void setToNull()
Sets color to null.
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition: qgis.h:182
This class is a composition of two QSettings instances:
Definition: qgssettings.h:61
bool event(QEvent *e) override
bool showMenu() const
Returns whether the drop-down menu is shown for the button.
virtual void setColor(const QColor &color, bool emitSignals=false)
Sets the color for the widget.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly...
Show a color picker dialog when clicked.
void mousePressEvent(QMouseEvent *e) override
Reimplemented to detect right mouse button clicks on the color button and allow dragging colors...
void colorClicked(const QColor &color)
Emitted when the button is clicked, if the button&#39;s behavior is set to SignalOnly.
void colorChanged(const QColor &color)
Emitted when a color has been selected from the widget.
void projectColorsChanged()
Emitted whenever the project&#39;s color scheme has been changed.
void setShowNull(bool showNull, const QString &nullString=QString())
Sets whether a set to null (clear) option is shown in the button&#39;s drop-down menu.
Base class for any widget that can be shown as a inline panel.
void mouseReleaseEvent(QMouseEvent *e) override
Reimplemented to allow color picking.
void resizeEvent(QResizeEvent *event) override
bool showNull() const
Returns whether the set to null (clear) option is shown in the button&#39;s drop-down menu...
QSize minimumSizeHint() const override
void unlink()
Unlinks the button from a project color.
Show scheme in color button drop-down menu.
void dragLeaveEvent(QDragLeaveEvent *e) override
Reimplemented to reset button appearance after drag leave.
void pasteColor()
Pastes a color from the clipboard to the color button.
void setAllowOpacity(bool allowOpacity)
Sets whether opacity modification (transparency) is permitted for the color dialog.
static QPixmap getThemePixmap(const QString &name)
Helper to get a theme icon as a pixmap.
QSize sizeHint() const override
void activatePicker()
Activates the color picker tool, which allows for sampling a color from anywhere on the screen...
static QString encodeColor(const QColor &color)
void changeEvent(QEvent *e) override
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
QList< QgsColorScheme * > schemes() const
Returns all color schemes in the registry.
void setTitle(const QString &title)
Sets the title for the color dialog.
A color wheel widget.
void linkToProjectColor(const QString &name)
Sets the button to link to an existing project color, by color name.
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget...
A custom QGIS widget for selecting a color, including options for selecting colors via hue wheel...
Alpha component (opacity) of color.
Behavior
Specifies the behavior when the button is clicked.
QString colorDialogTitle() const
Returns the title for the color chooser dialog window.
void setColorDialogTitle(const QString &title)
Set the title for the color chooser dialog window.
void setToDefaultColor()
Sets color to the button&#39;s default color, if set.
QList< QPair< QColor, QString > > QgsNamedColorList
List of colors paired with a friendly display name identifying the color.
A color ramp widget.
void setDefaultColor(const QColor &color)
Sets the default color for the button, which is shown in the button&#39;s drop-down menu for the "default...
void setShowMenu(bool showMenu)
Sets whether the drop-down menu should be shown for the button.
void setColor(const QColor &color, bool emitSignals=false) override
void mouseMoveEvent(QMouseEvent *e) override
Reimplemented to allow dragging colors from button.
Behavior behavior() const
Returns the behavior for when the button is clicked.
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window&#39;s toolbar icons.
static void addRecentColor(const QColor &color)
Adds a color to the list of recent colors.
QColor color() const
Returns the current color for the dialog.
void setAllowOpacity(bool allowOpacity)
Sets whether opacity modification (transparency) is permitted for the color dialog.
void setPreviousColor(const QColor &color)
Sets the color to show in an optional "previous color" section.
void colorChanged(const QColor &color)
Emitted whenever a new color is set for the button.
A custom QGIS dialog for selecting a color.
static QgsColorSchemeRegistry * colorSchemeRegistry()
Returns the application&#39;s color scheme registry, used for managing color schemes. ...
void setAllowOpacity(bool allowOpacity)
Sets whether opacity modification (transparency) is permitted for the color.
void unlinked()
Emitted when the color is unlinked, e.g.
void currentColorChanged(const QColor &color)
Emitted when the dialog&#39;s color changes.
An action containing a color widget, which can be embedded into a menu.
static QMimeData * colorToMimeData(const QColor &color)
Creates mime data from a color.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:457
void copyColor()
Copies the current color to the clipboard.
void setColor(const QColor &color)
Sets the current color for the button.
void dragEnterEvent(QDragEnterEvent *e) override
Reimplemented to accept dragged colors.
static QCursor getThemeCursor(Cursor cursor)
Helper to get a theme cursor.
void setDismissOnColorSelection(bool dismiss)
Sets whether the parent menu should be dismissed and closed when a color is selected from the action&#39;...
static const QPixmap & transparentBackground()
Returns a checkboard pattern pixmap for use as a background to transparent colors.
void setBehavior(Behavior behavior)
Sets the behavior for when the button is clicked.
static QPixmap createDragIcon(const QColor &color)
Create an icon for dragging colors.
QgsNamedColorList fetchColors(const QString &context=QString(), const QColor &baseColor=QColor()) override
Gets a list of colors from the scheme.
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
static QColor sampleColor(QPoint point)
Samples the color on screen at the specified global point (pixel).
Definition: qgsgui.cpp:183
void dropEvent(QDropEvent *e) override
Reimplemented to accept dropped colors.
Use a narrower, vertically stacked layout.
void showEvent(QShowEvent *e) override
static QColor colorFromMimeData(const QMimeData *data, bool &hasAlpha)
Attempts to parse mime data as a color.
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 color grid.