QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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"
21 #include "qgsdataitem.h"
23 #include "qgsproviderregistry.h"
24 #include "qgsvectordataprovider.h"
25 #include "qgsvectorlayer.h"
26 #include "qgsfield.h"
27 #include "qgsfields.h"
28 #include "qgssettings.h"
29 #include "qgsmemoryproviderutils.h"
30 #include "qgsgui.h"
31 
32 #include <QPushButton>
33 #include <QComboBox>
34 #include <QUuid>
35 #include <QFileDialog>
36 
38 {
39  QgsNewMemoryLayerDialog dialog( parent );
40  dialog.setCrs( defaultCrs );
41  if ( dialog.exec() == QDialog::Rejected )
42  {
43  return nullptr;
44  }
45 
46  QgsWkbTypes::Type geometrytype = dialog.selectedType();
47  QgsFields fields = dialog.fields();
48  QString name = dialog.layerName().isEmpty() ? tr( "New scratch layer" ) : dialog.layerName();
49  QgsVectorLayer *newLayer = QgsMemoryProviderUtils::createMemoryLayer( name, fields, geometrytype, dialog.crs() );
50  return newLayer;
51 }
52 
53 QgsNewMemoryLayerDialog::QgsNewMemoryLayerDialog( QWidget *parent, Qt::WindowFlags fl )
54  : QDialog( parent, fl )
55 {
56  setupUi( this );
58 
59  mNameLineEdit->setText( tr( "New scratch layer" ) );
60 
61  const QgsWkbTypes::Type geomTypes[] =
62  {
74  };
75 
76  for ( const auto type : geomTypes )
77  mGeometryTypeBox->addItem( QgsLayerItem::iconForWkbType( type ), QgsWkbTypes::translatedDisplayString( type ), type );
78  mGeometryTypeBox->setCurrentIndex( -1 );
79 
80  mGeometryWithZCheckBox->setEnabled( false );
81  mGeometryWithMCheckBox->setEnabled( false );
82  mCrsSelector->setEnabled( false );
83 
84  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldText.svg" ) ), tr( "Text" ), "string" );
85  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldInteger.svg" ) ), tr( "Whole Number" ), "integer" );
86  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldFloat.svg" ) ), tr( "Decimal Number" ), "double" );
87  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldBool.svg" ) ), tr( "Boolean" ), "bool" );
88  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldDate.svg" ) ), tr( "Date" ), "date" );
89  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldTime.svg" ) ), tr( "Time" ), "time" );
90  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldDateTime.svg" ) ), tr( "Date and Time" ), "datetime" );
91  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldBinary.svg" ) ), tr( "Binary (BLOB)" ), "binary" );
92  mTypeBox_currentIndexChanged( 1 );
93 
94  mWidth->setValidator( new QIntValidator( 1, 255, this ) );
95  mPrecision->setValidator( new QIntValidator( 0, 30, this ) );
96 
97  mAddAttributeButton->setEnabled( false );
98  mRemoveAttributeButton->setEnabled( false );
99 
100  mOkButton = mButtonBox->button( QDialogButtonBox::Ok );
101  mOkButton->setEnabled( false );
102 
103  connect( mGeometryTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewMemoryLayerDialog::geometryTypeChanged );
104  connect( mFieldNameEdit, &QLineEdit::textChanged, this, &QgsNewMemoryLayerDialog::fieldNameChanged );
105  connect( mTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewMemoryLayerDialog::mTypeBox_currentIndexChanged );
106  connect( mAttributeView, &QTreeWidget::itemSelectionChanged, this, &QgsNewMemoryLayerDialog::selectionChanged );
107  connect( mAddAttributeButton, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::mAddAttributeButton_clicked );
108  connect( mRemoveAttributeButton, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked );
109  connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsNewMemoryLayerDialog::showHelp );
110 }
111 
113 {
115  geomType = static_cast<QgsWkbTypes::Type>
116  ( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() );
117 
118  if ( geomType != QgsWkbTypes::Unknown && geomType != QgsWkbTypes::NoGeometry )
119  {
120  if ( mGeometryWithZCheckBox->isChecked() )
121  geomType = QgsWkbTypes::addZ( geomType );
122  if ( mGeometryWithMCheckBox->isChecked() )
123  geomType = QgsWkbTypes::addM( geomType );
124  }
125 
126  return geomType;
127 }
128 
129 void QgsNewMemoryLayerDialog::geometryTypeChanged( int )
130 {
131  QgsWkbTypes::Type geomType = static_cast<QgsWkbTypes::Type>
132  ( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() );
133 
134  bool isSpatial = geomType != QgsWkbTypes::NoGeometry;
135  mGeometryWithZCheckBox->setEnabled( isSpatial );
136  mGeometryWithMCheckBox->setEnabled( isSpatial );
137  mCrsSelector->setEnabled( isSpatial );
138 
139  bool ok = ( !mNameLineEdit->text().isEmpty() && mGeometryTypeBox->currentIndex() != -1 );
140  mOkButton->setEnabled( ok );
141 }
142 
143 void QgsNewMemoryLayerDialog::mTypeBox_currentIndexChanged( int index )
144 {
145  switch ( index )
146  {
147  case 0: // Text data
148  if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 255 )
149  mWidth->setText( QStringLiteral( "255" ) );
150  mPrecision->clear();
151  mPrecision->setEnabled( false );
152  mWidth->setValidator( new QIntValidator( 1, 255, this ) );
153  break;
154  case 1: // Whole number
155  if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 10 )
156  mWidth->setText( QStringLiteral( "10" ) );
157  mPrecision->clear();
158  mPrecision->setEnabled( false );
159  mWidth->setValidator( new QIntValidator( 1, 10, this ) );
160  break;
161  case 2: // Decimal number
162  if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 30 )
163  mWidth->setText( QStringLiteral( "30" ) );
164  if ( mPrecision->text().toInt() < 1 || mPrecision->text().toInt() > 30 )
165  mPrecision->setText( QStringLiteral( "6" ) );
166  mPrecision->setEnabled( true );
167  mWidth->setValidator( new QIntValidator( 1, 20, this ) );
168  break;
169  case 3: // Boolean
170  mWidth->clear();
171  mWidth->setEnabled( false );
172  mPrecision->clear();
173  mPrecision->setEnabled( false );
174  break;
175  case 4: // Date
176  mWidth->clear();
177  mWidth->setEnabled( false );
178  mPrecision->clear();
179  mPrecision->setEnabled( false );
180  break;
181  case 5: // Time
182  mWidth->clear();
183  mWidth->setEnabled( false );
184  mPrecision->clear();
185  mPrecision->setEnabled( false );
186  break;
187  case 6: // Datetime
188  mWidth->clear();
189  mWidth->setEnabled( false );
190  mPrecision->clear();
191  mPrecision->setEnabled( false );
192  break;
193  case 7: // Binary
194  mWidth->clear();
195  mWidth->setEnabled( false );
196  mPrecision->clear();
197  mPrecision->setEnabled( false );
198  break;
199 
200  default:
201  QgsDebugMsg( QStringLiteral( "unexpected index" ) );
202  break;
203  }
204 }
205 
207 {
208  mCrsSelector->setCrs( crs );
209 }
210 
212 {
213  return mCrsSelector->crs();
214 }
215 
217 {
218  return mNameLineEdit->text();
219 }
220 
221 void QgsNewMemoryLayerDialog::fieldNameChanged( const QString &name )
222 {
223  mAddAttributeButton->setDisabled( name.isEmpty() || ! mAttributeView->findItems( name, Qt::MatchExactly ).isEmpty() );
224 }
225 
226 void QgsNewMemoryLayerDialog::selectionChanged()
227 {
228  mRemoveAttributeButton->setDisabled( mAttributeView->selectedItems().isEmpty() );
229 }
230 
232 {
234 
235  QTreeWidgetItemIterator it( mAttributeView );
236  while ( *it )
237  {
238  QString name( ( *it )->text( 0 ) );
239  QString typeName( ( *it )->text( 1 ) );
240  int width = ( *it )->text( 2 ).toInt();
241  int precision = ( *it )->text( 3 ).toInt();
242  QVariant::Type fieldType = QVariant::Invalid;
243  if ( typeName == QLatin1String( "string" ) )
244  fieldType = QVariant::String;
245  else if ( typeName == QLatin1String( "integer" ) )
246  fieldType = QVariant::Int;
247  else if ( typeName == QLatin1String( "double" ) )
248  fieldType = QVariant::Double;
249  else if ( typeName == QLatin1String( "bool" ) )
250  fieldType = QVariant::Bool;
251  else if ( typeName == QLatin1String( "date" ) )
252  fieldType = QVariant::Date;
253  else if ( typeName == QLatin1String( "time" ) )
254  fieldType = QVariant::Time;
255  else if ( typeName == QLatin1String( "datetime" ) )
256  fieldType = QVariant::DateTime;
257 
258  QgsField field = QgsField( name, fieldType, typeName, width, precision );
259  fields.append( field );
260  ++it;
261  }
262 
263  return fields;
264 }
265 
266 void QgsNewMemoryLayerDialog::mAddAttributeButton_clicked()
267 {
268  if ( !mFieldNameEdit->text().isEmpty() )
269  {
270  QString fieldName = mFieldNameEdit->text();
271  QString fieldType = mTypeBox->currentData( Qt::UserRole ).toString();
272  QString width = mWidth->text();
273  QString precision = mPrecision->text();
274  mAttributeView->addTopLevelItem( new QTreeWidgetItem( QStringList() << fieldName << fieldType << width << precision ) );
275 
276  mFieldNameEdit->clear();
277  }
278 }
279 
280 void QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked()
281 {
282  delete mAttributeView->currentItem();
283 }
284 
285 void QgsNewMemoryLayerDialog::showHelp()
286 {
287  QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#creating-a-new-temporary-scratch-layer" ) );
288 }
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
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 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:156
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:36
static QIcon iconForWkbType(QgsWkbTypes::Type type)
Returns the icon for a vector layer whose geometry type is provided.
Definition: qgsdataitem.cpp:57
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.
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.
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:1146
static Type addM(Type type) SIP_HOLDGIL
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1171
const QgsField & field
Definition: qgsfield.h:472
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
const QgsCoordinateReferenceSystem & crs
const QString & typeName
int precision