19#include "moc_qgslayoutlabelwidget.cpp" 
   29#include <QColorDialog> 
   42  connect( mHtmlCheckBox, &QCheckBox::stateChanged, 
this, &QgsLayoutLabelWidget::mHtmlCheckBox_stateChanged );
 
   43  connect( mTextEdit, &QPlainTextEdit::textChanged, 
this, &QgsLayoutLabelWidget::mTextEdit_textChanged );
 
   44  connect( mInsertExpressionButton, &QPushButton::clicked, 
this, &QgsLayoutLabelWidget::mInsertExpressionButton_clicked );
 
   45  connect( mMarginXDoubleSpinBox, 
static_cast<void ( QDoubleSpinBox::* )( 
double )
>( &QDoubleSpinBox::valueChanged ), 
this, &QgsLayoutLabelWidget::mMarginXDoubleSpinBox_valueChanged );
 
   46  connect( mMarginYDoubleSpinBox, 
static_cast<void ( QDoubleSpinBox::* )( 
double )
>( &QDoubleSpinBox::valueChanged ), 
this, &QgsLayoutLabelWidget::mMarginYDoubleSpinBox_valueChanged );
 
   48  mHAlignmentComboBox->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight | Qt::AlignJustify );
 
   49  mVAlignmentComboBox->setAvailableAlignments( Qt::AlignTop | Qt::AlignVCenter | Qt::AlignBottom );
 
   57  mFontButton->setDialogTitle( tr( 
"Label Font" ) );
 
   58  mFontButton->registerExpressionContextGenerator( 
this );
 
   62  mainLayout->addWidget( mItemPropertiesWidget );
 
   64  mMarginXDoubleSpinBox->setClearValue( 0.0 );
 
   65  mMarginYDoubleSpinBox->setClearValue( 0.0 );
 
   67  setGuiElementValues();
 
   72  mDynamicTextMenu = 
new QMenu( 
this );
 
   73  mDynamicTextButton->setMenu( mDynamicTextMenu );
 
   75  connect( mDynamicTextMenu, &QMenu::aboutToShow, 
this, [
this] {
 
   76    mDynamicTextMenu->clear();
 
   77    if ( mLabel->layout() )
 
   80      buildInsertDynamicTextMenu( mLabel->layout(), mDynamicTextMenu, [this]( const QString &expression ) {
 
   81        mLabel->beginCommand( tr( 
"Insert dynamic text" ) );
 
   82        mTextEdit->insertPlainText( 
"[%" + expression.trimmed() + 
"%]" );
 
   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 ) {
 
  116    QAction *action = 
new QAction( name, menu );
 
  117    connect( action, &QAction::triggered, action, [callback, expression] {
 
  118      callback( expression );
 
  120    menu->addAction( action );
 
  123  QMenu *dateMenu = 
new QMenu( tr( 
"Current Date" ), menu );
 
  124  for ( 
const std::pair<QString, QString> &expression :
 
  126          std::make_pair( tr( 
"ISO Format (%1)" ).arg( QDateTime::currentDateTime().toString( QStringLiteral( 
"yyyy-MM-dd" ) ) ), QStringLiteral( 
"format_date(now(), 'yyyy-MM-dd')" ) ),
 
  127          std::make_pair( tr( 
"Day/Month/Year (%1)" ).arg( QDateTime::currentDateTime().toString( QStringLiteral( 
"dd/MM/yyyy" ) ) ), QStringLiteral( 
"format_date(now(), 'dd/MM/yyyy')" ) ),
 
  128          std::make_pair( tr( 
"Month/Day/Year (%1)" ).arg( QDateTime::currentDateTime().toString( QStringLiteral( 
"MM/dd/yyyy" ) ) ), QStringLiteral( 
"format_date(now(), 'MM/dd/yyyy')" ) ),
 
  131    addExpression( dateMenu, expression.first, expression.second );
 
  133  menu->addMenu( dateMenu );
 
  135  QMenu *mapsMenu = 
new QMenu( tr( 
"Map Properties" ), menu );
 
  136  QList<QgsLayoutItemMap *> maps;
 
  141    if ( map->id().isEmpty() )
 
  144    QMenu *mapMenu = 
new QMenu( map->displayName(), mapsMenu );
 
  145    for ( 
const std::pair<QString, QString> &expression :
 
  147            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() ) ),
 
  148            std::make_pair( tr( 
"Rotation (%1)" ).arg( map->rotation() ), QStringLiteral( 
"item_variables('%1')['map_rotation']" ).arg( map->id() ) ),
 
  151      addExpression( mapMenu, expression.first, expression.second );
 
  153    mapMenu->addSeparator();
 
  154    for ( 
const std::pair<QString, QString> &expression :
 
  156            std::make_pair( tr( 
"CRS Identifier (%1)" ).arg( map->crs().authid() ), QStringLiteral( 
"item_variables('%1')['map_crs']" ).arg( map->id() ) ),
 
  157            std::make_pair( tr( 
"CRS Name (%1)" ).arg( map->crs().description() ), QStringLiteral( 
"item_variables('%1')['map_crs_description']" ).arg( map->id() ) ),
 
  158            std::make_pair( tr( 
"Ellipsoid Name (%1)" ).arg( map->crs().ellipsoidAcronym() ), QStringLiteral( 
"item_variables('%1')['map_crs_ellipsoid']" ).arg( map->id() ) ),
 
  159            std::make_pair( tr( 
"Units (%1)" ).arg( 
QgsUnitTypes::toString( map->crs().mapUnits() ) ), QStringLiteral( 
"item_variables('%1')['map_units']" ).arg( map->id() ) ),
 
  160            std::make_pair( tr( 
"Projection (%1)" ).arg( map->crs().operation().description() ), QStringLiteral( 
"item_variables('%1')['map_crs_projection']" ).arg( map->id() ) ),
 
  163      addExpression( mapMenu, expression.first, expression.second );
 
  165    mapMenu->addSeparator();
 
  169    for ( 
const std::pair<QString, QString> &expression :
 
  171            std::make_pair( tr( 
"Center (X) (%1)" ).arg( center.
x() ), QStringLiteral( 
"x(item_variables('%1')['map_extent_center'])" ).arg( map->id() ) ),
 
  172            std::make_pair( tr( 
"Center (Y) (%1)" ).arg( center.
y() ), QStringLiteral( 
"y(item_variables('%1')['map_extent_center'])" ).arg( map->id() ) ),
 
  173            std::make_pair( tr( 
"X Minimum (%1)" ).arg( mapExtent.
xMinimum() ), QStringLiteral( 
"x_min(item_variables('%1')['map_extent'])" ).arg( map->id() ) ),
 
  174            std::make_pair( tr( 
"Y Minimum (%1)" ).arg( mapExtent.
yMinimum() ), QStringLiteral( 
"y_min(item_variables('%1')['map_extent'])" ).arg( map->id() ) ),
 
  175            std::make_pair( tr( 
"X Maximum (%1)" ).arg( mapExtent.
xMaximum() ), QStringLiteral( 
"x_max(item_variables('%1')['map_extent'])" ).arg( map->id() ) ),
 
  176            std::make_pair( tr( 
"Y Maximum (%1)" ).arg( mapExtent.
yMaximum() ), QStringLiteral( 
"y_max(item_variables('%1')['map_extent'])" ).arg( map->id() ) ),
 
  179      addExpression( mapMenu, expression.first, expression.second );
 
  181    mapMenu->addSeparator();
 
  182    for ( 
const std::pair<QString, QString> &expression :
 
  184            std::make_pair( tr( 
"Layer Credits" ), QStringLiteral( 
"array_to_string(map_credits('%1'))" ).arg( map->id() ) ),
 
  187      addExpression( mapMenu, expression.first, expression.second );
 
  189    mapsMenu->addMenu( mapMenu );
 
  191  menu->addMenu( mapsMenu );
 
  192  menu->addSeparator();
 
  198    QMenu *fieldsMenu = 
new QMenu( tr( 
"Field" ), menu );
 
  199    for ( 
const QgsField &field : fields )
 
  201      addExpression( fieldsMenu, field.displayName(), QStringLiteral( 
"\"%1\"" ).arg( field.name() ) );
 
  204    menu->addMenu( fieldsMenu );
 
  205    menu->addSeparator();
 
  208  for ( 
const std::pair<QString, QString> &expression :
 
  210          std::make_pair( tr( 
"Layout Name" ), QStringLiteral( 
"@layout_name" ) ),
 
  211          std::make_pair( tr( 
"Layout Page Number" ), QStringLiteral( 
"@layout_page" ) ),
 
  212          std::make_pair( tr( 
"Layout Page Count" ), QStringLiteral( 
"@layout_numpages" ) ),
 
  213          std::make_pair( tr( 
"Layer Credits" ), QStringLiteral( 
"array_to_string(map_credits())" ) )
 
  216    addExpression( menu, expression.first, expression.second );
 
  218  menu->addSeparator();
 
  219  for ( 
const std::pair<QString, QString> &expression :
 
  221          std::make_pair( tr( 
"Project Author" ), QStringLiteral( 
"@project_author" ) ),
 
  222          std::make_pair( tr( 
"Project Title" ), QStringLiteral( 
"@project_title" ) ),
 
  223          std::make_pair( tr( 
"Project Path" ), QStringLiteral( 
"@project_path" ) )
 
  226    addExpression( menu, expression.first, expression.second );
 
  228  menu->addSeparator();
 
  229  for ( 
const std::pair<QString, QString> &expression :
 
  231          std::make_pair( tr( 
"Current User Name" ), QStringLiteral( 
"@user_full_name" ) ),
 
  232          std::make_pair( tr( 
"Current User Account" ), QStringLiteral( 
"@user_account_name" ) )
 
  235    addExpression( menu, expression.first, expression.second );
 
 
  249  mLabel = qobject_cast<QgsLayoutItemLabel *>( item );
 
  250  mItemPropertiesWidget->
setItem( mLabel );
 
  257  setGuiElementValues();
 
 
  262void QgsLayoutLabelWidget::mHtmlCheckBox_stateChanged( 
int state )
 
  266    mVerticalAlignmentLabel->setDisabled( state );
 
  267    mVAlignmentComboBox->setDisabled( state );
 
  269    mLabel->beginCommand( tr( 
"Change Label Mode" ) );
 
  270    mLabel->blockSignals( 
true );
 
  272    mLabel->setText( mTextEdit->toPlainText() );
 
  274    mLabel->blockSignals( 
false );
 
  275    mLabel->endCommand();
 
  279void QgsLayoutLabelWidget::mTextEdit_textChanged()
 
  284    mLabel->blockSignals( 
true );
 
  285    mLabel->setText( mTextEdit->toPlainText() );
 
  287    mLabel->blockSignals( 
false );
 
  288    mLabel->endCommand();
 
  292void QgsLayoutLabelWidget::fontChanged()
 
  297    mLabel->setTextFormat( mFontButton->textFormat() );
 
  299    mLabel->endCommand();
 
  303void QgsLayoutLabelWidget::mMarginXDoubleSpinBox_valueChanged( 
double d )
 
  308    mLabel->setMarginX( d );
 
  310    mLabel->endCommand();
 
  314void QgsLayoutLabelWidget::mMarginYDoubleSpinBox_valueChanged( 
double d )
 
  319    mLabel->setMarginY( d );
 
  321    mLabel->endCommand();
 
  325void QgsLayoutLabelWidget::mInsertExpressionButton_clicked()
 
  340  exprDlg.setWindowTitle( tr( 
"Insert Expression" ) );
 
  341  if ( exprDlg.exec() == QDialog::Accepted )
 
  343    expression = exprDlg.expressionText();
 
  344    if ( !expression.isEmpty() )
 
  346      mLabel->beginCommand( tr( 
"Insert expression" ) );
 
  347      mTextEdit->insertPlainText( 
"[%" + expression.trimmed() + 
"%]" );
 
  348      mLabel->endCommand();
 
  353void QgsLayoutLabelWidget::horizontalAlignmentChanged()
 
  357    mLabel->beginCommand( tr( 
"Change Label Alignment" ) );
 
  358    mLabel->setHAlign( 
static_cast<Qt::AlignmentFlag
>( 
static_cast<int>( mHAlignmentComboBox->currentAlignment() ) ) );
 
  360    mLabel->endCommand();
 
  364void QgsLayoutLabelWidget::verticalAlignmentChanged()
 
  368    mLabel->beginCommand( tr( 
"Change Label Alignment" ) );
 
  369    mLabel->setVAlign( 
static_cast<Qt::AlignmentFlag
>( 
static_cast<int>( mVAlignmentComboBox->currentAlignment() ) ) );
 
  371    mLabel->endCommand();
 
  375void QgsLayoutLabelWidget::setGuiElementValues()
 
  377  blockAllSignals( 
true );
 
  378  mTextEdit->setPlainText( mLabel->text() );
 
  379  mTextEdit->moveCursor( QTextCursor::End, QTextCursor::MoveAnchor );
 
  380  mMarginXDoubleSpinBox->setValue( mLabel->marginX() );
 
  381  mMarginYDoubleSpinBox->setValue( mLabel->marginY() );
 
  384  mHAlignmentComboBox->setCurrentAlignment( mLabel->hAlign() );
 
  385  mVAlignmentComboBox->setCurrentAlignment( mLabel->vAlign() );
 
  387  mFontButton->setTextFormat( mLabel->textFormat() );
 
  391  blockAllSignals( 
false );
 
  394void QgsLayoutLabelWidget::blockAllSignals( 
bool block )
 
  396  mTextEdit->blockSignals( block );
 
  397  mHtmlCheckBox->blockSignals( block );
 
  398  mMarginXDoubleSpinBox->blockSignals( block );
 
  399  mMarginYDoubleSpinBox->blockSignals( block );
 
  400  mHAlignmentComboBox->blockSignals( block );
 
  401  mVAlignmentComboBox->blockSignals( block );
 
  402  mFontButton->blockSignals( block );
 
void changed()
Emitted when the alignment is changed.
 
A generic dialog for building expression strings.
 
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
 
static QString findAndSelectActiveExpression(QgsCodeEditor *editor, const QString &pattern=QString())
Find the expression under the cursor in the given editor and select it.
 
Encapsulate a field in an attribute table or data source.
 
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.
 
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 rectangle specified with double values.
 
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.