QGIS API Documentation  3.22.4-Białowieża (ce8e65e95e)
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 
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  const QgsWkbTypes::Type geometrytype = dialog.selectedType();
47  const QgsFields fields = dialog.fields();
48  const 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( QgsIconUtils::iconForWkbType( type ), QgsWkbTypes::translatedDisplayString( type ), type );
78  mGeometryTypeBox->setCurrentIndex( -1 );
79 
80  mGeometryWithZCheckBox->setEnabled( false );
81  mGeometryWithMCheckBox->setEnabled( false );
82  mCrsSelector->setEnabled( false );
83  mCrsSelector->setShowAccuracyWarnings( true );
84 
85  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldText.svg" ) ), tr( "Text" ), "string" );
86  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldInteger.svg" ) ), tr( "Whole Number" ), "integer" );
87  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldFloat.svg" ) ), tr( "Decimal Number" ), "double" );
88  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldBool.svg" ) ), tr( "Boolean" ), "bool" );
89  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldDate.svg" ) ), tr( "Date" ), "date" );
90  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldTime.svg" ) ), tr( "Time" ), "time" );
91  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldDateTime.svg" ) ), tr( "Date and Time" ), "datetime" );
92  mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldBinary.svg" ) ), tr( "Binary (BLOB)" ), "binary" );
93  mTypeBox_currentIndexChanged( 1 );
94 
95  mWidth->setValidator( new QIntValidator( 1, 255, this ) );
96  mPrecision->setValidator( new QIntValidator( 0, 30, this ) );
97 
98  mAddAttributeButton->setEnabled( false );
99  mRemoveAttributeButton->setEnabled( false );
100 
101  mOkButton = mButtonBox->button( QDialogButtonBox::Ok );
102  mOkButton->setEnabled( false );
103 
104  connect( mGeometryTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewMemoryLayerDialog::geometryTypeChanged );
105  connect( mFieldNameEdit, &QLineEdit::textChanged, this, &QgsNewMemoryLayerDialog::fieldNameChanged );
106  connect( mTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewMemoryLayerDialog::mTypeBox_currentIndexChanged );
107  connect( mAttributeView, &QTreeWidget::itemSelectionChanged, this, &QgsNewMemoryLayerDialog::selectionChanged );
108  connect( mAddAttributeButton, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::mAddAttributeButton_clicked );
109  connect( mRemoveAttributeButton, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked );
110  connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsNewMemoryLayerDialog::showHelp );
111 }
112 
114 {
116  geomType = static_cast<QgsWkbTypes::Type>
117  ( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() );
118 
119  if ( geomType != QgsWkbTypes::Unknown && geomType != QgsWkbTypes::NoGeometry )
120  {
121  if ( mGeometryWithZCheckBox->isChecked() )
122  geomType = QgsWkbTypes::addZ( geomType );
123  if ( mGeometryWithMCheckBox->isChecked() )
124  geomType = QgsWkbTypes::addM( geomType );
125  }
126 
127  return geomType;
128 }
129 
130 void QgsNewMemoryLayerDialog::geometryTypeChanged( int )
131 {
132  const QgsWkbTypes::Type geomType = static_cast<QgsWkbTypes::Type>
133  ( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() );
134 
135  const bool isSpatial = geomType != QgsWkbTypes::NoGeometry;
136  mGeometryWithZCheckBox->setEnabled( isSpatial );
137  mGeometryWithMCheckBox->setEnabled( isSpatial );
138  mCrsSelector->setEnabled( isSpatial );
139 
140  const bool ok = ( !mNameLineEdit->text().isEmpty() && mGeometryTypeBox->currentIndex() != -1 );
141  mOkButton->setEnabled( ok );
142 }
143 
144 void QgsNewMemoryLayerDialog::mTypeBox_currentIndexChanged( int index )
145 {
146  switch ( index )
147  {
148  case 0: // Text data
149  if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 255 )
150  mWidth->setText( QStringLiteral( "255" ) );
151  mPrecision->clear();
152  mPrecision->setEnabled( false );
153  mWidth->setValidator( new QIntValidator( 1, 255, this ) );
154  break;
155  case 1: // Whole number
156  if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 10 )
157  mWidth->setText( QStringLiteral( "10" ) );
158  mPrecision->clear();
159  mPrecision->setEnabled( false );
160  mWidth->setValidator( new QIntValidator( 1, 10, this ) );
161  break;
162  case 2: // Decimal number
163  if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 30 )
164  mWidth->setText( QStringLiteral( "30" ) );
165  if ( mPrecision->text().toInt() < 1 || mPrecision->text().toInt() > 30 )
166  mPrecision->setText( QStringLiteral( "6" ) );
167  mPrecision->setEnabled( true );
168  mWidth->setValidator( new QIntValidator( 1, 20, this ) );
169  break;
170  case 3: // Boolean
171  mWidth->clear();
172  mWidth->setEnabled( false );
173  mPrecision->clear();
174  mPrecision->setEnabled( false );
175  break;
176  case 4: // Date
177  mWidth->clear();
178  mWidth->setEnabled( false );
179  mPrecision->clear();
180  mPrecision->setEnabled( false );
181  break;
182  case 5: // Time
183  mWidth->clear();
184  mWidth->setEnabled( false );
185  mPrecision->clear();
186  mPrecision->setEnabled( false );
187  break;
188  case 6: // Datetime
189  mWidth->clear();
190  mWidth->setEnabled( false );
191  mPrecision->clear();
192  mPrecision->setEnabled( false );
193  break;
194  case 7: // Binary
195  mWidth->clear();
196  mWidth->setEnabled( false );
197  mPrecision->clear();
198  mPrecision->setEnabled( false );
199  break;
200 
201  default:
202  QgsDebugMsg( QStringLiteral( "unexpected index" ) );
203  break;
204  }
205 }
206 
208 {
209  mCrsSelector->setCrs( crs );
210 }
211 
213 {
214  return mCrsSelector->crs();
215 }
216 
218 {
219  return mNameLineEdit->text();
220 }
221 
222 void QgsNewMemoryLayerDialog::fieldNameChanged( const QString &name )
223 {
224  mAddAttributeButton->setDisabled( name.isEmpty() || ! mAttributeView->findItems( name, Qt::MatchExactly ).isEmpty() );
225 }
226 
227 void QgsNewMemoryLayerDialog::selectionChanged()
228 {
229  mRemoveAttributeButton->setDisabled( mAttributeView->selectedItems().isEmpty() );
230 }
231 
233 {
235 
236  QTreeWidgetItemIterator it( mAttributeView );
237  while ( *it )
238  {
239  const QString name( ( *it )->text( 0 ) );
240  const QString typeName( ( *it )->text( 1 ) );
241  const int width = ( *it )->text( 2 ).toInt();
242  const int precision = ( *it )->text( 3 ).toInt();
243  QVariant::Type fieldType = QVariant::Invalid;
244  if ( typeName == QLatin1String( "string" ) )
245  fieldType = QVariant::String;
246  else if ( typeName == QLatin1String( "integer" ) )
247  fieldType = QVariant::Int;
248  else if ( typeName == QLatin1String( "double" ) )
249  fieldType = QVariant::Double;
250  else if ( typeName == QLatin1String( "bool" ) )
251  fieldType = QVariant::Bool;
252  else if ( typeName == QLatin1String( "date" ) )
253  fieldType = QVariant::Date;
254  else if ( typeName == QLatin1String( "time" ) )
255  fieldType = QVariant::Time;
256  else if ( typeName == QLatin1String( "datetime" ) )
257  fieldType = QVariant::DateTime;
258 
259  const QgsField field = QgsField( name, fieldType, typeName, width, precision );
260  fields.append( field );
261  ++it;
262  }
263 
264  return fields;
265 }
266 
267 void QgsNewMemoryLayerDialog::mAddAttributeButton_clicked()
268 {
269  if ( !mFieldNameEdit->text().isEmpty() )
270  {
271  const QString fieldName = mFieldNameEdit->text();
272  const QString fieldType = mTypeBox->currentData( Qt::UserRole ).toString();
273  const QString width = mWidth->text();
274  const QString precision = mPrecision->text();
275  mAttributeView->addTopLevelItem( new QTreeWidgetItem( QStringList() << fieldName << fieldType << width << precision ) );
276 
277  mFieldNameEdit->clear();
278  }
279 }
280 
281 void QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked()
282 {
283  delete mAttributeView->currentItem();
284 }
285 
286 void QgsNewMemoryLayerDialog::showHelp()
287 {
288  QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#creating-a-new-temporary-scratch-layer" ) );
289 }
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
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:168
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.
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.
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