/*
* e-attachment-store.c
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with the program; if not, see
*
*
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*
*/
#include "e-attachment-store.h"
#include
#include "e-util/e-util.h"
#include "e-util/gconf-bridge.h"
#include "e-file-activity.h"
#define E_ATTACHMENT_STORE_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE \
((obj), E_TYPE_ATTACHMENT_STORE, EAttachmentStorePrivate))
#define DEFAULT_ICON_NAME "mail-attachment"
struct _EAttachmentStorePrivate {
GHashTable *activity_index;
GHashTable *attachment_index;
gchar *background_filename;
gchar *background_options;
gchar *current_folder;
guint ignore_row_changed : 1;
};
enum {
PROP_0,
PROP_BACKGROUND_FILENAME,
PROP_BACKGROUND_OPTIONS,
PROP_CURRENT_FOLDER,
PROP_NUM_ATTACHMENTS,
PROP_NUM_LOADING,
PROP_TOTAL_SIZE
};
enum {
NEW_ACTIVITY,
LAST_SIGNAL
};
static gpointer parent_class;
static guint signals[LAST_SIGNAL];
static const gchar *
attachment_store_get_background_filename (EAttachmentStore *store)
{
return store->priv->background_filename;
}
static void
attachment_store_set_background_filename (EAttachmentStore *store,
const gchar *background_filename)
{
if (background_filename == NULL)
background_filename = "";
g_free (store->priv->background_filename);
store->priv->background_filename = g_strdup (background_filename);
g_object_notify (G_OBJECT (store), "background-filename");
}
static const gchar *
attachment_store_get_background_options (EAttachmentStore *store)
{
return store->priv->background_options;
}
static void
attachment_store_set_background_options (EAttachmentStore *store,
const gchar *background_options)
{
if (background_options == NULL)
background_options = "";
g_free (store->priv->background_options);
store->priv->background_options = g_strdup (background_options);
g_object_notify (G_OBJECT (store), "background-options");
}
static void
attachment_store_remove_activity (EAttachmentStore *store,
EActivity *activity)
{
GtkTreeRowReference *reference;
GHashTable *hash_table;
hash_table = store->priv->activity_index;
reference = g_hash_table_lookup (hash_table, activity);
if (gtk_tree_row_reference_valid (reference)) {
GtkTreeModel *model;
GtkTreePath *path;
GtkTreeIter iter;
model = gtk_tree_row_reference_get_model (reference);
path = gtk_tree_row_reference_get_path (reference);
gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_path_free (path);
gtk_list_store_set (
GTK_LIST_STORE (store), &iter,
E_ATTACHMENT_STORE_COLUMN_ACTIVITY, NULL, -1);
}
g_hash_table_remove (hash_table, activity);
g_object_notify (G_OBJECT (store), "num-loading");
}
static void
attachment_store_copy_ready (GFile *source,
GAsyncResult *result,
GtkTreeRowReference *reference)
{
EAttachmentStore *store;
EAttachment *attachment;
EActivity *activity;
GFile *destination;
GtkTreeModel *model;
GtkTreePath *path;
GtkTreeIter iter;
gboolean valid;
GError *error = NULL;
model = gtk_tree_row_reference_get_model (reference);
path = gtk_tree_row_reference_get_path (reference);
valid = gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_path_free (path);
g_return_if_fail (valid);
gtk_tree_model_get (
model, &iter,
E_ATTACHMENT_STORE_COLUMN_ACTIVITY, &activity,
E_ATTACHMENT_STORE_COLUMN_ATTACHMENT, &attachment, -1);
gtk_tree_row_reference_free (reference);
store = E_ATTACHMENT_STORE (model);
if (!g_file_copy_finish (source, result, &error))
goto fail;
gtk_list_store_set (
GTK_LIST_STORE (store), &iter,
E_ATTACHMENT_STORE_COLUMN_ACTIVITY, NULL, -1);
destination = e_file_activity_get_file (E_FILE_ACTIVITY (activity));
e_attachment_set_file (attachment, destination);
e_activity_complete (activity);
g_object_unref (attachment);
g_object_unref (activity);
return;
fail:
e_attachment_store_remove_attachment (store, attachment);
g_object_unref (attachment);
g_object_unref (activity);
/* XXX Do something more useful with the error. */
g_warning ("%s", error->message);
g_error_free (error);
}
static void
attachment_store_copy_async (EAttachmentStore *store,
EAttachment *attachment)
{
EActivity *activity;
GCancellable *cancellable;
GtkTreeRowReference *reference;
GtkTreeModel *model;
GtkTreePath *path;
GtkTreeIter iter;
GHashTable *hash_table;
GFile *destination;
GFile *source;
gboolean valid;
gchar *filename;
gchar *uri;
gint fd;
GError *error = NULL;
hash_table = store->priv->attachment_index;
reference = g_hash_table_lookup (hash_table, attachment);
g_return_if_fail (reference != NULL);
fd = e_file_open_tmp (&filename, &error);
if (error != NULL)
goto fail;
source = e_attachment_get_file (attachment);
destination = g_file_new_for_path (filename);
g_free (filename);
close (fd);
model = gtk_tree_row_reference_get_model (reference);
path = gtk_tree_row_reference_get_path (reference);
valid = gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_path_free (path);
g_return_if_fail (valid);
uri = g_file_get_uri (source);
activity = e_file_activity_newv (_("Downloading '%s'"), uri);
g_free (uri);
gtk_list_store_set (
GTK_LIST_STORE (store), &iter,
E_ATTACHMENT_STORE_COLUMN_ACTIVITY, activity, -1);
reference = gtk_tree_row_reference_copy (reference);
hash_table = store->priv->activity_index;
g_hash_table_insert (hash_table, g_object_ref (activity), reference);
g_signal_connect_swapped (
activity, "cancelled",
G_CALLBACK (attachment_store_remove_activity), store);
g_signal_connect_swapped (
activity, "completed",
G_CALLBACK (attachment_store_remove_activity), store);
reference = gtk_tree_row_reference_copy (reference);
cancellable = e_file_activity_get_cancellable (
E_FILE_ACTIVITY (activity));
g_file_copy_async (
source, destination, G_FILE_COPY_OVERWRITE,
G_PRIORITY_DEFAULT, cancellable, (GFileProgressCallback)
e_file_activity_progress, activity, (GAsyncReadyCallback)
attachment_store_copy_ready, reference);
e_file_activity_set_file (E_FILE_ACTIVITY (activity), destination);
g_signal_emit (store, signals[NEW_ACTIVITY], 0, activity);
g_object_notify (G_OBJECT (store), "num-loading");
g_object_unref (activity);
g_object_unref (destination);
return;
fail:
e_attachment_store_remove_attachment (store, attachment);
/* XXX Do something more useful with the error. */
g_warning ("%s", error->message);
g_error_free (error);
}
static void
attachment_store_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
switch (property_id) {
case PROP_BACKGROUND_FILENAME:
attachment_store_set_background_filename (
E_ATTACHMENT_STORE (object),
g_value_get_string (value));
return;
case PROP_BACKGROUND_OPTIONS:
attachment_store_set_background_options (
E_ATTACHMENT_STORE (object),
g_value_get_string (value));
return;
case PROP_CURRENT_FOLDER:
e_attachment_store_set_current_folder (
E_ATTACHMENT_STORE (object),
g_value_get_string (value));
return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
static void
attachment_store_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
switch (property_id) {
case PROP_BACKGROUND_FILENAME:
g_value_set_string (
value,
attachment_store_get_background_filename (
E_ATTACHMENT_STORE (object)));
return;
case PROP_BACKGROUND_OPTIONS:
g_value_set_string (
value,
attachment_store_get_background_options (
E_ATTACHMENT_STORE (object)));
return;
case PROP_CURRENT_FOLDER:
g_value_set_string (
value,
e_attachment_store_get_current_folder (
E_ATTACHMENT_STORE (object)));
return;
case PROP_NUM_ATTACHMENTS:
g_value_set_uint (
value,
e_attachment_store_get_num_attachments (
E_ATTACHMENT_STORE (object)));
return;
case PROP_NUM_LOADING:
g_value_set_uint (
value,
e_attachment_store_get_num_loading (
E_ATTACHMENT_STORE (object)));
return;
case PROP_TOTAL_SIZE:
g_value_set_uint64 (
value,
e_attachment_store_get_total_size (
E_ATTACHMENT_STORE (object)));
return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
static void
attachment_store_dispose (GObject *object)
{
EAttachmentStorePrivate *priv;
priv = E_ATTACHMENT_STORE_GET_PRIVATE (object);
g_hash_table_remove_all (priv->activity_index);
g_hash_table_remove_all (priv->attachment_index);
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
attachment_store_finalize (GObject *object)
{
EAttachmentStorePrivate *priv;
priv = E_ATTACHMENT_STORE_GET_PRIVATE (object);
g_hash_table_destroy (priv->activity_index);
g_hash_table_destroy (priv->attachment_index);
g_free (priv->background_filename);
g_free (priv->background_options);
g_free (priv->current_folder);
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
attachment_store_constructed (GObject *object)
{
EAttachmentStorePrivate *priv;
GConfBridge *bridge;
const gchar *prop;
const gchar *key;
priv = E_ATTACHMENT_STORE_GET_PRIVATE (object);
bridge = gconf_bridge_get ();
prop = "background-filename";
key = "/desktop/gnome/background/picture_filename";
gconf_bridge_bind_property (bridge, key, object, prop);
prop = "background-options";
key = "/desktop/gnome/background/picture_options";
gconf_bridge_bind_property (bridge, key, object, prop);
}
static void
attachment_store_row_changed (GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter)
{
EAttachmentStorePrivate *priv;
EAttachment *attachment;
GFile *file;
GIcon *icon;
GList *list;
const gchar *content_type;
const gchar *display_name;
const gchar *thumbnail_path;
gchar *content_description;
gchar *display_size;
gchar *caption;
gboolean loading;
gboolean saving;
guint64 size;
gint column_id;
priv = E_ATTACHMENT_STORE_GET_PRIVATE (model);
if (priv->ignore_row_changed)
return;
column_id = E_ATTACHMENT_STORE_COLUMN_ATTACHMENT;
gtk_tree_model_get (model, iter, column_id, &attachment, -1);
g_return_if_fail (E_IS_ATTACHMENT (attachment));
content_type = e_attachment_get_content_type (attachment);
display_name = e_attachment_get_display_name (attachment);
thumbnail_path = e_attachment_get_thumbnail_path (attachment);
loading = e_attachment_get_loading (attachment);
saving = e_attachment_get_saving (attachment);
icon = e_attachment_get_icon (attachment);
size = e_attachment_get_size (attachment);
content_type = (content_type != NULL) ? content_type : "";
content_description = g_content_type_get_description (content_type);
display_size = g_format_size_for_display ((goffset) size);
if (size > 0)
caption = g_strdup_printf (
"%s\n(%s)", display_name, display_size);
else
caption = g_strdup (display_name);
/* Prefer the thumbnail if we have one. */
if (thumbnail_path != NULL && *thumbnail_path != '\0') {
file = g_file_new_for_path (thumbnail_path);
icon = g_file_icon_new (file);
g_object_unref (file);
/* Else use the standard icon for the content type. */
} else if (icon != NULL)
g_object_ref (icon);
/* Last ditch fallback. (GFileInfo not yet loaded?) */
else
icon = g_themed_icon_new (DEFAULT_ICON_NAME);
/* Apply emblems. */
list = e_attachment_list_emblems (attachment);
if (list != NULL) {
GIcon *emblemed_icon;
GEmblem *emblem;
emblem = G_EMBLEM (list->data);
emblemed_icon = g_emblemed_icon_new (icon, emblem);
list = g_list_delete_link (list, list);
g_object_unref (emblem);
while (list != NULL) {
emblem = G_EMBLEM (list->data);
g_emblemed_icon_add_emblem (
G_EMBLEMED_ICON (emblemed_icon), emblem);
list = g_list_delete_link (list, list);
g_object_unref (emblem);
}
g_object_unref (icon);
icon = emblemed_icon;
}
/* We're about to trigger another "row-changed"
* signal, so this prevents infinite recursion. */
priv->ignore_row_changed = TRUE;
gtk_list_store_set (
GTK_LIST_STORE (model), iter,
E_ATTACHMENT_STORE_COLUMN_CONTENT_TYPE, content_description,
E_ATTACHMENT_STORE_COLUMN_DISPLAY_NAME, display_name,
E_ATTACHMENT_STORE_COLUMN_CAPTION, caption,
E_ATTACHMENT_STORE_COLUMN_ICON, icon,
E_ATTACHMENT_STORE_COLUMN_LOADING, loading,
E_ATTACHMENT_STORE_COLUMN_SAVING, saving,
E_ATTACHMENT_STORE_COLUMN_SIZE, size,
-1);
priv->ignore_row_changed = FALSE;
g_object_unref (icon);
g_free (content_description);
g_free (display_size);
}
static void
attachment_store_class_init (EAttachmentStoreClass *class)
{
GObjectClass *object_class;
parent_class = g_type_class_peek_parent (class);
g_type_class_add_private (class, sizeof (EAttachmentStorePrivate));
object_class = G_OBJECT_CLASS (class);
object_class->set_property = attachment_store_set_property;
object_class->get_property = attachment_store_get_property;
object_class->dispose = attachment_store_dispose;
object_class->finalize = attachment_store_finalize;
object_class->constructed = attachment_store_constructed;
g_object_class_install_property (
object_class,
PROP_BACKGROUND_FILENAME,
g_param_spec_string (
"background-filename",
"Background Filename",
NULL,
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
g_object_class_install_property (
object_class,
PROP_BACKGROUND_OPTIONS,
g_param_spec_string (
"background-options",
"Background Options",
NULL,
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
g_object_class_install_property (
object_class,
PROP_CURRENT_FOLDER,
g_param_spec_string (
"current-folder",
"Current Folder",
NULL,
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
g_object_class_install_property (
object_class,
PROP_NUM_ATTACHMENTS,
g_param_spec_uint (
"num-attachments",
"Num Attachments",
NULL,
0,
G_MAXUINT,
0,
G_PARAM_READABLE));
g_object_class_install_property (
object_class,
PROP_NUM_LOADING,
g_param_spec_uint (
"num-loading",
"Num Loading",
NULL,
0,
G_MAXUINT,
0,
G_PARAM_READABLE));
g_object_class_install_property (
object_class,
PROP_TOTAL_SIZE,
g_param_spec_uint64 (
"total-size",
"Total Size",
NULL,
0,
G_MAXUINT64,
0,
G_PARAM_READABLE));
}
static void
attachment_store_iface_init (GtkTreeModelIface *iface)
{
iface->row_changed = attachment_store_row_changed;
}
static void
attachment_store_init (EAttachmentStore *store)
{
GType types[E_ATTACHMENT_STORE_NUM_COLUMNS];
GHashTable *activity_index;
GHashTable *attachment_index;
gint column = 0;
activity_index = g_hash_table_new_full (
g_direct_hash, g_direct_equal,
(GDestroyNotify) g_object_unref,
(GDestroyNotify) gtk_tree_row_reference_free);
attachment_index = g_hash_table_new_full (
g_direct_hash, g_direct_equal,
(GDestroyNotify) g_object_unref,
(GDestroyNotify) gtk_tree_row_reference_free);
store->priv = E_ATTACHMENT_STORE_GET_PRIVATE (store);
store->priv->activity_index = activity_index;
store->priv->attachment_index = attachment_index;
types[column++] = E_TYPE_ACTIVITY; /* COLUMN_ACTIVITY */
types[column++] = E_TYPE_ATTACHMENT; /* COLUMN_ATTACHMENT */
types[column++] = G_TYPE_STRING; /* COLUMN_CAPTION */
types[column++] = G_TYPE_STRING; /* COLUMN_CONTENT_TYPE */
types[column++] = G_TYPE_STRING; /* COLUMN_DISPLAY_NAME */
types[column++] = G_TYPE_ICON; /* COLUMN_ICON */
types[column++] = G_TYPE_BOOLEAN; /* COLUMN_LOADING */
types[column++] = G_TYPE_BOOLEAN; /* COLUMN_SAVING */
types[column++] = G_TYPE_UINT64; /* COLUMN_SIZE */
g_assert (column == E_ATTACHMENT_STORE_NUM_COLUMNS);
gtk_list_store_set_column_types (
GTK_LIST_STORE (store), G_N_ELEMENTS (types), types);
}
GType
e_attachment_store_get_type (void)
{
static GType type = 0;
if (G_UNLIKELY (type == 0)) {
static const GTypeInfo type_info = {
sizeof (EAttachmentStoreClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) attachment_store_class_init,
(GClassFinalizeFunc) NULL,
NULL, /* class_data */
sizeof (EAttachmentStore),
0, /* n_preallocs */
(GInstanceInitFunc) attachment_store_init,
NULL /* value_table */
};
static const GInterfaceInfo iface_info = {
(GInterfaceInitFunc) attachment_store_iface_init,
(GInterfaceFinalizeFunc) NULL,
NULL /* interface_data */
};
type = g_type_register_static (
GTK_TYPE_LIST_STORE, "EAttachmentStore",
&type_info, 0);
g_type_add_interface_static (
type, GTK_TYPE_TREE_MODEL, &iface_info);
}
return type;
}
GtkTreeModel *
e_attachment_store_new (void)
{
return g_object_new (E_TYPE_ATTACHMENT_STORE, NULL);
}
void
e_attachment_store_add_attachment (EAttachmentStore *store,
EAttachment *attachment)
{
GtkTreeRowReference *reference;
GtkTreeModel *model;
GtkTreePath *path;
GtkTreeIter iter;
GFile *file;
g_return_if_fail (E_IS_ATTACHMENT_STORE (store));
g_return_if_fail (E_IS_ATTACHMENT (attachment));
gtk_list_store_append (GTK_LIST_STORE (store), &iter);
gtk_list_store_set (
GTK_LIST_STORE (store), &iter,
E_ATTACHMENT_STORE_COLUMN_ATTACHMENT, attachment, -1);
model = GTK_TREE_MODEL (store);
path = gtk_tree_model_get_path (model, &iter);
reference = gtk_tree_row_reference_new (model, path);
gtk_tree_path_free (path);
g_hash_table_insert (
store->priv->attachment_index,
g_object_ref (attachment), reference);
file = e_attachment_get_file (attachment);
/* This lets the attachment tell us when to update. */
_e_attachment_set_reference (attachment, reference);
if (file != NULL && !g_file_is_native (file))
attachment_store_copy_async (store, attachment);
g_object_freeze_notify (G_OBJECT (store));
g_object_notify (G_OBJECT (store), "num-attachments");
g_object_notify (G_OBJECT (store), "total-size");
g_object_thaw_notify (G_OBJECT (store));
}
gboolean
e_attachment_store_remove_attachment (EAttachmentStore *store,
EAttachment *attachment)
{
GtkTreeRowReference *reference;
GHashTable *hash_table;
EActivity *activity;
GtkTreeModel *model;
GtkTreePath *path;
GtkTreeIter iter;
g_return_val_if_fail (E_IS_ATTACHMENT_STORE (store), FALSE);
g_return_val_if_fail (E_IS_ATTACHMENT (attachment), FALSE);
hash_table = store->priv->attachment_index;
reference = g_hash_table_lookup (hash_table, attachment);
if (reference == NULL)
return FALSE;
if (!gtk_tree_row_reference_valid (reference)) {
g_hash_table_remove (hash_table, attachment);
return FALSE;
}
model = gtk_tree_row_reference_get_model (reference);
path = gtk_tree_row_reference_get_path (reference);
gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_path_free (path);
gtk_tree_model_get (
model, &iter,
E_ATTACHMENT_STORE_COLUMN_ACTIVITY, &activity, -1);
if (activity != NULL) {
/* Cancel the file transfer. */
e_activity_cancel (activity);
g_object_unref (activity);
}
gtk_list_store_remove (GTK_LIST_STORE (store), &iter);
g_hash_table_remove (hash_table, attachment);
g_object_freeze_notify (G_OBJECT (store));
g_object_notify (G_OBJECT (store), "num-attachments");
g_object_notify (G_OBJECT (store), "total-size");
g_object_thaw_notify (G_OBJECT (store));
return TRUE;
}
void
e_attachment_store_add_to_multipart (EAttachmentStore *store,
CamelMultipart *multipart,
const gchar *default_charset)
{
GtkTreeModel *model;
GtkTreeIter iter;
gboolean valid;
g_return_if_fail (E_IS_ATTACHMENT_STORE (store));
g_return_if_fail (CAMEL_MULTIPART (multipart));
model = GTK_TREE_MODEL (store);
valid = gtk_tree_model_get_iter_first (model, &iter);
while (valid) {
EAttachment *attachment;
gint column_id;
column_id = E_ATTACHMENT_STORE_COLUMN_ATTACHMENT;
gtk_tree_model_get (model, &iter, column_id, &attachment, -1);
e_attachment_add_to_multipart (
attachment, multipart, default_charset);
g_object_unref (attachment);
valid = gtk_tree_model_iter_next (model, &iter);
}
}
const gchar *
e_attachment_store_get_current_folder (EAttachmentStore *store)
{
g_return_val_if_fail (E_IS_ATTACHMENT_STORE (store), NULL);
return store->priv->current_folder;
}
void
e_attachment_store_set_current_folder (EAttachmentStore *store,
const gchar *current_folder)
{
g_return_if_fail (E_IS_ATTACHMENT_STORE (store));
if (current_folder == NULL)
current_folder = g_get_home_dir ();
g_free (store->priv->current_folder);
store->priv->current_folder = g_strdup (current_folder);
g_object_notify (G_OBJECT (store), "current-folder");
}
guint
e_attachment_store_get_num_attachments (EAttachmentStore *store)
{
g_return_val_if_fail (E_IS_ATTACHMENT_STORE (store), 0);
return g_hash_table_size (store->priv->attachment_index);
}
guint
e_attachment_store_get_num_loading (EAttachmentStore *store)
{
g_return_val_if_fail (E_IS_ATTACHMENT_STORE (store), 0);
return g_hash_table_size (store->priv->activity_index);
}
guint64
e_attachment_store_get_total_size (EAttachmentStore *store)
{
GtkTreeModel *model;
GtkTreeIter iter;
guint64 total_size = 0;
gboolean valid;
g_return_val_if_fail (E_IS_ATTACHMENT_STORE (store), 0);
model = GTK_TREE_MODEL (store);
valid = gtk_tree_model_get_iter_first (model, &iter);
while (valid) {
EAttachment *attachment;
gint column_id;
column_id = E_ATTACHMENT_STORE_COLUMN_ATTACHMENT;
gtk_tree_model_get (model, &iter, column_id, &attachment, -1);
total_size += e_attachment_get_size (attachment);
g_object_unref (attachment);
valid = gtk_tree_model_iter_next (model, &iter);
}
return total_size;
}
gint
e_attachment_store_run_file_chooser_dialog (EAttachmentStore *store,
GtkWidget *dialog)
{
GtkFileChooser *file_chooser;
gint response = GTK_RESPONSE_NONE;
const gchar *current_folder;
gboolean update_folder;
g_return_val_if_fail (E_IS_ATTACHMENT_STORE (store), response);
g_return_val_if_fail (GTK_IS_FILE_CHOOSER_DIALOG (dialog), response);
file_chooser = GTK_FILE_CHOOSER (dialog);
current_folder = e_attachment_store_get_current_folder (store);
gtk_file_chooser_set_current_folder (file_chooser, current_folder);
response = gtk_dialog_run (GTK_DIALOG (dialog));
update_folder =
(response == GTK_RESPONSE_ACCEPT) ||
(response == GTK_RESPONSE_OK) ||
(response == GTK_RESPONSE_YES) ||
(response == GTK_RESPONSE_APPLY);
if (update_folder) {
gchar *folder;
folder = gtk_file_chooser_get_current_folder (file_chooser);
e_attachment_store_set_current_folder (store, folder);
g_free (folder);
}
return response;
}
void
e_attachment_store_run_load_dialog (EAttachmentStore *store,
GtkWindow *parent)
{
GtkFileChooser *file_chooser;
GtkWidget *dialog;
GtkWidget *option;
GSList *files, *iter;
const gchar *disposition;
gboolean active;
gint response;
g_return_if_fail (E_IS_ATTACHMENT_STORE (store));
dialog = gtk_file_chooser_dialog_new (
_("Add Attachment"), parent,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
_("A_ttach"), GTK_RESPONSE_OK, NULL);
file_chooser = GTK_FILE_CHOOSER (dialog);
gtk_file_chooser_set_local_only (file_chooser, FALSE);
gtk_file_chooser_set_select_multiple (file_chooser, TRUE);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
gtk_window_set_icon_name (GTK_WINDOW (dialog), "mail-attachment");
option = gtk_check_button_new_with_mnemonic (
_("_Suggest automatic display of attachment"));
gtk_file_chooser_set_extra_widget (file_chooser, option);
gtk_widget_show (option);
response = e_attachment_store_run_file_chooser_dialog (store, dialog);
if (response != GTK_RESPONSE_OK)
goto exit;
files = gtk_file_chooser_get_files (file_chooser);
active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (option));
disposition = active ? "inline" : "attachment";
for (iter = files; iter != NULL; iter = g_slist_next (iter)) {
EAttachment *attachment;
GFile *file = iter->data;
attachment = e_attachment_new ();
e_attachment_set_file (attachment, file);
e_attachment_store_add_attachment (store, attachment);
g_object_unref (attachment);
}
g_slist_foreach (files, (GFunc) g_object_unref, NULL);
g_slist_free (files);
exit:
gtk_widget_destroy (dialog);
}
void
e_attachment_store_run_save_dialog (EAttachmentStore *store,
EAttachment *attachment,
GtkWindow *parent)
{
GtkFileChooser *file_chooser;
GtkWidget *dialog;
GFile *file;
EActivity *activity;
const gchar *display_name;
gint response;
g_return_if_fail (E_IS_ATTACHMENT_STORE (store));
g_return_if_fail (E_IS_ATTACHMENT (attachment));
dialog = gtk_file_chooser_dialog_new (
_("Save Attachment"), parent,
GTK_FILE_CHOOSER_ACTION_SAVE,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL);
file_chooser = GTK_FILE_CHOOSER (dialog);
gtk_file_chooser_set_local_only (file_chooser, FALSE);
gtk_file_chooser_set_do_overwrite_confirmation (file_chooser, TRUE);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
gtk_window_set_icon_name (GTK_WINDOW (dialog), "mail-attachment");
display_name = e_attachment_get_display_name (attachment);
if (display_name != NULL)
gtk_file_chooser_set_current_name (file_chooser, display_name);
response = e_attachment_store_run_file_chooser_dialog (store, dialog);
if (response != GTK_RESPONSE_OK)
goto exit;
file = gtk_file_chooser_get_file (file_chooser);
activity = e_file_activity_new (_("Saving attachment"));
e_attachment_save_async (
attachment, E_FILE_ACTIVITY (activity), file);
g_signal_emit (store, signals[NEW_ACTIVITY], 0, activity);
g_object_unref (activity);
g_object_unref (file);
exit:
gtk_widget_destroy (dialog);
}