summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiří Klimeš <jklimes@redhat.com>2015-03-03 14:27:05 +0100
committerJiří Klimeš <jklimes@redhat.com>2015-03-05 09:16:58 +0100
commit975181df307cbd25d6b86d48138457e8a461ed5a (patch)
tree466518b431f7287044189dfa10144dfe66861ced
parentcddb7cb7b1cde92bd7f21a77dee61b0b3eb471eb (diff)
downloadnetwork-manager-applet-975181df307cbd25d6b86d48138457e8a461ed5a.tar.gz
editor: improve color-indication for bad addresses and routes (bgo #660915)
Incorrect values are already indicated while they are edited. However, this commit also makes the incorrect values visible afterwards by setting cell background to red. It uses the pango markup which has the advantage of being visible even if the row is selected. When there's no value in the cell, the cell-background property is used instead. https://bugzilla.gnome.org/show_bug.cgi?id=660915
-rw-r--r--src/connection-editor/ip4-routes-dialog.c90
-rw-r--r--src/connection-editor/ip6-routes-dialog.c79
-rw-r--r--src/connection-editor/page-ip4.c42
-rw-r--r--src/connection-editor/page-ip6.c89
-rw-r--r--src/utils/utils.c22
-rw-r--r--src/utils/utils.h3
6 files changed, 269 insertions, 56 deletions
diff --git a/src/connection-editor/ip4-routes-dialog.c b/src/connection-editor/ip4-routes-dialog.c
index 92654462..1d1f2716 100644
--- a/src/connection-editor/ip4-routes-dialog.c
+++ b/src/connection-editor/ip4-routes-dialog.c
@@ -54,15 +54,19 @@ get_one_int (GtkTreeModel *model,
int column,
guint32 max_value,
gboolean fail_if_missing,
- guint32 *out)
+ guint32 *out,
+ char **out_raw)
{
char *item = NULL;
gboolean success = FALSE;
long int tmp_int;
gtk_tree_model_get (model, iter, column, &item, -1);
+ if (out_raw)
+ *out_raw = item;
if (!item || !strlen (item)) {
- g_free (item);
+ if (!out_raw)
+ g_free (item);
return fail_if_missing ? FALSE : TRUE;
}
@@ -75,7 +79,8 @@ get_one_int (GtkTreeModel *model,
success = TRUE;
out:
- g_free (item);
+ if (!out_raw)
+ g_free (item);
return success;
}
@@ -84,7 +89,8 @@ get_one_prefix (GtkTreeModel *model,
GtkTreeIter *iter,
int column,
gboolean fail_if_missing,
- guint32 *out)
+ guint32 *out,
+ char **out_raw)
{
char *item = NULL;
struct in_addr tmp_addr = { 0 };
@@ -92,8 +98,11 @@ get_one_prefix (GtkTreeModel *model,
glong tmp_prefix;
gtk_tree_model_get (model, iter, column, &item, -1);
+ if (out_raw)
+ *out_raw = item;
if (!item || !strlen (item)) {
- g_free (item);
+ if (!out_raw)
+ g_free (item);
return fail_if_missing ? FALSE : TRUE;
}
@@ -116,7 +125,8 @@ get_one_prefix (GtkTreeModel *model,
}
out:
- g_free (item);
+ if (!out_raw)
+ g_free (item);
return success;
}
@@ -125,14 +135,18 @@ get_one_addr (GtkTreeModel *model,
GtkTreeIter *iter,
int column,
gboolean fail_if_missing,
- char **out)
+ char **out,
+ char **out_raw)
{
char *item = NULL;
struct in_addr tmp_addr = { 0 };
gtk_tree_model_get (model, iter, column, &item, -1);
+ if (out_raw)
+ *out_raw = item;
if (!item || !strlen (item)) {
- g_free (item);
+ if (!out_raw)
+ g_free (item);
return fail_if_missing ? FALSE : TRUE;
}
@@ -140,7 +154,8 @@ get_one_addr (GtkTreeModel *model,
return FALSE;
if (tmp_addr.s_addr == 0) {
- g_free (item);
+ if (!out_raw)
+ g_free (item);
return fail_if_missing ? FALSE : TRUE;
}
@@ -172,24 +187,24 @@ validate (GtkWidget *dialog)
guint32 prefix = 0, metric = 0;
/* Address */
- if (!get_one_addr (model, &tree_iter, COL_ADDRESS, TRUE, &addr))
+ if (!get_one_addr (model, &tree_iter, COL_ADDRESS, TRUE, &addr, NULL))
goto done;
g_free (addr);
/* Prefix */
- if (!get_one_prefix (model, &tree_iter, COL_PREFIX, TRUE, &prefix))
+ if (!get_one_prefix (model, &tree_iter, COL_PREFIX, TRUE, &prefix, NULL))
goto done;
/* Don't allow zero prefix for now - that's not supported in libnm-util */
if (prefix == 0)
goto done;
/* Next hop (optional) */
- if (!get_one_addr (model, &tree_iter, COL_NEXT_HOP, FALSE, &next_hop))
+ if (!get_one_addr (model, &tree_iter, COL_NEXT_HOP, FALSE, &next_hop, NULL))
goto done;
g_free (next_hop);
/* Metric (optional) */
- if (!get_one_int (model, &tree_iter, COL_METRIC, G_MAXUINT32, FALSE, &metric))
+ if (!get_one_int (model, &tree_iter, COL_METRIC, G_MAXUINT32, FALSE, &metric, NULL))
goto done;
iter_valid = gtk_tree_model_iter_next (model, &tree_iter);
@@ -632,6 +647,39 @@ tree_view_button_pressed_cb (GtkWidget *widget,
return FALSE;
}
+static void
+cell_error_data_func (GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ guint32 col = GPOINTER_TO_UINT (data);
+ char *value = NULL;
+ char *addr, *next_hop;
+ guint32 prefix, metric;
+ const char *color = "red";
+ gboolean invalid = FALSE;
+
+ if (col == COL_ADDRESS)
+ invalid = !get_one_addr (tree_model, iter, COL_ADDRESS, TRUE, &addr, &value);
+ else if (col == COL_PREFIX)
+ invalid = !get_one_prefix (tree_model, iter, COL_PREFIX, TRUE, &prefix, &value)
+ || prefix == 0;
+ else if (col == COL_NEXT_HOP)
+ invalid = !get_one_addr (tree_model, iter, COL_NEXT_HOP, FALSE, &next_hop, &value);
+ else if (col == COL_METRIC)
+ invalid = !get_one_int (tree_model, iter, COL_METRIC, G_MAXUINT32, FALSE, &metric, &value);
+ else
+ g_warn_if_reached ();
+
+ if (invalid)
+ utils_set_cell_background (cell, color, value);
+ else
+ utils_set_cell_background (cell, NULL, NULL);
+ g_free (value);
+}
+
GtkWidget *
ip4_routes_dialog_new (NMSettingIPConfig *s_ip4, gboolean automatic)
{
@@ -726,6 +774,8 @@ ip4_routes_dialog_new (NMSettingIPConfig *s_ip4, gboolean automatic)
column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), offset - 1);
gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
+ gtk_tree_view_column_set_cell_data_func (column, renderer, cell_error_data_func,
+ GUINT_TO_POINTER (COL_ADDRESS), NULL);
/* Prefix column */
renderer = gtk_cell_renderer_text_new ();
@@ -743,6 +793,8 @@ ip4_routes_dialog_new (NMSettingIPConfig *s_ip4, gboolean automatic)
column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), offset - 1);
gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
+ gtk_tree_view_column_set_cell_data_func (column, renderer, cell_error_data_func,
+ GUINT_TO_POINTER (COL_PREFIX), NULL);
/* Gateway column */
renderer = gtk_cell_renderer_text_new ();
@@ -760,6 +812,8 @@ ip4_routes_dialog_new (NMSettingIPConfig *s_ip4, gboolean automatic)
column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), offset - 1);
gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
+ gtk_tree_view_column_set_cell_data_func (column, renderer, cell_error_data_func,
+ GUINT_TO_POINTER (COL_NEXT_HOP), NULL);
/* Metric column */
renderer = gtk_cell_renderer_text_new ();
@@ -777,6 +831,8 @@ ip4_routes_dialog_new (NMSettingIPConfig *s_ip4, gboolean automatic)
column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), offset - 1);
gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
+ gtk_tree_view_column_set_cell_data_func (column, renderer, cell_error_data_func,
+ GUINT_TO_POINTER (COL_METRIC), NULL);
g_object_set_data_full (G_OBJECT (dialog), "renderers", renderers, (GDestroyNotify) g_slist_free);
@@ -837,27 +893,27 @@ ip4_routes_dialog_update_setting (GtkWidget *dialog, NMSettingIPConfig *s_ip4)
NMIPRoute *route;
/* Address */
- if (!get_one_addr (model, &tree_iter, COL_ADDRESS, TRUE, &addr)) {
+ if (!get_one_addr (model, &tree_iter, COL_ADDRESS, TRUE, &addr, NULL)) {
g_warning ("%s: IPv4 address missing or invalid!", __func__);
goto next;
}
/* Prefix */
- if (!get_one_prefix (model, &tree_iter, COL_PREFIX, TRUE, &prefix)) {
+ if (!get_one_prefix (model, &tree_iter, COL_PREFIX, TRUE, &prefix, NULL)) {
g_warning ("%s: IPv4 prefix/netmask missing or invalid!", __func__);
g_free (addr);
goto next;
}
/* Next hop (optional) */
- if (!get_one_addr (model, &tree_iter, COL_NEXT_HOP, FALSE, &next_hop)) {
+ if (!get_one_addr (model, &tree_iter, COL_NEXT_HOP, FALSE, &next_hop, NULL)) {
g_warning ("%s: IPv4 next hop invalid!", __func__);
g_free (addr);
goto next;
}
/* Metric (optional) */
- if (!get_one_int (model, &tree_iter, COL_METRIC, G_MAXUINT32, FALSE, &metric)) {
+ if (!get_one_int (model, &tree_iter, COL_METRIC, G_MAXUINT32, FALSE, &metric, NULL)) {
g_warning ("%s: IPv4 metric invalid!", __func__);
g_free (addr);
g_free (next_hop);
diff --git a/src/connection-editor/ip6-routes-dialog.c b/src/connection-editor/ip6-routes-dialog.c
index 29108c7c..1a3242ff 100644
--- a/src/connection-editor/ip6-routes-dialog.c
+++ b/src/connection-editor/ip6-routes-dialog.c
@@ -56,15 +56,19 @@ get_one_int (GtkTreeModel *model,
int column,
guint32 max_value,
gboolean fail_if_missing,
- guint *out)
+ guint *out,
+ char **out_raw)
{
char *item = NULL;
gboolean success = FALSE;
long int tmp_int;
gtk_tree_model_get (model, iter, column, &item, -1);
+ if (out_raw)
+ *out_raw = item;
if (!item || !strlen (item)) {
- g_free (item);
+ if (!out_raw)
+ g_free (item);
return fail_if_missing ? FALSE : TRUE;
}
@@ -77,7 +81,8 @@ get_one_int (GtkTreeModel *model,
success = TRUE;
out:
- g_free (item);
+ if (!out_raw)
+ g_free (item);
return success;
}
@@ -86,14 +91,18 @@ get_one_addr (GtkTreeModel *model,
GtkTreeIter *iter,
int column,
gboolean fail_if_missing,
- char **out)
+ char **out,
+ char **out_raw)
{
char *item = NULL;
struct in6_addr tmp_addr;
gtk_tree_model_get (model, iter, column, &item, -1);
+ if (out_raw)
+ *out_raw = item;
if (!item || !strlen (item)) {
- g_free (item);
+ if (!out_raw)
+ g_free (item);
return fail_if_missing ? FALSE : TRUE;
}
@@ -101,7 +110,8 @@ get_one_addr (GtkTreeModel *model,
return FALSE;
if (IN6_IS_ADDR_UNSPECIFIED (&tmp_addr)) {
- g_free (item);
+ if (!out_raw)
+ g_free (item);
return fail_if_missing ? FALSE : TRUE;
}
@@ -133,22 +143,22 @@ validate (GtkWidget *dialog)
guint prefix = 0, metric = 0;
/* Address */
- if (!get_one_addr (model, &tree_iter, COL_ADDRESS, TRUE, &dest))
+ if (!get_one_addr (model, &tree_iter, COL_ADDRESS, TRUE, &dest, NULL))
goto done;
g_free (dest);
/* Prefix */
- if ( !get_one_int (model, &tree_iter, COL_PREFIX, 128, TRUE, &prefix)
+ if ( !get_one_int (model, &tree_iter, COL_PREFIX, 128, TRUE, &prefix, NULL)
|| prefix == 0)
goto done;
/* Next hop (optional) */
- if (!get_one_addr (model, &tree_iter, COL_NEXT_HOP, FALSE, &next_hop))
+ if (!get_one_addr (model, &tree_iter, COL_NEXT_HOP, FALSE, &next_hop, NULL))
goto done;
g_free (next_hop);
/* Metric (optional) */
- if (!get_one_int (model, &tree_iter, COL_METRIC, G_MAXUINT32, FALSE, &metric))
+ if (!get_one_int (model, &tree_iter, COL_METRIC, G_MAXUINT32, FALSE, &metric, NULL))
goto done;
iter_valid = gtk_tree_model_iter_next (model, &tree_iter);
@@ -581,6 +591,39 @@ tree_view_button_pressed_cb (GtkWidget *widget,
return FALSE;
}
+static void
+cell_error_data_func (GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ guint32 col = GPOINTER_TO_UINT (data);
+ char *value = NULL;
+ char *addr, *next_hop;
+ guint32 prefix, metric;
+ const char *color = "red";
+ gboolean invalid = FALSE;
+
+ if (col == COL_ADDRESS)
+ invalid = !get_one_addr (tree_model, iter, COL_ADDRESS, TRUE, &addr, &value);
+ else if (col == COL_PREFIX)
+ invalid = !get_one_int (tree_model, iter, COL_PREFIX, 128, TRUE, &prefix, &value)
+ || prefix == 0;
+ else if (col == COL_NEXT_HOP)
+ invalid = !get_one_addr (tree_model, iter, COL_NEXT_HOP, FALSE, &next_hop, &value);
+ else if (col == COL_METRIC)
+ invalid = !get_one_int (tree_model, iter, COL_METRIC, G_MAXUINT32, FALSE, &metric, &value);
+ else
+ g_warn_if_reached ();
+
+ if (invalid)
+ utils_set_cell_background (cell, color, value);
+ else
+ utils_set_cell_background (cell, NULL, NULL);
+ g_free (value);
+}
+
GtkWidget *
ip6_routes_dialog_new (NMSettingIPConfig *s_ip6, gboolean automatic)
{
@@ -672,6 +715,8 @@ ip6_routes_dialog_new (NMSettingIPConfig *s_ip6, gboolean automatic)
column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), offset - 1);
gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
+ gtk_tree_view_column_set_cell_data_func (column, renderer, cell_error_data_func,
+ GUINT_TO_POINTER (COL_ADDRESS), NULL);
/* Prefix column */
renderer = gtk_cell_renderer_text_new ();
@@ -689,6 +734,8 @@ ip6_routes_dialog_new (NMSettingIPConfig *s_ip6, gboolean automatic)
column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), offset - 1);
gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
+ gtk_tree_view_column_set_cell_data_func (column, renderer, cell_error_data_func,
+ GUINT_TO_POINTER (COL_PREFIX), NULL);
/* Gateway column */
renderer = gtk_cell_renderer_text_new ();
@@ -706,6 +753,8 @@ ip6_routes_dialog_new (NMSettingIPConfig *s_ip6, gboolean automatic)
column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), offset - 1);
gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
+ gtk_tree_view_column_set_cell_data_func (column, renderer, cell_error_data_func,
+ GUINT_TO_POINTER (COL_NEXT_HOP), NULL);
/* Metric column */
renderer = gtk_cell_renderer_text_new ();
@@ -723,6 +772,8 @@ ip6_routes_dialog_new (NMSettingIPConfig *s_ip6, gboolean automatic)
column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), offset - 1);
gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
+ gtk_tree_view_column_set_cell_data_func (column, renderer, cell_error_data_func,
+ GUINT_TO_POINTER (COL_METRIC), NULL);
g_object_set_data_full (G_OBJECT (dialog), "renderers", renderers, (GDestroyNotify) g_slist_free);
@@ -783,13 +834,13 @@ ip6_routes_dialog_update_setting (GtkWidget *dialog, NMSettingIPConfig *s_ip6)
NMIPRoute *route;
/* Address */
- if (!get_one_addr (model, &tree_iter, COL_ADDRESS, TRUE, &dest)) {
+ if (!get_one_addr (model, &tree_iter, COL_ADDRESS, TRUE, &dest, NULL)) {
g_warning ("%s: IPv6 address missing or invalid!", __func__);
goto next;
}
/* Prefix */
- if ( !get_one_int (model, &tree_iter, COL_PREFIX, 128, TRUE, &prefix)
+ if ( !get_one_int (model, &tree_iter, COL_PREFIX, 128, TRUE, &prefix, NULL)
|| prefix == 0) {
g_warning ("%s: IPv6 prefix missing or invalid!", __func__);
g_free (dest);
@@ -797,14 +848,14 @@ ip6_routes_dialog_update_setting (GtkWidget *dialog, NMSettingIPConfig *s_ip6)
}
/* Next hop (optional) */
- if (!get_one_addr (model, &tree_iter, COL_NEXT_HOP, FALSE, &next_hop)) {
+ if (!get_one_addr (model, &tree_iter, COL_NEXT_HOP, FALSE, &next_hop, NULL)) {
g_warning ("%s: IPv6 next hop invalid!", __func__);
g_free (dest);
goto next;
}
/* Metric (optional) */
- if (!get_one_int (model, &tree_iter, COL_METRIC, G_MAXUINT32, FALSE, &metric)) {
+ if (!get_one_int (model, &tree_iter, COL_METRIC, G_MAXUINT32, FALSE, &metric, NULL)) {
g_warning ("%s: IPv6 metric invalid!", __func__);
g_free (dest);
g_free (next_hop);
diff --git a/src/connection-editor/page-ip4.c b/src/connection-editor/page-ip4.c
index 66e20859..07d4eac2 100644
--- a/src/connection-editor/page-ip4.c
+++ b/src/connection-editor/page-ip4.c
@@ -662,6 +662,9 @@ parse_netmask (const char *str, guint32 *prefix)
struct in_addr tmp_addr;
glong tmp_prefix;
+ if (!str || !*str)
+ return FALSE;
+
errno = 0;
/* Is it a prefix? */
@@ -882,6 +885,37 @@ tree_view_button_pressed_cb (GtkWidget *widget,
}
static void
+cell_error_data_func (GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ guint32 col = GPOINTER_TO_UINT (data);
+ char *value = NULL;
+ const char *color = "red";
+ guint32 prefix;
+ gboolean invalid = FALSE;
+
+ gtk_tree_model_get (tree_model, iter, col, &value, -1);
+
+ if (col == COL_ADDRESS)
+ invalid = !value || !*value || !nm_utils_ipaddr_valid (AF_INET, value);
+ else if (col == COL_PREFIX)
+ invalid = !parse_netmask (value, &prefix);
+ else if (col == COL_GATEWAY)
+ invalid = value && *value && !nm_utils_ipaddr_valid (AF_INET, value);
+ else
+ g_warn_if_reached ();
+
+ if (invalid)
+ utils_set_cell_background (cell, color, value);
+ else
+ utils_set_cell_background (cell, NULL, NULL);
+ g_free (value);
+}
+
+static void
finish_setup (CEPageIP4 *self, gpointer unused, GError *error, gpointer user_data)
{
CEPageIP4Private *priv = CE_PAGE_IP4_GET_PRIVATE (self);
@@ -911,6 +945,8 @@ finish_setup (CEPageIP4 *self, gpointer unused, GError *error, gpointer user_dat
column = gtk_tree_view_get_column (GTK_TREE_VIEW (priv->addr_list), offset - 1);
gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
+ gtk_tree_view_column_set_cell_data_func (column, renderer, cell_error_data_func,
+ GUINT_TO_POINTER (COL_ADDRESS), NULL);
/* Prefix/netmask column */
renderer = gtk_cell_renderer_text_new ();
@@ -928,6 +964,8 @@ finish_setup (CEPageIP4 *self, gpointer unused, GError *error, gpointer user_dat
column = gtk_tree_view_get_column (GTK_TREE_VIEW (priv->addr_list), offset - 1);
gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
+ gtk_tree_view_column_set_cell_data_func (column, renderer, cell_error_data_func,
+ GUINT_TO_POINTER (COL_PREFIX), NULL);
/* Gateway column */
renderer = gtk_cell_renderer_text_new ();
@@ -945,6 +983,8 @@ finish_setup (CEPageIP4 *self, gpointer unused, GError *error, gpointer user_dat
column = gtk_tree_view_get_column (GTK_TREE_VIEW (priv->addr_list), offset - 1);
gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
+ gtk_tree_view_column_set_cell_data_func (column, renderer, cell_error_data_func,
+ GUINT_TO_POINTER (COL_GATEWAY), NULL);
g_signal_connect (priv->addr_list, "button-press-event", G_CALLBACK (tree_view_button_pressed_cb), self);
@@ -1091,7 +1131,7 @@ ui_to_setting (CEPageIP4 *self)
goto out;
}
- if (!netmask || !parse_netmask (netmask, &prefix)) {
+ if (!parse_netmask (netmask, &prefix)) {
g_warning ("%s: IPv4 prefix '%s' missing or invalid!",
__func__, netmask ? netmask : "<none>");
g_free (addr);
diff --git a/src/connection-editor/page-ip6.c b/src/connection-editor/page-ip6.c
index 7c031a04..4e717120 100644
--- a/src/connection-editor/page-ip6.c
+++ b/src/connection-editor/page-ip6.c
@@ -455,6 +455,25 @@ populate_ui (CEPageIP6 *self)
!nm_setting_ip_config_get_may_fail (setting));
}
+static gboolean
+is_prefix_valid (const char *prefix_str, guint32 *out_prefix)
+{
+ guint32 prefix;
+ char *end;
+
+ if (!prefix_str || !*prefix_str)
+ return FALSE;
+
+ prefix = strtoul (prefix_str, &end, 10);
+ if (!end || *end || prefix == 0 || prefix > 128)
+ return FALSE;
+ else {
+ if (out_prefix)
+ *out_prefix = prefix;
+ return TRUE;
+ }
+}
+
static void
addr_add_clicked (GtkButton *button, gpointer user_data)
{
@@ -676,18 +695,11 @@ cell_changed_cb (GtkEditable *editable,
cell_text = gtk_editable_get_chars (editable, 0, -1);
- /* The Prefix column is 0..128 */
+ /* The Prefix column is 1..128 */
column = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (user_data), "column"));
- if (column == COL_PREFIX) {
- guint32 prefix;
- char *end;
-
- prefix = strtoul (cell_text, &end, 10);
- if (!end || *end || prefix == 0 || prefix > 128)
- value_valid = FALSE;
- else
- value_valid = TRUE;
- } else {
+ if (column == COL_PREFIX)
+ value_valid = is_prefix_valid (cell_text, NULL);
+ else {
struct in6_addr tmp_addr;
if (inet_pton (AF_INET6, cell_text, &tmp_addr))
@@ -874,6 +886,36 @@ tree_view_button_pressed_cb (GtkWidget *widget,
}
static void
+cell_error_data_func (GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ guint32 col = GPOINTER_TO_UINT (data);
+ char *value = NULL;
+ const char *color = "red";
+ gboolean invalid = FALSE;
+
+ gtk_tree_model_get (tree_model, iter, col, &value, -1);
+
+ if (col == COL_ADDRESS)
+ invalid = !value || !*value || !nm_utils_ipaddr_valid (AF_INET6, value);
+ else if (col == COL_PREFIX)
+ invalid = !is_prefix_valid (value, NULL);
+ else if (col == COL_GATEWAY)
+ invalid = value && *value && !nm_utils_ipaddr_valid (AF_INET6, value);
+ else
+ g_warn_if_reached ();
+
+ if (invalid)
+ utils_set_cell_background (cell, color, value);
+ else
+ utils_set_cell_background (cell, NULL, NULL);
+ g_free (value);
+}
+
+static void
finish_setup (CEPageIP6 *self, gpointer unused, GError *error, gpointer user_data)
{
CEPageIP6Private *priv = CE_PAGE_IP6_GET_PRIVATE (self);
@@ -903,6 +945,8 @@ finish_setup (CEPageIP6 *self, gpointer unused, GError *error, gpointer user_dat
column = gtk_tree_view_get_column (GTK_TREE_VIEW (priv->addr_list), offset - 1);
gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
+ gtk_tree_view_column_set_cell_data_func (column, renderer, cell_error_data_func,
+ GUINT_TO_POINTER (COL_ADDRESS), NULL);
/* Prefix column */
renderer = gtk_cell_renderer_text_new ();
@@ -920,6 +964,8 @@ finish_setup (CEPageIP6 *self, gpointer unused, GError *error, gpointer user_dat
column = gtk_tree_view_get_column (GTK_TREE_VIEW (priv->addr_list), offset - 1);
gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
+ gtk_tree_view_column_set_cell_data_func (column, renderer, cell_error_data_func,
+ GUINT_TO_POINTER (COL_PREFIX), NULL);
/* Gateway column */
renderer = gtk_cell_renderer_text_new ();
@@ -937,6 +983,8 @@ finish_setup (CEPageIP6 *self, gpointer unused, GError *error, gpointer user_dat
column = gtk_tree_view_get_column (GTK_TREE_VIEW (priv->addr_list), offset - 1);
gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
+ gtk_tree_view_column_set_cell_data_func (column, renderer, cell_error_data_func,
+ GUINT_TO_POINTER (COL_GATEWAY), NULL);
g_signal_connect (priv->addr_list, "button-press-event", G_CALLBACK (tree_view_button_pressed_cb), self);
@@ -1060,7 +1108,7 @@ ui_to_setting (CEPageIP6 *self)
model = gtk_tree_view_get_model (priv->addr_list);
iter_valid = gtk_tree_model_get_iter_first (model, &tree_iter);
while (iter_valid) {
- char *addr_str = NULL, *prefix_str = NULL, *addr_gw_str = NULL, *end;
+ char *addr_str = NULL, *prefix_str = NULL, *addr_gw_str = NULL;
NMIPAddress *addr;
guint32 prefix;
@@ -1079,18 +1127,11 @@ ui_to_setting (CEPageIP6 *self)
goto out;
}
- if (!prefix_str) {
- g_warning ("%s: IPv6 prefix missing!", __func__);
- g_free (addr_str);
- g_free (prefix_str);
- g_free (addr_gw_str);
- goto out;
- }
-
- prefix = strtoul (prefix_str, &end, 10);
- if (!end || *end || prefix == 0 || prefix > 128) {
- g_warning ("%s: IPv6 prefix '%s' invalid!",
- __func__, prefix_str);
+ if (!is_prefix_valid (prefix_str, &prefix)) {
+ if (!prefix_str)
+ g_warning ("%s: IPv6 prefix missing!", __func__);
+ else
+ g_warning ("%s: IPv6 prefix '%s' invalid!", __func__, prefix_str);
g_free (addr_str);
g_free (prefix_str);
g_free (addr_gw_str);
diff --git a/src/utils/utils.c b/src/utils/utils.c
index c9301fe9..64ceee81 100644
--- a/src/utils/utils.c
+++ b/src/utils/utils.c
@@ -517,3 +517,25 @@ utils_override_bg_color (GtkWidget *widget, GdkRGBA *rgba)
gtk_css_provider_load_from_data (provider, "", -1, NULL);
}
+void
+utils_set_cell_background (GtkCellRenderer *cell,
+ const char *color,
+ const char *value)
+{
+ if (color) {
+ if (!value || !*value) {
+ g_object_set (G_OBJECT (cell),
+ "cell-background-set", TRUE,
+ "cell-background", color,
+ NULL);
+ } else {
+ char *markup;
+ markup = g_markup_printf_escaped ("<span background='%s'>%s</span>",
+ color, value);
+ g_object_set (G_OBJECT (cell), "markup", markup, NULL);
+ g_free (markup);
+ g_object_set (G_OBJECT (cell), "cell-background-set", FALSE, NULL);
+ }
+ } else
+ g_object_set (G_OBJECT (cell), "cell-background-set", FALSE, NULL);
+}
diff --git a/src/utils/utils.h b/src/utils/utils.h
index 3e3d31bb..6d4147f3 100644
--- a/src/utils/utils.h
+++ b/src/utils/utils.h
@@ -101,6 +101,9 @@ void utils_update_password_storage (NMSetting *setting,
const char *password_flags_name);
void utils_override_bg_color (GtkWidget *widget, GdkRGBA *rgba);
+void utils_set_cell_background (GtkCellRenderer *cell,
+ const char *color,
+ const char *value);
#endif /* UTILS_H */