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