Moved Config into its own module
[zeroinstall/zeroinstall-afb.git] / zeroinstall / 0launch-gui / main.py
blobf1b49964c4ea862f719a1240ccab086a551a6cc3
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 requirements
9 from zeroinstall.injector.policy import Policy
10 from zeroinstall.injector.config import load_config
11 from zeroinstall.support import tasks
13 _recalculate = tasks.Blocker('recalculate')
15 def recalculate():
16 """Ask the mainloop to recalculate. If we're already recalculating, wait for that to finish
17 and then do it again."""
18 global _recalculate
19 _recalculate.trigger()
20 _recalculate = tasks.Blocker('recalculate')
22 def run_gui(args):
23 parser = OptionParser(usage=_("usage: %prog [options] interface"))
24 parser.add_option("", "--before", help=_("choose a version before this"), metavar='VERSION')
25 parser.add_option("", "--cpu", help=_("target CPU type"), metavar='CPU')
26 parser.add_option("", "--command", help=_("command to select"), metavar='COMMAND')
27 parser.add_option("-d", "--download-only", help=_("fetch but don't run"), action='store_true')
28 parser.add_option("", "--message", help=_("message to display when interacting with user"))
29 parser.add_option("", "--not-before", help=_("minimum version to choose"), metavar='VERSION')
30 parser.add_option("", "--os", help=_("target operation system type"), metavar='OS')
31 parser.add_option("-r", "--refresh", help=_("check for updates of all interfaces"), action='store_true')
32 parser.add_option("", "--select-only", help=_("only download the feeds"), action='store_true')
33 parser.add_option("-s", "--source", help=_("select source code"), action='store_true')
34 parser.add_option("", "--systray", help=_("download in the background"), action='store_true')
35 parser.add_option("-v", "--verbose", help=_("more verbose output"), action='count')
36 parser.add_option("-V", "--version", help=_("display version information"), action='store_true')
37 parser.add_option("", "--with-store", help=_("add an implementation cache"), action='append', metavar='DIR')
39 parser.disable_interspersed_args()
41 (options, args) = parser.parse_args(args)
43 if options.verbose:
44 import logging
45 logger = logging.getLogger()
46 if options.verbose == 1:
47 logger.setLevel(logging.INFO)
48 else:
49 logger.setLevel(logging.DEBUG)
51 import gui
53 if options.version:
54 print "0launch-gui (zero-install) " + gui.version
55 print "Copyright (C) 2010 Thomas Leonard"
56 print _("This program comes with ABSOLUTELY NO WARRANTY,"
57 "\nto the extent permitted by law."
58 "\nYou may redistribute copies of this program"
59 "\nunder the terms of the GNU Lesser General Public License."
60 "\nFor more information about these matters, see the file named COPYING.")
61 sys.exit(0)
63 import gtk
64 if gtk.gdk.get_display() is None:
65 print >>sys.stderr, "Failed to connect to display. Aborting."
66 sys.exit(1)
68 handler = gui.GUIHandler()
70 config = load_config(handler)
72 if options.with_store:
73 from zeroinstall import zerostore
74 for x in options.with_store:
75 config.stores.stores.append(zerostore.Store(os.path.abspath(x)))
77 if len(args) < 1:
78 import preferences
79 box = preferences.show_preferences(config)
80 box.connect('destroy', gtk.main_quit)
81 gtk.main()
82 sys.exit(0)
84 interface_uri = args[0]
86 if len(args) > 1:
87 parser.print_help()
88 sys.exit(1)
90 import mainwindow, dialog
92 r = requirements.Requirements(interface_uri)
93 r.parse_options(options)
95 widgets = dialog.Template('main')
97 policy = Policy(config = config, requirements = r)
98 root_iface = config.iface_cache.get_interface(interface_uri)
99 policy.solver.record_details = True
101 window = mainwindow.MainWindow(policy, widgets, download_only = bool(options.download_only), select_only = bool(options.select_only))
102 handler.mainwindow = window
104 if options.message:
105 window.set_message(options.message)
107 root = config.iface_cache.get_interface(policy.root)
108 window.browser.set_root(root)
110 window.window.connect('destroy', lambda w: handler.abort_all_downloads())
112 if options.systray:
113 window.use_systray_icon()
115 @tasks.async
116 def main():
117 force_refresh = bool(options.refresh)
118 while True:
119 window.refresh_button.set_sensitive(False)
120 window.browser.set_update_icons(force_refresh)
122 solved = policy.solve_with_downloads(force = force_refresh, update_local = True)
124 if not window.systray_icon:
125 window.show()
126 yield solved
127 try:
128 window.refresh_button.set_sensitive(True)
129 window.browser.highlight_problems()
130 tasks.check(solved)
131 except Exception, ex:
132 window.report_exception(ex)
134 if window.systray_icon and window.systray_icon.get_visible() and \
135 window.systray_icon.is_embedded():
136 if policy.ready:
137 window.systray_icon.set_tooltip(_('Downloading updates for %s') % root_iface.get_name())
138 window.run_button.set_active(True)
139 else:
140 # Should already be reporting an error, but
141 # blink it again just in case
142 window.systray_icon.set_blinking(True)
144 refresh_clicked = dialog.ButtonClickedBlocker(window.refresh_button)
145 yield refresh_clicked, _recalculate
147 if refresh_clicked.happened:
148 force_refresh = True
150 tasks.wait_for_blocker(main())