QSizeF QgsHistogramDiagram::diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s ) { Q_UNUSED( c ); QSizeF size; if ( attributes.count() == 0 ) { return QSizeF(); //zero size if no attributes } double maxValue = attributes.at( 0 ).toDouble(); for ( int i = 0; i < attributes.count(); ++i ) { maxValue = qMax( attributes.at( i ).toDouble(), maxValue ); } switch ( s.diagramOrientation ) { case QgsDiagramSettings::Up: case QgsDiagramSettings::Down: mScaleFactor = maxValue / s.size.height(); size.scale( s.barWidth * s.categoryColors.size(), s.size.height(), Qt::IgnoreAspectRatio ); break; case QgsDiagramSettings::Right: case QgsDiagramSettings::Left: default: // just in case... mScaleFactor = maxValue / s.size.width(); size.scale( s.size.width(), s.barWidth * s.categoryColors.size(), Qt::IgnoreAspectRatio ); break; } return size; }
bool QgsVectorLayerImport::addFeature( QgsFeature& feat ) { QgsAttributes attrs = feat.attributes(); QgsFeature newFeat; if ( feat.constGeometry() ) newFeat.setGeometry( *feat.constGeometry() ); newFeat.initAttributes( mAttributeCount ); for ( int i = 0; i < attrs.count(); ++i ) { // add only mapped attributes (un-mapped ones will not be present in the // destination layer) int dstIdx = mOldToNewAttrIdx.value( i, -1 ); if ( dstIdx < 0 ) continue; QgsDebugMsgLevel( QString( "moving field from pos %1 to %2" ).arg( i ).arg( dstIdx ), 3 ); newFeat.setAttribute( dstIdx, attrs.at( i ) ); } mFeatureBuffer.append( newFeat ); if ( mFeatureBuffer.count() >= FEATURE_BUFFER_SIZE ) { return flushBuffer(); } return true; }
QString QgsPointDisplacementRenderer::getLabel( const QgsFeature& f ) { QString attribute; QgsAttributes attrs = f.attributes(); if ( mLabelIndex >= 0 && mLabelIndex < attrs.count() ) { attribute = attrs[mLabelIndex].toString(); } return attribute; }
QVariant RgSpeedProperter::property( double distance, const QgsFeature& f ) const { QgsAttributes attrs = f.attributes(); if ( mAttributeId < 0 || mAttributeId >= attrs.count() ) return QVariant( distance / ( mDefaultValue*mToMetricFactor ) ); double val = distance / ( attrs.at( mAttributeId ).toDouble() * mToMetricFactor ); if ( val <= 0.0 ) return QVariant( distance / ( mDefaultValue / mToMetricFactor ) ); return QVariant( val ); }
QVariant QgsGraduatedSymbolRenderer::valueForFeature( QgsFeature &feature, QgsRenderContext &context ) const { QgsAttributes attrs = feature.attributes(); QVariant value; if ( mAttrNum < 0 || mAttrNum >= attrs.count() ) { value = mExpression->evaluate( &context.expressionContext() ); } else { value = attrs.at( mAttrNum ); } return value; }
QgsSymbolV2* QgsGraduatedSymbolRendererV2::originalSymbolForFeature( QgsFeature& feature ) { QgsAttributes attrs = feature.attributes(); QVariant value; if ( mAttrNum < 0 || mAttrNum >= attrs.count() ) { value = mExpression->evaluate( &feature ); } else { value = attrs[mAttrNum]; } // Null values should not be categorized if ( value.isNull() ) return NULL; // find the right category return symbolForValue( value.toDouble() ); }
void QgsOfflineEditing::applyFeaturesAdded( QgsVectorLayer* offlineLayer, QgsVectorLayer* remoteLayer, sqlite3* db, int layerId ) { QString sql = QString( "SELECT \"fid\" FROM 'log_added_features' WHERE \"layer_id\" = %1" ).arg( layerId ); QList<int> newFeatureIds = sqlQueryInts( db, sql ); // get new features from offline layer QgsFeatureList features; for ( int i = 0; i < newFeatureIds.size(); i++ ) { QgsFeature feature; if ( offlineLayer->getFeatures( QgsFeatureRequest().setFilterFid( newFeatureIds.at( i ) ) ).nextFeature( feature ) ) { features << feature; } } // copy features to remote layer emit progressModeSet( QgsOfflineEditing::AddFeatures, features.size() ); int i = 1; int newAttrsCount = remoteLayer->pendingFields().count(); for ( QgsFeatureList::iterator it = features.begin(); it != features.end(); ++it ) { QgsFeature f = *it; // NOTE: Spatialite provider ignores position of geometry column // restore gap in QgsAttributeMap if geometry column is not last (WORKAROUND) QMap<int, int> attrLookup = attributeLookup( offlineLayer, remoteLayer ); QgsAttributes newAttrs( newAttrsCount ); QgsAttributes attrs = f.attributes(); for ( int it = 0; it < attrs.count(); ++it ) { newAttrs[ attrLookup[ it ] ] = attrs[ it ]; } f.setAttributes( newAttrs ); remoteLayer->addFeature( f, false ); emit progressUpdated( i++ ); } }
QWidget *QgsFormAnnotation::createDesignerWidget( const QString &filePath ) { QFile file( filePath ); if ( !file.open( QFile::ReadOnly ) ) { return nullptr; } QUiLoader loader; QFileInfo fi( file ); loader.setWorkingDirectory( fi.dir() ); QWidget *widget = loader.load( &file, nullptr ); file.close(); //get feature and set attribute information QgsAttributeEditorContext context; QgsVectorLayer *vectorLayer = qobject_cast< QgsVectorLayer * >( mapLayer() ); if ( vectorLayer && associatedFeature().isValid() ) { QgsFields fields = vectorLayer->fields(); QgsAttributes attrs = associatedFeature().attributes(); for ( int i = 0; i < attrs.count(); ++i ) { if ( i < fields.count() ) { QWidget *attWidget = widget->findChild<QWidget *>( fields.at( i ).name() ); if ( attWidget ) { QgsEditorWidgetWrapper *eww = QgsGui::editorWidgetRegistry()->create( vectorLayer, i, attWidget, widget, context ); if ( eww ) { eww->setValue( attrs.at( i ) ); } } } } } return widget; }
/** * Slot called when the index changes for the cboxCompassBearingField combo box. * @param theIndex - The index of the new selected item */ void eVisGenericEventBrowserGui::on_cboxCompassOffsetField_currentIndexChanged( int theIndex ) { Q_UNUSED( theIndex ); if ( !mIgnoreEvent ) { mConfiguration.setCompassOffsetField( cboxCompassOffsetField->currentText() ); QgsFields myFields = mDataProvider->fields(); QgsFeature* myFeature = featureAtId( mFeatureIds.at( mCurrentFeatureIndex ) ); if ( !myFeature ) return; QgsAttributes myAttrs = myFeature->attributes(); for ( int i = 0; i < myAttrs.count(); ++i ) { if ( myFields.at( i ).name() == cboxCompassOffsetField->currentText() ) { mCompassOffset = myAttrs.at( i ).toDouble(); } } } }
void QgsVectorLayerEditBuffer::updateChangedAttributes( QgsFeature &f ) { QgsAttributes attrs = f.attributes(); // remove all attributes that will disappear - from higher indices to lower for ( int idx = mDeletedAttributeIds.count() - 1; idx >= 0; --idx ) { attrs.remove( mDeletedAttributeIds[idx] ); } // adjust size to accommodate added attributes attrs.resize( attrs.count() + mAddedAttributes.count() ); // update changed attributes if ( mChangedAttributeValues.contains( f.id() ) ) { const QgsAttributeMap &map = mChangedAttributeValues[f.id()]; for ( QgsAttributeMap::const_iterator it = map.begin(); it != map.end(); ++it ) attrs[it.key()] = it.value(); } f.setAttributes( attrs ); }
/** * Slot called when the index changes for the cboxEventImagePathField combo box. * \param index - The index of the new selected item */ void eVisGenericEventBrowserGui::cboxEventImagePathField_currentIndexChanged( int index ) { Q_UNUSED( index ); if ( !mIgnoreEvent ) { mConfiguration.setEventImagePathField( cboxEventImagePathField->currentText() ); QgsFields myFields = mVectorLayer->fields(); QgsFeature *myFeature = featureAtId( mFeatureIds.at( mCurrentFeatureIndex ) ); if ( !myFeature ) return; QgsAttributes myAttrs = myFeature->attributes(); for ( int i = 0; i < myAttrs.count(); ++i ) { if ( myFields.at( i ).name() == cboxEventImagePathField->currentText() ) { mEventImagePath = myAttrs.at( i ).toString(); } } } }
QString QgsClipboard::generateClipboardText() const { QgsSettings settings; CopyFormat format = AttributesWithWKT; if ( settings.contains( QStringLiteral( "/qgis/copyFeatureFormat" ) ) ) format = static_cast< CopyFormat >( settings.value( QStringLiteral( "qgis/copyFeatureFormat" ), true ).toInt() ); else { //old format setting format = settings.value( QStringLiteral( "qgis/copyGeometryAsWKT" ), true ).toBool() ? AttributesWithWKT : AttributesOnly; } switch ( format ) { case AttributesOnly: case AttributesWithWKT: { QStringList textLines; QStringList textFields; // first do the field names if ( format == AttributesWithWKT ) { textFields += QStringLiteral( "wkt_geom" ); } Q_FOREACH ( const QgsField &field, mFeatureFields ) { textFields += field.name(); } textLines += textFields.join( QStringLiteral( "\t" ) ); textFields.clear(); // then the field contents for ( QgsFeatureList::const_iterator it = mFeatureClipboard.constBegin(); it != mFeatureClipboard.constEnd(); ++it ) { QgsAttributes attributes = it->attributes(); // TODO: Set up Paste Transformations to specify the order in which fields are added. if ( format == AttributesWithWKT ) { if ( it->hasGeometry() ) textFields += it->geometry().exportToWkt(); else { textFields += QgsApplication::nullRepresentation(); } } // QgsDebugMsg("about to traverse fields."); for ( int idx = 0; idx < attributes.count(); ++idx ) { // QgsDebugMsg(QString("inspecting field '%1'.").arg(it2->toString())); textFields += attributes.at( idx ).toString(); } textLines += textFields.join( QStringLiteral( "\t" ) ); textFields.clear(); } return textLines.join( QStringLiteral( "\n" ) ); } case GeoJSON: { QgsJSONExporter exporter; exporter.setSourceCrs( mCRS ); return exporter.exportFeatures( mFeatureClipboard ); } } return QString(); }
/** * Display the attrbiutes for the current feature and load the image */ void eVisGenericEventBrowserGui::loadRecord() { treeEventData->clear(); //Get a pointer to the current feature QgsFeature* myFeature; myFeature = featureAtId( mFeatureIds.at( mCurrentFeatureIndex ) ); if ( !myFeature ) return; QString myCompassBearingField = cboxCompassBearingField->currentText(); QString myCompassOffsetField = cboxCompassOffsetField->currentText(); QString myEventImagePathField = cboxEventImagePathField->currentText(); QgsFields myFields = mDataProvider->fields(); QgsAttributes myAttrs = myFeature->attributes(); //loop through the attributes and display their contents for ( int i = 0; i < myAttrs.count(); ++i ) { QStringList myValues; QString fieldName = myFields.at( i ).name(); myValues << fieldName << myAttrs.at( i ).toString(); QTreeWidgetItem* myItem = new QTreeWidgetItem( myValues ); if ( fieldName == myEventImagePathField ) { mEventImagePath = myAttrs.at( i ).toString(); } if ( fieldName == myCompassBearingField ) { mCompassBearing = myAttrs.at( i ).toDouble(); } if ( mConfiguration.isAttributeCompassOffsetSet() ) { if ( fieldName == myCompassOffsetField ) { mCompassOffset = myAttrs.at( i ).toDouble(); } } else { mCompassOffset = 0.0; } //Check to see if the attribute is a know file type int myIterator = 0; while ( myIterator < tableFileTypeAssociations->rowCount() ) { if ( tableFileTypeAssociations->item( myIterator, 0 ) && ( myAttrs.at( i ).toString().startsWith( tableFileTypeAssociations->item( myIterator, 0 )->text() + ':', Qt::CaseInsensitive ) || myAttrs.at( i ).toString().endsWith( tableFileTypeAssociations->item( myIterator, 0 )->text(), Qt::CaseInsensitive ) ) ) { myItem->setBackground( 1, QBrush( QColor( 183, 216, 125, 255 ) ) ); break; } else myIterator++; } treeEventData->addTopLevelItem( myItem ); } //Modify EventImagePath as needed buildEventImagePath(); //Request the image to be displayed in the browser displayImage(); }
void QgsClipboard::setSystemClipboard() { // Replace the system clipboard. QSettings settings; bool copyWKT = settings.value( "qgis/copyGeometryAsWKT", true ).toBool(); QStringList textLines; QStringList textFields; // first do the field names if ( copyWKT ) { textFields += "wkt_geom"; } Q_FOREACH ( const QgsField& field, mFeatureFields ) { textFields += field.name(); } textLines += textFields.join( "\t" ); textFields.clear(); // then the field contents for ( QgsFeatureList::const_iterator it = mFeatureClipboard.constBegin(); it != mFeatureClipboard.constEnd(); ++it ) { QgsAttributes attributes = it->attributes(); // TODO: Set up Paste Transformations to specify the order in which fields are added. if ( copyWKT ) { if ( it->constGeometry() ) textFields += it->constGeometry()->exportToWkt(); else { textFields += settings.value( "qgis/nullValue", "NULL" ).toString(); } } // QgsDebugMsg("about to traverse fields."); for ( int idx = 0; idx < attributes.count(); ++idx ) { // QgsDebugMsg(QString("inspecting field '%1'.").arg(it2->toString())); textFields += attributes.at( idx ).toString(); } textLines += textFields.join( "\t" ); textFields.clear(); } QString textCopy = textLines.join( "\n" ); QClipboard *cb = QApplication::clipboard(); // Copy text into the clipboard // With qgis running under Linux, but with a Windows based X // server (Xwin32), ::Selection was necessary to get the data into // the Windows clipboard (which seems contrary to the Qt // docs). With a Linux X server, ::Clipboard was required. // The simple solution was to put the text into both clipboards. #ifdef Q_OS_LINUX cb->setText( textCopy, QClipboard::Selection ); #endif cb->setText( textCopy, QClipboard::Clipboard ); QgsDebugMsgLevel( QString( "replaced system clipboard with: %1." ).arg( textCopy ), 4 ); }
bool QgsGPXProvider::addFeature( QgsFeature& f ) { const unsigned char* geo = f.constGeometry()->asWkb(); QGis::WkbType wkbType = f.constGeometry()->wkbType(); bool success = false; QgsGPSObject* obj = NULL; QgsAttributes attrs = f.attributes(); QgsAttributeMap::const_iterator it; // is it a waypoint? if ( mFeatureType == WaypointType && geo != NULL && wkbType == QGis::WKBPoint ) { // add geometry QgsWaypoint wpt; std::memcpy( &wpt.lon, geo + 5, sizeof( double ) ); std::memcpy( &wpt.lat, geo + 13, sizeof( double ) ); // add waypoint-specific attributes for ( int i = 0; i < attrs.count(); ++i ) { if ( indexToAttr[i] == EleAttr ) { bool eleIsOK; double ele = attrs.at( i ).toDouble( &eleIsOK ); if ( eleIsOK ) wpt.ele = ele; } else if ( indexToAttr[i] == SymAttr ) { wpt.sym = attrs.at( i ).toString(); } } QgsGPSData::WaypointIterator iter = data->addWaypoint( wpt ); success = true; obj = &( *iter ); } // is it a route? if ( mFeatureType == RouteType && geo != NULL && wkbType == QGis::WKBLineString ) { QgsRoute rte; // reset bounds rte.xMin = std::numeric_limits<double>::max(); rte.xMax = -std::numeric_limits<double>::max(); rte.yMin = std::numeric_limits<double>::max(); rte.yMax = -std::numeric_limits<double>::max(); // add geometry int nPoints; std::memcpy( &nPoints, geo + 5, 4 ); for ( int i = 0; i < nPoints; ++i ) { double lat, lon; std::memcpy( &lon, geo + 9 + 16 * i, sizeof( double ) ); std::memcpy( &lat, geo + 9 + 16 * i + 8, sizeof( double ) ); QgsRoutepoint rtept; rtept.lat = lat; rtept.lon = lon; rte.points.push_back( rtept ); rte.xMin = rte.xMin < lon ? rte.xMin : lon; rte.xMax = rte.xMax > lon ? rte.xMax : lon; rte.yMin = rte.yMin < lat ? rte.yMin : lat; rte.yMax = rte.yMax > lat ? rte.yMax : lat; } // add route-specific attributes for ( int i = 0; i < attrs.count(); ++i ) { if ( indexToAttr[i] == NumAttr ) { bool numIsOK; long num = attrs.at( i ).toInt( &numIsOK ); if ( numIsOK ) rte.number = num; } } QgsGPSData::RouteIterator iter = data->addRoute( rte ); success = true; obj = &( *iter ); } // is it a track? if ( mFeatureType == TrackType && geo != NULL && wkbType == QGis::WKBLineString ) { QgsTrack trk; QgsTrackSegment trkseg; // reset bounds trk.xMin = std::numeric_limits<double>::max(); trk.xMax = -std::numeric_limits<double>::max(); trk.yMin = std::numeric_limits<double>::max(); trk.yMax = -std::numeric_limits<double>::max(); // add geometry int nPoints; std::memcpy( &nPoints, geo + 5, 4 ); for ( int i = 0; i < nPoints; ++i ) { double lat, lon; std::memcpy( &lon, geo + 9 + 16 * i, sizeof( double ) ); std::memcpy( &lat, geo + 9 + 16 * i + 8, sizeof( double ) ); QgsTrackpoint trkpt; trkpt.lat = lat; trkpt.lon = lon; trkseg.points.push_back( trkpt ); trk.xMin = trk.xMin < lon ? trk.xMin : lon; trk.xMax = trk.xMax > lon ? trk.xMax : lon; trk.yMin = trk.yMin < lat ? trk.yMin : lat; trk.yMax = trk.yMax > lat ? trk.yMax : lat; } // add track-specific attributes for ( int i = 0; i < attrs.count(); ++i ) { if ( indexToAttr[i] == NumAttr ) { bool numIsOK; long num = attrs.at( i ).toInt( &numIsOK ); if ( numIsOK ) trk.number = num; } } trk.segments.push_back( trkseg ); QgsGPSData::TrackIterator iter = data->addTrack( trk ); success = true; obj = &( *iter ); } // add common attributes if ( obj ) { for ( int i = 0; i < attrs.count(); ++i ) { switch ( indexToAttr[i] ) { case NameAttr: obj->name = attrs.at( i ).toString(); break; case CmtAttr: obj->cmt = attrs.at( i ).toString(); break; case DscAttr: obj->desc = attrs.at( i ).toString(); break; case SrcAttr: obj->src = attrs.at( i ).toString(); break; case URLAttr: obj->url = attrs.at( i ).toString(); break; case URLNameAttr: obj->urlname = attrs.at( i ).toString(); break; } } } return success; }
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; }
int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPoint>& splitLine, bool topologicalEditing ) { if ( !L->hasGeometryType() ) return 4; QgsFeatureList newFeatures; //store all the newly created features double xMin, yMin, xMax, yMax; QgsRectangle bBox; //bounding box of the split line int returnCode = 0; int splitFunctionReturn; //return code of QgsGeometry::splitGeometry int numberOfSplittedFeatures = 0; QgsFeatureList featureList; const QgsFeatureIds selectedIds = L->selectedFeaturesIds(); if ( selectedIds.size() > 0 ) //consider only the selected features if there is a selection { featureList = L->selectedFeatures(); } else //else consider all the feature that intersect the bounding box of the split line { if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) == 0 ) { bBox.setXMinimum( xMin ); bBox.setYMinimum( yMin ); bBox.setXMaximum( xMax ); bBox.setYMaximum( yMax ); } else { return 1; } if ( bBox.isEmpty() ) { //if the bbox is a line, try to make a square out of it if ( bBox.width() == 0.0 && bBox.height() > 0 ) { bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 ); bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 ); } else if ( bBox.height() == 0.0 && bBox.width() > 0 ) { bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 ); bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 ); } else { return 2; } } QgsFeatureIterator fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) ); QgsFeature f; while ( fit.nextFeature( f ) ) featureList << QgsFeature( f ); } QgsFeatureList::iterator select_it = featureList.begin(); for ( ; select_it != featureList.end(); ++select_it ) { if ( !select_it->geometry() ) { continue; } QList<QgsGeometry*> newGeometries; QList<QgsPoint> topologyTestPoints; QgsGeometry* newGeometry = 0; splitFunctionReturn = select_it->geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints ); if ( splitFunctionReturn == 0 ) { //change this geometry L->editBuffer()->changeGeometry( select_it->id(), select_it->geometry() ); //insert new features for ( int i = 0; i < newGeometries.size(); ++i ) { newGeometry = newGeometries.at( i ); QgsFeature newFeature; newFeature.setGeometry( newGeometry ); //use default value where possible (primary key issue), otherwise the value from the original (split) feature QgsAttributes newAttributes = select_it->attributes(); QVariant defaultValue; for ( int j = 0; j < newAttributes.count(); ++j ) { defaultValue = L->dataProvider()->defaultValue( j ); if ( !defaultValue.isNull() ) { newAttributes[ j ] = defaultValue; } } newFeature.setAttributes( newAttributes ); newFeatures.append( newFeature ); } if ( topologicalEditing ) { QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin(); for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it ) { addTopologicalPoints( *topol_it ); } } ++numberOfSplittedFeatures; } else if ( splitFunctionReturn > 1 ) //1 means no split but also no error { returnCode = splitFunctionReturn; } } if ( numberOfSplittedFeatures == 0 && selectedIds.size() > 0 ) { //There is a selection but no feature has been split. //Maybe user forgot that only the selected features are split returnCode = 4; } //now add the new features to this vectorlayer L->editBuffer()->addFeatures( newFeatures ); return returnCode; }
void QgsOfflineEditing::copyVectorLayer( QgsVectorLayer* layer, sqlite3* db, const QString& offlineDbPath ) { if ( layer == NULL ) { return; } QString tableName = layer->name(); // create table QString sql = QString( "CREATE TABLE '%1' (" ).arg( tableName ); QString delim = ""; const QgsFields& fields = layer->dataProvider()->fields(); for ( int idx = 0; idx < fields.count(); ++idx ) { QString dataType = ""; QVariant::Type type = fields[idx].type(); if ( type == QVariant::Int ) { dataType = "INTEGER"; } else if ( type == QVariant::Double ) { dataType = "REAL"; } else if ( type == QVariant::String ) { dataType = "TEXT"; } else { showWarning( tr( "Unknown data type %1" ).arg( type ) ); } sql += delim + QString( "'%1' %2" ).arg( fields[idx].name() ).arg( dataType ); delim = ","; } sql += ")"; // add geometry column QString geomType = ""; switch ( layer->wkbType() ) { case QGis::WKBPoint: geomType = "POINT"; break; case QGis::WKBMultiPoint: geomType = "MULTIPOINT"; break; case QGis::WKBLineString: geomType = "LINESTRING"; break; case QGis::WKBMultiLineString: geomType = "MULTILINESTRING"; break; case QGis::WKBPolygon: geomType = "POLYGON"; break; case QGis::WKBMultiPolygon: geomType = "MULTIPOLYGON"; break; default: showWarning( tr( "QGIS wkbType %1 not supported" ).arg( layer->wkbType() ) ); break; }; QString sqlAddGeom = QString( "SELECT AddGeometryColumn('%1', 'Geometry', %2, '%3', 2)" ) .arg( tableName ) .arg( layer->crs().authid().startsWith( "EPSG:", Qt::CaseInsensitive ) ? layer->crs().authid().mid( 5 ).toLong() : 0 ) .arg( geomType ); // create spatial index QString sqlCreateIndex = QString( "SELECT CreateSpatialIndex('%1', 'Geometry')" ).arg( tableName ); int rc = sqlExec( db, sql ); if ( rc == SQLITE_OK ) { rc = sqlExec( db, sqlAddGeom ); if ( rc == SQLITE_OK ) { rc = sqlExec( db, sqlCreateIndex ); } } if ( rc == SQLITE_OK ) { // add new layer QgsVectorLayer* newLayer = new QgsVectorLayer( QString( "dbname='%1' table='%2'(Geometry) sql=" ) .arg( offlineDbPath ).arg( tableName ), tableName + " (offline)", "spatialite" ); if ( newLayer->isValid() ) { // mark as offline layer newLayer->setCustomProperty( CUSTOM_PROPERTY_IS_OFFLINE_EDITABLE, true ); // store original layer source newLayer->setCustomProperty( CUSTOM_PROPERTY_REMOTE_SOURCE, layer->source() ); newLayer->setCustomProperty( CUSTOM_PROPERTY_REMOTE_PROVIDER, layer->providerType() ); // copy style bool hasLabels = layer->hasLabelsEnabled(); if ( !hasLabels ) { // NOTE: copy symbology before adding the layer so it is displayed correctly copySymbology( layer, newLayer ); } // register this layer with the central layers registry QgsMapLayerRegistry::instance()->addMapLayers( QList<QgsMapLayer *>() << newLayer ); if ( hasLabels ) { // NOTE: copy symbology of layers with labels enabled after adding to project, as it will crash otherwise (WORKAROUND) copySymbology( layer, newLayer ); } // TODO: layer order // copy features newLayer->startEditing(); QgsFeature f; // NOTE: force feature recount for PostGIS layer, else only visible features are counted, before iterating over all features (WORKAROUND) layer->setSubsetString( "" ); QgsFeatureIterator fit = layer->getFeatures(); emit progressModeSet( QgsOfflineEditing::CopyFeatures, layer->featureCount() ); int featureCount = 1; QList<QgsFeatureId> remoteFeatureIds; while ( fit.nextFeature( f ) ) { remoteFeatureIds << f.id(); // NOTE: Spatialite provider ignores position of geometry column // fill gap in QgsAttributeMap if geometry column is not last (WORKAROUND) int column = 0; QgsAttributes attrs = f.attributes(); QgsAttributes newAttrs( attrs.count() ); for ( int it = 0; it < attrs.count(); ++it ) { newAttrs[column++] = attrs[it]; } f.setAttributes( newAttrs ); newLayer->addFeature( f, false ); emit progressUpdated( featureCount++ ); } if ( newLayer->commitChanges() ) { emit progressModeSet( QgsOfflineEditing::ProcessFeatures, layer->featureCount() ); featureCount = 1; // update feature id lookup int layerId = getOrCreateLayerId( db, newLayer->id() ); QList<QgsFeatureId> offlineFeatureIds; QgsFeatureIterator fit = newLayer->getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ).setSubsetOfAttributes( QgsAttributeList() ) ); while ( fit.nextFeature( f ) ) { offlineFeatureIds << f.id(); } // NOTE: insert fids in this loop, as the db is locked during newLayer->nextFeature() sqlExec( db, "BEGIN" ); int remoteCount = remoteFeatureIds.size(); for ( int i = 0; i < remoteCount; i++ ) { addFidLookup( db, layerId, offlineFeatureIds.at( i ), remoteFeatureIds.at( remoteCount - ( i + 1 ) ) ); emit progressUpdated( featureCount++ ); } sqlExec( db, "COMMIT" ); } else { showWarning( newLayer->commitErrors().join( "\n" ) ); } // remove remote layer QgsMapLayerRegistry::instance()->removeMapLayers( QStringList() << layer->id() ); } } }