QGIS API Documentation 3.37.0-Master (614ebf5f6b2)
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#include "qgsexpressionfinder.h"
27
28#include <QColorDialog>
29#include <QFontDialog>
30#include <QWidget>
31#include <QAction>
32#include <QMenu>
33
35 : QgsLayoutItemBaseWidget( nullptr, label )
36 , mLabel( label )
37{
38 Q_ASSERT( mLabel );
39
40 setupUi( this );
41 connect( mHtmlCheckBox, &QCheckBox::stateChanged, this, &QgsLayoutLabelWidget::mHtmlCheckBox_stateChanged );
42 connect( mTextEdit, &QPlainTextEdit::textChanged, this, &QgsLayoutLabelWidget::mTextEdit_textChanged );
43 connect( mInsertExpressionButton, &QPushButton::clicked, this, &QgsLayoutLabelWidget::mInsertExpressionButton_clicked );
44 connect( mMarginXDoubleSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLabelWidget::mMarginXDoubleSpinBox_valueChanged );
45 connect( mMarginYDoubleSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLabelWidget::mMarginYDoubleSpinBox_valueChanged );
46 connect( mCenterRadioButton, &QRadioButton::clicked, this, &QgsLayoutLabelWidget::mCenterRadioButton_clicked );
47 connect( mLeftRadioButton, &QRadioButton::clicked, this, &QgsLayoutLabelWidget::mLeftRadioButton_clicked );
48 connect( mRightRadioButton, &QRadioButton::clicked, this, &QgsLayoutLabelWidget::mRightRadioButton_clicked );
49 connect( mTopRadioButton, &QRadioButton::clicked, this, &QgsLayoutLabelWidget::mTopRadioButton_clicked );
50 connect( mBottomRadioButton, &QRadioButton::clicked, this, &QgsLayoutLabelWidget::mBottomRadioButton_clicked );
51 connect( mMiddleRadioButton, &QRadioButton::clicked, this, &QgsLayoutLabelWidget::mMiddleRadioButton_clicked );
52 setPanelTitle( tr( "Label Properties" ) );
53
54 mFontButton->setMode( QgsFontButton::ModeTextRenderer );
55 mFontButton->setDialogTitle( tr( "Label Font" ) );
56 mFontButton->registerExpressionContextGenerator( this );
57
58 //add widget for general composer item properties
59 mItemPropertiesWidget = new QgsLayoutItemPropertiesWidget( this, label );
60 mainLayout->addWidget( mItemPropertiesWidget );
61
62 mMarginXDoubleSpinBox->setClearValue( 0.0 );
63 mMarginYDoubleSpinBox->setClearValue( 0.0 );
64
65 setGuiElementValues();
66 connect( mLabel, &QgsLayoutObject::changed, this, &QgsLayoutLabelWidget::setGuiElementValues );
67
68 connect( mFontButton, &QgsFontButton::changed, this, &QgsLayoutLabelWidget::fontChanged );
69 connect( mJustifyRadioButton, &QRadioButton::clicked, this, &QgsLayoutLabelWidget::justifyClicked );
70
71 mDynamicTextMenu = new QMenu( this );
72 mDynamicTextButton->setMenu( mDynamicTextMenu );
73
74 connect( mDynamicTextMenu, &QMenu::aboutToShow, this, [ = ]
75 {
76 mDynamicTextMenu->clear();
77 if ( mLabel->layout() )
78 {
79 // we need to rebuild this on each show, as the content varies depending on other available items...
80 buildInsertDynamicTextMenu( mLabel->layout(), mDynamicTextMenu, [ = ]( const QString & expression )
81 {
82 mLabel->beginCommand( tr( "Insert dynamic text" ) );
83 mTextEdit->insertPlainText( "[%" + expression.trimmed() + "%]" );
84 mLabel->endCommand();
85 } );
86 }
87 } );
88
89 QMenu *expressionMenu = new QMenu( this );
90 QAction *convertToStaticAction = new QAction( tr( "Convert to Static Text" ), this );
91 expressionMenu->addAction( convertToStaticAction );
92 connect( convertToStaticAction, &QAction::triggered, mLabel, &QgsLayoutItemLabel::convertToStaticText );
93 mInsertExpressionButton->setMenu( expressionMenu );
94
95 mFontButton->setLayer( coverageLayer() );
96 if ( mLabel->layout() )
97 {
98 connect( &mLabel->layout()->reportContext(), &QgsLayoutReportContext::layerChanged, mFontButton, &QgsFontButton::setLayer );
99 }
100}
101
103{
104 if ( mItemPropertiesWidget )
105 mItemPropertiesWidget->setMasterLayout( masterLayout );
106}
107
109{
110 return mLabel->createExpressionContext();
111}
112
113void QgsLayoutLabelWidget::buildInsertDynamicTextMenu( QgsLayout *layout, QMenu *menu, const std::function<void ( const QString & )> &callback )
114{
115 Q_ASSERT( layout );
116 auto addExpression = [&callback]( QMenu * menu, const QString & name, const QString & expression )
117 {
118 QAction *action = new QAction( name, menu );
119 connect( action, &QAction::triggered, action, [callback, expression]
120 {
121 callback( expression );
122 } );
123 menu->addAction( action );
124 };
125
126 QMenu *dateMenu = new QMenu( tr( "Current Date" ), menu );
127 for ( const std::pair< QString, QString > &expression :
128 {
129 std::make_pair( tr( "ISO Format (%1)" ).arg( QDateTime::currentDateTime().toString( QStringLiteral( "yyyy-MM-dd" ) ) ), QStringLiteral( "format_date(now(), 'yyyy-MM-dd')" ) ),
130 std::make_pair( tr( "Day/Month/Year (%1)" ).arg( QDateTime::currentDateTime().toString( QStringLiteral( "dd/MM/yyyy" ) ) ), QStringLiteral( "format_date(now(), 'dd/MM/yyyy')" ) ),
131 std::make_pair( tr( "Month/Day/Year (%1)" ).arg( QDateTime::currentDateTime().toString( QStringLiteral( "MM/dd/yyyy" ) ) ), QStringLiteral( "format_date(now(), 'MM/dd/yyyy')" ) ),
132 } )
133 {
134 addExpression( dateMenu, expression.first, expression.second );
135 }
136 menu->addMenu( dateMenu );
137
138 QMenu *mapsMenu = new QMenu( tr( "Map Properties" ), menu );
139 QList< QgsLayoutItemMap * > maps;
140 layout->layoutItems( maps );
141 for ( QgsLayoutItemMap *map : std::as_const( maps ) )
142 {
143 // these expressions require the map to have a non-empty ID set
144 if ( map->id().isEmpty() )
145 continue;
146
147 QMenu *mapMenu = new QMenu( map->displayName(), mapsMenu );
148 for ( const std::pair< QString, QString > &expression :
149 {
150 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() ) ),
151 std::make_pair( tr( "Rotation (%1)" ).arg( map->rotation() ), QStringLiteral( "item_variables('%1')['map_rotation']" ).arg( map->id() ) ),
152 } )
153 {
154 addExpression( mapMenu, expression.first, expression.second );
155 }
156 mapMenu->addSeparator();
157 for ( const std::pair< QString, QString > &expression :
158 {
159 std::make_pair( tr( "CRS Identifier (%1)" ).arg( map->crs().authid() ), QStringLiteral( "item_variables('%1')['map_crs']" ).arg( map->id() ) ),
160 std::make_pair( tr( "CRS Name (%1)" ).arg( map->crs().description() ), QStringLiteral( "item_variables('%1')['map_crs_description']" ).arg( map->id() ) ),
161 std::make_pair( tr( "Ellipsoid Name (%1)" ).arg( map->crs().ellipsoidAcronym() ), QStringLiteral( "item_variables('%1')['map_crs_ellipsoid']" ).arg( map->id() ) ),
162 std::make_pair( tr( "Units (%1)" ).arg( QgsUnitTypes::toString( map->crs().mapUnits() ) ), QStringLiteral( "item_variables('%1')['map_units']" ).arg( map->id() ) ),
163 std::make_pair( tr( "Projection (%1)" ).arg( map->crs().operation().description() ), QStringLiteral( "item_variables('%1')['map_crs_projection']" ).arg( map->id() ) ),
164 } )
165 {
166 addExpression( mapMenu, expression.first, expression.second );
167 }
168 mapMenu->addSeparator();
169
170 const QgsRectangle mapExtent = map->extent();
171 const QgsPointXY center = mapExtent.center();
172 for ( const std::pair< QString, QString > &expression :
173 {
174 std::make_pair( tr( "Center (X) (%1)" ).arg( center.x() ), QStringLiteral( "x(item_variables('%1')['map_extent_center'])" ).arg( map->id() ) ),
175 std::make_pair( tr( "Center (Y) (%1)" ).arg( center.y() ), QStringLiteral( "y(item_variables('%1')['map_extent_center'])" ).arg( map->id() ) ),
176 std::make_pair( tr( "X Minimum (%1)" ).arg( mapExtent.xMinimum() ), QStringLiteral( "x_min(item_variables('%1')['map_extent'])" ).arg( map->id() ) ),
177 std::make_pair( tr( "Y Minimum (%1)" ).arg( mapExtent.yMinimum() ), QStringLiteral( "y_min(item_variables('%1')['map_extent'])" ).arg( map->id() ) ),
178 std::make_pair( tr( "X Maximum (%1)" ).arg( mapExtent.xMaximum() ), QStringLiteral( "x_max(item_variables('%1')['map_extent'])" ).arg( map->id() ) ),
179 std::make_pair( tr( "Y Maximum (%1)" ).arg( mapExtent.yMaximum() ), QStringLiteral( "y_max(item_variables('%1')['map_extent'])" ).arg( map->id() ) ),
180 } )
181 {
182 addExpression( mapMenu, expression.first, expression.second );
183 }
184 mapMenu->addSeparator();
185 for ( const std::pair< QString, QString > &expression :
186 {
187 std::make_pair( tr( "Layer Credits" ), QStringLiteral( "array_to_string(map_credits('%1'))" ).arg( map->id() ) ),
188 } )
189 {
190 addExpression( mapMenu, expression.first, expression.second );
191 }
192 mapsMenu->addMenu( mapMenu );
193 }
194 menu->addMenu( mapsMenu );
195 menu->addSeparator();
196
197 if ( layout->reportContext().layer() )
198 {
199 const QgsFields fields = layout->reportContext().layer()->fields();
200
201 QMenu *fieldsMenu = new QMenu( tr( "Field" ), menu );
202 for ( const QgsField &field : fields )
203 {
204 addExpression( fieldsMenu, field.displayName(), QStringLiteral( "\"%1\"" ).arg( field.name() ) );
205 }
206
207 menu->addMenu( fieldsMenu );
208 menu->addSeparator();
209 }
210
211 for ( const std::pair< QString, QString > &expression :
212 {
213 std::make_pair( tr( "Layout Name" ), QStringLiteral( "@layout_name" ) ),
214 std::make_pair( tr( "Layout Page Number" ), QStringLiteral( "@layout_page" ) ),
215 std::make_pair( tr( "Layout Page Count" ), QStringLiteral( "@layout_numpages" ) ),
216 std::make_pair( tr( "Layer Credits" ), QStringLiteral( "array_to_string(map_credits())" ) )
217 } )
218 {
219 addExpression( menu, expression.first, expression.second );
220 }
221 menu->addSeparator();
222 for ( const std::pair< QString, QString > &expression :
223 {
224 std::make_pair( tr( "Project Author" ), QStringLiteral( "@project_author" ) ),
225 std::make_pair( tr( "Project Title" ), QStringLiteral( "@project_title" ) ),
226 std::make_pair( tr( "Project Path" ), QStringLiteral( "@project_path" ) )
227 } )
228 {
229 addExpression( menu, expression.first, expression.second );
230 }
231 menu->addSeparator();
232 for ( const std::pair< QString, QString > &expression :
233 {
234 std::make_pair( tr( "Current User Name" ), QStringLiteral( "@user_full_name" ) ),
235 std::make_pair( tr( "Current User Account" ), QStringLiteral( "@user_account_name" ) )
236 } )
237 {
238 addExpression( menu, expression.first, expression.second );
239 }
240}
241
243{
245 return false;
246
247 if ( mLabel )
248 {
249 disconnect( mLabel, &QgsLayoutObject::changed, this, &QgsLayoutLabelWidget::setGuiElementValues );
250 }
251
252 mLabel = qobject_cast< QgsLayoutItemLabel * >( item );
253 mItemPropertiesWidget->setItem( mLabel );
254
255 if ( mLabel )
256 {
257 connect( mLabel, &QgsLayoutObject::changed, this, &QgsLayoutLabelWidget::setGuiElementValues );
258 }
259
260 setGuiElementValues();
261
262 return true;
263}
264
265void QgsLayoutLabelWidget::mHtmlCheckBox_stateChanged( int state )
266{
267 if ( mLabel )
268 {
269 mVerticalAlignementLabel->setDisabled( state );
270 mTopRadioButton->setDisabled( state );
271 mMiddleRadioButton->setDisabled( state );
272 mBottomRadioButton->setDisabled( state );
273
274 mLabel->beginCommand( tr( "Change Label Mode" ) );
275 mLabel->blockSignals( true );
276 mLabel->setMode( state ? QgsLayoutItemLabel::ModeHtml : QgsLayoutItemLabel::ModeFont );
277 mLabel->setText( mTextEdit->toPlainText() );
278 mLabel->update();
279 mLabel->blockSignals( false );
280 mLabel->endCommand();
281 }
282}
283
284void QgsLayoutLabelWidget::mTextEdit_textChanged()
285{
286 if ( mLabel )
287 {
288 mLabel->beginCommand( tr( "Change Label Text" ), QgsLayoutItem::UndoLabelText );
289 mLabel->blockSignals( true );
290 mLabel->setText( mTextEdit->toPlainText() );
291 mLabel->update();
292 mLabel->blockSignals( false );
293 mLabel->endCommand();
294 }
295}
296
297void QgsLayoutLabelWidget::fontChanged()
298{
299 if ( mLabel )
300 {
301 mLabel->beginCommand( tr( "Change Label Font" ), QgsLayoutItem::UndoLabelFont );
302 mLabel->setTextFormat( mFontButton->textFormat() );
303 mLabel->update();
304 mLabel->endCommand();
305 }
306}
307
308void QgsLayoutLabelWidget::justifyClicked()
309{
310 if ( mLabel )
311 {
312 mLabel->beginCommand( tr( "Change Label Alignment" ) );
313 mLabel->setHAlign( Qt::AlignJustify );
314 mLabel->update();
315 mLabel->endCommand();
316 }
317}
318
319void QgsLayoutLabelWidget::mMarginXDoubleSpinBox_valueChanged( double d )
320{
321 if ( mLabel )
322 {
323 mLabel->beginCommand( tr( "Change Label Margin" ), QgsLayoutItem::UndoLabelMargin );
324 mLabel->setMarginX( d );
325 mLabel->update();
326 mLabel->endCommand();
327 }
328}
329
330void QgsLayoutLabelWidget::mMarginYDoubleSpinBox_valueChanged( double d )
331{
332 if ( mLabel )
333 {
334 mLabel->beginCommand( tr( "Change Label Margin" ), QgsLayoutItem::UndoLabelMargin );
335 mLabel->setMarginY( d );
336 mLabel->update();
337 mLabel->endCommand();
338 }
339}
340
341void QgsLayoutLabelWidget::mInsertExpressionButton_clicked()
342{
343 if ( !mLabel )
344 {
345 return;
346 }
347
348 QString expression = QgsExpressionFinder::findAndSelectActiveExpression( mTextEdit );
349
350 // use the atlas coverage layer, if any
351 QgsVectorLayer *layer = coverageLayer();
352
353 QgsExpressionContext context = mLabel->createExpressionContext();
354 QgsExpressionBuilderDialog exprDlg( layer, expression, this, QStringLiteral( "generic" ), context );
355
356 exprDlg.setWindowTitle( tr( "Insert Expression" ) );
357 if ( exprDlg.exec() == QDialog::Accepted )
358 {
359 expression = exprDlg.expressionText();
360 if ( !expression.isEmpty() )
361 {
362 mLabel->beginCommand( tr( "Insert expression" ) );
363 mTextEdit->insertPlainText( "[%" + expression.trimmed() + "%]" );
364 mLabel->endCommand();
365 }
366 }
367}
368
369void QgsLayoutLabelWidget::mCenterRadioButton_clicked()
370{
371 if ( mLabel )
372 {
373 mLabel->beginCommand( tr( "Change Label Alignment" ) );
374 mLabel->setHAlign( Qt::AlignHCenter );
375 mLabel->update();
376 mLabel->endCommand();
377 }
378}
379
380void QgsLayoutLabelWidget::mRightRadioButton_clicked()
381{
382 if ( mLabel )
383 {
384 mLabel->beginCommand( tr( "Change Label Alignment" ) );
385 mLabel->setHAlign( Qt::AlignRight );
386 mLabel->update();
387 mLabel->endCommand();
388 }
389}
390
391void QgsLayoutLabelWidget::mLeftRadioButton_clicked()
392{
393 if ( mLabel )
394 {
395 mLabel->beginCommand( tr( "Change Label Alignment" ) );
396 mLabel->setHAlign( Qt::AlignLeft );
397 mLabel->update();
398 mLabel->endCommand();
399 }
400}
401
402void QgsLayoutLabelWidget::mTopRadioButton_clicked()
403{
404 if ( mLabel )
405 {
406 mLabel->beginCommand( tr( "Change Label Alignment" ) );
407 mLabel->setVAlign( Qt::AlignTop );
408 mLabel->update();
409 mLabel->endCommand();
410 }
411}
412
413void QgsLayoutLabelWidget::mBottomRadioButton_clicked()
414{
415 if ( mLabel )
416 {
417 mLabel->beginCommand( tr( "Change Label Alignment" ) );
418 mLabel->setVAlign( Qt::AlignBottom );
419 mLabel->update();
420 mLabel->endCommand();
421 }
422}
423
424void QgsLayoutLabelWidget::mMiddleRadioButton_clicked()
425{
426 if ( mLabel )
427 {
428 mLabel->beginCommand( tr( "Change Label Alignment" ) );
429 mLabel->setVAlign( Qt::AlignVCenter );
430 mLabel->update();
431 mLabel->endCommand();
432 }
433}
434
435void QgsLayoutLabelWidget::setGuiElementValues()
436{
437 blockAllSignals( true );
438 mTextEdit->setPlainText( mLabel->text() );
439 mTextEdit->moveCursor( QTextCursor::End, QTextCursor::MoveAnchor );
440 mMarginXDoubleSpinBox->setValue( mLabel->marginX() );
441 mMarginYDoubleSpinBox->setValue( mLabel->marginY() );
442 mHtmlCheckBox->setChecked( mLabel->mode() == QgsLayoutItemLabel::ModeHtml );
443 mTopRadioButton->setChecked( mLabel->vAlign() == Qt::AlignTop );
444 mMiddleRadioButton->setChecked( mLabel->vAlign() == Qt::AlignVCenter );
445 mBottomRadioButton->setChecked( mLabel->vAlign() == Qt::AlignBottom );
446 mLeftRadioButton->setChecked( mLabel->hAlign() == Qt::AlignLeft );
447 mJustifyRadioButton->setChecked( mLabel->hAlign() == Qt::AlignJustify );
448 mCenterRadioButton->setChecked( mLabel->hAlign() == Qt::AlignHCenter );
449 mRightRadioButton->setChecked( mLabel->hAlign() == Qt::AlignRight );
450 mFontButton->setTextFormat( mLabel->textFormat() );
451 mVerticalAlignementLabel->setDisabled( mLabel->mode() == QgsLayoutItemLabel::ModeHtml );
452 mTopRadioButton->setDisabled( mLabel->mode() == QgsLayoutItemLabel::ModeHtml );
453 mMiddleRadioButton->setDisabled( mLabel->mode() == QgsLayoutItemLabel::ModeHtml );
454 mBottomRadioButton->setDisabled( mLabel->mode() == QgsLayoutItemLabel::ModeHtml );
455
456 blockAllSignals( false );
457}
458
459void QgsLayoutLabelWidget::blockAllSignals( bool block )
460{
461 mTextEdit->blockSignals( block );
462 mHtmlCheckBox->blockSignals( block );
463 mMarginXDoubleSpinBox->blockSignals( block );
464 mMarginYDoubleSpinBox->blockSignals( block );
465 mTopRadioButton->blockSignals( block );
466 mMiddleRadioButton->blockSignals( block );
467 mBottomRadioButton->blockSignals( block );
468 mLeftRadioButton->blockSignals( block );
469 mCenterRadioButton->blockSignals( block );
470 mRightRadioButton->blockSignals( block );
471 mJustifyRadioButton->blockSignals( block );
472 mFontButton->blockSignals( block );
473}
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.
Definition qgsfield.h:53
Container of fields for a vector layer.
Definition qgsfields.h:46
@ 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:49
void layoutItems(QList< T * > &itemList) const
Returns a list of layout items of a specific type.
Definition qgslayout.h:120
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:60
double y
Definition qgspointxy.h:64
double x
Definition qgspointxy.h:63
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.