QGIS API Documentation 3.39.0-Master (bca3cdb6021)
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#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 {
75 };
76
77 for ( const auto type : geomTypes )
78 mGeometryTypeBox->addItem( QgsIconUtils::iconForWkbType( type ), QgsWkbTypes::translatedDisplayString( type ), static_cast< quint32>( type ) );
79 mGeometryTypeBox->setCurrentIndex( -1 );
80
81 mGeometryWithZCheckBox->setEnabled( false );
82 mGeometryWithMCheckBox->setEnabled( false );
83 mCrsSelector->setEnabled( false );
84 mCrsSelector->setShowAccuracyWarnings( true );
85
86 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QString ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QString ), "string" );
87 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::Int ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::Int ), "integer" );
88 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::Double ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::Double ), "double" );
89 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::Bool ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::Bool ), "bool" );
90 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QDate ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QDate ), "date" );
91 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QTime ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QTime ), "time" );
92 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QDateTime ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QDateTime ), "datetime" );
93 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QByteArray ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QByteArray ), "binary" );
94 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QStringList ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QStringList ), "stringlist" );
95 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QVariantList, QMetaType::Type::Int ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QVariantList, QMetaType::Type::Int ), "integerlist" );
96 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QVariantList, QMetaType::Type::Double ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QVariantList, QMetaType::Type::Double ), "doublelist" );
97 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QVariantList, QMetaType::Type::LongLong ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QVariantList, QMetaType::Type::LongLong ), "integer64list" );
98 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::QVariantMap ), QgsVariantUtils::typeToDisplayString( QMetaType::Type::QVariantMap ), "map" );
99 mTypeBox->addItem( QgsFields::iconForFieldType( QMetaType::Type::User, QMetaType::Type::UnknownType, QStringLiteral( "geometry" ) ), tr( "Geometry" ), "geometry" );
100 mTypeBox_currentIndexChanged( 0 );
101
102 mWidth->setValidator( new QIntValidator( 1, 255, this ) );
103 mPrecision->setValidator( new QIntValidator( 0, 30, this ) );
104
105 mAddAttributeButton->setEnabled( false );
106 mRemoveAttributeButton->setEnabled( false );
107 mButtonUp->setEnabled( false );
108 mButtonDown->setEnabled( false );
109
110 mOkButton = mButtonBox->button( QDialogButtonBox::Ok );
111 mOkButton->setEnabled( false );
112
113 connect( mGeometryTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewMemoryLayerDialog::geometryTypeChanged );
114 connect( mFieldNameEdit, &QLineEdit::textChanged, this, &QgsNewMemoryLayerDialog::fieldNameChanged );
115 connect( mTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewMemoryLayerDialog::mTypeBox_currentIndexChanged );
116 connect( mAttributeView, &QTreeWidget::itemSelectionChanged, this, &QgsNewMemoryLayerDialog::selectionChanged );
117 connect( mAddAttributeButton, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::mAddAttributeButton_clicked );
118 connect( mRemoveAttributeButton, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked );
119 connect( mButtonUp, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::moveFieldsUp );
120 connect( mButtonDown, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::moveFieldsDown );
121
122 connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsNewMemoryLayerDialog::showHelp );
123 connect( mButtonBox, &QDialogButtonBox::accepted, this, &QgsNewMemoryLayerDialog::accept );
124 connect( mButtonBox, &QDialogButtonBox::rejected, this, &QgsNewMemoryLayerDialog::reject );
125
126 mNameLineEdit->selectAll();
127 mNameLineEdit->setFocus();
128}
129
131{
133 geomType = static_cast<Qgis::WkbType>
134 ( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() );
135
136 if ( geomType != Qgis::WkbType::Unknown && geomType != Qgis::WkbType::NoGeometry )
137 {
138 if ( mGeometryWithZCheckBox->isChecked() )
139 geomType = QgsWkbTypes::addZ( geomType );
140 if ( mGeometryWithMCheckBox->isChecked() )
141 geomType = QgsWkbTypes::addM( geomType );
142 }
143
144 return geomType;
145}
146
147void QgsNewMemoryLayerDialog::geometryTypeChanged( int )
148{
149 const Qgis::WkbType geomType = static_cast<Qgis::WkbType>
150 ( 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" ),
336 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 ),
337 QMessageBox::Ok | QMessageBox::Cancel ) != QMessageBox::Ok )
338 {
339 return;
340 }
341 }
342 }
343
344 QDialog::accept();
345}
346
347void QgsNewMemoryLayerDialog::mAddAttributeButton_clicked()
348{
349 if ( !mFieldNameEdit->text().isEmpty() )
350 {
351 const QString fieldName = mFieldNameEdit->text();
352 const QString fieldType = mTypeBox->currentData( Qt::UserRole ).toString();
353 const QString width = mWidth->text();
354 const QString precision = mPrecision->text();
355 mAttributeView->addTopLevelItem( new QTreeWidgetItem( QStringList() << fieldName << fieldType << width << precision ) );
356
357 mFieldNameEdit->clear();
358
359 if ( !mFieldNameEdit->hasFocus() )
360 {
361 mFieldNameEdit->setFocus();
362 }
363 }
364}
365
366void QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked()
367{
368 delete mAttributeView->currentItem();
369}
370
371void QgsNewMemoryLayerDialog::showHelp()
372{
373 QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#creating-a-new-temporary-scratch-layer" ) );
374}
375
376void QgsNewMemoryLayerDialog::moveFieldsUp()
377{
378 int currentRow = mAttributeView->currentIndex().row();
379 if ( currentRow == 0 )
380 return;
381
382 mAttributeView->insertTopLevelItem( currentRow - 1, mAttributeView->takeTopLevelItem( currentRow ) );
383 mAttributeView->setCurrentIndex( mAttributeView->model()->index( currentRow - 1, 0 ) );
384}
385
386void QgsNewMemoryLayerDialog::moveFieldsDown()
387{
388 int currentRow = mAttributeView->currentIndex().row();
389 if ( currentRow == mAttributeView->topLevelItemCount() - 1 )
390 return;
391
392 mAttributeView->insertTopLevelItem( currentRow + 1, mAttributeView->takeTopLevelItem( currentRow ) );
393 mAttributeView->setCurrentIndex( mAttributeView->model()->index( currentRow + 1, 0 ) );
394}
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:256
@ CompoundCurve
CompoundCurve.
@ LineString
LineString.
@ MultiPoint
MultiPoint.
@ Polygon
Polygon.
@ MultiPolygon
MultiPolygon.
@ Triangle
Triangle.
@ NoGeometry
No geometry.
@ MultiLineString
MultiLineString.
@ Unknown
Unknown.
@ MultiCurve
MultiCurve.
@ CurvePolygon
CurvePolygon.
@ PolyhedralSurface
PolyhedralSurface.
@ MultiSurface
MultiSurface.
This class represents a coordinate reference system (CRS).
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:53
Container of fields for a vector layer.
Definition qgsfields.h:46
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
Definition qgsfields.cpp:69
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:208
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition qgshelp.cpp:39
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 data sets.
static 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:38
const QgsCoordinateReferenceSystem & crs
const QString & typeName
int precision