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:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void colorChanged(const QColor &color)
Emitted when a color has been selected from the widget.
Show scheme in color button drop-down menu.
void setAllowOpacity(bool allowOpacity)
Sets whether opacity modification (transparency) is permitted for the color dialog.
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.
void setColor(const QColor &color, bool emitSignals=false) override
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.
A custom QGIS dialog for selecting a color.
static QgsColorSchemeRegistry * colorSchemeRegistry()
Returns the application's color scheme registry, used for managing color schemes. ...
static QMimeData * colorToMimeData(const QColor &color)
Creates mime data from a color.
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.