mirror of https://github.com/djcb/mu.git
* refactoring & add 'view-source' and 'view-message' (activate with context menu)
This commit is contained in:
parent
21fcef13d9
commit
6daf2e9989
|
@ -39,6 +39,10 @@ libmuwidgets_la_SOURCES= \
|
||||||
mu-msg-body-view.h \
|
mu-msg-body-view.h \
|
||||||
mu-msg-header-view.c \
|
mu-msg-header-view.c \
|
||||||
mu-msg-header-view.h \
|
mu-msg-header-view.h \
|
||||||
|
mu-msg-normal-view.h \
|
||||||
|
mu-msg-normal-view.c \
|
||||||
|
mu-msg-source-view.h \
|
||||||
|
mu-msg-source-view.c \
|
||||||
mu-msg-view.h \
|
mu-msg-view.h \
|
||||||
mu-msg-view.c
|
mu-msg-view.c
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,77 @@ item_activated (MuMsgAttachView *self, GtkTreePath *tpath)
|
||||||
partnum, self->_priv->_msg);
|
partnum, self->_priv->_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
accumulate_parts (MuMsgAttachView *self, GtkTreePath *path, GSList **lst)
|
||||||
|
{
|
||||||
|
GtkTreeIter iter;
|
||||||
|
GtkTreeModel *model;
|
||||||
|
|
||||||
|
/* don't unref */
|
||||||
|
model = gtk_icon_view_get_model (GTK_ICON_VIEW(self));
|
||||||
|
|
||||||
|
if (gtk_tree_model_get_iter (model, &iter, path)) {
|
||||||
|
gchar *filepath;
|
||||||
|
gint idx;
|
||||||
|
gtk_tree_model_get (model, &iter, PARTNUM_COL, &idx, -1);
|
||||||
|
filepath = mu_msg_part_filepath_cache (self->_priv->_msg, idx);
|
||||||
|
if (filepath) {
|
||||||
|
if (mu_msg_part_save (self->_priv->_msg, filepath,
|
||||||
|
idx, FALSE, TRUE)) {
|
||||||
|
GFile *file;
|
||||||
|
file = g_file_new_for_path (filepath);
|
||||||
|
*lst = g_slist_prepend (*lst, g_file_get_uri(file));
|
||||||
|
g_object_unref (file);
|
||||||
|
g_free (filepath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_drag_data_get (MuMsgAttachView *self, GdkDragContext *drag_context,
|
||||||
|
GtkSelectionData *data, guint info, guint time, gpointer user_data)
|
||||||
|
{
|
||||||
|
GSList *lst, *cur;
|
||||||
|
char **uris;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
lst = NULL;
|
||||||
|
gtk_icon_view_selected_foreach (GTK_ICON_VIEW(self),
|
||||||
|
(GtkIconViewForeachFunc)accumulate_parts,
|
||||||
|
&lst);
|
||||||
|
|
||||||
|
uris = g_new(char*, g_slist_length(lst) + 1);
|
||||||
|
|
||||||
|
/* now, create file uris for all of these ... */
|
||||||
|
for (cur = lst, i = 0; cur; cur = g_slist_next(lst)) {
|
||||||
|
uris[i] = (gchar*)cur->data;
|
||||||
|
g_warning ("%s", (gchar*)cur->data);
|
||||||
|
}
|
||||||
|
uris[i] = NULL;
|
||||||
|
|
||||||
|
gtk_selection_data_set_uris (data, uris);
|
||||||
|
|
||||||
|
g_strfreev (uris);
|
||||||
|
g_slist_foreach (lst, (GFunc)g_free, NULL);
|
||||||
|
g_slist_free (lst);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_drag_and_drop (MuMsgAttachView *self)
|
||||||
|
{
|
||||||
|
GtkTargetEntry target;
|
||||||
|
target.target = "text/uri-list";
|
||||||
|
target.flags = GTK_TARGET_OTHER_APP;
|
||||||
|
target.info = 0;
|
||||||
|
|
||||||
|
gtk_icon_view_enable_model_drag_source (GTK_ICON_VIEW(self),
|
||||||
|
GDK_BUTTON1_MASK,
|
||||||
|
&target, 1, GDK_ACTION_COPY);
|
||||||
|
g_signal_connect (self, "drag-data-get", G_CALLBACK(on_drag_data_get), self);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mu_msg_attach_view_init (MuMsgAttachView *obj)
|
mu_msg_attach_view_init (MuMsgAttachView *obj)
|
||||||
|
@ -120,6 +191,9 @@ mu_msg_attach_view_init (MuMsgAttachView *obj)
|
||||||
gtk_icon_view_set_item_padding (GTK_ICON_VIEW(obj), 0);
|
gtk_icon_view_set_item_padding (GTK_ICON_VIEW(obj), 0);
|
||||||
gtk_icon_view_set_item_orientation (GTK_ICON_VIEW(obj),
|
gtk_icon_view_set_item_orientation (GTK_ICON_VIEW(obj),
|
||||||
GTK_ORIENTATION_HORIZONTAL);
|
GTK_ORIENTATION_HORIZONTAL);
|
||||||
|
gtk_icon_view_set_selection_mode (GTK_ICON_VIEW(obj),
|
||||||
|
GTK_SELECTION_MULTIPLE);
|
||||||
|
init_drag_and_drop (obj);
|
||||||
|
|
||||||
g_signal_connect (G_OBJECT(obj), "item-activated",
|
g_signal_connect (G_OBJECT(obj), "item-activated",
|
||||||
G_CALLBACK(item_activated), NULL);
|
G_CALLBACK(item_activated), NULL);
|
||||||
|
@ -163,9 +237,11 @@ each_part (MuMsg *msg, MuMsgPart *part, CBData *cbdata)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!part->type || !part->subtype)
|
if (!part->type || !part->subtype)
|
||||||
snprintf (ctype, sizeof(ctype), "%s", "application/octet-stream");
|
snprintf (ctype, sizeof(ctype), "%s",
|
||||||
|
"application/octet-stream");
|
||||||
else
|
else
|
||||||
snprintf (ctype, sizeof(ctype), "%s/%s", part->type, part->subtype);
|
snprintf (ctype, sizeof(ctype), "%s/%s",
|
||||||
|
part->type, part->subtype);
|
||||||
|
|
||||||
pixbuf = mu_widget_util_get_icon_pixbuf_for_content_type (ctype, 16);
|
pixbuf = mu_widget_util_get_icon_pixbuf_for_content_type (ctype, 16);
|
||||||
if (!pixbuf) {
|
if (!pixbuf) {
|
||||||
|
@ -203,7 +279,6 @@ mu_msg_attach_view_set_message (MuMsgAttachView *self, MuMsg *msg)
|
||||||
|
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
self->_priv->_msg = mu_msg_ref (msg);
|
self->_priv->_msg = mu_msg_ref (msg);
|
||||||
|
|
||||||
|
|
|
@ -41,11 +41,8 @@ enum {
|
||||||
|
|
||||||
struct _MuMsgBodyViewPrivate {
|
struct _MuMsgBodyViewPrivate {
|
||||||
WebKitWebSettings *_settings;
|
WebKitWebSettings *_settings;
|
||||||
MuMsg *_message;
|
MuMsg *_msg;
|
||||||
|
gboolean _internal_msg;
|
||||||
/* 'mu_mode' means some internal mode where cmd: urls are
|
|
||||||
* acceptable */
|
|
||||||
gboolean _mu_mode;
|
|
||||||
};
|
};
|
||||||
#define MU_MSG_BODY_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
|
#define MU_MSG_BODY_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
|
||||||
MU_TYPE_MSG_BODY_VIEW, \
|
MU_TYPE_MSG_BODY_VIEW, \
|
||||||
|
@ -126,15 +123,15 @@ on_navigation_policy_decision_requested (MuMsgBodyView *self, WebKitWebFrame *fr
|
||||||
|
|
||||||
uri = webkit_network_request_get_uri (request);
|
uri = webkit_network_request_get_uri (request);
|
||||||
reason = webkit_web_navigation_action_get_reason (nav_action);
|
reason = webkit_web_navigation_action_get_reason (nav_action);
|
||||||
|
|
||||||
/* if it wasn't a user click, do the navigation */
|
/* if it wasn't a user click, don't the navigation */
|
||||||
if (reason != WEBKIT_WEB_NAVIGATION_REASON_LINK_CLICKED) {
|
if (reason != WEBKIT_WEB_NAVIGATION_REASON_LINK_CLICKED) {
|
||||||
webkit_web_policy_decision_ignore (policy_decision);
|
webkit_web_policy_decision_ignore (policy_decision);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we handle links clicked ourselves, no need for navigation */
|
/* we handle links clicked ourselves, no need for navigation */
|
||||||
webkit_web_policy_decision_ignore (policy_decision);
|
webkit_web_policy_decision_use (policy_decision);
|
||||||
|
|
||||||
/* if there are 'cmd:<action>" links in the body text of
|
/* if there are 'cmd:<action>" links in the body text of
|
||||||
* mu-internal messages (ie., notification from mu, not real
|
* mu-internal messages (ie., notification from mu, not real
|
||||||
|
@ -143,7 +140,7 @@ on_navigation_policy_decision_requested (MuMsgBodyView *self, WebKitWebFrame *fr
|
||||||
* a <a href="cmd:refresh">Refresh</a> link
|
* a <a href="cmd:refresh">Refresh</a> link
|
||||||
*/
|
*/
|
||||||
if (g_ascii_strncasecmp (uri, "cmd:", 4) == 0) {
|
if (g_ascii_strncasecmp (uri, "cmd:", 4) == 0) {
|
||||||
if (self->_priv->_mu_mode) {
|
if (self->_priv->_internal_msg) {
|
||||||
g_signal_emit (G_OBJECT(self),
|
g_signal_emit (G_OBJECT(self),
|
||||||
signals[ACTION_REQUESTED], 0,
|
signals[ACTION_REQUESTED], 0,
|
||||||
uri + 4);
|
uri + 4);
|
||||||
|
@ -169,8 +166,10 @@ on_resource_request_starting (MuMsgBodyView *self, WebKitWebFrame *frame,
|
||||||
const char* uri;
|
const char* uri;
|
||||||
MuMsg *msg;
|
MuMsg *msg;
|
||||||
|
|
||||||
msg = self->_priv->_message;
|
msg = self->_priv->_msg;
|
||||||
uri = webkit_network_request_get_uri (request);
|
uri = webkit_network_request_get_uri (request);
|
||||||
|
|
||||||
|
/* g_warning ("%s: %s", __FUNCTION__, uri); */
|
||||||
|
|
||||||
if (g_ascii_strncasecmp (uri, "cid:", 4) == 0) {
|
if (g_ascii_strncasecmp (uri, "cid:", 4) == 0) {
|
||||||
gchar *filepath;
|
gchar *filepath;
|
||||||
|
@ -185,10 +184,52 @@ on_resource_request_starting (MuMsgBodyView *self, WebKitWebFrame *frame,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_menu_item_activate (GtkMenuItem *item, MuMsgBodyView *self)
|
||||||
|
{
|
||||||
|
g_signal_emit (G_OBJECT(self),
|
||||||
|
signals[ACTION_REQUESTED], 0,
|
||||||
|
g_object_get_data (G_OBJECT(item), "action"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
popup_menu (MuMsgBodyView *self, guint button, guint32 activate_time)
|
||||||
|
{
|
||||||
|
GtkWidget *menu;
|
||||||
|
int i;
|
||||||
|
struct {
|
||||||
|
const char* title;
|
||||||
|
const char* action;
|
||||||
|
} actions[] = {
|
||||||
|
{ "View source...", "view-source" }
|
||||||
|
};
|
||||||
|
|
||||||
|
menu = gtk_menu_new ();
|
||||||
|
|
||||||
|
for (i = 0; i != G_N_ELEMENTS(actions); ++i) {
|
||||||
|
GtkWidget *item;
|
||||||
|
item = gtk_menu_item_new_with_label(actions[i].title);
|
||||||
|
g_object_set_data (G_OBJECT(item), "action", (gpointer)actions[i].action);
|
||||||
|
g_signal_connect (item, "activate", G_CALLBACK(on_menu_item_activate),
|
||||||
|
self);
|
||||||
|
gtk_menu_attach (GTK_MENU(menu), item, 0, 1, i, i+1);
|
||||||
|
gtk_widget_show (item);
|
||||||
|
}
|
||||||
|
gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
on_button_press_event (MuMsgBodyView *self, GdkEventButton *event, gpointer data)
|
on_button_press_event (MuMsgBodyView *self, GdkEventButton *event, gpointer data)
|
||||||
{
|
{
|
||||||
/* ignore all but the first (typically, left) mouse button */
|
/* ignore all but the first (typically, left) mouse button */
|
||||||
|
switch (event->button) {
|
||||||
|
case 1: return FALSE; /* propagate, let widget handle it */
|
||||||
|
case 3: popup_menu (self, event->button, event->time);
|
||||||
|
default: return TRUE; /* ignore */
|
||||||
|
}
|
||||||
|
|
||||||
return (event->button > 1) ? TRUE : FALSE;
|
return (event->button > 1) ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,8 +239,8 @@ mu_msg_body_view_init (MuMsgBodyView *obj)
|
||||||
{
|
{
|
||||||
obj->_priv = MU_MSG_BODY_VIEW_GET_PRIVATE(obj);
|
obj->_priv = MU_MSG_BODY_VIEW_GET_PRIVATE(obj);
|
||||||
|
|
||||||
obj->_priv->_message = NULL;
|
obj->_priv->_msg = NULL;
|
||||||
obj->_priv->_mu_mode = FALSE;
|
obj->_priv->_internal_msg = FALSE;
|
||||||
|
|
||||||
obj->_priv->_settings = webkit_web_settings_new ();
|
obj->_priv->_settings = webkit_web_settings_new ();
|
||||||
g_object_set (G_OBJECT(obj->_priv->_settings),
|
g_object_set (G_OBJECT(obj->_priv->_settings),
|
||||||
|
@ -218,7 +259,7 @@ mu_msg_body_view_init (MuMsgBodyView *obj)
|
||||||
/* handle navigation requests */
|
/* handle navigation requests */
|
||||||
g_signal_connect (obj, "navigation-policy-decision-requested",
|
g_signal_connect (obj, "navigation-policy-decision-requested",
|
||||||
G_CALLBACK (on_navigation_policy_decision_requested), NULL);
|
G_CALLBACK (on_navigation_policy_decision_requested), NULL);
|
||||||
/* ignore right-button clicks */
|
/* handle right-button clicks */
|
||||||
g_signal_connect (obj, "button-press-event",
|
g_signal_connect (obj, "button-press-event",
|
||||||
G_CALLBACK(on_button_press_event), NULL);
|
G_CALLBACK(on_button_press_event), NULL);
|
||||||
}
|
}
|
||||||
|
@ -232,8 +273,8 @@ mu_msg_body_view_finalize (GObject *obj)
|
||||||
if (priv && priv->_settings)
|
if (priv && priv->_settings)
|
||||||
g_object_unref (priv->_settings);
|
g_object_unref (priv->_settings);
|
||||||
|
|
||||||
if (priv->_message)
|
if (priv->_msg)
|
||||||
mu_msg_unref (priv->_message);
|
mu_msg_unref (priv->_msg);
|
||||||
|
|
||||||
G_OBJECT_CLASS(parent_class)->finalize (obj);
|
G_OBJECT_CLASS(parent_class)->finalize (obj);
|
||||||
}
|
}
|
||||||
|
@ -269,7 +310,6 @@ set_text (MuMsgBodyView *self, const char* txt)
|
||||||
"");
|
"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
mu_msg_body_view_set_message (MuMsgBodyView *self, MuMsg *msg)
|
mu_msg_body_view_set_message (MuMsgBodyView *self, MuMsg *msg)
|
||||||
{
|
{
|
||||||
|
@ -277,35 +317,37 @@ mu_msg_body_view_set_message (MuMsgBodyView *self, MuMsg *msg)
|
||||||
|
|
||||||
g_return_if_fail (self);
|
g_return_if_fail (self);
|
||||||
|
|
||||||
if (self->_priv->_message) {
|
/* ref this one before unreffing priv->_msg, it may be the
|
||||||
mu_msg_unref (self->_priv->_message);
|
* same...*/
|
||||||
self->_priv->_message = NULL;
|
if (msg)
|
||||||
}
|
msg = mu_msg_ref (msg);
|
||||||
|
|
||||||
self->_priv->_message = msg ? mu_msg_ref (msg) : NULL;
|
if (self->_priv->_msg) {
|
||||||
|
mu_msg_unref (self->_priv->_msg);
|
||||||
|
self->_priv->_msg = NULL;
|
||||||
|
}
|
||||||
|
self->_priv->_msg = msg;
|
||||||
|
|
||||||
data = msg ? mu_msg_get_body_html (msg) : "";
|
data = msg ? mu_msg_get_body_html (msg) : "";
|
||||||
if (data)
|
if (data)
|
||||||
set_html (self, data);
|
set_html (self, data);
|
||||||
else
|
else
|
||||||
set_text (self, mu_msg_get_body_text (msg));
|
set_text (self, mu_msg_get_body_text (msg));
|
||||||
|
|
||||||
self->_priv->_mu_mode = FALSE;
|
self->_priv->_internal_msg = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
mu_msg_body_view_set_note (MuMsgBodyView *self, const gchar *html)
|
mu_msg_body_view_set_note (MuMsgBodyView *self, const gchar *html)
|
||||||
{
|
{
|
||||||
g_return_if_fail (self);
|
g_return_if_fail (self);
|
||||||
g_return_if_fail (html);
|
g_return_if_fail (html);
|
||||||
|
|
||||||
if (self->_priv->_message) {
|
if (self->_priv->_msg) {
|
||||||
mu_msg_unref (self->_priv->_message);
|
mu_msg_unref (self->_priv->_msg);
|
||||||
self->_priv->_message = NULL;
|
self->_priv->_msg = NULL;
|
||||||
}
|
}
|
||||||
set_html (self, html);
|
set_html (self, html);
|
||||||
|
|
||||||
self->_priv->_mu_mode = TRUE;
|
self->_priv->_internal_msg = TRUE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ typedef struct _MuMsgBodyView MuMsgBodyView;
|
||||||
typedef struct _MuMsgBodyViewClass MuMsgBodyViewClass;
|
typedef struct _MuMsgBodyViewClass MuMsgBodyViewClass;
|
||||||
typedef struct _MuMsgBodyViewPrivate MuMsgBodyViewPrivate;
|
typedef struct _MuMsgBodyViewPrivate MuMsgBodyViewPrivate;
|
||||||
|
|
||||||
|
|
||||||
struct _MuMsgBodyView {
|
struct _MuMsgBodyView {
|
||||||
WebKitWebView parent;
|
WebKitWebView parent;
|
||||||
/* insert public members, if any */
|
/* insert public members, if any */
|
||||||
|
@ -47,6 +48,8 @@ struct _MuMsgBodyView {
|
||||||
|
|
||||||
struct _MuMsgBodyViewClass {
|
struct _MuMsgBodyViewClass {
|
||||||
WebKitWebViewClass parent_class;
|
WebKitWebViewClass parent_class;
|
||||||
|
|
||||||
|
/* supported actions: "reindex", "view-source" */
|
||||||
void (* action_requested) (MuMsgBodyView* self, const char* action);
|
void (* action_requested) (MuMsgBodyView* self, const char* action);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -177,7 +177,7 @@ mu_msg_header_view_set_message (MuMsgHeaderView *self, MuMsg *msg)
|
||||||
if (msg) {
|
if (msg) {
|
||||||
self->_priv->_table = get_table (msg);
|
self->_priv->_table = get_table (msg);
|
||||||
gtk_box_pack_start (GTK_BOX(self), self->_priv->_table,
|
gtk_box_pack_start (GTK_BOX(self), self->_priv->_table,
|
||||||
FALSE, FALSE, 2);
|
TRUE, TRUE, 0);
|
||||||
gtk_widget_show_all (self->_priv->_table);
|
gtk_widget_show_all (self->_priv->_table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,219 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||||
|
**
|
||||||
|
** 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; either version 3, or (at your option) any
|
||||||
|
** later version.
|
||||||
|
**
|
||||||
|
** 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, write to the Free Software Foundation,
|
||||||
|
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "mu-msg-normal-view.h"
|
||||||
|
|
||||||
|
#include "mu-msg-body-view.h"
|
||||||
|
#include "mu-msg-attach-view.h"
|
||||||
|
#include "mu-msg-header-view.h"
|
||||||
|
#include "mu-msg-part.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* 'private'/'protected' functions */
|
||||||
|
static void mu_msg_normal_view_class_init (MuMsgNormalViewClass *klass);
|
||||||
|
static void mu_msg_normal_view_init (MuMsgNormalView *obj);
|
||||||
|
static void mu_msg_normal_view_finalize (GObject *obj);
|
||||||
|
|
||||||
|
/* list my signals */
|
||||||
|
enum {
|
||||||
|
ACTION_REQUESTED,
|
||||||
|
/* MY_SIGNAL_2, */
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MuMsgNormalViewPrivate {
|
||||||
|
|
||||||
|
GtkWidget *_headers;
|
||||||
|
GtkWidget *_body;
|
||||||
|
GtkWidget *_attach, *_attacharea;
|
||||||
|
};
|
||||||
|
#define MU_MSG_NORMAL_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
|
||||||
|
MU_TYPE_MSG_NORMAL_VIEW, \
|
||||||
|
MuMsgNormalViewPrivate))
|
||||||
|
/* globals */
|
||||||
|
static GtkVBoxClass *parent_class = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
static guint signals[LAST_SIGNAL] = {0};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MuMsgNormalView, mu_msg_normal_view, GTK_TYPE_VBOX);
|
||||||
|
|
||||||
|
static void
|
||||||
|
mu_msg_normal_view_class_init (MuMsgNormalViewClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class;
|
||||||
|
gobject_class = (GObjectClass*) klass;
|
||||||
|
|
||||||
|
parent_class = g_type_class_peek_parent (klass);
|
||||||
|
gobject_class->finalize = mu_msg_normal_view_finalize;
|
||||||
|
|
||||||
|
g_type_class_add_private (gobject_class, sizeof(MuMsgNormalViewPrivate));
|
||||||
|
|
||||||
|
signals[ACTION_REQUESTED] =
|
||||||
|
g_signal_new ("action-requested",
|
||||||
|
G_TYPE_FROM_CLASS (gobject_class),
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
G_STRUCT_OFFSET (MuMsgNormalViewClass,
|
||||||
|
action_requested),
|
||||||
|
NULL, NULL,
|
||||||
|
g_cclosure_marshal_VOID__STRING,
|
||||||
|
G_TYPE_NONE, 1, G_TYPE_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
get_header_widget (MuMsgNormalView *self)
|
||||||
|
{
|
||||||
|
GtkWidget *scrolledwin;
|
||||||
|
|
||||||
|
self->_priv->_headers = mu_msg_header_view_new ();
|
||||||
|
|
||||||
|
scrolledwin = gtk_scrolled_window_new (NULL, NULL);
|
||||||
|
gtk_scrolled_window_set_policy (
|
||||||
|
GTK_SCROLLED_WINDOW(scrolledwin),
|
||||||
|
GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);
|
||||||
|
gtk_scrolled_window_add_with_viewport
|
||||||
|
(GTK_SCROLLED_WINDOW(scrolledwin), self->_priv->_headers);
|
||||||
|
|
||||||
|
gtk_widget_show_all (scrolledwin);
|
||||||
|
|
||||||
|
return scrolledwin;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_body_action_requested (MuMsgBodyView *body, const char* action,
|
||||||
|
MuMsgNormalView *self)
|
||||||
|
{
|
||||||
|
/* forward the signal */
|
||||||
|
g_signal_emit (G_OBJECT(self),
|
||||||
|
signals[ACTION_REQUESTED], 0, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
get_body_widget (MuMsgNormalView *self)
|
||||||
|
{
|
||||||
|
GtkWidget *scrolledwin;
|
||||||
|
|
||||||
|
self->_priv->_body = mu_msg_body_view_new ();
|
||||||
|
|
||||||
|
scrolledwin = gtk_scrolled_window_new (NULL, NULL);
|
||||||
|
gtk_container_add (GTK_CONTAINER(scrolledwin),
|
||||||
|
self->_priv->_body);
|
||||||
|
|
||||||
|
g_signal_connect (self->_priv->_body, "action-requested",
|
||||||
|
G_CALLBACK(on_body_action_requested), self);
|
||||||
|
|
||||||
|
gtk_widget_show_all (scrolledwin);
|
||||||
|
|
||||||
|
return scrolledwin;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_attach_activated (GtkWidget *w, guint partnum, MuMsg *msg)
|
||||||
|
{
|
||||||
|
gchar *filepath;
|
||||||
|
|
||||||
|
filepath = mu_msg_part_filepath_cache (msg, partnum);
|
||||||
|
if (filepath) {
|
||||||
|
mu_msg_part_save (msg, filepath, partnum, FALSE, TRUE);
|
||||||
|
mu_util_play (filepath, TRUE, FALSE);
|
||||||
|
g_free (filepath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
get_attach_widget (MuMsgNormalView *self)
|
||||||
|
{
|
||||||
|
self->_priv->_attacharea = gtk_frame_new ("");
|
||||||
|
self->_priv->_attach = mu_msg_attach_view_new ();
|
||||||
|
gtk_container_add (GTK_CONTAINER(self->_priv->_attacharea),
|
||||||
|
self->_priv->_attach);
|
||||||
|
|
||||||
|
g_signal_connect (self->_priv->_attach, "attach-activated",
|
||||||
|
G_CALLBACK(on_attach_activated),
|
||||||
|
self);
|
||||||
|
|
||||||
|
gtk_widget_show_all (self->_priv->_attacharea);
|
||||||
|
|
||||||
|
return self->_priv->_attacharea;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mu_msg_normal_view_init (MuMsgNormalView *self)
|
||||||
|
{
|
||||||
|
self->_priv = MU_MSG_NORMAL_VIEW_GET_PRIVATE(self);
|
||||||
|
|
||||||
|
gtk_box_pack_start (GTK_BOX(self),get_header_widget (self),
|
||||||
|
FALSE, TRUE, 0);
|
||||||
|
gtk_box_pack_start (GTK_BOX(self), get_attach_widget (self),
|
||||||
|
FALSE, TRUE, 0);
|
||||||
|
gtk_box_pack_start (GTK_BOX(self), get_body_widget (self),
|
||||||
|
TRUE, TRUE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mu_msg_normal_view_finalize (GObject *obj)
|
||||||
|
{
|
||||||
|
/* free/unref instance resources here */
|
||||||
|
G_OBJECT_CLASS(parent_class)->finalize (obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
mu_msg_normal_view_new (void)
|
||||||
|
{
|
||||||
|
return GTK_WIDGET(g_object_new(MU_TYPE_MSG_NORMAL_VIEW, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_attachment_area (MuMsgNormalView *self, MuMsg *msg)
|
||||||
|
{
|
||||||
|
gint attach_num;
|
||||||
|
|
||||||
|
attach_num = 0;
|
||||||
|
if (msg)
|
||||||
|
attach_num = mu_msg_attach_view_set_message
|
||||||
|
(MU_MSG_ATTACH_VIEW(self->_priv->_attach), msg);
|
||||||
|
|
||||||
|
if (attach_num > 0)
|
||||||
|
gtk_widget_show_all (self->_priv->_attacharea);
|
||||||
|
else
|
||||||
|
gtk_widget_hide_all (self->_priv->_attacharea);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mu_msg_normal_view_set_message (MuMsgNormalView *self, MuMsg *msg)
|
||||||
|
{
|
||||||
|
g_return_if_fail (MU_IS_MSG_NORMAL_VIEW(self));
|
||||||
|
|
||||||
|
mu_msg_header_view_set_message
|
||||||
|
(MU_MSG_HEADER_VIEW(self->_priv->_headers), msg);
|
||||||
|
mu_msg_body_view_set_message
|
||||||
|
(MU_MSG_BODY_VIEW(self->_priv->_body), msg);
|
||||||
|
|
||||||
|
update_attachment_area (self, msg);
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||||
|
**
|
||||||
|
** 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; either version 3, or (at your option) any
|
||||||
|
** later version.
|
||||||
|
**
|
||||||
|
** 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, write to the Free Software Foundation,
|
||||||
|
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __MU_MSG_NORMAL_VIEW_H__
|
||||||
|
#define __MU_MSG_NORMAL_VIEW_H__
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <mu-msg.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
/* convenience macros */
|
||||||
|
#define MU_TYPE_MSG_NORMAL_VIEW (mu_msg_normal_view_get_type())
|
||||||
|
#define MU_MSG_NORMAL_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MU_TYPE_MSG_NORMAL_VIEW,MuMsgNormalView))
|
||||||
|
#define MU_MSG_NORMAL_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MU_TYPE_MSG_NORMAL_VIEW,MuMsgNormalViewClass))
|
||||||
|
#define MU_IS_MSG_NORMAL_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MU_TYPE_MSG_NORMAL_VIEW))
|
||||||
|
#define MU_IS_MSG_NORMAL_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MU_TYPE_MSG_NORMAL_VIEW))
|
||||||
|
#define MU_MSG_NORMAL_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MU_TYPE_MSG_NORMAL_VIEW,MuMsgNormalViewClass))
|
||||||
|
|
||||||
|
typedef struct _MuMsgNormalView MuMsgNormalView;
|
||||||
|
typedef struct _MuMsgNormalViewClass MuMsgNormalViewClass;
|
||||||
|
typedef struct _MuMsgNormalViewPrivate MuMsgNormalViewPrivate;
|
||||||
|
|
||||||
|
struct _MuMsgNormalView {
|
||||||
|
GtkVBox parent;
|
||||||
|
/* insert public members, if any */
|
||||||
|
|
||||||
|
/* private */
|
||||||
|
MuMsgNormalViewPrivate *_priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MuMsgNormalViewClass {
|
||||||
|
GtkVBoxClass parent_class;
|
||||||
|
|
||||||
|
/* supported actions: "view-source" */
|
||||||
|
void (* action_requested) (MuMsgNormalView* self, const char* action);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* member functions */
|
||||||
|
GType mu_msg_normal_view_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
|
||||||
|
GtkWidget* mu_msg_normal_view_new (void);
|
||||||
|
void mu_msg_normal_view_set_message (MuMsgNormalView *self,
|
||||||
|
MuMsg *msg);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __MU_MSG_NORMAL_VIEW_H__ */
|
||||||
|
|
|
@ -0,0 +1,174 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||||
|
**
|
||||||
|
** 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; either version 3, or (at your option) any
|
||||||
|
** later version.
|
||||||
|
**
|
||||||
|
** 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, write to the Free Software Foundation,
|
||||||
|
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "mu-msg-source-view.h"
|
||||||
|
/* include other impl specific header files */
|
||||||
|
|
||||||
|
/* 'private'/'protected' functions */
|
||||||
|
static void mu_msg_source_view_class_init (MuMsgSourceViewClass *klass);
|
||||||
|
static void mu_msg_source_view_init (MuMsgSourceView *obj);
|
||||||
|
static void mu_msg_source_view_finalize (GObject *obj);
|
||||||
|
|
||||||
|
/* list my signals */
|
||||||
|
enum {
|
||||||
|
ACTION_REQUESTED,
|
||||||
|
/* MY_SIGNAL_2, */
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MuMsgSourceViewPrivate {
|
||||||
|
GtkWidget *_view;
|
||||||
|
};
|
||||||
|
#define MU_MSG_SOURCE_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
|
||||||
|
MU_TYPE_MSG_SOURCE_VIEW, \
|
||||||
|
MuMsgSourceViewPrivate))
|
||||||
|
/* globals */
|
||||||
|
static GtkVBoxClass *parent_class = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
static guint signals[LAST_SIGNAL] = {0};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MuMsgSourceView, mu_msg_source_view, GTK_TYPE_VBOX);
|
||||||
|
|
||||||
|
static void
|
||||||
|
mu_msg_source_view_class_init (MuMsgSourceViewClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class;
|
||||||
|
gobject_class = (GObjectClass*) klass;
|
||||||
|
|
||||||
|
parent_class = g_type_class_peek_parent (klass);
|
||||||
|
gobject_class->finalize = mu_msg_source_view_finalize;
|
||||||
|
|
||||||
|
g_type_class_add_private (gobject_class, sizeof(MuMsgSourceViewPrivate));
|
||||||
|
|
||||||
|
signals[ACTION_REQUESTED] =
|
||||||
|
g_signal_new ("action-requested",
|
||||||
|
G_TYPE_FROM_CLASS (gobject_class),
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
G_STRUCT_OFFSET (MuMsgSourceViewClass,
|
||||||
|
action_requested),
|
||||||
|
NULL, NULL,
|
||||||
|
g_cclosure_marshal_VOID__STRING,
|
||||||
|
G_TYPE_NONE, 1, G_TYPE_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_menu_item_activate (GtkMenuItem *item, MuMsgSourceView *self)
|
||||||
|
{
|
||||||
|
g_signal_emit (G_OBJECT(self),
|
||||||
|
signals[ACTION_REQUESTED], 0,
|
||||||
|
g_object_get_data (G_OBJECT(item), "action"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
popup_menu (MuMsgSourceView *self, guint button, guint32 activate_time)
|
||||||
|
{
|
||||||
|
GtkWidget *menu;
|
||||||
|
int i;
|
||||||
|
struct {
|
||||||
|
const char* title;
|
||||||
|
const char* action;
|
||||||
|
} actions[] = {
|
||||||
|
{ "View message...", "view-message" }
|
||||||
|
};
|
||||||
|
|
||||||
|
menu = gtk_menu_new ();
|
||||||
|
|
||||||
|
for (i = 0; i != G_N_ELEMENTS(actions); ++i) {
|
||||||
|
GtkWidget *item;
|
||||||
|
item = gtk_menu_item_new_with_label(actions[i].title);
|
||||||
|
g_object_set_data (G_OBJECT(item), "action", (gpointer)actions[i].action);
|
||||||
|
g_signal_connect (item, "activate", G_CALLBACK(on_menu_item_activate),
|
||||||
|
self);
|
||||||
|
gtk_menu_attach (GTK_MENU(menu), item, 0, 1, i, i+1);
|
||||||
|
gtk_widget_show (item);
|
||||||
|
}
|
||||||
|
gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
on_button_press_event (GtkWidget *w, GdkEventButton *event,
|
||||||
|
MuMsgSourceView *self)
|
||||||
|
{
|
||||||
|
/* ignore all but the first (typically, left) mouse button */
|
||||||
|
switch (event->button) {
|
||||||
|
case 1: return FALSE; /* propagate, let widget handle it */
|
||||||
|
case 3: popup_menu (self, event->button, event->time);
|
||||||
|
default: return TRUE; /* ignore */
|
||||||
|
}
|
||||||
|
|
||||||
|
return (event->button > 1) ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
mu_msg_source_view_init (MuMsgSourceView *self)
|
||||||
|
{
|
||||||
|
self->_priv = MU_MSG_SOURCE_VIEW_GET_PRIVATE(self);
|
||||||
|
|
||||||
|
self->_priv->_view = gtk_text_view_new ();
|
||||||
|
|
||||||
|
/* handle right-button clicks */
|
||||||
|
g_signal_connect (self->_priv->_view, "button-press-event",
|
||||||
|
G_CALLBACK(on_button_press_event), self);
|
||||||
|
|
||||||
|
gtk_box_pack_start (GTK_BOX(self), self->_priv->_view,
|
||||||
|
TRUE, TRUE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mu_msg_source_view_finalize (GObject *obj)
|
||||||
|
{
|
||||||
|
/* free/unref instance resources here */
|
||||||
|
G_OBJECT_CLASS(parent_class)->finalize (obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
mu_msg_source_view_new (void)
|
||||||
|
{
|
||||||
|
return GTK_WIDGET(g_object_new(MU_TYPE_MSG_SOURCE_VIEW, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mu_msg_source_view_set_message (MuMsgSourceView *self, MuMsg *msg)
|
||||||
|
{
|
||||||
|
GtkTextBuffer *buf;
|
||||||
|
const gchar *path;
|
||||||
|
gchar *data;
|
||||||
|
|
||||||
|
g_return_if_fail (MU_IS_MSG_SOURCE_VIEW(self));
|
||||||
|
g_return_if_fail (msg);
|
||||||
|
|
||||||
|
buf = gtk_text_view_get_buffer
|
||||||
|
(GTK_TEXT_VIEW(self->_priv->_view));
|
||||||
|
path = msg ? mu_msg_get_path (msg) : NULL;
|
||||||
|
|
||||||
|
if (path && g_file_get_contents (path, &data, NULL, NULL)) {
|
||||||
|
gtk_text_buffer_set_text (buf, data, -1);
|
||||||
|
g_free (data);
|
||||||
|
} else
|
||||||
|
gtk_text_buffer_set_text (buf, "", 0);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||||
|
**
|
||||||
|
** 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; either version 3, or (at your option) any
|
||||||
|
** later version.
|
||||||
|
**
|
||||||
|
** 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, write to the Free Software Foundation,
|
||||||
|
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __MU_MSG_SOURCE_VIEW_H__
|
||||||
|
#define __MU_MSG_SOURCE_VIEW_H__
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <mu-msg.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
/* convenience macros */
|
||||||
|
#define MU_TYPE_MSG_SOURCE_VIEW (mu_msg_source_view_get_type())
|
||||||
|
#define MU_MSG_SOURCE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MU_TYPE_MSG_SOURCE_VIEW,MuMsgSourceView))
|
||||||
|
#define MU_MSG_SOURCE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MU_TYPE_MSG_SOURCE_VIEW,MuMsgSourceViewClass))
|
||||||
|
#define MU_IS_MSG_SOURCE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MU_TYPE_MSG_SOURCE_VIEW))
|
||||||
|
#define MU_IS_MSG_SOURCE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MU_TYPE_MSG_SOURCE_VIEW))
|
||||||
|
#define MU_MSG_SOURCE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MU_TYPE_MSG_SOURCE_VIEW,MuMsgSourceViewClass))
|
||||||
|
|
||||||
|
typedef struct _MuMsgSourceView MuMsgSourceView;
|
||||||
|
typedef struct _MuMsgSourceViewClass MuMsgSourceViewClass;
|
||||||
|
typedef struct _MuMsgSourceViewPrivate MuMsgSourceViewPrivate;
|
||||||
|
|
||||||
|
struct _MuMsgSourceView {
|
||||||
|
GtkVBox parent;
|
||||||
|
/* insert public members, if any */
|
||||||
|
|
||||||
|
/* private */
|
||||||
|
MuMsgSourceViewPrivate *_priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MuMsgSourceViewClass {
|
||||||
|
GtkVBoxClass parent_class;
|
||||||
|
/* insert signal callback declarations, e.g. */
|
||||||
|
/* supported actions: "view-source" */
|
||||||
|
void (* action_requested) (MuMsgSourceView* self, const char* action);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* member functions */
|
||||||
|
GType mu_msg_source_view_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
/* parameter-less _new function (constructor) */
|
||||||
|
/* if this is a kind of GtkWidget, it should probably return at GtkWidget* */
|
||||||
|
GtkWidget* mu_msg_source_view_new (void);
|
||||||
|
void mu_msg_source_view_set_message (MuMsgSourceView *self,
|
||||||
|
MuMsg *msg);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __MU_MSG_SOURCE_VIEW_H__ */
|
||||||
|
|
|
@ -18,9 +18,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mu-msg-view.h"
|
#include "mu-msg-view.h"
|
||||||
#include "mu-msg-body-view.h"
|
|
||||||
#include "mu-msg-attach-view.h"
|
#include "mu-msg-normal-view.h"
|
||||||
#include "mu-msg-header-view.h"
|
#include "mu-msg-source-view.h"
|
||||||
|
|
||||||
#include <mu-msg.h>
|
#include <mu-msg.h>
|
||||||
#include <mu-msg-part.h>
|
#include <mu-msg-part.h>
|
||||||
|
@ -38,9 +38,15 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MuMsgViewPrivate {
|
struct _MuMsgViewPrivate {
|
||||||
GtkWidget *_headers;
|
|
||||||
GtkWidget *_body;
|
/* 'normal' view */
|
||||||
GtkWidget *_attach, *_attacharea;
|
GtkWidget *_normal_view, *_source_view;
|
||||||
|
|
||||||
|
/* TRUE if we're in view-source mode, FALSE otherwise */
|
||||||
|
gboolean _view_source;
|
||||||
|
|
||||||
|
/* the message */
|
||||||
|
MuMsg *_msg;
|
||||||
};
|
};
|
||||||
#define MU_MSG_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
|
#define MU_MSG_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
|
||||||
MU_TYPE_MSG_VIEW, \
|
MU_TYPE_MSG_VIEW, \
|
||||||
|
@ -73,100 +79,120 @@ mu_msg_view_class_init (MuMsgViewClass *klass)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_attach_activated (MuMsgView *self, guint partnum, MuMsg *msg)
|
each_child_remove (GtkWidget *child, MuMsgView *self)
|
||||||
{
|
{
|
||||||
gchar* filepath;
|
gtk_container_remove (GTK_CONTAINER(self), child);
|
||||||
|
}
|
||||||
|
|
||||||
filepath = mu_msg_part_filepath_cache (msg, partnum);
|
|
||||||
if (filepath) {
|
static void
|
||||||
mu_msg_part_save (msg, filepath, partnum, FALSE, TRUE);
|
clear_widgets (MuMsgView *self)
|
||||||
mu_util_play (filepath, TRUE, FALSE);
|
{
|
||||||
g_free (filepath);
|
/* remove the old children */
|
||||||
|
gtk_container_foreach (GTK_CONTAINER(self),
|
||||||
|
(GtkCallback)each_child_remove,
|
||||||
|
self);
|
||||||
|
|
||||||
|
self->_priv->_normal_view = NULL;
|
||||||
|
self->_priv->_source_view = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_body_action_requested (GtkWidget *w, const char* action,
|
||||||
|
MuMsgView *self)
|
||||||
|
{
|
||||||
|
if (g_strcmp0 (action, "view-source") == 0) {
|
||||||
|
|
||||||
|
self->_priv->_view_source = TRUE;
|
||||||
|
if (self->_priv->_msg)
|
||||||
|
mu_msg_ref (self->_priv->_msg);
|
||||||
|
mu_msg_view_set_message (self, self->_priv->_msg);
|
||||||
|
|
||||||
|
} else if (g_strcmp0 (action, "view-message") == 0) {
|
||||||
|
|
||||||
|
self->_priv->_view_source = FALSE;
|
||||||
|
if (self->_priv->_msg)
|
||||||
|
mu_msg_ref (self->_priv->_msg);
|
||||||
|
mu_msg_view_set_message (self, self->_priv->_msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static GtkWidget*
|
|
||||||
get_header_widget (MuMsgView *self)
|
|
||||||
{
|
|
||||||
GtkWidget *scrolledwin;
|
|
||||||
|
|
||||||
self->_priv->_headers = mu_msg_header_view_new ();
|
static GtkWidget*
|
||||||
|
get_source_view (MuMsgView *self, MuMsg *msg)
|
||||||
|
{
|
||||||
|
if (!self->_priv->_source_view) {
|
||||||
|
self->_priv->_source_view = mu_msg_source_view_new ();
|
||||||
|
g_signal_connect (self->_priv->_source_view,
|
||||||
|
"action-requested",
|
||||||
|
G_CALLBACK(on_body_action_requested),
|
||||||
|
self);
|
||||||
|
}
|
||||||
|
|
||||||
|
mu_msg_source_view_set_message
|
||||||
|
(MU_MSG_SOURCE_VIEW (self->_priv->_source_view), msg);
|
||||||
|
|
||||||
|
gtk_widget_show_all (self->_priv->_source_view);
|
||||||
|
|
||||||
|
return self->_priv->_source_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
get_normal_view (MuMsgView *self, MuMsg *msg)
|
||||||
|
{
|
||||||
|
GtkWidget *scrolledwin;
|
||||||
|
|
||||||
|
if (!self->_priv->_normal_view) {
|
||||||
|
self->_priv->_normal_view = mu_msg_normal_view_new ();
|
||||||
|
g_signal_connect (self->_priv->_normal_view,
|
||||||
|
"action-requested",
|
||||||
|
G_CALLBACK(on_body_action_requested),
|
||||||
|
self);
|
||||||
|
}
|
||||||
|
|
||||||
|
mu_msg_normal_view_set_message
|
||||||
|
(MU_MSG_NORMAL_VIEW(self->_priv->_normal_view), msg);
|
||||||
|
|
||||||
|
gtk_widget_show (self->_priv->_normal_view);
|
||||||
|
|
||||||
scrolledwin = gtk_scrolled_window_new (NULL, NULL);
|
scrolledwin = gtk_scrolled_window_new (NULL, NULL);
|
||||||
gtk_scrolled_window_set_policy (
|
gtk_scrolled_window_set_policy (
|
||||||
GTK_SCROLLED_WINDOW(scrolledwin),
|
GTK_SCROLLED_WINDOW(scrolledwin),
|
||||||
GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);
|
GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);
|
||||||
|
|
||||||
gtk_scrolled_window_add_with_viewport
|
gtk_scrolled_window_add_with_viewport
|
||||||
(GTK_SCROLLED_WINDOW(scrolledwin), self->_priv->_headers);
|
(GTK_SCROLLED_WINDOW(scrolledwin),
|
||||||
|
self->_priv->_normal_view);
|
||||||
|
|
||||||
|
gtk_widget_show_all (scrolledwin);
|
||||||
|
|
||||||
return scrolledwin;
|
return scrolledwin;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
on_body_action_requested (MuMsgBodyView *body, const char* action,
|
|
||||||
MuMsgView *self)
|
|
||||||
{
|
|
||||||
g_printerr ("received request: %s\n", action);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static GtkWidget*
|
|
||||||
get_body_widget (MuMsgView *self)
|
|
||||||
{
|
|
||||||
GtkWidget *scrolledwin;
|
|
||||||
|
|
||||||
self->_priv->_body = mu_msg_body_view_new ();
|
|
||||||
scrolledwin = gtk_scrolled_window_new (NULL, NULL);
|
|
||||||
gtk_container_add (GTK_CONTAINER(scrolledwin),
|
|
||||||
self->_priv->_body);
|
|
||||||
|
|
||||||
g_signal_connect (self->_priv->_body, "action-requested",
|
|
||||||
G_CALLBACK(on_body_action_requested), self);
|
|
||||||
|
|
||||||
return scrolledwin;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GtkWidget*
|
|
||||||
get_attach_widget (MuMsgView *self)
|
|
||||||
{
|
|
||||||
/* GtkWidget *scrolledwin; */
|
|
||||||
|
|
||||||
self->_priv->_attacharea = gtk_frame_new ("");
|
|
||||||
/* scrolledwin = gtk_scrolled_window_new (NULL, NULL); */
|
|
||||||
/* gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrolledwin), */
|
|
||||||
/* GTK_POLICY_NEVER, */
|
|
||||||
/* GTK_POLICY_AUTOMATIC); */
|
|
||||||
|
|
||||||
self->_priv->_attach = mu_msg_attach_view_new ();
|
|
||||||
gtk_container_add (GTK_CONTAINER(self->_priv->_attacharea),
|
|
||||||
self->_priv->_attach);
|
|
||||||
|
|
||||||
g_signal_connect (self->_priv->_attach, "attach-activated",
|
|
||||||
G_CALLBACK(on_attach_activated),
|
|
||||||
self);
|
|
||||||
|
|
||||||
return self->_priv->_attacharea;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mu_msg_view_init (MuMsgView *self)
|
mu_msg_view_init (MuMsgView *self)
|
||||||
{
|
{
|
||||||
self->_priv = MU_MSG_VIEW_GET_PRIVATE(self);
|
self->_priv = MU_MSG_VIEW_GET_PRIVATE(self);
|
||||||
|
|
||||||
gtk_box_pack_start (GTK_BOX(self), get_header_widget (self),
|
|
||||||
FALSE, FALSE, 2);
|
|
||||||
|
|
||||||
gtk_box_pack_start (GTK_BOX(self), get_attach_widget (self),
|
self->_priv->_normal_view = NULL;
|
||||||
FALSE, FALSE, 2);
|
self->_priv->_source_view = NULL;
|
||||||
|
|
||||||
gtk_box_pack_start (GTK_BOX(self), get_body_widget (self),
|
self->_priv->_view_source = FALSE;
|
||||||
TRUE, TRUE, 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mu_msg_view_finalize (GObject *obj)
|
mu_msg_view_finalize (GObject *obj)
|
||||||
{
|
{
|
||||||
|
MuMsgViewPrivate *priv;
|
||||||
|
|
||||||
|
priv = MU_MSG_VIEW_GET_PRIVATE(obj);
|
||||||
|
|
||||||
|
if (priv->_msg)
|
||||||
|
mu_msg_unref (priv->_msg);
|
||||||
|
|
||||||
/* free/unref instance resources here */
|
/* free/unref instance resources here */
|
||||||
G_OBJECT_CLASS(parent_class)->finalize (obj);
|
G_OBJECT_CLASS(parent_class)->finalize (obj);
|
||||||
}
|
}
|
||||||
|
@ -178,45 +204,34 @@ mu_msg_view_new (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
update_attachment_area (MuMsgView *self, MuMsg *msg)
|
|
||||||
{
|
|
||||||
gint attach_num;
|
|
||||||
|
|
||||||
attach_num = 0;
|
|
||||||
if (msg)
|
|
||||||
attach_num = mu_msg_attach_view_set_message
|
|
||||||
(MU_MSG_ATTACH_VIEW(self->_priv->_attach), msg);
|
|
||||||
|
|
||||||
if (attach_num > 0)
|
|
||||||
gtk_widget_show_all (self->_priv->_attacharea);
|
|
||||||
else
|
|
||||||
gtk_widget_hide_all (self->_priv->_attacharea);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
mu_msg_view_set_message (MuMsgView *self, MuMsg *msg)
|
mu_msg_view_set_message (MuMsgView *self, MuMsg *msg)
|
||||||
{
|
{
|
||||||
g_return_if_fail (MU_IS_MSG_VIEW(self));
|
g_return_if_fail (MU_IS_MSG_VIEW(self));
|
||||||
|
|
||||||
mu_msg_header_view_set_message (MU_MSG_HEADER_VIEW(self->_priv->_headers),
|
|
||||||
msg);
|
|
||||||
mu_msg_body_view_set_message (MU_MSG_BODY_VIEW(self->_priv->_body),
|
|
||||||
msg);
|
|
||||||
|
|
||||||
update_attachment_area (self, msg);
|
if (self->_priv->_msg)
|
||||||
}
|
mu_msg_unref (self->_priv->_msg);
|
||||||
|
|
||||||
|
self->_priv->_msg = msg ? mu_msg_ref (msg) : NULL;
|
||||||
|
|
||||||
|
clear_widgets (self);
|
||||||
|
|
||||||
|
if (!self->_priv->_view_source)
|
||||||
|
gtk_box_pack_start (GTK_BOX(self),
|
||||||
|
get_normal_view (self, msg),
|
||||||
|
TRUE, TRUE, 0);
|
||||||
|
else
|
||||||
|
gtk_box_pack_start (GTK_BOX(self),
|
||||||
|
get_source_view (self, msg),
|
||||||
|
TRUE, TRUE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
mu_msg_view_set_note (MuMsgView *self, const char *html)
|
mu_msg_view_set_note (MuMsgView *self, const char *html)
|
||||||
{
|
{
|
||||||
g_return_if_fail (MU_IS_MSG_VIEW(self));
|
g_return_if_fail (MU_IS_MSG_VIEW(self));
|
||||||
|
/* FIXME */
|
||||||
mu_msg_header_view_set_message (MU_MSG_HEADER_VIEW(self->_priv->_headers),
|
|
||||||
NULL);
|
|
||||||
mu_msg_body_view_set_note (MU_MSG_BODY_VIEW(self->_priv->_body),
|
|
||||||
html);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,8 @@ GtkWidget* mu_msg_view_new (void);
|
||||||
|
|
||||||
void mu_msg_view_set_message (MuMsgView *self, MuMsg *msg);
|
void mu_msg_view_set_message (MuMsgView *self, MuMsg *msg);
|
||||||
void mu_msg_view_set_note (MuMsgView *self, const char *html);
|
void mu_msg_view_set_note (MuMsgView *self, const char *html);
|
||||||
|
typedef enum _MuMsgViewDisplayType MuMsgViewDisplayType;
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue