QGIS API Documentation 3.99.0-Master (2fe06baccd8)
Loading...
Searching...
No Matches
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
20#include "qgis.h"
22#include "qgsfield.h"
23#include "qgsfields.h"
24#include "qgsgui.h"
25#include "qgsiconutils.h"
27#include "qgsvariantutils.h"
28#include "qgsvectorlayer.h"
29
30#include <QComboBox>
31#include <QFileDialog>
32#include <QMessageBox>
33#include <QPushButton>
34#include <QUuid>
35
36#include "moc_qgsnewmemorylayerdialog.cpp"
37
39{
40 QgsNewMemoryLayerDialog dialog( parent );
41 dialog.setCrs( defaultCrs );
42 if ( dialog.exec() == QDialog::Rejected )
43 {
44 return nullptr;
45 }
46
47 const Qgis::WkbType geometrytype = dialog.selectedType();
48 const QgsFields fields = dialog.fields();
49 const QString name = dialog.layerName().isEmpty() ? tr( "New scratch layer" ) : dialog.layerName();
50 QgsVectorLayer *newLayer = QgsMemoryProviderUtils::createMemoryLayer( name, fields, geometrytype, dialog.crs() );
51 return newLayer;
52}
53
54QgsNewMemoryLayerDialog::QgsNewMemoryLayerDialog( QWidget *parent, Qt::WindowFlags fl )
55 : QDialog( parent, fl )
56{
57 setupUi( this );
59
60 mNameLineEdit->setText( tr( "New scratch layer" ) );
61
62 const Qgis::WkbType geomTypes[] = {
77 };
78
79 for ( const auto type : geomTypes )
80 mGeometryTypeBox->addItem( QgsIconUtils::iconForWkbType( type ), QgsWkbTypes::translatedDisplayString( type ), static_cast<quint32>( type ) );
81 mGeometryTypeBox->setCurrentIndex( -1 );
82
83 mGeometryWithZCheckBox->setEnabled( false );
84 mGeometryWithMCheckBox->setEnabled( false );
85 mCrsSelector->setEnabled( false );
86 mCrsSelector->setShowAccuracyWarnings( true );
87
88 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QString ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QString ), "string" );
89 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::Int ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::Int ), "integer" );
90 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::Double ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::Double ), "double" );
91 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::Bool ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::Bool ), "bool" );
92 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QDate ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QDate ), "date" );
93 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QTime ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QTime ), "time" );
94 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QDateTime ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QDateTime ), "datetime" );
95 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QByteArray ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QByteArray ), "binary" );
96 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QStringList ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QStringList ), "stringlist" );
97 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QVariantList, QMetaType::Type::Int ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QVariantList, QMetaType::Type::Int ), "integerlist" );
98 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QVariantList, QMetaType::Type::Double ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QVariantList, QMetaType::Type::Double ), "doublelist" );
99 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QVariantList, QMetaType::Type::LongLong ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QVariantList, QMetaType::Type::LongLong ), "integer64list" );
100 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QVariantMap ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QVariantMap ), "map" );
101 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::User, QMetaType::Type::UnknownType, QStringLiteral( "geometry" ) ), tr( "Geometry" ), "geometry" );
102 mTypeBox_currentIndexChanged( 0 );
103
104 mWidth->setValidator( new QIntValidator( 1, 255, this ) );
105 mPrecision->setValidator( new QIntValidator( 0, 30, this ) );
106
107 mAddAttributeButton->setEnabled( false );
108 mRemoveAttributeButton->setEnabled( false );
109 mButtonUp->setEnabled( false );
110 mButtonDown->setEnabled( false );
111
112 mOkButton = mButtonBox->button( QDialogButtonBox::Ok );
113 mOkButton->setEnabled( false );
114
115 connect( mGeometryTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewMemoryLayerDialog::geometryTypeChanged );
116 connect( mFieldNameEdit, &QLineEdit::textChanged, this, &QgsNewMemoryLayerDialog::fieldNameChanged );
117 connect( mTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewMemoryLayerDialog::mTypeBox_currentIndexChanged );
118 connect( mAttributeView, &QTreeWidget::itemSelectionChanged, this, &QgsNewMemoryLayerDialog::selectionChanged );
119 connect( mAddAttributeButton, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::mAddAttributeButton_clicked );
120 connect( mRemoveAttributeButton, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked );
121 connect( mButtonUp, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::moveFieldsUp );
122 connect( mButtonDown, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::moveFieldsDown );
123
124 connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsNewMemoryLayerDialog::showHelp );
125 connect( mButtonBox, &QDialogButtonBox::accepted, this, &QgsNewMemoryLayerDialog::accept );
126 connect( mButtonBox, &QDialogButtonBox::rejected, this, &QgsNewMemoryLayerDialog::reject );
127
128 mNameLineEdit->selectAll();
129 mNameLineEdit->setFocus();
130}
131
133{
135 geomType = static_cast<Qgis::WkbType>( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() );
136
137 if ( geomType != Qgis::WkbType::Unknown && geomType != Qgis::WkbType::NoGeometry )
138 {
139 if ( mGeometryWithZCheckBox->isChecked() )
140 geomType = QgsWkbTypes::addZ( geomType );
141 if ( mGeometryWithMCheckBox->isChecked() )
142 geomType = QgsWkbTypes::addM( geomType );
143 }
144
145 return geomType;
146}
147
148void QgsNewMemoryLayerDialog::geometryTypeChanged( int )
149{
150 const Qgis::WkbType geomType = static_cast<Qgis::WkbType>( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() );
151
152 const bool isSpatial = geomType != Qgis::WkbType::NoGeometry;
153 mGeometryWithZCheckBox->setEnabled( isSpatial );
154 mGeometryWithMCheckBox->setEnabled( isSpatial );
155 mCrsSelector->setEnabled( isSpatial );
156
157 const bool ok = ( !mNameLineEdit->text().isEmpty() && mGeometryTypeBox->currentIndex() != -1 );
158 mOkButton->setEnabled( ok );
159}
160
161void QgsNewMemoryLayerDialog::mTypeBox_currentIndexChanged( int )
162{
163 const QString fieldType = mTypeBox->currentData().toString();
164 if ( fieldType == QLatin1String( "string" ) )
165 {
166 if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 255 )
167 mWidth->setText( QStringLiteral( "255" ) );
168 mPrecision->clear();
169 mPrecision->setEnabled( false );
170 mWidth->setValidator( new QIntValidator( 1, 255, this ) );
171 mWidth->setEnabled( true );
172 }
173 else if ( fieldType == QLatin1String( "integer" ) )
174 {
175 if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 10 )
176 mWidth->setText( QStringLiteral( "10" ) );
177 mPrecision->clear();
178 mPrecision->setEnabled( false );
179 mWidth->setValidator( new QIntValidator( 1, 10, this ) );
180 mWidth->setEnabled( true );
181 }
182 else if ( fieldType == QLatin1String( "double" ) )
183 {
184 if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 30 )
185 mWidth->setText( QStringLiteral( "30" ) );
186 if ( mPrecision->text().toInt() < 1 || mPrecision->text().toInt() > 30 )
187 mPrecision->setText( QStringLiteral( "6" ) );
188 mPrecision->setEnabled( true );
189 mWidth->setValidator( new QIntValidator( 1, 20, this ) );
190 mWidth->setEnabled( true );
191 }
192 else if ( fieldType == QLatin1String( "bool" ) )
193 {
194 mWidth->clear();
195 mWidth->setEnabled( false );
196 mPrecision->clear();
197 mPrecision->setEnabled( false );
198 }
199 else if ( fieldType == QLatin1String( "date" ) )
200 {
201 mWidth->clear();
202 mWidth->setEnabled( false );
203 mPrecision->clear();
204 mPrecision->setEnabled( false );
205 }
206 else if ( fieldType == QLatin1String( "time" ) )
207 {
208 mWidth->clear();
209 mWidth->setEnabled( false );
210 mPrecision->clear();
211 mPrecision->setEnabled( false );
212 }
213 else if ( fieldType == QLatin1String( "datetime" ) )
214 {
215 mWidth->clear();
216 mWidth->setEnabled( false );
217 mPrecision->clear();
218 mPrecision->setEnabled( false );
219 }
220 else if ( fieldType == QStringLiteral( "binary" )
221 || fieldType == QStringLiteral( "stringlist" )
222 || fieldType == QStringLiteral( "integerlist" )
223 || fieldType == QStringLiteral( "doublelist" )
224 || fieldType == QStringLiteral( "integer64list" )
225 || fieldType == QStringLiteral( "map" )
226 || fieldType == QLatin1String( "geometry" ) )
227 {
228 mWidth->clear();
229 mWidth->setEnabled( false );
230 mPrecision->clear();
231 mPrecision->setEnabled( false );
232 }
233 else
234 {
235 QgsDebugError( QStringLiteral( "unexpected index" ) );
236 }
237}
238
240{
241 mCrsSelector->setCrs( crs );
242}
243
245{
246 return mCrsSelector->crs();
247}
248
250{
251 return mNameLineEdit->text();
252}
253
254void QgsNewMemoryLayerDialog::fieldNameChanged( const QString &name )
255{
256 mAddAttributeButton->setDisabled( name.isEmpty() || !mAttributeView->findItems( name, Qt::MatchExactly ).isEmpty() );
257}
258
259void QgsNewMemoryLayerDialog::selectionChanged()
260{
261 mRemoveAttributeButton->setDisabled( mAttributeView->selectedItems().isEmpty() );
262 mButtonUp->setDisabled( mAttributeView->selectedItems().isEmpty() );
263 mButtonDown->setDisabled( mAttributeView->selectedItems().isEmpty() );
264}
265
267{
269
270 QTreeWidgetItemIterator it( mAttributeView );
271 while ( *it )
272 {
273 const QString name( ( *it )->text( 0 ) );
274 const QString typeName( ( *it )->text( 1 ) );
275 const int width = ( *it )->text( 2 ).toInt();
276 const int precision = ( *it )->text( 3 ).toInt();
277 QMetaType::Type fieldType = QMetaType::Type::UnknownType;
278 QMetaType::Type fieldSubType = QMetaType::Type::UnknownType;
279 if ( typeName == QLatin1String( "string" ) )
280 fieldType = QMetaType::Type::QString;
281 else if ( typeName == QLatin1String( "integer" ) )
282 fieldType = QMetaType::Type::Int;
283 else if ( typeName == QLatin1String( "double" ) )
284 fieldType = QMetaType::Type::Double;
285 else if ( typeName == QLatin1String( "bool" ) )
286 fieldType = QMetaType::Type::Bool;
287 else if ( typeName == QLatin1String( "date" ) )
288 fieldType = QMetaType::Type::QDate;
289 else if ( typeName == QLatin1String( "time" ) )
290 fieldType = QMetaType::Type::QTime;
291 else if ( typeName == QLatin1String( "datetime" ) )
292 fieldType = QMetaType::Type::QDateTime;
293 else if ( typeName == QLatin1String( "binary" ) )
294 fieldType = QMetaType::Type::QByteArray;
295 else if ( typeName == QLatin1String( "stringlist" ) )
296 {
297 fieldType = QMetaType::Type::QStringList;
298 fieldSubType = QMetaType::Type::QString;
299 }
300 else if ( typeName == QLatin1String( "integerlist" ) )
301 {
302 fieldType = QMetaType::Type::QVariantList;
303 fieldSubType = QMetaType::Type::Int;
304 }
305 else if ( typeName == QLatin1String( "doublelist" ) )
306 {
307 fieldType = QMetaType::Type::QVariantList;
308 fieldSubType = QMetaType::Type::Double;
309 }
310 else if ( typeName == QLatin1String( "integer64list" ) )
311 {
312 fieldType = QMetaType::Type::QVariantList;
313 fieldSubType = QMetaType::Type::LongLong;
314 }
315 else if ( typeName == QLatin1String( "map" ) )
316 fieldType = QMetaType::Type::QVariantMap;
317 else if ( typeName == QLatin1String( "geometry" ) )
318 fieldType = QMetaType::Type::User;
319
320 const QgsField field = QgsField( name, fieldType, typeName, width, precision, QString(), fieldSubType );
321 fields.append( field );
322 ++it;
323 }
324
325 return fields;
326}
327
329{
330 if ( !mFieldNameEdit->text().trimmed().isEmpty() )
331 {
332 const QString currentFieldName = mFieldNameEdit->text();
333 if ( fields().lookupField( currentFieldName ) == -1 )
334 {
335 if ( QMessageBox::question( this, tr( "New Temporary Scratch Layer" ), 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 ), QMessageBox::Ok | QMessageBox::Cancel ) != QMessageBox::Ok )
336 {
337 return;
338 }
339 }
340 }
341
342 QDialog::accept();
343}
344
345void QgsNewMemoryLayerDialog::mAddAttributeButton_clicked()
346{
347 if ( !mFieldNameEdit->text().isEmpty() )
348 {
349 const QString fieldName = mFieldNameEdit->text();
350 const QString fieldType = mTypeBox->currentData( Qt::UserRole ).toString();
351 const QString width = mWidth->text();
352 const QString precision = mPrecision->text();
353 mAttributeView->addTopLevelItem( new QTreeWidgetItem( QStringList() << fieldName << fieldType << width << precision ) );
354
355 mFieldNameEdit->clear();
356
357 if ( !mFieldNameEdit->hasFocus() )
358 {
359 mFieldNameEdit->setFocus();
360 }
361 }
362}
363
364void QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked()
365{
366 delete mAttributeView->currentItem();
367}
368
369void QgsNewMemoryLayerDialog::showHelp()
370{
371 QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#creating-a-new-temporary-scratch-layer" ) );
372}
373
374void QgsNewMemoryLayerDialog::moveFieldsUp()
375{
376 int currentRow = mAttributeView->currentIndex().row();
377 if ( currentRow == 0 )
378 return;
379
380 mAttributeView->insertTopLevelItem( currentRow - 1, mAttributeView->takeTopLevelItem( currentRow ) );
381 mAttributeView->setCurrentIndex( mAttributeView->model()->index( currentRow - 1, 0 ) );
382}
383
384void QgsNewMemoryLayerDialog::moveFieldsDown()
385{
386 int currentRow = mAttributeView->currentIndex().row();
387 if ( currentRow == mAttributeView->topLevelItemCount() - 1 )
388 return;
389
390 mAttributeView->insertTopLevelItem( currentRow + 1, mAttributeView->takeTopLevelItem( currentRow ) );
391 mAttributeView->setCurrentIndex( mAttributeView->model()->index( currentRow + 1, 0 ) );
392}
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:277
@ CompoundCurve
CompoundCurve.
Definition qgis.h:288
@ Point
Point.
Definition qgis.h:279
@ LineString
LineString.
Definition qgis.h:280
@ TIN
TIN.
Definition qgis.h:293
@ MultiPoint
MultiPoint.
Definition qgis.h:283
@ Polygon
Polygon.
Definition qgis.h:281
@ MultiPolygon
MultiPolygon.
Definition qgis.h:285
@ Triangle
Triangle.
Definition qgis.h:282
@ NoGeometry
No geometry.
Definition qgis.h:294
@ MultiLineString
MultiLineString.
Definition qgis.h:284
@ Unknown
Unknown.
Definition qgis.h:278
@ MultiCurve
MultiCurve.
Definition qgis.h:290
@ CurvePolygon
CurvePolygon.
Definition qgis.h:289
@ PolyhedralSurface
PolyhedralSurface.
Definition qgis.h:292
@ MultiSurface
MultiSurface.
Definition qgis.h:291
Represents a coordinate reference system (CRS).
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:54
Container of fields for a vector layer.
Definition qgsfields.h:46
static QIcon iconForFieldType(QMetaType::Type type, QMetaType::Type subType=QMetaType::Type::UnknownType, const QString &typeString=QString())
Returns an icon corresponding to a field type.
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:221
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(QMetaType::Type type, QMetaType::Type subType=QMetaType::Type::UnknownType)
Returns a user-friendly translated string representing a QVariant type.
Represents a vector layer which manages a vector based dataset.
static Q_INVOKABLE QString translatedDisplayString(Qgis::WkbType type)
Returns a translated display string type for a WKB type, e.g., the geometry name used in WKT geometry...
static Qgis::WkbType addM(Qgis::WkbType type)
Adds the m dimension to a WKB type and returns the new type.
static Qgis::WkbType addZ(Qgis::WkbType type)
Adds the z dimension to a WKB type and returns the new type.
#define QgsDebugError(str)
Definition qgslogger.h:57