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