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
515 QRectF textRect = rect;
516 textRect.setLeft( xtrans );
517 textRect.setWidth( textRect.width() - xtrans );
518 textRect.setTop( ytrans );
519 if ( textRect.height() > 300 )
520 textRect.setHeight( 300 );
521 if ( textRect.width() > 2000 )
522 textRect.setWidth( 2000 );
529 p.setBrush( Qt::NoBrush );
530 p.setPen( QColor( 0, 0, 0 ) );
531 p.setFont( *tempFont );
532 QRectF textRect = rect;
533 textRect.setLeft( 2 );
534 p.drawText( textRect, Qt::AlignVCenter, tr(
"Aa" ) );
543void QgsFontButton::prepareMenu()
553 mNullFormatAction =
new QAction( mNullFormatString,
this );
554 mMenu->addAction( mNullFormatAction );
556 if ( !mFormat.isValid() )
558 mNullFormatAction->setCheckable(
true );
559 mNullFormatAction->setChecked(
true );
563 QWidgetAction *sizeAction =
new QWidgetAction( mMenu );
564 QWidget *sizeWidget =
new QWidget();
565 QVBoxLayout *sizeLayout =
new QVBoxLayout();
566 sizeLayout->setContentsMargins( 0, 0, 0, 3 );
567 sizeLayout->setSpacing( 2 );
569 QString fontHeaderLabel;
577 fontHeaderLabel = tr(
"Font size (pt)" );
581 QgsMenuHeader *sizeLabel =
new QgsMenuHeader( fontHeaderLabel );
582 sizeLayout->addWidget( sizeLabel );
584 QgsDoubleSpinBox *sizeSpin =
new QgsDoubleSpinBox(
nullptr );
585 sizeSpin->setDecimals( 4 );
586 sizeSpin->setMaximum( 1e+9 );
588 sizeSpin->setValue( mMode ==
ModeTextRenderer ? mFormat.size() : mFont.pointSizeF() );
589 connect( sizeSpin,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, [
this](
double value ) {
593 if ( mNullFormatAction )
594 mNullFormatAction->setChecked(
false );
595 mFormat.setSize( value );
598 mFont.setPointSizeF( value );
604 QHBoxLayout *spinLayout =
new QHBoxLayout();
605 spinLayout->setContentsMargins( 4, 0, 4, 0 );
606 spinLayout->addWidget( sizeSpin );
607 sizeLayout->addLayout( spinLayout );
608 sizeWidget->setLayout( sizeLayout );
609 sizeAction->setDefaultWidget( sizeWidget );
610 sizeWidget->setFocusProxy( sizeSpin );
611 sizeWidget->setFocusPolicy( Qt::StrongFocus );
612 mMenu->addAction( sizeAction );
614 QMenu *recentFontMenu =
new QMenu( tr(
"Recent Fonts" ), mMenu );
616 for (
const QString &family : recentFontFamilies )
618 QAction *fontAction =
new QAction( family, recentFontMenu );
619 QFont f = fontAction->font();
621 fontAction->setFont( f );
622 fontAction->setToolTip( family );
623 recentFontMenu->addAction( fontAction );
625 || ( mMode ==
ModeQFont && family == mFont.family() ) )
627 fontAction->setCheckable(
true );
628 fontAction->setChecked(
true );
630 auto setFont = [
this, family] {
635 QgsTextFormat newFormat = mFormat;
636 QFont f = newFormat.
font();
653 connect( fontAction, &QAction::triggered,
this, setFont );
655 mMenu->addMenu( recentFontMenu );
657 QAction *configureAction =
new QAction( tr(
"Configure Format…" ),
this );
658 mMenu->addAction( configureAction );
659 connect( configureAction, &QAction::triggered,
this, &QgsFontButton::showSettingsDialog );
661 QAction *copyFormatAction =
new QAction( tr(
"Copy Format" ),
this );
662 mMenu->addAction( copyFormatAction );
664 QAction *pasteFormatAction =
new QAction( tr(
"Paste Format" ),
this );
667 QgsTextFormat tempFormat;
670 if ( mMode ==
ModeTextRenderer && formatFromMimeData( QApplication::clipboard()->mimeData(), tempFormat ) )
674 pasteFormatAction->setIcon( createDragIcon( QSize( iconSize, iconSize ), &tempFormat ) );
676 else if ( mMode ==
ModeQFont && fontFromMimeData( QApplication::clipboard()->mimeData(), tempFont ) )
678 tempFont.setPointSize( 8 );
679 pasteFormatAction->setIcon( createDragIcon( QSize( iconSize, iconSize ),
nullptr, &tempFont ) );
683 pasteFormatAction->setEnabled(
false );
685 mMenu->addAction( pasteFormatAction );
690 mMenu->addSeparator();
692 QgsColorWheel *colorWheel =
new QgsColorWheel( mMenu );
693 colorWheel->
setColor( mFormat.color() );
694 QgsColorWidgetAction *colorAction =
new QgsColorWidgetAction( colorWheel, mMenu, mMenu );
697 mMenu->addAction( colorAction );
700 QColor alphaColor = mFormat.color();
701 alphaColor.setAlphaF( mFormat.opacity() );
703 QgsColorWidgetAction *alphaAction =
new QgsColorWidgetAction( alphaRamp, mMenu, mMenu );
706 const double opacity = color.alphaF();
707 mFormat.setOpacity( opacity );
709 if ( mNullFormatAction )
710 mNullFormatAction->setChecked(
false );
714 mMenu->addAction( alphaAction );
718 QList<QgsColorScheme *>::iterator it = schemeList.begin();
719 for ( ; it != schemeList.end(); ++it )
721 QgsColorSwatchGridAction *colorAction =
new QgsColorSwatchGridAction( *it, mMenu, u
"labeling"_s,
this );
723 mMenu->addAction( colorAction );
728 mMenu->addSeparator();
730 QAction *copyColorAction =
new QAction( tr(
"Copy Color" ),
this );
731 mMenu->addAction( copyColorAction );
734 QAction *pasteColorAction =
new QAction( tr(
"Paste Color" ),
this );
738 bool hasAlpha =
false;
739 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor, hasAlpha ) )
741 pasteColorAction->setIcon( createColorIcon( clipColor ) );
745 pasteColorAction->setEnabled(
false );
747 mMenu->addAction( pasteColorAction );
752void QgsFontButton::addRecentColor(
const QColor &color )
774 mExpressionContextGenerator = generator;
795bool QgsFontButton::formatFromMimeData(
const QMimeData *mimeData,
QgsTextFormat &resultFormat )
const
805bool QgsFontButton::fontFromMimeData(
const QMimeData *mimeData, QFont &resultFont )
const
817 if ( e->type() == QEvent::EnabledChange )
821 QToolButton::changeEvent( e );
827 QToolButton::showEvent( e );
832 QToolButton::resizeEvent(
event );
838void QgsFontButton::updatePreview(
const QColor &color,
QgsTextFormat *format, QFont *font )
840 if ( mShowNoFormat && !mFormat.
isValid() )
842 setIcon( QPixmap() );
846 QgsTextFormat tempFormat;
850 tempFormat = *format;
852 tempFormat = mFormat;
858 if ( color.isValid() )
865 tempFormat.
setSize( QToolButton::font().pointSizeF() - 2 );
868 QSize currentIconSize;
872 if ( !mIconSize.isValid() )
875 QStyleOptionToolButton opt;
876 initStyleOption( &opt );
877 const QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton,
this );
880 mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
881#elif defined( Q_OS_MAC )
882 mIconSize = QSize( buttonSize.width() - 10, height() - 2 );
884 mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
887 currentIconSize = mIconSize;
893 currentIconSize = QSize( width() - 10, height() - 6 );
895 currentIconSize = QSize( width() - 10, height() - 12 );
899 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
905 QPixmap pixmap( currentIconSize * devicePixelRatioF() );
906 pixmap.fill( Qt::transparent );
907 pixmap.setDevicePixelRatio( devicePixelRatioF() );
910 p.setRenderHint( QPainter::Antialiasing );
911 const QRect rect( 0, 0, currentIconSize.width(), currentIconSize.height() );
917 QgsRenderContext context;
918 QgsMapToPixel newCoordXForm;
944 QRectF textRect = rect;
945 textRect.setLeft( xtrans );
946 textRect.setWidth( textRect.width() - xtrans );
947 textRect.setTop( ytrans );
948 if ( textRect.height() > 300 )
949 textRect.setHeight( 300 );
950 if ( textRect.width() > 2000 )
951 textRect.setWidth( 2000 );
958 p.setBrush( Qt::NoBrush );
959 p.setPen( QColor( 0, 0, 0 ) );
960 p.setFont( tempFont );
961 QRectF textRect = rect;
962 textRect.setLeft( 2 );
963 p.drawText( textRect, Qt::AlignVCenter, text() );
968 setIconSize( currentIconSize );
981 bool hasAlpha =
false;
982 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor, hasAlpha ) )
992 mDialogTitle = title;
@ 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.