[evolution/webkit-composer] Port HTML/plain text mode toggling



commit 2e4e8c05f0b068a9fb2a376553593a57bdfcd620
Author: Dan VrÃtil <dvratil redhat com>
Date:   Tue Jul 31 15:54:49 2012 +0200

    Port HTML/plain text mode toggling
    
    Unlike with GtkHTML, we can't change renderers and make WebKit to
    render HTML code as plain text. The only way is to discard any formatting
    when toggling from HTML to plain text. This is similar to what KMail does.

 widgets/editor/e-editor-actions.c |  143 ++++++++++++++++++++++---------------
 widgets/editor/e-editor-test.c    |    8 +-
 widgets/editor/e-editor-widget.c  |   65 +++++++++++------
 widgets/editor/e-editor-widget.h  |    7 +-
 4 files changed, 136 insertions(+), 87 deletions(-)
---
diff --git a/widgets/editor/e-editor-actions.c b/widgets/editor/e-editor-actions.c
index fce7573..09c2994 100644
--- a/widgets/editor/e-editor-actions.c
+++ b/widgets/editor/e-editor-actions.c
@@ -886,80 +886,102 @@ action_language_cb (GtkToggleAction *action,
 	*/
 }
 
-static void
-action_mode_cb (GtkRadioAction *action,
-                GtkRadioAction *current,
-                EEditor *editor)
+struct _ModeChanged {
+	GtkRadioAction *action;
+	EEditor *editor;
+};
+
+static gboolean
+mode_changed (struct _ModeChanged *data)
 {
-	/* FIXME WEBKIT */
-	/*
 	GtkActionGroup *action_group;
-	HTMLPainter *new_painter;
-	HTMLPainter *old_painter;
-	GtkHTML *html;
-	EditorMode mode;
-	gboolean html_mode;
+	EEditor *editor = data->editor;
+	EEditorWidget *widget;
+	EEditorWidgetMode mode;
+	gboolean is_html;
 
-	html = gtkhtml_editor_get_html (editor);
-	mode = gtk_radio_action_get_current_value (current);
-	html_mode = (mode == EDITOR_MODE_HTML);
+	widget = e_editor_get_editor_widget (editor);
+	mode = gtk_radio_action_get_current_value (data->action);
+	is_html = (mode == E_EDITOR_WIDGET_MODE_HTML);
+
+	if (mode == e_editor_widget_get_mode (widget)) {
+		goto exit;
+	}
+
+	/* If switching from HTML to plain text */
+	if (!is_html) {
+		GtkWidget *dialog, *parent;
+
+		parent = gtk_widget_get_toplevel (GTK_WIDGET (editor));
+		if (!GTK_IS_WINDOW (parent)) {
+			parent = NULL;
+		}
+
+		dialog = gtk_message_dialog_new (
+				parent ? GTK_WINDOW (parent) : NULL,
+				GTK_DIALOG_DESTROY_WITH_PARENT,
+				GTK_MESSAGE_WARNING,
+				GTK_BUTTONS_OK_CANCEL,
+				_("Turning HTML mode off will cause the text "
+				  "to loose all formatting. Do you want to continue?"));
+		if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_CANCEL) {
+			gtk_radio_action_set_current_value (
+				data->action, E_EDITOR_WIDGET_MODE_HTML);
+			gtk_widget_destroy (dialog);
+			goto exit;
+		}
+
+		gtk_widget_destroy (dialog);
+	}
 
 	action_group = editor->priv->html_actions;
-	gtk_action_group_set_sensitive (action_group, html_mode);
+	gtk_action_group_set_sensitive (action_group, is_html);
 
 	action_group = editor->priv->html_context_actions;
-	gtk_action_group_set_visible (action_group, html_mode);
+	gtk_action_group_set_visible (action_group, is_html);
 
-	gtk_widget_set_sensitive (editor->priv->color_combo_box, html_mode);
+	gtk_widget_set_sensitive (editor->priv->color_combo_box, is_html);
 
-	if (html_mode)
+	if (is_html) {
 		gtk_widget_show (editor->priv->html_toolbar);
-	else
+	} else {
 		gtk_widget_hide (editor->priv->html_toolbar);
+	}
 
-	// Certain paragraph styles are HTML-only.
-	gtk_action_set_sensitive (ACTION (STYLE_H1), html_mode);
-	gtk_action_set_sensitive (ACTION (STYLE_H2), html_mode);
-	gtk_action_set_sensitive (ACTION (STYLE_H3), html_mode);
-	gtk_action_set_sensitive (ACTION (STYLE_H4), html_mode);
-	gtk_action_set_sensitive (ACTION (STYLE_H5), html_mode);
-	gtk_action_set_sensitive (ACTION (STYLE_H6), html_mode);
-	gtk_action_set_sensitive (ACTION (STYLE_ADDRESS), html_mode);
+	/* Certain paragraph styles are HTML-only. */
+	gtk_action_set_sensitive (ACTION (STYLE_H1), is_html);
+	gtk_action_set_sensitive (ACTION (STYLE_H2), is_html);
+	gtk_action_set_sensitive (ACTION (STYLE_H3), is_html);
+	gtk_action_set_sensitive (ACTION (STYLE_H4), is_html);
+	gtk_action_set_sensitive (ACTION (STYLE_H5), is_html);
+	gtk_action_set_sensitive (ACTION (STYLE_H6), is_html);
+	gtk_action_set_sensitive (ACTION (STYLE_ADDRESS), is_html);
 
-	// Swap painters.
+	e_editor_widget_set_mode (
+		e_editor_get_editor_widget (editor), mode);
 
-	if (html_mode) {
-		new_painter = editor->priv->html_painter;
-		old_painter = editor->priv->plain_painter;
-	} else {
-		new_painter = editor->priv->plain_painter;
-		old_painter = editor->priv->html_painter;
-	}
+ exit:
+	g_clear_object (&data->editor);
+	g_clear_object (&data->action);
+	g_free (data);
 
-	// Might be true during initialization.
-	if (html->engine->painter == new_painter)
-		return;
+	return FALSE;
+}
 
-	html_gdk_painter_unrealize (HTML_GDK_PAINTER (old_painter));
-	if (html->engine->window != NULL)
-		html_gdk_painter_realize (
-			HTML_GDK_PAINTER (new_painter),
-			html->engine->window);
-
-	html_font_manager_set_default (
-		&new_painter->font_manager,
-		old_painter->font_manager.variable.face,
-		old_painter->font_manager.fixed.face,
-		old_painter->font_manager.var_size,
-		old_painter->font_manager.var_points,
-		old_painter->font_manager.fix_size,
-		old_painter->font_manager.fix_points);
-
-	html_engine_set_painter (html->engine, new_painter);
-	html_engine_schedule_redraw (html->engine);
-
-	g_object_notify (G_OBJECT (editor), "html-mode");
-	*/
+static void
+action_mode_cb (GtkRadioAction *action,
+                GtkRadioAction *current,
+                EEditor *editor)
+{
+	struct _ModeChanged *data;
+
+	data = g_new0 (struct _ModeChanged, 1);
+	data->action = g_object_ref (current);
+	data->editor = g_object_ref (editor);
+
+	/* We can't change group current value from this callback, so
+	 * let's do it all from an idle callback */
+	g_idle_add ((GSourceFunc) mode_changed, data);
 }
 
 static void
@@ -2131,6 +2153,7 @@ editor_actions_init (EEditor *editor)
 
 	manager = e_editor_get_ui_manager (editor);
 	domain = GETTEXT_PACKAGE;
+	editor_widget = e_editor_get_editor_widget (editor);
 
 	/* Core Actions */
 	action_group = editor->priv->core_actions;
@@ -2155,6 +2178,9 @@ editor_actions_init (EEditor *editor)
 		G_CALLBACK (action_style_cb), editor);
 	gtk_ui_manager_insert_action_group (manager, action_group, 0);
 
+	/* Synchronize wiget mode with the button */
+	e_editor_widget_set_mode (editor_widget, E_EDITOR_WIDGET_MODE_HTML);
+
 	/* Face Action */
 	action = e_emoticon_action_new (
 		"insert-face", _("_Emoticon"),
@@ -2240,7 +2266,6 @@ editor_actions_init (EEditor *editor)
 	gtk_action_set_sensitive (ACTION (UNINDENT), FALSE);
 	gtk_action_set_sensitive (ACTION (FIND_AGAIN), FALSE);
 
-	editor_widget = e_editor_get_editor_widget (editor);
 	g_object_bind_property (
 		editor_widget, "can-redo",
 		ACTION (REDO), "sensitive",
diff --git a/widgets/editor/e-editor-test.c b/widgets/editor/e-editor-test.c
index 6023e68..f55276a 100644
--- a/widgets/editor/e-editor-test.c
+++ b/widgets/editor/e-editor-test.c
@@ -217,8 +217,8 @@ action_save_cb (GtkAction *action,
 			return;
 
 	filename = e_editor_get_filename (editor);
-	as_html = e_editor_widget_get_html_mode (
-			e_editor_get_editor_widget (editor));
+	as_html = (e_editor_widget_get_mode (
+			e_editor_get_editor_widget (editor)) == E_EDITOR_WIDGET_MODE_HTML);
 
 	e_editor_save (editor, filename, as_html, &error);
 	handle_error (&error);
@@ -236,8 +236,8 @@ action_save_as_cb (GtkAction *action,
 		return;
 
 	filename = e_editor_get_filename (editor);
-	as_html = e_editor_widget_get_html_mode (
-			e_editor_get_editor_widget (editor));
+	as_html = (e_editor_widget_get_mode (
+			e_editor_get_editor_widget (editor)) == E_EDITOR_WIDGET_MODE_HTML);
 
 	e_editor_save (editor, filename, as_html, &error);
 	handle_error (&error);
diff --git a/widgets/editor/e-editor-widget.c b/widgets/editor/e-editor-widget.c
index 7930595..4951221 100644
--- a/widgets/editor/e-editor-widget.c
+++ b/widgets/editor/e-editor-widget.c
@@ -21,12 +21,12 @@
 #endif
 
 #include "e-editor-widget.h"
+#include "e-editor.h"
 
 #include <glib/gi18n-lib.h>
 
 struct _EEditorWidgetPrivate {
 	gint changed		: 1;
-	gint html_mode		: 1;
 	gint inline_spelling	: 1;
 	gint magic_links	: 1;
 	gint magic_smileys	: 1;
@@ -36,6 +36,8 @@ struct _EEditorWidgetPrivate {
 	gint can_redo		: 1;
 	gint can_undo		: 1;
 
+	EEditorWidgetMode mode;
+
 	/* FIXME WEBKIT Is this in widget's competence? */
 	GList *spelling_langs;
 };
@@ -49,7 +51,7 @@ G_DEFINE_TYPE (
 enum {
 	PROP_0,
 	PROP_CHANGED,
-	PROP_HTML_MODE,
+	PROP_MODE,
 	PROP_INLINE_SPELLING,
 	PROP_MAGIC_LINKS,
 	PROP_MAGIC_SMILEYS,
@@ -61,6 +63,22 @@ enum {
 	PROP_CAN_UNDO
 };
 
+static void
+editor_widget_strip_formatting (EEditorWidget *widget)
+{
+	gchar *plain, *html;
+
+	plain = e_editor_widget_get_text_plain (widget);
+
+	/* Convert \n to <br> */
+	regex = g_regex_new ("\n", 0, 0, NULL);
+	html = g_regex_replace (regex, plain, strlen (plain), 0, "<br>", 0, NULL);
+
+	e_editor_widget_set_text_html (widget, html);
+
+	g_free (plain);
+	g_free (html);
+}
 
 static void
 editor_widget_user_changed_contents_cb (EEditorWidget *widget,
@@ -116,9 +134,9 @@ e_editor_widget_get_property (GObject *object,
 {
 	switch (property_id) {
 
-		case PROP_HTML_MODE:
-			g_value_set_boolean (
-				value, e_editor_widget_get_html_mode (
+		case PROP_MODE:
+			g_value_set_int (
+				value, e_editor_widget_get_mode (
 				E_EDITOR_WIDGET (object)));
 			return;
 
@@ -182,10 +200,10 @@ e_editor_widget_set_property (GObject *object,
 {
 	switch (property_id) {
 
-		case PROP_HTML_MODE:
-			e_editor_widget_set_html_mode (
+		case PROP_MODE:
+			e_editor_widget_set_mode (
 				E_EDITOR_WIDGET (object),
-				g_value_get_boolean (value));
+				g_value_get_int (value));
 			return;
 
 		case PROP_INLINE_SPELLING:
@@ -234,12 +252,14 @@ e_editor_widget_class_init (EEditorWidgetClass *klass)
 
 	g_object_class_install_property (
 		object_class,
-		PROP_HTML_MODE,
-		g_param_spec_boolean (
-			"html-mode",
-			"HTML Mode",
+		PROP_MODE,
+		g_param_spec_int (
+			"mode",
+			"Mode",
 			"Edit HTML or plain text",
-			TRUE,
+			E_EDITOR_WIDGET_MODE_PLAIN_TEXT,
+		    	E_EDITOR_WIDGET_MODE_HTML,
+		    	E_EDITOR_WIDGET_MODE_PLAIN_TEXT,
 			G_PARAM_READWRITE |
 			G_PARAM_CONSTRUCT));
 
@@ -414,26 +434,29 @@ e_editor_widget_set_changed (EEditorWidget *widget,
 	g_object_notify (G_OBJECT (widget), "changed");
 }
 
-gboolean
-e_editor_widget_get_html_mode (EEditorWidget *widget)
+EEditorWidgetMode
+e_editor_widget_get_mode (EEditorWidget *widget)
 {
 	g_return_val_if_fail (E_IS_EDITOR_WIDGET (widget), FALSE);
 
-	return widget->priv->html_mode;
+	return widget->priv->mode;
 }
 
 void
-e_editor_widget_set_html_mode (EEditorWidget *widget,
-			       gboolean html_mode)
+e_editor_widget_set_mode (EEditorWidget *widget,
+			  EEditorWidgetMode mode)
 {
 	g_return_if_fail (E_IS_EDITOR_WIDGET (widget));
 
-	if ((widget->priv->html_mode ? TRUE : FALSE) == (html_mode ? TRUE : FALSE))
+	if (widget->priv->mode == mode)
 		return;
 
-	widget->priv->html_mode = html_mode;
+	widget->priv->mode = mode;
+
+	if (widget->priv->mode == E_EDITOR_WIDGET_MODE_PLAIN_TEXT)
+		editor_widget_strip_formatting (widget);
 
-	g_object_notify (G_OBJECT (widget), "html-mode");
+	g_object_notify (G_OBJECT (widget), "mode");
 }
 
 gboolean
diff --git a/widgets/editor/e-editor-widget.h b/widgets/editor/e-editor-widget.h
index 14ea8a7..e03d0e3 100644
--- a/widgets/editor/e-editor-widget.h
+++ b/widgets/editor/e-editor-widget.h
@@ -81,9 +81,10 @@ gboolean	e_editor_widget_get_changed	(EEditorWidget *widget);
 void		e_editor_widget_set_changed	(EEditorWidget *widget,
 						 gboolean changed);
 
-gboolean	e_editor_widget_get_html_mode	(EEditorWidget *widget);
-void		e_editor_widget_set_html_mode	(EEditorWidget *widget,
-						 gboolean html_mode);
+EEditorWidgetMode
+		e_editor_widget_get_mode	(EEditorWidget *widget);
+void		e_editor_widget_set_mode	(EEditorWidget *widget,
+						 EEditorWidgetMode mode);
 
 gboolean	e_editor_widget_get_inline_spelling
 						(EEditorWidget *widget);



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