Skip to content
Permalink
Browse files

[GRASS] editing test

  • Loading branch information
blazek committed Oct 13, 2015
1 parent 7b9148a commit 4bd6cf1532ff85056b679591f375d8427b482bcf
@@ -1749,6 +1749,7 @@ bool QgsGrass::mapRegion( QgsGrassObject::Type type, QString gisdbase,
G_TRY
{
Map = vectNewMapStruct();
Vect_set_open_level( 2 );
level = Vect_open_old_head( Map, map.toUtf8().data(), mapset.toUtf8().data() );
}
G_CATCH( QgsGrass::Exception &e )
@@ -249,6 +249,7 @@ bool QgsGrassFeatureIterator::fetchFeature( QgsFeature& feature )
int lid = 0;
QgsFeatureId featureId = 0;
QgsAbstractGeometryV2 *oldGeometry = 0;
int cidxFieldIndex = mSource->mLayer->cidxFieldIndex();

#ifdef QGISDEBUG
if ( mSource->mEditing )
@@ -313,9 +314,9 @@ bool QgsGrassFeatureIterator::fetchFeature( QgsFeature& feature )
cat = 0;
type = 0;
lid = 0;
QgsDebugMsgLevel( QString( "mNextLid = %1 mNextCidx = %2 numLines() = %3 mCidxFieldIndex = %4 cidxFieldNumCats() = %5" )
QgsDebugMsgLevel( QString( "mNextLid = %1 mNextCidx = %2 numLines() = %3 cidxFieldIndex() = %4 cidxFieldNumCats() = %5" )
.arg( mNextLid ).arg( mNextCidx ).arg( mSource->mLayer->map()->numLines() )
.arg( mSource->mCidxFieldIndex ).arg( mSource->mLayer->cidxFieldNumCats() ), 3 );
.arg( mSource->mLayer->cidxFieldIndex() ).arg( mSource->mLayer->cidxFieldNumCats() ), 3 );
if ( mSource->mEditing )
{
// TODO should be numLines before editing started (?), but another layer
@@ -421,12 +422,12 @@ bool QgsGrassFeatureIterator::fetchFeature( QgsFeature& feature )
int tmpLid, tmpType, tmpCat;

int numFields = Vect_cidx_get_num_fields( mSource->map() );
if ( mSource->mCidxFieldIndex < 0 || mSource->mCidxFieldIndex >= numFields )
if ( cidxFieldIndex < 0 || cidxFieldIndex >= numFields )
{
QgsDebugMsg( QString( "mCidxFieldIndex %1 out of range (0,%2)" ).arg( mSource->mCidxFieldIndex ).arg( numFields - 1 ) );
QgsDebugMsg( QString( "cidxFieldIndex %1 out of range (0,%2)" ).arg( cidxFieldIndex ).arg( numFields - 1 ) );
break;
}
Vect_cidx_get_cat_by_index( mSource->map(), mSource->mCidxFieldIndex, mNextCidx++, &tmpCat, &tmpType, &tmpLid );
Vect_cidx_get_cat_by_index( mSource->map(), cidxFieldIndex, mNextCidx++, &tmpCat, &tmpType, &tmpLid );
// Warning: selection array is only of type line/area of current layer -> check type first
if ( !( tmpType & mSource->mGrassType ) )
{
@@ -691,7 +692,6 @@ QgsGrassFeatureSource::QgsGrassFeatureSource( const QgsGrassProvider* p )
, mLayerType( p->mLayerType )
, mGrassType( p->mGrassType )
, mQgisType( p->mQgisType )
, mCidxFieldIndex( p->mCidxFieldIndex )
, mFields( p->fields() )
, mEncoding( p->mEncoding )
, mEditing( p->mEditBuffer )
@@ -56,8 +56,6 @@ class GRASS_LIB_EXPORT QgsGrassFeatureSource : public QgsAbstractFeatureSource

QGis::WkbType mQgisType; // WKBPoint, WKBLineString, ...

int mCidxFieldIndex; // !UPDATE! Index for layerField in category index or -1 if no such field

QgsFields mFields;
QTextCodec* mEncoding;

@@ -81,7 +81,6 @@ QgsGrassProvider::QgsGrassProvider( QString uri )
, mQgisType( QGis::WKBUnknown )
, mLayer( 0 )
, mMapVersion( 0 )
, mCidxFieldIndex( -1 )
, mNumberFeatures( 0 )
, mEditBuffer( 0 )
, mEditLayer( 0 )
@@ -226,9 +225,9 @@ QgsGrassProvider::QgsGrassProvider( QString uri )

// TODO: types according to database
mNativeTypes
<< QgsVectorDataProvider::NativeType( tr( "Whole number (integer)" ), "integer", QVariant::Int, 1, 10 )
<< QgsVectorDataProvider::NativeType( tr( "Decimal number (real)" ), "double precision", QVariant::Double, 1, 20, 0, 15 )
<< QgsVectorDataProvider::NativeType( tr( "Text, limited variable length (varchar)" ), "varchar", QVariant::String, 1, 255, -1, -1 );
<< QgsVectorDataProvider::NativeType( tr( "Whole number (integer)" ), "integer", QVariant::Int, -1, -1, -1, -1 )
<< QgsVectorDataProvider::NativeType( tr( "Decimal number (real)" ), "double precision", QVariant::Double, -1, -1, -1, -1 )
<< QgsVectorDataProvider::NativeType( tr( "Text, limited variable length (varchar)" ), "varchar", QVariant::String, 1, -1, -1, -1 );
// TODO:
// << QgsVectorDataProvider::NativeType( tr( "Date" ), "date", QVariant::Date, 8, 8 );

@@ -299,8 +298,8 @@ bool QgsGrassProvider::openLayer()
void QgsGrassProvider::loadMapInfo()
{
// Getting the total number of features in the layer
int cidxFieldIndex = -1;
mNumberFeatures = 0;
mCidxFieldIndex = -1;
if ( mLayerType == TOPO_POINT )
{
mNumberFeatures = Vect_get_num_primitives( map(), GV_POINTS );
@@ -317,8 +316,8 @@ void QgsGrassProvider::loadMapInfo()
{
if ( mLayerField >= 0 )
{
mCidxFieldIndex = Vect_cidx_get_field_index( map(), mLayerField );
if ( mCidxFieldIndex >= 0 )
cidxFieldIndex = Vect_cidx_get_field_index( map(), mLayerField );
if ( cidxFieldIndex >= 0 )
{
mNumberFeatures = Vect_cidx_get_type_count( map(), mLayerField, mGrassType );
}
@@ -329,7 +328,7 @@ void QgsGrassProvider::loadMapInfo()
mNumberFeatures = 0;
}
}
QgsDebugMsg( QString( "mNumberFeatures = %1 mCidxFieldIndex = %2" ).arg( mNumberFeatures ).arg( mCidxFieldIndex ) );
QgsDebugMsg( QString( "mNumberFeatures = %1 cidxFieldIndex = %2" ).arg( mNumberFeatures ).arg( cidxFieldIndex ) );
}

void QgsGrassProvider::update()
@@ -1093,6 +1092,7 @@ void QgsGrassProvider::startEditing( QgsVectorLayer *vectorLayer )

// let qgis know (attribute table etc.) that we added topo symbol field
vectorLayer->updateFields();
mEditLayerFields = vectorLayer->fields();

// TODO: enable cats editing once all consequences are implemented
// disable cat and topo symbol editing
@@ -1242,15 +1242,15 @@ void QgsGrassProvider::onFeatureAdded( QgsFeatureId fid )
}
if ( newCat == 0 )
{
QgsDebugMsg( QString( "get new cat for mCidxFieldIndex = %1" ).arg( mCidxFieldIndex ) );
if ( mCidxFieldIndex == -1 )
QgsDebugMsg( QString( "get new cat for cidxFieldIndex() = %1" ).arg( mLayer->cidxFieldIndex() ) );
if ( mLayer->cidxFieldIndex() == -1 )
{
// No features with this field yet in map
newCat = 1;
}
else
{
newCat = cidxGetMaxCat( mCidxFieldIndex ) + 1;
newCat = cidxGetMaxCat( mLayer->cidxFieldIndex() ) + 1;
}
}
QgsDebugMsg( QString( "newCat = %1" ).arg( newCat ) );
@@ -1456,17 +1456,10 @@ void QgsGrassProvider::onFeatureAdded( QgsFeatureId fid )

QgsDebugMsg( QString( "newLine = %1" ).arg( newLid ) );

if ( mCidxFieldIndex == -1 && type != GV_BOUNDARY )
{
// first feature in this layer
mCidxFieldIndex = Vect_cidx_get_field_index( map(), mLayerField );
QgsDebugMsg( QString( "new mCidxFieldIndex = %1" ).arg( mCidxFieldIndex ) );
}

setAddedFeaturesSymbol();
}
QgsDebugMsg( QString( "mCidxFieldIndex = %1 cidxFieldNumCats() = %2" )
.arg( mCidxFieldIndex ).arg( mLayer->cidxFieldNumCats() ) );
QgsDebugMsg( QString( "mLayer->cidxFieldIndex() = %1 cidxFieldNumCats() = %2" )
.arg( mLayer->cidxFieldIndex() ).arg( mLayer->cidxFieldNumCats() ) );
}

void QgsGrassProvider::onFeatureDeleted( QgsFeatureId fid )
@@ -1726,34 +1719,40 @@ void QgsGrassProvider::onAttributeAdded( int idx )
mLayer->addColumn( mEditLayer->fields()[idx], error );
if ( !error.isEmpty() )
{
QgsDebugMsg( error );
QgsGrass::warning( error );
// TODO: remove the column somehow from the layer/buffer - undo?
}
else
{
mEditLayerFields = mEditLayer->fields();
}
}

void QgsGrassProvider::onAttributeDeleted( int idx )
{
Q_UNUSED( idx );
QgsDebugMsg( QString( "idx = %1" ).arg( idx ) );
// The index of deleted field is useless because the field was already removed from mEditLayer->fields().
// Find deleted field.
QgsField deletedField;
for ( int i = 0; i < mLayer->fields().size(); i++ )
QgsDebugMsg( QString( "idx = %1 mEditLayerFields.size() = %2" ).arg( idx ).arg( mEditLayerFields.size() ) );
// The field was already removed from mEditLayer->fields() -> using stored last version of fields
if ( idx < 0 || idx >= mEditLayerFields.size() )
{
QgsField field = mLayer->fields()[i];
if ( mEditLayer->fields().indexFromName( field.name() ) == -1 )
{
deletedField = field;
}
QgsDebugMsg( "index out of range" );
return;
}
QgsField deletedField = mEditLayerFields.at( idx );
QgsDebugMsg( QString( "deletedField.name() = %1" ).arg( deletedField.name() ) );

QString error;
mLayer->deleteColumn( deletedField, error );
if ( !error.isEmpty() )
{
QgsDebugMsg( error );
QgsGrass::warning( error );
// TODO: get back the column somehow to the layer/buffer - undo?
}
else
{
mEditLayerFields = mEditLayer->fields();
}
}

void QgsGrassProvider::setAddedFeaturesSymbol()
@@ -1843,13 +1842,20 @@ int QgsGrassProvider::cidxGetFieldNumber( int idx )

int QgsGrassProvider::cidxGetMaxCat( int idx )
{
QgsDebugMsg( QString( "idx = %1" ).arg( idx ) );
if ( idx < 0 || idx >= cidxGetNumFields() )
{
QgsDebugMsg( QString( "idx %1 out of range (0,%2)" ).arg( idx ).arg( cidxGetNumFields() - 1 ) );
return 0;
}

int ncats = Vect_cidx_get_num_cats_by_index( map(), idx );
QgsDebugMsg( QString( "ncats = %1" ).arg( ncats ) );

if ( ncats == 0 )
{
return 0;
}

int cat, type, id;
Vect_cidx_get_cat_by_index( map(), idx, ncats - 1, &cat, &type, &id );
@@ -421,9 +421,6 @@ class GRASS_LIB_EXPORT QgsGrassProvider : public QgsVectorDataProvider
// The version of the map for which the instance was last time updated
int mMapVersion;

// Index for layerField in category index or -1 if no such field
int mCidxFieldIndex;

bool mValid;
long mNumberFeatures;

@@ -461,6 +458,9 @@ class GRASS_LIB_EXPORT QgsGrassProvider : public QgsVectorDataProvider
// next digitized feature GRASS type
int mNewFeatureType;

// Last version of layer fields during editing, updated after addAttribute and deleteAttribute
QgsFields mEditLayerFields;

// points and cats used only for editing
struct line_pnts *mPoints;
struct line_cats *mCats;
@@ -219,7 +219,7 @@ bool QgsGrassVector::openHead()

/* Open vector */
QgsGrass::resetError();
//Vect_set_open_level( 2 );
Vect_set_open_level( 2 );

// TODO: We are currently using vectDestroyMapStruct in G_CATCH blocks because we know
// that it cannot call another G_fatal_error, but once we switch to hypothetical Vect_destroy_map_struct
@@ -136,7 +136,7 @@ bool QgsGrassVectorMap::openMap()
int level = -1;
G_TRY
{
//Vect_set_open_level( 2 );
Vect_set_open_level( 2 );
level = Vect_open_old_head( mMap, mGrassObject.name().toUtf8().data(), mGrassObject.mapset().toUtf8().data() );
Vect_close( mMap );
}
@@ -235,6 +235,7 @@ bool QgsGrassVectorMap::startEdit()
G_TRY
{
Vect_close( mMap );
Vect_set_open_level( 2 );
level = Vect_open_update( mMap, mGrassObject.name().toUtf8().data(), mGrassObject.mapset().toUtf8().data() );
if ( level < 2 )
{
@@ -116,6 +116,7 @@ void QgsGrassVectorMapLayer::load()
QString error = QString( "Cannot open database %1 by driver %2" ).arg( mFieldInfo->database ).arg( mFieldInfo->driver );
G_TRY
{
setMapset();
databaseDriver = db_start_driver_open_database( mFieldInfo->driver, mFieldInfo->database );
}
G_CATCH( QgsGrass::Exception &e )
@@ -839,7 +840,8 @@ void QgsGrassVectorMapLayer::insertAttributes( int cat, const QgsFeature &featur
}
}

QString query = QString( "INSERT INTO %1 ( %2 ) VALUES ( %3 )" ).arg( mFieldInfo->table ).arg( names.join( ", " ) ).arg( values.join( "," ) );
QString query = QString( "INSERT INTO %1 ( %2 ) VALUES ( %3 )" ).arg( mFieldInfo->table )
.arg( names.join( ", " ) ).arg( values.join( "," ) );
executeSql( query, error );
if ( error.isEmpty() )
{
@@ -1031,7 +1033,7 @@ bool QgsGrassVectorMapLayer::isOrphan( int cat, QString &error )
QgsDebugMsg( QString( "mField = %1 cat = %2" ).arg( mField ).arg( cat ) );


// Check first if anothe return "Cannot open database";r line with such cat exists
// Check first if another line with such cat exists
int fieldIndex = Vect_cidx_get_field_index( mMap->map(), mField );
if ( fieldIndex >= 0 )
{
@@ -1053,19 +1055,41 @@ void QgsGrassVectorMapLayer::changeAttributeValue( int cat, QgsField field, QVar
{
QgsDebugMsg( QString( "cat = %1 field.name() = %2 value = %3" ).arg( cat ).arg( field.name() ).arg( value.toString() ) );


if ( !mDriver )
{
error = tr( "Driver is not open" );
QgsDebugMsg( error );
return;
}

bool exists = recordExists( cat, error );
if ( !error.isEmpty() )
{
error = tr( "Cannot check if record exists" ) + ": " + error;
return;
}

dbString dbstr;
db_init_string( &dbstr );
QString valueString = quotedValue( value );
QString query = QString( "UPDATE %1 SET %2 = %3 WHERE %4 = %5" ).arg( mFieldInfo->table )
.arg( field.name() ).arg( valueString ).arg( mFieldInfo->key ).arg( cat );
QString query;

if ( exists )
{
query = QString( "UPDATE %1 SET %2 = %3 WHERE %4 = %5" ).arg( mFieldInfo->table )
.arg( field.name() ).arg( valueString ).arg( mFieldInfo->key ).arg( cat );
}
else
{
QStringList names;
QStringList values;
names << mFieldInfo->key;
values << QString::number( cat );
names << field.name();
values << quotedValue( value );
query = QString( "INSERT INTO %1 ( %2 ) VALUES ( %3 )" ).arg( mFieldInfo->table )
.arg( names.join( ", " ) ).arg( values.join( "," ) );
}

QgsDebugMsg( QString( "query: %1" ).arg( query ) );

@@ -1085,14 +1109,31 @@ void QgsGrassVectorMapLayer::changeAttributeValue( int cat, QgsField field, QVar
QgsDebugMsg( QString( "SQL: %1" ).arg( db_get_string( &dbstr ) ) );

int ret = db_execute_immediate( mDriver, &dbstr );
db_free_string( &dbstr );
if ( ret != DB_OK )
{
error = QString::fromLatin1( db_get_error_msg() );
QgsDebugMsg( error );
return;
}
db_free_string( &dbstr );

// TODO: update cached attributes because another feature may share the same cat

return;
// update cached attributes which may be used by another feature/layer
if ( !mAttributes.contains( cat ) )
{
QgsDebugMsgLevel( QString( "cat %1 not found in attributes -> insert" ).arg( cat ), 3 );
QList<QVariant> values;
for ( int i = 0; i < mAttributeFields.size(); i++ )
{
values << QVariant();
}
mAttributes.insert( cat, values );
}
int index = mAttributeFields.indexFromName( field.name() );
if ( index == -1 )
{
error = tr( "Field %1 not found in cached attributes" ).arg( field.name() );
return;
}
mAttributes[cat][index] = value;
}

0 comments on commit 4bd6cf1

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