12 class Editor(rox
.Dialog
):
14 rox
.Dialog
.__init
__(self
)
15 self
.set_default_size(600, 400)
16 self
.set_has_separator(False)
20 self
.add_button(g
.STOCK_ADD
, ADD
)
21 self
.add_button(g
.STOCK_DELETE
, DELETE
)
22 self
.add_button(g
.STOCK_PROPERTIES
, EDIT
)
23 self
.add_button(g
.STOCK_CLOSE
, g
.RESPONSE_CANCEL
)
25 self
.set_default_response(g
.RESPONSE_CANCEL
)
27 swin
= g
.ScrolledWindow()
28 swin
.set_border_width(4)
29 swin
.set_policy(g
.POLICY_NEVER
, g
.POLICY_ALWAYS
)
30 swin
.set_shadow_type(g
.SHADOW_IN
)
31 self
.vbox
.pack_start(swin
, True, True, 0)
33 self
.mime_model
= g
.TreeStore(str, str)
34 view
= g
.TreeView(self
.mime_model
)
37 view
.set_search_column(1)
39 cell
= g
.CellRendererText()
40 column
= g
.TreeViewColumn('MIME-Type', cell
, text
= 0)
41 view
.append_column(column
)
42 column
.set_sort_column_id(0)
44 cell
= g
.CellRendererText()
45 column
= g
.TreeViewColumn('Description', cell
, text
= 1)
46 view
.append_column(column
)
47 column
.set_sort_column_id(1)
49 view
.connect('row-activated', self
.activate
)
53 def response(self
, resp
):
55 self
.edit_selected(view
.get_selection())
57 self
.delete_type(view
)
60 self
.add_type
.present()
62 self
.add_type
= NewType()
63 def destroyed(widget
): self
.add_type
= None
64 self
.add_type
.connect('destroy', destroyed
)
68 self
.connect('response', response
)
70 def changed(selection
):
71 model
, iter = selection
.get_selected()
72 self
.set_response_sensitive(EDIT
, iter != None)
73 self
.set_response_sensitive(DELETE
, iter != None)
74 selection
= view
.get_selection()
75 selection
.connect('changed', changed
)
78 def delete_type(self
, view
):
79 model
, iter = view
.get_selection().get_selected()
81 rox
.alert('Nothing selected')
83 type_name
= model
.get_value(iter, 0)
84 type.delete_type(type_name
)
87 self
.set_title('Scanning... please wait')
92 self
.mime_model
.clear()
97 return cmp(a
[1], b
[1])
99 return a
[:1].upper() + a
[1:]
100 items
= [(t
, caps(t
.get_comment())) for t
in type.types
.values()]
101 items
.sort(items_cmp
)
103 iter = self
.mime_model
.append(None)
104 self
.mime_model
.set(iter, 1, c
, 0, t
.get_name())
106 self
.set_title('MIME-Editor')
108 for b
in edit_boxes
.values():
109 if b
.mime_type
in type.types
:
114 def activate(self
, view
, path
, column
):
115 iter = self
.mime_model
.get_iter(path
)
116 type_name
= self
.mime_model
.get_value(iter, 0)
119 def edit(self
, type_name
):
120 if type_name
in edit_boxes
:
121 edit_boxes
[type_name
].present()
123 box
= EditBox(type_name
)
124 edit_boxes
[type_name
] = box
125 def destroy(dialog
): del edit_boxes
[type_name
]
126 box
.connect('destroy', destroy
)
129 def edit_selected(self
, selection
):
130 model
, iter = selection
.get_selected()
132 rox
.alert('You need to select a type to edit first')
134 type_name
= model
.get_value(iter, 0)
137 def show_type(self
, type_name
):
138 model
= self
.mime_model
139 iter = model
.get_iter_first()
141 name
= model
.get_value(iter, 0)
142 if name
== type_name
:
143 path
= model
.get_path(iter)
144 self
.view
.set_cursor(path
, None, False)
146 iter = model
.iter_next(iter)
148 class EditBox(rox
.Dialog
):
149 def __init__(self
, type_name
):
150 rox
.Dialog
.__init
__(self
)
151 self
.set_has_separator(False)
152 self
.set_default_size(-1, 400)
153 self
.mime_type
= type_name
155 self
.set_title('MIME-Editor: %s' % type_name
)
157 swin
= g
.ScrolledWindow()
158 swin
.set_border_width(4)
159 swin
.set_shadow_type(g
.SHADOW_IN
)
160 self
.vbox
.pack_start(swin
, True, True, 0)
162 self
.model
= g
.TreeStore(str, object)
163 view
= g
.TreeView(self
.model
)
166 cell
= g
.CellRendererText()
167 column
= g
.TreeViewColumn(type_name
, cell
, text
= 0)
168 view
.append_column(column
)
170 swin
.set_policy(g
.POLICY_NEVER
, g
.POLICY_AUTOMATIC
)
176 self
.add_button(g
.STOCK_ADD
, ADD
)
177 self
.add_button(g
.STOCK_DELETE
, DELETE
)
178 self
.add_button(g
.STOCK_PROPERTIES
, EDIT
)
179 self
.add_button(g
.STOCK_CLOSE
, g
.RESPONSE_CANCEL
)
180 def response(w
, resp
):
184 self
.delete_field(view
)
186 self
.edit_field(view
)
189 self
.connect('response', response
)
191 def changed(selection
):
192 model
, iter = selection
.get_selected()
195 path
= model
.get_path(iter)
196 on_field
= len(path
) > 1
197 self
.set_response_sensitive(ADD
, iter != None)
198 self
.set_response_sensitive(EDIT
, on_field
)
199 self
.set_response_sensitive(DELETE
, on_field
)
200 selection
= view
.get_selection()
201 selection
.connect('changed', changed
)
204 def activate(view
, path
, column
):
205 iter = self
.model
.get_iter(path
)
206 field
= self
.model
.get_value(iter, 1)
208 self
.add_new_field(field
)
211 view
.connect('row-activated', activate
)
213 self
.set_default_response(g
.RESPONSE_CANCEL
)
216 t
= type.get_type(self
.mime_type
)
218 for aspect
, getter
, klass
in [('Name matching', t
.get_globs
, type.Glob
),
219 ('Contents matching', t
.get_magic
, type.Magic
),
220 ('XML namespace matching', t
.get_xml
, type.XML
),
221 ('Others', t
.get_others
, type.Other
),
222 ('Descriptions', t
.get_comments
, type.Comment
)]:
223 iter = self
.model
.append(None)
224 self
.model
.set(iter, 0, aspect
, 1, klass
)
226 fields
.sort(lambda a
, b
: cmp(str(a
), str(b
)))
229 if field
== last
: continue
231 f
= self
.model
.append(iter)
232 self
.model
.set(f
, 0, str(field
), 1, field
)
233 field
.add_subtree(self
.model
, f
)
235 def add_new_field(self
, type):
236 rox
.alert("TODO: Add field of type '%s'" % type)
238 def add_field(self
, view
):
239 model
, iter = view
.get_selection().get_selected()
241 rox
.alert('You need to select a group, so I know what kind of thing to add')
243 path
= model
.get_path(iter)
244 field
= model
.get_value(model
.get_iter(path
[:1]), 1)
245 self
.add_new_field(field
)
247 def delete_field(self
, view
):
248 model
, iter = view
.get_selection().get_selected()
250 rox
.alert("Nothing selected!")
251 field
= model
.get_value(iter, 1)
255 def edit_field(self
, view
):
256 model
, iter = view
.get_selection().get_selected()
258 rox
.alert("Nothing selected!")
259 field
= model
.get_value(iter, 1)
263 class NewType(rox
.Dialog
):
265 rox
.Dialog
.__init
__(self
)
266 self
.set_title('Add new MIME type')
268 self
.add_button(g
.STOCK_CANCEL
, g
.RESPONSE_CANCEL
)
269 self
.add_button(g
.STOCK_ADD
, g
.RESPONSE_OK
)
270 self
.set_default_response(g
.RESPONSE_OK
)
272 vbox
= g
.VBox(False, 4)
273 self
.vbox
.pack_start(vbox
, True, True, 0)
274 vbox
.set_border_width(4)
276 hbox
= g
.HBox(False, 4)
277 vbox
.pack_start(hbox
, False, True, 0)
278 label
= g
.Label("Media type:")
279 hbox
.pack_start(label
, False, True, 0)
281 combo
.set_popdown_strings(["text", "application", "image", "audio",
282 "video", "message", "model"])
283 hbox
.pack_start(combo
, True, True, 0)
285 hbox
= g
.HBox(False, 4)
286 vbox
.pack_start(hbox
, False, True, 0)
287 label
= g
.Label("Subtype:")
288 hbox
.pack_start(label
, False, True, 0)
290 entry
.set_text('x-my-type')
291 hbox
.pack_start(entry
, True, True, 0)
292 entry
.set_activates_default(True)
294 label
= g
.Label("Note: the 'text' group should only be used for types that can be "
295 "viewed in a normal text editor. For example, HTML is text/html, "
296 "but Word documents are in the 'application' group.\n"
297 "Unoffical types should start with 'x-'.")
298 label
.set_line_wrap(True)
299 vbox
.pack_start(label
, False, True, 0)
303 def response(w
, resp
):
304 if resp
== g
.RESPONSE_OK
:
305 type_name
= combo
.entry
.get_text() + '/' + entry
.get_text()
306 if type_name
.count('/') != 1 or type_name
.count(' '):
307 rox
.alert("Invalid MIME type name '%s'" % type_name
)
309 if type_name
in type.types
:
310 rox
.alert("Type '%s' already exists!" % type_name
)
312 __main__
.box
.show_type(type_name
)
314 type.add_type(type_name
)
316 self
.connect('response', response
)