43 #include <QDomDocument> 46 #include <QMessageBox> 48 #include <ogr_srs_api.h> 53 #include <spatialite.h> 56 #define CUSTOM_PROPERTY_IS_OFFLINE_EDITABLE "isOfflineEditable" 57 #define CUSTOM_PROPERTY_REMOTE_SOURCE "remoteSource" 58 #define CUSTOM_PROPERTY_REMOTE_PROVIDER "remoteProvider" 59 #define CUSTOM_SHOW_FEATURE_COUNT "showFeatureCount" 60 #define PROJECT_ENTRY_SCOPE_OFFLINE "OfflineEditingPlugin" 61 #define PROJECT_ENTRY_KEY_OFFLINE_DB_PATH "/OfflineDbPath" 85 if ( layerIds.isEmpty() )
90 QString dbPath = QDir( offlineDataPath ).absoluteFilePath( offlineDbFile );
91 if ( createOfflineDb( dbPath, containerType ) )
94 int rc = database.
open( dbPath );
95 if ( rc != SQLITE_OK )
97 showWarning( tr(
"Could not open the SpatiaLite database" ) );
102 createLoggingTables( database.get() );
106 QMap<QString, QgsVectorJoinList > joinInfoBuffer;
107 QMap<QString, QgsVectorLayer *> layerIdMapping;
109 Q_FOREACH (
const QString &layerId, layerIds )
121 QgsVectorJoinList::iterator joinIt = joins.begin();
122 while ( joinIt != joins.end() )
124 if ( joinIt->prefix().isNull() )
129 joinIt->setPrefix( vl->
name() +
'_' );
133 joinInfoBuffer.insert( vl->
id(), joins );
139 for (
int i = 0; i < layerIds.count(); i++ )
147 QString origLayerId = vl->
id();
148 QgsVectorLayer *newLayer = copyVectorLayer( vl, database.get(), dbPath, onlySelected, containerType );
151 layerIdMapping.insert( origLayerId, newLayer );
154 snappingConfig.
removeLayers( QList<QgsMapLayer *>() << vl );
158 QStringList() << origLayerId );
166 QMap<QString, QgsVectorJoinList >::ConstIterator it;
167 for ( it = joinInfoBuffer.constBegin(); it != joinInfoBuffer.constEnd(); ++it )
176 if ( newJoinedLayer )
190 if ( projectTitle.isEmpty() )
194 projectTitle += QLatin1String(
" (offline)" );
225 QList<QgsMapLayer *> offlineLayers;
227 for ( QMap<QString, QgsMapLayer *>::iterator layer_it = mapLayers.begin() ; layer_it != mapLayers.end(); ++layer_it )
232 offlineLayers << layer;
236 QgsDebugMsgLevel( QStringLiteral(
"Found %1 offline layers" ).arg( offlineLayers.count() ), 4 );
237 for (
int l = 0; l < offlineLayers.count(); l++ )
245 QString remoteName = layer->
name();
246 remoteName.remove( QRegExp(
" \\(offline\\)$" ) );
252 if ( remoteLayer->
dataProvider()->
name().contains( QLatin1String(
"WFS" ), Qt::CaseInsensitive ) )
268 copySymbology( offlineLayer, remoteLayer );
269 updateRelations( offlineLayer, remoteLayer );
270 updateMapThemes( offlineLayer, remoteLayer );
271 updateLayerOrder( offlineLayer, remoteLayer );
275 snappingConfig.
removeLayers( QList<QgsMapLayer *>() << offlineLayer );
283 QString qgisLayerId = layer->
id();
284 QString sql = QStringLiteral(
"SELECT \"id\" FROM 'log_layer_ids' WHERE \"qgis_id\" = '%1'" ).arg( qgisLayerId );
285 int layerId = sqlQueryInt( database.get(), sql, -1 );
291 int commitNo = getCommitNo( database.get() );
292 QgsDebugMsgLevel( QStringLiteral(
"Found %1 commits" ).arg( commitNo ), 4 );
293 for (
int i = 0; i < commitNo; i++ )
297 applyAttributesAdded( remoteLayer, database.get(), layerId, i );
298 applyAttributeValueChanges( offlineLayer, remoteLayer, database.get(), layerId, i );
299 applyGeometryChanges( remoteLayer, database.get(), layerId, i );
302 applyFeaturesAdded( offlineLayer, remoteLayer, database.get(), layerId );
303 applyFeaturesRemoved( remoteLayer, database.get(), layerId );
308 updateFidLookup( remoteLayer, database.get(), layerId );
311 sql = QStringLiteral(
"DELETE FROM 'log_added_attrs' WHERE \"layer_id\" = %1" ).arg( layerId );
312 sqlExec( database.get(), sql );
313 sql = QStringLiteral(
"DELETE FROM 'log_added_features' WHERE \"layer_id\" = %1" ).arg( layerId );
314 sqlExec( database.get(), sql );
315 sql = QStringLiteral(
"DELETE FROM 'log_removed_features' WHERE \"layer_id\" = %1" ).arg( layerId );
316 sqlExec( database.get(), sql );
317 sql = QStringLiteral(
"DELETE FROM 'log_feature_updates' WHERE \"layer_id\" = %1" ).arg( layerId );
318 sqlExec( database.get(), sql );
319 sql = QStringLiteral(
"DELETE FROM 'log_geometry_updates' WHERE \"layer_id\" = %1" ).arg( layerId );
320 sqlExec( database.get(), sql );
324 showWarning( remoteLayer->
commitErrors().join( QStringLiteral(
"\n" ) ) );
329 QgsDebugMsg( QStringLiteral(
"Could not find the layer id in the edit logs!" ) );
340 projectTitle.remove( QRegExp(
" \\(offline\\)$" ) );
347 QgsDebugMsg( QStringLiteral(
"Remote layer is not valid!" ) );
352 QString sql = QStringLiteral(
"UPDATE 'log_indices' SET 'last_index' = 0 WHERE \"name\" = 'commit_no'" );
353 sqlExec( database.get(), sql );
360 void QgsOfflineEditing::initializeSpatialMetadata(
sqlite3 *sqlite_handle )
363 if ( !sqlite_handle )
366 char **results =
nullptr;
368 int ret = sqlite3_get_table( sqlite_handle,
"select count(*) from sqlite_master", &results, &rows, &columns,
nullptr );
369 if ( ret != SQLITE_OK )
374 for (
int i = 1; i <= rows; i++ )
375 count = atoi( results[( i * columns ) + 0] );
378 sqlite3_free_table( results );
383 bool above41 =
false;
384 ret = sqlite3_get_table( sqlite_handle,
"select spatialite_version()", &results, &rows, &columns,
nullptr );
385 if ( ret == SQLITE_OK && rows == 1 && columns == 1 )
387 QString version = QString::fromUtf8( results[1] );
388 QStringList parts = version.split(
' ', QString::SkipEmptyParts );
389 if ( !parts.empty() )
391 QStringList verparts = parts.at( 0 ).split(
'.', QString::SkipEmptyParts );
392 above41 = verparts.size() >= 2 && ( verparts.at( 0 ).toInt() > 4 || ( verparts.at( 0 ).toInt() == 4 && verparts.at( 1 ).toInt() >= 1 ) );
396 sqlite3_free_table( results );
399 char *errMsg =
nullptr;
400 ret = sqlite3_exec( sqlite_handle, above41 ?
"SELECT InitSpatialMetadata(1)" :
"SELECT InitSpatialMetadata()",
nullptr,
nullptr, &errMsg );
402 if ( ret != SQLITE_OK )
404 QString errCause = tr(
"Unable to initialize SpatialMetadata:\n" );
405 errCause += QString::fromUtf8( errMsg );
406 showWarning( errCause );
407 sqlite3_free( errMsg );
410 spatial_ref_sys_init( sqlite_handle, 0 );
413 bool QgsOfflineEditing::createOfflineDb(
const QString &offlineDbPath,
ContainerType containerType )
416 char *errMsg =
nullptr;
417 QFile newDb( offlineDbPath );
418 if ( newDb.exists() )
420 QFile::remove( offlineDbPath );
425 QFileInfo fullPath = QFileInfo( offlineDbPath );
426 QDir path = fullPath.dir();
429 QDir().mkpath( path.absolutePath() );
432 QString dbPath = newDb.fileName();
435 switch ( containerType )
439 OGRSFDriverH hGpkgDriver = OGRGetDriverByName(
"GPKG" );
442 showWarning( tr(
"Creation of database failed. GeoPackage driver not found." ) );
449 showWarning( tr(
"Creation of database failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ) );
461 ret = database.
open_v2( dbPath, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
nullptr );
465 QString errCause = tr(
"Could not create a new database\n" );
467 showWarning( errCause );
471 ret = sqlite3_exec( database.get(),
"PRAGMA foreign_keys = 1",
nullptr,
nullptr, &errMsg );
472 if ( ret != SQLITE_OK )
474 showWarning( tr(
"Unable to activate FOREIGN_KEY constraints" ) );
475 sqlite3_free( errMsg );
478 initializeSpatialMetadata( database.get() );
482 void QgsOfflineEditing::createLoggingTables(
sqlite3 *db )
485 QString sql = QStringLiteral(
"CREATE TABLE 'log_indices' ('name' TEXT, 'last_index' INTEGER)" );
488 sql = QStringLiteral(
"INSERT INTO 'log_indices' VALUES ('commit_no', 0)" );
491 sql = QStringLiteral(
"INSERT INTO 'log_indices' VALUES ('layer_id', 0)" );
495 sql = QStringLiteral(
"CREATE TABLE 'log_layer_ids' ('id' INTEGER, 'qgis_id' TEXT)" );
499 sql = QStringLiteral(
"CREATE TABLE 'log_fids' ('layer_id' INTEGER, 'offline_fid' INTEGER, 'remote_fid' INTEGER)" );
503 sql = QStringLiteral(
"CREATE TABLE 'log_added_attrs' ('layer_id' INTEGER, 'commit_no' INTEGER, " );
504 sql += QLatin1String(
"'name' TEXT, 'type' INTEGER, 'length' INTEGER, 'precision' INTEGER, 'comment' TEXT)" );
508 sql = QStringLiteral(
"CREATE TABLE 'log_added_features' ('layer_id' INTEGER, 'fid' INTEGER)" );
512 sql = QStringLiteral(
"CREATE TABLE 'log_removed_features' ('layer_id' INTEGER, 'fid' INTEGER)" );
516 sql = QStringLiteral(
"CREATE TABLE 'log_feature_updates' ('layer_id' INTEGER, 'commit_no' INTEGER, 'fid' INTEGER, 'attr' INTEGER, 'value' TEXT)" );
520 sql = QStringLiteral(
"CREATE TABLE 'log_geometry_updates' ('layer_id' INTEGER, 'commit_no' INTEGER, 'fid' INTEGER, 'geom_wkt' TEXT)" );
533 QString tableName = layer->
id();
534 QgsDebugMsgLevel( QStringLiteral(
"Creating offline table %1 ..." ).arg( tableName ), 4 );
539 switch ( containerType )
544 QString sql = QStringLiteral(
"CREATE TABLE '%1' (" ).arg( tableName );
547 for (
const auto &field : providerFields )
550 QVariant::Type type = field.type();
551 if ( type == QVariant::Int || type == QVariant::LongLong )
553 dataType = QStringLiteral(
"INTEGER" );
555 else if ( type == QVariant::Double )
557 dataType = QStringLiteral(
"REAL" );
559 else if ( type == QVariant::String )
561 dataType = QStringLiteral(
"TEXT" );
565 showWarning( tr(
"%1: Unknown data type %2. Not using type affinity for the field." ).arg( field.name(), QVariant::typeToName( type ) ) );
568 sql += delim + QStringLiteral(
"'%1' %2" ).arg( field.name(), dataType );
573 int rc = sqlExec( db, sql );
584 geomType = QStringLiteral(
"POINT" );
587 geomType = QStringLiteral(
"MULTIPOINT" );
590 geomType = QStringLiteral(
"LINESTRING" );
593 geomType = QStringLiteral(
"MULTILINESTRING" );
596 geomType = QStringLiteral(
"POLYGON" );
599 geomType = QStringLiteral(
"MULTIPOLYGON" );
606 QString zmInfo = QStringLiteral(
"XY" );
615 if ( layer->
crs().
authid().startsWith( QLatin1String(
"EPSG:" ), Qt::CaseInsensitive ) )
617 epsgCode = layer->
crs().
authid().mid( 5 );
622 showWarning( tr(
"Layer %1 has unsupported Coordinate Reference System (%2)." ).arg( layer->
name(), layer->
crs().
authid() ) );
625 QString sqlAddGeom = QStringLiteral(
"SELECT AddGeometryColumn('%1', 'Geometry', %2, '%3', '%4')" )
626 .arg( tableName, epsgCode, geomType, zmInfo );
629 QString sqlCreateIndex = QStringLiteral(
"SELECT CreateSpatialIndex('%1', 'Geometry')" ).arg( tableName );
631 if ( rc == SQLITE_OK )
633 rc = sqlExec( db, sqlAddGeom );
634 if ( rc == SQLITE_OK )
636 rc = sqlExec( db, sqlCreateIndex );
641 if ( rc != SQLITE_OK )
643 showWarning( tr(
"Filling SpatiaLite for layer %1 failed" ).arg( layer->
name() ) );
648 QString connectionString = QStringLiteral(
"dbname='%1' table='%2'%3 sql=" )
650 tableName, layer->
isSpatial() ?
"(Geometry)" :
"" );
652 layer->
name() +
" (offline)", QStringLiteral(
"spatialite" ) );
658 char **options =
nullptr;
660 options = CSLSetNameValue( options,
"OVERWRITE",
"YES" );
661 options = CSLSetNameValue( options,
"IDENTIFIER", tr(
"%1 (offline)" ).arg( layer->
id() ).toUtf8().constData() );
662 options = CSLSetNameValue( options,
"DESCRIPTION", layer->
dataComment().toUtf8().constData() );
665 QString fidBase( QStringLiteral(
"fid" ) );
666 QString fid = fidBase;
670 fid = fidBase +
'_' + QString::number( counter );
673 if ( counter == 10000 )
675 showWarning( tr(
"Cannot make FID-name for GPKG " ) );
679 options = CSLSetNameValue( options,
"FID", fid.toUtf8().constData() );
683 options = CSLSetNameValue( options,
"GEOMETRY_COLUMN",
"geom" );
684 options = CSLSetNameValue( options,
"SPATIAL_INDEX",
"YES" );
687 OGRSFDriverH hDriver =
nullptr;
690 OGRLayerH hLayer = OGR_DS_CreateLayer( hDS.get(), tableName.toUtf8().constData(), hSRS,
static_cast<OGRwkbGeometryType
>( layer->
wkbType() ), options );
691 CSLDestroy( options );
696 showWarning( tr(
"Creation of layer failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ) );
701 for (
const auto &field : providerFields )
703 const QString fieldName( field.name() );
704 const QVariant::Type type = field.type();
705 OGRFieldType ogrType( OFTString );
706 if ( type == QVariant::Int )
707 ogrType = OFTInteger;
708 else if ( type == QVariant::LongLong )
709 ogrType = OFTInteger64;
710 else if ( type == QVariant::Double )
712 else if ( type == QVariant::Time )
714 else if ( type == QVariant::Date )
716 else if ( type == QVariant::DateTime )
717 ogrType = OFTDateTime;
721 int ogrWidth = field.length();
724 OGR_Fld_SetWidth( fld.get(), ogrWidth );
726 if ( OGR_L_CreateField( hLayer, fld.get(), true ) != OGRERR_NONE )
728 showWarning( tr(
"Creation of field %1 failed (OGR error: %2)" )
729 .arg( fieldName, QString::fromUtf8( CPLGetLastErrorMsg() ) ) );
737 OGR_L_ResetReading( hLayer );
738 if ( CPLGetLastErrorType() != CE_None )
740 QString msg( tr(
"Creation of layer failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ) );
746 QString uri = QStringLiteral(
"%1|layername=%2" ).arg( offlineDbPath, tableName );
747 newLayer =
new QgsVectorLayer( uri, layer->
name() +
" (offline)", QStringLiteral(
"ogr" ) );
764 if ( !selectedFids.isEmpty() )
778 int featureCount = 1;
780 QList<QgsFeatureId> remoteFeatureIds;
783 remoteFeatureIds << f.
id();
790 QgsAttributes newAttrs( containerType ==
GPKG ? attrs.count() + 1 : attrs.count() );
791 for (
int it = 0; it < attrs.count(); ++it )
793 newAttrs[column++] = attrs.at( it );
807 int layerId = getOrCreateLayerId( db, newLayer->
id() );
808 QList<QgsFeatureId> offlineFeatureIds;
813 offlineFeatureIds << f.
id();
817 sqlExec( db, QStringLiteral(
"BEGIN" ) );
818 int remoteCount = remoteFeatureIds.size();
819 for (
int i = 0; i < remoteCount; i++ )
822 if ( i < offlineFeatureIds.count() )
824 addFidLookup( db, layerId, offlineFeatureIds.at( i ), remoteFeatureIds.at( i ) );
828 showWarning( tr(
"Feature cannot be copied to the offline layer, please check if the online layer '%1' is still accessible." ).arg( layer->
name() ) );
833 sqlExec( db, QStringLiteral(
"COMMIT" ) );
837 showWarning( newLayer->
commitErrors().join( QStringLiteral(
"\n" ) ) );
849 QList<QgsMapLayer *>() << newLayer );
852 copySymbology( layer, newLayer );
855 const auto fields = layer->
fields();
856 for (
const QgsField &field : fields )
867 if ( layerTreeLayer )
870 if ( parentTreeGroup )
872 int index = parentTreeGroup->
children().indexOf( layerTreeLayer );
875 if ( newLayerTreeLayer )
889 updateRelations( layer, newLayer );
890 updateMapThemes( layer, newLayer );
891 updateLayerOrder( layer, newLayer );
899 void QgsOfflineEditing::applyAttributesAdded(
QgsVectorLayer *remoteLayer,
sqlite3 *db,
int layerId,
int commitNo )
901 QString sql = QStringLiteral(
"SELECT \"name\", \"type\", \"length\", \"precision\", \"comment\" FROM 'log_added_attrs' WHERE \"layer_id\" = %1 AND \"commit_no\" = %2" ).arg( layerId ).arg( commitNo );
902 QList<QgsField> fields = sqlQueryAttributesAdded( db, sql );
905 QList<QgsVectorDataProvider::NativeType> nativeTypes = provider->
nativeTypes();
908 QMap < QVariant::Type, QString > typeNameLookup;
909 for (
int i = 0; i < nativeTypes.size(); i++ )
917 for (
int i = 0; i < fields.size(); i++ )
921 if ( typeNameLookup.contains( field.
type() ) )
929 showWarning( QStringLiteral(
"Could not add attribute '%1' of type %2" ).arg( field.
name() ).arg( field.
type() ) );
938 QString sql = QStringLiteral(
"SELECT \"fid\" FROM 'log_added_features' WHERE \"layer_id\" = %1" ).arg( layerId );
939 QList<int> featureIdInts = sqlQueryInts( db, sql );
941 Q_FOREACH (
int id, featureIdInts )
962 for ( QgsFeatureList::iterator it = features.begin(); it != features.end(); ++it )
966 QMap<int, int> attrLookup = attributeLookup( offlineLayer, remoteLayer );
969 for (
int it = 0; it < attrs.count(); ++it )
971 newAttrs[ attrLookup[ it ] ] = attrs.at( it );
982 void QgsOfflineEditing::applyFeaturesRemoved(
QgsVectorLayer *remoteLayer,
sqlite3 *db,
int layerId )
984 QString sql = QStringLiteral(
"SELECT \"fid\" FROM 'log_removed_features' WHERE \"layer_id\" = %1" ).arg( layerId );
990 for ( QgsFeatureIds::const_iterator it = values.constBegin(); it != values.constEnd(); ++it )
1001 QString sql = QStringLiteral(
"SELECT \"fid\", \"attr\", \"value\" FROM 'log_feature_updates' WHERE \"layer_id\" = %1 AND \"commit_no\" = %2 " ).arg( layerId ).arg( commitNo );
1002 AttributeValueChanges values = sqlQueryAttributeValueChanges( db, sql );
1006 QMap<int, int> attrLookup = attributeLookup( offlineLayer, remoteLayer );
1008 for (
int i = 0; i < values.size(); i++ )
1010 QgsFeatureId fid = remoteFid( db, layerId, values.at( i ).fid );
1011 QgsDebugMsgLevel( QStringLiteral(
"Offline changeAttributeValue %1 = %2" ).arg( QString( attrLookup[ values.at( i ).attr ] ), values.at( i ).value ), 4 );
1012 remoteLayer->
changeAttributeValue( fid, attrLookup[ values.at( i ).attr ], values.at( i ).value );
1018 void QgsOfflineEditing::applyGeometryChanges(
QgsVectorLayer *remoteLayer,
sqlite3 *db,
int layerId,
int commitNo )
1020 QString sql = QStringLiteral(
"SELECT \"fid\", \"geom_wkt\" FROM 'log_geometry_updates' WHERE \"layer_id\" = %1 AND \"commit_no\" = %2" ).arg( layerId ).arg( commitNo );
1021 GeometryChanges values = sqlQueryGeometryChanges( db, sql );
1025 for (
int i = 0; i < values.size(); i++ )
1027 QgsFeatureId fid = remoteFid( db, layerId, values.at( i ).fid );
1051 if ( offlineFid( db, layerId, f.
id() ) == -1 )
1053 newRemoteFids[ f.
id()] =
true;
1061 QString sql = QStringLiteral(
"SELECT \"fid\" FROM 'log_added_features' WHERE \"layer_id\" = %1" ).arg( layerId );
1062 QList<int> newOfflineFids = sqlQueryInts( db, sql );
1064 if ( newRemoteFids.size() != newOfflineFids.size() )
1072 sqlExec( db, QStringLiteral(
"BEGIN" ) );
1073 for ( QMap<QgsFeatureId, bool>::const_iterator it = newRemoteFids.constBegin(); it != newRemoteFids.constEnd(); ++it )
1075 addFidLookup( db, layerId, newOfflineFids.at( i++ ), it.key() );
1077 sqlExec( db, QStringLiteral(
"COMMIT" ) );
1089 if ( error.isEmpty() )
1093 if ( !error.isEmpty() )
1095 showWarning( error );
1102 QList<QgsRelation> relations;
1125 QStringList mapThemeNames = mapThemeCollection->
mapThemes();
1127 Q_FOREACH (
const QString &mapThemeName, mapThemeNames )
1133 if ( layerRecord.
layer() == sourceLayer )
1135 layerRecord.
setLayer( targetLayer );
1149 auto iterator = layerOrder.begin();
1151 while ( iterator != layerOrder.end() )
1153 if ( *iterator == targetLayer )
1155 iterator = layerOrder.erase( iterator );
1156 if ( iterator == layerOrder.end() )
1160 if ( *iterator == sourceLayer )
1162 *iterator = targetLayer;
1176 QMap <
int ,
int > attrLookup;
1179 for (
int i = 0; i < offlineAttrs.size(); i++ )
1188 void QgsOfflineEditing::showWarning(
const QString &message )
1190 emit
warning( tr(
"Offline Editing Plugin" ), message );
1197 if ( !dbPath.isEmpty() )
1200 int rc = database.
open( absoluteDbPath );
1201 if ( rc != SQLITE_OK )
1203 QgsDebugMsg( QStringLiteral(
"Could not open the SpatiaLite logging database" ) );
1204 showWarning( tr(
"Could not open the SpatiaLite logging database" ) );
1209 QgsDebugMsg( QStringLiteral(
"dbPath is empty!" ) );
1214 int QgsOfflineEditing::getOrCreateLayerId(
sqlite3 *db,
const QString &qgisLayerId )
1216 QString sql = QStringLiteral(
"SELECT \"id\" FROM 'log_layer_ids' WHERE \"qgis_id\" = '%1'" ).arg( qgisLayerId );
1217 int layerId = sqlQueryInt( db, sql, -1 );
1218 if ( layerId == -1 )
1221 sql = QStringLiteral(
"SELECT \"last_index\" FROM 'log_indices' WHERE \"name\" = 'layer_id'" );
1222 int newLayerId = sqlQueryInt( db, sql, -1 );
1225 sql = QStringLiteral(
"INSERT INTO 'log_layer_ids' VALUES (%1, '%2')" ).arg( newLayerId ).arg( qgisLayerId );
1230 sql = QStringLiteral(
"UPDATE 'log_indices' SET 'last_index' = %1 WHERE \"name\" = 'layer_id'" ).arg( newLayerId + 1 );
1233 layerId = newLayerId;
1239 int QgsOfflineEditing::getCommitNo(
sqlite3 *db )
1241 QString sql = QStringLiteral(
"SELECT \"last_index\" FROM 'log_indices' WHERE \"name\" = 'commit_no'" );
1242 return sqlQueryInt( db, sql, -1 );
1245 void QgsOfflineEditing::increaseCommitNo(
sqlite3 *db )
1247 QString sql = QStringLiteral(
"UPDATE 'log_indices' SET 'last_index' = %1 WHERE \"name\" = 'commit_no'" ).arg( getCommitNo( db ) + 1 );
1253 QString sql = QStringLiteral(
"INSERT INTO 'log_fids' VALUES ( %1, %2, %3 )" ).arg( layerId ).arg( offlineFid ).arg( remoteFid );
1259 QString sql = QStringLiteral(
"SELECT \"remote_fid\" FROM 'log_fids' WHERE \"layer_id\" = %1 AND \"offline_fid\" = %2" ).arg( layerId ).arg( offlineFid );
1260 return sqlQueryInt( db, sql, -1 );
1265 QString sql = QStringLiteral(
"SELECT \"offline_fid\" FROM 'log_fids' WHERE \"layer_id\" = %1 AND \"remote_fid\" = %2" ).arg( layerId ).arg( remoteFid );
1266 return sqlQueryInt( db, sql, -1 );
1271 QString sql = QStringLiteral(
"SELECT COUNT(\"fid\") FROM 'log_added_features' WHERE \"layer_id\" = %1 AND \"fid\" = %2" ).arg( layerId ).arg( fid );
1272 return ( sqlQueryInt( db, sql, 0 ) > 0 );
1275 int QgsOfflineEditing::sqlExec(
sqlite3 *db,
const QString &sql )
1277 char *errmsg =
nullptr;
1278 int rc = sqlite3_exec( db, sql.toUtf8(),
nullptr,
nullptr, &errmsg );
1279 if ( rc != SQLITE_OK )
1281 showWarning( errmsg );
1286 int QgsOfflineEditing::sqlQueryInt(
sqlite3 *db,
const QString &sql,
int defaultValue )
1288 sqlite3_stmt *stmt =
nullptr;
1289 if ( sqlite3_prepare_v2( db, sql.toUtf8().constData(), -1, &stmt, nullptr ) != SQLITE_OK )
1291 showWarning( sqlite3_errmsg( db ) );
1292 return defaultValue;
1295 int value = defaultValue;
1296 int ret = sqlite3_step( stmt );
1297 if ( ret == SQLITE_ROW )
1299 value = sqlite3_column_int( stmt, 0 );
1301 sqlite3_finalize( stmt );
1306 QList<int> QgsOfflineEditing::sqlQueryInts(
sqlite3 *db,
const QString &sql )
1310 sqlite3_stmt *stmt =
nullptr;
1311 if ( sqlite3_prepare_v2( db, sql.toUtf8().constData(), -1, &stmt, nullptr ) != SQLITE_OK )
1313 showWarning( sqlite3_errmsg( db ) );
1317 int ret = sqlite3_step( stmt );
1318 while ( ret == SQLITE_ROW )
1320 values << sqlite3_column_int( stmt, 0 );
1322 ret = sqlite3_step( stmt );
1324 sqlite3_finalize( stmt );
1329 QList<QgsField> QgsOfflineEditing::sqlQueryAttributesAdded(
sqlite3 *db,
const QString &sql )
1331 QList<QgsField> values;
1333 sqlite3_stmt *stmt =
nullptr;
1334 if ( sqlite3_prepare_v2( db, sql.toUtf8().constData(), -1, &stmt, nullptr ) != SQLITE_OK )
1336 showWarning( sqlite3_errmsg( db ) );
1340 int ret = sqlite3_step( stmt );
1341 while ( ret == SQLITE_ROW )
1343 QgsField field( QString( reinterpret_cast< const char * >( sqlite3_column_text( stmt, 0 ) ) ),
1344 static_cast< QVariant::Type >( sqlite3_column_int( stmt, 1 ) ),
1346 sqlite3_column_int( stmt, 2 ),
1347 sqlite3_column_int( stmt, 3 ),
1348 QString( reinterpret_cast< const char * >( sqlite3_column_text( stmt, 4 ) ) ) );
1351 ret = sqlite3_step( stmt );
1353 sqlite3_finalize( stmt );
1362 sqlite3_stmt *stmt =
nullptr;
1363 if ( sqlite3_prepare_v2( db, sql.toUtf8().constData(), -1, &stmt, nullptr ) != SQLITE_OK )
1365 showWarning( sqlite3_errmsg( db ) );
1369 int ret = sqlite3_step( stmt );
1370 while ( ret == SQLITE_ROW )
1372 values << sqlite3_column_int( stmt, 0 );
1374 ret = sqlite3_step( stmt );
1376 sqlite3_finalize( stmt );
1381 QgsOfflineEditing::AttributeValueChanges QgsOfflineEditing::sqlQueryAttributeValueChanges(
sqlite3 *db,
const QString &sql )
1383 AttributeValueChanges values;
1385 sqlite3_stmt *stmt =
nullptr;
1386 if ( sqlite3_prepare_v2( db, sql.toUtf8().constData(), -1, &stmt, nullptr ) != SQLITE_OK )
1388 showWarning( sqlite3_errmsg( db ) );
1392 int ret = sqlite3_step( stmt );
1393 while ( ret == SQLITE_ROW )
1395 AttributeValueChange change;
1396 change.fid = sqlite3_column_int( stmt, 0 );
1397 change.attr = sqlite3_column_int( stmt, 1 );
1398 change.value = QString( reinterpret_cast< const char * >( sqlite3_column_text( stmt, 2 ) ) );
1401 ret = sqlite3_step( stmt );
1403 sqlite3_finalize( stmt );
1408 QgsOfflineEditing::GeometryChanges QgsOfflineEditing::sqlQueryGeometryChanges(
sqlite3 *db,
const QString &sql )
1410 GeometryChanges values;
1412 sqlite3_stmt *stmt =
nullptr;
1413 if ( sqlite3_prepare_v2( db, sql.toUtf8().constData(), -1, &stmt, nullptr ) != SQLITE_OK )
1415 showWarning( sqlite3_errmsg( db ) );
1419 int ret = sqlite3_step( stmt );
1420 while ( ret == SQLITE_ROW )
1422 GeometryChange change;
1423 change.fid = sqlite3_column_int( stmt, 0 );
1424 change.geom_wkt = QString( reinterpret_cast< const char * >( sqlite3_column_text( stmt, 1 ) ) );
1427 ret = sqlite3_step( stmt );
1429 sqlite3_finalize( stmt );
1434 void QgsOfflineEditing::committedAttributesAdded(
const QString &qgisLayerId,
const QList<QgsField> &addedAttributes )
1441 int layerId = getOrCreateLayerId( database.get(), qgisLayerId );
1442 int commitNo = getCommitNo( database.get() );
1444 for ( QList<QgsField>::const_iterator it = addedAttributes.begin(); it != addedAttributes.end(); ++it )
1447 QString sql = QStringLiteral(
"INSERT INTO 'log_added_attrs' VALUES ( %1, %2, '%3', %4, %5, %6, '%7' )" )
1450 .arg( field.
name() )
1451 .arg( field.
type() )
1455 sqlExec( database.get(), sql );
1458 increaseCommitNo( database.get() );
1461 void QgsOfflineEditing::committedFeaturesAdded(
const QString &qgisLayerId,
const QgsFeatureList &addedFeatures )
1468 int layerId = getOrCreateLayerId( database.get(), qgisLayerId );
1477 if ( !offlinePath.contains(
".gpkg" ) )
1479 tableName = uri.
table();
1483 tableName = uri.
param( offlinePath +
"|layername" );
1487 QString sql = QStringLiteral(
"SELECT ROWID FROM '%1' ORDER BY ROWID DESC LIMIT %2" ).arg( tableName ).arg( addedFeatures.size() );
1488 QList<int> newFeatureIds = sqlQueryInts( database.get(), sql );
1489 for (
int i = newFeatureIds.size() - 1; i >= 0; i-- )
1491 QString sql = QStringLiteral(
"INSERT INTO 'log_added_features' VALUES ( %1, %2 )" )
1493 .arg( newFeatureIds.at( i ) );
1494 sqlExec( database.get(), sql );
1498 void QgsOfflineEditing::committedFeaturesRemoved(
const QString &qgisLayerId,
const QgsFeatureIds &deletedFeatureIds )
1505 int layerId = getOrCreateLayerId( database.get(), qgisLayerId );
1507 for ( QgsFeatureIds::const_iterator it = deletedFeatureIds.begin(); it != deletedFeatureIds.end(); ++it )
1509 if ( isAddedFeature( database.get(), layerId, *it ) )
1512 QString sql = QStringLiteral(
"DELETE FROM 'log_added_features' WHERE \"layer_id\" = %1 AND \"fid\" = %2" ).arg( layerId ).arg( *it );
1513 sqlExec( database.get(), sql );
1517 QString sql = QStringLiteral(
"INSERT INTO 'log_removed_features' VALUES ( %1, %2)" )
1520 sqlExec( database.get(), sql );
1525 void QgsOfflineEditing::committedAttributeValuesChanges(
const QString &qgisLayerId,
const QgsChangedAttributesMap &changedAttrsMap )
1532 int layerId = getOrCreateLayerId( database.get(), qgisLayerId );
1533 int commitNo = getCommitNo( database.get() );
1535 for ( QgsChangedAttributesMap::const_iterator cit = changedAttrsMap.begin(); cit != changedAttrsMap.end(); ++cit )
1538 if ( isAddedFeature( database.get(), layerId, fid ) )
1544 for ( QgsAttributeMap::const_iterator it = attrMap.constBegin(); it != attrMap.constEnd(); ++it )
1546 QString sql = QStringLiteral(
"INSERT INTO 'log_feature_updates' VALUES ( %1, %2, %3, %4, '%5' )" )
1551 .arg( it.value().toString() );
1552 sqlExec( database.get(), sql );
1556 increaseCommitNo( database.get() );
1559 void QgsOfflineEditing::committedGeometriesChanges(
const QString &qgisLayerId,
const QgsGeometryMap &changedGeometries )
1566 int layerId = getOrCreateLayerId( database.get(), qgisLayerId );
1567 int commitNo = getCommitNo( database.get() );
1569 for ( QgsGeometryMap::const_iterator it = changedGeometries.begin(); it != changedGeometries.end(); ++it )
1572 if ( isAddedFeature( database.get(), layerId, fid ) )
1578 QString sql = QStringLiteral(
"INSERT INTO 'log_geometry_updates' VALUES ( %1, %2, %3, '%4' )" )
1582 .arg( geom.
asWkt() );
1583 sqlExec( database.get(), sql );
1588 increaseCommitNo( database.get() );
1591 void QgsOfflineEditing::startListenFeatureChanges()
1599 this, &QgsOfflineEditing::committedAttributesAdded );
1601 this, &QgsOfflineEditing::committedAttributeValuesChanges );
1603 this, &QgsOfflineEditing::committedGeometriesChanges );
1606 this, &QgsOfflineEditing::committedFeaturesAdded );
1608 this, &QgsOfflineEditing::committedFeaturesRemoved );
1611 void QgsOfflineEditing::stopListenFeatureChanges()
1619 this, &QgsOfflineEditing::committedAttributesAdded );
1621 this, &QgsOfflineEditing::committedAttributeValuesChanges );
1623 this, &QgsOfflineEditing::committedGeometriesChanges );
1626 this, &QgsOfflineEditing::committedFeaturesAdded );
1628 this, &QgsOfflineEditing::committedFeaturesRemoved );
1631 void QgsOfflineEditing::layerAdded(
QgsMapLayer *layer )
const QList< QgsVectorLayerJoinInfo > vectorJoins() const
Layer tree group node serves as a container for layers and further groups.
void setJoinLayer(QgsVectorLayer *layer)
Sets weak reference to the joined layer.
The class is used as a container of context for various read/write operations on other objects...
Wrapper for iterator of features from vector data provider or vector layer.
QMap< QgsFeatureId, QgsGeometry > QgsGeometryMap
void layerProgressUpdated(int layer, int numLayers)
Is emitted whenever a new layer is being processed.
int open(const QString &path)
Opens the database at the specified file path.
bool addJoin(const QgsVectorLayerJoinInfo &joinInfo)
Joins another vector layer to this layer.
int open_v2(const QString &path, int flags, const char *zVfs)
Opens the database at the specified file path.
Base class for all map layer types.
void setLayer(QgsMapLayer *layer)
Sets the map layer for this record.
QgsAttributeList attributeList() const
Returns list of attribute indexes.
QString title() const
Returns the project's title.
Filter using feature IDs.
QSet< QgsFeatureId > QgsFeatureIds
QString joinLayerId() const
ID of the joined layer - may be used to resolve reference to the joined layer.
bool isValid() const
Returns the status of the layer.
void removeFieldConstraint(int index, QgsFieldConstraints::Constraint constraint)
Removes a constraint for a specified field index.
virtual bool importNamedStyle(QDomDocument &doc, QString &errorMsg, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Import the properties of this layer from a QDomDocument.
#define PROJECT_ENTRY_KEY_OFFLINE_DB_PATH
void setSnappingConfig(const QgsSnappingConfig &snappingConfig)
The snapping configuration for this project.
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer. Properties are stored in a map and saved in project file...
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
QStringList commitErrors() const
Returns a list containing any error messages generated when attempting to commit changes to the layer...
QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
bool deleteFeature(QgsFeatureId fid)
Deletes a feature from the layer (but does not commit it).
void committedAttributesAdded(const QString &layerId, const QList< QgsField > &addedAttributes)
QList< QgsFeature > QgsFeatureList
#define CUSTOM_PROPERTY_IS_OFFLINE_EDITABLE
Individual map theme record of visible layers and styles.
bool commitChanges()
Attempts to commit to the underlying data provider any buffered changes made since the last to call t...
void setReferencingLayer(const QString &id)
Set the referencing (child) layer id.
void update(const QString &name, const QgsMapThemeCollection::MapThemeRecord &state)
Updates a map theme within the collection.
bool startEditing()
Makes the layer editable.
void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
QString toWkt() const
Returns a WKT representation of this CRS.
#define CUSTOM_PROPERTY_REMOTE_SOURCE
Container of fields for a vector layer.
A geometry is the spatial representation of a feature.
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
void removeChildNode(QgsLayerTreeNode *node)
Remove a child node from this group.
QString source() const
Returns the source for the layer.
Individual record of a visible layer in a map theme record.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
QList< QgsRelation > referencingRelations(const QgsVectorLayer *layer=nullptr, int fieldIdx=-2) const
Gets all relations where the specified layer (and field) is the referencing part (i.e.
QString readEntry(const QString &scope, const QString &key, const QString &def=QString(), bool *ok=nullptr) const
void committedFeaturesRemoved(const QString &layerId, const QgsFeatureIds &deletedFeatureIds)
This signal is emitted, when features are deleted from the provider.
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
virtual QString name() const =0
Returns a provider name.
void setIndividualLayerSettings(QgsVectorLayer *vl, const QgsSnappingConfig::IndividualLayerSettings &individualLayerSettings)
Sets individual layer snappings settings (applied if mode is AdvancedConfiguration) ...
void removeLayerRecord(QgsMapLayer *layer)
Removes a record for layer if present.
QString param(const QString &key) const
Gets generic param (generic mode)
bool isVisible() const
Returns whether a node is really visible (ie checked and all its ancestors checked as well) ...
bool writeEntry(const QString &scope, const QString &key, bool value)
Write a boolean entry to the project file.
void progressUpdated(int progress)
Emitted with the progress of the current mode.
void committedGeometriesChanges(const QString &layerId, const QgsGeometryMap &changedGeometries)
QgsVectorLayerEditBuffer * editBuffer()
Buffer with uncommitted editing operations. Only valid after editing has been turned on...
Type
The WKB type describes the number of dimensions a geometry has.
void setCustomLayerOrder(const QList< QgsMapLayer * > &customLayerOrder)
The order in which layers will be rendered on the canvas.
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QgsMapThemeCollection mapThemeCollection
void progressStopped()
Emitted when the processing of all layers has finished.
bool changeGeometry(QgsFeatureId fid, QgsGeometry &geometry, bool skipDefaultValue=false)
Changes a feature's geometry within the layer's edit buffer (but does not immediately commit the chan...
Unique pointer for spatialite databases, which automatically closes the database when the pointer goe...
QString errorMessage() const
Returns the most recent error message encountered by the database.
#define QgsDebugMsgLevel(str, level)
void reload() FINAL
Synchronises with changes in the datasource.
QgsFields fields() const override=0
Returns the fields associated with this data provider.
void setTypeName(const QString &typeName)
Set the field type.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsLayerTreeNode * parent()
Gets pointer to the parent. If parent is a null pointer, the node is a root node. ...
void committedFeaturesAdded(const QString &layerId, const QgsFeatureList &addedFeatures)
This signal is emitted, when features are added to the provider.
static QgsFeature createFeature(const QgsVectorLayer *layer, const QgsGeometry &geometry=QgsGeometry(), const QgsAttributeMap &attributes=QgsAttributeMap(), QgsExpressionContext *context=nullptr)
Creates a new feature ready for insertion into a layer.
Defines left outer join from our vector layer to some other vector layer.
QMap< int, QVariant > QgsAttributeMap
int fieldOriginIndex(int fieldIdx) const
Gets field's origin index (its meaning is specific to each type of origin)
void editingStopped()
Is emitted, when edited changes successfully have been written to the data provider.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QList< QgsVectorDataProvider::NativeType > nativeTypes() const
Returns the names of the supported types.
This class is a base class for nodes in a layer tree.
ContainerType
Type of offline database container file.
long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
bool removeEntry(const QString &scope, const QString &key)
Remove the given key.
int count() const
Returns number of items.
FilterType filterType() const
Returns the filter type which is currently set on this request.
QHash< QgsVectorLayer *, QgsSnappingConfig::IndividualLayerSettings > individualLayerSettings() const
Returns individual snapping settings for all layers.
Encapsulate a field in an attribute table or data source.
const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
QgsRelationManager relationManager
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
QgsField field(int fieldIdx) const
Gets field at particular index (must be in range 0..N-1)
void editingStarted()
Is emitted, when editing on this layer has started.
QgsExpressionContext createExpressionContext() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
int open(const QString &path)
Opens the database at the specified file path.
#define PROJECT_ENTRY_SCOPE_OFFLINE
void setReferencedLayer(const QString &id)
Set the referenced (parent) layer id.
QList< QgsMapLayer * > customLayerOrder() const
The order in which layers will be rendered on the canvas.
Unique pointer for sqlite3 databases, which automatically closes the database when the pointer goes o...
#define CUSTOM_SHOW_FEATURE_COUNT
bool removeLayers(const QList< QgsMapLayer * > &layers)
Removes the specified layers from the individual layer configuration.
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
QgsMapLayer * layer() const
Returns map layer or null if the layer does not exist anymore.
bool convertToOfflineProject(const QString &offlineDataPath, const QString &offlineDbFile, const QStringList &layerIds, bool onlySelected=false, ContainerType containerType=SpatiaLite)
Convert current project for offline editing.
QList< QgsRelation > referencedRelations(QgsVectorLayer *layer=nullptr) const
Gets all relations where this layer is the referenced part (i.e.
QString providerType() const
Returns the provider type for this layer.
void warning(const QString &title, const QString &message)
Emitted when a warning needs to be displayed.
Custom properties (by plugins for instance)
QgsMapThemeCollection::MapThemeRecord mapThemeState(const QString &name) const
Returns the recorded state of a map theme.
QString asWkt(int precision=17) const
Exports the geometry to WKT.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets feature IDs that should be fetched.
void insertChildNode(int index, QgsLayerTreeNode *node)
Insert existing node at specified position.
QMap< QgsFeatureId, QgsAttributeMap > QgsChangedAttributesMap
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const override=0
Query the provider for features specified in request.
long featureCount() const override=0
Number of features in the layer.
QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
void synchronize()
Synchronize to remote layers.
This class manages a set of relations between layers.
void committedAttributeValuesChanges(const QString &layerId, const QgsChangedAttributesMap &changedAttributesValues)
static QgsProject * instance()
Returns the QgsProject singleton instance.
std::unique_ptr< std::remove_pointer< OGRFieldDefnH >::type, OGRFldDeleter > ogr_field_def_unique_ptr
Scoped OGR field definition.
QgsAttributeMap toMap() const
Returns a QgsAttributeMap of the attribute values.
void setTitle(const QString &title)
Sets the project's title.
QList< QgsMapThemeCollection::MapThemeLayerRecord > layerRecords() const
Returns a list of records for all visible layer belonging to the theme.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=nullptr) FINAL
Adds a single feature to the sink.
QString authid() const
Returns the authority identifier for the CRS.
static QString displayString(Type type)
Returns a display string type for a WKB type, e.g., the geometry name used in WKT geometry representa...
void progressModeSet(QgsOfflineEditing::ProgressMode mode, int maximum)
Is emitted when the mode for the progress of the current operation is set.
void setItemVisibilityChecked(bool checked)
Check or uncheck a node (independently of its ancestors or children)
void removeMapLayers(const QStringList &layerIds)
Remove a set of layers from the registry by layer ID.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Query the layer for features specified in request.
static bool hasM(Type type)
Tests whether a WKB type contains m values.
virtual void exportNamedStyle(QDomDocument &doc, QString &errorMsg, const QgsReadWriteContext &context=QgsReadWriteContext(), QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const
Export the properties of this layer as named style in a QDomDocument.
bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant(), bool skipDefaultValues=false)
Changes an attribute value for a feature (but does not immediately commit the changes).
QString dataComment() const
Returns a description for this layer as defined in the data provider.
void removeRelation(const QString &id)
Remove a relation.
Container class that allows storage of map themes consisting of visible map layers and layer styles...
This is a container for configuration of the snapping of the project.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider.
QgsLayerTree * layerTreeRoot() const
Returns pointer to the root (invisible) node of the project's layer tree.
QList< int > QgsAttributeList
QList< QgsVectorLayerJoinInfo > QgsVectorJoinList
bool nextFeature(QgsFeature &f)
This is the base class for vector data providers.
std::unique_ptr< std::remove_pointer< OGRDataSourceH >::type, OGRDataSourceDeleter > ogr_datasource_unique_ptr
Scoped OGR data source.
Geometry is not required. It may still be returned if e.g. required for a filter condition.
bool isOfflineProject() const
Returns true if current project is offline.
Class for storing the component parts of a PostgreSQL/RDBMS datasource URI.
virtual void invalidateConnections(const QString &connection)
Invalidate connections corresponding to specified name.
virtual QString defaultValueClause(int fieldIndex) const
Returns any default value clauses which are present at the provider for a specified field index...
Represents a vector layer which manages a vector based data sets.
QgsLayerTreeLayer * findLayer(QgsMapLayer *layer) const
Find layer node representing the map layer.
bool addAttribute(const QgsField &field)
Add an attribute field (but does not commit it) returns true if the field was added.
QString table() const
Returns the table.
static Type flatType(Type type)
Returns the flat type for a WKB type.
QList< QgsMapLayer * > addMapLayers(const QList< QgsMapLayer * > &mapLayers, bool addToLegend=true, bool takeOwnership=true)
Add a list of layers to the map of loaded layers.
QgsSnappingConfig snappingConfig
#define CUSTOM_PROPERTY_REMOTE_PROVIDER
void progressStarted()
The signal is emitted when the process has started.
QMap< QString, QgsMapLayer * > mapLayers() const
Returns a map of all registered layers by layer ID.
QgsLayerTreeLayer * clone() const override
Create a copy of the node. Returns new instance.
void addLayerRecord(const QgsMapThemeCollection::MapThemeLayerRecord &record)
Add a new record for a layer.
QgsCoordinateReferenceSystem crs
void * OGRSpatialReferenceH
void layerWasAdded(QgsMapLayer *layer)
Emitted when a layer was added to the registry.
void setCustomProperty(const QString &key, const QVariant &value)
Sets a custom property for the node. Properties are stored in a map and saved in project file...
Layer tree node points to a map layer.
void addRelation(const QgsRelation &relation)
Add a relation.