[Sugar-devel] [PATCH sugar, v3] Add menu to Control Panel/Network for proxy configuration

Anish Mangal anish at activitycentral.com
Fri Feb 3 07:56:00 EST 2012


From: Aleksey Lim <alsroot at activitycentral.org>

Both individual users and deployments need to be able to set a proxy for
Sugar and activities to use. While we'd like the system to work that all
out automatically (e.g. using WPAD [1]), this often isn't possible.  Common
reasons include legacy ("inherited") setups and network uplinks simply being
out of control of the user respectively deployment.

For consistency between Sugar and Gnome (and to the benefit of existing users
who currently switch to Gnome to change proxy settings), the layout of the
Gnome proxy settings dialog has been mirrored as much as possible.

This version of the patch also moves the menu from an independent CP
item to under the existing Network configuration menu [2].

[1] https://en.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol
[2] http://meeting.sugarlabs.org/sugar-meeting/meetings/2012-01-31T15:02:06

[Rebased the patch over sugar/mainline]
Signed-off-by: Anish Mangal <anish at sugarlabs.org>

[replaced description; merged fix-up patches from Aleksey; style fixes;
 added WPAD hint; fixed needs_restart defaults bug]
Signed-off-by: Sascha Silbe <silbe at activitycentral.com>

[Moved the proxy configuration menu from a new CP menu to under the
existing Network configuration CP]
Signed-off-by: Ajay Garg <ajay at activitycentral.com>

---
v1->v2: several bug and style fixes, added WPAD hint and line breaking
        for labels, replaced description. No (other) changes to the
	layout.

v2->v3: Moved from a new proxy menu in the CP to under the Network
	configuration menu
---
 extensions/cpsection/network/view.py |  391 ++++++++++++++++++++++++++++++++++
 1 files changed, 391 insertions(+), 0 deletions(-)

diff --git a/extensions/cpsection/network/view.py b/extensions/cpsection/network/view.py
index 381dcb6..22cd0a5 100644
--- a/extensions/cpsection/network/view.py
+++ b/extensions/cpsection/network/view.py
@@ -1,4 +1,5 @@
 # Copyright (C) 2008, OLPC
+# Copyright (C) 2011, Aleksey Lim
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -14,8 +15,11 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 
+import re
+
 import gtk
 import gobject
+import gconf
 from gettext import gettext as _
 
 from sugar.graphics import style
@@ -30,6 +34,8 @@ TITLE = _('Network')
 
 _APPLY_TIMEOUT = 3000
 
+_widget_sensitivies = {}
+_gconf_origin_values = {}
 
 class Network(SectionView):
     def __init__(self, model, alerts):
@@ -171,6 +177,31 @@ class Network(SectionView):
         workspace.pack_start(box_mesh, expand=False)
         box_mesh.show()
 
+        separator_proxy = gtk.HSeparator()
+        workspace.pack_start(separator_proxy, False)
+        separator_proxy.show()
+
+        label_proxy = gtk.Label(_('Proxy'))
+        label_proxy.set_alignment(0, 0)
+        workspace.pack_start(label_proxy, expand=False)
+        label_proxy.show()
+
+        box_proxy = gtk.VBox()
+        box_proxy.set_border_width(style.DEFAULT_SPACING * 2)
+        box_proxy.set_spacing(style.DEFAULT_SPACING)
+        proxy_info = gtk.Label(_("Please enter the correct settings if
+            your network connects through a proxy."))
+        proxy_info.set_alignment(0, 0)
+        proxy_info.set_line_wrap(True)
+        box_proxy.pack_start(proxy_info, expand=False)
+        proxy_info.show()
+        workspace.pack_start(box_proxy, expand=False)
+        box_proxy.show()
+
+        proxy = Proxy()
+        workspace.pack_start(proxy, expand=False)
+        proxy.show()
+
         scrolled = gtk.ScrolledWindow()
         scrolled.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
         scrolled.add_with_viewport(workspace)
@@ -259,3 +290,363 @@ class Network(SectionView):
         self._model.clear_networks()
         if not self._model.have_networks():
             self._clear_history_button.set_sensitive(False)
+
+class Proxy(SectionView):
+
+    def __init__(self):
+        SectionView.__init__(self)
+        self.set_border_width(style.DEFAULT_SPACING * 2)
+        self.set_spacing(style.DEFAULT_SPACING)
+        self.setup()
+
+    def setup(self):
+        for i in self.get_children():
+            self.remove(i)
+            # Destroy all widgets and connection to avoid any interfering
+            i.destroy()
+
+        _widget_sensitivies.clear()
+
+        workspace = gtk.VBox()
+        workspace.show()
+        self.add(workspace)
+
+        def add_section(section, label_text):
+            separator = gtk.HSeparator()
+            separator.show()
+            workspace.pack_start(separator, expand=False)
+
+            label = gtk.Label(label_text)
+            label.set_alignment(0, 0)
+            label.show()
+            workspace.pack_start(label, expand=False)
+
+            section.set_border_width(style.DEFAULT_SPACING * 2)
+            section.show()
+            workspace.pack_start(section, expand=False)
+
+        add_section(_ProxySection(),
+                _('Configure proxies to access the internet'))
+        add_section(_IgnoreSection(), _('Ignore host list'))
+
+    def undo(self):
+        conf = gconf.client_get_default()
+        for key, value in _gconf_origin_values.items():
+            if value is None:
+                conf.unset(key)
+            else:
+                conf.set(key, value)
+
+    @property
+    def needs_restart(self):
+        conf = gconf.client_get_default()
+        for key, value in _gconf_origin_values.items():
+            if ((value is None and conf.get_without_default(key) is not None) or
+                (value is not None and value.to_string() != conf.get(key).to_string())):
+                return True
+
+        return False
+
+    @needs_restart.setter
+    def needs_restart(self, value):
+        # needs_restart is a property (i.e. gets calculated) in this Control
+        # Panel, but SectionView.__init__() wants to initialise it to False,
+        # so we need to provide a (fake) setter.
+        pass
+
+
+class _ProxySection(gtk.VBox):
+
+    def __init__(self):
+        gtk.VBox.__init__(self)
+        self._common_hosts = {}
+        self._common_ports = {}
+
+        group = gtk.RadioButton()
+        group.props.label = _('Direct internet connection')
+        group.show()
+        self.pack_start(group, expand=False)
+        _register_selector_key('/system/proxy/mode', group, 'none')
+        _register_bool_key('/system/http_proxy/use_http_proxy', group, True)
+
+        manual_proxy = gtk.RadioButton(group)
+        manual_proxy.props.label = _('Manual proxy configuration')
+        manual_proxy.show()
+        self.pack_start(manual_proxy, expand=False)
+        _register_selector_key('/system/proxy/mode', manual_proxy, 'manual')
+
+        widgets = self._add_protos()
+        manual_proxy.connect('toggled', _set_sensitive, False, widgets)
+        _set_sensitive(manual_proxy, False, widgets)
+
+        auto_proxy = gtk.RadioButton(group)
+        auto_proxy.props.label = _('Automatic proxy configuration')
+        auto_proxy.show()
+        self.pack_start(auto_proxy, expand=False)
+        _register_selector_key('/system/proxy/mode', auto_proxy, 'auto')
+
+        grid = self._sub_section_new()
+        grid.attach_label(_('Autoconfiguration URL (leave empty to use WPAD):'),
+                          0, 1, 0, 1)
+        entry = grid.attach_entry(1, 2, 0, 1)
+        _register_string_key('/system/proxy/autoconfig_url', entry)
+        auto_proxy.connect('toggled', _set_sensitive, False, [grid])
+        _set_sensitive(auto_proxy, False, [grid])
+
+        print 'aa toh raha hai'
+
+    def _add_protos(self):
+        commons = gtk.CheckButton()
+        commons.props.label = _('Use the same proxy for all protocols')
+        commons.show()
+        self.pack_start(commons)
+        _register_bool_key('/system/http_proxy/use_same_proxy', commons)
+
+        grid = self._sub_section_new()
+
+        def add_proto(row, is_common, label_text, host_key, port_key):
+            host_label = grid.attach_label(label_text, 0, 1, row, row + 1)
+            host = grid.attach_entry(1, 2, row, row + 1)
+
+            port_label = grid.attach_label(_('Port:'), 2, 3, row, row + 1)
+            port_value = gtk.Adjustment(8080, 0, 65536, 1, 10)
+            port = gtk.SpinButton()
+            port.configure(port_value, .1, 0)
+            port.show()
+            grid.attach(port, 3, 4, row, row + 1,
+                    gtk.SHRINK | gtk.FILL, gtk.SHRINK)
+
+            if is_common:
+                _widget_sensitivies.update([
+                        (host_label, None), (host, None),
+                        (port_label, None), (port, None)])
+                self._common_hosts[host] = host.props.buffer
+                self._common_ports[port] = port.props.adjustment
+
+            _register_string_key(host_key, host)
+            _register_int_key(port_key, port)
+
+            return host, port
+
+        http_host, http_port = add_proto(1, False, _('HTTP proxy:'),
+                '/system/http_proxy/host', '/system/http_proxy/port')
+
+        auth_widget = _AuthWidget()
+        auth_widget.show()
+        grid.attach(auth_widget, 1, 2, 2, 3, gtk.SHRINK | gtk.FILL, gtk.SHRINK)
+
+        add_proto(3, True, _('Secure HTTP proxy:'),
+                '/system/proxy/secure_host', '/system/proxy/secure_port')
+        add_proto(4, True, _('FTP proxy:'),
+                '/system/proxy/ftp_host', '/system/proxy/ftp_port')
+        add_proto(5, True, _('Socks proxy:'),
+                '/system/proxy/socks_host', '/system/proxy/socks_port')
+
+        def commons_toggled_cb(sender):
+            for widget in _widget_sensitivies.keys():
+                _widget_sensitivies[widget] = not sender.props.active
+            _set_sensitive(sender, True, _widget_sensitivies.keys())
+
+            for widget, orig_buffer in self._common_hosts.items():
+                widget.props.buffer = http_host.props.buffer if \
+                        sender.props.active else orig_buffer
+
+            for widget, orig_adjustment in self._common_ports.items():
+                widget.props.adjustment = http_port.props.adjustment if \
+                        sender.props.active else orig_adjustment
+                widget.props.value = widget.props.adjustment.value
+
+        commons.connect('toggled', commons_toggled_cb)
+        commons_toggled_cb(commons)
+
+        return [commons, grid]
+
+    def _sub_section_new(self):
+        grid = _Grid(1, 1, False)
+        grid.props.column_spacing = style.DEFAULT_SPACING
+        grid.props.row_spacing = style.DEFAULT_SPACING
+        grid.show()
+
+        alignment = gtk.Alignment(0, 0, 1, 1)
+        alignment.props.left_padding = style.STANDARD_ICON_SIZE
+        alignment.props.right_padding = style.GRID_CELL_SIZE
+        alignment.add(grid)
+        alignment.show()
+        self.pack_start(alignment)
+
+        return grid
+
+
+class _IgnoreSection(gtk.VBox):
+
+    def __init__(self):
+        gtk.VBox.__init__(self)
+
+        entry = gtk.Entry()
+        entry.show()
+        self.pack_start(entry, expand=False)
+        _register_list_key('/system/http_proxy/ignore_hosts', entry)
+
+
+class _AuthWidget(gtk.VBox):
+
+    def __init__(self):
+        gtk.VBox.__init__(self)
+
+        enable = gtk.CheckButton()
+        enable.props.label = _('Use authentication')
+        enable.show()
+        self.pack_start(enable, expand=False)
+        _register_bool_key('/system/http_proxy/use_authentication', enable)
+
+        grid = _Grid(2, 2, False)
+        grid.props.column_spacing = style.DEFAULT_SPACING
+        grid.props.row_spacing = style.DEFAULT_SPACING
+        self.pack_start(grid)
+
+        grid.attach_label(_('Username:'), 0, 1, 0, 1)
+        entry = grid.attach_entry(1, 2, 0, 1)
+        _register_string_key('/system/http_proxy/authentication_user', entry)
+
+        grid.attach_label(_('Password:'), 0, 1, 1, 2)
+        entry = grid.attach_entry(1, 2, 1, 2)
+        entry.props.visibility = False
+        _register_string_key(
+                '/system/http_proxy/authentication_password', entry)
+
+        enable.connect('toggled', lambda sender:
+                grid.show() if sender.props.active else grid.hide())
+        if enable.props.active:
+            grid.show()
+
+
+class _Grid(gtk.Table):
+
+    def attach_label(self, label, left_attach, right_attach,
+            top_attach, bottom_attach):
+        widget = gtk.Label(label)
+        widget.set_alignment(0, 0)
+        widget.set_line_wrap(True)
+        self.attach(widget, left_attach, right_attach,
+                top_attach, bottom_attach, gtk.SHRINK | gtk.FILL, gtk.SHRINK)
+        widget.show()
+        return widget
+
+    def attach_entry(self, left_attach, right_attach,
+            top_attach, bottom_attach):
+        widget = gtk.Entry()
+        self.attach(widget, left_attach, right_attach,
+                top_attach, bottom_attach, gtk.EXPAND | gtk.FILL, gtk.SHRINK)
+        widget.show()
+        return widget
+
+
+def _set_sensitive(sender, reverse, widgets):
+    is_sensitive = sender.props.active
+    if reverse:
+        is_sensitive = not is_sensitive
+
+    for i in widgets:
+        if isinstance(i, gtk.Container):
+            _set_sensitive(sender, reverse, i.get_children())
+        i.props.sensitive = is_sensitive and _widget_sensitivies.get(i, True)
+
+
+def _register_bool_key(key, widget, reverse=False):
+
+    def set_cb(widget, x, reverse):
+        value = x.get_bool()
+        if reverse:
+            value = not value
+        widget.props.active = value
+
+    def get_cb(widget, reverse):
+        x = gconf.Value(gconf.VALUE_BOOL)
+        value = widget.props.active
+        if reverse:
+            value = not value
+        x.set_bool(value)
+        return x
+
+    _register_key(key, widget, 'toggled', set_cb, get_cb, reverse)
+
+
+def _register_string_key(key, widget):
+
+    def set_cb(widget, x):
+        widget.props.text = x.get_string()
+
+    def get_cb(widget):
+        x = gconf.Value(gconf.VALUE_STRING)
+        x.set_string(widget.props.text)
+        return x
+
+    _register_key(key, widget, 'changed', set_cb, get_cb)
+
+
+def _register_int_key(key, widget):
+
+    def set_cb(widget, x):
+        widget.props.value = x.get_int()
+
+    def get_cb(widget):
+        x = gconf.Value(gconf.VALUE_INT)
+        x.set_int(int(widget.props.value))
+        return x
+
+    _register_key(key, widget.props.adjustment, 'value_changed',
+            set_cb, get_cb)
+
+
+def _register_selector_key(key, widget, value):
+
+    def set_cb(widget, x, value):
+        widget.props.active = x.get_string() == value
+
+    def get_cb(widget, value):
+        if not widget.props.active:
+            return None
+        x = gconf.Value(gconf.VALUE_STRING)
+        x.set_string(value)
+        return x
+
+    _register_key(key, widget, 'toggled', set_cb, get_cb, value)
+
+
+def _register_list_key(key, widget):
+
+    def set_cb(widget, x):
+        hosts = [i.get_string() for i in x.get_list()]
+        widget.props.text = ', '.join(hosts)
+
+    def get_cb(widget):
+        hosts = []
+        for i in re.split('[\s,;:]+', widget.props.text or ''):
+            if not i.strip():
+                continue
+            value = gconf.Value(gconf.VALUE_STRING)
+            value.set_string(i.strip())
+            hosts.append(value)
+        x = gconf.Value(gconf.VALUE_LIST)
+        x.set_list_type(gconf.VALUE_STRING)
+        x.set_list(hosts)
+        return x
+
+    _register_key(key, widget, 'changed', set_cb, get_cb)
+
+
+def _register_key(key, widget, signal, set_cb, get_cb, *args):
+    conf = gconf.client_get_default()
+    value = conf.get(key)
+    if value is not None:
+        set_cb(widget, value, *args)
+
+    _gconf_origin_values[key] = value
+
+    def signal_cb(sender, key, widget, get_cb, *args):
+        value = get_cb(widget, *args)
+        if value is not None:
+            conf = gconf.client_get_default()
+            conf.set(key, value)
+
+    widget.connect(signal, signal_cb, key, widget, get_cb, *args)
-- 
1.7.4.4



More information about the Sugar-devel mailing list