From 4103ad3e71cef3d5cdc8f907af0f5606565f1c66 Mon Sep 17 00:00:00 2001 From: Gleb Smirnov Date: Sat, 19 Feb 2022 12:51:34 +0300 Subject: [PATCH] fix: allow adding action widgets to GtkInfoBar --- blueprintcompiler/language/gobject_object.py | 6 ++-- .../language/gtkbuilder_child.py | 2 +- .../{gtk_dialog.py => response_id.py} | 31 ++++++++++++++----- ...=> action_widget_in_invalid_container.blp} | 0 .../action_widget_in_invalid_container.err | 1 + .../action_widget_not_in_dialog.err | 1 - tests/samples/action_widgets.blp | 7 +++++ tests/samples/action_widgets.ui | 10 ++++++ tests/test_samples.py | 2 +- 9 files changed, 47 insertions(+), 13 deletions(-) rename blueprintcompiler/language/{gtk_dialog.py => response_id.py} (82%) rename tests/sample_errors/{action_widget_not_in_dialog.blp => action_widget_in_invalid_container.blp} (100%) create mode 100644 tests/sample_errors/action_widget_in_invalid_container.err delete mode 100644 tests/sample_errors/action_widget_not_in_dialog.err diff --git a/blueprintcompiler/language/gobject_object.py b/blueprintcompiler/language/gobject_object.py index f4b760a..f5dbc12 100644 --- a/blueprintcompiler/language/gobject_object.py +++ b/blueprintcompiler/language/gobject_object.py @@ -19,7 +19,7 @@ import typing as T -from .gtk_dialog import ResponseId +from .response_id import ResponseId from .common import * @@ -83,9 +83,9 @@ class Object(AstNode): @property def action_widgets(self) -> T.List[ResponseId]: - """Get list of `GtkDialog`'s action widgets. + """Get list of widget's action widgets. - Empty if object is not `GtkDialog`. + Empty if object doesn't have action widgets. """ from .gtkbuilder_child import Child diff --git a/blueprintcompiler/language/gtkbuilder_child.py b/blueprintcompiler/language/gtkbuilder_child.py index 6bda160..9e5be1b 100644 --- a/blueprintcompiler/language/gtkbuilder_child.py +++ b/blueprintcompiler/language/gtkbuilder_child.py @@ -21,7 +21,7 @@ from functools import cache from .gobject_object import Object -from .gtk_dialog import ResponseId +from .response_id import ResponseId from .common import * diff --git a/blueprintcompiler/language/gtk_dialog.py b/blueprintcompiler/language/response_id.py similarity index 82% rename from blueprintcompiler/language/gtk_dialog.py rename to blueprintcompiler/language/response_id.py index 2656a25..6a2f530 100644 --- a/blueprintcompiler/language/gtk_dialog.py +++ b/blueprintcompiler/language/response_id.py @@ -1,4 +1,4 @@ -# gtk_dialog.py +# response_id.py # # Copyright 2022 Gleb Smirnov # @@ -18,11 +18,18 @@ # SPDX-License-Identifier: LGPL-3.0-or-later +import typing as T + from .common import * class ResponseId(AstNode): - """Response ID of GtkDialog's action widget.""" + """Response ID of action widget.""" + + ALLOWED_PARENTS: T.List[T.Tuple[str, str]] = [ + ("Gtk", "Dialog"), + ("Gtk", "InfoBar") + ] grammar = [ UseIdent("response"), @@ -44,11 +51,21 @@ class ResponseId(AstNode): raise CompileError(f"Only action widget can have response ID") @validate() - def parent_is_dialog(self) -> None: - """Chech that parent widget is `GtkDialog`.""" - from .gobject_object import validate_parent_type + def parent_has_action_widgets(self) -> None: + """Chech that parent widget has allowed type.""" + from .gobject_object import Object - validate_parent_type(self, "Gtk", "Dialog", "action widgets") + container_type = self.parent_by_type(Object).gir_class + gir = self.root.gir + + for namespace, name in ResponseId.ALLOWED_PARENTS: + parent_type = gir.get_type(name, namespace) + if container_type.assignable_to(parent_type): + break + else: + raise CompileError( + f"{container_type.full_name} doesn't have action widgets" + ) @validate() def widget_have_id(self) -> None: @@ -121,7 +138,7 @@ class ResponseId(AstNode): Must be called while tag is open. - For more details see `GtkDialog` docs. + For more details see `GtkDialog` and `GtkInfoBar` docs. """ xml.start_tag( "action-widget", diff --git a/tests/sample_errors/action_widget_not_in_dialog.blp b/tests/sample_errors/action_widget_in_invalid_container.blp similarity index 100% rename from tests/sample_errors/action_widget_not_in_dialog.blp rename to tests/sample_errors/action_widget_in_invalid_container.blp diff --git a/tests/sample_errors/action_widget_in_invalid_container.err b/tests/sample_errors/action_widget_in_invalid_container.err new file mode 100644 index 0000000..20950a1 --- /dev/null +++ b/tests/sample_errors/action_widget_in_invalid_container.err @@ -0,0 +1 @@ +4,13,11,Gtk.Box doesn't have action widgets diff --git a/tests/sample_errors/action_widget_not_in_dialog.err b/tests/sample_errors/action_widget_not_in_dialog.err deleted file mode 100644 index 42ceff4..0000000 --- a/tests/sample_errors/action_widget_not_in_dialog.err +++ /dev/null @@ -1 +0,0 @@ -4,13,11,Gtk.Box is not a Gtk.Dialog, so it doesn't have action widgets diff --git a/tests/samples/action_widgets.blp b/tests/samples/action_widgets.blp index 7fb673c..09109bb 100644 --- a/tests/samples/action_widgets.blp +++ b/tests/samples/action_widgets.blp @@ -16,3 +16,10 @@ Dialog { label: _("Ok"); } } + +InfoBar { + [action response=ok] + Button ok_info_button { + label: _("Ok"); + } +} diff --git a/tests/samples/action_widgets.ui b/tests/samples/action_widgets.ui index ca26a5b..91b6e64 100644 --- a/tests/samples/action_widgets.ui +++ b/tests/samples/action_widgets.ui @@ -23,4 +23,14 @@ ok_button + + + + Ok + + + + ok_info_button + + diff --git a/tests/test_samples.py b/tests/test_samples.py index f4c4787..5b383f7 100644 --- a/tests/test_samples.py +++ b/tests/test_samples.py @@ -150,7 +150,7 @@ class TestSamples(unittest.TestCase): self.assert_sample_error("action_widget_have_no_id") self.assert_sample_error("action_widget_multiple_default") self.assert_sample_error("action_widget_not_action") - self.assert_sample_error("action_widget_not_in_dialog") + self.assert_sample_error("action_widget_in_invalid_container") self.assert_sample_error("action_widget_response_dne") self.assert_sample_error("action_widget_negative_response") self.assert_sample_error("class_assign")