QGIS API Documentation 3.99.0-Master (357b655ed83)
Loading...
Searching...
No Matches
qgsgeometrywidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsgeometrywidget.cpp
3 --------------------------------------
4 Date : March 2015
5 Copyright : (C) 2015 Nyall Dawson
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 "qgsgeometrywidget.h"
17
18#include "qgsapplication.h"
19#include "qgsgeometry.h"
20#include "qgsguiutils.h"
21#include "qgsjsonutils.h"
23
24#include <QAction>
25#include <QClipboard>
26#include <QHBoxLayout>
27#include <QLineEdit>
28#include <QMenu>
29#include <QString>
30#include <QToolButton>
31
32#include "moc_qgsgeometrywidget.cpp"
33
34using namespace Qt::StringLiterals;
35
37 : QWidget( parent )
38{
39 QHBoxLayout *layout = new QHBoxLayout();
40 layout->setContentsMargins( 0, 0, 0, 0 );
41
42 mLineEdit = new QLineEdit();
43 mLineEdit->setReadOnly( true );
44 mLineEdit->setStyleSheet( u"font-style: italic;"_s );
45
46 // make text appear in disabled text color, as it's not directly editable
47 QPalette palette = mLineEdit->palette();
48 palette.setColor( QPalette::Text, palette.color( QPalette::Disabled, QPalette::Text ) );
49 mLineEdit->setPalette( palette );
50
51 mLineEdit->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Minimum );
52
53 mButton = new QToolButton();
54 mButton->setStyleSheet( u"QToolButton{ background: none; border: 1px solid rgba(0, 0, 0, 0%);} QToolButton:focus { border: 1px solid palette(highlight); }"_s );
55 const int iconSize = QgsGuiUtils::scaleIconSize( 24 );
56 mButton->setIconSize( QSize( iconSize, iconSize ) );
57 // button width is 1.25 * icon size, height 1.1 * icon size. But we round to ensure even pixel sizes for equal margins
58 mButton->setFixedSize( 2 * static_cast<int>( 1.25 * iconSize / 2.0 ), 2 * static_cast<int>( iconSize * 1.1 / 2.0 ) );
59
60 mButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
61 mButton->setIcon( QgsApplication::getThemeIcon( u"/mActionOffsetCurve.svg"_s ) );
62
63 layout->addWidget( mLineEdit, 1 );
64 layout->addWidget( mButton );
65
66 setLayout( layout );
67
68 setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum );
69
70 setFocusProxy( mLineEdit );
71
72 mMenu = new QMenu( this );
73
74 mCopyWktAction = new QAction( mMenu );
75 mCopyWktAction->setText( tr( "Copy as WKT" ) );
76 connect( mCopyWktAction, &QAction::triggered, this, &QgsGeometryWidget::copyAsWkt );
77
78 mCopyGeoJsonAction = new QAction( mMenu );
79 mCopyGeoJsonAction->setText( tr( "Copy as GeoJSON" ) );
80 connect( mCopyGeoJsonAction, &QAction::triggered, this, &QgsGeometryWidget::copyAsGeoJson );
81
82 mPasteAction = new QAction( mMenu );
83 mPasteAction->setText( tr( "Paste Geometry" ) );
84 connect( mPasteAction, &QAction::triggered, this, &QgsGeometryWidget::pasteTriggered );
85
86 mClearAction = new QAction( mMenu );
87 mClearAction->setText( tr( "Clear" ) );
88 connect( mClearAction, &QAction::triggered, this, &QgsGeometryWidget::clearGeometry );
89
90 mMenu->addAction( mCopyWktAction );
91 mMenu->addAction( mCopyGeoJsonAction );
92 mMenu->addSeparator();
93 mMenu->addAction( mPasteAction );
94 mMenu->addAction( mClearAction );
95 connect( mMenu, &QMenu::aboutToShow, this, &QgsGeometryWidget::prepareMenu );
96
97 mButton->setMenu( mMenu );
98 mButton->setPopupMode( QToolButton::InstantPopup );
99
100 updateLineEdit();
101}
102
104{
105 if ( geometry == mGeometry )
106 return;
107
108 if ( !typeIsAcceptable( geometry.wkbType() ) )
109 {
110 return;
111 }
112
113 mGeometry = geometry;
114 updateLineEdit();
115 emit geometryValueChanged( mGeometry );
116}
117
119{
120 return mGeometry;
121}
122
123void QgsGeometryWidget::setAcceptedWkbTypes( const QList<Qgis::WkbType> &types )
124{
125 mAcceptedTypes = types;
126}
127
128QList<Qgis::WkbType> QgsGeometryWidget::acceptedWkbTypes() const
129{
130 return mAcceptedTypes;
131}
132
134{
135 return mReadOnly;
136}
137
139{
140 mReadOnly = readOnly;
141}
142
144{
145 if ( mGeometry.isNull() )
146 return;
147
149}
150
152{
153 if ( mGeometry.isNull() )
154 return;
155
156 QApplication::clipboard()->setText( mGeometry.asWkt() );
157}
158
160{
161 if ( mGeometry.isNull() )
162 return;
163
164 QApplication::clipboard()->setText( mGeometry.asJson() );
165}
166
167void QgsGeometryWidget::pasteTriggered()
168{
169 if ( !mPastedGeom.isNull() )
170 {
171 QgsCoordinateReferenceSystem defaultCrs = mPastedGeom.crs();
172
173 // default to CRS of current geometry, if we have no better guesses as to what the clipboard CRS is
174 if ( !defaultCrs.isValid() )
175 defaultCrs = mGeometry.crs();
176
177 QgsProjectionSelectionDialog crsSelector( this );
178 crsSelector.setWindowTitle( tr( "Paste Geometry" ) );
179 crsSelector.setMessage( tr( "Please specify the Coordinate Reference System (CRS) for the pasted geometry." ) );
180 crsSelector.setCrs( defaultCrs );
181 if ( crsSelector.exec() )
182 {
183 mPastedGeom.setCrs( crsSelector.crs() );
184 setGeometryValue( mPastedGeom );
185 mPastedGeom = QgsReferencedGeometry();
186 }
187 }
188}
189
190void QgsGeometryWidget::fetchGeomFromClipboard()
191{
192 mPastedGeom = QgsReferencedGeometry();
193 if ( mReadOnly )
194 return;
195
196 const QString text = QApplication::clipboard()->text();
197 if ( text.isEmpty() )
198 return;
199
200 //try reading as a single wkt string
201 mPastedGeom = QgsReferencedGeometry( QgsGeometry::fromWkt( text ), QgsCoordinateReferenceSystem() );
202 if ( !mPastedGeom.isNull() && typeIsAcceptable( mPastedGeom.wkbType() ) )
203 {
204 return;
205 }
206 mPastedGeom = QgsReferencedGeometry();
207
208 //try reading as a list
209 const QStringList lines = text.split( "\n", Qt::SkipEmptyParts );
210 if ( !lines.isEmpty() )
211 {
212 for ( const QString &line : lines )
213 {
214 const QgsGeometry geometry = QgsGeometry::fromWkt( line );
215 if ( !geometry.isNull() && typeIsAcceptable( geometry.wkbType() ) )
216 {
217 mPastedGeom = QgsReferencedGeometry( geometry, QgsCoordinateReferenceSystem() );
218 return;
219 }
220 }
221 }
222
223 // try reading a GeoJSON
224 const QgsFeatureList features = QgsJsonUtils::stringToFeatureList( text );
225 if ( !features.isEmpty() && features.at( 0 ).hasGeometry() )
226 {
227 // assume EPSG:4326 for GeoJSON
228 mPastedGeom = QgsReferencedGeometry( features.at( 0 ).geometry(), QgsCoordinateReferenceSystem( u"EPSG:4326"_s ) );
229 return;
230 }
231}
232
233bool QgsGeometryWidget::typeIsAcceptable( Qgis::WkbType type ) const
234{
235 if ( mAcceptedTypes.isEmpty() )
236 {
237 return true;
238 }
239
240 return mAcceptedTypes.contains( type );
241}
242
243void QgsGeometryWidget::prepareMenu()
244{
245 fetchGeomFromClipboard();
246
247 mCopyGeoJsonAction->setEnabled( !mGeometry.isNull() );
248 mCopyWktAction->setEnabled( !mGeometry.isNull() );
249 mClearAction->setEnabled( !mGeometry.isNull() && !mReadOnly );
250 mPasteAction->setEnabled( !mPastedGeom.isNull() && !mReadOnly );
251}
252
253void QgsGeometryWidget::updateLineEdit()
254{
255 if ( mGeometry.isNull() )
256 {
257 mLineEdit->setText( QgsApplication::nullRepresentation() );
258 }
259 else
260 {
261 QString wkt = mGeometry.asWkt();
262 if ( wkt.length() >= 1050 )
263 {
264 wkt = wkt.left( QgsField::MAX_WKT_LENGTH ) + QChar( 0x2026 );
265 }
266
267 if ( mGeometry.crs().isValid() )
268 {
269 mLineEdit->setText( u"%1 [%2]"_s.arg( wkt, mGeometry.crs().userFriendlyIdentifier() ) );
270 }
271 else
272 {
273 mLineEdit->setText( wkt );
274 }
275 }
276}
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:280
static QString nullRepresentation()
Returns the string used to represent the value NULL throughout QGIS.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
static constexpr int MAX_WKT_LENGTH
Definition qgsfield.h:580
void setGeometryValue(const QgsReferencedGeometry &geometry)
Sets the current geometry value for the widget.
QgsReferencedGeometry geometryValue
void setReadOnly(bool readOnly)
Sets whether the widget should be in a read-only state.
QgsGeometryWidget(QWidget *parent=nullptr)
Constructor for QgsGeometryWidget, with the specified parent widget.
void copyAsWkt()
Copies the current geometry value to the clipboard, as a WKT string.
void setAcceptedWkbTypes(const QList< Qgis::WkbType > &types)
Sets the list of WKB geometry types which are permitted for the widget.
QList< Qgis::WkbType > acceptedWkbTypes() const
Returns the list of WKB geometry types which are permitted for the widget.
void clearGeometry()
Clears the current geometry value stored in the widget.
void geometryValueChanged(const QgsReferencedGeometry &value)
Emitted whenever the geometry value of the widget is changed.
bool isReadOnly() const
Returns whether the widget is in a read-only state.
void copyAsGeoJson()
Copies the current geometry value to the clipboard, as a GeoJSON string.
static Q_INVOKABLE QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.).
static QgsFeatureList stringToFeatureList(const QString &string, const QgsFields &fields=QgsFields(), QTextCodec *encoding SIP_PYARGREMOVE6=nullptr)
Attempts to parse a GeoJSON string to a collection of features.
A generic dialog to prompt the user for a Coordinate Reference System.
QgsCoordinateReferenceSystem crs() const
Returns the associated coordinate reference system, or an invalid CRS if no reference system is set.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the associated crs.
A QgsGeometry with associated coordinate reference system.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
QList< QgsFeature > QgsFeatureList