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;