QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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"
23 #include "qgsvectordataprovider.h"
24 #include "qgsvectorlayer.h"
25 #include "qgsfield.h"
26 #include "qgsfields.h"
27 #include "qgssettings.h"
28 #include "qgsmemoryproviderutils.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 
54 QgsNewMemoryLayerDialog::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 
139 void 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 
153 void 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 
236 void QgsNewMemoryLayerDialog::fieldNameChanged( const QString &name )
237 {
238  mAddAttributeButton->setDisabled( name.isEmpty() || ! mAttributeView->findItems( name, Qt::MatchExactly ).isEmpty() );
239 }
240 
241 void 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 );
299  fields.append( field );
300  ++it;
301  }
302 
303  return fields;
304 }
305 
306 void 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 
320 void QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked()
321 {
322  delete mAttributeView->currentItem();
323 }
324 
325 void QgsNewMemoryLayerDialog::showHelp()
326 {
327  QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#creating-a-new-temporary-scratch-layer" ) );
328 }
qgsfields.h
QgsWkbTypes::Point
@ Point
Definition: qgswkbtypes.h:72
QgsNewMemoryLayerDialog::crs
QgsCoordinateReferenceSystem crs() const
Returns the selected CRS for the new layer.
Definition: qgsnewmemorylayerdialog.cpp:226
QgsWkbTypes::MultiPolygon
@ MultiPolygon
Definition: qgswkbtypes.h:78
QgsNewMemoryLayerDialog::layerName
QString layerName() const
Returns the layer name.
Definition: qgsnewmemorylayerdialog.cpp:231
qgsgui.h
crs
const QgsCoordinateReferenceSystem & crs
Definition: qgswfsgetfeature.cpp:105
QgsWkbTypes::LineString
@ LineString
Definition: qgswkbtypes.h:73
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:44
QgsWkbTypes::addZ
static Type addZ(Type type) SIP_HOLDGIL
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1176
qgis.h
QgsMemoryProviderUtils::createMemoryLayer
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.
Definition: qgsmemoryproviderutils.cpp:63
QgsWkbTypes::Type
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:69
QgsWkbTypes::MultiCurve
@ MultiCurve
Definition: qgswkbtypes.h:83
field
const QgsField & field
Definition: qgsfield.h:463
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsFields::append
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
qgsapplication.h
QgsNewMemoryLayerDialog
Definition: qgsnewmemorylayerdialog.h:33
QgsGui::enableAutoGeometryRestore
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:180
QgsWkbTypes::addM
static Type addM(Type type) SIP_HOLDGIL
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1201
precision
int precision
Definition: qgswfsgetfeature.cpp:103
QgsWkbTypes::MultiLineString
@ MultiLineString
Definition: qgswkbtypes.h:77
QgsWkbTypes::Unknown
@ Unknown
Definition: qgswkbtypes.h:71
qgsproviderregistry.h
QgsWkbTypes::CurvePolygon
@ CurvePolygon
Definition: qgswkbtypes.h:82
qgsvectordataprovider.h
qgsvariantutils.h
typeName
const QString & typeName
Definition: qgswfsgetfeature.cpp:109
QgsNewMemoryLayerDialog::setCrs
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the crs value for the new layer in the dialog.
Definition: qgsnewmemorylayerdialog.cpp:221
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:211
QgsFields::iconForFieldType
static QIcon iconForFieldType(QVariant::Type type, QVariant::Type subType=QVariant::Type::Invalid)
Returns an icon corresponding to a field type.
Definition: qgsfields.cpp:294
qgsvectorlayer.h
QgsVariantUtils::typeToDisplayString
static QString typeToDisplayString(QVariant::Type type, QVariant::Type subType=QVariant::Type::Invalid)
Returns a user-friendly translated string representing a QVariant type.
Definition: qgsvariantutils.cpp:19
QgsNewMemoryLayerDialog::runAndCreateLayer
static QgsVectorLayer * runAndCreateLayer(QWidget *parent=nullptr, const QgsCoordinateReferenceSystem &defaultCrs=QgsCoordinateReferenceSystem())
Runs the dialog and creates a new memory layer.
Definition: qgsnewmemorylayerdialog.cpp:38
QgsWkbTypes::NoGeometry
@ NoGeometry
Definition: qgswkbtypes.h:85
QgsWkbTypes::MultiSurface
@ MultiSurface
Definition: qgswkbtypes.h:84
QgsWkbTypes::translatedDisplayString
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...
Definition: qgswkbtypes.cpp:155
QgsHelp::openHelp
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:36
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:391
QgsIconUtils::iconForWkbType
static QIcon iconForWkbType(QgsWkbTypes::Type type)
Returns the icon for a vector layer whose geometry type is provided.
Definition: qgsiconutils.cpp:25
qgsfield.h
QgsWkbTypes::Polygon
@ Polygon
Definition: qgswkbtypes.h:74
QgsWkbTypes::MultiPoint
@ MultiPoint
Definition: qgswkbtypes.h:76
qgssettings.h
qgsiconutils.h
QgsNewMemoryLayerDialog::fields
QgsFields fields() const
Returns attributes for the new layer.
Definition: qgsnewmemorylayerdialog.cpp:246
qgsmemoryproviderutils.h
QgsNewMemoryLayerDialog::selectedType
QgsWkbTypes::Type selectedType() const
Returns the selected geometry type.
Definition: qgsnewmemorylayerdialog.cpp:122
qgscoordinatereferencesystem.h
qgsnewmemorylayerdialog.h
QgsNewMemoryLayerDialog::QgsNewMemoryLayerDialog
QgsNewMemoryLayerDialog(QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags)
New dialog constructor.
Definition: qgsnewmemorylayerdialog.cpp:54
QgsWkbTypes::CompoundCurve
@ CompoundCurve
Definition: qgswkbtypes.h:81
QgsField
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:50