41#include "moc_qgsfontbutton.cpp"
43using namespace Qt::StringLiterals;
46 : QToolButton( parent )
48 , mNullFormatString( tr(
"No Format" ) )
50 setText( tr(
"Font" ) );
52 setAcceptDrops(
true );
53 connect(
this, &QAbstractButton::clicked,
this, &QgsFontButton::showSettingsDialog );
56 mMenu =
new QMenu(
this );
57 connect( mMenu, &QMenu::aboutToShow,
this, &QgsFontButton::prepareMenu );
59 setPopupMode( QToolButton::MenuButtonPopup );
62 const QSize size = QToolButton::minimumSizeHint();
65 mSizeHint = QSize( std::max( minWidth, size.width() ), std::max( size.height(), fontHeight ) );
81void QgsFontButton::showSettingsDialog()
88 if ( mExpressionContextGenerator )
95 QgsSymbolWidgetContext symbolContext;
103 mActivePanel =
new QgsTextFormatPanelWidget( mFormat, mMapCanvas,
this, mLayer.data() );
104 mActivePanel->setPanelTitle( mDialogTitle );
105 mActivePanel->setContext( symbolContext );
115 QgsTextFormatDialog dialog( mFormat, mMapCanvas,
this, QgsGuiUtils::ModalDialogFlags, mLayer.data() );
116 dialog.setWindowTitle( mDialogTitle );
117 dialog.setContext( symbolContext );
166 if ( mActivePanel && !format.
isValid() )
167 mActivePanel->acceptPanel();
172 if ( mActivePanel && format.
isValid() )
173 mActivePanel->setFormat( format );
186 QColor opaque = color;
187 opaque.setAlphaF( 1.0 );
189 if ( mNullFormatAction )
190 mNullFormatAction->setChecked(
false );
192 if ( mFormat.color() != opaque )
194 mFormat.setColor( opaque );
205 QApplication::clipboard()->setMimeData( mFormat.toMimeData() );
218 if ( mMode ==
ModeTextRenderer && formatFromMimeData( QApplication::clipboard()->mimeData(), tempFormat ) )
223 else if ( mMode ==
ModeQFont && fontFromMimeData( QApplication::clipboard()->mimeData(), font ) )
232 if ( e->type() == QEvent::ToolTip )
234 QHelpEvent *helpEvent =
static_cast<QHelpEvent *
>( e );
236 double fontSize = 0.0;
240 fontSize = mFormat.size();
244 fontSize = mFont.pointSizeF();
247 toolTip = u
"<b>%1</b><br>%2<br>Size: %3"_s.arg( text(), mMode ==
ModeTextRenderer ? mFormat.font().family() : mFont.family() ).arg( fontSize );
248 QToolTip::showText( helpEvent->globalPos(), toolTip );
250 return QToolButton::event( e );
255 if ( e->button() == Qt::RightButton )
257 QToolButton::showMenu();
260 else if ( e->button() == Qt::LeftButton )
262 mDragStartPosition = e->pos();
264 QToolButton::mousePressEvent( e );
271 if ( !( e->buttons() & Qt::LeftButton ) )
274 QToolButton::mouseMoveEvent( e );
278 if ( ( e->pos() - mDragStartPosition ).manhattanLength() < QApplication::startDragDistance() )
281 QToolButton::mouseMoveEvent( e );
286 QDrag *drag =
new QDrag(
this );
290 drag->setMimeData( mFormat.toMimeData() );
298 drag->setPixmap( createDragIcon( QSize( iconSize, iconSize ) ) );
299 drag->exec( Qt::CopyAction );
303bool QgsFontButton::colorFromMimeData(
const QMimeData *mimeData, QColor &resultColor,
bool &hasAlpha )
308 if ( mimeColor.isValid() )
310 resultColor = mimeColor;
324 bool hasAlpha =
false;
326 if ( mMode ==
ModeTextRenderer && formatFromMimeData( e->mimeData(), format ) )
328 e->acceptProposedAction();
329 updatePreview( QColor(), &format );
331 else if ( mMode ==
ModeQFont && fontFromMimeData( e->mimeData(), font ) )
333 e->acceptProposedAction();
334 updatePreview( QColor(),
nullptr, &font );
336 else if ( mMode ==
ModeTextRenderer && colorFromMimeData( e->mimeData(), mimeColor, hasAlpha ) )
341 e->acceptProposedAction();
342 updatePreview( mimeColor );
359 bool hasAlpha =
false;
360 if ( mMode ==
ModeTextRenderer && formatFromMimeData( e->mimeData(), format ) )
366 else if ( mMode ==
ModeQFont && fontFromMimeData( e->mimeData(), font ) )
372 else if ( mMode ==
ModeTextRenderer && colorFromMimeData( e->mimeData(), mimeColor, hasAlpha ) )
375 e->acceptProposedAction();
379 mFormat.setOpacity( mimeColor.alphaF() );
381 mimeColor.setAlphaF( 1.0 );
382 mFormat.setColor( mimeColor );
396 size = mFormat.size();
400 size = mFont.pointSizeF();
404 const double increment = (
event->modifiers() & Qt::ControlModifier ) ? 0.1 : 1;
405 if (
event->angleDelta().y() > 0 )
413 size = std::max( size, 1.0 );
427 QFont newFont = mFont;
428 newFont.setPointSizeF( size );
437QPixmap QgsFontButton::createColorIcon(
const QColor &color )
const
441 QPixmap pixmap( iconSize, iconSize );
442 pixmap.fill( Qt::transparent );
448 p.setBrush( QBrush( color ) );
451 p.setPen( QColor( 197, 197, 197 ) );
452 p.drawRect( 0, 0, iconSize - 1, iconSize - 1 );
457QPixmap QgsFontButton::createDragIcon( QSize size,
const QgsTextFormat *tempFormat,
const QFont *tempFont )
const
460 tempFormat = &mFormat;
465 QPixmap pixmap( size.width(), size.height() );
466 pixmap.fill( Qt::transparent );
469 p.setRenderHint( QPainter::Antialiasing );
470 const QRect rect( 0, 0, size.width(), size.height() );
472 if ( mMode ==
ModeQFont || tempFormat->
color().lightnessF() < 0.7 )
474 p.setBrush( QBrush( QColor( 255, 255, 255 ) ) );
475 p.setPen( QPen( QColor( 150, 150, 150 ), 0 ) );
479 p.setBrush( QBrush( QColor( 0, 0, 0 ) ) );
480 p.setPen( QPen( QColor( 100, 100, 100 ), 0 ) );
483 p.setBrush( Qt::NoBrush );
484 p.setPen( Qt::NoPen );
490 QgsRenderContext context;
491 QgsMapToPixel newCoordXForm;
504 ? fontSize * tempFormat->
buffer().
size() / 100
514 ? fontSize * tempFormat->
buffer().
size() / 100
520 QRectF textRect = rect;
521 textRect.setLeft( xtrans );
522 textRect.setWidth( textRect.width() - xtrans );
523 textRect.setTop( ytrans );
524 if ( textRect.height() > 300 )
525 textRect.setHeight( 300 );
526 if ( textRect.width() > 2000 )
527 textRect.setWidth( 2000 );
534 p.setBrush( Qt::NoBrush );
535 p.setPen( QColor( 0, 0, 0 ) );
536 p.setFont( *tempFont );
537 QRectF textRect = rect;
538 textRect.setLeft( 2 );
539 p.drawText( textRect, Qt::AlignVCenter, tr(
"Aa" ) );
548void QgsFontButton::prepareMenu()
558 mNullFormatAction =
new QAction( mNullFormatString,
this );
559 mMenu->addAction( mNullFormatAction );
561 if ( !mFormat.isValid() )
563 mNullFormatAction->setCheckable(
true );
564 mNullFormatAction->setChecked(
true );
568 QWidgetAction *sizeAction =
new QWidgetAction( mMenu );
569 QWidget *sizeWidget =
new QWidget();
570 QVBoxLayout *sizeLayout =
new QVBoxLayout();
571 sizeLayout->setContentsMargins( 0, 0, 0, 3 );
572 sizeLayout->setSpacing( 2 );
574 QString fontHeaderLabel;
582 fontHeaderLabel = tr(
"Font size (pt)" );
586 QgsMenuHeader *sizeLabel =
new QgsMenuHeader( fontHeaderLabel );
587 sizeLayout->addWidget( sizeLabel );
589 QgsDoubleSpinBox *sizeSpin =
new QgsDoubleSpinBox(
nullptr );
590 sizeSpin->setDecimals( 4 );
591 sizeSpin->setMaximum( 1e+9 );
593 sizeSpin->setValue( mMode ==
ModeTextRenderer ? mFormat.size() : mFont.pointSizeF() );
594 connect( sizeSpin,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, [
this](
double value ) {
598 if ( mNullFormatAction )
599 mNullFormatAction->setChecked(
false );
600 mFormat.setSize( value );
603 mFont.setPointSizeF( value );
609 QHBoxLayout *spinLayout =
new QHBoxLayout();
610 spinLayout->setContentsMargins( 4, 0, 4, 0 );
611 spinLayout->addWidget( sizeSpin );
612 sizeLayout->addLayout( spinLayout );
613 sizeWidget->setLayout( sizeLayout );
614 sizeAction->setDefaultWidget( sizeWidget );
615 sizeWidget->setFocusProxy( sizeSpin );
616 sizeWidget->setFocusPolicy( Qt::StrongFocus );
617 mMenu->addAction( sizeAction );
619 QMenu *recentFontMenu =
new QMenu( tr(
"Recent Fonts" ), mMenu );
621 for (
const QString &family : recentFontFamilies )
623 QAction *fontAction =
new QAction( family, recentFontMenu );
624 QFont f = fontAction->font();
626 fontAction->setFont( f );
627 fontAction->setToolTip( family );
628 recentFontMenu->addAction( fontAction );
629 if ( ( mMode ==
ModeTextRenderer && family == mFormat.font().family() ) || ( mMode ==
ModeQFont && family == mFont.family() ) )
631 fontAction->setCheckable(
true );
632 fontAction->setChecked(
true );
634 auto setFont = [
this, family] {
639 QgsTextFormat newFormat = mFormat;
640 QFont f = newFormat.
font();
657 connect( fontAction, &QAction::triggered,
this, setFont );
659 mMenu->addMenu( recentFontMenu );
661 QAction *configureAction =
new QAction( tr(
"Configure Format…" ),
this );
662 mMenu->addAction( configureAction );
663 connect( configureAction, &QAction::triggered,
this, &QgsFontButton::showSettingsDialog );
665 QAction *copyFormatAction =
new QAction( tr(
"Copy Format" ),
this );
666 mMenu->addAction( copyFormatAction );
668 QAction *pasteFormatAction =
new QAction( tr(
"Paste Format" ),
this );
671 QgsTextFormat tempFormat;
674 if ( mMode ==
ModeTextRenderer && formatFromMimeData( QApplication::clipboard()->mimeData(), tempFormat ) )
678 pasteFormatAction->setIcon( createDragIcon( QSize( iconSize, iconSize ), &tempFormat ) );
680 else if ( mMode ==
ModeQFont && fontFromMimeData( QApplication::clipboard()->mimeData(), tempFont ) )
682 tempFont.setPointSize( 8 );
683 pasteFormatAction->setIcon( createDragIcon( QSize( iconSize, iconSize ),
nullptr, &tempFont ) );
687 pasteFormatAction->setEnabled(
false );
689 mMenu->addAction( pasteFormatAction );
694 mMenu->addSeparator();
696 QgsColorWheel *colorWheel =
new QgsColorWheel( mMenu );
697 colorWheel->
setColor( mFormat.color() );
698 QgsColorWidgetAction *colorAction =
new QgsColorWidgetAction( colorWheel, mMenu, mMenu );
701 mMenu->addAction( colorAction );
704 QColor alphaColor = mFormat.color();
705 alphaColor.setAlphaF( mFormat.opacity() );
707 QgsColorWidgetAction *alphaAction =
new QgsColorWidgetAction( alphaRamp, mMenu, mMenu );
710 const double opacity = color.alphaF();
711 mFormat.setOpacity( opacity );
713 if ( mNullFormatAction )
714 mNullFormatAction->setChecked(
false );
718 mMenu->addAction( alphaAction );
722 QList<QgsColorScheme *>::iterator it = schemeList.begin();
723 for ( ; it != schemeList.end(); ++it )
725 QgsColorSwatchGridAction *colorAction =
new QgsColorSwatchGridAction( *it, mMenu, u
"labeling"_s,
this );
727 mMenu->addAction( colorAction );
732 mMenu->addSeparator();
734 QAction *copyColorAction =
new QAction( tr(
"Copy Color" ),
this );
735 mMenu->addAction( copyColorAction );
738 QAction *pasteColorAction =
new QAction( tr(
"Paste Color" ),
this );
742 bool hasAlpha =
false;
743 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor, hasAlpha ) )
745 pasteColorAction->setIcon( createColorIcon( clipColor ) );
749 pasteColorAction->setEnabled(
false );
751 mMenu->addAction( pasteColorAction );
756void QgsFontButton::addRecentColor(
const QColor &color )
778 mExpressionContextGenerator = generator;
799bool QgsFontButton::formatFromMimeData(
const QMimeData *mimeData,
QgsTextFormat &resultFormat )
const
809bool QgsFontButton::fontFromMimeData(
const QMimeData *mimeData, QFont &resultFont )
const
821 if ( e->type() == QEvent::EnabledChange )
825 QToolButton::changeEvent( e );
831 QToolButton::showEvent( e );
836 QToolButton::resizeEvent(
event );
842void QgsFontButton::updatePreview(
const QColor &color,
QgsTextFormat *format, QFont *font )
844 if ( mShowNoFormat && !mFormat.
isValid() )
846 setIcon( QPixmap() );
850 QgsTextFormat tempFormat;
854 tempFormat = *format;
856 tempFormat = mFormat;
862 if ( color.isValid() )
869 tempFormat.
setSize( QToolButton::font().pointSizeF() - 2 );
872 QSize currentIconSize;
876 if ( !mIconSize.isValid() )
879 QStyleOptionToolButton opt;
880 initStyleOption( &opt );
881 const QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton,
this );
884 mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
885#elif defined( Q_OS_MAC )
886 mIconSize = QSize( buttonSize.width() - 10, height() - 2 );
888 mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
891 currentIconSize = mIconSize;
897 currentIconSize = QSize( width() - 10, height() - 6 );
899 currentIconSize = QSize( width() - 10, height() - 12 );
903 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
909 QPixmap pixmap( currentIconSize * devicePixelRatioF() );
910 pixmap.fill( Qt::transparent );
911 pixmap.setDevicePixelRatio( devicePixelRatioF() );
914 p.setRenderHint( QPainter::Antialiasing );
915 const QRect rect( 0, 0, currentIconSize.width(), currentIconSize.height() );
921 QgsRenderContext context;
922 QgsMapToPixel newCoordXForm;
953 QRectF textRect = rect;
954 textRect.setLeft( xtrans );
955 textRect.setWidth( textRect.width() - xtrans );
956 textRect.setTop( ytrans );
957 if ( textRect.height() > 300 )
958 textRect.setHeight( 300 );
959 if ( textRect.width() > 2000 )
960 textRect.setWidth( 2000 );
967 p.setBrush( Qt::NoBrush );
968 p.setPen( QColor( 0, 0, 0 ) );
969 p.setFont( tempFont );
970 QRectF textRect = rect;
971 textRect.setLeft( 2 );
972 p.drawText( textRect, Qt::AlignVCenter, text() );
977 setIconSize( currentIconSize );
990 bool hasAlpha =
false;
991 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor, hasAlpha ) )
1001 mDialogTitle = title;
1006 return mDialogTitle;
@ PreferVector
Prefer vector-based rendering, when the result will still be visually near-identical to a raster-base...
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size).
@ Points
Points (e.g., for font sizes).
@ Antialiasing
Use antialiasing while drawing.
static const double UI_SCALE_FACTOR
UI scaling factor.
static QgsColorSchemeRegistry * colorSchemeRegistry()
Returns the application's color scheme registry, used for managing color schemes.
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
void setShowClearButton(bool showClearButton)
Sets whether the widget will show a clear button.
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 QMimeData * toMimeData(const QFont &font)
Returns new mime data representing the specified font settings.
static void setFontFamily(QFont &font, const QString &family)
Sets the family for a font object.
static void addRecentFontFamily(const QString &family)
Adds a font family to the list of recently used font families.
static QFont fromMimeData(const QMimeData *data, bool *ok=nullptr)
Attempts to parse the provided mime data as a QFont.
static QStringList recentFontFamilies()
Returns a list of recently used font families.
Map canvas is a class for displaying all GIS data types on a canvas.
void setParameters(double mapUnitsPerPixel, double centerX, double centerY, int widthPixels, int heightPixels, double rotation)
Sets parameters for use in transforming coordinates.
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.
void setScaleFactor(double factor)
Sets the scaling factor for the render to convert painter units to physical sizes.
void setDevicePixelRatio(float ratio)
Sets the device pixel ratio.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
void setRasterizedRenderingPolicy(Qgis::RasterizedRenderingPolicy policy)
Sets the policy controlling when rasterisation of content during renders is permitted.
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected).
void setMapToPixel(const QgsMapToPixel &mtp)
Sets the context's map to pixel transform, which transforms between map coordinates and device coordi...
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
A utility class for dynamic handling of changes to screen properties.
void screenDpiChanged(double dpi)
Emitted whenever the screen dpi associated with the widget is changed.
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.
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.
QSizeF size() const
Returns the size of the background shape.
bool enabled() const
Returns whether the background is enabled.
SizeType sizeType() const
Returns the method used to determine the size of the background shape (e.g., fixed size or buffer aro...
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the shape size.
Qgis::RenderUnit sizeUnit() const
Returns the units used for the shape's size.
Qgis::RenderUnit sizeUnit() const
Returns the units for the buffer size.
double size() const
Returns the size of the buffer.
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the buffer size.
bool enabled() const
Returns whether the buffer is enabled.
Container for all settings relating to text rendering.
void setColor(const QColor &color)
Sets the color that text will be rendered in.
void setSize(double size)
Sets the size for rendered text.
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the size.
void setFont(const QFont &font)
Sets the font used for rendering text.
static QgsTextFormat fromMimeData(const QMimeData *data, bool *ok=nullptr)
Attempts to parse the provided mime data as a QgsTextFormat.
void setSizeUnit(Qgis::RenderUnit unit)
Sets the units for the size of rendered text.
bool isValid() const
Returns true if the format is valid.
QgsTextBackgroundSettings & background()
Returns a reference to the text background settings.
Qgis::RenderUnit sizeUnit() const
Returns the units for the size of rendered text.
double size() const
Returns the size for rendered text.
QColor color() const
Returns the color that text will be rendered in.
QFont font() const
Returns the font used for rendering text.
QgsTextBufferSettings & buffer()
Returns a reference to the text buffer settings.
static void drawText(const QRectF &rect, double rotation, Qgis::TextHorizontalAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, bool drawAsOutlines=true, Qgis::TextVerticalAlignment vAlignment=Qgis::TextVerticalAlignment::Top, Qgis::TextRendererFlags flags=Qgis::TextRendererFlags(), Qgis::TextLayoutMode mode=Qgis::TextLayoutMode::Rectangle)
Draws text within a rectangle using the specified settings.
static Q_INVOKABLE QString toString(Qgis::DistanceUnit unit)
Returns a translated string representing a distance unit.
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,...
QFont getFont(bool &ok, const QFont &initial, const QString &title)
Show font selection dialog.