Re: Patch: gtk folder store configurable with flags
- From: José Dapena Paz <jdapena igalia com>
- To: Philip Van Hoof <spam pvanhoof be>
- Cc: tinymail-devel-list <tinymail-devel-list gnome org>
- Subject: Re: Patch: gtk folder store configurable with flags
- Date: Fri, 21 Nov 2008 18:38:05 +0100
El vie, 21-11-2008 a las 18:16 +0100, Philip Van Hoof escribió:
> No patch, please attach it :)
Here it goes, now patch attached :).
> > This patch adds a new constructor for the gtk folder store, so that
> > developer can pass some flags specifying the way the folder store will
> > be filled.
> >
> > I added two flags:
> > * One makes folder names in treemodel contain the full path, instead of
> > the name of the folder leaf.
> > * The other one puts all the folders at the same tree level (put
> > folders in a list, instead of a tree).
> >
> > Both can be combined to show a plain representation of all the folders.
> >
> > Changelog would be:
> > * libtinymailui-gtk/tny-gtk-folder-store-tree-model.[ch]:
> > * Now developer can set flags on constructing the widget, to
> > specify how folders will be added to tree model.
> > * One of the modes will make name column contain the full path
> > of a folder.
> > * Another mode will store all the folders at the same level
> > (show items as a list instead of as a tree).
> >
--
José Dapena Paz <jdapena igalia com>
Igalia
Index: libtinymailui-gtk/tny-gtk-folder-store-tree-model.h
===================================================================
--- libtinymailui-gtk/tny-gtk-folder-store-tree-model.h (revisión: 3817)
+++ libtinymailui-gtk/tny-gtk-folder-store-tree-model.h (copia de trabajo)
@@ -54,6 +54,14 @@
typedef enum _TnyGtkFolderStoreTreeModelColumn TnyGtkFolderStoreTreeModelColumn;
+enum _TnyGtkFolderStoreTreeModelFlags
+{
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_FLAG_SHOW_PATH = 1<<0,
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_FLAG_PLAIN = 1<<1,
+};
+
+typedef enum _TnyGtkFolderStoreTreeModelFlags TnyGtkFolderStoreTreeModelFlags;
+
struct _TnyGtkFolderStoreTreeModel
{
GtkTreeStore parent;
@@ -62,6 +70,8 @@
TnyFolderStoreQuery *query;
gboolean first_needs_unref;
GPtrArray *signals;
+
+ TnyGtkFolderStoreTreeModelFlags flags;
};
struct _TnyGtkFolderStoreTreeModelClass
@@ -72,7 +82,8 @@
GType tny_gtk_folder_store_tree_model_get_type (void);
GType tny_gtk_folder_store_tree_model_column_get_type (void);
GtkTreeModel* tny_gtk_folder_store_tree_model_new (TnyFolderStoreQuery *query);
-
+GtkTreeModel* tny_gtk_folder_store_tree_model_new_with_flags (TnyFolderStoreQuery *query,
+ TnyGtkFolderStoreTreeModelFlags flags);
void tny_gtk_folder_store_tree_model_prepend (TnyGtkFolderStoreTreeModel *self, TnyFolderStore* item, const gchar *root_name);
void tny_gtk_folder_store_tree_model_append (TnyGtkFolderStoreTreeModel *self, TnyFolderStore* item, const gchar *root_name);
Index: libtinymailui-gtk/tny-gtk-folder-store-tree-model.c
===================================================================
--- libtinymailui-gtk/tny-gtk-folder-store-tree-model.c (revisión: 3817)
+++ libtinymailui-gtk/tny-gtk-folder-store-tree-model.c (copia de trabajo)
@@ -65,6 +65,8 @@
#include "tny-gtk-folder-store-tree-model-iterator-priv.h"
+#define PATH_SEPARATOR " "
+
static GObjectClass *parent_class = NULL;
typedef void (*treeaddfunc) (GtkTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent);
@@ -109,7 +111,10 @@
}
static void
-recurse_folders_sync (TnyGtkFolderStoreTreeModel *self, TnyFolderStore *store, GtkTreeIter *parent_tree_iter)
+recurse_folders_sync (TnyGtkFolderStoreTreeModel *self,
+ TnyFolderStore *store,
+ const gchar *parent_name,
+ GtkTreeIter *parent_tree_iter)
{
TnyIterator *iter;
TnyList *folders = tny_simple_list_new ();
@@ -118,6 +123,9 @@
tny_folder_store_get_folders (store, folders, self->query, TRUE, NULL);
iter = tny_list_create_iterator (folders);
+ if (parent_name == NULL)
+ parent_name = "";
+
while (!tny_iterator_is_done (iter))
{
GtkTreeModel *mmodel = (GtkTreeModel *) self;
@@ -129,6 +137,7 @@
GtkTreeIter miter;
gboolean found = FALSE;
GObject *mark_for_removal = NULL;
+ GtkTreeIter *parent_to_use;
if (instance && (TNY_IS_FOLDER (instance) || TNY_IS_MERGE_FOLDER (instance)))
folder = TNY_FOLDER (instance);
@@ -140,7 +149,14 @@
* whether it's a brand new one. If it's a new one, we'll add
* it, of course */
- if (gtk_tree_model_iter_children (mmodel, &miter, parent_tree_iter))
+ if (TNY_GTK_FOLDER_STORE_TREE_MODEL (self)->flags &
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_FLAG_PLAIN) {
+ parent_to_use = NULL;
+ } else {
+ parent_to_use = parent_tree_iter;
+ }
+
+ if (gtk_tree_model_iter_children (mmodel, &miter, parent_to_use))
do
{
GObject *citem = NULL;
@@ -186,7 +202,8 @@
if (!found)
{
- gtk_tree_store_append (model, &tree_iter, parent_tree_iter);
+ gchar *name;
+ gtk_tree_store_append (model, &tree_iter, parent_to_use);
/* Making self both a folder-store as a folder observer
* of this folder. This way we'll get notified when
@@ -201,9 +218,22 @@
add_folder_observer_weak (self, folder);
+ if (self->flags & TNY_GTK_FOLDER_STORE_TREE_MODEL_FLAG_SHOW_PATH) {
+ if ((parent_name == NULL) || *parent_name == '\0') {
+ name = g_strdup (tny_folder_get_name (folder));
+ } else {
+ name = g_strconcat (parent_name,
+ PATH_SEPARATOR,
+ tny_folder_get_name (folder),
+ NULL);
+ }
+ } else {
+ name = g_strdup (tny_folder_get_name (folder));
+ }
+
gtk_tree_store_set (model, &tree_iter,
TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN,
- tny_folder_get_name (TNY_FOLDER (folder)),
+ name,
TNY_GTK_FOLDER_STORE_TREE_MODEL_UNREAD_COLUMN,
tny_folder_get_unread_count (TNY_FOLDER (folder)),
TNY_GTK_FOLDER_STORE_TREE_MODEL_ALL_COLUMN,
@@ -213,14 +243,18 @@
TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN,
folder, -1);
+ } else {
+ name = g_strdup (tny_folder_get_name (folder));
}
/* it's a store by itself, so keep on recursing */
if (folder_store) {
add_folder_store_observer_weak (self, folder_store);
- recurse_folders_sync (self, folder_store, &tree_iter);
+ recurse_folders_sync (self, folder_store, name, &tree_iter);
}
+ g_free (name);
+
/* We're a folder, we'll request a status, since we've
* set self to be a folder observers of folder, we'll
* receive the status update. This makes it possible to
@@ -318,7 +352,7 @@
* folders that already exist (it wont add them a second time). */
if (found)
- recurse_folders_sync (self, fstore, &name_iter);
+ recurse_folders_sync (self, fstore, NULL, &name_iter);
g_object_unref (self);
@@ -542,7 +576,7 @@
* tny_gtk_folder_store_tree_model_new:
* @query: the #TnyFolderStoreQuery that will be used to retrieve the child folders of each #TnyFolderStore
*
- * Create a new #GtkTreeModel for showing #TnyFolderStore instances
+ * Create a new #GtkTreeModel for showing #TnyFolderStore instances, with default flags
*
* returns: (caller-owns): a new #GtkTreeModel for #TnyFolderStore instances
* since: 1.0
@@ -551,11 +585,31 @@
GtkTreeModel*
tny_gtk_folder_store_tree_model_new (TnyFolderStoreQuery *query)
{
+ return tny_gtk_folder_store_tree_model_new_with_flags (query, 0);
+}
+
+/**
+ * tny_gtk_folder_store_tree_model_new:
+ * @query: the #TnyFolderStoreQuery that will be used to retrieve the child folders of each #TnyFolderStore
+ * @flags: #TnyGtkFolderStoreTreeModelFlags for setting the store
+ *
+ * Create a new #GtkTreeModel for showing #TnyFolderStore instances
+ *
+ * returns: (caller-owns): a new #GtkTreeModel for #TnyFolderStore instances
+ * since: 1.0
+ * audience: application-developer
+ **/
+GtkTreeModel*
+tny_gtk_folder_store_tree_model_new_with_flags (TnyFolderStoreQuery *query,
+ TnyGtkFolderStoreTreeModelFlags flags)
+{
TnyGtkFolderStoreTreeModel *self = g_object_new (TNY_TYPE_GTK_FOLDER_STORE_TREE_MODEL, NULL);
if (query)
self->query = g_object_ref (query);
+ self->flags = flags;
+
return GTK_TREE_MODEL (self);
}
@@ -647,6 +701,8 @@
me->iterator_lock = g_mutex_new ();
me->first_needs_unref = FALSE;
+ me->flags = 0;
+
gtk_tree_store_set_column_types (store,
TNY_GTK_FOLDER_STORE_TREE_MODEL_N_COLUMNS, types);
@@ -849,7 +905,167 @@
return;
}
+typedef struct _FindParentHelperInfo {
+ GtkTreeIter *iter;
+ TnyFolder *folder;
+ TnyAccount *account;
+ gboolean found;
+} FindParentHelperInfo;
+static gboolean
+find_parent_helper (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer userdata)
+{
+ TnyFolderStore *folder_store;
+ FindParentHelperInfo *helper_info = (FindParentHelperInfo *) userdata;
+ TnyList *children;
+ TnyIterator *iterator;
+
+ gtk_tree_model_get (model, iter,
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN,
+ &folder_store, -1);
+
+ /* Only search on same account */
+ if (TNY_IS_ACCOUNT (folder_store) && ((TnyAccount *)folder_store == helper_info->account))
+ return FALSE;
+
+ if (TNY_IS_FOLDER (folder_store)) {
+ TnyAccount *account = NULL;
+ account = tny_folder_get_account (TNY_FOLDER (folder_store));
+ g_object_unref (account);
+ if (account == helper_info->account)
+ return FALSE;
+ }
+
+ children = TNY_LIST (tny_simple_list_new ());
+ tny_folder_store_get_folders (folder_store, children, NULL, FALSE, NULL);
+ iterator = tny_list_create_iterator (children);
+
+ while (!tny_iterator_is_done (iterator)) {
+ TnyFolderStore *child;
+
+ child = (TnyFolderStore *) tny_iterator_get_current (iterator);
+ g_object_unref (child);
+ if (child == (TnyFolderStore *) helper_info->folder) {
+ helper_info->found = TRUE;
+ *helper_info->iter = *iter;
+ break;
+ }
+ tny_iterator_next (iterator);
+ }
+ g_object_unref (iterator);
+ g_object_unref (children);
+
+ return helper_info->found;
+
+}
+
+static gboolean
+find_parent (GtkTreeModel *model, TnyFolder *folder, GtkTreeIter *iter)
+{
+ FindParentHelperInfo *helper_info;
+ gboolean result;
+
+ helper_info = g_slice_new0 (FindParentHelperInfo);
+
+ helper_info->folder = folder;
+ helper_info->iter = iter;
+ helper_info->account = tny_folder_get_account (folder);
+
+ gtk_tree_model_foreach (model, find_parent_helper, helper_info);
+
+ g_object_unref (helper_info->account);
+ result = helper_info->found;
+ g_slice_free (FindParentHelperInfo, helper_info);
+
+ return result;
+}
+
+typedef struct _FindHelperInfo {
+ GtkTreeIter *iter;
+ TnyFolder *folder;
+ gboolean found;
+} FindHelperInfo;
+
+static gboolean
+find_node_helper (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer userdata)
+{
+ TnyFolderStore *folder_store;
+ FindHelperInfo *helper_info = (FindHelperInfo *) userdata;
+
+ gtk_tree_model_get (model, iter,
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN,
+ &folder_store, -1);
+
+ if ((TnyFolderStore *) helper_info->folder == folder_store) {
+ helper_info->found = TRUE;
+ *helper_info->iter = *iter;
+ }
+
+ return helper_info->found;
+
+}
+
+static gboolean
+find_node (GtkTreeModel *model, TnyFolder *folder, GtkTreeIter *iter)
+{
+ FindHelperInfo *helper_info;
+ gboolean result;
+
+ helper_info = g_slice_new0 (FindHelperInfo);
+
+ helper_info->folder = folder;
+ helper_info->iter = iter;
+
+ gtk_tree_model_foreach (model, find_node_helper, helper_info);
+
+ result = helper_info->found;
+ g_slice_free (FindHelperInfo, helper_info);
+
+ return result;
+}
+
+static void
+update_children_names (GtkTreeModel *model, TnyFolder *folder, const gchar *name)
+{
+ TnyList *children;
+ TnyIterator *iterator;
+
+ children = TNY_LIST (tny_simple_list_new ());
+ iterator = tny_list_create_iterator (children);
+
+ while (!tny_iterator_is_done (iterator)) {
+ GtkTreeIter iter;
+ TnyFolder *child;
+
+ child = TNY_FOLDER (tny_iterator_get_current (iterator));
+ if (find_node (model, child, &iter)) {
+ gchar *new_name;
+ new_name = g_strconcat (name, PATH_SEPARATOR,
+ tny_folder_get_name (TNY_FOLDER (child)),
+ NULL);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN,
+ new_name,
+ -1);
+ update_children_names (model, child, new_name);
+ g_free (new_name);
+ }
+
+ g_object_unref (folder);
+ tny_iterator_next (iterator);
+ }
+
+ g_object_unref (iterator);
+ g_object_unref (children);
+}
+
+
static gboolean
updater (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data1)
{
@@ -906,17 +1122,50 @@
if (folder == changed_folder)
{
-
/* TNY TODO: This is not enough: Subfolders will be incorrect because the
the full_name of the subfolders will still be the old full_name!*/
gtk_tree_store_set (GTK_TREE_STORE (model), iter,
- TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN,
- tny_folder_get_name (TNY_FOLDER (folder)),
TNY_GTK_FOLDER_STORE_TREE_MODEL_UNREAD_COLUMN,
unread,
TNY_GTK_FOLDER_STORE_TREE_MODEL_ALL_COLUMN,
total, -1);
+
+ if (changed & TNY_FOLDER_CHANGE_CHANGED_FOLDER_RENAME) {
+ GtkTreeIter parent_iter;
+ gchar *name = NULL;
+
+ if (TNY_GTK_FOLDER_STORE_TREE_MODEL (model)->flags &
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_FLAG_SHOW_PATH) {
+ if (find_parent (model, folder, &parent_iter)) {
+ gchar *parent_name;
+ gtk_tree_model_get (model, &parent_iter,
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN,
+ &parent_name, -1);
+ if (parent_name && parent_name[0] == '\0')
+ name = g_strconcat (parent_name, PATH_SEPARATOR,
+ tny_folder_get_name (TNY_FOLDER (folder)),
+ NULL);
+ g_free (parent_name);
+
+
+ }
+ }
+
+
+ if (name == NULL)
+ name = g_strdup (tny_folder_get_name (TNY_FOLDER (folder)));
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), iter,
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN,
+ name,
+ -1);
+ if (TNY_GTK_FOLDER_STORE_TREE_MODEL (model)->flags &
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_FLAG_SHOW_PATH) {
+ update_children_names (model, folder, name);
+ }
+ g_free (name);
+ }
}
g_object_unref (folder);
@@ -1031,14 +1280,21 @@
{
TnyList *created = tny_simple_list_new ();
TnyIterator *miter;
+ gchar *parent_name;
tny_folder_store_change_get_created_folders (change, created);
miter = tny_list_create_iterator (created);
+ /* We assume parent name is already the expected one in full path style */
+ gtk_tree_model_get (model, in_iter,
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN, &parent_name,
+ -1);
+
while (!tny_iterator_is_done (miter))
{
GtkTreeIter newiter;
TnyFolder *folder = TNY_FOLDER (tny_iterator_get_current (miter));
+ gchar *finalname;
add_folder_observer_weak (self, folder);
add_folder_store_observer_weak (self, TNY_FOLDER_STORE (folder));
@@ -1047,12 +1303,27 @@
removed, that reference count is decreased automatically by
the gtktreestore infrastructure. */
+ if (TNY_GTK_FOLDER_STORE_TREE_MODEL (self)->flags &
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_FLAG_SHOW_PATH) {
+ if (parent_name && *parent_name != '\0')
+ finalname = g_strconcat (parent_name, PATH_SEPARATOR,
+ tny_folder_get_name (TNY_FOLDER (folder)), NULL);
+ else
+ finalname = g_strdup (tny_folder_get_name (TNY_FOLDER (folder)));
+ } else {
+ finalname = g_strdup (tny_folder_get_name (TNY_FOLDER (folder)));
+ }
- gtk_tree_store_prepend (GTK_TREE_STORE (model), &newiter, in_iter);
+ if (TNY_GTK_FOLDER_STORE_TREE_MODEL (self)->flags &
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_FLAG_PLAIN) {
+ gtk_tree_store_prepend (GTK_TREE_STORE (model), &newiter, NULL);
+ } else {
+ gtk_tree_store_prepend (GTK_TREE_STORE (model), &newiter, in_iter);
+ }
gtk_tree_store_set (GTK_TREE_STORE (model), &newiter,
TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN,
- tny_folder_get_name (TNY_FOLDER (folder)),
+ finalname,
TNY_GTK_FOLDER_STORE_TREE_MODEL_UNREAD_COLUMN,
tny_folder_get_unread_count (TNY_FOLDER (folder)),
TNY_GTK_FOLDER_STORE_TREE_MODEL_ALL_COLUMN,
@@ -1061,10 +1332,12 @@
tny_folder_get_folder_type (TNY_FOLDER (folder)),
TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN,
folder, -1);
+ g_free (finalname);
g_object_unref (folder);
tny_iterator_next (miter);
}
+ g_free (parent_name);
g_object_unref (miter);
g_object_unref (created);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]