1 # Copyright (C) 2009, Thomas Leonard
2 # See the README file for details, or visit http://0install.net.
4 from __future__
import print_function
10 from optparse
import OptionParser
12 from zeroinstall
import _
, SafeException
13 from zeroinstall
.injector
import requirements
14 from zeroinstall
.injector
.driver
import Driver
15 from zeroinstall
.injector
.config
import load_config
16 from zeroinstall
.support
import tasks
18 _recalculate
= tasks
.Blocker('recalculate')
21 """Ask the mainloop to recalculate. If we're already recalculating, wait for that to finish
22 and then do it again."""
24 _recalculate
.trigger()
25 _recalculate
= tasks
.Blocker('recalculate')
28 parser
= OptionParser(usage
=_("usage: %prog [options] interface"))
29 parser
.add_option("", "--apps", help=_("show app list"), action
='store_true')
30 parser
.add_option("", "--before", help=_("choose a version before this"), metavar
='VERSION')
31 parser
.add_option("", "--cpu", help=_("target CPU type"), metavar
='CPU')
32 parser
.add_option("", "--command", help=_("command to select"), metavar
='COMMAND')
33 parser
.add_option("-d", "--download-only", help=_("fetch but don't run"), action
='store_true')
34 parser
.add_option("-g", "--force-gui", help=_("display an error if there's no GUI"), action
='store_true')
35 parser
.add_option("", "--message", help=_("message to display when interacting with user"))
36 parser
.add_option("", "--not-before", help=_("minimum version to choose"), metavar
='VERSION')
37 parser
.add_option("", "--os", help=_("target operation system type"), metavar
='OS')
38 parser
.add_option("-r", "--refresh", help=_("check for updates of all interfaces"), action
='store_true')
39 parser
.add_option("", "--select-only", help=_("only download the feeds"), action
='store_true')
40 parser
.add_option("-s", "--source", help=_("select source code"), action
='store_true')
41 parser
.add_option("", "--systray", help=_("download in the background"), action
='store_true')
42 parser
.add_option("-v", "--verbose", help=_("more verbose output"), action
='count')
43 parser
.add_option("-V", "--version", help=_("display version information"), action
='store_true')
44 parser
.add_option("", "--with-store", help=_("add an implementation cache"), action
='append', metavar
='DIR')
46 parser
.disable_interspersed_args()
48 (options
, args
) = parser
.parse_args(args
)
51 logger
= logging
.getLogger()
52 if options
.verbose
== 1:
53 logger
.setLevel(logging
.INFO
)
55 logger
.setLevel(logging
.DEBUG
)
58 print("0launch-gui (zero-install) " + gui
.version
)
59 print("Copyright (C) 2010 Thomas Leonard")
60 print(_("This program comes with ABSOLUTELY NO WARRANTY,"
61 "\nto the extent permitted by law."
62 "\nYou may redistribute copies of this program"
63 "\nunder the terms of the GNU Lesser General Public License."
64 "\nFor more information about these matters, see the file named COPYING."))
72 fn("No GUI available", exc_info
= ex
)
75 with warnings
.catch_warnings():
76 if not options
.force_gui
:
77 warnings
.filterwarnings("ignore")
78 if sys
.version_info
[0] < 3:
80 import pygtk
; pygtk
.require('2.0')
81 except ImportError as ex
:
87 if sys
.version_info
[0] > 2:
88 from zeroinstall
.gtkui
import pygtkcompat
90 pygtkcompat
.enable_gtk(version
= '3.0')
92 except (ImportError, ValueError) as ex
:
95 if gtk
.gdk
.get_display() is None:
97 raise SafeException("Failed to connect to display.")
98 except SafeException
as ex
:
99 nogui(ex
) # logging needs this as a raised exception
102 from zeroinstall
.gtkui
.applistbox
import AppListBox
, AppList
103 from zeroinstall
.injector
.iface_cache
import iface_cache
104 box
= AppListBox(iface_cache
, AppList())
105 done
= tasks
.Blocker('close app list')
106 box
.window
.connect('destroy', lambda w
: done
.trigger())
108 tasks
.wait_for_blocker(done
)
111 handler
= gui
.GUIHandler()
113 config
= load_config(handler
)
115 if options
.with_store
:
116 from zeroinstall
import zerostore
117 for x
in options
.with_store
:
118 config
.stores
.stores
.append(zerostore
.Store(os
.path
.abspath(x
)))
124 box
= preferences
.show_preferences(config
)
125 done
= tasks
.Blocker('close preferences')
126 box
.connect('destroy', lambda w
: done
.trigger())
128 tasks
.wait_for_blocker(prefs_main())
131 interface_uri
= args
[0]
137 import mainwindow
, dialog
139 r
= requirements
.Requirements(interface_uri
)
140 r
.parse_options(options
)
142 widgets
= dialog
.Template('main')
144 driver
= Driver(config
= config
, requirements
= r
)
145 root_iface
= config
.iface_cache
.get_interface(interface_uri
)
146 driver
.solver
.record_details
= True
148 window
= mainwindow
.MainWindow(driver
, widgets
, download_only
= bool(options
.download_only
), select_only
= bool(options
.select_only
))
149 handler
.mainwindow
= window
152 window
.set_message(options
.message
)
154 root
= config
.iface_cache
.get_interface(r
.interface_uri
)
155 window
.browser
.set_root(root
)
157 window
.window
.connect('destroy', lambda w
: handler
.abort_all_downloads())
160 window
.use_systray_icon()
164 force_refresh
= bool(options
.refresh
)
166 window
.refresh_button
.set_sensitive(False)
167 window
.browser
.set_update_icons(force_refresh
)
169 solved
= driver
.solve_with_downloads(force
= force_refresh
, update_local
= True)
171 if not window
.systray_icon
:
175 window
.refresh_button
.set_sensitive(True)
176 window
.browser
.highlight_problems()
178 except Exception as ex
:
179 window
.report_exception(ex
)
181 if window
.systray_icon
and window
.systray_icon
.get_visible() and \
182 window
.systray_icon
.is_embedded():
183 if driver
.solver
.ready
:
184 window
.systray_icon
.set_tooltip(_('Downloading updates for %s') % root_iface
.get_name())
185 window
.run_button
.set_active(True)
187 # Should already be reporting an error, but
188 # blink it again just in case
189 window
.systray_icon
.set_blinking(True)
191 refresh_clicked
= dialog
.ButtonClickedBlocker(window
.refresh_button
)
192 yield refresh_clicked
, _recalculate
194 if refresh_clicked
.happened
:
197 tasks
.wait_for_blocker(main())