35 #include <QDomDocument> 38 #include <QMessageBox> 43 #include <spatialite.h> 50 #define CUSTOM_PROPERTY_IS_OFFLINE_EDITABLE "isOfflineEditable" 51 #define CUSTOM_PROPERTY_REMOTE_SOURCE "remoteSource" 52 #define CUSTOM_PROPERTY_REMOTE_PROVIDER "remoteProvider" 53 #define PROJECT_ENTRY_SCOPE_OFFLINE "OfflineEditingPlugin" 54 #define PROJECT_ENTRY_KEY_OFFLINE_DB_PATH "/OfflineDbPath" 76 if ( createSpatialiteDB( dbPath ) )
80 if ( rc != SQLITE_OK )
82 showWarning(
tr(
"Could not open the spatialite database" ) );
87 createLoggingTables( db );
94 for (
int i = 0; i < layerIds.
count(); i++ )
104 QgsVectorJoinList::iterator it = joins.
begin();
105 while ( it != joins.end() )
107 if (( *it ).prefix.isNull() )
112 ( *it ).prefix = vl->
name() +
'_';
116 joinInfoBuffer.
insert( vl->
id(), joins );
120 for (
int i = 0; i < layerIds.
count(); i++ )
131 layerIdMapping.
insert( origLayerId, newLayer );
146 if ( newJoinedLayer )
167 projectTitle +=
" (offline)";
212 offlineLayers << layer;
216 for (
int l = 0; l < offlineLayers.
count(); l++ )
239 copySymbology( offlineLayer, remoteLayer );
243 QString sql =
QString(
"SELECT \"id\" FROM 'log_layer_ids' WHERE \"qgis_id\" = '%1'" ).
arg( qgisLayerId );
244 int layerId = sqlQueryInt( db, sql, -1 );
250 int commitNo = getCommitNo( db );
251 for (
int i = 0; i < commitNo; i++ )
254 applyAttributesAdded( remoteLayer, db, layerId, i );
255 applyAttributeValueChanges( offlineLayer, remoteLayer, db, layerId, i );
256 applyGeometryChanges( remoteLayer, db, layerId, i );
259 applyFeaturesAdded( offlineLayer, remoteLayer, db, layerId );
260 applyFeaturesRemoved( remoteLayer, db, layerId );
265 updateFidLookup( remoteLayer, db, layerId );
268 sql =
QString(
"DELETE FROM 'log_added_attrs' WHERE \"layer_id\" = %1" ).
arg( layerId );
270 sql =
QString(
"DELETE FROM 'log_added_features' WHERE \"layer_id\" = %1" ).
arg( layerId );
272 sql =
QString(
"DELETE FROM 'log_removed_features' WHERE \"layer_id\" = %1" ).
arg( layerId );
274 sql =
QString(
"DELETE FROM 'log_feature_updates' WHERE \"layer_id\" = %1" ).
arg( layerId );
276 sql =
QString(
"DELETE FROM 'log_geometry_updates' WHERE \"layer_id\" = %1" ).
arg( layerId );
280 QString sql =
QString(
"UPDATE 'log_indices' SET 'last_index' = 0 WHERE \"name\" = 'commit_no'" );
307 void QgsOfflineEditing::initializeSpatialMetadata(
sqlite3 *sqlite_handle )
310 if ( !sqlite_handle )
315 int ret = sqlite3_get_table( sqlite_handle,
"select count(*) from sqlite_master", &results, &rows, &columns,
nullptr );
316 if ( ret != SQLITE_OK )
321 for (
int i = 1; i <= rows; i++ )
322 count = atoi( results[( i * columns ) + 0] );
325 sqlite3_free_table( results );
330 bool above41 =
false;
331 ret = sqlite3_get_table( sqlite_handle,
"select spatialite_version()", &results, &rows, &columns,
nullptr );
332 if ( ret == SQLITE_OK && rows == 1 && columns == 1 )
336 if ( parts.
size() >= 1 )
339 above41 = verparts.
size() >= 2 && ( verparts[0].toInt() > 4 || ( verparts[0].toInt() == 4 && verparts[1].toInt() >= 1 ) );
343 sqlite3_free_table( results );
346 char *errMsg =
nullptr;
347 ret = sqlite3_exec( sqlite_handle, above41 ?
"SELECT InitSpatialMetadata(1)" :
"SELECT InitSpatialMetadata()",
nullptr,
nullptr, &errMsg );
349 if ( ret != SQLITE_OK )
351 QString errCause =
tr(
"Unable to initialize SpatialMetadata:\n" );
353 showWarning( errCause );
354 sqlite3_free( errMsg );
357 spatial_ref_sys_init( sqlite_handle, 0 );
360 bool QgsOfflineEditing::createSpatialiteDB(
const QString& offlineDbPath )
364 char *errMsg =
nullptr;
365 QFile newDb( offlineDbPath );
385 QString errCause =
tr(
"Could not create a new database\n" );
387 sqlite3_close( sqlite_handle );
388 showWarning( errCause );
392 ret = sqlite3_exec( sqlite_handle,
"PRAGMA foreign_keys = 1",
nullptr,
nullptr, &errMsg );
393 if ( ret != SQLITE_OK )
395 showWarning(
tr(
"Unable to activate FOREIGN_KEY constraints" ) );
396 sqlite3_free( errMsg );
400 initializeSpatialMetadata( sqlite_handle );
408 void QgsOfflineEditing::createLoggingTables(
sqlite3* db )
411 QString sql =
"CREATE TABLE 'log_indices' ('name' TEXT, 'last_index' INTEGER)";
414 sql =
"INSERT INTO 'log_indices' VALUES ('commit_no', 0)";
417 sql =
"INSERT INTO 'log_indices' VALUES ('layer_id', 0)";
421 sql =
"CREATE TABLE 'log_layer_ids' ('id' INTEGER, 'qgis_id' TEXT)";
425 sql =
"CREATE TABLE 'log_fids' ('layer_id' INTEGER, 'offline_fid' INTEGER, 'remote_fid' INTEGER)";
429 sql =
"CREATE TABLE 'log_added_attrs' ('layer_id' INTEGER, 'commit_no' INTEGER, ";
430 sql +=
"'name' TEXT, 'type' INTEGER, 'length' INTEGER, 'precision' INTEGER, 'comment' TEXT)";
434 sql =
"CREATE TABLE 'log_added_features' ('layer_id' INTEGER, 'fid' INTEGER)";
438 sql =
"CREATE TABLE 'log_removed_features' ('layer_id' INTEGER, 'fid' INTEGER)";
442 sql =
"CREATE TABLE 'log_feature_updates' ('layer_id' INTEGER, 'commit_no' INTEGER, 'fid' INTEGER, 'attr' INTEGER, 'value' TEXT)";
446 sql =
"CREATE TABLE 'log_geometry_updates' ('layer_id' INTEGER, 'commit_no' INTEGER, 'fid' INTEGER, 'geom_wkt' TEXT)";
465 for (
int idx = 0; idx < fields.
count(); ++idx )
468 QVariant::Type type = fields[idx].type();
469 if ( type == QVariant::Int || type == QVariant::LongLong )
471 dataType =
"INTEGER";
473 else if ( type == QVariant::Double )
477 else if ( type == QVariant::String )
483 showWarning(
tr(
"%1: Unknown data type %2. Not using type affinity for the field." ).arg( fields[idx].
name(),
QVariant::typeToName( type ) ) );
486 sql += delim +
QString(
"'%1' %2" ).
arg( fields[idx].
name(), dataType );
491 int rc = sqlExec( db, sql );
503 geomType =
"MULTIPOINT";
506 geomType =
"LINESTRING";
509 geomType =
"MULTILINESTRING";
512 geomType =
"POLYGON";
515 geomType =
"MULTIPOLYGON";
518 showWarning(
tr(
"QGIS wkbType %1 not supported" ).arg( layer->
wkbType() ) );
521 QString sqlAddGeom =
QString(
"SELECT AddGeometryColumn('%1', 'Geometry', %2, '%3', 2)" )
527 QString sqlCreateIndex =
QString(
"SELECT CreateSpatialIndex('%1', 'Geometry')" ).
arg( tableName );
529 if ( rc == SQLITE_OK )
531 rc = sqlExec( db, sqlAddGeom );
532 if ( rc == SQLITE_OK )
534 rc = sqlExec( db, sqlCreateIndex );
539 if ( rc == SQLITE_OK )
545 layer->
name() +
" (offline)",
"spatialite" );
566 copySymbology( layer, newLayer );
572 if ( layerTreeLayer )
575 if ( parentTreeGroup )
580 if ( newLayerTreeLayer )
594 copySymbology( layer, newLayer );
607 int featureCount = 1;
612 remoteFeatureIds << f.
id();
619 for (
int it = 0; it < attrs.
count(); ++it )
621 newAttrs[column++] = attrs.
at( it );
635 int layerId = getOrCreateLayerId( db, newLayer->
id() );
641 offlineFeatureIds << f.
id();
645 sqlExec( db,
"BEGIN" );
646 int remoteCount = remoteFeatureIds.
size();
647 for (
int i = 0; i < remoteCount; i++ )
649 addFidLookup( db, layerId, offlineFeatureIds.at( i ), remoteFeatureIds.
at( remoteCount - ( i + 1 ) ) );
652 sqlExec( db,
"COMMIT" );
668 void QgsOfflineEditing::applyAttributesAdded(
QgsVectorLayer* remoteLayer,
sqlite3* db,
int layerId,
int commitNo )
670 QString sql =
QString(
"SELECT \"name\", \"type\", \"length\", \"precision\", \"comment\" FROM 'log_added_attrs' WHERE \"layer_id\" = %1 AND \"commit_no\" = %2" ).
arg( layerId ).
arg( commitNo );
678 for (
int i = 0; i < nativeTypes.
size(); i++ )
686 for (
int i = 0; i < fields.
size(); i++ )
690 if ( typeNameLookup.contains( field.
type() ) )
698 showWarning(
QString(
"Could not add attribute '%1' of type %2" ).arg( field.
name() ).arg( field.
type() ) );
707 QString sql =
QString(
"SELECT \"fid\" FROM 'log_added_features' WHERE \"layer_id\" = %1" ).
arg( layerId );
708 QList<int> newFeatureIds = sqlQueryInts( db, sql );
713 for (
int i = 0; i < remoteFlds.
count(); ++i )
721 for (
int i = 0; i < newFeatureIds.
size(); i++ )
741 QMap<int, int> attrLookup = attributeLookup( offlineLayer, remoteLayer );
744 for (
int it = 0; it < attrs.
count(); ++it )
746 newAttrs[ attrLookup[ it ] ] = attrs.
at( it );
751 for (
int k = 0; k < newAttrs.
count(); ++k )
753 if ( newAttrs.
at( k ).isNull() && !defaultValues.at( k ).isNull() )
754 newAttrs[k] = defaultValues.
at( k );
765 void QgsOfflineEditing::applyFeaturesRemoved(
QgsVectorLayer* remoteLayer,
sqlite3* db,
int layerId )
767 QString sql =
QString(
"SELECT \"fid\" FROM 'log_removed_features' WHERE \"layer_id\" = %1" ).
arg( layerId );
784 QString sql =
QString(
"SELECT \"fid\", \"attr\", \"value\" FROM 'log_feature_updates' WHERE \"layer_id\" = %1 AND \"commit_no\" = %2 " ).
arg( layerId ).
arg( commitNo );
789 QMap<int, int> attrLookup = attributeLookup( offlineLayer, remoteLayer );
791 for (
int i = 0; i < values.
size(); i++ )
801 void QgsOfflineEditing::applyGeometryChanges(
QgsVectorLayer* remoteLayer,
sqlite3* db,
int layerId,
int commitNo )
803 QString sql =
QString(
"SELECT \"fid\", \"geom_wkt\" FROM 'log_geometry_updates' WHERE \"layer_id\" = %1 AND \"commit_no\" = %2" ).
arg( layerId ).
arg( commitNo );
808 for (
int i = 0; i < values.
size(); i++ )
833 if ( offlineFid( db, layerId, f.
id() ) == -1 )
835 newRemoteFids[ f.
id()] =
true;
843 QString sql =
QString(
"SELECT \"fid\" FROM 'log_added_features' WHERE \"layer_id\" = %1" ).
arg( layerId );
844 QList<int> newOfflineFids = sqlQueryInts( db, sql );
846 if ( newRemoteFids.size() != newOfflineFids.
size() )
854 sqlExec( db,
"BEGIN" );
857 addFidLookup( db, layerId, newOfflineFids.
at( i++ ), it.key() );
859 sqlExec( db,
"COMMIT" );
875 showWarning( error );
885 QMap <
int ,
int > attrLookup;
887 for (
int i = 0; i < remoteAttrs.
size(); i++ )
889 attrLookup.
insert( offlineAttrs.
at( i ), remoteAttrs.
at( i ) );
895 void QgsOfflineEditing::showWarning(
const QString& message )
897 emit
warning(
tr(
"Offline Editing Plugin" ), message );
900 sqlite3* QgsOfflineEditing::openLoggingDb()
907 if ( rc != SQLITE_OK )
909 showWarning(
tr(
"Could not open the spatialite logging database" ) );
917 int QgsOfflineEditing::getOrCreateLayerId(
sqlite3* db,
const QString& qgisLayerId )
919 QString sql =
QString(
"SELECT \"id\" FROM 'log_layer_ids' WHERE \"qgis_id\" = '%1'" ).
arg( qgisLayerId );
920 int layerId = sqlQueryInt( db, sql, -1 );
924 sql =
"SELECT \"last_index\" FROM 'log_indices' WHERE \"name\" = 'layer_id'";
925 int newLayerId = sqlQueryInt( db, sql, -1 );
928 sql =
QString(
"INSERT INTO 'log_layer_ids' VALUES (%1, '%2')" ).
arg( newLayerId ).
arg( qgisLayerId );
933 sql =
QString(
"UPDATE 'log_indices' SET 'last_index' = %1 WHERE \"name\" = 'layer_id'" ).
arg( newLayerId + 1 );
936 layerId = newLayerId;
942 int QgsOfflineEditing::getCommitNo(
sqlite3* db )
944 QString sql =
"SELECT \"last_index\" FROM 'log_indices' WHERE \"name\" = 'commit_no'";
945 return sqlQueryInt( db, sql, -1 );
948 void QgsOfflineEditing::increaseCommitNo(
sqlite3* db )
950 QString sql =
QString(
"UPDATE 'log_indices' SET 'last_index' = %1 WHERE \"name\" = 'commit_no'" ).
arg( getCommitNo( db ) + 1 );
956 QString sql =
QString(
"INSERT INTO 'log_fids' VALUES ( %1, %2, %3 )" ).
arg( layerId ).
arg( offlineFid ).
arg( remoteFid );
962 QString sql =
QString(
"SELECT \"remote_fid\" FROM 'log_fids' WHERE \"layer_id\" = %1 AND \"offline_fid\" = %2" ).
arg( layerId ).
arg( offlineFid );
963 return sqlQueryInt( db, sql, -1 );
968 QString sql =
QString(
"SELECT \"offline_fid\" FROM 'log_fids' WHERE \"layer_id\" = %1 AND \"remote_fid\" = %2" ).
arg( layerId ).
arg( remoteFid );
969 return sqlQueryInt( db, sql, -1 );
974 QString sql =
QString(
"SELECT COUNT(\"fid\") FROM 'log_added_features' WHERE \"layer_id\" = %1 AND \"fid\" = %2" ).
arg( layerId ).
arg( fid );
975 return ( sqlQueryInt( db, sql, 0 ) > 0 );
981 int rc = sqlite3_exec( db, sql.
toUtf8(),
nullptr,
nullptr, &errmsg );
982 if ( rc != SQLITE_OK )
984 showWarning( errmsg );
989 int QgsOfflineEditing::sqlQueryInt(
sqlite3* db,
const QString& sql,
int defaultValue )
991 sqlite3_stmt* stmt =
nullptr;
992 if ( sqlite3_prepare_v2( db, sql.
toUtf8().
constData(), -1, &stmt, nullptr ) != SQLITE_OK )
994 showWarning( sqlite3_errmsg( db ) );
998 int value = defaultValue;
999 int ret = sqlite3_step( stmt );
1000 if ( ret == SQLITE_ROW )
1002 value = sqlite3_column_int( stmt, 0 );
1004 sqlite3_finalize( stmt );
1013 sqlite3_stmt* stmt =
nullptr;
1014 if ( sqlite3_prepare_v2( db, sql.
toUtf8().
constData(), -1, &stmt, nullptr ) != SQLITE_OK )
1016 showWarning( sqlite3_errmsg( db ) );
1020 int ret = sqlite3_step( stmt );
1021 while ( ret == SQLITE_ROW )
1023 values << sqlite3_column_int( stmt, 0 );
1025 ret = sqlite3_step( stmt );
1027 sqlite3_finalize( stmt );
1036 sqlite3_stmt* stmt =
nullptr;
1037 if ( sqlite3_prepare_v2( db, sql.
toUtf8().
constData(), -1, &stmt, nullptr ) != SQLITE_OK )
1039 showWarning( sqlite3_errmsg( db ) );
1043 int ret = sqlite3_step( stmt );
1044 while ( ret == SQLITE_ROW )
1046 QgsField field(
QString( reinterpret_cast< const char* >( sqlite3_column_text( stmt, 0 ) ) ),
1047 static_cast< QVariant::Type >( sqlite3_column_int( stmt, 1 ) ),
1049 sqlite3_column_int( stmt, 2 ),
1050 sqlite3_column_int( stmt, 3 ),
1051 QString( reinterpret_cast< const char* >( sqlite3_column_text( stmt, 4 ) ) ) );
1054 ret = sqlite3_step( stmt );
1056 sqlite3_finalize( stmt );
1065 sqlite3_stmt* stmt =
nullptr;
1066 if ( sqlite3_prepare_v2( db, sql.
toUtf8().
constData(), -1, &stmt, nullptr ) != SQLITE_OK )
1068 showWarning( sqlite3_errmsg( db ) );
1072 int ret = sqlite3_step( stmt );
1073 while ( ret == SQLITE_ROW )
1075 values << sqlite3_column_int( stmt, 0 );
1077 ret = sqlite3_step( stmt );
1079 sqlite3_finalize( stmt );
1088 sqlite3_stmt* stmt =
nullptr;
1089 if ( sqlite3_prepare_v2( db, sql.
toUtf8().
constData(), -1, &stmt, nullptr ) != SQLITE_OK )
1091 showWarning( sqlite3_errmsg( db ) );
1095 int ret = sqlite3_step( stmt );
1096 while ( ret == SQLITE_ROW )
1098 AttributeValueChange change;
1099 change.fid = sqlite3_column_int( stmt, 0 );
1100 change.attr = sqlite3_column_int( stmt, 1 );
1101 change.value =
QString( reinterpret_cast< const char* >( sqlite3_column_text( stmt, 2 ) ) );
1104 ret = sqlite3_step( stmt );
1106 sqlite3_finalize( stmt );
1115 sqlite3_stmt* stmt =
nullptr;
1116 if ( sqlite3_prepare_v2( db, sql.
toUtf8().
constData(), -1, &stmt, nullptr ) != SQLITE_OK )
1118 showWarning( sqlite3_errmsg( db ) );
1122 int ret = sqlite3_step( stmt );
1123 while ( ret == SQLITE_ROW )
1125 GeometryChange change;
1126 change.fid = sqlite3_column_int( stmt, 0 );
1127 change.geom_wkt =
QString( reinterpret_cast< const char* >( sqlite3_column_text( stmt, 1 ) ) );
1130 ret = sqlite3_step( stmt );
1132 sqlite3_finalize( stmt );
1137 void QgsOfflineEditing::committedAttributesAdded(
const QString& qgisLayerId,
const QList<QgsField>& addedAttributes )
1139 sqlite3* db = openLoggingDb();
1144 int layerId = getOrCreateLayerId( db, qgisLayerId );
1145 int commitNo = getCommitNo( db );
1150 QString sql =
QString(
"INSERT INTO 'log_added_attrs' VALUES ( %1, %2, '%3', %4, %5, %6, '%7' )" )
1154 .arg( field.
type() )
1161 increaseCommitNo( db );
1162 sqlite3_close( db );
1165 void QgsOfflineEditing::committedFeaturesAdded(
const QString& qgisLayerId,
const QgsFeatureList& addedFeatures )
1167 sqlite3* db = openLoggingDb();
1172 int layerId = getOrCreateLayerId( db, qgisLayerId );
1179 QString sql =
QString(
"SELECT ROWID FROM '%1' ORDER BY ROWID DESC LIMIT %2" ).
arg( uri.
table() ).arg( addedFeatures.
size() );
1180 QList<int> newFeatureIds = sqlQueryInts( db, sql );
1181 for (
int i = newFeatureIds.
size() - 1; i >= 0; i-- )
1183 QString sql =
QString(
"INSERT INTO 'log_added_features' VALUES ( %1, %2 )" )
1185 .
arg( newFeatureIds.
at( i ) );
1189 sqlite3_close( db );
1192 void QgsOfflineEditing::committedFeaturesRemoved(
const QString& qgisLayerId,
const QgsFeatureIds& deletedFeatureIds )
1194 sqlite3* db = openLoggingDb();
1199 int layerId = getOrCreateLayerId( db, qgisLayerId );
1203 if ( isAddedFeature( db, layerId, *it ) )
1206 QString sql =
QString(
"DELETE FROM 'log_added_features' WHERE \"layer_id\" = %1 AND \"fid\" = %2" ).
arg( layerId ).
arg( *it );
1211 QString sql =
QString(
"INSERT INTO 'log_removed_features' VALUES ( %1, %2)" )
1218 sqlite3_close( db );
1223 sqlite3* db = openLoggingDb();
1228 int layerId = getOrCreateLayerId( db, qgisLayerId );
1229 int commitNo = getCommitNo( db );
1231 for ( QgsChangedAttributesMap::const_iterator cit = changedAttrsMap.
begin(); cit != changedAttrsMap.
end(); ++cit )
1234 if ( isAddedFeature( db, layerId, fid ) )
1240 for ( QgsAttributeMap::const_iterator it = attrMap.
begin(); it != attrMap.
end(); ++it )
1242 QString sql =
QString(
"INSERT INTO 'log_feature_updates' VALUES ( %1, %2, %3, %4, '%5' )" )
1247 .arg( it.value().toString() );
1252 increaseCommitNo( db );
1253 sqlite3_close( db );
1256 void QgsOfflineEditing::committedGeometriesChanges(
const QString& qgisLayerId,
const QgsGeometryMap& changedGeometries )
1258 sqlite3* db = openLoggingDb();
1263 int layerId = getOrCreateLayerId( db, qgisLayerId );
1264 int commitNo = getCommitNo( db );
1266 for ( QgsGeometryMap::const_iterator it = changedGeometries.
begin(); it != changedGeometries.
end(); ++it )
1269 if ( isAddedFeature( db, layerId, fid ) )
1275 QString sql =
QString(
"INSERT INTO 'log_geometry_updates' VALUES ( %1, %2, %3, '%4' )" )
1285 increaseCommitNo( db );
1286 sqlite3_close( db );
1289 void QgsOfflineEditing::startListenFeatureChanges()
1305 void QgsOfflineEditing::stopListenFeatureChanges()
1321 void QgsOfflineEditing::layerAdded(
QgsMapLayer* layer )
1327 connect( vLayer, SIGNAL( editingStarted() ),
this, SLOT( startListenFeatureChanges() ) );
1328 connect( vLayer, SIGNAL( editingStopped() ),
this, SLOT( stopListenFeatureChanges() ) );
QgsFeatureId id() const
Get the feature ID for this feature.
virtual QString subsetString()
Get the string (typically sql) used to define a subset of the layer.
Layer tree group node serves as a container for layers and further groups.
Wrapper for iterator of features from vector data provider or vector layer.
void layerProgressUpdated(int layer, int numLayers)
Emit a signal that the next layer of numLayers has started processing.
bool addJoin(const QgsVectorJoinInfo &joinInfo)
Joins another vector layer to this layer.
Base class for all map layer types.
const QList< QgsVectorJoinInfo > vectorJoins() const
QgsAttributeList attributeList() const
Returns list of attribute indexes.
QString name() const
Get the display name of the layer.
#define PROJECT_ENTRY_KEY_OFFLINE_DB_PATH
bool convertToOfflineProject(const QString &offlineDataPath, const QString &offlineDbFile, const QStringList &layerIds)
Convert current project for offline editing.
QList< QgsMapLayer * > addMapLayers(const QList< QgsMapLayer * > &theMapLayers, bool addToLegend=true, bool takeOwnership=true)
Add a list of layers to the map of loaded layers.
bool deleteFeature(QgsFeatureId fid)
Delete a feature from the layer (but does not commit it)
QgsFields fields() const
Returns the list of fields of this layer.
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
#define CUSTOM_PROPERTY_IS_OFFLINE_EDITABLE
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
bool commitChanges()
Attempts to commit any changes to disk.
bool startEditing()
Make layer editable.
const_iterator constBegin() const
const T & at(int i) const
void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
#define Q_NOWARN_DEPRECATED_PUSH
#define CUSTOM_PROPERTY_REMOTE_SOURCE
int precision() const
Gets the precision of the field.
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. The node will be deleted.
void removeMapLayers(const QStringList &theLayerIds)
Remove a set of layers from the registry.
QString source() const
Returns the source for the layer.
QString comment() const
Returns the field comment.
bool addFeature(QgsFeature &f, bool alsoUpdateExtent=true)
Adds a feature.
field comes from the underlying data provider of the vector layer (originIndex = index in provider's ...
QString join(const QString &separator) const
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
QString & remove(int position, int n)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
QString tr(const char *sourceText, const char *disambiguation, int n)
static int sqlite3_close(sqlite3 *)
QgsMapLayer * mapLayer(const QString &theLayerId)
Retrieve a pointer to a loaded layer by id.
QGis::WkbType wkbType() const
Returns the WKBType or WKBUnknown in case of error.
int indexOf(const T &value, int from) const
bool isOfflineProject()
Return true if current project is offline.
long featureCount(QgsSymbolV2 *symbol)
Number of features rendered with specified symbol.
static int sqlite3_open(const char *filename, sqlite3 **ppDb)
const char * name() const
bool writeEntry(const QString &scope, const QString &key, bool value)
void progressUpdated(int progress)
Emit a signal with the progress of the current mode.
QString readEntry(const QString &scope, const QString &key, const QString &def=QString::null, bool *ok=nullptr) const
QgsVectorLayerEditBuffer * editBuffer()
Buffer with uncommitted editing operations. Only valid after editing has been turned on...
int count(const T &value) const
QString fromUtf8(const char *str, int size)
void progressStopped()
Emit a signal that processing of all layers has finished.
QgsAttributes attributes() const
Returns the feature's attributes.
Q_DECL_DEPRECATED void title(const QString &title)
Every project has an associated title string.
void setTypeName(const QString &typeName)
Set the field type.
static int sqlite3_open_v2(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs)
QString name() const
Gets the name of the field.
QgsLayerTreeNode * parent()
Get pointer to the parent. If parent is a null pointer, the node is a root node.
const_iterator constEnd() const
int fieldOriginIndex(int fieldIdx) const
Get field's origin index (its meaning is specific to each type of origin)
const char * constData() const
const QList< NativeType > & nativeTypes() const
Returns the names of the supported types.
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
virtual long featureCount() const =0
Number of features in the layer.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QList< int > QgsAttributeList
This class is a base class for nodes in a layer tree.
QString id() const
Get this layer's unique ID, this ID is used to access this layer from map layer registry.
virtual QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())=0
Query the provider for features specified in request.
bool removeEntry(const QString &scope, const QString &key)
Remove the given key.
int count() const
Return number of items.
bool changeGeometry(QgsFeatureId fid, QgsGeometry *geom)
Change feature's geometry.
Encapsulate a field in an attribute table or data source.
virtual bool importNamedStyle(QDomDocument &doc, QString &errorMsg)
Import the properties of this layer from a QDomDocument.
QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
QList< QgsLayerTreeNode * > children()
Get list of children of the node. Children are owned by the parent.
bool isValid()
Return the status of the layer.
#define PROJECT_ENTRY_SCOPE_OFFLINE
Q_DECL_DEPRECATED bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &value, bool emitSignal)
Changes an attribute value (but does not commit it)
const QStringList & commitErrors()
Class for storing the component parts of a PostgreSQL/RDBMS datasource URI.
virtual void reload() override
Synchronises with changes in the datasource.
const char * typeToName(Type typ)
#define Q_NOWARN_DEPRECATED_POP
const Key key(const T &value) const
long toLong(bool *ok, int base) const
virtual void exportNamedStyle(QDomDocument &doc, QString &errorMsg)
Export the properties of this layer as named style in a QDomDocument.
QString providerType() const
Return the provider type for this layer.
const T & at(int i) const
bool hasGeometryType() const
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
void warning(const QString &title, const QString &message)
Emitted when a warning needs to be displayed.
virtual const QgsFields & fields() const =0
Return a map of indexes with field names for this layer.
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
QString mid(int position, int n) const
virtual QVariant defaultValue(int fieldId)
Returns the default value for field specified by fieldId.
void insertChildNode(int index, QgsLayerTreeNode *node)
Insert existing node at specified position. The node must not have a parent yet. The node will be own...
QString absolutePath() const
void synchronize()
Synchronize to remote layers.
static QgsProject * instance()
access to canonical QgsProject instance
QString table() const
Returns the table.
int length() const
Gets the length of the field.
int count(const T &value) const
void setTitle(const QString &title)
Set project title.
Q_DECL_DEPRECATED bool hasLabelsEnabled() const
Label is on.
QString absoluteFilePath(const QString &fileName) const
FieldOrigin fieldOrigin(int fieldIdx) const
Get field's origin (value from an enumeration)
QString authid() const
Returns the authority identifier for the CRS, which includes both the authority (eg EPSG) and the CRS...
const QMap< QString, QgsMapLayer * > & mapLayers()
Retrieve the mapLayers collection (mainly intended for use by projection)
QStringList split(const QString &sep, const QString &str, bool allowEmptyEntries)
virtual bool setSubsetString(const QString &subset)
Set the string (typically sql) used to define a subset of the layer.
void progressModeSet(QgsOfflineEditing::ProgressMode mode, int maximum)
Emit a signal that sets the mode for the progress of the current operation.
QgsLayerTreeLayer * findLayer(const QString &layerId) const
Find layer node representing the map layer specified by its ID. Searches recursively the whole sub-tr...
const QgsCoordinateReferenceSystem & crs() const
Returns layer's spatial reference system.
iterator insert(const Key &key, const T &value)
static QgsGeometry * fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
QString exportToWkt(int precision=17) const
Exports the geometry to WKT.
QgsVectorDataProvider * dataProvider()
Returns the data provider.
bool nextFeature(QgsFeature &f)
This is the base class for vector data providers.
QgsLayerTreeGroup * layerTreeRoot() const
Return pointer to the root (invisible) node of the project's layer tree.
Geometry is not required. It may still be returned if e.g. required for a filter condition.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Represents a vector layer which manages a vector based data sets.
bool addAttribute(const QgsField &field)
Add an attribute field (but does not commit it) returns true if the field was added.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
#define CUSTOM_PROPERTY_REMOTE_PROVIDER
QString joinLayerId
Source layer.
void progressStarted()
Emit a signal that processing has started.
virtual QgsLayerTreeLayer * clone() const override
Create a copy of the node. Returns new instance.
bool mkpath(const QString &dirPath) const
Layer tree node points to a map layer.
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
const T value(const Key &key) const
QByteArray toUtf8() const