16117 lines
447 KiB
Diff
16117 lines
447 KiB
Diff
Description: Use Command as primary modifier key
|
||
Origin: Callisto Desktop
|
||
Author: Maia <maia@tsundoku.ne.jp>
|
||
Last-Update: 2025-06-07 evolution-3.46.4
|
||
|
||
diff -urN a/src/addressbook/gui/contact-editor/e-contact-editor.c b/src/addressbook/gui/contact-editor/e-contact-editor.c
|
||
--- a/src/addressbook/gui/contact-editor/e-contact-editor.c 2025-06-07 14:20:57.255396309 -0700
|
||
+++ b/src/addressbook/gui/contact-editor/e-contact-editor.c 2025-06-07 14:27:24.031672803 -0700
|
||
@@ -262,14 +262,14 @@
|
||
{ "undo",
|
||
"edit-undo",
|
||
N_("_Undo"),
|
||
- "<Control>z",
|
||
+ "<Super>z",
|
||
N_("Undo"),
|
||
NULL }, /* Handled by EFocusTracker */
|
||
|
||
{ "redo",
|
||
"edit-redo",
|
||
N_("_Redo"),
|
||
- "<Control>y",
|
||
+ "<Super>y",
|
||
N_("Redo"),
|
||
NULL } /* Handled by EFocusTracker */
|
||
|
||
diff -urN a/src/addressbook/gui/widgets/eab-contact-display.c b/src/addressbook/gui/widgets/eab-contact-display.c
|
||
--- a/src/addressbook/gui/widgets/eab-contact-display.c 2025-06-07 14:20:57.263396404 -0700
|
||
+++ b/src/addressbook/gui/widgets/eab-contact-display.c 2025-06-07 14:27:24.031672803 -0700
|
||
@@ -184,7 +184,7 @@
|
||
{ "contact-mailto-copy",
|
||
"edit-copy",
|
||
N_("Copy _Email Address"),
|
||
- "<Control>c",
|
||
+ "<Super>c",
|
||
N_("Copy the email address to the clipboard"),
|
||
G_CALLBACK (action_contact_mailto_copy_cb) },
|
||
|
||
diff -urN a/src/calendar/gui/e-comp-editor-event.c b/src/calendar/gui/e-comp-editor-event.c
|
||
--- a/src/calendar/gui/e-comp-editor-event.c 2025-06-07 14:20:57.267396453 -0700
|
||
+++ b/src/calendar/gui/e-comp-editor-event.c 2025-06-07 14:27:24.031672803 -0700
|
||
@@ -781,7 +781,7 @@
|
||
{ "all-day-event",
|
||
"stock_new-24h-appointment",
|
||
N_("All _Day Event"),
|
||
- "<Control>Y",
|
||
+ "<Super>Y",
|
||
N_("Toggles whether to have All Day Event"),
|
||
NULL,
|
||
FALSE },
|
||
diff -urN a/src/calendar/gui/e-comp-editor-event.c.orig b/src/calendar/gui/e-comp-editor-event.c.orig
|
||
--- a/src/calendar/gui/e-comp-editor-event.c.orig 1969-12-31 16:00:00.000000000 -0800
|
||
+++ b/src/calendar/gui/e-comp-editor-event.c.orig 2025-06-07 14:20:57.267396453 -0700
|
||
@@ -0,0 +1,1079 @@
|
||
+/*
|
||
+ * Copyright (C) 2015 Red Hat, Inc. (www.redhat.com)
|
||
+ *
|
||
+ * This program is free software: you can redistribute it and/or modify it
|
||
+ * under the terms of the GNU General Public License as published by
|
||
+ * the Free Software Foundation.
|
||
+ *
|
||
+ * This program is distributed in the hope that it will be useful, but
|
||
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||
+ * for more details.
|
||
+ *
|
||
+ * You should have received a copy of the GNU General Public License
|
||
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
+ *
|
||
+ */
|
||
+
|
||
+#include "evolution-config.h"
|
||
+
|
||
+#include <glib/gi18n-lib.h>
|
||
+#include <gtk/gtk.h>
|
||
+
|
||
+#include <e-util/e-util.h>
|
||
+
|
||
+#include "calendar-config.h"
|
||
+#include "comp-util.h"
|
||
+#include "e-comp-editor.h"
|
||
+#include "e-comp-editor-page.h"
|
||
+#include "e-comp-editor-page-attachments.h"
|
||
+#include "e-comp-editor-page-general.h"
|
||
+#include "e-comp-editor-page-recurrence.h"
|
||
+#include "e-comp-editor-page-reminders.h"
|
||
+#include "e-comp-editor-page-schedule.h"
|
||
+#include "e-comp-editor-property-parts.h"
|
||
+#include "e-timezone-entry.h"
|
||
+
|
||
+#include "e-comp-editor-event.h"
|
||
+
|
||
+struct _ECompEditorEventPrivate {
|
||
+ ECompEditorPage *page_general;
|
||
+ ECompEditorPropertyPart *dtstart;
|
||
+ ECompEditorPropertyPart *dtend;
|
||
+ ECompEditorPropertyPart *categories;
|
||
+ ECompEditorPropertyPart *timezone;
|
||
+ ECompEditorPropertyPart *transparency;
|
||
+ ECompEditorPropertyPart *description;
|
||
+ GtkWidget *all_day_check;
|
||
+
|
||
+ gpointer in_the_past_alert;
|
||
+ gpointer insensitive_info_alert;
|
||
+};
|
||
+
|
||
+G_DEFINE_TYPE (ECompEditorEvent, e_comp_editor_event, E_TYPE_COMP_EDITOR)
|
||
+
|
||
+static void
|
||
+ece_event_action_classification_cb (GtkRadioAction *action,
|
||
+ GtkRadioAction *current,
|
||
+ ECompEditorEvent *event_editor)
|
||
+{
|
||
+ g_return_if_fail (E_IS_COMP_EDITOR_EVENT (event_editor));
|
||
+
|
||
+ e_comp_editor_set_changed (E_COMP_EDITOR (event_editor), TRUE);
|
||
+}
|
||
+
|
||
+static void
|
||
+ece_event_update_times (ECompEditorEvent *event_editor,
|
||
+ EDateEdit *date_edit,
|
||
+ gboolean change_end_datetime)
|
||
+{
|
||
+ guint flags;
|
||
+
|
||
+ g_return_if_fail (E_IS_COMP_EDITOR_EVENT (event_editor));
|
||
+ g_return_if_fail (E_IS_DATE_EDIT (date_edit));
|
||
+
|
||
+ if (e_date_edit_has_focus (date_edit) ||
|
||
+ !e_date_edit_date_is_valid (date_edit) ||
|
||
+ !e_date_edit_time_is_valid (date_edit))
|
||
+ return;
|
||
+
|
||
+ if (!e_comp_editor_get_updating (E_COMP_EDITOR (event_editor))) {
|
||
+ e_comp_editor_ensure_start_before_end (E_COMP_EDITOR (event_editor),
|
||
+ event_editor->priv->dtstart,
|
||
+ event_editor->priv->dtend,
|
||
+ change_end_datetime);
|
||
+ e_comp_editor_ensure_same_value_type (E_COMP_EDITOR (event_editor),
|
||
+ change_end_datetime ? event_editor->priv->dtstart : event_editor->priv->dtend,
|
||
+ change_end_datetime ? event_editor->priv->dtend : event_editor->priv->dtstart);
|
||
+ }
|
||
+
|
||
+ flags = e_comp_editor_get_flags (E_COMP_EDITOR (event_editor));
|
||
+
|
||
+ if ((flags & E_COMP_EDITOR_FLAG_IS_NEW) != 0) {
|
||
+ ICalTime *start_tt;
|
||
+
|
||
+ start_tt = e_comp_editor_property_part_datetime_get_value (
|
||
+ E_COMP_EDITOR_PROPERTY_PART_DATETIME (event_editor->priv->dtstart));
|
||
+
|
||
+ if (cal_comp_util_compare_time_with_today (start_tt) < 0) {
|
||
+ if (!event_editor->priv->in_the_past_alert) {
|
||
+ EAlert *alert;
|
||
+
|
||
+ alert = e_comp_editor_add_warning (E_COMP_EDITOR (event_editor),
|
||
+ _("Event’s time is in the past"), NULL);
|
||
+
|
||
+ event_editor->priv->in_the_past_alert = alert;
|
||
+
|
||
+ if (alert)
|
||
+ g_object_add_weak_pointer (G_OBJECT (alert), &event_editor->priv->in_the_past_alert);
|
||
+
|
||
+ g_clear_object (&alert);
|
||
+ }
|
||
+ } else if (event_editor->priv->in_the_past_alert) {
|
||
+ e_alert_response (event_editor->priv->in_the_past_alert, GTK_RESPONSE_OK);
|
||
+ }
|
||
+
|
||
+ g_clear_object (&start_tt);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+ece_event_dtstart_changed_cb (EDateEdit *date_edit,
|
||
+ ECompEditorEvent *event_editor)
|
||
+{
|
||
+ g_return_if_fail (E_IS_DATE_EDIT (date_edit));
|
||
+ g_return_if_fail (E_IS_COMP_EDITOR_EVENT (event_editor));
|
||
+
|
||
+ if (!e_date_edit_has_focus (date_edit))
|
||
+ ece_event_update_times (event_editor, date_edit, TRUE);
|
||
+}
|
||
+
|
||
+static void
|
||
+ece_event_dtend_changed_cb (EDateEdit *date_edit,
|
||
+ ECompEditorEvent *event_editor)
|
||
+{
|
||
+ g_return_if_fail (E_IS_DATE_EDIT (date_edit));
|
||
+ g_return_if_fail (E_IS_COMP_EDITOR_EVENT (event_editor));
|
||
+
|
||
+ if (!e_date_edit_has_focus (date_edit))
|
||
+ ece_event_update_times (event_editor, date_edit, FALSE);
|
||
+}
|
||
+
|
||
+static void
|
||
+ece_event_all_day_toggled_cb (ECompEditorEvent *event_editor)
|
||
+{
|
||
+ GtkWidget *edit_widget;
|
||
+
|
||
+ g_return_if_fail (E_IS_COMP_EDITOR_EVENT (event_editor));
|
||
+
|
||
+ edit_widget = e_comp_editor_property_part_get_edit_widget (event_editor->priv->dtstart);
|
||
+
|
||
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (event_editor->priv->all_day_check))) {
|
||
+ gint hour, minute;
|
||
+
|
||
+ if (!e_date_edit_get_time_of_day (E_DATE_EDIT (edit_widget), &hour, &minute))
|
||
+ e_date_edit_set_time_of_day (E_DATE_EDIT (edit_widget), 0, 0);
|
||
+ }
|
||
+
|
||
+ ece_event_update_times (event_editor, E_DATE_EDIT (edit_widget), TRUE);
|
||
+
|
||
+ e_comp_editor_ensure_changed (E_COMP_EDITOR (event_editor));
|
||
+}
|
||
+
|
||
+static void
|
||
+ece_event_sensitize_widgets (ECompEditor *comp_editor,
|
||
+ gboolean force_insensitive)
|
||
+{
|
||
+ ECompEditorEvent *event_editor;
|
||
+ gboolean is_organizer;
|
||
+ GtkAction *action;
|
||
+ GtkWidget *widget;
|
||
+ guint32 flags;
|
||
+
|
||
+ g_return_if_fail (E_IS_COMP_EDITOR_EVENT (comp_editor));
|
||
+
|
||
+ E_COMP_EDITOR_CLASS (e_comp_editor_event_parent_class)->sensitize_widgets (comp_editor, force_insensitive);
|
||
+
|
||
+ flags = e_comp_editor_get_flags (comp_editor);
|
||
+ is_organizer = (flags & (E_COMP_EDITOR_FLAG_IS_NEW | E_COMP_EDITOR_FLAG_ORGANIZER_IS_USER)) != 0;
|
||
+ event_editor = E_COMP_EDITOR_EVENT (comp_editor);
|
||
+
|
||
+ gtk_widget_set_sensitive (event_editor->priv->all_day_check, !force_insensitive);
|
||
+
|
||
+ #define sensitize_part(x) G_STMT_START { \
|
||
+ widget = e_comp_editor_property_part_get_label_widget (x); \
|
||
+ if (widget) \
|
||
+ gtk_widget_set_sensitive (widget, !force_insensitive); \
|
||
+ \
|
||
+ widget = e_comp_editor_property_part_get_edit_widget (x); \
|
||
+ if (widget) \
|
||
+ gtk_widget_set_sensitive (widget, !force_insensitive); \
|
||
+ } G_STMT_END
|
||
+
|
||
+ sensitize_part (event_editor->priv->dtstart);
|
||
+ sensitize_part (event_editor->priv->dtend);
|
||
+ sensitize_part (event_editor->priv->timezone);
|
||
+
|
||
+ #undef sensitize_part
|
||
+
|
||
+ action = e_comp_editor_get_action (comp_editor, "all-day-event");
|
||
+ gtk_action_set_sensitive (action, !force_insensitive);
|
||
+
|
||
+ action = e_comp_editor_get_action (comp_editor, "classification-menu");
|
||
+ gtk_action_set_sensitive (action, !force_insensitive);
|
||
+
|
||
+ if (event_editor->priv->insensitive_info_alert)
|
||
+ e_alert_response (event_editor->priv->insensitive_info_alert, GTK_RESPONSE_OK);
|
||
+
|
||
+ if (force_insensitive || !is_organizer) {
|
||
+ ECalClient *client;
|
||
+ const gchar *message = NULL;
|
||
+
|
||
+ client = e_comp_editor_get_target_client (comp_editor);
|
||
+ if (!client)
|
||
+ message = _("Event cannot be edited, because the selected calendar could not be opened");
|
||
+ else if (e_client_is_readonly (E_CLIENT (client)))
|
||
+ message = _("Event cannot be edited, because the selected calendar is read only");
|
||
+ else if (!is_organizer)
|
||
+ message = _("Changes made to the event will not be sent to the attendees, because you are not the organizer");
|
||
+
|
||
+ if (message) {
|
||
+ EAlert *alert;
|
||
+
|
||
+ alert = e_comp_editor_add_information (comp_editor, message, NULL);
|
||
+
|
||
+ event_editor->priv->insensitive_info_alert = alert;
|
||
+
|
||
+ if (alert)
|
||
+ g_object_add_weak_pointer (G_OBJECT (alert), &event_editor->priv->insensitive_info_alert);
|
||
+
|
||
+ g_clear_object (&alert);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+static ICalTimezone *
|
||
+ece_event_get_timezone_from_property (ECompEditor *comp_editor,
|
||
+ ICalProperty *property)
|
||
+{
|
||
+ ECalClient *client;
|
||
+ ICalParameter *param;
|
||
+ ICalTimezone *zone = NULL;
|
||
+ const gchar *tzid;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
|
||
+
|
||
+ if (!property)
|
||
+ return NULL;
|
||
+
|
||
+ param = i_cal_property_get_first_parameter (property, I_CAL_TZID_PARAMETER);
|
||
+ if (!param)
|
||
+ return NULL;
|
||
+
|
||
+ tzid = i_cal_parameter_get_tzid (param);
|
||
+ if (!tzid || !*tzid) {
|
||
+ g_object_unref (param);
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ if (g_ascii_strcasecmp (tzid, "UTC") == 0) {
|
||
+ g_object_unref (param);
|
||
+ return i_cal_timezone_get_utc_timezone ();
|
||
+ }
|
||
+
|
||
+ client = e_comp_editor_get_source_client (comp_editor);
|
||
+ /* It should be already fetched for the UI, thus this should be non-blocking. */
|
||
+ if (client && e_cal_client_get_timezone_sync (client, tzid, &zone, NULL, NULL) && zone) {
|
||
+ g_object_unref (param);
|
||
+ return zone;
|
||
+ }
|
||
+
|
||
+ zone = i_cal_timezone_get_builtin_timezone_from_tzid (tzid);
|
||
+ if (!zone)
|
||
+ zone = i_cal_timezone_get_builtin_timezone (tzid);
|
||
+
|
||
+ g_object_unref (param);
|
||
+
|
||
+ return zone;
|
||
+}
|
||
+
|
||
+static void
|
||
+ece_event_update_timezone (ECompEditorEvent *event_editor,
|
||
+ ICalTime **out_dtstart,
|
||
+ ICalTime **out_dtend)
|
||
+{
|
||
+ ECompEditor *comp_editor;
|
||
+ ICalTime *dtstart = NULL, *dtend = NULL;
|
||
+ ICalComponent *component;
|
||
+ ICalProperty *prop;
|
||
+ ICalTimezone *zone = NULL;
|
||
+ gboolean has_property = FALSE, is_date_value = FALSE;
|
||
+
|
||
+ g_return_if_fail (E_IS_COMP_EDITOR_EVENT (event_editor));
|
||
+
|
||
+ comp_editor = E_COMP_EDITOR (event_editor);
|
||
+
|
||
+ component = e_comp_editor_get_component (comp_editor);
|
||
+ if (!component) {
|
||
+ if (out_dtstart)
|
||
+ *out_dtstart = NULL;
|
||
+
|
||
+ if (out_dtend)
|
||
+ *out_dtend = NULL;
|
||
+
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ if (e_cal_util_component_has_property (component, I_CAL_DTSTART_PROPERTY)) {
|
||
+ has_property = TRUE;
|
||
+
|
||
+ dtstart = i_cal_component_get_dtstart (component);
|
||
+ if (dtstart && i_cal_time_is_valid_time (dtstart)) {
|
||
+ if (i_cal_time_is_date (dtstart)) {
|
||
+ zone = NULL;
|
||
+ is_date_value = TRUE;
|
||
+ } else if (i_cal_time_is_utc (dtstart)) {
|
||
+ zone = i_cal_timezone_get_utc_timezone ();
|
||
+ } else {
|
||
+ prop = i_cal_component_get_first_property (component, I_CAL_DTSTART_PROPERTY);
|
||
+ zone = ece_event_get_timezone_from_property (comp_editor, prop);
|
||
+ g_clear_object (&prop);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (e_cal_util_component_has_property (component, I_CAL_DTEND_PROPERTY)) {
|
||
+ has_property = TRUE;
|
||
+
|
||
+ dtend = i_cal_component_get_dtend (component);
|
||
+ if (!zone && i_cal_time_is_valid_time (dtend)) {
|
||
+ if (i_cal_time_is_date (dtend)) {
|
||
+ zone = NULL;
|
||
+ is_date_value = TRUE;
|
||
+ } else if (i_cal_time_is_utc (dtend)) {
|
||
+ zone = i_cal_timezone_get_utc_timezone ();
|
||
+ } else {
|
||
+ prop = i_cal_component_get_first_property (component, I_CAL_DTEND_PROPERTY);
|
||
+ zone = ece_event_get_timezone_from_property (comp_editor, prop);
|
||
+ g_clear_object (&prop);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (!zone && e_cal_util_component_has_property (component, I_CAL_DUE_PROPERTY)) {
|
||
+ ICalTime *itt;
|
||
+
|
||
+ has_property = TRUE;
|
||
+
|
||
+ itt = i_cal_component_get_due (component);
|
||
+ if (itt && i_cal_time_is_valid_time (itt)) {
|
||
+ if (i_cal_time_is_date (itt)) {
|
||
+ zone = NULL;
|
||
+ is_date_value = TRUE;
|
||
+ } else if (i_cal_time_is_utc (itt)) {
|
||
+ zone = i_cal_timezone_get_utc_timezone ();
|
||
+ } else {
|
||
+ prop = i_cal_component_get_first_property (component, I_CAL_DUE_PROPERTY);
|
||
+ zone = ece_event_get_timezone_from_property (comp_editor, prop);
|
||
+ g_clear_object (&prop);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ g_clear_object (&itt);
|
||
+ }
|
||
+
|
||
+ if (has_property) {
|
||
+ GtkWidget *edit_widget;
|
||
+ ICalTimezone *cfg_zone;
|
||
+
|
||
+ edit_widget = e_comp_editor_property_part_get_edit_widget (event_editor->priv->timezone);
|
||
+
|
||
+ if (!zone && is_date_value)
|
||
+ e_timezone_entry_set_timezone (E_TIMEZONE_ENTRY (edit_widget), calendar_config_get_icaltimezone ());
|
||
+ else
|
||
+ e_timezone_entry_set_timezone (E_TIMEZONE_ENTRY (edit_widget), zone);
|
||
+
|
||
+ cfg_zone = calendar_config_get_icaltimezone ();
|
||
+
|
||
+ if (zone && cfg_zone && zone != cfg_zone &&
|
||
+ (g_strcmp0 (i_cal_timezone_get_location (zone), i_cal_timezone_get_location (cfg_zone)) != 0 ||
|
||
+ g_strcmp0 (i_cal_timezone_get_tzid (zone), i_cal_timezone_get_tzid (cfg_zone)) != 0)) {
|
||
+ /* Show timezone part */
|
||
+ GtkAction *action;
|
||
+
|
||
+ action = e_comp_editor_get_action (comp_editor, "view-timezone");
|
||
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (out_dtstart)
|
||
+ *out_dtstart = dtstart;
|
||
+ else
|
||
+ g_clear_object (&dtstart);
|
||
+
|
||
+ if (out_dtend)
|
||
+ *out_dtend = dtend;
|
||
+ else
|
||
+ g_clear_object (&dtend);
|
||
+}
|
||
+
|
||
+static void
|
||
+ece_event_fill_widgets (ECompEditor *comp_editor,
|
||
+ ICalComponent *component)
|
||
+{
|
||
+ ECompEditorEvent *event_editor;
|
||
+ ICalTime *dtstart, *dtend;
|
||
+ ICalProperty *prop;
|
||
+ gboolean all_day_event = FALSE;
|
||
+ GtkAction *action;
|
||
+ guint32 flags;
|
||
+
|
||
+ g_return_if_fail (E_IS_COMP_EDITOR_EVENT (comp_editor));
|
||
+ g_return_if_fail (component != NULL);
|
||
+
|
||
+ event_editor = E_COMP_EDITOR_EVENT (comp_editor);
|
||
+
|
||
+ flags = e_comp_editor_get_flags (comp_editor);
|
||
+ dtstart = NULL;
|
||
+ dtend = NULL;
|
||
+
|
||
+ /* Set timezone before the times, because they are converted into this timezone */
|
||
+ ece_event_update_timezone (event_editor, &dtstart, &dtend);
|
||
+
|
||
+ E_COMP_EDITOR_CLASS (e_comp_editor_event_parent_class)->fill_widgets (comp_editor, component);
|
||
+
|
||
+ if (dtstart && i_cal_time_is_valid_time (dtstart) && !i_cal_time_is_null_time (dtstart) &&
|
||
+ (!dtend || !i_cal_time_is_valid_time (dtend) || i_cal_time_is_null_time (dtend))) {
|
||
+ gboolean dtend_set = FALSE;
|
||
+ g_clear_object (&dtend);
|
||
+ dtend = i_cal_time_clone (dtstart);
|
||
+
|
||
+ if (e_cal_util_component_has_property (component, I_CAL_DURATION_PROPERTY)) {
|
||
+ ICalProperty *prop;
|
||
+
|
||
+ prop = i_cal_component_get_first_property (component, I_CAL_DURATION_PROPERTY);
|
||
+ if (prop) {
|
||
+ ICalDuration *duration;
|
||
+
|
||
+ g_clear_object (&prop);
|
||
+
|
||
+ duration = i_cal_component_get_duration (component);
|
||
+ if (!duration || i_cal_duration_is_null_duration (duration) || i_cal_duration_is_bad_duration (duration)) {
|
||
+ g_clear_object (&duration);
|
||
+ /* The DURATION shouldn't be negative, but just return DTSTART if it
|
||
+ * is, i.e. assume it is 0. */
|
||
+ } else if (!i_cal_duration_is_neg (duration)) {
|
||
+ guint dur_days, dur_hours, dur_minutes, dur_seconds;
|
||
+
|
||
+ /* If DTSTART is a DATE value, then we need to check if the DURATION
|
||
+ * includes any hours, minutes or seconds. If it does, we need to
|
||
+ * make the DTEND/DUE a DATE-TIME value. */
|
||
+ dur_days = i_cal_duration_get_days (duration) + (7 * i_cal_duration_get_weeks (duration));
|
||
+ dur_hours = i_cal_duration_get_hours (duration);
|
||
+ dur_minutes = i_cal_duration_get_minutes (duration);
|
||
+ dur_seconds = i_cal_duration_get_seconds (duration);
|
||
+
|
||
+ if (i_cal_time_is_date (dtend) && (
|
||
+ dur_hours != 0 || dur_minutes != 0 || dur_seconds != 0)) {
|
||
+ i_cal_time_set_is_date (dtend, FALSE);
|
||
+ }
|
||
+
|
||
+ /* Add on the DURATION. */
|
||
+ i_cal_time_adjust (dtend, dur_days, dur_hours, dur_minutes, dur_seconds);
|
||
+
|
||
+ dtend_set = TRUE;
|
||
+ }
|
||
+
|
||
+ g_clear_object (&duration);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (!dtend_set && i_cal_time_is_date (dtstart))
|
||
+ i_cal_time_adjust (dtend, 1, 0, 0, 0);
|
||
+ }
|
||
+
|
||
+ if (dtend && i_cal_time_is_valid_time (dtend) && !i_cal_time_is_null_time (dtend)) {
|
||
+ if (i_cal_time_is_date (dtstart) && i_cal_time_is_date (dtend)) {
|
||
+ all_day_event = TRUE;
|
||
+ if (i_cal_time_compare_date_only (dtend, dtstart) > 0) {
|
||
+ i_cal_time_adjust (dtend, -1, 0, 0, 0);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ e_comp_editor_property_part_datetime_set_value (
|
||
+ E_COMP_EDITOR_PROPERTY_PART_DATETIME (event_editor->priv->dtend), dtend);
|
||
+ }
|
||
+
|
||
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (event_editor->priv->all_day_check), all_day_event);
|
||
+
|
||
+ prop = i_cal_component_get_first_property (component, I_CAL_CLASS_PROPERTY);
|
||
+ if (prop && i_cal_property_get_class (prop) == I_CAL_CLASS_PRIVATE)
|
||
+ action = e_comp_editor_get_action (comp_editor, "classify-private");
|
||
+ else if (prop && i_cal_property_get_class (prop) == I_CAL_CLASS_CONFIDENTIAL)
|
||
+ action = e_comp_editor_get_action (comp_editor, "classify-confidential");
|
||
+ else if (!(flags & E_COMP_EDITOR_FLAG_IS_NEW))
|
||
+ action = e_comp_editor_get_action (comp_editor, "classify-public");
|
||
+ else {
|
||
+ GSettings *settings;
|
||
+
|
||
+ settings = e_util_ref_settings ("org.gnome.evolution.calendar");
|
||
+
|
||
+ if (g_settings_get_boolean (settings, "classify-private")) {
|
||
+ action = e_comp_editor_get_action (comp_editor, "classify-private");
|
||
+ } else {
|
||
+ action = e_comp_editor_get_action (comp_editor, "classify-public");
|
||
+ }
|
||
+
|
||
+ g_object_unref (settings);
|
||
+ }
|
||
+
|
||
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
|
||
+
|
||
+ g_clear_object (&dtstart);
|
||
+ g_clear_object (&dtend);
|
||
+ g_clear_object (&prop);
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+ece_event_client_needs_all_day_as_time (ECompEditor *comp_editor)
|
||
+{
|
||
+ ECalClient *client;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), FALSE);
|
||
+
|
||
+ client = e_comp_editor_get_target_client (comp_editor);
|
||
+
|
||
+ return client && e_client_check_capability (E_CLIENT (client), E_CAL_STATIC_CAPABILITY_ALL_DAY_EVENT_AS_TIME);
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+ece_event_fill_component (ECompEditor *comp_editor,
|
||
+ ICalComponent *component)
|
||
+{
|
||
+ ECompEditorEvent *event_editor;
|
||
+ gboolean date_valid, time_valid;
|
||
+ ICalProperty *dtstart_prop, *dtend_prop;
|
||
+ ICalProperty *prop;
|
||
+ ICalProperty_Class class_value;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), FALSE);
|
||
+ g_return_val_if_fail (I_CAL_IS_COMPONENT (component), FALSE);
|
||
+
|
||
+ if (!E_COMP_EDITOR_CLASS (e_comp_editor_event_parent_class)->fill_component (comp_editor, component))
|
||
+ return FALSE;
|
||
+
|
||
+ event_editor = E_COMP_EDITOR_EVENT (comp_editor);
|
||
+
|
||
+ if (!e_comp_editor_property_part_datetime_check_validity (
|
||
+ E_COMP_EDITOR_PROPERTY_PART_DATETIME (event_editor->priv->dtstart), &date_valid, &time_valid)) {
|
||
+ const gchar *error_message = NULL;
|
||
+
|
||
+ if (!date_valid)
|
||
+ error_message = g_strdup (_("Start date is not a valid date"));
|
||
+ else if (!time_valid)
|
||
+ error_message = g_strdup (_("Start time is not a valid time"));
|
||
+
|
||
+ e_comp_editor_set_validation_error (comp_editor, event_editor->priv->page_general,
|
||
+ e_comp_editor_property_part_get_edit_widget (event_editor->priv->dtstart),
|
||
+ error_message ? error_message : _("Unknown error"));
|
||
+
|
||
+ return FALSE;
|
||
+ }
|
||
+
|
||
+ if (!e_comp_editor_property_part_datetime_check_validity (
|
||
+ E_COMP_EDITOR_PROPERTY_PART_DATETIME (event_editor->priv->dtend), &date_valid, &time_valid)) {
|
||
+ const gchar *error_message = NULL;
|
||
+
|
||
+ if (!date_valid)
|
||
+ error_message = g_strdup (_("End date is not a valid date"));
|
||
+ else if (!time_valid)
|
||
+ error_message = g_strdup (_("End time is not a valid time"));
|
||
+
|
||
+ e_comp_editor_set_validation_error (comp_editor, event_editor->priv->page_general,
|
||
+ e_comp_editor_property_part_get_edit_widget (event_editor->priv->dtend),
|
||
+ error_message ? error_message : _("Unknown error"));
|
||
+
|
||
+ return FALSE;
|
||
+ }
|
||
+
|
||
+ dtstart_prop = i_cal_component_get_first_property (component, I_CAL_DTSTART_PROPERTY);
|
||
+ dtend_prop = i_cal_component_get_first_property (component, I_CAL_DTEND_PROPERTY);
|
||
+
|
||
+ if (dtstart_prop && dtend_prop) {
|
||
+ ICalTime *dtstart, *dtend;
|
||
+ gboolean set_dtstart = FALSE, set_dtend = FALSE;
|
||
+
|
||
+ dtstart = i_cal_property_get_dtstart (dtstart_prop);
|
||
+ dtend = i_cal_property_get_dtend (dtend_prop);
|
||
+
|
||
+ if (dtstart && i_cal_time_is_date (dtstart) &&
|
||
+ dtend && i_cal_time_is_date (dtend)) {
|
||
+ /* Add 1 day to DTEND, as it is not inclusive. */
|
||
+ i_cal_time_adjust (dtend, 1, 0, 0, 0);
|
||
+ set_dtend = TRUE;
|
||
+
|
||
+ if (ece_event_client_needs_all_day_as_time (comp_editor)) {
|
||
+ ECompEditorEvent *event_editor = E_COMP_EDITOR_EVENT (comp_editor);
|
||
+ GtkWidget *timezone_entry;
|
||
+ ICalTimezone *zone;
|
||
+
|
||
+ timezone_entry = e_comp_editor_property_part_get_edit_widget (event_editor->priv->timezone);
|
||
+ zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (timezone_entry));
|
||
+
|
||
+ cal_comp_util_ensure_allday_timezone (dtstart, zone);
|
||
+ cal_comp_util_ensure_allday_timezone (dtend, zone);
|
||
+
|
||
+ set_dtstart = TRUE;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (set_dtstart) {
|
||
+ /* Remove the VALUE parameter, to correspond to the actual value being set */
|
||
+ i_cal_property_remove_parameter_by_kind (dtstart_prop, I_CAL_VALUE_PARAMETER);
|
||
+
|
||
+ i_cal_property_set_dtstart (dtstart_prop, dtstart);
|
||
+ cal_comp_util_update_tzid_parameter (dtstart_prop, dtstart);
|
||
+ }
|
||
+
|
||
+ if (set_dtend) {
|
||
+ /* Remove the VALUE parameter, to correspond to the actual value being set */
|
||
+ i_cal_property_remove_parameter_by_kind (dtend_prop, I_CAL_VALUE_PARAMETER);
|
||
+
|
||
+ i_cal_property_set_dtend (dtend_prop, dtend);
|
||
+ cal_comp_util_update_tzid_parameter (dtend_prop, dtend);
|
||
+
|
||
+ e_cal_util_component_remove_property_by_kind (component, I_CAL_DURATION_PROPERTY, TRUE);
|
||
+ }
|
||
+
|
||
+ g_clear_object (&dtstart);
|
||
+ g_clear_object (&dtend);
|
||
+ }
|
||
+
|
||
+ g_clear_object (&dtstart_prop);
|
||
+ g_clear_object (&dtend_prop);
|
||
+
|
||
+ if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (
|
||
+ e_comp_editor_get_action (comp_editor, "classify-private"))))
|
||
+ class_value = I_CAL_CLASS_PRIVATE;
|
||
+ else if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (
|
||
+ e_comp_editor_get_action (comp_editor, "classify-confidential"))))
|
||
+ class_value = I_CAL_CLASS_CONFIDENTIAL;
|
||
+ else
|
||
+ class_value = I_CAL_CLASS_PUBLIC;
|
||
+
|
||
+ prop = i_cal_component_get_first_property (component, I_CAL_CLASS_PROPERTY);
|
||
+ if (prop) {
|
||
+ i_cal_property_set_class (prop, class_value);
|
||
+ g_object_unref (prop);
|
||
+ } else {
|
||
+ prop = i_cal_property_new_class (class_value);
|
||
+ i_cal_component_take_property (component, prop);
|
||
+ }
|
||
+
|
||
+ return TRUE;
|
||
+}
|
||
+
|
||
+static void
|
||
+ece_event_notify_source_client_cb (GObject *object,
|
||
+ GParamSpec *param,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ g_return_if_fail (E_IS_COMP_EDITOR_EVENT (object));
|
||
+
|
||
+ ece_event_update_timezone (E_COMP_EDITOR_EVENT (object), NULL, NULL);
|
||
+}
|
||
+
|
||
+static void
|
||
+ece_event_notify_target_client_cb (GObject *object,
|
||
+ GParamSpec *param,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ ECompEditorEvent *event_editor;
|
||
+ GtkAction *action;
|
||
+
|
||
+ g_return_if_fail (E_IS_COMP_EDITOR_EVENT (object));
|
||
+
|
||
+ event_editor = E_COMP_EDITOR_EVENT (object);
|
||
+ action = e_comp_editor_get_action (E_COMP_EDITOR (event_editor), "view-timezone");
|
||
+
|
||
+ /* These influence whether the timezone part is visible and they
|
||
+ depend on the target's client ece_event_client_needs_all_day_as_time() */
|
||
+ g_object_notify (G_OBJECT (action), "active");
|
||
+ g_object_notify (G_OBJECT (event_editor->priv->all_day_check), "active");
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+transform_action_to_timezone_visible_cb (GBinding *binding,
|
||
+ const GValue *from_value,
|
||
+ GValue *to_value,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ ECompEditorEvent *event_editor = user_data;
|
||
+ GtkToggleButton *all_day_check = GTK_TOGGLE_BUTTON (event_editor->priv->all_day_check);
|
||
+
|
||
+ g_value_set_boolean (to_value,
|
||
+ g_value_get_boolean (from_value) &&
|
||
+ (!gtk_toggle_button_get_active (all_day_check) || ece_event_client_needs_all_day_as_time (E_COMP_EDITOR (event_editor))));
|
||
+
|
||
+ return TRUE;
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+transform_toggle_to_timezone_visible_cb (GBinding *binding,
|
||
+ const GValue *from_value,
|
||
+ GValue *to_value,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ ECompEditor *comp_editor = user_data;
|
||
+ GtkToggleAction *action = GTK_TOGGLE_ACTION (e_comp_editor_get_action (comp_editor, "view-timezone"));
|
||
+
|
||
+ g_value_set_boolean (to_value,
|
||
+ gtk_toggle_action_get_active (action) &&
|
||
+ (!g_value_get_boolean (from_value) || ece_event_client_needs_all_day_as_time (comp_editor)));
|
||
+
|
||
+ return TRUE;
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+transform_all_day_check_to_action_sensitive_cb (GBinding *binding,
|
||
+ const GValue *from_value,
|
||
+ GValue *to_value,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ ECompEditor *comp_editor = user_data;
|
||
+
|
||
+ g_value_set_boolean (to_value,
|
||
+ !g_value_get_boolean (from_value) ||
|
||
+ ece_event_client_needs_all_day_as_time (comp_editor));
|
||
+
|
||
+ return TRUE;
|
||
+}
|
||
+
|
||
+static void
|
||
+ece_event_setup_ui (ECompEditorEvent *event_editor)
|
||
+{
|
||
+ const gchar *ui =
|
||
+ "<ui>"
|
||
+ " <menubar action='main-menu'>"
|
||
+ " <menu action='view-menu'>"
|
||
+ " <placeholder name='parts'>"
|
||
+ " <menuitem action='view-timezone'/>"
|
||
+ " <menuitem action='view-categories'/>"
|
||
+ " </placeholder>"
|
||
+ " </menu>"
|
||
+ " <menu action='options-menu'>"
|
||
+ " <placeholder name='toggles'>"
|
||
+ " <menuitem action='all-day-event'/>"
|
||
+ " <menuitem action='show-time-busy'/>"
|
||
+ " <menu action='classification-menu'>"
|
||
+ " <menuitem action='classify-public'/>"
|
||
+ " <menuitem action='classify-private'/>"
|
||
+ " <menuitem action='classify-confidential'/>"
|
||
+ " </menu>"
|
||
+ " </placeholder>"
|
||
+ " </menu>"
|
||
+ " </menubar>"
|
||
+ " <toolbar name='main-toolbar'>"
|
||
+ " <placeholder name='content'>\n"
|
||
+ " <toolitem action='all-day-event'/>\n"
|
||
+ " <toolitem action='show-time-busy'/>\n"
|
||
+ " </placeholder>"
|
||
+ " </toolbar>"
|
||
+ "</ui>";
|
||
+
|
||
+ const GtkToggleActionEntry view_actions[] = {
|
||
+ { "view-categories",
|
||
+ NULL,
|
||
+ N_("_Categories"),
|
||
+ NULL,
|
||
+ N_("Toggles whether to display categories"),
|
||
+ NULL,
|
||
+ FALSE },
|
||
+
|
||
+ { "view-timezone",
|
||
+ "stock_timezone",
|
||
+ N_("Time _Zone"),
|
||
+ NULL,
|
||
+ N_("Toggles whether the time zone is displayed"),
|
||
+ NULL,
|
||
+ FALSE },
|
||
+
|
||
+ { "all-day-event",
|
||
+ "stock_new-24h-appointment",
|
||
+ N_("All _Day Event"),
|
||
+ "<Control>Y",
|
||
+ N_("Toggles whether to have All Day Event"),
|
||
+ NULL,
|
||
+ FALSE },
|
||
+
|
||
+ { "show-time-busy",
|
||
+ "dialog-error",
|
||
+ N_("Show Time as _Busy"),
|
||
+ NULL,
|
||
+ N_("Toggles whether to show time as busy"),
|
||
+ NULL,
|
||
+ FALSE }
|
||
+ };
|
||
+
|
||
+ const GtkRadioActionEntry classification_radio_entries[] = {
|
||
+
|
||
+ { "classify-public",
|
||
+ NULL,
|
||
+ N_("Pu_blic"),
|
||
+ NULL,
|
||
+ N_("Classify as public"),
|
||
+ I_CAL_CLASS_PUBLIC },
|
||
+
|
||
+ { "classify-private",
|
||
+ NULL,
|
||
+ N_("_Private"),
|
||
+ NULL,
|
||
+ N_("Classify as private"),
|
||
+ I_CAL_CLASS_PRIVATE },
|
||
+
|
||
+ { "classify-confidential",
|
||
+ NULL,
|
||
+ N_("_Confidential"),
|
||
+ NULL,
|
||
+ N_("Classify as confidential"),
|
||
+ I_CAL_CLASS_CONFIDENTIAL }
|
||
+ };
|
||
+
|
||
+ ECompEditor *comp_editor;
|
||
+ GSettings *settings;
|
||
+ GtkUIManager *ui_manager;
|
||
+ GtkAction *action;
|
||
+ GtkActionGroup *action_group;
|
||
+ GtkWidget *widget;
|
||
+ GError *error = NULL;
|
||
+
|
||
+ g_return_if_fail (E_IS_COMP_EDITOR_EVENT (event_editor));
|
||
+
|
||
+ comp_editor = E_COMP_EDITOR (event_editor);
|
||
+ settings = e_comp_editor_get_settings (comp_editor);
|
||
+ ui_manager = e_comp_editor_get_ui_manager (comp_editor);
|
||
+ action_group = e_comp_editor_get_action_group (comp_editor, "individual");
|
||
+
|
||
+ gtk_action_group_add_toggle_actions (action_group,
|
||
+ view_actions, G_N_ELEMENTS (view_actions), event_editor);
|
||
+
|
||
+ gtk_action_group_add_radio_actions (
|
||
+ action_group, classification_radio_entries,
|
||
+ G_N_ELEMENTS (classification_radio_entries),
|
||
+ I_CAL_CLASS_PUBLIC,
|
||
+ G_CALLBACK (ece_event_action_classification_cb), event_editor);
|
||
+
|
||
+ gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error);
|
||
+
|
||
+ e_plugin_ui_register_manager (ui_manager, "org.gnome.evolution.event-editor", event_editor);
|
||
+ e_plugin_ui_enable_manager (ui_manager, "org.gnome.evolution.event-editor");
|
||
+
|
||
+ if (error) {
|
||
+ g_critical ("%s: %s", G_STRFUNC, error->message);
|
||
+ g_error_free (error);
|
||
+ }
|
||
+
|
||
+ action = e_comp_editor_get_action (comp_editor, "view-categories");
|
||
+ e_binding_bind_property (
|
||
+ event_editor->priv->categories, "visible",
|
||
+ action, "active",
|
||
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
|
||
+ g_settings_bind (
|
||
+ settings, "editor-show-categories",
|
||
+ action, "active",
|
||
+ G_SETTINGS_BIND_DEFAULT);
|
||
+
|
||
+ action = e_comp_editor_get_action (comp_editor, "view-timezone");
|
||
+ e_binding_bind_property_full (
|
||
+ action, "active",
|
||
+ event_editor->priv->timezone, "visible",
|
||
+ G_BINDING_DEFAULT,
|
||
+ transform_action_to_timezone_visible_cb,
|
||
+ NULL, /* not used */
|
||
+ event_editor, NULL);
|
||
+ e_binding_bind_property_full (
|
||
+ event_editor->priv->all_day_check, "active",
|
||
+ event_editor->priv->timezone, "visible",
|
||
+ G_BINDING_DEFAULT,
|
||
+ transform_toggle_to_timezone_visible_cb,
|
||
+ NULL, /* not used */
|
||
+ event_editor, NULL);
|
||
+ e_binding_bind_property_full (
|
||
+ event_editor->priv->all_day_check, "active",
|
||
+ action, "sensitive",
|
||
+ G_BINDING_SYNC_CREATE,
|
||
+ transform_all_day_check_to_action_sensitive_cb,
|
||
+ NULL, /* not used */
|
||
+ event_editor, NULL);
|
||
+ g_settings_bind (
|
||
+ settings, "editor-show-timezone",
|
||
+ action, "active",
|
||
+ G_SETTINGS_BIND_DEFAULT);
|
||
+
|
||
+ action = e_comp_editor_get_action (comp_editor, "all-day-event");
|
||
+ e_binding_bind_property (
|
||
+ event_editor->priv->all_day_check, "active",
|
||
+ action, "active",
|
||
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
|
||
+
|
||
+ widget = e_comp_editor_property_part_get_edit_widget (event_editor->priv->transparency);
|
||
+ action = e_comp_editor_get_action (comp_editor, "show-time-busy");
|
||
+ e_binding_bind_property (
|
||
+ widget, "active",
|
||
+ action, "active",
|
||
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
|
||
+}
|
||
+
|
||
+static void
|
||
+e_comp_editor_event_constructed (GObject *object)
|
||
+{
|
||
+ ECompEditor *comp_editor;
|
||
+ ECompEditorEvent *event_editor;
|
||
+ ECompEditorPage *page;
|
||
+ ECompEditorPropertyPart *part;
|
||
+ ECompEditorPropertyPart *summary;
|
||
+ EFocusTracker *focus_tracker;
|
||
+ GtkWidget *widget;
|
||
+
|
||
+ G_OBJECT_CLASS (e_comp_editor_event_parent_class)->constructed (object);
|
||
+
|
||
+ event_editor = E_COMP_EDITOR_EVENT (object);
|
||
+ comp_editor = E_COMP_EDITOR (event_editor);
|
||
+ focus_tracker = e_comp_editor_get_focus_tracker (comp_editor);
|
||
+
|
||
+ page = e_comp_editor_page_general_new (comp_editor,
|
||
+ _("_Calendar:"), E_SOURCE_EXTENSION_CALENDAR,
|
||
+ NULL, FALSE, 2);
|
||
+ event_editor->priv->page_general = page;
|
||
+
|
||
+ part = e_comp_editor_property_part_summary_new (focus_tracker);
|
||
+ e_comp_editor_page_add_property_part (page, part, 0, 2, 3, 1);
|
||
+ summary = part;
|
||
+
|
||
+ part = e_comp_editor_property_part_location_new (focus_tracker);
|
||
+ e_comp_editor_page_add_property_part (page, part, 0, 3, 3, 1);
|
||
+
|
||
+ part = e_comp_editor_property_part_dtstart_new (C_("ECompEditor", "_Start time:"), FALSE, FALSE, TRUE);
|
||
+ e_comp_editor_page_add_property_part (page, part, 0, 4, 2, 1);
|
||
+ e_comp_editor_property_part_set_sensitize_handled (part, TRUE);
|
||
+ event_editor->priv->dtstart = part;
|
||
+
|
||
+ part = e_comp_editor_property_part_dtend_new (C_("ECompEditor", "_End time:"), FALSE, FALSE);
|
||
+ e_comp_editor_page_add_property_part (page, part, 0, 5, 2, 1);
|
||
+ e_comp_editor_property_part_set_sensitize_handled (part, TRUE);
|
||
+ event_editor->priv->dtend = part;
|
||
+
|
||
+ part = e_comp_editor_property_part_timezone_new ();
|
||
+ e_comp_editor_page_add_property_part (page, part, 0, 6, 3, 1);
|
||
+ e_comp_editor_property_part_set_sensitize_handled (part, TRUE);
|
||
+ event_editor->priv->timezone = part;
|
||
+
|
||
+ widget = gtk_check_button_new_with_mnemonic (C_("ECompEditor", "All da_y event"));
|
||
+ g_object_set (G_OBJECT (widget),
|
||
+ "hexpand", TRUE,
|
||
+ "halign", GTK_ALIGN_FILL,
|
||
+ "vexpand", FALSE,
|
||
+ "valign", GTK_ALIGN_START,
|
||
+ NULL);
|
||
+ gtk_grid_attach (GTK_GRID (page), widget, 2, 4, 1, 1);
|
||
+ gtk_widget_show (widget);
|
||
+ event_editor->priv->all_day_check = widget;
|
||
+
|
||
+ part = e_comp_editor_property_part_transparency_new ();
|
||
+ e_comp_editor_page_add_property_part (page, part, 2, 5, 1, 1);
|
||
+ event_editor->priv->transparency = part;
|
||
+
|
||
+ widget = e_comp_editor_property_part_get_edit_widget (event_editor->priv->transparency);
|
||
+ /* Transparency checkbox is not shown in the page, even it's packed there */
|
||
+ gtk_widget_hide (widget);
|
||
+
|
||
+ part = e_comp_editor_property_part_status_new (I_CAL_VEVENT_COMPONENT);
|
||
+ e_comp_editor_page_add_property_part (page, part, 0, 7, 3, 1);
|
||
+
|
||
+ widget = e_comp_editor_property_part_get_edit_widget (part);
|
||
+ gtk_widget_set_halign (widget, GTK_ALIGN_START);
|
||
+ gtk_widget_set_hexpand (widget, FALSE);
|
||
+
|
||
+ part = e_comp_editor_property_part_url_new (focus_tracker);
|
||
+ e_comp_editor_page_add_property_part (page, part, 0, 8, 3, 1);
|
||
+
|
||
+ part = e_comp_editor_property_part_categories_new (focus_tracker);
|
||
+ e_comp_editor_page_add_property_part (page, part, 0, 9, 3, 1);
|
||
+ event_editor->priv->categories = part;
|
||
+
|
||
+ part = e_comp_editor_property_part_description_new (focus_tracker);
|
||
+ e_comp_editor_page_add_property_part (page, part, 0, 10, 3, 1);
|
||
+ event_editor->priv->description = part;
|
||
+
|
||
+ widget = e_comp_editor_property_part_get_edit_widget (event_editor->priv->timezone);
|
||
+ e_comp_editor_property_part_datetime_attach_timezone_entry (
|
||
+ E_COMP_EDITOR_PROPERTY_PART_DATETIME (event_editor->priv->dtstart),
|
||
+ E_TIMEZONE_ENTRY (widget));
|
||
+ g_signal_connect_swapped (event_editor->priv->dtstart, "lookup-timezone",
|
||
+ G_CALLBACK (e_comp_editor_lookup_timezone), event_editor);
|
||
+ e_comp_editor_property_part_datetime_attach_timezone_entry (
|
||
+ E_COMP_EDITOR_PROPERTY_PART_DATETIME (event_editor->priv->dtend),
|
||
+ E_TIMEZONE_ENTRY (widget));
|
||
+ g_signal_connect_swapped (event_editor->priv->dtend, "lookup-timezone",
|
||
+ G_CALLBACK (e_comp_editor_lookup_timezone), event_editor);
|
||
+
|
||
+ e_comp_editor_set_time_parts (comp_editor, event_editor->priv->dtstart, event_editor->priv->dtend);
|
||
+
|
||
+ widget = e_comp_editor_property_part_get_edit_widget (event_editor->priv->dtstart);
|
||
+ e_binding_bind_property (
|
||
+ event_editor->priv->all_day_check, "active",
|
||
+ widget, "show-time",
|
||
+ G_BINDING_INVERT_BOOLEAN | G_BINDING_BIDIRECTIONAL);
|
||
+ g_signal_connect (widget, "changed", G_CALLBACK (ece_event_dtstart_changed_cb), event_editor);
|
||
+
|
||
+ widget = e_comp_editor_property_part_get_edit_widget (event_editor->priv->dtend);
|
||
+ e_binding_bind_property (
|
||
+ event_editor->priv->all_day_check, "active",
|
||
+ widget, "show-time",
|
||
+ G_BINDING_INVERT_BOOLEAN | G_BINDING_BIDIRECTIONAL);
|
||
+ g_signal_connect (widget, "changed", G_CALLBACK (ece_event_dtend_changed_cb), event_editor);
|
||
+
|
||
+ e_signal_connect_notify_swapped (event_editor->priv->all_day_check, "notify::active",
|
||
+ G_CALLBACK (ece_event_all_day_toggled_cb), event_editor);
|
||
+
|
||
+ e_comp_editor_add_page (comp_editor, C_("ECompEditorPage", "General"), page);
|
||
+
|
||
+ page = e_comp_editor_page_reminders_new (comp_editor);
|
||
+ e_comp_editor_add_page (comp_editor, C_("ECompEditorPage", "Reminders"), page);
|
||
+
|
||
+ page = e_comp_editor_page_recurrence_new (comp_editor);
|
||
+ e_comp_editor_add_page (comp_editor, C_("ECompEditorPage", "Recurrence"), page);
|
||
+
|
||
+ page = e_comp_editor_page_attachments_new (comp_editor);
|
||
+ e_comp_editor_add_page (comp_editor, C_("ECompEditorPage", "Attachments"), page);
|
||
+
|
||
+ page = e_comp_editor_page_schedule_new (comp_editor,
|
||
+ e_comp_editor_page_general_get_meeting_store (
|
||
+ E_COMP_EDITOR_PAGE_GENERAL (event_editor->priv->page_general)));
|
||
+ e_binding_bind_property (
|
||
+ event_editor->priv->page_general, "show-attendees",
|
||
+ page, "visible",
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ e_comp_editor_add_page (comp_editor, C_("ECompEditorPage", "Schedule"), page);
|
||
+
|
||
+ ece_event_setup_ui (event_editor);
|
||
+
|
||
+ widget = e_comp_editor_property_part_get_edit_widget (summary);
|
||
+ e_binding_bind_property (widget, "text", comp_editor, "title-suffix", 0);
|
||
+ /* Do this as the last thing, because some widgets can call the function as well */
|
||
+ gtk_widget_grab_focus (widget);
|
||
+
|
||
+ g_signal_connect (comp_editor, "notify::source-client",
|
||
+ G_CALLBACK (ece_event_notify_source_client_cb), NULL);
|
||
+
|
||
+ g_signal_connect (comp_editor, "notify::target-client",
|
||
+ G_CALLBACK (ece_event_notify_target_client_cb), NULL);
|
||
+}
|
||
+
|
||
+static void
|
||
+e_comp_editor_event_init (ECompEditorEvent *event_editor)
|
||
+{
|
||
+ event_editor->priv = G_TYPE_INSTANCE_GET_PRIVATE (event_editor, E_TYPE_COMP_EDITOR_EVENT, ECompEditorEventPrivate);
|
||
+}
|
||
+
|
||
+static void
|
||
+e_comp_editor_event_class_init (ECompEditorEventClass *klass)
|
||
+{
|
||
+ GObjectClass *object_class;
|
||
+ ECompEditorClass *comp_editor_class;
|
||
+
|
||
+ g_type_class_add_private (klass, sizeof (ECompEditorEventPrivate));
|
||
+
|
||
+ object_class = G_OBJECT_CLASS (klass);
|
||
+ object_class->constructed = e_comp_editor_event_constructed;
|
||
+
|
||
+ comp_editor_class = E_COMP_EDITOR_CLASS (klass);
|
||
+ comp_editor_class->help_section = "calendar-usage-add-appointment";
|
||
+ comp_editor_class->title_format_with_attendees = _("Meeting — %s");
|
||
+ comp_editor_class->title_format_without_attendees = _("Appointment — %s");
|
||
+ comp_editor_class->icon_name = "appointment-new";
|
||
+ comp_editor_class->sensitize_widgets = ece_event_sensitize_widgets;
|
||
+ comp_editor_class->fill_widgets = ece_event_fill_widgets;
|
||
+ comp_editor_class->fill_component = ece_event_fill_component;
|
||
+}
|
||
diff -urN a/src/calendar/gui/e-comp-editor-page-attachments.c b/src/calendar/gui/e-comp-editor-page-attachments.c
|
||
--- a/src/calendar/gui/e-comp-editor-page-attachments.c 2025-06-07 14:20:57.267396453 -0700
|
||
+++ b/src/calendar/gui/e-comp-editor-page-attachments.c 2025-06-07 14:27:24.035672846 -0700
|
||
@@ -621,7 +621,7 @@
|
||
{ "attachments-attach",
|
||
"mail-attachment",
|
||
N_("_Attachment…"),
|
||
- "<Control>m",
|
||
+ "<Super>m",
|
||
N_("Attach a file"),
|
||
G_CALLBACK (ecep_attachments_action_attach_cb) }
|
||
};
|
||
diff -urN a/src/calendar/gui/e-comp-editor-task.c b/src/calendar/gui/e-comp-editor-task.c
|
||
--- a/src/calendar/gui/e-comp-editor-task.c 2025-06-07 14:20:57.271396501 -0700
|
||
+++ b/src/calendar/gui/e-comp-editor-task.c 2025-06-07 14:27:24.035672846 -0700
|
||
@@ -816,7 +816,7 @@
|
||
{ "all-day-task",
|
||
"stock_new-24h-appointment",
|
||
N_("All _Day Task"),
|
||
- "<Control>Y",
|
||
+ "<Super>Y",
|
||
N_("Toggles whether to have All Day Task"),
|
||
NULL,
|
||
FALSE }
|
||
diff -urN a/src/calendar/gui/e-comp-editor.c b/src/calendar/gui/e-comp-editor.c
|
||
--- a/src/calendar/gui/e-comp-editor.c 2025-06-07 14:20:57.271396501 -0700
|
||
+++ b/src/calendar/gui/e-comp-editor.c 2025-06-07 14:27:24.039672886 -0700
|
||
@@ -2171,21 +2171,21 @@
|
||
{ "close",
|
||
"window-close",
|
||
N_("_Close"),
|
||
- "<Control>w",
|
||
+ "<Super>w",
|
||
N_("Close the current window"),
|
||
G_CALLBACK (action_close_cb) },
|
||
|
||
{ "copy-clipboard",
|
||
"edit-copy",
|
||
N_("_Copy"),
|
||
- "<Control>c",
|
||
+ "<Super>c",
|
||
N_("Copy the selection"),
|
||
NULL }, /* Handled by EFocusTracker */
|
||
|
||
{ "cut-clipboard",
|
||
"edit-cut",
|
||
N_("Cu_t"),
|
||
- "<Control>x",
|
||
+ "<Super>x",
|
||
N_("Cut the selection"),
|
||
NULL }, /* Handled by EFocusTracker */
|
||
|
||
@@ -2206,14 +2206,14 @@
|
||
{ "paste-clipboard",
|
||
"edit-paste",
|
||
N_("_Paste"),
|
||
- "<Control>v",
|
||
+ "<Super>v",
|
||
N_("Paste the clipboard"),
|
||
NULL }, /* Handled by EFocusTracker */
|
||
|
||
{ "print",
|
||
"document-print",
|
||
N_("_Print…"),
|
||
- "<Control>p",
|
||
+ "<Super>p",
|
||
NULL,
|
||
G_CALLBACK (action_print_cb) },
|
||
|
||
@@ -2227,21 +2227,21 @@
|
||
{ "select-all",
|
||
"edit-select-all",
|
||
N_("Select _All"),
|
||
- "<Control>a",
|
||
+ "<Super>a",
|
||
N_("Select all text"),
|
||
NULL }, /* Handled by EFocusTracker */
|
||
|
||
{ "undo",
|
||
"edit-undo",
|
||
N_("_Undo"),
|
||
- "<Control>z",
|
||
+ "<Super>z",
|
||
N_("Undo"),
|
||
NULL }, /* Handled by EFocusTracker */
|
||
|
||
{ "redo",
|
||
"edit-redo",
|
||
N_("_Redo"),
|
||
- "<Control>y",
|
||
+ "<Super>y",
|
||
N_("Redo"),
|
||
NULL }, /* Handled by EFocusTracker */
|
||
|
||
@@ -2302,14 +2302,14 @@
|
||
{ "save",
|
||
"document-save",
|
||
N_("_Save"),
|
||
- "<Control>s",
|
||
+ "<Super>s",
|
||
N_("Save current changes"),
|
||
G_CALLBACK (action_save_cb) },
|
||
|
||
{ "save-and-close",
|
||
NULL,
|
||
N_("Save and Close"),
|
||
- "<Control>Return",
|
||
+ "<Alt><Super>S",
|
||
N_("Save current changes and close editor"),
|
||
G_CALLBACK (action_save_and_close_cb) }
|
||
};
|
||
diff -urN a/src/calendar/gui/ea-cal-view.c b/src/calendar/gui/ea-cal-view.c
|
||
--- a/src/calendar/gui/ea-cal-view.c 2025-06-07 14:20:30.163068622 -0700
|
||
+++ b/src/calendar/gui/ea-cal-view.c 2025-06-07 14:27:24.039672886 -0700
|
||
@@ -371,19 +371,19 @@
|
||
switch (index) {
|
||
case 0:
|
||
/* New Appointment */
|
||
- return "<Alt>fna;<Control>n";
|
||
+ return "<Alt>fna;<Super>n";
|
||
case 1:
|
||
/* New Event */
|
||
- return "<Alt>fnd;<Shift><Control>d";
|
||
+ return "<Alt>fnd;<Shift><Super>d";
|
||
case 2:
|
||
/* New Meeting */
|
||
- return "<Alt>fne;<Shift><Control>e";
|
||
+ return "<Alt>fne;<Shift><Super>e";
|
||
case 3:
|
||
/* Go to today */
|
||
- return "<Alt>vt;<Alt><Control>t";
|
||
+ return "<Alt>vt;<Alt><Super>t";
|
||
case 4:
|
||
/* Go to date */
|
||
- return "<Alt>vd;<Alt><Control>g";
|
||
+ return "<Alt>vd;<Alt><Super>g";
|
||
default:
|
||
break;
|
||
}
|
||
diff -urN a/src/composer/e-composer-actions.c b/src/composer/e-composer-actions.c
|
||
--- a/src/composer/e-composer-actions.c 2025-06-07 14:20:57.283396645 -0700
|
||
+++ b/src/composer/e-composer-actions.c 2025-06-07 14:27:24.043672927 -0700
|
||
@@ -324,21 +324,21 @@
|
||
{ "attach",
|
||
"mail-attachment",
|
||
N_("_Attachment…"),
|
||
- "<Control>m",
|
||
+ "<Super>m",
|
||
N_("Attach a file"),
|
||
G_CALLBACK (action_attach_cb) },
|
||
|
||
{ "close",
|
||
"window-close",
|
||
N_("_Close"),
|
||
- "<Control>w",
|
||
+ "<Super>w",
|
||
N_("Close the current file"),
|
||
G_CALLBACK (action_close_cb) },
|
||
|
||
{ "new-message",
|
||
"mail-message-new",
|
||
N_("New _Message"),
|
||
- "<Control>n",
|
||
+ "<Super>n",
|
||
N_("Open New Message window"),
|
||
G_CALLBACK (action_new_message_cb) },
|
||
|
||
@@ -352,7 +352,7 @@
|
||
{ "save",
|
||
"document-save",
|
||
N_("_Save"),
|
||
- "<Shift><Control>s",
|
||
+ "<Shift><Super>s",
|
||
N_("Save the current file"),
|
||
G_CALLBACK (action_save_cb) },
|
||
|
||
@@ -385,28 +385,28 @@
|
||
{ "print",
|
||
"document-print",
|
||
N_("_Print…"),
|
||
- "<Control>p",
|
||
+ "<Super>p",
|
||
NULL,
|
||
G_CALLBACK (action_print_cb) },
|
||
|
||
{ "print-preview",
|
||
"document-print-preview",
|
||
N_("Print Pre_view"),
|
||
- "<Shift><Control>p",
|
||
+ "<Shift><Super>p",
|
||
NULL,
|
||
G_CALLBACK (action_print_preview_cb) },
|
||
|
||
{ "save-draft",
|
||
"document-save",
|
||
N_("Save as _Draft"),
|
||
- "<Control>s",
|
||
+ "<Super>s",
|
||
N_("Save as draft"),
|
||
G_CALLBACK (action_save_draft_cb) },
|
||
|
||
{ "send",
|
||
"mail-send",
|
||
N_("S_end"),
|
||
- "<Control>Return",
|
||
+ "<Alt><Super>s",
|
||
N_("Send this message"),
|
||
G_CALLBACK (action_send_cb) },
|
||
};
|
||
diff -urN a/src/e-util/e-html-editor-actions.c b/src/e-util/e-html-editor-actions.c
|
||
--- a/src/e-util/e-html-editor-actions.c 2025-06-07 14:20:57.303396885 -0700
|
||
+++ b/src/e-util/e-html-editor-actions.c 2025-06-07 14:27:24.047672970 -0700
|
||
@@ -1124,42 +1124,42 @@
|
||
{ "copy",
|
||
"edit-copy",
|
||
N_("_Copy"),
|
||
- "<Control>c",
|
||
+ "<Super>c",
|
||
N_("Copy selected text to the clipboard"),
|
||
NULL }, /* Handled by focus tracker */
|
||
|
||
{ "cut",
|
||
"edit-cut",
|
||
N_("Cu_t"),
|
||
- "<Control>x",
|
||
+ "<Super>x",
|
||
N_("Cut selected text to the clipboard"),
|
||
NULL }, /* Handled by focus tracker */
|
||
|
||
{ "paste",
|
||
"edit-paste",
|
||
N_("_Paste"),
|
||
- "<Control>v",
|
||
+ "<Super>v",
|
||
N_("Paste text from the clipboard"),
|
||
NULL }, /* Handled by focus tracker */
|
||
|
||
{ "redo",
|
||
"edit-redo",
|
||
N_("_Redo"),
|
||
- "<Shift><Control>z",
|
||
+ "<Shift><Super>z",
|
||
N_("Redo the last undone action"),
|
||
G_CALLBACK (action_redo_cb) },
|
||
|
||
{ "select-all",
|
||
"edit-select-all",
|
||
N_("Select _All"),
|
||
- "<Control>a",
|
||
+ "<Super>a",
|
||
NULL,
|
||
NULL }, /* Handled by focus tracker */
|
||
|
||
{ "undo",
|
||
"edit-undo",
|
||
N_("_Undo"),
|
||
- "<Control>z",
|
||
+ "<Super>z",
|
||
N_("Undo the last action"),
|
||
G_CALLBACK (action_undo_cb) },
|
||
|
||
@@ -1227,7 +1227,7 @@
|
||
{ "indent",
|
||
"format-indent-more",
|
||
N_("_Increase Indent"),
|
||
- "<Control>bracketright",
|
||
+ "<Super>bracketright",
|
||
N_("Increase Indent"),
|
||
G_CALLBACK (action_indent_cb) },
|
||
|
||
@@ -1262,28 +1262,28 @@
|
||
{ "paste-quote",
|
||
NULL,
|
||
N_("Paste _Quotation"),
|
||
- "<Control><Alt>v",
|
||
+ "<Super><Alt>v",
|
||
NULL,
|
||
G_CALLBACK (action_paste_quote_cb) },
|
||
|
||
{ "show-find",
|
||
"edit-find",
|
||
N_("_Find…"),
|
||
- "<Control>f",
|
||
+ "<Super>f",
|
||
N_("Search for text"),
|
||
G_CALLBACK (action_show_find_cb) },
|
||
|
||
{ "find-again",
|
||
NULL,
|
||
N_("Find A_gain"),
|
||
- "<Control>g",
|
||
+ "<Super>g",
|
||
NULL,
|
||
G_CALLBACK (action_find_again_cb) },
|
||
|
||
{ "show-replace",
|
||
"edit-find-replace",
|
||
N_("Re_place…"),
|
||
- "<Control>h",
|
||
+ "<Super>h",
|
||
N_("Search for and replace text"),
|
||
G_CALLBACK (action_show_replace_cb) },
|
||
|
||
@@ -1297,14 +1297,14 @@
|
||
{ "unindent",
|
||
"format-indent-less",
|
||
N_("_Decrease Indent"),
|
||
- "<Control>bracketleft",
|
||
+ "<Super>bracketleft",
|
||
N_("Decrease Indent"),
|
||
G_CALLBACK (action_unindent_cb) },
|
||
|
||
{ "wrap-lines",
|
||
NULL,
|
||
N_("_Wrap Lines"),
|
||
- "<Control><Shift>k",
|
||
+ "<Super><Shift>k",
|
||
NULL,
|
||
G_CALLBACK (action_wrap_lines_cb) }
|
||
};
|
||
@@ -1314,28 +1314,28 @@
|
||
{ "justify-center",
|
||
"format-justify-center",
|
||
N_("_Center"),
|
||
- "<Control>e",
|
||
+ "<Super>e",
|
||
N_("Center Alignment"),
|
||
E_CONTENT_EDITOR_ALIGNMENT_CENTER },
|
||
|
||
{ "justify-fill",
|
||
"format-justify-fill",
|
||
N_("_Justified"),
|
||
- "<Control>j",
|
||
+ "<Super>j",
|
||
N_("Align Justified"),
|
||
E_CONTENT_EDITOR_ALIGNMENT_JUSTIFY },
|
||
|
||
{ "justify-left",
|
||
"format-justify-left",
|
||
N_("_Left"),
|
||
- "<Control>l",
|
||
+ "<Super>l",
|
||
N_("Left Alignment"),
|
||
E_CONTENT_EDITOR_ALIGNMENT_LEFT },
|
||
|
||
{ "justify-right",
|
||
"format-justify-right",
|
||
N_("_Right"),
|
||
- "<Control>r",
|
||
+ "<Super>r",
|
||
N_("Right Alignment"),
|
||
E_CONTENT_EDITOR_ALIGNMENT_RIGHT }
|
||
};
|
||
@@ -1383,63 +1383,63 @@
|
||
{ "style-normal",
|
||
NULL,
|
||
N_("_Normal"),
|
||
- "<Control>0",
|
||
+ "<Super>0",
|
||
NULL,
|
||
E_CONTENT_EDITOR_BLOCK_FORMAT_PARAGRAPH },
|
||
|
||
{ "style-h1",
|
||
NULL,
|
||
N_("Heading _1"),
|
||
- "<Control>1",
|
||
+ "<Super>1",
|
||
NULL,
|
||
E_CONTENT_EDITOR_BLOCK_FORMAT_H1 },
|
||
|
||
{ "style-h2",
|
||
NULL,
|
||
N_("Heading _2"),
|
||
- "<Control>2",
|
||
+ "<Super>2",
|
||
NULL,
|
||
E_CONTENT_EDITOR_BLOCK_FORMAT_H2 },
|
||
|
||
{ "style-h3",
|
||
NULL,
|
||
N_("Heading _3"),
|
||
- "<Control>3",
|
||
+ "<Super>3",
|
||
NULL,
|
||
E_CONTENT_EDITOR_BLOCK_FORMAT_H3 },
|
||
|
||
{ "style-h4",
|
||
NULL,
|
||
N_("Heading _4"),
|
||
- "<Control>4",
|
||
+ "<Super>4",
|
||
NULL,
|
||
E_CONTENT_EDITOR_BLOCK_FORMAT_H4 },
|
||
|
||
{ "style-h5",
|
||
NULL,
|
||
N_("Heading _5"),
|
||
- "<Control>5",
|
||
+ "<Super>5",
|
||
NULL,
|
||
E_CONTENT_EDITOR_BLOCK_FORMAT_H5 },
|
||
|
||
{ "style-h6",
|
||
NULL,
|
||
N_("Heading _6"),
|
||
- "<Control>6",
|
||
+ "<Super>6",
|
||
NULL,
|
||
E_CONTENT_EDITOR_BLOCK_FORMAT_H6 },
|
||
|
||
{ "style-preformat",
|
||
NULL,
|
||
N_("_Preformatted"),
|
||
- "<Control>7",
|
||
+ "<Super>7",
|
||
NULL,
|
||
E_CONTENT_EDITOR_BLOCK_FORMAT_PRE },
|
||
|
||
{ "style-address",
|
||
NULL,
|
||
N_("A_ddress"),
|
||
- "<Control>8",
|
||
+ "<Super>8",
|
||
NULL,
|
||
E_CONTENT_EDITOR_BLOCK_FORMAT_ADDRESS },
|
||
|
||
@@ -1491,7 +1491,7 @@
|
||
{ "insert-link",
|
||
"insert-link",
|
||
N_("_Link…"),
|
||
- "<Control>k",
|
||
+ "<Super>k",
|
||
N_("Insert Link"),
|
||
G_CALLBACK (action_insert_link_cb) },
|
||
|
||
@@ -1573,7 +1573,7 @@
|
||
{ "paste-as-text",
|
||
NULL,
|
||
N_("Paste As _Text"),
|
||
- "<Shift><Control>v",
|
||
+ "<Shift><Super>v",
|
||
NULL,
|
||
G_CALLBACK (action_paste_as_text_cb) },
|
||
|
||
@@ -1584,7 +1584,7 @@
|
||
{ "bold",
|
||
"format-text-bold",
|
||
N_("_Bold"),
|
||
- "<Control>b",
|
||
+ "<Super>b",
|
||
N_("Bold"),
|
||
NULL,
|
||
FALSE },
|
||
@@ -1592,7 +1592,7 @@
|
||
{ "italic",
|
||
"format-text-italic",
|
||
N_("_Italic"),
|
||
- "<Control>i",
|
||
+ "<Super>i",
|
||
N_("Italic"),
|
||
NULL,
|
||
FALSE },
|
||
@@ -1608,7 +1608,7 @@
|
||
{ "subscript",
|
||
NULL,
|
||
N_("Subs_cript"),
|
||
- "<Control><Shift>b",
|
||
+ "<Super><Shift>b",
|
||
N_("Subscript"),
|
||
NULL,
|
||
FALSE },
|
||
@@ -1616,7 +1616,7 @@
|
||
{ "superscript",
|
||
NULL,
|
||
N_("Su_perscript"),
|
||
- "<Control><Shift>p",
|
||
+ "<Super><Shift>p",
|
||
N_("Superscript"),
|
||
NULL,
|
||
FALSE },
|
||
@@ -1624,7 +1624,7 @@
|
||
{ "underline",
|
||
"format-text-underline",
|
||
N_("_Underline"),
|
||
- "<Control>u",
|
||
+ "<Super>u",
|
||
N_("Underline"),
|
||
NULL,
|
||
FALSE }
|
||
diff -urN a/src/e-util/e-mail-signature-editor.c b/src/e-util/e-mail-signature-editor.c
|
||
--- a/src/e-util/e-mail-signature-editor.c 2025-06-07 14:20:57.307396934 -0700
|
||
+++ b/src/e-util/e-mail-signature-editor.c 2025-06-07 14:27:24.047672970 -0700
|
||
@@ -332,14 +332,14 @@
|
||
{ "close",
|
||
"window-close",
|
||
N_("_Close"),
|
||
- "<Control>w",
|
||
+ "<Super>w",
|
||
N_("Close"),
|
||
G_CALLBACK (action_close_cb) },
|
||
|
||
{ "save-and-close",
|
||
"document-save",
|
||
N_("_Save and Close"),
|
||
- "<Control>Return",
|
||
+ "<Alt><Super>s",
|
||
N_("Save and Close"),
|
||
G_CALLBACK (action_save_and_close_cb) },
|
||
|
||
diff -urN a/src/e-util/e-web-view.c b/src/e-util/e-web-view.c
|
||
--- a/src/e-util/e-web-view.c 2025-06-07 14:20:57.327397173 -0700
|
||
+++ b/src/e-util/e-web-view.c 2025-06-07 14:27:24.051673010 -0700
|
||
@@ -404,7 +404,7 @@
|
||
{ "uri-copy",
|
||
"edit-copy",
|
||
N_("_Copy Link Location"),
|
||
- "<Control>c",
|
||
+ "<Super>c",
|
||
N_("Copy the link to the clipboard"),
|
||
G_CALLBACK (action_uri_copy_cb) }
|
||
};
|
||
@@ -424,7 +424,7 @@
|
||
{ "mailto-copy",
|
||
"edit-copy",
|
||
N_("_Copy Email Address"),
|
||
- "<Control>c",
|
||
+ "<Super>c",
|
||
N_("Copy the email address to the clipboard"),
|
||
G_CALLBACK (action_mailto_copy_cb) },
|
||
|
||
@@ -448,14 +448,14 @@
|
||
{ "image-copy",
|
||
"edit-copy",
|
||
N_("_Copy Image"),
|
||
- "<Control>c",
|
||
+ "<Super>c",
|
||
N_("Copy the image to the clipboard"),
|
||
G_CALLBACK (action_image_copy_cb) },
|
||
|
||
{ "image-save",
|
||
"document-save",
|
||
N_("Save _Image…"),
|
||
- "<Control>s",
|
||
+ "<Super>s",
|
||
N_("Save the image to a file"),
|
||
G_CALLBACK (action_image_save_cb) }
|
||
};
|
||
@@ -465,7 +465,7 @@
|
||
{ "copy-clipboard",
|
||
"edit-copy",
|
||
N_("_Copy"),
|
||
- "<Control>c",
|
||
+ "<Super>c",
|
||
N_("Copy the selection"),
|
||
G_CALLBACK (action_copy_clipboard_cb) },
|
||
|
||
diff -urN a/src/e-util/e-web-view.c.orig b/src/e-util/e-web-view.c.orig
|
||
--- a/src/e-util/e-web-view.c.orig 1969-12-31 16:00:00.000000000 -0800
|
||
+++ b/src/e-util/e-web-view.c.orig 2025-06-07 14:20:57.327397173 -0700
|
||
@@ -0,0 +1,4439 @@
|
||
+/*
|
||
+ * e-web-view.c
|
||
+ *
|
||
+ * This program is free software; you can redistribute it and/or modify it
|
||
+ * under the terms of the GNU Lesser General Public License as published by
|
||
+ * the Free Software Foundation.
|
||
+ *
|
||
+ * This program is distributed in the hope that it will be useful, but
|
||
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||
+ * for more details.
|
||
+ *
|
||
+ * You should have received a copy of the GNU Lesser General Public License
|
||
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||
+ *
|
||
+ */
|
||
+
|
||
+#include "evolution-config.h"
|
||
+
|
||
+#include <glib/gi18n-lib.h>
|
||
+
|
||
+#include <math.h>
|
||
+#include <stdlib.h>
|
||
+#include <string.h>
|
||
+
|
||
+#include <pango/pango.h>
|
||
+
|
||
+#include <camel/camel.h>
|
||
+#include <libebackend/libebackend.h>
|
||
+
|
||
+#include <libsoup/soup.h>
|
||
+
|
||
+#include "e-alert-dialog.h"
|
||
+#include "e-alert-sink.h"
|
||
+#include "e-file-request.h"
|
||
+#include "e-misc-utils.h"
|
||
+#include "e-plugin-ui.h"
|
||
+#include "e-popup-action.h"
|
||
+#include "e-selectable.h"
|
||
+#include "e-stock-request.h"
|
||
+#include "e-web-view-jsc-utils.h"
|
||
+
|
||
+#include "e-web-view.h"
|
||
+
|
||
+#define E_WEB_VIEW_GET_PRIVATE(obj) \
|
||
+ (G_TYPE_INSTANCE_GET_PRIVATE \
|
||
+ ((obj), E_TYPE_WEB_VIEW, EWebViewPrivate))
|
||
+
|
||
+typedef struct _AsyncContext AsyncContext;
|
||
+
|
||
+typedef struct _ElementClickedData {
|
||
+ EWebViewElementClickedFunc callback;
|
||
+ gpointer user_data;
|
||
+} ElementClickedData;
|
||
+
|
||
+struct _EWebViewPrivate {
|
||
+ GtkUIManager *ui_manager;
|
||
+ gchar *selected_uri;
|
||
+ gchar *cursor_image_src;
|
||
+
|
||
+ GQueue highlights;
|
||
+ gboolean highlights_enabled;
|
||
+
|
||
+ GtkAction *open_proxy;
|
||
+ GtkAction *print_proxy;
|
||
+ GtkAction *save_as_proxy;
|
||
+
|
||
+ /* Lockdown Options */
|
||
+ gboolean disable_printing;
|
||
+ gboolean disable_save_to_disk;
|
||
+
|
||
+ gboolean caret_mode;
|
||
+
|
||
+ GSettings *font_settings;
|
||
+ gulong font_name_changed_handler_id;
|
||
+ gulong monospace_font_name_changed_handler_id;
|
||
+
|
||
+ GHashTable *scheme_handlers; /* gchar *scheme ~> EContentRequest */
|
||
+ GHashTable *old_settings;
|
||
+
|
||
+ WebKitFindController *find_controller;
|
||
+ gulong found_text_handler_id;
|
||
+ gulong failed_to_find_text_handler_id;
|
||
+
|
||
+ gboolean has_hover_link;
|
||
+
|
||
+ GHashTable *element_clicked_cbs; /* gchar *element_class ~> GPtrArray {ElementClickedData} */
|
||
+
|
||
+ gboolean has_selection;
|
||
+ gboolean need_input;
|
||
+
|
||
+ GCancellable *cancellable;
|
||
+
|
||
+ gchar *last_popup_iframe_src;
|
||
+ gchar *last_popup_iframe_id;
|
||
+ gchar *last_popup_element_id;
|
||
+ gchar *last_popup_link_uri;
|
||
+
|
||
+ gint minimum_font_size;
|
||
+};
|
||
+
|
||
+struct _AsyncContext {
|
||
+ EActivity *activity;
|
||
+ GFile *destination;
|
||
+ GInputStream *input_stream;
|
||
+ EContentRequest *content_request;
|
||
+ gchar *uri;
|
||
+};
|
||
+
|
||
+enum {
|
||
+ PROP_0,
|
||
+ PROP_CARET_MODE,
|
||
+ PROP_COPY_TARGET_LIST,
|
||
+ PROP_CURSOR_IMAGE_SRC,
|
||
+ PROP_DISABLE_PRINTING,
|
||
+ PROP_DISABLE_SAVE_TO_DISK,
|
||
+ PROP_HAS_SELECTION,
|
||
+ PROP_NEED_INPUT,
|
||
+ PROP_MINIMUM_FONT_SIZE,
|
||
+ PROP_OPEN_PROXY,
|
||
+ PROP_PASTE_TARGET_LIST,
|
||
+ PROP_PRINT_PROXY,
|
||
+ PROP_SAVE_AS_PROXY,
|
||
+ PROP_SELECTED_URI
|
||
+};
|
||
+
|
||
+enum {
|
||
+ NEW_ACTIVITY,
|
||
+ POPUP_EVENT,
|
||
+ STATUS_MESSAGE,
|
||
+ STOP_LOADING,
|
||
+ UPDATE_ACTIONS,
|
||
+ PROCESS_MAILTO,
|
||
+ URI_REQUESTED,
|
||
+ CONTENT_LOADED,
|
||
+ BEFORE_POPUP_EVENT,
|
||
+ LAST_SIGNAL
|
||
+};
|
||
+
|
||
+static guint signals[LAST_SIGNAL];
|
||
+
|
||
+static const gchar *ui =
|
||
+"<ui>"
|
||
+" <popup name='context'>"
|
||
+" <menuitem action='copy-clipboard'/>"
|
||
+" <menuitem action='search-web'/>"
|
||
+" <separator/>"
|
||
+" <placeholder name='custom-actions-1'>"
|
||
+" <menuitem action='open'/>"
|
||
+" <menuitem action='save-as'/>"
|
||
+" <menuitem action='http-open'/>"
|
||
+" <menuitem action='send-message'/>"
|
||
+" <menuitem action='print'/>"
|
||
+" </placeholder>"
|
||
+" <placeholder name='custom-actions-2'>"
|
||
+" <menuitem action='uri-copy'/>"
|
||
+" <menuitem action='mailto-copy'/>"
|
||
+" <menuitem action='mailto-copy-raw'/>"
|
||
+" <menuitem action='image-copy'/>"
|
||
+" <menuitem action='image-save'/>"
|
||
+" </placeholder>"
|
||
+" <placeholder name='custom-actions-3'/>"
|
||
+" <separator/>"
|
||
+" <menuitem action='select-all'/>"
|
||
+" <placeholder name='inspect-menu' />"
|
||
+" </popup>"
|
||
+"</ui>";
|
||
+
|
||
+/* Forward Declarations */
|
||
+static void e_web_view_alert_sink_init (EAlertSinkInterface *iface);
|
||
+static void e_web_view_selectable_init (ESelectableInterface *iface);
|
||
+
|
||
+G_DEFINE_TYPE_WITH_CODE (
|
||
+ EWebView,
|
||
+ e_web_view,
|
||
+ WEBKIT_TYPE_WEB_VIEW,
|
||
+ G_IMPLEMENT_INTERFACE (
|
||
+ E_TYPE_EXTENSIBLE, NULL)
|
||
+ G_IMPLEMENT_INTERFACE (
|
||
+ E_TYPE_ALERT_SINK,
|
||
+ e_web_view_alert_sink_init)
|
||
+ G_IMPLEMENT_INTERFACE (
|
||
+ E_TYPE_SELECTABLE,
|
||
+ e_web_view_selectable_init))
|
||
+
|
||
+static void
|
||
+async_context_free (gpointer ptr)
|
||
+{
|
||
+ AsyncContext *async_context = ptr;
|
||
+
|
||
+ if (!async_context)
|
||
+ return;
|
||
+
|
||
+ g_clear_object (&async_context->activity);
|
||
+ g_clear_object (&async_context->destination);
|
||
+ g_clear_object (&async_context->input_stream);
|
||
+ g_clear_object (&async_context->content_request);
|
||
+ g_free (async_context->uri);
|
||
+
|
||
+ g_slice_free (AsyncContext, async_context);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_copy_clipboard_cb (GtkAction *action,
|
||
+ EWebView *web_view)
|
||
+{
|
||
+ e_web_view_copy_clipboard (web_view);
|
||
+}
|
||
+
|
||
+static void
|
||
+e_web_view_search_web_get_selection_cb (GObject *source,
|
||
+ GAsyncResult *result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ GSList *texts;
|
||
+ GError *local_error = NULL;
|
||
+
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (source));
|
||
+
|
||
+ e_web_view_jsc_get_selection_finish (WEBKIT_WEB_VIEW (source), result, &texts, &local_error);
|
||
+
|
||
+ if (local_error &&
|
||
+ !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||
+ e_alert_submit (E_ALERT_SINK (source), "widgets:get-selected-text-failed", local_error->message, NULL);
|
||
+ } else if (texts) {
|
||
+ GSettings *settings;
|
||
+ gchar *text = texts->data;
|
||
+ gchar *uri_prefix;
|
||
+ gchar *escaped;
|
||
+ gchar *uri;
|
||
+
|
||
+ g_strstrip (text);
|
||
+
|
||
+ settings = e_util_ref_settings ("org.gnome.evolution.shell");
|
||
+ uri_prefix = g_settings_get_string (settings, "search-web-uri-prefix");
|
||
+ g_object_unref (settings);
|
||
+
|
||
+ escaped = camel_url_encode (text, "& ?#:;,/\\");
|
||
+
|
||
+ uri = g_strconcat (uri_prefix, escaped, NULL);
|
||
+ if (uri && g_ascii_strncasecmp (uri, "https://", 8) == 0) {
|
||
+ GtkWidget *toplevel;
|
||
+
|
||
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (source));
|
||
+
|
||
+ e_show_uri (GTK_IS_WINDOW (toplevel) ? GTK_WINDOW (toplevel) : NULL, uri);
|
||
+ } else {
|
||
+ g_printerr ("Incorrect URI provided, expects https:// prefix, but has got: '%s'\n", uri ? uri : "null");
|
||
+ }
|
||
+
|
||
+ g_free (uri_prefix);
|
||
+ g_free (escaped);
|
||
+ g_free (uri);
|
||
+ }
|
||
+
|
||
+ g_clear_error (&local_error);
|
||
+ g_slist_free_full (texts, g_free);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_search_web_cb (GtkAction *action,
|
||
+ EWebView *web_view)
|
||
+{
|
||
+ e_web_view_jsc_get_selection (WEBKIT_WEB_VIEW (web_view), E_TEXT_FORMAT_PLAIN, web_view->priv->cancellable,
|
||
+ e_web_view_search_web_get_selection_cb, NULL);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_http_open_cb (GtkAction *action,
|
||
+ EWebView *web_view)
|
||
+{
|
||
+ const gchar *uri;
|
||
+ gpointer parent;
|
||
+
|
||
+ parent = gtk_widget_get_toplevel (GTK_WIDGET (web_view));
|
||
+ parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
|
||
+
|
||
+ uri = e_web_view_get_selected_uri (web_view);
|
||
+ g_return_if_fail (uri != NULL);
|
||
+
|
||
+ e_show_uri (parent, uri);
|
||
+}
|
||
+
|
||
+static void
|
||
+webview_mailto_copy (EWebView *web_view,
|
||
+ gboolean only_email_address)
|
||
+{
|
||
+ CamelURL *curl;
|
||
+ CamelInternetAddress *inet_addr;
|
||
+ GtkClipboard *clipboard;
|
||
+ const gchar *uri, *name = NULL, *email = NULL;
|
||
+ gchar *text;
|
||
+
|
||
+ uri = e_web_view_get_selected_uri (web_view);
|
||
+ g_return_if_fail (uri != NULL);
|
||
+
|
||
+ /* This should work because we checked it in update_actions(). */
|
||
+ curl = camel_url_new (uri, NULL);
|
||
+ g_return_if_fail (curl != NULL);
|
||
+
|
||
+ inet_addr = camel_internet_address_new ();
|
||
+ camel_address_decode (CAMEL_ADDRESS (inet_addr), curl->path);
|
||
+ if (only_email_address &&
|
||
+ camel_internet_address_get (inet_addr, 0, &name, &email) &&
|
||
+ email && *email) {
|
||
+ text = g_strdup (email);
|
||
+ } else {
|
||
+ text = camel_address_format (CAMEL_ADDRESS (inet_addr));
|
||
+ if (text == NULL || *text == '\0')
|
||
+ text = g_strdup (uri + strlen ("mailto:"));
|
||
+ }
|
||
+
|
||
+ g_object_unref (inet_addr);
|
||
+ camel_url_free (curl);
|
||
+
|
||
+ clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
|
||
+ gtk_clipboard_set_text (clipboard, text, -1);
|
||
+ gtk_clipboard_store (clipboard);
|
||
+
|
||
+ clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
|
||
+ gtk_clipboard_set_text (clipboard, text, -1);
|
||
+ gtk_clipboard_store (clipboard);
|
||
+
|
||
+ g_free (text);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mailto_copy_cb (GtkAction *action,
|
||
+ EWebView *web_view)
|
||
+{
|
||
+ webview_mailto_copy (web_view, FALSE);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mailto_copy_raw_cb (GtkAction *action,
|
||
+ EWebView *web_view)
|
||
+{
|
||
+ webview_mailto_copy (web_view, TRUE);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_select_all_cb (GtkAction *action,
|
||
+ EWebView *web_view)
|
||
+{
|
||
+ e_web_view_select_all (web_view);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_send_message_cb (GtkAction *action,
|
||
+ EWebView *web_view)
|
||
+{
|
||
+ const gchar *uri;
|
||
+ gpointer parent;
|
||
+ gboolean handled;
|
||
+
|
||
+ parent = gtk_widget_get_toplevel (GTK_WIDGET (web_view));
|
||
+ parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
|
||
+
|
||
+ uri = e_web_view_get_selected_uri (web_view);
|
||
+ g_return_if_fail (uri != NULL);
|
||
+
|
||
+ handled = FALSE;
|
||
+ g_signal_emit (web_view, signals[PROCESS_MAILTO], 0, uri, &handled);
|
||
+
|
||
+ if (!handled)
|
||
+ e_show_uri (parent, uri);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_uri_copy_cb (GtkAction *action,
|
||
+ EWebView *web_view)
|
||
+{
|
||
+ GtkClipboard *clipboard;
|
||
+ const gchar *uri;
|
||
+
|
||
+ uri = e_web_view_get_selected_uri (web_view);
|
||
+ g_return_if_fail (uri != NULL);
|
||
+
|
||
+ clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
|
||
+ gtk_clipboard_set_text (clipboard, uri, -1);
|
||
+ gtk_clipboard_store (clipboard);
|
||
+
|
||
+ clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
|
||
+ gtk_clipboard_set_text (clipboard, uri, -1);
|
||
+ gtk_clipboard_store (clipboard);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_image_copy_cb (GtkAction *action,
|
||
+ EWebView *web_view)
|
||
+{
|
||
+ e_web_view_cursor_image_copy (web_view);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_image_save_cb (GtkAction *action,
|
||
+ EWebView *web_view)
|
||
+{
|
||
+ e_web_view_cursor_image_save (web_view);
|
||
+}
|
||
+
|
||
+static GtkActionEntry uri_entries[] = {
|
||
+
|
||
+ { "uri-copy",
|
||
+ "edit-copy",
|
||
+ N_("_Copy Link Location"),
|
||
+ "<Control>c",
|
||
+ N_("Copy the link to the clipboard"),
|
||
+ G_CALLBACK (action_uri_copy_cb) }
|
||
+};
|
||
+
|
||
+static GtkActionEntry http_entries[] = {
|
||
+
|
||
+ { "http-open",
|
||
+ "emblem-web",
|
||
+ N_("_Open Link in Browser"),
|
||
+ NULL,
|
||
+ N_("Open the link in a web browser"),
|
||
+ G_CALLBACK (action_http_open_cb) }
|
||
+};
|
||
+
|
||
+static GtkActionEntry mailto_entries[] = {
|
||
+
|
||
+ { "mailto-copy",
|
||
+ "edit-copy",
|
||
+ N_("_Copy Email Address"),
|
||
+ "<Control>c",
|
||
+ N_("Copy the email address to the clipboard"),
|
||
+ G_CALLBACK (action_mailto_copy_cb) },
|
||
+
|
||
+ { "mailto-copy-raw",
|
||
+ "edit-copy",
|
||
+ N_("Copy _Raw Email Address"),
|
||
+ NULL,
|
||
+ N_("Copy the raw email address to the clipboard"),
|
||
+ G_CALLBACK (action_mailto_copy_raw_cb) },
|
||
+
|
||
+ { "send-message",
|
||
+ "mail-message-new",
|
||
+ N_("_Send New Message To…"),
|
||
+ NULL,
|
||
+ N_("Send a mail message to this address"),
|
||
+ G_CALLBACK (action_send_message_cb) }
|
||
+};
|
||
+
|
||
+static GtkActionEntry image_entries[] = {
|
||
+
|
||
+ { "image-copy",
|
||
+ "edit-copy",
|
||
+ N_("_Copy Image"),
|
||
+ "<Control>c",
|
||
+ N_("Copy the image to the clipboard"),
|
||
+ G_CALLBACK (action_image_copy_cb) },
|
||
+
|
||
+ { "image-save",
|
||
+ "document-save",
|
||
+ N_("Save _Image…"),
|
||
+ "<Control>s",
|
||
+ N_("Save the image to a file"),
|
||
+ G_CALLBACK (action_image_save_cb) }
|
||
+};
|
||
+
|
||
+static GtkActionEntry selection_entries[] = {
|
||
+
|
||
+ { "copy-clipboard",
|
||
+ "edit-copy",
|
||
+ N_("_Copy"),
|
||
+ "<Control>c",
|
||
+ N_("Copy the selection"),
|
||
+ G_CALLBACK (action_copy_clipboard_cb) },
|
||
+
|
||
+ { "search-web",
|
||
+ NULL,
|
||
+ N_("Search _Web…"),
|
||
+ NULL,
|
||
+ N_("Search the Web with the selected text"),
|
||
+ G_CALLBACK (action_search_web_cb) }
|
||
+};
|
||
+
|
||
+static GtkActionEntry standard_entries[] = {
|
||
+
|
||
+ { "select-all",
|
||
+ "edit-select-all",
|
||
+ N_("Select _All"),
|
||
+ NULL,
|
||
+ N_("Select all text and images"),
|
||
+ G_CALLBACK (action_select_all_cb) }
|
||
+};
|
||
+
|
||
+static void
|
||
+web_view_menu_item_select_cb (EWebView *web_view,
|
||
+ GtkWidget *widget)
|
||
+{
|
||
+ GtkAction *action;
|
||
+ GtkActivatable *activatable;
|
||
+ const gchar *tooltip;
|
||
+
|
||
+ activatable = GTK_ACTIVATABLE (widget);
|
||
+ action = gtk_activatable_get_related_action (activatable);
|
||
+ tooltip = gtk_action_get_tooltip (action);
|
||
+
|
||
+ if (tooltip == NULL)
|
||
+ return;
|
||
+
|
||
+ e_web_view_status_message (web_view, tooltip);
|
||
+}
|
||
+
|
||
+static void
|
||
+webkit_find_controller_found_text_cb (WebKitFindController *find_controller,
|
||
+ guint match_count,
|
||
+ EWebView *web_view)
|
||
+{
|
||
+ if (web_view->priv->highlights_enabled && !g_queue_is_empty (&web_view->priv->highlights))
|
||
+ e_web_view_unselect_all (web_view);
|
||
+}
|
||
+
|
||
+static void
|
||
+webkit_find_controller_failed_to_found_text_cb (WebKitFindController *find_controller,
|
||
+ EWebView *web_view)
|
||
+{
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_set_find_controller (EWebView *web_view)
|
||
+{
|
||
+ WebKitFindController *find_controller;
|
||
+
|
||
+ find_controller =
|
||
+ webkit_web_view_get_find_controller (WEBKIT_WEB_VIEW (web_view));
|
||
+
|
||
+ web_view->priv->found_text_handler_id = g_signal_connect (
|
||
+ find_controller, "found-text",
|
||
+ G_CALLBACK (webkit_find_controller_found_text_cb), web_view);
|
||
+
|
||
+ web_view->priv->failed_to_find_text_handler_id = g_signal_connect (
|
||
+ find_controller, "failed-to-find-text",
|
||
+ G_CALLBACK (webkit_find_controller_failed_to_found_text_cb), web_view);
|
||
+
|
||
+ web_view->priv->find_controller = find_controller;
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_update_document_highlights (EWebView *web_view)
|
||
+{
|
||
+ GList *head, *link;
|
||
+
|
||
+ head = g_queue_peek_head_link (&web_view->priv->highlights);
|
||
+
|
||
+ for (link = head; link != NULL; link = g_list_next (link)) {
|
||
+ webkit_find_controller_search (
|
||
+ web_view->priv->find_controller,
|
||
+ link->data,
|
||
+ WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE,
|
||
+ G_MAXUINT);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_menu_item_deselect_cb (EWebView *web_view)
|
||
+{
|
||
+ e_web_view_status_message (web_view, NULL);
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_connect_proxy_cb (EWebView *web_view,
|
||
+ GtkAction *action,
|
||
+ GtkWidget *proxy)
|
||
+{
|
||
+ if (!GTK_IS_MENU_ITEM (proxy))
|
||
+ return;
|
||
+
|
||
+ g_signal_connect_swapped (
|
||
+ proxy, "select",
|
||
+ G_CALLBACK (web_view_menu_item_select_cb), web_view);
|
||
+
|
||
+ g_signal_connect_swapped (
|
||
+ proxy, "deselect",
|
||
+ G_CALLBACK (web_view_menu_item_deselect_cb), web_view);
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_got_elem_from_point_for_popup_event_cb (GObject *source_object,
|
||
+ GAsyncResult *result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ EWebView *web_view;
|
||
+ GdkEvent *event = user_data;
|
||
+ GError *error = NULL;
|
||
+
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (source_object));
|
||
+
|
||
+ web_view = E_WEB_VIEW (source_object);
|
||
+
|
||
+ g_clear_pointer (&web_view->priv->last_popup_iframe_src, g_free);
|
||
+ g_clear_pointer (&web_view->priv->last_popup_iframe_id, g_free);
|
||
+ g_clear_pointer (&web_view->priv->last_popup_element_id, g_free);
|
||
+
|
||
+ if (!e_web_view_jsc_get_element_from_point_finish (WEBKIT_WEB_VIEW (web_view), result,
|
||
+ &web_view->priv->last_popup_iframe_src,
|
||
+ &web_view->priv->last_popup_iframe_id,
|
||
+ &web_view->priv->last_popup_element_id,
|
||
+ &error)) {
|
||
+ g_warning ("%s: Failed to get element from point: %s", G_STRFUNC, error ? error->message : "Unknown error");
|
||
+ }
|
||
+
|
||
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||
+ gboolean handled = FALSE;
|
||
+
|
||
+ g_signal_emit (web_view, signals[BEFORE_POPUP_EVENT], 0,
|
||
+ web_view->priv->last_popup_link_uri, NULL);
|
||
+
|
||
+ g_signal_emit (web_view, signals[POPUP_EVENT], 0,
|
||
+ web_view->priv->last_popup_link_uri, event, &handled);
|
||
+ }
|
||
+
|
||
+ if (event)
|
||
+ gdk_event_free (event);
|
||
+ g_clear_error (&error);
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+web_view_context_menu_cb (WebKitWebView *webkit_web_view,
|
||
+ WebKitContextMenu *context_menu,
|
||
+ GdkEvent *event,
|
||
+ WebKitHitTestResult *hit_test_result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ WebKitHitTestResultContext context;
|
||
+ EWebView *web_view;
|
||
+ gchar *link_uri = NULL;
|
||
+ gdouble xx, yy;
|
||
+
|
||
+ web_view = E_WEB_VIEW (webkit_web_view);
|
||
+
|
||
+ g_clear_pointer (&web_view->priv->cursor_image_src, g_free);
|
||
+ g_clear_pointer (&web_view->priv->last_popup_iframe_src, g_free);
|
||
+ g_clear_pointer (&web_view->priv->last_popup_iframe_id, g_free);
|
||
+ g_clear_pointer (&web_view->priv->last_popup_element_id, g_free);
|
||
+ g_clear_pointer (&web_view->priv->last_popup_link_uri, g_free);
|
||
+
|
||
+ if (!hit_test_result)
|
||
+ return FALSE;
|
||
+
|
||
+ context = webkit_hit_test_result_get_context (hit_test_result);
|
||
+
|
||
+ if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE) {
|
||
+ gchar *image_uri = NULL;
|
||
+
|
||
+ g_object_get (hit_test_result, "image-uri", &image_uri, NULL);
|
||
+
|
||
+ web_view->priv->cursor_image_src = image_uri;
|
||
+ }
|
||
+
|
||
+ if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK)
|
||
+ g_object_get (hit_test_result, "link-uri", &link_uri, NULL);
|
||
+
|
||
+ web_view->priv->last_popup_link_uri = link_uri;
|
||
+
|
||
+ if (!gdk_event_get_coords (event, &xx, &yy)) {
|
||
+ xx = 1;
|
||
+ yy = 1;
|
||
+ }
|
||
+
|
||
+ e_web_view_jsc_get_element_from_point (WEBKIT_WEB_VIEW (web_view), xx, yy, web_view->priv->cancellable,
|
||
+ web_view_got_elem_from_point_for_popup_event_cb, event ? gdk_event_copy (event) : NULL);
|
||
+
|
||
+ return TRUE;
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_mouse_target_changed_cb (EWebView *web_view,
|
||
+ WebKitHitTestResult *hit_test_result,
|
||
+ guint modifiers,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ EWebViewClass *class;
|
||
+ const gchar *title, *uri;
|
||
+
|
||
+ title = webkit_hit_test_result_get_link_title (hit_test_result);
|
||
+ uri = webkit_hit_test_result_get_link_uri (hit_test_result);
|
||
+
|
||
+ web_view->priv->has_hover_link = uri && *uri;
|
||
+
|
||
+ /* XXX WebKitWebView does not provide a class method for
|
||
+ * this signal, so we do so we can override the default
|
||
+ * behavior from subclasses for special URI types. */
|
||
+
|
||
+ class = E_WEB_VIEW_GET_CLASS (web_view);
|
||
+ g_return_if_fail (class != NULL);
|
||
+ g_return_if_fail (class->hovering_over_link != NULL);
|
||
+
|
||
+ class->hovering_over_link (web_view, title, uri);
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+web_view_decide_policy_cb (EWebView *web_view,
|
||
+ WebKitPolicyDecision *decision,
|
||
+ WebKitPolicyDecisionType type)
|
||
+{
|
||
+ EWebViewClass *class;
|
||
+ WebKitNavigationPolicyDecision *navigation_decision;
|
||
+ WebKitNavigationAction *navigation_action;
|
||
+ WebKitNavigationType navigation_type;
|
||
+ WebKitURIRequest *request;
|
||
+ const gchar *uri, *view_uri;
|
||
+
|
||
+ if (type != WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION &&
|
||
+ type != WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION)
|
||
+ return FALSE;
|
||
+
|
||
+ navigation_decision = WEBKIT_NAVIGATION_POLICY_DECISION (decision);
|
||
+ navigation_action = webkit_navigation_policy_decision_get_navigation_action (navigation_decision);
|
||
+ navigation_type = webkit_navigation_action_get_navigation_type (navigation_action);
|
||
+
|
||
+ if (navigation_type != WEBKIT_NAVIGATION_TYPE_LINK_CLICKED)
|
||
+ return FALSE;
|
||
+
|
||
+ request = webkit_navigation_action_get_request (navigation_action);
|
||
+ uri = webkit_uri_request_get_uri (request);
|
||
+ view_uri = webkit_web_view_get_uri (WEBKIT_WEB_VIEW (web_view));
|
||
+
|
||
+ /* Allow navigation through fragments in page */
|
||
+ if (uri && *uri && view_uri && *view_uri) {
|
||
+ GUri *uri_link, *uri_view;
|
||
+
|
||
+ uri_link = g_uri_parse (uri, SOUP_HTTP_URI_FLAGS | G_URI_FLAGS_PARSE_RELAXED, NULL);
|
||
+ uri_view = g_uri_parse (view_uri, SOUP_HTTP_URI_FLAGS | G_URI_FLAGS_PARSE_RELAXED, NULL);
|
||
+ if (uri_link && uri_view) {
|
||
+ const gchar *tmp1, *tmp2;
|
||
+
|
||
+ tmp1 = g_uri_get_scheme (uri_link);
|
||
+ tmp2 = g_uri_get_scheme (uri_view);
|
||
+
|
||
+ /* The scheme on both URIs should be the same */
|
||
+ if (tmp1 && tmp2 && g_ascii_strcasecmp (tmp1, tmp2) != 0)
|
||
+ goto free_uris;
|
||
+
|
||
+ tmp1 = g_uri_get_host (uri_link);
|
||
+ tmp2 = g_uri_get_host (uri_view);
|
||
+
|
||
+ /* The host on both URIs should be the same */
|
||
+ if (tmp1 && tmp2 && g_ascii_strcasecmp (tmp1, tmp2) != 0)
|
||
+ goto free_uris;
|
||
+
|
||
+ /* URI from link should have fragment set - could be empty */
|
||
+ if (g_uri_get_fragment (uri_link)) {
|
||
+ g_uri_unref (uri_link);
|
||
+ g_uri_unref (uri_view);
|
||
+ webkit_policy_decision_use (decision);
|
||
+ return TRUE;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ free_uris:
|
||
+ if (uri_link)
|
||
+ g_uri_unref (uri_link);
|
||
+ if (uri_view)
|
||
+ g_uri_unref (uri_view);
|
||
+ }
|
||
+
|
||
+ /* XXX WebKitWebView does not provide a class method for
|
||
+ * this signal, so we do so we can override the default
|
||
+ * behavior from subclasses for special URI types. */
|
||
+
|
||
+ class = E_WEB_VIEW_GET_CLASS (web_view);
|
||
+ g_return_val_if_fail (class != NULL, FALSE);
|
||
+ g_return_val_if_fail (class->link_clicked != NULL, FALSE);
|
||
+
|
||
+ webkit_policy_decision_ignore (decision);
|
||
+
|
||
+ class->link_clicked (web_view, uri);
|
||
+
|
||
+ return TRUE;
|
||
+}
|
||
+
|
||
+static void
|
||
+e_web_view_update_styles (EWebView *web_view,
|
||
+ const gchar *iframe_id)
|
||
+{
|
||
+ GdkRGBA color;
|
||
+ gchar *color_value;
|
||
+ gchar *style;
|
||
+ GtkStyleContext *style_context;
|
||
+ WebKitWebView *webkit_web_view;
|
||
+
|
||
+ style_context = gtk_widget_get_style_context (GTK_WIDGET (web_view));
|
||
+
|
||
+ if (gtk_style_context_lookup_color (style_context, "theme_base_color", &color))
|
||
+ color_value = g_strdup_printf ("#%06x", e_rgba_to_value (&color));
|
||
+ else {
|
||
+ color_value = g_strdup (E_UTILS_DEFAULT_THEME_BASE_COLOR);
|
||
+ if (!gdk_rgba_parse (&color, color_value)) {
|
||
+ color.red = 1.0;
|
||
+ color.green = 1.0;
|
||
+ color.blue = 1.0;
|
||
+ color.alpha = 1.0;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ style = g_strconcat ("background-color: ", color_value, ";", NULL);
|
||
+
|
||
+ webkit_web_view = WEBKIT_WEB_VIEW (web_view);
|
||
+
|
||
+ webkit_web_view_set_background_color (webkit_web_view, &color);
|
||
+
|
||
+ e_web_view_jsc_add_rule_into_style_sheet (webkit_web_view,
|
||
+ iframe_id,
|
||
+ "-e-web-view-style-sheet",
|
||
+ ".-e-web-view-background-color",
|
||
+ style,
|
||
+ web_view->priv->cancellable);
|
||
+
|
||
+ g_free (color_value);
|
||
+ g_free (style);
|
||
+
|
||
+ if (gtk_style_context_lookup_color (style_context, "theme_fg_color", &color))
|
||
+ color_value = g_strdup_printf ("#%06x", e_rgba_to_value (&color));
|
||
+ else
|
||
+ color_value = g_strdup (E_UTILS_DEFAULT_THEME_FG_COLOR);
|
||
+
|
||
+ style = g_strconcat ("color: ", color_value, ";", NULL);
|
||
+
|
||
+ e_web_view_jsc_add_rule_into_style_sheet (webkit_web_view,
|
||
+ iframe_id,
|
||
+ "-e-web-view-style-sheet",
|
||
+ ".-e-web-view-text-color",
|
||
+ style,
|
||
+ web_view->priv->cancellable);
|
||
+
|
||
+ g_free (color_value);
|
||
+ g_free (style);
|
||
+
|
||
+ e_web_view_jsc_add_rule_into_style_sheet (webkit_web_view,
|
||
+ iframe_id,
|
||
+ "-e-web-view-style-sheet",
|
||
+ "body, div, p, td",
|
||
+ "unicode-bidi: plaintext;",
|
||
+ web_view->priv->cancellable);
|
||
+}
|
||
+
|
||
+static void
|
||
+style_updated_cb (EWebView *web_view)
|
||
+{
|
||
+ e_web_view_update_styles (web_view, "*");
|
||
+}
|
||
+
|
||
+static void
|
||
+e_web_view_set_has_selection (EWebView *web_view,
|
||
+ gboolean has_selection)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ if ((!web_view->priv->has_selection) == (!has_selection))
|
||
+ return;
|
||
+
|
||
+ web_view->priv->has_selection = has_selection;
|
||
+
|
||
+ g_object_notify (G_OBJECT (web_view), "has-selection");
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_load_changed_cb (WebKitWebView *webkit_web_view,
|
||
+ WebKitLoadEvent load_event,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ EWebView *web_view;
|
||
+
|
||
+ web_view = E_WEB_VIEW (webkit_web_view);
|
||
+
|
||
+ if (load_event == WEBKIT_LOAD_STARTED) {
|
||
+ g_hash_table_remove_all (web_view->priv->element_clicked_cbs);
|
||
+ e_web_view_set_has_selection (web_view, FALSE);
|
||
+ }
|
||
+
|
||
+ if (load_event != WEBKIT_LOAD_FINISHED)
|
||
+ return;
|
||
+
|
||
+ /* Make sure the initialize function is called for the top document when it is loaded. */
|
||
+ e_web_view_jsc_run_script (webkit_web_view, web_view->priv->cancellable,
|
||
+ "Evo.EnsureMainDocumentInitialized();");
|
||
+
|
||
+ e_web_view_update_styles (web_view, "");
|
||
+
|
||
+ web_view_update_document_highlights (web_view);
|
||
+}
|
||
+
|
||
+static GObjectConstructParam*
|
||
+find_property (guint n_properties,
|
||
+ GObjectConstructParam* properties,
|
||
+ GParamSpec* param_spec)
|
||
+{
|
||
+ while (n_properties--) {
|
||
+ if (properties->pspec == param_spec)
|
||
+ return properties;
|
||
+ properties++;
|
||
+ }
|
||
+
|
||
+ return NULL;
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_uri_request_done_cb (GObject *source_object,
|
||
+ GAsyncResult *result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ WebKitURISchemeRequest *request = user_data;
|
||
+ GInputStream *stream = NULL;
|
||
+ gint64 stream_length = -1;
|
||
+ gchar *mime_type = NULL;
|
||
+ GError *error = NULL;
|
||
+
|
||
+ g_return_if_fail (E_IS_CONTENT_REQUEST (source_object));
|
||
+ g_return_if_fail (WEBKIT_IS_URI_SCHEME_REQUEST (request));
|
||
+
|
||
+ if (!e_content_request_process_finish (E_CONTENT_REQUEST (source_object),
|
||
+ result, &stream, &stream_length, &mime_type, &error)) {
|
||
+ if (!error)
|
||
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, "Failed to get '%s'", webkit_uri_scheme_request_get_uri (request));
|
||
+ webkit_uri_scheme_request_finish_error (request, error);
|
||
+ g_clear_error (&error);
|
||
+ } else {
|
||
+ webkit_uri_scheme_request_finish (request, stream, stream_length, mime_type);
|
||
+
|
||
+ g_clear_object (&stream);
|
||
+ g_free (mime_type);
|
||
+ }
|
||
+
|
||
+ g_object_unref (request);
|
||
+}
|
||
+
|
||
+static void
|
||
+e_web_view_process_uri_request (EWebView *web_view,
|
||
+ WebKitURISchemeRequest *request)
|
||
+{
|
||
+ EContentRequest *content_request;
|
||
+ const gchar *scheme;
|
||
+ const gchar *uri;
|
||
+ gchar *redirect_to_uri = NULL;
|
||
+
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+ g_return_if_fail (WEBKIT_IS_URI_SCHEME_REQUEST (request));
|
||
+
|
||
+ scheme = webkit_uri_scheme_request_get_scheme (request);
|
||
+ g_return_if_fail (scheme != NULL);
|
||
+
|
||
+ content_request = g_hash_table_lookup (web_view->priv->scheme_handlers, scheme);
|
||
+
|
||
+ if (!content_request) {
|
||
+ g_warning ("%s: Cannot find handler for scheme '%s'", G_STRFUNC, scheme);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ uri = webkit_uri_scheme_request_get_uri (request);
|
||
+
|
||
+ g_return_if_fail (e_content_request_can_process_uri (content_request, uri));
|
||
+
|
||
+ /* Expects an empty string to abandon the request,
|
||
+ or NULL to keep the passed-in uri,
|
||
+ or a new uri to load instead. */
|
||
+ g_signal_emit (web_view, signals[URI_REQUESTED], 0, uri, &redirect_to_uri);
|
||
+
|
||
+ if (redirect_to_uri && *redirect_to_uri) {
|
||
+ uri = redirect_to_uri;
|
||
+ } else if (redirect_to_uri) {
|
||
+ GError *error;
|
||
+
|
||
+ g_free (redirect_to_uri);
|
||
+
|
||
+ error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED, "Cancelled");
|
||
+
|
||
+ webkit_uri_scheme_request_finish_error (request, error);
|
||
+ g_clear_error (&error);
|
||
+
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ e_content_request_process (content_request, uri, G_OBJECT (web_view), web_view->priv->cancellable,
|
||
+ web_view_uri_request_done_cb, g_object_ref (request));
|
||
+
|
||
+ g_free (redirect_to_uri);
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_process_uri_request_cb (WebKitURISchemeRequest *request,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ WebKitWebView *web_view;
|
||
+
|
||
+ web_view = webkit_uri_scheme_request_get_web_view (request);
|
||
+
|
||
+ if (E_IS_WEB_VIEW (web_view)) {
|
||
+ e_web_view_process_uri_request (E_WEB_VIEW (web_view), request);
|
||
+ } else {
|
||
+ GError *error;
|
||
+
|
||
+ error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED, "Unexpected WebView type");
|
||
+ webkit_uri_scheme_request_finish_error (request, error);
|
||
+ g_clear_error (&error);
|
||
+
|
||
+ g_warning ("%s: Unexpected WebView type '%s' received", G_STRFUNC, web_view ? G_OBJECT_TYPE_NAME (web_view) : "null");
|
||
+
|
||
+ return;
|
||
+ }
|
||
+}
|
||
+
|
||
+static GSList *known_schemes = NULL;
|
||
+
|
||
+static void
|
||
+web_view_web_context_gone (gpointer user_data,
|
||
+ GObject *obj)
|
||
+{
|
||
+ gpointer *pweb_context = user_data;
|
||
+
|
||
+ g_return_if_fail (pweb_context != NULL);
|
||
+
|
||
+ *pweb_context = NULL;
|
||
+
|
||
+ g_slist_free_full (known_schemes, g_free);
|
||
+ known_schemes = NULL;
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_ensure_scheme_known (WebKitWebContext *web_context,
|
||
+ const gchar *scheme)
|
||
+{
|
||
+ GSList *link;
|
||
+
|
||
+ g_return_if_fail (WEBKIT_IS_WEB_CONTEXT (web_context));
|
||
+ g_return_if_fail (scheme != NULL);
|
||
+
|
||
+ for (link = known_schemes; link; link = g_slist_next (link)) {
|
||
+ if (g_strcmp0 (scheme, link->data) == 0)
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ if (!link) {
|
||
+ known_schemes = g_slist_prepend (known_schemes, g_strdup (scheme));
|
||
+
|
||
+ webkit_web_context_register_uri_scheme (web_context, scheme, web_view_process_uri_request_cb, NULL, NULL);
|
||
+ }
|
||
+}
|
||
+
|
||
+static GObject*
|
||
+web_view_constructor (GType type,
|
||
+ guint n_construct_properties,
|
||
+ GObjectConstructParam *construct_properties)
|
||
+{
|
||
+ GObjectClass* object_class;
|
||
+ GParamSpec* param_spec;
|
||
+ GObjectConstructParam *param = NULL;
|
||
+
|
||
+ object_class = G_OBJECT_CLASS (g_type_class_ref(type));
|
||
+ g_return_val_if_fail (object_class != NULL, NULL);
|
||
+
|
||
+ if (construct_properties && n_construct_properties != 0) {
|
||
+ param_spec = g_object_class_find_property (object_class, "settings");
|
||
+ if ((param = find_property (n_construct_properties, construct_properties, param_spec)))
|
||
+ g_value_take_object (param->value, e_web_view_get_default_webkit_settings ());
|
||
+ param_spec = g_object_class_find_property(object_class, "user-content-manager");
|
||
+ if ((param = find_property (n_construct_properties, construct_properties, param_spec)))
|
||
+ g_value_take_object (param->value, webkit_user_content_manager_new ());
|
||
+ param_spec = g_object_class_find_property (object_class, "web-context");
|
||
+ if ((param = find_property (n_construct_properties, construct_properties, param_spec))) {
|
||
+ /* Share one web_context between all previews. */
|
||
+ static gpointer web_context = NULL;
|
||
+
|
||
+ if (!web_context) {
|
||
+ GSList *link;
|
||
+ gchar *plugins_path;
|
||
+ #ifdef ENABLE_MAINTAINER_MODE
|
||
+ const gchar *source_webkitdatadir;
|
||
+ #endif
|
||
+
|
||
+ web_context = webkit_web_context_new ();
|
||
+
|
||
+ webkit_web_context_set_cache_model (web_context, WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER);
|
||
+ webkit_web_context_set_web_extensions_directory (web_context, EVOLUTION_WEB_EXTENSIONS_DIR);
|
||
+ webkit_web_context_set_sandbox_enabled (web_context, TRUE);
|
||
+ webkit_web_context_add_path_to_sandbox (web_context, EVOLUTION_WEBKITDATADIR, TRUE);
|
||
+
|
||
+ plugins_path = g_build_filename (e_get_user_data_dir (), "preview-plugins", NULL);
|
||
+ webkit_web_context_add_path_to_sandbox (web_context, plugins_path, TRUE);
|
||
+ g_free (plugins_path);
|
||
+
|
||
+ #ifdef ENABLE_MAINTAINER_MODE
|
||
+ source_webkitdatadir = g_getenv ("EVOLUTION_SOURCE_WEBKITDATADIR");
|
||
+ if (source_webkitdatadir && *source_webkitdatadir)
|
||
+ webkit_web_context_add_path_to_sandbox (web_context, source_webkitdatadir, TRUE);
|
||
+ #endif
|
||
+
|
||
+ g_object_weak_ref (G_OBJECT (web_context), web_view_web_context_gone, &web_context);
|
||
+
|
||
+ for (link = known_schemes; link; link = g_slist_next (link)) {
|
||
+ const gchar *scheme = link->data;
|
||
+
|
||
+ webkit_web_context_register_uri_scheme (web_context, scheme, web_view_process_uri_request_cb, NULL, NULL);
|
||
+ }
|
||
+ } else {
|
||
+ g_object_ref (web_context);
|
||
+ }
|
||
+
|
||
+ g_value_take_object (param->value, web_context);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ g_type_class_unref (object_class);
|
||
+
|
||
+ return G_OBJECT_CLASS (e_web_view_parent_class)->constructor (type, n_construct_properties, construct_properties);
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_set_property (GObject *object,
|
||
+ guint property_id,
|
||
+ const GValue *value,
|
||
+ GParamSpec *pspec)
|
||
+{
|
||
+ switch (property_id) {
|
||
+ case PROP_CARET_MODE:
|
||
+ e_web_view_set_caret_mode (
|
||
+ E_WEB_VIEW (object),
|
||
+ g_value_get_boolean (value));
|
||
+ return;
|
||
+
|
||
+ case PROP_COPY_TARGET_LIST:
|
||
+ /* This is a fake property. */
|
||
+ g_warning ("%s: EWebView::copy-target-list not used", G_STRFUNC);
|
||
+ return;
|
||
+
|
||
+ case PROP_CURSOR_IMAGE_SRC:
|
||
+ e_web_view_set_cursor_image_src (
|
||
+ E_WEB_VIEW (object),
|
||
+ g_value_get_string (value));
|
||
+ return;
|
||
+
|
||
+ case PROP_DISABLE_PRINTING:
|
||
+ e_web_view_set_disable_printing (
|
||
+ E_WEB_VIEW (object),
|
||
+ g_value_get_boolean (value));
|
||
+ return;
|
||
+
|
||
+ case PROP_DISABLE_SAVE_TO_DISK:
|
||
+ e_web_view_set_disable_save_to_disk (
|
||
+ E_WEB_VIEW (object),
|
||
+ g_value_get_boolean (value));
|
||
+ return;
|
||
+
|
||
+ case PROP_MINIMUM_FONT_SIZE:
|
||
+ e_web_view_set_minimum_font_size (
|
||
+ E_WEB_VIEW (object),
|
||
+ g_value_get_int (value));
|
||
+ return;
|
||
+
|
||
+ case PROP_OPEN_PROXY:
|
||
+ e_web_view_set_open_proxy (
|
||
+ E_WEB_VIEW (object),
|
||
+ g_value_get_object (value));
|
||
+ return;
|
||
+
|
||
+ case PROP_PASTE_TARGET_LIST:
|
||
+ /* This is a fake property. */
|
||
+ g_warning ("%s: EWebView::paste-target-list not used", G_STRFUNC);
|
||
+ return;
|
||
+
|
||
+ case PROP_PRINT_PROXY:
|
||
+ e_web_view_set_print_proxy (
|
||
+ E_WEB_VIEW (object),
|
||
+ g_value_get_object (value));
|
||
+ return;
|
||
+
|
||
+ case PROP_SAVE_AS_PROXY:
|
||
+ e_web_view_set_save_as_proxy (
|
||
+ E_WEB_VIEW (object),
|
||
+ g_value_get_object (value));
|
||
+ return;
|
||
+
|
||
+ case PROP_SELECTED_URI:
|
||
+ e_web_view_set_selected_uri (
|
||
+ E_WEB_VIEW (object),
|
||
+ g_value_get_string (value));
|
||
+ return;
|
||
+ }
|
||
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_get_property (GObject *object,
|
||
+ guint property_id,
|
||
+ GValue *value,
|
||
+ GParamSpec *pspec)
|
||
+{
|
||
+ switch (property_id) {
|
||
+ case PROP_CARET_MODE:
|
||
+ g_value_set_boolean (
|
||
+ value, e_web_view_get_caret_mode (
|
||
+ E_WEB_VIEW (object)));
|
||
+ return;
|
||
+
|
||
+ case PROP_COPY_TARGET_LIST:
|
||
+ /* This is a fake property. */
|
||
+ g_value_set_boxed (value, NULL);
|
||
+ return;
|
||
+
|
||
+ case PROP_CURSOR_IMAGE_SRC:
|
||
+ g_value_set_string (
|
||
+ value, e_web_view_get_cursor_image_src (
|
||
+ E_WEB_VIEW (object)));
|
||
+ return;
|
||
+
|
||
+ case PROP_DISABLE_PRINTING:
|
||
+ g_value_set_boolean (
|
||
+ value, e_web_view_get_disable_printing (
|
||
+ E_WEB_VIEW (object)));
|
||
+ return;
|
||
+
|
||
+ case PROP_DISABLE_SAVE_TO_DISK:
|
||
+ g_value_set_boolean (
|
||
+ value, e_web_view_get_disable_save_to_disk (
|
||
+ E_WEB_VIEW (object)));
|
||
+ return;
|
||
+
|
||
+ case PROP_HAS_SELECTION:
|
||
+ g_value_set_boolean (value, e_web_view_has_selection (E_WEB_VIEW (object)));
|
||
+ return;
|
||
+
|
||
+ case PROP_MINIMUM_FONT_SIZE:
|
||
+ g_value_set_int (
|
||
+ value, e_web_view_get_minimum_font_size (
|
||
+ E_WEB_VIEW (object)));
|
||
+ return;
|
||
+
|
||
+ case PROP_NEED_INPUT:
|
||
+ g_value_set_boolean (
|
||
+ value, e_web_view_get_need_input (
|
||
+ E_WEB_VIEW (object)));
|
||
+ return;
|
||
+
|
||
+ case PROP_OPEN_PROXY:
|
||
+ g_value_set_object (
|
||
+ value, e_web_view_get_open_proxy (
|
||
+ E_WEB_VIEW (object)));
|
||
+ return;
|
||
+
|
||
+ case PROP_PASTE_TARGET_LIST:
|
||
+ /* This is a fake property. */
|
||
+ g_value_set_boxed (value, NULL);
|
||
+ return;
|
||
+
|
||
+ case PROP_PRINT_PROXY:
|
||
+ g_value_set_object (
|
||
+ value, e_web_view_get_print_proxy (
|
||
+ E_WEB_VIEW (object)));
|
||
+ return;
|
||
+
|
||
+ case PROP_SAVE_AS_PROXY:
|
||
+ g_value_set_object (
|
||
+ value, e_web_view_get_save_as_proxy (
|
||
+ E_WEB_VIEW (object)));
|
||
+ return;
|
||
+
|
||
+ case PROP_SELECTED_URI:
|
||
+ g_value_set_string (
|
||
+ value, e_web_view_get_selected_uri (
|
||
+ E_WEB_VIEW (object)));
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_dispose (GObject *object)
|
||
+{
|
||
+ EWebViewPrivate *priv;
|
||
+
|
||
+ /* This can be called during dispose, thus disconnect early */
|
||
+ g_signal_handlers_disconnect_by_func (object, G_CALLBACK (style_updated_cb), NULL);
|
||
+
|
||
+ priv = E_WEB_VIEW_GET_PRIVATE (object);
|
||
+
|
||
+ if (priv->cancellable) {
|
||
+ g_cancellable_cancel (priv->cancellable);
|
||
+ g_clear_object (&priv->cancellable);
|
||
+ }
|
||
+
|
||
+ if (priv->font_name_changed_handler_id > 0) {
|
||
+ g_signal_handler_disconnect (
|
||
+ priv->font_settings,
|
||
+ priv->font_name_changed_handler_id);
|
||
+ priv->font_name_changed_handler_id = 0;
|
||
+ }
|
||
+
|
||
+ if (priv->monospace_font_name_changed_handler_id > 0) {
|
||
+ g_signal_handler_disconnect (
|
||
+ priv->font_settings,
|
||
+ priv->monospace_font_name_changed_handler_id);
|
||
+ priv->monospace_font_name_changed_handler_id = 0;
|
||
+ }
|
||
+
|
||
+ if (priv->found_text_handler_id > 0) {
|
||
+ g_signal_handler_disconnect (
|
||
+ priv->find_controller,
|
||
+ priv->found_text_handler_id);
|
||
+ priv->found_text_handler_id = 0;
|
||
+ }
|
||
+
|
||
+ if (priv->failed_to_find_text_handler_id > 0) {
|
||
+ g_signal_handler_disconnect (
|
||
+ priv->find_controller,
|
||
+ priv->failed_to_find_text_handler_id);
|
||
+ priv->failed_to_find_text_handler_id = 0;
|
||
+ }
|
||
+
|
||
+ g_hash_table_remove_all (priv->scheme_handlers);
|
||
+ g_hash_table_remove_all (priv->element_clicked_cbs);
|
||
+
|
||
+ g_clear_object (&priv->ui_manager);
|
||
+ g_clear_object (&priv->open_proxy);
|
||
+ g_clear_object (&priv->print_proxy);
|
||
+ g_clear_object (&priv->save_as_proxy);
|
||
+ g_clear_object (&priv->font_settings);
|
||
+
|
||
+ /* Chain up to parent's dispose() method. */
|
||
+ G_OBJECT_CLASS (e_web_view_parent_class)->dispose (object);
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_finalize (GObject *object)
|
||
+{
|
||
+ EWebViewPrivate *priv;
|
||
+
|
||
+ priv = E_WEB_VIEW_GET_PRIVATE (object);
|
||
+
|
||
+ g_clear_pointer (&priv->last_popup_iframe_src, g_free);
|
||
+ g_clear_pointer (&priv->last_popup_iframe_id, g_free);
|
||
+ g_clear_pointer (&priv->last_popup_element_id, g_free);
|
||
+ g_clear_pointer (&priv->last_popup_link_uri, g_free);
|
||
+ g_free (priv->selected_uri);
|
||
+ g_free (priv->cursor_image_src);
|
||
+
|
||
+ while (!g_queue_is_empty (&priv->highlights))
|
||
+ g_free (g_queue_pop_head (&priv->highlights));
|
||
+
|
||
+ g_clear_pointer (&priv->old_settings, g_hash_table_destroy);
|
||
+
|
||
+ g_hash_table_destroy (priv->scheme_handlers);
|
||
+ g_hash_table_destroy (priv->element_clicked_cbs);
|
||
+
|
||
+ /* Chain up to parent's finalize() method. */
|
||
+ G_OBJECT_CLASS (e_web_view_parent_class)->finalize (object);
|
||
+}
|
||
+
|
||
+/* 'scheme' is like "file", not "file:" */
|
||
+void
|
||
+e_web_view_register_content_request_for_scheme (EWebView *web_view,
|
||
+ const gchar *scheme,
|
||
+ EContentRequest *content_request)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+ g_return_if_fail (E_IS_CONTENT_REQUEST (content_request));
|
||
+ g_return_if_fail (scheme != NULL);
|
||
+
|
||
+ g_hash_table_insert (web_view->priv->scheme_handlers, g_strdup (scheme), g_object_ref (content_request));
|
||
+
|
||
+ web_view_ensure_scheme_known (webkit_web_view_get_context (WEBKIT_WEB_VIEW (web_view)), scheme);
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_initialize (WebKitWebView *web_view)
|
||
+{
|
||
+ EContentRequest *content_request;
|
||
+ GSettings *font_settings;
|
||
+
|
||
+ content_request = e_file_request_new ();
|
||
+ e_web_view_register_content_request_for_scheme (E_WEB_VIEW (web_view), "evo-file", content_request);
|
||
+ g_object_unref (content_request);
|
||
+
|
||
+ content_request = e_stock_request_new ();
|
||
+ e_binding_bind_property (web_view, "scale-factor",
|
||
+ content_request, "scale-factor",
|
||
+ G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
|
||
+ e_web_view_register_content_request_for_scheme (E_WEB_VIEW (web_view), "gtk-stock", content_request);
|
||
+ g_object_unref (content_request);
|
||
+
|
||
+ font_settings = e_util_ref_settings ("org.gnome.desktop.interface");
|
||
+
|
||
+ e_web_view_update_fonts_settings (font_settings, NULL, NULL, GTK_WIDGET (web_view));
|
||
+
|
||
+ g_object_unref (font_settings);
|
||
+}
|
||
+
|
||
+static void
|
||
+e_web_view_initialize_web_extensions_cb (WebKitWebContext *web_context,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ EWebView *web_view = user_data;
|
||
+
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ webkit_web_context_set_web_extensions_directory (web_context, EVOLUTION_WEB_EXTENSIONS_DIR);
|
||
+}
|
||
+
|
||
+static void
|
||
+e_web_view_element_clicked_cb (WebKitUserContentManager *manager,
|
||
+ WebKitJavascriptResult *js_result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ EWebView *web_view = user_data;
|
||
+ GtkAllocation elem_position;
|
||
+ GPtrArray *listeners;
|
||
+ JSCValue *jsc_object;
|
||
+ gchar *iframe_id, *elem_id, *elem_class, *elem_value;
|
||
+ gdouble zoom_level;
|
||
+
|
||
+ g_return_if_fail (web_view != NULL);
|
||
+ g_return_if_fail (js_result != NULL);
|
||
+
|
||
+ jsc_object = webkit_javascript_result_get_js_value (js_result);
|
||
+ g_return_if_fail (jsc_value_is_object (jsc_object));
|
||
+
|
||
+ iframe_id = e_web_view_jsc_get_object_property_string (jsc_object, "iframe-id", NULL);
|
||
+ elem_id = e_web_view_jsc_get_object_property_string (jsc_object, "elem-id", NULL);
|
||
+ elem_class = e_web_view_jsc_get_object_property_string (jsc_object, "elem-class", NULL);
|
||
+ elem_value = e_web_view_jsc_get_object_property_string (jsc_object, "elem-value", NULL);
|
||
+ elem_position.x = e_web_view_jsc_get_object_property_int32 (jsc_object, "left", 0);
|
||
+ elem_position.y = e_web_view_jsc_get_object_property_int32 (jsc_object, "top", 0);
|
||
+ elem_position.width = e_web_view_jsc_get_object_property_int32 (jsc_object, "width", 0);
|
||
+ elem_position.height = e_web_view_jsc_get_object_property_int32 (jsc_object, "height", 0);
|
||
+
|
||
+ zoom_level = webkit_web_view_get_zoom_level (WEBKIT_WEB_VIEW (web_view));
|
||
+ elem_position.x *= zoom_level;
|
||
+ elem_position.y *= zoom_level;
|
||
+ elem_position.width *= zoom_level;
|
||
+ elem_position.height *= zoom_level;
|
||
+
|
||
+ listeners = g_hash_table_lookup (web_view->priv->element_clicked_cbs, elem_class);
|
||
+
|
||
+ if (listeners) {
|
||
+ guint ii;
|
||
+
|
||
+ for (ii = 0; ii < listeners->len; ii++) {
|
||
+ ElementClickedData *ecd = g_ptr_array_index (listeners, ii);
|
||
+
|
||
+ if (ecd && ecd->callback)
|
||
+ ecd->callback (web_view, iframe_id, elem_id, elem_class, elem_value, &elem_position, ecd->user_data);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ g_free (iframe_id);
|
||
+ g_free (elem_id);
|
||
+ g_free (elem_class);
|
||
+ g_free (elem_value);
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_call_register_element_clicked (EWebView *web_view,
|
||
+ const gchar *iframe_id,
|
||
+ const gchar *only_elem_class)
|
||
+{
|
||
+ gchar *elem_classes = NULL;
|
||
+
|
||
+ if (!only_elem_class) {
|
||
+ GHashTableIter iter;
|
||
+ gpointer key;
|
||
+ GString *classes;
|
||
+
|
||
+ classes = g_string_sized_new (128);
|
||
+
|
||
+ g_hash_table_iter_init (&iter, web_view->priv->element_clicked_cbs);
|
||
+ while (g_hash_table_iter_next (&iter, &key, NULL)) {
|
||
+ if (classes->len)
|
||
+ g_string_append_c (classes, '\n');
|
||
+
|
||
+ g_string_append (classes, key);
|
||
+ }
|
||
+
|
||
+ elem_classes = g_string_free (classes, FALSE);
|
||
+ }
|
||
+
|
||
+ e_web_view_jsc_register_element_clicked (WEBKIT_WEB_VIEW (web_view), iframe_id,
|
||
+ only_elem_class ? only_elem_class : elem_classes,
|
||
+ web_view->priv->cancellable);
|
||
+
|
||
+ g_free (elem_classes);
|
||
+}
|
||
+
|
||
+static void
|
||
+e_web_view_content_loaded_cb (WebKitUserContentManager *manager,
|
||
+ WebKitJavascriptResult *js_result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ EWebView *web_view = user_data;
|
||
+ JSCValue *jsc_value;
|
||
+ gchar *iframe_id;
|
||
+
|
||
+ g_return_if_fail (web_view != NULL);
|
||
+ g_return_if_fail (js_result != NULL);
|
||
+
|
||
+ jsc_value = webkit_javascript_result_get_js_value (js_result);
|
||
+ g_return_if_fail (jsc_value_is_string (jsc_value));
|
||
+
|
||
+ iframe_id = jsc_value_to_string (jsc_value);
|
||
+
|
||
+ if (!iframe_id || !*iframe_id)
|
||
+ e_web_view_update_fonts (web_view);
|
||
+ else
|
||
+ e_web_view_update_styles (web_view, iframe_id);
|
||
+
|
||
+ web_view_call_register_element_clicked (web_view, iframe_id, NULL);
|
||
+
|
||
+ g_signal_emit (web_view, signals[CONTENT_LOADED], 0, iframe_id);
|
||
+
|
||
+ g_free (iframe_id);
|
||
+}
|
||
+
|
||
+static void
|
||
+e_web_view_has_selection_cb (WebKitUserContentManager *manager,
|
||
+ WebKitJavascriptResult *js_result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ EWebView *web_view = user_data;
|
||
+ JSCValue *jsc_value;
|
||
+
|
||
+ g_return_if_fail (web_view != NULL);
|
||
+ g_return_if_fail (js_result != NULL);
|
||
+
|
||
+ jsc_value = webkit_javascript_result_get_js_value (js_result);
|
||
+ g_return_if_fail (jsc_value_is_boolean (jsc_value));
|
||
+
|
||
+ e_web_view_set_has_selection (web_view, jsc_value_to_boolean (jsc_value));
|
||
+}
|
||
+
|
||
+static void
|
||
+e_web_view_set_need_input (EWebView *web_view,
|
||
+ gboolean need_input)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ if ((!web_view->priv->need_input) == (!need_input))
|
||
+ return;
|
||
+
|
||
+ web_view->priv->need_input = need_input;
|
||
+
|
||
+ g_object_notify (G_OBJECT (web_view), "need-input");
|
||
+}
|
||
+
|
||
+static void
|
||
+e_web_view_need_input_changed_cb (WebKitUserContentManager *manager,
|
||
+ WebKitJavascriptResult *js_result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ EWebView *web_view = user_data;
|
||
+ JSCValue *jsc_value;
|
||
+
|
||
+ g_return_if_fail (web_view != NULL);
|
||
+ g_return_if_fail (js_result != NULL);
|
||
+
|
||
+ jsc_value = webkit_javascript_result_get_js_value (js_result);
|
||
+ g_return_if_fail (jsc_value_is_boolean (jsc_value));
|
||
+
|
||
+ e_web_view_set_need_input (web_view, jsc_value_to_boolean (jsc_value));
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_constructed (GObject *object)
|
||
+{
|
||
+ WebKitSettings *web_settings;
|
||
+ WebKitUserContentManager *manager;
|
||
+ EWebView *web_view = E_WEB_VIEW (object);
|
||
+ GSettings *settings;
|
||
+
|
||
+#ifndef G_OS_WIN32
|
||
+ settings = e_util_ref_settings ("org.gnome.desktop.lockdown");
|
||
+
|
||
+ g_settings_bind (
|
||
+ settings, "disable-printing",
|
||
+ object, "disable-printing",
|
||
+ G_SETTINGS_BIND_GET);
|
||
+
|
||
+ g_settings_bind (
|
||
+ settings, "disable-save-to-disk",
|
||
+ object, "disable-save-to-disk",
|
||
+ G_SETTINGS_BIND_GET);
|
||
+
|
||
+ g_object_unref (settings);
|
||
+#endif
|
||
+
|
||
+ settings = e_util_ref_settings ("org.gnome.evolution.shell");
|
||
+
|
||
+ g_settings_bind (
|
||
+ settings, "webkit-minimum-font-size",
|
||
+ object, "minimum-font-size",
|
||
+ G_SETTINGS_BIND_GET);
|
||
+
|
||
+ g_clear_object (&settings);
|
||
+
|
||
+ g_signal_connect_object (webkit_web_view_get_context (WEBKIT_WEB_VIEW (web_view)), "initialize-web-extensions",
|
||
+ G_CALLBACK (e_web_view_initialize_web_extensions_cb), web_view, 0);
|
||
+
|
||
+ /* Chain up to parent's constructed() method. */
|
||
+ G_OBJECT_CLASS (e_web_view_parent_class)->constructed (object);
|
||
+
|
||
+ e_extensible_load_extensions (E_EXTENSIBLE (object));
|
||
+
|
||
+ web_settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW (object));
|
||
+ webkit_settings_set_enable_write_console_messages_to_stdout (web_settings, e_util_get_webkit_developer_mode_enabled ());
|
||
+
|
||
+ g_object_set (
|
||
+ G_OBJECT (web_settings),
|
||
+ "default-charset", "UTF-8",
|
||
+ NULL);
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ web_settings, "enable-caret-browsing",
|
||
+ E_WEB_VIEW (object), "caret-mode",
|
||
+ G_BINDING_BIDIRECTIONAL |
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ web_view_initialize (WEBKIT_WEB_VIEW (object));
|
||
+
|
||
+ web_view_set_find_controller (web_view);
|
||
+
|
||
+ manager = webkit_web_view_get_user_content_manager (WEBKIT_WEB_VIEW (object));
|
||
+
|
||
+ g_signal_connect_object (manager, "script-message-received::elementClicked",
|
||
+ G_CALLBACK (e_web_view_element_clicked_cb), web_view, 0);
|
||
+
|
||
+ g_signal_connect_object (manager, "script-message-received::contentLoaded",
|
||
+ G_CALLBACK (e_web_view_content_loaded_cb), web_view, 0);
|
||
+
|
||
+ g_signal_connect_object (manager, "script-message-received::hasSelection",
|
||
+ G_CALLBACK (e_web_view_has_selection_cb), web_view, 0);
|
||
+
|
||
+ g_signal_connect_object (manager, "script-message-received::needInputChanged",
|
||
+ G_CALLBACK (e_web_view_need_input_changed_cb), web_view, 0);
|
||
+
|
||
+ webkit_user_content_manager_register_script_message_handler (manager, "contentLoaded");
|
||
+ webkit_user_content_manager_register_script_message_handler (manager, "elementClicked");
|
||
+ webkit_user_content_manager_register_script_message_handler (manager, "hasSelection");
|
||
+ webkit_user_content_manager_register_script_message_handler (manager, "needInputChanged");
|
||
+}
|
||
+
|
||
+static void
|
||
+e_web_view_replace_load_cancellable (EWebView *web_view,
|
||
+ gboolean create_new)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ if (web_view->priv->cancellable) {
|
||
+ g_cancellable_cancel (web_view->priv->cancellable);
|
||
+ g_clear_object (&web_view->priv->cancellable);
|
||
+ }
|
||
+
|
||
+ if (create_new)
|
||
+ web_view->priv->cancellable = g_cancellable_new ();
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+web_view_scroll_event (GtkWidget *widget,
|
||
+ GdkEventScroll *event)
|
||
+{
|
||
+ if (event->state & GDK_CONTROL_MASK) {
|
||
+ GdkScrollDirection direction = event->direction;
|
||
+
|
||
+ if (direction == GDK_SCROLL_SMOOTH) {
|
||
+ static gdouble total_delta_y = 0.0;
|
||
+
|
||
+ total_delta_y += event->delta_y;
|
||
+
|
||
+ if (total_delta_y >= 1.0) {
|
||
+ total_delta_y = 0.0;
|
||
+ direction = GDK_SCROLL_DOWN;
|
||
+ } else if (total_delta_y <= -1.0) {
|
||
+ total_delta_y = 0.0;
|
||
+ direction = GDK_SCROLL_UP;
|
||
+ } else if (event->delta_y >= 1e-9 || event->delta_y <= -1e-9) {
|
||
+ return TRUE;
|
||
+ } else {
|
||
+ return FALSE;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ switch (direction) {
|
||
+ case GDK_SCROLL_UP:
|
||
+ e_web_view_zoom_in (E_WEB_VIEW (widget));
|
||
+ return TRUE;
|
||
+ case GDK_SCROLL_DOWN:
|
||
+ e_web_view_zoom_out (E_WEB_VIEW (widget));
|
||
+ return TRUE;
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return GTK_WIDGET_CLASS (e_web_view_parent_class)->
|
||
+ scroll_event (widget, event);
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+web_view_drag_motion (GtkWidget *widget,
|
||
+ GdkDragContext *context,
|
||
+ gint x,
|
||
+ gint y,
|
||
+ guint time_)
|
||
+{
|
||
+ /* Made this way to not pretend that this is a drop zone,
|
||
+ when only FALSE had been returned, even it is supposed
|
||
+ to be enough. Remove web_view_drag_leave() once fixed. */
|
||
+ gdk_drag_status (context, 0, time_);
|
||
+
|
||
+ return TRUE;
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+web_view_drag_drop (GtkWidget *widget,
|
||
+ GdkDragContext *context,
|
||
+ gint x,
|
||
+ gint y,
|
||
+ guint time_)
|
||
+{
|
||
+ /* Defined to avoid crash in WebKit */
|
||
+ return FALSE;
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_drag_leave (GtkWidget *widget,
|
||
+ GdkDragContext *context,
|
||
+ guint time_)
|
||
+{
|
||
+ /* Defined to avoid crash in WebKit, when the web_view_drag_motion()
|
||
+ uses the other way around. */
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_hovering_over_link (EWebView *web_view,
|
||
+ const gchar *title,
|
||
+ const gchar *uri)
|
||
+{
|
||
+ gchar *message = e_util_get_uri_tooltip (uri);
|
||
+
|
||
+ e_web_view_status_message (web_view, message);
|
||
+
|
||
+ g_free (message);
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_link_clicked (EWebView *web_view,
|
||
+ const gchar *uri)
|
||
+{
|
||
+ gpointer parent;
|
||
+
|
||
+ if (uri && g_ascii_strncasecmp (uri, "mailto:", 7) == 0) {
|
||
+ gboolean handled = FALSE;
|
||
+
|
||
+ g_signal_emit (
|
||
+ web_view, signals[PROCESS_MAILTO], 0, uri, &handled);
|
||
+
|
||
+ if (handled)
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ parent = gtk_widget_get_toplevel (GTK_WIDGET (web_view));
|
||
+ parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
|
||
+
|
||
+ e_show_uri (parent, uri);
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_load_string (EWebView *web_view,
|
||
+ const gchar *string)
|
||
+{
|
||
+ if (!string || !*string) {
|
||
+ webkit_web_view_load_html (WEBKIT_WEB_VIEW (web_view), "", "evo-file:///");
|
||
+ } else {
|
||
+ GBytes *bytes;
|
||
+
|
||
+ bytes = g_bytes_new (string, strlen (string));
|
||
+ webkit_web_view_load_bytes (WEBKIT_WEB_VIEW (web_view), bytes, NULL, NULL, "evo-file:///");
|
||
+ g_bytes_unref (bytes);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_load_uri (EWebView *web_view,
|
||
+ const gchar *uri)
|
||
+{
|
||
+ if (!uri)
|
||
+ uri = "about:blank";
|
||
+
|
||
+ webkit_web_view_load_uri (WEBKIT_WEB_VIEW (web_view), uri);
|
||
+}
|
||
+
|
||
+static gchar *
|
||
+web_view_suggest_filename (EWebView *web_view,
|
||
+ const gchar *uri)
|
||
+{
|
||
+ const gchar *cp;
|
||
+
|
||
+ /* Try to derive a filename from the last path segment. */
|
||
+
|
||
+ cp = strrchr (uri, '/');
|
||
+ if (cp != NULL) {
|
||
+ if (strchr (cp, '?') == NULL)
|
||
+ cp++;
|
||
+ else
|
||
+ cp = NULL;
|
||
+ }
|
||
+
|
||
+ return g_strdup (cp);
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_before_popup_event (EWebView *web_view,
|
||
+ const gchar *uri)
|
||
+{
|
||
+ e_web_view_set_selected_uri (web_view, uri);
|
||
+ e_web_view_update_actions (web_view);
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+web_view_popup_event (EWebView *web_view,
|
||
+ const gchar *uri,
|
||
+ GdkEvent *event)
|
||
+{
|
||
+ e_web_view_set_selected_uri (web_view, uri);
|
||
+ e_web_view_show_popup_menu (web_view, event);
|
||
+
|
||
+ return TRUE;
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_stop_loading (EWebView *web_view)
|
||
+{
|
||
+ e_web_view_replace_load_cancellable (web_view, FALSE);
|
||
+ webkit_web_view_stop_loading (WEBKIT_WEB_VIEW (web_view));
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_update_actions (EWebView *web_view)
|
||
+{
|
||
+ GtkActionGroup *action_group;
|
||
+ gboolean can_copy;
|
||
+ gboolean scheme_is_http = FALSE;
|
||
+ gboolean scheme_is_mailto = FALSE;
|
||
+ gboolean uri_is_valid = FALSE;
|
||
+ gboolean visible;
|
||
+ const gchar *cursor_image_src;
|
||
+ const gchar *group_name;
|
||
+ const gchar *uri;
|
||
+
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ uri = e_web_view_get_selected_uri (web_view);
|
||
+ can_copy = e_web_view_has_selection (web_view);
|
||
+ cursor_image_src = e_web_view_get_cursor_image_src (web_view);
|
||
+
|
||
+ /* Parse the URI early so we know if the actions will work. */
|
||
+ if (uri != NULL) {
|
||
+ CamelURL *curl;
|
||
+
|
||
+ curl = camel_url_new (uri, NULL);
|
||
+ uri_is_valid = (curl != NULL);
|
||
+ camel_url_free (curl);
|
||
+
|
||
+ scheme_is_http =
|
||
+ (g_ascii_strncasecmp (uri, "http:", 5) == 0) ||
|
||
+ (g_ascii_strncasecmp (uri, "https:", 6) == 0);
|
||
+
|
||
+ scheme_is_mailto =
|
||
+ (g_ascii_strncasecmp (uri, "mailto:", 7) == 0);
|
||
+ }
|
||
+
|
||
+ /* Allow copying the URI even if it's malformed. */
|
||
+ group_name = "uri";
|
||
+ visible = (uri != NULL) && !scheme_is_mailto;
|
||
+ action_group = e_web_view_get_action_group (web_view, group_name);
|
||
+ gtk_action_group_set_visible (action_group, visible);
|
||
+
|
||
+ group_name = "http";
|
||
+ visible = uri_is_valid && scheme_is_http;
|
||
+ action_group = e_web_view_get_action_group (web_view, group_name);
|
||
+ gtk_action_group_set_visible (action_group, visible);
|
||
+
|
||
+ group_name = "mailto";
|
||
+ visible = uri_is_valid && scheme_is_mailto;
|
||
+ action_group = e_web_view_get_action_group (web_view, group_name);
|
||
+ gtk_action_group_set_visible (action_group, visible);
|
||
+
|
||
+ if (visible) {
|
||
+ CamelURL *curl;
|
||
+
|
||
+ curl = camel_url_new (uri, NULL);
|
||
+ if (curl) {
|
||
+ CamelInternetAddress *inet_addr;
|
||
+ const gchar *name = NULL, *email = NULL;
|
||
+ GtkAction *action;
|
||
+
|
||
+ inet_addr = camel_internet_address_new ();
|
||
+ camel_address_decode (CAMEL_ADDRESS (inet_addr), curl->path);
|
||
+
|
||
+ action = gtk_action_group_get_action (action_group, "mailto-copy-raw");
|
||
+ gtk_action_set_visible (action,
|
||
+ camel_internet_address_get (inet_addr, 0, &name, &email) &&
|
||
+ name && *name && email && *email);
|
||
+
|
||
+ g_object_unref (inet_addr);
|
||
+ camel_url_free (curl);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ group_name = "image";
|
||
+ visible = (cursor_image_src != NULL);
|
||
+ action_group = e_web_view_get_action_group (web_view, group_name);
|
||
+ gtk_action_group_set_visible (action_group, visible);
|
||
+
|
||
+ group_name = "selection";
|
||
+ visible = can_copy;
|
||
+ action_group = e_web_view_get_action_group (web_view, group_name);
|
||
+ gtk_action_group_set_visible (action_group, visible);
|
||
+
|
||
+ group_name = "standard";
|
||
+ visible = (uri == NULL);
|
||
+ action_group = e_web_view_get_action_group (web_view, group_name);
|
||
+ gtk_action_group_set_visible (action_group, visible);
|
||
+
|
||
+ group_name = "lockdown-printing";
|
||
+ visible = (uri == NULL) && !web_view->priv->disable_printing;
|
||
+ action_group = e_web_view_get_action_group (web_view, group_name);
|
||
+ gtk_action_group_set_visible (action_group, visible);
|
||
+
|
||
+ group_name = "lockdown-save-to-disk";
|
||
+ visible = (uri == NULL) && !web_view->priv->disable_save_to_disk;
|
||
+ action_group = e_web_view_get_action_group (web_view, group_name);
|
||
+ gtk_action_group_set_visible (action_group, visible);
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_submit_alert (EAlertSink *alert_sink,
|
||
+ EAlert *alert)
|
||
+{
|
||
+ EWebView *web_view;
|
||
+ GtkWidget *dialog;
|
||
+ GString *buffer;
|
||
+ const gchar *icon_name = NULL;
|
||
+ const gchar *primary_text;
|
||
+ const gchar *secondary_text;
|
||
+ gint icon_width, icon_height;
|
||
+ gpointer parent;
|
||
+
|
||
+ web_view = E_WEB_VIEW (alert_sink);
|
||
+
|
||
+ parent = gtk_widget_get_toplevel (GTK_WIDGET (web_view));
|
||
+ parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
|
||
+
|
||
+ switch (e_alert_get_message_type (alert)) {
|
||
+ case GTK_MESSAGE_INFO:
|
||
+ icon_name = "dialog-information";
|
||
+ break;
|
||
+
|
||
+ case GTK_MESSAGE_WARNING:
|
||
+ icon_name = "dialog-warning";
|
||
+ break;
|
||
+
|
||
+ case GTK_MESSAGE_ERROR:
|
||
+ icon_name = "dialog-error";
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ dialog = e_alert_dialog_new (parent, alert);
|
||
+ gtk_dialog_run (GTK_DIALOG (dialog));
|
||
+ gtk_widget_destroy (dialog);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ /* Primary text is required. */
|
||
+ primary_text = e_alert_get_primary_text (alert);
|
||
+ g_return_if_fail (primary_text != NULL);
|
||
+
|
||
+ /* Secondary text is optional. */
|
||
+ secondary_text = e_alert_get_secondary_text (alert);
|
||
+ if (secondary_text == NULL)
|
||
+ secondary_text = "";
|
||
+
|
||
+ if (!gtk_icon_size_lookup (GTK_ICON_SIZE_DIALOG, &icon_width, &icon_height)) {
|
||
+ icon_width = 48;
|
||
+ icon_height = 48;
|
||
+ }
|
||
+
|
||
+ buffer = g_string_sized_new (512);
|
||
+
|
||
+ g_string_append (
|
||
+ buffer,
|
||
+ "<html>"
|
||
+ "<head>"
|
||
+ "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">"
|
||
+ "<meta name=\"color-scheme\" content=\"light dark\">"
|
||
+ "</head>"
|
||
+ "<body>");
|
||
+
|
||
+ g_string_append (
|
||
+ buffer,
|
||
+ "<table bgcolor='#000000' width='100%'"
|
||
+ " cellpadding='1' cellspacing='0'>"
|
||
+ "<tr>"
|
||
+ "<td>"
|
||
+ "<table bgcolor='#dddddd' width='100%' cellpadding='6' style=\"color:#000000;\">"
|
||
+ "<tr>");
|
||
+
|
||
+ g_string_append_printf (
|
||
+ buffer,
|
||
+ "<tr>"
|
||
+ "<td valign='top'>"
|
||
+ "<img src='gtk-stock://%s/?size=%d' width=\"%dpx\" height=\"%dpx\"/>"
|
||
+ "</td>"
|
||
+ "<td align='left' width='100%%'>"
|
||
+ "<h3>%s</h3>"
|
||
+ "%s"
|
||
+ "</td>"
|
||
+ "</tr>",
|
||
+ icon_name,
|
||
+ GTK_ICON_SIZE_DIALOG,
|
||
+ icon_width,
|
||
+ icon_height,
|
||
+ primary_text,
|
||
+ secondary_text);
|
||
+
|
||
+ g_string_append (
|
||
+ buffer,
|
||
+ "</table>"
|
||
+ "</td>"
|
||
+ "</tr>"
|
||
+ "</table>"
|
||
+ "</body>"
|
||
+ "</html>");
|
||
+
|
||
+ e_web_view_load_string (web_view, buffer->str);
|
||
+
|
||
+ g_string_free (buffer, TRUE);
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_can_execute_editing_command_cb (WebKitWebView *webkit_web_view,
|
||
+ GAsyncResult *result,
|
||
+ GtkAction *action)
|
||
+{
|
||
+ gboolean can_do_command;
|
||
+
|
||
+ can_do_command = webkit_web_view_can_execute_editing_command_finish (
|
||
+ webkit_web_view, result, NULL);
|
||
+
|
||
+ gtk_action_set_sensitive (action, can_do_command);
|
||
+ g_object_unref (action);
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_selectable_update_actions (ESelectable *selectable,
|
||
+ EFocusTracker *focus_tracker,
|
||
+ GdkAtom *clipboard_targets,
|
||
+ gint n_clipboard_targets)
|
||
+{
|
||
+ EWebView *web_view;
|
||
+ GtkAction *action;
|
||
+ gboolean can_copy = FALSE;
|
||
+
|
||
+ web_view = E_WEB_VIEW (selectable);
|
||
+
|
||
+ can_copy = e_web_view_has_selection (web_view);
|
||
+
|
||
+ action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
|
||
+ gtk_action_set_sensitive (action, can_copy);
|
||
+ gtk_action_set_tooltip (action, _("Copy the selection"));
|
||
+
|
||
+ action = e_focus_tracker_get_cut_clipboard_action (focus_tracker);
|
||
+ webkit_web_view_can_execute_editing_command (
|
||
+ WEBKIT_WEB_VIEW (web_view),
|
||
+ WEBKIT_EDITING_COMMAND_CUT,
|
||
+ NULL, /* cancellable */
|
||
+ (GAsyncReadyCallback) web_view_can_execute_editing_command_cb,
|
||
+ g_object_ref (action));
|
||
+ gtk_action_set_tooltip (action, _("Cut the selection"));
|
||
+
|
||
+ action = e_focus_tracker_get_paste_clipboard_action (focus_tracker);
|
||
+ webkit_web_view_can_execute_editing_command (
|
||
+ WEBKIT_WEB_VIEW (web_view),
|
||
+ WEBKIT_EDITING_COMMAND_PASTE,
|
||
+ NULL, /* cancellable */
|
||
+ (GAsyncReadyCallback) web_view_can_execute_editing_command_cb,
|
||
+ g_object_ref (action));
|
||
+ gtk_action_set_tooltip (action, _("Paste the clipboard"));
|
||
+
|
||
+ action = e_focus_tracker_get_select_all_action (focus_tracker);
|
||
+ gtk_action_set_sensitive (action, TRUE);
|
||
+ gtk_action_set_tooltip (action, _("Select all text and images"));
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_selectable_cut_clipboard (ESelectable *selectable)
|
||
+{
|
||
+ e_web_view_cut_clipboard (E_WEB_VIEW (selectable));
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_selectable_copy_clipboard (ESelectable *selectable)
|
||
+{
|
||
+ e_web_view_copy_clipboard (E_WEB_VIEW (selectable));
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_selectable_paste_clipboard (ESelectable *selectable)
|
||
+{
|
||
+ e_web_view_paste_clipboard (E_WEB_VIEW (selectable));
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_selectable_select_all (ESelectable *selectable)
|
||
+{
|
||
+ e_web_view_select_all (E_WEB_VIEW (selectable));
|
||
+}
|
||
+
|
||
+static void
|
||
+e_web_view_test_change_and_update_fonts_cb (EWebView *web_view,
|
||
+ const gchar *key,
|
||
+ GSettings *settings)
|
||
+{
|
||
+ GVariant *new_value, *old_value;
|
||
+
|
||
+ new_value = g_settings_get_value (settings, key);
|
||
+ old_value = g_hash_table_lookup (web_view->priv->old_settings, key);
|
||
+
|
||
+ if (!new_value || !old_value || !g_variant_equal (new_value, old_value)) {
|
||
+ if (new_value)
|
||
+ g_hash_table_insert (web_view->priv->old_settings, g_strdup (key), new_value);
|
||
+ else
|
||
+ g_hash_table_remove (web_view->priv->old_settings, key);
|
||
+
|
||
+ e_web_view_update_fonts (web_view);
|
||
+ } else if (new_value) {
|
||
+ g_variant_unref (new_value);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_toplevel_event_after_cb (GtkWidget *widget,
|
||
+ GdkEvent *event,
|
||
+ EWebView *web_view)
|
||
+{
|
||
+ if (event && event->type == GDK_MOTION_NOTIFY && web_view->priv->has_hover_link &&
|
||
+ gdk_event_get_window (event) != gtk_widget_get_window (GTK_WIDGET (web_view))) {
|
||
+ /* This won't reset WebKitGTK's cached link the cursor stays on, but do this,
|
||
+ instead of sending a fake signal to the WebKitGTK. */
|
||
+ e_web_view_status_message (web_view, NULL);
|
||
+
|
||
+ web_view->priv->has_hover_link = FALSE;
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_map (GtkWidget *widget)
|
||
+{
|
||
+ GtkWidget *toplevel;
|
||
+
|
||
+ toplevel = gtk_widget_get_toplevel (widget);
|
||
+
|
||
+ g_signal_connect (toplevel, "event-after", G_CALLBACK (web_view_toplevel_event_after_cb), widget);
|
||
+
|
||
+ GTK_WIDGET_CLASS (e_web_view_parent_class)->map (widget);
|
||
+}
|
||
+
|
||
+static void
|
||
+web_view_unmap (GtkWidget *widget)
|
||
+{
|
||
+ GtkWidget *toplevel;
|
||
+
|
||
+ toplevel = gtk_widget_get_toplevel (widget);
|
||
+
|
||
+ g_signal_handlers_disconnect_by_func (toplevel, G_CALLBACK (web_view_toplevel_event_after_cb), widget);
|
||
+
|
||
+ GTK_WIDGET_CLASS (e_web_view_parent_class)->unmap (widget);
|
||
+
|
||
+ e_web_view_status_message (E_WEB_VIEW (widget), NULL);
|
||
+}
|
||
+
|
||
+static void
|
||
+e_web_view_class_init (EWebViewClass *class)
|
||
+{
|
||
+ GObjectClass *object_class;
|
||
+ GtkWidgetClass *widget_class;
|
||
+
|
||
+ g_type_class_add_private (class, sizeof (EWebViewPrivate));
|
||
+
|
||
+ object_class = G_OBJECT_CLASS (class);
|
||
+ object_class->constructor = web_view_constructor;
|
||
+ object_class->set_property = web_view_set_property;
|
||
+ object_class->get_property = web_view_get_property;
|
||
+ object_class->dispose = web_view_dispose;
|
||
+ object_class->finalize = web_view_finalize;
|
||
+ object_class->constructed = web_view_constructed;
|
||
+
|
||
+ widget_class = GTK_WIDGET_CLASS (class);
|
||
+ widget_class->scroll_event = web_view_scroll_event;
|
||
+ widget_class->drag_motion = web_view_drag_motion;
|
||
+ widget_class->drag_drop = web_view_drag_drop;
|
||
+ widget_class->drag_leave = web_view_drag_leave;
|
||
+ widget_class->map = web_view_map;
|
||
+ widget_class->unmap = web_view_unmap;
|
||
+
|
||
+ class->hovering_over_link = web_view_hovering_over_link;
|
||
+ class->link_clicked = web_view_link_clicked;
|
||
+ class->load_string = web_view_load_string;
|
||
+ class->load_uri = web_view_load_uri;
|
||
+ class->suggest_filename = web_view_suggest_filename;
|
||
+ class->before_popup_event = web_view_before_popup_event;
|
||
+ class->popup_event = web_view_popup_event;
|
||
+ class->stop_loading = web_view_stop_loading;
|
||
+ class->update_actions = web_view_update_actions;
|
||
+
|
||
+ g_object_class_install_property (
|
||
+ object_class,
|
||
+ PROP_CARET_MODE,
|
||
+ g_param_spec_boolean (
|
||
+ "caret-mode",
|
||
+ "Caret Mode",
|
||
+ NULL,
|
||
+ FALSE,
|
||
+ G_PARAM_READWRITE));
|
||
+
|
||
+ /* Inherited from ESelectableInterface; just a fake property here */
|
||
+ g_object_class_override_property (
|
||
+ object_class,
|
||
+ PROP_COPY_TARGET_LIST,
|
||
+ "copy-target-list");
|
||
+
|
||
+ /* Inherited from ESelectableInterface; just a fake property here */
|
||
+ g_object_class_override_property (
|
||
+ object_class,
|
||
+ PROP_PASTE_TARGET_LIST,
|
||
+ "paste-target-list");
|
||
+
|
||
+ g_object_class_install_property (
|
||
+ object_class,
|
||
+ PROP_CURSOR_IMAGE_SRC,
|
||
+ g_param_spec_string (
|
||
+ "cursor-image-src",
|
||
+ "Image source uri at the mouse cursor",
|
||
+ NULL,
|
||
+ NULL,
|
||
+ G_PARAM_READWRITE));
|
||
+
|
||
+ g_object_class_install_property (
|
||
+ object_class,
|
||
+ PROP_DISABLE_PRINTING,
|
||
+ g_param_spec_boolean (
|
||
+ "disable-printing",
|
||
+ "Disable Printing",
|
||
+ NULL,
|
||
+ FALSE,
|
||
+ G_PARAM_READWRITE |
|
||
+ G_PARAM_CONSTRUCT));
|
||
+
|
||
+ g_object_class_install_property (
|
||
+ object_class,
|
||
+ PROP_DISABLE_SAVE_TO_DISK,
|
||
+ g_param_spec_boolean (
|
||
+ "disable-save-to-disk",
|
||
+ "Disable Save-to-Disk",
|
||
+ NULL,
|
||
+ FALSE,
|
||
+ G_PARAM_READWRITE |
|
||
+ G_PARAM_CONSTRUCT));
|
||
+
|
||
+ g_object_class_install_property (
|
||
+ object_class,
|
||
+ PROP_HAS_SELECTION,
|
||
+ g_param_spec_boolean (
|
||
+ "has-selection",
|
||
+ "Has Selection",
|
||
+ NULL,
|
||
+ FALSE,
|
||
+ G_PARAM_READABLE));
|
||
+
|
||
+ g_object_class_install_property (
|
||
+ object_class,
|
||
+ PROP_MINIMUM_FONT_SIZE,
|
||
+ g_param_spec_int (
|
||
+ "minimum-font-size",
|
||
+ "Minimum Font Size",
|
||
+ NULL,
|
||
+ G_MININT, G_MAXINT, 0,
|
||
+ G_PARAM_READWRITE));
|
||
+
|
||
+ g_object_class_install_property (
|
||
+ object_class,
|
||
+ PROP_NEED_INPUT,
|
||
+ g_param_spec_boolean (
|
||
+ "need-input",
|
||
+ "Need Input",
|
||
+ NULL,
|
||
+ FALSE,
|
||
+ G_PARAM_READABLE));
|
||
+
|
||
+ g_object_class_install_property (
|
||
+ object_class,
|
||
+ PROP_OPEN_PROXY,
|
||
+ g_param_spec_object (
|
||
+ "open-proxy",
|
||
+ "Open Proxy",
|
||
+ NULL,
|
||
+ GTK_TYPE_ACTION,
|
||
+ G_PARAM_READWRITE));
|
||
+
|
||
+ g_object_class_install_property (
|
||
+ object_class,
|
||
+ PROP_PRINT_PROXY,
|
||
+ g_param_spec_object (
|
||
+ "print-proxy",
|
||
+ "Print Proxy",
|
||
+ NULL,
|
||
+ GTK_TYPE_ACTION,
|
||
+ G_PARAM_READWRITE));
|
||
+
|
||
+ g_object_class_install_property (
|
||
+ object_class,
|
||
+ PROP_SAVE_AS_PROXY,
|
||
+ g_param_spec_object (
|
||
+ "save-as-proxy",
|
||
+ "Save As Proxy",
|
||
+ NULL,
|
||
+ GTK_TYPE_ACTION,
|
||
+ G_PARAM_READWRITE));
|
||
+
|
||
+ g_object_class_install_property (
|
||
+ object_class,
|
||
+ PROP_SELECTED_URI,
|
||
+ g_param_spec_string (
|
||
+ "selected-uri",
|
||
+ "Selected URI",
|
||
+ NULL,
|
||
+ NULL,
|
||
+ G_PARAM_READWRITE));
|
||
+
|
||
+ signals[NEW_ACTIVITY] = g_signal_new (
|
||
+ "new-activity",
|
||
+ G_TYPE_FROM_CLASS (class),
|
||
+ G_SIGNAL_RUN_LAST,
|
||
+ G_STRUCT_OFFSET (EWebViewClass, new_activity),
|
||
+ NULL, NULL,
|
||
+ g_cclosure_marshal_VOID__OBJECT,
|
||
+ G_TYPE_NONE, 1,
|
||
+ E_TYPE_ACTIVITY);
|
||
+
|
||
+ signals[POPUP_EVENT] = g_signal_new (
|
||
+ "popup-event",
|
||
+ G_TYPE_FROM_CLASS (class),
|
||
+ G_SIGNAL_RUN_LAST,
|
||
+ G_STRUCT_OFFSET (EWebViewClass, popup_event),
|
||
+ g_signal_accumulator_true_handled, NULL,
|
||
+ NULL,
|
||
+ G_TYPE_BOOLEAN, 2, G_TYPE_STRING, GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
|
||
+
|
||
+ signals[BEFORE_POPUP_EVENT] = g_signal_new (
|
||
+ "before-popup-event",
|
||
+ G_TYPE_FROM_CLASS (class),
|
||
+ G_SIGNAL_RUN_LAST,
|
||
+ G_STRUCT_OFFSET (EWebViewClass, before_popup_event),
|
||
+ NULL, NULL,
|
||
+ g_cclosure_marshal_VOID__STRING,
|
||
+ G_TYPE_NONE, 1, G_TYPE_STRING);
|
||
+
|
||
+ signals[STATUS_MESSAGE] = g_signal_new (
|
||
+ "status-message",
|
||
+ G_TYPE_FROM_CLASS (class),
|
||
+ G_SIGNAL_RUN_LAST,
|
||
+ G_STRUCT_OFFSET (EWebViewClass, status_message),
|
||
+ NULL, NULL,
|
||
+ g_cclosure_marshal_VOID__STRING,
|
||
+ G_TYPE_NONE, 1,
|
||
+ G_TYPE_STRING);
|
||
+
|
||
+ signals[STOP_LOADING] = g_signal_new (
|
||
+ "stop-loading",
|
||
+ G_TYPE_FROM_CLASS (class),
|
||
+ G_SIGNAL_RUN_LAST,
|
||
+ G_STRUCT_OFFSET (EWebViewClass, stop_loading),
|
||
+ NULL, NULL,
|
||
+ g_cclosure_marshal_VOID__VOID,
|
||
+ G_TYPE_NONE, 0);
|
||
+
|
||
+ signals[UPDATE_ACTIONS] = g_signal_new (
|
||
+ "update-actions",
|
||
+ G_TYPE_FROM_CLASS (class),
|
||
+ G_SIGNAL_RUN_LAST,
|
||
+ G_STRUCT_OFFSET (EWebViewClass, update_actions),
|
||
+ NULL, NULL,
|
||
+ g_cclosure_marshal_VOID__VOID,
|
||
+ G_TYPE_NONE, 0);
|
||
+
|
||
+ /* return TRUE when a signal handler processed the mailto URI */
|
||
+ signals[PROCESS_MAILTO] = g_signal_new (
|
||
+ "process-mailto",
|
||
+ G_TYPE_FROM_CLASS (class),
|
||
+ G_SIGNAL_RUN_LAST,
|
||
+ G_STRUCT_OFFSET (EWebViewClass, process_mailto),
|
||
+ NULL, NULL,
|
||
+ e_marshal_BOOLEAN__STRING,
|
||
+ G_TYPE_BOOLEAN, 1, G_TYPE_STRING);
|
||
+
|
||
+ /* Expects an empty string to abandon the request,
|
||
+ or NULL to keep the passed-in uri,
|
||
+ or a new uri to load instead. */
|
||
+ signals[URI_REQUESTED] = g_signal_new (
|
||
+ "uri-requested",
|
||
+ G_TYPE_FROM_CLASS (class),
|
||
+ G_SIGNAL_RUN_LAST,
|
||
+ G_STRUCT_OFFSET (EWebViewClass, uri_requested),
|
||
+ NULL, NULL, NULL,
|
||
+ G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_POINTER);
|
||
+
|
||
+ signals[CONTENT_LOADED] = g_signal_new (
|
||
+ "content-loaded",
|
||
+ G_TYPE_FROM_CLASS (class),
|
||
+ G_SIGNAL_RUN_LAST,
|
||
+ G_STRUCT_OFFSET (EWebViewClass, content_loaded),
|
||
+ NULL, NULL, NULL,
|
||
+ G_TYPE_NONE, 1, G_TYPE_STRING);
|
||
+}
|
||
+
|
||
+static void
|
||
+e_web_view_alert_sink_init (EAlertSinkInterface *iface)
|
||
+{
|
||
+ iface->submit_alert = web_view_submit_alert;
|
||
+}
|
||
+
|
||
+static void
|
||
+e_web_view_selectable_init (ESelectableInterface *iface)
|
||
+{
|
||
+ iface->update_actions = web_view_selectable_update_actions;
|
||
+ iface->cut_clipboard = web_view_selectable_cut_clipboard;
|
||
+ iface->copy_clipboard = web_view_selectable_copy_clipboard;
|
||
+ iface->paste_clipboard = web_view_selectable_paste_clipboard;
|
||
+ iface->select_all = web_view_selectable_select_all;
|
||
+}
|
||
+
|
||
+static void
|
||
+e_web_view_init (EWebView *web_view)
|
||
+{
|
||
+ GtkUIManager *ui_manager;
|
||
+ GtkActionGroup *action_group;
|
||
+ EPopupAction *popup_action;
|
||
+ GSettings *settings;
|
||
+ const gchar *domain = GETTEXT_PACKAGE;
|
||
+ const gchar *id;
|
||
+ gulong handler_id;
|
||
+ GError *error = NULL;
|
||
+
|
||
+ web_view->priv = E_WEB_VIEW_GET_PRIVATE (web_view);
|
||
+
|
||
+ web_view->priv->highlights_enabled = TRUE;
|
||
+ web_view->priv->old_settings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
|
||
+ web_view->priv->scheme_handlers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
|
||
+
|
||
+ g_signal_connect (
|
||
+ web_view, "context-menu",
|
||
+ G_CALLBACK (web_view_context_menu_cb), NULL);
|
||
+
|
||
+ g_signal_connect (
|
||
+ web_view, "mouse-target-changed",
|
||
+ G_CALLBACK (web_view_mouse_target_changed_cb), NULL);
|
||
+
|
||
+ g_signal_connect (
|
||
+ web_view, "decide-policy",
|
||
+ G_CALLBACK (web_view_decide_policy_cb),
|
||
+ NULL);
|
||
+
|
||
+ g_signal_connect (
|
||
+ web_view, "load-changed",
|
||
+ G_CALLBACK (web_view_load_changed_cb), NULL);
|
||
+
|
||
+ g_signal_connect (
|
||
+ web_view, "style-updated",
|
||
+ G_CALLBACK (style_updated_cb), NULL);
|
||
+
|
||
+ g_signal_connect (
|
||
+ web_view, "state-flags-changed",
|
||
+ G_CALLBACK (style_updated_cb), NULL);
|
||
+
|
||
+ ui_manager = gtk_ui_manager_new ();
|
||
+ web_view->priv->ui_manager = ui_manager;
|
||
+
|
||
+ g_signal_connect_swapped (
|
||
+ ui_manager, "connect-proxy",
|
||
+ G_CALLBACK (web_view_connect_proxy_cb), web_view);
|
||
+
|
||
+ settings = e_util_ref_settings ("org.gnome.desktop.interface");
|
||
+ web_view->priv->font_settings = g_object_ref (settings);
|
||
+ handler_id = g_signal_connect_swapped (
|
||
+ settings, "changed::font-name",
|
||
+ G_CALLBACK (e_web_view_test_change_and_update_fonts_cb), web_view);
|
||
+ web_view->priv->font_name_changed_handler_id = handler_id;
|
||
+ handler_id = g_signal_connect_swapped (
|
||
+ settings, "changed::monospace-font-name",
|
||
+ G_CALLBACK (e_web_view_test_change_and_update_fonts_cb), web_view);
|
||
+ web_view->priv->monospace_font_name_changed_handler_id = handler_id;
|
||
+ g_object_unref (settings);
|
||
+
|
||
+ action_group = gtk_action_group_new ("uri");
|
||
+ gtk_action_group_set_translation_domain (action_group, domain);
|
||
+ gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
||
+ g_object_unref (action_group);
|
||
+
|
||
+ gtk_action_group_add_actions (
|
||
+ action_group, uri_entries,
|
||
+ G_N_ELEMENTS (uri_entries), web_view);
|
||
+
|
||
+ action_group = gtk_action_group_new ("http");
|
||
+ gtk_action_group_set_translation_domain (action_group, domain);
|
||
+ gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
||
+ g_object_unref (action_group);
|
||
+
|
||
+ gtk_action_group_add_actions (
|
||
+ action_group, http_entries,
|
||
+ G_N_ELEMENTS (http_entries), web_view);
|
||
+
|
||
+ action_group = gtk_action_group_new ("mailto");
|
||
+ gtk_action_group_set_translation_domain (action_group, domain);
|
||
+ gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
||
+ g_object_unref (action_group);
|
||
+
|
||
+ gtk_action_group_add_actions (
|
||
+ action_group, mailto_entries,
|
||
+ G_N_ELEMENTS (mailto_entries), web_view);
|
||
+
|
||
+ action_group = gtk_action_group_new ("image");
|
||
+ gtk_action_group_set_translation_domain (action_group, domain);
|
||
+ gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
||
+ g_object_unref (action_group);
|
||
+
|
||
+ gtk_action_group_add_actions (
|
||
+ action_group, image_entries,
|
||
+ G_N_ELEMENTS (image_entries), web_view);
|
||
+
|
||
+ action_group = gtk_action_group_new ("selection");
|
||
+ gtk_action_group_set_translation_domain (action_group, domain);
|
||
+ gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
||
+ g_object_unref (action_group);
|
||
+
|
||
+ gtk_action_group_add_actions (
|
||
+ action_group, selection_entries,
|
||
+ G_N_ELEMENTS (selection_entries), web_view);
|
||
+
|
||
+ action_group = gtk_action_group_new ("standard");
|
||
+ gtk_action_group_set_translation_domain (action_group, domain);
|
||
+ gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
||
+ g_object_unref (action_group);
|
||
+
|
||
+ gtk_action_group_add_actions (
|
||
+ action_group, standard_entries,
|
||
+ G_N_ELEMENTS (standard_entries), web_view);
|
||
+
|
||
+ popup_action = e_popup_action_new ("open");
|
||
+ gtk_action_group_add_action (action_group, GTK_ACTION (popup_action));
|
||
+ g_object_unref (popup_action);
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ web_view, "open-proxy",
|
||
+ popup_action, "related-action",
|
||
+ G_BINDING_BIDIRECTIONAL |
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ /* Support lockdown. */
|
||
+
|
||
+ action_group = gtk_action_group_new ("lockdown-printing");
|
||
+ gtk_action_group_set_translation_domain (action_group, domain);
|
||
+ gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
||
+ g_object_unref (action_group);
|
||
+
|
||
+ popup_action = e_popup_action_new ("print");
|
||
+ gtk_action_group_add_action (action_group, GTK_ACTION (popup_action));
|
||
+ g_object_unref (popup_action);
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ web_view, "print-proxy",
|
||
+ popup_action, "related-action",
|
||
+ G_BINDING_BIDIRECTIONAL |
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ action_group = gtk_action_group_new ("lockdown-save-to-disk");
|
||
+ gtk_action_group_set_translation_domain (action_group, domain);
|
||
+ gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
||
+ g_object_unref (action_group);
|
||
+
|
||
+ popup_action = e_popup_action_new ("save-as");
|
||
+ gtk_action_group_add_action (action_group, GTK_ACTION (popup_action));
|
||
+ g_object_unref (popup_action);
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ web_view, "save-as-proxy",
|
||
+ popup_action, "related-action",
|
||
+ G_BINDING_BIDIRECTIONAL |
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ /* Because we are loading from a hard-coded string, there is
|
||
+ * no chance of I/O errors. Failure here implies a malformed
|
||
+ * UI definition. Full stop. */
|
||
+ gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error);
|
||
+ if (error != NULL)
|
||
+ g_error ("%s", error->message);
|
||
+
|
||
+ id = "org.gnome.evolution.webview";
|
||
+ e_plugin_ui_register_manager (ui_manager, id, web_view);
|
||
+ e_plugin_ui_enable_manager (ui_manager, id);
|
||
+
|
||
+ web_view->priv->element_clicked_cbs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_ptr_array_unref);
|
||
+
|
||
+ web_view->priv->cancellable = NULL;
|
||
+}
|
||
+
|
||
+GtkWidget *
|
||
+e_web_view_new (void)
|
||
+{
|
||
+ return g_object_new (
|
||
+ E_TYPE_WEB_VIEW,
|
||
+ NULL);
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_clear (EWebView *web_view)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ e_web_view_replace_load_cancellable (web_view, FALSE);
|
||
+
|
||
+ e_web_view_load_string (web_view,
|
||
+ "<html>"
|
||
+ "<head>"
|
||
+ "<meta name=\"color-scheme\" content=\"light dark\">"
|
||
+ "</head>"
|
||
+ "<body class=\"-e-web-view-background-color -e-web-view-text-color\"></body>"
|
||
+ "</html>");
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_load_string (EWebView *web_view,
|
||
+ const gchar *string)
|
||
+{
|
||
+ EWebViewClass *class;
|
||
+
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ class = E_WEB_VIEW_GET_CLASS (web_view);
|
||
+ g_return_if_fail (class != NULL);
|
||
+ g_return_if_fail (class->load_string != NULL);
|
||
+
|
||
+ e_web_view_replace_load_cancellable (web_view, TRUE);
|
||
+
|
||
+ class->load_string (web_view, string);
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_load_uri (EWebView *web_view,
|
||
+ const gchar *uri)
|
||
+{
|
||
+ EWebViewClass *class;
|
||
+
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ class = E_WEB_VIEW_GET_CLASS (web_view);
|
||
+ g_return_if_fail (class != NULL);
|
||
+ g_return_if_fail (class->load_uri != NULL);
|
||
+
|
||
+ e_web_view_replace_load_cancellable (web_view, TRUE);
|
||
+
|
||
+ class->load_uri (web_view, uri);
|
||
+}
|
||
+
|
||
+/**
|
||
+ * e_web_view_suggest_filename:
|
||
+ * @web_view: an #EWebView
|
||
+ * @uri: a URI string
|
||
+ *
|
||
+ * Attempts to derive a suggested filename from the @uri for use in a
|
||
+ * "Save As" dialog.
|
||
+ *
|
||
+ * By default the suggested filename is the last path segment of the @uri
|
||
+ * (unless @uri looks like a query), but subclasses can use other mechanisms
|
||
+ * for custom URI schemes. For example, "cid:" URIs in an email message may
|
||
+ * refer to a MIME part with a suggested filename in its Content-Disposition
|
||
+ * header.
|
||
+ *
|
||
+ * The returned string should be freed with g_free() when finished with it,
|
||
+ * but callers should also be prepared for the function to return %NULL if
|
||
+ * a filename cannot be determined.
|
||
+ *
|
||
+ * Returns: a suggested filename, or %NULL
|
||
+ **/
|
||
+gchar *
|
||
+e_web_view_suggest_filename (EWebView *web_view,
|
||
+ const gchar *uri)
|
||
+{
|
||
+ EWebViewClass *class;
|
||
+ gchar *filename;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
||
+ g_return_val_if_fail (uri != NULL, NULL);
|
||
+
|
||
+ class = E_WEB_VIEW_GET_CLASS (web_view);
|
||
+ g_return_val_if_fail (class != NULL, NULL);
|
||
+ g_return_val_if_fail (class->suggest_filename != NULL, NULL);
|
||
+
|
||
+ filename = class->suggest_filename (web_view, uri);
|
||
+
|
||
+ if (filename != NULL)
|
||
+ e_util_make_safe_filename (filename);
|
||
+
|
||
+ return filename;
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_reload (EWebView *web_view)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ e_web_view_replace_load_cancellable (web_view, TRUE);
|
||
+
|
||
+ webkit_web_view_reload (WEBKIT_WEB_VIEW (web_view));
|
||
+}
|
||
+
|
||
+gboolean
|
||
+e_web_view_get_caret_mode (EWebView *web_view)
|
||
+{
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
||
+
|
||
+ return web_view->priv->caret_mode;
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_set_caret_mode (EWebView *web_view,
|
||
+ gboolean caret_mode)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ if (web_view->priv->caret_mode == caret_mode)
|
||
+ return;
|
||
+
|
||
+ web_view->priv->caret_mode = caret_mode;
|
||
+
|
||
+ g_object_notify (G_OBJECT (web_view), "caret-mode");
|
||
+}
|
||
+
|
||
+GtkTargetList *
|
||
+e_web_view_get_copy_target_list (EWebView *web_view)
|
||
+{
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
||
+
|
||
+ return NULL;
|
||
+ /* FIXME WK2 */
|
||
+ /*return webkit_web_view_get_copy_target_list (
|
||
+ WEBKIT_WEB_VIEW (web_view));*/
|
||
+}
|
||
+
|
||
+gboolean
|
||
+e_web_view_get_disable_printing (EWebView *web_view)
|
||
+{
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
||
+
|
||
+ return web_view->priv->disable_printing;
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_set_disable_printing (EWebView *web_view,
|
||
+ gboolean disable_printing)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ if (web_view->priv->disable_printing == disable_printing)
|
||
+ return;
|
||
+
|
||
+ web_view->priv->disable_printing = disable_printing;
|
||
+
|
||
+ g_object_notify (G_OBJECT (web_view), "disable-printing");
|
||
+}
|
||
+
|
||
+gboolean
|
||
+e_web_view_get_disable_save_to_disk (EWebView *web_view)
|
||
+{
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
||
+
|
||
+ return web_view->priv->disable_save_to_disk;
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_set_disable_save_to_disk (EWebView *web_view,
|
||
+ gboolean disable_save_to_disk)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ if (web_view->priv->disable_save_to_disk == disable_save_to_disk)
|
||
+ return;
|
||
+
|
||
+ web_view->priv->disable_save_to_disk = disable_save_to_disk;
|
||
+
|
||
+ g_object_notify (G_OBJECT (web_view), "disable-save-to-disk");
|
||
+}
|
||
+
|
||
+gboolean
|
||
+e_web_view_get_editable (EWebView *web_view)
|
||
+{
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
||
+
|
||
+ return webkit_web_view_is_editable (WEBKIT_WEB_VIEW (web_view));
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_set_editable (EWebView *web_view,
|
||
+ gboolean editable)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ webkit_web_view_set_editable (WEBKIT_WEB_VIEW (web_view), editable);
|
||
+}
|
||
+
|
||
+gboolean
|
||
+e_web_view_get_need_input (EWebView *web_view)
|
||
+{
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
||
+
|
||
+ return web_view->priv->need_input;
|
||
+}
|
||
+
|
||
+const gchar *
|
||
+e_web_view_get_selected_uri (EWebView *web_view)
|
||
+{
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
||
+
|
||
+ return web_view->priv->selected_uri;
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_set_selected_uri (EWebView *web_view,
|
||
+ const gchar *selected_uri)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ if (g_strcmp0 (web_view->priv->selected_uri, selected_uri) == 0)
|
||
+ return;
|
||
+
|
||
+ g_free (web_view->priv->selected_uri);
|
||
+ web_view->priv->selected_uri = g_strdup (selected_uri);
|
||
+
|
||
+ g_object_notify (G_OBJECT (web_view), "selected-uri");
|
||
+}
|
||
+
|
||
+const gchar *
|
||
+e_web_view_get_cursor_image_src (EWebView *web_view)
|
||
+{
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
||
+
|
||
+ return web_view->priv->cursor_image_src;
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_set_cursor_image_src (EWebView *web_view,
|
||
+ const gchar *src_uri)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ if (g_strcmp0 (web_view->priv->cursor_image_src, src_uri) == 0)
|
||
+ return;
|
||
+
|
||
+ g_free (web_view->priv->cursor_image_src);
|
||
+ web_view->priv->cursor_image_src = g_strdup (src_uri);
|
||
+
|
||
+ g_object_notify (G_OBJECT (web_view), "cursor-image-src");
|
||
+}
|
||
+
|
||
+GtkAction *
|
||
+e_web_view_get_open_proxy (EWebView *web_view)
|
||
+{
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
||
+
|
||
+ return web_view->priv->open_proxy;
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_set_open_proxy (EWebView *web_view,
|
||
+ GtkAction *open_proxy)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ if (web_view->priv->open_proxy == open_proxy)
|
||
+ return;
|
||
+
|
||
+ if (open_proxy != NULL) {
|
||
+ g_return_if_fail (GTK_IS_ACTION (open_proxy));
|
||
+ g_object_ref (open_proxy);
|
||
+ }
|
||
+
|
||
+ if (web_view->priv->open_proxy != NULL)
|
||
+ g_object_unref (web_view->priv->open_proxy);
|
||
+
|
||
+ web_view->priv->open_proxy = open_proxy;
|
||
+
|
||
+ g_object_notify (G_OBJECT (web_view), "open-proxy");
|
||
+}
|
||
+
|
||
+GtkTargetList *
|
||
+e_web_view_get_paste_target_list (EWebView *web_view)
|
||
+{
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
||
+
|
||
+ /* FIXME WK2
|
||
+ return webkit_web_view_get_paste_target_list (
|
||
+ WEBKIT_WEB_VIEW (web_view)); */
|
||
+ return NULL;
|
||
+}
|
||
+
|
||
+GtkAction *
|
||
+e_web_view_get_print_proxy (EWebView *web_view)
|
||
+{
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
||
+
|
||
+ return web_view->priv->print_proxy;
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_set_print_proxy (EWebView *web_view,
|
||
+ GtkAction *print_proxy)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ if (web_view->priv->print_proxy == print_proxy)
|
||
+ return;
|
||
+
|
||
+ if (print_proxy != NULL) {
|
||
+ g_return_if_fail (GTK_IS_ACTION (print_proxy));
|
||
+ g_object_ref (print_proxy);
|
||
+ }
|
||
+
|
||
+ if (web_view->priv->print_proxy != NULL)
|
||
+ g_object_unref (web_view->priv->print_proxy);
|
||
+
|
||
+ web_view->priv->print_proxy = print_proxy;
|
||
+
|
||
+ g_object_notify (G_OBJECT (web_view), "print-proxy");
|
||
+}
|
||
+
|
||
+GtkAction *
|
||
+e_web_view_get_save_as_proxy (EWebView *web_view)
|
||
+{
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
||
+
|
||
+ return web_view->priv->save_as_proxy;
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_set_save_as_proxy (EWebView *web_view,
|
||
+ GtkAction *save_as_proxy)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ if (web_view->priv->save_as_proxy == save_as_proxy)
|
||
+ return;
|
||
+
|
||
+ if (save_as_proxy != NULL) {
|
||
+ g_return_if_fail (GTK_IS_ACTION (save_as_proxy));
|
||
+ g_object_ref (save_as_proxy);
|
||
+ }
|
||
+
|
||
+ if (web_view->priv->save_as_proxy != NULL)
|
||
+ g_object_unref (web_view->priv->save_as_proxy);
|
||
+
|
||
+ web_view->priv->save_as_proxy = save_as_proxy;
|
||
+
|
||
+ g_object_notify (G_OBJECT (web_view), "save-as-proxy");
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_get_last_popup_place (EWebView *web_view,
|
||
+ gchar **out_iframe_src,
|
||
+ gchar **out_iframe_id,
|
||
+ gchar **out_element_id,
|
||
+ gchar **out_link_uri)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ if (out_iframe_src)
|
||
+ *out_iframe_src = g_strdup (web_view->priv->last_popup_iframe_src);
|
||
+
|
||
+ if (out_iframe_id)
|
||
+ *out_iframe_id = g_strdup (web_view->priv->last_popup_iframe_id);
|
||
+
|
||
+ if (out_element_id)
|
||
+ *out_element_id = g_strdup (web_view->priv->last_popup_element_id);
|
||
+
|
||
+ if (out_link_uri)
|
||
+ *out_link_uri = g_strdup (web_view->priv->last_popup_link_uri);
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_add_highlight (EWebView *web_view,
|
||
+ const gchar *highlight)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+ g_return_if_fail (highlight && *highlight);
|
||
+
|
||
+ g_queue_push_tail (
|
||
+ &web_view->priv->highlights,
|
||
+ g_strdup (highlight));
|
||
+
|
||
+ webkit_find_controller_search (
|
||
+ web_view->priv->find_controller,
|
||
+ highlight,
|
||
+ WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE,
|
||
+ G_MAXUINT);
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_clear_highlights (EWebView *web_view)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ webkit_find_controller_search_finish (web_view->priv->find_controller);
|
||
+
|
||
+ while (!g_queue_is_empty (&web_view->priv->highlights))
|
||
+ g_free (g_queue_pop_head (&web_view->priv->highlights));
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_update_highlights (EWebView *web_view)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ web_view->priv->highlights_enabled = TRUE;
|
||
+ web_view_update_document_highlights (web_view);
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_disable_highlights (EWebView *web_view)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ web_view->priv->highlights_enabled = FALSE;
|
||
+}
|
||
+
|
||
+GtkAction *
|
||
+e_web_view_get_action (EWebView *web_view,
|
||
+ const gchar *action_name)
|
||
+{
|
||
+ GtkUIManager *ui_manager;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
||
+ g_return_val_if_fail (action_name != NULL, NULL);
|
||
+
|
||
+ ui_manager = e_web_view_get_ui_manager (web_view);
|
||
+
|
||
+ return e_lookup_action (ui_manager, action_name);
|
||
+}
|
||
+
|
||
+GtkActionGroup *
|
||
+e_web_view_get_action_group (EWebView *web_view,
|
||
+ const gchar *group_name)
|
||
+{
|
||
+ GtkUIManager *ui_manager;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
||
+ g_return_val_if_fail (group_name != NULL, NULL);
|
||
+
|
||
+ ui_manager = e_web_view_get_ui_manager (web_view);
|
||
+
|
||
+ return e_lookup_action_group (ui_manager, group_name);
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_copy_clipboard (EWebView *web_view)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ webkit_web_view_execute_editing_command (
|
||
+ WEBKIT_WEB_VIEW (web_view), WEBKIT_EDITING_COMMAND_COPY);
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_cut_clipboard (EWebView *web_view)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ webkit_web_view_execute_editing_command (
|
||
+ WEBKIT_WEB_VIEW (web_view), WEBKIT_EDITING_COMMAND_CUT);
|
||
+}
|
||
+
|
||
+gboolean
|
||
+e_web_view_has_selection (EWebView *web_view)
|
||
+{
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
||
+
|
||
+ return web_view->priv->has_selection;
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_paste_clipboard (EWebView *web_view)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ webkit_web_view_execute_editing_command (
|
||
+ WEBKIT_WEB_VIEW (web_view), WEBKIT_EDITING_COMMAND_PASTE);
|
||
+}
|
||
+
|
||
+gboolean
|
||
+e_web_view_scroll_forward (EWebView *web_view)
|
||
+{
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
||
+/* FIXME WK2
|
||
+ webkit_web_view_move_cursor (
|
||
+ WEBKIT_WEB_VIEW (web_view), GTK_MOVEMENT_PAGES, 1);
|
||
+*/
|
||
+ return TRUE; /* XXX This means nothing. */
|
||
+}
|
||
+
|
||
+gboolean
|
||
+e_web_view_scroll_backward (EWebView *web_view)
|
||
+{
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
||
+/* FIXME WK2
|
||
+ webkit_web_view_move_cursor (
|
||
+ WEBKIT_WEB_VIEW (web_view), GTK_MOVEMENT_PAGES, -1);
|
||
+*/
|
||
+ return TRUE; /* XXX This means nothing. */
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_select_all (EWebView *web_view)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ webkit_web_view_execute_editing_command (
|
||
+ WEBKIT_WEB_VIEW (web_view), WEBKIT_EDITING_COMMAND_SELECT_ALL);
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_unselect_all (EWebView *web_view)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ webkit_web_view_execute_editing_command (WEBKIT_WEB_VIEW (web_view), "Unselect");
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_zoom_100 (EWebView *web_view)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ webkit_web_view_set_zoom_level (WEBKIT_WEB_VIEW (web_view), 1.0);
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_zoom_in (EWebView *web_view)
|
||
+{
|
||
+ gdouble zoom_level;
|
||
+
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ /* There is no webkit_web_view_zoom_in function in WK2, so emulate it */
|
||
+ zoom_level = webkit_web_view_get_zoom_level (WEBKIT_WEB_VIEW (web_view));
|
||
+ /* zoom-step in WK1 was 0.1 */
|
||
+ zoom_level += 0.1;
|
||
+ if (zoom_level < 4.9999)
|
||
+ webkit_web_view_set_zoom_level (WEBKIT_WEB_VIEW (web_view), zoom_level);
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_zoom_out (EWebView *web_view)
|
||
+{
|
||
+ gdouble zoom_level;
|
||
+
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ /* There is no webkit_web_view_zoom_out function in WK2, so emulate it */
|
||
+ zoom_level = webkit_web_view_get_zoom_level (WEBKIT_WEB_VIEW (web_view));
|
||
+ /* zoom-step in WK1 was 0.1 */
|
||
+ zoom_level -= 0.1;
|
||
+ if (zoom_level > 0.7999)
|
||
+ webkit_web_view_set_zoom_level (WEBKIT_WEB_VIEW (web_view), zoom_level);
|
||
+}
|
||
+
|
||
+GtkUIManager *
|
||
+e_web_view_get_ui_manager (EWebView *web_view)
|
||
+{
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
||
+
|
||
+ return web_view->priv->ui_manager;
|
||
+}
|
||
+
|
||
+static void
|
||
+e_web_view_popup_menu_deactivate_cb (GtkMenu *popup_menu,
|
||
+ GtkWidget *web_view)
|
||
+{
|
||
+ g_return_if_fail (GTK_IS_MENU (popup_menu));
|
||
+
|
||
+ g_signal_handlers_disconnect_by_func (popup_menu, e_web_view_popup_menu_deactivate_cb, web_view);
|
||
+ gtk_menu_detach (popup_menu);
|
||
+}
|
||
+
|
||
+GtkWidget *
|
||
+e_web_view_get_popup_menu (EWebView *web_view)
|
||
+{
|
||
+ GtkUIManager *ui_manager;
|
||
+ GtkWidget *menu;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
||
+
|
||
+ ui_manager = e_web_view_get_ui_manager (web_view);
|
||
+ menu = gtk_ui_manager_get_widget (ui_manager, "/context");
|
||
+ g_return_val_if_fail (GTK_IS_MENU (menu), NULL);
|
||
+
|
||
+ g_warn_if_fail (!gtk_menu_get_attach_widget (GTK_MENU (menu)));
|
||
+
|
||
+ gtk_menu_attach_to_widget (GTK_MENU (menu),
|
||
+ GTK_WIDGET (web_view),
|
||
+ NULL);
|
||
+
|
||
+ g_signal_connect (
|
||
+ menu, "deactivate",
|
||
+ G_CALLBACK (e_web_view_popup_menu_deactivate_cb), web_view);
|
||
+
|
||
+ return menu;
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_show_popup_menu (EWebView *web_view,
|
||
+ GdkEvent *event)
|
||
+{
|
||
+ GtkWidget *menu;
|
||
+
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ e_web_view_update_actions (web_view);
|
||
+
|
||
+ menu = e_web_view_get_popup_menu (web_view);
|
||
+
|
||
+ gtk_menu_popup_at_pointer (GTK_MENU (menu), event);
|
||
+}
|
||
+
|
||
+/**
|
||
+ * e_web_view_new_activity:
|
||
+ * @web_view: an #EWebView
|
||
+ *
|
||
+ * Returns a new #EActivity for an #EWebView-related asynchronous operation,
|
||
+ * and emits the #EWebView::new-activity signal. By default the #EActivity
|
||
+ * comes loaded with a #GCancellable and sets the @web_view itself as the
|
||
+ * #EActivity:alert-sink (which means alerts are displayed directly in the
|
||
+ * content area). The signal emission allows the #EActivity to be further
|
||
+ * customized and/or tracked by the application.
|
||
+ *
|
||
+ * Returns: an #EActivity
|
||
+ **/
|
||
+EActivity *
|
||
+e_web_view_new_activity (EWebView *web_view)
|
||
+{
|
||
+ EActivity *activity;
|
||
+ EAlertSink *alert_sink;
|
||
+ GCancellable *cancellable;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
||
+
|
||
+ activity = e_activity_new ();
|
||
+
|
||
+ alert_sink = E_ALERT_SINK (web_view);
|
||
+ e_activity_set_alert_sink (activity, alert_sink);
|
||
+
|
||
+ cancellable = g_cancellable_new ();
|
||
+ e_activity_set_cancellable (activity, cancellable);
|
||
+ g_object_unref (cancellable);
|
||
+
|
||
+ g_signal_emit (web_view, signals[NEW_ACTIVITY], 0, activity);
|
||
+
|
||
+ return activity;
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_status_message (EWebView *web_view,
|
||
+ const gchar *status_message)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ g_signal_emit (web_view, signals[STATUS_MESSAGE], 0, status_message);
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_stop_loading (EWebView *web_view)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ g_signal_emit (web_view, signals[STOP_LOADING], 0);
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_update_actions (EWebView *web_view)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ g_signal_emit (web_view, signals[UPDATE_ACTIONS], 0);
|
||
+}
|
||
+
|
||
+const gchar *
|
||
+e_web_view_get_citation_color_for_level (gint level)
|
||
+{
|
||
+ /* Block quote border colors are borrowed from Thunderbird. */
|
||
+ static const gchar *citation_color_levels[5] = {
|
||
+ "rgb(233,185,110)", /* level 5 - Chocolate 1 */
|
||
+ "rgb(114,159,207)", /* level 1 - Sky Blue 1 */
|
||
+ "rgb(173,127,168)", /* level 2 - Plum 1 */
|
||
+ "rgb(138,226,52)", /* level 3 - Chameleon 1 */
|
||
+ "rgb(252,175,62)", /* level 4 - Orange 1 */
|
||
+ };
|
||
+
|
||
+ g_return_val_if_fail (level > 0, citation_color_levels[1]);
|
||
+
|
||
+ return citation_color_levels[level % 5];
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_update_fonts_settings (GSettings *font_settings,
|
||
+ PangoFontDescription *ms_font,
|
||
+ PangoFontDescription *vw_font,
|
||
+ GtkWidget *view_widget)
|
||
+{
|
||
+ gboolean clean_ms = FALSE, clean_vw = FALSE;
|
||
+ const gchar *styles[] = { "normal", "oblique", "italic" };
|
||
+ gchar fsbuff[G_ASCII_DTOSTR_BUF_SIZE];
|
||
+ GdkColor *link = NULL;
|
||
+ GdkColor *visited = NULL;
|
||
+ GString *stylesheet;
|
||
+ GtkStyleContext *context;
|
||
+ PangoFontDescription *ms, *vw;
|
||
+ WebKitSettings *wk_settings;
|
||
+ WebKitUserContentManager *manager;
|
||
+ WebKitUserStyleSheet *style_sheet;
|
||
+
|
||
+ if (!ms_font) {
|
||
+ gchar *font;
|
||
+
|
||
+ font = g_settings_get_string (
|
||
+ font_settings,
|
||
+ "monospace-font-name");
|
||
+
|
||
+ ms = pango_font_description_from_string (
|
||
+ (font && *font) ? font : "monospace 10");
|
||
+
|
||
+ clean_ms = TRUE;
|
||
+
|
||
+ g_free (font);
|
||
+ } else
|
||
+ ms = ms_font;
|
||
+
|
||
+ if (!pango_font_description_get_family (ms) ||
|
||
+ !pango_font_description_get_size (ms)) {
|
||
+ if (clean_ms)
|
||
+ pango_font_description_free (ms);
|
||
+
|
||
+ clean_ms = TRUE;
|
||
+ ms = pango_font_description_from_string ("monospace 10");
|
||
+ }
|
||
+
|
||
+ if (!vw_font) {
|
||
+ gchar *font;
|
||
+
|
||
+ font = g_settings_get_string (
|
||
+ font_settings,
|
||
+ "font-name");
|
||
+
|
||
+ vw = pango_font_description_from_string (
|
||
+ (font && *font) ? font : "serif 10");
|
||
+
|
||
+ clean_vw = TRUE;
|
||
+
|
||
+ g_free (font);
|
||
+ } else
|
||
+ vw = vw_font;
|
||
+
|
||
+ if (!pango_font_description_get_family (vw) ||
|
||
+ !pango_font_description_get_size (vw)) {
|
||
+ if (clean_vw)
|
||
+ pango_font_description_free (vw);
|
||
+
|
||
+ clean_vw = TRUE;
|
||
+ vw = pango_font_description_from_string ("serif 10");
|
||
+ }
|
||
+
|
||
+ stylesheet = g_string_new ("");
|
||
+ g_ascii_dtostr (fsbuff, G_ASCII_DTOSTR_BUF_SIZE,
|
||
+ ((gdouble) pango_font_description_get_size (vw)) / PANGO_SCALE);
|
||
+
|
||
+ g_string_append_printf (
|
||
+ stylesheet,
|
||
+ "body {\n"
|
||
+ " font-family: '%s';\n"
|
||
+ " font-size: %spt;\n"
|
||
+ " font-weight: %d;\n"
|
||
+ " font-style: %s;\n",
|
||
+ pango_font_description_get_family (vw),
|
||
+ fsbuff,
|
||
+ pango_font_description_get_weight (vw),
|
||
+ styles[pango_font_description_get_style (vw)]);
|
||
+
|
||
+ g_string_append (stylesheet, "}\n");
|
||
+
|
||
+ g_ascii_dtostr (fsbuff, G_ASCII_DTOSTR_BUF_SIZE,
|
||
+ ((gdouble) pango_font_description_get_size (ms)) / PANGO_SCALE);
|
||
+
|
||
+ g_string_append_printf (
|
||
+ stylesheet,
|
||
+ "pre,code,.pre {\n"
|
||
+ " font-family: '%s';\n"
|
||
+ " font-size: %spt;\n"
|
||
+ " font-weight: %d;\n"
|
||
+ " font-style: %s;\n"
|
||
+ " margin: 0px;\n"
|
||
+ "}\n",
|
||
+ pango_font_description_get_family (ms),
|
||
+ fsbuff,
|
||
+ pango_font_description_get_weight (ms),
|
||
+ styles[pango_font_description_get_style (ms)]);
|
||
+
|
||
+ if (view_widget) {
|
||
+ context = gtk_widget_get_style_context (view_widget);
|
||
+ gtk_style_context_get_style (
|
||
+ context,
|
||
+ "link-color", &link,
|
||
+ "visited-link-color", &visited,
|
||
+ NULL);
|
||
+
|
||
+ if (link == NULL) {
|
||
+ GdkRGBA rgba;
|
||
+ GtkStateFlags state;
|
||
+
|
||
+ link = g_slice_new0 (GdkColor);
|
||
+ link->blue = G_MAXINT16;
|
||
+
|
||
+ rgba.alpha = 1;
|
||
+ rgba.red = 0;
|
||
+ rgba.green = 0;
|
||
+ rgba.blue = 1;
|
||
+
|
||
+ state = gtk_style_context_get_state (context);
|
||
+ state = state & (~(GTK_STATE_FLAG_VISITED | GTK_STATE_FLAG_LINK));
|
||
+ state = state | GTK_STATE_FLAG_LINK;
|
||
+
|
||
+ gtk_style_context_save (context);
|
||
+ gtk_style_context_set_state (context, state);
|
||
+ gtk_style_context_get_color (context, state, &rgba);
|
||
+ gtk_style_context_restore (context);
|
||
+
|
||
+ e_rgba_to_color (&rgba, link);
|
||
+ }
|
||
+
|
||
+ if (visited == NULL) {
|
||
+ GdkRGBA rgba;
|
||
+ GtkStateFlags state;
|
||
+
|
||
+ visited = g_slice_new0 (GdkColor);
|
||
+ visited->red = G_MAXINT16;
|
||
+
|
||
+ rgba.alpha = 1;
|
||
+ rgba.red = 1;
|
||
+ rgba.green = 0;
|
||
+ rgba.blue = 0;
|
||
+
|
||
+ state = gtk_style_context_get_state (context);
|
||
+ state = state & (~(GTK_STATE_FLAG_VISITED | GTK_STATE_FLAG_LINK));
|
||
+ state = state | GTK_STATE_FLAG_VISITED;
|
||
+
|
||
+ gtk_style_context_save (context);
|
||
+ gtk_style_context_set_state (context, state);
|
||
+ gtk_style_context_get_color (context, state, &rgba);
|
||
+ gtk_style_context_restore (context);
|
||
+
|
||
+ e_rgba_to_color (&rgba, visited);
|
||
+ }
|
||
+
|
||
+ g_string_append_printf (
|
||
+ stylesheet,
|
||
+ "span.navigable, div.navigable, p.navigable {\n"
|
||
+ " color: #%06x;\n"
|
||
+ "}\n"
|
||
+ "a {\n"
|
||
+ " color: #%06x;\n"
|
||
+ "}\n"
|
||
+ "a:visited {\n"
|
||
+ " color: #%06x;\n"
|
||
+ "}\n",
|
||
+ e_color_to_value (link),
|
||
+ e_color_to_value (link),
|
||
+ e_color_to_value (visited));
|
||
+
|
||
+ gdk_color_free (link);
|
||
+ gdk_color_free (visited);
|
||
+
|
||
+ g_string_append (
|
||
+ stylesheet,
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "{\n"
|
||
+ " padding: 0ch 1ch 0ch 1ch;\n"
|
||
+ " margin: 0ch;\n"
|
||
+ " border-width: 0px 2px 0px 2px;\n"
|
||
+ " border-style: none solid none solid;\n"
|
||
+ " border-radius: 2px;\n"
|
||
+ "}\n");
|
||
+
|
||
+ g_string_append_printf (
|
||
+ stylesheet,
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "{\n"
|
||
+ " border-color: %s;\n"
|
||
+ " margin: 0 0 6px 0;\n"
|
||
+ "}\n",
|
||
+ e_web_view_get_citation_color_for_level (1));
|
||
+
|
||
+ g_string_append_printf (
|
||
+ stylesheet,
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "{\n"
|
||
+ " border-color: %s;\n"
|
||
+ " margin: 0ch;\n"
|
||
+ "}\n",
|
||
+ e_web_view_get_citation_color_for_level (2));
|
||
+
|
||
+ g_string_append_printf (
|
||
+ stylesheet,
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "{\n"
|
||
+ " border-color: %s;\n"
|
||
+ " margin: 0ch;\n"
|
||
+ "}\n",
|
||
+ e_web_view_get_citation_color_for_level (3));
|
||
+
|
||
+ g_string_append_printf (
|
||
+ stylesheet,
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "{\n"
|
||
+ " border-color: %s;\n"
|
||
+ " margin: 0ch;\n"
|
||
+ "}\n",
|
||
+ e_web_view_get_citation_color_for_level (4));
|
||
+
|
||
+ g_string_append_printf (
|
||
+ stylesheet,
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "{\n"
|
||
+ " border-color: %s;\n"
|
||
+ " margin: 0ch;\n"
|
||
+ "}\n",
|
||
+ e_web_view_get_citation_color_for_level (5));
|
||
+
|
||
+ g_string_append_printf (
|
||
+ stylesheet,
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
|
||
+ "{\n"
|
||
+ " border-color: %s;\n"
|
||
+ " padding: 0ch 0ch 0ch 1ch;\n"
|
||
+ " margin: 0ch;\n"
|
||
+ " border-width: 0px 0px 0px 2px;\n"
|
||
+ " border-style: none none none solid;\n"
|
||
+ "}\n",
|
||
+ e_web_view_get_citation_color_for_level (1));
|
||
+ }
|
||
+
|
||
+ wk_settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW (view_widget));
|
||
+
|
||
+ g_object_set (
|
||
+ wk_settings,
|
||
+ "default-font-size",
|
||
+ e_util_normalize_font_size (
|
||
+ view_widget, pango_font_description_get_size (vw) / PANGO_SCALE),
|
||
+ "default-font-family",
|
||
+ pango_font_description_get_family (vw),
|
||
+ "monospace-font-family",
|
||
+ pango_font_description_get_family (ms),
|
||
+ "default-monospace-font-size",
|
||
+ e_util_normalize_font_size (
|
||
+ view_widget, pango_font_description_get_size (ms) / PANGO_SCALE),
|
||
+ NULL);
|
||
+
|
||
+ manager = webkit_web_view_get_user_content_manager (WEBKIT_WEB_VIEW (view_widget));
|
||
+ webkit_user_content_manager_remove_all_style_sheets (manager);
|
||
+
|
||
+ style_sheet = webkit_user_style_sheet_new (
|
||
+ stylesheet->str,
|
||
+ WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
|
||
+ WEBKIT_USER_STYLE_LEVEL_USER,
|
||
+ NULL,
|
||
+ NULL);
|
||
+
|
||
+ webkit_user_content_manager_add_style_sheet (manager, style_sheet);
|
||
+
|
||
+ webkit_user_style_sheet_unref (style_sheet);
|
||
+
|
||
+ g_string_free (stylesheet, TRUE);
|
||
+
|
||
+ if (clean_ms)
|
||
+ pango_font_description_free (ms);
|
||
+ if (clean_vw)
|
||
+ pango_font_description_free (vw);
|
||
+
|
||
+ e_web_view_update_styles (E_WEB_VIEW (view_widget), "*");
|
||
+}
|
||
+
|
||
+WebKitSettings *
|
||
+e_web_view_get_default_webkit_settings (void)
|
||
+{
|
||
+ WebKitSettings *settings;
|
||
+
|
||
+ settings = webkit_settings_new_with_settings (
|
||
+ "auto-load-images", TRUE,
|
||
+ "default-charset", "utf-8",
|
||
+ "enable-html5-database", FALSE,
|
||
+ "enable-dns-prefetching", FALSE,
|
||
+ "enable-html5-local-storage", FALSE,
|
||
+ "enable-java", FALSE,
|
||
+ "enable-javascript", TRUE, /* Needed for JavaScriptCore API to work */
|
||
+ "enable-javascript-markup", FALSE, /* Discards user-provided javascript in HTML */
|
||
+ "enable-offline-web-application-cache", FALSE,
|
||
+ "enable-page-cache", FALSE,
|
||
+ "enable-plugins", FALSE,
|
||
+ "enable-smooth-scrolling", FALSE,
|
||
+ "media-playback-allows-inline", FALSE,
|
||
+ "hardware-acceleration-policy", WEBKIT_HARDWARE_ACCELERATION_POLICY_NEVER,
|
||
+ NULL);
|
||
+
|
||
+ e_web_view_utils_apply_minimum_font_size (settings);
|
||
+
|
||
+ return settings;
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_utils_apply_minimum_font_size (WebKitSettings *wk_settings)
|
||
+{
|
||
+ GSettings *settings;
|
||
+ gint value;
|
||
+
|
||
+ g_return_if_fail (WEBKIT_IS_SETTINGS (wk_settings));
|
||
+
|
||
+ settings = e_util_ref_settings ("org.gnome.evolution.shell");
|
||
+ value = g_settings_get_int (settings, "webkit-minimum-font-size");
|
||
+ g_clear_object (&settings);
|
||
+
|
||
+ if (value < 0)
|
||
+ value = 0;
|
||
+
|
||
+ if (webkit_settings_get_minimum_font_size (wk_settings) != (guint32) value)
|
||
+ webkit_settings_set_minimum_font_size (wk_settings, value);
|
||
+}
|
||
+
|
||
+gint
|
||
+e_web_view_get_minimum_font_size (EWebView *web_view)
|
||
+{
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), -1);
|
||
+
|
||
+ return web_view->priv->minimum_font_size;
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_set_minimum_font_size (EWebView *web_view,
|
||
+ gint pixels)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ if (web_view->priv->minimum_font_size != pixels) {
|
||
+ WebKitSettings *wk_settings;
|
||
+
|
||
+ web_view->priv->minimum_font_size = pixels;
|
||
+
|
||
+ wk_settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW (web_view));
|
||
+ e_web_view_utils_apply_minimum_font_size (wk_settings);
|
||
+
|
||
+ g_object_notify (G_OBJECT (web_view), "minimum-font-size");
|
||
+ }
|
||
+}
|
||
+
|
||
+GCancellable *
|
||
+e_web_view_get_cancellable (EWebView *web_view)
|
||
+{
|
||
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
||
+
|
||
+ return web_view->priv->cancellable;
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_update_fonts (EWebView *web_view)
|
||
+{
|
||
+ EWebViewClass *class;
|
||
+ PangoFontDescription *ms = NULL, *vw = NULL;
|
||
+
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ class = E_WEB_VIEW_GET_CLASS (web_view);
|
||
+ g_return_if_fail (class != NULL);
|
||
+
|
||
+ if (class->set_fonts != NULL)
|
||
+ class->set_fonts (web_view, &ms, &vw);
|
||
+
|
||
+ e_web_view_update_fonts_settings (
|
||
+ web_view->priv->font_settings,
|
||
+ ms, vw, GTK_WIDGET (web_view));
|
||
+
|
||
+ pango_font_description_free (ms);
|
||
+ pango_font_description_free (vw);
|
||
+}
|
||
+
|
||
+/* Helper for e_web_view_cursor_image_copy() */
|
||
+static void
|
||
+web_view_cursor_image_copy_pixbuf_cb (GObject *source_object,
|
||
+ GAsyncResult *result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ EActivity *activity;
|
||
+ EAlertSink *alert_sink;
|
||
+ GdkPixbuf *pixbuf;
|
||
+ GError *local_error = NULL;
|
||
+
|
||
+ activity = E_ACTIVITY (user_data);
|
||
+ alert_sink = e_activity_get_alert_sink (activity);
|
||
+
|
||
+ pixbuf = gdk_pixbuf_new_from_stream_finish (result, &local_error);
|
||
+
|
||
+ /* Sanity check. */
|
||
+ g_return_if_fail (
|
||
+ ((pixbuf != NULL) && (local_error == NULL)) ||
|
||
+ ((pixbuf == NULL) && (local_error != NULL)));
|
||
+
|
||
+ if (e_activity_handle_cancellation (activity, local_error)) {
|
||
+ g_error_free (local_error);
|
||
+
|
||
+ } else if (local_error != NULL) {
|
||
+ e_alert_submit (
|
||
+ alert_sink,
|
||
+ "widgets:no-image-copy",
|
||
+ local_error->message, NULL);
|
||
+ g_error_free (local_error);
|
||
+
|
||
+ } else {
|
||
+ GtkClipboard *clipboard;
|
||
+
|
||
+ clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
|
||
+ gtk_clipboard_set_image (clipboard, pixbuf);
|
||
+ gtk_clipboard_store (clipboard);
|
||
+
|
||
+ e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
|
||
+ }
|
||
+
|
||
+ g_clear_object (&activity);
|
||
+ g_clear_object (&pixbuf);
|
||
+}
|
||
+
|
||
+/* Helper for e_web_view_cursor_image_copy() */
|
||
+static void
|
||
+web_view_cursor_image_copy_request_cb (GObject *source_object,
|
||
+ GAsyncResult *result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ EActivity *activity;
|
||
+ EAlertSink *alert_sink;
|
||
+ GCancellable *cancellable;
|
||
+ GInputStream *input_stream;
|
||
+ GError *local_error = NULL;
|
||
+
|
||
+ activity = E_ACTIVITY (user_data);
|
||
+ alert_sink = e_activity_get_alert_sink (activity);
|
||
+ cancellable = e_activity_get_cancellable (activity);
|
||
+
|
||
+ input_stream = e_web_view_request_finish (
|
||
+ E_WEB_VIEW (source_object), result, &local_error);
|
||
+
|
||
+ /* Sanity check. */
|
||
+ g_return_if_fail (
|
||
+ ((input_stream != NULL) && (local_error == NULL)) ||
|
||
+ ((input_stream == NULL) && (local_error != NULL)));
|
||
+
|
||
+ if (e_activity_handle_cancellation (activity, local_error)) {
|
||
+ g_error_free (local_error);
|
||
+
|
||
+ } else if (local_error != NULL) {
|
||
+ e_alert_submit (
|
||
+ alert_sink,
|
||
+ "widgets:no-image-copy",
|
||
+ local_error->message, NULL);
|
||
+ g_error_free (local_error);
|
||
+
|
||
+ } else {
|
||
+ gdk_pixbuf_new_from_stream_async (
|
||
+ input_stream, cancellable,
|
||
+ web_view_cursor_image_copy_pixbuf_cb,
|
||
+ g_object_ref (activity));
|
||
+ }
|
||
+
|
||
+ g_clear_object (&activity);
|
||
+ g_clear_object (&input_stream);
|
||
+}
|
||
+
|
||
+/**
|
||
+ * e_web_view_cursor_image_copy:
|
||
+ * @web_view: an #EWebView
|
||
+ *
|
||
+ * Asynchronously copies the image under the cursor to the clipboard.
|
||
+ *
|
||
+ * This function triggers an #EWebView::new-activity signal emission so
|
||
+ * the asynchronous operation can be tracked and/or cancelled.
|
||
+ **/
|
||
+void
|
||
+e_web_view_cursor_image_copy (EWebView *web_view)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ if (web_view->priv->cursor_image_src != NULL) {
|
||
+ EActivity *activity;
|
||
+ GCancellable *cancellable;
|
||
+ const gchar *text;
|
||
+
|
||
+ activity = e_web_view_new_activity (web_view);
|
||
+ cancellable = e_activity_get_cancellable (activity);
|
||
+
|
||
+ text = _("Copying image to clipboard");
|
||
+ e_activity_set_text (activity, text);
|
||
+
|
||
+ e_web_view_request (
|
||
+ web_view,
|
||
+ web_view->priv->cursor_image_src,
|
||
+ cancellable,
|
||
+ web_view_cursor_image_copy_request_cb,
|
||
+ g_object_ref (activity));
|
||
+
|
||
+ g_object_unref (activity);
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Helper for e_web_view_cursor_image_save() */
|
||
+static void
|
||
+web_view_cursor_image_save_splice_cb (GObject *source_object,
|
||
+ GAsyncResult *result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ EActivity *activity;
|
||
+ EAlertSink *alert_sink;
|
||
+ AsyncContext *async_context;
|
||
+ GError *local_error = NULL;
|
||
+
|
||
+ async_context = (AsyncContext *) user_data;
|
||
+
|
||
+ activity = async_context->activity;
|
||
+ alert_sink = e_activity_get_alert_sink (activity);
|
||
+
|
||
+ g_output_stream_splice_finish (
|
||
+ G_OUTPUT_STREAM (source_object), result, &local_error);
|
||
+
|
||
+ if (e_activity_handle_cancellation (activity, local_error)) {
|
||
+ g_error_free (local_error);
|
||
+
|
||
+ } else if (local_error != NULL) {
|
||
+ e_alert_submit (
|
||
+ alert_sink,
|
||
+ "widgets:no-image-save",
|
||
+ local_error->message, NULL);
|
||
+ g_error_free (local_error);
|
||
+
|
||
+ } else {
|
||
+ e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
|
||
+ }
|
||
+
|
||
+ async_context_free (async_context);
|
||
+}
|
||
+
|
||
+/* Helper for e_web_view_cursor_image_save() */
|
||
+static void
|
||
+web_view_cursor_image_save_replace_cb (GObject *source_object,
|
||
+ GAsyncResult *result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ EActivity *activity;
|
||
+ EAlertSink *alert_sink;
|
||
+ GCancellable *cancellable;
|
||
+ GFileOutputStream *output_stream;
|
||
+ AsyncContext *async_context;
|
||
+ GError *local_error = NULL;
|
||
+
|
||
+ async_context = (AsyncContext *) user_data;
|
||
+
|
||
+ activity = async_context->activity;
|
||
+ alert_sink = e_activity_get_alert_sink (activity);
|
||
+ cancellable = e_activity_get_cancellable (activity);
|
||
+
|
||
+ output_stream = g_file_replace_finish (
|
||
+ G_FILE (source_object), result, &local_error);
|
||
+
|
||
+ /* Sanity check. */
|
||
+ g_return_if_fail (
|
||
+ ((output_stream != NULL) && (local_error == NULL)) ||
|
||
+ ((output_stream == NULL) && (local_error != NULL)));
|
||
+
|
||
+ if (e_activity_handle_cancellation (activity, local_error)) {
|
||
+ g_error_free (local_error);
|
||
+ async_context_free (async_context);
|
||
+
|
||
+ } else if (local_error != NULL) {
|
||
+ e_alert_submit (
|
||
+ alert_sink,
|
||
+ "widgets:no-image-save",
|
||
+ local_error->message, NULL);
|
||
+ g_error_free (local_error);
|
||
+ async_context_free (async_context);
|
||
+
|
||
+ } else {
|
||
+ g_output_stream_splice_async (
|
||
+ G_OUTPUT_STREAM (output_stream),
|
||
+ async_context->input_stream,
|
||
+ G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
|
||
+ G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
|
||
+ G_PRIORITY_DEFAULT,
|
||
+ cancellable,
|
||
+ web_view_cursor_image_save_splice_cb,
|
||
+ async_context);
|
||
+ }
|
||
+
|
||
+ g_clear_object (&output_stream);
|
||
+}
|
||
+
|
||
+/* Helper for e_web_view_cursor_image_save() */
|
||
+static void
|
||
+web_view_cursor_image_save_request_cb (GObject *source_object,
|
||
+ GAsyncResult *result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ EActivity *activity;
|
||
+ EAlertSink *alert_sink;
|
||
+ GCancellable *cancellable;
|
||
+ GInputStream *input_stream;
|
||
+ AsyncContext *async_context;
|
||
+ GError *local_error = NULL;
|
||
+
|
||
+ async_context = (AsyncContext *) user_data;
|
||
+
|
||
+ activity = async_context->activity;
|
||
+ alert_sink = e_activity_get_alert_sink (activity);
|
||
+ cancellable = e_activity_get_cancellable (activity);
|
||
+
|
||
+ input_stream = e_web_view_request_finish (
|
||
+ E_WEB_VIEW (source_object), result, &local_error);
|
||
+
|
||
+ /* Sanity check. */
|
||
+ g_return_if_fail (
|
||
+ ((input_stream != NULL) && (local_error == NULL)) ||
|
||
+ ((input_stream == NULL) && (local_error != NULL)));
|
||
+
|
||
+ if (e_activity_handle_cancellation (activity, local_error)) {
|
||
+ g_error_free (local_error);
|
||
+ async_context_free (async_context);
|
||
+
|
||
+ } else if (local_error != NULL) {
|
||
+ e_alert_submit (
|
||
+ alert_sink,
|
||
+ "widgets:no-image-save",
|
||
+ local_error->message, NULL);
|
||
+ g_error_free (local_error);
|
||
+ async_context_free (async_context);
|
||
+
|
||
+ } else {
|
||
+ async_context->input_stream = g_object_ref (input_stream);
|
||
+
|
||
+ /* Open an output stream to the destination file. */
|
||
+ g_file_replace_async (
|
||
+ async_context->destination,
|
||
+ NULL, FALSE,
|
||
+ G_FILE_CREATE_REPLACE_DESTINATION,
|
||
+ G_PRIORITY_DEFAULT,
|
||
+ cancellable,
|
||
+ web_view_cursor_image_save_replace_cb,
|
||
+ async_context);
|
||
+ }
|
||
+
|
||
+ g_clear_object (&input_stream);
|
||
+}
|
||
+
|
||
+/**
|
||
+ * e_web_view_cursor_image_save:
|
||
+ * @web_view: an #EWebView
|
||
+ *
|
||
+ * Prompts the user to choose a destination file and then asynchronously
|
||
+ * saves the image under the cursor to the destination file.
|
||
+ *
|
||
+ * This function triggers an #EWebView::new-activity signal emission so
|
||
+ * the asynchronous operation can be tracked and/or cancelled.
|
||
+ **/
|
||
+void
|
||
+e_web_view_cursor_image_save (EWebView *web_view)
|
||
+{
|
||
+ GtkFileChooser *file_chooser;
|
||
+ GtkFileChooserNative *native;
|
||
+ GFile *destination = NULL;
|
||
+ gchar *suggestion;
|
||
+ gpointer toplevel;
|
||
+
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ if (web_view->priv->cursor_image_src == NULL)
|
||
+ return;
|
||
+
|
||
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (web_view));
|
||
+ toplevel = gtk_widget_is_toplevel (toplevel) ? toplevel : NULL;
|
||
+
|
||
+ native = gtk_file_chooser_native_new (
|
||
+ _("Save Image"), toplevel,
|
||
+ GTK_FILE_CHOOSER_ACTION_SAVE,
|
||
+ _("_Save"), _("_Cancel"));
|
||
+
|
||
+ file_chooser = GTK_FILE_CHOOSER (native);
|
||
+ gtk_file_chooser_set_local_only (file_chooser, FALSE);
|
||
+ gtk_file_chooser_set_do_overwrite_confirmation (file_chooser, TRUE);
|
||
+
|
||
+ suggestion = e_web_view_suggest_filename (
|
||
+ web_view, web_view->priv->cursor_image_src);
|
||
+
|
||
+ if (suggestion != NULL) {
|
||
+ gtk_file_chooser_set_current_name (file_chooser, suggestion);
|
||
+ g_free (suggestion);
|
||
+ }
|
||
+
|
||
+ e_util_load_file_chooser_folder (file_chooser);
|
||
+
|
||
+ if (gtk_native_dialog_run (GTK_NATIVE_DIALOG (native)) == GTK_RESPONSE_ACCEPT) {
|
||
+ e_util_save_file_chooser_folder (file_chooser);
|
||
+
|
||
+ destination = gtk_file_chooser_get_file (file_chooser);
|
||
+ }
|
||
+
|
||
+ g_object_unref (native);
|
||
+
|
||
+ if (destination != NULL) {
|
||
+ EActivity *activity;
|
||
+ GCancellable *cancellable;
|
||
+ AsyncContext *async_context;
|
||
+ gchar *text;
|
||
+ gchar *uri;
|
||
+
|
||
+ activity = e_web_view_new_activity (web_view);
|
||
+ cancellable = e_activity_get_cancellable (activity);
|
||
+
|
||
+ uri = g_file_get_uri (destination);
|
||
+ text = g_strdup_printf (_("Saving image to “%s”"), uri);
|
||
+ e_activity_set_text (activity, text);
|
||
+ g_free (text);
|
||
+ g_free (uri);
|
||
+
|
||
+ async_context = g_slice_new0 (AsyncContext);
|
||
+ async_context->activity = g_object_ref (activity);
|
||
+ async_context->destination = g_object_ref (destination);
|
||
+
|
||
+ e_web_view_request (
|
||
+ web_view,
|
||
+ web_view->priv->cursor_image_src,
|
||
+ cancellable,
|
||
+ web_view_cursor_image_save_request_cb,
|
||
+ async_context);
|
||
+
|
||
+ g_object_unref (activity);
|
||
+ g_object_unref (destination);
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Helper for e_web_view_request() */
|
||
+static void
|
||
+web_view_request_process_thread (GTask *task,
|
||
+ gpointer source_object,
|
||
+ gpointer task_data,
|
||
+ GCancellable *cancellable)
|
||
+{
|
||
+ AsyncContext *async_context = task_data;
|
||
+ gint64 stream_length = -1;
|
||
+ gchar *mime_type = NULL;
|
||
+ GError *local_error = NULL;
|
||
+
|
||
+ if (!e_content_request_process_sync (async_context->content_request,
|
||
+ async_context->uri, source_object, &async_context->input_stream,
|
||
+ &stream_length, &mime_type, cancellable, &local_error)) {
|
||
+ g_task_return_error (task, local_error);
|
||
+ } else {
|
||
+ g_task_return_boolean (task, TRUE);
|
||
+ }
|
||
+
|
||
+ g_free (mime_type);
|
||
+}
|
||
+
|
||
+/**
|
||
+ * e_web_view_request:
|
||
+ * @web_view: an #EWebView
|
||
+ * @uri: the URI to load
|
||
+ * @cancellable: optional #GCancellable object, or %NULL
|
||
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
|
||
+ * @user_data: data to pass to the callback function
|
||
+ *
|
||
+ * Asynchronously requests data at @uri as displaed in the @web_view.
|
||
+ *
|
||
+ * When the operation is finished, @callback will be called. You can then
|
||
+ * call e_web_view_request_finish() to get the result of the operation.
|
||
+ **/
|
||
+void
|
||
+e_web_view_request (EWebView *web_view,
|
||
+ const gchar *uri,
|
||
+ GCancellable *cancellable,
|
||
+ GAsyncReadyCallback callback,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ EContentRequest *content_request = NULL;
|
||
+ AsyncContext *async_context;
|
||
+ GHashTableIter iter;
|
||
+ GTask *task;
|
||
+ gboolean is_processed = FALSE;
|
||
+ gpointer value;
|
||
+
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+ g_return_if_fail (uri != NULL);
|
||
+
|
||
+ g_hash_table_iter_init (&iter, web_view->priv->scheme_handlers);
|
||
+
|
||
+ while (g_hash_table_iter_next (&iter, NULL, &value)) {
|
||
+ EContentRequest *adept = value;
|
||
+
|
||
+ if (!E_IS_CONTENT_REQUEST (adept) ||
|
||
+ !e_content_request_can_process_uri (adept, uri))
|
||
+ continue;
|
||
+
|
||
+ content_request = adept;
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ async_context = g_slice_new0 (AsyncContext);
|
||
+ async_context->uri = g_strdup (uri);
|
||
+
|
||
+ task = g_task_new (web_view, cancellable, callback, user_data);
|
||
+ g_task_set_task_data (task, async_context, async_context_free);
|
||
+ g_task_set_check_cancellable (task, TRUE);
|
||
+
|
||
+ if (content_request) {
|
||
+ async_context->content_request = g_object_ref (content_request);
|
||
+ g_task_run_in_thread (task, web_view_request_process_thread);
|
||
+ is_processed = TRUE;
|
||
+
|
||
+ /* Handle base64-encoded "data:" URIs manually */
|
||
+ } else if (g_ascii_strncasecmp (uri, "data:", 5) == 0) {
|
||
+ /* data:[<mime type>][;charset=<charset>][;base64],<encoded data> */
|
||
+ const gchar *ptr, *from;
|
||
+ gboolean is_base64 = FALSE;
|
||
+
|
||
+ ptr = uri + 5;
|
||
+ from = ptr;
|
||
+ while (*ptr && *ptr != ',') {
|
||
+ ptr++;
|
||
+
|
||
+ if (*ptr == ',' || *ptr == ';') {
|
||
+ if (g_ascii_strncasecmp (from, "base64", ptr - from) == 0)
|
||
+ is_base64 = TRUE;
|
||
+
|
||
+ from = ptr + 1;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (is_base64 && *ptr == ',') {
|
||
+ guchar *data;
|
||
+ gsize len = 0;
|
||
+
|
||
+ data = g_base64_decode (ptr + 1, &len);
|
||
+
|
||
+ if (data && len > 0) {
|
||
+ async_context->input_stream = g_memory_input_stream_new_from_data (data, len, g_free);
|
||
+ g_task_return_boolean (task, TRUE);
|
||
+ is_processed = TRUE;
|
||
+ } else {
|
||
+ g_free (data);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (!is_processed) {
|
||
+ GString *shorten_uri = NULL;
|
||
+ gint len;
|
||
+
|
||
+ len = g_utf8_strlen (uri, -1);
|
||
+
|
||
+ /* The "data:" URIs can be quite long */
|
||
+ if (len > 512) {
|
||
+ const gchar *ptr = g_utf8_offset_to_pointer (uri, 512);
|
||
+
|
||
+ shorten_uri = g_string_sized_new (ptr - uri + 16);
|
||
+ g_string_append_len (shorten_uri, uri, ptr - uri);
|
||
+ g_string_append (shorten_uri, _("…"));
|
||
+ }
|
||
+
|
||
+ g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||
+ _("Cannot get URI “%s”, do not know how to download it."), shorten_uri ? shorten_uri->str : uri);
|
||
+
|
||
+ if (shorten_uri)
|
||
+ g_string_free (shorten_uri, TRUE);
|
||
+ }
|
||
+
|
||
+ g_object_unref (task);
|
||
+}
|
||
+
|
||
+/**
|
||
+ * e_web_view_request_finish:
|
||
+ * @web_view: an #EWebView
|
||
+ * @result: a #GAsyncResult
|
||
+ * @error: return location for a #GError, or %NULL
|
||
+ *
|
||
+ * Finishes the operation started with e_web_view_request().
|
||
+ *
|
||
+ * Unreference the returned #GInputStream with g_object_unref() when finished
|
||
+ * with it. If an error occurred, the function will set @error and return
|
||
+ * %NULL.
|
||
+ *
|
||
+ * Returns: a #GInputStream, or %NULL
|
||
+ **/
|
||
+GInputStream *
|
||
+e_web_view_request_finish (EWebView *web_view,
|
||
+ GAsyncResult *result,
|
||
+ GError **error)
|
||
+{
|
||
+ AsyncContext *async_context;
|
||
+
|
||
+ g_return_val_if_fail (g_task_is_valid (result, web_view), NULL);
|
||
+
|
||
+ if (!g_task_propagate_boolean (G_TASK (result), error))
|
||
+ return NULL;
|
||
+
|
||
+ async_context = g_task_get_task_data (G_TASK (result));
|
||
+
|
||
+ g_return_val_if_fail (async_context->input_stream != NULL, NULL);
|
||
+
|
||
+ return g_object_ref (async_context->input_stream);
|
||
+}
|
||
+
|
||
+/**
|
||
+ * e_web_view_set_iframe_src:
|
||
+ * @web_view: an #EWebView
|
||
+ * @document_uri: a document URI for whose IFrame change the source
|
||
+ * @src_uri: the source to change the IFrame to
|
||
+ *
|
||
+ * Change IFrame source for the given @document_uri IFrame
|
||
+ * to the @new_iframe_src.
|
||
+ *
|
||
+ * Since: 3.22
|
||
+ **/
|
||
+void
|
||
+e_web_view_set_iframe_src (EWebView *web_view,
|
||
+ const gchar *iframe_id,
|
||
+ const gchar *src_uri)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+
|
||
+ e_web_view_jsc_run_script (WEBKIT_WEB_VIEW (web_view), web_view->priv->cancellable,
|
||
+ "Evo.SetIFrameSrc(%s, %s);",
|
||
+ iframe_id, src_uri);
|
||
+}
|
||
+
|
||
+/**
|
||
+ * EWebViewElementClickedFunc:
|
||
+ * @web_view: an #EWebView
|
||
+ * @iframe_id: an iframe ID in which the click happened; empty string for the main frame
|
||
+ * @element_id: an element ID
|
||
+ * @element_class: an element class, as set on the element which had been clicked
|
||
+ * @element_value: a 'value' attribute content of the clicked element
|
||
+ * @element_position: a #GtkAllocation with the position of the clicked element
|
||
+ * @user_data: user data as provided in the e_web_view_register_element_clicked() call
|
||
+ *
|
||
+ * The callback is called whenever an element of class @element_class is clicked.
|
||
+ * The @element_value is a content of the 'value' attribute of the clicked element.
|
||
+ * The @element_position is the place of the element within the web page, already
|
||
+ * accounting scrollbar positions.
|
||
+ *
|
||
+ * See: e_web_view_register_element_clicked, e_web_view_unregister_element_clicked
|
||
+ *
|
||
+ * Since: 3.22
|
||
+ **/
|
||
+
|
||
+/**
|
||
+ * e_web_view_register_element_clicked:
|
||
+ * @web_view: an #EWebView
|
||
+ * @element_class: an element class on which to listen for clicking
|
||
+ * @callback: an #EWebViewElementClickedFunc to call, when the element is clicked
|
||
+ * @user_data: user data to pass to @callback
|
||
+ *
|
||
+ * Registers a @callback to be called when any element of the class @element_class
|
||
+ * is clicked. If the element contains a 'value' attribute, then it is passed to
|
||
+ * the @callback too. These callback are valid until a new content of the @web_view
|
||
+ * is loaded, after which all the registered callbacks are forgotten.
|
||
+ *
|
||
+ * Since: 3.22
|
||
+ **/
|
||
+void
|
||
+e_web_view_register_element_clicked (EWebView *web_view,
|
||
+ const gchar *element_class,
|
||
+ EWebViewElementClickedFunc callback,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ ElementClickedData *ecd;
|
||
+ GPtrArray *cbs;
|
||
+ guint ii;
|
||
+
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+ g_return_if_fail (element_class != NULL);
|
||
+ g_return_if_fail (callback != NULL);
|
||
+
|
||
+ cbs = g_hash_table_lookup (web_view->priv->element_clicked_cbs, element_class);
|
||
+ if (cbs) {
|
||
+ for (ii = 0; ii < cbs->len; ii++) {
|
||
+ ecd = g_ptr_array_index (cbs, ii);
|
||
+
|
||
+ if (ecd && ecd->callback == callback && ecd->user_data == user_data) {
|
||
+ /* Callback is already registered, but re-register it, in case the page
|
||
+ was changed dynamically and new elements with the given call are added. */
|
||
+ web_view_call_register_element_clicked (web_view, "*", element_class);
|
||
+ return;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ ecd = g_new0 (ElementClickedData, 1);
|
||
+ ecd->callback = callback;
|
||
+ ecd->user_data = user_data;
|
||
+
|
||
+ if (!cbs) {
|
||
+ cbs = g_ptr_array_new_full (1, g_free);
|
||
+ g_ptr_array_add (cbs, ecd);
|
||
+
|
||
+ g_hash_table_insert (web_view->priv->element_clicked_cbs, g_strdup (element_class), cbs);
|
||
+ } else {
|
||
+ g_ptr_array_add (cbs, ecd);
|
||
+ }
|
||
+
|
||
+ /* Dynamically changing page can call this multiple times; re-register all classes */
|
||
+ web_view_call_register_element_clicked (web_view, "*", NULL);
|
||
+}
|
||
+
|
||
+/**
|
||
+ * e_web_view_unregister_element_clicked:
|
||
+ * @web_view: an #EWebView
|
||
+ * @element_class: an element class on which to listen for clicking
|
||
+ * @callback: an #EWebViewElementClickedFunc to call, when the element is clicked
|
||
+ * @user_data: user data to pass to @callback
|
||
+ *
|
||
+ * Unregisters the @callback for the @element_class with the given @user_data, which
|
||
+ * should be previously registered with e_web_view_register_element_clicked(). This
|
||
+ * unregister is usually not needed, because the @web_view unregisters all callbacks
|
||
+ * when a new content is loaded.
|
||
+ *
|
||
+ * Since: 3.22
|
||
+ **/
|
||
+void
|
||
+e_web_view_unregister_element_clicked (EWebView *web_view,
|
||
+ const gchar *element_class,
|
||
+ EWebViewElementClickedFunc callback,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ ElementClickedData *ecd;
|
||
+ GPtrArray *cbs;
|
||
+ guint ii;
|
||
+
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+ g_return_if_fail (element_class != NULL);
|
||
+ g_return_if_fail (callback != NULL);
|
||
+
|
||
+ cbs = g_hash_table_lookup (web_view->priv->element_clicked_cbs, element_class);
|
||
+ if (!cbs)
|
||
+ return;
|
||
+
|
||
+ for (ii = 0; ii < cbs->len; ii++) {
|
||
+ ecd = g_ptr_array_index (cbs, ii);
|
||
+
|
||
+ if (ecd && ecd->callback == callback && ecd->user_data == user_data) {
|
||
+ g_ptr_array_remove (cbs, ecd);
|
||
+ if (!cbs->len)
|
||
+ g_hash_table_remove (web_view->priv->element_clicked_cbs, element_class);
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_set_element_hidden (EWebView *web_view,
|
||
+ const gchar *element_id,
|
||
+ gboolean hidden)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+ g_return_if_fail (element_id && *element_id);
|
||
+
|
||
+ e_web_view_jsc_set_element_hidden (WEBKIT_WEB_VIEW (web_view),
|
||
+ "*", element_id, hidden,
|
||
+ web_view->priv->cancellable);
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_set_element_style_property (EWebView *web_view,
|
||
+ const gchar *element_id,
|
||
+ const gchar *property_name,
|
||
+ const gchar *value)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+ g_return_if_fail (element_id && *element_id);
|
||
+ g_return_if_fail (property_name && *property_name);
|
||
+
|
||
+ e_web_view_jsc_set_element_style_property (WEBKIT_WEB_VIEW (web_view),
|
||
+ "*", element_id, property_name, value,
|
||
+ web_view->priv->cancellable);
|
||
+}
|
||
+
|
||
+void
|
||
+e_web_view_set_element_attribute (EWebView *web_view,
|
||
+ const gchar *element_id,
|
||
+ const gchar *namespace_uri,
|
||
+ const gchar *qualified_name,
|
||
+ const gchar *value)
|
||
+{
|
||
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
||
+ g_return_if_fail (element_id && *element_id);
|
||
+ g_return_if_fail (qualified_name && *qualified_name);
|
||
+
|
||
+ e_web_view_jsc_set_element_attribute (WEBKIT_WEB_VIEW (web_view),
|
||
+ "*", element_id, namespace_uri, qualified_name, value,
|
||
+ web_view->priv->cancellable);
|
||
+}
|
||
diff -urN a/src/e-util/test-html-editor-units-utils.c b/src/e-util/test-html-editor-units-utils.c
|
||
--- a/src/e-util/test-html-editor-units-utils.c 2025-06-07 14:20:57.327397173 -0700
|
||
+++ b/src/e-util/test-html-editor-units-utils.c 2025-06-07 14:27:24.051673010 -0700
|
||
@@ -227,7 +227,7 @@
|
||
return FALSE;
|
||
}
|
||
|
||
-/* <Control>+<Shift>+I */
|
||
+/* <Super>+<Shift>+I */
|
||
#define WEBKIT_INSPECTOR_MOD (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
|
||
#define WEBKIT_INSPECTOR_KEY (GDK_KEY_I)
|
||
|
||
diff -urN a/src/e-util/test-html-editor.c b/src/e-util/test-html-editor.c
|
||
--- a/src/e-util/test-html-editor.c 2025-06-07 14:20:57.331397221 -0700
|
||
+++ b/src/e-util/test-html-editor.c 2025-06-07 14:27:24.051673010 -0700
|
||
@@ -423,7 +423,7 @@
|
||
{ "new-editor",
|
||
"document-new",
|
||
N_("_New editor"),
|
||
- "<Control>N",
|
||
+ "<Super>N",
|
||
NULL,
|
||
G_CALLBACK (action_new_editor_cb) },
|
||
|
||
@@ -431,14 +431,14 @@
|
||
{ "print",
|
||
"document-print",
|
||
N_("_Print…"),
|
||
- "<Control>p",
|
||
+ "<Super>p",
|
||
NULL,
|
||
G_CALLBACK (action_print_cb) },
|
||
|
||
{ "print-preview",
|
||
"document-print-preview",
|
||
N_("Print Pre_view"),
|
||
- "<Control><Shift>p",
|
||
+ "<Super><Shift>p",
|
||
NULL,
|
||
G_CALLBACK (action_print_preview_cb) },
|
||
#endif /* ENABLE_PRINT */
|
||
@@ -513,7 +513,7 @@
|
||
NULL,
|
||
N_("Inspector"),
|
||
NULL,
|
||
- "<Control><Shift>I",
|
||
+ "<Super><Shift>I",
|
||
G_CALLBACK (action_view_inspector) },
|
||
|
||
{ "view-menu",
|
||
diff -urN a/src/mail/e-mail-browser.c b/src/mail/e-mail-browser.c
|
||
--- a/src/mail/e-mail-browser.c 2025-06-07 14:20:57.347397414 -0700
|
||
+++ b/src/mail/e-mail-browser.c 2025-06-07 14:27:24.055673052 -0700
|
||
@@ -164,28 +164,28 @@
|
||
{ "close",
|
||
"window-close",
|
||
N_("_Close"),
|
||
- "<Control>w",
|
||
+ "<Super>w",
|
||
N_("Close this window"),
|
||
G_CALLBACK (action_close_cb) },
|
||
|
||
{ "copy-clipboard",
|
||
"edit-copy",
|
||
N_("_Copy"),
|
||
- "<Control>c",
|
||
+ "<Super>c",
|
||
N_("Copy the selection"),
|
||
NULL }, /* Handled by EFocusTracker */
|
||
|
||
{ "cut-clipboard",
|
||
"edit-cut",
|
||
N_("Cu_t"),
|
||
- "<Control>x",
|
||
+ "<Super>x",
|
||
N_("Cut the selection"),
|
||
NULL }, /* Handled by EFocusTracker */
|
||
|
||
{ "paste-clipboard",
|
||
"edit-paste",
|
||
N_("_Paste"),
|
||
- "<Control>v",
|
||
+ "<Super>v",
|
||
N_("Paste the clipboard"),
|
||
NULL }, /* Handled by EFocusTracker */
|
||
|
||
diff -urN a/src/mail/e-mail-notes.c b/src/mail/e-mail-notes.c
|
||
--- a/src/mail/e-mail-notes.c 2025-06-07 14:20:57.351397462 -0700
|
||
+++ b/src/mail/e-mail-notes.c 2025-06-07 14:27:24.055673052 -0700
|
||
@@ -1107,14 +1107,14 @@
|
||
{ "close",
|
||
"window-close",
|
||
N_("_Close"),
|
||
- "<Control>w",
|
||
+ "<Super>w",
|
||
N_("Close"),
|
||
G_CALLBACK (action_close_cb) },
|
||
|
||
{ "save-and-close",
|
||
"document-save",
|
||
N_("_Save and Close"),
|
||
- "<Control>Return",
|
||
+ "<Alt><Super>s",
|
||
N_("Save and Close"),
|
||
G_CALLBACK (action_save_and_close_cb) },
|
||
|
||
diff -urN a/src/mail/e-mail-reader.c b/src/mail/e-mail-reader.c
|
||
--- a/src/mail/e-mail-reader.c 2025-06-07 14:20:57.351397462 -0700
|
||
+++ b/src/mail/e-mail-reader.c 2025-06-07 14:27:24.055673052 -0700
|
||
@@ -2514,14 +2514,14 @@
|
||
{ "mail-archive",
|
||
"mail-archive",
|
||
N_("_Archive…"),
|
||
- "<Alt><Control>a",
|
||
+ "<Alt><Super>a",
|
||
N_("Move selected messages to the Archive folder for the account"),
|
||
G_CALLBACK (action_mail_archive_cb) },
|
||
|
||
{ "mail-check-for-junk",
|
||
"mail-mark-junk",
|
||
N_("Check for _Junk"),
|
||
- "<Control><Alt>j",
|
||
+ "<Super><Alt>j",
|
||
N_("Filter the selected messages for junk status"),
|
||
G_CALLBACK (action_mail_check_for_junk_cb) },
|
||
|
||
@@ -2542,14 +2542,14 @@
|
||
{ "mail-copy",
|
||
"mail-copy",
|
||
N_("_Copy to Folder…"),
|
||
- "<Shift><Control>y",
|
||
+ "<Shift><Super>y",
|
||
N_("Copy selected messages to another folder"),
|
||
G_CALLBACK (action_mail_copy_cb) },
|
||
|
||
{ "mail-delete",
|
||
"user-trash",
|
||
N_("_Delete Message"),
|
||
- "<Control>d",
|
||
+ "<Super>d",
|
||
N_("Mark the selected messages for deletion"),
|
||
G_CALLBACK (action_mail_delete_cb) },
|
||
|
||
@@ -2605,14 +2605,14 @@
|
||
{ "mail-filters-apply",
|
||
"stock_mail-filters-apply",
|
||
N_("A_pply Filters"),
|
||
- "<Control>y",
|
||
+ "<Super>y",
|
||
N_("Apply filter rules to the selected messages"),
|
||
G_CALLBACK (action_mail_filters_apply_cb) },
|
||
|
||
{ "mail-find",
|
||
"edit-find",
|
||
N_("_Find in Message…"),
|
||
- "<Shift><Control>f",
|
||
+ "<Shift><Super>f",
|
||
N_("Search for text in the body of the displayed message"),
|
||
G_CALLBACK (action_mail_find_cb) },
|
||
|
||
@@ -2633,14 +2633,14 @@
|
||
{ "mail-flag-for-followup",
|
||
"stock_mail-flag-for-followup",
|
||
N_("Follow _Up…"),
|
||
- "<Shift><Control>g",
|
||
+ "<Shift><Super>g",
|
||
N_("Flag the selected messages for follow-up"),
|
||
G_CALLBACK (action_mail_flag_for_followup_cb) },
|
||
|
||
{ "mail-forward",
|
||
"mail-forward",
|
||
N_("_Forward"),
|
||
- "<Control>f",
|
||
+ "<Super>f",
|
||
N_("Forward the selected message to someone"),
|
||
G_CALLBACK (action_mail_forward_cb) },
|
||
|
||
@@ -2705,7 +2705,7 @@
|
||
{ "mail-load-images",
|
||
"image-x-generic",
|
||
N_("_Load Images"),
|
||
- "<Control>i",
|
||
+ "<Super>i",
|
||
N_("Force images in HTML mail to be loaded"),
|
||
G_CALLBACK (action_mail_load_images_cb) },
|
||
|
||
@@ -2733,21 +2733,21 @@
|
||
{ "mail-mark-junk",
|
||
"mail-mark-junk",
|
||
N_("_Junk"),
|
||
- "<Control>j",
|
||
+ "<Super>j",
|
||
N_("Mark the selected messages as junk"),
|
||
G_CALLBACK (action_mail_mark_junk_cb) },
|
||
|
||
{ "mail-mark-notjunk",
|
||
"mail-mark-notjunk",
|
||
N_("_Not Junk"),
|
||
- "<Shift><Control>j",
|
||
+ "<Shift><Super>j",
|
||
N_("Mark the selected messages as not being junk"),
|
||
G_CALLBACK (action_mail_mark_notjunk_cb) },
|
||
|
||
{ "mail-mark-read",
|
||
"mail-mark-read",
|
||
N_("_Read"),
|
||
- "<Control>k",
|
||
+ "<Super>k",
|
||
N_("Mark the selected messages as having been read"),
|
||
G_CALLBACK (action_mail_mark_read_cb) },
|
||
|
||
@@ -2775,7 +2775,7 @@
|
||
{ "mail-mark-unread",
|
||
"mail-mark-unread",
|
||
N_("_Unread"),
|
||
- "<Shift><Control>k",
|
||
+ "<Shift><Super>k",
|
||
N_("Mark the selected messages as not having been read"),
|
||
G_CALLBACK (action_mail_mark_unread_cb) },
|
||
|
||
@@ -2789,28 +2789,28 @@
|
||
{ "mail-message-new",
|
||
"mail-message-new",
|
||
N_("Compose _New Message"),
|
||
- "<Shift><Control>m",
|
||
+ "<Shift><Super>m",
|
||
N_("Open a window for composing a mail message"),
|
||
G_CALLBACK (action_mail_message_new_cb) },
|
||
|
||
{ "mail-message-open",
|
||
NULL,
|
||
N_("_Open in New Window"),
|
||
- "<Control>o",
|
||
+ "<Super>o",
|
||
N_("Open the selected messages in a new window"),
|
||
G_CALLBACK (action_mail_message_open_cb) },
|
||
|
||
{ "mail-move",
|
||
"mail-move",
|
||
N_("_Move to Folder…"),
|
||
- "<Shift><Control>v",
|
||
+ "<Shift><Super>v",
|
||
N_("Move selected messages to another folder"),
|
||
G_CALLBACK (action_mail_move_cb) },
|
||
|
||
{ "mail-next",
|
||
"go-next",
|
||
N_("_Next Message"),
|
||
- "<Control>Page_Down",
|
||
+ "<Super>Page_Down",
|
||
N_("Display the next message"),
|
||
G_CALLBACK (action_mail_next_cb) },
|
||
|
||
@@ -2831,14 +2831,14 @@
|
||
{ "mail-next-unread",
|
||
"go-jump",
|
||
N_("Next _Unread Message"),
|
||
- "<Control>bracketright",
|
||
+ "<Super>bracketright",
|
||
N_("Display the next unread message"),
|
||
G_CALLBACK (action_mail_next_unread_cb) },
|
||
|
||
{ "mail-previous",
|
||
"go-previous",
|
||
N_("_Previous Message"),
|
||
- "<Control>Page_Up",
|
||
+ "<Super>Page_Up",
|
||
N_("Display the previous message"),
|
||
G_CALLBACK (action_mail_previous_cb) },
|
||
|
||
@@ -2859,14 +2859,14 @@
|
||
{ "mail-previous-unread",
|
||
NULL,
|
||
N_("P_revious Unread Message"),
|
||
- "<Control>bracketleft",
|
||
+ "<Super>bracketleft",
|
||
N_("Display the previous unread message"),
|
||
G_CALLBACK (action_mail_previous_unread_cb) },
|
||
|
||
{ "mail-print",
|
||
"document-print",
|
||
N_("_Print…"),
|
||
- "<Control>p",
|
||
+ "<Super>p",
|
||
N_("Print this message"),
|
||
G_CALLBACK (action_mail_print_cb) },
|
||
|
||
@@ -2901,35 +2901,35 @@
|
||
{ "mail-reply-all",
|
||
NULL,
|
||
N_("Reply to _All"),
|
||
- "<Shift><Control>r",
|
||
+ "<Shift><Super>r",
|
||
N_("Compose a reply to all the recipients of the selected message"),
|
||
G_CALLBACK (action_mail_reply_all_cb) },
|
||
|
||
{ "mail-reply-alternative",
|
||
NULL,
|
||
N_("Al_ternative Reply…"),
|
||
- "<Alt><Control>r",
|
||
+ "<Alt><Super>r",
|
||
N_("Choose reply options for the selected message"),
|
||
G_CALLBACK (action_mail_reply_alternative_cb) },
|
||
|
||
{ "mail-reply-group",
|
||
"mail-reply-all",
|
||
N_("Group Reply"),
|
||
- "<Control>g",
|
||
+ "<Super>g",
|
||
N_("Reply to the mailing list, or to all recipients"),
|
||
G_CALLBACK (action_mail_reply_group_cb) },
|
||
|
||
{ "mail-reply-list",
|
||
NULL,
|
||
N_("Reply to _List"),
|
||
- "<Control>l",
|
||
+ "<Super>l",
|
||
N_("Compose a reply to the mailing list of the selected message"),
|
||
G_CALLBACK (action_mail_reply_list_cb) },
|
||
|
||
{ "mail-reply-sender",
|
||
"mail-reply-sender",
|
||
N_("_Reply to Sender"),
|
||
- "<Control>r",
|
||
+ "<Super>r",
|
||
N_("Compose a reply to the sender of the selected message"),
|
||
G_CALLBACK (action_mail_reply_sender_cb) },
|
||
|
||
@@ -2943,7 +2943,7 @@
|
||
{ "mail-save-as",
|
||
"document-save-as",
|
||
N_("_Save as mbox…"),
|
||
- "<Control>s",
|
||
+ "<Super>s",
|
||
N_("Save selected messages as an mbox file"),
|
||
G_CALLBACK (action_mail_save_as_cb) },
|
||
|
||
@@ -2957,7 +2957,7 @@
|
||
{ "mail-show-source",
|
||
NULL,
|
||
N_("_Message Source"),
|
||
- "<Control>u",
|
||
+ "<Super>u",
|
||
N_("Show the raw email source of the message"),
|
||
G_CALLBACK (action_mail_show_source_cb) },
|
||
|
||
@@ -2971,28 +2971,28 @@
|
||
{ "mail-undelete",
|
||
NULL,
|
||
N_("_Undelete Message"),
|
||
- "<Shift><Control>d",
|
||
+ "<Shift><Super>d",
|
||
N_("Undelete the selected messages"),
|
||
G_CALLBACK (action_mail_undelete_cb) },
|
||
|
||
{ "mail-zoom-100",
|
||
"zoom-original",
|
||
N_("_Normal Size"),
|
||
- "<Control>0",
|
||
+ "<Super>0",
|
||
N_("Reset the text to its original size"),
|
||
G_CALLBACK (action_mail_zoom_100_cb) },
|
||
|
||
{ "mail-zoom-in",
|
||
"zoom-in",
|
||
N_("_Zoom In"),
|
||
- "<Control>plus",
|
||
+ "<Super>plus",
|
||
N_("Increase the text size"),
|
||
G_CALLBACK (action_mail_zoom_in_cb) },
|
||
|
||
{ "mail-zoom-out",
|
||
"zoom-out",
|
||
N_("Zoom _Out"),
|
||
- "<Control>minus",
|
||
+ "<Super>minus",
|
||
N_("Decrease the text size"),
|
||
G_CALLBACK (action_mail_zoom_out_cb) },
|
||
|
||
@@ -5238,7 +5238,7 @@
|
||
G_CALLBACK (action_mail_forward_cb), reader);
|
||
|
||
gtk_action_group_add_action_with_accel (
|
||
- action_group, GTK_ACTION (menu_tool_action), "<Control>f");
|
||
+ action_group, GTK_ACTION (menu_tool_action), "<Super>f");
|
||
|
||
/* Likewise the "mail-reply-group" action. */
|
||
|
||
@@ -5263,7 +5263,7 @@
|
||
G_CALLBACK (action_mail_reply_group_cb), reader);
|
||
|
||
gtk_action_group_add_action_with_accel (
|
||
- action_group, GTK_ACTION (menu_tool_action), "<Control>g");
|
||
+ action_group, GTK_ACTION (menu_tool_action), "<Super>g");
|
||
|
||
/* Add EMailReader actions for Search Folders. The action group
|
||
* should be made invisible if Search Folders are disabled. */
|
||
diff -urN a/src/mail/e-mail-reader.c.orig b/src/mail/e-mail-reader.c.orig
|
||
--- a/src/mail/e-mail-reader.c.orig 1969-12-31 16:00:00.000000000 -0800
|
||
+++ b/src/mail/e-mail-reader.c.orig 2025-06-07 14:20:57.351397462 -0700
|
||
@@ -0,0 +1,6452 @@
|
||
+/*
|
||
+ * e-mail-reader.c
|
||
+ *
|
||
+ * This program is free software; you can redistribute it and/or modify it
|
||
+ * under the terms of the GNU Lesser General Public License as published by
|
||
+ * the Free Software Foundation.
|
||
+ *
|
||
+ * This program is distributed in the hope that it will be useful, but
|
||
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||
+ * for more details.
|
||
+ *
|
||
+ * You should have received a copy of the GNU Lesser General Public License
|
||
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||
+ *
|
||
+ *
|
||
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
|
||
+ *
|
||
+ */
|
||
+
|
||
+#include "evolution-config.h"
|
||
+
|
||
+#include "e-mail-reader.h"
|
||
+
|
||
+#include <glib/gi18n.h>
|
||
+#include <gdk/gdkkeysyms.h>
|
||
+
|
||
+#ifdef HAVE_XFREE
|
||
+#include <X11/XF86keysym.h>
|
||
+#endif
|
||
+
|
||
+#include <shell/e-shell-headerbar.h>
|
||
+#include <shell/e-shell-utils.h>
|
||
+
|
||
+#include <libemail-engine/libemail-engine.h>
|
||
+
|
||
+#include <em-format/e-mail-formatter.h>
|
||
+#include <em-format/e-mail-parser.h>
|
||
+#include <em-format/e-mail-part-utils.h>
|
||
+
|
||
+#include "e-mail-backend.h"
|
||
+#include "e-mail-browser.h"
|
||
+#include "e-mail-enumtypes.h"
|
||
+#include "e-mail-label-action.h"
|
||
+#include "e-mail-label-dialog.h"
|
||
+#include "e-mail-label-list-store.h"
|
||
+#include "e-mail-notes.h"
|
||
+#include "e-mail-reader-utils.h"
|
||
+#include "e-mail-remote-content-popover.h"
|
||
+#include "e-mail-ui-session.h"
|
||
+#include "e-mail-view.h"
|
||
+#include "em-composer-utils.h"
|
||
+#include "em-event.h"
|
||
+#include "em-folder-selector.h"
|
||
+#include "em-folder-tree.h"
|
||
+#include "em-utils.h"
|
||
+#include "mail-autofilter.h"
|
||
+#include "mail-vfolder-ui.h"
|
||
+#include "message-list.h"
|
||
+
|
||
+#define E_MAIL_READER_GET_PRIVATE(obj) \
|
||
+ ((EMailReaderPrivate *) g_object_get_qdata \
|
||
+ (G_OBJECT (obj), quark_private))
|
||
+
|
||
+#define d(x)
|
||
+
|
||
+typedef struct _EMailReaderClosure EMailReaderClosure;
|
||
+typedef struct _EMailReaderPrivate EMailReaderPrivate;
|
||
+
|
||
+struct _EMailReaderClosure {
|
||
+ EMailReader *reader;
|
||
+ EActivity *activity;
|
||
+ CamelMimeMessage *message;
|
||
+ CamelFolder *folder;
|
||
+ gchar *message_uid;
|
||
+ gboolean selection_is_html;
|
||
+};
|
||
+
|
||
+struct _EMailReaderPrivate {
|
||
+
|
||
+ EMailForwardStyle forward_style;
|
||
+ EMailReplyStyle reply_style;
|
||
+
|
||
+ /* This timer runs when the user selects a single message. */
|
||
+ guint message_selected_timeout_id;
|
||
+
|
||
+ /* This allows message retrieval to be cancelled if another
|
||
+ * message is selected before the retrieval has completed. */
|
||
+ GCancellable *retrieving_message;
|
||
+
|
||
+ /* These flags work to prevent a folder switch from
|
||
+ * automatically marking the message as read. We only want
|
||
+ * that to happen when the -user- selects a message. */
|
||
+ guint folder_was_just_selected : 1;
|
||
+ guint avoid_next_mark_as_seen : 1;
|
||
+ guint did_try_to_open_message : 1;
|
||
+
|
||
+ guint group_by_threads : 1;
|
||
+ guint mark_seen_always : 1;
|
||
+ guint delete_selects_previous : 1;
|
||
+
|
||
+ /* to be able to start the mark_seen timeout only after
|
||
+ * the message is loaded into the EMailDisplay */
|
||
+ gboolean schedule_mark_seen;
|
||
+ guint schedule_mark_seen_interval;
|
||
+
|
||
+ gpointer followup_alert; /* weak pointer to an EAlert */
|
||
+
|
||
+ GSList *ongoing_operations; /* GCancellable * */
|
||
+
|
||
+ guint main_menu_label_merge_id;
|
||
+ guint popup_menu_label_merge_id;
|
||
+};
|
||
+
|
||
+enum {
|
||
+ CHANGED,
|
||
+ COMPOSER_CREATED,
|
||
+ FOLDER_LOADED,
|
||
+ MESSAGE_LOADED,
|
||
+ MESSAGE_SEEN,
|
||
+ SHOW_SEARCH_BAR,
|
||
+ UPDATE_ACTIONS,
|
||
+ LAST_SIGNAL
|
||
+};
|
||
+
|
||
+/* Remembers the previously selected folder when transferring messages. */
|
||
+static gchar *default_xfer_messages_uri;
|
||
+
|
||
+static GQuark quark_private;
|
||
+static guint signals[LAST_SIGNAL];
|
||
+
|
||
+G_DEFINE_INTERFACE (EMailReader, e_mail_reader, G_TYPE_INITIALLY_UNOWNED)
|
||
+
|
||
+static void
|
||
+mail_reader_set_display_formatter_for_message (EMailReader *reader,
|
||
+ EMailDisplay *display,
|
||
+ const gchar *message_uid,
|
||
+ CamelMimeMessage *message,
|
||
+ CamelFolder *folder);
|
||
+
|
||
+static void
|
||
+mail_reader_closure_free (EMailReaderClosure *closure)
|
||
+{
|
||
+ g_clear_object (&closure->reader);
|
||
+ g_clear_object (&closure->activity);
|
||
+ g_clear_object (&closure->folder);
|
||
+ g_clear_object (&closure->message);
|
||
+ g_free (closure->message_uid);
|
||
+
|
||
+ g_slice_free (EMailReaderClosure, closure);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_private_free (EMailReaderPrivate *priv)
|
||
+{
|
||
+ if (priv->message_selected_timeout_id > 0)
|
||
+ g_source_remove (priv->message_selected_timeout_id);
|
||
+
|
||
+ if (priv->retrieving_message != NULL) {
|
||
+ g_cancellable_cancel (priv->retrieving_message);
|
||
+ g_object_unref (priv->retrieving_message);
|
||
+ priv->retrieving_message = NULL;
|
||
+ }
|
||
+
|
||
+ g_slice_free (EMailReaderPrivate, priv);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_add_sender_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EShell *shell;
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+ EShellBackend *shell_backend;
|
||
+ CamelInternetAddress *cia;
|
||
+ CamelMessageInfo *info = NULL;
|
||
+ CamelFolder *folder;
|
||
+ GPtrArray *uids;
|
||
+ const gchar *address;
|
||
+ const gchar *message_uid;
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+ backend = e_mail_reader_get_backend (reader);
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+
|
||
+ uids = e_mail_reader_get_selected_uids (reader);
|
||
+ g_return_if_fail (uids != NULL && uids->len == 1);
|
||
+ message_uid = g_ptr_array_index (uids, 0);
|
||
+
|
||
+ info = camel_folder_get_message_info (folder, message_uid);
|
||
+ if (info == NULL)
|
||
+ goto exit;
|
||
+
|
||
+ address = camel_message_info_get_from (info);
|
||
+ if (address == NULL || *address == '\0')
|
||
+ goto exit;
|
||
+
|
||
+ /* XXX EBookShellBackend should be listening for this
|
||
+ * event. Kind of kludgey, but works for now. */
|
||
+ shell_backend = E_SHELL_BACKEND (backend);
|
||
+ shell = e_shell_backend_get_shell (shell_backend);
|
||
+ e_shell_event (shell, "contact-quick-add-email", (gpointer) address);
|
||
+
|
||
+ /* Remove this address from the photo cache. */
|
||
+ cia = camel_internet_address_new ();
|
||
+ if (camel_address_decode (CAMEL_ADDRESS (cia), address) > 0) {
|
||
+ EPhotoCache *photo_cache;
|
||
+ const gchar *address_only = NULL;
|
||
+
|
||
+ photo_cache = e_mail_ui_session_get_photo_cache (
|
||
+ E_MAIL_UI_SESSION (session));
|
||
+ if (camel_internet_address_get (cia, 0, NULL, &address_only))
|
||
+ e_photo_cache_remove_photo (photo_cache, address_only);
|
||
+ }
|
||
+ g_object_unref (cia);
|
||
+
|
||
+exit:
|
||
+ g_clear_object (&info);
|
||
+ g_ptr_array_unref (uids);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_add_to_address_book_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EShell *shell;
|
||
+ EMailBackend *backend;
|
||
+ EMailDisplay *display;
|
||
+ EMailSession *session;
|
||
+ EShellBackend *shell_backend;
|
||
+ CamelInternetAddress *cia;
|
||
+ EPhotoCache *photo_cache;
|
||
+ EWebView *web_view;
|
||
+ CamelURL *curl;
|
||
+ const gchar *uri;
|
||
+ const gchar *address_only = NULL;
|
||
+ gchar *email;
|
||
+
|
||
+ /* This action is defined in EMailDisplay. */
|
||
+
|
||
+ backend = e_mail_reader_get_backend (reader);
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+
|
||
+ display = e_mail_reader_get_mail_display (reader);
|
||
+ if (display == NULL)
|
||
+ return;
|
||
+
|
||
+ web_view = E_WEB_VIEW (display);
|
||
+ uri = e_web_view_get_selected_uri (web_view);
|
||
+ g_return_if_fail (uri != NULL);
|
||
+
|
||
+ curl = camel_url_new (uri, NULL);
|
||
+ g_return_if_fail (curl != NULL);
|
||
+
|
||
+ if (curl->path == NULL || *curl->path == '\0')
|
||
+ goto exit;
|
||
+
|
||
+ cia = camel_internet_address_new ();
|
||
+ if (camel_address_decode (CAMEL_ADDRESS (cia), curl->path) < 0) {
|
||
+ g_object_unref (cia);
|
||
+ goto exit;
|
||
+ }
|
||
+
|
||
+ /* XXX EBookShellBackend should be listening for this
|
||
+ * event. Kind of kludgey, but works for now. */
|
||
+ shell_backend = E_SHELL_BACKEND (backend);
|
||
+ shell = e_shell_backend_get_shell (shell_backend);
|
||
+ email = camel_address_format (CAMEL_ADDRESS (cia));
|
||
+ e_shell_event (shell, "contact-quick-add-email", email);
|
||
+ g_free (email);
|
||
+
|
||
+ /* Remove this address from the photo cache. */
|
||
+ photo_cache = e_mail_ui_session_get_photo_cache (
|
||
+ E_MAIL_UI_SESSION (session));
|
||
+ if (camel_internet_address_get (cia, 0, NULL, &address_only))
|
||
+ e_photo_cache_remove_photo (photo_cache, address_only);
|
||
+
|
||
+ g_object_unref (cia);
|
||
+
|
||
+exit:
|
||
+ camel_url_free (curl);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_charset_cb (GtkRadioAction *action,
|
||
+ GtkRadioAction *current,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EMailDisplay *display;
|
||
+ EMailFormatter *formatter;
|
||
+
|
||
+ if (action != current)
|
||
+ return;
|
||
+
|
||
+ display = e_mail_reader_get_mail_display (reader);
|
||
+ formatter = e_mail_display_get_formatter (display);
|
||
+
|
||
+ if (formatter != NULL) {
|
||
+ const gchar *charset;
|
||
+
|
||
+ /* Charset for "Default" action will be NULL. */
|
||
+ charset = g_object_get_data (G_OBJECT (action), "charset");
|
||
+ e_mail_formatter_set_charset (formatter, charset);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_check_for_junk_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+ CamelFolder *folder;
|
||
+ GPtrArray *uids;
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+ backend = e_mail_reader_get_backend (reader);
|
||
+ uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
|
||
+
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+
|
||
+ mail_filter_folder (
|
||
+ session, folder, uids,
|
||
+ E_FILTER_SOURCE_JUNKTEST, FALSE);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ g_ptr_array_unref (uids);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_copy_or_move_selected_messages (EMailReader *reader,
|
||
+ gboolean is_move)
|
||
+{
|
||
+ CamelFolder *folder;
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+ EMFolderSelector *selector;
|
||
+ EMFolderTree *folder_tree;
|
||
+ EMFolderTreeModel *model;
|
||
+ GSettings *settings;
|
||
+ GtkWidget *dialog;
|
||
+ GtkWindow *window;
|
||
+ GPtrArray *uids;
|
||
+ const gchar *uri;
|
||
+
|
||
+ backend = e_mail_reader_get_backend (reader);
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+ window = e_mail_reader_get_window (reader);
|
||
+ uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
|
||
+
|
||
+ model = em_folder_tree_model_get_default ();
|
||
+
|
||
+ dialog = em_folder_selector_new (window, model);
|
||
+
|
||
+ gtk_window_set_title (GTK_WINDOW (dialog), is_move ? _("Move to Folder") : _("Copy to Folder"));
|
||
+
|
||
+ selector = EM_FOLDER_SELECTOR (dialog);
|
||
+ em_folder_selector_set_can_create (selector, TRUE);
|
||
+ em_folder_selector_set_default_button_label (selector, is_move ? _("_Move") : _("C_opy"));
|
||
+
|
||
+ folder_tree = em_folder_selector_get_folder_tree (selector);
|
||
+
|
||
+ em_folder_tree_set_excluded (
|
||
+ folder_tree,
|
||
+ EMFT_EXCLUDE_NOSELECT |
|
||
+ EMFT_EXCLUDE_VIRTUAL |
|
||
+ EMFT_EXCLUDE_VTRASH);
|
||
+
|
||
+ settings = e_util_ref_settings ("org.gnome.evolution.mail");
|
||
+
|
||
+ if (!g_settings_get_boolean (settings, "copy-move-to-folder-preserve-expand"))
|
||
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (folder_tree));
|
||
+
|
||
+ g_clear_object (&settings);
|
||
+
|
||
+ em_folder_selector_maybe_collapse_archive_folders (selector);
|
||
+
|
||
+ if (default_xfer_messages_uri != NULL) {
|
||
+ em_folder_tree_set_selected (
|
||
+ folder_tree, default_xfer_messages_uri, FALSE);
|
||
+ } else if (folder) {
|
||
+ gchar *uri = e_mail_folder_uri_from_folder (folder);
|
||
+
|
||
+ if (uri) {
|
||
+ em_folder_tree_set_selected (folder_tree, uri, FALSE);
|
||
+ g_free (uri);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK)
|
||
+ goto exit;
|
||
+
|
||
+ uri = em_folder_selector_get_selected_uri (selector);
|
||
+
|
||
+ g_free (default_xfer_messages_uri);
|
||
+ default_xfer_messages_uri = g_strdup (uri);
|
||
+
|
||
+ if (uri != NULL)
|
||
+ mail_transfer_messages (
|
||
+ session, folder, uids,
|
||
+ is_move, uri, 0, NULL, NULL);
|
||
+
|
||
+exit:
|
||
+ gtk_widget_destroy (dialog);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ g_ptr_array_unref (uids);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_manage_color_flag_on_selection (EMailReader *reader,
|
||
+ const gchar *color)
|
||
+{
|
||
+ CamelFolder *folder;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+
|
||
+ if (folder != NULL) {
|
||
+ GPtrArray *uids;
|
||
+ guint ii;
|
||
+
|
||
+ camel_folder_freeze (folder);
|
||
+
|
||
+ uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
|
||
+
|
||
+ for (ii = 0; ii < uids->len; ii++) {
|
||
+ CamelMessageInfo *info;
|
||
+
|
||
+ info = camel_folder_get_message_info (folder, uids->pdata[ii]);
|
||
+ if (info) {
|
||
+ camel_message_info_set_user_tag (info, "color", color);
|
||
+ g_object_unref (info);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ g_ptr_array_unref (uids);
|
||
+
|
||
+ camel_folder_thaw (folder);
|
||
+
|
||
+ g_object_unref (folder);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_color_assign_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ GtkWidget *dialog;
|
||
+
|
||
+ dialog = gtk_color_chooser_dialog_new (NULL, e_mail_reader_get_window (reader));
|
||
+
|
||
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
|
||
+ GdkRGBA rgba;
|
||
+ gchar *color;
|
||
+
|
||
+ gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (dialog), &rgba);
|
||
+
|
||
+ color = g_strdup_printf ("#%02X%02X%02X",
|
||
+ 0xFF & ((gint) (255 * rgba.red)),
|
||
+ 0xFF & ((gint) (255 * rgba.green)),
|
||
+ 0xFF & ((gint) (255 * rgba.blue)));
|
||
+
|
||
+ if (color) {
|
||
+ mail_reader_manage_color_flag_on_selection (reader, color);
|
||
+
|
||
+ g_free (color);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ gtk_widget_destroy (dialog);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_color_unset_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ mail_reader_manage_color_flag_on_selection (reader, NULL);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_copy_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ mail_reader_copy_or_move_selected_messages (reader, FALSE);
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+mail_reader_replace_vee_folder_with_real (CamelFolder **inout_folder,
|
||
+ const gchar *uid,
|
||
+ gchar **out_real_uid)
|
||
+{
|
||
+ g_return_val_if_fail (inout_folder != NULL, FALSE);
|
||
+ g_return_val_if_fail (CAMEL_IS_FOLDER (*inout_folder), FALSE);
|
||
+ g_return_val_if_fail (uid != NULL, FALSE);
|
||
+ g_return_val_if_fail (out_real_uid != NULL, FALSE);
|
||
+
|
||
+ *out_real_uid = NULL;
|
||
+
|
||
+ if (CAMEL_IS_VEE_FOLDER (*inout_folder)) {
|
||
+ CamelMessageInfo *info;
|
||
+
|
||
+ info = camel_folder_get_message_info (*inout_folder, uid);
|
||
+ if (info) {
|
||
+ CamelFolder *real_folder;
|
||
+
|
||
+ real_folder = camel_vee_folder_get_location (CAMEL_VEE_FOLDER (*inout_folder), CAMEL_VEE_MESSAGE_INFO (info), out_real_uid);
|
||
+
|
||
+ if (real_folder && *out_real_uid) {
|
||
+ g_object_unref (*inout_folder);
|
||
+
|
||
+ *inout_folder = g_object_ref (real_folder);
|
||
+ }
|
||
+
|
||
+ g_object_unref (info);
|
||
+ } else {
|
||
+ g_warn_if_reached ();
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return *out_real_uid != NULL;
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_edit_note_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ CamelFolder *folder;
|
||
+ GPtrArray *uids;
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+ uids = e_mail_reader_get_selected_uids (reader);
|
||
+
|
||
+ if (uids && uids->len == 1) {
|
||
+ gchar *real_uid = NULL;
|
||
+ const gchar *uid = uids->pdata[0];
|
||
+
|
||
+ if (mail_reader_replace_vee_folder_with_real (&folder, uid, &real_uid))
|
||
+ uid = real_uid;
|
||
+
|
||
+ e_mail_notes_edit (e_mail_reader_get_window (reader), folder, uid);
|
||
+
|
||
+ g_free (real_uid);
|
||
+ } else {
|
||
+ g_warn_if_reached ();
|
||
+ }
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ g_ptr_array_unref (uids);
|
||
+}
|
||
+
|
||
+typedef struct {
|
||
+ CamelFolder *folder;
|
||
+ gchar *uid;
|
||
+} DeleteNoteData;
|
||
+
|
||
+static void
|
||
+delete_note_data_free (gpointer ptr)
|
||
+{
|
||
+ DeleteNoteData *dnd = ptr;
|
||
+
|
||
+ if (dnd) {
|
||
+ g_clear_object (&dnd->folder);
|
||
+ g_free (dnd->uid);
|
||
+ g_slice_free (DeleteNoteData, dnd);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_delete_note_thread (EAlertSinkThreadJobData *job_data,
|
||
+ gpointer user_data,
|
||
+ GCancellable *cancellable,
|
||
+ GError **error)
|
||
+{
|
||
+ DeleteNoteData *dnd = user_data;
|
||
+
|
||
+ g_return_if_fail (dnd != NULL);
|
||
+ g_return_if_fail (CAMEL_IS_FOLDER (dnd->folder));
|
||
+ g_return_if_fail (dnd->uid != NULL);
|
||
+
|
||
+ e_mail_notes_remove_sync (dnd->folder, dnd->uid, cancellable, error);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_delete_note_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ CamelFolder *folder;
|
||
+ GPtrArray *uids;
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+ uids = e_mail_reader_get_selected_uids (reader);
|
||
+
|
||
+ if (uids && uids->len == 1) {
|
||
+ DeleteNoteData *dnd;
|
||
+ EAlertSink *alert_sink;
|
||
+ EActivity *activity;
|
||
+ gchar *full_display_name;
|
||
+ gchar *real_uid = NULL;
|
||
+ const gchar *uid = uids->pdata[0];
|
||
+
|
||
+ if (mail_reader_replace_vee_folder_with_real (&folder, uid, &real_uid))
|
||
+ uid = real_uid;
|
||
+
|
||
+ dnd = g_slice_new0 (DeleteNoteData);
|
||
+ dnd->folder = g_object_ref (folder);
|
||
+ dnd->uid = g_strdup (uid);
|
||
+
|
||
+ full_display_name = e_mail_folder_to_full_display_name (folder, NULL);
|
||
+ alert_sink = e_mail_reader_get_alert_sink (reader);
|
||
+
|
||
+ activity = e_alert_sink_submit_thread_job (alert_sink,
|
||
+ _("Deleting message note…"),
|
||
+ "mail:failed-delete-note",
|
||
+ full_display_name ? full_display_name : camel_folder_get_full_name (folder),
|
||
+ mail_delete_note_thread, dnd, delete_note_data_free);
|
||
+
|
||
+ if (activity)
|
||
+ e_shell_backend_add_activity (E_SHELL_BACKEND (e_mail_reader_get_backend (reader)), activity);
|
||
+
|
||
+ g_clear_object (&activity);
|
||
+ g_free (full_display_name);
|
||
+ g_free (real_uid);
|
||
+ } else {
|
||
+ g_warn_if_reached ();
|
||
+ }
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ g_ptr_array_unref (uids);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_delete_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ guint32 mask = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED;
|
||
+ guint32 set = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED;
|
||
+
|
||
+ if (!e_mail_reader_confirm_delete (reader))
|
||
+ return;
|
||
+
|
||
+ /* FIXME Verify all selected messages are deletable.
|
||
+ * But handle it by disabling this action. */
|
||
+
|
||
+ if (e_mail_reader_mark_selected (reader, mask, set) != 0 &&
|
||
+ !e_mail_reader_close_on_delete_or_junk (reader)) {
|
||
+ if (e_mail_reader_get_delete_selects_previous (reader))
|
||
+ e_mail_reader_select_previous_message (reader, FALSE);
|
||
+ else
|
||
+ e_mail_reader_select_next_message (reader, FALSE);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_filter_on_mailing_list_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ e_mail_reader_create_filter_from_selected (reader, AUTO_MLIST);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_filter_on_recipients_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ e_mail_reader_create_filter_from_selected (reader, AUTO_TO);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_filter_on_sender_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ e_mail_reader_create_filter_from_selected (reader, AUTO_FROM);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_filter_on_subject_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ e_mail_reader_create_filter_from_selected (reader, AUTO_SUBJECT);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_filters_apply_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+ CamelFolder *folder;
|
||
+ GPtrArray *uids;
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+ backend = e_mail_reader_get_backend (reader);
|
||
+ uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
|
||
+
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+
|
||
+ mail_filter_folder (
|
||
+ session, folder, uids,
|
||
+ E_FILTER_SOURCE_DEMAND, FALSE);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ g_ptr_array_unref (uids);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_remove_attachments_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ e_mail_reader_remove_attachments (reader);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_remove_duplicates_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ e_mail_reader_remove_duplicates (reader);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_find_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ e_mail_reader_show_search_bar (reader);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_flag_clear_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ CamelFolder *folder;
|
||
+ GtkWindow *window;
|
||
+ GPtrArray *uids;
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+ uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
|
||
+ window = e_mail_reader_get_window (reader);
|
||
+
|
||
+ em_utils_flag_for_followup_clear (window, folder, uids);
|
||
+
|
||
+ e_mail_reader_reload (reader);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ g_ptr_array_unref (uids);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_flag_completed_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ CamelFolder *folder;
|
||
+ GtkWindow *window;
|
||
+ GPtrArray *uids;
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+ uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
|
||
+ window = e_mail_reader_get_window (reader);
|
||
+
|
||
+ em_utils_flag_for_followup_completed (window, folder, uids);
|
||
+
|
||
+ e_mail_reader_reload (reader);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ g_ptr_array_unref (uids);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_flag_for_followup_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ CamelFolder *folder;
|
||
+ GPtrArray *uids;
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+ uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
|
||
+
|
||
+ em_utils_flag_for_followup (reader, folder, uids);
|
||
+
|
||
+ e_mail_reader_reload (reader);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ g_ptr_array_unref (uids);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_forward_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ GtkWindow *window;
|
||
+ GPtrArray *uids;
|
||
+
|
||
+ window = e_mail_reader_get_window (reader);
|
||
+ uids = e_mail_reader_get_selected_uids (reader);
|
||
+ g_return_if_fail (uids != NULL);
|
||
+
|
||
+ if (em_utils_ask_open_many (window, uids->len)) {
|
||
+ CamelFolder *folder;
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+
|
||
+ e_mail_reader_forward_messages (
|
||
+ reader, folder, uids,
|
||
+ e_mail_reader_get_forward_style (reader));
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ }
|
||
+
|
||
+ g_ptr_array_unref (uids);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_forward_attached_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ GtkWindow *window;
|
||
+ GPtrArray *uids;
|
||
+
|
||
+ window = e_mail_reader_get_window (reader);
|
||
+ uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
|
||
+ g_return_if_fail (uids != NULL);
|
||
+
|
||
+ if (em_utils_ask_open_many (window, uids->len)) {
|
||
+ CamelFolder *folder;
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+
|
||
+ e_mail_reader_forward_messages (
|
||
+ reader, folder, uids,
|
||
+ E_MAIL_FORWARD_STYLE_ATTACHED);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ }
|
||
+
|
||
+ g_ptr_array_unref (uids);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_forward_inline_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ GtkWindow *window;
|
||
+ GPtrArray *uids;
|
||
+
|
||
+ window = e_mail_reader_get_window (reader);
|
||
+ uids = e_mail_reader_get_selected_uids (reader);
|
||
+ g_return_if_fail (uids != NULL);
|
||
+
|
||
+ if (em_utils_ask_open_many (window, uids->len)) {
|
||
+ CamelFolder *folder;
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+
|
||
+ e_mail_reader_forward_messages (
|
||
+ reader, folder, uids,
|
||
+ E_MAIL_FORWARD_STYLE_INLINE);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ }
|
||
+
|
||
+ g_ptr_array_unref (uids);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_forward_quoted_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ GtkWindow *window;
|
||
+ GPtrArray *uids;
|
||
+
|
||
+ window = e_mail_reader_get_window (reader);
|
||
+ uids = e_mail_reader_get_selected_uids (reader);
|
||
+ g_return_if_fail (uids != NULL);
|
||
+
|
||
+ if (em_utils_ask_open_many (window, uids->len)) {
|
||
+ CamelFolder *folder;
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+
|
||
+ e_mail_reader_forward_messages (
|
||
+ reader, folder, uids,
|
||
+ E_MAIL_FORWARD_STYLE_QUOTED);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ }
|
||
+
|
||
+ g_ptr_array_unref (uids);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_label_new_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EMailLabelDialog *label_dialog;
|
||
+ EMailLabelListStore *label_store;
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+ GtkTreeModel *model;
|
||
+ GtkTreeIter iter;
|
||
+ GtkWidget *dialog;
|
||
+ GPtrArray *uids;
|
||
+ GdkColor label_color;
|
||
+ const gchar *label_name;
|
||
+ gchar *label_tag;
|
||
+ gint n_children;
|
||
+ guint ii;
|
||
+
|
||
+ dialog = e_mail_label_dialog_new (e_mail_reader_get_window (reader));
|
||
+
|
||
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Add Label"));
|
||
+
|
||
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK)
|
||
+ goto exit;
|
||
+
|
||
+ backend = e_mail_reader_get_backend (reader);
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+ label_store = e_mail_ui_session_get_label_store (
|
||
+ E_MAIL_UI_SESSION (session));
|
||
+
|
||
+ label_dialog = E_MAIL_LABEL_DIALOG (dialog);
|
||
+ label_name = e_mail_label_dialog_get_label_name (label_dialog);
|
||
+ e_mail_label_dialog_get_label_color (label_dialog, &label_color);
|
||
+
|
||
+ e_mail_label_list_store_set (
|
||
+ label_store, NULL, label_name, &label_color);
|
||
+
|
||
+ /* XXX This is awkward. We've added a new label to the list store
|
||
+ * but we don't have the new label's tag nor an iterator to use
|
||
+ * to fetch it. We know the label was appended to the store,
|
||
+ * so we have to dig it out manually. EMailLabelListStore API
|
||
+ * probably needs some rethinking. */
|
||
+ model = GTK_TREE_MODEL (label_store);
|
||
+ n_children = gtk_tree_model_iter_n_children (model, NULL);
|
||
+ g_warn_if_fail (gtk_tree_model_iter_nth_child (model, &iter, NULL, n_children - 1));
|
||
+ label_tag = e_mail_label_list_store_get_tag (label_store, &iter);
|
||
+
|
||
+ uids = e_mail_reader_get_selected_uids (reader);
|
||
+ if (uids) {
|
||
+ CamelFolder *folder;
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+
|
||
+ for (ii = 0; ii < uids->len; ii++) {
|
||
+ camel_folder_set_message_user_flag (
|
||
+ folder, uids->pdata[ii], label_tag, TRUE);
|
||
+ }
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ g_ptr_array_unref (uids);
|
||
+ }
|
||
+
|
||
+ g_free (label_tag);
|
||
+
|
||
+ exit:
|
||
+ gtk_widget_destroy (dialog);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_label_none_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+ EMailLabelListStore *label_store;
|
||
+ CamelFolder *folder;
|
||
+ GtkTreeIter iter;
|
||
+ GPtrArray *uids;
|
||
+ gboolean valid;
|
||
+ guint ii;
|
||
+
|
||
+ uids = e_mail_reader_get_selected_uids (reader);
|
||
+ if (!uids)
|
||
+ return;
|
||
+
|
||
+ backend = e_mail_reader_get_backend (reader);
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+ label_store = e_mail_ui_session_get_label_store (
|
||
+ E_MAIL_UI_SESSION (session));
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+
|
||
+ valid = gtk_tree_model_get_iter_first (
|
||
+ GTK_TREE_MODEL (label_store), &iter);
|
||
+
|
||
+ while (valid) {
|
||
+ gchar *tag;
|
||
+
|
||
+ tag = e_mail_label_list_store_get_tag (label_store, &iter);
|
||
+
|
||
+ for (ii = 0; ii < uids->len; ii++) {
|
||
+ camel_folder_set_message_user_flag (
|
||
+ folder, uids->pdata[ii], tag, FALSE);
|
||
+ camel_folder_set_message_user_tag (
|
||
+ folder, uids->pdata[ii], "label", NULL);
|
||
+ }
|
||
+
|
||
+ g_free (tag);
|
||
+
|
||
+ valid = gtk_tree_model_iter_next (
|
||
+ GTK_TREE_MODEL (label_store), &iter);
|
||
+ }
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ g_ptr_array_unref (uids);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_load_images_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EMailDisplay *display;
|
||
+
|
||
+ display = e_mail_reader_get_mail_display (reader);
|
||
+
|
||
+ e_mail_display_load_images (display);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_mark_important_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ guint32 mask = CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_DELETED;
|
||
+ guint32 set = CAMEL_MESSAGE_FLAGGED;
|
||
+
|
||
+ e_mail_reader_mark_selected (reader, mask, set);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_mark_junk_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ guint32 mask =
|
||
+ CAMEL_MESSAGE_SEEN |
|
||
+ CAMEL_MESSAGE_JUNK |
|
||
+ CAMEL_MESSAGE_NOTJUNK |
|
||
+ CAMEL_MESSAGE_JUNK_LEARN;
|
||
+ guint32 set =
|
||
+ CAMEL_MESSAGE_SEEN |
|
||
+ CAMEL_MESSAGE_JUNK |
|
||
+ CAMEL_MESSAGE_JUNK_LEARN;
|
||
+
|
||
+ if (e_mail_reader_mark_selected (reader, mask, set) != 0 &&
|
||
+ !e_mail_reader_close_on_delete_or_junk (reader)) {
|
||
+ if (e_mail_reader_get_delete_selects_previous (reader))
|
||
+ e_mail_reader_select_previous_message (reader, TRUE);
|
||
+ else
|
||
+ e_mail_reader_select_next_message (reader, TRUE);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_mark_notjunk_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ guint32 mask =
|
||
+ CAMEL_MESSAGE_JUNK |
|
||
+ CAMEL_MESSAGE_NOTJUNK |
|
||
+ CAMEL_MESSAGE_JUNK_LEARN;
|
||
+ guint32 set =
|
||
+ CAMEL_MESSAGE_NOTJUNK |
|
||
+ CAMEL_MESSAGE_JUNK_LEARN;
|
||
+
|
||
+ if (e_mail_reader_mark_selected (reader, mask, set) != 0) {
|
||
+ if (e_mail_reader_get_delete_selects_previous (reader))
|
||
+ e_mail_reader_select_previous_message (reader, TRUE);
|
||
+ else
|
||
+ e_mail_reader_select_next_message (reader, TRUE);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_mark_read_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ guint32 mask = CAMEL_MESSAGE_SEEN;
|
||
+ guint32 set = CAMEL_MESSAGE_SEEN;
|
||
+
|
||
+ e_mail_reader_mark_selected (reader, mask, set);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_mark_unimportant_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ guint32 mask = CAMEL_MESSAGE_FLAGGED;
|
||
+ guint32 set = 0;
|
||
+
|
||
+ e_mail_reader_mark_selected (reader, mask, set);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_mark_ignore_thread_sub_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_SUBSET_SET);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_mark_unignore_thread_sub_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_SUBSET_UNSET);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_mark_ignore_thread_whole_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_WHOLE_SET);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_mark_unignore_thread_whole_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_WHOLE_UNSET);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_mark_unread_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ GtkWidget *message_list;
|
||
+ EMFolderTreeModel *model;
|
||
+ CamelFolder *folder;
|
||
+ guint32 mask = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED;
|
||
+ guint32 set = 0;
|
||
+ guint n_marked;
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ n_marked = e_mail_reader_mark_selected (reader, mask, set);
|
||
+
|
||
+ if (MESSAGE_LIST (message_list)->seen_id != 0) {
|
||
+ g_source_remove (MESSAGE_LIST (message_list)->seen_id);
|
||
+ MESSAGE_LIST (message_list)->seen_id = 0;
|
||
+ }
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+
|
||
+ /* Notify the tree model that the user has marked messages as
|
||
+ * unread so it doesn't mistake the event as new mail arriving. */
|
||
+ model = em_folder_tree_model_get_default ();
|
||
+ em_folder_tree_model_user_marked_unread (model, folder, n_marked);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_message_edit_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EShell *shell;
|
||
+ EMailBackend *backend;
|
||
+ ESourceRegistry *registry;
|
||
+ CamelFolder *folder;
|
||
+ GPtrArray *uids;
|
||
+ gboolean replace;
|
||
+
|
||
+ uids = e_mail_reader_get_selected_uids (reader);
|
||
+ g_return_if_fail (uids != NULL);
|
||
+
|
||
+ backend = e_mail_reader_get_backend (reader);
|
||
+ shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
|
||
+ registry = e_shell_get_registry (shell);
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+ replace = em_utils_folder_is_drafts (registry, folder);
|
||
+ e_mail_reader_edit_messages (reader, folder, uids, replace, replace);
|
||
+ g_clear_object (&folder);
|
||
+
|
||
+ g_ptr_array_unref (uids);
|
||
+}
|
||
+
|
||
+typedef struct _CreateComposerData {
|
||
+ EMailReader *reader;
|
||
+ CamelMimeMessage *message;
|
||
+ CamelFolder *folder;
|
||
+ const gchar *message_uid; /* In the Camel string pool */
|
||
+ gboolean is_redirect;
|
||
+} CreateComposerData;
|
||
+
|
||
+static void
|
||
+mail_reader_new_composer_created_cb (GObject *source_object,
|
||
+ GAsyncResult *result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ CreateComposerData *ccd = user_data;
|
||
+ EMsgComposer *composer;
|
||
+ GError *error = NULL;
|
||
+
|
||
+ g_return_if_fail (ccd != NULL);
|
||
+
|
||
+ composer = e_msg_composer_new_finish (result, &error);
|
||
+ if (error) {
|
||
+ g_warning ("%s: Failed to create msg composer: %s", G_STRFUNC, error->message);
|
||
+ g_clear_error (&error);
|
||
+ } else {
|
||
+ if (ccd->is_redirect)
|
||
+ em_utils_redirect_message (composer, ccd->message);
|
||
+ else
|
||
+ em_utils_compose_new_message_with_selection (composer, ccd->folder, ccd->message_uid);
|
||
+
|
||
+ e_mail_reader_composer_created (ccd->reader, composer, ccd->message);
|
||
+ }
|
||
+
|
||
+ g_clear_object (&ccd->reader);
|
||
+ g_clear_object (&ccd->message);
|
||
+ g_clear_object (&ccd->folder);
|
||
+ camel_pstring_free (ccd->message_uid);
|
||
+ g_slice_free (CreateComposerData, ccd);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_message_new_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EShell *shell;
|
||
+ EMailBackend *backend;
|
||
+ EShellBackend *shell_backend;
|
||
+ CamelFolder *folder;
|
||
+ CreateComposerData *ccd;
|
||
+ GPtrArray *selected_uids = NULL;
|
||
+ const gchar *selected_uid = NULL;
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+ backend = e_mail_reader_get_backend (reader);
|
||
+
|
||
+ selected_uids = e_mail_reader_get_selected_uids (reader);
|
||
+ if (selected_uids && selected_uids->len > 0)
|
||
+ selected_uid = g_ptr_array_index (selected_uids, 0);
|
||
+
|
||
+ if (!selected_uid) {
|
||
+ GtkWidget *message_list;
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+ if (message_list)
|
||
+ selected_uid = MESSAGE_LIST (message_list)->cursor_uid;
|
||
+ }
|
||
+
|
||
+ shell_backend = E_SHELL_BACKEND (backend);
|
||
+ shell = e_shell_backend_get_shell (shell_backend);
|
||
+
|
||
+ ccd = g_slice_new0 (CreateComposerData);
|
||
+ ccd->reader = g_object_ref (reader);
|
||
+ ccd->folder = folder;
|
||
+ ccd->message_uid = camel_pstring_strdup (selected_uid);
|
||
+ ccd->is_redirect = FALSE;
|
||
+
|
||
+ e_msg_composer_new (shell, mail_reader_new_composer_created_cb, ccd);
|
||
+
|
||
+ if (selected_uids)
|
||
+ g_ptr_array_unref (selected_uids);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_message_open_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ e_mail_reader_open_selected_mail (reader);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_archive_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ CamelFolder *folder;
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+ GPtrArray *uids;
|
||
+ gchar *archive_folder;
|
||
+
|
||
+ backend = e_mail_reader_get_backend (reader);
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+
|
||
+ uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
|
||
+ g_return_if_fail (uids != NULL);
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+
|
||
+ if (CAMEL_IS_VEE_FOLDER (folder) && uids->len > 1) {
|
||
+ GHashTable *split_by_folder; /* CamelFolder * ~> GPtrArray { gchar * uids } */
|
||
+ GHashTableIter iter;
|
||
+ gpointer key, value;
|
||
+ guint ii, n_successful = 0, n_failed = 0;
|
||
+
|
||
+ split_by_folder = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, (GDestroyNotify) g_ptr_array_unref);
|
||
+
|
||
+ for (ii = 0; ii < uids->len; ii++) {
|
||
+ const gchar *uid = g_ptr_array_index (uids, ii);
|
||
+ CamelFolder *real_folder = NULL;
|
||
+ gchar *real_message_uid = NULL;
|
||
+
|
||
+ em_utils_get_real_folder_and_message_uid (folder, uid, &real_folder, NULL, &real_message_uid);
|
||
+
|
||
+ if (real_folder && real_message_uid) {
|
||
+ GPtrArray *array;
|
||
+
|
||
+ array = g_hash_table_lookup (split_by_folder, real_folder);
|
||
+
|
||
+ if (array) {
|
||
+ g_object_unref (real_folder);
|
||
+ } else {
|
||
+ array = g_ptr_array_new_with_free_func (g_free);
|
||
+ g_hash_table_insert (split_by_folder, real_folder, array);
|
||
+ }
|
||
+
|
||
+ g_ptr_array_add (array, real_message_uid);
|
||
+ } else {
|
||
+ g_clear_object (&real_folder);
|
||
+ g_free (real_message_uid);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ g_hash_table_iter_init (&iter, split_by_folder);
|
||
+
|
||
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
|
||
+ CamelFolder *real_folder = key;
|
||
+ GPtrArray *real_uids = value;
|
||
+
|
||
+ archive_folder = em_utils_get_archive_folder_uri_from_folder (real_folder, backend, real_uids, TRUE);
|
||
+
|
||
+ if (archive_folder && *archive_folder) {
|
||
+ n_successful++;
|
||
+ mail_transfer_messages (
|
||
+ session, folder, uids,
|
||
+ TRUE, archive_folder, 0, NULL, NULL);
|
||
+ } else {
|
||
+ n_failed++;
|
||
+ }
|
||
+
|
||
+ g_free (archive_folder);
|
||
+ }
|
||
+
|
||
+ g_hash_table_destroy (split_by_folder);
|
||
+
|
||
+ if (n_failed && !n_successful) {
|
||
+ EAlertSink *alert_sink;
|
||
+
|
||
+ alert_sink = e_mail_reader_get_alert_sink (reader);
|
||
+
|
||
+ e_alert_submit (
|
||
+ alert_sink, "mail:no-archive-folder",
|
||
+ NULL);
|
||
+ }
|
||
+ } else {
|
||
+ archive_folder = em_utils_get_archive_folder_uri_from_folder (folder, backend, uids, TRUE);
|
||
+
|
||
+ if (archive_folder && *archive_folder) {
|
||
+ mail_transfer_messages (
|
||
+ session, folder, uids,
|
||
+ TRUE, archive_folder, 0, NULL, NULL);
|
||
+ } else {
|
||
+ EAlertSink *alert_sink;
|
||
+
|
||
+ alert_sink = e_mail_reader_get_alert_sink (reader);
|
||
+
|
||
+ e_alert_submit (
|
||
+ alert_sink, "mail:no-archive-folder",
|
||
+ NULL);
|
||
+ }
|
||
+
|
||
+ g_free (archive_folder);
|
||
+ }
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ g_ptr_array_unref (uids);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_move_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ mail_reader_copy_or_move_selected_messages (reader, TRUE);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_next_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ GtkWidget *message_list;
|
||
+ MessageListSelectDirection direction;
|
||
+ guint32 flags, mask;
|
||
+
|
||
+ direction = MESSAGE_LIST_SELECT_NEXT;
|
||
+ flags = 0;
|
||
+ mask = 0;
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ message_list_select (
|
||
+ MESSAGE_LIST (message_list), direction, flags, mask);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_next_important_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ GtkWidget *message_list;
|
||
+ MessageListSelectDirection direction;
|
||
+ guint32 flags, mask;
|
||
+
|
||
+ direction = MESSAGE_LIST_SELECT_NEXT | MESSAGE_LIST_SELECT_WRAP;
|
||
+ flags = CAMEL_MESSAGE_FLAGGED;
|
||
+ mask = CAMEL_MESSAGE_FLAGGED;
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ message_list_select (
|
||
+ MESSAGE_LIST (message_list), direction, flags, mask);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_next_thread_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ GtkWidget *message_list;
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ message_list_select_next_thread (MESSAGE_LIST (message_list));
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_select_unread (EMailReader *reader,
|
||
+ gboolean move_forward)
|
||
+{
|
||
+ GtkWidget *message_list;
|
||
+ MessageListSelectDirection direction;
|
||
+ guint32 flags, mask;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ direction = (move_forward ? MESSAGE_LIST_SELECT_NEXT : MESSAGE_LIST_SELECT_PREVIOUS) |
|
||
+ MESSAGE_LIST_SELECT_WRAP | MESSAGE_LIST_SELECT_INCLUDE_COLLAPSED;
|
||
+ flags = 0;
|
||
+ mask = CAMEL_MESSAGE_SEEN;
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ if (!message_list_select (MESSAGE_LIST (message_list), direction, flags, mask)) {
|
||
+ GtkWindow *window;
|
||
+
|
||
+ window = e_mail_reader_get_window (reader);
|
||
+ if (E_IS_SHELL_WINDOW (window)) {
|
||
+ EShellWindow *shell_window;
|
||
+ EMFolderTree *folder_tree = NULL;
|
||
+ const gchar *active_view;
|
||
+
|
||
+ shell_window = E_SHELL_WINDOW (window);
|
||
+ active_view = e_shell_window_get_active_view (shell_window);
|
||
+
|
||
+ if (g_strcmp0 (active_view, "mail") == 0) {
|
||
+ EShellView *shell_view;
|
||
+ EShellSidebar *shell_sidebar;
|
||
+
|
||
+ shell_view = e_shell_window_get_shell_view (shell_window, "mail");
|
||
+ shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
|
||
+ g_object_get (shell_sidebar, "folder-tree", &folder_tree, NULL);
|
||
+
|
||
+ if (folder_tree) {
|
||
+ gboolean selected;
|
||
+
|
||
+ if (move_forward)
|
||
+ selected = em_folder_tree_select_next_path (folder_tree, TRUE);
|
||
+ else
|
||
+ selected = em_folder_tree_select_prev_path (folder_tree, TRUE);
|
||
+
|
||
+ if (selected)
|
||
+ message_list_set_regen_selects_unread (MESSAGE_LIST (message_list), TRUE);
|
||
+ }
|
||
+
|
||
+ g_clear_object (&folder_tree);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_next_unread_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ mail_reader_select_unread (reader, TRUE);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_previous_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ GtkWidget *message_list;
|
||
+ MessageListSelectDirection direction;
|
||
+ guint32 flags, mask;
|
||
+
|
||
+ direction = MESSAGE_LIST_SELECT_PREVIOUS;
|
||
+ flags = 0;
|
||
+ mask = 0;
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ message_list_select (
|
||
+ MESSAGE_LIST (message_list), direction, flags, mask);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_previous_important_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ GtkWidget *message_list;
|
||
+ MessageListSelectDirection direction;
|
||
+ guint32 flags, mask;
|
||
+
|
||
+ direction = MESSAGE_LIST_SELECT_PREVIOUS | MESSAGE_LIST_SELECT_WRAP;
|
||
+ flags = CAMEL_MESSAGE_FLAGGED;
|
||
+ mask = CAMEL_MESSAGE_FLAGGED;
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ message_list_select (
|
||
+ MESSAGE_LIST (message_list), direction, flags, mask);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_previous_thread_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ GtkWidget *message_list;
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ message_list_select_prev_thread (MESSAGE_LIST (message_list));
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_previous_unread_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ mail_reader_select_unread (reader, FALSE);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_print_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ GtkPrintOperationAction print_action;
|
||
+
|
||
+ print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG;
|
||
+ e_mail_reader_print (reader, print_action);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_print_preview_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ GtkPrintOperationAction print_action;
|
||
+
|
||
+ print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW;
|
||
+ e_mail_reader_print (reader, print_action);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_redirect_cb (CamelFolder *folder,
|
||
+ GAsyncResult *result,
|
||
+ EMailReaderClosure *closure)
|
||
+{
|
||
+ EShell *shell;
|
||
+ EMailBackend *backend;
|
||
+ EAlertSink *alert_sink;
|
||
+ CamelMimeMessage *message;
|
||
+ CreateComposerData *ccd;
|
||
+ GError *error = NULL;
|
||
+
|
||
+ alert_sink = e_activity_get_alert_sink (closure->activity);
|
||
+
|
||
+ message = camel_folder_get_message_finish (folder, result, &error);
|
||
+
|
||
+ if (e_activity_handle_cancellation (closure->activity, error)) {
|
||
+ g_warn_if_fail (message == NULL);
|
||
+ mail_reader_closure_free (closure);
|
||
+ g_error_free (error);
|
||
+ return;
|
||
+
|
||
+ } else if (error != NULL) {
|
||
+ g_warn_if_fail (message == NULL);
|
||
+ e_alert_submit (
|
||
+ alert_sink, "mail:no-retrieve-message",
|
||
+ error->message, NULL);
|
||
+ mail_reader_closure_free (closure);
|
||
+ g_error_free (error);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
|
||
+
|
||
+ backend = e_mail_reader_get_backend (closure->reader);
|
||
+ shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
|
||
+
|
||
+ ccd = g_slice_new0 (CreateComposerData);
|
||
+ ccd->reader = g_object_ref (closure->reader);
|
||
+ ccd->message = message;
|
||
+ ccd->message_uid = camel_pstring_strdup (closure->message_uid);
|
||
+ ccd->is_redirect = TRUE;
|
||
+
|
||
+ e_msg_composer_new (shell, mail_reader_new_composer_created_cb, ccd);
|
||
+
|
||
+ mail_reader_closure_free (closure);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_redirect_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EActivity *activity;
|
||
+ GCancellable *cancellable;
|
||
+ EMailReaderClosure *closure;
|
||
+ GtkWidget *message_list;
|
||
+ CamelFolder *folder;
|
||
+ const gchar *message_uid;
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+ message_uid = MESSAGE_LIST (message_list)->cursor_uid;
|
||
+ g_return_if_fail (message_uid != NULL);
|
||
+
|
||
+ /* Open the message asynchronously. */
|
||
+
|
||
+ activity = e_mail_reader_new_activity (reader);
|
||
+ cancellable = e_activity_get_cancellable (activity);
|
||
+
|
||
+ closure = g_slice_new0 (EMailReaderClosure);
|
||
+ closure->activity = activity;
|
||
+ closure->reader = g_object_ref (reader);
|
||
+ closure->message_uid = g_strdup (message_uid);
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+
|
||
+ camel_folder_get_message (
|
||
+ folder, message_uid, G_PRIORITY_DEFAULT,
|
||
+ cancellable, (GAsyncReadyCallback)
|
||
+ mail_reader_redirect_cb, closure);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_reply_all_check (CamelFolder *folder,
|
||
+ GAsyncResult *result,
|
||
+ EMailReaderClosure *closure)
|
||
+{
|
||
+ EAlertSink *alert_sink;
|
||
+ CamelMimeMessage *message;
|
||
+ CamelInternetAddress *to, *cc;
|
||
+ gint recip_count = 0;
|
||
+ EMailReplyType type = E_MAIL_REPLY_TO_ALL;
|
||
+ GError *error = NULL;
|
||
+
|
||
+ alert_sink = e_activity_get_alert_sink (closure->activity);
|
||
+
|
||
+ message = camel_folder_get_message_finish (folder, result, &error);
|
||
+
|
||
+ if (e_activity_handle_cancellation (closure->activity, error)) {
|
||
+ g_warn_if_fail (message == NULL);
|
||
+ mail_reader_closure_free (closure);
|
||
+ g_error_free (error);
|
||
+ return;
|
||
+
|
||
+ } else if (error != NULL) {
|
||
+ g_warn_if_fail (message == NULL);
|
||
+ e_alert_submit (
|
||
+ alert_sink, "mail:no-retrieve-message",
|
||
+ error->message, NULL);
|
||
+ mail_reader_closure_free (closure);
|
||
+ g_error_free (error);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
|
||
+
|
||
+ to = camel_mime_message_get_recipients (
|
||
+ message, CAMEL_RECIPIENT_TYPE_TO);
|
||
+ cc = camel_mime_message_get_recipients (
|
||
+ message, CAMEL_RECIPIENT_TYPE_CC);
|
||
+
|
||
+ recip_count = camel_address_length (CAMEL_ADDRESS (to));
|
||
+ recip_count += camel_address_length (CAMEL_ADDRESS (cc));
|
||
+
|
||
+ if (recip_count >= 15) {
|
||
+ GtkWidget *dialog;
|
||
+ GtkWidget *check;
|
||
+ GtkWidget *container;
|
||
+ gint response;
|
||
+
|
||
+ dialog = e_alert_dialog_new_for_args (
|
||
+ e_mail_reader_get_window (closure->reader),
|
||
+ "mail:ask-reply-many-recips", NULL);
|
||
+
|
||
+ container = e_alert_dialog_get_content_area (
|
||
+ E_ALERT_DIALOG (dialog));
|
||
+
|
||
+ /* Check buttons */
|
||
+ check = gtk_check_button_new_with_mnemonic (
|
||
+ _("_Do not ask me again."));
|
||
+ gtk_box_pack_start (
|
||
+ GTK_BOX (container), check, FALSE, FALSE, 0);
|
||
+ gtk_widget_show (check);
|
||
+
|
||
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
|
||
+
|
||
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check))) {
|
||
+ GSettings *settings;
|
||
+ const gchar *key;
|
||
+
|
||
+ settings = e_util_ref_settings ("org.gnome.evolution.mail");
|
||
+
|
||
+ key = "prompt-on-reply-many-recips";
|
||
+ g_settings_set_boolean (settings, key, FALSE);
|
||
+
|
||
+ g_object_unref (settings);
|
||
+ }
|
||
+
|
||
+ gtk_widget_destroy (dialog);
|
||
+
|
||
+ switch (response) {
|
||
+ case GTK_RESPONSE_NO:
|
||
+ type = E_MAIL_REPLY_TO_SENDER;
|
||
+ break;
|
||
+ case GTK_RESPONSE_CANCEL:
|
||
+ case GTK_RESPONSE_DELETE_EVENT:
|
||
+ goto exit;
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ e_mail_reader_reply_to_message (closure->reader, message, type);
|
||
+
|
||
+exit:
|
||
+ g_object_unref (message);
|
||
+
|
||
+ mail_reader_closure_free (closure);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_reply_all_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ GSettings *settings;
|
||
+ const gchar *key;
|
||
+ guint32 state;
|
||
+ gboolean ask;
|
||
+
|
||
+ state = e_mail_reader_check_state (reader);
|
||
+
|
||
+ settings = e_util_ref_settings ("org.gnome.evolution.mail");
|
||
+
|
||
+ key = "prompt-on-reply-many-recips";
|
||
+ ask = g_settings_get_boolean (settings, key);
|
||
+
|
||
+ g_object_unref (settings);
|
||
+
|
||
+ if (ask && !(state & E_MAIL_READER_SELECTION_IS_MAILING_LIST)) {
|
||
+ EActivity *activity;
|
||
+ GCancellable *cancellable;
|
||
+ EMailReaderClosure *closure;
|
||
+ CamelFolder *folder;
|
||
+ GtkWidget *message_list;
|
||
+ const gchar *message_uid;
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+ message_uid = MESSAGE_LIST (message_list)->cursor_uid;
|
||
+ g_return_if_fail (message_uid != NULL);
|
||
+
|
||
+ activity = e_mail_reader_new_activity (reader);
|
||
+ cancellable = e_activity_get_cancellable (activity);
|
||
+
|
||
+ closure = g_slice_new0 (EMailReaderClosure);
|
||
+ closure->activity = activity;
|
||
+ closure->reader = g_object_ref (reader);
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+
|
||
+ camel_folder_get_message (
|
||
+ folder, message_uid, G_PRIORITY_DEFAULT,
|
||
+ cancellable, (GAsyncReadyCallback)
|
||
+ action_mail_reply_all_check, closure);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ e_mail_reader_reply_to_message (reader, NULL, E_MAIL_REPLY_TO_ALL);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_reply_alternative_got_message (GObject *source_object,
|
||
+ GAsyncResult *result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ EMailReaderClosure *closure = user_data;
|
||
+ EAlertSink *alert_sink;
|
||
+ CamelMimeMessage *message;
|
||
+ gboolean is_selection;
|
||
+ CamelFolder *folder = NULL;
|
||
+ const gchar *message_uid = NULL;
|
||
+ EMailPartList *part_list = NULL;
|
||
+ EMailPartValidityFlags validity_pgp_sum = 0;
|
||
+ EMailPartValidityFlags validity_smime_sum = 0;
|
||
+ GError *error = NULL;
|
||
+
|
||
+ alert_sink = e_activity_get_alert_sink (closure->activity);
|
||
+
|
||
+ message = e_mail_reader_utils_get_selection_or_message_finish (E_MAIL_READER (source_object), result,
|
||
+ &is_selection, &folder, &message_uid, &part_list, &validity_pgp_sum, &validity_smime_sum, &error);
|
||
+
|
||
+ if (e_activity_handle_cancellation (closure->activity, error)) {
|
||
+ g_warn_if_fail (message == NULL);
|
||
+ mail_reader_closure_free (closure);
|
||
+ g_error_free (error);
|
||
+ return;
|
||
+
|
||
+ } else if (error != NULL) {
|
||
+ g_warn_if_fail (message == NULL);
|
||
+ e_alert_submit (
|
||
+ alert_sink, "mail:no-retrieve-message",
|
||
+ error->message, NULL);
|
||
+ mail_reader_closure_free (closure);
|
||
+ g_error_free (error);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
|
||
+
|
||
+ g_clear_object (&closure->activity);
|
||
+
|
||
+ em_utils_reply_alternative (e_mail_reader_get_window (closure->reader),
|
||
+ e_shell_backend_get_shell (E_SHELL_BACKEND (e_mail_reader_get_backend (closure->reader))),
|
||
+ alert_sink, message, folder, message_uid,
|
||
+ e_mail_reader_get_reply_style (closure->reader),
|
||
+ is_selection ? NULL : part_list, validity_pgp_sum, validity_smime_sum);
|
||
+
|
||
+ mail_reader_closure_free (closure);
|
||
+ camel_pstring_free (message_uid);
|
||
+ g_clear_object (&message);
|
||
+ g_clear_object (&folder);
|
||
+ g_clear_object (&part_list);
|
||
+ g_clear_error (&error);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_reply_alternative_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EActivity *activity;
|
||
+ GCancellable *cancellable;
|
||
+ EMailReaderClosure *closure;
|
||
+ GtkWidget *message_list;
|
||
+ const gchar *message_uid;
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+ message_uid = MESSAGE_LIST (message_list)->cursor_uid;
|
||
+ g_return_if_fail (message_uid != NULL);
|
||
+
|
||
+ activity = e_mail_reader_new_activity (reader);
|
||
+ cancellable = e_activity_get_cancellable (activity);
|
||
+
|
||
+ closure = g_slice_new0 (EMailReaderClosure);
|
||
+ closure->activity = activity;
|
||
+ closure->reader = g_object_ref (reader);
|
||
+
|
||
+ e_mail_reader_utils_get_selection_or_message (reader, NULL, cancellable,
|
||
+ action_mail_reply_alternative_got_message, closure);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_reply_group_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ GSettings *settings;
|
||
+ gboolean reply_list;
|
||
+ guint32 state;
|
||
+ const gchar *key;
|
||
+
|
||
+ state = e_mail_reader_check_state (reader);
|
||
+
|
||
+ settings = e_util_ref_settings ("org.gnome.evolution.mail");
|
||
+
|
||
+ key = "composer-group-reply-to-list";
|
||
+ reply_list = g_settings_get_boolean (settings, key);
|
||
+
|
||
+ g_object_unref (settings);
|
||
+
|
||
+ if (reply_list && (state & E_MAIL_READER_SELECTION_IS_MAILING_LIST)) {
|
||
+ e_mail_reader_reply_to_message (
|
||
+ reader, NULL, E_MAIL_REPLY_TO_LIST);
|
||
+ } else
|
||
+ action_mail_reply_all_cb (action, reader);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_reply_list_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ e_mail_reader_reply_to_message (reader, NULL, E_MAIL_REPLY_TO_LIST);
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+message_is_list_administrative (CamelMimeMessage *message)
|
||
+{
|
||
+ const gchar *header;
|
||
+
|
||
+ header = camel_medium_get_header (
|
||
+ CAMEL_MEDIUM (message), "X-List-Administrivia");
|
||
+ if (header == NULL)
|
||
+ return FALSE;
|
||
+
|
||
+ while (*header == ' ' || *header == '\t')
|
||
+ header++;
|
||
+
|
||
+ return g_ascii_strncasecmp (header, "yes", 3) == 0;
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_reply_sender_check (CamelFolder *folder,
|
||
+ GAsyncResult *result,
|
||
+ EMailReaderClosure *closure)
|
||
+{
|
||
+ EAlertSink *alert_sink;
|
||
+ CamelMimeMessage *message;
|
||
+ EMailReplyType type = E_MAIL_REPLY_TO_SENDER;
|
||
+ GSettings *settings;
|
||
+ gboolean ask_ignore_list_reply_to;
|
||
+ gboolean ask_list_reply_to;
|
||
+ gboolean munged_list_message;
|
||
+ gboolean active;
|
||
+ const gchar *key;
|
||
+ GError *local_error = NULL;
|
||
+
|
||
+ alert_sink = e_activity_get_alert_sink (closure->activity);
|
||
+
|
||
+ message = camel_folder_get_message_finish (
|
||
+ folder, result, &local_error);
|
||
+
|
||
+ /* Sanity check. */
|
||
+ g_return_if_fail (
|
||
+ ((message != NULL) && (local_error == NULL)) ||
|
||
+ ((message == NULL) && (local_error != NULL)));
|
||
+
|
||
+ if (e_activity_handle_cancellation (closure->activity, local_error)) {
|
||
+ mail_reader_closure_free (closure);
|
||
+ g_error_free (local_error);
|
||
+ return;
|
||
+
|
||
+ } else if (local_error != NULL) {
|
||
+ e_alert_submit (
|
||
+ alert_sink, "mail:no-retrieve-message",
|
||
+ local_error->message, NULL);
|
||
+ mail_reader_closure_free (closure);
|
||
+ g_error_free (local_error);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ settings = e_util_ref_settings ("org.gnome.evolution.mail");
|
||
+
|
||
+ key = "composer-ignore-list-reply-to";
|
||
+ ask_ignore_list_reply_to = g_settings_get_boolean (settings, key);
|
||
+
|
||
+ key = "prompt-on-list-reply-to";
|
||
+ ask_list_reply_to = g_settings_get_boolean (settings, key);
|
||
+
|
||
+ munged_list_message = em_utils_is_munged_list_message (message);
|
||
+
|
||
+ if (message_is_list_administrative (message)) {
|
||
+ /* Do not ask for messages which are list administrative,
|
||
+ * like list confirmation messages. */
|
||
+ } else if (ask_ignore_list_reply_to || !munged_list_message) {
|
||
+ /* Don't do the "Are you sure you want to reply in private?"
|
||
+ * pop-up if it's a Reply-To: munged list message... unless
|
||
+ * we're ignoring munging. */
|
||
+ GtkWidget *dialog;
|
||
+ GtkWidget *check;
|
||
+ GtkWidget *container;
|
||
+ gint response;
|
||
+
|
||
+ dialog = e_alert_dialog_new_for_args (
|
||
+ e_mail_reader_get_window (closure->reader),
|
||
+ "mail:ask-list-private-reply", NULL);
|
||
+
|
||
+ container = e_alert_dialog_get_content_area (
|
||
+ E_ALERT_DIALOG (dialog));
|
||
+
|
||
+ /* Check buttons */
|
||
+ check = gtk_check_button_new_with_mnemonic (
|
||
+ _("_Do not ask me again."));
|
||
+ gtk_box_pack_start (
|
||
+ GTK_BOX (container), check, FALSE, FALSE, 0);
|
||
+ gtk_widget_show (check);
|
||
+
|
||
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
|
||
+
|
||
+ active = gtk_toggle_button_get_active (
|
||
+ GTK_TOGGLE_BUTTON (check));
|
||
+ if (active) {
|
||
+ key = "prompt-on-private-list-reply";
|
||
+ g_settings_set_boolean (settings, key, FALSE);
|
||
+ }
|
||
+
|
||
+ gtk_widget_destroy (dialog);
|
||
+
|
||
+ if (response == GTK_RESPONSE_YES)
|
||
+ type = E_MAIL_REPLY_TO_ALL;
|
||
+ else if (response == GTK_RESPONSE_OK)
|
||
+ type = E_MAIL_REPLY_TO_LIST;
|
||
+ else if (response == GTK_RESPONSE_CANCEL ||
|
||
+ response == GTK_RESPONSE_DELETE_EVENT) {
|
||
+ goto exit;
|
||
+ }
|
||
+
|
||
+ } else if (ask_list_reply_to) {
|
||
+ GtkWidget *dialog;
|
||
+ GtkWidget *container;
|
||
+ GtkWidget *check_again;
|
||
+ GtkWidget *check_always_ignore;
|
||
+ gint response;
|
||
+
|
||
+ dialog = e_alert_dialog_new_for_args (
|
||
+ e_mail_reader_get_window (closure->reader),
|
||
+ "mail:ask-list-honour-reply-to", NULL);
|
||
+
|
||
+ container = e_alert_dialog_get_content_area (
|
||
+ E_ALERT_DIALOG (dialog));
|
||
+
|
||
+ check_again = gtk_check_button_new_with_mnemonic (
|
||
+ _("_Do not ask me again."));
|
||
+ gtk_box_pack_start (
|
||
+ GTK_BOX (container), check_again, FALSE, FALSE, 0);
|
||
+ gtk_widget_show (check_again);
|
||
+
|
||
+ check_always_ignore = gtk_check_button_new_with_mnemonic (
|
||
+ _("_Always ignore Reply-To: for mailing lists."));
|
||
+ gtk_box_pack_start (
|
||
+ GTK_BOX (container), check_always_ignore,
|
||
+ FALSE, FALSE, 0);
|
||
+ gtk_widget_show (check_always_ignore);
|
||
+
|
||
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
|
||
+
|
||
+ active = gtk_toggle_button_get_active (
|
||
+ GTK_TOGGLE_BUTTON (check_again));
|
||
+ if (active) {
|
||
+ key = "prompt-on-list-reply-to";
|
||
+ g_settings_set_boolean (settings, key, FALSE);
|
||
+ }
|
||
+
|
||
+ key = "composer-ignore-list-reply-to";
|
||
+ active = gtk_toggle_button_get_active (
|
||
+ GTK_TOGGLE_BUTTON (check_always_ignore));
|
||
+ g_settings_set_boolean (settings, key, active);
|
||
+
|
||
+ gtk_widget_destroy (dialog);
|
||
+
|
||
+ switch (response) {
|
||
+ case GTK_RESPONSE_NO:
|
||
+ type = E_MAIL_REPLY_TO_FROM;
|
||
+ break;
|
||
+ case GTK_RESPONSE_OK:
|
||
+ type = E_MAIL_REPLY_TO_LIST;
|
||
+ break;
|
||
+ case GTK_RESPONSE_CANCEL:
|
||
+ case GTK_RESPONSE_DELETE_EVENT:
|
||
+ goto exit;
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ e_mail_reader_reply_to_message (closure->reader, message, type);
|
||
+
|
||
+exit:
|
||
+ g_object_unref (settings);
|
||
+ g_object_unref (message);
|
||
+
|
||
+ mail_reader_closure_free (closure);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_reply_sender_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ GSettings *settings;
|
||
+ gboolean ask_list_reply_to;
|
||
+ gboolean ask_private_list_reply;
|
||
+ gboolean ask;
|
||
+ guint32 state;
|
||
+ const gchar *key;
|
||
+
|
||
+ state = e_mail_reader_check_state (reader);
|
||
+
|
||
+ settings = e_util_ref_settings ("org.gnome.evolution.mail");
|
||
+
|
||
+ key = "prompt-on-list-reply-to";
|
||
+ ask_list_reply_to = g_settings_get_boolean (settings, key);
|
||
+
|
||
+ key = "prompt-on-private-list-reply";
|
||
+ ask_private_list_reply = g_settings_get_boolean (settings, key);
|
||
+
|
||
+ g_object_unref (settings);
|
||
+
|
||
+ ask = (ask_private_list_reply || ask_list_reply_to);
|
||
+
|
||
+ if (ask && (state & E_MAIL_READER_SELECTION_IS_MAILING_LIST)) {
|
||
+ EActivity *activity;
|
||
+ GCancellable *cancellable;
|
||
+ EMailReaderClosure *closure;
|
||
+ CamelFolder *folder;
|
||
+ GtkWidget *message_list;
|
||
+ const gchar *message_uid;
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+ message_uid = MESSAGE_LIST (message_list)->cursor_uid;
|
||
+ g_return_if_fail (message_uid != NULL);
|
||
+
|
||
+ activity = e_mail_reader_new_activity (reader);
|
||
+ cancellable = e_activity_get_cancellable (activity);
|
||
+
|
||
+ closure = g_slice_new0 (EMailReaderClosure);
|
||
+ closure->activity = activity;
|
||
+ closure->reader = g_object_ref (reader);
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+
|
||
+ camel_folder_get_message (
|
||
+ folder, message_uid, G_PRIORITY_DEFAULT,
|
||
+ cancellable, (GAsyncReadyCallback)
|
||
+ action_mail_reply_sender_check, closure);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ e_mail_reader_reply_to_message (reader, NULL, E_MAIL_REPLY_TO_SENDER);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_reply_recipient_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ e_mail_reader_reply_to_message (reader, NULL, E_MAIL_REPLY_TO_RECIPIENT);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_save_as_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ e_mail_reader_save_messages (reader);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_search_folder_from_mailing_list_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ e_mail_reader_create_vfolder_from_selected (reader, AUTO_MLIST);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_search_folder_from_recipients_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ e_mail_reader_create_vfolder_from_selected (reader, AUTO_TO);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_search_folder_from_sender_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ e_mail_reader_create_vfolder_from_selected (reader, AUTO_FROM);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_search_folder_from_subject_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ e_mail_reader_create_vfolder_from_selected (reader, AUTO_SUBJECT);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_show_all_headers_cb (GtkToggleAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EMailDisplay *display;
|
||
+ EMailFormatterMode mode;
|
||
+
|
||
+ display = e_mail_reader_get_mail_display (reader);
|
||
+
|
||
+ /* Ignore action when viewing message source. */
|
||
+ mode = e_mail_display_get_mode (display);
|
||
+ if (mode == E_MAIL_FORMATTER_MODE_SOURCE)
|
||
+ return;
|
||
+ if (mode == E_MAIL_FORMATTER_MODE_RAW)
|
||
+ return;
|
||
+
|
||
+ if (gtk_toggle_action_get_active (action))
|
||
+ mode = E_MAIL_FORMATTER_MODE_ALL_HEADERS;
|
||
+ else
|
||
+ mode = E_MAIL_FORMATTER_MODE_NORMAL;
|
||
+
|
||
+ e_mail_display_set_mode (display, mode);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_source_retrieved (GObject *source_object,
|
||
+ GAsyncResult *result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ EMailReaderClosure *closure;
|
||
+ CamelMimeMessage *message;
|
||
+ EMailDisplay *display;
|
||
+ GError *error = NULL;
|
||
+
|
||
+ closure = (EMailReaderClosure *) user_data;
|
||
+ display = e_mail_reader_get_mail_display (closure->reader);
|
||
+
|
||
+ message = camel_folder_get_message_finish (
|
||
+ CAMEL_FOLDER (source_object), result, &error);
|
||
+
|
||
+ /* Sanity check. */
|
||
+ g_return_if_fail (
|
||
+ ((message != NULL) && (error == NULL)) ||
|
||
+ ((message == NULL) && (error != NULL)));
|
||
+
|
||
+ if (message != NULL) {
|
||
+ mail_reader_set_display_formatter_for_message (
|
||
+ closure->reader, display,
|
||
+ closure->message_uid, message,
|
||
+ CAMEL_FOLDER (source_object));
|
||
+ g_object_unref (message);
|
||
+ } else if (error) {
|
||
+ if (display) {
|
||
+ gchar *status;
|
||
+
|
||
+ status = g_strdup_printf (
|
||
+ "%s<br>%s",
|
||
+ _("Failed to retrieve message:"),
|
||
+ error->message);
|
||
+ e_mail_display_set_status (display, status);
|
||
+ g_free (status);
|
||
+ }
|
||
+
|
||
+ g_error_free (error);
|
||
+ }
|
||
+
|
||
+ e_activity_set_state (closure->activity, E_ACTIVITY_COMPLETED);
|
||
+
|
||
+ mail_reader_closure_free (closure);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_show_source_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EMailDisplay *display;
|
||
+ EMailBackend *backend;
|
||
+ GtkWidget *browser;
|
||
+ CamelFolder *folder;
|
||
+ GPtrArray *uids;
|
||
+ const gchar *message_uid;
|
||
+ gchar *string;
|
||
+ EActivity *activity;
|
||
+ GCancellable *cancellable;
|
||
+ EMailReaderClosure *closure;
|
||
+ MessageList *ml;
|
||
+
|
||
+ backend = e_mail_reader_get_backend (reader);
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+ uids = e_mail_reader_get_selected_uids (reader);
|
||
+ g_return_if_fail (uids != NULL && uids->len == 1);
|
||
+ message_uid = g_ptr_array_index (uids, 0);
|
||
+
|
||
+ if (!E_IS_MAIL_BROWSER (e_mail_reader_get_window (reader))) {
|
||
+ EMailBrowser *mail_browser;
|
||
+
|
||
+ mail_browser = em_utils_find_message_window (E_MAIL_FORMATTER_MODE_SOURCE, folder, message_uid);
|
||
+
|
||
+ if (mail_browser) {
|
||
+ gtk_window_present (GTK_WINDOW (mail_browser));
|
||
+ g_ptr_array_unref (uids);
|
||
+ g_clear_object (&folder);
|
||
+ return;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ browser = e_mail_browser_new (backend, E_MAIL_FORMATTER_MODE_SOURCE);
|
||
+ ml = MESSAGE_LIST (e_mail_reader_get_message_list (E_MAIL_READER (browser)));
|
||
+
|
||
+ message_list_freeze (ml);
|
||
+ e_mail_reader_set_folder (E_MAIL_READER (browser), folder);
|
||
+ e_mail_reader_set_message (E_MAIL_READER (browser), message_uid);
|
||
+ message_list_thaw (ml);
|
||
+
|
||
+ display = e_mail_reader_get_mail_display (E_MAIL_READER (browser));
|
||
+
|
||
+ string = g_strdup_printf (_("Retrieving message “%s”"), message_uid);
|
||
+ e_mail_display_set_part_list (display, NULL);
|
||
+ e_mail_display_set_status (display, string);
|
||
+ gtk_widget_show (browser);
|
||
+
|
||
+ activity = e_mail_reader_new_activity (E_MAIL_READER (browser));
|
||
+ e_activity_set_text (activity, string);
|
||
+ cancellable = e_activity_get_cancellable (activity);
|
||
+ g_free (string);
|
||
+
|
||
+ closure = g_slice_new0 (EMailReaderClosure);
|
||
+ closure->reader = E_MAIL_READER (g_object_ref (browser));
|
||
+ closure->activity = g_object_ref (activity);
|
||
+ closure->message_uid = g_strdup (message_uid);
|
||
+
|
||
+ camel_folder_get_message (
|
||
+ folder, message_uid, G_PRIORITY_DEFAULT,
|
||
+ cancellable, mail_source_retrieved, closure);
|
||
+
|
||
+ g_object_unref (activity);
|
||
+
|
||
+ g_ptr_array_unref (uids);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_toggle_important_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ CamelFolder *folder;
|
||
+ GPtrArray *uids;
|
||
+ guint ii;
|
||
+
|
||
+ uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
|
||
+ if (!uids)
|
||
+ return;
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+
|
||
+ camel_folder_freeze (folder);
|
||
+
|
||
+ for (ii = 0; ii < uids->len; ii++) {
|
||
+ guint32 flags;
|
||
+
|
||
+ flags = camel_folder_get_message_flags (
|
||
+ folder, uids->pdata[ii]);
|
||
+ flags ^= CAMEL_MESSAGE_FLAGGED;
|
||
+ if (flags & CAMEL_MESSAGE_FLAGGED)
|
||
+ flags &= ~CAMEL_MESSAGE_DELETED;
|
||
+
|
||
+ camel_folder_set_message_flags (
|
||
+ folder, uids->pdata[ii], CAMEL_MESSAGE_FLAGGED |
|
||
+ CAMEL_MESSAGE_DELETED, flags);
|
||
+ }
|
||
+
|
||
+ camel_folder_thaw (folder);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ g_ptr_array_unref (uids);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_undelete_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ guint32 mask = CAMEL_MESSAGE_DELETED;
|
||
+ guint32 set = 0;
|
||
+
|
||
+ e_mail_reader_mark_selected (reader, mask, set);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_zoom_100_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EMailDisplay *display;
|
||
+
|
||
+ display = e_mail_reader_get_mail_display (reader);
|
||
+
|
||
+ e_web_view_zoom_100 (E_WEB_VIEW (display));
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_zoom_in_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EMailDisplay *display;
|
||
+
|
||
+ display = e_mail_reader_get_mail_display (reader);
|
||
+
|
||
+ e_web_view_zoom_in (E_WEB_VIEW (display));
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_zoom_out_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EMailDisplay *display;
|
||
+
|
||
+ display = e_mail_reader_get_mail_display (reader);
|
||
+
|
||
+ e_web_view_zoom_out (E_WEB_VIEW (display));
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_search_web_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EMailDisplay *display;
|
||
+ GtkAction *wv_action;
|
||
+
|
||
+ display = e_mail_reader_get_mail_display (reader);
|
||
+ wv_action = e_web_view_get_action (E_WEB_VIEW (display), "search-web");
|
||
+
|
||
+ gtk_action_activate (wv_action);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_search_folder_recipient_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+ EWebView *web_view;
|
||
+ CamelURL *curl;
|
||
+ const gchar *uri;
|
||
+
|
||
+ /* This action is defined in EMailDisplay. */
|
||
+
|
||
+ web_view = E_WEB_VIEW (e_mail_reader_get_mail_display (reader));
|
||
+
|
||
+ uri = e_web_view_get_selected_uri (web_view);
|
||
+ g_return_if_fail (uri != NULL);
|
||
+
|
||
+ curl = camel_url_new (uri, NULL);
|
||
+ g_return_if_fail (curl != NULL);
|
||
+
|
||
+ backend = e_mail_reader_get_backend (reader);
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+
|
||
+ if (curl->path != NULL && *curl->path != '\0') {
|
||
+ CamelFolder *folder;
|
||
+ CamelInternetAddress *inet_addr;
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+
|
||
+ inet_addr = camel_internet_address_new ();
|
||
+ camel_address_decode (CAMEL_ADDRESS (inet_addr), curl->path);
|
||
+ vfolder_gui_add_from_address (
|
||
+ session, inet_addr, AUTO_TO, folder);
|
||
+ g_object_unref (inet_addr);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ }
|
||
+
|
||
+ camel_url_free (curl);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_search_folder_sender_cb (GtkAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+ EWebView *web_view;
|
||
+ CamelURL *curl;
|
||
+ const gchar *uri;
|
||
+
|
||
+ /* This action is defined in EMailDisplay. */
|
||
+
|
||
+ web_view = E_WEB_VIEW (e_mail_reader_get_mail_display (reader));
|
||
+
|
||
+ uri = e_web_view_get_selected_uri (web_view);
|
||
+ g_return_if_fail (uri != NULL);
|
||
+
|
||
+ curl = camel_url_new (uri, NULL);
|
||
+ g_return_if_fail (curl != NULL);
|
||
+
|
||
+ backend = e_mail_reader_get_backend (reader);
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+
|
||
+ if (curl->path != NULL && *curl->path != '\0') {
|
||
+ CamelFolder *folder;
|
||
+ CamelInternetAddress *inet_addr;
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+
|
||
+ inet_addr = camel_internet_address_new ();
|
||
+ camel_address_decode (CAMEL_ADDRESS (inet_addr), curl->path);
|
||
+ vfolder_gui_add_from_address (
|
||
+ session, inet_addr, AUTO_FROM, folder);
|
||
+ g_object_unref (inet_addr);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ }
|
||
+
|
||
+ camel_url_free (curl);
|
||
+}
|
||
+
|
||
+static GtkActionEntry mail_reader_entries[] = {
|
||
+
|
||
+ { "mail-add-sender",
|
||
+ NULL,
|
||
+ N_("A_dd Sender to Address Book"),
|
||
+ NULL,
|
||
+ N_("Add sender to address book"),
|
||
+ G_CALLBACK (action_mail_add_sender_cb) },
|
||
+
|
||
+ { "mail-archive",
|
||
+ "mail-archive",
|
||
+ N_("_Archive…"),
|
||
+ "<Alt><Control>a",
|
||
+ N_("Move selected messages to the Archive folder for the account"),
|
||
+ G_CALLBACK (action_mail_archive_cb) },
|
||
+
|
||
+ { "mail-check-for-junk",
|
||
+ "mail-mark-junk",
|
||
+ N_("Check for _Junk"),
|
||
+ "<Control><Alt>j",
|
||
+ N_("Filter the selected messages for junk status"),
|
||
+ G_CALLBACK (action_mail_check_for_junk_cb) },
|
||
+
|
||
+ { "mail-color-assign",
|
||
+ NULL,
|
||
+ N_("Assign C_olor…"),
|
||
+ NULL,
|
||
+ N_("Assign color for the selected messages"),
|
||
+ G_CALLBACK (action_mail_color_assign_cb) },
|
||
+
|
||
+ { "mail-color-unset",
|
||
+ NULL,
|
||
+ N_("Unse_t Color"),
|
||
+ NULL,
|
||
+ N_("Unset color for the selected messages"),
|
||
+ G_CALLBACK (action_mail_color_unset_cb) },
|
||
+
|
||
+ { "mail-copy",
|
||
+ "mail-copy",
|
||
+ N_("_Copy to Folder…"),
|
||
+ "<Shift><Control>y",
|
||
+ N_("Copy selected messages to another folder"),
|
||
+ G_CALLBACK (action_mail_copy_cb) },
|
||
+
|
||
+ { "mail-delete",
|
||
+ "user-trash",
|
||
+ N_("_Delete Message"),
|
||
+ "<Control>d",
|
||
+ N_("Mark the selected messages for deletion"),
|
||
+ G_CALLBACK (action_mail_delete_cb) },
|
||
+
|
||
+ { "mail-add-note",
|
||
+ "evolution-memos",
|
||
+ N_("_Add note…"),
|
||
+ NULL,
|
||
+ N_("Add a note for the selected message"),
|
||
+ G_CALLBACK (action_mail_edit_note_cb) },
|
||
+
|
||
+ { "mail-delete-note",
|
||
+ NULL,
|
||
+ N_("Delete no_te"),
|
||
+ NULL,
|
||
+ N_("Delete the note for the selected message"),
|
||
+ G_CALLBACK (action_mail_delete_note_cb) },
|
||
+
|
||
+ { "mail-edit-note",
|
||
+ "evolution-memos",
|
||
+ N_("_Edit note…"),
|
||
+ NULL,
|
||
+ N_("Edit a note for the selected message"),
|
||
+ G_CALLBACK (action_mail_edit_note_cb) },
|
||
+
|
||
+ { "mail-filter-rule-for-mailing-list",
|
||
+ NULL,
|
||
+ N_("Create a Filter Rule for Mailing _List…"),
|
||
+ NULL,
|
||
+ N_("Create a rule to filter messages to this mailing list"),
|
||
+ G_CALLBACK (action_mail_filter_on_mailing_list_cb) },
|
||
+
|
||
+ { "mail-filter-rule-for-recipients",
|
||
+ NULL,
|
||
+ N_("Create a Filter Rule for _Recipients…"),
|
||
+ NULL,
|
||
+ N_("Create a rule to filter messages to these recipients"),
|
||
+ G_CALLBACK (action_mail_filter_on_recipients_cb) },
|
||
+
|
||
+ { "mail-filter-rule-for-sender",
|
||
+ NULL,
|
||
+ N_("Create a Filter Rule for Se_nder…"),
|
||
+ NULL,
|
||
+ N_("Create a rule to filter messages from this sender"),
|
||
+ G_CALLBACK (action_mail_filter_on_sender_cb) },
|
||
+
|
||
+ { "mail-filter-rule-for-subject",
|
||
+ NULL,
|
||
+ N_("Create a Filter Rule for _Subject…"),
|
||
+ NULL,
|
||
+ N_("Create a rule to filter messages with this subject"),
|
||
+ G_CALLBACK (action_mail_filter_on_subject_cb) },
|
||
+
|
||
+ { "mail-filters-apply",
|
||
+ "stock_mail-filters-apply",
|
||
+ N_("A_pply Filters"),
|
||
+ "<Control>y",
|
||
+ N_("Apply filter rules to the selected messages"),
|
||
+ G_CALLBACK (action_mail_filters_apply_cb) },
|
||
+
|
||
+ { "mail-find",
|
||
+ "edit-find",
|
||
+ N_("_Find in Message…"),
|
||
+ "<Shift><Control>f",
|
||
+ N_("Search for text in the body of the displayed message"),
|
||
+ G_CALLBACK (action_mail_find_cb) },
|
||
+
|
||
+ { "mail-flag-clear",
|
||
+ NULL,
|
||
+ N_("_Clear Flag"),
|
||
+ NULL,
|
||
+ N_("Remove the follow-up flag from the selected messages"),
|
||
+ G_CALLBACK (action_mail_flag_clear_cb) },
|
||
+
|
||
+ { "mail-flag-completed",
|
||
+ NULL,
|
||
+ N_("_Flag Completed"),
|
||
+ NULL,
|
||
+ N_("Set the follow-up flag to completed on the selected messages"),
|
||
+ G_CALLBACK (action_mail_flag_completed_cb) },
|
||
+
|
||
+ { "mail-flag-for-followup",
|
||
+ "stock_mail-flag-for-followup",
|
||
+ N_("Follow _Up…"),
|
||
+ "<Shift><Control>g",
|
||
+ N_("Flag the selected messages for follow-up"),
|
||
+ G_CALLBACK (action_mail_flag_for_followup_cb) },
|
||
+
|
||
+ { "mail-forward",
|
||
+ "mail-forward",
|
||
+ N_("_Forward"),
|
||
+ "<Control>f",
|
||
+ N_("Forward the selected message to someone"),
|
||
+ G_CALLBACK (action_mail_forward_cb) },
|
||
+
|
||
+ { "mail-forward-attached",
|
||
+ NULL,
|
||
+ N_("_Attached"),
|
||
+ NULL,
|
||
+ N_("Forward the selected message to someone as an attachment"),
|
||
+ G_CALLBACK (action_mail_forward_attached_cb) },
|
||
+
|
||
+ { "mail-forward-attached-full",
|
||
+ NULL,
|
||
+ N_("Forward As _Attached"),
|
||
+ NULL,
|
||
+ N_("Forward the selected message to someone as an attachment"),
|
||
+ G_CALLBACK (action_mail_forward_attached_cb) },
|
||
+
|
||
+ { "mail-forward-inline",
|
||
+ NULL,
|
||
+ N_("_Inline"),
|
||
+ NULL,
|
||
+ N_("Forward the selected message in the body of a new message"),
|
||
+ G_CALLBACK (action_mail_forward_inline_cb) },
|
||
+
|
||
+ { "mail-forward-inline-full",
|
||
+ NULL,
|
||
+ N_("Forward As _Inline"),
|
||
+ NULL,
|
||
+ N_("Forward the selected message in the body of a new message"),
|
||
+ G_CALLBACK (action_mail_forward_inline_cb) },
|
||
+
|
||
+ { "mail-forward-quoted",
|
||
+ NULL,
|
||
+ N_("_Quoted"),
|
||
+ NULL,
|
||
+ N_("Forward the selected message quoted like a reply"),
|
||
+ G_CALLBACK (action_mail_forward_quoted_cb) },
|
||
+
|
||
+ { "mail-forward-quoted-full",
|
||
+ NULL,
|
||
+ N_("Forward As _Quoted"),
|
||
+ NULL,
|
||
+ N_("Forward the selected message quoted like a reply"),
|
||
+ G_CALLBACK (action_mail_forward_quoted_cb) },
|
||
+
|
||
+ { "mail-label-new",
|
||
+ NULL,
|
||
+ N_("_New Label"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ G_CALLBACK (action_mail_label_new_cb) },
|
||
+
|
||
+ { "mail-label-none",
|
||
+ NULL,
|
||
+ /* Translators: "None" is used in the message label context menu.
|
||
+ * It removes all labels from the selected messages. */
|
||
+ N_("N_one"),
|
||
+ "0",
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ G_CALLBACK (action_mail_label_none_cb) },
|
||
+
|
||
+ { "mail-load-images",
|
||
+ "image-x-generic",
|
||
+ N_("_Load Images"),
|
||
+ "<Control>i",
|
||
+ N_("Force images in HTML mail to be loaded"),
|
||
+ G_CALLBACK (action_mail_load_images_cb) },
|
||
+
|
||
+ { "mail-mark-ignore-thread-sub",
|
||
+ NULL,
|
||
+ N_("_Ignore Subthread"),
|
||
+ NULL,
|
||
+ N_("Mark new mails in a subthread as read automatically"),
|
||
+ G_CALLBACK (action_mail_mark_ignore_thread_sub_cb) },
|
||
+
|
||
+ { "mail-mark-ignore-thread-whole",
|
||
+ NULL,
|
||
+ N_("_Ignore Thread"),
|
||
+ NULL,
|
||
+ N_("Mark new mails in this thread as read automatically"),
|
||
+ G_CALLBACK (action_mail_mark_ignore_thread_whole_cb) },
|
||
+
|
||
+ { "mail-mark-important",
|
||
+ "mail-mark-important",
|
||
+ N_("_Important"),
|
||
+ NULL,
|
||
+ N_("Mark the selected messages as important"),
|
||
+ G_CALLBACK (action_mail_mark_important_cb) },
|
||
+
|
||
+ { "mail-mark-junk",
|
||
+ "mail-mark-junk",
|
||
+ N_("_Junk"),
|
||
+ "<Control>j",
|
||
+ N_("Mark the selected messages as junk"),
|
||
+ G_CALLBACK (action_mail_mark_junk_cb) },
|
||
+
|
||
+ { "mail-mark-notjunk",
|
||
+ "mail-mark-notjunk",
|
||
+ N_("_Not Junk"),
|
||
+ "<Shift><Control>j",
|
||
+ N_("Mark the selected messages as not being junk"),
|
||
+ G_CALLBACK (action_mail_mark_notjunk_cb) },
|
||
+
|
||
+ { "mail-mark-read",
|
||
+ "mail-mark-read",
|
||
+ N_("_Read"),
|
||
+ "<Control>k",
|
||
+ N_("Mark the selected messages as having been read"),
|
||
+ G_CALLBACK (action_mail_mark_read_cb) },
|
||
+
|
||
+ { "mail-mark-unignore-thread-sub",
|
||
+ NULL,
|
||
+ N_("Do not _Ignore Subthread"),
|
||
+ NULL,
|
||
+ N_("Do not mark new mails in a subthread as read automatically"),
|
||
+ G_CALLBACK (action_mail_mark_unignore_thread_sub_cb) },
|
||
+
|
||
+ { "mail-mark-unignore-thread-whole",
|
||
+ NULL,
|
||
+ N_("Do not _Ignore Thread"),
|
||
+ NULL,
|
||
+ N_("Do not mark new mails in this thread as read automatically"),
|
||
+ G_CALLBACK (action_mail_mark_unignore_thread_whole_cb) },
|
||
+
|
||
+ { "mail-mark-unimportant",
|
||
+ NULL,
|
||
+ N_("Uni_mportant"),
|
||
+ NULL,
|
||
+ N_("Mark the selected messages as unimportant"),
|
||
+ G_CALLBACK (action_mail_mark_unimportant_cb) },
|
||
+
|
||
+ { "mail-mark-unread",
|
||
+ "mail-mark-unread",
|
||
+ N_("_Unread"),
|
||
+ "<Shift><Control>k",
|
||
+ N_("Mark the selected messages as not having been read"),
|
||
+ G_CALLBACK (action_mail_mark_unread_cb) },
|
||
+
|
||
+ { "mail-message-edit",
|
||
+ NULL,
|
||
+ N_("_Edit as New Message…"),
|
||
+ NULL,
|
||
+ N_("Open the selected messages in the composer for editing"),
|
||
+ G_CALLBACK (action_mail_message_edit_cb) },
|
||
+
|
||
+ { "mail-message-new",
|
||
+ "mail-message-new",
|
||
+ N_("Compose _New Message"),
|
||
+ "<Shift><Control>m",
|
||
+ N_("Open a window for composing a mail message"),
|
||
+ G_CALLBACK (action_mail_message_new_cb) },
|
||
+
|
||
+ { "mail-message-open",
|
||
+ NULL,
|
||
+ N_("_Open in New Window"),
|
||
+ "<Control>o",
|
||
+ N_("Open the selected messages in a new window"),
|
||
+ G_CALLBACK (action_mail_message_open_cb) },
|
||
+
|
||
+ { "mail-move",
|
||
+ "mail-move",
|
||
+ N_("_Move to Folder…"),
|
||
+ "<Shift><Control>v",
|
||
+ N_("Move selected messages to another folder"),
|
||
+ G_CALLBACK (action_mail_move_cb) },
|
||
+
|
||
+ { "mail-next",
|
||
+ "go-next",
|
||
+ N_("_Next Message"),
|
||
+ "<Control>Page_Down",
|
||
+ N_("Display the next message"),
|
||
+ G_CALLBACK (action_mail_next_cb) },
|
||
+
|
||
+ { "mail-next-important",
|
||
+ NULL,
|
||
+ N_("Next _Important Message"),
|
||
+ NULL,
|
||
+ N_("Display the next important message"),
|
||
+ G_CALLBACK (action_mail_next_important_cb) },
|
||
+
|
||
+ { "mail-next-thread",
|
||
+ NULL,
|
||
+ N_("Next _Thread"),
|
||
+ NULL,
|
||
+ N_("Display the next thread"),
|
||
+ G_CALLBACK (action_mail_next_thread_cb) },
|
||
+
|
||
+ { "mail-next-unread",
|
||
+ "go-jump",
|
||
+ N_("Next _Unread Message"),
|
||
+ "<Control>bracketright",
|
||
+ N_("Display the next unread message"),
|
||
+ G_CALLBACK (action_mail_next_unread_cb) },
|
||
+
|
||
+ { "mail-previous",
|
||
+ "go-previous",
|
||
+ N_("_Previous Message"),
|
||
+ "<Control>Page_Up",
|
||
+ N_("Display the previous message"),
|
||
+ G_CALLBACK (action_mail_previous_cb) },
|
||
+
|
||
+ { "mail-previous-important",
|
||
+ NULL,
|
||
+ N_("Pr_evious Important Message"),
|
||
+ NULL,
|
||
+ N_("Display the previous important message"),
|
||
+ G_CALLBACK (action_mail_previous_important_cb) },
|
||
+
|
||
+ { "mail-previous-thread",
|
||
+ NULL,
|
||
+ N_("Previous T_hread"),
|
||
+ NULL,
|
||
+ N_("Display the previous thread"),
|
||
+ G_CALLBACK (action_mail_previous_thread_cb) },
|
||
+
|
||
+ { "mail-previous-unread",
|
||
+ NULL,
|
||
+ N_("P_revious Unread Message"),
|
||
+ "<Control>bracketleft",
|
||
+ N_("Display the previous unread message"),
|
||
+ G_CALLBACK (action_mail_previous_unread_cb) },
|
||
+
|
||
+ { "mail-print",
|
||
+ "document-print",
|
||
+ N_("_Print…"),
|
||
+ "<Control>p",
|
||
+ N_("Print this message"),
|
||
+ G_CALLBACK (action_mail_print_cb) },
|
||
+
|
||
+ { "mail-print-preview",
|
||
+ "document-print-preview",
|
||
+ N_("Pre_view…"),
|
||
+ NULL,
|
||
+ N_("Preview the message to be printed"),
|
||
+ G_CALLBACK (action_mail_print_preview_cb) },
|
||
+
|
||
+ { "mail-redirect",
|
||
+ NULL,
|
||
+ N_("Re_direct"),
|
||
+ NULL,
|
||
+ N_("Redirect (bounce) the selected message to someone"),
|
||
+ G_CALLBACK (action_mail_redirect_cb) },
|
||
+
|
||
+ { "mail-remove-attachments",
|
||
+ "edit-delete",
|
||
+ N_("Remo_ve Attachments"),
|
||
+ NULL,
|
||
+ N_("Remove attachments"),
|
||
+ G_CALLBACK (action_mail_remove_attachments_cb) },
|
||
+
|
||
+ { "mail-remove-duplicates",
|
||
+ NULL,
|
||
+ N_("Remove Du_plicate Messages"),
|
||
+ NULL,
|
||
+ N_("Checks selected messages for duplicates"),
|
||
+ G_CALLBACK (action_mail_remove_duplicates_cb) },
|
||
+
|
||
+ { "mail-reply-all",
|
||
+ NULL,
|
||
+ N_("Reply to _All"),
|
||
+ "<Shift><Control>r",
|
||
+ N_("Compose a reply to all the recipients of the selected message"),
|
||
+ G_CALLBACK (action_mail_reply_all_cb) },
|
||
+
|
||
+ { "mail-reply-alternative",
|
||
+ NULL,
|
||
+ N_("Al_ternative Reply…"),
|
||
+ "<Alt><Control>r",
|
||
+ N_("Choose reply options for the selected message"),
|
||
+ G_CALLBACK (action_mail_reply_alternative_cb) },
|
||
+
|
||
+ { "mail-reply-group",
|
||
+ "mail-reply-all",
|
||
+ N_("Group Reply"),
|
||
+ "<Control>g",
|
||
+ N_("Reply to the mailing list, or to all recipients"),
|
||
+ G_CALLBACK (action_mail_reply_group_cb) },
|
||
+
|
||
+ { "mail-reply-list",
|
||
+ NULL,
|
||
+ N_("Reply to _List"),
|
||
+ "<Control>l",
|
||
+ N_("Compose a reply to the mailing list of the selected message"),
|
||
+ G_CALLBACK (action_mail_reply_list_cb) },
|
||
+
|
||
+ { "mail-reply-sender",
|
||
+ "mail-reply-sender",
|
||
+ N_("_Reply to Sender"),
|
||
+ "<Control>r",
|
||
+ N_("Compose a reply to the sender of the selected message"),
|
||
+ G_CALLBACK (action_mail_reply_sender_cb) },
|
||
+
|
||
+ { "mail-reply-template",
|
||
+ NULL,
|
||
+ N_("Repl_y with Template"),
|
||
+ NULL,
|
||
+ NULL,
|
||
+ NULL },
|
||
+
|
||
+ { "mail-save-as",
|
||
+ "document-save-as",
|
||
+ N_("_Save as mbox…"),
|
||
+ "<Control>s",
|
||
+ N_("Save selected messages as an mbox file"),
|
||
+ G_CALLBACK (action_mail_save_as_cb) },
|
||
+
|
||
+ { "mail-search-web",
|
||
+ NULL,
|
||
+ N_("Search _Web…"),
|
||
+ NULL,
|
||
+ N_("Search the Web with the selected text"),
|
||
+ G_CALLBACK (action_mail_search_web_cb) },
|
||
+
|
||
+ { "mail-show-source",
|
||
+ NULL,
|
||
+ N_("_Message Source"),
|
||
+ "<Control>u",
|
||
+ N_("Show the raw email source of the message"),
|
||
+ G_CALLBACK (action_mail_show_source_cb) },
|
||
+
|
||
+ { "mail-toggle-important",
|
||
+ NULL,
|
||
+ NULL, /* No menu item; key press only */
|
||
+ NULL,
|
||
+ NULL,
|
||
+ G_CALLBACK (action_mail_toggle_important_cb) },
|
||
+
|
||
+ { "mail-undelete",
|
||
+ NULL,
|
||
+ N_("_Undelete Message"),
|
||
+ "<Shift><Control>d",
|
||
+ N_("Undelete the selected messages"),
|
||
+ G_CALLBACK (action_mail_undelete_cb) },
|
||
+
|
||
+ { "mail-zoom-100",
|
||
+ "zoom-original",
|
||
+ N_("_Normal Size"),
|
||
+ "<Control>0",
|
||
+ N_("Reset the text to its original size"),
|
||
+ G_CALLBACK (action_mail_zoom_100_cb) },
|
||
+
|
||
+ { "mail-zoom-in",
|
||
+ "zoom-in",
|
||
+ N_("_Zoom In"),
|
||
+ "<Control>plus",
|
||
+ N_("Increase the text size"),
|
||
+ G_CALLBACK (action_mail_zoom_in_cb) },
|
||
+
|
||
+ { "mail-zoom-out",
|
||
+ "zoom-out",
|
||
+ N_("Zoom _Out"),
|
||
+ "<Control>minus",
|
||
+ N_("Decrease the text size"),
|
||
+ G_CALLBACK (action_mail_zoom_out_cb) },
|
||
+
|
||
+ /*** Menus ***/
|
||
+
|
||
+ { "mail-create-menu",
|
||
+ NULL,
|
||
+ N_("Cre_ate"),
|
||
+ NULL,
|
||
+ NULL,
|
||
+ NULL },
|
||
+
|
||
+ { "mail-encoding-menu",
|
||
+ NULL,
|
||
+ N_("Ch_aracter Encoding"),
|
||
+ NULL,
|
||
+ NULL,
|
||
+ NULL },
|
||
+
|
||
+ { "mail-forward-as-menu",
|
||
+ NULL,
|
||
+ N_("F_orward As"),
|
||
+ NULL,
|
||
+ NULL,
|
||
+ NULL },
|
||
+
|
||
+ { "mail-label-menu",
|
||
+ NULL,
|
||
+ N_("_Label"),
|
||
+ NULL,
|
||
+ NULL,
|
||
+ NULL },
|
||
+
|
||
+ { "mail-reply-group-menu",
|
||
+ NULL,
|
||
+ N_("_Group Reply"),
|
||
+ NULL,
|
||
+ NULL,
|
||
+ NULL },
|
||
+
|
||
+ { "mail-goto-menu",
|
||
+ NULL,
|
||
+ N_("_Go To"),
|
||
+ NULL,
|
||
+ NULL,
|
||
+ NULL },
|
||
+
|
||
+ { "mail-mark-as-menu",
|
||
+ NULL,
|
||
+ N_("Mar_k As"),
|
||
+ NULL,
|
||
+ NULL,
|
||
+ NULL },
|
||
+
|
||
+ { "mail-message-menu",
|
||
+ NULL,
|
||
+ N_("_Message"),
|
||
+ NULL,
|
||
+ NULL,
|
||
+ NULL },
|
||
+
|
||
+ { "mail-zoom-menu",
|
||
+ NULL,
|
||
+ N_("_Zoom"),
|
||
+ NULL,
|
||
+ NULL,
|
||
+ NULL }
|
||
+};
|
||
+
|
||
+static GtkActionEntry mail_reader_search_folder_entries[] = {
|
||
+
|
||
+ { "mail-search-folder-from-mailing-list",
|
||
+ NULL,
|
||
+ N_("Create a Search Folder from Mailing _List…"),
|
||
+ NULL,
|
||
+ N_("Create a search folder for this mailing list"),
|
||
+ G_CALLBACK (action_mail_search_folder_from_mailing_list_cb) },
|
||
+
|
||
+ { "mail-search-folder-from-recipients",
|
||
+ NULL,
|
||
+ N_("Create a Search Folder from Recipien_ts…"),
|
||
+ NULL,
|
||
+ N_("Create a search folder for these recipients"),
|
||
+ G_CALLBACK (action_mail_search_folder_from_recipients_cb) },
|
||
+
|
||
+ { "mail-search-folder-from-sender",
|
||
+ NULL,
|
||
+ N_("Create a Search Folder from Sen_der…"),
|
||
+ NULL,
|
||
+ N_("Create a search folder for this sender"),
|
||
+ G_CALLBACK (action_mail_search_folder_from_sender_cb) },
|
||
+
|
||
+ { "mail-search-folder-from-subject",
|
||
+ NULL,
|
||
+ N_("Create a Search Folder from S_ubject…"),
|
||
+ NULL,
|
||
+ N_("Create a search folder for this subject"),
|
||
+ G_CALLBACK (action_mail_search_folder_from_subject_cb) },
|
||
+};
|
||
+
|
||
+static EPopupActionEntry mail_reader_popup_entries[] = {
|
||
+
|
||
+ { "mail-popup-archive",
|
||
+ NULL,
|
||
+ "mail-archive" },
|
||
+
|
||
+ { "mail-popup-color-assign",
|
||
+ NULL,
|
||
+ "mail-color-assign" },
|
||
+
|
||
+ { "mail-popup-color-unset",
|
||
+ NULL,
|
||
+ "mail-color-unset" },
|
||
+
|
||
+ { "mail-popup-copy",
|
||
+ NULL,
|
||
+ "mail-copy" },
|
||
+
|
||
+ { "mail-popup-delete",
|
||
+ NULL,
|
||
+ "mail-delete" },
|
||
+
|
||
+ { "mail-popup-add-note",
|
||
+ NULL,
|
||
+ "mail-add-note" },
|
||
+
|
||
+ { "mail-popup-delete-note",
|
||
+ NULL,
|
||
+ "mail-delete-note" },
|
||
+
|
||
+ { "mail-popup-edit-note",
|
||
+ NULL,
|
||
+ "mail-edit-note" },
|
||
+
|
||
+ { "mail-popup-flag-clear",
|
||
+ NULL,
|
||
+ "mail-flag-clear" },
|
||
+
|
||
+ { "mail-popup-flag-completed",
|
||
+ NULL,
|
||
+ "mail-flag-completed" },
|
||
+
|
||
+ { "mail-popup-flag-for-followup",
|
||
+ N_("Mark for Follo_w Up…"),
|
||
+ "mail-flag-for-followup" },
|
||
+
|
||
+ { "mail-popup-forward",
|
||
+ NULL,
|
||
+ "mail-forward" },
|
||
+
|
||
+ { "mail-popup-mark-ignore-thread-sub",
|
||
+ N_("_Ignore Subthread"),
|
||
+ "mail-mark-ignore-thread-sub" },
|
||
+
|
||
+ { "mail-popup-mark-ignore-thread-whole",
|
||
+ N_("_Ignore Thread"),
|
||
+ "mail-mark-ignore-thread-whole" },
|
||
+
|
||
+ { "mail-popup-mark-important",
|
||
+ N_("Mark as _Important"),
|
||
+ "mail-mark-important" },
|
||
+
|
||
+ { "mail-popup-mark-junk",
|
||
+ N_("Mark as _Junk"),
|
||
+ "mail-mark-junk" },
|
||
+
|
||
+ { "mail-popup-mark-notjunk",
|
||
+ N_("Mark as _Not Junk"),
|
||
+ "mail-mark-notjunk" },
|
||
+
|
||
+ { "mail-popup-mark-read",
|
||
+ N_("Mar_k as Read"),
|
||
+ "mail-mark-read" },
|
||
+
|
||
+ { "mail-popup-mark-unignore-thread-sub",
|
||
+ N_("Do not _Ignore Subthread"),
|
||
+ "mail-mark-unignore-thread-sub" },
|
||
+
|
||
+ { "mail-popup-mark-unignore-thread-whole",
|
||
+ N_("Do not _Ignore Thread"),
|
||
+ "mail-mark-unignore-thread-whole" },
|
||
+
|
||
+ { "mail-popup-mark-unimportant",
|
||
+ N_("Mark as Uni_mportant"),
|
||
+ "mail-mark-unimportant" },
|
||
+
|
||
+ { "mail-popup-mark-unread",
|
||
+ N_("Mark as _Unread"),
|
||
+ "mail-mark-unread" },
|
||
+
|
||
+ { "mail-popup-message-edit",
|
||
+ NULL,
|
||
+ "mail-message-edit" },
|
||
+
|
||
+ { "mail-popup-move",
|
||
+ NULL,
|
||
+ "mail-move" },
|
||
+
|
||
+ { "mail-popup-print",
|
||
+ NULL,
|
||
+ "mail-print" },
|
||
+
|
||
+ { "mail-popup-remove-attachments",
|
||
+ NULL,
|
||
+ "mail-remove-attachments" },
|
||
+
|
||
+ { "mail-popup-remove-duplicates",
|
||
+ NULL,
|
||
+ "mail-remove-duplicates" },
|
||
+
|
||
+ { "mail-popup-reply-all",
|
||
+ NULL,
|
||
+ "mail-reply-all" },
|
||
+
|
||
+ { "mail-popup-reply-sender",
|
||
+ NULL,
|
||
+ "mail-reply-sender" },
|
||
+
|
||
+ { "mail-popup-reply-template",
|
||
+ NULL,
|
||
+ "mail-reply-template" },
|
||
+
|
||
+ { "mail-popup-save-as",
|
||
+ NULL,
|
||
+ "mail-save-as" },
|
||
+
|
||
+ { "mail-popup-search-web",
|
||
+ NULL,
|
||
+ "mail-search-web" },
|
||
+
|
||
+ { "mail-popup-undelete",
|
||
+ NULL,
|
||
+ "mail-undelete" }
|
||
+};
|
||
+
|
||
+static GtkToggleActionEntry mail_reader_toggle_entries[] = {
|
||
+
|
||
+ { "mail-caret-mode",
|
||
+ NULL,
|
||
+ N_("_Caret Mode"),
|
||
+ "F7",
|
||
+ N_("Show a blinking cursor in the body of displayed messages"),
|
||
+ NULL, /* No callback required */
|
||
+ FALSE },
|
||
+
|
||
+ { "mail-show-all-headers",
|
||
+ NULL,
|
||
+ N_("All Message _Headers"),
|
||
+ NULL,
|
||
+ N_("Show messages with all email headers"),
|
||
+ G_CALLBACK (action_mail_show_all_headers_cb),
|
||
+ FALSE }
|
||
+};
|
||
+
|
||
+static void
|
||
+mail_reader_double_click_cb (EMailReader *reader,
|
||
+ gint row,
|
||
+ ETreePath path,
|
||
+ gint col,
|
||
+ GdkEvent *event)
|
||
+{
|
||
+ GtkAction *action;
|
||
+
|
||
+ /* Ignore double clicks on columns that handle their own state. */
|
||
+ if (MESSAGE_LIST_COLUMN_IS_ACTIVE (col))
|
||
+ return;
|
||
+
|
||
+ action = e_mail_reader_get_action (reader, "mail-message-open");
|
||
+ gtk_action_activate (action);
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+mail_reader_key_press_event_cb (EMailReader *reader,
|
||
+ GdkEventKey *event)
|
||
+{
|
||
+ GtkAction *action;
|
||
+ const gchar *action_name;
|
||
+
|
||
+ if (!gtk_widget_has_focus (GTK_WIDGET (reader))) {
|
||
+ EMailDisplay *display;
|
||
+
|
||
+ display = e_mail_reader_get_mail_display (reader);
|
||
+ if (e_web_view_get_need_input (E_WEB_VIEW (display)) &&
|
||
+ gtk_widget_has_focus (GTK_WIDGET (display)))
|
||
+ return FALSE;
|
||
+ }
|
||
+
|
||
+ if ((event->state & GDK_CONTROL_MASK) != 0)
|
||
+ goto ctrl;
|
||
+
|
||
+ /* <keyval> alone */
|
||
+ switch (event->keyval) {
|
||
+ case GDK_KEY_Delete:
|
||
+ case GDK_KEY_KP_Delete:
|
||
+ action_name = "mail-delete";
|
||
+ break;
|
||
+
|
||
+ case GDK_KEY_Return:
|
||
+ case GDK_KEY_KP_Enter:
|
||
+ case GDK_KEY_ISO_Enter:
|
||
+ if (E_IS_MAIL_BROWSER (reader))
|
||
+ return FALSE;
|
||
+
|
||
+ action_name = "mail-message-open";
|
||
+ break;
|
||
+
|
||
+ case GDK_KEY_period:
|
||
+ case GDK_KEY_bracketright:
|
||
+ action_name = "mail-next-unread";
|
||
+ break;
|
||
+
|
||
+ case GDK_KEY_comma:
|
||
+ case GDK_KEY_bracketleft:
|
||
+ action_name = "mail-previous-unread";
|
||
+ break;
|
||
+
|
||
+#ifdef HAVE_XFREE
|
||
+ case XF86XK_Reply:
|
||
+ action_name = "mail-reply-all";
|
||
+ break;
|
||
+
|
||
+ case XF86XK_MailForward:
|
||
+ action_name = "mail-forward";
|
||
+ break;
|
||
+#endif
|
||
+
|
||
+ case GDK_KEY_exclam:
|
||
+ action_name = "mail-toggle-important";
|
||
+ break;
|
||
+
|
||
+ case GDK_KEY_ZoomIn:
|
||
+ action_name = "mail-zoom-in";
|
||
+ break;
|
||
+
|
||
+ case GDK_KEY_ZoomOut:
|
||
+ action_name = "mail-zoom-out";
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ return FALSE;
|
||
+ }
|
||
+
|
||
+ goto exit;
|
||
+
|
||
+ctrl:
|
||
+
|
||
+ /* Ctrl + <keyval> */
|
||
+ switch (event->keyval) {
|
||
+ case GDK_KEY_period:
|
||
+ action_name = "mail-next-unread";
|
||
+ break;
|
||
+
|
||
+ case GDK_KEY_comma:
|
||
+ action_name = "mail-previous-unread";
|
||
+ break;
|
||
+
|
||
+ case GDK_KEY_equal:
|
||
+ case GDK_KEY_KP_Add:
|
||
+ action_name = "mail-zoom-in";
|
||
+ break;
|
||
+
|
||
+ case GDK_KEY_KP_Subtract:
|
||
+ action_name = "mail-zoom-out";
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ return FALSE;
|
||
+ }
|
||
+
|
||
+exit:
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_activate (action);
|
||
+
|
||
+ return TRUE;
|
||
+}
|
||
+
|
||
+static gint
|
||
+mail_reader_key_press_cb (EMailReader *reader,
|
||
+ gint row,
|
||
+ ETreePath path,
|
||
+ gint col,
|
||
+ GdkEvent *event)
|
||
+{
|
||
+ return mail_reader_key_press_event_cb (reader, &event->key);
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+mail_reader_message_seen_cb (gpointer user_data)
|
||
+{
|
||
+ EMailReaderClosure *closure = user_data;
|
||
+ EMailReader *reader;
|
||
+ GtkWidget *message_list;
|
||
+ EMailPartList *parts;
|
||
+ EMailDisplay *display;
|
||
+ CamelMimeMessage *message;
|
||
+ const gchar *current_uid;
|
||
+ const gchar *message_uid;
|
||
+ gboolean uid_is_current = TRUE;
|
||
+
|
||
+ reader = closure->reader;
|
||
+ message_uid = closure->message_uid;
|
||
+
|
||
+ display = e_mail_reader_get_mail_display (reader);
|
||
+ parts = e_mail_display_get_part_list (display);
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ g_return_val_if_fail (IS_MESSAGE_LIST (message_list), FALSE);
|
||
+
|
||
+ /* zero the timeout id now, if it was not rescheduled */
|
||
+ if (g_source_get_id (g_main_current_source ()) == MESSAGE_LIST (message_list)->seen_id)
|
||
+ MESSAGE_LIST (message_list)->seen_id = 0;
|
||
+
|
||
+ if (e_tree_is_dragging (E_TREE (message_list)))
|
||
+ return FALSE;
|
||
+
|
||
+ current_uid = MESSAGE_LIST (message_list)->cursor_uid;
|
||
+ uid_is_current &= (g_strcmp0 (current_uid, message_uid) == 0);
|
||
+
|
||
+ if (parts != NULL)
|
||
+ message = e_mail_part_list_get_message (parts);
|
||
+ else
|
||
+ message = NULL;
|
||
+
|
||
+ if (uid_is_current && message != NULL)
|
||
+ g_signal_emit (
|
||
+ reader, signals[MESSAGE_SEEN], 0,
|
||
+ message_uid, message);
|
||
+
|
||
+ return FALSE;
|
||
+}
|
||
+
|
||
+static void
|
||
+schedule_timeout_mark_seen (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+ MessageList *message_list;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
|
||
+ g_return_if_fail (message_list != NULL);
|
||
+
|
||
+ if (message_list->cursor_uid) {
|
||
+ EMailReaderClosure *timeout_closure;
|
||
+
|
||
+ if (message_list->seen_id > 0) {
|
||
+ g_source_remove (message_list->seen_id);
|
||
+ message_list->seen_id = 0;
|
||
+ }
|
||
+
|
||
+ timeout_closure = g_slice_new0 (EMailReaderClosure);
|
||
+ timeout_closure->reader = g_object_ref (reader);
|
||
+ timeout_closure->message_uid = g_strdup (message_list->cursor_uid);
|
||
+
|
||
+ MESSAGE_LIST (message_list)->seen_id =
|
||
+ e_named_timeout_add_full (
|
||
+ G_PRIORITY_DEFAULT, priv->schedule_mark_seen_interval,
|
||
+ mail_reader_message_seen_cb,
|
||
+ timeout_closure, (GDestroyNotify)
|
||
+ mail_reader_closure_free);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_load_changed_cb (EMailReader *reader,
|
||
+ WebKitLoadEvent event,
|
||
+ EMailDisplay *display)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+
|
||
+ if (event != WEBKIT_LOAD_FINISHED)
|
||
+ return;
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+ if (priv->schedule_mark_seen &&
|
||
+ E_IS_MAIL_VIEW (reader) &&
|
||
+ e_mail_display_get_part_list (display) &&
|
||
+ e_mail_view_get_preview_visible (E_MAIL_VIEW (reader))) {
|
||
+ if (priv->folder_was_just_selected)
|
||
+ priv->folder_was_just_selected = FALSE;
|
||
+ else
|
||
+ schedule_timeout_mark_seen (reader);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_remote_content_clicked_cb (EMailReader *reader,
|
||
+ const GdkRectangle *position,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ GtkWidget *mail_display = user_data;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+ g_return_if_fail (E_IS_MAIL_DISPLAY (mail_display));
|
||
+
|
||
+ e_mail_remote_content_popover_run (reader, mail_display, position);
|
||
+}
|
||
+
|
||
+static void
|
||
+maybe_schedule_timeout_mark_seen (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+ MessageList *message_list;
|
||
+ gboolean schedule_timeout;
|
||
+ gint timeout_interval = -1;
|
||
+ const gchar *message_uid;
|
||
+
|
||
+ message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
|
||
+
|
||
+ message_uid = message_list->cursor_uid;
|
||
+ if (message_uid == NULL ||
|
||
+ e_tree_is_dragging (E_TREE (message_list)))
|
||
+ return;
|
||
+
|
||
+ schedule_timeout =
|
||
+ (message_uid != NULL) &&
|
||
+ e_mail_reader_utils_get_mark_seen_setting (reader, &timeout_interval);
|
||
+
|
||
+ if (message_list->seen_id > 0) {
|
||
+ g_source_remove (message_list->seen_id);
|
||
+ message_list->seen_id = 0;
|
||
+ }
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+ priv->schedule_mark_seen = schedule_timeout;
|
||
+ priv->schedule_mark_seen_interval = timeout_interval;
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+discard_timeout_mark_seen_cb (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+ MessageList *message_list;
|
||
+
|
||
+ g_return_val_if_fail (reader != NULL, FALSE);
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+ priv->schedule_mark_seen = FALSE;
|
||
+
|
||
+ message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
|
||
+ g_return_val_if_fail (message_list != NULL, FALSE);
|
||
+
|
||
+ if (message_list->seen_id > 0) {
|
||
+ g_source_remove (message_list->seen_id);
|
||
+ message_list->seen_id = 0;
|
||
+ }
|
||
+
|
||
+ return FALSE;
|
||
+}
|
||
+
|
||
+
|
||
+static void
|
||
+mail_reader_preview_pane_visible_changed_cb (EMailReader *reader,
|
||
+ GParamSpec *param,
|
||
+ GtkWidget *widget)
|
||
+{
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+ g_return_if_fail (GTK_IS_WIDGET (widget));
|
||
+
|
||
+ if (!gtk_widget_is_visible (widget))
|
||
+ discard_timeout_mark_seen_cb (reader);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_remove_followup_alert (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+ if (!priv)
|
||
+ return;
|
||
+
|
||
+ if (priv->followup_alert)
|
||
+ e_alert_response (priv->followup_alert, GTK_RESPONSE_OK);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_manage_followup_flag (EMailReader *reader,
|
||
+ CamelFolder *folder,
|
||
+ const gchar *message_uid)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+ CamelMessageInfo *info;
|
||
+ const gchar *followup, *completed_on, *due_by;
|
||
+ time_t date;
|
||
+ gchar *date_str = NULL;
|
||
+ gboolean alert_added = FALSE;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+ g_return_if_fail (CAMEL_IS_FOLDER (folder));
|
||
+ g_return_if_fail (message_uid != NULL);
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+ if (!priv)
|
||
+ return;
|
||
+
|
||
+ info = camel_folder_get_message_info (folder, message_uid);
|
||
+ if (!info)
|
||
+ return;
|
||
+
|
||
+ followup = camel_message_info_get_user_tag (info, "follow-up");
|
||
+ if (followup && *followup) {
|
||
+ EPreviewPane *preview_pane;
|
||
+ const gchar *alert_tag;
|
||
+ EAlert *alert;
|
||
+
|
||
+ completed_on = camel_message_info_get_user_tag (info, "completed-on");
|
||
+ due_by = camel_message_info_get_user_tag (info, "due-by");
|
||
+
|
||
+ if (completed_on && *completed_on) {
|
||
+ alert_tag = "mail:follow-up-completed-info";
|
||
+ date = camel_header_decode_date (completed_on, NULL);
|
||
+ date_str = e_datetime_format_format ("mail", "header", DTFormatKindDateTime, date);
|
||
+ } else if (due_by && *due_by) {
|
||
+ time_t now;
|
||
+
|
||
+ alert_tag = "mail:follow-up-dueby-info";
|
||
+ date = camel_header_decode_date (due_by, NULL);
|
||
+ date_str = e_datetime_format_format ("mail", "header", DTFormatKindDateTime, date);
|
||
+
|
||
+ now = time (NULL);
|
||
+ if (now > date)
|
||
+ alert_tag = "mail:follow-up-overdue-error";
|
||
+ } else {
|
||
+ alert_tag = "mail:follow-up-flag-info";
|
||
+ }
|
||
+
|
||
+ alert = e_alert_new (alert_tag, followup, date_str ? date_str : "???", NULL);
|
||
+
|
||
+ g_free (date_str);
|
||
+
|
||
+ preview_pane = e_mail_reader_get_preview_pane (reader);
|
||
+ e_alert_sink_submit_alert (E_ALERT_SINK (preview_pane), alert);
|
||
+
|
||
+ alert_added = TRUE;
|
||
+
|
||
+ mail_reader_remove_followup_alert (reader);
|
||
+ priv->followup_alert = alert;
|
||
+ g_object_add_weak_pointer (G_OBJECT (priv->followup_alert), &priv->followup_alert);
|
||
+
|
||
+ g_object_unref (alert);
|
||
+ }
|
||
+
|
||
+ g_clear_object (&info);
|
||
+
|
||
+ if (!alert_added)
|
||
+ mail_reader_remove_followup_alert (reader);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_reload (EMailReader *reader)
|
||
+{
|
||
+ CamelFolder *folder;
|
||
+ GPtrArray *uids;
|
||
+ EMailDisplay *mail_display;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+ uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
|
||
+
|
||
+ if (uids && uids->len == 1)
|
||
+ mail_reader_manage_followup_flag (reader, folder, uids->pdata[0]);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ if (uids)
|
||
+ g_ptr_array_unref (uids);
|
||
+
|
||
+ mail_display = e_mail_reader_get_mail_display (reader);
|
||
+ e_mail_display_reload (mail_display);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_remove_ui (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+ GtkWindow *window;
|
||
+ GtkUIManager *ui_manager = NULL;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ if (!priv->main_menu_label_merge_id)
|
||
+ return;
|
||
+
|
||
+ window = e_mail_reader_get_window (reader);
|
||
+ g_return_if_fail (window != NULL);
|
||
+
|
||
+ if (E_IS_SHELL_WINDOW (window))
|
||
+ ui_manager = e_shell_window_get_ui_manager (E_SHELL_WINDOW (window));
|
||
+ else if (E_IS_MAIL_BROWSER (window))
|
||
+ ui_manager = e_mail_browser_get_ui_manager (E_MAIL_BROWSER (window));
|
||
+
|
||
+ g_return_if_fail (ui_manager != NULL);
|
||
+ g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager));
|
||
+
|
||
+ gtk_ui_manager_remove_ui (ui_manager, priv->main_menu_label_merge_id);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_message_loaded_cb (CamelFolder *folder,
|
||
+ GAsyncResult *result,
|
||
+ EMailReaderClosure *closure)
|
||
+{
|
||
+ EMailReader *reader;
|
||
+ EMailReaderPrivate *priv;
|
||
+ CamelMimeMessage *message = NULL;
|
||
+ GtkWidget *message_list;
|
||
+ const gchar *message_uid;
|
||
+ GError *error = NULL;
|
||
+
|
||
+ reader = closure->reader;
|
||
+ message_uid = closure->message_uid;
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ /* If the private struct is NULL, the EMailReader was destroyed
|
||
+ * while we were loading the message and we're likely holding the
|
||
+ * last reference. Nothing to do but drop the reference.
|
||
+ * FIXME Use a GWeakRef instead of this hack. */
|
||
+ if (priv == NULL) {
|
||
+ mail_reader_closure_free (closure);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ message = camel_folder_get_message_finish (folder, result, &error);
|
||
+
|
||
+ /* If the user picked a different message in the time it took
|
||
+ * to fetch this message, then don't bother rendering it. */
|
||
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||
+ g_clear_error (&error);
|
||
+ goto exit;
|
||
+ }
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ if (message_list == NULL) {
|
||
+ /* For cases where message fetching took so long that
|
||
+ * user closed the message window before this was called. */
|
||
+ goto exit;
|
||
+ }
|
||
+
|
||
+ if (message != NULL) {
|
||
+ CamelMessageInfo *mi;
|
||
+
|
||
+ mail_reader_manage_followup_flag (reader, folder, message_uid);
|
||
+
|
||
+ mi = camel_folder_get_message_info (folder, message_uid);
|
||
+ if (mi) {
|
||
+ if (camel_util_fill_message_info_user_headers (mi, camel_medium_get_headers (CAMEL_MEDIUM (message))))
|
||
+ gtk_widget_queue_draw (message_list);
|
||
+
|
||
+ g_object_unref (mi);
|
||
+ }
|
||
+
|
||
+ g_signal_emit (
|
||
+ reader, signals[MESSAGE_LOADED], 0,
|
||
+ message_uid, message);
|
||
+ }
|
||
+
|
||
+exit:
|
||
+ if (error != NULL) {
|
||
+ EPreviewPane *preview_pane;
|
||
+ EWebView *web_view;
|
||
+
|
||
+ preview_pane = e_mail_reader_get_preview_pane (reader);
|
||
+ web_view = e_preview_pane_get_web_view (preview_pane);
|
||
+
|
||
+ if (g_error_matches (error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE) &&
|
||
+ CAMEL_IS_OFFLINE_FOLDER (folder) &&
|
||
+ camel_service_get_connection_status (CAMEL_SERVICE (camel_folder_get_parent_store (folder))) != CAMEL_SERVICE_CONNECTED)
|
||
+ e_alert_submit (
|
||
+ E_ALERT_SINK (web_view),
|
||
+ "mail:no-retrieve-message-offline",
|
||
+ NULL);
|
||
+ else
|
||
+ e_alert_submit (
|
||
+ E_ALERT_SINK (web_view),
|
||
+ "mail:no-retrieve-message",
|
||
+ error->message, NULL);
|
||
+ }
|
||
+
|
||
+ g_clear_error (&error);
|
||
+
|
||
+ mail_reader_closure_free (closure);
|
||
+
|
||
+ g_clear_object (&message);
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+mail_reader_message_selected_timeout_cb (gpointer user_data)
|
||
+{
|
||
+ EMailReader *reader;
|
||
+ EMailReaderPrivate *priv;
|
||
+ EMailDisplay *display;
|
||
+ GtkWidget *message_list;
|
||
+ const gchar *cursor_uid;
|
||
+ const gchar *format_uid;
|
||
+ EMailPartList *parts;
|
||
+
|
||
+ reader = E_MAIL_READER (user_data);
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+ display = e_mail_reader_get_mail_display (reader);
|
||
+ parts = e_mail_display_get_part_list (display);
|
||
+
|
||
+ cursor_uid = MESSAGE_LIST (message_list)->cursor_uid;
|
||
+ if (parts != NULL)
|
||
+ format_uid = e_mail_part_list_get_message_uid (parts);
|
||
+ else
|
||
+ format_uid = NULL;
|
||
+
|
||
+ if (MESSAGE_LIST (message_list)->last_sel_single) {
|
||
+ GtkWidget *widget;
|
||
+ gboolean display_visible;
|
||
+ gboolean selected_uid_changed;
|
||
+
|
||
+ /* Decide whether to download the full message now. */
|
||
+ widget = GTK_WIDGET (display);
|
||
+ display_visible = gtk_widget_get_mapped (widget);
|
||
+
|
||
+ selected_uid_changed = (g_strcmp0 (cursor_uid, format_uid) != 0);
|
||
+
|
||
+ if (display_visible && selected_uid_changed) {
|
||
+ EMailReaderClosure *closure;
|
||
+ GCancellable *cancellable;
|
||
+ CamelFolder *folder;
|
||
+ EActivity *activity;
|
||
+ gchar *string;
|
||
+
|
||
+ string = g_strdup_printf (
|
||
+ _("Retrieving message “%s”"), cursor_uid);
|
||
+ e_mail_display_set_part_list (display, NULL);
|
||
+ e_mail_display_set_status (display, string);
|
||
+ g_free (string);
|
||
+
|
||
+ activity = e_mail_reader_new_activity (reader);
|
||
+ e_activity_set_text (activity, _("Retrieving message"));
|
||
+ cancellable = e_activity_get_cancellable (activity);
|
||
+
|
||
+ closure = g_slice_new0 (EMailReaderClosure);
|
||
+ closure->activity = activity;
|
||
+ closure->reader = g_object_ref (reader);
|
||
+ closure->message_uid = g_strdup (cursor_uid);
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+
|
||
+ camel_folder_get_message (
|
||
+ folder, cursor_uid, G_PRIORITY_DEFAULT,
|
||
+ cancellable, (GAsyncReadyCallback)
|
||
+ mail_reader_message_loaded_cb, closure);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+
|
||
+ if (priv->retrieving_message != NULL)
|
||
+ g_object_unref (priv->retrieving_message);
|
||
+ priv->retrieving_message = g_object_ref (cancellable);
|
||
+ }
|
||
+ } else {
|
||
+ e_mail_display_set_part_list (display, NULL);
|
||
+ }
|
||
+
|
||
+ priv->message_selected_timeout_id = 0;
|
||
+
|
||
+ return FALSE;
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_message_selected_cb (EMailReader *reader,
|
||
+ const gchar *message_uid)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+ MessageList *message_list;
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ /* Cancel the previous message retrieval activity. */
|
||
+ g_cancellable_cancel (priv->retrieving_message);
|
||
+
|
||
+ /* Cancel the message selected timer. */
|
||
+ if (priv->message_selected_timeout_id > 0) {
|
||
+ g_source_remove (priv->message_selected_timeout_id);
|
||
+ priv->message_selected_timeout_id = 0;
|
||
+ }
|
||
+
|
||
+ if (priv->folder_was_just_selected && message_uid) {
|
||
+ if (priv->did_try_to_open_message)
|
||
+ priv->folder_was_just_selected = FALSE;
|
||
+ else
|
||
+ priv->did_try_to_open_message = TRUE;
|
||
+ }
|
||
+
|
||
+ message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
|
||
+ if (message_list) {
|
||
+ EMailPartList *parts;
|
||
+ const gchar *cursor_uid, *format_uid;
|
||
+
|
||
+ parts = e_mail_display_get_part_list (e_mail_reader_get_mail_display (reader));
|
||
+
|
||
+ cursor_uid = MESSAGE_LIST (message_list)->cursor_uid;
|
||
+ if (parts != NULL)
|
||
+ format_uid = e_mail_part_list_get_message_uid (parts);
|
||
+ else
|
||
+ format_uid = NULL;
|
||
+
|
||
+ /* It can happen when the message was loaded that quickly that
|
||
+ it was delivered before this callback. */
|
||
+ if (g_strcmp0 (cursor_uid, format_uid) == 0) {
|
||
+ e_mail_reader_changed (reader);
|
||
+ return;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* Cancel the seen timer. */
|
||
+ if (message_list != NULL && message_list->seen_id) {
|
||
+ g_source_remove (message_list->seen_id);
|
||
+ message_list->seen_id = 0;
|
||
+ }
|
||
+
|
||
+ if (message_list_selected_count (message_list) != 1) {
|
||
+ EMailDisplay *display;
|
||
+
|
||
+ display = e_mail_reader_get_mail_display (reader);
|
||
+ e_mail_display_set_part_list (display, NULL);
|
||
+ e_web_view_clear (E_WEB_VIEW (display));
|
||
+
|
||
+ } else if (priv->folder_was_just_selected) {
|
||
+ /* Skip the timeout if we're restoring the previous message
|
||
+ * selection. The timeout is there for when we're scrolling
|
||
+ * rapidly through the message list. */
|
||
+ mail_reader_message_selected_timeout_cb (reader);
|
||
+
|
||
+ } else {
|
||
+ priv->message_selected_timeout_id = e_named_timeout_add (
|
||
+ 100, mail_reader_message_selected_timeout_cb, reader);
|
||
+ }
|
||
+
|
||
+ e_mail_reader_changed (reader);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_message_cursor_change_cb (EMailReader *reader)
|
||
+{
|
||
+ MessageList *message_list;
|
||
+ EMailReaderPrivate *priv;
|
||
+
|
||
+ g_return_if_fail (reader != NULL);
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+ g_return_if_fail (priv != NULL);
|
||
+
|
||
+ message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
|
||
+ g_return_if_fail (message_list != NULL);
|
||
+
|
||
+ if (message_list->seen_id == 0 &&
|
||
+ E_IS_MAIL_VIEW (reader) &&
|
||
+ e_mail_view_get_preview_visible (E_MAIL_VIEW (reader)) &&
|
||
+ !priv->avoid_next_mark_as_seen)
|
||
+ maybe_schedule_timeout_mark_seen (reader);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_emit_folder_loaded (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+ MessageList *message_list;
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+ message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
|
||
+
|
||
+ if (priv && (message_list_count (message_list) <= 0 ||
|
||
+ message_list_selected_count (message_list) <= 0))
|
||
+ priv->avoid_next_mark_as_seen = FALSE;
|
||
+
|
||
+ g_signal_emit (reader, signals[FOLDER_LOADED], 0);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_message_list_built_cb (MessageList *message_list,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+ mail_reader_emit_folder_loaded (reader);
|
||
+
|
||
+ /* No cursor_uid means that there will not be emitted any
|
||
+ "cursor-changed" and "message-selected" signal, thus
|
||
+ unset the "just selected folder" flag */
|
||
+ if (!message_list->cursor_uid)
|
||
+ priv->folder_was_just_selected = FALSE;
|
||
+}
|
||
+
|
||
+static EAlertSink *
|
||
+mail_reader_get_alert_sink (EMailReader *reader)
|
||
+{
|
||
+ EPreviewPane *preview_pane;
|
||
+
|
||
+ preview_pane = e_mail_reader_get_preview_pane (reader);
|
||
+
|
||
+ if (!gtk_widget_is_visible (GTK_WIDGET (preview_pane))) {
|
||
+ GtkWindow *window;
|
||
+
|
||
+ window = e_mail_reader_get_window (reader);
|
||
+
|
||
+ if (E_IS_SHELL_WINDOW (window))
|
||
+ return E_ALERT_SINK (window);
|
||
+ }
|
||
+
|
||
+ return E_ALERT_SINK (preview_pane);
|
||
+}
|
||
+
|
||
+static GPtrArray *
|
||
+mail_reader_get_selected_uids (EMailReader *reader)
|
||
+{
|
||
+ GtkWidget *message_list;
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ return message_list_get_selected (MESSAGE_LIST (message_list));
|
||
+}
|
||
+
|
||
+static GPtrArray *
|
||
+mail_reader_get_selected_uids_with_collapsed_threads (EMailReader *reader)
|
||
+{
|
||
+ GtkWidget *message_list;
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ return message_list_get_selected_with_collapsed_threads (MESSAGE_LIST (message_list));
|
||
+}
|
||
+
|
||
+static CamelFolder *
|
||
+mail_reader_ref_folder (EMailReader *reader)
|
||
+{
|
||
+ GtkWidget *message_list;
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ return message_list_ref_folder (MESSAGE_LIST (message_list));
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_set_folder (EMailReader *reader,
|
||
+ CamelFolder *folder)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+ EMailDisplay *display;
|
||
+ CamelFolder *previous_folder;
|
||
+ GtkWidget *message_list;
|
||
+ EMailBackend *backend;
|
||
+ EShell *shell;
|
||
+ gboolean sync_folder;
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ display = e_mail_reader_get_mail_display (reader);
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ previous_folder = e_mail_reader_ref_folder (reader);
|
||
+
|
||
+ backend = e_mail_reader_get_backend (reader);
|
||
+ shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
|
||
+
|
||
+ /* Only synchronize the real folder if we're online. */
|
||
+ sync_folder =
|
||
+ (previous_folder != NULL) &&
|
||
+ (CAMEL_IS_VEE_FOLDER (previous_folder) ||
|
||
+ e_shell_get_online (shell));
|
||
+ if (sync_folder)
|
||
+ mail_sync_folder (previous_folder, TRUE, NULL, NULL);
|
||
+
|
||
+ /* Skip the rest if we're already viewing the folder. */
|
||
+ if (folder != previous_folder) {
|
||
+ e_web_view_clear (E_WEB_VIEW (display));
|
||
+
|
||
+ priv->folder_was_just_selected = (folder != NULL) && !priv->mark_seen_always;
|
||
+ priv->did_try_to_open_message = FALSE;
|
||
+
|
||
+ /* This is to make sure any post-poned changes in Search
|
||
+ * Folders will be propagated on folder selection. */
|
||
+ if (CAMEL_IS_VEE_FOLDER (folder))
|
||
+ mail_sync_folder (folder, FALSE, NULL, NULL);
|
||
+
|
||
+ message_list_set_folder (MESSAGE_LIST (message_list), folder);
|
||
+
|
||
+ mail_reader_emit_folder_loaded (reader);
|
||
+ }
|
||
+
|
||
+ g_clear_object (&previous_folder);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_set_message (EMailReader *reader,
|
||
+ const gchar *message_uid)
|
||
+{
|
||
+ GtkWidget *message_list;
|
||
+ EMailReaderPrivate *priv;
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ /* For a case when the preview panel had been disabled */
|
||
+ priv->folder_was_just_selected = FALSE;
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ message_list_select_uid (
|
||
+ MESSAGE_LIST (message_list), message_uid, FALSE);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_folder_loaded (EMailReader *reader)
|
||
+{
|
||
+ guint32 state;
|
||
+
|
||
+ state = e_mail_reader_check_state (reader);
|
||
+ e_mail_reader_update_actions (reader, state);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_message_list_suggest_update_actions_cb (EMailReader *reader)
|
||
+{
|
||
+ guint32 state;
|
||
+
|
||
+ state = e_mail_reader_check_state (reader);
|
||
+ e_mail_reader_update_actions (reader, state);
|
||
+}
|
||
+
|
||
+static void
|
||
+set_mail_display_part_list (GObject *object,
|
||
+ GAsyncResult *result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ EMailPartList *part_list;
|
||
+ EMailReader *reader;
|
||
+ EMailDisplay *display;
|
||
+ GError *local_error = NULL;
|
||
+
|
||
+ reader = E_MAIL_READER (object);
|
||
+
|
||
+ part_list = e_mail_reader_parse_message_finish (reader, result, &local_error);
|
||
+
|
||
+ if (local_error) {
|
||
+ g_warn_if_fail (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED));
|
||
+
|
||
+ g_clear_error (&local_error);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ display = e_mail_reader_get_mail_display (reader);
|
||
+
|
||
+ e_mail_display_set_part_list (display, part_list);
|
||
+ e_mail_display_load (display, NULL);
|
||
+
|
||
+ /* Remove the reference added when parts list was
|
||
+ * created, so that only owners are EMailDisplays. */
|
||
+ g_object_unref (part_list);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_set_display_formatter_for_message (EMailReader *reader,
|
||
+ EMailDisplay *display,
|
||
+ const gchar *message_uid,
|
||
+ CamelMimeMessage *message,
|
||
+ CamelFolder *folder)
|
||
+{
|
||
+ CamelObjectBag *registry;
|
||
+ EMailPartList *parts;
|
||
+ EMailReaderPrivate *priv;
|
||
+ gchar *mail_uri;
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+ mail_uri = e_mail_part_build_uri (folder, message_uid, NULL, NULL);
|
||
+ registry = e_mail_part_list_get_registry ();
|
||
+ parts = camel_object_bag_peek (registry, mail_uri);
|
||
+ g_free (mail_uri);
|
||
+
|
||
+ if (parts == NULL) {
|
||
+ if (!priv->retrieving_message)
|
||
+ priv->retrieving_message = camel_operation_new ();
|
||
+
|
||
+ e_mail_reader_parse_message (
|
||
+ reader, folder, message_uid, message,
|
||
+ priv->retrieving_message,
|
||
+ set_mail_display_part_list, NULL);
|
||
+ } else {
|
||
+ e_mail_display_set_part_list (display, parts);
|
||
+ e_mail_display_load (display, NULL);
|
||
+ g_object_unref (parts);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_message_loaded (EMailReader *reader,
|
||
+ const gchar *message_uid,
|
||
+ CamelMimeMessage *message)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+ GtkWidget *message_list;
|
||
+ EMailBackend *backend;
|
||
+ CamelFolder *folder;
|
||
+ EMailDisplay *display;
|
||
+ EShellBackend *shell_backend;
|
||
+ EShell *shell;
|
||
+ EMEvent *event;
|
||
+ EMEventTargetMessage *target;
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+ backend = e_mail_reader_get_backend (reader);
|
||
+ display = e_mail_reader_get_mail_display (reader);
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ shell_backend = E_SHELL_BACKEND (backend);
|
||
+ shell = e_shell_backend_get_shell (shell_backend);
|
||
+
|
||
+ /** @Event: message.reading
|
||
+ * @Title: Viewing a message
|
||
+ * @Target: EMEventTargetMessage
|
||
+ *
|
||
+ * message.reading is emitted whenever a user views a message.
|
||
+ */
|
||
+ event = em_event_peek ();
|
||
+ target = em_event_target_new_message (
|
||
+ event, folder, message, message_uid, 0, NULL);
|
||
+ e_event_emit (
|
||
+ (EEvent *) event, "message.reading",
|
||
+ (EEventTarget *) target);
|
||
+
|
||
+ mail_reader_set_display_formatter_for_message (
|
||
+ reader, display, message_uid, message, folder);
|
||
+
|
||
+ /* Reset the shell view icon. */
|
||
+ e_shell_event (shell, "mail-icon", (gpointer) "evolution-mail");
|
||
+
|
||
+ if (MESSAGE_LIST (message_list)->seen_id > 0) {
|
||
+ g_source_remove (MESSAGE_LIST (message_list)->seen_id);
|
||
+ MESSAGE_LIST (message_list)->seen_id = 0;
|
||
+ }
|
||
+
|
||
+ /* Determine whether to mark the message as read. */
|
||
+ if (message != NULL &&
|
||
+ !priv->avoid_next_mark_as_seen)
|
||
+ maybe_schedule_timeout_mark_seen (reader);
|
||
+
|
||
+ priv->avoid_next_mark_as_seen = FALSE;
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_message_seen (EMailReader *reader,
|
||
+ const gchar *message_uid,
|
||
+ CamelMimeMessage *message)
|
||
+{
|
||
+ CamelFolder *folder;
|
||
+ guint32 mask, set;
|
||
+
|
||
+ mask = CAMEL_MESSAGE_SEEN;
|
||
+ set = CAMEL_MESSAGE_SEEN;
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+ camel_folder_set_message_flags (folder, message_uid, mask, set);
|
||
+ g_clear_object (&folder);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_show_search_bar (EMailReader *reader)
|
||
+{
|
||
+ EPreviewPane *preview_pane;
|
||
+
|
||
+ preview_pane = e_mail_reader_get_preview_pane (reader);
|
||
+ e_preview_pane_show_search_bar (preview_pane);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_label_cb (GtkToggleAction *action,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ CamelFolder *folder;
|
||
+ GPtrArray *uids;
|
||
+ const gchar *tag;
|
||
+ gint ii;
|
||
+
|
||
+ tag = g_object_get_data (G_OBJECT (action), "tag");
|
||
+ g_return_if_fail (tag != NULL);
|
||
+
|
||
+ uids = e_mail_reader_get_selected_uids (reader);
|
||
+ if (!uids)
|
||
+ return;
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+
|
||
+ camel_folder_freeze (folder);
|
||
+ for (ii = 0; ii < uids->len; ii++) {
|
||
+ if (gtk_toggle_action_get_active (action))
|
||
+ camel_folder_set_message_user_flag (
|
||
+ folder, uids->pdata[ii], tag, TRUE);
|
||
+ else {
|
||
+ camel_folder_set_message_user_flag (
|
||
+ folder, uids->pdata[ii], tag, FALSE);
|
||
+ camel_folder_set_message_user_tag (
|
||
+ folder, uids->pdata[ii], "label", NULL);
|
||
+ }
|
||
+ }
|
||
+ camel_folder_thaw (folder);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ g_ptr_array_unref (uids);
|
||
+}
|
||
+
|
||
+#define LABEL_UNKNOWN 0
|
||
+#define LABEL_EXISTS (1 << 0)
|
||
+#define LABEL_NOTEXIST (1 << 1)
|
||
+
|
||
+static GHashTable *
|
||
+mail_reader_gather_labels_info (EMailReader *reader,
|
||
+ EMailLabelListStore *label_store,
|
||
+ GPtrArray *uids)
|
||
+{
|
||
+ GHashTable *labels_info;
|
||
+ CamelFolder *folder;
|
||
+ GtkTreeIter iter;
|
||
+ GtkTreeModel *model;
|
||
+ gboolean valid;
|
||
+ guint ii;
|
||
+
|
||
+ labels_info = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||
+
|
||
+ model = GTK_TREE_MODEL (label_store);
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+
|
||
+ if (!folder)
|
||
+ return labels_info;
|
||
+
|
||
+ for (ii = 0; ii < uids->len; ii++) {
|
||
+ CamelMessageInfo *info;
|
||
+
|
||
+ info = camel_folder_get_message_info (folder, uids->pdata[ii]);
|
||
+ if (!info)
|
||
+ continue;
|
||
+
|
||
+ for (valid = gtk_tree_model_get_iter_first (model, &iter);
|
||
+ valid;
|
||
+ valid = gtk_tree_model_iter_next (model, &iter)) {
|
||
+ gchar *tag;
|
||
+ guint value;
|
||
+
|
||
+ tag = e_mail_label_list_store_get_tag (label_store, &iter);
|
||
+ value = GPOINTER_TO_UINT (g_hash_table_lookup (labels_info, tag));
|
||
+ if ((!(value & LABEL_EXISTS)) || (!(value & LABEL_NOTEXIST))) {
|
||
+ gboolean exists = FALSE, notexist = FALSE;
|
||
+
|
||
+ /* Check for new-style labels. */
|
||
+ if (camel_message_info_get_user_flag (info, tag)) {
|
||
+ exists = TRUE;
|
||
+ } else {
|
||
+ /* Check for old-style labels. */
|
||
+ const gchar *old_label = camel_message_info_get_user_tag (info, "label");
|
||
+ if (old_label) {
|
||
+ gchar *new_label;
|
||
+
|
||
+ /* Convert old-style labels ("<name>") to "$Label<name>". */
|
||
+ new_label = g_alloca (strlen (old_label) + 10);
|
||
+ g_stpcpy (g_stpcpy (new_label, "$Label"), old_label);
|
||
+
|
||
+ if (g_strcmp0 (new_label, tag) == 0)
|
||
+ exists = TRUE;
|
||
+ else
|
||
+ notexist = TRUE;
|
||
+ } else {
|
||
+ notexist = TRUE;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ value = value |
|
||
+ (exists ? LABEL_EXISTS : LABEL_UNKNOWN) |
|
||
+ (notexist ? LABEL_NOTEXIST : LABEL_UNKNOWN);
|
||
+
|
||
+ g_hash_table_insert (labels_info, tag, GUINT_TO_POINTER (value));
|
||
+
|
||
+ /* the hash table took the 'tag' */
|
||
+ tag = NULL;
|
||
+ }
|
||
+
|
||
+ g_free (tag);
|
||
+ }
|
||
+
|
||
+ g_clear_object (&info);
|
||
+ }
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+
|
||
+ return labels_info;
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_update_label_action (GtkToggleAction *action,
|
||
+ GHashTable *labels_info, /* gchar * ~> guint */
|
||
+ const gchar *label_tag)
|
||
+{
|
||
+ gboolean exists = FALSE;
|
||
+ gboolean not_exists = FALSE;
|
||
+ gboolean sensitive;
|
||
+ guint value;
|
||
+
|
||
+ /* Figure out the proper label action state for the selected
|
||
+ * messages. If all the selected messages have the given label,
|
||
+ * make the toggle action active. If all the selected message
|
||
+ * DO NOT have the given label, make the toggle action inactive.
|
||
+ * If some do and some don't, make the action insensitive. */
|
||
+
|
||
+ value = GPOINTER_TO_UINT (g_hash_table_lookup (labels_info, label_tag));
|
||
+ exists = (value & LABEL_EXISTS) != 0;
|
||
+ not_exists = (value & LABEL_NOTEXIST) != 0;
|
||
+
|
||
+ sensitive = !(exists && not_exists);
|
||
+ gtk_toggle_action_set_active (action, exists);
|
||
+ gtk_action_set_sensitive (GTK_ACTION (action), sensitive);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_update_labels_menu (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+ EMailLabelListStore *label_store;
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+ GtkWindow *window;
|
||
+ GtkUIManager *ui_manager = NULL;
|
||
+ GtkActionGroup *action_group;
|
||
+ GtkTreeIter iter;
|
||
+ GHashTable *labels_info; /* gchar * ~> guint { LABEL_EXISTS | LABEL_NOTEXIST | LABEL_UNKNOWN } */
|
||
+ GPtrArray *uids;
|
||
+ const gchar *main_menu_path, *popup_menu_path;
|
||
+ gboolean valid;
|
||
+ gint ii = 0;
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ window = e_mail_reader_get_window (reader);
|
||
+ g_return_if_fail (window != NULL);
|
||
+
|
||
+ if (E_IS_SHELL_WINDOW (window))
|
||
+ ui_manager = e_shell_window_get_ui_manager (E_SHELL_WINDOW (window));
|
||
+ else if (E_IS_MAIL_BROWSER (window))
|
||
+ ui_manager = e_mail_browser_get_ui_manager (E_MAIL_BROWSER (window));
|
||
+
|
||
+ g_return_if_fail (ui_manager != NULL);
|
||
+ g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager));
|
||
+
|
||
+ backend = e_mail_reader_get_backend (reader);
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+ label_store = e_mail_ui_session_get_label_store (E_MAIL_UI_SESSION (session));
|
||
+
|
||
+ action_group = e_mail_reader_get_action_group (reader, E_MAIL_READER_ACTION_GROUP_LABELS);
|
||
+ main_menu_path = "/main-menu/custom-menus/mail-message-menu/mail-mark-as-menu/mail-label-menu/mail-label-actions";
|
||
+ popup_menu_path = "/mail-message-popup/mail-label-menu/mail-label-actions";
|
||
+
|
||
+ /* Unmerge the previous menu items. */
|
||
+ if (priv->main_menu_label_merge_id)
|
||
+ gtk_ui_manager_remove_ui (ui_manager, priv->main_menu_label_merge_id);
|
||
+ else
|
||
+ priv->main_menu_label_merge_id = gtk_ui_manager_new_merge_id (ui_manager);
|
||
+
|
||
+ if (priv->popup_menu_label_merge_id)
|
||
+ gtk_ui_manager_remove_ui (ui_manager, priv->popup_menu_label_merge_id);
|
||
+ else
|
||
+ priv->popup_menu_label_merge_id = gtk_ui_manager_new_merge_id (ui_manager);
|
||
+
|
||
+ e_action_group_remove_all_actions (action_group);
|
||
+ gtk_ui_manager_ensure_update (ui_manager);
|
||
+
|
||
+ uids = e_mail_reader_get_selected_uids (reader);
|
||
+ labels_info = mail_reader_gather_labels_info (reader, label_store, uids);
|
||
+
|
||
+ valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (label_store), &iter);
|
||
+
|
||
+ while (valid) {
|
||
+ EMailLabelAction *label_action;
|
||
+ GtkAction *action;
|
||
+ gchar *action_name;
|
||
+ gchar *stock_id;
|
||
+ gchar *label;
|
||
+ gchar *tag;
|
||
+
|
||
+ label = e_mail_label_list_store_get_name (label_store, &iter);
|
||
+ stock_id = e_mail_label_list_store_get_stock_id (label_store, &iter);
|
||
+ tag = e_mail_label_list_store_get_tag (label_store, &iter);
|
||
+ action_name = g_strdup_printf ("mail-label-%d", ii);
|
||
+
|
||
+ /* XXX Add a tooltip! */
|
||
+ label_action = e_mail_label_action_new (action_name, label, NULL, stock_id);
|
||
+
|
||
+ g_object_set_data_full (
|
||
+ G_OBJECT (label_action), "tag",
|
||
+ tag, (GDestroyNotify) g_free);
|
||
+
|
||
+ /* Configure the action before we connect to signals. */
|
||
+ mail_reader_update_label_action (GTK_TOGGLE_ACTION (label_action), labels_info, tag);
|
||
+
|
||
+ g_signal_connect (
|
||
+ label_action, "toggled",
|
||
+ G_CALLBACK (action_mail_label_cb), reader);
|
||
+
|
||
+ /* The action group takes ownership of the action. */
|
||
+ action = GTK_ACTION (label_action);
|
||
+
|
||
+ if (ii + 1 < 10) {
|
||
+ gchar accel[5];
|
||
+
|
||
+ accel[0] = '1' + ii;
|
||
+ accel[1] = '\0';
|
||
+
|
||
+ gtk_action_group_add_action_with_accel (action_group, action, accel);
|
||
+ } else {
|
||
+ gtk_action_group_add_action (action_group, action);
|
||
+ }
|
||
+ g_object_unref (label_action);
|
||
+
|
||
+ gtk_ui_manager_add_ui (
|
||
+ ui_manager, priv->main_menu_label_merge_id, main_menu_path,
|
||
+ action_name, action_name, GTK_UI_MANAGER_AUTO, FALSE);
|
||
+
|
||
+ gtk_ui_manager_add_ui (
|
||
+ ui_manager, priv->popup_menu_label_merge_id, popup_menu_path,
|
||
+ action_name, action_name, GTK_UI_MANAGER_AUTO, FALSE);
|
||
+
|
||
+ g_free (label);
|
||
+ g_free (stock_id);
|
||
+ g_free (action_name);
|
||
+
|
||
+ valid = gtk_tree_model_iter_next (
|
||
+ GTK_TREE_MODEL (label_store), &iter);
|
||
+ ii++;
|
||
+ }
|
||
+
|
||
+ g_hash_table_destroy (labels_info);
|
||
+ g_ptr_array_unref (uids);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_update_actions (EMailReader *reader,
|
||
+ guint32 state)
|
||
+{
|
||
+ GtkAction *action;
|
||
+ const gchar *action_name;
|
||
+ gboolean sensitive;
|
||
+ EMailDisplay *mail_display;
|
||
+
|
||
+ /* Be descriptive. */
|
||
+ gboolean any_messages_selected;
|
||
+ gboolean enable_flag_clear;
|
||
+ gboolean enable_flag_completed;
|
||
+ gboolean have_enabled_account;
|
||
+ gboolean multiple_messages_selected;
|
||
+ gboolean selection_has_attachment_messages;
|
||
+ gboolean selection_has_deleted_messages;
|
||
+ gboolean selection_has_ignore_thread_messages;
|
||
+ gboolean selection_has_notignore_thread_messages;
|
||
+ gboolean selection_has_important_messages;
|
||
+ gboolean selection_has_junk_messages;
|
||
+ gboolean selection_has_not_junk_messages;
|
||
+ gboolean selection_has_read_messages;
|
||
+ gboolean selection_has_undeleted_messages;
|
||
+ gboolean selection_has_unimportant_messages;
|
||
+ gboolean selection_has_unread_messages;
|
||
+ gboolean selection_has_mail_note;
|
||
+ gboolean selection_has_color;
|
||
+ gboolean selection_is_mailing_list;
|
||
+ gboolean single_message_selected;
|
||
+ gboolean first_message_selected = FALSE;
|
||
+ gboolean last_message_selected = FALSE;
|
||
+
|
||
+ have_enabled_account =
|
||
+ (state & E_MAIL_READER_HAVE_ENABLED_ACCOUNT);
|
||
+ single_message_selected =
|
||
+ (state & E_MAIL_READER_SELECTION_SINGLE);
|
||
+ multiple_messages_selected =
|
||
+ (state & E_MAIL_READER_SELECTION_MULTIPLE);
|
||
+ /* FIXME Missing CAN_ADD_SENDER */
|
||
+ enable_flag_clear =
|
||
+ (state & E_MAIL_READER_SELECTION_FLAG_CLEAR);
|
||
+ enable_flag_completed =
|
||
+ (state & E_MAIL_READER_SELECTION_FLAG_COMPLETED);
|
||
+ selection_has_attachment_messages =
|
||
+ (state & E_MAIL_READER_SELECTION_HAS_ATTACHMENTS);
|
||
+ selection_has_deleted_messages =
|
||
+ (state & E_MAIL_READER_SELECTION_HAS_DELETED);
|
||
+ selection_has_ignore_thread_messages =
|
||
+ (state & E_MAIL_READER_SELECTION_HAS_IGNORE_THREAD);
|
||
+ selection_has_notignore_thread_messages =
|
||
+ (state & E_MAIL_READER_SELECTION_HAS_NOTIGNORE_THREAD);
|
||
+ selection_has_important_messages =
|
||
+ (state & E_MAIL_READER_SELECTION_HAS_IMPORTANT);
|
||
+ selection_has_junk_messages =
|
||
+ (state & E_MAIL_READER_SELECTION_HAS_JUNK);
|
||
+ selection_has_not_junk_messages =
|
||
+ (state & E_MAIL_READER_SELECTION_HAS_NOT_JUNK);
|
||
+ selection_has_read_messages =
|
||
+ (state & E_MAIL_READER_SELECTION_HAS_READ);
|
||
+ selection_has_undeleted_messages =
|
||
+ (state & E_MAIL_READER_SELECTION_HAS_UNDELETED);
|
||
+ selection_has_unimportant_messages =
|
||
+ (state & E_MAIL_READER_SELECTION_HAS_UNIMPORTANT);
|
||
+ selection_has_unread_messages =
|
||
+ (state & E_MAIL_READER_SELECTION_HAS_UNREAD);
|
||
+ selection_has_mail_note =
|
||
+ (state & E_MAIL_READER_SELECTION_HAS_MAIL_NOTE);
|
||
+ selection_has_color =
|
||
+ (state & E_MAIL_READER_SELECTION_HAS_COLOR);
|
||
+ selection_is_mailing_list =
|
||
+ (state & E_MAIL_READER_SELECTION_IS_MAILING_LIST);
|
||
+
|
||
+ any_messages_selected =
|
||
+ (single_message_selected || multiple_messages_selected);
|
||
+
|
||
+ mail_display = e_mail_reader_get_mail_display (reader);
|
||
+
|
||
+ if (any_messages_selected) {
|
||
+ MessageList *message_list;
|
||
+ gint row = -1, count = -1;
|
||
+ ETreeTableAdapter *etta;
|
||
+ ETreePath node = NULL;
|
||
+
|
||
+ message_list = MESSAGE_LIST (
|
||
+ e_mail_reader_get_message_list (reader));
|
||
+ etta = e_tree_get_table_adapter (E_TREE (message_list));
|
||
+
|
||
+ if (message_list->cursor_uid != NULL)
|
||
+ node = g_hash_table_lookup (
|
||
+ message_list->uid_nodemap,
|
||
+ message_list->cursor_uid);
|
||
+
|
||
+ if (node != NULL) {
|
||
+ row = e_tree_table_adapter_row_of_node (etta, node);
|
||
+ count = e_table_model_row_count (E_TABLE_MODEL (etta));
|
||
+ }
|
||
+
|
||
+ first_message_selected = row <= 0;
|
||
+ last_message_selected = row < 0 || row + 1 >= count;
|
||
+ }
|
||
+
|
||
+ action_name = "mail-add-sender";
|
||
+ sensitive = single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-archive";
|
||
+ sensitive = any_messages_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-check-for-junk";
|
||
+ sensitive = any_messages_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-color-assign";
|
||
+ sensitive = any_messages_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-color-unset";
|
||
+ sensitive = any_messages_selected && selection_has_color;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-copy";
|
||
+ sensitive = any_messages_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-create-menu";
|
||
+ sensitive = single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ /* If a single message is selected, let the user hit delete to
|
||
+ * advance the cursor even if the message is already deleted. */
|
||
+ action_name = "mail-delete";
|
||
+ sensitive =
|
||
+ (single_message_selected ||
|
||
+ selection_has_undeleted_messages) &&
|
||
+ (state & E_MAIL_READER_FOLDER_IS_VTRASH) == 0;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-add-note";
|
||
+ sensitive = single_message_selected && !selection_has_mail_note;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+ gtk_action_set_visible (action, sensitive);
|
||
+
|
||
+ action_name = "mail-edit-note";
|
||
+ sensitive = single_message_selected && selection_has_mail_note;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+ gtk_action_set_visible (action, sensitive);
|
||
+
|
||
+ action_name = "mail-delete-note";
|
||
+ sensitive = single_message_selected && selection_has_mail_note;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+ gtk_action_set_visible (action, sensitive);
|
||
+
|
||
+ action_name = "mail-filters-apply";
|
||
+ sensitive = any_messages_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-filter-rule-for-mailing-list";
|
||
+ sensitive = single_message_selected && selection_is_mailing_list;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-find";
|
||
+ sensitive = single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-flag-clear";
|
||
+ sensitive = enable_flag_clear;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-flag-completed";
|
||
+ sensitive = enable_flag_completed;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-flag-for-followup";
|
||
+ sensitive = any_messages_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-forward";
|
||
+ sensitive = have_enabled_account && any_messages_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-forward-attached";
|
||
+ sensitive = have_enabled_account && any_messages_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-forward-attached-full";
|
||
+ sensitive = have_enabled_account && any_messages_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-forward-as-menu";
|
||
+ sensitive = have_enabled_account && any_messages_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-forward-inline";
|
||
+ sensitive = have_enabled_account && single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-forward-inline-full";
|
||
+ sensitive = have_enabled_account && single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-forward-quoted";
|
||
+ sensitive = have_enabled_account && single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-forward-quoted-full";
|
||
+ sensitive = have_enabled_account && single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-goto-menu";
|
||
+ sensitive = TRUE;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-load-images";
|
||
+ sensitive = single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-mark-as-menu";
|
||
+ sensitive = any_messages_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-mark-ignore-thread-sub";
|
||
+ sensitive = selection_has_notignore_thread_messages;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+ gtk_action_set_visible (action, sensitive);
|
||
+
|
||
+ action_name = "mail-mark-ignore-thread-whole";
|
||
+ sensitive = selection_has_notignore_thread_messages;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+ gtk_action_set_visible (action, sensitive);
|
||
+
|
||
+ action_name = "mail-mark-important";
|
||
+ sensitive = selection_has_unimportant_messages;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-mark-junk";
|
||
+ sensitive = selection_has_not_junk_messages;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-mark-notjunk";
|
||
+ sensitive = selection_has_junk_messages;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-mark-read";
|
||
+ sensitive = selection_has_unread_messages;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-mark-unignore-thread-sub";
|
||
+ sensitive = selection_has_ignore_thread_messages;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+ gtk_action_set_visible (action, sensitive);
|
||
+
|
||
+ action_name = "mail-mark-unignore-thread-whole";
|
||
+ sensitive = selection_has_ignore_thread_messages;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+ gtk_action_set_visible (action, sensitive);
|
||
+
|
||
+ action_name = "mail-mark-unimportant";
|
||
+ sensitive = selection_has_important_messages;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-mark-unread";
|
||
+ sensitive = selection_has_read_messages;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-message-edit";
|
||
+ sensitive = have_enabled_account && single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-message-new";
|
||
+ sensitive = have_enabled_account;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-message-open";
|
||
+ sensitive = any_messages_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-move";
|
||
+ sensitive = any_messages_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-next";
|
||
+ sensitive = any_messages_selected && !last_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-next-important";
|
||
+ sensitive = single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-next-thread";
|
||
+ sensitive = single_message_selected && !last_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-next-unread";
|
||
+ sensitive = TRUE;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-previous";
|
||
+ sensitive = any_messages_selected && !first_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-previous-important";
|
||
+ sensitive = single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-previous-unread";
|
||
+ sensitive = TRUE;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-previous-thread";
|
||
+ sensitive = any_messages_selected && !first_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-print";
|
||
+ sensitive = single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-print-preview";
|
||
+ sensitive = single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-redirect";
|
||
+ sensitive = have_enabled_account && single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-remove-attachments";
|
||
+ sensitive = any_messages_selected && selection_has_attachment_messages;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-remove-duplicates";
|
||
+ sensitive = multiple_messages_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-reply-all";
|
||
+ sensitive = have_enabled_account && single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-reply-alternative";
|
||
+ sensitive = have_enabled_account && single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-reply-group";
|
||
+ sensitive = have_enabled_account && single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-reply-group-menu";
|
||
+ sensitive = have_enabled_account && any_messages_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-reply-list";
|
||
+ sensitive = have_enabled_account && single_message_selected &&
|
||
+ selection_is_mailing_list;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-reply-sender";
|
||
+ sensitive = have_enabled_account && single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-save-as";
|
||
+ sensitive = any_messages_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-show-source";
|
||
+ sensitive = single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-undelete";
|
||
+ sensitive = selection_has_deleted_messages;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-zoom-100";
|
||
+ sensitive = single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-zoom-in";
|
||
+ sensitive = single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action_name = "mail-zoom-out";
|
||
+ sensitive = single_message_selected;
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_sensitive (action, sensitive);
|
||
+
|
||
+ action = e_mail_reader_get_action (reader, "mail-search-web");
|
||
+ gtk_action_set_sensitive (action, single_message_selected &&
|
||
+ mail_display && e_web_view_has_selection (E_WEB_VIEW (mail_display)));
|
||
+
|
||
+ mail_reader_update_labels_menu (reader);
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+mail_reader_close_on_delete_or_junk (EMailReader *reader)
|
||
+{
|
||
+ return FALSE;
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_init_charset_actions (EMailReader *reader,
|
||
+ GtkActionGroup *action_group)
|
||
+{
|
||
+ GtkRadioAction *default_action;
|
||
+ GSList *radio_group;
|
||
+
|
||
+ radio_group = e_charset_add_radio_actions (
|
||
+ action_group, "mail-charset-", NULL,
|
||
+ G_CALLBACK (action_mail_charset_cb), reader);
|
||
+
|
||
+ /* XXX Add a tooltip! */
|
||
+ default_action = gtk_radio_action_new (
|
||
+ "mail-charset-default", _("Default"), NULL, NULL, -1);
|
||
+
|
||
+ gtk_radio_action_set_group (default_action, radio_group);
|
||
+
|
||
+ g_signal_connect (
|
||
+ default_action, "changed",
|
||
+ G_CALLBACK (action_mail_charset_cb), reader);
|
||
+
|
||
+ gtk_action_group_add_action (
|
||
+ action_group, GTK_ACTION (default_action));
|
||
+
|
||
+ gtk_radio_action_set_current_value (default_action, -1);
|
||
+}
|
||
+
|
||
+static void
|
||
+e_mail_reader_default_init (EMailReaderInterface *iface)
|
||
+{
|
||
+ quark_private = g_quark_from_static_string ("e-mail-reader-private");
|
||
+
|
||
+ iface->get_alert_sink = mail_reader_get_alert_sink;
|
||
+ iface->get_selected_uids = mail_reader_get_selected_uids;
|
||
+ iface->get_selected_uids_with_collapsed_threads = mail_reader_get_selected_uids_with_collapsed_threads;
|
||
+ iface->ref_folder = mail_reader_ref_folder;
|
||
+ iface->set_folder = mail_reader_set_folder;
|
||
+ iface->set_message = mail_reader_set_message;
|
||
+ iface->open_selected_mail = e_mail_reader_open_selected;
|
||
+ iface->folder_loaded = mail_reader_folder_loaded;
|
||
+ iface->message_loaded = mail_reader_message_loaded;
|
||
+ iface->message_seen = mail_reader_message_seen;
|
||
+ iface->show_search_bar = mail_reader_show_search_bar;
|
||
+ iface->update_actions = mail_reader_update_actions;
|
||
+ iface->close_on_delete_or_junk = mail_reader_close_on_delete_or_junk;
|
||
+ iface->reload = mail_reader_reload;
|
||
+ iface->remove_ui = mail_reader_remove_ui;
|
||
+
|
||
+ g_object_interface_install_property (
|
||
+ iface,
|
||
+ g_param_spec_enum (
|
||
+ "forward-style",
|
||
+ "Forward Style",
|
||
+ "How to forward messages",
|
||
+ E_TYPE_MAIL_FORWARD_STYLE,
|
||
+ E_MAIL_FORWARD_STYLE_ATTACHED,
|
||
+ G_PARAM_READWRITE));
|
||
+
|
||
+ g_object_interface_install_property (
|
||
+ iface,
|
||
+ g_param_spec_boolean (
|
||
+ "group-by-threads",
|
||
+ "Group by Threads",
|
||
+ "Whether to group messages by threads",
|
||
+ FALSE,
|
||
+ G_PARAM_READWRITE));
|
||
+
|
||
+ g_object_interface_install_property (
|
||
+ iface,
|
||
+ g_param_spec_enum (
|
||
+ "reply-style",
|
||
+ "Reply Style",
|
||
+ "How to reply to messages",
|
||
+ E_TYPE_MAIL_REPLY_STYLE,
|
||
+ E_MAIL_REPLY_STYLE_QUOTED,
|
||
+ G_PARAM_READWRITE));
|
||
+
|
||
+ g_object_interface_install_property (
|
||
+ iface,
|
||
+ g_param_spec_boolean (
|
||
+ "mark-seen-always",
|
||
+ "Mark Seen Always",
|
||
+ "Whether to mark unread message seen even after folder change",
|
||
+ FALSE,
|
||
+ G_PARAM_READWRITE));
|
||
+
|
||
+ g_object_interface_install_property (
|
||
+ iface,
|
||
+ g_param_spec_boolean (
|
||
+ "delete-selects-previous",
|
||
+ "Delete Selects Previous",
|
||
+ "Whether go to the previous message after message deletion",
|
||
+ FALSE,
|
||
+ G_PARAM_READWRITE));
|
||
+
|
||
+ signals[CHANGED] = g_signal_new (
|
||
+ "changed",
|
||
+ G_OBJECT_CLASS_TYPE (iface),
|
||
+ G_SIGNAL_RUN_FIRST,
|
||
+ 0, NULL, NULL,
|
||
+ g_cclosure_marshal_VOID__VOID,
|
||
+ G_TYPE_NONE, 0);
|
||
+
|
||
+ signals[COMPOSER_CREATED] = g_signal_new (
|
||
+ "composer-created",
|
||
+ G_OBJECT_CLASS_TYPE (iface),
|
||
+ G_SIGNAL_RUN_FIRST,
|
||
+ G_STRUCT_OFFSET (EMailReaderInterface, composer_created),
|
||
+ NULL, NULL, NULL,
|
||
+ G_TYPE_NONE, 2,
|
||
+ E_TYPE_MSG_COMPOSER,
|
||
+ CAMEL_TYPE_MIME_MESSAGE);
|
||
+
|
||
+ signals[FOLDER_LOADED] = g_signal_new (
|
||
+ "folder-loaded",
|
||
+ G_OBJECT_CLASS_TYPE (iface),
|
||
+ G_SIGNAL_RUN_FIRST,
|
||
+ G_STRUCT_OFFSET (EMailReaderInterface, folder_loaded),
|
||
+ NULL, NULL,
|
||
+ g_cclosure_marshal_VOID__VOID,
|
||
+ G_TYPE_NONE, 0);
|
||
+
|
||
+ signals[MESSAGE_LOADED] = g_signal_new (
|
||
+ "message-loaded",
|
||
+ G_OBJECT_CLASS_TYPE (iface),
|
||
+ G_SIGNAL_RUN_LAST,
|
||
+ G_STRUCT_OFFSET (EMailReaderInterface, message_loaded),
|
||
+ NULL, NULL,
|
||
+ e_marshal_VOID__STRING_OBJECT,
|
||
+ G_TYPE_NONE, 2,
|
||
+ G_TYPE_STRING,
|
||
+ CAMEL_TYPE_MIME_MESSAGE);
|
||
+
|
||
+ signals[MESSAGE_SEEN] = g_signal_new (
|
||
+ "message-seen",
|
||
+ G_OBJECT_CLASS_TYPE (iface),
|
||
+ G_SIGNAL_RUN_LAST,
|
||
+ G_STRUCT_OFFSET (EMailReaderInterface, message_seen),
|
||
+ NULL, NULL,
|
||
+ e_marshal_VOID__STRING_OBJECT,
|
||
+ G_TYPE_NONE, 2,
|
||
+ G_TYPE_STRING,
|
||
+ CAMEL_TYPE_MIME_MESSAGE);
|
||
+
|
||
+ signals[SHOW_SEARCH_BAR] = g_signal_new (
|
||
+ "show-search-bar",
|
||
+ G_OBJECT_CLASS_TYPE (iface),
|
||
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
|
||
+ G_STRUCT_OFFSET (EMailReaderInterface, show_search_bar),
|
||
+ NULL, NULL,
|
||
+ g_cclosure_marshal_VOID__VOID,
|
||
+ G_TYPE_NONE, 0);
|
||
+
|
||
+ signals[UPDATE_ACTIONS] = g_signal_new (
|
||
+ "update-actions",
|
||
+ G_OBJECT_CLASS_TYPE (iface),
|
||
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
|
||
+ G_STRUCT_OFFSET (EMailReaderInterface, update_actions),
|
||
+ NULL, NULL,
|
||
+ g_cclosure_marshal_VOID__UINT,
|
||
+ G_TYPE_NONE, 1,
|
||
+ G_TYPE_UINT);
|
||
+}
|
||
+
|
||
+void
|
||
+e_mail_reader_init (EMailReader *reader,
|
||
+ gboolean init_actions,
|
||
+ gboolean connect_signals)
|
||
+{
|
||
+ GtkActionGroup *action_group;
|
||
+ GtkWidget *message_list;
|
||
+ GtkAction *action;
|
||
+ const gchar *action_name;
|
||
+ EMailDisplay *display;
|
||
+ EMenuToolAction *menu_tool_action;
|
||
+ GSettings *settings;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+ display = e_mail_reader_get_mail_display (reader);
|
||
+
|
||
+ /* Initialize a private struct. */
|
||
+ g_object_set_qdata_full (
|
||
+ G_OBJECT (reader), quark_private,
|
||
+ g_slice_new0 (EMailReaderPrivate),
|
||
+ (GDestroyNotify) mail_reader_private_free);
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ reader, "group-by-threads",
|
||
+ message_list, "group-by-threads",
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ if (!init_actions)
|
||
+ goto connect_signals;
|
||
+
|
||
+ /* Add the "standard" EMailReader actions. */
|
||
+
|
||
+ action_group = e_mail_reader_get_action_group (
|
||
+ reader, E_MAIL_READER_ACTION_GROUP_STANDARD);
|
||
+
|
||
+ gtk_action_group_add_actions (
|
||
+ action_group, mail_reader_entries,
|
||
+ G_N_ELEMENTS (mail_reader_entries), reader);
|
||
+ e_action_group_add_popup_actions (
|
||
+ action_group, mail_reader_popup_entries,
|
||
+ G_N_ELEMENTS (mail_reader_popup_entries));
|
||
+ gtk_action_group_add_toggle_actions (
|
||
+ action_group, mail_reader_toggle_entries,
|
||
+ G_N_ELEMENTS (mail_reader_toggle_entries), reader);
|
||
+
|
||
+ mail_reader_init_charset_actions (reader, action_group);
|
||
+
|
||
+
|
||
+ /* The "mail-forward" action is special: it uses a GtkMenuToolButton
|
||
+ * for its toolbar item type. So we have to create it separately. */
|
||
+
|
||
+ menu_tool_action = e_menu_tool_action_new (
|
||
+ "toolbar-mail-forward", _("_Forward"),
|
||
+ _("Forward the selected message to someone"));
|
||
+
|
||
+ gtk_action_set_icon_name (GTK_ACTION (menu_tool_action), "mail-forward");
|
||
+ gtk_action_set_visible (GTK_ACTION (menu_tool_action), !e_util_get_use_header_bar ());
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ e_mail_reader_get_action (reader, "mail-forward"), "sensitive",
|
||
+ menu_tool_action, "sensitive",
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ g_signal_connect (
|
||
+ menu_tool_action, "activate",
|
||
+ G_CALLBACK (action_mail_forward_cb), reader);
|
||
+
|
||
+ gtk_action_group_add_action_with_accel (
|
||
+ action_group, GTK_ACTION (menu_tool_action), "<Control>f");
|
||
+
|
||
+ /* Likewise the "mail-reply-group" action. */
|
||
+
|
||
+ menu_tool_action = e_menu_tool_action_new (
|
||
+ /* Translators: "Group Reply" will reply either to a mailing list
|
||
+ * (if possible and if that configuration option is enabled), or else
|
||
+ * it will reply to all. The word "Group" was chosen because it covers
|
||
+ * either of those, without too strongly implying one or the other. */
|
||
+ "toolbar-mail-reply-group", _("Group Reply"),
|
||
+ _("Reply to the mailing list, or to all recipients"));
|
||
+
|
||
+ gtk_action_set_icon_name (GTK_ACTION (menu_tool_action), "mail-reply-all");
|
||
+ gtk_action_set_visible (GTK_ACTION (menu_tool_action), !e_util_get_use_header_bar ());
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ e_mail_reader_get_action (reader, "mail-reply-group"), "sensitive",
|
||
+ menu_tool_action, "sensitive",
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ g_signal_connect (
|
||
+ menu_tool_action, "activate",
|
||
+ G_CALLBACK (action_mail_reply_group_cb), reader);
|
||
+
|
||
+ gtk_action_group_add_action_with_accel (
|
||
+ action_group, GTK_ACTION (menu_tool_action), "<Control>g");
|
||
+
|
||
+ /* Add EMailReader actions for Search Folders. The action group
|
||
+ * should be made invisible if Search Folders are disabled. */
|
||
+
|
||
+ action_group = e_mail_reader_get_action_group (
|
||
+ reader, E_MAIL_READER_ACTION_GROUP_SEARCH_FOLDERS);
|
||
+
|
||
+ gtk_action_group_add_actions (
|
||
+ action_group, mail_reader_search_folder_entries,
|
||
+ G_N_ELEMENTS (mail_reader_search_folder_entries), reader);
|
||
+
|
||
+ display = e_mail_reader_get_mail_display (reader);
|
||
+
|
||
+ /* Bind GObject properties to GSettings keys. */
|
||
+
|
||
+ settings = e_util_ref_settings ("org.gnome.evolution.mail");
|
||
+
|
||
+ action_name = "mail-caret-mode";
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ g_settings_bind (
|
||
+ settings, "caret-mode",
|
||
+ action, "active", G_SETTINGS_BIND_DEFAULT);
|
||
+
|
||
+ action_name = "mail-show-all-headers";
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ g_settings_bind (
|
||
+ settings, "show-all-headers",
|
||
+ action, "active", G_SETTINGS_BIND_DEFAULT);
|
||
+
|
||
+ /* Mode change when viewing message source is ignored. */
|
||
+ if (e_mail_display_get_mode (display) == E_MAIL_FORMATTER_MODE_SOURCE ||
|
||
+ e_mail_display_get_mode (display) == E_MAIL_FORMATTER_MODE_RAW) {
|
||
+ gtk_action_set_sensitive (action, FALSE);
|
||
+ gtk_action_set_visible (action, FALSE);
|
||
+ }
|
||
+
|
||
+ g_object_unref (settings);
|
||
+
|
||
+ /* Fine tuning. */
|
||
+
|
||
+ action_name = "mail-delete";
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_short_label (action, _("Delete"));
|
||
+
|
||
+ action_name = "toolbar-mail-forward";
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_is_important (action, TRUE);
|
||
+
|
||
+ action_name = "toolbar-mail-reply-group";
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_is_important (action, TRUE);
|
||
+
|
||
+ action_name = "mail-next";
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_short_label (action, _("Next"));
|
||
+
|
||
+ action_name = "mail-previous";
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_short_label (action, _("Previous"));
|
||
+
|
||
+ action_name = "mail-reply-all";
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_is_important (action, TRUE);
|
||
+
|
||
+ action_name = "mail-reply-sender";
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ gtk_action_set_is_important (action, TRUE);
|
||
+ gtk_action_set_short_label (action, _("Reply"));
|
||
+
|
||
+ action_name = "add-to-address-book";
|
||
+ action = e_mail_display_get_action (display, action_name);
|
||
+ g_signal_connect (
|
||
+ action, "activate",
|
||
+ G_CALLBACK (action_add_to_address_book_cb), reader);
|
||
+
|
||
+ action_name = "send-reply";
|
||
+ action = e_mail_display_get_action (display, action_name);
|
||
+ g_signal_connect (
|
||
+ action, "activate",
|
||
+ G_CALLBACK (action_mail_reply_recipient_cb), reader);
|
||
+
|
||
+ action_name = "search-folder-recipient";
|
||
+ action = e_mail_display_get_action (display, action_name);
|
||
+ g_signal_connect (
|
||
+ action, "activate",
|
||
+ G_CALLBACK (action_search_folder_recipient_cb), reader);
|
||
+
|
||
+ action_name = "search-folder-sender";
|
||
+ action = e_mail_display_get_action (display, action_name);
|
||
+ g_signal_connect (
|
||
+ action, "activate",
|
||
+ G_CALLBACK (action_search_folder_sender_cb), reader);
|
||
+
|
||
+#ifndef G_OS_WIN32
|
||
+ /* Lockdown integration. */
|
||
+
|
||
+ settings = e_util_ref_settings ("org.gnome.desktop.lockdown");
|
||
+
|
||
+ action_name = "mail-print";
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ g_settings_bind (
|
||
+ settings, "disable-printing",
|
||
+ action, "visible",
|
||
+ G_SETTINGS_BIND_GET |
|
||
+ G_SETTINGS_BIND_NO_SENSITIVITY |
|
||
+ G_SETTINGS_BIND_INVERT_BOOLEAN);
|
||
+
|
||
+ action_name = "mail-print-preview";
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ g_settings_bind (
|
||
+ settings, "disable-printing",
|
||
+ action, "visible",
|
||
+ G_SETTINGS_BIND_GET |
|
||
+ G_SETTINGS_BIND_NO_SENSITIVITY |
|
||
+ G_SETTINGS_BIND_INVERT_BOOLEAN);
|
||
+
|
||
+ action_name = "mail-save-as";
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ g_settings_bind (
|
||
+ settings, "disable-save-to-disk",
|
||
+ action, "visible",
|
||
+ G_SETTINGS_BIND_GET |
|
||
+ G_SETTINGS_BIND_NO_SENSITIVITY |
|
||
+ G_SETTINGS_BIND_INVERT_BOOLEAN);
|
||
+
|
||
+ g_object_unref (settings);
|
||
+#endif
|
||
+
|
||
+ /* Bind properties. */
|
||
+
|
||
+ action_name = "mail-caret-mode";
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ action, "active",
|
||
+ display, "caret-mode",
|
||
+ G_BINDING_BIDIRECTIONAL |
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+connect_signals:
|
||
+
|
||
+ if (!connect_signals)
|
||
+ return;
|
||
+
|
||
+ /* Connect signals. */
|
||
+ g_signal_connect_swapped (
|
||
+ display, "key-press-event",
|
||
+ G_CALLBACK (mail_reader_key_press_event_cb), reader);
|
||
+
|
||
+ g_signal_connect_swapped (
|
||
+ display, "load-changed",
|
||
+ G_CALLBACK (mail_reader_load_changed_cb), reader);
|
||
+
|
||
+ g_signal_connect_swapped (
|
||
+ display, "remote-content-clicked",
|
||
+ G_CALLBACK (mail_reader_remote_content_clicked_cb), reader);
|
||
+
|
||
+ g_signal_connect_swapped (
|
||
+ message_list, "message-selected",
|
||
+ G_CALLBACK (mail_reader_message_selected_cb), reader);
|
||
+
|
||
+ g_signal_connect_swapped (
|
||
+ message_list, "update-actions",
|
||
+ G_CALLBACK (mail_reader_message_list_suggest_update_actions_cb), reader);
|
||
+
|
||
+ /* re-schedule mark-as-seen,... */
|
||
+ g_signal_connect_swapped (
|
||
+ message_list, "cursor-change",
|
||
+ G_CALLBACK (mail_reader_message_cursor_change_cb), reader);
|
||
+
|
||
+ /* but do not mark-as-seen if... */
|
||
+ g_signal_connect_swapped (
|
||
+ message_list, "tree-drag-begin",
|
||
+ G_CALLBACK (discard_timeout_mark_seen_cb), reader);
|
||
+
|
||
+ g_signal_connect_swapped (
|
||
+ message_list, "tree-drag-end",
|
||
+ G_CALLBACK (discard_timeout_mark_seen_cb), reader);
|
||
+
|
||
+ g_signal_connect_swapped (
|
||
+ message_list, "right-click",
|
||
+ G_CALLBACK (discard_timeout_mark_seen_cb), reader);
|
||
+
|
||
+ g_signal_connect_swapped (
|
||
+ e_mail_reader_get_preview_pane (reader), "notify::visible",
|
||
+ G_CALLBACK (mail_reader_preview_pane_visible_changed_cb), reader);
|
||
+
|
||
+ g_signal_connect_after (
|
||
+ message_list, "message-list-built",
|
||
+ G_CALLBACK (mail_reader_message_list_built_cb), reader);
|
||
+
|
||
+ g_signal_connect_swapped (
|
||
+ message_list, "double-click",
|
||
+ G_CALLBACK (mail_reader_double_click_cb), reader);
|
||
+
|
||
+ g_signal_connect_swapped (
|
||
+ message_list, "key-press",
|
||
+ G_CALLBACK (mail_reader_key_press_cb), reader);
|
||
+
|
||
+ g_signal_connect_swapped (
|
||
+ message_list, "selection-change",
|
||
+ G_CALLBACK (e_mail_reader_changed), reader);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_reader_ongoing_operation_destroyed (gpointer user_data,
|
||
+ GObject *cancellable)
|
||
+{
|
||
+ EMailReader *reader = user_data;
|
||
+ EMailReaderPrivate *priv;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ priv->ongoing_operations = g_slist_remove (priv->ongoing_operations, cancellable);
|
||
+}
|
||
+
|
||
+void
|
||
+e_mail_reader_dispose (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+ EMailDisplay *mail_display;
|
||
+ GtkWidget *message_list;
|
||
+ GSList *ongoing_operations, *link;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ if (priv->message_selected_timeout_id > 0) {
|
||
+ g_source_remove (priv->message_selected_timeout_id);
|
||
+ priv->message_selected_timeout_id = 0;
|
||
+ }
|
||
+
|
||
+ if (priv->retrieving_message)
|
||
+ g_cancellable_cancel (priv->retrieving_message);
|
||
+
|
||
+ ongoing_operations = g_slist_copy_deep (priv->ongoing_operations, (GCopyFunc) g_object_ref, NULL);
|
||
+ g_slist_free (priv->ongoing_operations);
|
||
+ priv->ongoing_operations = NULL;
|
||
+
|
||
+ for (link = ongoing_operations; link; link = g_slist_next (link)) {
|
||
+ GCancellable *cancellable = link->data;
|
||
+
|
||
+ g_object_weak_unref (G_OBJECT (cancellable), mail_reader_ongoing_operation_destroyed, reader);
|
||
+
|
||
+ g_cancellable_cancel (cancellable);
|
||
+ }
|
||
+
|
||
+ g_slist_free_full (ongoing_operations, g_object_unref);
|
||
+
|
||
+ mail_display = e_mail_reader_get_mail_display (reader);
|
||
+ if (mail_display)
|
||
+ g_signal_handlers_disconnect_by_data (mail_display, reader);
|
||
+
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+ if (message_list)
|
||
+ g_signal_handlers_disconnect_by_data (message_list, reader);
|
||
+}
|
||
+
|
||
+void
|
||
+e_mail_reader_changed (EMailReader *reader)
|
||
+{
|
||
+ MessageList *message_list;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ g_signal_emit (reader, signals[CHANGED], 0);
|
||
+
|
||
+ message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
|
||
+
|
||
+ if (!message_list || message_list_selected_count (message_list) != 1)
|
||
+ mail_reader_remove_followup_alert (reader);
|
||
+}
|
||
+
|
||
+guint32
|
||
+e_mail_reader_check_state (EMailReader *reader)
|
||
+{
|
||
+ EShell *shell;
|
||
+ GPtrArray *uids;
|
||
+ CamelFolder *folder;
|
||
+ CamelStore *store = NULL;
|
||
+ EMailBackend *backend;
|
||
+ ESourceRegistry *registry;
|
||
+ EMailSession *mail_session;
|
||
+ EMailAccountStore *account_store;
|
||
+ const gchar *tag;
|
||
+ gboolean can_clear_flags = FALSE;
|
||
+ gboolean can_flag_completed = FALSE;
|
||
+ gboolean can_flag_for_followup = FALSE;
|
||
+ gboolean has_attachments = FALSE;
|
||
+ gboolean has_deleted = FALSE;
|
||
+ gboolean has_ignore_thread = FALSE;
|
||
+ gboolean has_notignore_thread = FALSE;
|
||
+ gboolean has_important = FALSE;
|
||
+ gboolean has_junk = FALSE;
|
||
+ gboolean has_not_junk = FALSE;
|
||
+ gboolean has_read = FALSE;
|
||
+ gboolean has_undeleted = FALSE;
|
||
+ gboolean has_unimportant = FALSE;
|
||
+ gboolean has_unread = FALSE;
|
||
+ gboolean has_mail_note = FALSE;
|
||
+ gboolean has_color = FALSE;
|
||
+ gboolean have_enabled_account = FALSE;
|
||
+ gboolean drafts_or_outbox = FALSE;
|
||
+ gboolean is_mailing_list;
|
||
+ gboolean is_junk_folder = FALSE;
|
||
+ gboolean is_vtrash_folder = FALSE;
|
||
+ guint32 state = 0;
|
||
+ guint ii;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
|
||
+
|
||
+ backend = e_mail_reader_get_backend (reader);
|
||
+ shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
|
||
+ registry = e_shell_get_registry (shell);
|
||
+ mail_session = e_mail_backend_get_session (backend);
|
||
+ account_store = e_mail_ui_session_get_account_store (
|
||
+ E_MAIL_UI_SESSION (mail_session));
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+ uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
|
||
+
|
||
+ if (folder != NULL) {
|
||
+ guint32 folder_flags;
|
||
+
|
||
+ store = camel_folder_get_parent_store (folder);
|
||
+ folder_flags = camel_folder_get_flags (folder);
|
||
+ is_junk_folder = (folder_flags & CAMEL_FOLDER_IS_JUNK) != 0;
|
||
+ is_vtrash_folder = (camel_store_get_flags (store) & CAMEL_STORE_VTRASH) != 0 && (folder_flags & CAMEL_FOLDER_IS_TRASH) != 0;
|
||
+ drafts_or_outbox =
|
||
+ em_utils_folder_is_drafts (registry, folder) ||
|
||
+ em_utils_folder_is_outbox (registry, folder);
|
||
+ }
|
||
+
|
||
+ /* Initialize this flag based on whether there are any
|
||
+ * messages selected. We will update it in the loop. */
|
||
+ is_mailing_list = (uids->len > 0);
|
||
+
|
||
+ for (ii = 0; ii < uids->len; ii++) {
|
||
+ CamelMessageInfo *info;
|
||
+ const gchar *string;
|
||
+ guint32 flags;
|
||
+
|
||
+ info = camel_folder_get_message_info (
|
||
+ folder, uids->pdata[ii]);
|
||
+ if (info == NULL)
|
||
+ continue;
|
||
+
|
||
+ flags = camel_message_info_get_flags (info);
|
||
+
|
||
+ if (flags & CAMEL_MESSAGE_SEEN)
|
||
+ has_read = TRUE;
|
||
+ else
|
||
+ has_unread = TRUE;
|
||
+
|
||
+ if (flags & CAMEL_MESSAGE_ATTACHMENTS)
|
||
+ has_attachments = TRUE;
|
||
+
|
||
+ if (drafts_or_outbox) {
|
||
+ has_junk = FALSE;
|
||
+ has_not_junk = FALSE;
|
||
+ } else {
|
||
+ guint32 bitmask;
|
||
+
|
||
+ /* XXX Strictly speaking, this logic is correct.
|
||
+ * Problem is there's nothing in the message
|
||
+ * list that indicates whether a message is
|
||
+ * already marked "Not Junk". So the user may
|
||
+ * think the "Not Junk" button is enabling and
|
||
+ * disabling itself randomly as he reads mail. */
|
||
+
|
||
+ if (flags & CAMEL_MESSAGE_JUNK)
|
||
+ has_junk = TRUE;
|
||
+ if (flags & CAMEL_MESSAGE_NOTJUNK)
|
||
+ has_not_junk = TRUE;
|
||
+
|
||
+ bitmask = CAMEL_MESSAGE_JUNK | CAMEL_MESSAGE_NOTJUNK;
|
||
+
|
||
+ /* If neither junk flag is set, the
|
||
+ * message can be marked either way. */
|
||
+ if ((flags & bitmask) == 0) {
|
||
+ has_junk = TRUE;
|
||
+ has_not_junk = TRUE;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (flags & CAMEL_MESSAGE_DELETED)
|
||
+ has_deleted = TRUE;
|
||
+ else
|
||
+ has_undeleted = TRUE;
|
||
+
|
||
+ if (flags & CAMEL_MESSAGE_FLAGGED)
|
||
+ has_important = TRUE;
|
||
+ else
|
||
+ has_unimportant = TRUE;
|
||
+
|
||
+ tag = camel_message_info_get_user_tag (info, "follow-up");
|
||
+ if (tag != NULL && *tag != '\0') {
|
||
+ can_clear_flags = TRUE;
|
||
+ tag = camel_message_info_get_user_tag (
|
||
+ info, "completed-on");
|
||
+ if (tag == NULL || *tag == '\0')
|
||
+ can_flag_completed = TRUE;
|
||
+ } else
|
||
+ can_flag_for_followup = TRUE;
|
||
+
|
||
+ string = camel_message_info_get_mlist (info);
|
||
+ is_mailing_list &= (string != NULL && *string != '\0');
|
||
+
|
||
+ has_ignore_thread = has_ignore_thread || camel_message_info_get_user_flag (info, "ignore-thread");
|
||
+ has_notignore_thread = has_notignore_thread || !camel_message_info_get_user_flag (info, "ignore-thread");
|
||
+ has_mail_note = has_mail_note || camel_message_info_get_user_flag (info, E_MAIL_NOTES_USER_FLAG);
|
||
+ has_color = has_color || camel_message_info_get_user_tag (info, "color") != NULL;
|
||
+
|
||
+ g_clear_object (&info);
|
||
+ }
|
||
+
|
||
+ have_enabled_account =
|
||
+ e_mail_account_store_have_enabled_service (
|
||
+ account_store, CAMEL_TYPE_STORE);
|
||
+
|
||
+ if (have_enabled_account)
|
||
+ state |= E_MAIL_READER_HAVE_ENABLED_ACCOUNT;
|
||
+ if (uids->len == 1)
|
||
+ state |= E_MAIL_READER_SELECTION_SINGLE;
|
||
+ if (uids->len > 1)
|
||
+ state |= E_MAIL_READER_SELECTION_MULTIPLE;
|
||
+ if (!drafts_or_outbox && uids->len == 1)
|
||
+ state |= E_MAIL_READER_SELECTION_CAN_ADD_SENDER;
|
||
+ if (can_clear_flags)
|
||
+ state |= E_MAIL_READER_SELECTION_FLAG_CLEAR;
|
||
+ if (can_flag_completed)
|
||
+ state |= E_MAIL_READER_SELECTION_FLAG_COMPLETED;
|
||
+ if (can_flag_for_followup)
|
||
+ state |= E_MAIL_READER_SELECTION_FLAG_FOLLOWUP;
|
||
+ if (has_attachments)
|
||
+ state |= E_MAIL_READER_SELECTION_HAS_ATTACHMENTS;
|
||
+ if (has_deleted)
|
||
+ state |= E_MAIL_READER_SELECTION_HAS_DELETED;
|
||
+ if (has_ignore_thread)
|
||
+ state |= E_MAIL_READER_SELECTION_HAS_IGNORE_THREAD;
|
||
+ if (has_notignore_thread)
|
||
+ state |= E_MAIL_READER_SELECTION_HAS_NOTIGNORE_THREAD;
|
||
+ if (has_important)
|
||
+ state |= E_MAIL_READER_SELECTION_HAS_IMPORTANT;
|
||
+ if (has_junk)
|
||
+ state |= E_MAIL_READER_SELECTION_HAS_JUNK;
|
||
+ if (has_not_junk)
|
||
+ state |= E_MAIL_READER_SELECTION_HAS_NOT_JUNK;
|
||
+ if (has_read)
|
||
+ state |= E_MAIL_READER_SELECTION_HAS_READ;
|
||
+ if (has_undeleted)
|
||
+ state |= E_MAIL_READER_SELECTION_HAS_UNDELETED;
|
||
+ if (has_unimportant)
|
||
+ state |= E_MAIL_READER_SELECTION_HAS_UNIMPORTANT;
|
||
+ if (has_unread)
|
||
+ state |= E_MAIL_READER_SELECTION_HAS_UNREAD;
|
||
+ if (is_mailing_list)
|
||
+ state |= E_MAIL_READER_SELECTION_IS_MAILING_LIST;
|
||
+ if (is_junk_folder)
|
||
+ state |= E_MAIL_READER_FOLDER_IS_JUNK;
|
||
+ if (is_vtrash_folder)
|
||
+ state |= E_MAIL_READER_FOLDER_IS_VTRASH;
|
||
+ if (has_mail_note)
|
||
+ state |= E_MAIL_READER_SELECTION_HAS_MAIL_NOTE;
|
||
+ if (has_color)
|
||
+ state |= E_MAIL_READER_SELECTION_HAS_COLOR;
|
||
+
|
||
+ if (!(state & E_MAIL_READER_SELECTION_SINGLE)) {
|
||
+ GPtrArray *real_selected_uids;
|
||
+
|
||
+ real_selected_uids = e_mail_reader_get_selected_uids (reader);
|
||
+
|
||
+ if (real_selected_uids && real_selected_uids->len == 1) {
|
||
+ state |= E_MAIL_READER_SELECTION_SINGLE;
|
||
+ }
|
||
+
|
||
+ if (real_selected_uids)
|
||
+ g_ptr_array_unref (real_selected_uids);
|
||
+ }
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ g_ptr_array_unref (uids);
|
||
+
|
||
+ return state;
|
||
+}
|
||
+
|
||
+EActivity *
|
||
+e_mail_reader_new_activity (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+ EActivity *activity;
|
||
+ EMailBackend *backend;
|
||
+ EAlertSink *alert_sink;
|
||
+ GCancellable *cancellable;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ activity = e_activity_new ();
|
||
+
|
||
+ alert_sink = e_mail_reader_get_alert_sink (reader);
|
||
+ e_activity_set_alert_sink (activity, alert_sink);
|
||
+
|
||
+ cancellable = camel_operation_new ();
|
||
+
|
||
+ priv->ongoing_operations = g_slist_prepend (priv->ongoing_operations, cancellable);
|
||
+ g_object_weak_ref (G_OBJECT (cancellable), mail_reader_ongoing_operation_destroyed, reader);
|
||
+
|
||
+ e_activity_set_cancellable (activity, cancellable);
|
||
+ g_object_unref (cancellable);
|
||
+
|
||
+ backend = e_mail_reader_get_backend (reader);
|
||
+ e_shell_backend_add_activity (E_SHELL_BACKEND (backend), activity);
|
||
+
|
||
+ return activity;
|
||
+}
|
||
+
|
||
+void
|
||
+e_mail_reader_update_actions (EMailReader *reader,
|
||
+ guint32 state)
|
||
+{
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ g_signal_emit (reader, signals[UPDATE_ACTIONS], 0, state);
|
||
+}
|
||
+
|
||
+GtkAction *
|
||
+e_mail_reader_get_action (EMailReader *reader,
|
||
+ const gchar *action_name)
|
||
+{
|
||
+ GtkAction *action = NULL;
|
||
+ gint ii;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
|
||
+ g_return_val_if_fail (action_name != NULL, NULL);
|
||
+
|
||
+ for (ii = 0; ii < E_MAIL_READER_NUM_ACTION_GROUPS; ii++) {
|
||
+ GtkActionGroup *group;
|
||
+
|
||
+ group = e_mail_reader_get_action_group (reader, ii);
|
||
+ action = gtk_action_group_get_action (group, action_name);
|
||
+
|
||
+ if (action != NULL)
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ if (action == NULL)
|
||
+ g_critical (
|
||
+ "%s: action '%s' not found", G_STRFUNC, action_name);
|
||
+
|
||
+ return action;
|
||
+}
|
||
+
|
||
+GtkActionGroup *
|
||
+e_mail_reader_get_action_group (EMailReader *reader,
|
||
+ EMailReaderActionGroup group)
|
||
+{
|
||
+ EMailReaderInterface *iface;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
|
||
+
|
||
+ iface = E_MAIL_READER_GET_INTERFACE (reader);
|
||
+ g_return_val_if_fail (iface->get_action_group != NULL, NULL);
|
||
+
|
||
+ return iface->get_action_group (reader, group);
|
||
+}
|
||
+
|
||
+EAlertSink *
|
||
+e_mail_reader_get_alert_sink (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderInterface *iface;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
|
||
+
|
||
+ iface = E_MAIL_READER_GET_INTERFACE (reader);
|
||
+ g_return_val_if_fail (iface->get_alert_sink != NULL, NULL);
|
||
+
|
||
+ return iface->get_alert_sink (reader);
|
||
+}
|
||
+
|
||
+EMailBackend *
|
||
+e_mail_reader_get_backend (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderInterface *iface;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
|
||
+
|
||
+ iface = E_MAIL_READER_GET_INTERFACE (reader);
|
||
+ g_return_val_if_fail (iface->get_backend != NULL, NULL);
|
||
+
|
||
+ return iface->get_backend (reader);
|
||
+}
|
||
+
|
||
+EMailDisplay *
|
||
+e_mail_reader_get_mail_display (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderInterface *iface;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
|
||
+
|
||
+ iface = E_MAIL_READER_GET_INTERFACE (reader);
|
||
+ g_return_val_if_fail (iface->get_mail_display != NULL, NULL);
|
||
+
|
||
+ return iface->get_mail_display (reader);
|
||
+}
|
||
+
|
||
+gboolean
|
||
+e_mail_reader_get_hide_deleted (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderInterface *iface;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
|
||
+
|
||
+ iface = E_MAIL_READER_GET_INTERFACE (reader);
|
||
+ g_return_val_if_fail (iface->get_hide_deleted != NULL, FALSE);
|
||
+
|
||
+ return iface->get_hide_deleted (reader);
|
||
+}
|
||
+
|
||
+GtkWidget *
|
||
+e_mail_reader_get_message_list (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderInterface *iface;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
|
||
+
|
||
+ iface = E_MAIL_READER_GET_INTERFACE (reader);
|
||
+ g_return_val_if_fail (iface->get_message_list != NULL, NULL);
|
||
+
|
||
+ return iface->get_message_list (reader);
|
||
+}
|
||
+
|
||
+static void
|
||
+e_mail_reader_popup_menu_deactivate_cb (GtkMenu *popup_menu,
|
||
+ EMailReader *reader)
|
||
+{
|
||
+ g_return_if_fail (GTK_IS_MENU (popup_menu));
|
||
+
|
||
+ g_signal_handlers_disconnect_by_func (popup_menu, e_mail_reader_popup_menu_deactivate_cb, reader);
|
||
+ gtk_menu_detach (popup_menu);
|
||
+}
|
||
+
|
||
+GtkMenu *
|
||
+e_mail_reader_get_popup_menu (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderInterface *iface;
|
||
+ GtkMenu *menu;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
|
||
+
|
||
+ iface = E_MAIL_READER_GET_INTERFACE (reader);
|
||
+ g_return_val_if_fail (iface->get_popup_menu != NULL, NULL);
|
||
+
|
||
+ menu = iface->get_popup_menu (reader);
|
||
+ if (!gtk_menu_get_attach_widget (GTK_MENU (menu))) {
|
||
+ gtk_menu_attach_to_widget (GTK_MENU (menu),
|
||
+ GTK_WIDGET (reader),
|
||
+ NULL);
|
||
+ g_signal_connect (
|
||
+ menu, "deactivate",
|
||
+ G_CALLBACK (e_mail_reader_popup_menu_deactivate_cb), reader);
|
||
+ }
|
||
+
|
||
+ return menu;
|
||
+}
|
||
+
|
||
+EPreviewPane *
|
||
+e_mail_reader_get_preview_pane (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderInterface *iface;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
|
||
+
|
||
+ iface = E_MAIL_READER_GET_INTERFACE (reader);
|
||
+ g_return_val_if_fail (iface->get_preview_pane != NULL, NULL);
|
||
+
|
||
+ return iface->get_preview_pane (reader);
|
||
+}
|
||
+
|
||
+GPtrArray *
|
||
+e_mail_reader_get_selected_uids (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderInterface *iface;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
|
||
+
|
||
+ iface = E_MAIL_READER_GET_INTERFACE (reader);
|
||
+ g_return_val_if_fail (iface->get_selected_uids != NULL, NULL);
|
||
+
|
||
+ return iface->get_selected_uids (reader);
|
||
+}
|
||
+
|
||
+GPtrArray *
|
||
+e_mail_reader_get_selected_uids_with_collapsed_threads (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderInterface *iface;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
|
||
+
|
||
+ iface = E_MAIL_READER_GET_INTERFACE (reader);
|
||
+ g_return_val_if_fail (iface->get_selected_uids_with_collapsed_threads != NULL, NULL);
|
||
+
|
||
+ return iface->get_selected_uids_with_collapsed_threads (reader);
|
||
+}
|
||
+
|
||
+GtkWindow *
|
||
+e_mail_reader_get_window (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderInterface *iface;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
|
||
+
|
||
+ iface = E_MAIL_READER_GET_INTERFACE (reader);
|
||
+ g_return_val_if_fail (iface->get_window != NULL, NULL);
|
||
+
|
||
+ return iface->get_window (reader);
|
||
+}
|
||
+
|
||
+gboolean
|
||
+e_mail_reader_close_on_delete_or_junk (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderInterface *iface;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
|
||
+
|
||
+ iface = E_MAIL_READER_GET_INTERFACE (reader);
|
||
+
|
||
+ return iface->close_on_delete_or_junk != NULL &&
|
||
+ iface->close_on_delete_or_junk (reader);
|
||
+}
|
||
+
|
||
+CamelFolder *
|
||
+e_mail_reader_ref_folder (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderInterface *iface;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
|
||
+
|
||
+ iface = E_MAIL_READER_GET_INTERFACE (reader);
|
||
+ g_return_val_if_fail (iface->ref_folder != NULL, NULL);
|
||
+
|
||
+ return iface->ref_folder (reader);
|
||
+}
|
||
+
|
||
+void
|
||
+e_mail_reader_set_folder (EMailReader *reader,
|
||
+ CamelFolder *folder)
|
||
+{
|
||
+ EMailReaderInterface *iface;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ iface = E_MAIL_READER_GET_INTERFACE (reader);
|
||
+ g_return_if_fail (iface->set_folder != NULL);
|
||
+
|
||
+ iface->set_folder (reader, folder);
|
||
+}
|
||
+
|
||
+void
|
||
+e_mail_reader_set_message (EMailReader *reader,
|
||
+ const gchar *message_uid)
|
||
+{
|
||
+ EMailReaderInterface *iface;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ iface = E_MAIL_READER_GET_INTERFACE (reader);
|
||
+ g_return_if_fail (iface->set_message != NULL);
|
||
+
|
||
+ iface->set_message (reader, message_uid);
|
||
+}
|
||
+
|
||
+guint
|
||
+e_mail_reader_open_selected_mail (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderInterface *iface;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
|
||
+
|
||
+ iface = E_MAIL_READER_GET_INTERFACE (reader);
|
||
+ g_return_val_if_fail (iface->open_selected_mail != NULL, 0);
|
||
+
|
||
+ return iface->open_selected_mail (reader);
|
||
+}
|
||
+
|
||
+EMailForwardStyle
|
||
+e_mail_reader_get_forward_style (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ return priv->forward_style;
|
||
+}
|
||
+
|
||
+void
|
||
+e_mail_reader_set_forward_style (EMailReader *reader,
|
||
+ EMailForwardStyle style)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ if (priv->forward_style == style)
|
||
+ return;
|
||
+
|
||
+ priv->forward_style = style;
|
||
+
|
||
+ g_object_notify (G_OBJECT (reader), "forward-style");
|
||
+}
|
||
+
|
||
+gboolean
|
||
+e_mail_reader_get_group_by_threads (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ return priv->group_by_threads;
|
||
+}
|
||
+
|
||
+void
|
||
+e_mail_reader_set_group_by_threads (EMailReader *reader,
|
||
+ gboolean group_by_threads)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ if (priv->group_by_threads == group_by_threads)
|
||
+ return;
|
||
+
|
||
+ priv->group_by_threads = group_by_threads;
|
||
+
|
||
+ g_object_notify (G_OBJECT (reader), "group-by-threads");
|
||
+}
|
||
+
|
||
+EMailReplyStyle
|
||
+e_mail_reader_get_reply_style (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ return priv->reply_style;
|
||
+}
|
||
+
|
||
+void
|
||
+e_mail_reader_set_reply_style (EMailReader *reader,
|
||
+ EMailReplyStyle style)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ if (priv->reply_style == style)
|
||
+ return;
|
||
+
|
||
+ priv->reply_style = style;
|
||
+
|
||
+ g_object_notify (G_OBJECT (reader), "reply-style");
|
||
+}
|
||
+
|
||
+gboolean
|
||
+e_mail_reader_get_mark_seen_always (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ return priv->mark_seen_always;
|
||
+}
|
||
+
|
||
+void
|
||
+e_mail_reader_set_mark_seen_always (EMailReader *reader,
|
||
+ gboolean mark_seen_always)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ if (priv->mark_seen_always == mark_seen_always)
|
||
+ return;
|
||
+
|
||
+ priv->mark_seen_always = mark_seen_always;
|
||
+
|
||
+ g_object_notify (G_OBJECT (reader), "mark-seen-always");
|
||
+}
|
||
+
|
||
+gboolean
|
||
+e_mail_reader_get_delete_selects_previous (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+
|
||
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ return priv->delete_selects_previous;
|
||
+}
|
||
+
|
||
+void
|
||
+e_mail_reader_set_delete_selects_previous (EMailReader *reader,
|
||
+ gboolean delete_selects_previous)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+
|
||
+ if (priv->delete_selects_previous == delete_selects_previous)
|
||
+ return;
|
||
+
|
||
+ priv->delete_selects_previous = delete_selects_previous;
|
||
+
|
||
+ g_object_notify (G_OBJECT (reader), "delete-selects-previous");
|
||
+}
|
||
+
|
||
+void
|
||
+e_mail_reader_create_charset_menu (EMailReader *reader,
|
||
+ GtkUIManager *ui_manager,
|
||
+ guint merge_id)
|
||
+{
|
||
+ GtkAction *action;
|
||
+ const gchar *action_name;
|
||
+ const gchar *path;
|
||
+ GSList *list;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+ g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager));
|
||
+
|
||
+ action_name = "mail-charset-default";
|
||
+ action = e_mail_reader_get_action (reader, action_name);
|
||
+ g_return_if_fail (action != NULL);
|
||
+
|
||
+ list = gtk_radio_action_get_group (GTK_RADIO_ACTION (action));
|
||
+ list = g_slist_copy (list);
|
||
+ list = g_slist_remove (list, action);
|
||
+ list = g_slist_sort (list, (GCompareFunc) e_action_compare_by_label);
|
||
+
|
||
+ path = "/main-menu/view-menu/mail-message-view-actions/mail-encoding-menu";
|
||
+
|
||
+ while (list != NULL) {
|
||
+ action = list->data;
|
||
+
|
||
+ gtk_ui_manager_add_ui (
|
||
+ ui_manager, merge_id, path,
|
||
+ gtk_action_get_name (action),
|
||
+ gtk_action_get_name (action),
|
||
+ GTK_UI_MANAGER_AUTO, FALSE);
|
||
+
|
||
+ list = g_slist_delete_link (list, list);
|
||
+ }
|
||
+
|
||
+ gtk_ui_manager_ensure_update (ui_manager);
|
||
+}
|
||
+
|
||
+void
|
||
+e_mail_reader_show_search_bar (EMailReader *reader)
|
||
+{
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ g_signal_emit (reader, signals[SHOW_SEARCH_BAR], 0);
|
||
+}
|
||
+
|
||
+void
|
||
+e_mail_reader_avoid_next_mark_as_seen (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+ MessageList *message_list;
|
||
+
|
||
+ g_return_if_fail (reader != NULL);
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+ g_return_if_fail (priv != NULL);
|
||
+
|
||
+ message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
|
||
+ g_return_if_fail (message_list != NULL);
|
||
+
|
||
+ priv->avoid_next_mark_as_seen = TRUE;
|
||
+}
|
||
+
|
||
+void
|
||
+e_mail_reader_unset_folder_just_selected (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderPrivate *priv;
|
||
+
|
||
+ g_return_if_fail (reader != NULL);
|
||
+
|
||
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
|
||
+ g_return_if_fail (priv != NULL);
|
||
+
|
||
+ priv->folder_was_just_selected = FALSE;
|
||
+}
|
||
+
|
||
+/**
|
||
+ * e_mail_reader_composer_created:
|
||
+ * @reader: an #EMailReader
|
||
+ * @composer: an #EMsgComposer
|
||
+ * @message: the source #CamelMimeMessage, or %NULL
|
||
+ *
|
||
+ * Emits an #EMailReader::composer-created signal to indicate the @composer
|
||
+ * window was created in response to a user action on @reader. Examples of
|
||
+ * such actions include replying, forwarding, and composing a new message.
|
||
+ * If applicable, the source @message (i.e. the message being replied to or
|
||
+ * forwarded) should be included.
|
||
+ **/
|
||
+void
|
||
+e_mail_reader_composer_created (EMailReader *reader,
|
||
+ EMsgComposer *composer,
|
||
+ CamelMimeMessage *message)
|
||
+{
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+ g_return_if_fail (E_IS_MSG_COMPOSER (composer));
|
||
+
|
||
+ if (message != NULL)
|
||
+ g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
|
||
+
|
||
+ g_signal_emit (
|
||
+ reader, signals[COMPOSER_CREATED], 0, composer, message);
|
||
+}
|
||
+
|
||
+void
|
||
+e_mail_reader_reload (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderInterface *iface;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ iface = E_MAIL_READER_GET_INTERFACE (reader);
|
||
+ g_return_if_fail (iface->reload != NULL);
|
||
+
|
||
+ iface->reload (reader);
|
||
+}
|
||
+
|
||
+void
|
||
+e_mail_reader_remove_ui (EMailReader *reader)
|
||
+{
|
||
+ EMailReaderInterface *iface;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_READER (reader));
|
||
+
|
||
+ iface = E_MAIL_READER_GET_INTERFACE (reader);
|
||
+ g_return_if_fail (iface->remove_ui != NULL);
|
||
+
|
||
+ iface->remove_ui (reader);
|
||
+}
|
||
+
|
||
+/**
|
||
+ * e_mail_reader_create_reply_menu:
|
||
+ * @reader: A #EMailReader
|
||
+ *
|
||
+ * Get reply menu
|
||
+ *
|
||
+ * Returns: (transfer full): A new #GtkMenu
|
||
+ *
|
||
+ * Since: 3.46
|
||
+ **/
|
||
+GtkWidget *
|
||
+e_mail_reader_create_reply_menu (EMailReader *reader)
|
||
+{
|
||
+ GtkWindow *window;
|
||
+ GtkWidget *menu;
|
||
+ GtkAction *action;
|
||
+ GtkAccelGroup *accel_group;
|
||
+ GtkUIManager *ui_manager;
|
||
+
|
||
+ menu = gtk_menu_new ();
|
||
+
|
||
+ window = e_mail_reader_get_window (reader);
|
||
+ g_return_val_if_fail (window != NULL, menu);
|
||
+
|
||
+ if (E_IS_SHELL_WINDOW (window))
|
||
+ ui_manager = e_shell_window_get_ui_manager (E_SHELL_WINDOW (window));
|
||
+ else if (E_IS_MAIL_BROWSER (window))
|
||
+ ui_manager = e_mail_browser_get_ui_manager (E_MAIL_BROWSER (window));
|
||
+ else
|
||
+ return menu;
|
||
+
|
||
+ accel_group = gtk_ui_manager_get_accel_group (ui_manager);
|
||
+
|
||
+ action = e_mail_reader_get_action (reader, "mail-reply-all");
|
||
+ gtk_action_set_accel_group (action, accel_group);
|
||
+ gtk_menu_shell_append (
|
||
+ GTK_MENU_SHELL (menu),
|
||
+ gtk_action_create_menu_item (action));
|
||
+
|
||
+ action = e_mail_reader_get_action (reader, "mail-reply-list");
|
||
+ gtk_action_set_accel_group (action, accel_group);
|
||
+ gtk_menu_shell_append (
|
||
+ GTK_MENU_SHELL (menu),
|
||
+ gtk_action_create_menu_item (action));
|
||
+
|
||
+ action = e_mail_reader_get_action (reader, "mail-reply-alternative");
|
||
+ gtk_action_set_accel_group (action, accel_group);
|
||
+ gtk_menu_shell_append (
|
||
+ GTK_MENU_SHELL (menu),
|
||
+ gtk_action_create_menu_item (action));
|
||
+
|
||
+ gtk_widget_show_all (menu);
|
||
+
|
||
+ return menu;
|
||
+}
|
||
+
|
||
+/**
|
||
+ * e_mail_reader_create_forward_menu:
|
||
+ * @reader: A #EMailReader
|
||
+ *
|
||
+ * Get forward menu
|
||
+ *
|
||
+ * Returns: (transfer full): A new #GtkMenu
|
||
+ *
|
||
+ * Since: 3.46
|
||
+ **/
|
||
+GtkWidget *
|
||
+e_mail_reader_create_forward_menu (EMailReader *reader)
|
||
+{
|
||
+ GtkWindow *window;
|
||
+ GtkWidget *menu;
|
||
+ GtkAction *action;
|
||
+ GtkAccelGroup *accel_group;
|
||
+ GtkUIManager *ui_manager;
|
||
+
|
||
+ menu = gtk_menu_new ();
|
||
+
|
||
+ window = e_mail_reader_get_window (reader);
|
||
+ g_return_val_if_fail (window != NULL, menu);
|
||
+
|
||
+ if (E_IS_SHELL_WINDOW (window))
|
||
+ ui_manager = e_shell_window_get_ui_manager (E_SHELL_WINDOW (window));
|
||
+ else if (E_IS_MAIL_BROWSER (window))
|
||
+ ui_manager = e_mail_browser_get_ui_manager (E_MAIL_BROWSER (window));
|
||
+ else
|
||
+ return menu;
|
||
+
|
||
+ accel_group = gtk_ui_manager_get_accel_group (ui_manager);
|
||
+
|
||
+ action = e_mail_reader_get_action (reader, "mail-forward-attached-full");
|
||
+ gtk_action_set_accel_group (action, accel_group);
|
||
+ gtk_menu_shell_append (
|
||
+ GTK_MENU_SHELL (menu),
|
||
+ gtk_action_create_menu_item (action));
|
||
+
|
||
+ action = e_mail_reader_get_action (reader, "mail-forward-inline-full");
|
||
+ gtk_action_set_accel_group (action, accel_group);
|
||
+ gtk_menu_shell_append (
|
||
+ GTK_MENU_SHELL (menu),
|
||
+ gtk_action_create_menu_item (action));
|
||
+
|
||
+ action = e_mail_reader_get_action (reader, "mail-forward-quoted-full");
|
||
+ gtk_action_set_accel_group (action, accel_group);
|
||
+ gtk_menu_shell_append (
|
||
+ GTK_MENU_SHELL (menu),
|
||
+ gtk_action_create_menu_item (action));
|
||
+
|
||
+ action = e_mail_reader_get_action (reader, "mail-redirect");
|
||
+ gtk_action_set_accel_group (action, accel_group);
|
||
+ gtk_menu_shell_append (
|
||
+ GTK_MENU_SHELL (menu),
|
||
+ gtk_action_create_menu_item (action));
|
||
+
|
||
+ gtk_widget_show_all (menu);
|
||
+
|
||
+ return menu;
|
||
+}
|
||
diff -urN a/src/modules/addressbook/e-book-shell-backend.c b/src/modules/addressbook/e-book-shell-backend.c
|
||
--- a/src/modules/addressbook/e-book-shell-backend.c 2025-06-07 14:20:57.363397606 -0700
|
||
+++ b/src/modules/addressbook/e-book-shell-backend.c 2025-06-07 14:27:24.055673052 -0700
|
||
@@ -276,14 +276,14 @@
|
||
{ "contact-new",
|
||
"contact-new",
|
||
NC_("New", "_Contact"),
|
||
- "<Shift><Control>c",
|
||
+ "<Shift><Super>c",
|
||
N_("Create a new contact"),
|
||
G_CALLBACK (action_contact_new_cb) },
|
||
|
||
{ "contact-new-list",
|
||
"stock_contact-list",
|
||
NC_("New", "Contact _List"),
|
||
- "<Shift><Control>l",
|
||
+ "<Shift><Super>l",
|
||
N_("Create a new contact list"),
|
||
G_CALLBACK (action_contact_new_cb) }
|
||
};
|
||
diff -urN a/src/modules/addressbook/e-book-shell-view-actions.c b/src/modules/addressbook/e-book-shell-view-actions.c
|
||
--- a/src/modules/addressbook/e-book-shell-view-actions.c 2025-06-07 14:20:57.363397606 -0700
|
||
+++ b/src/modules/addressbook/e-book-shell-view-actions.c 2025-06-07 14:27:24.059673092 -0700
|
||
@@ -1090,21 +1090,21 @@
|
||
{ "contact-copy",
|
||
NULL,
|
||
N_("_Copy Contact To…"),
|
||
- "<Control><Shift>y",
|
||
+ "<Super><Shift>y",
|
||
N_("Copy selected contacts to another address book"),
|
||
G_CALLBACK (action_contact_copy_cb) },
|
||
|
||
{ "contact-delete",
|
||
"edit-delete",
|
||
N_("_Delete Contact"),
|
||
- "<Control>d",
|
||
+ "<Super>d",
|
||
N_("Delete selected contacts"),
|
||
G_CALLBACK (action_contact_delete_cb) },
|
||
|
||
{ "contact-find",
|
||
"edit-find",
|
||
N_("_Find in Contact…"),
|
||
- "<Shift><Control>f",
|
||
+ "<Shift><Super>f",
|
||
N_("Search for text in the displayed contact"),
|
||
G_CALLBACK (action_contact_find_cb) },
|
||
|
||
@@ -1118,7 +1118,7 @@
|
||
{ "contact-move",
|
||
NULL,
|
||
N_("_Move Contact To…"),
|
||
- "<Control><Shift>v",
|
||
+ "<Super><Shift>v",
|
||
N_("Move selected contacts to another address book"),
|
||
G_CALLBACK (action_contact_move_cb) },
|
||
|
||
@@ -1139,7 +1139,7 @@
|
||
{ "contact-open",
|
||
NULL,
|
||
N_("_Open Contact"),
|
||
- "<Control>o",
|
||
+ "<Super>o",
|
||
N_("View the current contact"),
|
||
G_CALLBACK (action_contact_open_cb) },
|
||
|
||
@@ -1223,7 +1223,7 @@
|
||
{ "contact-preview",
|
||
NULL,
|
||
N_("Contact _Preview"),
|
||
- "<Control>m",
|
||
+ "<Super>m",
|
||
N_("Show contact preview window"),
|
||
G_CALLBACK (action_contact_preview_cb),
|
||
TRUE },
|
||
@@ -1317,7 +1317,7 @@
|
||
{ "address-book-print",
|
||
"document-print",
|
||
N_("_Print…"),
|
||
- "<Control>p",
|
||
+ "<Super>p",
|
||
N_("Print all shown contacts"),
|
||
G_CALLBACK (action_address_book_print_cb) },
|
||
|
||
diff -urN a/src/modules/calendar/e-cal-shell-backend.c b/src/modules/calendar/e-cal-shell-backend.c
|
||
--- a/src/modules/calendar/e-cal-shell-backend.c 2025-06-07 14:20:57.371397702 -0700
|
||
+++ b/src/modules/calendar/e-cal-shell-backend.c 2025-06-07 14:27:24.059673092 -0700
|
||
@@ -116,7 +116,7 @@
|
||
{ "event-new",
|
||
"appointment-new",
|
||
NC_("New", "_Appointment"),
|
||
- "<Shift><Control>a",
|
||
+ "<Shift><Super>a",
|
||
N_("Create a new appointment"),
|
||
G_CALLBACK (action_event_new_cb) },
|
||
|
||
@@ -130,7 +130,7 @@
|
||
{ "event-meeting-new",
|
||
"stock_people",
|
||
NC_("New", "M_eeting"),
|
||
- "<Shift><Control>e",
|
||
+ "<Shift><Super>e",
|
||
N_("Create a new meeting request"),
|
||
G_CALLBACK (action_event_new_cb) }
|
||
};
|
||
diff -urN a/src/modules/calendar/e-cal-shell-view-actions.c b/src/modules/calendar/e-cal-shell-view-actions.c
|
||
--- a/src/modules/calendar/e-cal-shell-view-actions.c 2025-06-07 14:20:57.371397702 -0700
|
||
+++ b/src/modules/calendar/e-cal-shell-view-actions.c 2025-06-07 14:27:24.059673092 -0700
|
||
@@ -1304,7 +1304,7 @@
|
||
{ "calendar-copy",
|
||
"edit-copy",
|
||
N_("_Copy…"),
|
||
- "<Control>c",
|
||
+ "<Super>c",
|
||
NULL, /* XXX Add a tooltip! */
|
||
G_CALLBACK (action_calendar_copy_cb) },
|
||
|
||
@@ -1332,14 +1332,14 @@
|
||
{ "calendar-go-today",
|
||
"go-today",
|
||
N_("Select _Today"),
|
||
- "<Control>t",
|
||
+ "<Super>t",
|
||
N_("Select today"),
|
||
G_CALLBACK (action_calendar_go_today_cb) },
|
||
|
||
{ "calendar-jump-to",
|
||
"go-jump",
|
||
N_("Select _Date"),
|
||
- "<Control>g",
|
||
+ "<Super>g",
|
||
N_("Select a specific date"),
|
||
G_CALLBACK (action_calendar_jump_to_cb) },
|
||
|
||
@@ -1367,7 +1367,7 @@
|
||
{ "calendar-purge",
|
||
NULL,
|
||
N_("Purg_e"),
|
||
- "<Control>e",
|
||
+ "<Super>e",
|
||
N_("Purge old appointments and meetings"),
|
||
G_CALLBACK (action_calendar_purge_cb) },
|
||
|
||
@@ -1395,14 +1395,14 @@
|
||
{ "calendar-search-next",
|
||
"go-next",
|
||
N_("Find _Next"),
|
||
- "<Control><Shift>n",
|
||
+ "<Super><Shift>n",
|
||
N_("Find next occurrence of the current search string"),
|
||
G_CALLBACK (action_calendar_search_next_cb) },
|
||
|
||
{ "calendar-search-prev",
|
||
"go-previous",
|
||
N_("Find _Previous"),
|
||
- "<Control><Shift>p",
|
||
+ "<Super><Shift>p",
|
||
N_("Find previous occurrence of the current search string"),
|
||
G_CALLBACK (action_calendar_search_prev_cb) },
|
||
|
||
@@ -1444,7 +1444,7 @@
|
||
{ "event-delete",
|
||
"edit-delete",
|
||
N_("_Delete Appointment"),
|
||
- "<Control>d",
|
||
+ "<Super>d",
|
||
N_("Delete selected appointments"),
|
||
G_CALLBACK (action_event_delete_cb) },
|
||
|
||
@@ -1570,7 +1570,7 @@
|
||
{ "event-open",
|
||
"document-open",
|
||
N_("_Open Appointment"),
|
||
- "<Control>o",
|
||
+ "<Super>o",
|
||
N_("View the current appointment"),
|
||
G_CALLBACK (action_event_open_cb) },
|
||
|
||
@@ -1605,7 +1605,7 @@
|
||
{ "quit-calendar",
|
||
"window-close",
|
||
N_("Quit"),
|
||
- "<Control>w",
|
||
+ "<Super>w",
|
||
NULL, /* XXX Add a tooltip! */
|
||
G_CALLBACK (quit_calendar_cb) },
|
||
|
||
@@ -1771,35 +1771,35 @@
|
||
{ "calendar-view-day",
|
||
"view-calendar-day",
|
||
N_("Day"),
|
||
- "<Control>y",
|
||
+ "<Super>y",
|
||
N_("Show one day"),
|
||
E_CAL_VIEW_KIND_DAY },
|
||
|
||
{ "calendar-view-list",
|
||
"view-calendar-list",
|
||
N_("List"),
|
||
- "<Control>l",
|
||
+ "<Super>l",
|
||
N_("Show as list"),
|
||
E_CAL_VIEW_KIND_LIST },
|
||
|
||
{ "calendar-view-month",
|
||
"view-calendar-month",
|
||
N_("Month"),
|
||
- "<Control>m",
|
||
+ "<Super>m",
|
||
N_("Show one month"),
|
||
E_CAL_VIEW_KIND_MONTH },
|
||
|
||
{ "calendar-view-week",
|
||
"view-calendar-week",
|
||
N_("Week"),
|
||
- "<Control>k",
|
||
+ "<Super>k",
|
||
N_("Show one week"),
|
||
E_CAL_VIEW_KIND_WEEK },
|
||
|
||
{ "calendar-view-workweek",
|
||
"view-calendar-workweek",
|
||
N_("Work Week"),
|
||
- "<Control>j",
|
||
+ "<Super>j",
|
||
N_("Show one work week"),
|
||
E_CAL_VIEW_KIND_WORKWEEK },
|
||
|
||
@@ -1912,7 +1912,7 @@
|
||
{ "calendar-print",
|
||
"document-print",
|
||
N_("Print…"),
|
||
- "<Control>p",
|
||
+ "<Super>p",
|
||
N_("Print this calendar"),
|
||
G_CALLBACK (action_calendar_print_cb) },
|
||
|
||
diff -urN a/src/modules/calendar/e-cal-shell-view-memopad.c b/src/modules/calendar/e-cal-shell-view-memopad.c
|
||
--- a/src/modules/calendar/e-cal-shell-view-memopad.c 2025-06-07 14:20:57.371397702 -0700
|
||
+++ b/src/modules/calendar/e-cal-shell-view-memopad.c 2025-06-07 14:27:24.059673092 -0700
|
||
@@ -250,7 +250,7 @@
|
||
{ "calendar-memopad-open",
|
||
"document-open",
|
||
N_("_Open Memo"),
|
||
- "<Control>o",
|
||
+ "<Super>o",
|
||
N_("View the selected memo"),
|
||
G_CALLBACK (action_calendar_memopad_open_cb) },
|
||
|
||
diff -urN a/src/modules/calendar/e-cal-shell-view-taskpad.c b/src/modules/calendar/e-cal-shell-view-taskpad.c
|
||
--- a/src/modules/calendar/e-cal-shell-view-taskpad.c 2025-06-07 14:20:57.371397702 -0700
|
||
+++ b/src/modules/calendar/e-cal-shell-view-taskpad.c 2025-06-07 14:27:24.059673092 -0700
|
||
@@ -344,7 +344,7 @@
|
||
{ "calendar-taskpad-open",
|
||
"document-open",
|
||
N_("_Open Task"),
|
||
- "<Control>o",
|
||
+ "<Super>o",
|
||
N_("View the selected task"),
|
||
G_CALLBACK (action_calendar_taskpad_open_cb) },
|
||
|
||
diff -urN a/src/modules/calendar/e-memo-shell-backend.c b/src/modules/calendar/e-memo-shell-backend.c
|
||
--- a/src/modules/calendar/e-memo-shell-backend.c 2025-06-07 14:20:57.371397702 -0700
|
||
+++ b/src/modules/calendar/e-memo-shell-backend.c 2025-06-07 14:27:24.059673092 -0700
|
||
@@ -75,14 +75,14 @@
|
||
{ "memo-new",
|
||
"stock_insert-note",
|
||
NC_("New", "Mem_o"),
|
||
- "<Shift><Control>o",
|
||
+ "<Shift><Super>o",
|
||
N_("Create a new memo"),
|
||
G_CALLBACK (action_memo_new_cb) },
|
||
|
||
{ "memo-shared-new",
|
||
"stock_insert-note",
|
||
NC_("New", "_Shared Memo"),
|
||
- "<Shift><Control>u",
|
||
+ "<Shift><Super>u",
|
||
N_("Create a new shared memo"),
|
||
G_CALLBACK (action_memo_new_cb) }
|
||
};
|
||
diff -urN a/src/modules/calendar/e-memo-shell-view-actions.c b/src/modules/calendar/e-memo-shell-view-actions.c
|
||
--- a/src/modules/calendar/e-memo-shell-view-actions.c 2025-06-07 14:20:57.371397702 -0700
|
||
+++ b/src/modules/calendar/e-memo-shell-view-actions.c 2025-06-07 14:27:24.059673092 -0700
|
||
@@ -575,21 +575,21 @@
|
||
{ "memo-find",
|
||
"edit-find",
|
||
N_("_Find in Memo…"),
|
||
- "<Shift><Control>f",
|
||
+ "<Shift><Super>f",
|
||
N_("Search for text in the displayed memo"),
|
||
G_CALLBACK (action_memo_find_cb) },
|
||
|
||
{ "memo-forward",
|
||
"mail-forward",
|
||
N_("_Forward as iCalendar…"),
|
||
- "<Control>f",
|
||
+ "<Super>f",
|
||
NULL, /* XXX Add a tooltip! */
|
||
G_CALLBACK (action_memo_forward_cb) },
|
||
|
||
{ "memo-list-copy",
|
||
"edit-copy",
|
||
N_("_Copy…"),
|
||
- "<Control>c",
|
||
+ "<Super>c",
|
||
NULL, /* XXX Add a tooltip! */
|
||
G_CALLBACK (action_memo_list_copy_cb) },
|
||
|
||
@@ -666,7 +666,7 @@
|
||
{ "memo-open",
|
||
"document-open",
|
||
N_("_Open Memo"),
|
||
- "<Control>o",
|
||
+ "<Super>o",
|
||
N_("View the selected memo"),
|
||
G_CALLBACK (action_memo_open_cb) },
|
||
|
||
@@ -743,7 +743,7 @@
|
||
{ "memo-preview",
|
||
NULL,
|
||
N_("Memo _Preview"),
|
||
- "<Control>m",
|
||
+ "<Super>m",
|
||
N_("Show memo preview pane"),
|
||
G_CALLBACK (action_memo_preview_cb),
|
||
TRUE }
|
||
@@ -829,7 +829,7 @@
|
||
{ "memo-list-print",
|
||
"document-print",
|
||
N_("Print…"),
|
||
- "<Control>p",
|
||
+ "<Super>p",
|
||
N_("Print the list of memos"),
|
||
G_CALLBACK (action_memo_list_print_cb) },
|
||
|
||
diff -urN a/src/modules/calendar/e-task-shell-backend.c b/src/modules/calendar/e-task-shell-backend.c
|
||
--- a/src/modules/calendar/e-task-shell-backend.c 2025-06-07 14:20:57.371397702 -0700
|
||
+++ b/src/modules/calendar/e-task-shell-backend.c 2025-06-07 14:27:24.059673092 -0700
|
||
@@ -73,14 +73,14 @@
|
||
{ "task-new",
|
||
"stock_task",
|
||
NC_("New", "_Task"),
|
||
- "<Shift><Control>t",
|
||
+ "<Shift><Super>t",
|
||
N_("Create a new task"),
|
||
G_CALLBACK (action_task_new_cb) },
|
||
|
||
{ "task-assigned-new",
|
||
"stock_task-assigned-to",
|
||
NC_("New", "Assigne_d Task"),
|
||
- "<Shift><Control>i",
|
||
+ "<Shift><Super>i",
|
||
N_("Create a new assigned task"),
|
||
G_CALLBACK (action_task_new_cb) }
|
||
};
|
||
diff -urN a/src/modules/calendar/e-task-shell-view-actions.c b/src/modules/calendar/e-task-shell-view-actions.c
|
||
--- a/src/modules/calendar/e-task-shell-view-actions.c 2025-06-07 14:20:57.371397702 -0700
|
||
+++ b/src/modules/calendar/e-task-shell-view-actions.c 2025-06-07 14:27:24.063673134 -0700
|
||
@@ -701,21 +701,21 @@
|
||
{ "task-find",
|
||
"edit-find",
|
||
N_("_Find in Task…"),
|
||
- "<Shift><Control>f",
|
||
+ "<Shift><Super>f",
|
||
N_("Search for text in the displayed task"),
|
||
G_CALLBACK (action_task_find_cb) },
|
||
|
||
{ "task-forward",
|
||
"mail-forward",
|
||
N_("_Forward as iCalendar…"),
|
||
- "<Control>f",
|
||
+ "<Super>f",
|
||
NULL, /* XXX Add a tooltip! */
|
||
G_CALLBACK (action_task_forward_cb) },
|
||
|
||
{ "task-list-copy",
|
||
"edit-copy",
|
||
N_("_Copy…"),
|
||
- "<Control>c",
|
||
+ "<Super>c",
|
||
NULL, /* XXX Add a tooltip! */
|
||
G_CALLBACK (action_task_list_copy_cb) },
|
||
|
||
@@ -785,7 +785,7 @@
|
||
{ "task-mark-complete",
|
||
NULL,
|
||
N_("_Mark as Complete"),
|
||
- "<Control>k",
|
||
+ "<Super>k",
|
||
N_("Mark selected tasks as complete"),
|
||
G_CALLBACK (action_task_mark_complete_cb) },
|
||
|
||
@@ -806,7 +806,7 @@
|
||
{ "task-open",
|
||
"document-open",
|
||
N_("_Open Task"),
|
||
- "<Control>o",
|
||
+ "<Super>o",
|
||
N_("View the selected task"),
|
||
G_CALLBACK (action_task_open_cb) },
|
||
|
||
@@ -820,7 +820,7 @@
|
||
{ "task-purge",
|
||
NULL,
|
||
N_("Purg_e"),
|
||
- "<Control>e",
|
||
+ "<Super>e",
|
||
N_("Delete completed tasks"),
|
||
G_CALLBACK (action_task_purge_cb) },
|
||
|
||
@@ -909,7 +909,7 @@
|
||
{ "task-preview",
|
||
NULL,
|
||
N_("Task _Preview"),
|
||
- "<Control>m",
|
||
+ "<Super>m",
|
||
N_("Show task preview pane"),
|
||
G_CALLBACK (action_task_preview_cb),
|
||
TRUE }
|
||
@@ -1058,7 +1058,7 @@
|
||
{ "task-list-print",
|
||
"document-print",
|
||
N_("Print…"),
|
||
- "<Control>p",
|
||
+ "<Super>p",
|
||
N_("Print the list of tasks"),
|
||
G_CALLBACK (action_task_list_print_cb) },
|
||
|
||
diff -urN a/src/modules/mail/e-mail-shell-backend.c b/src/modules/mail/e-mail-shell-backend.c
|
||
--- a/src/modules/mail/e-mail-shell-backend.c 2025-06-07 14:20:57.379397797 -0700
|
||
+++ b/src/modules/mail/e-mail-shell-backend.c 2025-06-07 14:27:24.063673134 -0700
|
||
@@ -421,7 +421,7 @@
|
||
{ "mail-message-new",
|
||
"mail-message-new",
|
||
NC_("New", "_Mail Message"),
|
||
- "<Shift><Control>m",
|
||
+ "<Shift><Super>m",
|
||
N_("Compose a new mail message"),
|
||
G_CALLBACK (action_mail_message_new_cb) }
|
||
};
|
||
diff -urN a/src/modules/mail/e-mail-shell-view-actions.c b/src/modules/mail/e-mail-shell-view-actions.c
|
||
--- a/src/modules/mail/e-mail-shell-view-actions.c 2025-06-07 14:20:57.379397797 -0700
|
||
+++ b/src/modules/mail/e-mail-shell-view-actions.c 2025-06-07 14:27:24.063673134 -0700
|
||
@@ -1634,14 +1634,14 @@
|
||
{ "mail-folder-expunge",
|
||
NULL,
|
||
N_("E_xpunge"),
|
||
- "<Control>e",
|
||
+ "<Super>e",
|
||
N_("Permanently remove all deleted messages from this folder"),
|
||
G_CALLBACK (action_mail_folder_expunge_cb) },
|
||
|
||
{ "mail-folder-mark-all-as-read",
|
||
"mail-mark-read",
|
||
N_("Mar_k All Messages as Read"),
|
||
- "<Control>slash",
|
||
+ "<Super>slash",
|
||
N_("Mark all messages in the folder as read"),
|
||
G_CALLBACK (action_mail_folder_mark_all_as_read_cb) },
|
||
|
||
@@ -1684,14 +1684,14 @@
|
||
{ "mail-folder-select-thread",
|
||
NULL,
|
||
N_("Select Message _Thread"),
|
||
- "<Control>h",
|
||
+ "<Super>h",
|
||
N_("Select all messages in the same thread as the selected message"),
|
||
G_CALLBACK (action_mail_folder_select_thread_cb) },
|
||
|
||
{ "mail-folder-select-subthread",
|
||
NULL,
|
||
N_("Select Message S_ubthread"),
|
||
- "<Shift><Control>h",
|
||
+ "<Shift><Super>h",
|
||
N_("Select all replies to the currently selected message"),
|
||
G_CALLBACK (action_mail_folder_select_subthread_cb) },
|
||
|
||
@@ -1712,7 +1712,7 @@
|
||
{ "mail-goto-folder",
|
||
NULL,
|
||
N_("Go to _Folder"),
|
||
- "<Control>g",
|
||
+ "<Super>g",
|
||
N_("Opens a dialog to select a folder to go to"),
|
||
G_CALLBACK (action_mail_goto_folder_cb) },
|
||
|
||
@@ -1789,7 +1789,7 @@
|
||
{ "mail-threads-collapse-all",
|
||
NULL,
|
||
N_("Collapse All _Threads"),
|
||
- "<Shift><Control>b",
|
||
+ "<Shift><Super>b",
|
||
N_("Collapse all message threads"),
|
||
G_CALLBACK (action_mail_threads_collapse_all_cb) },
|
||
|
||
@@ -1916,7 +1916,7 @@
|
||
{ "mail-preview",
|
||
NULL,
|
||
N_("Show Message _Preview"),
|
||
- "<Control>m",
|
||
+ "<Super>m",
|
||
N_("Show message preview pane"),
|
||
NULL, /* Handled by property bindings */
|
||
TRUE },
|
||
@@ -1948,7 +1948,7 @@
|
||
{ "mail-threads-group-by",
|
||
NULL,
|
||
N_("_Group By Threads"),
|
||
- "<Control>t",
|
||
+ "<Super>t",
|
||
N_("Threaded message list"),
|
||
NULL, /* Handled by property bindings */
|
||
FALSE },
|
||
diff -urN a/src/modules/mail/e-mail-shell-view-actions.c.orig b/src/modules/mail/e-mail-shell-view-actions.c.orig
|
||
--- a/src/modules/mail/e-mail-shell-view-actions.c.orig 1969-12-31 16:00:00.000000000 -0800
|
||
+++ b/src/modules/mail/e-mail-shell-view-actions.c.orig 2025-06-07 14:20:57.379397797 -0700
|
||
@@ -0,0 +1,2455 @@
|
||
+/*
|
||
+ * e-mail-shell-view-actions.c
|
||
+ *
|
||
+ * This program is free software; you can redistribute it and/or modify it
|
||
+ * under the terms of the GNU Lesser General Public License as published by
|
||
+ * the Free Software Foundation.
|
||
+ *
|
||
+ * This program is distributed in the hope that it will be useful, but
|
||
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||
+ * for more details.
|
||
+ *
|
||
+ * You should have received a copy of the GNU Lesser General Public License
|
||
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||
+ *
|
||
+ *
|
||
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
|
||
+ *
|
||
+ */
|
||
+
|
||
+#include "evolution-config.h"
|
||
+
|
||
+#include "mail/e-mail-folder-sort-order-dialog.h"
|
||
+
|
||
+#include "e-mail-shell-view-private.h"
|
||
+
|
||
+static void
|
||
+mail_shell_view_folder_created_cb (EMailFolderCreateDialog *dialog,
|
||
+ CamelStore *store,
|
||
+ const gchar *folder_name,
|
||
+ GWeakRef *folder_tree_weak_ref)
|
||
+{
|
||
+ EMFolderTree *folder_tree;
|
||
+
|
||
+ folder_tree = g_weak_ref_get (folder_tree_weak_ref);
|
||
+
|
||
+ if (folder_tree != NULL) {
|
||
+ gchar *folder_uri;
|
||
+
|
||
+ /* Select the newly created folder. */
|
||
+ folder_uri = e_mail_folder_uri_build (store, folder_name);
|
||
+ em_folder_tree_set_selected (folder_tree, folder_uri, FALSE);
|
||
+ g_free (folder_uri);
|
||
+
|
||
+ g_object_unref (folder_tree);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_account_disable_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellSidebar *mail_shell_sidebar;
|
||
+ EShellView *shell_view;
|
||
+ EShellWindow *shell_window;
|
||
+ EShellBackend *shell_backend;
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+ EMailAccountStore *account_store;
|
||
+ EMFolderTree *folder_tree;
|
||
+ CamelStore *store;
|
||
+
|
||
+ mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_backend = e_shell_view_get_shell_backend (shell_view);
|
||
+ shell_window = e_shell_view_get_shell_window (shell_view);
|
||
+
|
||
+ backend = E_MAIL_BACKEND (shell_backend);
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+ account_store = e_mail_ui_session_get_account_store (
|
||
+ E_MAIL_UI_SESSION (session));
|
||
+
|
||
+ folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
|
||
+ store = em_folder_tree_ref_selected_store (folder_tree);
|
||
+ g_return_if_fail (store != NULL);
|
||
+
|
||
+ e_mail_account_store_disable_service (
|
||
+ account_store,
|
||
+ GTK_WINDOW (shell_window),
|
||
+ CAMEL_SERVICE (store));
|
||
+
|
||
+ e_shell_view_update_actions (shell_view);
|
||
+
|
||
+ g_object_unref (store);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_account_properties_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellSidebar *mail_shell_sidebar;
|
||
+ EShell *shell;
|
||
+ EShellView *shell_view;
|
||
+ EShellWindow *shell_window;
|
||
+ EShellBackend *shell_backend;
|
||
+ ESourceRegistry *registry;
|
||
+ ESource *source;
|
||
+ EMFolderTree *folder_tree;
|
||
+ CamelService *service;
|
||
+ CamelStore *store;
|
||
+ const gchar *uid;
|
||
+
|
||
+ mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_backend = e_shell_view_get_shell_backend (shell_view);
|
||
+ shell_window = e_shell_view_get_shell_window (shell_view);
|
||
+ shell = e_shell_backend_get_shell (shell_backend);
|
||
+
|
||
+ folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
|
||
+ store = em_folder_tree_ref_selected_store (folder_tree);
|
||
+ g_return_if_fail (store != NULL);
|
||
+
|
||
+ service = CAMEL_SERVICE (store);
|
||
+ uid = camel_service_get_uid (service);
|
||
+ registry = e_shell_get_registry (shell);
|
||
+ source = e_source_registry_ref_source (registry, uid);
|
||
+ g_return_if_fail (source != NULL);
|
||
+
|
||
+ e_mail_shell_backend_edit_account (
|
||
+ E_MAIL_SHELL_BACKEND (shell_backend),
|
||
+ GTK_WINDOW (shell_window), source);
|
||
+
|
||
+ g_object_unref (source);
|
||
+ g_object_unref (store);
|
||
+}
|
||
+
|
||
+static void
|
||
+account_refresh_folder_info_received_cb (GObject *source,
|
||
+ GAsyncResult *result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ CamelStore *store;
|
||
+ CamelFolderInfo *info;
|
||
+ EActivity *activity;
|
||
+ GError *error = NULL;
|
||
+
|
||
+ store = CAMEL_STORE (source);
|
||
+ activity = E_ACTIVITY (user_data);
|
||
+
|
||
+ info = camel_store_get_folder_info_finish (store, result, &error);
|
||
+
|
||
+ /* Provider takes care of notifications of new/removed
|
||
+ * folders, thus it's enough to free the returned list. */
|
||
+ camel_folder_info_free (info);
|
||
+
|
||
+ if (e_activity_handle_cancellation (activity, error)) {
|
||
+ g_error_free (error);
|
||
+
|
||
+ } else if (error != NULL) {
|
||
+ g_warning ("%s: %s", G_STRFUNC, error->message);
|
||
+ g_error_free (error);
|
||
+ }
|
||
+
|
||
+ g_clear_object (&activity);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_account_refresh_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellContent *mail_shell_content;
|
||
+ EMailShellSidebar *mail_shell_sidebar;
|
||
+ EMFolderTree *folder_tree;
|
||
+ EMailView *mail_view;
|
||
+ EActivity *activity;
|
||
+ ESourceRegistry *registry;
|
||
+ ESource *source;
|
||
+ EShell *shell;
|
||
+ CamelStore *store;
|
||
+ GCancellable *cancellable;
|
||
+
|
||
+ mail_shell_content = mail_shell_view->priv->mail_shell_content;
|
||
+ mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
|
||
+
|
||
+ folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
|
||
+ store = em_folder_tree_ref_selected_store (folder_tree);
|
||
+ g_return_if_fail (store != NULL);
|
||
+
|
||
+ mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
|
||
+ activity = e_mail_reader_new_activity (E_MAIL_READER (mail_view));
|
||
+ cancellable = e_activity_get_cancellable (activity);
|
||
+
|
||
+ shell = e_shell_backend_get_shell (e_shell_view_get_shell_backend (E_SHELL_VIEW (mail_shell_view)));
|
||
+ registry = e_shell_get_registry (shell);
|
||
+ source = e_source_registry_ref_source (registry, camel_service_get_uid (CAMEL_SERVICE (store)));
|
||
+ g_return_if_fail (source != NULL);
|
||
+
|
||
+ e_shell_allow_auth_prompt_for (shell, source);
|
||
+
|
||
+ camel_store_get_folder_info (
|
||
+ store, NULL,
|
||
+ CAMEL_STORE_FOLDER_INFO_RECURSIVE | CAMEL_STORE_FOLDER_INFO_REFRESH,
|
||
+ G_PRIORITY_DEFAULT, cancellable,
|
||
+ account_refresh_folder_info_received_cb, activity);
|
||
+
|
||
+ g_clear_object (&source);
|
||
+ g_clear_object (&store);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_create_search_folder_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellContent *mail_shell_content;
|
||
+ EMailReader *reader;
|
||
+ EShellView *shell_view;
|
||
+ EShellBackend *shell_backend;
|
||
+ EShellSearchbar *searchbar;
|
||
+ EFilterRule *search_rule;
|
||
+ EMVFolderRule *vfolder_rule;
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+ EMailView *mail_view;
|
||
+ CamelFolder *folder;
|
||
+ const gchar *search_text;
|
||
+ gchar *folder_uri;
|
||
+ gchar *rule_name;
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_backend = e_shell_view_get_shell_backend (shell_view);
|
||
+
|
||
+ mail_shell_content = mail_shell_view->priv->mail_shell_content;
|
||
+ mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
|
||
+ searchbar = e_mail_shell_content_get_searchbar (mail_shell_content);
|
||
+
|
||
+ search_rule = e_shell_view_get_search_rule (shell_view);
|
||
+ g_return_if_fail (search_rule != NULL);
|
||
+
|
||
+ search_text = e_shell_searchbar_get_search_text (searchbar);
|
||
+ if (search_text == NULL || *search_text == '\0')
|
||
+ search_text = "''";
|
||
+
|
||
+ backend = E_MAIL_BACKEND (shell_backend);
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+
|
||
+ search_rule = vfolder_clone_rule (session, search_rule);
|
||
+ g_return_if_fail (search_rule != NULL);
|
||
+
|
||
+ rule_name = g_strdup_printf ("%s %s", search_rule->name, search_text);
|
||
+ e_filter_rule_set_source (search_rule, E_FILTER_SOURCE_INCOMING);
|
||
+ e_filter_rule_set_name (search_rule, rule_name);
|
||
+ g_free (rule_name);
|
||
+
|
||
+ reader = E_MAIL_READER (mail_view);
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+ folder_uri = e_mail_folder_uri_from_folder (folder);
|
||
+
|
||
+ vfolder_rule = EM_VFOLDER_RULE (search_rule);
|
||
+ em_vfolder_rule_add_source (vfolder_rule, folder_uri);
|
||
+ vfolder_gui_add_rule (vfolder_rule);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+ g_free (folder_uri);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_attachment_bar_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailDisplay *mail_display;
|
||
+ EAttachmentView *attachment_view;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view));
|
||
+
|
||
+ mail_display = e_mail_reader_get_mail_display (E_MAIL_READER (mail_shell_view->priv->mail_shell_content));
|
||
+ attachment_view = e_mail_display_get_attachment_view (mail_display);
|
||
+ if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
|
||
+ EAttachmentStore *store;
|
||
+ guint num_attachments;
|
||
+
|
||
+ store = e_attachment_bar_get_store (E_ATTACHMENT_BAR (attachment_view));
|
||
+ num_attachments = e_attachment_store_get_num_attachments (store);
|
||
+ gtk_widget_set_visible (GTK_WIDGET (attachment_view), num_attachments > 0);
|
||
+ } else {
|
||
+ gtk_widget_hide (GTK_WIDGET (attachment_view));
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_to_do_bar_cb (GtkAction *action,
|
||
+ EShellView *shell_view)
|
||
+{
|
||
+ EShellContent *shell_content;
|
||
+ GtkWidget *to_do_pane;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_SHELL_VIEW (shell_view));
|
||
+
|
||
+ shell_content = e_shell_view_get_shell_content (shell_view);
|
||
+ to_do_pane = e_mail_shell_content_get_to_do_pane (E_MAIL_SHELL_CONTENT (shell_content));
|
||
+
|
||
+ gtk_widget_set_visible (to_do_pane, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_download_finished_cb (CamelStore *store,
|
||
+ GAsyncResult *result,
|
||
+ EActivity *activity)
|
||
+{
|
||
+ EAlertSink *alert_sink;
|
||
+ GError *error = NULL;
|
||
+
|
||
+ alert_sink = e_activity_get_alert_sink (activity);
|
||
+
|
||
+ e_mail_store_prepare_for_offline_finish (store, result, &error);
|
||
+
|
||
+ if (e_activity_handle_cancellation (activity, error)) {
|
||
+ g_error_free (error);
|
||
+
|
||
+ } else if (error != NULL) {
|
||
+ e_alert_submit (
|
||
+ alert_sink, "mail:prepare-for-offline",
|
||
+ camel_service_get_display_name (CAMEL_SERVICE (store)),
|
||
+ error->message, NULL);
|
||
+ g_error_free (error);
|
||
+ }
|
||
+
|
||
+ g_object_unref (activity);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_download_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellContent *mail_shell_content;
|
||
+ EMailView *mail_view;
|
||
+ EMailReader *reader;
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+ GList *list, *link;
|
||
+
|
||
+ mail_shell_content = mail_shell_view->priv->mail_shell_content;
|
||
+ mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
|
||
+
|
||
+ reader = E_MAIL_READER (mail_view);
|
||
+ backend = e_mail_reader_get_backend (reader);
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+
|
||
+ list = camel_session_list_services (CAMEL_SESSION (session));
|
||
+
|
||
+ for (link = list; link != NULL; link = g_list_next (link)) {
|
||
+ EActivity *activity;
|
||
+ CamelService *service;
|
||
+ GCancellable *cancellable;
|
||
+
|
||
+ service = CAMEL_SERVICE (link->data);
|
||
+
|
||
+ if (!CAMEL_IS_STORE (service))
|
||
+ continue;
|
||
+
|
||
+ activity = e_mail_reader_new_activity (reader);
|
||
+ cancellable = e_activity_get_cancellable (activity);
|
||
+
|
||
+ e_mail_store_prepare_for_offline (
|
||
+ CAMEL_STORE (service), G_PRIORITY_DEFAULT,
|
||
+ cancellable, (GAsyncReadyCallback)
|
||
+ action_mail_download_finished_cb, activity);
|
||
+ }
|
||
+
|
||
+ g_list_free_full (list, (GDestroyNotify) g_object_unref);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_flush_outbox_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EShellBackend *shell_backend;
|
||
+ EShellView *shell_view;
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_backend = e_shell_view_get_shell_backend (shell_view);
|
||
+
|
||
+ backend = E_MAIL_BACKEND (shell_backend);
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+
|
||
+ mail_send_immediately (session);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_folder_copy_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellSidebar *mail_shell_sidebar;
|
||
+ EShellContent *shell_content;
|
||
+ EShellWindow *shell_window;
|
||
+ EShellView *shell_view;
|
||
+ EMFolderTree *folder_tree;
|
||
+ EMailSession *session;
|
||
+ gchar *selected_uri;
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_window = e_shell_view_get_shell_window (shell_view);
|
||
+ shell_content = e_shell_view_get_shell_content (shell_view);
|
||
+
|
||
+ mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
|
||
+ folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
|
||
+ selected_uri = em_folder_tree_get_selected_uri (folder_tree);
|
||
+ session = em_folder_tree_get_session (folder_tree);
|
||
+ g_return_if_fail (selected_uri != NULL);
|
||
+
|
||
+ em_folder_utils_copy_folder (
|
||
+ GTK_WINDOW (shell_window),
|
||
+ session,
|
||
+ E_ALERT_SINK (shell_content),
|
||
+ selected_uri, FALSE);
|
||
+
|
||
+ g_free (selected_uri);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_folder_delete_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellContent *mail_shell_content;
|
||
+ EMailShellSidebar *mail_shell_sidebar;
|
||
+ EMailView *mail_view;
|
||
+ EMFolderTree *folder_tree;
|
||
+ CamelStore *selected_store = NULL;
|
||
+ gchar *selected_folder_name = NULL;
|
||
+
|
||
+ mail_shell_content = mail_shell_view->priv->mail_shell_content;
|
||
+ mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
|
||
+
|
||
+ mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
|
||
+ folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
|
||
+
|
||
+ em_folder_tree_get_selected (
|
||
+ folder_tree, &selected_store, &selected_folder_name);
|
||
+ g_return_if_fail (CAMEL_IS_STORE (selected_store));
|
||
+ g_return_if_fail (selected_folder_name != NULL);
|
||
+
|
||
+ e_mail_reader_delete_folder_name (
|
||
+ E_MAIL_READER (mail_view),
|
||
+ selected_store, selected_folder_name);
|
||
+
|
||
+ g_object_unref (selected_store);
|
||
+ g_free (selected_folder_name);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_folder_edit_sort_order_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailView *mail_view;
|
||
+ EMFolderTree *folder_tree;
|
||
+ CamelStore *store;
|
||
+ GtkWidget *dialog;
|
||
+ GtkWindow *window;
|
||
+ gchar *selected_uri;
|
||
+
|
||
+ folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_view->priv->mail_shell_sidebar);
|
||
+ store = em_folder_tree_ref_selected_store (folder_tree);
|
||
+
|
||
+ g_return_if_fail (store != NULL);
|
||
+
|
||
+ selected_uri = em_folder_tree_get_selected_uri (folder_tree);
|
||
+
|
||
+ mail_view = e_mail_shell_content_get_mail_view (mail_shell_view->priv->mail_shell_content);
|
||
+ window = e_mail_reader_get_window (E_MAIL_READER (mail_view));
|
||
+
|
||
+ dialog = e_mail_folder_sort_order_dialog_new (window, store, selected_uri);
|
||
+
|
||
+ gtk_dialog_run (GTK_DIALOG (dialog));
|
||
+
|
||
+ gtk_widget_destroy (dialog);
|
||
+ g_object_unref (store);
|
||
+ g_free (selected_uri);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_folder_expunge_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellContent *mail_shell_content;
|
||
+ EMailShellSidebar *mail_shell_sidebar;
|
||
+ EMailView *mail_view;
|
||
+ EMFolderTree *folder_tree;
|
||
+ CamelStore *selected_store = NULL;
|
||
+ gchar *selected_folder_name = NULL;
|
||
+
|
||
+ /* This handles both the "folder-expunge" and "account-expunge"
|
||
+ * actions. */
|
||
+
|
||
+ mail_shell_content = mail_shell_view->priv->mail_shell_content;
|
||
+ mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
|
||
+
|
||
+ mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
|
||
+ folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
|
||
+
|
||
+ /* Get the folder from the folder tree, not the message list.
|
||
+ * This correctly handles the use case of right-clicking on
|
||
+ * the "Trash" folder and selecting "Empty Trash" without
|
||
+ * actually selecting the folder. In that case the message
|
||
+ * list would not contain the correct folder to expunge. */
|
||
+ em_folder_tree_get_selected (
|
||
+ folder_tree, &selected_store, &selected_folder_name);
|
||
+ g_return_if_fail (CAMEL_IS_STORE (selected_store));
|
||
+ g_return_if_fail (selected_folder_name != NULL);
|
||
+
|
||
+ e_mail_reader_expunge_folder_name (
|
||
+ E_MAIL_READER (mail_view),
|
||
+ selected_store, selected_folder_name);
|
||
+
|
||
+ g_object_unref (selected_store);
|
||
+ g_free (selected_folder_name);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_folder_empty_junk_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellContent *mail_shell_content;
|
||
+ EMailShellSidebar *mail_shell_sidebar;
|
||
+ EMailView *mail_view;
|
||
+ EMFolderTree *folder_tree;
|
||
+ CamelStore *selected_store = NULL;
|
||
+ gchar *selected_folder_name = NULL;
|
||
+
|
||
+ mail_shell_content = mail_shell_view->priv->mail_shell_content;
|
||
+ mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
|
||
+
|
||
+ mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
|
||
+ folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
|
||
+
|
||
+ /* Get the folder from the folder tree, not the message list.
|
||
+ * This correctly handles the use case of right-clicking on
|
||
+ * the "Junk" folder and selecting "Empty Junk" without
|
||
+ * actually selecting the folder. In that case the message
|
||
+ * list would not contain the correct folder. */
|
||
+ em_folder_tree_get_selected (folder_tree, &selected_store, &selected_folder_name);
|
||
+ g_return_if_fail (CAMEL_IS_STORE (selected_store));
|
||
+ g_return_if_fail (selected_folder_name != NULL);
|
||
+
|
||
+ e_mail_reader_empty_junk_folder_name (E_MAIL_READER (mail_view), selected_store, selected_folder_name);
|
||
+
|
||
+ g_object_unref (selected_store);
|
||
+ g_free (selected_folder_name);
|
||
+}
|
||
+
|
||
+typedef struct _AsyncContext {
|
||
+ EActivity *activity;
|
||
+ EMailShellView *mail_shell_view;
|
||
+ gboolean can_subfolders;
|
||
+ GQueue folder_names;
|
||
+} AsyncContext;
|
||
+
|
||
+static void
|
||
+async_context_free (AsyncContext *context)
|
||
+{
|
||
+ if (context->activity != NULL)
|
||
+ g_object_unref (context->activity);
|
||
+
|
||
+ if (context->mail_shell_view != NULL)
|
||
+ g_object_unref (context->mail_shell_view);
|
||
+
|
||
+ /* This should be empty already, unless an error occurred... */
|
||
+ while (!g_queue_is_empty (&context->folder_names))
|
||
+ g_free (g_queue_pop_head (&context->folder_names));
|
||
+
|
||
+ g_slice_free (AsyncContext, context);
|
||
+}
|
||
+
|
||
+static void
|
||
+mark_all_read_thread (GSimpleAsyncResult *simple,
|
||
+ GObject *object,
|
||
+ GCancellable *cancellable)
|
||
+{
|
||
+ AsyncContext *context;
|
||
+ CamelStore *store;
|
||
+ CamelFolder *folder;
|
||
+ GPtrArray *uids;
|
||
+ gint ii;
|
||
+ GError *error = NULL;
|
||
+
|
||
+ context = g_simple_async_result_get_op_res_gpointer (simple);
|
||
+ store = CAMEL_STORE (object);
|
||
+
|
||
+ while (!g_queue_is_empty (&context->folder_names) && !error) {
|
||
+ gchar *folder_name;
|
||
+
|
||
+ folder_name = g_queue_pop_head (&context->folder_names);
|
||
+ folder = camel_store_get_folder_sync (
|
||
+ store, folder_name, 0, cancellable, &error);
|
||
+ g_free (folder_name);
|
||
+
|
||
+ if (folder == NULL)
|
||
+ break;
|
||
+
|
||
+ camel_folder_freeze (folder);
|
||
+
|
||
+ uids = camel_folder_get_uids (folder);
|
||
+
|
||
+ for (ii = 0; ii < uids->len; ii++)
|
||
+ camel_folder_set_message_flags (
|
||
+ folder, uids->pdata[ii],
|
||
+ CAMEL_MESSAGE_SEEN,
|
||
+ CAMEL_MESSAGE_SEEN);
|
||
+
|
||
+ camel_folder_thaw (folder);
|
||
+
|
||
+ /* Save changes to the server immediately. */
|
||
+ camel_folder_synchronize_sync (folder, FALSE, cancellable, &error);
|
||
+
|
||
+ camel_folder_free_uids (folder, uids);
|
||
+ g_object_unref (folder);
|
||
+ }
|
||
+
|
||
+ if (error != NULL)
|
||
+ g_simple_async_result_take_error (simple, error);
|
||
+}
|
||
+
|
||
+static void
|
||
+mark_all_read_done_cb (GObject *source,
|
||
+ GAsyncResult *result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ GSimpleAsyncResult *simple;
|
||
+ AsyncContext *context;
|
||
+ GError *local_error = NULL;
|
||
+
|
||
+ g_return_if_fail (
|
||
+ g_simple_async_result_is_valid (
|
||
+ result, source, mark_all_read_thread));
|
||
+
|
||
+ simple = G_SIMPLE_ASYNC_RESULT (result);
|
||
+ context = g_simple_async_result_get_op_res_gpointer (simple);
|
||
+
|
||
+ if (g_simple_async_result_propagate_error (simple, &local_error) &&
|
||
+ local_error &&
|
||
+ !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||
+ EAlertSink *alert_sink;
|
||
+
|
||
+ alert_sink = e_activity_get_alert_sink (context->activity);
|
||
+
|
||
+ e_alert_submit (
|
||
+ alert_sink, "mail:mark-all-read",
|
||
+ local_error->message, NULL);
|
||
+ }
|
||
+
|
||
+ g_clear_error (&local_error);
|
||
+
|
||
+ e_activity_set_state (context->activity, E_ACTIVITY_COMPLETED);
|
||
+}
|
||
+
|
||
+static void
|
||
+mark_all_read_collect_folder_names (GQueue *folder_names,
|
||
+ CamelFolderInfo *folder_info)
|
||
+{
|
||
+ while (folder_info != NULL) {
|
||
+ if (folder_info->child != NULL)
|
||
+ mark_all_read_collect_folder_names (
|
||
+ folder_names, folder_info->child);
|
||
+
|
||
+ g_queue_push_tail (
|
||
+ folder_names, g_strdup (folder_info->full_name));
|
||
+
|
||
+ folder_info = folder_info->next;
|
||
+ }
|
||
+}
|
||
+
|
||
+enum {
|
||
+ MARK_ALL_READ_CANCEL,
|
||
+ MARK_ALL_READ_CURRENT_ONLY,
|
||
+ MARK_ALL_READ_WITH_SUBFOLDERS
|
||
+};
|
||
+
|
||
+static gint
|
||
+mark_all_read_prompt_user (EMailShellView *mail_shell_view,
|
||
+ gboolean with_subfolders)
|
||
+{
|
||
+ EShellView *shell_view;
|
||
+ EShellWindow *shell_window;
|
||
+ GtkWindow *parent;
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_window = e_shell_view_get_shell_window (shell_view);
|
||
+ parent = GTK_WINDOW (shell_window);
|
||
+
|
||
+ if (with_subfolders) {
|
||
+ GSettings *settings;
|
||
+ GdkDisplay *display;
|
||
+ GdkKeymap *keymap;
|
||
+
|
||
+ display = gtk_widget_get_display (GTK_WIDGET (e_shell_view_get_shell_window (E_SHELL_VIEW (mail_shell_view))));
|
||
+ keymap = gdk_keymap_get_for_display (display);
|
||
+
|
||
+ settings = e_util_ref_settings ("org.gnome.evolution.mail");
|
||
+ if ((gdk_keymap_get_modifier_state (keymap) & (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK)) != GDK_SHIFT_MASK &&
|
||
+ !g_settings_get_boolean (settings, "prompt-on-mark-all-read")) {
|
||
+ g_object_unref (settings);
|
||
+ return MARK_ALL_READ_CURRENT_ONLY;
|
||
+ }
|
||
+
|
||
+ switch (e_alert_run_dialog_for_args (parent,
|
||
+ "mail:ask-mark-all-read-sub", NULL)) {
|
||
+ case GTK_RESPONSE_YES:
|
||
+ g_object_unref (settings);
|
||
+ return MARK_ALL_READ_WITH_SUBFOLDERS;
|
||
+ case GTK_RESPONSE_NO:
|
||
+ g_object_unref (settings);
|
||
+ return MARK_ALL_READ_CURRENT_ONLY;
|
||
+ case GTK_RESPONSE_ACCEPT:
|
||
+ g_settings_set_boolean (settings, "prompt-on-mark-all-read", FALSE);
|
||
+ g_object_unref (settings);
|
||
+ return MARK_ALL_READ_CURRENT_ONLY;
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ g_object_unref (settings);
|
||
+ } else if (e_util_prompt_user (parent,
|
||
+ "org.gnome.evolution.mail",
|
||
+ "prompt-on-mark-all-read",
|
||
+ "mail:ask-mark-all-read", NULL))
|
||
+ return MARK_ALL_READ_CURRENT_ONLY;
|
||
+
|
||
+ return MARK_ALL_READ_CANCEL;
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+mark_all_read_child_has_unread (CamelFolderInfo *folder_info)
|
||
+{
|
||
+ gboolean any_has = FALSE;
|
||
+
|
||
+ if (!folder_info)
|
||
+ return FALSE;
|
||
+
|
||
+ while (!any_has && folder_info) {
|
||
+ any_has = folder_info->unread > 0 || mark_all_read_child_has_unread (folder_info->child);
|
||
+
|
||
+ folder_info = folder_info->next;
|
||
+ }
|
||
+
|
||
+ return any_has;
|
||
+}
|
||
+
|
||
+static void
|
||
+mark_all_read_got_folder_info (GObject *source,
|
||
+ GAsyncResult *result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ CamelStore *store = CAMEL_STORE (source);
|
||
+ AsyncContext *context = user_data;
|
||
+ EAlertSink *alert_sink;
|
||
+ GCancellable *cancellable;
|
||
+ GSimpleAsyncResult *simple;
|
||
+ CamelFolderInfo *folder_info;
|
||
+ gint response;
|
||
+ GError *error = NULL;
|
||
+
|
||
+ alert_sink = e_activity_get_alert_sink (context->activity);
|
||
+ cancellable = e_activity_get_cancellable (context->activity);
|
||
+
|
||
+ folder_info = camel_store_get_folder_info_finish (
|
||
+ store, result, &error);
|
||
+
|
||
+ if (e_activity_handle_cancellation (context->activity, error)) {
|
||
+ g_warn_if_fail (folder_info == NULL);
|
||
+ async_context_free (context);
|
||
+ g_error_free (error);
|
||
+ return;
|
||
+
|
||
+ } else if (error != NULL) {
|
||
+ g_warn_if_fail (folder_info == NULL);
|
||
+ e_alert_submit (
|
||
+ alert_sink, "mail:mark-all-read",
|
||
+ error->message, NULL);
|
||
+ async_context_free (context);
|
||
+ g_error_free (error);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ if (!folder_info) {
|
||
+ /* Otherwise the operation is stuck and the Evolution cannot be quit */
|
||
+ g_warn_if_fail (folder_info != NULL);
|
||
+ e_activity_set_state (context->activity, E_ACTIVITY_COMPLETED);
|
||
+ async_context_free (context);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ response = mark_all_read_prompt_user (
|
||
+ context->mail_shell_view,
|
||
+ context->can_subfolders && mark_all_read_child_has_unread (folder_info->child));
|
||
+
|
||
+ if (response == MARK_ALL_READ_CURRENT_ONLY)
|
||
+ g_queue_push_tail (
|
||
+ &context->folder_names,
|
||
+ g_strdup (folder_info->full_name));
|
||
+
|
||
+ if (response == MARK_ALL_READ_WITH_SUBFOLDERS)
|
||
+ mark_all_read_collect_folder_names (
|
||
+ &context->folder_names, folder_info);
|
||
+
|
||
+ camel_folder_info_free (folder_info);
|
||
+
|
||
+ if (g_queue_is_empty (&context->folder_names)) {
|
||
+ e_activity_set_state (context->activity, E_ACTIVITY_COMPLETED);
|
||
+ async_context_free (context);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ simple = g_simple_async_result_new (
|
||
+ source, mark_all_read_done_cb,
|
||
+ context, mark_all_read_thread);
|
||
+
|
||
+ g_simple_async_result_set_op_res_gpointer (
|
||
+ simple, context, (GDestroyNotify) async_context_free);
|
||
+
|
||
+ g_simple_async_result_run_in_thread (
|
||
+ simple, mark_all_read_thread,
|
||
+ G_PRIORITY_DEFAULT, cancellable);
|
||
+
|
||
+ g_object_unref (simple);
|
||
+}
|
||
+
|
||
+static void
|
||
+e_mail_shell_view_actions_mark_all_read (EMailShellView *mail_shell_view,
|
||
+ CamelStore *store,
|
||
+ const gchar *folder_name,
|
||
+ gboolean can_subfolders)
|
||
+{
|
||
+ EShellView *shell_view;
|
||
+ EShellBackend *shell_backend;
|
||
+ EShellContent *shell_content;
|
||
+ EAlertSink *alert_sink;
|
||
+ GCancellable *cancellable;
|
||
+ AsyncContext *context;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view));
|
||
+ g_return_if_fail (CAMEL_IS_STORE (store));
|
||
+ g_return_if_fail (folder_name != NULL);
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_backend = e_shell_view_get_shell_backend (shell_view);
|
||
+ shell_content = e_shell_view_get_shell_content (shell_view);
|
||
+
|
||
+ context = g_slice_new0 (AsyncContext);
|
||
+ context->mail_shell_view = g_object_ref (mail_shell_view);
|
||
+ context->can_subfolders = can_subfolders;
|
||
+ context->activity = e_activity_new ();
|
||
+ g_queue_init (&context->folder_names);
|
||
+
|
||
+ alert_sink = E_ALERT_SINK (shell_content);
|
||
+ e_activity_set_alert_sink (context->activity, alert_sink);
|
||
+
|
||
+ cancellable = camel_operation_new ();
|
||
+ e_activity_set_cancellable (context->activity, cancellable);
|
||
+
|
||
+ camel_operation_push_message (
|
||
+ cancellable, _("Marking messages as read…"));
|
||
+
|
||
+ e_shell_backend_add_activity (shell_backend, context->activity);
|
||
+
|
||
+ camel_store_get_folder_info (
|
||
+ store, folder_name,
|
||
+ can_subfolders ? CAMEL_STORE_FOLDER_INFO_RECURSIVE : 0,
|
||
+ G_PRIORITY_DEFAULT, cancellable,
|
||
+ mark_all_read_got_folder_info, context);
|
||
+
|
||
+ g_object_unref (cancellable);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_folder_mark_all_as_read_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellContent *mail_shell_content;
|
||
+ EMailReader *reader;
|
||
+ EMailView *mail_view;
|
||
+ CamelFolder *folder;
|
||
+
|
||
+ mail_shell_content = mail_shell_view->priv->mail_shell_content;
|
||
+ mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
|
||
+
|
||
+ reader = E_MAIL_READER (mail_view);
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+ g_return_if_fail (folder != NULL);
|
||
+
|
||
+ if (camel_folder_get_folder_summary (folder) != NULL &&
|
||
+ camel_folder_summary_get_unread_count (camel_folder_get_folder_summary (folder)) == 0) {
|
||
+ g_object_unref (folder);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ e_mail_shell_view_actions_mark_all_read (
|
||
+ mail_shell_view,
|
||
+ camel_folder_get_parent_store (folder),
|
||
+ camel_folder_get_full_name (folder),
|
||
+ FALSE);
|
||
+
|
||
+ g_object_unref (folder);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_popup_folder_mark_all_as_read_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellSidebar *mail_shell_sidebar;
|
||
+ EMFolderTree *folder_tree;
|
||
+ CamelStore *store = NULL;
|
||
+ gchar *folder_name = NULL;
|
||
+
|
||
+ mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
|
||
+ folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
|
||
+ em_folder_tree_get_selected (folder_tree, &store, &folder_name);
|
||
+
|
||
+ /* This action should only be activatable if a folder is selected. */
|
||
+ g_return_if_fail (store != NULL && folder_name != NULL);
|
||
+
|
||
+ e_mail_shell_view_actions_mark_all_read (
|
||
+ mail_shell_view, store, folder_name, TRUE);
|
||
+
|
||
+ g_object_unref (store);
|
||
+ g_free (folder_name);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_folder_move_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellSidebar *mail_shell_sidebar;
|
||
+ EShellContent *shell_content;
|
||
+ EShellWindow *shell_window;
|
||
+ EShellView *shell_view;
|
||
+ EMFolderTree *folder_tree;
|
||
+ EMailSession *session;
|
||
+ gchar *selected_uri;
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_window = e_shell_view_get_shell_window (shell_view);
|
||
+ shell_content = e_shell_view_get_shell_content (shell_view);
|
||
+
|
||
+ mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
|
||
+ folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
|
||
+ selected_uri = em_folder_tree_get_selected_uri (folder_tree);
|
||
+ session = em_folder_tree_get_session (folder_tree);
|
||
+ g_return_if_fail (selected_uri != NULL);
|
||
+
|
||
+ em_folder_utils_copy_folder (
|
||
+ GTK_WINDOW (shell_window),
|
||
+ session,
|
||
+ E_ALERT_SINK (shell_content),
|
||
+ selected_uri, TRUE);
|
||
+
|
||
+ g_free (selected_uri);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_folder_new_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EShellView *shell_view;
|
||
+ EShellWindow *shell_window;
|
||
+ EMailSession *session;
|
||
+ EMailShellSidebar *mail_shell_sidebar;
|
||
+ EMFolderTree *folder_tree;
|
||
+ GtkWidget *dialog;
|
||
+ CamelStore *store = NULL;
|
||
+ gchar *folder_name = NULL;
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_window = e_shell_view_get_shell_window (shell_view);
|
||
+
|
||
+ mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
|
||
+ folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
|
||
+
|
||
+ session = em_folder_tree_get_session (folder_tree);
|
||
+
|
||
+ dialog = e_mail_folder_create_dialog_new (
|
||
+ GTK_WINDOW (shell_window),
|
||
+ E_MAIL_UI_SESSION (session));
|
||
+
|
||
+ g_signal_connect_data (
|
||
+ dialog, "folder-created",
|
||
+ G_CALLBACK (mail_shell_view_folder_created_cb),
|
||
+ e_weak_ref_new (folder_tree),
|
||
+ (GClosureNotify) e_weak_ref_free, 0);
|
||
+
|
||
+ if (em_folder_tree_get_selected (folder_tree, &store, &folder_name)) {
|
||
+ em_folder_selector_set_selected (
|
||
+ EM_FOLDER_SELECTOR (dialog), store, folder_name);
|
||
+ g_object_unref (store);
|
||
+ g_free (folder_name);
|
||
+ }
|
||
+
|
||
+ gtk_widget_show (GTK_WIDGET (dialog));
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_folder_properties_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellSidebar *mail_shell_sidebar;
|
||
+ EShellView *shell_view;
|
||
+ EShellWindow *shell_window;
|
||
+ EShellContent *shell_content;
|
||
+ EMFolderTree *folder_tree;
|
||
+ CamelStore *store;
|
||
+ gchar *folder_name;
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_window = e_shell_view_get_shell_window (shell_view);
|
||
+ shell_content = e_shell_view_get_shell_content (shell_view);
|
||
+
|
||
+ mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
|
||
+ folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
|
||
+
|
||
+ if (!em_folder_tree_get_selected (folder_tree, &store, &folder_name))
|
||
+ g_return_if_reached ();
|
||
+
|
||
+ em_folder_properties_show (
|
||
+ store, folder_name,
|
||
+ E_ALERT_SINK (shell_content),
|
||
+ GTK_WINDOW (shell_window));
|
||
+
|
||
+ g_object_unref (store);
|
||
+ g_free (folder_name);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_folder_refresh_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellContent *mail_shell_content;
|
||
+ EMailShellSidebar *mail_shell_sidebar;
|
||
+ EMailView *mail_view;
|
||
+ EMFolderTree *folder_tree;
|
||
+ CamelStore *selected_store = NULL;
|
||
+ gchar *selected_folder_name = NULL;
|
||
+
|
||
+ mail_shell_content = mail_shell_view->priv->mail_shell_content;
|
||
+ mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
|
||
+
|
||
+ mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
|
||
+ folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
|
||
+
|
||
+ em_folder_tree_get_selected (
|
||
+ folder_tree, &selected_store, &selected_folder_name);
|
||
+ g_return_if_fail (CAMEL_IS_STORE (selected_store));
|
||
+ g_return_if_fail (selected_folder_name != NULL);
|
||
+
|
||
+ e_mail_reader_refresh_folder_name (
|
||
+ E_MAIL_READER (mail_view),
|
||
+ selected_store, selected_folder_name);
|
||
+
|
||
+ g_object_unref (selected_store);
|
||
+ g_free (selected_folder_name);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_folder_rename_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ e_mail_shell_view_rename_folder (mail_shell_view);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_folder_select_thread_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellContent *mail_shell_content;
|
||
+ GtkWidget *message_list;
|
||
+ EMailReader *reader;
|
||
+ EMailView *mail_view;
|
||
+
|
||
+ mail_shell_content = mail_shell_view->priv->mail_shell_content;
|
||
+ mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
|
||
+
|
||
+ reader = E_MAIL_READER (mail_view);
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ message_list_select_thread (MESSAGE_LIST (message_list));
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_folder_select_subthread_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellContent *mail_shell_content;
|
||
+ GtkWidget *message_list;
|
||
+ EMailReader *reader;
|
||
+ EMailView *mail_view;
|
||
+
|
||
+ mail_shell_content = mail_shell_view->priv->mail_shell_content;
|
||
+ mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
|
||
+
|
||
+ reader = E_MAIL_READER (mail_view);
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ message_list_select_subthread (MESSAGE_LIST (message_list));
|
||
+}
|
||
+
|
||
+static gboolean
|
||
+ask_can_unsubscribe_folder (GtkWindow *parent,
|
||
+ CamelFolder *folder)
|
||
+{
|
||
+ gchar *full_display_name;
|
||
+ gboolean res;
|
||
+
|
||
+ g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
|
||
+
|
||
+ full_display_name = e_mail_folder_to_full_display_name (folder, NULL);
|
||
+
|
||
+ res = GTK_RESPONSE_YES == e_alert_run_dialog_for_args (parent,
|
||
+ "mail:ask-unsubscribe-folder", full_display_name ? full_display_name : camel_folder_get_full_name (folder), NULL);
|
||
+
|
||
+ g_free (full_display_name);
|
||
+
|
||
+ return res;
|
||
+}
|
||
+
|
||
+typedef struct _GetFolderData {
|
||
+ EMailShellView *mail_shell_view;
|
||
+ EActivity *activity;
|
||
+ CamelStore *store;
|
||
+ gchar *folder_name;
|
||
+} GetFolderData;
|
||
+
|
||
+static void
|
||
+get_folder_data_free (GetFolderData *gfd)
|
||
+{
|
||
+ if (gfd) {
|
||
+ g_clear_object (&gfd->mail_shell_view);
|
||
+ g_clear_object (&gfd->activity);
|
||
+ g_clear_object (&gfd->store);
|
||
+ g_free (gfd->folder_name);
|
||
+ g_slice_free (GetFolderData, gfd);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_folder_unsubscribe_got_folder_cb (GObject *source_object,
|
||
+ GAsyncResult *result,
|
||
+ gpointer user_data)
|
||
+{
|
||
+ GetFolderData *gfd = user_data;
|
||
+ CamelFolder *folder;
|
||
+ GError *local_error = NULL;
|
||
+
|
||
+ g_return_if_fail (gfd != NULL);
|
||
+
|
||
+ folder = camel_store_get_folder_finish (CAMEL_STORE (source_object), result, &local_error);
|
||
+
|
||
+ if (e_activity_handle_cancellation (gfd->activity, local_error)) {
|
||
+ g_error_free (local_error);
|
||
+
|
||
+ } else if (local_error != NULL) {
|
||
+ e_alert_submit (
|
||
+ e_activity_get_alert_sink (gfd->activity), "mail:folder-open",
|
||
+ local_error->message, NULL);
|
||
+ g_error_free (local_error);
|
||
+
|
||
+ } else {
|
||
+ EShellWindow *shell_window;
|
||
+ EMailView *mail_view;
|
||
+
|
||
+ e_activity_set_state (gfd->activity, E_ACTIVITY_COMPLETED);
|
||
+
|
||
+ shell_window = e_shell_view_get_shell_window (E_SHELL_VIEW (gfd->mail_shell_view));
|
||
+ mail_view = e_mail_shell_content_get_mail_view (gfd->mail_shell_view->priv->mail_shell_content);
|
||
+
|
||
+ if (ask_can_unsubscribe_folder (GTK_WINDOW (shell_window), folder))
|
||
+ e_mail_reader_unsubscribe_folder_name (E_MAIL_READER (mail_view), gfd->store, gfd->folder_name);
|
||
+ }
|
||
+
|
||
+ get_folder_data_free (gfd);
|
||
+ g_clear_object (&folder);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_folder_unsubscribe_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellContent *mail_shell_content;
|
||
+ EMailShellSidebar *mail_shell_sidebar;
|
||
+ EMailView *mail_view;
|
||
+ EMFolderTree *folder_tree;
|
||
+ CamelStore *selected_store = NULL;
|
||
+ gchar *selected_folder_name = NULL;
|
||
+ GetFolderData *gfd;
|
||
+
|
||
+ mail_shell_content = mail_shell_view->priv->mail_shell_content;
|
||
+ mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
|
||
+
|
||
+ mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
|
||
+ folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
|
||
+
|
||
+ em_folder_tree_get_selected (folder_tree, &selected_store, &selected_folder_name);
|
||
+ g_return_if_fail (CAMEL_IS_STORE (selected_store));
|
||
+ g_return_if_fail (selected_folder_name != NULL);
|
||
+
|
||
+ gfd = g_slice_new0 (GetFolderData);
|
||
+ gfd->mail_shell_view = g_object_ref (mail_shell_view);
|
||
+ gfd->activity = e_mail_reader_new_activity (E_MAIL_READER (mail_view));
|
||
+ gfd->store = selected_store;
|
||
+ gfd->folder_name = selected_folder_name;
|
||
+
|
||
+ camel_store_get_folder (gfd->store, gfd->folder_name, 0, G_PRIORITY_DEFAULT,
|
||
+ e_activity_get_cancellable (gfd->activity),
|
||
+ mail_folder_unsubscribe_got_folder_cb, gfd);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_global_expunge_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EShellBackend *shell_backend;
|
||
+ EShellWindow *shell_window;
|
||
+ EShellView *shell_view;
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_window = e_shell_view_get_shell_window (shell_view);
|
||
+ shell_backend = e_shell_view_get_shell_backend (shell_view);
|
||
+
|
||
+ backend = E_MAIL_BACKEND (shell_backend);
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+
|
||
+ em_utils_empty_trash (
|
||
+ GTK_WIDGET (shell_window), session);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_goto_folder_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ CamelFolder *folder;
|
||
+ EMailReader *reader;
|
||
+ EMailView *mail_view;
|
||
+ EMFolderSelector *selector;
|
||
+ EMFolderTree *folder_tree;
|
||
+ EMFolderTreeModel *model;
|
||
+ GtkWidget *dialog;
|
||
+ GtkWindow *window;
|
||
+ const gchar *uri;
|
||
+
|
||
+ mail_view = e_mail_shell_content_get_mail_view (mail_shell_view->priv->mail_shell_content);
|
||
+ reader = E_MAIL_READER (mail_view);
|
||
+
|
||
+ folder = e_mail_reader_ref_folder (reader);
|
||
+ window = e_mail_reader_get_window (reader);
|
||
+
|
||
+ model = em_folder_tree_model_get_default ();
|
||
+
|
||
+ dialog = em_folder_selector_new (window, model);
|
||
+
|
||
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Go to Folder"));
|
||
+
|
||
+ selector = EM_FOLDER_SELECTOR (dialog);
|
||
+ em_folder_selector_set_can_create (selector, FALSE);
|
||
+ em_folder_selector_set_default_button_label (selector, _("_Select"));
|
||
+
|
||
+ folder_tree = em_folder_selector_get_folder_tree (selector);
|
||
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (folder_tree));
|
||
+ em_folder_selector_maybe_collapse_archive_folders (selector);
|
||
+
|
||
+ if (folder) {
|
||
+ gchar *uri = e_mail_folder_uri_from_folder (folder);
|
||
+
|
||
+ if (uri) {
|
||
+ em_folder_tree_set_selected (folder_tree, uri, FALSE);
|
||
+ g_free (uri);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
|
||
+ uri = em_folder_selector_get_selected_uri (selector);
|
||
+
|
||
+ if (uri != NULL) {
|
||
+ folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_view->priv->mail_shell_sidebar);
|
||
+ em_folder_tree_set_selected (folder_tree, uri, FALSE);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ gtk_widget_destroy (dialog);
|
||
+
|
||
+ g_clear_object (&folder);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_send_receive_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EShellView *shell_view;
|
||
+ EShellWindow *shell_window;
|
||
+ EShellBackend *shell_backend;
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_window = e_shell_view_get_shell_window (shell_view);
|
||
+ shell_backend = e_shell_view_get_shell_backend (shell_view);
|
||
+
|
||
+ backend = E_MAIL_BACKEND (shell_backend);
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+
|
||
+ mail_send_receive (GTK_WINDOW (shell_window), session);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_send_receive_receive_all_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EShellView *shell_view;
|
||
+ EShellWindow *shell_window;
|
||
+ EShellBackend *shell_backend;
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_window = e_shell_view_get_shell_window (shell_view);
|
||
+ shell_backend = e_shell_view_get_shell_backend (shell_view);
|
||
+
|
||
+ backend = E_MAIL_BACKEND (shell_backend);
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+
|
||
+ mail_receive (GTK_WINDOW (shell_window), session);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_send_receive_send_all_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EShellView *shell_view;
|
||
+ EShellBackend *shell_backend;
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_backend = e_shell_view_get_shell_backend (shell_view);
|
||
+
|
||
+ backend = E_MAIL_BACKEND (shell_backend);
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+
|
||
+ mail_send_immediately (session);
|
||
+}
|
||
+
|
||
+static void
|
||
+mail_shell_view_magic_spacebar (EMailShellView *mail_shell_view,
|
||
+ gboolean move_forward)
|
||
+{
|
||
+ EMailShellContent *mail_shell_content;
|
||
+ EMailShellSidebar *mail_shell_sidebar;
|
||
+ EMFolderTree *folder_tree;
|
||
+ EMailReader *reader;
|
||
+ EMailView *mail_view;
|
||
+ GtkWidget *message_list;
|
||
+ EMailDisplay *display;
|
||
+ GSettings *settings;
|
||
+ gboolean magic_spacebar;
|
||
+
|
||
+ /* This implements the so-called "Magic Backspace". */
|
||
+ g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view));
|
||
+
|
||
+ mail_shell_content = mail_shell_view->priv->mail_shell_content;
|
||
+ mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
|
||
+
|
||
+ mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
|
||
+ folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
|
||
+
|
||
+ reader = E_MAIL_READER (mail_view);
|
||
+ display = e_mail_reader_get_mail_display (reader);
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ settings = e_util_ref_settings ("org.gnome.evolution.mail");
|
||
+ magic_spacebar = g_settings_get_boolean (settings, "magic-spacebar");
|
||
+ g_object_unref (settings);
|
||
+
|
||
+ if (!e_mail_display_process_magic_spacebar (display, move_forward)) {
|
||
+ guint32 direction = move_forward ? MESSAGE_LIST_SELECT_NEXT : MESSAGE_LIST_SELECT_PREVIOUS;
|
||
+ gboolean selected;
|
||
+
|
||
+ if (!magic_spacebar)
|
||
+ return;
|
||
+
|
||
+ if (message_list_select (MESSAGE_LIST (message_list),
|
||
+ direction | MESSAGE_LIST_SELECT_WRAP |
|
||
+ MESSAGE_LIST_SELECT_INCLUDE_COLLAPSED,
|
||
+ 0, CAMEL_MESSAGE_SEEN))
|
||
+ return;
|
||
+
|
||
+ if (move_forward)
|
||
+ selected = em_folder_tree_select_next_path (folder_tree, TRUE);
|
||
+ else
|
||
+ selected = em_folder_tree_select_prev_path (folder_tree, TRUE);
|
||
+
|
||
+ if (selected)
|
||
+ message_list_set_regen_selects_unread (MESSAGE_LIST (message_list), TRUE);
|
||
+
|
||
+ gtk_widget_grab_focus (message_list);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_smart_backward_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ mail_shell_view_magic_spacebar (mail_shell_view, FALSE);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_smart_forward_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ mail_shell_view_magic_spacebar (mail_shell_view, TRUE);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_stop_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EShellView *shell_view;
|
||
+ EShellBackend *shell_backend;
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_backend = e_shell_view_get_shell_backend (shell_view);
|
||
+
|
||
+ e_shell_backend_cancel_all (shell_backend);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_threads_collapse_all_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellContent *mail_shell_content;
|
||
+ GtkWidget *message_list;
|
||
+ EMailReader *reader;
|
||
+ EMailView *mail_view;
|
||
+
|
||
+ mail_shell_content = mail_shell_view->priv->mail_shell_content;
|
||
+ mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
|
||
+
|
||
+ reader = E_MAIL_READER (mail_view);
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ message_list_set_threaded_collapse_all (MESSAGE_LIST (message_list));
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_threads_expand_all_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellContent *mail_shell_content;
|
||
+ GtkWidget *message_list;
|
||
+ EMailReader *reader;
|
||
+ EMailView *mail_view;
|
||
+
|
||
+ mail_shell_content = mail_shell_view->priv->mail_shell_content;
|
||
+ mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
|
||
+
|
||
+ reader = E_MAIL_READER (mail_view);
|
||
+ message_list = e_mail_reader_get_message_list (reader);
|
||
+
|
||
+ message_list_set_threaded_expand_all (MESSAGE_LIST (message_list));
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_tools_filters_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EShellBackend *shell_backend;
|
||
+ EShellContent *shell_content;
|
||
+ EShellWindow *shell_window;
|
||
+ EShellView *shell_view;
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_window = e_shell_view_get_shell_window (shell_view);
|
||
+ shell_backend = e_shell_view_get_shell_backend (shell_view);
|
||
+ shell_content = e_shell_view_get_shell_content (shell_view);
|
||
+
|
||
+ backend = E_MAIL_BACKEND (shell_backend);
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+
|
||
+ em_utils_edit_filters (
|
||
+ session,
|
||
+ E_ALERT_SINK (shell_content),
|
||
+ GTK_WINDOW (shell_window));
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_tools_search_folders_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EShellView *shell_view;
|
||
+ EShellWindow *shell_window;
|
||
+ EShellBackend *shell_backend;
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_window = e_shell_view_get_shell_window (shell_view);
|
||
+ shell_backend = e_shell_view_get_shell_backend (shell_view);
|
||
+
|
||
+ vfolder_edit (
|
||
+ E_MAIL_BACKEND (shell_backend),
|
||
+ GTK_WINDOW (shell_window));
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_tools_subscriptions_cb (GtkAction *action,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellSidebar *mail_shell_sidebar;
|
||
+ EShellWindow *shell_window;
|
||
+ EShellView *shell_view;
|
||
+ EMailSession *session;
|
||
+ EMFolderTree *folder_tree;
|
||
+ GtkWidget *dialog;
|
||
+ CamelStore *store;
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_window = e_shell_view_get_shell_window (shell_view);
|
||
+
|
||
+ mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
|
||
+ folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
|
||
+ session = em_folder_tree_get_session (folder_tree);
|
||
+
|
||
+ /* The subscription editor's initial store can be NULL. */
|
||
+ store = em_folder_tree_ref_selected_store (folder_tree);
|
||
+
|
||
+ dialog = em_subscription_editor_new (
|
||
+ GTK_WINDOW (shell_window), session, store);
|
||
+
|
||
+ if (store != NULL)
|
||
+ g_object_unref (store);
|
||
+
|
||
+ gtk_dialog_run (GTK_DIALOG (dialog));
|
||
+ gtk_widget_destroy (dialog);
|
||
+}
|
||
+
|
||
+static void
|
||
+action_mail_view_cb (GtkRadioAction *action,
|
||
+ GtkRadioAction *current,
|
||
+ EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellContent *mail_shell_content;
|
||
+ GtkOrientation orientation;
|
||
+ EMailView *mail_view;
|
||
+
|
||
+ mail_shell_content = mail_shell_view->priv->mail_shell_content;
|
||
+ mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
|
||
+
|
||
+ switch (gtk_radio_action_get_current_value (action)) {
|
||
+ case 0:
|
||
+ orientation = GTK_ORIENTATION_VERTICAL;
|
||
+ break;
|
||
+ case 1:
|
||
+ orientation = GTK_ORIENTATION_HORIZONTAL;
|
||
+ break;
|
||
+ default:
|
||
+ g_return_if_reached ();
|
||
+ }
|
||
+
|
||
+ e_mail_view_set_orientation (mail_view, orientation);
|
||
+}
|
||
+
|
||
+static GtkActionEntry mail_entries[] = {
|
||
+
|
||
+ { "mail-account-disable",
|
||
+ NULL,
|
||
+ N_("_Disable Account"),
|
||
+ NULL,
|
||
+ N_("Disable this account"),
|
||
+ G_CALLBACK (action_mail_account_disable_cb) },
|
||
+
|
||
+ { "mail-account-expunge",
|
||
+ NULL,
|
||
+ N_("_Empty Trash"),
|
||
+ NULL,
|
||
+ N_("Permanently remove all the deleted messages from all folders"),
|
||
+ G_CALLBACK (action_mail_folder_expunge_cb) },
|
||
+
|
||
+ { "mail-account-empty-junk",
|
||
+ NULL,
|
||
+ N_("Empty _Junk"),
|
||
+ NULL,
|
||
+ N_("Delete all Junk messages from all folders"),
|
||
+ G_CALLBACK (action_mail_folder_empty_junk_cb) },
|
||
+
|
||
+ { "mail-account-properties",
|
||
+ "document-properties",
|
||
+ N_("_Properties"),
|
||
+ NULL,
|
||
+ N_("Edit properties of this account"),
|
||
+ G_CALLBACK (action_mail_account_properties_cb) },
|
||
+
|
||
+ { "mail-account-refresh",
|
||
+ "view-refresh",
|
||
+ N_("_Refresh"),
|
||
+ NULL,
|
||
+ N_("Refresh list of folders of this account"),
|
||
+ G_CALLBACK (action_mail_account_refresh_cb) },
|
||
+
|
||
+ { "mail-download",
|
||
+ NULL,
|
||
+ N_("_Download Messages for Offline Usage"),
|
||
+ NULL,
|
||
+ N_("Download messages of accounts and folders marked for offline usage"),
|
||
+ G_CALLBACK (action_mail_download_cb) },
|
||
+
|
||
+ { "mail-flush-outbox",
|
||
+ "mail-send",
|
||
+ N_("Fl_ush Outbox"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ G_CALLBACK (action_mail_flush_outbox_cb) },
|
||
+
|
||
+ { "mail-folder-copy",
|
||
+ "folder-copy",
|
||
+ N_("_Copy Folder To…"),
|
||
+ NULL,
|
||
+ N_("Copy the selected folder into another folder"),
|
||
+ G_CALLBACK (action_mail_folder_copy_cb) },
|
||
+
|
||
+ { "mail-folder-delete",
|
||
+ "edit-delete",
|
||
+ N_("_Delete"),
|
||
+ NULL,
|
||
+ N_("Permanently remove this folder"),
|
||
+ G_CALLBACK (action_mail_folder_delete_cb) },
|
||
+
|
||
+ { "mail-folder-edit-sort-order",
|
||
+ NULL,
|
||
+ N_("Edit Sort _Order…"),
|
||
+ NULL,
|
||
+ N_("Change sort order of the folders in the folder tree"),
|
||
+ G_CALLBACK (action_mail_folder_edit_sort_order_cb) },
|
||
+
|
||
+ { "mail-folder-expunge",
|
||
+ NULL,
|
||
+ N_("E_xpunge"),
|
||
+ "<Control>e",
|
||
+ N_("Permanently remove all deleted messages from this folder"),
|
||
+ G_CALLBACK (action_mail_folder_expunge_cb) },
|
||
+
|
||
+ { "mail-folder-mark-all-as-read",
|
||
+ "mail-mark-read",
|
||
+ N_("Mar_k All Messages as Read"),
|
||
+ "<Control>slash",
|
||
+ N_("Mark all messages in the folder as read"),
|
||
+ G_CALLBACK (action_mail_folder_mark_all_as_read_cb) },
|
||
+
|
||
+ { "mail-folder-move",
|
||
+ "folder-move",
|
||
+ N_("_Move Folder To…"),
|
||
+ NULL,
|
||
+ N_("Move the selected folder into another folder"),
|
||
+ G_CALLBACK (action_mail_folder_move_cb) },
|
||
+
|
||
+ { "mail-folder-new",
|
||
+ "folder-new",
|
||
+ /* Translators: An action caption to create a new mail folder */
|
||
+ N_("_New…"),
|
||
+ NULL,
|
||
+ N_("Create a new folder for storing mail"),
|
||
+ G_CALLBACK (action_mail_folder_new_cb) },
|
||
+
|
||
+ { "mail-folder-properties",
|
||
+ "document-properties",
|
||
+ N_("_Properties"),
|
||
+ NULL,
|
||
+ N_("Change the properties of this folder"),
|
||
+ G_CALLBACK (action_mail_folder_properties_cb) },
|
||
+
|
||
+ { "mail-folder-refresh",
|
||
+ "view-refresh",
|
||
+ N_("_Refresh"),
|
||
+ "F5",
|
||
+ N_("Refresh the folder"),
|
||
+ G_CALLBACK (action_mail_folder_refresh_cb) },
|
||
+
|
||
+ { "mail-folder-rename",
|
||
+ NULL,
|
||
+ N_("_Rename…"),
|
||
+ "F2",
|
||
+ N_("Change the name of this folder"),
|
||
+ G_CALLBACK (action_mail_folder_rename_cb) },
|
||
+
|
||
+ { "mail-folder-select-thread",
|
||
+ NULL,
|
||
+ N_("Select Message _Thread"),
|
||
+ "<Control>h",
|
||
+ N_("Select all messages in the same thread as the selected message"),
|
||
+ G_CALLBACK (action_mail_folder_select_thread_cb) },
|
||
+
|
||
+ { "mail-folder-select-subthread",
|
||
+ NULL,
|
||
+ N_("Select Message S_ubthread"),
|
||
+ "<Shift><Control>h",
|
||
+ N_("Select all replies to the currently selected message"),
|
||
+ G_CALLBACK (action_mail_folder_select_subthread_cb) },
|
||
+
|
||
+ { "mail-folder-unsubscribe",
|
||
+ NULL,
|
||
+ N_("_Unsubscribe"),
|
||
+ NULL,
|
||
+ N_("Unsubscribe from the selected folder"),
|
||
+ G_CALLBACK (action_mail_folder_unsubscribe_cb) },
|
||
+
|
||
+ { "mail-global-expunge",
|
||
+ NULL,
|
||
+ N_("Empty _Trash"),
|
||
+ NULL,
|
||
+ N_("Permanently remove all the deleted messages from all accounts"),
|
||
+ G_CALLBACK (action_mail_global_expunge_cb) },
|
||
+
|
||
+ { "mail-goto-folder",
|
||
+ NULL,
|
||
+ N_("Go to _Folder"),
|
||
+ "<Control>g",
|
||
+ N_("Opens a dialog to select a folder to go to"),
|
||
+ G_CALLBACK (action_mail_goto_folder_cb) },
|
||
+
|
||
+ /* This is the same as "mail-tools-subscriptions" but only
|
||
+ * appears in the sidebar context menu when right-clicking
|
||
+ * on a store that supports folder subscriptions. No need
|
||
+ * for a special callback because Folder->Subscriptions...
|
||
+ * already tries to open the "Folder Subscriptions" dialog
|
||
+ * according to the highlighted item in the sidebar, which
|
||
+ * is exactly the behavior we want here. */
|
||
+ { "mail-manage-subscriptions",
|
||
+ NULL,
|
||
+ N_("_Manage Subscriptions"),
|
||
+ NULL,
|
||
+ N_("Subscribe or unsubscribe to folders on remote servers"),
|
||
+ G_CALLBACK (action_mail_tools_subscriptions_cb) },
|
||
+
|
||
+ { "mail-popup-folder-mark-all-as-read",
|
||
+ "mail-mark-read",
|
||
+ N_("Mar_k All Messages as Read"),
|
||
+ NULL,
|
||
+ N_("Mark all messages in the folder as read"),
|
||
+ G_CALLBACK (action_mail_popup_folder_mark_all_as_read_cb) },
|
||
+
|
||
+ { "mail-send-receive",
|
||
+ "mail-send-receive",
|
||
+ N_("Send / _Receive"),
|
||
+ "F12",
|
||
+ N_("Send queued items and retrieve new items"),
|
||
+ G_CALLBACK (action_mail_send_receive_cb) },
|
||
+
|
||
+ { "mail-send-receive-receive-all",
|
||
+ NULL,
|
||
+ N_("R_eceive All"),
|
||
+ NULL,
|
||
+ N_("Receive new items from all accounts"),
|
||
+ G_CALLBACK (action_mail_send_receive_receive_all_cb) },
|
||
+
|
||
+ { "mail-send-receive-send-all",
|
||
+ "mail-send",
|
||
+ N_("_Send All"),
|
||
+ NULL,
|
||
+ N_("Send queued items in all accounts"),
|
||
+ G_CALLBACK (action_mail_send_receive_send_all_cb) },
|
||
+
|
||
+ { "mail-send-receive-submenu",
|
||
+ "mail-send-receive",
|
||
+ N_("Send / _Receive"),
|
||
+ NULL,
|
||
+ NULL,
|
||
+ NULL },
|
||
+
|
||
+ { "mail-smart-backward",
|
||
+ "go-up", /* In case a user adds it to the UI */
|
||
+ NULL, /* No menu item; key press only */
|
||
+ "BackSpace",
|
||
+ NULL,
|
||
+ G_CALLBACK (action_mail_smart_backward_cb) },
|
||
+
|
||
+ { "mail-smart-forward",
|
||
+ "go-down", /* In case a user adds it to the UI */
|
||
+ NULL, /* No menu item; key press only */
|
||
+ "space",
|
||
+ NULL,
|
||
+ G_CALLBACK (action_mail_smart_forward_cb) },
|
||
+
|
||
+ { "mail-stop",
|
||
+ "process-stop",
|
||
+ N_("Cancel"),
|
||
+ NULL,
|
||
+ N_("Cancel the current mail operation"),
|
||
+ G_CALLBACK (action_mail_stop_cb) },
|
||
+
|
||
+ { "mail-threads-collapse-all",
|
||
+ NULL,
|
||
+ N_("Collapse All _Threads"),
|
||
+ "<Shift><Control>b",
|
||
+ N_("Collapse all message threads"),
|
||
+ G_CALLBACK (action_mail_threads_collapse_all_cb) },
|
||
+
|
||
+ { "mail-threads-expand-all",
|
||
+ NULL,
|
||
+ N_("E_xpand All Threads"),
|
||
+ NULL,
|
||
+ N_("Expand all message threads"),
|
||
+ G_CALLBACK (action_mail_threads_expand_all_cb) },
|
||
+
|
||
+ { "mail-tools-filters",
|
||
+ NULL,
|
||
+ N_("_Message Filters"),
|
||
+ NULL,
|
||
+ N_("Create or edit rules for filtering new mail"),
|
||
+ G_CALLBACK (action_mail_tools_filters_cb) },
|
||
+
|
||
+ { "mail-tools-subscriptions",
|
||
+ NULL,
|
||
+ N_("_Subscriptions…"),
|
||
+ NULL,
|
||
+ N_("Subscribe or unsubscribe to folders on remote servers"),
|
||
+ G_CALLBACK (action_mail_tools_subscriptions_cb) },
|
||
+
|
||
+ /*** Menus ***/
|
||
+
|
||
+ { "mail-folder-menu",
|
||
+ NULL,
|
||
+ N_("F_older"),
|
||
+ NULL,
|
||
+ NULL,
|
||
+ NULL },
|
||
+
|
||
+ { "mail-preview-menu",
|
||
+ NULL,
|
||
+ N_("_Preview"),
|
||
+ NULL,
|
||
+ NULL,
|
||
+ NULL }
|
||
+};
|
||
+
|
||
+static GtkActionEntry search_folder_entries[] = {
|
||
+
|
||
+ { "mail-create-search-folder",
|
||
+ NULL,
|
||
+ N_("C_reate Search Folder From Search…"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ G_CALLBACK (action_mail_create_search_folder_cb) },
|
||
+
|
||
+ { "mail-tools-search-folders",
|
||
+ NULL,
|
||
+ N_("Search F_olders"),
|
||
+ NULL,
|
||
+ N_("Create or edit search folder definitions"),
|
||
+ G_CALLBACK (action_mail_tools_search_folders_cb) },
|
||
+};
|
||
+
|
||
+static EPopupActionEntry mail_popup_entries[] = {
|
||
+
|
||
+ { "mail-popup-account-disable",
|
||
+ NULL,
|
||
+ "mail-account-disable" },
|
||
+
|
||
+ { "mail-popup-account-expunge",
|
||
+ NULL,
|
||
+ "mail-account-expunge" },
|
||
+
|
||
+ { "mail-popup-account-empty-junk",
|
||
+ NULL,
|
||
+ "mail-account-empty-junk" },
|
||
+
|
||
+ { "mail-popup-account-refresh",
|
||
+ NULL,
|
||
+ "mail-account-refresh" },
|
||
+
|
||
+ { "mail-popup-account-properties",
|
||
+ NULL,
|
||
+ "mail-account-properties" },
|
||
+
|
||
+ { "mail-popup-flush-outbox",
|
||
+ NULL,
|
||
+ "mail-flush-outbox" },
|
||
+
|
||
+ { "mail-popup-folder-copy",
|
||
+ NULL,
|
||
+ "mail-folder-copy" },
|
||
+
|
||
+ { "mail-popup-folder-delete",
|
||
+ NULL,
|
||
+ "mail-folder-delete" },
|
||
+
|
||
+ { "mail-popup-folder-move",
|
||
+ NULL,
|
||
+ "mail-folder-move" },
|
||
+
|
||
+ { "mail-popup-folder-new",
|
||
+ N_("_New Folder…"),
|
||
+ "mail-folder-new" },
|
||
+
|
||
+ { "mail-popup-folder-properties",
|
||
+ NULL,
|
||
+ "mail-folder-properties" },
|
||
+
|
||
+ { "mail-popup-folder-refresh",
|
||
+ NULL,
|
||
+ "mail-folder-refresh" },
|
||
+
|
||
+ { "mail-popup-folder-rename",
|
||
+ NULL,
|
||
+ "mail-folder-rename" },
|
||
+
|
||
+ { "mail-popup-folder-unsubscribe",
|
||
+ NULL,
|
||
+ "mail-folder-unsubscribe" },
|
||
+
|
||
+ { "mail-popup-manage-subscriptions",
|
||
+ NULL,
|
||
+ "mail-manage-subscriptions" }
|
||
+};
|
||
+
|
||
+static GtkToggleActionEntry mail_toggle_entries[] = {
|
||
+
|
||
+ { "mail-preview",
|
||
+ NULL,
|
||
+ N_("Show Message _Preview"),
|
||
+ "<Control>m",
|
||
+ N_("Show message preview pane"),
|
||
+ NULL, /* Handled by property bindings */
|
||
+ TRUE },
|
||
+
|
||
+ { "mail-attachment-bar",
|
||
+ NULL,
|
||
+ N_("Show _Attachment Bar"),
|
||
+ NULL,
|
||
+ N_("Show Attachment Bar below the message preview pane when the message has attachments"),
|
||
+ G_CALLBACK (action_mail_attachment_bar_cb),
|
||
+ TRUE },
|
||
+
|
||
+ { "mail-show-deleted",
|
||
+ NULL,
|
||
+ N_("Show _Deleted Messages"),
|
||
+ NULL,
|
||
+ N_("Show deleted messages with a line through them"),
|
||
+ NULL, /* Handled by property bindings */
|
||
+ FALSE },
|
||
+
|
||
+ { "mail-show-junk",
|
||
+ NULL,
|
||
+ N_("Show _Junk Messages"),
|
||
+ NULL,
|
||
+ N_("Show junk messages with a red line through them"),
|
||
+ NULL, /* Handled by property bindings */
|
||
+ FALSE },
|
||
+
|
||
+ { "mail-threads-group-by",
|
||
+ NULL,
|
||
+ N_("_Group By Threads"),
|
||
+ "<Control>t",
|
||
+ N_("Threaded message list"),
|
||
+ NULL, /* Handled by property bindings */
|
||
+ FALSE },
|
||
+
|
||
+ { "mail-to-do-bar",
|
||
+ NULL,
|
||
+ N_("Show To _Do Bar"),
|
||
+ NULL,
|
||
+ N_("Show To Do bar with appointments and tasks"),
|
||
+ G_CALLBACK (action_mail_to_do_bar_cb),
|
||
+ TRUE },
|
||
+
|
||
+ { "mail-vfolder-unmatched-enable",
|
||
+ NULL,
|
||
+ N_("_Unmatched Folder Enabled"),
|
||
+ NULL,
|
||
+ N_("Toggles whether Unmatched search folder is enabled"),
|
||
+ NULL }
|
||
+};
|
||
+
|
||
+static GtkRadioActionEntry mail_view_entries[] = {
|
||
+
|
||
+ /* This action represents the initial active mail view.
|
||
+ * It should not be visible in the UI, nor should it be
|
||
+ * possible to switch to it from another shell view. */
|
||
+ { "mail-view-initial",
|
||
+ NULL,
|
||
+ NULL,
|
||
+ NULL,
|
||
+ NULL,
|
||
+ -1 },
|
||
+
|
||
+ { "mail-view-classic",
|
||
+ NULL,
|
||
+ N_("_Classic View"),
|
||
+ NULL,
|
||
+ N_("Show message preview below the message list"),
|
||
+ 0 },
|
||
+
|
||
+ { "mail-view-vertical",
|
||
+ NULL,
|
||
+ N_("_Vertical View"),
|
||
+ NULL,
|
||
+ N_("Show message preview alongside the message list"),
|
||
+ 1 }
|
||
+};
|
||
+
|
||
+static GtkRadioActionEntry mail_filter_entries[] = {
|
||
+
|
||
+ { "mail-filter-all-messages",
|
||
+ NULL,
|
||
+ N_("All Messages"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_FILTER_ALL_MESSAGES },
|
||
+
|
||
+ { "mail-filter-important-messages",
|
||
+ "emblem-important",
|
||
+ N_("Important Messages"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_FILTER_IMPORTANT_MESSAGES },
|
||
+
|
||
+ { "mail-filter-last-5-days-messages",
|
||
+ NULL,
|
||
+ N_("Last 5 Days’ Messages"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_FILTER_LAST_5_DAYS_MESSAGES },
|
||
+
|
||
+ { "mail-filter-messages-not-junk",
|
||
+ "mail-mark-notjunk",
|
||
+ N_("Messages Not Junk"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_FILTER_MESSAGES_NOT_JUNK },
|
||
+
|
||
+ { "mail-filter-messages-with-attachments",
|
||
+ "mail-attachment",
|
||
+ N_("Messages with Attachments"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS },
|
||
+
|
||
+ { "mail-filter-messages-with-notes",
|
||
+ "evolution-memos",
|
||
+ N_("Messages with Notes"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_FILTER_MESSAGES_WITH_NOTES },
|
||
+
|
||
+ { "mail-filter-no-label",
|
||
+ NULL,
|
||
+ N_("No Label"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_FILTER_NO_LABEL },
|
||
+
|
||
+ { "mail-filter-read-messages",
|
||
+ "mail-read",
|
||
+ N_("Read Messages"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_FILTER_READ_MESSAGES },
|
||
+
|
||
+ { "mail-filter-unread-messages",
|
||
+ "mail-unread",
|
||
+ N_("Unread Messages"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_FILTER_UNREAD_MESSAGES },
|
||
+
|
||
+ { "mail-filter-message-thread",
|
||
+ NULL,
|
||
+ N_("Message Thread"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_FILTER_MESSAGE_THREAD }
|
||
+
|
||
+};
|
||
+
|
||
+static GtkRadioActionEntry mail_search_entries[] = {
|
||
+
|
||
+ { "mail-search-advanced-hidden",
|
||
+ NULL,
|
||
+ N_("Advanced Search"),
|
||
+ NULL,
|
||
+ NULL,
|
||
+ MAIL_SEARCH_ADVANCED },
|
||
+
|
||
+ { "mail-search-body-contains",
|
||
+ NULL,
|
||
+ N_("Body contains"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_SEARCH_BODY_CONTAINS },
|
||
+
|
||
+ { "mail-search-free-form-expr",
|
||
+ NULL,
|
||
+ N_("Free form expression"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_SEARCH_FREE_FORM_EXPR },
|
||
+
|
||
+ { "mail-search-message-contains",
|
||
+ NULL,
|
||
+ N_("Message contains"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_SEARCH_MESSAGE_CONTAINS },
|
||
+
|
||
+ { "mail-search-recipients-contain",
|
||
+ NULL,
|
||
+ N_("Recipients contain"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_SEARCH_RECIPIENTS_CONTAIN },
|
||
+
|
||
+ { "mail-search-sender-contains",
|
||
+ NULL,
|
||
+ N_("Sender contains"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_SEARCH_SENDER_CONTAINS },
|
||
+
|
||
+ { "mail-search-subject-contains",
|
||
+ NULL,
|
||
+ N_("Subject contains"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_SEARCH_SUBJECT_CONTAINS },
|
||
+
|
||
+ { "mail-search-subject-or-addresses-contain",
|
||
+ NULL,
|
||
+ N_("Subject or Addresses contain"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_SEARCH_SUBJECT_OR_ADDRESSES_CONTAIN }
|
||
+};
|
||
+
|
||
+static GtkRadioActionEntry mail_scope_entries[] = {
|
||
+
|
||
+ { "mail-scope-all-accounts",
|
||
+ NULL,
|
||
+ N_("All Accounts"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_SCOPE_ALL_ACCOUNTS },
|
||
+
|
||
+ { "mail-scope-current-account",
|
||
+ NULL,
|
||
+ N_("Current Account"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_SCOPE_CURRENT_ACCOUNT },
|
||
+
|
||
+ { "mail-scope-current-folder",
|
||
+ NULL,
|
||
+ N_("Current Folder"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_SCOPE_CURRENT_FOLDER },
|
||
+
|
||
+ { "mail-scope-current-folder-and-subfolders",
|
||
+ NULL,
|
||
+ N_("Current Folder and Subfolders"),
|
||
+ NULL,
|
||
+ NULL, /* XXX Add a tooltip! */
|
||
+ MAIL_SCOPE_CURRENT_FOLDER_AND_SUBFOLDERS }
|
||
+};
|
||
+
|
||
+void
|
||
+e_mail_shell_view_actions_init (EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellContent *mail_shell_content;
|
||
+ EShellView *shell_view;
|
||
+ EShellWindow *shell_window;
|
||
+ EShellBackend *shell_backend;
|
||
+ EShell *shell;
|
||
+ EShellSearchbar *searchbar;
|
||
+ EActionComboBox *combo_box;
|
||
+ EMailView *mail_view;
|
||
+ GtkActionGroup *action_group;
|
||
+ GtkAction *action;
|
||
+ GSettings *settings;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view));
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_window = e_shell_view_get_shell_window (shell_view);
|
||
+ shell_backend = e_shell_view_get_shell_backend (shell_view);
|
||
+ shell = e_shell_window_get_shell (shell_window);
|
||
+
|
||
+ mail_shell_content = mail_shell_view->priv->mail_shell_content;
|
||
+ mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
|
||
+ searchbar = e_mail_shell_content_get_searchbar (mail_shell_content);
|
||
+
|
||
+ /* Mail Actions */
|
||
+ action_group = ACTION_GROUP (MAIL);
|
||
+ gtk_action_group_add_actions (
|
||
+ action_group, mail_entries,
|
||
+ G_N_ELEMENTS (mail_entries), mail_shell_view);
|
||
+ gtk_action_group_add_toggle_actions (
|
||
+ action_group, mail_toggle_entries,
|
||
+ G_N_ELEMENTS (mail_toggle_entries), mail_shell_view);
|
||
+ gtk_action_group_add_radio_actions (
|
||
+ action_group, mail_view_entries,
|
||
+ G_N_ELEMENTS (mail_view_entries), -1,
|
||
+ G_CALLBACK (action_mail_view_cb), mail_shell_view);
|
||
+ gtk_action_group_add_radio_actions (
|
||
+ action_group, mail_search_entries,
|
||
+ G_N_ELEMENTS (mail_search_entries),
|
||
+ -1, NULL, NULL);
|
||
+ gtk_action_group_add_radio_actions (
|
||
+ action_group, mail_scope_entries,
|
||
+ G_N_ELEMENTS (mail_scope_entries),
|
||
+ MAIL_SCOPE_CURRENT_FOLDER, NULL, NULL);
|
||
+ e_action_group_add_popup_actions (
|
||
+ action_group, mail_popup_entries,
|
||
+ G_N_ELEMENTS (mail_popup_entries));
|
||
+
|
||
+ /* WebKitGTK does not support print preview, thus hide the option from the menu;
|
||
+ maybe it'll be supported in the future */
|
||
+ action = ACTION (MAIL_PRINT_PREVIEW);
|
||
+ gtk_action_set_visible (action, FALSE);
|
||
+
|
||
+ /* Search Folder Actions */
|
||
+ action_group = ACTION_GROUP (SEARCH_FOLDERS);
|
||
+ gtk_action_group_add_actions (
|
||
+ action_group, search_folder_entries,
|
||
+ G_N_ELEMENTS (search_folder_entries), mail_shell_view);
|
||
+
|
||
+ action = ACTION (MAIL_SCOPE_ALL_ACCOUNTS);
|
||
+ combo_box = e_shell_searchbar_get_scope_combo_box (searchbar);
|
||
+ e_action_combo_box_set_action (combo_box, GTK_RADIO_ACTION (action));
|
||
+ e_shell_searchbar_set_scope_visible (searchbar, TRUE);
|
||
+
|
||
+ /* Advanced Search Action */
|
||
+ action = ACTION (MAIL_SEARCH_ADVANCED_HIDDEN);
|
||
+ gtk_action_set_visible (action, FALSE);
|
||
+ e_shell_searchbar_set_search_option (
|
||
+ searchbar, GTK_RADIO_ACTION (action));
|
||
+
|
||
+ g_object_set (ACTION (MAIL_SEND_RECEIVE), "is-important", TRUE, NULL);
|
||
+
|
||
+ /* Bind GObject properties for GSettings keys. */
|
||
+
|
||
+ settings = e_util_ref_settings ("org.gnome.evolution.mail");
|
||
+
|
||
+ g_settings_bind (
|
||
+ settings, "show-deleted",
|
||
+ ACTION (MAIL_SHOW_DELETED), "active",
|
||
+ G_SETTINGS_BIND_DEFAULT);
|
||
+
|
||
+ g_settings_bind (
|
||
+ settings, "show-junk",
|
||
+ ACTION (MAIL_SHOW_JUNK), "active",
|
||
+ G_SETTINGS_BIND_DEFAULT);
|
||
+
|
||
+ g_settings_bind (
|
||
+ settings, "layout",
|
||
+ ACTION (MAIL_VIEW_VERTICAL), "current-value",
|
||
+ G_SETTINGS_BIND_DEFAULT);
|
||
+
|
||
+ g_settings_bind (
|
||
+ settings, "enable-unmatched",
|
||
+ ACTION (MAIL_VFOLDER_UNMATCHED_ENABLE), "active",
|
||
+ G_SETTINGS_BIND_DEFAULT);
|
||
+
|
||
+ g_settings_bind (
|
||
+ settings, "show-attachment-bar",
|
||
+ ACTION (MAIL_ATTACHMENT_BAR), "active",
|
||
+ G_SETTINGS_BIND_DEFAULT);
|
||
+
|
||
+ if (e_shell_window_is_main_instance (shell_window)) {
|
||
+ g_settings_bind (
|
||
+ settings, "show-to-do-bar",
|
||
+ ACTION (MAIL_TO_DO_BAR), "active",
|
||
+ G_SETTINGS_BIND_DEFAULT);
|
||
+ } else {
|
||
+ g_settings_bind (
|
||
+ settings, "show-to-do-bar-sub",
|
||
+ ACTION (MAIL_TO_DO_BAR), "active",
|
||
+ G_SETTINGS_BIND_DEFAULT);
|
||
+ }
|
||
+
|
||
+ g_object_unref (settings);
|
||
+
|
||
+ /* Fine tuning. */
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ ACTION (MAIL_THREADS_GROUP_BY), "active",
|
||
+ ACTION (MAIL_FOLDER_SELECT_THREAD), "sensitive",
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ ACTION (MAIL_THREADS_GROUP_BY), "active",
|
||
+ ACTION (MAIL_FOLDER_SELECT_SUBTHREAD), "sensitive",
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ ACTION (MAIL_THREADS_GROUP_BY), "active",
|
||
+ ACTION (MAIL_THREADS_COLLAPSE_ALL), "sensitive",
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ ACTION (MAIL_THREADS_GROUP_BY), "active",
|
||
+ ACTION (MAIL_THREADS_EXPAND_ALL), "sensitive",
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ ACTION (MAIL_PREVIEW), "active",
|
||
+ mail_view, "preview-visible",
|
||
+ G_BINDING_BIDIRECTIONAL |
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ ACTION (MAIL_THREADS_GROUP_BY), "active",
|
||
+ mail_shell_content, "group-by-threads",
|
||
+ G_BINDING_BIDIRECTIONAL |
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ ACTION (MAIL_PREVIEW), "active",
|
||
+ ACTION (MAIL_VIEW_CLASSIC), "sensitive",
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ ACTION (MAIL_PREVIEW), "active",
|
||
+ ACTION (MAIL_VIEW_VERTICAL), "sensitive",
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ ACTION (MAIL_SHOW_DELETED), "active",
|
||
+ mail_view, "show-deleted",
|
||
+ G_BINDING_BIDIRECTIONAL |
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ ACTION (MAIL_SHOW_JUNK), "active",
|
||
+ mail_view, "show-junk",
|
||
+ G_BINDING_BIDIRECTIONAL |
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ shell_backend, "busy",
|
||
+ ACTION (MAIL_STOP), "sensitive",
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ /* Keep the sensitivity of "Create Search Folder from Search"
|
||
+ * in sync with "Save Search" so that its only selectable when
|
||
+ * showing search results. */
|
||
+ e_binding_bind_property (
|
||
+ ACTION (SEARCH_SAVE), "sensitive",
|
||
+ ACTION (MAIL_CREATE_SEARCH_FOLDER), "sensitive",
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+
|
||
+ e_binding_bind_property (
|
||
+ shell, "online",
|
||
+ ACTION (MAIL_DOWNLOAD), "sensitive",
|
||
+ G_BINDING_SYNC_CREATE);
|
||
+}
|
||
+
|
||
+void
|
||
+e_mail_shell_view_update_search_filter (EMailShellView *mail_shell_view)
|
||
+{
|
||
+ EMailShellContent *mail_shell_content;
|
||
+ EShellView *shell_view;
|
||
+ EShellWindow *shell_window;
|
||
+ EShellBackend *shell_backend;
|
||
+ EShellSearchbar *searchbar;
|
||
+ EMailLabelListStore *label_store;
|
||
+ EMailBackend *backend;
|
||
+ EMailSession *session;
|
||
+ EActionComboBox *combo_box;
|
||
+ GtkActionGroup *action_group;
|
||
+ GtkRadioAction *radio_action;
|
||
+ GtkTreeIter iter;
|
||
+ GList *list;
|
||
+ GSList *group;
|
||
+ gboolean valid;
|
||
+ gint ii = 0;
|
||
+
|
||
+ g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view));
|
||
+
|
||
+ shell_view = E_SHELL_VIEW (mail_shell_view);
|
||
+ shell_window = e_shell_view_get_shell_window (shell_view);
|
||
+ shell_backend = e_shell_view_get_shell_backend (shell_view);
|
||
+
|
||
+ backend = E_MAIL_BACKEND (shell_backend);
|
||
+ session = e_mail_backend_get_session (backend);
|
||
+ label_store = e_mail_ui_session_get_label_store (
|
||
+ E_MAIL_UI_SESSION (session));
|
||
+
|
||
+ action_group = ACTION_GROUP (MAIL_FILTER);
|
||
+ e_action_group_remove_all_actions (action_group);
|
||
+
|
||
+ /* Add the standard filter actions. No callback is needed
|
||
+ * because changes in the EActionComboBox are detected and
|
||
+ * handled by EShellSearchbar. */
|
||
+ gtk_action_group_add_radio_actions (
|
||
+ action_group, mail_filter_entries,
|
||
+ G_N_ELEMENTS (mail_filter_entries),
|
||
+ MAIL_FILTER_ALL_MESSAGES, NULL, NULL);
|
||
+
|
||
+ /* Retrieve the radio group from an action we just added. */
|
||
+ list = gtk_action_group_list_actions (action_group);
|
||
+ radio_action = GTK_RADIO_ACTION (list->data);
|
||
+ group = gtk_radio_action_get_group (radio_action);
|
||
+ g_list_free (list);
|
||
+
|
||
+ valid = gtk_tree_model_get_iter_first (
|
||
+ GTK_TREE_MODEL (label_store), &iter);
|
||
+
|
||
+ while (valid) {
|
||
+ GtkAction *action;
|
||
+ gchar *action_name;
|
||
+ gchar *stock_id;
|
||
+ gchar *label;
|
||
+
|
||
+ label = e_mail_label_list_store_get_name (
|
||
+ label_store, &iter);
|
||
+ stock_id = e_mail_label_list_store_get_stock_id (
|
||
+ label_store, &iter);
|
||
+
|
||
+ action_name = g_strdup_printf ("mail-filter-label-%d", ii);
|
||
+ radio_action = gtk_radio_action_new (
|
||
+ action_name, label, NULL, stock_id, ii);
|
||
+ g_free (action_name);
|
||
+
|
||
+ gtk_radio_action_set_group (radio_action, group);
|
||
+ group = gtk_radio_action_get_group (radio_action);
|
||
+
|
||
+ /* The action group takes ownership of the action. */
|
||
+ action = GTK_ACTION (radio_action);
|
||
+ gtk_action_group_add_action (action_group, action);
|
||
+ g_object_unref (radio_action);
|
||
+
|
||
+ g_free (label);
|
||
+ g_free (stock_id);
|
||
+
|
||
+ valid = gtk_tree_model_iter_next (
|
||
+ GTK_TREE_MODEL (label_store), &iter);
|
||
+ ii++;
|
||
+ }
|
||
+
|
||
+ mail_shell_content = mail_shell_view->priv->mail_shell_content;
|
||
+ searchbar = e_mail_shell_content_get_searchbar (mail_shell_content);
|
||
+ combo_box = e_shell_searchbar_get_filter_combo_box (searchbar);
|
||
+
|
||
+ e_shell_view_block_execute_search (shell_view);
|
||
+
|
||
+ /* Use any action in the group; doesn't matter which. */
|
||
+ e_action_combo_box_set_action (combo_box, radio_action);
|
||
+
|
||
+ ii = MAIL_FILTER_MESSAGES_NOT_JUNK;
|
||
+ e_action_combo_box_add_separator_after (combo_box, ii);
|
||
+
|
||
+ ii = MAIL_FILTER_READ_MESSAGES;
|
||
+ e_action_combo_box_add_separator_after (combo_box, ii);
|
||
+
|
||
+ e_shell_view_unblock_execute_search (shell_view);
|
||
+}
|
||
+
|
||
diff -urN a/src/modules/webkit-inspector/evolution-webkit-inspector.c b/src/modules/webkit-inspector/evolution-webkit-inspector.c
|
||
--- a/src/modules/webkit-inspector/evolution-webkit-inspector.c 2025-06-07 14:20:30.299070278 -0700
|
||
+++ b/src/modules/webkit-inspector/evolution-webkit-inspector.c 2025-06-07 14:27:24.063673134 -0700
|
||
@@ -31,7 +31,7 @@
|
||
(G_TYPE_CHECK_INSTANCE_CAST \
|
||
((obj), E_TYPE_WEBKIT_INSPECTOR, EWebKitInspector))
|
||
|
||
-/* <Control>+<Shift>+I or <Control>+<Shift>+D */
|
||
+/* <Super>+<Shift>+I or <Super>+<Shift>+D */
|
||
#define WEBKIT_INSPECTOR_MOD (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
|
||
#define WEBKIT_INSPECTOR_KEY1 (GDK_KEY_I)
|
||
#define WEBKIT_INSPECTOR_KEY2 (GDK_KEY_D)
|
||
diff -urN a/src/plugins/external-editor/external-editor.c b/src/plugins/external-editor/external-editor.c
|
||
--- a/src/plugins/external-editor/external-editor.c 2025-06-07 14:20:57.387397894 -0700
|
||
+++ b/src/plugins/external-editor/external-editor.c 2025-06-07 14:27:24.063673134 -0700
|
||
@@ -487,7 +487,7 @@
|
||
{ "ExternalEditor",
|
||
NULL,
|
||
N_("Compose in External Editor"),
|
||
- "<Shift><Control>e",
|
||
+ "<Shift><Super>e",
|
||
N_("Compose in External Editor"),
|
||
G_CALLBACK (launch_editor) }
|
||
};
|
||
diff -urN a/src/plugins/templates/templates.c b/src/plugins/templates/templates.c
|
||
--- a/src/plugins/templates/templates.c 2025-06-07 14:20:57.391397942 -0700
|
||
+++ b/src/plugins/templates/templates.c 2025-06-07 14:27:24.063673134 -0700
|
||
@@ -906,7 +906,7 @@
|
||
{ "template",
|
||
"document-save",
|
||
N_("Save as _Template"),
|
||
- "<Shift><Control>t",
|
||
+ "<Shift><Super>t",
|
||
N_("Save as Template"),
|
||
G_CALLBACK (action_template_cb) }
|
||
};
|
||
diff -urN a/src/shell/e-shell-window-actions.c b/src/shell/e-shell-window-actions.c
|
||
--- a/src/shell/e-shell-window-actions.c 2025-06-07 14:20:57.395397990 -0700
|
||
+++ b/src/shell/e-shell-window-actions.c 2025-06-07 14:27:24.063673134 -0700
|
||
@@ -921,21 +921,21 @@
|
||
{ "close",
|
||
"window-close",
|
||
N_("_Close Window"),
|
||
- "<Control>w",
|
||
+ "<Super>w",
|
||
N_("Close this window"),
|
||
G_CALLBACK (action_close_cb) },
|
||
|
||
{ "close-window-menu",
|
||
"window-close",
|
||
N_("_Close"),
|
||
- "<Control>w",
|
||
+ "<Super>w",
|
||
N_("Close this window"),
|
||
G_CALLBACK (action_close_cb) },
|
||
|
||
{ "close-window",
|
||
"window-close",
|
||
N_("_Close Window"),
|
||
- "<Control>w",
|
||
+ "<Super>w",
|
||
N_("Close this window"),
|
||
G_CALLBACK (action_close_cb) },
|
||
|
||
@@ -949,14 +949,14 @@
|
||
{ "copy-clipboard",
|
||
"edit-copy",
|
||
N_("_Copy"),
|
||
- "<Control>c",
|
||
+ "<Super>c",
|
||
N_("Copy the selection"),
|
||
NULL }, /* Handled by EFocusTracker */
|
||
|
||
{ "cut-clipboard",
|
||
"edit-cut",
|
||
N_("Cu_t"),
|
||
- "<Control>x",
|
||
+ "<Super>x",
|
||
N_("Cut the selection"),
|
||
NULL }, /* Handled by EFocusTracker */
|
||
|
||
@@ -977,14 +977,14 @@
|
||
{ "new-window",
|
||
"window-new",
|
||
N_("New _Window"),
|
||
- "<Control><Shift>w",
|
||
+ "<Super><Shift>w",
|
||
N_("Create a new window displaying this view"),
|
||
G_CALLBACK (action_new_window_cb) },
|
||
|
||
{ "paste-clipboard",
|
||
"edit-paste",
|
||
N_("_Paste"),
|
||
- "<Control>v",
|
||
+ "<Super>v",
|
||
N_("Paste the clipboard"),
|
||
NULL }, /* Handled by EFocusTracker */
|
||
|
||
@@ -998,14 +998,14 @@
|
||
{ "preferences",
|
||
"preferences-system",
|
||
N_("_Preferences"),
|
||
- "<Control><Shift>s",
|
||
+ "<Super><Shift>s",
|
||
N_("Configure Evolution"),
|
||
G_CALLBACK (action_preferences_cb) },
|
||
|
||
{ "quit",
|
||
"application-exit",
|
||
N_("_Quit"),
|
||
- "<Control>q",
|
||
+ "<Super>q",
|
||
N_("Exit the program"),
|
||
G_CALLBACK (action_quit_cb) },
|
||
|
||
@@ -1026,7 +1026,7 @@
|
||
{ "search-clear",
|
||
"edit-clear",
|
||
N_("_Clear"),
|
||
- "<Control><Shift>q",
|
||
+ "<Super><Shift>q",
|
||
N_("Clear the current search parameters"),
|
||
G_CALLBACK (action_search_clear_cb) },
|
||
|
||
@@ -1040,7 +1040,7 @@
|
||
{ "search-options",
|
||
"edit-find",
|
||
N_("_Find"),
|
||
- "<Control>f",
|
||
+ "<Super>f",
|
||
N_("Click here to change the search type"),
|
||
G_CALLBACK (action_search_options_cb) },
|
||
|
||
@@ -1061,14 +1061,14 @@
|
||
{ "select-all",
|
||
"edit-select-all",
|
||
N_("Select _All"),
|
||
- "<Control>a",
|
||
+ "<Super>a",
|
||
N_("Select all text"),
|
||
NULL }, /* Handled by EFocusTracker */
|
||
|
||
{ "shortcuts",
|
||
NULL,
|
||
N_("_Keyboard Shortcuts"),
|
||
- "<Control><Shift>question",
|
||
+ "<Super><Shift>question",
|
||
N_("Show keyboard shortcuts"),
|
||
G_CALLBACK (action_shortcuts_cb) },
|
||
|
||
@@ -1717,7 +1717,7 @@
|
||
|
||
/* The first nine views have accelerators Ctrl+(1-9). */
|
||
if (ii < 10)
|
||
- accelerator = g_strdup_printf ("<Control>%d", ii);
|
||
+ accelerator = g_strdup_printf ("<Super>%d", ii);
|
||
else
|
||
accelerator = g_strdup ("");
|
||
|