Skip to content

Commit 3e63210

Browse files
authoredMay 12, 2020
Merge pull request #36289 from alexbruy/scratch-attributes
allow adding attributes in the New Scratch Layer dialog (fix #24397)
2 parents 59e1dce + 95463e6 commit 3e63210

File tree

4 files changed

+317
-65
lines changed

4 files changed

+317
-65
lines changed
 

‎python/gui/auto_generated/qgsnewmemorylayerdialog.sip.in

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ Returns the selected CRS for the new layer.
5656
QString layerName() const;
5757
%Docstring
5858
Returns the layer name
59+
%End
60+
61+
QgsFields fields() const;
62+
%Docstring
63+
Returns attributes for the new layer.
64+
65+
.. versionadded:: 3.14
5966
%End
6067

6168
};

‎src/gui/qgsnewmemorylayerdialog.cpp

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "qgsproviderregistry.h"
2323
#include "qgsvectordataprovider.h"
2424
#include "qgsvectorlayer.h"
25+
#include "qgsfield.h"
26+
#include "qgsfields.h"
2527
#include "qgssettings.h"
2628
#include "qgsmemoryproviderutils.h"
2729
#include "qgsgui.h"
@@ -41,8 +43,9 @@ QgsVectorLayer *QgsNewMemoryLayerDialog::runAndCreateLayer( QWidget *parent, con
4143
}
4244

4345
QgsWkbTypes::Type geometrytype = dialog.selectedType();
46+
QgsFields fields = dialog.fields();
4447
QString name = dialog.layerName().isEmpty() ? tr( "New scratch layer" ) : dialog.layerName();
45-
QgsVectorLayer *newLayer = QgsMemoryProviderUtils::createMemoryLayer( name, QgsFields(), geometrytype, dialog.crs() );
48+
QgsVectorLayer *newLayer = QgsMemoryProviderUtils::createMemoryLayer( name, fields, geometrytype, dialog.crs() );
4649
return newLayer;
4750
}
4851

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

58+
mNameLineEdit->setText( tr( "New scratch layer" ) );
59+
5560
mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconTableLayer.svg" ) ), tr( "No geometry" ), QgsWkbTypes::NoGeometry );
5661
mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPointLayer.svg" ) ), tr( "Point" ), QgsWkbTypes::Point );
5762
mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "LineString / CompoundCurve" ), QgsWkbTypes::LineString );
5863
mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ), tr( "Polygon / CurvePolygon" ), QgsWkbTypes::Polygon );
5964
mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPointLayer.svg" ) ), tr( "MultiPoint" ), QgsWkbTypes::MultiPoint );
6065
mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "MultiLineString / MultiCurve" ), QgsWkbTypes::MultiLineString );
6166
mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ), tr( "MultiPolygon / MultiSurface" ), QgsWkbTypes::MultiPolygon );
67+
mGeometryTypeBox->setCurrentIndex( -1 );
6268

6369
mGeometryWithZCheckBox->setEnabled( false );
6470
mGeometryWithMCheckBox->setEnabled( false );
71+
mCrsSelector->setEnabled( false );
6572

66-
mNameLineEdit->setText( tr( "New scratch layer" ) );
73+
mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldText.svg" ) ), tr( "Text" ), "string" );
74+
mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldInteger.svg" ) ), tr( "Whole number" ), "integer" );
75+
mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldFloat.svg" ) ), tr( "Decimal number" ), "double" );
76+
mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldBool.svg" ) ), tr( "Boolean" ), "bool" );
77+
mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldDate.svg" ) ), tr( "Date" ), "date" );
78+
mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldTime.svg" ) ), tr( "Time" ), "time" );
79+
mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldDateTime.svg" ) ), tr( "Date & time" ), "datetime" );
80+
81+
mWidth->setValidator( new QIntValidator( 1, 255, this ) );
82+
mPrecision->setValidator( new QIntValidator( 0, 15, this ) );
83+
84+
mOkButton = mButtonBox->button( QDialogButtonBox::Ok );
85+
mOkButton->setEnabled( false );
6786

6887
connect( mGeometryTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewMemoryLayerDialog::geometryTypeChanged );
88+
connect( mFieldNameEdit, &QLineEdit::textChanged, this, &QgsNewMemoryLayerDialog::fieldNameChanged );
89+
connect( mAttributeView, &QTreeWidget::itemSelectionChanged, this, &QgsNewMemoryLayerDialog::selectionChanged );
90+
connect( mAddAttributeButton, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::mAddAttributeButton_clicked );
91+
connect( mRemoveAttributeButton, &QToolButton::clicked, this, &QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked );
6992
connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsNewMemoryLayerDialog::showHelp );
70-
geometryTypeChanged( mGeometryTypeBox->currentIndex() );
93+
//geometryTypeChanged( mGeometryTypeBox->currentIndex() );
7194
}
7295

7396
QgsWkbTypes::Type QgsNewMemoryLayerDialog::selectedType() const
@@ -96,6 +119,9 @@ void QgsNewMemoryLayerDialog::geometryTypeChanged( int )
96119
mGeometryWithZCheckBox->setEnabled( isSpatial );
97120
mGeometryWithMCheckBox->setEnabled( isSpatial );
98121
mCrsSelector->setEnabled( isSpatial );
122+
123+
bool ok = ( !mNameLineEdit->text().isEmpty() && mGeometryTypeBox->currentIndex() != -1 );
124+
mOkButton->setEnabled( ok );
99125
}
100126

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

142+
void QgsNewMemoryLayerDialog::fieldNameChanged( const QString &name )
143+
{
144+
mAddAttributeButton->setDisabled( name.isEmpty() || ! mAttributeView->findItems( name, Qt::MatchExactly ).isEmpty() );
145+
}
146+
147+
void QgsNewMemoryLayerDialog::selectionChanged()
148+
{
149+
mRemoveAttributeButton->setDisabled( mAttributeView->selectedItems().isEmpty() );
150+
}
151+
152+
QgsFields QgsNewMemoryLayerDialog::fields() const
153+
{
154+
QgsFields fields = QgsFields();
155+
156+
QTreeWidgetItemIterator it( mAttributeView );
157+
while ( *it )
158+
{
159+
QString name( ( *it )->text( 0 ) );
160+
QString typeName( ( *it )->text( 1 ) );
161+
int width = ( *it )->text( 2 ).toInt();
162+
int precision = ( *it )->text( 3 ).toInt();
163+
QVariant::Type fieldType = QVariant::Invalid;
164+
if ( typeName == QLatin1String( "string" ) )
165+
fieldType = QVariant::String;
166+
else if ( typeName == QLatin1String( "integer" ) )
167+
fieldType = QVariant::Int;
168+
else if ( typeName == QLatin1String( "double" ) )
169+
fieldType = QVariant::Double;
170+
else if ( typeName == QLatin1String( "bool" ) )
171+
fieldType = QVariant::Bool;
172+
else if ( typeName == QLatin1String( "date" ) )
173+
fieldType = QVariant::Date;
174+
else if ( typeName == QLatin1String( "time" ) )
175+
fieldType = QVariant::Time;
176+
else if ( typeName == QLatin1String( "datetime" ) )
177+
fieldType = QVariant::DateTime;
178+
179+
QgsField field = QgsField( name, fieldType, typeName, width, precision );
180+
fields.append( field );
181+
++it;
182+
}
183+
184+
return fields;
185+
}
186+
187+
void QgsNewMemoryLayerDialog::mAddAttributeButton_clicked()
188+
{
189+
if ( !mFieldNameEdit->text().isEmpty() )
190+
{
191+
QString fieldName = mFieldNameEdit->text();
192+
QString fieldType = mTypeBox->currentData( Qt::UserRole ).toString();
193+
QString width = mWidth->text();
194+
QString precision = mPrecision->text();
195+
mAttributeView->addTopLevelItem( new QTreeWidgetItem( QStringList() << fieldName << fieldType << width << precision ) );
196+
197+
mFieldNameEdit->clear();
198+
}
199+
}
200+
201+
void QgsNewMemoryLayerDialog::mRemoveAttributeButton_clicked()
202+
{
203+
delete mAttributeView->currentItem();
204+
}
205+
116206
void QgsNewMemoryLayerDialog::showHelp()
117207
{
118208
QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#creating-a-new-temporary-scratch-layer" ) );

‎src/gui/qgsnewmemorylayerdialog.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "qgshelp.h"
2424
#include "qgis_gui.h"
2525

26+
class QgsFields;
2627
class QgsVectorLayer;
2728

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

71+
/**
72+
* Returns attributes for the new layer.
73+
* \since QGIS 3.14
74+
*/
75+
QgsFields fields() const;
76+
7077
private:
7178

7279
QString mCrsId;
80+
QPushButton *mOkButton = nullptr;
7381

7482
private slots:
7583

7684
void geometryTypeChanged( int index );
85+
void fieldNameChanged( const QString & );
86+
void mAddAttributeButton_clicked();
87+
void mRemoveAttributeButton_clicked();
88+
void selectionChanged();
7789
void showHelp();
7890
};
7991

‎src/ui/qgsnewmemorylayerdialogbase.ui

Lines changed: 205 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<x>0</x>
88
<y>0</y>
99
<width>444</width>
10-
<height>246</height>
10+
<height>596</height>
1111
</rect>
1212
</property>
1313
<property name="sizePolicy">
@@ -22,53 +22,194 @@
2222
<property name="modal">
2323
<bool>true</bool>
2424
</property>
25-
<layout class="QVBoxLayout" name="verticalLayout">
26-
<item>
27-
<layout class="QGridLayout" name="gridLayout">
28-
<item row="2" column="2">
29-
<widget class="QCheckBox" name="mGeometryWithMCheckBox">
30-
<property name="text">
31-
<string>Include M values</string>
32-
</property>
33-
</widget>
34-
</item>
35-
<item row="1" column="0">
36-
<widget class="QLabel" name="label_3">
37-
<property name="text">
38-
<string>Geometry type</string>
39-
</property>
40-
</widget>
41-
</item>
42-
<item row="0" column="0">
43-
<widget class="QLabel" name="label">
44-
<property name="text">
45-
<string>Layer name</string>
46-
</property>
47-
</widget>
48-
</item>
49-
<item row="2" column="1">
50-
<widget class="QCheckBox" name="mGeometryWithZCheckBox">
51-
<property name="text">
52-
<string>Include Z dimension</string>
53-
</property>
54-
</widget>
55-
</item>
56-
<item row="1" column="1" colspan="2">
57-
<widget class="QComboBox" name="mGeometryTypeBox"/>
58-
</item>
59-
<item row="0" column="1" colspan="2">
60-
<widget class="QLineEdit" name="mNameLineEdit"/>
61-
</item>
62-
<item row="3" column="1" colspan="2">
63-
<widget class="QgsProjectionSelectionWidget" name="mCrsSelector" native="true">
64-
<property name="focusPolicy">
65-
<enum>Qt::StrongFocus</enum>
66-
</property>
67-
</widget>
68-
</item>
69-
</layout>
25+
<layout class="QGridLayout" name="gridLayout">
26+
<item row="0" column="0">
27+
<widget class="QLabel" name="label">
28+
<property name="text">
29+
<string>Layer name</string>
30+
</property>
31+
</widget>
32+
</item>
33+
<item row="1" column="0">
34+
<widget class="QLabel" name="label_3">
35+
<property name="text">
36+
<string>Geometry type</string>
37+
</property>
38+
</widget>
39+
</item>
40+
<item row="2" column="1">
41+
<widget class="QCheckBox" name="mGeometryWithZCheckBox">
42+
<property name="text">
43+
<string>Include Z dimension</string>
44+
</property>
45+
</widget>
46+
</item>
47+
<item row="2" column="2">
48+
<widget class="QCheckBox" name="mGeometryWithMCheckBox">
49+
<property name="text">
50+
<string>Include M values</string>
51+
</property>
52+
</widget>
7053
</item>
71-
<item>
54+
<item row="4" column="0" colspan="3">
55+
<widget class="QGroupBox" name="groupBox">
56+
<property name="title">
57+
<string>New Field</string>
58+
</property>
59+
<layout class="QGridLayout" name="_2">
60+
<item row="0" column="0">
61+
<widget class="QLabel" name="textLabel1">
62+
<property name="text">
63+
<string>Name</string>
64+
</property>
65+
<property name="buddy">
66+
<cstring>mFieldNameEdit</cstring>
67+
</property>
68+
</widget>
69+
</item>
70+
<item row="0" column="1" colspan="4">
71+
<widget class="QLineEdit" name="mFieldNameEdit"/>
72+
</item>
73+
<item row="1" column="0">
74+
<widget class="QLabel" name="textLabel2">
75+
<property name="text">
76+
<string>Type</string>
77+
</property>
78+
<property name="buddy">
79+
<cstring>mTypeBox</cstring>
80+
</property>
81+
</widget>
82+
</item>
83+
<item row="1" column="1" colspan="4">
84+
<widget class="QComboBox" name="mTypeBox"/>
85+
</item>
86+
<item row="2" column="0">
87+
<widget class="QLabel" name="label_4">
88+
<property name="text">
89+
<string>Length</string>
90+
</property>
91+
<property name="buddy">
92+
<cstring>mWidth</cstring>
93+
</property>
94+
</widget>
95+
</item>
96+
<item row="2" column="1" colspan="2">
97+
<widget class="QLineEdit" name="mWidth"/>
98+
</item>
99+
<item row="2" column="3">
100+
<widget class="QLabel" name="label_5">
101+
<property name="text">
102+
<string>Precision</string>
103+
</property>
104+
<property name="buddy">
105+
<cstring>mPrecision</cstring>
106+
</property>
107+
</widget>
108+
</item>
109+
<item row="2" column="4">
110+
<widget class="QLineEdit" name="mPrecision"/>
111+
</item>
112+
<item row="4" column="4">
113+
<widget class="QToolButton" name="mAddAttributeButton">
114+
<property name="sizePolicy">
115+
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
116+
<horstretch>0</horstretch>
117+
<verstretch>0</verstretch>
118+
</sizepolicy>
119+
</property>
120+
<property name="toolTip">
121+
<string>Add field to list</string>
122+
</property>
123+
<property name="layoutDirection">
124+
<enum>Qt::LeftToRight</enum>
125+
</property>
126+
<property name="text">
127+
<string>Add to Fields List</string>
128+
</property>
129+
<property name="icon">
130+
<iconset resource="../../images/images.qrc">
131+
<normaloff>:/images/themes/default/mActionNewAttribute.svg</normaloff>:/images/themes/default/mActionNewAttribute.svg</iconset>
132+
</property>
133+
<property name="toolButtonStyle">
134+
<enum>Qt::ToolButtonTextBesideIcon</enum>
135+
</property>
136+
</widget>
137+
</item>
138+
</layout>
139+
</widget>
140+
</item>
141+
<item row="5" column="0" colspan="3">
142+
<widget class="QGroupBox" name="groupBox_2">
143+
<property name="title">
144+
<string>Fields List</string>
145+
</property>
146+
<layout class="QGridLayout" name="_3">
147+
<item row="2" column="0" colspan="3">
148+
<widget class="QTreeWidget" name="mAttributeView">
149+
<property name="sizePolicy">
150+
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
151+
<horstretch>0</horstretch>
152+
<verstretch>0</verstretch>
153+
</sizepolicy>
154+
</property>
155+
<property name="alternatingRowColors">
156+
<bool>true</bool>
157+
</property>
158+
<property name="rootIsDecorated">
159+
<bool>false</bool>
160+
</property>
161+
<property name="columnCount">
162+
<number>4</number>
163+
</property>
164+
<column>
165+
<property name="text">
166+
<string>Name</string>
167+
</property>
168+
</column>
169+
<column>
170+
<property name="text">
171+
<string>Type</string>
172+
</property>
173+
</column>
174+
<column>
175+
<property name="text">
176+
<string>Length</string>
177+
</property>
178+
</column>
179+
<column>
180+
<property name="text">
181+
<string>Precision</string>
182+
</property>
183+
</column>
184+
</widget>
185+
</item>
186+
<item row="3" column="2">
187+
<widget class="QToolButton" name="mRemoveAttributeButton">
188+
<property name="sizePolicy">
189+
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
190+
<horstretch>0</horstretch>
191+
<verstretch>0</verstretch>
192+
</sizepolicy>
193+
</property>
194+
<property name="toolTip">
195+
<string>Delete selected field</string>
196+
</property>
197+
<property name="text">
198+
<string>Remove Field</string>
199+
</property>
200+
<property name="icon">
201+
<iconset resource="../../images/images.qrc">
202+
<normaloff>:/images/themes/default/mActionDeleteAttribute.svg</normaloff>:/images/themes/default/mActionDeleteAttribute.svg</iconset>
203+
</property>
204+
<property name="toolButtonStyle">
205+
<enum>Qt::ToolButtonTextBesideIcon</enum>
206+
</property>
207+
</widget>
208+
</item>
209+
</layout>
210+
</widget>
211+
</item>
212+
<item row="6" column="0" colspan="3">
72213
<widget class="QLabel" name="label_2">
73214
<property name="text">
74215
<string>&lt;i&gt;&lt;b&gt;Warning:&lt;/b&gt; Temporary scratch layers are not saved and will be discarded when QGIS is closed.&lt;/i&gt;</string>
@@ -81,20 +222,7 @@
81222
</property>
82223
</widget>
83224
</item>
84-
<item>
85-
<spacer name="verticalSpacer">
86-
<property name="orientation">
87-
<enum>Qt::Vertical</enum>
88-
</property>
89-
<property name="sizeHint" stdset="0">
90-
<size>
91-
<width>20</width>
92-
<height>40</height>
93-
</size>
94-
</property>
95-
</spacer>
96-
</item>
97-
<item>
225+
<item row="7" column="0" colspan="3">
98226
<widget class="QDialogButtonBox" name="mButtonBox">
99227
<property name="orientation">
100228
<enum>Qt::Horizontal</enum>
@@ -104,6 +232,19 @@
104232
</property>
105233
</widget>
106234
</item>
235+
<item row="3" column="0" colspan="3">
236+
<widget class="QgsProjectionSelectionWidget" name="mCrsSelector" native="true">
237+
<property name="focusPolicy">
238+
<enum>Qt::StrongFocus</enum>
239+
</property>
240+
</widget>
241+
</item>
242+
<item row="1" column="1" colspan="2">
243+
<widget class="QComboBox" name="mGeometryTypeBox"/>
244+
</item>
245+
<item row="0" column="1" colspan="2">
246+
<widget class="QLineEdit" name="mNameLineEdit"/>
247+
</item>
107248
</layout>
108249
</widget>
109250
<layoutdefault spacing="6" margin="11"/>
@@ -122,7 +263,9 @@
122263
<tabstop>mGeometryWithMCheckBox</tabstop>
123264
<tabstop>mCrsSelector</tabstop>
124265
</tabstops>
125-
<resources/>
266+
<resources>
267+
<include location="../../images/images.qrc"/>
268+
</resources>
126269
<connections>
127270
<connection>
128271
<sender>mButtonBox</sender>

0 commit comments

Comments
 (0)
Please sign in to comment.