mirror of
https://gitlab.gnome.org/jwestman/blueprint-compiler.git
synced 2025-05-04 15:59:08 -04:00
language: Fix some issues with menus
Blueprint's handling of menus didn't line up with how GtkBuilder handles them. The root <menu> element must have an ID and may not have attributes, and menus may not be used inline in a property.
This commit is contained in:
parent
93f2a27e35
commit
bbad6988fa
18 changed files with 52 additions and 53 deletions
|
@ -21,11 +21,6 @@ from .values import IdentValue, TranslatedStringValue, FlagsValue, LiteralValue
|
||||||
|
|
||||||
from .common import *
|
from .common import *
|
||||||
|
|
||||||
OBJECT_HOOKS.children = [
|
|
||||||
menu,
|
|
||||||
Object,
|
|
||||||
]
|
|
||||||
|
|
||||||
OBJECT_CONTENT_HOOKS.children = [
|
OBJECT_CONTENT_HOOKS.children = [
|
||||||
Signal,
|
Signal,
|
||||||
Property,
|
Property,
|
||||||
|
|
|
@ -31,6 +31,5 @@ from ..parser_utils import *
|
||||||
from ..xml_emitter import XmlEmitter
|
from ..xml_emitter import XmlEmitter
|
||||||
|
|
||||||
|
|
||||||
OBJECT_HOOKS = AnyOf()
|
|
||||||
OBJECT_CONTENT_HOOKS = AnyOf()
|
OBJECT_CONTENT_HOOKS = AnyOf()
|
||||||
VALUE_HOOKS = AnyOf()
|
VALUE_HOOKS = AnyOf()
|
||||||
|
|
|
@ -44,7 +44,7 @@ class Property(AstNode):
|
||||||
UseIdent("name"),
|
UseIdent("name"),
|
||||||
":",
|
":",
|
||||||
AnyOf(
|
AnyOf(
|
||||||
OBJECT_HOOKS,
|
Object,
|
||||||
VALUE_HOOKS,
|
VALUE_HOOKS,
|
||||||
).expected("a value"),
|
).expected("a value"),
|
||||||
),
|
),
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
|
|
||||||
from .attributes import BaseAttribute
|
from .attributes import BaseAttribute
|
||||||
from .gobject_object import Object, ObjectContent
|
from .gobject_object import Object, ObjectContent
|
||||||
from .ui import UI
|
|
||||||
from .common import *
|
from .common import *
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,6 +30,11 @@ class Menu(Object):
|
||||||
child.emit_xml(xml)
|
child.emit_xml(xml)
|
||||||
xml.end_tag()
|
xml.end_tag()
|
||||||
|
|
||||||
|
@validate("menu")
|
||||||
|
def has_id(self):
|
||||||
|
if self.tokens["tag"] == "menu" and self.tokens["id"] is None:
|
||||||
|
raise CompileError("Menu requires an ID")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def gir_class(self):
|
def gir_class(self):
|
||||||
return self.root.gir.namespaces["Gtk"].lookup_type("Gio.MenuModel")
|
return self.root.gir.namespaces["Gtk"].lookup_type("Gio.MenuModel")
|
||||||
|
@ -39,6 +43,11 @@ class Menu(Object):
|
||||||
class MenuAttribute(BaseAttribute):
|
class MenuAttribute(BaseAttribute):
|
||||||
tag_name = "attribute"
|
tag_name = "attribute"
|
||||||
|
|
||||||
|
@validate()
|
||||||
|
def not_in_menu(self):
|
||||||
|
if self.parent.tokens["tag"] == "menu":
|
||||||
|
raise CompileError("Menu root may not have attributes")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value_type(self):
|
def value_type(self):
|
||||||
return None
|
return None
|
||||||
|
@ -128,16 +137,17 @@ menu_contents.children = [
|
||||||
), "}"),
|
), "}"),
|
||||||
]
|
]
|
||||||
|
|
||||||
menu = Group(
|
menu: Group = Group(
|
||||||
Menu,
|
Menu,
|
||||||
[
|
[
|
||||||
"menu",
|
Keyword("menu"),
|
||||||
UseLiteral("tag", "menu"),
|
UseLiteral("tag", "menu"),
|
||||||
Optional(UseIdent("id")),
|
Optional(UseIdent("id")),
|
||||||
menu_contents
|
menu_contents
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from .ui import UI
|
||||||
|
|
||||||
@completer(
|
@completer(
|
||||||
applies_in=[UI],
|
applies_in=[UI],
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
|
|
||||||
from .. import gir
|
from .. import gir
|
||||||
from .imports import GtkDirective, Import
|
from .imports import GtkDirective, Import
|
||||||
|
from .gtk_menu import menu
|
||||||
|
from .gobject_object import Object
|
||||||
from .gtkbuilder_template import Template
|
from .gtkbuilder_template import Template
|
||||||
from .common import *
|
from .common import *
|
||||||
|
|
||||||
|
@ -32,7 +34,8 @@ class UI(AstNode):
|
||||||
ZeroOrMore(Import),
|
ZeroOrMore(Import),
|
||||||
Until(AnyOf(
|
Until(AnyOf(
|
||||||
Template,
|
Template,
|
||||||
OBJECT_HOOKS,
|
menu,
|
||||||
|
Object,
|
||||||
), Eof()),
|
), Eof()),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ from .errors import MultipleErrors, PrintableError
|
||||||
from .parse_tree import *
|
from .parse_tree import *
|
||||||
from .parser_utils import *
|
from .parser_utils import *
|
||||||
from .tokenizer import TokenType
|
from .tokenizer import TokenType
|
||||||
from .language import OBJECT_HOOKS, OBJECT_CONTENT_HOOKS, VALUE_HOOKS, Template, UI
|
from .language import OBJECT_CONTENT_HOOKS, VALUE_HOOKS, Template, UI
|
||||||
|
|
||||||
|
|
||||||
def parse(tokens) -> T.Tuple[UI, T.Optional[MultipleErrors], T.List[PrintableError]]:
|
def parse(tokens) -> T.Tuple[UI, T.Optional[MultipleErrors], T.List[PrintableError]]:
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
using Gtk 4.0;
|
|
||||||
|
|
||||||
Button {
|
|
||||||
label: menu {};
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
4,3,15,Cannot assign Gio.MenuModel to string
|
|
7
tests/sample_errors/assign_menu.blp
Normal file
7
tests/sample_errors/assign_menu.blp
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
using Gtk 4.0;
|
||||||
|
|
||||||
|
Button {
|
||||||
|
label: my_menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
menu my_menu {}
|
1
tests/sample_errors/assign_menu.err
Normal file
1
tests/sample_errors/assign_menu.err
Normal file
|
@ -0,0 +1 @@
|
||||||
|
4,10,7,Cannot assign Gio.MenuModel to string
|
5
tests/sample_errors/menu_errors.blp
Normal file
5
tests/sample_errors/menu_errors.blp
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
using Gtk 4.0;
|
||||||
|
|
||||||
|
menu {
|
||||||
|
label: "hi";
|
||||||
|
}
|
2
tests/sample_errors/menu_errors.err
Normal file
2
tests/sample_errors/menu_errors.err
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
3,1,4,Menu requires an ID
|
||||||
|
4,3,12,Menu root may not have attributes
|
|
@ -1,5 +0,0 @@
|
||||||
using Gtk 4.0;
|
|
||||||
|
|
||||||
MenuButton {
|
|
||||||
menu-model: menu primary_menu {};
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<interface>
|
|
||||||
<requires lib="gtk" version="4.0"/>
|
|
||||||
<object class="GtkMenuButton">
|
|
||||||
<property name="menu-model">
|
|
||||||
<menu id="primary_menu"></menu>
|
|
||||||
</property>
|
|
||||||
</object>
|
|
||||||
</interface>
|
|
|
@ -1,13 +1,12 @@
|
||||||
using Gtk 4.0;
|
using Gtk 4.0;
|
||||||
|
|
||||||
menu {
|
menu my_menu {
|
||||||
label: _("menu label");
|
section {
|
||||||
test-custom-attribute: 3.1415;
|
label: "test section";
|
||||||
|
}
|
||||||
|
|
||||||
submenu {
|
submenu {
|
||||||
section {
|
label: "test submenu";
|
||||||
label: "test section";
|
|
||||||
}
|
|
||||||
|
|
||||||
item {
|
item {
|
||||||
label: "test item";
|
label: "test item";
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<interface>
|
<interface>
|
||||||
<requires lib="gtk" version="4.0"/>
|
<requires lib="gtk" version="4.0"/>
|
||||||
<menu>
|
<menu id="my_menu">
|
||||||
<attribute name="label" translatable="true">menu label</attribute>
|
<section>
|
||||||
<attribute name="test-custom-attribute">3.1415</attribute>
|
<attribute name="label">test section</attribute>
|
||||||
|
</section>
|
||||||
<submenu>
|
<submenu>
|
||||||
<section>
|
<attribute name="label">test submenu</attribute>
|
||||||
<attribute name="label">test section</attribute>
|
|
||||||
</section>
|
|
||||||
<item>
|
<item>
|
||||||
<attribute name="label">test item</attribute>
|
<attribute name="label">test item</attribute>
|
||||||
</item>
|
</item>
|
||||||
|
@ -25,4 +24,4 @@
|
||||||
</item>
|
</item>
|
||||||
</submenu>
|
</submenu>
|
||||||
</menu>
|
</menu>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
using Gtk 4.0;
|
using Gtk 4.0;
|
||||||
|
|
||||||
menu {
|
menu my_menu {
|
||||||
label: _("menu label");
|
section {
|
||||||
test-custom-attribute: "3.1415";
|
label: "test section";
|
||||||
|
}
|
||||||
|
|
||||||
submenu {
|
submenu {
|
||||||
section {
|
label: "test submenu";
|
||||||
label: "test section";
|
|
||||||
}
|
|
||||||
|
|
||||||
item {
|
item {
|
||||||
label: "test item";
|
label: "test item";
|
||||||
|
|
|
@ -124,7 +124,6 @@ class TestSamples(unittest.TestCase):
|
||||||
self.assert_sample("file_filter")
|
self.assert_sample("file_filter")
|
||||||
self.assert_sample("flags")
|
self.assert_sample("flags")
|
||||||
self.assert_sample("id_prop")
|
self.assert_sample("id_prop")
|
||||||
self.assert_sample("inline_menu")
|
|
||||||
self.assert_sample("layout")
|
self.assert_sample("layout")
|
||||||
self.assert_sample("menu")
|
self.assert_sample("menu")
|
||||||
self.assert_sample("object_prop")
|
self.assert_sample("object_prop")
|
||||||
|
@ -147,7 +146,7 @@ class TestSamples(unittest.TestCase):
|
||||||
self.assert_sample_error("a11y_prop_dne")
|
self.assert_sample_error("a11y_prop_dne")
|
||||||
self.assert_sample_error("a11y_prop_obj_dne")
|
self.assert_sample_error("a11y_prop_obj_dne")
|
||||||
self.assert_sample_error("a11y_prop_type")
|
self.assert_sample_error("a11y_prop_type")
|
||||||
self.assert_sample_error("assign_inline_menu")
|
self.assert_sample_error("assign_menu")
|
||||||
self.assert_sample_error("action_widget_float_response")
|
self.assert_sample_error("action_widget_float_response")
|
||||||
self.assert_sample_error("action_widget_have_no_id")
|
self.assert_sample_error("action_widget_have_no_id")
|
||||||
self.assert_sample_error("action_widget_multiple_default")
|
self.assert_sample_error("action_widget_multiple_default")
|
||||||
|
@ -165,6 +164,7 @@ class TestSamples(unittest.TestCase):
|
||||||
self.assert_sample_error("filters_in_non_file_filter")
|
self.assert_sample_error("filters_in_non_file_filter")
|
||||||
self.assert_sample_error("invalid_bool")
|
self.assert_sample_error("invalid_bool")
|
||||||
self.assert_sample_error("layout_in_non_widget")
|
self.assert_sample_error("layout_in_non_widget")
|
||||||
|
self.assert_sample_error("menu_errors")
|
||||||
self.assert_sample_error("ns_not_imported")
|
self.assert_sample_error("ns_not_imported")
|
||||||
self.assert_sample_error("not_a_class")
|
self.assert_sample_error("not_a_class")
|
||||||
self.assert_sample_error("object_dne")
|
self.assert_sample_error("object_dne")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue