Skip to content

Commit

Permalink
Merge pull request #36289 from alexbruy/scratch-attributes
Browse files Browse the repository at this point in the history
allow adding attributes in the New Scratch Layer dialog (fix #24397)
  • Loading branch information
alexbruy committed May 12, 2020
2 parents 59e1dce + 95463e6 commit 3e63210
Show file tree
Hide file tree
Showing 4 changed files with 317 additions and 65 deletions.
7 changes: 7 additions & 0 deletions python/gui/auto_generated/qgsnewmemorylayerdialog.sip.in
Expand Up @@ -56,6 +56,13 @@ Returns the selected CRS for the new layer.
QString layerName() const;
%Docstring
Returns the layer name
%End

QgsFields fields() const;
%Docstring
Returns attributes for the new layer.

.. versionadded:: 3.14
%End

};
Expand Down
96 changes: 93 additions & 3 deletions src/gui/qgsnewmemorylayerdialog.cpp
Expand Up @@ -22,6 +22,8 @@
#include "qgsproviderregistry.h"
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"
#include "qgsfield.h"
#include "qgsfields.h"
#include "qgssettings.h"
#include "qgsmemoryproviderutils.h"
#include "qgsgui.h"
Expand All @@ -41,8 +43,9 @@ QgsVectorLayer *QgsNewMemoryLayerDialog::runAndCreateLayer( QWidget *parent, con
}

QgsWkbTypes::Type geometrytype = dialog.selectedType();
QgsFields fields = dialog.fields();
QString name = dialog.layerName().isEmpty() ? tr( "New scratch layer" ) : dialog.layerName();
QgsVectorLayer *newLayer = QgsMemoryProviderUtils::createMemoryLayer( name, QgsFields(), geometrytype, dialog.crs() );
QgsVectorLayer *newLayer = QgsMemoryProviderUtils::createMemoryLayer( name, fields, geometrytype, dialog.crs() );
return newLayer;
}

Expand All @@ -52,22 +55,42 @@ QgsNewMemoryLayerDialog::QgsNewMemoryLayerDialog( QWidget *parent, Qt::WindowFla
setupUi( this );
QgsGui::enableAutoGeometryRestore( this );

mNameLineEdit->setText( tr( "New scratch layer" ) );

mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconTableLayer.svg" ) ), tr( "No geometry" ), QgsWkbTypes::NoGeometry );
mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPointLayer.svg" ) ), tr( "Point" ), QgsWkbTypes::Point );
mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "LineString / CompoundCurve" ), QgsWkbTypes::LineString );
mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ), tr( "Polygon / CurvePolygon" ), QgsWkbTypes::Polygon );
mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPointLayer.svg" ) ), tr( "MultiPoint" ), QgsWkbTypes::MultiPoint );
mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "MultiLineString / MultiCurve" ), QgsWkbTypes::MultiLineString );
mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ), tr( "MultiPolygon / MultiSurface" ), QgsWkbTypes::MultiPolygon );
mGeometryTypeBox->setCurrentIndex( -1 );

mGeometryWithZCheckBox->setEnabled( false );
mGeometryWithMCheckBox->setEnabled( false );
mCrsSelector->setEnabled( false );

mNameLineEdit->setText( tr( "New scratch layer" ) );
mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldText.svg" ) ), tr( "Text" ), "string" );
mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldInteger.svg" ) ), tr( "Whole number" ), "integer" );
mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldFloat.svg" ) ), tr( "Decimal number" ), "double" );
mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldBool.svg" ) ), tr( "Boolean" ), "bool" );
mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldDate.svg" ) ), tr( "Date" ), "date" );
mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldTime.svg" ) ), tr( "Time" ), "time" );
mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldDateTime.svg" ) ), tr( "Date & time" ), "datetime" );

mWidth->setValidator( new QIntValidator( 1, 255, this ) );
mPrecision->setValidator( new QIntValidator( 0, 15, this ) );

mOkButton = mButtonBox->button( QDialogButtonBox::Ok );
mOkButton->setEnabled( false );

connect( mGeometryTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewMemoryLayerDialog::geometryTypeChanged );
connect( mFieldNameEdit, &QLineEdit::textChanged, this, &QgsNewMemoryLayerDialog::fieldNameChanged );
connect( mAttributeView, &QTreeWidget::itemSelectionChanged, this, &QgsNewMemoryLayerDialog::selectionChanged );
connect( mAddAttributeButton, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::mAddAttributeButton_clicked );
connect( mRemoveAttributeButton, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked );
connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsNewMemoryLayerDialog::showHelp );
geometryTypeChanged( mGeometryTypeBox->currentIndex() );
//geometryTypeChanged( mGeometryTypeBox->currentIndex() );
}

QgsWkbTypes::Type QgsNewMemoryLayerDialog::selectedType() const
Expand Down Expand Up @@ -96,6 +119,9 @@ void QgsNewMemoryLayerDialog::geometryTypeChanged( int )
mGeometryWithZCheckBox->setEnabled( isSpatial );
mGeometryWithMCheckBox->setEnabled( isSpatial );
mCrsSelector->setEnabled( isSpatial );

bool ok = ( !mNameLineEdit->text().isEmpty() && mGeometryTypeBox->currentIndex() != -1 );
mOkButton->setEnabled( ok );
}

void QgsNewMemoryLayerDialog::setCrs( const QgsCoordinateReferenceSystem &crs )
Expand All @@ -113,6 +139,70 @@ QString QgsNewMemoryLayerDialog::layerName() const
return mNameLineEdit->text();
}

void QgsNewMemoryLayerDialog::fieldNameChanged( const QString &name )
{
mAddAttributeButton->setDisabled( name.isEmpty() || ! mAttributeView->findItems( name, Qt::MatchExactly ).isEmpty() );
}

void QgsNewMemoryLayerDialog::selectionChanged()
{
mRemoveAttributeButton->setDisabled( mAttributeView->selectedItems().isEmpty() );
}

QgsFields QgsNewMemoryLayerDialog::fields() const
{
QgsFields fields = QgsFields();

QTreeWidgetItemIterator it( mAttributeView );
while ( *it )
{
QString name( ( *it )->text( 0 ) );
QString typeName( ( *it )->text( 1 ) );
int width = ( *it )->text( 2 ).toInt();
int precision = ( *it )->text( 3 ).toInt();
QVariant::Type fieldType = QVariant::Invalid;
if ( typeName == QLatin1String( "string" ) )
fieldType = QVariant::String;
else if ( typeName == QLatin1String( "integer" ) )
fieldType = QVariant::Int;
else if ( typeName == QLatin1String( "double" ) )
fieldType = QVariant::Double;
else if ( typeName == QLatin1String( "bool" ) )
fieldType = QVariant::Bool;
else if ( typeName == QLatin1String( "date" ) )
fieldType = QVariant::Date;
else if ( typeName == QLatin1String( "time" ) )
fieldType = QVariant::Time;
else if ( typeName == QLatin1String( "datetime" ) )
fieldType = QVariant::DateTime;

QgsField field = QgsField( name, fieldType, typeName, width, precision );
fields.append( field );
++it;
}

return fields;
}

void QgsNewMemoryLayerDialog::mAddAttributeButton_clicked()
{
if ( !mFieldNameEdit->text().isEmpty() )
{
QString fieldName = mFieldNameEdit->text();
QString fieldType = mTypeBox->currentData( Qt::UserRole ).toString();
QString width = mWidth->text();
QString precision = mPrecision->text();
mAttributeView->addTopLevelItem( new QTreeWidgetItem( QStringList() << fieldName << fieldType << width << precision ) );

mFieldNameEdit->clear();
}
}

void QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked()
{
delete mAttributeView->currentItem();
}

void QgsNewMemoryLayerDialog::showHelp()
{
QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#creating-a-new-temporary-scratch-layer" ) );
Expand Down
12 changes: 12 additions & 0 deletions src/gui/qgsnewmemorylayerdialog.h
Expand Up @@ -23,6 +23,7 @@
#include "qgshelp.h"
#include "qgis_gui.h"

class QgsFields;
class QgsVectorLayer;

/**
Expand Down Expand Up @@ -67,13 +68,24 @@ class GUI_EXPORT QgsNewMemoryLayerDialog: public QDialog, private Ui::QgsNewMemo
//! Returns the layer name
QString layerName() const;

/**
* Returns attributes for the new layer.
* \since QGIS 3.14
*/
QgsFields fields() const;

private:

QString mCrsId;
QPushButton *mOkButton = nullptr;

private slots:

void geometryTypeChanged( int index );
void fieldNameChanged( const QString & );
void mAddAttributeButton_clicked();
void mRemoveAttributeButton_clicked();
void selectionChanged();
void showHelp();
};

Expand Down

0 comments on commit 3e63210

Please sign in to comment.