summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--docs/reference/ChangeLog5
-rw-r--r--docs/reference/pygtk-pygtkgenerictreemodel.xml69
-rw-r--r--examples/Makefile.am1
-rw-r--r--examples/gtk/customtreemodel.py177
-rw-r--r--gtk/gtk-extrafuncs.defs18
-rw-r--r--gtk/pygtktreemodel.c40
-rw-r--r--gtk/pygtktreemodel.h6
8 files changed, 327 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index f617db16..d8e8b765 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2007-07-30 Paul Pogonyshev <pogonyshev@gmx.net>
+
+ reviewed by: Johan, Fix bug #388754
+
+ * examples/gtk/customtreemodel.py: Add usage example.
+
+ * gtk/gtk-extrafuncs.defs (get_user_data, create_tree_iter): New
+ methods of `gtk.GenericTreeModel'.
+
+ * gtk/pygtktreemodel.c (pygtk_generic_tree_model_get_user_data)
+ (pygtk_generic_tree_model_create_tree_iter): New functions.
+
2007-07-28 Gian Mario Tagliaretti <gianmt@gnome.org>
reviewed by: gjc, Fix bug #461245
diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog
index 3fb6257f..3d9e6262 100644
--- a/docs/reference/ChangeLog
+++ b/docs/reference/ChangeLog
@@ -1,3 +1,8 @@
+2007-07-30 Paul Pogonyshev <pogonyshev@gmx.net>
+
+ * pygtk-pygtkgenerictreemodel.xml: Document new create_tree_iter()
+ and get_user_data().
+
2007-07-29 Gian Mario Tagliaretti <gianmt@gnome.org>
* pygtk-gtkicontheme.xml: Update with 2.12 API.
diff --git a/docs/reference/pygtk-pygtkgenerictreemodel.xml b/docs/reference/pygtk-pygtkgenerictreemodel.xml
index 54677206..455a28e9 100644
--- a/docs/reference/pygtk-pygtkgenerictreemodel.xml
+++ b/docs/reference/pygtk-pygtkgenerictreemodel.xml
@@ -30,6 +30,14 @@ linkend="constructor-gtkgenerictreemodel">gtk.GenericTreeModel</link></methodnam
<methodname><link linkend="method-gtkgenerictreemodel--iter-is-valid">iter_is_valid</link></methodname>
<methodparam><parameter role="keyword">iter</parameter></methodparam>
</methodsynopsis>
+ <methodsynopsis language="python">
+ <methodname><link linkend="method-gtkgenerictreemodel--get-user-data">get_user_data</link></methodname>
+ <methodparam><parameter role="keyword">iter</parameter></methodparam>
+ </methodsynopsis>
+ <methodsynopsis language="python">
+ <methodname><link linkend="method-gtkgenerictreemodel--create-tree-iter">create_tree_iter</link></methodname>
+ <methodparam><parameter role="keyword">user_data</parameter></methodparam>
+ </methodsynopsis>
</classsynopsis>
</refsect1>
@@ -274,6 +282,67 @@ model.</para>
</refsect2>
+ <refsect2 id="method-gtkgenerictreemodel--get-user-data">
+ <title>gtk.GenericTreeModel.get_user_data</title>
+
+ <programlisting><methodsynopsis language="python">
+ <methodname>get_user_data</methodname>
+ <methodparam><parameter
+ role="keyword">iter</parameter></methodparam>
+ </methodsynopsis></programlisting>
+ <variablelist>
+ <varlistentry>
+ <term><parameter role="keyword">iter</parameter>&nbsp;:</term>
+ <listitem><simpara>a <link
+ linkend="class-gtktreeiter"><classname>gtk.TreeIter</classname></link>
+ created by this tree model.</simpara></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><emphasis>Returns</emphasis>&nbsp;:</term>
+ <listitem><simpara>Python object reference that is wrapped by this
+ <classname>gtk.TreeIter</classname>.</simpara></listitem>
+ </varlistentry>
+ </variablelist>
+
+ <warning>
+ <para>This method should be treated as protected. It should only
+ be used by derived classes.</para>
+ </warning>
+
+ <para><classname>gtk.GenericTreeModel</classname> transparently wraps arbitrary Python objects to instances of <link linkend="class-gtktreeiter"><classname>gtk.TreeIter</classname></link>. E.g. you return anything from <methodname>on_get_iter</methodname> and the model wraps the value, so <methodname>get_iter</methodname> method returns a <classname>gtk.TreeIter</classname>. This method allows to retrieve the Python object used to construct given iterator.</para>
+
+ </refsect2>
+
+ <refsect2 id="method-gtkgenerictreemodel--create-tree-iter">
+ <title>gtk.GenericTreeModel.create_tree_iter</title>
+
+ <programlisting><methodsynopsis language="python">
+ <methodname>create_tree_iter</methodname>
+ <methodparam><parameter
+ role="keyword">user_data</parameter></methodparam>
+ </methodsynopsis></programlisting>
+ <variablelist>
+ <varlistentry>
+ <term><parameter role="keyword">user_data</parameter>&nbsp;:</term>
+ <listitem><simpara>a Python object, the same you would return from
+ e.g. <methodname>on_get_iter</methodname>.</simpara></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><emphasis>Returns</emphasis>&nbsp;:</term>
+ <listitem><simpara>a <link
+ linkend="class-gtktreeiter"><classname>gtk.TreeIter</classname></link>.</simpara></listitem>
+ </varlistentry>
+ </variablelist>
+
+ <warning>
+ <para>This method should be treated as protected. It should only
+ be used by derived classes.</para>
+ </warning>
+
+ <para><classname>gtk.GenericTreeModel</classname> transparently wraps arbitrary Python objects to instances of <link linkend="class-gtktreeiter"><classname>gtk.TreeIter</classname></link>. E.g. you return anything from <methodname>on_get_iter</methodname> and the model wraps the value, so <methodname>get_iter</methodname> method returns a <classname>gtk.TreeIter</classname>. This method allows you to perform this wrapping explicitly, not just from a predefined set of methods.</para>
+
+ </refsect2>
+
</refsect1>
</refentry>
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 2407b296..e53dbbd3 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -20,6 +20,7 @@ EXTRA_DIST = \
gobject/properties.py \
gobject/signal.py \
gtk/bin.py \
+ gtk/customtreemodel.py \
gtk/filechooser.py \
gtk/scrollable.py \
gtk/sizegroup.py \
diff --git a/examples/gtk/customtreemodel.py b/examples/gtk/customtreemodel.py
new file mode 100644
index 00000000..27335dce
--- /dev/null
+++ b/examples/gtk/customtreemodel.py
@@ -0,0 +1,177 @@
+#! /usr/bin/env python
+
+import sys
+import weakref
+
+import pango
+import gtk
+
+
+class SimpleListTreeModel(gtk.GenericTreeModel):
+
+ def on_get_flags(self):
+ return gtk.TREE_MODEL_LIST_ONLY
+
+ def __init__(self, *values):
+ gtk.GenericTreeModel.__init__(self)
+ self.__values = list(values)
+
+ self.props.leak_references = False
+
+ # This is only needed to make the model gc-safe, since
+ # leak_references is False.
+ self.__iters = range(0, len(values))
+
+ def on_get_n_columns(self):
+ return 0
+
+ def on_get_column_type(self, index):
+ raise NotImplementedError
+
+ def on_get_value(self, row, column):
+ raise NotImplementedError
+
+ def on_get_iter(self, path):
+ return self.__iters[path[0]]
+
+ def on_get_path(self, row):
+ return(row,)
+
+ def on_iter_parent(self, row):
+ return None
+
+ def on_iter_next(self, row):
+ if row + 1 < len(self.__values):
+ return self.__iters[row + 1]
+ else:
+ return None
+
+ def on_iter_has_child(self, row):
+ return False
+
+ def on_iter_children(self, row):
+ if row is None:
+ return self.__iters[0]
+ else:
+ return None
+
+ def on_iter_n_children(self, row):
+ if row is None:
+ return len(self.__values)
+ else:
+ return 0
+
+ def on_iter_nth_child(self, parent, n):
+ if parent:
+ return None
+ else:
+ return self.__iters[n]
+
+
+ def __len__ (self):
+ return len(self.__values)
+
+ def __getitem__ (self, key):
+ return self.__values[self.get_user_data(key)]
+
+ def __iter__ (self):
+ return iter(self.__values)
+
+ def __contains__ (self, value):
+ return value in self.__values
+
+
+ def insert(self, index_or_iter, new_value):
+ if isinstance(index_or_iter, gtk.TreeIter):
+ index_or_iter = self.get_user_data(index_or_iter)
+
+ self.__values.insert(index_or_iter, new_value)
+ self.__iters.append(len(self.__iters))
+
+ titer = self.create_tree_iter(self.__iters[index_or_iter])
+ self.row_inserted(self.get_path(titer), titer)
+
+
+class Food(object):
+
+ def __init__(self, name, description=None):
+ self.name = name
+ self.description = description
+
+ def set_to_text_renderer(column, cell, model, iter):
+ value = model[iter]
+
+ cell.props.text = value.name
+
+ if value.description is None:
+ cell.props.weight = pango.WEIGHT_BOLD
+ else:
+ cell.props.weight = pango.WEIGHT_NORMAL
+
+ set_to_text_renderer = staticmethod(set_to_text_renderer)
+
+
+def generate_values():
+ yield Food('Fruits')
+ yield Food('Apple', 'Round and red. Or green. Or yellow.')
+ yield Food('Orange', 'Juicy')
+ yield Food('Vegetables')
+ yield Food('Tomato', 'Red and juicy.')
+ yield Food('Cucumber', 'Long and hard.')
+
+def insert_item(*ignored):
+ model, titer = tree_view.get_selection().get_selected()
+
+ if titer is None or model[titer].description is None:
+ dialog = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_OK,
+ message_format='Please select something. And not a header!')
+ dialog.run()
+ dialog.destroy()
+ else:
+ model.insert(titer, Food('Random name', 'Some random, but useful description.'))
+
+def show_description(*ignored):
+ model, titer = tree_view.get_selection().get_selected()
+
+ if titer is None or model[titer].description is None:
+ dialog = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_OK,
+ message_format='Please select something. And not a header!')
+ else:
+ dialog = gtk.MessageDialog(buttons=gtk.BUTTONS_OK,
+ message_format=model[titer].description)
+
+ dialog.run()
+ dialog.destroy()
+
+window = gtk.Window()
+tree_model = SimpleListTreeModel(*generate_values())
+tree_view = gtk.TreeView(tree_model)
+scrolled_window = gtk.ScrolledWindow()
+vertical_box = gtk.VBox(False, 6)
+button_box = gtk.HButtonBox()
+insert = gtk.Button('Insert')
+description = gtk.Button('Show Description')
+
+scrolled_window.add(tree_view)
+vertical_box.pack_start(scrolled_window)
+vertical_box.pack_start(button_box, False, False)
+button_box.pack_start(insert)
+button_box.pack_start(description)
+window.add(vertical_box)
+
+tree_view.set_headers_visible(False)
+
+text_renderer = gtk.CellRendererText()
+column = gtk.TreeViewColumn(None, text_renderer)
+
+column.set_cell_data_func(text_renderer, Food.set_to_text_renderer)
+tree_view.append_column(column)
+
+insert.connect('clicked', insert_item)
+description.connect('clicked', show_description)
+window.connect('destroy', lambda window: gtk.main_quit())
+
+window.resize(400, 500)
+window.show_all()
+
+gtk.main()
diff --git a/gtk/gtk-extrafuncs.defs b/gtk/gtk-extrafuncs.defs
index af690ef8..29c71f0c 100644
--- a/gtk/gtk-extrafuncs.defs
+++ b/gtk/gtk-extrafuncs.defs
@@ -88,6 +88,24 @@
)
)
+(define-method get_user_data
+ (of-object "PyGtkGenericTreeModel")
+ (c-name "pygtk_generic_tree_model_get_user_data")
+ (return-type "PyObject*")
+ (parameters
+ '("GtkTreeIter*" "iter")
+ )
+)
+
+(define-method create_tree_iter
+ (of-object "PyGtkGenericTreeModel")
+ (c-name "pygtk_generic_tree_model_create_tree_iter")
+ (return-type "GtkTreeIter")
+ (parameters
+ '("PyObject*" "user_data")
+ )
+)
+
;; PyGtkGenericCellRenderer
(define-object GenericCellRenderer
diff --git a/gtk/pygtktreemodel.c b/gtk/pygtktreemodel.c
index a3f85805..f908c37b 100644
--- a/gtk/pygtktreemodel.c
+++ b/gtk/pygtktreemodel.c
@@ -24,7 +24,6 @@
#endif
#include "pygtktreemodel.h"
-#include <Python.h>
#include "pygtk-private.h"
/* define this to print out debug messages */
@@ -801,3 +800,42 @@ pygtk_generic_tree_model_iter_is_valid(PyGtkGenericTreeModel *tree_model,
return VALID_ITER(iter, tree_model);
}
+
+PyObject *
+pygtk_generic_tree_model_get_user_data(PyGtkGenericTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ g_return_val_if_fail(tree_model != NULL, NULL);
+
+ if (VALID_ITER(iter, tree_model)) {
+ /* Py_INCREF and NULL checking is done at _wrap_*() level. */
+ return iter->user_data;
+ }
+ else {
+ g_warning("iter is not valid for the tree model");
+ return NULL;
+ }
+}
+
+GtkTreeIter
+pygtk_generic_tree_model_create_tree_iter(PyGtkGenericTreeModel *tree_model,
+ PyObject *user_data)
+{
+ GtkTreeIter iter;
+
+ if (tree_model != NULL) {
+ iter.user_data = user_data;
+ iter.stamp = PYGTK_GENERIC_TREE_MODEL(tree_model)->stamp;
+
+ /* Otherwise, caller is supposed to hold a reference somewhere. */
+ if (PYGTK_GENERIC_TREE_MODEL(tree_model)->leak_references)
+ Py_INCREF(user_data);
+ }
+ else {
+ /* FIXME: I guess this is still not enough. */
+ iter.user_data = NULL;
+ iter.stamp = 0;
+ }
+
+ return iter;
+}
diff --git a/gtk/pygtktreemodel.h b/gtk/pygtktreemodel.h
index 703eefb0..2412c4bc 100644
--- a/gtk/pygtktreemodel.h
+++ b/gtk/pygtktreemodel.h
@@ -20,6 +20,8 @@
* USA
*/
+#include <Python.h>
+
#include <gtk/gtktreemodel.h>
#define PYGTK_TYPE_GENERIC_TREE_MODEL (pygtk_generic_tree_model_get_type())
@@ -48,3 +50,7 @@ PyGtkGenericTreeModel * pygtk_generic_tree_model_new (void);
void pygtk_generic_tree_model_invalidate_iters(PyGtkGenericTreeModel *);
gboolean pygtk_generic_tree_model_iter_is_valid(PyGtkGenericTreeModel *,
GtkTreeIter *);
+PyObject * pygtk_generic_tree_model_get_user_data(PyGtkGenericTreeModel *,
+ GtkTreeIter *);
+GtkTreeIter pygtk_generic_tree_model_create_tree_iter(PyGtkGenericTreeModel *,
+ PyObject *);