Add support for native Gentoo packages
[zeroinstall.git] / zeroinstall / 0launch-gui / main.py
blobc8d60cf1e05810ec697fd25dd12169ef629468a3
1 # Copyright (C) 2009, Thomas Leonard
2 # See the README file for details, or visit http://0install.net.
4 import os, sys
6 from optparse import OptionParser
8 from zeroinstall.injector import model, arch
9 from zeroinstall.injector.policy import Policy
10 from zeroinstall.injector.iface_cache import iface_cache
11 from zeroinstall.support import tasks
13 def run_gui(args):
14 parser = OptionParser(usage=_("usage: %prog [options] interface"))
15 parser.add_option("", "--before", help=_("choose a version before this"), metavar='VERSION')
16 parser.add_option("", "--cpu", help=_("target CPU type"), metavar='CPU')
17 parser.add_option("-c", "--cache", help=_("show the cache"), action='store_true')
18 parser.add_option("-d", "--download-only", help=_("fetch but don't run"), action='store_true')
19 parser.add_option("", "--message", help=_("message to display when interacting with user"))
20 parser.add_option("", "--not-before", help=_("minimum version to choose"), metavar='VERSION')
21 parser.add_option("", "--os", help=_("target operation system type"), metavar='OS')
22 parser.add_option("-r", "--refresh", help=_("check for updates of all interfaces"), action='store_true')
23 parser.add_option("-s", "--source", help=_("select source code"), action='store_true')
24 parser.add_option("", "--systray", help=_("download in the background"), action='store_true')
25 parser.add_option("-v", "--verbose", help=_("more verbose output"), action='count')
26 parser.add_option("-V", "--version", help=_("display version information"), action='store_true')
27 parser.add_option("", "--with-store", help=_("add an implementation cache"), action='append', metavar='DIR')
29 parser.disable_interspersed_args()
31 (options, args) = parser.parse_args(args)
33 if options.verbose:
34 import logging
35 logger = logging.getLogger()
36 if options.verbose == 1:
37 logger.setLevel(logging.INFO)
38 else:
39 logger.setLevel(logging.DEBUG)
41 if options.cache:
42 # Must fork before importing gtk, or ATK dies
43 if os.fork():
44 # We exit, so our parent can call waitpid and unblock.
45 sys.exit(0)
46 # The grandchild continues...
48 if options.with_store:
49 from zeroinstall import zerostore
50 for x in options.with_store:
51 iface_cache.stores.stores.append(zerostore.Store(os.path.abspath(x)))
53 import gui
55 if options.version:
56 print "0launch-gui (zero-install) " + gui.version
57 print "Copyright (C) 2009 Thomas Leonard"
58 print _("This program comes with ABSOLUTELY NO WARRANTY,"
59 "\nto the extent permitted by law."
60 "\nYou may redistribute copies of this program"
61 "\nunder the terms of the GNU Lesser General Public License."
62 "\nFor more information about these matters, see the file named COPYING.")
63 sys.exit(0)
65 import gtk
66 if gtk.gdk.get_display() is None:
67 print >>sys.stderr, "Failed to connect to display. Aborting."
68 sys.exit(1)
70 if not hasattr(gtk, 'combo_box_new_text'):
71 import combo_compat
73 if options.cache:
74 import cache
75 cache_explorer = cache.CacheExplorer()
76 cache_explorer.show()
77 cache_explorer.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
78 gtk.gdk.flush()
79 cache_explorer.populate_model()
80 cache_explorer.window.set_cursor(None)
81 gtk.main()
82 sys.exit(0)
84 handler = gui.GUIHandler()
86 if len(args) < 1:
87 import preferences
88 # Once we separate configuration from Policy, this hack can go away
89 class DummyPolicy(Policy):
90 def recalculate(fetch_stale_interfaces = True):
91 pass
92 def solve_with_downloads(force = False):
93 pass
94 box = preferences.show_preferences(DummyPolicy('http://localhost/dummy', handler))
95 box.connect('destroy', gtk.main_quit)
96 gtk.main()
97 sys.exit(0)
99 interface_uri = args[0]
101 if len(args) > 1:
102 parser.print_help()
103 sys.exit(1)
105 import mainwindow, dialog
107 restrictions = []
108 if options.before or options.not_before:
109 restrictions.append(model.VersionRangeRestriction(model.parse_version(options.before),
110 model.parse_version(options.not_before)))
112 widgets = dialog.Template('main')
114 policy = Policy(interface_uri, handler, src = bool(options.source))
115 policy.target_arch = arch.get_architecture(options.os, options.cpu)
116 root_iface = iface_cache.get_interface(interface_uri)
117 policy.solver.extra_restrictions[root_iface] = restrictions
118 policy.solver.record_details = True
120 window = mainwindow.MainWindow(policy, widgets, download_only = bool(options.download_only))
121 handler.mainwindow = window
123 if options.message:
124 window.set_message(options.message)
126 root = iface_cache.get_interface(policy.root)
127 window.browser.set_root(root)
129 window.window.connect('destroy', lambda w: handler.abort_all_downloads())
131 if options.systray:
132 window.use_systray_icon()
134 @tasks.async
135 def main():
136 force_refresh = bool(options.refresh)
137 while True:
138 window.refresh_button.set_sensitive(False)
139 window.browser.set_update_icons(force_refresh)
141 solved = policy.solve_with_downloads(force = force_refresh)
143 if not window.systray_icon:
144 window.show()
145 yield solved
146 try:
147 window.refresh_button.set_sensitive(True)
148 tasks.check(solved)
149 except Exception, ex:
150 window.report_exception(ex)
152 if window.systray_icon and window.systray_icon.get_visible() and \
153 window.systray_icon.is_embedded():
154 if policy.ready:
155 window.systray_icon.set_tooltip(_('Downloading updates for %s') % root_iface.get_name())
156 window.run_button.set_active(True)
157 else:
158 # Should already be reporting an error, but
159 # blink it again just in case
160 window.systray_icon.set_blinking(True)
162 yield dialog.ButtonClickedBlocker(window.refresh_button)
163 force_refresh = True
165 handler.wait_for_blocker(main())