[evolution/449-support-markdown-in-composer] Change how editors connect to the EHTMLEditor::content_editor
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/449-support-markdown-in-composer] Change how editors connect to the EHTMLEditor::content_editor
- Date: Wed, 9 Feb 2022 14:15:36 +0000 (UTC)
commit 4e9af47337dfa060e5233302f54b251687dc22ec
Author: Milan Crha <mcrha redhat com>
Date: Wed Feb 9 15:14:26 2022 +0100
Change how editors connect to the EHTMLEditor::content_editor
As the content editor can change on the mode change, the connections
to the properties and the like should change together with it.
src/e-util/e-html-editor-actions.c | 168 ++++++++++++++++++++++---------------
src/e-util/e-html-editor-private.h | 4 +
src/e-util/e-html-editor.c | 40 ++++-----
src/e-util/e-markdown-editor.c | 5 +-
src/mail/e-mail-notes.c | 56 +++++++++++--
5 files changed, 180 insertions(+), 93 deletions(-)
---
diff --git a/src/e-util/e-html-editor-actions.c b/src/e-util/e-html-editor-actions.c
index 657340d5f7..797ad6ee44 100644
--- a/src/e-util/e-html-editor-actions.c
+++ b/src/e-util/e-html-editor-actions.c
@@ -2153,6 +2153,7 @@ e_html_editor_actions_init (EHTMLEditor *editor)
GtkActionGroup *action_group;
GtkUIManager *manager;
const gchar *domain;
+ guint ii;
g_return_if_fail (E_IS_HTML_EDITOR (editor));
@@ -2280,6 +2281,26 @@ e_html_editor_actions_init (EHTMLEditor *editor)
gtk_action_set_sensitive (ACTION (UNINDENT), FALSE);
gtk_action_set_sensitive (ACTION (FIND_AGAIN), FALSE);
+
+ g_signal_connect_object (ACTION (SUBSCRIPT), "toggled",
+ G_CALLBACK (html_editor_actions_subscript_toggled_cb), editor, 0);
+ g_signal_connect_object (ACTION (SUPERSCRIPT), "toggled",
+ G_CALLBACK (html_editor_actions_superscript_toggled_cb), editor, 0);
+ g_signal_connect (editor, "notify::mode",
+ G_CALLBACK (html_editor_actions_notify_mode_cb), NULL);
+
+ action_group = editor->priv->core_editor_actions;
+ action = gtk_action_group_get_action (action_group, "mode-html");
+ e_binding_bind_property (
+ editor, "mode",
+ action, "current-value",
+ G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+
+ for (ii = 0; ii < G_N_ELEMENTS (core_mode_entries); ii++) {
+ action = gtk_action_group_get_action (action_group, core_mode_entries[ii].name);
+
+ gtk_action_set_visible (action, e_html_editor_has_editor_for_mode (editor,
core_mode_entries[ii].value));
+ }
}
static gboolean
@@ -2359,138 +2380,149 @@ e_html_editor_util_new_mode_combobox (void)
void
e_html_editor_actions_bind (EHTMLEditor *editor)
{
- GtkAction *action;
- GtkActionGroup *action_group;
EContentEditor *cnt_editor;
- guint ii;
g_return_if_fail (E_IS_HTML_EDITOR (editor));
cnt_editor = e_html_editor_get_content_editor (editor);
- action_group = editor->priv->core_editor_actions;
- action = gtk_action_group_get_action (action_group, "mode-html");
- e_binding_bind_property (
- editor, "mode",
- action, "current-value",
- G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+ /* 'rb' for 'remember binding' */
+ #define rb(x) editor->priv->content_editor_bindings = g_slist_prepend
(editor->priv->content_editor_bindings, g_object_ref (x))
- for (ii = 0; ii < G_N_ELEMENTS (core_mode_entries); ii++) {
- action = gtk_action_group_get_action (action_group, core_mode_entries[ii].name);
-
- gtk_action_set_visible (action, e_html_editor_has_editor_for_mode (editor,
core_mode_entries[ii].value));
- }
-
- e_action_combo_box_update_model (E_ACTION_COMBO_BOX (editor->priv->mode_combo_box));
-
- /* Synchronize widget mode with the buttons */
- e_html_editor_set_mode (editor, E_CONTENT_EDITOR_MODE_HTML);
+ rb (e_binding_bind_property (
+ editor->priv->fg_color_combo_box, "current-color",
+ cnt_editor, "font-color",
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL));
+ rb (e_binding_bind_property (
+ cnt_editor, "editable",
+ editor->priv->fg_color_combo_box, "sensitive",
+ G_BINDING_SYNC_CREATE));
+ rb (e_binding_bind_property (
+ editor->priv->bg_color_combo_box, "current-color",
+ cnt_editor, "background-color",
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL));
+ rb (e_binding_bind_property (
+ cnt_editor, "editable",
+ editor->priv->bg_color_combo_box, "sensitive",
+ G_BINDING_SYNC_CREATE));
- e_binding_bind_property (
+ rb (e_binding_bind_property (
cnt_editor, "can-redo",
ACTION (REDO), "sensitive",
- G_BINDING_SYNC_CREATE);
- e_binding_bind_property (
+ G_BINDING_SYNC_CREATE));
+ rb (e_binding_bind_property (
cnt_editor, "can-undo",
ACTION (UNDO), "sensitive",
- G_BINDING_SYNC_CREATE);
- e_binding_bind_property (
+ G_BINDING_SYNC_CREATE));
+ rb (e_binding_bind_property (
cnt_editor, "can-copy",
ACTION (COPY), "sensitive",
- G_BINDING_SYNC_CREATE);
- e_binding_bind_property (
+ G_BINDING_SYNC_CREATE));
+ rb (e_binding_bind_property (
cnt_editor, "can-cut",
ACTION (CUT), "sensitive",
- G_BINDING_SYNC_CREATE);
- e_binding_bind_property (
+ G_BINDING_SYNC_CREATE));
+ rb (e_binding_bind_property (
cnt_editor, "can-paste",
ACTION (PASTE), "sensitive",
- G_BINDING_SYNC_CREATE);
- e_binding_bind_property (
+ G_BINDING_SYNC_CREATE));
+ rb (e_binding_bind_property (
cnt_editor, "can-paste",
ACTION (PASTE_QUOTE), "sensitive",
- G_BINDING_SYNC_CREATE);
+ G_BINDING_SYNC_CREATE));
/* This is connected to JUSTIFY_LEFT action only, but
* it automatically applies on all actions in the group. */
- e_binding_bind_property (
+ rb (e_binding_bind_property (
cnt_editor, "alignment",
ACTION (JUSTIFY_LEFT), "current-value",
- G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
- e_binding_bind_property (
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL));
+ rb (e_binding_bind_property (
cnt_editor, "bold",
ACTION (BOLD), "active",
- G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
- e_binding_bind_property (
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL));
+ rb (e_binding_bind_property (
cnt_editor, "font-size",
ACTION (FONT_SIZE_GROUP), "current-value",
- G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
- e_binding_bind_property (
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL));
+ rb (e_binding_bind_property (
cnt_editor, "block-format",
ACTION (STYLE_NORMAL), "current-value",
- G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
- e_binding_bind_property_full (
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL));
+ rb (e_binding_bind_property_full (
cnt_editor, "indent-level",
ACTION (INDENT), "sensitive",
G_BINDING_SYNC_CREATE,
e_html_editor_indent_level_to_bool_indent_cb,
- NULL, NULL, NULL);
- e_binding_bind_property_full (
+ NULL, NULL, NULL));
+ rb (e_binding_bind_property_full (
cnt_editor, "indent-level",
ACTION (UNINDENT), "sensitive",
G_BINDING_SYNC_CREATE,
e_html_editor_indent_level_to_bool_unindent_cb,
- NULL, NULL, NULL);
- e_binding_bind_property (
+ NULL, NULL, NULL));
+ rb (e_binding_bind_property (
cnt_editor, "italic",
ACTION (ITALIC), "active",
- G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
- e_binding_bind_property (
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL));
+ rb (e_binding_bind_property (
cnt_editor, "strikethrough",
ACTION (STRIKETHROUGH), "active",
- G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
- e_binding_bind_property (
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL));
+ rb (e_binding_bind_property (
cnt_editor, "underline",
ACTION (UNDERLINE), "active",
- G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
- e_binding_bind_property_full (
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL));
+ rb (e_binding_bind_property_full (
cnt_editor, "font-name",
editor->priv->font_name_combo_box, "active-id",
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL,
e_html_editor_content_editor_font_name_to_combo_box,
NULL,
- NULL, NULL);
+ NULL, NULL));
/* Cannot use binding, due to subscript and superscript being mutually exclusive */
- g_signal_connect_object (ACTION (SUBSCRIPT), "toggled",
- G_CALLBACK (html_editor_actions_subscript_toggled_cb), editor, 0);
- g_signal_connect_object (cnt_editor, "notify::subscript",
+ editor->priv->subscript_notify_id = g_signal_connect_object (cnt_editor, "notify::subscript",
G_CALLBACK (html_editor_actions_notify_subscript_cb), editor, 0);
- g_signal_connect_object (ACTION (SUPERSCRIPT), "toggled",
- G_CALLBACK (html_editor_actions_superscript_toggled_cb), editor, 0);
- g_signal_connect_object (cnt_editor, "notify::superscript",
+ editor->priv->superscript_notify_id = g_signal_connect_object (cnt_editor, "notify::superscript",
G_CALLBACK (html_editor_actions_notify_superscript_cb), editor, 0);
- g_signal_connect (editor, "notify::mode",
- G_CALLBACK (html_editor_actions_notify_mode_cb), NULL);
-
/* Disable all actions and toolbars when editor is not editable */
- e_binding_bind_property (
+ rb (e_binding_bind_property (
cnt_editor, "editable",
editor->priv->core_editor_actions, "sensitive",
- G_BINDING_SYNC_CREATE);
- e_binding_bind_property (
+ G_BINDING_SYNC_CREATE));
+ rb (e_binding_bind_property (
cnt_editor, "editable",
editor->priv->html_actions, "sensitive",
- G_BINDING_SYNC_CREATE);
- e_binding_bind_property (
+ G_BINDING_SYNC_CREATE));
+ rb (e_binding_bind_property (
cnt_editor, "editable",
editor->priv->spell_check_actions, "sensitive",
- G_BINDING_SYNC_CREATE);
- e_binding_bind_property (
+ G_BINDING_SYNC_CREATE));
+ rb (e_binding_bind_property (
cnt_editor, "editable",
editor->priv->suggestion_actions, "sensitive",
- G_BINDING_SYNC_CREATE);
+ G_BINDING_SYNC_CREATE));
+
+ #undef rb
+}
+
+void
+e_html_editor_actions_unbind (EHTMLEditor *editor)
+{
+ EContentEditor *cnt_editor;
+
+ g_slist_foreach (editor->priv->content_editor_bindings, (GFunc) g_binding_unbind, NULL);
+ g_slist_free_full (editor->priv->content_editor_bindings, g_object_unref);
+ editor->priv->content_editor_bindings = NULL;
+
+ cnt_editor = e_html_editor_get_content_editor (editor);
+
+ if (cnt_editor) {
+ e_signal_disconnect_notify_handler (cnt_editor, &editor->priv->subscript_notify_id);
+ e_signal_disconnect_notify_handler (cnt_editor, &editor->priv->superscript_notify_id);
+ }
}
void
diff --git a/src/e-util/e-html-editor-private.h b/src/e-util/e-html-editor-private.h
index 45f44e69bd..909a603011 100644
--- a/src/e-util/e-html-editor-private.h
+++ b/src/e-util/e-html-editor-private.h
@@ -101,6 +101,9 @@ struct _EHTMLEditorPrivate {
GCancellable *mode_change_content_cancellable;
gchar *filename;
+ GSList *content_editor_bindings; /* reffed GBinding-s related to the EContentEditor */
+ gulong subscript_notify_id;
+ gulong superscript_notify_id;
guint spell_suggestions_merge_id;
guint recent_spell_languages_merge_id;
@@ -112,6 +115,7 @@ struct _EHTMLEditorPrivate {
void e_html_editor_actions_init (EHTMLEditor *editor);
void e_html_editor_actions_bind (EHTMLEditor *editor);
+void e_html_editor_actions_unbind (EHTMLEditor *editor);
void e_html_editor_actions_update_spellcheck_languages_menu
(EHTMLEditor *editor,
const gchar * const *languages);
diff --git a/src/e-util/e-html-editor.c b/src/e-util/e-html-editor.c
index 019a66ee5b..07767f54e9 100644
--- a/src/e-util/e-html-editor.c
+++ b/src/e-util/e-html-editor.c
@@ -1074,6 +1074,12 @@ html_editor_dispose (GObject *object)
g_clear_object (&priv->mode_change_content_cancellable);
+ /* Do not unbind/disconnect signal handlers here, just free/unset them */
+ g_slist_free_full (priv->content_editor_bindings, g_object_unref);
+ priv->content_editor_bindings = NULL;
+ priv->subscript_notify_id = 0;
+ priv->superscript_notify_id = 0;
+
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (e_html_editor_parent_class)->dispose (object);
}
@@ -1196,6 +1202,7 @@ e_html_editor_init (EHTMLEditor *editor)
priv = editor->priv;
+ priv->mode = E_CONTENT_EDITOR_MODE_HTML;
priv->manager = gtk_ui_manager_new ();
priv->core_actions = gtk_action_group_new ("core");
priv->core_editor_actions = gtk_action_group_new ("core-editor");
@@ -1230,23 +1237,8 @@ e_html_editor_content_editor_initialized (EContentEditor *content_editor,
g_return_if_fail (E_IS_HTML_EDITOR (html_editor));
g_return_if_fail (content_editor == e_html_editor_get_content_editor (html_editor));
- e_binding_bind_property (
- html_editor->priv->fg_color_combo_box, "current-color",
- content_editor, "font-color",
- G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
- e_binding_bind_property (
- content_editor, "editable",
- html_editor->priv->fg_color_combo_box, "sensitive",
- G_BINDING_SYNC_CREATE);
- e_binding_bind_property (
- html_editor->priv->bg_color_combo_box, "current-color",
- content_editor, "background-color",
- G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
- e_binding_bind_property (
- content_editor, "editable",
- html_editor->priv->bg_color_combo_box, "sensitive",
- G_BINDING_SYNC_CREATE);
- e_html_editor_actions_bind (html_editor);
+ /* Synchronize widget mode with the buttons */
+ e_html_editor_set_mode (html_editor, E_CONTENT_EDITOR_MODE_HTML);
g_object_set (G_OBJECT (content_editor),
"halign", GTK_ALIGN_FILL,
@@ -1689,6 +1681,8 @@ e_html_editor_update_content_on_mode_change_cb (GObject *source_object,
}
}
+ e_content_editor_clear_undo_redo_history (editor->priv->use_content_editor);
+
e_content_editor_util_free_content_hash (content_hash);
}
@@ -1731,7 +1725,8 @@ e_html_editor_set_mode (EHTMLEditor *editor,
if (mode == E_CONTENT_EDITOR_MODE_UNKNOWN)
mode = E_CONTENT_EDITOR_MODE_PLAIN_TEXT;
- if (editor->priv->mode == mode)
+ /* In case the same mode is set, but no editor is assigned, then assign it */
+ if (editor->priv->mode == mode && editor->priv->use_content_editor != NULL)
return;
if (editor->priv->mode_change_content_cancellable) {
@@ -1742,11 +1737,15 @@ e_html_editor_set_mode (EHTMLEditor *editor,
cnt_editor = e_html_editor_get_content_editor_for_mode (editor, mode);
if (cnt_editor) {
- if (cnt_editor != editor->priv->use_content_editor) {
+ gboolean editor_changed = cnt_editor != editor->priv->use_content_editor;
+
+ if (editor_changed) {
EContentEditorInterface *iface;
gboolean is_focused = FALSE;
if (editor->priv->use_content_editor) {
+ e_html_editor_actions_unbind (editor);
+
is_focused = e_content_editor_is_focus (editor->priv->use_content_editor);
editor->priv->mode_change_content_cancellable = g_cancellable_new ();
@@ -1811,6 +1810,9 @@ e_html_editor_set_mode (EHTMLEditor *editor,
editor->priv->mode = mode;
editor->priv->use_content_editor = cnt_editor;
+ if (editor_changed)
+ e_html_editor_actions_bind (editor);
+
g_object_set (G_OBJECT (cnt_editor), "mode", mode, NULL);
g_object_notify (G_OBJECT (editor), "mode");
}
diff --git a/src/e-util/e-markdown-editor.c b/src/e-util/e-markdown-editor.c
index 4771e35c37..7c1f7b50f9 100644
--- a/src/e-util/e-markdown-editor.c
+++ b/src/e-util/e-markdown-editor.c
@@ -443,6 +443,9 @@ e_markdown_editor_clear_undo_redo_history (EContentEditor *cnt_editor)
EMarkdownEditor *self = E_MARKDOWN_EDITOR (cnt_editor);
e_widget_undo_reset (GTK_WIDGET (self->priv->text_view));
+
+ g_object_notify (G_OBJECT (self), "can-undo");
+ g_object_notify (G_OBJECT (self), "can-redo");
}
static void
@@ -1263,7 +1266,7 @@ e_markdown_editor_get_property (GObject *object,
return;
case PROP_FONT_SIZE:
- g_value_set_int (value, 0);
+ g_value_set_int (value, E_CONTENT_EDITOR_FONT_SIZE_NORMAL);
return;
case PROP_INDENT_LEVEL:
diff --git a/src/mail/e-mail-notes.c b/src/mail/e-mail-notes.c
index 4bddbdd202..edca97ef6d 100644
--- a/src/mail/e-mail-notes.c
+++ b/src/mail/e-mail-notes.c
@@ -49,6 +49,7 @@ struct _EMailNotesEditor {
EAttachmentPaned *attachment_paned; /* not referenced */
EFocusTracker *focus_tracker;
GtkActionGroup *action_group;
+ GBinding *attachment_paned_binding;
gboolean had_message;
CamelMimeMessage *message;
@@ -954,15 +955,58 @@ action_save_and_close_cb (GtkAction *action,
mail_notes_get_content_ready_cb, scd);
}
+static void
+notes_editor_notify_mode_cb (GObject *object,
+ GParamSpec *param,
+ EMailNotesEditor *notes_editor)
+{
+ g_return_if_fail (E_IS_MAIL_NOTES_EDITOR (notes_editor));
+
+ if (notes_editor->attachment_paned_binding) {
+ g_binding_unbind (notes_editor->attachment_paned_binding);
+ g_clear_object (¬es_editor->attachment_paned_binding);
+ }
+
+ if (notes_editor->editor) {
+ EContentEditor *cnt_editor;
+
+ cnt_editor = e_html_editor_get_content_editor (notes_editor->editor);
+
+ if (cnt_editor) {
+ EActivityBar *activity_bar;
+ gboolean can_edit;
+
+ activity_bar = e_html_editor_get_activity_bar (notes_editor->editor);
+ can_edit = notes_editor->had_message && !e_activity_bar_get_activity (activity_bar);
+
+ g_object_set (cnt_editor, "editable", can_edit, NULL);
+
+ notes_editor->attachment_paned_binding = g_object_ref (e_binding_bind_property (
+ cnt_editor, "editable",
+ notes_editor->attachment_paned, "sensitive",
+ G_BINDING_SYNC_CREATE));
+ }
+ }
+}
+
static void
e_mail_notes_editor_dispose (GObject *object)
{
EMailNotesEditor *notes_editor = E_MAIL_NOTES_EDITOR (object);
- notes_editor->editor = NULL;
+ if (notes_editor->editor) {
+ EActivityBar *activity_bar;
+
+ activity_bar = e_html_editor_get_activity_bar (notes_editor->editor);
+ g_signal_handlers_disconnect_by_func (activity_bar,
+ G_CALLBACK (notes_editor_update_editable_on_notify_cb), notes_editor);
+
+ notes_editor->editor = NULL;
+ }
g_clear_object (¬es_editor->focus_tracker);
g_clear_object (¬es_editor->action_group);
+ g_clear_object (¬es_editor->attachment_paned_binding);
/* Chain up to parent's method */
G_OBJECT_CLASS (e_mail_notes_editor_parent_class)->dispose (object);
@@ -1143,10 +1187,10 @@ e_mail_notes_editor_new_with_editor (EHTMLEditor *html_editor,
notes_editor->attachment_paned = E_ATTACHMENT_PANED (widget);
gtk_widget_show (widget);
- e_binding_bind_property (
+ notes_editor->attachment_paned_binding = g_object_ref (e_binding_bind_property (
cnt_editor, "editable",
widget, "sensitive",
- G_BINDING_SYNC_CREATE);
+ G_BINDING_SYNC_CREATE));
/* Configure an EFocusTracker to manage selection actions. */
focus_tracker = e_focus_tracker_new (GTK_WINDOW (notes_editor));
@@ -1171,8 +1215,10 @@ e_mail_notes_editor_new_with_editor (EHTMLEditor *html_editor,
activity_bar = e_html_editor_get_activity_bar (notes_editor->editor);
- g_signal_connect_object (activity_bar, "notify::activity",
- G_CALLBACK (notes_editor_update_editable_on_notify_cb), notes_editor, 0);
+ g_signal_connect (activity_bar, "notify::activity",
+ G_CALLBACK (notes_editor_update_editable_on_notify_cb), notes_editor);
+ g_signal_connect_object (notes_editor->editor, "notify::mode",
+ G_CALLBACK (notes_editor_notify_mode_cb), notes_editor, 0);
notes_editor->folder = g_object_ref (folder);
notes_editor->uid = g_strdup (uid);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]