** Fixes bug #495123
2007-11-27 Matthew Barnes <mbarnes@redhat.com> ** Fixes bug #495123 * composer/Makefile.am: Add a bunch of files for managing composer headers. * composer/e-msg-composer.c (build_message), (from_changed_cb), (set_editor_signature), (e_msg_composer_set_body), (e_msg_composer_get_preferred_account): * plugins/exchange-operations/exchange-mail-send-options.c (append_to_header): Use e_msg_composer_hdrs_get_from_account() to obtain the EAccount. * composer/e-msg-composer-hdrs.c: * composer/e-msg-composer-hdrs.h: Massive refactoring to use new EComposerHeader classes. * composer/e-composer-header.c: * composer/e-composer-header.h: * composer/e-composer-from-header.c: * composer/e-composer-from-header.h: * composer/e-composer-name-header.c: * composer/e-composer-name-header.h: * composer/e-composer-post-header.c: * composer/e-composer-post-header.h: * composer/e-composer-text-header.c: * composer/e-composer-text-header.h: New GObject classes manage different types of composer headers. See bug #495123 for a more detailed description of each class. * mail/mail-session.c (mail_session_init): Pass the CamelSession to the EAccountComboBox class (ugly hack). * widgets/misc/Makefile.am: Add e-account-combo-box.[ch]. * widgets/misc/e-account-combo-box.c: * widgets/misc/e-account-combo-box.h: New widget renders an EAccountList as a combo box. Also listens for changes to the EAccountList and updates itself accordingly. svn path=/trunk/; revision=34600
This commit is contained in:
committed by
Matthew Barnes
parent
8aa60af54e
commit
f5bed9bf7b
@ -1,3 +1,32 @@
|
||||
2007-11-27 Matthew Barnes <mbarnes@redhat.com>
|
||||
|
||||
** Fixes part of bug #495123
|
||||
|
||||
* Makefile.am:
|
||||
Add a bunch of files for managing composer headers.
|
||||
|
||||
* e-msg-composer.c (build_message), (from_changed_cb),
|
||||
(set_editor_signature), (e_msg_composer_set_body),
|
||||
(e_msg_composer_get_preferred_account):
|
||||
Use e_msg_composer_hdrs_get_from_account() to obtain the EAccount.
|
||||
|
||||
* e-msg-composer-hdrs.c:
|
||||
* e-msg-composer-hdrs.h:
|
||||
Massive refactoring to use new EComposerHeader classes.
|
||||
|
||||
* e-composer-header.c:
|
||||
* e-composer-header.h:
|
||||
* e-composer-from-header.c:
|
||||
* e-composer-from-header.h:
|
||||
* e-composer-name-header.c:
|
||||
* e-composer-name-header.h:
|
||||
* e-composer-post-header.c:
|
||||
* e-composer-post-header.h:
|
||||
* e-composer-text-header.c:
|
||||
* e-composer-text-header.h:
|
||||
New GObject classes manage different types of composer headers.
|
||||
See bug #495123 for a more detailed description of each class.
|
||||
|
||||
2007-11-01 Milan Crha <mcrha@redhat.com>
|
||||
|
||||
** Fix for bug #318592
|
||||
|
||||
@ -58,6 +58,17 @@ INCLUDES = \
|
||||
libcomposer_la_SOURCES = \
|
||||
$(IDL_GENERATED) \
|
||||
$(HTML_EDITOR_GENERATED) \
|
||||
e-composer-common.h \
|
||||
e-composer-header.c \
|
||||
e-composer-header.h \
|
||||
e-composer-from-header.c \
|
||||
e-composer-from_header.h \
|
||||
e-composer-name-header.c \
|
||||
e-composer-name-header.h \
|
||||
e-composer-post-header.c \
|
||||
e-composer-post-header.h \
|
||||
e-composer-text-header.c \
|
||||
e-composer-text-header.h \
|
||||
e-msg-composer-hdrs.c \
|
||||
e-msg-composer-hdrs.h \
|
||||
e-msg-composer-select-file.c \
|
||||
|
||||
10
composer/e-composer-common.h
Normal file
10
composer/e-composer-common.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef E_COMPOSER_COMMON
|
||||
#define E_COMPOSER_COMMON
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#endif /* E_COMPOSER_COMMON */
|
||||
178
composer/e-composer-from-header.c
Normal file
178
composer/e-composer-from-header.c
Normal file
@ -0,0 +1,178 @@
|
||||
#include "e-composer-from-header.h"
|
||||
|
||||
#define E_COMPOSER_FROM_HEADER_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE \
|
||||
((obj), E_TYPE_COMPOSER_FROM_HEADER, EComposerFromHeaderPrivate))
|
||||
|
||||
struct _EComposerFromHeaderPrivate {
|
||||
GtkWidget *combo_box;
|
||||
};
|
||||
|
||||
static gpointer parent_class;
|
||||
|
||||
static void
|
||||
composer_from_header_changed_cb (EAccountComboBox *combo_box,
|
||||
EComposerFromHeader *header)
|
||||
{
|
||||
g_signal_emit_by_name (header, "changed");
|
||||
}
|
||||
|
||||
static void
|
||||
composer_from_header_dispose (GObject *object)
|
||||
{
|
||||
EComposerFromHeaderPrivate *priv;
|
||||
|
||||
priv = E_COMPOSER_FROM_HEADER_GET_PRIVATE (object);
|
||||
|
||||
if (priv->combo_box != NULL) {
|
||||
g_object_unref (priv->combo_box);
|
||||
priv->combo_box = NULL;
|
||||
}
|
||||
|
||||
/* Chain up to parent's dispose() method. */
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
composer_from_header_class_init (EComposerFromHeaderClass *class)
|
||||
{
|
||||
GObjectClass *object_class;
|
||||
|
||||
parent_class = g_type_class_peek_parent (class);
|
||||
g_type_class_add_private (class, sizeof (EComposerFromHeaderPrivate));
|
||||
|
||||
object_class = G_OBJECT_CLASS (class);
|
||||
object_class->dispose = composer_from_header_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
composer_from_header_init (EComposerFromHeader *header)
|
||||
{
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *widget;
|
||||
|
||||
header->priv = E_COMPOSER_FROM_HEADER_GET_PRIVATE (header);
|
||||
|
||||
hbox = g_object_ref_sink (gtk_hbox_new (FALSE, 6));
|
||||
E_COMPOSER_HEADER (header)->input_widget = hbox;
|
||||
|
||||
widget = e_account_combo_box_new ();
|
||||
g_signal_connect (
|
||||
widget, "changed",
|
||||
G_CALLBACK (composer_from_header_changed_cb), header);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
|
||||
header->priv->combo_box = g_object_ref_sink (widget);
|
||||
gtk_widget_show (widget);
|
||||
}
|
||||
|
||||
GType
|
||||
e_composer_from_header_get_type (void)
|
||||
{
|
||||
static GType type = 0;
|
||||
|
||||
if (G_UNLIKELY (type == 0)) {
|
||||
static const GTypeInfo type_info = {
|
||||
sizeof (EComposerFromHeaderClass),
|
||||
(GBaseInitFunc) NULL,
|
||||
(GBaseFinalizeFunc) NULL,
|
||||
(GClassInitFunc) composer_from_header_class_init,
|
||||
(GClassFinalizeFunc) NULL,
|
||||
NULL, /* class_data */
|
||||
sizeof (EComposerFromHeader),
|
||||
0, /* n_preallocs */
|
||||
(GInstanceInitFunc) composer_from_header_init,
|
||||
NULL /* value_table */
|
||||
};
|
||||
|
||||
type = g_type_register_static (
|
||||
E_TYPE_COMPOSER_HEADER, "EComposerFromHeader",
|
||||
&type_info, 0);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
EComposerHeader *
|
||||
e_composer_from_header_new (const gchar *label)
|
||||
{
|
||||
return g_object_new (
|
||||
E_TYPE_COMPOSER_FROM_HEADER, "label", label,
|
||||
"button", FALSE, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
e_composer_from_header_set_account_list (EComposerFromHeader *header,
|
||||
EAccountList *account_list)
|
||||
{
|
||||
EAccountComboBox *combo_box;
|
||||
|
||||
g_return_if_fail (E_IS_COMPOSER_FROM_HEADER (header));
|
||||
|
||||
combo_box = E_ACCOUNT_COMBO_BOX (header->priv->combo_box);
|
||||
e_account_combo_box_set_account_list (combo_box, account_list);
|
||||
}
|
||||
|
||||
EAccount *
|
||||
e_composer_from_header_get_active (EComposerFromHeader *header)
|
||||
{
|
||||
EAccountComboBox *combo_box;
|
||||
|
||||
g_return_val_if_fail (E_IS_COMPOSER_FROM_HEADER (header), NULL);
|
||||
|
||||
combo_box = E_ACCOUNT_COMBO_BOX (header->priv->combo_box);
|
||||
return e_account_combo_box_get_active (combo_box);
|
||||
}
|
||||
|
||||
gboolean
|
||||
e_composer_from_header_set_active (EComposerFromHeader *header,
|
||||
EAccount *account)
|
||||
{
|
||||
EAccountComboBox *combo_box;
|
||||
|
||||
g_return_val_if_fail (E_IS_COMPOSER_FROM_HEADER (header), FALSE);
|
||||
|
||||
combo_box = E_ACCOUNT_COMBO_BOX (header->priv->combo_box);
|
||||
return e_account_combo_box_set_active (combo_box, account);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
e_composer_from_header_get_active_name (EComposerFromHeader *header)
|
||||
{
|
||||
EAccountComboBox *combo_box;
|
||||
|
||||
g_return_val_if_fail (E_IS_COMPOSER_FROM_HEADER (header), NULL);
|
||||
|
||||
combo_box = E_ACCOUNT_COMBO_BOX (header->priv->combo_box);
|
||||
return e_account_combo_box_get_active_name (combo_box);
|
||||
}
|
||||
|
||||
gboolean
|
||||
e_composer_from_header_set_active_name (EComposerFromHeader *header,
|
||||
const gchar *account_name)
|
||||
{
|
||||
EAccountComboBox *combo_box;
|
||||
|
||||
g_return_val_if_fail (E_IS_COMPOSER_FROM_HEADER (header), FALSE);
|
||||
|
||||
combo_box = E_ACCOUNT_COMBO_BOX (header->priv->combo_box);
|
||||
return e_account_combo_box_set_active_name (combo_box, account_name);
|
||||
}
|
||||
|
||||
CamelInternetAddress *
|
||||
e_composer_from_header_get_active_address (EComposerFromHeader *header)
|
||||
{
|
||||
CamelInternetAddress *address;
|
||||
EAccount *account;
|
||||
|
||||
g_return_val_if_fail (E_IS_COMPOSER_FROM_HEADER (header), NULL);
|
||||
|
||||
account = e_composer_from_header_get_active (header);
|
||||
if (account == NULL)
|
||||
return NULL;
|
||||
|
||||
address = camel_internet_address_new ();
|
||||
camel_internet_address_add (
|
||||
address, account->id->name, account->id->address);
|
||||
|
||||
return address;
|
||||
}
|
||||
67
composer/e-composer-from-header.h
Normal file
67
composer/e-composer-from-header.h
Normal file
@ -0,0 +1,67 @@
|
||||
#ifndef E_COMPOSER_FROM_HEADER_H
|
||||
#define E_COMPOSER_FROM_HEADER_H
|
||||
|
||||
#include "e-composer-common.h"
|
||||
|
||||
#include <libedataserver/e-account.h>
|
||||
#include <libedataserver/e-account-list.h>
|
||||
#include <camel/camel-internet-address.h>
|
||||
|
||||
#include "e-account-combo-box.h"
|
||||
#include "e-composer-header.h"
|
||||
|
||||
/* Standard GObject macros */
|
||||
#define E_TYPE_COMPOSER_FROM_HEADER \
|
||||
(e_composer_from_header_get_type ())
|
||||
#define E_COMPOSER_FROM_HEADER(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST \
|
||||
((obj), E_TYPE_COMPOSER_FROM_HEADER, EComposerFromHeader))
|
||||
#define E_COMPOSER_FROM_HEADER_CLASS(cls) \
|
||||
(G_TYPE_CHECK_CLASS_CAST \
|
||||
((obj), E_TYPE_COMPOSER_FROM_HEADER, EComposerFromHeaderClass))
|
||||
#define E_IS_COMPOSER_FROM_HEADER(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE \
|
||||
((obj), E_TYPE_COMPOSER_FROM_HEADER))
|
||||
#define E_IS_COMPOSER_FROM_HEADER_CLASS(cls) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE \
|
||||
((obj), E_TYPE_COMPOSER_FROM_HEADER))
|
||||
#define E_COMPOSER_FROM_HEADER_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS \
|
||||
((obj), E_TYPE_COMPOSER_FROM_HEADER, EComposerFromHeaderClass))
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _EComposerFromHeader EComposerFromHeader;
|
||||
typedef struct _EComposerFromHeaderClass EComposerFromHeaderClass;
|
||||
typedef struct _EComposerFromHeaderPrivate EComposerFromHeaderPrivate;
|
||||
|
||||
struct _EComposerFromHeader {
|
||||
EComposerHeader parent;
|
||||
EComposerFromHeaderPrivate *priv;
|
||||
};
|
||||
|
||||
struct _EComposerFromHeaderClass {
|
||||
EComposerHeaderClass parent_class;
|
||||
};
|
||||
|
||||
GType e_composer_from_header_get_type (void);
|
||||
EComposerHeader * e_composer_from_header_new (const gchar *label);
|
||||
void e_composer_from_header_set_account_list
|
||||
(EComposerFromHeader *header,
|
||||
EAccountList *account_list);
|
||||
EAccount * e_composer_from_header_get_active
|
||||
(EComposerFromHeader *header);
|
||||
gboolean e_composer_from_header_set_active
|
||||
(EComposerFromHeader *header,
|
||||
EAccount *account);
|
||||
const gchar * e_composer_from_header_get_active_name
|
||||
(EComposerFromHeader *header);
|
||||
gboolean e_composer_from_header_set_active_name
|
||||
(EComposerFromHeader *header,
|
||||
const gchar *account_name);
|
||||
CamelInternetAddress * e_composer_from_header_get_active_address
|
||||
(EComposerFromHeader *header);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* E_COMPOSER_FROM_HEADER_H */
|
||||
310
composer/e-composer-header.c
Normal file
310
composer/e-composer-header.c
Normal file
@ -0,0 +1,310 @@
|
||||
#include "e-composer-header.h"
|
||||
|
||||
#define E_COMPOSER_HEADER_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE \
|
||||
((obj), E_TYPE_COMPOSER_HEADER, EComposerHeaderPrivate))
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_BUTTON,
|
||||
PROP_LABEL,
|
||||
PROP_VISIBLE
|
||||
};
|
||||
|
||||
enum {
|
||||
CHANGED,
|
||||
CLICKED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
struct _EComposerHeaderPrivate {
|
||||
gchar *label;
|
||||
gboolean button;
|
||||
};
|
||||
|
||||
static gpointer parent_class;
|
||||
static guint signal_ids[LAST_SIGNAL];
|
||||
|
||||
static void
|
||||
composer_header_button_clicked_cb (GtkButton *button,
|
||||
EComposerHeader *header)
|
||||
{
|
||||
gtk_widget_grab_focus (header->input_widget);
|
||||
g_signal_emit (header, signal_ids[CLICKED], 0);
|
||||
}
|
||||
|
||||
static GObject *
|
||||
composer_header_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_properties)
|
||||
{
|
||||
GObject *object;
|
||||
GtkWidget *widget;
|
||||
EComposerHeader *header;
|
||||
|
||||
/* Chain up to parent's constructor() method. */
|
||||
object = G_OBJECT_CLASS (parent_class)->constructor (
|
||||
type, n_construct_properties, construct_properties);
|
||||
|
||||
header = E_COMPOSER_HEADER (object);
|
||||
|
||||
if (header->priv->button) {
|
||||
widget = gtk_button_new_with_mnemonic (header->priv->label);
|
||||
GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_FOCUS);
|
||||
g_signal_connect (
|
||||
widget, "clicked",
|
||||
G_CALLBACK (composer_header_button_clicked_cb),
|
||||
header);
|
||||
} else {
|
||||
widget = gtk_label_new_with_mnemonic (header->priv->label);
|
||||
|
||||
/* The subclass may not have initialized 'input_widget' yet,
|
||||
* in which case the subclass will have to do this. */
|
||||
if (header->input_widget != NULL)
|
||||
gtk_label_set_mnemonic_widget (
|
||||
GTK_LABEL (widget), header->input_widget);
|
||||
}
|
||||
header->title_widget = g_object_ref_sink (widget);
|
||||
|
||||
g_free (header->priv->label);
|
||||
header->priv->label = NULL;
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
static void
|
||||
composer_header_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
EComposerHeaderPrivate *priv;
|
||||
|
||||
priv = E_COMPOSER_HEADER_GET_PRIVATE (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_BUTTON: /* construct only */
|
||||
priv->button = g_value_get_boolean (value);
|
||||
return;
|
||||
|
||||
case PROP_LABEL: /* construct only */
|
||||
priv->label = g_value_dup_string (value);
|
||||
return;
|
||||
|
||||
case PROP_VISIBLE:
|
||||
e_composer_header_set_visible (
|
||||
E_COMPOSER_HEADER (object),
|
||||
g_value_get_boolean (value));
|
||||
return;
|
||||
}
|
||||
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
composer_header_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
EComposerHeaderPrivate *priv;
|
||||
|
||||
priv = E_COMPOSER_HEADER_GET_PRIVATE (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_BUTTON: /* construct only */
|
||||
g_value_set_boolean (value, priv->button);
|
||||
return;
|
||||
|
||||
case PROP_LABEL: /* construct only */
|
||||
g_value_take_string (
|
||||
value, e_composer_header_get_label (
|
||||
E_COMPOSER_HEADER (object)));
|
||||
return;
|
||||
|
||||
case PROP_VISIBLE:
|
||||
g_value_set_boolean (
|
||||
value, e_composer_header_get_visible (
|
||||
E_COMPOSER_HEADER (object)));
|
||||
return;
|
||||
}
|
||||
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
composer_header_dispose (GObject *object)
|
||||
{
|
||||
EComposerHeader *header = E_COMPOSER_HEADER (object);
|
||||
|
||||
if (header->title_widget != NULL) {
|
||||
g_object_unref (header->title_widget);
|
||||
header->title_widget = NULL;
|
||||
}
|
||||
|
||||
if (header->input_widget != NULL) {
|
||||
g_object_unref (header->input_widget);
|
||||
header->input_widget = NULL;
|
||||
}
|
||||
|
||||
/* Chain up to parent's dispose() method. */
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
composer_header_class_init (EComposerHeaderClass *class)
|
||||
{
|
||||
GObjectClass *object_class;
|
||||
|
||||
parent_class = g_type_class_peek_parent (class);
|
||||
g_type_class_add_private (class, sizeof (EComposerHeaderPrivate));
|
||||
|
||||
object_class = G_OBJECT_CLASS (class);
|
||||
object_class->constructor = composer_header_constructor;
|
||||
object_class->set_property = composer_header_set_property;
|
||||
object_class->get_property = composer_header_get_property;
|
||||
object_class->dispose = composer_header_dispose;
|
||||
|
||||
g_object_class_install_property (
|
||||
object_class,
|
||||
PROP_BUTTON,
|
||||
g_param_spec_boolean (
|
||||
"button",
|
||||
NULL,
|
||||
NULL,
|
||||
FALSE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (
|
||||
object_class,
|
||||
PROP_LABEL,
|
||||
g_param_spec_string (
|
||||
"label",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (
|
||||
object_class,
|
||||
PROP_VISIBLE,
|
||||
g_param_spec_boolean (
|
||||
"visible",
|
||||
NULL,
|
||||
NULL,
|
||||
FALSE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
signal_ids[CHANGED] = g_signal_new (
|
||||
"changed",
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
signal_ids[CLICKED] = g_signal_new (
|
||||
"clicked",
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
composer_header_init (EComposerHeader *header)
|
||||
{
|
||||
header->priv = E_COMPOSER_HEADER_GET_PRIVATE (header);
|
||||
}
|
||||
|
||||
GType
|
||||
e_composer_header_get_type (void)
|
||||
{
|
||||
static GType type = 0;
|
||||
|
||||
if (G_UNLIKELY (type == 0)) {
|
||||
static const GTypeInfo type_info = {
|
||||
sizeof (EComposerHeaderClass),
|
||||
(GBaseInitFunc) NULL,
|
||||
(GBaseFinalizeFunc) NULL,
|
||||
(GClassInitFunc) composer_header_class_init,
|
||||
(GClassFinalizeFunc) NULL,
|
||||
NULL, /* class_data */
|
||||
sizeof (EComposerHeader),
|
||||
0, /* n_preallocs */
|
||||
(GInstanceInitFunc) composer_header_init,
|
||||
NULL /* value_table */
|
||||
};
|
||||
|
||||
type = g_type_register_static (
|
||||
G_TYPE_OBJECT, "EComposerHeader",
|
||||
&type_info, G_TYPE_FLAG_ABSTRACT);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
gchar *
|
||||
e_composer_header_get_label (EComposerHeader *header)
|
||||
{
|
||||
gchar *label;
|
||||
|
||||
g_return_val_if_fail (E_IS_COMPOSER_HEADER (header), NULL);
|
||||
|
||||
/* GtkButton and GtkLabel both have a "label" property. */
|
||||
g_object_get (header->title_widget, "label", &label, NULL);
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
gboolean
|
||||
e_composer_header_get_visible (EComposerHeader *header)
|
||||
{
|
||||
gboolean visible;
|
||||
|
||||
g_return_val_if_fail (E_IS_COMPOSER_HEADER (header), FALSE);
|
||||
|
||||
visible = GTK_WIDGET_VISIBLE (header->title_widget);
|
||||
if (GTK_WIDGET_VISIBLE (header->input_widget) != visible)
|
||||
g_warning ("%s: Visibility is out of sync", G_STRFUNC);
|
||||
|
||||
return visible;
|
||||
}
|
||||
|
||||
void
|
||||
e_composer_header_set_visible (EComposerHeader *header,
|
||||
gboolean visible)
|
||||
{
|
||||
g_return_if_fail (E_IS_COMPOSER_HEADER (header));
|
||||
|
||||
if (visible) {
|
||||
gtk_widget_show (header->title_widget);
|
||||
gtk_widget_show (header->input_widget);
|
||||
} else {
|
||||
gtk_widget_hide (header->title_widget);
|
||||
gtk_widget_hide (header->input_widget);
|
||||
}
|
||||
|
||||
g_object_notify (G_OBJECT (header), "visible");
|
||||
}
|
||||
|
||||
void
|
||||
e_composer_header_set_title_tooltip (EComposerHeader *header,
|
||||
const gchar *tooltip)
|
||||
{
|
||||
g_return_if_fail (E_IS_COMPOSER_HEADER (header));
|
||||
|
||||
gtk_widget_set_tooltip_text (header->title_widget, tooltip);
|
||||
}
|
||||
|
||||
void
|
||||
e_composer_header_set_input_tooltip (EComposerHeader *header,
|
||||
const gchar *tooltip)
|
||||
{
|
||||
g_return_if_fail (E_IS_COMPOSER_HEADER (header));
|
||||
|
||||
gtk_widget_set_tooltip_text (header->input_widget, tooltip);
|
||||
}
|
||||
56
composer/e-composer-header.h
Normal file
56
composer/e-composer-header.h
Normal file
@ -0,0 +1,56 @@
|
||||
#ifndef E_COMPOSER_HEADER_H
|
||||
#define E_COMPOSER_HEADER_H
|
||||
|
||||
#include "e-composer-common.h"
|
||||
|
||||
/* Standard GObject macros */
|
||||
#define E_TYPE_COMPOSER_HEADER \
|
||||
(e_composer_header_get_type ())
|
||||
#define E_COMPOSER_HEADER(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST \
|
||||
((obj), E_TYPE_COMPOSER_HEADER, EComposerHeader))
|
||||
#define E_COMPOSER_HEADER_CLASS(cls) \
|
||||
(G_TYPE_CHECK_CLASS_CAST \
|
||||
((obj), E_TYPE_COMPOSER_HEADER, EComposerHeaderClass))
|
||||
#define E_IS_COMPOSER_HEADER(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE \
|
||||
((obj), E_TYPE_COMPOSER_HEADER))
|
||||
#define E_IS_COMPOSER_HEADER_CLASS(cls) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE \
|
||||
((cls), E_TYPE_COMPOSER_HEADER))
|
||||
#define E_COMPOSER_HEADER_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS \
|
||||
((obj), E_TYPE_COMPOSER_HEADER, EComposerHeaderClass))
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _EComposerHeader EComposerHeader;
|
||||
typedef struct _EComposerHeaderClass EComposerHeaderClass;
|
||||
typedef struct _EComposerHeaderPrivate EComposerHeaderPrivate;
|
||||
|
||||
struct _EComposerHeader {
|
||||
GObject parent;
|
||||
GtkWidget *title_widget;
|
||||
GtkWidget *input_widget;
|
||||
EComposerHeaderPrivate *priv;
|
||||
};
|
||||
|
||||
struct _EComposerHeaderClass {
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
GType e_composer_header_get_type (void);
|
||||
gchar * e_composer_header_get_label (EComposerHeader *header);
|
||||
gboolean e_composer_header_get_visible (EComposerHeader *header);
|
||||
void e_composer_header_set_visible (EComposerHeader *header,
|
||||
gboolean visible);
|
||||
void e_composer_header_set_title_tooltip
|
||||
(EComposerHeader *header,
|
||||
const gchar *tooltip);
|
||||
void e_composer_header_set_input_tooltip
|
||||
(EComposerHeader *header,
|
||||
const gchar *tooltip);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* E_COMPOSER_HEADER_H */
|
||||
301
composer/e-composer-name-header.c
Normal file
301
composer/e-composer-name-header.c
Normal file
@ -0,0 +1,301 @@
|
||||
#include "e-composer-name-header.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
/* XXX Temporary kludge */
|
||||
#include "addressbook/gui/contact-editor/e-contact-editor.h"
|
||||
#include "addressbook/gui/contact-list-editor/e-contact-list-editor.h"
|
||||
|
||||
#define E_COMPOSER_NAME_HEADER_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE \
|
||||
((obj), E_TYPE_COMPOSER_NAME_HEADER, EComposerNameHeaderPrivate))
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_NAME_SELECTOR
|
||||
};
|
||||
|
||||
struct _EComposerNameHeaderPrivate {
|
||||
ENameSelector *name_selector;
|
||||
guint destination_index;
|
||||
};
|
||||
|
||||
static gpointer parent_class;
|
||||
|
||||
static void
|
||||
composer_name_header_clicked_cb (EComposerNameHeader *header)
|
||||
{
|
||||
ENameSelectorDialog *dialog;
|
||||
|
||||
dialog = e_name_selector_peek_dialog (header->priv->name_selector);
|
||||
e_name_selector_dialog_set_destination_index (
|
||||
dialog, header->priv->destination_index);
|
||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
gtk_widget_hide (GTK_WIDGET (dialog));
|
||||
}
|
||||
|
||||
static void
|
||||
composer_name_header_entry_changed_cb (ENameSelectorEntry *entry,
|
||||
EComposerNameHeader *header)
|
||||
{
|
||||
g_signal_emit_by_name (header, "changed");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
composer_name_header_entry_query_tooltip_cb (GtkEntry *entry,
|
||||
gint x,
|
||||
gint y,
|
||||
gboolean keyboard_mode,
|
||||
GtkTooltip *tooltip)
|
||||
{
|
||||
const gchar *text;
|
||||
|
||||
text = gtk_entry_get_text (entry);
|
||||
|
||||
if (keyboard_mode || text == NULL || *text == '\0')
|
||||
return FALSE;
|
||||
|
||||
gtk_tooltip_set_text (tooltip, text);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GObject *
|
||||
composer_name_header_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_properties)
|
||||
{
|
||||
EComposerNameHeaderPrivate *priv;
|
||||
ENameSelectorModel *model;
|
||||
ENameSelectorEntry *entry;
|
||||
GObject *object;
|
||||
gchar *label;
|
||||
|
||||
/* Chain up to parent's constructor() method. */
|
||||
object = G_OBJECT_CLASS (parent_class)->constructor (
|
||||
type, n_construct_properties, construct_properties);
|
||||
|
||||
priv = E_COMPOSER_NAME_HEADER_GET_PRIVATE (object);
|
||||
g_assert (E_IS_NAME_SELECTOR (priv->name_selector));
|
||||
|
||||
model = e_name_selector_peek_model (priv->name_selector);
|
||||
label = e_composer_header_get_label (E_COMPOSER_HEADER (object));
|
||||
g_assert (label != NULL);
|
||||
|
||||
/* XXX Peeking at private data. */
|
||||
priv->destination_index = model->sections->len;
|
||||
e_name_selector_model_add_section (model, label, label, NULL);
|
||||
|
||||
e_composer_header_set_title_tooltip (
|
||||
E_COMPOSER_HEADER (object),
|
||||
_("Click here for the address book"));
|
||||
|
||||
entry = E_NAME_SELECTOR_ENTRY (
|
||||
e_name_selector_peek_section_list (
|
||||
priv->name_selector, label));
|
||||
e_name_selector_entry_set_contact_editor_func (
|
||||
entry, e_contact_editor_new);
|
||||
e_name_selector_entry_set_contact_list_editor_func (
|
||||
entry, e_contact_list_editor_new);
|
||||
g_signal_connect (
|
||||
entry, "changed",
|
||||
G_CALLBACK (composer_name_header_entry_changed_cb), object);
|
||||
g_signal_connect (
|
||||
entry, "query-tooltip",
|
||||
G_CALLBACK (composer_name_header_entry_query_tooltip_cb),
|
||||
NULL);
|
||||
E_COMPOSER_HEADER (object)->input_widget = g_object_ref_sink (entry);
|
||||
|
||||
g_signal_connect (
|
||||
object, "clicked",
|
||||
G_CALLBACK (composer_name_header_clicked_cb), NULL);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
static void
|
||||
composer_name_header_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
EComposerNameHeaderPrivate *priv;
|
||||
|
||||
priv = E_COMPOSER_NAME_HEADER_GET_PRIVATE (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_NAME_SELECTOR: /* construct only */
|
||||
g_assert (priv->name_selector == NULL);
|
||||
priv->name_selector = g_value_dup_object (value);
|
||||
return;
|
||||
}
|
||||
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
composer_name_header_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
switch (property_id) {
|
||||
case PROP_NAME_SELECTOR: /* construct only */
|
||||
g_value_set_object (
|
||||
value,
|
||||
e_composer_name_header_get_name_selector (
|
||||
E_COMPOSER_NAME_HEADER (object)));
|
||||
return;
|
||||
}
|
||||
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
composer_name_header_dispose (GObject *object)
|
||||
{
|
||||
EComposerNameHeaderPrivate *priv;
|
||||
|
||||
priv = E_COMPOSER_NAME_HEADER_GET_PRIVATE (object);
|
||||
|
||||
if (priv->name_selector != NULL) {
|
||||
g_object_unref (priv->name_selector);
|
||||
priv->name_selector = NULL;
|
||||
}
|
||||
|
||||
/* Chain up to parent's dispose() method. */
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
composer_name_header_class_init (EComposerNameHeaderClass *class)
|
||||
{
|
||||
GObjectClass *object_class;
|
||||
|
||||
parent_class = g_type_class_peek_parent (class);
|
||||
g_type_class_add_private (class, sizeof (EComposerNameHeaderPrivate));
|
||||
|
||||
object_class = G_OBJECT_CLASS (class);
|
||||
object_class->constructor = composer_name_header_constructor;
|
||||
object_class->set_property = composer_name_header_set_property;
|
||||
object_class->get_property = composer_name_header_get_property;
|
||||
object_class->dispose = composer_name_header_dispose;
|
||||
|
||||
g_object_class_install_property (
|
||||
object_class,
|
||||
PROP_NAME_SELECTOR,
|
||||
g_param_spec_object (
|
||||
"name-selector",
|
||||
NULL,
|
||||
NULL,
|
||||
E_TYPE_NAME_SELECTOR,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
}
|
||||
|
||||
static void
|
||||
composer_name_header_init (EComposerNameHeader *header)
|
||||
{
|
||||
header->priv = E_COMPOSER_NAME_HEADER_GET_PRIVATE (header);
|
||||
}
|
||||
|
||||
GType
|
||||
e_composer_name_header_get_type (void)
|
||||
{
|
||||
static GType type = 0;
|
||||
|
||||
if (G_UNLIKELY (type == 0)) {
|
||||
static const GTypeInfo type_info = {
|
||||
sizeof (EComposerNameHeaderClass),
|
||||
(GBaseInitFunc) NULL,
|
||||
(GBaseFinalizeFunc) NULL,
|
||||
(GClassInitFunc) composer_name_header_class_init,
|
||||
(GClassFinalizeFunc) NULL,
|
||||
NULL, /* class_data */
|
||||
sizeof (EComposerNameHeader),
|
||||
0, /* n_preallocs */
|
||||
(GInstanceInitFunc) composer_name_header_init,
|
||||
NULL /* value_table */
|
||||
};
|
||||
|
||||
type = g_type_register_static (
|
||||
E_TYPE_COMPOSER_HEADER, "EComposerNameHeader",
|
||||
&type_info, 0);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
EComposerHeader *
|
||||
e_composer_name_header_new (const gchar *label,
|
||||
ENameSelector *name_selector)
|
||||
{
|
||||
g_return_val_if_fail (E_IS_NAME_SELECTOR (name_selector), NULL);
|
||||
|
||||
return g_object_new (
|
||||
E_TYPE_COMPOSER_NAME_HEADER, "label", label,
|
||||
"button", TRUE, "name-selector", name_selector, NULL);
|
||||
}
|
||||
|
||||
ENameSelector *
|
||||
e_composer_name_header_get_name_selector (EComposerNameHeader *header)
|
||||
{
|
||||
g_return_val_if_fail (E_IS_COMPOSER_NAME_HEADER (header), NULL);
|
||||
|
||||
return header->priv->name_selector;
|
||||
}
|
||||
|
||||
EDestination **
|
||||
e_composer_name_header_get_destinations (EComposerNameHeader *header)
|
||||
{
|
||||
EDestinationStore *store;
|
||||
EDestination **destinations;
|
||||
GtkWidget *input_widget;
|
||||
GList *list, *iter;
|
||||
gint ii = 0;
|
||||
|
||||
g_return_val_if_fail (E_IS_COMPOSER_NAME_HEADER (header), NULL);
|
||||
|
||||
input_widget = E_COMPOSER_HEADER (header)->input_widget;
|
||||
store = e_name_selector_entry_peek_destination_store (
|
||||
E_NAME_SELECTOR_ENTRY (input_widget));
|
||||
|
||||
list = e_destination_store_list_destinations (store);
|
||||
destinations = g_new0 (EDestination *, g_list_length (list) + 1);
|
||||
|
||||
for (iter = list; iter != NULL; iter = iter->next)
|
||||
destinations[ii++] = g_object_ref (iter->data);
|
||||
|
||||
g_list_free (list);
|
||||
|
||||
return destinations;
|
||||
}
|
||||
|
||||
void
|
||||
e_composer_name_header_set_destinations (EComposerNameHeader *header,
|
||||
EDestination **destinations)
|
||||
{
|
||||
EDestinationStore *store;
|
||||
GtkWidget *input_widget;
|
||||
GList *list, *iter;
|
||||
gint ii;
|
||||
|
||||
g_return_if_fail (E_IS_COMPOSER_NAME_HEADER (header));
|
||||
|
||||
input_widget = E_COMPOSER_HEADER (header)->input_widget;
|
||||
store = e_name_selector_entry_peek_destination_store (
|
||||
E_NAME_SELECTOR_ENTRY (input_widget));
|
||||
|
||||
/* Clear the destination store. */
|
||||
list = e_destination_store_list_destinations (store);
|
||||
for (iter = list; iter != NULL; iter = iter->next)
|
||||
e_destination_store_remove_destination (store, iter->data);
|
||||
g_list_free (list);
|
||||
|
||||
if (destinations == NULL)
|
||||
return;
|
||||
|
||||
for (ii = 0; destinations[ii] != NULL; ii++)
|
||||
e_destination_store_append_destination (
|
||||
store, destinations[ii]);
|
||||
}
|
||||
58
composer/e-composer-name-header.h
Normal file
58
composer/e-composer-name-header.h
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef E_COMPOSER_NAME_HEADER_H
|
||||
#define E_COMPOSER_NAME_HEADER_H
|
||||
|
||||
#include "e-composer-common.h"
|
||||
|
||||
#include <libebook/e-destination.h>
|
||||
#include <libedataserverui/e-name-selector.h>
|
||||
|
||||
#include "e-composer-header.h"
|
||||
|
||||
/* Standard GObject macros */
|
||||
#define E_TYPE_COMPOSER_NAME_HEADER \
|
||||
(e_composer_name_header_get_type ())
|
||||
#define E_COMPOSER_NAME_HEADER(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST \
|
||||
((obj), E_TYPE_COMPOSER_NAME_HEADER, EComposerNameHeader))
|
||||
#define E_COMPOSER_NAME_HEADER_CLASS(cls) \
|
||||
(G_TYPE_CHECK_CLASS_CAST \
|
||||
((cls), E_TYPE_COMPOSER_NAME_HEADER, EComposerNameHeaderClass))
|
||||
#define E_IS_COMPOSER_NAME_HEADER(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE \
|
||||
((obj), E_TYPE_COMPOSER_NAME_HEADER))
|
||||
#define E_IS_COMPOSER_NAME_HEADER_CLASS(cls) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE \
|
||||
((cls), E_TYPE_COMPOSER_NAME_HEADER))
|
||||
#define E_COMPOSER_NAME_HEADER_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS \
|
||||
((obj), E_TYPE_COMPOSER_NAME_HEADER, EComposerNameHeaderClass))
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _EComposerNameHeader EComposerNameHeader;
|
||||
typedef struct _EComposerNameHeaderClass EComposerNameHeaderClass;
|
||||
typedef struct _EComposerNameHeaderPrivate EComposerNameHeaderPrivate;
|
||||
|
||||
struct _EComposerNameHeader {
|
||||
EComposerHeader parent;
|
||||
EComposerNameHeaderPrivate *priv;
|
||||
};
|
||||
|
||||
struct _EComposerNameHeaderClass {
|
||||
EComposerHeaderClass parent_class;
|
||||
};
|
||||
|
||||
GType e_composer_name_header_get_type (void);
|
||||
EComposerHeader * e_composer_name_header_new (const gchar *label,
|
||||
ENameSelector *name_selector);
|
||||
ENameSelector * e_composer_name_header_get_name_selector
|
||||
(EComposerNameHeader *header);
|
||||
EDestination ** e_composer_name_header_get_destinations
|
||||
(EComposerNameHeader *header);
|
||||
void e_composer_name_header_set_destinations
|
||||
(EComposerNameHeader *header,
|
||||
EDestination **destinations);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* E_COMPOSER_NAME_HEADER_H */
|
||||
401
composer/e-composer-post-header.c
Normal file
401
composer/e-composer-post-header.c
Normal file
@ -0,0 +1,401 @@
|
||||
#include "e-composer-post-header.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "mail/em-folder-selector.h"
|
||||
#include "mail/em-folder-tree.h"
|
||||
|
||||
#define E_COMPOSER_POST_HEADER_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE \
|
||||
((obj), E_TYPE_COMPOSER_POST_HEADER, EComposerPostHeaderPrivate))
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_ACCOUNT
|
||||
};
|
||||
|
||||
struct _EComposerPostHeaderPrivate {
|
||||
EAccount *account;
|
||||
gchar *base_url; /* derived from account */
|
||||
gboolean custom;
|
||||
};
|
||||
|
||||
static gpointer parent_class;
|
||||
|
||||
/* Forward Declarations (to avoid pulling in Bonobo stuff) */
|
||||
struct _MailComponent *mail_component_peek (void);
|
||||
struct _EMFolderTreeModel *mail_component_peek_tree_model (struct _MailComponent *component);
|
||||
|
||||
static gchar *
|
||||
composer_post_header_folder_name_to_string (EComposerPostHeader *header,
|
||||
const gchar *url)
|
||||
{
|
||||
const gchar *base_url = header->priv->base_url;
|
||||
|
||||
if (base_url != NULL) {
|
||||
gsize length = strlen (base_url);
|
||||
|
||||
if (g_ascii_strncasecmp (url, base_url, length) == 0)
|
||||
return g_strdup (url + length);
|
||||
}
|
||||
|
||||
return g_strdup (url);
|
||||
}
|
||||
|
||||
static void
|
||||
composer_post_header_set_base_url (EComposerPostHeader *header)
|
||||
{
|
||||
EAccount *account = header->priv->account;
|
||||
CamelURL *camel_url;
|
||||
gchar *url;
|
||||
|
||||
if (account == NULL || account->source == NULL)
|
||||
return;
|
||||
|
||||
url = account->source->url;
|
||||
if (url == NULL || *url == '\0')
|
||||
return;
|
||||
|
||||
camel_url = camel_url_new (url, NULL);
|
||||
if (camel_url == NULL)
|
||||
return;
|
||||
|
||||
url = camel_url_to_string (camel_url, CAMEL_URL_HIDE_ALL);
|
||||
camel_url_free (camel_url);
|
||||
|
||||
header->priv->base_url = url;
|
||||
}
|
||||
|
||||
static GList *
|
||||
composer_post_header_split_csv (const gchar *csv)
|
||||
{
|
||||
GList *list = NULL;
|
||||
gchar **strv;
|
||||
guint length, ii;
|
||||
|
||||
strv = g_strsplit (csv, ",", 0);
|
||||
length = g_strv_length (strv);
|
||||
|
||||
for (ii = 0; ii < length; ii++)
|
||||
if (*g_strstrip (strv[ii]) != '\0')
|
||||
list = g_list_prepend (list, g_strdup (strv[ii]));
|
||||
|
||||
g_strfreev (strv);
|
||||
|
||||
return g_list_reverse (list);
|
||||
}
|
||||
|
||||
static void
|
||||
composer_post_header_changed_cb (EComposerPostHeader *header)
|
||||
{
|
||||
header->priv->custom = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
composer_post_header_clicked_cb (EComposerPostHeader *header)
|
||||
{
|
||||
EMFolderTreeModel *model;
|
||||
GtkWidget *folder_tree;
|
||||
GtkWidget *dialog;
|
||||
GList *list;
|
||||
|
||||
model = mail_component_peek_tree_model (mail_component_peek ());
|
||||
folder_tree = em_folder_tree_new_with_model (model);
|
||||
|
||||
em_folder_tree_set_multiselect (
|
||||
EM_FOLDER_TREE (folder_tree), TRUE);
|
||||
em_folder_tree_set_excluded (
|
||||
EM_FOLDER_TREE (folder_tree),
|
||||
EMFT_EXCLUDE_NOSELECT |
|
||||
EMFT_EXCLUDE_VIRTUAL |
|
||||
EMFT_EXCLUDE_VTRASH);
|
||||
|
||||
dialog = em_folder_selector_new (
|
||||
EM_FOLDER_TREE (folder_tree),
|
||||
EM_FOLDER_SELECTOR_CAN_CREATE,
|
||||
_("Posting destination"),
|
||||
_("Choose folders to post the message to."),
|
||||
NULL);
|
||||
|
||||
list = e_composer_post_header_get_folders (header);
|
||||
em_folder_selector_set_selected_list (
|
||||
EM_FOLDER_SELECTOR (dialog), list);
|
||||
g_list_foreach (list, (GFunc) g_free, NULL);
|
||||
g_list_free (list);
|
||||
|
||||
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
|
||||
list = em_folder_selector_get_selected_uris (
|
||||
EM_FOLDER_SELECTOR (dialog));
|
||||
e_composer_post_header_set_folders (header, list);
|
||||
header->priv->custom = FALSE;
|
||||
g_list_foreach (list, (GFunc) g_free, NULL);
|
||||
g_list_free (list);
|
||||
}
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
|
||||
static GObject *
|
||||
composer_post_header_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_properties)
|
||||
{
|
||||
GObject *object;
|
||||
|
||||
/* Chain up to parent's constructor() method. */
|
||||
object = G_OBJECT_CLASS (parent_class)->constructor (
|
||||
type, n_construct_properties, construct_properties);
|
||||
|
||||
e_composer_header_set_title_tooltip (
|
||||
E_COMPOSER_HEADER (object),
|
||||
_("Click here to select folders to post to"));
|
||||
|
||||
g_signal_connect (
|
||||
object, "changed",
|
||||
G_CALLBACK (composer_post_header_changed_cb), NULL);
|
||||
|
||||
g_signal_connect (
|
||||
object, "clicked",
|
||||
G_CALLBACK (composer_post_header_clicked_cb), NULL);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
static void
|
||||
composer_post_header_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
switch (property_id) {
|
||||
case PROP_ACCOUNT:
|
||||
e_composer_post_header_set_account (
|
||||
E_COMPOSER_POST_HEADER (object),
|
||||
g_value_get_object (value));
|
||||
return;
|
||||
}
|
||||
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
composer_post_header_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
switch (property_id) {
|
||||
case PROP_ACCOUNT:
|
||||
g_value_set_object (
|
||||
value, e_composer_post_header_get_account (
|
||||
E_COMPOSER_POST_HEADER (object)));
|
||||
return;
|
||||
}
|
||||
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
composer_post_header_dispose (GObject *object)
|
||||
{
|
||||
EComposerPostHeaderPrivate *priv;
|
||||
|
||||
priv = E_COMPOSER_POST_HEADER_GET_PRIVATE (object);
|
||||
|
||||
if (priv->account != NULL) {
|
||||
g_object_unref (priv->account);
|
||||
priv->account = NULL;
|
||||
}
|
||||
|
||||
/* Chain up to parent's dispose() method. */
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
composer_post_header_class_init (EComposerPostHeaderClass *class)
|
||||
{
|
||||
GObjectClass *object_class;
|
||||
|
||||
parent_class = g_type_class_peek_parent (class);
|
||||
g_type_class_add_private (class, sizeof (EComposerPostHeaderPrivate));
|
||||
|
||||
object_class = G_OBJECT_CLASS (class);
|
||||
object_class->constructor = composer_post_header_constructor;
|
||||
object_class->set_property = composer_post_header_set_property;
|
||||
object_class->get_property = composer_post_header_get_property;
|
||||
object_class->dispose = composer_post_header_dispose;
|
||||
|
||||
g_object_class_install_property (
|
||||
object_class,
|
||||
PROP_ACCOUNT,
|
||||
g_param_spec_object (
|
||||
"account",
|
||||
NULL,
|
||||
NULL,
|
||||
E_TYPE_ACCOUNT,
|
||||
G_PARAM_READWRITE));
|
||||
}
|
||||
|
||||
static void
|
||||
composer_post_header_init (EComposerPostHeader *header)
|
||||
{
|
||||
header->priv = E_COMPOSER_POST_HEADER_GET_PRIVATE (header);
|
||||
}
|
||||
|
||||
GType
|
||||
e_composer_post_header_get_type (void)
|
||||
{
|
||||
static GType type = 0;
|
||||
|
||||
if (G_UNLIKELY (type == 0)) {
|
||||
static const GTypeInfo type_info = {
|
||||
sizeof (EComposerPostHeaderClass),
|
||||
(GBaseInitFunc) NULL,
|
||||
(GBaseFinalizeFunc) NULL,
|
||||
(GClassInitFunc) composer_post_header_class_init,
|
||||
(GClassFinalizeFunc) NULL,
|
||||
NULL, /* class_data */
|
||||
sizeof (EComposerPostHeader),
|
||||
0, /* n_preallocs */
|
||||
(GInstanceInitFunc) composer_post_header_init,
|
||||
NULL /* value_table */
|
||||
};
|
||||
|
||||
type = g_type_register_static (
|
||||
E_TYPE_COMPOSER_TEXT_HEADER,
|
||||
"EComposerPostHeader", &type_info, 0);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
EComposerHeader *
|
||||
e_composer_post_header_new (const gchar *label)
|
||||
{
|
||||
return g_object_new (
|
||||
E_TYPE_COMPOSER_POST_HEADER,
|
||||
"label", label, "button", TRUE, NULL);
|
||||
}
|
||||
|
||||
EAccount *
|
||||
e_composer_post_header_get_account (EComposerPostHeader *header)
|
||||
{
|
||||
g_return_val_if_fail (E_IS_COMPOSER_POST_HEADER (header), NULL);
|
||||
|
||||
return header->priv->account;
|
||||
}
|
||||
|
||||
void
|
||||
e_composer_post_header_set_account (EComposerPostHeader *header,
|
||||
EAccount *account)
|
||||
{
|
||||
GList *folders = NULL;
|
||||
|
||||
g_return_if_fail (E_IS_COMPOSER_POST_HEADER (header));
|
||||
|
||||
if (account != NULL) {
|
||||
g_return_if_fail (E_IS_ACCOUNT (account));
|
||||
g_object_ref (account);
|
||||
}
|
||||
|
||||
if (!header->priv->custom)
|
||||
folders = e_composer_post_header_get_folders (header);
|
||||
|
||||
if (header->priv->account != NULL)
|
||||
g_object_unref (header->priv->account);
|
||||
|
||||
header->priv->account = account;
|
||||
composer_post_header_set_base_url (header);
|
||||
|
||||
/* Make folders relative to the new account. */
|
||||
if (!header->priv->custom) {
|
||||
e_composer_post_header_set_folders (header, folders);
|
||||
g_list_foreach (folders, (GFunc) g_free, NULL);
|
||||
g_list_free (folders);
|
||||
}
|
||||
|
||||
g_object_notify (G_OBJECT (header), "account");
|
||||
}
|
||||
|
||||
GList *
|
||||
e_composer_post_header_get_folders (EComposerPostHeader *header)
|
||||
{
|
||||
GList *folders, *iter;
|
||||
gchar *base_url;
|
||||
|
||||
g_return_val_if_fail (E_IS_COMPOSER_POST_HEADER (header), NULL);
|
||||
|
||||
folders = composer_post_header_split_csv (
|
||||
e_composer_text_header_get_text (
|
||||
E_COMPOSER_TEXT_HEADER (header)));
|
||||
|
||||
base_url = header->priv->base_url;
|
||||
if (base_url == NULL)
|
||||
return folders;
|
||||
|
||||
for (iter = folders; iter != NULL; iter = iter->next) {
|
||||
/* Convert relative folder names to absolute. */
|
||||
/* XXX Should use CamelURL for this. */
|
||||
if (strstr (iter->data, ":/") == NULL) {
|
||||
gchar *abs_url;
|
||||
|
||||
abs_url = g_strconcat (base_url, iter->data, NULL);
|
||||
g_free (iter->data);
|
||||
iter->data = abs_url;
|
||||
}
|
||||
}
|
||||
|
||||
return folders;
|
||||
}
|
||||
|
||||
void
|
||||
e_composer_post_header_set_folders (EComposerPostHeader *header,
|
||||
GList *folders)
|
||||
{
|
||||
GList *iter;
|
||||
gint ii = 0;
|
||||
gchar **strv;
|
||||
gchar *text;
|
||||
gboolean custom_save;
|
||||
|
||||
g_return_if_fail (E_IS_COMPOSER_POST_HEADER (header));
|
||||
|
||||
strv = g_new0 (gchar *, g_list_length (folders) + 1);
|
||||
|
||||
for (iter = folders; iter != NULL; iter = iter->next)
|
||||
strv[ii++] = composer_post_header_folder_name_to_string (
|
||||
header, iter->data);
|
||||
|
||||
text = g_strjoinv (", ", strv);
|
||||
custom_save = header->priv->custom;
|
||||
e_composer_text_header_set_text (
|
||||
E_COMPOSER_TEXT_HEADER (header), text);
|
||||
header->priv->custom = custom_save;
|
||||
g_free (text);
|
||||
|
||||
g_strfreev (strv);
|
||||
}
|
||||
|
||||
void
|
||||
e_composer_post_header_set_folders_base (EComposerPostHeader *header,
|
||||
const gchar *base_url,
|
||||
const gchar *folders)
|
||||
{
|
||||
GList *list, *iter;
|
||||
|
||||
list = composer_post_header_split_csv (folders);
|
||||
for (iter = list; iter != NULL; iter = iter->next) {
|
||||
gchar *abs_url;
|
||||
|
||||
/* FIXME This doesn't handle all folder names properly. */
|
||||
abs_url = g_strdup_printf (
|
||||
"%s/%s", base_url, (gchar *) iter->data);
|
||||
g_free (iter->data);
|
||||
iter->data = abs_url;
|
||||
}
|
||||
|
||||
e_composer_post_header_set_folders (header, list);
|
||||
g_list_foreach (list, (GFunc) g_free, NULL);
|
||||
g_list_free (list);
|
||||
}
|
||||
63
composer/e-composer-post-header.h
Normal file
63
composer/e-composer-post-header.h
Normal file
@ -0,0 +1,63 @@
|
||||
#ifndef E_COMPOSER_POST_HEADER_H
|
||||
#define E_COMPOSER_POST_HEADER_H
|
||||
|
||||
#include "e-composer-common.h"
|
||||
|
||||
#include <libedataserver/e-account.h>
|
||||
|
||||
#include "e-composer-text-header.h"
|
||||
|
||||
/* Standard GObject macros */
|
||||
#define E_TYPE_COMPOSER_POST_HEADER \
|
||||
(e_composer_post_header_get_type ())
|
||||
#define E_COMPOSER_POST_HEADER(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST \
|
||||
((obj), E_TYPE_COMPOSER_POST_HEADER, EComposerPostHeader))
|
||||
#define E_COMPOSER_POST_HEADER_CLASS(cls) \
|
||||
(G_TYPE_CHECK_CLASS_CAST \
|
||||
((cls), E_TYPE_COMPOSER_POST_HEADER, EComposerPostHeaderClass))
|
||||
#define E_IS_COMPOSER_POST_HEADER(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE \
|
||||
((obj), E_TYPE_COMPOSER_POST_HEADER))
|
||||
#define E_IS_COMPOSER_POST_HEADER_CLASS(cls) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE \
|
||||
((cls), E_TYPE_COMPOSER_POST_HEADER))
|
||||
#define E_COMPOSER_POST_HEADER_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS \
|
||||
((obj), E_TYPE_COMPOSER_POST_HEADER, EComposerPostHeaderClass))
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _EComposerPostHeader EComposerPostHeader;
|
||||
typedef struct _EComposerPostHeaderClass EComposerPostHeaderClass;
|
||||
typedef struct _EComposerPostHeaderPrivate EComposerPostHeaderPrivate;
|
||||
|
||||
struct _EComposerPostHeader {
|
||||
EComposerTextHeader parent;
|
||||
EComposerPostHeaderPrivate *priv;
|
||||
};
|
||||
|
||||
struct _EComposerPostHeaderClass {
|
||||
EComposerTextHeaderClass parent_class;
|
||||
};
|
||||
|
||||
GType e_composer_post_header_get_type (void);
|
||||
EComposerHeader * e_composer_post_header_new (const gchar *label);
|
||||
EAccount * e_composer_post_header_get_account
|
||||
(EComposerPostHeader *header);
|
||||
void e_composer_post_header_set_account
|
||||
(EComposerPostHeader *header,
|
||||
EAccount *account);
|
||||
GList * e_composer_post_header_get_folders
|
||||
(EComposerPostHeader *header);
|
||||
void e_composer_post_header_set_folders
|
||||
(EComposerPostHeader *header,
|
||||
GList *folders);
|
||||
void e_composer_post_header_set_folders_base
|
||||
(EComposerPostHeader *header,
|
||||
const gchar *base_url,
|
||||
const gchar *folders);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* E_COMPOSER_POST_HEADER_H */
|
||||
120
composer/e-composer-text-header.c
Normal file
120
composer/e-composer-text-header.c
Normal file
@ -0,0 +1,120 @@
|
||||
#include "e-composer-text-header.h"
|
||||
|
||||
static gpointer parent_class;
|
||||
|
||||
static void
|
||||
composer_text_header_changed_cb (GtkEntry *entry,
|
||||
EComposerTextHeader *header)
|
||||
{
|
||||
g_signal_emit_by_name (header, "changed");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
composer_text_header_query_tooltip_cb (GtkEntry *entry,
|
||||
gint x,
|
||||
gint y,
|
||||
gboolean keyboard_mode,
|
||||
GtkTooltip *tooltip)
|
||||
{
|
||||
const gchar *text;
|
||||
|
||||
text = gtk_entry_get_text (entry);
|
||||
|
||||
if (keyboard_mode || text == NULL || *text == '\0')
|
||||
return FALSE;
|
||||
|
||||
gtk_tooltip_set_text (tooltip, text);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
composer_text_header_class_init (EComposerTextHeaderClass *class)
|
||||
{
|
||||
parent_class = g_type_class_peek_parent (class);
|
||||
}
|
||||
|
||||
static void
|
||||
composer_text_header_init (EComposerTextHeader *header)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = g_object_ref_sink (gtk_entry_new ());
|
||||
g_signal_connect (
|
||||
widget, "changed",
|
||||
G_CALLBACK (composer_text_header_changed_cb), header);
|
||||
g_signal_connect (
|
||||
widget, "query-tooltip",
|
||||
G_CALLBACK (composer_text_header_query_tooltip_cb), NULL);
|
||||
gtk_widget_set_has_tooltip (widget, TRUE);
|
||||
E_COMPOSER_HEADER (header)->input_widget = widget;
|
||||
}
|
||||
|
||||
GType
|
||||
e_composer_text_header_get_type (void)
|
||||
{
|
||||
static GType type = 0;
|
||||
|
||||
if (G_UNLIKELY (type == 0)) {
|
||||
static const GTypeInfo type_info = {
|
||||
sizeof (EComposerTextHeaderClass),
|
||||
(GBaseInitFunc) NULL,
|
||||
(GBaseFinalizeFunc) NULL,
|
||||
(GClassInitFunc) composer_text_header_class_init,
|
||||
(GClassFinalizeFunc) NULL,
|
||||
NULL, /* class_data */
|
||||
sizeof (EComposerTextHeader),
|
||||
0, /* n_preallocs */
|
||||
(GInstanceInitFunc) composer_text_header_init,
|
||||
NULL /* value_table */
|
||||
};
|
||||
|
||||
type = g_type_register_static (
|
||||
E_TYPE_COMPOSER_HEADER, "EComposerTextHeader",
|
||||
&type_info, 0);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
EComposerHeader *
|
||||
e_composer_text_header_new_label (const gchar *label)
|
||||
{
|
||||
return g_object_new (
|
||||
E_TYPE_COMPOSER_TEXT_HEADER, "label", label,
|
||||
"button", FALSE, NULL);
|
||||
}
|
||||
|
||||
EComposerHeader *
|
||||
e_composer_text_header_new_button (const gchar *label)
|
||||
{
|
||||
return g_object_new (
|
||||
E_TYPE_COMPOSER_TEXT_HEADER, "label", label,
|
||||
"button", TRUE, NULL);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
e_composer_text_header_get_text (EComposerTextHeader *header)
|
||||
{
|
||||
GtkWidget *input_widget;
|
||||
|
||||
g_return_val_if_fail (E_IS_COMPOSER_TEXT_HEADER (header), NULL);
|
||||
|
||||
input_widget = E_COMPOSER_HEADER (header)->input_widget;
|
||||
return gtk_entry_get_text (GTK_ENTRY (input_widget));
|
||||
}
|
||||
|
||||
void
|
||||
e_composer_text_header_set_text (EComposerTextHeader *header,
|
||||
const gchar *text)
|
||||
{
|
||||
GtkWidget *input_widget;
|
||||
|
||||
g_return_if_fail (E_IS_COMPOSER_TEXT_HEADER (header));
|
||||
|
||||
if (text == NULL)
|
||||
text = "";
|
||||
|
||||
input_widget = E_COMPOSER_HEADER (header)->input_widget;
|
||||
gtk_entry_set_text (GTK_ENTRY (input_widget), text);
|
||||
}
|
||||
50
composer/e-composer-text-header.h
Normal file
50
composer/e-composer-text-header.h
Normal file
@ -0,0 +1,50 @@
|
||||
#ifndef E_COMPOSER_TEXT_HEADER_H
|
||||
#define E_COMPOSER_TEXT_HEADER_H
|
||||
|
||||
#include "e-composer-common.h"
|
||||
#include "e-composer-header.h"
|
||||
|
||||
/* Standard GObject macros */
|
||||
#define E_TYPE_COMPOSER_TEXT_HEADER \
|
||||
(e_composer_text_header_get_type ())
|
||||
#define E_COMPOSER_TEXT_HEADER(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST \
|
||||
((obj), E_TYPE_COMPOSER_TEXT_HEADER, EComposerTextHeader))
|
||||
#define E_COMPOSER_TEXT_HEADER_CLASS(cls) \
|
||||
(G_TYPE_CHECK_CLASS_CAST \
|
||||
((cls), E_TYPE_COMPOSER_TEXT_HEADER, EComposerTextHeaderClass))
|
||||
#define E_IS_COMPOSER_TEXT_HEADER(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE \
|
||||
((obj), E_TYPE_COMPOSER_TEXT_HEADER))
|
||||
#define E_IS_COMPOSER_TEXT_HEADER_CLASS(cls) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE \
|
||||
((cls), E_TYPE_COMPOSER_TEXT_HEADER))
|
||||
#define E_COMPOSER_TEXT_HEADER_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS \
|
||||
((obj), E_TYPE_COMPOSER_TEXT_HEADER, EComposerTextHeaderClass))
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _EComposerTextHeader EComposerTextHeader;
|
||||
typedef struct _EComposerTextHeaderClass EComposerTextHeaderClass;
|
||||
|
||||
struct _EComposerTextHeader {
|
||||
EComposerHeader parent;
|
||||
};
|
||||
|
||||
struct _EComposerTextHeaderClass {
|
||||
EComposerHeaderClass parent_class;
|
||||
};
|
||||
|
||||
GType e_composer_text_header_get_type (void);
|
||||
EComposerHeader * e_composer_text_header_new_label
|
||||
(const gchar *label);
|
||||
EComposerHeader * e_composer_text_header_new_button
|
||||
(const gchar *label);
|
||||
const gchar * e_composer_text_header_get_text (EComposerTextHeader *header);
|
||||
void e_composer_text_header_set_text (EComposerTextHeader *header,
|
||||
const gchar *text);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* E_COMPOSER_TEXT_HEADER_H */
|
||||
File diff suppressed because it is too large
Load Diff
@ -21,11 +21,10 @@
|
||||
* Author: Ettore Perazzoli
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ___E_MSG_COMPOSER_HDRS_H__
|
||||
#define ___E_MSG_COMPOSER_HDRS_H__
|
||||
|
||||
#include <gtk/gtktable.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <bonobo/bonobo-ui-component.h>
|
||||
|
||||
@ -33,20 +32,28 @@
|
||||
#include <camel/camel-mime-message.h>
|
||||
#include <libebook/e-destination.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#pragma }
|
||||
#endif /* __cplusplus */
|
||||
#define E_TYPE_MSG_COMPOSER_HDRS \
|
||||
(e_msg_composer_hdrs_get_type ())
|
||||
#define E_MSG_COMPOSER_HDRS(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST \
|
||||
((obj), E_TYPE_MSG_COMPOSER_HDRS, EMsgComposerHdrs))
|
||||
#define E_MSG_COMPOSER_HDRS_CLASS(cls) \
|
||||
(G_TYPE_CHECK_CLASS_CAST \
|
||||
((cls), E_TYPE_MSG_COMPOSER_HDRS, EMsgComposerHdrsClass))
|
||||
#define E_IS_MSG_COMPOSER_HDRS(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE \
|
||||
((obj), E_TYPE_MSG_COMPOSER_HDRS))
|
||||
#define E_IS_MSG_COMPOSER_HDRS_CLASS(cls) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE \
|
||||
((cls), E_TYPE_MSG_COMPOSER_HDRS))
|
||||
#define E_MSG_COMPOSER_HDRS_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS \
|
||||
((obj), E_TYPE_MSG_COMPOSER_HDRS, EMsgComposerHdrsClass))
|
||||
|
||||
#define E_TYPE_MSG_COMPOSER_HDRS (e_msg_composer_hdrs_get_type ())
|
||||
#define E_MSG_COMPOSER_HDRS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_MSG_COMPOSER_HDRS, EMsgComposerHdrs))
|
||||
#define E_MSG_COMPOSER_HDRS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_MSG_COMPOSER_HDRS, EMsgComposerHdrsClass))
|
||||
#define E_IS_MSG_COMPOSER_HDRS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_MSG_COMPOSER_HDRS))
|
||||
#define E_IS_MSG_COMPOSER_HDRS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_MSG_COMPOSER_HDRS))
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
typedef struct _EMsgComposerHdrs EMsgComposerHdrs;
|
||||
typedef struct _EMsgComposerHdrsClass EMsgComposerHdrsClass;
|
||||
typedef struct _EMsgComposerHdrs EMsgComposerHdrs;
|
||||
typedef struct _EMsgComposerHdrsClass EMsgComposerHdrsClass;
|
||||
typedef struct _EMsgComposerHdrsPrivate EMsgComposerHdrsPrivate;
|
||||
|
||||
struct _EMsgComposerHdrs {
|
||||
@ -54,18 +61,12 @@ struct _EMsgComposerHdrs {
|
||||
|
||||
EMsgComposerHdrsPrivate *priv;
|
||||
|
||||
EAccount *account;
|
||||
|
||||
guint32 visible_mask;
|
||||
|
||||
gboolean has_changed;
|
||||
};
|
||||
|
||||
struct _EMsgComposerHdrsClass {
|
||||
GtkTableClass parent_class;
|
||||
|
||||
void (* show_address_dialog) (EMsgComposerHdrs *hdrs);
|
||||
|
||||
void (* subject_changed) (EMsgComposerHdrs *hdrs, gchar *subject);
|
||||
|
||||
void (* hdrs_changed) (EMsgComposerHdrs *hdrs);
|
||||
@ -79,19 +80,32 @@ typedef enum {
|
||||
E_MSG_COMPOSER_VISIBLE_TO = (1 << 2),
|
||||
E_MSG_COMPOSER_VISIBLE_CC = (1 << 3),
|
||||
E_MSG_COMPOSER_VISIBLE_BCC = (1 << 4),
|
||||
E_MSG_COMPOSER_VISIBLE_POSTTO = (1 << 5), /* for posting to folders */
|
||||
E_MSG_COMPOSER_VISIBLE_POSTTO = (1 << 5),
|
||||
E_MSG_COMPOSER_VISIBLE_SUBJECT = (1 << 7)
|
||||
} EMsgComposerHeaderVisibleFlags;
|
||||
|
||||
#define E_MSG_COMPOSER_VISIBLE_MASK_SENDER (E_MSG_COMPOSER_VISIBLE_FROM | E_MSG_COMPOSER_VISIBLE_REPLYTO)
|
||||
#define E_MSG_COMPOSER_VISIBLE_MASK_BASIC (E_MSG_COMPOSER_VISIBLE_MASK_SENDER | E_MSG_COMPOSER_VISIBLE_SUBJECT)
|
||||
#define E_MSG_COMPOSER_VISIBLE_MASK_RECIPIENTS (E_MSG_COMPOSER_VISIBLE_TO | E_MSG_COMPOSER_VISIBLE_CC | E_MSG_COMPOSER_VISIBLE_BCC)
|
||||
#define E_MSG_COMPOSER_VISIBLE_MASK_SENDER \
|
||||
(E_MSG_COMPOSER_VISIBLE_FROM | \
|
||||
E_MSG_COMPOSER_VISIBLE_REPLYTO)
|
||||
|
||||
#define E_MSG_COMPOSER_VISIBLE_MASK_MAIL (E_MSG_COMPOSER_VISIBLE_MASK_BASIC | E_MSG_COMPOSER_VISIBLE_MASK_RECIPIENTS)
|
||||
#define E_MSG_COMPOSER_VISIBLE_MASK_POST (E_MSG_COMPOSER_VISIBLE_MASK_BASIC | E_MSG_COMPOSER_VISIBLE_POSTTO)
|
||||
#define E_MSG_COMPOSER_VISIBLE_MASK_BASIC \
|
||||
(E_MSG_COMPOSER_VISIBLE_MASK_SENDER | \
|
||||
E_MSG_COMPOSER_VISIBLE_SUBJECT)
|
||||
|
||||
#define E_MSG_COMPOSER_VISIBLE_MASK_RECIPIENTS \
|
||||
(E_MSG_COMPOSER_VISIBLE_TO | \
|
||||
E_MSG_COMPOSER_VISIBLE_CC | \
|
||||
E_MSG_COMPOSER_VISIBLE_BCC)
|
||||
|
||||
GtkType e_msg_composer_hdrs_get_type (void);
|
||||
#define E_MSG_COMPOSER_VISIBLE_MASK_MAIL \
|
||||
(E_MSG_COMPOSER_VISIBLE_MASK_BASIC | \
|
||||
E_MSG_COMPOSER_VISIBLE_MASK_RECIPIENTS)
|
||||
|
||||
#define E_MSG_COMPOSER_VISIBLE_MASK_POST \
|
||||
(E_MSG_COMPOSER_VISIBLE_MASK_BASIC | \
|
||||
E_MSG_COMPOSER_VISIBLE_POSTTO)
|
||||
|
||||
GType e_msg_composer_hdrs_get_type (void);
|
||||
GtkWidget *e_msg_composer_hdrs_new (BonoboUIComponent *uic, int visible_mask, int visible_flags);
|
||||
|
||||
void e_msg_composer_hdrs_to_message (EMsgComposerHdrs *hdrs,
|
||||
@ -101,7 +115,8 @@ void e_msg_composer_hdrs_to_redirect (EMsgComposerHdrs *hdrs,
|
||||
CamelMimeMessage *msg);
|
||||
|
||||
|
||||
void e_msg_composer_hdrs_set_from_account (EMsgComposerHdrs *hdrs,
|
||||
EAccount * e_msg_composer_hdrs_get_from_account (EMsgComposerHdrs *hdrs);
|
||||
gboolean e_msg_composer_hdrs_set_from_account (EMsgComposerHdrs *hdrs,
|
||||
const char *account_name);
|
||||
void e_msg_composer_hdrs_set_reply_to (EMsgComposerHdrs *hdrs,
|
||||
const char *reply_to);
|
||||
@ -116,8 +131,8 @@ void e_msg_composer_hdrs_set_post_to (EMsgComposerHdrs *hdrs,
|
||||
void e_msg_composer_hdrs_set_post_to_list (EMsgComposerHdrs *hdrs,
|
||||
GList *urls);
|
||||
void e_msg_composer_hdrs_set_post_to_base (EMsgComposerHdrs *hdrs,
|
||||
const char *base,
|
||||
const char *post_to);
|
||||
const gchar *base,
|
||||
const gchar *post_to);
|
||||
void e_msg_composer_hdrs_set_subject (EMsgComposerHdrs *hdrs,
|
||||
const char *subject);
|
||||
|
||||
@ -134,7 +149,6 @@ const char *e_msg_composer_hdrs_get_subject (EMsgComposerHdrs *hdrs);
|
||||
GList *e_msg_composer_hdrs_get_post_to (EMsgComposerHdrs *hdrs);
|
||||
|
||||
GtkWidget *e_msg_composer_hdrs_get_from_hbox (EMsgComposerHdrs *hdrs);
|
||||
GtkWidget *e_msg_composer_hdrs_get_from_omenu (EMsgComposerHdrs *hdrs);
|
||||
GtkWidget *e_msg_composer_hdrs_get_reply_to_entry (EMsgComposerHdrs *hdrs);
|
||||
GtkWidget *e_msg_composer_hdrs_get_to_entry (EMsgComposerHdrs *hdrs);
|
||||
GtkWidget *e_msg_composer_hdrs_get_cc_entry (EMsgComposerHdrs *hdrs);
|
||||
@ -147,9 +161,6 @@ void e_msg_composer_hdrs_set_visible_mask (EMsgComposerHdrs *hdrs,
|
||||
void e_msg_composer_hdrs_set_visible (EMsgComposerHdrs *hdrs,
|
||||
int visible_flags);
|
||||
|
||||
#ifdef _cplusplus
|
||||
}
|
||||
#endif /* _cplusplus */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __E_MSG_COMPOSER_HDRS_H__ */
|
||||
|
||||
@ -520,9 +520,12 @@ build_message (EMsgComposer *composer, gboolean save_html_object_data)
|
||||
CamelMimePart *part;
|
||||
CamelException ex;
|
||||
GByteArray *data;
|
||||
EAccount *account;
|
||||
char *charset;
|
||||
int i;
|
||||
|
||||
account = e_msg_composer_hdrs_get_from_account (hdrs);
|
||||
|
||||
if (p->persist_stream_interface == CORBA_OBJECT_NIL)
|
||||
return NULL;
|
||||
|
||||
@ -543,9 +546,9 @@ build_message (EMsgComposer *composer, gboolean save_html_object_data)
|
||||
|
||||
/* Message Disposition Notification */
|
||||
if (p->request_receipt) {
|
||||
char *mdn_address = hdrs->account->id->reply_to;
|
||||
char *mdn_address = account->id->reply_to;
|
||||
if (!mdn_address || !*mdn_address)
|
||||
mdn_address = hdrs->account->id->address;
|
||||
mdn_address = account->id->address;
|
||||
|
||||
camel_medium_add_header (CAMEL_MEDIUM (new), "Disposition-Notification-To", mdn_address);
|
||||
}
|
||||
@ -747,8 +750,8 @@ build_message (EMsgComposer *composer, gboolean save_html_object_data)
|
||||
camel_mime_part_set_encoding (part, plain_encoding);
|
||||
camel_object_unref (current);
|
||||
|
||||
if (hdrs->account && hdrs->account->pgp_key && *hdrs->account->pgp_key) {
|
||||
pgp_userid = hdrs->account->pgp_key;
|
||||
if (account && account->pgp_key && *account->pgp_key) {
|
||||
pgp_userid = account->pgp_key;
|
||||
} else {
|
||||
from = e_msg_composer_hdrs_get_from(hdrs);
|
||||
camel_internet_address_get(from, 0, NULL, &pgp_userid);
|
||||
@ -757,7 +760,7 @@ build_message (EMsgComposer *composer, gboolean save_html_object_data)
|
||||
if (p->pgp_sign) {
|
||||
CamelMimePart *npart = camel_mime_part_new();
|
||||
|
||||
cipher = mail_crypto_get_pgp_cipher_context(hdrs->account);
|
||||
cipher = mail_crypto_get_pgp_cipher_context(account);
|
||||
camel_cipher_sign(cipher, pgp_userid, CAMEL_CIPHER_HASH_SHA1, part, npart, &ex);
|
||||
camel_object_unref(cipher);
|
||||
|
||||
@ -774,14 +777,14 @@ build_message (EMsgComposer *composer, gboolean save_html_object_data)
|
||||
CamelMimePart *npart = camel_mime_part_new();
|
||||
|
||||
/* check to see if we should encrypt to self, NB gets removed immediately after use */
|
||||
if (hdrs->account && hdrs->account->pgp_encrypt_to_self && pgp_userid)
|
||||
if (account && account->pgp_encrypt_to_self && pgp_userid)
|
||||
g_ptr_array_add (recipients, g_strdup (pgp_userid));
|
||||
|
||||
cipher = mail_crypto_get_pgp_cipher_context (hdrs->account);
|
||||
cipher = mail_crypto_get_pgp_cipher_context (account);
|
||||
camel_cipher_encrypt(cipher, pgp_userid, recipients, part, npart, &ex);
|
||||
camel_object_unref (cipher);
|
||||
|
||||
if (hdrs->account && hdrs->account->pgp_encrypt_to_self && pgp_userid)
|
||||
if (account && account->pgp_encrypt_to_self && pgp_userid)
|
||||
g_ptr_array_set_size(recipients, recipients->len - 1);
|
||||
|
||||
if (camel_exception_is_set (&ex)) {
|
||||
@ -813,14 +816,14 @@ build_message (EMsgComposer *composer, gboolean save_html_object_data)
|
||||
camel_object_unref(current);
|
||||
|
||||
if (p->smime_sign
|
||||
&& (hdrs->account == NULL || hdrs->account->smime_sign_key == NULL || hdrs->account->smime_sign_key[0] == 0)) {
|
||||
&& (account == NULL || account->smime_sign_key == NULL || account->smime_sign_key[0] == 0)) {
|
||||
camel_exception_set (&ex, CAMEL_EXCEPTION_SYSTEM,
|
||||
_("Cannot sign outgoing message: No signing certificate set for this account"));
|
||||
goto exception;
|
||||
}
|
||||
|
||||
if (p->smime_encrypt
|
||||
&& (hdrs->account == NULL || hdrs->account->smime_sign_key == NULL || hdrs->account->smime_sign_key[0] == 0)) {
|
||||
&& (account == NULL || account->smime_sign_key == NULL || account->smime_sign_key[0] == 0)) {
|
||||
camel_exception_set (&ex, CAMEL_EXCEPTION_SYSTEM,
|
||||
_("Cannot encrypt outgoing message: No encryption certificate set for this account"));
|
||||
goto exception;
|
||||
@ -834,12 +837,12 @@ build_message (EMsgComposer *composer, gboolean save_html_object_data)
|
||||
/* if we're also encrypting, envelope-sign rather than clear-sign */
|
||||
if (p->smime_encrypt) {
|
||||
camel_smime_context_set_sign_mode((CamelSMIMEContext *)cipher, CAMEL_SMIME_SIGN_ENVELOPED);
|
||||
camel_smime_context_set_encrypt_key((CamelSMIMEContext *)cipher, TRUE, hdrs->account->smime_encrypt_key);
|
||||
} else if (hdrs->account && hdrs->account->smime_encrypt_key && *hdrs->account->smime_encrypt_key) {
|
||||
camel_smime_context_set_encrypt_key((CamelSMIMEContext *)cipher, TRUE, hdrs->account->smime_encrypt_key);
|
||||
camel_smime_context_set_encrypt_key((CamelSMIMEContext *)cipher, TRUE, account->smime_encrypt_key);
|
||||
} else if (account && account->smime_encrypt_key && *account->smime_encrypt_key) {
|
||||
camel_smime_context_set_encrypt_key((CamelSMIMEContext *)cipher, TRUE, account->smime_encrypt_key);
|
||||
}
|
||||
|
||||
camel_cipher_sign(cipher, hdrs->account->smime_sign_key, CAMEL_CIPHER_HASH_SHA1, part, npart, &ex);
|
||||
camel_cipher_sign(cipher, account->smime_sign_key, CAMEL_CIPHER_HASH_SHA1, part, npart, &ex);
|
||||
camel_object_unref(cipher);
|
||||
|
||||
if (camel_exception_is_set(&ex)) {
|
||||
@ -853,11 +856,11 @@ build_message (EMsgComposer *composer, gboolean save_html_object_data)
|
||||
|
||||
if (p->smime_encrypt) {
|
||||
/* check to see if we should encrypt to self, NB removed after use */
|
||||
if (hdrs->account->smime_encrypt_to_self)
|
||||
g_ptr_array_add(recipients, g_strdup (hdrs->account->smime_encrypt_key));
|
||||
if (account->smime_encrypt_to_self)
|
||||
g_ptr_array_add(recipients, g_strdup (account->smime_encrypt_key));
|
||||
|
||||
cipher = camel_smime_context_new(session);
|
||||
camel_smime_context_set_encrypt_key((CamelSMIMEContext *)cipher, TRUE, hdrs->account->smime_encrypt_key);
|
||||
camel_smime_context_set_encrypt_key((CamelSMIMEContext *)cipher, TRUE, account->smime_encrypt_key);
|
||||
|
||||
camel_cipher_encrypt(cipher, NULL, recipients, part, (CamelMimePart *)new, &ex);
|
||||
camel_object_unref(cipher);
|
||||
@ -865,7 +868,7 @@ build_message (EMsgComposer *composer, gboolean save_html_object_data)
|
||||
if (camel_exception_is_set(&ex))
|
||||
goto exception;
|
||||
|
||||
if (hdrs->account->smime_encrypt_to_self)
|
||||
if (account->smime_encrypt_to_self)
|
||||
g_ptr_array_set_size(recipients, recipients->len - 1);
|
||||
}
|
||||
|
||||
@ -1186,7 +1189,8 @@ get_signature_html (EMsgComposer *composer)
|
||||
char *address;
|
||||
char *name;
|
||||
|
||||
id = E_MSG_COMPOSER_HDRS (p->hdrs)->account->id;
|
||||
id = e_msg_composer_hdrs_get_from_account (
|
||||
E_MSG_COMPOSER_HDRS (p->hdrs))->id;
|
||||
address = id->address ? camel_text_to_html (id->address, CONVERT_SPACES, 0) : NULL;
|
||||
name = id->name ? camel_text_to_html (id->name, CONVERT_SPACES, 0) : NULL;
|
||||
organization = id->organization ? camel_text_to_html (id->organization, CONVERT_SPACES, 0) : NULL;
|
||||
@ -2737,10 +2741,11 @@ from_changed_cb (EMsgComposerHdrs *hdrs, void *data)
|
||||
{
|
||||
EMsgComposer *composer = E_MSG_COMPOSER (data);
|
||||
EMsgComposerPrivate *p = composer->priv;
|
||||
EAccount *account;
|
||||
|
||||
if (hdrs->account) {
|
||||
EAccount *account = hdrs->account;
|
||||
account = e_msg_composer_hdrs_get_from_account (hdrs);
|
||||
|
||||
if (account) {
|
||||
e_msg_composer_set_pgp_sign (composer,
|
||||
account->pgp_always_sign &&
|
||||
(!account->pgp_no_imip_sign || !p->mime_type ||
|
||||
@ -4058,10 +4063,14 @@ set_editor_signature (EMsgComposer *composer)
|
||||
{
|
||||
EAccountIdentity *id;
|
||||
EMsgComposerPrivate *p = composer->priv;
|
||||
EAccount *account;
|
||||
|
||||
g_return_if_fail (E_MSG_COMPOSER_HDRS (p->hdrs)->account != NULL);
|
||||
account = e_msg_composer_hdrs_get_from_account (
|
||||
E_MSG_COMPOSER_HDRS (p->hdrs));
|
||||
|
||||
id = E_MSG_COMPOSER_HDRS (p->hdrs)->account->id;
|
||||
g_return_if_fail (account != NULL);
|
||||
|
||||
id = account->id;
|
||||
if (id->sig_uid)
|
||||
p->signature = mail_config_get_signature_by_uid (id->sig_uid);
|
||||
else
|
||||
@ -5133,7 +5142,10 @@ e_msg_composer_set_body (EMsgComposer *composer, const char *body,
|
||||
|
||||
if (g_ascii_strncasecmp (p->mime_type, "text/calendar", 13) == 0) {
|
||||
EMsgComposerHdrs *hdrs = E_MSG_COMPOSER_HDRS (p->hdrs);
|
||||
if (hdrs->account && hdrs->account->pgp_no_imip_sign)
|
||||
EAccount *account;
|
||||
|
||||
account = e_msg_composer_hdrs_get_from_account (hdrs);
|
||||
if (account && account->pgp_no_imip_sign)
|
||||
e_msg_composer_set_pgp_sign (composer, FALSE);
|
||||
}
|
||||
}
|
||||
@ -5608,7 +5620,7 @@ e_msg_composer_get_preferred_account (EMsgComposer *composer)
|
||||
|
||||
hdrs = E_MSG_COMPOSER_HDRS (p->hdrs);
|
||||
|
||||
return hdrs->account;
|
||||
return e_msg_composer_hdrs_get_from_account (hdrs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,3 +1,10 @@
|
||||
2007-11-27 Matthew Barnes <mbarnes@redhat.com>
|
||||
|
||||
** Fixes part of bug #495123
|
||||
|
||||
* mail-session.c (mail_session_init):
|
||||
Pass the CamelSession to the EAccountComboBox class (ugly hack).
|
||||
|
||||
2007-11-26 Nicholas Miell <nmiell@gmail.com>
|
||||
|
||||
** Fix for bug #216485
|
||||
|
||||
@ -656,6 +656,7 @@ mail_session_init (const char *base_directory)
|
||||
camel_provider_init();
|
||||
|
||||
session = CAMEL_SESSION (camel_object_new (MAIL_SESSION_TYPE));
|
||||
e_account_combo_box_set_session (session); /* XXX Don't ask... */
|
||||
|
||||
camel_dir = g_strdup_printf ("%s/mail", base_directory);
|
||||
camel_session_construct (session, camel_dir);
|
||||
|
||||
@ -1,3 +1,10 @@
|
||||
2007-11-27 Matthew Barnes <mbarnes@redhat.com>
|
||||
|
||||
** Fixes part of bug #495123
|
||||
|
||||
* exchange-mail-send-options.c (append_to_header):
|
||||
Use e_msg_composer_hdrs_get_from_account() to obtain the EAccount.
|
||||
|
||||
2007-11-23 Milan Crha <mcrha@redhat.com>
|
||||
|
||||
** Fix for bug #479081
|
||||
|
||||
@ -123,10 +123,13 @@ append_to_header (ExchangeSendOptionsDialog *dialog, gint state, gpointer data)
|
||||
|
||||
if (dialog->options->delivery_enabled) {
|
||||
EMsgComposerHdrs *hdrs = e_msg_composer_get_hdrs(composer);
|
||||
EAccount *account;
|
||||
char *mdn_address;
|
||||
|
||||
char *mdn_address = hdrs->account->id->reply_to;
|
||||
account = e_msg_composer_hdrs_get_from_account (hdrs);
|
||||
mdn_address = account->id->reply_to;
|
||||
if (!mdn_address || !*mdn_address)
|
||||
mdn_address = hdrs->account->id->address;
|
||||
mdn_address = account->id->address;
|
||||
e_msg_composer_modify_header (composer, "Return-Receipt-To", mdn_address);
|
||||
}
|
||||
else
|
||||
@ -134,10 +137,13 @@ append_to_header (ExchangeSendOptionsDialog *dialog, gint state, gpointer data)
|
||||
|
||||
if (dialog->options->read_enabled) {
|
||||
EMsgComposerHdrs *hdrs = e_msg_composer_get_hdrs(composer);
|
||||
EAccount *account;
|
||||
char *mdn_address;
|
||||
|
||||
char *mdn_address = hdrs->account->id->reply_to;
|
||||
account = e_msg_composer_hdrs_get_from_account (hdrs);
|
||||
mdn_address = account->id->reply_to;
|
||||
if (!mdn_address || !*mdn_address)
|
||||
mdn_address = hdrs->account->id->address;
|
||||
mdn_address = account->id->address;
|
||||
|
||||
e_msg_composer_modify_header (composer, "Disposition-Notification-To", mdn_address);
|
||||
}
|
||||
|
||||
@ -1,3 +1,15 @@
|
||||
2007-11-27 Matthew Barnes <mbarnes@redhat.com>
|
||||
|
||||
** Fixes part of bug #495123
|
||||
|
||||
* Makefile.am:
|
||||
Add e-account-combo-box.[ch].
|
||||
|
||||
* e-account-combo-box.c:
|
||||
* e-account-combo-box.h:
|
||||
New widget renders an EAccountList as a combo box. Also listens
|
||||
for changes to the EAccountList and updates itself accordingly.
|
||||
|
||||
2007-11-05 Milan Crha <mcrha@redhat.com>
|
||||
|
||||
** Fix for bug #231166
|
||||
|
||||
@ -34,6 +34,7 @@ glade_DATA = e-send-options.glade \
|
||||
|
||||
widgetsinclude_HEADERS = \
|
||||
$(pilot_headers) \
|
||||
e-account-combo-box.h \
|
||||
e-activity-handler.h \
|
||||
e-attachment.h \
|
||||
e-attachment-bar.h \
|
||||
@ -81,6 +82,7 @@ widgetsinclude_HEADERS = \
|
||||
libemiscwidgets_la_SOURCES = \
|
||||
$(widgetsinclude_HEADERS) \
|
||||
$(pilot_sources) \
|
||||
e-account-combo-box.c \
|
||||
e-activity-handler.c \
|
||||
e-calendar.c \
|
||||
e-attachment.c \
|
||||
|
||||
413
widgets/misc/e-account-combo-box.c
Normal file
413
widgets/misc/e-account-combo-box.c
Normal file
@ -0,0 +1,413 @@
|
||||
#include "e-account-combo-box.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <camel/camel-store.h>
|
||||
|
||||
#define E_ACCOUNT_COMBO_BOX_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE \
|
||||
((obj), E_TYPE_ACCOUNT_COMBO_BOX, EAccountComboBoxPrivate))
|
||||
|
||||
enum {
|
||||
COLUMN_STRING,
|
||||
COLUMN_ACCOUNT
|
||||
};
|
||||
|
||||
struct _EAccountComboBoxPrivate {
|
||||
EAccountList *account_list;
|
||||
};
|
||||
|
||||
static gpointer parent_class;
|
||||
static CamelSession *camel_session;
|
||||
|
||||
static gboolean
|
||||
account_combo_box_has_dupes (GList *list,
|
||||
const gchar *address)
|
||||
{
|
||||
GList *iter;
|
||||
guint count = 0;
|
||||
|
||||
/* Look for duplicates of the given email address. */
|
||||
for (iter = list; iter != NULL; iter = iter->next) {
|
||||
EAccount *account = iter->data;
|
||||
|
||||
if (strcmp (account->id->address, address) == 0)
|
||||
count++;
|
||||
}
|
||||
|
||||
return (count > 1);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
account_combo_box_test_account (EAccount *account)
|
||||
{
|
||||
CamelStore *store;
|
||||
CamelException ex;
|
||||
const gchar *url;
|
||||
gboolean writable = FALSE;
|
||||
|
||||
/* Account must be enabled. */
|
||||
if (!account->enabled)
|
||||
return FALSE;
|
||||
|
||||
/* Account must have a non-empty email address. */
|
||||
if (account->id->address == NULL || *account->id->address == '\0')
|
||||
return FALSE;
|
||||
|
||||
/* XXX Not sure I understand this part. */
|
||||
if (account->parent_uid == NULL)
|
||||
return TRUE;
|
||||
|
||||
/* Account must be writable. */
|
||||
camel_exception_init (&ex);
|
||||
url = e_account_get_string (account, E_ACCOUNT_SOURCE_URL);
|
||||
store = CAMEL_STORE (camel_session_get_service (
|
||||
camel_session, url, CAMEL_PROVIDER_STORE, &ex));
|
||||
if (store != NULL) {
|
||||
writable = (store->mode & CAMEL_STORE_WRITE);
|
||||
camel_object_unref (store);
|
||||
}
|
||||
camel_exception_clear (&ex);
|
||||
|
||||
return writable;
|
||||
}
|
||||
|
||||
static void
|
||||
account_combo_box_refresh_cb (EAccountList *account_list,
|
||||
EAccount *unused,
|
||||
EAccountComboBox *combo_box)
|
||||
{
|
||||
GtkListStore *store;
|
||||
GtkTreeModel *model;
|
||||
EIterator *account_iter;
|
||||
EAccount *account;
|
||||
GHashTable *index;
|
||||
GList *list = NULL;
|
||||
GList *iter;
|
||||
|
||||
store = gtk_list_store_new (2, G_TYPE_STRING, E_TYPE_ACCOUNT);
|
||||
model = GTK_TREE_MODEL (store);
|
||||
|
||||
/* Embed a reverse-lookup index into the list store. */
|
||||
index = g_hash_table_new_full (
|
||||
g_direct_hash, g_direct_equal,
|
||||
(GDestroyNotify) g_object_unref,
|
||||
(GDestroyNotify) gtk_tree_row_reference_free);
|
||||
g_object_set_data_full (
|
||||
G_OBJECT (combo_box), "index", index,
|
||||
(GDestroyNotify) g_hash_table_destroy);
|
||||
|
||||
if (account_list == NULL)
|
||||
goto skip;
|
||||
|
||||
/* Build a list of EAccounts to display. */
|
||||
account_iter = e_list_get_iterator (E_LIST (account_list));
|
||||
while (e_iterator_is_valid (account_iter)) {
|
||||
EAccount *account;
|
||||
|
||||
/* XXX EIterator misuses const. */
|
||||
account = (EAccount *) e_iterator_get (account_iter);
|
||||
if (account_combo_box_test_account (account))
|
||||
list = g_list_prepend (list, account);
|
||||
e_iterator_next (account_iter);
|
||||
}
|
||||
g_object_unref (account_iter);
|
||||
|
||||
list = g_list_reverse (list);
|
||||
|
||||
/* Populate the list store and index. */
|
||||
for (iter = list; iter != NULL; iter = iter->next) {
|
||||
GtkTreeRowReference *reference;
|
||||
GtkTreeIter tree_iter;
|
||||
GtkTreePath *path;
|
||||
gchar *string;
|
||||
|
||||
account = iter->data;
|
||||
|
||||
/* Show the account name for duplicate email addresses. */
|
||||
if (account_combo_box_has_dupes (list, account->id->address))
|
||||
string = g_strdup_printf (
|
||||
"%s <%s> (%s)",
|
||||
account->id->name,
|
||||
account->id->address,
|
||||
account->name);
|
||||
else
|
||||
string = g_strdup_printf (
|
||||
"%s <%s>",
|
||||
account->id->name,
|
||||
account->id->address);
|
||||
|
||||
gtk_list_store_append (store, &tree_iter);
|
||||
gtk_list_store_set (
|
||||
store, &tree_iter,
|
||||
COLUMN_STRING, string,
|
||||
COLUMN_ACCOUNT, account, -1);
|
||||
|
||||
path = gtk_tree_model_get_path (model, &tree_iter);
|
||||
reference = gtk_tree_row_reference_new (model, path);
|
||||
g_hash_table_insert (index, account, reference);
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
g_free (string);
|
||||
}
|
||||
|
||||
g_list_free (list);
|
||||
|
||||
skip:
|
||||
/* Restore the previously selected account. */
|
||||
account = e_account_combo_box_get_active (combo_box);
|
||||
gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box), model);
|
||||
e_account_combo_box_set_active (combo_box, account);
|
||||
}
|
||||
|
||||
static GObject *
|
||||
account_combo_box_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_properties)
|
||||
{
|
||||
GObject *object;
|
||||
GtkCellRenderer *renderer;
|
||||
|
||||
/* Chain up to parent's constructor() method. */
|
||||
object = G_OBJECT_CLASS (parent_class)->constructor (
|
||||
type, n_construct_properties, construct_properties);
|
||||
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
|
||||
gtk_cell_layout_pack_start (
|
||||
GTK_CELL_LAYOUT (object), renderer, TRUE);
|
||||
gtk_cell_layout_add_attribute (
|
||||
GTK_CELL_LAYOUT (object), renderer, "text", COLUMN_STRING);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
static void
|
||||
account_combo_box_dispose (GObject *object)
|
||||
{
|
||||
EAccountComboBoxPrivate *priv;
|
||||
|
||||
priv = E_ACCOUNT_COMBO_BOX_GET_PRIVATE (object);
|
||||
|
||||
if (priv->account_list != NULL) {
|
||||
g_signal_handlers_disconnect_by_func (
|
||||
priv->account_list,
|
||||
account_combo_box_refresh_cb, object);
|
||||
g_object_unref (priv->account_list);
|
||||
priv->account_list = NULL;
|
||||
}
|
||||
|
||||
/* Chain up to parent's dispose() method. */
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
account_combo_box_class_init (EAccountComboBoxClass *class)
|
||||
{
|
||||
GObjectClass *object_class;
|
||||
|
||||
parent_class = g_type_class_peek_parent (class);
|
||||
g_type_class_add_private (class, sizeof (EAccountComboBoxPrivate));
|
||||
|
||||
object_class = G_OBJECT_CLASS (class);
|
||||
object_class->constructor = account_combo_box_constructor;
|
||||
object_class->dispose = account_combo_box_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
account_combo_box_init (EAccountComboBox *combo_box)
|
||||
{
|
||||
combo_box->priv = E_ACCOUNT_COMBO_BOX_GET_PRIVATE (combo_box);
|
||||
}
|
||||
|
||||
GType
|
||||
e_account_combo_box_get_type (void)
|
||||
{
|
||||
static GType type = 0;
|
||||
|
||||
if (G_UNLIKELY (type == 0)) {
|
||||
static const GTypeInfo type_info = {
|
||||
sizeof (EAccountComboBoxClass),
|
||||
(GBaseInitFunc) NULL,
|
||||
(GBaseFinalizeFunc) NULL,
|
||||
(GClassInitFunc) account_combo_box_class_init,
|
||||
(GClassFinalizeFunc) NULL,
|
||||
NULL, /* class_data */
|
||||
sizeof (EAccountComboBox),
|
||||
0, /* n_preallocs */
|
||||
(GInstanceInitFunc) account_combo_box_init,
|
||||
NULL /* value_table */
|
||||
};
|
||||
|
||||
type = g_type_register_static (
|
||||
GTK_TYPE_COMBO_BOX, "EAccountComboBox", &type_info, 0);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
e_account_combo_box_new (void)
|
||||
{
|
||||
return g_object_new (E_TYPE_ACCOUNT_COMBO_BOX, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
e_account_combo_box_set_session (CamelSession *session)
|
||||
{
|
||||
/* XXX Really gross hack.
|
||||
*
|
||||
* We need a CamelSession to test whether a given EAccount is
|
||||
* writable. The global CamelSession object is defined in the
|
||||
* mailer, but we're too far down the stack to access it. So
|
||||
* we have to rely on someone passing us a reference to it.
|
||||
*
|
||||
* A much cleaner solution would be to store the writeability
|
||||
* of an account directly into the EAccount, but this would likely
|
||||
* require breaking ABI and all the fun that goes along with that.
|
||||
*/
|
||||
|
||||
camel_session = session;
|
||||
}
|
||||
|
||||
void
|
||||
e_account_combo_box_set_account_list (EAccountComboBox *combo_box,
|
||||
EAccountList *account_list)
|
||||
{
|
||||
EAccountComboBoxPrivate *priv;
|
||||
|
||||
g_return_if_fail (E_IS_ACCOUNT_COMBO_BOX (combo_box));
|
||||
|
||||
if (account_list != NULL)
|
||||
g_return_if_fail (E_IS_ACCOUNT_LIST (account_list));
|
||||
|
||||
priv = E_ACCOUNT_COMBO_BOX_GET_PRIVATE (combo_box);
|
||||
|
||||
if (priv->account_list != NULL) {
|
||||
g_signal_handlers_disconnect_by_func (
|
||||
priv->account_list,
|
||||
account_combo_box_refresh_cb, combo_box);
|
||||
g_object_unref (priv->account_list);
|
||||
priv->account_list = NULL;
|
||||
}
|
||||
|
||||
if (account_list != NULL) {
|
||||
priv->account_list = g_object_ref (account_list);
|
||||
|
||||
/* Listen for changes to the account list. */
|
||||
g_signal_connect (
|
||||
priv->account_list, "account-added",
|
||||
G_CALLBACK (account_combo_box_refresh_cb), combo_box);
|
||||
g_signal_connect (
|
||||
priv->account_list, "account-changed",
|
||||
G_CALLBACK (account_combo_box_refresh_cb), combo_box);
|
||||
g_signal_connect (
|
||||
priv->account_list, "account-removed",
|
||||
G_CALLBACK (account_combo_box_refresh_cb), combo_box);
|
||||
}
|
||||
|
||||
account_combo_box_refresh_cb (account_list, NULL, combo_box);
|
||||
}
|
||||
|
||||
EAccount *
|
||||
e_account_combo_box_get_active (EAccountComboBox *combo_box)
|
||||
{
|
||||
EAccount *account;
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
gboolean iter_set;
|
||||
|
||||
g_return_val_if_fail (E_IS_ACCOUNT_COMBO_BOX (combo_box), NULL);
|
||||
|
||||
iter_set = gtk_combo_box_get_active_iter (
|
||||
GTK_COMBO_BOX (combo_box), &iter);
|
||||
if (!iter_set)
|
||||
return NULL;
|
||||
|
||||
model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
|
||||
gtk_tree_model_get (model, &iter, COLUMN_ACCOUNT, &account, -1);
|
||||
|
||||
return account;
|
||||
}
|
||||
|
||||
gboolean
|
||||
e_account_combo_box_set_active (EAccountComboBox *combo_box,
|
||||
EAccount *account)
|
||||
{
|
||||
GHashTable *index;
|
||||
EAccountList *account_list;
|
||||
GtkTreeRowReference *reference;
|
||||
GtkTreeModel *model;
|
||||
GtkTreePath *path;
|
||||
GtkTreeIter iter;
|
||||
gboolean iter_set;
|
||||
|
||||
g_return_val_if_fail (E_IS_ACCOUNT_COMBO_BOX (combo_box), FALSE);
|
||||
|
||||
if (account != NULL)
|
||||
g_return_val_if_fail (E_IS_ACCOUNT (account), FALSE);
|
||||
|
||||
account_list = combo_box->priv->account_list;
|
||||
g_return_val_if_fail (account_list != NULL, FALSE);
|
||||
|
||||
/* Failure here indicates a programming error. */
|
||||
index = g_object_get_data (G_OBJECT (combo_box), "index");
|
||||
g_assert (index != NULL);
|
||||
|
||||
/* NULL means select the default account. */
|
||||
/* XXX EAccountList misuses const. */
|
||||
if (account == NULL)
|
||||
account = (EAccount *)
|
||||
e_account_list_get_default (account_list);
|
||||
|
||||
/* Lookup the tree row reference for the account. */
|
||||
reference = g_hash_table_lookup (index, account);
|
||||
if (reference == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* Convert the reference to a tree iterator. */
|
||||
path = gtk_tree_row_reference_get_path (reference);
|
||||
model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
|
||||
iter_set = gtk_tree_model_get_iter (model, &iter, path);
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
if (!iter_set)
|
||||
return FALSE;
|
||||
|
||||
/* Activate the corresponding combo box item. */
|
||||
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo_box), &iter);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
e_account_combo_box_get_active_name (EAccountComboBox *combo_box)
|
||||
{
|
||||
EAccount *account;
|
||||
|
||||
g_return_val_if_fail (E_IS_ACCOUNT_COMBO_BOX (combo_box), NULL);
|
||||
|
||||
account = e_account_combo_box_get_active (combo_box);
|
||||
return (account != NULL) ? account->name : NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
e_account_combo_box_set_active_name (EAccountComboBox *combo_box,
|
||||
const gchar *account_name)
|
||||
{
|
||||
EAccountList *account_list;
|
||||
EAccount *account;
|
||||
|
||||
g_return_val_if_fail (E_IS_ACCOUNT_COMBO_BOX (combo_box), FALSE);
|
||||
|
||||
account_list = combo_box->priv->account_list;
|
||||
g_return_val_if_fail (account_list != NULL, FALSE);
|
||||
|
||||
/* XXX EAccountList misuses const. */
|
||||
account = (EAccount *) e_account_list_find (
|
||||
account_list, E_ACCOUNT_FIND_NAME, account_name);
|
||||
|
||||
if (account == NULL)
|
||||
return FALSE;
|
||||
|
||||
return e_account_combo_box_set_active (combo_box, account);
|
||||
}
|
||||
60
widgets/misc/e-account-combo-box.h
Normal file
60
widgets/misc/e-account-combo-box.h
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef E_ACCOUNT_COMBO_BOX_H
|
||||
#define E_ACCOUNT_COMBO_BOX_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <camel/camel-session.h>
|
||||
#include <libedataserver/e-account.h>
|
||||
#include <libedataserver/e-account-list.h>
|
||||
|
||||
/* Standard GObject macros */
|
||||
#define E_TYPE_ACCOUNT_COMBO_BOX \
|
||||
(e_account_combo_box_get_type ())
|
||||
#define E_ACCOUNT_COMBO_BOX(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST \
|
||||
((obj), E_TYPE_ACCOUNT_COMBO_BOX, EAccountComboBox))
|
||||
#define E_ACCOUNT_COMBO_BOX_CLASS(cls) \
|
||||
(G_TYPE_CHECK_CLASS_CAST \
|
||||
((cls), E_TYPE_ACCOUNT_COMBO_BOX, EAccountComboBoxClass))
|
||||
#define E_IS_ACCOUNT_COMBO_BOX(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE \
|
||||
((obj), E_TYPE_ACCOUNT_COMBO_BOX))
|
||||
#define E_IS_ACCOUNT_COMBO_BOX_CLASS(cls) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE \
|
||||
((cls), E_TYPE_ACCOUNT_COMBO_BOX))
|
||||
#define E_ACCOUNT_COMBO_BOX_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS \
|
||||
((obj), E_TYPE_ACCOUNT_COMBO_BOX, EAccountComboBoxClass))
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _EAccountComboBox EAccountComboBox;
|
||||
typedef struct _EAccountComboBoxClass EAccountComboBoxClass;
|
||||
typedef struct _EAccountComboBoxPrivate EAccountComboBoxPrivate;
|
||||
|
||||
struct _EAccountComboBox {
|
||||
GtkComboBox parent;
|
||||
EAccountComboBoxPrivate *priv;
|
||||
};
|
||||
|
||||
struct _EAccountComboBoxClass {
|
||||
GtkComboBoxClass parent_class;
|
||||
};
|
||||
|
||||
GType e_account_combo_box_get_type (void);
|
||||
GtkWidget * e_account_combo_box_new (void);
|
||||
void e_account_combo_box_set_session (CamelSession *session);
|
||||
void e_account_combo_box_set_account_list
|
||||
(EAccountComboBox *combo_box,
|
||||
EAccountList *account_list);
|
||||
EAccount * e_account_combo_box_get_active (EAccountComboBox *combo_box);
|
||||
gboolean e_account_combo_box_set_active (EAccountComboBox *combo_box,
|
||||
EAccount *account);
|
||||
const gchar * e_account_combo_box_get_active_name
|
||||
(EAccountComboBox *combo_box);
|
||||
gboolean e_account_combo_box_set_active_name
|
||||
(EAccountComboBox *combo_box,
|
||||
const gchar *account_name);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* E_ACCOUNT_COMBO_BOX_H */
|
||||
Reference in New Issue
Block a user