No issues found
1 /*
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2 of the License, or (at your option) version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with the program; if not, see <http://www.gnu.org/licenses/>
15 *
16 *
17 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
18 *
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include "e-msg-composer.h"
26 #include "e-composer-name-header.h"
27
28 #include <glib/gi18n.h>
29
30 /* XXX Temporary kludge */
31 #include "addressbook/gui/contact-editor/e-contact-editor.h"
32 #include "addressbook/gui/contact-list-editor/e-contact-list-editor.h"
33
34 #define E_COMPOSER_NAME_HEADER_GET_PRIVATE(obj) \
35 (G_TYPE_INSTANCE_GET_PRIVATE \
36 ((obj), E_TYPE_COMPOSER_NAME_HEADER, EComposerNameHeaderPrivate))
37
38 /* Convenience macro */
39 #define E_COMPOSER_NAME_HEADER_GET_ENTRY(header) \
40 (E_NAME_SELECTOR_ENTRY (E_COMPOSER_HEADER (header)->input_widget))
41
42 enum {
43 PROP_0,
44 PROP_NAME_SELECTOR
45 };
46
47 struct _EComposerNameHeaderPrivate {
48 ENameSelector *name_selector;
49 guint destination_index;
50 };
51
52 G_DEFINE_TYPE (
53 EComposerNameHeader,
54 e_composer_name_header,
55 E_TYPE_COMPOSER_HEADER)
56
57 static gpointer
58 contact_editor_fudge_new (EBookClient *book_client,
59 EContact *contact,
60 gboolean is_new,
61 gboolean editable)
62 {
63 EShell *shell = e_shell_get_default ();
64
65 /* XXX Putting this function signature in libedataserverui
66 * was a terrible idea. Now we're stuck with it. */
67
68 return e_contact_editor_new (
69 shell, book_client, contact, is_new, editable);
70 }
71
72 static gpointer
73 contact_list_editor_fudge_new (EBookClient *book_client,
74 EContact *contact,
75 gboolean is_new,
76 gboolean editable)
77 {
78 EShell *shell = e_shell_get_default ();
79
80 /* XXX Putting this function signature in libedataserverui
81 * was a terrible idea. Now we're stuck with it. */
82
83 return e_contact_list_editor_new (
84 shell, book_client, contact, is_new, editable);
85 }
86
87 static void
88 composer_name_header_entry_changed_cb (ENameSelectorEntry *entry,
89 EComposerNameHeader *header)
90 {
91 g_signal_emit_by_name (header, "changed");
92 }
93
94 static gboolean
95 composer_name_header_entry_query_tooltip_cb (GtkEntry *entry,
96 gint x,
97 gint y,
98 gboolean keyboard_mode,
99 GtkTooltip *tooltip)
100 {
101 const gchar *text;
102
103 text = gtk_entry_get_text (entry);
104
105 if (keyboard_mode || text == NULL || *text == '\0')
106 return FALSE;
107
108 gtk_tooltip_set_text (tooltip, text);
109
110 return TRUE;
111 }
112
113 static void
114 composer_name_header_set_property (GObject *object,
115 guint property_id,
116 const GValue *value,
117 GParamSpec *pspec)
118 {
119 EComposerNameHeaderPrivate *priv;
120
121 priv = E_COMPOSER_NAME_HEADER_GET_PRIVATE (object);
122
123 switch (property_id) {
124 case PROP_NAME_SELECTOR: /* construct only */
125 g_assert (priv->name_selector == NULL);
126 priv->name_selector = g_value_dup_object (value);
127 return;
128 }
129
130 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
131 }
132
133 static void
134 composer_name_header_get_property (GObject *object,
135 guint property_id,
136 GValue *value,
137 GParamSpec *pspec)
138 {
139 switch (property_id) {
140 case PROP_NAME_SELECTOR: /* construct only */
141 g_value_set_object (
142 value,
143 e_composer_name_header_get_name_selector (
144 E_COMPOSER_NAME_HEADER (object)));
145 return;
146 }
147
148 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
149 }
150
151 static void
152 composer_name_header_dispose (GObject *object)
153 {
154 EComposerNameHeaderPrivate *priv;
155
156 priv = E_COMPOSER_NAME_HEADER_GET_PRIVATE (object);
157
158 if (priv->name_selector != NULL) {
159 g_object_unref (priv->name_selector);
160 priv->name_selector = NULL;
161 }
162
163 /* Chain up to parent's dispose() method. */
164 G_OBJECT_CLASS (e_composer_name_header_parent_class)->dispose (object);
165 }
166
167 static void
168 composer_name_header_constructed (GObject *object)
169 {
170 EComposerNameHeaderPrivate *priv;
171 ENameSelectorModel *model;
172 ENameSelectorEntry *entry;
173 GList *sections;
174 const gchar *label;
175
176 /* Input widget must be set before chaining up. */
177
178 priv = E_COMPOSER_NAME_HEADER_GET_PRIVATE (object);
179 g_assert (E_IS_NAME_SELECTOR (priv->name_selector));
180
181 model = e_name_selector_peek_model (priv->name_selector);
182 label = e_composer_header_get_label (E_COMPOSER_HEADER (object));
183 g_assert (label != NULL);
184
185 sections = e_name_selector_model_list_sections (model);
186 priv->destination_index = g_list_length (sections);
187 e_name_selector_model_add_section (model, label, label, NULL);
188 g_list_foreach (sections, (GFunc) g_free, NULL);
189 g_list_free (sections);
190
191 entry = E_NAME_SELECTOR_ENTRY (
192 e_name_selector_peek_section_list (
193 priv->name_selector, label));
194
195 e_name_selector_entry_set_contact_editor_func (
196 entry, contact_editor_fudge_new);
197 e_name_selector_entry_set_contact_list_editor_func (
198 entry, contact_list_editor_fudge_new);
199
200 g_signal_connect (
201 entry, "changed",
202 G_CALLBACK (composer_name_header_entry_changed_cb), object);
203 g_signal_connect (
204 entry, "query-tooltip",
205 G_CALLBACK (composer_name_header_entry_query_tooltip_cb),
206 NULL);
207 E_COMPOSER_HEADER (object)->input_widget = g_object_ref_sink (entry);
208
209 /* Chain up to parent's constructed() method. */
210 G_OBJECT_CLASS (e_composer_name_header_parent_class)->
211 constructed (object);
212
213 e_composer_header_set_title_tooltip (
214 E_COMPOSER_HEADER (object),
215 _("Click here for the address book"));
216 }
217
218 static void
219 composer_name_header_clicked (EComposerHeader *header)
220 {
221 EComposerNameHeaderPrivate *priv;
222 ENameSelectorDialog *dialog;
223
224 priv = E_COMPOSER_NAME_HEADER_GET_PRIVATE (header);
225
226 dialog = e_name_selector_peek_dialog (priv->name_selector);
227 e_name_selector_dialog_set_destination_index (
228 dialog, priv->destination_index);
229 e_name_selector_show_dialog (
230 priv->name_selector, header->title_widget);
231 gtk_dialog_run (GTK_DIALOG (dialog));
232 gtk_widget_hide (GTK_WIDGET (dialog));
233 }
234
235 static void
236 e_composer_name_header_class_init (EComposerNameHeaderClass *class)
237 {
238 GObjectClass *object_class;
239 EComposerHeaderClass *header_class;
240
241 g_type_class_add_private (class, sizeof (EComposerNameHeaderPrivate));
242
243 object_class = G_OBJECT_CLASS (class);
244 object_class->set_property = composer_name_header_set_property;
245 object_class->get_property = composer_name_header_get_property;
246 object_class->dispose = composer_name_header_dispose;
247 object_class->constructed = composer_name_header_constructed;
248
249 header_class = E_COMPOSER_HEADER_CLASS (class);
250 header_class->clicked = composer_name_header_clicked;
251
252 g_object_class_install_property (
253 object_class,
254 PROP_NAME_SELECTOR,
255 g_param_spec_object (
256 "name-selector",
257 NULL,
258 NULL,
259 E_TYPE_NAME_SELECTOR,
260 G_PARAM_READWRITE |
261 G_PARAM_CONSTRUCT_ONLY));
262 }
263
264 static void
265 e_composer_name_header_init (EComposerNameHeader *header)
266 {
267 header->priv = E_COMPOSER_NAME_HEADER_GET_PRIVATE (header);
268 }
269
270 EComposerHeader *
271 e_composer_name_header_new (ESourceRegistry *registry,
272 const gchar *label,
273 ENameSelector *name_selector)
274 {
275 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
276 g_return_val_if_fail (E_IS_NAME_SELECTOR (name_selector), NULL);
277
278 return g_object_new (
279 E_TYPE_COMPOSER_NAME_HEADER,
280 "label", label, "button", TRUE,
281 "name-selector", name_selector,
282 "registry", registry, NULL);
283 }
284
285 ENameSelector *
286 e_composer_name_header_get_name_selector (EComposerNameHeader *header)
287 {
288 g_return_val_if_fail (E_IS_COMPOSER_NAME_HEADER (header), NULL);
289
290 return header->priv->name_selector;
291 }
292
293 EDestination **
294 e_composer_name_header_get_destinations (EComposerNameHeader *header)
295 {
296 EDestinationStore *store;
297 EDestination **destinations;
298 ENameSelectorEntry *entry;
299 GList *list, *iter;
300 gint ii = 0;
301
302 g_return_val_if_fail (E_IS_COMPOSER_NAME_HEADER (header), NULL);
303
304 entry = E_COMPOSER_NAME_HEADER_GET_ENTRY (header);
305 store = e_name_selector_entry_peek_destination_store (entry);
306
307 list = e_destination_store_list_destinations (store);
308 destinations = g_new0 (EDestination *, g_list_length (list) + 1);
309
310 for (iter = list; iter != NULL; iter = iter->next)
311 destinations[ii++] = g_object_ref (iter->data);
312
313 g_list_free (list);
314
315 /* free with e_destination_freev() */
316 return destinations;
317 }
318
319 void
320 e_composer_name_header_add_destinations (EComposerNameHeader *header,
321 EDestination **destinations)
322 {
323 EDestinationStore *store;
324 ENameSelectorEntry *entry;
325 gint ii;
326
327 g_return_if_fail (E_IS_COMPOSER_NAME_HEADER (header));
328
329 entry = E_COMPOSER_NAME_HEADER_GET_ENTRY (header);
330 store = e_name_selector_entry_peek_destination_store (entry);
331
332 if (destinations == NULL)
333 return;
334
335 for (ii = 0; destinations[ii] != NULL; ii++)
336 e_destination_store_append_destination (
337 store, destinations[ii]);
338 }
339
340 void
341 e_composer_name_header_set_destinations (EComposerNameHeader *header,
342 EDestination **destinations)
343 {
344 EDestinationStore *store;
345 ENameSelectorEntry *entry;
346 GList *list, *iter;
347
348 g_return_if_fail (E_IS_COMPOSER_NAME_HEADER (header));
349
350 entry = E_COMPOSER_NAME_HEADER_GET_ENTRY (header);
351 store = e_name_selector_entry_peek_destination_store (entry);
352
353 /* Clear the destination store. */
354 list = e_destination_store_list_destinations (store);
355 for (iter = list; iter != NULL; iter = iter->next)
356 e_destination_store_remove_destination (store, iter->data);
357 g_list_free (list);
358
359 e_composer_name_header_add_destinations (header, destinations);
360 }