30#include <QColorDialog>
36#include "moc_qgslayoutlabelwidget.cpp"
38using namespace Qt::StringLiterals;
47 connect( mHtmlCheckBox, &QCheckBox::stateChanged,
this, &QgsLayoutLabelWidget::mHtmlCheckBox_stateChanged );
48 connect( mTextEdit, &QPlainTextEdit::textChanged,
this, &QgsLayoutLabelWidget::mTextEdit_textChanged );
49 connect( mInsertExpressionButton, &QPushButton::clicked,
this, &QgsLayoutLabelWidget::mInsertExpressionButton_clicked );
50 connect( mMarginXDoubleSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLabelWidget::mMarginXDoubleSpinBox_valueChanged );
51 connect( mMarginYDoubleSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLabelWidget::mMarginYDoubleSpinBox_valueChanged );
53 mHAlignmentComboBox->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight | Qt::AlignJustify );
54 mVAlignmentComboBox->setAvailableAlignments( Qt::AlignTop | Qt::AlignVCenter | Qt::AlignBottom );
62 mFontButton->setDialogTitle( tr(
"Label Font" ) );
63 mFontButton->registerExpressionContextGenerator(
this );
67 mainLayout->addWidget( mItemPropertiesWidget );
69 mMarginXDoubleSpinBox->setClearValue( 0.0 );
70 mMarginYDoubleSpinBox->setClearValue( 0.0 );
72 setGuiElementValues();
77 mDynamicTextMenu =
new QMenu(
this );
78 mDynamicTextButton->setMenu( mDynamicTextMenu );
80 connect( mDynamicTextMenu, &QMenu::aboutToShow,
this, [
this] {
81 mDynamicTextMenu->clear();
82 if ( mLabel->layout() )
86 mLabel->beginCommand( tr(
"Insert dynamic text" ) );
87 mTextEdit->insertPlainText(
"[%" + expression.trimmed() +
"%]" );
93 QMenu *expressionMenu =
new QMenu(
this );
94 QAction *convertToStaticAction =
new QAction( tr(
"Convert to Static Text" ),
this );
95 expressionMenu->addAction( convertToStaticAction );
97 mInsertExpressionButton->setMenu( expressionMenu );
100 if ( mLabel->layout() )
108 if ( mItemPropertiesWidget )
109 mItemPropertiesWidget->setMasterLayout( masterLayout );
114 return mLabel->createExpressionContext();
120 auto addExpression = [&callback]( QMenu *menu,
const QString &name,
const QString &expression ) {
121 QAction *action =
new QAction( name, menu );
122 connect( action, &QAction::triggered, action, [callback, expression] {
123 callback( expression );
125 menu->addAction( action );
128 QMenu *dateMenu =
new QMenu( tr(
"Current Date" ), menu );
129 for (
const std::pair<QString, QString> &expression :
131 std::make_pair( tr(
"ISO Format (%1)" ).arg( QDateTime::currentDateTime().toString( u
"yyyy-MM-dd"_s ) ), u
"format_date(now(), 'yyyy-MM-dd')"_s ),
132 std::make_pair( tr(
"Day/Month/Year (%1)" ).arg( QDateTime::currentDateTime().toString( u
"dd/MM/yyyy"_s ) ), u
"format_date(now(), 'dd/MM/yyyy')"_s ),
133 std::make_pair( tr(
"Month/Day/Year (%1)" ).arg( QDateTime::currentDateTime().toString( u
"MM/dd/yyyy"_s ) ), u
"format_date(now(), 'MM/dd/yyyy')"_s ),
136 addExpression( dateMenu, expression.first, expression.second );
138 menu->addMenu( dateMenu );
140 QMenu *mapsMenu =
new QMenu( tr(
"Map Properties" ), menu );
141 QList<QgsLayoutItemMap *> maps;
146 if ( map->id().isEmpty() )
149 QMenu *mapMenu =
new QMenu( map->displayName(), mapsMenu );
150 for (
const std::pair<QString, QString> &expression :
152 std::make_pair( tr(
"Scale (%1)" ).arg( map->scale() ), u
"format_number(item_variables('%1')['map_scale'], places:=6, omit_group_separators:=true, trim_trailing_zeroes:=true)"_s.arg( map->id() ) ),
153 std::make_pair( tr(
"Rotation (%1)" ).arg( map->rotation() ), u
"item_variables('%1')['map_rotation']"_s.arg( map->id() ) ),
156 addExpression( mapMenu, expression.first, expression.second );
158 mapMenu->addSeparator();
159 for (
const std::pair<QString, QString> &expression :
161 std::make_pair( tr(
"CRS Identifier (%1)" ).arg( map->crs().authid() ), u
"item_variables('%1')['map_crs']"_s.arg( map->id() ) ),
162 std::make_pair( tr(
"CRS Name (%1)" ).arg( map->crs().description() ), u
"item_variables('%1')['map_crs_description']"_s.arg( map->id() ) ),
163 std::make_pair( tr(
"Ellipsoid Name (%1)" ).arg( map->crs().ellipsoidAcronym() ), u
"item_variables('%1')['map_crs_ellipsoid']"_s.arg( map->id() ) ),
164 std::make_pair( tr(
"Units (%1)" ).arg(
QgsUnitTypes::toString( map->crs().mapUnits() ) ), u
"item_variables('%1')['map_units']"_s.arg( map->id() ) ),
165 std::make_pair( tr(
"Projection (%1)" ).arg( map->crs().operation().description() ), u
"item_variables('%1')['map_crs_projection']"_s.arg( map->id() ) ),
168 addExpression( mapMenu, expression.first, expression.second );
170 mapMenu->addSeparator();
174 for (
const std::pair<QString, QString> &expression :
176 std::make_pair( tr(
"Center (X) (%1)" ).arg( center.
x() ), u
"x(item_variables('%1')['map_extent_center'])"_s.arg( map->id() ) ),
177 std::make_pair( tr(
"Center (Y) (%1)" ).arg( center.
y() ), u
"y(item_variables('%1')['map_extent_center'])"_s.arg( map->id() ) ),
178 std::make_pair( tr(
"X Minimum (%1)" ).arg( mapExtent.
xMinimum() ), u
"x_min(item_variables('%1')['map_extent'])"_s.arg( map->id() ) ),
179 std::make_pair( tr(
"Y Minimum (%1)" ).arg( mapExtent.
yMinimum() ), u
"y_min(item_variables('%1')['map_extent'])"_s.arg( map->id() ) ),
180 std::make_pair( tr(
"X Maximum (%1)" ).arg( mapExtent.
xMaximum() ), u
"x_max(item_variables('%1')['map_extent'])"_s.arg( map->id() ) ),
181 std::make_pair( tr(
"Y Maximum (%1)" ).arg( mapExtent.
yMaximum() ), u
"y_max(item_variables('%1')['map_extent'])"_s.arg( map->id() ) ),
184 addExpression( mapMenu, expression.first, expression.second );
186 mapMenu->addSeparator();
187 for (
const std::pair<QString, QString> &expression :
189 std::make_pair( tr(
"Layer Credits" ), u
"array_to_string(map_credits('%1'))"_s.arg( map->id() ) ),
192 addExpression( mapMenu, expression.first, expression.second );
194 mapsMenu->addMenu( mapMenu );
196 menu->addMenu( mapsMenu );
197 menu->addSeparator();
203 QMenu *fieldsMenu =
new QMenu( tr(
"Field" ), menu );
204 for (
const QgsField &field : fields )
206 addExpression( fieldsMenu, field.displayName(), u
"\"%1\""_s.arg( field.name() ) );
209 menu->addMenu( fieldsMenu );
210 menu->addSeparator();
213 for (
const std::pair<QString, QString> &expression :
215 std::make_pair( tr(
"Layout Name" ), u
"@layout_name"_s ),
216 std::make_pair( tr(
"Layout Page Number" ), u
"@layout_page"_s ),
217 std::make_pair( tr(
"Layout Page Count" ), u
"@layout_numpages"_s ),
218 std::make_pair( tr(
"Layer Credits" ), u
"array_to_string(map_credits())"_s )
221 addExpression( menu, expression.first, expression.second );
223 menu->addSeparator();
224 for (
const std::pair<QString, QString> &expression :
226 std::make_pair( tr(
"Project Author" ), u
"@project_author"_s ),
227 std::make_pair( tr(
"Project Title" ), u
"@project_title"_s ),
228 std::make_pair( tr(
"Project Path" ), u
"@project_path"_s )
231 addExpression( menu, expression.first, expression.second );
233 menu->addSeparator();
234 for (
const std::pair<QString, QString> &expression :
236 std::make_pair( tr(
"Current User Name" ), u
"@user_full_name"_s ),
237 std::make_pair( tr(
"Current User Account" ), u
"@user_account_name"_s )
240 addExpression( menu, expression.first, expression.second );
254 mLabel = qobject_cast<QgsLayoutItemLabel *>( item );
255 mItemPropertiesWidget->setItem( mLabel );
262 setGuiElementValues();
267void QgsLayoutLabelWidget::mHtmlCheckBox_stateChanged(
int state )
271 mVerticalAlignmentLabel->setDisabled( state );
272 mVAlignmentComboBox->setDisabled( state );
274 mLabel->beginCommand( tr(
"Change Label Mode" ) );
275 mLabel->blockSignals(
true );
277 mLabel->setText( mTextEdit->toPlainText() );
279 mLabel->blockSignals(
false );
280 mLabel->endCommand();
284void QgsLayoutLabelWidget::mTextEdit_textChanged()
289 mLabel->blockSignals(
true );
290 mLabel->setText( mTextEdit->toPlainText() );
292 mLabel->blockSignals(
false );
293 mLabel->endCommand();
297void QgsLayoutLabelWidget::fontChanged()
302 mLabel->setTextFormat( mFontButton->textFormat() );
304 mLabel->endCommand();
308void QgsLayoutLabelWidget::mMarginXDoubleSpinBox_valueChanged(
double d )
313 mLabel->setMarginX( d );
315 mLabel->endCommand();
319void QgsLayoutLabelWidget::mMarginYDoubleSpinBox_valueChanged(
double d )
324 mLabel->setMarginY( d );
326 mLabel->endCommand();
330void QgsLayoutLabelWidget::mInsertExpressionButton_clicked()
342 QgsExpressionContext context = mLabel->createExpressionContext();
343 QgsExpressionBuilderDialog exprDlg( layer, expression,
this, u
"generic"_s, context );
345 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
346 if ( exprDlg.exec() == QDialog::Accepted )
348 expression = exprDlg.expressionText();
349 if ( !expression.isEmpty() )
351 mLabel->beginCommand( tr(
"Insert expression" ) );
352 mTextEdit->insertPlainText(
"[%" + expression.trimmed() +
"%]" );
353 mLabel->endCommand();
358void QgsLayoutLabelWidget::horizontalAlignmentChanged()
362 mLabel->beginCommand( tr(
"Change Label Alignment" ) );
363 mLabel->setHAlign(
static_cast<Qt::AlignmentFlag
>(
static_cast<int>( mHAlignmentComboBox->currentAlignment() ) ) );
365 mLabel->endCommand();
369void QgsLayoutLabelWidget::verticalAlignmentChanged()
373 mLabel->beginCommand( tr(
"Change Label Alignment" ) );
374 mLabel->setVAlign(
static_cast<Qt::AlignmentFlag
>(
static_cast<int>( mVAlignmentComboBox->currentAlignment() ) ) );
376 mLabel->endCommand();
380void QgsLayoutLabelWidget::setGuiElementValues()
382 blockAllSignals(
true );
383 mTextEdit->setPlainText( mLabel->text() );
384 mTextEdit->moveCursor( QTextCursor::End, QTextCursor::MoveAnchor );
385 mMarginXDoubleSpinBox->setValue( mLabel->marginX() );
386 mMarginYDoubleSpinBox->setValue( mLabel->marginY() );
389 mHAlignmentComboBox->setCurrentAlignment( mLabel->hAlign() );
390 mVAlignmentComboBox->setCurrentAlignment( mLabel->vAlign() );
392 mFontButton->setTextFormat( mLabel->textFormat() );
396 blockAllSignals(
false );
399void QgsLayoutLabelWidget::blockAllSignals(
bool block )
401 mTextEdit->blockSignals( block );
402 mHtmlCheckBox->blockSignals( block );
403 mMarginXDoubleSpinBox->blockSignals( block );
404 mMarginYDoubleSpinBox->blockSignals( block );
405 mHAlignmentComboBox->blockSignals( block );
406 mVAlignmentComboBox->blockSignals( block );
407 mFontButton->blockSignals( block );
void changed()
Emitted when the alignment is changed.
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.
@ 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 rectangle specified with double values.
static Q_INVOKABLE QString toString(Qgis::DistanceUnit unit)
Returns a translated string representing a distance unit.