<br><br><div class="gmail_quote">On Tue, Feb 19, 2013 at 4:00 PM, Simon Schampijer <span dir="ltr"><<a href="mailto:simon@schampijer.de" target="_blank">simon@schampijer.de</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi Ajay,<br>
<br>
there are some questions open from the last time this feature was submitted for review: <a href="http://lists.sugarlabs.org/archive/sugar-devel/2012-August/038917.html" target="_blank">http://lists.sugarlabs.org/<u></u>archive/sugar-devel/2012-<u></u>August/038917.html</a><br>

<br>
"There are two differences to the GNOME 3 design. There is a check box in the 'Manual' option that says 'Use authentication'.</blockquote><div><br><br>It is used to specify credentials for the proxy-server, in cased it needs them.<br>
Not specifying these credentials (when a proxy-server demands them), causes "network connection" failures in "Browse".<br><br>So this IS a required section.<br><br><br><br><br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
 And there is an<br>
option 'Ignored Hosts'.</blockquote><div><br>This supposedly bypasses the proxy for the mentioned hosts (though I have been unable to get "<a href="http://www.facebook.com">http://www.facebook.com</a>" to get bypassed using the proxy as specified in <a href="http://wiki.sugarlabs.org/go/Features/Proxy_Settings">http://wiki.sugarlabs.org/go/Features/Proxy_Settings</a>).<br>
<br>On second thoughts, this option might actually do more bad than good, as it might at first defeat the purpose of having all relays being done through a proxy. <br><br>More thoughts welcome regarding this point !!<br><br>
<br><br><br><br><br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> Can you give a bit of background on those, why<br>
you did add those, what issue we have on the XO or discovered does it solve?"<div class="im"><br>
<br>
On 02/17/2013 11:28 AM, Ajay Garg wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
This patch is to be applied on the master-branch.<br>
<br>
Some details of this patch ::<br>
<br>
a)<br>
The proxy-settings are stored both in the "gconf" schema; and "dconf"<br>
schema.<br>
</blockquote>
<br></div>
Can you elaborate why you have chosen to also store into dconf? At one point Sugar wants to switch to Gsettings. Would that help for that case?<br>
<br>
Regards,<br>
   Simon<div><div class="h5"><br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
b)<br>
The package "gnome-vfs2" is a pre-requisite for this patch to work,<br>
since the settings are (also) stored in the dconf schema.<br>
<br>
c)<br>
Also, a slightly unrelated change is the persistence of the values in<br>
the "Network" control-panel.<br>
<br>
Earlier, there was a timeout involved (of 3000 milliseconds), which<br>
would trigger the saving of the values (for eg., "Collaboration  Server"<br>
field was persisted this way).<br>
<br>
Now, the values  are persisted SYNCHRONOUSLY, when the "tick"<br>
toolbar-button is clicked (of course, all the changes are undone, if the<br>
user instead decides to "Cancel changes").<br>
<br>
d)<br>
All the use-cases  of the proxy, are working, as per the wiki page<br>
<a href="http://wiki.sugarlabs.org/go/Features/Proxy_Settings" target="_blank">http://wiki.sugarlabs.org/go/<u></u>Features/Proxy_Settings</a><br>
<br>
Signed-off-by: Ajay Garg <<a href="mailto:ajay@activitycentral.com" target="_blank">ajay@activitycentral.com</a>><br>
---<br>
  extensions/cpsection/network/<u></u>view.py   | 695 ++++++++++++++++++++++++++++++<u></u>+--<br>
  src/jarabe/controlpanel/gui.py         |   2 +<br>
  src/jarabe/controlpanel/<u></u>sectionview.py |   8 +<br>
  src/jarabe/main.py                     |  36 ++<br>
  4 files changed, 707 insertions(+), 34 deletions(-)<br>
<br>
diff --git a/extensions/cpsection/<u></u>network/view.py b/extensions/cpsection/<u></u>network/view.py<br>
index b360759..99b792b 100644<br>
--- a/extensions/cpsection/<u></u>network/view.py<br>
+++ b/extensions/cpsection/<u></u>network/view.py<br>
@@ -16,10 +16,19 @@<br>
<br>
  from gi.repository import Gtk<br>
  from gi.repository import Gdk<br>
+from gi.repository import GConf<br>
  from gi.repository import GObject<br>
+from gi.repository import Gio<br>
+from gi.repository import Pango<br>
  from gettext import gettext as _<br>
<br>
+import os<br>
+import subprocess<br>
+import logging<br>
+<br>
  from sugar3.graphics import style<br>
+from sugar3.graphics.alert import Alert<br>
+from sugar3.graphics.icon import Icon<br>
<br>
  from jarabe.controlpanel.<u></u>sectionview import SectionView<br>
  from jarabe.controlpanel.<u></u>inlinealert import InlineAlert<br>
@@ -31,6 +40,471 @@ TITLE = _('Network')<br>
<br>
  _APPLY_TIMEOUT = 3000<br>
<br>
+# Please refer ::<br>
+# <a href="http://developer.gnome.org/ProxyConfiguration/" target="_blank">http://developer.gnome.org/<u></u>ProxyConfiguration/</a><br>
+<br>
+GSETTINGS_PROXY       = Gio.Settings.new('org.gnome.<u></u>system.proxy')<br>
+GSETTINGS_PROXY_FTP   = Gio.Settings.new('org.gnome.<u></u>system.proxy.ftp')<br>
+GSETTINGS_PROXY_HTTP  = Gio.Settings.new('org.gnome.<u></u>system.proxy.http')<br>
+GSETTINGS_PROXY_HTTPS = Gio.Settings.new('org.gnome.<u></u>system.proxy.https')<br>
+GSETTINGS_PROXY_SOCKS = Gio.Settings.new('org.gnome.<u></u>system.proxy.socks')<br>
+<br>
+<br>
+client = GConf.Client.get_default()<br>
+<br>
+<br>
+class GConfMixin(object):<br>
+    """Mix-in class for GTK widgets backed by GConf"""<br>
+    def __init__(self, gconf_key, gsettings_dconf, dconf_key, widget=None, signal='changed'):<br>
+        self._gconf_key = gconf_key<br>
+        self._gsettings_dconf = gsettings_dconf<br>
+        self._dconf_key = dconf_key<br>
+        self._notify_id = client.notify_add(gconf_key, self.__gconf_notify_cb, None)<br>
+        initial_value = self._get_gconf_value()<br>
+        self._undo_value = initial_value<br>
+        self.set_value_from_gconf(<u></u>initial_value)<br>
+        widget = widget or self<br>
+<br>
+    def undo(self):<br>
+        """Revert to original value if modified"""<br>
+        if not self.changed:<br>
+            return<br>
+        logging.debug('Reverting %r to %r', self._gconf_key, self._undo_value)<br>
+        self._set_gconf_value(self._<u></u>undo_value)<br>
+<br>
+    def get_value_for_gconf(self):<br>
+        """<br>
+        Return the current value of the widget in a format suitable for GConf<br>
+<br>
+        MUST be implemented by subclasses.<br>
+        """<br>
+        raise NotImplementedError()<br>
+<br>
+    def set_value_from_gconf(self, value):<br>
+        """<br>
+        Set the current value of the widget based on a value from GConf<br>
+        MUST be implemented by subclasses.<br>
+        """<br>
+        raise NotImplementedError()<br>
+<br>
+    def __gconf_notify_cb(self, client, transaction_id_, entry, user_data_):<br>
+        new_value = _gconf_value_to_python(entry.<u></u>value)<br>
+        self.set_value_from_gconf(new_<u></u>value)<br>
+<br>
+    def _commit(self, widget):<br>
+        new_value = self.get_value_for_gconf()<br>
+        logging.debug('Setting %r to %r', self._gconf_key, new_value)<br>
+<br>
+        self._set_gconf_value(new_<u></u>value)<br>
+<br>
+    def _set_gconf_value(self, new_value):<br>
+        gconf_type = client.get(self._gconf_key).<u></u>type<br>
+        if gconf_type == GConf.ValueType.STRING:<br>
+            client.set_string(self._gconf_<u></u>key, new_value)<br>
+            self._gsettings_dconf.set_<u></u>string(self._dconf_key, new_value)<br>
+        elif gconf_type == <a href="http://GConf.ValueType.INT" target="_blank">GConf.ValueType.INT</a>:<br>
+            client.set_int(self._gconf_<u></u>key, new_value)<br>
+            self._gsettings_dconf.set_int(<u></u>self._dconf_key, new_value)<br>
+        elif gconf_type == GConf.ValueType.FLOAT:<br>
+            client.set_float(self._gconf_<u></u>key, new_value)<br>
+            self._gsettings_dconf.set_<u></u>double(self._dconf_key, new_value)<br>
+        elif gconf_type == GConf.ValueType.BOOL:<br>
+            client.set_bool(self._gconf_<u></u>key, new_value)<br>
+            self._gsettings_dconf.set_<u></u>boolean(self._dconf_key, new_value)<br>
+        elif gconf_type == GConf.ValueType.LIST:<br>
+            import traceback<br>
+            list_type = client.get(self._gconf_key).<u></u>get_list_type()<br>
+<br>
+            # Persisting the value of a "LIST" via shell, unless and<br>
+            # until <a href="http://bugs.sugarlabs.org/ticket/3926" target="_blank">http://bugs.sugarlabs.org/<u></u>ticket/3926</a> gets solved.<br>
+            commit_list = []<br>
+            for value in new_value:<br>
+                translated_value = value.translate(None, "' ")<br>
+                commit_list.append(translated_<u></u>value)<br>
+<br>
+            environment = os.environ.copy()<br>
+            try:<br>
+                process = subprocess.Popen(['gconftool-2 '<br>
+                                            '--type list '<br>
+                                            '--list-type string '<br>
+                                            '--set %s \'%s\'' % (self._gconf_key,<br>
+                                                                 commit_list)],<br>
+                                            stdout=subprocess.PIPE,<br>
+                                            env=environment,<br>
+                                            shell=True)<br>
+                process.wait()<br>
+<br>
+                self._gsettings_dconf.set_<u></u>strv(self._dconf_key, new_value)<br>
+            except Exception, e:<br>
+                logging.exception(e)<br>
+            #client.set_list(self._gconf_<u></u>key, list_type, new_value)<br>
+        else:<br>
+            raise TypeError('Cannot store %r in GConf' % (new_value, ))<br>
+<br>
+    def _get_gconf_value(self):<br>
+        return _gconf_value_to_python(client.<u></u>get(self._gconf_key))<br>
+<br>
+    def changed(self):<br>
+        return self._undo_value != self.get_value_for_gconf()<br>
+<br>
+<br>
+class GConfEntry(Gtk.Entry, GConfMixin):<br>
+    """Text entry backed by GConf<br>
+<br>
+    It is the callers responsibility to call GConfClient.add_dir() for the<br>
+    GConf directory containing the key.<br>
+    """<br>
+<br>
+    def __init__(self, gconf_key, gsettings_dconf, dconf_key):<br>
+        Gtk.Entry.__init__(self)<br>
+        GConfMixin.__init__(self, gconf_key, gsettings_dconf, dconf_key)<br>
+<br>
+    def get_value_for_gconf(self):<br>
+        return self.props.text<br>
+<br>
+    def set_value_from_gconf(self, value):<br>
+        self.props.text = value<br>
+<br>
+<br>
+class GConfIntegerSpinButton(Gtk.<u></u>SpinButton, GConfMixin):<br>
+    """Integer SpinButton backed by GConf<br>
+    It is the callers responsibility to call GConfClient.add_dir() for the<br>
+    GConf directory containing the key.<br>
+    """<br>
+<br>
+    def __init__(self, gconf_key, gsettings_dconf, dconf_key, adjustment, climb_rate=0):<br>
+        Gtk.SpinButton.__init__(self, adjustment=adjustment, climb_rate=climb_rate)<br>
+        GConfMixin.__init__(self, gconf_key, gsettings_dconf, dconf_key)<br>
+<br>
+    def get_value_for_gconf(self):<br>
+        return self.get_value_as_int()<br>
+<br>
+    def set_value_from_gconf(self, value):<br>
+        self.set_value(value)<br>
+<br>
+<br>
+class GConfStringListEntry(<u></u>GConfEntry):<br>
+    """Text entry backed by a GConf list of strings"""<br>
+<br>
+    def __init__(self, gconf_key, gsettings_dconf, dconf_key, separator=','):<br>
+        self._separator = separator<br>
+        GConfEntry.__init__(self, gconf_key, gsettings_dconf, dconf_key)<br>
+<br>
+    def get_value_for_gconf(self):<br>
+        entries = self.props.text.split(self._<u></u>separator)<br>
+        return [entry for entry in entries if entry]<br>
+<br>
+    def set_value_from_gconf(self, value):<br>
+        self.props.text = self._separator.join(value)<br>
+<br>
+<br>
+class SettingBox(Gtk.HBox):<br>
+    """<br>
+    Base class for "lines" on the screen representing configuration settings<br>
+    """<br>
+<br>
+    def __init__(self, name, size_group=None):<br>
+        Gtk.HBox.__init__(self, spacing=style.DEFAULT_SPACING)<br>
+        self.label = Gtk.Label(name)<br>
+        self.label.modify_fg(Gtk.<u></u>StateType.NORMAL,<br>
+                             style.COLOR_SELECTION_GREY.<u></u>get_gdk_color())<br>
+        self.label.set_alignment(1, 0.5)<br>
+        self.label.show()<br>
+        self.pack_start(self.label, False, False, 0)<br>
+<br>
+        if size_group is not None:<br>
+            size_group.add_widget(self.<u></u>label)<br>
+<br>
+<br>
+class GConfStringSettingBox(<u></u>SettingBox):<br>
+    """A configuration line for a GConf string setting"""<br>
+<br>
+    def __init__(self, name, gconf_key, gsettings_dconf, dconf_key, size_group=None):<br>
+        SettingBox.__init__(self, name, size_group=size_group)<br>
+        self.string_entry = GConfEntry(gconf_key, gsettings_dconf, dconf_key)<br>
+        self.string_entry.show()<br>
+        self.pack_start(self.string_<u></u>entry, True, True, 0)<br>
+<br>
+    def undo(self):<br>
+        """Revert to original value if modified"""<br>
+        self.string_entry.undo()<br>
+<br>
+    def _commit(self, widget):<br>
+        self.string_entry._commit(<u></u>self.string_entry)<br>
+<br>
+    @property<br>
+    def changed(self):<br>
+        return self.string_entry.changed<br>
+<br>
+<br>
+class GConfPasswordSettingBox(<u></u>GConfStringSettingBox):<br>
+    """A configuration line for a GConf password setting"""<br>
+<br>
+    def __init__(self, name, gconf_key, gsettings_dconf, dconf_key, size_group=None):<br>
+        GConfStringSettingBox.__init__<u></u>(self, name, gconf_key,<br>
+                                       gsettings_dconf, dconf_key, size_group)<br>
+        self.string_entry.set_<u></u>visibility(False)<br>
+<br>
+<br>
+class GConfHostListSettingBox(<u></u>GConfStringSettingBox):<br>
+    """A configuration line for a host list GConf setting"""<br>
+<br>
+    def __init__(self, name, gconf_key, gsettings_dconf, dconf_key, size_group=None):<br>
+        SettingBox.__init__(self, name, size_group=size_group)<br>
+        self.hosts_entry = GConfStringListEntry(gconf_<u></u>key,<br>
+                                                gsettings_dconf, dconf_key)<br>
+        self.hosts_entry.show()<br>
+        self.pack_start(self.hosts_<u></u>entry, True, True, 0)<br>
+<br>
+    def undo(self):<br>
+        """Revert to original value if modified"""<br>
+        self.hosts_entry.undo()<br>
+<br>
+    def _commit(self, widget):<br>
+        self.hosts_entry._commit(self.<u></u>hosts_entry)<br>
+<br>
+    @property<br>
+    def changed(self):<br>
+        return self.hosts_entry.changed<br>
+<br>
+class GConfHostPortSettingBox(<u></u>SettingBox):<br>
+    """A configuration line for a combined host name and port GConf setting"""<br>
+<br>
+    def __init__(self, name, host_key, port_key, gsettings_dconf,<br>
+                 dconf_host_key, dconf_port_key, size_group=None):<br>
+        SettingBox.__init__(self, name, size_group=size_group)<br>
+        self.host_name_entry = GConfEntry(host_key, gsettings_dconf,<br>
+                                          dconf_host_key)<br>
+        self.host_name_entry.show()<br>
+        self.pack_start(self.host_<u></u>name_entry, True, True, 0)<br>
+<br>
+        # port number 0 means n/a<br>
+        adjustment = Gtk.Adjustment(0, 0, 65535, 1, 10)<br>
+        self.port_spin_button = GConfIntegerSpinButton(port_<u></u>key,<br>
+                                                       gsettings_dconf,<br>
+                                                       dconf_port_key,<br>
+                                                       adjustment,<br>
+                                                       climb_rate=0.1)<br>
+        self.port_spin_button.show()<br>
+        self.pack_start(self.port_<u></u>spin_button, False, False, 0)<br>
+<br>
+    def undo(self):<br>
+        """Revert to original values if modified"""<br>
+        self.host_name_entry.undo()<br>
+        self.port_spin_button.undo()<br>
+<br>
+    def _commit(self, widget):<br>
+        self.host_name_entry._commit(<u></u>self.host_name_entry)<br>
+        self.port_spin_button._commit(<u></u>self.port_spin_button)<br>
+<br>
+    @property<br>
+    def changed(self):<br>
+        return self.host_name_entry.changed or self.port_spin_button.changed<br>
+<br>
+<br>
+class ExclusiveOptionSetsBox(Gtk.<u></u>VBox):<br>
+    """<br>
+    Container for sets of different settings selected by a top-level setting<br>
+    Renders the top level setting as a ComboBox. Only the currently<br>
+    active set is shown on screen.<br>
+    """<br>
+    def __init__(self, top_name, option_sets, size_group=None):<br>
+        """Initialize an ExclusiveOptionSetsBox instance<br>
+<br>
+        Arguments:<br>
+<br>
+        top_name -- text label used for the top-level selection<br>
+        option_sets -- list of tuples containing text label and GTK<br>
+                       widget to display for each of the option sets<br>
+        size_group -- optional gtk.SizeGroup to use for the top-level label<br>
+        """<br>
+        Gtk.VBox.__init__(self, spacing=style.DEFAULT_SPACING)<br>
+        self.label_size_group = size_group<br>
+        top_box = Gtk.HBox(spacing=style.<u></u>DEFAULT_SPACING)<br>
+        top_box.show()<br>
+        top_label = Gtk.Label(top_name)<br>
+        top_label.modify_fg(Gtk.<u></u>StateType.NORMAL,<br>
+                            style.COLOR_SELECTION_GREY.<u></u>get_gdk_color())<br>
+        top_label.set_alignment(1, 0.5)<br>
+        top_label.show()<br>
+        self.label_size_group.add_<u></u>widget(top_label)<br>
+        top_box.pack_start(top_label, False, False, 0)<br>
+<br>
+        model = Gtk.ListStore(GObject.TYPE_<u></u>STRING, GObject.TYPE_OBJECT)<br>
+        self._top_combo_box = Gtk.ComboBox(model=model)<br>
+        self._top_combo_box.connect('<u></u>changed', self.__combo_changed_cb)<br>
+        self._top_combo_box.show()<br>
+<br>
+        cell_renderer = Gtk.CellRendererText()<br>
+        cell_renderer.props.ellipsize = Pango.EllipsizeMode.MIDDLE<br>
+        cell_renderer.props.ellipsize_<u></u>set = True<br>
+        self._top_combo_box.pack_<u></u>start(cell_renderer, True)<br>
+        self._top_combo_box.add_<u></u>attribute(cell_renderer, 'text', 0)<br>
+        top_box.pack_start(self._top_<u></u>combo_box, True, True, 0)<br>
+        self.pack_start(top_box, False, False, 0)<br>
+<br>
+        self._settings_box = Gtk.VBox()<br>
+        self._settings_box.show()<br>
+        self.pack_start(self._<u></u>settings_box, False, False, 0)<br>
+<br>
+        for name, box in option_sets:<br>
+            model.append((name, box))<br>
+<br>
+    def __combo_changed_cb(self, combobox):<br>
+        giter = combobox.get_active_iter()<br>
+        new_box = combobox.get_model().get(<u></u>giter, 1)[0]<br>
+        current_box = self._settings_box.get_<u></u>children()<br>
+        if current_box:<br>
+            self._settings_box.remove(<u></u>current_box[0])<br>
+<br>
+        self._settings_box.add(new_<u></u>box)<br>
+        new_box.show()<br>
+<br>
+<br>
+class GConfExclusiveOptionSetsBox(<u></u>ExclusiveOptionSetsBox, GConfMixin):<br>
+    """<br>
+    Container for sets of GConf settings based on a top-level setting<br>
+    """<br>
+<br>
+    def __init__(self, top_name, top_gconf_key, gsettings_dconf,<br>
+                 dconf_key, option_sets, size_group=None):<br>
+        """Initialize a GConfExclusiveOptionSetsBox instance<br>
+<br>
+        Arguments:<br>
+<br>
+        top_name -- text label used for the top-level selection<br>
+        top_gconf_key -- key for the GConf entry to use for the<br>
+                         top-level selection<br>
+        option_sets -- list of tuples containing text label, matching<br>
+                       GConf value as well as the GTK widget to display<br>
+                       for each of the option sets<br>
+        size_group -- optional gtk.SizeGroup to use for the top-level label<br>
+        """<br>
+        display_sets = [(name, widget) for name, value, widget in option_sets]<br>
+        self._top_mapping = dict([(name, value)<br>
+                                  for name, value, widget in option_sets])<br>
+        ExclusiveOptionSetsBox.__init_<u></u>_(self, top_name, display_sets,<br>
+                                        size_group=size_group)<br>
+        GConfMixin.__init__(self, top_gconf_key, gsettings_dconf,<br>
+                            dconf_key, self._top_combo_box)<br>
+<br>
+    def get_value_for_gconf(self):<br>
+        giter = self._top_combo_box.get_<u></u>active_iter()<br>
+        if giter is None:<br>
+            return None<br>
+        name = self._top_combo_box.get_model(<u></u>).get(giter, 0)[0]<br>
+        return self._top_mapping[name]<br>
+<br>
+    def set_value_from_gconf(self, value):<br>
+        for idx, (name, widget_) in enumerate(self._top_combo_box.<u></u>get_model()):<br>
+            if self._top_mapping[name] == value:<br>
+                self._top_combo_box.set_<u></u>active(idx)<br>
+                return<br>
+<br>
+        raise ValueError('Invalid value %r' % (value, ))<br>
+<br>
+<br>
+class SpecialGConfExclusiveOptionSet<u></u>sBox(<u></u>GConfExclusiveOptionSetsBox):<br>
+    def __init__(self, top_name, top_gconf_key, gsettings_dconf,<br>
+                 dconf_key, option_sets, size_group=None):<br>
+        GConfExclusiveOptionSetsBox.__<u></u>init__(self, top_name, top_gconf_key,<br>
+                                             gsettings_dconf, dconf_key,<br>
+                                             option_sets, size_group)<br>
+        self._initial_enabled_value = True<br>
+        if self._undo_value == 'none':<br>
+            self._initial_enabled_value = False<br>
+<br>
+    def undo(self):<br>
+        """Revert to original value if modified"""<br>
+        if not self.changed:<br>
+            return<br>
+        logging.debug('Reverting %r to %r', self._gconf_key, self._undo_value)<br>
+        self._set_gconf_value(self._<u></u>undo_value)<br>
+<br>
+        # Also, set the initial value for "org.gnome.system.proxy.http enabled"<br>
+        logging.debug('Reverting org.gnome.system.proxy.http enabled to %r', self._initial_enabled_value)<br>
+        GSETTINGS_PROXY_HTTP.set_<u></u>boolean('enabled', self._initial_enabled_value)<br>
+<br>
+    def _commit(self, widget):<br>
+        """Commit the base key."""<br>
+        super(<u></u>SpecialGConfExclusiveOptionSet<u></u>sBox, self)._commit(None)<br>
+<br>
+        """Plus commit the dconf key :: org.gnome.system.proxy.http enabled"""<br>
+        # The logic to set the value is ::<br>
+        #<br>
+        # * If the mode is "none", the key is to  be set to false.<br>
+        #<br>
+        # * If the mode is not "none" (in other words, it is "manual"<br>
+        #   or "automatic"), the key is to be set to true.<br>
+        enabled_value = True<br>
+        mode = self.get_value_for_gconf()<br>
+        if mode == 'none':<br>
+            enabled_value = False<br>
+<br>
+        logging.debug('Setting org.gnome.system.proxy.http enabled to %r', enabled_value)<br>
+        GSETTINGS_PROXY_HTTP.set_<u></u>boolean('enabled', enabled_value)<br>
+<br>
+    def changed(self):<br>
+        return self._undo_value != self.get_value_for_gconf()<br>
+<br>
+<br>
+class OptionalSettingsBox(Gtk.VBox):<br>
+    """<br>
+    Container for settings (de)activated by a top-level setting<br>
+<br>
+    Renders the top level setting as a CheckButton. The settings are only<br>
+    shown on screen if the top-level setting is enabled.<br>
+    """<br>
+    def __init__(self, top_name, options):<br>
+        """Initialize an OptionalSettingsBox instance<br>
+        Arguments:<br>
+<br>
+        top_name -- text label used for the top-level selection<br>
+        options -- list of GTK widgets to display for each of the options<br>
+        """<br>
+        Gtk.VBox.__init__(self, spacing=style.DEFAULT_SPACING)<br>
+        self._top_check_button = Gtk.CheckButton()<br>
+        self._top_check_button.props.<u></u>label = top_name<br>
+        self._top_check_button.<u></u>connect('toggled', self.__button_changed_cb)<br>
+        self._top_check_button.show()<br>
+        self.pack_start(self._top_<u></u>check_button, True, True, 0)<br>
+        self._settings_box = Gtk.VBox(spacing=style.<u></u>DEFAULT_SPACING)<br>
+        for box in options:<br>
+            self._settings_box.pack_start(<u></u>box, True, True, 0)<br>
+<br>
+    def __button_changed_cb(self, check_button):<br>
+        if check_button.get_active():<br>
+            self._settings_box.show()<br>
+        else:<br>
+            self._settings_box.hide()<br>
+<br>
+<br>
+class GConfOptionalSettingsBox(<u></u>OptionalSettingsBox, GConfMixin):<br>
+    """<br>
+    Container for GConf settings (de)activated by a top-level setting<br>
+    """<br>
+    def __init__(self, top_name, top_gconf_key, gsettings_dconf,<br>
+                 dconf_key, options):<br>
+        """Initialize a GConfExclusiveOptionSetsBox instance<br>
+        Arguments:<br>
+<br>
+        top_name -- text label used for the top-level selection<br>
+        top_gconf_key -- key for the GConf entry to use for the<br>
+                         top-level selection<br>
+        options -- list of  GTK widgets to display for each of the options<br>
+        """<br>
+        OptionalSettingsBox.__init__(<u></u>self, top_name, options)<br>
+        GConfMixin.__init__(self, top_gconf_key, gsettings_dconf,<br>
+                            dconf_key, self._top_check_button,<br>
+                            signal='toggled')<br>
+<br>
+    def get_value_for_gconf(self):<br>
+        return self._top_check_button.get_<u></u>active()<br>
+<br>
+    def set_value_from_gconf(self, value):<br>
+        self._top_check_button.set_<u></u>active(value)<br>
+        self.pack_start(self._<u></u>settings_box, False, False, 0)<br>
+<br>
<br>
  class Network(SectionView):<br>
      def __init__(self, model, alerts):<br>
@@ -44,6 +518,10 @@ class Network(SectionView):<br>
          self._jabber_change_handler = None<br>
          self._radio_change_handler = None<br>
          self._network_configuration_<u></u>reset_handler = None<br>
+        self._undo_objects = []<br>
+<br>
+        client.add_dir('/system/http_<u></u>proxy', GConf.ClientPreloadType.<u></u>PRELOAD_ONELEVEL)<br>
+        client.add_dir('/system/proxy'<u></u>, GConf.ClientPreloadType.<u></u>PRELOAD_ONELEVEL)<br>
<br>
          self.set_border_width(style.<u></u>DEFAULT_SPACING * 2)<br>
          self.set_spacing(style.<u></u>DEFAULT_SPACING)<br>
@@ -174,10 +652,141 @@ class Network(SectionView):<br>
          workspace.pack_start(box_mesh, False, True, 0)<br>
          box_mesh.show()<br>
<br>
+        proxy_separator = Gtk.HSeparator()<br>
+        workspace.pack_start(proxy_<u></u>separator, False, False, 0)<br>
+        proxy_separator.show()<br>
+<br>
+        self._add_proxy_section(<u></u>workspace)<br>
+<br>
          self.setup()<br>
<br>
+    def _add_proxy_section(self, workspace):<br>
+        proxy_title = Gtk.Label(_('Proxy'))<br>
+        proxy_title.set_alignment(0, 0)<br>
+        proxy_title.show()<br>
+        workspace.pack_start(proxy_<u></u>title, False, False, 0)<br>
+<br>
+        proxy_box = Gtk.VBox()<br>
+        proxy_box.set_border_width(<u></u>style.DEFAULT_SPACING * 2)<br>
+        proxy_box.set_spacing(style.<u></u>DEFAULT_SPACING)<br>
+        proxy_box.show()<br>
+<br>
+        workspace.pack_start(proxy_<u></u>box, True, True, 0)<br>
+<br>
+        size_group = Gtk.SizeGroup(Gtk.<u></u>SizeGroupMode.HORIZONTAL)<br>
+<br>
+        automatic_proxy_box = Gtk.VBox()<br>
+        automatic_proxy_box.set_<u></u>spacing(style.DEFAULT_SPACING)<br>
+<br>
+        url_box = GConfStringSettingBox(_('<u></u>Configuration URL:'),<br>
+                                        '/system/proxy/autoconfig_url'<u></u>,<br>
+                                        GSETTINGS_PROXY,<br>
+                                        'autoconfig-url',<br>
+                                        size_group)<br>
+        url_box.show()<br>
+        automatic_proxy_box.pack_<u></u>start(url_box, True, True, 0)<br>
+        self._undo_objects.append(url_<u></u>box)<br>
+<br>
+        wpad_help_text = _('Web Proxy Autodiscovery (WPAD) is used when a'<br>
+                           ' Configuration URL is not provided. This is not'<br>
+                           ' recommended for untrusted public networks.')<br>
+        automatic_proxy_help = Gtk.Label(wpad_help_text)<br>
+        automatic_proxy_help.set_<u></u>alignment(0, 0)<br>
+        automatic_proxy_help.set_line_<u></u>wrap(True)<br>
+        automatic_proxy_help.show()<br>
+        automatic_proxy_box.pack_<u></u>start(automatic_proxy_help, True, True, 0)<br>
+<br>
+        manual_proxy_box = Gtk.VBox()<br>
+        manual_proxy_box.set_spacing(<u></u>style.DEFAULT_SPACING)<br>
+<br>
+        http_box = GConfHostPortSettingBox(_('<u></u>HTTP Proxy:'),<br>
+                                           '/system/http_proxy/host',<br>
+                                           '/system/http_proxy/port',<br>
+                                            GSETTINGS_PROXY_HTTP,<br>
+                                            'host',<br>
+                                            'port',<br>
+                                           size_group)<br>
+        http_box.show()<br>
+        manual_proxy_box.pack_start(<u></u>http_box, True, True, 0)<br>
+        self._undo_objects.append(<u></u>http_box)<br>
+<br>
+        user_name_box = GConfStringSettingBox(_('<u></u>Username:'),<br>
+            '/system/http_proxy/<u></u>authentication_user',<br>
+            GSETTINGS_PROXY_HTTP, 'authentication-user', size_group)<br>
+        user_name_box.show()<br>
+        self._undo_objects.append(<u></u>user_name_box)<br>
+<br>
+        password_box = GConfPasswordSettingBox(_('<u></u>Password:'),<br>
+            '/system/http_proxy/<u></u>authentication_password',<br>
+            GSETTINGS_PROXY_HTTP, 'authentication-password', size_group)<br>
+        password_box.show()<br>
+        self._undo_objects.append(<u></u>password_box)<br>
+<br>
+        auth_box = GConfOptionalSettingsBox(_('<u></u>Use authentication'),<br>
+            '/system/http_proxy/use_<u></u>authentication',<br>
+            GSETTINGS_PROXY_HTTP,<br>
+            'use-authentication',<br>
+            [user_name_box, password_box])<br>
+        auth_box.show()<br>
+        manual_proxy_box.pack_start(<u></u>auth_box, True, True, 0)<br>
+        self._undo_objects.append(<u></u>auth_box)<br>
+<br>
+        https_box = GConfHostPortSettingBox(_('<u></u>HTTPS Proxy:'),<br>
+                                            '/system/proxy/secure_host',<br>
+                                            '/system/proxy/secure_port',<br>
+                                            GSETTINGS_PROXY_HTTPS,<br>
+                                            'host',<br>
+                                            'port',<br>
+                                            size_group)<br>
+        https_box.show()<br>
+        manual_proxy_box.pack_start(<u></u>https_box, True, True, 0)<br>
+        self._undo_objects.append(<u></u>https_box)<br>
+<br>
+        ftp_box = GConfHostPortSettingBox(_('FTP Proxy:'),<br>
+                                          '/system/proxy/ftp_host',<br>
+                                          '/system/proxy/ftp_port',<br>
+                                          GSETTINGS_PROXY_FTP,<br>
+                                          'host',<br>
+                                          'port',<br>
+                                          size_group)<br>
+        ftp_box.show()<br>
+        manual_proxy_box.pack_start(<u></u>ftp_box, True, True, 0)<br>
+        self._undo_objects.append(ftp_<u></u>box)<br>
+<br>
+        socks_box = GConfHostPortSettingBox(_('<u></u>SOCKS Proxy:'),<br>
+                                            '/system/proxy/socks_host',<br>
+                                            '/system/proxy/socks_port',<br>
+                                            GSETTINGS_PROXY_SOCKS,<br>
+                                            'host',<br>
+                                            'port',<br>
+                                            size_group)<br>
+        socks_box.show()<br>
+        manual_proxy_box.pack_start(<u></u>socks_box, True, True, 0)<br>
+        self._undo_objects.append(<u></u>socks_box)<br>
+<br>
+        option_sets = [('None', 'none', Gtk.VBox()),<br>
+                       ('Automatic', 'auto', automatic_proxy_box),<br>
+                       ('Manual', 'manual', manual_proxy_box)]<br>
+        option_sets_box = SpecialGConfExclusiveOptionSet<u></u>sBox(_('Method:'),<br>
+                                                      '/system/proxy/mode',<br>
+                                                      GSETTINGS_PROXY,<br>
+                                                      'mode',<br>
+                                                      option_sets, size_group)<br>
+        option_sets_box.show()<br>
+        proxy_box.pack_start(option_<u></u>sets_box, False, False, 0)<br>
+        self._undo_objects.append(<u></u>option_sets_box)<br>
+<br>
+        no_proxy_box = GConfHostListSettingBox(_('<u></u>Ignored Hosts'),<br>
+            '/system/http_proxy/ignore_<u></u>hosts', GSETTINGS_PROXY,<br>
+            'ignore-hosts', size_group)<br>
+        no_proxy_box.show()<br>
+        proxy_box.pack_start(no_proxy_<u></u>box, False, False, 0)<br>
+        self._undo_objects.append(no_<u></u>proxy_box)<br>
+<br>
+<br>
      def setup(self):<br>
-        self._entry.set_text(self._<u></u>model.get_jabber())<br>
+        self._old_jabber_entry = self._model.get_jabber()<br>
+        self._entry.set_text(self._<u></u>old_jabber_entry)<br>
          try:<br>
              radio_state = self._model.get_radio()<br>
          except self._model.ReadError, detail:<br>
@@ -191,24 +800,42 @@ class Network(SectionView):<br>
          self.needs_restart = False<br>
          self._radio_change_handler = self._button.connect( \<br>
                  'toggled', self.__radio_toggled_cb)<br>
-        self._jabber_change_handler = self._entry.connect( \<br>
-                'changed', self.__jabber_changed_cb)<br>
          self._network_configuration_<u></u>reset_handler =  \<br>
                  self._clear_history_button.<u></u>connect( \<br>
                          'clicked', self.__network_configuration_<u></u>reset_cb)<br>
<br>
      def undo(self):<br>
          self._button.disconnect(self._<u></u>radio_change_handler)<br>
-        self._entry.disconnect(self._<u></u>jabber_change_handler)<br>
          self._model.undo()<br>
          self._jabber_alert.hide()<br>
+        self._entry.set_text(self._<u></u>old_jabber_entry)<br>
          self._radio_alert.hide()<br>
+        for setting in self._undo_objects:<br>
+            setting.undo()<br>
+<br>
+    # pylint: disable=E0202<br>
+    @property<br>
+    def needs_restart(self):<br>
+        # Some parts of Sugar as well as many non-Gnome applications<br>
+        # use environment variables rather than gconf for proxy<br>
+        # settings, so we need to restart for the changes to take<br>
+        # _full_ effect.<br>
+        if self._entry.get_text() != self._old_jabber_entry:<br>
+            return True<br>
+<br>
+        for setting in self._undo_objects:<br>
+            if setting.changed():<br>
+                return True<br>
<br>
-    def _validate(self):<br>
-        if self._jabber_valid and self._radio_valid:<br>
-            self.props.is_valid = True<br>
-        else:<br>
-            self.props.is_valid = False<br>
+        return False<br>
+<br>
+    # pylint: disable=E0102,E1101<br>
+    @needs_restart.setter<br>
+    def needs_restart(self, value):<br>
+        # needs_restart is a property (i.e. gets calculated) in this Control<br>
+        # Panel, but SectionView.__init__() wants to initialise it to False,<br>
+        # so we need to provide a (fake) setter.<br>
+        pass<br>
<br>
      def __radio_toggled_cb(self, widget, data=None):<br>
          radio_state = widget.get_active()<br>
@@ -225,34 +852,34 @@ class Network(SectionView):<br>
          self._validate()<br>
          return False<br>
<br>
-    def __jabber_changed_cb(self, widget, data=None):<br>
-        if self._jabber_sid:<br>
-            GObject.source_remove(self._<u></u>jabber_sid)<br>
-        self._jabber_sid = GObject.timeout_add(_APPLY_<u></u>TIMEOUT,<br>
-                                               self.__jabber_timeout_cb,<br>
-                                               widget)<br>
-<br>
-    def __jabber_timeout_cb(self, widget):<br>
-        self._jabber_sid = 0<br>
-        if widget.get_text() == self._model.get_jabber:<br>
-            return<br>
-        try:<br>
-            self._model.set_jabber(widget.<u></u>get_text())<br>
-        except self._model.ReadError, detail:<br>
-            self._jabber_alert.props.msg = detail<br>
-            self._jabber_valid = False<br>
-            self._jabber_alert.show()<br>
-            self.restart_alerts.append('<u></u>jabber')<br>
-        else:<br>
-            self._jabber_valid = True<br>
-            self._jabber_alert.hide()<br>
-<br>
-        self._validate()<br>
-        return False<br>
-<br>
      def __network_configuration_reset_<u></u>cb(self, widget):<br>
          # FIXME: takes effect immediately, not after CP is closed with<br>
          # confirmation button<br>
          self._model.clear_networks()<br>
          if not self._model.have_networks():<br>
              self._clear_history_button.<u></u>set_sensitive(False)<br>
+<br>
+    def perform_accept_actions(self):<br>
+        current_jabber_entry = self._entry.get_text()<br>
+        if current_jabber_entry != self._old_jabber_entry:<br>
+            self._model.set_jabber(<u></u>current_jabber_entry)<br>
+<br>
+        for setting in self._undo_objects:<br>
+            setting._commit(setting)<br>
+<br>
+<br>
+def _gconf_value_to_python(gconf_<u></u>value):<br>
+    if gconf_value.type == GConf.ValueType.STRING:<br>
+        return gconf_value.get_string()<br>
+    elif gconf_value.type == <a href="http://GConf.ValueType.INT" target="_blank">GConf.ValueType.INT</a>:<br>
+        return gconf_value.get_int()<br>
+    elif gconf_value.type == GConf.ValueType.FLOAT:<br>
+        return gconf_value.get_float()<br>
+    elif gconf_value.type == GConf.ValueType.BOOL:<br>
+        return gconf_value.get_bool()<br>
+    elif gconf_value.type == GConf.ValueType.LIST:<br>
+        return [_gconf_value_to_python(entry)<br>
+                for entry in gconf_value.get_list()]<br>
+    else:<br>
+        raise TypeError("Don't know how to handle GConf value"<br>
+                        " type %r" % (gconf_value.type, ))<br>
diff --git a/src/jarabe/controlpanel/gui.<u></u>py b/src/jarabe/controlpanel/gui.<u></u>py<br>
index f28b248..7805bb2 100644<br>
--- a/src/jarabe/controlpanel/gui.<u></u>py<br>
+++ b/src/jarabe/controlpanel/gui.<u></u>py<br>
@@ -302,12 +302,14 @@ class ControlPanel(Gtk.Window):<br>
          return options<br>
<br>
      def __cancel_clicked_cb(self, widget):<br>
+        self._section_view.perform_<u></u>cancel_actions()<br>
          self._section_view.undo()<br>
          self._options[self._current_<u></u>option]['alerts'] = []<br>
          self._section_toolbar.accept_<u></u>button.set_sensitive(True)<br>
          self._show_main_view()<br>
<br>
      def __accept_clicked_cb(self, widget):<br>
+        self._section_view.perform_<u></u>accept_actions()<br>
          if self._section_view.needs_<u></u>restart:<br>
              self._section_toolbar.accept_<u></u>button.set_sensitive(False)<br>
              self._section_toolbar.cancel_<u></u>button.set_sensitive(False)<br>
diff --git a/src/jarabe/controlpanel/<u></u>sectionview.py b/src/jarabe/controlpanel/<u></u>sectionview.py<br>
index cbf4768..bee64e0 100644<br>
--- a/src/jarabe/controlpanel/<u></u>sectionview.py<br>
+++ b/src/jarabe/controlpanel/<u></u>sectionview.py<br>
@@ -52,3 +52,11 @@ class SectionView(Gtk.VBox):<br>
      def undo(self):<br>
          """Undo here the changes that have been made in this section."""<br>
          pass<br>
+<br>
+    def perform_cancel_actions(self):<br>
+        """Perform additional actions, when the "Cancel" button is clicked."""<br>
+        pass<br>
+<br>
+    def perform_accept_actions(self):<br>
+        """Perform additional actions, when the "Ok" button is clicked."""<br>
+        pass<br>
diff --git a/src/jarabe/main.py b/src/jarabe/main.py<br>
index 44880ba..e4893a1 100755<br>
--- a/src/jarabe/main.py<br>
+++ b/src/jarabe/main.py<br>
@@ -230,6 +230,41 @@ def setup_theme():<br>
      icons_path = os.path.join(config.data_path, 'icons')<br>
      Gtk.IconTheme.get_default().<u></u>append_search_path(icons_path)<br>
<br>
+def export_proxy_settings():<br>
+    """<br>
+    Export manual proxy settings from GConf as environment variables<br>
+<br>
+    Some applications and tools and even some parts of Sugar will use<br>
+    the http_proxy environment variable if set, but don't use the Gnome<br>
+    (GConf) proxy settings.<br>
+    """<br>
+    client = GConf.Client.get_default()<br>
+<br>
+    # Note: See <a href="https://dev.laptop.org.au/issues/1179#note-9" target="_blank">https://dev.laptop.org.au/<u></u>issues/1179#note-9</a><br>
+    if client.get_string('/system/<u></u>proxy/mode') == 'none':<br>
+        return<br>
+<br>
+    http_host = client.get_string('/system/<u></u>http_proxy/host')<br>
+    http_port = client.get_int('/system/http_<u></u>proxy/port')<br>
+    use_auth = client.get_bool('/system/http_<u></u>proxy/use_authentication')<br>
+    if use_auth:<br>
+        user = client.get_string('/system/<u></u>http_proxy/authentication_<u></u>user')<br>
+        pw = client.get_string('/system/<u></u>http_proxy/authentication_<u></u>password')<br>
+        http_proxy = 'http://%s:%s@%s:%d/' % (user, pw, http_host, http_port)<br>
+    else:<br>
+        http_proxy = 'http://%s:%d/' % (http_host, http_port)<br>
+<br>
+    os.environ['http_proxy'] = http_proxy<br>
+<br>
+    ignore_hosts = []<br>
+    ignore_hosts_list = client.get('/system/http_<u></u>proxy/ignore_hosts')<br>
+<br>
+    # Process, only if the "ignore_hosts_list" is non-empty.<br>
+    if ignore_hosts_list:<br>
+        for entry in ignore_hosts_list.get_list():<br>
+            ignore_hosts.append(entry.get_<u></u>string())<br>
+        os.environ['no_proxy'] = ','.join(ignore_hosts)<br>
+<br>
  def _start_intro():<br>
      window = IntroWindow()<br>
      window.connect('done', __intro_window_done_cb)<br>
@@ -246,6 +281,7 @@ def main():<br>
<br>
      _start_window_manager()<br>
<br>
+    export_proxy_settings()<br>
      setup_locale()<br>
      setup_fonts()<br>
      setup_theme()<br>
<br>
</blockquote>
<br></div></div>
______________________________<u></u>_________________<br>
Sugar-devel mailing list<br>
<a href="mailto:Sugar-devel@lists.sugarlabs.org" target="_blank">Sugar-devel@lists.sugarlabs.<u></u>org</a><br>
<a href="http://lists.sugarlabs.org/listinfo/sugar-devel" target="_blank">http://lists.sugarlabs.org/<u></u>listinfo/sugar-devel</a><br>
</blockquote></div><br><br clear="all"><br>-- <br><font face="arial, sans-serif">Regards,<br><br>Ajay Garg</font><br style="font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)"><font face="arial, sans-serif">Dextrose Developer</font><br style="font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)">
<span style="font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)">Activity Central: </span><a href="http://activitycentral.com/" style="font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)" target="_blank">http://activitycentral.com</a>