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