#include <modest-runtime.h>
#include "modest-folder-view.h"
#include <modest-dnd.h>
+#include <modest-platform.h>
/* 'private'/'protected' functions */
static void modest_folder_view_class_init (ModestFolderViewClass *klass);
static void setup_drag_and_drop (GtkTreeView *self);
+static gboolean on_key_pressed (GtkWidget *self,
+ GdkEventKey *event,
+ gpointer user_data);
+
+static void on_configuration_key_changed (ModestConf* conf,
+ const gchar *key,
+ ModestConfEvent event,
+ ModestFolderView *self);
+
enum {
FOLDER_SELECTION_CHANGED_SIGNAL,
LAST_SIGNAL
GtkTreeSelection *cur_selection;
TnyFolderStoreQuery *query;
guint timer_expander;
+
+ gchar *local_account_name;
};
#define MODEST_FOLDER_VIEW_GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE((o), \
gchar *fname = NULL;
gint unread;
TnyFolderType type;
- TnyFolder *folder = NULL;
+ GObject *instance = NULL;
g_return_if_fail (column);
g_return_if_fail (tree_model);
TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN, &fname,
TNY_GTK_FOLDER_STORE_TREE_MODEL_UNREAD_COLUMN, &unread,
TNY_GTK_FOLDER_STORE_TREE_MODEL_TYPE_COLUMN, &type,
- TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN, &folder,
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN, &instance,
-1);
rendobj = G_OBJECT(renderer);
if (!fname)
return;
+
+ if (!instance) {
+ g_free (fname);
+ return;
+ }
- if (folder && type != TNY_FOLDER_TYPE_ROOT) { /* FIXME: tnymail bug? crashes with root folders */
- if (modest_tny_folder_is_local_folder (folder)) {
+ if (type != TNY_FOLDER_TYPE_ROOT) {
+ if (modest_tny_folder_is_local_folder (TNY_FOLDER (instance))) {
TnyFolderType type;
- type = modest_tny_folder_get_local_folder_type (folder);
+ type = modest_tny_folder_get_local_folder_type (TNY_FOLDER (instance));
if (type != TNY_FOLDER_TYPE_UNKNOWN) {
g_free (fname);
fname = g_strdup(modest_local_folder_info_get_type_display_name (type));
}
}
- } else if (folder && type == TNY_FOLDER_TYPE_ROOT) {
- /* FIXME: todo */
- }
-
- if (unread > 0) {
- gchar *folder_title = g_strdup_printf ("%s (%d)", fname, unread);
- g_object_set (rendobj,"text", folder_title, "weight", 800, NULL);
- g_free (folder_title);
- } else
- g_object_set (rendobj,"text", fname, "weight", 400, NULL);
-
- g_free (fname);
- if (folder) g_object_unref (G_OBJECT (folder));
-}
-
-static GdkPixbuf*
-get_cached_icon (const gchar *name)
-{
- GError *err = NULL;
- gpointer pixbuf;
- gpointer orig_key;
- static GHashTable *icon_cache = NULL;
-
- g_return_val_if_fail (name, NULL);
+ /* Use bold font style if there are unread messages */
+ if (unread > 0) {
+ gchar *folder_title = g_strdup_printf ("%s (%d)", fname, unread);
+ g_object_set (rendobj,"text", folder_title, "weight", 800, NULL);
+ g_free (folder_title);
+ } else
+ g_object_set (rendobj,"text", fname, "weight", 400, NULL);
- if (G_UNLIKELY(!icon_cache))
- icon_cache = modest_cache_mgr_get_cache (modest_runtime_get_cache_mgr(),
- MODEST_CACHE_MGR_CACHE_TYPE_PIXBUF);
+ } else {
+ ModestFolderViewPrivate *priv;
+ const gchar *account_name, *account_id;
- if (!icon_cache || !g_hash_table_lookup_extended (icon_cache, name, &orig_key, &pixbuf)) {
- pixbuf = (gpointer)gdk_pixbuf_new_from_file (name, &err);
- if (!pixbuf) {
- g_printerr ("modest: error in icon factory while loading '%s': %s\n",
- name, err->message);
- g_error_free (err);
+ priv = MODEST_FOLDER_VIEW_GET_PRIVATE (data);
+
+ /* If it's a server account */
+ account_id = tny_account_get_id (TNY_ACCOUNT (instance));
+ if (!strcmp (account_id, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
+ account_name = priv->local_account_name;
+ } else {
+ if (!strcmp (account_id, MODEST_MMC_ACCOUNT_ID)) {
+ /* TODO: get MMC card name */
+ } else {
+ account_name = fname;
+ }
}
- /* if we cannot find it, we still insert (if we have a cache), so we get the error
- * only once */
- if (icon_cache)
- g_hash_table_insert (icon_cache, g_strdup(name),(gpointer)pixbuf);
+
+ /* Use bold font style */
+ g_object_set (rendobj,"text", account_name, "weight", 800, NULL);
}
- return GDK_PIXBUF(pixbuf);
+
+ g_object_unref (G_OBJECT (instance));
+ g_free (fname);
}
+
static void
icon_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
{
- GObject *rendobj;
+ GObject *rendobj, *instance;
GdkPixbuf *pixbuf;
TnyFolderType type;
gchar *fname = NULL;
+ const gchar *account_id = NULL;
gint unread;
rendobj = G_OBJECT(renderer);
TNY_GTK_FOLDER_STORE_TREE_MODEL_TYPE_COLUMN, &type,
TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN, &fname,
TNY_GTK_FOLDER_STORE_TREE_MODEL_UNREAD_COLUMN, &unread,
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN, &instance,
-1);
- rendobj = G_OBJECT(renderer);
+
+ if (!fname)
+ return;
+
+ if (!instance) {
+ g_free (fname);
+ return;
+ }
if (type == TNY_FOLDER_TYPE_NORMAL || type == TNY_FOLDER_TYPE_UNKNOWN) {
type = modest_tny_folder_guess_folder_type_from_name (fname);
}
- g_free (fname);
switch (type) {
case TNY_FOLDER_TYPE_ROOT:
- pixbuf = get_cached_icon (MODEST_FOLDER_ICON_ACCOUNT);
+ account_id = tny_account_get_id (TNY_ACCOUNT (instance));
+ if (!strcmp (account_id, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
+ pixbuf = modest_platform_get_icon (MODEST_FOLDER_ICON_LOCAL_FOLDERS);
+ } else {
+ if (!strcmp (account_id, MODEST_MMC_ACCOUNT_ID))
+ pixbuf = modest_platform_get_icon (MODEST_FOLDER_ICON_MMC);
+ else
+ pixbuf = modest_platform_get_icon (MODEST_FOLDER_ICON_ACCOUNT);
+ }
break;
case TNY_FOLDER_TYPE_INBOX:
- pixbuf = get_cached_icon (MODEST_FOLDER_ICON_INBOX);
+ pixbuf = modest_platform_get_icon (MODEST_FOLDER_ICON_INBOX);
break;
case TNY_FOLDER_TYPE_OUTBOX:
- pixbuf = get_cached_icon (MODEST_FOLDER_ICON_OUTBOX);
+ pixbuf = modest_platform_get_icon (MODEST_FOLDER_ICON_OUTBOX);
break;
case TNY_FOLDER_TYPE_JUNK:
- pixbuf = get_cached_icon (MODEST_FOLDER_ICON_JUNK);
+ pixbuf = modest_platform_get_icon (MODEST_FOLDER_ICON_JUNK);
break;
case TNY_FOLDER_TYPE_SENT:
- pixbuf = get_cached_icon (MODEST_FOLDER_ICON_SENT);
+ pixbuf = modest_platform_get_icon (MODEST_FOLDER_ICON_SENT);
break;
case TNY_FOLDER_TYPE_TRASH:
- pixbuf = get_cached_icon (MODEST_FOLDER_ICON_TRASH);
+ pixbuf = modest_platform_get_icon (MODEST_FOLDER_ICON_TRASH);
break;
case TNY_FOLDER_TYPE_DRAFTS:
- pixbuf = get_cached_icon (MODEST_FOLDER_ICON_DRAFTS);
- break;
- case TNY_FOLDER_TYPE_NOTES:
- pixbuf = get_cached_icon (MODEST_FOLDER_ICON_NOTES);
- break;
- case TNY_FOLDER_TYPE_CALENDAR:
- pixbuf = get_cached_icon (MODEST_FOLDER_ICON_CALENDAR);
- break;
- case TNY_FOLDER_TYPE_CONTACTS:
- pixbuf = get_cached_icon (MODEST_FOLDER_ICON_CONTACTS);
+ pixbuf = modest_platform_get_icon (MODEST_FOLDER_ICON_DRAFTS);
break;
case TNY_FOLDER_TYPE_NORMAL:
default:
- pixbuf = get_cached_icon (MODEST_FOLDER_ICON_NORMAL);
+ pixbuf = modest_platform_get_icon (MODEST_FOLDER_ICON_NORMAL);
break;
}
+ g_object_unref (G_OBJECT (instance));
+ g_free (fname);
+
+ /* Set pixbuf */
g_object_set (rendobj, "pixbuf", pixbuf, NULL);
}
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
GtkTreeSelection *sel;
+ ModestConf *conf;
priv = MODEST_FOLDER_VIEW_GET_PRIVATE(obj);
priv->cur_row = NULL;
priv->query = NULL;
+ /* Initialize the local account name */
+ conf = modest_runtime_get_conf();
+ priv->local_account_name = modest_conf_get_string (conf, MODEST_CONF_DEVICE_NAME, NULL);
+
+ /* Build treeview */
column = gtk_tree_view_column_new ();
renderer = gtk_cell_renderer_pixbuf_new();
gtk_tree_view_column_pack_start (column, renderer, FALSE);
gtk_tree_view_column_set_cell_data_func(column, renderer,
- icon_cell_data, NULL, NULL);
+ icon_cell_data, obj, NULL);
renderer = gtk_cell_renderer_text_new();
gtk_tree_view_column_pack_start (column, renderer, FALSE);
gtk_tree_view_column_set_cell_data_func(column, renderer,
- text_cell_data, NULL, NULL);
+ text_cell_data, obj, NULL);
sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(obj));
gtk_tree_selection_set_mode (sel, GTK_SELECTION_SINGLE);
gtk_tree_view_append_column (GTK_TREE_VIEW(obj),column);
+ /* Setup drag and drop */
setup_drag_and_drop (GTK_TREE_VIEW(obj));
+
+ /* Connect signals */
+ g_signal_connect (G_OBJECT (obj),
+ "key-press-event",
+ G_CALLBACK (on_key_pressed), NULL);
+
+ /*
+ * Track changes in the local account name (in the device it
+ * will be the device name)
+ */
+ g_signal_connect (G_OBJECT(conf),
+ "key_changed",
+ G_CALLBACK(on_configuration_key_changed), obj);
+
}
static void
sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(obj));
if (sel)
g_signal_handler_disconnect (G_OBJECT(sel), priv->changed_signal);
+
+ g_free (priv->local_account_name);
G_OBJECT_CLASS(parent_class)->finalize (obj);
}
TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN, &folder,
-1);
- /* If the folder is the same or is a root folder do not notify */
+ /* If the folder is the same do not notify */
if ((type == TNY_FOLDER_TYPE_ROOT) || (priv->cur_folder == folder)) {
g_object_unref (folder);
return;
/*
* This function is the callback of the
- * modest_mail_operation_xfer_msg() call. We check here if the message
- * was correctly asynchronously transfered
+ * modest_mail_operation_xfer_msg() and
+ * modest_mail_operation_xfer_folder() calls. We check here if the
+ * message/folder was correctly asynchronously transferred. The reason
+ * to use the same callback is that the code is the same, it only has
+ * to check that the operation went fine and then finalize the drag
+ * and drop action
*/
static void
on_progress_changed (ModestMailOperation *mail_op, gpointer user_data)
{
- ModestMailOperationQueue *queue;
- gboolean success = FALSE;
+ gboolean success;
DndHelper *helper;
helper = (DndHelper *) user_data;
+ if (!modest_mail_operation_is_finished (mail_op))
+ return;
+
if (modest_mail_operation_get_status (mail_op) ==
MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
success = TRUE;
} else {
- const GError *error;
- error = modest_mail_operation_get_error (mail_op);
- g_warning ("Error transferring messages: %s\n", error->message);
+ success = FALSE;
}
- /* Remove the mail operation */
- queue = modest_runtime_get_mail_operation_queue ();
- modest_mail_operation_queue_remove (queue, mail_op);
- g_object_unref (G_OBJECT (mail_op));
-
/* Notify the drag source. Never call delete, the monitor will
do the job if needed */
gtk_drag_finish (helper->context, success, FALSE, helper->time);
{
TnyHeader *header;
TnyFolder *folder;
- ModestMailOperationQueue *queue;
ModestMailOperation *mail_op;
- gboolean started;
GtkTreeIter source_iter, dest_iter;
/* Get header */
&folder, -1);
/* Transfer message */
- queue = modest_runtime_get_mail_operation_queue ();
mail_op = modest_mail_operation_new ();
- started = modest_mail_operation_xfer_msg (mail_op, header,
- folder, helper->delete_source);
- if (started) {
- g_signal_connect (G_OBJECT (mail_op), "progress_changed",
- G_CALLBACK (on_progress_changed), helper);
- modest_mail_operation_queue_add (queue, mail_op);
- } else {
- const GError *error;
- error = modest_mail_operation_get_error (mail_op);
- if (error)
- g_warning ("Error trying to transfer messages: %s\n",
- error->message);
+ modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
+ mail_op);
+ g_signal_connect (G_OBJECT (mail_op), "progress-changed",
+ G_CALLBACK (on_progress_changed), helper);
- g_slice_free (DndHelper, helper);
- }
+ modest_mail_operation_xfer_msg (mail_op, header, folder, helper->delete_source);
/* Frees */
g_object_unref (G_OBJECT (mail_op));
DndHelper *helper)
{
ModestMailOperation *mail_op;
- const GError *error;
GtkTreeIter parent_iter, iter;
- TnyFolder *folder;
TnyFolderStore *parent_folder;
- gboolean success = FALSE;
+ TnyFolder *folder;
/* Check if the drag is possible */
- if (!gtk_tree_path_compare (helper->source_row, dest_row))
- goto out;
-
- if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (dest_model),
+ if (!gtk_tree_path_compare (helper->source_row, dest_row) ||
+ !gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (dest_model),
dest_row,
- selection_data))
- goto out;
+ selection_data)) {
+
+ gtk_drag_finish (helper->context, FALSE, FALSE, helper->time);
+ gtk_tree_path_free (helper->source_row);
+ g_slice_free (DndHelper, helper);
+ return;
+ }
/* Get data */
gtk_tree_model_get_iter (source_model, &parent_iter, dest_row);
/* Do the mail operation */
mail_op = modest_mail_operation_new ();
- modest_mail_operation_xfer_folder (mail_op, folder, parent_folder,
+ modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
+ mail_op);
+ g_signal_connect (G_OBJECT (mail_op), "progress-changed",
+ G_CALLBACK (on_progress_changed), helper);
+
+ modest_mail_operation_xfer_folder (mail_op,
+ folder,
+ parent_folder,
helper->delete_source);
+ /* Frees */
g_object_unref (G_OBJECT (parent_folder));
g_object_unref (G_OBJECT (folder));
-
- error = modest_mail_operation_get_error (mail_op);
- if (error) {
- g_warning ("Error transferring folder: %s\n", error->message);
- g_object_unref (G_OBJECT (mail_op));
- goto out;
- }
g_object_unref (G_OBJECT (mail_op));
- success = TRUE;
- out:
- gtk_drag_finish (helper->context, success, FALSE, helper->time);
-
- /* Free the helper */
- gtk_tree_path_free (helper->source_row);
- g_slice_free (DndHelper, helper);
}
/*
G_CALLBACK (drag_drop_cb),
NULL);
}
+
+/*
+ * This function manages the navigation through the folders using the
+ * keyboard or the hardware keys in the device
+ */
+static gboolean
+on_key_pressed (GtkWidget *self,
+ GdkEventKey *event,
+ gpointer user_data)
+{
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ gboolean retval = FALSE;
+
+ /* Up and Down are automatically managed by the treeview */
+ if (event->keyval == GDK_Return) {
+ /* Expand/Collapse the selected row */
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self));
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ GtkTreePath *path;
+
+ path = gtk_tree_model_get_path (model, &iter);
+
+ if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (self), path))
+ gtk_tree_view_collapse_row (GTK_TREE_VIEW (self), path);
+ else
+ gtk_tree_view_expand_row (GTK_TREE_VIEW (self), path, FALSE);
+ gtk_tree_path_free (path);
+ }
+ /* No further processing */
+ retval = TRUE;
+ }
+
+ return retval;
+}
+
+/*
+ * We listen to the changes in the local folder account name key,
+ * because we want to show the right name in the view. The local
+ * folder account name corresponds to the device name in the Maemo
+ * version. We do this because we do not want to query gconf on each
+ * tree view refresh. It's better to cache it and change whenever
+ * necessary.
+ */
+static void
+on_configuration_key_changed (ModestConf* conf,
+ const gchar *key,
+ ModestConfEvent event,
+ ModestFolderView *self)
+{
+ ModestFolderViewPrivate *priv;
+ GtkTreeViewColumn *tree_column;
+
+ if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
+ return;
+
+ priv = MODEST_FOLDER_VIEW_GET_PRIVATE(self);
+
+ g_free (priv->local_account_name);
+
+ if (event == MODEST_CONF_EVENT_KEY_UNSET)
+ priv->local_account_name = g_strdup (MODEST_LOCAL_FOLDERS_DEFAULT_DISPLAY_NAME);
+ else
+ priv->local_account_name = modest_conf_get_string (modest_runtime_get_conf(),
+ MODEST_CONF_DEVICE_NAME, NULL);
+
+ /* Force a redraw */
+ tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (self),
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN);
+ gtk_tree_view_column_queue_resize (tree_column);
+}