30 #include <QMouseEvent>
34 #include <QDesktopWidget>
36 #include <QStyleOptionToolButton>
37 #include <QWidgetAction>
40 #include <QGridLayout>
41 #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() ) );
91 static QPixmap sTranspBkgrd;
93 if ( sTranspBkgrd.isNull() )
99 void QgsColorButton::showColorDialog()
104 QColor currentColor =
color();
109 if ( currentColor.isValid() )
123 bool useNative = settings.
value( QStringLiteral(
"qgis/native_color_dialogs" ),
false ).toBool();
127 newColor = QColorDialog::getColor(
color(),
this, mColorDialogTitle, mAllowOpacity ? QColorDialog::ShowAlphaChannel : ( QColorDialog::ColorDialogOption )0 );
132 dialog.setTitle( mColorDialogTitle );
133 dialog.setAllowOpacity( mAllowOpacity );
137 newColor = dialog.color();
141 if ( newColor.isValid() )
143 setValidColor( newColor );
152 if ( !mDefaultColor.isValid() )
174 if ( e->type() == QEvent::ToolTip )
176 QColor
c = linkedProjectColor();
177 bool isProjectColor =
c.isValid();
178 if ( !isProjectColor )
181 QString name =
c.name();
183 int value =
c.value();
184 int saturation =
c.saturation();
187 #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
190 int width =
static_cast< int >(
Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance(
'X' ) * 23 );
192 int height =
static_cast< int >( width / 1.61803398875 );
194 int margin =
static_cast< int >( height * 0.1 );
195 QImage icon = QImage( width + 2 * margin, height + 2 * margin, QImage::Format_ARGB32 );
196 icon.fill( Qt::transparent );
203 p.setPen( Qt::NoPen );
204 p.setBrush( checkBrush );
205 p.drawRect( margin, margin, width, height );
208 p.setBrush( QBrush(
c ) );
211 p.setPen( QColor( 197, 197, 197 ) );
212 p.drawRect( margin, margin, width, height );
216 QBuffer buffer( &data );
217 icon.save( &buffer,
"PNG", 100 );
219 QString info = ( isProjectColor ? QStringLiteral(
"<p>%1: %2</p>" ).arg( tr(
"Linked color" ), mLinkedColorName ) : QString() )
220 + QStringLiteral(
"<b>HEX</b> %1<br>"
222 "<b>HSV</b> %3,%4,%5<p>"
223 "<img src='data:image/png;base64, %0'>" ).arg( QString( data.toBase64() ), name,
225 .arg( hue ).arg( saturation ).arg( value );
228 return QToolButton::event( e );
233 QColor noColor = QColor( mColor );
234 noColor.setAlpha( 0 );
247 if ( e->button() == Qt::RightButton )
249 QToolButton::showMenu();
252 else if ( e->button() == Qt::LeftButton )
254 mDragStartPosition = e->pos();
256 QToolButton::mousePressEvent( e );
259 bool QgsColorButton::colorFromMimeData(
const QMimeData *mimeData, QColor &resultColor )
261 bool hasAlpha =
false;
264 if ( mimeColor.isValid() )
266 if ( !mAllowOpacity )
269 mimeColor.setAlpha( 255 );
271 else if ( !hasAlpha )
274 mimeColor.setAlpha( mColor.alpha() );
276 resultColor = mimeColor;
294 QColor
c = linkedProjectColor();
298 if ( !( e->buttons() & Qt::LeftButton ) || !
c.isValid() )
301 QToolButton::mouseMoveEvent( e );
305 if ( ( e->pos() - mDragStartPosition ).manhattanLength() < QApplication::startDragDistance() )
308 QToolButton::mouseMoveEvent( e );
313 QDrag *drag =
new QDrag(
this );
316 drag->exec( Qt::CopyAction );
325 stopPicking( e->globalPos() );
330 QToolButton::mouseReleaseEvent( e );
333 void QgsColorButton::stopPicking( QPoint eventPos,
bool samplingColor )
338 QgsApplication::restoreOverrideCursor();
339 setMouseTracking(
false );
340 mPickingColor =
false;
342 if ( !samplingColor )
350 addRecentColor( mColor );
353 QColor QgsColorButton::linkedProjectColor()
const
355 QList<QgsProjectColorScheme *> projectSchemes;
357 if ( projectSchemes.length() > 0 )
361 for (
const auto &
color : colors )
363 if (
color.second.isEmpty() )
366 if (
color.second == mLinkedColorName )
377 if ( !mPickingColor )
380 QToolButton::keyPressEvent( e );
385 stopPicking( QCursor::pos(), e->key() == Qt::Key_Space );
390 const bool isProjectColor = linkedProjectColor().isValid();
391 if ( isProjectColor )
396 if ( colorFromMimeData( e->mimeData(), mimeColor ) )
401 e->acceptProposedAction();
415 const bool isProjectColor = linkedProjectColor().isValid();
416 if ( isProjectColor )
421 if ( colorFromMimeData( e->mimeData(), mimeColor ) )
424 e->acceptProposedAction();
426 addRecentColor( mimeColor );
430 void QgsColorButton::setValidColor(
const QColor &newColor )
432 if ( newColor.isValid() )
435 addRecentColor( newColor );
439 void QgsColorButton::setValidTemporaryColor(
const QColor &newColor )
441 if ( newColor.isValid() )
453 pixmap.fill( Qt::transparent );
462 p.setPen( Qt::NoPen );
463 p.setBrush( checkBrush );
468 p.setBrush( QBrush(
color ) );
471 p.setPen( QColor( 197, 197, 197 ) );
477 void QgsColorButton::buttonClicked()
479 if ( linkedProjectColor().isValid() )
481 QToolButton::showMenu();
497 void QgsColorButton::prepareMenu()
505 const bool isProjectColor = linkedProjectColor().isValid();
507 if ( !isProjectColor )
511 QAction *nullAction =
new QAction( mNullColorString.isEmpty() ? tr(
"Clear Color" ) : mNullColorString,
this );
513 mMenu->addAction( nullAction );
518 if ( mDefaultColor.isValid() )
520 QAction *defaultColorAction =
new QAction( tr(
"Default Color" ),
this );
522 mMenu->addAction( defaultColorAction );
526 if ( mShowNoColorOption )
528 QAction *noColorAction =
new QAction( mNoColorString,
this );
529 noColorAction->setIcon(
createMenuIcon( Qt::transparent,
false ) );
530 mMenu->addAction( noColorAction );
534 mMenu->addSeparator();
540 mMenu->addAction( colorAction );
552 mMenu->addAction( alphaAction );
555 if ( mColorSchemeRegistry )
559 QList< QgsColorScheme * >::iterator it = schemeList.begin();
560 for ( ; it != schemeList.end(); ++it )
564 mMenu->addAction( colorAction );
570 mMenu->addSeparator();
573 if ( isProjectColor )
575 QAction *unlinkAction =
new QAction( tr(
"Unlink Color" ), mMenu );
576 mMenu->addAction( unlinkAction );
580 QAction *copyColorAction =
new QAction( tr(
"Copy Color" ),
this );
581 mMenu->addAction( copyColorAction );
584 if ( !isProjectColor )
586 QAction *pasteColorAction =
new QAction( tr(
"Paste Color" ),
this );
590 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor ) )
596 pasteColorAction->setEnabled(
false );
598 mMenu->addAction( pasteColorAction );
601 QAction *pickColorAction =
new QAction( tr(
"Pick Color" ),
this );
602 mMenu->addAction( pickColorAction );
605 QAction *chooseColorAction =
new QAction( tr(
"Choose Color…" ),
this );
606 mMenu->addAction( chooseColorAction );
607 connect( chooseColorAction, &QAction::triggered,
this, &QgsColorButton::showColorDialog );
613 if ( e->type() == QEvent::EnabledChange )
617 QToolButton::changeEvent( e );
620 #if 0 // causes too many cyclical updates, but may be needed on some platforms
621 void QgsColorButton::paintEvent( QPaintEvent *e )
623 QToolButton::paintEvent( e );
625 if ( !mBackgroundSet )
635 QToolButton::showEvent( e );
640 QToolButton::resizeEvent(
event );
648 QColor oldColor = mColor;
652 if ( oldColor != mColor || ( mColor == QColor( Qt::black ) && !mColorSet ) )
665 void QgsColorButton::addRecentColor(
const QColor &color )
672 QColor backgroundColor =
color;
673 bool isProjectColor =
false;
674 if ( !backgroundColor.isValid() && !mLinkedColorName.isEmpty() )
676 backgroundColor = linkedProjectColor();
677 isProjectColor = backgroundColor.isValid();
678 if ( !isProjectColor )
680 mLinkedColorName.clear();
684 if ( !backgroundColor.isValid() )
686 backgroundColor = mColor;
689 QSize currentIconSize;
693 if ( !mIconSize.isValid() )
696 QStyleOptionToolButton opt;
697 initStyleOption( &opt );
698 QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton,
702 mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
704 mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
707 currentIconSize = mIconSize;
713 currentIconSize = QSize( width() - 10, height() - 6 );
715 currentIconSize = QSize( width() - 10, height() - 12 );
719 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
725 QPixmap pixmap( currentIconSize );
726 pixmap.fill( Qt::transparent );
728 if ( backgroundColor.isValid() )
730 QRect rect( 0, 0, currentIconSize.width(), currentIconSize.height() );
733 p.setRenderHint( QPainter::Antialiasing );
734 p.setPen( Qt::NoPen );
735 if ( mAllowOpacity && backgroundColor.alpha() < 255 )
739 p.setBrush( checkBrush );
740 p.drawRoundedRect( rect, 3, 3 );
744 p.setBrush( backgroundColor );
745 p.drawRoundedRect( rect, 3, 3 );
749 setIconSize( currentIconSize );
756 QColor
c = linkedProjectColor();
765 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor ) )
769 addRecentColor( clipColor );
777 mCurrentColor = mColor;
781 mPickingColor =
true;
782 setMouseTracking(
true );
787 QColor
c = linkedProjectColor();
795 mAllowOpacity = allow;
800 mColorDialogTitle = title;
805 return mColorDialogTitle;
811 setMenu(
showMenu ? mMenu :
nullptr );
812 setPopupMode(
showMenu ? QToolButton::MenuButtonPopup : QToolButton::DelayedPopup );
825 mDefaultColor =
color;
831 mNullColorString = nullString;
841 return !mColor.isValid();
846 mLinkedColorName = name;