1 from zeroinstall
.injector
import policy
, namespaces
, model
2 from zeroinstall
.injector
.iface_cache
import iface_cache
6 from xml
.dom
import minidom
8 import tempfile
, shutil
10 addapp_uri
= "http://rox.sourceforge.net/2005/interfaces/AddApp"
12 class Policy(policy
.Policy
):
15 class NoMain(Exception):
18 class AppLauncher(saving
.Saveable
):
19 def __init__(self
, uri
):
24 self
.policy
= Policy(uri
)
25 self
.policy
.freshness
= 0 # No further updates
26 self
.policy
.network_use
= model
.network_offline
27 self
.policy
.recalculate()
28 iface
= iface_cache
.get_interface(uri
)
29 self
.impl
= self
.policy
.implementation
[iface
]
31 raise Exception("Failed to select an implementation of %s" % iface
)
32 if hasattr(self
.impl
, 'main'):
33 self
.main
= self
.impl
.main
35 self
.main
= iface
.main
37 raise NoMain("Interface '%s' cannot be executed directly; it is just a library "
38 "to be used by other programs (or missing 'main' attribute on the "
39 "root <interface> element)." % iface
.name
)
41 def save_to_file(self
, path
):
43 assert "'" not in self
.uri
44 iface
= iface_cache
.get_interface(self
.uri
)
46 apprun
= os
.fdopen(os
.open(os
.path
.join(path
, 'AppRun'), os
.O_CREAT | os
.O_WRONLY
, 0777), 'w')
47 if self
.uri
== 'http://rox.sourceforge.net/2005/interfaces/AddApp':
48 # Funky special case: AddApp behaves differently when run through AppRun
49 apprun
.write("""#!/bin/sh
50 if [ "$*" = "--versions" ]; then
52 elif [ "$*" = "" ]; then
53 exec 0launch '%s' --prompt
54 elif [ "$*" = "--help" ]; then
55 exec 0launch '%s' --show-help '%s'
57 exec 0launch '%s' -- "$@"
58 fi""" % (self
.uri
, self
.uri
, addapp_uri
, self
.uri
, self
.uri
))
60 if len(iface
.get_metadata(namespaces
.XMLNS_IFACE
, 'needs-terminal')):
61 xterm
= addapp_uri
+ ' --run-in-terminal '
64 apprun
.write("""#!/bin/sh
65 if [ "$*" = "--versions" ]; then
66 exec 0launch -gd '%(uri)s'
67 elif [ "$*" = "--help" ]; then
68 exec 0launch '%(addapp)s' --show-help '%(uri)s'
70 exec 0launch %(xterm)s'%(uri)s' "$@"
71 fi""" % {'uri': self
.uri
, 'addapp': addapp_uri
, 'xterm': xterm
})
75 shutil
.copyfile(self
.icon
, os
.path
.join(path
, '.DirIcon'))
77 doc
= self
.get_appinfo(iface
)
78 info_file
= file(os
.path
.join(path
, 'AppInfo.xml'), 'w')
79 doc
.writexml(info_file
)
82 if self
.is_applet(iface
):
83 appletrun
= os
.fdopen(os
.open(os
.path
.join(path
, 'AppletRun'),
84 os
.O_CREAT | os
.O_WRONLY
, 0777), 'w')
85 appletrun
.write("""#!/bin/sh
86 exec 0launch --main=AppletRun '%s' "$@"
90 def get_appinfo(self
, iface
):
91 impl_path
= self
.get_impl_path(self
.impl
)
93 appinfo
= os
.path
.join(impl_path
, os
.path
.dirname(self
.main
), 'AppInfo.xml')
97 if appinfo
and os
.path
.exists(appinfo
):
98 doc
= minidom
.parse(appinfo
)
100 doc
= minidom
.parseString("<?xml version='1.0'?>\n<AppInfo/>")
101 root
= doc
.documentElement
102 appmenu
= self
.get_item(root
, 'AppMenu')
103 self
.add_item(appmenu
, '--versions', {'en': 'Versions...'})
104 self
.add_item(appmenu
, '--help', {'en': 'Help'})
105 if not root
.getElementsByTagName('Summary'):
106 summary
= doc
.createElement('Summary')
107 summary
.appendChild(doc
.createTextNode('%s -- %s' % (iface
.name
, iface
.summary
)))
108 root
.appendChild(summary
)
109 for summary
in root
.getElementsByTagName('Summary'):
110 summary
.appendChild(doc
.createTextNode('\n(%s)' % iface
.uri
))
112 for about
in root
.getElementsByTagName('About'):
113 for version
in about
.getElementsByTagName('Version'):
114 if not version
.childNodes
: continue
115 for c
in version
.childNodes
:
116 version
.removeChild(c
)
117 version
.appendChild(doc
.createTextNode('(launcher)'))
120 def add_item(self
, menu
, option
, labels
):
121 doc
= menu
.ownerDocument
122 item
= doc
.createElement('Item')
123 kids
= menu
.childNodes
125 menu
.insertBefore(item
, kids
[0])
127 menu
.appendChild(item
)
128 item
.setAttribute('option', option
)
131 label
= doc
.createElement('Label')
132 item
.appendChild(label
)
133 label
.setAttribute('xml:lang', lang
)
134 label
.appendChild(doc
.createTextNode(labels
[lang
]))
136 def get_item(self
, parent
, name
):
137 items
= parent
.getElementsByTagName(name
)
140 item
= parent
.ownerDocument
.createElement(name
)
141 parent
.appendChild(item
)
144 def get_impl_path(self
, impl
):
145 if impl
.id.startswith('.') or impl
.id.startswith('/'):
147 elif impl
.id.startswith('package:'):
150 impl_path
= self
.policy
.get_implementation_path(impl
)
154 def is_applet(self
, iface
):
155 impl_path
= self
.get_impl_path(self
.impl
)
157 applet_run
= os
.path
.join(impl_path
, os
.path
.dirname(self
.main
), 'AppletRun')
158 return os
.path
.exists(applet_run
)
163 """Sets self.icon to a filename of an icon for the app (downloading it first), or None."""
165 if hasattr(iface_cache
, 'get_icon_path'):
166 iface
= iface_cache
.get_interface(self
.uri
)
167 path
= iface_cache
.get_icon_path(iface
)
172 # Older versions of 0launch...
174 from zeroinstall
.injector
import reader
, model
, basedir
, namespaces
175 if self
.uri
.startswith('/'):
178 cached
= basedir
.load_first_cache(namespaces
.config_site
, 'interfaces', model
.escape(self
.uri
))
180 print >>sys
.stderr
, "Internal error: interface '%s' still not cached!" % self
.uri
182 from xml
.dom
import minidom
183 doc
= minidom
.parse(cached
)
184 names
= doc
.documentElement
.getElementsByTagNameNS(namespaces
.XMLNS_IFACE
, 'icon')
186 type = x
.getAttribute('type')
187 if str(type) != 'image/png':
188 print "Skipping unknown icon type '%s'" % type
190 icon_uri
= x
.getAttribute('href')
191 print "Downloading icon from", icon_uri
193 icon_data
= urllib2
.urlopen(icon_uri
)
195 rox
.report_exception()
197 tmp
= tempfile
.NamedTemporaryFile()
198 shutil
.copyfileobj(icon_data
, tmp
)
205 def delete_icon(self
):
206 """Remove the temporary icon file, if any"""
207 self
._icon
_tmp
= None