diff --git a/src/hyspecppt/hppt/experiment_settings.py b/src/hyspecppt/hppt/experiment_settings.py index 9eaca18..a942107 100644 --- a/src/hyspecppt/hppt/experiment_settings.py +++ b/src/hyspecppt/hppt/experiment_settings.py @@ -18,6 +18,9 @@ DEFAULT_LATTICE = dict(a=1, b=1, c=1, alpha=90, beta=90, gamma=90, h=0, k=0, l=0) DEFAULT_EXPERIMENT = dict(Ei=20, S2=30, alpha_p=0, plot_type=PLOT_TYPES[1]) DEFAULT_CROSSHAIR = dict(DeltaE=0, modQ=0) +DEFAULT_MODE = dict(current_experiment_type="single_crystal") + +# maximum momentum transfer MaxQ = 15 # invalid style diff --git a/src/hyspecppt/hppt/hppt_model.py b/src/hyspecppt/hppt/hppt_model.py index c20bf05..002bd71 100644 --- a/src/hyspecppt/hppt/hppt_model.py +++ b/src/hyspecppt/hppt/hppt_model.py @@ -157,6 +157,15 @@ def set_experiment_data(self, Ei: float, S2: float, alpha_p: float, plot_type: s self.alpha_p = alpha_p self.plot_type = plot_type + def get_experiment_data(self) -> dict[str, float]: + data = dict() + + data["Ei"] = self.Ei + data["S2"] = self.S2 + data["alpha_p"] = self.alpha_p + data["plot_type"] = self.plot_type + return data + def get_graph_data(self) -> list[float, float, float, list, list, list]: return self.calculate_graph_data() diff --git a/src/hyspecppt/hppt/hppt_presenter.py b/src/hyspecppt/hppt/hppt_presenter.py index 3c7f20e..2416585 100644 --- a/src/hyspecppt/hppt/hppt_presenter.py +++ b/src/hyspecppt/hppt/hppt_presenter.py @@ -1,30 +1,41 @@ """Presenter for the Main tab""" -from qtpy.QtWidgets import QWidget - -from .experiment_settings import DEFAULT_CROSSHAIR, DEFAULT_EXPERIMENT, DEFAULT_LATTICE, PLOT_TYPES +from .experiment_settings import DEFAULT_CROSSHAIR, DEFAULT_EXPERIMENT, DEFAULT_LATTICE, DEFAULT_MODE, PLOT_TYPES class HyspecPPTPresenter: """Main presenter""" - def __init__(self, view: "[QWidget]", model: "[QWidget]"): + def __init__(self, view: any, model: any): """Constructor :view: hppt_view class type :model:hppt_model class type """ self._view = view self._model = model + + # M-V-P connections through callbacks + self.view.connect_fields_update(self.handle_field_values_update) + self.view.connect_powder_mode_switch(self.handle_switch_to_powder) + self.view.connect_sc_mode_switch(self.handle_switch_to_sc) + + # populate fields self.view.SCW.set_values(DEFAULT_LATTICE) self.view.EW.initializeCombo(PLOT_TYPES) self.view.EW.set_values(DEFAULT_EXPERIMENT) self.view.CW.set_values(DEFAULT_CROSSHAIR) - self.view.SelW.set_SC_toggle(True) - self.get_Experiment_values() - self.get_SingleCrystal_values() - self.get_Selector_values() - self.get_Crosshair_values() + # model init + # to be removed needs to happen in the model + self.model.set_experiment_data(**DEFAULT_EXPERIMENT) + self.model.set_crosshair_data(**DEFAULT_CROSSHAIR, **DEFAULT_MODE) + self.model.set_single_crystal_data(params=DEFAULT_LATTICE) + + # set default selection mode + experiment_type = self.view.SelW.powder_label + if DEFAULT_MODE["current_experiment_type"].startswith("single"): + experiment_type = self.view.SelW.sc_label + self.view.SelW.selector_init(experiment_type) # pass the default mode from experiment type @property def view(self): @@ -36,55 +47,55 @@ def model(self): """Return the model for this presenter""" return self._model - def get_Experiment_values(self) -> dict: - """Get Ei, Pangle, S2, Type values from Experiment - - return: dict of Experiment key value pairs - """ - EW_dict = {} - EW_dict["Ei"] = self.view.EW.Ei_edit.text() - EW_dict["Pangle"] = self.view.EW.Pangle_edit.text() - EW_dict["S2"] = self.view.EW.S2_edit.text() - EW_dict["Type"] = self.view.EW.Type_combobox.currentText() - return EW_dict - - def get_Selector_values(self): - """Check if Single Crystal radio button is checked - - return: True - Single Crystal radio button is toggled - False - Single Crystal radio button is not toggled. Powder radio button is toggled - """ - return self.view.SelW.sc_rb.isChecked() - - def get_SingleCrystal_values(self): - """Get Single Crystal mode specific values from SingleCrystalWidget - - return: dict of Single Crystal key value pairs - """ - SC_dict = {} - SC_dict["a"] = self.view.SCW.a_edit.text() - SC_dict["b"] = self.view.SCW.b_edit.text() - SC_dict["c"] = self.view.SCW.c_edit.text() - - SC_dict["alpha"] = self.view.SCW.alpha_edit.text() - SC_dict["beta"] = self.view.SCW.beta_edit.text() - SC_dict["gamma"] = self.view.SCW.gamma_edit.text() - - SC_dict["h"] = self.view.SCW.h_edit.text() - SC_dict["k"] = self.view.SCW.k_edit.text() - SC_dict["l"] = self.view.SCW.l_edit.text() - return SC_dict - - def get_Crosshair_values(self): - """Get Crosshair mode specific values from CrosshairWidget - - return: dict of Crosshair key value pairs - """ - CH_dict = {} - CH_dict["DeltaE"] = self.view.CW.DeltaE_edit.text() - CH_dict["modQ"] = self.view.CW.modQ_edit.text() - return CH_dict - - def set_PlotWidget_values(self): - """Pass through intensity matrix into plot in view""" - pass + def handle_field_values_update(self, field_values): + """Save the values in the model""" + section = field_values["name"] + data = field_values["data"] + if section == "crosshair": + # get the current experiment type + experiment_type_label = self.view.SelW.get_selected_mode_label() + experiment_type = "powder" + if experiment_type_label.startswith("Single"): + experiment_type = "single_crystal" + self.model.set_crosshair_data( + current_experiment_type=experiment_type, DeltaE=float(data["DeltaE"]), modQ=float(data["modQ"]) + ) + elif section == "experiment": + self.model.set_experiment_data( + float(data["Ei"]), float(data["S2"]), float(data["alpha_p"]), data["plot_type"] + ) + else: + self.model.set_single_crystal_data(data) + + def handle_switch_to_powder(self): + """Switch to Powder mode""" + # update the fields' visibility + self.view.field_visibility_in_Powder() + # update the experiment type in the model + experiment_type = "powder" + self.model.set_crosshair_data(current_experiment_type=experiment_type) + + # get the valid values for crosshair saved fields + # if the view contains an invalid value it is overwritten + saved_values = self.model.get_crosshair_data() + self.view.CW.set_values(saved_values) + + saved_values = self.model.get_experiment_data() + self.view.EW.set_values(saved_values) + + def handle_switch_to_sc(self): + """Switch to Single Crystal mode""" + # update the fields' visibility + self.view.field_visibility_in_SC() + # update the experiment type in the model + experiment_type = "single_crystal" + self.model.set_crosshair_data(current_experiment_type=experiment_type) + + # get the valid values for crosshair saved fields + # if the view contains an invalid value it is overwritten + saved_values = self.model.get_crosshair_data() + self.view.CW.set_values(saved_values) + + # get the valid values for lattice saved fields + # saved_values = self.model.get_single_crystal_data() + # self.view.CW.set_values(saved_values) diff --git a/src/hyspecppt/hppt/hppt_view.py b/src/hyspecppt/hppt/hppt_view.py index a11d36f..0ff6572 100644 --- a/src/hyspecppt/hppt/hppt_view.py +++ b/src/hyspecppt/hppt/hppt_view.py @@ -1,14 +1,12 @@ """Widgets for the main window""" -import copy from typing import Optional, Union -import numpy as np from matplotlib.backends.backend_qtagg import FigureCanvas from matplotlib.backends.backend_qtagg import NavigationToolbar2QT as NavigationToolbar from matplotlib.figure import Figure from qtpy.QtCore import QObject, Signal -from qtpy.QtGui import QDoubleValidator, QValidator +from qtpy.QtGui import QDoubleValidator from qtpy.QtWidgets import ( QButtonGroup, QComboBox, @@ -25,50 +23,7 @@ ) from .experiment_settings import INVALID_QLINEEDIT, PLOT_TYPES, alpha, beta, gamma - - -class AbsValidator(QDoubleValidator): - """Absolute value validator""" - - def __init__( - self, parent: Optional["QObject"] = None, bottom: float = 0, top: float = np.inf, decimals: int = -1 - ) -> None: - """Constructor for the absolute value validator. All the parameters - are the same as for QDoubleValidator, but the valid value is between a - positive bottom and top, or between -top and -bottom - - Args: - parent (QObject): Optional parent - bottom (float): the minimum positive value (set to 0 if not positive) - top (float): the highest top value (set to infinity if not greater than bottom) - decimals (int): the number of digits after the decimal point. - - """ - if bottom < 0: - bottom = 0 - if top <= bottom: - top = np.inf - super().__init__(parent=parent, bottom=bottom, top=top, decimals=decimals) - - def validate(self, inp: str, pos: int) -> tuple[QValidator.State, str, int]: - """Override for validate method - - Args: - inp (str): the input string - pos (int): cursor position - - """ - original_str = copy.copy(inp) - original_pos = pos - if inp == "-": - return QValidator.Intermediate - try: - inp = str(abs(float(inp))) - except ValueError: - pass - x = super().validate(inp, pos) - # do not "fix" the input - return x[0], original_str, original_pos +from .hppt_view_validators import AbsValidator class HyspecPPTView(QWidget): @@ -83,31 +38,69 @@ def __init__(self, parent: Optional["QObject"] = None) -> None: """ super().__init__(parent) + # callback functions defined by the presenter + self.fields_callback = None + self.powder_mode_switch_callback = None + self.sc_mode_switch_callback = None + layout = QHBoxLayout() self.setLayout(layout) layoutLeft = QVBoxLayout() layout.addLayout(layoutLeft) self.EW = ExperimentWidget(self) layoutLeft.addWidget(self.EW) + self.SCW = SingleCrystalWidget(self) + self.CW = CrosshairWidget(self) self.SelW = SelectorWidget(self) layoutLeft.addWidget(self.SelW) - self.SCW = SingleCrystalWidget(self) layoutLeft.addWidget(self.SCW) - self.CW = CrosshairWidget(self) layoutLeft.addWidget(self.CW) spacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) layoutLeft.addItem(spacer) self.PW = PlotWidget(self) layout.addWidget(self.PW) - self.switch_to_SC() + # signal handling for every valid field update + self.EW.valid_signal.connect(self.values_update) + self.SCW.valid_signal.connect(self.values_update) + self.CW.valid_signal.connect(self.values_update) + + def connect_fields_update(self, callback): + """Callback for the fields update - set by the presenter""" + self.fields_callback = callback + + def connect_powder_mode_switch(self, callback): + """Callback function setup for the switching to Powder mode from the radio button + - function defined and set by the presenter + """ + self.powder_mode_switch_callback = callback + + def connect_sc_mode_switch(self, callback): + """Callback function setup for the switching to Single Crystal mode from the radio button + - function defined and set by the presenter + """ + self.sc_mode_switch_callback = callback + + def values_update(self, values): + """Fields update""" + self.fields_callback(values) def switch_to_SC(self) -> None: + """Switch to Single Crystal mode""" + if self.sc_mode_switch_callback: + self.sc_mode_switch_callback() + + def switch_to_powder(self) -> None: + """Switch to Powder mode""" + if self.powder_mode_switch_callback: + self.powder_mode_switch_callback() + + def field_visibility_in_SC(self) -> None: """Set visibility for Single Crystal mode""" self.SCW.setVisible(True) self.CW.set_Qmod_enabled(False) - def switch_to_Powder(self) -> None: + def field_visibility_in_Powder(self) -> None: """Set visibility for Powder mode""" self.SCW.setVisible(False) self.CW.set_Qmod_enabled(True) @@ -144,8 +137,10 @@ def __init__(self, parent: Optional["QObject"] = None) -> None: super().__init__(parent) selector_layout = QHBoxLayout() - self.powder_rb = QRadioButton("Po&wder") - self.sc_rb = QRadioButton("Single C&rystal") + self.powder_label = "Po&wder" + self.sc_label = "Single C&rystal" + self.powder_rb = QRadioButton(self.powder_label) + self.sc_rb = QRadioButton(self.sc_label) selector_group = QButtonGroup(self) selector_group.addButton(self.powder_rb) @@ -155,13 +150,41 @@ def __init__(self, parent: Optional["QObject"] = None) -> None: selector_layout.addWidget(self.sc_rb) self.setLayout(selector_layout) - def set_SC_toggle(self, toggle: bool) -> None: - """Sets widget display based on the values dictionary + if parent: + self.powder_rb.toggled.connect(self.sc_toggle) + self.sc_rb.toggled.connect(self.sc_toggle) + + def selector_init(self, selected_label: str): + """Initialize the default selected mode Args: - toggle: True - Single Crystal radio button is toggled - toggle: False - Single Crystal radio button is not toggled + selected_label: it contains either sc_label or powder_label + based on the selected label the mode is set during initialization """ - self.sc_rb.setChecked(toggle) + if selected_label == self.sc_label: + self.sc_rb.setChecked(True) + else: + self.powder_rb.setChecked(True) + + def sc_toggle(self) -> None: + """Update fields based on selected mode + Args: + """ + if self.parent(): + sender = self.sender().text() + + if sender == self.powder_label and self.powder_rb.isChecked(): + self.parent().switch_to_powder() + if sender == self.sc_label and self.sc_rb.isChecked(): + self.parent().switch_to_SC() + + def get_selected_mode_label(self) -> str: + """Return the label of the selected mode + Args: + """ + if self.powder_rb.isChecked(): + return self.powder_label + else: + return self.sc_label class SingleCrystalWidget(QWidget): @@ -261,23 +284,23 @@ def __init__(self, parent: Optional["QObject"] = None) -> None: # connections self.a_edit.editingFinished.connect(self.validate_all_inputs) - self.a_edit.textEdited.connect(self.validate_inputs) + self.a_edit.textChanged.connect(self.validate_inputs) self.b_edit.editingFinished.connect(self.validate_all_inputs) - self.b_edit.textEdited.connect(self.validate_inputs) + self.b_edit.textChanged.connect(self.validate_inputs) self.c_edit.editingFinished.connect(self.validate_all_inputs) - self.c_edit.textEdited.connect(self.validate_inputs) + self.c_edit.textChanged.connect(self.validate_inputs) self.alpha_edit.editingFinished.connect(self.validate_all_inputs) - self.alpha_edit.textEdited.connect(self.validate_inputs) + self.alpha_edit.textChanged.connect(self.validate_inputs) self.beta_edit.editingFinished.connect(self.validate_all_inputs) - self.beta_edit.textEdited.connect(self.validate_inputs) + self.beta_edit.textChanged.connect(self.validate_inputs) self.gamma_edit.editingFinished.connect(self.validate_all_inputs) - self.gamma_edit.textEdited.connect(self.validate_inputs) + self.gamma_edit.textChanged.connect(self.validate_inputs) self.h_edit.editingFinished.connect(self.validate_all_inputs) - self.h_edit.textEdited.connect(self.validate_inputs) + self.h_edit.textChanged.connect(self.validate_inputs) self.k_edit.editingFinished.connect(self.validate_all_inputs) - self.k_edit.textEdited.connect(self.validate_inputs) + self.k_edit.textChanged.connect(self.validate_inputs) self.l_edit.editingFinished.connect(self.validate_all_inputs) - self.l_edit.textEdited.connect(self.validate_inputs) + self.l_edit.textChanged.connect(self.validate_inputs) def set_values(self, values: dict[str, float]) -> None: """Sets widget display based on the values dictionary @@ -318,13 +341,13 @@ def validate_all_inputs(self): self.l_edit, ] keys = ["a", "b", "c", "alpha", "beta", "gamma", "h", "k", "l"] - out_signal = dict() + out_signal = dict(name="sc_lattice", data=dict()) for k, edit in zip(keys, inputs): if edit.hasAcceptableInput(): - out_signal[k] = float(edit.text()) + out_signal["data"][k] = float(edit.text()) - if len(out_signal) == 9: + if len(out_signal["data"]) == 9: self.valid_signal.emit(out_signal) @@ -383,11 +406,11 @@ def __init__(self, parent: Optional["QObject"] = None) -> None: # connections self.Ei_edit.editingFinished.connect(self.validate_all_inputs) - self.Ei_edit.textEdited.connect(self.validate_inputs) + self.Ei_edit.textChanged.connect(self.validate_inputs) self.S2_edit.editingFinished.connect(self.validate_all_inputs) - self.S2_edit.textEdited.connect(self.validate_inputs) + self.S2_edit.textChanged.connect(self.validate_inputs) self.Pangle_edit.editingFinished.connect(self.validate_all_inputs) - self.Pangle_edit.textEdited.connect(self.validate_inputs) + self.Pangle_edit.textChanged.connect(self.validate_inputs) self.Type_combobox.currentIndexChanged.connect(self.validate_all_inputs) def initializeCombo(self, options: list[str]) -> None: @@ -412,11 +435,12 @@ def validate_all_inputs(self) -> None: inputs = [self.Ei_edit, self.S2_edit, self.Pangle_edit] keys = ["Ei", "S2", "alpha_p"] - out_signal = dict(plot_type=self.Type_combobox.currentText()) + out_signal = dict(name="experiment", data=dict()) + out_signal["data"] = dict(plot_type=self.Type_combobox.currentText()) for k, edit in zip(keys, inputs): if edit.hasAcceptableInput(): - out_signal[k] = float(edit.text()) - if len(out_signal) == 4: + out_signal["data"][k] = float(edit.text()) + if len(out_signal["data"]) == 4: self.valid_signal.emit(out_signal) def set_values(self, values: dict[str, Union[float, str]]) -> None: @@ -472,9 +496,9 @@ def __init__(self, parent: Optional["QObject"] = None) -> None: # connections self.DeltaE_edit.editingFinished.connect(self.validate_all_inputs) - self.DeltaE_edit.textEdited.connect(self.validate_inputs) + self.DeltaE_edit.textChanged.connect(self.validate_inputs) self.modQ_edit.editingFinished.connect(self.validate_all_inputs) - self.modQ_edit.textEdited.connect(self.validate_inputs) + self.modQ_edit.textChanged.connect(self.validate_inputs) groupBox = QGroupBox("Crosshair position") groupBox.setLayout(box_layout) @@ -513,9 +537,9 @@ def validate_all_inputs(self): inputs = [self.DeltaE_edit, self.modQ_edit] keys = ["DeltaE", "modQ"] - out_signal = dict() + out_signal = dict(name="crosshair", data=dict()) for k, edit in zip(keys, inputs): if edit.hasAcceptableInput(): - out_signal[k] = float(edit.text()) - if len(out_signal) == 2: + out_signal["data"][k] = float(edit.text()) + if len(out_signal["data"]) == 2: self.valid_signal.emit(out_signal) diff --git a/src/hyspecppt/hppt/hppt_view_validators.py b/src/hyspecppt/hppt/hppt_view_validators.py new file mode 100644 index 0000000..83bdf27 --- /dev/null +++ b/src/hyspecppt/hppt/hppt_view_validators.py @@ -0,0 +1,42 @@ +import copy + +from qtpy.QtCore import QObject +from qtpy.QtGui import QDoubleValidator, QValidator + + +class AbsValidator(QDoubleValidator): + """Absolute value validator""" + + def __init__(self, parent: QObject, bottom: float, top: float, decimals: int = -1) -> None: + """Constructor for the absolute value validator. All the parameters + are the same as for QDoubleValidator, but the valid value is between a + positive bottom and top, or between -top and -bottom + + Args: + parent (QObject): Optional parent + bottom (float): the minimum positive value (set to 0 if not positive) + top (float): the highest top value (set to infinity if not greater than bottom) + decimals (int): the number of digits after the decimal point. + + """ + super().__init__(parent=parent, bottom=bottom, top=top, decimals=decimals) + + def validate(self, inp: str, pos: int) -> tuple[QValidator.State, str, int]: + """Override for validate method + + Args: + inp (str): the input string + pos (int): cursor position + + """ + original_str = copy.copy(inp) + original_pos = pos + if inp == "-": + return QValidator.Intermediate + try: + inp = str(abs(float(inp))) + except ValueError: + pass + x = super().validate(inp, pos) + # do not "fix" the input + return x[0], original_str, original_pos diff --git a/tests/hppt_presenter/test_presenter.py b/tests/hppt_presenter/test_presenter.py index e8e714a..42158dd 100644 --- a/tests/hppt_presenter/test_presenter.py +++ b/tests/hppt_presenter/test_presenter.py @@ -1,25 +1,247 @@ -import unittest -from unittest.mock import Mock - -import hyspecppt.hppt.hppt_presenter as hppt_presenter -from hyspecppt.hppt.experiment_settings import DEFAULT_CROSSHAIR, DEFAULT_EXPERIMENT, DEFAULT_LATTICE, PLOT_TYPES - - -class PresenterTests(unittest.TestCase): - def test_presenter_init(self): - """Tests that presenter is initialized correctly""" - mock_view = Mock() - mock_model = Mock() - presenter = hppt_presenter.HyspecPPTPresenter(mock_view, mock_model) - mock_view.SCW.set_values.assert_called_once_with(DEFAULT_LATTICE) - mock_view.EW.initializeCombo.assert_called_once_with(PLOT_TYPES) - mock_view.EW.set_values.assert_called_once_with(DEFAULT_EXPERIMENT) - mock_view.CW.set_values.assert_called_once_with(DEFAULT_CROSSHAIR) - mock_view.SelW.set_SC_toggle.assert_called_once_with(True) - # maybe move these to a function in the view - mock_view.EW.Ei_edit.text.assert_called_once() - mock_view.EW.Pangle_edit.text.assert_called_once() - mock_view.EW.S2_edit.text.assert_called_once() - mock_view.EW.Type_combobox.currentText.assert_called_once() - assert presenter.view == mock_view - assert presenter.model == mock_model +from PySide6.QtCore import Qt + +from hyspecppt.hppt.experiment_settings import INVALID_QLINEEDIT + + +def test_presenter_init(qtbot, hyspec_app): + """Tests that presenter is initialized correctly""" + # show the app + hyspec_app.show() + qtbot.waitUntil(hyspec_app.show, timeout=5000) + assert hyspec_app.isVisible() + + view = hyspec_app.main_window.HPPT_view + + # check the default values are populated + assert view.EW.Ei_edit.text() == "20" + assert view.EW.Pangle_edit.text() == "0" + assert view.EW.S2_edit.text() == "30" + assert view.EW.Type_combobox.currentText() == "cos" + "\u03b1" + "\u209b" + "\u00b2" + + +def test_selector_widget_powder_mode(hyspec_app, qtbot): + """Test the Powder Mode in Selector widget when the radio button is pressed""" + # show the app + hyspec_app.show() + qtbot.waitUntil(hyspec_app.show, timeout=5000) + assert hyspec_app.isVisible() + + hyspec_view = hyspec_app.main_window.HPPT_view + hyspec_view.SelW.powder_rb.setChecked(True) + + assert not hyspec_view.SCW.isVisibleTo(hyspec_app) + assert hyspec_view.CW.modQ_edit.isEnabled() + + +def test_switch_to_sc(hyspec_app, qtbot): + """Test switch_to_SC() set SingleCrystalWidget visible""" + # show the app + hyspec_app.show() + qtbot.waitUntil(hyspec_app.show, timeout=5000) + assert hyspec_app.isVisible() + + hyspec_view = hyspec_app.main_window.HPPT_view + hyspec_view.switch_to_SC() + assert hyspec_view.SCW.isVisibleTo(hyspec_view) + assert not hyspec_view.CW.modQ_edit.isEnabled() + + +def test_switch_to_powder(hyspec_app, qtbot): + """Test switch_to_powder() set SingleCrystalWidget visible""" + # show the app + hyspec_app.show() + qtbot.waitUntil(hyspec_app.show, timeout=5000) + assert hyspec_app.isVisible() + + qtbot.waitUntil(hyspec_app.show, timeout=5000) + hyspec_view = hyspec_app.main_window.HPPT_view + hyspec_view.switch_to_powder() + assert not hyspec_view.SCW.isVisibleTo(hyspec_view) + assert hyspec_view.CW.modQ_edit.isEnabled() + + +def test_switch_to_powder_ei(hyspec_app, qtbot): + """Test switch to Powder check Ei value""" + # show the app + hyspec_app.show() + qtbot.waitUntil(hyspec_app.show, timeout=5000) + assert hyspec_app.isVisible() + + hyspec_view = hyspec_app.main_window.HPPT_view + experiment_widget = hyspec_view.EW + + # set Ei invalid value + qtbot.keyClicks(experiment_widget.Ei_edit, "4") + assert experiment_widget.Ei_edit.text() == "204" + assert experiment_widget.Ei_edit.styleSheet() == INVALID_QLINEEDIT + + # switch to powder + hyspec_view.switch_to_powder() + + # Ei value should have the default valid value + assert experiment_widget.Ei_edit.text() == "20" + assert experiment_widget.Ei_edit.styleSheet() != INVALID_QLINEEDIT + + +def test_switch_to_powder_pangle(hyspec_app, qtbot): + """Test switch to Powder check P angle value""" + # show the app + hyspec_app.show() + qtbot.waitUntil(hyspec_app.show, timeout=5000) + assert hyspec_app.isVisible() + + hyspec_view = hyspec_app.main_window.HPPT_view + experiment_widget = hyspec_view.EW + + # empty p angle value + experiment_widget.Pangle_edit.clear() + assert experiment_widget.Pangle_edit.text() == "" + assert experiment_widget.Pangle_edit.styleSheet() == INVALID_QLINEEDIT + + # switch to powder + hyspec_view.switch_to_powder() + + # P angle value should have the default valid value + assert experiment_widget.Pangle_edit.text() == "0" + assert experiment_widget.Pangle_edit.styleSheet() != INVALID_QLINEEDIT + + +def test_switch_to_powder_s2(hyspec_app, qtbot): + """Test switch to Powder check S2 value""" + # show the app + hyspec_app.show() + qtbot.waitUntil(hyspec_app.show, timeout=5000) + assert hyspec_app.isVisible() + + hyspec_view = hyspec_app.main_window.HPPT_view + experiment_widget = hyspec_view.EW + + # set Ei invalid value + qtbot.keyClicks(experiment_widget.S2_edit, "6") + assert experiment_widget.S2_edit.text() == "306" + assert experiment_widget.S2_edit.styleSheet() == INVALID_QLINEEDIT + + # switch to powder + hyspec_view.switch_to_powder() + + # Ei value should have the default valid value + assert experiment_widget.S2_edit.text() == "30" + assert experiment_widget.S2_edit.styleSheet() != INVALID_QLINEEDIT + + +def test_switch_to_powder_deltae_default_value(hyspec_app, qtbot): + """Test switch to Powder check DeltaE value""" + # show the app + hyspec_app.show() + qtbot.waitUntil(hyspec_app.show, timeout=5000) + assert hyspec_app.isVisible() + + hyspec_view = hyspec_app.main_window.HPPT_view + crosshair_widget = hyspec_view.CW + + # empty DeltaE value + crosshair_widget.DeltaE_edit.clear() + assert crosshair_widget.DeltaE_edit.text() == "" + assert crosshair_widget.DeltaE_edit.styleSheet() == INVALID_QLINEEDIT + + # switch to powder + hyspec_view.switch_to_powder() + + # Delta E value should be back to its default value + assert crosshair_widget.DeltaE_edit.text() == "0" + assert crosshair_widget.DeltaE_edit.styleSheet() != INVALID_QLINEEDIT + + +def test_switch_to_powder_qmod_default_value(hyspec_app, qtbot): + """Test switch to Powder check Qmod value""" + # show the app + hyspec_app.show() + qtbot.waitUntil(hyspec_app.show, timeout=5000) + assert hyspec_app.isVisible() + + hyspec_view = hyspec_app.main_window.HPPT_view + crosshair_widget = hyspec_view.CW + + # empty Qmod value + crosshair_widget.modQ_edit.clear() + assert crosshair_widget.modQ_edit.text() == "" + assert crosshair_widget.modQ_edit.styleSheet() == INVALID_QLINEEDIT + + # switch to powder + hyspec_view.switch_to_powder() + + # Qmod value should be back to its default value + assert crosshair_widget.modQ_edit.text() == "0.0" + assert crosshair_widget.modQ_edit.styleSheet() != INVALID_QLINEEDIT + + +def test_switch_to_powder_deltae_updated_values(hyspec_app, qtbot): + """Test switch to Powder check DeltaE value with a new value""" + # show the app + hyspec_app.show() + qtbot.waitUntil(hyspec_app.show, timeout=5000) + assert hyspec_app.isVisible() + + hyspec_view = hyspec_app.main_window.HPPT_view + crosshair_widget = hyspec_view.CW + + # set a valid DeltaE value + crosshair_widget.DeltaE_edit.clear() + + qtbot.keyClicks(crosshair_widget.DeltaE_edit, "4.1") + assert crosshair_widget.DeltaE_edit.text() == "4.1" + + # Simulate gaining/losing focus + crosshair_widget.DeltaE_edit.setFocus() + qtbot.keyPress(crosshair_widget.DeltaE_edit, Qt.Key_Return) + + # empty DeltaE value + crosshair_widget.DeltaE_edit.clear() + assert crosshair_widget.DeltaE_edit.text() == "" + assert crosshair_widget.DeltaE_edit.styleSheet() == INVALID_QLINEEDIT + + # switch to powder + hyspec_view.switch_to_powder() + + # Delta E value should be back to its default value + assert crosshair_widget.DeltaE_edit.text() == "4.1" + assert crosshair_widget.DeltaE_edit.styleSheet() != INVALID_QLINEEDIT + + +def test_switch_to_powder_qmod_updated_values(hyspec_app, qtbot): + """Test switch to Powder check Qmod value with a new value""" + # show the app + hyspec_app.show() + qtbot.waitUntil(hyspec_app.show, timeout=5000) + assert hyspec_app.isVisible() + + hyspec_view = hyspec_app.main_window.HPPT_view + crosshair_widget = hyspec_view.CW + + assert crosshair_widget.modQ_edit.text() == "0.0" + + # switch to powder + hyspec_view.switch_to_powder() + + # set a valid Qmod value + crosshair_widget.modQ_edit.clear() + assert crosshair_widget.modQ_edit.text() == "" + + qtbot.keyClicks(crosshair_widget.modQ_edit, "2.35") + assert crosshair_widget.modQ_edit.text() == "2.35" + + # Simulate gaining/losing focus + crosshair_widget.modQ_edit.setFocus() + qtbot.keyPress(crosshair_widget.modQ_edit, Qt.Key_Return) + + # empty Qmod value + crosshair_widget.modQ_edit.clear() + assert crosshair_widget.modQ_edit.text() == "" + assert crosshair_widget.modQ_edit.styleSheet() == INVALID_QLINEEDIT + + # switch to powder + hyspec_view.switch_to_SC() + + # Qmod value should be back to its default value + assert crosshair_widget.modQ_edit.text() == "0.0" + assert crosshair_widget.modQ_edit.styleSheet() != INVALID_QLINEEDIT diff --git a/tests/hppt_view/test_basegui.py b/tests/hppt_view/test_basegui.py index 0935911..38f6121 100644 --- a/tests/hppt_view/test_basegui.py +++ b/tests/hppt_view/test_basegui.py @@ -86,19 +86,3 @@ def test_Selector_widget(qtbot): assert SELWidget.powder_rb.text() == "Po&wder" assert SELWidget.sc_rb.text() == "Single C&rystal" - - -def test_switch_to_SC(): - """Test switch_to_SC() set SingleCrystalWidget visible""" - view = hppt_view.HyspecPPTView() - view.switch_to_SC() - assert view.SCW.isVisibleTo(view) - assert not view.CW.modQ_edit.isEnabled() - - -def test_switch_to_Powder(): - """Test switch_to_Powder() set SingleCrystalWidget visible""" - view = hppt_view.HyspecPPTView() - view.switch_to_Powder() - assert not view.SCW.isVisibleTo(view) - assert view.CW.modQ_edit.isEnabled() diff --git a/tests/hppt_view/test_setdefaults.py b/tests/hppt_view/test_setdefaults.py index daf925b..d4cf89f 100644 --- a/tests/hppt_view/test_setdefaults.py +++ b/tests/hppt_view/test_setdefaults.py @@ -49,8 +49,9 @@ def test_set_Crosshair_widget_Default_Values(qtbot): def test_set_Selector_widget_Default_Values(qtbot): """Test the default SC mode is toggled""" SelWidget = hppt_view.SelectorWidget() - SelWidget.set_SC_toggle(True) qtbot.addWidget(SelWidget) + label = "Single C&rystal" + SelWidget.selector_init(label) assert SelWidget.sc_rb.isChecked() assert not SelWidget.powder_rb.isChecked() diff --git a/tests/hppt_view/test_validators.py b/tests/hppt_view/test_validators.py index 23529c9..6bf385d 100644 --- a/tests/hppt_view/test_validators.py +++ b/tests/hppt_view/test_validators.py @@ -44,7 +44,9 @@ def test_Experiment_validators(qtbot): # all valid qtbot.keyClicks(ExpWidget.S2_edit, "0") ExpWidget.S2_edit.editingFinished.emit() - mock_slot.assert_called_once_with({"Ei": 30.0, "S2": -40.0, "alpha_p": -45.0, "plot_type": PLOT_TYPES[0]}) + mock_slot.assert_called_once_with( + {"data": {"Ei": 30.0, "S2": -40.0, "alpha_p": -45.0, "plot_type": PLOT_TYPES[0]}, "name": "experiment"} + ) def test_Single_Crystal_validators(qtbot): @@ -91,15 +93,18 @@ def test_Single_Crystal_validators(qtbot): SCWidget.a_edit.editingFinished.emit() mock_slot.assert_called_once_with( { - "a": 45.0, - "alpha": 45.0, - "b": 45.0, - "beta": 45.0, - "c": 45.0, - "gamma": 45.0, - "h": -45.0, - "k": -45.0, - "l": -45.0, + "data": { + "a": 45.0, + "alpha": 45.0, + "b": 45.0, + "beta": 45.0, + "c": 45.0, + "gamma": 45.0, + "h": -45.0, + "k": -45.0, + "l": -45.0, + }, + "name": "sc_lattice", } ) @@ -129,4 +134,4 @@ def test_Crosshairs_validators(qtbot): # all valid qtbot.keyClicks(CHWidget.modQ_edit, "\b") CHWidget.DeltaE_edit.editingFinished.emit() - mock_slot.assert_called_once_with({"DeltaE": -1.0, "modQ": 2.0}) + mock_slot.assert_called_once_with({"data": {"DeltaE": -1.0, "modQ": 2.0}, "name": "crosshair"})