Пример #1
0
    def __init__(self, driver, widgets, download_only, resolve, select_only=False):
        self.driver = driver
        self.select_only = select_only
        self.resolve = resolve

        def update_ok_state():
            self.window.set_response_sensitive(gtk.RESPONSE_OK, driver.ready)
            if driver.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()
        if gtk.pygtk_version >= (2, 22, 0):
            run_button.set_can_default(True)
        else:
            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.driver.config.handler.abort_all_downloads()
                resolve("cancel")
            elif resp == gtk.RESPONSE_OK:
                self.driver.config.handler.abort_all_downloads()
                if run_button.get_active():
                    self.download_and_run(run_button)
            elif resp == gtk.RESPONSE_HELP:
                gui_help.display()
            elif resp == SHOW_PREFERENCES:
                from zeroinstall.gui import preferences, main

                preferences.show_preferences(driver.config, notify_cb=main.recalculate)

        self.window.connect("response", response)
        self.window.realize()  # Make busy pointer work, even with --systray
Пример #2
0
class MainWindow(object):
    progress = None
    progress_area = None
    browser = None
    window = None
    driver = None
    comment = None
    systray_icon = None
    systray_icon_blocker = None

    def __init__(self, driver, widgets, download_only, resolve, select_only=False):
        self.driver = driver
        self.select_only = select_only
        self.resolve = resolve

        def update_ok_state():
            self.window.set_response_sensitive(gtk.RESPONSE_OK, driver.ready)
            if driver.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()
        if gtk.pygtk_version >= (2, 22, 0):
            run_button.set_can_default(True)
        else:
            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.driver.config.handler.abort_all_downloads()
                resolve("cancel")
            elif resp == gtk.RESPONSE_OK:
                self.driver.config.handler.abort_all_downloads()
                if run_button.get_active():
                    self.download_and_run(run_button)
            elif resp == gtk.RESPONSE_HELP:
                gui_help.display()
            elif resp == SHOW_PREFERENCES:
                from zeroinstall.gui import preferences, main

                preferences.show_preferences(driver.config, notify_cb=main.recalculate)

        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):
        try:
            blocker = slave.download_archives()
            yield blocker
            tasks.check(blocker)

            if blocker.result == "aborted-by-user":
                run_button.set_active(False)
                # Don't bother reporting this to the user
            elif blocker.result == "ok":
                if not run_button.get_active():
                    return
                self.driver.config.handler.abort_all_downloads()
                self.resolve("ok")
            else:
                assert 0, blocker.result
        except SystemExit:
            raise
        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."""
        if not self.window:
            return  # (being destroyed)
        if not self.window.get_window():
            return  # (being destroyed)
        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()
        try:
            attrs.insert(pango.AttrWeight(pango.WEIGHT_BOLD, end_index=len(message)))
        except AttributeError:
            pass  # PyGtk 3
        self.comment.set_attributes(attrs)
        self.comment.show()

    def use_systray_icon(self, root_iface):
        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:
            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 tb is None:
                warning(ex, exc_info=True)
            else:
                warning(ex, exc_info=(type(ex), ex, tb))
            if isinstance(ex, AssertionError):
                # Assertions often don't say that they're errors (and are frequently
                # blank).
                ex = repr(ex)
        if self.systray_icon:
            if hasattr(self.systray_icon, "set_blinking"):
                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))