Move QgsOfflineEditing to core and add SIP bindings; refactor Offline Editing Plugin

This commit is contained in:
Mathias Walker 2013-01-15 16:30:35 +01:00
parent 831f99a401
commit a1743ab0e5
8 changed files with 213 additions and 44 deletions

View File

@ -42,6 +42,7 @@
%Include qgsmessageoutput.sip
%Include qgsmimedatautils.sip
%Include qgsnetworkaccessmanager.sip
%Include qgsofflineediting.sip
%Include qgsoverlayobject.sip
%Include qgsowsconnection.sip
%Include qgspaintenginehack.sip

View File

@ -0,0 +1,61 @@
/** \class QgsOfflineEditing
* \brief Class for accessing functionality of Offline Editing Plugin.
* This class can be used to access offline editing functionality from plugins.
*/
class QgsOfflineEditing : QObject
{
%TypeHeaderCode
#include <qgsofflineediting.h>
%End
public:
enum ProgressMode {
CopyFeatures = 0,
ProcessFeatures,
AddFields,
AddFeatures,
RemoveFeatures,
UpdateFeatures,
UpdateGeometries
};
QgsOfflineEditing();
~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
*/
bool convertToOfflineProject( const QString& offlineDataPath, const QString& offlineDbFile, const QStringList& layerIds );
/** return true if current project is offline */
bool isOfflineProject();
/** synchronize to remote layers */
void synchronize();
signals:
/** emit a signal that processing has started */
void progressStarted();
/** emit a signal that the next layer of numLayers has started processing
* @param layer current layer index
* @param numLayers total number of layers
*/
void layerProgressUpdated( int layer, int numLayers );
/** emit a signal that sets the mode for the progress of the current operation
* @param mode progress mode
* @param maximum total number of entities to process in the current operation
*/
void progressModeSet( QgsOfflineEditing::ProgressMode mode, int maximum );
/** emit a signal with the progress of the current mode
* @param progress current index of processed entities
*/
void progressUpdated( int progress );
/** emit a signal that processing of all layers has finished */
void progressStopped();
};

View File

@ -80,6 +80,7 @@ SET(QGIS_CORE_SRCS
qgsmessagelog.cpp
qgsnetworkreplyparser.cpp
qgscredentials.cpp
qgsofflineediting.cpp
qgsoverlayobject.cpp
qgsowsconnection.cpp
qgspalgeometry.cpp
@ -267,7 +268,7 @@ IF (WITH_INTERNAL_SPATIALITE)
SET_SOURCE_FILES_PROPERTIES(spatialite/sqlite3.c spatialite/spatialite.c PROPERTIES COMPILE_FLAGS -w)
ENDIF(MSVC)
INCLUDE_DIRECTORIES(BEFORE spatialite/headers/spatialite)
INCLUDE_DIRECTORIES(BEFORE spatialite/headers/spatialite spatialite/headers)
ENDIF (WITH_INTERNAL_SPATIALITE)
ADD_FLEX_FILES(QGIS_CORE_SRCS qgsexpressionlexer.ll)
@ -288,6 +289,7 @@ SET(QGIS_CORE_MOC_HDRS
qgsmessageoutput.h
qgsmessagelog.h
qgsnetworkreplyparser.h
qgsofflineediting.h
qgscredentials.h
qgspluginlayer.h
qgsproject.h
@ -379,6 +381,7 @@ SET(QGIS_CORE_HDRS
qgsmimedatautils.h
qgsnetworkreplyparser.h
qgscredentials.h
qgsofflineediting.h
qgsoverlayobjectpositionmanager.h
qgsowsconnection.h
qgspallabeling.h

View File

@ -16,15 +16,13 @@
* *
***************************************************************************/
#include "offline_editing.h"
#include "offline_editing_progress_dialog.h"
#include <qgsapplication.h>
#include <qgsdatasourceuri.h>
#include <qgsgeometry.h>
#include <qgslegendinterface.h>
#include <qgsmaplayer.h>
#include <qgsmaplayerregistry.h>
#include <qgsofflineediting.h>
#include <qgsproject.h>
#include <qgsvectordataprovider.h>
@ -50,9 +48,8 @@ extern "C"
#define PROJECT_ENTRY_SCOPE_OFFLINE "OfflineEditingPlugin"
#define PROJECT_ENTRY_KEY_OFFLINE_DB_PATH "/OfflineDbPath"
QgsOfflineEditing::QgsOfflineEditing( QgsOfflineEditingProgressDialog* progressDialog )
QgsOfflineEditing::QgsOfflineEditing()
{
mProgressDialog = progressDialog;
connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWasAdded( QgsMapLayer* ) ), this, SLOT( layerAdded( QgsMapLayer* ) ) );
}
@ -85,19 +82,18 @@ bool QgsOfflineEditing::convertToOfflineProject( const QString& offlineDataPath,
// create logging tables
createLoggingTables( db );
mProgressDialog->setTitle( "Converting to offline project" );
mProgressDialog->show();
emit progressStarted();
// copy selected vector layers to SpatiaLite
for ( int i = 0; i < layerIds.count(); i++ )
{
mProgressDialog->setCurrentLayer( i + 1, layerIds.count() );
emit layerProgressUpdated( i + 1, layerIds.count() );
QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerIds.at( i ) );
copyVectorLayer( qobject_cast<QgsVectorLayer*>( layer ), db, dbPath );
}
mProgressDialog->hide();
emit progressStopped();
sqlite3_close( db );
@ -135,9 +131,8 @@ bool QgsOfflineEditing::isOfflineProject()
return !QgsProject::instance()->readEntry( PROJECT_ENTRY_SCOPE_OFFLINE, PROJECT_ENTRY_KEY_OFFLINE_DB_PATH ).isEmpty();
}
void QgsOfflineEditing::synchronize( QgsLegendInterface* legendInterface )
void QgsOfflineEditing::synchronize()
{
Q_UNUSED( legendInterface );
// open logging db
sqlite3* db = openLoggingDb();
if ( db == NULL )
@ -145,8 +140,7 @@ void QgsOfflineEditing::synchronize( QgsLegendInterface* legendInterface )
return;
}
mProgressDialog->setTitle( "Synchronizing to remote layers" );
mProgressDialog->show();
emit progressStarted();
// restore and sync remote layers
QList<QgsMapLayer*> offlineLayers;
@ -164,7 +158,7 @@ void QgsOfflineEditing::synchronize( QgsLegendInterface* legendInterface )
{
QgsMapLayer* layer = offlineLayers[l];
mProgressDialog->setCurrentLayer( l + 1, offlineLayers.count() );
emit layerProgressUpdated( l + 1, offlineLayers.count() );
QString remoteSource = layer->customProperty( CUSTOM_PROPERTY_REMOTE_SOURCE, "" ).toString();
QString remoteProvider = layer->customProperty( CUSTOM_PROPERTY_REMOTE_PROVIDER, "" ).toString();
@ -246,7 +240,7 @@ void QgsOfflineEditing::synchronize( QgsLegendInterface* legendInterface )
}
}
mProgressDialog->hide();
emit progressStopped();
sqlite3_close( db );
}
@ -517,7 +511,7 @@ void QgsOfflineEditing::copyVectorLayer( QgsVectorLayer* layer, sqlite3* db, con
layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );
mProgressDialog->setupProgressBar( tr( "%v / %m features copied" ), layer->featureCount() );
emit progressModeSet( QgsOfflineEditing::CopyFeatures, layer->featureCount() );
int featureCount = 1;
QList<QgsFeatureId> remoteFeatureIds;
@ -538,11 +532,11 @@ void QgsOfflineEditing::copyVectorLayer( QgsVectorLayer* layer, sqlite3* db, con
newLayer->addFeature( f, false );
mProgressDialog->setProgressValue( featureCount++ );
emit progressUpdated( featureCount++ );
}
if ( newLayer->commitChanges() )
{
mProgressDialog->setupProgressBar( tr( "%v / %m features processed" ), layer->featureCount() );
emit progressModeSet( QgsOfflineEditing::ProcessFeatures, layer->featureCount() );
featureCount = 1;
// update feature id lookup
@ -560,7 +554,7 @@ void QgsOfflineEditing::copyVectorLayer( QgsVectorLayer* layer, sqlite3* db, con
{
addFidLookup( db, layerId, offlineFeatureIds.at( i ), remoteFeatureIds.at( i ) );
mProgressDialog->setProgressValue( featureCount++ );
emit progressUpdated( featureCount++ );
}
sqlExec( db, "COMMIT" );
}
@ -592,7 +586,7 @@ void QgsOfflineEditing::applyAttributesAdded( QgsVectorLayer* remoteLayer, sqlit
typeNameLookup[ nativeType.mType ] = nativeType.mTypeName;
}
mProgressDialog->setupProgressBar( tr( "%v / %m fields added" ), fields.size() );
emit progressModeSet( QgsOfflineEditing::AddFields, fields.size() );
for ( int i = 0; i < fields.size(); i++ )
{
@ -609,7 +603,7 @@ void QgsOfflineEditing::applyAttributesAdded( QgsVectorLayer* remoteLayer, sqlit
showWarning( QString( "Could not add attribute '%1' of type %2" ).arg( field.name() ).arg( field.type() ) );
}
mProgressDialog->setProgressValue( i + 1 );
emit progressUpdated( i + 1 );
}
}
@ -630,7 +624,7 @@ void QgsOfflineEditing::applyFeaturesAdded( QgsVectorLayer* offlineLayer, QgsVec
}
// copy features to remote layer
mProgressDialog->setupProgressBar( tr( "%v / %m features added" ), features.size() );
emit progressModeSet( QgsOfflineEditing::AddFeatures, features.size() );
int i = 1;
for ( QgsFeatureList::iterator it = features.begin(); it != features.end(); ++it )
@ -650,7 +644,7 @@ void QgsOfflineEditing::applyFeaturesAdded( QgsVectorLayer* offlineLayer, QgsVec
remoteLayer->addFeature( f, false );
mProgressDialog->setProgressValue( i++ );
emit progressUpdated( i++ );
}
}
@ -659,7 +653,7 @@ void QgsOfflineEditing::applyFeaturesRemoved( QgsVectorLayer* remoteLayer, sqlit
QString sql = QString( "SELECT \"fid\" FROM 'log_removed_features' WHERE \"layer_id\" = %1" ).arg( layerId );
QgsFeatureIds values = sqlQueryFeaturesRemoved( db, sql );
mProgressDialog->setupProgressBar( tr( "%v / %m features removed" ), values.size() );
emit progressModeSet( QgsOfflineEditing::RemoveFeatures, values.size() );
int i = 1;
for ( QgsFeatureIds::const_iterator it = values.begin(); it != values.end(); ++it )
@ -667,7 +661,7 @@ void QgsOfflineEditing::applyFeaturesRemoved( QgsVectorLayer* remoteLayer, sqlit
QgsFeatureId fid = remoteFid( db, layerId, *it );
remoteLayer->deleteFeature( fid );
mProgressDialog->setProgressValue( i++ );
emit progressUpdated( i++ );
}
}
@ -676,7 +670,7 @@ void QgsOfflineEditing::applyAttributeValueChanges( QgsVectorLayer* offlineLayer
QString sql = QString( "SELECT \"fid\", \"attr\", \"value\" FROM 'log_feature_updates' WHERE \"layer_id\" = %1 AND \"commit_no\" = %2 " ).arg( layerId ).arg( commitNo );
AttributeValueChanges values = sqlQueryAttributeValueChanges( db, sql );
mProgressDialog->setupProgressBar( tr( "%v / %m feature updates" ), values.size() );
emit progressModeSet( QgsOfflineEditing::UpdateFeatures, values.size() );
QMap<int, int> attrLookup = attributeLookup( offlineLayer, remoteLayer );
@ -686,7 +680,7 @@ void QgsOfflineEditing::applyAttributeValueChanges( QgsVectorLayer* offlineLayer
remoteLayer->changeAttributeValue( fid, attrLookup[ values.at( i ).attr ], values.at( i ).value, false );
mProgressDialog->setProgressValue( i + 1 );
emit progressUpdated( i + 1 );
}
}
@ -695,14 +689,14 @@ void QgsOfflineEditing::applyGeometryChanges( QgsVectorLayer* remoteLayer, sqlit
QString sql = QString( "SELECT \"fid\", \"geom_wkt\" FROM 'log_geometry_updates' WHERE \"layer_id\" = %1 AND \"commit_no\" = %2" ).arg( layerId ).arg( commitNo );
GeometryChanges values = sqlQueryGeometryChanges( db, sql );
mProgressDialog->setupProgressBar( tr( "%v / %m feature geometry updates" ), values.size() );
emit progressModeSet( QgsOfflineEditing::UpdateGeometries, values.size() );
for ( int i = 0; i < values.size(); i++ )
{
QgsFeatureId fid = remoteFid( db, layerId, values.at( i ).fid );
remoteLayer->changeGeometry( fid, QgsGeometry::fromWkt( values.at( i ).geom_wkt ) );
mProgressDialog->setProgressValue( i + 1 );
emit progressUpdated( i + 1 );
}
}
@ -716,7 +710,7 @@ void QgsOfflineEditing::updateFidLookup( QgsVectorLayer* remoteLayer, sqlite3* d
QgsFeature f;
remoteLayer->select( QgsAttributeList(), QgsRectangle(), false, false );
mProgressDialog->setupProgressBar( tr( "%v / %m features processed" ), remoteLayer->featureCount() );
emit progressModeSet( QgsOfflineEditing::ProcessFeatures, remoteLayer->featureCount() );
int i = 1;
while ( remoteLayer->nextFeature( f ) )
@ -726,7 +720,7 @@ void QgsOfflineEditing::updateFidLookup( QgsVectorLayer* remoteLayer, sqlite3* d
newRemoteFids[ f.id()] = true;
}
mProgressDialog->setProgressValue( i++ );
emit progressUpdated( i++ );
}
// get local added fids

View File

@ -25,9 +25,7 @@
#include <QObject>
#include <QString>
class QgsLegendInterface;
class QgsMapLayer;
class QgsOfflineEditingProgressDialog;
class QgsVectorLayer;
struct sqlite3;
@ -36,12 +34,55 @@ class QgsOfflineEditing : public QObject
Q_OBJECT
public:
QgsOfflineEditing( QgsOfflineEditingProgressDialog* progressDialog );
enum ProgressMode {
CopyFeatures = 0,
ProcessFeatures,
AddFields,
AddFeatures,
RemoveFeatures,
UpdateFeatures,
UpdateGeometries
};
QgsOfflineEditing();
~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
*/
bool convertToOfflineProject( const QString& offlineDataPath, const QString& offlineDbFile, const QStringList& layerIds );
/** return true if current project is offline */
bool isOfflineProject();
void synchronize( QgsLegendInterface* legendInterface );
/** synchronize to remote layers */
void synchronize();
signals:
/** emit a signal that processing has started */
void progressStarted();
/** emit a signal that the next layer of numLayers has started processing
* @param layer current layer index
* @param numLayers total number of layers
*/
void layerProgressUpdated( int layer, int numLayers );
/** emit a signal that sets the mode for the progress of the current operation
* @param mode progress mode
* @param maximum total number of entities to process in the current operation
*/
void progressModeSet( QgsOfflineEditing::ProgressMode mode, int maximum );
/** emit a signal with the progress of the current mode
* @param progress current index of processed entities
*/
void progressUpdated( int progress );
/** emit a signal that processing of all layers has finished */
void progressStopped();
private:
void initializeSpatialMetadata( sqlite3 *sqlite_handle );
@ -93,8 +134,6 @@ class QgsOfflineEditing : public QObject
typedef QList<GeometryChange> GeometryChanges;
GeometryChanges sqlQueryGeometryChanges( sqlite3* db, const QString& sql );
QgsOfflineEditingProgressDialog* mProgressDialog;
private slots:
void layerAdded( QgsMapLayer* layer );
void committedAttributesAdded( const QString& qgisLayerId, const QList<QgsField>& addedAttributes );

View File

@ -5,7 +5,6 @@
SET (offline_editing_plugin_SRCS
offline_editing_plugin.cpp
offline_editing_plugin_gui.cpp
offline_editing.cpp
offline_editing_progress_dialog.cpp
)
@ -17,7 +16,6 @@ SET (offline_editing_plugin_UIS
SET (offline_editing_plugin_MOC_HDRS
offline_editing_plugin.h
offline_editing_plugin_gui.h
offline_editing.h
offline_editing_progress_dialog.h
)

View File

@ -19,7 +19,6 @@
#include "offline_editing_plugin.h"
#include "offline_editing_plugin_gui.h"
#include "offline_editing_progress_dialog.h"
#include "offline_editing.h"
#include <qgisinterface.h>
#include <qgisgui.h>
@ -47,6 +46,7 @@ QgsOfflineEditingPlugin::QgsOfflineEditingPlugin( QgisInterface* theQgisInterfac
QgsOfflineEditingPlugin::~QgsOfflineEditingPlugin()
{
delete mOfflineEditing;
delete mProgressDialog;
}
void QgsOfflineEditingPlugin::initGui()
@ -69,7 +69,14 @@ void QgsOfflineEditingPlugin::initGui()
mQGisIface->addPluginToDatabaseMenu( tr( "&Offline Editing" ), mActionSynchronize );
mActionSynchronize->setEnabled( false );
mOfflineEditing = new QgsOfflineEditing( new QgsOfflineEditingProgressDialog( mQGisIface->mainWindow(), QgisGui::ModalDialogFlags ) );
mOfflineEditing = new QgsOfflineEditing();
mProgressDialog = new QgsOfflineEditingProgressDialog( mQGisIface->mainWindow(), QgisGui::ModalDialogFlags );
connect( mOfflineEditing, SIGNAL( progressStarted() ), this, SLOT( showProgress() ) );
connect( mOfflineEditing, SIGNAL( layerProgressUpdated( int, int ) ), this, SLOT( setLayerProgress( int, int ) ) );
connect( mOfflineEditing, SIGNAL( progressModeSet( QgsOfflineEditing::ProgressMode, int ) ), this, SLOT( setProgressMode( QgsOfflineEditing::ProgressMode, int ) ) );
connect( mOfflineEditing, SIGNAL( progressUpdated( int ) ), this, SLOT( updateProgress( int ) ) );
connect( mOfflineEditing, SIGNAL( progressStopped() ), this, SLOT( hideProgress() ) );
connect( mQGisIface->mainWindow(), SIGNAL( projectRead() ), this, SLOT( updateActions() ) );
connect( mQGisIface->mainWindow(), SIGNAL( newProject() ), this, SLOT( updateActions() ) );
@ -94,6 +101,7 @@ void QgsOfflineEditingPlugin::convertProject()
return;
}
mProgressDialog->setTitle( tr( "Converting to offline project" ) );
if ( mOfflineEditing->convertToOfflineProject( myPluginGui->offlineDataPath(), myPluginGui->offlineDbFile(), selectedLayerIds ) )
{
updateActions();
@ -105,7 +113,8 @@ void QgsOfflineEditingPlugin::convertProject()
void QgsOfflineEditingPlugin::synchronize()
{
mOfflineEditing->synchronize( mQGisIface->legendInterface() );
mProgressDialog->setTitle( tr( "Synchronizing to remote layers" ) );
mOfflineEditing->synchronize();
updateActions();
}
@ -137,6 +146,61 @@ void QgsOfflineEditingPlugin::updateActions()
mActionSynchronize->setEnabled( hasLayers && isOfflineProject );
}
void QgsOfflineEditingPlugin::showProgress()
{
mProgressDialog->show();
}
void QgsOfflineEditingPlugin::setLayerProgress( int layer, int numLayers )
{
mProgressDialog->setCurrentLayer( layer, numLayers );
}
void QgsOfflineEditingPlugin::setProgressMode( QgsOfflineEditing::ProgressMode mode, int maximum )
{
QString format = "";
switch ( mode )
{
case QgsOfflineEditing::CopyFeatures:
format = tr( "%v / %m features copied" );
break;
case QgsOfflineEditing::ProcessFeatures:
format = tr( "%v / %m features processed" );
break;
case QgsOfflineEditing::AddFields:
format = tr( "%v / %m fields added" );
break;
case QgsOfflineEditing::AddFeatures:
format = tr( "%v / %m features added" );
break;
case QgsOfflineEditing::RemoveFeatures:
format = tr( "%v / %m features removed" );
break;
case QgsOfflineEditing::UpdateFeatures:
format = tr( "%v / %m feature updates" );
break;
case QgsOfflineEditing::UpdateGeometries:
format = tr( "%v / %m feature geometry updates" );
break;
default:
break;
}
mProgressDialog->setupProgressBar( format, maximum );
}
void QgsOfflineEditingPlugin::updateProgress( int progress )
{
mProgressDialog->setProgressValue( progress );
}
void QgsOfflineEditingPlugin::hideProgress()
{
mProgressDialog->hide();
}
/**
* Required extern functions needed for every plugin
* These functions can be called prior to creating an instance

View File

@ -20,11 +20,12 @@
#define QGS_OFFLINE_EDITING_PLUGIN_H
#include "../qgisplugin.h"
#include <qgsofflineediting.h>
#include <QObject>
class QAction;
class QgisInterface;
class QgsOfflineEditing;
class QgsOfflineEditingProgressDialog;
class QgsOfflineEditingPlugin : public QObject, public QgisPlugin
{
@ -54,9 +55,17 @@ class QgsOfflineEditingPlugin : public QObject, public QgisPlugin
QAction* mActionSynchronize;
QgsOfflineEditing* mOfflineEditing;
QgsOfflineEditingProgressDialog* mProgressDialog;
private slots:
void updateActions();
//! update progress dialog
void showProgress();
void setLayerProgress( int layer, int numLayers );
void setProgressMode( QgsOfflineEditing::ProgressMode mode, int maximum );
void updateProgress( int progress );
void hideProgress();
};
#endif // QGS_OFFLINE_EDITING_PLUGIN_H