35 #include <QDesktopWidget>
39 : QToolButton( parent )
40 , mDialogTitle( dialogTitle.isEmpty() ? tr(
"Text Format" ) : dialogTitle )
41 , mNullFormatString( tr(
"No Format" ) )
43 setText( tr(
"Font" ) );
45 setAcceptDrops(
true );
46 connect(
this, &QAbstractButton::clicked,
this, &QgsFontButton::showSettingsDialog );
49 mMenu =
new QMenu(
this );
50 connect( mMenu, &QMenu::aboutToShow,
this, &QgsFontButton::prepareMenu );
52 setPopupMode( QToolButton::MenuButtonPopup );
55 const QSize size = QToolButton::minimumSizeHint();
58 mSizeHint = QSize( std::max( minWidth, size.width() ), std::max( size.height(), fontHeight ) );
71 void QgsFontButton::showSettingsDialog()
78 if ( mExpressionContextGenerator )
94 mActivePanel->setPanelTitle( mDialogTitle );
95 mActivePanel->setContext( symbolContext );
102 QgsTextFormatDialog dialog( mFormat, mMapCanvas,
this, QgsGuiUtils::ModalDialogFlags, mLayer.data() );
103 dialog.setWindowTitle( mDialogTitle );
104 dialog.setContext( symbolContext );
153 if ( mActivePanel && !format.
isValid() )
154 mActivePanel->acceptPanel();
159 if ( mActivePanel && format.
isValid() )
160 mActivePanel->setFormat( format );
173 QColor opaque = color;
174 opaque.setAlphaF( 1.0 );
176 if ( mNullFormatAction )
177 mNullFormatAction->setChecked(
false );
179 if ( mFormat.
color() != opaque )
192 QApplication::clipboard()->setMimeData( mFormat.
toMimeData() );
205 if ( mMode ==
ModeTextRenderer && formatFromMimeData( QApplication::clipboard()->mimeData(), tempFormat ) )
210 else if ( mMode ==
ModeQFont && fontFromMimeData( QApplication::clipboard()->mimeData(), font ) )
219 if ( e->type() == QEvent::ToolTip )
221 QHelpEvent *helpEvent =
static_cast< QHelpEvent *
>( e );
223 double fontSize = 0.0;
227 fontSize = mFormat.
size();
231 fontSize = mFont.pointSizeF();
234 toolTip = QStringLiteral(
"<b>%1</b><br>%2<br>Size: %3" ).arg( text(), mMode ==
ModeTextRenderer ? mFormat.
font().family() : mFont.family() ).arg( fontSize );
235 QToolTip::showText( helpEvent->globalPos(), toolTip );
237 return QToolButton::event( e );
242 if ( e->button() == Qt::RightButton )
244 QToolButton::showMenu();
247 else if ( e->button() == Qt::LeftButton )
249 mDragStartPosition = e->pos();
251 QToolButton::mousePressEvent( e );
258 if ( !( e->buttons() & Qt::LeftButton ) )
261 QToolButton::mouseMoveEvent( e );
265 if ( ( e->pos() - mDragStartPosition ).manhattanLength() < QApplication::startDragDistance() )
268 QToolButton::mouseMoveEvent( e );
273 QDrag *drag =
new QDrag(
this );
286 drag->exec( Qt::CopyAction );
290 bool QgsFontButton::colorFromMimeData(
const QMimeData *mimeData, QColor &resultColor,
bool &hasAlpha )
295 if ( mimeColor.isValid() )
297 resultColor = mimeColor;
311 bool hasAlpha =
false;
313 if ( mMode ==
ModeTextRenderer && formatFromMimeData( e->mimeData(), format ) )
315 e->acceptProposedAction();
316 updatePreview( QColor(), &format );
318 else if ( mMode ==
ModeQFont && fontFromMimeData( e->mimeData(), font ) )
320 e->acceptProposedAction();
321 updatePreview( QColor(),
nullptr, &font );
323 else if ( mMode ==
ModeTextRenderer && colorFromMimeData( e->mimeData(), mimeColor, hasAlpha ) )
328 e->acceptProposedAction();
329 updatePreview( mimeColor );
346 bool hasAlpha =
false;
347 if ( mMode ==
ModeTextRenderer && formatFromMimeData( e->mimeData(), format ) )
353 else if ( mMode ==
ModeQFont && fontFromMimeData( e->mimeData(), font ) )
359 else if ( mMode ==
ModeTextRenderer && colorFromMimeData( e->mimeData(), mimeColor, hasAlpha ) )
362 e->acceptProposedAction();
368 mimeColor.setAlphaF( 1.0 );
383 size = mFormat.
size();
387 size = mFont.pointSizeF();
391 const double increment = (
event->modifiers() & Qt::ControlModifier ) ? 0.1 : 1;
392 if (
event->angleDelta().y() > 0 )
400 size = std::max( size, 1.0 );
414 QFont newFont = mFont;
415 newFont.setPointSizeF( size );
424 QPixmap QgsFontButton::createColorIcon(
const QColor &color )
const
429 pixmap.fill( Qt::transparent );
435 p.setBrush( QBrush( color ) );
438 p.setPen( QColor( 197, 197, 197 ) );
444 QPixmap QgsFontButton::createDragIcon( QSize size,
const QgsTextFormat *tempFormat,
const QFont *tempFont )
const
447 tempFormat = &mFormat;
452 QPixmap pixmap( size.width(), size.height() );
453 pixmap.fill( Qt::transparent );
456 p.setRenderHint( QPainter::Antialiasing );
457 const QRect rect( 0, 0, size.width(), size.height() );
459 if ( mMode ==
ModeQFont || tempFormat->
color().lightnessF() < 0.7 )
461 p.setBrush( QBrush( QColor( 255, 255, 255 ) ) );
462 p.setPen( QPen( QColor( 150, 150, 150 ), 0 ) );
466 p.setBrush( QBrush( QColor( 0, 0, 0 ) ) );
467 p.setPen( QPen( QColor( 100, 100, 100 ), 0 ) );
470 p.setBrush( Qt::NoBrush );
471 p.setPen( Qt::NoPen );
482 context.
setScaleFactor( QgsApplication::desktop()->logicalDpiX() / 25.4 );
491 ? fontSize * tempFormat->
buffer().
size() / 100
499 ? fontSize * tempFormat->
buffer().
size() / 100
504 QRectF textRect = rect;
505 textRect.setLeft( xtrans );
506 textRect.setWidth( textRect.width() - xtrans );
507 textRect.setTop( ytrans );
508 if ( textRect.height() > 300 )
509 textRect.setHeight( 300 );
510 if ( textRect.width() > 2000 )
511 textRect.setWidth( 2000 );
514 context, *tempFormat );
519 p.setBrush( Qt::NoBrush );
520 p.setPen( QColor( 0, 0, 0 ) );
521 p.setFont( *tempFont );
522 QRectF textRect = rect;
523 textRect.setLeft( 2 );
524 p.drawText( textRect, Qt::AlignVCenter, tr(
"Aa" ) );
533 void QgsFontButton::prepareMenu()
543 mNullFormatAction =
new QAction( mNullFormatString,
this );
544 mMenu->addAction( mNullFormatAction );
548 mNullFormatAction->setCheckable(
true );
549 mNullFormatAction->setChecked(
true );
553 QWidgetAction *sizeAction =
new QWidgetAction( mMenu );
554 QWidget *sizeWidget =
new QWidget();
555 QVBoxLayout *sizeLayout =
new QVBoxLayout();
556 sizeLayout->setContentsMargins( 0, 0, 0, 3 );
557 sizeLayout->setSpacing( 2 );
559 QString fontHeaderLabel;
567 fontHeaderLabel = tr(
"Font size (pt)" );
572 sizeLayout->addWidget( sizeLabel );
575 sizeSpin->setDecimals( 4 );
576 sizeSpin->setMaximum( 1e+9 );
579 connect( sizeSpin,
static_cast < void (
QgsDoubleSpinBox::* )(
double )
> ( &QgsDoubleSpinBox::valueChanged ),
580 this, [ = ](
double value )
585 if ( mNullFormatAction )
586 mNullFormatAction->setChecked(
false );
590 mFont.setPointSizeF( value );
596 QHBoxLayout *spinLayout =
new QHBoxLayout();
597 spinLayout->setContentsMargins( 4, 0, 4, 0 );
598 spinLayout->addWidget( sizeSpin );
599 sizeLayout->addLayout( spinLayout );
600 sizeWidget->setLayout( sizeLayout );
601 sizeAction->setDefaultWidget( sizeWidget );
602 sizeWidget->setFocusProxy( sizeSpin );
603 sizeWidget->setFocusPolicy( Qt::StrongFocus );
604 mMenu->addAction( sizeAction );
606 QMenu *recentFontMenu =
new QMenu( tr(
"Recent Fonts" ), mMenu );
608 for (
const QString &family : recentFontFamilies )
610 QAction *fontAction =
new QAction( family, recentFontMenu );
611 QFont f = fontAction->font();
612 f.setFamily( family );
613 fontAction->setFont( f );
614 fontAction->setToolTip( family );
615 recentFontMenu->addAction( fontAction );
617 || ( mMode ==
ModeQFont && family == mFont.family() ) )
619 fontAction->setCheckable(
true );
620 fontAction->setChecked(
true );
622 auto setFont = [
this, family]
629 QFont f = newFormat.
font();
630 f.setFamily( family );
639 font.setFamily( family );
646 connect( fontAction, &QAction::triggered,
this, setFont );
648 mMenu->addMenu( recentFontMenu );
650 QAction *configureAction =
new QAction( tr(
"Configure Format…" ),
this );
651 mMenu->addAction( configureAction );
652 connect( configureAction, &QAction::triggered,
this, &QgsFontButton::showSettingsDialog );
654 QAction *copyFormatAction =
new QAction( tr(
"Copy Format" ),
this );
655 mMenu->addAction( copyFormatAction );
657 QAction *pasteFormatAction =
new QAction( tr(
"Paste Format" ),
this );
663 if ( mMode ==
ModeTextRenderer && formatFromMimeData( QApplication::clipboard()->mimeData(), tempFormat ) )
667 pasteFormatAction->setIcon( createDragIcon( QSize(
iconSize,
iconSize ), &tempFormat ) );
669 else if ( mMode ==
ModeQFont && fontFromMimeData( QApplication::clipboard()->mimeData(), tempFont ) )
671 tempFont.setPointSize( 8 );
672 pasteFormatAction->setIcon( createDragIcon( QSize(
iconSize,
iconSize ),
nullptr, &tempFont ) );
676 pasteFormatAction->setEnabled(
false );
678 mMenu->addAction( pasteFormatAction );
683 mMenu->addSeparator();
690 mMenu->addAction( colorAction );
693 QColor alphaColor = mFormat.
color();
694 alphaColor.setAlphaF( mFormat.
opacity() );
700 const double opacity = color.alphaF();
703 if ( mNullFormatAction )
704 mNullFormatAction->setChecked(
false );
709 mMenu->addAction( alphaAction );
713 QList< QgsColorScheme * >::iterator it = schemeList.begin();
714 for ( ; it != schemeList.end(); ++it )
718 mMenu->addAction( colorAction );
723 mMenu->addSeparator();
725 QAction *copyColorAction =
new QAction( tr(
"Copy Color" ),
this );
726 mMenu->addAction( copyColorAction );
729 QAction *pasteColorAction =
new QAction( tr(
"Paste Color" ),
this );
733 bool hasAlpha =
false;
734 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor, hasAlpha ) )
736 pasteColorAction->setIcon( createColorIcon( clipColor ) );
740 pasteColorAction->setEnabled(
false );
742 mMenu->addAction( pasteColorAction );
747 void QgsFontButton::addRecentColor(
const QColor &color )
769 mExpressionContextGenerator = generator;
790 bool QgsFontButton::formatFromMimeData(
const QMimeData *mimeData,
QgsTextFormat &resultFormat )
const
797 bool QgsFontButton::fontFromMimeData(
const QMimeData *mimeData, QFont &resultFont )
const
806 if ( e->type() == QEvent::EnabledChange )
810 QToolButton::changeEvent( e );
816 QToolButton::showEvent( e );
821 QToolButton::resizeEvent(
event );
827 void QgsFontButton::updatePreview(
const QColor &color,
QgsTextFormat *format, QFont *font )
829 if ( mShowNoFormat && !mFormat.
isValid() )
831 setIcon( QPixmap() );
839 tempFormat = *format;
841 tempFormat = mFormat;
847 if ( color.isValid() )
850 QSize currentIconSize;
854 if ( !mIconSize.isValid() )
857 QStyleOptionToolButton opt;
858 initStyleOption( &opt );
859 const QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton,
863 mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
864 #elif defined(Q_OS_MAC)
865 mIconSize = QSize( buttonSize.width() - 10, height() - 2 );
867 mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
870 currentIconSize = mIconSize;
876 currentIconSize = QSize( width() - 10, height() - 6 );
878 currentIconSize = QSize( width() - 10, height() - 12 );
882 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
888 QPixmap pixmap( currentIconSize );
889 pixmap.fill( Qt::transparent );
892 p.setRenderHint( QPainter::Antialiasing );
893 const QRect rect( 0, 0, currentIconSize.width(), currentIconSize.height() );
904 context.
setScaleFactor( QgsApplication::desktop()->logicalDpiX() / 25.4 );
927 QRectF textRect = rect;
928 textRect.setLeft( xtrans );
929 textRect.setWidth( textRect.width() - xtrans );
930 textRect.setTop( ytrans );
931 if ( textRect.height() > 300 )
932 textRect.setHeight( 300 );
933 if ( textRect.width() > 2000 )
934 textRect.setWidth( 2000 );
937 context, tempFormat );
942 p.setBrush( Qt::NoBrush );
943 p.setPen( QColor( 0, 0, 0 ) );
944 p.setFont( tempFont );
945 QRectF textRect = rect;
946 textRect.setLeft( 2 );
947 p.drawText( textRect, Qt::AlignVCenter, text() );
953 setIconSize( currentIconSize );
966 bool hasAlpha =
false;
967 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor, hasAlpha ) )
977 mDialogTitle = title;