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() ) );
92 static QPixmap sTranspBkgrd;
94 if ( sTranspBkgrd.isNull() )
100 void QgsColorButton::showColorDialog()
105 QColor currentColor =
color();
110 if ( currentColor.isValid() )
124 bool useNative = settings.
value( QStringLiteral(
"qgis/native_color_dialogs" ),
false ).toBool();
128 newColor = QColorDialog::getColor(
color(),
this, mColorDialogTitle, mAllowOpacity ? QColorDialog::ShowAlphaChannel : ( QColorDialog::ColorDialogOption )0 );
133 dialog.setTitle( mColorDialogTitle );
134 dialog.setAllowOpacity( mAllowOpacity );
138 newColor = dialog.color();
142 if ( newColor.isValid() )
144 setValidColor( newColor );
153 if ( !mDefaultColor.isValid() )
175 if ( e->type() == QEvent::ToolTip )
177 QColor
c = linkedProjectColor();
178 bool isProjectColor =
c.isValid();
179 if ( !isProjectColor )
182 QString name =
c.name();
184 int value =
c.value();
185 int saturation =
c.saturation();
188 #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
191 int width =
static_cast< int >(
Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance(
'X' ) * 23 );
193 int height =
static_cast< int >( width / 1.61803398875 );
195 int margin =
static_cast< int >( height * 0.1 );
196 QImage icon = QImage( width + 2 * margin, height + 2 * margin, QImage::Format_ARGB32 );
197 icon.fill( Qt::transparent );
204 p.setPen( Qt::NoPen );
205 p.setBrush( checkBrush );
206 p.drawRect( margin, margin, width, height );
209 p.setBrush( QBrush(
c ) );
212 p.setPen( QColor( 197, 197, 197 ) );
213 p.drawRect( margin, margin, width, height );
217 QBuffer buffer( &data );
218 icon.save( &buffer,
"PNG", 100 );
220 QString info = ( isProjectColor ? QStringLiteral(
"<p>%1: %2</p>" ).arg( tr(
"Linked color" ), mLinkedColorName ) : QString() )
221 + QStringLiteral(
"<b>HEX</b> %1<br>"
223 "<b>HSV</b> %3,%4,%5<p>"
224 "<img src='data:image/png;base64, %0'>" ).arg( QString( data.toBase64() ), name,
226 .arg( hue ).arg( saturation ).arg( value );
229 return QToolButton::event( e );
234 QColor noColor = QColor( mColor );
235 noColor.setAlpha( 0 );
248 if ( e->button() == Qt::RightButton )
250 QToolButton::showMenu();
253 else if ( e->button() == Qt::LeftButton )
255 mDragStartPosition = e->pos();
257 QToolButton::mousePressEvent( e );
260 bool QgsColorButton::colorFromMimeData(
const QMimeData *mimeData, QColor &resultColor )
262 bool hasAlpha =
false;
265 if ( mimeColor.isValid() )
267 if ( !mAllowOpacity )
270 mimeColor.setAlpha( 255 );
272 else if ( !hasAlpha )
275 mimeColor.setAlpha( mColor.alpha() );
277 resultColor = mimeColor;
295 QColor
c = linkedProjectColor();
299 if ( !( e->buttons() & Qt::LeftButton ) || !
c.isValid() )
302 QToolButton::mouseMoveEvent( e );
306 if ( ( e->pos() - mDragStartPosition ).manhattanLength() < QApplication::startDragDistance() )
309 QToolButton::mouseMoveEvent( e );
314 QDrag *drag =
new QDrag(
this );
317 drag->exec( Qt::CopyAction );
326 stopPicking( e->globalPos() );
331 QToolButton::mouseReleaseEvent( e );
334 void QgsColorButton::stopPicking( QPoint eventPos,
bool samplingColor )
339 QgsApplication::restoreOverrideCursor();
340 setMouseTracking(
false );
341 mPickingColor =
false;
343 if ( !samplingColor )
351 addRecentColor( mColor );
354 QColor QgsColorButton::linkedProjectColor()
const
356 QList<QgsProjectColorScheme *> projectSchemes;
358 if ( projectSchemes.length() > 0 )
362 for (
const auto &
color : colors )
364 if (
color.second.isEmpty() )
367 if (
color.second == mLinkedColorName )
378 if ( !mPickingColor )
381 QToolButton::keyPressEvent( e );
386 stopPicking( QCursor::pos(), e->key() == Qt::Key_Space );
391 const bool isProjectColor = linkedProjectColor().isValid();
392 if ( isProjectColor )
397 if ( colorFromMimeData( e->mimeData(), mimeColor ) )
402 e->acceptProposedAction();
416 const bool isProjectColor = linkedProjectColor().isValid();
417 if ( isProjectColor )
422 if ( colorFromMimeData( e->mimeData(), mimeColor ) )
425 e->acceptProposedAction();
427 addRecentColor( mimeColor );
431 void QgsColorButton::setValidColor(
const QColor &newColor )
433 if ( newColor.isValid() )
436 addRecentColor( newColor );
440 void QgsColorButton::setValidTemporaryColor(
const QColor &newColor )
442 if ( newColor.isValid() )
454 pixmap.fill( Qt::transparent );
463 p.setPen( Qt::NoPen );
464 p.setBrush( checkBrush );
469 p.setBrush( QBrush(
color ) );
472 p.setPen( QColor( 197, 197, 197 ) );
478 void QgsColorButton::buttonClicked()
480 if ( linkedProjectColor().isValid() )
482 QToolButton::showMenu();
498 void QgsColorButton::prepareMenu()
506 const bool isProjectColor = linkedProjectColor().isValid();
508 if ( !isProjectColor )
512 QAction *nullAction =
new QAction( mNullColorString.isEmpty() ? tr(
"Clear Color" ) : mNullColorString,
this );
514 mMenu->addAction( nullAction );
519 if ( mDefaultColor.isValid() )
521 QAction *defaultColorAction =
new QAction( tr(
"Default Color" ),
this );
523 mMenu->addAction( defaultColorAction );
527 if ( mShowNoColorOption )
529 QAction *noColorAction =
new QAction( mNoColorString,
this );
530 noColorAction->setIcon(
createMenuIcon( Qt::transparent,
false ) );
531 mMenu->addAction( noColorAction );
535 mMenu->addSeparator();
541 mMenu->addAction( colorAction );
553 mMenu->addAction( alphaAction );
556 if ( mColorSchemeRegistry )
560 QList< QgsColorScheme * >::iterator it = schemeList.begin();
561 for ( ; it != schemeList.end(); ++it )
565 mMenu->addAction( colorAction );
571 mMenu->addSeparator();
574 if ( isProjectColor )
576 QAction *unlinkAction =
new QAction( tr(
"Unlink Color" ), mMenu );
577 mMenu->addAction( unlinkAction );
581 QAction *copyColorAction =
new QAction( tr(
"Copy Color" ),
this );
582 mMenu->addAction( copyColorAction );
585 if ( !isProjectColor )
587 QAction *pasteColorAction =
new QAction( tr(
"Paste Color" ),
this );
591 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor ) )
597 pasteColorAction->setEnabled(
false );
599 mMenu->addAction( pasteColorAction );
602 QAction *pickColorAction =
new QAction( tr(
"Pick Color" ),
this );
603 mMenu->addAction( pickColorAction );
606 QAction *chooseColorAction =
new QAction( tr(
"Choose Color…" ),
this );
607 mMenu->addAction( chooseColorAction );
608 connect( chooseColorAction, &QAction::triggered,
this, &QgsColorButton::showColorDialog );
614 if ( e->type() == QEvent::EnabledChange )
618 QToolButton::changeEvent( e );
622 void QgsColorButton::paintEvent( QPaintEvent *e )
624 QToolButton::paintEvent( e );
626 if ( !mBackgroundSet )
636 QToolButton::showEvent( e );
641 QToolButton::resizeEvent(
event );
649 QColor oldColor = mColor;
653 if ( oldColor != mColor || ( mColor == QColor( Qt::black ) && !mColorSet ) )
666 void QgsColorButton::addRecentColor(
const QColor &color )
673 QColor backgroundColor =
color;
674 bool isProjectColor =
false;
675 if ( !backgroundColor.isValid() && !mLinkedColorName.isEmpty() )
677 backgroundColor = linkedProjectColor();
678 isProjectColor = backgroundColor.isValid();
679 if ( !isProjectColor )
681 mLinkedColorName.clear();
685 if ( !backgroundColor.isValid() )
687 backgroundColor = mColor;
690 QSize currentIconSize;
694 if ( !mIconSize.isValid() )
697 QStyleOptionToolButton opt;
698 initStyleOption( &opt );
699 QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton,
703 mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
705 mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
708 currentIconSize = mIconSize;
714 currentIconSize = QSize( width() - 10, height() - 6 );
716 currentIconSize = QSize( width() - 10, height() - 12 );
720 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
726 QPixmap pixmap( currentIconSize );
727 pixmap.fill( Qt::transparent );
729 if ( backgroundColor.isValid() )
731 QRect rect( 0, 0, currentIconSize.width(), currentIconSize.height() );
734 p.setRenderHint( QPainter::Antialiasing );
735 p.setPen( Qt::NoPen );
736 if ( mAllowOpacity && backgroundColor.alpha() < 255 )
740 p.setBrush( checkBrush );
741 p.drawRoundedRect( rect, 3, 3 );
745 p.setBrush( backgroundColor );
746 p.drawRoundedRect( rect, 3, 3 );
750 setIconSize( currentIconSize );
757 QColor
c = linkedProjectColor();
766 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor ) )
770 addRecentColor( clipColor );
778 mCurrentColor = mColor;
782 mPickingColor =
true;
783 setMouseTracking(
true );
788 QColor
c = linkedProjectColor();
796 mAllowOpacity = allow;
801 mColorDialogTitle = title;
806 return mColorDialogTitle;
812 setMenu(
showMenu ? mMenu :
nullptr );
813 setPopupMode(
showMenu ? QToolButton::MenuButtonPopup : QToolButton::DelayedPopup );
826 mDefaultColor =
color;
832 mNullColorString = nullString;
842 return !mColor.isValid();
847 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.
This class is a composition of two QSettings instances:
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