[geany/geany-plugins] 2aec03: Add support for keybindings
Thomas Martitz
git-noreply at xxxxx
Sun Mar 6 12:26:50 UTC 2016
Branch: refs/heads/master
Author: Thomas Martitz <kugel at rockbox.org>
Committer: Thomas Martitz <kugel at rockbox.org>
Date: Sun, 06 Mar 2016 12:26:50 UTC
Commit: 2aec034029f9a84ab0777fa00b54560c8954e7e2
https://github.com/geany/geany-plugins/commit/2aec034029f9a84ab0777fa00b54560c8954e7e2
Log Message:
-----------
Add support for keybindings
geany.Plugin gains a method to create keybinding groups, which in turn
has a method to add key items (losely matching Geany's original API, but
heavily simplified).
Modified Paths:
--------------
geanypy/geany/__init__.py
geanypy/geany/plugin.py
geanypy/src/Makefile.am
geanypy/src/geanypy-keybindings.c
geanypy/src/geanypy-keybindings.h
geanypy/src/geanypy-plugin.c
Modified: geanypy/geany/__init__.py
2 lines changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -24,6 +24,7 @@
import search
import templates
import ui_utils
+import keybindings
from app import App
from prefs import Prefs, ToolPrefs
@@ -41,6 +42,7 @@
"main_widgets",
"interface_prefs",
"app",
+ "keybindings",
"general_prefs",
"search_prefs",
"template_prefs",
Modified: geanypy/geany/plugin.py
8 lines changed, 8 insertions(+), 0 deletions(-)
===================================================================
@@ -36,6 +36,7 @@ def cleanup(self):
files with a `.py` extension will be loaded.
"""
+import keybindings
class Plugin(object):
"""
@@ -120,3 +121,10 @@ def author(self):
return self.__plugin_author__
else:
return ""
+
+ def set_key_group(self, section_name, count, callback = None):
+ """
+ Sets up a GeanyKeyGroup for this plugin. You can use that group to add keybindings
+ with group.add_key_item().
+ """
+ return keybindings.set_key_group(self, section_name, count, callback)
Modified: geanypy/src/Makefile.am
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -23,6 +23,7 @@ geanypy_la_SOURCES = geanypy-app.c \
geanypy-highlighting.c \
geanypy-indentprefs.c \
geanypy-interfaceprefs.c \
+ geanypy-keybindings.c \
geanypy-main.c \
geanypy-mainwidgets.c \
geanypy-msgwindow.c \
Modified: geanypy/src/geanypy-keybindings.c
213 lines changed, 213 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,213 @@
+/*
+ * plugin.c
+ *
+ * Copyright 2015 Thomas Martitz <kugel at rockbox.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+
+#include "geanypy.h"
+#include "geanypy-keybindings.h"
+
+#include <glib.h>
+
+static gboolean call_key(gpointer *unused, guint key_id, gpointer data)
+{
+ PyObject *callback = data;
+ PyObject *args;
+
+ args = Py_BuildValue("(i)", key_id);
+ PyObject_CallObject(callback, args);
+ Py_DECREF(args);
+}
+
+
+/* plugin.py provides an OOP-style wrapper around this so call it like:
+ * class Foo(geany.Plugin):
+ * def __init__(self):
+ * self.set_key_group(...)
+ */
+static PyObject *
+Keybindings_set_key_group(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ static gchar *kwlist[] = { "plugin", "section_name", "count", "callback", NULL };
+ int count = 0;
+ const gchar *section_name = NULL;
+ GeanyKeyGroup *group = NULL;
+ PyObject *py_callback = NULL;
+ PyObject *py_ret = Py_None;
+ PyObject *py_plugin;
+ gboolean has_cb = FALSE;
+
+ Py_INCREF(Py_None);
+
+ if (PyArg_ParseTupleAndKeywords(args, kwargs, "Osi|O", kwlist,
+ &py_plugin, §ion_name, &count, &py_callback))
+ {
+ GeanyPlugin *plugin = plugin_get(py_plugin);
+ g_return_val_if_fail(plugin != NULL, Py_None);
+
+ has_cb = PyCallable_Check(py_callback);
+ if (has_cb)
+ {
+ Py_INCREF(py_callback);
+ group = plugin_set_key_group_full(plugin, section_name, count,
+ (GeanyKeyGroupFunc) call_key, py_callback,
+ (GDestroyNotify) Py_DecRef);
+ }
+ else
+ group = plugin_set_key_group(plugin, section_name, count, NULL);
+ }
+
+ if (group)
+ {
+ Py_DECREF(py_ret);
+ py_ret = KeyGroup_new_with_geany_key_group(group, has_cb);
+ }
+
+ return py_ret;
+}
+
+
+static PyObject *
+KeyGroup_add_key_item(KeyGroup *self, PyObject *args, PyObject *kwargs)
+{
+ static gchar *kwlist[] = { "name", "label", "callback", "key_id", "key", "mod" , "menu_item", NULL };
+ int id = -1;
+ int key = 0, mod = 0;
+ const gchar *name = NULL, *label = NULL;
+ PyObject *py_menu_item = NULL;
+ PyObject *py_callback = NULL;
+ GeanyKeyBinding *item = NULL;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwargs, "ss|OiiiO", kwlist,
+ &name, &label, &py_callback, &id, &key, &mod, &py_menu_item))
+ {
+ if (id == -1)
+ id = self->item_index;
+
+ GtkWidget *menu_item = (py_menu_item == NULL || py_menu_item == Py_None)
+ ? NULL : GTK_WIDGET(pygobject_get(py_menu_item));
+ if (PyCallable_Check(py_callback))
+ {
+ Py_INCREF(py_callback);
+ item = keybindings_set_item_full(self->kb_group, id, (guint) key,
+ (GdkModifierType) mod, name, label, menu_item,
+ (GeanyKeyBindingFunc) call_key, py_callback,
+ (GDestroyNotify) Py_DecRef);
+ }
+ else
+ {
+ if (!self->has_cb)
+ g_warning("Either KeyGroup or the Keybinding must have a callback\n");
+ else
+ item = keybindings_set_item(self->kb_group, id, NULL, (guint) key,
+ (GdkModifierType) mod, name, label, menu_item);
+ }
+ Py_XDECREF(py_menu_item);
+
+ self->item_index = id + 1;
+ }
+
+ if (item)
+ {
+ /* Return a tuple containing the key group and the opaque GeanyKeyBinding pointer.
+ * This is in preparation of allowing chained calls like
+ * set_kb_group(X, 3).add_key_item().add_key_item().add_key_item()
+ * without losing access to the keybinding pointer (might become necessary for newer
+ * Geany APIs).
+ * Note that the plain tuple doesn't support the above yet, we've got to subclass it,
+ * but we are prepared without breaking sub-plugins */
+ PyObject *ret = PyTuple_Pack(2, self, PyCapsule_New(item, "GeanyKeyBinding", NULL));
+ return ret;
+ }
+ Py_RETURN_NONE;
+}
+
+
+static PyMethodDef
+KeyGroup_methods[] = {
+ { "add_key_item", (PyCFunction)KeyGroup_add_key_item, METH_KEYWORDS,
+ "Adds an action to the plugin's key group" },
+ { NULL }
+};
+
+static PyMethodDef
+Keybindings_methods[] = {
+ { "set_key_group", (PyCFunction)Keybindings_set_key_group, METH_KEYWORDS,
+ "Sets up a GeanyKeybindingGroup for this plugin." },
+ { NULL }
+};
+
+
+static PyGetSetDef
+KeyGroup_getseters[] = {
+ { NULL },
+};
+
+
+static void
+KeyGroup_dealloc(KeyGroup *self)
+{
+ g_return_if_fail(self != NULL);
+ self->ob_type->tp_free((PyObject *) self);
+}
+
+
+static PyTypeObject KeyGroupType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ "geany.keybindings.KeyGroup", /* tp_name */
+ sizeof(KeyGroup), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor) KeyGroup_dealloc, /* tp_dealloc */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* tp_print - tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ "Wrapper around a GeanyKeyGroup structure." ,/* tp_doc */
+ 0, 0, 0, 0, 0, 0, /* tp_traverse - tp_iternext */
+ KeyGroup_methods, /* tp_methods */
+ 0, /* tp_members */
+ KeyGroup_getseters, /* tp_getset */
+ 0, 0, 0, 0, 0, /* tp_base - tp_dictoffset */
+ 0, 0, (newfunc) PyType_GenericNew, /* tp_init - tp_alloc, tp_new */
+};
+
+
+PyMODINIT_FUNC initkeybindings(void)
+{
+ PyObject *m;
+
+ if (PyType_Ready(&KeyGroupType) < 0)
+ return;
+
+ m = Py_InitModule3("keybindings", Keybindings_methods, "Keybindings support.");
+
+ Py_INCREF(&KeyGroupType);
+ PyModule_AddObject(m, "KeyGroup", (PyObject *)&KeyGroupType);
+}
+
+PyObject *KeyGroup_new_with_geany_key_group(GeanyKeyGroup *group, gboolean has_cb)
+{
+ KeyGroup *ret = PyObject_New(KeyGroup, &KeyGroupType);
+
+ ret->kb_group = group;
+ ret->has_cb = has_cb;
+ ret->item_index = 0;
+
+ return (PyObject *) ret;
+}
+
Modified: geanypy/src/geanypy-keybindings.h
39 lines changed, 39 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,39 @@
+/*
+ * geanypy-keybindings.h
+ *
+ * Copyright 2015 Thomas Martitz <kugel at rockbox.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+
+#ifndef GEANYPY_KEYBINDINGS_H
+#define GEANYPY_KEYBINDINGS_H
+
+#include <glib.h>
+
+typedef struct
+{
+ PyObject_HEAD
+ GeanyKeyGroup *kb_group;
+ gboolean has_cb;
+ gint item_index;
+} KeyGroup;
+
+extern PyObject *
+KeyGroup_new_with_geany_key_group(GeanyKeyGroup *group, gboolean has_cb);
+
+#endif /* GEANYPY_KEYBINDINGS_H */
Modified: geanypy/src/geanypy-plugin.c
3 lines changed, 3 insertions(+), 0 deletions(-)
===================================================================
@@ -26,6 +26,7 @@
#define INCLUDE_PYGOBJECT_ONCE_FULL
#include "geanypy.h"
+#include "geanypy-keybindings.h"
#include <glib.h>
#include <glib/gstdio.h>
@@ -49,6 +50,7 @@ PyMODINIT_FUNC initscintilla(void);
PyMODINIT_FUNC initsearch(void);
PyMODINIT_FUNC inittemplates(void);
PyMODINIT_FUNC initui_utils(void);
+PyMODINIT_FUNC initkeybindings(void);
static void
@@ -89,6 +91,7 @@ GeanyPy_start_interpreter(void)
initsearch();
inittemplates();
initui_utils();
+ initkeybindings();
#ifdef GEANYPY_WINDOWS
{ /* On windows, get path at runtime since we don't really know where
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
More information about the Plugins-Commits
mailing list