Re: CList DnD/selection "format" broken?
- From: vishnu pobox com
- To: Skip Montanaro <skip pobox com>
- Cc: gtk-list gnome org
- Subject: Re: CList DnD/selection "format" broken?
- Date: Thu, 11 Oct 2001 13:34:44 -0700
On Thu, Oct 11, 2001 at 03:18:31PM -0500, Skip Montanaro wrote:
> Havoc> It's actually a bit overcomplex for many uses, .... However if
> Havoc> you are just making a simple list, clist is fine.
>
> Which suggests to me that either clist shouldn't be deprecated or there
> should be a simpler way to use treeview/treeselection/liststore to create
> simple lists. For all the power of the treeview stuff, most of the time I
> think people just need single-column lists.
It's not really that hard. The biggest missing piece is a pointer array
collection that also exports a GtkTreeModel interface. For example, see
the attached code.
--
Victory to the Divine Mother!!
http://sahajayoga.org
/* GLIB - Library of useful routines for C programming
* Copyright (C) 2001 Joshua Nathaniel Pritikin
*
* This library 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) any later version.
*
* This library 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 this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/* originally adapted from g_ptr_array */
#ifndef _G_PTRSET_H_
#define _G_PTRSET_H_
#include <glib-object.h>
typedef struct _GPtrSetClass GPtrSetClass;
typedef struct _GPtrSet GPtrSet;
#define G_TYPE_PTR_SET (g_ptr_set_get_type())
#define G_PTR_SET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PTR_SET, GPtrSet))
#define G_IS_PTR_SET(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PTR_SET))
#define G_PTR_SET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PTR_SET, GPtrSetClass))
#define G_PTR_SET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PTR_SET, GPtrSetClass))
#define G_IS_PTR_SET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PTR_SET))
struct _GPtrSetClass {
GObjectClass parent_class;
void (*delete_elem) (GPtrSet *set, gint index, gpointer data);
void (*insert_elem) (GPtrSet *set, gint index);
};
struct _GPtrSet
{
GObject parent_instance;
gpointer * pdata;
gint len;
gint alloc;
gconstpointer compare_data;
GCompareDataFunc ptr_compare;
GCompareDataFunc key_compare;
GDestroyNotify destroy_func;
guint is_refcounted : 1;
};
#define g_ptr_set_at(set,index) ((set)->pdata)[(index)]
#define g_ptr_set_len(set) ((set)->len)
GType g_ptr_set_get_type (void);
GPtrSet * g_ptr_set_new (GCompareDataFunc ptr_compare,
gconstpointer compare_data);
void g_ptr_set_set_key_compare (GPtrSet *set,
GCompareDataFunc key_compare);
void g_ptr_set_free (GPtrSet *set);
gpointer g_ptr_set_remove_index (GPtrSet * set,
gint index);
gint g_ptr_set_add_index (GPtrSet * set,
gint index,
gpointer data);
gboolean g_ptr_set_lookup (GPtrSet * set,
gint * ret,
gconstpointer sample);
gboolean g_ptr_set_lookup_ptr (GPtrSet * fset,
gint * ret,
gconstpointer sample);
gboolean g_ptr_set_lookup_key (GPtrSet * set,
gint * ret,
gconstpointer sample_key);
gint g_ptr_set_add (GPtrSet * set,
gpointer data);
gboolean g_ptr_set_try_remove (GPtrSet * fset,
gpointer data);
void g_ptr_set_remove (GPtrSet * set,
gpointer data);
void g_ptr_set_remove_all (GPtrSet *ps);
void g_ptr_set_sync_to_slist (GPtrSet *ps, GSList *target);
#endif
/* GLIB - Library of useful routines for C programming
* Copyright (C) 2001 Joshua Nathaniel Pritikin
*
* This library 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) any later version.
*
* This library 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 this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <glib.h>
#include <string.h>
#include "gptrset.h"
#include "appmarshal.h"
enum {
PROP_0,
PROP_COMPARE_DATA,
PROP_KEY_COMPARE,
PROP_PTR_COMPARE,
PROP_DESTROY_FUNC,
PROP_IS_REFCOUNTED
};
enum {
DELETE_ELEM,
INSERT_ELEM,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
#define MIN_SET_SIZE 16
static void g_ptr_set_maybe_expand (GPtrSet *set,
gint len);
static void
g_ptr_set_verify_sort (GPtrSet *set)
{
if (!set->ptr_compare)
return;
if (set->len <= 1)
return;
for (gint xx=0; xx < set->len - 1; xx++)
{
if (set->ptr_compare (g_ptr_set_at (set, xx),
g_ptr_set_at (set, xx + 1),
(gpointer) set->compare_data) > 0)
g_critical ("%d, %d are unsorted", xx, xx+1);
}
}
static gint
g_nearest_pow (gint num)
{
gint n = 1;
while (n < num)
n <<= 1;
return n;
}
GPtrSet *
g_ptr_set_new (GCompareDataFunc ptr_compare,
gconstpointer compare_data)
{
GPtrSet *set;
set = G_PTR_SET (g_object_new (g_ptr_set_get_type(), 0));
set->ptr_compare = ptr_compare;
set->compare_data = compare_data;
return set;
}
void
g_ptr_set_set_key_compare (GPtrSet *set, GCompareDataFunc key_compare)
{
set->key_compare = key_compare;
}
static void
g_ptr_set_init (GPtrSet *set)
{
/* zero fill is good */
}
// g_ptr_set_maybe_shrink XXX
static void
g_ptr_set_maybe_expand (GPtrSet *set,
gint len)
{
if ((set->len + len) > set->alloc)
{
#ifdef ENABLE_GC_FRIENDLY
gint old_alloc = set->alloc;
#endif /* ENABLE_GC_FRIENDLY */
set->alloc = g_nearest_pow (set->len + len);
set->alloc = MAX (set->alloc, MIN_SET_SIZE);
set->pdata = g_realloc (set->pdata, sizeof(gpointer) * set->alloc);
#ifdef ENABLE_GC_FRIENDLY
for ( ; old_alloc < set->alloc; old_alloc++)
set->pdata [old_alloc] = NULL;
#endif /* ENABLE_GC_FRIENDLY */
}
}
static gboolean
_ptr_set_lookup (GPtrSet * fset,
gint * ret,
GCompareDataFunc compare,
gconstpointer sample)
{
gint first, last;
gint mid;
gint midsize;
gint cmp;
gint tx;
g_return_val_if_fail (compare, FALSE);
if (!fset->len)
{
if (ret) *ret = 0;
return FALSE;
}
first = 0;
last = fset->len - 1;
midsize = last - first;
while (midsize > 1) {
mid = first + midsize / 2;
cmp = (*compare) (sample, g_ptr_set_at (fset, mid), (gpointer) fset->compare_data);
if (cmp == 0)
{
// if there are multiple matches then scan for the first match
while (mid > 0 &&
(*compare) (sample,
g_ptr_set_at (fset, mid - 1),
(gpointer) fset->compare_data) == 0)
--mid;
if (ret) *ret = mid;
return TRUE;
}
if (cmp < 0)
last = mid-1;
else
first = mid+1;
midsize = last - first;
}
for (tx = first; tx <= last; tx++)
{
cmp = (*compare) (sample, g_ptr_set_at (fset, tx), (gpointer) fset->compare_data);
if (cmp < 0)
{
if (ret) *ret = tx;
return FALSE;
}
if (cmp == 0)
{
if (ret) *ret = tx;
return TRUE;
}
}
if (ret) *ret = last+1;
return FALSE;
}
gboolean
g_ptr_set_lookup (GPtrSet * fset,
gint * ret,
gconstpointer sample)
{
g_return_val_if_fail (fset, FALSE);
return _ptr_set_lookup (fset, ret, fset->ptr_compare, sample);
}
gboolean
g_ptr_set_lookup_ptr (GPtrSet * fset,
gint * ret,
gconstpointer sample)
{
g_return_val_if_fail (fset, FALSE);
gint at;
if (!_ptr_set_lookup (fset, &at, fset->ptr_compare, sample))
return FALSE;
// cope with non-unique sets of unique pointers
while (g_ptr_set_at (fset, at) != sample)
{
if (at < fset->len - 1 &&
(*fset->ptr_compare) (sample,
g_ptr_set_at (fset, at+1),
(gpointer) fset->compare_data) == 0)
{ ++at; continue; }
return FALSE;
}
if (ret)
*ret = at;
return TRUE;
}
gboolean
g_ptr_set_lookup_key (GPtrSet * set,
gint * ret,
gconstpointer sample_key)
{
g_return_val_if_fail (set, FALSE);
return _ptr_set_lookup (set, ret, set->key_compare, sample_key);
}
gpointer
g_ptr_set_remove_index (GPtrSet* fset,
gint index)
{
gpointer result;
g_return_val_if_fail (fset, NULL);
g_return_val_if_fail (0 <= index && index < fset->len, NULL);
result = fset->pdata[index];
if (index != fset->len - 1)
g_memmove (fset->pdata + index, fset->pdata + index + 1,
sizeof (gpointer) * (fset->len - index - 1));
fset->len -= 1;
#ifdef ENABLE_GC_FRIENDLY
fset->pdata[fset->len] = NULL;
#endif /* ENABLE_GC_FRIENDLY */
g_ptr_set_verify_sort (fset);
g_signal_emit (fset, signals[DELETE_ELEM], 0, index, result);
if (fset->destroy_func)
(*fset->destroy_func) (result);
if (fset->is_refcounted)
g_object_unref (result);
return result;
}
gboolean
g_ptr_set_try_remove (GPtrSet* fset,
gpointer data)
{
g_return_val_if_fail (fset, FALSE);
g_return_val_if_fail (data, FALSE);
// only remove first match
gint at;
if (!g_ptr_set_lookup_ptr (fset, &at, data))
return FALSE;
gpointer removed = g_ptr_set_remove_index (fset, at);
g_assert (data == removed);
return TRUE;
}
void
g_ptr_set_remove (GPtrSet* fset,
gpointer data)
{
gboolean removed =
g_ptr_set_try_remove (fset, data);
g_assert (removed);
}
gint
g_ptr_set_add_index (GPtrSet * set,
gint index,
gpointer data)
{
g_return_val_if_fail (set, -1);
g_return_val_if_fail (0 <= index && index <= set->len, -1);
if (set->is_refcounted)
g_object_ref (data);
g_ptr_set_maybe_expand ((GPtrSet*) set, 1);
g_memmove (&g_ptr_set_at (set, 1 + index),
&g_ptr_set_at (set, index),
sizeof(gpointer) * (set->len - index));
g_ptr_set_at (set, index) = data;
set->len += 1;
g_ptr_set_verify_sort (set);
g_signal_emit (set, signals[INSERT_ELEM], 0, index);
return index;
}
gint
g_ptr_set_add (GPtrSet * set,
gpointer data)
{
gint at;
g_return_val_if_fail (set, -1);
g_return_val_if_fail (data, -1);
if (g_ptr_set_lookup (set, &at, data))
++at; // reduce memmove
return g_ptr_set_add_index (set, at, data);
}
void
g_ptr_set_remove_all (GPtrSet *ps)
{
g_return_if_fail (ps);
gint old_len = ps->len;
gpointer *pdata = ps->pdata;
ps->alloc = 0;
ps->pdata = NULL;
ps->len = 0;
// For this emission, we always use the zeroth index
// because downstream handlers don't know what we're doing.
//
for (gint xx=0; xx < old_len; xx++)
g_signal_emit (ps, signals[DELETE_ELEM], 0, 0, pdata[xx]);
if (ps->destroy_func)
for (gint xx=0; xx < old_len; xx++)
(*ps->destroy_func) (pdata[xx]);
if (ps->is_refcounted)
for (gint xx=0; xx < old_len; xx++)
g_object_unref (pdata[xx]);
g_free (pdata);
}
// Do the minimum number of adds/removes.
//
void g_ptr_set_sync_to_slist (GPtrSet *ps, GSList *target)
{
gint xx=0;
while (xx < g_ptr_set_len (ps))
{
gpointer data = g_ptr_set_at (ps, xx);
if (!g_slist_find (target, data))
g_ptr_set_remove (ps, data);
else
++xx;
}
for (GSList *elem = target; elem; elem = g_slist_next (elem))
{
gpointer data = elem->data;
if (!g_ptr_set_lookup (ps, NULL, data))
g_ptr_set_add (ps, data);
}
}
static void
g_ptr_set_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GPtrSet *set = G_PTR_SET (object);
g_return_if_fail (set->len == 0);
switch (prop_id) {
case PROP_COMPARE_DATA:
set->compare_data = g_value_get_pointer (value);
break;
case PROP_KEY_COMPARE:
set->key_compare = g_value_get_pointer (value);
break;
case PROP_PTR_COMPARE:
set->ptr_compare = g_value_get_pointer (value);
break;
case PROP_DESTROY_FUNC:
set->destroy_func = g_value_get_pointer (value);
break;
case PROP_IS_REFCOUNTED:
set->is_refcounted = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
g_ptr_set_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GPtrSet *set = G_PTR_SET (object);
switch (prop_id) {
case PROP_COMPARE_DATA:
g_value_set_pointer (value, (gpointer) set->compare_data);
break;
case PROP_KEY_COMPARE:
g_value_set_pointer (value, set->key_compare);
break;
case PROP_PTR_COMPARE:
g_value_set_pointer (value, set->ptr_compare);
break;
case PROP_DESTROY_FUNC:
g_value_set_pointer (value, set->destroy_func);
break;
case PROP_IS_REFCOUNTED:
g_value_set_boolean (value, set->is_refcounted);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static GObjectClass *parent_class;
static void
g_ptr_set_finalize (GObject *object)
{
GPtrSet *set;
gint xx;
g_return_if_fail (G_IS_PTR_SET (object));
set = G_PTR_SET (object);
if (set->destroy_func)
for (xx=0; xx < set->len; xx++)
(* set->destroy_func) (g_ptr_set_at (set, xx));
if (set->is_refcounted)
for (xx=0; xx < set->len; xx++)
g_object_unref (g_ptr_set_at (set, xx));
g_free (set->pdata);
set->pdata = NULL;
(* G_OBJECT_CLASS(parent_class)->finalize) (object);
}
static void
g_ptr_set_class_init(GPtrSetClass *klass) {
GObjectClass *object_class = G_OBJECT_CLASS(klass);
parent_class = g_type_class_peek_parent (klass);
object_class->set_property = g_ptr_set_set_property;
object_class->get_property = g_ptr_set_get_property;
object_class->finalize = g_ptr_set_finalize;
g_object_class_install_property
(object_class, PROP_COMPARE_DATA,
g_param_spec_pointer ("compare-data",
"",
"",
G_PARAM_READABLE|G_PARAM_WRITABLE));
g_object_class_install_property
(object_class, PROP_KEY_COMPARE,
g_param_spec_pointer ("key-compare",
"",
"GCompareDataFunc",
G_PARAM_READABLE|G_PARAM_WRITABLE));
g_object_class_install_property
(object_class, PROP_PTR_COMPARE,
g_param_spec_pointer ("ptr-compare",
"",
"GCompareDataFunc",
G_PARAM_READABLE|G_PARAM_WRITABLE));
g_object_class_install_property
(object_class, PROP_DESTROY_FUNC,
g_param_spec_pointer ("destroy-func",
"",
"GDestroyNotify",
G_PARAM_READABLE|G_PARAM_WRITABLE));
g_object_class_install_property
(object_class, PROP_IS_REFCOUNTED,
g_param_spec_boolean ("is-refcounted",
"",
"Whether to do reference count the elements.",
FALSE,
G_PARAM_READABLE|G_PARAM_WRITABLE));
signals[DELETE_ELEM] =
g_signal_new ("delete_elem",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST, // ACTION? XXX
G_STRUCT_OFFSET (GPtrSetClass, delete_elem),
NULL, NULL,
app_marshal_VOID__UINT_POINTER,
G_TYPE_NONE,
2,
G_TYPE_UINT,
G_TYPE_POINTER);
signals[INSERT_ELEM] =
g_signal_new ("insert_elem",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GPtrSetClass, insert_elem),
NULL, NULL,
app_marshal_VOID__UINT,
G_TYPE_NONE,
1,
G_TYPE_UINT);
}
GType g_ptr_set_get_type (void)
{
static GType our_type = 0;
if (our_type == 0) {
static const GTypeInfo our_info = {
sizeof(GPtrSetClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) g_ptr_set_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GPtrSet),
0, /* n_preallocs */
(GInstanceInitFunc) g_ptr_set_init,
NULL
};
our_type = g_type_register_static (G_TYPE_OBJECT,
"GPtrSet",
&our_info,
0);
}
return our_type;
}
#include <gtk/gtk.h>
#include "gptrset.h"
#define APP_TYPE_LIST_STORE (app_list_store_get_type ())
#define APP_LIST_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), APP_TYPE_LIST_STORE, AppListStore))
#define APP_LIST_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), APP_TYPE_LIST_STORE, AppListStoreClass))
#define APP_IS_LIST_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), APP_TYPE_LIST_STORE))
#define APP_IS_LIST_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), APP_TYPE_LIST_STORE))
#define APP_LIST_STORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), APP_TYPE_LIST_STORE, AppListStoreClass))
typedef struct _AppListStore AppListStore;
typedef struct _AppListStoreClass AppListStoreClass;
GType app_list_store_get_type (void);
AppListStore *app_list_store_new (GCompareDataFunc ptr_compare,
gconstpointer compare_data);
struct _AppListStore
{
GPtrSet parent;
gint stamp;
};
struct _AppListStoreClass
{
GPtrSetClass parent_class;
};
#include "appliststore.h"
static gint
_direct_ptr_compare (gpointer p1, gpointer p2)
{
if (p1==p2)
return 0;
else if (p1 < p2)
return -1;
else
return 1;
}
AppListStore *
app_list_store_new (GCompareDataFunc ptr_compare,
gconstpointer compare_data)
{
AppListStore *ret;
GPtrSet *ps;
ret = APP_LIST_STORE (g_object_new (APP_TYPE_LIST_STORE, NULL));
ps = G_PTR_SET (ret);
ps->ptr_compare = (ptr_compare?
ptr_compare : (GCompareDataFunc) _direct_ptr_compare);
ps->compare_data = compare_data;
return ret;
}
static guint
app_list_store_get_flags (GtkTreeModel *tree_model)
{
g_return_val_if_fail (APP_IS_LIST_STORE (tree_model), 0);
return GTK_TREE_MODEL_ITERS_PERSIST | GTK_TREE_MODEL_LIST_ONLY;
}
static gint
app_list_store_get_n_columns (GtkTreeModel *tree_model)
{
g_return_val_if_fail (APP_IS_LIST_STORE (tree_model), 0);
return 1;
}
static GType
app_list_store_get_column_type (GtkTreeModel *tree_model,
gint index)
{
g_return_val_if_fail (APP_IS_LIST_STORE (tree_model), G_TYPE_INVALID);
g_return_val_if_fail (index == 0, G_TYPE_INVALID);
return G_PTR_SET (tree_model)->is_refcounted? G_TYPE_OBJECT : G_TYPE_POINTER;
}
static gboolean
app_list_store_get_iter (GtkTreeModel *tree_model,
GtkTreeIter *iter,
GtkTreePath *path)
{
gint i;
g_return_val_if_fail (APP_IS_LIST_STORE (tree_model), FALSE);
g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
i = gtk_tree_path_get_indices (path)[0];
if (i >= G_PTR_SET (tree_model)->len)
return FALSE;
iter->stamp = APP_LIST_STORE (tree_model)->stamp;
iter->user_data = GINT_TO_POINTER (i);
return TRUE;
}
static GtkTreePath *
app_list_store_get_path (GtkTreeModel *tree_model,
GtkTreeIter *iter)
{
GtkTreePath *retval;
g_return_val_if_fail (APP_IS_LIST_STORE (tree_model), NULL);
g_return_val_if_fail (iter->stamp == APP_LIST_STORE (tree_model)->stamp, NULL);
retval = gtk_tree_path_new ();
gtk_tree_path_append_index (retval, GPOINTER_TO_INT (iter->user_data));
return retval;
}
static void
app_list_store_get_value (GtkTreeModel *tree_model,
GtkTreeIter *iter,
gint column,
GValue *value)
{
GPtrSet *ps;
g_return_if_fail (APP_IS_LIST_STORE (tree_model));
g_return_if_fail (column < 1);
g_return_if_fail (APP_LIST_STORE (tree_model)->stamp == iter->stamp);
ps = G_PTR_SET (tree_model);
if (ps->is_refcounted)
{
g_value_init (value, G_TYPE_OBJECT);
g_value_set_object (value, g_ptr_set_at (ps, GPOINTER_TO_INT(iter->user_data)));
}
else
{
g_value_init (value, G_TYPE_POINTER);
g_value_set_pointer (value, g_ptr_set_at (ps, GPOINTER_TO_INT(iter->user_data)));
}
}
static gboolean
app_list_store_iter_next (GtkTreeModel *tree_model,
GtkTreeIter *iter)
{
gint at;
g_return_val_if_fail (APP_IS_LIST_STORE (tree_model), FALSE);
g_return_val_if_fail (APP_LIST_STORE (tree_model)->stamp == iter->stamp, FALSE);
at = GPOINTER_TO_INT (iter->user_data) + 1;
iter->user_data = GINT_TO_POINTER (at);
return at < G_PTR_SET(tree_model)->len;
}
static gboolean
app_list_store_iter_children (GtkTreeModel *tree_model,
GtkTreeIter *iter,
GtkTreeIter *parent)
{
if (parent)
return FALSE;
if (G_PTR_SET (tree_model)->len)
{
iter->stamp = APP_LIST_STORE (tree_model)->stamp;
iter->user_data = 0;
return TRUE;
}
else
return FALSE;
}
static gboolean
app_list_store_iter_has_child (GtkTreeModel *tree_model,
GtkTreeIter *iter)
{
return FALSE;
}
static gint
app_list_store_iter_n_children (GtkTreeModel *tree_model,
GtkTreeIter *iter)
{
g_return_val_if_fail (APP_IS_LIST_STORE (tree_model), -1);
if (iter == NULL)
return G_PTR_SET (tree_model)->len;
g_return_val_if_fail (APP_LIST_STORE (tree_model)->stamp == iter->stamp, -1);
return 0;
}
static gboolean
app_list_store_iter_nth_child (GtkTreeModel *tree_model,
GtkTreeIter *iter,
GtkTreeIter *parent,
gint n)
{
g_return_val_if_fail (APP_IS_LIST_STORE (tree_model), FALSE);
if (parent)
return FALSE;
if (n <= G_PTR_SET(tree_model)->len)
{
iter->stamp = APP_LIST_STORE (tree_model)->stamp;
iter->user_data = GINT_TO_POINTER (n);
return TRUE;
}
else
return FALSE;
}
static gboolean
app_list_store_iter_parent (GtkTreeModel *tree_model,
GtkTreeIter *iter,
GtkTreeIter *child)
{
return FALSE;
}
static void
app_list_store_delete_elem (GPtrSet *ps, gint index, gpointer data)
{
AppListStore *list_store;
GtkTreePath *path;
list_store = APP_LIST_STORE (ps);
++list_store->stamp;
path = gtk_tree_path_new ();
gtk_tree_path_append_index (path, index);
gtk_tree_model_row_deleted (GTK_TREE_MODEL (ps), path);
gtk_tree_path_free (path);
}
static void
app_list_store_insert_elem (GPtrSet *ps, gint index)
{
AppListStore *list_store;
GtkTreePath *path;
GtkTreeIter iter;
list_store = APP_LIST_STORE (ps);
++list_store->stamp;
iter.stamp = list_store->stamp;
iter.user_data = GINT_TO_POINTER (index);
path = gtk_tree_path_new ();
gtk_tree_path_append_index (path, index);
gtk_tree_model_row_inserted (GTK_TREE_MODEL (ps), path, &iter);
gtk_tree_path_free (path);
}
static void
app_list_store_init (AppListStore *list_store)
{
list_store->stamp = g_random_int ();
}
static void
app_list_store_class_init (AppListStoreClass *klass)
{
GPtrSetClass *ps_class;
ps_class = (GPtrSetClass*) klass;
ps_class->delete_elem = app_list_store_delete_elem;
ps_class->insert_elem = app_list_store_insert_elem;
}
static void
app_list_store_tree_model_init (GtkTreeModelIface *iface)
{
iface->get_flags = app_list_store_get_flags;
iface->get_n_columns = app_list_store_get_n_columns;
iface->get_column_type = app_list_store_get_column_type;
iface->get_iter = app_list_store_get_iter;
iface->get_path = app_list_store_get_path;
iface->get_value = app_list_store_get_value;
iface->iter_next = app_list_store_iter_next;
iface->iter_children = app_list_store_iter_children;
iface->iter_has_child = app_list_store_iter_has_child;
iface->iter_n_children = app_list_store_iter_n_children;
iface->iter_nth_child = app_list_store_iter_nth_child;
iface->iter_parent = app_list_store_iter_parent;
}
GType app_list_store_get_type (void)
{
static GType list_store_type = 0;
if (!list_store_type)
{
static const GTypeInfo list_store_info =
{
sizeof (AppListStoreClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) app_list_store_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (AppListStore),
0,
(GInstanceInitFunc) app_list_store_init,
NULL
};
static const GInterfaceInfo tree_model_info =
{
(GInterfaceInitFunc) app_list_store_tree_model_init,
NULL,
NULL
};
list_store_type = g_type_register_static (G_TYPE_PTR_SET, "AppListStore", &list_store_info, 0);
g_type_add_interface_static (list_store_type,
GTK_TYPE_TREE_MODEL,
&tree_model_info);
}
return list_store_type;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]