network: Use a table-like widget to edit routes

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 routes. This editor 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
This commit is contained in:
Georges Basile Stavracas Neto 2017-05-23 13:04:52 -03:00 committed by Rui Matos
parent 2e570099f6
commit 08657fac44
4 changed files with 320 additions and 142 deletions

View file

@ -34,6 +34,8 @@
#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_routes_row (CEPageIP4 *page);
G_DEFINE_TYPE (CEPageIP4, ce_page_ip4, CE_TYPE_PAGE)
enum {
@ -88,7 +90,7 @@ static void
update_row_sensitivity (CEPageIP4 *page, GtkWidget *list)
{
GList *children, *l;
gint rows = 0;
gint rows = 0, i = 0;
children = gtk_container_get_children (GTK_CONTAINER (list));
for (l = children; l; l = l->next) {
@ -105,7 +107,7 @@ update_row_sensitivity (CEPageIP4 *page, GtkWidget *list)
button = GTK_WIDGET (g_object_get_data (G_OBJECT (row), "delete-button"));
if (button != NULL)
gtk_widget_set_sensitive (button, rows > 1);
gtk_widget_set_sensitive (button, rows > 1 && ++i < rows);
}
g_list_free (children);
}
@ -152,6 +154,29 @@ remove_row (GtkButton *button, CEPageIP4 *page)
update_row_gateway_visibility (page);
}
static gboolean
validate_row (GtkWidget *row)
{
GtkWidget *box;
GList *children, *l;
gboolean valid;
valid = FALSE;
box = gtk_bin_get_child (GTK_BIN (row));
children = gtk_container_get_children (GTK_CONTAINER (box));
for (l = children; l != NULL; l = l->next) {
if (!GTK_IS_ENTRY (l->data))
continue;
valid = valid || gtk_entry_get_text_length (l->data) > 0;
}
g_list_free (children);
return valid;
}
static gint
sort_first_last (gconstpointer a, gconstpointer b, gpointer data)
{
@ -235,6 +260,7 @@ add_address_row (CEPageIP4 *page,
gtk_widget_set_no_show_all (widget, FALSE);
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);
@ -382,92 +408,76 @@ add_route_row (CEPageIP4 *page,
const gchar *gateway,
gint metric)
{
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_routes_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_routes_row), page);
g_object_set_data (G_OBJECT (row), "netmask", widget);
gtk_entry_set_text (GTK_ENTRY (widget), netmask);
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_routes_row), page);
g_object_set_data (G_OBJECT (row), "gateway", widget);
gtk_entry_set_text (GTK_ENTRY (widget), 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);
/* Translators: Please see https://en.wikipedia.org/wiki/Metrics_(networking) */
label = gtk_label_new (C_("network parameters", "Metric"));
gtk_widget_set_halign (label, GTK_ALIGN_END);
gtk_grid_attach (GTK_GRID (row_grid), label, 1, 4, 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_routes_row), page);
g_object_set_data (G_OBJECT (row), "metric", widget);
if (metric >= 0) {
gchar *s = g_strdup_printf ("%d", metric);
gtk_entry_set_text (GTK_ENTRY (widget), s);
g_free (s);
}
gtk_widget_set_margin_start (widget, 10);
gtk_widget_set_margin_end (widget, 10);
gtk_entry_set_width_chars (GTK_ENTRY (widget), 5);
gtk_widget_set_hexpand (widget, TRUE);
gtk_grid_attach (GTK_GRID (row_grid), widget, 2, 4, 1, 1);
gtk_container_add (GTK_CONTAINER (row_box), widget);
group = GTK_SIZE_GROUP (gtk_builder_get_object (CE_PAGE (page)->builder, "routes_metric_sizegroup"));
gtk_size_group_add_widget (group, widget);
delete_button = gtk_button_new ();
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 Route"));
gtk_button_set_image (GTK_BUTTON (delete_button), image);
gtk_widget_set_halign (delete_button, GTK_ALIGN_CENTER);
gtk_widget_set_valign (delete_button, GTK_ALIGN_CENTER);
gtk_grid_attach (GTK_GRID (row_grid), delete_button, 3, 1, 1, 4);
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, "routes_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->routes_list), row);
@ -475,33 +485,41 @@ add_route_row (CEPageIP4 *page,
}
static void
add_empty_route_row (CEPageIP4 *page)
ensure_empty_routes_row (CEPageIP4 *page)
{
add_route_row (page, "", "", "", -1);
GList *children, *l;
children = gtk_container_get_children (GTK_CONTAINER (page->routes_list));
l = children;
while (l && l->next)
l = l->next;
/* Add the last, stub row if needed*/
if (!l || validate_row (l->data))
add_route_row (page, "", "", "", -1);
g_list_free (children);
}
static void
add_routes_section (CEPageIP4 *page)
{
GtkWidget *widget;
GtkWidget *frame;
GtkWidget *list;
gint i;
widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "routes_section"));
frame = gtk_frame_new (NULL);
gtk_container_add (GTK_CONTAINER (widget), frame);
page->routes_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);
gtk_container_add (GTK_CONTAINER (widget), list);
page->auto_routes = GTK_SWITCH (gtk_builder_get_object (CE_PAGE (page)->builder, "auto_routes_switch"));
gtk_switch_set_active (page->auto_routes, !nm_setting_ip_config_get_ignore_auto_routes (page->setting));
g_signal_connect (page->auto_routes, "notify::active", G_CALLBACK (switch_toggled), page);
add_section_toolbar (page, widget, G_CALLBACK (add_empty_route_row));
for (i = 0; i < nm_setting_ip_config_get_num_routes (page->setting); i++) {
NMIPRoute *route;
@ -522,7 +540,7 @@ add_routes_section (CEPageIP4 *page)
nm_ip_route_get_metric (route));
}
if (nm_setting_ip_config_get_num_routes (page->setting) == 0)
add_empty_route_row (page);
ensure_empty_routes_row (page);
gtk_widget_show_all (widget);
}
@ -842,6 +860,9 @@ ui_to_setting (CEPageIP4 *page)
route = nm_ip_route_new (AF_INET, text_address, netmask, text_gateway, metric, NULL);
if (route)
g_ptr_array_add (routes, route);
if (!l || !l->next)
ensure_empty_routes_row (page);
}
g_list_free (children);

View file

@ -34,6 +34,8 @@
#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_routes_row (CEPageIP6 *page);
G_DEFINE_TYPE (CEPageIP6, ce_page_ip6, CE_TYPE_PAGE)
enum {
@ -89,7 +91,7 @@ static void
update_row_sensitivity (CEPageIP6 *page, GtkWidget *list)
{
GList *children, *l;
gint rows = 0;
gint rows = 0, i = 0;
children = gtk_container_get_children (GTK_CONTAINER (list));
for (l = children; l; l = l->next) {
@ -106,7 +108,7 @@ update_row_sensitivity (CEPageIP6 *page, GtkWidget *list)
button = GTK_WIDGET (g_object_get_data (G_OBJECT (row), "delete-button"));
if (button != NULL)
gtk_widget_set_sensitive (button, rows > 1);
gtk_widget_set_sensitive (button, rows > 1 && ++i < rows);
}
g_list_free (children);
}
@ -129,6 +131,29 @@ remove_row (GtkButton *button, CEPageIP6 *page)
update_row_sensitivity (page, list);
}
static gboolean
validate_row (GtkWidget *row)
{
GtkWidget *box;
GList *children, *l;
gboolean valid;
valid = FALSE;
box = gtk_bin_get_child (GTK_BIN (row));
children = gtk_container_get_children (GTK_CONTAINER (box));
for (l = children; l != NULL; l = l->next) {
if (!GTK_IS_ENTRY (l->data))
continue;
valid = valid || gtk_entry_get_text_length (l->data) > 0;
}
g_list_free (children);
return valid;
}
static gint
sort_first_last (gconstpointer a, gconstpointer b, gpointer data)
{
@ -347,94 +372,96 @@ add_route_row (CEPageIP6 *page,
const gchar *gateway,
const gchar *metric)
{
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_routes_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_routes_row), page);
g_object_set_data (G_OBJECT (row), "prefix", widget);
gtk_entry_set_text (GTK_ENTRY (widget), prefix ? prefix : "");
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_routes_row), page);
g_object_set_data (G_OBJECT (row), "gateway", widget);
gtk_entry_set_text (GTK_ENTRY (widget), 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);
/* Translators: Please see https://en.wikipedia.org/wiki/Metrics_(networking) */
label = gtk_label_new (C_("network parameters", "Metric"));
gtk_widget_set_halign (label, GTK_ALIGN_END);
gtk_grid_attach (GTK_GRID (row_grid), label, 1, 4, 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_routes_row), page);
g_object_set_data (G_OBJECT (row), "metric", widget);
gtk_entry_set_text (GTK_ENTRY (widget), metric ? metric : "");
gtk_widget_set_margin_start (widget, 10);
gtk_widget_set_margin_end (widget, 10);
gtk_entry_set_width_chars (GTK_ENTRY (widget), 5);
gtk_widget_set_hexpand (widget, TRUE);
gtk_grid_attach (GTK_GRID (row_grid), widget, 2, 4, 1, 1);
gtk_container_add (GTK_CONTAINER (row_box), widget);
group = GTK_SIZE_GROUP (gtk_builder_get_object (CE_PAGE (page)->builder, "routes_metric_sizegroup"));
gtk_size_group_add_widget (group, widget);
delete_button = gtk_button_new ();
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 Route"));
gtk_button_set_image (GTK_BUTTON (delete_button), image);
gtk_widget_set_halign (delete_button, GTK_ALIGN_CENTER);
gtk_widget_set_valign (delete_button, GTK_ALIGN_CENTER);
gtk_grid_attach (GTK_GRID (row_grid), delete_button, 3, 1, 1, 4);
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, "routes_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->routes_list), row);
update_row_sensitivity (page, page->routes_list);
}
static void
ensure_empty_routes_row (CEPageIP6 *page)
{
GList *children, *l;
children = gtk_container_get_children (GTK_CONTAINER (page->routes_list));
l = children;
while (l && l->next)
l = l->next;
/* Add the last, stub row if needed*/
if (!l || validate_row (l->data))
add_route_row (page, "", NULL, "", NULL);
g_list_free (children);
}
static void
add_empty_route_row (CEPageIP6 *page)
{
@ -445,25 +472,20 @@ static void
add_routes_section (CEPageIP6 *page)
{
GtkWidget *widget;
GtkWidget *frame;
GtkWidget *list;
gint i;
widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "routes_section"));
frame = gtk_frame_new (NULL);
gtk_container_add (GTK_CONTAINER (widget), frame);
page->routes_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);
gtk_container_add (GTK_CONTAINER (widget), list);
page->auto_routes = GTK_SWITCH (gtk_builder_get_object (CE_PAGE (page)->builder, "auto_routes_switch"));
gtk_switch_set_active (page->auto_routes, !nm_setting_ip_config_get_ignore_auto_routes (page->setting));
g_signal_connect (page->auto_routes, "notify::active", G_CALLBACK (switch_toggled), page);
add_section_toolbar (page, widget, G_CALLBACK (add_empty_route_row));
for (i = 0; i < nm_setting_ip_config_get_num_routes (page->setting); i++) {
NMIPRoute *route;
char *prefix, *metric;
@ -778,6 +800,9 @@ ui_to_setting (CEPageIP6 *page)
route = nm_ip_route_new (AF_INET6, text_address, prefix, text_gateway, metric, NULL);
nm_setting_ip_config_add_route (page->setting, route);
nm_ip_route_unref (route);
if (!l || !l->next)
ensure_empty_routes_row (page);
}
g_list_free (children);

View file

@ -182,62 +182,47 @@
</object>
</child>
<child>
<object class="GtkBox" id="box3">
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">24</property>
<property name="margin_bottom">5</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="heading_routes">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Routes</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Automatic</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="auto_routes_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
<child internal-child="accessible">
<object class="AtkObject" id="auto_routes_switch-accessible">
<property name="accessible-name" translatable="yes">Automatic Routes</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">5</property>
</packing>
</child>
@ -247,7 +232,76 @@
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">horizontal</property>
<child>
<object class="GtkLabel" id="routes_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" id="routes_netmask_label">
<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" id="routes_gateway_label">
<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>
<child>
<object class="GtkLabel" id="routes_metric_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes" comments="Translators: Please see https://en.wikipedia.org/wiki/Metrics_(networking)">Metric</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="routes_stub_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
</object>
</child>
</object>
<packing>
@ -284,4 +338,16 @@
</object>
</child>
</object>
<object class="GtkSizeGroup" id="routes_metric_sizegroup">
<property name="mode">horizontal</property>
<widgets>
<widget name="routes_metric_label" />
</widgets>
</object>
<object class="GtkSizeGroup" id="routes_sizegroup">
<property name="mode">horizontal</property>
<widgets>
<widget name="routes_stub_box" />
</widgets>
</object>
</interface>

View file

@ -196,62 +196,47 @@
</object>
</child>
<child>
<object class="GtkBox" id="box3">
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">24</property>
<property name="margin_bottom">5</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="heading_routes">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Routes</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Automatic</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="auto_routes_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
<child internal-child="accessible">
<object class="AtkObject" id="auto_routes_switch-accessible">
<property name="accessible-name" translatable="yes">Automatic Routes</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">5</property>
</packing>
</child>
@ -261,7 +246,76 @@
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">horizontal</property>
<child>
<object class="GtkLabel" id="routes_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" id="routes_prefix_label">
<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" id="routes_gateway_label">
<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>
<child>
<object class="GtkLabel" id="routes_metric_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes" comments="Translators: Please see https://en.wikipedia.org/wiki/Metrics_(networking)">Metric</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="routes_stub_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
</object>
</child>
</object>
<packing>
@ -298,4 +352,16 @@
</object>
</child>
</object>
<object class="GtkSizeGroup" id="routes_metric_sizegroup">
<property name="mode">horizontal</property>
<widgets>
<widget name="routes_metric_label" />
</widgets>
</object>
<object class="GtkSizeGroup" id="routes_sizegroup">
<property name="mode">horizontal</property>
<widgets>
<widget name="routes_stub_box" />
</widgets>
</object>
</interface>