[QGIS Commit] r14729 - in trunk/qgis/src: app app/attributetable
app/gps core ui
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Sun Nov 21 15:09:36 EST 2010
Author: jef
Date: 2010-11-21 12:09:36 -0800 (Sun, 21 Nov 2010)
New Revision: 14729
Modified:
trunk/qgis/src/app/attributetable/qgsattributetabledelegate.cpp
trunk/qgis/src/app/attributetable/qgsattributetabledelegate.h
trunk/qgis/src/app/attributetable/qgsattributetabledialog.cpp
trunk/qgis/src/app/attributetable/qgsattributetabledialog.h
trunk/qgis/src/app/attributetable/qgsattributetablememorymodel.cpp
trunk/qgis/src/app/attributetable/qgsattributetablememorymodel.h
trunk/qgis/src/app/attributetable/qgsattributetablemodel.cpp
trunk/qgis/src/app/attributetable/qgsattributetablemodel.h
trunk/qgis/src/app/attributetable/qgsattributetableview.cpp
trunk/qgis/src/app/attributetable/qgsattributetableview.h
trunk/qgis/src/app/gps/qgsgpsinformationwidget.cpp
trunk/qgis/src/app/qgisappinterface.cpp
trunk/qgis/src/app/qgsfeatureaction.cpp
trunk/qgis/src/app/qgsfeatureaction.h
trunk/qgis/src/app/qgsidentifyresults.cpp
trunk/qgis/src/app/qgsidentifyresults.h
trunk/qgis/src/app/qgsmaptooladdfeature.cpp
trunk/qgis/src/app/qgsmaptooladdfeature.h
trunk/qgis/src/app/qgsmaptoolidentify.cpp
trunk/qgis/src/app/qgsmergeattributesdialog.cpp
trunk/qgis/src/core/qgsvectorlayer.cpp
trunk/qgis/src/core/qgsvectorlayer.h
trunk/qgis/src/ui/qgsattributetabledialog.ui
Log:
[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
Modified: trunk/qgis/src/app/attributetable/qgsattributetabledelegate.cpp
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetabledelegate.cpp 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/attributetable/qgsattributetabledelegate.cpp 2010-11-21 20:09:36 UTC (rev 14729)
@@ -52,7 +52,20 @@
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,
const QStyleOptionViewItem &option,
@@ -87,11 +100,16 @@
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
Modified: trunk/qgis/src/app/attributetable/qgsattributetabledelegate.h
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetabledelegate.h 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/attributetable/qgsattributetabledelegate.h 2010-11-21 20:09:36 UTC (rev 14729)
@@ -32,6 +32,7 @@
QgsVectorLayer *layer( const QAbstractItemModel *model ) const;
int fieldIdx( const QModelIndex &index ) const;
+ int featureId( const QModelIndex &index ) const;
public:
/** Constructor
Modified: trunk/qgis/src/app/attributetable/qgsattributetabledialog.cpp
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetabledialog.cpp 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/attributetable/qgsattributetabledialog.cpp 2010-11-21 20:09:36 UTC (rev 14729)
@@ -34,6 +34,7 @@
#include "qgslogger.h"
#include "qgsmapcanvas.h"
#include "qgsfieldcalculator.h"
+#include "qgsfeatureaction.h"
class QgsAttributeTableDock : public QDockWidget
{
@@ -99,6 +100,7 @@
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 @@
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 @@
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 @@
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_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() ) );
}
}
Modified: trunk/qgis/src/app/attributetable/qgsattributetabledialog.h
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetabledialog.h 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/attributetable/qgsattributetabledialog.h 2010-11-21 20:09:36 UTC (rev 14729)
@@ -151,6 +151,11 @@
*/
void on_mDeleteSelectedButton_clicked();
+ /**
+ * add feature
+ */
+ void addFeature();
+
void on_mHelpButton_clicked() { QgsContextHelp::run( metaObject()->className() ); }
signals:
Modified: trunk/qgis/src/app/attributetable/qgsattributetablememorymodel.cpp
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetablememorymodel.cpp 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/attributetable/qgsattributetablememorymodel.cpp 2010-11-21 20:09:36 UTC (rev 14729)
@@ -60,7 +60,6 @@
}
}
-#if 0
void QgsAttributeTableMemoryModel::featureDeleted( int fid )
{
QgsDebugMsg( "entered." );
@@ -76,7 +75,6 @@
mFeatureMap.insert( fid, f );
QgsAttributeTableModel::featureAdded( fid );
}
-#endif
void QgsAttributeTableMemoryModel::layerDeleted()
{
@@ -89,5 +87,5 @@
{
QgsDebugMsg( "entered." );
mFeatureMap[fid].changeAttribute( idx, value );
- reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
+ QgsAttributeTableModel::attributeValueChanged( fid, idx, value );
}
Modified: trunk/qgis/src/app/attributetable/qgsattributetablememorymodel.h
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetablememorymodel.h 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/attributetable/qgsattributetablememorymodel.h 2010-11-21 20:09:36 UTC (rev 14729)
@@ -40,7 +40,6 @@
QgsAttributeTableMemoryModel( QgsVectorLayer *theLayer );
protected slots:
-#if 0
/**
* Launched when a feature has been deleted
* @param fid feature id
@@ -51,7 +50,6 @@
* @param fid feature id
*/
virtual void featureAdded( int fid );
-#endif
/**
* Launched when layer has been deleted
*/
Modified: trunk/qgis/src/app/attributetable/qgsattributetablemodel.cpp
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetablemodel.cpp 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/attributetable/qgsattributetablemodel.cpp 2010-11-21 20:09:36 UTC (rev 14729)
@@ -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 @@
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 ) ) );
-#ifdef QGISDEBUG
- int idx = mIdRowMap[fid];
- QgsDebugMsg( idx );
- QgsDebugMsg( fid );
-#endif
+ 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
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 ) );
+#endif
+ return true;
}
-void QgsAttributeTableModel::featureAdded( int fid )
+void QgsAttributeTableModel::featureAdded( int fid, bool newOperation )
{
- 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() ) );
+ 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() ) );
}
-#endif
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,30 +133,17 @@
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() ) );
+ setData( index( idToRow( fid ), mAttributes.indexOf( idx ) ), value, Qt::EditRole );
}
-void QgsAttributeTableModel::layerModified( bool onlyGeometry )
-{
- if ( onlyGeometry )
- return;
-
- loadAttributes();
- loadLayer();
- emit modelChanged();
- emit headerDataChanged( Qt::Horizontal, 0, columnCount() - 1 );
-}
-
void QgsAttributeTableModel::loadAttributes()
{
if ( !mLayer )
@@ -187,26 +201,25 @@
{
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 @@
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 @@
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 @@
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();
+}
Modified: trunk/qgis/src/app/attributetable/qgsattributetablemodel.h
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetablemodel.h 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/attributetable/qgsattributetablemodel.h 2010-11-21 20:09:36 UTC (rev 14729)
@@ -82,6 +82,10 @@
*/
void reload( const QModelIndex &index1, const QModelIndex &index2 );
/**
+ * Remove rows
+ */
+ bool removeRows( int row, int count, const QModelIndex &parent = QModelIndex() );
+ /**
* Resets the model
*/
void resetModel();
@@ -104,9 +108,9 @@
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 @@
/** Execute an action */
void executeAction( int action, const QModelIndex &idx ) const;
+ void featureForm( QModelIndex& );
+
signals:
/**
* Model has been changed
@@ -151,6 +157,7 @@
* @param idx attribute index
*/
virtual void attributeDeleted( int idx );
+ protected slots:
/**
* Launched when attribute value has been changed
* @param fid feature id
@@ -159,15 +166,6 @@
*/
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 @@
/**
* 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
*/
Modified: trunk/qgis/src/app/attributetable/qgsattributetableview.cpp
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetableview.cpp 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/attributetable/qgsattributetableview.cpp 2010-11-21 20:09:36 UTC (rev 14729)
@@ -88,27 +88,32 @@
}
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 @@
{
mModel->executeAction( mAction, mFieldIdx );
}
+
+void QgsAttributeTableAction::featureForm()
+{
+ mModel->featureForm( mFieldIdx );
+}
Modified: trunk/qgis/src/app/attributetable/qgsattributetableview.h
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetableview.h 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/attributetable/qgsattributetableview.h 2010-11-21 20:09:36 UTC (rev 14729)
@@ -26,7 +26,7 @@
class QMenu;
-class QgsAttributeTableView: public QTableView
+class QgsAttributeTableView : public QTableView
{
Q_OBJECT
@@ -65,6 +65,7 @@
public slots:
void execute();
+ void featureForm();
private:
QgsAttributeTableModel *mModel;
Modified: trunk/qgis/src/app/gps/qgsgpsinformationwidget.cpp
===================================================================
--- trunk/qgis/src/app/gps/qgsgpsinformationwidget.cpp 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/gps/qgsgpsinformationwidget.cpp 2010-11-21 20:09:36 UTC (rev 14729)
@@ -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 @@
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 @@
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;
Modified: trunk/qgis/src/app/qgisappinterface.cpp
===================================================================
--- trunk/qgis/src/app/qgisappinterface.cpp 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/qgisappinterface.cpp 2010-11-21 20:09:36 UTC (rev 14729)
@@ -380,73 +380,6 @@
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();
}
Modified: trunk/qgis/src/app/qgsfeatureaction.cpp
===================================================================
--- trunk/qgis/src/app/qgsfeatureaction.cpp 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/qgsfeatureaction.cpp 2010-11-21 20:09:36 UTC (rev 14729)
@@ -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;
Modified: trunk/qgis/src/app/qgsfeatureaction.h
===================================================================
--- trunk/qgis/src/app/qgsfeatureaction.h 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/qgsfeatureaction.h 2010-11-21 20:09:36 UTC (rev 14729)
@@ -26,7 +26,8 @@
class QgsIdentifyResults;
class QgsVectorLayer;
-class QTreeWidgetItem;
+class QgsRubberBand;
+class QgsAttributeDialog;
class QgsFeatureAction : public QAction
{
@@ -34,16 +35,22 @@
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
Modified: trunk/qgis/src/app/qgsidentifyresults.cpp
===================================================================
--- trunk/qgis/src/app/qgsidentifyresults.cpp 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/qgsidentifyresults.cpp 2010-11-21 20:09:36 UTC (rev 14729)
@@ -63,7 +63,7 @@
// 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 @@
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 @@
}
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 @@
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 @@
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();
-
+ QgsFeatureAction action( tr( "Attribute changes" ), f, vlayer, idx, this );
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++ )
+ if ( action.editFeature() )
{
- 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() ) );
+ mCanvas->refresh();
}
}
-
- if ( vlayer->isEditable() )
- {
- if ( ad->exec() )
- {
- 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;
-
- mCanvas->refresh();
- }
else
{
- QgsRubberBand *rb = mRubberBands.take( featItem );
- ad->setHighlight( rb );
- ad->show();
+ action.viewFeatureForm( mRubberBands.take( featItem ) );
}
}
Modified: trunk/qgis/src/app/qgsidentifyresults.h
===================================================================
--- trunk/qgis/src/app/qgsidentifyresults.h 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/qgsidentifyresults.h 2010-11-21 20:09:36 UTC (rev 14729)
@@ -55,8 +55,8 @@
~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 @@
QMenu *mActionPopup;
QMap<QTreeWidgetItem *, QgsRubberBand * > mRubberBands;
QgsMapCanvas *mCanvas;
+ QList<QgsFeature> mFeatures;
QgsVectorLayer *vectorLayer( QTreeWidgetItem *item );
QTreeWidgetItem *featureItem( QTreeWidgetItem *item );
Modified: trunk/qgis/src/app/qgsmaptooladdfeature.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptooladdfeature.cpp 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/qgsmaptooladdfeature.cpp 2010-11-21 20:09:36 UTC (rev 14729)
@@ -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 )
Modified: trunk/qgis/src/app/qgsmaptooladdfeature.h
===================================================================
--- trunk/qgis/src/app/qgsmaptooladdfeature.h 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/qgsmaptooladdfeature.h 2010-11-21 20:09:36 UTC (rev 14729)
@@ -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 @@
virtual ~QgsMapToolAddFeature();
void canvasReleaseEvent( QMouseEvent * e );
- private:
bool addFeature( QgsVectorLayer *vlayer, QgsFeature *f );
- QMap<QgsVectorLayer *, QgsAttributeMap> mLastUsedValues;
};
Modified: trunk/qgis/src/app/qgsmaptoolidentify.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptoolidentify.cpp 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/qgsmaptoolidentify.cpp 2010-11-21 20:09:36 UTC (rev 14729)
@@ -300,7 +300,7 @@
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 ) );
Modified: trunk/qgis/src/app/qgsmergeattributesdialog.cpp
===================================================================
--- trunk/qgis/src/app/qgsmergeattributesdialog.cpp 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/app/qgsmergeattributesdialog.cpp 2010-11-21 20:09:36 UTC (rev 14729)
@@ -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 @@
{
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 )
+ //create combo boxes and insert attribute names
+ const QgsFieldMap& fieldMap = mVectorLayer->pendingFields();
+
+ int col = 0;
+ for ( QgsFieldMap::const_iterator fieldIt = fieldMap.constBegin();
+ fieldIt != fieldMap.constEnd();
+ ++fieldIt )
{
- mTableWidget->setCellWidget( 0, i, createMergeComboBox( fieldMap[i].type() ) );
- }
+ if ( mVectorLayer->editType( fieldIt.key() ) == QgsVectorLayer::Hidden ||
+ mVectorLayer->editType( fieldIt.key() ) == QgsVectorLayer::Immutable )
+ continue;
- QgsFieldMap::const_iterator fieldIt = fieldMap.constBegin();
+ mTableWidget->setColumnCount( col + 1 );
- //insert attribute names
- int col = 0;
- for ( ; fieldIt != fieldMap.constEnd(); ++fieldIt )
- {
+ 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 @@
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 @@
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 @@
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 @@
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();
+ QgsAttributeMap resultMap;
+ for ( int i = 0; i < mTableWidget->columnCount(); i++ )
+ {
+ int idx = mTableWidget->horizontalHeaderItem( i )->data( Qt::UserRole ).toInt();
- for ( ; it != resultMap.end(); ++it )
- {
- QTableWidgetItem* currentItem = mTableWidget->item( mFeatureList.size() + 1, index );
+ 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;
}
-
Modified: trunk/qgis/src/core/qgsvectorlayer.cpp
===================================================================
--- trunk/qgis/src/core/qgsvectorlayer.cpp 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/core/qgsvectorlayer.cpp 2010-11-21 20:09:36 UTC (rev 14729)
@@ -169,7 +169,7 @@
QgsVectorLayer::~QgsVectorLayer()
{
- QgsDebugMsg( "In QgsVectorLayer destructor" );
+ QgsDebugMsg( "entered." );
emit layerDeleted();
@@ -1813,6 +1813,8 @@
updateExtents();
}
+ emit featureAdded( f.id() );
+
return true;
}
@@ -4509,6 +4511,7 @@
for ( ; delIt != deletedFeatureIdChange.end(); ++delIt )
{
mDeletedFeatureIds.insert( *delIt );
+ emit featureDeleted( *delIt );
}
// added features
@@ -4516,6 +4519,7 @@
for ( ; addIt != addedFeatures.end(); ++addIt )
{
mAddedFeatures.append( *addIt );
+ emit featureAdded( addIt->id() );
}
// changed attributes
@@ -4553,9 +4557,8 @@
break;
}
}
-
}
-
+ emit attributeValueChanged( fid, attrChIt.key(), attrChIt.value().target );
}
}
@@ -4566,6 +4569,7 @@
int attrIndex = attrIt.key();
mAddedAttributeIds.insert( attrIndex );
mUpdatedFields.insert( attrIndex, attrIt.value() );
+ emit attributeAdded( attrIndex );
}
// deleted attributes
@@ -4575,6 +4579,7 @@
int attrIndex = dAttrIt.key();
mDeletedAttributeIds.insert( attrIndex );
mUpdatedFields.remove( attrIndex );
+ emit attributeDeleted( attrIndex );
}
setModified( true );
@@ -4598,6 +4603,7 @@
int attrIndex = dAttrIt.key();
mDeletedAttributeIds.remove( attrIndex );
mUpdatedFields.insert( attrIndex, dAttrIt.value() );
+ emit attributeAdded( attrIndex );
}
// added attributes
@@ -4607,6 +4613,7 @@
int attrIndex = attrIt.key();
mAddedAttributeIds.remove( attrIndex );
mUpdatedFields.remove( attrIndex );
+ emit attributeDeleted( attrIndex );
}
// geometry changes
@@ -4628,6 +4635,7 @@
for ( ; delIt != deletedFeatureIdChange.end(); ++delIt )
{
mDeletedFeatureIds.remove( *delIt );
+ emit featureAdded( *delIt );
}
// added features
@@ -4640,6 +4648,7 @@
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 @@
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 );
Modified: trunk/qgis/src/core/qgsvectorlayer.h
===================================================================
--- trunk/qgis/src/core/qgsvectorlayer.h 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/core/qgsvectorlayer.h 2010-11-21 20:09:36 UTC (rev 14729)
@@ -623,6 +623,7 @@
void editingStopped();
void attributeAdded( int idx );
void attributeDeleted( int idx );
+ void featureAdded( int fid ); // added in 1.7
void featureDeleted( int fid );
void layerDeleted();
Modified: trunk/qgis/src/ui/qgsattributetabledialog.ui
===================================================================
--- trunk/qgis/src/ui/qgsattributetabledialog.ui 2010-11-21 20:04:36 UTC (rev 14728)
+++ trunk/qgis/src/ui/qgsattributetabledialog.ui 2010-11-21 20:09:36 UTC (rev 14729)
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>646</width>
+ <width>763</width>
<height>570</height>
</rect>
</property>
@@ -313,6 +313,19 @@
</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">
<string>Open field calculator (Ctrl+I)</string>
More information about the QGIS-commit
mailing list