Skip to content

Commit

Permalink
Move creation of SpatiaLite DB to provider + option to create DB from…
Browse files Browse the repository at this point in the history
… browser
  • Loading branch information
wonder-sk committed Nov 16, 2011
1 parent 4906f77 commit 462284d
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 86 deletions.
109 changes: 27 additions & 82 deletions src/app/spatialite/qgsnewspatialitelayerdialog.cpp
Expand Up @@ -22,6 +22,7 @@

#include "qgsspatialitesridsdialog.h"
#include "qgsapplication.h"
#include "qgsproviderregistry.h"
#include "qgisapp.h" // <- for theme icons
#include <qgsvectorlayer.h>
#include <qgsmaplayerregistry.h>
Expand All @@ -33,6 +34,7 @@
#include <QLineEdit>
#include <QMessageBox>
#include <QFileDialog>
#include <QLibrary>

#include <spatialite.h>

Expand Down Expand Up @@ -187,101 +189,43 @@ void QgsNewSpatialiteLayerDialog::on_pbnFindSRID_clicked()
}
}

void QgsNewSpatialiteLayerDialog::initializeSpatialMetadata( sqlite3 *sqlite_handle )
{
// attempting to perform self-initialization for a newly created DB
int ret;
char sql[1024];
char *errMsg = NULL;
int count = 0;
int i;
char **results;
int rows;
int columns;

if ( sqlite_handle == NULL )
return;
// checking if this DB is really empty
strcpy( sql, "SELECT Count(*) from sqlite_master" );
ret = sqlite3_get_table( sqlite_handle, sql, &results, &rows, &columns, NULL );
if ( ret != SQLITE_OK )
return;
if ( rows < 1 )
;
else
{
for ( i = 1; i <= rows; i++ )
count = atoi( results[( i * columns ) + 0] );
}
sqlite3_free_table( results );

if ( count > 0 )
return;

// all right, it's empty: proceding to initialize
strcpy( sql, "SELECT InitSpatialMetadata()" );
ret = sqlite3_exec( sqlite_handle, sql, NULL, NULL, &errMsg );
if ( ret != SQLITE_OK )
{
QString errCause = tr( "Unable to initialize SpatialMetadata:\n" );
errCause += QString::fromUtf8( errMsg );
QMessageBox::warning( 0, tr( "SpatiaLite Database" ), errCause );
sqlite3_free( errMsg );
return;
}
spatial_ref_sys_init( sqlite_handle, 0 );
}

bool QgsNewSpatialiteLayerDialog::createDb()
{
QSettings settings;
int ret;
sqlite3 *sqlite_handle;
char *errMsg = NULL;

if ( mDatabaseComboBox->currentText().isEmpty() )
QString dbPath = mDatabaseComboBox->currentText();
if ( dbPath.isEmpty() )
return false;

QFile newDb( mDatabaseComboBox->currentText() );
QFile newDb( dbPath );
if ( !newDb.exists() )
{
QgsDebugMsg( "creating a new db" );
QString errCause;
bool res = false;

QFileInfo fullPath = QFileInfo( mDatabaseComboBox->currentText() );
QDir path = fullPath.dir();
QgsDebugMsg( QString( "making this dir: %1" ).arg( path.absolutePath() ) );
QString spatialite_lib = QgsProviderRegistry::instance()->library( "spatialite" );
QLibrary* myLib = new QLibrary( spatialite_lib );
bool loaded = myLib->load();
if ( loaded )
{
QgsDebugMsg( "spatialite provider loaded" );

// Must be sure there is destination directory ~/.qgis
QDir().mkpath( path.absolutePath( ) );
typedef bool ( *createDbProc )( const QString&, QString& );
createDbProc createDbPtr = ( createDbProc ) cast_to_fptr( myLib->resolve( "createDb" ) );
if ( createDbPtr )
{
res = createDbPtr( dbPath, errCause );
}
else
{
errCause = "Resolving createDb(...) failed";
}
}
delete myLib;

// creating/opening the new database
QString dbPath = newDb.fileName();
spatialite_init( 0 );
ret = sqlite3_open_v2( dbPath.toUtf8().constData(), &sqlite_handle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL );
if ( ret )
if ( !res )
{
// an error occurred
QString errCause = tr( "Could not create a new database\n" );
errCause += QString::fromUtf8( sqlite3_errmsg( sqlite_handle ) );
sqlite3_close( sqlite_handle );
QMessageBox::warning( 0, tr( "SpatiaLite Database" ), errCause );
pbnFindSRID->setEnabled( false );
return false;
}
// activating Foreign Key constraints
ret = sqlite3_exec( sqlite_handle, "PRAGMA foreign_keys = 1", NULL, 0, &errMsg );
if ( ret != SQLITE_OK )
{
QMessageBox::warning( 0, tr( "SpatiaLite Database" ), tr( "Unable to activate FOREIGN_KEY constraints" ) );
sqlite3_free( errMsg );
sqlite3_close( sqlite_handle );
pbnFindSRID->setEnabled( false );
return false;
}
initializeSpatialMetadata( sqlite_handle );

// all done: closing the DB connection
sqlite3_close( sqlite_handle );
}

QFileInfo fi( newDb );
Expand All @@ -293,6 +237,7 @@ bool QgsNewSpatialiteLayerDialog::createDb()

QString key = "/SpatiaLite/connections/" + fi.fileName() + "/sqlitepath";

QSettings settings;
if ( !settings.contains( key ) )
{
settings.setValue( "/SpatiaLite/connections/selected", fi.fileName() + tr( "@" ) + fi.canonicalFilePath() );
Expand Down
3 changes: 0 additions & 3 deletions src/app/spatialite/qgsnewspatialitelayerdialog.h
Expand Up @@ -58,9 +58,6 @@ class QgsNewSpatialiteLayerDialog: public QDialog, private Ui::QgsNewSpatialiteL
/** Create a new database */
bool createDb();

/** Initializes SpatialMetadata db-tables */
void initializeSpatialMetadata( sqlite3 *sqlite_handle );

static QString quotedIdentifier( QString id );
static QString quotedValue( QString value );
};
Expand Down
39 changes: 38 additions & 1 deletion src/providers/spatialite/qgsspatialitedataitems.cpp
Expand Up @@ -7,7 +7,8 @@
#include "qgslogger.h"

#include <QAction>

#include <QMessageBox>
#include <QSettings>

QgsSLConnectionItem::QgsSLConnectionItem( QgsDataItem* parent, QString name, QString path )
: QgsDataCollectionItem( parent, name, path )
Expand Down Expand Up @@ -149,6 +150,10 @@ QList<QAction*> QgsSLRootItem::actions()
connect( actionNew, SIGNAL( triggered() ), this, SLOT( newConnection() ) );
lst.append( actionNew );

QAction* actionCreateDatabase = new QAction( tr( "Create database..." ), this );
connect( actionCreateDatabase, SIGNAL( triggered() ), this, SLOT( createDatabase() ) );
lst.append( actionCreateDatabase );

return lst;
}

Expand All @@ -172,6 +177,38 @@ void QgsSLRootItem::newConnection()
}
}

QGISEXTERN bool createDb( const QString& dbPath, QString& errCause );

void QgsSLRootItem::createDatabase()
{
QSettings settings;
QString lastUsedDir = settings.value( "/UI/lastSpatiaLiteDir", "." ).toString();

QString filename = QFileDialog::getSaveFileName( 0, tr( "New SpatiaLite Database File" ),
lastUsedDir,
tr( "SpatiaLite (*.sqlite *.db )" ) );
if ( filename.isEmpty() )
return;

QString errCause;
if ( ::createDb( filename, errCause ) )
{
QMessageBox::information( 0, tr( "Create SpatiaLite database" ), tr( "The database has been created" ) );

// add connection
QString baseKey = "/SpatiaLite/connections/";
QSettings settings;
settings.setValue( baseKey + "/sqlitepath", filename );

refresh();
}
else
{
QMessageBox::critical( 0, tr( "Create SpatiaLite database" ), tr( "Failed to create the database:\n" ) + errCause );
}

}

// ---------------------------------------------------------------------------

QGISEXTERN QgsSpatiaLiteSourceSelect * selectWidget( QWidget * parent, Qt::WFlags fl )
Expand Down
1 change: 1 addition & 0 deletions src/providers/spatialite/qgsspatialitedataitems.h
Expand Up @@ -49,6 +49,7 @@ class QgsSLRootItem : public QgsDataCollectionItem
public slots:
void connectionsChanged();
void newConnection();
void createDatabase();
};


Expand Down
91 changes: 91 additions & 0 deletions src/providers/spatialite/qgsspatialiteprovider.cpp
Expand Up @@ -28,6 +28,9 @@ email : a.furieri@lqt.it

#include "qgslogger.h"

#include <QFileInfo>
#include <QDir>

#ifdef _MSC_VER
#define strcasecmp(a,b) stricmp(a,b)
#endif
Expand Down Expand Up @@ -4895,3 +4898,91 @@ QGISEXTERN QgsVectorLayerImport::ImportError createEmptyLayer(
oldToNewAttrIdxMap, errorMessage, options
);
}

// -------------

static bool initializeSpatialMetadata( sqlite3 *sqlite_handle, QString& errCause )
{
// attempting to perform self-initialization for a newly created DB
int ret;
char sql[1024];
char *errMsg = NULL;
int count = 0;
int i;
char **results;
int rows;
int columns;

if ( sqlite_handle == NULL )
return false;
// checking if this DB is really empty
strcpy( sql, "SELECT Count(*) from sqlite_master" );
ret = sqlite3_get_table( sqlite_handle, sql, &results, &rows, &columns, NULL );
if ( ret != SQLITE_OK )
return false;
if ( rows < 1 )
;
else
{
for ( i = 1; i <= rows; i++ )
count = atoi( results[( i * columns ) + 0] );
}
sqlite3_free_table( results );

if ( count > 0 )
return false;

// all right, it's empty: proceding to initialize
strcpy( sql, "SELECT InitSpatialMetadata()" );
ret = sqlite3_exec( sqlite_handle, sql, NULL, NULL, &errMsg );
if ( ret != SQLITE_OK )
{
errCause = QObject::tr( "Unable to initialize SpatialMetadata:\n" );
errCause += QString::fromUtf8( errMsg );
sqlite3_free( errMsg );
return false;
}
spatial_ref_sys_init( sqlite_handle, 0 );
return true;
}

QGISEXTERN bool createDb( const QString& dbPath, QString& errCause )
{
QgsDebugMsg( "creating a new db" );

QFileInfo fullPath = QFileInfo( dbPath );
QDir path = fullPath.dir();
QgsDebugMsg( QString( "making this dir: %1" ).arg( path.absolutePath() ) );

// Must be sure there is destination directory ~/.qgis
QDir().mkpath( path.absolutePath( ) );

// creating/opening the new database
spatialite_init( 0 );
sqlite3 *sqlite_handle;
int ret = sqlite3_open_v2( dbPath.toUtf8().constData(), &sqlite_handle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL );
if ( ret )
{
// an error occurred
errCause = QObject::tr( "Could not create a new database\n" );
errCause += QString::fromUtf8( sqlite3_errmsg( sqlite_handle ) );
sqlite3_close( sqlite_handle );
return false;
}
// activating Foreign Key constraints
char *errMsg = NULL;
ret = sqlite3_exec( sqlite_handle, "PRAGMA foreign_keys = 1", NULL, 0, &errMsg );
if ( ret != SQLITE_OK )
{
errCause = QObject::tr( "Unable to activate FOREIGN_KEY constraints" );
sqlite3_free( errMsg );
sqlite3_close( sqlite_handle );
return false;
}
bool init_res = ::initializeSpatialMetadata( sqlite_handle, errCause );

// all done: closing the DB connection
sqlite3_close( sqlite_handle );

return init_res;
}

0 comments on commit 462284d

Please sign in to comment.