commit 0bd26dc511ebf9a2d1649541296409c8d0b4bb1c
parent 95bb5095c8c979afd0484b97ea56e0ab1adfe381
Author: Anders Damsgaard <anders@adamsgaard.dk>
Date: Fri, 15 May 2026 22:55:15 +0200
feat(qgis): wire import options into loading
Diffstat:
2 files changed, 79 insertions(+), 4 deletions(-)
diff --git a/tem_loader/tem_loader.py b/tem_loader/tem_loader.py
@@ -173,11 +173,19 @@ class TEMLoaderPlugin:
'',
'XYZ files (*.xyz);;All files (*)',
)
+ if not paths:
+ return
+
+ dialog = _ImportOptionsDialog(self.iface.mainWindow())
+ if _exec_dialog(dialog) != QDialog.Accepted:
+ return
+
+ options = dialog.options()
failed = []
for path in paths:
filepath = Path(path)
try:
- self._load_xyz(filepath)
+ self._load_xyz(filepath, **options)
except Exception as exc:
failed.append(f'{filepath.name}: {exc}')
if failed:
@@ -202,8 +210,17 @@ class TEMLoaderPlugin:
crs.createFromString('EPSG:4326')
return crs
- def _load_xyz(self, filepath):
- points, doi_points, layers = core.process_xyz(filepath)
+ def _load_xyz(
+ self,
+ filepath,
+ mask_below_doi=True,
+ below_doi_opacity=core.BELOW_DOI_OPACITY,
+ ):
+ points, doi_points, layers = core.process_xyz(
+ filepath,
+ mask_below_doi=mask_below_doi,
+ below_doi_opacity=below_doi_opacity,
+ )
project = QgsProject.instance()
crs = self._resolve_crs(filepath, project)
diff --git a/test/test_core.py b/test/test_core.py
@@ -781,6 +781,13 @@ class PluginTests(unittest.TestCase):
file_dialog.paths = ["/tmp/bad.xyz", "/tmp/good.xyz"]
iface = Mock()
iface.mainWindow.return_value = object()
+ dialog = Mock()
+ dialog.options.return_value = {
+ "mask_below_doi": True,
+ "below_doi_opacity": 35,
+ }
+ module._ImportOptionsDialog = Mock(return_value=dialog)
+ module._exec_dialog = Mock(return_value=module.QDialog.Accepted)
plugin = module.TEMLoaderPlugin(iface)
plugin._load_xyz = Mock(
side_effect=[ValueError("Row 3 has 4 columns, expected 6"), None]
@@ -793,6 +800,48 @@ class PluginTests(unittest.TestCase):
self.assertIn("bad.xyz", message_box.warnings[0][2])
self.assertIn("Row 3 has 4 columns, expected 6", message_box.warnings[0][2])
+ def test_run_opens_options_dialog_after_file_selection_and_passes_options(self):
+ module, file_dialog, _ = self._import_plugin_module()
+ file_dialog.paths = ["/tmp/model.xyz"]
+ iface = Mock()
+ parent = object()
+ iface.mainWindow.return_value = parent
+ dialog = Mock()
+ dialog.options.return_value = {
+ "mask_below_doi": True,
+ "below_doi_opacity": 35,
+ }
+ module._ImportOptionsDialog = Mock(return_value=dialog)
+ module._exec_dialog = Mock(return_value=module.QDialog.Accepted)
+ plugin = module.TEMLoaderPlugin(iface)
+ plugin._load_xyz = Mock()
+
+ plugin.run()
+
+ module._ImportOptionsDialog.assert_called_once_with(parent)
+ module._exec_dialog.assert_called_once_with(dialog)
+ plugin._load_xyz.assert_called_once_with(
+ Path("/tmp/model.xyz"),
+ mask_below_doi=True,
+ below_doi_opacity=35,
+ )
+
+ def test_run_cancel_options_dialog_skips_all_loads(self):
+ module, file_dialog, _ = self._import_plugin_module()
+ file_dialog.paths = ["/tmp/one.xyz", "/tmp/two.xyz"]
+ iface = Mock()
+ iface.mainWindow.return_value = object()
+ dialog = Mock()
+ module._ImportOptionsDialog = Mock(return_value=dialog)
+ module._exec_dialog = Mock(return_value=module.QDialog.Rejected)
+ plugin = module.TEMLoaderPlugin(iface)
+ plugin._load_xyz = Mock()
+
+ plugin.run()
+
+ plugin._load_xyz.assert_not_called()
+ dialog.options.assert_not_called()
+
def test_import_options_dialog_defaults_and_options(self):
module, _, _ = self._import_plugin_module()
@@ -1011,8 +1060,17 @@ class PluginTests(unittest.TestCase):
module.core.write_csv = Mock()
plugin = module.TEMLoaderPlugin(Mock())
- plugin._load_xyz(Path("/tmp/model.xyz"))
+ plugin._load_xyz(
+ Path("/tmp/model.xyz"),
+ mask_below_doi=False,
+ below_doi_opacity=35,
+ )
+ module.core.process_xyz.assert_called_once_with(
+ Path("/tmp/model.xyz"),
+ mask_below_doi=False,
+ below_doi_opacity=35,
+ )
self.assertFalse(module.core.write_csv.called)
self.assertEqual(
[call["layerName"] for call in module.QgsVectorFileWriter.calls],