Uh oh!
There was an error while loading. Please reload this page.
- 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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
ae425a0fc7b8ebdd79214ff55f3f351a96a2ec3fcd24cc53956ceb775fba7c84a0ba19752f217914864091d94e6e590b19c487decc74aedc118aecce74bcc775ff03e7208085440fd2e3a22d1a52cccd137e0319cc9a0deFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Uh oh!
There was an error while loading. Please reload this page.
| 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: | ||||||||
CopilotAI | ||||||||
| pass | ||||||||
| finally: | ||||||||
| try: | ||||||||
| progress.close() | ||||||||
| except Exception: | ||||||||
CopilotAI | ||||||||
| pass | ||||||||
| # cleanup worker/thread | ||||||||
| try: | ||||||||
| worker.deleteLater() | ||||||||
| except Exception: | ||||||||
CopilotAI | ||||||||
| pass | ||||||||
| try: | ||||||||
| thread.quit() | ||||||||
| thread.wait(2000) | ||||||||
| except Exception: | ||||||||
CopilotAI | ||||||||
| pass | ||||||||
| def _on_error(tb): | ||||||||
| try: | ||||||||
| progress.close() | ||||||||
| except Exception: | ||||||||
CopilotAI | ||||||||
| pass | ||||||||
| try: | ||||||||
| QMessageBox.critical( | ||||||||
| self, | ||||||||
| "Model update failed", | ||||||||
| f"An error occurred while updating the model:\n{tb}", | ||||||||
| ) | ||||||||
| except Exception: | ||||||||
CopilotAI | ||||||||
| exceptException: | |
| exceptException: | |
| # Best-effort display of error dialog; ignore failures in QMessageBox. |
CopilotAIJan 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.
CopilotAIJan 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.
CopilotAIJan 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().
CopilotAIJan 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.
CopilotAIJan 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().
CopilotAIJan 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.
CopilotAIJan 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.
CopilotAIJan 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.
CopilotAIJan 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.
Uh oh!
There was an error while loading. Please reload this page.
CopilotAIJan 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.