1 #if defined(HAVE_CONFIG_H) && !defined(GEANYPY_WINDOWS)
2 # include "config.h"
3 #endif
4
5 #include "geanypy.h"
6
7
8 #define GOB_CHECK(pyobj, arg) \
9 { \
10 if (!pyobj || pyobj == Py_None || !pygobject_check(pyobj, PyGObject_Type)) \
11 { \
12 PyErr_SetString(PyExc_ValueError, \
13 "argument " #arg " must inherit from a gobject.GObject type"); \
14 return NULL; \
15 } \
16 }
17
18 #define GOB_TYPE_CHECK(gob, gob_type, arg) \
19 { \
20 if (!gob || !G_IS_OBJECT(gob) || \
21 !g_type_is_a(G_TYPE_FROM_INSTANCE(gob), gob_type)) \
22 { \
23 PyErr_SetString(PyExc_ValueError, \
24 "argument " #arg " must inherit from a " #gob_type " type"); \
25 return NULL; \
26 } \
27 }
28
29
30 static PyTypeObject *PyGObject_Type = NULL;
31
32
33 static PyObject *
UiUtils_hookup_widget(PyObject * module,PyObject * args,PyObject * kwargs)34 UiUtils_hookup_widget(PyObject *module, PyObject *args, PyObject *kwargs)
35 {
36 PyObject *py_owner = NULL, *py_widget = NULL;
37 const gchar *widget_name = NULL;
38 GObject *owner = NULL, *widget = NULL;
39 static gchar *kwlist[] = { "owner", "widget", "widget_name", NULL };
40
41 if (PyArg_ParseTupleAndKeywords(args, kwargs, "OOs", kwlist,
42 &py_owner, &py_widget, &widget_name))
43 {
44 GOB_CHECK(py_owner, 1);
45 GOB_CHECK(py_widget, 2);
46 owner = pygobject_get(py_owner);
47 widget = pygobject_get(py_widget);
48 ui_hookup_widget(owner, widget, widget_name);
49 }
50
51 Py_RETURN_NONE;
52 }
53
54
55 static PyObject *
UiUtils_lookup_widget(PyObject * module,PyObject * args,PyObject * kwargs)56 UiUtils_lookup_widget(PyObject *module, PyObject *args, PyObject *kwargs)
57 {
58 PyObject *py_widget = NULL;
59 const gchar *widget_name = NULL;
60 GObject *widget = NULL;
61 GtkWidget *found_widget = NULL;
62 static gchar *kwlist[] = { "widget", "widget_name", NULL };
63
64 if (PyArg_ParseTupleAndKeywords(args, kwargs, "Os", kwlist,
65 &py_widget, &widget_name))
66 {
67 GOB_CHECK(py_widget, 1);
68 widget = pygobject_get(py_widget);
69 GOB_TYPE_CHECK(widget, GTK_TYPE_WIDGET, 1);
70 found_widget = ui_lookup_widget(GTK_WIDGET(widget), widget_name);
71 if (GTK_IS_WIDGET(found_widget))
72 return pygobject_new(G_OBJECT(found_widget));
73 }
74
75 Py_RETURN_NONE;
76 }
77
78
79 static PyObject *
UiUtils_add_document_sensitive(PyObject * module,PyObject * args,PyObject * kwargs)80 UiUtils_add_document_sensitive(PyObject *module, PyObject *args, PyObject *kwargs)
81 {
82 PyObject *py_widget = NULL;
83 GObject *widget = NULL;
84 static gchar *kwlist[] = { "widget", NULL };
85
86 if (PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &py_widget))
87 {
88 GOB_CHECK(py_widget, 1);
89 widget = pygobject_get(py_widget);
90 GOB_TYPE_CHECK(widget, GTK_TYPE_WIDGET, 1);
91 ui_add_document_sensitive(GTK_WIDGET(widget));
92 }
93
94 Py_RETURN_NONE;
95 }
96
97
98 static PyObject *
UiUtils_button_new_with_image(PyObject * module,PyObject * args,PyObject * kwargs)99 UiUtils_button_new_with_image(PyObject *module, PyObject *args, PyObject *kwargs)
100 {
101 const gchar *stock_id = NULL, *text = NULL;
102 GtkWidget *button = NULL;
103 static gchar *kwlist[] = { "stock_id", "text", NULL };
104
105 if (PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist, &stock_id, &text))
106 {
107 button = ui_button_new_with_image(stock_id, text);
108 if (GTK_IS_WIDGET(button))
109 return pygobject_new(G_OBJECT(button));
110 }
111
112 Py_RETURN_NONE;
113 }
114
115
116 static PyObject *
UiUtils_combo_box_add_to_history(PyObject * module,PyObject * args,PyObject * kwargs)117 UiUtils_combo_box_add_to_history(PyObject *module, PyObject *args, PyObject *kwargs)
118 {
119 PyObject *py_cbo = NULL;
120 const gchar *text = NULL;
121 gint hist_len = 0;
122 GObject *widget = NULL;
123 static gchar *kwlist[] = { "combo_entry", "text", "history_len", NULL };
124
125 if (PyArg_ParseTupleAndKeywords(args, kwargs, "Osi", kwlist,
126 &py_cbo, &text, &hist_len))
127 {
128 GOB_CHECK(py_cbo, 1);
129 widget = pygobject_get(py_cbo);
130 GOB_TYPE_CHECK(widget, GTK_TYPE_COMBO_BOX_TEXT, 1);
131 ui_combo_box_add_to_history(GTK_COMBO_BOX_TEXT(widget), text, hist_len);
132 }
133
134 Py_RETURN_NONE;
135 }
136
137
138 static PyObject *
UiUtils_dialog_vbox_new(PyObject * module,PyObject * args,PyObject * kwargs)139 UiUtils_dialog_vbox_new(PyObject *module, PyObject *args, PyObject *kwargs)
140 {
141 PyObject *py_dlg;
142 GObject *dlg;
143 GtkWidget *widget;
144 static gchar *kwlist[] = { "dialog", NULL };
145
146 if (PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &py_dlg))
147 {
148 GOB_CHECK(py_dlg, 1);
149 dlg = pygobject_get(py_dlg);
150 GOB_TYPE_CHECK(dlg, GTK_TYPE_DIALOG, 1);
151 widget = ui_dialog_vbox_new(GTK_DIALOG(dlg));
152 if (GTK_IS_WIDGET(widget))
153 return pygobject_new(G_OBJECT(widget));
154 }
155
156 Py_RETURN_NONE;
157 }
158
159
160 static PyObject *
UiUtils_entry_add_clear_icon(PyObject * module,PyObject * args,PyObject * kwargs)161 UiUtils_entry_add_clear_icon(PyObject *module, PyObject *args, PyObject *kwargs)
162 {
163 PyObject *py_ent = NULL;
164 GObject *ent;
165 static gchar *kwlist[] = { "entry", NULL };
166
167 if (PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &py_ent))
168 {
169 GOB_CHECK(py_ent, 1);
170 ent = pygobject_get(py_ent);
171 GOB_TYPE_CHECK(ent, GTK_TYPE_ENTRY, 1);
172 ui_entry_add_clear_icon(GTK_ENTRY(ent));
173 }
174
175 Py_RETURN_NONE;
176 }
177
178
179 static PyObject *
UiUtils_frame_new_with_alignment(PyObject * module,PyObject * args,PyObject * kwargs)180 UiUtils_frame_new_with_alignment(PyObject *module, PyObject *args, PyObject *kwargs)
181 {
182 const gchar *text = NULL;
183 static gchar *kwlist[] = { "label_text", NULL };
184 GtkWidget *alignment = NULL, *frame = NULL;
185 PyObject *py_al = NULL, *py_fr = NULL, *ret;
186
187 if (PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &text))
188 {
189 frame = ui_frame_new_with_alignment(text, &alignment);
190 py_al = (PyObject *) pygobject_new(G_OBJECT(frame));
191 py_fr = (PyObject *) pygobject_new(G_OBJECT(alignment));
192 ret = Py_BuildValue("OO", py_al, py_fr);
193 Py_DECREF(py_al);
194 Py_DECREF(py_fr);
195 return ret;
196 }
197
198 Py_RETURN_NONE;
199 }
200
201
202 static PyObject *
UiUtils_get_gtk_settings_integer(PyObject * module,PyObject * args,PyObject * kwargs)203 UiUtils_get_gtk_settings_integer(PyObject *module, PyObject *args, PyObject *kwargs)
204 {
205 const gchar *prop_name = NULL;
206 gint default_value = 0;
207 static gchar *kwlist[] = { "property_name", "default_value", NULL };
208
209 if (PyArg_ParseTupleAndKeywords(args, kwargs, "si", kwlist, &prop_name,
210 &default_value))
211 {
212 return PyInt_FromLong(
213 (glong) ui_get_gtk_settings_integer(prop_name, default_value));
214 }
215
216 Py_RETURN_NONE;
217 }
218
219
220 static PyObject *
UiUtils_image_menu_item_new(PyObject * module,PyObject * args,PyObject * kwargs)221 UiUtils_image_menu_item_new(PyObject *module, PyObject *args, PyObject *kwargs)
222 {
223 const gchar *stock_id = NULL, *label = NULL;
224 GtkWidget *ret = NULL;
225 static gchar *kwlist[] = { "stock_id", "label", NULL };
226
227 if (PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist,
228 &stock_id, &label))
229 {
230 ret = ui_image_menu_item_new(stock_id, label);
231 if (GTK_IS_WIDGET(ret))
232 return pygobject_new(G_OBJECT(ret));
233 }
234
235 Py_RETURN_NONE;
236 }
237
238
239 static PyObject *
UiUtils_is_keyval_enter_or_return(PyObject * module,PyObject * args,PyObject * kwargs)240 UiUtils_is_keyval_enter_or_return(PyObject *module, PyObject *args, PyObject *kwargs)
241 {
242 guint kv;
243 static gchar *kwlist[] = { "keyval", NULL };
244
245 if (PyArg_ParseTupleAndKeywords(args, kwargs, "I", kwlist, &kv))
246 {
247 if (ui_is_keyval_enter_or_return(kv))
248 Py_RETURN_TRUE;
249 else
250 Py_RETURN_FALSE;
251 }
252
253 Py_RETURN_NONE;
254 }
255
256
257 /* FIXME: ui_menu_add_document_items() and ui_menu_add_document_items_sorted()
258 * skipped because I don't know how to pass GCallbacks between Python and C,
259 * if it's even possible. */
260
261
262 static PyObject *
UiUtils_path_box_new(PyObject * module,PyObject * args,PyObject * kwargs)263 UiUtils_path_box_new(PyObject *module, PyObject *args, PyObject *kwargs)
264 {
265 gint act;
266 PyObject *py_ent = NULL;
267 GObject *ent = NULL;
268 GtkWidget *pbox = NULL;
269 const gchar *title = NULL;
270 static gchar *kwlist[] = { "title", "action", "entry", NULL };
271
272 if (PyArg_ParseTupleAndKeywords(args, kwargs, "ziO", kwlist,
273 &title, &act, &py_ent))
274 {
275 GOB_CHECK(py_ent, 3);
276 ent = pygobject_get(py_ent);
277 GOB_TYPE_CHECK(ent, GTK_TYPE_ENTRY, 3);
278 pbox = ui_path_box_new(title, (GtkFileChooserAction) act, GTK_ENTRY(ent));
279 if (GTK_IS_WIDGET(pbox))
280 return pygobject_new(G_OBJECT(pbox));
281 }
282
283
284 Py_RETURN_NONE;
285 }
286
287
288 static PyObject *
UiUtils_progress_bar_start(PyObject * module,PyObject * args,PyObject * kwargs)289 UiUtils_progress_bar_start(PyObject *module, PyObject *args, PyObject *kwargs)
290 {
291 const gchar *text = NULL;
292 static gchar *kwlist[] = { "text", NULL };
293
294 if (PyArg_ParseTupleAndKeywords(args, kwargs, "z", kwlist, &text))
295 ui_progress_bar_start(text);
296
297 Py_RETURN_NONE;
298 }
299
300
301 static PyObject *
UiUtils_progress_bar_stop(PyObject * module)302 UiUtils_progress_bar_stop(PyObject *module)
303 {
304 ui_progress_bar_stop();
305 Py_RETURN_NONE;
306 }
307
308
309 static PyObject *
UiUtils_set_statusbar(PyObject * module,PyObject * args,PyObject * kwargs)310 UiUtils_set_statusbar(PyObject *module, PyObject *args, PyObject *kwargs)
311 {
312 gint log = 0;
313 const gchar *text = NULL;
314 static gchar *kwlist[] = { "text", "log", NULL };
315
316 if (PyArg_ParseTupleAndKeywords(args, kwargs, "s|i", kwlist, &text, &log))
317 ui_set_statusbar((gboolean) log, "%s", text);
318
319 Py_RETURN_NONE;
320 }
321
322
323 /* FIXME: ui_table_add_row() skipped since it's probably not useful and
324 * not well documented. */
325
326
327 static PyObject *
UiUtils_widget_modify_font_from_string(PyObject * module,PyObject * args,PyObject * kwargs)328 UiUtils_widget_modify_font_from_string(PyObject *module, PyObject *args, PyObject *kwargs)
329 {
330 PyObject *py_widget = NULL;
331 GObject *widget = NULL;
332 const gchar *font_str = NULL;
333 static gchar *kwlist[] = { "widget", "font_str", NULL };
334
335 if (PyArg_ParseTupleAndKeywords(args, kwargs, "Os", kwlist, &py_widget, &font_str))
336 {
337 GOB_CHECK(py_widget, 1);
338 widget = pygobject_get(py_widget);
339 GOB_TYPE_CHECK(widget, GTK_TYPE_WIDGET, 1);
340 ui_widget_modify_font_from_string(GTK_WIDGET(widget), font_str);
341 }
342
343 Py_RETURN_NONE;
344 }
345
346
347 /* Deprecated in Geany 0.21 in favour of gtk_widget_set_tooltip_text() */
348 #if 0
349 static PyObject *
350 UiUtils_widget_set_tooltip_text(PyObject *module, PyObject *args, PyObject *kwargs)
351 {
352 PyObject *py_widget = NULL;
353 GObject *widget = NULL;
354 const gchar *text = NULL;
355 static gchar *kwlist[] = { "widget", "text", NULL };
356
357 if (PyArg_ParseTupleAndKeywords(args, kwargs, "Os", kwlist, &py_widget, &text))
358 {
359 GOB_CHECK(py_widget, 1);
360 widget = pygobject_get(py_widget);
361 GOB_TYPE_CHECK(widget, GTK_TYPE_WIDGET, 1);
362 gtk_widget_set_tooltip_text(GTK_WIDGET(widget), text);
363 }
364
365 Py_RETURN_NONE;
366 }
367 #endif
368
369
370 static PyMethodDef UiUtilsModule_methods[] = {
371 { "hookup_widget", (PyCFunction) UiUtils_hookup_widget, METH_KEYWORDS,
372 "Sets a name to lookup widget from owner." },
373 { "lookup_widget", (PyCFunction) UiUtils_lookup_widget, METH_KEYWORDS,
374 "Returns a widget from a name in a component, usually created "
375 "by Glade. Call it with the toplevel widget in the component "
376 "(ie. a window or dialog), or alternatively any widget in the "
377 "component, and the name of the widget you want returned."},
378 { "add_document_sensitive", (PyCFunction) UiUtils_add_document_sensitive, METH_KEYWORDS,
379 "Adds a widget to the list of widgets that should be set "
380 "sensitive or insensitive depending if any documents are open." },
381 { "button_new_with_image", (PyCFunction) UiUtils_button_new_with_image, METH_KEYWORDS,
382 "Creates a gtk.Button with custom text and a stock image similar "
383 "to gtk.Button() initializer." },
384 { "combo_box_add_to_history", (PyCFunction) UiUtils_combo_box_add_to_history, METH_KEYWORDS,
385 "Prepends text to the dropdown list, removing a duplicate element "
386 "in the list if found. Also ensures there are less than the "
387 "specified number of elements in the history." },
388 { "dialog_vbox_new", (PyCFunction) UiUtils_dialog_vbox_new, METH_KEYWORDS,
389 "Makes a fixed border for dialogs without increasing the button "
390 "box border size." },
391 { "entry_add_clear_icon", (PyCFunction) UiUtils_entry_add_clear_icon, METH_KEYWORDS,
392 "Adds a small clear icon to the right end of the passed in entry. "
393 "A callback to clear the contents of the gtk.Entry is automatically "
394 "added." },
395 { "frame_new_with_alignement", (PyCFunction) UiUtils_frame_new_with_alignment, METH_KEYWORDS,
396 "Creates a GNOME HIG-style frame with no border and indented "
397 "child alignment. Returns a tuple with the gtk.Frame as the first "
398 "element and the gtk.Alignment as the second element." },
399 { "get_gtk_settings_integer", (PyCFunction) UiUtils_get_gtk_settings_integer, METH_KEYWORDS,
400 "Reads an integer from the GTK default settings registry." },
401 { "image_menu_item_new", (PyCFunction) UiUtils_image_menu_item_new, METH_KEYWORDS,
402 "Creates a gtk.ImageMenuItem with a stock image and a custom label." },
403 { "is_keyval_enter_or_return", (PyCFunction) UiUtils_is_keyval_enter_or_return, METH_KEYWORDS,
404 "Checks whether the passed in keyval is the Enter or Returns key. " },
405 { "path_box_new", (PyCFunction) UiUtils_path_box_new, METH_KEYWORDS,
406 "Creates a gtk.HBox with entry packed into it and an open button "
407 "which runs a file chooser, replacing entry text (if successful) "
408 "with the path returned from the gtk.FileChooser." },
409 { "progress_bar_start", (PyCFunction) UiUtils_progress_bar_start, METH_KEYWORDS,
410 "Starts a constantly pulsing progressbar in the right corner of "
411 "the statusbar (if the status bar is visible)." },
412 { "progress_bar_stop", (PyCFunction) UiUtils_progress_bar_stop, METH_NOARGS,
413 "Stops a running progress bar and hides the widget again." },
414 { "set_statusbar", (PyCFunction) UiUtils_set_statusbar, METH_KEYWORDS,
415 "Displays text on the statusbar." },
416 { "widget_modify_font_from_string", (PyCFunction) UiUtils_widget_modify_font_from_string, METH_KEYWORDS,
417 "Modifies the font of a widget using modify_font() automatically "
418 "parsing the Pango font description string in font_str." },
419 { NULL },
420 };
421
422
initui_utils(void)423 PyMODINIT_FUNC initui_utils(void)
424 {
425 PyObject *m;
426
427 init_pygobject();
428 init_pygtk();
429 m = PyImport_ImportModule("gobject");
430
431 if (m)
432 {
433 PyGObject_Type = (PyTypeObject *) PyObject_GetAttrString(m, "GObject");
434 Py_XDECREF(m);
435 }
436
437 InterfacePrefsType.tp_new = PyType_GenericNew;
438 if (PyType_Ready(&InterfacePrefsType) < 0)
439 return;
440
441 MainWidgetsType.tp_new = PyType_GenericNew;
442 if (PyType_Ready(&MainWidgetsType) < 0)
443 return;
444
445 m = Py_InitModule3("ui_utils", UiUtilsModule_methods,
446 "User interface information and utilities.");
447
448 Py_INCREF(&InterfacePrefsType);
449 PyModule_AddObject(m, "InterfacePrefs", (PyObject *) &InterfacePrefsType);
450
451 Py_INCREF(&MainWidgetsType);
452 PyModule_AddObject(m, "MainWidgets", (PyObject *) &MainWidgetsType);
453 }
454