Skip to content

Commit 03916d5

Browse files
committed
[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
1 parent 7d79a73 commit 03916d5

File tree

7 files changed

+287
-95
lines changed

7 files changed

+287
-95
lines changed

python/plugins/db_manager/db_model.py

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,8 @@ def __init__(self, parent=None):
284284
if self.isImportVectorAvail:
285285
self.connect(self, SIGNAL("importVector"), self.importVector)
286286

287+
self.hasSpatialiteSupport = "spatialite" in supportedDbTypes()
288+
287289
self.rootItem = TreeItem(None, None)
288290
for dbtype in supportedDbTypes():
289291
dbpluginclass = createDbPlugin(dbtype)
@@ -373,13 +375,18 @@ def flags(self, index):
373375
if isinstance(item, TableItem):
374376
flags |= Qt.ItemIsDragEnabled
375377

376-
if self.isImportVectorAvail: # allow to import a vector layer
378+
# vectors/tables can be dropped on connected databases to be imported
379+
if self.isImportVectorAvail:
377380
if isinstance(item, ConnectionItem) and item.populated:
378381
flags |= Qt.ItemIsDropEnabled
379382

380-
if isinstance(item, SchemaItem) or isinstance(item, TableItem):
383+
if isinstance(item, (SchemaItem, TableItem)):
381384
flags |= Qt.ItemIsDropEnabled
382385

386+
# SL/Geopackage db files can be dropped everywhere in the tree
387+
if self.hasSpatialiteSupport:
388+
flags |= Qt.ItemIsDropEnabled
389+
383390
return flags
384391

385392
def headerData(self, section, orientation, role):
@@ -508,8 +515,10 @@ def dropMimeData(self, data, action, row, column, parent):
508515
if action == Qt.IgnoreAction:
509516
return True
510517

511-
if not self.isImportVectorAvail:
512-
return False
518+
# vectors/tables to be imported must be dropped on connected db, schema or table
519+
canImportLayer = self.isImportVectorAvail and parent.isValid() and \
520+
( isinstance(parent.internalPointer(), (SchemaItem, TableItem)) or \
521+
( isinstance(parent.internalPointer(), ConnectionItem) and parent.internalPointer().populated ) )
513522

514523
added = 0
515524

@@ -518,22 +527,42 @@ def dropMimeData(self, data, action, row, column, parent):
518527
filename = u.toLocalFile()
519528
if filename == "":
520529
continue
521-
if qgis.core.QgsRasterLayer.isValidRasterFileName(filename):
522-
layerType = 'raster'
523-
providerKey = 'gdal'
524-
else:
525-
layerType = 'vector'
526-
providerKey = 'ogr'
527-
528-
layerName = QFileInfo(filename).completeBaseName()
529530

530-
if self.importLayer(layerType, providerKey, layerName, filename, parent):
531-
added += 1
531+
if self.hasSpatialiteSupport:
532+
from .db_plugins.spatialite.connector import SpatiaLiteDBConnector
533+
534+
if SpatiaLiteDBConnector.isValidDatabase(filename):
535+
# retrieve the SL plugin tree item using its path
536+
index = self._rPath2Index(["spatialite"])
537+
if not index.isValid():
538+
continue
539+
item = index.internalPointer()
540+
541+
conn_name = QFileInfo(filename).fileName()
542+
uri = qgis.core.QgsDataSourceURI()
543+
uri.setDatabase(filename)
544+
item.getItemData().addConnection(conn_name, uri)
545+
item.emit(SIGNAL('itemChanged'), item)
546+
added += 1
547+
continue
548+
549+
if canImportLayer:
550+
if qgis.core.QgsRasterLayer.isValidRasterFileName(filename):
551+
layerType = 'raster'
552+
providerKey = 'gdal'
553+
else:
554+
layerType = 'vector'
555+
providerKey = 'ogr'
556+
557+
layerName = QFileInfo(filename).completeBaseName()
558+
if self.importLayer(layerType, providerKey, layerName, filename, parent):
559+
added += 1
532560

533561
if data.hasFormat(self.QGIS_URI_MIME):
534562
for uri in qgis.core.QgsMimeDataUtils.decodeUriList(data):
535-
if self.importLayer(uri.layerType, uri.providerKey, uri.name, uri.uri, parent):
536-
added += 1
563+
if canImportLayer:
564+
if self.importLayer(uri.layerType, uri.providerKey, uri.name, uri.uri, parent):
565+
added += 1
537566

538567
return added > 0
539568

python/plugins/db_manager/db_plugins/plugin.py

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ def info(self):
9797

9898
return DatabaseInfo(None)
9999

100+
def connect(self, parent=None):
101+
raise NotImplemented
102+
100103
def connectToUri(self, uri):
101104
self.db = self.databasesFactory(self, uri)
102105
if self.db:
@@ -111,6 +114,17 @@ def reconnect(self):
111114
return self.connectToUri(uri)
112115
return self.connect(self.parent())
113116

117+
def remove(self):
118+
settings = QSettings()
119+
settings.beginGroup(u"/%s/%s" % (self.connectionSettingsKey(), self.connectionName()))
120+
settings.remove("")
121+
self.emit(SIGNAL('deleted'))
122+
return True
123+
124+
@classmethod
125+
def addConnection(self, conn_name, uri):
126+
raise NotImplemented
127+
114128
@classmethod
115129
def icon(self):
116130
return None
@@ -135,11 +149,6 @@ def connectionSettingsKey(self):
135149
# return the key used to store the connections in settings
136150
pass
137151

138-
@classmethod
139-
def connectionSettingsFileKey(self):
140-
# return the filekey for the settings
141-
pass
142-
143152
@classmethod
144153
def connections(self):
145154
# get the list of connections
@@ -154,6 +163,24 @@ def connections(self):
154163
def databasesFactory(self, connection, uri):
155164
return None
156165

166+
@classmethod
167+
def addConnectionActionSlot(self, item, action, parent):
168+
raise NotImplemented
169+
170+
def removeActionSlot(self, item, action, parent):
171+
QApplication.restoreOverrideCursor()
172+
try:
173+
res = QMessageBox.question(parent, QApplication.translate("DBManagerPlugin", "hey!"),
174+
QApplication.translate("DBManagerPlugin",
175+
"Really remove connection to %s?") % item.connectionName(),
176+
QMessageBox.Yes | QMessageBox.No)
177+
if res != QMessageBox.Yes:
178+
return
179+
finally:
180+
QApplication.setOverrideCursor(Qt.WaitCursor)
181+
182+
item.remove()
183+
157184

158185
class DbItemObject(QObject):
159186

@@ -207,6 +234,13 @@ def uri(self):
207234
def publicUri(self):
208235
return self.connector.publicUri()
209236

237+
def delete(self):
238+
self.aboutToChange()
239+
ret = self.connection().remove()
240+
if ret is not False:
241+
self.emit(SIGNAL('deleted'))
242+
return ret
243+
210244
def info(self):
211245
from .info_model import DatabaseInfo
212246

@@ -636,9 +670,6 @@ def uri(self):
636670

637671
def mimeUri(self):
638672
layerType = "raster" if self.type == Table.RasterType else "vector"
639-
if self.database().dbplugin().typeName() == "spatialite" and self.database().connector.isgpkg():
640-
url = unicode(self.database().connector._connectionInfo() + "|layername=" + self.name)
641-
return u"%s:%s:%s:%s" % (layerType, "ogr", self.name, url)
642673
return u"%s:%s:%s:%s" % (layerType, self.database().dbplugin().providerName(), self.name, self.uri().uri())
643674

644675
def toMapLayer(self):

python/plugins/db_manager/db_plugins/postgis/plugin.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,6 @@ def providerName(self):
6464
def connectionSettingsKey(self):
6565
return '/PostgreSQL/connections'
6666

67-
@classmethod
68-
def connectionSettingsFileKey(self):
69-
return "database"
70-
7167
def databasesFactory(self, connection, uri):
7268
return PGDatabase(connection, uri)
7369

@@ -284,6 +280,7 @@ def gdalUri(self):
284280
return gdalUri
285281

286282
def mimeUri(self):
283+
# QGIS has no provider for PGRasters, let's use GDAL
287284
uri = u"raster:gdal:%s:%s" % (self.name, re.sub(":", "\:", self.gdalUri()))
288285
return uri
289286

0 commit comments

Comments
 (0)