Commit 4c0c3621 authored by Milan Crha's avatar Milan Crha

Bug 255032 - Be able to write a note on a mail

parent 82c6b612
......@@ -386,8 +386,12 @@ attachment_update_icon_column_idle_cb (gpointer weak_ref)
file_info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
}
if (e_attachment_is_mail_note (attachment)) {
g_clear_object (&icon);
icon = g_themed_icon_new ("evolution-memos");
/* Prefer the thumbnail if we have one. */
if (thumbnail_path != NULL && *thumbnail_path != '\0') {
} else if (thumbnail_path != NULL && *thumbnail_path != '\0') {
GFile *file;
file = g_file_new_for_path (thumbnail_path);
......@@ -1335,6 +1339,23 @@ e_attachment_cancel (EAttachment *attachment)
g_cancellable_cancel (attachment->priv->cancellable);
}
gboolean
e_attachment_is_mail_note (EAttachment *attachment)
{
CamelContentType *ct;
g_return_val_if_fail (E_IS_ATTACHMENT (attachment), FALSE);
if (!attachment->priv->mime_part)
return FALSE;
ct = camel_mime_part_get_content_type (attachment->priv->mime_part);
if (!ct || !camel_content_type_is (ct, "message", "rfc822"))
return FALSE;
return camel_medium_get_header (CAMEL_MEDIUM (attachment->priv->mime_part), "X-Evolution-Note") != NULL;
}
gboolean
e_attachment_get_can_show (EAttachment *attachment)
{
......
......@@ -71,6 +71,7 @@ void e_attachment_add_to_multipart (EAttachment *attachment,
CamelMultipart *multipart,
const gchar *default_charset);
void e_attachment_cancel (EAttachment *attachment);
gboolean e_attachment_is_mail_note (EAttachment *attachment);
gboolean e_attachment_get_can_show (EAttachment *attachment);
void e_attachment_set_can_show (EAttachment *attachment,
gboolean can_show);
......
......@@ -95,6 +95,7 @@ mailinclude_HEADERS = \
e-mail-label-tree-view.h \
e-mail-message-pane.h \
e-mail-migrate.h \
e-mail-notes.h \
e-mail-paned-view.h \
e-mail-print-config-headers.h \
e-mail-printer.h \
......@@ -175,6 +176,7 @@ libevolution_mail_la_SOURCES = \
e-mail-label-tree-view.c \
e-mail-message-pane.c \
e-mail-migrate.c \
e-mail-notes.c \
e-mail-paned-view.c \
e-mail-print-config-headers.c \
e-mail-printer.c \
......
......@@ -36,6 +36,7 @@
#include "e-http-request.h"
#include "e-mail-display-popup-extension.h"
#include "e-mail-notes.h"
#include "e-mail-request.h"
#include "em-composer-utils.h"
#include "em-utils.h"
......@@ -758,6 +759,7 @@ mail_display_plugin_widget_requested (WebKitWebView *web_view,
* that URI identifies the attachment itself */
if (E_IS_ATTACHMENT_BUTTON (widget)) {
EMailPartAttachment *empa = (EMailPartAttachment *) part;
EAttachment *attachment;
gchar *attachment_part_id;
if (empa->attachment_view_part_id)
......@@ -771,6 +773,28 @@ mail_display_plugin_widget_requested (WebKitWebView *web_view,
G_OBJECT (widget), "attachment_id",
g_strdup (attachment_part_id),
(GDestroyNotify) g_free);
attachment = e_mail_part_attachment_ref_attachment (empa);
if (attachment && e_attachment_is_mail_note (attachment)) {
CamelFolder *folder;
const gchar *message_uid;
folder = e_mail_part_list_get_folder (display->priv->part_list);
message_uid = e_mail_part_list_get_message_uid (display->priv->part_list);
if (folder && message_uid) {
CamelMessageInfo *info;
info = camel_folder_get_message_info (folder, message_uid);
if (info) {
if (!camel_message_info_user_flag (info, E_MAIL_NOTES_USER_FLAG))
camel_message_info_set_user_flag (info, E_MAIL_NOTES_USER_FLAG, TRUE);
camel_message_info_unref (info);
}
}
}
g_clear_object (&attachment);
} else {
object_uri = g_strdup (part_id);
}
......
This diff is collapsed.
/*
* 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 Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef E_MAIL_NOTES_H
#define E_MAIL_NOTES_H
#include <glib.h>
#include <gio/gio.h>
#include <gtk/gtk.h>
#include <camel/camel.h>
#define E_MAIL_NOTES_USER_FLAG "$has_note"
#define E_MAIL_NOTES_HEADER "X-Evolution-Note"
G_BEGIN_DECLS
void e_mail_notes_edit (GtkWindow *parent,
CamelFolder *folder,
const gchar *uid);
gboolean e_mail_notes_remove_sync (CamelFolder *folder,
const gchar *uid,
GCancellable *cancellable,
GError **error);
G_END_DECLS
#endif /* E_MAIL_NOTES_H */
......@@ -1193,6 +1193,10 @@ e_mail_reader_mark_selected_ignore_thread (EMailReader *reader,
camel_folder_get_full_name (folder), mail_reader_utils_mark_ignore_thread_thread,
mit, mark_ignore_thread_data_free);
if (activity)
e_shell_backend_add_activity (E_SHELL_BACKEND (e_mail_reader_get_backend (reader)), activity);
g_clear_object (&activity);
}
......
......@@ -42,6 +42,7 @@
#include "e-mail-backend.h"
#include "e-mail-browser.h"
#include "e-mail-enumtypes.h"
#include "e-mail-notes.h"
#include "e-mail-reader-utils.h"
#include "e-mail-ui-session.h"
#include "e-mail-view.h"
......@@ -408,6 +409,100 @@ action_mail_copy_cb (GtkAction *action,
mail_reader_copy_or_move_selected_messages (reader, FALSE);
}
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) {
e_mail_notes_edit (e_mail_reader_get_window (reader), folder, uids->pdata[0]);
} 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_free (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;
dnd = g_new0 (DeleteNoteData, 1);
dnd->folder = g_object_ref (folder);
dnd->uid = g_strdup (uids->pdata[0]);
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);
} else {
g_warn_if_reached ();
}
g_clear_object (&folder);
g_ptr_array_unref (uids);
}
static void
action_mail_delete_cb (GtkAction *action,
EMailReader *reader)
......@@ -1924,6 +2019,27 @@ static GtkActionEntry mail_reader_entries[] = {
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..."),
......@@ -2399,6 +2515,18 @@ static EPopupActionEntry mail_reader_popup_entries[] = {
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" },
......@@ -3495,6 +3623,7 @@ mail_reader_update_actions (EMailReader *reader,
gboolean selection_has_undeleted_messages;
gboolean selection_has_unimportant_messages;
gboolean selection_has_unread_messages;
gboolean selection_has_mail_note;
gboolean selection_is_mailing_list;
gboolean single_message_selected;
gboolean first_message_selected = FALSE;
......@@ -3535,6 +3664,8 @@ mail_reader_update_actions (EMailReader *reader,
(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_is_mailing_list =
(state & E_MAIL_READER_SELECTION_IS_MAILING_LIST);
......@@ -3600,6 +3731,24 @@ mail_reader_update_actions (EMailReader *reader,
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);
......@@ -4353,6 +4502,7 @@ e_mail_reader_check_state (EMailReader *reader)
gboolean has_undeleted = FALSE;
gboolean has_unimportant = FALSE;
gboolean has_unread = FALSE;
gboolean has_mail_note = FALSE;
gboolean have_enabled_account = FALSE;
gboolean drafts_or_outbox = FALSE;
gboolean store_supports_vjunk = FALSE;
......@@ -4408,6 +4558,9 @@ e_mail_reader_check_state (EMailReader *reader)
if (info == NULL)
continue;
if (camel_message_info_user_flag (info, E_MAIL_NOTES_USER_FLAG))
has_mail_note = TRUE;
flags = camel_message_info_flags (info);
if (flags & CAMEL_MESSAGE_SEEN)
......@@ -4529,6 +4682,8 @@ e_mail_reader_check_state (EMailReader *reader)
state |= E_MAIL_READER_FOLDER_IS_VTRASH;
if (archive_folder_set)
state |= E_MAIL_READER_FOLDER_ARCHIVE_FOLDER_SET;
if (has_mail_note)
state |= E_MAIL_READER_SELECTION_HAS_MAIL_NOTE;
g_clear_object (&folder);
g_ptr_array_unref (uids);
......
......@@ -90,7 +90,8 @@ enum {
E_MAIL_READER_FOLDER_IS_VTRASH = 1 << 18,
E_MAIL_READER_FOLDER_ARCHIVE_FOLDER_SET = 1 << 19,
E_MAIL_READER_SELECTION_HAS_IGNORE_THREAD = 1 << 20,
E_MAIL_READER_SELECTION_HAS_NOTIGNORE_THREAD = 1 << 21
E_MAIL_READER_SELECTION_HAS_NOTIGNORE_THREAD = 1 << 21,
E_MAIL_READER_SELECTION_HAS_MAIL_NOTE = 1 << 22
};
struct _EMailReaderInterface {
......
......@@ -29,6 +29,7 @@
#include <mail/e-mail-label-tree-view.h>
#include <mail/e-mail-message-pane.h>
#include <mail/e-mail-migrate.h>
#include <mail/e-mail-notes.h>
#include <mail/e-mail-paned-view.h>
#include <mail/e-mail-reader.h>
#include <mail/e-mail-reader-utils.h>
......
......@@ -790,6 +790,24 @@
</input>
</part>
<part name="notes">
<_title>Notes</_title>
<input type="optionlist" name="match-type">
<option value="exist">
<_title>Exist</_title>
<code>
(match-all (user-flag "$has_note"))
</code>
</option>
<option value="not exist">
<_title>Do Not Exist</_title>
<code>
(match-all (not (user-flag "$has_note")))
</code>
</option>
</input>
</part>
<part name="mlist">
<_title>Mailing list</_title>
<input type="optionlist" name="mlist-type">
......
......@@ -599,4 +599,24 @@ in the folder will be available in offline mode.</_secondary>
<!-- Translators: This constructs a string like "Overdue: Follow-up by Tuesday, January 13, 2009" -->
<_primary>Overdue: {0} by {1}</_primary>
</error>
<error id="ask-mail-note-changed" type="question" default="GTK_RESPONSE_YES">
<_primary>Do you wish to save your changes?</_primary>
<_secondary xml:space="preserve">This message note has been changed, but has not been saved.</_secondary>
<button _label="_Discard changes" response="GTK_RESPONSE_NO"/>
<button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
<button stock="gtk-save" response="GTK_RESPONSE_YES"/>
</error>
<error id="failed-delete-note" type="error">
<!-- Translators: {0} is the name of the folder where the delete of the message note failed. -->
<_primary>Failed to delete message note in folder '{0}'</_primary>
<secondary>{1}</secondary>
</error>
<error id="failed-store-note" type="error">
<!-- Translators: {0} is the name of the folder where the store of the message note failed. -->
<_primary>Failed to store message note in folder '{0}'</_primary>
<secondary>{1}</secondary>
</error>
</error-list>
......@@ -34,6 +34,7 @@
#include <glib/gstdio.h>
#include "e-mail-label-list-store.h"
#include "e-mail-notes.h"
#include "e-mail-ui-session.h"
#include "em-utils.h"
......@@ -328,7 +329,8 @@ static const gchar *score_icons[] = {
static const gchar *attachment_icons[] = {
NULL, /* empty icon */
"mail-attachment",
"stock_new-meeting"
"stock_new-meeting",
"evolution-memos"
};
static const gchar *flagged_icons[] = {
......@@ -1818,6 +1820,8 @@ ml_tree_value_at_ex (ETreeModel *etm,
str = camel_message_info_user_tag (msg_info, "follow-up");
return (gpointer)(str ? str : "");
case COL_ATTACHMENT:
if (camel_message_info_user_flag (msg_info, E_MAIL_NOTES_USER_FLAG))
return GINT_TO_POINTER (3);
if (camel_message_info_user_flag (msg_info, "$has_cal"))
return GINT_TO_POINTER (2);
return GINT_TO_POINTER ((camel_message_info_flags (msg_info) & CAMEL_MESSAGE_ATTACHMENTS) != 0);
......
......@@ -875,6 +875,24 @@
</input>
</part>
<part name="notes">
<_title>Notes</_title>
<input type="optionlist" name="match-type">
<option value="exist">
<_title>Exist</_title>
<code>
(match-all (user-flag "$has_note"))
</code>
</option>
<option value="not exist">
<_title>Do Not Exist</_title>
<code>
(match-all (not (user-flag "$has_note")))
</code>
</option>
</input>
</part>
<part name="mlist">
<_title>Mailing list</_title>
<input type="optionlist" name="mlist-type">
......
......@@ -874,6 +874,24 @@
</input>
</part>
<part name="notes">
<_title>Notes</_title>
<input type="optionlist" name="match-type">
<option value="exist">
<_title>Exist</_title>
<code>
(match-all (user-flag "$has_note"))
</code>
</option>
<option value="not exist">
<_title>Do Not Exist</_title>
<code>
(match-all (not (user-flag "$has_note")))
</code>
</option>
</input>
</part>
<part name="mlist">
<_title>Mailing list</_title>
<input type="optionlist" name="mlist-type">
......
......@@ -2079,6 +2079,13 @@ static GtkRadioActionEntry mail_filter_entries[] = {
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"),
......
......@@ -230,6 +230,8 @@
E_SHELL_WINDOW_ACTION ((window), "mail-filter-messages-not-junk")
#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS(window) \
E_SHELL_WINDOW_ACTION ((window), "mail-filter-messages-with-attachments")
#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_MESSAGES_WITH_NOTES(window) \
E_SHELL_WINDOW_ACTION ((window), "mail-filter-messages-with-notes")
#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_NO_LABEL(window) \
E_SHELL_WINDOW_ACTION ((window), "mail-filter-no-label")
#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_READ_MESSAGES(window) \
......
......@@ -83,8 +83,9 @@ enum {
MAIL_FILTER_READ_MESSAGES = 5000,
MAIL_FILTER_LAST_5_DAYS_MESSAGES = 5001,
MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS = 5002,
MAIL_FILTER_IMPORTANT_MESSAGES = 5003,
MAIL_FILTER_MESSAGES_NOT_JUNK = 5004
MAIL_FILTER_MESSAGES_WITH_NOTES = 5003,
MAIL_FILTER_IMPORTANT_MESSAGES = 5004,
MAIL_FILTER_MESSAGES_NOT_JUNK = 5005
};
/* Search items are displayed in ascending order. */
......
......@@ -553,6 +553,13 @@ filter:
query = temp;
break;
case MAIL_FILTER_MESSAGES_WITH_NOTES:
temp = g_strdup_printf (
"(and %s (match-all (user-flag \"$has_note\")))", query);
g_free (query);
query = temp;
break;
case MAIL_FILTER_IMPORTANT_MESSAGES:
temp = g_strdup_printf (
"(and %s (match-all "
......
......@@ -355,6 +355,7 @@ mail/e-mail-label-list-store.c
mail/e-mail-label-manager.c
mail/e-mail-label-tree-view.c
mail/e-mail-migrate.c
mail/e-mail-notes.c
mail/e-mail-print-config-headers.c
mail/e-mail-printer.c
mail/e-mail-reader.c
......
......@@ -98,6 +98,10 @@
<menuitem action='mail-remove-attachments'/>
<menuitem action='mail-remove-duplicates'/>
<separator/>
<menuitem action='mail-add-note'/>
<menuitem action='mail-edit-note'/>
<menuitem action='mail-delete-note'/>
<separator/>
<menu action='mail-create-menu'>
<placeholder action='mail-conversion-actions'/>
<separator/>
......@@ -169,6 +173,10 @@
<menuitem action='mail-popup-save-as'/>
<menuitem action='mail-popup-print'/>
<separator/>
<menuitem action='mail-add-note'/>
<menuitem action='mail-edit-note'/>
<menuitem action='mail-delete-note'/>
<separator/>
<placeholder name='mail-message-popup-actions'/>
</popup>
</ui>
......@@ -114,6 +114,11 @@
<menuitem action='mail-popup-flag-for-followup'/>
<menuitem action="mail-popup-flag-clear"/>
<menuitem action="mail-popup-flag-completed"/>
<separator/>
<menuitem action='mail-popup-add-note'/>
<menuitem action='mail-popup-edit-note'/>
<menuitem action='mail-popup-delete-note'/>
<separator/>
<menuitem action='mail-popup-mark-ignore-thread-whole'/>
<menuitem action='mail-popup-mark-ignore-thread-sub'/>
<menuitem action='mail-popup-mark-unignore-thread-whole'/>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment