mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
[DBManager] add SL/Geopackage connection by drag&drop (follow b11f67b4f5), improve GPKG support:
- recognize tables with geometry, - load GPGK layers to canvas from context menu, - disable table editing
This commit is contained in:
parent
7d79a73f58
commit
03916d549a
@ -284,6 +284,8 @@ class DBModel(QAbstractItemModel):
|
||||
if self.isImportVectorAvail:
|
||||
self.connect(self, SIGNAL("importVector"), self.importVector)
|
||||
|
||||
self.hasSpatialiteSupport = "spatialite" in supportedDbTypes()
|
||||
|
||||
self.rootItem = TreeItem(None, None)
|
||||
for dbtype in supportedDbTypes():
|
||||
dbpluginclass = createDbPlugin(dbtype)
|
||||
@ -373,13 +375,18 @@ class DBModel(QAbstractItemModel):
|
||||
if isinstance(item, TableItem):
|
||||
flags |= Qt.ItemIsDragEnabled
|
||||
|
||||
if self.isImportVectorAvail: # allow to import a vector layer
|
||||
# vectors/tables can be dropped on connected databases to be imported
|
||||
if self.isImportVectorAvail:
|
||||
if isinstance(item, ConnectionItem) and item.populated:
|
||||
flags |= Qt.ItemIsDropEnabled
|
||||
|
||||
if isinstance(item, SchemaItem) or isinstance(item, TableItem):
|
||||
if isinstance(item, (SchemaItem, TableItem)):
|
||||
flags |= Qt.ItemIsDropEnabled
|
||||
|
||||
# SL/Geopackage db files can be dropped everywhere in the tree
|
||||
if self.hasSpatialiteSupport:
|
||||
flags |= Qt.ItemIsDropEnabled
|
||||
|
||||
return flags
|
||||
|
||||
def headerData(self, section, orientation, role):
|
||||
@ -508,8 +515,10 @@ class DBModel(QAbstractItemModel):
|
||||
if action == Qt.IgnoreAction:
|
||||
return True
|
||||
|
||||
if not self.isImportVectorAvail:
|
||||
return False
|
||||
# vectors/tables to be imported must be dropped on connected db, schema or table
|
||||
canImportLayer = self.isImportVectorAvail and parent.isValid() and \
|
||||
( isinstance(parent.internalPointer(), (SchemaItem, TableItem)) or \
|
||||
( isinstance(parent.internalPointer(), ConnectionItem) and parent.internalPointer().populated ) )
|
||||
|
||||
added = 0
|
||||
|
||||
@ -518,22 +527,42 @@ class DBModel(QAbstractItemModel):
|
||||
filename = u.toLocalFile()
|
||||
if filename == "":
|
||||
continue
|
||||
if qgis.core.QgsRasterLayer.isValidRasterFileName(filename):
|
||||
layerType = 'raster'
|
||||
providerKey = 'gdal'
|
||||
else:
|
||||
layerType = 'vector'
|
||||
providerKey = 'ogr'
|
||||
|
||||
layerName = QFileInfo(filename).completeBaseName()
|
||||
if self.hasSpatialiteSupport:
|
||||
from .db_plugins.spatialite.connector import SpatiaLiteDBConnector
|
||||
|
||||
if self.importLayer(layerType, providerKey, layerName, filename, parent):
|
||||
added += 1
|
||||
if SpatiaLiteDBConnector.isValidDatabase(filename):
|
||||
# retrieve the SL plugin tree item using its path
|
||||
index = self._rPath2Index(["spatialite"])
|
||||
if not index.isValid():
|
||||
continue
|
||||
item = index.internalPointer()
|
||||
|
||||
conn_name = QFileInfo(filename).fileName()
|
||||
uri = qgis.core.QgsDataSourceURI()
|
||||
uri.setDatabase(filename)
|
||||
item.getItemData().addConnection(conn_name, uri)
|
||||
item.emit(SIGNAL('itemChanged'), item)
|
||||
added += 1
|
||||
continue
|
||||
|
||||
if canImportLayer:
|
||||
if qgis.core.QgsRasterLayer.isValidRasterFileName(filename):
|
||||
layerType = 'raster'
|
||||
providerKey = 'gdal'
|
||||
else:
|
||||
layerType = 'vector'
|
||||
providerKey = 'ogr'
|
||||
|
||||
layerName = QFileInfo(filename).completeBaseName()
|
||||
if self.importLayer(layerType, providerKey, layerName, filename, parent):
|
||||
added += 1
|
||||
|
||||
if data.hasFormat(self.QGIS_URI_MIME):
|
||||
for uri in qgis.core.QgsMimeDataUtils.decodeUriList(data):
|
||||
if self.importLayer(uri.layerType, uri.providerKey, uri.name, uri.uri, parent):
|
||||
added += 1
|
||||
if canImportLayer:
|
||||
if self.importLayer(uri.layerType, uri.providerKey, uri.name, uri.uri, parent):
|
||||
added += 1
|
||||
|
||||
return added > 0
|
||||
|
||||
|
@ -97,6 +97,9 @@ class DBPlugin(QObject):
|
||||
|
||||
return DatabaseInfo(None)
|
||||
|
||||
def connect(self, parent=None):
|
||||
raise NotImplemented
|
||||
|
||||
def connectToUri(self, uri):
|
||||
self.db = self.databasesFactory(self, uri)
|
||||
if self.db:
|
||||
@ -111,6 +114,17 @@ class DBPlugin(QObject):
|
||||
return self.connectToUri(uri)
|
||||
return self.connect(self.parent())
|
||||
|
||||
def remove(self):
|
||||
settings = QSettings()
|
||||
settings.beginGroup(u"/%s/%s" % (self.connectionSettingsKey(), self.connectionName()))
|
||||
settings.remove("")
|
||||
self.emit(SIGNAL('deleted'))
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def addConnection(self, conn_name, uri):
|
||||
raise NotImplemented
|
||||
|
||||
@classmethod
|
||||
def icon(self):
|
||||
return None
|
||||
@ -135,11 +149,6 @@ class DBPlugin(QObject):
|
||||
# return the key used to store the connections in settings
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def connectionSettingsFileKey(self):
|
||||
# return the filekey for the settings
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def connections(self):
|
||||
# get the list of connections
|
||||
@ -154,6 +163,24 @@ class DBPlugin(QObject):
|
||||
def databasesFactory(self, connection, uri):
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def addConnectionActionSlot(self, item, action, parent):
|
||||
raise NotImplemented
|
||||
|
||||
def removeActionSlot(self, item, action, parent):
|
||||
QApplication.restoreOverrideCursor()
|
||||
try:
|
||||
res = QMessageBox.question(parent, QApplication.translate("DBManagerPlugin", "hey!"),
|
||||
QApplication.translate("DBManagerPlugin",
|
||||
"Really remove connection to %s?") % item.connectionName(),
|
||||
QMessageBox.Yes | QMessageBox.No)
|
||||
if res != QMessageBox.Yes:
|
||||
return
|
||||
finally:
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
|
||||
item.remove()
|
||||
|
||||
|
||||
class DbItemObject(QObject):
|
||||
|
||||
@ -207,6 +234,13 @@ class Database(DbItemObject):
|
||||
def publicUri(self):
|
||||
return self.connector.publicUri()
|
||||
|
||||
def delete(self):
|
||||
self.aboutToChange()
|
||||
ret = self.connection().remove()
|
||||
if ret is not False:
|
||||
self.emit(SIGNAL('deleted'))
|
||||
return ret
|
||||
|
||||
def info(self):
|
||||
from .info_model import DatabaseInfo
|
||||
|
||||
@ -636,9 +670,6 @@ class Table(DbItemObject):
|
||||
|
||||
def mimeUri(self):
|
||||
layerType = "raster" if self.type == Table.RasterType else "vector"
|
||||
if self.database().dbplugin().typeName() == "spatialite" and self.database().connector.isgpkg():
|
||||
url = unicode(self.database().connector._connectionInfo() + "|layername=" + self.name)
|
||||
return u"%s:%s:%s:%s" % (layerType, "ogr", self.name, url)
|
||||
return u"%s:%s:%s:%s" % (layerType, self.database().dbplugin().providerName(), self.name, self.uri().uri())
|
||||
|
||||
def toMapLayer(self):
|
||||
|
@ -64,10 +64,6 @@ class PostGisDBPlugin(DBPlugin):
|
||||
def connectionSettingsKey(self):
|
||||
return '/PostgreSQL/connections'
|
||||
|
||||
@classmethod
|
||||
def connectionSettingsFileKey(self):
|
||||
return "database"
|
||||
|
||||
def databasesFactory(self, connection, uri):
|
||||
return PGDatabase(connection, uri)
|
||||
|
||||
@ -284,6 +280,7 @@ class PGRasterTable(PGTable, RasterTable):
|
||||
return gdalUri
|
||||
|
||||
def mimeUri(self):
|
||||
# QGIS has no provider for PGRasters, let's use GDAL
|
||||
uri = u"raster:gdal:%s:%s" % (self.name, re.sub(":", "\:", self.gdalUri()))
|
||||
return uri
|
||||
|
||||
|
@ -50,12 +50,22 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
|
||||
self._checkSpatial()
|
||||
self._checkRaster()
|
||||
self._checkGeometryColumnsTable()
|
||||
self._checkRastersTable()
|
||||
self._checkGeopackage()
|
||||
|
||||
def _connectionInfo(self):
|
||||
return unicode(self.dbname)
|
||||
|
||||
@classmethod
|
||||
def isValidDatabase(self, path):
|
||||
if not QFile.exists(path):
|
||||
return False
|
||||
try:
|
||||
conn = sqlite.connect(path)
|
||||
except self.connection_error_types() as e:
|
||||
return False
|
||||
conn.close()
|
||||
return True
|
||||
|
||||
def _checkSpatial(self):
|
||||
""" check if it's a valid spatialite db """
|
||||
self.has_spatial = self._checkGeometryColumnsTable()
|
||||
@ -63,9 +73,14 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
|
||||
def _checkRaster(self):
|
||||
""" check if it's a rasterite db """
|
||||
self.has_raster = self._checkRastersTable()
|
||||
self.has_raster = self._checkRasterTables()
|
||||
return self.has_raster
|
||||
|
||||
def _checkGeopackage(self):
|
||||
""" check if it's a geopackage db """
|
||||
self.is_gpkg = self._checkGeopackageTables()
|
||||
return self.is_gpkg
|
||||
|
||||
def _checkGeometryColumnsTable(self):
|
||||
try:
|
||||
c = self._get_cursor()
|
||||
@ -80,13 +95,40 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
self.has_geometry_columns_access = self.has_geometry_columns
|
||||
return self.has_geometry_columns
|
||||
|
||||
def _checkRastersTable(self):
|
||||
def _checkRasterTables(self):
|
||||
c = self._get_cursor()
|
||||
sql = u"SELECT count(*) = 3 FROM sqlite_master WHERE name IN ('layer_params', 'layer_statistics', 'raster_pyramids')"
|
||||
self._execute(c, sql)
|
||||
ret = c.fetchone()
|
||||
return ret and ret[0]
|
||||
|
||||
def _checkGeopackageTables(self):
|
||||
try:
|
||||
sql = u"SELECT HasGeoPackage()"
|
||||
result = self._execute(None, sql).fetchone()[0] == 1
|
||||
except ConnectionError:
|
||||
result = False
|
||||
|
||||
if result:
|
||||
try:
|
||||
sql = u"SELECT CheckGeoPackageMetaData()"
|
||||
result = self._execute(None, sql).fetchone()[0] == 1
|
||||
except ConnectionError:
|
||||
result = False
|
||||
else:
|
||||
# Spatialite < 4.2 has no GeoPackage support, check for filename and GPKG layout
|
||||
ver = map(int, self.getInfo()[0].split('.')[0:2])
|
||||
if ver[0] < 4 or (ver[0] == 4 and ver[1] < 2):
|
||||
hasGpkgFileExt = self.dbname[-5:] == ".gpkg" or self.dbname[-11:] == ".geopackage"
|
||||
|
||||
sql = u"SELECT count(*) = 3 FROM sqlite_master WHERE name IN ('gpkg_geometry_columns', 'gpkg_spatial_ref_sys', 'gpkg_contents')"
|
||||
ret = self._execute(None, sql).fetchone()
|
||||
hasGpkgLayout = ret and ret[0]
|
||||
|
||||
result = hasGpkgFileExt and hasGpkgLayout
|
||||
|
||||
return result
|
||||
|
||||
def getInfo(self):
|
||||
c = self._get_cursor()
|
||||
self._execute(c, u"SELECT sqlite_version()")
|
||||
@ -98,7 +140,7 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
- geos version
|
||||
- proj version
|
||||
"""
|
||||
if not self.has_spatial:
|
||||
if not self.has_spatial and not self.is_gpkg:
|
||||
return
|
||||
|
||||
c = self._get_cursor()
|
||||
@ -126,14 +168,8 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
def hasCreateSpatialViewSupport(self):
|
||||
return True
|
||||
|
||||
def isgpkg(self):
|
||||
info = map(int, self.getInfo()[0].split('.')[0:2])
|
||||
if info[0] < 4 or (info[0] == 4 and info[1] < 2):
|
||||
result = self.uri().database()[-5:] == ".gpkg"
|
||||
else:
|
||||
sql = u"SELECT HasGeoPackage()"
|
||||
result = self._execute(None, sql).fetchone()[0] == 1
|
||||
return result
|
||||
def isGpkg(self):
|
||||
return self.is_gpkg
|
||||
|
||||
def fieldTypes(self):
|
||||
return [
|
||||
@ -225,13 +261,9 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
srid
|
||||
"""
|
||||
|
||||
if not self.has_geometry_columns:
|
||||
return []
|
||||
|
||||
c = self._get_cursor()
|
||||
|
||||
if self.has_spatialite4:
|
||||
cols = """CASE geometry_type % 10
|
||||
if self.has_geometry_columns:
|
||||
if self.has_spatialite4:
|
||||
cols = """CASE geometry_type % 10
|
||||
WHEN 1 THEN 'POINT'
|
||||
WHEN 2 THEN 'LINESTRING'
|
||||
WHEN 3 THEN 'POLYGON'
|
||||
@ -247,15 +279,27 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
WHEN 3 THEN 'XYZM'
|
||||
ELSE NULL
|
||||
END AS coord_dimension"""
|
||||
else:
|
||||
cols = "g.type,g.coord_dimension"
|
||||
else:
|
||||
cols = "g.type,g.coord_dimension"
|
||||
|
||||
# get geometry info from geometry_columns if exists
|
||||
sql = u"""SELECT m.name, m.type = 'view', g.f_table_name, g.f_geometry_column, %s, g.srid
|
||||
# get geometry info from geometry_columns if exists
|
||||
sql = u"""SELECT m.name, m.type = 'view', g.f_table_name, g.f_geometry_column, %s, g.srid
|
||||
FROM sqlite_master AS m JOIN geometry_columns AS g ON upper(m.name) = upper(g.f_table_name)
|
||||
WHERE m.type in ('table', 'view')
|
||||
ORDER BY m.name, g.f_geometry_column""" % cols
|
||||
|
||||
elif self.is_gpkg:
|
||||
# get info from gpkg_geometry_columns table
|
||||
dim = " 'XY' || CASE z WHEN 1 THEN 'Z' END || CASE m WHEN 1 THEN 'M' END AS coord_dimension "
|
||||
sql = u"""SELECT m.name, m.type = 'view', g.table_name, g.column_name, g.geometry_type_name AS gtype, %s, g.srs_id
|
||||
FROM sqlite_master AS m JOIN gpkg_geometry_columns AS g ON upper(m.name) = upper(g.table_name)
|
||||
WHERE m.type in ('table', 'view')
|
||||
ORDER BY m.name, g.column_name""" % dim
|
||||
|
||||
else:
|
||||
return []
|
||||
|
||||
c = self._get_cursor()
|
||||
self._execute(c, sql)
|
||||
|
||||
items = []
|
||||
@ -277,6 +321,8 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
srid
|
||||
"""
|
||||
|
||||
if self.is_gpkg:
|
||||
return [] # Not implemented
|
||||
if not self.has_geometry_columns:
|
||||
return []
|
||||
if not self.has_raster:
|
||||
@ -375,7 +421,10 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
return ret[0] if ret is not None else None
|
||||
|
||||
def getSpatialRefInfo(self, srid):
|
||||
sql = u"SELECT ref_sys_name FROM spatial_ref_sys WHERE srid = %s" % self.quoteString(srid)
|
||||
if self.is_gpkg:
|
||||
sql = u"SELECT srs_name FROM gpkg_spatial_ref_sys WHERE srs_id = %s" % self.quoteString(srid)
|
||||
else:
|
||||
sql = u"SELECT ref_sys_name FROM spatial_ref_sys WHERE srid = %s" % self.quoteString(srid)
|
||||
c = self._execute(None, sql)
|
||||
ret = c.fetchone()
|
||||
return ret[0] if ret is not None else None
|
||||
@ -428,6 +477,8 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
""" delete table from the database """
|
||||
if self.isRasterTable(table):
|
||||
return False
|
||||
if self.is_gpkg:
|
||||
return False # Not implemented
|
||||
|
||||
c = self._get_cursor()
|
||||
sql = u"DROP TABLE %s" % self.quoteId(table)
|
||||
@ -441,6 +492,8 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
""" delete all rows from table """
|
||||
if self.isRasterTable(table):
|
||||
return False
|
||||
if self.is_gpkg:
|
||||
return False # Not implemented
|
||||
|
||||
sql = u"DELETE FROM %s" % self.quoteId(table)
|
||||
self._execute_and_commit(sql)
|
||||
@ -453,6 +506,8 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
|
||||
if self.isRasterTable(table):
|
||||
return False
|
||||
if self.is_gpkg:
|
||||
return False # Not implemented
|
||||
|
||||
c = self._get_cursor()
|
||||
|
||||
@ -492,6 +547,9 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
return self.renameTable(view, new_name)
|
||||
|
||||
def createSpatialView(self, view, query):
|
||||
if self.is_gpkg:
|
||||
return False # Not implemented
|
||||
|
||||
self.createView(view, query)
|
||||
# get type info about the view
|
||||
sql = u"PRAGMA table_info(%s)" % self.quoteString(view)
|
||||
@ -570,6 +628,9 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
return False # column editing not supported
|
||||
|
||||
def isGeometryColumn(self, table, column):
|
||||
if self.is_gpkg:
|
||||
return False # Not implemented
|
||||
|
||||
c = self._get_cursor()
|
||||
schema, tablename = self.getSchemaTableName(table)
|
||||
sql = u"SELECT count(*) > 0 FROM geometry_columns WHERE upper(f_table_name) = upper(%s) AND upper(f_geometry_column) = upper(%s)" % (
|
||||
@ -578,6 +639,9 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
return c.fetchone()[0] == 't'
|
||||
|
||||
def addGeometryColumn(self, table, geom_column='geometry', geom_type='POINT', srid=-1, dim=2):
|
||||
if self.is_gpkg:
|
||||
return False # Not implemented
|
||||
|
||||
schema, tablename = self.getSchemaTableName(table)
|
||||
sql = u"SELECT AddGeometryColumn(%s, %s, %d, %s, %s)" % (
|
||||
self.quoteString(tablename), self.quoteString(geom_column), srid, self.quoteString(geom_type), dim)
|
||||
@ -614,6 +678,8 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
def createSpatialIndex(self, table, geom_column='geometry'):
|
||||
if self.isRasterTable(table):
|
||||
return False
|
||||
if self.is_gpkg:
|
||||
return False # Not implemented
|
||||
|
||||
schema, tablename = self.getSchemaTableName(table)
|
||||
sql = u"SELECT CreateSpatialIndex(%s, %s)" % (self.quoteString(tablename), self.quoteString(geom_column))
|
||||
@ -622,6 +688,8 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
def deleteSpatialIndex(self, table, geom_column='geometry'):
|
||||
if self.isRasterTable(table):
|
||||
return False
|
||||
if self.is_gpkg:
|
||||
return False # Not implemented
|
||||
|
||||
schema, tablename = self.getSchemaTableName(table)
|
||||
try:
|
||||
@ -635,6 +703,8 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
self.deleteTable(idx_table_name)
|
||||
|
||||
def hasSpatialIndex(self, table, geom_column='geometry'):
|
||||
if self.is_gpkg:
|
||||
return False # Not implemented
|
||||
if not self.has_geometry_columns or self.isRasterTable(table):
|
||||
return False
|
||||
c = self._get_cursor()
|
||||
|
@ -44,5 +44,29 @@ class SLDatabaseInfo(DatabaseInfo):
|
||||
]
|
||||
return HtmlTable(tbl)
|
||||
|
||||
def spatialInfo(self):
|
||||
ret = []
|
||||
|
||||
info = self.db.connector.getSpatialInfo()
|
||||
if info is None:
|
||||
return
|
||||
|
||||
tbl = [
|
||||
(QApplication.translate("DBManagerPlugin", "Library:"), info[0]),
|
||||
("GEOS:", info[1]),
|
||||
("Proj:", info[2])
|
||||
]
|
||||
ret.append(HtmlTable(tbl))
|
||||
|
||||
if self.db.connector.is_gpkg:
|
||||
pass
|
||||
|
||||
elif not self.db.connector.has_geometry_columns:
|
||||
ret.append(HtmlParagraph(
|
||||
QApplication.translate("DBManagerPlugin", "<warning> geometry_columns table doesn't exist!\n"
|
||||
"This table is essential for many GIS applications for enumeration of tables.")))
|
||||
|
||||
return ret
|
||||
|
||||
def privilegesDetails(self):
|
||||
return None
|
||||
|
@ -62,10 +62,6 @@ class SpatiaLiteDBPlugin(DBPlugin):
|
||||
def connectionSettingsKey(self):
|
||||
return '/SpatiaLite/connections'
|
||||
|
||||
@classmethod
|
||||
def connectionSettingsFileKey(self):
|
||||
return "sqlitepath"
|
||||
|
||||
def databasesFactory(self, connection, uri):
|
||||
return SLDatabase(connection, uri)
|
||||
|
||||
@ -85,6 +81,31 @@ class SpatiaLiteDBPlugin(DBPlugin):
|
||||
uri.setDatabase(database)
|
||||
return self.connectToUri(uri)
|
||||
|
||||
@classmethod
|
||||
def addConnection(self, conn_name, uri):
|
||||
settings = QSettings()
|
||||
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 = QFileDialog.getOpenFileName(self, "Choose Sqlite/Spatialite/Geopackage file")
|
||||
if not filename:
|
||||
return
|
||||
finally:
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
|
||||
conn_name = QFileInfo(filepath).fileName()
|
||||
uri = qgis.core.QgsDataSourceURI()
|
||||
uri.setDatabase(filepath)
|
||||
self.addConnection(conn_name, uri)
|
||||
index.internalPointer().emit(SIGNAL('itemChanged'))
|
||||
|
||||
|
||||
|
||||
class SLDatabase(Database):
|
||||
|
||||
@ -153,7 +174,7 @@ class SLDatabase(Database):
|
||||
return True
|
||||
|
||||
def spatialIndexClause(self, src_table, src_column, dest_table, dest_column):
|
||||
return """"%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)
|
||||
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):
|
||||
@ -162,6 +183,29 @@ class SLTable(Table):
|
||||
Table.__init__(self, db, None)
|
||||
self.name, self.isView, self.isSysTable = row
|
||||
|
||||
def ogrUri(self):
|
||||
ogrUri = u"%s|layername=%s" % (self.uri().database(), self.name)
|
||||
return ogrUri
|
||||
|
||||
def mimeUri(self):
|
||||
if self.database().connector.isGpkg():
|
||||
# QGIS has no provider to load Geopackage vectors, let's use OGR
|
||||
return u"vector:ogr:%s:%s" % (self.name, self.ogrUri())
|
||||
return VectorTable.mimeUri(self)
|
||||
|
||||
def toMapLayer(self):
|
||||
from qgis.core import QgsVectorLayer
|
||||
|
||||
if self.database().connector.isGpkg():
|
||||
# QGIS has no provider to load Geopackage vectors, let's use OGR
|
||||
provider = "ogr"
|
||||
uri = self.ogrUri()
|
||||
else:
|
||||
provider = self.database().dbplugin().providerName()
|
||||
uri = self.uri().uri()
|
||||
|
||||
return QgsVectorLayer(uri, self.name, provider)
|
||||
|
||||
def tableFieldsFactory(self, row, table):
|
||||
return SLTableField(row, table)
|
||||
|
||||
@ -231,19 +275,30 @@ class SLRasterTable(SLTable, RasterTable):
|
||||
#from .info_model import SLRasterTableInfo
|
||||
#return SLRasterTableInfo(self)
|
||||
|
||||
def gdalUri(self):
|
||||
uri = self.database().uri()
|
||||
gdalUri = u'RASTERLITE:%s,table=%s' % (uri.database(), self.prefixName)
|
||||
def rasterliteGdalUri(self):
|
||||
gdalUri = u'RASTERLITE:%s,table=%s' % (self.uri().database(), self.prefixName)
|
||||
return gdalUri
|
||||
|
||||
def mimeUri(self):
|
||||
uri = u"raster:gdal:%s:%s" % (self.name, self.gdalUri())
|
||||
if self.database().connector.isGpkg():
|
||||
# QGIS has no provider to load Geopackage rasters, let's use GDAL
|
||||
uri = u"raster:gdal:%s:%s" % (self.name, self.uri().database())
|
||||
else:
|
||||
# QGIS has no provider to load Rasterlite rasters, let's use GDAL
|
||||
uri = u"raster:gdal:%s:%s" % (self.name, self.rasterliteGdalUri())
|
||||
return uri
|
||||
|
||||
def toMapLayer(self):
|
||||
from qgis.core import QgsRasterLayer, QgsContrastEnhancement
|
||||
|
||||
rl = QgsRasterLayer(self.gdalUri(), self.name)
|
||||
if self.database().connector.isGpkg():
|
||||
# QGIS has no provider to load Geopackage rasters, let's use GDAL
|
||||
uri = self.ogrUri()
|
||||
else:
|
||||
# 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
|
||||
|
@ -26,7 +26,7 @@ from PyQt4.QtGui import QWidget, QTreeView, QMenu, QLabel, QFileDialog
|
||||
from qgis.core import QgsMapLayerRegistry, QgsMessageLog
|
||||
from qgis.gui import QgsMessageBar, QgsMessageBarItem
|
||||
|
||||
from .db_model import DBModel
|
||||
from .db_model import DBModel, PluginItem
|
||||
from .db_plugins.plugin import DBPlugin, Schema, Table
|
||||
|
||||
|
||||
@ -94,12 +94,12 @@ class DBTree(QTreeView):
|
||||
return item
|
||||
return None
|
||||
|
||||
def openConnection(self):
|
||||
index = self.selectedIndexes()[0]
|
||||
if index:
|
||||
if index.data() != "PostGIS":
|
||||
filename = QFileDialog.getOpenFileName(self, "Open File")
|
||||
self.model().addConnection(filename, index)
|
||||
def newConnection(self):
|
||||
index = self.currentIndex()
|
||||
if not index.isValid() or not isinstance(index.internalPointer(), PluginItem):
|
||||
return
|
||||
item = self.currentItem()
|
||||
self.mainWindow.invokeCallback(item.addConnectionActionSlot, index)
|
||||
|
||||
def itemChanged(self, index):
|
||||
self.setCurrentIndex(index)
|
||||
@ -131,12 +131,13 @@ class DBTree(QTreeView):
|
||||
menu.addSeparator()
|
||||
menu.addAction(self.tr("Add to canvas"), self.addLayer)
|
||||
|
||||
elif isinstance(item, DBPlugin) and item.database() is not None:
|
||||
menu.addAction(self.tr("Re-connect"), self.reconnect)
|
||||
menu.addAction(self.tr("Delete"), self.delActionSlot)
|
||||
elif isinstance(item, DBPlugin):
|
||||
if item.database() is not None:
|
||||
menu.addAction(self.tr("Re-connect"), self.reconnect)
|
||||
menu.addAction(self.tr("Remove"), self.delete)
|
||||
|
||||
elif not index.parent().data():
|
||||
menu.addAction(self.tr("New Connection..."), self.openConnection)
|
||||
elif not index.parent().isValid() and item.typeName() == "spatialite":
|
||||
menu.addAction(self.tr("New Connection..."), self.newConnection)
|
||||
|
||||
if not menu.isEmpty():
|
||||
menu.exec_(ev.globalPos())
|
||||
@ -144,32 +145,16 @@ class DBTree(QTreeView):
|
||||
menu.deleteLater()
|
||||
|
||||
def rename(self):
|
||||
index = self.currentIndex()
|
||||
item = self.model().getItem(index)
|
||||
item = self.currentItem()
|
||||
if isinstance(item, (Table, Schema)):
|
||||
self.edit(index)
|
||||
|
||||
def delActionSlot(self):
|
||||
db = self.currentDatabase()
|
||||
path = db.uri().database()
|
||||
connkey = db.connection().connectionSettingsKey()
|
||||
self.deletedb(path, connkey)
|
||||
|
||||
index = self.currentIndex().parent()
|
||||
self.setCurrentIndex(index)
|
||||
self.mainWindow.refreshActionSlot()
|
||||
|
||||
def deletedb(self, path, conn):
|
||||
paths = path.split("/")
|
||||
path = paths[-1]
|
||||
s = QSettings()
|
||||
s.beginGroup("/%s/%s" % (conn, path))
|
||||
s.remove("")
|
||||
self.edit(self.currentIndex())
|
||||
|
||||
def delete(self):
|
||||
item = self.currentItem()
|
||||
if isinstance(item, (Table, Schema)):
|
||||
self.mainWindow.invokeCallback(item.database().deleteActionSlot)
|
||||
elif isinstance(item, DBPlugin):
|
||||
self.mainWindow.invokeCallback(item.removeActionSlot)
|
||||
|
||||
def addLayer(self):
|
||||
table = self.currentTable()
|
||||
@ -193,3 +178,4 @@ class DBTree(QTreeView):
|
||||
db = self.currentDatabase()
|
||||
if db is not None:
|
||||
self.mainWindow.invokeCallback(db.reconnectActionSlot)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user