plugin.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. """
  2. /***************************************************************************
  3. Name : DB Manager plugin for virtual layers
  4. Date : December 2015
  5. copyright : (C) 2015 by Hugo Mercier
  6. email : hugo dot mercier at oslandia dot com
  7. ***************************************************************************/
  8. /***************************************************************************
  9. * *
  10. * This program is free software; you can redistribute it and/or modify *
  11. * it under the terms of the GNU General Public License as published by *
  12. * the Free Software Foundation; either version 2 of the License, or *
  13. * (at your option) any later version. *
  14. * *
  15. ***************************************************************************/
  16. """
  17. # this will disable the dbplugin if the connector raise an ImportError
  18. from .connector import VLayerConnector
  19. from qgis.PyQt.QtCore import QCoreApplication
  20. from qgis.PyQt.QtGui import QIcon
  21. from qgis.core import QgsApplication, QgsVectorLayer, QgsProject, QgsVirtualLayerDefinition
  22. from ..plugin import DBPlugin, Database, Table, VectorTable, TableField
  23. def classFactory():
  24. return VLayerDBPlugin
  25. class VLayerDBPlugin(DBPlugin):
  26. @classmethod
  27. def icon(self):
  28. return QgsApplication.getThemeIcon("/mIconVirtualLayer.svg")
  29. def connectionIcon(self):
  30. return QgsApplication.getThemeIcon("/providerQgis.svg")
  31. @classmethod
  32. def typeName(self):
  33. return 'vlayers'
  34. @classmethod
  35. def typeNameString(self):
  36. return QCoreApplication.translate('db_manager', 'Virtual Layers')
  37. @classmethod
  38. def providerName(self):
  39. return 'virtual'
  40. @classmethod
  41. def connectionSettingsKey(self):
  42. return 'vlayers'
  43. @classmethod
  44. def connections(self):
  45. return [VLayerDBPlugin(QCoreApplication.translate('db_manager', 'Project layers'))]
  46. def databasesFactory(self, connection, uri):
  47. return FakeDatabase(connection, uri)
  48. def database(self):
  49. return self.db
  50. # def info( self ):
  51. def connect(self, parent=None):
  52. self.connectToUri("qgis")
  53. return True
  54. class FakeDatabase(Database):
  55. def __init__(self, connection, uri):
  56. Database.__init__(self, connection, uri)
  57. def connectorsFactory(self, uri):
  58. return VLayerConnector(uri)
  59. def dataTablesFactory(self, row, db, schema=None):
  60. return LTable(row, db, schema)
  61. def vectorTablesFactory(self, row, db, schema=None):
  62. return LVectorTable(row, db, schema)
  63. def rasterTablesFactory(self, row, db, schema=None):
  64. return None
  65. def info(self):
  66. from .info_model import LDatabaseInfo
  67. return LDatabaseInfo(self)
  68. def sqlResultModel(self, sql, parent):
  69. from .data_model import LSqlResultModel
  70. return LSqlResultModel(self, sql, parent)
  71. def sqlResultModelAsync(self, sql, parent):
  72. from .data_model import LSqlResultModelAsync
  73. return LSqlResultModelAsync(self, sql, parent)
  74. def toSqlLayer(self, sql, geomCol, uniqueCol, layerName="QueryLayer", layerType=None, avoidSelectById=False, _filter=""):
  75. df = QgsVirtualLayerDefinition()
  76. df.setQuery(sql)
  77. if uniqueCol is not None:
  78. uniqueCol = uniqueCol.strip('"').replace('""', '"')
  79. df.setUid(uniqueCol)
  80. if geomCol is not None:
  81. df.setGeometryField(geomCol)
  82. vl = QgsVectorLayer(df.toString(), layerName, "virtual")
  83. if _filter:
  84. vl.setSubsetString(_filter)
  85. return vl
  86. def registerDatabaseActions(self, mainWindow):
  87. return
  88. def runAction(self, action):
  89. return
  90. def uniqueIdFunction(self):
  91. return None
  92. def explicitSpatialIndex(self):
  93. return True
  94. def spatialIndexClause(self, src_table, src_column, dest_table, dest_column):
  95. return '"%s"._search_frame_ = "%s"."%s"' % (src_table, dest_table, dest_column)
  96. def supportsComment(self):
  97. return False
  98. class LTable(Table):
  99. def __init__(self, row, db, schema=None):
  100. Table.__init__(self, db, None)
  101. self.name, self.isView, self.isSysTable = row
  102. def tableFieldsFactory(self, row, table):
  103. return LTableField(row, table)
  104. def tableDataModel(self, parent):
  105. from .data_model import LTableDataModel
  106. return LTableDataModel(self, parent)
  107. def canBeAddedToCanvas(self):
  108. return False
  109. class LVectorTable(LTable, VectorTable):
  110. def __init__(self, row, db, schema=None):
  111. LTable.__init__(self, row[:-5], db, schema)
  112. VectorTable.__init__(self, db, schema)
  113. # SpatiaLite does case-insensitive checks for table names, but the
  114. # SL provider didn't do the same in QGIS < 1.9, so self.geomTableName
  115. # stores the table name like stored in the geometry_columns table
  116. self.geomTableName, self.geomColumn, self.geomType, self.geomDim, self.srid = row[
  117. -5:]
  118. def uri(self):
  119. uri = self.database().uri()
  120. uri.setDataSource('', self.geomTableName, self.geomColumn)
  121. return uri
  122. def hasSpatialIndex(self, geom_column=None):
  123. return True
  124. def createSpatialIndex(self, geom_column=None):
  125. return
  126. def deleteSpatialIndex(self, geom_column=None):
  127. return
  128. def refreshTableEstimatedExtent(self):
  129. self.extent = self.database().connector.getTableExtent(
  130. ("id", self.geomTableName), None)
  131. def runAction(self, action):
  132. return
  133. def toMapLayer(self, geometryType=None, crs=None):
  134. return QgsProject.instance().mapLayer(self.geomTableName)
  135. class LTableField(TableField):
  136. def __init__(self, row, table):
  137. TableField.__init__(self, table)
  138. self.num, self.name, self.dataType, self.notNull, self.default, self.primaryKey = row
  139. self.hasDefault = self.default