1 """This module allows applications to set themselves as the default handler for
2 a particular MIME type. This is generally not a good thing to do, because it
3 annoys users if programs fight over the defaults."""
8 from rox
import _
, mime
, choices
16 _IS_OURS
= 6 # Hidden column
18 class InstallList(rox
.Dialog
):
19 """Dialog to select installation of MIME type handlers"""
20 def __init__(self
, application
, itype
, dir, types
, info
=None, check
=True):
21 """Create the install list dialog.
22 application - path to application to install
23 itype - string describing the type of action to install
24 dir - directory in Choices to store links in
25 types - list of MIME types
26 info - optional message to display below list
27 check - if true (the default), check for existing entries"""
28 rox
.Dialog
.__init
__(self
, title
='Install %s' % itype
,
29 buttons
=(rox
.g
.STOCK_CANCEL
, rox
.g
.RESPONSE_CLOSE
,
30 rox
.g
.STOCK_OK
, rox
.g
.RESPONSE_ACCEPT
))
36 self
.aname
=os
.path
.basename(application
)
41 swin
= rox
.g
.ScrolledWindow()
42 swin
.set_size_request(-1, 160)
43 swin
.set_border_width(4)
44 swin
.set_policy(rox
.g
.POLICY_NEVER
, rox
.g
.POLICY_ALWAYS
)
45 swin
.set_shadow_type(rox
.g
.SHADOW_IN
)
46 vbox
.pack_start(swin
, True, True, 0)
48 self
.model
= rox
.g
.ListStore(str, str, str, int, rox
.g
.gdk
.Pixbuf
,
50 view
= rox
.g
.TreeView(self
.model
)
53 view
.set_search_column(1)
55 cell
= rox
.g
.CellRendererPixbuf()
56 column
= rox
.g
.TreeViewColumn('', cell
, pixbuf
= _ICON
)
57 view
.append_column(column
)
59 cell
= rox
.g
.CellRendererText()
60 column
= rox
.g
.TreeViewColumn('Type', cell
, text
= _TNAME
)
61 view
.append_column(column
)
62 column
.set_sort_column_id(_TNAME
)
64 cell
= rox
.g
.CellRendererText()
65 column
= rox
.g
.TreeViewColumn('Name', cell
, text
= _COMMENT
)
66 view
.append_column(column
)
67 column
.set_sort_column_id(_COMMENT
)
70 cell
= rox
.g
.CellRendererText()
71 column
= rox
.g
.TreeViewColumn('Current', cell
, text
= _CURRENT
)
72 view
.append_column(column
)
73 column
.set_sort_column_id(_CURRENT
)
75 cell
= rox
.g
.CellRendererToggle()
76 cell
.set_property('activatable', True)
77 cell
.connect('toggled', self
.install_toggled
, self
.model
)
78 column
= rox
.g
.TreeViewColumn('Install?', cell
, active
= _INSTALL
)
79 view
.append_column(column
)
80 column
.set_sort_column_id(_INSTALL
)
82 cell
= rox
.g
.CellRendererToggle()
83 cell
.connect('toggled', self
.uninstall_toggled
, self
.model
)
84 column
= rox
.g
.TreeViewColumn('Uninstall?', cell
, active
= _UNINSTALL
,
85 activatable
= _IS_OURS
)
86 view
.append_column(column
)
87 column
.set_sort_column_id(_UNINSTALL
)
89 view
.get_selection().set_mode(rox
.g
.SELECTION_NONE
)
92 hbox
=rox
.g
.HBox(spacing
=4)
93 img
=rox
.g
.image_new_from_stock(rox
.g
.STOCK_DIALOG_INFO
,
94 rox
.g
.ICON_SIZE_DIALOG
)
98 lbl
.set_line_wrap(True)
101 vbox
.pack_start(hbox
)
107 def install_toggled(self
, cell
, path
, model
):
108 """Handle the CellRedererToggle stuff for the install column"""
109 if type(path
) == str:
110 # Does this vary by pygtk version?
111 titer
=model
.iter_nth_child(None, int(path
))
113 titer
=model
.get_iter(path
)
114 model
.set_value(titer
, _INSTALL
, not cell
.get_active())
115 if not cell
.get_active():
116 model
.set_value(titer
, _UNINSTALL
, 0)
118 def uninstall_toggled(self
, cell
, path
, model
):
119 """Handle the CellRedererToggle stuff for the uninstall column"""
120 if type(path
) == str:
121 # Does this vary by pygtk version?
122 titer
=model
.iter_nth_child(None, int(path
))
124 titer
=model
.get_iter(path
)
125 avail
=model
.get_value(titer
, _IS_OURS
)
127 model
.set_value(titer
, _UNINSTALL
, not cell
.get_active())
128 if not cell
.get_active():
129 model
.set_value(titer
, _INSTALL
, 0)
131 model
.set_value(titer
, _UNINSTALL
, 0)
133 def load_types(self
):
134 """Load list of types into window"""
137 for tname
in self
.types
:
138 mime_type
=mime
.lookup(tname
)
140 old
=choices
.load(self
.dir, '%s_%s' %
141 (mime_type
.media
, mime_type
.subtype
))
142 if old
and os
.path
.islink(old
):
144 oname
=os
.path
.basename(old
)
161 icon
=mime_type
.get_icon(mime
.ICON_SIZE_SMALL
)
163 titer
=self
.model
.append()
164 self
.model
.set(titer
, _TNAME
, tname
,
165 _COMMENT
, mime_type
.get_comment(),
167 _UNINSTALL
, False, _IS_OURS
, can_un
)
169 self
.model
.set(titer
, _CURRENT
, oname
)
171 self
.model
.set(titer
, _ICON
, icon
)
174 def get_active(self
):
175 """Return list of types selected for installing"""
176 titer
=self
.model
.get_iter_first()
179 if self
.model
.get_value(titer
, _INSTALL
):
180 active
.append(self
.model
.get_value(titer
, _TNAME
))
181 titer
=self
.model
.iter_next(titer
)
185 def get_uninstall(self
):
186 """Return list of types selected for uninstalling"""
187 titer
=self
.model
.get_iter_first()
190 if self
.model
.get_value(titer
, _UNINSTALL
) and self
.model
.get_value(titer
, _IS_OURS
):
191 uninstall
.append(self
.model
.get_value(titer
, _TNAME
))
192 titer
=self
.model
.iter_next(titer
)
197 def _install_type_handler(types
, dir, desc
, application
=None, overwrite
=True,
199 """Internal function. Does the work of setting MIME-types or MIME-thumb"""
204 application
=rox
.app_dir
205 if application
[0]!='/':
206 application
=os
.path
.abspath(application
)
208 win
=InstallList(application
, desc
, dir, types
, info
)
210 if win
.run()!=rox
.g
.RESPONSE_ACCEPT
:
215 types
=win
.get_active()
218 mime_type
= mime
.lookup(tname
)
220 sname
=choices
.save(dir,
221 '%s_%s' % (mime_type
.media
, mime_type
.subtype
))
222 os
.symlink(application
, sname
+'.tmp')
223 os
.rename(sname
+'.tmp', sname
)
225 types
=win
.get_uninstall()
228 mime_type
= mime
.lookup(tname
)
230 sname
=choices
.save(dir,
231 '%s_%s' % (mime_type
.media
, mime_type
.subtype
))
236 run_action_msg
=_("""Run actions can be changed by selecting a file of the appropriate type in the Filer and selecting the menu option 'Set Run Action...'""")
237 def install_run_action(types
, application
=None, overwrite
=True):
238 """Install application as the run action for 1 or more types.
239 application should be the full path to the AppDir.
240 If application is None then it is the running program which will
241 be installed. If overwrite is False then existing run actions will
242 not be changed. The user is asked to confirm the setting for each
244 _install_type_handler(types
, "MIME-types", _("run action"),
245 application
, overwrite
, run_action_msg
)
247 def install_thumbnailer(types
, application
=None, overwrite
=True):
248 """Install application as the thumbnail handler for 1 or more types.
249 application should be the full path to the AppDir.
250 If application is None then it is the running program which will
251 be installed. If overwrite is False then existing thumbnailerss will
252 not be changed. The user is asked to confirm the setting for each
254 _install_type_handler(types
, "MIME-thumb", _("thumbnail handler"),
255 application
, overwrite
, _("""Thumbnail handlers provide support for creating thumbnail images of types of file. The filer can generate thumbnails for most types of image (JPEG, PNG, etc.) but relies on helper applications for the others."""))
257 def install_send_to_types(types
, application
=None):
258 """Install application in the SendTo menu for 1 or more types.
259 application should be the full path to the AppDir.
260 If application is None then it is the running program which will
261 be installed. The user is asked to confirm the setting for each
267 application
=rox
.app_dir
268 if application
[0]!='/':
269 application
=os
.path
.abspath(application
)
271 win
=InstallList(application
, _('type handler'), 'SendTo', types
,
272 _("""The application can handle files of these types. Click on OK to add it to the SendTo menu for the type of file, and also the customized File menu."""),
275 if win
.run()!=rox
.g
.RESPONSE_ACCEPT
:
279 types
=win
.get_active()
282 mime_type
=mime
.lookup(tname
)
284 sname
=choices
.save('SendTo/.%s_%s' % (mime_type
.media
,
287 os
.symlink(application
, sname
+'.tmp')
288 os
.rename(sname
+'.tmp', sname
)
290 types
=win
.get_uninstall()
293 mime_type
=mime
.lookup(tname
)
295 sname
=choices
.save('SendTo/.%s_%s' % (mime_type
.media
,
302 def install_from_appinfo(appdir
= rox
.app_dir
):
303 """Read the AppInfo file from the AppDir and perform the installations
304 indicated. The elements to use are <CanThumbnail> and <CanRun>, each containing
305 a number of <MimeType type='...'/> elements.
306 appdir - Path to application (defaults to current app)
310 app_info_path
= os
.path
.join(appdir
, 'AppInfo.xml')
311 ainfo
= rox
.AppInfo
.AppInfo(app_info_path
)
313 can_run
= ainfo
.getCanRun()
314 can_thumbnail
= ainfo
.getCanThumbnail()
315 if can_run
or can_thumbnail
:
316 install_run_action(can_run
, appdir
)
317 install_thumbnailer(can_thumbnail
, appdir
)
318 install_send_to_types(can_run
, appdir
)
320 raise Exception('Internal error: No actions found in %s. '
321 'Check your namespaces!' % app_info_path
)