evolution-3.6.4/widgets/misc/e-web-view-preview.c

No issues found

  1 /*
  2  * e-web-view-preview.c
  3  *
  4  * This program is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU Lesser General Public
  6  * License as published by the Free Software Foundation; either
  7  * version 2 of the License, or (at your option) version 3.
  8  *
  9  * This program is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12  * Lesser General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU Lesser General Public
 15  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 16  *
 17  *
 18  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 19  *
 20  */
 21 
 22 #ifdef HAVE_CONFIG_H
 23 #include <config.h>
 24 #endif
 25 
 26 #include "e-web-view-preview.h"
 27 
 28 #include <string.h>
 29 #include <glib/gi18n-lib.h>
 30 
 31 #define E_WEB_VIEW_PREVIEW_GET_PRIVATE(obj) \
 32 	(G_TYPE_INSTANCE_GET_PRIVATE \
 33 	((obj), E_TYPE_WEB_VIEW_PREVIEW, EWebViewPreviewPrivate))
 34 
 35 struct _EWebViewPreviewPrivate {
 36 	gboolean escape_values;
 37 	GString *updating_content; /* is NULL when not between begin_update/end_update */
 38 };
 39 
 40 enum {
 41 	PROP_0,
 42 	PROP_TREE_VIEW,
 43 	PROP_PREVIEW_WIDGET,
 44 	PROP_ESCAPE_VALUES
 45 };
 46 
 47 G_DEFINE_TYPE (
 48 	EWebViewPreview,
 49 	e_web_view_preview,
 50 	GTK_TYPE_VPANED);
 51 
 52 static void
 53 web_view_preview_set_property (GObject *object,
 54                                guint property_id,
 55                                const GValue *value,
 56                                GParamSpec *pspec)
 57 {
 58 	switch (property_id) {
 59 		case PROP_ESCAPE_VALUES:
 60 			e_web_view_preview_set_escape_values (
 61 				E_WEB_VIEW_PREVIEW (object),
 62 				g_value_get_boolean (value));
 63 			return;
 64 	}
 65 
 66 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 67 }
 68 
 69 static void
 70 web_view_preview_get_property (GObject *object,
 71                                guint property_id,
 72                                GValue *value,
 73                                GParamSpec *pspec)
 74 {
 75 	switch (property_id) {
 76 		case PROP_TREE_VIEW:
 77 			g_value_set_object (
 78 				value, e_web_view_preview_get_tree_view (
 79 				E_WEB_VIEW_PREVIEW (object)));
 80 			return;
 81 
 82 		case PROP_PREVIEW_WIDGET:
 83 			g_value_set_object (
 84 				value, e_web_view_preview_get_preview (
 85 				E_WEB_VIEW_PREVIEW (object)));
 86 			return;
 87 
 88 		case PROP_ESCAPE_VALUES:
 89 			g_value_set_boolean (
 90 				value, e_web_view_preview_get_escape_values (
 91 				E_WEB_VIEW_PREVIEW (object)));
 92 			return;
 93 	}
 94 
 95 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 96 }
 97 
 98 static void
 99 web_view_preview_dispose (GObject *object)
100 {
101 	EWebViewPreviewPrivate *priv;
102 
103 	priv = E_WEB_VIEW_PREVIEW_GET_PRIVATE (object);
104 
105 	if (priv->updating_content != NULL) {
106 		g_string_free (priv->updating_content, TRUE);
107 		priv->updating_content = NULL;
108 	}
109 
110 	/* Chain up to parent's dispose() method. */
111 	G_OBJECT_CLASS (e_web_view_preview_parent_class)->dispose (object);
112 }
113 
114 static void
115 e_web_view_preview_class_init (EWebViewPreviewClass *class)
116 {
117 	GObjectClass *object_class;
118 
119 	g_type_class_add_private (class, sizeof (EWebViewPreviewPrivate));
120 
121 	object_class = G_OBJECT_CLASS (class);
122 	object_class->set_property = web_view_preview_set_property;
123 	object_class->get_property = web_view_preview_get_property;
124 	object_class->dispose = web_view_preview_dispose;
125 
126 	g_object_class_install_property (
127 		object_class,
128 		PROP_TREE_VIEW,
129 		g_param_spec_object (
130 			"tree-view",
131 			"Tree View",
132 			NULL,
133 			GTK_TYPE_TREE_VIEW,
134 			G_PARAM_READABLE));
135 
136 	g_object_class_install_property (
137 		object_class,
138 		PROP_PREVIEW_WIDGET,
139 		g_param_spec_object (
140 			"preview-widget",
141 			"Preview Widget",
142 			NULL,
143 			GTK_TYPE_WIDGET,
144 			G_PARAM_READABLE));
145 
146 	g_object_class_install_property (
147 		object_class,
148 		PROP_ESCAPE_VALUES,
149 		g_param_spec_boolean (
150 			"escape-values",
151 			"Whether escaping values automatically, when inserting",
152 			NULL,
153 			TRUE,
154 			G_PARAM_READWRITE));
155 }
156 
157 static GtkWidget *
158 in_scrolled_window (GtkWidget *widget)
159 {
160 	GtkWidget *sw;
161 
162 	g_return_val_if_fail (widget != NULL, NULL);
163 
164 	sw = gtk_scrolled_window_new (NULL, NULL);
165 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
166 	gtk_container_add (GTK_CONTAINER (sw), widget);
167 
168 	gtk_widget_show (widget);
169 	gtk_widget_show (sw);
170 
171 	return sw;
172 }
173 
174 static void
175 e_web_view_preview_init (EWebViewPreview *preview)
176 {
177 	GtkWidget *tree_view_sw, *web_view_sw;
178 
179 	preview->priv = E_WEB_VIEW_PREVIEW_GET_PRIVATE (preview);
180 	preview->priv->escape_values = TRUE;
181 
182 	tree_view_sw = in_scrolled_window (gtk_tree_view_new ());
183 	web_view_sw = in_scrolled_window (e_web_view_new ());
184 
185 	gtk_widget_hide (tree_view_sw);
186 	gtk_widget_show (web_view_sw);
187 
188 	gtk_paned_pack1 (GTK_PANED (preview), tree_view_sw, FALSE, TRUE);
189 	gtk_paned_pack2 (GTK_PANED (preview), web_view_sw, TRUE, TRUE);
190 
191 	/* rawly 3 lines of a text plus a little bit more */
192 	if (gtk_paned_get_position (GTK_PANED (preview)) < 85)
193 		gtk_paned_set_position (GTK_PANED (preview), 85);
194 }
195 
196 GtkWidget *
197 e_web_view_preview_new (void)
198 {
199 	return g_object_new (E_TYPE_WEB_VIEW_PREVIEW, NULL);
200 }
201 
202 GtkTreeView *
203 e_web_view_preview_get_tree_view (EWebViewPreview *preview)
204 {
205 	g_return_val_if_fail (preview != NULL, NULL);
206 	g_return_val_if_fail (E_IS_WEB_VIEW_PREVIEW (preview), NULL);
207 
208 	return GTK_TREE_VIEW (gtk_bin_get_child (GTK_BIN (gtk_paned_get_child1 (GTK_PANED (preview)))));
209 }
210 
211 GtkWidget *
212 e_web_view_preview_get_preview (EWebViewPreview *preview)
213 {
214 	g_return_val_if_fail (preview != NULL, NULL);
215 	g_return_val_if_fail (E_IS_WEB_VIEW_PREVIEW (preview), NULL);
216 
217 	return gtk_bin_get_child (GTK_BIN (gtk_paned_get_child2 (GTK_PANED (preview))));
218 }
219 
220 void
221 e_web_view_preview_set_preview (EWebViewPreview *preview,
222                                 GtkWidget *preview_widget)
223 {
224 	GtkWidget *old_child;
225 
226 	g_return_if_fail (E_IS_WEB_VIEW_PREVIEW (preview));
227 	g_return_if_fail (GTK_IS_WIDGET (preview_widget));
228 
229 	old_child = gtk_bin_get_child (GTK_BIN (gtk_paned_get_child2 (GTK_PANED (preview))));
230 	if (old_child) {
231 		g_return_if_fail (old_child != preview_widget);
232 		gtk_widget_destroy (old_child);
233 	}
234 
235 	gtk_container_add (GTK_CONTAINER (gtk_paned_get_child2 (GTK_PANED (preview))), preview_widget);
236 }
237 
238 void
239 e_web_view_preview_show_tree_view (EWebViewPreview *preview)
240 {
241 	g_return_if_fail (E_IS_WEB_VIEW_PREVIEW (preview));
242 
243 	gtk_widget_show (gtk_paned_get_child1 (GTK_PANED (preview)));
244 }
245 
246 void
247 e_web_view_preview_hide_tree_view (EWebViewPreview *preview)
248 {
249 	g_return_if_fail (E_IS_WEB_VIEW_PREVIEW (preview));
250 
251 	gtk_widget_hide (gtk_paned_get_child1 (GTK_PANED (preview)));
252 }
253 
254 void
255 e_web_view_preview_set_escape_values (EWebViewPreview *preview,
256                                       gboolean escape)
257 {
258 	g_return_if_fail (E_IS_WEB_VIEW_PREVIEW (preview));
259 
260 	preview->priv->escape_values = escape;
261 }
262 
263 gboolean
264 e_web_view_preview_get_escape_values (EWebViewPreview *preview)
265 {
266 	g_return_val_if_fail (preview != NULL, FALSE);
267 	g_return_val_if_fail (E_IS_WEB_VIEW_PREVIEW (preview), FALSE);
268 	g_return_val_if_fail (preview->priv != NULL, FALSE);
269 
270 	return preview->priv->escape_values;
271 }
272 
273 void
274 e_web_view_preview_begin_update (EWebViewPreview *preview)
275 {
276 	g_return_if_fail (E_IS_WEB_VIEW_PREVIEW (preview));
277 
278 	if (preview->priv->updating_content) {
279 		g_warning ("%s: Previous content update isn't finished with e_web_view_preview_end_update()", G_STRFUNC);
280 		g_string_free (preview->priv->updating_content, TRUE);
281 	}
282 
283 	preview->priv->updating_content = g_string_new ("<TABLE width=\"100%\" border=\"0\" cols=\"2\">");
284 }
285 
286 void
287 e_web_view_preview_end_update (EWebViewPreview *preview)
288 {
289 	GtkWidget *web_view;
290 
291 	g_return_if_fail (E_IS_WEB_VIEW_PREVIEW (preview));
292 	g_return_if_fail (preview->priv->updating_content != NULL);
293 
294 	g_string_append (preview->priv->updating_content, "</TABLE>");
295 
296 	web_view = e_web_view_preview_get_preview (preview);
297 	if (E_IS_WEB_VIEW (web_view))
298 		e_web_view_load_string (E_WEB_VIEW (web_view), preview->priv->updating_content->str);
299 
300 	g_string_free (preview->priv->updating_content, TRUE);
301 	preview->priv->updating_content = NULL;
302 }
303 
304 static gchar *
305 replace_string (const gchar *text,
306                 const gchar *find,
307                 const gchar *replace)
308 {
309 	const gchar *p, *next;
310 	GString *str;
311 	gint find_len;
312 
313 	g_return_val_if_fail (text != NULL, NULL);
314 	g_return_val_if_fail (find != NULL, NULL);
315 	g_return_val_if_fail (*find, NULL);
316 
317 	find_len = strlen (find);
318 	str = g_string_new ("");
319 
320 	p = text;
321 	while (next = strstr (p, find), next) {
322 		if (p + 1 < next)
323 			g_string_append_len (str, p, next - p);
324 
325 		if (replace && *replace)
326 			g_string_append (str, replace);
327 
328 		p = next + find_len;
329 	}
330 
331 	g_string_append (str, p);
332 
333 	return g_string_free (str, FALSE);
334 }
335 
336 static gchar *
337 web_view_preview_escape_text (EWebViewPreview *preview,
338                               const gchar *text)
339 {
340 	gchar *utf8_valid, *res, *end;
341 
342 	if (!e_web_view_preview_get_escape_values (preview))
343 		return NULL;
344 
345 	g_return_val_if_fail (text != NULL, NULL);
346 
347 	if (g_utf8_validate (text, -1, NULL)) {
348 		res = g_markup_escape_text (text, -1);
349 	} else {
350 		utf8_valid = g_strdup (text);
351 		while (end = NULL, !g_utf8_validate (utf8_valid, -1, (const gchar **) &end) && end && *end)
352 			*end = '?';
353 
354 		res = g_markup_escape_text (utf8_valid, -1);
355 
356 		g_free (utf8_valid);
357 	}
358 
359 	if (res && strchr (res, '\n')) {
360 		/* replace line breaks with <BR> */
361 		if (strchr (res, '\r')) {
362 			end = replace_string (res, "\r", "");
363 			g_free (res);
364 			res = end;
365 		}
366 
367 		end = replace_string (res, "\n", "<BR>");
368 		g_free (res);
369 		res = end;
370 	}
371 
372 	return res;
373 }
374 
375 void
376 e_web_view_preview_add_header (EWebViewPreview *preview,
377                                gint index,
378                                const gchar *header)
379 {
380 	gchar *escaped;
381 
382 	g_return_if_fail (E_IS_WEB_VIEW_PREVIEW (preview));
383 	g_return_if_fail (preview->priv->updating_content != NULL);
384 	g_return_if_fail (header != NULL);
385 
386 	if (index < 1)
387 		index = 1;
388 	else if (index > 6)
389 		index = 6;
390 
391 	escaped = web_view_preview_escape_text (preview, header);
392 	if (escaped)
393 		header = escaped;
394 
395 	g_string_append_printf (preview->priv->updating_content, "<TR><TD colspan=2><H%d>%s</H%d></TD></TR>", index, header, index);
396 
397 	g_free (escaped);
398 }
399 
400 void
401 e_web_view_preview_add_text (EWebViewPreview *preview,
402                              const gchar *text)
403 {
404 	gchar *escaped;
405 
406 	g_return_if_fail (E_IS_WEB_VIEW_PREVIEW (preview));
407 	g_return_if_fail (preview->priv->updating_content != NULL);
408 	g_return_if_fail (text != NULL);
409 
410 	escaped = web_view_preview_escape_text (preview, text);
411 	if (escaped)
412 		text = escaped;
413 
414 	g_string_append_printf (preview->priv->updating_content, "<TR><TD colspan=2><FONT size=\"3\">%s</FONT></TD></TR>", text);
415 
416 	g_free (escaped);
417 }
418 
419 void
420 e_web_view_preview_add_raw_html (EWebViewPreview *preview,
421                                  const gchar *raw_html)
422 {
423 	g_return_if_fail (E_IS_WEB_VIEW_PREVIEW (preview));
424 	g_return_if_fail (preview->priv->updating_content != NULL);
425 	g_return_if_fail (raw_html != NULL);
426 
427 	g_string_append_printf (preview->priv->updating_content, "<TR><TD colspan=2>%s</TD></TR>", raw_html);
428 }
429 
430 void
431 e_web_view_preview_add_separator (EWebViewPreview *preview)
432 {
433 	g_return_if_fail (E_IS_WEB_VIEW_PREVIEW (preview));
434 	g_return_if_fail (preview->priv->updating_content != NULL);
435 
436 	g_string_append (preview->priv->updating_content, "<TR><TD colspan=2><HR></TD></TR>");
437 }
438 
439 void
440 e_web_view_preview_add_empty_line (EWebViewPreview *preview)
441 {
442 	g_return_if_fail (E_IS_WEB_VIEW_PREVIEW (preview));
443 	g_return_if_fail (preview->priv->updating_content != NULL);
444 
445 	g_string_append (preview->priv->updating_content, "<TR><TD colspan=2>&nbsp;</TD></TR>");
446 }
447 
448 /* section can be NULL, but value cannot */
449 void
450 e_web_view_preview_add_section (EWebViewPreview *preview,
451                                 const gchar *section,
452                                 const gchar *value)
453 {
454 	gchar *escaped_section = NULL, *escaped_value;
455 
456 	g_return_if_fail (E_IS_WEB_VIEW_PREVIEW (preview));
457 	g_return_if_fail (preview->priv->updating_content != NULL);
458 	g_return_if_fail (value != NULL);
459 
460 	if (section) {
461 		escaped_section = web_view_preview_escape_text (preview, section);
462 		if (escaped_section)
463 			section = escaped_section;
464 	}
465 
466 	escaped_value = web_view_preview_escape_text (preview, value);
467 	if (escaped_value)
468 		value = escaped_value;
469 
470 	g_string_append_printf (preview->priv->updating_content, "<TR><TD width=\"10%%\" valign=\"top\" nowrap><FONT size=\"3\"><B>%s</B></FONT></TD><TD width=\"90%%\"><FONT size=\"3\">%s</FONT></TD></TR>", section ? section : "", value);
471 
472 	g_free (escaped_section);
473 	g_free (escaped_value);
474 }