2a693549e732b67b7308bee4176387636384ead2
[platform/upstream/pygobject2.git] / glib / pygoptiongroup.c
1 /* -*- Mode: C; c-basic-offset: 4 -*-
2  * pygobject - Python bindings for the GLib, GObject and GIO
3  * Copyright (C) 2006  Johannes Hoelzl
4  *
5  *   pygoptiongroup.c: GOptionContext and GOptionGroup wrapper
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
20  * USA
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #  include <config.h>
25 #endif
26
27 #include <pyglib.h>
28 #include "pyglib-private.h"
29 #include "pygoptiongroup.h"
30
31 PYGLIB_DEFINE_TYPE("glib.OptionGroup", PyGOptionGroup_Type, PyGOptionGroup)
32
33 /**
34  * pyg_option_group_new:
35  * @group: a GOptionGroup
36  *
37  * The returned GOptionGroup can't be used to set any hooks, translation domains
38  * or add entries. It's only intend is, to use for GOptionContext.add_group().
39  *
40  * Returns: the GOptionGroup wrapper.
41  */
42 PyObject *
43 pyg_option_group_new (GOptionGroup *group)
44 {
45     PyGOptionGroup *self;
46
47     self = (PyGOptionGroup *)PyObject_NEW(PyGOptionGroup,
48                       &PyGOptionGroup_Type);
49     if (self == NULL)
50         return NULL;
51
52     self->group = group;
53     self->other_owner = TRUE;
54     self->is_in_context = FALSE;
55
56     return (PyObject *)self;
57 }
58
59 static gboolean
60 check_if_owned(PyGOptionGroup *self)
61 {
62     if (self->other_owner)
63     {
64         PyErr_SetString(PyExc_ValueError, "The GOptionGroup was not created by "
65                         "glib.OptionGroup(), so operation is not possible.");
66         return TRUE;
67     }
68     return FALSE;
69 }
70
71 static void
72 destroy_g_group(PyGOptionGroup *self)
73 {
74     PyGILState_STATE state;
75     state = pyglib_gil_state_ensure();
76
77     self->group = NULL;
78     Py_CLEAR(self->callback);
79     g_slist_foreach(self->strings, (GFunc) g_free, NULL);
80     g_slist_free(self->strings);
81     self->strings = NULL;
82
83     if (self->is_in_context)
84     {
85         Py_DECREF(self);
86     }
87
88     pyglib_gil_state_release(state);
89 }
90
91 static int
92 pyg_option_group_init(PyGOptionGroup *self, PyObject *args, PyObject *kwargs)
93 {
94     static char *kwlist[] = { "name", "description", "help_description",
95                               "callback", NULL };
96     char *name, *description, *help_description;
97     PyObject *callback;
98
99     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "zzzO:GOptionGroup.__init__",
100                                      kwlist, &name, &description,
101                                      &help_description, &callback))
102         return -1;
103
104     self->group = g_option_group_new(name, description, help_description,
105                                      self, (GDestroyNotify) destroy_g_group);
106     self->other_owner = FALSE;
107     self->is_in_context = FALSE;
108
109     Py_INCREF(callback);
110     self->callback = callback;
111
112     return 0;
113 }
114
115 static void
116 pyg_option_group_dealloc(PyGOptionGroup *self)
117 {
118     if (!self->other_owner && !self->is_in_context)
119     {
120         GOptionGroup *tmp = self->group;
121         self->group = NULL;
122         if (tmp)
123             g_option_group_free(tmp);
124     }
125
126     PyObject_Del(self);
127 }
128
129 static gboolean
130 arg_func(const gchar *option_name,
131          const gchar *value,
132          PyGOptionGroup *self,
133          GError **error)
134 {
135     PyObject *ret;
136     PyGILState_STATE state;
137     gboolean no_error;
138
139     state = pyglib_gil_state_ensure();
140
141     if (value == NULL)
142         ret = PyObject_CallFunction(self->callback, "sOO",
143                                     option_name, Py_None, self);
144     else
145         ret = PyObject_CallFunction(self->callback, "ssO",
146                                     option_name, value, self);
147
148     if (ret != NULL)
149     {
150         Py_DECREF(ret);
151         no_error = TRUE;
152     } else
153         no_error = pyglib_gerror_exception_check(error) != -1;
154
155     pyglib_gil_state_release(state);
156     return no_error;
157 }
158
159 static PyObject *
160 pyg_option_group_add_entries(PyGOptionGroup *self, PyObject *args,
161                              PyObject *kwargs)
162 {
163     static char *kwlist[] = { "entries", NULL };
164     gssize entry_count, pos;
165     PyObject *entry_tuple, *list;
166     GOptionEntry *entries;
167
168     if (check_if_owned(self))
169         return NULL;
170
171     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:GOptionGroup.add_entries",
172                                      kwlist, &list))
173         return NULL;
174
175     if (!PyList_Check(list))
176     {
177         PyErr_SetString(PyExc_TypeError,
178                         "GOptionGroup.add_entries expected a list of entries");
179         return NULL;
180     }
181
182     entry_count = PyList_Size(list);
183     if (entry_count == -1)
184     {
185         PyErr_SetString(PyExc_TypeError,
186                         "GOptionGroup.add_entries expected a list of entries");
187         return NULL;
188     }
189
190     entries = g_new0(GOptionEntry, entry_count + 1);
191     for (pos = 0; pos < entry_count; pos++)
192     {
193         gchar *long_name, *description, *arg_description;
194         entry_tuple = PyList_GetItem(list, pos);
195         if (!PyTuple_Check(entry_tuple))
196         {
197             PyErr_SetString(PyExc_TypeError, "GOptionGroup.add_entries "
198                                              "expected a list of entries");
199             g_free(entries);
200             return NULL;
201         }
202         if (!PyArg_ParseTuple(entry_tuple, "scisz",
203             &long_name,
204             &(entries[pos].short_name),
205             &(entries[pos].flags),
206             &description,
207             &arg_description))
208         {
209             PyErr_SetString(PyExc_TypeError, "GOptionGroup.add_entries "
210                                              "expected a list of entries");
211             g_free(entries);
212             return NULL;
213         }
214         long_name = g_strdup(long_name);
215         self->strings = g_slist_prepend(self->strings, long_name);
216         entries[pos].long_name = long_name;
217
218         description = g_strdup(description);
219         self->strings = g_slist_prepend(self->strings, description);
220         entries[pos].description = description;
221
222         arg_description = g_strdup(arg_description);
223         self->strings = g_slist_prepend(self->strings, arg_description);
224         entries[pos].arg_description = arg_description;
225
226         entries[pos].arg = G_OPTION_ARG_CALLBACK;
227         entries[pos].arg_data = arg_func;
228     }
229
230     g_option_group_add_entries(self->group, entries);
231
232     g_free(entries);
233
234     Py_INCREF(Py_None);
235     return Py_None;
236 }
237
238
239 static PyObject *
240 pyg_option_group_set_translation_domain(PyGOptionGroup *self,
241                                         PyObject *args,
242                                         PyObject *kwargs)
243 {
244     static char *kwlist[] = { "domain", NULL };
245     char *domain;
246
247     if (check_if_owned(self))
248         return NULL;
249
250     if (self->group == NULL)
251     {
252         PyErr_SetString(PyExc_RuntimeError,
253                         "The corresponding GOptionGroup was already freed, "
254                         "probably through the release of GOptionContext");
255         return NULL;
256     }
257
258     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
259                                      "z:GOptionGroup.set_translate_domain",
260                                      kwlist, &domain))
261         return NULL;
262
263     g_option_group_set_translation_domain(self->group, domain);
264
265     Py_INCREF(Py_None);
266     return Py_None;
267 }
268
269 static PyObject*
270 pyg_option_group_richcompare(PyObject *self, PyObject *other, int op)
271 {
272     if (Py_TYPE(self) == Py_TYPE(other) && 
273           Py_TYPE(self) == &PyGOptionGroup_Type) {
274         return _pyglib_generic_ptr_richcompare(((PyGOptionGroup*)self)->group,
275                                                ((PyGOptionGroup*)other)->group,
276                                                op);
277     } else {
278         Py_INCREF(Py_NotImplemented);
279         return Py_NotImplemented;
280     }
281 }
282
283 static PyMethodDef pyg_option_group_methods[] = {
284     { "add_entries", (PyCFunction)pyg_option_group_add_entries, METH_VARARGS | METH_KEYWORDS },
285     { "set_translation_domain", (PyCFunction)pyg_option_group_set_translation_domain, METH_VARARGS | METH_KEYWORDS },
286     { NULL, NULL, 0 },
287 };
288
289 void
290 pyglib_option_group_register_types(PyObject *d)
291 {
292     PyGOptionGroup_Type.tp_dealloc = (destructor)pyg_option_group_dealloc;
293     PyGOptionGroup_Type.tp_richcompare = pyg_option_group_richcompare;
294     PyGOptionGroup_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
295     PyGOptionGroup_Type.tp_methods = pyg_option_group_methods;
296     PyGOptionGroup_Type.tp_init = (initproc)pyg_option_group_init;
297     PYGLIB_REGISTER_TYPE(d, PyGOptionGroup_Type, "OptionGroup");
298 }