QGIS API Documentation 3.34.0-Prizren (ffbdd678812)
Loading...
Searching...
No Matches
qgslayoutlabelwidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslayoutlabelwidget.cpp
3 ------------------------
4 begin : October 2017
5 copyright : (C) 2017 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19#include "qgslayoutitemlabel.h"
20#include "qgslayout.h"
22#include "qgslayoutitemmap.h"
23#include "qgsvectorlayer.h"
24#include "qgsprojoperation.h"
26
27#include <QColorDialog>
28#include <QFontDialog>
29#include <QWidget>
30#include <QAction>
31#include <QMenu>
32
34 : QgsLayoutItemBaseWidget( nullptr, label )
35 , mLabel( label )
36{
37 Q_ASSERT( mLabel );
38
39 setupUi( this );
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 );
51 setPanelTitle( tr( "Label Properties" ) );
52
53 mFontButton->setMode( QgsFontButton::ModeTextRenderer );
54 mFontButton->setDialogTitle( tr( "Label Font" ) );
55 mFontButton->registerExpressionContextGenerator( this );
56
57 //add widget for general composer item properties
58 mItemPropertiesWidget = new QgsLayoutItemPropertiesWidget( this, label );
59 mainLayout->addWidget( mItemPropertiesWidget );
60
61 mMarginXDoubleSpinBox->setClearValue( 0.0 );
62 mMarginYDoubleSpinBox->setClearValue( 0.0 );
63
64 setGuiElementValues();
65 connect( mLabel, &QgsLayoutObject::changed, this, &QgsLayoutLabelWidget::setGuiElementValues );
66
67 connect( mFontButton, &QgsFontButton::changed, this, &QgsLayoutLabelWidget::fontChanged );
68 connect( mJustifyRadioButton, &QRadioButton::clicked, this, &QgsLayoutLabelWidget::justifyClicked );
69
70 mDynamicTextMenu = new QMenu( this );
71 mDynamicTextButton->setMenu( mDynamicTextMenu );
72
73 connect( mDynamicTextMenu, &QMenu::aboutToShow, this, [ = ]
74 {
75 mDynamicTextMenu->clear();
76 if ( mLabel->layout() )
77 {
78 // we need to rebuild this on each show, as the content varies depending on other available items...
79 buildInsertDynamicTextMenu( mLabel->layout(), mDynamicTextMenu, [ = ]( const QString & expression )
80 {
81 mLabel->beginCommand( tr( "Insert dynamic text" ) );
82 mTextEdit->insertPlainText( "[%" + expression + "%]" );
83 mLabel->endCommand();
84 } );
85 }
86 } );
87
88 QMenu *expressionMenu = new QMenu( this );
89 QAction *convertToStaticAction = new QAction( tr( "Convert to Static Text" ), this );
90 expressionMenu->addAction( convertToStaticAction );
91 connect( convertToStaticAction, &QAction::triggered, mLabel, &QgsLayoutItemLabel::convertToStaticText );
92 mInsertExpressionButton->setMenu( expressionMenu );
93
94 mFontButton->setLayer( coverageLayer() );
95 if ( mLabel->layout() )
96 {
97 connect( &mLabel->layout()->reportContext(), &QgsLayoutReportContext::layerChanged, mFontButton, &QgsFontButton::setLayer );
98 }
99}
100
102{
103 if ( mItemPropertiesWidget )
104 mItemPropertiesWidget->setMasterLayout( masterLayout );
105}
106
108{
109 return mLabel->createExpressionContext();
110}
111
112void QgsLayoutLabelWidget::buildInsertDynamicTextMenu( QgsLayout *layout, QMenu *menu, const std::function<void ( const QString & )> &callback )
113{
114 Q_ASSERT( layout );
115 auto addExpression = [&callback]( QMenu * menu, const QString & name, const QString & expression )
116 {
117 QAction *action = new QAction( name, menu );
118 connect( action, &QAction::triggered, action, [callback, expression]
119 {
120 callback( expression );
121 } );
122 menu->addAction( action );
123 };
124
125 QMenu *dateMenu = new QMenu( tr( "Current Date" ), menu );
126 for ( const std::pair< QString, QString > &expression :
127 {
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')" ) ),
131 } )
132 {
133 addExpression( dateMenu, expression.first, expression.second );
134 }
135 menu->addMenu( dateMenu );
136
137 QMenu *mapsMenu = new QMenu( tr( "Map Properties" ), menu );
138 QList< QgsLayoutItemMap * > maps;
139 layout->layoutItems( maps );
140 for ( QgsLayoutItemMap *map : std::as_const( maps ) )
141 {
142 // these expressions require the map to have a non-empty ID set
143 if ( map->id().isEmpty() )
144 continue;
145
146 QMenu *mapMenu = new QMenu( map->displayName(), mapsMenu );
147 for ( const std::pair< QString, QString > &expression :
148 {
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() ) ),
151 } )
152 {
153 addExpression( mapMenu, expression.first, expression.second );
154 }
155 mapMenu->addSeparator();
156 for ( const std::pair< QString, QString > &expression :
157 {
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() ) ),
163 } )
164 {
165 addExpression( mapMenu, expression.first, expression.second );
166 }
167 mapMenu->addSeparator();
168
169 const QgsRectangle mapExtent = map->extent();
170 const QgsPointXY center = mapExtent.center();
171 for ( const std::pair< QString, QString > &expression :
172 {
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() ) ),
179 } )
180 {
181 addExpression( mapMenu, expression.first, expression.second );
182 }
183 mapMenu->addSeparator();
184 for ( const std::pair< QString, QString > &expression :
185 {
186 std::make_pair( tr( "Layer Credits" ), QStringLiteral( "array_to_string(map_credits('%1'))" ).arg( map->id() ) ),
187 } )
188 {
189 addExpression( mapMenu, expression.first, expression.second );
190 }
191 mapsMenu->addMenu( mapMenu );
192 }
193 menu->addMenu( mapsMenu );
194 menu->addSeparator();
195
196 if ( layout->reportContext().layer() )
197 {
198 const QgsFields fields = layout->reportContext().layer()->fields();
199
200 QMenu *fieldsMenu = new QMenu( tr( "Field" ), menu );
201 for ( const QgsField &field : fields )
202 {
203 addExpression( fieldsMenu, field.displayName(), QStringLiteral( "\"%1\"" ).arg( field.name() ) );
204 }
205
206 menu->addMenu( fieldsMenu );
207 menu->addSeparator();
208 }
209
210 for ( const std::pair< QString, QString > &expression :
211 {
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())" ) )
216 } )
217 {
218 addExpression( menu, expression.first, expression.second );
219 }
220 menu->addSeparator();
221 for ( const std::pair< QString, QString > &expression :
222 {
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" ) )
226 } )
227 {
228 addExpression( menu, expression.first, expression.second );
229 }
230 menu->addSeparator();
231 for ( const std::pair< QString, QString > &expression :
232 {
233 std::make_pair( tr( "Current User Name" ), QStringLiteral( "@user_full_name" ) ),
234 std::make_pair( tr( "Current User Account" ), QStringLiteral( "@user_account_name" ) )
235 } )
236 {
237 addExpression( menu, expression.first, expression.second );
238 }
239}
240
242{
244 return false;
245
246 if ( mLabel )
247 {
248 disconnect( mLabel, &QgsLayoutObject::changed, this, &QgsLayoutLabelWidget::setGuiElementValues );
249 }
250
251 mLabel = qobject_cast< QgsLayoutItemLabel * >( item );
252 mItemPropertiesWidget->setItem( mLabel );
253
254 if ( mLabel )
255 {
256 connect( mLabel, &QgsLayoutObject::changed, this, &QgsLayoutLabelWidget::setGuiElementValues );
257 }
258
259 setGuiElementValues();
260
261 return true;
262}
263
264void QgsLayoutLabelWidget::mHtmlCheckBox_stateChanged( int state )
265{
266 if ( mLabel )
267 {
268 mVerticalAlignementLabel->setDisabled( state );
269 mTopRadioButton->setDisabled( state );
270 mMiddleRadioButton->setDisabled( state );
271 mBottomRadioButton->setDisabled( state );
272
273 mLabel->beginCommand( tr( "Change Label Mode" ) );
274 mLabel->blockSignals( true );
275 mLabel->setMode( state ? QgsLayoutItemLabel::ModeHtml : QgsLayoutItemLabel::ModeFont );
276 mLabel->setText( mTextEdit->toPlainText() );
277 mLabel->update();
278 mLabel->blockSignals( false );
279 mLabel->endCommand();
280 }
281}
282
283void QgsLayoutLabelWidget::mTextEdit_textChanged()
284{
285 if ( mLabel )
286 {
287 mLabel->beginCommand( tr( "Change Label Text" ), QgsLayoutItem::UndoLabelText );
288 mLabel->blockSignals( true );
289 mLabel->setText( mTextEdit->toPlainText() );
290 mLabel->update();
291 mLabel->blockSignals( false );
292 mLabel->endCommand();
293 }
294}
295
296void QgsLayoutLabelWidget::fontChanged()
297{
298 if ( mLabel )
299 {
300 mLabel->beginCommand( tr( "Change Label Font" ), QgsLayoutItem::UndoLabelFont );
301 mLabel->setTextFormat( mFontButton->textFormat() );
302 mLabel->update();
303 mLabel->endCommand();
304 }
305}
306
307void QgsLayoutLabelWidget::justifyClicked()
308{
309 if ( mLabel )
310 {
311 mLabel->beginCommand( tr( "Change Label Alignment" ) );
312 mLabel->setHAlign( Qt::AlignJustify );
313 mLabel->update();
314 mLabel->endCommand();
315 }
316}
317
318void QgsLayoutLabelWidget::mMarginXDoubleSpinBox_valueChanged( double d )
319{
320 if ( mLabel )
321 {
322 mLabel->beginCommand( tr( "Change Label Margin" ), QgsLayoutItem::UndoLabelMargin );
323 mLabel->setMarginX( d );
324 mLabel->update();
325 mLabel->endCommand();
326 }
327}
328
329void QgsLayoutLabelWidget::mMarginYDoubleSpinBox_valueChanged( double d )
330{
331 if ( mLabel )
332 {
333 mLabel->beginCommand( tr( "Change Label Margin" ), QgsLayoutItem::UndoLabelMargin );
334 mLabel->setMarginY( d );
335 mLabel->update();
336 mLabel->endCommand();
337 }
338}
339
340void QgsLayoutLabelWidget::mInsertExpressionButton_clicked()
341{
342 if ( !mLabel )
343 {
344 return;
345 }
346
347 QString selText = mTextEdit->textCursor().selectedText();
348
349 // html editor replaces newlines with Paragraph Separator characters - see https://github.com/qgis/QGIS/issues/27568
350 selText = selText.replace( QChar( 0x2029 ), QChar( '\n' ) );
351
352 // edit the selected expression if there's one
353 if ( selText.startsWith( QLatin1String( "[%" ) ) && selText.endsWith( QLatin1String( "%]" ) ) )
354 selText = selText.mid( 2, selText.size() - 4 );
355
356 // use the atlas coverage layer, if any
357 QgsVectorLayer *layer = coverageLayer();
358
359 QgsExpressionContext context = mLabel->createExpressionContext();
360 QgsExpressionBuilderDialog exprDlg( layer, selText, this, QStringLiteral( "generic" ), context );
361
362 exprDlg.setWindowTitle( tr( "Insert Expression" ) );
363 if ( exprDlg.exec() == QDialog::Accepted )
364 {
365 QString expression = exprDlg.expressionText();
366 if ( !expression.isEmpty() )
367 {
368 mLabel->beginCommand( tr( "Insert expression" ) );
369 mTextEdit->insertPlainText( "[%" + expression + "%]" );
370 mLabel->endCommand();
371 }
372 }
373}
374
375void QgsLayoutLabelWidget::mCenterRadioButton_clicked()
376{
377 if ( mLabel )
378 {
379 mLabel->beginCommand( tr( "Change Label Alignment" ) );
380 mLabel->setHAlign( Qt::AlignHCenter );
381 mLabel->update();
382 mLabel->endCommand();
383 }
384}
385
386void QgsLayoutLabelWidget::mRightRadioButton_clicked()
387{
388 if ( mLabel )
389 {
390 mLabel->beginCommand( tr( "Change Label Alignment" ) );
391 mLabel->setHAlign( Qt::AlignRight );
392 mLabel->update();
393 mLabel->endCommand();
394 }
395}
396
397void QgsLayoutLabelWidget::mLeftRadioButton_clicked()
398{
399 if ( mLabel )
400 {
401 mLabel->beginCommand( tr( "Change Label Alignment" ) );
402 mLabel->setHAlign( Qt::AlignLeft );
403 mLabel->update();
404 mLabel->endCommand();
405 }
406}
407
408void QgsLayoutLabelWidget::mTopRadioButton_clicked()
409{
410 if ( mLabel )
411 {
412 mLabel->beginCommand( tr( "Change Label Alignment" ) );
413 mLabel->setVAlign( Qt::AlignTop );
414 mLabel->update();
415 mLabel->endCommand();
416 }
417}
418
419void QgsLayoutLabelWidget::mBottomRadioButton_clicked()
420{
421 if ( mLabel )
422 {
423 mLabel->beginCommand( tr( "Change Label Alignment" ) );
424 mLabel->setVAlign( Qt::AlignBottom );
425 mLabel->update();
426 mLabel->endCommand();
427 }
428}
429
430void QgsLayoutLabelWidget::mMiddleRadioButton_clicked()
431{
432 if ( mLabel )
433 {
434 mLabel->beginCommand( tr( "Change Label Alignment" ) );
435 mLabel->setVAlign( Qt::AlignVCenter );
436 mLabel->update();
437 mLabel->endCommand();
438 }
439}
440
441void QgsLayoutLabelWidget::setGuiElementValues()
442{
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() );
448 mHtmlCheckBox->setChecked( mLabel->mode() == QgsLayoutItemLabel::ModeHtml );
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() );
457 mVerticalAlignementLabel->setDisabled( mLabel->mode() == QgsLayoutItemLabel::ModeHtml );
458 mTopRadioButton->setDisabled( mLabel->mode() == QgsLayoutItemLabel::ModeHtml );
459 mMiddleRadioButton->setDisabled( mLabel->mode() == QgsLayoutItemLabel::ModeHtml );
460 mBottomRadioButton->setDisabled( mLabel->mode() == QgsLayoutItemLabel::ModeHtml );
461
462 blockAllSignals( false );
463}
464
465void QgsLayoutLabelWidget::blockAllSignals( bool block )
466{
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 );
479}
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.
Definition qgsfield.h:53
Container of fields for a vector layer.
Definition qgsfields.h:45
@ ModeTextRenderer
Configure font settings for use with QgsTextRenderer.
void setLayer(QgsVectorLayer *layer)
Sets a layer to associate with the widget.
void changed()
Emitted when the widget's text format settings are changed.
A base class for property widgets for layout items.
QgsVectorLayer * coverageLayer() const
Returns the current layout context coverage layer (if set).
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.
A widget for controlling the common properties of layout items (e.g.
void setMasterLayout(QgsMasterLayoutInterface *masterLayout)
Sets the master layout associated with the item.
void setItem(QgsLayoutItem *item)
Sets the layout item.
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 setMasterLayout(QgsMasterLayoutInterface *masterLayout) override
Sets the master layout associated with the item.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
bool setNewItem(QgsLayoutItem *item) override
Attempts to update the widget to show the properties for the specified item.
QgsLayoutLabelWidget(QgsLayoutItemLabel *label)
constructor
static void buildInsertDynamicTextMenu(QgsLayout *layout, QMenu *menu, const std::function< void(const QString &expression) > &callback)
Populates the specified menu with actions reflecting dynamic text expressions applicable for a layout...
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.
Definition qgslayout.h:50
void layoutItems(QList< T * > &itemList) const
Returns a list of layout items of a specific type.
Definition qgslayout.h:121
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.
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
A class to represent a 2D point.
Definition qgspointxy.h:59
double y
Definition qgspointxy.h:63
double x
Definition qgspointxy.h:62
A rectangle specified with double values.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double xMaximum() const
Returns the x maximum value (right side of rectangle).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
QgsPointXY center() const
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.