[dia] python: dia.Diagram actually extends dia.DiagramData



commit 0ae66a147bcca584e4be7cc600ad775c1be9741d
Author: Zander Brown <zbrown gnome org>
Date:   Thu Apr 23 00:18:41 2020 +0100

    python: dia.Diagram actually extends dia.DiagramData
    
    For now the old .data and .diagram properties are kept
    
    Use getset instead of getattr for properties
    
    Modernise type registration (as much as Python 2 allows)

 plug-ins/python/diamodule.c         | 392 ++++++++----------
 plug-ins/python/pydia-diagram.c     | 807 +++++++++++++++++++-----------------
 plug-ins/python/pydia-diagram.h     |  13 +-
 plug-ins/python/pydia-diagramdata.c | 316 +++++++-------
 plug-ins/python/pydia-layer.c       | 312 +++++++-------
 5 files changed, 964 insertions(+), 876 deletions(-)
---
diff --git a/plug-ins/python/diamodule.c b/plug-ins/python/diamodule.c
index f42027a8..c5615d01 100644
--- a/plug-ins/python/diamodule.c
+++ b/plug-ins/python/diamodule.c
@@ -361,54 +361,60 @@ PyDia_RegisterImport(PyObject *self, PyObject *args)
     return Py_None;
 }
 
+
 /*
  * This function gets called by Dia as a reaction to a menu item.
  * It needs to be registered before via Python function
  * dia.register_action (or dia.register_callback)
  */
 static ObjectChange *
-PyDia_callback_func (DiagramData *dia, const gchar *filename, guint flags, void *user_data)
+PyDia_callback_func (DiagramData *dia,
+                     const char  *filename,
+                     guint        flags,
+                     void        *user_data)
 {
-    PyObject *diaobj, *res, *arg, *func = user_data;
-    if (!func || !PyCallable_Check (func)) {
-        g_warning ("Callback called without valid callback function.");
-        return NULL;
-    }
+  PyObject *diaobj, *res, *arg, *func = user_data;
 
-    if (dia)
-        diaobj = PyDiaDiagramData_New (dia);
-    else {
-        diaobj = Py_None;
-        Py_INCREF (diaobj);
-    }
+  if (!func || !PyCallable_Check (func)) {
+    g_warning ("Callback called without valid callback function.");
+    return NULL;
+  }
 
-    Py_INCREF(func);
+  if (dia) {
+    diaobj = PyDiaDiagramData_New (dia);
+  } else {
+    diaobj = Py_None;
+    Py_INCREF (diaobj);
+  }
 
-    arg = Py_BuildValue ("(Oi)", diaobj, flags);
-    if (arg) {
-      res = PyEval_CallObject (func, arg);
-      ON_RES(res, TRUE);
-    }
-    Py_XDECREF (arg);
+  Py_INCREF (func);
 
-    Py_DECREF(func);
-    Py_XDECREF(diaobj);
+  arg = Py_BuildValue ("(Oi)", diaobj, flags);
+  if (arg) {
+    res = PyEval_CallObject (func, arg);
+    ON_RES(res, TRUE);
+  }
+  Py_XDECREF (arg);
 
-    return NULL;
+  Py_DECREF (func);
+  Py_XDECREF (diaobj);
+
+  return NULL;
 }
 
-static PyObject *
-_RegisterAction (gchar *action,
-                 gchar *desc,
-                 gchar *menupath,
-                 PyObject *func);
 
-static gchar *
-_strip_non_alphanum (gchar* in)
+static PyObject *_RegisterAction (char     *action,
+                                  char     *desc,
+                                  char     *menupath,
+                                  PyObject *func);
+
+
+static char *
+_strip_non_alphanum (char* in)
 {
   int i, o;
   int len = strlen (in);
-  gchar *out = g_new (gchar, len);
+  char *out = g_new (char, len);
 
   for (i = 0, o = 0; i < len; ++i) {
     if (g_ascii_isalnum (in[i])) {
@@ -417,108 +423,117 @@ _strip_non_alphanum (gchar* in)
     }
   }
   out[o] = '\0';
+
   return out;
 }
 
+
 static PyObject *
-PyDia_RegisterCallback(PyObject *self, PyObject *args)
+PyDia_RegisterCallback (PyObject *self, PyObject *args)
 {
-    gchar *desc;
-    gchar *menupath;
-    gchar *path;
-    PyObject *func;
-    gchar *action;
-    PyObject *ret;
-
-    if (!PyArg_ParseTuple(args, "ssO:dia.register_callback",
-                         &desc, &menupath, &func))
-       return NULL;
+  char *desc;
+  char *menupath;
+  char *path;
+  PyObject *func;
+  char *action;
+  PyObject *ret;
+
+  if (!PyArg_ParseTuple (args, "ssO:dia.register_callback",
+                         &desc, &menupath, &func)) {
+    return NULL;
+  }
 
-    /* if root node name does not match : <Display> -> /DisplayMenu */
-    if (strstr (menupath, "<Display>") == menupath)
-        path = g_strdup_printf ("/DisplayMenu%s", menupath + strlen("<Display>"));
-    else if (strstr (menupath, "<Toolbox>") == menupath)
-        path = g_strdup_printf ("/ToolboxMenu%s", menupath + strlen("<Toolbox>"));
-    else {
-        /* no need for g_warning here, we'll get one when entering into the GtkUiManager */
-       path = g_strdup (menupath);
-    }
-    action = _strip_non_alphanum (path);
+  /* if root node name does not match : <Display> -> /DisplayMenu */
+  if (strstr (menupath, "<Display>") == menupath) {
+    path = g_strdup_printf ("/DisplayMenu%s", menupath + strlen ("<Display>"));
+  } else if (strstr (menupath, "<Toolbox>") == menupath) {
+    path = g_strdup_printf ("/ToolboxMenu%s", menupath + strlen ("<Toolbox>"));
+  } else {
+    /* no need for g_warning here, we'll get one when entering into the GtkUiManager */
+    path = g_strdup (menupath);
+  }
+  action = _strip_non_alphanum (path);
 #if 1
-    if (strrchr (path, '/') - path < strlen(path))
-      *(strrchr (path, '/')) = '\0';
+  if (strrchr (path, '/') - path < strlen(path)) {
+    *(strrchr (path, '/')) = '\0';
+  }
 #endif
-    ret = _RegisterAction (action, desc, path, func);
-    g_clear_pointer (&path, g_free);
-    g_clear_pointer (&action, g_free);
+  ret = _RegisterAction (action, desc, path, func);
+  g_clear_pointer (&path, g_free);
+  g_clear_pointer (&action, g_free);
 
-    return ret;
+  return ret;
 }
 
+
 static PyObject *
 PyDia_RegisterAction (PyObject *self, PyObject *args)
 {
-    gchar *action;
-    gchar *desc;
-    gchar *menupath;
-    PyObject *func;
+  char *action;
+  char *desc;
+  char *menupath;
+  PyObject *func;
 
-    if (!PyArg_ParseTuple(args, "sssO:dia.register_action",
-                         &action, &desc, &menupath, &func))
-       return NULL;
+  if (!PyArg_ParseTuple (args, "sssO:dia.register_action",
+                         &action, &desc, &menupath, &func)) {
+    return NULL;
+  }
 
-    return _RegisterAction (action, desc, menupath, func);
+  return _RegisterAction (action, desc, menupath, func);
 }
 
+
 static PyObject *
-_RegisterAction (gchar *action,
-                 gchar *desc,
-                 gchar *menupath,
+_RegisterAction (char     *action,
+                 char     *desc,
+                 char     *menupath,
                  PyObject *func)
 {
-       DiaCallbackFilter *filter;
+  DiaCallbackFilter *filter;
 
-    if (!PyCallable_Check(func)) {
-        PyErr_SetString(PyExc_TypeError, "third parameter must be callable");
-        return NULL;
-    }
+  if (!PyCallable_Check (func)) {
+    PyErr_SetString (PyExc_TypeError, "third parameter must be callable");
+    return NULL;
+  }
 
-    Py_INCREF(func); /* stay alive, where to kill ?? */
+  Py_INCREF (func); /* stay alive, where to kill ?? */
 
-    filter = g_new0 (DiaCallbackFilter, 1);
-    filter->action = g_strdup (action);
-    filter->description = g_strdup (desc);
-    filter->menupath = g_strdup (menupath);
-    filter->callback = &PyDia_callback_func;
-    filter->user_data = func;
+  filter = g_new0 (DiaCallbackFilter, 1);
+  filter->action = g_strdup (action);
+  filter->description = g_strdup (desc);
+  filter->menupath = g_strdup (menupath);
+  filter->callback = &PyDia_callback_func;
+  filter->user_data = func;
 
-    filter_register_callback(filter);
+  filter_register_callback (filter);
 
-    Py_INCREF(Py_None);
-    return Py_None;
+  Py_RETURN_NONE;
 }
 
+
 static PyObject *
 PyDia_Message (PyObject *self, PyObject *args)
 {
-    int type = 0;
-    char *text = "Huh?";
+  int type = 0;
+  char *text = "Huh?";
 
-    if (!PyArg_ParseTuple(args, "is:dia.message",
-                         &type, &text))
-       return NULL;
+  if (!PyArg_ParseTuple (args, "is:dia.message",
+                         &type, &text)) {
+    return NULL;
+  }
 
-    if (0 == type)
-       message_notice ("%s", text);
-    else if (1 == type)
-       message_warning ("%s", text);
-    else
-       message_error ("%s", text);
+  if (0 == type) {
+    message_notice ("%s", text);
+  } else if (1 == type) {
+    message_warning ("%s", text);
+  } else {
+    message_error ("%s", text);
+  }
 
-    Py_INCREF(Py_None);
-    return Py_None;
+  Py_RETURN_NONE;
 }
 
+
 static PyMethodDef dia_methods[] = {
     { "group_create", PyDia_GroupCreate, METH_VARARGS,
       "group_create(List of Object: objs) -> Object."
@@ -565,119 +580,80 @@ static PyMethodDef dia_methods[] = {
     { NULL, NULL }
 };
 
-PyDoc_STRVAR(dia_module_doc,
-"The dia module allows to write Python plug-ins for Dia [http://live.gnome.org/Dia/Python]\n";
-"\n"
-"This modules is designed to run Python scripts embedded in Dia. To make your script accessible\n"
-"to Dia you have to put it into $HOME/.dia/python and let it call one of the register_*() functions.\n"
-"It is possible to write import filters [register_import()] and export filters [register_export()], "
-"as well as scripts to manipulate existing diagrams or create new ones [register_action()].\n"
-"\n"
-"For stand-alone Python bindings to Dia see 
http://mail.gnome.org/archives/dia-list/2007-March/msg00092.html";);
 
-DL_EXPORT(void) initdia(void);
+PyDoc_STRVAR (dia_module_doc,
+              "The dia module allows to write Python plug-ins for Dia "
+              "[https://wiki.gnome.org/Apps/Dia/Python]\n";
+              "\n"
+              "This modules is designed to run Python scripts embedded in Dia."
+              " To make your script accessible\n"
+              "to Dia you have to put it into $HOME/.dia/python and let it "
+              "call one of the register_*() functions.\n"
+              "It is possible to write import filters [register_import()] and"
+              " export filters [register_export()], as well as scripts to "
+              "manipulate existing diagrams or create new ones"
+              " [register_action()].\n");
+
+
+DL_EXPORT (void) initdia (void);
+
+
+#define ADD_TYPE(Name)                                                  \
+  {                                                                     \
+    if (PyType_Ready (&PyDia##Name##_Type) != 0) {                      \
+      g_critical ("Failed to register PyDia##Name##_Type");             \
+    }                                                                   \
+                                                                        \
+    Py_INCREF (&PyDia##Name##_Type);                                    \
+    if (PyModule_AddObject (module,                                     \
+                            #Name,                                      \
+                            (PyObject *) &PyDia##Name##_Type) < 0) {    \
+      Py_DECREF (&PyDia##Name##_Type);                                  \
+      Py_DECREF (module);                                               \
+                                                                        \
+      g_critical ("Failed to add PyDia##Name##_Type");                  \
+    }                                                                   \
+  }
+
 
-DL_EXPORT(void)
-initdia(void)
+PyMODINIT_FUNC
+initdia (void)
 {
-    PyObject *m, *d;
-
-    /* see: Python FAQ 3.24 "Initializer not a constant." */
-    /* https://docs.python.org/2/c-api/typeobj.html#c.PyObject.ob_type */
-    PyDiaConnectionPoint_Type.ob_type = &PyType_Type;
-    PyDiaDiagram_Type.ob_type = &PyType_Type;
-    PyDiaDisplay_Type.ob_type = &PyType_Type;
-    PyDiaHandle_Type.ob_type = &PyType_Type;
-    PyDiaLayer_Type.ob_type = &PyType_Type;
-    PyDiaObject_Type.ob_type = &PyType_Type;
-    PyDiaObjectType_Type.ob_type = &PyType_Type;
-
-    PyDiaExportFilter_Type.ob_type = &PyType_Type;
-    PyDiaDiagramData_Type.ob_type = &PyType_Type;
-
-    PyDiaPoint_Type.ob_type = &PyType_Type;
-    PyDiaRectangle_Type.ob_type = &PyType_Type;
-    PyDiaBezPoint_Type.ob_type = &PyType_Type;
-    PyDiaArrow_Type.ob_type = &PyType_Type;
-    PyDiaMatrix_Type.ob_type = &PyType_Type;
-
-    PyDiaFont_Type.ob_type = &PyType_Type;
-    PyDiaColor_Type.ob_type = &PyType_Type;
-    PyDiaImage_Type.ob_type = &PyType_Type;
-    PyDiaProperty_Type.ob_type = &PyType_Type;
-    PyDiaProperties_Type.ob_type = &PyType_Type;
-    PyDiaError_Type.ob_type = &PyType_Type;
-    PyDiaText_Type.ob_type = &PyType_Type;
-    PyDiaPaperinfo_Type.ob_type = &PyType_Type;
-    PyDiaMenuitem_Type.ob_type = &PyType_Type;
-    PyDiaSheet_Type.ob_type = &PyType_Type;
-
-    m = Py_InitModule3("dia", dia_methods, dia_module_doc);
-    d = PyModule_GetDict(m);
-
-    /*
-     * The postfix 'Type' should not be there (one obvious exception, but there
-     * it isn't a Postfix). That is: names here and in the respective
-     * PyTypeObject must match.
-     * The extra namespacing (prefix 'Dia') isn't necessary either, we use the
-     * pythonesque namespacing instead.
-     */
-    /* instead to cast to PyObject* we use void* just to silence the ugly
-     * warning: dereferencing type-punned pointer will break strict-aliasing rules
-     */
-    PyDict_SetItemString(d, "Diagram",
-                        (void *)&PyDiaDiagram_Type);
-    PyDict_SetItemString(d, "Display",
-                        (void *)&PyDiaDisplay_Type);
-    PyDict_SetItemString(d, "Layer",
-                        (void *)&PyDiaLayer_Type);
-    PyDict_SetItemString(d, "Object",
-                        (void *)&PyDiaObject_Type);
-    PyDict_SetItemString(d, "ObjectType",
-                        (void *)&PyDiaObjectType_Type);
-    PyDict_SetItemString(d, "ConnectionPoint",
-                        (void *)&PyDiaConnectionPoint_Type);
-    PyDict_SetItemString(d, "Handle",
-                        (void *)&PyDiaHandle_Type);
-    PyDict_SetItemString(d, "ExportFilter",
-                        (void *)&PyDiaExportFilter_Type);
-    PyDict_SetItemString(d, "DiagramData",
-                        (void *)&PyDiaDiagramData_Type);
-    PyDict_SetItemString(d, "Point",
-                        (void *)&PyDiaPoint_Type);
-    PyDict_SetItemString(d, "Rectangle",
-                        (void *)&PyDiaRectangle_Type);
-    PyDict_SetItemString(d, "BezPoint",
-                        (void *)&PyDiaBezPoint_Type);
-    PyDict_SetItemString(d, "Font",
-                        (void *)&PyDiaFont_Type);
-    PyDict_SetItemString(d, "Color",
-                        (void *)&PyDiaColor_Type);
-    PyDict_SetItemString(d, "Image",
-                        (void *)&PyDiaImage_Type);
-    PyDict_SetItemString(d, "Property",
-                        (void *)&PyDiaProperty_Type);
-    PyDict_SetItemString(d, "Properties",
-                        (void *)&PyDiaProperties_Type);
-    PyDict_SetItemString(d, "Error",
-                        (void *)&PyDiaError_Type);
-    PyDict_SetItemString(d, "Arrow",
-                        (void *)&PyDiaArrow_Type);
-    PyDict_SetItemString(d, "Matrix",
-                        (void *)&PyDiaMatrix_Type);
-    PyDict_SetItemString(d, "Text",
-                        (void *)&PyDiaText_Type);
-    PyDict_SetItemString(d, "Paperinfo",
-                        (void *)&PyDiaPaperinfo_Type);
-    PyDict_SetItemString(d, "Menuitem",
-                        (void *)&PyDiaMenuitem_Type);
-    PyDict_SetItemString(d, "Sheet",
-                        (void *)&PyDiaSheet_Type);
-
-    if (PyErr_Occurred ())
-      Py_FatalError ("can't initialize module dia");
-    else {
-      /* should all be no-ops when used embedded */
-      libdia_init (DIA_MESSAGE_STDERR);
-    }
+  PyObject *module;
+
+  PyDiaDiagram_Type.tp_base = &PyDiaDiagramData_Type,
+
+  module = Py_InitModule3 ("dia", dia_methods, dia_module_doc);
+
+  ADD_TYPE (Display);
+  ADD_TYPE (Layer);
+  ADD_TYPE (Object);
+  ADD_TYPE (ObjectType);
+  ADD_TYPE (ConnectionPoint);
+  ADD_TYPE (Handle);
+  ADD_TYPE (ExportFilter);
+  ADD_TYPE (DiagramData);
+  ADD_TYPE (Diagram);
+  ADD_TYPE (Point);
+  ADD_TYPE (Rectangle);
+  ADD_TYPE (BezPoint);
+  ADD_TYPE (Font);
+  ADD_TYPE (Color);
+  ADD_TYPE (Image);
+  ADD_TYPE (Property);
+  ADD_TYPE (Properties);
+  ADD_TYPE (Error);
+  ADD_TYPE (Arrow);
+  ADD_TYPE (Matrix);
+  ADD_TYPE (Text);
+  ADD_TYPE (Paperinfo);
+  ADD_TYPE (Menuitem);
+  ADD_TYPE (Sheet);
+
+  if (PyErr_Occurred ()) {
+    Py_FatalError ("can't initialize module dia");
+  } else {
+    /* should all be no-ops when used embedded */
+    libdia_init (DIA_MESSAGE_STDERR);
+  }
 }
diff --git a/plug-ins/python/pydia-diagram.c b/plug-ins/python/pydia-diagram.c
index 089dbdc4..49c9125e 100644
--- a/plug-ins/python/pydia-diagram.c
+++ b/plug-ins/python/pydia-diagram.c
@@ -31,12 +31,12 @@
 #include "pydia-color.h"
 #include "pydia-error.h"
 
-#include <structmember.h> /* PyMemberDef */
-
 #include "app/load_save.h"
 #include "app/connectionpoint_ops.h"
 
 
+#define PYDIA_DIAGRAM(self) DIA_DIAGRAM (((PyDiaDiagramData *) self)->data)
+
 PyObject *
 PyDiaDiagram_New (Diagram *dia)
 {
@@ -46,7 +46,7 @@ PyDiaDiagram_New (Diagram *dia)
 
   if (!self) return NULL;
 
-  g_set_object (&self->dia, dia);
+  ((PyDiaDiagramData *) self)->data = DIA_DIAGRAM_DATA (g_object_ref (dia));
 
   return (PyObject *) self;
 }
@@ -55,297 +55,351 @@ PyDiaDiagram_New (Diagram *dia)
 static void
 PyDiaDiagram_Dealloc (PyDiaDiagram *self)
 {
-  g_clear_object (&self->dia);
-
   PyObject_DEL (self);
 }
 
 
-static int
-PyDiaDiagram_Compare(PyDiaDiagram *self, PyDiaDiagram *other)
+static PyObject *
+PyDiaDiagram_Str (PyDiaDiagram *self)
 {
-    if (self->dia == other->dia) return 0;
-    if (self->dia > other->dia) return -1;
-    return 1;
+  return PyString_FromString (PYDIA_DIAGRAM (self)->filename);
 }
 
-static long
-PyDiaDiagram_Hash(PyDiaDiagram *self)
-{
-    return (long)self->dia;
-}
 
 static PyObject *
-PyDiaDiagram_Str(PyDiaDiagram *self)
+PyDiaDiagram_Select (PyDiaDiagram *self, PyObject *args)
 {
-    return PyString_FromString(self->dia->filename);
-}
+  PyDiaObject *obj;
 
-static PyObject *
-PyDiaDiagram_Select(PyDiaDiagram *self, PyObject *args)
-{
-    PyDiaObject *obj;
+  if (!PyArg_ParseTuple (args, "O!:Diagram.select",
+      &PyDiaObject_Type, &obj)) {
+    return NULL;
+  }
+  diagram_select (PYDIA_DIAGRAM (self), obj->object);
 
-    if (!PyArg_ParseTuple(args, "O!:Diagram.select",
-                         &PyDiaObject_Type, &obj))
-       return NULL;
-    diagram_select(self->dia, obj->object);
-    Py_INCREF(Py_None);
-    return Py_None;
+  Py_RETURN_NONE;
 }
 
+
 static PyObject *
-PyDiaDiagram_IsSelected(PyDiaDiagram *self, PyObject *args)
+PyDiaDiagram_IsSelected (PyDiaDiagram *self, PyObject *args)
 {
-    PyDiaObject *obj;
+  PyDiaObject *obj;
 
-    if (!PyArg_ParseTuple(args, "O!:Diagram.is_selected",
-                         &PyDiaObject_Type, &obj))
-       return NULL;
-    return PyInt_FromLong(diagram_is_selected(self->dia, obj->object));
+  if (!PyArg_ParseTuple (args, "O!:Diagram.is_selected",
+                         &PyDiaObject_Type, &obj)) {
+    return NULL;
+  }
+
+  return PyBool_FromLong (diagram_is_selected (PYDIA_DIAGRAM (self),
+                                               obj->object));
 }
 
+
 static PyObject *
-PyDiaDiagram_Unselect(PyDiaDiagram *self, PyObject *args)
+PyDiaDiagram_Unselect (PyDiaDiagram *self, PyObject *args)
 {
-    PyDiaObject *obj;
+  PyDiaObject *obj;
 
-    if (!PyArg_ParseTuple(args, "O!:Diagram.unselect",
-                         &PyDiaObject_Type, &obj))
-       return NULL;
-    diagram_unselect_object(self->dia, obj->object);
-    Py_INCREF(Py_None);
-    return Py_None;
+  if (!PyArg_ParseTuple (args, "O!:Diagram.unselect",
+                         &PyDiaObject_Type, &obj)) {
+    return NULL;
+  }
+
+  diagram_unselect_object (PYDIA_DIAGRAM (self),
+                           obj->object);
+
+  Py_RETURN_NONE;
 }
 
+
 static PyObject *
-PyDiaDiagram_RemoveAllSelected(PyDiaDiagram *self, PyObject *args)
+PyDiaDiagram_RemoveAllSelected (PyDiaDiagram *self, PyObject *args)
 {
-    if (!PyArg_ParseTuple(args, ":Diagram.remove_all_selected"))
-       return NULL;
-    diagram_remove_all_selected(self->dia, TRUE);
-    Py_INCREF(Py_None);
-    return Py_None;
+  if (!PyArg_ParseTuple (args, ":Diagram.remove_all_selected")) {
+    return NULL;
+  }
+
+  diagram_remove_all_selected (PYDIA_DIAGRAM (self), TRUE);
+
+  Py_RETURN_NONE;
 }
 
+
 static PyObject *
-PyDiaDiagram_UpdateExtents(PyDiaDiagram *self, PyObject *args)
+PyDiaDiagram_UpdateExtents (PyDiaDiagram *self, PyObject *args)
 {
-    if (!PyArg_ParseTuple(args, ":Diagram.update_extents"))
-       return NULL;
-    diagram_update_extents(self->dia);
-    Py_INCREF(Py_None);
-    return Py_None;
+  if (!PyArg_ParseTuple (args, ":Diagram.update_extents")) {
+    return NULL;
+  }
+
+  diagram_update_extents (PYDIA_DIAGRAM (self));
+
+  Py_RETURN_NONE;
 }
 
+
 static PyObject *
-PyDiaDiagram_GetSortedSelected(PyDiaDiagram *self, PyObject *args)
+PyDiaDiagram_GetSortedSelected (PyDiaDiagram *self, PyObject *args)
 {
-    GList *list, *tmp;
-    PyObject *ret;
-    guint i, len;
+  GList *list, *tmp;
+  PyObject *ret;
+  guint i, len;
 
-    if (!PyArg_ParseTuple(args, ":Diagram.get_sorted_selected"))
-       return NULL;
-    list = diagram_get_sorted_selected(self->dia);
+  if (!PyArg_ParseTuple (args, ":Diagram.get_sorted_selected")) {
+    return NULL;
+  }
+
+  list = diagram_get_sorted_selected (PYDIA_DIAGRAM (self));
+
+  len = g_list_length (list);
+  ret = PyTuple_New (len);
 
-    len = g_list_length (list);
-    ret = PyTuple_New(len);
+  for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
+    PyTuple_SetItem (ret, i, PyDiaObject_New (DIA_OBJECT (tmp->data)));
+  }
 
-    for (i = 0, tmp = list; tmp; i++, tmp = tmp->next)
-       PyTuple_SetItem(ret, i, PyDiaObject_New((DiaObject *)tmp->data));
-    g_list_free(list);
-    return ret;
+  g_list_free (list);
+
+  return ret;
 }
 
+
 static PyObject *
-PyDiaDiagram_GetSortedSelectedRemove(PyDiaDiagram *self, PyObject *args)
+PyDiaDiagram_GetSortedSelectedRemove (PyDiaDiagram *self, PyObject *args)
 {
-    GList *list, *tmp;
-    PyObject *ret;
-    guint i, len;
+  GList *list, *tmp;
+  PyObject *ret;
+  guint i, len;
 
-    if (!PyArg_ParseTuple(args, ":Diagram.get_sorted_selected_remove"))
-       return NULL;
-    list = diagram_get_sorted_selected_remove(self->dia);
+  if (!PyArg_ParseTuple (args, ":Diagram.get_sorted_selected_remove")) {
+    return NULL;
+  }
+
+  list = diagram_get_sorted_selected_remove (PYDIA_DIAGRAM (self));
+
+  len = g_list_length (list);
+  ret = PyTuple_New (len);
 
-    len = g_list_length (list);
-    ret = PyTuple_New(len);
+  for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
+    PyTuple_SetItem (ret, i, PyDiaObject_New (DIA_OBJECT (tmp->data)));
+  }
 
-    for (i = 0, tmp = list; tmp; i++, tmp = tmp->next)
-       PyTuple_SetItem(ret, i, PyDiaObject_New((DiaObject *)tmp->data));
-    g_list_free(list);
-    return ret;
+  g_list_free (list);
+
+  return ret;
 }
 
+
 static PyObject *
-PyDiaDiagram_AddUpdate(PyDiaDiagram *self, PyObject *args)
+PyDiaDiagram_AddUpdate (PyDiaDiagram *self, PyObject *args)
 {
   DiaRectangle r;
 
   if (!PyArg_ParseTuple (args, "dddd:Diagram.add_update", &r.top,
-      &r.left, &r.bottom, &r.right))
+                         &r.left, &r.bottom, &r.right)) {
     return NULL;
+  }
 
-  diagram_add_update (self->dia, &r);
-  Py_INCREF (Py_None);
-  return Py_None;
+  diagram_add_update (PYDIA_DIAGRAM (self), &r);
+
+  Py_RETURN_NONE;
 }
 
+
 static PyObject *
-PyDiaDiagram_AddUpdateAll(PyDiaDiagram *self, PyObject *args)
+PyDiaDiagram_AddUpdateAll (PyDiaDiagram *self, PyObject *args)
 {
-    if (!PyArg_ParseTuple(args, ":Diagram.add_update_all"))
-       return NULL;
-    diagram_add_update_all(self->dia);
-    Py_INCREF(Py_None);
-    return Py_None;
+  if (!PyArg_ParseTuple (args, ":Diagram.add_update_all")) {
+    return NULL;
+  }
+
+  diagram_add_update_all (PYDIA_DIAGRAM (self));
+
+  Py_RETURN_NONE;
 }
 
+
 static PyObject *
-PyDiaDiagram_UpdateConnections(PyDiaDiagram *self, PyObject *args)
+PyDiaDiagram_UpdateConnections (PyDiaDiagram *self, PyObject *args)
 {
-    PyDiaObject *obj;
+  PyDiaObject *obj;
 
-    if (!PyArg_ParseTuple(args, "O!:Diagram.update_connections",
-                          &PyDiaObject_Type, &obj))
-       return NULL;
-    diagram_update_connections_object(self->dia, obj->object, TRUE);
-    Py_INCREF(Py_None);
-    return Py_None;
+  if (!PyArg_ParseTuple (args, "O!:Diagram.update_connections",
+                         &PyDiaObject_Type, &obj)) {
+    return NULL;
+  }
+
+  diagram_update_connections_object (PYDIA_DIAGRAM (self), obj->object, TRUE);
+
+  Py_RETURN_NONE;
 }
 
+
 static PyObject *
 PyDiaDiagram_Flush(PyDiaDiagram *self, PyObject *args)
 {
-    if (!PyArg_ParseTuple(args, ":Diagram.flush"))
-       return NULL;
-    diagram_flush(self->dia);
-    Py_INCREF(Py_None);
-    return Py_None;
+  if (!PyArg_ParseTuple (args, ":Diagram.flush")) {
+    return NULL;
+  }
+
+  diagram_flush (PYDIA_DIAGRAM (self));
+
+  Py_RETURN_NONE;
 }
 
+
 static PyObject *
-PyDiaDiagram_FindClickedObject(PyDiaDiagram *self, PyObject *args)
+PyDiaDiagram_FindClickedObject (PyDiaDiagram *self, PyObject *args)
 {
-    Point p;
-    double dist;
-    DiaObject *obj;
-
-    if (!PyArg_ParseTuple(args, "(dd)d:Diagram.find_clicked_object",
-                         &p.x, &p.y, &dist))
-       return NULL;
-    obj = diagram_find_clicked_object(self->dia, &p, dist);
-    if (obj)
-       return PyDiaObject_New(obj);
-    Py_INCREF(Py_None);
-    return Py_None;
+  Point p;
+  double dist;
+  DiaObject *obj;
+
+  if (!PyArg_ParseTuple (args, "(dd)d:Diagram.find_clicked_object",
+                         &p.x, &p.y, &dist)) {
+    return NULL;
+  }
+  obj = diagram_find_clicked_object (PYDIA_DIAGRAM (self), &p, dist);
+  if (obj) {
+    return PyDiaObject_New (obj);
+  }
+
+  Py_RETURN_NONE;
 }
 
+
 static PyObject *
-PyDiaDiagram_FindClosestHandle(PyDiaDiagram *self, PyObject *args)
+PyDiaDiagram_FindClosestHandle (PyDiaDiagram *self, PyObject *args)
 {
-    Point p;
-    double dist;
-    Handle *handle;
-    DiaObject *obj;
-    PyObject *ret;
-
-    if (!PyArg_ParseTuple(args, "dd:Diagram.find_closest_handle",
-                         &p.x, &p.y))
-       return NULL;
-    dist = diagram_find_closest_handle(self->dia, &handle, &obj, &p);
-    ret = PyTuple_New(3);
-    PyTuple_SetItem(ret, 0, PyFloat_FromDouble(dist));
-    if (handle)
-       PyTuple_SetItem(ret, 1, PyDiaHandle_New(handle, obj));
-    else {
-       Py_INCREF(Py_None);
-       PyTuple_SetItem(ret, 1, Py_None);
-    }
-    if (obj)
-       PyTuple_SetItem(ret, 1, PyDiaObject_New(obj));
-    else {
-       Py_INCREF(Py_None);
-       PyTuple_SetItem(ret, 1, Py_None);
-    }
-    return ret;
+  Point p;
+  double dist;
+  Handle *handle;
+  DiaObject *obj;
+  PyObject *ret;
+
+  if (!PyArg_ParseTuple (args, "dd:Diagram.find_closest_handle",
+                         &p.x, &p.y)) {
+    return NULL;
+  }
+
+  dist = diagram_find_closest_handle (PYDIA_DIAGRAM (self), &handle, &obj, &p);
+  ret = PyTuple_New (3);
+  PyTuple_SetItem (ret, 0, PyFloat_FromDouble (dist));
+  if (handle) {
+    PyTuple_SetItem (ret, 1, PyDiaHandle_New (handle, obj));
+  } else {
+    Py_INCREF (Py_None);
+    PyTuple_SetItem (ret, 1, Py_None);
+  }
+
+  if (obj) {
+    PyTuple_SetItem (ret, 1, PyDiaObject_New (obj));
+  } else {
+    Py_INCREF(Py_None);
+    PyTuple_SetItem (ret, 1, Py_None);
+  }
+
+  return ret;
 }
 
+
 static PyObject *
-PyDiaDiagram_FindClosestConnectionPoint(PyDiaDiagram *self, PyObject *args)
+PyDiaDiagram_FindClosestConnectionPoint (PyDiaDiagram *self, PyObject *args)
 {
-    Point p;
-    double dist;
-    ConnectionPoint *cpoint;
-    PyObject *ret;
-    PyDiaObject *obj = NULL;
-
-    if (!PyArg_ParseTuple(args, "dd|O!:Diagram.find_closest_connectionpoint",
-                         &p.x, &p.y, PyDiaObject_Type, &obj))
-       return NULL;
-    dist = diagram_find_closest_connectionpoint(self->dia, &cpoint, &p,
-                                               obj ? obj->object : NULL);
-    ret = PyTuple_New(2);
-    PyTuple_SetItem(ret, 0, PyFloat_FromDouble(dist));
-    if (cpoint)
-       PyTuple_SetItem(ret, 1, PyDiaConnectionPoint_New(cpoint));
-    else {
-       Py_INCREF(Py_None);
-       PyTuple_SetItem(ret, 1, Py_None);
-    }
-    return ret;
+  Point p;
+  double dist;
+  ConnectionPoint *cpoint;
+  PyObject *ret;
+  PyDiaObject *obj = NULL;
+
+  if (!PyArg_ParseTuple (args, "dd|O!:Diagram.find_closest_connectionpoint",
+                         &p.x, &p.y, PyDiaObject_Type, &obj)) {
+    return NULL;
+  }
+
+  dist = diagram_find_closest_connectionpoint (PYDIA_DIAGRAM (self),
+                                               &cpoint,
+                                               &p,
+                                               obj ? obj->object : NULL);
+
+  ret = PyTuple_New (2);
+  PyTuple_SetItem (ret, 0, PyFloat_FromDouble (dist));
+
+  if (cpoint) {
+    PyTuple_SetItem(ret, 1, PyDiaConnectionPoint_New (cpoint));
+  } else {
+    Py_INCREF (Py_None);
+    PyTuple_SetItem (ret, 1, Py_None);
+  }
+
+  return ret;
 }
 
+
 static PyObject *
-PyDiaDiagram_GroupSelected(PyDiaDiagram *self, PyObject *args)
+PyDiaDiagram_GroupSelected (PyDiaDiagram *self, PyObject *args)
 {
-    if (!PyArg_ParseTuple(args, ":Diagram.group_selected"))
-       return NULL;
-    diagram_group_selected(self->dia);
-    Py_INCREF(Py_None);
-    return Py_None;
+  if (!PyArg_ParseTuple(args, ":Diagram.group_selected")) {
+    return NULL;
+  }
+
+  diagram_group_selected (PYDIA_DIAGRAM (self));
+
+  Py_RETURN_NONE;
 }
 
+
 static PyObject *
-PyDiaDiagram_UngroupSelected(PyDiaDiagram *self, PyObject *args)
+PyDiaDiagram_UngroupSelected (PyDiaDiagram *self, PyObject *args)
 {
-    if (!PyArg_ParseTuple(args, ":Diagram.ungroup_selected"))
-       return NULL;
-    diagram_ungroup_selected(self->dia);
-    Py_INCREF(Py_None);
-    return Py_None;
+  if (!PyArg_ParseTuple (args, ":Diagram.ungroup_selected")) {
+    return NULL;
+  }
+
+  diagram_ungroup_selected (PYDIA_DIAGRAM (self));
+
+  Py_RETURN_NONE;
 }
 
+
 static PyObject *
-PyDiaDiagram_Save(PyDiaDiagram *self, PyObject *args)
+PyDiaDiagram_Save (PyDiaDiagram *self, PyObject *args)
 {
-    DiaContext *ctx;
-    gchar *filename = self->dia->filename;
-    int ret;
-
-    if (!PyArg_ParseTuple(args, "|s:Diagram.save", &filename))
-       return NULL;
-    ctx = dia_context_new ("PyDia Save");
-    dia_context_set_filename (ctx, filename);
-    ret = diagram_save(self->dia, filename, ctx);
-    /* FIXME: throwing away possible error messages */
-    dia_context_reset (ctx);
-    dia_context_release (ctx);
-    return PyInt_FromLong(ret);
+  DiaContext *ctx;
+  char *filename = PYDIA_DIAGRAM (self)->filename;
+  int ret;
+
+  if (!PyArg_ParseTuple(args, "|s:Diagram.save", &filename)) {
+    return NULL;
+  }
+
+  ctx = dia_context_new ("PyDia Save");
+  dia_context_set_filename (ctx, filename);
+  ret = diagram_save (PYDIA_DIAGRAM (self), filename, ctx);
+  /* FIXME: throwing away possible error messages */
+  dia_context_reset (ctx);
+  dia_context_release (ctx);
+
+  return PyInt_FromLong (ret);
 }
 
+
 static PyObject *
-PyDiaDiagram_Display(PyDiaDiagram *self, PyObject *args)
+PyDiaDiagram_Display (PyDiaDiagram *self, PyObject *args)
 {
-    DDisplay *disp;
+  DDisplay *disp;
+
+  if (!PyArg_ParseTuple (args, ":Diagram.display")) {
+    return NULL;
+  }
 
-    if (!PyArg_ParseTuple(args, ":Diagram.display"))
-       return NULL;
-    disp = new_display(self->dia);
-    return PyDiaDisplay_New(disp);
+  disp = new_display (PYDIA_DIAGRAM (self));
+
+  return PyDiaDisplay_New(disp);
 }
 
+
 /*
  *  Callback for "removed" signal, used by the connect_after method,
  *  it's a proxy for the python function, creating the values it needs.
@@ -354,39 +408,40 @@ PyDiaDiagram_Display(PyDiaDiagram *self, PyObject *args)
  *  @param user_data The python function to be called by the callback.
  */
 static void
-PyDiaDiagram_CallbackRemoved(Diagram *dia,void *user_data)
+PyDiaDiagram_CallbackRemoved (Diagram *dia, void *user_data)
 {
-    /* Check that we got a function */
-    PyObject *diaobj,*res,*arg;
-    PyObject *func = user_data;
-
-    if (!func || !PyCallable_Check (func)) {
-        g_warning ("Callback called without valid callback function.");
-        return;
-    }
-
-    /* Create a new PyDiaDiagram object. This really should reuse the object that we connected to.
-     * We'll do that later.
-     */
-    if (dia)
-        diaobj = PyDiaDiagram_New (dia);
-    else {
-        diaobj = Py_None;
-        Py_INCREF (diaobj);
-    }
-
-    Py_INCREF(func);
-
-    /* Call the callback. */
-    arg = Py_BuildValue ("(O)", diaobj);
-    if (arg) {
-      res = PyEval_CallObject (func, arg);
-      ON_RES(res, FALSE);
-    }
-    Py_XDECREF (arg);
-
-    Py_DECREF(func);
-    Py_XDECREF(diaobj);
+  /* Check that we got a function */
+  PyObject *diaobj, *res, *arg;
+  PyObject *func = user_data;
+
+  if (!func || !PyCallable_Check (func)) {
+    g_warning ("Callback called without valid callback function.");
+    return;
+  }
+
+  /*
+   * Create a new PyDiaDiagram object. This really should reuse the object
+   * that we connected to. We'll do that later.
+   */
+  if (dia) {
+    diaobj = PyDiaDiagram_New (dia);
+  } else {
+    diaobj = Py_None;
+    Py_INCREF (diaobj);
+  }
+
+  Py_INCREF (func);
+
+  /* Call the callback. */
+  arg = Py_BuildValue ("(O)", diaobj);
+  if (arg) {
+    res = PyEval_CallObject (func, arg);
+    ON_RES (res, FALSE);
+  }
+  Py_XDECREF (arg);
+
+  Py_DECREF (func);
+  Py_XDECREF (diaobj);
 }
 
 
@@ -399,86 +454,91 @@ PyDiaDiagram_CallbackRemoved(Diagram *dia,void *user_data)
  *  @param user_data The python function to be called by the callback.
  */
 static void
-PyDiaDiagram_CallbackSelectionChanged(Diagram *dia,int sel,void *user_data)
+PyDiaDiagram_CallbackSelectionChanged (Diagram *dia, int sel, void *user_data)
 {
-    /* Check that we got a function */
-    PyObject *dgm,*res,*arg;
-    PyObject *func = user_data;
-
-    if (!func || !PyCallable_Check (func)) {
-        g_warning ("Callback called without valid callback function.");
-        return;
-    }
-
-    /* Create a new PyDiaDiagram object. This really should reuse the object that we connected to.
-     * We'll do that later.
-     */
-    if (dia)
-        dgm = PyDiaDiagram_New (dia);
-    else {
-        dgm = Py_None;
-        Py_INCREF (dgm);
-    }
-
-
-    Py_INCREF(func);
-
-    /* Call the callback. */
-    arg = Py_BuildValue ("(Oi)", dgm,sel);
-    if (arg) {
-      res = PyEval_CallObject (func, arg);
-      ON_RES(res, FALSE);
-    }
-    Py_XDECREF (arg);
-
-    Py_DECREF(func);
-    Py_XDECREF(dgm);
+  /* Check that we got a function */
+  PyObject *dgm, *res, *arg;
+  PyObject *func = user_data;
+
+  if (!func || !PyCallable_Check (func)) {
+    g_warning ("Callback called without valid callback function.");
+    return;
+  }
+
+  /*
+   * Create a new PyDiaDiagram object. This really should reuse the object
+   * that we connected to. We'll do that later.
+   */
+  if (dia) {
+    dgm = PyDiaDiagram_New (dia);
+  } else {
+    dgm = Py_None;
+    Py_INCREF (dgm);
+  }
+
+  Py_INCREF (func);
+
+  /* Call the callback. */
+  arg = Py_BuildValue ("(Oi)", dgm, sel);
+  if (arg) {
+    res = PyEval_CallObject (func, arg);
+    ON_RES (res, FALSE);
+  }
+  Py_XDECREF (arg);
+
+  Py_DECREF (func);
+  Py_XDECREF (dgm);
 }
 
+
 /** Connects a python function to a signal.
  *  @param self The PyDiaDiagram this is a method of.
  *  @param args A tuple containing the arguments, a str for signal name
  *  and a callable object (like a function)
  */
 static PyObject *
-PyDiaDiagram_ConnectAfter(PyDiaDiagram *self, PyObject *args)
+PyDiaDiagram_ConnectAfter (PyDiaDiagram *self, PyObject *args)
 {
-    PyObject *func;
-    char *signal;
-
-    /* Check arguments */
-    if (!PyArg_ParseTuple(args, "sO:connect_after",&signal,&func))
-        return NULL;
-
-    /* Check that the arg is callable */
-    if (!PyCallable_Check(func)) {
-        PyErr_SetString(PyExc_TypeError, "Second parameter must be callable");
-        return NULL;
-    }
+  PyObject *func;
+  char *signal;
 
-    /* check if the signals name is valid */
-    if ( strcmp("removed",signal) == 0 || strcmp("selection_changed",signal) == 0) {
+  /* Check arguments */
+  if (!PyArg_ParseTuple (args, "sO:connect_after", &signal, &func)) {
+    return NULL;
+  }
 
-        Py_INCREF(func); /* stay alive, where to kill ?? */
+  /* Check that the arg is callable */
+  if (!PyCallable_Check (func)) {
+    PyErr_SetString (PyExc_TypeError, "Second parameter must be callable");
+    return NULL;
+  }
 
-        /* connect to signal after by signal name */
-        if (strcmp("removed",signal) == 0)
-        {
-            
g_signal_connect_after(DIA_DIAGRAM(self->dia),"removed",G_CALLBACK(PyDiaDiagram_CallbackRemoved), func);
-        }
+  /* check if the signals name is valid */
+  if (g_strcmp0 ("removed", signal) == 0 ||
+      g_strcmp0 ("selection_changed", signal) == 0) {
 
-        if (strcmp("selection_changed",signal) == 0)
-        {
-            
g_signal_connect_after(DIA_DIAGRAM(self->dia),"selection_changed",G_CALLBACK(PyDiaDiagram_CallbackSelectionChanged),
 func);
-        }
+    Py_INCREF (func); /* stay alive, where to kill ?? */
 
-        Py_INCREF(Py_None);
-        return Py_None;
+    /* connect to signal after by signal name */
+    if (g_strcmp0 ("removed", signal) == 0) {
+      g_signal_connect_after (PYDIA_DIAGRAM (self),
+                              "removed",
+                              G_CALLBACK (PyDiaDiagram_CallbackRemoved),
+                              func);
     }
-    else {
-            PyErr_SetString(PyExc_TypeError, "Wrong signal name");
-            return NULL;
+
+    if (strcmp ("selection_changed", signal) == 0) {
+      g_signal_connect_after (PYDIA_DIAGRAM (self),
+                              "selection_changed",
+                              G_CALLBACK (PyDiaDiagram_CallbackSelectionChanged),
+                              func);
     }
+
+    Py_RETURN_NONE;
+  } else {
+    PyErr_SetString (PyExc_TypeError, "Wrong signal name");
+    return NULL;
+  }
 }
 
 static PyMethodDef PyDiaDiagram_Methods[] = {
@@ -532,90 +592,97 @@ static PyMethodDef PyDiaDiagram_Methods[] = {
     {NULL, 0, 0, NULL}
 };
 
-#define T_INVALID -1 /* can't allow direct access due to pyobject->handle indirection */
-static PyMemberDef PyDiaDiagram_Members[] = {
-    { "data", T_INVALID, 0, RESTRICTED|READONLY, /* can't allow direct access due to pyobject->dia 
indirection */
-      "Backward-compatible base-class access" },
-    { "displays", T_INVALID, 0, RESTRICTED|READONLY,
-      "The list of current displays of this diagram." },
-    { "filename", T_INVALID, 0, RESTRICTED|READONLY,
-      "Filename in utf-8 encoding." },
-    { "modified", T_INVALID, 0, RESTRICTED|READONLY,
-      "Modification state." },
-    { "selected", T_INVALID, 0, RESTRICTED|READONLY,
-      "The current object selection." },
-    { "unsaved", T_INVALID, 0, RESTRICTED|READONLY,
-      "True if the diagram was not saved yet." },
-    { NULL }
-};
 
 static PyObject *
-PyDiaDiagram_GetAttr(PyDiaDiagram *self, gchar *attr)
+PyDiaDiagram_GetData (PyDiaDiagram *self, void *closure)
 {
-    if (!strcmp(attr, "__members__"))
-       return Py_BuildValue("[sssss]",
-                            "data", "displays", "filename",
-                            "modified", "selected", "unsaved");
-    else if (!strcmp(attr, "data"))
-        return PyDiaDiagramData_New (self->dia->data);
-    else if (!strcmp(attr, "filename"))
-       return PyString_FromString(self->dia->filename);
-    else if (!strcmp(attr, "unsaved"))
-       return PyInt_FromLong(self->dia->unsaved);
-    else if (!strcmp(attr, "modified"))
-       return PyInt_FromLong(diagram_is_modified(self->dia));
-    else if (!strcmp(attr, "selected")) {
-       guint i, len = g_list_length (self->dia->data->selected);
-       PyObject *ret = PyTuple_New(len);
-       GList *tmp;
-
-       for (i = 0, tmp = self->dia->data->selected; tmp; i++, tmp = tmp->next)
-           PyTuple_SetItem(ret, i, PyDiaObject_New((DiaObject *)tmp->data));
-       return ret;
-    } else if (!strcmp(attr, "displays")) {
-       PyObject *ret;
-       GSList *tmp;
-       gint i;
-
-       ret = PyTuple_New(g_slist_length(self->dia->displays));
-       for (i = 0, tmp = self->dia->displays; tmp; i++, tmp = tmp->next)
-           PyTuple_SetItem(ret, i, PyDiaDisplay_New((DDisplay *)tmp->data));
-       return ret;
-    }
+  Py_INCREF (self);
+
+  g_warning ("Use of <PyDiaDiagram>.data. PyDiaDiagram is PyDiaDiagramData, use directly");
+
+  return (PyObject *) self;
+}
+
+
+static PyObject *
+PyDiaDiagram_GetDisplays (PyDiaDiagram *self, void *closure)
+{
+  PyObject *ret;
+  GSList *tmp;
+  int i;
+
+  ret = PyTuple_New (g_slist_length (PYDIA_DIAGRAM (self)->displays));
+
+  for (i = 0, tmp = PYDIA_DIAGRAM (self)->displays; tmp; i++, tmp = tmp->next) {
+    PyTuple_SetItem (ret, i, PyDiaDisplay_New ((DDisplay *) tmp->data));
+  }
+
+  return ret;
+}
 
-    return Py_FindMethod(PyDiaDiagram_Methods, (PyObject *)self, attr);
+
+static PyObject *
+PyDiaDiagram_GetFilename (PyDiaDiagram *self, void *closure)
+{
+  return PyString_FromString (PYDIA_DIAGRAM (self)->filename);
 }
 
+
+static PyObject *
+PyDiaDiagram_GetModified (PyDiaDiagram *self, void *closure)
+{
+  return PyBool_FromLong (diagram_is_modified (PYDIA_DIAGRAM (self)));
+}
+
+
+static PyObject *
+PyDiaDiagram_GetSelected (PyDiaDiagram *self, void *closure)
+{
+  guint i, len = g_list_length (DIA_DIAGRAM_DATA (PYDIA_DIAGRAM (self))->selected);
+  PyObject *ret = PyTuple_New (len);
+  GList *tmp;
+
+  for (i = 0, tmp = DIA_DIAGRAM_DATA (PYDIA_DIAGRAM (self))->selected; tmp; i++, tmp = tmp->next) {
+    PyTuple_SetItem (ret, i, PyDiaObject_New (DIA_OBJECT (tmp->data)));
+  }
+
+  return ret;
+}
+
+
+static PyObject *
+PyDiaDiagram_GetUnsaved (PyDiaDiagram *self, void *closure)
+{
+  return PyBool_FromLong (PYDIA_DIAGRAM (self)->unsaved);
+}
+
+
+static PyGetSetDef PyDiaDiagram_GetSetters[] = {
+  { "data", (getter) PyDiaDiagram_GetData, NULL,
+    "Backward-compatible base-class access", NULL },
+  { "displays", (getter) PyDiaDiagram_GetDisplays, NULL,
+    "The list of current displays of this diagram.", NULL },
+  { "filename", (getter) PyDiaDiagram_GetFilename, NULL,
+    "Filename in utf-8 encoding.", NULL },
+  { "modified", (getter) PyDiaDiagram_GetModified, NULL,
+    "Modification state.", NULL },
+  { "selected", (getter) PyDiaDiagram_GetSelected, NULL,
+    "The current object selection.", NULL },
+  { "unsaved", (getter) PyDiaDiagram_GetUnsaved, NULL,
+    "True if the diagram was not saved yet.", NULL },
+  { NULL }
+};
+
+
 PyTypeObject PyDiaDiagram_Type = {
-    PyObject_HEAD_INIT(NULL)
-    0,
-    "dia.Diagram",
-    sizeof(PyDiaDiagram),
-    0,
-    (destructor)PyDiaDiagram_Dealloc,
-    (printfunc)0,
-    (getattrfunc)PyDiaDiagram_GetAttr,
-    (setattrfunc)0,
-    (cmpfunc)PyDiaDiagram_Compare,
-    (reprfunc)0,
-    0,
-    0,
-    0,
-    (hashfunc)PyDiaDiagram_Hash,
-    (ternaryfunc)0,
-    (reprfunc)PyDiaDiagram_Str,
-    (getattrofunc)0,
-    (setattrofunc)0,
-    (PyBufferProcs *)0,
-    0L, /* Flags */
-    "Subclass of dia.DiagramData (at least in the C implementation) adding interfacing the GUI elements.",
-    (traverseproc)0,
-    (inquiry)0,
-    (richcmpfunc)0,
-    0, /* tp_weakliszoffset */
-    (getiterfunc)0,
-    (iternextfunc)0,
-    PyDiaDiagram_Methods, /* tp_methods */
-    PyDiaDiagram_Members, /* tp_members */
-    0
+  PyObject_HEAD_INIT (NULL)
+  .tp_name = "dia.Diagram",
+  .tp_basicsize = sizeof (PyDiaDiagram),
+  .tp_flags = Py_TPFLAGS_DEFAULT,
+  .tp_dealloc = (destructor) PyDiaDiagram_Dealloc,
+  .tp_str = (reprfunc) PyDiaDiagram_Str,
+  .tp_doc = "Subclass of dia.DiagramData adding interfacing the GUI "
+            "elements.",
+  .tp_methods = PyDiaDiagram_Methods,
+  .tp_getset = PyDiaDiagram_GetSetters,
 };
diff --git a/plug-ins/python/pydia-diagram.h b/plug-ins/python/pydia-diagram.h
index 5e0e506c..3b251885 100644
--- a/plug-ins/python/pydia-diagram.h
+++ b/plug-ins/python/pydia-diagram.h
@@ -17,16 +17,17 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifndef PYDIA_DIAGRAM_H
-#define PYDIA_DIAGRAM_H
-
 #include <Python.h>
 
 #include "app/diagram.h"
+#include "pydia-diagramdata.h"
+
+#pragma once
+
+G_BEGIN_DECLS
 
 typedef struct {
-    PyObject_HEAD
-    Diagram *dia;
+  PyDiaDiagramData parent;
 } PyDiaDiagram;
 
 
@@ -34,4 +35,4 @@ extern PyTypeObject PyDiaDiagram_Type;
 
 PyObject *PyDiaDiagram_New(Diagram *dia);
 
-#endif
+G_END_DECLS
diff --git a/plug-ins/python/pydia-diagramdata.c b/plug-ins/python/pydia-diagramdata.c
index c5f12f83..37c968f8 100644
--- a/plug-ins/python/pydia-diagramdata.c
+++ b/plug-ins/python/pydia-diagramdata.c
@@ -29,8 +29,6 @@
 #include "pydia-paperinfo.h"
 #include "pydia-error.h"
 
-#include <structmember.h> /* PyMemberDef */
-
 #include "app/diagram.h"
 #include "dia-layer.h"
 #include "pydia-diagram.h" /* support dynamic_cast */
@@ -41,11 +39,16 @@ PyDiaDiagramData_New (DiagramData *dd)
 {
   PyDiaDiagramData *self;
 
+  // Bit of a hack
+  if (DIA_IS_DIAGRAM (dd)) {
+    return PyDiaDiagram_New (DIA_DIAGRAM (dd));
+  }
+
   self = PyObject_NEW (PyDiaDiagramData, &PyDiaDiagramData_Type);
 
   if (!self) return NULL;
 
-  g_set_object (&self->data, dd);
+  self->data = g_object_ref (dd);
 
   return (PyObject *) self;
 }
@@ -56,32 +59,36 @@ PyDiaDiagramData_Dealloc (PyDiaDiagramData *self)
 {
   g_clear_object (&self->data);
 
-  PyObject_DEL(self);
+  PyObject_DEL (self);
 }
 
 
 static int
-PyDiaDiagramData_Compare(PyDiaDiagramData *self, PyDiaDiagramData *other)
+PyDiaDiagramData_Compare (PyDiaDiagramData *self, PyDiaDiagramData *other)
 {
-    if (self->data == other->data) return 0;
-    if (self->data > other->data) return -1;
-    return 1;
+  if (self->data == other->data) return 0;
+  if (self->data > other->data) return -1;
+  return 1;
 }
 
+
 static long
-PyDiaDiagramData_Hash(PyDiaDiagramData *self)
+PyDiaDiagramData_Hash (PyDiaDiagramData *self)
 {
-    return (long)self->data;
+  return (long) self->data;
 }
 
 
 static PyObject *
-PyDiaDiagramData_Str(PyDiaDiagramData *self)
+PyDiaDiagramData_Str (PyDiaDiagramData *self)
 {
-  PyObject* py_s;
-  char* s = g_strdup_printf ("<PyDiaDiagramData %p>", self);
+  PyObject *py_s;
+  char *s = g_strdup_printf ("<PyDiaDiagramData %p>", self);
+
   py_s = PyString_FromString (s);
+
   g_clear_pointer (&s, g_free);
+
   return py_s;
 }
 
@@ -90,33 +97,41 @@ PyDiaDiagramData_Str(PyDiaDiagramData *self)
  * "real" member function implementaion ?
  */
 static PyObject *
-PyDiaDiagramData_UpdateExtents(PyDiaDiagramData *self, PyObject *args)
+PyDiaDiagramData_UpdateExtents (PyDiaDiagramData *self, PyObject *args)
 {
-    if (!PyArg_ParseTuple(args, ":DiagramData.update_extents"))
-       return NULL;
-    data_update_extents(self->data);
-    Py_INCREF(Py_None);
-    return Py_None;
+  if (!PyArg_ParseTuple (args, ":DiagramData.update_extents")) {
+    return NULL;
+  }
+
+  data_update_extents(self->data);
+
+  Py_RETURN_NONE;
 }
 
+
 static PyObject *
-PyDiaDiagramData_GetSortedSelected(PyDiaDiagramData *self, PyObject *args)
+PyDiaDiagramData_GetSortedSelected (PyDiaDiagramData *self, PyObject *args)
 {
-    GList *list, *tmp;
-    PyObject *ret;
-    guint i, len;
+  GList *list, *tmp;
+  PyObject *ret;
+  guint i, len;
 
-    if (!PyArg_ParseTuple(args, ":DiagramData.get_sorted_selected"))
-       return NULL;
-    list = data_get_sorted_selected(self->data);
+  if (!PyArg_ParseTuple(args, ":DiagramData.get_sorted_selected")) {
+    return NULL;
+  }
 
-    len = g_list_length (list);
-    ret = PyTuple_New(len);
+  list = data_get_sorted_selected (self->data);
 
-    for (i = 0, tmp = list; tmp; i++, tmp = tmp->next)
-       PyTuple_SetItem(ret, i, PyDiaObject_New((DiaObject *)tmp->data));
-    g_list_free(list);
-    return ret;
+  len = g_list_length (list);
+  ret = PyTuple_New (len);
+
+  for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
+    PyTuple_SetItem (ret, i, PyDiaObject_New (DIA_OBJECT (tmp->data)));
+  }
+
+  g_list_free (list);
+
+  return ret;
 }
 
 
@@ -328,128 +343,137 @@ static PyMethodDef PyDiaDiagramData_Methods[] = {
     {NULL, 0, 0, NULL}
 };
 
-#define T_INVALID -1 /* can't allow direct access due to pyobject->data indirection */
-static PyMemberDef PyDiaDiagramData_Members[] = {
-    { "extents", T_INVALID, 0, RESTRICTED|READONLY,
-      "Rectangle covering all object's bounding boxes." },
-    { "bg_color", T_INVALID, 0, RESTRICTED|READONLY,
-      "Color of the diagram's background."},
-    { "paper", T_INVALID, 0, RESTRICTED|READONLY,
-      "Paperinfo of the diagram."},
-    { "layers", T_INVALID, 0, RESTRICTED|READONLY,
-      "Read-only list of the diagrams layers."},
-    { "active_layer", T_INVALID, 0, RESTRICTED|READONLY,
-      "Layer currently active in the diagram."},
-    { "grid_width", T_INVALID, 0, RESTRICTED|READONLY,
-      "Tuple(real: x, real: y) : describing the grid size."},
-    { "grid_visible", T_INVALID, 0, RESTRICTED|READONLY,
-      "bool: visibility of the grid."},
-    { "hguides", T_INVALID, 0, RESTRICTED|READONLY,
-      "List of real: horizontal guides."},
-    { "vguides", T_INVALID, 0, RESTRICTED|READONLY,
-      "List of real: vertical guides."},
-    { "selected", T_INVALID, 0, RESTRICTED|READONLY,
-      "List of Object: current selection."},
-    { "diagram", T_INVALID, 0, RESTRICTED|READONLY,
-      "This data objects Diagram or None"},
-    { NULL }
-};
+
+static PyObject *
+PyDiaDiagramData_GetExtents (PyDiaDiagramData *self, void *closure)
+{
+  return PyDiaRectangle_New (&self->data->extents, NULL);
+}
 
 
 static PyObject *
-PyDiaDiagramData_GetAttr (PyDiaDiagramData *self, char *attr)
+PyDiaDiagramData_GetBgColor (PyDiaDiagramData *self, void *closure)
 {
-  DiagramData *data = self->data;
-
-  if (!strcmp (attr, "__members__")) {
-    return Py_BuildValue ("[ssssssssssss]",
-                          "extents", "bg_color", "paper",
-                          "layers", "active_layer",
-                          "grid_width", "grid_visible",
-                          "hguides", "vguides",
-                          "selected" );
-  } else if (!strcmp (attr, "extents")) {
-    return PyDiaRectangle_New (&data->extents, NULL);
-  } else if (!strcmp (attr, "bg_color")) {
-    return PyDiaColor_New (&(data->bg_color));
-  } else if (!strcmp (attr, "layers")) {
-    PyObject *ret = PyTuple_New (data_layer_count (data));
-
-    DIA_FOR_LAYER_IN_DIAGRAM (data, layer, i, {
-      PyTuple_SetItem (ret, i, PyDiaLayer_New (layer));
-    });
-
-    return ret;
-  } else if (!strcmp (attr, "active_layer")) {
-    return PyDiaLayer_New (dia_diagram_data_get_active_layer (data));
-  } else if (!strcmp (attr, "paper")) {
-    return PyDiaPaperinfo_New (&data->paper);
-  } else if (!strcmp(attr, "selected")) {
-    PyObject *ret;
-    GList *tmp;
-    int i;
-
-    ret = PyTuple_New (g_list_length (self->data->selected));
-    for (i = 0, tmp = data->selected; tmp; i++, tmp = tmp->next) {
-      PyTuple_SetItem (ret, i, PyDiaObject_New ((DiaObject *) tmp->data));
-    }
-    return ret;
-  } else if (!strcmp(attr, "diagram")) {
-    if (DIA_IS_DIAGRAM (self->data)) {
-      return PyDiaDiagram_New (DIA_DIAGRAM (self->data));
-    }
-    Py_INCREF (Py_None);
-    return Py_None;
-  } else {
-    /* In the interactive case diagramdata is_a diagram */
-    if (DIA_IS_DIAGRAM (self->data)) {
-      Diagram *diagram = DIA_DIAGRAM (self->data);
-      if (diagram) { /* paranoid and helping scan-build */
-        if (!strcmp (attr, "grid_width")) {
-          return Py_BuildValue ("(dd)", diagram->grid.width_x, diagram->grid.width_y);
-        } else if (!strcmp (attr, "grid_visible")) {
-          return Py_BuildValue ("(ii)", diagram->grid.visible_x, diagram->grid.visible_y);
-        }
-      }
-    }
+  return PyDiaColor_New (&(self->data->bg_color));
+}
+
+
+static PyObject *
+PyDiaDiagramData_GetPaper (PyDiaDiagramData *self, void *closure)
+{
+  return PyDiaPaperinfo_New (&self->data->paper);
+}
+
+
+static PyObject *
+PyDiaDiagramData_GetLayers (PyDiaDiagramData *self, void *closure)
+{
+  PyObject *ret = PyTuple_New (data_layer_count (self->data));
+
+  DIA_FOR_LAYER_IN_DIAGRAM (self->data, layer, i, {
+    PyTuple_SetItem (ret, i, PyDiaLayer_New (layer));
+  });
+
+  return ret;
+}
+
+
+static PyObject *
+PyDiaDiagramData_GetActiveLayer (PyDiaDiagramData *self, void *closure)
+{
+  return PyDiaLayer_New (dia_diagram_data_get_active_layer (self->data));
+}
+
+
+static PyObject *
+PyDiaDiagramData_GetGridWidth (PyDiaDiagramData *self, void *closure)
+{
+  if (DIA_IS_DIAGRAM (self->data)) {
+    return Py_BuildValue ("(dd)",
+                          DIA_DIAGRAM (self->data)->grid.width_x,
+                          DIA_DIAGRAM (self->data)->grid.width_y);
   }
 
-  return Py_FindMethod (PyDiaDiagramData_Methods, (PyObject *) self, attr);
+  Py_RETURN_NONE;
+}
+
+
+static PyObject *
+PyDiaDiagramData_GetGridVisible (PyDiaDiagramData *self, void *closure)
+{
+  return Py_BuildValue ("(ii)",
+                        DIA_DIAGRAM (self->data)->grid.visible_x,
+                        DIA_DIAGRAM (self->data)->grid.visible_y);
 }
 
 
+static PyObject *
+PyDiaDiagramData_GetSelected (PyDiaDiagramData *self, void *closure)
+{
+  PyObject *ret;
+  GList *tmp;
+  int i;
+
+  ret = PyTuple_New (g_list_length (self->data->selected));
+  for (i = 0, tmp = self->data->selected; tmp; i++, tmp = tmp->next) {
+    PyTuple_SetItem (ret, i, PyDiaObject_New ((DiaObject *) tmp->data));
+  }
+
+  return ret;
+}
+
+
+static PyObject *
+PyDiaDiagramData_GetDiagram (PyDiaDiagramData *self, void *closure)
+{
+  g_warning ("Use of <PyDiaDiagramData>.diagram. PyDiaDiagram is PyDiaDiagramData, use directly");
+
+  if (DIA_IS_DIAGRAM (self->data)) {
+    Py_INCREF (self);
+    return (PyObject *) self;
+  }
+
+  Py_RETURN_NONE;
+}
+
+
+static PyGetSetDef PyDiaDiagramData_GetSetters[] = {
+  { "extents", (getter) PyDiaDiagramData_GetExtents, NULL,
+    "Rectangle covering all object's bounding boxes.", NULL },
+  { "bg_color", (getter) PyDiaDiagramData_GetBgColor, NULL,
+    "Color of the diagram's background.", NULL },
+  { "paper", (getter) PyDiaDiagramData_GetPaper, NULL,
+    "Paperinfo of the diagram.", NULL },
+  { "layers", (getter) PyDiaDiagramData_GetLayers, NULL,
+    "Read-only list of the diagrams layers.", NULL },
+  { "active_layer", (getter) PyDiaDiagramData_GetActiveLayer, NULL,
+    "Layer currently active in the diagram.", NULL },
+  { "grid_width", (getter) PyDiaDiagramData_GetGridWidth, NULL,
+    "Tuple(real: x, real: y) : describing the grid size.", NULL },
+  { "grid_visible", (getter) PyDiaDiagramData_GetGridVisible, NULL,
+    "bool: visibility of the grid.", NULL },
+  { "selected", (getter) PyDiaDiagramData_GetSelected, NULL,
+    "List of Object: current selection.", NULL },
+  { "diagram", (getter) PyDiaDiagramData_GetDiagram, NULL,
+    "This data objects Diagram or None", NULL },
+  { NULL }
+};
+
+
 PyTypeObject PyDiaDiagramData_Type = {
-    PyObject_HEAD_INIT(NULL)
-    0,
-    "dia.DiagramData",
-    sizeof(PyDiaDiagramData),
-    0,
-    (destructor)PyDiaDiagramData_Dealloc,
-    (printfunc)0,
-    (getattrfunc)PyDiaDiagramData_GetAttr,
-    (setattrfunc)0,
-    (cmpfunc)PyDiaDiagramData_Compare,
-    (reprfunc)0,
-    0,
-    0,
-    0,
-    (hashfunc)PyDiaDiagramData_Hash,
-    (ternaryfunc)0,
-    (reprfunc)PyDiaDiagramData_Str,
-    (getattrofunc)0,
-    (setattrofunc)0,
-    (PyBufferProcs *)0,
-    0L, /* Flags */
-    "The 'low level' diagram object. It contains everything to manipulate diagrams from im- and export "
-    "filters as well as from the UI. It does not provide any access to GUI elements related to the diagram."
-    "Use the subclass dia.Diagram object for such matters.",
-    (traverseproc)0,
-    (inquiry)0,
-    (richcmpfunc)0,
-    0, /* tp_weakliszoffset */
-    (getiterfunc)0,
-    (iternextfunc)0,
-    PyDiaDiagramData_Methods, /* tp_methods */
-    PyDiaDiagramData_Members, /* tp_members */
-    0
+  PyObject_HEAD_INIT (NULL)
+  .tp_name = "dia.DiagramData",
+  .tp_basicsize = sizeof (PyDiaDiagramData),
+  .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+  .tp_dealloc = (destructor) PyDiaDiagramData_Dealloc,
+  .tp_compare = (cmpfunc) PyDiaDiagramData_Compare,
+  .tp_hash = (hashfunc) PyDiaDiagramData_Hash,
+  .tp_str = (reprfunc) PyDiaDiagramData_Str,
+  .tp_doc = "The 'low level' diagram object. It contains everything to "
+            "manipulate diagrams from im- and export filters as well as"
+            " from the UI. It does not provide any access to GUI elements "
+            "related to the diagram. Use the subclass dia.Diagram object"
+            " for such matters.",
+  .tp_methods = PyDiaDiagramData_Methods,
+  .tp_getset = PyDiaDiagramData_GetSetters,
 };
diff --git a/plug-ins/python/pydia-layer.c b/plug-ins/python/pydia-layer.c
index 20d0f088..9f529e39 100644
--- a/plug-ins/python/pydia-layer.c
+++ b/plug-ins/python/pydia-layer.c
@@ -25,44 +25,53 @@
 #include "pydia-render.h"
 #include "dia-layer.h"
 
-#include <structmember.h> /* PyMemberDef */
 
 PyObject *
-PyDiaLayer_New(DiaLayer *layer)
+PyDiaLayer_New (DiaLayer *layer)
 {
   PyDiaLayer *self;
 
   self = PyObject_NEW (PyDiaLayer, &PyDiaLayer_Type);
 
-  if (!self) return NULL;
-  self->layer = layer;
-  return (PyObject *)self;
+  if (!self) {
+    return NULL;
+  }
+
+  self->layer = g_object_ref (layer);
+
+  return (PyObject *) self;
 }
 
+
 static void
-PyDiaLayer_Dealloc(PyDiaLayer *self)
+PyDiaLayer_Dealloc (PyDiaLayer *self)
 {
-     PyObject_DEL(self);
+  g_clear_object (&self->layer);
+
+  PyObject_DEL (self);
 }
 
+
 static int
-PyDiaLayer_Compare(PyDiaLayer *self, PyDiaLayer *other)
+PyDiaLayer_Compare (PyDiaLayer *self, PyDiaLayer *other)
 {
-    if (self->layer == other->layer) return 0;
-    if (self->layer > other->layer) return -1;
-    return 1;
+  if (self->layer == other->layer) return 0;
+  if (self->layer > other->layer) return -1;
+  return 1;
 }
 
+
 static long
-PyDiaLayer_Hash(PyDiaLayer *self)
+PyDiaLayer_Hash (PyDiaLayer *self)
 {
-    return (long)self->layer;
+  return (long) self->layer;
 }
 
+
 static PyObject *
-PyDiaLayer_Str(PyDiaLayer *self)
+PyDiaLayer_Str (PyDiaLayer *self)
 {
-    return PyString_FromString (dia_layer_get_name (self->layer));
+  return PyString_FromString (dia_layer_get_name (self->layer));
 }
 
 /* methods here */
@@ -74,32 +83,35 @@ PyDiaLayer_Destroy (PyDiaLayer *self, PyObject *args)
     return NULL;
 
   g_clear_object (&self->layer);
-  self->layer = NULL; /* we need some error checking elsewhere */
-  Py_INCREF (Py_None);
-  return Py_None;
+  /* we need some error checking elsewhere */
+
+  Py_RETURN_NONE;
 }
 
+
 static PyObject *
 PyDiaLayer_ObjectGetIndex (PyDiaLayer *self, PyObject *args)
 {
   PyDiaObject *obj;
 
-  if (!PyArg_ParseTuple(args, "O!:Layer.object_get_index",
-      &PyDiaObject_Type, &obj))
+  if (!PyArg_ParseTuple (args, "O!:Layer.object_get_index",
+                         &PyDiaObject_Type, &obj)) {
     return NULL;
+  }
 
-  return PyInt_FromLong (dia_layer_object_get_index (self->layer, obj->object));
+  return PyInt_FromLong (dia_layer_object_get_index (self->layer,
+                                                     obj->object));
 }
 
+
 static PyObject *
 PyDiaLayer_AddObject (PyDiaLayer *self, PyObject *args)
 {
   PyDiaObject *obj;
   int pos = -1;
 
-  if (!PyArg_ParseTuple(args, "O!|i:Layer.add_object",
-      &PyDiaObject_Type, &obj,
-      &pos)) {
+  if (!PyArg_ParseTuple (args, "O!|i:Layer.add_object",
+                         &PyDiaObject_Type, &obj, &pos)) {
     return NULL;
   }
 
@@ -109,25 +121,26 @@ PyDiaLayer_AddObject (PyDiaLayer *self, PyObject *args)
     dia_layer_add_object (self->layer, obj->object);
   }
 
-  Py_INCREF(Py_None);
-  return Py_None;
+  Py_RETURN_NONE;
 }
 
+
 static PyObject *
-PyDiaLayer_RemoveObject(PyDiaLayer *self, PyObject *args)
+PyDiaLayer_RemoveObject (PyDiaLayer *self, PyObject *args)
 {
   PyDiaObject *obj;
 
-  if (!PyArg_ParseTuple(args, "O!:Layer.remove_object",
-      &PyDiaObject_Type, &obj))
+  if (!PyArg_ParseTuple (args, "O!:Layer.remove_object",
+                         &PyDiaObject_Type, &obj)) {
     return NULL;
+  }
 
   dia_layer_remove_object (self->layer, obj->object);
 
-  Py_INCREF(Py_None);
-  return Py_None;
+  Py_RETURN_NONE;
 }
 
+
 static PyObject *
 PyDiaLayer_FindObjectsInRectangle (PyDiaLayer *self, PyObject *args)
 {
@@ -136,8 +149,9 @@ PyDiaLayer_FindObjectsInRectangle (PyDiaLayer *self, PyObject *args)
   PyObject *ret;
 
   if (!PyArg_ParseTuple (args, "dddd:Layer.find_objects_in_rectange",
-      &rect.top, &rect.left, &rect.bottom, &rect.right))
+                         &rect.top, &rect.left, &rect.bottom, &rect.right)) {
     return NULL;
+  }
 
   list = dia_layer_find_objects_in_rectangle (self->layer, &rect);
   ret = PyList_New (0);
@@ -149,40 +163,47 @@ PyDiaLayer_FindObjectsInRectangle (PyDiaLayer *self, PyObject *args)
   return ret;
 }
 
+
 static PyObject *
 PyDiaLayer_FindClosestObject (PyDiaLayer *self, PyObject *args)
 {
   Point pos;
-  real maxdist;
+  double maxdist;
   DiaObject *obj;
 
-  if (!PyArg_ParseTuple(args, "ddd:Layer.find_closest_object",
-      &pos.x, &pos.y, &maxdist))
+  if (!PyArg_ParseTuple (args, "ddd:Layer.find_closest_object",
+                         &pos.x, &pos.y, &maxdist)) {
     return NULL;
+  }
 
   obj = dia_layer_find_closest_object (self->layer, &pos, maxdist);
 
-  if (obj)
+  if (obj) {
     return PyDiaObject_New (obj);
+  }
 
-  Py_INCREF(Py_None);
-  return Py_None;
+  Py_RETURN_NONE;
 }
 
+
 static PyObject *
 PyDiaLayer_FindClosestConnectionPoint (PyDiaLayer *self, PyObject *args)
 {
   ConnectionPoint *cpoint = NULL;
   Point pos;
-  real dist;
+  double dist;
   PyObject *ret;
   PyDiaObject *obj;
 
-   if (!PyArg_ParseTuple(args, "dd|O!:Layer.find_closest_connection_point",
-       &pos.x, &pos.y, PyDiaObject_Type, &obj))
+   if (!PyArg_ParseTuple (args, "dd|O!:Layer.find_closest_connection_point",
+                          &pos.x, &pos.y, PyDiaObject_Type, &obj)) {
     return NULL;
+  }
 
-  dist = dia_layer_find_closest_connectionpoint (self->layer, &cpoint, &pos, obj ? obj->object : NULL);
+  dist = dia_layer_find_closest_connectionpoint (self->layer,
+                                                 &cpoint,
+                                                 &pos,
+                                                 obj ? obj->object : NULL);
 
   ret = PyTuple_New (2);
   PyTuple_SetItem (ret, 0, PyFloat_FromDouble (dist));
@@ -195,25 +216,30 @@ PyDiaLayer_FindClosestConnectionPoint (PyDiaLayer *self, PyObject *args)
   return ret;
 }
 
+
 static PyObject *
 PyDiaLayer_UpdateExtents (PyDiaLayer *self, PyObject *args)
 {
-  if (!PyArg_ParseTuple (args, ":Layer.update_extents"))
+  if (!PyArg_ParseTuple (args, ":Layer.update_extents")) {
     return NULL;
+  }
 
   return PyInt_FromLong (dia_layer_update_extents (self->layer));
 }
 
+
 static PyObject *
 PyDiaLayer_Render (PyDiaLayer *self, PyObject *args)
 {
   PyObject* renderer;
   DiaRenderer *wrapper;
   DiaRectangle *update = NULL;
-  gboolean active = FALSE; /* could derive but not sure if it's worth the effort. */
+  gboolean active = FALSE;
+  /* could derive but not sure if it's worth the effort. */
 
-  if (!PyArg_ParseTuple (args, "O:Layer.render", &renderer))
+  if (!PyArg_ParseTuple (args, "O:Layer.render", &renderer)) {
     return NULL;
+  }
 
   /* We need to create the PythonRenderer wrapper to provide the gobject interface.
    * This could be done much more efficient if it would somehow be cached for the
@@ -226,8 +252,7 @@ PyDiaLayer_Render (PyDiaLayer *self, PyObject *args)
                     active);
   g_clear_object (&wrapper);
 
-  Py_INCREF (Py_None);
-  return Py_None;
+  Py_RETURN_NONE;
 }
 
 /* missing functions:
@@ -239,113 +264,108 @@ PyDiaLayer_Render (PyDiaLayer *self, PyObject *args)
  */
 
 static PyMethodDef PyDiaLayer_Methods[] = {
-    {"destroy", (PyCFunction)PyDiaLayer_Destroy, METH_VARARGS,
-     "Release the layer. Must not be called when already added to a diagram."},
-    {"object_get_index", (PyCFunction)PyDiaLayer_ObjectGetIndex, METH_VARARGS,
-     "object_get_index(Object: o) -> int."
-     "  Returns the index of the object in the layers list of objects."},
-    {"add_object", (PyCFunction)PyDiaLayer_AddObject, METH_VARARGS,
-     "add_object(Object: o[, int: position]) -> None."
-     "  Add the object to the layer at the top or the given position counting from bottom."},
-    {"remove_object", (PyCFunction)PyDiaLayer_RemoveObject, METH_VARARGS,
-     "remove_object(Object: o) -> None"
-     "  Remove the object from the layer and delete it."},
-    {"find_objects_in_rectangle",
-     (PyCFunction)PyDiaLayer_FindObjectsInRectangle, METH_VARARGS,
-     "find_objects_in_rectangle(real: top, real left, real: bottom, real: right) -> Objects"
-     "  Returns a list of objects found in the given rectangle."},
-    {"find_closest_object", (PyCFunction)PyDiaLayer_FindClosestObject, METH_VARARGS,
-     "find_closest_object(real: x, real: y, real: maxdist) -> Object."
-     "  Find an object in the given maximum distance of the given point."},
-    {"find_closest_connection_point",
-     (PyCFunction)PyDiaLayer_FindClosestConnectionPoint, METH_VARARGS,
-     "find_closest_connectionpoint(real: x, real: y[, Object: o]) -> (real: dist, ConnectionPoint: cp)."
-     "  Given a point and an optional object to exclude return the distance and the closest connection point 
or None."},
-    {"update_extents", (PyCFunction)PyDiaLayer_UpdateExtents, METH_VARARGS,
-     "update_extents() -> None.  Force recaculation of the layer extents."},
-    { "render", (PyCFunction)PyDiaLayer_Render, METH_VARARGS,
-      "render(dia.Renderer: r) -> None."
-      "  Render the layer with the given renderer" },
-    {NULL, 0, 0, NULL}
+  { "destroy", (PyCFunction) PyDiaLayer_Destroy, METH_VARARGS,
+    "Release the layer. Must not be called when already added to a diagram."},
+  { "object_get_index", (PyCFunction) PyDiaLayer_ObjectGetIndex, METH_VARARGS,
+    "object_get_index(Object: o) -> int."
+    "  Returns the index of the object in the layers list of objects."},
+  { "add_object", (PyCFunction) PyDiaLayer_AddObject, METH_VARARGS,
+    "add_object(Object: o[, int: position]) -> None."
+    "  Add the object to the layer at the top or the given position counting from bottom."},
+  { "remove_object", (PyCFunction) PyDiaLayer_RemoveObject, METH_VARARGS,
+    "remove_object(Object: o) -> None"
+    "  Remove the object from the layer and delete it."},
+  { "find_objects_in_rectangle",
+    (PyCFunction) PyDiaLayer_FindObjectsInRectangle, METH_VARARGS,
+    "find_objects_in_rectangle(real: top, real left, real: bottom, real: right) -> Objects"
+    "  Returns a list of objects found in the given rectangle."},
+  { "find_closest_object", (PyCFunction) PyDiaLayer_FindClosestObject, METH_VARARGS,
+    "find_closest_object(real: x, real: y, real: maxdist) -> Object."
+    "  Find an object in the given maximum distance of the given point."},
+  { "find_closest_connection_point",
+    (PyCFunction) PyDiaLayer_FindClosestConnectionPoint, METH_VARARGS,
+    "find_closest_connectionpoint(real: x, real: y[, Object: o]) -> (real: dist, ConnectionPoint: cp)."
+    "  Given a point and an optional object to exclude return the distance and the closest connection point 
or None."},
+  { "update_extents", (PyCFunction) PyDiaLayer_UpdateExtents, METH_VARARGS,
+    "update_extents() -> None.  Force recaculation of the layer extents."},
+  { "render", (PyCFunction) PyDiaLayer_Render, METH_VARARGS,
+    "render(dia.Renderer: r) -> None."
+    "  Render the layer with the given renderer" },
+  { NULL, 0, 0, NULL }
 };
 
-#define T_INVALID -1 /* can't allow direct access due to pyobject->data indirection */
-static PyMemberDef PyDiaLayer_Members[] = {
-    { "extents", T_INVALID, 0, RESTRICTED|READONLY,
-      "Rectangle covering all object's bounding boxes." },
-    { "name", T_INVALID, 0, RESTRICTED|READONLY,
-      "The name of the layer." },
-    { "objects", T_INVALID, 0, RESTRICTED|READONLY,
-      "The list of objects in the layer." },
-    { "visible", T_INVALID, 0, RESTRICTED|READONLY,
-      "The visibility of the layer." },
-    { NULL }
-};
 
 static PyObject *
-PyDiaLayer_GetAttr(PyDiaLayer *self, gchar *attr)
+PyDiaLayer_GetExtents (PyDiaLayer *self, void *closure)
+{
+  DiaRectangle extents;
+
+  dia_layer_get_extents (self->layer, &extents);
+
+  return Py_BuildValue ("(dddd)",
+                        extents.top,
+                        extents.left,
+                        extents.bottom,
+                        extents.right);
+}
+
+
+static PyObject *
+PyDiaLayer_GetName (PyDiaLayer *self, void *closure)
+{
+  return PyString_FromString (dia_layer_get_name (self->layer));
+}
+
+
+static PyObject *
+PyDiaLayer_GetObjects (PyDiaLayer *self, void *closure)
 {
-  if (!strcmp (attr, "__members__"))
-    return Py_BuildValue ("[ssss]", "extents", "name", "objects", "visible");
-  else if (!strcmp (attr, "name")) {
-    return PyString_FromString (dia_layer_get_name (self->layer));
-  } else if (!strcmp (attr, "extents")) {
-    DiaRectangle extents;
-
-    dia_layer_get_extents (self->layer, &extents);
-
-    return Py_BuildValue ("(dddd)",
-                          extents.top,
-                          extents.left,
-                          extents.bottom,
-                          extents.right);
-  } else if (!strcmp (attr, "objects")) {
-    PyObject *ret;
-    GList *tmp;
-    gint i;
-
-    ret = PyTuple_New (g_list_length (dia_layer_get_object_list (self->layer)));
-    for (i = 0, tmp = dia_layer_get_object_list (self->layer); tmp; i++, tmp = tmp->next) {
-      PyTuple_SetItem (ret, i, PyDiaObject_New ((DiaObject *)tmp->data));
-    }
-    return ret;
-  } else if (!strcmp (attr, "visible")) {
-    return PyInt_FromLong (dia_layer_is_visible (self->layer));
+  PyObject *ret;
+  GList *tmp;
+  int i;
+
+  ret = PyTuple_New (g_list_length (dia_layer_get_object_list (self->layer)));
+
+  for (i = 0, tmp = dia_layer_get_object_list (self->layer);
+       tmp;
+       i++, tmp = tmp->next) {
+    PyTuple_SetItem (ret, i, PyDiaObject_New ((DiaObject *)tmp->data));
   }
 
-  return Py_FindMethod (PyDiaLayer_Methods, (PyObject *) self, attr);
+  return ret;
 }
 
+
+static PyObject *
+PyDiaLayer_GetVisible (PyDiaLayer *self, void *closure)
+{
+  return PyBool_FromLong (dia_layer_is_visible (self->layer));
+}
+
+
+static PyGetSetDef PyDiaLayer_GetSetters[] = {
+  { "extents", (getter) PyDiaLayer_GetExtents, NULL,
+    "Rectangle covering all object's bounding boxes.", NULL },
+  { "name", (getter) PyDiaLayer_GetName, NULL,
+    "The name of the layer.", NULL },
+  { "objects", (getter) PyDiaLayer_GetObjects, NULL,
+    "The list of objects in the layer.", NULL },
+  { "visible", (getter) PyDiaLayer_GetVisible, NULL,
+    "The visibility of the layer.", NULL },
+  { NULL }
+};
+
+
 PyTypeObject PyDiaLayer_Type = {
-    PyObject_HEAD_INIT(NULL)
-    0,
-    "dia.Layer",
-    sizeof(PyDiaLayer),
-    0,
-    (destructor)PyDiaLayer_Dealloc,
-    (printfunc)0,
-    (getattrfunc)PyDiaLayer_GetAttr,
-    (setattrfunc)0,
-    (cmpfunc)PyDiaLayer_Compare,
-    (reprfunc)0,
-    0,
-    0,
-    0,
-    (hashfunc)PyDiaLayer_Hash,
-    (ternaryfunc)0,
-    (reprfunc)PyDiaLayer_Str,
-    (getattrofunc)0,
-    (setattrofunc)0,
-    (PyBufferProcs *)0,
-    0L, /* Flags */
-    "A Layer is part of a Diagram and can contain objects.",
-    (traverseproc)0,
-    (inquiry)0,
-    (richcmpfunc)0,
-    0, /* tp_weakliszoffset */
-    (getiterfunc)0,
-    (iternextfunc)0,
-    PyDiaLayer_Methods, /* tp_methods */
-    PyDiaLayer_Members, /* tp_members */
-    0
+  PyObject_HEAD_INIT(NULL)
+  .tp_name = "dia.Layer",
+  .tp_basicsize = sizeof (PyDiaLayer),
+  .tp_flags = Py_TPFLAGS_DEFAULT,
+  .tp_dealloc = (destructor) PyDiaLayer_Dealloc,
+  .tp_compare = (cmpfunc) PyDiaLayer_Compare,
+  .tp_hash = (hashfunc) PyDiaLayer_Hash,
+  .tp_str = (reprfunc) PyDiaLayer_Str,
+  .tp_doc = "A Layer is part of a Diagram and can contain objects.",
+  .tp_methods = PyDiaLayer_Methods,
+  .tp_getset = PyDiaLayer_GetSetters,
 };


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]