Skip to content

Commit 79d224e

Browse files
committed
add advanced config to offset map tool widget
fix #14750
1 parent e1d481f commit 79d224e

4 files changed

+228
-47
lines changed

src/app/qgsmaptooloffsetcurve.cpp

+50-37
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,12 @@
3131
#include "qgssettings.h"
3232
#include "qgisapp.h"
3333

34-
#include "qgisapp.h"
34+
#include "qgslogger.h"
3535

3636
QgsMapToolOffsetCurve::QgsMapToolOffsetCurve( QgsMapCanvas *canvas )
3737
: QgsMapToolEdit( canvas )
3838
, mSnapIndicator( qgis::make_unique< QgsSnapIndicator >( canvas ) )
39-
{
40-
}
39+
{}
4140

4241
QgsMapToolOffsetCurve::~QgsMapToolOffsetCurve()
4342
{
@@ -241,6 +240,7 @@ void QgsMapToolOffsetCurve::cancel()
241240
{
242241
deleteUserInputWidget();
243242
deleteRubberBandAndGeometry();
243+
mCtrlHeldOnFirstClick = false;
244244
mLayer = nullptr;
245245
}
246246

@@ -275,10 +275,6 @@ void QgsMapToolOffsetCurve::canvasMoveEvent( QgsMapMouseEvent *e )
275275
mSnapIndicator->setMatch( e->mapPointMatch() );
276276

277277
double offset = calculateOffset( mapPoint );
278-
if ( offset == 0.0 )
279-
{
280-
return;
281-
}
282278

283279
if ( mUserInputWidget )
284280
{
@@ -356,19 +352,18 @@ void QgsMapToolOffsetCurve::prepareGeometry( QgsVectorLayer *vl, const QgsPointL
356352

357353
void QgsMapToolOffsetCurve::createUserInputWidget()
358354
{
359-
if ( !mCanvas )
360-
{
361-
return;
362-
}
363-
364355
deleteUserInputWidget();
356+
365357
mUserInputWidget = new QgsOffsetUserWidget();
358+
mUserInputWidget->setPolygonMode( QgsWkbTypes::geometryType( mOriginalGeometry.wkbType() ) != QgsWkbTypes::LineGeometry );
366359
QgisApp::instance()->addUserInputWidget( mUserInputWidget );
367360
mUserInputWidget->setFocus( Qt::TabFocusReason );
368361

369362
connect( mUserInputWidget, &QgsOffsetUserWidget::offsetChanged, this, &QgsMapToolOffsetCurve::updateGeometryAndRubberBand );
370363
connect( mUserInputWidget, &QgsOffsetUserWidget::offsetEditingFinished, this, &QgsMapToolOffsetCurve::applyOffset );
371364
connect( mUserInputWidget, &QgsOffsetUserWidget::offsetEditingCanceled, this, &QgsMapToolOffsetCurve::cancel );
365+
366+
connect( mUserInputWidget, &QgsOffsetUserWidget::offsetConfigChanged, this, [ = ] {updateGeometryAndRubberBand( mUserInputWidget->offset() );} );
372367
}
373368

374369
void QgsMapToolOffsetCurve::deleteUserInputWidget()
@@ -404,19 +399,21 @@ void QgsMapToolOffsetCurve::updateGeometryAndRubberBand( double offset )
404399
return;
405400
}
406401

402+
QgsGeometry offsetGeom;
407403
QgsSettings s;
408-
QgsGeometry::JoinStyle joinStyle = static_cast< QgsGeometry::JoinStyle >( s.value( QStringLiteral( "/qgis/digitizing/offset_join_style" ), 0 ).toInt() );
404+
QgsGeometry::JoinStyle joinStyle = static_cast< QgsGeometry::JoinStyle >( s.value( QStringLiteral( "/qgis/digitizing/offset_join_style" ), QgsGeometry::JoinStyleRound ).toInt() );
409405
int quadSegments = s.value( QStringLiteral( "/qgis/digitizing/offset_quad_seg" ), 8 ).toInt();
410406
double miterLimit = s.value( QStringLiteral( "/qgis/digitizing/offset_miter_limit" ), 5.0 ).toDouble();
407+
QgsGeometry::EndCapStyle capStyle = static_cast< QgsGeometry::EndCapStyle >( s.value( QStringLiteral( "/qgis/digitizing/offset_cap_style" ), QgsGeometry::CapRound ).toInt() );
408+
411409

412-
QgsGeometry offsetGeom;
413410
if ( QgsWkbTypes::geometryType( mOriginalGeometry.wkbType() ) == QgsWkbTypes::LineGeometry )
414411
{
415412
offsetGeom = mManipulatedGeometry.offsetCurve( offset, quadSegments, joinStyle, miterLimit );
416413
}
417414
else
418415
{
419-
offsetGeom = mManipulatedGeometry.buffer( offset, quadSegments, QgsGeometry::CapRound, joinStyle, miterLimit );
416+
offsetGeom = mManipulatedGeometry.buffer( offset, quadSegments, capStyle, joinStyle, miterLimit );
420417
}
421418

422419
if ( !offsetGeom )
@@ -441,26 +438,41 @@ void QgsMapToolOffsetCurve::updateGeometryAndRubberBand( double offset )
441438
QgsOffsetUserWidget::QgsOffsetUserWidget( QWidget *parent )
442439
: QWidget( parent )
443440
{
444-
mLayout = new QGridLayout( this );
445-
mLayout->setContentsMargins( 0, 0, 0, 0 );
446-
//mLayout->setAlignment( Qt::AlignLeft );
447-
setLayout( mLayout );
448-
449-
QLabel *lbl = new QLabel( tr( "Offset" ), this );
450-
lbl->setAlignment( Qt::AlignRight | Qt::AlignCenter );
451-
mLayout->addWidget( lbl, 0, 0 );
452-
453-
mOffsetSpinBox = new QgsDoubleSpinBox();
454-
mOffsetSpinBox->setMinimum( -99999999 );
455-
mOffsetSpinBox->setMaximum( 99999999 );
456-
mOffsetSpinBox->setDecimals( 6 );
457-
mOffsetSpinBox->setClearValue( 0.0 );
458-
mOffsetSpinBox->setShowClearButton( false );
459-
mLayout->addWidget( mOffsetSpinBox, 0, 1 );
441+
setupUi( this );
442+
443+
// fill comboboxes
444+
mJoinStyleComboBox->addItem( tr( "round" ), QgsGeometry::JoinStyleRound );
445+
mJoinStyleComboBox->addItem( tr( "miter" ), QgsGeometry::JoinStyleMiter );
446+
mJoinStyleComboBox->addItem( tr( "bevel" ), QgsGeometry::JoinStyleBevel );
447+
mCapStyleComboBox->addItem( tr( "round" ), QgsGeometry::CapRound );
448+
mCapStyleComboBox->addItem( tr( "flat" ), QgsGeometry::CapFlat );
449+
mCapStyleComboBox->addItem( tr( "square" ), QgsGeometry::CapSquare );
450+
451+
QgsSettings s;
452+
QgsGeometry::JoinStyle joinStyle = static_cast< QgsGeometry::JoinStyle >( s.value( QStringLiteral( "/qgis/digitizing/offset_join_style" ), QgsGeometry::JoinStyleRound ).toInt() );
453+
int quadSegments = s.value( QStringLiteral( "/qgis/digitizing/offset_quad_seg" ), 8 ).toInt();
454+
double miterLimit = s.value( QStringLiteral( "/qgis/digitizing/offset_miter_limit" ), 5.0 ).toDouble();
455+
QgsGeometry::EndCapStyle capStyle = static_cast< QgsGeometry::EndCapStyle >( s.value( QStringLiteral( "/qgis/digitizing/offset_cap_style" ), QgsGeometry::CapRound ).toInt() );
456+
457+
mJoinStyleComboBox->setCurrentIndex( mJoinStyleComboBox->findData( joinStyle ) );
458+
mQuadrantSpinBox->setValue( quadSegments );
459+
mMiterLimitSpinBox->setValue( miterLimit );
460+
mCapStyleComboBox->setCurrentIndex( mCapStyleComboBox->findData( capStyle ) );
460461

461462
// connect signals
462463
mOffsetSpinBox->installEventFilter( this );
463-
connect( mOffsetSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsOffsetUserWidget::offsetSpinBoxValueChanged );
464+
connect( mOffsetSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsOffsetUserWidget::offsetChanged );
465+
466+
connect( mJoinStyleComboBox, static_cast < void ( QComboBox::* )( int ) > ( &QComboBox::currentIndexChanged ), this, [ = ] { QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/offset_join_style" ), mJoinStyleComboBox->currentData() ); emit offsetConfigChanged(); } );
467+
connect( mQuadrantSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, [ = ]( const int quadSegments ) { QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/offset_quad_seg" ), quadSegments ); emit offsetConfigChanged(); } );
468+
connect( mMiterLimitSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, [ = ]( const double & miterLimit ) { QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/offset_miter_limit" ), miterLimit ); emit offsetConfigChanged(); } );
469+
connect( mCapStyleComboBox, static_cast < void ( QComboBox::* )( int ) > ( &QComboBox::currentIndexChanged ), this, [ = ] { QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/offset_cap_style" ), mCapStyleComboBox->currentData() ); emit offsetConfigChanged(); } );
470+
471+
bool showAdvanced = s.value( QStringLiteral( "/qgis/digitizing/offset_show_advanced" ), false ).toBool();
472+
mShowAdvancedButton->setChecked( showAdvanced );
473+
mAdvancedConfigWidget->setVisible( showAdvanced );
474+
connect( mShowAdvancedButton, &QToolButton::clicked, mAdvancedConfigWidget, &QWidget::setVisible );
475+
connect( mShowAdvancedButton, &QToolButton::clicked, this, [ = ]( const bool clicked ) {QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/offset_show_advanced" ), clicked );} );
464476

465477
// config focus
466478
setFocusProxy( mOffsetSpinBox );
@@ -476,6 +488,12 @@ double QgsOffsetUserWidget::offset()
476488
return mOffsetSpinBox->value();
477489
}
478490

491+
void QgsOffsetUserWidget::setPolygonMode( bool polygon )
492+
{
493+
mCapStyleLabel->setEnabled( polygon );
494+
mCapStyleComboBox->setEnabled( polygon );
495+
}
496+
479497
bool QgsOffsetUserWidget::eventFilter( QObject *obj, QEvent *ev )
480498
{
481499
if ( obj == mOffsetSpinBox && ev->type() == QEvent::KeyPress )
@@ -495,8 +513,3 @@ bool QgsOffsetUserWidget::eventFilter( QObject *obj, QEvent *ev )
495513

496514
return false;
497515
}
498-
499-
void QgsOffsetUserWidget::offsetSpinBoxValueChanged( double offset )
500-
{
501-
emit offsetChanged( offset );
502-
}

src/app/qgsmaptooloffsetcurve.h

+5-10
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,15 @@
1919
#include "qgsmaptooledit.h"
2020
#include "qgsgeometry.h"
2121
#include "qgis_app.h"
22+
#include "ui_qgsoffsetuserinputwidget.h"
2223

2324
class QGridLayout;
2425

2526
class QgsSnapIndicator;
2627
class QgsDoubleSpinBox;
2728
class QGraphicsProxyWidget;
2829

29-
class APP_EXPORT QgsOffsetUserWidget : public QWidget
30+
class APP_EXPORT QgsOffsetUserWidget : public QWidget, private Ui::QgsOffsetUserInputBase
3031
{
3132
Q_OBJECT
3233

@@ -35,25 +36,19 @@ class APP_EXPORT QgsOffsetUserWidget : public QWidget
3536
explicit QgsOffsetUserWidget( QWidget *parent = nullptr );
3637

3738
void setOffset( double offset );
38-
3939
double offset();
40+
QDoubleSpinBox *editor() const {return mOffsetSpinBox;}
4041

41-
QgsDoubleSpinBox *editor() {return mOffsetSpinBox;}
42+
void setPolygonMode( bool polygon );
4243

4344
signals:
4445
void offsetChanged( double offset );
4546
void offsetEditingFinished( double offset, const Qt::KeyboardModifiers &modifiers );
4647
void offsetEditingCanceled();
48+
void offsetConfigChanged();
4749

4850
protected:
4951
bool eventFilter( QObject *obj, QEvent *ev ) override;
50-
51-
private slots:
52-
void offsetSpinBoxValueChanged( double offset );
53-
54-
private:
55-
QGridLayout *mLayout = nullptr;
56-
QgsDoubleSpinBox *mOffsetSpinBox = nullptr;
5752
};
5853

5954
class APP_EXPORT QgsMapToolOffsetCurve: public QgsMapToolEdit

src/gui/qgsuserinputwidget.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ QgsUserInputWidget::QgsUserInputWidget( QWidget *parent )
4040
topLayout->addWidget( f );
4141
setLayout( topLayout );
4242

43+
// this allows the widget to be resized on demand
44+
topLayout->setSizeConstraint( QLayout::SetFixedSize );
45+
mLayout->setSizeConstraint( QLayout::SetFixedSize );
46+
4347
setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding );
4448
hide();
4549
}

src/ui/qgsoffsetuserinputwidget.ui

+169
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>QgsOffsetUserInputBase</class>
4+
<widget class="QWidget" name="QgsOffsetUserInputBase">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>362</width>
10+
<height>142</height>
11+
</rect>
12+
</property>
13+
<property name="sizePolicy">
14+
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
15+
<horstretch>0</horstretch>
16+
<verstretch>0</verstretch>
17+
</sizepolicy>
18+
</property>
19+
<property name="windowTitle">
20+
<string>Form</string>
21+
</property>
22+
<layout class="QGridLayout" name="gridLayout">
23+
<item row="1" column="2">
24+
<widget class="QDoubleSpinBox" name="mOffsetSpinBox">
25+
<property name="sizePolicy">
26+
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
27+
<horstretch>0</horstretch>
28+
<verstretch>0</verstretch>
29+
</sizepolicy>
30+
</property>
31+
<property name="minimum">
32+
<double>-9999999.000000000000000</double>
33+
</property>
34+
<property name="maximum">
35+
<double>999999.989999999990687</double>
36+
</property>
37+
</widget>
38+
</item>
39+
<item row="1" column="1">
40+
<widget class="QLabel" name="label">
41+
<property name="text">
42+
<string>Offset</string>
43+
</property>
44+
</widget>
45+
</item>
46+
<item row="1" column="0">
47+
<widget class="QToolButton" name="mShowAdvancedButton">
48+
<property name="text">
49+
<string>...</string>
50+
</property>
51+
<property name="icon">
52+
<iconset resource="../../images/images.qrc">
53+
<normaloff>:/images/themes/default/propertyicons/settings.svg</normaloff>:/images/themes/default/propertyicons/settings.svg</iconset>
54+
</property>
55+
<property name="checkable">
56+
<bool>true</bool>
57+
</property>
58+
<property name="checked">
59+
<bool>true</bool>
60+
</property>
61+
<property name="arrowType">
62+
<enum>Qt::NoArrow</enum>
63+
</property>
64+
</widget>
65+
</item>
66+
<item row="0" column="0" colspan="3">
67+
<widget class="QWidget" name="mAdvancedConfigWidget" native="true">
68+
<layout class="QGridLayout" name="gridLayout_2">
69+
<property name="leftMargin">
70+
<number>0</number>
71+
</property>
72+
<property name="topMargin">
73+
<number>0</number>
74+
</property>
75+
<property name="rightMargin">
76+
<number>0</number>
77+
</property>
78+
<property name="bottomMargin">
79+
<number>0</number>
80+
</property>
81+
<item row="0" column="0">
82+
<widget class="QLabel" name="label_2">
83+
<property name="text">
84+
<string>Join style</string>
85+
</property>
86+
<property name="wordWrap">
87+
<bool>true</bool>
88+
</property>
89+
</widget>
90+
</item>
91+
<item row="0" column="1">
92+
<widget class="QComboBox" name="mJoinStyleComboBox"/>
93+
</item>
94+
<item row="0" column="2">
95+
<widget class="QLabel" name="label_3">
96+
<property name="text">
97+
<string>Quadrant segments</string>
98+
</property>
99+
<property name="wordWrap">
100+
<bool>true</bool>
101+
</property>
102+
</widget>
103+
</item>
104+
<item row="0" column="3">
105+
<widget class="QSpinBox" name="mQuadrantSpinBox"/>
106+
</item>
107+
<item row="1" column="0">
108+
<widget class="QLabel" name="label_4">
109+
<property name="text">
110+
<string>Miter limit</string>
111+
</property>
112+
<property name="wordWrap">
113+
<bool>true</bool>
114+
</property>
115+
</widget>
116+
</item>
117+
<item row="1" column="1">
118+
<widget class="QDoubleSpinBox" name="mMiterLimitSpinBox"/>
119+
</item>
120+
<item row="1" column="2">
121+
<widget class="QLabel" name="mCapStyleLabel">
122+
<property name="text">
123+
<string>Cap style</string>
124+
</property>
125+
<property name="wordWrap">
126+
<bool>true</bool>
127+
</property>
128+
</widget>
129+
</item>
130+
<item row="1" column="3">
131+
<widget class="QComboBox" name="mCapStyleComboBox"/>
132+
</item>
133+
</layout>
134+
</widget>
135+
</item>
136+
</layout>
137+
</widget>
138+
<resources>
139+
<include location="../../images/images.qrc"/>
140+
<include location="../../images/images.qrc"/>
141+
<include location="../../images/images.qrc"/>
142+
<include location="../../images/images.qrc"/>
143+
<include location="../../images/images.qrc"/>
144+
<include location="../../images/images.qrc"/>
145+
<include location="../../images/images.qrc"/>
146+
<include location="../../images/images.qrc"/>
147+
<include location="../../images/images.qrc"/>
148+
<include location="../../images/images.qrc"/>
149+
<include location="../../images/images.qrc"/>
150+
<include location="../../images/images.qrc"/>
151+
<include location="../../images/images.qrc"/>
152+
<include location="../../images/images.qrc"/>
153+
<include location="../../images/images.qrc"/>
154+
<include location="../../images/images.qrc"/>
155+
<include location="../../images/images.qrc"/>
156+
<include location="../../images/images.qrc"/>
157+
<include location="../../images/images.qrc"/>
158+
<include location="../../images/images.qrc"/>
159+
<include location="../../images/images.qrc"/>
160+
<include location="../../images/images.qrc"/>
161+
<include location="../../images/images.qrc"/>
162+
<include location="../../images/images.qrc"/>
163+
<include location="../../images/images.qrc"/>
164+
<include location="../../images/images.qrc"/>
165+
<include location="../../images/images.qrc"/>
166+
<include location="../../images/images.qrc"/>
167+
</resources>
168+
<connections/>
169+
</ui>

0 commit comments

Comments
 (0)