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 formatResponse(self) -> (QByteArray, str): doc = QDomDocument() root = doc.createElement('ServiceExceptionReport') root.setAttribute('version', self.version) root.setAttribute('xmlns', 'http://www.opengis.net/ogc') doc.appendChild(root) elem = doc.createElement('ServiceException') elem.setAttribute('code', self.code) elem.appendChild(doc.createTextNode(self.message)) root.appendChild(elem) if self.locator: elem.setAttribute('locator', self.locator) return doc.toByteArray(), 'text/xml; charset=utf-8'
def testClone(self): myPath = os.path.join(unitTestDataPath('raster'), 'band1_float32_noct_epsg4326.tif') myFileInfo = QFileInfo(myPath) myBaseName = myFileInfo.baseName() layer = QgsRasterLayer(myPath, myBaseName) renderer = layer.renderer().clone() renderer.setOpacity(33.3) layer.setRenderer(renderer) # clone layer clone = layer.clone() # generate xml from layer layer_doc = QDomDocument("doc") layer_elem = layer_doc.createElement("maplayer") layer.writeLayerXml(layer_elem, layer_doc, QgsReadWriteContext()) # generate xml from clone clone_doc = QDomDocument("doc") clone_elem = clone_doc.createElement("maplayer") clone.writeLayerXml(clone_elem, clone_doc, QgsReadWriteContext()) # replace id within xml of clone clone_id_elem = clone_elem.firstChildElement("id") clone_id_elem_patch = clone_doc.createElement("id") clone_id_elem_patch_value = clone_doc.createTextNode(layer.id()) clone_id_elem_patch.appendChild(clone_id_elem_patch_value) clone_elem.replaceChild(clone_id_elem_patch, clone_id_elem) # update doc clone_doc.appendChild(clone_elem) layer_doc.appendChild(layer_elem) # compare xml documents self.assertEqual(layer_doc.toString(), clone_doc.toString())
def testClone(self): myPath = os.path.join(unitTestDataPath('raster'), 'band1_float32_noct_epsg4326.tif') myFileInfo = QFileInfo(myPath) myBaseName = myFileInfo.baseName() layer = QgsRasterLayer(myPath, myBaseName) renderer = layer.renderer().clone() renderer.setOpacity(33.3) layer.setRenderer(renderer) # clone layer clone = layer.clone() # generate xml from layer layer_doc = QDomDocument("doc") layer_elem = layer_doc.createElement("maplayer") layer.writeLayerXml(layer_elem, layer_doc, QgsReadWriteContext()) # generate xml from clone clone_doc = QDomDocument("doc") clone_elem = clone_doc.createElement("maplayer") clone.writeLayerXml(clone_elem, clone_doc, QgsReadWriteContext()) # replace id within xml of clone clone_id_elem = clone_elem.firstChildElement("id") clone_id_elem_patch = clone_doc.createElement("id") clone_id_elem_patch_value = clone_doc.createTextNode(layer.id()) clone_id_elem_patch.appendChild(clone_id_elem_patch_value) clone_elem.replaceChild(clone_id_elem_patch, clone_id_elem) # update doc clone_doc.appendChild(clone_elem) layer_doc.appendChild(layer_elem) # compare xml documents self.assertEqual(layer_doc.toString(), clone_doc.toString())
def createAndParseSld(qgisLayerItem): document = QDomDocument() header = document.createProcessingInstruction( 'xml', 'version=\'1.0\' encoding=\'UTF-8\'') document.appendChild(header) root = document.createElementNS('http://www.opengis.net/sld', 'StyledLayerDescriptor') root.setAttribute('version', '1.0.0') root.setAttribute('xmlns:ogc', 'http://www.opengis.net/ogc') root.setAttribute('xmlns:sld', 'http://www.opengis.net/sld') root.setAttribute('xmlns:gml', 'http://www.opengis.net/gml') document.appendChild(root) namedLayerNode = document.createElement('sld:NamedLayer') root.appendChild(namedLayerNode) qgisLayerItem.layer.writeSld(namedLayerNode, document, '') nameNode = namedLayerNode.firstChildElement('se:Name') oldNameText = nameNode.firstChild() newname = qgisLayerItem.parentShogunLayer.source['layerNames'] newNameText = document.createTextNode(newname) nameNode.appendChild(newNameText) nameNode.removeChild(oldNameText) userStyleNode = namedLayerNode.firstChildElement('UserStyle') userStyleNameNode = userStyleNode.firstChildElement('se:Name') userStyleNameText = userStyleNameNode.firstChild() userStyleNameNode.removeChild(userStyleNameText) userStyleNameNode.appendChild( document.createTextNode(qgisLayerItem.stylename)) titleNode = document.createElement('sld:Title') title = document.createTextNode('A QGIS-Style for ' + qgisLayerItem.layer.name()) titleNode.appendChild(title) userStyleNode.appendChild(titleNode) defaultNode = document.createElement('sld:IsDefault') defaultNode.appendChild(document.createTextNode('1')) userStyleNode.appendChild(defaultNode) featureTypeStyleNode = userStyleNode.firstChildElement( 'se:FeatureTypeStyle') featureTypeStyleNameNode = document.createElement('sld:Name') featureTypeStyleNameNode.appendChild(document.createTextNode('name')) featureTypeStyleNode.appendChild(featureTypeStyleNameNode) rules = featureTypeStyleNode.elementsByTagName('se:Rule') for x in range(rules.length()): rule = rules.at(x) rule.removeChild(rule.firstChildElement('se:Description')) # Check if custom icons are used in symbology and replace the text: # search if tag 'se:OnlineResource' is in the sld document listOfGraphics = rule.toElement().elementsByTagName('se:OnlineResource') if not listOfGraphics.isEmpty(): for x in range(listOfGraphics.length()): graphicNode = listOfGraphics.at(x) currentIcon = graphicNode.attributes().namedItem( 'xlink:href').nodeValue() iconUrl = qgisLayerItem.ressource.prepareIconForUpload(currentIcon) graphicNode.toElement().setAttribute('xlink:href', iconUrl) graphicNode.toElement().setAttribute( 'xmlns:xlink', 'http://www.w3.org/1999/xlink') sld = document.toString() # in qgis3 layer.writeSld() also incluedes labeling in the output sld, # whereas in qgis2 we have to do this manually by using this module's function # getLabelingAsSld ## TODO: The automatic sld labeling from QGIS 3 produces an extra rule for # every labeling style, thus leading to a less beautiful viewe in the # shogun2-webapp styler - is this a problem? if qgisLayerItem.layer.labelsEnabled() and PYTHON_VERSION < 3: labelSld = getLabelingAsSld(qgisLayerItem.layer) sld = sld.replace('</se:Rule>', labelSld + '</se:Rule>') sld = sld.replace('ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"', 'ogc:Filter') # the following fixes weird problems with the sld compability with the # shogun webapp sld = sld.replace('<ogc:And>', '') sld = sld.replace('</ogc:And>', '') sld = sld.replace('<se:Name> ', '<se:Name>') sld = sld.replace(' </se:Name>', '</se:Name>') sld = sld.replace('StyledLayerDescriptor', 'sld:StyledLayerDescriptor') sld = sld.replace('UserStyle', 'sld:UserStyle') sld = sld.replace('se:', 'sld:') sld = sld.replace('SvgParameter', 'CssParameter') sld = sld.replace('\n', '') sld = sld.replace('\t', '') return sld
class XFORMDocument: """ class to generate an Xml file that is needed for data collection using mobile device. The class creates the file and QDOM sections for holding data once the file is called """ def __init__(self, fname): """ Initalize the class so that we have a new file everytime document generation method is called """ self.dt_text = QDate() self.file_handler = FilePaths() self.doc = QDomDocument() self.form = None self.fname = fname self.doc_with_entities = [] self.supports_doc = self.document() def document(self): """ use the globally defined Document name for supporting document :return: """ global DOCUMENT return DOCUMENT def form_name(self): """ Format the name for the new file to be created. We need to ensure it is .xml file. :return: """ if len(self.fname.split(".")) > 1: return self.fname else: return self.fname + "{}".format(DOCEXTENSION) def set_form_name(self, local_name): """ Allow the user to update the name of the file. This method will be called to return a new file with the local_name given :param local_name: string :return: QFile """ self.fname = local_name + "{}".format(DOCEXTENSION) self.form.setFileName(self.fname) self.create_form() return self.fname def create_form(self): """ Create an XML file that will be our XFORM Document for reading and writing We want a new file when everytime we are creating XForm type: file :return: file """ self.form = QFile(os.path.join(FORM_HOME, self.form_name())) if not QFileInfo(self.form).suffix() == DOCEXTENSION: self.form_name() if not self.form.open(QIODevice.ReadWrite | QIODevice.Truncate | QIODevice.Text): return self.form.OpenError def create_node(self, name): """ Create a XML element node :param name: :return: node :rtype: QelementNode """ return self.doc.createElement(name) def create_text_node(self, text): """ Create an XML text node :param text: :return: """ return self.doc.createTextNode(text) def create_node_attribute(self, node, key, value): """ Create an attribute and attach it to the node :param node: Qnode :param key: Qnode name :param value: Qnode value :return: QNode """ return node.setAttribute(key, value) def xform_document(self): """ :return: QDomDocument """ return self.doc def write_to_form(self): """ Write data to xml file from the base calling class to an output file created earlier :return: """ if isinstance(self.form, QFile): self.form.write(self.doc.toByteArray()) self.form.close() self.doc.clear() else: return None def update_form_data(self): """ Update the xml file with changes that the user has made. Particular section of the document will be deleted or added :return: """ pass
def getStyleAsSld(layer, styleName): if layer.type() == layer.VectorLayer: document = QDomDocument() header = document.createProcessingInstruction("xml", "version=\"1.0\"") document.appendChild(header) root = document.createElementNS("http://www.opengis.net/sld", "StyledLayerDescriptor") root.setAttribute("version", "1.0.0") root.setAttribute("xmlns:ogc", "http://www.opengis.net/ogc") root.setAttribute("xmlns:sld", "http://www.opengis.net/sld") # root.setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink" ) # root.setAttribute( # "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" ) document.appendChild(root) namedLayerNode = document.createElement("sld:NamedLayer") root.appendChild(namedLayerNode) nameNode = document.createElement("sld:Name") featureTypeStyleElem = document.createElement("sld:FeatureTypeStyle") namedLayerNode.appendChild(nameNode) nameNode.appendChild(document.createTextNode(styleName)) userNode = document.createElement("sld:UserStyle") namedLayerNode.appendChild(userNode) nameElem = document.createElement("sld:Name") nameElem.appendChild(document.createTextNode(styleName)) userNode.appendChild(nameElem) titleElem = document.createElement("sld:Title") titleElem.appendChild(document.createTextNode(styleName)) userNode.appendChild(titleElem) rule = layer.renderer().rootRule() props = {} # QgsStringMap() can be see as a python dictionary rule_to_sld(rule, document, featureTypeStyleElem, props) userNode.appendChild(featureTypeStyleElem) return str(document.toString(4)) elif layer.type() == layer.RasterLayer: renderer = layer.renderer() if isinstance(renderer, QgsSingleBandGrayRenderer): symbolizerCode = "<Opacity>%d</Opacity>" % renderer.opacity() symbolizerCode += ( "<ChannelSelection><GrayChannel><SourceChannelName>" + str(renderer.grayBand()) + "</SourceChannelName></GrayChannel></ChannelSelection>") sld = RASTER_SLD_TEMPLATE.replace("SYMBOLIZER_CODE", symbolizerCode).replace( "STYLE_NAME", layer.name()) return sld elif isinstance(renderer, QgsSingleBandPseudoColorRenderer): symbolizerCode = "<ColorMap>" # band = renderer.usesBands()[0] items = \ renderer.shader().rasterShaderFunction().colorRampItemList() for item in items: color = item.color rgb = '#%02x%02x%02x' % (color.red(), color.green(), color.blue()) symbolizerCode += ('<ColorMapEntry color="' + rgb + '" quantity="' + str(item.value) + '" />') symbolizerCode += "</ColorMap>" sld = RASTER_SLD_TEMPLATE.replace("SYMBOLIZER_CODE", symbolizerCode).replace( "STYLE_NAME", layer.name()) return sld else: # we use some default styles in case we have an # unsupported renderer sldpath = os.path.join(os.path.dirname(__file__), "..", "resources") if layer.bandCount() == 1: sldfile = os.path.join(sldpath, "grayscale.sld") else: sldfile = os.path.join(sldpath, "rgb.sld") with open(sldfile, 'r', newline='') as f: sld = f.read() return sld else: return None
def adjust(self): """ Export data to GNU Gama xml, adjust the network and read result :returns: result list of adjusment from GNU Gama """ # fix = 0 free network fix = 0 adj = 0 for p, s in self.points: if s == 'FIX': fix += 1 else: adj += 1 if adj == 0 or len(self.observations) == 0: # no unknowns or observations return None doc = QDomDocument() doc.appendChild( doc.createComment( 'Gama XML created by SurveyingCalculation plugin for QGIS')) gama_local = doc.createElement('gama-local') gama_local.setAttribute('version', '2.0') doc.appendChild(gama_local) network = doc.createElement('network') network.setAttribute('axes-xy', 'ne') network.setAttribute('angles', 'left-handed') gama_local.appendChild(network) description = doc.createElement('description') if self.dimension == 1: description.appendChild(doc.createTextNode('GNU Gama 1D network')) elif self.dimension == 2: description.appendChild(doc.createTextNode('GNU Gama 2D network')) elif self.dimension == 3: description.appendChild(doc.createTextNode('GNU Gama 3D network')) network.appendChild(description) parameters = doc.createElement('parameters') parameters.setAttribute('sigma-apr', '1') parameters.setAttribute('conf-pr', str(self.probability)) parameters.setAttribute('tol-abs', '1000') parameters.setAttribute('sigma-act', 'aposteriori') parameters.setAttribute('update-constrained-coordinates', 'yes') network.appendChild(parameters) points_observations = doc.createElement('points-observations') points_observations.setAttribute( 'distance-stdev', str(self.stdev_dist) + ' ' + str(self.stdev_dist1)) points_observations.setAttribute('direction-stdev', str(self.stdev_angle)) points_observations.setAttribute('angle-stdev', str(math.sqrt(self.stdev_angle * 2))) points_observations.setAttribute('zenith-angle-stdev', str(self.stdev_angle)) network.appendChild(points_observations) for p, s in self.points: if self.dimension == 1: tmp = doc.createElement('point') tmp.setAttribute('id', p.id) if p.z is not None: tmp.setAttribute('z', str(p.z)) if s == 'FIX': tmp.setAttribute('fix', 'z') else: if fix == 0: tmp.setAttribute('adj', 'Z') else: tmp.setAttribute('adj', 'z') points_observations.appendChild(tmp) elif self.dimension == 2: tmp = doc.createElement('point') tmp.setAttribute('id', p.id) if p.e is not None and p.n is not None: tmp.setAttribute('y', str(p.e)) tmp.setAttribute('x', str(p.n)) if s == 'FIX': tmp.setAttribute('fix', 'xy') else: if fix == 0: # free network tmp.setAttribute('adj', 'XY') else: tmp.setAttribute('adj', 'xy') points_observations.appendChild(tmp) elif self.dimension == 3: tmp = doc.createElement('point') tmp.setAttribute('id', p.id) if p.e is not None and p.n is not None: tmp.setAttribute('y', str(p.e)) tmp.setAttribute('x', str(p.n)) if p.z is not None: tmp.setAttribute('z', str(p.z)) if s == 'FIX': tmp.setAttribute('fix', 'xyz') else: if fix == 0: tmp.setAttribute('adj', 'XYZ') else: tmp.setAttribute('adj', 'xyz') points_observations.appendChild(tmp) if self.dimension == 1: hd = doc.createElement('height-differences') points_observations.appendChild(hd) for o in self.observations: if o.station == 'station': # station record st_id = o.point_id if o.th is None: ih = 0 else: ih = o.th if self.dimension in [2, 3]: sta = doc.createElement('obs') sta.setAttribute('from', o.point_id) points_observations.appendChild(sta) else: # observation if self.dimension == 2: # horizontal network if o.hz is not None: tmp = doc.createElement('direction') tmp.setAttribute('to', o.point_id) tmp.setAttribute('val', str(o.hz.get_angle('GON'))) sta.appendChild(tmp) if o.d is not None: # horizontal distance hd = o.horiz_dist() if hd is not None: tmp = doc.createElement('distance') tmp.setAttribute('to', o.point_id) tmp.setAttribute('val', str(hd)) sta.appendChild(tmp) elif self.dimension == 1: # elevations only 1d if o.th is None: th = 0 else: th = o.th if o.d is not None and o.v is not None: tmp = doc.createElement('dh') tmp.setAttribute('from', st_id) tmp.setAttribute('to', o.point_id) # TODO hibaterjedes tmp.setAttribute('stdev', '1') sz = math.sin(o.v.get_angle()) w = self.stdev_dist + self.stdev_dist1 * o.d.d / 1000 ro_cc = 200 * 100 * 100 / math.pi if o.d.mode == 'SD': cz = math.cos(o.v.get_angle()) tmp.setAttribute('val', str(o.d.d * cz + ih - th)) tmp.setAttribute( 'stdev', str( math.sqrt(cz**2 * w**2 + (o.d.d * 1000)**2 * sz**2 * (self.stdev_angle / RO_CC)**2))) else: tz = math.tan(o.v.get_angle()) tmp.setAttribute( 'val', str(o.d.d / math.tan(o.v.get_angle()) + ih - th)) tmp.setAttribute( 'stdev', str( math.sqrt((1 / tz)**2 * w**2 + (o.d.d * 1000)**2 * (o.d.d * 1000)**2 * (1 / sz**2)**2 * (self.stdev_angle / RO_CC)**2))) hd.appendChild(tmp) elif self.dimension == 3: # 3d if o.th is None: th = 0 else: th = o.th if o.hz is not None: tmp = doc.createElement('direction') tmp.setAttribute('to', o.point_id) tmp.setAttribute('val', str(o.hz.get_angle('GON'))) sta.appendChild(tmp) if o.d is not None: if o.d.mode == 'SD': tmp = doc.createElement('s-distance') tmp.setAttribute('val', str(o.d.d)) tmp.setAttribute('from_dh', str(ih)) tmp.setAttribute('to_dh', str(th)) else: tmp = doc.createElement('distance') tmp.setAttribute('val', str(o.d.d)) tmp.setAttribute('to', o.point_id) sta.appendChild(tmp) if o.v is not None: tmp = doc.createElement('z-angle') tmp.setAttribute('to', o.point_id) tmp.setAttribute('val', str(o.v.get_angle('GON'))) tmp.setAttribute('from_dh', str(ih)) tmp.setAttribute('to_dh', str(th)) sta.appendChild(tmp) else: # unknown dimension return None # generate temp file name tmpf = QTemporaryFile(QDir.temp().absoluteFilePath('w')) tmpf.open(QIODevice.WriteOnly) tmpf.close() tmp_name = tmpf.fileName() f = QFile(tmp_name + '.xml') if f.open(QIODevice.WriteOnly): f.write(doc.toByteArray()) f.close() # run gama-local if self.gama_prog is None: return None status = QProcess.execute(self.gama_prog, [ tmp_name + '.xml', '--angles', '360', '--text', tmp_name + '.txt', '--xml', tmp_name + 'out.xml' ]) if status != 0: return None xmlParser = QXmlSimpleReader() xmlFile = QFile(tmp_name + 'out.xml') xmlInputSource = QXmlInputSource(xmlFile) doc.setContent(xmlInputSource, xmlParser) f_txt = QFile(tmp_name + '.txt') f_txt.open(QIODevice.ReadOnly) res = f_txt.readAll().data() f_txt.close() # store coordinates adj_nodes = doc.elementsByTagName('adjusted') if adj_nodes.count() < 1: return res adj_node = adj_nodes.at(0) for i in range(len(adj_node.childNodes())): pp = adj_node.childNodes().at(i) if pp.nodeName() == 'point': for ii in range(len(pp.childNodes())): ppp = pp.childNodes().at(ii) if ppp.nodeName() == 'id': p = Point(ppp.firstChild().nodeValue()) elif ppp.nodeName() == 'Y' or ppp.nodeName() == 'y': p.e = float(ppp.firstChild().nodeValue()) elif ppp.nodeName() == 'X' or ppp.nodeName() == 'x': p.n = float(ppp.firstChild().nodeValue()) elif ppp.nodeName() == 'Z' or ppp.nodeName() == 'z': p.z = float(ppp.firstChild().nodeValue()) ScPoint(p).store_coord(self.dimension) # remove input xml and output xml tmpf.remove() f_txt.remove() f.remove() xmlFile.remove() return res
def addToDefaultProject(maps, visibleMaps, authcfg=None): """Add basemaps to the existing default project""" layers = [] for m in maps: connstring = u'type=xyz&url={url}' if authcfg is not None: connstring = u'authcfg={authcfg}&' + connstring layer = QgsRasterLayer(connstring.format(url=urllib2.quote("{}?version={}".format(m['endpoint'], pluginSetting("apiVersion"))), authcfg=authcfg), m['name'], 'wms') # I've no idea why the following is required even if the crs is specified # in the layer definition layer.setCrs(QgsCoordinateReferenceSystem('EPSG:3857')) layers.append(layer) if os.path.isfile(defaultProjectPath()): backup = defaultProjectPath().replace( '.qgs', '-%s.qgs' % datetime.now().strftime('%Y-%m-%d-%H_%M_%S')) shutil.copy2(defaultProjectPath(), backup) # open default project with open(defaultProjectPath()) as f: content = f.read() doc = QDomDocument() setOk, errorString, errorLine, errorColumn = doc.setContent(content) if not setOk: return False root = doc.documentElement() for layer in layers: is_visible = layer.name() in visibleMaps xml = QgsMapLayer.asLayerDefinition([layer]) r = xml.documentElement() mapLayerElement = r.firstChildElement("maplayers").firstChildElement("maplayer") layerTreeLayerElement = doc.createElement("layer-tree-layer") layerTreeLayerElement.setAttribute("expanded", "1") layerTreeLayerElement.setAttribute("checked", "Qt::Checked" if is_visible else "Qt::Unchecked") layerTreeLayerElement.setAttribute("id", layer.id()) layerTreeLayerElement.setAttribute("name", layer.name()) customPropertiesElement = doc.createElement("customproperties") layerTreeLayerElement.appendChild(customPropertiesElement) legendLayerElement = doc.createElement("legendlayer") legendLayerElement.setAttribute("drawingOrder", "-1") legendLayerElement.setAttribute("open", "true") legendLayerElement.setAttribute("checked", "Qt::Checked" if is_visible else "Qt::Unchecked") legendLayerElement.setAttribute("name", layer.name()) legendLayerElement.setAttribute("showFeatureCount", "0") filegroupElement = doc.createElement("filegroup") filegroupElement.setAttribute("open", "true") filegroupElement.setAttribute("hidden", "false") legendlayerfileElement = doc.createElement("legendlayerfile") legendlayerfileElement.setAttribute("isInOverview", "0") legendlayerfileElement.setAttribute("layerid", layer.id()) legendlayerfileElement.setAttribute("visible", "1" if is_visible else "0") filegroupElement.appendChild(legendlayerfileElement) legendLayerElement.appendChild(filegroupElement) crsElement = doc.createElement("layer_coordinate_transform") crsElement.setAttribute("destAuthId", "EPSG:3857") crsElement.setAttribute("srcAuthId", "EPSG:3857") crsElement.setAttribute("srcDatumTransform", "-1") crsElement.setAttribute("destDatumTransform", "-1") crsElement.setAttribute("layerid", layer.id()) itemElement = doc.createElement("item") text = doc.createTextNode(layer.id()) itemElement.appendChild(text) e = root.firstChildElement("layer-tree-group") e.appendChild(layerTreeLayerElement) e = root.firstChildElement("mapcanvas").firstChildElement("layer_coordinate_transform_info") e.appendChild(crsElement) e = root.firstChildElement("layer-tree-canvas").firstChildElement("custom-order") e.appendChild(itemElement) e = root.firstChildElement("legend") e.appendChild(legendLayerElement) e = root.firstChildElement("projectlayers") e.appendChild(mapLayerElement) with open(defaultProjectPath(), "wb+") as f: f.write(doc.toString(2)) settings = QSettings() settings.setValue('/qgis/newProjectDefault', True) return True