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