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