QGIS API Documentation 3.30.0-'s-Hertogenbosch (f186b8efe0)
qgsnewmemorylayerdialog.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsnewmemorylayerdialog.cpp
3 -------------------
4 begin : September 2014
5 copyright : (C) 2014 by Nyall Dawson, Marco Hugentobler
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19#include "qgis.h"
21#include "qgsvectorlayer.h"
22#include "qgsfield.h"
23#include "qgsfields.h"
25#include "qgsgui.h"
26#include "qgsiconutils.h"
27#include "qgsvariantutils.h"
28
29#include <QPushButton>
30#include <QComboBox>
31#include <QUuid>
32#include <QFileDialog>
33#include <QMessageBox>
34
36{
37 QgsNewMemoryLayerDialog dialog( parent );
38 dialog.setCrs( defaultCrs );
39 if ( dialog.exec() == QDialog::Rejected )
40 {
41 return nullptr;
42 }
43
44 const Qgis::WkbType geometrytype = dialog.selectedType();
45 const QgsFields fields = dialog.fields();
46 const QString name = dialog.layerName().isEmpty() ? tr( "New scratch layer" ) : dialog.layerName();
47 QgsVectorLayer *newLayer = QgsMemoryProviderUtils::createMemoryLayer( name, fields, geometrytype, dialog.crs() );
48 return newLayer;
49}
50
51QgsNewMemoryLayerDialog::QgsNewMemoryLayerDialog( QWidget *parent, Qt::WindowFlags fl )
52 : QDialog( parent, fl )
53{
54 setupUi( this );
56
57 mNameLineEdit->setText( tr( "New scratch layer" ) );
58
59 const Qgis::WkbType geomTypes[] =
60 {
72 };
73
74 for ( const auto type : geomTypes )
75 mGeometryTypeBox->addItem( QgsIconUtils::iconForWkbType( type ), QgsWkbTypes::translatedDisplayString( type ), static_cast< quint32>( type ) );
76 mGeometryTypeBox->setCurrentIndex( -1 );
77
78 mGeometryWithZCheckBox->setEnabled( false );
79 mGeometryWithMCheckBox->setEnabled( false );
80 mCrsSelector->setEnabled( false );
81 mCrsSelector->setShowAccuracyWarnings( true );
82
83 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::String ), QgsVariantUtils::typeToDisplayString( QVariant::String ), "string" );
84 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::Int ), QgsVariantUtils::typeToDisplayString( QVariant::Int ), "integer" );
85 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::Double ), QgsVariantUtils::typeToDisplayString( QVariant::Double ), "double" );
86 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::Bool ), QgsVariantUtils::typeToDisplayString( QVariant::Bool ), "bool" );
87 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::Date ), QgsVariantUtils::typeToDisplayString( QVariant::Date ), "date" );
88 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::Time ), QgsVariantUtils::typeToDisplayString( QVariant::Time ), "time" );
89 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::DateTime ), QgsVariantUtils::typeToDisplayString( QVariant::DateTime ), "datetime" );
90 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::ByteArray ), QgsVariantUtils::typeToDisplayString( QVariant::ByteArray ), "binary" );
91 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::StringList ), QgsVariantUtils::typeToDisplayString( QVariant::StringList ), "stringlist" );
92 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::List, QVariant::Int ), QgsVariantUtils::typeToDisplayString( QVariant::List, QVariant::Int ), "integerlist" );
93 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::List, QVariant::Double ), QgsVariantUtils::typeToDisplayString( QVariant::List, QVariant::Double ), "doublelist" );
94 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::List, QVariant::LongLong ), QgsVariantUtils::typeToDisplayString( QVariant::List, QVariant::LongLong ), "integer64list" );
95 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::Map ), QgsVariantUtils::typeToDisplayString( QVariant::Map ), "map" );
96 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::UserType, QVariant::Invalid, QStringLiteral( "geometry" ) ), tr( "Geometry" ), "geometry" );
97 mTypeBox_currentIndexChanged( 1 );
98
99 mWidth->setValidator( new QIntValidator( 1, 255, this ) );
100 mPrecision->setValidator( new QIntValidator( 0, 30, this ) );
101
102 mAddAttributeButton->setEnabled( false );
103 mRemoveAttributeButton->setEnabled( false );
104
105 mOkButton = mButtonBox->button( QDialogButtonBox::Ok );
106 mOkButton->setEnabled( false );
107
108 connect( mGeometryTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewMemoryLayerDialog::geometryTypeChanged );
109 connect( mFieldNameEdit, &QLineEdit::textChanged, this, &QgsNewMemoryLayerDialog::fieldNameChanged );
110 connect( mTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewMemoryLayerDialog::mTypeBox_currentIndexChanged );
111 connect( mAttributeView, &QTreeWidget::itemSelectionChanged, this, &QgsNewMemoryLayerDialog::selectionChanged );
112 connect( mAddAttributeButton, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::mAddAttributeButton_clicked );
113 connect( mRemoveAttributeButton, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked );
114
115 connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsNewMemoryLayerDialog::showHelp );
116 connect( mButtonBox, &QDialogButtonBox::accepted, this, &QgsNewMemoryLayerDialog::accept );
117 connect( mButtonBox, &QDialogButtonBox::rejected, this, &QgsNewMemoryLayerDialog::reject );
118
119 mNameLineEdit->selectAll();
120 mNameLineEdit->setFocus();
121}
122
124{
126 geomType = static_cast<Qgis::WkbType>
127 ( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() );
128
129 if ( geomType != Qgis::WkbType::Unknown && geomType != Qgis::WkbType::NoGeometry )
130 {
131 if ( mGeometryWithZCheckBox->isChecked() )
132 geomType = QgsWkbTypes::addZ( geomType );
133 if ( mGeometryWithMCheckBox->isChecked() )
134 geomType = QgsWkbTypes::addM( geomType );
135 }
136
137 return geomType;
138}
139
140void QgsNewMemoryLayerDialog::geometryTypeChanged( int )
141{
142 const Qgis::WkbType geomType = static_cast<Qgis::WkbType>
143 ( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() );
144
145 const bool isSpatial = geomType != Qgis::WkbType::NoGeometry;
146 mGeometryWithZCheckBox->setEnabled( isSpatial );
147 mGeometryWithMCheckBox->setEnabled( isSpatial );
148 mCrsSelector->setEnabled( isSpatial );
149
150 const bool ok = ( !mNameLineEdit->text().isEmpty() && mGeometryTypeBox->currentIndex() != -1 );
151 mOkButton->setEnabled( ok );
152}
153
154void QgsNewMemoryLayerDialog::mTypeBox_currentIndexChanged( int )
155{
156 const QString fieldType = mTypeBox->currentData().toString();
157 if ( fieldType == QLatin1String( "string" ) )
158 {
159 if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 255 )
160 mWidth->setText( QStringLiteral( "255" ) );
161 mPrecision->clear();
162 mPrecision->setEnabled( false );
163 mWidth->setValidator( new QIntValidator( 1, 255, this ) );
164 }
165 else if ( fieldType == QLatin1String( "integer" ) )
166 {
167 if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 10 )
168 mWidth->setText( QStringLiteral( "10" ) );
169 mPrecision->clear();
170 mPrecision->setEnabled( false );
171 mWidth->setValidator( new QIntValidator( 1, 10, this ) );
172 }
173 else if ( fieldType == QLatin1String( "double" ) )
174 {
175 if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 30 )
176 mWidth->setText( QStringLiteral( "30" ) );
177 if ( mPrecision->text().toInt() < 1 || mPrecision->text().toInt() > 30 )
178 mPrecision->setText( QStringLiteral( "6" ) );
179 mPrecision->setEnabled( true );
180 mWidth->setValidator( new QIntValidator( 1, 20, this ) );
181 }
182 else if ( fieldType == QLatin1String( "bool" ) )
183 {
184 mWidth->clear();
185 mWidth->setEnabled( false );
186 mPrecision->clear();
187 mPrecision->setEnabled( false );
188 }
189 else if ( fieldType == QLatin1String( "date" ) )
190 {
191 mWidth->clear();
192 mWidth->setEnabled( false );
193 mPrecision->clear();
194 mPrecision->setEnabled( false );
195 }
196 else if ( fieldType == QLatin1String( "time" ) )
197 {
198 mWidth->clear();
199 mWidth->setEnabled( false );
200 mPrecision->clear();
201 mPrecision->setEnabled( false );
202 }
203 else if ( fieldType == QLatin1String( "datetime" ) )
204 {
205 mWidth->clear();
206 mWidth->setEnabled( false );
207 mPrecision->clear();
208 mPrecision->setEnabled( false );
209 }
210 else if ( fieldType == QStringLiteral( "binary" )
211 || fieldType == QStringLiteral( "stringlist" )
212 || fieldType == QStringLiteral( "integerlist" )
213 || fieldType == QStringLiteral( "doublelist" )
214 || fieldType == QStringLiteral( "integer64list" )
215 || fieldType == QStringLiteral( "map" )
216 || fieldType == QLatin1String( "geometry" ) )
217 {
218 mWidth->clear();
219 mWidth->setEnabled( false );
220 mPrecision->clear();
221 mPrecision->setEnabled( false );
222 }
223 else
224 {
225 QgsDebugMsg( QStringLiteral( "unexpected index" ) );
226 }
227}
228
230{
231 mCrsSelector->setCrs( crs );
232}
233
235{
236 return mCrsSelector->crs();
237}
238
240{
241 return mNameLineEdit->text();
242}
243
244void QgsNewMemoryLayerDialog::fieldNameChanged( const QString &name )
245{
246 mAddAttributeButton->setDisabled( name.isEmpty() || ! mAttributeView->findItems( name, Qt::MatchExactly ).isEmpty() );
247}
248
249void QgsNewMemoryLayerDialog::selectionChanged()
250{
251 mRemoveAttributeButton->setDisabled( mAttributeView->selectedItems().isEmpty() );
252}
253
255{
257
258 QTreeWidgetItemIterator it( mAttributeView );
259 while ( *it )
260 {
261 const QString name( ( *it )->text( 0 ) );
262 const QString typeName( ( *it )->text( 1 ) );
263 const int width = ( *it )->text( 2 ).toInt();
264 const int precision = ( *it )->text( 3 ).toInt();
265 QVariant::Type fieldType = QVariant::Invalid;
266 QVariant::Type fieldSubType = QVariant::Invalid;
267 if ( typeName == QLatin1String( "string" ) )
268 fieldType = QVariant::String;
269 else if ( typeName == QLatin1String( "integer" ) )
270 fieldType = QVariant::Int;
271 else if ( typeName == QLatin1String( "double" ) )
272 fieldType = QVariant::Double;
273 else if ( typeName == QLatin1String( "bool" ) )
274 fieldType = QVariant::Bool;
275 else if ( typeName == QLatin1String( "date" ) )
276 fieldType = QVariant::Date;
277 else if ( typeName == QLatin1String( "time" ) )
278 fieldType = QVariant::Time;
279 else if ( typeName == QLatin1String( "datetime" ) )
280 fieldType = QVariant::DateTime;
281 else if ( typeName == QLatin1String( "binary" ) )
282 fieldType = QVariant::ByteArray;
283 else if ( typeName == QLatin1String( "stringlist" ) )
284 {
285 fieldType = QVariant::StringList;
286 fieldSubType = QVariant::String;
287 }
288 else if ( typeName == QLatin1String( "integerlist" ) )
289 {
290 fieldType = QVariant::List;
291 fieldSubType = QVariant::Int;
292 }
293 else if ( typeName == QLatin1String( "doublelist" ) )
294 {
295 fieldType = QVariant::List;
296 fieldSubType = QVariant::Double;
297 }
298 else if ( typeName == QLatin1String( "integer64list" ) )
299 {
300 fieldType = QVariant::List;
301 fieldSubType = QVariant::LongLong;
302 }
303 else if ( typeName == QLatin1String( "map" ) )
304 fieldType = QVariant::Map;
305 else if ( typeName == QLatin1String( "geometry" ) )
306 fieldType = QVariant::UserType;
307
308 const QgsField field = QgsField( name, fieldType, typeName, width, precision, QString(), fieldSubType );
310 ++it;
311 }
312
313 return fields;
314}
315
317{
318 if ( !mFieldNameEdit->text().trimmed().isEmpty() )
319 {
320 const QString currentFieldName = mFieldNameEdit->text();
321 if ( fields().lookupField( currentFieldName ) == -1 )
322 {
323 if ( QMessageBox::question( this, tr( "New Temporary Scratch Layer" ),
324 tr( "The field “%1” has not been added to the fields list. Are you sure you want to proceed and discard this field?" ).arg( currentFieldName ),
325 QMessageBox::Ok | QMessageBox::Cancel ) != QMessageBox::Ok )
326 {
327 return;
328 }
329 }
330 }
331
332 QDialog::accept();
333}
334
335void QgsNewMemoryLayerDialog::mAddAttributeButton_clicked()
336{
337 if ( !mFieldNameEdit->text().isEmpty() )
338 {
339 const QString fieldName = mFieldNameEdit->text();
340 const QString fieldType = mTypeBox->currentData( Qt::UserRole ).toString();
341 const QString width = mWidth->text();
342 const QString precision = mPrecision->text();
343 mAttributeView->addTopLevelItem( new QTreeWidgetItem( QStringList() << fieldName << fieldType << width << precision ) );
344
345 mFieldNameEdit->clear();
346 }
347}
348
349void QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked()
350{
351 delete mAttributeView->currentItem();
352}
353
354void QgsNewMemoryLayerDialog::showHelp()
355{
356 QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#creating-a-new-temporary-scratch-layer" ) );
357}
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition: qgis.h:155
@ CompoundCurve
CompoundCurve.
@ LineString
LineString.
@ MultiPoint
MultiPoint.
@ Polygon
Polygon.
@ MultiPolygon
MultiPolygon.
@ NoGeometry
No geometry.
@ MultiLineString
MultiLineString.
@ Unknown
Unknown.
@ MultiCurve
MultiCurve.
@ CurvePolygon
CurvePolygon.
@ MultiSurface
MultiSurface.
This class represents a coordinate reference system (CRS).
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:52
Container of fields for a vector layer.
Definition: qgsfields.h:45
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false)
Definition: qgsfields.cpp:59
static QIcon iconForFieldType(QVariant::Type type, QVariant::Type subType=QVariant::Type::Invalid, const QString &typeString=QString())
Returns an icon corresponding to a field type.
Definition: qgsfields.cpp:294
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition: qgsgui.cpp:178
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:38
static QIcon iconForWkbType(Qgis::WkbType type)
Returns the icon for a vector layer whose geometry type is provided.
static QgsVectorLayer * createMemoryLayer(const QString &name, const QgsFields &fields, Qgis::WkbType geometryType=Qgis::WkbType::NoGeometry, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem(), bool loadDefaultStyle=true) SIP_FACTORY
Creates a new memory layer using the specified parameters.
QgsCoordinateReferenceSystem crs() const
Returns the selected CRS for the new layer.
QgsFields fields() const
Returns attributes for the new layer.
QString layerName() const
Returns the layer name.
Qgis::WkbType selectedType() const
Returns the selected geometry type.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the crs value for the new layer in the dialog.
static QgsVectorLayer * runAndCreateLayer(QWidget *parent=nullptr, const QgsCoordinateReferenceSystem &defaultCrs=QgsCoordinateReferenceSystem())
Runs the dialog and creates a new memory layer.
QgsNewMemoryLayerDialog(QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags)
New dialog constructor.
static QString typeToDisplayString(QVariant::Type type, QVariant::Type subType=QVariant::Type::Invalid)
Returns a user-friendly translated string representing a QVariant type.
Represents a vector layer which manages a vector based data sets.
static Qgis::WkbType addZ(Qgis::WkbType type) SIP_HOLDGIL
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1073
static Qgis::WkbType addM(Qgis::WkbType type) SIP_HOLDGIL
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1098
static QString translatedDisplayString(Qgis::WkbType type) SIP_HOLDGIL
Returns a translated display string type for a WKB type, e.g., the geometry name used in WKT geometry...
const QgsField & field
Definition: qgsfield.h:501
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
const QgsCoordinateReferenceSystem & crs
const QString & typeName
int precision