mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
[FEATURE] attribute editing improvements:
- refactor attribute dialog calls to QgsFeatureAttribute - add QgsVectorLayer::featureAdded signal - improve interactive attribute editing in table (adding/deleting features, attribute update) - allow adding of geometryless features - fix attribute undo/redo git-svn-id: http://svn.osgeo.org/qgis/trunk@14729 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
parent
2c84b529d9
commit
c3c979a0f2
@ -52,6 +52,19 @@ int QgsAttributeTableDelegate::fieldIdx( const QModelIndex &index ) const
|
||||
return -1;
|
||||
}
|
||||
|
||||
int QgsAttributeTableDelegate::featureId( const QModelIndex &index ) const
|
||||
{
|
||||
const QgsAttributeTableModel *tm = qobject_cast<const QgsAttributeTableModel *>( index.model() );
|
||||
if ( tm )
|
||||
return tm->rowToId( index.row() );
|
||||
|
||||
const QgsAttributeTableFilterModel *fm = dynamic_cast<const QgsAttributeTableFilterModel *>( index.model() );
|
||||
if ( fm )
|
||||
return fm->tableModel()->rowToId( index.row() );
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
QWidget *QgsAttributeTableDelegate::createEditor(
|
||||
QWidget *parent,
|
||||
@ -87,11 +100,16 @@ void QgsAttributeTableDelegate::setModelData( QWidget *editor, QAbstractItemMode
|
||||
if ( vl == NULL )
|
||||
return;
|
||||
|
||||
int idx = fieldIdx( index );
|
||||
int fid = featureId( index );
|
||||
|
||||
QVariant value;
|
||||
if ( !QgsAttributeEditor::retrieveValue( editor, vl, fieldIdx( index ), value ) )
|
||||
if ( !QgsAttributeEditor::retrieveValue( editor, vl, idx, value ) )
|
||||
return;
|
||||
|
||||
model->setData( index, value );
|
||||
vl->beginEditCommand( tr( "Attribute changed" ) );
|
||||
vl->changeAttributeValue( fid, idx, value, true );
|
||||
vl->endEditCommand();
|
||||
}
|
||||
|
||||
void QgsAttributeTableDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
|
||||
|
@ -32,6 +32,7 @@ class QgsAttributeTableDelegate : public QItemDelegate
|
||||
|
||||
QgsVectorLayer *layer( const QAbstractItemModel *model ) const;
|
||||
int fieldIdx( const QModelIndex &index ) const;
|
||||
int featureId( const QModelIndex &index ) const;
|
||||
|
||||
public:
|
||||
/** Constructor
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "qgslogger.h"
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgsfieldcalculator.h"
|
||||
#include "qgsfeatureaction.h"
|
||||
|
||||
class QgsAttributeTableDock : public QDockWidget
|
||||
{
|
||||
@ -99,6 +100,7 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWid
|
||||
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;
|
||||
mToggleEditingButton->setCheckable( true );
|
||||
mToggleEditingButton->setChecked( mLayer->isEditable() );
|
||||
mToggleEditingButton->setEnabled( canChangeAttributes && !mLayer->isReadOnly() );
|
||||
@ -106,6 +108,8 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWid
|
||||
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 );
|
||||
|
||||
// info from table to application
|
||||
connect( this, SIGNAL( editingToggled( QgsMapLayer * ) ), QgisApp::instance(), SLOT( toggleEditing( QgsMapLayer * ) ) );
|
||||
@ -114,6 +118,7 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWid
|
||||
connect( mLayer, SIGNAL( editingStopped() ), this, SLOT( editingToggled() ) );
|
||||
|
||||
connect( searchButton, SIGNAL( clicked() ), this, SLOT( search() ) );
|
||||
connect( mAddFeature, SIGNAL( clicked() ), this, SLOT( addFeature() ) );
|
||||
|
||||
connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
|
||||
connect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( close() ) );
|
||||
@ -674,10 +679,12 @@ void QgsAttributeTableDialog::editingToggled()
|
||||
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 && 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 );
|
||||
|
||||
// (probably reload data if user stopped editing - possible revert)
|
||||
mModel->reload( mModel->index( 0, 0 ), mModel->index( mModel->rowCount(), mModel->columnCount() ) );
|
||||
@ -775,9 +782,18 @@ void QgsAttributeTableDialog::on_mRemoveAttribute_clicked()
|
||||
void QgsAttributeTableDialog::on_mOpenFieldCalculator_clicked()
|
||||
{
|
||||
QgsFieldCalculator calc( mLayer );
|
||||
if ( calc.exec() == QDialog::Accepted )
|
||||
calc.exec();
|
||||
}
|
||||
|
||||
void QgsAttributeTableDialog::addFeature()
|
||||
{
|
||||
if ( !mLayer->isEditable() )
|
||||
return;
|
||||
|
||||
QgsFeature f;
|
||||
QgsFeatureAction action( tr( "Geometryless feature added" ), f, mLayer, -1, this );
|
||||
if ( action.addFeature() )
|
||||
{
|
||||
// update model - a field has been added or updated
|
||||
mModel->reload( mModel->index( 0, 0 ), mModel->index( mModel->rowCount(), mModel->columnCount() ) );
|
||||
}
|
||||
}
|
||||
|
@ -151,6 +151,11 @@ class QgsAttributeTableDialog : public QDialog, private Ui::QgsAttributeTableDia
|
||||
*/
|
||||
void on_mDeleteSelectedButton_clicked();
|
||||
|
||||
/**
|
||||
* add feature
|
||||
*/
|
||||
void addFeature();
|
||||
|
||||
void on_mHelpButton_clicked() { QgsContextHelp::run( metaObject()->className() ); }
|
||||
|
||||
signals:
|
||||
|
@ -60,7 +60,6 @@ bool QgsAttributeTableMemoryModel::featureAtId( int fid )
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void QgsAttributeTableMemoryModel::featureDeleted( int fid )
|
||||
{
|
||||
QgsDebugMsg( "entered." );
|
||||
@ -76,7 +75,6 @@ void QgsAttributeTableMemoryModel::featureAdded( int fid )
|
||||
mFeatureMap.insert( fid, f );
|
||||
QgsAttributeTableModel::featureAdded( fid );
|
||||
}
|
||||
#endif
|
||||
|
||||
void QgsAttributeTableMemoryModel::layerDeleted()
|
||||
{
|
||||
@ -89,5 +87,5 @@ void QgsAttributeTableMemoryModel::attributeValueChanged( int fid, int idx, cons
|
||||
{
|
||||
QgsDebugMsg( "entered." );
|
||||
mFeatureMap[fid].changeAttribute( idx, value );
|
||||
reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
|
||||
QgsAttributeTableModel::attributeValueChanged( fid, idx, value );
|
||||
}
|
||||
|
@ -40,7 +40,6 @@ class QgsAttributeTableMemoryModel : public QgsAttributeTableModel
|
||||
QgsAttributeTableMemoryModel( QgsVectorLayer *theLayer );
|
||||
|
||||
protected slots:
|
||||
#if 0
|
||||
/**
|
||||
* Launched when a feature has been deleted
|
||||
* @param fid feature id
|
||||
@ -51,7 +50,6 @@ class QgsAttributeTableMemoryModel : public QgsAttributeTableModel
|
||||
* @param fid feature id
|
||||
*/
|
||||
virtual void featureAdded( int fid );
|
||||
#endif
|
||||
/**
|
||||
* Launched when layer has been deleted
|
||||
*/
|
||||
|
@ -22,14 +22,12 @@
|
||||
#include "qgisapp.h"
|
||||
#include "qgsattributeaction.h"
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgsfeatureaction.h"
|
||||
|
||||
#include <QtGui>
|
||||
#include <QVariant>
|
||||
#include <limits>
|
||||
|
||||
////////////////////////////
|
||||
// QgsAttributeTableModel //
|
||||
////////////////////////////
|
||||
|
||||
QgsAttributeTableModel::QgsAttributeTableModel( QgsVectorLayer *theLayer, QObject *parent )
|
||||
: QAbstractTableModel( parent )
|
||||
@ -38,67 +36,96 @@ QgsAttributeTableModel::QgsAttributeTableModel( QgsVectorLayer *theLayer, QObjec
|
||||
mLayer = theLayer;
|
||||
loadAttributes();
|
||||
|
||||
connect( mLayer, SIGNAL( layerModified( bool ) ), this, SLOT( layerModified( bool ) ) );
|
||||
//connect(mLayer, SIGNAL(attributeValueChanged(int, int, const QVariant&)), this, SLOT( attributeValueChanged(int, int, const QVariant&)));
|
||||
//connect(mLayer, SIGNAL(featureDeleted(int)), this, SLOT( featureDeleted(int)));
|
||||
//connect(mLayer, SIGNAL(featureAdded(int)), this, SLOT( featureAdded(int)));
|
||||
connect( mLayer, SIGNAL( attributeValueChanged( int, int, const QVariant& ) ), this, SLOT( attributeValueChanged( int, int, const QVariant& ) ) );
|
||||
connect( mLayer, SIGNAL( featureAdded( int ) ), this, SLOT( featureAdded( int ) ) );
|
||||
connect( mLayer, SIGNAL( featureDeleted( int ) ), this, SLOT( featureDeleted( int ) ) );
|
||||
|
||||
loadLayer();
|
||||
}
|
||||
|
||||
bool QgsAttributeTableModel::featureAtId( int fid ) const
|
||||
{
|
||||
return mLayer->featureAtId( fid, mFeat, false, true );
|
||||
QgsDebugMsg( QString( "loading feature %1" ).arg( fid ) );
|
||||
|
||||
if ( fid == std::numeric_limits<int>::min() )
|
||||
return false;
|
||||
else
|
||||
return mLayer->featureAtId( fid, mFeat, false, true );
|
||||
}
|
||||
|
||||
#if 0
|
||||
void QgsAttributeTableModel::featureDeleted( int fid )
|
||||
{
|
||||
QgsDebugMsg( "entered." );
|
||||
QgsDebugMsg( QString( "deleted fid=%1 => row=%2" ).arg( fid ).arg( idToRow( fid ) ) );
|
||||
|
||||
int row = idToRow( fid );
|
||||
|
||||
beginRemoveRows( QModelIndex(), row, row );
|
||||
removeRow( row );
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
bool QgsAttributeTableModel::removeRows( int row, int count, const QModelIndex &parent )
|
||||
{
|
||||
QgsDebugMsg( QString( "remove %2 rows at %1" ).arg( row ).arg( count ) );
|
||||
|
||||
// clean old references
|
||||
for ( int i = row; i < row + count; i++ )
|
||||
{
|
||||
mIdRowMap.remove( mRowIdMap[ row ] );
|
||||
mRowIdMap.remove( row );
|
||||
}
|
||||
|
||||
// update maps
|
||||
int n = mRowIdMap.size() + count;
|
||||
for ( int i = row + count; i < n; i++ )
|
||||
{
|
||||
int id = mRowIdMap[i];
|
||||
mIdRowMap[ id ] -= count;
|
||||
mRowIdMap[ i-count ] = id;
|
||||
mRowIdMap.remove( i );
|
||||
}
|
||||
|
||||
#ifdef QGISDEBUG
|
||||
int idx = mIdRowMap[fid];
|
||||
QgsDebugMsg( idx );
|
||||
QgsDebugMsg( fid );
|
||||
#endif
|
||||
|
||||
QgsDebugMsg( "id->row" );
|
||||
QHash<int, int>::iterator it;
|
||||
for ( it = mIdRowMap.begin(); it != mIdRowMap.end(); ++it )
|
||||
QgsDebugMsg( QString( "%1->%2" ).arg( it.key() ).arg( *it ) );
|
||||
|
||||
QgsDebugMsg( "row->id" );
|
||||
|
||||
for ( it = mRowIdMap.begin(); it != mRowIdMap.end(); ++it )
|
||||
QgsDebugMsg( QString( "%1->%2" ).arg( it.key() ).arg( *it ) );
|
||||
|
||||
}
|
||||
|
||||
void QgsAttributeTableModel::featureAdded( int fid )
|
||||
{
|
||||
QgsDebugMsg( "BM feature added" );
|
||||
++mFeatureCount;
|
||||
mIdRowMap.insert( fid, mFeatureCount - 1 );
|
||||
mRowIdMap.insert( mFeatureCount - 1, fid );
|
||||
QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
|
||||
reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QgsAttributeTableModel::featureAdded( int fid, bool newOperation )
|
||||
{
|
||||
QgsDebugMsg( QString( "feature %1 added (%2, rows %3, ids %4)" ).arg( fid ).arg( newOperation ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
|
||||
|
||||
int n = mRowIdMap.size();
|
||||
if ( newOperation )
|
||||
beginInsertRows( QModelIndex(), n, n );
|
||||
|
||||
mIdRowMap.insert( fid, n );
|
||||
mRowIdMap.insert( n, fid );
|
||||
|
||||
if ( newOperation )
|
||||
endInsertRows();
|
||||
|
||||
reload( index( rowCount() - 1, 0 ), index( rowCount() - 1, columnCount() ) );
|
||||
}
|
||||
|
||||
void QgsAttributeTableModel::attributeAdded( int idx )
|
||||
{
|
||||
QgsDebugMsg( "BM attribute added" );
|
||||
loadLayer();
|
||||
QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
|
||||
QgsDebugMsg( "entered." );
|
||||
reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
|
||||
emit modelChanged();
|
||||
}
|
||||
|
||||
void QgsAttributeTableModel::attributeDeleted( int idx )
|
||||
{
|
||||
QgsDebugMsg( "BM attribute deleted" );
|
||||
loadLayer();
|
||||
QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
|
||||
QgsDebugMsg( "entered." );
|
||||
reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
|
||||
emit modelChanged();
|
||||
}
|
||||
@ -106,28 +133,15 @@ void QgsAttributeTableModel::attributeDeleted( int idx )
|
||||
void QgsAttributeTableModel::layerDeleted()
|
||||
{
|
||||
QgsDebugMsg( "entered." );
|
||||
mIdRowMap.clear();
|
||||
mRowIdMap.clear();
|
||||
QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
|
||||
reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
|
||||
|
||||
beginRemoveRows( QModelIndex(), 0, rowCount() - 1 );
|
||||
removeRows( 0, rowCount() );
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
//TODO: check whether caching in data()/setData() doesn't cache old value
|
||||
void QgsAttributeTableModel::attributeValueChanged( int fid, int idx, const QVariant &value )
|
||||
{
|
||||
QgsDebugMsg( "entered." );
|
||||
reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
|
||||
}
|
||||
|
||||
void QgsAttributeTableModel::layerModified( bool onlyGeometry )
|
||||
{
|
||||
if ( onlyGeometry )
|
||||
return;
|
||||
|
||||
loadAttributes();
|
||||
loadLayer();
|
||||
emit modelChanged();
|
||||
emit headerDataChanged( Qt::Horizontal, 0, columnCount() - 1 );
|
||||
setData( index( idToRow( fid ), mAttributes.indexOf( idx ) ), value, Qt::EditRole );
|
||||
}
|
||||
|
||||
void QgsAttributeTableModel::loadAttributes()
|
||||
@ -187,26 +201,25 @@ void QgsAttributeTableModel::loadLayer()
|
||||
{
|
||||
QgsDebugMsg( "entered." );
|
||||
|
||||
QgsFeature f;
|
||||
bool ins = false, rm = false;
|
||||
Q_ASSERT( mRowIdMap.size() == mIdRowMap.size() );
|
||||
|
||||
int previousSize = mRowIdMap.size();
|
||||
beginRemoveRows( QModelIndex(), 0, rowCount() - 1 );
|
||||
removeRows( 0, rowCount() );
|
||||
endRemoveRows();
|
||||
|
||||
mRowIdMap.clear();
|
||||
mIdRowMap.clear();
|
||||
Q_ASSERT( mRowIdMap.size() == mIdRowMap.size() );
|
||||
|
||||
QSettings settings;
|
||||
int behaviour = settings.value( "/qgis/attributeTableBehaviour", 0 ).toInt();
|
||||
|
||||
if ( behaviour == 1 )
|
||||
{
|
||||
const QgsFeatureList &features = mLayer->selectedFeatures();
|
||||
|
||||
for ( int i = 0; i < features.size(); ++i )
|
||||
beginInsertRows( QModelIndex(), 0, mLayer->selectedFeatureCount() );
|
||||
foreach( int fid, mLayer->selectedFeaturesIds() )
|
||||
{
|
||||
mRowIdMap.insert( i, features[i].id() );
|
||||
mIdRowMap.insert( features[i].id(), i );
|
||||
featureAdded( fid, false );
|
||||
}
|
||||
endInsertRows();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -219,39 +232,16 @@ void QgsAttributeTableModel::loadLayer()
|
||||
|
||||
mLayer->select( mAttributes, rect, false );
|
||||
|
||||
QgsFeature f;
|
||||
for ( int i = 0; mLayer->nextFeature( f ); ++i )
|
||||
{
|
||||
mRowIdMap.insert( i, f.id() );
|
||||
mIdRowMap.insert( f.id(), i );
|
||||
featureAdded( f.id() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( previousSize < mRowIdMap.size() )
|
||||
{
|
||||
QgsDebugMsg( "ins" );
|
||||
ins = true;
|
||||
beginInsertRows( QModelIndex(), previousSize, mRowIdMap.size() - 1 );
|
||||
}
|
||||
else if ( previousSize > mRowIdMap.size() )
|
||||
{
|
||||
QgsDebugMsg( "rm" );
|
||||
rm = true;
|
||||
beginRemoveRows( QModelIndex(), mRowIdMap.size(), previousSize - 1 );
|
||||
}
|
||||
Q_ASSERT( mRowIdMap.size() == mIdRowMap.size() );
|
||||
|
||||
// not needed when we have featureAdded signal
|
||||
mFieldCount = mAttributes.size();
|
||||
|
||||
if ( ins )
|
||||
{
|
||||
endInsertRows();
|
||||
QgsDebugMsg( "end ins" );
|
||||
}
|
||||
else if ( rm )
|
||||
{
|
||||
endRemoveRows();
|
||||
QgsDebugMsg( "end rm" );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsAttributeTableModel::swapRows( int a, int b )
|
||||
@ -442,17 +432,7 @@ bool QgsAttributeTableModel::setData( const QModelIndex &index, const QVariant &
|
||||
int rowId = rowToId( index.row() );
|
||||
if ( mFeat.id() == rowId || featureAtId( rowId ) )
|
||||
{
|
||||
int fieldId = mAttributes[ index.column()];
|
||||
|
||||
disconnect( mLayer, SIGNAL( layerModified( bool ) ), this, SLOT( layerModified( bool ) ) );
|
||||
|
||||
mLayer->beginEditCommand( tr( "Attribute changed" ) );
|
||||
mLayer->changeAttributeValue( rowId, fieldId, value, true );
|
||||
mLayer->endEditCommand();
|
||||
|
||||
mFeat.changeAttribute( fieldId, value );
|
||||
|
||||
connect( mLayer, SIGNAL( layerModified( bool ) ), this, SLOT( layerModified( bool ) ) );
|
||||
mFeat.changeAttribute( mAttributes[ index.column()], value );
|
||||
}
|
||||
|
||||
if ( !mLayer->isModified() )
|
||||
@ -509,3 +489,20 @@ void QgsAttributeTableModel::executeAction( int action, const QModelIndex &idx )
|
||||
|
||||
mLayer->actions()->doAction( action, attributes, fieldIdx( idx.column() ) );
|
||||
}
|
||||
|
||||
void QgsAttributeTableModel::featureForm( QModelIndex &idx )
|
||||
{
|
||||
QgsFeature f;
|
||||
QgsAttributeMap attributes;
|
||||
|
||||
for ( int i = 0; i < mAttributes.size(); i++ )
|
||||
{
|
||||
f.changeAttribute( i, data( index( idx.row(), i ), Qt::EditRole ) );
|
||||
}
|
||||
|
||||
QgsFeatureAction action( tr( "Attributes changed" ), f, mLayer, -1, this );
|
||||
if ( mLayer->isEditable() )
|
||||
action.editFeature();
|
||||
else
|
||||
action.viewFeatureForm();
|
||||
}
|
||||
|
@ -81,6 +81,10 @@ class QgsAttributeTableModel: public QAbstractTableModel
|
||||
* @param index2 end index
|
||||
*/
|
||||
void reload( const QModelIndex &index1, const QModelIndex &index2 );
|
||||
/**
|
||||
* Remove rows
|
||||
*/
|
||||
bool removeRows( int row, int count, const QModelIndex &parent = QModelIndex() );
|
||||
/**
|
||||
* Resets the model
|
||||
*/
|
||||
@ -104,9 +108,9 @@ class QgsAttributeTableModel: public QAbstractTableModel
|
||||
int fieldIdx( int col ) const;
|
||||
/**
|
||||
* Maps row to feature id
|
||||
* @param id row id
|
||||
* @param row row number
|
||||
*/
|
||||
int rowToId( const int id ) const;
|
||||
int rowToId( const int row ) const;
|
||||
/**
|
||||
* Sorts the model
|
||||
* @param column column to sort by
|
||||
@ -128,6 +132,8 @@ class QgsAttributeTableModel: public QAbstractTableModel
|
||||
/** Execute an action */
|
||||
void executeAction( int action, const QModelIndex &idx ) const;
|
||||
|
||||
void featureForm( QModelIndex& );
|
||||
|
||||
signals:
|
||||
/**
|
||||
* Model has been changed
|
||||
@ -151,6 +157,7 @@ class QgsAttributeTableModel: public QAbstractTableModel
|
||||
* @param idx attribute index
|
||||
*/
|
||||
virtual void attributeDeleted( int idx );
|
||||
protected slots:
|
||||
/**
|
||||
* Launched when attribute value has been changed
|
||||
* @param fid feature id
|
||||
@ -158,15 +165,6 @@ class QgsAttributeTableModel: public QAbstractTableModel
|
||||
* @param value new value
|
||||
*/
|
||||
virtual void attributeValueChanged( int fid, int idx, const QVariant &value );
|
||||
/**
|
||||
* Launched when layer has been modified
|
||||
* Rebuilds the model
|
||||
* @param onlyGeometry true if only geometry has changed
|
||||
*/
|
||||
virtual void layerModified( bool onlyGeometry = false );
|
||||
|
||||
protected slots:
|
||||
#if 0
|
||||
/**
|
||||
* Launched when a feature has been deleted
|
||||
* @param fid feature id
|
||||
@ -175,9 +173,9 @@ class QgsAttributeTableModel: public QAbstractTableModel
|
||||
/**
|
||||
* Launched when a feature has been added
|
||||
* @param fid feature id
|
||||
* @parem inOperation guard insertion with beginInsertRows() / endInsertRows()
|
||||
*/
|
||||
virtual void featureAdded( int fid );
|
||||
#endif
|
||||
virtual void featureAdded( int fid, bool inOperation = true );
|
||||
/**
|
||||
* Launched when layer has been deleted
|
||||
*/
|
||||
|
@ -88,27 +88,32 @@ void QgsAttributeTableView::contextMenuEvent( QContextMenuEvent *event )
|
||||
}
|
||||
|
||||
QgsVectorLayer *vlayer = mModel->layer();
|
||||
if ( !vlayer || vlayer->actions()->size() == 0 )
|
||||
{
|
||||
if ( !vlayer )
|
||||
return;
|
||||
}
|
||||
|
||||
mActionPopup = new QMenu();
|
||||
|
||||
QAction *a = mActionPopup->addAction( tr( "Run action" ) );
|
||||
a->setEnabled( false );
|
||||
|
||||
for ( int i = 0; i < vlayer->actions()->size(); i++ )
|
||||
if ( vlayer->actions()->size() == 0 )
|
||||
{
|
||||
const QgsAction &action = vlayer->actions()->at( i );
|
||||
|
||||
if ( !action.runable() )
|
||||
continue;
|
||||
QAction *a = mActionPopup->addAction( tr( "Run action" ) );
|
||||
a->setEnabled( false );
|
||||
|
||||
QgsAttributeTableAction *a = new QgsAttributeTableAction( action.name(), this, mModel, i, idx );
|
||||
mActionPopup->addAction( action.name(), a, SLOT( execute() ) );
|
||||
for ( int i = 0; i < vlayer->actions()->size(); i++ )
|
||||
{
|
||||
const QgsAction &action = vlayer->actions()->at( i );
|
||||
|
||||
if ( !action.runable() )
|
||||
continue;
|
||||
|
||||
QgsAttributeTableAction *a = new QgsAttributeTableAction( action.name(), this, mModel, i, idx );
|
||||
mActionPopup->addAction( action.name(), a, SLOT( execute() ) );
|
||||
}
|
||||
}
|
||||
|
||||
QgsAttributeTableAction *a = new QgsAttributeTableAction( tr( "Open form" ), this, mModel, -1, idx );
|
||||
mActionPopup->addAction( tr( "Open form" ), a, SLOT( featureForm() ) );
|
||||
|
||||
mActionPopup->popup( event->globalPos() );
|
||||
}
|
||||
|
||||
@ -116,3 +121,8 @@ void QgsAttributeTableAction::execute()
|
||||
{
|
||||
mModel->executeAction( mAction, mFieldIdx );
|
||||
}
|
||||
|
||||
void QgsAttributeTableAction::featureForm()
|
||||
{
|
||||
mModel->featureForm( mFieldIdx );
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ class QgsVectorLayer;
|
||||
class QMenu;
|
||||
|
||||
|
||||
class QgsAttributeTableView: public QTableView
|
||||
class QgsAttributeTableView : public QTableView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@ -65,6 +65,7 @@ class QgsAttributeTableAction : public QAction
|
||||
|
||||
public slots:
|
||||
void execute();
|
||||
void featureForm();
|
||||
|
||||
private:
|
||||
QgsAttributeTableModel *mModel;
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "qgsproject.h"
|
||||
#include "qgsapplication.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgsattributedialog.h"
|
||||
#include "qgsfeatureaction.h"
|
||||
#include "qgsgeometry.h"
|
||||
|
||||
//for avoid intersections static method
|
||||
@ -674,45 +674,13 @@ void QgsGPSInformationWidget::on_mBtnCloseFeature_clicked( )
|
||||
memcpy( &wkb[5] + sizeof( double ), &y, sizeof( double ) );
|
||||
|
||||
f->setGeometryAndOwnership( &wkb[0], size );
|
||||
// add the fields to the QgsFeature
|
||||
const QgsFieldMap fields = vlayer->pendingFields();
|
||||
for ( QgsFieldMap::const_iterator it = fields.constBegin(); it != fields.constEnd(); ++it )
|
||||
{
|
||||
f->addAttribute( it.key(), provider->defaultValue( it.key() ) );
|
||||
}
|
||||
|
||||
vlayer->beginEditCommand( tr( "Feature added" ) );
|
||||
QgsFeatureAction action( tr( "Feature added" ), *f, vlayer, -1, this );
|
||||
if ( action.addFeature() )
|
||||
mpCanvas->refresh();
|
||||
|
||||
// show the dialog to enter attribute values
|
||||
QSettings settings;
|
||||
bool isDisabledAttributeValuesDlg = settings.value( "/qgis/digitizing/disable_enter_attribute_values_dialog", false ).toBool();
|
||||
if ( isDisabledAttributeValuesDlg )
|
||||
{
|
||||
QgsDebugMsg( "Adding feature to layer" );
|
||||
vlayer->addFeature( *f );
|
||||
vlayer->endEditCommand();
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsAttributeDialog *mypDialog = new QgsAttributeDialog( vlayer, f );
|
||||
if ( mypDialog->exec() )
|
||||
{
|
||||
QgsDebugMsg( "Adding feature to layer" );
|
||||
vlayer->addFeature( *f );
|
||||
vlayer->endEditCommand();
|
||||
}
|
||||
else
|
||||
{
|
||||
vlayer->destroyEditCommand();
|
||||
QgsDebugMsg( "Adding feature to layer failed" );
|
||||
delete f;
|
||||
}
|
||||
delete mypDialog;
|
||||
}
|
||||
|
||||
mpCanvas->refresh();
|
||||
delete f;
|
||||
}
|
||||
|
||||
}
|
||||
else // Line or poly
|
||||
{
|
||||
@ -819,48 +787,10 @@ void QgsGPSInformationWidget::on_mBtnCloseFeature_clicked( )
|
||||
return; //unknown wkbtype
|
||||
}
|
||||
|
||||
// add the fields to the QgsFeature
|
||||
const QgsFieldMap fields = vlayer->pendingFields();
|
||||
for ( QgsFieldMap::const_iterator it = fields.begin(); it != fields.end(); ++it )
|
||||
{
|
||||
f->addAttribute( it.key(), provider->defaultValue( it.key() ) );
|
||||
}
|
||||
QgsFeatureAction action( tr( "Feature added" ), *f, vlayer, -1, this );
|
||||
if ( action.addFeature() )
|
||||
mpCanvas->refresh();
|
||||
|
||||
QSettings settings;
|
||||
bool isDisabledAttributeValuesDlg = settings.value( "/qgis/digitizing/disable_enter_attribute_values_dialog", false ).toBool();
|
||||
if ( isDisabledAttributeValuesDlg )
|
||||
{
|
||||
vlayer->beginEditCommand( tr( "Feature added" ) );
|
||||
if ( vlayer->addFeature( *f ) )
|
||||
{
|
||||
//add points to other features to keep topology up-to-date
|
||||
int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 );
|
||||
if ( topologicalEditing )
|
||||
{
|
||||
vlayer->addTopologicalPoints( f->geometry() );
|
||||
}
|
||||
}
|
||||
vlayer->endEditCommand();
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsAttributeDialog * mypDialog = new QgsAttributeDialog( vlayer, f );
|
||||
if ( mypDialog->exec() )
|
||||
{
|
||||
vlayer->beginEditCommand( tr( "Feature added" ) );
|
||||
if ( vlayer->addFeature( *f ) )
|
||||
{
|
||||
//add points to other features to keep topology up-to-date
|
||||
int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 );
|
||||
if ( topologicalEditing )
|
||||
{
|
||||
vlayer->addTopologicalPoints( f->geometry() );
|
||||
}
|
||||
}
|
||||
vlayer->endEditCommand();
|
||||
}
|
||||
mypDialog->deleteLater();
|
||||
}
|
||||
delete f;
|
||||
|
||||
delete mpRubberBand;
|
||||
|
@ -380,73 +380,6 @@ bool QgisAppInterface::openFeatureForm( QgsVectorLayer *vlayer, QgsFeature &f, b
|
||||
if ( !vlayer )
|
||||
return false;
|
||||
|
||||
QgsVectorDataProvider *dp = vlayer->dataProvider();
|
||||
if ( dp )
|
||||
{
|
||||
// add the fields to the QgsFeature
|
||||
const QgsFieldMap fields = vlayer->pendingFields();
|
||||
for ( QgsFieldMap::const_iterator it = fields.constBegin(); it != fields.constEnd(); ++it )
|
||||
{
|
||||
if ( !f.attributeMap().contains( it.key() ) )
|
||||
f.addAttribute( it.key(), dp->defaultValue( it.key() ) );
|
||||
}
|
||||
}
|
||||
|
||||
QgsAttributeMap src = f.attributeMap();
|
||||
|
||||
if ( !updateFeatureOnly && vlayer->isEditable() )
|
||||
vlayer->beginEditCommand( tr( "Feature form edit" ) );
|
||||
|
||||
QgsAttributeDialog *ad = new QgsAttributeDialog( vlayer, &f );
|
||||
|
||||
if ( vlayer->actions()->size() > 0 )
|
||||
{
|
||||
ad->dialog()->setContextMenuPolicy( Qt::ActionsContextMenu );
|
||||
|
||||
QAction *a = new QAction( tr( "Run actions" ), ad->dialog() );
|
||||
a->setEnabled( false );
|
||||
ad->dialog()->addAction( a );
|
||||
|
||||
for ( int i = 0; i < vlayer->actions()->size(); i++ )
|
||||
{
|
||||
const QgsAction &action = vlayer->actions()->at( i );
|
||||
|
||||
if ( !action.runable() )
|
||||
continue;
|
||||
|
||||
QgsFeatureAction *a = new QgsFeatureAction( action.name(), f, vlayer, i, ad->dialog() );
|
||||
ad->dialog()->addAction( a );
|
||||
connect( a, SIGNAL( triggered() ), a, SLOT( execute() ) );
|
||||
|
||||
QAbstractButton *pb = ad->dialog()->findChild<QAbstractButton *>( action.name() );
|
||||
if ( pb )
|
||||
connect( pb, SIGNAL( clicked() ), a, SLOT( execute() ) );
|
||||
}
|
||||
}
|
||||
|
||||
bool res = ad->exec();
|
||||
|
||||
if ( !updateFeatureOnly && vlayer->isEditable() )
|
||||
{
|
||||
if ( res )
|
||||
{
|
||||
const QgsAttributeMap &dst = f.attributeMap();
|
||||
for ( QgsAttributeMap::const_iterator it = dst.begin(); it != dst.end(); it++ )
|
||||
{
|
||||
if ( !src.contains( it.key() ) || it.value() != src[it.key()] )
|
||||
{
|
||||
vlayer->changeAttributeValue( f.id(), it.key(), it.value() );
|
||||
}
|
||||
}
|
||||
vlayer->endEditCommand();
|
||||
}
|
||||
else
|
||||
{
|
||||
vlayer->destroyEditCommand();
|
||||
}
|
||||
}
|
||||
|
||||
delete ad;
|
||||
|
||||
return res;
|
||||
QgsFeatureAction action( tr( "Attributes changed" ), f, vlayer, -1, QgisApp::instance() );
|
||||
return action.editFeature();
|
||||
}
|
||||
|
@ -18,25 +18,189 @@
|
||||
|
||||
#include "qgsfeatureaction.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgsvectordataprovider.h"
|
||||
#include "qgsidentifyresults.h"
|
||||
#include "qgsattributedialog.h"
|
||||
#include "qgslogger.h"
|
||||
|
||||
QgsFeatureAction::QgsFeatureAction( const QString &name, QgsIdentifyResults *results, QgsVectorLayer *vl, int action, QTreeWidgetItem *featItem )
|
||||
: QAction( name, results )
|
||||
, mLayer( vl )
|
||||
, mAction( action )
|
||||
{
|
||||
results->retrieveAttributes( featItem, mAttributes, mIdx );
|
||||
}
|
||||
#include <QPushButton>
|
||||
#include <QSettings>
|
||||
|
||||
QgsFeatureAction::QgsFeatureAction( const QString &name, QgsFeature &f, QgsVectorLayer *layer, int action, QObject *parent )
|
||||
: QAction( name, parent )
|
||||
, mLayer( layer )
|
||||
, mFeature( f )
|
||||
, mAction( action )
|
||||
{
|
||||
mAttributes = f.attributeMap();
|
||||
}
|
||||
|
||||
void QgsFeatureAction::execute()
|
||||
{
|
||||
mLayer->actions()->doAction( mAction, mAttributes, mIdx );
|
||||
mLayer->actions()->doAction( mAction, mFeature.attributeMap(), mIdx );
|
||||
}
|
||||
|
||||
QgsAttributeDialog *QgsFeatureAction::newDialog()
|
||||
{
|
||||
QgsAttributeDialog *dialog = new QgsAttributeDialog( mLayer, &mFeature );
|
||||
|
||||
if ( mLayer->actions()->size() == 0 )
|
||||
{
|
||||
dialog->dialog()->setContextMenuPolicy( Qt::ActionsContextMenu );
|
||||
|
||||
QAction *a = new QAction( tr( "Run actions" ), dialog->dialog() );
|
||||
a->setEnabled( false );
|
||||
dialog->dialog()->addAction( a );
|
||||
|
||||
for ( int i = 0; i < mLayer->actions()->size(); i++ )
|
||||
{
|
||||
const QgsAction &action = mLayer->actions()->at( i );
|
||||
|
||||
if ( !action.runable() )
|
||||
continue;
|
||||
|
||||
QgsFeatureAction *a = new QgsFeatureAction( action.name(), mFeature, mLayer, i, dialog->dialog() );
|
||||
dialog->dialog()->addAction( a );
|
||||
connect( a, SIGNAL( triggered() ), a, SLOT( execute() ) );
|
||||
|
||||
QAbstractButton *pb = dialog->dialog()->findChild<QAbstractButton *>( action.name() );
|
||||
if ( pb )
|
||||
connect( pb, SIGNAL( clicked() ), a, SLOT( execute() ) );
|
||||
}
|
||||
}
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
bool QgsFeatureAction::viewFeatureForm( QgsRubberBand *rb )
|
||||
{
|
||||
if ( !mLayer )
|
||||
return false;
|
||||
|
||||
QgsAttributeDialog *dialog = newDialog();
|
||||
dialog->setHighlight( rb );
|
||||
dialog->show();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsFeatureAction::editFeature()
|
||||
{
|
||||
bool res = false;
|
||||
|
||||
if ( !mLayer )
|
||||
return res;
|
||||
|
||||
QgsAttributeDialog *dialog = newDialog();
|
||||
|
||||
if ( !mLayer->isEditable() )
|
||||
{
|
||||
res = dialog->exec();
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsAttributeMap src = mFeature.attributeMap();
|
||||
|
||||
if ( dialog->exec() )
|
||||
{
|
||||
mLayer->beginEditCommand( text() );
|
||||
|
||||
const QgsAttributeMap &dst = mFeature.attributeMap();
|
||||
for ( QgsAttributeMap::const_iterator it = dst.begin(); it != dst.end(); it++ )
|
||||
{
|
||||
if ( !src.contains( it.key() ) || it.value() != src[it.key()] )
|
||||
{
|
||||
mLayer->changeAttributeValue( mFeature.id(), it.key(), it.value() );
|
||||
}
|
||||
}
|
||||
|
||||
mLayer->endEditCommand();
|
||||
res = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
|
||||
delete dialog;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool QgsFeatureAction::addFeature()
|
||||
{
|
||||
if ( !mLayer || !mLayer->isEditable() )
|
||||
return false;
|
||||
|
||||
QgsVectorDataProvider *provider = mLayer->dataProvider();
|
||||
|
||||
QSettings settings;
|
||||
bool reuseLastValues = settings.value( "/qgis/digitizing/reuseLastValues", false ).toBool();
|
||||
QgsDebugMsg( QString( "reuseLastValues: %1" ).arg( reuseLastValues ) );
|
||||
|
||||
// add the fields to the QgsFeature
|
||||
const QgsFieldMap fields = mLayer->pendingFields();
|
||||
for ( QgsFieldMap::const_iterator it = fields.constBegin(); it != fields.constEnd(); ++it )
|
||||
{
|
||||
if ( reuseLastValues && mLastUsedValues.contains( mLayer ) && mLastUsedValues[ mLayer ].contains( it.key() ) )
|
||||
{
|
||||
QgsDebugMsg( QString( "reusing %1 for %2" ).arg( mLastUsedValues[ mLayer ][ it.key()].toString() ).arg( it.key() ) );
|
||||
mFeature.addAttribute( it.key(), mLastUsedValues[ mLayer ][ it.key()] );
|
||||
}
|
||||
else
|
||||
{
|
||||
mFeature.addAttribute( it.key(), provider->defaultValue( it.key() ) );
|
||||
}
|
||||
}
|
||||
|
||||
bool res = false;
|
||||
|
||||
mLayer->beginEditCommand( text() );
|
||||
|
||||
// show the dialog to enter attribute values
|
||||
bool isDisabledAttributeValuesDlg = settings.value( "/qgis/digitizing/disable_enter_attribute_values_dialog", true ).toBool();
|
||||
if ( isDisabledAttributeValuesDlg )
|
||||
{
|
||||
res = mLayer->addFeature( mFeature );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsAttributeMap origValues;
|
||||
if ( reuseLastValues )
|
||||
origValues = mFeature.attributeMap();
|
||||
|
||||
QgsAttributeDialog *dialog = newDialog();
|
||||
if ( dialog->exec() )
|
||||
{
|
||||
if ( reuseLastValues )
|
||||
{
|
||||
for ( QgsFieldMap::const_iterator it = fields.constBegin(); it != fields.constEnd(); ++it )
|
||||
{
|
||||
const QgsAttributeMap &newValues = mFeature.attributeMap();
|
||||
if ( newValues.contains( it.key() )
|
||||
&& origValues.contains( it.key() )
|
||||
&& origValues[ it.key()] != newValues[ it.key()] )
|
||||
{
|
||||
QgsDebugMsg( QString( "saving %1 for %2" ).arg( mLastUsedValues[ mLayer ][ it.key()].toString() ).arg( it.key() ) );
|
||||
mLastUsedValues[ mLayer ][ it.key()] = newValues[ it.key()];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res = mLayer->addFeature( mFeature );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDebugMsg( "Adding feature to layer failed" );
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( res )
|
||||
mLayer->endEditCommand();
|
||||
else
|
||||
mLayer->destroyEditCommand();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
QMap<QgsVectorLayer *, QgsAttributeMap> QgsFeatureAction::mLastUsedValues;
|
||||
|
@ -26,7 +26,8 @@
|
||||
|
||||
class QgsIdentifyResults;
|
||||
class QgsVectorLayer;
|
||||
class QTreeWidgetItem;
|
||||
class QgsRubberBand;
|
||||
class QgsAttributeDialog;
|
||||
|
||||
class QgsFeatureAction : public QAction
|
||||
{
|
||||
@ -34,16 +35,22 @@ class QgsFeatureAction : public QAction
|
||||
|
||||
public:
|
||||
QgsFeatureAction( const QString &name, QgsFeature &f, QgsVectorLayer *vl, int action, QObject *parent );
|
||||
QgsFeatureAction( const QString &name, QgsIdentifyResults *results, QgsVectorLayer *vl, int action, QTreeWidgetItem *featItem );
|
||||
|
||||
public slots:
|
||||
void execute();
|
||||
bool viewFeatureForm( QgsRubberBand *rb = 0 );
|
||||
bool editFeature();
|
||||
bool addFeature();
|
||||
|
||||
private:
|
||||
QgsAttributeDialog *newDialog();
|
||||
|
||||
QgsVectorLayer *mLayer;
|
||||
QgsFeature &mFeature;
|
||||
int mAction;
|
||||
int mIdx;
|
||||
QgsAttributeMap mAttributes;
|
||||
|
||||
static QMap<QgsVectorLayer *, QgsAttributeMap> mLastUsedValues;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -63,7 +63,7 @@ class QgsIdentifyResultsDock : public QDockWidget
|
||||
// Tree hierarchy
|
||||
//
|
||||
// layer [userrole: QgsMapLayer]
|
||||
// feature: displayfield|displayvalue [userrole: fid]
|
||||
// feature: displayfield|displayvalue [userrole: fid, index in feature list]
|
||||
// derived attributes (if any) [userrole: "derived"]
|
||||
// name value
|
||||
// actions (if any) [userrole: "actions"]
|
||||
@ -132,8 +132,8 @@ QTreeWidgetItem *QgsIdentifyResults::layerItem( QObject *layer )
|
||||
return 0;
|
||||
}
|
||||
|
||||
void QgsIdentifyResults::addFeature( QgsVectorLayer *vlayer, int fid,
|
||||
const QgsAttributeMap &attributes,
|
||||
void QgsIdentifyResults::addFeature( QgsVectorLayer *vlayer,
|
||||
const QgsFeature &f,
|
||||
const QMap<QString, QString> &derivedAttributes )
|
||||
{
|
||||
QTreeWidgetItem *layItem = layerItem( vlayer );
|
||||
@ -153,10 +153,12 @@ void QgsIdentifyResults::addFeature( QgsVectorLayer *vlayer, int fid,
|
||||
}
|
||||
|
||||
QTreeWidgetItem *featItem = new QTreeWidgetItem;
|
||||
featItem->setData( 0, Qt::UserRole, fid );
|
||||
featItem->setData( 0, Qt::UserRole, f.id() );
|
||||
featItem->setData( 0, Qt::UserRole + 1, mFeatures.size() );
|
||||
mFeatures << f;
|
||||
layItem->addChild( featItem );
|
||||
|
||||
for ( QgsAttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++ )
|
||||
for ( QgsAttributeMap::const_iterator it = f.attributeMap().begin(); it != f.attributeMap().end(); it++ )
|
||||
{
|
||||
QTreeWidgetItem *attrItem = new QTreeWidgetItem( QStringList() << QString::number( it.key() ) << it.value().toString() );
|
||||
|
||||
@ -461,7 +463,8 @@ void QgsIdentifyResults::contextMenuEvent( QContextMenuEvent* event )
|
||||
if ( !action.runable() )
|
||||
continue;
|
||||
|
||||
QgsFeatureAction *a = new QgsFeatureAction( action.name(), this, vlayer, i, featItem );
|
||||
int idx = featItem->data( 0, Qt::UserRole + 1 ).toInt();
|
||||
QgsFeatureAction *a = new QgsFeatureAction( action.name(), mFeatures[ idx ], vlayer, i, this );
|
||||
mActionPopup->addAction( QgisApp::getThemeIcon( "/mAction.png" ), action.name(), a, SLOT( execute() ) );
|
||||
}
|
||||
}
|
||||
@ -869,71 +872,23 @@ void QgsIdentifyResults::featureForm()
|
||||
return;
|
||||
|
||||
int fid = featItem->data( 0, Qt::UserRole ).toInt();
|
||||
int idx = featItem->data( 0, Qt::UserRole + 1 ).toInt();
|
||||
|
||||
QgsFeature f;
|
||||
if ( !vlayer->featureAtId( fid, f ) )
|
||||
return;
|
||||
|
||||
QgsAttributeMap src = f.attributeMap();
|
||||
|
||||
if ( vlayer->isEditable() )
|
||||
vlayer->beginEditCommand( tr( "Attribute changed" ) );
|
||||
|
||||
QgsAttributeDialog *ad = new QgsAttributeDialog( vlayer, &f );
|
||||
|
||||
if ( vlayer->actions()->size() > 0 )
|
||||
{
|
||||
ad->dialog()->setContextMenuPolicy( Qt::ActionsContextMenu );
|
||||
|
||||
QAction *a = new QAction( tr( "Run actions" ), ad->dialog() );
|
||||
a->setEnabled( false );
|
||||
ad->dialog()->addAction( a );
|
||||
|
||||
for ( int i = 0; i < vlayer->actions()->size(); i++ )
|
||||
{
|
||||
const QgsAction &action = vlayer->actions()->at( i );
|
||||
|
||||
if ( !action.runable() )
|
||||
continue;
|
||||
|
||||
QgsFeatureAction *a = new QgsFeatureAction( action.name(), this, vlayer, i, featItem );
|
||||
ad->dialog()->addAction( a );
|
||||
connect( a, SIGNAL( triggered() ), a, SLOT( execute() ) );
|
||||
|
||||
QAbstractButton *pb = ad->dialog()->findChild<QAbstractButton *>( action.name() );
|
||||
if ( pb )
|
||||
connect( pb, SIGNAL( clicked() ), a, SLOT( execute() ) );
|
||||
}
|
||||
}
|
||||
|
||||
QgsFeatureAction action( tr( "Attribute changes" ), f, vlayer, idx, this );
|
||||
if ( vlayer->isEditable() )
|
||||
{
|
||||
if ( ad->exec() )
|
||||
if ( action.editFeature() )
|
||||
{
|
||||
const QgsAttributeMap &dst = f.attributeMap();
|
||||
for ( QgsAttributeMap::const_iterator it = dst.begin(); it != dst.end(); it++ )
|
||||
{
|
||||
if ( !src.contains( it.key() ) || it.value() != src[it.key()] )
|
||||
{
|
||||
vlayer->changeAttributeValue( f.id(), it.key(), it.value() );
|
||||
}
|
||||
}
|
||||
vlayer->endEditCommand();
|
||||
mCanvas->refresh();
|
||||
}
|
||||
else
|
||||
{
|
||||
vlayer->destroyEditCommand();
|
||||
}
|
||||
|
||||
delete ad;
|
||||
|
||||
mCanvas->refresh();
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsRubberBand *rb = mRubberBands.take( featItem );
|
||||
ad->setHighlight( rb );
|
||||
ad->show();
|
||||
action.viewFeatureForm( mRubberBands.take( featItem ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,8 +55,8 @@ class QgsIdentifyResults: public QDialog, private Ui::QgsIdentifyResultsBase
|
||||
~QgsIdentifyResults();
|
||||
|
||||
/** Add add feature from vector layer */
|
||||
void addFeature( QgsVectorLayer *layer, int fid,
|
||||
const QgsAttributeMap &attributes,
|
||||
void addFeature( QgsVectorLayer *layer,
|
||||
const QgsFeature &f,
|
||||
const QMap< QString, QString > &derivedAttributes );
|
||||
|
||||
/** Add add feature from other layer */
|
||||
@ -117,6 +117,7 @@ class QgsIdentifyResults: public QDialog, private Ui::QgsIdentifyResultsBase
|
||||
QMenu *mActionPopup;
|
||||
QMap<QTreeWidgetItem *, QgsRubberBand * > mRubberBands;
|
||||
QgsMapCanvas *mCanvas;
|
||||
QList<QgsFeature> mFeatures;
|
||||
|
||||
QgsVectorLayer *vectorLayer( QTreeWidgetItem *item );
|
||||
QTreeWidgetItem *featureItem( QTreeWidgetItem *item );
|
||||
|
@ -27,87 +27,24 @@
|
||||
#include "qgsvectordataprovider.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgsfeatureaction.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QMouseEvent>
|
||||
#include <QSettings>
|
||||
|
||||
QgsMapToolAddFeature::QgsMapToolAddFeature( QgsMapCanvas* canvas, CaptureMode tool ): QgsMapToolCapture( canvas, tool )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QgsMapToolAddFeature::~QgsMapToolAddFeature()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool QgsMapToolAddFeature::addFeature( QgsVectorLayer *vlayer, QgsFeature *f )
|
||||
{
|
||||
bool res = false;
|
||||
QgsVectorDataProvider* provider = vlayer->dataProvider();
|
||||
|
||||
QSettings settings;
|
||||
bool reuseLastValues = settings.value( "/qgis/digitizing/reuseLastValues", false ).toBool();
|
||||
QgsDebugMsg( QString( "reuseLastValues: %1" ).arg( reuseLastValues ) );
|
||||
|
||||
// add the fields to the QgsFeature
|
||||
const QgsFieldMap fields = vlayer->pendingFields();
|
||||
for ( QgsFieldMap::const_iterator it = fields.constBegin(); it != fields.constEnd(); ++it )
|
||||
{
|
||||
if ( reuseLastValues && mLastUsedValues.contains( vlayer ) && mLastUsedValues[ vlayer ].contains( it.key() ) )
|
||||
{
|
||||
QgsDebugMsg( QString( "reusing %1 for %2" ).arg( mLastUsedValues[ vlayer ][ it.key()].toString() ).arg( it.key() ) );
|
||||
f->addAttribute( it.key(), mLastUsedValues[ vlayer ][ it.key()] );
|
||||
}
|
||||
else
|
||||
{
|
||||
f->addAttribute( it.key(), provider->defaultValue( it.key() ) );
|
||||
}
|
||||
}
|
||||
|
||||
// show the dialog to enter attribute values
|
||||
bool isDisabledAttributeValuesDlg = settings.value( "/qgis/digitizing/disable_enter_attribute_values_dialog", true ).toBool();
|
||||
if ( isDisabledAttributeValuesDlg )
|
||||
{
|
||||
res = vlayer->addFeature( *f );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsAttributeDialog *mypDialog = new QgsAttributeDialog( vlayer, f );
|
||||
|
||||
QgsAttributeMap origValues;
|
||||
if ( reuseLastValues )
|
||||
origValues = f->attributeMap();
|
||||
|
||||
if ( mypDialog->exec() )
|
||||
{
|
||||
if ( reuseLastValues )
|
||||
{
|
||||
for ( QgsFieldMap::const_iterator it = fields.constBegin(); it != fields.constEnd(); ++it )
|
||||
{
|
||||
const QgsAttributeMap &newValues = f->attributeMap();
|
||||
if ( newValues.contains( it.key() )
|
||||
&& origValues.contains( it.key() )
|
||||
&& origValues[ it.key()] != newValues[ it.key()] )
|
||||
{
|
||||
QgsDebugMsg( QString( "saving %1 for %2" ).arg( mLastUsedValues[ vlayer ][ it.key()].toString() ).arg( it.key() ) );
|
||||
mLastUsedValues[ vlayer ][ it.key()] = newValues[ it.key()];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res = vlayer->addFeature( *f );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDebugMsg( "Adding feature to layer failed" );
|
||||
res = false;
|
||||
}
|
||||
|
||||
mypDialog->deleteLater();
|
||||
}
|
||||
|
||||
return res;
|
||||
QgsFeatureAction action( tr( "add feature" ), *f, vlayer, -1, this );
|
||||
return action.addFeature();
|
||||
}
|
||||
|
||||
void QgsMapToolAddFeature::canvasReleaseEvent( QMouseEvent * e )
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "qgsfeature.h"
|
||||
|
||||
/**This tool adds new point/line/polygon features to already existing vector layers*/
|
||||
class QgsMapToolAddFeature: public QgsMapToolCapture
|
||||
class QgsMapToolAddFeature : public QgsMapToolCapture
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@ -26,7 +26,5 @@ class QgsMapToolAddFeature: public QgsMapToolCapture
|
||||
virtual ~QgsMapToolAddFeature();
|
||||
void canvasReleaseEvent( QMouseEvent * e );
|
||||
|
||||
private:
|
||||
bool addFeature( QgsVectorLayer *vlayer, QgsFeature *f );
|
||||
QMap<QgsVectorLayer *, QgsAttributeMap> mLastUsedValues;
|
||||
};
|
||||
|
@ -300,7 +300,7 @@ bool QgsMapToolIdentify::identifyVectorLayer( QgsVectorLayer *layer, int x, int
|
||||
|
||||
derivedAttributes.insert( tr( "feature id" ), fid < 0 ? tr( "new feature" ) : QString::number( fid ) );
|
||||
|
||||
results()->addFeature( layer, fid, f_it->attributeMap(), derivedAttributes );
|
||||
results()->addFeature( layer, *f_it, derivedAttributes );
|
||||
}
|
||||
|
||||
QgsDebugMsg( "Feature count on identify: " + QString::number( featureCount ) );
|
||||
|
@ -26,7 +26,12 @@
|
||||
#include <limits>
|
||||
#include <QComboBox>
|
||||
|
||||
QgsMergeAttributesDialog::QgsMergeAttributesDialog( const QgsFeatureList& features, QgsVectorLayer* vl, QgsMapCanvas* canvas, QWidget * parent, Qt::WindowFlags f ): QDialog( parent, f ), mFeatureList( features ), mVectorLayer( vl ), mMapCanvas( canvas ), mSelectionRubberBand( 0 )
|
||||
QgsMergeAttributesDialog::QgsMergeAttributesDialog( const QgsFeatureList &features, QgsVectorLayer *vl, QgsMapCanvas *canvas, QWidget *parent, Qt::WindowFlags f )
|
||||
: QDialog( parent, f )
|
||||
, mFeatureList( features )
|
||||
, mVectorLayer( vl )
|
||||
, mMapCanvas( canvas )
|
||||
, mSelectionRubberBand( 0 )
|
||||
{
|
||||
setupUi( this );
|
||||
createTableWidgetContents();
|
||||
@ -60,48 +65,50 @@ void QgsMergeAttributesDialog::createTableWidgetContents()
|
||||
{
|
||||
return;
|
||||
}
|
||||
const QgsFieldMap& fieldMap = mVectorLayer->pendingFields();
|
||||
|
||||
//combo box row, attributes titles, feature values and current merge results
|
||||
mTableWidget->setRowCount( mFeatureList.size() + 2 );
|
||||
mTableWidget->setColumnCount( fieldMap.size() );
|
||||
|
||||
//create combo boxes
|
||||
for ( int i = 0; i < fieldMap.size(); ++i )
|
||||
{
|
||||
mTableWidget->setCellWidget( 0, i, createMergeComboBox( fieldMap[i].type() ) );
|
||||
}
|
||||
//create combo boxes and insert attribute names
|
||||
const QgsFieldMap& fieldMap = mVectorLayer->pendingFields();
|
||||
|
||||
QgsFieldMap::const_iterator fieldIt = fieldMap.constBegin();
|
||||
|
||||
//insert attribute names
|
||||
int col = 0;
|
||||
for ( ; fieldIt != fieldMap.constEnd(); ++fieldIt )
|
||||
for ( QgsFieldMap::const_iterator fieldIt = fieldMap.constBegin();
|
||||
fieldIt != fieldMap.constEnd();
|
||||
++fieldIt )
|
||||
{
|
||||
if ( mVectorLayer->editType( fieldIt.key() ) == QgsVectorLayer::Hidden ||
|
||||
mVectorLayer->editType( fieldIt.key() ) == QgsVectorLayer::Immutable )
|
||||
continue;
|
||||
|
||||
mTableWidget->setColumnCount( col + 1 );
|
||||
|
||||
mTableWidget->setCellWidget( 0, col, createMergeComboBox( fieldIt->type() ) );
|
||||
|
||||
QTableWidgetItem *item = new QTableWidgetItem( fieldIt.value().name() );
|
||||
item->setData( Qt::UserRole, fieldIt.key() );
|
||||
mTableWidget->setHorizontalHeaderItem( col++, item );
|
||||
}
|
||||
|
||||
//insert the attribute values
|
||||
int currentRow = 1;
|
||||
QStringList verticalHeaderLabels; //the id column is in the
|
||||
verticalHeaderLabels << tr( "Id" );
|
||||
|
||||
for ( int i = 0; i < mFeatureList.size(); ++i )
|
||||
{
|
||||
verticalHeaderLabels << QString::number( mFeatureList[i].id() );
|
||||
QgsAttributeMap currentAttributeMap = mFeatureList[i].attributeMap();
|
||||
QgsAttributeMap::const_iterator currentMapIt = currentAttributeMap.constBegin();
|
||||
int col = 0;
|
||||
for ( ; currentMapIt != currentAttributeMap.constEnd(); ++currentMapIt )
|
||||
|
||||
const QgsAttributeMap &attrs = mFeatureList[i].attributeMap();
|
||||
|
||||
for ( int j = 0; j < mTableWidget->columnCount(); j++ )
|
||||
{
|
||||
QTableWidgetItem* attributeValItem = new QTableWidgetItem( currentMapIt.value().toString() );
|
||||
int idx = mTableWidget->horizontalHeaderItem( j )->data( Qt::UserRole ).toInt();
|
||||
|
||||
QTableWidgetItem* attributeValItem = new QTableWidgetItem( attrs[idx].toString() );
|
||||
attributeValItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
|
||||
mTableWidget->setItem( currentRow, col, attributeValItem );
|
||||
mTableWidget->setCellWidget( currentRow, col++, QgsAttributeEditor::createAttributeEditor( mTableWidget, NULL, mVectorLayer, currentMapIt.key(), currentMapIt.value() ) );
|
||||
mTableWidget->setItem( i + 1, j, attributeValItem );
|
||||
mTableWidget->setCellWidget( i + 1, j, QgsAttributeEditor::createAttributeEditor( mTableWidget, NULL, mVectorLayer, idx, attrs[idx] ) );
|
||||
}
|
||||
++currentRow;
|
||||
}
|
||||
|
||||
//merge
|
||||
@ -109,7 +116,7 @@ void QgsMergeAttributesDialog::createTableWidgetContents()
|
||||
mTableWidget->setVerticalHeaderLabels( verticalHeaderLabels );
|
||||
|
||||
//insert currently merged values
|
||||
for ( int i = 0; i < fieldMap.size(); ++i )
|
||||
for ( int i = 0; i < mTableWidget->columnCount(); ++i )
|
||||
{
|
||||
refreshMergedValue( i );
|
||||
}
|
||||
@ -180,7 +187,7 @@ void QgsMergeAttributesDialog::selectedRowChanged()
|
||||
|
||||
int row = selectionList[0]->row();
|
||||
|
||||
if ( !mTableWidget || !mMapCanvas || !mVectorLayer || row < 1 || row >= ( mTableWidget->rowCount() ) )
|
||||
if ( !mTableWidget || !mMapCanvas || !mVectorLayer || row < 1 || row >= mTableWidget->rowCount() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -476,17 +483,18 @@ void QgsMergeAttributesDialog::on_mRemoveFeatureFromSelectionButton_clicked()
|
||||
for ( int i = 0; i < mTableWidget->columnCount(); ++i )
|
||||
{
|
||||
QComboBox* currentComboBox = qobject_cast<QComboBox *>( mTableWidget->cellWidget( 0, i ) );
|
||||
if ( currentComboBox )
|
||||
{
|
||||
currentComboBox->blockSignals( true );
|
||||
currentComboBox->removeItem( currentComboBox->findText( tr( "feature %1" ).arg( featureId ) ) );
|
||||
currentComboBox->blockSignals( false );
|
||||
}
|
||||
if ( !currentComboBox )
|
||||
continue;
|
||||
|
||||
currentComboBox->blockSignals( true );
|
||||
currentComboBox->removeItem( currentComboBox->findText( tr( "feature %1" ).arg( featureId ) ) );
|
||||
currentComboBox->blockSignals( false );
|
||||
}
|
||||
|
||||
//finally remove the feature from mFeatureList
|
||||
QgsFeatureList::iterator f_it = mFeatureList.begin();
|
||||
for ( ; f_it != mFeatureList.end(); ++f_it )
|
||||
for ( QgsFeatureList::iterator f_it = mFeatureList.begin();
|
||||
f_it != mFeatureList.end();
|
||||
++f_it )
|
||||
{
|
||||
if ( f_it->id() == featureId )
|
||||
{
|
||||
@ -509,29 +517,22 @@ void QgsMergeAttributesDialog::createRubberBandForFeature( int featureId )
|
||||
|
||||
QgsAttributeMap QgsMergeAttributesDialog::mergedAttributesMap() const
|
||||
{
|
||||
QgsAttributeMap resultMap;
|
||||
if ( mFeatureList.size() < 1 )
|
||||
{
|
||||
return resultMap; //return empty map
|
||||
return QgsAttributeMap();
|
||||
}
|
||||
|
||||
resultMap = mFeatureList[0].attributeMap();
|
||||
int index = 0;
|
||||
QgsAttributeMap::iterator it = resultMap.begin();
|
||||
|
||||
for ( ; it != resultMap.end(); ++it )
|
||||
QgsAttributeMap resultMap;
|
||||
for ( int i = 0; i < mTableWidget->columnCount(); i++ )
|
||||
{
|
||||
QTableWidgetItem* currentItem = mTableWidget->item( mFeatureList.size() + 1, index );
|
||||
int idx = mTableWidget->horizontalHeaderItem( i )->data( Qt::UserRole ).toInt();
|
||||
|
||||
QTableWidgetItem* currentItem = mTableWidget->item( mFeatureList.size() + 1, i );
|
||||
if ( !currentItem )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
QString mergedString = currentItem->text();
|
||||
QVariant newValue( mergedString );
|
||||
resultMap.insert( it.key(), newValue );
|
||||
++index;
|
||||
|
||||
resultMap.insert( idx, currentItem->text() );
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
|
@ -169,7 +169,7 @@ QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath,
|
||||
|
||||
QgsVectorLayer::~QgsVectorLayer()
|
||||
{
|
||||
QgsDebugMsg( "In QgsVectorLayer destructor" );
|
||||
QgsDebugMsg( "entered." );
|
||||
|
||||
emit layerDeleted();
|
||||
|
||||
@ -1813,6 +1813,8 @@ bool QgsVectorLayer::addFeature( QgsFeature& f, bool alsoUpdateExtent )
|
||||
updateExtents();
|
||||
}
|
||||
|
||||
emit featureAdded( f.id() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -4509,6 +4511,7 @@ void QgsVectorLayer::redoEditCommand( QgsUndoCommand* cmd )
|
||||
for ( ; delIt != deletedFeatureIdChange.end(); ++delIt )
|
||||
{
|
||||
mDeletedFeatureIds.insert( *delIt );
|
||||
emit featureDeleted( *delIt );
|
||||
}
|
||||
|
||||
// added features
|
||||
@ -4516,6 +4519,7 @@ void QgsVectorLayer::redoEditCommand( QgsUndoCommand* cmd )
|
||||
for ( ; addIt != addedFeatures.end(); ++addIt )
|
||||
{
|
||||
mAddedFeatures.append( *addIt );
|
||||
emit featureAdded( addIt->id() );
|
||||
}
|
||||
|
||||
// changed attributes
|
||||
@ -4553,9 +4557,8 @@ void QgsVectorLayer::redoEditCommand( QgsUndoCommand* cmd )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
emit attributeValueChanged( fid, attrChIt.key(), attrChIt.value().target );
|
||||
}
|
||||
}
|
||||
|
||||
@ -4566,6 +4569,7 @@ void QgsVectorLayer::redoEditCommand( QgsUndoCommand* cmd )
|
||||
int attrIndex = attrIt.key();
|
||||
mAddedAttributeIds.insert( attrIndex );
|
||||
mUpdatedFields.insert( attrIndex, attrIt.value() );
|
||||
emit attributeAdded( attrIndex );
|
||||
}
|
||||
|
||||
// deleted attributes
|
||||
@ -4575,6 +4579,7 @@ void QgsVectorLayer::redoEditCommand( QgsUndoCommand* cmd )
|
||||
int attrIndex = dAttrIt.key();
|
||||
mDeletedAttributeIds.insert( attrIndex );
|
||||
mUpdatedFields.remove( attrIndex );
|
||||
emit attributeDeleted( attrIndex );
|
||||
}
|
||||
setModified( true );
|
||||
|
||||
@ -4598,6 +4603,7 @@ void QgsVectorLayer::undoEditCommand( QgsUndoCommand* cmd )
|
||||
int attrIndex = dAttrIt.key();
|
||||
mDeletedAttributeIds.remove( attrIndex );
|
||||
mUpdatedFields.insert( attrIndex, dAttrIt.value() );
|
||||
emit attributeAdded( attrIndex );
|
||||
}
|
||||
|
||||
// added attributes
|
||||
@ -4607,6 +4613,7 @@ void QgsVectorLayer::undoEditCommand( QgsUndoCommand* cmd )
|
||||
int attrIndex = attrIt.key();
|
||||
mAddedAttributeIds.remove( attrIndex );
|
||||
mUpdatedFields.remove( attrIndex );
|
||||
emit attributeDeleted( attrIndex );
|
||||
}
|
||||
|
||||
// geometry changes
|
||||
@ -4628,6 +4635,7 @@ void QgsVectorLayer::undoEditCommand( QgsUndoCommand* cmd )
|
||||
for ( ; delIt != deletedFeatureIdChange.end(); ++delIt )
|
||||
{
|
||||
mDeletedFeatureIds.remove( *delIt );
|
||||
emit featureAdded( *delIt );
|
||||
}
|
||||
|
||||
// added features
|
||||
@ -4640,6 +4648,7 @@ void QgsVectorLayer::undoEditCommand( QgsUndoCommand* cmd )
|
||||
if ( addedIt->id() == addIt->id() )
|
||||
{
|
||||
mAddedFeatures.erase( addedIt );
|
||||
emit featureDeleted( addIt->id() );
|
||||
break; // feature was found so move to next one
|
||||
}
|
||||
}
|
||||
@ -4675,9 +4684,15 @@ void QgsVectorLayer::undoEditCommand( QgsUndoCommand* cmd )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
emit attributeValueChanged( fid, attrChIt.key(), attrChIt.value().original );
|
||||
QVariant original = attrChIt.value().original;
|
||||
if ( attrChIt.value().isFirstChange )
|
||||
{
|
||||
QgsFeature tmp;
|
||||
mDataProvider->featureAtId( fid, tmp, false, QgsAttributeList() << attrChIt.key() );
|
||||
original = tmp.attributeMap()[ attrChIt.key()];
|
||||
}
|
||||
emit attributeValueChanged( fid, attrChIt.key(), original );
|
||||
}
|
||||
}
|
||||
setModified( true );
|
||||
|
@ -623,6 +623,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
|
||||
void editingStopped();
|
||||
void attributeAdded( int idx );
|
||||
void attributeDeleted( int idx );
|
||||
void featureAdded( int fid ); // added in 1.7
|
||||
void featureDeleted( int fid );
|
||||
void layerDeleted();
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>646</width>
|
||||
<width>763</width>
|
||||
<height>570</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -312,6 +312,19 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="mAddFeature">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Add feature</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>+</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="mOpenFieldCalculator">
|
||||
<property name="toolTip">
|
||||
|
Loading…
x
Reference in New Issue
Block a user