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)";
214 offlineLayers << layer;
218 for (
int l = 0; l < offlineLayers.
count(); l++ )
241 copySymbology( offlineLayer, remoteLayer );
245 QString sql =
QString(
"SELECT \"id\" FROM 'log_layer_ids' WHERE \"qgis_id\" = '%1'" ).
arg( qgisLayerId );
246 int layerId = sqlQueryInt( db, sql, -1 );
252 int commitNo = getCommitNo( db );
253 for (
int i = 0; i < commitNo; i++ )
256 applyAttributesAdded( remoteLayer, db, layerId, i );
257 applyAttributeValueChanges( offlineLayer, remoteLayer, db, layerId, i );
258 applyGeometryChanges( remoteLayer, db, layerId, i );
261 applyFeaturesAdded( offlineLayer, remoteLayer, db, layerId );
262 applyFeaturesRemoved( remoteLayer, db, layerId );
267 updateFidLookup( remoteLayer, db, layerId );
270 sql =
QString(
"DELETE FROM 'log_added_attrs' WHERE \"layer_id\" = %1" ).
arg( layerId );
272 sql =
QString(
"DELETE FROM 'log_added_features' WHERE \"layer_id\" = %1" ).
arg( layerId );
274 sql =
QString(
"DELETE FROM 'log_removed_features' WHERE \"layer_id\" = %1" ).
arg( layerId );
276 sql =
QString(
"DELETE FROM 'log_feature_updates' WHERE \"layer_id\" = %1" ).
arg( layerId );
278 sql =
QString(
"DELETE FROM 'log_geometry_updates' WHERE \"layer_id\" = %1" ).
arg( layerId );
282 QString sql =
QString(
"UPDATE 'log_indices' SET 'last_index' = 0 WHERE \"name\" = 'commit_no'" );
309 void QgsOfflineEditing::initializeSpatialMetadata(
sqlite3 *sqlite_handle )
312 if ( !sqlite_handle )
317 int ret = sqlite3_get_table( sqlite_handle,
"select count(*) from sqlite_master", &results, &rows, &columns, NULL );
318 if ( ret != SQLITE_OK )
323 for (
int i = 1; i <= rows; i++ )
324 count = atoi( results[( i * columns ) + 0] );
327 sqlite3_free_table( results );
332 bool above41 =
false;
333 ret = sqlite3_get_table( sqlite_handle,
"select spatialite_version()", &results, &rows, &columns, NULL );
334 if ( ret == SQLITE_OK && rows == 1 && columns == 1 )
338 if ( parts.
size() >= 1 )
341 above41 = verparts.
size() >= 2 && ( verparts[0].toInt() > 4 || ( verparts[0].toInt() == 4 && verparts[1].toInt() >= 1 ) );
345 sqlite3_free_table( results );
349 ret = sqlite3_exec( sqlite_handle, above41 ?
"SELECT InitSpatialMetadata(1)" :
"SELECT InitSpatialMetadata()", NULL, NULL, &errMsg );
351 if ( ret != SQLITE_OK )
353 QString errCause =
tr(
"Unable to initialize SpatialMetadata:\n" );
355 showWarning( errCause );
356 sqlite3_free( errMsg );
359 spatial_ref_sys_init( sqlite_handle, 0 );
362 bool QgsOfflineEditing::createSpatialiteDB(
const QString& offlineDbPath )
367 QFile newDb( offlineDbPath );
368 if ( newDb.exists() )
382 QString dbPath = newDb.fileName();
387 QString errCause =
tr(
"Could not create a new database\n" );
389 sqlite3_close( sqlite_handle );
390 showWarning( errCause );
394 ret = sqlite3_exec( sqlite_handle,
"PRAGMA foreign_keys = 1", NULL, 0, &errMsg );
395 if ( ret != SQLITE_OK )
397 showWarning(
tr(
"Unable to activate FOREIGN_KEY constraints" ) );
398 sqlite3_free( errMsg );
402 initializeSpatialMetadata( sqlite_handle );
410 void QgsOfflineEditing::createLoggingTables(
sqlite3* db )
413 QString sql =
"CREATE TABLE 'log_indices' ('name' TEXT, 'last_index' INTEGER)";
416 sql =
"INSERT INTO 'log_indices' VALUES ('commit_no', 0)";
419 sql =
"INSERT INTO 'log_indices' VALUES ('layer_id', 0)";
423 sql =
"CREATE TABLE 'log_layer_ids' ('id' INTEGER, 'qgis_id' TEXT)";
427 sql =
"CREATE TABLE 'log_fids' ('layer_id' INTEGER, 'offline_fid' INTEGER, 'remote_fid' INTEGER)";
431 sql =
"CREATE TABLE 'log_added_attrs' ('layer_id' INTEGER, 'commit_no' INTEGER, ";
432 sql +=
"'name' TEXT, 'type' INTEGER, 'length' INTEGER, 'precision' INTEGER, 'comment' TEXT)";
436 sql =
"CREATE TABLE 'log_added_features' ('layer_id' INTEGER, 'fid' INTEGER)";
440 sql =
"CREATE TABLE 'log_removed_features' ('layer_id' INTEGER, 'fid' INTEGER)";
444 sql =
"CREATE TABLE 'log_feature_updates' ('layer_id' INTEGER, 'commit_no' INTEGER, 'fid' INTEGER, 'attr' INTEGER, 'value' TEXT)";
448 sql =
"CREATE TABLE 'log_geometry_updates' ('layer_id' INTEGER, 'commit_no' INTEGER, 'fid' INTEGER, 'geom_wkt' TEXT)";
469 for (
int idx = 0; idx < fields.
count(); ++idx )
472 QVariant::Type type = fields[idx].type();
473 if ( type == QVariant::Int || type == QVariant::LongLong )
475 dataType =
"INTEGER";
477 else if ( type == QVariant::Double )
481 else if ( type == QVariant::String )
487 showWarning(
tr(
"%1: Unknown data type %2. Not using type affinity for the field." ).arg( fields[idx].
name() ).arg(
QVariant::typeToName( type ) ) );
495 int rc = sqlExec( db, sql );
507 geomType =
"MULTIPOINT";
510 geomType =
"LINESTRING";
513 geomType =
"MULTILINESTRING";
516 geomType =
"POLYGON";
519 geomType =
"MULTIPOLYGON";
522 showWarning(
tr(
"QGIS wkbType %1 not supported" ).arg( layer->
wkbType() ) );
525 QString sqlAddGeom =
QString(
"SELECT AddGeometryColumn('%1', 'Geometry', %2, '%3', 2)" )
531 QString sqlCreateIndex =
QString(
"SELECT CreateSpatialIndex('%1', 'Geometry')" ).
arg( tableName );
533 if ( rc == SQLITE_OK )
535 rc = sqlExec( db, sqlAddGeom );
536 if ( rc == SQLITE_OK )
538 rc = sqlExec( db, sqlCreateIndex );
543 if ( rc == SQLITE_OK )
547 .arg( offlineDbPath )
549 layer->
name() +
" (offline)",
"spatialite" );
570 copySymbology( layer, newLayer );
576 if ( layerTreeLayer )
579 if ( parentTreeGroup )
584 if ( newLayerTreeLayer )
598 copySymbology( layer, newLayer );
611 int featureCount = 1;
616 remoteFeatureIds << f.
id();
623 for (
int it = 0; it < attrs.
count(); ++it )
625 newAttrs[column++] = attrs[it];
639 int layerId = getOrCreateLayerId( db, newLayer->
id() );
645 offlineFeatureIds << f.
id();
649 sqlExec( db,
"BEGIN" );
650 int remoteCount = remoteFeatureIds.
size();
651 for (
int i = 0; i < remoteCount; i++ )
653 addFidLookup( db, layerId, offlineFeatureIds.at( i ), remoteFeatureIds.
at( remoteCount - ( i + 1 ) ) );
656 sqlExec( db,
"COMMIT" );
672 void QgsOfflineEditing::applyAttributesAdded(
QgsVectorLayer* remoteLayer,
sqlite3* db,
int layerId,
int commitNo )
674 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 );
682 for (
int i = 0; i < nativeTypes.
size(); i++ )
690 for (
int i = 0; i < fields.
size(); i++ )
694 if ( typeNameLookup.contains( field.
type() ) )
702 showWarning(
QString(
"Could not add attribute '%1' of type %2" ).arg( field.
name() ).arg( field.
type() ) );
711 QString sql =
QString(
"SELECT \"fid\" FROM 'log_added_features' WHERE \"layer_id\" = %1" ).
arg( layerId );
712 QList<int> newFeatureIds = sqlQueryInts( db, sql );
717 for (
int i = 0; i < remoteFlds.
count(); ++i )
725 for (
int i = 0; i < newFeatureIds.
size(); i++ )
745 QMap<int, int> attrLookup = attributeLookup( offlineLayer, remoteLayer );
748 for (
int it = 0; it < attrs.
count(); ++it )
750 newAttrs[ attrLookup[ it ] ] = attrs[ it ];
755 for (
int k = 0; k < newAttrs.count(); ++k )
757 if ( newAttrs[k].
isNull() && !defaultValues[k].isNull() )
758 newAttrs[k] = defaultValues[k];
769 void QgsOfflineEditing::applyFeaturesRemoved(
QgsVectorLayer* remoteLayer,
sqlite3* db,
int layerId )
771 QString sql =
QString(
"SELECT \"fid\" FROM 'log_removed_features' WHERE \"layer_id\" = %1" ).
arg( layerId );
788 QString sql =
QString(
"SELECT \"fid\", \"attr\", \"value\" FROM 'log_feature_updates' WHERE \"layer_id\" = %1 AND \"commit_no\" = %2 " ).
arg( layerId ).
arg( commitNo );
789 AttributeValueChanges values = sqlQueryAttributeValueChanges( db, sql );
793 QMap<int, int> attrLookup = attributeLookup( offlineLayer, remoteLayer );
795 for (
int i = 0; i < values.size(); i++ )
797 QgsFeatureId fid = remoteFid( db, layerId, values.at( i ).fid );
799 remoteLayer->
changeAttributeValue( fid, attrLookup[ values.at( i ).attr ], values.at( i ).value );
805 void QgsOfflineEditing::applyGeometryChanges(
QgsVectorLayer* remoteLayer,
sqlite3* db,
int layerId,
int commitNo )
807 QString sql =
QString(
"SELECT \"fid\", \"geom_wkt\" FROM 'log_geometry_updates' WHERE \"layer_id\" = %1 AND \"commit_no\" = %2" ).
arg( layerId ).
arg( commitNo );
808 GeometryChanges values = sqlQueryGeometryChanges( db, sql );
812 for (
int i = 0; i < values.size(); i++ )
814 QgsFeatureId fid = remoteFid( db, layerId, values.at( i ).fid );
837 if ( offlineFid( db, layerId, f.
id() ) == -1 )
839 newRemoteFids[ f.
id()] =
true;
847 QString sql =
QString(
"SELECT \"fid\" FROM 'log_added_features' WHERE \"layer_id\" = %1" ).
arg( layerId );
848 QList<int> newOfflineFids = sqlQueryInts( db, sql );
850 if ( newRemoteFids.size() != newOfflineFids.
size() )
858 sqlExec( db,
"BEGIN" );
861 addFidLookup( db, layerId, newOfflineFids.
at( i++ ), it.key() );
863 sqlExec( db,
"COMMIT" );
879 showWarning( error );
889 QMap <
int ,
int > attrLookup;
891 for (
int i = 0; i < remoteAttrs.
size(); i++ )
893 attrLookup.
insert( offlineAttrs.
at( i ), remoteAttrs.
at( i ) );
899 void QgsOfflineEditing::showWarning(
const QString& message )
901 emit
warning(
tr(
"Offline Editing Plugin" ), message );
904 sqlite3* QgsOfflineEditing::openLoggingDb()
911 if ( rc != SQLITE_OK )
913 showWarning(
tr(
"Could not open the spatialite logging database" ) );
921 int QgsOfflineEditing::getOrCreateLayerId(
sqlite3* db,
const QString& qgisLayerId )
923 QString sql =
QString(
"SELECT \"id\" FROM 'log_layer_ids' WHERE \"qgis_id\" = '%1'" ).
arg( qgisLayerId );
924 int layerId = sqlQueryInt( db, sql, -1 );
928 sql =
"SELECT \"last_index\" FROM 'log_indices' WHERE \"name\" = 'layer_id'";
929 int newLayerId = sqlQueryInt( db, sql, -1 );
932 sql =
QString(
"INSERT INTO 'log_layer_ids' VALUES (%1, '%2')" ).
arg( newLayerId ).
arg( qgisLayerId );
937 sql =
QString(
"UPDATE 'log_indices' SET 'last_index' = %1 WHERE \"name\" = 'layer_id'" ).
arg( newLayerId + 1 );
940 layerId = newLayerId;
946 int QgsOfflineEditing::getCommitNo(
sqlite3* db )
948 QString sql =
"SELECT \"last_index\" FROM 'log_indices' WHERE \"name\" = 'commit_no'";
949 return sqlQueryInt( db, sql, -1 );
952 void QgsOfflineEditing::increaseCommitNo(
sqlite3* db )
954 QString sql =
QString(
"UPDATE 'log_indices' SET 'last_index' = %1 WHERE \"name\" = 'commit_no'" ).
arg( getCommitNo( db ) + 1 );
958 void QgsOfflineEditing::addFidLookup(
sqlite3* db,
int layerId, QgsFeatureId offlineFid, QgsFeatureId remoteFid )
960 QString sql =
QString(
"INSERT INTO 'log_fids' VALUES ( %1, %2, %3 )" ).
arg( layerId ).
arg( offlineFid ).
arg( remoteFid );
964 QgsFeatureId QgsOfflineEditing::remoteFid(
sqlite3* db,
int layerId, QgsFeatureId offlineFid )
966 QString sql =
QString(
"SELECT \"remote_fid\" FROM 'log_fids' WHERE \"layer_id\" = %1 AND \"offline_fid\" = %2" ).
arg( layerId ).
arg( offlineFid );
967 return sqlQueryInt( db, sql, -1 );
970 QgsFeatureId QgsOfflineEditing::offlineFid(
sqlite3* db,
int layerId, QgsFeatureId remoteFid )
972 QString sql =
QString(
"SELECT \"offline_fid\" FROM 'log_fids' WHERE \"layer_id\" = %1 AND \"remote_fid\" = %2" ).
arg( layerId ).
arg( remoteFid );
973 return sqlQueryInt( db, sql, -1 );
976 bool QgsOfflineEditing::isAddedFeature(
sqlite3* db,
int layerId, QgsFeatureId fid )
978 QString sql =
QString(
"SELECT COUNT(\"fid\") FROM 'log_added_features' WHERE \"layer_id\" = %1 AND \"fid\" = %2" ).
arg( layerId ).
arg( fid );
979 return ( sqlQueryInt( db, sql, 0 ) > 0 );
985 int rc = sqlite3_exec( db, sql.
toUtf8(), NULL, NULL, &errmsg );
986 if ( rc != SQLITE_OK )
988 showWarning( errmsg );
993 int QgsOfflineEditing::sqlQueryInt(
sqlite3* db,
const QString& sql,
int defaultValue )
995 sqlite3_stmt* stmt = NULL;
996 if ( sqlite3_prepare_v2( db, sql.
toUtf8().
constData(), -1, &stmt, NULL ) != SQLITE_OK )
998 showWarning( sqlite3_errmsg( db ) );
1002 int value = defaultValue;
1003 int ret = sqlite3_step( stmt );
1004 if ( ret == SQLITE_ROW )
1006 value = sqlite3_column_int( stmt, 0 );
1008 sqlite3_finalize( stmt );
1017 sqlite3_stmt* stmt = NULL;
1018 if ( sqlite3_prepare_v2( db, sql.
toUtf8().
constData(), -1, &stmt, NULL ) != SQLITE_OK )
1020 showWarning( sqlite3_errmsg( db ) );
1024 int ret = sqlite3_step( stmt );
1025 while ( ret == SQLITE_ROW )
1027 values << sqlite3_column_int( stmt, 0 );
1029 ret = sqlite3_step( stmt );
1031 sqlite3_finalize( stmt );
1040 sqlite3_stmt* stmt = NULL;
1041 if ( sqlite3_prepare_v2( db, sql.
toUtf8().
constData(), -1, &stmt, NULL ) != SQLITE_OK )
1043 showWarning( sqlite3_errmsg( db ) );
1047 int ret = sqlite3_step( stmt );
1048 while ( ret == SQLITE_ROW )
1050 QgsField field(
QString((
const char* )sqlite3_column_text( stmt, 0 ) ),
1051 ( QVariant::Type )sqlite3_column_int( stmt, 1 ),
1053 sqlite3_column_int( stmt, 2 ),
1054 sqlite3_column_int( stmt, 3 ),
1055 QString((
const char* )sqlite3_column_text( stmt, 4 ) ) );
1058 ret = sqlite3_step( stmt );
1060 sqlite3_finalize( stmt );
1069 sqlite3_stmt* stmt = NULL;
1070 if ( sqlite3_prepare_v2( db, sql.
toUtf8().
constData(), -1, &stmt, NULL ) != SQLITE_OK )
1072 showWarning( sqlite3_errmsg( db ) );
1076 int ret = sqlite3_step( stmt );
1077 while ( ret == SQLITE_ROW )
1079 values << sqlite3_column_int( stmt, 0 );
1081 ret = sqlite3_step( stmt );
1083 sqlite3_finalize( stmt );
1090 AttributeValueChanges values;
1092 sqlite3_stmt* stmt = NULL;
1093 if ( sqlite3_prepare_v2( db, sql.
toUtf8().
constData(), -1, &stmt, NULL ) != SQLITE_OK )
1095 showWarning( sqlite3_errmsg( db ) );
1099 int ret = sqlite3_step( stmt );
1100 while ( ret == SQLITE_ROW )
1102 AttributeValueChange change;
1103 change.fid = sqlite3_column_int( stmt, 0 );
1104 change.attr = sqlite3_column_int( stmt, 1 );
1105 change.value =
QString((
const char* )sqlite3_column_text( stmt, 2 ) );
1108 ret = sqlite3_step( stmt );
1110 sqlite3_finalize( stmt );
1117 GeometryChanges values;
1119 sqlite3_stmt* stmt = NULL;
1120 if ( sqlite3_prepare_v2( db, sql.
toUtf8().
constData(), -1, &stmt, NULL ) != SQLITE_OK )
1122 showWarning( sqlite3_errmsg( db ) );
1126 int ret = sqlite3_step( stmt );
1127 while ( ret == SQLITE_ROW )
1129 GeometryChange change;
1130 change.fid = sqlite3_column_int( stmt, 0 );
1131 change.geom_wkt =
QString((
const char* )sqlite3_column_text( stmt, 1 ) );
1134 ret = sqlite3_step( stmt );
1136 sqlite3_finalize( stmt );
1141 void QgsOfflineEditing::committedAttributesAdded(
const QString& qgisLayerId,
const QList<QgsField>& addedAttributes )
1143 sqlite3* db = openLoggingDb();
1150 int layerId = getOrCreateLayerId( db, qgisLayerId );
1151 int commitNo = getCommitNo( db );
1156 QString sql =
QString(
"INSERT INTO 'log_added_attrs' VALUES ( %1, %2, '%3', %4, %5, %6, '%7' )" )
1160 .arg( field.
type() )
1167 increaseCommitNo( db );
1168 sqlite3_close( db );
1171 void QgsOfflineEditing::committedFeaturesAdded(
const QString& qgisLayerId,
const QgsFeatureList& addedFeatures )
1173 sqlite3* db = openLoggingDb();
1180 int layerId = getOrCreateLayerId( db, qgisLayerId );
1187 QString sql =
QString(
"SELECT ROWID FROM '%1' ORDER BY ROWID DESC LIMIT %2" ).
arg( uri.
table() ).arg( addedFeatures.
size() );
1188 QList<int> newFeatureIds = sqlQueryInts( db, sql );
1189 for (
int i = newFeatureIds.
size() - 1; i >= 0; i-- )
1191 QString sql =
QString(
"INSERT INTO 'log_added_features' VALUES ( %1, %2 )" )
1193 .
arg( newFeatureIds.
at( i ) );
1197 sqlite3_close( db );
1200 void QgsOfflineEditing::committedFeaturesRemoved(
const QString& qgisLayerId,
const QgsFeatureIds& deletedFeatureIds )
1202 sqlite3* db = openLoggingDb();
1209 int layerId = getOrCreateLayerId( db, qgisLayerId );
1213 if ( isAddedFeature( db, layerId, *it ) )
1216 QString sql =
QString(
"DELETE FROM 'log_added_features' WHERE \"layer_id\" = %1 AND \"fid\" = %2" ).
arg( layerId ).
arg( *it );
1221 QString sql =
QString(
"INSERT INTO 'log_removed_features' VALUES ( %1, %2)" )
1228 sqlite3_close( db );
1233 sqlite3* db = openLoggingDb();
1240 int layerId = getOrCreateLayerId( db, qgisLayerId );
1241 int commitNo = getCommitNo( db );
1243 for ( QgsChangedAttributesMap::const_iterator cit = changedAttrsMap.
begin(); cit != changedAttrsMap.
end(); ++cit )
1245 QgsFeatureId fid = cit.
key();
1246 if ( isAddedFeature( db, layerId, fid ) )
1252 for ( QgsAttributeMap::const_iterator it = attrMap.
begin(); it != attrMap.
end(); ++it )
1254 QString sql =
QString(
"INSERT INTO 'log_feature_updates' VALUES ( %1, %2, %3, %4, '%5' )" )
1259 .arg( it.value().toString() );
1264 increaseCommitNo( db );
1265 sqlite3_close( db );
1268 void QgsOfflineEditing::committedGeometriesChanges(
const QString& qgisLayerId,
const QgsGeometryMap& changedGeometries )
1270 sqlite3* db = openLoggingDb();
1277 int layerId = getOrCreateLayerId( db, qgisLayerId );
1278 int commitNo = getCommitNo( db );
1280 for ( QgsGeometryMap::const_iterator it = changedGeometries.
begin(); it != changedGeometries.
end(); ++it )
1282 QgsFeatureId fid = it.
key();
1283 if ( isAddedFeature( db, layerId, fid ) )
1289 QString sql =
QString(
"INSERT INTO 'log_geometry_updates' VALUES ( %1, %2, %3, '%4' )" )
1299 increaseCommitNo( db );
1300 sqlite3_close( db );
1303 void QgsOfflineEditing::startListenFeatureChanges()
1319 void QgsOfflineEditing::stopListenFeatureChanges()
1335 void QgsOfflineEditing::layerAdded(
QgsMapLayer* layer )
1341 connect( vLayer, SIGNAL( editingStarted() ),
this, SLOT( startListenFeatureChanges() ) );
1342 connect( vLayer, SIGNAL( editingStopped() ),
this, SLOT( stopListenFeatureChanges() ) );
virtual QgsLayerTreeNode * clone() const override
Create a copy of the node. Returns new instance.
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.
const QString & name() const
Gets the name of the field.
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
#define PROJECT_ENTRY_KEY_OFFLINE_DB_PATH
bool convertToOfflineProject(const QString &offlineDataPath, const QString &offlineDbFile, const QStringList &layerIds)
convert current project for offline editing
bool deleteFeature(QgsFeatureId fid)
delete a feature from the layer (but does not commit it)
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.
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 *)
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
const QString & name() const
Get the display name of the layer.
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
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
const QString & source() const
Returns the source for the layer.
QList< QgsMapLayer * > addMapLayers(QList< QgsMapLayer * > theMapLayers, bool addToLegend=true, bool takeOwnership=true)
Add a list of layers to the map of loaded layers.
QgsAttributes attributes() const
Returns the feature's attributes.
void setTypeName(const QString &typeName)
Set the field type.
static int sqlite3_open_v2(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs)
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
Q_DECL_DEPRECATED bool changeAttributeValue(QgsFeatureId fid, int field, QVariant value, bool emitSignal)
Changes an attribute value (but does not commit it)
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.
#define PROJECT_ENTRY_SCOPE_OFFLINE
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.
bool hasGeometryType() const
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
virtual long featureCount() const
Number of features in the layer.
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.
QString readEntry(const QString &scope, const QString &key, const QString &def=QString::null, bool *ok=0) const
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
QgsAttributeList pendingAllAttributesList()
returns list of attributes
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...
void removeMapLayers(QStringList theLayerIds)
Remove a set of layers from the registry.
void title(const QString &title)
Every project has an associated title string.
QString absolutePath() const
void synchronize()
synchronize to remote layers
virtual bool setSubsetString(QString subset)
Set the string (typically sql) used to define a subset of the layer.
static QgsProject * instance()
access to canonical QgsProject instance
int length() const
Gets the length of the field.
int count(const T &value) const
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)
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)
const QString & comment() const
Returns the field comment.
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...
static QgsGeometry * fromWkt(QString wkt)
Creates a new geometry from a WKT string.
const QgsCoordinateReferenceSystem & crs() const
Returns layer's spatial reference system.
QgsMapLayer * mapLayer(QString theLayerId)
Retrieve a pointer to a loaded layer by id.
iterator insert(const Key &key, const T &value)
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
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
QString exportToWkt(const int &precision=17) const
Exports the geometry to WKT.
bool isNull(const QVariant &v)
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