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