307 lines
9.9 KiB
Python
Raw Normal View History

2012-04-16 13:19:40 +02:00
# -*- coding: utf-8 -*-
"""
/***************************************************************************
Name : DB Manager
2013-06-09 18:28:52 +02:00
Description : Database manager plugin for QGIS
2012-04-16 13:19:40 +02:00
Date : May 23, 2011
copyright : (C) 2011 by Giuseppe Sucameli
email : brush.tyler@gmail.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
"""
2016-09-21 18:24:26 +02:00
from builtins import str
2012-04-16 13:19:40 +02:00
# this will disable the dbplugin if the connector raise an ImportError
from .connector import SpatiaLiteDBConnector
from qgis.PyQt.QtCore import Qt, QFileInfo
2016-04-22 10:38:48 +02:00
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import QApplication, QAction, QFileDialog
from qgis.core import Qgis, QgsDataSourceUri, QgsSettings
from qgis.gui import QgsMessageBar
2012-04-16 13:19:40 +02:00
from ..plugin import DBPlugin, Database, Table, VectorTable, RasterTable, TableField, TableIndex, TableTrigger, \
InvalidDataException
2016-03-21 04:51:10 +01:00
from . import resources_rc # NOQA
2012-04-16 13:19:40 +02:00
def classFactory():
return SpatiaLiteDBPlugin
2012-04-16 13:19:40 +02:00
class SpatiaLiteDBPlugin(DBPlugin):
@classmethod
def icon(self):
return QIcon(":/db_manager/spatialite/icon")
2012-04-16 13:19:40 +02:00
@classmethod
def typeName(self):
return 'spatialite'
2012-04-16 13:19:40 +02:00
@classmethod
def typeNameString(self):
return 'SpatiaLite'
2012-04-16 13:19:40 +02:00
@classmethod
def providerName(self):
return 'spatialite'
2012-04-16 13:19:40 +02:00
@classmethod
def connectionSettingsKey(self):
return '/SpatiaLite/connections'
2012-04-16 13:19:40 +02:00
def databasesFactory(self, connection, uri):
return SLDatabase(connection, uri)
2012-04-16 13:19:40 +02:00
def connect(self, parent=None):
conn_name = self.connectionName()
settings = QgsSettings()
settings.beginGroup(u"/%s/%s" % (self.connectionSettingsKey(), conn_name))
2012-04-16 13:19:40 +02:00
if not settings.contains("sqlitepath"): # non-existent entry?
2017-03-04 16:23:36 +01:00
raise InvalidDataException(self.tr(u'There is no defined database connection "{0}".').format(conn_name))
2012-04-16 13:19:40 +02:00
database = settings.value("sqlitepath")
2012-04-16 13:19:40 +02:00
uri = QgsDataSourceUri()
uri.setDatabase(database)
return self.connectToUri(uri)
2012-04-16 13:19:40 +02:00
@classmethod
def addConnection(self, conn_name, uri):
settings = QgsSettings()
settings.beginGroup(u"/%s/%s" % (self.connectionSettingsKey(), conn_name))
settings.setValue("sqlitepath", uri.database())
return True
@classmethod
def addConnectionActionSlot(self, item, action, parent, index):
QApplication.restoreOverrideCursor()
try:
filename, selected_filter = QFileDialog.getOpenFileName(parent, "Choose SQLite/SpatiaLite file")
if not filename:
return
finally:
QApplication.setOverrideCursor(Qt.WaitCursor)
conn_name = QFileInfo(filename).fileName()
uri = QgsDataSourceUri()
uri.setDatabase(filename)
self.addConnection(conn_name, uri)
index.internalPointer().itemChanged()
2012-04-16 13:19:40 +02:00
class SLDatabase(Database):
def __init__(self, connection, uri):
Database.__init__(self, connection, uri)
2012-04-16 13:19:40 +02:00
def connectorsFactory(self, uri):
return SpatiaLiteDBConnector(uri)
2012-04-16 13:19:40 +02:00
def dataTablesFactory(self, row, db, schema=None):
return SLTable(row, db, schema)
2012-04-16 13:19:40 +02:00
def vectorTablesFactory(self, row, db, schema=None):
return SLVectorTable(row, db, schema)
2012-04-16 13:19:40 +02:00
def rasterTablesFactory(self, row, db, schema=None):
return SLRasterTable(row, db, schema)
2012-04-16 13:19:40 +02:00
def info(self):
from .info_model import SLDatabaseInfo
2012-04-16 13:19:40 +02:00
return SLDatabaseInfo(self)
2012-04-16 13:19:40 +02:00
def sqlResultModel(self, sql, parent):
from .data_model import SLSqlResultModel
2012-04-16 13:19:40 +02:00
return SLSqlResultModel(self, sql, parent)
2012-04-16 13:19:40 +02:00
def registerDatabaseActions(self, mainWindow):
action = QAction(self.tr("Run &Vacuum"), self)
mainWindow.registerAction(action, self.tr("&Database"), self.runVacuumActionSlot)
2012-04-16 13:19:40 +02:00
Database.registerDatabaseActions(self, mainWindow)
2012-04-16 13:19:40 +02:00
def runVacuumActionSlot(self, item, action, parent):
QApplication.restoreOverrideCursor()
try:
if not isinstance(item, (DBPlugin, Table)) or item.database() is None:
parent.infoBar.pushMessage(self.tr("No database selected or you are not connected to it."),
Qgis.Info, parent.iface.messageTimeout())
return
finally:
QApplication.setOverrideCursor(Qt.WaitCursor)
2012-04-16 13:19:40 +02:00
self.runVacuum()
2012-04-16 13:19:40 +02:00
def runVacuum(self):
self.database().aboutToChange.emit()
self.database().connector.runVacuum()
self.database().refresh()
2012-04-16 13:19:40 +02:00
def runAction(self, action):
2016-09-21 18:24:26 +02:00
action = str(action)
2012-04-16 13:19:40 +02:00
if action.startswith("vacuum/"):
if action == "vacuum/run":
self.runVacuum()
return True
2012-04-16 13:19:40 +02:00
return Database.runAction(self, action)
2012-04-16 13:19:40 +02:00
def uniqueIdFunction(self):
return None
2012-04-16 13:19:40 +02:00
def explicitSpatialIndex(self):
return True
def spatialIndexClause(self, src_table, src_column, dest_table, dest_column):
return u""" "%s".ROWID IN (\nSELECT ROWID FROM SpatialIndex WHERE f_table_name='%s' AND search_frame="%s"."%s") """ % (src_table, src_table, dest_table, dest_column)
class SLTable(Table):
def __init__(self, row, db, schema=None):
Table.__init__(self, db, None)
self.name, self.isView, self.isSysTable = row
2012-04-16 13:19:40 +02:00
def ogrUri(self):
ogrUri = u"%s|layername=%s" % (self.uri().database(), self.name)
return ogrUri
def mimeUri(self):
return Table.mimeUri(self)
def toMapLayer(self):
from qgis.core import QgsVectorLayer
provider = self.database().dbplugin().providerName()
uri = self.uri().uri()
return QgsVectorLayer(uri, self.name, provider)
def tableFieldsFactory(self, row, table):
return SLTableField(row, table)
2012-04-16 13:19:40 +02:00
def tableIndexesFactory(self, row, table):
return SLTableIndex(row, table)
2012-04-16 13:19:40 +02:00
def tableTriggersFactory(self, row, table):
return SLTableTrigger(row, table)
2012-04-16 13:19:40 +02:00
def tableDataModel(self, parent):
from .data_model import SLTableDataModel
return SLTableDataModel(self, parent)
class SLVectorTable(SLTable, VectorTable):
def __init__(self, row, db, schema=None):
SLTable.__init__(self, row[:-5], db, schema)
VectorTable.__init__(self, db, schema)
# SpatiaLite does case-insensitive checks for table names, but the
# SL provider didn't do the same in Qgis < 1.9, so self.geomTableName
# stores the table name like stored in the geometry_columns table
self.geomTableName, self.geomColumn, self.geomType, self.geomDim, self.srid = row[-5:]
def uri(self):
uri = self.database().uri()
uri.setDataSource('', self.geomTableName, self.geomColumn)
return uri
def hasSpatialIndex(self, geom_column=None):
geom_column = geom_column if geom_column is not None else self.geomColumn
return self.database().connector.hasSpatialIndex((self.schemaName(), self.name), geom_column)
def createSpatialIndex(self, geom_column=None):
2016-03-21 04:51:10 +01:00
self.aboutToChange.emit()
ret = VectorTable.createSpatialIndex(self, geom_column)
if ret is not False:
self.database().refresh()
return ret
def deleteSpatialIndex(self, geom_column=None):
2016-03-21 04:51:10 +01:00
self.aboutToChange.emit()
ret = VectorTable.deleteSpatialIndex(self, geom_column)
if ret is not False:
self.database().refresh()
return ret
def refreshTableEstimatedExtent(self):
return
def runAction(self, action):
if SLTable.runAction(self, action):
return True
return VectorTable.runAction(self, action)
2012-04-16 13:19:40 +02:00
class SLRasterTable(SLTable, RasterTable):
def __init__(self, row, db, schema=None):
SLTable.__init__(self, row[:-3], db, schema)
RasterTable.__init__(self, db, schema)
self.prefixName, self.geomColumn, self.srid = row[-3:]
self.geomType = 'RASTER'
2012-04-16 13:19:40 +02:00
# def info(self):
#from .info_model import SLRasterTableInfo
#return SLRasterTableInfo(self)
2012-04-16 13:19:40 +02:00
def rasterliteGdalUri(self):
gdalUri = u'RASTERLITE:%s,table=%s' % (self.uri().database(), self.prefixName)
return gdalUri
2012-04-16 13:19:40 +02:00
def mimeUri(self):
# QGIS has no provider to load rasters, let's use GDAL
uri = u"raster:gdal:%s:%s" % (self.name, self.uri().database())
return uri
2012-12-10 00:12:07 +01:00
def toMapLayer(self):
from qgis.core import QgsRasterLayer, QgsContrastEnhancement
# QGIS has no provider to load Rasterlite rasters, let's use GDAL
uri = self.rasterliteGdalUri()
rl = QgsRasterLayer(uri, self.name)
if rl.isValid():
rl.setContrastEnhancement(QgsContrastEnhancement.StretchToMinimumMaximum)
return rl
2012-04-16 13:19:40 +02:00
class SLTableField(TableField):
def __init__(self, row, table):
TableField.__init__(self, table)
self.num, self.name, self.dataType, self.notNull, self.default, self.primaryKey = row
self.hasDefault = self.default
2012-04-16 13:19:40 +02:00
class SLTableIndex(TableIndex):
def __init__(self, row, table):
TableIndex.__init__(self, table)
self.num, self.name, self.isUnique, self.columns = row
2012-04-16 13:19:40 +02:00
class SLTableTrigger(TableTrigger):
def __init__(self, row, table):
TableTrigger.__init__(self, table)
self.name, self.function = row