-
Notifications
You must be signed in to change notification settings - Fork 1
Fault feature panel upgrade #63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
ae425a0
fc7b8eb
dd79214
ff55f3f
351a96a
2ec3fcd
24cc539
56ceb77
5fba7c8
4a0ba19
752f217
9148640
91d94e6
e590b19
c487dec
c74aedc
118aecc
e74bcc7
75ff03e
7208085
440fd2e
3a22d1a
52cccd1
37e0319
cc9a0de
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -1,6 +1,8 @@ | ||||||||
| from PyQt5.QtCore import Qt | ||||||||
| from PyQt5.QtCore import QObject, Qt, QThread, pyqtSignal, pyqtSlot | ||||||||
| from PyQt5.QtWidgets import ( | ||||||||
| QMenu, | ||||||||
| QMessageBox, | ||||||||
| QProgressDialog, | ||||||||
| QPushButton, | ||||||||
| QSplitter, | ||||||||
| QTreeWidget, | ||||||||
|
|
@@ -9,26 +11,47 @@ | |||||||
| QWidget, | ||||||||
| ) | ||||||||
|
|
||||||||
| from .feature_details_panel import ( | ||||||||
| FaultFeatureDetailsPanel, | ||||||||
| FoldedFeatureDetailsPanel, | ||||||||
| FoliationFeatureDetailsPanel, | ||||||||
| StructuralFrameFeatureDetailsPanel, | ||||||||
| ) | ||||||||
| from LoopStructural.modelling.features import FeatureType | ||||||||
|
|
||||||||
| # Import the AddFaultDialog | ||||||||
| from .add_fault_dialog import AddFaultDialog | ||||||||
| from .add_foliation_dialog import AddFoliationDialog | ||||||||
| from .add_unconformity_dialog import AddUnconformityDialog | ||||||||
| from .feature_details_panel import ( | ||||||||
| FaultFeatureDetailsPanel, | ||||||||
| FoldedFeatureDetailsPanel, | ||||||||
| FoliationFeatureDetailsPanel, | ||||||||
| StructuralFrameFeatureDetailsPanel, | ||||||||
| ) | ||||||||
|
|
||||||||
|
|
||||||||
| class GeologicalModelTab(QWidget): | ||||||||
| def __init__(self, parent=None, *, model_manager=None, data_manager=None): | ||||||||
| super().__init__(parent) | ||||||||
| self.model_manager = model_manager | ||||||||
| self.data_manager = data_manager | ||||||||
| self.model_manager.observers.append(self.update_feature_list) | ||||||||
| # Register update observer using Observable API if available | ||||||||
| if self.model_manager is not None: | ||||||||
| try: | ||||||||
| # listen for model-level updates | ||||||||
| self._disp_model = self.model_manager.attach( | ||||||||
| self.update_feature_list, 'model_updated' | ||||||||
| ) | ||||||||
| # show progress when model updates start/finish (covers indirect calls) | ||||||||
| self._disp_update_start = self.model_manager.attach( | ||||||||
| lambda _obs, _ev, *a, **k: self._on_model_update_started(), | ||||||||
| 'model_update_started', | ||||||||
| ) | ||||||||
| self._disp_update_finish = self.model_manager.attach( | ||||||||
| lambda _obs, _ev, *a, **k: self._on_model_update_finished(), | ||||||||
| 'model_update_finished', | ||||||||
| ) | ||||||||
| except Exception: | ||||||||
| # fallback to legacy list | ||||||||
| try: | ||||||||
| self.model_manager.observers.append(self.update_feature_list) | ||||||||
| except Exception: | ||||||||
| pass | ||||||||
| # Main layout | ||||||||
| mainLayout = QVBoxLayout(self) | ||||||||
|
|
||||||||
|
|
@@ -75,6 +98,10 @@ def __init__(self, parent=None, *, model_manager=None, data_manager=None): | |||||||
| # Connect feature selection to update details panel | ||||||||
| self.featureList.itemClicked.connect(self.on_feature_selected) | ||||||||
|
|
||||||||
| # thread handle to keep worker alive while running | ||||||||
| self._model_update_thread = None | ||||||||
| self._model_update_worker = None | ||||||||
|
|
||||||||
| def show_add_feature_menu(self, *args): | ||||||||
| menu = QMenu(self) | ||||||||
| add_fault = menu.addAction("Add Fault") | ||||||||
|
|
@@ -89,6 +116,7 @@ def show_add_feature_menu(self, *args): | |||||||
| self.open_add_foliation_dialog() | ||||||||
| elif action == add_unconformity: | ||||||||
| self.open_add_unconformity_dialog() | ||||||||
|
|
||||||||
| def open_add_fault_dialog(self): | ||||||||
| dialog = AddFaultDialog(self) | ||||||||
| if dialog.exec_() == dialog.Accepted: | ||||||||
|
|
@@ -102,16 +130,95 @@ def open_add_foliation_dialog(self): | |||||||
| ) | ||||||||
| if dialog.exec_() == dialog.Accepted: | ||||||||
| pass | ||||||||
|
|
||||||||
| def open_add_unconformity_dialog(self): | ||||||||
| dialog = AddUnconformityDialog( | ||||||||
| self, data_manager=self.data_manager, model_manager=self.model_manager | ||||||||
| ) | ||||||||
| if dialog.exec_() == dialog.Accepted: | ||||||||
| pass | ||||||||
|
|
||||||||
| def initialize_model(self): | ||||||||
| self.model_manager.update_model() | ||||||||
| # Run update_model in a background thread to avoid blocking the UI. | ||||||||
| if not self.model_manager: | ||||||||
| return | ||||||||
|
|
||||||||
| # create progress dialog (indeterminate) | ||||||||
| progress = QProgressDialog("Updating geological model...", "Cancel", 0, 0, self) | ||||||||
| progress.setWindowModality(Qt.ApplicationModal) | ||||||||
| progress.setWindowTitle("Updating Model") | ||||||||
| progress.setCancelButton(None) | ||||||||
| progress.setMinimumDuration(0) | ||||||||
| progress.show() | ||||||||
|
|
||||||||
| # worker and thread | ||||||||
| thread = QThread(self) | ||||||||
| worker = _ModelUpdateWorker(self.model_manager) | ||||||||
| worker.moveToThread(thread) | ||||||||
|
|
||||||||
| # When thread starts run worker.run | ||||||||
| thread.started.connect(worker.run) | ||||||||
|
|
||||||||
| # on worker finished, notify observers on main thread and cleanup | ||||||||
| def _on_finished(): | ||||||||
| try: | ||||||||
| # notify observers now on main thread | ||||||||
| try: | ||||||||
| self.model_manager.notify('model_updated') | ||||||||
| except Exception: | ||||||||
| for obs in getattr(self.model_manager, 'observers', []): | ||||||||
| try: | ||||||||
| obs() | ||||||||
| except Exception: | ||||||||
|
||||||||
| pass | ||||||||
| finally: | ||||||||
| try: | ||||||||
| progress.close() | ||||||||
| except Exception: | ||||||||
|
||||||||
| pass | ||||||||
| # cleanup worker/thread | ||||||||
| try: | ||||||||
| worker.deleteLater() | ||||||||
| except Exception: | ||||||||
|
||||||||
| pass | ||||||||
| try: | ||||||||
| thread.quit() | ||||||||
| thread.wait(2000) | ||||||||
| except Exception: | ||||||||
|
||||||||
| pass | ||||||||
|
|
||||||||
| def _on_error(tb): | ||||||||
| try: | ||||||||
| progress.close() | ||||||||
| except Exception: | ||||||||
|
||||||||
| pass | ||||||||
| try: | ||||||||
| QMessageBox.critical( | ||||||||
| self, | ||||||||
| "Model update failed", | ||||||||
| f"An error occurred while updating the model:\n{tb}", | ||||||||
| ) | ||||||||
| except Exception: | ||||||||
|
||||||||
| except Exception: | |
| except Exception: | |
| # Best-effort display of error dialog; ignore failures in QMessageBox. |
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'except' clause does nothing but pass and there is no explanatory comment.
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'except' clause does nothing but pass and there is no explanatory comment.
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debug print statement left in production code. This should use proper logging instead of print().
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'except' clause does nothing but pass and there is no explanatory comment.
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debug print statement left in production code. This should use proper logging instead of print().
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'except' clause does nothing but pass and there is no explanatory comment.
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'except' clause does nothing but pass and there is no explanatory comment.
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'except' clause does nothing but pass and there is no explanatory comment.
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'except' clause does nothing but pass and there is no explanatory comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'except' clause does nothing but pass and there is no explanatory comment.