def __init__(self, policy, widgets, download_only, select_only = False): self.policy = policy self.select_only = select_only def update_ok_state(): self.window.set_response_sensitive(gtk.RESPONSE_OK, policy.solver.ready) if policy.solver.ready and self.window.get_focus() is None: run_button.grab_focus() policy.watchers.append(update_ok_state) self.window = widgets.get_widget('main') self.window.set_default_size(gtk.gdk.screen_width() * 2 / 5, 300) self.progress = widgets.get_widget('progress') self.progress_area = widgets.get_widget('progress_area') self.comment = widgets.get_widget('comment') widgets.get_widget('stop').connect('clicked', lambda b: policy.handler.abort_all_downloads()) self.refresh_button = widgets.get_widget('refresh') # Tree view self.browser = InterfaceBrowser(policy, widgets) prefs = widgets.get_widget('preferences') self.window.action_area.set_child_secondary(prefs, True) # Glade won't let me add this to the template! if select_only: run_button = dialog.MixedButton(_("_Select"), gtk.STOCK_EXECUTE, button = gtk.ToggleButton()) elif download_only: run_button = dialog.MixedButton(_("_Download"), gtk.STOCK_EXECUTE, button = gtk.ToggleButton()) else: run_button = dialog.MixedButton(_("_Run"), gtk.STOCK_EXECUTE, button = gtk.ToggleButton()) self.window.add_action_widget(run_button, gtk.RESPONSE_OK) run_button.show_all() run_button.set_flags(gtk.CAN_DEFAULT) self.run_button = run_button run_button.grab_focus() def response(dialog, resp): if resp in (gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT): self.window.destroy() sys.exit(1) elif resp == gtk.RESPONSE_OK: if self.cancel_download_and_run: self.cancel_download_and_run.trigger() if run_button.get_active(): self.cancel_download_and_run = tasks.Blocker("cancel downloads") self.download_and_run(run_button, self.cancel_download_and_run) elif resp == gtk.RESPONSE_HELP: gui_help.display() elif resp == SHOW_PREFERENCES: import preferences preferences.show_preferences(policy.config, notify_cb = lambda: policy.solve_with_downloads()) self.window.connect('response', response) self.window.realize() # Make busy pointer work, even with --systray
class MainWindow: progress = None progress_area = None browser = None window = None cancel_download_and_run = None policy = None comment = None systray_icon = None systray_icon_blocker = None def __init__(self, policy, widgets, download_only, select_only=False): self.policy = policy self.select_only = select_only def update_ok_state(): self.window.set_response_sensitive(gtk.RESPONSE_OK, policy.solver.ready) if policy.solver.ready and self.window.get_focus() is None: run_button.grab_focus() policy.watchers.append(update_ok_state) self.window = widgets.get_widget('main') self.window.set_default_size(gtk.gdk.screen_width() * 2 / 5, 300) self.progress = widgets.get_widget('progress') self.progress_area = widgets.get_widget('progress_area') self.comment = widgets.get_widget('comment') widgets.get_widget('stop').connect( 'clicked', lambda b: policy.handler.abort_all_downloads()) self.refresh_button = widgets.get_widget('refresh') # Tree view self.browser = InterfaceBrowser(policy, widgets) prefs = widgets.get_widget('preferences') self.window.action_area.set_child_secondary(prefs, True) # Glade won't let me add this to the template! if select_only: run_button = dialog.MixedButton(_("_Select"), gtk.STOCK_EXECUTE, button=gtk.ToggleButton()) elif download_only: run_button = dialog.MixedButton(_("_Download"), gtk.STOCK_EXECUTE, button=gtk.ToggleButton()) else: run_button = dialog.MixedButton(_("_Run"), gtk.STOCK_EXECUTE, button=gtk.ToggleButton()) self.window.add_action_widget(run_button, gtk.RESPONSE_OK) run_button.show_all() run_button.set_flags(gtk.CAN_DEFAULT) self.run_button = run_button run_button.grab_focus() def response(dialog, resp): if resp in (gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT): self.window.destroy() sys.exit(1) elif resp == gtk.RESPONSE_OK: if self.cancel_download_and_run: self.cancel_download_and_run.trigger() if run_button.get_active(): self.cancel_download_and_run = tasks.Blocker( "cancel downloads") self.download_and_run(run_button, self.cancel_download_and_run) elif resp == gtk.RESPONSE_HELP: gui_help.display() elif resp == SHOW_PREFERENCES: import preferences preferences.show_preferences( policy.config, notify_cb=lambda: policy.solve_with_downloads()) self.window.connect('response', response) self.window.realize() # Make busy pointer work, even with --systray def destroy(self): self.window.destroy() def show(self): self.window.show() def set_response_sensitive(self, response, sensitive): self.window.set_response_sensitive(response, sensitive) @tasks. async def download_and_run(self, run_button, cancelled): try: if not self.select_only: downloaded = self.policy.download_uncached_implementations() if downloaded: # We need to wait until everything is downloaded... blockers = [downloaded, cancelled] yield blockers tasks.check(blockers) if cancelled.happened: return uncached = self.policy.get_uncached_implementations() else: uncached = None # (we don't care) if uncached: missing = '\n- '.join([ _('%(iface_name)s %(impl_version)s') % { 'iface_name': iface.get_name(), 'impl_version': impl.get_version() } for iface, impl in uncached ]) dialog.alert( self.window, _('Not all downloads succeeded; cannot run program.\n\nFailed to get:' ) + '\n- ' + missing) else: sels = self.policy.solver.selections doc = sels.toDOM() reply = doc.toxml('utf-8') sys.stdout.write(('Length:%8x\n' % len(reply)) + reply) self.window.destroy() sys.exit(0) # Success except SystemExit: raise except download.DownloadAborted as ex: run_button.set_active(False) # Don't bother reporting this to the user except Exception as ex: run_button.set_active(False) self.report_exception(ex) def update_download_status(self, only_update_visible=False): """Called at regular intervals while there are downloads in progress, and once at the end. Update the display.""" monitored_downloads = self.policy.handler.monitored_downloads self.browser.update_download_status(only_update_visible) if not monitored_downloads: self.progress_area.hide() self.window.window.set_cursor(None) return if not self.progress_area.get_property('visible'): self.progress_area.show() self.window.window.set_cursor(gtkutils.get_busy_pointer()) any_known = False done = total = self.policy.handler.total_bytes_downloaded # Completed downloads n_downloads = self.policy.handler.n_completed_downloads # Now add downloads in progress... for x in monitored_downloads: if x.status != download.download_fetching: continue n_downloads += 1 if x.expected_size: any_known = True so_far = x.get_bytes_downloaded_so_far() total += x.expected_size or max( 4096, so_far) # Guess about 4K for feeds/icons done += so_far progress_text = '%s / %s' % (pretty_size(done), pretty_size(total)) self.progress.set_text( ngettext('Downloading one file (%(progress)s)', 'Downloading %(number)d files (%(progress)s)', n_downloads) % { 'progress': progress_text, 'number': n_downloads }) if total == 0 or (n_downloads < 2 and not any_known): self.progress.pulse() else: self.progress.set_fraction(float(done) / total) def set_message(self, message): import pango self.comment.set_text(message) attrs = pango.AttrList() attrs.insert( pango.AttrWeight(pango.WEIGHT_BOLD, end_index=len(message))) self.comment.set_attributes(attrs) self.comment.show() def use_systray_icon(self): try: self.systray_icon = gtk.status_icon_new_from_icon_name( "zeroinstall") except Exception as ex: info(_("No system tray support: %s"), ex) else: root_iface = iface_cache.iface_cache.get_interface( self.policy.root) self.systray_icon.set_tooltip( _('Checking for updates for %s') % root_iface.get_name()) self.systray_icon.connect('activate', self.remove_systray_icon) self.systray_icon_blocker = tasks.Blocker('Tray icon clicked') def remove_systray_icon(self, i=None): assert self.systray_icon, i self.show() self.systray_icon.set_visible(False) self.systray_icon = None self.systray_icon_blocker.trigger() self.systray_icon_blocker = None def report_exception(self, ex, tb=None): if not isinstance(ex, SafeException): import traceback traceback.print_exception(ex, None, tb) if self.systray_icon: self.systray_icon.set_blinking(True) self.systray_icon.set_tooltip( str(ex) + '\n' + _('(click for details)')) else: dialog.alert(self.window, str(ex) or repr(ex))
class MainWindow(Dialog): progress = None browser = None def __init__(self, prog_args): Dialog.__init__(self) self.set_title('Dependency Injector') self.set_default_size(400, 300) tips = gtk.Tooltips() # Network use hbox = gtk.HBox(False, 2) self.vbox.pack_start(hbox, False, True, 0) hbox.set_border_width(4) network = gtk.combo_box_new_text() for level in network_levels: network.append_text(level.capitalize()) network.set_active(list(network_levels).index(policy.network_use)) hbox.pack_start(gtk.Label('Network use:'), False, True, 0) hbox.pack_start(network, True, True, 2) def set_network_use(combo): policy.network_use = network_levels[network.get_active()] policy.save_config() policy.recalculate() network.connect('changed', set_network_use) hbox.show_all() # Freshness hbox = gtk.HBox(False, 2) self.vbox.pack_start(hbox, False, True, 0) hbox.set_border_width(4) times = [x.time for x in freshness_levels] if policy.freshness not in times: freshness_levels.append( Freshness(policy.freshness, '%d seconds' % policy.freshness)) times.append(policy.freshness) freshness = gtk.combo_box_new_text() for level in freshness_levels: freshness.append_text(str(level)) freshness.set_active(times.index(policy.freshness)) hbox.pack_start(gtk.Label('Freshness:'), False, True, 0) hbox.pack_start(freshness, True, True, 2) def set_freshness(combo): policy.freshness = freshness_levels[freshness.get_active()].time policy.save_config() policy.recalculate() freshness.connect('changed', set_freshness) button = gtk.Button('Refresh all now') def refresh_all(b): for x in policy.walk_interfaces(): policy.begin_iface_download(x, True) button.connect('clicked', refresh_all) hbox.pack_start(button, False, True, 2) hbox.show_all() # Tree view self.browser = InterfaceBrowser() self.vbox.pack_start(self.browser, True, True, 0) self.browser.show() # Select versions hbox = gtk.HBox(False, 2) self.vbox.pack_start(hbox, False, True, 0) hbox.set_border_width(4) button = gtk.Button() self.browser.edit_properties.connect_proxy(button) hbox.pack_start(button, False, True, 0) stable_toggle = gtk.CheckButton('Help test new versions') hbox.pack_start(stable_toggle, False, True, 0) tips.set_tip( stable_toggle, "Try out new versions as soon as they are available, instead of " "waiting for them to be marked as 'stable'. " "This sets the default policy. Click on 'Interface Properties...' " "to set the policy for an individual interface.") stable_toggle.set_active(policy.help_with_testing) def toggle_stability(toggle): policy.help_with_testing = toggle.get_active() policy.save_config() policy.recalculate() stable_toggle.connect('toggled', toggle_stability) hbox.show_all() # Progress bar self.progress = gtk.ProgressBar() self.vbox.pack_start(self.progress, False, True, 0) # Responses self.add_button(gtk.STOCK_HELP, gtk.RESPONSE_HELP) self.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) self.add_button(gtk.STOCK_EXECUTE, gtk.RESPONSE_OK) self.set_default_response(gtk.RESPONSE_OK) def response(dialog, resp): if resp == gtk.RESPONSE_CANCEL: self.destroy() elif resp == gtk.RESPONSE_OK: import download_box download_box.download_and_run(self, prog_args) elif resp == gtk.RESPONSE_HELP: gui_help.display() self.connect('response', response)
class MainWindow: progress = None progress_area = None browser = None window = None cancel_download_and_run = None policy = None comment = None systray_icon = None systray_icon_blocker = None def __init__(self, policy, widgets, download_only, select_only = False): self.policy = policy self.select_only = select_only def update_ok_state(): self.window.set_response_sensitive(gtk.RESPONSE_OK, policy.solver.ready) if policy.solver.ready and self.window.get_focus() is None: run_button.grab_focus() policy.watchers.append(update_ok_state) self.window = widgets.get_widget('main') self.window.set_default_size(gtk.gdk.screen_width() * 2 / 5, 300) self.progress = widgets.get_widget('progress') self.progress_area = widgets.get_widget('progress_area') self.comment = widgets.get_widget('comment') widgets.get_widget('stop').connect('clicked', lambda b: policy.handler.abort_all_downloads()) self.refresh_button = widgets.get_widget('refresh') # Tree view self.browser = InterfaceBrowser(policy, widgets) prefs = widgets.get_widget('preferences') self.window.action_area.set_child_secondary(prefs, True) # Glade won't let me add this to the template! if select_only: run_button = dialog.MixedButton(_("_Select"), gtk.STOCK_EXECUTE, button = gtk.ToggleButton()) elif download_only: run_button = dialog.MixedButton(_("_Download"), gtk.STOCK_EXECUTE, button = gtk.ToggleButton()) else: run_button = dialog.MixedButton(_("_Run"), gtk.STOCK_EXECUTE, button = gtk.ToggleButton()) self.window.add_action_widget(run_button, gtk.RESPONSE_OK) run_button.show_all() run_button.set_flags(gtk.CAN_DEFAULT) self.run_button = run_button run_button.grab_focus() def response(dialog, resp): if resp in (gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT): self.window.destroy() sys.exit(1) elif resp == gtk.RESPONSE_OK: if self.cancel_download_and_run: self.cancel_download_and_run.trigger() if run_button.get_active(): self.cancel_download_and_run = tasks.Blocker("cancel downloads") self.download_and_run(run_button, self.cancel_download_and_run) elif resp == gtk.RESPONSE_HELP: gui_help.display() elif resp == SHOW_PREFERENCES: import preferences preferences.show_preferences(policy.config, notify_cb = lambda: policy.solve_with_downloads()) self.window.connect('response', response) self.window.realize() # Make busy pointer work, even with --systray def destroy(self): self.window.destroy() def show(self): self.window.show() def set_response_sensitive(self, response, sensitive): self.window.set_response_sensitive(response, sensitive) @tasks.async def download_and_run(self, run_button, cancelled): try: if not self.select_only: downloaded = self.policy.download_uncached_implementations() if downloaded: # We need to wait until everything is downloaded... blockers = [downloaded, cancelled] yield blockers tasks.check(blockers) if cancelled.happened: return uncached = self.policy.get_uncached_implementations() else: uncached = None # (we don't care) if uncached: missing = '\n- '.join([_('%(iface_name)s %(impl_version)s') % {'iface_name': iface.get_name(), 'impl_version': impl.get_version()} for iface, impl in uncached]) dialog.alert(self.window, _('Not all downloads succeeded; cannot run program.\n\nFailed to get:') + '\n- ' + missing) else: from zeroinstall.injector import selections sels = selections.Selections(self.policy) doc = sels.toDOM() reply = doc.toxml('utf-8') sys.stdout.write(('Length:%8x\n' % len(reply)) + reply) self.window.destroy() sys.exit(0) # Success except SystemExit: raise except download.DownloadAborted as ex: run_button.set_active(False) # Don't bother reporting this to the user except Exception as ex: run_button.set_active(False) self.report_exception(ex) def update_download_status(self): """Called at regular intervals while there are downloads in progress, and once at the end. Update the display.""" monitored_downloads = self.policy.handler.monitored_downloads self.browser.update_download_status() if not monitored_downloads: self.progress_area.hide() self.window.window.set_cursor(None) return if not self.progress_area.get_property('visible'): self.progress_area.show() self.window.window.set_cursor(gtkutils.get_busy_pointer()) any_known = False done = total = self.policy.handler.total_bytes_downloaded # Completed downloads n_downloads = self.policy.handler.n_completed_downloads # Now add downloads in progress... for x in monitored_downloads.values(): if x.status != download.download_fetching: continue n_downloads += 1 if x.expected_size: any_known = True so_far = x.get_bytes_downloaded_so_far() total += x.expected_size or max(4096, so_far) # Guess about 4K for feeds/icons done += so_far progress_text = '%s / %s' % (pretty_size(done), pretty_size(total)) self.progress.set_text( ngettext('Downloading one file (%(progress)s)', 'Downloading %(number)d files (%(progress)s)', n_downloads) % {'progress': progress_text, 'number': n_downloads}) if total == 0 or (n_downloads < 2 and not any_known): self.progress.pulse() else: self.progress.set_fraction(float(done) / total) def set_message(self, message): import pango self.comment.set_text(message) attrs = pango.AttrList() attrs.insert(pango.AttrWeight(pango.WEIGHT_BOLD, end_index = len(message))) self.comment.set_attributes(attrs) self.comment.show() def use_systray_icon(self): try: self.systray_icon = gtk.status_icon_new_from_icon_name("zeroinstall") except Exception as ex: info(_("No system tray support: %s"), ex) else: root_iface = iface_cache.iface_cache.get_interface(self.policy.root) self.systray_icon.set_tooltip(_('Checking for updates for %s') % root_iface.get_name()) self.systray_icon.connect('activate', self.remove_systray_icon) self.systray_icon_blocker = tasks.Blocker('Tray icon clicked') def remove_systray_icon(self, i = None): assert self.systray_icon, i self.show() self.systray_icon.set_visible(False) self.systray_icon = None self.systray_icon_blocker.trigger() self.systray_icon_blocker = None def report_exception(self, ex, tb = None): if not isinstance(ex, SafeException): import traceback traceback.print_exception(ex, None, tb) if self.systray_icon: self.systray_icon.set_blinking(True) self.systray_icon.set_tooltip(str(ex) + '\n' + _('(click for details)')) else: dialog.alert(self.window, str(ex))
class MainWindow: progress = None progress_area = None browser = None window = None cancel_download_and_run = None driver = None comment = None systray_icon = None systray_icon_blocker = None def __init__(self, driver, widgets, download_only, select_only=False): self.driver = driver self.select_only = select_only def update_ok_state(): self.window.set_response_sensitive(gtk.RESPONSE_OK, driver.solver.ready) if driver.solver.ready and self.window.get_focus() is None: run_button.grab_focus() driver.watchers.append(update_ok_state) self.window = widgets.get_widget("main") self.window.set_default_size(gtk.gdk.screen_width() * 2 / 5, 300) self.progress = widgets.get_widget("progress") self.progress_area = widgets.get_widget("progress_area") self.comment = widgets.get_widget("comment") widgets.get_widget("stop").connect("clicked", lambda b: driver.config.handler.abort_all_downloads()) self.refresh_button = widgets.get_widget("refresh") # Tree view self.browser = InterfaceBrowser(driver, widgets) prefs = widgets.get_widget("preferences") self.window.get_action_area().set_child_secondary(prefs, True) # Glade won't let me add this to the template! if select_only: run_button = dialog.MixedButton(_("_Select"), gtk.STOCK_EXECUTE, button=gtk.ToggleButton()) elif download_only: run_button = dialog.MixedButton(_("_Download"), gtk.STOCK_EXECUTE, button=gtk.ToggleButton()) else: run_button = dialog.MixedButton(_("_Run"), gtk.STOCK_EXECUTE, button=gtk.ToggleButton()) self.window.add_action_widget(run_button, gtk.RESPONSE_OK) run_button.show_all() run_button.set_can_default(True) self.run_button = run_button run_button.grab_focus() def response(dialog, resp): if resp in (gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT): self.window.destroy() sys.exit(1) elif resp == gtk.RESPONSE_OK: if self.cancel_download_and_run: self.cancel_download_and_run.trigger() if run_button.get_active(): self.cancel_download_and_run = tasks.Blocker("cancel downloads") self.download_and_run(run_button, self.cancel_download_and_run) elif resp == gtk.RESPONSE_HELP: gui_help.display() elif resp == SHOW_PREFERENCES: import preferences preferences.show_preferences(driver.config, notify_cb=lambda: driver.solve_with_downloads()) self.window.connect("response", response) self.window.realize() # Make busy pointer work, even with --systray def destroy(self): self.window.destroy() def show(self): self.window.show() def set_response_sensitive(self, response, sensitive): self.window.set_response_sensitive(response, sensitive) @tasks.async def download_and_run(self, run_button, cancelled): try: if not self.select_only: downloaded = self.driver.download_uncached_implementations() if downloaded: # We need to wait until everything is downloaded... blockers = [downloaded, cancelled] yield blockers tasks.check(blockers) if cancelled.happened: return uncached = self.driver.get_uncached_implementations() else: uncached = None # (we don't care) if uncached: missing = "\n- ".join( [ _("%(iface_name)s %(impl_version)s") % {"iface_name": iface.get_name(), "impl_version": impl.get_version()} for iface, impl in uncached ] ) dialog.alert( self.window, _("Not all downloads succeeded; cannot run program.\n\nFailed to get:") + "\n- " + missing, ) else: sels = self.driver.solver.selections doc = sels.toDOM() reply = doc.toxml("utf-8") if sys.version_info[0] > 2: stdout = sys.stdout.buffer else: stdout = sys.stdout stdout.write(("Length:%8x\n" % len(reply)).encode("utf-8") + reply) self.window.destroy() sys.exit(0) # Success except SystemExit: raise except download.DownloadAborted as ex: run_button.set_active(False) # Don't bother reporting this to the user except Exception as ex: run_button.set_active(False) self.report_exception(ex) def update_download_status(self, only_update_visible=False): """Called at regular intervals while there are downloads in progress, and once at the end. Update the display.""" monitored_downloads = self.driver.config.handler.monitored_downloads self.browser.update_download_status(only_update_visible) if not monitored_downloads: self.progress_area.hide() self.window.get_window().set_cursor(None) return if not self.progress_area.get_property("visible"): self.progress_area.show() self.window.get_window().set_cursor(gtkutils.get_busy_pointer()) any_known = False done = total = self.driver.config.handler.total_bytes_downloaded # Completed downloads n_downloads = self.driver.config.handler.n_completed_downloads # Now add downloads in progress... for x in monitored_downloads: if x.status != download.download_fetching: continue n_downloads += 1 if x.expected_size: any_known = True so_far = x.get_bytes_downloaded_so_far() total += x.expected_size or max(4096, so_far) # Guess about 4K for feeds/icons done += so_far progress_text = "%s / %s" % (pretty_size(done), pretty_size(total)) self.progress.set_text( ngettext("Downloading one file (%(progress)s)", "Downloading %(number)d files (%(progress)s)", n_downloads) % {"progress": progress_text, "number": n_downloads} ) if total == 0 or (n_downloads < 2 and not any_known): self.progress.pulse() else: self.progress.set_fraction(float(done) / total) def set_message(self, message): import pango self.comment.set_text(message) attrs = pango.AttrList() attrs.insert(pango.AttrWeight(pango.WEIGHT_BOLD, end_index=len(message))) self.comment.set_attributes(attrs) self.comment.show() def use_systray_icon(self): try: if sys.version_info[0] > 2: self.systray_icon = gtk.StatusIcon.new_from_icon_name("zeroinstall") else: self.systray_icon = gtk.status_icon_new_from_icon_name("zeroinstall") except Exception as ex: info(_("No system tray support: %s"), ex) else: root_iface = iface_cache.iface_cache.get_interface(self.driver.requirements.interface_uri) self.systray_icon.set_tooltip(_("Checking for updates for %s") % root_iface.get_name()) self.systray_icon.connect("activate", self.remove_systray_icon) self.systray_icon_blocker = tasks.Blocker("Tray icon clicked") def remove_systray_icon(self, i=None): assert self.systray_icon, i self.show() self.systray_icon.set_visible(False) self.systray_icon = None self.systray_icon_blocker.trigger() self.systray_icon_blocker = None def report_exception(self, ex, tb=None): if not isinstance(ex, SafeException): if isinstance(ex, AssertionError): # Assertions often don't say that they're errors (and are frequently # blank). ex = repr(ex) if tb is None: warn(ex, exc_info=True) else: warn(ex, exc_info=(type(ex), ex, tb)) if self.systray_icon: self.systray_icon.set_blinking(True) self.systray_icon.set_tooltip(str(ex) + "\n" + _("(click for details)")) else: dialog.alert(self.window, str(ex) or repr(ex))