示例#1
0
class Network(SectionView):
    def __init__(self, model, alerts):
        SectionView.__init__(self)

        self._model = model
        self.restart_alerts = alerts
        self._jabber_sid = 0
        self._radio_valid = True
        self._jabber_change_handler = None
        self._radio_change_handler = None
        self._wireless_configuration_reset_handler = None
        self._start_jabber = self._model.get_jabber()
        self._proxy_settings = {}
        self._proxy_inline_alerts = {}

        self.set_border_width(style.DEFAULT_SPACING * 2)
        self.set_spacing(style.DEFAULT_SPACING)
        group = Gtk.SizeGroup(Gtk.SizeGroupMode.HORIZONTAL)

        self._radio_alert_box = Gtk.HBox(spacing=style.DEFAULT_SPACING)

        scrolled = Gtk.ScrolledWindow()
        scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
        self.add(scrolled)
        scrolled.show()

        workspace = Gtk.VBox()
        scrolled.add_with_viewport(workspace)
        workspace.show()

        separator_wireless = Gtk.HSeparator()
        workspace.pack_start(separator_wireless, False, True, 0)
        separator_wireless.show()

        label_wireless = Gtk.Label(label=_('Wireless'))
        label_wireless.set_alignment(0, 0)
        workspace.pack_start(label_wireless, False, True, 0)
        label_wireless.show()
        box_wireless = Gtk.VBox()
        box_wireless.set_border_width(style.DEFAULT_SPACING * 2)
        box_wireless.set_spacing(style.DEFAULT_SPACING)

        radio_info = Gtk.Label(label=_('The wireless radio may be turned'
                                       ' off to save battery life.'))
        radio_info.set_alignment(0, 0)
        radio_info.set_line_wrap(True)
        radio_info.show()
        box_wireless.pack_start(radio_info, False, True, 0)

        box_radio = Gtk.HBox(spacing=style.DEFAULT_SPACING)
        self._button = Gtk.CheckButton()
        self._button.set_alignment(0, 0)
        box_radio.pack_start(self._button, False, True, 0)
        self._button.show()

        label_radio = Gtk.Label(label=_('Radio'))
        label_radio.set_alignment(0, 0.5)
        box_radio.pack_start(label_radio, False, True, 0)
        label_radio.show()

        box_wireless.pack_start(box_radio, False, True, 0)
        box_radio.show()

        self._radio_alert = InlineAlert()
        self._radio_alert_box.pack_start(self._radio_alert, False, True, 0)
        box_radio.pack_end(self._radio_alert_box, False, True, 0)
        self._radio_alert_box.show()
        if 'radio' in self.restart_alerts:
            self._radio_alert.props.msg = self.restart_msg
            self._radio_alert.show()

        wireless_info = Gtk.Label(
            label=_('Discard wireless connections if'
                    ' you have trouble connecting to the network'))
        wireless_info.set_alignment(0, 0)
        wireless_info.set_line_wrap(True)
        wireless_info.show()
        box_wireless.pack_start(wireless_info, False, True, 0)

        box_clear_wireless = Gtk.HBox(spacing=style.DEFAULT_SPACING)
        self._clear_wireless_button = Gtk.Button()
        self._clear_wireless_button.set_label(
            _('Discard wireless connections'))
        box_clear_wireless.pack_start(self._clear_wireless_button, False, True,
                                      0)
        if not self._model.have_wireless_networks():
            self._clear_wireless_button.set_sensitive(False)
        self._clear_wireless_button.show()
        box_wireless.pack_start(box_clear_wireless, False, True, 0)
        box_clear_wireless.show()

        workspace.pack_start(box_wireless, False, True, 0)
        box_wireless.show()

        separator_mesh = Gtk.HSeparator()
        workspace.pack_start(separator_mesh, False, False, 0)
        separator_mesh.show()

        label_mesh = Gtk.Label(label=_('Collaboration'))
        label_mesh.set_alignment(0, 0)
        workspace.pack_start(label_mesh, False, True, 0)
        label_mesh.show()
        box_mesh = Gtk.VBox()
        box_mesh.set_border_width(style.DEFAULT_SPACING * 2)
        box_mesh.set_spacing(style.DEFAULT_SPACING)

        server_info = Gtk.Label(
            _("The server is the equivalent of what"
              " room you are in; people on the same server"
              " will be able to see each other, even when"
              " they aren't on the same network."))
        server_info.set_alignment(0, 0)
        server_info.set_line_wrap(True)
        box_mesh.pack_start(server_info, False, True, 0)
        server_info.show()

        box_server = Gtk.HBox(spacing=style.DEFAULT_SPACING)
        label_server = Gtk.Label(label=_('Server:'))
        label_server.set_alignment(1, 0.5)
        label_server.modify_fg(Gtk.StateType.NORMAL,
                               style.COLOR_SELECTION_GREY.get_gdk_color())
        box_server.pack_start(label_server, False, True, 0)
        group.add_widget(label_server)
        label_server.show()
        self._entry = Gtk.Entry()
        self._entry.set_alignment(0)
        self._entry.set_size_request(int(Gdk.Screen.width() / 3), -1)
        box_server.pack_start(self._entry, False, True, 0)
        self._entry.show()
        box_mesh.pack_start(box_server, False, True, 0)
        box_server.show()

        social_help_info = Gtk.Label(
            _('Social Help is a forum that lets you connect with developers'
              ' and discuss Sugar Activities.  Changing servers means'
              ' discussions will happen in a different place with'
              ' different people.'))
        social_help_info.set_alignment(0, 0)
        social_help_info.set_line_wrap(True)
        box_mesh.pack_start(social_help_info, False, True, 0)
        social_help_info.show()

        social_help_box = Gtk.HBox(spacing=style.DEFAULT_SPACING)
        social_help_label = Gtk.Label(label=_('Social Help Server:'))
        social_help_label.set_alignment(1, 0.5)
        social_help_label.modify_fg(Gtk.StateType.NORMAL,
                                    style.COLOR_SELECTION_GREY.get_gdk_color())
        social_help_box.pack_start(social_help_label, False, True, 0)
        group.add_widget(social_help_label)
        social_help_label.show()

        self._social_help_entry = Gtk.Entry()
        self._social_help_entry.set_alignment(0)
        self._social_help_entry.set_size_request(int(Gdk.Screen.width() / 3),
                                                 -1)
        social_help_box.pack_start(self._social_help_entry, False, True, 0)
        self._social_help_entry.show()
        box_mesh.pack_start(social_help_box, False, True, 0)
        social_help_box.show()

        workspace.pack_start(box_mesh, False, True, 0)
        box_mesh.show()

        separator_proxy = Gtk.HSeparator()
        workspace.pack_start(separator_proxy, False, False, 0)
        separator_proxy.show()

        self._add_proxy_section(workspace)

        self.setup()

    def _add_proxy_section(self, workspace):
        label_proxy = Gtk.Label(_('Proxy'))
        label_proxy.set_alignment(0, 0)
        workspace.pack_start(label_proxy, False, True, 0)
        label_proxy.show()

        box_proxy = Gtk.VBox()
        box_proxy.set_border_width(style.DEFAULT_SPACING * 2)
        box_proxy.set_spacing(style.DEFAULT_SPACING)
        workspace.pack_start(box_proxy, False, True, 0)
        box_proxy.show()

        self._proxy_alert = Alert()
        self._proxy_alert.props.title = _('Error')
        self._proxy_alert.props.msg = _('Proxy settings cannot be verified')
        box_proxy.pack_start(self._proxy_alert, False, False, 0)
        self._proxy_alert.connect('response', self._response_cb)
        self._proxy_alert.hide()

        # GSettings schemas for proxy:
        schemas = [
            'org.sugarlabs.system.proxy', 'org.sugarlabs.system.proxy.http',
            'org.sugarlabs.system.proxy.https',
            'org.sugarlabs.system.proxy.ftp',
            'org.sugarlabs.system.proxy.socks'
        ]

        for schema in schemas:
            proxy_setting = Gio.Settings.new(schema)

            # We are not going to apply the settings immediatly.
            # We'll apply them if the user presses the "accept"
            # button, or we'll revert them if the user presses the
            # "cancel" button.
            proxy_setting.delay()
            alert = InlineAlert()

            self._proxy_settings[schema] = proxy_setting
            self._proxy_inline_alerts[schema] = alert

        size_group = Gtk.SizeGroup(Gtk.SizeGroupMode.HORIZONTAL)

        automatic_proxy_box = Gtk.VBox(spacing=style.DEFAULT_SPACING)
        manual_proxy_box = Gtk.VBox(spacing=style.DEFAULT_SPACING)

        option_sets = [('None', 'none', Gtk.VBox()),
                       ('Use system proxy', 'system', Gtk.VBox()),
                       ('Manual', 'manual', manual_proxy_box),
                       ('Automatic', 'auto', automatic_proxy_box)]

        box_mode = ComboSettingBox(
            _('Method:'), self._proxy_settings['org.sugarlabs.system.proxy'],
            'mode', option_sets, size_group)

        box_proxy.pack_start(box_mode, False, False, 0)
        box_mode.show()

        url_box = StringSettingBox(
            _('Configuration URL:'),
            self._proxy_settings['org.sugarlabs.system.proxy'],
            'autoconfig-url', size_group)

        automatic_proxy_box.pack_start(url_box, True, True, 0)
        url_box.show()

        wpad_help_text = _('Web Proxy Autodiscovery is used when a'
                           ' Configuration URL is not provided. This is not'
                           ' recommended for untrusted public networks.')
        automatic_proxy_help = Gtk.Label(wpad_help_text)
        automatic_proxy_help.set_alignment(0, 0)
        automatic_proxy_help.set_line_wrap(True)
        automatic_proxy_help.show()
        automatic_proxy_box.pack_start(automatic_proxy_help, True, True, 0)

        # HTTP Section
        schema = 'org.sugarlabs.system.proxy.http'
        box_http = HostPortSettingBox(_('HTTP Proxy:'),
                                      self._proxy_inline_alerts[schema],
                                      self._proxy_settings[schema], size_group)
        manual_proxy_box.pack_start(box_http, False, False, 0)
        box_http.show()
        auth_contents_box = Gtk.VBox(spacing=style.DEFAULT_SPACING)
        auth_box = OptionalSettingsBox(_('Use authentication'),
                                       self._proxy_settings[schema],
                                       'use-authentication', auth_contents_box)
        manual_proxy_box.pack_start(auth_box, False, False, 0)
        auth_box.show()
        proxy_http_setting = Gio.Settings.new(schema)
        proxy_http_setting.delay()
        box_username = StringSettingBox(_('Username:'******'authentication-user', size_group)
        auth_contents_box.pack_start(box_username, False, False, 0)
        box_username.show()
        box_password = StringSettingBox(_('Password:'******'authentication-password',
                                        size_group,
                                        password_field=True)
        auth_contents_box.pack_start(box_password, False, False, 0)
        box_password.show()

        # HTTPS Section
        schema = 'org.sugarlabs.system.proxy.https'
        box_https = HostPortSettingBox(_('HTTPS Proxy:'),
                                       self._proxy_inline_alerts[schema],
                                       self._proxy_settings[schema],
                                       size_group)
        manual_proxy_box.pack_start(box_https, False, False, 0)
        box_https.show()

        # FTP Section
        schema = 'org.sugarlabs.system.proxy.ftp'
        box_ftp = HostPortSettingBox(_('FTP Proxy:'),
                                     self._proxy_inline_alerts[schema],
                                     self._proxy_settings[schema], size_group)
        manual_proxy_box.pack_start(box_ftp, False, False, 0)
        box_ftp.show()

        # SOCKS Section
        schema = 'org.sugarlabs.system.proxy.socks'
        box_socks = HostPortSettingBox(_('SOCKS Proxy:'),
                                       self._proxy_inline_alerts[schema],
                                       self._proxy_settings[schema],
                                       size_group)
        manual_proxy_box.pack_start(box_socks, False, False, 0)
        box_socks.show()

        box_ignore = StringSettingBox_with_convert(
            _('Ignore Hosts:'),
            self._proxy_settings['org.sugarlabs.system.proxy'], 'ignore-hosts',
            type_as_to_string, string_to_type_as, size_group)
        manual_proxy_box.pack_start(box_ignore, False, False, 0)
        box_ignore.show()

    def setup(self):
        self._entry.set_text(self._start_jabber)
        self._social_help_entry.set_text(self._model.get_social_help())

        try:
            radio_state = self._model.get_radio()
        except self._model.ReadError as detail:
            self._radio_alert.props.msg = detail
            self._radio_alert.show()
        else:
            self._button.set_active(radio_state)

        self._radio_valid = True
        self.needs_restart = False
        self._radio_change_handler = self._button.connect(
            'toggled', self.__radio_toggled_cb)
        self._wireless_configuration_reset_handler =  \
            self._clear_wireless_button.connect(
                'clicked', self.__wireless_configuration_reset_cb)

    def _response_cb(self, alert, response_id):
        if response_id is Gtk.ResponseType.APPLY:
            self._proxy_alert.hide()
            self._apply_proxy_settings()
            self.show_restart_alert = True
            self.emit('add-alert')
        elif response_id is Gtk.ResponseType.CANCEL:
            self.undo()
            self._proxy_alert.remove_button(Gtk.ResponseType.APPLY)
            self._proxy_alert.remove_button(Gtk.ResponseType.CANCEL)
            self._proxy_alert.hide()
            self.emit('set-toolbar-sensitivity', True)

    def _ping_servers(self):
        response_to_return = True
        non_blank_host_name_counter = 0  # To check accidental blank hostnames
        for schema in list(self._proxy_settings.keys()):
            if (schema != 'org.sugarlabs.system.proxy'):
                hostname = Gio.Settings.get_string(
                    self._proxy_settings[schema], 'host')
                if hostname != '':
                    non_blank_host_name_counter += 1
                    response = os.system("ping -c 1 -W 1 " + hostname)
                    if (response):
                        self._proxy_inline_alerts[schema].show()
                        response_to_return = False
        if non_blank_host_name_counter == 0:
            response_to_return = False
        return response_to_return

    def _verify_settings(self):
        self._proxy_alert.props.title = _('Please Wait!')
        self._proxy_alert.props.msg = _('Proxy settings are being verified.')
        self._proxy_alert.show()
        flag_all_true = True
        g_proxy_schema = self._proxy_settings['org.sugarlabs.system.proxy']
        g_mode = Gio.Settings.get_string(g_proxy_schema, 'mode')
        self.show_restart_alert = False

        if g_mode == 'auto':
            flag_all_true = os.path.isfile(
                Gio.Settings.get_string(g_proxy_schema, 'autoconfig-url'))
        elif g_mode == 'manual':
            flag_all_true = self._ping_servers()
        if flag_all_true:
            self.show_restart_alert = True
            self._proxy_alert.hide()
            self._apply_proxy_settings()
        else:
            self._proxy_alert.props.title = _('Error!')
            self._proxy_alert.props.msg = _('The following setting(s) seems '
                                            'to be incorrect and may break '
                                            'your internet connection')

            icon = Icon(icon_name='dialog-cancel')
            self._proxy_alert.add_button(Gtk.ResponseType.APPLY,
                                         _('Break my internet'), icon)
            icon.show()
            icon = Icon(icon_name='dialog-ok')
            self._proxy_alert.add_button(Gtk.ResponseType.CANCEL, _('Reset'),
                                         icon)
            icon.show()

    def _apply_proxy_settings(self):
        for setting in list(self._proxy_settings.values()):
            if (Gio.Settings.get_has_unapplied(setting)):
                setting.apply()

    def apply(self):
        self._apply_jabber(self._entry.get_text())
        self._model.set_social_help(self._social_help_entry.get_text())
        settings_changed = False
        for setting in list(self._proxy_settings.values()):
            if (Gio.Settings.get_has_unapplied(setting)):
                settings_changed = True
        if settings_changed:
            self.needs_restart = True
            self._is_cancellable = False
            self.restart_msg = _('Proxy changes require restart')
            self._verify_settings()
        else:
            self.show_restart_alert = True

    def undo(self):
        self._button.disconnect(self._radio_change_handler)
        self._radio_alert.hide()
        for setting in list(self._proxy_settings.values()):
            setting.revert()
        for alert in list(self._proxy_inline_alerts.values()):
            alert.hide()

    def _validate(self):
        if self._radio_valid:
            self.props.is_valid = True
        else:
            self.props.is_valid = False

    def __radio_toggled_cb(self, widget, data=None):
        radio_state = widget.get_active()
        try:
            self._model.set_radio(radio_state)
        except self._model.ReadError as detail:
            self._radio_alert.props.msg = detail
            self._radio_valid = False
        else:
            self._radio_valid = True
            if self._model.have_wireless_networks():
                self._clear_wireless_button.set_sensitive(True)

        self._validate()
        return False

    def _apply_jabber(self, jabber):
        if jabber == self._model.get_jabber():
            return
        self._model.set_jabber(jabber)

    def __wireless_configuration_reset_cb(self, widget):
        # FIXME: takes effect immediately, not after CP is closed with
        # confirmation button
        self._model.clear_wireless_networks()
        self._clear_wireless_button.set_sensitive(False)