QGIS API Documentation 3.41.0-Master (cea29feecf2)
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[] = {
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>( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() );
134
135 if ( geomType != Qgis::WkbType::Unknown && geomType != Qgis::WkbType::NoGeometry )
136 {
137 if ( mGeometryWithZCheckBox->isChecked() )
138 geomType = QgsWkbTypes::addZ( geomType );
139 if ( mGeometryWithMCheckBox->isChecked() )
140 geomType = QgsWkbTypes::addM( geomType );
141 }
142
143 return geomType;
144}
145
146void QgsNewMemoryLayerDialog::geometryTypeChanged( int )
147{
148 const Qgis::WkbType geomType = static_cast<Qgis::WkbType>( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() );
149
150 const bool isSpatial = geomType != Qgis::WkbType::NoGeometry;
151 mGeometryWithZCheckBox->setEnabled( isSpatial );
152 mGeometryWithMCheckBox->setEnabled( isSpatial );
153 mCrsSelector->setEnabled( isSpatial );
154
155 const bool ok = ( !mNameLineEdit->text().isEmpty() && mGeometryTypeBox->currentIndex() != -1 );
156 mOkButton->setEnabled( ok );
157}
158
159void QgsNewMemoryLayerDialog::mTypeBox_currentIndexChanged( int )
160{
161 const QString fieldType = mTypeBox->currentData().toString();
162 if ( fieldType == QLatin1String( "string" ) )
163 {
164 if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 255 )
165 mWidth->setText( QStringLiteral( "255" ) );
166 mPrecision->clear();
167 mPrecision->setEnabled( false );
168 mWidth->setValidator( new QIntValidator( 1, 255, this ) );
169 mWidth->setEnabled( true );
170 }
171 else if ( fieldType == QLatin1String( "integer" ) )
172 {
173 if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 10 )
174 mWidth->setText( QStringLiteral( "10" ) );
175 mPrecision->clear();
176 mPrecision->setEnabled( false );
177 mWidth->setValidator( new QIntValidator( 1, 10, this ) );
178 mWidth->setEnabled( true );
179 }
180 else if ( fieldType == QLatin1String( "double" ) )
181 {
182 if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 30 )
183 mWidth->setText( QStringLiteral( "30" ) );
184 if ( mPrecision->text().toInt() < 1 || mPrecision->text().toInt() > 30 )
185 mPrecision->setText( QStringLiteral( "6" ) );
186 mPrecision->setEnabled( true );
187 mWidth->setValidator( new QIntValidator( 1, 20, this ) );
188 mWidth->setEnabled( true );
189 }
190 else if ( fieldType == QLatin1String( "bool" ) )
191 {
192 mWidth->clear();
193 mWidth->setEnabled( false );
194 mPrecision->clear();
195 mPrecision->setEnabled( false );
196 }
197 else if ( fieldType == QLatin1String( "date" ) )
198 {
199 mWidth->clear();
200 mWidth->setEnabled( false );
201 mPrecision->clear();
202 mPrecision->setEnabled( false );
203 }
204 else if ( fieldType == QLatin1String( "time" ) )
205 {
206 mWidth->clear();
207 mWidth->setEnabled( false );
208 mPrecision->clear();
209 mPrecision->setEnabled( false );
210 }
211 else if ( fieldType == QLatin1String( "datetime" ) )
212 {
213 mWidth->clear();
214 mWidth->setEnabled( false );
215 mPrecision->clear();
216 mPrecision->setEnabled( false );
217 }
218 else if ( fieldType == QStringLiteral( "binary" )
219 || fieldType == QStringLiteral( "stringlist" )
220 || fieldType == QStringLiteral( "integerlist" )
221 || fieldType == QStringLiteral( "doublelist" )
222 || fieldType == QStringLiteral( "integer64list" )
223 || fieldType == QStringLiteral( "map" )
224 || fieldType == QLatin1String( "geometry" ) )
225 {
226 mWidth->clear();
227 mWidth->setEnabled( false );
228 mPrecision->clear();
229 mPrecision->setEnabled( false );
230 }
231 else
232 {
233 QgsDebugError( QStringLiteral( "unexpected index" ) );
234 }
235}
236
238{
239 mCrsSelector->setCrs( crs );
240}
241
243{
244 return mCrsSelector->crs();
245}
246
248{
249 return mNameLineEdit->text();
250}
251
252void QgsNewMemoryLayerDialog::fieldNameChanged( const QString &name )
253{
254 mAddAttributeButton->setDisabled( name.isEmpty() || !mAttributeView->findItems( name, Qt::MatchExactly ).isEmpty() );
255}
256
257void QgsNewMemoryLayerDialog::selectionChanged()
258{
259 mRemoveAttributeButton->setDisabled( mAttributeView->selectedItems().isEmpty() );
260 mButtonUp->setDisabled( mAttributeView->selectedItems().isEmpty() );
261 mButtonDown->setDisabled( mAttributeView->selectedItems().isEmpty() );
262}
263
265{
267
268 QTreeWidgetItemIterator it( mAttributeView );
269 while ( *it )
270 {
271 const QString name( ( *it )->text( 0 ) );
272 const QString typeName( ( *it )->text( 1 ) );
273 const int width = ( *it )->text( 2 ).toInt();
274 const int precision = ( *it )->text( 3 ).toInt();
275 QMetaType::Type fieldType = QMetaType::Type::UnknownType;
276 QMetaType::Type fieldSubType = QMetaType::Type::UnknownType;
277 if ( typeName == QLatin1String( "string" ) )
278 fieldType = QMetaType::Type::QString;
279 else if ( typeName == QLatin1String( "integer" ) )
280 fieldType = QMetaType::Type::Int;
281 else if ( typeName == QLatin1String( "double" ) )
282 fieldType = QMetaType::Type::Double;
283 else if ( typeName == QLatin1String( "bool" ) )
284 fieldType = QMetaType::Type::Bool;
285 else if ( typeName == QLatin1String( "date" ) )
286 fieldType = QMetaType::Type::QDate;
287 else if ( typeName == QLatin1String( "time" ) )
288 fieldType = QMetaType::Type::QTime;
289 else if ( typeName == QLatin1String( "datetime" ) )
290 fieldType = QMetaType::Type::QDateTime;
291 else if ( typeName == QLatin1String( "binary" ) )
292 fieldType = QMetaType::Type::QByteArray;
293 else if ( typeName == QLatin1String( "stringlist" ) )
294 {
295 fieldType = QMetaType::Type::QStringList;
296 fieldSubType = QMetaType::Type::QString;
297 }
298 else if ( typeName == QLatin1String( "integerlist" ) )
299 {
300 fieldType = QMetaType::Type::QVariantList;
301 fieldSubType = QMetaType::Type::Int;
302 }
303 else if ( typeName == QLatin1String( "doublelist" ) )
304 {
305 fieldType = QMetaType::Type::QVariantList;
306 fieldSubType = QMetaType::Type::Double;
307 }
308 else if ( typeName == QLatin1String( "integer64list" ) )
309 {
310 fieldType = QMetaType::Type::QVariantList;
311 fieldSubType = QMetaType::Type::LongLong;
312 }
313 else if ( typeName == QLatin1String( "map" ) )
314 fieldType = QMetaType::Type::QVariantMap;
315 else if ( typeName == QLatin1String( "geometry" ) )
316 fieldType = QMetaType::Type::User;
317
318 const QgsField field = QgsField( name, fieldType, typeName, width, precision, QString(), fieldSubType );
319 fields.append( field );
320 ++it;
321 }
322
323 return fields;
324}
325
327{
328 if ( !mFieldNameEdit->text().trimmed().isEmpty() )
329 {
330 const QString currentFieldName = mFieldNameEdit->text();
331 if ( fields().lookupField( currentFieldName ) == -1 )
332 {
333 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 )
334 {
335 return;
336 }
337 }
338 }
339
340 QDialog::accept();
341}
342
343void QgsNewMemoryLayerDialog::mAddAttributeButton_clicked()
344{
345 if ( !mFieldNameEdit->text().isEmpty() )
346 {
347 const QString fieldName = mFieldNameEdit->text();
348 const QString fieldType = mTypeBox->currentData( Qt::UserRole ).toString();
349 const QString width = mWidth->text();
350 const QString precision = mPrecision->text();
351 mAttributeView->addTopLevelItem( new QTreeWidgetItem( QStringList() << fieldName << fieldType << width << precision ) );
352
353 mFieldNameEdit->clear();
354
355 if ( !mFieldNameEdit->hasFocus() )
356 {
357 mFieldNameEdit->setFocus();
358 }
359 }
360}
361
362void QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked()
363{
364 delete mAttributeView->currentItem();
365}
366
367void QgsNewMemoryLayerDialog::showHelp()
368{
369 QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#creating-a-new-temporary-scratch-layer" ) );
370}
371
372void QgsNewMemoryLayerDialog::moveFieldsUp()
373{
374 int currentRow = mAttributeView->currentIndex().row();
375 if ( currentRow == 0 )
376 return;
377
378 mAttributeView->insertTopLevelItem( currentRow - 1, mAttributeView->takeTopLevelItem( currentRow ) );
379 mAttributeView->setCurrentIndex( mAttributeView->model()->index( currentRow - 1, 0 ) );
380}
381
382void QgsNewMemoryLayerDialog::moveFieldsDown()
383{
384 int currentRow = mAttributeView->currentIndex().row();
385 if ( currentRow == mAttributeView->topLevelItemCount() - 1 )
386 return;
387
388 mAttributeView->insertTopLevelItem( currentRow + 1, mAttributeView->takeTopLevelItem( currentRow ) );
389 mAttributeView->setCurrentIndex( mAttributeView->model()->index( currentRow + 1, 0 ) );
390}
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:210
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