Compare commits

...

17 commits

Author SHA1 Message Date
Megadash452
33c8ad03db Merge branch 'main' into 'main'
Draft: Created Tutorial page; TODOs pending.

See merge request GNOME/blueprint-compiler!66
2025-06-03 13:55:55 +00:00
James Westman
5c7fb03da7 Fix incorrect error with Adw.AlertDialog responses 2025-05-07 17:08:26 -05:00
James Westman
2e42dc6848
decompiler: Fix bug in signals with template object
If a signal handler had the template as its object, the decompiler would
output the class name instead of the 'template' keyword.
2025-05-03 07:46:34 -05:00
James Westman
a12d3f5c81
decompile: Fix bug in lookup tags
A lookup tag with no type attribute would crash the decompiler, even if
that was valid. This wasn't caught by the tests since blueprint never
generates such XML.

Also fixed a bug in the tests that caused decompiler-only tests not to
run.
2025-04-25 20:13:01 -05:00
James Westman
a83c7e936d
black: Update formatting 2025-04-25 18:32:33 -05:00
James Westman
3816f4fe8d
Add .doap file 2025-04-25 18:29:55 -05:00
James Westman
e9d61cb6f9
Update URLs after move to GNOME namespace on GitLab 2025-04-25 18:29:55 -05:00
FeRD (Frank Dana)
e1f972ef16 Apply 5 suggestion(s) to 1 file(s) 2022-10-19 14:00:09 +00:00
Megadash452
13e477aa25 Tutorial: Fixed a broken link, and some other tweaks. 2022-10-19 12:39:14 +00:00
FeRD (Frank Dana)
ba8ec80456 Apply 6 suggestion(s) to 1 file(s) 2022-10-19 12:04:47 +00:00
Megadash452
0fe58ffc37 Tutorial: Fixed .rst rendering issues 2022-10-19 02:30:23 +00:00
Megadash452
14d1892254 Tutorial: added doc for binding flag no-sync-create 2022-10-19 02:24:20 +00:00
Megadash452
c74c5ac232 Tutorial: changed terminology *name* to *id* 2022-10-19 02:22:51 +00:00
FeRD (Frank Dana)
9e293a31e6 Apply 1 suggestion(s) to 1 file(s) 2022-10-19 01:45:33 +00:00
FeRD (Frank Dana)
cce1af5f09 Apply 6 suggestion(s) to 1 file(s) 2022-10-19 01:32:19 +00:00
FeRD (Frank Dana)
4dd55ab2aa Apply 1 suggestion(s) to 1 file(s) 2022-10-19 01:19:44 +00:00
Megadash452
52e651a168 Created Tutorial page; TODOs pending. 2022-10-02 15:23:48 +00:00
22 changed files with 623 additions and 30 deletions

View file

@ -3,7 +3,7 @@ stages:
- pages - pages
build: build:
image: registry.gitlab.gnome.org/jwestman/blueprint-compiler image: registry.gitlab.gnome.org/gnome/blueprint-compiler
stage: build stage: build
script: script:
- black --check --diff ./ tests - black --check --diff ./ tests
@ -33,7 +33,7 @@ build:
path: coverage.xml path: coverage.xml
fuzz: fuzz:
image: registry.gitlab.gnome.org/jwestman/blueprint-compiler image: registry.gitlab.gnome.org/gnome/blueprint-compiler
stage: build stage: build
script: script:
- meson _build - meson _build

27
blueprint-compiler.doap Normal file
View file

@ -0,0 +1,27 @@
<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:gnome="http://api.gnome.org/doap-extensions#"
xmlns="http://usefulinc.com/ns/doap#">
<name xml:lang="en">Blueprint</name>
<shortdesc xml:lang="en">A modern language for creating GTK interfaces</shortdesc>
<description xml:lang="en">Blueprint is a language and associated tooling for building user interfaces for GTK.</description>
<category rdf:resource="http://api.gnome.org/doap-extensions#apps" />
<programming-language>Python</programming-language>
<homepage
rdf:resource="https://gnome.gitlab.gnome.org/blueprint-compiler/" />
<download-page
rdf:resource="https://gitlab.gnome.org/GNOME/blueprint-compiler/-/releases" />
<bug-database
rdf:resource="https://gitlab.gnome.org/GNOME/blueprint-compiler/issues" />
<maintainer>
<foaf:Person>
<foaf:name>James Westman</foaf:name>
<foaf:mbox rdf:resource="mailto:james@jwestman.net" />
<gnome:userid>jwestman</gnome:userid>
</foaf:Person>
</maintainer>
</Project>

View file

@ -255,7 +255,11 @@ def decompile_element(
ctx._node_stack.append(xml) ctx._node_stack.append(xml)
ctx.start_block() ctx.start_block()
gir = decompiler(*args, **kwargs)
try:
gir = decompiler(*args, **kwargs)
except TypeError as e:
raise UnsupportedError(tag=xml.tag)
if not decompiler._skip_children: if not decompiler._skip_children:
for child in xml.children: for child in xml.children:
@ -266,8 +270,6 @@ def decompile_element(
except UnsupportedError as e: except UnsupportedError as e:
raise e raise e
except TypeError as e:
raise UnsupportedError(tag=xml.tag)
def decompile(data: str) -> str: def decompile(data: str) -> str:

View file

@ -219,7 +219,7 @@ def report_bug(): # pragma: no cover
f"""{Colors.BOLD}{Colors.RED}***** COMPILER BUG ***** f"""{Colors.BOLD}{Colors.RED}***** COMPILER BUG *****
The blueprint-compiler program has crashed. Please report the above stacktrace, The blueprint-compiler program has crashed. Please report the above stacktrace,
along with the input file(s) if possible, on GitLab: along with the input file(s) if possible, on GitLab:
{Colors.BOLD}{Colors.BLUE}{Colors.UNDERLINE}https://gitlab.gnome.org/jwestman/blueprint-compiler/-/issues/new?issue {Colors.BOLD}{Colors.BLUE}{Colors.UNDERLINE}https://gitlab.gnome.org/GNOME/blueprint-compiler/-/issues/new?issue
{Colors.CLEAR}""" {Colors.CLEAR}"""
) )

View file

@ -71,7 +71,7 @@ def decompile_file(in_file, out_file) -> T.Union[str, CouldNotPort]:
print( print(
f"""{Colors.FAINT}Either the original XML file had an error, or there is a bug in the f"""{Colors.FAINT}Either the original XML file had an error, or there is a bug in the
porting tool. If you think it's a bug (which is likely), please file an issue on GitLab: porting tool. If you think it's a bug (which is likely), please file an issue on GitLab:
{Colors.BLUE}{Colors.UNDERLINE}https://gitlab.gnome.org/jwestman/blueprint-compiler/-/issues/new?issue{Colors.CLEAR}\n""" {Colors.BLUE}{Colors.UNDERLINE}https://gitlab.gnome.org/GNOME/blueprint-compiler/-/issues/new?issue{Colors.CLEAR}\n"""
) )
return CouldNotPort("does not compile") return CouldNotPort("does not compile")
@ -136,7 +136,7 @@ def step1():
wrap.write( wrap.write(
f"""[wrap-git] f"""[wrap-git]
directory = blueprint-compiler directory = blueprint-compiler
url = https://gitlab.gnome.org/jwestman/blueprint-compiler.git url = https://gitlab.gnome.org/GNOME/blueprint-compiler.git
revision = {VERSION} revision = {VERSION}
depth = 1 depth = 1

View file

@ -60,19 +60,21 @@ class ScopeCtx:
passed = {} passed = {}
for obj in self._iter_recursive(self.node): for obj in self._iter_recursive(self.node):
if obj.tokens["id"] is None: from .gtk_menu import Menu
if not (isinstance(obj, Object) or isinstance(obj, Menu)) or obj.id is None:
continue continue
if obj.tokens["id"] in passed: if obj.id in passed:
token = obj.group.tokens["id"] token = obj.group.tokens["id"]
if not isinstance(obj, Template) and not isinstance( if not isinstance(obj, Template) and not isinstance(
obj, ExtListItemFactory obj, ExtListItemFactory
): ):
raise CompileError( raise CompileError(
f"Duplicate object ID '{obj.tokens['id']}'", f"Duplicate object ID '{obj.id}'",
token.range, token.range,
) )
passed[obj.tokens["id"]] = obj passed[obj.id] = obj
def _iter_recursive(self, node: AstNode): def _iter_recursive(self, node: AstNode):
yield node yield node

View file

@ -302,12 +302,18 @@ expr.children = [
@decompiler("lookup", skip_children=True, cdata=True) @decompiler("lookup", skip_children=True, cdata=True)
def decompile_lookup( def decompile_lookup(
ctx: DecompileCtx, gir: gir.GirContext, cdata: str, name: str, type: str ctx: DecompileCtx,
gir: gir.GirContext,
cdata: str,
name: str,
type: T.Optional[str] = None,
): ):
if ctx.parent_node is not None and ctx.parent_node.tag == "property": if ctx.parent_node is not None and ctx.parent_node.tag == "property":
ctx.print("expr ") ctx.print("expr ")
if t := ctx.type_by_cname(type): if type is None:
type = ""
elif t := ctx.type_by_cname(type):
type = decompile.full_name(t) type = decompile.full_name(t)
else: else:
type = "$" + type type = "$" + type
@ -327,7 +333,7 @@ def decompile_lookup(
if constant == ctx.template_class: if constant == ctx.template_class:
ctx.print("template." + name) ctx.print("template." + name)
elif constant == "": elif constant == "":
ctx.print("item as <" + type + ">." + name) ctx.print(f"item as <{type}>.{name}")
else: else:
ctx.print(constant + "." + name) ctx.print(constant + "." + name)
return return

View file

@ -225,8 +225,14 @@ class Signal(AstNode):
@decompiler("signal") @decompiler("signal")
def decompile_signal(ctx, gir, name, handler, swapped=None, after="false", object=None): def decompile_signal(
ctx: DecompileCtx, gir, name, handler, swapped=None, after="false", object=None
):
object_name = object or "" object_name = object or ""
if object_name == ctx.template_class:
object_name = "template"
name = name.replace("_", "-") name = name.replace("_", "-")
line = f"{name} => ${handler}({object_name})" line = f"{name} => ${handler}({object_name})"

View file

@ -17,7 +17,7 @@
# #
# SPDX-License-Identifier: LGPL-3.0-or-later # SPDX-License-Identifier: LGPL-3.0-or-later
""" Utilities for parsing an AST from a token stream. """ """Utilities for parsing an AST from a token stream."""
import typing as T import typing as T
from enum import Enum from enum import Enum

View file

@ -9,7 +9,7 @@ from pathlib import Path
__all__ = ["get_docs_section"] __all__ = ["get_docs_section"]
DOCS_ROOT = "https://jwestman.pages.gitlab.gnome.org/blueprint-compiler" DOCS_ROOT = "https://gnome.pages.gitlab.gnome.org/blueprint-compiler"
sections: dict[str, "Section"] = {} sections: dict[str, "Section"] = {}

View file

@ -16,7 +16,7 @@ a module in your flatpak manifest:
"sources": [ "sources": [
{ {
"type": "git", "type": "git",
"url": "https://gitlab.gnome.org/jwestman/blueprint-compiler", "url": "https://gitlab.gnome.org/GNOME/blueprint-compiler",
"tag": "v0.16.0" "tag": "v0.16.0"
} }
] ]

View file

@ -59,7 +59,7 @@ Features
Links Links
----- -----
- `Source code <https://gitlab.gnome.org/jwestman/blueprint-compiler>`_ - `Source code <https://gitlab.gnome.org/GNOME/blueprint-compiler>`_
- `Workbench <https://github.com/sonnyp/Workbench>`_ lets you try, preview and export Blueprint - `Workbench <https://github.com/sonnyp/Workbench>`_ lets you try, preview and export Blueprint
- `GNOME Builder <https://developer.gnome.org/documentation/introduction/builder.html>`_ provides builtin support - `GNOME Builder <https://developer.gnome.org/documentation/introduction/builder.html>`_ provides builtin support
- `Vim syntax highlighting plugin by thetek42 <https://github.com/thetek42/vim-blueprint-syntax>`_ - `Vim syntax highlighting plugin by thetek42 <https://github.com/thetek42/vim-blueprint-syntax>`_

View file

@ -10,7 +10,7 @@ Properties are the main way to set values on objects, but they are limited by th
Extensions are a feature of ``Gtk.Buildable``--see `Gtk.Buildable.custom_tag_start() <https://docs.gtk.org/gtk4/vfunc.Buildable.custom_tag_start.html>`_ for internal details. Extensions are a feature of ``Gtk.Buildable``--see `Gtk.Buildable.custom_tag_start() <https://docs.gtk.org/gtk4/vfunc.Buildable.custom_tag_start.html>`_ for internal details.
Because they aren't part of the type system, they aren't present in typelib files like properties and signals are. Therefore, if a library adds a new extension, syntax for it must be added to Blueprint manually. If there's a commonly used extension that isn't supported by Blueprint, please `file an issue <https://gitlab.gnome.org/jwestman/blueprint-compiler/-/issues>`_. Because they aren't part of the type system, they aren't present in typelib files like properties and signals are. Therefore, if a library adds a new extension, syntax for it must be added to Blueprint manually. If there's a commonly used extension that isn't supported by Blueprint, please `file an issue <https://gitlab.gnome.org/GNOME/blueprint-compiler/-/issues>`_.
.. rst-class:: grammar-block .. rst-class:: grammar-block

View file

@ -8,7 +8,7 @@ Setting up Blueprint on a new or existing project
Using the porting tool Using the porting tool
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
Clone `blueprint-compiler <https://gitlab.gnome.org/jwestman/blueprint-compiler>`_ Clone `blueprint-compiler <https://gitlab.gnome.org/GNOME/blueprint-compiler>`_
from source. You can install it using ``meson _build`` and ``ninja -C _build install``, from source. You can install it using ``meson _build`` and ``ninja -C _build install``,
or you can leave it uninstalled. or you can leave it uninstalled.
@ -29,7 +29,7 @@ blueprint-compiler works as a meson subproject.
[wrap-git] [wrap-git]
directory = blueprint-compiler directory = blueprint-compiler
url = https://gitlab.gnome.org/jwestman/blueprint-compiler.git url = https://gitlab.gnome.org/GNOME/blueprint-compiler.git
revision = main revision = main
depth = 1 depth = 1

481
docs/tutorial.rst Normal file
View file

@ -0,0 +1,481 @@
========
Tutorial
========
.. margin at column 75
Read this if you want to learn how to use Blueprint and never used
the XML syntax that can be read by GtkBuilder.
For compatibility with Blueprint IDE extensions, blueprint files
should end with ``.blp``.
Namespaces
----------
Blueprint needs the widget library to be imported. These include Gtk,
Libadwaita, Shumate, etc. To import a namespace, write ``using`` followed
by the library and version number.
.. code-block::
using Gtk 4.0;
using Adw 1;
The Gtk import is required in all blueprints and the minor version
number must be 0.
Comments
--------
Blueprint has inline or multi-line comments
.. code-block::
// This is an inline comment
/* This is
a multiline
comment */
Multi-line comments can't have inner multi-line comments. The compiler
will interpret the inner comment's closing token as the outer comment's
closing token. For example, the following will not compile:
.. code-block::
// Bad comment below:
/* Outer comment
/* Inner comment */
*/
Widgets
-------
Create widgets in the following format:
.. code-block::
Namespace.WidgetClass {
}
The Gtk namespace is implied for widgets, so you can just write the
widget class
.. code-block::
Box {
}
Other namespaces must be written explicitly.
.. code-block::
Adw.Leaflet {
}
Consult the widget library's documentation for a list of widgets.
A good place to start is
`the Gtk4 widget list <https://docs.gtk.org/gtk4/index.html>`_.
Naming Widgets
~~~~~~~~~~~~~~
Widgets can be given a **name/ID** so that they can be referenced by your
program or other widgets in the blueprint.
.. code-block::
Namespace.WidgetClass widget_id {
}
Any time you want to use this widget as a property (more about that in the
next section) or something else, write the widget's **ID** (e.g.
``main_window``).
Properties
----------
Every widget has properties defined by their GObject class.
For example, the Libadwaita documentation lists the
`properties of the Toast class <https://gnome.pages.gitlab.gnome.org/libadwaita/doc/1.2/class.Toast.html#properties>`_.
Write properties inside the curly brackets of a widget:
.. code-block::
Namespace.WidgetClass {
property-name: value;
}
Properties values are *all lowercase* (except strings) and must end with a
semicolon (``;``).
Property Types
~~~~~~~~~~~~~~
These are the **types** of values that can be used in properties:
- Booleans: ``true``, ``false``
- Numbers: e.g. ``1``, ``1.5``, ``-2``, ``-2.5``
- Strings (single- or double-quoted): e.g. ``"a string"``, ``'another string'``
- Enums
- Widgets
Properties are **strongly typed**, so you can't use, for example, a string
for the orientation property, which requires an ``Orientation`` enum
vartiant as its value.
Enum Properties
~~~~~~~~~~~~~~~
In the Gtk documentation, enum variants have long names and are
capitalized. For example, these are the
`Orientation <https://docs.gtk.org/gtk4/enum.Orientation.html>`_
enum variants:
- GTK_ORIENTATION_HORIZONTAL
- GTK_ORIENTATION_VERTICAL
In the blueprint, you would only write the *variant* part of the enum in
*lowercase*, just like you would in the XML.
.. code-block::
Box {
orientation: horizontal;
}
Widget Properties
~~~~~~~~~~~~~~~~~
Some widgets take other widgets as properties. For example, the
``Gtk.StackSidebar`` has a stack property which takes a ``Gtk.Stack`` widget.
You can create a new widget for the value, or you can reference another
widget by its **ID**.
.. code-block::
StackSidebar {
stack: Stack { };
}
OR
.. code-block::
StackSidebar {
stack: my_stack;
}
Stack my_stack {
}
Note the use of a semicolon at the end of the property in both cases.
Inline widget properties are not exempt of this rule.
Property Bindings
-----------------
If you want a widget's property to have the same value as another widget's
property (without hard-coding the value), you could ``bind`` two widgets'
properties of the same type. Bindings must reference a *source* widget by
**ID**. As long as the two properties have the same type, you can bind
properties of different names and of widgets with different widget classes.
.. code-block::
Box my_box {
halign: fill; // Source
}
Button {
valign: bind my_box.halign; // Target
}
Binding Flags
~~~~~~~~~~~~~
Modify the behavior of bindings with flags. Flags are written after the
binding. The default behavior is that the *Target*'s value will be
changed to the *Source*'s value when the binding is created and when the
*Source* value changes.
.. code-block::
Box my_box {
hexpand: true; // Source
}
Button {
vexpand: bind my_box.hexpand inverted bidirectional; // Target
}
no-sync-create
Prevent setting the *Tartget* with the *Source*'s value,
updating the target value when the *Source* value changes, not when
the binding is first created. Useful when the *Target* property has
another initial value that is not the *Source* value.
bidirectional
When either the *Source* or *Target* value is modified, the other's
value will be updated. For example, if the logic of the program
changes the Button's vexpand value to ``false``, then the Box's halign
value will also be updated to ``false``.
inverted
If the property is a boolean, the value of the bind can be negated
with this flag. For example, if the Box's hexpand property is ``true``,
the Button's vexpand property will be ``false`` in the code above.
Signals
-------
Gtk allows you to register signals in your program. This can be done by
getting the object from the GtkBuilder and connecting a handler to the
signal. Or register the handler with the application and reference it in
the blueprint.
Signals have an *event name*, a *handler* (aka callback), and optionally
some *flags*. Each widget will have a set of defined signals. Consult the
widget's documentation for a list of its signals.
To register a handler with the application, consult the documentation for
your language's bindings of Gtk.
.. code-block::
WidgetClass {
event_name => handler_name() flags;
}
.. TODO: add a list of flags and their descriptions
By default, signals in the blueprint will pass the widget that the signal
is for as an argument to the *handler*. However, you can specify the
widget that is passed to the handler by referencing its **ID** inside the
parenthesis.
.. code-block::
Label my_label {
label: "Hide me";
}
Button {
clicked => hide_widget(my_label);
}
Custom Widget Classes
---------------------
Some programs have custom widgets defined in their logic, so blueprint
won't know that they exist. Writing widgets not defined in the GIR will
result in an error. Prepend a custom widget with a period (``.``) to prevent the
compiler from trying to validate the widget. This is essentially saying
the widget has no *namespace*.
To register a custom widget with the application consult the documentation
for your language's bindings of Gtk.
.. code-block::
.MyCustomWidget {
}
Templates
---------
.. TODO
CSS Style Classes
-----------------
.. TODO: Unsure if to group styles with widget-specific items
Widgets can be given style classes that can be used with your CSS or
`predefined styles <https://gnome.pages.gitlab.gnome.org/libadwaita/doc/1.2/style-classes.html>`_
in libraries like Libadwaita.
.. code-block::
Button {
label: "Click me";
styles ["my-style", "pill"]
}
Note the lack of a *colon* after "styles" and a *semicolon* at the end of
the line. This syntax looks like the properties syntax, but it compiles to
XML completely different from properties.
Consult your language's bindings of Gtk to use a CSS file.
Non-property Elements
~~~~~~~~~~~~~~~~~~~~~
Some widgets will have elements which are not properties, but they sort
of act like properties. Most of the time they will be specific only to a
certain widget. *Styles* is one of these elements, except that styles can
be used for any widget. Similar to how every widget has styles,
``Gtk.ComboBoxText`` has *items*:
.. code-block::
Gtk.ComboBoxText {
items [
item1: "Item 1",
item2: _("Items can be translated"),
"The item ID is not required",
]
}
See :doc:`examples <examples#widget-specific-items>` for a list of more of these
widget-specific items.
Menus
-----
Menus are usually the widgets that are placed along the top-bar of a
window, or pop up when you right-click some other widget. In Blueprint, a
``menu`` is a ``Gio.MenuModel`` that can be shown by MenuButtons or other
widgets.
In Blueprint, a ``menu`` can have *items*, *sections*, and *submenus*.
Like widgets, a ``menu`` can also be given an **ID**.
The `Menu Model section of the Gtk.PopoverMenu documentation <https://docs.gtk.org/gtk4/class.PopoverMenu.html#menu-models>`_
has complete details on the menu model.
Here is an example of a menu:
.. code-block::
menu my_menu {
section {
label: "File";
item {
label: "Open";
action: "win.open";
icon-name: "document-open-symbolic";
}
item {
label: "Save";
action: "win.save";
icon-name: "document-save-symbolic";
}
submenu {
label: "Save As";
icon-name: "document-save-as-symbolic";
item {
label: "PDF";
action: "win.save_as_pdf";
}
}
}
}
There is a shorthand for *items*. Items require at least a label. The
action and icon-name are optional.
.. code-block::
menu {
item ( "Item 2" )
item ( "Item 2", "app.action", "icon-name" )
}
A widget that uses a ``menu`` is ``Gtk.MenuButton``. It has the *menu-model*
property, which takes a menu. Write the menu at the root of the blueprint
(meaning not inside any widgets) and reference it by **ID**.
.. code-block::
MenuButton {
menu-model: my_menu;
}
Child Types
-----------
Child types describe how a child widget is placed on a parent widget. For
example, HeaderBar widgets can have children placed either at the *start*
or the *end* of the HeaderBar. Child widgets of HeaderBars can have the
*start* or *end* types. Values for child types a widget can have are
defined in the widget's documentation.
Child types in blueprint are written between square brackets (``[`` ``]``) and before
the child the type is for.
The following blueprint code...
.. code-block::
HeaderBar {
[start]
Button {
label: "Button";
}
}
\... would look like this:
.. code-block::
---------------------------
| Button |
---------------------------
And the following blueprint code...
.. code-block::
HeaderBar {
[end]
Button {
label: "Button";
}
}
\... would look like this:
.. code-block::
---------------------------
| Button |
---------------------------
Translatable Strings
--------------------
Mark any string as translatable using this syntax: ``_("...")``.
Two strings that are the same in English could be translated in different
ways in other languages because of different *contexts*. Translatable
strings with context look like this: ``C_("context", "...")``. An example
where a context is needed is the word "have", which in Spanish could
translate to "tener" or "haber".
.. code-block::
Label {
label: C_("1st have", "have");
}
Label {
label: C_("2nd have", "have");
}
See `translations <translations.html>`_ for more details.

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<template class="GtkListItem">
<property name="child">
<object class="GtkLabel">
<binding name="label">
<lookup type="RecentObject" name="filename">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</property>
</template>
</interface>

View file

@ -0,0 +1,7 @@
using Gtk 4.0;
template ListItem {
child: Label {
label: bind template.item as <$RecentObject>.filename;
};
}

View file

@ -0,0 +1,11 @@
using Gtk 4.0;
using Adw 1;
Adw.AlertDialog dialog1 {
responses [
ok: "Ok",
cancel: "Cancel",
]
}
Button cancel {}

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
DO NOT EDIT!
This file was @generated by blueprint-compiler. Instead, edit the
corresponding .blp file and regenerate this file with blueprint-compiler.
-->
<interface>
<requires lib="gtk" version="4.0"/>
<object class="AdwAlertDialog" id="dialog1">
<responses>
<response id="ok">Ok</response>
<response id="cancel">Cancel</response>
</responses>
</object>
<object class="GtkButton" id="cancel"></object>
</interface>

View file

@ -0,0 +1,7 @@
using Gtk 4.0;
template $MyTemplate {
Button {
clicked => $my_signal_handler(template);
}
}

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
DO NOT EDIT!
This file was @generated by blueprint-compiler. Instead, edit the
corresponding .blp file and regenerate this file with blueprint-compiler.
-->
<interface>
<requires lib="gtk" version="4.0"/>
<template class="MyTemplate">
<child>
<object class="GtkButton">
<signal name="clicked" handler="my_signal_handler" object="MyTemplate"/>
</object>
</child>
</template>
</interface>

View file

@ -181,11 +181,7 @@ class TestSamples(unittest.TestCase):
def test_samples(self): def test_samples(self):
# list the samples directory # list the samples directory
samples = [ samples = [f.stem for f in Path(__file__).parent.glob("samples/*.blp")]
f.stem
for f in Path(__file__).parent.glob("samples/*.blp")
if not f.stem.endswith("_dec")
]
samples.sort() samples.sort()
for sample in samples: for sample in samples:
REQUIRE_ADW_1_4 = ["adw_breakpoint"] REQUIRE_ADW_1_4 = ["adw_breakpoint"]
@ -202,6 +198,7 @@ class TestSamples(unittest.TestCase):
"parseable", "parseable",
"signal", "signal",
"signal_not_swapped", "signal_not_swapped",
"signal_template_object",
"template", "template",
"template_binding", "template_binding",
"template_binding_extern", "template_binding_extern",
@ -215,7 +212,7 @@ class TestSamples(unittest.TestCase):
] ]
# Decompiler-only tests # Decompiler-only tests
SKIP_COMPILE = ["issue_177", "translator_comments"] SKIP_COMPILE = ["issue_177", "issue_187", "translator_comments"]
SKIP_DECOMPILE = [ SKIP_DECOMPILE = [
# Comments are not preserved in either direction # Comments are not preserved in either direction
@ -228,7 +225,7 @@ class TestSamples(unittest.TestCase):
continue continue
with self.subTest(sample): with self.subTest(sample):
if sample not in SKIP_COMPILE: if sample not in SKIP_COMPILE and not sample.endswith("_dec"):
self.assert_sample(sample, skip_run=sample in SKIP_RUN) self.assert_sample(sample, skip_run=sample in SKIP_RUN)
with self.subTest("decompile/" + sample): with self.subTest("decompile/" + sample):