27 #include <QTemporaryFile> 28 #include <QMouseEvent> 32 #include <QDesktopWidget> 34 #include <QStyleOptionToolButton> 35 #include <QWidgetAction> 38 #include <QGridLayout> 39 #include <QPushButton> 42 : QToolButton( parent )
43 , mColorDialogTitle( cdt.isEmpty() ? tr(
"Select Color" ) : cdt )
44 , mNoColorString( tr(
"No color" ) )
49 setAcceptDrops(
true );
50 setMinimumSize( QSize( 24, 16 ) );
51 connect(
this, &QAbstractButton::clicked,
this, &QgsColorButton::buttonClicked );
54 mMenu =
new QMenu(
this );
55 connect( mMenu, &QMenu::aboutToShow,
this, &QgsColorButton::prepareMenu );
57 setPopupMode( QToolButton::MenuButtonPopup );
60 mMinimumSize = QSize( 120, 22 );
62 mMinimumSize = QSize( 120, 28 );
65 mMinimumSize.setHeight( std::max( static_cast<int>(
Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 1.1 ), mMinimumSize.height() ) );
82 static QPixmap sTranspBkgrd;
84 if ( sTranspBkgrd.isNull() )
90 void QgsColorButton::showColorDialog()
95 QColor currentColor =
color();
100 if ( currentColor.isValid() )
114 bool useNative = settings.
value( QStringLiteral(
"qgis/native_color_dialogs" ),
false ).toBool();
118 newColor = QColorDialog::getColor(
color(),
this, mColorDialogTitle, mAllowOpacity ? QColorDialog::ShowAlphaChannel : ( QColorDialog::ColorDialogOption )0 );
123 dialog.
setTitle( mColorDialogTitle );
128 newColor = dialog.
color();
132 if ( newColor.isValid() )
134 setValidColor( newColor );
143 if ( !mDefaultColor.isValid() )
158 if ( e->type() == QEvent::ToolTip )
160 QString name = this->
color().name();
161 int hue = this->
color().hue();
162 int value = this->
color().value();
163 int saturation = this->
color().saturation();
164 QString info = QString(
"HEX: %1 \n" 166 "HSV: %3,%4,%5" ).arg( name,
168 .arg( hue ).arg( saturation ).arg( value );
171 return QToolButton::event( e );
178 QColor noColor = QColor( mColor );
179 noColor.setAlpha( 0 );
193 if ( e->button() == Qt::RightButton )
195 QToolButton::showMenu();
198 else if ( e->button() == Qt::LeftButton )
200 mDragStartPosition = e->pos();
202 QToolButton::mousePressEvent( e );
205 bool QgsColorButton::colorFromMimeData(
const QMimeData *mimeData, QColor &resultColor )
207 bool hasAlpha =
false;
210 if ( mimeColor.isValid() )
212 if ( !mAllowOpacity )
215 mimeColor.setAlpha( 255 );
217 else if ( !hasAlpha )
220 mimeColor.setAlpha( mColor.alpha() );
222 resultColor = mimeColor;
241 if ( !( e->buttons() & Qt::LeftButton ) || !mColor.isValid() )
244 QToolButton::mouseMoveEvent( e );
248 if ( ( e->pos() - mDragStartPosition ).manhattanLength() < QApplication::startDragDistance() )
251 QToolButton::mouseMoveEvent( e );
256 QDrag *drag =
new QDrag(
this );
259 drag->exec( Qt::CopyAction );
268 stopPicking( e->globalPos() );
273 QToolButton::mouseReleaseEvent( e );
276 void QgsColorButton::stopPicking( QPoint eventPos,
bool samplingColor )
281 QgsApplication::restoreOverrideCursor();
282 setMouseTracking(
false );
283 mPickingColor =
false;
285 if ( !samplingColor )
292 setColor( sampleColor( eventPos ) );
293 addRecentColor( mColor );
298 if ( !mPickingColor )
301 QToolButton::keyPressEvent( e );
306 stopPicking( QCursor::pos(), e->key() == Qt::Key_Space );
313 if ( colorFromMimeData( e->mimeData(), mimeColor ) )
318 e->acceptProposedAction();
334 if ( colorFromMimeData( e->mimeData(), mimeColor ) )
337 e->acceptProposedAction();
339 addRecentColor( mimeColor );
343 QColor QgsColorButton::sampleColor( QPoint point )
const 346 QScreen *screen = findScreenAt( point );
351 QPixmap snappedPixmap = screen->grabWindow( QApplication::desktop()->winId(), point.x(), point.y(), 1, 1 );
352 QImage snappedImage = snappedPixmap.toImage();
353 return snappedImage.pixel( 0, 0 );
356 QScreen *QgsColorButton::findScreenAt( QPoint pos )
358 for ( QScreen *screen : QGuiApplication::screens() )
360 if ( screen->geometry().contains( pos ) )
368 void QgsColorButton::setValidColor(
const QColor &newColor )
370 if ( newColor.isValid() )
373 addRecentColor( newColor );
377 void QgsColorButton::setValidTemporaryColor(
const QColor &newColor )
379 if ( newColor.isValid() )
385 QPixmap QgsColorButton::createMenuIcon(
const QColor &
color,
const bool showChecks )
388 QPixmap pixmap( 16, 16 );
389 pixmap.fill( Qt::transparent );
398 p.setPen( Qt::NoPen );
399 p.setBrush( checkBrush );
400 p.drawRect( 0, 0, 15, 15 );
404 p.setBrush( QBrush(
color ) );
407 p.setPen( QColor( 197, 197, 197 ) );
408 p.drawRect( 0, 0, 15, 15 );
413 void QgsColorButton::buttonClicked()
426 void QgsColorButton::prepareMenu()
436 QAction *nullAction =
new QAction( tr(
"Clear Color" ),
this );
437 nullAction->setIcon( createMenuIcon( Qt::transparent,
false ) );
438 mMenu->addAction( nullAction );
443 if ( mDefaultColor.isValid() )
445 QAction *defaultColorAction =
new QAction( tr(
"Default Color" ),
this );
446 defaultColorAction->setIcon( createMenuIcon( mDefaultColor ) );
447 mMenu->addAction( defaultColorAction );
451 if ( mShowNoColorOption && mAllowOpacity )
453 QAction *noColorAction =
new QAction( mNoColorString,
this );
454 noColorAction->setIcon( createMenuIcon( Qt::transparent,
false ) );
455 mMenu->addAction( noColorAction );
459 mMenu->addSeparator();
465 mMenu->addAction( colorAction );
477 mMenu->addAction( alphaAction );
480 if ( mColorSchemeRegistry )
484 QList< QgsColorScheme * >::iterator it = schemeList.begin();
485 for ( ; it != schemeList.end(); ++it )
489 mMenu->addAction( colorAction );
495 mMenu->addSeparator();
497 QAction *copyColorAction =
new QAction( tr(
"Copy Color" ),
this );
498 mMenu->addAction( copyColorAction );
501 QAction *pasteColorAction =
new QAction( tr(
"Paste Color" ),
this );
505 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor ) )
507 pasteColorAction->setIcon( createMenuIcon( clipColor ) );
511 pasteColorAction->setEnabled(
false );
513 mMenu->addAction( pasteColorAction );
519 QAction *pickColorAction =
new QAction( tr(
"Pick Color" ),
this );
520 mMenu->addAction( pickColorAction );
523 QAction *chooseColorAction =
new QAction( tr(
"Choose Color…" ),
this );
524 mMenu->addAction( chooseColorAction );
525 connect( chooseColorAction, &QAction::triggered,
this, &QgsColorButton::showColorDialog );
530 if ( e->type() == QEvent::EnabledChange )
534 QToolButton::changeEvent( e );
537 #if 0 // causes too many cyclical updates, but may be needed on some platforms 538 void QgsColorButton::paintEvent( QPaintEvent *e )
540 QToolButton::paintEvent( e );
542 if ( !mBackgroundSet )
552 QToolButton::showEvent( e );
557 QToolButton::resizeEvent( event );
565 QColor oldColor = mColor;
569 if ( oldColor != mColor || ( mColor == QColor( Qt::black ) && !mColorSet ) )
582 void QgsColorButton::addRecentColor(
const QColor &
color )
589 QColor backgroundColor =
color;
591 if ( !color.isValid() )
593 backgroundColor = mColor;
596 QSize currentIconSize;
600 if ( !mIconSize.isValid() )
603 QStyleOptionToolButton opt;
604 initStyleOption( &opt );
605 QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton,
609 mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
611 mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
614 currentIconSize = mIconSize;
620 currentIconSize = QSize( width() - 10, height() - 6 );
622 currentIconSize = QSize( width() - 10, height() - 12 );
626 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
632 QPixmap pixmap( currentIconSize );
633 pixmap.fill( Qt::transparent );
635 if ( backgroundColor.isValid() )
637 QRect rect( 0, 0, currentIconSize.width(), currentIconSize.height() );
640 p.setRenderHint( QPainter::Antialiasing );
641 p.setPen( Qt::NoPen );
642 if ( mAllowOpacity && backgroundColor.alpha() < 255 )
646 p.setBrush( checkBrush );
647 p.drawRoundedRect( rect, 3, 3 );
651 p.setBrush( backgroundColor );
652 p.drawRoundedRect( rect, 3, 3 );
656 setIconSize( currentIconSize );
669 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor ) )
673 addRecentColor( clipColor );
681 mCurrentColor = mColor;
685 mPickingColor =
true;
686 setMouseTracking(
true );
696 mAllowOpacity = allow;
701 mColorDialogTitle = title;
706 return mColorDialogTitle;
711 setMenu( showMenu ? mMenu :
nullptr );
712 setPopupMode( showMenu ? QToolButton::MenuButtonPopup : QToolButton::DelayedPopup );
725 mDefaultColor =
color;
740 return !mColor.isValid();
A color swatch grid which can be embedded into a menu.
Registry of color schemes.
static const double UI_SCALE_FACTOR
UI scaling factor.
This class is a composition of two QSettings instances:
void colorChanged(const QColor &color)
Emitted when a color has been selected from the widget.
Show scheme in color button drop-down menu.
static QPixmap getThemePixmap(const QString &name)
Helper to get a theme icon as a pixmap.
static QString encodeColor(const QColor &color)
QList< QgsColorScheme * > schemes() const
Returns all color schemes in the registry.
void setTitle(const QString &title)
Sets the title for the color dialog.
static void addRecentColor(const QColor &color)
Adds a color to the list of recent colors.
QColor color() const
Returns the current color for the dialog.
void setAllowOpacity(const bool allowOpacity)
Sets whether opacity modification (transparency) is permitted for the color dialog.
A custom QGIS dialog for selecting a color.
static QgsColorSchemeRegistry * colorSchemeRegistry()
Returns the application's color scheme registry, used for managing color schemes. ...
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=NoSection) const
Returns the value for setting key.
static QMimeData * colorToMimeData(const QColor &color)
Creates mime data from a color.
void setColor(const QColor &color, const bool emitSignals=false) override
static QCursor getThemeCursor(Cursor cursor)
Helper to get a theme cursor.
static QColor colorFromMimeData(const QMimeData *data, bool &hasAlpha)
Attempts to parse mime data as a color.
void setBaseColor(const QColor &baseColor)
Sets the base color for the color grid.