def testLayerDataSourceReset(self): """When adding a layer with the same id to the store make sure the data source is also updated in case the layer validity has changed from False to True""" p = QgsProject() store = p.layerStore() vl1 = createLayer('valid') vl2 = QgsVectorLayer('/not_a_valid_path.shp', 'invalid', 'ogr') self.assertTrue(vl1.isValid()) self.assertFalse(vl2.isValid()) store.addMapLayers([vl1, vl2]) self.assertEqual(store.validCount(), 1) self.assertEqual(len(store.mapLayers()), 2) # Re-add the bad layer store.addMapLayers([vl2]) self.assertEqual(store.validCount(), 1) self.assertEqual(len(store.mapLayers()), 2) doc = QDomDocument() doc.setContent( '<maplayer><provider encoding="UTF-8">ogr</provider><layername>fixed</layername><id>%s</id></maplayer>' % vl2.id()) layer_node = QDomNode(doc.firstChild()) self.assertTrue(vl2.writeXml(layer_node, doc, QgsReadWriteContext())) datasource_node = doc.createElement("datasource") datasource_node.appendChild( doc.createTextNode(os.path.join(TEST_DATA_DIR, 'points.shp'))) layer_node.appendChild(datasource_node) p.readLayer(layer_node) self.assertEqual(store.validCount(), 2) self.assertEqual(len(store.mapLayers()), 2) self.assertEqual(store.mapLayers()[vl2.id()].name(), 'fixed')
def testLayerDataSourceReset(self): """When adding a layer with the same id to the store make sure the data source is also updated in case the layer validity has changed from False to True""" p = QgsProject() store = p.layerStore() vl1 = createLayer('valid') vl2 = QgsVectorLayer('/not_a_valid_path.shp', 'invalid', 'ogr') self.assertTrue(vl1.isValid()) self.assertFalse(vl2.isValid()) store.addMapLayers([vl1, vl2]) self.assertEqual(store.validCount(), 1) self.assertEqual(len(store.mapLayers()), 2) # Re-add the bad layer store.addMapLayers([vl2]) self.assertEqual(store.validCount(), 1) self.assertEqual(len(store.mapLayers()), 2) doc = QDomDocument() doc.setContent('<maplayer><provider encoding="UTF-8">ogr</provider><layername>fixed</layername><id>%s</id></maplayer>' % vl2.id()) layer_node = QDomNode(doc.firstChild()) self.assertTrue(vl2.writeXml(layer_node, doc, QgsReadWriteContext())) datasource_node = doc.createElement("datasource") datasource_node.appendChild(doc.createTextNode(os.path.join(TEST_DATA_DIR, 'points.shp'))) layer_node.appendChild(datasource_node) p.readLayer(layer_node) self.assertEqual(store.validCount(), 2) self.assertEqual(len(store.mapLayers()), 2) self.assertEqual(store.mapLayers()[vl2.id()].name(), 'fixed')
def __init__(self, path): """ Initatlize class variables """ self.file_path = path self.file = None self.new_list = [] self.doc = QDomDocument() self.node = QDomNode()
def _change_data_source(self, layer, datasource, provider_key): """Due to the fact that a project r/w context is not available inside the map layers classes, the original style and subset string restore happens in app, this function replicates app behavior""" options = QgsDataProvider.ProviderOptions() subset_string = '' if not layer.isValid(): try: subset_string = layer.dataProvider().subsetString() except: pass layer.setDataSource(datasource, layer.name(), provider_key, options) if subset_string: layer.setSubsetString(subset_string) self.assertTrue(layer.originalXmlProperties(), layer.name()) context = QgsReadWriteContext() context.setPathResolver(QgsProject.instance().pathResolver()) errorMsg = '' doc = QDomDocument() self.assertTrue(doc.setContent(layer.originalXmlProperties())) layer_node = QDomNode(doc.firstChild()) self.assertTrue(layer.readSymbology(layer_node, errorMsg, context))
class InstanceUUIDExtractor(): """ Class constructor """ def __init__(self, path): """ Initatlize class variables """ self.file_path = path self.file = None self.new_list = [] self.doc = QDomDocument() self.node = QDomNode() def set_file_path(self, path): """ Update the path based on the new file being read :param path: :return: """ self.file_path = path def unset_path(self): """Clear the current document path""" self.file_path = None def set_document(self): """ :return: """ self.file = QFile(self.file_path) if self.file.open(QIODevice.ReadOnly): self.doc.setContent(self.file) self.file.close() def update_document(self): '''Update the current instance by clearing the document in the cache ''' self.doc.clear() self.set_document() def on_file_passed(self): """ Pass the raw file to an xml document object and format the its filename to GeoODK standards :return: """ try: self.set_document() self.read_uuid_element() self.doc.clear() self.file.close() self.rename_file() except: pass def read_uuid_element(self): """ get the uuid element and text from the xml document from the mobile divice """ node = self.doc.elementsByTagName("meta") for i in range(node.count()): node = node.item(i).firstChild().toElement() self.node = node.text() return self.node def document_entities(self, profile): """ Get entities in the document :return: """ self.set_document() node_list = [] nodes = self.doc.elementsByTagName(profile) node = nodes.item(0).childNodes() if node: for j in range(node.count()): node_val = node.item(j) node_list.append(node_val.nodeName()) return node_list def profile_entity_nodes(self, profile): ''' Fetch and return QDomNodeList for entities of a profile :rtype: QDomNodeList ''' self.set_document() nodes = self.doc.elementsByTagName(profile) return nodes.item(0).childNodes() def document_entities_with_data(self, profile, selected_entities): """ Get entities in the dom document matching user selected entities :rtype: OrderedDict """ instance_data = OrderedDict() self.set_document() nodes = self.doc.elementsByTagName(profile) entity_nodes = nodes.item(0).childNodes() for attrs in range(entity_nodes.count()): if entity_nodes.item(attrs).nodeName() in selected_entities: name_entity = entity_nodes.item(attrs).nodeName() attr_nodes = self.doc.elementsByTagName(name_entity) instance_data[attr_nodes] = name_entity return instance_data def attribute_data_from_nodelist(self, args_list): """ process nodelist data before Importing attribute data into db """ repeat_instance_data = OrderedDict() attribute_data = OrderedDict() for attr_nodes, entity in args_list.items(): '''The assuption is that there are repeated entities from mobile sub forms. handle them separately''' if attr_nodes.count() > 1: for i in range(attr_nodes.count()): attrib_node = attr_nodes.at(i).childNodes() attr_list = OrderedDict() for j in range(attrib_node.count()): field_name = attrib_node.at(j).nodeName() field_value = attrib_node.at(j).toElement().text() attr_list[field_name] = field_value repeat_instance_data['{}'.format(i) + entity] = attr_list else: '''Entities must appear onces in the form''' node_list_var = OrderedDict() attr_node = attr_nodes.at(0).childNodes() for j in range(attr_node.count()): field_name = attr_node.at(j).nodeName() field_value = attr_node.at(j).toElement().text() node_list_var[field_name] = field_value attribute_data[entity] = node_list_var return attribute_data, repeat_instance_data def read_attribute_data_from_node(self, node, entity_name): """Read attribute data from a node item""" node_list_var = OrderedDict() attributes = OrderedDict() attr_node = node.at(0).childNodes() for j in range(attr_node.count()): field_name = attr_node.at(j).nodeName() field_value = attr_node.at(j).toElement().text() node_list_var[field_name] = field_value attributes[entity_name] = node_list_var return attributes def str_definition(self, instance=None): """ Check if the instance file has entry social tenure :return: """ if instance: self.set_file_path(instance) self.set_document() attributes = {} nodes = self.doc.elementsByTagName('social_tenure') entity_nodes = nodes.item(0).childNodes() if entity_nodes: for j in range(entity_nodes.count()): node_val = entity_nodes.item(j).toElement() attributes[node_val.nodeName()] = node_val.text().rstrip() return attributes def has_str_captured_in_instance(self, instance): """ Bool if the str inclusion is required based on whether is captured or not :return: """ count = len(self.str_definition(instance)) return True if count > 1 else False def entity_atrributes(self): """ Get collected data from the entity in the document :return: """ pass def uuid_element(self): """ Format the guuid from the file :return: """ return self.node.replace(":", "") def rename_file(self): """ Remane the existing instance file with Guuid from the mobile divice to conform with GeoODk naming convention :return: """ if isinstance(self.file, QFile): dir_n, file_n = os.path.split(self.file_path) os.chdir(dir_n) if not file_n.startswith(UUID): new_file_name = self.uuid_element() + ".xml" isrenamed = self.file.setFileName(new_file_name) os.rename(file_n, new_file_name) self.new_list.append(new_file_name) return isrenamed else: self.new_list.append(self.file.fileName()) self.file.close() else: return def file_list(self): """ check through the list of document to ensure they are complete file path """ complete_file = [] for fi in self.new_list: if os.path.isfile(fi): complete_file.append(fi) else: continue return complete_file def close_document(self): '''Close all the open documents and unset current paths''' self.file_path = None self.doc.clear() self.new_list = None