Skip to content

Commit

Permalink
[feature] Add flag to only copy selected features
Browse files Browse the repository at this point in the history
This extends the offline editing possibilities to only work on subset of
large layers

Sponsored by DB Fahrwegdienste GmbH
  • Loading branch information
m-kuhn committed Sep 15, 2016
1 parent f80021e commit eb39278
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 30 deletions.
4 changes: 2 additions & 2 deletions python/core/qgsofflineediting.sip
Expand Up @@ -28,10 +28,10 @@ class QgsOfflineEditing : QObject
* @param offlineDbFile offline db file name
* @param layerIds list of layer names to convert
*/
bool convertToOfflineProject( const QString& offlineDataPath, const QString& offlineDbFile, const QStringList& layerIds );
bool convertToOfflineProject( const QString& offlineDataPath, const QString& offlineDbFile, const QStringList& layerIds, bool onlySelected = false );

/** Return true if current project is offline */
bool isOfflineProject();
bool isOfflineProject() const;

/** Synchronize to remote layers */
void synchronize();
Expand Down
38 changes: 21 additions & 17 deletions src/core/qgsofflineediting.cpp
Expand Up @@ -77,7 +77,7 @@ QgsOfflineEditing::~QgsOfflineEditing()
* - remove remote layers
* - mark as offline project
*/
bool QgsOfflineEditing::convertToOfflineProject( const QString& offlineDataPath, const QString& offlineDbFile, const QStringList& layerIds )
bool QgsOfflineEditing::convertToOfflineProject( const QString& offlineDataPath, const QString& offlineDbFile, const QStringList& layerIds, bool onlySelected )
{
if ( layerIds.isEmpty() )
{
Expand All @@ -102,9 +102,9 @@ bool QgsOfflineEditing::convertToOfflineProject( const QString& offlineDataPath,
QMap<QString, QgsVectorJoinList > joinInfoBuffer;
QMap<QString, QgsVectorLayer*> layerIdMapping;

for ( int i = 0; i < layerIds.count(); i++ )
Q_FOREACH ( const QString& layerId, layerIds )
{
QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerIds.at( i ) );
QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerId );
QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( layer );
if ( !vl )
continue;
Expand All @@ -114,17 +114,17 @@ bool QgsOfflineEditing::convertToOfflineProject( const QString& offlineDataPath,
// Join fields are prefixed with the layer name and we do not want the
// field name to change so we stabilize the field name by defining a
// custom prefix with the layername without _offline suffix.
QgsVectorJoinList::iterator it = joins.begin();
while ( it != joins.end() )
QgsVectorJoinList::iterator joinIt = joins.begin();
while ( joinIt != joins.end() )
{
if (( *it ).prefix.isNull() )
if ( joinIt->prefix.isNull() )
{
QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer(( *it ).joinLayerId ) );
QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinIt->joinLayerId ) );

if ( vl )
( *it ).prefix = vl->name() + '_';
joinIt->prefix = vl->name() + '_';
}
++it;
++joinIt;
}
joinInfoBuffer.insert( vl->id(), joins );
}
Expand All @@ -139,7 +139,7 @@ bool QgsOfflineEditing::convertToOfflineProject( const QString& offlineDataPath,
if ( vl )
{
QString origLayerId = vl->id();
QgsVectorLayer* newLayer = copyVectorLayer( vl, db, dbPath );
QgsVectorLayer* newLayer = copyVectorLayer( vl, db, dbPath, onlySelected );

if ( newLayer )
{
Expand Down Expand Up @@ -195,7 +195,7 @@ bool QgsOfflineEditing::convertToOfflineProject( const QString& offlineDataPath,
return false;
}

bool QgsOfflineEditing::isOfflineProject()
bool QgsOfflineEditing::isOfflineProject() const
{
return !QgsProject::instance()->readEntry( PROJECT_ENTRY_SCOPE_OFFLINE, PROJECT_ENTRY_KEY_OFFLINE_DB_PATH ).isEmpty();
}
Expand Down Expand Up @@ -226,7 +226,7 @@ void QgsOfflineEditing::synchronize()
QgsDebugMsgLevel( QString( "Found %1 offline layers" ).arg( offlineLayers.count() ), 4 );
for ( int l = 0; l < offlineLayers.count(); l++ )
{
QgsMapLayer* layer = offlineLayers[l];
QgsMapLayer* layer = offlineLayers.at( l );

emit layerProgressUpdated( l + 1, offlineLayers.count() );

Expand All @@ -252,8 +252,7 @@ void QgsOfflineEditing::synchronize()
QgsVectorLayer* offlineLayer = qobject_cast<QgsVectorLayer*>( layer );

// register this layer with the central layers registry
QgsMapLayerRegistry::instance()->addMapLayers(
QList<QgsMapLayer *>() << remoteLayer, true );
QgsMapLayerRegistry::instance()->addMapLayers( QList<QgsMapLayer *>() << remoteLayer, true );

// copy style
copySymbology( offlineLayer, remoteLayer );
Expand Down Expand Up @@ -315,8 +314,7 @@ void QgsOfflineEditing::synchronize()
// again with the same path
offlineLayer->dataProvider()->invalidateConnections( QgsDataSourceURI( offlineLayer->source() ).database() );
// remove offline layer
QgsMapLayerRegistry::instance()->removeMapLayers(
( QStringList() << qgisLayerId ) );
QgsMapLayerRegistry::instance()->removeMapLayers( QStringList() << qgisLayerId );


// disable offline project
Expand Down Expand Up @@ -484,7 +482,7 @@ void QgsOfflineEditing::createLoggingTables( sqlite3* db )
*/
}

QgsVectorLayer* QgsOfflineEditing::copyVectorLayer( QgsVectorLayer* layer, sqlite3* db, const QString& offlineDbPath )
QgsVectorLayer* QgsOfflineEditing::copyVectorLayer( QgsVectorLayer* layer, sqlite3* db, const QString& offlineDbPath , bool onlySelected )
{
if ( !layer )
return nullptr;
Expand Down Expand Up @@ -637,12 +635,18 @@ QgsVectorLayer* QgsOfflineEditing::copyVectorLayer( QgsVectorLayer* layer, sqlit

QgsFeatureIterator fit = layer->dataProvider()->getFeatures();

QgsFeatureIds selectedFids = layer->selectedFeaturesIds();

emit progressModeSet( QgsOfflineEditing::CopyFeatures, layer->dataProvider()->featureCount() );
int featureCount = 1;

QList<QgsFeatureId> remoteFeatureIds;
while ( fit.nextFeature( f ) )
{
// Check if we only want selected feature, if the selection is not empty and the current feature is not selected: dismiss it
if ( onlySelected && !selectedFids.isEmpty() && !selectedFids.contains( f.id() ) )
continue;

remoteFeatureIds << f.id();

// NOTE: Spatialite provider ignores position of geometry column
Expand Down
13 changes: 7 additions & 6 deletions src/core/qgsofflineediting.h
Expand Up @@ -51,14 +51,15 @@ class CORE_EXPORT QgsOfflineEditing : public QObject
~QgsOfflineEditing();

/** Convert current project for offline editing
* @param offlineDataPath path to offline db file
* @param offlineDbFile offline db file name
* @param layerIds list of layer names to convert
* @param offlineDataPath Path to offline db file
* @param offlineDbFile Offline db file name
* @param layerIds List of layer names to convert
* @param onlySelected Only copy selected features from layers where a selection is present
*/
bool convertToOfflineProject( const QString& offlineDataPath, const QString& offlineDbFile, const QStringList& layerIds );
bool convertToOfflineProject( const QString& offlineDataPath, const QString& offlineDbFile, const QStringList& layerIds, bool onlySelected = false );

/** Return true if current project is offline */
bool isOfflineProject();
bool isOfflineProject() const;

/** Synchronize to remote layers */
void synchronize();
Expand Down Expand Up @@ -98,7 +99,7 @@ class CORE_EXPORT QgsOfflineEditing : public QObject
void initializeSpatialMetadata( sqlite3 *sqlite_handle );
bool createSpatialiteDB( const QString& offlineDbPath );
void createLoggingTables( sqlite3* db );
QgsVectorLayer* copyVectorLayer( QgsVectorLayer* layer, sqlite3* db, const QString& offlineDbPath );
QgsVectorLayer* copyVectorLayer( QgsVectorLayer* layer, sqlite3* db, const QString& offlineDbPath, bool onlySelected );

void applyAttributesAdded( QgsVectorLayer* remoteLayer, sqlite3* db, int layerId, int commitNo );
void applyFeaturesAdded( QgsVectorLayer* offlineLayer, QgsVectorLayer* remoteLayer, sqlite3* db, int layerId );
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/offline_editing/offline_editing_plugin.cpp
Expand Up @@ -109,7 +109,7 @@ void QgsOfflineEditingPlugin::convertProject()
}

mProgressDialog->setTitle( tr( "Converting to offline project" ) );
if ( mOfflineEditing->convertToOfflineProject( myPluginGui->offlineDataPath(), myPluginGui->offlineDbFile(), selectedLayerIds ) )
if ( mOfflineEditing->convertToOfflineProject( myPluginGui->offlineDataPath(), myPluginGui->offlineDbFile(), selectedLayerIds, myPluginGui->onlySelected() ) )
{
updateActions();
// Redraw, to make the offline layer visible
Expand Down
7 changes: 6 additions & 1 deletion src/plugins/offline_editing/offline_editing_plugin_gui.cpp
Expand Up @@ -102,11 +102,16 @@ QString QgsOfflineEditingPluginGui::offlineDbFile()
return mOfflineDbFile;
}

QStringList& QgsOfflineEditingPluginGui::selectedLayerIds()
QStringList QgsOfflineEditingPluginGui::selectedLayerIds()
{
return mSelectedLayerIds;
}

bool QgsOfflineEditingPluginGui::onlySelected() const
{
return mOnlySelectedCheckBox->checkState() == Qt::Checked;
}

void QgsOfflineEditingPluginGui::on_mBrowseButton_clicked()
{
QString fileName = QFileDialog::getSaveFileName( this,
Expand Down
3 changes: 2 additions & 1 deletion src/plugins/offline_editing/offline_editing_plugin_gui.h
Expand Up @@ -46,7 +46,8 @@ class QgsOfflineEditingPluginGui : public QDialog, private Ui::QgsOfflineEditing

QString offlineDataPath();
QString offlineDbFile();
QStringList& selectedLayerIds();
QStringList selectedLayerIds();
bool onlySelected() const;

public slots:
/** Change the selection of layers in the list */
Expand Down
11 changes: 9 additions & 2 deletions src/plugins/offline_editing/offline_editing_plugin_guibase.ui
Expand Up @@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>435</width>
<height>270</height>
<width>590</width>
<height>570</height>
</rect>
</property>
<property name="windowTitle">
Expand Down Expand Up @@ -92,6 +92,13 @@
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="mOnlySelectedCheckBox">
<property name="text">
<string>Only synchronize selected features if a selection is present</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
Expand Down

0 comments on commit eb39278

Please sign in to comment.