Skip to content

Commit dcc51d3

Browse files
JanCahaCopilot
andcommitted
fix reading Mergin project settings saved from QGIS 4.0 to 3.x
Co-authored-by: Copilot <copilot@github.com>
1 parent 2d7f28c commit dcc51d3

2 files changed

Lines changed: 74 additions & 0 deletions

File tree

Mergin/project_settings_widget.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
QgsMapLayer,
2121
QgsVectorLayer,
2222
QgsFieldProxyModel,
23+
Qgis,
2324
)
2425
from qgis.gui import (
2526
QgsOptionsWidgetFactory,
@@ -51,6 +52,7 @@
5152
excluded_layers_list,
5253
get_fields_for_checkbox,
5354
)
55+
from .qgis_properties_version_4 import read_mergin_properties, is_qgis_version_4
5456

5557
ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), "ui", "ui_project_config.ui")
5658
ProjectConfigUiWidget, _ = uic.loadUiType(ui_file)
@@ -82,6 +84,11 @@ def __init__(self, parent=None):
8284
QgsOptionsPageWidget.__init__(self, parent)
8385
self.setupUi(self)
8486

87+
if Qgis.versionInt() < 40000 and is_qgis_version_4(QgsProject.instance().fileName()):
88+
props = read_mergin_properties(QgsProject.instance().fileName())
89+
for key, value in props.items():
90+
QgsProject.instance().writeEntry("Mergin", key, value)
91+
8592
self.cmb_photo_quality.addItem("Original", 0)
8693
self.cmb_photo_quality.addItem("High (approx. 2-4 Mb)", 1)
8794
self.cmb_photo_quality.addItem("Medium (approx. 1-2 Mb)", 2)
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import xml.etree.ElementTree as ET
2+
from typing import Dict
3+
import zipfile
4+
5+
6+
def read_xml_tree_from_qgz(qgz_path: str) -> ET.Element:
7+
qgs_filename = next(
8+
(name for name in zipfile.ZipFile(qgz_path).namelist() if name.endswith(".qgs")),
9+
None,
10+
)
11+
12+
if qgs_filename is None:
13+
raise ValueError(f"No .qgs file found inside {qgz_path}")
14+
15+
with zipfile.ZipFile(qgz_path, "r") as input_zip_file:
16+
entries = {name: input_zip_file.read(name) for name in input_zip_file.namelist()}
17+
18+
return ET.fromstring(entries[qgs_filename])
19+
20+
21+
def is_qgis_version_4(qgz_file: str) -> bool:
22+
root = read_xml_tree_from_qgz(qgz_file)
23+
24+
version = root.attrib.get("version", "")
25+
if not version.startswith("4."):
26+
return False
27+
28+
return True
29+
30+
31+
def parse_properties(element, prefix="") -> Dict:
32+
"""Recursively parse nested <properties> elements into a flat dict with path keys."""
33+
result = {}
34+
35+
for child in element:
36+
if child.tag != "properties":
37+
continue
38+
39+
name = child.attrib.get("name", "")
40+
key = f"{prefix}/{name}" if prefix else name
41+
prop_type = child.attrib.get("type")
42+
43+
if prop_type is not None:
44+
if prop_type == "QStringList":
45+
result[key] = [v.text for v in child.findall("value")]
46+
else:
47+
result[key] = child.text
48+
else:
49+
result.update(parse_properties(child, prefix=key))
50+
51+
return result
52+
53+
54+
def read_mergin_properties(qgz_file: str) -> Dict:
55+
root = read_xml_tree_from_qgz(qgz_file)
56+
57+
version = root.attrib.get("version", "")
58+
if not version.startswith("4."):
59+
return {}
60+
61+
mergin_elem = root.find(".//properties[@name='Mergin']")
62+
if mergin_elem is None:
63+
return {}
64+
65+
props = parse_properties(mergin_elem)
66+
67+
return props

0 commit comments

Comments
 (0)