QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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 
31 #include <QPushButton>
32 #include <QComboBox>
33 #include <QUuid>
34 #include <QFileDialog>
35 
37 {
38  QgsNewMemoryLayerDialog dialog( parent );
39  dialog.setCrs( defaultCrs );
40  if ( dialog.exec() == QDialog::Rejected )
41  {
42  return nullptr;
43  }
44 
45  QgsWkbTypes::Type geometrytype = dialog.selectedType();
46  QgsFields fields = dialog.fields();
47  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 
52 QgsNewMemoryLayerDialog::QgsNewMemoryLayerDialog( QWidget *parent, Qt::WindowFlags fl )
53  : QDialog( parent, fl )
54 {
55  setupUi( this );
57 
58  mNameLineEdit->setText( tr( "New scratch layer" ) );
59 
60  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconTableLayer.svg" ) ), tr( "No Geometry" ), QgsWkbTypes::NoGeometry );
61  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPointLayer.svg" ) ), tr( "Point" ), QgsWkbTypes::Point );
62  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "LineString" ), QgsWkbTypes::LineString );
63  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "CompoundCurve" ), QgsWkbTypes::CompoundCurve );
64  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ), tr( "Polygon" ), QgsWkbTypes::Polygon );
65  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ), tr( "CurvePolygon" ), QgsWkbTypes::CurvePolygon );
66  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPointLayer.svg" ) ), tr( "MultiPoint" ), QgsWkbTypes::MultiPoint );
67  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "MultiLineString" ), QgsWkbTypes::MultiLineString );
68  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "MultiCurve" ), QgsWkbTypes::MultiCurve );
69  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ), tr( "MultiPolygon" ), QgsWkbTypes::MultiPolygon );
70  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ), tr( "MultiSurface" ), QgsWkbTypes::MultiSurface );
71  mGeometryTypeBox->setCurrentIndex( -1 );
72 
73  mGeometryWithZCheckBox->setEnabled( false );
74  mGeometryWithMCheckBox->setEnabled( false );
75  mCrsSelector->setEnabled( false );
76 
77  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldText.svg" ) ), tr( "Text" ), "string" );
78  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldInteger.svg" ) ), tr( "Whole Number" ), "integer" );
79  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldFloat.svg" ) ), tr( "Decimal Number" ), "double" );
80  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldBool.svg" ) ), tr( "Boolean" ), "bool" );
81  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldDate.svg" ) ), tr( "Date" ), "date" );
82  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldTime.svg" ) ), tr( "Time" ), "time" );
83  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldDateTime.svg" ) ), tr( "Date and Time" ), "datetime" );
84  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldBinary.svg" ) ), tr( "Binary (BLOB)" ), "binary" );
85  mTypeBox_currentIndexChanged( 1 );
86 
87  mWidth->setValidator( new QIntValidator( 1, 255, this ) );
88  mPrecision->setValidator( new QIntValidator( 0, 30, this ) );
89 
90  mAddAttributeButton->setEnabled( false );
91  mRemoveAttributeButton->setEnabled( false );
92 
93  mOkButton = mButtonBox->button( QDialogButtonBox::Ok );
94  mOkButton->setEnabled( false );
95 
96  connect( mGeometryTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewMemoryLayerDialog::geometryTypeChanged );
97  connect( mFieldNameEdit, &QLineEdit::textChanged, this, &QgsNewMemoryLayerDialog::fieldNameChanged );
98  connect( mTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewMemoryLayerDialog::mTypeBox_currentIndexChanged );
99  connect( mAttributeView, &QTreeWidget::itemSelectionChanged, this, &QgsNewMemoryLayerDialog::selectionChanged );
100  connect( mAddAttributeButton, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::mAddAttributeButton_clicked );
101  connect( mRemoveAttributeButton, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked );
102  connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsNewMemoryLayerDialog::showHelp );
103 }
104 
106 {
108  geomType = static_cast<QgsWkbTypes::Type>
109  ( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() );
110 
111  if ( geomType != QgsWkbTypes::Unknown && geomType != QgsWkbTypes::NoGeometry )
112  {
113  if ( mGeometryWithZCheckBox->isChecked() )
114  geomType = QgsWkbTypes::addZ( geomType );
115  if ( mGeometryWithMCheckBox->isChecked() )
116  geomType = QgsWkbTypes::addM( geomType );
117  }
118 
119  return geomType;
120 }
121 
122 void QgsNewMemoryLayerDialog::geometryTypeChanged( int )
123 {
124  QgsWkbTypes::Type geomType = static_cast<QgsWkbTypes::Type>
125  ( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() );
126 
127  bool isSpatial = geomType != QgsWkbTypes::NoGeometry;
128  mGeometryWithZCheckBox->setEnabled( isSpatial );
129  mGeometryWithMCheckBox->setEnabled( isSpatial );
130  mCrsSelector->setEnabled( isSpatial );
131 
132  bool ok = ( !mNameLineEdit->text().isEmpty() && mGeometryTypeBox->currentIndex() != -1 );
133  mOkButton->setEnabled( ok );
134 }
135 
136 void QgsNewMemoryLayerDialog::mTypeBox_currentIndexChanged( int index )
137 {
138  switch ( index )
139  {
140  case 0: // Text data
141  if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 255 )
142  mWidth->setText( QStringLiteral( "255" ) );
143  mPrecision->clear();
144  mPrecision->setEnabled( false );
145  mWidth->setValidator( new QIntValidator( 1, 255, this ) );
146  break;
147  case 1: // Whole number
148  if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 10 )
149  mWidth->setText( QStringLiteral( "10" ) );
150  mPrecision->clear();
151  mPrecision->setEnabled( false );
152  mWidth->setValidator( new QIntValidator( 1, 10, this ) );
153  break;
154  case 2: // Decimal number
155  if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 30 )
156  mWidth->setText( QStringLiteral( "30" ) );
157  if ( mPrecision->text().toInt() < 1 || mPrecision->text().toInt() > 30 )
158  mPrecision->setText( QStringLiteral( "6" ) );
159  mPrecision->setEnabled( true );
160  mWidth->setValidator( new QIntValidator( 1, 20, this ) );
161  break;
162  case 3: // Boolean
163  mWidth->clear();
164  mWidth->setEnabled( false );
165  mPrecision->clear();
166  mPrecision->setEnabled( false );
167  break;
168  case 4: // Date
169  mWidth->clear();
170  mWidth->setEnabled( false );
171  mPrecision->clear();
172  mPrecision->setEnabled( false );
173  break;
174  case 5: // Time
175  mWidth->clear();
176  mWidth->setEnabled( false );
177  mPrecision->clear();
178  mPrecision->setEnabled( false );
179  break;
180  case 6: // Datetime
181  mWidth->clear();
182  mWidth->setEnabled( false );
183  mPrecision->clear();
184  mPrecision->setEnabled( false );
185  break;
186  case 7: // Binary
187  mWidth->clear();
188  mWidth->setEnabled( false );
189  mPrecision->clear();
190  mPrecision->setEnabled( false );
191  break;
192 
193  default:
194  QgsDebugMsg( QStringLiteral( "unexpected index" ) );
195  break;
196  }
197 }
198 
200 {
201  mCrsSelector->setCrs( crs );
202 }
203 
205 {
206  return mCrsSelector->crs();
207 }
208 
210 {
211  return mNameLineEdit->text();
212 }
213 
214 void QgsNewMemoryLayerDialog::fieldNameChanged( const QString &name )
215 {
216  mAddAttributeButton->setDisabled( name.isEmpty() || ! mAttributeView->findItems( name, Qt::MatchExactly ).isEmpty() );
217 }
218 
219 void QgsNewMemoryLayerDialog::selectionChanged()
220 {
221  mRemoveAttributeButton->setDisabled( mAttributeView->selectedItems().isEmpty() );
222 }
223 
225 {
227 
228  QTreeWidgetItemIterator it( mAttributeView );
229  while ( *it )
230  {
231  QString name( ( *it )->text( 0 ) );
232  QString typeName( ( *it )->text( 1 ) );
233  int width = ( *it )->text( 2 ).toInt();
234  int precision = ( *it )->text( 3 ).toInt();
235  QVariant::Type fieldType = QVariant::Invalid;
236  if ( typeName == QLatin1String( "string" ) )
237  fieldType = QVariant::String;
238  else if ( typeName == QLatin1String( "integer" ) )
239  fieldType = QVariant::Int;
240  else if ( typeName == QLatin1String( "double" ) )
241  fieldType = QVariant::Double;
242  else if ( typeName == QLatin1String( "bool" ) )
243  fieldType = QVariant::Bool;
244  else if ( typeName == QLatin1String( "date" ) )
245  fieldType = QVariant::Date;
246  else if ( typeName == QLatin1String( "time" ) )
247  fieldType = QVariant::Time;
248  else if ( typeName == QLatin1String( "datetime" ) )
249  fieldType = QVariant::DateTime;
250 
251  QgsField field = QgsField( name, fieldType, typeName, width, precision );
252  fields.append( field );
253  ++it;
254  }
255 
256  return fields;
257 }
258 
259 void QgsNewMemoryLayerDialog::mAddAttributeButton_clicked()
260 {
261  if ( !mFieldNameEdit->text().isEmpty() )
262  {
263  QString fieldName = mFieldNameEdit->text();
264  QString fieldType = mTypeBox->currentData( Qt::UserRole ).toString();
265  QString width = mWidth->text();
266  QString precision = mPrecision->text();
267  mAttributeView->addTopLevelItem( new QTreeWidgetItem( QStringList() << fieldName << fieldType << width << precision ) );
268 
269  mFieldNameEdit->clear();
270  }
271 }
272 
273 void QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked()
274 {
275  delete mAttributeView->currentItem();
276 }
277 
278 void QgsNewMemoryLayerDialog::showHelp()
279 {
280  QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#creating-a-new-temporary-scratch-layer" ) );
281 }
qgsfields.h
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Definition: qgsapplication.cpp:626
QgsWkbTypes::Point
@ Point
Definition: qgswkbtypes.h:72
QgsNewMemoryLayerDialog::crs
QgsCoordinateReferenceSystem crs() const
Returns the selected CRS for the new layer.
Definition: qgsnewmemorylayerdialog.cpp:204
QgsWkbTypes::MultiPolygon
@ MultiPolygon
Definition: qgswkbtypes.h:78
QgsNewMemoryLayerDialog::layerName
QString layerName() const
Returns the layer name.
Definition: qgsnewmemorylayerdialog.cpp:209
qgsgui.h
crs
const QgsCoordinateReferenceSystem & crs
Definition: qgswfsgetfeature.cpp:51
QgsWkbTypes::LineString
@ LineString
Definition: qgswkbtypes.h:73
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:45
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:1139
qgis.h
QgsWkbTypes::Type
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
QgsWkbTypes::MultiCurve
@ MultiCurve
Definition: qgswkbtypes.h:83
field
const QgsField & field
Definition: qgsfield.h:456
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:34
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:139
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:1164
precision
int precision
Definition: qgswfsgetfeature.cpp:49
QgsWkbTypes::MultiLineString
@ MultiLineString
Definition: qgswkbtypes.h:77
QgsMemoryProviderUtils::createMemoryLayer
static QgsVectorLayer * createMemoryLayer(const QString &name, const QgsFields &fields, QgsWkbTypes::Type geometryType=QgsWkbTypes::NoGeometry, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem())
Creates a new memory layer using the specified parameters.
Definition: qgsmemoryproviderutils.cpp:59
QgsWkbTypes::Unknown
@ Unknown
Definition: qgswkbtypes.h:71
qgsproviderregistry.h
QgsWkbTypes::CurvePolygon
@ CurvePolygon
Definition: qgswkbtypes.h:82
qgsvectordataprovider.h
typeName
const QString & typeName
Definition: qgswfsgetfeature.cpp:55
QgsNewMemoryLayerDialog::setCrs
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the crs value for the new layer in the dialog.
Definition: qgsnewmemorylayerdialog.cpp:199
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:206
qgsvectorlayer.h
QgsNewMemoryLayerDialog::runAndCreateLayer
static QgsVectorLayer * runAndCreateLayer(QWidget *parent=nullptr, const QgsCoordinateReferenceSystem &defaultCrs=QgsCoordinateReferenceSystem())
Runs the dialog and creates a new memory layer.
Definition: qgsnewmemorylayerdialog.cpp:36
QgsWkbTypes::NoGeometry
@ NoGeometry
Definition: qgswkbtypes.h:85
QgsWkbTypes::MultiSurface
@ MultiSurface
Definition: qgswkbtypes.h:84
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:387
qgsfield.h
QgsWkbTypes::Polygon
@ Polygon
Definition: qgswkbtypes.h:74
QgsWkbTypes::MultiPoint
@ MultiPoint
Definition: qgswkbtypes.h:76
qgssettings.h
QgsNewMemoryLayerDialog::fields
QgsFields fields() const
Returns attributes for the new layer.
Definition: qgsnewmemorylayerdialog.cpp:224
qgsmemoryproviderutils.h
QgsNewMemoryLayerDialog::selectedType
QgsWkbTypes::Type selectedType() const
Returns the selected geometry type.
Definition: qgsnewmemorylayerdialog.cpp:105
qgscoordinatereferencesystem.h
qgsnewmemorylayerdialog.h
QgsNewMemoryLayerDialog::QgsNewMemoryLayerDialog
QgsNewMemoryLayerDialog(QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags)
New dialog constructor.
Definition: qgsnewmemorylayerdialog.cpp:52
QgsWkbTypes::CompoundCurve
@ CompoundCurve
Definition: qgswkbtypes.h:81
QgsField
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:50