QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgslayoutmapwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayoutmapwidget.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  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 
19 #include "qgslayoutmapwidget.h"
20 #include "qgslayoutitemmap.h"
21 #include "qgsproject.h"
22 #include "qgsmapthemecollection.h"
23 #include "qgslayout.h"
24 #include "qgslayertree.h"
25 #include "qgsmapcanvas.h"
27 #include "qgssymbollayerutils.h"
28 #include "qgslayoutmapgridwidget.h"
29 #include "qgsstyle.h"
30 #include "qgslayoutundostack.h"
31 #include "qgslayoutatlas.h"
33 #include "qgsguiutils.h"
34 #include "qgsbookmarkmodel.h"
35 #include "qgsreferencedgeometry.h"
36 #include "qgsprojectviewsettings.h"
37 #include "qgsmaplayermodel.h"
38 #include "qgsfillsymbol.h"
39 
40 #include <QMenu>
41 #include <QMessageBox>
42 #include <QStringListModel>
43 
45  : QgsLayoutItemBaseWidget( nullptr, item )
46  , mMapItem( item )
47  , mMapCanvas( mapCanvas )
48 {
49  Q_ASSERT( mMapItem );
50 
51  setupUi( this );
52  connect( mScaleLineEdit, &QLineEdit::editingFinished, this, &QgsLayoutMapWidget::mScaleLineEdit_editingFinished );
53  connect( mActionSetToCanvasExtent, &QAction::triggered, this, &QgsLayoutMapWidget::setToMapCanvasExtent );
54  connect( mActionViewExtentInCanvas, &QAction::triggered, this, &QgsLayoutMapWidget::viewExtentInCanvas );
55  connect( mActionSetToCanvasScale, &QAction::triggered, this, &QgsLayoutMapWidget::setToMapCanvasScale );
56  connect( mActionViewScaleInCanvas, &QAction::triggered, this, &QgsLayoutMapWidget::viewScaleInCanvas );
57  connect( mActionUpdatePreview, &QAction::triggered, this, &QgsLayoutMapWidget::updatePreview );
58  connect( mFollowVisibilityPresetCheckBox, &QCheckBox::stateChanged, this, &QgsLayoutMapWidget::mFollowVisibilityPresetCheckBox_stateChanged );
59  connect( mKeepLayerListCheckBox, &QCheckBox::stateChanged, this, &QgsLayoutMapWidget::mKeepLayerListCheckBox_stateChanged );
60  connect( mKeepLayerStylesCheckBox, &QCheckBox::stateChanged, this, &QgsLayoutMapWidget::mKeepLayerStylesCheckBox_stateChanged );
61  connect( mDrawCanvasItemsCheckBox, &QCheckBox::stateChanged, this, &QgsLayoutMapWidget::mDrawCanvasItemsCheckBox_stateChanged );
62  connect( mOverviewBlendModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutMapWidget::mOverviewBlendModeComboBox_currentIndexChanged );
63  connect( mOverviewInvertCheckbox, &QCheckBox::toggled, this, &QgsLayoutMapWidget::mOverviewInvertCheckbox_toggled );
64  connect( mOverviewCenterCheckbox, &QCheckBox::toggled, this, &QgsLayoutMapWidget::mOverviewCenterCheckbox_toggled );
65  connect( mOverviewPositionComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutMapWidget::overviewStackingChanged );
66  connect( mOverviewStackingLayerComboBox, &QgsMapLayerComboBox::layerChanged, this, &QgsLayoutMapWidget::overviewStackingLayerChanged );
67  connect( mXMinLineEdit, &QLineEdit::editingFinished, this, &QgsLayoutMapWidget::mXMinLineEdit_editingFinished );
68  connect( mXMaxLineEdit, &QLineEdit::editingFinished, this, &QgsLayoutMapWidget::mXMaxLineEdit_editingFinished );
69  connect( mYMinLineEdit, &QLineEdit::editingFinished, this, &QgsLayoutMapWidget::mYMinLineEdit_editingFinished );
70  connect( mYMaxLineEdit, &QLineEdit::editingFinished, this, &QgsLayoutMapWidget::mYMaxLineEdit_editingFinished );
71  connect( mAtlasMarginRadio, &QRadioButton::toggled, this, &QgsLayoutMapWidget::mAtlasMarginRadio_toggled );
72  connect( mAtlasCheckBox, &QgsCollapsibleGroupBoxBasic::toggled, this, &QgsLayoutMapWidget::mAtlasCheckBox_toggled );
73  connect( mAtlasMarginSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsLayoutMapWidget::mAtlasMarginSpinBox_valueChanged );
74  connect( mAtlasFixedScaleRadio, &QRadioButton::toggled, this, &QgsLayoutMapWidget::mAtlasFixedScaleRadio_toggled );
75  connect( mAtlasPredefinedScaleRadio, &QRadioButton::toggled, this, &QgsLayoutMapWidget::mAtlasPredefinedScaleRadio_toggled );
76  connect( mAddGridPushButton, &QPushButton::clicked, this, &QgsLayoutMapWidget::mAddGridPushButton_clicked );
77  connect( mRemoveGridPushButton, &QPushButton::clicked, this, &QgsLayoutMapWidget::mRemoveGridPushButton_clicked );
78  connect( mGridUpButton, &QPushButton::clicked, this, &QgsLayoutMapWidget::mGridUpButton_clicked );
79  connect( mGridDownButton, &QPushButton::clicked, this, &QgsLayoutMapWidget::mGridDownButton_clicked );
80  connect( mGridListWidget, &QListWidget::currentItemChanged, this, &QgsLayoutMapWidget::mGridListWidget_currentItemChanged );
81  connect( mGridListWidget, &QListWidget::itemChanged, this, &QgsLayoutMapWidget::mGridListWidget_itemChanged );
82  connect( mGridPropertiesButton, &QPushButton::clicked, this, &QgsLayoutMapWidget::mGridPropertiesButton_clicked );
83  connect( mAddOverviewPushButton, &QPushButton::clicked, this, &QgsLayoutMapWidget::mAddOverviewPushButton_clicked );
84  connect( mRemoveOverviewPushButton, &QPushButton::clicked, this, &QgsLayoutMapWidget::mRemoveOverviewPushButton_clicked );
85  connect( mOverviewUpButton, &QPushButton::clicked, this, &QgsLayoutMapWidget::mOverviewUpButton_clicked );
86  connect( mOverviewDownButton, &QPushButton::clicked, this, &QgsLayoutMapWidget::mOverviewDownButton_clicked );
87  connect( mOverviewCheckBox, &QgsCollapsibleGroupBoxBasic::toggled, this, &QgsLayoutMapWidget::mOverviewCheckBox_toggled );
88  connect( mOverviewListWidget, &QListWidget::currentItemChanged, this, &QgsLayoutMapWidget::mOverviewListWidget_currentItemChanged );
89  connect( mOverviewListWidget, &QListWidget::itemChanged, this, &QgsLayoutMapWidget::mOverviewListWidget_itemChanged );
90  connect( mActionLabelSettings, &QAction::triggered, this, &QgsLayoutMapWidget::showLabelSettings );
91  connect( mActionClipSettings, &QAction::triggered, this, &QgsLayoutMapWidget::showClipSettings );
92 
93  connect( mTemporalCheckBox, &QgsCollapsibleGroupBoxBasic::toggled, this, &QgsLayoutMapWidget::mTemporalCheckBox_toggled );
94  connect( mStartDateTime, &QDateTimeEdit::dateTimeChanged, this, &QgsLayoutMapWidget::updateTemporalExtent );
95  connect( mEndDateTime, &QDateTimeEdit::dateTimeChanged, this, &QgsLayoutMapWidget::updateTemporalExtent );
96 
97  mStartDateTime->setDateTimeRange( QDateTime( QDate( 1, 1, 1 ), QTime( 0, 0, 0 ) ), mStartDateTime->maximumDateTime() );
98  mEndDateTime->setDateTimeRange( QDateTime( QDate( 1, 1, 1 ), QTime( 0, 0, 0 ) ), mStartDateTime->maximumDateTime() );
99  mStartDateTime->setDisplayFormat( "yyyy-MM-dd HH:mm:ss" );
100  mEndDateTime->setDisplayFormat( "yyyy-MM-dd HH:mm:ss" );
101 
102  connect( mActionMoveContent, &QAction::triggered, this, &QgsLayoutMapWidget::switchToMoveContentTool );
103  setPanelTitle( tr( "Map Properties" ) );
104  mMapRotationSpinBox->setClearValue( 0 );
105 
106  mDockToolbar->setIconSize( QgsGuiUtils::iconSize( true ) );
107 
108  mBookmarkMenu = new QMenu( this );
109  QToolButton *btnBookmarks = new QToolButton( this );
110  btnBookmarks->setAutoRaise( true );
111  btnBookmarks->setToolTip( tr( "Bookmarks" ) );
112  btnBookmarks->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowBookmarks.svg" ) ) );
113  btnBookmarks->setPopupMode( QToolButton::InstantPopup );
114  btnBookmarks->setMenu( mBookmarkMenu );
115 
116  mDockToolbar->insertWidget( mActionMoveContent, btnBookmarks );
117  connect( mBookmarkMenu, &QMenu::aboutToShow, this, &QgsLayoutMapWidget::aboutToShowBookmarkMenu );
118 
119  //add widget for general composer item properties
120  mItemPropertiesWidget = new QgsLayoutItemPropertiesWidget( this, item );
121  mainLayout->addWidget( mItemPropertiesWidget );
122 
123  mScaleLineEdit->setValidator( new QDoubleValidator( mScaleLineEdit ) );
124 
125  mXMinLineEdit->setValidator( new QDoubleValidator( mXMinLineEdit ) );
126  mXMaxLineEdit->setValidator( new QDoubleValidator( mXMaxLineEdit ) );
127  mYMinLineEdit->setValidator( new QDoubleValidator( mYMinLineEdit ) );
128  mYMaxLineEdit->setValidator( new QDoubleValidator( mYMaxLineEdit ) );
129 
130  mOverviewPositionComboBox->addItem( tr( "Below Map" ), QgsLayoutItemMapItem::StackBelowMap );
131  mOverviewPositionComboBox->addItem( tr( "Below Map Layer" ), QgsLayoutItemMapItem::StackBelowMapLayer );
132  mOverviewPositionComboBox->addItem( tr( "Above Map Layer" ), QgsLayoutItemMapItem::StackAboveMapLayer );
133  mOverviewPositionComboBox->addItem( tr( "Below Map Labels" ), QgsLayoutItemMapItem::StackBelowMapLabels );
134  mOverviewPositionComboBox->addItem( tr( "Above Map Labels" ), QgsLayoutItemMapItem::StackAboveMapLabels );
135 
136  blockAllSignals( true );
137 
138  mCrsSelector->setOptionVisible( QgsProjectionSelectionWidget::CrsNotSet, true );
139  mCrsSelector->setNotSetText( tr( "Use Project CRS" ) );
140  mCrsSelector->setDialogTitle( tr( "Map Item CRS" ) );
141 
142  mOverviewFrameStyleButton->setSymbolType( Qgis::SymbolType::Fill );
143 
144  // follow preset combo
145  mFollowVisibilityPresetCombo->setModel( new QStringListModel( mFollowVisibilityPresetCombo ) );
146  connect( mFollowVisibilityPresetCombo, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutMapWidget::followVisibilityPresetSelected );
147  connect( QgsProject::instance()->mapThemeCollection(), &QgsMapThemeCollection::mapThemesChanged,
148  this, &QgsLayoutMapWidget::onMapThemesChanged );
149  onMapThemesChanged();
150 
151  // keep layers from preset button
152  QMenu *menuKeepLayers = new QMenu( this );
153  mLayerListFromPresetButton->setMenu( menuKeepLayers );
154  mLayerListFromPresetButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowAllLayers.svg" ) ) );
155  mLayerListFromPresetButton->setToolTip( tr( "Set layer list from a map theme" ) );
156  connect( menuKeepLayers, &QMenu::aboutToShow, this, &QgsLayoutMapWidget::aboutToShowKeepLayersVisibilityPresetsMenu );
157 
158  connect( item, &QgsLayoutObject::changed, this, &QgsLayoutMapWidget::updateGuiElements );
159 
161  this, &QgsLayoutMapWidget::atlasLayerChanged );
162  if ( QgsLayoutAtlas *atlas = layoutAtlas() )
163  {
164  connect( atlas, &QgsLayoutAtlas::toggled, this, &QgsLayoutMapWidget::compositionAtlasToggled );
165  compositionAtlasToggled( atlas->enabled() );
166  }
167 
168  mOverviewFrameMapComboBox->setCurrentLayout( item->layout() );
169  mOverviewFrameMapComboBox->setItemType( QgsLayoutItemRegistry::LayoutMap );
170  mOverviewFrameStyleButton->registerExpressionContextGenerator( item );
171 
172  connect( mOverviewFrameMapComboBox, &QgsLayoutItemComboBox::itemChanged, this, &QgsLayoutMapWidget::overviewMapChanged );
173  connect( mCrsSelector, &QgsProjectionSelectionWidget::crsChanged, this, &QgsLayoutMapWidget::mapCrsChanged );
174  connect( mOverviewFrameStyleButton, &QgsSymbolButton::changed, this, &QgsLayoutMapWidget::overviewSymbolChanged );
175 
176  mOverviewFrameStyleButton->registerExpressionContextGenerator( item );
177  mOverviewFrameStyleButton->setLayer( coverageLayer() );
178  if ( item->layout() )
179  {
180  connect( &item->layout()->reportContext(), &QgsLayoutReportContext::layerChanged, mOverviewFrameStyleButton, &QgsSymbolButton::setLayer );
181  }
182 
183 
196 
197  updateGuiElements();
198  loadGridEntries();
199  loadOverviewEntries();
200 
201  connect( mMapRotationSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsLayoutMapWidget::rotationChanged );
202  connect( mMapItem, &QgsLayoutItemMap::extentChanged, mItemPropertiesWidget, &QgsLayoutItemPropertiesWidget::updateVariables );
203  connect( mMapItem, &QgsLayoutItemMap::mapRotationChanged, mItemPropertiesWidget, &QgsLayoutItemPropertiesWidget::updateVariables );
204 
205  blockAllSignals( false );
206 }
207 
209 {
210  if ( mItemPropertiesWidget )
211  mItemPropertiesWidget->setMasterLayout( masterLayout );
212 }
213 
214 void QgsLayoutMapWidget::setReportTypeString( const QString &string )
215 {
216  mReportTypeString = string;
217  mAtlasCheckBox->setTitle( tr( "Controlled by %1" ).arg( string == tr( "atlas" ) ? tr( "Atlas" ) : tr( "Report" ) ) );
218  mAtlasPredefinedScaleRadio->setToolTip( tr( "Use one of the predefined scales of the project where the %1 feature best fits." ).arg( string ) );
219 
220  if ( mClipWidget )
221  mClipWidget->setReportTypeString( string );
222  if ( mLabelWidget )
223  mLabelWidget->setReportTypeString( string );
224 }
225 
227 {
228  mInterface = iface;
230 }
231 
233 {
234  if ( item->type() != QgsLayoutItemRegistry::LayoutMap )
235  return false;
236 
237  if ( mMapItem )
238  {
239  disconnect( mMapItem, &QgsLayoutObject::changed, this, &QgsLayoutMapWidget::updateGuiElements );
240  disconnect( mMapItem, &QgsLayoutItemMap::extentChanged, mItemPropertiesWidget, &QgsLayoutItemPropertiesWidget::updateVariables );
241  disconnect( mMapItem, &QgsLayoutItemMap::mapRotationChanged, mItemPropertiesWidget, &QgsLayoutItemPropertiesWidget::updateVariables );
242  }
243 
244  mMapItem = qobject_cast< QgsLayoutItemMap * >( item );
245  mItemPropertiesWidget->setItem( mMapItem );
246  if ( mLabelWidget )
247  mLabelWidget->setItem( mMapItem );
248  if ( mClipWidget )
249  mClipWidget->setItem( mMapItem );
250 
251  if ( mMapItem )
252  {
253  connect( mMapItem, &QgsLayoutObject::changed, this, &QgsLayoutMapWidget::updateGuiElements );
254  connect( mMapItem, &QgsLayoutItemMap::extentChanged, mItemPropertiesWidget, &QgsLayoutItemPropertiesWidget::updateVariables );
255  connect( mMapItem, &QgsLayoutItemMap::mapRotationChanged, mItemPropertiesWidget, &QgsLayoutItemPropertiesWidget::updateVariables );
256  mOverviewFrameStyleButton->registerExpressionContextGenerator( mMapItem );
257  }
258 
259  updateGuiElements();
260 
261  return true;
262 }
263 
265 {
266  updateDataDefinedButton( mScaleDDBtn );
267  updateDataDefinedButton( mMapRotationDDBtn );
268  updateDataDefinedButton( mXMinDDBtn );
269  updateDataDefinedButton( mYMinDDBtn );
270  updateDataDefinedButton( mXMaxDDBtn );
271  updateDataDefinedButton( mYMaxDDBtn );
272  updateDataDefinedButton( mAtlasMarginDDBtn );
273  updateDataDefinedButton( mStylePresetsDDBtn );
274  updateDataDefinedButton( mLayersDDBtn );
275  updateDataDefinedButton( mCRSDDBtn );
276  updateDataDefinedButton( mStartDateTimeDDBtn );
277  updateDataDefinedButton( mEndDateTimeDDBtn );
278 }
279 
280 void QgsLayoutMapWidget::compositionAtlasToggled( bool atlasEnabled )
281 {
282  if ( atlasEnabled &&
283  mMapItem && mMapItem->layout() && mMapItem->layout()->reportContext().layer()
284  && mMapItem->layout()->reportContext().layer()->wkbType() != QgsWkbTypes::NoGeometry )
285  {
286  mAtlasCheckBox->setEnabled( true );
287  }
288  else
289  {
290  mAtlasCheckBox->setEnabled( false );
291  mAtlasCheckBox->setChecked( false );
292  }
293 }
294 
295 void QgsLayoutMapWidget::aboutToShowKeepLayersVisibilityPresetsMenu()
296 {
297  // this menu is for the case when setting "keep layers" and "keep layer styles"
298  // and the preset configuration is copied. The preset is not followed further.
299 
300  QMenu *menu = qobject_cast<QMenu *>( sender() );
301  if ( !menu )
302  return;
303 
304  menu->clear();
305  const auto constMapThemes = QgsProject::instance()->mapThemeCollection()->mapThemes();
306  for ( const QString &presetName : constMapThemes )
307  {
308  menu->addAction( presetName, this, &QgsLayoutMapWidget::keepLayersVisibilityPresetSelected );
309  }
310 
311  if ( menu->actions().isEmpty() )
312  menu->addAction( tr( "No presets defined" ) )->setEnabled( false );
313 }
314 
315 void QgsLayoutMapWidget::followVisibilityPresetSelected( int currentIndex )
316 {
317  if ( !mMapItem )
318  return;
319 
320  if ( mBlockThemeComboChanges != 0 )
321  return;
322 
323  if ( currentIndex == -1 )
324  return; // doing combo box model reset
325 
326  QString presetName;
327  if ( currentIndex != 0 )
328  {
329  presetName = mFollowVisibilityPresetCombo->currentText();
330  }
331 
332  if ( presetName == mMapItem->followVisibilityPresetName() )
333  return;
334 
335  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Map Preset" ) );
336  mFollowVisibilityPresetCheckBox->setChecked( true );
337  mMapItem->setFollowVisibilityPresetName( presetName );
338  mMapItem->layout()->undoStack()->endCommand();
339 
340  mMapItem->invalidateCache();
341 }
342 
343 void QgsLayoutMapWidget::keepLayersVisibilityPresetSelected()
344 {
345  QAction *action = qobject_cast<QAction *>( sender() );
346  if ( !action )
347  return;
348 
349  const QString presetName = action->text();
350  const QList<QgsMapLayer *> lst = orderedPresetVisibleLayers( presetName );
351  if ( mMapItem )
352  {
353  mKeepLayerListCheckBox->setChecked( true );
354  mMapItem->setLayers( lst );
355 
356  mKeepLayerStylesCheckBox->setChecked( true );
357 
358  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Map Preset" ) );
359  mMapItem->setLayerStyleOverrides( QgsProject::instance()->mapThemeCollection()->mapThemeStyleOverrides( presetName ) );
360  mMapItem->layout()->undoStack()->endCommand();
361 
362  mMapItem->invalidateCache();
363  }
364 }
365 
366 void QgsLayoutMapWidget::onMapThemesChanged()
367 {
368  if ( QStringListModel *model = qobject_cast<QStringListModel *>( mFollowVisibilityPresetCombo->model() ) )
369  {
370  mBlockThemeComboChanges++;
371  QStringList lst;
372  lst.append( tr( "(none)" ) );
374  model->setStringList( lst );
375 
376  // select the previously selected item again
377  const int presetModelIndex = mFollowVisibilityPresetCombo->findText( mMapItem->followVisibilityPresetName() );
378  mFollowVisibilityPresetCombo->blockSignals( true );
379  mFollowVisibilityPresetCombo->setCurrentIndex( presetModelIndex != -1 ? presetModelIndex : 0 ); // 0 == none
380  mFollowVisibilityPresetCombo->blockSignals( false );
381  mBlockThemeComboChanges--;
382  }
383 }
384 
385 void QgsLayoutMapWidget::mapCrsChanged( const QgsCoordinateReferenceSystem &crs )
386 {
387  if ( !mMapItem )
388  {
389  return;
390  }
391 
392  if ( mMapItem->presetCrs() == crs )
393  return;
394 
395  // try to reproject to maintain extent
396  const QgsCoordinateReferenceSystem oldCrs = mMapItem->crs();
397 
398  bool updateExtent = false;
399  QgsRectangle newExtent;
400  try
401  {
403  xForm.setBallparkTransformsAreAppropriate( true );
404  const QgsRectangle prevExtent = mMapItem->extent();
405  newExtent = xForm.transformBoundingBox( prevExtent );
406  updateExtent = true;
407  }
408  catch ( QgsCsException & )
409  {
410  //transform failed, don't update extent
411  }
412 
413  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Map CRS" ) );
414  mMapItem->setCrs( crs );
415  if ( updateExtent )
416  mMapItem->zoomToExtent( newExtent );
417  mMapItem->layout()->undoStack()->endCommand();
418  mMapItem->invalidateCache();
419 }
420 
421 void QgsLayoutMapWidget::overviewSymbolChanged()
422 {
423  QgsLayoutItemMapOverview *overview = currentOverview();
424  if ( !overview )
425  return;
426 
427  mMapItem->beginCommand( tr( "Change Overview Style" ), QgsLayoutItem::UndoOverviewStyle );
428  overview->setFrameSymbol( mOverviewFrameStyleButton->clonedSymbol<QgsFillSymbol>() );
429  mMapItem->endCommand();
430  mMapItem->invalidateCache();
431 }
432 
433 void QgsLayoutMapWidget::showLabelSettings()
434 {
435  mLabelWidget = new QgsLayoutMapLabelingWidget( mMapItem );
436 
437  if ( !mReportTypeString.isEmpty() )
438  mLabelWidget->setReportTypeString( mReportTypeString );
439 
440  openPanel( mLabelWidget );
441 }
442 
443 void QgsLayoutMapWidget::showClipSettings()
444 {
445  mClipWidget = new QgsLayoutMapClippingWidget( mMapItem );
446  if ( !mReportTypeString.isEmpty() )
447  mClipWidget->setReportTypeString( mReportTypeString );
448  openPanel( mClipWidget );
449 }
450 
451 void QgsLayoutMapWidget::switchToMoveContentTool()
452 {
453  if ( mInterface )
455 }
456 
457 void QgsLayoutMapWidget::aboutToShowBookmarkMenu()
458 {
459  mBookmarkMenu->clear();
460 
461  // query the bookmarks now? or once during widget creation... Hmm. Either way, there's potentially a
462  // delay if there's LOTS of bookmarks. Let's avoid the cost until bookmarks are actually required.
463  if ( !mBookmarkModel )
464  mBookmarkModel = new QgsBookmarkManagerProxyModel( QgsApplication::bookmarkManager(), QgsProject::instance()->bookmarkManager(), this );
465 
466  QMap< QString, QMenu * > groupMenus;
467  for ( int i = 0; i < mBookmarkModel->rowCount(); ++i )
468  {
469  const QString group = mBookmarkModel->data( mBookmarkModel->index( i, 0 ), QgsBookmarkManagerModel::RoleGroup ).toString();
470  QMenu *destMenu = mBookmarkMenu;
471  if ( !group.isEmpty() )
472  {
473  destMenu = groupMenus.value( group );
474  if ( !destMenu )
475  {
476  destMenu = new QMenu( group, mBookmarkMenu );
477  groupMenus[ group ] = destMenu;
478  }
479  }
480  QAction *action = new QAction( mBookmarkModel->data( mBookmarkModel->index( i, 0 ), QgsBookmarkManagerModel::RoleName ).toString(), mBookmarkMenu );
481  const QgsReferencedRectangle extent = mBookmarkModel->data( mBookmarkModel->index( i, 0 ), QgsBookmarkManagerModel::RoleExtent ).value< QgsReferencedRectangle >();
482  connect( action, &QAction::triggered, this, [ = ]
483  {
484  if ( !mMapItem )
485  {
486  return;
487  }
488 
489  QgsRectangle newExtent = extent;
490 
491  //transform?
492  if ( extent.crs() != mMapItem->crs() )
493  {
494  try
495  {
496  QgsCoordinateTransform xForm( extent.crs(), mMapItem->crs(), QgsProject::instance() );
497  xForm.setBallparkTransformsAreAppropriate( true );
498  newExtent = xForm.transformBoundingBox( newExtent );
499  }
500  catch ( QgsCsException & )
501  {
502  //transform failed, better not proceed
503  return;
504  }
505  }
506 
507  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Map Extent" ) );
508  mMapItem->zoomToExtent( newExtent );
509  mMapItem->layout()->undoStack()->endCommand();
510  } );
511  destMenu->addAction( action );
512  }
513 
514  QStringList groupKeys = groupMenus.keys();
515  groupKeys.sort( Qt::CaseInsensitive );
516  for ( int i = 0; i < groupKeys.count(); ++i )
517  {
518  if ( mBookmarkMenu->actions().value( i ) )
519  mBookmarkMenu->insertMenu( mBookmarkMenu->actions().at( i ), groupMenus.value( groupKeys.at( i ) ) );
520  else
521  mBookmarkMenu->addMenu( groupMenus.value( groupKeys.at( i ) ) );
522  }
523 }
524 
525 void QgsLayoutMapWidget::mTemporalCheckBox_toggled( bool checked )
526 {
527  if ( !mMapItem )
528  {
529  return;
530  }
531 
532  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Toggle Temporal Range" ) );
533  mMapItem->setIsTemporal( checked );
534  mMapItem->layout()->undoStack()->endCommand();
535 
536  if ( checked )
537  {
538  whileBlocking( mStartDateTime )->setDateTime( mMapItem->temporalRange().begin() );
539  whileBlocking( mEndDateTime )->setDateTime( mMapItem->temporalRange().end() );
540  }
541 
542  updatePreview();
543 }
544 
545 void QgsLayoutMapWidget::updateTemporalExtent()
546 {
547  if ( !mMapItem )
548  {
549  return;
550  }
551 
552  const QDateTime begin = mStartDateTime->dateTime();
553  const QDateTime end = mEndDateTime->dateTime();
554  const QgsDateTimeRange range = QgsDateTimeRange( begin, end, true, begin == end );
555 
556  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Set Temporal Range" ) );
557  mMapItem->setTemporalRange( range );
558  mMapItem->layout()->undoStack()->endCommand();
559 
560  updatePreview();
561 }
562 
563 void QgsLayoutMapWidget::mAtlasCheckBox_toggled( bool checked )
564 {
565  if ( !mMapItem )
566  {
567  return;
568  }
569 
570  mAtlasFixedScaleRadio->setEnabled( checked );
571  mAtlasMarginRadio->setEnabled( checked );
572 
573  if ( mAtlasMarginRadio->isEnabled() && mAtlasMarginRadio->isChecked() )
574  {
575  mAtlasMarginSpinBox->setEnabled( true );
576  }
577  else
578  {
579  mAtlasMarginSpinBox->setEnabled( false );
580  }
581 
582  mAtlasPredefinedScaleRadio->setEnabled( checked );
583 
584  if ( checked )
585  {
586  //check atlas coverage layer type
587  if ( mMapItem->layout() )
588  {
589  toggleAtlasScalingOptionsByLayerType();
590  }
591  }
592 
593  // disable predefined scales if none are defined
594  if ( !hasPredefinedScales() )
595  {
596  mAtlasPredefinedScaleRadio->setEnabled( false );
597  }
598 
599  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Set Atlas Driven" ) );
600  mMapItem->setAtlasDriven( checked );
601  mMapItem->layout()->undoStack()->endCommand();
602  updateMapForAtlas();
603 }
604 
605 void QgsLayoutMapWidget::updateMapForAtlas()
606 {
607  //update map if in atlas preview mode
608  if ( mMapItem->atlasDriven() )
609  {
610  mMapItem->refresh();
611  }
612  else
613  {
614  //redraw map
615  mMapItem->invalidateCache();
616  }
617 }
618 
619 void QgsLayoutMapWidget::mAtlasMarginRadio_toggled( bool checked )
620 {
621  mAtlasMarginSpinBox->setEnabled( checked );
622 
623  if ( checked && mMapItem )
624  {
625  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Atlas Mode" ) );
626  mMapItem->setAtlasScalingMode( QgsLayoutItemMap::Auto );
627  mMapItem->layout()->undoStack()->endCommand();
628  updateMapForAtlas();
629  }
630 }
631 
632 void QgsLayoutMapWidget::mAtlasMarginSpinBox_valueChanged( int value )
633 {
634  if ( !mMapItem )
635  {
636  return;
637  }
638 
639  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Atlas Margin" ), QgsLayoutItem::UndoAtlasMargin );
640  mMapItem->setAtlasMargin( value / 100. );
641  mMapItem->layout()->undoStack()->endCommand();
642  updateMapForAtlas();
643 }
644 
645 void QgsLayoutMapWidget::mAtlasFixedScaleRadio_toggled( bool checked )
646 {
647  if ( !mMapItem )
648  {
649  return;
650  }
651 
652  if ( checked )
653  {
654  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Atlas Mode" ) );
655  mMapItem->setAtlasScalingMode( QgsLayoutItemMap::Fixed );
656  mMapItem->layout()->undoStack()->endCommand();
657  updateMapForAtlas();
658  }
659 }
660 
661 void QgsLayoutMapWidget::mAtlasPredefinedScaleRadio_toggled( bool checked )
662 {
663  if ( !mMapItem )
664  {
665  return;
666  }
667 
668  if ( hasPredefinedScales() )
669  {
670  if ( checked )
671  {
672  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Atlas Scales" ) );
673  mMapItem->setAtlasScalingMode( QgsLayoutItemMap::Predefined );
674  mMapItem->layout()->undoStack()->endCommand();
675  updateMapForAtlas();
676  }
677  }
678  else
679  {
680  // restore to fixed scale if no predefined scales exist
681  whileBlocking( mAtlasFixedScaleRadio )->setChecked( true );
682  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Atlas Mode" ) );
683  mMapItem->setAtlasScalingMode( QgsLayoutItemMap::Fixed );
684  mMapItem->layout()->undoStack()->endCommand();
685  }
686 }
687 
688 void QgsLayoutMapWidget::mScaleLineEdit_editingFinished()
689 {
690  if ( !mMapItem )
691  {
692  return;
693  }
694 
695  bool conversionSuccess = false;
696  const double scaleDenominator = QLocale().toDouble( mScaleLineEdit->text(), &conversionSuccess );
697  if ( !conversionSuccess )
698  {
699  return;
700  }
701 
702  if ( qgsDoubleNear( scaleDenominator, mMapItem->scale() ) )
703  return;
704 
705  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Map Scale" ) );
706  mMapItem->setScale( scaleDenominator );
707  mMapItem->layout()->undoStack()->endCommand();
708 }
709 
710 void QgsLayoutMapWidget::rotationChanged( double value )
711 {
712  if ( !mMapItem )
713  {
714  return;
715  }
716 
717  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Map Rotation" ), QgsLayoutItem::UndoMapRotation );
718  mMapItem->setMapRotation( value );
719  mMapItem->layout()->undoStack()->endCommand();
720  mMapItem->invalidateCache();
721 }
722 
723 void QgsLayoutMapWidget::setToMapCanvasExtent()
724 {
725  if ( !mMapItem )
726  {
727  return;
728  }
729 
730  QgsRectangle newExtent = mMapCanvas->mapSettings().visibleExtent();
731 
732  //transform?
733  if ( mMapCanvas->mapSettings().destinationCrs()
734  != mMapItem->crs() )
735  {
736  try
737  {
738  QgsCoordinateTransform xForm( mMapCanvas->mapSettings().destinationCrs(),
739  mMapItem->crs(), QgsProject::instance() );
740  xForm.setBallparkTransformsAreAppropriate( true );
741  newExtent = xForm.transformBoundingBox( newExtent );
742  }
743  catch ( QgsCsException & )
744  {
745  //transform failed, better not proceed
746  return;
747  }
748  }
749 
750  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Map Extent" ) );
751  mMapItem->zoomToExtent( newExtent );
752  mMapItem->layout()->undoStack()->endCommand();
753 }
754 
755 void QgsLayoutMapWidget::setToMapCanvasScale()
756 {
757  if ( !mMapItem )
758  {
759  return;
760  }
761 
762  const double newScale = mMapCanvas->scale();
763 
764  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Map Scale" ) );
765  mMapItem->setScale( newScale );
766  mMapItem->layout()->undoStack()->endCommand();
767 }
768 
769 void QgsLayoutMapWidget::viewExtentInCanvas()
770 {
771  if ( !mMapItem )
772  {
773  return;
774  }
775 
776  const QgsRectangle currentMapExtent = mMapItem->extent();
777 
778  if ( !currentMapExtent.isEmpty() )
779  {
780  try
781  {
782  mMapCanvas->setReferencedExtent( QgsReferencedRectangle( currentMapExtent, mMapItem->crs() ) );
783  }
784  catch ( QgsCsException & )
785  {
786  //transform failed, better not proceed
787  return;
788  }
789  mMapCanvas->refresh();
790  }
791 }
792 
793 void QgsLayoutMapWidget::viewScaleInCanvas()
794 {
795  if ( !mMapItem )
796  {
797  return;
798  }
799 
800  const double currentScale = mMapItem->scale();
801  mMapCanvas->zoomScale( currentScale, true );
802 }
803 
804 void QgsLayoutMapWidget::mXMinLineEdit_editingFinished()
805 {
806  updateComposerExtentFromGui();
807 }
808 
809 void QgsLayoutMapWidget::mXMaxLineEdit_editingFinished()
810 {
811  updateComposerExtentFromGui();
812 }
813 
814 void QgsLayoutMapWidget::mYMinLineEdit_editingFinished()
815 {
816  updateComposerExtentFromGui();
817 }
818 
819 void QgsLayoutMapWidget::mYMaxLineEdit_editingFinished()
820 {
821  updateComposerExtentFromGui();
822 }
823 
824 void QgsLayoutMapWidget::updateGuiElements()
825 {
826  if ( !mMapItem )
827  {
828  return;
829  }
830 
831  blockAllSignals( true );
832  mLabel->setText( mMapItem->displayName() );
833 
834  whileBlocking( mCrsSelector )->setCrs( mMapItem->presetCrs() );
835 
836  //width, height, scale
837  const double scale = mMapItem->scale();
838 
839  //round scale to an appropriate number of decimal places
840  if ( scale >= 10000 )
841  {
842  //round scale to integer if it's greater than 10000
843  mScaleLineEdit->setText( QLocale().toString( mMapItem->scale(), 'f', 0 ) );
844  }
845  else if ( scale >= 10 )
846  {
847  mScaleLineEdit->setText( QLocale().toString( mMapItem->scale(), 'f', 3 ) );
848  }
849  else if ( scale >= 1 )
850  {
851  //don't round scale if it's less than 10, instead use 4 decimal places
852  mScaleLineEdit->setText( QLocale().toString( mMapItem->scale(), 'f', 4 ) );
853  }
854  else
855  {
856  //if scale < 1 then use 10 decimal places
857  mScaleLineEdit->setText( QLocale().toString( mMapItem->scale(), 'f', 10 ) );
858  }
859 
860  //composer map extent
861  const QgsRectangle composerMapExtent = mMapItem->extent();
862  mXMinLineEdit->setText( QLocale().toString( composerMapExtent.xMinimum(), 'f', 3 ) );
863  mXMaxLineEdit->setText( QLocale().toString( composerMapExtent.xMaximum(), 'f', 3 ) );
864  mYMinLineEdit->setText( QLocale().toString( composerMapExtent.yMinimum(), 'f', 3 ) );
865  mYMaxLineEdit->setText( QLocale().toString( composerMapExtent.yMaximum(), 'f', 3 ) );
866 
867  mMapRotationSpinBox->setValue( mMapItem->mapRotation( QgsLayoutObject::OriginalValue ) );
868 
869  // follow preset checkbox
870  mFollowVisibilityPresetCheckBox->setCheckState(
871  mMapItem->followVisibilityPreset() ? Qt::Checked : Qt::Unchecked );
872  const int presetModelIndex = mFollowVisibilityPresetCombo->findText( mMapItem->followVisibilityPresetName() );
873  mFollowVisibilityPresetCombo->setCurrentIndex( presetModelIndex != -1 ? presetModelIndex : 0 ); // 0 == none
874 
875  //keep layer list checkbox
876  if ( mMapItem->keepLayerSet() )
877  {
878  mKeepLayerListCheckBox->setCheckState( Qt::Checked );
879  }
880  else
881  {
882  mKeepLayerListCheckBox->setCheckState( Qt::Unchecked );
883  }
884 
885  mKeepLayerStylesCheckBox->setEnabled( mMapItem->keepLayerSet() );
886  mKeepLayerStylesCheckBox->setCheckState( mMapItem->keepLayerStyles() ? Qt::Checked : Qt::Unchecked );
887 
888  //draw canvas items
889  if ( mMapItem->drawAnnotations() )
890  {
891  mDrawCanvasItemsCheckBox->setCheckState( Qt::Checked );
892  }
893  else
894  {
895  mDrawCanvasItemsCheckBox->setCheckState( Qt::Unchecked );
896  }
897 
898  //atlas controls
899  mAtlasCheckBox->setChecked( mMapItem->atlasDriven() );
900  mAtlasMarginSpinBox->setValue( static_cast<int>( mMapItem->atlasMargin( QgsLayoutObject::OriginalValue ) * 100 ) );
901 
902  mAtlasFixedScaleRadio->setEnabled( mMapItem->atlasDriven() );
903  mAtlasFixedScaleRadio->setChecked( mMapItem->atlasScalingMode() == QgsLayoutItemMap::Fixed );
904  mAtlasMarginSpinBox->setEnabled( mMapItem->atlasScalingMode() == QgsLayoutItemMap::Auto );
905  mAtlasMarginRadio->setEnabled( mMapItem->atlasDriven() );
906  mAtlasMarginRadio->setChecked( mMapItem->atlasScalingMode() == QgsLayoutItemMap::Auto );
907  mAtlasPredefinedScaleRadio->setEnabled( mMapItem->atlasDriven() );
908  mAtlasPredefinedScaleRadio->setChecked( mMapItem->atlasScalingMode() == QgsLayoutItemMap::Predefined );
909 
910  if ( mMapItem->atlasDriven() )
911  {
912  toggleAtlasScalingOptionsByLayerType();
913  }
914  // disable predefined scales if none are defined
915  if ( !hasPredefinedScales() )
916  {
917  mAtlasPredefinedScaleRadio->setEnabled( false );
918  }
919 
920  mTemporalCheckBox->setChecked( mMapItem->isTemporal() );
921  mTemporalCheckBox->setCollapsed( !mMapItem->isTemporal() );
922  mStartDateTime->setEnabled( mMapItem->isTemporal() );
923  mEndDateTime->setEnabled( mMapItem->isTemporal() );
924  if ( mMapItem->isTemporal() )
925  {
926  mStartDateTime->setDateTime( mMapItem->temporalRange().begin() );
927  mEndDateTime->setDateTime( mMapItem->temporalRange().end() );
928  }
929 
931  loadGridEntries();
932  loadOverviewEntries();
933 
934  blockAllSignals( false );
935 }
936 
937 void QgsLayoutMapWidget::toggleAtlasScalingOptionsByLayerType()
938 {
939  if ( !mMapItem )
940  {
941  return;
942  }
943 
944  //get atlas coverage layer
945  QgsVectorLayer *layer = coverageLayer();
946  if ( !layer )
947  {
948  return;
949  }
950 
952  {
953  //For point layers buffer setting makes no sense, so set "fixed scale" on and disable margin control
954  if ( mMapItem->atlasScalingMode() == QgsLayoutItemMap::Auto )
955  mAtlasFixedScaleRadio->setChecked( true );
956  mAtlasMarginRadio->setEnabled( false );
957  }
958  else
959  {
960  //Not a point layer, so enable changes to fixed scale control
961  mAtlasMarginRadio->setEnabled( true );
962  }
963 }
964 
965 void QgsLayoutMapWidget::updateComposerExtentFromGui()
966 {
967  if ( !mMapItem )
968  {
969  return;
970  }
971 
972  double xmin, ymin, xmax, ymax;
973  bool conversionSuccess;
974 
975  xmin = QLocale().toDouble( mXMinLineEdit->text(), &conversionSuccess );
976  if ( !conversionSuccess )
977  return;
978  xmax = QLocale().toDouble( mXMaxLineEdit->text(), &conversionSuccess );
979  if ( !conversionSuccess )
980  return;
981  ymin = QLocale().toDouble( mYMinLineEdit->text(), &conversionSuccess );
982  if ( !conversionSuccess )
983  return;
984  ymax = QLocale().toDouble( mYMaxLineEdit->text(), &conversionSuccess );
985  if ( !conversionSuccess )
986  return;
987 
988  const QgsRectangle newExtent( xmin, ymin, xmax, ymax );
989 
990  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Map Extent" ) );
991  mMapItem->setExtent( newExtent );
992  mMapItem->layout()->undoStack()->endCommand();
993 }
994 
995 void QgsLayoutMapWidget::blockAllSignals( bool b )
996 {
997  mScaleLineEdit->blockSignals( b );
998  mXMinLineEdit->blockSignals( b );
999  mXMaxLineEdit->blockSignals( b );
1000  mYMinLineEdit->blockSignals( b );
1001  mYMaxLineEdit->blockSignals( b );
1002  mDrawCanvasItemsCheckBox->blockSignals( b );
1003  mOverviewFrameMapComboBox->blockSignals( b );
1004  mOverviewFrameStyleButton->blockSignals( b );
1005  mOverviewBlendModeComboBox->blockSignals( b );
1006  mOverviewInvertCheckbox->blockSignals( b );
1007  mOverviewCenterCheckbox->blockSignals( b );
1008  mAtlasCheckBox->blockSignals( b );
1009  mAtlasMarginSpinBox->blockSignals( b );
1010  mAtlasFixedScaleRadio->blockSignals( b );
1011  mAtlasMarginRadio->blockSignals( b );
1012  mFollowVisibilityPresetCheckBox->blockSignals( b );
1013  mFollowVisibilityPresetCombo->blockSignals( b );
1014  mKeepLayerListCheckBox->blockSignals( b );
1015  mKeepLayerStylesCheckBox->blockSignals( b );
1016  mActionSetToCanvasExtent->blockSignals( b );
1017  mActionUpdatePreview->blockSignals( b );
1018  mTemporalCheckBox->blockSignals( b );
1019  mStartDateTime->blockSignals( b );
1020  mEndDateTime->blockSignals( b );
1021 
1022  blockOverviewItemsSignals( b );
1023 }
1024 
1025 void QgsLayoutMapWidget::updatePreview()
1026 {
1027  if ( !mMapItem )
1028  {
1029  return;
1030  }
1031  mMapItem->refresh();
1032 }
1033 
1034 void QgsLayoutMapWidget::mFollowVisibilityPresetCheckBox_stateChanged( int state )
1035 {
1036  if ( !mMapItem )
1037  {
1038  return;
1039  }
1040 
1041  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Map Preset" ) );
1042  if ( state == Qt::Checked )
1043  {
1044  mMapItem->setFollowVisibilityPreset( true );
1045 
1046  // mutually exclusive with keeping custom layer list
1047  mKeepLayerListCheckBox->setCheckState( Qt::Unchecked );
1048  mKeepLayerStylesCheckBox->setCheckState( Qt::Unchecked );
1049 
1050  mMapItem->invalidateCache();
1051  }
1052  else
1053  {
1054  mMapItem->setFollowVisibilityPreset( false );
1055  }
1056  mMapItem->layout()->undoStack()->endCommand();
1057 }
1058 
1059 void QgsLayoutMapWidget::mKeepLayerListCheckBox_stateChanged( int state )
1060 {
1061  if ( !mMapItem )
1062  {
1063  return;
1064  }
1065 
1066  // update map
1067  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Map Preset Changed" ) );
1068  storeCurrentLayerSet();
1069  mMapItem->setKeepLayerSet( state == Qt::Checked );
1070  if ( state == Qt::Unchecked )
1071  {
1072  mMapItem->setLayers( QList< QgsMapLayer * >() );
1073  }
1074  mMapItem->layout()->undoStack()->endCommand();
1075 
1076  // update gui
1077  if ( state == Qt::Checked )
1078  {
1079  // mutually exclusive with following a preset
1080  mFollowVisibilityPresetCheckBox->setCheckState( Qt::Unchecked );
1081  }
1082  else
1083  {
1084  mKeepLayerStylesCheckBox->setChecked( Qt::Unchecked );
1085  mMapItem->invalidateCache();
1086  }
1087 
1088  mKeepLayerStylesCheckBox->setEnabled( state == Qt::Checked );
1089 }
1090 
1091 void QgsLayoutMapWidget::mKeepLayerStylesCheckBox_stateChanged( int state )
1092 {
1093  if ( !mMapItem )
1094  {
1095  return;
1096  }
1097 
1098  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Map Preset" ) );
1099  if ( state == Qt::Checked )
1100  {
1101  mMapItem->storeCurrentLayerStyles();
1102  mMapItem->setKeepLayerStyles( true );
1103  }
1104  else
1105  {
1106  mMapItem->setLayerStyleOverrides( QMap<QString, QString>() );
1107  mMapItem->setKeepLayerStyles( false );
1108  }
1109  mMapItem->layout()->undoStack()->endCommand();
1110 }
1111 
1112 void QgsLayoutMapWidget::mDrawCanvasItemsCheckBox_stateChanged( int state )
1113 {
1114  if ( !mMapItem )
1115  {
1116  return;
1117  }
1118 
1119  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Toggle Map Item" ) );
1120  mMapItem->setDrawAnnotations( state == Qt::Checked );
1121  mMapItem->invalidateCache();
1122  mMapItem->layout()->undoStack()->endCommand();
1123 }
1124 
1125 void QgsLayoutMapWidget::atlasLayerChanged( QgsVectorLayer *layer )
1126 {
1127  if ( !layer || layer->wkbType() == QgsWkbTypes::NoGeometry )
1128  {
1129  //geometryless layer, disable atlas control
1130  mAtlasCheckBox->setChecked( false );
1131  mAtlasCheckBox->setEnabled( false );
1132  return;
1133  }
1134  else
1135  {
1136  mAtlasCheckBox->setEnabled( true );
1137  }
1138 
1139  // enable or disable fixed scale control based on layer type
1140  if ( mAtlasCheckBox->isChecked() )
1141  toggleAtlasScalingOptionsByLayerType();
1142 }
1143 
1144 bool QgsLayoutMapWidget::hasPredefinedScales() const
1145 {
1146  // first look at project's scales
1147  const QVector< double > scales( QgsProject::instance()->viewSettings()->mapScales() );
1148  const bool hasProjectScales( QgsProject::instance()->viewSettings()->useProjectScales() );
1149  if ( !hasProjectScales || scales.isEmpty() )
1150  {
1151  // default to global map tool scales
1152  const QgsSettings settings;
1153  const QString scalesStr( settings.value( QStringLiteral( "Map/scales" ), Qgis::defaultProjectScales() ).toString() );
1154  QStringList myScalesList = scalesStr.split( ',' );
1155  return !myScalesList.isEmpty() && !myScalesList[0].isEmpty();
1156  }
1157  return true;
1158 }
1159 
1160 void QgsLayoutMapWidget::mAddGridPushButton_clicked()
1161 {
1162  if ( !mMapItem )
1163  {
1164  return;
1165  }
1166 
1167  const QString itemName = tr( "Grid %1" ).arg( mMapItem->grids()->size() + 1 );
1168  QgsLayoutItemMapGrid *grid = new QgsLayoutItemMapGrid( itemName, mMapItem );
1169  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Add Map Grid" ) );
1170  mMapItem->grids()->addGrid( grid );
1171  mMapItem->layout()->undoStack()->endCommand();
1172  mMapItem->updateBoundingRect();
1173  mMapItem->update();
1174 
1175  addGridListItem( grid->id(), grid->name() );
1176  mGridListWidget->setCurrentRow( 0 );
1177  mGridListWidget_currentItemChanged( mGridListWidget->currentItem(), nullptr );
1178 }
1179 
1180 void QgsLayoutMapWidget::mRemoveGridPushButton_clicked()
1181 {
1182  QListWidgetItem *item = mGridListWidget->currentItem();
1183  if ( !item )
1184  {
1185  return;
1186  }
1187 
1188  mMapItem->beginCommand( tr( "Remove Grid" ) );
1189  mMapItem->grids()->removeGrid( item->data( Qt::UserRole ).toString() );
1190  QListWidgetItem *delItem = mGridListWidget->takeItem( mGridListWidget->row( item ) );
1191  delete delItem;
1192  mMapItem->endCommand();
1193  mMapItem->updateBoundingRect();
1194  mMapItem->update();
1195 }
1196 
1197 void QgsLayoutMapWidget::mGridUpButton_clicked()
1198 {
1199  QListWidgetItem *item = mGridListWidget->currentItem();
1200  if ( !item )
1201  {
1202  return;
1203  }
1204 
1205  const int row = mGridListWidget->row( item );
1206  if ( row < 1 )
1207  {
1208  return;
1209  }
1210  mGridListWidget->takeItem( row );
1211  mGridListWidget->insertItem( row - 1, item );
1212  mGridListWidget->setCurrentItem( item );
1213  mMapItem->beginCommand( tr( "Move Grid Up" ) );
1214  mMapItem->grids()->moveGridUp( item->data( Qt::UserRole ).toString() );
1215  mMapItem->endCommand();
1216  mMapItem->update();
1217 }
1218 
1219 void QgsLayoutMapWidget::mGridDownButton_clicked()
1220 {
1221  QListWidgetItem *item = mGridListWidget->currentItem();
1222  if ( !item )
1223  {
1224  return;
1225  }
1226 
1227  const int row = mGridListWidget->row( item );
1228  if ( mGridListWidget->count() <= row )
1229  {
1230  return;
1231  }
1232  mGridListWidget->takeItem( row );
1233  mGridListWidget->insertItem( row + 1, item );
1234  mGridListWidget->setCurrentItem( item );
1235  mMapItem->beginCommand( tr( "Move Grid Down" ) );
1236  mMapItem->grids()->moveGridDown( item->data( Qt::UserRole ).toString() );
1237  mMapItem->endCommand();
1238  mMapItem->update();
1239 }
1240 
1241 QgsLayoutItemMapGrid *QgsLayoutMapWidget::currentGrid()
1242 {
1243  if ( !mMapItem )
1244  {
1245  return nullptr;
1246  }
1247 
1248  QListWidgetItem *item = mGridListWidget->currentItem();
1249  if ( !item )
1250  {
1251  return nullptr;
1252  }
1253  return mMapItem->grids()->grid( item->data( Qt::UserRole ).toString() );
1254 }
1255 
1256 void QgsLayoutMapWidget::mGridListWidget_currentItemChanged( QListWidgetItem *current, QListWidgetItem * )
1257 {
1258  mGridPropertiesButton->setEnabled( static_cast< bool >( current ) );
1259 }
1260 
1261 void QgsLayoutMapWidget::mGridListWidget_itemChanged( QListWidgetItem *item )
1262 {
1263  if ( !mMapItem )
1264  {
1265  return;
1266  }
1267 
1268  QgsLayoutItemMapGrid *grid = mMapItem->grids()->grid( item->data( Qt::UserRole ).toString() );
1269  if ( !grid )
1270  {
1271  return;
1272  }
1273 
1274  mMapItem->beginCommand( tr( "Rename Grid" ) );
1275  grid->setName( item->text() );
1276  mMapItem->endCommand();
1277 }
1278 
1279 void QgsLayoutMapWidget::mGridPropertiesButton_clicked()
1280 {
1281  if ( !mMapItem )
1282  {
1283  return;
1284  }
1285  QgsLayoutItemMapGrid *grid = currentGrid();
1286  if ( !grid )
1287  {
1288  return;
1289  }
1290 
1291  QgsLayoutMapGridWidget *w = new QgsLayoutMapGridWidget( grid, mMapItem );
1292  w->setDesignerInterface( mInterface );
1293  openPanel( w );
1294 }
1295 
1296 QListWidgetItem *QgsLayoutMapWidget::addGridListItem( const QString &id, const QString &name )
1297 {
1298  QListWidgetItem *item = new QListWidgetItem( name, nullptr );
1299  item->setData( Qt::UserRole, id );
1300  item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable );
1301  mGridListWidget->insertItem( 0, item );
1302  return item;
1303 }
1304 
1305 void QgsLayoutMapWidget::loadGridEntries()
1306 {
1307  //save selection
1308  QSet<QString> selectedIds;
1309  const QList<QListWidgetItem *> itemSelection = mGridListWidget->selectedItems();
1310  QList<QListWidgetItem *>::const_iterator sIt = itemSelection.constBegin();
1311  for ( ; sIt != itemSelection.constEnd(); ++sIt )
1312  {
1313  selectedIds.insert( ( *sIt )->data( Qt::UserRole ).toString() );
1314  }
1315 
1316  mGridListWidget->clear();
1317  if ( !mMapItem )
1318  {
1319  return;
1320  }
1321  //load all composer grids into list widget
1322  const QList< QgsLayoutItemMapGrid * > grids = mMapItem->grids()->asList();
1323  QList< QgsLayoutItemMapGrid * >::const_iterator gridIt = grids.constBegin();
1324  for ( ; gridIt != grids.constEnd(); ++gridIt )
1325  {
1326  QListWidgetItem *item = addGridListItem( ( *gridIt )->id(), ( *gridIt )->name() );
1327  if ( selectedIds.contains( ( *gridIt )->id() ) )
1328  {
1329  item->setSelected( true );
1330  mGridListWidget->setCurrentItem( item );
1331  }
1332  }
1333 
1334  if ( mGridListWidget->currentItem() )
1335  {
1336  mGridListWidget_currentItemChanged( mGridListWidget->currentItem(), nullptr );
1337  }
1338  else
1339  {
1340  mGridListWidget_currentItemChanged( nullptr, nullptr );
1341  }
1342 }
1343 
1344 void QgsLayoutMapWidget::mAddOverviewPushButton_clicked()
1345 {
1346  if ( !mMapItem )
1347  {
1348  return;
1349  }
1350 
1351  const QString itemName = tr( "Overview %1" ).arg( mMapItem->overviews()->size() + 1 );
1352  QgsLayoutItemMapOverview *overview = new QgsLayoutItemMapOverview( itemName, mMapItem );
1353  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Add Map Overview" ) );
1354  mMapItem->overviews()->addOverview( overview );
1355  mMapItem->layout()->undoStack()->endCommand();
1356  mMapItem->invalidateCache();
1357 
1358  addOverviewListItem( overview->id(), overview->name() );
1359 
1360  mOverviewListWidget->setCurrentRow( 0 );
1361 }
1362 
1363 void QgsLayoutMapWidget::mRemoveOverviewPushButton_clicked()
1364 {
1365  QListWidgetItem *item = mOverviewListWidget->currentItem();
1366  if ( !item )
1367  {
1368  return;
1369  }
1370  mMapItem->beginCommand( tr( "Remove Map Overview" ) );
1371  mMapItem->overviews()->removeOverview( item->data( Qt::UserRole ).toString() );
1372  mMapItem->endCommand();
1373  QListWidgetItem *delItem = mOverviewListWidget->takeItem( mOverviewListWidget->row( item ) );
1374  delete delItem;
1375  mMapItem->invalidateCache();
1376 }
1377 
1378 void QgsLayoutMapWidget::mOverviewUpButton_clicked()
1379 {
1380  QListWidgetItem *item = mOverviewListWidget->currentItem();
1381  if ( !item )
1382  {
1383  return;
1384  }
1385 
1386  const int row = mOverviewListWidget->row( item );
1387  if ( row < 1 )
1388  {
1389  return;
1390  }
1391  mOverviewListWidget->takeItem( row );
1392  mOverviewListWidget->insertItem( row - 1, item );
1393  mOverviewListWidget->setCurrentItem( item );
1394  mMapItem->beginCommand( tr( "Move Overview Up" ) );
1395  mMapItem->overviews()->moveOverviewUp( item->data( Qt::UserRole ).toString() );
1396  mMapItem->endCommand();
1397  mMapItem->invalidateCache();
1398 }
1399 
1400 void QgsLayoutMapWidget::mOverviewDownButton_clicked()
1401 {
1402  QListWidgetItem *item = mOverviewListWidget->currentItem();
1403  if ( !item )
1404  {
1405  return;
1406  }
1407 
1408  const int row = mOverviewListWidget->row( item );
1409  if ( mOverviewListWidget->count() <= row )
1410  {
1411  return;
1412  }
1413  mOverviewListWidget->takeItem( row );
1414  mOverviewListWidget->insertItem( row + 1, item );
1415  mOverviewListWidget->setCurrentItem( item );
1416  mMapItem->beginCommand( tr( "Move Overview Down" ) );
1417  mMapItem->overviews()->moveOverviewDown( item->data( Qt::UserRole ).toString() );
1418  mMapItem->endCommand();
1419  mMapItem->invalidateCache();
1420 }
1421 
1422 QgsLayoutItemMapOverview *QgsLayoutMapWidget::currentOverview()
1423 {
1424  if ( !mMapItem )
1425  {
1426  return nullptr;
1427  }
1428 
1429  QListWidgetItem *item = mOverviewListWidget->currentItem();
1430  if ( !item )
1431  {
1432  return nullptr;
1433  }
1434 
1435  return mMapItem->overviews()->overview( item->data( Qt::UserRole ).toString() );
1436 }
1437 
1438 void QgsLayoutMapWidget::mOverviewListWidget_currentItemChanged( QListWidgetItem *current, QListWidgetItem *previous )
1439 {
1440  Q_UNUSED( previous )
1441  if ( !current )
1442  {
1443  mOverviewCheckBox->setEnabled( false );
1444  return;
1445  }
1446 
1447  mOverviewCheckBox->setEnabled( true );
1448  setOverviewItems( mMapItem->overviews()->overview( current->data( Qt::UserRole ).toString() ) );
1449 }
1450 
1451 void QgsLayoutMapWidget::mOverviewListWidget_itemChanged( QListWidgetItem *item )
1452 {
1453  if ( !mMapItem )
1454  {
1455  return;
1456  }
1457 
1458  QgsLayoutItemMapOverview *overview = mMapItem->overviews()->overview( item->data( Qt::UserRole ).toString() );
1459  if ( !overview )
1460  {
1461  return;
1462  }
1463 
1464  mMapItem->beginCommand( QStringLiteral( "Rename Overview" ) );
1465  overview->setName( item->text() );
1466  mMapItem->endCommand();
1467  if ( item->isSelected() )
1468  {
1469  //update checkbox title if item is current item
1470  mOverviewCheckBox->setTitle( tr( "Draw \"%1\" overview" ).arg( overview->name() ) );
1471  }
1472 }
1473 
1474 void QgsLayoutMapWidget::setOverviewItemsEnabled( bool enabled )
1475 {
1476  mOverviewFrameMapLabel->setEnabled( enabled );
1477  mOverviewFrameMapComboBox->setEnabled( enabled );
1478  mOverviewFrameStyleLabel->setEnabled( enabled );
1479  mOverviewFrameStyleButton->setEnabled( enabled );
1480  mOverviewBlendModeLabel->setEnabled( enabled );
1481  mOverviewBlendModeComboBox->setEnabled( enabled );
1482  mOverviewInvertCheckbox->setEnabled( enabled );
1483  mOverviewCenterCheckbox->setEnabled( enabled );
1484  mOverviewPositionComboBox->setEnabled( enabled );
1485 
1486  const QgsLayoutItemMapItem::StackingPosition currentStackingPos = static_cast< QgsLayoutItemMapItem::StackingPosition >( mOverviewPositionComboBox->currentData().toInt() );
1487  mOverviewStackingLayerComboBox->setEnabled( enabled && ( currentStackingPos == QgsLayoutItemMapItem::StackAboveMapLayer || currentStackingPos == QgsLayoutItemMapItem::StackBelowMapLayer ) );
1488 }
1489 
1490 void QgsLayoutMapWidget::blockOverviewItemsSignals( const bool block )
1491 {
1492  mOverviewFrameMapComboBox->blockSignals( block );
1493  mOverviewFrameStyleButton->blockSignals( block );
1494  mOverviewBlendModeComboBox->blockSignals( block );
1495  mOverviewInvertCheckbox->blockSignals( block );
1496  mOverviewCenterCheckbox->blockSignals( block );
1497  mOverviewPositionComboBox->blockSignals( block );
1498  mOverviewStackingLayerComboBox->blockSignals( block );
1499 }
1500 
1501 void QgsLayoutMapWidget::setOverviewItems( QgsLayoutItemMapOverview *overview )
1502 {
1503  if ( !overview )
1504  {
1505  return;
1506  }
1507 
1508  blockOverviewItemsSignals( true );
1509 
1510  mOverviewCheckBox->setTitle( tr( "Draw \"%1\" overview" ).arg( overview->name() ) );
1511  mOverviewCheckBox->setChecked( overview->enabled() );
1512 
1513  //overview frame
1514  mOverviewFrameMapComboBox->setItem( overview->linkedMap() );
1515 
1516  //overview frame blending mode
1517  mOverviewBlendModeComboBox->setBlendMode( overview->blendMode() );
1518  //overview inverted
1519  mOverviewInvertCheckbox->setChecked( overview->inverted() );
1520  //center overview
1521  mOverviewCenterCheckbox->setChecked( overview->centered() );
1522 
1523  mOverviewPositionComboBox->setCurrentIndex( mOverviewPositionComboBox->findData( overview->stackingPosition() ) );
1524  mOverviewStackingLayerComboBox->setLayer( overview->stackingLayer() );
1525  mOverviewStackingLayerComboBox->setEnabled( mOverviewPositionComboBox->isEnabled() && ( overview->stackingPosition() == QgsLayoutItemMapItem::StackAboveMapLayer
1527 
1528  mOverviewFrameStyleButton->setSymbol( overview->frameSymbol()->clone() );
1529 
1530  blockOverviewItemsSignals( false );
1531 }
1532 
1533 void QgsLayoutMapWidget::storeCurrentLayerSet()
1534 {
1535  if ( !mMapItem )
1536  return;
1537 
1538  const QList<QgsMapLayer *> layers = mMapCanvas->mapSettings().layers();
1539  mMapItem->setLayers( layers );
1540 
1541  if ( mMapItem->keepLayerStyles() )
1542  {
1543  // also store styles associated with the layers
1544  mMapItem->storeCurrentLayerStyles();
1545  }
1546 }
1547 
1548 QList<QgsMapLayer *> QgsLayoutMapWidget::orderedPresetVisibleLayers( const QString &name ) const
1549 {
1550  const QStringList visibleIds = QgsProject::instance()->mapThemeCollection()->mapThemeVisibleLayerIds( name );
1551 
1552  // also make sure to order the layers according to map canvas order
1553  QList<QgsMapLayer *> lst;
1554  const auto constLayerOrder = QgsProject::instance()->layerTreeRoot()->layerOrder();
1555  for ( QgsMapLayer *layer : constLayerOrder )
1556  {
1557  if ( visibleIds.contains( layer->id() ) )
1558  {
1559  lst << layer;
1560  }
1561  }
1562  return lst;
1563 }
1564 
1565 QListWidgetItem *QgsLayoutMapWidget::addOverviewListItem( const QString &id, const QString &name )
1566 {
1567  QListWidgetItem *item = new QListWidgetItem( name, nullptr );
1568  item->setData( Qt::UserRole, id );
1569  item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable );
1570  mOverviewListWidget->insertItem( 0, item );
1571  return item;
1572 }
1573 
1574 void QgsLayoutMapWidget::loadOverviewEntries()
1575 {
1576  //save selection
1577  QSet<QString> selectedIds;
1578  const QList<QListWidgetItem *> itemSelection = mOverviewListWidget->selectedItems();
1579  QList<QListWidgetItem *>::const_iterator sIt = itemSelection.constBegin();
1580  for ( ; sIt != itemSelection.constEnd(); ++sIt )
1581  {
1582  selectedIds.insert( ( *sIt )->data( Qt::UserRole ).toString() );
1583  }
1584 
1585  mOverviewListWidget->clear();
1586  if ( !mMapItem )
1587  {
1588  return;
1589  }
1590 
1591  mOverviewFrameMapComboBox->setExceptedItemList( QList< QgsLayoutItem * >() << mMapItem );
1592 
1593  //load all composer overviews into list widget
1594  const QList< QgsLayoutItemMapOverview * > overviews = mMapItem->overviews()->asList();
1595  QList< QgsLayoutItemMapOverview * >::const_iterator overviewIt = overviews.constBegin();
1596  for ( ; overviewIt != overviews.constEnd(); ++overviewIt )
1597  {
1598  QListWidgetItem *item = addOverviewListItem( ( *overviewIt )->id(), ( *overviewIt )->name() );
1599  if ( selectedIds.contains( ( *overviewIt )->id() ) )
1600  {
1601  item->setSelected( true );
1602  mOverviewListWidget->setCurrentItem( item );
1603  }
1604  }
1605 
1606  if ( mOverviewListWidget->currentItem() )
1607  {
1608  mOverviewListWidget_currentItemChanged( mOverviewListWidget->currentItem(), nullptr );
1609  }
1610  else
1611  {
1612  mOverviewListWidget_currentItemChanged( nullptr, nullptr );
1613  }
1614 }
1615 
1616 void QgsLayoutMapWidget::mOverviewCheckBox_toggled( bool state )
1617 {
1618  QgsLayoutItemMapOverview *overview = currentOverview();
1619  if ( !overview )
1620  {
1621  return;
1622  }
1623 
1624  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Overview Display Toggled" ) );
1625  overview->setEnabled( state );
1626  mMapItem->invalidateCache();
1627  mMapItem->layout()->undoStack()->endCommand();
1628 }
1629 
1630 void QgsLayoutMapWidget::overviewMapChanged( QgsLayoutItem *item )
1631 {
1632  QgsLayoutItemMapOverview *overview = currentOverview();
1633  if ( !overview )
1634  {
1635  return;
1636  }
1637 
1638  QgsLayoutItemMap *map = dynamic_cast< QgsLayoutItemMap * >( item );
1639  if ( !map )
1640  return;
1641 
1642  mMapItem->beginCommand( tr( "Change Overview Map" ) );
1643  overview->setLinkedMap( map );
1644  mMapItem->invalidateCache();
1645  mMapItem->endCommand();
1646 }
1647 
1648 void QgsLayoutMapWidget::mOverviewBlendModeComboBox_currentIndexChanged( int index )
1649 {
1650  Q_UNUSED( index )
1651  QgsLayoutItemMapOverview *overview = currentOverview();
1652  if ( !overview )
1653  {
1654  return;
1655  }
1656 
1657  mMapItem->beginCommand( tr( "Change Overview Blend Mode" ) );
1658  overview->setBlendMode( mOverviewBlendModeComboBox->blendMode() );
1659  mMapItem->invalidateCache();
1660  mMapItem->endCommand();
1661 }
1662 
1663 void QgsLayoutMapWidget::mOverviewInvertCheckbox_toggled( bool state )
1664 {
1665  QgsLayoutItemMapOverview *overview = currentOverview();
1666  if ( !overview )
1667  {
1668  return;
1669  }
1670 
1671  mMapItem->beginCommand( tr( "Toggle Overview Inverted" ) );
1672  overview->setInverted( state );
1673  mMapItem->invalidateCache();
1674  mMapItem->endCommand();
1675 }
1676 
1677 void QgsLayoutMapWidget::mOverviewCenterCheckbox_toggled( bool state )
1678 {
1679  QgsLayoutItemMapOverview *overview = currentOverview();
1680  if ( !overview )
1681  {
1682  return;
1683  }
1684 
1685  mMapItem->beginCommand( tr( "Toggle Overview Centered" ) );
1686  overview->setCentered( state );
1687  mMapItem->invalidateCache();
1688  mMapItem->endCommand();
1689 }
1690 
1691 void QgsLayoutMapWidget::overviewStackingChanged( int )
1692 {
1693  QgsLayoutItemMapOverview *overview = currentOverview();
1694  if ( !overview )
1695  {
1696  return;
1697  }
1698 
1699  mMapItem->beginCommand( tr( "Change Overview Position" ) );
1700  overview->setStackingPosition( static_cast< QgsLayoutItemMapItem::StackingPosition >( mOverviewPositionComboBox->currentData().toInt() ) );
1701  mMapItem->invalidateCache();
1702  mMapItem->endCommand();
1703 
1704  switch ( overview->stackingPosition() )
1705  {
1709  mOverviewStackingLayerComboBox->setEnabled( false );
1710  break;
1711 
1714  mOverviewStackingLayerComboBox->setEnabled( true );
1715  break;
1716  }
1717 }
1718 
1719 void QgsLayoutMapWidget::overviewStackingLayerChanged( QgsMapLayer *layer )
1720 {
1721  QgsLayoutItemMapOverview *overview = currentOverview();
1722  if ( !overview )
1723  {
1724  return;
1725  }
1726 
1727  mMapItem->beginCommand( tr( "Change Overview Position" ) );
1728  overview->setStackingLayer( layer );
1729  mMapItem->invalidateCache();
1730  mMapItem->endCommand();
1731 }
1732 
1733 //
1734 // QgsLayoutMapLabelingWidget
1735 //
1736 
1738  : QgsLayoutItemBaseWidget( nullptr, map )
1739  , mMapItem( map )
1740 {
1741  setupUi( this );
1742  setPanelTitle( tr( "Label Settings" ) );
1743 
1744  mLabelBoundarySpinBox->setClearValue( 0 );
1745  mLabelBoundarySpinBox->setShowClearButton( true );
1746 
1747  mLabelBoundaryUnitsCombo->linkToWidget( mLabelBoundarySpinBox );
1748  mLabelBoundaryUnitsCombo->setConverter( &mMapItem->layout()->renderContext().measurementConverter() );
1749 
1750  connect( mLabelBoundaryUnitsCombo, &QgsLayoutUnitsComboBox::changed, this, &QgsLayoutMapLabelingWidget::labelMarginUnitsChanged );
1751  connect( mLabelBoundarySpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutMapLabelingWidget::labelMarginChanged );
1752  connect( mShowPartialLabelsCheckBox, &QCheckBox::toggled, this, &QgsLayoutMapLabelingWidget::showPartialsToggled );
1753  connect( mShowUnplacedCheckBox, &QCheckBox::toggled, this, &QgsLayoutMapLabelingWidget::showUnplacedToggled );
1754 
1756 
1757  setNewItem( map );
1758 }
1759 
1761 {
1762  if ( item->type() != QgsLayoutItemRegistry::LayoutMap )
1763  return false;
1764 
1765  if ( mMapItem )
1766  {
1767  disconnect( mMapItem, &QgsLayoutObject::changed, this, &QgsLayoutMapLabelingWidget::updateGuiElements );
1768  }
1769 
1770  mMapItem = qobject_cast< QgsLayoutItemMap * >( item );
1771 
1772  if ( mMapItem )
1773  {
1774  connect( mMapItem, &QgsLayoutObject::changed, this, &QgsLayoutMapLabelingWidget::updateGuiElements );
1775  }
1776 
1777  updateGuiElements();
1778 
1779  return true;
1780 }
1781 
1782 void QgsLayoutMapLabelingWidget::updateGuiElements()
1783 {
1784  whileBlocking( mLabelBoundarySpinBox )->setValue( mMapItem->labelMargin().length() );
1785  whileBlocking( mLabelBoundaryUnitsCombo )->setUnit( mMapItem->labelMargin().units() );
1786  whileBlocking( mShowPartialLabelsCheckBox )->setChecked( mMapItem->mapFlags() & QgsLayoutItemMap::ShowPartialLabels );
1787  whileBlocking( mShowUnplacedCheckBox )->setChecked( mMapItem->mapFlags() & QgsLayoutItemMap::ShowUnplacedLabels );
1788 
1789  if ( mBlockingItemsListView->model() )
1790  {
1791  QAbstractItemModel *oldModel = mBlockingItemsListView->model();
1792  mBlockingItemsListView->setModel( nullptr );
1793  oldModel->deleteLater();
1794  }
1795 
1796  QgsLayoutMapItemBlocksLabelsModel *model = new QgsLayoutMapItemBlocksLabelsModel( mMapItem, mMapItem->layout()->itemsModel(), mBlockingItemsListView );
1797  mBlockingItemsListView->setModel( model );
1798 
1799  updateDataDefinedButton( mLabelMarginDDBtn );
1800 }
1801 
1802 void QgsLayoutMapLabelingWidget::labelMarginChanged( double val )
1803 {
1804  if ( !mMapItem )
1805  return;
1806 
1807  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Label Margin" ), QgsLayoutItem::UndoMapLabelMargin );
1808  mMapItem->setLabelMargin( QgsLayoutMeasurement( val, mLabelBoundaryUnitsCombo->unit() ) );
1809  mMapItem->layout()->undoStack()->endCommand();
1810  mMapItem->invalidateCache();
1811 }
1812 
1813 void QgsLayoutMapLabelingWidget::labelMarginUnitsChanged()
1814 {
1815  if ( !mMapItem )
1816  return;
1817 
1818  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Label Margin" ), QgsLayoutItem::UndoMapLabelMargin );
1819  mMapItem->setLabelMargin( QgsLayoutMeasurement( mLabelBoundarySpinBox->value(), mLabelBoundaryUnitsCombo->unit() ) );
1820  mMapItem->layout()->undoStack()->endCommand();
1821  mMapItem->invalidateCache();
1822 }
1823 
1824 void QgsLayoutMapLabelingWidget::showPartialsToggled( bool checked )
1825 {
1826  if ( !mMapItem )
1827  return;
1828 
1829  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Label Visibility" ) );
1830  QgsLayoutItemMap::MapItemFlags flags = mMapItem->mapFlags();
1831  if ( checked )
1833  else
1834  flags &= ~QgsLayoutItemMap::ShowPartialLabels;
1835  mMapItem->setMapFlags( flags );
1836  mMapItem->layout()->undoStack()->endCommand();
1837  mMapItem->invalidateCache();
1838 }
1839 
1840 void QgsLayoutMapLabelingWidget::showUnplacedToggled( bool checked )
1841 {
1842  if ( !mMapItem )
1843  return;
1844 
1845  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Label Visibility" ) );
1846  QgsLayoutItemMap::MapItemFlags flags = mMapItem->mapFlags();
1847  if ( checked )
1849  else
1850  flags &= ~QgsLayoutItemMap::ShowUnplacedLabels;
1851  mMapItem->setMapFlags( flags );
1852  mMapItem->layout()->undoStack()->endCommand();
1853  mMapItem->invalidateCache();
1854 }
1855 
1857  : QSortFilterProxyModel( parent )
1858  , mLayoutModel( layoutModel )
1859  , mMapItem( map )
1860 {
1861  setSourceModel( layoutModel );
1862 }
1863 
1864 int QgsLayoutMapItemBlocksLabelsModel::columnCount( const QModelIndex & ) const
1865 {
1866  return 1;
1867 }
1868 
1869 QVariant QgsLayoutMapItemBlocksLabelsModel::data( const QModelIndex &i, int role ) const
1870 {
1871  if ( !i.isValid() )
1872  return QVariant();
1873 
1874  if ( i.column() != 0 )
1875  return QVariant();
1876 
1877  const QModelIndex sourceIndex = mapToSource( index( i.row(), QgsLayoutModel::ItemId, i.parent() ) );
1878 
1879  QgsLayoutItem *item = mLayoutModel->itemFromIndex( mapToSource( i ) );
1880  if ( !item )
1881  {
1882  return QVariant();
1883  }
1884 
1885  switch ( role )
1886  {
1887  case Qt::CheckStateRole:
1888  switch ( i.column() )
1889  {
1890  case 0:
1891  return mMapItem ? ( mMapItem->isLabelBlockingItem( item ) ? Qt::Checked : Qt::Unchecked ) : Qt::Unchecked;
1892  default:
1893  return QVariant();
1894  }
1895 
1896  default:
1897  return mLayoutModel->data( sourceIndex, role );
1898  }
1899 }
1900 
1901 bool QgsLayoutMapItemBlocksLabelsModel::setData( const QModelIndex &index, const QVariant &value, int role )
1902 {
1903  Q_UNUSED( role )
1904 
1905  if ( !index.isValid() )
1906  return false;
1907 
1908  QgsLayoutItem *item = mLayoutModel->itemFromIndex( mapToSource( index ) );
1909  if ( !item || !mMapItem )
1910  {
1911  return false;
1912  }
1913 
1914  mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Label Blocking Items" ) );
1915 
1916  if ( value.toBool() )
1917  {
1918  mMapItem->addLabelBlockingItem( item );
1919  }
1920  else
1921  {
1922  mMapItem->removeLabelBlockingItem( item );
1923  }
1924  emit dataChanged( index, index, QVector<int>() << role );
1925 
1926  mMapItem->layout()->undoStack()->endCommand();
1927  mMapItem->invalidateCache();
1928 
1929  return true;
1930 }
1931 
1932 Qt::ItemFlags QgsLayoutMapItemBlocksLabelsModel::flags( const QModelIndex &index ) const
1933 {
1934  Qt::ItemFlags flags = QAbstractItemModel::flags( index );
1935 
1936  if ( ! index.isValid() )
1937  {
1938  return flags ;
1939  }
1940 
1941  switch ( index.column() )
1942  {
1943  case 0:
1944  return flags | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
1945  default:
1946  return flags | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
1947  }
1948 }
1949 
1950 bool QgsLayoutMapItemBlocksLabelsModel::filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const
1951 {
1952  QgsLayoutItem *item = mLayoutModel->itemFromIndex( mLayoutModel->index( source_row, 0, source_parent ) );
1953  if ( !item || item == mMapItem )
1954  {
1955  return false;
1956  }
1957 
1958  return true;
1959 }
1960 
1961 
1962 
1963 //
1964 // QgsLayoutMapClippingWidget
1965 //
1966 
1968  : QgsLayoutItemBaseWidget( nullptr, map )
1969  , mMapItem( map )
1970 {
1971  setupUi( this );
1972  setPanelTitle( tr( "Clipping Settings" ) );
1973 
1974  mLayerModel = new QgsMapLayerModel( this );
1975  mLayerModel->setItemsCheckable( true );
1976  mLayersTreeView->setModel( mLayerModel );
1977 
1978  mAtlasClippingTypeComboBox->addItem( tr( "Clip During Render Only" ), static_cast< int >( QgsMapClippingRegion::FeatureClippingType::ClipPainterOnly ) );
1979  mAtlasClippingTypeComboBox->addItem( tr( "Clip Feature Before Render" ), static_cast< int >( QgsMapClippingRegion::FeatureClippingType::ClipToIntersection ) );
1980  mAtlasClippingTypeComboBox->addItem( tr( "Render Intersecting Features Unchanged" ), static_cast< int >( QgsMapClippingRegion::FeatureClippingType::NoClipping ) );
1981 
1982  for ( int i = 0; i < mAtlasClippingTypeComboBox->count(); ++i )
1983  {
1984  mItemClippingTypeComboBox->addItem( mAtlasClippingTypeComboBox->itemText( i ), mAtlasClippingTypeComboBox->itemData( i ) );
1985  }
1986 
1987  mClipItemComboBox->setCurrentLayout( map->layout() );
1988  mClipItemComboBox->setItemFlags( QgsLayoutItem::FlagProvidesClipPath );
1989 
1990  connect( mRadioClipSelectedLayers, &QRadioButton::toggled, mLayersTreeView, &QWidget::setEnabled );
1991  mLayersTreeView->setEnabled( false );
1992  mRadioClipAllLayers->setChecked( true );
1993 
1994  connect( mClipToAtlasCheckBox, &QGroupBox::toggled, this, [ = ]( bool active )
1995  {
1996  if ( !mBlockUpdates )
1997  {
1998  mMapItem->beginCommand( tr( "Toggle Atlas Clipping" ) );
1999  mMapItem->atlasClippingSettings()->setEnabled( active );
2000  mMapItem->endCommand();
2001  }
2002  } );
2003  connect( mForceLabelsInsideCheckBox, &QCheckBox::toggled, this, [ = ]( bool active )
2004  {
2005  if ( !mBlockUpdates )
2006  {
2007  mMapItem->beginCommand( tr( "Change Atlas Clipping Label Behavior" ) );
2008  mMapItem->atlasClippingSettings()->setForceLabelsInsideFeature( active );
2009  mMapItem->endCommand();
2010  }
2011  } );
2012  connect( mAtlasClippingTypeComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [ = ]
2013  {
2014  if ( !mBlockUpdates )
2015  {
2016  mMapItem->beginCommand( tr( "Change Atlas Clipping Behavior" ) );
2017  mMapItem->atlasClippingSettings()->setFeatureClippingType( static_cast< QgsMapClippingRegion::FeatureClippingType >( mAtlasClippingTypeComboBox->currentData().toInt() ) );
2018  mMapItem->endCommand();
2019  }
2020  } );
2021 
2022  connect( mRadioClipSelectedLayers, &QCheckBox::toggled, this, [ = ]( bool active )
2023  {
2024  if ( active && !mBlockUpdates )
2025  {
2026  mBlockUpdates = true;
2027  mMapItem->beginCommand( tr( "Change Atlas Clipping Layers" ) );
2028  mMapItem->atlasClippingSettings()->setRestrictToLayers( true );
2029  mMapItem->endCommand();
2030  mBlockUpdates = false;
2031  }
2032  } );
2033  connect( mRadioClipAllLayers, &QCheckBox::toggled, this, [ = ]( bool active )
2034  {
2035  if ( active && !mBlockUpdates )
2036  {
2037  mBlockUpdates = true;
2038  mMapItem->beginCommand( tr( "Change Atlas Clipping Layers" ) );
2039  mMapItem->atlasClippingSettings()->setRestrictToLayers( false );
2040  mMapItem->endCommand();
2041  mBlockUpdates = false;
2042  }
2043  } );
2044  connect( mLayerModel, &QgsMapLayerModel::dataChanged, this, [ = ]( const QModelIndex &, const QModelIndex &, const QVector<int> &roles = QVector<int>() )
2045  {
2046  if ( !roles.contains( Qt::CheckStateRole ) )
2047  return;
2048 
2049  if ( !mBlockUpdates )
2050  {
2051  mBlockUpdates = true;
2052  mMapItem->beginCommand( tr( "Change Atlas Clipping Layers" ) );
2053  mMapItem->atlasClippingSettings()->setLayersToClip( mLayerModel->layersChecked() );
2054  mMapItem->endCommand();
2055  mBlockUpdates = false;
2056  }
2057  } );
2058 
2059  // item clipping widgets
2060 
2061  connect( mClipToItemCheckBox, &QGroupBox::toggled, this, [ = ]( bool active )
2062  {
2063  if ( !mBlockUpdates )
2064  {
2065  mMapItem->beginCommand( tr( "Toggle Map Clipping" ) );
2066  mMapItem->itemClippingSettings()->setEnabled( active );
2067  mMapItem->endCommand();
2068  }
2069  } );
2070  connect( mItemClippingTypeComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [ = ]
2071  {
2072  if ( !mBlockUpdates )
2073  {
2074  mMapItem->beginCommand( tr( "Change Map Clipping Behavior" ) );
2075  mMapItem->itemClippingSettings()->setFeatureClippingType( static_cast< QgsMapClippingRegion::FeatureClippingType >( mItemClippingTypeComboBox->currentData().toInt() ) );
2076  mMapItem->endCommand();
2077  }
2078  } );
2079  connect( mForceLabelsInsideItemCheckBox, &QCheckBox::toggled, this, [ = ]( bool active )
2080  {
2081  if ( !mBlockUpdates )
2082  {
2083  mMapItem->beginCommand( tr( "Change Map Clipping Label Behavior" ) );
2084  mMapItem->itemClippingSettings()->setForceLabelsInsideClipPath( active );
2085  mMapItem->endCommand();
2086  }
2087  } );
2088  connect( mClipItemComboBox, &QgsLayoutItemComboBox::itemChanged, this, [ = ]( QgsLayoutItem * item )
2089  {
2090  if ( !mBlockUpdates )
2091  {
2092  mMapItem->beginCommand( tr( "Change Map Clipping Item" ) );
2093  mMapItem->itemClippingSettings()->setSourceItem( item );
2094  mMapItem->endCommand();
2095  }
2096  } );
2097 
2098  setNewItem( map );
2099 
2101  this, &QgsLayoutMapClippingWidget::atlasLayerChanged );
2102  if ( QgsLayoutAtlas *atlas = layoutAtlas() )
2103  {
2104  connect( atlas, &QgsLayoutAtlas::toggled, this, &QgsLayoutMapClippingWidget::atlasToggled );
2105  atlasToggled( atlas->enabled() );
2106  }
2107 }
2108 
2110 {
2111  mClipToAtlasCheckBox->setTitle( tr( "Clip to %1 feature" ).arg( string ) );
2112  mClipToAtlasLabel->setText( tr( "<b>When enabled, map layers will be automatically clipped to the boundary of the current %1 feature.</b>" ).arg( string ) );
2113  mForceLabelsInsideCheckBox->setText( tr( "Force labels inside %1 feature" ).arg( string ) );
2114 }
2115 
2117 {
2118  if ( item->type() != QgsLayoutItemRegistry::LayoutMap )
2119  return false;
2120 
2121  if ( mMapItem )
2122  {
2123  disconnect( mMapItem, &QgsLayoutObject::changed, this, &QgsLayoutMapClippingWidget::updateGuiElements );
2124  }
2125 
2126  mMapItem = qobject_cast< QgsLayoutItemMap * >( item );
2127 
2128  if ( mMapItem )
2129  {
2130  connect( mMapItem, &QgsLayoutObject::changed, this, &QgsLayoutMapClippingWidget::updateGuiElements );
2131  }
2132 
2133  updateGuiElements();
2134 
2135  return true;
2136 }
2137 
2138 void QgsLayoutMapClippingWidget::updateGuiElements()
2139 {
2140  if ( mBlockUpdates )
2141  return;
2142 
2143  mBlockUpdates = true;
2144  mClipToAtlasCheckBox->setChecked( mMapItem->atlasClippingSettings()->enabled() );
2145  mAtlasClippingTypeComboBox->setCurrentIndex( mAtlasClippingTypeComboBox->findData( static_cast< int >( mMapItem->atlasClippingSettings()->featureClippingType() ) ) );
2146  mForceLabelsInsideCheckBox->setChecked( mMapItem->atlasClippingSettings()->forceLabelsInsideFeature() );
2147 
2148  mRadioClipAllLayers->setChecked( !mMapItem->atlasClippingSettings()->restrictToLayers() );
2149  mRadioClipSelectedLayers->setChecked( mMapItem->atlasClippingSettings()->restrictToLayers() );
2150  mLayerModel->setLayersChecked( mMapItem->atlasClippingSettings()->layersToClip() );
2151 
2152  mClipToItemCheckBox->setChecked( mMapItem->itemClippingSettings()->enabled() );
2153  mItemClippingTypeComboBox->setCurrentIndex( mItemClippingTypeComboBox->findData( static_cast< int >( mMapItem->itemClippingSettings()->featureClippingType() ) ) );
2154  mForceLabelsInsideItemCheckBox->setChecked( mMapItem->itemClippingSettings()->forceLabelsInsideClipPath() );
2155  mClipItemComboBox->setItem( mMapItem->itemClippingSettings()->sourceItem() );
2156 
2157  mBlockUpdates = false;
2158 }
2159 
2160 void QgsLayoutMapClippingWidget::atlasLayerChanged( QgsVectorLayer *layer )
2161 {
2162  if ( !layer || layer->geometryType() != QgsWkbTypes::PolygonGeometry )
2163  {
2164  //non-polygon layer, disable atlas control
2165  mClipToAtlasCheckBox->setChecked( false );
2166  mClipToAtlasCheckBox->setEnabled( false );
2167  return;
2168  }
2169  else
2170  {
2171  mClipToAtlasCheckBox->setEnabled( true );
2172  }
2173 }
2174 
2175 void QgsLayoutMapClippingWidget::atlasToggled( bool atlasEnabled )
2176 {
2177  if ( atlasEnabled &&
2178  mMapItem && mMapItem->layout() && mMapItem->layout()->reportContext().layer()
2179  && mMapItem->layout()->reportContext().layer()->geometryType() == QgsWkbTypes::PolygonGeometry )
2180  {
2181  mClipToAtlasCheckBox->setEnabled( true );
2182  }
2183  else
2184  {
2185  mClipToAtlasCheckBox->setEnabled( false );
2186  mClipToAtlasCheckBox->setChecked( false );
2187  }
2188 }
QgsLayoutItemMapItem::setEnabled
virtual void setEnabled(bool enabled)
Controls whether the item will be drawn.
Definition: qgslayoutitemmapitem.cpp:99
QgsLayoutItemBaseWidget::updateDataDefinedButton
void updateDataDefinedButton(QgsPropertyOverrideButton *button)
Updates a previously registered data defined button to reflect the item's current properties.
Definition: qgslayoutitemwidget.cpp:251
QgsLayoutObject::layout
const QgsLayout * layout() const
Returns the layout the object is attached to.
Definition: qgslayoutobject.cpp:216
QgsLayoutItemMapItem::StackAboveMapLayer
@ StackAboveMapLayer
Render above a specific map layer (see stackingLayer())
Definition: qgslayoutitemmapitem.h:44
QgsLayoutItemMapGrid
An individual grid which is drawn above the map content in a QgsLayoutItemMap.
Definition: qgslayoutitemmapgrid.h:140
QgsMapThemeCollection::mapThemes
QStringList mapThemes
Definition: qgsmapthemecollection.h:48
QgsLayoutObject::StartDateTime
@ StartDateTime
Temporal range's start DateTime.
Definition: qgslayoutobject.h:211
QgsSymbolButton::changed
void changed()
Emitted when the symbol's settings are changed.
QgsLayoutMapClippingWidget::setNewItem
bool setNewItem(QgsLayoutItem *item) override
Attempts to update the widget to show the properties for the specified item.
Definition: qgslayoutmapwidget.cpp:2116
QgsVectorLayer::wkbType
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
Definition: qgsvectorlayer.cpp:725
QgsLayoutMapClippingWidget
Allows configuration of layout map clipping settings.
Definition: qgslayoutmapwidget.h:258
qgslayoutundostack.h
QgsLayoutItemMapItem::StackBelowMapLayer
@ StackBelowMapLayer
Render below a specific map layer (see stackingLayer())
Definition: qgslayoutitemmapitem.h:43
QgsMapCanvas::refresh
void refresh()
Repaints the canvas map.
Definition: qgsmapcanvas.cpp:643
QgsLayoutItemMap::Auto
@ Auto
The extent is adjusted so that each feature is fully visible.
Definition: qgslayoutitemmap.h:344
Qgis::SymbolType::Fill
@ Fill
Fill symbol.
QgsLayoutMapItemBlocksLabelsModel::columnCount
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Definition: qgslayoutmapwidget.cpp:1864
QgsSettings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Definition: qgssettings.cpp:161
qgslayoutmapgridwidget.h
QgsMapCanvas::zoomScale
void zoomScale(double scale, bool ignoreScaleLock=false)
Zooms the canvas to a specific scale.
Definition: qgsmapcanvas.cpp:2408
qgsmapcanvas.h
qgsmapthemecollection.h
QgsReferencedRectangle
A QgsRectangle with associated coordinate reference system.
Definition: qgsreferencedgeometry.h:73
QgsLayoutUnitsComboBox::changed
void changed(QgsUnitTypes::LayoutUnit unit)
Emitted when the unit is changed.
QgsMapClippingRegion::FeatureClippingType::NoClipping
@ NoClipping
Only render features which intersect the clipping region, but do not clip these features to the regio...
QgsMapThemeCollection::mapThemeVisibleLayerIds
QStringList mapThemeVisibleLayerIds(const QString &name) const
Returns the list of layer IDs that are visible for the specified map theme.
Definition: qgsmapthemecollection.cpp:320
QgsBookmarkManagerModel::RoleExtent
@ RoleExtent
Bookmark extent as a QgsReferencedRectangle.
Definition: qgsbookmarkmodel.h:50
QgsMapCanvas::mapSettings
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
Definition: qgsmapcanvas.cpp:437
QgsLayoutMapWidget::setMasterLayout
void setMasterLayout(QgsMasterLayoutInterface *masterLayout) override
Sets the master layout associated with the item.
Definition: qgslayoutmapwidget.cpp:208
Qgis::defaultProjectScales
static QString defaultProjectScales()
A string with default project scales.
Definition: qgis.cpp:271
QgsLayoutItemMap::extentChanged
void extentChanged()
Emitted when the map's extent changes.
crs
const QgsCoordinateReferenceSystem & crs
Definition: qgswfsgetfeature.cpp:105
QgsLayoutItemMapOverview::setInverted
void setInverted(bool inverted)
Sets whether the overview frame is inverted, ie, whether the shaded area is drawn outside the extent ...
Definition: qgslayoutitemmapoverview.cpp:350
QgsLayoutMapClippingWidget::setReportTypeString
void setReportTypeString(const QString &string) override
Sets the string to use to describe the current report type (e.g.
Definition: qgslayoutmapwidget.cpp:2109
QgsLayoutItemMapOverview::setLinkedMap
void setLinkedMap(QgsLayoutItemMap *map)
Sets the map to show the overview extent of.
Definition: qgslayoutitemmapoverview.cpp:218
qgssymbollayerutils.h
QgsProjectionSelectionWidget::crsChanged
void crsChanged(const QgsCoordinateReferenceSystem &)
Emitted when the selected CRS is changed.
QgsRectangle::yMinimum
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
QgsMapCanvas
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:89
QgsPanelWidget::openPanel
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
Definition: qgspanelwidget.cpp:84
QgsLayoutItemBaseWidget::registerDataDefinedButton
void registerDataDefinedButton(QgsPropertyOverrideButton *button, QgsLayoutObject::DataDefinedProperty property)
Registers a data defined button, setting up its initial value, connections and description.
Definition: qgslayoutitemwidget.cpp:246
QgsLayoutMapLabelingWidget::setNewItem
bool setNewItem(QgsLayoutItem *item) override
Attempts to update the widget to show the properties for the specified item.
Definition: qgslayoutmapwidget.cpp:1760
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:480
QgsLayoutMapWidget::QgsLayoutMapWidget
QgsLayoutMapWidget(QgsLayoutItemMap *item, QgsMapCanvas *mapCanvas)
constructor
Definition: qgslayoutmapwidget.cpp:44
QgsMapCanvas::scale
double scale() const
Returns the last reported scale of the canvas.
Definition: qgsmapcanvas.cpp:367
QgsLayoutItemMapItem::setName
void setName(const QString &name)
Sets the friendly display name for the item.
Definition: qgslayoutitemmapitem.cpp:89
QgsLayoutItemMapItem::id
QString id() const
Returns the unique id for the map item.
Definition: qgslayoutitemmapitem.h:100
QgsLayoutMapGridWidget
A widget for configuring layout map grid items.
Definition: qgslayoutmapgridwidget.h:36
QgsSettings
This class is a composition of two QSettings instances:
Definition: qgssettings.h:61
QgsLayoutMapWidget::populateDataDefinedButtons
void populateDataDefinedButtons()
Initializes data defined buttons to current atlas coverage layer.
Definition: qgslayoutmapwidget.cpp:264
QgsLayoutMapWidget::setNewItem
bool setNewItem(QgsLayoutItem *item) override
Attempts to update the widget to show the properties for the specified item.
Definition: qgslayoutmapwidget.cpp:232
QgsLayoutItemMap::ShowPartialLabels
@ ShowPartialLabels
Whether to draw labels which are partially outside of the map view.
Definition: qgslayoutitemmap.h:353
QgsLayoutMapItemBlocksLabelsModel
Model for label blocking items.
Definition: qgslayoutmapwidget.h:199
QgsLayoutItemMapItem::StackBelowMap
@ StackBelowMap
Render below all map layers.
Definition: qgslayoutitemmapitem.h:42
QgsLayoutMapItemBlocksLabelsModel::filterAcceptsRow
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override
Definition: qgslayoutmapwidget.cpp:1950
QgsLayoutItemMapOverview::setFrameSymbol
void setFrameSymbol(QgsFillSymbol *symbol)
Sets the fill symbol used for drawing the overview extent.
Definition: qgslayoutitemmapoverview.cpp:330
QgsLayoutObject::changed
void changed()
Emitted when the object's properties change.
QgsLayoutItemMapItem::setStackingPosition
void setStackingPosition(StackingPosition position)
Sets the item's stacking position, which specifies where the in the map's stack the item should be re...
Definition: qgslayoutitemmapitem.h:151
QgsLayoutDesignerInterface::ToolMoveItemContent
@ ToolMoveItemContent
Move item content tool.
Definition: qgslayoutdesignerinterface.h:74
QgsLayoutObject::MapXMin
@ MapXMin
Map extent x minimum.
Definition: qgslayoutobject.h:159
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsLayoutItemPropertiesWidget
A widget for controlling the common properties of layout items (e.g. position and size,...
Definition: qgslayoutitemwidget.h:217
QgsWkbTypes::PolygonGeometry
@ PolygonGeometry
Definition: qgswkbtypes.h:144
QgsLayoutItemMapOverview::inverted
bool inverted() const
Returns whether the overview frame is inverted, ie, whether the shaded area is drawn outside the exte...
Definition: qgslayoutitemmapoverview.h:195
QgsLayoutItemBaseWidget::layoutAtlas
QgsLayoutAtlas * layoutAtlas() const
Returns the atlas for the layout (if available)
Definition: qgslayoutitemwidget.cpp:266
QgsLayoutItem::FlagProvidesClipPath
@ FlagProvidesClipPath
Item can act as a clipping path provider (see clipPath())
Definition: qgslayoutitem.h:306
QgsGuiUtils::iconSize
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
Definition: qgsguiutils.cpp:264
QgsLayoutItemBaseWidget::coverageLayer
QgsVectorLayer * coverageLayer() const
Returns the current layout context coverage layer (if set).
Definition: qgslayoutitemwidget.cpp:256
QgsLayoutObject::MapCrs
@ MapCrs
Map CRS.
Definition: qgslayoutobject.h:210
QgsMapLayerModel::layersChecked
QList< QgsMapLayer * > layersChecked(Qt::CheckState checkState=Qt::Checked)
layersChecked returns the list of layers which are checked (or unchecked)
Definition: qgsmaplayermodel.cpp:117
QgsLayoutItemPropertiesWidget::setMasterLayout
void setMasterLayout(QgsMasterLayoutInterface *masterLayout)
Sets the master layout associated with the item.
Definition: qgslayoutitemwidget.cpp:420
QgsLayoutItem::type
int type() const override
Returns a unique graphics item type identifier.
Definition: qgslayoutitem.cpp:124
QgsLayoutObject::MapYMin
@ MapYMin
Map extent y minimum.
Definition: qgslayoutobject.h:160
QgsLayoutItemMapOverview::setCentered
void setCentered(bool centered)
Sets whether the extent of the map is forced to center on the overview.
Definition: qgslayoutitemmapoverview.cpp:355
QgsLayoutItemMapOverview::setBlendMode
void setBlendMode(QPainter::CompositionMode mode)
Sets the blending mode used for drawing the overview.
Definition: qgslayoutitemmapoverview.cpp:345
QgsRectangle::xMaximum
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
QgsProject::layerTreeRoot
QgsLayerTree * layerTreeRoot() const
Returns pointer to the root (invisible) node of the project's layer tree.
Definition: qgsproject.cpp:3541
QgsLayoutItemMapOverview::linkedMap
QgsLayoutItemMap * linkedMap()
Returns the source map to show the overview extent of.
Definition: qgslayoutitemmapoverview.cpp:238
QgsLayoutMapItemBlocksLabelsModel::setData
bool setData(const QModelIndex &index, const QVariant &value, int role) override
Definition: qgslayoutmapwidget.cpp:1901
QgsCsException
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
QgsLayoutItemMapItem::stackingLayer
QgsMapLayer * stackingLayer() const
Returns the item's stacking layer, which specifies where the in the map's stack the item should be re...
Definition: qgslayoutitemmapitem.cpp:114
QgsLayoutModel::index
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Definition: qgslayoutmodel.cpp:51
QgsLayoutModel
A model for items attached to a layout. The model also maintains the z-order for the layout,...
Definition: qgslayoutmodel.h:52
QgsLayoutObject::OriginalValue
@ OriginalValue
Return the original, user set value.
Definition: qgslayoutobject.h:223
QgsLayoutItemBaseWidget::setDesignerInterface
virtual void setDesignerInterface(QgsLayoutDesignerInterface *iface)
Sets the the layout designer interface in which the widget is being shown.
Definition: qgslayoutitemwidget.cpp:227
whileBlocking
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:2191
QgsLayoutItemMapOverview::centered
bool centered() const
Returns whether the extent of the map is forced to center on the overview.
Definition: qgslayoutitemmapoverview.h:208
QgsLayoutObject::MapRotation
@ MapRotation
Map rotation.
Definition: qgslayoutobject.h:157
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2265
QgsLayoutObject::MapXMax
@ MapXMax
Map extent x maximum.
Definition: qgslayoutobject.h:161
QgsLayerTree::layerOrder
QList< QgsMapLayer * > layerOrder() const
The order in which layers will be rendered on the canvas.
Definition: qgslayertree.cpp:79
QgsLayoutObject::MapYMax
@ MapYMax
Map extent y maximum.
Definition: qgslayoutobject.h:162
QgsMapClippingRegion::FeatureClippingType::ClipToIntersection
@ ClipToIntersection
Clip the geometry of these features to the region prior to rendering (i.e. feature boundaries will fo...
qgslayoutmapwidget.h
QgsMapThemeCollection::mapThemesChanged
void mapThemesChanged()
Emitted when map themes within the collection are changed.
QgsLayout::reportContext
QgsLayoutReportContext & reportContext()
Returns a reference to the layout's report context, which stores information relating to the current ...
Definition: qgslayout.cpp:369
QgsLayoutMapWidget::setReportTypeString
void setReportTypeString(const QString &string) override
Sets the string to use to describe the current report type (e.g.
Definition: qgslayoutmapwidget.cpp:214
QgsLayoutItemMap::Fixed
@ Fixed
The current scale of the map is used for each feature of the atlas.
Definition: qgslayoutitemmap.h:329
QgsCoordinateReferenceSystem::isValid
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Definition: qgscoordinatereferencesystem.cpp:977
QgsLayoutItem::UndoAtlasMargin
@ UndoAtlasMargin
Map atlas margin changed.
Definition: qgslayoutitem.h:229
QgsLayoutModel::ItemId
@ ItemId
Item ID.
Definition: qgslayoutmodel.h:63
QgsMapLayer::id
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
Definition: qgsmaplayer.cpp:169
QgsLayoutItem::UndoMapRotation
@ UndoMapRotation
Map rotation changed.
Definition: qgslayoutitem.h:230
QgsLayoutMapWidget::setDesignerInterface
void setDesignerInterface(QgsLayoutDesignerInterface *iface) override
Sets the the layout designer interface in which the widget is being shown.
Definition: qgslayoutmapwidget.cpp:226
QgsProject::mapThemeCollection
QgsMapThemeCollection mapThemeCollection
Definition: qgsproject.h:112
QgsMapCanvas::setReferencedExtent
bool setReferencedExtent(const QgsReferencedRectangle &extent) SIP_THROW(QgsCsException)
Sets the canvas to the specified extent.
Definition: qgsmapcanvas.cpp:1427
QgsLayoutItem
Base class for graphical items within a QgsLayout.
Definition: qgslayoutitem.h:112
QgsRectangle::xMinimum
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
QgsLayoutItemMapItem::StackBelowMapLabels
@ StackBelowMapLabels
Render above all map layers, but below map labels.
Definition: qgslayoutitemmapitem.h:45
QgsApplication::bookmarkManager
static QgsBookmarkManager * bookmarkManager()
Returns the application's bookmark manager, used for storing installation-wide bookmarks.
Definition: qgsapplication.cpp:2425
qgslayertree.h
QgsMapClippingRegion::FeatureClippingType
FeatureClippingType
Feature clipping behavior, which controls how features from vector layers will be clipped.
Definition: qgsmapclippingregion.h:41
QgsPanelWidget::setPanelTitle
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
Definition: qgspanelwidget.h:44
qgslayout.h
QgsLayoutObject::MapScale
@ MapScale
Map scale.
Definition: qgslayoutobject.h:158
QgsProjectionSelectionWidget::CrsNotSet
@ CrsNotSet
Not set (hidden by default)
Definition: qgsprojectionselectionwidget.h:55
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:211
QgsLayoutObject::MapLabelMargin
@ MapLabelMargin
Map label margin.
Definition: qgslayoutobject.h:166
QgsBookmarkManagerModel::RoleGroup
@ RoleGroup
Bookmark group.
Definition: qgsbookmarkmodel.h:53
qgssymbolselectordialog.h
qgsstyle.h
QgsLayoutItemBaseWidget
A base class for property widgets for layout items. All layout item widgets should inherit from this ...
Definition: qgslayoutitemwidget.h:122
QgsLayoutItemMapOverview
An individual overview which is drawn above the map content in a QgsLayoutItemMap,...
Definition: qgslayoutitemmapoverview.h:126
QgsLayoutObject::MapAtlasMargin
@ MapAtlasMargin
Map atlas margin.
Definition: qgslayoutobject.h:163
QgsMapSettings::destinationCrs
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
Definition: qgsmapsettings.cpp:358
QgsLayoutItemMap
Layout graphical items for displaying a map.
Definition: qgslayoutitemmap.h:317
QgsReferencedGeometryBase::crs
QgsCoordinateReferenceSystem crs() const
Returns the associated coordinate reference system, or an invalid CRS if no reference system is set.
Definition: qgsreferencedgeometry.h:53
qgsbookmarkmodel.h
qgsreferencedgeometry.h
qgsprojectviewsettings.h
QgsLayoutDesignerInterface::activateTool
virtual void activateTool(StandardTool tool)=0
Activates a standard layout designer tool.
QgsWkbTypes::PointGeometry
@ PointGeometry
Definition: qgswkbtypes.h:142
QgsLayoutItemMap::Predefined
@ Predefined
A scale is chosen from the predefined scales.
Definition: qgslayoutitemmap.h:337
QgsLayoutItemMapItem::stackingPosition
StackingPosition stackingPosition() const
Returns the item's stacking position, which specifies where the in the map's stack the item should be...
Definition: qgslayoutitemmapitem.h:140
QgsRectangle::yMaximum
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
QgsWkbTypes::NoGeometry
@ NoGeometry
Definition: qgswkbtypes.h:85
QgsLayoutMapItemBlocksLabelsModel::QgsLayoutMapItemBlocksLabelsModel
QgsLayoutMapItemBlocksLabelsModel(QgsLayoutItemMap *map, QgsLayoutModel *layoutModel, QObject *parent=nullptr)
constructor
Definition: qgslayoutmapwidget.cpp:1856
QgsSymbolButton::setLayer
void setLayer(QgsVectorLayer *layer)
Sets a layer to associate with the widget.
Definition: qgssymbolbutton.cpp:208
QgsLayoutItemMapItem::StackAboveMapLabels
@ StackAboveMapLabels
Render above all map layers and labels.
Definition: qgslayoutitemmapitem.h:46
qgsmaplayermodel.h
QgsMapClippingRegion::FeatureClippingType::ClipPainterOnly
@ ClipPainterOnly
Applying clipping on the painter only (i.e. feature boundaries will be unchanged, but may be invisibl...
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:391
QgsLayoutMapClippingWidget::QgsLayoutMapClippingWidget
QgsLayoutMapClippingWidget(QgsLayoutItemMap *map)
constructor
Definition: qgslayoutmapwidget.cpp:1967
QgsLayoutItemMap::mapRotationChanged
void mapRotationChanged(double newRotation)
Emitted when the map's rotation changes.
QgsLayoutItemMapItem::StackingPosition
StackingPosition
Item stacking position, specifies where the in the map's stack the item should be rendered.
Definition: qgslayoutitemmapitem.h:40
QgsMapLayer
Base class for all map layer types. This is the base class for all map layer types (vector,...
Definition: qgsmaplayer.h:72
QgsMapLayerModel::setLayersChecked
void setLayersChecked(const QList< QgsMapLayer * > &layers)
Sets which layers are checked in the model.
Definition: qgsmaplayermodel.cpp:131
QgsLayoutDesignerInterface
A common interface for layout designer dialogs and widgets.
Definition: qgslayoutdesignerinterface.h:55
QgsLayoutAtlas::toggled
void toggled(bool)
Emitted when atlas is enabled or disabled.
QgsFillSymbol::clone
QgsFillSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgsfillsymbol.cpp:144
QgsFillSymbol
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgsfillsymbol.h:29
QgsLayoutItemRegistry::LayoutMap
@ LayoutMap
Map item.
Definition: qgslayoutitemregistry.h:347
QgsWkbTypes::geometryType
static GeometryType geometryType(Type type) SIP_HOLDGIL
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:968
QgsDoubleSpinBox
The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value....
Definition: qgsdoublespinbox.h:42
QgsLayoutModel::data
QVariant data(const QModelIndex &index, int role) const override
Definition: qgslayoutmodel.cpp:125
QgsLayoutItemComboBox::itemChanged
void itemChanged(QgsLayoutItem *item)
Emitted whenever the currently selected item changes.
QgsLayoutMapLabelingWidget::QgsLayoutMapLabelingWidget
QgsLayoutMapLabelingWidget(QgsLayoutItemMap *map)
constructor
Definition: qgslayoutmapwidget.cpp:1737
QgsLayoutMapItemBlocksLabelsModel::data
QVariant data(const QModelIndex &index, int role) const override
Definition: qgslayoutmapwidget.cpp:1869
QgsLayoutItemMapItem::name
QString name() const
Returns the friendly display name for the item.
Definition: qgslayoutitemmapitem.cpp:94
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Definition: qgsapplication.cpp:693
QgsLayoutItemMapOverview::frameSymbol
QgsFillSymbol * frameSymbol()
Returns the fill symbol used for drawing the overview extent.
Definition: qgslayoutitemmapoverview.cpp:335
QgsMasterLayoutInterface
Interface for master layout type objects, such as print layouts and reports.
Definition: qgsmasterlayoutinterface.h:42
qgsguiutils.h
QgsLayoutItem::UndoOverviewStyle
@ UndoOverviewStyle
Map overview style.
Definition: qgslayoutitem.h:232
qgslayoutdesignerinterface.h
QgsLayoutItemPropertiesWidget::setItem
void setItem(QgsLayoutItem *item)
Sets the layout item.
Definition: qgslayoutitemwidget.cpp:401
QgsLayoutReportContext::layerChanged
void layerChanged(QgsVectorLayer *layer)
Emitted when the context's layer is changed.
QgsLayoutObject::EndDateTime
@ EndDateTime
Temporal range's end DateTime.
Definition: qgslayoutobject.h:212
QgsMapSettings::visibleExtent
QgsRectangle visibleExtent() const
Returns the actual extent derived from requested extent that takes output image size into account.
Definition: qgsmapsettings.cpp:411
QgsLayoutObject::MapStylePreset
@ MapStylePreset
Layer and style map theme.
Definition: qgslayoutobject.h:165
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:57
QgsLayoutItemMapOverview::blendMode
QPainter::CompositionMode blendMode() const
Retrieves the blending mode used for drawing the overview.
Definition: qgslayoutitemmapoverview.h:182
QgsLayoutModel::itemFromIndex
QgsLayoutItem * itemFromIndex(const QModelIndex &index) const
Returns the QgsLayoutItem corresponding to a QModelIndex index, if possible.
Definition: qgslayoutmodel.cpp:39
QgsLayoutItemMapItem::setStackingLayer
void setStackingLayer(QgsMapLayer *layer)
Sets the item's stacking layer, which specifies where the in the map's stack the item should be rende...
Definition: qgslayoutitemmapitem.cpp:119
QgsVectorLayer::geometryType
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
Definition: qgsvectorlayer.cpp:720
QgsBookmarkManagerProxyModel
A QSortFilterProxyModel subclass for sorting the entries in a QgsBookmarkManagerModel.
Definition: qgsbookmarkmodel.h:108
QgsLayoutMapLabelingWidget
Allows configuration of layout map labeling settings.
Definition: qgslayoutmapwidget.h:229
QgsRectangle::isEmpty
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:469
QgsBookmarkManagerModel::RoleName
@ RoleName
Bookmark name.
Definition: qgsbookmarkmodel.h:51
qgsfillsymbol.h
QgsLayoutAtlas
Class used to render QgsLayout as an atlas, by iterating over the features from an associated vector ...
Definition: qgslayoutatlas.h:41
QgsProject::crs
QgsCoordinateReferenceSystem crs
Definition: qgsproject.h:109
QgsMapLayerModel::setItemsCheckable
void setItemsCheckable(bool checkable)
setItemsCheckable defines if layers should be selectable in the widget
Definition: qgsmaplayermodel.cpp:62
qgsproject.h
QgsLayoutItemMapItem::enabled
bool enabled() const
Returns whether the item will be drawn.
Definition: qgslayoutitemmapitem.cpp:104
QgsLayoutItemMap::ShowUnplacedLabels
@ ShowUnplacedLabels
Whether to render unplaced labels in the map view.
Definition: qgslayoutitemmap.h:354
QgsLayoutMeasurement
This class provides a method of storing measurements for use in QGIS layouts using a variety of diffe...
Definition: qgslayoutmeasurement.h:33
QgsMapLayerComboBox::layerChanged
void layerChanged(QgsMapLayer *layer)
Emitted whenever the currently selected layer changes.
QgsMapSettings::layers
QList< QgsMapLayer * > layers(bool expandGroupLayers=false) const
Returns the list of layers which will be rendered in the map.
Definition: qgsmapsettings.cpp:299
QgsMapLayerModel
The QgsMapLayerModel class is a model to display layers in widgets.
Definition: qgsmaplayermodel.h:37
QgsLayoutItemPropertiesWidget::updateVariables
void updateVariables()
Updates the variables widget, refreshing the values of variables shown.
Definition: qgslayoutitemwidget.cpp:276
QgsLayoutItem::UndoMapLabelMargin
@ UndoMapLabelMargin
Margin for labels from edge of map.
Definition: qgslayoutitem.h:241
qgslayoutitemmap.h
QgsLayoutObject::MapLayers
@ MapLayers
Map layer set.
Definition: qgslayoutobject.h:164
QgsLayoutMapItemBlocksLabelsModel::flags
Qt::ItemFlags flags(const QModelIndex &index) const override
Definition: qgslayoutmapwidget.cpp:1932
qgslayoutatlas.h