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, g
.gdk
.Color
)
163 view
= g
.TreeView(self
.model
)
167 cell
= g
.CellRendererText()
168 column
= g
.TreeViewColumn(type_name
, cell
, text
= 0, foreground_gdk
= 2)
169 view
.append_column(column
)
171 swin
.set_policy(g
.POLICY_NEVER
, g
.POLICY_AUTOMATIC
)
174 self
.add_button(g
.STOCK_ADD
, ADD
)
175 self
.add_button(g
.STOCK_DELETE
, DELETE
)
176 self
.add_button(g
.STOCK_PROPERTIES
, EDIT
)
177 self
.add_button(g
.STOCK_CLOSE
, g
.RESPONSE_CANCEL
)
178 def response(w
, resp
):
182 self
.delete_field(view
)
184 self
.edit_field(view
)
187 self
.connect('response', response
)
189 def changed(selection
):
190 model
, iter = selection
.get_selected()
193 path
= model
.get_path(iter)
194 on_field
= len(path
) > 1
195 self
.set_response_sensitive(ADD
, iter != None)
196 self
.set_response_sensitive(EDIT
, on_field
)
197 self
.set_response_sensitive(DELETE
, on_field
)
198 selection
= view
.get_selection()
199 selection
.connect('changed', changed
)
200 def may_change(path
):
203 iter = self
.model
.get_iter(path
)
204 field
= self
.model
.get_value(iter, 1)
206 selection
.set_select_function(may_change
)
209 def activate(view
, path
, column
):
210 iter = self
.model
.get_iter(path
)
211 field
= self
.model
.get_value(iter, 1)
213 self
.add_new_field(field
)
216 view
.connect('row-activated', activate
)
218 self
.set_default_response(g
.RESPONSE_CANCEL
)
220 label
= g
.Label("Shaded entries are provided by system packages and cannot "
221 "be edited or deleted. However, any information you add will "
222 "take precedence over them.")
223 label
.set_line_wrap(True)
224 self
.vbox
.pack_start(label
, False, True, 0)
229 grey
= self
.get_style().fg
[g
.STATE_INSENSITIVE
]
230 t
= type.get_type(self
.mime_type
)
232 for aspect
, getter
, klass
in [('Name matching', t
.get_globs
, type.Glob
),
233 ('Contents matching', t
.get_magic
, type.Magic
),
234 ('XML namespace matching', t
.get_xml
, type.XML
),
235 ('Others', t
.get_others
, type.Other
),
236 ('Descriptions', t
.get_comments
, type.Comment
)]:
237 iter = self
.model
.append(None)
238 self
.model
.set(iter, 0, aspect
, 1, klass
)
240 fields
.sort(lambda a
, b
: cmp(str(a
), str(b
)))
243 if field
== last
: continue
245 f
= self
.model
.append(iter)
247 self
.model
.set(f
, 0, str(field
), 1, field
)
249 self
.model
.set(f
, 0, str(field
), 1, field
, 2, grey
)
250 field
.add_subtree(self
.model
, f
, grey
)
251 self
.view
.expand_all()
253 def add_new_field(self
, klass
):
254 new
= klass(type.get_type(self
.mime_type
))
257 def add_field(self
, view
):
258 model
, iter = view
.get_selection().get_selected()
260 rox
.alert('You need to select a group, so I know what kind of thing to add')
262 path
= model
.get_path(iter)
263 field
= model
.get_value(model
.get_iter(path
[:1]), 1)
264 self
.add_new_field(field
)
266 def delete_field(self
, view
):
267 model
, iter = view
.get_selection().get_selected()
269 rox
.alert("Nothing selected!")
270 field
= model
.get_value(iter, 1)
274 def edit_field(self
, view
):
275 model
, iter = view
.get_selection().get_selected()
277 rox
.alert("Nothing selected!")
278 field
= model
.get_value(iter, 1)
282 class NewType(rox
.Dialog
):
284 rox
.Dialog
.__init
__(self
)
285 self
.set_title('Add new MIME type')
287 self
.add_button(g
.STOCK_CANCEL
, g
.RESPONSE_CANCEL
)
288 self
.add_button(g
.STOCK_ADD
, g
.RESPONSE_OK
)
289 self
.set_default_response(g
.RESPONSE_OK
)
291 vbox
= g
.VBox(False, 4)
292 self
.vbox
.pack_start(vbox
, True, True, 0)
293 vbox
.set_border_width(4)
295 hbox
= g
.HBox(False, 4)
296 vbox
.pack_start(hbox
, False, True, 0)
297 label
= g
.Label("Media type:")
298 hbox
.pack_start(label
, False, True, 0)
300 combo
.set_popdown_strings(["text", "application", "image", "audio",
301 "video", "message", "model"])
302 hbox
.pack_start(combo
, True, True, 0)
304 hbox
= g
.HBox(False, 4)
305 vbox
.pack_start(hbox
, False, True, 0)
306 label
= g
.Label("Subtype:")
307 hbox
.pack_start(label
, False, True, 0)
309 entry
.set_text('x-my-type')
310 hbox
.pack_start(entry
, True, True, 0)
311 entry
.set_activates_default(True)
313 label
= g
.Label("Note: the 'text' group should only be used for types that can be "
314 "viewed in a normal text editor. For example, HTML is text/html, "
315 "but Word documents are in the 'application' group.\n"
316 "Unoffical types should start with 'x-'.")
317 label
.set_line_wrap(True)
318 vbox
.pack_start(label
, False, True, 0)
322 def response(w
, resp
):
323 if resp
== g
.RESPONSE_OK
:
324 type_name
= combo
.entry
.get_text() + '/' + entry
.get_text()
325 if type_name
.count('/') != 1 or type_name
.count(' '):
326 rox
.alert("Invalid MIME type name '%s'" % type_name
)
328 if type_name
in type.types
:
329 rox
.alert("Type '%s' already exists!" % type_name
)
331 __main__
.box
.show_type(type_name
)
333 type.add_type(type_name
)
335 self
.connect('response', response
)