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