17#include "moc_qgscolorbutton.cpp"
36#include <QStyleOptionToolButton>
37#include <QWidgetAction>
45 : QToolButton( parent )
46 , mColorDialogTitle( cdt.isEmpty() ? tr(
"Select Color" ) : cdt )
47 , mNoColorString( tr(
"No color" ) )
52 setAcceptDrops(
true );
53 setMinimumSize( QSize( 24, 16 ) );
54 connect(
this, &QAbstractButton::clicked,
this, &QgsColorButton::buttonClicked );
57 mMenu =
new QMenu(
this );
58 connect( mMenu, &QMenu::aboutToShow,
this, &QgsColorButton::prepareMenu );
60 setPopupMode( QToolButton::MenuButtonPopup );
63 mMinimumSize = QSize( 120, 22 );
65 mMinimumSize = QSize( 120, 28 );
68 mMinimumSize.setHeight( std::max(
static_cast<int>(
Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 1.1 ), mMinimumSize.height() ) );
88 static QPixmap sTranspBkgrd;
90 if ( sTranspBkgrd.isNull() )
96void QgsColorButton::showColorDialog()
101 const QColor currentColor =
color();
106 if ( currentColor.isValid() )
120 const bool useNative = settings.
value( QStringLiteral(
"qgis/native_color_dialogs" ),
false ).toBool();
124 newColor = QColorDialog::getColor(
color(),
this, mColorDialogTitle, mAllowOpacity ? QColorDialog::ShowAlphaChannel : ( QColorDialog::ColorDialogOption ) 0 );
129 dialog.setTitle( mColorDialogTitle );
130 dialog.setAllowOpacity( mAllowOpacity );
134 newColor = dialog.color();
138 if ( newColor.isValid() )
140 setValidColor( newColor );
149 if ( !mDefaultColor.isValid() )
171 if ( e->type() == QEvent::ToolTip && isEnabled() )
173 QColor
c = linkedProjectColor();
174 const bool isProjectColor =
c.isValid();
175 if ( !isProjectColor )
178 QString info = ( isProjectColor ? QStringLiteral(
"<p>%1: %2</p>" ).arg( tr(
"Linked color" ), mLinkedColorName ) : QString() );
184 return QToolButton::event( e );
189 QColor noColor = QColor( mColor );
190 noColor.setAlpha( 0 );
203 if ( e->button() == Qt::RightButton )
205 QToolButton::showMenu();
208 else if ( e->button() == Qt::LeftButton )
210 mDragStartPosition = e->pos();
212 QToolButton::mousePressEvent( e );
215bool QgsColorButton::colorFromMimeData(
const QMimeData *mimeData, QColor &resultColor )
220 bool hasAlpha =
false;
223 if ( mimeColor.isValid() )
225 if ( !mAllowOpacity )
228 mimeColor.setAlpha( 255 );
230 else if ( !hasAlpha )
233 mimeColor.setAlpha( mColor.alpha() );
235 resultColor = mimeColor;
253 QColor
c = linkedProjectColor();
257 if ( !( e->buttons() & Qt::LeftButton ) || !
c.isValid() )
260 QToolButton::mouseMoveEvent( e );
264 if ( ( e->pos() - mDragStartPosition ).manhattanLength() < QApplication::startDragDistance() )
267 QToolButton::mouseMoveEvent( e );
272 QDrag *drag =
new QDrag(
this );
275 drag->exec( Qt::CopyAction );
284 stopPicking( e->globalPos() );
289 QToolButton::mouseReleaseEvent( e );
292void QgsColorButton::stopPicking( QPoint eventPos,
bool samplingColor )
297 QgsApplication::restoreOverrideCursor();
298 setMouseTracking(
false );
299 mPickingColor =
false;
301 if ( !samplingColor )
309 addRecentColor( mColor );
312QColor QgsColorButton::linkedProjectColor()
const
314 QList<QgsProjectColorScheme *> projectSchemes;
316 if ( projectSchemes.length() > 0 )
320 for (
const auto &
color : colors )
322 if (
color.second.isEmpty() )
325 if (
color.second == mLinkedColorName )
336 if ( !mPickingColor )
339 QToolButton::keyPressEvent( e );
344 stopPicking( QCursor::pos(), e->key() == Qt::Key_Space );
349 const bool isProjectColor = linkedProjectColor().isValid();
350 if ( isProjectColor )
355 if ( colorFromMimeData( e->mimeData(), mimeColor ) )
360 e->acceptProposedAction();
374 const bool isProjectColor = linkedProjectColor().isValid();
375 if ( isProjectColor )
380 if ( colorFromMimeData( e->mimeData(), mimeColor ) )
383 e->acceptProposedAction();
385 addRecentColor( mimeColor );
391 if ( mAllowOpacity && isEnabled() && !
isNull() )
393 const double increment = ( (
event->modifiers() & Qt::ControlModifier ) ? 0.01 : 0.1 ) * (
event->angleDelta().y() > 0 ? 1 : -1 );
394 const double alpha = std::min( std::max( 0.0, mColor.alphaF() + increment ), 1.0 );
395 mColor.setAlphaF( alpha );
403 QToolButton::wheelEvent(
event );
407void QgsColorButton::setValidColor(
const QColor &newColor )
409 if ( newColor.isValid() )
412 addRecentColor( newColor );
416void QgsColorButton::setValidTemporaryColor(
const QColor &newColor )
418 if ( newColor.isValid() )
429 QPixmap pixmap( iconSize, iconSize );
430 pixmap.fill( Qt::transparent );
439 p.setPen( Qt::NoPen );
440 p.setBrush( checkBrush );
441 p.drawRect( 0, 0, iconSize - 1, iconSize - 1 );
445 p.setBrush( QBrush(
color ) );
448 p.setPen( QColor( 197, 197, 197 ) );
449 p.drawRect( 0, 0, iconSize - 1, iconSize - 1 );
454void QgsColorButton::buttonClicked()
456 if ( linkedProjectColor().isValid() )
458 QToolButton::showMenu();
474void QgsColorButton::prepareMenu()
482 const bool isProjectColor = linkedProjectColor().isValid();
484 if ( !isProjectColor )
488 QAction *nullAction =
new QAction( mNullColorString.isEmpty() ? tr(
"Clear Color" ) : mNullColorString, this );
490 mMenu->addAction( nullAction );
495 if ( mDefaultColor.isValid() )
497 QAction *defaultColorAction =
new QAction( tr(
"Default Color" ),
this );
499 mMenu->addAction( defaultColorAction );
503 if ( mShowNoColorOption )
505 QAction *noColorAction =
new QAction( mNoColorString,
this );
506 noColorAction->setIcon(
createMenuIcon( Qt::transparent,
false ) );
507 mMenu->addAction( noColorAction );
511 mMenu->addSeparator();
517 mMenu->addAction( colorAction );
527 mMenu->addAction( alphaAction );
530 if ( mColorSchemeRegistry )
534 QList<QgsColorScheme *>::iterator it = schemeList.begin();
535 for ( ; it != schemeList.end(); ++it )
539 mMenu->addAction( colorAction );
545 mMenu->addSeparator();
548 if ( isProjectColor )
550 QAction *unlinkAction =
new QAction( tr(
"Unlink Color" ), mMenu );
551 mMenu->addAction( unlinkAction );
555 QAction *copyColorAction =
new QAction( tr(
"Copy Color" ),
this );
556 mMenu->addAction( copyColorAction );
559 if ( !isProjectColor )
561 QAction *pasteColorAction =
new QAction( tr(
"Paste Color" ),
this );
565 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor ) )
571 pasteColorAction->setEnabled(
false );
573 mMenu->addAction( pasteColorAction );
576 QAction *pickColorAction =
new QAction( tr(
"Pick Color" ),
this );
577 mMenu->addAction( pickColorAction );
580 QAction *chooseColorAction =
new QAction( tr(
"Choose Color…" ),
this );
581 mMenu->addAction( chooseColorAction );
582 connect( chooseColorAction, &QAction::triggered,
this, &QgsColorButton::showColorDialog );
588 if ( e->type() == QEvent::EnabledChange )
592 QToolButton::changeEvent( e );
596void QgsColorButton::paintEvent( QPaintEvent *e )
598 QToolButton::paintEvent( e );
600 if ( !mBackgroundSet )
610 QToolButton::showEvent( e );
615 QToolButton::resizeEvent(
event );
623 const QColor oldColor = mColor;
627 if ( oldColor != mColor || ( mColor == QColor( Qt::black ) && !mColorSet ) )
640void QgsColorButton::addRecentColor(
const QColor &color )
647 QColor backgroundColor =
color;
648 bool isProjectColor =
false;
649 if ( !backgroundColor.isValid() && !mLinkedColorName.isEmpty() )
651 backgroundColor = linkedProjectColor();
652 isProjectColor = backgroundColor.isValid();
653 if ( !isProjectColor )
655 mLinkedColorName.clear();
659 if ( !backgroundColor.isValid() )
661 backgroundColor = mColor;
664 QSize currentIconSize;
668 if ( !mIconSize.isValid() )
671 QStyleOptionToolButton opt;
672 initStyleOption( &opt );
673 const QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton,
this );
676 mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
678 mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
681 currentIconSize = mIconSize;
687 currentIconSize = QSize( width() - 10, height() - 6 );
689 currentIconSize = QSize( width() - 10, height() - 12 );
693 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
699 const double pixelRatio = devicePixelRatioF();
700 QPixmap pixmap( currentIconSize * pixelRatio );
701 pixmap.setDevicePixelRatio( pixelRatio );
702 pixmap.fill( Qt::transparent );
704 if ( backgroundColor.isValid() )
706 const QRectF rect( 0, 0, currentIconSize.width(), currentIconSize.height() );
709 p.setRenderHint( QPainter::Antialiasing );
710 p.setPen( Qt::NoPen );
711 if ( mAllowOpacity && backgroundColor.alpha() < 255 )
715 p.setBrush( checkBrush );
716 p.drawRoundedRect( rect, 3, 3 );
719 p.setBrush( backgroundColor );
720 p.drawRoundedRect( rect, 3, 3 );
723 const QRectF clipRect( 0, 0,
static_cast<qreal
>( currentIconSize.width() ) / 2.0, currentIconSize.height() );
724 p.setClipRect( clipRect );
725 backgroundColor.setAlpha( 255 );
726 p.setBrush( backgroundColor );
727 p.drawRoundedRect( rect, 3, 3 );
731 p.setBrush( backgroundColor );
732 p.drawRoundedRect( rect, 3, 3 );
737 setIconSize( currentIconSize );
744 QColor
c = linkedProjectColor();
753 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor ) )
757 addRecentColor( clipColor );
765 mCurrentColor = mColor;
769 mPickingColor =
true;
770 setMouseTracking(
true );
775 QColor
c = linkedProjectColor();
783 mAllowOpacity = allow;
788 mColorDialogTitle = title;
793 return mColorDialogTitle;
799 setMenu(
showMenu ? mMenu : nullptr );
800 setPopupMode(
showMenu ? QToolButton::MenuButtonPopup : QToolButton::DelayedPopup );
813 mDefaultColor =
color;
819 mNullColorString = nullString;
829 return !mColor.isValid();
834 mLinkedColorName = name;
static const double UI_SCALE_FACTOR
UI scaling factor.
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.
A custom QGIS dialog for selecting a color.
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.
void setColor(const QColor &color, bool emitSignals=false) override
static QColor sampleColor(QPoint point)
Samples the color on screen at the specified global point (pixel).
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.
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.
Stores settings for use within QGIS.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
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.
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