QGIS API Documentation  2.99.0-Master (a18066b)
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 
27 #include <QPushButton>
28 #include <QComboBox>
29 #include <QLibrary>
30 #include <QSettings>
31 #include <QFileDialog>
32 
33 
34 QgsNewVectorLayerDialog::QgsNewVectorLayerDialog( QWidget *parent, Qt::WindowFlags fl )
35  : QDialog( parent, fl )
36 {
37  setupUi( this );
38 
39  QSettings 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 = QSettings().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 
88  QgsCoordinateReferenceSystem defaultCrs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( settings.value( QStringLiteral( "/Projections/layerDefaultCrs" ), GEO_EPSG_CRS_AUTHID ).toString() );
89  defaultCrs.validate();
90  mCrsSelector->setCrs( defaultCrs );
91 
92  connect( mNameEdit, SIGNAL( textChanged( QString ) ), this, SLOT( nameChanged( QString ) ) );
93  connect( mAttributeView, SIGNAL( itemSelectionChanged() ), this, SLOT( selectionChanged() ) );
94 
95  mAddAttributeButton->setEnabled( false );
96  mRemoveAttributeButton->setEnabled( false );
97 }
98 
100 {
101  QSettings settings;
102  settings.setValue( QStringLiteral( "/Windows/NewVectorLayer/geometry" ), saveGeometry() );
103 }
104 
106 {
107  Q_UNUSED( index );
108  if ( mFileFormatComboBox->currentText() == tr( "ESRI Shapefile" ) )
109  mNameEdit->setMaxLength( 10 );
110  else
111  mNameEdit->setMaxLength( 32767 );
112 }
113 
115 {
116  // FIXME: sync with providers/ogr/qgsogrprovider.cpp
117  switch ( index )
118  {
119  case 0: // Text data
120  if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 255 )
121  mWidth->setText( QStringLiteral( "80" ) );
122  mPrecision->setEnabled( false );
123  mWidth->setValidator( new QIntValidator( 1, 255, this ) );
124  break;
125 
126  case 1: // Whole number
127  if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 10 )
128  mWidth->setText( QStringLiteral( "10" ) );
129  mPrecision->setEnabled( false );
130  mWidth->setValidator( new QIntValidator( 1, 10, this ) );
131  break;
132 
133  case 2: // Decimal number
134  if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 20 )
135  mWidth->setText( QStringLiteral( "20" ) );
136  mPrecision->setEnabled( true );
137  mWidth->setValidator( new QIntValidator( 1, 20, this ) );
138  break;
139 
140  default:
141  QgsDebugMsg( "unexpected index" );
142  break;
143  }
144 }
145 
147 {
149  if ( mPointRadioButton->isChecked() )
150  {
151  wkbType = QgsWkbTypes::Point;
152  }
153  else if ( mLineRadioButton->isChecked() )
154  {
155  wkbType = QgsWkbTypes::LineString;
156  }
157  else if ( mPolygonRadioButton->isChecked() )
158  {
159  wkbType = QgsWkbTypes::Polygon;
160  }
161 
162  if ( mGeometryWithZCheckBox->isChecked() && wkbType != QgsWkbTypes::Unknown )
163  wkbType = QgsWkbTypes::to25D( wkbType );
164 
165  return wkbType;
166 }
167 
169 {
170  return mCrsSelector->crs().srsid();
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 )
235 {
236  QgsNewVectorLayerDialog geomDialog( parent );
237  if ( geomDialog.exec() == QDialog::Rejected )
238  {
239  return QLatin1String( "" );
240  }
241 
242  QgsWkbTypes::Type geometrytype = geomDialog.selectedType();
243  QString fileformat = geomDialog.selectedFileFormat();
244  QString enc = geomDialog.selectedFileEncoding();
245  int crsId = geomDialog.selectedCrsId();
246  QgsDebugMsg( QString( "New file format will be: %1" ).arg( fileformat ) );
247 
248  QList< QPair<QString, QString> > attributes;
249  geomDialog.attributes( attributes );
250 
251  QSettings 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  {
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 unsigned index
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:892
QString selectedFileFormat() const
Returns the file format for storage.
void on_mTypeBox_currentIndexChanged(int index)
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
void validate()
Perform some validation on this CRS.
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.
QgsNewVectorLayerDialog(QWidget *parent=nullptr, Qt::WindowFlags fl=QgisGui::ModalDialogFlags)
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:65
const QString GEO_EPSG_CRS_AUTHID
Geographic coord sys from EPSG authority.
Definition: qgis.cpp:69
#define cast_to_fptr(f)
Definition: qgis.h:128
A registry / canonical manager of data providers.
int selectedCrsId() const
Returns the selected crs id.
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
static QString runAndCreateLayer(QWidget *parent=nullptr, QString *enc=nullptr)
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.
static QgsCoordinateReferenceSystem fromSrsId(long srsId)
Creates a CRS from a specified QGIS SRS ID.