QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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( 0 );
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 mWidth->setEnabled( true );
165 }
166 else if ( fieldType == QLatin1String( "integer" ) )
167 {
168 if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 10 )
169 mWidth->setText( QStringLiteral( "10" ) );
170 mPrecision->clear();
171 mPrecision->setEnabled( false );
172 mWidth->setValidator( new QIntValidator( 1, 10, this ) );
173 mWidth->setEnabled( true );
174 }
175 else if ( fieldType == QLatin1String( "double" ) )
176 {
177 if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 30 )
178 mWidth->setText( QStringLiteral( "30" ) );
179 if ( mPrecision->text().toInt() < 1 || mPrecision->text().toInt() > 30 )
180 mPrecision->setText( QStringLiteral( "6" ) );
181 mPrecision->setEnabled( true );
182 mWidth->setValidator( new QIntValidator( 1, 20, this ) );
183 mWidth->setEnabled( true );
184 }
185 else if ( fieldType == QLatin1String( "bool" ) )
186 {
187 mWidth->clear();
188 mWidth->setEnabled( false );
189 mPrecision->clear();
190 mPrecision->setEnabled( false );
191 }
192 else if ( fieldType == QLatin1String( "date" ) )
193 {
194 mWidth->clear();
195 mWidth->setEnabled( false );
196 mPrecision->clear();
197 mPrecision->setEnabled( false );
198 }
199 else if ( fieldType == QLatin1String( "time" ) )
200 {
201 mWidth->clear();
202 mWidth->setEnabled( false );
203 mPrecision->clear();
204 mPrecision->setEnabled( false );
205 }
206 else if ( fieldType == QLatin1String( "datetime" ) )
207 {
208 mWidth->clear();
209 mWidth->setEnabled( false );
210 mPrecision->clear();
211 mPrecision->setEnabled( false );
212 }
213 else if ( fieldType == QStringLiteral( "binary" )
214 || fieldType == QStringLiteral( "stringlist" )
215 || fieldType == QStringLiteral( "integerlist" )
216 || fieldType == QStringLiteral( "doublelist" )
217 || fieldType == QStringLiteral( "integer64list" )
218 || fieldType == QStringLiteral( "map" )
219 || fieldType == QLatin1String( "geometry" ) )
220 {
221 mWidth->clear();
222 mWidth->setEnabled( false );
223 mPrecision->clear();
224 mPrecision->setEnabled( false );
225 }
226 else
227 {
228 QgsDebugError( QStringLiteral( "unexpected index" ) );
229 }
230}
231
233{
234 mCrsSelector->setCrs( crs );
235}
236
238{
239 return mCrsSelector->crs();
240}
241
243{
244 return mNameLineEdit->text();
245}
246
247void QgsNewMemoryLayerDialog::fieldNameChanged( const QString &name )
248{
249 mAddAttributeButton->setDisabled( name.isEmpty() || ! mAttributeView->findItems( name, Qt::MatchExactly ).isEmpty() );
250}
251
252void QgsNewMemoryLayerDialog::selectionChanged()
253{
254 mRemoveAttributeButton->setDisabled( mAttributeView->selectedItems().isEmpty() );
255}
256
258{
260
261 QTreeWidgetItemIterator it( mAttributeView );
262 while ( *it )
263 {
264 const QString name( ( *it )->text( 0 ) );
265 const QString typeName( ( *it )->text( 1 ) );
266 const int width = ( *it )->text( 2 ).toInt();
267 const int precision = ( *it )->text( 3 ).toInt();
268 QVariant::Type fieldType = QVariant::Invalid;
269 QVariant::Type fieldSubType = QVariant::Invalid;
270 if ( typeName == QLatin1String( "string" ) )
271 fieldType = QVariant::String;
272 else if ( typeName == QLatin1String( "integer" ) )
273 fieldType = QVariant::Int;
274 else if ( typeName == QLatin1String( "double" ) )
275 fieldType = QVariant::Double;
276 else if ( typeName == QLatin1String( "bool" ) )
277 fieldType = QVariant::Bool;
278 else if ( typeName == QLatin1String( "date" ) )
279 fieldType = QVariant::Date;
280 else if ( typeName == QLatin1String( "time" ) )
281 fieldType = QVariant::Time;
282 else if ( typeName == QLatin1String( "datetime" ) )
283 fieldType = QVariant::DateTime;
284 else if ( typeName == QLatin1String( "binary" ) )
285 fieldType = QVariant::ByteArray;
286 else if ( typeName == QLatin1String( "stringlist" ) )
287 {
288 fieldType = QVariant::StringList;
289 fieldSubType = QVariant::String;
290 }
291 else if ( typeName == QLatin1String( "integerlist" ) )
292 {
293 fieldType = QVariant::List;
294 fieldSubType = QVariant::Int;
295 }
296 else if ( typeName == QLatin1String( "doublelist" ) )
297 {
298 fieldType = QVariant::List;
299 fieldSubType = QVariant::Double;
300 }
301 else if ( typeName == QLatin1String( "integer64list" ) )
302 {
303 fieldType = QVariant::List;
304 fieldSubType = QVariant::LongLong;
305 }
306 else if ( typeName == QLatin1String( "map" ) )
307 fieldType = QVariant::Map;
308 else if ( typeName == QLatin1String( "geometry" ) )
309 fieldType = QVariant::UserType;
310
311 const QgsField field = QgsField( name, fieldType, typeName, width, precision, QString(), fieldSubType );
312 fields.append( field );
313 ++it;
314 }
315
316 return fields;
317}
318
320{
321 if ( !mFieldNameEdit->text().trimmed().isEmpty() )
322 {
323 const QString currentFieldName = mFieldNameEdit->text();
324 if ( fields().lookupField( currentFieldName ) == -1 )
325 {
326 if ( QMessageBox::question( this, tr( "New Temporary Scratch Layer" ),
327 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 ),
328 QMessageBox::Ok | QMessageBox::Cancel ) != QMessageBox::Ok )
329 {
330 return;
331 }
332 }
333 }
334
335 QDialog::accept();
336}
337
338void QgsNewMemoryLayerDialog::mAddAttributeButton_clicked()
339{
340 if ( !mFieldNameEdit->text().isEmpty() )
341 {
342 const QString fieldName = mFieldNameEdit->text();
343 const QString fieldType = mTypeBox->currentData( Qt::UserRole ).toString();
344 const QString width = mWidth->text();
345 const QString precision = mPrecision->text();
346 mAttributeView->addTopLevelItem( new QTreeWidgetItem( QStringList() << fieldName << fieldType << width << precision ) );
347
348 mFieldNameEdit->clear();
349 }
350}
351
352void QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked()
353{
354 delete mAttributeView->currentItem();
355}
356
357void QgsNewMemoryLayerDialog::showHelp()
358{
359 QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#creating-a-new-temporary-scratch-layer" ) );
360}
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition: qgis.h:182
@ 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:53
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:194
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(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 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.
Definition: qgswkbtypes.h:1092
static Qgis::WkbType addZ(Qgis::WkbType type)
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1068
#define QgsDebugError(str)
Definition: qgslogger.h:38
const QgsCoordinateReferenceSystem & crs
const QString & typeName
int precision