collagraph 0.8.2__tar.gz → 0.8.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {collagraph-0.8.2 → collagraph-0.8.4}/PKG-INFO +12 -16
- {collagraph-0.8.2 → collagraph-0.8.4}/README.md +11 -15
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/component.py +6 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/layouts.py +30 -4
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/sfc/parser.py +20 -1
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pygfx/app_point_cloud.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pygfx/button.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pygfx/numberpad.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pygfx/point_cloud.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/big_list.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/cgx_component_example.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/counter.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/dialog_example.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/dialog_example_window.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/layout_example.cgx +1 -2
- collagraph-0.8.4/examples/pyside/list_and_form.cgx +46 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/lists_example.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/slider_example.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/tabs_example.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/todo_example.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/tree_view_example.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/tree_widget_example.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/pyproject.toml +1 -1
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/component/events_parent.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/component/provide_child.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/component/provide_parent.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/component/provide_root.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/pyside/app.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/pyside/test_pyside_update.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/shadow_imports.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/pyside/lists.cgx +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/pyside/test_pyside_elements.py +2 -4
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/pyside/test_pyside_sfc.py +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_attributes_dynamic.py +3 -6
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_component.py +3 -6
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_component_life_cycle.py +27 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_directive_for.py +2 -4
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_parser.py +28 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_resolve_names.py +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_tag_component.py +1 -2
- {collagraph-0.8.2 → collagraph-0.8.4}/.coveragerc +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/.github/workflows/ci.yml +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/.gitignore +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/.pre-commit-config.yaml +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/LICENSE +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/__init__.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/__main__.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/__pyinstaller/__init__.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/__pyinstaller/hook-collagraph.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/collagraph.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/constants.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/fragment.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/__init__.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/dict_renderer.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pygfx_renderer.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/__init__.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/__init__.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/combobox.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/dialogbuttonbox.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/dockwidget.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/itemmodel.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/listview.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/menu.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/menubar.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/qobject.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/scrollarea.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/splitter.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/standarditem.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/statusbar.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/tab.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/toolbar.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/treewidget.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/treewidgetitem.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/widget.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside/objects/window.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/renderers/pyside_renderer.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/sfc/__init__.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/sfc/compiler.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/sfc/importer.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/collagraph/weak.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pygfx/README.md +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pygfx/combined-example.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pygfx/component-example.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pygfx/point.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pygfx/pygfx-component.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pygfx/render_widget.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/app.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/combobox_example.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/debug_example.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/flow_layout.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/item.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/todo_list.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/tree_view_item.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/tree_view_model.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/examples/pyside/tree_widget_item.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/__init__.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/conftest.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/component/events_child.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/example.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/file_dunder.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/multiple_classes_right_order.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/multiple_classes_wrong_order.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/multiple_root_elements.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/no_component_class.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/simple.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/slots/dynamic_for.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/slots/dynamic_for_template.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/slots/dynamic_if.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/slots/dynamic_if_template.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/slots/node.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/slots/simple_tree.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/slots/slots_implicit_default_slot.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/slots/template.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/slots/template_empty.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/slots/template_implicit_default_slot.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/slots/template_implicit_default_slot_name.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/slots/template_partial.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/slots/tree.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/slots/widget_with_slots.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/data/text/expressions.cgx +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/pyside/conftest.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/pyside/test_pyside_ci.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/pyside/test_pyside_renderer.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/pyside/test_update.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/pyside/test_widget.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_attributes_static.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_collagraph.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_component_events.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_component_provide_inject.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_directive_else.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_directive_else_if.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_directive_if.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_events.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_load_string.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_pygfx_renderer.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_reconciliation.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_sfc_comments.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_sfc_compilation.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_sfc_import.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_sfc_linting_support.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_sfc_shadowing.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_slots.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_slots_dynamic.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_tag_dynamic.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_tag_static.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_tag_template.py +0 -0
- {collagraph-0.8.2 → collagraph-0.8.4}/tests/test_text_expressions.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: collagraph
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.4
|
|
4
4
|
Summary: Reactive user interfaces
|
|
5
5
|
Author-email: Berend Klein Haneveld <berendkleinhaneveld@gmail.com>, Korijn van Golen <korijn@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -30,7 +30,6 @@ Inspired by Vue and React.
|
|
|
30
30
|
Write your Python interfaces in a declarative manner with plain render functions, component classes or even single-file components using Vue-like syntax, but with Python!
|
|
31
31
|
|
|
32
32
|
* Reactivity (made possible by leveraging [observ](https://github.com/fork-tongue/observ))
|
|
33
|
-
* Function components
|
|
34
33
|
* Class components with local state and life-cycle methods/hooks
|
|
35
34
|
* Single-file components with Vue-like template syntax (`.cgx` files)
|
|
36
35
|
* Custom renderers
|
|
@@ -39,25 +38,22 @@ Here is an example that shows a counter, made with a component with Vue-like syn
|
|
|
39
38
|
|
|
40
39
|
Contents of `counter.cgx`:
|
|
41
40
|
```html
|
|
42
|
-
<
|
|
43
|
-
<
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
</widget>
|
|
52
|
-
</template>
|
|
41
|
+
<widget>
|
|
42
|
+
<label
|
|
43
|
+
:text="f'Count: {count}'"
|
|
44
|
+
/>
|
|
45
|
+
<button
|
|
46
|
+
text="bump"
|
|
47
|
+
@clicked="bump"
|
|
48
|
+
/>
|
|
49
|
+
</widget>
|
|
53
50
|
|
|
54
51
|
<script>
|
|
55
52
|
import collagraph as cg
|
|
56
53
|
|
|
57
54
|
|
|
58
55
|
class Counter(cg.Component):
|
|
59
|
-
def
|
|
60
|
-
super().__init__(*args, **kwargs)
|
|
56
|
+
def init(self):
|
|
61
57
|
self.state["count"] = 0
|
|
62
58
|
|
|
63
59
|
def bump(self):
|
|
@@ -80,7 +76,7 @@ gui = cg.Collagraph(renderer=cg.PySideRenderer())
|
|
|
80
76
|
# Render the component into a container
|
|
81
77
|
# (in this case the app but can be another widget)
|
|
82
78
|
app = QtWidgets.QApplication()
|
|
83
|
-
gui.render(
|
|
79
|
+
gui.render(Counter, app)
|
|
84
80
|
app.exec()
|
|
85
81
|
```
|
|
86
82
|
|
|
@@ -15,7 +15,6 @@ Inspired by Vue and React.
|
|
|
15
15
|
Write your Python interfaces in a declarative manner with plain render functions, component classes or even single-file components using Vue-like syntax, but with Python!
|
|
16
16
|
|
|
17
17
|
* Reactivity (made possible by leveraging [observ](https://github.com/fork-tongue/observ))
|
|
18
|
-
* Function components
|
|
19
18
|
* Class components with local state and life-cycle methods/hooks
|
|
20
19
|
* Single-file components with Vue-like template syntax (`.cgx` files)
|
|
21
20
|
* Custom renderers
|
|
@@ -24,25 +23,22 @@ Here is an example that shows a counter, made with a component with Vue-like syn
|
|
|
24
23
|
|
|
25
24
|
Contents of `counter.cgx`:
|
|
26
25
|
```html
|
|
27
|
-
<
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
</widget>
|
|
37
|
-
</template>
|
|
26
|
+
<widget>
|
|
27
|
+
<label
|
|
28
|
+
:text="f'Count: {count}'"
|
|
29
|
+
/>
|
|
30
|
+
<button
|
|
31
|
+
text="bump"
|
|
32
|
+
@clicked="bump"
|
|
33
|
+
/>
|
|
34
|
+
</widget>
|
|
38
35
|
|
|
39
36
|
<script>
|
|
40
37
|
import collagraph as cg
|
|
41
38
|
|
|
42
39
|
|
|
43
40
|
class Counter(cg.Component):
|
|
44
|
-
def
|
|
45
|
-
super().__init__(*args, **kwargs)
|
|
41
|
+
def init(self):
|
|
46
42
|
self.state["count"] = 0
|
|
47
43
|
|
|
48
44
|
def bump(self):
|
|
@@ -65,7 +61,7 @@ gui = cg.Collagraph(renderer=cg.PySideRenderer())
|
|
|
65
61
|
# Render the component into a container
|
|
66
62
|
# (in this case the app but can be another widget)
|
|
67
63
|
app = QtWidgets.QApplication()
|
|
68
|
-
gui.render(
|
|
64
|
+
gui.render(Counter, app)
|
|
69
65
|
app.exec()
|
|
70
66
|
```
|
|
71
67
|
|
|
@@ -27,6 +27,12 @@ class Component:
|
|
|
27
27
|
self._parent = ref(parent) if parent else None
|
|
28
28
|
self._provided = {}
|
|
29
29
|
|
|
30
|
+
# Call init hook at end of __init__
|
|
31
|
+
self.init()
|
|
32
|
+
|
|
33
|
+
def init(self):
|
|
34
|
+
pass
|
|
35
|
+
|
|
30
36
|
@property
|
|
31
37
|
def props(self):
|
|
32
38
|
"""The incoming props of this component."""
|
|
@@ -59,8 +59,15 @@ def remove_layout(self, el):
|
|
|
59
59
|
|
|
60
60
|
@PySideRenderer.register_remove(QFormLayout)
|
|
61
61
|
def remove_form(self, el):
|
|
62
|
-
#
|
|
63
|
-
|
|
62
|
+
# Don't use removeRow, even though it should theoratically work
|
|
63
|
+
# In reality it causes a hard crash...
|
|
64
|
+
# Instead, take the row, and then unset the parents of the
|
|
65
|
+
# associated widgets of the return layout item
|
|
66
|
+
layout_item = self.takeRow(el)
|
|
67
|
+
if layout_item:
|
|
68
|
+
layout_item.labelItem.widget().setParent(None)
|
|
69
|
+
layout_item.fieldItem.widget().setParent(None)
|
|
70
|
+
el.setParent(None)
|
|
64
71
|
|
|
65
72
|
|
|
66
73
|
@PySideRenderer.register_set_attr(QLayout)
|
|
@@ -105,12 +112,31 @@ def set_grid_index(self, attr, value):
|
|
|
105
112
|
layout.addWidget(self, *value)
|
|
106
113
|
|
|
107
114
|
|
|
108
|
-
@PySideRenderer.register_custom_attribute("form_label"
|
|
115
|
+
@PySideRenderer.register_custom_attribute("form_label")
|
|
116
|
+
def set_form_label(self, attr, value):
|
|
117
|
+
setattr(self, attr, value)
|
|
118
|
+
index = getattr(self, "form_index", None)
|
|
119
|
+
if parent := self.parent():
|
|
120
|
+
layout = parent.layout()
|
|
121
|
+
if index is not None:
|
|
122
|
+
label_item = layout.itemAt(index, QFormLayout.LabelRole)
|
|
123
|
+
label_item.widget().setText(value)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@PySideRenderer.register_custom_attribute("form_index")
|
|
109
127
|
def set_form_index(self, attr, value):
|
|
128
|
+
old_index = getattr(self, "form_index", None)
|
|
110
129
|
setattr(self, attr, value)
|
|
111
130
|
if parent := self.parent():
|
|
112
131
|
layout = parent.layout()
|
|
132
|
+
label_widget = None
|
|
133
|
+
if old_index is not None:
|
|
134
|
+
layout_item = layout.takeRow(old_index)
|
|
135
|
+
label_widget = layout_item.labelItem.widget()
|
|
136
|
+
assert layout_item.fieldItem.widget() is self
|
|
113
137
|
if hasattr(self, "form_label") and hasattr(self, "form_index"):
|
|
114
|
-
layout.insertRow(
|
|
138
|
+
layout.insertRow(
|
|
139
|
+
self.form_index, label_widget if label_widget else self.form_label, self
|
|
140
|
+
)
|
|
115
141
|
elif hasattr(self, "form_label"):
|
|
116
142
|
layout.addRow(self.form_label, self)
|
|
@@ -45,7 +45,7 @@ class CGXParser(HTMLParser):
|
|
|
45
45
|
self.root = Element("root", attrs={}, location=(-1, -1))
|
|
46
46
|
self.stack = [self.root]
|
|
47
47
|
|
|
48
|
-
def
|
|
48
|
+
def _handle_tag(self, tag: str, attrs: list[tuple[str, str | None]]) -> Element:
|
|
49
49
|
# The tag parameter is lower-cased by the HTMLParser.
|
|
50
50
|
# In order to figure out whether the tag indicates
|
|
51
51
|
# an imported class, we need the original casing for
|
|
@@ -68,6 +68,11 @@ class CGXParser(HTMLParser):
|
|
|
68
68
|
parent = self.stack[-1]
|
|
69
69
|
parent.children.append(node)
|
|
70
70
|
node.parent = ref(parent)
|
|
71
|
+
|
|
72
|
+
return node
|
|
73
|
+
|
|
74
|
+
def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]):
|
|
75
|
+
node = self._handle_tag(tag, attrs)
|
|
71
76
|
# Make the new node the last on the stack
|
|
72
77
|
self.stack.append(node)
|
|
73
78
|
|
|
@@ -81,6 +86,20 @@ class CGXParser(HTMLParser):
|
|
|
81
86
|
if node.tag.lower() == tag:
|
|
82
87
|
break
|
|
83
88
|
|
|
89
|
+
def handle_startendtag(self, tag: str, attrs):
|
|
90
|
+
"""Handle self-closing tags"""
|
|
91
|
+
node = self._handle_tag(tag, attrs)
|
|
92
|
+
# Get the full text and split it
|
|
93
|
+
text = self.get_starttag_text()
|
|
94
|
+
lines = text.splitlines()
|
|
95
|
+
# Find the location of where the tag is actually closed
|
|
96
|
+
column = lines[-1].index("/>")
|
|
97
|
+
# Figure out how many lines the tag spans
|
|
98
|
+
line_span_count = len(lines) - 1
|
|
99
|
+
line, _ = self.getpos()
|
|
100
|
+
# Set the end to be exactly where the '/>' is located
|
|
101
|
+
node.end = (line + line_span_count, column)
|
|
102
|
+
|
|
84
103
|
def handle_data(self, data: str):
|
|
85
104
|
if data.strip():
|
|
86
105
|
# Add item as child to the last on the stack
|
|
@@ -32,8 +32,7 @@ class Button(cg.Component):
|
|
|
32
32
|
),
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
def
|
|
36
|
-
super().__init__(*args, **kwargs)
|
|
35
|
+
def init(self):
|
|
37
36
|
self.state["pressed"] = False
|
|
38
37
|
self.state["hovered"] = False
|
|
39
38
|
self.state["scale"] = self.props.get("scale", [0.85] * 3)
|
|
@@ -63,8 +63,7 @@ from examples.pyside.item import Item
|
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
class TreeWidget(cg.Component):
|
|
66
|
-
def
|
|
67
|
-
super().__init__(*args, **kwargs)
|
|
66
|
+
def init(self):
|
|
68
67
|
self.state["columns"] = ["text", "other"]
|
|
69
68
|
self.state["items"] = [
|
|
70
69
|
*[{"text": f"text-{idx}", "other": f"other-{idx}"} for idx in range(500)]
|
|
@@ -41,8 +41,7 @@ from examples.pyside.dialog_example import ListDialog
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
class Window(cg.Component):
|
|
44
|
-
def
|
|
45
|
-
super().__init__(*args, **kwargs)
|
|
44
|
+
def init(self):
|
|
46
45
|
self.state["dialog_active"] = False
|
|
47
46
|
self.state["selected_text"] = ""
|
|
48
47
|
self.state["modality"] = "window"
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<widget>
|
|
2
|
+
<qsplitter>
|
|
3
|
+
<treewidget
|
|
4
|
+
object-name="tree-widget"
|
|
5
|
+
:header-labels="['content']"
|
|
6
|
+
:column-count="1"
|
|
7
|
+
:selection-mode="QtWidgets.QTreeView.ExtendedSelection"
|
|
8
|
+
@item-selection-changed="selection_changed"
|
|
9
|
+
>
|
|
10
|
+
<treewidgetitem
|
|
11
|
+
v-for="item in items"
|
|
12
|
+
:content="{0: item['name']}"
|
|
13
|
+
:obj_id="item['id']"
|
|
14
|
+
/>
|
|
15
|
+
</treewidget>
|
|
16
|
+
<widget :layout="{'type': 'form'}">
|
|
17
|
+
<label v-for="item in selected_items()" v-bind="item" />
|
|
18
|
+
</widget>
|
|
19
|
+
</qsplitter>
|
|
20
|
+
</widget>
|
|
21
|
+
|
|
22
|
+
<script>
|
|
23
|
+
import collagraph as cg
|
|
24
|
+
from PySide6 import QtWidgets
|
|
25
|
+
|
|
26
|
+
class App(cg.Component):
|
|
27
|
+
def init(self):
|
|
28
|
+
self.state["items"] = [{"id": 0, "name": "first"}, {"id": 1, "name":"second"}]
|
|
29
|
+
self.state["selected"] = []
|
|
30
|
+
|
|
31
|
+
def selection_changed(self):
|
|
32
|
+
if not self.element:
|
|
33
|
+
return
|
|
34
|
+
|
|
35
|
+
tree_widget = self.element.findChild(QtWidgets.QTreeWidget, "tree-widget")
|
|
36
|
+
selected_items = tree_widget.selectedItems()
|
|
37
|
+
selected_ids = list([item.obj_id for item in selected_items])
|
|
38
|
+
self.state["selected"] = selected_ids
|
|
39
|
+
|
|
40
|
+
def selected_items(self):
|
|
41
|
+
result = [
|
|
42
|
+
{'text': self.state['items'][idx]["name"], 'form_label': f'Type {idx}:', 'form_index': 0}
|
|
43
|
+
for idx in self.state['selected']]
|
|
44
|
+
return result
|
|
45
|
+
|
|
46
|
+
</script>
|
|
@@ -60,8 +60,7 @@ def row(text: str, /, children=None, **kwargs):
|
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
class TreeView(cg.Component):
|
|
63
|
-
def
|
|
64
|
-
super().__init__(*args, **kwargs)
|
|
63
|
+
def init(self):
|
|
65
64
|
# Adding columns seems to work relatively OK, but removing columns
|
|
66
65
|
# has some problems...
|
|
67
66
|
self.state["columns"] = ["text", "other"]
|
|
@@ -9,8 +9,7 @@ import collagraph as cg
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class Child(cg.Component):
|
|
12
|
-
def
|
|
13
|
-
super().__init__(*args, **kwargs)
|
|
12
|
+
def init(self):
|
|
14
13
|
self.state["injected_value"] = self.inject("value")
|
|
15
14
|
self.state["injected_non_existing"] = self.inject("non_existing")
|
|
16
15
|
self.state["injected_default"] = self.inject("other", default="bar")
|
|
@@ -55,8 +55,7 @@ import collagraph as cg
|
|
|
55
55
|
from observ import to_raw
|
|
56
56
|
|
|
57
57
|
class ListsExample(cg.Component):
|
|
58
|
-
def
|
|
59
|
-
super().__init__(*args, **kwargs)
|
|
58
|
+
def init(self):
|
|
60
59
|
self.state["values"] = to_raw(self.props["items"])
|
|
61
60
|
|
|
62
61
|
def items_content(self):
|
|
@@ -101,8 +101,7 @@ def test_layouts(qapp, qtbot, parse_source):
|
|
|
101
101
|
import collagraph as cg
|
|
102
102
|
|
|
103
103
|
class LayoutExample(cg.Component):
|
|
104
|
-
def
|
|
105
|
-
super().__init__(*args, **kwargs)
|
|
104
|
+
def init(self):
|
|
106
105
|
# Data to fill the box layout
|
|
107
106
|
self.box = []
|
|
108
107
|
for i in range(1, 5):
|
|
@@ -207,8 +206,7 @@ def test_lists(qapp, qtbot, qtmodeltester, parse_source):
|
|
|
207
206
|
import collagraph as cg
|
|
208
207
|
|
|
209
208
|
class ListsExample(cg.Component):
|
|
210
|
-
def
|
|
211
|
-
super().__init__(*args, **kwargs)
|
|
209
|
+
def init(self):
|
|
212
210
|
self.state["values"] = self.props["items"]
|
|
213
211
|
|
|
214
212
|
def items_content(self):
|
|
@@ -21,8 +21,7 @@ def test_pyside_sfc_event_handlers(qtbot, parse_source):
|
|
|
21
21
|
import collagraph as cg
|
|
22
22
|
|
|
23
23
|
class Buttons(cg.Component):
|
|
24
|
-
def
|
|
25
|
-
super().__init__(*args, **kwargs)
|
|
24
|
+
def init(self):
|
|
26
25
|
self.state["count"] = 0
|
|
27
26
|
|
|
28
27
|
def increase(self):
|
|
@@ -191,8 +191,7 @@ def test_dynamic_attribute_basic_dict(parse_source):
|
|
|
191
191
|
|
|
192
192
|
|
|
193
193
|
class Labels(cg.Component):
|
|
194
|
-
def
|
|
195
|
-
super().__init__(*args, **kwargs)
|
|
194
|
+
def init(self):
|
|
196
195
|
self.state["label_text"] = self.props.get("text", "Label")
|
|
197
196
|
</script>
|
|
198
197
|
"""
|
|
@@ -317,8 +316,7 @@ def test_dynamic_attribute_full(parse_source):
|
|
|
317
316
|
import collagraph as cg
|
|
318
317
|
|
|
319
318
|
class Labels(cg.Component):
|
|
320
|
-
def
|
|
321
|
-
super().__init__(*args, **kwargs)
|
|
319
|
+
def init(self):
|
|
322
320
|
self.state["other"] = "bar"
|
|
323
321
|
</script>
|
|
324
322
|
"""
|
|
@@ -360,8 +358,7 @@ def test_dynamic_attribute_typo(parse_source):
|
|
|
360
358
|
import collagraph as cg
|
|
361
359
|
|
|
362
360
|
class App(cg.Component):
|
|
363
|
-
def
|
|
364
|
-
super().__init__(*args, **kwargs)
|
|
361
|
+
def init(self):
|
|
365
362
|
self.state["text"] = "Foo"
|
|
366
363
|
</script>
|
|
367
364
|
"""
|
|
@@ -26,8 +26,7 @@ def test_component_no_override(parse_source, attr):
|
|
|
26
26
|
import collagraph as cg
|
|
27
27
|
|
|
28
28
|
class Item(cg.Component):
|
|
29
|
-
def
|
|
30
|
-
super().__init__(*args, **kwargs)
|
|
29
|
+
def init(self):
|
|
31
30
|
self.{attr} = {{}}
|
|
32
31
|
</script>
|
|
33
32
|
"""
|
|
@@ -49,8 +48,7 @@ def test_component_props_read_only(parse_source):
|
|
|
49
48
|
import collagraph as cg
|
|
50
49
|
|
|
51
50
|
class Item(cg.Component):
|
|
52
|
-
def
|
|
53
|
-
super().__init__(*args, **kwargs)
|
|
51
|
+
def init(self):
|
|
54
52
|
self.props["foo"] = "bar"
|
|
55
53
|
</script>
|
|
56
54
|
"""
|
|
@@ -115,8 +113,7 @@ def test_component_callback(parse_source):
|
|
|
115
113
|
import collagraph as cg
|
|
116
114
|
|
|
117
115
|
class Counter(cg.Component):
|
|
118
|
-
def
|
|
119
|
-
super().__init__(*args, **kwargs)
|
|
116
|
+
def init(self):
|
|
120
117
|
self.state["count"] = self.props.get("count", 0)
|
|
121
118
|
self.state["step_size"] = self.props.get("step_size", 1)
|
|
122
119
|
|