42#include "moc_qgssymbolbutton.cpp"
45 : QToolButton( parent )
50 setAcceptDrops(
true );
51 connect(
this, &QAbstractButton::clicked,
this, &QgsSymbolButton::showSettingsDialog );
54 mMenu =
new QMenu(
this );
55 connect( mMenu, &QMenu::aboutToShow,
this, &QgsSymbolButton::prepareMenu );
57 setPopupMode( QToolButton::MenuButtonPopup );
62void QgsSymbolButton::updateSizeHint()
65 const QSize size = QToolButton::minimumSizeHint();
70 if ( mFixedSizeConstraints )
74 mSizeHint = QSize( size.width(), std::max( size.height(), fontHeight * 3 ) );
75 setMaximumWidth( mSizeHint.height() * 1.5 );
76 setMinimumWidth( maximumWidth() );
80 mSizeHint = QSize( size.width(), fontHeight );
81 setMaximumWidth( 999999 );
82 mSizeHint.setWidth( QToolButton::sizeHint().width() );
87 setMaximumWidth( 999999 );
88 mSizeHint = QSize( size.width(), std::max( size.height(), fontHeight ) );
95 mSizeHint = QSize( size.width(), std::max( size.height(), fontHeight ) );
99 setMinimumHeight( mSizeHint.height() );
143void QgsSymbolButton::showSettingsDialog()
146 if ( mExpressionContextGenerator )
153 std::unique_ptr<QgsSymbol> newSymbol;
156 newSymbol.reset( mSymbol->clone() );
176 QgsSymbolWidgetContext symbolContext;
193 dialog.setWindowTitle( mDialogTitle );
194 dialog.setContext( symbolContext );
242 mExpressionContextGenerator = generator;
247 mDefaultSymbol.reset(
symbol );
252 return mDefaultSymbol.get();
268 QColor opaque = color;
269 opaque.setAlphaF( 1.0 );
271 if ( opaque == mSymbol->color() )
274 mSymbol->setColor( opaque );
299 bool hasAlpha =
false;
300 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor, hasAlpha ) )
317 if ( e->button() == Qt::RightButton )
319 QToolButton::showMenu();
322 else if ( e->button() == Qt::LeftButton )
324 mDragStartPosition = e->pos();
326 QToolButton::mousePressEvent( e );
340 if ( !( e->buttons() & Qt::LeftButton ) )
343 QToolButton::mouseMoveEvent( e );
347 if ( ( e->pos() - mDragStartPosition ).manhattanLength() < QApplication::startDragDistance() )
350 QToolButton::mouseMoveEvent( e );
355 QDrag *drag =
new QDrag(
this );
358 drag->exec( Qt::CopyAction );
367 stopPicking( e->globalPos() );
372 QToolButton::mouseReleaseEvent( e );
377 if ( !mPickingColor )
380 QToolButton::keyPressEvent( e );
385 stopPicking( QCursor::pos(), e->key() == Qt::Key_Space );
392 bool hasAlpha =
false;
394 if ( colorFromMimeData( e->mimeData(), mimeColor, hasAlpha ) )
399 e->acceptProposedAction();
400 updatePreview( mimeColor );
415 bool hasAlpha =
false;
416 if ( colorFromMimeData( e->mimeData(), mimeColor, hasAlpha ) )
419 e->acceptProposedAction();
420 mimeColor.setAlphaF( 1.0 );
421 mSymbol->setColor( mimeColor );
431 if ( isEnabled() && mSymbol )
433 bool symbolChanged =
false;
434 const double increment = ( (
event->modifiers() & Qt::ControlModifier ) ? 0.1 : 1 ) * (
event->angleDelta().y() > 0 ? 1 : -1 );
435 switch ( mSymbol->type() )
439 QgsMarkerSymbol *marker = qgis::down_cast<QgsMarkerSymbol *>( mSymbol.get() );
442 const double size = std::max( 0.0, marker->
size() + increment );
444 symbolChanged =
true;
451 QgsLineSymbol *line = qgis::down_cast<QgsLineSymbol *>( mSymbol.get() );
454 const double width = std::max( 0.0, line->
width() + increment );
456 symbolChanged =
true;
476 QToolButton::wheelEvent( event );
480void QgsSymbolButton::prepareMenu()
488 QAction *configureAction =
new QAction( tr(
"Configure Symbol…" ),
this );
489 mMenu->addAction( configureAction );
490 connect( configureAction, &QAction::triggered,
this, &QgsSymbolButton::showSettingsDialog );
492 QAction *copySymbolAction =
new QAction( tr(
"Copy Symbol" ),
this );
493 copySymbolAction->setEnabled( !
isNull() );
494 mMenu->addAction( copySymbolAction );
499 QAction *pasteSymbolAction =
new QAction( tr(
"Paste Symbol" ),
this );
503 if ( tempSymbol && tempSymbol->type() == mType )
509 pasteSymbolAction->setEnabled(
false );
511 mMenu->addAction( pasteSymbolAction );
516 QAction *nullAction =
new QAction( tr(
"Clear Current Symbol" ),
this );
517 nullAction->setEnabled( !
isNull() );
518 mMenu->addAction( nullAction );
523 if ( mDefaultSymbol )
525 QAction *defaultSymbolAction =
new QAction( tr(
"Default Symbol" ),
this );
527 mMenu->addAction( defaultSymbolAction );
533 mMenu->addSeparator();
535 QgsColorWheel *colorWheel =
new QgsColorWheel( mMenu );
536 colorWheel->
setColor( mSymbol->color() );
537 QgsColorWidgetAction *colorAction =
new QgsColorWidgetAction( colorWheel, mMenu, mMenu );
540 mMenu->addAction( colorAction );
543 QColor alphaColor = mSymbol->color();
544 alphaColor.setAlphaF( mSymbol->opacity() );
546 QgsColorWidgetAction *alphaAction =
new QgsColorWidgetAction( alphaRamp, mMenu, mMenu );
549 const double opacity = color.alphaF();
550 mSymbol->setOpacity( opacity );
555 mMenu->addAction( alphaAction );
559 QList<QgsColorScheme *>::iterator it = schemeList.begin();
560 for ( ; it != schemeList.end(); ++it )
562 QgsColorSwatchGridAction *colorAction =
new QgsColorSwatchGridAction( *it, mMenu, QStringLiteral(
"symbology" ),
this );
564 mMenu->addAction( colorAction );
569 mMenu->addSeparator();
571 QAction *copyColorAction =
new QAction( tr(
"Copy Color" ),
this );
572 mMenu->addAction( copyColorAction );
575 QAction *pasteColorAction =
new QAction( tr(
"Paste Color" ),
this );
579 bool hasAlpha =
false;
580 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor, hasAlpha ) )
582 pasteColorAction->setIcon( createColorIcon( clipColor ) );
586 pasteColorAction->setEnabled(
false );
588 mMenu->addAction( pasteColorAction );
591 QAction *pickColorAction =
new QAction( tr(
"Pick Color" ),
this );
592 mMenu->addAction( pickColorAction );
593 connect( pickColorAction, &QAction::triggered,
this, &QgsSymbolButton::activatePicker );
595 QAction *chooseColorAction =
new QAction( tr(
"Choose Color…" ),
this );
596 mMenu->addAction( chooseColorAction );
597 connect( chooseColorAction, &QAction::triggered,
this, &QgsSymbolButton::showColorDialog );
601void QgsSymbolButton::addRecentColor(
const QColor &color )
606void QgsSymbolButton::activatePicker()
612 mPickingColor =
true;
613 setMouseTracking(
true );
619 if ( e->type() == QEvent::EnabledChange )
623 QToolButton::changeEvent( e );
629 QToolButton::showEvent( e );
634 QToolButton::resizeEvent( event );
640void QgsSymbolButton::updatePreview(
const QColor &color,
QgsSymbol *tempSymbol )
642 QSize currentIconSize;
646 if ( !mIconSize.isValid() )
649 QStyleOptionToolButton opt;
650 initStyleOption( &opt );
651 const QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton,
this );
654 mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
656 mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
659 currentIconSize = mIconSize;
665 currentIconSize = QSize( width() - 10, height() - 6 );
667 currentIconSize = QSize( width() - 10, height() - 12 );
671 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
676 std::unique_ptr<QgsSymbol> previewSymbol;
680 previewSymbol.reset( tempSymbol->
clone() );
684 previewSymbol.reset( mSymbol->clone() );
688 setIconSize( currentIconSize );
690 setToolTip( QString() );
694 if ( color.isValid() )
695 previewSymbol->setColor( color );
699 setIconSize( currentIconSize );
704 const int width =
static_cast<int>(
Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance(
'X' ) * 23 );
705 const int height =
static_cast<int>( width / 1.61803398875 );
709 QBuffer buffer( &data );
710 pm.save( &buffer,
"PNG", 100 );
711 setToolTip( QStringLiteral(
"<img src='data:image/png;base64, %3' width=\"%4\">" ).arg( QString( data.toBase64() ) ).arg( width ) );
714bool QgsSymbolButton::colorFromMimeData(
const QMimeData *mimeData, QColor &resultColor,
bool &hasAlpha )
719 if ( mimeColor.isValid() )
721 resultColor = mimeColor;
729QPixmap QgsSymbolButton::createColorIcon(
const QColor &color )
const
733 QPixmap pixmap( iconSize, iconSize );
734 pixmap.fill( Qt::transparent );
740 p.setBrush( QBrush( color ) );
743 p.setPen( QColor( 197, 197, 197 ) );
744 p.drawRect( 0, 0, iconSize - 1, iconSize - 1 );
749void QgsSymbolButton::stopPicking( QPoint eventPos,
bool samplingColor )
754 QgsApplication::restoreOverrideCursor();
755 setMouseTracking(
false );
756 mPickingColor =
false;
758 if ( !samplingColor )
767 addRecentColor( newColor );
770void QgsSymbolButton::showColorDialog()
778 const QColor currentColor = mSymbol->color();
783 if ( currentColor.isValid() )
789 if ( newColor.isValid() )
798 QgsColorDialog dialog(
this, Qt::WindowFlags(), mSymbol->color() );
799 dialog.setTitle( tr(
"Symbol Color" ) );
800 dialog.setAllowOpacity(
true );
802 if ( dialog.exec() && dialog.color().isValid() )
813 mDialogTitle = title;
823 return mSymbol.get();
845 return mFixedSizeConstraints;
860 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,...