24 #include "qgssettings.h"
30 #include <QMouseEvent>
34 #include <QDesktopWidget>
36 #include <QStyleOptionToolButton>
37 #include <QWidgetAction>
40 #include <QGridLayout>
41 #include <QPushButton>
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() ) );
89 static QPixmap sTranspBkgrd;
91 if ( sTranspBkgrd.isNull() )
97 void QgsColorButton::showColorDialog()
102 QColor currentColor =
color();
107 if ( currentColor.isValid() )
118 QgsSettings settings;
121 bool useNative = settings.value( QStringLiteral(
"qgis/native_color_dialogs" ),
false ).toBool();
125 newColor = QColorDialog::getColor(
color(),
this, mColorDialogTitle, mAllowOpacity ? QColorDialog::ShowAlphaChannel : ( QColorDialog::ColorDialogOption )0 );
130 dialog.setTitle( mColorDialogTitle );
131 dialog.setAllowOpacity( mAllowOpacity );
135 newColor = dialog.color();
139 if ( newColor.isValid() )
141 setValidColor( newColor );
150 if ( !mDefaultColor.isValid() )
172 if ( e->type() == QEvent::ToolTip )
174 QColor
c = linkedProjectColor();
175 bool isProjectColor =
c.isValid();
176 if ( !isProjectColor )
179 QString name =
c.name();
181 int value =
c.value();
182 int saturation =
c.saturation();
185 int width =
static_cast< int >(
Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance(
'X' ) * 23 );
186 int height =
static_cast< int >( width / 1.61803398875 );
188 int margin =
static_cast< int >( height * 0.1 );
189 QImage icon = QImage( width + 2 * margin, height + 2 * margin, QImage::Format_ARGB32 );
190 icon.fill( Qt::transparent );
197 p.setPen( Qt::NoPen );
198 p.setBrush( checkBrush );
199 p.drawRect( margin, margin, width, height );
202 p.setBrush( QBrush(
c ) );
205 p.setPen( QColor( 197, 197, 197 ) );
206 p.drawRect( margin, margin, width, height );
210 QBuffer buffer( &data );
211 icon.save( &buffer,
"PNG", 100 );
213 QString info = ( isProjectColor ? QStringLiteral(
"<p>%1: %2</p>" ).arg( tr(
"Linked color" ), mLinkedColorName ) : QString() )
214 + QStringLiteral(
"<b>HEX</b> %1<br>"
216 "<b>HSV</b> %3,%4,%5<p>"
217 "<img src='data:image/png;base64, %0'>" ).arg( QString( data.toBase64() ), name,
219 .arg( hue ).arg( saturation ).arg( value );
222 return QToolButton::event( e );
227 QColor noColor = QColor( mColor );
228 noColor.setAlpha( 0 );
241 if ( e->button() == Qt::RightButton )
243 QToolButton::showMenu();
246 else if ( e->button() == Qt::LeftButton )
248 mDragStartPosition = e->pos();
250 QToolButton::mousePressEvent( e );
253 bool QgsColorButton::colorFromMimeData(
const QMimeData *mimeData, QColor &resultColor )
255 bool hasAlpha =
false;
258 if ( mimeColor.isValid() )
260 if ( !mAllowOpacity )
263 mimeColor.setAlpha( 255 );
265 else if ( !hasAlpha )
268 mimeColor.setAlpha( mColor.alpha() );
270 resultColor = mimeColor;
288 QColor
c = linkedProjectColor();
292 if ( !( e->buttons() & Qt::LeftButton ) || !
c.isValid() )
295 QToolButton::mouseMoveEvent( e );
299 if ( ( e->pos() - mDragStartPosition ).manhattanLength() < QApplication::startDragDistance() )
302 QToolButton::mouseMoveEvent( e );
307 QDrag *drag =
new QDrag(
this );
310 drag->exec( Qt::CopyAction );
319 stopPicking( e->globalPos() );
324 QToolButton::mouseReleaseEvent( e );
327 void QgsColorButton::stopPicking( QPoint eventPos,
bool samplingColor )
332 QgsApplication::restoreOverrideCursor();
333 setMouseTracking(
false );
334 mPickingColor =
false;
336 if ( !samplingColor )
344 addRecentColor( mColor );
347 QColor QgsColorButton::linkedProjectColor()
const
349 QList<QgsProjectColorScheme *> projectSchemes;
351 if ( projectSchemes.length() > 0 )
355 for (
const auto &
color : colors )
357 if (
color.second.isEmpty() )
360 if (
color.second == mLinkedColorName )
371 if ( !mPickingColor )
374 QToolButton::keyPressEvent( e );
379 stopPicking( QCursor::pos(), e->key() == Qt::Key_Space );
384 const bool isProjectColor = linkedProjectColor().isValid();
385 if ( isProjectColor )
390 if ( colorFromMimeData( e->mimeData(), mimeColor ) )
395 e->acceptProposedAction();
409 const bool isProjectColor = linkedProjectColor().isValid();
410 if ( isProjectColor )
415 if ( colorFromMimeData( e->mimeData(), mimeColor ) )
418 e->acceptProposedAction();
420 addRecentColor( mimeColor );
424 void QgsColorButton::setValidColor(
const QColor &newColor )
426 if ( newColor.isValid() )
429 addRecentColor( newColor );
433 void QgsColorButton::setValidTemporaryColor(
const QColor &newColor )
435 if ( newColor.isValid() )
447 pixmap.fill( Qt::transparent );
456 p.setPen( Qt::NoPen );
457 p.setBrush( checkBrush );
462 p.setBrush( QBrush(
color ) );
465 p.setPen( QColor( 197, 197, 197 ) );
471 void QgsColorButton::buttonClicked()
473 if ( linkedProjectColor().isValid() )
475 QToolButton::showMenu();
491 void QgsColorButton::prepareMenu()
499 const bool isProjectColor = linkedProjectColor().isValid();
501 if ( !isProjectColor )
505 QAction *nullAction =
new QAction( mNullColorString.isEmpty() ? tr(
"Clear Color" ) : mNullColorString,
this );
507 mMenu->addAction( nullAction );
512 if ( mDefaultColor.isValid() )
514 QAction *defaultColorAction =
new QAction( tr(
"Default Color" ),
this );
516 mMenu->addAction( defaultColorAction );
520 if ( mShowNoColorOption )
522 QAction *noColorAction =
new QAction( mNoColorString,
this );
523 noColorAction->setIcon(
createMenuIcon( Qt::transparent,
false ) );
524 mMenu->addAction( noColorAction );
528 mMenu->addSeparator();
534 mMenu->addAction( colorAction );
546 mMenu->addAction( alphaAction );
549 if ( mColorSchemeRegistry )
553 QList< QgsColorScheme * >::iterator it = schemeList.begin();
554 for ( ; it != schemeList.end(); ++it )
558 mMenu->addAction( colorAction );
564 mMenu->addSeparator();
567 if ( isProjectColor )
569 QAction *unlinkAction =
new QAction( tr(
"Unlink Color" ), mMenu );
570 mMenu->addAction( unlinkAction );
574 QAction *copyColorAction =
new QAction( tr(
"Copy Color" ),
this );
575 mMenu->addAction( copyColorAction );
578 if ( !isProjectColor )
580 QAction *pasteColorAction =
new QAction( tr(
"Paste Color" ),
this );
584 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor ) )
590 pasteColorAction->setEnabled(
false );
592 mMenu->addAction( pasteColorAction );
595 QAction *pickColorAction =
new QAction( tr(
"Pick Color" ),
this );
596 mMenu->addAction( pickColorAction );
599 QAction *chooseColorAction =
new QAction( tr(
"Choose Color…" ),
this );
600 mMenu->addAction( chooseColorAction );
601 connect( chooseColorAction, &QAction::triggered,
this, &QgsColorButton::showColorDialog );
607 if ( e->type() == QEvent::EnabledChange )
611 QToolButton::changeEvent( e );
615 void QgsColorButton::paintEvent( QPaintEvent *e )
617 QToolButton::paintEvent( e );
619 if ( !mBackgroundSet )
629 QToolButton::showEvent( e );
634 QToolButton::resizeEvent(
event );
642 QColor oldColor = mColor;
646 if ( oldColor != mColor || ( mColor == QColor( Qt::black ) && !mColorSet ) )
659 void QgsColorButton::addRecentColor(
const QColor &color )
666 QColor backgroundColor =
color;
667 bool isProjectColor =
false;
668 if ( !backgroundColor.isValid() && !mLinkedColorName.isEmpty() )
670 backgroundColor = linkedProjectColor();
671 isProjectColor = backgroundColor.isValid();
672 if ( !isProjectColor )
674 mLinkedColorName.clear();
678 if ( !backgroundColor.isValid() )
680 backgroundColor = mColor;
683 QSize currentIconSize;
687 if ( !mIconSize.isValid() )
690 QStyleOptionToolButton opt;
691 initStyleOption( &opt );
692 QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton,
696 mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
698 mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
701 currentIconSize = mIconSize;
707 currentIconSize = QSize( width() - 10, height() - 6 );
709 currentIconSize = QSize( width() - 10, height() - 12 );
713 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
719 QPixmap pixmap( currentIconSize );
720 pixmap.fill( Qt::transparent );
722 if ( backgroundColor.isValid() )
724 QRect rect( 0, 0, currentIconSize.width(), currentIconSize.height() );
727 p.setRenderHint( QPainter::Antialiasing );
728 p.setPen( Qt::NoPen );
729 if ( mAllowOpacity && backgroundColor.alpha() < 255 )
733 p.setBrush( checkBrush );
734 p.drawRoundedRect( rect, 3, 3 );
738 p.setBrush( backgroundColor );
739 p.drawRoundedRect( rect, 3, 3 );
743 setIconSize( currentIconSize );
750 QColor
c = linkedProjectColor();
759 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor ) )
763 addRecentColor( clipColor );
771 mCurrentColor = mColor;
775 mPickingColor =
true;
776 setMouseTracking(
true );
781 QColor
c = linkedProjectColor();
789 mAllowOpacity = allow;
794 mColorDialogTitle = title;
799 return mColorDialogTitle;
805 setMenu(
showMenu ? mMenu :
nullptr );
806 setPopupMode(
showMenu ? QToolButton::MenuButtonPopup : QToolButton::DelayedPopup );
819 mDefaultColor =
color;
825 mNullColorString = nullString;
835 return !mColor.isValid();
840 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.
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.
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