aboutsummaryrefslogtreecommitdiffstats
path: root/mail/folder-browser.c
diff options
context:
space:
mode:
Diffstat (limited to 'mail/folder-browser.c')
-rw-r--r--mail/folder-browser.c214
1 files changed, 198 insertions, 16 deletions
diff --git a/mail/folder-browser.c b/mail/folder-browser.c
index a796063540..b50fae4a5d 100644
--- a/mail/folder-browser.c
+++ b/mail/folder-browser.c
@@ -15,6 +15,7 @@
#include <ctype.h>
#include <gdk/gdkkeysyms.h>
+#include <gtk/gtkinvisible.h>
#include <gal/e-paned/e-vpaned.h>
#include <gal/e-table/e-table.h>
#include <gal/util/e-util.h>
@@ -72,6 +73,10 @@ static GtkTargetEntry drag_types[] = {
static const int num_drag_types = sizeof (drag_types) / sizeof (drag_types[0]);
+static GdkAtom clipboard_atom = GDK_NONE;
+static GByteArray *clipboard_selection = NULL;
+static GtkWidget *invisible = NULL;
+
static void fb_resize_cb (GtkWidget *w, GtkAllocation *a);
static void update_unread_count (CamelObject *, gpointer, gpointer);
@@ -86,6 +91,13 @@ enum {
static guint folder_browser_signals [LAST_SIGNAL] = {0, };
static void
+invisible_destroyed (GtkObject *invisible)
+{
+ g_byte_array_free (clipboard_selection, TRUE);
+ clipboard_selection = NULL;
+}
+
+static void
folder_browser_destroy (GtkObject *object)
{
FolderBrowser *folder_browser;
@@ -106,7 +118,7 @@ folder_browser_destroy (GtkObject *object)
if (folder_browser->folder) {
CamelObject *folder = CAMEL_OBJECT (folder_browser->folder);
EvolutionStorage *storage;
-
+
if ((storage = mail_lookup_storage (folder_browser->folder->parent_store))) {
gtk_object_unref (GTK_OBJECT (storage));
camel_object_unhook_event (folder, "message_changed",
@@ -116,7 +128,7 @@ folder_browser_destroy (GtkObject *object)
update_unread_count,
folder_browser);
}
-
+
mail_sync_folder (folder_browser->folder, NULL, NULL);
camel_object_unref (folder);
}
@@ -133,12 +145,14 @@ folder_browser_destroy (GtkObject *object)
gtk_object_unref (GTK_OBJECT (folder_browser->view_collection));
folder_browser->view_collection = NULL;
}
-
+
if (folder_browser->view_menus) {
gtk_object_unref (GTK_OBJECT (folder_browser->view_menus));
folder_browser->view_menus = NULL;
}
-
+
+ gtk_object_unref (GTK_OBJECT (invisible));
+
folder_browser_parent_class->destroy (object);
}
@@ -166,6 +180,10 @@ folder_browser_class_init (GtkObjectClass *object_class)
GTK_TYPE_NONE, 1, GTK_TYPE_STRING);
gtk_object_class_add_signals (object_class, folder_browser_signals, LAST_SIGNAL);
+
+ /* clipboard atom */
+ if (!clipboard_atom)
+ clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE);
}
static void
@@ -175,14 +193,14 @@ update_unread_count_main(CamelObject *object, gpointer event_data, gpointer user
FolderBrowser *fb = user_data;
EvolutionStorage *storage;
char *name;
-
+
storage = mail_lookup_storage (folder->parent_store);
-
+
if (fb->unread_count == 0)
name = g_strdup (camel_folder_get_name (folder));
else
name = g_strdup_printf ("%s (%d)", camel_folder_get_name (folder), fb->unread_count);
-
+
evolution_storage_update_folder_by_uri (storage, fb->uri, name, fb->unread_count != 0);
g_free (name);
gtk_object_unref (GTK_OBJECT (storage));
@@ -194,7 +212,7 @@ update_unread_count (CamelObject *object, gpointer event_data, gpointer user_dat
CamelFolder *folder = (CamelFolder *)object;
FolderBrowser *fb = user_data;
int unread;
-
+
unread = camel_folder_get_unread_message_count (folder);
if (unread == fb->unread_count)
return;
@@ -362,6 +380,142 @@ message_list_drag_data_get (ETree *tree, int row, ETreePath path, int col,
}
static void
+selection_get (GtkWidget *widget, GtkSelectionData *selection_data,
+ guint info, guint time_stamp, FolderBrowser *fb)
+{
+ if (clipboard_selection != NULL) {
+ gtk_selection_data_set (selection_data,
+ GDK_SELECTION_TYPE_STRING,
+ 8,
+ clipboard_selection->data,
+ clipboard_selection->len);
+ }
+}
+
+static void
+selection_clear_event (GtkWidget *widget, GdkEventSelection *event, FolderBrowser *fb)
+{
+ if (clipboard_selection != NULL) {
+ g_byte_array_free (clipboard_selection, TRUE);
+ clipboard_selection = NULL;
+ }
+}
+
+static void
+selection_received (GtkWidget *widget, GtkSelectionData *selection_data,
+ guint time, FolderBrowser *fb)
+{
+ char *url, *name, *in, *inptr, *inend;
+ CamelFolder *source;
+ GPtrArray *uids;
+
+ /* format: "url folder_name uid1\0uid2\0uid3\0...\0uidn" */
+
+ in = selection_data->data;
+ inend = in + selection_data->length;
+
+ inptr = strchr (in, ' ');
+ url = g_strndup (in, inptr - in);
+
+ name = inptr + 1;
+ inptr = strchr (name, ' ');
+ name = g_strndup (name, inptr - name);
+
+ source = mail_tool_get_folder_from_urlname (url, name, 0, NULL);
+ g_free (name);
+ g_free (url);
+
+ if (!source)
+ return;
+
+ /* split the uids */
+ inptr++;
+ uids = g_ptr_array_new ();
+ while (inptr < inend) {
+ char *start = inptr;
+
+ while (inptr < inend && *inptr)
+ inptr++;
+
+ g_ptr_array_add (uids, g_strndup (start, inptr - start));
+ inptr++;
+ }
+
+ mail_do_transfer_messages (source, uids, FALSE, fb->uri);
+
+ camel_object_unref (CAMEL_OBJECT (source));
+}
+
+void
+folder_browser_copy (GtkWidget *menuitem, FolderBrowser *fb)
+{
+ GPtrArray *uids = NULL;
+ GByteArray *bytes;
+ gboolean cut;
+ char *url;
+ int i;
+
+ cut = menuitem == NULL;
+
+ if (clipboard_selection) {
+ g_byte_array_free (clipboard_selection, TRUE);
+ clipboard_selection = NULL;
+ }
+
+ uids = g_ptr_array_new ();
+ message_list_foreach (fb->message_list, add_uid, uids);
+
+ /* format: "url folder_name uid1\0uid2\0uid3\0...\0uidn" */
+
+ url = camel_url_to_string (CAMEL_SERVICE (camel_folder_get_parent_store (fb->folder))->url, 0);
+
+ /* write the url portion */
+ bytes = g_byte_array_new ();
+ g_byte_array_append (bytes, url, strlen (url));
+ g_byte_array_append (bytes, " ", 1);
+ g_free (url);
+
+ /* write the folder_name portion */
+ g_byte_array_append (bytes, fb->folder->name, strlen (fb->folder->name));
+ g_byte_array_append (bytes, " ", 1);
+
+ /* write the uids */
+ for (i = 0; i < uids->len; i++) {
+ if (cut) {
+ camel_folder_set_message_flags (fb->folder, uids->pdata[i],
+ CAMEL_MESSAGE_DELETED,
+ CAMEL_MESSAGE_DELETED);
+ }
+ g_byte_array_append (bytes, uids->pdata[i], strlen (uids->pdata[i]));
+ g_free (uids->pdata[i]);
+
+ if (i + 1 < uids->len)
+ g_byte_array_append (bytes, "", 1);
+ }
+
+ g_ptr_array_free (uids, TRUE);
+
+ clipboard_selection = bytes;
+
+ gtk_selection_owner_set (invisible, clipboard_atom, GDK_CURRENT_TIME);
+}
+
+void
+folder_browser_cut (GtkWidget *menuitem, FolderBrowser *fb)
+{
+ folder_browser_copy (NULL, fb);
+}
+
+void
+folder_browser_paste (GtkWidget *menuitem, FolderBrowser *fb)
+{
+ gtk_selection_convert (invisible,
+ clipboard_atom,
+ GDK_SELECTION_TYPE_STRING,
+ GDK_CURRENT_TIME);
+}
+
+static void
got_folder(char *uri, CamelFolder *folder, void *data)
{
FolderBrowser *fb = data;
@@ -1346,35 +1500,35 @@ static void
my_folder_browser_init (GtkObject *object)
{
FolderBrowser *fb = FOLDER_BROWSER (object);
-
+
fb->view_collection = NULL;
fb->view_menus = NULL;
-
+
/*
* Setup parent class fields.
*/
GTK_TABLE (fb)->homogeneous = FALSE;
gtk_table_resize (GTK_TABLE (fb), 1, 2);
-
+
/*
* Our instance data
*/
fb->message_list = (MessageList *)message_list_new ();
fb->mail_display = (MailDisplay *)mail_display_new ();
-
+
e_scroll_frame_set_policy(E_SCROLL_FRAME(fb->message_list),
GTK_POLICY_NEVER,
GTK_POLICY_ALWAYS);
gtk_signal_connect (GTK_OBJECT (fb->mail_display->html),
"key_press_event", GTK_SIGNAL_FUNC (on_key_press), fb);
-
+
gtk_signal_connect (GTK_OBJECT (fb->message_list->tree),
"key_press", GTK_SIGNAL_FUNC (etree_key), fb);
-
+
gtk_signal_connect (GTK_OBJECT (fb->message_list->tree),
"right_click", GTK_SIGNAL_FUNC (on_right_click), fb);
-
+
gtk_signal_connect (GTK_OBJECT (fb->message_list->tree),
"double_click", GTK_SIGNAL_FUNC (on_double_click), fb);
@@ -1388,6 +1542,34 @@ my_folder_browser_init (GtkObject *object)
gtk_signal_connect (GTK_OBJECT (fb->message_list->tree), "tree_drag_data_get",
GTK_SIGNAL_FUNC (message_list_drag_data_get), fb);
+ /* cut, copy & paste */
+ if (!invisible) {
+ invisible = gtk_invisible_new ();
+
+ gtk_signal_connect (GTK_OBJECT (invisible), "destroy",
+ GTK_SIGNAL_FUNC (invisible_destroyed),
+ NULL);
+
+ gtk_selection_add_target (invisible,
+ clipboard_atom,
+ GDK_SELECTION_TYPE_STRING,
+ 0);
+ } else
+ gtk_object_ref (GTK_OBJECT (invisible));
+
+ gtk_signal_connect (GTK_OBJECT (invisible),
+ "selection_get",
+ GTK_SIGNAL_FUNC (selection_get),
+ (gpointer) fb);
+ gtk_signal_connect (GTK_OBJECT (invisible),
+ "selection_clear_event",
+ GTK_SIGNAL_FUNC (selection_clear_event),
+ (gpointer) fb);
+ gtk_signal_connect (GTK_OBJECT (invisible),
+ "selection_received",
+ GTK_SIGNAL_FUNC (selection_received),
+ (gpointer) fb);
+
folder_browser_gui_init (fb);
}
@@ -1396,7 +1578,7 @@ folder_browser_new (const GNOME_Evolution_Shell shell)
{
CORBA_Environment ev;
FolderBrowser *folder_browser;
-
+
CORBA_exception_init (&ev);
folder_browser = gtk_type_new (folder_browser_get_type ());