def __init__(self, dataSourceName="", category="", referenced_table_name=''): self._dataSourceName = dataSourceName self._dataSourceCategory = category self.referenced_table_name = referenced_table_name self._dataFieldmappings = ReverseDict() self._spatialFieldsConfig = None
def pg_layerNamesIDMapping(): ''' Returns a dictionary containing the original table names and corresponding layer IDs in the QGIS legend for only those layers from a postgres database. ''' mapping = ReverseDict() layers = QgsProject.instance().mapLayers() for name, layer in layers.items(): if hasattr(layer, 'dataProvider'): if layer.dataProvider().name() == 'postgres': layerConnStr = layer.dataProvider().dataSourceUri() dataSourceURI = QgsDataSourceUri(layerConnStr) mapping[dataSourceURI.table()] = layer.id() return mapping
def lookup_values(lookup_entity): """ Fetches the lookup values and stores them in a reversible collection i.e. you can get the lookup values from the primary keys or the primary keys from the lookup values. :param lookup_entity: Entity for the lookup values :type lookup_entity: ValueList :return: A bi-directional collection. :rtype: ReverseDict """ lookup_items = ReverseDict() # Add all lookup values in the value list table vl_cls = entity_model(lookup_entity) if not vl_cls is None: vl_obj = vl_cls() res = vl_obj.queryObject().all() for r in res: pk_id = r.id lk_value = r.value lookup_items[pk_id] = lk_value return lookup_items
def clear(self): """ Clears the data source name and removes all data field mappings. """ self._dataSourceName = "" self._dataFieldmappings = ReverseDict()
class ComposerDataSource: """ Container for data source settings. """ def __init__(self, dataSourceName="", category="", referenced_table_name=''): self._dataSourceName = dataSourceName self._dataSourceCategory = category self.referenced_table_name = referenced_table_name self._dataFieldmappings = ReverseDict() self._spatialFieldsConfig = None def setName(self, dataSourceName): """ Sets the data source name. """ self._dataSourceName = dataSourceName def name(self): """ Returns the data source name. """ return self._dataSourceName def category(self): """ Returns the category of the data source. """ return self._dataSourceCategory def setCategory(self, category): """ Set the category of the data source. """ self._dataSourceCategory = category def setSpatialFieldsConfig(self, spFieldsConfig): """ Set the spatial fields configuration object """ self._spatialFieldsConfig = spFieldsConfig def addDataFieldMapping(self, dataField, composerItemId): """ Add the name of the data field. """ self._dataFieldmappings[dataField] = composerItemId def dataFieldMappings(self): """ Returns the collection of data field mappings. """ return self._dataFieldmappings def clear(self): """ Clears the data source name and removes all data field mappings. """ self._dataSourceName = "" self._dataFieldmappings = ReverseDict() def dataFieldName(self, composerItemId): """ Returns the data field name corresponding to the composer item id. """ if composerItemId in self._dataFieldmappings.reverse: return self._dataFieldmappings.reverse[composerItemId] else: return None def composerItemId(self, dataField): """ Returns the composer item unique identifier corresponding to the given field. """ if dataField in self._dataFieldmappings: return self._dataFieldmappings[dataField] else: return None def sqlSelectStatement(self): """ Returns a sql select statement based on the data source and fields specified,as well as the spatial fields. """ dataFields = list(self._dataFieldmappings.keys()) #Get spatial fields and embed into the dataFields list if self._spatialFieldsConfig != None: spatialFieldsCollection = list( self._spatialFieldsConfig.spatialFieldsMapping().values()) for spfEntry in spatialFieldsCollection: spFields = [spm.spatialField() for spm in spfEntry] labelFields = [spm.labelField() for spm in spfEntry] dataFields.extend(spFields) dataFields.extend(labelFields) if len(dataFields) == 0: return "" #Ensure you only have unique fields dataFieldsSet = set(dataFields) dtFieldsStr = ",".join(dataFieldsSet) return "SELECT {0} FROM {1}".format(dtFieldsStr, self._dataSourceName) @staticmethod def create(domDocument): """ Create an instance of the ComposerDataSource object from a DOM document. Returns None if the domDocument is invalid. """ dataSourceElem = domDocument.documentElement().firstChildElement( "DataSource") if dataSourceElem is None: return None dataSourceName = dataSourceElem.attribute("name") dataSourceCategory = dataSourceElem.attribute("category") referenced_table_name = dataSourceElem.attribute('referencedTable', '') composerDS = ComposerDataSource(dataSourceName, dataSourceCategory, referenced_table_name) #Get data fields dataFieldList = dataSourceElem.elementsByTagName("DataField") numItems = dataFieldList.length() for i in range(numItems): dataFieldElement = dataFieldList.item(i).toElement() dataFieldName = dataFieldElement.attribute("name") composerItemId = dataFieldElement.attribute("itemid") composerDS.addDataFieldMapping(dataFieldName, composerItemId) return composerDS @staticmethod def domElement(composerWrapper, domDocument): """ Helper method that creates a data source DOM element from a composer wrapper instance. """ from stdm.ui.composer import ComposerFieldSelector dataSourceElement = domDocument.createElement("DataSource") dataSourceElement.setAttribute("name", composerWrapper.selectedDataSource()) dataSourceElement.setAttribute( "category", composerWrapper.selectedDataSourceCategory()) dataSourceElement.setAttribute( "referencedTable", composerWrapper.selected_referenced_table()) #Get the configured field names for uuid, fieldWidget in composerWrapper.widgetMappings().items(): """ Assert whether the item exists in the composition since the 'itemRemoved' signal cannot be used to delete items from the collection as it only returns a QObject instead of a QgsComposerItem subclass. """ composerItem = composerWrapper.composition().getComposerItemByUuid( uuid) if composerItem != None: if isinstance(fieldWidget, ComposerFieldSelector): fieldName = fieldWidget.fieldName() fieldElement = domDocument.createElement("DataField") fieldElement.setAttribute("itemid", uuid) fieldElement.setAttribute("name", fieldName) dataSourceElement.appendChild(fieldElement) return dataSourceElement
class ComposerDataSource: """ Container for data source settings. """ def __init__(self, dataSourceName="", category: str = "", referenced_table_name: str = ''): self._dataSourceName = dataSourceName self._dataSourceCategory = category self.referenced_table_name = referenced_table_name self._dataFieldmappings = ReverseDict() self._spatialFieldsConfig = None def setName(self, dataSourceName): """ Sets the data source name. """ self._dataSourceName = dataSourceName def name(self): """ Returns the data source name. """ return self._dataSourceName def category(self) -> str: """ Returns the category of the data source. """ return self._dataSourceCategory def setCategory(self, category: str): """ Set the category of the data source. """ self._dataSourceCategory = category def setSpatialFieldsConfig(self, spFieldsConfig): """ Set the spatial fields configuration object """ self._spatialFieldsConfig = spFieldsConfig def addDataFieldMapping(self, dataField, composerItemId): """ Add the name of the data field. """ self._dataFieldmappings[dataField] = composerItemId def dataFieldMappings(self): """ Returns the collection of data field mappings. """ return self._dataFieldmappings def clear(self): """ Clears the data source name and removes all data field mappings. """ self._dataSourceName = "" self._dataFieldmappings = ReverseDict() def dataFieldName(self, composerItemId): """ Returns the data field name corresponding to the composer item id. """ if composerItemId in self._dataFieldmappings.reverse: return self._dataFieldmappings.reverse[composerItemId] else: return None def composerItemId(self, dataField): """ Returns the composer item unique identifier corresponding to the given field. """ if dataField in self._dataFieldmappings: return self._dataFieldmappings[dataField] else: return None def sqlSelectStatement(self): """ Returns a sql select statement based on the data source and fields specified,as well as the spatial fields. """ dataFields = list(self._dataFieldmappings.keys()) # Get spatial fields and embed into the dataFields list if self._spatialFieldsConfig is not None: spatialFieldsCollection = list( self._spatialFieldsConfig.spatialFieldsMapping().values()) for spfEntry in spatialFieldsCollection: spFields = [spm.spatialField() for spm in spfEntry] labelFields = [spm.labelField() for spm in spfEntry] dataFields.extend(spFields) dataFields.extend(labelFields) if len(dataFields) == 0: return "" # Ensure you only have unique fields dataFieldsSet = set(dataFields) dtFieldsStr = ",".join(dataFieldsSet) return "SELECT {0} FROM {1}".format(dtFieldsStr, self._dataSourceName) @staticmethod def from_layout(layout: QgsLayout) -> 'ComposerDataSource': """ Creates a ComposerDataSource using properties from the specified layout """ data_source_name = LayoutUtils.get_stdm_data_source_for_layout(layout) data_source_category = LayoutUtils.get_stdm_data_category_for_layout( layout) referenced_table_name = LayoutUtils.get_stdm_referenced_table_for_layout( layout) return ComposerDataSource(data_source_name, data_source_category, referenced_table_name) @staticmethod def create(document: QDomDocument): """ Create an instance of the ComposerDataSource object from a DOM document. Returns None if the domDocument is invalid. """ custom_properties = QgsObjectCustomProperties() custom_properties.readXml(document.documentElement()) data_source_name = custom_properties.value( LayoutUtils.DATA_SOURCE_PROPERTY) data_category = custom_properties.value( LayoutUtils.DATA_CATEGORY_PROPERTY) referenced_table_name = custom_properties.value( LayoutUtils.REFERENCED_TABLE_PROPERTY) if not data_source_name: return None data_source = ComposerDataSource(data_source_name, data_category, referenced_table_name) return data_source @staticmethod def from_template_file( template_file: str) -> 'Optional[ComposerDataSource]': """ Creates a ComposerDataSource object from the specified template file. If the file cannot be opened due to file permissions or if it does not exist then the function will return None. :param template_file: Absolute template file path. :type template_file: str :return: Composer data source object. :rtype: ComposerDataSource """ t_file = QFile(template_file) # Check if the file exists if not t_file.exists(): return None # Check if the file can be opened if not t_file.open(QIODevice.ReadOnly): return None template_doc = QDomDocument() # Populate dom document if template_doc.setContent(t_file): return ComposerDataSource.create(template_doc) return None