1 """Base classes for organizing data (for instance to visualize data
2 with Qt, or to run hierarchical checks) in a global graph, and a
3 detail tree at each node of the global graph.
4
5 The classes defined here assume that data can be organized in two
6 stages: a global level which only shows 'top-level' objects
7 (i.e. large file blocks, chunks, and so on) as nodes and links between
8 the nodes via directed arcs, and a detail level which shows the
9 details of a top-level object, that is, the actual data they
10 contain.
11
12 :class:`DetailNode` implements the detail side of things. The
13 :class:`GlobalNode` class implements the global level, which does not show
14 any actual data, but only structure.
15
16 The global level forms a directed graph where the nodes are data
17 blocks and directed edges represent links from one block to
18 another.
19
20 This directed graph is assumed to have a spanning acyclic directed
21 subgraph, that is, a subgraph which contains all nodes of the original
22 graph, and which contains no cycles. This graph constitutes of those
23 edges which have the default edge type.
24
25 The :class:`pyffi.object_models.Data` class is the root node of
26 the graph. Recursing over all edges of default type of this node will
27 visit each node (possibly more than once) in a hierarchical order.
28
29 The base classes are roughly based on the TreeItem example in the Qt docs:
30 http://doc.trolltech.com/4.4/itemviews-simpletreemodel.html
31 """
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 from itertools import repeat
73 from operator import itemgetter
74
76 """Represents all possible edge types. By default, there are four
77 types: any edge can be part of the acyclic graph or not, and can
78 be active or not.
79
80 The default edge type is active and acylic.
81 """
82
83 - def __new__(cls, active=True, acyclic=True):
85
86 active = property(itemgetter(0))
87 acyclic = property(itemgetter(1))
88
90 """A simple filter for edges. The default filter only checks the edge's
91 active and acyclic attributes, and accepts them if both are ``True``.
92 """
93 - def __new__(cls, active_filter=True, acyclic_filter=True):
95
96 active_filter = property(itemgetter(0))
97 acyclic_filter = property(itemgetter(1))
98
106
108 """A node of the detail tree which can have children.
109
110 If the data must be editable, also derive the class from one of
111 the delegate classes defined in :mod:`pyffi.object_models.editable`,
112 and make sure that the get_value and set_value functions are
113 implemented.
114 """
115
117 """Generator which yields all children of this item in the
118 detail view (by default, all acyclic and active ones).
119
120 Override this method if the node has children.
121
122 :param edge_filter: The edge type to include.
123 :type edge_filter: :class:`EdgeFilter` or ``type(None)``
124 :return: Generator for detail tree child nodes.
125 :rtype: generator yielding :class:`DetailNode`\ s
126 """
127 return (dummy for dummy in ())
128
130 """Generator which yields all child names of this item in the detail
131 view.
132
133 Override this method if the node has children.
134
135 :return: Generator for detail tree child names.
136 :rtype: generator yielding ``str``\ s
137 """
138 return (dummy for dummy in ())
139
141 """Generator which yields all edge types of this item in the
142 detail view, one edge type for each child.
143
144 Override this method if you rely on more than one edge type.
145 """
146 return repeat(EdgeType())
147
149 """Object used to display the instance in the detail view.
150
151 Override this method if the node has data to display in the detail view.
152
153 :return: A string that can be used to display the instance.
154 :rtype: ``str``
155 """
156 return ""
157
159 """Iterate over self, all children, all grandchildren, and so
160 on (only given edge type is followed). Do not override.
161 """
162 yield self
163 for child in self.get_detail_child_nodes(edge_filter=edge_filter):
164 for branch in child.get_detail_iterator(edge_filter=edge_filter):
165 yield branch
166
168 """Replace a particular branch in the graph."""
169 raise NotImplementedError
170
172 """A node of the global graph."""
173
175 """Very short summary of the data of this global branch for display
176 purposes. Override this method.
177
178 :return: A string.
179 """
180 return ""
181
182
183
185 """Generator which yields all children of this item in the
186 global view, of given edge type (default is edges of type 0).
187
188 Override this method.
189
190 :return: Generator for global node children.
191 """
192 return (dummy for dummy in ())
193
195 """Generator which yields all edge types of this item in the
196 global view, one edge type for each child.
197
198 Override this method if you rely on non-default edge types.
199 """
200 return repeat(EdgeType())
201
203 """Iterate over self, all children, all grandchildren, and so
204 on (only given edge_filter is followed). Do not override.
205 """
206 yield self
207 for child in self.get_global_child_nodes(edge_filter=edge_filter):
208 for branch in child.get_global_iterator(edge_filter=edge_filter):
209 yield branch
210