30#include "qgsogrproviderutils.h"
42#include "moc_qgsnewvectorlayerdialog.cpp"
44using namespace Qt::StringLiterals;
47 : QDialog( parent, fl )
52 connect( mAddAttributeButton, &QToolButton::clicked,
this, &QgsNewVectorLayerDialog::mAddAttributeButton_clicked );
53 connect( mRemoveAttributeButton, &QToolButton::clicked,
this, &QgsNewVectorLayerDialog::mRemoveAttributeButton_clicked );
54 connect( mFileFormatComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsNewVectorLayerDialog::mFileFormatComboBox_currentIndexChanged );
55 connect( mTypeBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsNewVectorLayerDialog::mTypeBox_currentIndexChanged );
56 connect( buttonBox, &QDialogButtonBox::helpRequested,
this, &QgsNewVectorLayerDialog::showHelp );
57 connect( mButtonUp, &QToolButton::clicked,
this, &QgsNewVectorLayerDialog::moveFieldsUp );
58 connect( mButtonDown, &QToolButton::clicked,
this, &QgsNewVectorLayerDialog::moveFieldsDown );
67#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 9, 0 )
71 mWidth->setValidator(
new QIntValidator( 1, 255,
this ) );
72 mPrecision->setValidator(
new QIntValidator( 0, 15,
this ) );
82 for (
const auto type : geomTypes )
84 mGeometryTypeBox->setCurrentIndex( -1 );
86 mOkButton = buttonBox->button( QDialogButtonBox::Ok );
87 mOkButton->setEnabled(
false );
89 mFileFormatComboBox->addItem( tr(
"ESRI Shapefile" ),
"ESRI Shapefile" );
93 mFileFormatComboBox->addItem( tr(
"Comma Separated Value" ),
"Comma Separated Value" );
94 mFileFormatComboBox->addItem( tr(
"GML" ),
"GML" );
95 mFileFormatComboBox->addItem( tr(
"Mapinfo File" ),
"Mapinfo File" );
97 if ( mFileFormatComboBox->count() == 1 )
99 mFileFormatComboBox->setVisible(
false );
100 mFileFormatLabel->setVisible(
false );
103 mCrsSelector->setShowAccuracyWarnings(
true );
105 mFileFormatComboBox->setCurrentIndex( 0 );
110 const QString enc =
QgsSettings().
value( u
"/UI/encoding"_s,
"System" ).toString();
114 int encindex = mFileEncoding->findText( enc );
117 mFileEncoding->insertItem( 0, enc );
120 mFileEncoding->setCurrentIndex( encindex );
122 mAttributeView->addTopLevelItem(
new QTreeWidgetItem( QStringList() << u
"id"_s << u
"Integer"_s << u
"10"_s << QString() ) );
123 connect( mNameEdit, &QLineEdit::textChanged,
this, &QgsNewVectorLayerDialog::nameChanged );
124 connect( mAttributeView, &QTreeWidget::itemSelectionChanged,
this, &QgsNewVectorLayerDialog::selectionChanged );
125 connect( mGeometryTypeBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, [
this](
int ) {
130 mAddAttributeButton->setEnabled(
false );
131 mRemoveAttributeButton->setEnabled(
false );
132 mButtonUp->setEnabled(
false );
133 mButtonDown->setEnabled(
false );
137 mFileName->setConfirmOverwrite(
false );
138 mFileName->setDialogTitle( tr(
"Save Layer As" ) );
140 mFileName->setDefaultRoot( settings.
value( u
"UI/lastVectorFileFilterDir"_s, QDir::homePath() ).toString() );
143 const QFileInfo tmplFileInfo( mFileName->filePath() );
144 settings.
setValue( u
"UI/lastVectorFileFilterDir"_s, tmplFileInfo.absolutePath() );
149void QgsNewVectorLayerDialog::mFileFormatComboBox_currentIndexChanged(
int index )
152 if ( mFileFormatComboBox->currentText() == tr(
"ESRI Shapefile" ) )
153 mNameEdit->setMaxLength( 10 );
155 mNameEdit->setMaxLength( 32767 );
158void QgsNewVectorLayerDialog::mTypeBox_currentIndexChanged(
int index )
164 if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 255 )
165 mWidth->setText( u
"80"_s );
166 mPrecision->setEnabled(
false );
167 mWidth->setEnabled(
true );
168 mWidth->setValidator(
new QIntValidator( 1, 255,
this ) );
172 if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 10 )
173 mWidth->setText( u
"10"_s );
174 mPrecision->setEnabled(
false );
175 mWidth->setEnabled(
true );
176 mWidth->setValidator(
new QIntValidator( 1, 10,
this ) );
180 if ( mWidth->text().toInt() < 1 || mWidth->text().toInt() > 20 )
181 mWidth->setText( u
"20"_s );
182 if ( mPrecision->text().toInt() < 1 || mPrecision->text().toInt() > 15 )
183 mPrecision->setText( u
"6"_s );
185 mPrecision->setEnabled(
true );
186 mWidth->setEnabled(
true );
187 mWidth->setValidator(
new QIntValidator( 1, 20,
this ) );
191 mPrecision->setEnabled(
false );
192 mWidth->setEnabled(
false );
202 wkbType =
static_cast<Qgis::WkbType>( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() );
204 if ( mGeometryWithZRadioButton->isChecked() )
207 if ( mGeometryWithMRadioButton->isChecked() )
215 return mCrsSelector->crs();
220 mCrsSelector->setCrs(
crs );
223void QgsNewVectorLayerDialog::mAddAttributeButton_clicked()
225 const QString myName = mNameEdit->text();
226 const QString myWidth = mWidth->text();
227 const QString myPrecision = mPrecision->isEnabled() ? mPrecision->text() : QString();
229 const QString myType = mTypeBox->currentData( Qt::UserRole ).toString();
230 mAttributeView->addTopLevelItem(
new QTreeWidgetItem( QStringList() << myName << myType << myWidth << myPrecision ) );
236 if ( !mNameEdit->hasFocus() )
238 mNameEdit->setFocus();
242void QgsNewVectorLayerDialog::mRemoveAttributeButton_clicked()
244 delete mAttributeView->currentItem();
250 QTreeWidgetItemIterator it( mAttributeView );
253 QTreeWidgetItem *item = *it;
254 const QString type = u
"%1;%2;%3"_s.arg( item->text( 1 ), item->text( 2 ), item->text( 3 ) );
255 at.push_back( qMakePair( item->text( 0 ), type ) );
264 QString myType = mFileFormatComboBox->currentData( Qt::UserRole ).toString();
270 return mFileEncoding->currentText();
273void QgsNewVectorLayerDialog::nameChanged(
const QString &name )
275 mAddAttributeButton->setDisabled( name.isEmpty() || !mAttributeView->findItems( name, Qt::MatchExactly ).isEmpty() );
278void QgsNewVectorLayerDialog::selectionChanged()
280 mRemoveAttributeButton->setDisabled( mAttributeView->selectedItems().isEmpty() );
281 mButtonUp->setDisabled( mAttributeView->selectedItems().isEmpty() );
282 mButtonDown->setDisabled( mAttributeView->selectedItems().isEmpty() );
285void QgsNewVectorLayerDialog::moveFieldsUp()
287 int currentRow = mAttributeView->currentIndex().row();
288 if ( currentRow == 0 )
291 mAttributeView->insertTopLevelItem( currentRow - 1, mAttributeView->takeTopLevelItem( currentRow ) );
292 mAttributeView->setCurrentIndex( mAttributeView->model()->index( currentRow - 1, 0 ) );
295void QgsNewVectorLayerDialog::moveFieldsDown()
297 int currentRow = mAttributeView->currentIndex().row();
298 if ( currentRow == mAttributeView->topLevelItemCount() - 1 )
301 mAttributeView->insertTopLevelItem( currentRow + 1, mAttributeView->takeTopLevelItem( currentRow ) );
302 mAttributeView->setCurrentIndex( mAttributeView->model()->index( currentRow + 1, 0 ) );
307 return mFileName->filePath();
315void QgsNewVectorLayerDialog::checkOk()
317 const bool ok = ( !mFileName->filePath().isEmpty() && mAttributeView->topLevelItemCount() > 0 && mGeometryTypeBox->currentIndex() != -1 );
318 mOkButton->setEnabled( ok );
326 if ( res.isEmpty() && error.isEmpty() )
331void QgsNewVectorLayerDialog::updateExtension()
336 if ( fileformat ==
"ESRI Shapefile"_L1 )
340 fileName = fileName.replace( fileName.lastIndexOf(
".dbf"_L1, -1, Qt::CaseInsensitive ), 4,
".shp"_L1 );
345 fileName = fileName.replace( fileName.lastIndexOf(
".shp"_L1, -1, Qt::CaseInsensitive ), 4,
".dbf"_L1 );
354 if ( !mNameEdit->text().trimmed().isEmpty() )
356 const QString currentFieldName = mNameEdit->text();
357 bool currentFound =
false;
358 QTreeWidgetItemIterator it( mAttributeView );
361 QTreeWidgetItem *item = *it;
362 if ( item->text( 0 ) == currentFieldName )
372 if ( QMessageBox::question(
this, windowTitle(), tr(
"The field “%1” has not been added to the fields list. Are you sure you want to proceed and discard this field?" ).arg( currentFieldName ), QMessageBox::Ok | QMessageBox::Cancel ) != QMessageBox::Ok )
381 if ( QFile::exists(
filename() ) && QMessageBox::warning(
this, tr(
"New ShapeFile Layer" ), tr(
"The layer already exists. Are you sure you want to overwrite the existing file?" ), QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel ) != QMessageBox::Yes )
389 errorMessage.clear();
392 if ( !initialPath.isEmpty() )
394 if ( geomDialog.exec() == QDialog::Rejected )
401 QString fileName = geomDialog.
filename();
410 settings.
setValue( u
"UI/lastVectorFileFilterDir"_s, QFileInfo( fileName ).absolutePath() );
411 settings.
setValue( u
"UI/encoding"_s, enc );
417 const bool success = QgsOgrProviderUtils::createEmptyDataSource( fileName, fileformat, enc, geometrytype,
attributes, srs, errorMessage );
425 errorMessage = QObject::tr(
"Geometry type not recognised" );
436void QgsNewVectorLayerDialog::showHelp()
438 QgsHelp::openHelp( u
"managing_data_source/create_layers.html#creating-a-new-shapefile-layer"_s );
WkbType
The WKB type describes the number of dimensions a geometry has.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Represents a coordinate reference system (CRS).
static QIcon iconForFieldType(QMetaType::Type type, QMetaType::Type subType=QMetaType::Type::UnknownType, const QString &typeString=QString())
Returns an icon corresponding to a field type.
static QString ensureFileNameHasExtension(const QString &fileName, const QStringList &extensions)
Ensures that a fileName ends with an extension from the provided list of extensions.
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...
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
static QIcon iconForWkbType(Qgis::WkbType type)
Returns the icon for a vector layer whose geometry type is provided.
static Q_DECL_DEPRECATED QString runAndCreateLayer(QWidget *parent=nullptr, QString *enc=nullptr, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem(), const QString &initialPath=QString())
Runs the dialog and creates a layer matching the dialog parameters.
void attributes(QList< QPair< QString, QString > > &at) const
Appends the chosen attribute names and types to at.
QgsCoordinateReferenceSystem crs() const
Returns the selected CRS for the new layer.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the crs value for the new layer in the dialog.
QString filename() const
Returns the name for the new layer.
QString selectedFileFormat() const
Returns the file format for storage.
QString selectedFileEncoding() const
Returns the file format for storage.
QgsNewVectorLayerDialog(QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags)
New dialog constructor.
static QString execAndCreateLayer(QString &errorMessage, QWidget *parent=nullptr, const QString &initialPath=QString(), QString *encoding=nullptr, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem())
Runs the dialog and creates a layer matching the dialog parameters.
Qgis::WkbType selectedType() const
Returns the selected geometry type.
void setFilename(const QString &filename)
Sets the initial file name to show in the dialog.
Stores settings for use within QGIS.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
static QString typeToDisplayString(QMetaType::Type type, QMetaType::Type subType=QMetaType::Type::UnknownType)
Returns a user-friendly translated string representing a QVariant type.
static QStringList availableEncodings()
Returns a list of available encodings.
static QString filterForDriver(const QString &driverName)
Creates a filter for an OGR driver key.
static Q_INVOKABLE QString translatedDisplayString(Qgis::WkbType type)
Returns a translated display string type for a WKB type, e.g., the geometry name used in WKT geometry...
static Qgis::WkbType addM(Qgis::WkbType type)
Adds the m dimension to a WKB type and returns the new type.
static Qgis::WkbType addZ(Qgis::WkbType type)
Adds the z dimension to a WKB type and returns the new type.
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)