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
)
36 view
.set_search_column(1)
38 cell
= g
.CellRendererText()
39 column
= g
.TreeViewColumn('MIME-Type', cell
, text
= 0)
40 view
.append_column(column
)
41 column
.set_sort_column_id(0)
43 cell
= g
.CellRendererText()
44 column
= g
.TreeViewColumn('Description', cell
, text
= 1)
45 view
.append_column(column
)
46 column
.set_sort_column_id(1)
48 view
.connect('row-activated', self
.activate
)
52 def response(self
, resp
):
54 self
.edit_selected(view
.get_selection())
56 self
.delete_type(view
)
59 self
.add_type
.present()
61 self
.add_type
= NewType()
62 def destroyed(widget
): self
.add_type
= None
63 self
.add_type
.connect('destroy', destroyed
)
67 self
.connect('response', response
)
69 def changed(selection
):
70 model
, iter = selection
.get_selected()
71 self
.set_response_sensitive(EDIT
, iter != None)
72 self
.set_response_sensitive(DELETE
, iter != None)
73 selection
= view
.get_selection()
74 selection
.connect('changed', changed
)
77 def delete_type(self
, view
):
78 model
, iter = view
.get_selection().get_selected()
80 rox
.alert('Nothing selected')
82 type_name
= model
.get_value(iter, 0)
83 type.delete_type(type_name
)
86 self
.set_title('Scanning... please wait')
91 self
.mime_model
.clear()
96 return cmp(a
[1], b
[1])
98 return a
[:1].upper() + a
[1:]
99 items
= [(t
, caps(t
.get_comment())) for t
in type.types
.values()]
100 items
.sort(items_cmp
)
102 iter = self
.mime_model
.append(None)
103 self
.mime_model
.set(iter, 1, c
, 0, t
.get_name())
105 self
.set_title('MIME-Editor')
107 for b
in edit_boxes
.values():
108 if b
.mime_type
in type.types
:
113 def activate(self
, view
, path
, column
):
114 iter = self
.mime_model
.get_iter(path
)
115 type_name
= self
.mime_model
.get_value(iter, 0)
118 def edit(self
, type_name
):
119 if type_name
in edit_boxes
:
120 edit_boxes
[type_name
].present()
122 box
= EditBox(type_name
)
123 edit_boxes
[type_name
] = box
124 def destroy(dialog
): del edit_boxes
[type_name
]
125 box
.connect('destroy', destroy
)
128 def edit_selected(self
, selection
):
129 model
, iter = selection
.get_selected()
131 rox
.alert('You need to select a type to edit first')
133 type_name
= model
.get_value(iter, 0)
136 class EditBox(rox
.Dialog
):
137 def __init__(self
, type_name
):
138 rox
.Dialog
.__init
__(self
)
139 self
.set_has_separator(False)
140 self
.set_default_size(-1, 400)
141 self
.mime_type
= type_name
143 self
.set_title('MIME-Editor: %s' % type_name
)
145 swin
= g
.ScrolledWindow()
146 swin
.set_border_width(4)
147 swin
.set_shadow_type(g
.SHADOW_IN
)
148 self
.vbox
.pack_start(swin
, True, True, 0)
150 self
.model
= g
.TreeStore(str, object)
151 view
= g
.TreeView(self
.model
)
154 cell
= g
.CellRendererText()
155 column
= g
.TreeViewColumn(type_name
, cell
, text
= 0)
156 view
.append_column(column
)
158 swin
.set_policy(g
.POLICY_NEVER
, g
.POLICY_AUTOMATIC
)
164 self
.add_button(g
.STOCK_ADD
, ADD
)
165 self
.add_button(g
.STOCK_DELETE
, DELETE
)
166 self
.add_button(g
.STOCK_PROPERTIES
, EDIT
)
167 self
.add_button(g
.STOCK_CLOSE
, g
.RESPONSE_CANCEL
)
168 def response(w
, resp
):
172 self
.delete_field(view
)
174 self
.edit_field(view
)
177 self
.connect('response', response
)
179 def changed(selection
):
180 model
, iter = selection
.get_selected()
183 path
= model
.get_path(iter)
184 on_field
= len(path
) > 1
185 self
.set_response_sensitive(ADD
, iter != None)
186 self
.set_response_sensitive(EDIT
, on_field
)
187 self
.set_response_sensitive(DELETE
, on_field
)
188 selection
= view
.get_selection()
189 selection
.connect('changed', changed
)
192 def activate(view
, path
, column
):
193 iter = self
.model
.get_iter(path
)
194 field
= self
.model
.get_value(iter, 1)
196 self
.add_new_field(field
)
199 view
.connect('row-activated', activate
)
201 self
.set_default_response(g
.RESPONSE_CANCEL
)
204 t
= type.get_type(self
.mime_type
)
206 for aspect
, getter
, klass
in [('Name matching', t
.get_globs
, type.Glob
),
207 ('Contents matching', t
.get_magic
, type.Magic
),
208 ('XML namespace matching', t
.get_xml
, type.XML
),
209 ('Others', t
.get_others
, type.Other
),
210 ('Descriptions', t
.get_comments
, type.Comment
)]:
211 iter = self
.model
.append(None)
212 self
.model
.set(iter, 0, aspect
, 1, klass
)
214 fields
.sort(lambda a
, b
: cmp(str(a
), str(b
)))
217 if field
== last
: continue
219 f
= self
.model
.append(iter)
220 self
.model
.set(f
, 0, str(field
), 1, field
)
221 field
.add_subtree(self
.model
, f
)
223 def add_new_field(self
, type):
224 rox
.alert("TODO: Add field of type '%s'" % type)
226 def add_field(self
, view
):
227 model
, iter = view
.get_selection().get_selected()
229 rox
.alert('You need to select a group, so I know what kind of thing to add')
231 path
= model
.get_path(iter)
232 field
= model
.get_value(model
.get_iter(path
[:1]), 1)
233 self
.add_new_field(field
)
235 def delete_field(self
, view
):
236 model
, iter = view
.get_selection().get_selected()
238 rox
.alert("Nothing selected!")
239 field
= model
.get_value(iter, 1)
243 def edit_field(self
, view
):
244 model
, iter = view
.get_selection().get_selected()
246 rox
.alert("Nothing selected!")
247 field
= model
.get_value(iter, 1)
251 class NewType(rox
.Dialog
):
253 rox
.Dialog
.__init
__(self
)
254 self
.set_title('Add new MIME type')
256 self
.add_button(g
.STOCK_CANCEL
, g
.RESPONSE_CANCEL
)
257 self
.add_button(g
.STOCK_ADD
, g
.RESPONSE_OK
)
258 self
.set_default_response(g
.RESPONSE_OK
)
260 vbox
= g
.VBox(False, 4)
261 self
.vbox
.pack_start(vbox
, True, True, 0)
262 vbox
.set_border_width(4)
264 hbox
= g
.HBox(False, 4)
265 vbox
.pack_start(hbox
, False, True, 0)
266 label
= g
.Label("Media type:")
267 hbox
.pack_start(label
, False, True, 0)
269 combo
.set_popdown_strings(["text", "application", "image", "audio",
270 "video", "message", "model"])
271 hbox
.pack_start(combo
, True, True, 0)
273 hbox
= g
.HBox(False, 4)
274 vbox
.pack_start(hbox
, False, True, 0)
275 label
= g
.Label("Subtype:")
276 hbox
.pack_start(label
, False, True, 0)
278 entry
.set_text('x-my-type')
279 hbox
.pack_start(entry
, True, True, 0)
280 entry
.set_activates_default(True)
282 label
= g
.Label("Note: the 'text' group should only be used for types that can be "
283 "viewed in a normal text editor. For example, HTML is text/html, "
284 "but Word documents are in the 'application' group.\n"
285 "Unoffical types should start with 'x-'.")
286 label
.set_line_wrap(True)
287 vbox
.pack_start(label
, False, True, 0)
291 def response(w
, resp
):
292 if resp
== g
.RESPONSE_OK
:
293 type_name
= combo
.entry
.get_text() + '/' + entry
.get_text()
294 if type_name
.count('/') != 1 or type_name
.count(' '):
295 rox
.alert("Invalid MIME type name '%s'" % type_name
)
297 if type_name
in type.types
:
298 rox
.alert("Type '%s' already exists!" % type_name
)
300 type.add_type(type_name
)
302 self
.connect('response', response
)