summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohan Dahlin <johan@src.gnome.org>2004-07-17 16:38:46 +0000
committerJohan Dahlin <johan@src.gnome.org>2004-07-17 16:38:46 +0000
commita565ad51fe4d189ed0bc85bde14bf3aa87f2f344 (patch)
tree70be806b8e19117619961a07def10dc931d7d5f7
parent2fa0940002a5ebe976d88e3c9397a1fb5cb5486d (diff)
downloadpygtk-a565ad51fe4d189ed0bc85bde14bf3aa87f2f344.tar.gz
gtk/*.override
* gtk/*.override * codegen/codegen.py: * codegen/argtypes.py: Update for enums * pygtype.c (pyg_value_as_pyobject): Use new enum/flag functions * pygenum.[ch]: Handle GFlag * pygflags.[ch]: Handle GFlag * atk-types.defs: Fix gtype-id for all enums * gobjectmodule.c (initgobject): Clean up and add convinience macros * tests/enum.py: New file * tests/common.py: New file, also stole from gst-python
-rw-r--r--ChangeLog19
-rw-r--r--Makefile.am14
-rw-r--r--atk-types.defs8
-rw-r--r--atk.override1
-rw-r--r--codegen/argtypes.py4
-rw-r--r--codegen/codegen.py15
-rw-r--r--gobject/gobjectmodule.c84
-rw-r--r--gobject/pygenum.c252
-rw-r--r--gobject/pygenum.h54
-rw-r--r--gobject/pygflags.c367
-rw-r--r--gobject/pygflags.h52
-rw-r--r--gobject/pygobject-private.h3
-rw-r--r--gobject/pygobject.h29
-rw-r--r--gobject/pygtype.c7
-rw-r--r--gobjectmodule.c84
-rw-r--r--gtk/__init__.py2
-rw-r--r--gtk/gdk.override26
-rw-r--r--gtk/gtk.override25
-rw-r--r--gtk/gtktreeview.override9
-rw-r--r--pygenum.c252
-rw-r--r--pygenum.h54
-rw-r--r--pygflags.c367
-rw-r--r--pygflags.h52
-rw-r--r--pygobject-private.h3
-rw-r--r--pygobject.h29
-rw-r--r--pygtype.c7
-rw-r--r--tests/Makefile.am1
-rw-r--r--tests/common.py16
-rw-r--r--tests/conversion.py2
-rw-r--r--tests/runtests.py2
-rw-r--r--tests/signal.py2
31 files changed, 1698 insertions, 144 deletions
diff --git a/ChangeLog b/ChangeLog
index 5bd3dabe..73ee2d2f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2004-07-17 Johan Dahlin <johan@gnome.org>
+
+ * codegen/codegen.py:
+ * codegen/argtypes.py: Update for enums
+
+ * pygtype.c (pyg_value_as_pyobject): Use new enum/flag functions
+
+ * pygenum.[ch]: Handle GFlag
+
+ * pygflags.[ch]: Handle GFlag
+
+ * atk-types.defs: Fix gtype-id for all enums
+
+ * gobjectmodule.c (initgobject): Clean up and add convinience macros
+
+ * tests/enum.py: New file
+
+ * tests/common.py: New file, also stole from gst-python
+
2004-07-17 Gustavo J. A. M. Carneiro <gustavo@users.sourceforge.net>
* gtk/gtk.override (_wrap_gtk_table_new): Override to allow rows
diff --git a/Makefile.am b/Makefile.am
index c996dd30..a5dbbf57 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,7 @@
# require automake-1.7
AUTOMAKE_OPTIONS = 1.7
-SUBDIRS = codegen gtk docs
+SUBDIRS = codegen gtk docs tests
CLEANFILES =
EXTRA_DIST = $(defs_DATA)
@@ -53,8 +53,16 @@ endif
gobject_la_LDFLAGS = $(common_ldflags) -export-symbols-regex initgobject
gobject_la_LIBADD = $(GLIB_LIBS)
gobject_la_SOURCES = \
- pygobject.h pygobject-private.h \
- gobjectmodule.c pygtype.c pygobject.c pygboxed.c
+ gobjectmodule.c \
+ pygboxed.c \
+ pygenum.c \
+ pygenum.h \
+ pygflags.c \
+ pygflags.h \
+ pygobject.c \
+ pygobject.h \
+ pygobject-private.h \
+ pygtype.c
# pango module
pango_la_LDFLAGS = $(common_ldflags) -export-symbols-regex initpango
diff --git a/atk-types.defs b/atk-types.defs
index 80ac340b..222840f0 100644
--- a/atk-types.defs
+++ b/atk-types.defs
@@ -75,6 +75,7 @@
(define-enum Role
(in-module "Atk")
(c-name "AtkRole")
+ (gtype-id "ATK_TYPE_ROLE")
(values
'("invalid" "ATK_ROLE_INVALID")
'("accel-label" "ATK_ROLE_ACCEL_LABEL")
@@ -152,6 +153,7 @@
(define-enum Layer
(in-module "Atk")
(c-name "AtkLayer")
+ (gtype-id "ATK_TYPE_LAYER")
(values
'("invalid" "ATK_LAYER_INVALID")
'("background" "ATK_LAYER_BACKGROUND")
@@ -166,6 +168,7 @@
(define-enum RelationType
(in-module "Atk")
(c-name "AtkRelationType")
+ (gtype-id "ATK_TYPE_RELATION_TYPE")
(values
'("null" "ATK_RELATION_NULL")
'("controlled-by" "ATK_RELATION_CONTROLLED_BY")
@@ -181,6 +184,7 @@
(define-enum StateType
(in-module "Atk")
(c-name "AtkStateType")
+ (gtype-id "ATK_TYPE_STATE_TYPE")
(values
'("invalid" "ATK_STATE_INVALID")
'("active" "ATK_STATE_ACTIVE")
@@ -218,6 +222,7 @@
(define-enum TextAttribute
(in-module "Atk")
(c-name "AtkTextAttribute")
+ (gtype-id "ATK_TYPE_TEXT_ATTRIBUTE")
(values
'("left-margin" "ATK_TEXT_ATTR_LEFT_MARGIN")
'("right-margin" "ATK_TEXT_ATTR_RIGHT_MARGIN")
@@ -252,6 +257,7 @@
(define-enum TextBoundary
(in-module "Atk")
(c-name "AtkTextBoundary")
+ (gtype-id "ATK_TYPE_TEXT_BOUNDARY")
(values
'("char" "ATK_TEXT_BOUNDARY_CHAR")
'("word-start" "ATK_TEXT_BOUNDARY_WORD_START")
@@ -266,6 +272,7 @@
(define-enum KeyEventType
(in-module "Atk")
(c-name "AtkKeyEventType")
+ (gtype-id "ATK_TYPE_KEY_EVENT_TYPE")
(values
'("press" "ATK_KEY_EVENT_PRESS")
'("release" "ATK_KEY_EVENT_RELEASE")
@@ -276,6 +283,7 @@
(define-enum CoordType
(in-module "Atk")
(c-name "AtkCoordType")
+ (gtype-id "ATK_TYPE_COORD_TYPE")
(values
'("screen" "ATK_XY_SCREEN")
'("window" "ATK_XY_WINDOW")
diff --git a/atk.override b/atk.override
index 7b7e0de1..5f27e3be 100644
--- a/atk.override
+++ b/atk.override
@@ -24,6 +24,7 @@ headers
#define NO_IMPORT_PYGOBJECT
#include "pygobject.h"
#include <atk/atk.h>
+#include <atk/atk-enum-types.h>
#include <atk/atknoopobjectfactory.h>
#include <atk/atknoopobject.h>
%%
diff --git a/codegen/argtypes.py b/codegen/argtypes.py
index 9d4afd48..1fe1eb27 100644
--- a/codegen/argtypes.py
+++ b/codegen/argtypes.py
@@ -318,7 +318,7 @@ class EnumArg(ArgType):
info.add_parselist('O', ['&py_' + pname], [pname]);
def write_return(self, ptype, ownsreturn, info):
info.varlist.add('gint', 'ret')
- info.codeafter.append(' return PyInt_FromLong(ret);')
+ info.codeafter.append(' return pyg_enum_from_gtype(%s, ret);' % self.typecode)
class FlagsArg(ArgType):
flag = (' if (%(default)spyg_flags_get_value(%(typecode)s, py_%(name)s, (gint *)&%(name)s))\n'
@@ -341,7 +341,7 @@ class FlagsArg(ArgType):
info.add_parselist('O', ['&py_' + pname], [pname])
def write_return(self, ptype, ownsreturn, info):
info.varlist.add('guint', 'ret')
- info.codeafter.append(' return PyInt_FromLong(ret);')
+ info.codeafter.append(' return pyg_flags_from_gtype(%s, ret);' % self.typecode)
class ObjectArg(ArgType):
# should change these checks to more typesafe versions that check
diff --git a/codegen/codegen.py b/codegen/codegen.py
index 659c6adb..f4c292d1 100644
--- a/codegen/codegen.py
+++ b/codegen/codegen.py
@@ -752,6 +752,7 @@ def write_enums(parser, prefix, fp=sys.stdout):
return
fp.write('\n/* ----------- enums and flags ----------- */\n\n')
fp.write('void\n' + prefix + '_add_constants(PyObject *module, const gchar *strip_prefix)\n{\n')
+
for enum in parser.enums:
if enum.typecode is None:
for nick, value in enum.values:
@@ -759,15 +760,17 @@ def write_enums(parser, prefix, fp=sys.stdout):
% (value, value))
else:
if enum.deftype == 'enum':
- fp.write(' pyg_enum_add_constants(module, %s, strip_prefix);\n'
- % (enum.typecode,))
+ fp.write(' pyg_enum_add(module, "%s", strip_prefix, %s);\n' % (enum.name, enum.typecode))
else:
- fp.write(' pyg_flags_add_constants(module, %s, strip_prefix);\n'
- % (enum.typecode,))
+ fp.write(' pyg_flags_add(module, "%s", strip_prefix, %s);\n' % (enum.name, enum.typecode))
+
+ fp.write('\n')
+ fp.write(' if (!PyErr_Occurred())\n')
+ fp.write(' PyErr_Print();\n')
fp.write('}\n\n')
def write_extension_init(overrides, prefix, fp):
- fp.write('/* intialise stuff extension classes */\n')
+ fp.write('/* initialise stuff extension classes */\n')
fp.write('void\n' + prefix + '_register_classes(PyObject *d)\n{\n')
imports = overrides.get_imports()[:]
if imports:
@@ -905,7 +908,9 @@ def main(argv):
p = defsparser.DefsParser(args[0], defines)
if not outfilename:
outfilename = os.path.splitext(args[0])[0] + '.c'
+
p.startParsing()
+
register_types(p)
write_source(p, o, prefix, FileOutput(sys.stdout, outfilename))
diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c
index ec9fcf49..6159ca90 100644
--- a/gobject/gobjectmodule.c
+++ b/gobject/gobjectmodule.c
@@ -26,6 +26,9 @@
#include "pygobject-private.h"
+#include "pygenum.h"
+#include "pygflags.h"
+
static PyObject *gerror_exc = NULL;
static const gchar *pyginterface_type_id = "PyGInterface::type";
GQuark pyginterface_type_key = 0;
@@ -1880,7 +1883,7 @@ static PyMethodDef pygobject_functions[] = {
*
* Returns: the stripped constant name.
*/
-static char *
+char *
pyg_constant_strip_prefix(gchar *name, const gchar *strip_prefix)
{
gint prefix_len;
@@ -2158,12 +2161,35 @@ struct _PyGObject_Functions pygobject_api_functions = {
&PyGParamSpec_Type,
pyg_param_spec_new,
pyg_param_spec_from_object,
+
pyg_pyobj_to_unichar_conv,
pyg_parse_constructor_args,
pyg_param_gvalue_as_pyobject,
- pyg_param_gvalue_from_pyobject
+ pyg_param_gvalue_from_pyobject,
+
+ &PyGEnum_Type,
+ pyg_enum_add,
+ pyg_enum_from_gtype,
+
+ &PyGFlags_Type,
+ pyg_flags_add,
+ pyg_flags_from_gtype
};
+#define REGISTER_TYPE(d, type, name) \
+ type.ob_type = &PyType_Type; \
+ type.tp_alloc = PyType_GenericAlloc; \
+ type.tp_new = PyType_GenericNew; \
+ if (PyType_Ready(&type)) \
+ return; \
+ PyDict_SetItemString(d, name, (PyObject *)&type);
+
+#define REGISTER_GTYPE(d, type, name, gtype) \
+ REGISTER_TYPE(d, type, name); \
+ PyDict_SetItemString(type.tp_dict, "__gtype__", \
+ o=pyg_type_wrapper_new(gtype)); \
+ Py_DECREF(o);
+
DL_EXPORT(void)
initgobject(void)
{
@@ -2188,7 +2214,7 @@ initgobject(void)
gerror_exc = PyErr_NewException("gobject.GError", PyExc_RuntimeError,NULL);
PyDict_SetItemString(d, "GError", gerror_exc);
-
+
PyGObject_Type.tp_alloc = PyType_GenericAlloc;
PyGObject_Type.tp_new = PyType_GenericNew;
pygobject_register_class(d, "GObject", G_TYPE_OBJECT,
@@ -2196,55 +2222,23 @@ initgobject(void)
PyDict_SetItemString(PyGObject_Type.tp_dict, "__gdoc__",
pyg_object_descr_doc_get());
- PyGInterface_Type.ob_type = &PyType_Type;
- PyGInterface_Type.tp_alloc = PyType_GenericAlloc;
- PyGInterface_Type.tp_new = PyType_GenericNew;
- if (PyType_Ready(&PyGInterface_Type))
- return;
- PyDict_SetItemString(d, "GInterface", (PyObject *)&PyGInterface_Type);
- PyDict_SetItemString(PyGInterface_Type.tp_dict, "__gtype__",
- o=pyg_type_wrapper_new(G_TYPE_INTERFACE));
- Py_DECREF(o);
+ REGISTER_GTYPE(d, PyGInterface_Type, "GInterface", G_TYPE_INTERFACE);
PyDict_SetItemString(PyGInterface_Type.tp_dict, "__doc__",
pyg_object_descr_doc_get());
PyDict_SetItemString(PyGInterface_Type.tp_dict, "__gdoc__",
pyg_object_descr_doc_get());
pyginterface_type_key = g_quark_from_static_string(pyginterface_type_id);
- PyGBoxed_Type.ob_type = &PyType_Type;
- PyGBoxed_Type.tp_alloc = PyType_GenericAlloc;
- PyGBoxed_Type.tp_new = PyType_GenericNew;
- if (PyType_Ready(&PyGBoxed_Type))
- return;
- PyDict_SetItemString(d, "GBoxed", (PyObject *)&PyGBoxed_Type);
- PyDict_SetItemString(PyGBoxed_Type.tp_dict, "__gtype__",
- o=pyg_type_wrapper_new(G_TYPE_BOXED));
- Py_DECREF(o);
+ REGISTER_GTYPE(d, PyGBoxed_Type, "GBoxed", G_TYPE_BOXED);
+ REGISTER_GTYPE(d, PyGPointer_Type, "GPointer", G_TYPE_POINTER);
+ REGISTER_GTYPE(d, PyGEnum_Type, "GEnum", G_TYPE_ENUM);
+ PyGEnum_Type.tp_base = &PyInt_Type;
+ REGISTER_GTYPE(d, PyGFlags_Type, "GFlags", G_TYPE_FLAGS);
+ PyGFlags_Type.tp_base = &PyInt_Type;
- PyGMainLoop_Type.ob_type = &PyType_Type;
- PyGMainLoop_Type.tp_alloc = PyType_GenericAlloc;
- PyGMainLoop_Type.tp_new = PyType_GenericNew;
- if (PyType_Ready(&PyGMainLoop_Type))
- return;
- PyDict_SetItemString(d, "MainLoop", (PyObject *)&PyGMainLoop_Type);
+ REGISTER_TYPE(d, PyGMainLoop_Type, "GMainLoop");
+ REGISTER_TYPE(d, PyGMainContext_Type, "GMainContext");
- PyGMainContext_Type.ob_type = &PyType_Type;
- PyGMainContext_Type.tp_alloc = PyType_GenericAlloc;
- PyGMainContext_Type.tp_new = PyType_GenericNew;
- if (PyType_Ready(&PyGMainContext_Type))
- return;
- PyDict_SetItemString(d, "MainContext", (PyObject *)&PyGMainContext_Type);
-
- PyGPointer_Type.ob_type = &PyType_Type;
- PyGPointer_Type.tp_alloc = PyType_GenericAlloc;
- PyGPointer_Type.tp_new = PyType_GenericNew;
- if (PyType_Ready(&PyGPointer_Type))
- return;
- PyDict_SetItemString(d, "GPointer", (PyObject *)&PyGPointer_Type);
- PyDict_SetItemString(PyGPointer_Type.tp_dict, "__gtype__",
- o=pyg_type_wrapper_new(G_TYPE_POINTER));
- Py_DECREF(o);
-
/* glib version */
tuple = Py_BuildValue ("(iii)", glib_major_version, glib_minor_version,
glib_micro_version);
@@ -2281,7 +2275,7 @@ initgobject(void)
PyModule_AddIntConstant(m, "PRIORITY_HIGH", G_PRIORITY_HIGH);
PyModule_AddIntConstant(m, "PRIORITY_DEFAULT", G_PRIORITY_DEFAULT);
PyModule_AddIntConstant(m, "PRIORITY_HIGH_IDLE", G_PRIORITY_HIGH_IDLE);
- PyModule_AddIntConstant(m,"PRIORITY_DEFAULT_IDLE",G_PRIORITY_DEFAULT_IDLE);
+ PyModule_AddIntConstant(m, "PRIORITY_DEFAULT_IDLE",G_PRIORITY_DEFAULT_IDLE);
PyModule_AddIntConstant(m, "PRIORITY_LOW", G_PRIORITY_LOW);
PyModule_AddIntConstant(m, "IO_IN", G_IO_IN);
diff --git a/gobject/pygenum.c b/gobject/pygenum.c
new file mode 100644
index 00000000..c9444f0a
--- /dev/null
+++ b/gobject/pygenum.c
@@ -0,0 +1,252 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * pygtk- Python bindings for the GTK toolkit.
+ * Copyright (C) 1998-2003 James Henstridge
+ * Copyright (C) 2004 Johan Dahlin
+ *
+ * pygenum.c: GEnum and GFlag wrappers
+ *
+ * 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.1 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
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "pygobject-private.h"
+#include "pygenum.h"
+
+static const gchar *pygenum_class_id = "PyGEnum::class";
+static GQuark pygenum_class_key = 0;
+
+#define GET_INT(x) (((PyIntObject*)x)->ob_ival)
+static int
+pyg_enum_compare(PyGEnum *self, PyObject *other)
+{
+ if (!PyInt_CheckExact(other) && ((PyGEnum*)other)->gtype != self->gtype) {
+ PyErr_Warn(PyExc_Warning, "comparing different enum types");
+ return -1;
+ }
+
+ if (GET_INT(self) == GET_INT(other))
+ return 0;
+ else if (GET_INT(self) > GET_INT(other))
+ return -1;
+ else
+ return 1;
+}
+#undef GET_INT
+
+static PyObject *
+pyg_enum_repr(PyGEnum *self)
+{
+ GEnumClass *enum_class;
+ GEnumValue *enum_value;
+ static char tmp[256];
+
+ enum_class = g_type_class_ref(self->gtype);
+ g_assert(G_IS_ENUM_CLASS(enum_class));
+
+ enum_value = g_enum_get_value(enum_class, self->parent.ob_ival);
+ g_assert(enum_value != 0);
+
+ sprintf(tmp, "<enum %s of type %s>", enum_value->value_name, g_type_name(self->gtype));
+
+ g_type_class_unref(enum_class);
+
+ return PyString_FromString(tmp);
+}
+
+static PyObject *
+pyg_enum_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "value", NULL };
+ long value;
+ PyObject *pytc, *values, *ret;
+ GType gtype;
+ GEnumClass *eclass;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "l", kwlist, &value))
+ return NULL;
+
+ pytc = PyObject_GetAttrString((PyObject *)type, "__gtype__");
+ if (!pytc)
+ return NULL;
+
+ if (!PyObject_TypeCheck(pytc, &PyGEnum_Type)) {
+ Py_DECREF(pytc);
+ PyErr_SetString(PyExc_TypeError,
+ "__gtype__ attribute not a typecode");
+ return NULL;
+ }
+
+ gtype = pyg_type_from_object(pytc);
+ Py_DECREF(pytc);
+
+ eclass = G_ENUM_CLASS(g_type_class_ref(gtype));
+
+ if (value < 0 || value > eclass->n_values) {
+ PyErr_SetString(PyExc_ValueError, "value out of range");
+ g_type_class_unref(eclass);
+ return NULL;
+ }
+
+ values = PyObject_GetAttrString((PyObject *)type, "__enum_values__");
+ if (!values) {
+ g_type_class_unref(eclass);
+ return NULL;
+ }
+
+ if (!PyTuple_Check(values) || PyTuple_Size(values) != eclass->n_values) {
+ PyErr_SetString(PyExc_TypeError, "__enum_values__ badly formed");
+ Py_DECREF(values);
+ g_type_class_unref(eclass);
+ return NULL;
+ }
+
+ g_type_class_unref(eclass);
+
+ ret = PyTuple_GetItem(values, value);
+ Py_INCREF(ret);
+ Py_DECREF(values);
+ return ret;
+}
+
+PyObject*
+pyg_enum_from_gtype (GType gtype, int value)
+{
+ PyObject *pyclass, *values, *retval;
+
+ g_return_val_if_fail(gtype != G_TYPE_INVALID, NULL);
+
+ pyclass = (PyObject*)g_type_get_qdata(gtype, pygenum_class_key);
+ g_assert(pyclass != NULL);
+
+ values = PyDict_GetItemString(((PyTypeObject *)pyclass)->tp_dict,
+ "__enum_values__");
+ retval = PyTuple_GetItem(values, value);
+ Py_INCREF(retval);
+
+ return retval;
+}
+
+PyObject *
+pyg_enum_add (PyObject * module,
+ const char * typename,
+ const char * strip_prefix,
+ GType gtype)
+{
+ PyObject *instance_dict, *stub, *values;
+ GEnumClass *eclass;
+ int i;
+
+ g_return_val_if_fail(module != NULL, NULL);
+ g_return_val_if_fail(typename != NULL, NULL);
+ g_return_val_if_fail(g_type_is_a(gtype, G_TYPE_ENUM), NULL);
+
+ instance_dict = PyDict_New();
+ stub = PyObject_CallFunction((PyObject *)&PyType_Type, "s(O)O",
+ typename, (PyObject *)&PyGEnum_Type,
+ instance_dict);
+ Py_DECREF(instance_dict);
+ if (!stub) {
+ PyErr_SetString(PyExc_RuntimeError, "can't create const");
+ return NULL;
+ }
+
+ PyDict_SetItemString(((PyTypeObject *)stub)->tp_dict,
+ "__module__",
+ PyString_FromString(PyModule_GetName(module)));
+
+ if (!pygenum_class_key)
+ pygenum_class_key = g_quark_from_static_string(pygenum_class_id);
+
+ g_type_set_qdata(gtype, pygenum_class_key, stub);
+
+ /* Add it to the module name space */
+ PyModule_AddObject(module, (char*)typename, stub);
+ Py_INCREF(stub);
+
+ /* Register enum values */
+ eclass = G_ENUM_CLASS(g_type_class_ref(gtype));
+
+ values = PyTuple_New(eclass->n_values);
+ for (i = 0; i < eclass->n_values; i++) {
+ PyObject *item;
+
+ item = ((PyTypeObject *)stub)->tp_alloc((PyTypeObject *)stub, 0);
+ ((PyIntObject*)item)->ob_ival = eclass->values[i].value;
+ ((PyGEnum*)item)->gtype = gtype;
+
+ PyTuple_SetItem(values, i, item);
+
+ PyModule_AddObject(module,
+ pyg_constant_strip_prefix(eclass->values[i].value_name,
+ strip_prefix),
+ item);
+ Py_INCREF(item);
+ }
+
+ PyDict_SetItemString(((PyTypeObject *)stub)->tp_dict,
+ "__enum_values__", values);
+ Py_DECREF(values);
+
+ g_type_class_unref(eclass);
+
+ return stub;
+}
+
+PyTypeObject PyGEnum_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "gobject.GEnum",
+ sizeof(PyGEnum),
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ (cmpfunc)pyg_enum_compare, /* tp_compare */
+ (reprfunc)pyg_enum_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ (reprfunc)pyg_enum_repr, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &PyInt_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ pyg_enum_new, /* tp_new */
+};
+
diff --git a/gobject/pygenum.h b/gobject/pygenum.h
new file mode 100644
index 00000000..cfa9a928
--- /dev/null
+++ b/gobject/pygenum.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * pygtk- Python bindings for the GTK toolkit.
+ * Copyright (C) 1998-2003 James Henstridge
+ * Copyright (C) 2004 Johan Dahlin
+ *
+ * pygenum.c: GEnum and GFlag wrappers
+ *
+ * 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.1 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
+ */
+
+#ifndef __PYGENUM_H__
+#define __PYGENUM_H__
+
+#include <Python.h>
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define PyGEnum_Check(x) (g_type_is_a(((PyGFlags*)x)->gtype, G_TYPE_ENUM))
+
+typedef struct {
+ PyIntObject parent;
+ GType gtype;
+} PyGEnum;
+
+PyTypeObject PyGEnum_Type;
+
+PyObject * pyg_enum_add (PyObject * module,
+ const char * typename,
+ const char * strip_prefix,
+ GType gtype);
+PyObject * pyg_enum_from_gtype (GType gtype,
+ int value);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __PYGENUM_H__ */
diff --git a/gobject/pygflags.c b/gobject/pygflags.c
new file mode 100644
index 00000000..2c37cc1e
--- /dev/null
+++ b/gobject/pygflags.c
@@ -0,0 +1,367 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * pygtk- Python bindings for the GTK toolkit.
+ * Copyright (C) 1998-2003 James Henstridge
+ * Copyright (C) 2004 Johan Dahlin
+ *
+ * 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.1 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
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "pygobject-private.h"
+#include "pygflags.h"
+
+static const gchar *pygflags_class_id = "PyGFlags::class";
+static GQuark pygflags_class_key = 0;
+
+#define GET_INT_VALUE(x) (((PyIntObject*)x)->ob_ival)
+static int
+pyg_flags_compare(PyGFlags *self, PyObject *other)
+{
+ if (!PyInt_CheckExact(other) && ((PyGFlags*)other)->gtype != self->gtype) {
+ PyErr_Warn(PyExc_Warning, "comparing different flags types");
+ return -1;
+ }
+
+ if (GET_INT_VALUE(self) == GET_INT_VALUE(other))
+ return 0;
+ else if (GET_INT_VALUE(self) > GET_INT_VALUE(other))
+ return -1;
+ else
+ return 1;
+}
+
+static char *
+generate_repr(GType gtype, int value)
+{
+ GFlagsClass *flags_class;
+ char *retval = NULL, *tmp;
+ int i;
+
+ flags_class = g_type_class_ref(gtype);
+ g_assert(G_IS_FLAGS_CLASS(flags_class));
+
+ for (i = 0; i < flags_class->n_values; i++) {
+ if ((value & flags_class->values[i].value) == flags_class->values[i].value) {
+ if (retval) {
+ tmp = g_strdup_printf("%s | %s", retval, flags_class->values[i].value_name);
+ g_free(retval);
+ retval = tmp;
+ } else {
+ retval = g_strdup_printf("%s", flags_class->values[i].value_name);
+ }
+ }
+ }
+
+ g_type_class_unref(flags_class);
+
+ return retval;
+}
+
+static PyObject *
+pyg_flags_repr(PyGFlags *self)
+{
+ char *tmp, *retval;
+ PyObject *pyretval;
+
+ tmp = generate_repr(self->gtype,
+ self->parent.ob_ival);
+
+ retval = g_strdup_printf("<flag %s of type %s>", tmp,
+ g_type_name(self->gtype));
+ g_free(tmp);
+
+ pyretval = PyString_FromString(retval);
+ g_free(retval);
+
+ return pyretval;
+}
+
+static PyObject *
+pyg_flags_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "value", NULL };
+ long value;
+ PyObject *pytc, *values, *ret;
+ GType gtype;
+ GFlagsClass *eclass;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "l", kwlist, &value))
+ return NULL;
+
+ pytc = PyObject_GetAttrString((PyObject *)type, "__gtype__");
+ if (!pytc)
+ return NULL;
+
+ if (!PyObject_TypeCheck(pytc, &PyGFlags_Type)) {
+ Py_DECREF(pytc);
+ PyErr_SetString(PyExc_TypeError,
+ "__gtype__ attribute not a typecode");
+ return NULL;
+ }
+
+ gtype = pyg_type_from_object(pytc);
+ Py_DECREF(pytc);
+
+ eclass = G_FLAGS_CLASS(g_type_class_ref(gtype));
+
+ if (value < 0 || value > eclass->n_values) {
+ PyErr_SetString(PyExc_ValueError, "value out of range");
+ g_type_class_unref(eclass);
+ return NULL;
+ }
+
+ values = PyObject_GetAttrString((PyObject *)type, "__flags_values__");
+ if (!values) {
+ g_type_class_unref(eclass);
+ return NULL;
+ }
+
+ if (!PyTuple_Check(values) || PyTuple_Size(values) != eclass->n_values) {
+ PyErr_SetString(PyExc_TypeError, "__flags_values__ badly formed");
+ Py_DECREF(values);
+ g_type_class_unref(eclass);
+ return NULL;
+ }
+
+ g_type_class_unref(eclass);
+
+ ret = PyTuple_GetItem(values, value);
+ Py_INCREF(ret);
+ Py_DECREF(values);
+ return ret;
+}
+
+PyObject*
+pyg_flags_from_gtype (GType gtype, int value)
+{
+ PyObject *pyclass, *values, *retval;
+
+ g_return_val_if_fail(gtype != G_TYPE_INVALID, NULL);
+
+ pyclass = (PyObject*)g_type_get_qdata(gtype, pygflags_class_key);
+ g_assert(pyclass != NULL);
+
+ values = PyDict_GetItemString(((PyTypeObject *)pyclass)->tp_dict,
+ "__flags_values__");
+ retval = PyTuple_GetItem(values, value);
+ if (!retval) {
+ PyErr_Clear();
+
+ retval = ((PyTypeObject *)pyclass)->tp_alloc((PyTypeObject *)pyclass, 0);
+ g_assert(retval != NULL);
+
+ ((PyIntObject*)retval)->ob_ival = value;
+ ((PyGFlags*)retval)->gtype = gtype;
+ }
+
+ Py_INCREF(retval);
+ return retval;
+}
+
+PyObject *
+pyg_flags_add (PyObject * module,
+ const char * typename,
+ const char * strip_prefix,
+ GType gtype)
+{
+ PyObject *instance_dict, *stub, *values;
+ GFlagsClass *eclass;
+ int i;
+
+ g_return_val_if_fail(module != NULL, NULL);
+ g_return_val_if_fail(typename != NULL, NULL);
+ g_return_val_if_fail(g_type_is_a(gtype, G_TYPE_FLAGS), NULL);
+
+ instance_dict = PyDict_New();
+ stub = PyObject_CallFunction((PyObject *)&PyType_Type, "s(O)O",
+ typename, (PyObject *)&PyGFlags_Type,
+ instance_dict);
+ Py_DECREF(instance_dict);
+ if (!stub) {
+ PyErr_SetString(PyExc_RuntimeError, "can't create const");
+ return NULL;
+ }
+
+ PyDict_SetItemString(((PyTypeObject *)stub)->tp_dict,
+ "__module__",
+ PyString_FromString(PyModule_GetName(module)));
+
+ /* Add it to the module name space */
+ PyModule_AddObject(module, (char*)typename, stub);
+ Py_INCREF(stub);
+
+ if (!pygflags_class_key)
+ pygflags_class_key = g_quark_from_static_string(pygflags_class_id);
+
+ g_type_set_qdata(gtype, pygflags_class_key, stub);
+
+ /* Register flag values */
+ eclass = G_FLAGS_CLASS(g_type_class_ref(gtype));
+
+ values = PyTuple_New(eclass->n_values);
+ for (i = 0; i < eclass->n_values; i++) {
+ PyObject *item;
+
+ item = ((PyTypeObject *)stub)->tp_alloc((PyTypeObject *)stub, 0);
+ ((PyIntObject*)item)->ob_ival = eclass->values[i].value;
+ ((PyGFlags*)item)->gtype = gtype;
+
+ PyTuple_SetItem(values, i, item);
+
+ PyModule_AddObject(module,
+ pyg_constant_strip_prefix(eclass->values[i].value_name,
+ strip_prefix),
+ item);
+ Py_INCREF(item);
+ }
+
+ PyDict_SetItemString(((PyTypeObject *)stub)->tp_dict,
+ "__flags_values__", values);
+ Py_DECREF(values);
+
+ g_type_class_unref(eclass);
+
+ return stub;
+}
+
+static PyObject *
+pyg_flags_and(PyGFlags *a, PyGFlags *b)
+{
+ if (!PyGFlags_Check(a) || !PyGFlags_Check(b))
+ return PyInt_Type.tp_as_number->nb_and((PyObject*)a,
+ (PyObject*)b);
+
+ return pyg_flags_from_gtype(a->gtype,
+ GET_INT_VALUE(a) & GET_INT_VALUE(b));
+}
+
+static PyObject *
+pyg_flags_or(PyGFlags *a, PyGFlags *b)
+{
+ if (!PyGFlags_Check(a) || !PyGFlags_Check(b))
+ return PyInt_Type.tp_as_number->nb_or((PyObject*)a,
+ (PyObject*)b);
+
+ return pyg_flags_from_gtype(a->gtype, GET_INT_VALUE(a) | GET_INT_VALUE(b));
+}
+
+static PyObject *
+pyg_flags_xor(PyGFlags *a, PyGFlags *b)
+{
+ if (!PyGFlags_Check(a) || !PyGFlags_Check(b))
+ return PyInt_Type.tp_as_number->nb_xor((PyObject*)a,
+ (PyObject*)b);
+
+ return pyg_flags_from_gtype(a->gtype,
+ GET_INT_VALUE(a) ^ GET_INT_VALUE(b));
+
+}
+
+static PyObject *
+pyg_flags_warn (PyObject *self, PyObject *args)
+{
+ if (PyErr_Warn(PyExc_Warning, "unsupported arithmetic operation for flags type"))
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyNumberMethods pyg_flags_as_number = {
+ (binaryfunc)pyg_flags_warn, /* nb_add */
+ (binaryfunc)pyg_flags_warn, /* nb_subtract */
+ (binaryfunc)pyg_flags_warn, /* nb_multiply */
+ (binaryfunc)pyg_flags_warn, /* nb_divide */
+ (binaryfunc)pyg_flags_warn, /* nb_remainder */
+ (binaryfunc)pyg_flags_warn, /* nb_divmod */
+ (ternaryfunc)pyg_flags_warn, /* nb_power */
+ 0, /* nb_negative */
+ 0, /* nb_positive */
+ 0, /* nb_absolute */
+ 0, /* nb_nonzero */
+ 0, /* nb_invert */
+ 0, /* nb_lshift */
+ 0, /* nb_rshift */
+ (binaryfunc)pyg_flags_and, /* nb_and */
+ (binaryfunc)pyg_flags_xor, /* nb_xor */
+ (binaryfunc)pyg_flags_or, /* nb_or */
+ 0, /* nb_coerce */
+ 0, /* nb_int */
+ 0, /* nb_long */
+ 0, /* nb_float */
+ 0, /* nb_oct */
+ 0, /* nb_hex */
+ 0, /* nb_inplace_add */
+ 0, /* nb_inplace_subtract */
+ 0, /* nb_inplace_multiply */
+ 0, /* nb_inplace_divide */
+ 0, /* nb_inplace_remainder */
+ 0, /* nb_inplace_power */
+ 0, /* nb_inplace_lshift */
+ 0, /* nb_inplace_rshift */
+ 0, /* nb_inplace_and */
+ 0, /* nb_inplace_xor */
+ 0, /* nb_inplace_or */
+ 0, /* nb_floor_divide */
+ 0, /* nb_true_divide */
+ 0, /* nb_inplace_floor_divide */
+ 0, /* nb_inplace_true_divide */
+};
+
+PyTypeObject PyGFlags_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "gobject.GFlags",
+ sizeof(PyGFlags),
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ (cmpfunc)pyg_flags_compare, /* tp_compare */
+ (reprfunc)pyg_flags_repr, /* tp_repr */
+ &pyg_flags_as_number, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ (reprfunc)pyg_flags_repr, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &PyInt_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ pyg_flags_new, /* tp_new */
+};
diff --git a/gobject/pygflags.h b/gobject/pygflags.h
new file mode 100644
index 00000000..6bf93cd2
--- /dev/null
+++ b/gobject/pygflags.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * pygtk- Python bindings for the GTK toolkit.
+ * Copyright (C) 1998-2003 James Henstridge
+ * Copyright (C) 2004 Johan Dahlin
+ *
+ * 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.1 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
+ */
+
+#ifndef __PYGFLAGS_H__
+#define __PYGFLAGS_H__
+
+#include <Python.h>
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct {
+ PyIntObject parent;
+ GType gtype;
+} PyGFlags;
+
+PyTypeObject PyGFlags_Type;
+
+#define PyGFlags_Check(x) (g_type_is_a(((PyGFlags*)x)->gtype, G_TYPE_FLAGS))
+
+PyObject * pyg_flags_add (PyObject * module,
+ const char * typename,
+ const char * strip_prefix,
+ GType gtype);
+PyObject * pyg_flags_from_gtype (GType gtype,
+ int value);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __PYGFLAGS_H__ */
diff --git a/gobject/pygobject-private.h b/gobject/pygobject-private.h
index 38eff227..da340c79 100644
--- a/gobject/pygobject-private.h
+++ b/gobject/pygobject-private.h
@@ -8,7 +8,6 @@
#define _INSIDE_PYGOBJECT_
#include "pygobject.h"
-
/* from gobjectmodule.c */
extern struct _PyGObject_Functions pygobject_api_functions;
#define pyg_block_threads() G_STMT_START { \
@@ -108,4 +107,6 @@ PyObject * pyg_pointer_new (GType pointer_type, gpointer pointer);
extern PyTypeObject PyGParamSpec_Type;
PyObject *pyg_param_spec_new (GParamSpec *pspec);
+extern char * pyg_constant_strip_prefix(gchar *name, const gchar *strip_prefix);
+
#endif
diff --git a/gobject/pygobject.h b/gobject/pygobject.h
index 594e2850..9292cec2 100644
--- a/gobject/pygobject.h
+++ b/gobject/pygobject.h
@@ -29,15 +29,15 @@ typedef struct {
gboolean free_on_dealloc;
} PyGBoxed;
+#define pyg_boxed_get(v,t) ((t *)((PyGBoxed *)(v))->boxed)
+#define pyg_boxed_check(v,typecode) (PyObject_TypeCheck(v, &PyGBoxed_Type) && ((PyGBoxed *)(v))->gtype == typecode)
+
typedef struct {
PyObject_HEAD
gpointer pointer;
GType gtype;
} PyGPointer;
-#define pyg_boxed_get(v,t) ((t *)((PyGBoxed *)(v))->boxed)
-#define pyg_boxed_check(v,typecode) (PyObject_TypeCheck(v, &PyGBoxed_Type) && ((PyGBoxed *)(v))->gtype == typecode)
-
#define pyg_pointer_get(v,t) ((t *)((PyGPointer *)(v))->pointer)
#define pyg_pointer_check(v,typecode) (PyObject_TypeCheck(v, &PyGPointer_Type) && ((PyGPointer *)(v))->gtype == typecode)
@@ -117,13 +117,25 @@ struct _PyGObject_Functions {
GParameter *params,
guint *nparams,
PyObject **py_args);
- PyObject* (* param_gvalue_as_pyobject) (const GValue* gvalue,
+ PyObject *(* param_gvalue_as_pyobject) (const GValue* gvalue,
gboolean copy_boxed,
const GParamSpec* pspec);
int (* gvalue_from_param_pyobject) (GValue* value,
PyObject* py_obj,
const GParamSpec* pspec);
-
+ PyTypeObject *enum_type;
+ PyObject *(*enum_add)(PyObject *module,
+ const char *typename,
+ const char *strip_prefix,
+ GType gtype);
+ PyObject* (*enum_from_gtype)(GType gtype, int value);
+
+ PyTypeObject *flags_type;
+ PyObject *(*flags_add)(PyObject *module,
+ const char *typename,
+ const char *strip_prefix,
+ GType gtype);
+ PyObject* (*flags_from_gtype)(GType gtype, int value);
};
#ifndef _INSIDE_PYGOBJECT_
@@ -168,6 +180,13 @@ struct _PyGObject_Functions *_PyGObject_API;
#define pyg_parse_constructor_args (_PyGObject_API->parse_constructor_args)
#define pyg_param_gvalue_from_pyobject (_PyGObject_API->value_from_pyobject)
#define pyg_param_gvalue_as_pyobject (_PyGObject_API->value_as_pyobject)
+#define PyGEnum_Type (*_PyGObject_API->enum_type)
+#define pyg_enum_add (_PyGObject_API->enum_add)
+#define pyg_enum_from_gtype (_PyGObject_API->enum_from_gtype)
+#define PyGFlags_Type (*_PyGObject_API->flags_type)
+#define pyg_flags_add (_PyGObject_API->flags_add)
+#define pyg_flags_from_gtype (_PyGObject_API->flags_from_gtype)
+
#define pyg_block_threads() G_STMT_START { \
if (_PyGObject_API->block_threads != NULL) \
(* _PyGObject_API->block_threads)(); \
diff --git a/gobject/pygtype.c b/gobject/pygtype.c
index e28c84c1..eff5e0df 100644
--- a/gobject/pygtype.c
+++ b/gobject/pygtype.c
@@ -22,6 +22,9 @@
#include "pygobject-private.h"
+#include "pygenum.h"
+#include "pygflags.h"
+
/* -------------- __gtype__ objects ---------------------------- */
typedef struct {
@@ -652,9 +655,9 @@ pyg_value_as_pyobject(const GValue *value, gboolean copy_boxed)
return PyLong_FromUnsignedLongLong(val);
}
case G_TYPE_ENUM:
- return PyInt_FromLong(g_value_get_enum(value));
+ return pyg_enum_from_gtype(G_VALUE_TYPE(value), g_value_get_enum(value));
case G_TYPE_FLAGS:
- return PyInt_FromLong(g_value_get_flags(value));
+ return pyg_flags_from_gtype(G_VALUE_TYPE(value), g_value_get_flags(value));
case G_TYPE_FLOAT:
return PyFloat_FromDouble(g_value_get_float(value));
case G_TYPE_DOUBLE:
diff --git a/gobjectmodule.c b/gobjectmodule.c
index ec9fcf49..6159ca90 100644
--- a/gobjectmodule.c
+++ b/gobjectmodule.c
@@ -26,6 +26,9 @@
#include "pygobject-private.h"
+#include "pygenum.h"
+#include "pygflags.h"
+
static PyObject *gerror_exc = NULL;
static const gchar *pyginterface_type_id = "PyGInterface::type";
GQuark pyginterface_type_key = 0;
@@ -1880,7 +1883,7 @@ static PyMethodDef pygobject_functions[] = {
*
* Returns: the stripped constant name.
*/
-static char *
+char *
pyg_constant_strip_prefix(gchar *name, const gchar *strip_prefix)
{
gint prefix_len;
@@ -2158,12 +2161,35 @@ struct _PyGObject_Functions pygobject_api_functions = {
&PyGParamSpec_Type,
pyg_param_spec_new,
pyg_param_spec_from_object,
+
pyg_pyobj_to_unichar_conv,
pyg_parse_constructor_args,
pyg_param_gvalue_as_pyobject,
- pyg_param_gvalue_from_pyobject
+ pyg_param_gvalue_from_pyobject,
+
+ &PyGEnum_Type,
+ pyg_enum_add,
+ pyg_enum_from_gtype,
+
+ &PyGFlags_Type,
+ pyg_flags_add,
+ pyg_flags_from_gtype
};
+#define REGISTER_TYPE(d, type, name) \
+ type.ob_type = &PyType_Type; \
+ type.tp_alloc = PyType_GenericAlloc; \
+ type.tp_new = PyType_GenericNew; \
+ if (PyType_Ready(&type)) \
+ return; \
+ PyDict_SetItemString(d, name, (PyObject *)&type);
+
+#define REGISTER_GTYPE(d, type, name, gtype) \
+ REGISTER_TYPE(d, type, name); \
+ PyDict_SetItemString(type.tp_dict, "__gtype__", \
+ o=pyg_type_wrapper_new(gtype)); \
+ Py_DECREF(o);
+
DL_EXPORT(void)
initgobject(void)
{
@@ -2188,7 +2214,7 @@ initgobject(void)
gerror_exc = PyErr_NewException("gobject.GError", PyExc_RuntimeError,NULL);
PyDict_SetItemString(d, "GError", gerror_exc);
-
+
PyGObject_Type.tp_alloc = PyType_GenericAlloc;
PyGObject_Type.tp_new = PyType_GenericNew;
pygobject_register_class(d, "GObject", G_TYPE_OBJECT,
@@ -2196,55 +2222,23 @@ initgobject(void)
PyDict_SetItemString(PyGObject_Type.tp_dict, "__gdoc__",
pyg_object_descr_doc_get());
- PyGInterface_Type.ob_type = &PyType_Type;
- PyGInterface_Type.tp_alloc = PyType_GenericAlloc;
- PyGInterface_Type.tp_new = PyType_GenericNew;
- if (PyType_Ready(&PyGInterface_Type))
- return;
- PyDict_SetItemString(d, "GInterface", (PyObject *)&PyGInterface_Type);
- PyDict_SetItemString(PyGInterface_Type.tp_dict, "__gtype__",
- o=pyg_type_wrapper_new(G_TYPE_INTERFACE));
- Py_DECREF(o);
+ REGISTER_GTYPE(d, PyGInterface_Type, "GInterface", G_TYPE_INTERFACE);
PyDict_SetItemString(PyGInterface_Type.tp_dict, "__doc__",
pyg_object_descr_doc_get());
PyDict_SetItemString(PyGInterface_Type.tp_dict, "__gdoc__",
pyg_object_descr_doc_get());
pyginterface_type_key = g_quark_from_static_string(pyginterface_type_id);
- PyGBoxed_Type.ob_type = &PyType_Type;
- PyGBoxed_Type.tp_alloc = PyType_GenericAlloc;
- PyGBoxed_Type.tp_new = PyType_GenericNew;
- if (PyType_Ready(&PyGBoxed_Type))
- return;
- PyDict_SetItemString(d, "GBoxed", (PyObject *)&PyGBoxed_Type);
- PyDict_SetItemString(PyGBoxed_Type.tp_dict, "__gtype__",
- o=pyg_type_wrapper_new(G_TYPE_BOXED));
- Py_DECREF(o);
+ REGISTER_GTYPE(d, PyGBoxed_Type, "GBoxed", G_TYPE_BOXED);
+ REGISTER_GTYPE(d, PyGPointer_Type, "GPointer", G_TYPE_POINTER);
+ REGISTER_GTYPE(d, PyGEnum_Type, "GEnum", G_TYPE_ENUM);
+ PyGEnum_Type.tp_base = &PyInt_Type;
+ REGISTER_GTYPE(d, PyGFlags_Type, "GFlags", G_TYPE_FLAGS);
+ PyGFlags_Type.tp_base = &PyInt_Type;
- PyGMainLoop_Type.ob_type = &PyType_Type;
- PyGMainLoop_Type.tp_alloc = PyType_GenericAlloc;
- PyGMainLoop_Type.tp_new = PyType_GenericNew;
- if (PyType_Ready(&PyGMainLoop_Type))
- return;
- PyDict_SetItemString(d, "MainLoop", (PyObject *)&PyGMainLoop_Type);
+ REGISTER_TYPE(d, PyGMainLoop_Type, "GMainLoop");
+ REGISTER_TYPE(d, PyGMainContext_Type, "GMainContext");
- PyGMainContext_Type.ob_type = &PyType_Type;
- PyGMainContext_Type.tp_alloc = PyType_GenericAlloc;
- PyGMainContext_Type.tp_new = PyType_GenericNew;
- if (PyType_Ready(&PyGMainContext_Type))
- return;
- PyDict_SetItemString(d, "MainContext", (PyObject *)&PyGMainContext_Type);
-
- PyGPointer_Type.ob_type = &PyType_Type;
- PyGPointer_Type.tp_alloc = PyType_GenericAlloc;
- PyGPointer_Type.tp_new = PyType_GenericNew;
- if (PyType_Ready(&PyGPointer_Type))
- return;
- PyDict_SetItemString(d, "GPointer", (PyObject *)&PyGPointer_Type);
- PyDict_SetItemString(PyGPointer_Type.tp_dict, "__gtype__",
- o=pyg_type_wrapper_new(G_TYPE_POINTER));
- Py_DECREF(o);
-
/* glib version */
tuple = Py_BuildValue ("(iii)", glib_major_version, glib_minor_version,
glib_micro_version);
@@ -2281,7 +2275,7 @@ initgobject(void)
PyModule_AddIntConstant(m, "PRIORITY_HIGH", G_PRIORITY_HIGH);
PyModule_AddIntConstant(m, "PRIORITY_DEFAULT", G_PRIORITY_DEFAULT);
PyModule_AddIntConstant(m, "PRIORITY_HIGH_IDLE", G_PRIORITY_HIGH_IDLE);
- PyModule_AddIntConstant(m,"PRIORITY_DEFAULT_IDLE",G_PRIORITY_DEFAULT_IDLE);
+ PyModule_AddIntConstant(m, "PRIORITY_DEFAULT_IDLE",G_PRIORITY_DEFAULT_IDLE);
PyModule_AddIntConstant(m, "PRIORITY_LOW", G_PRIORITY_LOW);
PyModule_AddIntConstant(m, "IO_IN", G_IO_IN);
diff --git a/gtk/__init__.py b/gtk/__init__.py
index a504ebcf..51090433 100644
--- a/gtk/__init__.py
+++ b/gtk/__init__.py
@@ -58,6 +58,8 @@ gdk.INPUT_READ = _gobject.IO_IN | _gobject.IO_HUP | _gobject.IO_ERR
gdk.INPUT_WRITE = _gobject.IO_OUT | _gobject.IO_HUP
gdk.INPUT_EXCEPTION = _gobject.IO_PRI
+del _gobject
+
# Warnings
class _Deprecated:
from warnings import warn
diff --git a/gtk/gdk.override b/gtk/gdk.override
index 83652915..7684f17d 100644
--- a/gtk/gdk.override
+++ b/gtk/gdk.override
@@ -1261,7 +1261,7 @@ _wrap_gdk_event_tp_setattr(PyObject *self, char *attr, PyObject *value)
event->scroll.state = PyInt_AsLong(value);
return 0;
} else if (!strcmp(attr, "direction")) {
- INT_CHECK();
+ INT_CHECK(); /* XXX: ENUM */
event->scroll.direction = PyInt_AsLong(value);
return 0;
} else if (!strcmp(attr, "device")) {
@@ -1449,13 +1449,13 @@ _wrap_gdk_event_tp_getattr(PyObject *self, char *attr)
if (!strcmp(attr, "y_root"))
return PyFloat_FromDouble(event->crossing.y_root);
if (!strcmp(attr, "mode"))
- return PyInt_FromLong(event->crossing.mode);
+ return pyg_enum_from_gtype(GDK_TYPE_CROSSING_MODE, event->crossing.mode);
if (!strcmp(attr, "detail"))
return PyInt_FromLong(event->crossing.detail);
if (!strcmp(attr, "focus"))
return PyInt_FromLong(event->crossing.focus);
if (!strcmp(attr, "state"))
- return PyInt_FromLong(event->crossing.state);
+ return pyg_enum_from_gtype(GDK_TYPE_NOTIFY_TYPE, event->crossing.mode);
break;
case GDK_FOCUS_CHANGE: /*GdkEventFocus focus_change*/
if (!strcmp(attr, "__members__"))
@@ -1491,7 +1491,7 @@ _wrap_gdk_event_tp_getattr(PyObject *self, char *attr)
if (!strcmp(attr, "time"))
return PyInt_FromLong(event->property.time);
if (!strcmp(attr, "state"))
- return PyInt_FromLong(event->property.state);
+ return pyg_enum_from_gtype(GDK_TYPE_PROPERTY_STATE, event->property.state);
break;
case GDK_SELECTION_CLEAR: /*GdkEventSelection selection*/
case GDK_SELECTION_REQUEST: /*GdkEventSelection selection*/
@@ -1560,7 +1560,7 @@ _wrap_gdk_event_tp_getattr(PyObject *self, char *attr)
"type", "window", "send_event",
"state");
if (!strcmp(attr, "state"))
- return PyInt_FromLong(event->visibility.state);
+ return pyg_enum_from_gtype(GDK_TYPE_VISIBILITY_STATE, event->visibility.state);
break;
case GDK_NO_EXPOSE: /*GdkEventNoExpose no_expose*/
break;
@@ -1579,7 +1579,7 @@ _wrap_gdk_event_tp_getattr(PyObject *self, char *attr)
if (!strcmp(attr, "state"))
return PyInt_FromLong(event->scroll.state);
if (!strcmp(attr, "direction"))
- return PyInt_FromLong(event->scroll.direction);
+ return pyg_enum_from_gtype(GDK_TYPE_SCROLL_DIRECTION, event->scroll.direction);
if (!strcmp(attr, "device"))
return pygobject_new((GObject *)event->scroll.device);
if (!strcmp(attr, "x_root"))
@@ -1603,7 +1603,7 @@ _wrap_gdk_event_tp_getattr(PyObject *self, char *attr)
"type", "window", "send_event",
"action", "name");
if (!strcmp(attr, "action"))
- return PyInt_FromLong(event->setting.action);
+ return pyg_enum_from_gtype(GDK_TYPE_SETTING_ACTION, event->setting.action);
if (!strcmp(attr, "name"))
return PyString_FromString(event->setting.name);
break;
@@ -1612,7 +1612,7 @@ _wrap_gdk_event_tp_getattr(PyObject *self, char *attr)
}
if (!strcmp(attr, "type"))
- return PyInt_FromLong(event->type);
+ return pyg_enum_from_gtype(GDK_TYPE_EVENT_TYPE, event->type);
if (!strcmp(attr, "window"))
return pygobject_new((GObject *)event->any.window);
if (!strcmp(attr, "send_event"))
@@ -2041,7 +2041,7 @@ _wrap_gdk_gc_tp_getattr(PyGObject *self, char *attr)
if (!strcmp(attr, "clip_mask"))
return pygobject_new((GObject *)gc.clip_mask);
if (!strcmp(attr, "subwindow_mode"))
- return PyInt_FromLong(gc.subwindow_mode);
+ return pyg_enum_from_gtype(GDK_TYPE_SUBWINDOW_MODE, gc.subwindow_mode);
if (!strcmp(attr, "ts_x_origin"))
return PyInt_FromLong(gc.ts_x_origin);
if (!strcmp(attr, "ts_y_origin"))
@@ -2055,11 +2055,11 @@ _wrap_gdk_gc_tp_getattr(PyGObject *self, char *attr)
if (!strcmp(attr, "line_width"))
return PyInt_FromLong(gc.line_width);
if (!strcmp(attr, "line_style"))
- return PyInt_FromLong(gc.line_style);
+ return pyg_enum_from_gtype(GDK_TYPE_LINE_STYLE, gc.line_style);
if (!strcmp(attr, "cap_style"))
- return PyInt_FromLong(gc.cap_style);
+ return pyg_enum_from_gtype(GDK_TYPE_CAP_STYLE, gc.cap_style);
if (!strcmp(attr, "join_style"))
- return PyInt_FromLong(gc.join_style);
+ return pyg_enum_from_gtype(GDK_TYPE_JOIN_STYLE, gc.join_style);
{
PyObject *name = PyString_FromString(attr);
@@ -3857,7 +3857,7 @@ _wrap_gdk_window_get_decorations(PyGObject *self)
gdk_window_get_decorations(GDK_WINDOW(self->obj), &decor);
- return PyInt_FromLong(decor);
+ return pyg_enum_from_gtype(GDK_TYPE_WM_DECORATION, decor);
}
%%
override gdk_window_get_toplevels noargs
diff --git a/gtk/gtk.override b/gtk/gtk.override
index d992196d..60225fcb 100644
--- a/gtk/gtk.override
+++ b/gtk/gtk.override
@@ -611,7 +611,8 @@ _wrap_gtk_box_query_child_packing(PyGObject *self, PyObject *args,
gtk_box_query_child_packing(GTK_BOX(self->obj),
child, &expand, &fill,
&padding, &pack_type);
- return Py_BuildValue("(iiii)", (int)expand, (int)fill, padding, pack_type);
+ return Py_BuildValue("(iiiO)", (int)expand, (int)fill, padding,
+ pyg_enum_from_gtype(GTK_TYPE_PACK_TYPE, pack_type));
}
%%
override gtk_combo_set_popdown_strings kwargs
@@ -2113,7 +2114,8 @@ _wrap_gtk_notebook_query_tab_label_packing(PyGObject *self, PyObject *args,
gtk_notebook_query_tab_label_packing(GTK_NOTEBOOK(self->obj),
GTK_WIDGET(child->obj),
&expand, &fill, &pack_type);
- return Py_BuildValue("(iii)", expand, fill, pack_type);
+ return Py_BuildValue("(iiO)", expand, fill,
+ pyg_enum_from_gtype(GTK_TYPE_PACK_TYPE, pack_type));
}
%%
override gtk_list_insert_items kwargs
@@ -3022,7 +3024,7 @@ _wrap_gtk_stock_lookup(PyGObject *self, PyObject *args)
return Py_BuildValue("zziiz",
item.stock_id,
item.label,
- item.modifier,
+ pyg_enum_from_gtype(GDK_TYPE_MODIFIER_TYPE, item.modifier),
item.keyval,
item.translation_domain);
}
@@ -3413,10 +3415,12 @@ _wrap_gtk_image_get_stock(PyGObject *self)
if (stock_id) {
return Py_BuildValue("(OO)",
PyString_FromString(stock_id),
- PyInt_FromLong(size));
+ pyg_enum_from_gtype(GTK_TYPE_ICON_SIZE, size));
} else {
Py_INCREF(Py_None);
- return Py_BuildValue("(OO)", Py_None, PyInt_FromLong(size));
+ return Py_BuildValue("(OO)",
+ Py_None,
+ pyg_enum_from_gtype(GTK_TYPE_ICON_SIZE, size));
}
}
%%
@@ -3435,7 +3439,7 @@ _wrap_gtk_image_get_icon_set(PyGObject *self)
}
gtk_image_get_icon_set(GTK_IMAGE(self->obj), &icon_set, &size);
return Py_BuildValue("(OO)", pygobject_new((GObject *)icon_set),
- PyInt_FromLong(size));
+ pyg_enum_from_gtype(GTK_TYPE_ICON_SIZE, size));
}
%%
override gtk_image_get noargs
@@ -3561,7 +3565,9 @@ _wrap_gtk_scrolled_window_get_policy(PyGObject *self)
gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(self->obj),
&hscrollbar_policy, &vscrollbar_policy);
- return Py_BuildValue("(ii)", hscrollbar_policy, vscrollbar_policy);
+ return Py_BuildValue("(OO)",
+ pyg_enum_from_gtype(GTK_TYPE_POLICY_TYPE, hscrollbar_policy),
+ pyg_enum_from_gtype(GTK_TYPE_POLICY_TYPE, vscrollbar_policy));
}
%%
override gtk_tooltips_data_get kwargs
@@ -3616,7 +3622,7 @@ _wrap_gtk_accelerator_parse(PyGObject *self, PyObject *args, PyObject *kwargs)
gtk_accelerator_parse((const gchar *)accel, &keyval, &modifier);
- return Py_BuildValue("ii", keyval, modifier);
+ return Py_BuildValue("iO", keyval, pyg_enum_from_gtype(GDK_TYPE_MODIFIER_TYPE, modifier));
}
%%
override gtk_accel_map_lookup_entry kwargs
@@ -3634,7 +3640,8 @@ _wrap_gtk_accel_map_lookup_entry(PyGObject *self, PyObject *args,
return NULL;
if (gtk_accel_map_lookup_entry((const gchar *)accel_path, &accel_key))
- return Py_BuildValue("ii", accel_key.accel_key, accel_key.accel_mods);
+ return Py_BuildValue("iO", accel_key.accel_key,
+ pyg_enum_from_gtype(GDK_TYPE_MODIFIER_TYPE, accel_key.accel_mods));
Py_INCREF(Py_None);
return Py_None;
diff --git a/gtk/gtktreeview.override b/gtk/gtktreeview.override
index 5aff0fd3..044c8519 100644
--- a/gtk/gtktreeview.override
+++ b/gtk/gtktreeview.override
@@ -993,7 +993,8 @@ _wrap_gtk_tree_sortable_get_sort_column_id(PyGObject *self)
/* if we don't have a sort column set, return (None, None) */
if (ret)
- return Py_BuildValue("(ii)", sort_column_id, order);
+ return Py_BuildValue("(iO)", sort_column_id,
+ pyg_enum_from_gtype(GTK_TYPE_SORT_TYPE, order));
else
return Py_BuildValue("(OO)", Py_None, Py_None);
}
@@ -2249,7 +2250,8 @@ _wrap_gtk_tree_view_get_drag_dest_row(PyGObject *self)
PyObject *py_path = pygtk_tree_path_to_pyobject(path);
gint py_pos = (gint) pos;
gtk_tree_path_free(path);
- return Py_BuildValue("(Oi)", py_path, py_pos);
+ return Py_BuildValue("(OO)", py_path,
+ pyg_enum_from_gtype(GTK_TYPE_TREE_VIEW_DROP_POSITION, py_pos));
} else {
Py_INCREF(Py_None);
return Py_None;
@@ -2311,7 +2313,8 @@ _wrap_gtk_tree_view_get_dest_row_at_pos(PyGObject *self, PyObject *args,
PyObject *py_path = pygtk_tree_path_to_pyobject(path);
gint py_pos = (gint) pos;
gtk_tree_path_free(path);
- return Py_BuildValue("(Oi)", py_path, py_pos);
+ return Py_BuildValue("(OO)", py_path,
+ pyg_enum_from_gtype(GTK_TYPE_TREE_VIEW_DROP_POSITION, py_pos));
}
Py_INCREF(Py_None);
diff --git a/pygenum.c b/pygenum.c
new file mode 100644
index 00000000..c9444f0a
--- /dev/null
+++ b/pygenum.c
@@ -0,0 +1,252 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * pygtk- Python bindings for the GTK toolkit.
+ * Copyright (C) 1998-2003 James Henstridge
+ * Copyright (C) 2004 Johan Dahlin
+ *
+ * pygenum.c: GEnum and GFlag wrappers
+ *
+ * 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.1 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
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "pygobject-private.h"
+#include "pygenum.h"
+
+static const gchar *pygenum_class_id = "PyGEnum::class";
+static GQuark pygenum_class_key = 0;
+
+#define GET_INT(x) (((PyIntObject*)x)->ob_ival)
+static int
+pyg_enum_compare(PyGEnum *self, PyObject *other)
+{
+ if (!PyInt_CheckExact(other) && ((PyGEnum*)other)->gtype != self->gtype) {
+ PyErr_Warn(PyExc_Warning, "comparing different enum types");
+ return -1;
+ }
+
+ if (GET_INT(self) == GET_INT(other))
+ return 0;
+ else if (GET_INT(self) > GET_INT(other))
+ return -1;
+ else
+ return 1;
+}
+#undef GET_INT
+
+static PyObject *
+pyg_enum_repr(PyGEnum *self)
+{
+ GEnumClass *enum_class;
+ GEnumValue *enum_value;
+ static char tmp[256];
+
+ enum_class = g_type_class_ref(self->gtype);
+ g_assert(G_IS_ENUM_CLASS(enum_class));
+
+ enum_value = g_enum_get_value(enum_class, self->parent.ob_ival);
+ g_assert(enum_value != 0);
+
+ sprintf(tmp, "<enum %s of type %s>", enum_value->value_name, g_type_name(self->gtype));
+
+ g_type_class_unref(enum_class);
+
+ return PyString_FromString(tmp);
+}
+
+static PyObject *
+pyg_enum_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "value", NULL };
+ long value;
+ PyObject *pytc, *values, *ret;
+ GType gtype;
+ GEnumClass *eclass;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "l", kwlist, &value))
+ return NULL;
+
+ pytc = PyObject_GetAttrString((PyObject *)type, "__gtype__");
+ if (!pytc)
+ return NULL;
+
+ if (!PyObject_TypeCheck(pytc, &PyGEnum_Type)) {
+ Py_DECREF(pytc);
+ PyErr_SetString(PyExc_TypeError,
+ "__gtype__ attribute not a typecode");
+ return NULL;
+ }
+
+ gtype = pyg_type_from_object(pytc);
+ Py_DECREF(pytc);
+
+ eclass = G_ENUM_CLASS(g_type_class_ref(gtype));
+
+ if (value < 0 || value > eclass->n_values) {
+ PyErr_SetString(PyExc_ValueError, "value out of range");
+ g_type_class_unref(eclass);
+ return NULL;
+ }
+
+ values = PyObject_GetAttrString((PyObject *)type, "__enum_values__");
+ if (!values) {
+ g_type_class_unref(eclass);
+ return NULL;
+ }
+
+ if (!PyTuple_Check(values) || PyTuple_Size(values) != eclass->n_values) {
+ PyErr_SetString(PyExc_TypeError, "__enum_values__ badly formed");
+ Py_DECREF(values);
+ g_type_class_unref(eclass);
+ return NULL;
+ }
+
+ g_type_class_unref(eclass);
+
+ ret = PyTuple_GetItem(values, value);
+ Py_INCREF(ret);
+ Py_DECREF(values);
+ return ret;
+}
+
+PyObject*
+pyg_enum_from_gtype (GType gtype, int value)
+{
+ PyObject *pyclass, *values, *retval;
+
+ g_return_val_if_fail(gtype != G_TYPE_INVALID, NULL);
+
+ pyclass = (PyObject*)g_type_get_qdata(gtype, pygenum_class_key);
+ g_assert(pyclass != NULL);
+
+ values = PyDict_GetItemString(((PyTypeObject *)pyclass)->tp_dict,
+ "__enum_values__");
+ retval = PyTuple_GetItem(values, value);
+ Py_INCREF(retval);
+
+ return retval;
+}
+
+PyObject *
+pyg_enum_add (PyObject * module,
+ const char * typename,
+ const char * strip_prefix,
+ GType gtype)
+{
+ PyObject *instance_dict, *stub, *values;
+ GEnumClass *eclass;
+ int i;
+
+ g_return_val_if_fail(module != NULL, NULL);
+ g_return_val_if_fail(typename != NULL, NULL);
+ g_return_val_if_fail(g_type_is_a(gtype, G_TYPE_ENUM), NULL);
+
+ instance_dict = PyDict_New();
+ stub = PyObject_CallFunction((PyObject *)&PyType_Type, "s(O)O",
+ typename, (PyObject *)&PyGEnum_Type,
+ instance_dict);
+ Py_DECREF(instance_dict);
+ if (!stub) {
+ PyErr_SetString(PyExc_RuntimeError, "can't create const");
+ return NULL;
+ }
+
+ PyDict_SetItemString(((PyTypeObject *)stub)->tp_dict,
+ "__module__",
+ PyString_FromString(PyModule_GetName(module)));
+
+ if (!pygenum_class_key)
+ pygenum_class_key = g_quark_from_static_string(pygenum_class_id);
+
+ g_type_set_qdata(gtype, pygenum_class_key, stub);
+
+ /* Add it to the module name space */
+ PyModule_AddObject(module, (char*)typename, stub);
+ Py_INCREF(stub);
+
+ /* Register enum values */
+ eclass = G_ENUM_CLASS(g_type_class_ref(gtype));
+
+ values = PyTuple_New(eclass->n_values);
+ for (i = 0; i < eclass->n_values; i++) {
+ PyObject *item;
+
+ item = ((PyTypeObject *)stub)->tp_alloc((PyTypeObject *)stub, 0);
+ ((PyIntObject*)item)->ob_ival = eclass->values[i].value;
+ ((PyGEnum*)item)->gtype = gtype;
+
+ PyTuple_SetItem(values, i, item);
+
+ PyModule_AddObject(module,
+ pyg_constant_strip_prefix(eclass->values[i].value_name,
+ strip_prefix),
+ item);
+ Py_INCREF(item);
+ }
+
+ PyDict_SetItemString(((PyTypeObject *)stub)->tp_dict,
+ "__enum_values__", values);
+ Py_DECREF(values);
+
+ g_type_class_unref(eclass);
+
+ return stub;
+}
+
+PyTypeObject PyGEnum_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "gobject.GEnum",
+ sizeof(PyGEnum),
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ (cmpfunc)pyg_enum_compare, /* tp_compare */
+ (reprfunc)pyg_enum_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ (reprfunc)pyg_enum_repr, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &PyInt_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ pyg_enum_new, /* tp_new */
+};
+
diff --git a/pygenum.h b/pygenum.h
new file mode 100644
index 00000000..cfa9a928
--- /dev/null
+++ b/pygenum.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * pygtk- Python bindings for the GTK toolkit.
+ * Copyright (C) 1998-2003 James Henstridge
+ * Copyright (C) 2004 Johan Dahlin
+ *
+ * pygenum.c: GEnum and GFlag wrappers
+ *
+ * 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.1 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
+ */
+
+#ifndef __PYGENUM_H__
+#define __PYGENUM_H__
+
+#include <Python.h>
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define PyGEnum_Check(x) (g_type_is_a(((PyGFlags*)x)->gtype, G_TYPE_ENUM))
+
+typedef struct {
+ PyIntObject parent;
+ GType gtype;
+} PyGEnum;
+
+PyTypeObject PyGEnum_Type;
+
+PyObject * pyg_enum_add (PyObject * module,
+ const char * typename,
+ const char * strip_prefix,
+ GType gtype);
+PyObject * pyg_enum_from_gtype (GType gtype,
+ int value);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __PYGENUM_H__ */
diff --git a/pygflags.c b/pygflags.c
new file mode 100644
index 00000000..2c37cc1e
--- /dev/null
+++ b/pygflags.c
@@ -0,0 +1,367 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * pygtk- Python bindings for the GTK toolkit.
+ * Copyright (C) 1998-2003 James Henstridge
+ * Copyright (C) 2004 Johan Dahlin
+ *
+ * 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.1 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
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "pygobject-private.h"
+#include "pygflags.h"
+
+static const gchar *pygflags_class_id = "PyGFlags::class";
+static GQuark pygflags_class_key = 0;
+
+#define GET_INT_VALUE(x) (((PyIntObject*)x)->ob_ival)
+static int
+pyg_flags_compare(PyGFlags *self, PyObject *other)
+{
+ if (!PyInt_CheckExact(other) && ((PyGFlags*)other)->gtype != self->gtype) {
+ PyErr_Warn(PyExc_Warning, "comparing different flags types");
+ return -1;
+ }
+
+ if (GET_INT_VALUE(self) == GET_INT_VALUE(other))
+ return 0;
+ else if (GET_INT_VALUE(self) > GET_INT_VALUE(other))
+ return -1;
+ else
+ return 1;
+}
+
+static char *
+generate_repr(GType gtype, int value)
+{
+ GFlagsClass *flags_class;
+ char *retval = NULL, *tmp;
+ int i;
+
+ flags_class = g_type_class_ref(gtype);
+ g_assert(G_IS_FLAGS_CLASS(flags_class));
+
+ for (i = 0; i < flags_class->n_values; i++) {
+ if ((value & flags_class->values[i].value) == flags_class->values[i].value) {
+ if (retval) {
+ tmp = g_strdup_printf("%s | %s", retval, flags_class->values[i].value_name);
+ g_free(retval);
+ retval = tmp;
+ } else {
+ retval = g_strdup_printf("%s", flags_class->values[i].value_name);
+ }
+ }
+ }
+
+ g_type_class_unref(flags_class);
+
+ return retval;
+}
+
+static PyObject *
+pyg_flags_repr(PyGFlags *self)
+{
+ char *tmp, *retval;
+ PyObject *pyretval;
+
+ tmp = generate_repr(self->gtype,
+ self->parent.ob_ival);
+
+ retval = g_strdup_printf("<flag %s of type %s>", tmp,
+ g_type_name(self->gtype));
+ g_free(tmp);
+
+ pyretval = PyString_FromString(retval);
+ g_free(retval);
+
+ return pyretval;
+}
+
+static PyObject *
+pyg_flags_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "value", NULL };
+ long value;
+ PyObject *pytc, *values, *ret;
+ GType gtype;
+ GFlagsClass *eclass;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "l", kwlist, &value))
+ return NULL;
+
+ pytc = PyObject_GetAttrString((PyObject *)type, "__gtype__");
+ if (!pytc)
+ return NULL;
+
+ if (!PyObject_TypeCheck(pytc, &PyGFlags_Type)) {
+ Py_DECREF(pytc);
+ PyErr_SetString(PyExc_TypeError,
+ "__gtype__ attribute not a typecode");
+ return NULL;
+ }
+
+ gtype = pyg_type_from_object(pytc);
+ Py_DECREF(pytc);
+
+ eclass = G_FLAGS_CLASS(g_type_class_ref(gtype));
+
+ if (value < 0 || value > eclass->n_values) {
+ PyErr_SetString(PyExc_ValueError, "value out of range");
+ g_type_class_unref(eclass);
+ return NULL;
+ }
+
+ values = PyObject_GetAttrString((PyObject *)type, "__flags_values__");
+ if (!values) {
+ g_type_class_unref(eclass);
+ return NULL;
+ }
+
+ if (!PyTuple_Check(values) || PyTuple_Size(values) != eclass->n_values) {
+ PyErr_SetString(PyExc_TypeError, "__flags_values__ badly formed");
+ Py_DECREF(values);
+ g_type_class_unref(eclass);
+ return NULL;
+ }
+
+ g_type_class_unref(eclass);
+
+ ret = PyTuple_GetItem(values, value);
+ Py_INCREF(ret);
+ Py_DECREF(values);
+ return ret;
+}
+
+PyObject*
+pyg_flags_from_gtype (GType gtype, int value)
+{
+ PyObject *pyclass, *values, *retval;
+
+ g_return_val_if_fail(gtype != G_TYPE_INVALID, NULL);
+
+ pyclass = (PyObject*)g_type_get_qdata(gtype, pygflags_class_key);
+ g_assert(pyclass != NULL);
+
+ values = PyDict_GetItemString(((PyTypeObject *)pyclass)->tp_dict,
+ "__flags_values__");
+ retval = PyTuple_GetItem(values, value);
+ if (!retval) {
+ PyErr_Clear();
+
+ retval = ((PyTypeObject *)pyclass)->tp_alloc((PyTypeObject *)pyclass, 0);
+ g_assert(retval != NULL);
+
+ ((PyIntObject*)retval)->ob_ival = value;
+ ((PyGFlags*)retval)->gtype = gtype;
+ }
+
+ Py_INCREF(retval);
+ return retval;
+}
+
+PyObject *
+pyg_flags_add (PyObject * module,
+ const char * typename,
+ const char * strip_prefix,
+ GType gtype)
+{
+ PyObject *instance_dict, *stub, *values;
+ GFlagsClass *eclass;
+ int i;
+
+ g_return_val_if_fail(module != NULL, NULL);
+ g_return_val_if_fail(typename != NULL, NULL);
+ g_return_val_if_fail(g_type_is_a(gtype, G_TYPE_FLAGS), NULL);
+
+ instance_dict = PyDict_New();
+ stub = PyObject_CallFunction((PyObject *)&PyType_Type, "s(O)O",
+ typename, (PyObject *)&PyGFlags_Type,
+ instance_dict);
+ Py_DECREF(instance_dict);
+ if (!stub) {
+ PyErr_SetString(PyExc_RuntimeError, "can't create const");
+ return NULL;
+ }
+
+ PyDict_SetItemString(((PyTypeObject *)stub)->tp_dict,
+ "__module__",
+ PyString_FromString(PyModule_GetName(module)));
+
+ /* Add it to the module name space */
+ PyModule_AddObject(module, (char*)typename, stub);
+ Py_INCREF(stub);
+
+ if (!pygflags_class_key)
+ pygflags_class_key = g_quark_from_static_string(pygflags_class_id);
+
+ g_type_set_qdata(gtype, pygflags_class_key, stub);
+
+ /* Register flag values */
+ eclass = G_FLAGS_CLASS(g_type_class_ref(gtype));
+
+ values = PyTuple_New(eclass->n_values);
+ for (i = 0; i < eclass->n_values; i++) {
+ PyObject *item;
+
+ item = ((PyTypeObject *)stub)->tp_alloc((PyTypeObject *)stub, 0);
+ ((PyIntObject*)item)->ob_ival = eclass->values[i].value;
+ ((PyGFlags*)item)->gtype = gtype;
+
+ PyTuple_SetItem(values, i, item);
+
+ PyModule_AddObject(module,
+ pyg_constant_strip_prefix(eclass->values[i].value_name,
+ strip_prefix),
+ item);
+ Py_INCREF(item);
+ }
+
+ PyDict_SetItemString(((PyTypeObject *)stub)->tp_dict,
+ "__flags_values__", values);
+ Py_DECREF(values);
+
+ g_type_class_unref(eclass);
+
+ return stub;
+}
+
+static PyObject *
+pyg_flags_and(PyGFlags *a, PyGFlags *b)
+{
+ if (!PyGFlags_Check(a) || !PyGFlags_Check(b))
+ return PyInt_Type.tp_as_number->nb_and((PyObject*)a,
+ (PyObject*)b);
+
+ return pyg_flags_from_gtype(a->gtype,
+ GET_INT_VALUE(a) & GET_INT_VALUE(b));
+}
+
+static PyObject *
+pyg_flags_or(PyGFlags *a, PyGFlags *b)
+{
+ if (!PyGFlags_Check(a) || !PyGFlags_Check(b))
+ return PyInt_Type.tp_as_number->nb_or((PyObject*)a,
+ (PyObject*)b);
+
+ return pyg_flags_from_gtype(a->gtype, GET_INT_VALUE(a) | GET_INT_VALUE(b));
+}
+
+static PyObject *
+pyg_flags_xor(PyGFlags *a, PyGFlags *b)
+{
+ if (!PyGFlags_Check(a) || !PyGFlags_Check(b))
+ return PyInt_Type.tp_as_number->nb_xor((PyObject*)a,
+ (PyObject*)b);
+
+ return pyg_flags_from_gtype(a->gtype,
+ GET_INT_VALUE(a) ^ GET_INT_VALUE(b));
+
+}
+
+static PyObject *
+pyg_flags_warn (PyObject *self, PyObject *args)
+{
+ if (PyErr_Warn(PyExc_Warning, "unsupported arithmetic operation for flags type"))
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyNumberMethods pyg_flags_as_number = {
+ (binaryfunc)pyg_flags_warn, /* nb_add */
+ (binaryfunc)pyg_flags_warn, /* nb_subtract */
+ (binaryfunc)pyg_flags_warn, /* nb_multiply */
+ (binaryfunc)pyg_flags_warn, /* nb_divide */
+ (binaryfunc)pyg_flags_warn, /* nb_remainder */
+ (binaryfunc)pyg_flags_warn, /* nb_divmod */
+ (ternaryfunc)pyg_flags_warn, /* nb_power */
+ 0, /* nb_negative */
+ 0, /* nb_positive */
+ 0, /* nb_absolute */
+ 0, /* nb_nonzero */
+ 0, /* nb_invert */
+ 0, /* nb_lshift */
+ 0, /* nb_rshift */
+ (binaryfunc)pyg_flags_and, /* nb_and */
+ (binaryfunc)pyg_flags_xor, /* nb_xor */
+ (binaryfunc)pyg_flags_or, /* nb_or */
+ 0, /* nb_coerce */
+ 0, /* nb_int */
+ 0, /* nb_long */
+ 0, /* nb_float */
+ 0, /* nb_oct */
+ 0, /* nb_hex */
+ 0, /* nb_inplace_add */
+ 0, /* nb_inplace_subtract */
+ 0, /* nb_inplace_multiply */
+ 0, /* nb_inplace_divide */
+ 0, /* nb_inplace_remainder */
+ 0, /* nb_inplace_power */
+ 0, /* nb_inplace_lshift */
+ 0, /* nb_inplace_rshift */
+ 0, /* nb_inplace_and */
+ 0, /* nb_inplace_xor */
+ 0, /* nb_inplace_or */
+ 0, /* nb_floor_divide */
+ 0, /* nb_true_divide */
+ 0, /* nb_inplace_floor_divide */
+ 0, /* nb_inplace_true_divide */
+};
+
+PyTypeObject PyGFlags_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "gobject.GFlags",
+ sizeof(PyGFlags),
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ (cmpfunc)pyg_flags_compare, /* tp_compare */
+ (reprfunc)pyg_flags_repr, /* tp_repr */
+ &pyg_flags_as_number, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ (reprfunc)pyg_flags_repr, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &PyInt_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ pyg_flags_new, /* tp_new */
+};
diff --git a/pygflags.h b/pygflags.h
new file mode 100644
index 00000000..6bf93cd2
--- /dev/null
+++ b/pygflags.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * pygtk- Python bindings for the GTK toolkit.
+ * Copyright (C) 1998-2003 James Henstridge
+ * Copyright (C) 2004 Johan Dahlin
+ *
+ * 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.1 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
+ */
+
+#ifndef __PYGFLAGS_H__
+#define __PYGFLAGS_H__
+
+#include <Python.h>
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct {
+ PyIntObject parent;
+ GType gtype;
+} PyGFlags;
+
+PyTypeObject PyGFlags_Type;
+
+#define PyGFlags_Check(x) (g_type_is_a(((PyGFlags*)x)->gtype, G_TYPE_FLAGS))
+
+PyObject * pyg_flags_add (PyObject * module,
+ const char * typename,
+ const char * strip_prefix,
+ GType gtype);
+PyObject * pyg_flags_from_gtype (GType gtype,
+ int value);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __PYGFLAGS_H__ */
diff --git a/pygobject-private.h b/pygobject-private.h
index 38eff227..da340c79 100644
--- a/pygobject-private.h
+++ b/pygobject-private.h
@@ -8,7 +8,6 @@
#define _INSIDE_PYGOBJECT_
#include "pygobject.h"
-
/* from gobjectmodule.c */
extern struct _PyGObject_Functions pygobject_api_functions;
#define pyg_block_threads() G_STMT_START { \
@@ -108,4 +107,6 @@ PyObject * pyg_pointer_new (GType pointer_type, gpointer pointer);
extern PyTypeObject PyGParamSpec_Type;
PyObject *pyg_param_spec_new (GParamSpec *pspec);
+extern char * pyg_constant_strip_prefix(gchar *name, const gchar *strip_prefix);
+
#endif
diff --git a/pygobject.h b/pygobject.h
index 594e2850..9292cec2 100644
--- a/pygobject.h
+++ b/pygobject.h
@@ -29,15 +29,15 @@ typedef struct {
gboolean free_on_dealloc;
} PyGBoxed;
+#define pyg_boxed_get(v,t) ((t *)((PyGBoxed *)(v))->boxed)
+#define pyg_boxed_check(v,typecode) (PyObject_TypeCheck(v, &PyGBoxed_Type) && ((PyGBoxed *)(v))->gtype == typecode)
+
typedef struct {
PyObject_HEAD
gpointer pointer;
GType gtype;
} PyGPointer;
-#define pyg_boxed_get(v,t) ((t *)((PyGBoxed *)(v))->boxed)
-#define pyg_boxed_check(v,typecode) (PyObject_TypeCheck(v, &PyGBoxed_Type) && ((PyGBoxed *)(v))->gtype == typecode)
-
#define pyg_pointer_get(v,t) ((t *)((PyGPointer *)(v))->pointer)
#define pyg_pointer_check(v,typecode) (PyObject_TypeCheck(v, &PyGPointer_Type) && ((PyGPointer *)(v))->gtype == typecode)
@@ -117,13 +117,25 @@ struct _PyGObject_Functions {
GParameter *params,
guint *nparams,
PyObject **py_args);
- PyObject* (* param_gvalue_as_pyobject) (const GValue* gvalue,
+ PyObject *(* param_gvalue_as_pyobject) (const GValue* gvalue,
gboolean copy_boxed,
const GParamSpec* pspec);
int (* gvalue_from_param_pyobject) (GValue* value,
PyObject* py_obj,
const GParamSpec* pspec);
-
+ PyTypeObject *enum_type;
+ PyObject *(*enum_add)(PyObject *module,
+ const char *typename,
+ const char *strip_prefix,
+ GType gtype);
+ PyObject* (*enum_from_gtype)(GType gtype, int value);
+
+ PyTypeObject *flags_type;
+ PyObject *(*flags_add)(PyObject *module,
+ const char *typename,
+ const char *strip_prefix,
+ GType gtype);
+ PyObject* (*flags_from_gtype)(GType gtype, int value);
};
#ifndef _INSIDE_PYGOBJECT_
@@ -168,6 +180,13 @@ struct _PyGObject_Functions *_PyGObject_API;
#define pyg_parse_constructor_args (_PyGObject_API->parse_constructor_args)
#define pyg_param_gvalue_from_pyobject (_PyGObject_API->value_from_pyobject)
#define pyg_param_gvalue_as_pyobject (_PyGObject_API->value_as_pyobject)
+#define PyGEnum_Type (*_PyGObject_API->enum_type)
+#define pyg_enum_add (_PyGObject_API->enum_add)
+#define pyg_enum_from_gtype (_PyGObject_API->enum_from_gtype)
+#define PyGFlags_Type (*_PyGObject_API->flags_type)
+#define pyg_flags_add (_PyGObject_API->flags_add)
+#define pyg_flags_from_gtype (_PyGObject_API->flags_from_gtype)
+
#define pyg_block_threads() G_STMT_START { \
if (_PyGObject_API->block_threads != NULL) \
(* _PyGObject_API->block_threads)(); \
diff --git a/pygtype.c b/pygtype.c
index e28c84c1..eff5e0df 100644
--- a/pygtype.c
+++ b/pygtype.c
@@ -22,6 +22,9 @@
#include "pygobject-private.h"
+#include "pygenum.h"
+#include "pygflags.h"
+
/* -------------- __gtype__ objects ---------------------------- */
typedef struct {
@@ -652,9 +655,9 @@ pyg_value_as_pyobject(const GValue *value, gboolean copy_boxed)
return PyLong_FromUnsignedLongLong(val);
}
case G_TYPE_ENUM:
- return PyInt_FromLong(g_value_get_enum(value));
+ return pyg_enum_from_gtype(G_VALUE_TYPE(value), g_value_get_enum(value));
case G_TYPE_FLAGS:
- return PyInt_FromLong(g_value_get_flags(value));
+ return pyg_flags_from_gtype(G_VALUE_TYPE(value), g_value_get_flags(value));
case G_TYPE_FLOAT:
return PyFloat_FromDouble(g_value_get_float(value));
case G_TYPE_DOUBLE:
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 8324aeff..c592b968 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,5 +1,6 @@
tests = \
conversion.py \
+ enum.py \
signal.py
check-local:
diff --git a/tests/common.py b/tests/common.py
new file mode 100644
index 00000000..ff2eef90
--- /dev/null
+++ b/tests/common.py
@@ -0,0 +1,16 @@
+import os
+import sys
+
+# Don't insert before . (first in list)
+sys.path.insert(1, os.path.join('..'))
+
+path = os.path.abspath(os.path.join('..', 'gtk'))
+import gobject
+import atk
+import pango
+import gtk
+from gtk import gdk
+from gtk import glade
+
+import ltihooks
+ltihooks.uninstall()
diff --git a/tests/conversion.py b/tests/conversion.py
index 1fe8c22a..dece7bd9 100644
--- a/tests/conversion.py
+++ b/tests/conversion.py
@@ -2,7 +2,7 @@
import unittest
-import gtk
+from common import gtk
class Tests(unittest.TestCase):
diff --git a/tests/runtests.py b/tests/runtests.py
index f3559f54..83b6013b 100644
--- a/tests/runtests.py
+++ b/tests/runtests.py
@@ -4,7 +4,7 @@ import os
import sys
import unittest
-SKIP_FILES = ['runtests']
+SKIP_FILES = ['common', 'runtests']
dir = os.path.split(os.path.abspath(__file__))[0]
os.chdir(dir)
diff --git a/tests/signal.py b/tests/signal.py
index ce328014..65eda262 100644
--- a/tests/signal.py
+++ b/tests/signal.py
@@ -2,7 +2,7 @@
import unittest
-import gobject
+from common import gobject
class C(gobject.GObject):
__gsignals__ = { 'my_signal': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,