QGIS API Documentation  2.99.0-Master (d55fa22)
qgsnewvectorlayerdialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsnewvectorlayerdialog.cpp - description
3  -------------------
4  begin : October 2004
5  copyright : (C) 2004 by Marco Hugentobler
6  email : [email protected]
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 "qgslogger.h"
23 #include "qgsproviderregistry.h"
24 #include "qgsvectordataprovider.h"
25 #include "qgsvectorfilewriter.h"
26 #include "qgssettings.h"
27 
28 #include <QPushButton>
29 #include <QComboBox>
30 #include <QLibrary>
31 #include <QFileDialog>
32 
33 
34 QgsNewVectorLayerDialog::QgsNewVectorLayerDialog( QWidget *parent, Qt::WindowFlags fl )
35  : QDialog( parent, fl )
36 {
37  setupUi( this );
38 
39  QgsSettings settings;
40  restoreGeometry( settings.value( QStringLiteral( "Windows/NewVectorLayer/geometry" ) ).toByteArray() );
41 
42  mAddAttributeButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionNewAttribute.svg" ) ) );
43  mRemoveAttributeButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDeleteAttribute.svg" ) ) );
44  mTypeBox->addItem( tr( "Text data" ), "String" );
45  mTypeBox->addItem( tr( "Whole number" ), "Integer" );
46  mTypeBox->addItem( tr( "Decimal number" ), "Real" );
47  mTypeBox->addItem( tr( "Date" ), "Date" );
48 
49  mWidth->setValidator( new QIntValidator( 1, 255, this ) );
50  mPrecision->setValidator( new QIntValidator( 0, 15, this ) );
51 
52  mPointRadioButton->setChecked( true );
53  mFileFormatComboBox->addItem( tr( "ESRI Shapefile" ), "ESRI Shapefile" );
54 #if 0
55  // Disabled until provider properly supports editing the created file formats
56  // When enabling this, adapt the window-title of the dialog and the title of all actions showing this dialog.
57  mFileFormatComboBox->addItem( tr( "Comma Separated Value" ), "Comma Separated Value" );
58  mFileFormatComboBox->addItem( tr( "GML" ), "GML" );
59  mFileFormatComboBox->addItem( tr( "Mapinfo File" ), "Mapinfo File" );
60 #endif
61  if ( mFileFormatComboBox->count() == 1 )
62  {
63  mFileFormatComboBox->setVisible( false );
64  mFileFormatLabel->setVisible( false );
65  }
66 
67  mFileFormatComboBox->setCurrentIndex( 0 );
68 
69  mFileEncoding->addItems( QgsVectorDataProvider::availableEncodings() );
70 
71  // Use default encoding if none supplied
72  QString enc = QgsSettings().value( QStringLiteral( "/UI/encoding" ), "System" ).toString();
73 
74  // The specified decoding is added if not existing alread, and then set current.
75  // This should select it.
76  int encindex = mFileEncoding->findText( enc );
77  if ( encindex < 0 )
78  {
79  mFileEncoding->insertItem( 0, enc );
80  encindex = 0;
81  }
82  mFileEncoding->setCurrentIndex( encindex );
83 
84  mOkButton = buttonBox->button( QDialogButtonBox::Ok );
85 
86  mAttributeView->addTopLevelItem( new QTreeWidgetItem( QStringList() << QStringLiteral( "id" ) << QStringLiteral( "Integer" ) << QStringLiteral( "10" ) << QLatin1String( "" ) ) );
87  connect( mNameEdit, &QLineEdit::textChanged, this, &QgsNewVectorLayerDialog::nameChanged );
88  connect( mAttributeView, &QTreeWidget::itemSelectionChanged, this, &QgsNewVectorLayerDialog::selectionChanged );
89 
90  mAddAttributeButton->setEnabled( false );
91  mRemoveAttributeButton->setEnabled( false );
92 }
93 
95 {
96  QgsSettings settings;
97  settings.setValue( QStringLiteral( "Windows/NewVectorLayer/geometry" ), saveGeometry() );
98 }
99 
101 {
102  Q_UNUSED( index );
103  if ( mFileFormatComboBox->currentText() == tr( "ESRI Shapefile" ) )
104  mNameEdit->setMaxLength( 10 );
105  else
106  mNameEdit->setMaxLength( 32767 );
107 }
108 
110 {
111  // FIXME: sync with providers/ogr/qgsogrprovider.cpp
112  switch ( index )
113  {
114  case 0: // Text data
115  if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 255 )
116  mWidth->setText( QStringLiteral( "80" ) );
117  mPrecision->setEnabled( false );
118  mWidth->setValidator( new QIntValidator( 1, 255, this ) );
119  break;
120 
121  case 1: // Whole number
122  if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 10 )
123  mWidth->setText( QStringLiteral( "10" ) );
124  mPrecision->setEnabled( false );
125  mWidth->setValidator( new QIntValidator( 1, 10, this ) );
126  break;
127 
128  case 2: // Decimal number
129  if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 20 )
130  mWidth->setText( QStringLiteral( "20" ) );
131  mPrecision->setEnabled( true );
132  mWidth->setValidator( new QIntValidator( 1, 20, this ) );
133  break;
134 
135  default:
136  QgsDebugMsg( "unexpected index" );
137  break;
138  }
139 }
140 
142 {
144  if ( mPointRadioButton->isChecked() )
145  {
146  wkbType = QgsWkbTypes::Point;
147  }
148  else if ( mLineRadioButton->isChecked() )
149  {
150  wkbType = QgsWkbTypes::LineString;
151  }
152  else if ( mPolygonRadioButton->isChecked() )
153  {
154  wkbType = QgsWkbTypes::Polygon;
155  }
156 
157  if ( mGeometryWithZCheckBox->isChecked() && wkbType != QgsWkbTypes::Unknown )
158  wkbType = QgsWkbTypes::to25D( wkbType );
159 
160  return wkbType;
161 }
162 
164 {
165  return mCrsSelector->crs();
166 }
167 
169 {
170  mCrsSelector->setCrs( crs );
171 }
172 
174 {
175  QString myName = mNameEdit->text();
176  QString myWidth = mWidth->text();
177  QString myPrecision = mPrecision->isEnabled() ? mPrecision->text() : QLatin1String( "" );
178  //use userrole to avoid translated type string
179  QString myType = mTypeBox->currentData( Qt::UserRole ).toString();
180  mAttributeView->addTopLevelItem( new QTreeWidgetItem( QStringList() << myName << myType << myWidth << myPrecision ) );
181  if ( mAttributeView->topLevelItemCount() > 0 )
182  {
183  mOkButton->setEnabled( true );
184  }
185  mNameEdit->clear();
186 }
187 
189 {
190  delete mAttributeView->currentItem();
191  if ( mAttributeView->topLevelItemCount() == 0 )
192  {
193  mOkButton->setEnabled( false );
194  }
195 }
196 
197 void QgsNewVectorLayerDialog::attributes( QList< QPair<QString, QString> > &at ) const
198 {
199  QTreeWidgetItemIterator it( mAttributeView );
200  while ( *it )
201  {
202  QTreeWidgetItem *item = *it;
203  QString type = QStringLiteral( "%1;%2;%3" ).arg( item->text( 1 ), item->text( 2 ), item->text( 3 ) );
204  at.push_back( qMakePair( item->text( 0 ), type ) );
205  QgsDebugMsg( QString( "appending %1//%2" ).arg( item->text( 0 ), type ) );
206  ++it;
207  }
208 }
209 
211 {
212  //use userrole to avoid translated type string
213  QString myType = mFileFormatComboBox->currentData( Qt::UserRole ).toString();
214  return myType;
215 }
216 
218 {
219  return mFileEncoding->currentText();
220 }
221 
222 void QgsNewVectorLayerDialog::nameChanged( const QString &name )
223 {
224  mAddAttributeButton->setDisabled( name.isEmpty() || !mAttributeView->findItems( name, Qt::MatchExactly ).isEmpty() );
225 }
226 
228 {
229  mRemoveAttributeButton->setDisabled( mAttributeView->selectedItems().isEmpty() );
230 }
231 
232 
233 // this is static
234 QString QgsNewVectorLayerDialog::runAndCreateLayer( QWidget *parent, QString *pEnc, const QgsCoordinateReferenceSystem &crs )
235 {
236  QgsNewVectorLayerDialog geomDialog( parent );
237  geomDialog.setCrs( crs );
238  if ( geomDialog.exec() == QDialog::Rejected )
239  {
240  return QLatin1String( "" );
241  }
242 
243  QgsWkbTypes::Type geometrytype = geomDialog.selectedType();
244  QString fileformat = geomDialog.selectedFileFormat();
245  QString enc = geomDialog.selectedFileEncoding();
246  QgsDebugMsg( QString( "New file format will be: %1" ).arg( fileformat ) );
247 
248  QList< QPair<QString, QString> > attributes;
249  geomDialog.attributes( attributes );
250 
251  QgsSettings settings;
252  QString lastUsedDir = settings.value( QStringLiteral( "UI/lastVectorFileFilterDir" ), QDir::homePath() ).toString();
253  QString filterString = QgsVectorFileWriter::filterForDriver( fileformat );
254  QString fileName = QFileDialog::getSaveFileName( nullptr, tr( "Save layer as..." ), lastUsedDir, filterString );
255  if ( fileName.isNull() )
256  {
257  return QLatin1String( "" );
258  }
259 
260  if ( fileformat == QLatin1String( "ESRI Shapefile" ) && !fileName.endsWith( QLatin1String( ".shp" ), Qt::CaseInsensitive ) )
261  fileName += QLatin1String( ".shp" );
262 
263  settings.setValue( QStringLiteral( "UI/lastVectorFileFilterDir" ), QFileInfo( fileName ).absolutePath() );
264  settings.setValue( QStringLiteral( "UI/encoding" ), enc );
265 
266  //try to create the new layer with OGRProvider instead of QgsVectorFileWriter
268  QString ogrlib = pReg->library( QStringLiteral( "ogr" ) );
269  // load the data provider
270  QLibrary *myLib = new QLibrary( ogrlib );
271  bool loaded = myLib->load();
272  if ( loaded )
273  {
274  QgsDebugMsg( "ogr provider loaded" );
275 
276  typedef bool ( *createEmptyDataSourceProc )( const QString &, const QString &, const QString &, QgsWkbTypes::Type,
277  const QList< QPair<QString, QString> > &, const QgsCoordinateReferenceSystem & );
278  createEmptyDataSourceProc createEmptyDataSource = ( createEmptyDataSourceProc ) cast_to_fptr( myLib->resolve( "createEmptyDataSource" ) );
279  if ( createEmptyDataSource )
280  {
281  if ( geometrytype != QgsWkbTypes::Unknown )
282  {
283  QgsCoordinateReferenceSystem srs = geomDialog.crs();
284  if ( !createEmptyDataSource( fileName, fileformat, enc, geometrytype, attributes, srs ) )
285  {
286  return QString::null;
287  }
288  }
289  else
290  {
291  QgsDebugMsg( "geometry type not recognised" );
292  return QString::null;
293  }
294  }
295  else
296  {
297  QgsDebugMsg( "Resolving newEmptyDataSource(...) failed" );
298  return QString::null;
299  }
300  }
301 
302  if ( pEnc )
303  *pEnc = enc;
304 
305  return fileName;
306 }
void nameChanged(const QString &)
static QgsProviderRegistry * instance(const QString &pluginPath=QString::null)
Means of accessing canonical single instance.
QString selectedFileEncoding() const
Returns the file format for storage.
static Type to25D(Type type)
Will convert the 25D version of the flat type if supported or Unknown if not supported.
Definition: qgswkbtypes.h:936
QString selectedFileFormat() const
Returns the file format for storage.
void on_mTypeBox_currentIndexChanged(int index)
This class is a composition of two QSettings instances:
Definition: qgssettings.h:54
#define QgsDebugMsg(str)
Definition: qgslogger.h:37
QString library(const QString &providerKey) const
Return path for the library of the provider.
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
void attributes(QList< QPair< QString, QString > > &at) const
Appends the chosen attribute names and types to at.
void setValue(const QString &key, const QVariant &value, const QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:66
#define cast_to_fptr(f)
Definition: qgis.h:119
static QString runAndCreateLayer(QWidget *parent=nullptr, QString *enc=nullptr, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem())
Runs the dialog and creates a layer matching the dialog parameters.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the crs value for the new layer in the dialog.
A registry / canonical manager of data providers.
QgsNewVectorLayerDialog(QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags)
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=NoSection) const
Returns the value for setting key.
QgsCoordinateReferenceSystem crs() const
Returns the selected CRS for the new layer.
This class represents a coordinate reference system (CRS).
QgsWkbTypes::Type selectedType() const
Returns the selected geometry type.
void on_mFileFormatComboBox_currentIndexChanged(int index)
static QString filterForDriver(const QString &driverName)
Creates a filter for an OGR driver key.
static QStringList availableEncodings()
Returns a list of available encodings.