[gnome-control-center/wip/gbsneto/connection-editor: 3/4] network: Use a table-like widget in address editor



commit 4da80ee6b7e804d04872f484579a274bc9eec446
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Tue May 23 15:02:45 2017 -0300

    network: Use a table-like widget in address editor
    
    According to the latest mockups for the connection editor dialog [1],
    the IPv4 and IPv6 pages are supposed to use a table-like editor to
    manage the addresses, in a similar fashion of what was done to the
    routes editor. This way of editing is not only easier to comprehend,
    but also improves the size of the dialog, requiring much less vertical
    space to present the routes.
    
    The current implementation, however, uses a vertical layout and a toolbar,
    which is inefficient in its usage of space.
    
    Fix that by implementing the table-like editor widget, both in IPv4
    and IPv6 pages.
    
    [1] 
https://raw.githubusercontent.com/gnome-design-team/gnome-mockups/master/system-settings/network/aday2/network-wires.png
    
    https://bugzilla.gnome.org/show_bug.cgi?id=779841

 panels/network/connection-editor/ce-page-ip4.c |  129 ++++++++----------------
 panels/network/connection-editor/ce-page-ip6.c |  113 +++++++--------------
 panels/network/connection-editor/ip4-page.ui   |   77 ++++++++++++++-
 panels/network/connection-editor/ip6-page.ui   |   78 ++++++++++++++-
 4 files changed, 233 insertions(+), 164 deletions(-)
---
diff --git a/panels/network/connection-editor/ce-page-ip4.c b/panels/network/connection-editor/ce-page-ip4.c
index 3b29526..a195065 100644
--- a/panels/network/connection-editor/ce-page-ip4.c
+++ b/panels/network/connection-editor/ce-page-ip4.c
@@ -34,6 +34,7 @@
 
 #define RADIO_IS_ACTIVE(x) (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object(CE_PAGE 
(page)->builder, x))))
 
+static void ensure_empty_address_row (CEPageIP4 *page);
 static void ensure_empty_routes_row (CEPageIP4 *page);
 
 G_DEFINE_TYPE (CEPageIP4, ce_page_ip4, CE_TYPE_PAGE)
@@ -105,7 +106,7 @@ update_row_sensitivity (CEPageIP4 *page, GtkWidget *list)
 }
 
 static void
-update_row_gateway_visibility (CEPageIP4 *page)
+update_row_gateway_sensitivity (CEPageIP4 *page)
 {
         GList *children, *l;
         gint rows = 0;
@@ -113,13 +114,11 @@ update_row_gateway_visibility (CEPageIP4 *page)
         children = gtk_container_get_children (GTK_CONTAINER (page->address_list));
         for (l = children; l; l = l->next) {
                 GtkWidget *row = l->data;
-                GtkWidget *label, *entry;
+                GtkWidget *entry;
 
-                label = GTK_WIDGET (g_object_get_data (G_OBJECT (row), "gateway-label"));
                 entry = GTK_WIDGET (g_object_get_data (G_OBJECT (row), "gateway"));
 
-                gtk_widget_set_visible (label, (rows == 0));
-                gtk_widget_set_visible (entry, (rows == 0));
+                gtk_widget_set_sensitive (entry, (rows == 0));
 
                 rows++;
         }
@@ -143,7 +142,7 @@ remove_row (GtkButton *button, CEPageIP4 *page)
 
         update_row_sensitivity (page, list);
         if (list == page->address_list)
-                update_row_gateway_visibility (page);
+                update_row_gateway_sensitivity (page);
 }
 
 static gboolean
@@ -197,145 +196,98 @@ add_address_row (CEPageIP4   *page,
                  const gchar *network,
                  const gchar *gateway)
 {
+        GtkSizeGroup *group;
         GtkWidget *row;
-        GtkWidget *row_grid;
+        GtkWidget *row_box;
         GtkWidget *widget;
-        GtkWidget *label;
         GtkWidget *delete_button;
         GtkWidget *image;
 
         row = gtk_list_box_row_new ();
 
-        row_grid = gtk_grid_new ();
-        label = gtk_label_new (_("Address"));
-        gtk_widget_set_halign (label, GTK_ALIGN_END);
-        gtk_grid_attach (GTK_GRID (row_grid), label, 1, 1, 1, 1);
+        row_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+        gtk_style_context_add_class (gtk_widget_get_style_context (row_box), "linked");
+
         widget = gtk_entry_new ();
-        gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
         g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_signal_connect_swapped (widget, "activate", G_CALLBACK (ensure_empty_address_row), page);
         g_object_set_data (G_OBJECT (row), "address", widget);
         gtk_entry_set_text (GTK_ENTRY (widget), address);
-        gtk_widget_set_margin_start (widget, 10);
-        gtk_widget_set_margin_end (widget, 10);
+        gtk_entry_set_width_chars (GTK_ENTRY (widget), 16);
         gtk_widget_set_hexpand (widget, TRUE);
-        gtk_grid_attach (GTK_GRID (row_grid), widget, 2, 1, 1, 1);
+        gtk_container_add (GTK_CONTAINER (row_box), widget);
 
-        label = gtk_label_new (_("Netmask"));
-        gtk_widget_set_halign (label, GTK_ALIGN_END);
-        gtk_grid_attach (GTK_GRID (row_grid), label, 1, 2, 1, 1);
         widget = gtk_entry_new ();
-        gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
         g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_signal_connect_swapped (widget, "activate", G_CALLBACK (ensure_empty_address_row), page);
         g_object_set_data (G_OBJECT (row), "network", widget);
         gtk_entry_set_text (GTK_ENTRY (widget), network);
-        gtk_widget_set_margin_start (widget, 10);
-        gtk_widget_set_margin_end (widget, 10);
+        gtk_entry_set_width_chars (GTK_ENTRY (widget), 16);
         gtk_widget_set_hexpand (widget, TRUE);
-        gtk_grid_attach (GTK_GRID (row_grid), widget, 2, 2, 1, 1);
-
+        gtk_container_add (GTK_CONTAINER (row_box), widget);
 
-        label = gtk_label_new (_("Gateway"));
-        gtk_widget_set_halign (label, GTK_ALIGN_END);
-        gtk_grid_attach (GTK_GRID (row_grid), label, 1, 3, 1, 1);
-        g_object_set_data (G_OBJECT (row), "gateway-label", label);
         widget = gtk_entry_new ();
-        gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
         g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_signal_connect_swapped (widget, "activate", G_CALLBACK (ensure_empty_address_row), page);
         g_object_set_data (G_OBJECT (row), "gateway", widget);
         gtk_entry_set_text (GTK_ENTRY (widget), gateway ? gateway : "");
-        gtk_widget_set_margin_start (widget, 10);
-        gtk_widget_set_margin_end (widget, 10);
+        gtk_entry_set_width_chars (GTK_ENTRY (widget), 16);
         gtk_widget_set_hexpand (widget, TRUE);
-        gtk_grid_attach (GTK_GRID (row_grid), widget, 2, 3, 1, 1);
-
-        gtk_widget_set_no_show_all (label, TRUE);
-        gtk_widget_set_no_show_all (widget, FALSE);
+        gtk_container_add (GTK_CONTAINER (row_box), widget);
 
         delete_button = gtk_button_new ();
         gtk_widget_set_sensitive (delete_button, FALSE);
         gtk_style_context_add_class (gtk_widget_get_style_context (delete_button), "image-button");
         g_signal_connect (delete_button, "clicked", G_CALLBACK (remove_row), page);
-        image = gtk_image_new_from_icon_name ("user-trash-symbolic", GTK_ICON_SIZE_MENU);
+        image = gtk_image_new_from_icon_name ("edit-delete-symbolic", GTK_ICON_SIZE_MENU);
         atk_object_set_name (gtk_widget_get_accessible (delete_button), _("Delete Address"));
         gtk_button_set_image (GTK_BUTTON (delete_button), image);
-        gtk_grid_attach (GTK_GRID (row_grid), delete_button, 3, 2, 1, 1);
+        gtk_container_add (GTK_CONTAINER (row_box), delete_button);
         g_object_set_data (G_OBJECT (row), "delete-button", delete_button);
 
-        gtk_grid_set_row_spacing (GTK_GRID (row_grid), 10);
-        gtk_widget_set_margin_start (row_grid, 10);
-        gtk_widget_set_margin_end (row_grid, 10);
-        gtk_widget_set_margin_top (row_grid, 10);
-        gtk_widget_set_margin_bottom (row_grid, 10);
-        gtk_widget_set_halign (row_grid, GTK_ALIGN_FILL);
+        group = GTK_SIZE_GROUP (gtk_builder_get_object (CE_PAGE (page)->builder, "address_sizegroup"));
+        gtk_size_group_add_widget (group, delete_button);
 
-        gtk_container_add (GTK_CONTAINER (row), row_grid);
+        gtk_container_add (GTK_CONTAINER (row), row_box);
         gtk_widget_show_all (row);
         gtk_container_add (GTK_CONTAINER (page->address_list), row);
 
-        update_row_gateway_visibility (page);
+        update_row_gateway_sensitivity (page);
         update_row_sensitivity (page, page->address_list);
 }
 
 static void
-add_empty_address_row (CEPageIP4 *page)
+ensure_empty_address_row (CEPageIP4 *page)
 {
-        add_address_row (page, "", "", "");
-}
+        GList *children, *l;
 
-static void
-add_section_toolbar (CEPageIP4 *page, GtkWidget *section, GCallback add_cb)
-{
-        GtkWidget *toolbar;
-        GtkToolItem *item;
-        GtkStyleContext *context;
-        GtkWidget *box;
-        GtkWidget *button;
-        GtkWidget *image;
+        children = gtk_container_get_children (GTK_CONTAINER (page->address_list));
+        l = children;
+
+        while (l && l->next)
+                l = l->next;
 
-        toolbar = gtk_toolbar_new ();
-        gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS);
-        gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_MENU);
-        context = gtk_widget_get_style_context (toolbar);
-        gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
-        gtk_style_context_add_class (context, GTK_STYLE_CLASS_INLINE_TOOLBAR);
-        gtk_container_add (GTK_CONTAINER (section), toolbar);
-
-        item = gtk_separator_tool_item_new ();
-        gtk_tool_item_set_expand (item, TRUE);
-        gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (item), FALSE);
-        gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (item), 0);
-
-        box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-        item = gtk_tool_item_new ();
-        gtk_container_add (GTK_CONTAINER (item), box);
-        button = gtk_button_new ();
-        g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_cb), page);
-        image = gtk_image_new_from_icon_name ("list-add-symbolic", GTK_ICON_SIZE_MENU);
-        atk_object_set_name (gtk_widget_get_accessible (button), _("Add"));
-        gtk_button_set_image (GTK_BUTTON (button), image);
-        gtk_container_add (GTK_CONTAINER (box), button);
-        gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (item), 1);
+        /* Add the last, stub row if needed*/
+        if (!l || validate_row (l->data))
+                add_address_row (page, "", "", "");
+
+        g_list_free (children);
 }
 
 static void
 add_address_section (CEPageIP4 *page)
 {
         GtkWidget *widget;
-        GtkWidget *frame;
         GtkWidget *list;
         gint i;
 
         widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "address_section"));
 
-        frame = gtk_frame_new (NULL);
-        gtk_container_add (GTK_CONTAINER (widget), frame);
         page->address_list = list = gtk_list_box_new ();
         gtk_list_box_set_selection_mode (GTK_LIST_BOX (list), GTK_SELECTION_NONE);
         gtk_list_box_set_header_func (GTK_LIST_BOX (list), cc_list_box_update_header_func, NULL, NULL);
         gtk_list_box_set_sort_func (GTK_LIST_BOX (list), (GtkListBoxSortFunc)sort_first_last, NULL, NULL);
-        gtk_container_add (GTK_CONTAINER (frame), list);
-
-        add_section_toolbar (page, widget, G_CALLBACK (add_empty_address_row));
+        gtk_container_add (GTK_CONTAINER (widget), list);
 
         for (i = 0; i < nm_setting_ip_config_get_num_addresses (page->setting); i++) {
                 NMIPAddress *addr;
@@ -355,7 +307,7 @@ add_address_section (CEPageIP4 *page)
                                  i == 0 ? nm_setting_ip_config_get_gateway (page->setting) : "");
         }
         if (nm_setting_ip_config_get_num_addresses (page->setting) == 0)
-                add_empty_address_row (page);
+                ensure_empty_address_row (page);
 
         gtk_widget_show_all (widget);
 }
@@ -728,6 +680,9 @@ ui_to_setting (CEPageIP4 *page)
                 addr = nm_ip_address_new (AF_INET, text_address, prefix, NULL);
                 if (addr)
                         g_ptr_array_add (addresses, addr);
+
+                if (!l || !l->next)
+                        ensure_empty_address_row (page);
         }
         g_list_free (children);
 
diff --git a/panels/network/connection-editor/ce-page-ip6.c b/panels/network/connection-editor/ce-page-ip6.c
index f9d5f77..a0fbc9f 100644
--- a/panels/network/connection-editor/ce-page-ip6.c
+++ b/panels/network/connection-editor/ce-page-ip6.c
@@ -34,6 +34,7 @@
 
 #define RADIO_IS_ACTIVE(x) (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object(CE_PAGE 
(page)->builder, x))))
 
+static void ensure_empty_address_row (CEPageIP6 *page);
 static void ensure_empty_routes_row (CEPageIP6 *page);
 
 G_DEFINE_TYPE (CEPageIP6, ce_page_ip6, CE_TYPE_PAGE)
@@ -174,72 +175,59 @@ add_address_row (CEPageIP6   *page,
                  const gchar *network,
                  const gchar *gateway)
 {
+        GtkSizeGroup *group;
         GtkWidget *row;
-        GtkWidget *row_grid;
-        GtkWidget *label;
+        GtkWidget *row_box;
         GtkWidget *widget;
         GtkWidget *delete_button;
         GtkWidget *image;
 
         row = gtk_list_box_row_new ();
 
-        row_grid = gtk_grid_new ();
-        label = gtk_label_new (_("Address"));
-        gtk_widget_set_halign (label, GTK_ALIGN_END);
-        gtk_grid_attach (GTK_GRID (row_grid), label, 1, 1, 1, 1);
+        row_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+        gtk_style_context_add_class (gtk_widget_get_style_context (row_box), "linked");
+
         widget = gtk_entry_new ();
-        gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
         g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_signal_connect_swapped (widget, "activate", G_CALLBACK (ensure_empty_address_row), page);
         g_object_set_data (G_OBJECT (row), "address", widget);
         gtk_entry_set_text (GTK_ENTRY (widget), address);
-        gtk_widget_set_margin_start (widget, 10);
-        gtk_widget_set_margin_end (widget, 10);
+        gtk_entry_set_width_chars (GTK_ENTRY (widget), 16);
         gtk_widget_set_hexpand (widget, TRUE);
-        gtk_grid_attach (GTK_GRID (row_grid), widget, 2, 1, 1, 1);
+        gtk_container_add (GTK_CONTAINER (row_box), widget);
 
-        label = gtk_label_new (_("Prefix"));
-        gtk_widget_set_halign (label, GTK_ALIGN_END);
-        gtk_grid_attach (GTK_GRID (row_grid), label, 1, 2, 1, 1);
         widget = gtk_entry_new ();
-        gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
         g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_signal_connect_swapped (widget, "activate", G_CALLBACK (ensure_empty_address_row), page);
         g_object_set_data (G_OBJECT (row), "prefix", widget);
         gtk_entry_set_text (GTK_ENTRY (widget), network);
-        gtk_widget_set_margin_start (widget, 10);
-        gtk_widget_set_margin_end (widget, 10);
+        gtk_entry_set_width_chars (GTK_ENTRY (widget), 16);
         gtk_widget_set_hexpand (widget, TRUE);
-        gtk_grid_attach (GTK_GRID (row_grid), widget, 2, 2, 1, 1);
+        gtk_container_add (GTK_CONTAINER (row_box), widget);
 
-        label = gtk_label_new (_("Gateway"));
-        gtk_widget_set_halign (label, GTK_ALIGN_END);
-        gtk_grid_attach (GTK_GRID (row_grid), label, 1, 3, 1, 1);
         widget = gtk_entry_new ();
-        gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
         g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_signal_connect_swapped (widget, "activate", G_CALLBACK (ensure_empty_address_row), page);
         g_object_set_data (G_OBJECT (row), "gateway", widget);
         gtk_entry_set_text (GTK_ENTRY (widget), gateway ? gateway : "");
-        gtk_widget_set_margin_start (widget, 10);
-        gtk_widget_set_margin_end (widget, 10);
+        gtk_entry_set_width_chars (GTK_ENTRY (widget), 16);
         gtk_widget_set_hexpand (widget, TRUE);
-        gtk_grid_attach (GTK_GRID (row_grid), widget, 2, 3, 1, 1);
+        gtk_container_add (GTK_CONTAINER (row_box), widget);
 
         delete_button = gtk_button_new ();
+        gtk_widget_set_sensitive (delete_button, FALSE);
         gtk_style_context_add_class (gtk_widget_get_style_context (delete_button), "image-button");
         g_signal_connect (delete_button, "clicked", G_CALLBACK (remove_row), page);
-        image = gtk_image_new_from_icon_name ("user-trash-symbolic", GTK_ICON_SIZE_MENU);
+        image = gtk_image_new_from_icon_name ("edit-delete-symbolic", GTK_ICON_SIZE_MENU);
         atk_object_set_name (gtk_widget_get_accessible (delete_button), _("Delete Address"));
         gtk_button_set_image (GTK_BUTTON (delete_button), image);
-        gtk_grid_attach (GTK_GRID (row_grid), delete_button, 3, 2, 1, 1);
+        gtk_container_add (GTK_CONTAINER (row_box), delete_button);
         g_object_set_data (G_OBJECT (row), "delete-button", delete_button);
 
-        gtk_grid_set_row_spacing (GTK_GRID (row_grid), 10);
-        gtk_widget_set_margin_start (row_grid, 10);
-        gtk_widget_set_margin_end (row_grid, 10);
-        gtk_widget_set_margin_top (row_grid, 10);
-        gtk_widget_set_margin_bottom (row_grid, 10);
-        gtk_widget_set_halign (row_grid, GTK_ALIGN_FILL);
+        group = GTK_SIZE_GROUP (gtk_builder_get_object (CE_PAGE (page)->builder, "address_sizegroup"));
+        gtk_size_group_add_widget (group, delete_button);
 
-        gtk_container_add (GTK_CONTAINER (row), row_grid);
+        gtk_container_add (GTK_CONTAINER (row), row_box);
         gtk_widget_show_all (row);
         gtk_container_add (GTK_CONTAINER (page->address_list), row);
 
@@ -247,65 +235,37 @@ add_address_row (CEPageIP6   *page,
 }
 
 static void
-add_empty_address_row (CEPageIP6 *page)
+ensure_empty_address_row (CEPageIP6 *page)
 {
-        add_address_row (page, "", "", "");
-}
+        GList *children, *l;
 
-static void
-add_section_toolbar (CEPageIP6 *page, GtkWidget *section, GCallback add_cb)
-{
-        GtkWidget *toolbar;
-        GtkToolItem *item;
-        GtkStyleContext *context;
-        GtkWidget *box;
-        GtkWidget *button;
-        GtkWidget *image;
+        children = gtk_container_get_children (GTK_CONTAINER (page->address_list));
+        l = children;
+
+        while (l && l->next)
+                l = l->next;
 
-        toolbar = gtk_toolbar_new ();
-        gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS);
-        gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_MENU);
-        context = gtk_widget_get_style_context (toolbar);
-        gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
-        gtk_style_context_add_class (context, GTK_STYLE_CLASS_INLINE_TOOLBAR);
-        gtk_container_add (GTK_CONTAINER (section), toolbar);
-
-        item = gtk_separator_tool_item_new ();
-        gtk_tool_item_set_expand (item, TRUE);
-        gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (item), FALSE);
-        gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (item), 0);
-
-        box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-        item = gtk_tool_item_new ();
-        gtk_container_add (GTK_CONTAINER (item), box);
-        button = gtk_button_new ();
-        g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_cb), page);
-        image = gtk_image_new_from_icon_name ("list-add-symbolic", GTK_ICON_SIZE_MENU);
-        atk_object_set_name (gtk_widget_get_accessible (button), _("Add"));
-        gtk_button_set_image (GTK_BUTTON (button), image);
-        gtk_container_add (GTK_CONTAINER (box), button);
-        gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (item), 1);
+        /* Add the last, stub row if needed*/
+        if (!l || validate_row (l->data))
+                add_address_row (page, "", "", "");
+
+        g_list_free (children);
 }
 
 static void
 add_address_section (CEPageIP6 *page)
 {
         GtkWidget *widget;
-        GtkWidget *frame;
         GtkWidget *list;
         gint i;
 
         widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "address_section"));
 
-        frame = gtk_frame_new (NULL);
-        gtk_container_add (GTK_CONTAINER (widget), frame);
         page->address_list = list = gtk_list_box_new ();
         gtk_list_box_set_selection_mode (GTK_LIST_BOX (list), GTK_SELECTION_NONE);
         gtk_list_box_set_header_func (GTK_LIST_BOX (list), cc_list_box_update_header_func, NULL, NULL);
         gtk_list_box_set_sort_func (GTK_LIST_BOX (list), (GtkListBoxSortFunc)sort_first_last, NULL, NULL);
-        gtk_container_add (GTK_CONTAINER (frame), list);
-
-        add_section_toolbar (page, widget, G_CALLBACK (add_empty_address_row));
+        gtk_container_add (GTK_CONTAINER (widget), list);
 
         for (i = 0; i < nm_setting_ip_config_get_num_addresses (page->setting); i++) {
                 NMIPAddress *addr;
@@ -318,7 +278,7 @@ add_address_section (CEPageIP6 *page)
                 g_free (netmask);
         }
         if (nm_setting_ip_config_get_num_addresses (page->setting) == 0)
-                add_empty_address_row (page);
+                ensure_empty_address_row (page);
 
         gtk_widget_show_all (widget);
 }
@@ -673,6 +633,9 @@ ui_to_setting (CEPageIP6 *page)
                                       NM_SETTING_IP_CONFIG_GATEWAY, text_gateway,
                                       NULL);
                 nm_setting_ip_config_add_address (page->setting, addr);
+
+                if (!l || !l->next)
+                        ensure_empty_address_row (page);
         }
         g_list_free (children);
 
diff --git a/panels/network/connection-editor/ip4-page.ui b/panels/network/connection-editor/ip4-page.ui
index 844430e..88d7ded 100644
--- a/panels/network/connection-editor/ip4-page.ui
+++ b/panels/network/connection-editor/ip4-page.ui
@@ -104,7 +104,76 @@
                     <property name="can_focus">False</property>
                     <property name="orientation">vertical</property>
                     <child>
-                      <placeholder/>
+                      <object class="GtkLabel">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Addresses</property>
+                        <property name="margin_top">24</property>
+                        <property name="margin_bottom">12</property>
+                        <attributes>
+                          <attribute name="weight" value="bold"/>
+                        </attributes>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="orientation">horizontal</property>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="label" translatable="yes">Address</property>
+                            <style>
+                              <class name="dim-label" />
+                            </style>
+                            <attributes>
+                              <attribute name="scale" value="0.8"/>
+                            </attributes>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="label" translatable="yes">Netmask</property>
+                            <style>
+                              <class name="dim-label" />
+                            </style>
+                            <attributes>
+                              <attribute name="scale" value="0.8"/>
+                            </attributes>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="label" translatable="yes">Gateway</property>
+                            <style>
+                              <class name="dim-label" />
+                            </style>
+                            <attributes>
+                              <attribute name="scale" value="0.8"/>
+                            </attributes>
+                          </object>
+                        </child>
+
+                        <!-- This invisible box is used to add some width in the
+                             end of the header row, assuming the space used by the
+                             delete button in the rows -->
+                        <child>
+                          <object class="GtkBox" id="address_stub_box">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                          </object>
+                        </child>
+                      </object>
                     </child>
                   </object>
                   <packing>
@@ -293,4 +362,10 @@
       <widget name="routes_stub_box" />
     </widgets>
   </object>
+  <object class="GtkSizeGroup" id="address_sizegroup">
+    <property name="mode">horizontal</property>
+    <widgets>
+      <widget name="address_stub_box" />
+    </widgets>
+  </object>
 </interface>
diff --git a/panels/network/connection-editor/ip6-page.ui b/panels/network/connection-editor/ip6-page.ui
index aa55d1b..c2ee1c6 100644
--- a/panels/network/connection-editor/ip6-page.ui
+++ b/panels/network/connection-editor/ip6-page.ui
@@ -118,7 +118,76 @@
                     <property name="can_focus">False</property>
                     <property name="orientation">vertical</property>
                     <child>
-                      <placeholder/>
+                      <object class="GtkLabel">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Addresses</property>
+                        <property name="margin_top">24</property>
+                        <property name="margin_bottom">12</property>
+                        <attributes>
+                          <attribute name="weight" value="bold"/>
+                        </attributes>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="orientation">horizontal</property>
+                        <child>
+                          <object class="GtkLabel" id="address_address_label">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="label" translatable="yes">Address</property>
+                            <style>
+                              <class name="dim-label" />
+                            </style>
+                            <attributes>
+                              <attribute name="scale" value="0.8"/>
+                            </attributes>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="label" translatable="yes">Prefix</property>
+                            <style>
+                              <class name="dim-label" />
+                            </style>
+                            <attributes>
+                              <attribute name="scale" value="0.8"/>
+                            </attributes>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="label" translatable="yes">Gateway</property>
+                            <style>
+                              <class name="dim-label" />
+                            </style>
+                            <attributes>
+                              <attribute name="scale" value="0.8"/>
+                            </attributes>
+                          </object>
+                        </child>
+
+                        <!-- This invisible box is used to add some width in the
+                             end of the header row, assuming the space used by the
+                             delete button in the rows -->
+                        <child>
+                          <object class="GtkBox" id="address_stub_box">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                          </object>
+                        </child>
+                      </object>
                     </child>
                   </object>
                   <packing>
@@ -133,6 +202,7 @@
                     <property name="can_focus">False</property>
                     <property name="xalign">0</property>
                     <property name="label" translatable="yes">DNS</property>
+                    <property name="margin_top">24</property>
                     <attributes>
                       <attribute name="weight" value="bold"/>
                     </attributes>
@@ -305,4 +375,10 @@
       <widget name="routes_stub_box" />
     </widgets>
   </object>
+  <object class="GtkSizeGroup" id="address_sizegroup">
+    <property name="mode">horizontal</property>
+    <widgets>
+      <widget name="address_stub_box" />
+    </widgets>
+  </object>
 </interface>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]