Skip to content

Commit bed164e

Browse files
committed
Allow usage of virtual fields also for layer w/o add attribute support
Fix #11168
1 parent 7318c73 commit bed164e

9 files changed

+172
-62
lines changed

src/app/qgsaddattrdialog.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "qgsexpressionbuilderdialog.h"
2323

2424
#include <QMessageBox>
25+
#include <QLabel>
2526

2627
QgsAddAttrDialog::QgsAddAttrDialog( QgsVectorLayer *vlayer, QWidget *parent, Qt::WindowFlags fl )
2728
: QDialog( parent, fl )
@@ -58,6 +59,12 @@ QgsAddAttrDialog::QgsAddAttrDialog( QgsVectorLayer *vlayer, QWidget *parent, Qt:
5859
mNameEdit->setMaxLength( 10 );
5960

6061
mExpressionWidget->setLayer( vlayer );
62+
63+
int cap = mLayer->dataProvider()->capabilities();
64+
65+
mButtonProviderField->setEnabled( cap & QgsVectorDataProvider::AddAttributes );
66+
67+
mInfoIcon->setPixmap( style()->standardPixmap( QStyle::SP_MessageBoxInformation ) );
6168
}
6269

6370
void QgsAddAttrDialog::on_mTypeBox_currentIndexChanged( int idx )
@@ -87,6 +94,8 @@ void QgsAddAttrDialog::on_mFieldModeButtonGroup_buttonClicked( QAbstractButton*
8794
mExpressionWidget->show();
8895
mExpressionLabel->show();
8996
}
97+
98+
mLayerEditableInfo->setVisible( !mLayer->isEditable() && button == mButtonProviderField );
9099
}
91100

92101
void QgsAddAttrDialog::on_mLength_editingFinished()
@@ -125,6 +134,12 @@ void QgsAddAttrDialog::accept()
125134
tr( "No expression specified. Please enter an expression that will be used to calculate the field values." ) );
126135
return;
127136
}
137+
138+
if ( !mLayer->isEditable() && mode() == ProviderField )
139+
{
140+
mLayer->startEditing();
141+
}
142+
128143
QDialog::accept();
129144
}
130145

src/app/qgsaddattrdialog.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ class APP_EXPORT QgsAddAttrDialog: public QDialog, private Ui::QgsAddAttrDialogB
3636

3737
QgsAddAttrDialog( QgsVectorLayer *vlayer,
3838
QWidget *parent = 0, Qt::WindowFlags fl = QgisGui::ModalDialogFlags );
39-
QgsAddAttrDialog( const std::list<QString>& typelist,
40-
QWidget *parent = 0, Qt::WindowFlags fl = QgisGui::ModalDialogFlags );
4139

4240
QgsField field() const;
4341
const QString expression() const;

src/app/qgsattributetabledialog.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,6 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWid
174174
mSaveEditsButton->setEnabled( mToggleEditingButton->isEnabled() && mLayer->isEditable() );
175175
mOpenFieldCalculator->setEnabled(( canChangeAttributes || canAddAttributes ) && mLayer->isEditable() );
176176
mDeleteSelectedButton->setEnabled( canDeleteFeatures && mLayer->isEditable() );
177-
mAddAttribute->setEnabled( canAddAttributes && mLayer->isEditable() );
178-
mRemoveAttribute->setEnabled( canDeleteAttributes && mLayer->isEditable() );
179177
mAddFeature->setEnabled( canAddFeatures && mLayer->isEditable() && mLayer->geometryType() == QGis::NoGeometry );
180178
mAddFeature->setHidden( !canAddFeatures || mLayer->geometryType() != QGis::NoGeometry );
181179

@@ -559,12 +557,9 @@ void QgsAttributeTableDialog::editingToggled()
559557
bool canChangeAttributes = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues;
560558
bool canDeleteFeatures = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::DeleteFeatures;
561559
bool canAddAttributes = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::AddAttributes;
562-
bool canDeleteAttributes = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::DeleteAttributes;
563560
bool canAddFeatures = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::AddFeatures;
564561
mOpenFieldCalculator->setEnabled(( canChangeAttributes || canAddAttributes ) && mLayer->isEditable() );
565562
mDeleteSelectedButton->setEnabled( canDeleteFeatures && mLayer->isEditable() );
566-
mAddAttribute->setEnabled( canAddAttributes && mLayer->isEditable() );
567-
mRemoveAttribute->setEnabled( canDeleteAttributes && mLayer->isEditable() );
568563
mAddFeature->setEnabled( canAddFeatures && mLayer->isEditable() && mLayer->geometryType() == QGis::NoGeometry );
569564

570565
mUpdateExpressionBox->setVisible( mLayer->isEditable() );
@@ -597,8 +592,8 @@ void QgsAttributeTableDialog::on_mAddAttribute_clicked()
597592
}
598593
else
599594
{
600-
QMessageBox::critical( 0, tr( "Attribute Error" ), tr( "The attribute could not be added to the layer" ) );
601595
mLayer->destroyEditCommand();
596+
QMessageBox::critical( this, tr( "Failed to add field" ), tr( "Failed to add field '%1' of type '%2'. Is the field name unique?" ).arg( dialog.field().name() ).arg( dialog.field().typeName() ) );
602597
}
603598
}
604599

src/app/qgsdelattrdialog.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,49 @@
1515
* *
1616
***************************************************************************/
1717

18+
#include "qgsapplication.h"
1819
#include "qgsdelattrdialog.h"
1920
#include "qgsfield.h"
21+
#include "qgsvectordataprovider.h"
2022
#include "qgsvectorlayer.h"
2123

2224
#include <QSettings>
2325

24-
QgsDelAttrDialog::QgsDelAttrDialog( const QgsVectorLayer* vl ): QDialog()
26+
QgsDelAttrDialog::QgsDelAttrDialog( const QgsVectorLayer* vl )
27+
: QDialog()
2528
{
2629
setupUi( this );
2730
if ( vl )
2831
{
32+
bool canDeleteAttributes = vl->dataProvider()->capabilities() & QgsVectorDataProvider::DeleteAttributes;
2933
listBox2->clear();
3034
const QgsFields& layerAttributes = vl->pendingFields();
3135
for ( int idx = 0; idx < layerAttributes.count(); ++idx )
3236
{
3337
QListWidgetItem* item = new QListWidgetItem( layerAttributes[idx].name(), listBox2 );
38+
switch ( vl->pendingFields().fieldOrigin( idx ) )
39+
{
40+
case QgsFields::OriginExpression:
41+
item->setIcon( QgsApplication::getThemeIcon( "/mIconExpression.svg" ) );
42+
break;
43+
44+
case QgsFields::OriginJoin:
45+
item->setIcon( QgsApplication::getThemeIcon( "/propertyicons/join.png" ) );
46+
item->setFlags( item->flags() & ~Qt::ItemIsEnabled );
47+
break;
48+
49+
default:
50+
item->setIcon( QgsApplication::getThemeIcon( "/propertyicons/attributes.png" ) );
51+
if ( !vl->isEditable() || !canDeleteAttributes )
52+
item->setFlags( item->flags() & ~Qt::ItemIsEnabled );
53+
break;
54+
}
55+
3456
item->setData( Qt::UserRole, idx );
3557
}
58+
59+
mEditModeInfo->setVisible( !vl->isEditable() );
60+
mCanDeleteAttributesInfo->setVisible( !canDeleteAttributes );
3661
}
3762

3863
QSettings settings;

src/app/qgsfieldsproperties.cpp

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ void QgsFieldsProperties::onAttributeSelectionChanged()
140140
if ( mDesignerTree->selectedItems()[0]->data( 0, DesignerTreeRole ).value<DesignerTreeItemData>().type() == DesignerTreeItemData::Container )
141141
isAddPossible = true;
142142
mAddItemButton->setEnabled( isAddPossible );
143+
144+
updateButtons();
143145
}
144146

145147
QTreeWidgetItem *QgsFieldsProperties::loadAttributeEditorTreeItem( QgsAttributeEditorElement* const widgetDef, QTreeWidgetItem* parent )
@@ -161,7 +163,7 @@ QTreeWidgetItem *QgsFieldsProperties::loadAttributeEditorTreeItem( QgsAttributeE
161163

162164
const QgsAttributeEditorContainer* container = dynamic_cast<const QgsAttributeEditorContainer*>( widgetDef );
163165

164-
Q_FOREACH ( QgsAttributeEditorElement* wdg, container->children() )
166+
Q_FOREACH( QgsAttributeEditorElement* wdg, container->children() )
165167
{
166168
loadAttributeEditorTreeItem( wdg, newWidget );
167169
}
@@ -185,7 +187,7 @@ void QgsFieldsProperties::loadAttributeEditorTree()
185187
mDesignerTree->setAcceptDrops( true );
186188
mDesignerTree->setDragDropMode( QAbstractItemView::DragDrop );
187189

188-
Q_FOREACH ( QgsAttributeEditorElement* wdg, mLayer->attributeEditorElements() )
190+
Q_FOREACH( QgsAttributeEditorElement* wdg, mLayer->attributeEditorElements() )
189191
{
190192
loadAttributeEditorTreeItem( wdg, mDesignerTree->invisibleRootItem() );
191193
}
@@ -270,7 +272,7 @@ void QgsFieldsProperties::loadRelations()
270272

271273
int idx = 0;
272274

273-
Q_FOREACH ( const QgsRelation& relation, relations )
275+
Q_FOREACH( const QgsRelation& relation, relations )
274276
{
275277
mRelationsList->insertRow( idx );
276278

@@ -308,7 +310,7 @@ void QgsFieldsProperties::on_mAddItemButton_clicked()
308310
if ( parent->data( 0, DesignerTreeRole ).value<DesignerTreeItemData>().type() != DesignerTreeItemData::Container )
309311
return;
310312

311-
Q_FOREACH ( QTableWidgetItem* item, listItems )
313+
Q_FOREACH( QTableWidgetItem* item, listItems )
312314
{
313315
if ( item->column() == 0 ) // Information is in the first column
314316
mDesignerTree->addItem( parent , item->data( DesignerTreeRole ).value<DesignerTreeItemData>() );
@@ -407,7 +409,7 @@ void QgsFieldsProperties::attributeTypeDialog()
407409
int index = -1;
408410
int row = -1;
409411

410-
Q_FOREACH ( QTableWidgetItem* wdg, mIndexedWidgets )
412+
Q_FOREACH( QTableWidgetItem* wdg, mIndexedWidgets )
411413
{
412414
cfg = wdg->data( FieldConfigRole ).value<FieldConfig>();
413415
if ( cfg.mButton == pb )
@@ -486,6 +488,7 @@ bool QgsFieldsProperties::addAttribute( const QgsField &field )
486488
else
487489
{
488490
mLayer->destroyEditCommand();
491+
QMessageBox::critical( this, tr( "Failed to add field" ), tr( "Failed to add field '%1' of type '%2'. Is the field name unique?" ).arg( field.name() ).arg( field.typeName() ) );
489492
return false;
490493
}
491494
}
@@ -536,34 +539,38 @@ void QgsFieldsProperties::on_mAddAttributeButton_clicked()
536539
}
537540
else
538541
{
539-
mLayer->beginEditCommand( "Attribute added" );
540-
if ( !addAttribute( dialog.field() ) )
541-
{
542-
mLayer->destroyEditCommand();
543-
QMessageBox::information( this, tr( "Name conflict" ), tr( "The attribute could not be inserted. The name already exists in the table." ) );
544-
}
545-
else
546-
{
547-
mLayer->endEditCommand();
548-
}
542+
addAttribute( dialog.field() );
549543
}
550544
}
551545
}
552546

553547
void QgsFieldsProperties::on_mDeleteAttributeButton_clicked()
554548
{
555-
QSet<int> attrs;
556-
foreach ( QTableWidgetItem* item, mFieldsList->selectedItems() )
549+
QSet<int> providerFields;
550+
QSet<int> expressionFields;
551+
Q_FOREACH( QTableWidgetItem* item, mFieldsList->selectedItems() )
557552
{
558553
if ( item->column() == 0 )
559554
{
560-
attrs << mIndexedWidgets.indexOf( item );
555+
int idx = mIndexedWidgets.indexOf( item );
556+
if ( mLayer->pendingFields().fieldOrigin( idx ) == QgsFields::OriginExpression )
557+
expressionFields << idx;
558+
else
559+
providerFields << idx;
561560
}
562561
}
563562

564-
mLayer->beginEditCommand( tr( "Deleted attribute" ) );
565-
mLayer->deleteAttributes( attrs.toList() );
566-
mLayer->endEditCommand();
563+
if ( expressionFields.count() )
564+
mLayer->deleteAttributes( expressionFields.toList() );
565+
566+
if ( providerFields.count() )
567+
{
568+
mLayer->beginEditCommand( tr( "Deleted attributes" ) );
569+
if ( mLayer->deleteAttributes( providerFields.toList() ) )
570+
mLayer->endEditCommand();
571+
else
572+
mLayer->destroyEditCommand();
573+
}
567574
}
568575

569576
void QgsFieldsProperties::updateButtons()
@@ -574,17 +581,31 @@ void QgsFieldsProperties::updateButtons()
574581

575582
if ( mLayer->isEditable() )
576583
{
577-
mAddAttributeButton->setEnabled( cap & QgsVectorDataProvider::AddAttributes );
578584
mDeleteAttributeButton->setEnabled( cap & QgsVectorDataProvider::DeleteAttributes );
579585
mCalculateFieldButton->setEnabled( cap & ( QgsVectorDataProvider::ChangeAttributeValues | QgsVectorDataProvider::AddAttributes ) );
580586
mToggleEditingButton->setChecked( true );
581587
}
582588
else
583589
{
584-
mAddAttributeButton->setEnabled( false );
585-
mDeleteAttributeButton->setEnabled( false );
586590
mToggleEditingButton->setChecked( false );
587591
mCalculateFieldButton->setEnabled( false );
592+
593+
// Enable delete button if items are selected
594+
mDeleteAttributeButton->setEnabled( mFieldsList->selectedItems().count() > 0 );
595+
596+
// and only if all selected items have their origin in an expression
597+
Q_FOREACH( QTableWidgetItem* item, mFieldsList->selectedItems() )
598+
{
599+
if ( item->column() == 0 )
600+
{
601+
int idx = mIndexedWidgets.indexOf( item );
602+
if ( mLayer->pendingFields().fieldOrigin( idx ) != QgsFields::OriginExpression )
603+
{
604+
mDeleteAttributeButton->setEnabled( false );
605+
break;
606+
}
607+
}
608+
}
588609
}
589610
}
590611

@@ -826,7 +847,7 @@ QMimeData* QgsFieldsProperties::DragList::mimeData( const QList<QTableWidgetItem
826847
QByteArray encoded;
827848
QDataStream stream( &encoded, QIODevice::WriteOnly );
828849

829-
Q_FOREACH ( const QTableWidgetItem* item, items )
850+
Q_FOREACH( const QTableWidgetItem* item, items )
830851
{
831852
// Relevant information is always in the UserRole of the first column
832853
if ( item && item->column() == 0 )
@@ -996,7 +1017,7 @@ QMimeData* QgsFieldsProperties::DesignerTree::mimeData( const QList<QTreeWidgetI
9961017
QByteArray encoded;
9971018
QDataStream stream( &encoded, QIODevice::WriteOnly );
9981019

999-
Q_FOREACH ( const QTreeWidgetItem* item, items )
1020+
Q_FOREACH( const QTreeWidgetItem* item, items )
10001021
{
10011022
if ( item )
10021023
{

src/app/qgsfieldsproperties.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@ class APP_EXPORT QgsFieldsProperties : public QWidget, private Ui_QgsFieldsPrope
150150
void init();
151151
void apply();
152152

153-
void updateButtons();
154153
void loadRows();
155154
void setRow( int row, int idx, const QgsField &field );
156155

@@ -162,7 +161,7 @@ class APP_EXPORT QgsFieldsProperties : public QWidget, private Ui_QgsFieldsPrope
162161
signals:
163162
void toggleEditing();
164163

165-
public slots:
164+
private slots:
166165
void on_mAddAttributeButton_clicked();
167166
void on_mDeleteAttributeButton_clicked();
168167
void on_mCalculateFieldButton_clicked();
@@ -182,11 +181,13 @@ class APP_EXPORT QgsFieldsProperties : public QWidget, private Ui_QgsFieldsPrope
182181

183182
void attributesListCellChanged( int row, int column );
184183

185-
protected slots:
184+
186185
/** editing of layer was toggled */
187186
void editingToggled();
188187

189188
protected:
189+
void updateButtons();
190+
190191
FieldConfig configForRow( int row );
191192
void setConfigForRow( int row, FieldConfig cfg );
192193

src/core/qgsvectorlayer.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2119,6 +2119,12 @@ QString QgsVectorLayer::attributeDisplayName( int attributeIndex ) const
21192119

21202120
bool QgsVectorLayer::deleteAttribute( int index )
21212121
{
2122+
if ( mUpdatedFields.fieldOrigin( index ) == QgsFields::OriginExpression )
2123+
{
2124+
removeExpressionField( index );
2125+
return true;
2126+
}
2127+
21222128
if ( !mEditBuffer || !mDataProvider )
21232129
return false;
21242130

@@ -2134,7 +2140,7 @@ bool QgsVectorLayer::deleteAttributes( QList<int> attrs )
21342140

21352141
qSort( attrs.begin(), attrs.end(), qGreater<int>() );
21362142

2137-
foreach ( int attr, attrs )
2143+
Q_FOREACH( int attr, attrs )
21382144
{
21392145
if ( deleteAttribute( attr ) )
21402146
{

0 commit comments

Comments
 (0)