43#include "moc_qgssymbolbutton.cpp"
45using namespace Qt::StringLiterals;
48 : QToolButton( parent )
53 setAcceptDrops(
true );
54 connect(
this, &QAbstractButton::clicked,
this, &QgsSymbolButton::showSettingsDialog );
57 mMenu =
new QMenu(
this );
58 connect( mMenu, &QMenu::aboutToShow,
this, &QgsSymbolButton::prepareMenu );
60 setPopupMode( QToolButton::MenuButtonPopup );
65void QgsSymbolButton::updateSizeHint()
68 const QSize size = QToolButton::minimumSizeHint();
73 if ( mFixedSizeConstraints )
77 mSizeHint = QSize( size.width(), std::max( size.height(), fontHeight * 3 ) );
78 setMaximumWidth( mSizeHint.height() * 1.5 );
79 setMinimumWidth( maximumWidth() );
83 mSizeHint = QSize( size.width(), fontHeight );
84 setMaximumWidth( 999999 );
85 mSizeHint.setWidth( QToolButton::sizeHint().width() );
90 setMaximumWidth( 999999 );
91 mSizeHint = QSize( size.width(), std::max( size.height(), fontHeight ) );
98 mSizeHint = QSize( size.width(), std::max( size.height(), fontHeight ) );
102 setMinimumHeight( mSizeHint.height() );
146void QgsSymbolButton::showSettingsDialog()
149 if ( mExpressionContextGenerator )
156 std::unique_ptr<QgsSymbol> newSymbol;
159 newSymbol.reset( mSymbol->clone() );
179 QgsSymbolWidgetContext symbolContext;
196 dialog.setWindowTitle( mDialogTitle );
197 dialog.setContext( symbolContext );
245 mExpressionContextGenerator = generator;
250 mDefaultSymbol.reset(
symbol );
255 return mDefaultSymbol.get();
271 QColor opaque = color;
272 opaque.setAlphaF( 1.0 );
274 if ( opaque == mSymbol->color() )
277 mSymbol->setColor( opaque );
302 bool hasAlpha =
false;
303 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor, hasAlpha ) )
320 if ( e->button() == Qt::RightButton )
322 QToolButton::showMenu();
325 else if ( e->button() == Qt::LeftButton )
327 mDragStartPosition = e->pos();
329 QToolButton::mousePressEvent( e );
343 if ( !( e->buttons() & Qt::LeftButton ) )
346 QToolButton::mouseMoveEvent( e );
350 if ( ( e->pos() - mDragStartPosition ).manhattanLength() < QApplication::startDragDistance() )
353 QToolButton::mouseMoveEvent( e );
358 QDrag *drag =
new QDrag(
this );
361 drag->exec( Qt::CopyAction );
370 stopPicking( e->globalPos() );
375 QToolButton::mouseReleaseEvent( e );
380 if ( !mPickingColor )
383 QToolButton::keyPressEvent( e );
388 stopPicking( QCursor::pos(), e->key() == Qt::Key_Space );
395 bool hasAlpha =
false;
397 if ( colorFromMimeData( e->mimeData(), mimeColor, hasAlpha ) )
402 e->acceptProposedAction();
403 updatePreview( mimeColor );
418 bool hasAlpha =
false;
419 if ( colorFromMimeData( e->mimeData(), mimeColor, hasAlpha ) )
422 e->acceptProposedAction();
423 mimeColor.setAlphaF( 1.0 );
424 mSymbol->setColor( mimeColor );
434 if ( isEnabled() && mSymbol )
436 bool symbolChanged =
false;
437 const double increment = ( (
event->modifiers() & Qt::ControlModifier ) ? 0.1 : 1 ) * (
event->angleDelta().y() > 0 ? 1 : -1 );
438 switch ( mSymbol->type() )
442 QgsMarkerSymbol *marker = qgis::down_cast<QgsMarkerSymbol *>( mSymbol.get() );
445 const double size = std::max( 0.0, marker->
size() + increment );
447 symbolChanged =
true;
454 QgsLineSymbol *line = qgis::down_cast<QgsLineSymbol *>( mSymbol.get() );
457 const double width = std::max( 0.0, line->
width() + increment );
459 symbolChanged =
true;
479 QToolButton::wheelEvent( event );
483void QgsSymbolButton::prepareMenu()
491 QAction *configureAction =
new QAction( tr(
"Configure Symbol…" ),
this );
492 mMenu->addAction( configureAction );
493 connect( configureAction, &QAction::triggered,
this, &QgsSymbolButton::showSettingsDialog );
495 QAction *copySymbolAction =
new QAction( tr(
"Copy Symbol" ),
this );
496 copySymbolAction->setEnabled( !
isNull() );
497 mMenu->addAction( copySymbolAction );
502 QAction *pasteSymbolAction =
new QAction( tr(
"Paste Symbol" ),
this );
506 if ( tempSymbol && tempSymbol->type() == mType )
512 pasteSymbolAction->setEnabled(
false );
514 mMenu->addAction( pasteSymbolAction );
519 QAction *nullAction =
new QAction( tr(
"Clear Current Symbol" ),
this );
520 nullAction->setEnabled( !
isNull() );
521 mMenu->addAction( nullAction );
526 if ( mDefaultSymbol )
528 QAction *defaultSymbolAction =
new QAction( tr(
"Default Symbol" ),
this );
530 mMenu->addAction( defaultSymbolAction );
536 mMenu->addSeparator();
538 QgsColorWheel *colorWheel =
new QgsColorWheel( mMenu );
539 colorWheel->
setColor( mSymbol->color() );
540 QgsColorWidgetAction *colorAction =
new QgsColorWidgetAction( colorWheel, mMenu, mMenu );
543 mMenu->addAction( colorAction );
546 QColor alphaColor = mSymbol->color();
547 alphaColor.setAlphaF( mSymbol->opacity() );
549 QgsColorWidgetAction *alphaAction =
new QgsColorWidgetAction( alphaRamp, mMenu, mMenu );
552 const double opacity = color.alphaF();
553 mSymbol->setOpacity( opacity );
558 mMenu->addAction( alphaAction );
562 QList<QgsColorScheme *>::iterator it = schemeList.begin();
563 for ( ; it != schemeList.end(); ++it )
565 QgsColorSwatchGridAction *colorAction =
new QgsColorSwatchGridAction( *it, mMenu, u
"symbology"_s,
this );
567 mMenu->addAction( colorAction );
572 mMenu->addSeparator();
574 QAction *copyColorAction =
new QAction( tr(
"Copy Color" ),
this );
575 mMenu->addAction( copyColorAction );
578 QAction *pasteColorAction =
new QAction( tr(
"Paste Color" ),
this );
582 bool hasAlpha =
false;
583 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor, hasAlpha ) )
585 pasteColorAction->setIcon( createColorIcon( clipColor ) );
589 pasteColorAction->setEnabled(
false );
591 mMenu->addAction( pasteColorAction );
594 QAction *pickColorAction =
new QAction( tr(
"Pick Color" ),
this );
595 mMenu->addAction( pickColorAction );
596 connect( pickColorAction, &QAction::triggered,
this, &QgsSymbolButton::activatePicker );
598 QAction *chooseColorAction =
new QAction( tr(
"Choose Color…" ),
this );
599 mMenu->addAction( chooseColorAction );
600 connect( chooseColorAction, &QAction::triggered,
this, &QgsSymbolButton::showColorDialog );
604void QgsSymbolButton::addRecentColor(
const QColor &color )
609void QgsSymbolButton::activatePicker()
615 mPickingColor =
true;
616 setMouseTracking(
true );
622 if ( e->type() == QEvent::EnabledChange )
626 QToolButton::changeEvent( e );
632 QToolButton::showEvent( e );
637 QToolButton::resizeEvent( event );
643void QgsSymbolButton::updatePreview(
const QColor &color,
QgsSymbol *tempSymbol )
645 QSize currentIconSize;
649 if ( !mIconSize.isValid() )
652 QStyleOptionToolButton opt;
653 initStyleOption( &opt );
654 const QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton,
this );
657 mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
659 mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
662 currentIconSize = mIconSize;
668 currentIconSize = QSize( width() - 10, height() - 6 );
670 currentIconSize = QSize( width() - 10, height() - 12 );
674 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
679 std::unique_ptr<QgsSymbol> previewSymbol;
683 previewSymbol.reset( tempSymbol->
clone() );
687 previewSymbol.reset( mSymbol->clone() );
691 setIconSize( currentIconSize );
693 setToolTip( QString() );
697 if ( color.isValid() )
698 previewSymbol->setColor( color );
702 setIconSize( currentIconSize );
707 const int width =
static_cast<int>(
Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance(
'X' ) * 23 );
708 const int height =
static_cast<int>( width / 1.61803398875 );
712 QBuffer buffer( &data );
713 pm.save( &buffer,
"PNG", 100 );
714 setToolTip( u
"<img src='data:image/png;base64, %3' width=\"%4\">"_s.arg( QString( data.toBase64() ) ).arg( width ) );
717bool QgsSymbolButton::colorFromMimeData(
const QMimeData *mimeData, QColor &resultColor,
bool &hasAlpha )
722 if ( mimeColor.isValid() )
724 resultColor = mimeColor;
732QPixmap QgsSymbolButton::createColorIcon(
const QColor &color )
const
736 QPixmap pixmap( iconSize, iconSize );
737 pixmap.fill( Qt::transparent );
743 p.setBrush( QBrush( color ) );
746 p.setPen( QColor( 197, 197, 197 ) );
747 p.drawRect( 0, 0, iconSize - 1, iconSize - 1 );
752void QgsSymbolButton::stopPicking( QPoint eventPos,
bool samplingColor )
757 QgsApplication::restoreOverrideCursor();
758 setMouseTracking(
false );
759 mPickingColor =
false;
761 if ( !samplingColor )
770 addRecentColor( newColor );
773void QgsSymbolButton::showColorDialog()
781 const QColor currentColor = mSymbol->color();
786 if ( currentColor.isValid() )
792 if ( newColor.isValid() )
801 QgsColorDialog dialog(
this, Qt::WindowFlags(), mSymbol->color() );
802 dialog.setTitle( tr(
"Symbol Color" ) );
803 dialog.setAllowOpacity(
true );
805 if ( dialog.exec() && dialog.color().isValid() )
816 mDialogTitle = title;
826 return mSymbol.get();
848 return mFixedSizeConstraints;
863 if ( !mDefaultSymbol )
static const double UI_SCALE_FACTOR
UI scaling factor.
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.
@ Sampler
Color/Value picker.
QList< QgsColorScheme * > schemes() const
Returns all color schemes in the registry.
@ ShowInColorButtonMenu
Show scheme in color button drop-down 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
Abstract interface for generating an expression context.
virtual QgsExpressionContext createExpressionContext() const =0
This method needs to be reimplemented in all classes which implement this interface and return an exp...
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
static std::unique_ptr< QgsFillSymbol > createSimple(const QVariantMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
static QColor sampleColor(QPoint point)
Samples the color on screen at the specified global point (pixel).
A line symbol type, for rendering LineString and MultiLineString geometries.
void setWidth(double width) const
Sets the width for the whole line symbol.
static std::unique_ptr< QgsLineSymbol > createSimple(const QVariantMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties.
double width() const
Returns the estimated width for the whole symbol, which is the maximum width of all marker symbol lay...
Map canvas is a class for displaying all GIS data types on a canvas.
A marker symbol type, for rendering Point and MultiPoint geometries.
void setSize(double size) const
Sets the size for the whole symbol.
static std::unique_ptr< QgsMarkerSymbol > createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
double size() const
Returns the estimated size for the whole symbol, which is the maximum size of all marker symbol layer...
A bar for displaying non-blocking messages to the user.
static void addRecentColor(const QColor &color)
Adds a color to the list of recent colors.
Stores properties relating to a screen.
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
static std::unique_ptr< QgsSymbol > symbolFromMimeData(const QMimeData *data)
Attempts to parse mime data as a symbol.
static QPixmap symbolPreviewPixmap(const QgsSymbol *symbol, QSize size, int padding=0, QgsRenderContext *customContext=nullptr, bool selected=false, const QgsExpressionContext *expressionContext=nullptr, const QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns a pixmap preview for a color ramp.
static QMimeData * symbolToMimeData(const QgsSymbol *symbol)
Creates new mime data from a symbol.
static QColor colorFromMimeData(const QMimeData *data, bool &hasAlpha)
Attempts to parse mime data as a color.
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns an icon preview for a color ramp.
static QMimeData * colorToMimeData(const QColor &color)
Creates mime data from a color.
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
void setMessageBar(QgsMessageBar *bar)
Sets the message bar associated with the widget.
void setExpressionContext(QgsExpressionContext *context)
Sets the optional expression context used for the widget.
Abstract base class for all rendered symbols.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
static QgsSymbol * defaultSymbol(Qgis::GeometryType geomType)
Returns a new default symbol for the specified geometry type.
Represents a vector layer which manages a vector based dataset.
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,...