Skip to content

Commit 410bd6c

Browse files
Copilotlachlangrose
andcommitted
Prevent model init with unset bounding box and persist flag
Co-authored-by: lachlangrose <7371904+lachlangrose@users.noreply.github.com>
1 parent 369877f commit 410bd6c

File tree

3 files changed

+49
-4
lines changed

3 files changed

+49
-4
lines changed

loopstructural/gui/modelling/geological_model_tab/geological_model_tab.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,14 @@ def initialize_model(self):
142142
# Run update_model in a background thread to avoid blocking the UI.
143143
if not self.model_manager:
144144
return
145+
if self.data_manager is not None:
146+
if not self.data_manager.is_bounding_box_set():
147+
QMessageBox.critical(
148+
self,
149+
"Bounding box required",
150+
"Please set the bounding box before initializing the model.",
151+
)
152+
return
145153

146154
# create progress dialog (indeterminate)
147155
progress = QProgressDialog("Updating geological model...", "Cancel", 0, 0, self)

loopstructural/gui/modelling/model_definition/bounding_box.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ def __init__(self, parent=None, data_manager=None):
2222
self.useCurrentViewExtentButton.clicked.connect(self.useCurrentViewExtent)
2323
self.selectFromCurrentLayerButton.clicked.connect(self.selectFromCurrentLayer)
2424
self.data_manager.set_bounding_box_update_callback(self.set_bounding_box)
25+
self._update_bounding_box_styles()
2526

2627
def set_bounding_box(self, bounding_box):
2728
"""Populate UI controls with values from a BoundingBox object.
@@ -37,6 +38,7 @@ def set_bounding_box(self, bounding_box):
3738
self.maxYSpinBox.setValue(bounding_box.maximum[1])
3839
self.originZSpinBox.setValue(bounding_box.origin[2])
3940
self.maxZSpinBox.setValue(bounding_box.maximum[2])
41+
self._update_bounding_box_styles()
4042

4143
def useCurrentViewExtent(self):
4244
"""Set bounding box values from the current map canvas view extent."""
@@ -70,3 +72,27 @@ def selectFromCurrentLayer(self):
7072

7173
def onChangeExtent(self, value):
7274
self.data_manager.set_bounding_box(**value)
75+
try:
76+
self._update_bounding_box_styles()
77+
except Exception:
78+
pass
79+
80+
def _update_bounding_box_styles(self):
81+
"""Highlight spin boxes if bounding box has not been set."""
82+
if not hasattr(self, 'data_manager'):
83+
return
84+
try:
85+
is_set = self.data_manager.is_bounding_box_set()
86+
except Exception:
87+
is_set = False
88+
red_style = "border: 1px solid red;"
89+
clear_style = ""
90+
for sb in (
91+
self.originXSpinBox,
92+
self.originYSpinBox,
93+
self.originZSpinBox,
94+
self.maxXSpinBox,
95+
self.maxYSpinBox,
96+
self.maxZSpinBox,
97+
):
98+
sb.setStyleSheet(clear_style if is_set else red_style)

loopstructural/main/data_manager.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ def __init__(self, *, project=None, mapCanvas=None, logger=None):
4545
default_bounding_box['zmax'],
4646
],
4747
)
48+
self._bounding_box_set = False
4849

4950
self._basal_contacts = None
5051
self._fault_traces = None
@@ -99,7 +100,9 @@ def set_model_manager(self, model_manager):
99100
self._model_manager.set_fault_topology(self._fault_topology)
100101
self._model_manager.update_bounding_box(self._bounding_box)
101102

102-
def set_bounding_box(self, xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None):
103+
def set_bounding_box(
104+
self, xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None, *, mark_set=True
105+
):
103106
"""Set the bounding box for the model."""
104107
origin = self._bounding_box.origin
105108
maximum = self._bounding_box.maximum
@@ -118,8 +121,8 @@ def set_bounding_box(self, xmin=None, xmax=None, ymin=None, ymax=None, zmin=None
118121
maximum[2] = zmax
119122
self._bounding_box.origin = origin
120123
self._bounding_box.maximum = maximum
121-
self._bounding_box.origin = origin
122-
self._bounding_box.maximum = maximum
124+
if mark_set:
125+
self._bounding_box_set = True
123126
self._model_manager.update_bounding_box(self._bounding_box)
124127
if self.bounding_box_callback:
125128
self.bounding_box_callback(self._bounding_box)
@@ -128,6 +131,10 @@ def set_bounding_box_update_callback(self, callback):
128131
self.bounding_box_callback = callback
129132
self.bounding_box_callback(self._bounding_box)
130133

134+
def is_bounding_box_set(self):
135+
"""Return True if the bounding box has been explicitly set by the user."""
136+
return bool(self._bounding_box_set)
137+
131138
def set_fault_trace_layer_callback(self, callback):
132139
"""Set the callback for when the fault trace layer is updated."""
133140
self.fault_traces_callback = callback
@@ -162,6 +169,7 @@ def get_bounding_box(self):
162169
"""Get the current bounding box."""
163170
return self._bounding_box
164171

172+
165173
def set_elevation(self, elevation):
166174
"""Set the elevation for the model."""
167175
self.elevation = elevation
@@ -457,6 +465,7 @@ def to_dict(self):
457465

458466
return {
459467
'bounding_box': self._bounding_box.to_dict(),
468+
'bounding_box_set': self._bounding_box_set,
460469
'basal_contacts': basal_contacts,
461470
'fault_traces': fault_traces,
462471
'structural_orientations': structural_orientations,
@@ -478,6 +487,7 @@ def from_dict(self, data):
478487
ymax=data['bounding_box']['maximum'][1],
479488
zmin=data['bounding_box']['origin'][2],
480489
zmax=data['bounding_box']['maximum'][2],
490+
mark_set=data.get('bounding_box_set', True),
481491
)
482492
if 'dem_layer' in data and data['dem_layer'] is not None:
483493
dem_layer = QgsProject.instance().mapLayersByName(data['dem_layer'])
@@ -512,9 +522,10 @@ def update_from_dict(self, data):
512522
ymax=data['bounding_box']['maximum'][1],
513523
zmin=data['bounding_box']['origin'][2],
514524
zmax=data['bounding_box']['maximum'][2],
525+
mark_set=data.get('bounding_box_set', True),
515526
)
516527
else:
517-
self.set_bounding_box(**default_bounding_box)
528+
self.set_bounding_box(**default_bounding_box, mark_set=False)
518529
if 'dem_layer' in data and data['dem_layer'] is not None:
519530
dem_layer = QgsProject.instance().mapLayersByName(data['dem_layer'])
520531
if dem_layer:

0 commit comments

Comments
 (0)