QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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#include "qgsapplication.h"
18#include "qgsgeometry.h"
19#include "qgsjsonutils.h"
20#include "qgsguiutils.h"
22#include <QLineEdit>
23#include <QHBoxLayout>
24#include <QToolButton>
25#include <QMenu>
26#include <QAction>
27#include <QClipboard>
28
30 : QWidget( parent )
31{
32 QHBoxLayout *layout = new QHBoxLayout();
33 layout->setContentsMargins( 0, 0, 0, 0 );
34
35 mLineEdit = new QLineEdit();
36 mLineEdit->setReadOnly( true );
37 mLineEdit->setStyleSheet( QStringLiteral( "font-style: italic;" ) );
38
39 // make text appear in disabled text color, as it's not directly editable
40 QPalette palette = mLineEdit->palette();
41 palette.setColor( QPalette::Text, palette.color( QPalette::Disabled, QPalette::Text ) );
42 mLineEdit->setPalette( palette );
43
44 mLineEdit->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Minimum );
45
46 mButton = new QToolButton();
47 mButton->setStyleSheet( QStringLiteral( "QToolButton{ background: none; border: 1px solid rgba(0, 0, 0, 0%);} QToolButton:focus { border: 1px solid palette(highlight); }" ) );
48 const int iconSize = QgsGuiUtils::scaleIconSize( 24 );
49 mButton->setIconSize( QSize( iconSize, iconSize ) );
50 // button width is 1.25 * icon size, height 1.1 * icon size. But we round to ensure even pixel sizes for equal margins
51 mButton->setFixedSize( 2 * static_cast< int >( 1.25 * iconSize / 2.0 ), 2 * static_cast< int >( iconSize * 1.1 / 2.0 ) );
52
53 mButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
54 mButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionOffsetCurve.svg" ) ) );
55
56 layout->addWidget( mLineEdit, 1 );
57 layout->addWidget( mButton );
58
59 setLayout( layout );
60
61 setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum );
62
63 setFocusProxy( mLineEdit );
64
65 mMenu = new QMenu( this );
66
67 mCopyWktAction = new QAction( mMenu );
68 mCopyWktAction->setText( tr( "Copy as WKT" ) );
69 connect( mCopyWktAction, &QAction::triggered, this, &QgsGeometryWidget::copyAsWkt );
70
71 mCopyGeoJsonAction = new QAction( mMenu );
72 mCopyGeoJsonAction->setText( tr( "Copy as GeoJSON" ) );
73 connect( mCopyGeoJsonAction, &QAction::triggered, this, &QgsGeometryWidget::copyAsGeoJson );
74
75 mPasteAction = new QAction( mMenu );
76 mPasteAction->setText( tr( "Paste Geometry" ) );
77 connect( mPasteAction, &QAction::triggered, this, &QgsGeometryWidget::pasteTriggered );
78
79 mClearAction = new QAction( mMenu );
80 mClearAction->setText( tr( "Clear" ) );
81 connect( mClearAction, &QAction::triggered, this, &QgsGeometryWidget::clearGeometry );
82
83 mMenu->addAction( mCopyWktAction );
84 mMenu->addAction( mCopyGeoJsonAction );
85 mMenu->addSeparator();
86 mMenu->addAction( mPasteAction );
87 mMenu->addAction( mClearAction );
88 connect( mMenu, &QMenu::aboutToShow, this, &QgsGeometryWidget::prepareMenu );
89
90 mButton->setMenu( mMenu );
91 mButton->setPopupMode( QToolButton::InstantPopup );
92
93 updateLineEdit();
94}
95
97{
98 if ( geometry == mGeometry )
99 return;
100
101 if ( !typeIsAcceptable( geometry.wkbType() ) )
102 {
103 return;
104 }
105
106 mGeometry = geometry;
107 updateLineEdit();
108 emit geometryValueChanged( mGeometry );
109}
110
112{
113 return mGeometry;
114}
115
116void QgsGeometryWidget::setAcceptedWkbTypes( const QList<Qgis::WkbType> &types )
117{
118 mAcceptedTypes = types;
119}
120
121QList< Qgis::WkbType > QgsGeometryWidget::acceptedWkbTypes() const
122{
123 return mAcceptedTypes;
124}
125
127{
128 return mReadOnly;
129}
130
132{
133 mReadOnly = readOnly;
134}
135
137{
138 if ( mGeometry.isNull() )
139 return;
140
142}
143
145{
146 if ( mGeometry.isNull() )
147 return;
148
149 QApplication::clipboard()->setText( mGeometry.asWkt() );
150}
151
153{
154 if ( mGeometry.isNull() )
155 return;
156
157 QApplication::clipboard()->setText( mGeometry.asJson() );
158}
159
160void QgsGeometryWidget::pasteTriggered()
161{
162 if ( !mPastedGeom.isNull() )
163 {
164 QgsCoordinateReferenceSystem defaultCrs = mPastedGeom.crs();
165
166 // default to CRS of current geometry, if we have no better guesses as to what the clipboard CRS is
167 if ( !defaultCrs.isValid() )
168 defaultCrs = mGeometry.crs();
169
170 QgsProjectionSelectionDialog crsSelector( this );
171 crsSelector.setWindowTitle( tr( "Paste Geometry" ) );
172 crsSelector.setMessage( tr( "Please specify the Coordinate Reference System (CRS) for the pasted geometry." ) );
173 crsSelector.setCrs( defaultCrs );
174 if ( crsSelector.exec() )
175 {
176 mPastedGeom.setCrs( crsSelector.crs() );
177 setGeometryValue( mPastedGeom );
178 mPastedGeom = QgsReferencedGeometry();
179 }
180 }
181}
182
183void QgsGeometryWidget::fetchGeomFromClipboard()
184{
185 mPastedGeom = QgsReferencedGeometry();
186 if ( mReadOnly )
187 return;
188
189 const QString text = QApplication::clipboard()->text();
190 if ( text.isEmpty() )
191 return;
192
193 //try reading as a single wkt string
195 if ( !mPastedGeom.isNull() && typeIsAcceptable( mPastedGeom.wkbType() ) )
196 {
197 return;
198 }
199 mPastedGeom = QgsReferencedGeometry();
200
201 //try reading as a list
202 const QStringList lines = text.split( "\n", Qt::SkipEmptyParts );
203 if ( !lines.isEmpty() )
204 {
205 for ( const QString &line : lines )
206 {
207 const QgsGeometry geometry = QgsGeometry::fromWkt( line );
208 if ( !geometry.isNull() && typeIsAcceptable( geometry.wkbType() ) )
209 {
210 mPastedGeom = QgsReferencedGeometry( geometry, QgsCoordinateReferenceSystem() );
211 return;
212 }
213 }
214 }
215
216 // try reading a GeoJSON
217 const QgsFeatureList features = QgsJsonUtils::stringToFeatureList( text );
218 if ( !features.isEmpty() && features.at( 0 ).hasGeometry() )
219 {
220 // assume EPSG:4326 for GeoJSON
221 mPastedGeom = QgsReferencedGeometry( features.at( 0 ).geometry(), QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
222 return;
223 }
224}
225
226bool QgsGeometryWidget::typeIsAcceptable( Qgis::WkbType type ) const
227{
228 if ( mAcceptedTypes.isEmpty() )
229 {
230 return true;
231 }
232
233 return mAcceptedTypes.contains( type );
234}
235
236void QgsGeometryWidget::prepareMenu()
237{
238 fetchGeomFromClipboard();
239
240 mCopyGeoJsonAction->setEnabled( !mGeometry.isNull() );
241 mCopyWktAction->setEnabled( !mGeometry.isNull() );
242 mClearAction->setEnabled( !mGeometry.isNull() && !mReadOnly );
243 mPasteAction->setEnabled( !mPastedGeom.isNull() && !mReadOnly );
244}
245
246void QgsGeometryWidget::updateLineEdit()
247{
248 if ( mGeometry.isNull() )
249 {
250 mLineEdit->setText( QgsApplication::nullRepresentation() );
251 }
252 else
253 {
254 QString wkt = mGeometry.asWkt();
255 if ( wkt.length() >= 1050 )
256 {
257 wkt = wkt.left( QgsField::MAX_WKT_LENGTH ) + QChar( 0x2026 );
258 }
259
260 if ( mGeometry.crs().isValid() )
261 {
262 mLineEdit->setText( QStringLiteral( "%1 [%2]" ).arg( wkt,
263 mGeometry.crs().userFriendlyIdentifier( ) ) );
264 }
265 else
266 {
267 mLineEdit->setText( wkt );
268 }
269 }
270}
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition: qgis.h:182
static QString nullRepresentation()
This string is 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.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QString userFriendlyIdentifier(Qgis::CrsIdentifierType type=Qgis::CrsIdentifierType::MediumString) const
Returns a user friendly identifier for the CRS.
static constexpr int MAX_WKT_LENGTH
Definition: qgsfield.h:509
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.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:162
Q_GADGET bool isNull
Definition: qgsgeometry.h:164
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
QString asJson(int precision=17) const
Exports the geometry to a GeoJSON string.
QString asWkt(int precision=17) const
Exports the geometry to WKT.
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.
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:917