2024-11-29 15:38:02 +01:00

227 lines
6.2 KiB
Python

"""
/***************************************************************************
Name : DB Manager plugin for virtual layers
Date : December 2015
copyright : (C) 2015 by Hugo Mercier
email : hugo dot mercier at oslandia dot 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. *
* *
***************************************************************************/
"""
# this will disable the dbplugin if the connector raise an ImportError
from .connector import VLayerConnector
from qgis.PyQt.QtCore import QCoreApplication
from qgis.PyQt.QtGui import QIcon
from qgis.core import (
QgsApplication,
QgsVectorLayer,
QgsProject,
QgsVirtualLayerDefinition,
)
from ..plugin import DBPlugin, Database, Table, VectorTable, TableField
def classFactory():
return VLayerDBPlugin
class VLayerDBPlugin(DBPlugin):
@classmethod
def icon(self):
return QgsApplication.getThemeIcon("/mIconVirtualLayer.svg")
def connectionIcon(self):
return QgsApplication.getThemeIcon("/providerQgis.svg")
@classmethod
def typeName(self):
return "vlayers"
@classmethod
def typeNameString(self):
return QCoreApplication.translate("db_manager", "Virtual Layers")
@classmethod
def providerName(self):
return "virtual"
@classmethod
def connectionSettingsKey(self):
return "vlayers"
@classmethod
def connections(self):
return [
VLayerDBPlugin(QCoreApplication.translate("db_manager", "Project layers"))
]
def databasesFactory(self, connection, uri):
return FakeDatabase(connection, uri)
def database(self):
return self.db
# def info( self ):
def connect(self, parent=None):
self.connectToUri("qgis")
return True
class FakeDatabase(Database):
def __init__(self, connection, uri):
Database.__init__(self, connection, uri)
def connectorsFactory(self, uri):
return VLayerConnector(uri)
def dataTablesFactory(self, row, db, schema=None):
return LTable(row, db, schema)
def vectorTablesFactory(self, row, db, schema=None):
return LVectorTable(row, db, schema)
def rasterTablesFactory(self, row, db, schema=None):
return None
def info(self):
from .info_model import LDatabaseInfo
return LDatabaseInfo(self)
def sqlResultModel(self, sql, parent):
from .data_model import LSqlResultModel
return LSqlResultModel(self, sql, parent)
def sqlResultModelAsync(self, sql, parent):
from .data_model import LSqlResultModelAsync
return LSqlResultModelAsync(self, sql, parent)
def toSqlLayer(
self,
sql,
geomCol,
uniqueCol,
layerName="QueryLayer",
layerType=None,
avoidSelectById=False,
_filter="",
):
df = QgsVirtualLayerDefinition()
df.setQuery(sql)
if uniqueCol is not None:
uniqueCol = uniqueCol.strip('"').replace('""', '"')
df.setUid(uniqueCol)
if geomCol is not None:
df.setGeometryField(geomCol)
vl = QgsVectorLayer(df.toString(), layerName, "virtual")
if _filter:
vl.setSubsetString(_filter)
return vl
def registerDatabaseActions(self, mainWindow):
return
def runAction(self, action):
return
def uniqueIdFunction(self):
return None
def explicitSpatialIndex(self):
return True
def spatialIndexClause(self, src_table, src_column, dest_table, dest_column):
return '"{}"._search_frame_ = "{}"."{}"'.format(
src_table, dest_table, dest_column
)
def supportsComment(self):
return False
class LTable(Table):
def __init__(self, row, db, schema=None):
Table.__init__(self, db, None)
self.name, self.isView, self.isSysTable = row
def tableFieldsFactory(self, row, table):
return LTableField(row, table)
def tableDataModel(self, parent):
from .data_model import LTableDataModel
return LTableDataModel(self, parent)
def canBeAddedToCanvas(self):
return False
class LVectorTable(LTable, VectorTable):
def __init__(self, row, db, schema=None):
LTable.__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):
return True
def createSpatialIndex(self, geom_column=None):
return
def deleteSpatialIndex(self, geom_column=None):
return
def refreshTableEstimatedExtent(self):
self.extent = self.database().connector.getTableExtent(
("id", self.geomTableName), None
)
def runAction(self, action):
return
def toMapLayer(self, geometryType=None, crs=None):
return QgsProject.instance().mapLayer(self.geomTableName)
class LTableField(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