30 #include <QMouseEvent> 
   35 #include <QStyleOptionToolButton> 
   36 #include <QWidgetAction> 
   39 #include <QGridLayout> 
   40 #include <QPushButton> 
   44   : QToolButton( parent )
 
   45   , mColorDialogTitle( cdt.isEmpty() ? tr( 
"Select Color" ) : cdt )
 
   46   , mNoColorString( tr( 
"No color" ) )
 
   51   setAcceptDrops( 
true );
 
   52   setMinimumSize( QSize( 24, 16 ) );
 
   53   connect( 
this, &QAbstractButton::clicked, 
this, &QgsColorButton::buttonClicked );
 
   56   mMenu = 
new QMenu( 
this );
 
   57   connect( mMenu, &QMenu::aboutToShow, 
this, &QgsColorButton::prepareMenu );
 
   59   setPopupMode( QToolButton::MenuButtonPopup );
 
   62   mMinimumSize = QSize( 120, 22 );
 
   64   mMinimumSize = QSize( 120, 28 );
 
   67   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() )
 
   96 void 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 )
 
  173     QColor 
c = linkedProjectColor();
 
  174     const bool isProjectColor = 
c.isValid();
 
  175     if ( !isProjectColor )
 
  178     const QString name = 
c.name();
 
  179     const int hue = 
c.hue();
 
  180     const int value = 
c.value();
 
  181     const int saturation = 
c.saturation();
 
  184     const int width = 
static_cast< int >( 
Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 
'X' ) * 23 );
 
  185     const int height = 
static_cast< int >( width / 1.61803398875 ); 
 
  187     const int margin = 
static_cast< int >( height * 0.1 );
 
  188     QImage icon = QImage( width + 2 * margin, height + 2 * margin, QImage::Format_ARGB32 );
 
  189     icon.fill( Qt::transparent );
 
  196     p.setPen( Qt::NoPen );
 
  197     p.setBrush( checkBrush );
 
  198     p.drawRect( margin, margin, width, height );
 
  201     p.setBrush( QBrush( 
c ) );
 
  204     p.setPen( QColor( 197, 197, 197 ) );
 
  205     p.drawRect( margin, margin, width, height );
 
  209     QBuffer buffer( &data );
 
  210     icon.save( &buffer, 
"PNG", 100 );
 
  212     const QString info = ( isProjectColor ? QStringLiteral( 
"<p>%1: %2</p>" ).arg( tr( 
"Linked color" ), mLinkedColorName ) : QString() )
 
  213                          + QStringLiteral( 
"<b>HEX</b> %1<br>" 
  215                                            "<b>HSV</b> %3,%4,%5<p>" 
  216                                            "<img src='data:image/png;base64, %0'>" ).arg( QString( data.toBase64() ), name,
 
  218                          .arg( hue ).arg( saturation ).arg( value );
 
  221   return QToolButton::event( e );
 
  226   QColor noColor = QColor( mColor );
 
  227   noColor.setAlpha( 0 );
 
  240   if ( e->button() == Qt::RightButton )
 
  242     QToolButton::showMenu();
 
  245   else if ( e->button() == Qt::LeftButton )
 
  247     mDragStartPosition = e->pos();
 
  249   QToolButton::mousePressEvent( e );
 
  252 bool QgsColorButton::colorFromMimeData( 
const QMimeData *mimeData, QColor &resultColor )
 
  254   bool hasAlpha = 
false;
 
  257   if ( mimeColor.isValid() )
 
  259     if ( !mAllowOpacity )
 
  262       mimeColor.setAlpha( 255 );
 
  264     else if ( !hasAlpha )
 
  267       mimeColor.setAlpha( mColor.alpha() );
 
  269     resultColor = mimeColor;
 
  287   QColor 
c = linkedProjectColor();
 
  291   if ( !( e->buttons() & Qt::LeftButton ) || !
c.isValid() )
 
  294     QToolButton::mouseMoveEvent( e );
 
  298   if ( ( e->pos() - mDragStartPosition ).manhattanLength() < QApplication::startDragDistance() )
 
  301     QToolButton::mouseMoveEvent( e );
 
  306   QDrag *drag = 
new QDrag( 
this );
 
  309   drag->exec( Qt::CopyAction );
 
  318     stopPicking( e->globalPos() );
 
  323   QToolButton::mouseReleaseEvent( e );
 
  326 void QgsColorButton::stopPicking( QPoint eventPos, 
bool samplingColor )
 
  331   QgsApplication::restoreOverrideCursor();
 
  332   setMouseTracking( 
false );
 
  333   mPickingColor = 
false;
 
  335   if ( !samplingColor )
 
  343   addRecentColor( mColor );
 
  346 QColor QgsColorButton::linkedProjectColor()
 const 
  348   QList<QgsProjectColorScheme *> projectSchemes;
 
  350   if ( projectSchemes.length() > 0 )
 
  354     for ( 
const auto &
color : colors )
 
  356       if ( 
color.second.isEmpty() )
 
  359       if ( 
color.second == mLinkedColorName )
 
  370   if ( !mPickingColor )
 
  373     QToolButton::keyPressEvent( e );
 
  378   stopPicking( QCursor::pos(), e->key() == Qt::Key_Space );
 
  383   const bool isProjectColor = linkedProjectColor().isValid();
 
  384   if ( isProjectColor )
 
  389   if ( colorFromMimeData( e->mimeData(), mimeColor ) )
 
  394     e->acceptProposedAction();
 
  408   const bool isProjectColor = linkedProjectColor().isValid();
 
  409   if ( isProjectColor )
 
  414   if ( colorFromMimeData( e->mimeData(), mimeColor ) )
 
  417     e->acceptProposedAction();
 
  419     addRecentColor( mimeColor );
 
  423 void QgsColorButton::setValidColor( 
const QColor &newColor )
 
  425   if ( newColor.isValid() )
 
  428     addRecentColor( newColor );
 
  432 void QgsColorButton::setValidTemporaryColor( 
const QColor &newColor )
 
  434   if ( newColor.isValid() )
 
  446   pixmap.fill( Qt::transparent );
 
  455     p.setPen( Qt::NoPen );
 
  456     p.setBrush( checkBrush );
 
  461   p.setBrush( QBrush( 
color ) );
 
  464   p.setPen( QColor( 197, 197, 197 ) );
 
  470 void QgsColorButton::buttonClicked()
 
  472   if ( linkedProjectColor().isValid() )
 
  474     QToolButton::showMenu();
 
  490 void QgsColorButton::prepareMenu()
 
  498   const bool isProjectColor = linkedProjectColor().isValid();
 
  500   if ( !isProjectColor )
 
  504       QAction *nullAction = 
new QAction( mNullColorString.isEmpty() ? tr( 
"Clear Color" ) : mNullColorString, 
this );
 
  506       mMenu->addAction( nullAction );
 
  511     if ( mDefaultColor.isValid() )
 
  513       QAction *defaultColorAction = 
new QAction( tr( 
"Default Color" ), 
this );
 
  515       mMenu->addAction( defaultColorAction );
 
  519     if ( mShowNoColorOption )
 
  521       QAction *noColorAction = 
new QAction( mNoColorString, 
this );
 
  522       noColorAction->setIcon( 
createMenuIcon( Qt::transparent, 
false ) );
 
  523       mMenu->addAction( noColorAction );
 
  527     mMenu->addSeparator();
 
  533     mMenu->addAction( colorAction );
 
  545       mMenu->addAction( alphaAction );
 
  548     if ( mColorSchemeRegistry )
 
  552       QList< QgsColorScheme * >::iterator it = schemeList.begin();
 
  553       for ( ; it != schemeList.end(); ++it )
 
  557         mMenu->addAction( colorAction );
 
  563     mMenu->addSeparator();
 
  566   if ( isProjectColor )
 
  568     QAction *unlinkAction = 
new QAction( tr( 
"Unlink Color" ), mMenu );
 
  569     mMenu->addAction( unlinkAction );
 
  573   QAction *copyColorAction = 
new QAction( tr( 
"Copy Color" ), 
this );
 
  574   mMenu->addAction( copyColorAction );
 
  577   if ( !isProjectColor )
 
  579     QAction *pasteColorAction = 
new QAction( tr( 
"Paste Color" ), 
this );
 
  583     if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor ) )
 
  589       pasteColorAction->setEnabled( 
false );
 
  591     mMenu->addAction( pasteColorAction );
 
  594     QAction *pickColorAction = 
new QAction( tr( 
"Pick Color" ), 
this );
 
  595     mMenu->addAction( pickColorAction );
 
  598     QAction *chooseColorAction = 
new QAction( tr( 
"Choose Color…" ), 
this );
 
  599     mMenu->addAction( chooseColorAction );
 
  600     connect( chooseColorAction, &QAction::triggered, 
this, &QgsColorButton::showColorDialog );
 
  606   if ( e->type() == QEvent::EnabledChange )
 
  610   QToolButton::changeEvent( e );
 
  614 void QgsColorButton::paintEvent( QPaintEvent *e )
 
  616   QToolButton::paintEvent( e );
 
  618   if ( !mBackgroundSet )
 
  628   QToolButton::showEvent( e );
 
  633   QToolButton::resizeEvent( 
event );
 
  641   const QColor oldColor = mColor;
 
  645   if ( oldColor != mColor || ( mColor == QColor( Qt::black ) && !mColorSet ) )
 
  658 void QgsColorButton::addRecentColor( 
const QColor &color )
 
  665   QColor backgroundColor = 
color;
 
  666   bool isProjectColor = 
false;
 
  667   if ( !backgroundColor.isValid() && !mLinkedColorName.isEmpty() )
 
  669     backgroundColor = linkedProjectColor();
 
  670     isProjectColor = backgroundColor.isValid();
 
  671     if ( !isProjectColor )
 
  673       mLinkedColorName.clear(); 
 
  677   if ( !backgroundColor.isValid() )
 
  679     backgroundColor = mColor;
 
  682   QSize currentIconSize;
 
  686     if ( !mIconSize.isValid() )
 
  689       QStyleOptionToolButton opt;
 
  690       initStyleOption( &opt );
 
  691       const QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton,
 
  695       mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
 
  697       mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
 
  700     currentIconSize = mIconSize;
 
  706     currentIconSize = QSize( width() - 10, height() - 6 );
 
  708     currentIconSize = QSize( width() - 10, height() - 12 );
 
  712   if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
 
  718   QPixmap pixmap( currentIconSize );
 
  719   pixmap.fill( Qt::transparent );
 
  721   if ( backgroundColor.isValid() )
 
  723     const QRect rect( 0, 0, currentIconSize.width(), currentIconSize.height() );
 
  726     p.setRenderHint( QPainter::Antialiasing );
 
  727     p.setPen( Qt::NoPen );
 
  728     if ( mAllowOpacity && backgroundColor.alpha() < 255 )
 
  732       p.setBrush( checkBrush );
 
  733       p.drawRoundedRect( rect, 3, 3 );
 
  737     p.setBrush( backgroundColor );
 
  738     p.drawRoundedRect( rect, 3, 3 );
 
  742   setIconSize( currentIconSize );
 
  749   QColor 
c = linkedProjectColor();
 
  758   if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor ) )
 
  762     addRecentColor( clipColor );
 
  770   mCurrentColor = mColor;
 
  774   mPickingColor = 
true;
 
  775   setMouseTracking( 
true );
 
  780   QColor 
c = linkedProjectColor();
 
  788   mAllowOpacity = allow;
 
  793   mColorDialogTitle = title;
 
  798   return mColorDialogTitle;
 
  804   setMenu( 
showMenu ? mMenu : 
nullptr );
 
  805   setPopupMode( 
showMenu ? QToolButton::MenuButtonPopup : QToolButton::DelayedPopup );
 
  818   mDefaultColor = 
color;
 
  824   mNullColorString = nullString;
 
  834   return !mColor.isValid();
 
  839   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