diff options
author | Havoc Pennington <hp@redhat.com> | 2001-01-06 01:31:58 +0000 |
---|---|---|
committer | Havoc Pennington <hp@src.gnome.org> | 2001-01-06 01:31:58 +0000 |
commit | 5c37906778148c435a4580497ec72a8378f3fbca (patch) | |
tree | 8e4f8b970a0514c915e51cbd25ec9855612d3145 /tests | |
parent | eb2fdbb1769a90f34a916e4a912b648d067b5f7d (diff) | |
download | gtk+-5c37906778148c435a4580497ec72a8378f3fbca.tar.gz |
hack on this a bit
2001-01-05 Havoc Pennington <hp@redhat.com>
* tests/testtreeview.c: hack on this a bit
* gtk/gtktextlayout.c (gtk_text_layout_class_init):
s/GTK_RUN_LAST/G_SIGNAL_RUN_LAST
* gtk/gtktreemodelsimple.h (GTK_IS_TREE_MODEL_SIMPLE_CLASS):
was spelled incorrectly
(GTK_IS_TREE_MODEL_SIMPLE): ditto
* gtk/gtktreeview.c (gtk_tree_view_set_headers_clickable): rename
from gtk_tree_view_set_headers_active
* gtk/gtktexttag.c:
(gtk_text_tag_get_property): handle PROP_DIRECTION
(gtk_text_tag_set_property): g_object_notify when we toggle the _set
properties, bug 40235
* gtk/gtktextiter.c (gtk_text_iter_forward_to_delimiters): rename
forward_to_line_end
Diffstat (limited to 'tests')
-rw-r--r-- | tests/testtreeview-plan.txt | 4 | ||||
-rw-r--r-- | tests/testtreeview.c | 754 |
2 files changed, 729 insertions, 29 deletions
diff --git a/tests/testtreeview-plan.txt b/tests/testtreeview-plan.txt new file mode 100644 index 0000000000..9662d699d6 --- /dev/null +++ b/tests/testtreeview-plan.txt @@ -0,0 +1,4 @@ +This document is a laundry list of stuff to check if you want to +verify that GtkTreeView and associated objects are working properly. + + diff --git a/tests/testtreeview.c b/tests/testtreeview.c index ce0f3ccb00..0b38023ce6 100644 --- a/tests/testtreeview.c +++ b/tests/testtreeview.c @@ -2,6 +2,627 @@ #include <gtk/gtk.h> #include <string.h> +static GtkWidget* create_prop_editor (GObject *object); + +/* This custom model is to test custom model use. */ + +#define GTK_TYPE_MODEL_TYPES (gtk_tree_model_types_get_type ()) +#define GTK_TREE_MODEL_TYPES(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_MODEL_TYPES, GtkTreeModelTypes)) +#define GTK_TREE_MODEL_TYPES_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_MODEL_TYPES, GtkTreeModelTypesClass)) +#define GTK_IS_TREE_MODEL_TYPES(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_MODEL_TYPES)) +#define GTK_IS_TREE_MODEL_TYPES_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), GTK_TYPE_MODEL_TYPES)) + +typedef struct _GtkTreeModelTypes GtkTreeModelTypes; +typedef struct _GtkTreeModelTypesClass GtkTreeModelTypesClass; + +struct _GtkTreeModelTypes +{ + GtkObject parent; + + gint stamp; +}; + +struct _GtkTreeModelTypesClass +{ + GtkObjectClass parent_class; + + guint (* get_flags) (GtkTreeModel *tree_model); + gint (* get_n_columns) (GtkTreeModel *tree_model); + GType (* get_column_type) (GtkTreeModel *tree_model, + gint index); + gboolean (* get_iter) (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreePath *path); + GtkTreePath *(* get_path) (GtkTreeModel *tree_model, + GtkTreeIter *iter); + void (* get_value) (GtkTreeModel *tree_model, + GtkTreeIter *iter, + gint column, + GValue *value); + gboolean (* iter_next) (GtkTreeModel *tree_model, + GtkTreeIter *iter); + gboolean (* iter_children) (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *parent); + gboolean (* iter_has_child) (GtkTreeModel *tree_model, + GtkTreeIter *iter); + gint (* iter_n_children) (GtkTreeModel *tree_model, + GtkTreeIter *iter); + gboolean (* iter_nth_child) (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *parent, + gint n); + gboolean (* iter_parent) (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *child); + void (* ref_iter) (GtkTreeModel *tree_model, + GtkTreeIter *iter); + void (* unref_iter) (GtkTreeModel *tree_model, + GtkTreeIter *iter); + + /* These will be moved into the GtkTreeModelIface eventually */ + void (* changed) (GtkTreeModel *tree_model, + GtkTreePath *path, + GtkTreeIter *iter); + void (* inserted) (GtkTreeModel *tree_model, + GtkTreePath *path, + GtkTreeIter *iter); + void (* child_toggled) (GtkTreeModel *tree_model, + GtkTreePath *path, + GtkTreeIter *iter); + void (* deleted) (GtkTreeModel *tree_model, + GtkTreePath *path); +}; + +GtkType gtk_tree_model_types_get_type (void); +GtkTreeModelTypes *gtk_tree_model_types_new (void); + +typedef enum +{ + MODEL_TYPES, + MODEL_LAST +} ModelType; + +static GtkTreeModel *models[MODEL_LAST]; + +int +main (int argc, + char **argv) +{ + GtkWidget *window; + GtkWidget *sw; + GtkWidget *tv; + GtkTreeViewColumn *col; + GtkCellRenderer *rend; + gint i; + + gtk_init (&argc, &argv); + + models[MODEL_TYPES] = GTK_TREE_MODEL (gtk_tree_model_types_new ()); + + i = 0; + while (i < MODEL_LAST) + { + window = create_prop_editor (G_OBJECT (models[i])); + + gtk_window_set_title (GTK_WINDOW (window), g_type_name (G_TYPE_FROM_INSTANCE (models[i]))); + + ++i; + } + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + + gtk_window_set_default_size (GTK_WINDOW (window), 400, 400); + + sw = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + gtk_container_add (GTK_CONTAINER (window), sw); + + tv = gtk_tree_view_new_with_model (models[0]); + + gtk_container_add (GTK_CONTAINER (sw), tv); + + rend = gtk_cell_renderer_text_new (); + + col = gtk_tree_view_column_new_with_attributes ("Type ID", + rend, + "text", 0, + NULL); + + gtk_tree_view_append_column (GTK_TREE_VIEW (tv), col); + + g_object_unref (G_OBJECT (rend)); + g_object_unref (G_OBJECT (col)); + + rend = gtk_cell_renderer_text_new (); + + col = gtk_tree_view_column_new_with_attributes ("Name", + rend, + "text", 1, + NULL); + + gtk_tree_view_append_column (GTK_TREE_VIEW (tv), col); + + g_object_unref (G_OBJECT (rend)); + g_object_unref (G_OBJECT (col)); + + gtk_widget_show_all (window); + + gtk_main (); + + return 0; +} + +/* + * GtkTreeModelTypes + */ + +enum { + CHANGED, + INSERTED, + CHILD_TOGGLED, + DELETED, + + LAST_SIGNAL +}; + +static void gtk_tree_model_types_init (GtkTreeModelTypes *model_types); +static void gtk_tree_model_types_class_init (GtkTreeModelTypesClass *class); +static void gtk_tree_model_types_tree_model_init (GtkTreeModelIface *iface); +static gint gtk_real_model_types_get_n_columns (GtkTreeModel *tree_model); +static GType gtk_real_model_types_get_column_type (GtkTreeModel *tree_model, + gint index); +static GtkTreePath *gtk_real_model_types_get_path (GtkTreeModel *tree_model, + GtkTreeIter *iter); +static void gtk_real_model_types_get_value (GtkTreeModel *tree_model, + GtkTreeIter *iter, + gint column, + GValue *value); +static gboolean gtk_real_model_types_iter_next (GtkTreeModel *tree_model, + GtkTreeIter *iter); +static gboolean gtk_real_model_types_iter_children (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *parent); +static gboolean gtk_real_model_types_iter_has_child (GtkTreeModel *tree_model, + GtkTreeIter *iter); +static gint gtk_real_model_types_iter_n_children (GtkTreeModel *tree_model, + GtkTreeIter *iter); +static gboolean gtk_real_model_types_iter_nth_child (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *parent, + gint n); +static gboolean gtk_real_model_types_iter_parent (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *child); + + +static guint model_types_signals[LAST_SIGNAL] = { 0 }; + + +GtkType +gtk_tree_model_types_get_type (void) +{ + static GtkType model_types_type = 0; + + if (!model_types_type) + { + static const GTypeInfo model_types_info = + { + sizeof (GtkTreeModelTypesClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gtk_tree_model_types_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GtkTreeModelTypes), + 0, + (GInstanceInitFunc) gtk_tree_model_types_init + }; + + static const GInterfaceInfo tree_model_info = + { + (GInterfaceInitFunc) gtk_tree_model_types_tree_model_init, + NULL, + NULL + }; + + model_types_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkTreeModelTypes", &model_types_info, 0); + g_type_add_interface_static (model_types_type, + GTK_TYPE_TREE_MODEL, + &tree_model_info); + } + + return model_types_type; +} + +GtkTreeModelTypes * +gtk_tree_model_types_new (void) +{ + GtkTreeModelTypes *retval; + + retval = GTK_TREE_MODEL_TYPES (g_object_new (GTK_TYPE_MODEL_TYPES, NULL)); + + return retval; +} + +static void +gtk_tree_model_types_class_init (GtkTreeModelTypesClass *class) +{ + GObjectClass *object_class; + + object_class = (GObjectClass*) class; + + model_types_signals[CHANGED] = + g_signal_newc ("changed", + GTK_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + GTK_SIGNAL_OFFSET (GtkTreeModelTypesClass, changed), + NULL, + gtk_marshal_VOID__BOXED_BOXED, + G_TYPE_NONE, 2, + G_TYPE_POINTER, + G_TYPE_POINTER); + model_types_signals[INSERTED] = + g_signal_newc ("inserted", + GTK_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + GTK_SIGNAL_OFFSET (GtkTreeModelTypesClass, inserted), + NULL, + gtk_marshal_VOID__BOXED_BOXED, + G_TYPE_NONE, 2, + G_TYPE_POINTER, + G_TYPE_POINTER); + model_types_signals[CHILD_TOGGLED] = + g_signal_newc ("child_toggled", + GTK_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + GTK_SIGNAL_OFFSET (GtkTreeModelTypesClass, child_toggled), + NULL, + gtk_marshal_VOID__BOXED_BOXED, + G_TYPE_NONE, 2, + G_TYPE_POINTER, + G_TYPE_POINTER); + model_types_signals[DELETED] = + g_signal_newc ("deleted", + GTK_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + GTK_SIGNAL_OFFSET (GtkTreeModelTypesClass, deleted), + NULL, + gtk_marshal_VOID__BOXED, + G_TYPE_NONE, 1, + G_TYPE_POINTER); +} + +static void +gtk_tree_model_types_tree_model_init (GtkTreeModelIface *iface) +{ + iface->get_n_columns = gtk_real_model_types_get_n_columns; + iface->get_column_type = gtk_real_model_types_get_column_type; + iface->get_path = gtk_real_model_types_get_path; + iface->get_value = gtk_real_model_types_get_value; + iface->iter_next = gtk_real_model_types_iter_next; + iface->iter_children = gtk_real_model_types_iter_children; + iface->iter_has_child = gtk_real_model_types_iter_has_child; + iface->iter_n_children = gtk_real_model_types_iter_n_children; + iface->iter_nth_child = gtk_real_model_types_iter_nth_child; + iface->iter_parent = gtk_real_model_types_iter_parent; +} + +static void +gtk_tree_model_types_init (GtkTreeModelTypes *model_types) +{ + model_types->stamp = g_random_int (); +} + +static GType column_types[] = { + G_TYPE_STRING, /* GType */ + G_TYPE_STRING /* type name */ +}; + +static gint +gtk_real_model_types_get_n_columns (GtkTreeModel *tree_model) +{ + return G_N_ELEMENTS (column_types); +} + +static GType +gtk_real_model_types_get_column_type (GtkTreeModel *tree_model, + gint index) +{ + g_return_val_if_fail (index < G_N_ELEMENTS (column_types), G_TYPE_INVALID); + + return column_types[index]; +} + +#if 0 +/* Use default implementation of this */ +static gboolean +gtk_real_model_types_get_iter (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreePath *path) +{ + +} +#endif + +/* The toplevel nodes of the tree are the reserved types, G_TYPE_NONE through + * G_TYPE_RESERVED_FUNDAMENTAL. + */ + +static GtkTreePath * +gtk_real_model_types_get_path (GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + GtkTreePath *retval; + GType type; + GType parent; + + g_return_val_if_fail (GTK_IS_TREE_MODEL_TYPES (tree_model), NULL); + g_return_val_if_fail (iter != NULL, NULL); + + type = GPOINTER_TO_INT (iter->user_data); + + retval = gtk_tree_path_new (); + + parent = g_type_parent (type); + while (parent != G_TYPE_INVALID) + { + GType* children = g_type_children (parent, NULL); + gint i = 0; + + if (!children || children[0] == G_TYPE_INVALID) + { + g_warning ("bad iterator?"); + return NULL; + } + + while (children[i] != type) + ++i; + + gtk_tree_path_prepend_index (retval, i); + + g_free (children); + + type = parent; + parent = g_type_parent (parent); + } + + /* The fundamental type itself is the index on the toplevel */ + gtk_tree_path_prepend_index (retval, type); + + return retval; +} + +static void +gtk_real_model_types_get_value (GtkTreeModel *tree_model, + GtkTreeIter *iter, + gint column, + GValue *value) +{ + GType type; + + type = GPOINTER_TO_INT (iter->user_data); + + switch (column) + { + case 0: + { + gchar *str; + + g_value_init (value, G_TYPE_STRING); + + str = g_strdup_printf ("%d", type); + g_value_set_string (value, str); + g_free (str); + } + break; + + case 1: + g_value_init (value, G_TYPE_STRING); + g_value_set_string (value, g_type_name (type)); + break; + + default: + g_warning ("Bad column %d requested", column); + } +} + +static gboolean +gtk_real_model_types_iter_next (GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + + GType parent; + GType type; + + type = GPOINTER_TO_INT (iter->user_data); + + parent = g_type_parent (type); + + if (parent == G_TYPE_INVALID) + { + /* fundamental type, add 1 */ + if ((type + 1) < G_TYPE_LAST_RESERVED_FUNDAMENTAL) + { + iter->user_data = GINT_TO_POINTER (type + 1); + return TRUE; + } + else + return FALSE; + } + else + { + GType* children = g_type_children (parent, NULL); + gint i = 0; + + g_assert (children != NULL); + + while (children[i] != type) + ++i; + + ++i; + + if (children[i] != G_TYPE_INVALID) + { + g_free (children); + iter->user_data = GINT_TO_POINTER (children[i]); + return TRUE; + } + else + { + g_free (children); + return FALSE; + } + } +} + +static gboolean +gtk_real_model_types_iter_children (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *parent) +{ + GType type; + GType* children; + + type = GPOINTER_TO_INT (parent->user_data); + + children = g_type_children (type, NULL); + + if (!children || children[0] == G_TYPE_INVALID) + { + g_free (children); + return FALSE; + } + else + { + iter->user_data = GINT_TO_POINTER (children[0]); + g_free (children); + return TRUE; + } +} + +static gboolean +gtk_real_model_types_iter_has_child (GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + GType type; + GType* children; + + type = GPOINTER_TO_INT (iter->user_data); + + children = g_type_children (type, NULL); + + if (!children || children[0] == G_TYPE_INVALID) + { + g_free (children); + return FALSE; + } + else + { + g_free (children); + return TRUE; + } +} + +static gint +gtk_real_model_types_iter_n_children (GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + if (iter == NULL) + { + return G_TYPE_LAST_RESERVED_FUNDAMENTAL - 1; + } + else + { + GType type; + GType* children; + guint n_children = 0; + + type = GPOINTER_TO_INT (iter->user_data); + + children = g_type_children (type, &n_children); + + g_free (children); + + return n_children; + } +} + +static gboolean +gtk_real_model_types_iter_nth_child (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *parent, + gint n) +{ + if (parent == NULL) + { + /* fundamental type */ + if (n < G_TYPE_LAST_RESERVED_FUNDAMENTAL) + { + iter->user_data = GINT_TO_POINTER (n); + return TRUE; + } + else + return FALSE; + } + else + { + GType type = GPOINTER_TO_INT (parent->user_data); + guint n_children = 0; + GType* children = g_type_children (type, &n_children); + + if (n_children == 0) + { + g_free (children); + return FALSE; + } + else if (n >= n_children) + { + g_free (children); + return FALSE; + } + else + { + iter->user_data = GINT_TO_POINTER (children[n]); + g_free (children); + + return TRUE; + } + } +} + +static gboolean +gtk_real_model_types_iter_parent (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *child) +{ + GType type; + GType parent; + + type = GPOINTER_TO_INT (child->user_data); + + parent = g_type_parent (type); + + if (parent == G_TYPE_INVALID) + { + if (type >= G_TYPE_LAST_RESERVED_FUNDAMENTAL) + g_warning ("no parent for %d %s\n", type, g_type_name (type)); + return FALSE; + } + else + { + iter->user_data = GINT_TO_POINTER (parent); + + return TRUE; + } +} + +/* + * Property editor thingy + */ static void get_param_specs (GObject *object, @@ -55,7 +676,7 @@ connect_controller (GObject *controller, p->prop = g_strdup (prop_name); g_signal_connect_data (controller, signal, func, p, - (GDestroyNotify)free_object_property, + (GClosureNotify)free_object_property, FALSE, FALSE); } @@ -142,6 +763,52 @@ bool_changed (GObject *object, GParamSpec *pspec, gpointer data) g_value_unset (&val); } + +static void +enum_modified (GtkOptionMenu *om, gpointer data) +{ + ObjectProperty *p = data; + gint i; + GParamSpec *spec; + GEnumClass *eclass; + + spec = g_object_class_find_property (G_OBJECT_GET_CLASS (p->obj), + p->prop); + + eclass = G_ENUM_CLASS (g_type_class_peek (spec->value_type)); + + i = gtk_option_menu_get_history (om); + + g_object_set (p->obj, p->prop, eclass->values[i].value, NULL); +} + +static void +enum_changed (GObject *object, GParamSpec *pspec, gpointer data) +{ + GtkOptionMenu *om = GTK_OPTION_MENU (data); + GValue val = { 0, }; + GEnumClass *eclass; + gint i; + + eclass = G_ENUM_CLASS (g_type_class_peek (pspec->value_type)); + + g_value_init (&val, pspec->value_type); + g_object_get_property (object, pspec->name, &val); + + i = 0; + while (i < eclass->n_values) + { + if (eclass->values[i].value == g_value_get_enum (&val)) + break; + ++i; + } + + if (gtk_option_menu_get_history (om) != i) + gtk_option_menu_set_history (om, i); + + g_value_unset (&val); +} + static GtkWidget* create_prop_editor (GObject *object) { @@ -260,18 +927,64 @@ create_prop_editor (GObject *object) connect_controller (G_OBJECT (prop_edit), "toggled", object, spec->name, (GtkSignalFunc) bool_modified); break; - + default: - { - gchar *msg = g_strdup_printf ("%s: don't know how to edit type %s", - spec->nick, g_type_name (spec->value_type)); - hbox = gtk_hbox_new (FALSE, 10); - label = gtk_label_new (msg); - g_free (msg); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - } + if (g_type_is_a (spec->value_type, G_TYPE_ENUM)) + { + GtkWidget *menu; + GEnumClass *eclass; + gint i; + + hbox = gtk_hbox_new (FALSE, 10); + label = gtk_label_new (spec->nick); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + + prop_edit = gtk_option_menu_new (); + + menu = gtk_menu_new (); + + eclass = G_ENUM_CLASS (g_type_class_peek (spec->value_type)); + + i = 0; + while (i < eclass->n_values) + { + GtkWidget *mi; + + mi = gtk_menu_item_new_with_label (eclass->values[i].value_name); + + gtk_widget_show (mi); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi); + + ++i; + } + + gtk_option_menu_set_menu (GTK_OPTION_MENU (prop_edit), menu); + + gtk_box_pack_end (GTK_BOX (hbox), prop_edit, FALSE, FALSE, 0); + + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + + g_object_connect_property (object, spec->name, + GTK_SIGNAL_FUNC (enum_changed), + prop_edit); + + if (can_modify) + connect_controller (G_OBJECT (prop_edit), "changed", + object, spec->name, (GtkSignalFunc) enum_modified); + } + else + { + gchar *msg = g_strdup_printf ("%s: don't know how to edit type %s", + spec->nick, g_type_name (spec->value_type)); + hbox = gtk_hbox_new (FALSE, 10); + label = gtk_label_new (msg); + g_free (msg); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + } break; } @@ -294,20 +1007,3 @@ create_prop_editor (GObject *object) return win; } -int -main (int argc, - char **argv) -{ - GtkWidget *window; - - gtk_init (&argc, &argv); - - /* I didn't write the tree test yet, just the property editor to use - * inside the tree test ;-) - */ - window = create_prop_editor (G_OBJECT (gtk_text_tag_new ("foo"))); - - gtk_main (); - - return 0; -} |