QGIS API Documentation 4.3.0-Master (0cfde48c85b)
Loading...
Searching...
No Matches
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
18#include "qgsapplication.h"
19#include "qgscolordialog.h"
21#include "qgscolorswatchgrid.h"
22#include "qgscolortooltip_p.h"
23#include "qgscolorwidgets.h"
24#include "qgsgui.h"
25#include "qgsguiutils.h"
26#include "qgsproject.h"
27#include "qgssettings.h"
29#include "qgssymbollayerutils.h"
30
31#include <QBuffer>
32#include <QClipboard>
33#include <QDrag>
34#include <QGridLayout>
35#include <QLabel>
36#include <QMenu>
37#include <QMimeData>
38#include <QMouseEvent>
39#include <QPainter>
40#include <QPushButton>
41#include <QScreen>
42#include <QString>
43#include <QStyle>
44#include <QStyleOptionToolButton>
45#include <QWidgetAction>
46
47#include "moc_qgscolorbutton.cpp"
48
49using namespace Qt::StringLiterals;
50
51QgsColorButton::QgsColorButton( QWidget *parent, const QString &cdt, QgsColorSchemeRegistry *registry )
52 : QToolButton( parent )
53 , mColorDialogTitle( cdt.isEmpty() ? tr( "Select Color" ) : cdt )
54 , mNoColorString( tr( "No color" ) )
55 , mOpaqueColorString( tr( "Opaque color" ) )
56{
57 //if a color scheme registry was specified, use it, otherwise use the global instance
58 mColorSchemeRegistry = registry ? registry : QgsApplication::colorSchemeRegistry();
59
60 setAcceptDrops( true );
61 setMinimumSize( QSize( 24, 16 ) );
62 connect( this, &QAbstractButton::clicked, this, &QgsColorButton::buttonClicked );
63
64 //setup drop-down menu
65 mMenu = new QMenu( this );
66 connect( mMenu, &QMenu::aboutToShow, this, &QgsColorButton::prepareMenu );
67 setMenu( mMenu );
68 setPopupMode( QToolButton::MenuButtonPopup );
69
70#ifdef Q_OS_WIN
71 mMinimumSize = QSize( 120, 22 );
72#else
73 mMinimumSize = QSize( 120, 28 );
74#endif
75
76 mMinimumSize.setHeight( std::max( static_cast<int>( Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 1.1 ), mMinimumSize.height() ) );
77
78 // If project colors change, we need to redraw the button, as it may be set to follow a project color
80}
81
83{
84 return mMinimumSize;
85}
86
88{
89 return mMinimumSize;
90}
91
93{
94 static QPixmap sTranspBkgrd;
95
96 if ( sTranspBkgrd.isNull() )
97 sTranspBkgrd = QgsApplication::getThemePixmap( u"/transp-background_8x8.png"_s );
98
99 return sTranspBkgrd;
100}
101
102void QgsColorButton::showColorDialog()
103{
105 if ( panel && panel->dockMode() )
106 {
107 const QColor currentColor = color();
109 colorWidget->setPanelTitle( mColorDialogTitle );
110 colorWidget->setAllowOpacity( mAllowOpacity );
111
112 if ( currentColor.isValid() )
113 {
114 colorWidget->setPreviousColor( currentColor );
115 }
116
117 connect( colorWidget, &QgsCompoundColorWidget::currentColorChanged, this, &QgsColorButton::setValidTemporaryColor );
118 panel->openPanel( colorWidget );
119 return;
120 }
121
122 QColor newColor;
123 const QgsSettings settings;
124
125 // first check if we need to use the limited native dialogs
127 if ( useNative )
128 {
129 // why would anyone want this? who knows.... maybe the limited nature of native dialogs helps ease the transition for MapInfo users?
130 newColor = QColorDialog::getColor( color(), this, mColorDialogTitle, mAllowOpacity ? QColorDialog::ShowAlphaChannel : ( QColorDialog::ColorDialogOption ) 0 );
131 }
132 else
133 {
134 QgsColorDialog dialog( this, Qt::WindowFlags(), color() );
135 dialog.setTitle( mColorDialogTitle );
136 dialog.setAllowOpacity( mAllowOpacity );
137
138 if ( dialog.exec() )
139 {
140 newColor = dialog.color();
141 }
142 }
143
144 if ( newColor.isValid() )
145 {
146 setValidColor( newColor );
147 }
148
149 // reactivate button's window
150 activateWindow();
151}
152
154{
155 if ( !mDefaultColor.isValid() )
156 {
157 return;
158 }
159
160 setColor( mDefaultColor );
161}
162
164{
165 setColor( QColor() );
166 emit cleared();
167}
168
170{
171 linkToProjectColor( QString() );
172 emit unlinked();
173}
174
175bool QgsColorButton::event( QEvent *e )
176{
177 if ( e->type() == QEvent::ToolTip && isEnabled() )
178 {
179 QColor c = linkedProjectColor();
180 const bool isProjectColor = c.isValid();
181 if ( !isProjectColor )
182 c = mColor;
183
184 QString info = ( isProjectColor ? u"<p>%1: %2</p>"_s.arg( tr( "Linked color" ), mLinkedColorName ) : QString() );
185
186 info += QgsColorTooltip::htmlDescription( c, this );
187
188 setToolTip( info );
189 }
190 return QToolButton::event( e );
191}
192
194{
195 QColor noColor = QColor( mColor );
196 noColor.setAlpha( 0 );
197 setColor( noColor );
198}
199
201{
202 QColor opaqueColor = QColor( mColor );
203 opaqueColor.setAlpha( 255 );
204 setColor( opaqueColor );
205}
206
208{
209 if ( mPickingColor )
210 {
211 //don't show dialog if in color picker mode
212 e->accept();
213 return;
214 }
215
216 if ( e->button() == Qt::RightButton )
217 {
218 QToolButton::showMenu();
219 return;
220 }
221 else if ( e->button() == Qt::LeftButton )
222 {
223 mDragStartPosition = e->pos();
224 }
225 QToolButton::mousePressEvent( e );
226}
227
228bool QgsColorButton::colorFromMimeData( const QMimeData *mimeData, QColor &resultColor )
229{
230 if ( !mimeData )
231 return false;
232
233 bool hasAlpha = false;
234 QColor mimeColor = QgsSymbolLayerUtils::colorFromMimeData( mimeData, hasAlpha );
235
236 if ( mimeColor.isValid() )
237 {
238 if ( !mAllowOpacity )
239 {
240 //remove alpha channel
241 mimeColor.setAlpha( 255 );
242 }
243 else if ( !hasAlpha )
244 {
245 //mime color has no explicit alpha component, so keep existing alpha
246 mimeColor.setAlpha( mColor.alpha() );
247 }
248 resultColor = mimeColor;
249 return true;
250 }
251
252 //could not get color from mime data
253 return false;
254}
255
256void QgsColorButton::mouseMoveEvent( QMouseEvent *e )
257{
258 if ( mPickingColor )
259 {
260 setButtonBackground( QgsGui::sampleColor( e->globalPos() ) );
261 e->accept();
262 return;
263 }
264
265 //handle dragging colors from button
266 QColor c = linkedProjectColor();
267 if ( !c.isValid() )
268 c = mColor;
269
270 if ( !( e->buttons() & Qt::LeftButton ) || !c.isValid() )
271 {
272 //left button not depressed or no color set, so not a drag
273 QToolButton::mouseMoveEvent( e );
274 return;
275 }
276
277 if ( ( e->pos() - mDragStartPosition ).manhattanLength() < QApplication::startDragDistance() )
278 {
279 //mouse not moved, so not a drag
280 QToolButton::mouseMoveEvent( e );
281 return;
282 }
283
284 //user is dragging color
285 QDrag *drag = new QDrag( this );
286 drag->setMimeData( QgsSymbolLayerUtils::colorToMimeData( c ).release() );
287 drag->setPixmap( QgsColorWidget::createDragIcon( c ) );
288 drag->exec( Qt::CopyAction );
289 setDown( false );
290}
291
293{
294 if ( mPickingColor )
295 {
296 //end color picking operation by sampling the color under cursor
297 stopPicking( e->globalPos() );
298 e->accept();
299 return;
300 }
301
302 QToolButton::mouseReleaseEvent( e );
303}
304
305void QgsColorButton::stopPicking( QPoint eventPos, bool samplingColor )
306{
307 //release mouse and keyboard, and reset cursor
308 releaseMouse();
309 releaseKeyboard();
310 QgsApplication::restoreOverrideCursor();
311 setMouseTracking( false );
312 mPickingColor = false;
313
314 if ( !samplingColor )
315 {
316 //not sampling color, restore old color
318 return;
319 }
320
321 setColor( QgsGui::sampleColor( eventPos ) );
322 addRecentColor( mColor );
323}
324
325QColor QgsColorButton::linkedProjectColor() const
326{
327 QList<QgsProjectColorScheme *> projectSchemes;
328 QgsApplication::colorSchemeRegistry()->schemes( projectSchemes );
329 if ( projectSchemes.length() > 0 )
330 {
331 QgsProjectColorScheme *scheme = projectSchemes.at( 0 );
332 const QgsNamedColorList colors = scheme->fetchColors();
333 for ( const auto &color : colors )
334 {
335 if ( color.second.isEmpty() )
336 continue;
337
338 if ( color.second == mLinkedColorName )
339 {
340 return color.first;
341 }
342 }
343 }
344 return QColor();
345}
346
348{
349 if ( !mPickingColor )
350 {
351 //if not picking a color, use default tool button behavior
352 QToolButton::keyPressEvent( e );
353 return;
354 }
355
356 //cancel picking, sampling the color if space was pressed
357 stopPicking( QCursor::pos(), e->key() == Qt::Key_Space );
358}
359
360void QgsColorButton::dragEnterEvent( QDragEnterEvent *e )
361{
362 const bool isProjectColor = linkedProjectColor().isValid();
363 if ( isProjectColor )
364 return;
365
366 //is dragged data valid color data?
367 QColor mimeColor;
368 if ( colorFromMimeData( e->mimeData(), mimeColor ) )
369 {
370 //if so, we accept the drag, and temporarily change the button's color
371 //to match the dragged color. This gives immediate feedback to the user
372 //that colors can be dropped here
373 e->acceptProposedAction();
374 setButtonBackground( mimeColor );
375 }
376}
377
378void QgsColorButton::dragLeaveEvent( QDragLeaveEvent *e )
379{
380 Q_UNUSED( e )
381 //reset button color
383}
384
385void QgsColorButton::dropEvent( QDropEvent *e )
386{
387 const bool isProjectColor = linkedProjectColor().isValid();
388 if ( isProjectColor )
389 return;
390
391 //is dropped data valid color data?
392 QColor mimeColor;
393 if ( colorFromMimeData( e->mimeData(), mimeColor ) )
394 {
395 //accept drop and set new color
396 e->acceptProposedAction();
397 setColor( mimeColor );
398 addRecentColor( mimeColor );
399 }
400}
401
403{
404 if ( mAllowOpacity && isEnabled() && !isNull() )
405 {
406 const double increment = ( ( event->modifiers() & Qt::ControlModifier ) ? 0.01 : 0.1 ) * ( event->angleDelta().y() > 0 ? 1 : -1 );
407 const double alpha = std::min( std::max( 0.0, mColor.alphaF() + increment ), 1.0 );
408 mColor.setAlphaF( alpha );
409
411 emit colorChanged( mColor );
412 event->accept();
413 }
414 else
415 {
416 QToolButton::wheelEvent( event );
417 }
418}
419
420void QgsColorButton::setValidColor( const QColor &newColor )
421{
422 if ( newColor.isValid() )
423 {
424 setColor( newColor );
425 addRecentColor( newColor );
426 }
427}
428
429void QgsColorButton::setValidTemporaryColor( const QColor &newColor )
430{
431 if ( newColor.isValid() )
432 {
433 setColor( newColor );
434 }
435}
436
437QPixmap QgsColorButton::createMenuIcon( const QColor &color, const bool showChecks )
438{
439 const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
440
441 //create an icon pixmap
442 QPixmap pixmap( iconSize, iconSize );
443 pixmap.fill( Qt::transparent );
444
445 QPainter p;
446 p.begin( &pixmap );
447
448 //start with checkboard pattern
449 if ( showChecks )
450 {
451 const QBrush checkBrush = QBrush( transparentBackground() );
452 p.setPen( Qt::NoPen );
453 p.setBrush( checkBrush );
454 p.drawRect( 0, 0, iconSize - 1, iconSize - 1 );
455 }
456
457 //draw color over pattern
458 p.setBrush( QBrush( color ) );
459
460 //draw border
461 p.setPen( QColor( 197, 197, 197 ) );
462 p.drawRect( 0, 0, iconSize - 1, iconSize - 1 );
463 p.end();
464 return pixmap;
465}
466
467void QgsColorButton::buttonClicked()
468{
469 if ( linkedProjectColor().isValid() )
470 {
471 QToolButton::showMenu();
472 }
473 else
474 {
475 switch ( mBehavior )
476 {
477 case ShowDialog:
478 showColorDialog();
479 return;
480 case SignalOnly:
481 emit colorClicked( mColor );
482 return;
483 }
484 }
485}
486
487void QgsColorButton::prepareMenu()
488{
489 //we need to tear down and rebuild this menu every time it is shown. Otherwise the space allocated to any
490 //QgsColorSwatchGridAction is not recalculated by Qt and the swatch grid may not be the correct size
491 //for the number of colors shown in the grid. Note that we MUST refresh color swatch grids every time this
492 //menu is opened, otherwise color schemes like the recent color scheme grid are meaningless
493 mMenu->clear();
494
495 const bool isProjectColor = linkedProjectColor().isValid();
496
497 if ( !isProjectColor )
498 {
499 if ( mShowNull )
500 {
501 QAction *nullAction = new QAction( mNullColorString.isEmpty() ? tr( "Clear Color" ) : mNullColorString, this );
502 nullAction->setIcon( createMenuIcon( Qt::transparent, false ) );
503 mMenu->addAction( nullAction );
504 connect( nullAction, &QAction::triggered, this, &QgsColorButton::setToNull );
505 }
506
507 //show default color option if set
508 if ( mDefaultColor.isValid() )
509 {
510 QAction *defaultColorAction = new QAction( tr( "Default Color" ), this );
511 defaultColorAction->setIcon( createMenuIcon( mDefaultColor ) );
512 mMenu->addAction( defaultColorAction );
513 connect( defaultColorAction, &QAction::triggered, this, &QgsColorButton::setToDefaultColor );
514 }
515
516 if ( mShowNoColorOption && mColor.alpha() > 0 )
517 {
518 QAction *noColorAction = new QAction( mNoColorString, this );
519 noColorAction->setIcon( createMenuIcon( Qt::transparent, false ) );
520 mMenu->addAction( noColorAction );
521 connect( noColorAction, &QAction::triggered, this, &QgsColorButton::setToNoColor );
522 }
523
524 if ( ( mAllowOpacity || mShowNoColorOption ) && mColor.isValid() && mColor.alpha() < 255 )
525 {
526 QColor opaqueColor = QColor( mColor );
527 opaqueColor.setAlpha( 255 );
528 QAction *opaqueColorAction = new QAction( mOpaqueColorString, this );
529 opaqueColorAction->setIcon( createMenuIcon( opaqueColor ) );
530 mMenu->addAction( opaqueColorAction );
531 connect( opaqueColorAction, &QAction::triggered, this, &QgsColorButton::setToOpaqueColor );
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 {
543 QgsColorRampWidget *alphaRamp = new QgsColorRampWidget( mMenu, QgsColorWidget::Alpha, QgsColorRampWidget::Horizontal );
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 connect( colorAction, &QgsColorWidgetAction::colorChanged, alphaRamp, [alphaRamp]( const QColor &color ) { alphaRamp->setColor( color, false ); } );
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
619void QgsColorButton::paintEvent( QPaintEvent *e )
620{
621 QToolButton::paintEvent( e );
622
623 if ( !mBackgroundSet )
624 {
626 }
627}
628#endif
629
630void QgsColorButton::showEvent( QShowEvent *e )
631{
633 QToolButton::showEvent( e );
634}
635
637{
638 QToolButton::resizeEvent( event );
639 //recalculate icon size and redraw icon
640 mIconSize = QSize();
642}
643
644void QgsColorButton::setColor( const QColor &color )
645{
646 const 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
663void 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 const QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton, this );
697 //make sure height of icon looks good under different platforms
698#ifdef Q_OS_WIN
699 mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
700#else
701 mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
702#endif
703 }
704 currentIconSize = mIconSize;
705 }
706 else
707 {
708 //no menu
709#ifdef Q_OS_WIN
710 currentIconSize = QSize( width() - 10, height() - 6 );
711#else
712 currentIconSize = QSize( width() - 10, height() - 12 );
713#endif
714 }
715
716 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
717 {
718 return;
719 }
720
721 //create an icon pixmap
722 const double pixelRatio = devicePixelRatioF();
723 QPixmap pixmap( currentIconSize * pixelRatio );
724 pixmap.setDevicePixelRatio( pixelRatio );
725 pixmap.fill( Qt::transparent );
726
727 if ( backgroundColor.isValid() )
728 {
729 const QRectF rect( 0, 0, currentIconSize.width(), currentIconSize.height() );
730 QPainter p;
731 p.begin( &pixmap );
732 p.setRenderHint( QPainter::Antialiasing );
733 p.setPen( Qt::NoPen );
734 if ( mAllowOpacity && backgroundColor.alpha() < 255 )
735 {
736 //start with checkboard pattern
737 const QBrush checkBrush = QBrush( transparentBackground() );
738 p.setBrush( checkBrush );
739 p.drawRoundedRect( rect, 3, 3 );
740
741 //draw semi-transparent color on top
742 p.setBrush( backgroundColor );
743 p.drawRoundedRect( rect, 3, 3 );
744
745 //draw fully opaque color on the left side
746 const QRectF clipRect( 0, 0, static_cast<qreal>( currentIconSize.width() ) / 2.0, currentIconSize.height() );
747 p.setClipRect( clipRect );
748 backgroundColor.setAlpha( 255 );
749 p.setBrush( backgroundColor );
750 p.drawRoundedRect( rect, 3, 3 );
751 }
752 else
753 {
754 p.setBrush( backgroundColor );
755 p.drawRoundedRect( rect, 3, 3 );
756 }
757 p.end();
758 }
759
760 setIconSize( currentIconSize );
761 setIcon( pixmap );
762}
763
765{
766 //copy color
767 QColor c = linkedProjectColor();
768 if ( !c.isValid() )
769 c = mColor;
770 QApplication::clipboard()->setMimeData( QgsSymbolLayerUtils::colorToMimeData( c ).release() );
771}
772
774{
775 QColor clipColor;
776 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor ) )
777 {
778 //paste color
779 setColor( clipColor );
780 addRecentColor( clipColor );
781 }
782}
783
785{
786 //activate picker color
787 // Store current color
788 mCurrentColor = mColor;
789 QApplication::setOverrideCursor( QgsApplication::getThemeCursor( QgsApplication::Cursor::Sampler ) );
790 grabMouse();
791 grabKeyboard();
792 mPickingColor = true;
793 setMouseTracking( true );
794}
795
797{
798 QColor c = linkedProjectColor();
799 if ( !c.isValid() )
800 c = mColor;
801 return c;
802}
803
804void QgsColorButton::setAllowOpacity( const bool allow )
805{
806 mAllowOpacity = allow;
807}
808
809void QgsColorButton::setColorDialogTitle( const QString &title )
810{
811 mColorDialogTitle = title;
812}
813
815{
816 return mColorDialogTitle;
817}
818
820{
821 mShowMenu = showMenu;
822 setMenu( showMenu ? mMenu : nullptr );
823 setPopupMode( showMenu ? QToolButton::MenuButtonPopup : QToolButton::DelayedPopup );
824 //force recalculation of icon size
825 mIconSize = QSize();
827}
828
833
835{
836 mDefaultColor = color;
837}
838
839void QgsColorButton::setShowNull( bool showNull, const QString &nullString )
840{
841 mShowNull = showNull;
842 mNullColorString = nullString;
843}
844
846{
847 return mShowNull;
848}
849
851{
852 return !mColor.isValid();
853}
854
855void QgsColorButton::linkToProjectColor( const QString &name )
856{
857 mLinkedColorName = name;
859}
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition qgis.h:7320
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.
@ Sampler
Color/Value picker.
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 setToOpaqueColor()
Sets the color to a totally opaque one, leaving the other color components untouched.
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.
void wheelEvent(QWheelEvent *event) override
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
@ 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.
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.
static QString htmlDescription(QColor color, T *widget)
Returns an HTML description given a color with a preview image of the color.
void setColor(const QColor &color, bool emitSignals=false) override
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:299
Base class for any widget that can be shown as an 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 ...
bool dockMode() const
Returns the dock mode state.
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.
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.
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.
T value(const QString &dynamicKeyPart=QString()) const
Returns settings value.
static const QgsSettingsEntryBool * settingsNativeColorDialogs
Settings entry whether to use native color dialogs.
static QColor colorFromMimeData(const QMimeData *data, bool &hasAlpha)
Attempts to parse mime data as a color.
static std::unique_ptr< 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.
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