Auxiliary data is cloned too

This commit is contained in:
Blottiere Paul 2017-09-02 18:47:36 +01:00
parent 9306226e94
commit baa2b968bc
5 changed files with 116 additions and 21 deletions

View File

@ -109,6 +109,16 @@ class QgsAuxiliaryLayer : QgsVectorLayer
QgsAuxiliaryLayer *clone( QgsVectorLayer *layer ) const /Factory/;
%Docstring
Returns a new instance equivalent to this one. The underlying table
is duplicate for the layer given in parameter. Note that the current
auxiliary layer should be saved to have a proper duplicated table.
\param layer The layer for which the clone is made
:rtype: QgsAuxiliaryLayer
%End
QgsVectorLayer *toSpatialLayer() const;
%Docstring
An auxiliary layer is not spatial. This method returns a spatial
@ -348,10 +358,23 @@ class QgsAuxiliaryStorage
%Docstring
Removes a table from the auxiliary storage.
\param uri The uri of the table to remove
:return: true if the table is well deleted, false otherwise
:rtype: bool
%End
static bool duplicateTable( const QgsDataSourceUri &uri, const QString &newTable );
%Docstring
Duplicates a table and its content.
\param uri The uri of the table to duplicate
\param newTable The name of the new table
:return: true if the table is well duplicated, false otherwise
:rtype: bool
%End
static QString extension();
%Docstring
Returns the extension used for auxiliary databases.

View File

@ -8873,6 +8873,9 @@ void QgisApp::duplicateLayers( const QList<QgsMapLayer *> &lyrList )
}
else if ( vlayer )
{
if ( vlayer->auxiliaryLayer() )
vlayer->auxiliaryLayer()->save();
dupLayer = vlayer->clone();
}
}

View File

@ -181,6 +181,8 @@ QgsPropertyDefinition QgsAuxiliaryField::propertyDefinition() const
QgsAuxiliaryLayer::QgsAuxiliaryLayer( const QString &pkField, const QString &filename, const QString &table, QgsVectorLayer *vlayer )
: QgsVectorLayer( QString( "%1|layername=%2" ).arg( filename, table ), QString( "%1_auxiliarystorage" ).arg( table ), "ogr" )
, mFileName( filename )
, mTable( table )
, mLayer( vlayer )
{
// init join info
@ -194,6 +196,12 @@ QgsAuxiliaryLayer::QgsAuxiliaryLayer( const QString &pkField, const QString &fil
mJoinInfo.setJoinFieldNamesBlackList( QStringList() << QStringLiteral( "rowid" ) ); // introduced by ogr provider
}
QgsAuxiliaryLayer *QgsAuxiliaryLayer::clone( QgsVectorLayer *target ) const
{
QgsAuxiliaryStorage::duplicateTable( source(), target->id() );
return new QgsAuxiliaryLayer( mJoinInfo.targetFieldName(), mFileName, target->id(), target );
}
QgsVectorLayer *QgsAuxiliaryLayer::toSpatialLayer() const
{
QgsVectorLayer *layer = QgsMemoryProviderUtils::createMemoryLayer( QStringLiteral( "auxiliary_layer" ), fields(), mLayer->wkbType(), mLayer->crs() );
@ -472,33 +480,18 @@ QgsAuxiliaryLayer *QgsAuxiliaryStorage::createAuxiliaryLayer( const QgsField &fi
return alayer;
}
bool QgsAuxiliaryStorage::deleteTable( const QgsDataSourceUri &uri )
bool QgsAuxiliaryStorage::deleteTable( const QgsDataSourceUri &ogrUri )
{
bool rc = false;
QgsDataSourceUri uri = parseOgrUri( ogrUri );
// parsing for ogr style uri :
// " filePath|layername='tableName' table="" sql="
QStringList uriParts = uri.uri().split( '|' );
if ( uriParts.count() < 2 )
return false;
const QString databasePath = uriParts[0].replace( ' ', "" );
const QString table = uriParts[1];
QStringList tableParts = table.split( ' ' );
if ( tableParts.count() < 1 )
return false;
const QString tableName = tableParts[0].replace( "layername=", "" );
if ( !databasePath.isEmpty() && !tableName.isEmpty() )
if ( !uri.database().isEmpty() && !uri.table().isEmpty() )
{
sqlite3 *handler = openDB( databasePath );
sqlite3 *handler = openDB( uri.database() );
if ( handler )
{
QString sql = QString( "DROP TABLE %1" ).arg( tableName );
QString sql = QString( "DROP TABLE %1" ).arg( uri.table() );
rc = exec( sql, handler );
sql = QString( "VACUUM" );
@ -511,6 +504,27 @@ bool QgsAuxiliaryStorage::deleteTable( const QgsDataSourceUri &uri )
return rc;
}
bool QgsAuxiliaryStorage::duplicateTable( const QgsDataSourceUri &ogrUri, const QString &newTable )
{
QgsDataSourceUri uri = parseOgrUri( ogrUri );
bool rc = false;
if ( !uri.table().isEmpty() && !uri.database().isEmpty() )
{
sqlite3 *handler = openDB( uri.database() );
if ( handler )
{
QString sql = QString( "CREATE TABLE %1 AS SELECT * FROM %2" ).arg( newTable, uri.table() );
rc = exec( sql, handler );
close( handler );
}
}
return rc;
}
bool QgsAuxiliaryStorage::saveAs( const QString &filename ) const
{
if ( QFile::exists( filename ) )
@ -680,3 +694,29 @@ QString QgsAuxiliaryStorage::currentFileName() const
else
return mFileName;
}
QgsDataSourceUri QgsAuxiliaryStorage::parseOgrUri( const QgsDataSourceUri &uri )
{
QgsDataSourceUri newUri;
// parsing for ogr style uri :
// " filePath|layername='tableName' table="" sql="
QStringList uriParts = uri.uri().split( '|' );
if ( uriParts.count() < 2 )
return newUri;
const QString databasePath = uriParts[0].replace( ' ', "" );
const QString table = uriParts[1];
QStringList tableParts = table.split( ' ' );
if ( tableParts.count() < 1 )
return newUri;
const QString tableName = tableParts[0].replace( "layername=", "" );
newUri.setDataSource( QString(), tableName, QString() );
newUri.setDatabase( databasePath );
return newUri;
}

View File

@ -137,6 +137,15 @@ class CORE_EXPORT QgsAuxiliaryLayer : public QgsVectorLayer
QgsAuxiliaryLayer &operator=( QgsAuxiliaryLayer const &rhs ) = delete;
/**
* Returns a new instance equivalent to this one. The underlying table
* is duplicate for the layer given in parameter. Note that the current
* auxiliary layer should be saved to have a proper duplicated table.
*
* \param layer The layer for which the clone is made
*/
QgsAuxiliaryLayer *clone( QgsVectorLayer *layer ) const SIP_FACTORY;
/**
* An auxiliary layer is not spatial. This method returns a spatial
* representation of auxiliary data.
@ -243,6 +252,8 @@ class CORE_EXPORT QgsAuxiliaryLayer : public QgsVectorLayer
private:
QgsVectorLayerJoinInfo mJoinInfo;
QString mFileName;
QString mTable;
QgsVectorLayer *mLayer = nullptr;
};
@ -357,10 +368,22 @@ class CORE_EXPORT QgsAuxiliaryStorage
/**
* Removes a table from the auxiliary storage.
*
* \param uri The uri of the table to remove
*
* \returns true if the table is well deleted, false otherwise
*/
static bool deleteTable( const QgsDataSourceUri &uri );
/**
* Duplicates a table and its content.
*
* \param uri The uri of the table to duplicate
* \param newTable The name of the new table
*
* \returns true if the table is well duplicated, false otherwise
*/
static bool duplicateTable( const QgsDataSourceUri &uri, const QString &newTable );
/**
* Returns the extension used for auxiliary databases.
*/
@ -382,6 +405,8 @@ class CORE_EXPORT QgsAuxiliaryStorage
static bool exec( const QString &sql, sqlite3 *handler );
static void debugMsg( const QString &sql, sqlite3 *handler );
static QgsDataSourceUri parseOgrUri( const QgsDataSourceUri &uri );
bool mValid = false;
QString mFileName; // original filename
QString mTmpFileName; // temporary filename used in copy mode

View File

@ -201,7 +201,9 @@ QgsVectorLayer *QgsVectorLayer::clone() const
QList<QgsVectorLayerJoinInfo> joins = vectorJoins();
Q_FOREACH ( const QgsVectorLayerJoinInfo &join, joins )
{
layer->addJoin( join );
// do not copy join information for auxiliary layer
if ( auxiliaryLayer() && auxiliaryLayer()->id() != join.joinLayerId() )
layer->addJoin( join );
}
layer->setProviderEncoding( dataProvider()->encoding() );
@ -264,6 +266,8 @@ QgsVectorLayer *QgsVectorLayer::clone() const
layer->setEditFormConfig( editFormConfig() );
layer->setAuxiliaryLayer( auxiliaryLayer()->clone( layer ) );
return layer;
}