From: Javier Fernandez Garcia-Boente Date: Mon, 18 Jun 2007 13:13:55 +0000 (+0000) Subject: * Add a new singleton to be used as headers clipboard X-Git-Tag: git_migration_finished~3237 X-Git-Url: http://git.maemo.org/git/?p=modest;a=commitdiff_plain;h=bf831b6566516e6b57de7a64afb732eb8686e792 * Add a new singleton to be used as headers clipboard on copy, cut and paste operaitons. * Implement copy, cut and paste operations for both, headers and folders view. * Fixes: NB##58174 pmo-trunk-r2280 --- diff --git a/src/Makefile.am b/src/Makefile.am index fb4b397..531bd7c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -36,6 +36,8 @@ modest_SOURCES=\ modest-account-mgr-priv.h\ modest-account-mgr.c\ modest-account-mgr.h\ + modest-email-clipboard.c\ + modest-email-clipboard.h\ modest-address-book.h\ modest-cache-mgr.c\ modest-cache-mgr.h\ diff --git a/src/maemo/modest-main-window-ui.h b/src/maemo/modest-main-window-ui.h index dc30576..1299510 100644 --- a/src/maemo/modest-main-window-ui.h +++ b/src/maemo/modest-main-window-ui.h @@ -31,11 +31,13 @@ #define __MODEST_MAIN_WINDOW_UI_PRIV_H__ #include + #include "modest-icon-names.h" #include "modest-ui-actions.h" G_BEGIN_DECLS + /* Action entries */ static const GtkActionEntry modest_action_entries [] = { diff --git a/src/maemo/modest-main-window.c b/src/maemo/modest-main-window.c index 174caca..d8ece67 100644 --- a/src/maemo/modest-main-window.c +++ b/src/maemo/modest-main-window.c @@ -688,7 +688,7 @@ modest_main_window_new (void) menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules"); toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules"); - + /* Add common actions */ gtk_action_group_add_actions (action_group, modest_action_entries, diff --git a/src/modest-email-clipboard.c b/src/modest-email-clipboard.c new file mode 100644 index 0000000..af0e192 --- /dev/null +++ b/src/modest-email-clipboard.c @@ -0,0 +1,277 @@ +/* Copyright (c) 2006, Nokia Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Nokia Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +/* 'private'/'protected' functions */ +static void modest_email_clipboard_class_init (ModestEmailClipboardClass * klass); +static void modest_email_clipboard_init (ModestEmailClipboard * obj); +static void modest_email_clipboard_finalize (GObject * obj); + +/* globals */ +static GObjectClass *parent_class = NULL; + +typedef struct _ModestEmailClipboardPrivate ModestEmailClipboardPrivate; +struct _ModestEmailClipboardPrivate { + TnyList *selection; + TnyFolder *src; + gchar **hidding; + gboolean delete; +}; + + +#define MODEST_EMAIL_CLIPBOARD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ + MODEST_TYPE_EMAIL_CLIPBOARD, \ + ModestEmailClipboardPrivate)) + + +GType +modest_email_clipboard_get_type (void) +{ + static GType my_type = 0; + + if (!my_type) { + static const GTypeInfo my_info = { + sizeof (ModestEmailClipboardClass), + NULL, /* base init */ + NULL, /* base finalize */ + (GClassInitFunc) modest_email_clipboard_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (ModestEmailClipboard), + 1, /* n_preallocs */ + (GInstanceInitFunc) modest_email_clipboard_init, + NULL + }; + + my_type = g_type_register_static (G_TYPE_OBJECT, + "ModestEmailClipboard", + &my_info, 0); + } + return my_type; +} + + + +static void +modest_email_clipboard_class_init (ModestEmailClipboardClass * klass) +{ + GObjectClass *gobject_class; + gobject_class = (GObjectClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + gobject_class->finalize = modest_email_clipboard_finalize; + + g_type_class_add_private (gobject_class, + sizeof (ModestEmailClipboardPrivate)); + + /* signal definitions */ +} + + +static void +modest_email_clipboard_init (ModestEmailClipboard * obj) +{ + ModestEmailClipboardPrivate *priv = + MODEST_EMAIL_CLIPBOARD_GET_PRIVATE (obj); + + priv->src = NULL; + priv->selection = NULL; + priv->hidding = NULL; + priv->delete = FALSE; +} + +static void +modest_email_clipboard_finalize (GObject * obj) +{ + /* Clear objects stored on clipboard */ + modest_email_clipboard_clear (MODEST_EMAIL_CLIPBOARD(obj)); + + G_OBJECT_CLASS(parent_class)->finalize (obj); +} + + +ModestEmailClipboard * +modest_email_clipboard_new () +{ + GObject *obj; + ModestEmailClipboardPrivate *priv; + + obj = G_OBJECT (g_object_new (MODEST_TYPE_EMAIL_CLIPBOARD, NULL)); + priv = MODEST_EMAIL_CLIPBOARD_GET_PRIVATE (obj); + + return MODEST_EMAIL_CLIPBOARD (obj); +} + + +void +modest_email_clipboard_get_data (ModestEmailClipboard *self, + TnyFolder **src_folder, + TnyList **data, + gboolean *delete) +{ + ModestEmailClipboardPrivate *priv = NULL;; + + *src_folder = NULL; + *data = NULL; + *delete = FALSE; + + g_return_if_fail (MODEST_IS_EMAIL_CLIPBOARD (self)); + priv = MODEST_EMAIL_CLIPBOARD_GET_PRIVATE (self); + g_return_if_fail (TNY_IS_FOLDER (priv->src)); + + /* if no data into clipboard, do nothing */ + if (modest_email_clipboard_cleared (self)) return; + + /* Get data stored on clipboard */ + *src_folder = g_object_ref(priv->src); + if (priv->selection) + *data = g_object_ref(priv->selection); + *delete = priv->delete; + + /* Clear objects stored on clipboard */ + modest_email_clipboard_clear (MODEST_EMAIL_CLIPBOARD(self)); +} + +void +modest_email_clipboard_set_data (ModestEmailClipboard *self, + TnyFolder *src_folder, + TnyList *data, + gboolean delete) +{ + ModestEmailClipboardPrivate *priv = NULL;; + TnyIterator *iter = NULL; + GObject *obj = NULL; + gchar *id = NULL; + guint i, n_selected; + + g_return_if_fail (MODEST_IS_EMAIL_CLIPBOARD (self)); + g_return_if_fail (TNY_IS_FOLDER (src_folder)); + priv = MODEST_EMAIL_CLIPBOARD_GET_PRIVATE (self); + + /* if data into clipboard, clear them */ + if (!modest_email_clipboard_cleared (self)) + modest_email_clipboard_clear (self); + + /* set new data */ + priv->src = g_object_ref (src_folder); + if (data != NULL) + priv->selection = g_object_ref (data); + priv->delete = delete; + priv->hidding = NULL; + + /* Fill hidding array (for cut operation) */ + if (delete) { + n_selected = 1; + if (data != NULL) { + n_selected = tny_list_get_length (data); + priv->hidding = g_malloc0(sizeof(gchar *) * n_selected); + iter = tny_list_create_iterator (priv->selection); + i = 0; + while (!tny_iterator_is_done (iter)) { + obj = tny_iterator_get_current (iter); + if (TNY_IS_HEADER (obj)) + id = g_strdup(tny_header_get_message_id (TNY_HEADER (obj))); + + priv->hidding[i++] = id; + tny_iterator_next (iter); + + g_object_unref (obj); + } + g_object_unref (iter); + } + else { + priv->hidding = g_malloc0(sizeof(gchar *)); + id = g_strdup (tny_folder_get_id (src_folder)); + priv->hidding[0] = id; + } + } +} + +void +modest_email_clipboard_clear (ModestEmailClipboard *self) +{ + ModestEmailClipboardPrivate *priv = NULL; + guint i, n_selected; + + g_return_if_fail (MODEST_IS_EMAIL_CLIPBOARD (self)); + priv = MODEST_EMAIL_CLIPBOARD_GET_PRIVATE (self); + + n_selected = 1; + if (priv->src) + g_object_unref (priv->src); + if (priv->selection) { + n_selected = tny_list_get_length(priv->selection); + g_object_unref (priv->selection); + } + if (priv->hidding) { + for (i=0; i < n_selected; i++) + g_free (priv->hidding[i]); + g_free(priv->hidding); + } + + priv->src = NULL; + priv->selection = NULL; + priv->hidding = NULL; + priv->delete = FALSE; +} + +gboolean +modest_email_clipboard_cleared (ModestEmailClipboard *self) +{ + ModestEmailClipboardPrivate *priv = NULL;; + gboolean cleared = FALSE; + + g_return_val_if_fail (MODEST_IS_EMAIL_CLIPBOARD (self), TRUE); + priv = MODEST_EMAIL_CLIPBOARD_GET_PRIVATE (self); + + cleared = ((priv->src == NULL) && (priv->selection == NULL)); + + return cleared; +} + +const gchar ** +modest_email_clipboard_get_hidding_ids (ModestEmailClipboard *self, + guint *n_selected) +{ + ModestEmailClipboardPrivate *priv = NULL;; + + *n_selected = 0; + + g_return_val_if_fail (MODEST_IS_EMAIL_CLIPBOARD (self), NULL); + priv = MODEST_EMAIL_CLIPBOARD_GET_PRIVATE (self); + + if (priv->selection != NULL) + *n_selected = tny_list_get_length (priv->selection); + else + *n_selected = 1; + + return (const gchar **) priv->hidding; +} + diff --git a/src/modest-email-clipboard.h b/src/modest-email-clipboard.h new file mode 100644 index 0000000..d34e329 --- /dev/null +++ b/src/modest-email-clipboard.h @@ -0,0 +1,147 @@ +/* Copyright (c) 2006, Nokia Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Nokia Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef __MODEST_EMAIL_CLIPBOARD_H__ +#define __MODEST_EMAIL_CLIPBOARD_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +/* convenience macros */ +#define MODEST_TYPE_EMAIL_CLIPBOARD (modest_email_clipboard_get_type()) +#define MODEST_EMAIL_CLIPBOARD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MODEST_TYPE_EMAIL_CLIPBOARD,ModestEmailClipboard)) +#define MODEST_EMAIL_CLIPBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MODEST_TYPE_EMAIL_CLIPBOARD,ModestEmailClipboardClass)) +#define MODEST_IS_EMAIL_CLIPBOARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MODEST_TYPE_EMAIL_CLIPBOARD)) +#define MODEST_IS_EMAIL_CLIPBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MODEST_TYPE_EMAIL_CLIPBOARD)) +#define MODEST_EMAIL_CLIPBOARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MODEST_TYPE_EMAIL_CLIPBOARD,ModestEmailClipboardClass)) + +typedef struct _ModestEmailClipboard ModestEmailClipboard; +typedef struct _ModestEmailClipboardClass ModestEmailClipboardClass; + +struct _ModestEmailClipboard { + GObject parent; +}; + +struct _ModestEmailClipboardClass { + GObjectClass parent_class; + +}; + +/** + * modest_email_clipboard_get_type: + * + * get the GType for #ModestEmailClipboard + * + * Returns: the GType + */ +GType modest_email_clipboard_get_type (void) G_GNUC_CONST; + + +/** + * modest_email_clipboard_new: + * + * Returns: a new #ModestEmailClipboard, or NULL in case of error + */ +ModestEmailClipboard* modest_email_clipboard_new (void); + + +/** + * modest_email_clipboard_get_data: + * @self: a #ModestEmailClipboard singlenton instance. + * @src_folder: a #TnyFolder instance which is the source of selection data. + * @data: a #TnyList of objects to manage. + * @delete: determines whether data will be removed after copy them. + * + * Gets data from clipboard to manage them with copy, cut and paste operations. + * Currently imementation allows #TnyFolder or #TnyHeader objects. + * + */ +void +modest_email_clipboard_get_data (ModestEmailClipboard *self, + TnyFolder **src_folder, + TnyList **data, + gboolean *delete); + +/** + * modest_email_clipboard_set_data: + * @self: a #ModestEmailClipboard singlenton instance. + * @src_folder: a #TnyFolder instance which is the source of selection data. + * @data: a #TnyList of objects to manage. + * @delete: determines whether data will be removed after copy them. + * + * Sets data on clipboard to manage them wiht copy, cut and paste operations. + * Currently imementation allows #TnyFolder or #TnyHeader objects. + * + */ +void modest_email_clipboard_set_data (ModestEmailClipboard *self, + TnyFolder *src_folder, + TnyList *data, + gboolean delete); + + +/** + * modest_email_clipboard_clear: + * @self: a #ModestEmailClipboard singlenton instance. + * + * Clear all data stored inside clipboard. + */ +void modest_email_clipboard_clear (ModestEmailClipboard *self); + + +/** + * modest_email_clipboard_cleared: + * @self: a #ModestEmailClipboard singlenton instance. + * + * Determines if clipboard is clreared, no seleciton data is stored. + * + * returns TRUE, if clipboard is cleared, FALSE otherwise. + */ +gboolean modest_email_clipboard_cleared (ModestEmailClipboard *self); + + +/** + * modest_email_clipboard_set_data: + * @self: a #ModestEmailClipboard singlenton instance. + * @n_selected: the number of items copied and marked to delete. + * + * Returns the string array of item identifiers stored on clipboard. + * + * returns TRUE, if clipboard is cleared, FALSE otherwise. + */ +const gchar **modest_email_clipboard_get_hidding_ids (ModestEmailClipboard *self, + guint *n_selected); + +G_END_DECLS + +#endif /* __MODEST_EMAIL_CLIPBOARD_H__ */ diff --git a/src/modest-runtime.c b/src/modest-runtime.c index ed4cf76..9e843c0 100644 --- a/src/modest-runtime.c +++ b/src/modest-runtime.c @@ -93,6 +93,13 @@ modest_runtime_get_account_mgr (void) return modest_singletons_get_account_mgr (_singletons); } +ModestEmailClipboard* +modest_runtime_get_email_clipboard (void) +{ + g_return_val_if_fail (_singletons, NULL); + return modest_singletons_get_email_clipboard (_singletons); +} + ModestTnyAccountStore* modest_runtime_get_account_store (void) { diff --git a/src/modest-runtime.h b/src/modest-runtime.h index 7399e12..d84b43c 100644 --- a/src/modest-runtime.h +++ b/src/modest-runtime.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -132,6 +133,15 @@ ModestConf* modest_runtime_get_conf (void); ModestAccountMgr* modest_runtime_get_account_mgr (void); /** + * modest_runtime_get_email_clipboard: + * + * get the #ModestEmailClipboard singleton instance + * + * Returns: the #ModestEamilClipboard singleton. This should NOT be unref'd. + **/ +ModestEmailClipboard* modest_runtime_get_email_clipboard (void); + +/** * modest_runtime_get_account_store: * * get the ModestTnyAccountStore singleton instance diff --git a/src/modest-singletons.c b/src/modest-singletons.c index 9c0ede2..c373988 100644 --- a/src/modest-singletons.c +++ b/src/modest-singletons.c @@ -39,6 +39,7 @@ typedef struct _ModestSingletonsPrivate ModestSingletonsPrivate; struct _ModestSingletonsPrivate { ModestConf *conf; ModestAccountMgr *account_mgr; + ModestEmailClipboard *email_clipboard; ModestTnyAccountStore *account_store; ModestCacheMgr *cache_mgr; ModestMailOperationQueue *mail_op_queue; @@ -94,14 +95,15 @@ modest_singletons_init (ModestSingletons *obj) ModestSingletonsPrivate *priv; priv = MODEST_SINGLETONS_GET_PRIVATE(obj); - priv->conf = NULL; - priv->account_mgr = NULL; - priv->account_store = NULL; - priv->cache_mgr = NULL; - priv->mail_op_queue = NULL; - priv->platform_fact = NULL; - priv->device = NULL; - priv->window_mgr = NULL; + priv->conf = NULL; + priv->account_mgr = NULL; + priv->email_clipboard = NULL; + priv->account_store = NULL; + priv->cache_mgr = NULL; + priv->mail_op_queue = NULL; + priv->platform_fact = NULL; + priv->device = NULL; + priv->window_mgr = NULL; priv->conf = modest_conf_new (); if (!priv->conf) { @@ -115,6 +117,12 @@ modest_singletons_init (ModestSingletons *obj) return; } + priv->email_clipboard = modest_email_clipboard_new (); + if (!priv->email_clipboard) { + g_printerr ("modest: cannot create modest email clipboard instance\n"); + return; + } + priv->platform_fact = modest_tny_platform_factory_get_instance (); if (!priv->platform_fact) { g_printerr ("modest: cannot create platform factory instance\n"); @@ -171,6 +179,12 @@ modest_singletons_finalize (GObject *obj) priv->account_mgr = NULL; } + if (priv->email_clipboard) { + modest_runtime_verify_object_last_ref(priv->email_clipboard,""); + g_object_unref (G_OBJECT(priv->email_clipboard)); + priv->email_clipboard = NULL; + } + if (priv->conf) { modest_runtime_verify_object_last_ref(priv->conf,""); g_object_unref (G_OBJECT(priv->conf)); @@ -227,7 +241,7 @@ modest_singletons_new (void) priv = MODEST_SINGLETONS_GET_PRIVATE(self); /* widget_factory will still be NULL, as it is initialized lazily */ - if (!(priv->conf && priv->account_mgr && priv->account_store && + if (!(priv->conf && priv->account_mgr && priv->email_clipboard && priv->account_store && priv->cache_mgr && priv->mail_op_queue && priv->device && priv->platform_fact)) { g_printerr ("modest: failed to create singletons object\n"); g_object_unref (G_OBJECT(self)); @@ -253,6 +267,13 @@ modest_singletons_get_account_mgr (ModestSingletons *self) return MODEST_SINGLETONS_GET_PRIVATE(self)->account_mgr; } +ModestEmailClipboard* +modest_singletons_get_email_clipboard (ModestSingletons *self) +{ + g_return_val_if_fail (self, NULL); + return MODEST_SINGLETONS_GET_PRIVATE(self)->email_clipboard; +} + ModestTnyAccountStore* modest_singletons_get_account_store (ModestSingletons *self) { @@ -274,8 +295,6 @@ modest_singletons_get_mail_operation_queue (ModestSingletons *self) return MODEST_SINGLETONS_GET_PRIVATE(self)->mail_op_queue; } - - TnyDevice* modest_singletons_get_device (ModestSingletons *self) { @@ -284,7 +303,6 @@ modest_singletons_get_device (ModestSingletons *self) } - TnyPlatformFactory* modest_singletons_get_platform_factory (ModestSingletons *self) { diff --git a/src/modest-singletons.h b/src/modest-singletons.h index 2e5d1fa..1c40a50 100644 --- a/src/modest-singletons.h +++ b/src/modest-singletons.h @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -111,6 +112,17 @@ ModestConf* modest_singletons_get_conf (ModestSingletons **/ ModestAccountMgr* modest_singletons_get_account_mgr (ModestSingletons *self); +/** + * modest_singletons_get_account_mgr: + * @self: a valid #ModestSingletons instance + * + * get the #ModestEamilClipboard singleton instance + * don't use this function directly, use the modest-runtime + * functions instead. + * + * Returns: the #ModestEmailClipboard singleton + **/ +ModestEmailClipboard* modest_singletons_get_email_clipboard (ModestSingletons *self); /** * modest_singletons_get_account_store: diff --git a/src/modest-ui-actions.c b/src/modest-ui-actions.c index 5dc7a56..9b8dfff 100644 --- a/src/modest-ui-actions.c +++ b/src/modest-ui-actions.c @@ -97,6 +97,7 @@ typedef struct _ReplyForwardHelper { GtkWidget *parent_window; } ReplyForwardHelper; + /* * The do_headers_action uses this kind of functions to perform some * action to each member of a list of headers @@ -2157,6 +2158,10 @@ modest_ui_actions_on_cut (GtkAction *action, clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget)); gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE); + } else if (MODEST_IS_HEADER_VIEW (focused_widget)) { + modest_header_view_cut_selection (MODEST_HEADER_VIEW (focused_widget)); + } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) { + modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget)); } } @@ -2175,10 +2180,14 @@ modest_ui_actions_on_copy (GtkAction *action, gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget)); } else if (GTK_IS_TEXT_VIEW (focused_widget)) { GtkTextBuffer *buffer; - buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget)); gtk_text_buffer_copy_clipboard (buffer, clipboard); - } + modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget)); + } else if (MODEST_IS_HEADER_VIEW (focused_widget)) { + modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget)); + } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) { + modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget)); + } } void @@ -2197,6 +2206,7 @@ modest_ui_actions_on_paste (GtkAction *action, ModestWindow *window) { GtkWidget *focused_widget; + ModestMailOperation *mail_op = NULL; focused_widget = gtk_window_get_focus (GTK_WINDOW (window)); if (GTK_IS_EDITABLE (focused_widget)) { @@ -2208,6 +2218,52 @@ modest_ui_actions_on_paste (GtkAction *action, clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget)); gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE); + } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) { + ModestEmailClipboard *clipboard = NULL; + TnyFolder *src_folder = NULL; + TnyFolderStore *folder_store = NULL; + TnyList *data = NULL; + gboolean delete = FALSE; + + /* Check clipboard source */ + clipboard = modest_runtime_get_email_clipboard (); + if (modest_email_clipboard_cleared (clipboard)) + return; + + /* Get elements to paste */ + modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete); + + /* Create a new mail operation */ + mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window)); + modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), + mail_op); + + /* Get destination folder */ + folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget)); + + /* transfer messages */ + if (data != NULL) { + modest_mail_operation_xfer_msgs (mail_op, + data, + TNY_FOLDER (folder_store), + delete, + NULL, + NULL); + + } else if (src_folder != NULL) { + modest_mail_operation_xfer_folder (mail_op, + src_folder, + folder_store, + delete); + } + + /* Free */ + if (data != NULL) + g_object_unref (data); + if (src_folder != NULL) + g_object_unref (src_folder); + if (folder_store != NULL) + g_object_unref (folder_store); } } @@ -3191,3 +3247,5 @@ _on_send_receive_progress_changed (ModestMailOperation *mail_op, modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data)); } + + diff --git a/src/widgets/modest-folder-view.c b/src/widgets/modest-folder-view.c index 26451a6..887d99f 100644 --- a/src/widgets/modest-folder-view.c +++ b/src/widgets/modest-folder-view.c @@ -125,6 +125,12 @@ static gint expand_row_timeout (gpointer data); static void setup_drag_and_drop (GtkTreeView *self); +static void _clipboard_set_selected_data (ModestFolderView *folder_view, gboolean delete); + +static void _clear_hidding_filter (ModestFolderView *folder_view); + + + enum { FOLDER_SELECTION_CHANGED_SIGNAL, FOLDER_DISPLAY_NAME_CHANGED_SIGNAL, @@ -142,6 +148,13 @@ struct _ModestFolderViewPrivate { gulong account_removed_signal; gulong conf_key_signal; + /* not unref this object, its a singlenton */ + ModestEmailClipboard *clipboard; + + /* Filter tree model */ + gchar **hidding_ids; + guint n_selected; + TnyFolderStoreQuery *query; guint timer_expander; @@ -476,6 +489,11 @@ modest_folder_view_init (ModestFolderView *obj) conf = modest_runtime_get_conf(); priv->local_account_name = modest_conf_get_string (conf, MODEST_CONF_DEVICE_NAME, NULL); + /* Init email clipboard */ + priv->clipboard = modest_runtime_get_email_clipboard (); + priv->hidding_ids = NULL; + priv->n_selected = 0; + /* Build treeview */ add_columns (GTK_WIDGET (obj)); @@ -551,6 +569,9 @@ modest_folder_view_finalize (GObject *obj) priv->conf_key_signal = 0; } + /* Clear hidding array created by cut operation */ + _clear_hidding_filter (MODEST_FOLDER_VIEW (obj)); + G_OBJECT_CLASS(parent_class)->finalize (obj); } @@ -708,9 +729,17 @@ filter_row (GtkTreeModel *model, GtkTreeIter *iter, gpointer data) { + ModestFolderViewPrivate *priv; gboolean retval = TRUE; TnyFolderType type = TNY_FOLDER_TYPE_UNKNOWN; GObject *instance = NULL; + const gchar *id = NULL; + guint i; + gboolean found = FALSE; + gboolean cleared = FALSE; + + g_return_val_if_fail (MODEST_IS_FOLDER_VIEW (data), FALSE); + priv = MODEST_FOLDER_VIEW_GET_PRIVATE (data); gtk_tree_model_get (model, iter, TNY_GTK_FOLDER_STORE_TREE_MODEL_TYPE_COLUMN, &type, @@ -735,8 +764,6 @@ filter_row (GtkTreeModel *model, if (!modest_tny_account_is_virtual_local_folders (acc) && strcmp (account_id, MODEST_MMC_ACCOUNT_ID)) { /* Show only the visible account id */ - ModestFolderViewPrivate *priv = - MODEST_FOLDER_VIEW_GET_PRIVATE (data); if (priv->visible_account_id && strcmp (account_id, priv->visible_account_id)) retval = FALSE; } @@ -750,6 +777,19 @@ filter_row (GtkTreeModel *model, /* The virtual local-folders folder store is also shown by default. */ + /* Check hiding (if necessary) */ + cleared = modest_email_clipboard_cleared (priv->clipboard); + if ((retval) && (!cleared) && (TNY_IS_FOLDER (instance))) { + id = tny_folder_get_id (TNY_FOLDER(instance)); + if (priv->hidding_ids != NULL) + for (i=0; i < priv->n_selected && !found; i++) + if (priv->hidding_ids[i] != NULL && id != NULL) + found = (!strcmp (priv->hidding_ids[i], id)); + + retval = !found; + } + + /* Free */ g_object_unref (instance); return retval; @@ -800,23 +840,30 @@ modest_folder_view_update_model (ModestFolderView *self, cmp_rows, NULL, NULL); /* Create filter model */ - if (priv->style == MODEST_FOLDER_VIEW_STYLE_SHOW_ONE) { - filter_model = gtk_tree_model_filter_new (sortable, NULL); - gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter_model), - filter_row, - self, - NULL); - } + filter_model = gtk_tree_model_filter_new (sortable, NULL); + gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter_model), + filter_row, + self, + NULL); +/* if (priv->style == MODEST_FOLDER_VIEW_STYLE_SHOW_ONE) { */ +/* filter_model = gtk_tree_model_filter_new (sortable, NULL); */ +/* gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter_model), */ +/* filter_row, */ +/* self, */ +/* NULL); */ +/* } */ /* Set new model */ - gtk_tree_view_set_model (GTK_TREE_VIEW(self), - (filter_model) ? filter_model : sortable); + gtk_tree_view_set_model (GTK_TREE_VIEW(self), filter_model); +/* gtk_tree_view_set_model (GTK_TREE_VIEW(self), */ +/* (filter_model) ? filter_model : sortable); */ expand_root_items (self); /* expand all account folders */ g_object_unref (model); - if (filter_model) - g_object_unref (filter_model); + g_object_unref (filter_model); +/* if (filter_model) */ +/* g_object_unref (filter_model); */ g_object_unref (sortable); @@ -1700,3 +1747,76 @@ modest_folder_view_select_first_inbox_or_local (ModestFolderView *self) gtk_tree_selection_select_iter (sel, &iter); } } + +void +modest_folder_view_copy_selection (ModestFolderView *folder_view) +{ + /* Copy selection */ + _clipboard_set_selected_data (folder_view, FALSE); +} + +void +modest_folder_view_cut_selection (ModestFolderView *folder_view) +{ + ModestFolderViewPrivate *priv = NULL; + GtkTreeModel *model = NULL; + const gchar **hidding = NULL; + guint i, n_selected; + + g_return_if_fail (MODEST_IS_FOLDER_VIEW (folder_view)); + priv = MODEST_FOLDER_VIEW_GET_PRIVATE (folder_view); + + /* Copy selection */ + _clipboard_set_selected_data (folder_view, TRUE); + + /* Get hidding ids */ + hidding = modest_email_clipboard_get_hidding_ids (priv->clipboard, &n_selected); + + /* Clear hidding array created by previous cut operation */ + _clear_hidding_filter (MODEST_FOLDER_VIEW (folder_view)); + + /* Copy hidding array */ + priv->n_selected = n_selected; + priv->hidding_ids = g_malloc0(sizeof(gchar *) * n_selected); + for (i=0; i < n_selected; i++) + priv->hidding_ids[i] = g_strdup(hidding[i]); + + /* Hide cut folders */ + model = gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)); + gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (model)); +} + +static void +_clipboard_set_selected_data (ModestFolderView *folder_view, + gboolean delete) +{ + ModestFolderViewPrivate *priv = NULL; + TnyFolderStore *folder = NULL; + + g_return_if_fail (MODEST_IS_FOLDER_VIEW (folder_view)); + priv = MODEST_FOLDER_VIEW_GET_PRIVATE (folder_view); + + /* Set selected data on clipboard */ + g_return_if_fail (MODEST_IS_EMAIL_CLIPBOARD (priv->clipboard)); + folder = modest_folder_view_get_selected (folder_view); + modest_email_clipboard_set_data (priv->clipboard, TNY_FOLDER(folder), NULL, delete); + + /* Free */ + g_object_unref (folder); +} + +static void +_clear_hidding_filter (ModestFolderView *folder_view) +{ + ModestFolderViewPrivate *priv; + guint i; + + g_return_if_fail (MODEST_IS_FOLDER_VIEW (folder_view)); + priv = MODEST_FOLDER_VIEW_GET_PRIVATE(folder_view); + + if (priv->hidding_ids != NULL) { + for (i=0; i < priv->n_selected; i++) + g_free (priv->hidding_ids[i]); + g_free(priv->hidding_ids); + } +} diff --git a/src/widgets/modest-folder-view.h b/src/widgets/modest-folder-view.h index 20cc430..6eab8a8 100644 --- a/src/widgets/modest-folder-view.h +++ b/src/widgets/modest-folder-view.h @@ -185,6 +185,41 @@ const gchar* modest_folder_view_get_account_id_of_visible_server_account (Modest void modest_folder_view_select_first_inbox_or_local (ModestFolderView *self); +/** + * modest_folder_view_copy_selection: + * @self: a #ModestFolderView + * + * Stores a #TnyList of selected folders in the own clibpoard of + * @self folder view. + **/ +void +modest_folder_view_copy_selection (ModestFolderView *folder_view); + +/** + * modest_folder_view_cut_selection: + * @self: a #ModestFolderView + * + * Stores a #TnyList of selected folders in the own clibpoard of + * @self folder view and filter them into folders tree model to + * hide these rows in treeview. + **/ +void +modest_folder_view_cut_selection (ModestFolderView *folder_view); + + +/** + * modest_folder_view_paste_selection: + * @self: a #ModestFolderView + * @folders: ouput parameter with a #TnyList of folders which will be returned. + * @delete: output parameter with indication about delete or not the selected folders. + * + * Gets the selected folders to copy/cut. + **/ +void +modest_folder_view_paste_selection (ModestFolderView *folder_view, + TnyList **folders, + gboolean *delete); + G_END_DECLS #endif /* __MODEST_FOLDER_VIEW_H__ */ diff --git a/src/widgets/modest-header-view.c b/src/widgets/modest-header-view.c index 62e604d..297e1cb 100644 --- a/src/widgets/modest-header-view.c +++ b/src/widgets/modest-header-view.c @@ -65,6 +65,10 @@ static gint cmp_subject_rows (GtkTreeModel *tree_model, GtkTreeIter *iter2, gpointer user_data); +static gboolean filter_row (GtkTreeModel *model, + GtkTreeIter *iter, + gpointer data); + static void on_selection_changed (GtkTreeSelection *sel, gpointer user_data); @@ -81,6 +85,10 @@ static void folder_monitor_update (TnyFolderObserver *self, static void tny_folder_observer_init (TnyFolderObserverIface *klass); +static void _clipboard_set_selected_data (ModestHeaderView *header_view, gboolean delete); + +static void _clear_hidding_filter (ModestHeaderView *header_view); + typedef struct _ModestHeaderViewPrivate ModestHeaderViewPrivate; struct _ModestHeaderViewPrivate { @@ -90,6 +98,13 @@ struct _ModestHeaderViewPrivate { TnyFolderMonitor *monitor; GMutex *observers_lock; + /* not unref this object, its a singlenton */ + ModestEmailClipboard *clipboard; + + /* Filter tree model */ + gchar **hidding_ids; + guint n_selected; + gint sort_colid[2][TNY_FOLDER_TYPE_NUM]; gint sort_type[2][TNY_FOLDER_TYPE_NUM]; @@ -262,7 +277,7 @@ remove_all_columns (ModestHeaderView *obj) gboolean modest_header_view_set_columns (ModestHeaderView *self, const GList *columns, TnyFolderType type) { - GtkTreeModel *sortable; + GtkTreeModel *tree_filter, *sortable; GtkTreeViewColumn *column=NULL; GtkTreeSelection *selection = NULL; GtkCellRenderer *renderer_msgtype,*renderer_header, @@ -324,7 +339,9 @@ modest_header_view_set_columns (ModestHeaderView *self, const GList *columns, Tn selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(self)); gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); - sortable = gtk_tree_view_get_model (GTK_TREE_VIEW (self)); +/* sortable = gtk_tree_view_get_model (GTK_TREE_VIEW (self)); */ + tree_filter = gtk_tree_view_get_model (GTK_TREE_VIEW (self)); + sortable = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER(tree_filter)); /* Add new columns */ for (cursor = columns; cursor; cursor = g_list_next(cursor)) { @@ -473,6 +490,10 @@ modest_header_view_init (ModestHeaderView *obj) priv->monitor = NULL; priv->observers_lock = g_mutex_new (); + priv->clipboard = modest_runtime_get_email_clipboard (); + priv->hidding_ids = NULL; + priv->n_selected = 0; + /* Sort parameters */ for (j=0; j < 2; j++) { for (i=0; i < TNY_FOLDER_TYPE_NUM; i++) { @@ -507,6 +528,9 @@ modest_header_view_finalize (GObject *obj) priv->folder = NULL; } + /* Clear hidding array created by cut operation */ + _clear_hidding_filter (MODEST_HEADER_VIEW (obj)); + G_OBJECT_CLASS(parent_class)->finalize (obj); } @@ -744,7 +768,11 @@ modest_header_view_get_style (ModestHeaderView *self) static void modest_header_view_set_model (GtkTreeView *header_view, GtkTreeModel *model) { - GtkTreeModel *old_model_sort = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)); + GtkTreeModel *old_model_filter = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)); + GtkTreeModel *old_model_sort = NULL; + + if (old_model_filter) + old_model_sort = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER(old_model_filter)); if (old_model_sort && GTK_IS_TREE_MODEL_SORT (old_model_sort)) { GtkTreeModel *old_model; @@ -780,7 +808,7 @@ modest_header_view_set_folder_intern (ModestHeaderView *self, TnyFolder *folder) TnyList *headers; ModestHeaderViewPrivate *priv; GList *cols, *cursor; - GtkTreeModel *sortable; + GtkTreeModel *filter_model, *sortable; guint sort_colid; GtkSortType sort_type; @@ -807,6 +835,14 @@ modest_header_view_set_folder_intern (ModestHeaderView *self, TnyFolder *folder) sortable = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL(headers)); g_object_unref (G_OBJECT (headers)); + /* Create a tree model filter to hide and show rows for cut operations */ + filter_model = gtk_tree_model_filter_new (sortable, NULL); + gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter_model), + filter_row, + self, + NULL); + g_object_unref (G_OBJECT (sortable)); + /* install our special sorting functions */ cursor = cols = gtk_tree_view_get_columns (GTK_TREE_VIEW(self)); @@ -829,8 +865,10 @@ modest_header_view_set_folder_intern (ModestHeaderView *self, TnyFolder *folder) } /* Set new model */ - modest_header_view_set_model (GTK_TREE_VIEW (self), sortable); - g_object_unref (G_OBJECT (sortable)); + modest_header_view_set_model (GTK_TREE_VIEW (self), filter_model); + g_object_unref (G_OBJECT (filter_model)); +/* modest_header_view_set_model (GTK_TREE_VIEW (self), sortable); */ +/* g_object_unref (G_OBJECT (sortable)); */ /* Free */ g_list_free (cols); @@ -842,12 +880,14 @@ modest_header_view_sort_by_column_id (ModestHeaderView *self, GtkSortType sort_type) { ModestHeaderViewPrivate *priv = NULL; - GtkTreeModel *sortable = NULL; + GtkTreeModel *tree_filter, *sortable = NULL; TnyFolderType type; /* Get model and private data */ priv = MODEST_HEADER_VIEW_GET_PRIVATE(self); - sortable = gtk_tree_view_get_model (GTK_TREE_VIEW (self)); + tree_filter = gtk_tree_view_get_model (GTK_TREE_VIEW (self)); + sortable = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER(tree_filter)); +/* sortable = gtk_tree_view_get_model (GTK_TREE_VIEW (self)); */ /* Sort tree model */ type = modest_tny_folder_guess_folder_type (priv->folder); @@ -1311,8 +1351,12 @@ idle_notify_headers_count_changed (gpointer data) priv = MODEST_HEADER_VIEW_GET_PRIVATE (helper->self); g_mutex_lock (priv->observers_lock); + /* Emmit signal to evaluate how headers changes affects to the window view */ g_signal_emit (G_OBJECT(helper->self), signals[MSG_COUNT_CHANGED_SIGNAL], 0, folder, helper->change); + /* Added or removed headers, so data sotred on cliboard are invalid */ + modest_email_clipboard_clear (priv->clipboard); + g_mutex_unlock (priv->observers_lock); return FALSE; @@ -1352,3 +1396,121 @@ modest_header_view_clear (ModestHeaderView *self) { modest_header_view_set_folder (self, NULL, NULL, NULL); } + +void +modest_header_view_copy_selection (ModestHeaderView *header_view) +{ + /* Copy selection */ + _clipboard_set_selected_data (header_view, FALSE); +} + +void +modest_header_view_cut_selection (ModestHeaderView *header_view) +{ + ModestHeaderViewPrivate *priv = NULL; + GtkTreeModel *model = NULL; + const gchar **hidding = NULL; + guint i, n_selected; + + g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view)); + priv = MODEST_HEADER_VIEW_GET_PRIVATE (header_view); + + /* Copy selection */ + _clipboard_set_selected_data (header_view, TRUE); + + /* Get hidding ids */ + hidding = modest_email_clipboard_get_hidding_ids (priv->clipboard, &n_selected); + + /* Clear hidding array created by previous cut operation */ + _clear_hidding_filter (MODEST_HEADER_VIEW (header_view)); + + /* Copy hidding array */ + priv->n_selected = n_selected; + priv->hidding_ids = g_malloc0(sizeof(gchar *) * n_selected); + for (i=0; i < n_selected; i++) + priv->hidding_ids[i] = g_strdup(hidding[i]); + + /* Hide cut headers */ + model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)); + if (GTK_IS_TREE_MODEL_FILTER (model)) + gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (model)); +} + + + + +static void +_clipboard_set_selected_data (ModestHeaderView *header_view, + gboolean delete) +{ + ModestHeaderViewPrivate *priv = NULL; + TnyList *headers = NULL; + + g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view)); + priv = MODEST_HEADER_VIEW_GET_PRIVATE (header_view); + + /* Set selected data on clipboard */ + g_return_if_fail (MODEST_IS_EMAIL_CLIPBOARD (priv->clipboard)); + headers = modest_header_view_get_selected_headers (header_view); + modest_email_clipboard_set_data (priv->clipboard, priv->folder, headers, delete); + + /* Free */ + g_object_unref (headers); +} + + + +static gboolean +filter_row (GtkTreeModel *model, + GtkTreeIter *iter, + gpointer user_data) +{ + ModestHeaderViewPrivate *priv = NULL; + TnyHeader *header = NULL; + guint i; + gchar *id = NULL; + gboolean found = FALSE; + + g_return_val_if_fail (MODEST_IS_HEADER_VIEW (user_data), FALSE); + priv = MODEST_HEADER_VIEW_GET_PRIVATE (user_data); + + /* If no data on clipboard, return always TRUE */ + if (modest_email_clipboard_cleared(priv->clipboard)) return TRUE; + + /* Get header from model */ + gtk_tree_model_get (model, iter, + TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN, &header, + -1); + + /* Get message id from header (ensure is a valid id) */ + if (!header) return FALSE; + id = g_strdup(tny_header_get_message_id (header)); + + /* Check hiding */ + if (priv->hidding_ids != NULL) + for (i=0; i < priv->n_selected && !found; i++) + if (priv->hidding_ids[i] != NULL && id != NULL) + found = (!strcmp (priv->hidding_ids[i], id)); + + /* Free */ + g_object_unref (header); + g_free(id); + + return !found; +} + +static void +_clear_hidding_filter (ModestHeaderView *header_view) +{ + ModestHeaderViewPrivate *priv; + guint i; + + g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view)); + priv = MODEST_HEADER_VIEW_GET_PRIVATE(header_view); + + if (priv->hidding_ids != NULL) { + for (i=0; i < priv->n_selected; i++) + g_free (priv->hidding_ids[i]); + g_free(priv->hidding_ids); + } +}