No issues found
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2 of the License, or (at your option) version 3.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with the program; if not, see <http://www.gnu.org/licenses/>
14 *
15 *
16 * Authors:
17 * Mike Kestner <mkestner@ximian.com>
18 *
19 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
20 *
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include "e-util/e-util.h"
28
29 #include "e-select-names-editable.h"
30 #include "e-select-names-renderer.h"
31
32 #define E_SELECT_NAMES_RENDERER_GET_PRIVATE(obj) \
33 (G_TYPE_INSTANCE_GET_PRIVATE \
34 ((obj), E_TYPE_SELECT_NAMES_RENDERER, ESelectNamesRendererPrivate))
35
36 struct _ESelectNamesRendererPrivate {
37 ESelectNamesEditable *editable;
38 gchar *path;
39
40 gchar *name;
41 gchar *email;
42 };
43
44 enum {
45 PROP_0,
46 PROP_NAME,
47 PROP_EMAIL
48 };
49
50 enum {
51 CELL_EDITED,
52 LAST_SIGNAL
53 };
54
55 static gint signals[LAST_SIGNAL];
56
57 G_DEFINE_TYPE (
58 ESelectNamesRenderer,
59 e_select_names_renderer,
60 GTK_TYPE_CELL_RENDERER_TEXT)
61
62 static void
63 e_select_names_renderer_editing_done (GtkCellEditable *editable,
64 ESelectNamesRenderer *cell)
65 {
66 GList *addresses = NULL, *names = NULL, *a, *n;
67 gboolean editing_canceled;
68
69 /* We don't need to listen for the focus out event any more */
70 g_signal_handlers_disconnect_matched (editable, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, cell);
71
72 g_object_get (editable, "editing-canceled", &editing_canceled, NULL);
73 if (editing_canceled) {
74 gtk_cell_renderer_stop_editing (GTK_CELL_RENDERER (cell), TRUE);
75 goto cleanup;
76 }
77
78 addresses = e_select_names_editable_get_emails (E_SELECT_NAMES_EDITABLE (editable));
79 names = e_select_names_editable_get_names (E_SELECT_NAMES_EDITABLE (editable));
80
81 /* remove empty addresses */
82 for (a = addresses, n = names; a && n;) {
83 gchar *addr = a->data, *nm = n->data;
84
85 if ((!addr || !*addr) && (!nm || !*nm)) {
86 g_free (addr);
87 g_free (nm);
88 addresses = g_list_remove_link (addresses, a);
89 names = g_list_remove_link (names, n);
90 a = addresses;
91 n = names;
92 } else {
93 a = a->next;
94 n = n->next;
95 }
96 }
97
98 g_signal_emit (cell, signals[CELL_EDITED], 0, cell->priv->path, addresses, names);
99
100 g_list_foreach (addresses, (GFunc) g_free, NULL);
101 g_list_foreach (names, (GFunc) g_free, NULL);
102 g_list_free (addresses);
103 g_list_free (names);
104
105 cleanup:
106 g_free (cell->priv->path);
107 cell->priv->path = NULL;
108 cell->priv->editable = NULL;
109 }
110
111 static GtkCellEditable *
112 e_select_names_renderer_start_editing (GtkCellRenderer *cell,
113 GdkEvent *event,
114 GtkWidget *widget,
115 const gchar *path,
116 const GdkRectangle *bg_area,
117 const GdkRectangle *cell_area,
118 GtkCellRendererState flags)
119 {
120 ESelectNamesRenderer *sn_cell = E_SELECT_NAMES_RENDERER (cell);
121 GtkCellRendererText *text_cell = GTK_CELL_RENDERER_TEXT (cell);
122 ESelectNamesEditable *editable;
123 gboolean is_editable;
124 gfloat xalign;
125
126 g_object_get (
127 text_cell,
128 "editable", &is_editable,
129 "xalign", &xalign, NULL);
130
131 if (!is_editable)
132 return NULL;
133
134 editable = E_SELECT_NAMES_EDITABLE (e_select_names_editable_new ());
135 gtk_entry_set_has_frame (GTK_ENTRY (editable), FALSE);
136 gtk_entry_set_alignment (GTK_ENTRY (editable), xalign);
137 if (sn_cell->priv->email && *sn_cell->priv->email)
138 e_select_names_editable_set_address (editable, sn_cell->priv->name, sn_cell->priv->email);
139 gtk_widget_show (GTK_WIDGET (editable));
140
141 g_signal_connect (
142 editable, "editing_done",
143 G_CALLBACK (e_select_names_renderer_editing_done), sn_cell);
144
145 /* Removed focus-out-event. focus out event already listen by base class.
146 * We don't need to listen for the focus out event any more */
147
148 sn_cell->priv->editable = g_object_ref (editable);
149 sn_cell->priv->path = g_strdup (path);
150
151 return GTK_CELL_EDITABLE (editable);
152 }
153
154 static void
155 e_select_names_renderer_get_property (GObject *object,
156 guint property_id,
157 GValue *value,
158 GParamSpec *pspec)
159 {
160 ESelectNamesRenderer *esnr = E_SELECT_NAMES_RENDERER (object);
161
162 switch (property_id) {
163 case PROP_NAME:
164 g_value_set_string (value, esnr->priv->name);
165 break;
166 case PROP_EMAIL:
167 g_value_set_string (value, esnr->priv->email);
168 break;
169 default:
170 break;
171 }
172 }
173
174 static void
175 e_select_names_renderer_set_property (GObject *object,
176 guint property_id,
177 const GValue *value,
178 GParamSpec *pspec)
179 {
180 ESelectNamesRenderer *esnr = E_SELECT_NAMES_RENDERER (object);
181
182 switch (property_id) {
183 case PROP_NAME:
184 g_free (esnr->priv->name);
185 esnr->priv->name = g_strdup (g_value_get_string (value));
186 break;
187 case PROP_EMAIL:
188 g_free (esnr->priv->email);
189 esnr->priv->email = g_strdup (g_value_get_string (value));
190 break;
191 default:
192 break;
193 }
194 }
195
196 static void
197 e_select_names_renderer_finalize (GObject *object)
198 {
199 ESelectNamesRendererPrivate *priv;
200
201 priv = E_SELECT_NAMES_RENDERER_GET_PRIVATE (object);
202
203 if (priv->editable != NULL) {
204 g_object_unref (priv->editable);
205 priv->editable = NULL;
206 }
207
208 g_free (priv->path);
209 g_free (priv->name);
210 g_free (priv->email);
211
212 /* Chain up to parent's finalize() method. */
213 G_OBJECT_CLASS (e_select_names_renderer_parent_class)->finalize (object);
214 }
215
216 static void
217 e_select_names_renderer_class_init (ESelectNamesRendererClass *class)
218 {
219 GObjectClass *object_class;
220 GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
221
222 g_type_class_add_private (class, sizeof (ESelectNamesRendererPrivate));
223
224 object_class = G_OBJECT_CLASS (class);
225 object_class->get_property = e_select_names_renderer_get_property;
226 object_class->set_property = e_select_names_renderer_set_property;
227 object_class->finalize = e_select_names_renderer_finalize;
228
229 cell_class->start_editing = e_select_names_renderer_start_editing;
230
231 g_object_class_install_property (
232 object_class,
233 PROP_NAME,
234 g_param_spec_string (
235 "name",
236 "Name",
237 "Email name.",
238 NULL,
239 G_PARAM_READWRITE));
240
241 g_object_class_install_property (
242 object_class,
243 PROP_EMAIL,
244 g_param_spec_string (
245 "email",
246 "Email",
247 "Email address.",
248 NULL,
249 G_PARAM_READWRITE));
250
251 signals[CELL_EDITED] = g_signal_new (
252 "cell_edited",
253 G_OBJECT_CLASS_TYPE (object_class),
254 G_SIGNAL_RUN_LAST,
255 G_STRUCT_OFFSET (ESelectNamesRendererClass, cell_edited),
256 NULL, NULL,
257 e_marshal_VOID__STRING_POINTER_POINTER,
258 G_TYPE_NONE, 3,
259 G_TYPE_STRING,
260 G_TYPE_POINTER,
261 G_TYPE_POINTER);
262 }
263
264 static void
265 e_select_names_renderer_init (ESelectNamesRenderer *cell)
266 {
267 cell->priv = E_SELECT_NAMES_RENDERER_GET_PRIVATE (cell);
268 }
269
270 GtkCellRenderer *
271 e_select_names_renderer_new (void)
272 {
273 return g_object_new (E_TYPE_SELECT_NAMES_RENDERER, NULL);
274 }