QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgslayoutitemwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayoutitemwidget.cpp
3  ------------------------
4  Date : July 2017
5  Copyright : (C) 2017 Nyall Dawson
6  Email : nyall dot dawson at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgslayoutitemwidget.h"
18 #include "qgslayout.h"
19 #include "qgsproject.h"
20 #include "qgslayoutundostack.h"
21 #include "qgsprintlayout.h"
22 #include "qgslayoutatlas.h"
23 
24 #include <QButtonGroup>
25 
26 //
27 // QgsLayoutConfigObject
28 //
29 
31  : QObject( parent )
32  , mLayoutObject( layoutObject )
33 {
34  if ( mLayoutObject->layout() )
35  {
36  connect( &mLayoutObject->layout()->reportContext(), &QgsLayoutReportContext::layerChanged,
37  this, [ = ] { updateDataDefinedButtons(); } );
38  }
39  if ( layoutAtlas() )
40  {
41  connect( layoutAtlas(), &QgsLayoutAtlas::toggled, this, &QgsLayoutConfigObject::updateDataDefinedButtons );
42  }
43 }
44 
45 void QgsLayoutConfigObject::updateDataDefinedProperty()
46 {
47  //match data defined button to item's data defined property
48  QgsPropertyOverrideButton *ddButton = qobject_cast<QgsPropertyOverrideButton *>( sender() );
49  if ( !ddButton )
50  {
51  return;
52  }
54 
55  if ( ddButton->propertyKey() >= 0 )
56  key = static_cast< QgsLayoutObject::DataDefinedProperty >( ddButton->propertyKey() );
57 
58  if ( key == QgsLayoutObject::NoProperty )
59  {
60  return;
61  }
62 
63  //set the data defined property and refresh the item
64  if ( mLayoutObject )
65  {
66  mLayoutObject->dataDefinedProperties().setProperty( key, ddButton->toProperty() );
67  mLayoutObject->refresh();
68  }
69 }
70 
71 void QgsLayoutConfigObject::updateDataDefinedButtons()
72 {
73  const QList< QgsPropertyOverrideButton * > buttons = findChildren< QgsPropertyOverrideButton * >();
74  for ( QgsPropertyOverrideButton *button : buttons )
75  {
76  button->setVectorLayer( coverageLayer() );
77  }
78 }
79 
81 {
82  button->blockSignals( true );
83  button->init( key, mLayoutObject->dataDefinedProperties(), QgsLayoutObject::propertyDefinitions(), coverageLayer() );
84  connect( button, &QgsPropertyOverrideButton::changed, this, &QgsLayoutConfigObject::updateDataDefinedProperty, Qt::UniqueConnection );
85  button->registerExpressionContextGenerator( mLayoutObject );
86  button->blockSignals( false );
87 }
88 
90 {
91  if ( !button )
92  return;
93 
94  if ( button->propertyKey() < 0 || !mLayoutObject )
95  return;
96 
98  whileBlocking( button )->setToProperty( mLayoutObject->dataDefinedProperties().property( key ) );
99 
100  // In case the button was initialized to a different config object, we need to reconnect to it here (see https://issues.qgis.org/issues/18694 )
101  connect( button, &QgsPropertyOverrideButton::changed, this, &QgsLayoutConfigObject::updateDataDefinedProperty, Qt::UniqueConnection );
102  button->registerExpressionContextGenerator( mLayoutObject );
103 }
104 
106 {
107  if ( !mLayoutObject )
108  {
109  return nullptr;
110  }
111 
112  QgsPrintLayout *printLayout = qobject_cast< QgsPrintLayout * >( mLayoutObject->layout() );
113 
114  if ( !printLayout )
115  {
116  return nullptr;
117  }
118 
119  return printLayout->atlas();
120 }
121 
123 {
124  mLayoutObject = object;
125 }
126 
128 {
129  if ( !mLayoutObject )
130  return nullptr;
131 
132  QgsLayout *layout = mLayoutObject->layout();
133  if ( !layout )
134  return nullptr;
135 
136  return layout->reportContext().layer();
137 }
138 
139 
140 //
141 // QgsLayoutItemBaseWidget
142 //
143 
145  : QgsPanelWidget( parent )
146  , mConfigObject( new QgsLayoutConfigObject( this, layoutObject ) )
147  , mObject( layoutObject )
148 {
149 
150 }
151 
153 {
154  return mObject;
155 }
156 
158 {
159  QgsLayoutObject *oldObject = mObject;
160  QgsLayoutConfigObject *oldConfigObject = mConfigObject;
161  // have to set new mObject/mConfigObject here, because setNewItem methods require access to them
162  mObject = item;
163  mConfigObject = new QgsLayoutConfigObject( this, mObject );
164  if ( setNewItem( item ) )
165  {
166  oldConfigObject->deleteLater();
167  return true;
168  }
169  else
170  {
171  // revert object change since it was unsuccessful
172  mObject = oldObject;
173  mConfigObject->deleteLater();
174  mConfigObject = oldConfigObject;
175  return false;
176  }
177 }
178 
180 {
181 }
182 
184 {
185  mConfigObject->initializeDataDefinedButton( button, property );
186 }
187 
189 {
190  mConfigObject->updateDataDefinedButton( button );
191 }
192 
194 {
195  return mConfigObject->coverageLayer();
196 }
197 
199 {
200  return false;
201 }
202 
204 {
205  return mConfigObject->layoutAtlas();
206 }
207 
208 //
209 
210 
211 //QgsLayoutItemPropertiesWidget
212 
213 void QgsLayoutItemPropertiesWidget::updateVariables()
214 {
215  if ( !mItem )
216  return;
217 
218  mBlockVariableUpdates = true;
219  QgsExpressionContext context = mItem->createExpressionContext();
220  mVariableEditor->setContext( &context );
221  int editableIndex = context.indexOfScope( tr( "Layout Item" ) );
222  if ( editableIndex >= 0 )
223  mVariableEditor->setEditableScopeIndex( editableIndex );
224  mBlockVariableUpdates = false;
225 }
226 
228  : QWidget( parent )
229  , mConfigObject( new QgsLayoutConfigObject( this, item ) )
230 {
231  setupUi( this );
232 
233  mVariableEditor->setMinimumHeight( mVariableEditor->fontMetrics().height() * 15 );
234 
235  mItemRotationSpinBox->setClearValue( 0 );
236  mStrokeUnitsComboBox->linkToWidget( mStrokeWidthSpinBox );
237  mStrokeUnitsComboBox->setConverter( &item->layout()->renderContext().measurementConverter() );
238 
239  mPosUnitsComboBox->linkToWidget( mXPosSpin );
240  mPosUnitsComboBox->linkToWidget( mYPosSpin );
241  mSizeUnitsComboBox->linkToWidget( mWidthSpin );
242  mSizeUnitsComboBox->linkToWidget( mHeightSpin );
243 
244  mPosUnitsComboBox->setConverter( &item->layout()->renderContext().measurementConverter() );
245  mSizeUnitsComboBox->setConverter( &item->layout()->renderContext().measurementConverter() );
246 
247  mPosLockAspectRatio->setWidthSpinBox( mXPosSpin );
248  mPosLockAspectRatio->setHeightSpinBox( mYPosSpin );
249  mSizeLockAspectRatio->setWidthSpinBox( mWidthSpin );
250  mSizeLockAspectRatio->setHeightSpinBox( mHeightSpin );
251 
252  connect( mFrameColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutItemPropertiesWidget::mFrameColorButton_colorChanged );
253  connect( mBackgroundColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutItemPropertiesWidget::mBackgroundColorButton_colorChanged );
254  connect( mStrokeWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutItemPropertiesWidget::mStrokeWidthSpinBox_valueChanged );
255  connect( mStrokeUnitsComboBox, &QgsLayoutUnitsComboBox::changed, this, &QgsLayoutItemPropertiesWidget::strokeUnitChanged );
256  connect( mFrameGroupBox, &QgsCollapsibleGroupBoxBasic::toggled, this, &QgsLayoutItemPropertiesWidget::mFrameGroupBox_toggled );
257  connect( mFrameJoinStyleCombo, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutItemPropertiesWidget::mFrameJoinStyleCombo_currentIndexChanged );
258  connect( mBackgroundGroupBox, &QgsCollapsibleGroupBoxBasic::toggled, this, &QgsLayoutItemPropertiesWidget::mBackgroundGroupBox_toggled );
259  connect( mItemIdLineEdit, &QLineEdit::editingFinished, this, &QgsLayoutItemPropertiesWidget::mItemIdLineEdit_editingFinished );
260  connect( mPageSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsLayoutItemPropertiesWidget::mPageSpinBox_valueChanged );
261  connect( mXPosSpin, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutItemPropertiesWidget::mXPosSpin_valueChanged );
262  connect( mYPosSpin, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutItemPropertiesWidget::mYPosSpin_valueChanged );
263  connect( mPosUnitsComboBox, &QgsLayoutUnitsComboBox::changed, this, &QgsLayoutItemPropertiesWidget::positionUnitsChanged );
264  connect( mWidthSpin, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutItemPropertiesWidget::mWidthSpin_valueChanged );
265  connect( mHeightSpin, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutItemPropertiesWidget::mHeightSpin_valueChanged );
266  connect( mSizeUnitsComboBox, &QgsLayoutUnitsComboBox::changed, this, &QgsLayoutItemPropertiesWidget::sizeUnitsChanged );
267  connect( mUpperLeftRadioButton, &QRadioButton::toggled, this, &QgsLayoutItemPropertiesWidget::mUpperLeftCheckBox_stateChanged );
268  connect( mUpperMiddleRadioButton, &QRadioButton::toggled, this, &QgsLayoutItemPropertiesWidget::mUpperMiddleCheckBox_stateChanged );
269  connect( mUpperRightRadioButton, &QRadioButton::toggled, this, &QgsLayoutItemPropertiesWidget::mUpperRightCheckBox_stateChanged );
270  connect( mMiddleLeftRadioButton, &QRadioButton::toggled, this, &QgsLayoutItemPropertiesWidget::mMiddleLeftCheckBox_stateChanged );
271  connect( mMiddleRadioButton, &QRadioButton::toggled, this, &QgsLayoutItemPropertiesWidget::mMiddleCheckBox_stateChanged );
272  connect( mMiddleRightRadioButton, &QRadioButton::toggled, this, &QgsLayoutItemPropertiesWidget::mMiddleRightCheckBox_stateChanged );
273  connect( mLowerLeftRadioButton, &QRadioButton::toggled, this, &QgsLayoutItemPropertiesWidget::mLowerLeftCheckBox_stateChanged );
274  connect( mLowerMiddleRadioButton, &QRadioButton::toggled, this, &QgsLayoutItemPropertiesWidget::mLowerMiddleCheckBox_stateChanged );
275  connect( mLowerRightRadioButton, &QRadioButton::toggled, this, &QgsLayoutItemPropertiesWidget::mLowerRightCheckBox_stateChanged );
276  connect( mBlendModeCombo, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutItemPropertiesWidget::mBlendModeCombo_currentIndexChanged );
277  connect( mItemRotationSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutItemPropertiesWidget::mItemRotationSpinBox_valueChanged );
278  connect( mExcludeFromPrintsCheckBox, &QCheckBox::toggled, this, &QgsLayoutItemPropertiesWidget::mExcludeFromPrintsCheckBox_toggled );
279 
280  //make button exclusive
281  QButtonGroup *buttonGroup = new QButtonGroup( this );
282  buttonGroup->addButton( mUpperLeftRadioButton );
283  buttonGroup->addButton( mUpperMiddleRadioButton );
284  buttonGroup->addButton( mUpperRightRadioButton );
285  buttonGroup->addButton( mMiddleLeftRadioButton );
286  buttonGroup->addButton( mMiddleRadioButton );
287  buttonGroup->addButton( mMiddleRightRadioButton );
288  buttonGroup->addButton( mLowerLeftRadioButton );
289  buttonGroup->addButton( mLowerMiddleRadioButton );
290  buttonGroup->addButton( mLowerRightRadioButton );
291  buttonGroup->setExclusive( true );
292 
294 
295  setItem( item );
296 
297  connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsLayoutItemPropertiesWidget::opacityChanged );
298 
299  updateVariables();
300  connect( mVariableEditor, &QgsVariableEditorWidget::scopeChanged, this, [ = ]
301  {
302  if ( !mBlockVariableUpdates )
303  QgsLayoutItemPropertiesWidget::variablesChanged();
304  } );
305  // listen out for variable edits
306  connect( QgsApplication::instance(), &QgsApplication::customVariablesChanged, this, &QgsLayoutItemPropertiesWidget::updateVariables );
307  connect( item->layout()->project(), &QgsProject::customVariablesChanged, this, &QgsLayoutItemPropertiesWidget::updateVariables );
308 
309  if ( item->layout() )
310  connect( item->layout(), &QgsLayout::variablesChanged, this, &QgsLayoutItemPropertiesWidget::updateVariables );
311 }
312 
314 {
315  mBackgroundGroupBox->setVisible( showGroup );
316 }
317 
319 {
320  mFrameGroupBox->setVisible( showGroup );
321 }
322 
324 {
325  if ( mItem )
326  {
327  disconnect( mItem, &QgsLayoutItem::sizePositionChanged, this, &QgsLayoutItemPropertiesWidget::setValuesForGuiPositionElements );
328  disconnect( mItem, &QgsLayoutObject::changed, this, &QgsLayoutItemPropertiesWidget::setValuesForGuiNonPositionElements );
329  }
330  mItem = item;
331  if ( mItem )
332  {
333  connect( mItem, &QgsLayoutItem::sizePositionChanged, this, &QgsLayoutItemPropertiesWidget::setValuesForGuiPositionElements );
334  connect( mItem, &QgsLayoutObject::changed, this, &QgsLayoutItemPropertiesWidget::setValuesForGuiNonPositionElements );
335  }
336 
337  mConfigObject->setObject( mItem );
338 
339  setValuesForGuiElements();
340 }
341 
342 //slots
343 
344 void QgsLayoutItemPropertiesWidget::mFrameColorButton_colorChanged( const QColor &newFrameColor )
345 {
346  if ( !mItem )
347  {
348  return;
349  }
350  mItem->layout()->undoStack()->beginCommand( mItem, tr( "Change Frame Color" ), QgsLayoutItem::UndoStrokeColor );
351  mItem->setFrameStrokeColor( newFrameColor );
352  mItem->layout()->undoStack()->endCommand();
353  mItem->update();
354 }
355 
356 void QgsLayoutItemPropertiesWidget::mBackgroundColorButton_colorChanged( const QColor &newBackgroundColor )
357 {
358  if ( !mItem )
359  {
360  return;
361  }
362  mItem->layout()->undoStack()->beginCommand( mItem, tr( "Change Background Color" ), QgsLayoutItem::UndoBackgroundColor );
363  mItem->setBackgroundColor( newBackgroundColor );
364  mItem->layout()->undoStack()->endCommand();
365  mItem->invalidateCache();
366 }
367 
368 void QgsLayoutItemPropertiesWidget::changeItemPosition()
369 {
370  if ( !mItem )
371  return;
372 
373  mItem->layout()->undoStack()->beginCommand( mItem, tr( "Move Item" ), QgsLayoutItem::UndoIncrementalMove );
374 
375  QgsLayoutPoint point( mXPosSpin->value(), mYPosSpin->value(), mPosUnitsComboBox->unit() );
376  mItem->attemptMove( point, true, false, mPageSpinBox->value() - 1 );
377 
378  mItem->layout()->undoStack()->endCommand();
379 }
380 
381 void QgsLayoutItemPropertiesWidget::changeItemReference( QgsLayoutItem::ReferencePoint point )
382 {
383  if ( !mItem )
384  return;
385 
386  mItem->layout()->undoStack()->beginCommand( mItem, tr( "Change Item Reference" ) );
387  mItem->setReferencePoint( point );
388  mItem->layout()->undoStack()->endCommand();
389 }
390 
391 void QgsLayoutItemPropertiesWidget::changeItemSize()
392 {
393  if ( !mItem )
394  return;
395 
396  mItem->layout()->undoStack()->beginCommand( mItem, tr( "Resize Item" ), QgsLayoutItem::UndoIncrementalResize );
397 
398  QgsLayoutSize size( mWidthSpin->value(), mHeightSpin->value(), mSizeUnitsComboBox->unit() );
399  mItem->attemptResize( size );
400 
401  mItem->layout()->undoStack()->endCommand();
402 }
403 
404 void QgsLayoutItemPropertiesWidget::variablesChanged()
405 {
406  if ( !mItem )
407  return;
408 
409  QgsExpressionContextUtils::setLayoutItemVariables( mItem, mVariableEditor->variablesInActiveScope() );
410 }
411 
413 {
414  if ( mUpperLeftRadioButton->isChecked() )
415  {
417  }
418  else if ( mUpperMiddleRadioButton->isChecked() )
419  {
421  }
422  else if ( mUpperRightRadioButton->isChecked() )
423  {
425  }
426  else if ( mMiddleLeftRadioButton->isChecked() )
427  {
429  }
430  else if ( mMiddleRadioButton->isChecked() )
431  {
432  return QgsLayoutItem::Middle;
433  }
434  else if ( mMiddleRightRadioButton->isChecked() )
435  {
437  }
438  else if ( mLowerLeftRadioButton->isChecked() )
439  {
441  }
442  else if ( mLowerMiddleRadioButton->isChecked() )
443  {
445  }
446  else if ( mLowerRightRadioButton->isChecked() )
447  {
449  }
451 }
452 
453 void QgsLayoutItemPropertiesWidget::mStrokeWidthSpinBox_valueChanged( double d )
454 {
455  if ( !mItem )
456  {
457  return;
458  }
459 
460  mItem->layout()->undoStack()->beginCommand( mItem, tr( "Change Frame Stroke Width" ), QgsLayoutItem::UndoStrokeWidth );
461  mItem->setFrameStrokeWidth( QgsLayoutMeasurement( d, mStrokeUnitsComboBox->unit() ) );
462  mItem->layout()->undoStack()->endCommand();
463 }
464 
465 void QgsLayoutItemPropertiesWidget::strokeUnitChanged( QgsUnitTypes::LayoutUnit unit )
466 {
467  if ( !mItem )
468  {
469  return;
470  }
471 
472  mItem->layout()->undoStack()->beginCommand( mItem, tr( "Change Frame Stroke Width" ), QgsLayoutItem::UndoStrokeWidth );
473  mItem->setFrameStrokeWidth( QgsLayoutMeasurement( mStrokeWidthSpinBox->value(), unit ) );
474  mItem->layout()->undoStack()->endCommand();
475 }
476 
477 void QgsLayoutItemPropertiesWidget::mFrameJoinStyleCombo_currentIndexChanged( int index )
478 {
479  Q_UNUSED( index );
480  if ( !mItem )
481  {
482  return;
483  }
484 
485  mItem->layout()->undoStack()->beginCommand( mItem, tr( "Change Frame Join Style" ) );
486  mItem->setFrameJoinStyle( mFrameJoinStyleCombo->penJoinStyle() );
487  mItem->layout()->undoStack()->endCommand();
488 }
489 
490 void QgsLayoutItemPropertiesWidget::mFrameGroupBox_toggled( bool state )
491 {
492  if ( !mItem )
493  {
494  return;
495  }
496 
497  mItem->layout()->undoStack()->beginCommand( mItem, state ? tr( "Enable Frame" ) : tr( "Disable Frame" ) );
498  mItem->setFrameEnabled( state );
499  mItem->update();
500  mItem->layout()->undoStack()->endCommand();
501 }
502 
503 void QgsLayoutItemPropertiesWidget::mBackgroundGroupBox_toggled( bool state )
504 {
505  if ( !mItem )
506  {
507  return;
508  }
509 
510  mItem->layout()->undoStack()->beginCommand( mItem, state ? tr( "Enable Background" ) : tr( "Disable Background" ) );
511  mItem->setBackgroundEnabled( state );
512  mItem->layout()->undoStack()->endCommand();
513  mItem->invalidateCache();
514 }
515 
516 
517 void QgsLayoutItemPropertiesWidget::setValuesForGuiPositionElements()
518 {
519  if ( !mItem )
520  {
521  return;
522  }
523 
524  auto block = [ = ]( bool blocked )
525  {
526  mXPosSpin->blockSignals( blocked );
527  mYPosSpin->blockSignals( blocked );
528  mPosUnitsComboBox->blockSignals( blocked );
529  mWidthSpin->blockSignals( blocked );
530  mHeightSpin->blockSignals( blocked );
531  mSizeUnitsComboBox->blockSignals( blocked );
532  mUpperLeftRadioButton->blockSignals( blocked );
533  mUpperMiddleRadioButton->blockSignals( blocked );
534  mUpperRightRadioButton->blockSignals( blocked );
535  mMiddleLeftRadioButton->blockSignals( blocked );
536  mMiddleRadioButton->blockSignals( blocked );
537  mMiddleRightRadioButton->blockSignals( blocked );
538  mLowerLeftRadioButton->blockSignals( blocked );
539  mLowerMiddleRadioButton->blockSignals( blocked );
540  mLowerRightRadioButton->blockSignals( blocked );
541  mPageSpinBox->blockSignals( blocked );
542  };
543  block( true );
544 
545  QgsLayoutPoint point = mItem->pagePositionWithUnits();
546 
547  if ( !mFreezeXPosSpin )
548  mXPosSpin->setValue( point.x() );
549  if ( !mFreezeYPosSpin )
550  mYPosSpin->setValue( point.y() );
551  mPosUnitsComboBox->setUnit( point.units() );
552 
553  switch ( mItem->referencePoint() )
554  {
556  {
557  mUpperLeftRadioButton->setChecked( true );
558  break;
559  }
560 
562  {
563  mUpperMiddleRadioButton->setChecked( true );
564  break;
565  }
566 
568  {
569  mUpperRightRadioButton->setChecked( true );
570  break;
571  }
572 
574  {
575  mMiddleLeftRadioButton->setChecked( true );
576  break;
577  }
578 
580  {
581  mMiddleRadioButton->setChecked( true );
582  break;
583  }
584 
586  {
587  mMiddleRightRadioButton->setChecked( true );
588  break;
589  }
590 
592  {
593  mLowerLeftRadioButton->setChecked( true );
594  break;
595  }
596 
598  {
599  mLowerMiddleRadioButton->setChecked( true );
600  break;
601  }
602 
604  {
605  mLowerRightRadioButton->setChecked( true );
606  break;
607  }
608  }
609 
610  QgsLayoutSize size = mItem->sizeWithUnits();
611  if ( !mFreezeWidthSpin )
612  mWidthSpin->setValue( size.width() );
613  if ( !mFreezeHeightSpin )
614  mHeightSpin->setValue( size.height() );
615 
616  mSizeUnitsComboBox->setUnit( size.units() );
617 
618  mSizeLockAspectRatio->resetRatio();
619  mPosLockAspectRatio->resetRatio();
620 
621  if ( !mFreezePageSpin )
622  mPageSpinBox->setValue( mItem->page() + 1 );
623 
624  block( false );
625 }
626 
627 void QgsLayoutItemPropertiesWidget::setValuesForGuiNonPositionElements()
628 {
629  if ( !mItem )
630  {
631  return;
632  }
633 
634  auto block = [ = ]( bool blocked )
635  {
636  mStrokeWidthSpinBox->blockSignals( blocked );
637  mStrokeUnitsComboBox->blockSignals( blocked );
638  mFrameGroupBox->blockSignals( blocked );
639  mBackgroundGroupBox->blockSignals( blocked );
640  mItemIdLineEdit->blockSignals( blocked );
641  mBlendModeCombo->blockSignals( blocked );
642  mOpacityWidget->blockSignals( blocked );
643  mFrameColorButton->blockSignals( blocked );
644  mFrameJoinStyleCombo->blockSignals( blocked );
645  mBackgroundColorButton->blockSignals( blocked );
646  mItemRotationSpinBox->blockSignals( blocked );
647  mExcludeFromPrintsCheckBox->blockSignals( blocked );
648  };
649  block( true );
650 
651  mBackgroundColorButton->setColor( mItem->backgroundColor() );
652  mFrameColorButton->setColor( mItem->frameStrokeColor() );
653  mStrokeUnitsComboBox->setUnit( mItem->frameStrokeWidth().units() );
654  mStrokeWidthSpinBox->setValue( mItem->frameStrokeWidth().length() );
655  mFrameJoinStyleCombo->setPenJoinStyle( mItem->frameJoinStyle() );
656  mItemIdLineEdit->setText( mItem->id() );
657  mFrameGroupBox->setChecked( mItem->frameEnabled() );
658  mBackgroundGroupBox->setChecked( mItem->hasBackground() );
659  mBlendModeCombo->setBlendMode( mItem->blendMode() );
660  mOpacityWidget->setOpacity( mItem->itemOpacity() );
661  mItemRotationSpinBox->setValue( mItem->itemRotation() );
662  mExcludeFromPrintsCheckBox->setChecked( mItem->excludeFromExports() );
663 
664  block( false );
665 }
666 
668 {
669  mConfigObject->initializeDataDefinedButton( mXPositionDDBtn, QgsLayoutObject::PositionX );
670  mConfigObject->initializeDataDefinedButton( mYPositionDDBtn, QgsLayoutObject::PositionY );
671  mConfigObject->initializeDataDefinedButton( mWidthDDBtn, QgsLayoutObject::ItemWidth );
672  mConfigObject->initializeDataDefinedButton( mHeightDDBtn, QgsLayoutObject::ItemHeight );
673  mConfigObject->initializeDataDefinedButton( mItemRotationDDBtn, QgsLayoutObject::ItemRotation );
674  mConfigObject->initializeDataDefinedButton( mOpacityDDBtn, QgsLayoutObject::Opacity );
675  mConfigObject->initializeDataDefinedButton( mBlendModeDDBtn, QgsLayoutObject::BlendMode );
676  mConfigObject->initializeDataDefinedButton( mExcludePrintsDDBtn, QgsLayoutObject::ExcludeFromExports );
677  mConfigObject->initializeDataDefinedButton( mItemFrameColorDDBtn, QgsLayoutObject::FrameColor );
678  mConfigObject->initializeDataDefinedButton( mItemBackgroundColorDDBtn, QgsLayoutObject::BackgroundColor );
679 }
680 
682 {
683  const QList< QgsPropertyOverrideButton * > buttons = findChildren< QgsPropertyOverrideButton * >();
684  for ( QgsPropertyOverrideButton *button : buttons )
685  {
686  mConfigObject->updateDataDefinedButton( button );
687  }
688 }
689 
690 void QgsLayoutItemPropertiesWidget::setValuesForGuiElements()
691 {
692  if ( !mItem )
693  {
694  return;
695  }
696 
697  mBackgroundColorButton->setColorDialogTitle( tr( "Select Background Color" ) );
698  mBackgroundColorButton->setAllowOpacity( true );
699  mBackgroundColorButton->setContext( QStringLiteral( "composer" ) );
700  mFrameColorButton->setColorDialogTitle( tr( "Select Frame Color" ) );
701  mFrameColorButton->setAllowOpacity( true );
702  mFrameColorButton->setContext( QStringLiteral( "composer" ) );
703 
704  setValuesForGuiPositionElements();
705  setValuesForGuiNonPositionElements();
707 
708  updateVariables();
709 }
710 
711 void QgsLayoutItemPropertiesWidget::mBlendModeCombo_currentIndexChanged( int index )
712 {
713  Q_UNUSED( index );
714  if ( mItem )
715  {
716  mItem->layout()->undoStack()->beginCommand( mItem, tr( "Change Blend Mode" ) );
717  mItem->setBlendMode( mBlendModeCombo->blendMode() );
718  mItem->layout()->undoStack()->endCommand();
719  }
720 }
721 
722 void QgsLayoutItemPropertiesWidget::opacityChanged( double value )
723 {
724  if ( mItem )
725  {
726  mItem->layout()->undoStack()->beginCommand( mItem, tr( "Change Opacity" ), QgsLayoutItem::UndoOpacity );
727  mItem->setItemOpacity( value );
728  mItem->layout()->undoStack()->endCommand();
729  }
730 }
731 
732 void QgsLayoutItemPropertiesWidget::mItemIdLineEdit_editingFinished()
733 {
734  if ( mItem )
735  {
736  mItem->layout()->undoStack()->beginCommand( mItem, tr( "Change Item ID" ), QgsLayoutItem::UndoSetId );
737  mItem->setId( mItemIdLineEdit->text() );
738  mItemIdLineEdit->setText( mItem->id() );
739  mItem->layout()->undoStack()->endCommand();
740  }
741 }
742 
743 void QgsLayoutItemPropertiesWidget::mPageSpinBox_valueChanged( int )
744 {
745  mFreezePageSpin = true;
746  changeItemPosition();
747  mFreezePageSpin = false;
748 }
749 
750 void QgsLayoutItemPropertiesWidget::mXPosSpin_valueChanged( double )
751 {
752  mFreezeXPosSpin = true;
753  changeItemPosition();
754  mFreezeXPosSpin = false;
755 }
756 
757 void QgsLayoutItemPropertiesWidget::mYPosSpin_valueChanged( double )
758 {
759  mFreezeYPosSpin = true;
760  changeItemPosition();
761  mFreezeYPosSpin = false;
762 }
763 
764 void QgsLayoutItemPropertiesWidget::positionUnitsChanged( QgsUnitTypes::LayoutUnit )
765 {
766  changeItemPosition();
767 }
768 
769 void QgsLayoutItemPropertiesWidget::mWidthSpin_valueChanged( double )
770 {
771  mFreezeWidthSpin = true;
772  changeItemSize();
773  mFreezeWidthSpin = false;
774 }
775 
776 void QgsLayoutItemPropertiesWidget::mHeightSpin_valueChanged( double )
777 {
778  mFreezeHeightSpin = true;
779  changeItemSize();
780  mFreezeHeightSpin = false;
781 }
782 
783 void QgsLayoutItemPropertiesWidget::sizeUnitsChanged( QgsUnitTypes::LayoutUnit )
784 {
785  changeItemSize();
786 }
787 
788 void QgsLayoutItemPropertiesWidget::mUpperLeftCheckBox_stateChanged( bool state )
789 {
790  if ( !state )
791  return;
792 
793  if ( mItem )
794  {
795  changeItemReference( QgsLayoutItem::UpperLeft );
796  }
797  setValuesForGuiPositionElements();
798 }
799 
800 void QgsLayoutItemPropertiesWidget::mUpperMiddleCheckBox_stateChanged( bool state )
801 {
802  if ( !state )
803  return;
804  if ( mItem )
805  {
806  changeItemReference( QgsLayoutItem::UpperMiddle );
807  }
808  setValuesForGuiPositionElements();
809 }
810 
811 void QgsLayoutItemPropertiesWidget::mUpperRightCheckBox_stateChanged( bool state )
812 {
813  if ( !state )
814  return;
815  if ( mItem )
816  {
817  changeItemReference( QgsLayoutItem::UpperRight );
818  }
819  setValuesForGuiPositionElements();
820 }
821 
822 void QgsLayoutItemPropertiesWidget::mMiddleLeftCheckBox_stateChanged( bool state )
823 {
824  if ( !state )
825  return;
826  if ( mItem )
827  {
828  changeItemReference( QgsLayoutItem::MiddleLeft );
829  }
830  setValuesForGuiPositionElements();
831 }
832 
833 void QgsLayoutItemPropertiesWidget::mMiddleCheckBox_stateChanged( bool state )
834 {
835  if ( !state )
836  return;
837  if ( mItem )
838  {
839  changeItemReference( QgsLayoutItem::Middle );
840  }
841  setValuesForGuiPositionElements();
842 }
843 
844 void QgsLayoutItemPropertiesWidget::mMiddleRightCheckBox_stateChanged( bool state )
845 {
846  if ( !state )
847  return;
848  if ( mItem )
849  {
850  changeItemReference( QgsLayoutItem::MiddleRight );
851  }
852  setValuesForGuiPositionElements();
853 }
854 
855 void QgsLayoutItemPropertiesWidget::mLowerLeftCheckBox_stateChanged( bool state )
856 {
857  if ( !state )
858  return;
859  if ( mItem )
860  {
861  changeItemReference( QgsLayoutItem::LowerLeft );
862  }
863  setValuesForGuiPositionElements();
864 }
865 
866 void QgsLayoutItemPropertiesWidget::mLowerMiddleCheckBox_stateChanged( bool state )
867 {
868  if ( !state )
869  return;
870  if ( mItem )
871  {
872  changeItemReference( QgsLayoutItem::LowerMiddle );
873  }
874  setValuesForGuiPositionElements();
875 }
876 
877 void QgsLayoutItemPropertiesWidget::mLowerRightCheckBox_stateChanged( bool state )
878 {
879  if ( !state )
880  return;
881  if ( mItem )
882  {
883  changeItemReference( QgsLayoutItem::LowerRight );
884  }
885  setValuesForGuiPositionElements();
886 }
887 
888 void QgsLayoutItemPropertiesWidget::mItemRotationSpinBox_valueChanged( double val )
889 {
890  if ( mItem )
891  {
892  mItem->layout()->undoStack()->beginCommand( mItem, tr( "Rotate" ), QgsLayoutItem::UndoRotation );
893  mItem->setItemRotation( val, true );
894  mItem->update();
895  mItem->layout()->undoStack()->endCommand();
896  }
897 }
898 
899 void QgsLayoutItemPropertiesWidget::mExcludeFromPrintsCheckBox_toggled( bool checked )
900 {
901  if ( mItem )
902  {
903  mItem->layout()->undoStack()->beginCommand( mItem, checked ? tr( "Exclude from Exports" ) : tr( "Include in Exports" ) );
904  mItem->setExcludeFromExports( checked );
905  mItem->layout()->undoStack()->endCommand();
906  }
907 }
void populateDataDefinedButtons()
Sets data defined button state to match item.
static void setLayoutItemVariables(QgsLayoutItem *item, const QVariantMap &variables)
Sets all layout item context variables for an item.
Base class for graphical items within a QgsLayout.
Lower left corner of item.
void showBackgroundGroup(bool showGroup)
Determines if the background of the group box shall be shown.
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
void customVariablesChanged()
Emitted whenever a custom global variable changes.
int propertyKey() const
Returns the property key linked to the button.
QgsUnitTypes::LayoutUnit units() const
Returns the units for the size.
Exclude item from exports.
Upper center of item.
Y position on page.
double x() const
Returns x coordinate of point.
Base class for any widget that can be shown as a inline panel.
void toggled(bool)
Emitted when atlas is enabled or disabled.
QgsLayoutConfigObject(QWidget *parent SIP_TRANSFERTHIS, QgsLayoutObject *layoutObject)
Constructor for QgsLayoutConfigObject, linked with the specified layoutObject.
Opacity adjustment.
void updateDataDefinedButton(QgsPropertyOverrideButton *button)
Updates a previously registered data defined button to reflect the item&#39;s current properties...
Lower right corner of item.
int indexOfScope(QgsExpressionContextScope *scope) const
Returns the index of the specified scope if it exists within the context.
const QgsLayoutMeasurementConverter & measurementConverter() const
Returns the layout measurement converter to be used in the layout.
double height() const
Returns the height of the size.
Definition: qgslayoutsize.h:90
QgsLayoutRenderContext & renderContext()
Returns a reference to the layout&#39;s render context, which stores information relating to the current ...
Definition: qgslayout.cpp:356
void initializeDataDefinedButtons()
Initializes data defined buttons to current atlas coverage layer.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the layout object property definitions.
This class provides a method of storing points, consisting of an x and y coordinate, for use in QGIS layouts.
void registerDataDefinedButton(QgsPropertyOverrideButton *button, QgsLayoutObject::DataDefinedProperty property)
Registers a data defined button, setting up its initial value, connections and description.
ReferencePoint
Fixed position reference point.
void scopeChanged()
Emitted when the user has modified a scope using the widget.
void sizePositionChanged()
Emitted when the item&#39;s size or position changes.
X position on page.
double width() const
Returns the width of the size.
Definition: qgslayoutsize.h:76
QgsLayoutItemBaseWidget(QWidget *parent SIP_TRANSFERTHIS, QgsLayoutObject *layoutObject)
Constructor for QgsLayoutItemBaseWidget, linked with the specified layoutObject.
A button for controlling property overrides which may apply to a widget.
QgsLayoutAtlas * layoutAtlas() const
Returns the atlas for the layout (if available)
void variablesChanged()
Emitted whenever the expression variables stored in the layout have been changed. ...
This class provides a method of storing measurements for use in QGIS layouts using a variety of diffe...
Upper right corner of item.
Lower center of item.
void registerExpressionContextGenerator(QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
void opacityChanged(double opacity)
Emitted when the opacity is changed in the widget, where opacity ranges from 0.0 (transparent) to 1...
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Middle right of item.
virtual void setReportTypeString(const QString &string)
Sets the string to use to describe the current report type (e.g.
Class used to render QgsLayout as an atlas, by iterating over the features from an associated vector ...
void showFrameGroup(bool showGroup)
Determines if the frame of the group box shall be shown.
void initializeDataDefinedButton(QgsPropertyOverrideButton *button, QgsLayoutObject::DataDefinedProperty key)
Registers a data defined button, setting up its initial value, connections and description.
void setObject(QgsLayoutObject *object) SIP_SKIP
Links a new layout object to this QgsLayoutConfigObject.
QgsVectorLayer * coverageLayer() const
Returns the current layout context coverage layer (if set).
void layerChanged(QgsVectorLayer *layer)
Emitted when the context&#39;s layer is changed.
void updateDataDefinedButton(QgsPropertyOverrideButton *button)
Updates a data defined button to reflect the item&#39;s current properties.
void changed(QgsUnitTypes::LayoutUnit unit)
Emitted when the unit is changed.
Upper left corner of item.
QgsLayoutItem::ReferencePoint positionMode() const
Returns the position mode.
QgsLayoutAtlas * atlas()
Returns the print layout&#39;s atlas.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:49
QgsLayoutAtlas * layoutAtlas() const
Returns the atlas for the layout, if available.
QgsLayoutItemPropertiesWidget(QWidget *parent, QgsLayoutItem *item)
Constructs a QgsLayoutItemPropertiesWidget with a parent and for the given layout item...
Middle left of item.
QgsLayoutReportContext & reportContext()
Returns a reference to the layout&#39;s report context, which stores information relating to the current ...
Definition: qgslayout.cpp:366
void colorChanged(const QColor &color)
Is emitted whenever a new color is set for the button.
void changed()
Emitted when property definition changes.
QgsProperty toProperty() const
Returns a QgsProperty object encapsulating the current state of the widget.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:225
virtual bool setNewItem(QgsLayoutItem *item)
Attempts to update the widget to show the properties for the specified item.
void customVariablesChanged()
Emitted whenever the expression variables stored in the project have been changed.
Center of item.
QgsVectorLayer * coverageLayer() const
Returns the current layout context coverage layer (if set).
An object for property widgets for layout items.
Background color adjustment.
A base class for objects which belong to a layout.
LayoutUnit
Layout measurement units.
Definition: qgsunittypes.h:124
Layout item incremental movement, e.g. as a result of a keypress.
void setItem(QgsLayoutItem *item)
Sets the layout item.
bool setItem(QgsLayoutItem *item)
Sets the current item to show in the widget.
Stroke color adjustment.
const QgsLayout * layout() const
Returns the layout the object is attached to.
Print layout, a QgsLayout subclass for static or atlas-based layouts.
This class provides a method of storing sizes, consisting of a width and height, for use in QGIS layo...
Definition: qgslayoutsize.h:40
void changed()
Emitted when the object&#39;s properties change.
Rotation adjustment.
Represents a vector layer which manages a vector based data sets.
DataDefinedProperty
Data defined properties for different item types.
void init(int propertyKey, const QgsProperty &property, const QgsPropertiesDefinition &definitions, const QgsVectorLayer *layer=nullptr, bool auxiliaryStorageEnabled=false)
Initialize a newly constructed property button (useful if button was included in a UI layout)...
Stroke width adjustment.
QgsUnitTypes::LayoutUnit units() const
Returns the units for the point.
QgsProject * project() const
The project associated with the layout.
Definition: qgslayout.cpp:129
QgsVectorLayer * layer() const
Returns the vector layer associated with the layout&#39;s context.
double y() const
Returns y coordinate of point.
QgsLayoutObject * layoutObject()
Returns the layout object associated with this widget.