[network-manager-applet/jk/editor-error-bg-color-bgo660915: 1/3] editor: improve color-indication for bad addresses and routes (bgo #660915)



commit 0804505ba64e6a3de4663b4fb457bdbf80879018
Author: Jiří Klimeš <jklimes redhat com>
Date:   Tue Mar 3 14:27:05 2015 +0100

    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.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=660915

 src/connection-editor/ip4-routes-dialog.c |  102 ++++++++++++++++++++++++-----
 src/connection-editor/ip6-routes-dialog.c |   91 ++++++++++++++++++++++----
 src/connection-editor/page-ip4.c          |   49 ++++++++++++++
 src/connection-editor/page-ip6.c          |  101 ++++++++++++++++++++++-------
 4 files changed, 288 insertions(+), 55 deletions(-)
---
diff --git a/src/connection-editor/ip4-routes-dialog.c b/src/connection-editor/ip4-routes-dialog.c
index 9265446..7e3ce33 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,51 @@ 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) {
+               if (!value || !*value) {
+                       g_object_set (G_OBJECT (cell),
+                                     "cell-background-set", TRUE,
+                                     "cell-background", color,
+                                     NULL);
+               } else {
+                       char *markup;
+                       markup = g_strdup_printf ("<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);
+
+       g_free (value);
+}
+
 GtkWidget *
 ip4_routes_dialog_new (NMSettingIPConfig *s_ip4, gboolean automatic)
 {
@@ -726,6 +786,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 +805,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 +824,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 +843,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 +905,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 29108c7..5fde54c 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,51 @@ 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) {
+               if (!value || !*value) {
+                       g_object_set (G_OBJECT (cell),
+                                     "cell-background-set", TRUE,
+                                     "cell-background", color,
+                                     NULL);
+               } else {
+                       char *markup;
+                       markup = g_strdup_printf ("<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);
+
+       g_free (value);
+}
+
 GtkWidget *
 ip6_routes_dialog_new (NMSettingIPConfig *s_ip6, gboolean automatic)
 {
@@ -672,6 +727,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 +746,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 +765,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 +784,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 +846,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 +860,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 66e2085..6a8fe06 100644
--- a/src/connection-editor/page-ip4.c
+++ b/src/connection-editor/page-ip4.c
@@ -882,6 +882,49 @@ 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 = !value || !*value || !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) {
+               if (!value || !*value) {
+                       g_object_set (G_OBJECT (cell),
+                                     "cell-background-set", TRUE,
+                                     "cell-background", color,
+                                     NULL);
+               } else {
+                       char *markup;
+                       markup = g_strdup_printf ("<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);
+
+       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 +954,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 +973,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 +992,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);
 
diff --git a/src/connection-editor/page-ip6.c b/src/connection-editor/page-ip6.c
index 7c031a0..d08f229 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)
+               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,48 @@ 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 = !value || !*value || !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) {
+               if (!value || !*value) {
+                       g_object_set (G_OBJECT (cell),
+                                     "cell-background-set", TRUE,
+                                     "cell-background", color,
+                                     NULL);
+               } else {
+                       char *markup;
+                       markup = g_strdup_printf ("<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);
+
+       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 +957,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 +976,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 +995,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 +1120,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 +1139,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);


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