Index: capplets/network/gnome-network-preferences.glade
===================================================================
--- capplets/network/gnome-network-preferences.glade	(revision 8870)
+++ capplets/network/gnome-network-preferences.glade	(working copy)
@@ -26,6 +26,73 @@
       <property name="visible">True</property>
       <property name="homogeneous">False</property>
       <property name="spacing">2</property>
+        <child>
+          <widget class="GtkHBox" id="hbox2">
+            <property name="visible">True</property>
+            <child>
+              <widget class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Location:</property>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkComboBox" id="location_combobox">
+                <property name="visible">True</property>
+                <property name="items" translatable="yes"> </property>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="apply_button">
+		<property name="label">gtk-apply</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="save_button">
+		<property name="label">gtk-save</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="position">3</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="delete_button">
+		<property name="label">gtk-delete</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="position">4</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
 
       <child internal-child="action_area">
 	<widget class="GtkHButtonBox" id="dialog-action_area1">
Index: capplets/network/gnome-network-preferences.c
===================================================================
--- capplets/network/gnome-network-preferences.c	(revision 8870)
+++ capplets/network/gnome-network-preferences.c	(working copy)
@@ -68,6 +68,7 @@
 #define SOCKS_PROXY_PORT_KEY  "/system/proxy/socks_port"
 #define OLD_SOCKS_PROXY_PORT_KEY  "/system/proxy/old_socks_port"
 #define PROXY_AUTOCONFIG_URL_KEY  "/system/proxy/autoconfig_url"
+#define LOCATION_DIR "/apps/control-center/network"
 
 static GtkWidget *details_dialog = NULL;
 static GSList *ignore_hosts = NULL;
@@ -257,7 +258,284 @@
 	gtk_widget_show_all (widget);
 }
 
+static gchar*
+pack_key_to_string (GConfClient* client,gchar* key)
+{
+	int t;
+	gchar *tstr=NULL,*ret,*type=NULL,*t1;
+	GSList *list,*iter;
+	GConfValue* val=gconf_client_get(client,key,NULL);
+	switch (val->type)
+	{
+		case GCONF_VALUE_STRING:
+			t1=gconf_client_get_string (client,key,NULL);
+			tstr=gconf_escape_key (t1,-1);
+			g_free(t1);
+			type="STRING";
+			break;
+		case GCONF_VALUE_INT:
+			t=gconf_client_get_int( client,key,NULL);
+			tstr=g_new (gchar,6);
+			g_snprintf (tstr,6,"%d",t);
+			type="INT";
+			break;
+		case GCONF_VALUE_BOOL:
+			t=gconf_client_get_bool (client,key,NULL);
+			tstr=g_new (gchar,6);
+			g_snprintf (tstr,6,"%d",t);
+			type="BOOL";
+			break;
+		case GCONF_VALUE_LIST:
+			tstr=NULL;
+			list=gconf_client_get_list (client,key,GCONF_VALUE_STRING,NULL);
+			for (iter=list;iter!=NULL;iter=g_slist_next(iter))
+			{
+				if (tstr==NULL) tstr=g_strdup (iter->data);
+				else
+				{
+					t1=g_strconcat (tstr,"@",iter->data,NULL);
+					g_free (tstr);
+					tstr=t1;
+				}
+			}
+			g_slist_foreach (list,(GFunc)g_free,NULL);
+			g_slist_free (list);
+			type="LIST";
+			break;
+		default:
+			return NULL;
+			break;
+	}
+
+	ret=g_malloc (strlen (tstr)+strlen (key)+20);
+	sprintf (ret,"%s %s %s",key,type,tstr);
+
+	g_free (tstr);
+	return ret;
+}
+
 static void
+unpack_string(GConfClient* client,gchar* str)
+{
+	int t;
+	GConfValue* k;
+	gchar *tstr;
+	gchar *key=g_malloc (strlen (str));
+	gchar *type=g_malloc (strlen (str));
+	gchar *value=g_malloc (strlen (str));
+	if (str==NULL) return;
+	key[0]='\0';
+	type[0]='\0';
+	value[0]='\0';
+	sscanf (str,"%s %s %s",key,type,value);
+	if ( !gconf_valid_key (key,NULL) ) return;
+	k=gconf_client_get (client,key,NULL);
+	switch (k->type)
+	{
+		case GCONF_VALUE_STRING:
+			if ( strcmp (type,"STRING")==0 )
+			{
+				tstr=gconf_unescape_key (value,-1);
+				gconf_client_set_string (client,key,tstr,NULL);
+				g_free (tstr);
+			}
+			break;
+		case GCONF_VALUE_BOOL:
+			if ( strcmp (type,"BOOL")==0 )
+			{
+				if (value[0]=='0') gconf_client_set_bool (client,key,FALSE,NULL);\
+				else gconf_client_set_bool (client,key,TRUE,NULL);\
+			}
+			break;
+		case GCONF_VALUE_INT:
+			if ( strcmp (type,"INT")==0 )
+			{
+				sscanf (value,"%d",&t);
+				gconf_client_set_int (client,key,t,NULL);
+			}
+			break;
+		case GCONF_VALUE_LIST:
+			if ( strcmp (type,"LIST")==0 )
+			{
+				GSList *list=NULL;
+				int l=0;
+				for (t=0;t<=strlen (value);t++)
+				{
+					if (value[t]=='@'||value[t]=='\0')
+					{
+						tstr=gconf_unescape_key (value+l,t-l);
+						l=t+1;
+						list=g_slist_append (list,tstr);
+					}
+				}
+				gconf_client_set_list (client,key,GCONF_VALUE_STRING,list,NULL);
+				g_slist_foreach (list,(GFunc)g_free,NULL);
+				g_slist_free (list);
+			}
+			break;
+		default:
+			break;
+	}
+	g_free (key);
+	g_free (type);
+	g_free (value);
+}
+
+static void
+load_location (GConfClient *client,gchar* from)
+{
+	GSList *val=gconf_client_get_list (client,from,GCONF_VALUE_STRING,NULL);
+	GSList *iter=val;
+	while (iter!=NULL)
+	{
+		unpack_string (client,iter->data);
+		iter=g_slist_next (iter);
+	}
+
+	g_slist_foreach (val,(GFunc)g_free,NULL);
+	g_slist_free (val);
+}
+
+static void
+save_location (GConfClient *client,gchar* key)
+{
+	GSList* list=NULL;
+
+	list=g_slist_append (list,pack_key_to_string(client,PROXY_AUTOCONFIG_URL_KEY));
+	list=g_slist_append (list,pack_key_to_string(client,SOCKS_PROXY_PORT_KEY));
+	list=g_slist_append (list,pack_key_to_string(client,SOCKS_PROXY_HOST_KEY));
+	list=g_slist_append (list,pack_key_to_string(client,FTP_PROXY_PORT_KEY));
+	list=g_slist_append (list,pack_key_to_string(client,FTP_PROXY_HOST_KEY));
+	list=g_slist_append (list,pack_key_to_string(client,SECURE_PROXY_PORT_KEY));
+	list=g_slist_append (list,pack_key_to_string(client,SECURE_PROXY_HOST_KEY));
+	list=g_slist_append (list,pack_key_to_string(client,PROXY_MODE_KEY));
+	list=g_slist_append (list,pack_key_to_string(client,HTTP_AUTH_PASSWD_KEY));
+	list=g_slist_append (list,pack_key_to_string(client,HTTP_AUTH_USER_KEY));
+	list=g_slist_append (list,pack_key_to_string(client,HTTP_USE_AUTH_KEY));
+	list=g_slist_append (list,pack_key_to_string(client,HTTP_PROXY_PORT_KEY));
+	list=g_slist_append (list,pack_key_to_string(client,HTTP_PROXY_HOST_KEY));
+	list=g_slist_append (list,pack_key_to_string(client,USE_SAME_PROXY_KEY));
+	list=g_slist_append (list,pack_key_to_string(client,USE_PROXY_KEY));
+	list=g_slist_append (list,pack_key_to_string(client,IGNORE_HOSTS_KEY));
+
+	gconf_client_set_list (client,key,GCONF_VALUE_STRING,list,NULL);
+	gconf_client_notify (client,LOCATION_DIR);
+	g_slist_foreach (list,(GFunc)g_free,NULL);
+	g_slist_free (list);
+}
+
+static void
+cb_change_location_dir(GConfClient *client,
+						guint cnxn_id,
+						GConfEntry *entry,
+						GladeXML *dialog)
+{
+	int i;
+	GtkComboBox *location=GTK_COMBO_BOX (WID ("location_combobox"));
+	GSList *list=gconf_client_all_entries (client,LOCATION_DIR,NULL);
+	GSList *iter;
+	/*Clear GtkComboBox*/
+	i=gtk_tree_model_iter_n_children (gtk_combo_box_get_model (location),NULL);
+	while (i>=0)
+	{
+		gtk_combo_box_remove_text (location,i);
+		i--;
+	}
+
+	for (iter=list;iter!=NULL;iter=g_slist_next(iter))
+	{
+		if (((GConfEntry*)iter->data)->value!=NULL) gtk_combo_box_append_text (location,((GConfEntry*)iter->data)->key+strlen (LOCATION_DIR)+1);
+	}
+
+	g_slist_foreach (list,(GFunc)gconf_entry_free,NULL);
+	g_slist_free (list);
+}
+
+static void
+cb_apply_button_clicked (GtkWidget *applybutton,
+						 GladeXML *dialog)
+{
+	gchar *str;
+	GConfClient* client= gconf_client_get_default ();
+	gchar* name=gtk_combo_box_get_active_text (GTK_COMBO_BOX(WID("location_combobox")));
+
+	str=g_strconcat (LOCATION_DIR,"/",name,NULL);
+	if ( gconf_valid_key (str,NULL) ) load_location (client,str);
+	else
+	{
+		GtkDialog *dialog=GTK_DIALOG (gtk_message_dialog_new (NULL,0,GTK_MESSAGE_ERROR,GTK_BUTTONS_CANCEL,"Incorrect location name"));
+		g_signal_connect_swapped (dialog,"response",G_CALLBACK (gtk_widget_destroy),dialog);
+		gtk_dialog_run (dialog);
+	}
+
+	g_free (str);
+	g_free (name);
+	g_object_unref (client);
+}
+
+static void
+cb_save_button_clicked (GtkWidget *savebutton,
+						 GladeXML *dialog)
+{
+	GConfClient* client=gconf_client_get_default();
+	GtkWidget *askdialog, *text, *content_area;
+	askdialog = gtk_dialog_new_with_buttons ("Save As",
+	                                         NULL,
+	                                         GTK_DIALOG_DESTROY_WITH_PARENT,
+	                                         GTK_STOCK_OK,
+	                                         GTK_RESPONSE_OK,
+	                                         GTK_STOCK_CANCEL,
+	                                         GTK_RESPONSE_CANCEL,
+	                                         NULL);
+	content_area = gtk_dialog_get_content_area (GTK_DIALOG (askdialog));
+	text=gtk_entry_new ();
+	gtk_widget_show (text);
+	gtk_container_add (GTK_CONTAINER (content_area), text);
+	if (gtk_dialog_run (GTK_DIALOG(askdialog))==GTK_RESPONSE_OK)
+	{
+		gchar* key_name=NULL;
+		key_name=g_strconcat (LOCATION_DIR,"/",gtk_entry_get_text(GTK_ENTRY(text)),NULL);
+		if ( gconf_valid_key (key_name,NULL) )
+		{
+			save_location (client,key_name);
+		}
+		else
+		{
+			GtkDialog *dialog=GTK_DIALOG (gtk_message_dialog_new (NULL,0,GTK_MESSAGE_ERROR,GTK_BUTTONS_CANCEL,"Incorrect location name"));
+			g_signal_connect_swapped (dialog,"response",G_CALLBACK (gtk_widget_destroy),dialog);
+			gtk_dialog_run (dialog);
+		}
+		g_free (key_name);
+	}
+	gtk_widget_destroy (text);
+	gtk_widget_destroy (askdialog);
+	g_object_unref (client);
+}
+
+static void
+cb_delete_button_clicked (GtkWidget *deletebutton,
+						 GladeXML *dialog)
+{
+	gchar* str;
+	GConfClient* client=gconf_client_get_default ();
+	gchar* name=gtk_combo_box_get_active_text (GTK_COMBO_BOX(WID("location_combobox")));
+
+	str=g_strconcat (LOCATION_DIR,"/",name,NULL);
+	if ( gconf_valid_key(str,NULL) ) gconf_client_unset (client,str,NULL);
+	else
+	{
+		GtkDialog *dialog=GTK_DIALOG (gtk_message_dialog_new (NULL,0,GTK_MESSAGE_ERROR,GTK_BUTTONS_CANCEL,"Incorrect location name"));
+		g_signal_connect_swapped (dialog,"response",G_CALLBACK (gtk_widget_destroy),dialog);
+		gtk_dialog_run (dialog);
+	}
+	gconf_client_notify (client,LOCATION_DIR);
+
+	g_free (str);
+	g_free (name);
+	g_object_unref (client);
+}
+
+static void
 cb_use_same_proxy_checkbutton_clicked (GtkWidget *checkbutton,
 					GladeXML *dialog)
 {
@@ -445,7 +723,12 @@
 	/* There's a bug in peditors that cause them to not initialize the entry
 	 * correctly. */
 	client = gconf_client_get_default ();
-
+	/*Locations*/
+	gconf_client_notify_add(client,LOCATION_DIR,cb_change_location_dir,dialog,NULL,NULL);
+	g_signal_connect(WID("apply_button"),"clicked",G_CALLBACK(cb_apply_button_clicked),dialog);
+	g_signal_connect(WID("save_button"),"clicked",G_CALLBACK(cb_save_button_clicked),dialog);
+	g_signal_connect(WID("delete_button"),"clicked",G_CALLBACK(cb_delete_button_clicked),dialog);
+	cb_change_location_dir(client,0,NULL,dialog);
 	/* Hackety hack */
 	gtk_label_set_use_markup (GTK_LABEL (GTK_BIN (WID ("none_radiobutton"))->child), TRUE);
 	gtk_label_set_use_markup (GTK_LABEL (GTK_BIN (WID ("manual_radiobutton"))->child), TRUE);
