Skip to content
Permalink
Browse files

[FEATURE] improve attribute handling

- optionally reuse entered attribute values for next digitized feature
- allow merging/assigning attribute values to a set of features


git-svn-id: http://svn.osgeo.org/qgis/trunk@14599 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
jef
jef committed Nov 13, 2010
1 parent ee82cf4 commit b1bf738ad83a0a673c47b989fa9059d79656fc38
@@ -44,6 +44,7 @@
<file>themes/newgis/mActionMeasure.png</file>
<file>themes/newgis/mActionMeasureArea.png</file>
<file>themes/newgis/mActionMergeFeatures.png</file>
<file>themes/newgis/mActionMergeFeatureAttributes.png</file>
<file>themes/newgis/mActionMoveFeature.png</file>
<file>themes/newgis/mActionMoveItemContent.png</file>
<file>themes/newgis/mActionMoveVertex.png</file>
@@ -165,6 +166,7 @@
<file>themes/default/mActionMeasureAngle.png</file>
<file>themes/default/mActionMeasureArea.png</file>
<file>themes/default/mActionMergeFeatures.png</file>
<file>themes/default/mActionMergeFeatureAttributes.png</file>
<file>themes/default/mActionMoveFeature.png</file>
<file>themes/default/mActionMoveItemContent.png</file>
<file>themes/default/mActionMoveItemsToBottom.png</file>
@@ -332,6 +334,7 @@
<file>themes/gis/mActionMeasureAngle.png</file>
<file>themes/gis/mActionMeasureArea.png</file>
<file>themes/gis/mActionMergeFeatures.png</file>
<file>themes/gis/mActionMergeFeatureAttributes.png</file>
<file>themes/gis/mActionMoveFeature.png</file>
<file>themes/gis/mActionMoveItemContent.png</file>
<file>themes/gis/mActionMoveItemsToBottom.png</file>
Binary file not shown.
Binary file not shown.
Binary file not shown.

Large diffs are not rendered by default.

@@ -612,6 +612,8 @@ class QgisApp : public QMainWindow
void deletePart();
//! merges the selected features together
void mergeSelectedFeatures();
//! merges the attributes of selected features
void mergeAttributesOfSelectedFeatures();
//! provides operations with nodes
void nodeTool();
//! activates the rotate points tool
@@ -894,6 +896,7 @@ class QgisApp : public QMainWindow
QAction *mActionDeleteRing;
QAction *mActionDeletePart;
QAction *mActionMergeFeatures;
QAction *mActionMergeFeatureAttributes;
QAction *mActionNodeTool;
QAction *mActionRotatePointSymbols;
QAction *mActionEditSeparator3;
@@ -31,10 +31,6 @@
#include <QMouseEvent>
#include <QSettings>

#ifdef Q_OS_WIN
#include <qgisapp.h>
#endif

QgsMapToolAddFeature::QgsMapToolAddFeature( QgsMapCanvas* canvas, CaptureMode tool ): QgsMapToolCapture( canvas, tool )
{

@@ -45,8 +41,79 @@ 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;
}

void QgsMapToolAddFeature::canvasReleaseEvent( QMouseEvent * e )
{
QgsDebugMsg( "entered." );

QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() );

if ( !vlayer )
@@ -160,45 +227,21 @@ void QgsMapToolAddFeature::canvasReleaseEvent( QMouseEvent * e )
}

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" ) );

// show the dialog to enter attribute values
QSettings settings;
bool isDisabledAttributeValuesDlg = settings.value( "/qgis/digitizing/disable_enter_attribute_values_dialog", false ).toBool();
if ( isDisabledAttributeValuesDlg )
if ( addFeature( vlayer, f ) )
{
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;
delete f;
vlayer->destroyEditCommand();
}

mCanvas->refresh();
}

}
else if ( mode() == CaptureLine || mode() == CapturePolygon )
{
@@ -395,7 +438,7 @@ void QgsMapToolAddFeature::canvasReleaseEvent( QMouseEvent * e )
position += sizeof( int );
double x, y;
QList<QgsPoint>::iterator it;
for ( it = begin(); it != end(); ++it )//add the captured points to the polygon
for ( it = begin(); it != end(); ++it ) //add the captured points to the polygon
{
QgsPoint savePoint = *it;
x = savePoint.x();
@@ -441,53 +484,26 @@ void QgsMapToolAddFeature::canvasReleaseEvent( QMouseEvent * e )
{
QMessageBox::critical( 0, tr( "Error" ), tr( "An error was reported during intersection removal" ) );
}


}

// 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() ) );
}
vlayer->beginEditCommand( tr( "Feature added" ) );

QSettings settings;
bool isDisabledAttributeValuesDlg = settings.value( "/qgis/digitizing/disable_enter_attribute_values_dialog", false ).toBool();
if ( isDisabledAttributeValuesDlg )
if ( addFeature( vlayer, f ) )
{
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 )
{
//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->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;
vlayer->destroyEditCommand();
}
delete f;

stopCapturing();
}
@@ -15,6 +15,7 @@
/* $Id$ */

#include "qgsmaptoolcapture.h"
#include "qgsfeature.h"

/**This tool adds new point/line/polygon features to already existing vector layers*/
class QgsMapToolAddFeature: public QgsMapToolCapture
@@ -24,4 +25,8 @@ class QgsMapToolAddFeature: public QgsMapToolCapture
QgsMapToolAddFeature( QgsMapCanvas* canvas, CaptureMode mode );
virtual ~QgsMapToolAddFeature();
void canvasReleaseEvent( QMouseEvent * e );

private:
bool addFeature( QgsVectorLayer *vlayer, QgsFeature *f );
QMap<QgsVectorLayer *, QgsAttributeMap> mLastUsedValues;
};
@@ -352,6 +352,7 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) :
}
mMarkerSizeSpinBox->setValue( settings.value( "/qgis/digitizing/marker_size", 3 ).toInt() );

chkReuseLastValues->setChecked( settings.value( "/qgis/digitizing/reuseLastValues", false ).toBool() );
chkDisableAttributeValuesDlg->setChecked( settings.value( "/qgis/digitizing/disable_enter_attribute_values_dialog", false ).toBool() );

#ifdef Q_WS_MAC //MH: disable incremental update on Mac for now to avoid problems with resizing
@@ -659,6 +660,7 @@ void QgsOptions::saveOptions()
}
settings.setValue( "/qgis/digitizing/marker_size", ( mMarkerSizeSpinBox->value() ) );

settings.setValue( "/qgis/digitizing/reuseLastValues", chkReuseLastValues->isChecked() );
settings.setValue( "/qgis/digitizing/disable_enter_attribute_values_dialog", chkDisableAttributeValuesDlg->isChecked() );

//
@@ -1130,7 +1130,7 @@ void QgsVectorLayer::drawVertexMarker( double x, double y, QPainter& p, QgsVecto
{
p.setPen( QColor( 50, 100, 120, 200 ) );
p.setBrush( QColor( 200, 200, 210, 120 ) );
p.drawEllipse( x - m, y - m, m*2 + 1, m*2 + 1 );
p.drawEllipse( x - m, y - m, m * 2 + 1, m * 2 + 1 );
}
else if ( type == QgsVectorLayer::Cross )
{
@@ -1358,7 +1358,7 @@ QGis::WkbType QgsVectorLayer::wkbType() const

QgsRectangle QgsVectorLayer::boundingBoxOfSelected()
{
if ( mSelectedFeatureIds.size() == 0 )//no selected features
if ( mSelectedFeatureIds.size() == 0 ) //no selected features
{
return QgsRectangle( 0, 0, 0, 0 );
}
@@ -2157,7 +2157,7 @@ int QgsVectorLayer::splitFeatures( const QList<QgsPoint>& splitLine, bool topolo
QgsFeatureList featureList;
const QgsFeatureIds selectedIds = selectedFeaturesIds();

if ( selectedIds.size() > 0 )//consider only the selected features if there is a selection
if ( selectedIds.size() > 0 ) //consider only the selected features if there is a selection
{
featureList = selectedFeatures();
}
@@ -3838,8 +3838,6 @@ int QgsVectorLayer::snapWithContext( const QgsPoint& startPoint, double snapping

if ( mCachedGeometriesRect.contains( searchRect ) )
{
QgsDebugMsg( "Using cached geometries for snapping." );

QgsGeometryMap::iterator it = mCachedGeometries.begin();
for ( ; it != mCachedGeometries.end() ; ++it )
{
@@ -4046,8 +4044,8 @@ void QgsVectorLayer::drawFeature( QgsRenderContext &renderContext,
}

//QPointF pt(x - (marker->width()/2), y - (marker->height()/2));
QPointF pt( x*renderContext.rasterScaleFactor() - ( marker->width() / 2 ),
y*renderContext.rasterScaleFactor() - ( marker->height() / 2 ) );
QPointF pt( x * renderContext.rasterScaleFactor() - ( marker->width() / 2 ),
y * renderContext.rasterScaleFactor() - ( marker->height() / 2 ) );

p->save();
//p->scale(markerScaleFactor,markerScaleFactor);
@@ -4082,8 +4080,8 @@ void QgsVectorLayer::drawFeature( QgsRenderContext &renderContext,
transformPoint( x, y, &renderContext.mapToPixel(), renderContext.coordinateTransform() );
//QPointF pt(x - (marker->width()/2), y - (marker->height()/2));
//QPointF pt(x/markerScaleFactor - (marker->width()/2), y/markerScaleFactor - (marker->height()/2));
QPointF pt( x*renderContext.rasterScaleFactor() - ( marker->width() / 2 ),
y*renderContext.rasterScaleFactor() - ( marker->height() / 2 ) );
QPointF pt( x * renderContext.rasterScaleFactor() - ( marker->width() / 2 ),
y * renderContext.rasterScaleFactor() - ( marker->height() / 2 ) );
//QPointF pt( x, y );

// Work around a +/- 32768 limitation on coordinates
@@ -1283,6 +1283,16 @@
<string>Enter attribute values</string>
</property>
<layout class="QHBoxLayout">
<item>
<widget class="QCheckBox" name="chkReuseLastValues">
<property name="text">
<string>Reuse last entered attribute values</string>
</property>
<property name="tristate">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="chkDisableAttributeValuesDlg">
<property name="text">

0 comments on commit b1bf738

Please sign in to comment.
You can’t perform that action at this time.