void QgsMapToolAddPart::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { //check if we operate on a vector layer QgsVectorLayer *vlayer = currentVectorLayer(); if ( !vlayer ) { notifyNotVectorLayer(); return; } if ( !vlayer->isEditable() ) { notifyNotEditableLayer(); return; } bool isGeometryEmpty = false; QgsFeatureList selectedFeatures = vlayer->selectedFeatures(); if ( !selectedFeatures.isEmpty() && selectedFeatures.at( 0 ).geometry().isNull() ) isGeometryEmpty = true; if ( !checkSelection() ) { stopCapturing(); return; } int errorCode = 0; switch ( mode() ) { case CapturePoint: { QgsPoint layerPoint; QgsPointXY mapPoint = e->mapPoint(); if ( nextPoint( QgsPoint( mapPoint ), layerPoint ) != 0 ) { QgsDebugMsg( "nextPoint failed" ); return; } vlayer->beginEditCommand( tr( "Part added" ) ); errorCode = vlayer->addPart( QgsPointSequence() << layerPoint ); } break; case CaptureLine: case CapturePolygon: { //add point to list and to rubber band if ( e->button() == Qt::LeftButton ) { int error = addVertex( e->mapPoint(), e->mapPointMatch() ); if ( error == 1 ) { QgsDebugMsg( "current layer is not a vector layer" ); return; } else if ( error == 2 ) { //problem with coordinate transformation emit messageEmitted( tr( "Coordinate transform error. Cannot transform the point to the layers coordinate system" ), Qgis::Warning ); return; } startCapturing(); return; } else if ( e->button() != Qt::RightButton ) { deleteTempRubberBand(); return; } if ( !isCapturing() ) return; if ( mode() == CapturePolygon ) { closePolygon(); } //does compoundcurve contain circular strings? //does provider support circular strings? bool hasCurvedSegments = captureCurve()->hasCurvedSegments(); bool providerSupportsCurvedSegments = vlayer->dataProvider()->capabilities() & QgsVectorDataProvider::CircularGeometries; QgsCurve *curveToAdd = nullptr; if ( hasCurvedSegments && providerSupportsCurvedSegments ) { curveToAdd = captureCurve()->clone(); } else { curveToAdd = captureCurve()->curveToLine(); } vlayer->beginEditCommand( tr( "Part added" ) ); if ( mode() == CapturePolygon ) { //avoid intersections QgsCurvePolygon *cp = new QgsCurvePolygon(); cp->setExteriorRing( curveToAdd ); QgsGeometry *geom = new QgsGeometry( cp ); geom->avoidIntersections( QgsProject::instance()->avoidIntersectionsLayers() ); const QgsCurvePolygon *cpGeom = qgsgeometry_cast<const QgsCurvePolygon *>( geom->constGet() ); if ( !cpGeom ) { stopCapturing(); delete geom; vlayer->destroyEditCommand(); return; } errorCode = vlayer->addPart( cpGeom->exteriorRing()->clone() ); delete geom; } else { errorCode = vlayer->addPart( curveToAdd ); } stopCapturing(); } break; default: Q_ASSERT( !"invalid capture mode" ); errorCode = 6; break; } QString errorMessage; switch ( errorCode ) { case 0: { // remove previous message emit messageDiscarded(); //add points to other features to keep topology up-to-date bool topologicalEditing = QgsProject::instance()->topologicalEditing(); if ( topologicalEditing ) { addTopologicalPoints( points() ); } vlayer->endEditCommand(); vlayer->triggerRepaint(); if ( ( !isGeometryEmpty ) && QgsWkbTypes::isSingleType( vlayer->wkbType() ) ) { emit messageEmitted( tr( "Add part: Feature geom is single part and you've added more than one" ), Qgis::Warning ); } return; } case 1: errorMessage = tr( "Selected feature is not multi part." ); break; case 2: errorMessage = tr( "New part's geometry is not valid." ); break; case 3: errorMessage = tr( "New polygon ring not disjoint with existing polygons." ); break; case 4: errorMessage = tr( "No feature selected. Please select a feature with the selection tool or in the attribute table" ); break; case 5: errorMessage = tr( "Several features are selected. Please select only one feature to which an island should be added." ); break; case 6: errorMessage = tr( "Selected geometry could not be found" ); break; } emit messageEmitted( errorMessage, Qgis::Warning ); vlayer->destroyEditCommand(); }
bool QgsDb2Provider::addFeatures( QgsFeatureList & flist ) { QgsDebugMsg( "mGeometryColType: " + mGeometryColType ); int writeCount = 0; bool copyOperation = false; if ( !mDatabase.isOpen() ) { QString errMsg; mDatabase = getDatabase( mConnInfo, errMsg ); if ( !errMsg.isEmpty() ) { QgsDebugMsg( "getDatabase failed: " + errMsg ); return false; } } if ( !mDatabase.transaction() ) { QgsDebugMsg( "transaction failed" ); return false; } QSqlQuery query = QSqlQuery( mDatabase ); query.setForwardOnly( true ); QSqlQuery queryFid = QSqlQuery( mDatabase ); queryFid.setForwardOnly( true ); QgsFeature it = flist.at( 0 ); QString statement; QString values; statement = QString( "INSERT INTO %1.%2 (" ).arg( mSchemaName, mTableName ); bool first = true; // Get the first geometry and its wkbType as when we are doing drag/drop, // the wkbType is not passed to the DB2 provider from QgsVectorLayerImport // Can't figure out how to resolved "unreferenced" wkbType compile message // Don't really do anything with it at this point #if 0 QgsGeometry *geom = it.geometry(); QgsWkbTypes::Type wkbType = geom->wkbType(); QgsDebugMsg( QString( "wkbType: %1" ).arg( wkbType ) ); QgsDebugMsg( QString( "mWkbType: %1" ).arg( mWkbType ) ); #endif QgsAttributes attrs = it.attributes(); QgsDebugMsg( QString( "attrs.count: %1" ).arg( attrs.count() ) ); QgsDebugMsg( QString( "fields.count: %1" ).arg( mAttributeFields.count() ) ); if ( mAttributeFields.count() == ( attrs.count() + 1 ) ) { copyOperation = true; // FID is first field but no attribute in attrs } else if ( mAttributeFields.count() != attrs.count() ) { QgsDebugMsg( "Count mismatch - failing" ); return false; } if ( attrs.count() != mAttributeFields.count() ) { QgsDebugMsg( "field counts don't match" ); // return false; } for ( int i = 0; i < mAttributeFields.count(); ++i ) { QgsField fld = mAttributeFields.at( i ); QgsDebugMsg( QString( "i: %1; got field: %2" ).arg( i ).arg( fld.name() ) ); if ( fld.name().isEmpty() ) continue; // invalid if ( mFidColName == fld.name() ) continue; // skip identity field // if ( mDefaultValues.contains( i ) && mDefaultValues[i] == attrs.at( i ) ) // continue; // skip fields having default values if ( !first ) { statement += ','; values += ','; } else first = false; statement += QString( "%1" ).arg( fld.name() ); values += QString( "?" ); } // append geometry column name if ( !mGeometryColName.isEmpty() ) { if ( !first ) { statement += ','; values += ','; } statement += QString( "%1" ).arg( mGeometryColName ); values += QString( "db2gse.%1(CAST (%2 AS BLOB(2M)),%3)" ) .arg( mGeometryColType, QString( "?" ), QString::number( mSRId ) ); } QgsDebugMsg( statement ); QgsDebugMsg( values ); statement += ") VALUES (" + values + ')'; QgsDebugMsg( statement ); QgsDebugMsg( "Prepare statement" ); // use prepared statement to prevent from sql injection if ( !query.prepare( statement ) ) { QString msg = query.lastError().text(); QgsDebugMsg( msg ); pushError( msg ); return false; } for ( QgsFeatureList::iterator it = flist.begin(); it != flist.end(); ++it ) { attrs = it->attributes(); int fieldIdx = 0; if ( copyOperation ) { fieldIdx = 1; // skip first (FID) field if copying from shapefile } int bindIdx = 0; for ( int i = 0; i < attrs.count(); i++ ) { QgsField fld = mAttributeFields.at( fieldIdx++ ); if ( fld.name().isEmpty() ) continue; // invalid if ( mFidColName == fld.name() ) continue; // skip identity field // if ( mDefaultValues.contains( i ) && mDefaultValues[i] == attrs.at( i ) ) // continue; // skip fields having default values QVariant::Type type = fld.type(); if ( attrs.at( i ).isNull() || !attrs.at( i ).isValid() ) { // binding null values if ( type == QVariant::Date || type == QVariant::DateTime ) query.bindValue( bindIdx, QVariant( QVariant::String ) ); else query.bindValue( bindIdx, QVariant( type ) ); } else if ( type == QVariant::Int ) { // binding an INTEGER value query.bindValue( bindIdx, attrs.at( i ).toInt() ); } else if ( type == QVariant::Double ) { // binding a DOUBLE value query.bindValue( bindIdx, attrs.at( i ).toDouble() ); } else if ( type == QVariant::String ) { // binding a TEXT value query.bindValue( bindIdx, attrs.at( i ).toString() ); } else if ( type == QVariant::Time ) { // binding a TIME value query.bindValue( bindIdx, attrs.at( i ).toTime().toString( Qt::ISODate ) ); } else if ( type == QVariant::Date ) { // binding a DATE value query.bindValue( bindIdx, attrs.at( i ).toDate().toString( Qt::ISODate ) ); } else if ( type == QVariant::DateTime ) { // binding a DATETIME value query.bindValue( bindIdx, attrs.at( i ).toDateTime().toString( Qt::ISODate ) ); } else { query.bindValue( bindIdx, attrs.at( i ) ); } #if 0 QgsDebugMsg( QString( "bound i: %1; name: %2; value: %3; bindIdx: %4" ). arg( i ).arg( fld.name() ).arg( attrs.at( i ).toString() ).arg( bindIdx ) ); #endif bindIdx++; } if ( !mGeometryColName.isEmpty() ) { QgsGeometry geom = it->geometry(); QByteArray bytea = QByteArray(( char* )geom.asWkb(), ( int ) geom.wkbSize() ); query.bindValue( bindIdx, bytea, QSql::In | QSql::Binary ); } QList<QVariant> list = query.boundValues().values(); // Show bound values #if 0 for ( int i = 0; i < list.size(); ++i ) { QgsDebugMsg( QString( "i: %1; value: %2; type: %3" ) .arg( i ).arg( list.at( i ).toString().toLatin1().data() ).arg( list.at( i ).typeName() ) ); } #endif if ( !query.exec() ) { QString msg = query.lastError().text(); QgsDebugMsg( msg ); if ( !mSkipFailures ) { pushError( msg ); return false; } } statement = QString( "select IDENTITY_VAL_LOCAL() AS IDENTITY " "FROM SYSIBM.SYSDUMMY1" ); // QgsDebugMsg( statement ); if ( !queryFid.exec( statement ) ) { QString msg = query.lastError().text(); QgsDebugMsg( msg ); if ( !mSkipFailures ) { pushError( msg ); return false; } } if ( !queryFid.next() ) { QString msg = query.lastError().text(); QgsDebugMsg( msg ); if ( !mSkipFailures ) { pushError( msg ); return false; } } it->setFeatureId( queryFid.value( 0 ).toLongLong() ); writeCount++; // QgsDebugMsg( QString( "count: %1; featureId: %2" ).arg( writeCount ).arg( queryFid.value( 0 ).toLongLong() ) ); } bool commitStatus = mDatabase.commit(); QgsDebugMsg( QString( "commitStatus: %1; write count: %2; featureId: %3" ) .arg( commitStatus ).arg( writeCount ).arg( queryFid.value( 0 ).toLongLong() ) ); if ( !commitStatus ) { pushError( "Commit of new features failed" ); return false; } return true; }