3 from xml
.dom
import XML_NAMESPACE
, Node
6 from override
import FREE_NS
8 class Invalid(Exception):
11 def pair(vbox
, label
, widget
):
12 hbox
= g
.HBox(False, 0)
13 vbox
.pack_start(hbox
, False, True, 0)
14 hbox
.pack_start(g
.Label(label
+ ': '), False, True, 0)
15 hbox
.pack_start(widget
, True, True, 0)
17 match_types
= ['string', 'byte', 'big16', 'big32', 'little16', 'little32', 'host16', 'host32']
20 "MIME_Type.get_* functions return a list of these."
21 def __init__(self
, type, item
= None):
24 self
.item
= self
.get_blank_item()
34 assert self
.user
in (True, False)
39 def get_blank_item(self
):
40 raise Exception("Can't create fields of this type yet")
43 return "<%s>" % self
.item
45 def get_sub_fields(self
):
48 def add_subtree(self
, model
, iter, grey
):
55 "Returns True on success."
56 if not hasattr(self
, 'add_edit_widgets'):
57 rox
.alert('Sorry, MIME-Editor does not support editing fields of this type')
61 box
.set_has_separator(False)
62 vbox
= g
.VBox(False, 4)
63 vbox
.set_border_width(4)
64 box
.vbox
.pack_start(vbox
, True, True, 0)
65 self
.add_edit_widgets(vbox
)
66 box
.add_button(g
.STOCK_CANCEL
, g
.RESPONSE_CANCEL
)
67 box
.add_button(g
.STOCK_OK
, g
.RESPONSE_OK
)
68 box
.set_default_response(g
.RESPONSE_OK
)
73 if resp
== g
.RESPONSE_OK
:
82 rox
.report_exception()
86 def delete_from_node(self
, type_node
):
87 raise Invalid("TODO: Can't delete/edit fields of this type yet")
89 def add_to_node(self
, node
):
90 raise Invalid("TODO: Can't add/edit fields of this type yet")
94 doc
, node
= override
.get_override_type(self
.type.get_name())
95 self
.delete_from_node(node
)
96 override
.write_override(doc
)
98 def commit_edit(self
, box
):
99 doc
, node
= override
.get_override_type(self
.type.get_name())
101 self
.delete_from_node(node
)
102 self
.add_to_node(node
)
103 override
.write_override(doc
)
105 class Comment(Field
):
106 def get_blank_item(self
):
107 return (None, 'Unknown format')
110 lang
, data
= self
.item
112 lang
= '[' + lang
+ '] '
117 def add_edit_widgets(self
, vbox
):
119 g
.Label("Enter a brief description of the type, eg 'HTML Page'.\n"
120 "Leave the language blank unless this is a translation, in \n"
121 "which case enter the country code (eg 'fr')."),
124 self
.lang
= g
.Entry()
125 self
.lang
.set_text(self
.item
[0] or '')
126 self
.lang
.set_activates_default(True)
127 pair(vbox
, 'Language', self
.lang
)
129 self
.entry
= g
.Entry()
130 self
.entry
.set_text(self
.item
[1])
131 self
.entry
.grab_focus()
132 self
.entry
.set_activates_default(True)
133 pair(vbox
, 'Description', self
.entry
)
135 def delete_from_node(self
, node
):
136 lang
= self
.item
[0] or ''
137 for x
in node
.childNodes
:
138 if x
.nodeType
!= Node
.ELEMENT_NODE
: continue
139 if x
.localName
== 'comment' and x
.namespaceURI
== FREE_NS
:
140 if (x
.getAttributeNS(XML_NAMESPACE
, 'lang') or '') == lang
and \
141 type.data(x
) == self
.item
[1]:
142 x
.parentNode
.removeChild(x
)
145 raise Exception("Can't find this comment in Override.xml!")
147 def add_to_node(self
, node
):
148 new_lang
= self
.lang
.get_text()
149 new
= self
.entry
.get_text()
151 raise Invalid("Comment can't be empty")
152 comment
= node
.ownerDocument
.createElementNS(FREE_NS
, 'comment')
154 comment
.setAttributeNS(XML_NAMESPACE
, 'xml:lang', new_lang
)
155 data
= node
.ownerDocument
.createTextNode(new
)
156 comment
.appendChild(data
)
157 node
.appendChild(comment
)
160 def get_blank_item(self
):
164 return "Match '%s'" % self
.item
166 def add_edit_widgets(self
, vbox
):
168 g
.Label("Enter a glob pattern which matches files of this type.\n"
169 "Special characters are:\n"
170 "? - any one character\n"
171 "* - zero or more characters\n"
172 "[abc] - any character between the brackets\n"
173 "Example: '*.html' matches all files ending in '.html'\n"
174 "(or '.HTML', etc)"),
176 self
.entry
= g
.Entry()
177 self
.entry
.set_text(self
.item
)
178 vbox
.pack_start(self
.entry
, False, True, 0)
179 self
.entry
.set_activates_default(True)
181 def delete_from_node(self
, node
):
182 for x
in node
.childNodes
:
183 if x
.nodeType
!= Node
.ELEMENT_NODE
: continue
184 if x
.localName
== 'glob' and x
.namespaceURI
== FREE_NS
:
185 if x
.getAttributeNS(None, 'pattern') == self
.item
:
186 x
.parentNode
.removeChild(x
)
189 raise Exception("Can't find this pattern in Override.xml!")
191 def add_to_node(self
, node
):
192 new
= self
.entry
.get_text()
194 raise Invalid("Pattern can't be empty")
195 glob
= node
.ownerDocument
.createElementNS(FREE_NS
, 'glob')
196 glob
.setAttributeNS(None, 'pattern', new
)
197 node
.appendChild(glob
)
200 def __init__(self
, type, item
= None):
202 prio
, match
, user
= item
203 if prio
is None or prio
is '':
207 item
= (int(prio
), match
, user
)
208 Field
.__init
__(self
, type, item
)
209 self
.match
= Match(self
.type, (self
, self
.item
[1], self
.item
[1].user
))
211 def get_blank_item(self
):
212 return (50, type.Match(None, True))
215 prio
, match
= self
.item
216 return "Match with priority %d" % prio
218 def add_sub_field(self
):
219 self
.match
.add_sub_field()
221 def get_sub_fields(self
):
222 return self
.match
.get_sub_fields()
224 def add_edit_widgets(self
, vbox
):
226 g
.Label("The priority is from 0 (low) to 100 (high).\n"
227 "High priority matches take precedence over low ones.\n"
228 "To add matches to this group, select it and click on Add."),
231 self
.adj
= g
.Adjustment(prio
, lower
= 0, upper
= 100, step_incr
= 1)
232 spinner
= g
.SpinButton(self
.adj
, 1, 0)
233 vbox
.pack_start(spinner
, False, True, 0)
234 spinner
.set_activates_default(True)
236 def add_to_node(self
, node
, child_edit
= False):
237 prio
, match
= self
.item
242 new
= int(self
.adj
.value
)
244 magic_node
= node
.ownerDocument
.createElementNS(FREE_NS
, 'magic')
246 magic_node
.setAttributeNS(None, 'priority', str(new
))
247 node
.appendChild(magic_node
)
248 match
.write_xml(magic_node
)
250 def equals_node(self
, node
):
251 prio
, match
= self
.item
252 node_prio
= node
.getAttributeNS(None, 'priority')
253 if node_prio
is None or node_prio
is '':
256 node_prio
= int(node_prio
)
257 if node_prio
!= prio
:
259 return match
.equals_node(node
)
261 def delete_from_node(self
, node
):
262 for x
in node
.childNodes
:
263 if x
.nodeType
!= Node
.ELEMENT_NODE
: continue
264 if x
.localName
== 'magic' and x
.namespaceURI
== FREE_NS
:
265 if self
.equals_node(x
):
266 x
.parentNode
.removeChild(x
)
269 raise Exception("Can't find this magic in Override.xml!")
272 # Note, this is a different class to type.Match!
273 def get_blank_item(self
):
274 match
= type.Match(None, True)
275 match
.type = 'string'
281 def add_sub_field(self
):
282 new
= Match(self
.type)
283 new
.item
[0] = self
.item
[0]
284 new
.item
[1].parent
= self
.item
[1]
287 def get_sub_fields(self
):
288 magic
, match
= self
.item
289 return [Match(self
.type, (magic
, m
, m
.user
)) for m
in match
.matches
]
291 def add_edit_widgets(self
, vbox
):
292 magic
, match
= self
.item
295 g
.Label("Offset is the position in the file to check at. It can be a\n"
296 "single number, or a range in the form 'first:last'\n"
297 "To add sub-matches to this one, select it and click on Add."),
301 for t
in match_types
:
304 self
.match_type
= g
.OptionMenu()
305 self
.match_type
.set_menu(menu
)
306 self
.match_type
.set_history(match_types
.index(match
.type))
307 pair(vbox
, 'Type', self
.match_type
)
309 self
.offset
= g
.Entry()
310 pair(vbox
, 'Offset(s)', self
.offset
)
311 self
.offset
.set_activates_default(True)
312 self
.offset
.set_text(match
.offset
)
313 self
.offset
.grab_focus()
315 self
.value
= g
.Entry()
316 pair(vbox
, 'Value', self
.value
)
317 self
.value
.set_text(match
.value
)
318 self
.value
.set_activates_default(True)
320 self
.mask
= g
.Entry()
321 pair(vbox
, 'Mask', self
.mask
)
322 self
.mask
.set_text(match
.mask
or '')
323 self
.mask
.set_activates_default(True)
325 def delete_from_node(self
, node
):
326 magic
, match
= self
.item
329 magic
.delete_from_node(node
)
331 match
.parent
.matches
.remove(match
)
333 magic
.add_to_node(node
, child_edit
= True)
335 def commit_edit(self
, box
):
336 magic
, match
= self
.item
338 offset
= self
.offset
.get_text()
339 value
= self
.value
.get_text()
341 if not offset
or not value
:
342 raise Invalid('Missing offset or value')
344 doc
, node
= override
.get_override_type(self
.type.get_name())
345 magic
.delete_from_node(node
)
347 match
.type = match_types
[self
.match_type
.get_history()]
348 match
.offset
= offset
350 match
.mask
= self
.mask
.get_text() or None
352 if match
not in match
.parent
.matches
:
353 match
.parent
.matches
.append(match
)
355 magic
.add_to_node(node
, child_edit
= True)
356 override
.write_override(doc
)
360 text
= '%s at %s = %s' % (m
.type, m
.offset
, m
.value
)
362 text
+= ' masked with ' + m
.mask
366 def get_blank_item(self
):
367 return ('http://example.com', 'documentElement')
370 return "<%s> with namespace '%s'" % (self
.item
[1], self
.item
[0])
372 def add_edit_widgets(self
, vbox
):
374 g
.Label("Enter the namespace URI and element name of the root element."),
378 self
.ns
.set_text(self
.item
[0])
379 self
.ns
.set_activates_default(True)
380 pair(vbox
, 'Namespace', self
.ns
)
382 self
.entry
= g
.Entry()
383 self
.entry
.set_text(self
.item
[1])
384 self
.entry
.set_activates_default(True)
385 pair(vbox
, 'Local name', self
.entry
)
387 def delete_from_node(self
, node
):
389 localName
= self
.item
[1]
390 for x
in node
.childNodes
:
391 if x
.nodeType
!= Node
.ELEMENT_NODE
: continue
392 if x
.localName
== 'root-XML' and x
.namespaceURI
== FREE_NS
:
393 if (x
.getAttributeNS(None, 'namespaceURI') == ns
and \
394 x
.getAttributeNS(None, 'localName') == localName
):
395 x
.parentNode
.removeChild(x
)
398 raise Exception("Can't find this root-XML in Override.xml!")
400 def add_to_node(self
, node
):
401 new_ns
= self
.ns
.get_text()
402 new
= self
.entry
.get_text()
403 if (not new
) and (not new_ns
):
404 raise Invalid("Name and namespace can't both be empty")
405 if ' ' in new
or ' ' in new_ns
:
406 raise Invalid("Name and namespace can't contain spaces")
407 xmlroot
= node
.ownerDocument
.createElementNS(FREE_NS
, 'root-XML')
408 xmlroot
.setAttributeNS(None, 'namespaceURI', new_ns
)
409 xmlroot
.setAttributeNS(None, 'localName', new
)
410 node
.appendChild(xmlroot
)
413 def can_edit(self
): return False