QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgslayoutpolylinewidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayoutpolylinewidget.cpp
3  begin : March 2016
4  copyright : (C) 2016 Paul Blottiere, Oslandia
5  email : paul dot blottiere at oslandia dot com
6  ***************************************************************************/
7 
8 /***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
19 #include "qgsstyle.h"
20 #include "qgssymbollayerutils.h"
21 #include "qgslayoutitemregistry.h"
22 #include "qgslayout.h"
23 #include "qgslayoutundostack.h"
24 #include "qgsvectorlayer.h"
25 
26 #include <QButtonGroup>
27 #include <QFileDialog>
28 
30  : QgsLayoutItemBaseWidget( nullptr, polyline )
31  , mPolyline( polyline )
32 {
33  setupUi( this );
34  setPanelTitle( tr( "Polyline Properties" ) );
35 
36  connect( mStrokeWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutPolylineWidget::arrowStrokeWidthChanged );
37  connect( mArrowHeadWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutPolylineWidget::arrowHeadWidthChanged );
38  connect( mArrowHeadFillColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutPolylineWidget::arrowHeadFillColorChanged );
39  connect( mArrowHeadStrokeColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutPolylineWidget::arrowHeadStrokeColorChanged );
40  connect( mRadioStartArrow, &QRadioButton::toggled, this, &QgsLayoutPolylineWidget::startArrowHeadToggled );
41  connect( mRadioStartNoMarker, &QRadioButton::toggled, this, &QgsLayoutPolylineWidget::startNoMarkerToggled );
42  connect( mRadioStartSVG, &QRadioButton::toggled, this, &QgsLayoutPolylineWidget::startSvgMarkerToggled );
43  connect( mRadioEndArrow, &QRadioButton::toggled, this, &QgsLayoutPolylineWidget::endArrowHeadToggled );
44  connect( mRadioEndNoMarker, &QRadioButton::toggled, this, &QgsLayoutPolylineWidget::endNoMarkerToggled );
45  connect( mRadioEndSvg, &QRadioButton::toggled, this, &QgsLayoutPolylineWidget::endSvgMarkerToggled );
46  connect( mStartMarkerLineEdit, &QLineEdit::textChanged, this, &QgsLayoutPolylineWidget::mStartMarkerLineEdit_textChanged );
47  connect( mEndMarkerLineEdit, &QLineEdit::textChanged, this, &QgsLayoutPolylineWidget::mEndMarkerLineEdit_textChanged );
48  connect( mStartMarkerToolButton, &QToolButton::clicked, this, &QgsLayoutPolylineWidget::mStartMarkerToolButton_clicked );
49  connect( mEndMarkerToolButton, &QToolButton::clicked, this, &QgsLayoutPolylineWidget::mEndMarkerToolButton_clicked );
50  setPanelTitle( tr( "Arrow Properties" ) );
51  QButtonGroup *startMarkerGroup = new QButtonGroup( this );
52  startMarkerGroup->addButton( mRadioStartNoMarker );
53  startMarkerGroup->addButton( mRadioStartArrow );
54  startMarkerGroup->addButton( mRadioStartSVG );
55  startMarkerGroup->setExclusive( true );
56  QButtonGroup *endMarkerGroup = new QButtonGroup( this );
57  endMarkerGroup->addButton( mRadioEndNoMarker );
58  endMarkerGroup->addButton( mRadioEndArrow );
59  endMarkerGroup->addButton( mRadioEndSvg );
60  endMarkerGroup->setExclusive( true );
61 
62  //disable the svg related gui elements by default
63  enableStartSvgInputElements( false );
64  enableEndSvgInputElements( false );
65 
66  mArrowHeadStrokeColorButton->setColorDialogTitle( tr( "Select Arrow Head Stroke Color" ) );
67  mArrowHeadStrokeColorButton->setAllowOpacity( true );
68  mArrowHeadStrokeColorButton->setContext( QStringLiteral( "composer" ) );
69  mArrowHeadStrokeColorButton->setNoColorString( tr( "Transparent Stroke" ) );
70  mArrowHeadStrokeColorButton->setShowNoColor( true );
71  mArrowHeadFillColorButton->setColorDialogTitle( tr( "Select Arrow Head Fill Color" ) );
72  mArrowHeadFillColorButton->setAllowOpacity( true );
73  mArrowHeadFillColorButton->setContext( QStringLiteral( "composer" ) );
74  mArrowHeadFillColorButton->setNoColorString( tr( "Transparent Fill" ) );
75  mArrowHeadFillColorButton->setShowNoColor( true );
76 
77  //add widget for general composer item properties
78  mItemPropertiesWidget = new QgsLayoutItemPropertiesWidget( this, polyline );
79  //shapes don't use background or frame, since the symbol style is set through a QgsSymbolSelectorWidget
80  mItemPropertiesWidget->showBackgroundGroup( false );
81  mItemPropertiesWidget->showFrameGroup( false );
82  mainLayout->addWidget( mItemPropertiesWidget );
83 
84  mLineStyleButton->setSymbolType( QgsSymbol::Line );
85  connect( mLineStyleButton, &QgsSymbolButton::changed, this, &QgsLayoutPolylineWidget::symbolChanged );
86 
87  if ( mPolyline )
88  {
89  connect( mPolyline, &QgsLayoutObject::changed, this, &QgsLayoutPolylineWidget::setGuiElementValues );
90  mLineStyleButton->registerExpressionContextGenerator( mPolyline );
91  }
92  setGuiElementValues();
93 
94  mLineStyleButton->registerExpressionContextGenerator( mPolyline );
95  mLineStyleButton->setLayer( coverageLayer() );
96  if ( mPolyline->layout() )
97  {
98  connect( &mPolyline->layout()->reportContext(), &QgsLayoutReportContext::layerChanged, mLineStyleButton, &QgsSymbolButton::setLayer );
99  }
100 }
101 
103 {
104  if ( mItemPropertiesWidget )
105  mItemPropertiesWidget->setMasterLayout( masterLayout );
106 }
107 
109 {
111  return false;
112 
113  if ( mPolyline )
114  {
115  disconnect( mPolyline, &QgsLayoutObject::changed, this, &QgsLayoutPolylineWidget::setGuiElementValues );
116  }
117 
118  mPolyline = qobject_cast< QgsLayoutItemPolyline * >( item );
119  mItemPropertiesWidget->setItem( mPolyline );
120 
121  if ( mPolyline )
122  {
123  connect( mPolyline, &QgsLayoutObject::changed, this, &QgsLayoutPolylineWidget::setGuiElementValues );
124  mLineStyleButton->registerExpressionContextGenerator( mPolyline );
125  }
126 
127  setGuiElementValues();
128 
129  return true;
130 }
131 
132 
133 void QgsLayoutPolylineWidget::setGuiElementValues()
134 {
135  if ( !mPolyline )
136  return;
137 
138  whileBlocking( mLineStyleButton )->setSymbol( mPolyline->symbol()->clone() );
139 
140  whileBlocking( mArrowHeadFillColorButton )->setColor( mPolyline->arrowHeadFillColor() );
141  whileBlocking( mArrowHeadStrokeColorButton )->setColor( mPolyline->arrowHeadStrokeColor() );
142  whileBlocking( mStrokeWidthSpinBox )->setValue( mPolyline->arrowHeadStrokeWidth() );
143  whileBlocking( mArrowHeadWidthSpinBox )->setValue( mPolyline->arrowHeadWidth() );
144 
145  mRadioStartNoMarker->blockSignals( true );
146  mRadioStartArrow->blockSignals( true );
147  mRadioStartSVG->blockSignals( true );
148  mRadioEndArrow->blockSignals( true );
149  mRadioEndNoMarker->blockSignals( true );
150  mRadioEndSvg->blockSignals( true );
151  switch ( mPolyline->startMarker() )
152  {
154  mRadioStartNoMarker->setChecked( true );
155  break;
157  mRadioStartArrow->setChecked( true );
158  break;
160  mRadioStartSVG->setChecked( true );
161  enableStartSvgInputElements( true );
162  break;
163  }
164  switch ( mPolyline->endMarker() )
165  {
167  mRadioEndNoMarker->setChecked( true );
168  break;
170  mRadioEndArrow->setChecked( true );
171  break;
173  mRadioEndSvg->setChecked( true );
174  enableEndSvgInputElements( true );
175  break;
176  }
177  mRadioStartNoMarker->blockSignals( false );
178  mRadioStartArrow->blockSignals( false );
179  mRadioStartSVG->blockSignals( false );
180  mRadioEndArrow->blockSignals( false );
181  mRadioEndNoMarker->blockSignals( false );
182  mRadioEndSvg->blockSignals( false );
183 
184  mStartMarkerLineEdit->setText( mPolyline->startSvgMarkerPath() );
185  mEndMarkerLineEdit->setText( mPolyline->endSvgMarkerPath() );
186 }
187 
188 void QgsLayoutPolylineWidget::symbolChanged()
189 {
190  if ( !mPolyline )
191  return;
192 
193  mPolyline->layout()->undoStack()->beginCommand( mPolyline, tr( "Change Shape Style" ), QgsLayoutItem::UndoShapeStyle );
194  mPolyline->setSymbol( mLineStyleButton->clonedSymbol<QgsLineSymbol>() );
195  mPolyline->layout()->undoStack()->endCommand();
196 }
197 
198 void QgsLayoutPolylineWidget::arrowStrokeWidthChanged( double d )
199 {
200  if ( !mPolyline )
201  return;
202 
203  mPolyline->beginCommand( tr( "Change Arrow Head" ), QgsLayoutItem::UndoArrowStrokeWidth );
204  mPolyline->setArrowHeadStrokeWidth( d );
205  mPolyline->endCommand();
206 }
207 
208 void QgsLayoutPolylineWidget::arrowHeadWidthChanged( double d )
209 {
210  if ( !mPolyline )
211  return;
212 
213  mPolyline->beginCommand( tr( "Change Arrow Width" ), QgsLayoutItem::UndoArrowHeadWidth );
214  mPolyline->setArrowHeadWidth( d );
215  mPolyline->endCommand();
216 }
217 
218 
219 void QgsLayoutPolylineWidget::arrowHeadFillColorChanged( const QColor &newColor )
220 {
221  if ( !mPolyline )
222  return;
223 
224  mPolyline->beginCommand( tr( "Change Arrow Fill Color" ), QgsLayoutItem::UndoArrowHeadFillColor );
225  mPolyline->setArrowHeadFillColor( newColor );
226  mPolyline->endCommand();
227 }
228 
229 
230 void QgsLayoutPolylineWidget::arrowHeadStrokeColorChanged( const QColor &newColor )
231 {
232  if ( !mPolyline )
233  return;
234 
235  mPolyline->beginCommand( tr( "Change Arrow Stroke Color" ), QgsLayoutItem::UndoArrowHeadStrokeColor );
236  mPolyline->setArrowHeadStrokeColor( newColor );
237  mPolyline->endCommand();
238 }
239 
240 
241 void QgsLayoutPolylineWidget::startArrowHeadToggled( bool toggled )
242 {
243  if ( !mPolyline || !toggled )
244  return;
245 
246  mPolyline->beginCommand( tr( "Set Arrow Marker" ) );
247  mPolyline->setStartMarker( QgsLayoutItemPolyline::ArrowHead );
248  mPolyline->endCommand();
249 }
250 
251 void QgsLayoutPolylineWidget::endArrowHeadToggled( bool toggled )
252 {
253  if ( !mPolyline || !toggled )
254  return;
255 
256  mPolyline->beginCommand( tr( "Set Arrow Marker" ) );
257  mPolyline->setEndMarker( QgsLayoutItemPolyline::ArrowHead );
258  mPolyline->endCommand();
259 }
260 
261 void QgsLayoutPolylineWidget::startNoMarkerToggled( bool toggled )
262 {
263  if ( !mPolyline || !toggled )
264  return;
265 
266  mPolyline->beginCommand( tr( "Set Line Marker" ) );
267  mPolyline->setStartMarker( QgsLayoutItemPolyline::NoMarker );
268  mPolyline->endCommand();
269 }
270 
271 void QgsLayoutPolylineWidget::endNoMarkerToggled( bool toggled )
272 {
273  if ( !mPolyline || !toggled )
274  return;
275 
276  mPolyline->beginCommand( tr( "Set Line Marker" ) );
277  mPolyline->setEndMarker( QgsLayoutItemPolyline::NoMarker );
278  mPolyline->endCommand();
279 }
280 
281 void QgsLayoutPolylineWidget::startSvgMarkerToggled( bool toggled )
282 {
283  enableStartSvgInputElements( toggled );
284  if ( !mPolyline || !toggled )
285  return;
286 
287  mPolyline->beginCommand( tr( "Set SVG Marker" ) );
288  mPolyline->setStartMarker( QgsLayoutItemPolyline::SvgMarker );
289  mPolyline->endCommand();
290 }
291 
292 void QgsLayoutPolylineWidget::endSvgMarkerToggled( bool toggled )
293 {
294  enableEndSvgInputElements( toggled );
295  if ( !mPolyline || !toggled )
296  return;
297 
298  mPolyline->beginCommand( tr( "Set SVG Marker" ) );
299  mPolyline->setEndMarker( QgsLayoutItemPolyline::SvgMarker );
300  mPolyline->endCommand();
301 }
302 
303 void QgsLayoutPolylineWidget::enableStartSvgInputElements( bool enable )
304 {
305  mStartMarkerLineEdit->setEnabled( enable );
306  mStartMarkerToolButton->setEnabled( enable );
307 }
308 
309 void QgsLayoutPolylineWidget::enableEndSvgInputElements( bool enable )
310 {
311  mEndMarkerLineEdit->setEnabled( enable );
312  mEndMarkerToolButton->setEnabled( enable );
313 }
314 
315 void QgsLayoutPolylineWidget::mStartMarkerLineEdit_textChanged( const QString &text )
316 {
317  if ( !mPolyline )
318  return;
319 
320  mPolyline->beginCommand( tr( "Change Start Marker File" ) );
321  QFileInfo fi( text );
322  if ( fi.exists() && fi.isFile() )
323  {
324  mPolyline->setStartSvgMarkerPath( text );
325  }
326  else
327  {
328  mPolyline->setStartSvgMarkerPath( QString() );
329  }
330  mPolyline->endCommand();
331 }
332 
333 void QgsLayoutPolylineWidget::mEndMarkerLineEdit_textChanged( const QString &text )
334 {
335  if ( !mPolyline )
336  return;
337 
338  mPolyline->beginCommand( tr( "Change End Marker File" ) );
339  QFileInfo fi( text );
340  if ( fi.exists() && fi.isFile() )
341  {
342  mPolyline->setEndSvgMarkerPath( text );
343  }
344  else
345  {
346  mPolyline->setEndSvgMarkerPath( QString() );
347  }
348  mPolyline->endCommand();
349 }
350 
351 void QgsLayoutPolylineWidget::mStartMarkerToolButton_clicked()
352 {
353  QgsSettings s;
354  QString openDir;
355 
356  if ( !mStartMarkerLineEdit->text().isEmpty() )
357  {
358  QFileInfo fi( mStartMarkerLineEdit->text() );
359  openDir = fi.dir().absolutePath();
360  }
361 
362  if ( openDir.isEmpty() )
363  {
364  openDir = s.value( QStringLiteral( "/UI/lastComposerMarkerDir" ), QDir::homePath() ).toString();
365  }
366 
367  QString svgFileName = QFileDialog::getOpenFileName( this, tr( "Start marker svg file" ), openDir );
368  if ( !svgFileName.isNull() )
369  {
370  QFileInfo fileInfo( svgFileName );
371  s.setValue( QStringLiteral( "/UI/lastComposerMarkerDir" ), fileInfo.absolutePath() );
372  mPolyline->beginCommand( tr( "Change Start Marker File" ) );
373  mStartMarkerLineEdit->setText( svgFileName );
374  mPolyline->endCommand();
375  }
376 }
377 
378 void QgsLayoutPolylineWidget::mEndMarkerToolButton_clicked()
379 {
380  QgsSettings s;
381  QString openDir;
382 
383  if ( !mEndMarkerLineEdit->text().isEmpty() )
384  {
385  QFileInfo fi( mEndMarkerLineEdit->text() );
386  openDir = fi.dir().absolutePath();
387  }
388 
389  if ( openDir.isEmpty() )
390  {
391  openDir = s.value( QStringLiteral( "/UI/lastComposerMarkerDir" ), QDir::homePath() ).toString();
392  }
393 
394  QString svgFileName = QFileDialog::getOpenFileName( this, tr( "End marker svg file" ), openDir );
395  if ( !svgFileName.isNull() )
396  {
397  QFileInfo fileInfo( svgFileName );
398  s.setValue( QStringLiteral( "/UI/lastComposerMarkerDir" ), fileInfo.absolutePath() );
399  mPolyline->beginCommand( tr( "Change End Marker File" ) );
400  mEndMarkerLineEdit->setText( svgFileName );
401  mPolyline->endCommand();
402  }
403 }
QgsSymbolButton::changed
void changed()
Emitted when the symbol's settings are changed.
qgslayoutundostack.h
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
QgsLayoutItem::UndoShapeStyle
@ UndoShapeStyle
Shape symbol style.
Definition: qgslayoutitem.h:226
QgsLayoutItemPropertiesWidget::showBackgroundGroup
void showBackgroundGroup(bool showGroup)
Determines if the background of the group box shall be shown.
Definition: qgslayoutitemwidget.cpp:352
QgsLayoutItemPolyline
Layout item for node based polyline shapes.
Definition: qgslayoutitempolyline.h:33
QgsLayoutItem::UndoArrowHeadStrokeColor
@ UndoArrowHeadStrokeColor
Arrow head stroke color.
Definition: qgslayoutitem.h:292
qgssymbollayerutils.h
QgsSettings
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
QgsLayoutObject::changed
void changed()
Emitted when the object's properties change.
QgsLayoutItemPropertiesWidget
A widget for controlling the common properties of layout items (e.g.
Definition: qgslayoutitemwidget.h:219
QgsLayoutItemBaseWidget::coverageLayer
QgsVectorLayer * coverageLayer() const
Returns the current layout context coverage layer (if set).
Definition: qgslayoutitemwidget.cpp:217
QgsColorButton::colorChanged
void colorChanged(const QColor &color)
Emitted whenever a new color is set for the button.
QgsLayoutItemPropertiesWidget::showFrameGroup
void showFrameGroup(bool showGroup)
Determines if the frame of the group box shall be shown.
Definition: qgslayoutitemwidget.cpp:357
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
QgsLayoutItemPolyline::SvgMarker
@ SvgMarker
Show SVG marker.
Definition: qgslayoutitempolyline.h:43
QgsLayoutItem::UndoArrowHeadWidth
@ UndoArrowHeadWidth
Arrow head width.
Definition: qgslayoutitem.h:290
whileBlocking
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:262
QgsLayoutItemRegistry::LayoutPolyline
@ LayoutPolyline
Polyline shape item.
Definition: qgslayoutitemregistry.h:323
QgsLineSymbol
A line symbol type, for rendering LineString and MultiLineString geometries.
Definition: qgssymbol.h:1131
QgsLayoutPolylineWidget::QgsLayoutPolylineWidget
QgsLayoutPolylineWidget(QgsLayoutItemPolyline *polyline)
constructor
Definition: qgslayoutpolylinewidget.cpp:29
QgsSettings::setValue
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Definition: qgssettings.cpp:289
QgsLayoutItem
Base class for graphical items within a QgsLayout.
Definition: qgslayoutitem.h:113
QgsPanelWidget::setPanelTitle
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
Definition: qgspanelwidget.h:44
qgslayout.h
qgssymbolselectordialog.h
qgsstyle.h
QgsLayoutItemBaseWidget
A base class for property widgets for layout items.
Definition: qgslayoutitemwidget.h:123
qgslayoutpolylinewidget.h
qgsvectorlayer.h
QgsLayoutItemPolyline::ArrowHead
@ ArrowHead
Show arrow marker.
Definition: qgslayoutitempolyline.h:42
QgsLayoutPolylineWidget::setNewItem
bool setNewItem(QgsLayoutItem *item) override
Attempts to update the widget to show the properties for the specified item.
Definition: qgslayoutpolylinewidget.cpp:108
QgsLayoutItem::UndoArrowHeadFillColor
@ UndoArrowHeadFillColor
Arrow head fill color.
Definition: qgslayoutitem.h:291
QgsSymbolButton::setLayer
void setLayer(QgsVectorLayer *layer)
Sets a layer to associate with the widget.
Definition: qgssymbolbutton.cpp:180
QgsLayoutPolylineWidget::setMasterLayout
void setMasterLayout(QgsMasterLayoutInterface *masterLayout) override
Sets the master layout associated with the item.
Definition: qgslayoutpolylinewidget.cpp:102
QgsSymbol::Line
@ Line
Line symbol.
Definition: qgssymbol.h:88
QgsLayoutItemPolyline::NoMarker
@ NoMarker
Don't show marker.
Definition: qgslayoutitempolyline.h:41
QgsMasterLayoutInterface
Interface for master layout type objects, such as print layouts and reports.
Definition: qgsmasterlayoutinterface.h:43
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.
qgslayoutitemregistry.h
QgsLayoutItem::UndoArrowStrokeWidth
@ UndoArrowStrokeWidth
Arrow stroke width.
Definition: qgslayoutitem.h:289