QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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 }
164 
166 {
167  linkToProjectColor( QString() );
168  emit unlinked();
169 }
170 
171 bool QgsColorButton::event( QEvent *e )
172 {
173  if ( e->type() == QEvent::ToolTip )
174  {
175  QColor c = linkedProjectColor();
176  bool isProjectColor = c.isValid();
177  if ( !isProjectColor )
178  c = mColor;
179 
180  QString name = c.name();
181  int hue = c.hue();
182  int value = c.value();
183  int saturation = c.saturation();
184 
185  // create very large preview swatch
186  int width = static_cast< int >( Qgis::UI_SCALE_FACTOR * fontMetrics().width( 'X' ) * 23 );
187  int height = static_cast< int >( width / 1.61803398875 ); // golden ratio
188 
189  int margin = static_cast< int >( height * 0.1 );
190  QImage icon = QImage( width + 2 * margin, height + 2 * margin, QImage::Format_ARGB32 );
191  icon.fill( Qt::transparent );
192 
193  QPainter p;
194  p.begin( &icon );
195 
196  //start with checkboard pattern
197  QBrush checkBrush = QBrush( transparentBackground() );
198  p.setPen( Qt::NoPen );
199  p.setBrush( checkBrush );
200  p.drawRect( margin, margin, width, height );
201 
202  //draw color over pattern
203  p.setBrush( QBrush( c ) );
204 
205  //draw border
206  p.setPen( QColor( 197, 197, 197 ) );
207  p.drawRect( margin, margin, width, height );
208  p.end();
209 
210  QByteArray data;
211  QBuffer buffer( &data );
212  icon.save( &buffer, "PNG", 100 );
213 
214  QString info = ( isProjectColor ? QStringLiteral( "<p>%1: %2</p>" ).arg( tr( "Linked color" ), mLinkedColorName ) : QString() )
215  + QStringLiteral( "<b>HEX</b> %1<br>"
216  "<b>RGB</b> %2<br>"
217  "<b>HSV</b> %3,%4,%5<p>"
218  "<img src='data:image/png;base64, %0'>" ).arg( QString( data.toBase64() ), name,
220  .arg( hue ).arg( saturation ).arg( value );
221  setToolTip( info );
222  }
223  return QToolButton::event( e );
224 }
225 
227 {
228  if ( mAllowOpacity )
229  {
230  QColor noColor = QColor( mColor );
231  noColor.setAlpha( 0 );
232  setColor( noColor );
233  }
234 }
235 
236 void QgsColorButton::mousePressEvent( QMouseEvent *e )
237 {
238  if ( mPickingColor )
239  {
240  //don't show dialog if in color picker mode
241  e->accept();
242  return;
243  }
244 
245  if ( e->button() == Qt::RightButton )
246  {
247  QToolButton::showMenu();
248  return;
249  }
250  else if ( e->button() == Qt::LeftButton )
251  {
252  mDragStartPosition = e->pos();
253  }
254  QToolButton::mousePressEvent( e );
255 }
256 
257 bool QgsColorButton::colorFromMimeData( const QMimeData *mimeData, QColor &resultColor )
258 {
259  bool hasAlpha = false;
260  QColor mimeColor = QgsSymbolLayerUtils::colorFromMimeData( mimeData, hasAlpha );
261 
262  if ( mimeColor.isValid() )
263  {
264  if ( !mAllowOpacity )
265  {
266  //remove alpha channel
267  mimeColor.setAlpha( 255 );
268  }
269  else if ( !hasAlpha )
270  {
271  //mime color has no explicit alpha component, so keep existing alpha
272  mimeColor.setAlpha( mColor.alpha() );
273  }
274  resultColor = mimeColor;
275  return true;
276  }
277 
278  //could not get color from mime data
279  return false;
280 }
281 
282 void QgsColorButton::mouseMoveEvent( QMouseEvent *e )
283 {
284  if ( mPickingColor )
285  {
286  setButtonBackground( QgsGui::sampleColor( e->globalPos() ) );
287  e->accept();
288  return;
289  }
290 
291  //handle dragging colors from button
292  QColor c = linkedProjectColor();
293  if ( !c.isValid() )
294  c = mColor;
295 
296  if ( !( e->buttons() & Qt::LeftButton ) || !c.isValid() )
297  {
298  //left button not depressed or no color set, so not a drag
299  QToolButton::mouseMoveEvent( e );
300  return;
301  }
302 
303  if ( ( e->pos() - mDragStartPosition ).manhattanLength() < QApplication::startDragDistance() )
304  {
305  //mouse not moved, so not a drag
306  QToolButton::mouseMoveEvent( e );
307  return;
308  }
309 
310  //user is dragging color
311  QDrag *drag = new QDrag( this );
312  drag->setMimeData( QgsSymbolLayerUtils::colorToMimeData( c ) );
313  drag->setPixmap( QgsColorWidget::createDragIcon( c ) );
314  drag->exec( Qt::CopyAction );
315  setDown( false );
316 }
317 
318 void QgsColorButton::mouseReleaseEvent( QMouseEvent *e )
319 {
320  if ( mPickingColor )
321  {
322  //end color picking operation by sampling the color under cursor
323  stopPicking( e->globalPos() );
324  e->accept();
325  return;
326  }
327 
328  QToolButton::mouseReleaseEvent( e );
329 }
330 
331 void QgsColorButton::stopPicking( QPoint eventPos, bool samplingColor )
332 {
333  //release mouse and keyboard, and reset cursor
334  releaseMouse();
335  releaseKeyboard();
336  QgsApplication::restoreOverrideCursor();
337  setMouseTracking( false );
338  mPickingColor = false;
339 
340  if ( !samplingColor )
341  {
342  //not sampling color, restore old color
344  return;
345  }
346 
347  setColor( QgsGui::sampleColor( eventPos ) );
348  addRecentColor( mColor );
349 }
350 
351 QColor QgsColorButton::linkedProjectColor() const
352 {
353  QList<QgsProjectColorScheme *> projectSchemes;
354  QgsApplication::colorSchemeRegistry()->schemes( projectSchemes );
355  if ( projectSchemes.length() > 0 )
356  {
357  QgsProjectColorScheme *scheme = projectSchemes.at( 0 );
358  const QgsNamedColorList colors = scheme->fetchColors();
359  for ( const auto &color : colors )
360  {
361  if ( color.second.isEmpty() )
362  continue;
363 
364  if ( color.second == mLinkedColorName )
365  {
366  return color.first;
367  }
368  }
369  }
370  return QColor();
371 }
372 
373 void QgsColorButton::keyPressEvent( QKeyEvent *e )
374 {
375  if ( !mPickingColor )
376  {
377  //if not picking a color, use default tool button behavior
378  QToolButton::keyPressEvent( e );
379  return;
380  }
381 
382  //cancel picking, sampling the color if space was pressed
383  stopPicking( QCursor::pos(), e->key() == Qt::Key_Space );
384 }
385 
386 void QgsColorButton::dragEnterEvent( QDragEnterEvent *e )
387 {
388  const bool isProjectColor = linkedProjectColor().isValid();
389  if ( isProjectColor )
390  return;
391 
392  //is dragged data valid color data?
393  QColor mimeColor;
394  if ( colorFromMimeData( e->mimeData(), mimeColor ) )
395  {
396  //if so, we accept the drag, and temporarily change the button's color
397  //to match the dragged color. This gives immediate feedback to the user
398  //that colors can be dropped here
399  e->acceptProposedAction();
400  setButtonBackground( mimeColor );
401  }
402 }
403 
404 void QgsColorButton::dragLeaveEvent( QDragLeaveEvent *e )
405 {
406  Q_UNUSED( e )
407  //reset button color
409 }
410 
411 void QgsColorButton::dropEvent( QDropEvent *e )
412 {
413  const bool isProjectColor = linkedProjectColor().isValid();
414  if ( isProjectColor )
415  return;
416 
417  //is dropped data valid color data?
418  QColor mimeColor;
419  if ( colorFromMimeData( e->mimeData(), mimeColor ) )
420  {
421  //accept drop and set new color
422  e->acceptProposedAction();
423  setColor( mimeColor );
424  addRecentColor( mimeColor );
425  }
426 }
427 
428 void QgsColorButton::setValidColor( const QColor &newColor )
429 {
430  if ( newColor.isValid() )
431  {
432  setColor( newColor );
433  addRecentColor( newColor );
434  }
435 }
436 
437 void QgsColorButton::setValidTemporaryColor( const QColor &newColor )
438 {
439  if ( newColor.isValid() )
440  {
441  setColor( newColor );
442  }
443 }
444 
445 QPixmap QgsColorButton::createMenuIcon( const QColor &color, const bool showChecks )
446 {
447  const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
448 
449  //create an icon pixmap
450  QPixmap pixmap( iconSize, iconSize );
451  pixmap.fill( Qt::transparent );
452 
453  QPainter p;
454  p.begin( &pixmap );
455 
456  //start with checkboard pattern
457  if ( showChecks )
458  {
459  QBrush checkBrush = QBrush( transparentBackground() );
460  p.setPen( Qt::NoPen );
461  p.setBrush( checkBrush );
462  p.drawRect( 0, 0, iconSize - 1, iconSize - 1 );
463  }
464 
465  //draw color over pattern
466  p.setBrush( QBrush( color ) );
467 
468  //draw border
469  p.setPen( QColor( 197, 197, 197 ) );
470  p.drawRect( 0, 0, iconSize - 1, iconSize - 1 );
471  p.end();
472  return pixmap;
473 }
474 
475 void QgsColorButton::buttonClicked()
476 {
477  if ( linkedProjectColor().isValid() )
478  {
479  QToolButton::showMenu();
480  }
481  else
482  {
483  switch ( mBehavior )
484  {
485  case ShowDialog:
486  showColorDialog();
487  return;
488  case SignalOnly:
489  emit colorClicked( mColor );
490  return;
491  }
492  }
493 }
494 
495 void QgsColorButton::prepareMenu()
496 {
497  //we need to tear down and rebuild this menu every time it is shown. Otherwise the space allocated to any
498  //QgsColorSwatchGridAction is not recalculated by Qt and the swatch grid may not be the correct size
499  //for the number of colors shown in the grid. Note that we MUST refresh color swatch grids every time this
500  //menu is opened, otherwise color schemes like the recent color scheme grid are meaningless
501  mMenu->clear();
502 
503  const bool isProjectColor = linkedProjectColor().isValid();
504 
505  if ( !isProjectColor )
506  {
507  if ( mShowNull )
508  {
509  QAction *nullAction = new QAction( tr( "Clear Color" ), this );
510  nullAction->setIcon( createMenuIcon( Qt::transparent, false ) );
511  mMenu->addAction( nullAction );
512  connect( nullAction, &QAction::triggered, this, &QgsColorButton::setToNull );
513  }
514 
515  //show default color option if set
516  if ( mDefaultColor.isValid() )
517  {
518  QAction *defaultColorAction = new QAction( tr( "Default Color" ), this );
519  defaultColorAction->setIcon( createMenuIcon( mDefaultColor ) );
520  mMenu->addAction( defaultColorAction );
521  connect( defaultColorAction, &QAction::triggered, this, &QgsColorButton::setToDefaultColor );
522  }
523 
524  if ( mShowNoColorOption && mAllowOpacity )
525  {
526  QAction *noColorAction = new QAction( mNoColorString, this );
527  noColorAction->setIcon( createMenuIcon( Qt::transparent, false ) );
528  mMenu->addAction( noColorAction );
529  connect( noColorAction, &QAction::triggered, this, &QgsColorButton::setToNoColor );
530  }
531 
532  mMenu->addSeparator();
533  QgsColorWheel *colorWheel = new QgsColorWheel( mMenu );
534  colorWheel->setColor( color() );
535  QgsColorWidgetAction *colorAction = new QgsColorWidgetAction( colorWheel, mMenu, mMenu );
536  colorAction->setDismissOnColorSelection( false );
537  connect( colorAction, &QgsColorWidgetAction::colorChanged, this, &QgsColorButton::setColor );
538  mMenu->addAction( colorAction );
539  if ( mAllowOpacity )
540  {
542  alphaRamp->setColor( color() );
543  QgsColorWidgetAction *alphaAction = new QgsColorWidgetAction( alphaRamp, mMenu, mMenu );
544  alphaAction->setDismissOnColorSelection( false );
545  connect( alphaAction, &QgsColorWidgetAction::colorChanged, this, &QgsColorButton::setColor );
546  connect( alphaAction, &QgsColorWidgetAction::colorChanged, colorWheel, [colorWheel]( const QColor & color ) { colorWheel->setColor( color, false ); }
547  );
548  connect( colorAction, &QgsColorWidgetAction::colorChanged, alphaRamp, [alphaRamp]( const QColor & color ) { alphaRamp->setColor( color, false ); }
549  );
550  mMenu->addAction( alphaAction );
551  }
552 
553  if ( mColorSchemeRegistry )
554  {
555  //get schemes with ShowInColorButtonMenu flag set
556  QList< QgsColorScheme * > schemeList = mColorSchemeRegistry->schemes( QgsColorScheme::ShowInColorButtonMenu );
557  QList< QgsColorScheme * >::iterator it = schemeList.begin();
558  for ( ; it != schemeList.end(); ++it )
559  {
560  QgsColorSwatchGridAction *colorAction = new QgsColorSwatchGridAction( *it, mMenu, mContext, this );
561  colorAction->setBaseColor( mColor );
562  mMenu->addAction( colorAction );
563  connect( colorAction, &QgsColorSwatchGridAction::colorChanged, this, &QgsColorButton::setValidColor );
564  connect( colorAction, &QgsColorSwatchGridAction::colorChanged, this, &QgsColorButton::addRecentColor );
565  }
566  }
567 
568  mMenu->addSeparator();
569  }
570 
571  if ( isProjectColor )
572  {
573  QAction *unlinkAction = new QAction( tr( "Unlink Color" ), mMenu );
574  mMenu->addAction( unlinkAction );
575  connect( unlinkAction, &QAction::triggered, this, &QgsColorButton::unlink );
576  }
577 
578  QAction *copyColorAction = new QAction( tr( "Copy Color" ), this );
579  mMenu->addAction( copyColorAction );
580  connect( copyColorAction, &QAction::triggered, this, &QgsColorButton::copyColor );
581 
582  if ( !isProjectColor )
583  {
584  QAction *pasteColorAction = new QAction( tr( "Paste Color" ), this );
585  //enable or disable paste action based on current clipboard contents. We always show the paste
586  //action, even if it's disabled, to give hint to the user that pasting colors is possible
587  QColor clipColor;
588  if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor ) )
589  {
590  pasteColorAction->setIcon( createMenuIcon( clipColor ) );
591  }
592  else
593  {
594  pasteColorAction->setEnabled( false );
595  }
596  mMenu->addAction( pasteColorAction );
597  connect( pasteColorAction, &QAction::triggered, this, &QgsColorButton::pasteColor );
598 
599  QAction *pickColorAction = new QAction( tr( "Pick Color" ), this );
600  mMenu->addAction( pickColorAction );
601  connect( pickColorAction, &QAction::triggered, this, &QgsColorButton::activatePicker );
602 
603  QAction *chooseColorAction = new QAction( tr( "Choose Color…" ), this );
604  mMenu->addAction( chooseColorAction );
605  connect( chooseColorAction, &QAction::triggered, this, &QgsColorButton::showColorDialog );
606  }
607 }
608 
610 {
611  if ( e->type() == QEvent::EnabledChange )
612  {
614  }
615  QToolButton::changeEvent( e );
616 }
617 
618 #if 0 // causes too many cyclical updates, but may be needed on some platforms
619 void QgsColorButton::paintEvent( QPaintEvent *e )
620 {
621  QToolButton::paintEvent( e );
622 
623  if ( !mBackgroundSet )
624  {
626  }
627 }
628 #endif
629 
630 void QgsColorButton::showEvent( QShowEvent *e )
631 {
633  QToolButton::showEvent( e );
634 }
635 
636 void QgsColorButton::resizeEvent( QResizeEvent *event )
637 {
638  QToolButton::resizeEvent( event );
639  //recalculate icon size and redraw icon
640  mIconSize = QSize();
642 }
643 
644 void QgsColorButton::setColor( const QColor &color )
645 {
646  QColor oldColor = mColor;
647  mColor = color;
648 
649  // handle when initially set color is same as default (Qt::black); consider it a color change
650  if ( oldColor != mColor || ( mColor == QColor( Qt::black ) && !mColorSet ) )
651  {
653  if ( isEnabled() )
654  {
655  // TODO: May be beneficial to have the option to set color without emitting this signal.
656  // Now done by blockSignals( bool ) where button is used
657  emit colorChanged( mColor );
658  }
659  }
660  mColorSet = true;
661 }
662 
663 void QgsColorButton::addRecentColor( const QColor &color )
664 {
666 }
667 
669 {
670  QColor backgroundColor = color;
671  bool isProjectColor = false;
672  if ( !backgroundColor.isValid() && !mLinkedColorName.isEmpty() )
673  {
674  backgroundColor = linkedProjectColor();
675  isProjectColor = backgroundColor.isValid();
676  if ( !isProjectColor )
677  {
678  mLinkedColorName.clear(); //color has been deleted, renamed, etc...
679  emit unlinked();
680  }
681  }
682  if ( !backgroundColor.isValid() )
683  {
684  backgroundColor = mColor;
685  }
686 
687  QSize currentIconSize;
688  //icon size is button size with a small margin
689  if ( menu() )
690  {
691  if ( !mIconSize.isValid() )
692  {
693  //calculate size of push button part of widget (ie, without the menu drop-down button part)
694  QStyleOptionToolButton opt;
695  initStyleOption( &opt );
696  QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton,
697  this );
698  //make sure height of icon looks good under different platforms
699 #ifdef Q_OS_WIN
700  mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
701 #else
702  mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
703 #endif
704  }
705  currentIconSize = mIconSize;
706  }
707  else
708  {
709  //no menu
710 #ifdef Q_OS_WIN
711  currentIconSize = QSize( width() - 10, height() - 6 );
712 #else
713  currentIconSize = QSize( width() - 10, height() - 12 );
714 #endif
715  }
716 
717  if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
718  {
719  return;
720  }
721 
722  //create an icon pixmap
723  QPixmap pixmap( currentIconSize );
724  pixmap.fill( Qt::transparent );
725 
726  if ( backgroundColor.isValid() )
727  {
728  QRect rect( 0, 0, currentIconSize.width(), currentIconSize.height() );
729  QPainter p;
730  p.begin( &pixmap );
731  p.setRenderHint( QPainter::Antialiasing );
732  p.setPen( Qt::NoPen );
733  if ( mAllowOpacity && backgroundColor.alpha() < 255 )
734  {
735  //start with checkboard pattern
736  QBrush checkBrush = QBrush( transparentBackground() );
737  p.setBrush( checkBrush );
738  p.drawRoundedRect( rect, 3, 3 );
739  }
740 
741  //draw semi-transparent color on top
742  p.setBrush( backgroundColor );
743  p.drawRoundedRect( rect, 3, 3 );
744  p.end();
745  }
746 
747  setIconSize( currentIconSize );
748  setIcon( pixmap );
749 }
750 
752 {
753  //copy color
754  QColor c = linkedProjectColor();
755  if ( !c.isValid() )
756  c = mColor;
757  QApplication::clipboard()->setMimeData( QgsSymbolLayerUtils::colorToMimeData( c ) );
758 }
759 
761 {
762  QColor clipColor;
763  if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor ) )
764  {
765  //paste color
766  setColor( clipColor );
767  addRecentColor( clipColor );
768  }
769 }
770 
772 {
773  //activate picker color
774  // Store current color
775  mCurrentColor = mColor;
776  QApplication::setOverrideCursor( QgsApplication::getThemeCursor( QgsApplication::Cursor::Sampler ) );
777  grabMouse();
778  grabKeyboard();
779  mPickingColor = true;
780  setMouseTracking( true );
781 }
782 
783 QColor QgsColorButton::color() const
784 {
785  QColor c = linkedProjectColor();
786  if ( !c.isValid() )
787  c = mColor;
788  return c;
789 }
790 
791 void QgsColorButton::setAllowOpacity( const bool allow )
792 {
793  mAllowOpacity = allow;
794 }
795 
796 void QgsColorButton::setColorDialogTitle( const QString &title )
797 {
798  mColorDialogTitle = title;
799 }
800 
801 QString QgsColorButton::colorDialogTitle() const
802 {
803  return mColorDialogTitle;
804 }
805 
807 {
808  mShowMenu = showMenu;
809  setMenu( showMenu ? mMenu : nullptr );
810  setPopupMode( showMenu ? QToolButton::MenuButtonPopup : QToolButton::DelayedPopup );
811  //force recalculation of icon size
812  mIconSize = QSize();
814 }
815 
817 {
818  mBehavior = behavior;
819 }
820 
822 {
823  mDefaultColor = color;
824 }
825 
827 {
828  mShowNull = showNull;
829 }
830 
832 {
833  return mShowNull;
834 }
835 
837 {
838  return !mColor.isValid();
839 }
840 
841 void QgsColorButton::linkToProjectColor( const QString &name )
842 {
843  mLinkedColorName = name;
845 }
846 
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.
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:154
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
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.
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:442
void setShowNull(bool showNull)
Sets whether a set to null (clear) option is shown in the button&#39;s drop-down menu.
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:176
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.