27#include <QColorDialog> 
   40  connect( mHtmlCheckBox, &QCheckBox::stateChanged, 
this, &QgsLayoutLabelWidget::mHtmlCheckBox_stateChanged );
 
   41  connect( mTextEdit, &QPlainTextEdit::textChanged, 
this, &QgsLayoutLabelWidget::mTextEdit_textChanged );
 
   42  connect( mInsertExpressionButton, &QPushButton::clicked, 
this, &QgsLayoutLabelWidget::mInsertExpressionButton_clicked );
 
   43  connect( mMarginXDoubleSpinBox, 
static_cast < void ( QDoubleSpinBox::* )( 
double ) 
> ( &QDoubleSpinBox::valueChanged ), 
this, &QgsLayoutLabelWidget::mMarginXDoubleSpinBox_valueChanged );
 
   44  connect( mMarginYDoubleSpinBox, 
static_cast < void ( QDoubleSpinBox::* )( 
double ) 
> ( &QDoubleSpinBox::valueChanged ), 
this, &QgsLayoutLabelWidget::mMarginYDoubleSpinBox_valueChanged );
 
   45  connect( mCenterRadioButton, &QRadioButton::clicked, 
this, &QgsLayoutLabelWidget::mCenterRadioButton_clicked );
 
   46  connect( mLeftRadioButton, &QRadioButton::clicked, 
this, &QgsLayoutLabelWidget::mLeftRadioButton_clicked );
 
   47  connect( mRightRadioButton, &QRadioButton::clicked, 
this, &QgsLayoutLabelWidget::mRightRadioButton_clicked );
 
   48  connect( mTopRadioButton, &QRadioButton::clicked, 
this, &QgsLayoutLabelWidget::mTopRadioButton_clicked );
 
   49  connect( mBottomRadioButton, &QRadioButton::clicked, 
this, &QgsLayoutLabelWidget::mBottomRadioButton_clicked );
 
   50  connect( mMiddleRadioButton, &QRadioButton::clicked, 
this, &QgsLayoutLabelWidget::mMiddleRadioButton_clicked );
 
   54  mFontButton->setDialogTitle( tr( 
"Label Font" ) );
 
   55  mFontButton->registerExpressionContextGenerator( 
this );
 
   59  mainLayout->addWidget( mItemPropertiesWidget );
 
   61  mMarginXDoubleSpinBox->setClearValue( 0.0 );
 
   62  mMarginYDoubleSpinBox->setClearValue( 0.0 );
 
   64  setGuiElementValues();
 
   68  connect( mJustifyRadioButton, &QRadioButton::clicked, 
this, &QgsLayoutLabelWidget::justifyClicked );
 
   70  mDynamicTextMenu = 
new QMenu( 
this );
 
   71  mDynamicTextButton->setMenu( mDynamicTextMenu );
 
   73  connect( mDynamicTextMenu, &QMenu::aboutToShow, 
this, [ = ]
 
   75    mDynamicTextMenu->clear();
 
   76    if ( mLabel->layout() )
 
   79      buildInsertDynamicTextMenu( mLabel->layout(), mDynamicTextMenu, [ = ]( const QString & expression )
 
   81        mLabel->beginCommand( tr( 
"Insert dynamic text" ) );
 
   82        mTextEdit->insertPlainText( 
"[%" + expression + 
"%]" );
 
   88  QMenu *expressionMenu = 
new QMenu( 
this );
 
   89  QAction *convertToStaticAction = 
new QAction( tr( 
"Convert to Static Text" ), 
this );
 
   90  expressionMenu->addAction( convertToStaticAction );
 
   92  mInsertExpressionButton->setMenu( expressionMenu );
 
   94  mFontButton->setLayer( coverageLayer() );
 
   95  if ( mLabel->layout() )
 
  103  if ( mItemPropertiesWidget )
 
  109  return mLabel->createExpressionContext();
 
  115  auto addExpression = [&callback]( QMenu * menu, 
const QString & name, 
const QString & expression )
 
  117    QAction *action = 
new QAction( name, menu );
 
  118    connect( action, &QAction::triggered, action, [callback, expression]
 
  120      callback( expression );
 
  122    menu->addAction( action );
 
  125  QMenu *dateMenu = 
new QMenu( tr( 
"Current Date" ), menu );
 
  126  for ( 
const std::pair< QString, QString > &expression :
 
  128          std::make_pair( tr( 
"ISO Format (%1)" ).arg( QDateTime::currentDateTime().toString( QStringLiteral( 
"yyyy-MM-dd" ) ) ), QStringLiteral( 
"format_date(now(), 'yyyy-MM-dd')" ) ),
 
  129          std::make_pair( tr( 
"Day/Month/Year (%1)" ).arg( QDateTime::currentDateTime().toString( QStringLiteral( 
"dd/MM/yyyy" ) ) ), QStringLiteral( 
"format_date(now(), 'dd/MM/yyyy')" ) ),
 
  130          std::make_pair( tr( 
"Month/Day/Year (%1)" ).arg( QDateTime::currentDateTime().toString( QStringLiteral( 
"MM/dd/yyyy" ) ) ), QStringLiteral( 
"format_date(now(), 'MM/dd/yyyy')" ) ),
 
  133    addExpression( dateMenu, expression.first, expression.second );
 
  135  menu->addMenu( dateMenu );
 
  137  QMenu *mapsMenu = 
new QMenu( tr( 
"Map Properties" ), menu );
 
  138  QList< QgsLayoutItemMap * > maps;
 
  143    if ( map->id().isEmpty() )
 
  146    QMenu *mapMenu = 
new QMenu( map->displayName(), mapsMenu );
 
  147    for ( 
const std::pair< QString, QString > &expression :
 
  149            std::make_pair( tr( 
"Scale (%1)" ).arg( map->scale() ), QStringLiteral( 
"format_number(item_variables('%1')['map_scale'], places:=6, omit_group_separators:=true, trim_trailing_zeroes:=true)" ).arg( map->id() ) ),
 
  150            std::make_pair( tr( 
"Rotation (%1)" ).arg( map->rotation() ), QStringLiteral( 
"item_variables('%1')['map_rotation']" ).arg( map->id() ) ),
 
  153      addExpression( mapMenu, expression.first, expression.second );
 
  155    mapMenu->addSeparator();
 
  156    for ( 
const std::pair< QString, QString > &expression :
 
  158            std::make_pair( tr( 
"CRS Identifier (%1)" ).arg( map->crs().authid() ),  QStringLiteral( 
"item_variables('%1')['map_crs']" ).arg( map->id() ) ),
 
  159            std::make_pair( tr( 
"CRS Name (%1)" ).arg( map->crs().description() ),  QStringLiteral( 
"item_variables('%1')['map_crs_description']" ).arg( map->id() ) ),
 
  160            std::make_pair( tr( 
"Ellipsoid Name (%1)" ).arg( map->crs().ellipsoidAcronym() ),  QStringLiteral( 
"item_variables('%1')['map_crs_ellipsoid']" ).arg( map->id() ) ),
 
  161            std::make_pair( tr( 
"Units (%1)" ).arg( 
QgsUnitTypes::toString( map->crs().mapUnits() ) ),  QStringLiteral( 
"item_variables('%1')['map_units']" ).arg( map->id() ) ),
 
  162            std::make_pair( tr( 
"Projection (%1)" ).arg( map->crs().operation().description() ),  QStringLiteral( 
"item_variables('%1')['map_crs_projection']" ).arg( map->id() ) ),
 
  165      addExpression( mapMenu, expression.first, expression.second );
 
  167    mapMenu->addSeparator();
 
  171    for ( 
const std::pair< QString, QString > &expression :
 
  173            std::make_pair( tr( 
"Center (X) (%1)" ).arg( center.
x() ),  QStringLiteral( 
"x(item_variables('%1')['map_extent_center'])" ).arg( map->id() ) ),
 
  174            std::make_pair( tr( 
"Center (Y) (%1)" ).arg( center.
y() ),  QStringLiteral( 
"y(item_variables('%1')['map_extent_center'])" ).arg( map->id() ) ),
 
  175            std::make_pair( tr( 
"X Minimum (%1)" ).arg( mapExtent.
xMinimum() ),  QStringLiteral( 
"x_min(item_variables('%1')['map_extent'])" ).arg( map->id() ) ),
 
  176            std::make_pair( tr( 
"Y Minimum (%1)" ).arg( mapExtent.
yMinimum() ),  QStringLiteral( 
"y_min(item_variables('%1')['map_extent'])" ).arg( map->id() ) ),
 
  177            std::make_pair( tr( 
"X Maximum (%1)" ).arg( mapExtent.
xMaximum() ),  QStringLiteral( 
"x_max(item_variables('%1')['map_extent'])" ).arg( map->id() ) ),
 
  178            std::make_pair( tr( 
"Y Maximum (%1)" ).arg( mapExtent.
yMaximum() ),  QStringLiteral( 
"y_max(item_variables('%1')['map_extent'])" ).arg( map->id() ) ),
 
  181      addExpression( mapMenu, expression.first, expression.second );
 
  183    mapMenu->addSeparator();
 
  184    for ( 
const std::pair< QString, QString > &expression :
 
  186            std::make_pair( tr( 
"Layer Credits" ),  QStringLiteral( 
"array_to_string(map_credits('%1'))" ).arg( map->id() ) ),
 
  189      addExpression( mapMenu, expression.first, expression.second );
 
  191    mapsMenu->addMenu( mapMenu );
 
  193  menu->addMenu( mapsMenu );
 
  194  menu->addSeparator();
 
  200    QMenu *fieldsMenu = 
new QMenu( tr( 
"Field" ), menu );
 
  206    menu->addMenu( fieldsMenu );
 
  207    menu->addSeparator();
 
  210  for ( 
const std::pair< QString, QString > &expression :
 
  212          std::make_pair( tr( 
"Layout Name" ), QStringLiteral( 
"@layout_name" ) ),
 
  213          std::make_pair( tr( 
"Layout Page Number" ), QStringLiteral( 
"@layout_page" ) ),
 
  214          std::make_pair( tr( 
"Layout Page Count" ), QStringLiteral( 
"@layout_numpages" ) ),
 
  215          std::make_pair( tr( 
"Layer Credits" ), QStringLiteral( 
"array_to_string(map_credits())" ) )
 
  218    addExpression( menu, expression.first, expression.second );
 
  220  menu->addSeparator();
 
  221  for ( 
const std::pair< QString, QString > &expression :
 
  223          std::make_pair( tr( 
"Project Author" ), QStringLiteral( 
"@project_author" ) ),
 
  224          std::make_pair( tr( 
"Project Title" ), QStringLiteral( 
"@project_title" ) ),
 
  225          std::make_pair( tr( 
"Project Path" ), QStringLiteral( 
"@project_path" ) )
 
  228    addExpression( menu, expression.first, expression.second );
 
  230  menu->addSeparator();
 
  231  for ( 
const std::pair< QString, QString > &expression :
 
  233          std::make_pair( tr( 
"Current User Name" ), QStringLiteral( 
"@user_full_name" ) ),
 
  234          std::make_pair( tr( 
"Current User Account" ), QStringLiteral( 
"@user_account_name" ) )
 
  237    addExpression( menu, expression.first, expression.second );
 
  251  mLabel = qobject_cast< QgsLayoutItemLabel * >( item );
 
  252  mItemPropertiesWidget->
setItem( mLabel );
 
  259  setGuiElementValues();
 
  264void QgsLayoutLabelWidget::mHtmlCheckBox_stateChanged( 
int state )
 
  268    mVerticalAlignementLabel->setDisabled( state );
 
  269    mTopRadioButton->setDisabled( state );
 
  270    mMiddleRadioButton->setDisabled( state );
 
  271    mBottomRadioButton->setDisabled( state );
 
  273    mLabel->beginCommand( tr( 
"Change Label Mode" ) );
 
  274    mLabel->blockSignals( 
true );
 
  276    mLabel->setText( mTextEdit->toPlainText() );
 
  278    mLabel->blockSignals( 
false );
 
  279    mLabel->endCommand();
 
  283void QgsLayoutLabelWidget::mTextEdit_textChanged()
 
  288    mLabel->blockSignals( 
true );
 
  289    mLabel->setText( mTextEdit->toPlainText() );
 
  291    mLabel->blockSignals( 
false );
 
  292    mLabel->endCommand();
 
  296void QgsLayoutLabelWidget::fontChanged()
 
  301    mLabel->setTextFormat( mFontButton->textFormat() );
 
  303    mLabel->endCommand();
 
  307void QgsLayoutLabelWidget::justifyClicked()
 
  311    mLabel->beginCommand( tr( 
"Change Label Alignment" ) );
 
  312    mLabel->setHAlign( Qt::AlignJustify );
 
  314    mLabel->endCommand();
 
  318void QgsLayoutLabelWidget::mMarginXDoubleSpinBox_valueChanged( 
double d )
 
  323    mLabel->setMarginX( d );
 
  325    mLabel->endCommand();
 
  329void QgsLayoutLabelWidget::mMarginYDoubleSpinBox_valueChanged( 
double d )
 
  334    mLabel->setMarginY( d );
 
  336    mLabel->endCommand();
 
  340void QgsLayoutLabelWidget::mInsertExpressionButton_clicked()
 
  347  QString selText = mTextEdit->textCursor().selectedText();
 
  350  selText = selText.replace( QChar( 0x2029 ), QChar( 
'\n' ) );
 
  353  if ( selText.startsWith( QLatin1String( 
"[%" ) ) && selText.endsWith( QLatin1String( 
"%]" ) ) )
 
  354    selText = selText.mid( 2, selText.size() - 4 );
 
  362  exprDlg.setWindowTitle( tr( 
"Insert Expression" ) );
 
  363  if ( exprDlg.exec() == QDialog::Accepted )
 
  365    QString expression = exprDlg.expressionText();
 
  366    if ( !expression.isEmpty() )
 
  368      mLabel->beginCommand( tr( 
"Insert expression" ) );
 
  369      mTextEdit->insertPlainText( 
"[%" + expression + 
"%]" );
 
  370      mLabel->endCommand();
 
  375void QgsLayoutLabelWidget::mCenterRadioButton_clicked()
 
  379    mLabel->beginCommand( tr( 
"Change Label Alignment" ) );
 
  380    mLabel->setHAlign( Qt::AlignHCenter );
 
  382    mLabel->endCommand();
 
  386void QgsLayoutLabelWidget::mRightRadioButton_clicked()
 
  390    mLabel->beginCommand( tr( 
"Change Label Alignment" ) );
 
  391    mLabel->setHAlign( Qt::AlignRight );
 
  393    mLabel->endCommand();
 
  397void QgsLayoutLabelWidget::mLeftRadioButton_clicked()
 
  401    mLabel->beginCommand( tr( 
"Change Label Alignment" ) );
 
  402    mLabel->setHAlign( Qt::AlignLeft );
 
  404    mLabel->endCommand();
 
  408void QgsLayoutLabelWidget::mTopRadioButton_clicked()
 
  412    mLabel->beginCommand( tr( 
"Change Label Alignment" ) );
 
  413    mLabel->setVAlign( Qt::AlignTop );
 
  415    mLabel->endCommand();
 
  419void QgsLayoutLabelWidget::mBottomRadioButton_clicked()
 
  423    mLabel->beginCommand( tr( 
"Change Label Alignment" ) );
 
  424    mLabel->setVAlign( Qt::AlignBottom );
 
  426    mLabel->endCommand();
 
  430void QgsLayoutLabelWidget::mMiddleRadioButton_clicked()
 
  434    mLabel->beginCommand( tr( 
"Change Label Alignment" ) );
 
  435    mLabel->setVAlign( Qt::AlignVCenter );
 
  437    mLabel->endCommand();
 
  441void QgsLayoutLabelWidget::setGuiElementValues()
 
  443  blockAllSignals( 
true );
 
  444  mTextEdit->setPlainText( mLabel->text() );
 
  445  mTextEdit->moveCursor( QTextCursor::End, QTextCursor::MoveAnchor );
 
  446  mMarginXDoubleSpinBox->setValue( mLabel->marginX() );
 
  447  mMarginYDoubleSpinBox->setValue( mLabel->marginY() );
 
  449  mTopRadioButton->setChecked( mLabel->vAlign() == Qt::AlignTop );
 
  450  mMiddleRadioButton->setChecked( mLabel->vAlign() == Qt::AlignVCenter );
 
  451  mBottomRadioButton->setChecked( mLabel->vAlign() == Qt::AlignBottom );
 
  452  mLeftRadioButton->setChecked( mLabel->hAlign() == Qt::AlignLeft );
 
  453  mJustifyRadioButton->setChecked( mLabel->hAlign() == Qt::AlignJustify );
 
  454  mCenterRadioButton->setChecked( mLabel->hAlign() == Qt::AlignHCenter );
 
  455  mRightRadioButton->setChecked( mLabel->hAlign() == Qt::AlignRight );
 
  456  mFontButton->setTextFormat( mLabel->textFormat() );
 
  462  blockAllSignals( 
false );
 
  465void QgsLayoutLabelWidget::blockAllSignals( 
bool block )
 
  467  mTextEdit->blockSignals( block );
 
  468  mHtmlCheckBox->blockSignals( block );
 
  469  mMarginXDoubleSpinBox->blockSignals( block );
 
  470  mMarginYDoubleSpinBox->blockSignals( block );
 
  471  mTopRadioButton->blockSignals( block );
 
  472  mMiddleRadioButton->blockSignals( block );
 
  473  mBottomRadioButton->blockSignals( block );
 
  474  mLeftRadioButton->blockSignals( block );
 
  475  mCenterRadioButton->blockSignals( block );
 
  476  mRightRadioButton->blockSignals( block );
 
  477  mJustifyRadioButton->blockSignals( block );
 
  478  mFontButton->blockSignals( block );
 
A generic dialog for building expression strings.
 
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
 
Encapsulate a field in an attribute table or data source.
 
QString displayName() const
Returns the name to use when displaying this field.
 
Container of fields for a vector layer.
 
A layout item subclass for text labels.
 
void convertToStaticText()
Converts the label's text() to a static string, by evaluating any expressions included in the text an...
 
@ ModeHtml
Label displays rendered HTML content.
 
@ ModeFont
Label displays text rendered using a single font.
 
Layout graphical items for displaying a map.
 
Base class for graphical items within a QgsLayout.
 
@ UndoLabelMargin
Label margin.
 
@ UndoLabelFont
Label font.
 
@ UndoLabelText
Label text.
 
int type() const override
Returns a unique graphics item type identifier.
 
void changed()
Emitted when the object's properties change.
 
void layerChanged(QgsVectorLayer *layer)
Emitted when the context's layer is changed.
 
QgsVectorLayer * layer() const
Returns the vector layer associated with the layout's context.
 
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
 
void layoutItems(QList< T * > &itemList) const
Returns a list of layout items of a specific type.
 
QgsLayoutReportContext & reportContext()
Returns a reference to the layout's report context, which stores information relating to the current ...
 
Interface for master layout type objects, such as print layouts and reports.
 
A class to represent a 2D point.
 
A rectangle specified with double values.
 
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
 
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
 
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
 
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
 
QgsPointXY center() const SIP_HOLDGIL
Returns the center point of the rectangle.
 
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 data sets.
 
QgsFields fields() const FINAL
Returns the list of fields of this layer.