Moved MIME handler installation into a separate module (mime_handler) and
[rox-lib.git] / python / rox / mime_handler.py
blob4f549a32e1f6efd5f107f82b5fce14e7f74e692c
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 annoys users
3 if programs fight over the defaults."""
5 import os
7 import rox
8 import rox.choices
9 from rox import _, mime
11 _TNAME = 0
12 _COMMENT = 1
13 _CURRENT = 2
14 _INSTALL = 3
16 class InstallList(rox.Dialog):
17 """Dialog to select installation of MIME type handlers"""
18 def __init__(self, application, itype, dir, types):
19 """Create the install list dialog.
20 application - path to application to install
21 itype - string describing the type of action to install
22 dir - directory in Choices to store links in
23 types - list of MIME types"""
24 rox.Dialog.__init__(self, title='Install %s' % itype,
25 buttons=(rox.g.STOCK_CANCEL, rox.g.RESPONSE_CLOSE,
26 rox.g.STOCK_OK, rox.g.RESPONSE_ACCEPT))
28 self.itype=itype
29 self.dir=dir
30 self.types=types
31 self.app=application
32 self.aname=os.path.basename(application)
34 vbox=self.vbox
36 swin = rox.g.ScrolledWindow()
37 swin.set_size_request(-1, 160)
38 swin.set_border_width(4)
39 swin.set_policy(rox.g.POLICY_NEVER, rox.g.POLICY_ALWAYS)
40 swin.set_shadow_type(rox.g.SHADOW_IN)
41 vbox.pack_start(swin, True, True, 0)
43 self.model = rox.g.ListStore(str, str, str, int)
44 view = rox.g.TreeView(self.model)
45 self.view = view
46 swin.add(view)
47 view.set_search_column(1)
49 cell = rox.g.CellRendererText()
50 column = rox.g.TreeViewColumn('Type', cell, text = _TNAME)
51 view.append_column(column)
52 column.set_sort_column_id(_TNAME)
54 cell = rox.g.CellRendererText()
55 column = rox.g.TreeViewColumn('Name', cell, text = _COMMENT)
56 view.append_column(column)
57 column.set_sort_column_id(_COMMENT)
59 cell = rox.g.CellRendererText()
60 column = rox.g.TreeViewColumn('Current', cell, text = _CURRENT)
61 view.append_column(column)
62 column.set_sort_column_id(_CURRENT)
64 cell = rox.g.CellRendererToggle()
65 cell.set_property('activatable', True)
66 cell.connect('toggled', self.toggled, self.model)
67 column = rox.g.TreeViewColumn('Install?', cell, active = _INSTALL)
68 view.append_column(column)
69 column.set_sort_column_id(_INSTALL)
71 view.get_selection().set_mode(rox.g.SELECTION_NONE)
73 vbox.show_all()
75 self.load_types()
77 def toggled(self, cell, path, model):
78 """Handle the CellRedererToggle stuff"""
79 if type(path) == str:
80 # Does this vary by pygtk version?
81 iter=model.iter_nth_child(None, int(path))
82 else:
83 iter=model.get_iter(path)
84 model.set_value(iter, _INSTALL, not cell.get_active())
86 def load_types(self):
87 """Load list of types into window"""
88 self.model.clear()
90 for tname in self.types:
91 type = mime.lookup(tname)
92 old=rox.choices.load(self.dir, '%s_%s' %
93 (type.media, type.subtype))
94 if old and os.path.islink(old):
95 old=os.readlink(old)
96 oname=os.path.basename(old)
97 elif old:
98 oname='script'
99 else:
100 oname=''
101 #print oname, old, self.app
102 if old==self.app:
103 dinstall=False
104 else:
105 dinstall=True
107 iter=self.model.append()
108 self.model.set(iter, _TNAME, tname, _COMMENT, type.get_comment(),
109 _CURRENT, oname, _INSTALL, dinstall)
111 def get_active(self):
112 """Return list of selected types"""
113 iter=self.model.get_iter_first()
114 active=[]
115 while iter:
116 if self.model.get_value(iter, _INSTALL):
117 active.append(self.model.get_value(iter, _TNAME))
118 iter=self.model.iter_next(iter)
120 return active
122 def _install_type_handler(types, dir, desc, application=None, overwrite=True):
123 if len(types)<1:
124 return
126 if not application:
127 application=rox.app_dir
128 if application[0]!='/':
129 application=os.path.abspath(application)
131 win=InstallList(application, desc, dir, types)
133 if win.run()!=rox.g.RESPONSE_ACCEPT:
134 win.destroy()
135 return
137 types=win.get_active()
139 for tname in types:
140 type = mime.lookup(tname)
142 sname=rox.choices.save(dir,
143 '%s_%s' % (type.media, type.subtype))
144 os.symlink(application, sname+'.tmp')
145 os.rename(sname+'.tmp', sname)
147 win.destroy()
149 def install_run_action(types, application=None, overwrite=True):
150 """Install application as the run action for 1 or more types.
151 application should be the full path to the AppDir.
152 If application is None then it is the running program which will
153 be installed. If overwrite is False then existing run actions will
154 not be changed. The user is asked to confirm the setting for each
155 type."""
156 _install_type_handler(types, "MIME-types", _("run action"),
157 application, overwrite)
159 def install_thumbnailer(types, application=None, overwrite=True):
160 """Install application as the thumbnail handler for 1 or more types.
161 application should be the full path to the AppDir.
162 If application is None then it is the running program which will
163 be installed. If overwrite is False then existing thumbnailerss will
164 not be changed. The user is asked to confirm the setting for each
165 type."""
166 _install_type_handler(types, "MIME-thumb", _("thumbnail handler"),
167 application, overwrite)
169 def install_from_appinfo(appdir = rox.app_dir):
170 """Read the AppInfo file from the AppDir and perform the installations
171 indicated. The elements to use are <CanThumbnail> and <CanRun>, each containing
172 a number of <MimeType type='...'/> elements.
173 appdir - Path to application (defaults to current app)
175 import rox.AppInfo
177 app_info_path = os.path.join(appdir, 'AppInfo.xml')
178 ainfo = rox.AppInfo.AppInfo(app_info_path)
180 can_run = ainfo.getCanRun()
181 can_thumbnail = ainfo.getCanThumbnail()
182 if can_run or can_thumbnail:
183 install_run_action(can_run, appdir)
184 install_thumbnailer(can_thumbnail, appdir)
185 else:
186 raise Exception('Internal error: No actions found in %s. '
187 'Check your namespaces!' % app_info_path)