qgis-tem-loader

qgis plugin for loading TEM geophysical inversion XYZ files as 3D objects
git clone git://src.adamsgaard.dk/qgis-tem-loader # fast
git clone https://src.adamsgaard.dk/qgis-tem-loader.git # slow
Log | Files | Refs | README | LICENSE Back to index

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:
Mtem_loader/tem_loader.py | 23++++++++++++++++++++---
Mtest/test_core.py | 60+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
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],