QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
qgslayoutpicturewidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayoutpicturewidget.cpp
3  --------------------------
4  begin : October 2017
5  copyright : (C) 2017 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgslayoutpicturewidget.h"
19 #include "qgsapplication.h"
20 #include "qgslayoutitemmap.h"
21 #include "qgslayoutitempicture.h"
22 #include "qgslayout.h"
24 #include "qgssvgcache.h"
25 #include "qgssettings.h"
26 #include "qgssvgselectorwidget.h"
27 
28 #include <QDoubleValidator>
29 #include <QFileDialog>
30 #include <QFileInfo>
31 #include <QImageReader>
32 #include <QMessageBox>
33 #include <QPainter>
34 #include <QProgressDialog>
35 #include <QSvgRenderer>
36 
38  : QgsLayoutItemBaseWidget( nullptr, picture )
39  , mPicture( picture )
40 {
41  setupUi( this );
42 
43  mResizeModeComboBox->addItem( tr( "Zoom" ), QgsLayoutItemPicture::Zoom );
44  mResizeModeComboBox->addItem( tr( "Stretch" ), QgsLayoutItemPicture::Stretch );
45  mResizeModeComboBox->addItem( tr( "Clip" ), QgsLayoutItemPicture::Clip );
46  mResizeModeComboBox->addItem( tr( "Zoom and Resize Frame" ), QgsLayoutItemPicture::ZoomResizeFrame );
47  mResizeModeComboBox->addItem( tr( "Resize Frame to Image Size" ), QgsLayoutItemPicture::FrameToImageSize );
48 
49  mAnchorPointComboBox->addItem( tr( "Top Left" ), QgsLayoutItem::UpperLeft );
50  mAnchorPointComboBox->addItem( tr( "Top Center" ), QgsLayoutItem::UpperMiddle );
51  mAnchorPointComboBox->addItem( tr( "Top Right" ), QgsLayoutItem::UpperRight );
52  mAnchorPointComboBox->addItem( tr( "Middle Left" ), QgsLayoutItem::MiddleLeft );
53  mAnchorPointComboBox->addItem( tr( "Middle" ), QgsLayoutItem::Middle );
54  mAnchorPointComboBox->addItem( tr( "Middle Right" ), QgsLayoutItem::MiddleRight );
55  mAnchorPointComboBox->addItem( tr( "Bottom Left" ), QgsLayoutItem::LowerLeft );
56  mAnchorPointComboBox->addItem( tr( "Bottom Center" ), QgsLayoutItem::LowerMiddle );
57  mAnchorPointComboBox->addItem( tr( "Bottom Right" ), QgsLayoutItem::LowerRight );
58 
59  connect( mPictureRotationSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutPictureWidget::mPictureRotationSpinBox_valueChanged );
60  connect( mRotationFromComposerMapCheckBox, &QCheckBox::stateChanged, this, &QgsLayoutPictureWidget::mRotationFromComposerMapCheckBox_stateChanged );
61  connect( mResizeModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutPictureWidget::mResizeModeComboBox_currentIndexChanged );
62  connect( mAnchorPointComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutPictureWidget::mAnchorPointComboBox_currentIndexChanged );
63  connect( mFillColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutPictureWidget::mFillColorButton_colorChanged );
64  connect( mStrokeColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutPictureWidget::mStrokeColorButton_colorChanged );
65  connect( mStrokeWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutPictureWidget::mStrokeWidthSpinBox_valueChanged );
66  connect( mPictureRotationOffsetSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutPictureWidget::mPictureRotationOffsetSpinBox_valueChanged );
67  connect( mNorthTypeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutPictureWidget::mNorthTypeComboBox_currentIndexChanged );
68  connect( mRadioSVG, &QRadioButton::toggled, this, &QgsLayoutPictureWidget::modeChanged );
69  connect( mRadioRaster, &QRadioButton::toggled, this, &QgsLayoutPictureWidget::modeChanged );
70  connect( mSvgSourceLineEdit, &QgsSvgSourceLineEdit::sourceChanged, this, &QgsLayoutPictureWidget::svgSourceChanged );
71  connect( mImageSourceLineEdit, &QgsImageSourceLineEdit::sourceChanged, this, &QgsLayoutPictureWidget::rasterSourceChanged );
72 
73  mSvgSourceLineEdit->setLastPathSettingsKey( QStringLiteral( "/UI/lastComposerPictureDir" ) );
74 
75  setPanelTitle( tr( "Picture Properties" ) );
76 
77  mFillColorButton->setAllowOpacity( true );
78  mFillColorButton->setColorDialogTitle( tr( "Select Fill Color" ) );
79  mFillColorButton->setContext( QStringLiteral( "composer" ) );
80  mStrokeColorButton->setAllowOpacity( true );
81  mStrokeColorButton->setColorDialogTitle( tr( "Select Stroke Color" ) );
82  mStrokeColorButton->setContext( QStringLiteral( "composer" ) );
83 
84  mFillColorDDBtn->registerLinkedWidget( mFillColorButton );
85  mStrokeColorDDBtn->registerLinkedWidget( mStrokeColorButton );
86 
87  mNorthTypeComboBox->blockSignals( true );
88  mNorthTypeComboBox->addItem( tr( "Grid North" ), QgsLayoutItemPicture::GridNorth );
89  mNorthTypeComboBox->addItem( tr( "True North" ), QgsLayoutItemPicture::TrueNorth );
90  mNorthTypeComboBox->blockSignals( false );
91  mPictureRotationOffsetSpinBox->setClearValue( 0.0 );
92  mPictureRotationSpinBox->setClearValue( 0.0 );
93 
94  viewGroups->setHeaderHidden( true );
95 #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
96  mIconSize = std::max( 30, static_cast< int >( std::round( Qgis::UI_SCALE_FACTOR * fontMetrics().width( 'X' ) * 4 ) ) );
97 #else
98  mIconSize = std::max( 30, static_cast< int >( std::round( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 4 ) ) );
99 #endif
100  viewImages->setGridSize( QSize( mIconSize * 1.2, mIconSize * 1.2 ) );
101  viewImages->setUniformItemSizes( false );
102  populateList();
103 
104  connect( viewImages->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsLayoutPictureWidget::setSvgName );
105  connect( viewGroups->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsLayoutPictureWidget::populateIcons );
106 
107 
108  //add widget for general composer item properties
109  mItemPropertiesWidget = new QgsLayoutItemPropertiesWidget( this, picture );
110  mainLayout->addWidget( mItemPropertiesWidget );
111 
112  if ( mPicture->layout() )
113  {
114  mComposerMapComboBox->setCurrentLayout( mPicture->layout() );
115  mComposerMapComboBox->setItemType( QgsLayoutItemRegistry::LayoutMap );
116  connect( mComposerMapComboBox, &QgsLayoutItemComboBox::itemChanged, this, &QgsLayoutPictureWidget::mapChanged );
117  }
118 
119  setGuiElementValues();
120 
121  connect( mPicture, &QgsLayoutObject::changed, this, &QgsLayoutPictureWidget::setGuiElementValues );
122  connect( mPicture, &QgsLayoutItemPicture::pictureRotationChanged, this, &QgsLayoutPictureWidget::setPicRotationSpinValue );
123 
124  //connections for data defined buttons
125  mSourceDDBtn->registerEnabledWidget( mImageSourceLineEdit, false );
126  mSourceDDBtn->registerEnabledWidget( mSvgSourceLineEdit, false );
127 
132 
133  updatePictureTypeWidgets();
134 }
135 
137 {
138  if ( mItemPropertiesWidget )
139  mItemPropertiesWidget->setMasterLayout( masterLayout );
140 }
141 
142 void QgsLayoutPictureWidget::mPictureRotationSpinBox_valueChanged( double d )
143 {
144  if ( mPicture )
145  {
146  mPicture->beginCommand( tr( "Change Picture Rotation" ), QgsLayoutItem::UndoPictureRotation );
147  mPicture->setPictureRotation( d );
148  mPicture->endCommand();
149  }
150 }
151 
152 void QgsLayoutPictureWidget::mResizeModeComboBox_currentIndexChanged( int )
153 {
154  if ( !mPicture )
155  {
156  return;
157  }
158 
159  mPicture->beginCommand( tr( "Change Resize Mode" ) );
160  mPicture->setResizeMode( static_cast< QgsLayoutItemPicture::ResizeMode >( mResizeModeComboBox->currentData().toInt() ) );
161  mPicture->endCommand();
162 
163  //disable picture rotation for non-zoom modes
164  mRotationGroupBox->setEnabled( mPicture->resizeMode() == QgsLayoutItemPicture::Zoom ||
165  mPicture->resizeMode() == QgsLayoutItemPicture::ZoomResizeFrame );
166 
167  //disable anchor point control for certain zoom modes
168  if ( mPicture->resizeMode() == QgsLayoutItemPicture::Zoom ||
169  mPicture->resizeMode() == QgsLayoutItemPicture::Clip )
170  {
171  mAnchorPointComboBox->setEnabled( true );
172  }
173  else
174  {
175  mAnchorPointComboBox->setEnabled( false );
176  }
177 }
178 
179 void QgsLayoutPictureWidget::mAnchorPointComboBox_currentIndexChanged( int )
180 {
181  if ( !mPicture )
182  {
183  return;
184  }
185 
186  mPicture->beginCommand( tr( "Change Placement" ) );
187  mPicture->setPictureAnchor( static_cast< QgsLayoutItem::ReferencePoint >( mAnchorPointComboBox->currentData().toInt() ) );
188  mPicture->endCommand();
189 }
190 
192 {
194  return false;
195 
196  if ( mPicture )
197  {
198  disconnect( mPicture, &QgsLayoutObject::changed, this, &QgsLayoutPictureWidget::setGuiElementValues );
199  disconnect( mPicture, &QgsLayoutItemPicture::pictureRotationChanged, this, &QgsLayoutPictureWidget::setPicRotationSpinValue );
200  }
201 
202  mPicture = qobject_cast< QgsLayoutItemPicture * >( item );
203  mItemPropertiesWidget->setItem( mPicture );
204 
205  if ( mPicture )
206  {
207  connect( mPicture, &QgsLayoutObject::changed, this, &QgsLayoutPictureWidget::setGuiElementValues );
208  connect( mPicture, &QgsLayoutItemPicture::pictureRotationChanged, this, &QgsLayoutPictureWidget::setPicRotationSpinValue );
209  }
210 
211  setGuiElementValues();
212 
213  return true;
214 }
215 
216 void QgsLayoutPictureWidget::mRotationFromComposerMapCheckBox_stateChanged( int state )
217 {
218  if ( !mPicture )
219  {
220  return;
221  }
222 
223  mPicture->beginCommand( tr( "Toggle Rotation Sync" ) );
224  if ( state == Qt::Unchecked )
225  {
226  mPicture->setLinkedMap( nullptr );
227  mPictureRotationSpinBox->setEnabled( true );
228  mComposerMapComboBox->setEnabled( false );
229  mNorthTypeComboBox->setEnabled( false );
230  mPictureRotationOffsetSpinBox->setEnabled( false );
231  mPicture->setPictureRotation( mPictureRotationSpinBox->value() );
232  }
233  else
234  {
235  QgsLayoutItemMap *map = qobject_cast< QgsLayoutItemMap * >( mComposerMapComboBox->currentItem() );
236  mPicture->setLinkedMap( map );
237  mPictureRotationSpinBox->setEnabled( false );
238  mNorthTypeComboBox->setEnabled( true );
239  mPictureRotationOffsetSpinBox->setEnabled( true );
240  mComposerMapComboBox->setEnabled( true );
241  }
242  mPicture->endCommand();
243 }
244 
245 void QgsLayoutPictureWidget::mapChanged( QgsLayoutItem *item )
246 {
247  if ( !mPicture )
248  {
249  return;
250  }
251 
252  //get composition
253  const QgsLayout *layout = mPicture->layout();
254  if ( !layout )
255  {
256  return;
257  }
258 
259  QgsLayoutItemMap *map = qobject_cast< QgsLayoutItemMap *>( item );
260  if ( !map )
261  {
262  return;
263  }
264 
265  mPicture->beginCommand( tr( "Change Rotation Map" ) );
266  mPicture->setLinkedMap( map );
267  mPicture->update();
268  mPicture->endCommand();
269 }
270 
271 void QgsLayoutPictureWidget::setPicRotationSpinValue( double r )
272 {
273  mPictureRotationSpinBox->blockSignals( true );
274  mPictureRotationSpinBox->setValue( r );
275  mPictureRotationSpinBox->blockSignals( false );
276 }
277 
278 void QgsLayoutPictureWidget::setGuiElementValues()
279 {
280  //set initial gui values
281  if ( mPicture )
282  {
283  mPictureRotationSpinBox->blockSignals( true );
284  mComposerMapComboBox->blockSignals( true );
285  mRotationFromComposerMapCheckBox->blockSignals( true );
286  mNorthTypeComboBox->blockSignals( true );
287  mPictureRotationOffsetSpinBox->blockSignals( true );
288  mResizeModeComboBox->blockSignals( true );
289  mAnchorPointComboBox->blockSignals( true );
290  mFillColorButton->blockSignals( true );
291  mStrokeColorButton->blockSignals( true );
292  mStrokeWidthSpinBox->blockSignals( true );
293 
294  mPictureRotationSpinBox->setValue( mPicture->pictureRotation() );
295 
296  mComposerMapComboBox->setItem( mPicture->linkedMap() );
297 
298  if ( mPicture->linkedMap() )
299  {
300  mRotationFromComposerMapCheckBox->setCheckState( Qt::Checked );
301  mPictureRotationSpinBox->setEnabled( false );
302  mComposerMapComboBox->setEnabled( true );
303  mNorthTypeComboBox->setEnabled( true );
304  mPictureRotationOffsetSpinBox->setEnabled( true );
305  }
306  else
307  {
308  mRotationFromComposerMapCheckBox->setCheckState( Qt::Unchecked );
309  mPictureRotationSpinBox->setEnabled( true );
310  mComposerMapComboBox->setEnabled( false );
311  mNorthTypeComboBox->setEnabled( false );
312  mPictureRotationOffsetSpinBox->setEnabled( false );
313  }
314  mNorthTypeComboBox->setCurrentIndex( mNorthTypeComboBox->findData( mPicture->northMode() ) );
315  mPictureRotationOffsetSpinBox->setValue( mPicture->northOffset() );
316 
317  mResizeModeComboBox->setCurrentIndex( mResizeModeComboBox->findData( mPicture->resizeMode() ) );
318  //disable picture rotation for non-zoom modes
319  mRotationGroupBox->setEnabled( mPicture->resizeMode() == QgsLayoutItemPicture::Zoom ||
320  mPicture->resizeMode() == QgsLayoutItemPicture::ZoomResizeFrame );
321 
322  mAnchorPointComboBox->setCurrentIndex( mAnchorPointComboBox->findData( mPicture->pictureAnchor() ) );
323  //disable anchor point control for certain zoom modes
324  if ( mPicture->resizeMode() == QgsLayoutItemPicture::Zoom ||
325  mPicture->resizeMode() == QgsLayoutItemPicture::Clip )
326  {
327  mAnchorPointComboBox->setEnabled( true );
328  }
329  else
330  {
331  mAnchorPointComboBox->setEnabled( false );
332  }
333 
334  whileBlocking( mRadioSVG )->setChecked( mPicture->mode() == QgsLayoutItemPicture::FormatSVG );
335  whileBlocking( mRadioRaster )->setChecked( mPicture->mode() == QgsLayoutItemPicture::FormatRaster );
336  updatePictureTypeWidgets();
337 
338  if ( mRadioSVG->isChecked() )
339  {
340  whileBlocking( mSvgSourceLineEdit )->setSource( mPicture->picturePath() );
341 
342  mBlockSvgModelChanges++;
343  QAbstractItemModel *m = viewImages->model();
344  QItemSelectionModel *selModel = viewImages->selectionModel();
345  for ( int i = 0; i < m->rowCount(); i++ )
346  {
347  QModelIndex idx( m->index( i, 0 ) );
348  if ( m->data( idx ).toString() == mPicture->picturePath() )
349  {
350  selModel->select( idx, QItemSelectionModel::SelectCurrent );
351  selModel->setCurrentIndex( idx, QItemSelectionModel::SelectCurrent );
352  break;
353  }
354  }
355  mBlockSvgModelChanges--;
356  }
357  else if ( mRadioRaster->isChecked() )
358  {
359  whileBlocking( mImageSourceLineEdit )->setSource( mPicture->picturePath() );
360  }
361 
362  updateSvgParamGui( false );
363  mFillColorButton->setColor( mPicture->svgFillColor() );
364  mStrokeColorButton->setColor( mPicture->svgStrokeColor() );
365  mStrokeWidthSpinBox->setValue( mPicture->svgStrokeWidth() );
366 
367  mRotationFromComposerMapCheckBox->blockSignals( false );
368  mPictureRotationSpinBox->blockSignals( false );
369  mComposerMapComboBox->blockSignals( false );
370  mNorthTypeComboBox->blockSignals( false );
371  mPictureRotationOffsetSpinBox->blockSignals( false );
372  mResizeModeComboBox->blockSignals( false );
373  mAnchorPointComboBox->blockSignals( false );
374  mFillColorButton->blockSignals( false );
375  mStrokeColorButton->blockSignals( false );
376  mStrokeWidthSpinBox->blockSignals( false );
377 
379  }
380 }
381 
382 void QgsLayoutPictureWidget::updateSvgParamGui( bool resetValues )
383 {
384  if ( !mPicture )
385  return;
386 
387  QString picturePath = mPicture->picturePath();
388 
389  //activate gui for svg parameters only if supported by the svg file
390  bool hasFillParam, hasFillOpacityParam, hasStrokeParam, hasStrokeWidthParam, hasStrokeOpacityParam;
391  QColor defaultFill, defaultStroke;
392  double defaultStrokeWidth, defaultFillOpacity, defaultStrokeOpacity;
393  bool hasDefaultFillColor, hasDefaultFillOpacity, hasDefaultStrokeColor, hasDefaultStrokeWidth, hasDefaultStrokeOpacity;
394  QgsApplication::svgCache()->containsParams( picturePath, hasFillParam, hasDefaultFillColor, defaultFill,
395  hasFillOpacityParam, hasDefaultFillOpacity, defaultFillOpacity,
396  hasStrokeParam, hasDefaultStrokeColor, defaultStroke,
397  hasStrokeWidthParam, hasDefaultStrokeWidth, defaultStrokeWidth,
398  hasStrokeOpacityParam, hasDefaultStrokeOpacity, defaultStrokeOpacity );
399 
400  if ( resetValues )
401  {
402  QColor fill = mFillColorButton->color();
403  double newOpacity = hasFillOpacityParam ? fill.alphaF() : 1.0;
404  if ( hasDefaultFillColor )
405  {
406  fill = defaultFill;
407  }
408  fill.setAlphaF( hasDefaultFillOpacity ? defaultFillOpacity : newOpacity );
409  mFillColorButton->setColor( fill );
410  }
411  mFillColorButton->setEnabled( hasFillParam );
412  mFillColorButton->setAllowOpacity( hasFillOpacityParam );
413  if ( resetValues )
414  {
415  QColor stroke = mStrokeColorButton->color();
416  double newOpacity = hasStrokeOpacityParam ? stroke.alphaF() : 1.0;
417  if ( hasDefaultStrokeColor )
418  {
419  stroke = defaultStroke;
420  }
421  stroke.setAlphaF( hasDefaultStrokeOpacity ? defaultStrokeOpacity : newOpacity );
422  mStrokeColorButton->setColor( stroke );
423  }
424  mStrokeColorButton->setEnabled( hasStrokeParam );
425  mStrokeColorButton->setAllowOpacity( hasStrokeOpacityParam );
426  if ( hasDefaultStrokeWidth && resetValues )
427  {
428  mStrokeWidthSpinBox->setValue( defaultStrokeWidth );
429  }
430  mStrokeWidthSpinBox->setEnabled( hasStrokeWidthParam );
431 }
432 
433 void QgsLayoutPictureWidget::mFillColorButton_colorChanged( const QColor &color )
434 {
435  mPicture->beginCommand( tr( "Change Picture Fill Color" ), QgsLayoutItem::UndoPictureFillColor );
436  mPicture->setSvgFillColor( color );
437  mPicture->endCommand();
438  mPicture->update();
439 }
440 
441 void QgsLayoutPictureWidget::mStrokeColorButton_colorChanged( const QColor &color )
442 {
443  mPicture->beginCommand( tr( "Change Picture Stroke Color" ), QgsLayoutItem::UndoPictureStrokeColor );
444  mPicture->setSvgStrokeColor( color );
445  mPicture->endCommand();
446  mPicture->update();
447 }
448 
449 void QgsLayoutPictureWidget::mStrokeWidthSpinBox_valueChanged( double d )
450 {
451  mPicture->beginCommand( tr( "Change Picture Stroke Width" ), QgsLayoutItem::UndoPictureStrokeWidth );
452  mPicture->setSvgStrokeWidth( d );
453  mPicture->endCommand();
454  mPicture->update();
455 }
456 
457 void QgsLayoutPictureWidget::mPictureRotationOffsetSpinBox_valueChanged( double d )
458 {
459  mPicture->beginCommand( tr( "Change Picture North Offset" ), QgsLayoutItem::UndoPictureNorthOffset );
460  mPicture->setNorthOffset( d );
461  mPicture->endCommand();
462  mPicture->update();
463 }
464 
465 void QgsLayoutPictureWidget::mNorthTypeComboBox_currentIndexChanged( int index )
466 {
467  mPicture->beginCommand( tr( "Change Picture North Mode" ) );
468  mPicture->setNorthMode( static_cast< QgsLayoutItemPicture::NorthMode >( mNorthTypeComboBox->itemData( index ).toInt() ) );
469  mPicture->endCommand();
470  mPicture->update();
471 }
472 
473 void QgsLayoutPictureWidget::modeChanged()
474 {
476  if ( mPicture && mPicture->mode() != newFormat )
477  {
478  whileBlocking( mSvgSourceLineEdit )->setSource( QString() );
479  whileBlocking( mImageSourceLineEdit )->setSource( QString() );
480  mPicture->beginCommand( tr( "Change Picture Type" ) );
481  mPicture->setPicturePath( QString(), newFormat );
482  mPicture->endCommand();
483  }
484  updatePictureTypeWidgets();
485 }
486 
487 void QgsLayoutPictureWidget::updatePictureTypeWidgets()
488 {
489  mRasterFrame->setVisible( mRadioRaster->isChecked() );
490  mSVGFrame->setVisible( mRadioSVG->isChecked() );
491  mSVGParamsGroupBox->setVisible( mRadioSVG->isChecked() );
492 
493  // need to move the data defined button to the appropriate frame -- we can't have two buttons linked to the one property!
494  if ( mRadioSVG->isChecked() )
495  mSvgDDBtnFrame->layout()->addWidget( mSourceDDBtn );
496  else
497  mRasterDDBtnFrame->layout()->addWidget( mSourceDDBtn );
498 }
499 
500 void QgsLayoutPictureWidget::populateList()
501 {
502  QAbstractItemModel *oldModel = viewGroups->model();
504  viewGroups->setModel( g );
505  delete oldModel;
506 
507  // Set the tree expanded at the first level
508  int rows = g->rowCount( g->indexFromItem( g->invisibleRootItem() ) );
509  for ( int i = 0; i < rows; i++ )
510  {
511  viewGroups->setExpanded( g->indexFromItem( g->item( i ) ), true );
512  }
513 
514  // Initially load the icons in the List view without any grouping
515  oldModel = viewImages->model();
516  QgsSvgSelectorListModel *m = new QgsSvgSelectorListModel( viewImages, mIconSize );
517  viewImages->setModel( m );
518 
519  delete oldModel;
520 }
521 
522 void QgsLayoutPictureWidget::populateIcons( const QModelIndex &idx )
523 {
524  QString path = idx.data( Qt::UserRole + 1 ).toString();
525 
526  QAbstractItemModel *oldModel = viewImages->model();
527  QgsSvgSelectorListModel *m = new QgsSvgSelectorListModel( viewImages, path, mIconSize );
528  viewImages->setModel( m );
529  delete oldModel;
530 
531  connect( viewImages->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsLayoutPictureWidget::setSvgName );
532 }
533 
534 void QgsLayoutPictureWidget::setSvgName( const QModelIndex &idx )
535 {
536  if ( mBlockSvgModelChanges )
537  return;
538 
539  QString name = idx.data( Qt::UserRole ).toString();
540  whileBlocking( mSvgSourceLineEdit )->setSource( name );
541  svgSourceChanged( name );
542 }
543 
544 void QgsLayoutPictureWidget::svgSourceChanged( const QString &source )
545 {
546  if ( mPicture )
547  {
548  mPicture->beginCommand( tr( "Change Picture" ) );
549  mPicture->setPicturePath( source, QgsLayoutItemPicture::FormatSVG );
550  mPicture->update();
551  mPicture->endCommand();
552  updateSvgParamGui();
553  }
554 }
555 
556 void QgsLayoutPictureWidget::rasterSourceChanged( const QString &source )
557 {
558  if ( mPicture )
559  {
560  mPicture->beginCommand( tr( "Change Picture" ) );
561  mPicture->setPicturePath( source, QgsLayoutItemPicture::FormatRaster );
562  mPicture->update();
563  mPicture->endCommand();
564  }
565 }
566 
568 {
569  updateDataDefinedButton( mSourceDDBtn );
570  updateDataDefinedButton( mFillColorDDBtn );
571  updateDataDefinedButton( mStrokeColorDDBtn );
572  updateDataDefinedButton( mStrokeWidthDDBtn );
573 
574  //initial state of controls - disable related controls when dd buttons are active
575  mImageSourceLineEdit->setEnabled( !mSourceDDBtn->isActive() );
576  mSvgSourceLineEdit->setEnabled( !mSourceDDBtn->isActive() );
577 }
578 
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition: qgis.h:183
void sourceChanged(const QString &source)
Emitted whenever the file source is changed in the widget.
static QgsSvgCache * svgCache()
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement w...
void colorChanged(const QColor &color)
Emitted whenever a new color is set for the button.
A base class for property widgets for layout items.
void updateDataDefinedButton(QgsPropertyOverrideButton *button)
Updates a previously registered data defined button to reflect the item's current properties.
void registerDataDefinedButton(QgsPropertyOverrideButton *button, QgsLayoutObject::DataDefinedProperty property)
Registers a data defined button, setting up its initial value, connections and description.
void itemChanged(QgsLayoutItem *item)
Emitted whenever the currently selected item changes.
Layout graphical items for displaying a map.
A layout item subclass that displays SVG files or raster format images (jpg, png, ....
void pictureRotationChanged(double newRotation)
Emitted on picture rotation change.
NorthMode
Method for syncing rotation to a map's North direction.
@ GridNorth
Align to grid north.
@ TrueNorth
Align to true north.
ResizeMode
Controls how pictures are scaled within the item's frame.
@ FrameToImageSize
Sets size of frame to match original size of image without scaling.
@ ZoomResizeFrame
Enlarges image to fit frame, then resizes frame to fit resultant image.
@ Clip
Draws image at original size and clips any portion which falls outside frame.
@ Stretch
Stretches image to fit frame, ignores aspect ratio.
@ Zoom
Enlarges image to fit frame while maintaining aspect ratio of picture.
Format
Format of source image.
A widget for controlling the common properties of layout items (e.g.
void setMasterLayout(QgsMasterLayoutInterface *masterLayout)
Sets the master layout associated with the item.
void setItem(QgsLayoutItem *item)
Sets the layout item.
Base class for graphical items within a QgsLayout.
@ UndoPictureStrokeWidth
Picture stroke width.
@ UndoPictureRotation
Picture rotation.
@ UndoPictureFillColor
Picture fill color.
@ UndoPictureNorthOffset
Picture north offset.
@ UndoPictureStrokeColor
Picture stroke color.
ReferencePoint
Fixed position reference point.
@ LowerMiddle
Lower center of item.
@ MiddleLeft
Middle left of item.
@ Middle
Center of item.
@ UpperRight
Upper right corner of item.
@ LowerLeft
Lower left corner of item.
@ UpperLeft
Upper left corner of item.
@ UpperMiddle
Upper center of item.
@ MiddleRight
Middle right of item.
@ LowerRight
Lower right corner of item.
int type() const override
Returns a unique graphics item type identifier.
void changed()
Emitted when the object's properties change.
@ PictureSvgStrokeColor
SVG stroke color.
@ PictureSvgStrokeWidth
SVG stroke width.
@ PictureSvgBackgroundColor
SVG background color.
@ PictureSource
Picture source url.
QgsLayoutPictureWidget(QgsLayoutItemPicture *picture)
constructor
bool setNewItem(QgsLayoutItem *item) override
Attempts to update the widget to show the properties for the specified item.
void populateDataDefinedButtons()
Initializes data defined buttons to current atlas coverage layer.
void setMasterLayout(QgsMasterLayoutInterface *masterLayout) override
Sets the master layout associated with the item.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:50
Interface for master layout type objects, such as print layouts and reports.
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
void containsParams(const QString &path, bool &hasFillParam, QColor &defaultFillColor, bool &hasStrokeParam, QColor &defaultStrokeColor, bool &hasStrokeWidthParam, double &defaultStrokeWidth, bool blocking=false) const
Tests if an SVG file contains parameters for fill, stroke color, stroke width.
A model for displaying SVG search paths.
A model for displaying SVG files with a preview icon.
void sourceChanged(const QString &source)
Emitted whenever the SVG source is changed in the widget.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:263