Implementing your own mime part viewer

About

This example shows how to from-scratch implement your own mime part viewer. You will need to do this if you want your application software to support displaying less typical MIME parts. The typical ones being text/plain, text/html and mime parts that are actually attachments and therefore don't necessarily need an embedded viewer. When porting to a non Gtk+ platform you will also have to implement replacements for the default components, of course.

When using Gtk+, you can of course start with inheriting an existing one like the TnyGtkTextMimePartView. You should also take a look at Implementing your own message view. Especially at the tny_msg_view_create_mime_part_view_for API which you will have to implement by letting it return the implementation of this type, in case it's about the mime part type which you are indeed targetting.

Implementing a new one (tny-my-mime-part-view.c)

Note that the file is split up in parts that you can typically copy-paste and search-n-replace and parts that you must implement.

You will usually inherit or decorate the ui component that can display your content. For example for a text/html mime part you will most likely inherit a HTML component like GtkMozEmbed (Gecko or the firefox HTML component) or GtkHTML. For a text/plain mime part you can for example inherit or decorate GtkTextView. For a fancy never-ever-seen-before mime part content type, you might want to implement the viewer from scratch.

copy-n-paste, search-n-replace

 
#include <config.h>
#include <glib/gi18n-lib.h>

#include <tny-my-mime-part-view.h>

static GObjectClass *parent_class = NULL;

typedef struct _TnyMyMimePartViewPriv TnyMyMimePartViewPriv;

struct _TnyMyMimePartViewPriv
{
	TnyMimePart *part;
};

#define TNY_MY_MIME_PART_VIEW_GET_PRIVATE(o) \
	(G_TYPE_INSTANCE_GET_PRIVATE ((o), TNY_TYPE_MY_MIME_PART_VIEW, TnyMyMimePartViewPriv))


static TnyMimePart*
tny_my_mime_part_view_get_part (TnyMimePartView *self)
{
	TnyMyMimePartViewPriv *priv = TNY_MY_MIME_PART_VIEW_GET_PRIVATE (self);
	return (priv->part)?TNY_MIME_PART (g_object_ref (priv->part)):NULL;
}

tny_my_mime_part_view_set_part

static void 
tny_my_mime_part_view_set_part (TnyMimePartView *self, TnyMimePart *part)
{
	TnyMyMimePartViewPriv *priv = TNY_MY_MIME_PART_VIEW_GET_PRIVATE (self);

	if (priv->part)
		g_object_unref (G_OBJECT (priv->part));

	if (part)
	{

		/* Write part to your component (usually using the TnyStream 
		 * API and tny_mime_part_decode_to_stream of TnyMimePart) */

		g_object_ref (G_OBJECT (part));
		priv->part = part;
	}

	return;
}

tny_my_mime_part_view_clear

static void
tny_my_mime_part_view_clear (TnyMimePartView *self)
{
	return;
}

tny_my_mime_part_view_new

/**
 * tny_my_mime_part_view_new:
 *
 * Return value: a new #TnyMimePartView instance
 **/
TnyMimePartView*
tny_my_mime_part_view_new (void)
{
	TnyMyMimePartView *self = g_object_new (TNY_TYPE_MY_MIME_PART_VIEW, NULL);

	return TNY_MIME_PART_VIEW (self);
}

copy-n-paste, search-n-replace

static void
tny_my_mime_part_view_instance_init (GTypeInstance *instance, gpointer g_class)
{
	TnyMyMimePartView *self  = (TnyMyMimePartView*) instance;
	TnyMyMimePartViewPriv *priv = TNY_MY_MIME_PART_VIEW_GET_PRIVATE (self);
	priv->part = NULL;
	return;
}

static void
tny_my_mime_part_view_finalize (GObject *object)
{
	TnyMyMimePartView *self = (TnyMyMimePartView *)object;	
	TnyMyMimePartViewPriv *priv = TNY_MY_MIME_PART_VIEW_GET_PRIVATE (self);
	if (G_LIKELY (priv->part))
		g_object_unref (G_OBJECT (priv->part));
	(*parent_class->finalize) (object);
	return;
}

static void
tny_mime_part_view_init (gpointer g, gpointer iface_data)
{
	TnyMimePartViewIface *klass = (TnyMimePartViewIface *)g;

	klass->get_part_func = tny_my_mime_part_view_get_part;
	klass->set_part_func = tny_my_mime_part_view_set_part;
	klass->clear_func = tny_my_mime_part_view_clear;

	return;
}

static void 
tny_my_mime_part_view_class_init (TnyMyMimePartViewClass *class)
{
	GObjectClass *object_class;
	parent_class = g_type_class_peek_parent (class);
	object_class = (GObjectClass*) class;
	object_class->finalize = tny_my_mime_part_view_finalize;
	g_type_class_add_private (object_class, sizeof (TnyMyMimePartViewPriv));
	return;
}

GType 
tny_my_mime_part_view_get_type (void)
{
	static GType type = 0;

	if (G_UNLIKELY(type == 0))
	{
		static const GTypeInfo info = 
		{
		  sizeof (TnyMyMimePartViewClass),
		  NULL,   /* base_init */
		  NULL,   /* base_finalize */
		  (GClassInitFunc) tny_my_mime_part_view_class_init,
		  NULL,   /* class_finalize */
		  NULL,   /* class_data */
		  sizeof (TnyMyMimePartView),
		  0,      /* n_preallocs */
		  tny_my_mime_part_view_instance_init,
		  NULL
		};

		static const GInterfaceInfo tny_mime_part_view_info = 
		{
		  (GInterfaceInitFunc) tny_mime_part_view_init,
		  NULL,         /* interface_finalize */
		  NULL          /* interface_data */
		};

		type = g_type_register_static (GTK_TYPE_BOX,
			"TnyMyMimePartView",
			&info, 0);

		g_type_add_interface_static (type, TNY_TYPE_MIME_PART_VIEW, 
			&tny_mime_part_view_info);
	}

	return type;
}

The public .h file (tny-my-mime-part-view.h)

#ifndef TNY_MY_MIME_PART_VIEW_H
#define TNY_MY_MIME_PART_VIEW_H

/* Your copyright here */

#include <gtk/gtk.h>
#include <glib-object.h>
#include <tny-shared.h>

#include <tny-mime-part-view.h>
#include <tny-stream.h>
#include <tny-mime-part.h>

G_BEGIN_DECLS

#define TNY_TYPE_MY_MIME_PART_VIEW \
	(tny_my_mime_part_view_get_type ())
#define TNY_MY_MIME_PART_VIEW(obj) \
	(G_TYPE_CHECK_INSTANCE_CAST ((obj), TNY_TYPE_MY_MIME_PART_VIEW, TnyMyMimePartView))
#define TNY_MY_MIME_PART_VIEW_CLASS(vtable) \
	(G_TYPE_CHECK_CLASS_CAST ((vtable), TNY_TYPE_MY_MIME_PART_VIEW, TnyMyMimePartViewClass))
#define TNY_IS_MY_MIME_PART_VIEW(obj) \
	(G_TYPE_CHECK_INSTANCE_TYPE ((obj), TNY_TYPE_MY_MIME_PART_VIEW))
#define TNY_IS_MY_MIME_PART_VIEW_CLASS(vtable) \
	(G_TYPE_CHECK_CLASS_TYPE ((vtable), TNY_TYPE_MY_MIME_PART_VIEW))
#define TNY_MY_MIME_PART_VIEW_GET_CLASS(inst) \
	(G_TYPE_INSTANCE_GET_CLASS ((inst), TNY_TYPE_MY_MIME_PART_VIEW, TnyMyMimePartViewClass))

typedef struct _TnyMyMimePartView TnyMyMimePartView;
typedef struct _TnyMyMimePartViewClass TnyMyMimePartViewClass;

struct _TnyMyMimePartView
{
	GtkBox parent;

};

struct _TnyMyMimePartViewClass
{
	GtkBoxClass parent_class;
};

GType tny_my_mime_part_view_get_type (void);
TnyMimePartView* tny_my_mime_part_view_new (void);

G_END_DECLS

#endif

References to related other documentation

TODO for this documentation document

  • Linking API with the online API documentation