Skip to content

Commit 462284d

Browse files
committed
Move creation of SpatiaLite DB to provider + option to create DB from browser
1 parent 4906f77 commit 462284d

File tree

5 files changed

+157
-86
lines changed

5 files changed

+157
-86
lines changed

src/app/spatialite/qgsnewspatialitelayerdialog.cpp

Lines changed: 27 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "qgsspatialitesridsdialog.h"
2424
#include "qgsapplication.h"
25+
#include "qgsproviderregistry.h"
2526
#include "qgisapp.h" // <- for theme icons
2627
#include <qgsvectorlayer.h>
2728
#include <qgsmaplayerregistry.h>
@@ -33,6 +34,7 @@
3334
#include <QLineEdit>
3435
#include <QMessageBox>
3536
#include <QFileDialog>
37+
#include <QLibrary>
3638

3739
#include <spatialite.h>
3840

@@ -187,101 +189,43 @@ void QgsNewSpatialiteLayerDialog::on_pbnFindSRID_clicked()
187189
}
188190
}
189191

190-
void QgsNewSpatialiteLayerDialog::initializeSpatialMetadata( sqlite3 *sqlite_handle )
191-
{
192-
// attempting to perform self-initialization for a newly created DB
193-
int ret;
194-
char sql[1024];
195-
char *errMsg = NULL;
196-
int count = 0;
197-
int i;
198-
char **results;
199-
int rows;
200-
int columns;
201-
202-
if ( sqlite_handle == NULL )
203-
return;
204-
// checking if this DB is really empty
205-
strcpy( sql, "SELECT Count(*) from sqlite_master" );
206-
ret = sqlite3_get_table( sqlite_handle, sql, &results, &rows, &columns, NULL );
207-
if ( ret != SQLITE_OK )
208-
return;
209-
if ( rows < 1 )
210-
;
211-
else
212-
{
213-
for ( i = 1; i <= rows; i++ )
214-
count = atoi( results[( i * columns ) + 0] );
215-
}
216-
sqlite3_free_table( results );
217-
218-
if ( count > 0 )
219-
return;
220-
221-
// all right, it's empty: proceding to initialize
222-
strcpy( sql, "SELECT InitSpatialMetadata()" );
223-
ret = sqlite3_exec( sqlite_handle, sql, NULL, NULL, &errMsg );
224-
if ( ret != SQLITE_OK )
225-
{
226-
QString errCause = tr( "Unable to initialize SpatialMetadata:\n" );
227-
errCause += QString::fromUtf8( errMsg );
228-
QMessageBox::warning( 0, tr( "SpatiaLite Database" ), errCause );
229-
sqlite3_free( errMsg );
230-
return;
231-
}
232-
spatial_ref_sys_init( sqlite_handle, 0 );
233-
}
234-
235192
bool QgsNewSpatialiteLayerDialog::createDb()
236193
{
237-
QSettings settings;
238-
int ret;
239-
sqlite3 *sqlite_handle;
240-
char *errMsg = NULL;
241-
242-
if ( mDatabaseComboBox->currentText().isEmpty() )
194+
QString dbPath = mDatabaseComboBox->currentText();
195+
if ( dbPath.isEmpty() )
243196
return false;
244197

245-
QFile newDb( mDatabaseComboBox->currentText() );
198+
QFile newDb( dbPath );
246199
if ( !newDb.exists() )
247200
{
248-
QgsDebugMsg( "creating a new db" );
201+
QString errCause;
202+
bool res = false;
249203

250-
QFileInfo fullPath = QFileInfo( mDatabaseComboBox->currentText() );
251-
QDir path = fullPath.dir();
252-
QgsDebugMsg( QString( "making this dir: %1" ).arg( path.absolutePath() ) );
204+
QString spatialite_lib = QgsProviderRegistry::instance()->library( "spatialite" );
205+
QLibrary* myLib = new QLibrary( spatialite_lib );
206+
bool loaded = myLib->load();
207+
if ( loaded )
208+
{
209+
QgsDebugMsg( "spatialite provider loaded" );
253210

254-
// Must be sure there is destination directory ~/.qgis
255-
QDir().mkpath( path.absolutePath( ) );
211+
typedef bool ( *createDbProc )( const QString&, QString& );
212+
createDbProc createDbPtr = ( createDbProc ) cast_to_fptr( myLib->resolve( "createDb" ) );
213+
if ( createDbPtr )
214+
{
215+
res = createDbPtr( dbPath, errCause );
216+
}
217+
else
218+
{
219+
errCause = "Resolving createDb(...) failed";
220+
}
221+
}
222+
delete myLib;
256223

257-
// creating/opening the new database
258-
QString dbPath = newDb.fileName();
259-
spatialite_init( 0 );
260-
ret = sqlite3_open_v2( dbPath.toUtf8().constData(), &sqlite_handle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL );
261-
if ( ret )
224+
if ( !res )
262225
{
263-
// an error occurred
264-
QString errCause = tr( "Could not create a new database\n" );
265-
errCause += QString::fromUtf8( sqlite3_errmsg( sqlite_handle ) );
266-
sqlite3_close( sqlite_handle );
267226
QMessageBox::warning( 0, tr( "SpatiaLite Database" ), errCause );
268227
pbnFindSRID->setEnabled( false );
269-
return false;
270228
}
271-
// activating Foreign Key constraints
272-
ret = sqlite3_exec( sqlite_handle, "PRAGMA foreign_keys = 1", NULL, 0, &errMsg );
273-
if ( ret != SQLITE_OK )
274-
{
275-
QMessageBox::warning( 0, tr( "SpatiaLite Database" ), tr( "Unable to activate FOREIGN_KEY constraints" ) );
276-
sqlite3_free( errMsg );
277-
sqlite3_close( sqlite_handle );
278-
pbnFindSRID->setEnabled( false );
279-
return false;
280-
}
281-
initializeSpatialMetadata( sqlite_handle );
282-
283-
// all done: closing the DB connection
284-
sqlite3_close( sqlite_handle );
285229
}
286230

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

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

240+
QSettings settings;
296241
if ( !settings.contains( key ) )
297242
{
298243
settings.setValue( "/SpatiaLite/connections/selected", fi.fileName() + tr( "@" ) + fi.canonicalFilePath() );

src/app/spatialite/qgsnewspatialitelayerdialog.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,6 @@ class QgsNewSpatialiteLayerDialog: public QDialog, private Ui::QgsNewSpatialiteL
5858
/** Create a new database */
5959
bool createDb();
6060

61-
/** Initializes SpatialMetadata db-tables */
62-
void initializeSpatialMetadata( sqlite3 *sqlite_handle );
63-
6461
static QString quotedIdentifier( QString id );
6562
static QString quotedValue( QString value );
6663
};

src/providers/spatialite/qgsspatialitedataitems.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
#include "qgslogger.h"
88

99
#include <QAction>
10-
10+
#include <QMessageBox>
11+
#include <QSettings>
1112

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

153+
QAction* actionCreateDatabase = new QAction( tr( "Create database..." ), this );
154+
connect( actionCreateDatabase, SIGNAL( triggered() ), this, SLOT( createDatabase() ) );
155+
lst.append( actionCreateDatabase );
156+
152157
return lst;
153158
}
154159

@@ -172,6 +177,38 @@ void QgsSLRootItem::newConnection()
172177
}
173178
}
174179

180+
QGISEXTERN bool createDb( const QString& dbPath, QString& errCause );
181+
182+
void QgsSLRootItem::createDatabase()
183+
{
184+
QSettings settings;
185+
QString lastUsedDir = settings.value( "/UI/lastSpatiaLiteDir", "." ).toString();
186+
187+
QString filename = QFileDialog::getSaveFileName( 0, tr( "New SpatiaLite Database File" ),
188+
lastUsedDir,
189+
tr( "SpatiaLite (*.sqlite *.db )" ) );
190+
if ( filename.isEmpty() )
191+
return;
192+
193+
QString errCause;
194+
if ( ::createDb( filename, errCause ) )
195+
{
196+
QMessageBox::information( 0, tr( "Create SpatiaLite database" ), tr( "The database has been created" ) );
197+
198+
// add connection
199+
QString baseKey = "/SpatiaLite/connections/";
200+
QSettings settings;
201+
settings.setValue( baseKey + "/sqlitepath", filename );
202+
203+
refresh();
204+
}
205+
else
206+
{
207+
QMessageBox::critical( 0, tr( "Create SpatiaLite database" ), tr( "Failed to create the database:\n" ) + errCause );
208+
}
209+
210+
}
211+
175212
// ---------------------------------------------------------------------------
176213

177214
QGISEXTERN QgsSpatiaLiteSourceSelect * selectWidget( QWidget * parent, Qt::WFlags fl )

src/providers/spatialite/qgsspatialitedataitems.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class QgsSLRootItem : public QgsDataCollectionItem
4949
public slots:
5050
void connectionsChanged();
5151
void newConnection();
52+
void createDatabase();
5253
};
5354

5455

src/providers/spatialite/qgsspatialiteprovider.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ email : a.furieri@lqt.it
2828

2929
#include "qgslogger.h"
3030

31+
#include <QFileInfo>
32+
#include <QDir>
33+
3134
#ifdef _MSC_VER
3235
#define strcasecmp(a,b) stricmp(a,b)
3336
#endif
@@ -4895,3 +4898,91 @@ QGISEXTERN QgsVectorLayerImport::ImportError createEmptyLayer(
48954898
oldToNewAttrIdxMap, errorMessage, options
48964899
);
48974900
}
4901+
4902+
// -------------
4903+
4904+
static bool initializeSpatialMetadata( sqlite3 *sqlite_handle, QString& errCause )
4905+
{
4906+
// attempting to perform self-initialization for a newly created DB
4907+
int ret;
4908+
char sql[1024];
4909+
char *errMsg = NULL;
4910+
int count = 0;
4911+
int i;
4912+
char **results;
4913+
int rows;
4914+
int columns;
4915+
4916+
if ( sqlite_handle == NULL )
4917+
return false;
4918+
// checking if this DB is really empty
4919+
strcpy( sql, "SELECT Count(*) from sqlite_master" );
4920+
ret = sqlite3_get_table( sqlite_handle, sql, &results, &rows, &columns, NULL );
4921+
if ( ret != SQLITE_OK )
4922+
return false;
4923+
if ( rows < 1 )
4924+
;
4925+
else
4926+
{
4927+
for ( i = 1; i <= rows; i++ )
4928+
count = atoi( results[( i * columns ) + 0] );
4929+
}
4930+
sqlite3_free_table( results );
4931+
4932+
if ( count > 0 )
4933+
return false;
4934+
4935+
// all right, it's empty: proceding to initialize
4936+
strcpy( sql, "SELECT InitSpatialMetadata()" );
4937+
ret = sqlite3_exec( sqlite_handle, sql, NULL, NULL, &errMsg );
4938+
if ( ret != SQLITE_OK )
4939+
{
4940+
errCause = QObject::tr( "Unable to initialize SpatialMetadata:\n" );
4941+
errCause += QString::fromUtf8( errMsg );
4942+
sqlite3_free( errMsg );
4943+
return false;
4944+
}
4945+
spatial_ref_sys_init( sqlite_handle, 0 );
4946+
return true;
4947+
}
4948+
4949+
QGISEXTERN bool createDb( const QString& dbPath, QString& errCause )
4950+
{
4951+
QgsDebugMsg( "creating a new db" );
4952+
4953+
QFileInfo fullPath = QFileInfo( dbPath );
4954+
QDir path = fullPath.dir();
4955+
QgsDebugMsg( QString( "making this dir: %1" ).arg( path.absolutePath() ) );
4956+
4957+
// Must be sure there is destination directory ~/.qgis
4958+
QDir().mkpath( path.absolutePath( ) );
4959+
4960+
// creating/opening the new database
4961+
spatialite_init( 0 );
4962+
sqlite3 *sqlite_handle;
4963+
int ret = sqlite3_open_v2( dbPath.toUtf8().constData(), &sqlite_handle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL );
4964+
if ( ret )
4965+
{
4966+
// an error occurred
4967+
errCause = QObject::tr( "Could not create a new database\n" );
4968+
errCause += QString::fromUtf8( sqlite3_errmsg( sqlite_handle ) );
4969+
sqlite3_close( sqlite_handle );
4970+
return false;
4971+
}
4972+
// activating Foreign Key constraints
4973+
char *errMsg = NULL;
4974+
ret = sqlite3_exec( sqlite_handle, "PRAGMA foreign_keys = 1", NULL, 0, &errMsg );
4975+
if ( ret != SQLITE_OK )
4976+
{
4977+
errCause = QObject::tr( "Unable to activate FOREIGN_KEY constraints" );
4978+
sqlite3_free( errMsg );
4979+
sqlite3_close( sqlite_handle );
4980+
return false;
4981+
}
4982+
bool init_res = ::initializeSpatialMetadata( sqlite_handle, errCause );
4983+
4984+
// all done: closing the DB connection
4985+
sqlite3_close( sqlite_handle );
4986+
4987+
return init_res;
4988+
}

0 commit comments

Comments
 (0)