QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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 "qgsapplication.h"
20#include "qgis.h"
22#include "qgsproviderregistry.h"
24#include "qgsvectorlayer.h"
25#include "qgsfield.h"
26#include "qgsfields.h"
27#include "qgssettings.h"
29#include "qgsgui.h"
30#include "qgsiconutils.h"
31#include "qgsvariantutils.h"
32
33#include <QPushButton>
34#include <QComboBox>
35#include <QUuid>
36#include <QFileDialog>
37
39{
40 QgsNewMemoryLayerDialog dialog( parent );
41 dialog.setCrs( defaultCrs );
42 if ( dialog.exec() == QDialog::Rejected )
43 {
44 return nullptr;
45 }
46
47 const QgsWkbTypes::Type geometrytype = dialog.selectedType();
48 const QgsFields fields = dialog.fields();
49 const QString name = dialog.layerName().isEmpty() ? tr( "New scratch layer" ) : dialog.layerName();
50 QgsVectorLayer *newLayer = QgsMemoryProviderUtils::createMemoryLayer( name, fields, geometrytype, dialog.crs() );
51 return newLayer;
52}
53
54QgsNewMemoryLayerDialog::QgsNewMemoryLayerDialog( QWidget *parent, Qt::WindowFlags fl )
55 : QDialog( parent, fl )
56{
57 setupUi( this );
59
60 mNameLineEdit->setText( tr( "New scratch layer" ) );
61
62 const QgsWkbTypes::Type geomTypes[] =
63 {
75 };
76
77 for ( const auto type : geomTypes )
78 mGeometryTypeBox->addItem( QgsIconUtils::iconForWkbType( type ), QgsWkbTypes::translatedDisplayString( type ), 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( QVariant::String ), QgsVariantUtils::typeToDisplayString( QVariant::String ), "string" );
87 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::Int ), QgsVariantUtils::typeToDisplayString( QVariant::Int ), "integer" );
88 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::Double ), QgsVariantUtils::typeToDisplayString( QVariant::Double ), "double" );
89 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::Bool ), QgsVariantUtils::typeToDisplayString( QVariant::Bool ), "bool" );
90 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::Date ), QgsVariantUtils::typeToDisplayString( QVariant::Date ), "date" );
91 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::Time ), QgsVariantUtils::typeToDisplayString( QVariant::Time ), "time" );
92 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::DateTime ), QgsVariantUtils::typeToDisplayString( QVariant::DateTime ), "datetime" );
93 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::ByteArray ), QgsVariantUtils::typeToDisplayString( QVariant::ByteArray ), "binary" );
94 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::StringList ), QgsVariantUtils::typeToDisplayString( QVariant::StringList ), "stringlist" );
95 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::List, QVariant::Int ), QgsVariantUtils::typeToDisplayString( QVariant::List, QVariant::Int ), "integerlist" );
96 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::List, QVariant::Double ), QgsVariantUtils::typeToDisplayString( QVariant::List, QVariant::Double ), "doublelist" );
97 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::List, QVariant::LongLong ), QgsVariantUtils::typeToDisplayString( QVariant::List, QVariant::LongLong ), "integer64list" );
98 mTypeBox->addItem( QgsFields::iconForFieldType( QVariant::Map ), QgsVariantUtils::typeToDisplayString( QVariant::Map ), "map" );
99 mTypeBox_currentIndexChanged( 1 );
100
101 mWidth->setValidator( new QIntValidator( 1, 255, this ) );
102 mPrecision->setValidator( new QIntValidator( 0, 30, this ) );
103
104 mAddAttributeButton->setEnabled( false );
105 mRemoveAttributeButton->setEnabled( false );
106
107 mOkButton = mButtonBox->button( QDialogButtonBox::Ok );
108 mOkButton->setEnabled( false );
109
110 connect( mGeometryTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewMemoryLayerDialog::geometryTypeChanged );
111 connect( mFieldNameEdit, &QLineEdit::textChanged, this, &QgsNewMemoryLayerDialog::fieldNameChanged );
112 connect( mTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewMemoryLayerDialog::mTypeBox_currentIndexChanged );
113 connect( mAttributeView, &QTreeWidget::itemSelectionChanged, this, &QgsNewMemoryLayerDialog::selectionChanged );
114 connect( mAddAttributeButton, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::mAddAttributeButton_clicked );
115 connect( mRemoveAttributeButton, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked );
116 connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsNewMemoryLayerDialog::showHelp );
117
118 mNameLineEdit->selectAll();
119 mNameLineEdit->setFocus();
120}
121
123{
125 geomType = static_cast<QgsWkbTypes::Type>
126 ( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() );
127
128 if ( geomType != QgsWkbTypes::Unknown && geomType != QgsWkbTypes::NoGeometry )
129 {
130 if ( mGeometryWithZCheckBox->isChecked() )
131 geomType = QgsWkbTypes::addZ( geomType );
132 if ( mGeometryWithMCheckBox->isChecked() )
133 geomType = QgsWkbTypes::addM( geomType );
134 }
135
136 return geomType;
137}
138
139void QgsNewMemoryLayerDialog::geometryTypeChanged( int )
140{
141 const QgsWkbTypes::Type geomType = static_cast<QgsWkbTypes::Type>
142 ( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() );
143
144 const bool isSpatial = geomType != QgsWkbTypes::NoGeometry;
145 mGeometryWithZCheckBox->setEnabled( isSpatial );
146 mGeometryWithMCheckBox->setEnabled( isSpatial );
147 mCrsSelector->setEnabled( isSpatial );
148
149 const bool ok = ( !mNameLineEdit->text().isEmpty() && mGeometryTypeBox->currentIndex() != -1 );
150 mOkButton->setEnabled( ok );
151}
152
153void QgsNewMemoryLayerDialog::mTypeBox_currentIndexChanged( int index )
154{
155 switch ( index )
156 {
157 case 0: // Text data
158 if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 255 )
159 mWidth->setText( QStringLiteral( "255" ) );
160 mPrecision->clear();
161 mPrecision->setEnabled( false );
162 mWidth->setValidator( new QIntValidator( 1, 255, this ) );
163 break;
164 case 1: // Whole number
165 if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 10 )
166 mWidth->setText( QStringLiteral( "10" ) );
167 mPrecision->clear();
168 mPrecision->setEnabled( false );
169 mWidth->setValidator( new QIntValidator( 1, 10, this ) );
170 break;
171 case 2: // Decimal number
172 if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 30 )
173 mWidth->setText( QStringLiteral( "30" ) );
174 if ( mPrecision->text().toInt() < 1 || mPrecision->text().toInt() > 30 )
175 mPrecision->setText( QStringLiteral( "6" ) );
176 mPrecision->setEnabled( true );
177 mWidth->setValidator( new QIntValidator( 1, 20, this ) );
178 break;
179 case 3: // Boolean
180 mWidth->clear();
181 mWidth->setEnabled( false );
182 mPrecision->clear();
183 mPrecision->setEnabled( false );
184 break;
185 case 4: // Date
186 mWidth->clear();
187 mWidth->setEnabled( false );
188 mPrecision->clear();
189 mPrecision->setEnabled( false );
190 break;
191 case 5: // Time
192 mWidth->clear();
193 mWidth->setEnabled( false );
194 mPrecision->clear();
195 mPrecision->setEnabled( false );
196 break;
197 case 6: // Datetime
198 mWidth->clear();
199 mWidth->setEnabled( false );
200 mPrecision->clear();
201 mPrecision->setEnabled( false );
202 break;
203 case 7: // Binary
204 case 8: // Stringlist
205 case 9: // Integerlist
206 case 10: // Doublelist
207 case 11: // Integer64list
208 case 12: // Map
209 mWidth->clear();
210 mWidth->setEnabled( false );
211 mPrecision->clear();
212 mPrecision->setEnabled( false );
213 break;
214
215 default:
216 QgsDebugMsg( QStringLiteral( "unexpected index" ) );
217 break;
218 }
219}
220
222{
223 mCrsSelector->setCrs( crs );
224}
225
227{
228 return mCrsSelector->crs();
229}
230
232{
233 return mNameLineEdit->text();
234}
235
236void QgsNewMemoryLayerDialog::fieldNameChanged( const QString &name )
237{
238 mAddAttributeButton->setDisabled( name.isEmpty() || ! mAttributeView->findItems( name, Qt::MatchExactly ).isEmpty() );
239}
240
241void QgsNewMemoryLayerDialog::selectionChanged()
242{
243 mRemoveAttributeButton->setDisabled( mAttributeView->selectedItems().isEmpty() );
244}
245
247{
249
250 QTreeWidgetItemIterator it( mAttributeView );
251 while ( *it )
252 {
253 const QString name( ( *it )->text( 0 ) );
254 const QString typeName( ( *it )->text( 1 ) );
255 const int width = ( *it )->text( 2 ).toInt();
256 const int precision = ( *it )->text( 3 ).toInt();
257 QVariant::Type fieldType = QVariant::Invalid;
258 QVariant::Type fieldSubType = QVariant::Invalid;
259 if ( typeName == QLatin1String( "string" ) )
260 fieldType = QVariant::String;
261 else if ( typeName == QLatin1String( "integer" ) )
262 fieldType = QVariant::Int;
263 else if ( typeName == QLatin1String( "double" ) )
264 fieldType = QVariant::Double;
265 else if ( typeName == QLatin1String( "bool" ) )
266 fieldType = QVariant::Bool;
267 else if ( typeName == QLatin1String( "date" ) )
268 fieldType = QVariant::Date;
269 else if ( typeName == QLatin1String( "time" ) )
270 fieldType = QVariant::Time;
271 else if ( typeName == QLatin1String( "datetime" ) )
272 fieldType = QVariant::DateTime;
273 else if ( typeName == QLatin1String( "binary" ) )
274 fieldType = QVariant::ByteArray;
275 else if ( typeName == QLatin1String( "stringlist" ) )
276 {
277 fieldType = QVariant::StringList;
278 fieldSubType = QVariant::String;
279 }
280 else if ( typeName == QLatin1String( "integerlist" ) )
281 {
282 fieldType = QVariant::List;
283 fieldSubType = QVariant::Int;
284 }
285 else if ( typeName == QLatin1String( "doublelist" ) )
286 {
287 fieldType = QVariant::List;
288 fieldSubType = QVariant::Double;
289 }
290 else if ( typeName == QLatin1String( "integer64list" ) )
291 {
292 fieldType = QVariant::List;
293 fieldSubType = QVariant::LongLong;
294 }
295 else if ( typeName == QLatin1String( "map" ) )
296 fieldType = QVariant::Map;
297
298 const QgsField field = QgsField( name, fieldType, typeName, width, precision, QString(), fieldSubType );
300 ++it;
301 }
302
303 return fields;
304}
305
306void QgsNewMemoryLayerDialog::mAddAttributeButton_clicked()
307{
308 if ( !mFieldNameEdit->text().isEmpty() )
309 {
310 const QString fieldName = mFieldNameEdit->text();
311 const QString fieldType = mTypeBox->currentData( Qt::UserRole ).toString();
312 const QString width = mWidth->text();
313 const QString precision = mPrecision->text();
314 mAttributeView->addTopLevelItem( new QTreeWidgetItem( QStringList() << fieldName << fieldType << width << precision ) );
315
316 mFieldNameEdit->clear();
317 }
318}
319
320void QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked()
321{
322 delete mAttributeView->currentItem();
323}
324
325void QgsNewMemoryLayerDialog::showHelp()
326{
327 QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#creating-a-new-temporary-scratch-layer" ) );
328}
This class represents a coordinate reference system (CRS).
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
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)
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:178
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:38
static QIcon iconForWkbType(QgsWkbTypes::Type type)
Returns the icon for a vector layer whose geometry type is provided.
static QgsVectorLayer * createMemoryLayer(const QString &name, const QgsFields &fields, QgsWkbTypes::Type geometryType=QgsWkbTypes::NoGeometry, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem()) SIP_FACTORY
Creates a new memory layer using the specified parameters.
QgsWkbTypes::Type selectedType() const
Returns the selected geometry type.
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.
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(Type type) SIP_HOLDGIL
Returns a translated display string type for a WKB type, e.g., the geometry name used in WKT geometry...
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
static Type addZ(Type type) SIP_HOLDGIL
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1176
static Type addM(Type type) SIP_HOLDGIL
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1201
const QgsField & field
Definition: qgsfield.h:463
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
const QgsCoordinateReferenceSystem & crs
const QString & typeName
int precision