QGIS API Documentation
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 
35  : QDialog( parent, fl )
36 {
37  setupUi( this );
38 
39  QSettings settings;
40  restoreGeometry( settings.value( "/Windows/NewVectorLayer/geometry" ).toByteArray() );
41 
42  mAddAttributeButton->setIcon( QgsApplication::getThemeIcon( "/mActionNewAttribute.png" ) );
43  mRemoveAttributeButton->setIcon( QgsApplication::getThemeIcon( "/mActionDeleteAttribute.png" ) );
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( "/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() << "id" << "Integer" << "10" << "" ) );
87 
89  defaultCrs.createFromOgcWmsCrs( settings.value( "/Projections/layerDefaultCrs", GEO_EPSG_CRS_AUTHID ).toString() );
90  defaultCrs.validate();
91  mCrsSelector->setCrs( defaultCrs );
92 
93  connect( mNameEdit, SIGNAL( textChanged( QString ) ), this, SLOT( nameChanged( QString ) ) );
94  connect( mAttributeView, SIGNAL( itemSelectionChanged() ), this, SLOT( selectionChanged() ) );
95 
96  mAddAttributeButton->setEnabled( false );
97  mRemoveAttributeButton->setEnabled( false );
98 }
99 
101 {
102  QSettings settings;
103  settings.setValue( "/Windows/NewVectorLayer/geometry", saveGeometry() );
104 }
105 
107 {
108  Q_UNUSED( index );
109  if ( mFileFormatComboBox->currentText() == tr( "ESRI Shapefile" ) )
110  mNameEdit->setMaxLength( 10 );
111  else
112  mNameEdit->setMaxLength( 32767 );
113 }
114 
116 {
117  // FIXME: sync with providers/ogr/qgsogrprovider.cpp
118  switch ( index )
119  {
120  case 0: // Text data
121  if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 255 )
122  mWidth->setText( "80" );
123  mPrecision->setEnabled( false );
124  mWidth->setValidator( new QIntValidator( 1, 255, this ) );
125  break;
126 
127  case 1: // Whole number
128  if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 10 )
129  mWidth->setText( "10" );
130  mPrecision->setEnabled( false );
131  mWidth->setValidator( new QIntValidator( 1, 10, this ) );
132  break;
133 
134  case 2: // Decimal number
135  if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 20 )
136  mWidth->setText( "20" );
137  mPrecision->setEnabled( true );
138  mWidth->setValidator( new QIntValidator( 1, 20, this ) );
139  break;
140 
141  default:
142  QgsDebugMsg( "unexpected index" );
143  break;
144  }
145 }
146 
148 {
149  if ( mPointRadioButton->isChecked() )
150  {
151  return QGis::WKBPoint;
152  }
153  else if ( mLineRadioButton->isChecked() )
154  {
155  return QGis::WKBLineString;
156  }
157  else if ( mPolygonRadioButton->isChecked() )
158  {
159  return QGis::WKBPolygon;
160  }
161  return QGis::WKBUnknown;
162 }
163 
165 {
166  return mCrsSelector->crs().srsid();
167 }
168 
170 {
171  QString myName = mNameEdit->text();
172  QString myWidth = mWidth->text();
173  QString myPrecision = mPrecision->isEnabled() ? mPrecision->text() : "";
174  //use userrole to avoid translated type string
175  QString myType = mTypeBox->itemData( mTypeBox->currentIndex(), Qt::UserRole ).toString();
176  mAttributeView->addTopLevelItem( new QTreeWidgetItem( QStringList() << myName << myType << myWidth << myPrecision ) );
177  if ( mAttributeView->topLevelItemCount() > 0 )
178  {
179  mOkButton->setEnabled( true );
180  }
181  mNameEdit->clear();
182 }
183 
185 {
186  delete mAttributeView->currentItem();
187  if ( mAttributeView->topLevelItemCount() == 0 )
188  {
189  mOkButton->setEnabled( false );
190  }
191 }
192 
194 {
195  QTreeWidgetItemIterator it( mAttributeView );
196  while ( *it )
197  {
198  QTreeWidgetItem *item = *it;
199  QString type = QString( "%1;%2;%3" ).arg( item->text( 1 ), item->text( 2 ), item->text( 3 ) );
200  at.push_back( qMakePair( item->text( 0 ), type ) );
201  QgsDebugMsg( QString( "appending %1//%2" ).arg( item->text( 0 ), type ) );
202  ++it;
203  }
204 }
205 
207 {
208  //use userrole to avoid translated type string
209  QString myType = mFileFormatComboBox->itemData( mFileFormatComboBox->currentIndex(), Qt::UserRole ).toString();
210  return myType;
211 }
212 
214 {
215  return mFileEncoding->currentText();
216 }
217 
219 {
220  mAddAttributeButton->setDisabled( name.isEmpty() || !mAttributeView->findItems( name, Qt::MatchExactly ).isEmpty() );
221 }
222 
224 {
225  mRemoveAttributeButton->setDisabled( mAttributeView->selectedItems().isEmpty() );
226 }
227 
228 
229 // this is static
231 {
232  QgsNewVectorLayerDialog geomDialog( parent );
233  if ( geomDialog.exec() == QDialog::Rejected )
234  {
235  return "";
236  }
237 
238  QGis::WkbType geometrytype = geomDialog.selectedType();
239  QString fileformat = geomDialog.selectedFileFormat();
240  QString enc = geomDialog.selectedFileEncoding();
241  int crsId = geomDialog.selectedCrsId();
242  QgsDebugMsg( QString( "New file format will be: %1" ).arg( fileformat ) );
243 
245  geomDialog.attributes( attributes );
246 
247  QSettings settings;
248  QString lastUsedDir = settings.value( "/UI/lastVectorFileFilterDir", QDir::homePath() ).toString();
249  QString filterString = QgsVectorFileWriter::filterForDriver( fileformat );
250  QString fileName = QFileDialog::getSaveFileName( nullptr, tr( "Save layer as..." ), lastUsedDir, filterString );
251  if ( fileName.isNull() )
252  {
253  return "";
254  }
255 
256  if ( fileformat == "ESRI Shapefile" && !fileName.endsWith( ".shp", Qt::CaseInsensitive ) )
257  fileName += ".shp";
258 
259  settings.setValue( "/UI/lastVectorFileFilterDir", QFileInfo( fileName ).absolutePath() );
260  settings.setValue( "/UI/encoding", enc );
261 
262  //try to create the new layer with OGRProvider instead of QgsVectorFileWriter
264  QString ogrlib = pReg->library( "ogr" );
265  // load the data provider
266  QLibrary* myLib = new QLibrary( ogrlib );
267  bool loaded = myLib->load();
268  if ( loaded )
269  {
270  QgsDebugMsg( "ogr provider loaded" );
271 
272  typedef bool ( *createEmptyDataSourceProc )( const QString&, const QString&, const QString&, QGis::WkbType,
274  createEmptyDataSourceProc createEmptyDataSource = ( createEmptyDataSourceProc ) cast_to_fptr( myLib->resolve( "createEmptyDataSource" ) );
275  if ( createEmptyDataSource )
276  {
277  if ( geometrytype != QGis::WKBUnknown )
278  {
280  if ( !createEmptyDataSource( fileName, fileformat, enc, geometrytype, attributes, &srs ) )
281  {
282  return QString::null;
283  }
284  }
285  else
286  {
287  QgsDebugMsg( "geometry type not recognised" );
288  return QString::null;
289  }
290  }
291  else
292  {
293  QgsDebugMsg( "Resolving newEmptyDataSource(...) failed" );
294  return QString::null;
295  }
296  }
297 
298  if ( pEnc )
299  *pEnc = enc;
300 
301  return fileName;
302 }
void nameChanged(const QString &)
QByteArray toByteArray() const
static unsigned index
static QgsProviderRegistry * instance(const QString &pluginPath=QString::null)
Means of accessing canonical single instance.
void setupUi(QWidget *widget)
QString selectedFileEncoding() const
Returns the file format for storage.
void on_mTypeBox_currentIndexChanged(int index)
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QString library(const QString &providerKey) const
Return path for the library of the provider.
void validate()
Perform some validation on this CRS.
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
int selectedCrsId() const
Returns the selected crs id.
int exec()
WkbType
Used for symbology operations.
Definition: qgis.h:57
QString homePath()
QString selectedFileFormat() const
Returns the file format for storage.
QString tr(const char *sourceText, const char *disambiguation, int n)
bool isNull() const
static const QStringList & availableEncodings()
Returns a list of available encodings.
void setValue(const QString &key, const QVariant &value)
bool createFromOgcWmsCrs(QString theCrs)
Set up this CRS from the given OGC CRS.
const char * name() const
void setEnabled(bool)
bool restoreGeometry(const QByteArray &geometry)
bool isEmpty() const
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
const QString GEO_EPSG_CRS_AUTHID
Geographic coord sys from EPSG authority.
Definition: qgis.cpp:74
void push_back(QChar ch)
bool load()
A registry / canonical manager of data providers.
QVariant value(const QString &key, const QVariant &defaultValue) const
void attributes(QList< QPair< QString, QString > > &at) const
Appends the chosen attribute names and types to at.
QGis::WkbType selectedType() const
Returns the selected geometry type.
void * resolve(const char *symbol)
QByteArray saveGeometry() const
static QString runAndCreateLayer(QWidget *parent=nullptr, QString *enc=nullptr)
Class for storing a coordinate reference system (CRS)
QgsNewVectorLayerDialog(QWidget *parent=nullptr, const Qt::WindowFlags &fl=QgisGui::ModalDialogFlags)
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFlags< QFileDialog::Option > options)
typedef WindowFlags
void(*)() cast_to_fptr(void *p)
Definition: qgis.h:268
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
QString text(int column) const
void on_mFileFormatComboBox_currentIndexChanged(int index)
static QString filterForDriver(const QString &driverName)
Creates a filter for an OGR driver key.