Skip to content

Commit

Permalink
Exit handling, more decimals, context menu style inheritance
Browse files Browse the repository at this point in the history
  • Loading branch information
mlauer154 committed Aug 31, 2023
1 parent c849365 commit e4a577b
Show file tree
Hide file tree
Showing 7 changed files with 228 additions and 44 deletions.
9 changes: 9 additions & 0 deletions pymead/gui/airfoil_pos_parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@
from pyqtgraph import SpinBox
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QDoubleSpinBox
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject
from PyQt5 import QtCore
from PyQt5.QtWidgets import QMenu

translate = QtCore.QCoreApplication.translate
import numpy as np

from pymead.gui.custom_context_menu_event import custom_context_menu_event


class SignalContainer(QObject):
"""Need to create a separate class to contain the composite signal because the WidgetParameterItem cannot be cast
Expand Down Expand Up @@ -57,3 +63,6 @@ def either_changed():
widget.value = value
widget.setValue = setValue
return widget

def contextMenuEvent(self, ev):
custom_context_menu_event(ev, self)
5 changes: 5 additions & 0 deletions pymead/gui/autocomplete.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from PyQt5.QtCore import Qt
from pyqtgraph.parametertree.parameterTypes.basetypes import WidgetParameterItem

from pymead.gui.custom_context_menu_event import custom_context_menu_event


class AutoStrParameterItem(WidgetParameterItem):
"""Parameter type which displays a QLineEdit with an auto-completion mechanism built in"""
Expand All @@ -23,6 +25,9 @@ def makeWidget(self):
self.widget = w
return w

def contextMenuEvent(self, ev):
custom_context_menu_event(ev, self)


class Completer(QCompleter):
"""
Expand Down
54 changes: 54 additions & 0 deletions pymead/gui/custom_context_menu_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from PyQt5.QtCore import QEvent, QCoreApplication
from PyQt5.QtWidgets import QMenu
from pyqtgraph.parametertree.ParameterItem import ParameterItem

translate = QCoreApplication.translate


def custom_context_menu_event(ev: QEvent, param_item: ParameterItem):
"""
Re-implemented to provide style inherited from GUI main window
"""
opts = param_item.param.opts

if not opts.get('removable', False) and not opts.get('renamable', False) \
and "context" not in opts:
return

## Generate context menu for renaming/removing parameter

# Loop to identify the GUI object
max_iter = 12
iter_count = 0
current_parent = param_item.param
gui = None

while True:
if iter_count > max_iter:
break
current_parent = current_parent.parent()
if hasattr(current_parent, "status_bar"):
gui = current_parent.status_bar.parent()
break

ss = gui.themes[gui.current_theme]
param_item.contextMenu = QMenu(parent=gui) # Put in global name space to prevent garbage collection
param_item.contextMenu.setStyleSheet(f"QMenu::item:selected {{ color: {ss['menu-main-color']}; background-color: {ss['menu-item-selected-color']} }} ")
param_item.contextMenu.addSeparator()
if opts.get('renamable', False):
param_item.contextMenu.addAction(translate("ParameterItem", 'Rename')).triggered.connect(param_item.editName)
if opts.get('removable', False):
param_item.contextMenu.addAction(translate("ParameterItem", "Remove")).triggered.connect(param_item.requestRemove)

# context menu
context = opts.get('context', None)
if isinstance(context, list):
for name in context:
param_item.contextMenu.addAction(name).triggered.connect(
param_item.contextMenuTriggered(name))
elif isinstance(context, dict):
for name, title in context.items():
param_item.contextMenu.addAction(title).triggered.connect(
param_item.contextMenuTriggered(name))

param_item.contextMenu.popup(ev.globalPos())
31 changes: 25 additions & 6 deletions pymead/gui/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
from pymead import RESOURCE_DIR
from pymead.gui.input_dialog import SingleAirfoilViscousDialog, LoadDialog, SaveAsDialog, OptimizationSetupDialog, \
MultiAirfoilDialog, ColorInputDialog, ExportCoordinatesDialog, ExportControlPointsDialog, AirfoilPlotDialog, \
AirfoilMatchingDialog, MSESFieldPlotDialog, ExportIGESDialog, XFOILDialog, NewMEADialog, EditBoundsDialog
AirfoilMatchingDialog, MSESFieldPlotDialog, ExportIGESDialog, XFOILDialog, NewMEADialog, EditBoundsDialog, \
ExitDialog
from pymead.gui.pymeadPColorMeshItem import PymeadPColorMeshItem
from pymead.gui.analysis_graph import AnalysisGraph
from pymead.gui.parameter_tree import MEAParamTree
Expand Down Expand Up @@ -245,8 +246,29 @@ def __init__(self, path=None, parent=None):
self.load_mea_no_dialog(self.path)

def closeEvent(self, a0) -> None:
print(f"{a0 = }")
# a0.accept()
"""
Close Event handling for the GUI, allowing changes to be saved before exiting the program.
Parameters
==========
a0: QCloseEvent
Qt CloseEvent object
"""
save_dialog = NewMEADialog(parent=self)
exit_dialog = ExitDialog(parent=self)
while True:
if save_dialog.exec_(): # If "Yes" to "Save Changes,"
if self.mea.file_name is not None: # If the changes were saved successfully, close the program.
break
else:
if exit_dialog.exec_(): # Otherwise, If "Yes" to "Exit the Program Anyway," close the program.
break
if save_dialog.reject_changes: # If "No" to "Save Changes," close the program.
break
else: # If "Cancel" to "Save Changes," end the CloseEvent and keep the program running.
a0.ignore()
break

# TODO: Make an "abort" button for optimization

def on_tab_closed(self, name: str, event: QCloseEvent):
Expand All @@ -263,8 +285,6 @@ def on_tab_closed(self, name: str, event: QCloseEvent):
self.parallel_coords_graph = None
elif name == "Cp":
self.Cp_graph = None
# TODO: need to do more than just set these to None (closing tab in the middle of optimization forces
# additional data to be plotted in a new, non-dockable window)

@pyqtSlot(str)
def setStatusBarText(self, message: str):
Expand Down Expand Up @@ -1612,7 +1632,6 @@ def main():
else:
gui = GUI()

# TODO: ask the user to save before closing
gui.show()
sys.exit(app.exec_())

Expand Down
20 changes: 19 additions & 1 deletion pymead/gui/input_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -1859,6 +1859,7 @@ def __init__(self, parent=None):
super().__init__(parent=parent)
self.setWindowTitle("Save Changes?")
self.setFont(self.parent().font())
self.reject_changes = False
buttonBox = QDialogButtonBox(QDialogButtonBox.Yes | QDialogButtonBox.No | QDialogButtonBox.Cancel, self)
layout = QFormLayout(self)

Expand All @@ -1876,7 +1877,24 @@ def yes(self):

@pyqtSlot()
def no(self):
pass
self.reject_changes = True


class ExitDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent=parent)
self.setWindowTitle("Exit?")
self.setFont(self.parent().font())
buttonBox = QDialogButtonBox(QDialogButtonBox.Yes | QDialogButtonBox.No, self)
layout = QFormLayout(self)

label = QLabel("Airfoil not saved.\nAre you sure you want to exit?", parent=self)

layout.addWidget(label)
layout.addWidget(buttonBox)

buttonBox.button(QDialogButtonBox.Yes).clicked.connect(self.accept)
buttonBox.button(QDialogButtonBox.No).clicked.connect(self.reject)


class EditBoundsDialog(QDialog):
Expand Down
Loading

0 comments on commit e4a577b

Please sign in to comment.