* big cleanup, simplification for the message widget

This commit is contained in:
Dirk-Jan C. Binnema 2011-03-08 00:50:24 +02:00
parent f8fd420215
commit 858dcb123c
9 changed files with 157 additions and 703 deletions

View File

@ -39,10 +39,6 @@ libmuwidgets_la_SOURCES= \
mu-msg-body-view.h \
mu-msg-header-view.c \
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.c

View File

@ -20,11 +20,17 @@
#include <webkit/webkitnetworkresponse.h>
#include <webkit/webkitwebnavigationaction.h>
#include <webkit/webkitwebpolicydecision.h>
#include "mu-msg-body-view.h"
#include <mu-msg-part.h>
enum _ViewMode {
VIEW_MODE_MSG,
VIEW_MODE_SOURCE,
VIEW_MODE_NOTE,
VIEW_MODE_NONE
};
typedef enum _ViewMode ViewMode;
/* 'private'/'protected' functions */
static void mu_msg_body_view_class_init (MuMsgBodyViewClass *klass);
@ -42,7 +48,7 @@ enum {
struct _MuMsgBodyViewPrivate {
WebKitWebSettings *_settings;
MuMsg *_msg;
gboolean _internal_msg;
ViewMode _view_mode;
};
#define MU_MSG_BODY_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
MU_TYPE_MSG_BODY_VIEW, \
@ -138,7 +144,7 @@ on_navigation_policy_decision_requested (MuMsgBodyView *self, WebKitWebFrame *fr
* a <a href="cmd:refresh">Refresh</a> link
*/
if (g_ascii_strncasecmp (uri, "cmd:", 4) == 0) {
if (self->_priv->_internal_msg) {
if (self->_priv->_view_mode == VIEW_MODE_NOTE) {
g_signal_emit (G_OBJECT(self),
signals[ACTION_REQUESTED], 0,
uri + 4);
@ -199,14 +205,20 @@ popup_menu (MuMsgBodyView *self, guint button, guint32 activate_time)
struct {
const char* title;
const char* action;
ViewMode mode;
} actions[] = {
{ "View source...", "view-source" }
{ "View source...", "view-source", VIEW_MODE_MSG },
{ "View message...", "view-message", VIEW_MODE_SOURCE },
};
menu = gtk_menu_new ();
for (i = 0; i != G_N_ELEMENTS(actions); ++i) {
GtkWidget *item;
if (self->_priv->_view_mode != actions[i].mode)
continue;
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),
@ -225,8 +237,8 @@ on_button_press_event (MuMsgBodyView *self, GdkEventButton *event, gpointer data
switch (event->button) {
case 1: return FALSE; /* propagate, let widget handle it */
case 3:
/* no popup menus for internal messages */
if (!self->_priv->_internal_msg)
/* no popup menus for notes */
if (self->_priv->_view_mode != VIEW_MODE_NOTE)
popup_menu (self, event->button, event->time);
break;
default: return TRUE; /* ignore */
@ -242,7 +254,7 @@ mu_msg_body_view_init (MuMsgBodyView *obj)
obj->_priv = MU_MSG_BODY_VIEW_GET_PRIVATE(obj);
obj->_priv->_msg = NULL;
obj->_priv->_internal_msg = FALSE;
obj->_priv->_view_mode = VIEW_MODE_NONE;
obj->_priv->_settings = webkit_web_settings_new ();
g_object_set (G_OBJECT(obj->_priv->_settings),
@ -336,9 +348,32 @@ mu_msg_body_view_set_message (MuMsgBodyView *self, MuMsg *msg)
else
set_text (self, mu_msg_get_body_text (msg));
self->_priv->_internal_msg = FALSE;
self->_priv->_view_mode = VIEW_MODE_MSG;
}
void
mu_msg_body_view_set_message_source (MuMsgBodyView *self, MuMsg *msg)
{
const gchar *path;
gchar *data;
g_return_if_fail (MU_IS_MSG_BODY_VIEW(self));
g_return_if_fail (msg);
path = msg ? mu_msg_get_path (msg) : NULL;
if (path && g_file_get_contents (path, &data, NULL, NULL)) {
set_text (self, data);
g_free (data);
} else
set_text (self, "");
self->_priv->_view_mode = VIEW_MODE_SOURCE;
}
void
mu_msg_body_view_set_note (MuMsgBodyView *self, const gchar *html)
{
@ -351,5 +386,5 @@ mu_msg_body_view_set_note (MuMsgBodyView *self, const gchar *html)
}
set_html (self, html);
self->_priv->_internal_msg = TRUE;
self->_priv->_view_mode = VIEW_MODE_NOTE;
}

View File

@ -62,6 +62,7 @@ GtkWidget* mu_msg_body_view_new (void);
void mu_msg_body_view_set_message (MuMsgBodyView *self, MuMsg *msg);
void mu_msg_body_view_set_note (MuMsgBodyView *self, const gchar *html);
void mu_msg_body_view_set_message_source (MuMsgBodyView *self, MuMsg *msg);
G_END_DECLS

View File

@ -1,220 +0,0 @@
/*
** 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_NEVER);
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)
{
self->_priv->_body = mu_msg_body_view_new ();
g_signal_connect (self->_priv->_body, "action-requested",
G_CALLBACK(on_body_action_requested), self);
gtk_widget_show (self->_priv->_body);
return self->_priv->_body;
}
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->_attach = mu_msg_attach_view_new ();
self->_priv->_attacharea = gtk_expander_new_with_mnemonic
("_Attachments");
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
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),
TRUE, FALSE, 0);
gtk_box_pack_start (GTK_BOX(self), get_attach_widget (self),
FALSE, FALSE, 1);
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)
{
GtkExpander *exp;
gint attach_num;
gchar *label;
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_hide_all (self->_priv->_attacharea);
return;
}
exp = GTK_EXPANDER(self->_priv->_attacharea);
gtk_expander_set_use_markup (exp,TRUE);
label = g_strdup_printf ("<b>_Attachments (%d)</b>", attach_num);
gtk_expander_set_label (exp, label);
g_free (label);
gtk_expander_set_expanded (exp, FALSE);
gtk_widget_show_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);
}

View File

@ -1,67 +0,0 @@
/*
** 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__ */

View File

@ -1,179 +0,0 @@
/*
** 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 ();
gtk_text_view_set_editable (GTK_TEXT_VIEW(self->_priv->_view),
FALSE);
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW(self->_priv->_view),
GTK_WRAP_NONE);
/* 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);
}

View File

@ -1,68 +0,0 @@
/*
** 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__ */

View File

@ -18,15 +18,10 @@
*/
#include "mu-msg-view.h"
#include "mu-msg-normal-view.h"
#include "mu-msg-body-view.h"
#include "mu-msg-source-view.h"
#include <webkit/webkitwebview.h>
#include <mu-msg.h>
#include <mu-msg-part.h>
#include "mu-msg-header-view.h"
#include "mu-msg-attach-view.h"
#include "mu-msg-part.h"
/* 'private'/'protected' functions */
static void mu_msg_view_class_init (MuMsgViewClass *klass);
@ -41,14 +36,7 @@ enum {
};
struct _MuMsgViewPrivate {
/* 'normal' view */
GtkWidget *_normal_view, *_source_view, *_internal_view;
/* TRUE if we're in view-source mode, FALSE otherwise */
gboolean _view_source;
/* the message */
GtkWidget *_headers, *_attach, *_attachexpander, *_body;
MuMsg *_msg;
};
#define MU_MSG_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
@ -81,48 +69,19 @@ mu_msg_view_class_init (MuMsgViewClass *klass)
/* etc. */
}
static void
each_child_remove (GtkWidget *child, MuMsgView *self)
{
/* g_object_ref (child); /\* save the children *\/ */
gtk_container_remove (GTK_CONTAINER(self), child);
}
static void
remove_widgets (MuMsgView *self)
{
/* FIXME: keep the widgets around for re-use */
/* 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;
self->_priv->_internal_view = NULL;
}
static void
on_action_requested (GtkWidget *w, const char* action,
MuMsgView *self)
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);
mu_msg_view_set_message_source (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);
mu_msg_view_set_message (self, self->_priv->_msg);
} else if (g_strcmp0 (action, "reindex") == 0) {
g_warning ("reindex");
} else {
@ -130,106 +89,53 @@ on_action_requested (GtkWidget *w, const char* action,
}
}
static GtkWidget*
get_source_view (MuMsgView *self, MuMsg *msg)
static void
on_attach_activated (GtkWidget *w, guint partnum, 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_action_requested),
self);
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);
}
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) {
mu_msg_normal_view_set_message
(MU_MSG_NORMAL_VIEW(self->_priv->_normal_view), msg);
return gtk_widget_get_parent (self->_priv->_normal_view);
}
self->_priv->_normal_view = mu_msg_normal_view_new ();
mu_msg_normal_view_set_message
(MU_MSG_NORMAL_VIEW(self->_priv->_normal_view), msg);
g_signal_connect (self->_priv->_normal_view,
"action-requested",
G_CALLBACK(on_action_requested),
self);
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->_normal_view);
gtk_widget_show (self->_priv->_normal_view);
gtk_widget_show (scrolledwin);
return scrolledwin;
}
static GtkWidget*
get_internal_view (MuMsgView *self, const char *html)
{
if (!self->_priv->_internal_view) {
self->_priv->_internal_view = mu_msg_body_view_new();
g_signal_connect (self->_priv->_internal_view,
"action-requested",
G_CALLBACK(on_action_requested),
self);
}
mu_msg_body_view_set_note (MU_MSG_BODY_VIEW(self->_priv->_internal_view),
html);
gtk_widget_show (self->_priv->_internal_view);
return self->_priv->_internal_view;
}
static void
mu_msg_view_init (MuMsgView *self)
{
self->_priv = MU_MSG_VIEW_GET_PRIVATE(self);
self->_priv = MU_MSG_VIEW_GET_PRIVATE(self);
self->_priv->_normal_view = NULL;
self->_priv->_source_view = NULL;
self->_priv->_internal_view = NULL;
self->_priv->_headers = mu_msg_header_view_new ();
self->_priv->_attach = mu_msg_attach_view_new ();
self->_priv->_attachexpander = gtk_expander_new_with_mnemonic
("_Attachments");
gtk_container_add (GTK_CONTAINER(self->_priv->_attachexpander),
self->_priv->_attach);
g_signal_connect (self->_priv->_attach, "attach-activated",
G_CALLBACK(on_attach_activated),
self);
self->_priv->_view_source = FALSE;
self->_priv->_body = mu_msg_body_view_new ();
g_signal_connect (self->_priv->_body,
"action-requested",
G_CALLBACK(on_body_action_requested),
self);
gtk_box_pack_start (GTK_BOX(self), self->_priv->_headers,
FALSE, FALSE, 2);
gtk_box_pack_start (GTK_BOX(self), self->_priv->_attachexpander,
FALSE, FALSE, 2);
gtk_box_pack_start (GTK_BOX(self), self->_priv->_body,
TRUE, TRUE, 2);
}
static void
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 */
G_OBJECT_CLASS(parent_class)->finalize (obj);
}
@ -241,9 +147,63 @@ mu_msg_view_new (void)
}
struct _ChildData {
GtkWidget *child;
gboolean show;
};
typedef struct _ChildData ChildData;
static void
each_child_visibility (GtkWidget *child, ChildData *cdata)
{
if (child == cdata->child)
gtk_widget_set_visible (child, cdata->show);
}
static void
set_visibility (MuMsgView *self, GtkWidget *w, gboolean show)
{
ChildData cdata;
cdata.child = w;
cdata.show = show;
gtk_container_foreach (GTK_CONTAINER(self),
(GtkCallback)each_child_visibility,
&cdata);
}
void
mu_msg_view_set_message (MuMsgView *self, MuMsg *msg)
{
gint attachnum;
g_return_if_fail (MU_IS_MSG_VIEW(self));
if (self->_priv->_msg)
mu_msg_unref (self->_priv->_msg);
self->_priv->_msg = msg ? mu_msg_ref (msg) : NULL;
mu_msg_header_view_set_message (MU_MSG_HEADER_VIEW(self->_priv->_headers),
msg);
attachnum = mu_msg_attach_view_set_message (MU_MSG_ATTACH_VIEW(self->_priv->_attach),
msg);
mu_msg_body_view_set_message (MU_MSG_BODY_VIEW(self->_priv->_body),
msg);
set_visibility (self, self->_priv->_headers, TRUE);
set_visibility (self, self->_priv->_attachexpander, attachnum > 0);
set_visibility (self, self->_priv->_body, TRUE);
}
void
mu_msg_view_set_message_source (MuMsgView *self, MuMsg *msg)
{
g_return_if_fail (MU_IS_MSG_VIEW(self));
@ -252,31 +212,26 @@ mu_msg_view_set_message (MuMsgView *self, MuMsg *msg)
self->_priv->_msg = msg ? mu_msg_ref (msg) : NULL;
remove_widgets (self);
if (!msg)
return;
mu_msg_body_view_set_message_source (MU_MSG_BODY_VIEW(self->_priv->_body),
msg);
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);
set_visibility (self, self->_priv->_headers, FALSE);
set_visibility (self, self->_priv->_attachexpander, FALSE);
set_visibility (self, self->_priv->_body, TRUE);
}
void
mu_msg_view_set_note (MuMsgView *self, const gchar* html)
{
g_return_if_fail (MU_IS_MSG_VIEW(self));
remove_widgets (self);
gtk_box_pack_start (GTK_BOX(self),
get_internal_view (self, html),
TRUE, TRUE, 0);
set_visibility (self, self->_priv->_headers, FALSE);
set_visibility (self, self->_priv->_attachexpander, FALSE);
set_visibility (self, self->_priv->_body, TRUE);
mu_msg_body_view_set_note (MU_MSG_BODY_VIEW(self->_priv->_body),
html);
}

View File

@ -59,7 +59,8 @@ GType mu_msg_view_get_type (void) G_GNUC_CONST;
GtkWidget* mu_msg_view_new (void);
void mu_msg_view_set_message (MuMsgView *self, MuMsg *msg);
void mu_msg_view_set_note (MuMsgView *self, const char *markup);
void mu_msg_view_set_note (MuMsgView *self, const gchar* html);
void mu_msg_view_set_message_source (MuMsgView *self, MuMsg *msg);
G_END_DECLS