From 04a7714cbdb31f04a5c00b5195f9c3a92e9b807f Mon Sep 17 00:00:00 2001 From: David Yonge-Mallo Date: Fri, 19 Apr 2024 12:20:07 +0200 Subject: [PATCH 1/2] Move UI code for showing errors out of `custom_rule.py`. Incidentally, make the warning dialogs modal (see issue #156). --- zxlive/custom_rule.py | 15 ++++++--------- zxlive/dialogs.py | 7 ++++++- zxlive/mainwindow.py | 10 ++++++++-- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/zxlive/custom_rule.py b/zxlive/custom_rule.py index 95bc12d0..4c0239dc 100644 --- a/zxlive/custom_rule.py +++ b/zxlive/custom_rule.py @@ -315,30 +315,28 @@ def get_vertex_positions(graph: GraphT, rhs_graph: nx.Graph, boundary_vertex_map ret: dict[NodeView, tuple[float, float]] = nx.spring_layout(rhs_graph, k=k, pos=pos_dict, fixed=boundary_vertex_map.keys()) return ret + def check_rule(rule: CustomRule, show_error: bool = True) -> bool: rule.lhs_graph.auto_detect_io() rule.rhs_graph.auto_detect_io() if len(rule.lhs_graph.inputs()) != len(rule.rhs_graph.inputs()) or \ len(rule.lhs_graph.outputs()) != len(rule.rhs_graph.outputs()): if show_error: - from .dialogs import show_error_msg - show_error_msg("Warning!", "The left-hand side and right-hand side of the rule have different numbers of inputs or outputs.") + raise ValueError("The left-hand side and right-hand side of the rule have different numbers of inputs or outputs.") return False if not rule.lhs_graph.variable_types and not rule.rhs_graph.variable_types: left_matrix, right_matrix = rule.lhs_graph.to_matrix(), rule.rhs_graph.to_matrix() if not np.allclose(left_matrix, right_matrix): if show_error: - from .dialogs import show_error_msg if np.allclose(left_matrix / np.linalg.norm(left_matrix), right_matrix / np.linalg.norm(right_matrix)): - show_error_msg("Warning!", "The left-hand side and right-hand side of the rule differ by a scalar.") + raise ValueError("The left-hand side and right-hand side of the rule differ by a scalar.") else: - show_error_msg("Warning!", "The left-hand side and right-hand side of the rule have different semantics.") + raise ValueError("The left-hand side and right-hand side of the rule have different semantics.") return False else: if not (rule.rhs_graph.variable_types.items() <= rule.lhs_graph.variable_types.items()): if show_error: - from .dialogs import show_error_msg - show_error_msg("Warning!", "The right-hand side has more free variables than the left-hand side.") + raise ValueError("The right-hand side has more free variables than the left-hand side.") return False for vertex in rule.lhs_graph.vertices(): if isinstance(rule.lhs_graph.phase(vertex), Poly): @@ -346,7 +344,6 @@ def check_rule(rule: CustomRule, show_error: bool = True) -> bool: get_linear(rule.lhs_graph.phase(vertex)) except ValueError as e: if show_error: - from .dialogs import show_error_msg - show_error_msg("Warning!", str(e)) + raise ValueError(f"Error in left-hand side phase: {str(e)}") return False return True diff --git a/zxlive/dialogs.py b/zxlive/dialogs.py index 786defaa..662c9f22 100644 --- a/zxlive/dialogs.py +++ b/zxlive/dialogs.py @@ -76,6 +76,7 @@ class ImportRuleOutput: file_path: str r: CustomRule + def show_error_msg(title: str, description: Optional[str] = None, parent: Optional[QWidget] = None) -> None: """Displays an error message box.""" msg = QMessageBox(parent) #Set the parent of the QMessageBox @@ -289,12 +290,16 @@ def get_file(self: MainWindow, button: QPushButton, side: str) -> None: rewrite_form.addRow(right_button) button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) rewrite_form.addRow(button_box) + def add_rewrite() -> None: nonlocal left_graph, right_graph if left_graph is None or right_graph is None or name.text() == "" or description.toPlainText() == "": return rule = CustomRule(left_graph, right_graph, name.text(), description.toPlainText()) - check_rule(rule, show_error=True) + try: + check_rule(rule, show_error=True) + except Exception as e: + show_error_msg("Warning!", str(e), parent=parent) if save_rule_dialog(rule, parent): dialog.accept() button_box.accepted.connect(add_rewrite) diff --git a/zxlive/mainwindow.py b/zxlive/mainwindow.py index 7e06b5c0..a49baae5 100644 --- a/zxlive/mainwindow.py +++ b/zxlive/mainwindow.py @@ -341,7 +341,10 @@ def handle_save_file_action(self) -> bool: if isinstance(self.active_panel, ProofPanel): data = self.active_panel.proof_model.to_json() elif isinstance(self.active_panel, RulePanel): - check_rule(self.active_panel.get_rule(), show_error=True) + try: + check_rule(self.active_panel.get_rule(), show_error=True) + except Exception as e: + show_error_msg("Warning!", str(e), parent=self) data = self.active_panel.get_rule().to_json() elif self.active_panel.file_type in (FileFormat.QGraph, FileFormat.Json): data = self.active_panel.graph.to_json() @@ -366,7 +369,10 @@ def handle_save_as_action(self) -> bool: if isinstance(self.active_panel, ProofPanel): out = save_proof_dialog(self.active_panel.proof_model, self) elif isinstance(self.active_panel, RulePanel): - check_rule(self.active_panel.get_rule(), show_error=True) + try: + check_rule(self.active_panel.get_rule(), show_error=True) + except Exception as e: + show_error_msg("Warning!", str(e), parent=self) out = save_rule_dialog(self.active_panel.get_rule(), self) else: out = save_diagram_dialog(self.active_panel.graph_scene.g, self) From f9847899961503f643009fbc4cb022a6adb5cc5c Mon Sep 17 00:00:00 2001 From: David Yonge-Mallo Date: Mon, 6 May 2024 22:09:02 +0200 Subject: [PATCH 2/2] From `check_rule`, remove the `show_error` parameter (never used) and the return value (never checked). --- zxlive/custom_rule.py | 25 ++++++++----------------- zxlive/dialogs.py | 2 +- zxlive/mainwindow.py | 4 ++-- 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/zxlive/custom_rule.py b/zxlive/custom_rule.py index 4c0239dc..5a135cf6 100644 --- a/zxlive/custom_rule.py +++ b/zxlive/custom_rule.py @@ -316,34 +316,25 @@ def get_vertex_positions(graph: GraphT, rhs_graph: nx.Graph, boundary_vertex_map return ret -def check_rule(rule: CustomRule, show_error: bool = True) -> bool: +def check_rule(rule: CustomRule) -> None: rule.lhs_graph.auto_detect_io() rule.rhs_graph.auto_detect_io() if len(rule.lhs_graph.inputs()) != len(rule.rhs_graph.inputs()) or \ len(rule.lhs_graph.outputs()) != len(rule.rhs_graph.outputs()): - if show_error: - raise ValueError("The left-hand side and right-hand side of the rule have different numbers of inputs or outputs.") - return False + raise ValueError("The left-hand side and right-hand side of the rule have different numbers of inputs or outputs.") if not rule.lhs_graph.variable_types and not rule.rhs_graph.variable_types: left_matrix, right_matrix = rule.lhs_graph.to_matrix(), rule.rhs_graph.to_matrix() if not np.allclose(left_matrix, right_matrix): - if show_error: - if np.allclose(left_matrix / np.linalg.norm(left_matrix), right_matrix / np.linalg.norm(right_matrix)): - raise ValueError("The left-hand side and right-hand side of the rule differ by a scalar.") - else: - raise ValueError("The left-hand side and right-hand side of the rule have different semantics.") - return False + if np.allclose(left_matrix / np.linalg.norm(left_matrix), right_matrix / np.linalg.norm(right_matrix)): + raise ValueError("The left-hand side and right-hand side of the rule differ by a scalar.") + else: + raise ValueError("The left-hand side and right-hand side of the rule have different semantics.") else: if not (rule.rhs_graph.variable_types.items() <= rule.lhs_graph.variable_types.items()): - if show_error: - raise ValueError("The right-hand side has more free variables than the left-hand side.") - return False + raise ValueError("The right-hand side has more free variables than the left-hand side.") for vertex in rule.lhs_graph.vertices(): if isinstance(rule.lhs_graph.phase(vertex), Poly): try: get_linear(rule.lhs_graph.phase(vertex)) except ValueError as e: - if show_error: - raise ValueError(f"Error in left-hand side phase: {str(e)}") - return False - return True + raise ValueError(f"Error in left-hand side phase: {str(e)}") diff --git a/zxlive/dialogs.py b/zxlive/dialogs.py index 662c9f22..d8ec1d5e 100644 --- a/zxlive/dialogs.py +++ b/zxlive/dialogs.py @@ -297,7 +297,7 @@ def add_rewrite() -> None: return rule = CustomRule(left_graph, right_graph, name.text(), description.toPlainText()) try: - check_rule(rule, show_error=True) + check_rule(rule) except Exception as e: show_error_msg("Warning!", str(e), parent=parent) if save_rule_dialog(rule, parent): diff --git a/zxlive/mainwindow.py b/zxlive/mainwindow.py index a49baae5..cf02ff6a 100644 --- a/zxlive/mainwindow.py +++ b/zxlive/mainwindow.py @@ -342,7 +342,7 @@ def handle_save_file_action(self) -> bool: data = self.active_panel.proof_model.to_json() elif isinstance(self.active_panel, RulePanel): try: - check_rule(self.active_panel.get_rule(), show_error=True) + check_rule(self.active_panel.get_rule()) except Exception as e: show_error_msg("Warning!", str(e), parent=self) data = self.active_panel.get_rule().to_json() @@ -370,7 +370,7 @@ def handle_save_as_action(self) -> bool: out = save_proof_dialog(self.active_panel.proof_model, self) elif isinstance(self.active_panel, RulePanel): try: - check_rule(self.active_panel.get_rule(), show_error=True) + check_rule(self.active_panel.get_rule()) except Exception as e: show_error_msg("Warning!", str(e), parent=self) out = save_rule_dialog(self.active_panel.get_rule(), self)