Skip to content
Permalink
Browse files
Allow usage of virtual fields also for layer w/o add attribute support
Fix #11168
  • Loading branch information
m-kuhn committed Oct 6, 2014
1 parent 7318c73 commit bed164e70c4405de7f6b729159b476244835c15f
@@ -22,6 +22,7 @@
#include "qgsexpressionbuilderdialog.h"

#include <QMessageBox>
#include <QLabel>

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

mExpressionWidget->setLayer( vlayer );

int cap = mLayer->dataProvider()->capabilities();

mButtonProviderField->setEnabled( cap & QgsVectorDataProvider::AddAttributes );

mInfoIcon->setPixmap( style()->standardPixmap( QStyle::SP_MessageBoxInformation ) );
}

void QgsAddAttrDialog::on_mTypeBox_currentIndexChanged( int idx )
@@ -87,6 +94,8 @@ void QgsAddAttrDialog::on_mFieldModeButtonGroup_buttonClicked( QAbstractButton*
mExpressionWidget->show();
mExpressionLabel->show();
}

mLayerEditableInfo->setVisible( !mLayer->isEditable() && button == mButtonProviderField );
}

void QgsAddAttrDialog::on_mLength_editingFinished()
@@ -125,6 +134,12 @@ void QgsAddAttrDialog::accept()
tr( "No expression specified. Please enter an expression that will be used to calculate the field values." ) );
return;
}

if ( !mLayer->isEditable() && mode() == ProviderField )
{
mLayer->startEditing();
}

QDialog::accept();
}

@@ -36,8 +36,6 @@ class APP_EXPORT QgsAddAttrDialog: public QDialog, private Ui::QgsAddAttrDialogB

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

QgsField field() const;
const QString expression() const;
@@ -174,8 +174,6 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWid
mSaveEditsButton->setEnabled( mToggleEditingButton->isEnabled() && mLayer->isEditable() );
mOpenFieldCalculator->setEnabled(( canChangeAttributes || canAddAttributes ) && mLayer->isEditable() );
mDeleteSelectedButton->setEnabled( canDeleteFeatures && mLayer->isEditable() );
mAddAttribute->setEnabled( canAddAttributes && mLayer->isEditable() );
mRemoveAttribute->setEnabled( canDeleteAttributes && mLayer->isEditable() );
mAddFeature->setEnabled( canAddFeatures && mLayer->isEditable() && mLayer->geometryType() == QGis::NoGeometry );
mAddFeature->setHidden( !canAddFeatures || mLayer->geometryType() != QGis::NoGeometry );

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

mUpdateExpressionBox->setVisible( mLayer->isEditable() );
@@ -597,8 +592,8 @@ void QgsAttributeTableDialog::on_mAddAttribute_clicked()
}
else
{
QMessageBox::critical( 0, tr( "Attribute Error" ), tr( "The attribute could not be added to the layer" ) );
mLayer->destroyEditCommand();
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() ) );
}
}

@@ -15,24 +15,49 @@
* *
***************************************************************************/

#include "qgsapplication.h"
#include "qgsdelattrdialog.h"
#include "qgsfield.h"
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"

#include <QSettings>

QgsDelAttrDialog::QgsDelAttrDialog( const QgsVectorLayer* vl ): QDialog()
QgsDelAttrDialog::QgsDelAttrDialog( const QgsVectorLayer* vl )
: QDialog()
{
setupUi( this );
if ( vl )
{
bool canDeleteAttributes = vl->dataProvider()->capabilities() & QgsVectorDataProvider::DeleteAttributes;
listBox2->clear();
const QgsFields& layerAttributes = vl->pendingFields();
for ( int idx = 0; idx < layerAttributes.count(); ++idx )
{
QListWidgetItem* item = new QListWidgetItem( layerAttributes[idx].name(), listBox2 );
switch ( vl->pendingFields().fieldOrigin( idx ) )
{
case QgsFields::OriginExpression:
item->setIcon( QgsApplication::getThemeIcon( "/mIconExpression.svg" ) );
break;

case QgsFields::OriginJoin:
item->setIcon( QgsApplication::getThemeIcon( "/propertyicons/join.png" ) );
item->setFlags( item->flags() & ~Qt::ItemIsEnabled );
break;

default:
item->setIcon( QgsApplication::getThemeIcon( "/propertyicons/attributes.png" ) );
if ( !vl->isEditable() || !canDeleteAttributes )
item->setFlags( item->flags() & ~Qt::ItemIsEnabled );
break;
}

item->setData( Qt::UserRole, idx );
}

mEditModeInfo->setVisible( !vl->isEditable() );
mCanDeleteAttributesInfo->setVisible( !canDeleteAttributes );
}

QSettings settings;
@@ -140,6 +140,8 @@ void QgsFieldsProperties::onAttributeSelectionChanged()
if ( mDesignerTree->selectedItems()[0]->data( 0, DesignerTreeRole ).value<DesignerTreeItemData>().type() == DesignerTreeItemData::Container )
isAddPossible = true;
mAddItemButton->setEnabled( isAddPossible );

updateButtons();
}

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

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

Q_FOREACH ( QgsAttributeEditorElement* wdg, container->children() )
Q_FOREACH( QgsAttributeEditorElement* wdg, container->children() )
{
loadAttributeEditorTreeItem( wdg, newWidget );
}
@@ -185,7 +187,7 @@ void QgsFieldsProperties::loadAttributeEditorTree()
mDesignerTree->setAcceptDrops( true );
mDesignerTree->setDragDropMode( QAbstractItemView::DragDrop );

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

int idx = 0;

Q_FOREACH ( const QgsRelation& relation, relations )
Q_FOREACH( const QgsRelation& relation, relations )
{
mRelationsList->insertRow( idx );

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

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

Q_FOREACH ( QTableWidgetItem* wdg, mIndexedWidgets )
Q_FOREACH( QTableWidgetItem* wdg, mIndexedWidgets )
{
cfg = wdg->data( FieldConfigRole ).value<FieldConfig>();
if ( cfg.mButton == pb )
@@ -486,6 +488,7 @@ bool QgsFieldsProperties::addAttribute( const QgsField &field )
else
{
mLayer->destroyEditCommand();
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() ) );
return false;
}
}
@@ -536,34 +539,38 @@ void QgsFieldsProperties::on_mAddAttributeButton_clicked()
}
else
{
mLayer->beginEditCommand( "Attribute added" );
if ( !addAttribute( dialog.field() ) )
{
mLayer->destroyEditCommand();
QMessageBox::information( this, tr( "Name conflict" ), tr( "The attribute could not be inserted. The name already exists in the table." ) );
}
else
{
mLayer->endEditCommand();
}
addAttribute( dialog.field() );
}
}
}

void QgsFieldsProperties::on_mDeleteAttributeButton_clicked()
{
QSet<int> attrs;
foreach ( QTableWidgetItem* item, mFieldsList->selectedItems() )
QSet<int> providerFields;
QSet<int> expressionFields;
Q_FOREACH( QTableWidgetItem* item, mFieldsList->selectedItems() )
{
if ( item->column() == 0 )
{
attrs << mIndexedWidgets.indexOf( item );
int idx = mIndexedWidgets.indexOf( item );
if ( mLayer->pendingFields().fieldOrigin( idx ) == QgsFields::OriginExpression )
expressionFields << idx;
else
providerFields << idx;
}
}

mLayer->beginEditCommand( tr( "Deleted attribute" ) );
mLayer->deleteAttributes( attrs.toList() );
mLayer->endEditCommand();
if ( expressionFields.count() )
mLayer->deleteAttributes( expressionFields.toList() );

if ( providerFields.count() )
{
mLayer->beginEditCommand( tr( "Deleted attributes" ) );
if ( mLayer->deleteAttributes( providerFields.toList() ) )
mLayer->endEditCommand();
else
mLayer->destroyEditCommand();
}
}

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

if ( mLayer->isEditable() )
{
mAddAttributeButton->setEnabled( cap & QgsVectorDataProvider::AddAttributes );
mDeleteAttributeButton->setEnabled( cap & QgsVectorDataProvider::DeleteAttributes );
mCalculateFieldButton->setEnabled( cap & ( QgsVectorDataProvider::ChangeAttributeValues | QgsVectorDataProvider::AddAttributes ) );
mToggleEditingButton->setChecked( true );
}
else
{
mAddAttributeButton->setEnabled( false );
mDeleteAttributeButton->setEnabled( false );
mToggleEditingButton->setChecked( false );
mCalculateFieldButton->setEnabled( false );

// Enable delete button if items are selected
mDeleteAttributeButton->setEnabled( mFieldsList->selectedItems().count() > 0 );

// and only if all selected items have their origin in an expression
Q_FOREACH( QTableWidgetItem* item, mFieldsList->selectedItems() )
{
if ( item->column() == 0 )
{
int idx = mIndexedWidgets.indexOf( item );
if ( mLayer->pendingFields().fieldOrigin( idx ) != QgsFields::OriginExpression )
{
mDeleteAttributeButton->setEnabled( false );
break;
}
}
}
}
}

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

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

Q_FOREACH ( const QTreeWidgetItem* item, items )
Q_FOREACH( const QTreeWidgetItem* item, items )
{
if ( item )
{
@@ -150,7 +150,6 @@ class APP_EXPORT QgsFieldsProperties : public QWidget, private Ui_QgsFieldsPrope
void init();
void apply();

void updateButtons();
void loadRows();
void setRow( int row, int idx, const QgsField &field );

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

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

void attributesListCellChanged( int row, int column );

protected slots:

/** editing of layer was toggled */
void editingToggled();

protected:
void updateButtons();

FieldConfig configForRow( int row );
void setConfigForRow( int row, FieldConfig cfg );

@@ -2119,6 +2119,12 @@ QString QgsVectorLayer::attributeDisplayName( int attributeIndex ) const

bool QgsVectorLayer::deleteAttribute( int index )
{
if ( mUpdatedFields.fieldOrigin( index ) == QgsFields::OriginExpression )
{
removeExpressionField( index );
return true;
}

if ( !mEditBuffer || !mDataProvider )
return false;

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

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

foreach ( int attr, attrs )
Q_FOREACH( int attr, attrs )
{
if ( deleteAttribute( attr ) )
{

0 comments on commit bed164e

Please sign in to comment.