Merge lp:~bregma/geis/lp-617301 into lp:geis

Proposed by Stephen M. Webb
Status: Merged
Merged at revision: 142
Proposed branch: lp:~bregma/geis/lp-617301
Merge into: lp:geis
Diff against target: 2876 lines (+2731/-3)
21 files modified
.bzrignore (+1/-0)
ChangeLog (+12/-0)
Makefile.am (+1/-1)
configure.ac (+6/-2)
python/Makefile.am (+44/-0)
python/_geis_bindings/_geis_bindings.c (+165/-0)
python/geis/__init__.py (+234/-0)
python/geis/geis_v2.py (+640/-0)
python/pygeis (+136/-0)
python/run_pygeis (+11/-0)
tools/Makefile.am (+23/-0)
tools/geisview/Makefile.am (+46/-0)
tools/geisview/__init__.py (+24/-0)
tools/geisview/defaults.py.in (+62/-0)
tools/geisview/deviceview.py (+46/-0)
tools/geisview/filter_definition.py (+135/-0)
tools/geisview/filter_definition.ui (+329/-0)
tools/geisview/filter_list.py (+59/-0)
tools/geisview/filter_list.ui (+174/-0)
tools/geisview/geisview (+250/-0)
tools/geisview/geisview.ui (+333/-0)
To merge this branch: bzr merge lp:~bregma/geis/lp-617301
Reviewer Review Type Date Requested Status
Jussi Pakkanen (community) Needs Fixing
Review via email: mp+61883@code.launchpad.net

Description of the change

Added Python bindings and the start of a Python-based "geisview" tool to visualize gesture events.

To post a comment you must log in.
Revision history for this message
Jussi Pakkanen (jpakkane) wrote :

Looks fine, builds, installs and works. Some minor things:

Some Python files are still GPL 2+ (e.g. tools/geisview/defaults.py.in).

The documentation for Group says this:

class Group(object):
 """Represents a particular group."""

Since group is a very common word, maybe some clarification would be in order. What is this a group of, exactly?

review: Needs Fixing
lp:~bregma/geis/lp-617301 updated
153. By Stephen M. Webb

Fixed tools/geisview/defaults.py.in licensing and descriptive comment for geis.Group class.

154. By Stephen M. Webb

Fixed some pyflakes warnings.

155. By Stephen M. Webb

Silenced some pylint whinings.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2011-03-17 04:06:04 +0000
3+++ .bzrignore 2011-05-27 15:36:38 +0000
4@@ -21,6 +21,7 @@
5 debian/libutouch-geis1
6 debian/libutouch-geis1-dbg
7 debian/tmp
8+defaults.py
9 doc/api
10 doc/docbook-xsl.css
11 doc/geisspec-1.0.html
12
13=== modified file 'ChangeLog'
14--- ChangeLog 2011-05-03 16:29:45 +0000
15+++ ChangeLog 2011-05-27 15:36:38 +0000
16@@ -1,3 +1,15 @@
17+2011-03-31 Stephen M. Webb <stephen.webb@canonical.com>
18+
19+ Add initial python bindings.
20+
21+ * python/Makefile.am: new file
22+ * python/_geis_bindings/_geis_bindings.c: new file
23+ * python/geis/__init__.py: new file
24+ * python/geis/geis_v2.py: new file
25+ * python/pygeis: new script
26+ * Makefile.am (SUBDIRS): added python
27+ * configure.ac (AC_CONFIG_FILES): added new generated files
28+
29 2011-04-10 Stephen M. Webb <stephen.webb@canonical.com>
30
31 Repaired a callback persistence problem (LP: #754135).
32
33=== modified file 'Makefile.am'
34--- Makefile.am 2011-03-17 04:06:04 +0000
35+++ Makefile.am 2011-05-27 15:36:38 +0000
36@@ -21,7 +21,7 @@
37
38 ACLOCAL_MFLAGS = -I m4
39
40-SUBDIRS = include libs libutouch-geis testsuite examples doc
41+SUBDIRS = include libs libutouch-geis testsuite python tools examples doc
42
43 doc-%:
44 $(MAKE) -C doc $@
45
46=== modified file 'configure.ac'
47--- configure.ac 2011-05-05 08:20:51 +0000
48+++ configure.ac 2011-05-27 15:36:38 +0000
49@@ -31,7 +31,7 @@
50
51 # Checks for programs.
52 AM_PROG_CC_C_O
53-AM_PATH_PYTHON([2.5])
54+AM_PATH_PYTHON([2.7])
55
56 LT_PREREQ([2.2.6b])
57 LT_INIT
58@@ -47,6 +47,7 @@
59 AC_MSG_ERROR([X11-XCB development libraries not found]))
60 PKG_CHECK_MODULES([XI2], [xi >= 1.3], ,
61 AC_MSG_ERROR([XI2 development libraries not found]))
62+PKG_CHECK_MODULES([PYTHON], [python >= 2.7])
63
64 AX_ENABLE_XI2
65
66@@ -101,5 +102,8 @@
67 testsuite/geis2/Makefile
68 testsuite/geis1/Makefile
69 testsuite/geistest/Makefile
70- examples/Makefile])
71+ examples/Makefile
72+ python/Makefile
73+ tools/Makefile
74+ tools/geisview/Makefile])
75 AC_OUTPUT
76
77=== added directory 'python'
78=== added file 'python/Makefile.am'
79--- python/Makefile.am 1970-01-01 00:00:00 +0000
80+++ python/Makefile.am 2011-05-27 15:36:38 +0000
81@@ -0,0 +1,44 @@
82+#
83+# @file python/Makefile.am
84+# @brief automake recipe for the libgeis python bindings
85+#
86+# Copyright 2011 Canonical, Ltd.
87+#
88+# This file is part of the utouch-geis library. This library is free software;
89+# you can redistribute it and/or modify it under the terms of the GNU Lesser
90+# General Public License as published by the Free Software Foundation; either
91+# version 3 of the License, or (at your option) any later version.
92+#
93+# This library is distributed in the hope that it will be useful, but WITHOUT
94+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
95+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
96+# details.
97+#
98+# You should have received a copy of the GNU Lesser General Public License
99+# along with this program; if not, write to the Free Software Foundation, Inc.,
100+# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
101+
102+dist_bin_SCRIPTS = pygeis
103+
104+dist_noinst_SCRIPTS = run_pygeis
105+
106+nobase_python_PYTHON = \
107+ geis/__init__.py \
108+ geis/geis_v2.py
109+
110+pyexec_LTLIBRARIES = _geis_bindings.la
111+
112+_geis_bindings_la_SOURCES = \
113+ _geis_bindings/_geis_bindings.c
114+
115+_geis_bindings_la_CFLAGS = \
116+ -I$(top_srcdir)/include \
117+ -I$(top_srcdir)/libutouch-geis \
118+ $(PYTHON_CFLAGS)
119+
120+_geis_bindings_la_LDFLAGS = \
121+ -module -avoid-version \
122+ -export-symbols-regex init_geis_bindings \
123+ $(top_builddir)/libutouch-geis/libutouch-geis.la \
124+ $(PYTHON_LDFLAGS)
125+
126
127=== added directory 'python/_geis_bindings'
128=== added file 'python/_geis_bindings/_geis_bindings.c'
129--- python/_geis_bindings/_geis_bindings.c 1970-01-01 00:00:00 +0000
130+++ python/_geis_bindings/_geis_bindings.c 2011-05-27 15:36:38 +0000
131@@ -0,0 +1,165 @@
132+#include <Python.h>
133+
134+#include <geis/geis.h>
135+
136+
137+PyDoc_STRVAR(module_doc,
138+ "Low-level python bindings for libutouch-geis.\n"
139+ "Do not use this module directly "
140+ "-- the public API is provided by the 'geis' module."
141+);
142+
143+
144+static PyMethodDef exported_functions[] = {
145+ { NULL, NULL, 0, NULL }
146+};
147+
148+PyMODINIT_FUNC
149+init_geis_bindings(void)
150+{
151+ PyObject *this_module;
152+
153+ this_module = Py_InitModule3("_geis_bindings", exported_functions, module_doc);
154+ if (!this_module)
155+ return;
156+
157+ /* Global status values. */
158+ PyModule_AddIntConstant(this_module, "GEIS_STATUS_SUCCESS",
159+ GEIS_STATUS_SUCCESS);
160+ PyModule_AddIntConstant(this_module, "GEIS_STATUS_CONTINUE",
161+ GEIS_STATUS_CONTINUE);
162+ PyModule_AddIntConstant(this_module, "GEIS_STATUS_EMPTY",
163+ GEIS_STATUS_EMPTY);
164+ PyModule_AddIntConstant(this_module, "GEIS_STATUS_NOT_SUPPORTED",
165+ GEIS_STATUS_NOT_SUPPORTED);
166+ PyModule_AddIntConstant(this_module, "GEIS_STATUS_BAD_ARGUMENT",
167+ GEIS_STATUS_BAD_ARGUMENT);
168+ PyModule_AddIntConstant(this_module, "GEIS_STATUS_UNKNOWN_ERROR",
169+ GEIS_STATUS_UNKNOWN_ERROR);
170+
171+ /* Attribute types */
172+ PyModule_AddIntConstant(this_module, "GEIS_ATTR_TYPE_BOOLEAN",
173+ GEIS_ATTR_TYPE_BOOLEAN);
174+ PyModule_AddIntConstant(this_module, "GEIS_ATTR_TYPE_FLOAT",
175+ GEIS_ATTR_TYPE_FLOAT);
176+ PyModule_AddIntConstant(this_module, "GEIS_ATTR_TYPE_INTEGER",
177+ GEIS_ATTR_TYPE_INTEGER);
178+ PyModule_AddIntConstant(this_module, "GEIS_ATTR_TYPE_POINTER",
179+ GEIS_ATTR_TYPE_POINTER);
180+ PyModule_AddIntConstant(this_module, "GEIS_ATTR_TYPE_STRING",
181+ GEIS_ATTR_TYPE_STRING);
182+
183+ /* Initialization Options */
184+ PyModule_AddStringMacro(this_module, GEIS_INIT_SERVICE_PROVIDER);
185+ PyModule_AddStringMacro(this_module, GEIS_INIT_TRACK_DEVICES);
186+ PyModule_AddStringMacro(this_module, GEIS_INIT_TRACK_GESTURE_CLASSES);
187+ PyModule_AddStringMacro(this_module, GEIS_INIT_UTOUCH_MOCK_ENGINE);
188+ PyModule_AddStringMacro(this_module, GEIS_INIT_UTOUCH_XCB);
189+
190+ /* Configuration Items */
191+ PyModule_AddStringMacro(this_module, GEIS_CONFIGURATION_FD);
192+ PyModule_AddStringMacro(this_module, GEIS_CONFIG_UTOUCH_MAX_EVENTS);
193+
194+ /* Device Constants */
195+ PyModule_AddStringMacro(this_module, GEIS_EVENT_ATTRIBUTE_DEVICE);
196+ PyModule_AddStringMacro(this_module, GEIS_DEVICE_ATTRIBUTE_NAME);
197+ PyModule_AddStringMacro(this_module, GEIS_DEVICE_ATTRIBUTE_ID);
198+ PyModule_AddStringMacro(this_module, GEIS_DEVICE_ATTRIBUTE_TOUCHES);
199+ PyModule_AddStringMacro(this_module, GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH);
200+ PyModule_AddStringMacro(this_module, GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH);
201+
202+ /* Gesture Class Constants */
203+ PyModule_AddStringMacro(this_module, GEIS_EVENT_ATTRIBUTE_CLASS);
204+ PyModule_AddStringMacro(this_module, GEIS_CLASS_ATTRIBUTE_NAME);
205+ PyModule_AddStringMacro(this_module, GEIS_CLASS_ATTRIBUTE_ID);
206+
207+ /* Region Constants */
208+ PyModule_AddStringMacro(this_module, GEIS_REGION_ATTRIBUTE_WINDOWID);
209+ PyModule_AddStringMacro(this_module, GEIS_REGION_X11_ROOT);
210+ PyModule_AddStringMacro(this_module, GEIS_REGION_X11_WINDOWID);
211+
212+ /* Gesture Constants */
213+ PyModule_AddStringMacro(this_module, GEIS_EVENT_ATTRIBUTE_GROUPSET);
214+ PyModule_AddStringMacro(this_module, GEIS_EVENT_ATTRIBUTE_TOUCHSET);
215+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_ANGLE);
216+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA);
217+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_ANGULAR_VELOCITY);
218+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X1);
219+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X2);
220+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y1);
221+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y2);
222+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_CHILD_WINDOW_ID);
223+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_DELTA_X);
224+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_DELTA_Y);
225+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_DEVICE_ID);
226+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_EVENT_WINDOW_ID);
227+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_FOCUS_X);
228+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y);
229+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_GESTURE_NAME);
230+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_POSITION_X);
231+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_POSITION_Y);
232+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_RADIAL_VELOCITY);
233+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_RADIUS);
234+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA);
235+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_ROOT_WINDOW_ID);
236+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TAP_TIME);
237+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP);
238+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_0_ID);
239+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_0_X);
240+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_0_Y);
241+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_1_ID);
242+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_1_X);
243+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_1_Y);
244+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_2_ID);
245+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_2_X);
246+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_2_Y);
247+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_3_ID);
248+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_3_X);
249+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_3_Y);
250+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_4_ID);
251+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_4_X);
252+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCH_4_Y);
253+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_TOUCHES);
254+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_VELOCITY_X);
255+ PyModule_AddStringMacro(this_module, GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y);
256+ PyModule_AddStringMacro(this_module, GEIS_TOUCH_ATTRIBUTE_ID);
257+ PyModule_AddStringMacro(this_module, GEIS_TOUCH_ATTRIBUTE_X);
258+ PyModule_AddStringMacro(this_module, GEIS_TOUCH_ATTRIBUTE_Y);
259+
260+ /* Event Types */
261+ PyModule_AddIntConstant(this_module, "GEIS_EVENT_DEVICE_AVAILABLE",
262+ GEIS_EVENT_DEVICE_AVAILABLE);
263+ PyModule_AddIntConstant(this_module, "GEIS_EVENT_DEVICE_UNAVAILABLE",
264+ GEIS_EVENT_DEVICE_UNAVAILABLE);
265+ PyModule_AddIntConstant(this_module, "GEIS_EVENT_CLASS_AVAILABLE",
266+ GEIS_EVENT_CLASS_AVAILABLE);
267+ PyModule_AddIntConstant(this_module, "GEIS_EVENT_CLASS_CHANGED",
268+ GEIS_EVENT_CLASS_CHANGED);
269+ PyModule_AddIntConstant(this_module, "GEIS_EVENT_CLASS_UNAVAILABLE",
270+ GEIS_EVENT_CLASS_UNAVAILABLE);
271+ PyModule_AddIntConstant(this_module, "GEIS_EVENT_GESTURE_BEGIN",
272+ GEIS_EVENT_GESTURE_BEGIN);
273+ PyModule_AddIntConstant(this_module, "GEIS_EVENT_GESTURE_UPDATE",
274+ GEIS_EVENT_GESTURE_UPDATE);
275+ PyModule_AddIntConstant(this_module, "GEIS_EVENT_GESTURE_END",
276+ GEIS_EVENT_GESTURE_END);
277+ PyModule_AddIntConstant(this_module, "GEIS_EVENT_INIT_COMPLETE",
278+ GEIS_EVENT_INIT_COMPLETE);
279+ PyModule_AddIntConstant(this_module, "GEIS_EVENT_USER_DEFINED",
280+ GEIS_EVENT_USER_DEFINED);
281+ PyModule_AddIntConstant(this_module, "GEIS_EVENT_ERROR",
282+ GEIS_EVENT_ERROR);
283+
284+ /* Filtery Bits */
285+ PyModule_AddIntConstant(this_module, "GEIS_FILTER_DEVICE", GEIS_FILTER_DEVICE);
286+ PyModule_AddIntConstant(this_module, "GEIS_FILTER_CLASS", GEIS_FILTER_CLASS);
287+ PyModule_AddIntConstant(this_module, "GEIS_FILTER_REGION", GEIS_FILTER_REGION);
288+
289+ PyModule_AddIntConstant(this_module, "GEIS_FILTER_OP_EQ", GEIS_FILTER_OP_EQ);
290+ PyModule_AddIntConstant(this_module, "GEIS_FILTER_OP_NE", GEIS_FILTER_OP_NE);
291+ PyModule_AddIntConstant(this_module, "GEIS_FILTER_OP_GT", GEIS_FILTER_OP_GT);
292+ PyModule_AddIntConstant(this_module, "GEIS_FILTER_OP_GE", GEIS_FILTER_OP_GE);
293+ PyModule_AddIntConstant(this_module, "GEIS_FILTER_OP_LT", GEIS_FILTER_OP_LT);
294+ PyModule_AddIntConstant(this_module, "GEIS_FILTER_OP_LE", GEIS_FILTER_OP_LE);
295+}
296+
297
298=== added directory 'python/geis'
299=== added file 'python/geis/__init__.py'
300--- python/geis/__init__.py 1970-01-01 00:00:00 +0000
301+++ python/geis/__init__.py 2011-05-27 15:36:38 +0000
302@@ -0,0 +1,234 @@
303+# Copyright (C) 2011 Canonical Ltd
304+#
305+# This program is free software; you can redistribute it and/or modify
306+# it under the terms of the GNU General Public License as published by
307+# the Free Software Foundation; either version 3 of the License, or
308+# (at your option) any later version.
309+#
310+# This program is distributed in the hope that it will be useful,
311+# but WITHOUT ANY WARRANTY; without even the implied warranty of
312+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
313+# GNU General Public License for more details.
314+#
315+# You should have received a copy of the GNU General Public License
316+# along with this program; if not, write to the Free Software
317+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
318+
319+"""Python bindings for the GEIS gesture recognition interface.
320+"""
321+
322+__all__ = (
323+ 'Geis', 'Event', 'Filter', 'Subscription',
324+ 'NoMoreEvents',
325+ 'GEIS_STATUS_SUCCESS',
326+ 'GEIS_STATUS_CONTINUE',
327+ 'GEIS_STATUS_EMPTY',
328+ 'GEIS_STATUS_NOT_SUPPORTED',
329+ 'GEIS_STATUS_BAD_ARGUMENT',
330+ 'GEIS_STATUS_UNKNOWN_ERROR',
331+ 'GEIS_ATTR_TYPE_BOOLEAN',
332+ 'GEIS_ATTR_TYPE_FLOAT',
333+ 'GEIS_ATTR_TYPE_INTEGER',
334+ 'GEIS_ATTR_TYPE_POINTER',
335+ 'GEIS_ATTR_TYPE_STRING',
336+ 'GEIS_INIT_SERVICE_PROVIDER',
337+ 'GEIS_INIT_TRACK_DEVICES',
338+ 'GEIS_INIT_TRACK_GESTURE_CLASSES',
339+ 'GEIS_INIT_UTOUCH_MOCK_ENGINE',
340+ 'GEIS_INIT_UTOUCH_XCB',
341+ 'GEIS_CLASS_ATTRIBUTE_ID',
342+ 'GEIS_CLASS_ATTRIBUTE_NAME',
343+ 'GEIS_CONFIGURATION_FD',
344+ 'GEIS_CONFIG_UTOUCH_MAX_EVENTS',
345+ 'GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH',
346+ 'GEIS_DEVICE_ATTRIBUTE_ID',
347+ 'GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH',
348+ 'GEIS_DEVICE_ATTRIBUTE_NAME',
349+ 'GEIS_DEVICE_ATTRIBUTE_TOUCHES',
350+ 'GEIS_EVENT_ATTRIBUTE_CLASS',
351+ 'GEIS_EVENT_ATTRIBUTE_DEVICE',
352+ 'GEIS_EVENT_ATTRIBUTE_GROUPSET',
353+ 'GEIS_EVENT_ATTRIBUTE_GROUPSET',
354+ 'GEIS_EVENT_ATTRIBUTE_TOUCHSET',
355+ 'GEIS_EVENT_ATTRIBUTE_TOUCHSET',
356+ 'GEIS_EVENT_CLASS_AVAILABLE',
357+ 'GEIS_EVENT_CLASS_CHANGED',
358+ 'GEIS_EVENT_CLASS_UNAVAILABLE',
359+ 'GEIS_EVENT_DEVICE_AVAILABLE',
360+ 'GEIS_EVENT_DEVICE_UNAVAILABLE',
361+ 'GEIS_EVENT_ERROR',
362+ 'GEIS_EVENT_GESTURE_BEGIN',
363+ 'GEIS_EVENT_GESTURE_END',
364+ 'GEIS_EVENT_GESTURE_UPDATE',
365+ 'GEIS_EVENT_INIT_COMPLETE',
366+ 'GEIS_EVENT_USER_DEFINED',
367+ 'GEIS_GESTURE_ATTRIBUTE_ANGLE',
368+ 'GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA',
369+ 'GEIS_GESTURE_ATTRIBUTE_ANGULAR_VELOCITY',
370+ 'GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X1',
371+ 'GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X2',
372+ 'GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y1',
373+ 'GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y2',
374+ 'GEIS_GESTURE_ATTRIBUTE_CHILD_WINDOW_ID',
375+ 'GEIS_GESTURE_ATTRIBUTE_DELTA_X',
376+ 'GEIS_GESTURE_ATTRIBUTE_DELTA_Y',
377+ 'GEIS_GESTURE_ATTRIBUTE_DEVICE_ID',
378+ 'GEIS_GESTURE_ATTRIBUTE_EVENT_WINDOW_ID',
379+ 'GEIS_GESTURE_ATTRIBUTE_FOCUS_X',
380+ 'GEIS_GESTURE_ATTRIBUTE_FOCUS_Y',
381+ 'GEIS_GESTURE_ATTRIBUTE_GESTURE_NAME',
382+ 'GEIS_GESTURE_ATTRIBUTE_POSITION_X',
383+ 'GEIS_GESTURE_ATTRIBUTE_POSITION_Y',
384+ 'GEIS_GESTURE_ATTRIBUTE_RADIAL_VELOCITY',
385+ 'GEIS_GESTURE_ATTRIBUTE_RADIUS',
386+ 'GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA',
387+ 'GEIS_GESTURE_ATTRIBUTE_ROOT_WINDOW_ID',
388+ 'GEIS_GESTURE_ATTRIBUTE_TAP_TIME',
389+ 'GEIS_GESTURE_ATTRIBUTE_TIMESTAMP',
390+ 'GEIS_GESTURE_ATTRIBUTE_TOUCH_0_ID',
391+ 'GEIS_GESTURE_ATTRIBUTE_TOUCH_0_X',
392+ 'GEIS_GESTURE_ATTRIBUTE_TOUCH_0_Y',
393+ 'GEIS_GESTURE_ATTRIBUTE_TOUCH_1_ID',
394+ 'GEIS_GESTURE_ATTRIBUTE_TOUCH_1_X',
395+ 'GEIS_GESTURE_ATTRIBUTE_TOUCH_1_Y',
396+ 'GEIS_GESTURE_ATTRIBUTE_TOUCH_2_ID',
397+ 'GEIS_GESTURE_ATTRIBUTE_TOUCH_2_X',
398+ 'GEIS_GESTURE_ATTRIBUTE_TOUCH_2_Y',
399+ 'GEIS_GESTURE_ATTRIBUTE_TOUCH_3_ID',
400+ 'GEIS_GESTURE_ATTRIBUTE_TOUCH_3_X',
401+ 'GEIS_GESTURE_ATTRIBUTE_TOUCH_3_Y',
402+ 'GEIS_GESTURE_ATTRIBUTE_TOUCH_4_ID',
403+ 'GEIS_GESTURE_ATTRIBUTE_TOUCH_4_X',
404+ 'GEIS_GESTURE_ATTRIBUTE_TOUCH_4_Y',
405+ 'GEIS_GESTURE_ATTRIBUTE_TOUCHES',
406+ 'GEIS_GESTURE_ATTRIBUTE_VELOCITY_X',
407+ 'GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y',
408+ 'GEIS_REGION_ATTRIBUTE_WINDOWID',
409+ 'GEIS_REGION_X11_ROOT',
410+ 'GEIS_REGION_X11_WINDOWID',
411+ 'GEIS_TOUCH_ATTRIBUTE_ID',
412+ 'GEIS_TOUCH_ATTRIBUTE_ID',
413+ 'GEIS_TOUCH_ATTRIBUTE_X',
414+ 'GEIS_TOUCH_ATTRIBUTE_X',
415+ 'GEIS_TOUCH_ATTRIBUTE_Y',
416+ 'GEIS_TOUCH_ATTRIBUTE_Y',
417+ 'GEIS_FILTER_DEVICE',
418+ 'GEIS_FILTER_CLASS',
419+ 'GEIS_FILTER_REGION',
420+ 'GEIS_FILTER_OP_EQ',
421+ 'GEIS_FILTER_OP_NE',
422+ 'GEIS_FILTER_OP_GT',
423+ 'GEIS_FILTER_OP_GE',
424+ 'GEIS_FILTER_OP_LT',
425+ 'GEIS_FILTER_OP_LE',
426+ )
427+
428+from _geis_bindings import GEIS_STATUS_SUCCESS, \
429+ GEIS_STATUS_CONTINUE, \
430+ GEIS_STATUS_EMPTY, \
431+ GEIS_STATUS_NOT_SUPPORTED, \
432+ GEIS_STATUS_BAD_ARGUMENT, \
433+ GEIS_STATUS_UNKNOWN_ERROR
434+
435+from _geis_bindings import GEIS_ATTR_TYPE_BOOLEAN, \
436+ GEIS_ATTR_TYPE_FLOAT, \
437+ GEIS_ATTR_TYPE_INTEGER, \
438+ GEIS_ATTR_TYPE_POINTER, \
439+ GEIS_ATTR_TYPE_STRING
440+
441+from _geis_bindings import GEIS_INIT_SERVICE_PROVIDER, \
442+ GEIS_INIT_TRACK_DEVICES, \
443+ GEIS_INIT_TRACK_GESTURE_CLASSES, \
444+ GEIS_INIT_UTOUCH_MOCK_ENGINE, \
445+ GEIS_INIT_UTOUCH_XCB
446+
447+from _geis_bindings import GEIS_CONFIGURATION_FD, \
448+ GEIS_CONFIG_UTOUCH_MAX_EVENTS
449+
450+from _geis_bindings import GEIS_EVENT_ATTRIBUTE_DEVICE, \
451+ GEIS_DEVICE_ATTRIBUTE_NAME, \
452+ GEIS_DEVICE_ATTRIBUTE_ID, \
453+ GEIS_DEVICE_ATTRIBUTE_TOUCHES, \
454+ GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, \
455+ GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH
456+
457+from _geis_bindings import GEIS_EVENT_ATTRIBUTE_CLASS, \
458+ GEIS_CLASS_ATTRIBUTE_NAME, \
459+ GEIS_CLASS_ATTRIBUTE_ID
460+
461+from _geis_bindings import GEIS_REGION_ATTRIBUTE_WINDOWID, \
462+ GEIS_REGION_X11_ROOT, \
463+ GEIS_REGION_X11_WINDOWID
464+
465+from _geis_bindings import GEIS_EVENT_ATTRIBUTE_GROUPSET, \
466+ GEIS_EVENT_ATTRIBUTE_TOUCHSET, \
467+ GEIS_TOUCH_ATTRIBUTE_ID, \
468+ GEIS_TOUCH_ATTRIBUTE_X, \
469+ GEIS_TOUCH_ATTRIBUTE_Y
470+
471+from _geis_bindings import GEIS_EVENT_DEVICE_AVAILABLE, \
472+ GEIS_EVENT_DEVICE_UNAVAILABLE, \
473+ GEIS_EVENT_CLASS_AVAILABLE, \
474+ GEIS_EVENT_CLASS_CHANGED, \
475+ GEIS_EVENT_CLASS_UNAVAILABLE, \
476+ GEIS_EVENT_GESTURE_BEGIN, \
477+ GEIS_EVENT_GESTURE_UPDATE, \
478+ GEIS_EVENT_GESTURE_END, \
479+ GEIS_EVENT_INIT_COMPLETE, \
480+ GEIS_EVENT_USER_DEFINED, \
481+ GEIS_EVENT_ERROR
482+
483+from _geis_bindings import GEIS_GESTURE_ATTRIBUTE_ANGLE, \
484+ GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA, \
485+ GEIS_GESTURE_ATTRIBUTE_ANGULAR_VELOCITY, \
486+ GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X1, \
487+ GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X2, \
488+ GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y1, \
489+ GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y2, \
490+ GEIS_GESTURE_ATTRIBUTE_CHILD_WINDOW_ID, \
491+ GEIS_GESTURE_ATTRIBUTE_DELTA_X, \
492+ GEIS_GESTURE_ATTRIBUTE_DELTA_Y, \
493+ GEIS_GESTURE_ATTRIBUTE_DEVICE_ID, \
494+ GEIS_GESTURE_ATTRIBUTE_EVENT_WINDOW_ID, \
495+ GEIS_GESTURE_ATTRIBUTE_FOCUS_X, \
496+ GEIS_GESTURE_ATTRIBUTE_FOCUS_Y, \
497+ GEIS_GESTURE_ATTRIBUTE_GESTURE_NAME, \
498+ GEIS_GESTURE_ATTRIBUTE_POSITION_X, \
499+ GEIS_GESTURE_ATTRIBUTE_POSITION_Y, \
500+ GEIS_GESTURE_ATTRIBUTE_RADIAL_VELOCITY, \
501+ GEIS_GESTURE_ATTRIBUTE_RADIUS, \
502+ GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA, \
503+ GEIS_GESTURE_ATTRIBUTE_ROOT_WINDOW_ID, \
504+ GEIS_GESTURE_ATTRIBUTE_TAP_TIME, \
505+ GEIS_GESTURE_ATTRIBUTE_TIMESTAMP, \
506+ GEIS_GESTURE_ATTRIBUTE_TOUCH_0_ID, \
507+ GEIS_GESTURE_ATTRIBUTE_TOUCH_0_X, \
508+ GEIS_GESTURE_ATTRIBUTE_TOUCH_0_Y, \
509+ GEIS_GESTURE_ATTRIBUTE_TOUCH_1_ID, \
510+ GEIS_GESTURE_ATTRIBUTE_TOUCH_1_X, \
511+ GEIS_GESTURE_ATTRIBUTE_TOUCH_1_Y, \
512+ GEIS_GESTURE_ATTRIBUTE_TOUCH_2_ID, \
513+ GEIS_GESTURE_ATTRIBUTE_TOUCH_2_X, \
514+ GEIS_GESTURE_ATTRIBUTE_TOUCH_2_Y, \
515+ GEIS_GESTURE_ATTRIBUTE_TOUCH_3_ID, \
516+ GEIS_GESTURE_ATTRIBUTE_TOUCH_3_X, \
517+ GEIS_GESTURE_ATTRIBUTE_TOUCH_3_Y, \
518+ GEIS_GESTURE_ATTRIBUTE_TOUCH_4_ID, \
519+ GEIS_GESTURE_ATTRIBUTE_TOUCH_4_X, \
520+ GEIS_GESTURE_ATTRIBUTE_TOUCH_4_Y, \
521+ GEIS_GESTURE_ATTRIBUTE_TOUCHES, \
522+ GEIS_GESTURE_ATTRIBUTE_VELOCITY_X, \
523+ GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y
524+
525+from _geis_bindings import GEIS_FILTER_DEVICE, \
526+ GEIS_FILTER_CLASS, \
527+ GEIS_FILTER_REGION, \
528+ GEIS_FILTER_OP_EQ, \
529+ GEIS_FILTER_OP_NE, \
530+ GEIS_FILTER_OP_GT, \
531+ GEIS_FILTER_OP_GE, \
532+ GEIS_FILTER_OP_LT, \
533+ GEIS_FILTER_OP_LE
534+
535+from geis.geis_v2 import Geis, Event, Filter, Subscription, NoMoreEvents
536+
537
538=== added file 'python/geis/geis_v2.py'
539--- python/geis/geis_v2.py 1970-01-01 00:00:00 +0000
540+++ python/geis/geis_v2.py 2011-05-27 15:36:38 +0000
541@@ -0,0 +1,640 @@
542+# Copyright (C) 2011 Canonical Ltd
543+#
544+# This program is free software; you can redistribute it and/or modify
545+# it under the terms of the GNU General Public License as published by
546+# the Free Software Foundation; either version 3 of the License, or
547+# (at your option) any later version.
548+#
549+# This program is distributed in the hope that it will be useful,
550+# but WITHOUT ANY WARRANTY; without even the implied warranty of
551+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
552+# GNU General Public License for more details.
553+#
554+# You should have received a copy of the GNU General Public License
555+# along with this program; if not, write to the Free Software
556+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
557+
558+"""Python bindings for the GEIS v2 gesture recognition interface.
559+
560+Do not use this module directly -- the public API is provided by the 'geis'
561+module.
562+"""
563+
564+import ctypes
565+import ctypes.util
566+import _geis_bindings
567+import re
568+import sys
569+
570+
571+class GeisError(Exception):
572+ """ A general error has occurred internally in GEIS.
573+ """
574+ def __init__(self, reason):
575+ Exception.__init__(self, reason)
576+
577+
578+class NoMoreEvents(Exception):
579+ """ Raised by the event dispatch mechanism to indicate there are no
580+ pending events in the queue.
581+ """
582+
583+ def __init__(self):
584+ Exception.__init__(self, 'geis event queue is empty')
585+
586+
587+
588+def _check_null(ret, func, args):
589+ """ Converts a NULL pointer return value into an Exception.
590+ """
591+ if ret == 0:
592+ raise GeisError("%s failed" % func.__name__)
593+ return ret
594+
595+_EventCallback = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p,
596+ ctypes.py_object)
597+
598+_geis_lib = ctypes.CDLL(ctypes.util.find_library("utouch-geis"))
599+try:
600+ _geis_new = _geis_lib.geis_new
601+ _geis_new.restype = ctypes.c_void_p
602+ _geis_new.errcheck = _check_null
603+ _geis_delete = _geis_lib.geis_delete
604+ _geis_get_configuration = _geis_lib.geis_get_configuration
605+ _geis_dispatch_events = _geis_lib.geis_dispatch_events
606+ _geis_register_class_callback = _geis_lib.geis_register_class_callback
607+ _geis_register_device_callback = _geis_lib.geis_register_device_callback
608+ _geis_register_event_callback = _geis_lib.geis_register_event_callback
609+ _geis_next_event = _geis_lib.geis_next_event
610+
611+ _geis_subscription_new = _geis_lib.geis_subscription_new
612+ _geis_subscription_new.restype = ctypes.c_void_p
613+ _geis_subscription_new.errcheck = _check_null
614+ _geis_subscription_delete = _geis_lib.geis_subscription_delete
615+ _geis_subscription_activate = _geis_lib.geis_subscription_activate
616+ _geis_subscription_deactivate = _geis_lib.geis_subscription_deactivate
617+ _geis_subscription_name = _geis_lib.geis_subscription_name
618+
619+ _geis_attr_name = _geis_lib.geis_attr_name
620+ _geis_attr_name.restype = ctypes.c_char_p
621+ _geis_attr_type = _geis_lib.geis_attr_type
622+ _geis_attr_value_to_pointer = _geis_lib.geis_attr_value_to_pointer
623+
624+ _geis_event_type = _geis_lib.geis_event_type
625+ _geis_event_attr_count = _geis_lib.geis_event_attr_count
626+ _geis_event_attr = _geis_lib.geis_event_attr
627+ _geis_event_attr.restype = ctypes.c_void_p
628+
629+ _geis_gesture_class_unref = _geis_lib.geis_gesture_class_unref
630+ _geis_gesture_class_name = _geis_lib.geis_gesture_class_name
631+ _geis_gesture_class_name.restype = ctypes.c_char_p
632+ _geis_gesture_class_id = _geis_lib.geis_gesture_class_id
633+ _geis_gesture_class_attr_count = _geis_lib.geis_gesture_class_attr_count
634+ _geis_gesture_class_attr = _geis_lib.geis_gesture_class_attr
635+ _geis_gesture_class_attr.restype = ctypes.c_void_p
636+
637+ _geis_device_ref = _geis_lib.geis_device_ref
638+ _geis_device_unref = _geis_lib.geis_device_unref
639+ _geis_device_name = _geis_lib.geis_device_name
640+ _geis_device_name.restype = ctypes.c_char_p
641+ _geis_device_id = _geis_lib.geis_device_id
642+ _geis_device_attr_count = _geis_lib.geis_device_attr_count
643+ _geis_device_attr = _geis_lib.geis_device_attr
644+ _geis_device_attr.restype = ctypes.c_void_p
645+
646+ _geis_touchset_touch_count = _geis_lib.geis_touchset_touch_count
647+ _geis_touchset_touch = _geis_lib.geis_touchset_touch
648+ _geis_touchset_touch.restype = ctypes.c_void_p
649+
650+ _geis_touch_attr_count = _geis_lib.geis_touch_attr_count
651+ _geis_touch_attr = _geis_lib.geis_touch_attr
652+ _geis_touch_attr.restype = ctypes.c_void_p
653+
654+ _geis_groupset_group_count = _geis_lib.geis_groupset_group_count
655+ _geis_groupset_group = _geis_lib.geis_groupset_group
656+ _geis_groupset_group.restype = ctypes.c_void_p
657+
658+ _geis_group_frame_count = _geis_lib.geis_group_frame_count
659+ _geis_group_frame = _geis_lib.geis_group_frame
660+ _geis_group_frame.restype = ctypes.c_void_p
661+
662+ _geis_frame_attr_count = _geis_lib.geis_frame_attr_count
663+ _geis_frame_attr = _geis_lib.geis_frame_attr
664+ _geis_frame_attr.restype = ctypes.c_void_p
665+ _geis_frame_touchid_count = _geis_lib.geis_frame_touchid_count
666+ _geis_frame_touchid = _geis_lib.geis_frame_touchid
667+
668+except AttributeError as ex:
669+ print ex
670+ sys.exit(1)
671+
672+
673+class GestureClass(object):
674+ """Describes a class of gestures.
675+ """
676+
677+ def __init__(self, attr):
678+ self._class = _geis_attr_value_to_pointer(attr)
679+ self._id = _geis_gesture_class_id(self._class)
680+ self._name = _geis_gesture_class_name(self._class)
681+ self._attr_count = _geis_gesture_class_attr_count(self._class)
682+ self._attrs = {}
683+ for i in range(self._attr_count):
684+ attr = _geis_gesture_class_attr(self._class, i)
685+ attr_name = _geis_attr_name(attr)
686+ self._attrs[attr_name] = _attr_types.get(_geis_attr_type(attr),
687+ _attr_type_unknown)(attr)
688+
689+ def id(self):
690+ """ Gets the gesture class's system identifier (an integer).
691+ """
692+ return self._id
693+
694+ def name(self):
695+ """ Gets the gesture class's self-identified name.
696+ """
697+ return self._name
698+
699+ def attrs(self):
700+ """ Gets the named attributes associated with the gesture class.
701+ """
702+ return self._attrs
703+
704+
705+class Device(object):
706+ """Describes a touchable device.
707+ """
708+
709+ def __init__(self, attr):
710+ self._device = _geis_attr_value_to_pointer(attr)
711+ self._id = _geis_device_id(self._device)
712+ self._name = _geis_device_name(self._device)
713+ self._min_x = 0.0
714+ self._min_y = 0.0
715+ self._max_x = 0.0
716+ self._max_y = 0.0
717+ self._attr_count = _geis_device_attr_count(self._device)
718+ self._attrs = {}
719+ for i in range(self._attr_count):
720+ attr = _geis_device_attr(self._device, i)
721+ attr_name = _geis_attr_name(attr)
722+ self._attrs[attr_name] = _attr_types.get(_geis_attr_type(attr),
723+ _attr_type_unknown)(attr)
724+ if re.search("Abs MT Position X \d+ min", attr_name):
725+ self._min_x = self._attrs[attr_name]
726+ if re.search("Abs MT Position X \d+ max", attr_name):
727+ self._max_x = self._attrs[attr_name]
728+ if re.search("Abs MT Position Y \d+ min", attr_name):
729+ self._min_y = self._attrs[attr_name]
730+ if re.search("Abs MT Position Y \d+ max", attr_name):
731+ self._max_y = self._attrs[attr_name]
732+
733+ def id(self):
734+ """ Gets the device's system identifier (an integer).
735+ """
736+ return self._id
737+
738+ def name(self):
739+ """ Gets the device's self-identified name.
740+ """
741+ return self._name
742+
743+ def extents(self):
744+ """ Gets the device's defined extents (bounding box).
745+
746+ Returns: A tuple of (min X, min Y, max X, max Y).
747+ """
748+ return (self._min_x, self._min_y, self._max_x, self._max_y)
749+
750+ def attrs(self):
751+ """ Gets the named attributes associated with the device.
752+ """
753+ return self._attrs
754+
755+
756+class Touch(object):
757+ """Represents a particular touch."""
758+
759+ def __init__(self, touch):
760+ self._touch = touch
761+ self._attr_count = _geis_touch_attr_count(self._touch)
762+
763+ def id(self):
764+ """ Gets the persistent identifier of the touch.
765+ """
766+ return _geis_lib.geis_touch_id(self._touch)
767+
768+ def attrs(self):
769+ """ Gets the attributes of the touch.
770+ """
771+ attr_list = {}
772+ for i in range(self._attr_count):
773+ attr = _geis_touch_attr(self._touch, i)
774+ attr_name = _geis_attr_name(attr)
775+ attr_list[attr_name] = _attr_types.get(_geis_attr_type(attr),
776+ _attr_type_unknown)(attr)
777+ return attr_list
778+
779+
780+class Touchset(object):
781+ """A collection of Touch objects."""
782+
783+ def __init__(self, attr):
784+ self._touchset = _geis_attr_value_to_pointer(attr)
785+ self._count = _geis_touchset_touch_count(self._touchset)
786+ self._index = 0
787+
788+ def __len__(self):
789+ return self._count
790+
791+ def __iter__(self):
792+ return self
793+
794+ def next(self):
795+ """ Gets the next touch in the touchset as an iterable.
796+ """
797+ if self._index == self._count:
798+ raise StopIteration
799+ touch = Touch(_geis_touchset_touch(self._touchset, self._index))
800+ self._index = self._index + 1
801+ return touch
802+
803+
804+class Groupset(object):
805+ """A collection of Group objects."""
806+
807+ def __init__(self, attr):
808+ self._groupset = _geis_attr_value_to_pointer(attr)
809+ self._count = _geis_groupset_group_count(self._groupset)
810+ self._index = 0
811+
812+ def __len__(self):
813+ return self._count
814+
815+ def __iter__(self):
816+ return self
817+
818+ def next(self):
819+ """ Gets the next group in the groupset as an iterable.
820+ """
821+ if self._index == self._count:
822+ raise StopIteration
823+ touch = Group(_geis_groupset_group(self._groupset, self._index))
824+ self._index = self._index + 1
825+ return touch
826+
827+
828+class Group(object):
829+ """A set of Frame objects made up of a combination of touches."""
830+
831+ def __init__(self, group):
832+ self._group = group
833+ self._count = _geis_group_frame_count(self._group)
834+ self._index = 0
835+
836+ def __len__(self):
837+ return self._count
838+
839+ def __iter__(self):
840+ return self
841+
842+ def id(self):
843+ return _geis_lib.geis_group_id(self._group)
844+
845+ def next(self):
846+ """ Gets the next frame in the group as an iterable.
847+ """
848+ if self._index == self._count:
849+ raise StopIteration
850+ frame = Frame(_geis_group_frame(self._group, self._index))
851+ self._index = self._index + 1
852+ return frame
853+
854+
855+class Frame(object):
856+ """A gesture frame."""
857+
858+ def __init__(self, frame):
859+ self._frame = frame
860+
861+ def id(self):
862+ return _geis_lib.geis_frame_id(self._frame)
863+
864+ def attrs(self):
865+ attr_list = {}
866+ for i in range(_geis_frame_attr_count(self._frame)):
867+ attr = _geis_frame_attr(self._frame, i)
868+ attr_name = _geis_attr_name(attr)
869+ attr_list[attr_name] = _attr_types.get(_geis_attr_type(attr),
870+ _attr_type_unknown)(attr)
871+ return attr_list
872+
873+ def touches(self):
874+ touch_list = []
875+ for i in range(_geis_frame_touchid_count(self._frame)):
876+ touch_list.append(_geis_frame_touchid(self._frame, i))
877+ return touch_list
878+
879+
880+def _pointer_type_class(attr):
881+ """ Converts a generic attr into a GestureClass object.
882+ """
883+ return GestureClass(attr)
884+
885+
886+def _pointer_type_device(attr):
887+ """ Converts a generic attr into a Device object.
888+ """
889+ return Device(attr)
890+
891+
892+def _pointer_type_groupset(attr):
893+ """ Converts a generic attr into a Groupset object.
894+ """
895+ return Groupset(attr)
896+
897+
898+def _pointer_type_touchset(attr):
899+ """ Converts a generic attr into a Touchset object.
900+ """
901+ return Touchset(attr)
902+
903+
904+def _pointer_type_unknown(attr):
905+ print "unknown pointer type", _geis_attr_name(attr)
906+ return None
907+
908+
909+_attr_pointer_type = {
910+ _geis_bindings.GEIS_EVENT_ATTRIBUTE_CLASS: _pointer_type_class,
911+ _geis_bindings.GEIS_EVENT_ATTRIBUTE_DEVICE: _pointer_type_device,
912+ _geis_bindings.GEIS_EVENT_ATTRIBUTE_GROUPSET: _pointer_type_groupset,
913+ _geis_bindings.GEIS_EVENT_ATTRIBUTE_TOUCHSET: _pointer_type_touchset
914+}
915+
916+
917+def _attr_type_boolean(attr):
918+ """ Extracts an attribute value as a boolean.
919+ """
920+ return _geis_lib.geis_attr_value_to_boolean(attr)
921+
922+
923+def _attr_type_float(attr):
924+ """ Extracts an attribute value as a float.
925+ """
926+ geis_attr_value_to_float = _geis_lib.geis_attr_value_to_float
927+ geis_attr_value_to_float.restype = ctypes.c_float
928+ return geis_attr_value_to_float(attr)
929+
930+
931+def _attr_type_integer(attr):
932+ """ Extracts an attribute value as a integer.
933+ """
934+ return _geis_lib.geis_attr_value_to_integer(attr)
935+
936+
937+def _attr_type_pointer(attr):
938+ """ Extracts an attribute value as an object.
939+ """
940+ return _attr_pointer_type.get(_geis_attr_name(attr), _pointer_type_unknown)(attr)
941+
942+
943+def _attr_type_string(attr):
944+ """ Extracts an attribute value as a string.
945+ """
946+ geis_attr_value_to_string = _geis_lib.geis_attr_value_to_string
947+ geis_attr_value_to_string.restype = ctypes.c_char_p
948+ return geis_attr_value_to_string(attr)
949+
950+
951+def _attr_type_unknown(attr):
952+ print "unknown attr type", _geis_attr_name(attr)
953+ return None
954+
955+
956+_attr_types = {
957+ _geis_bindings.GEIS_ATTR_TYPE_BOOLEAN: _attr_type_boolean,
958+ _geis_bindings.GEIS_ATTR_TYPE_FLOAT: _attr_type_float,
959+ _geis_bindings.GEIS_ATTR_TYPE_INTEGER: _attr_type_integer,
960+ _geis_bindings.GEIS_ATTR_TYPE_POINTER: _attr_type_pointer,
961+ _geis_bindings.GEIS_ATTR_TYPE_STRING: _attr_type_string
962+}
963+
964+
965+def _cb_wrapper(ignored, eptr, context):
966+ """ A currying wrapper for event callbacks.
967+
968+ This is a currying function to wrap a Python callback with arbitrary
969+ arguments so it can be invoked from a C callback.
970+
971+ :param ignored: This argumenet is ignored.
972+ :param eptr: A C pointer to the internal GEIS event.
973+ :param context: A tuple containing the Geis class instance,
974+ the Python callable, and the argument list.
975+ """
976+ (geis_instance, cb, args) = context
977+ cb(geis_instance, Event(eptr), args[0])
978+
979+
980+class Geis(object):
981+ """A GEIS API instance.
982+ """
983+
984+ def __init__(self, *args):
985+ """Create a GEIS instance.
986+
987+ This constructor takes a variable number of arguments (zero or more)
988+ all of he geis.GEIS_INIT_... form.
989+
990+ On failure, an Exception is raised.
991+ """
992+ terminator = 0,
993+ va_args = args + terminator
994+ self._instance = _geis_new(*va_args)
995+ self._cb_wrapper = _EventCallback(_cb_wrapper)
996+ self._class_curry = None
997+ self._device_curry = None
998+ self._event_curry = None
999+
1000+ def __del__(self):
1001+ _geis_delete(self._instance)
1002+
1003+ @property
1004+ def _as_parameter_(self):
1005+ return self._instance
1006+
1007+ def get_configuration(self, item_name):
1008+ """ Gets a named configuration value. """
1009+ if (item_name == _geis_bindings.GEIS_CONFIGURATION_FD):
1010+ fd = ctypes.c_long()
1011+ status = _geis_get_configuration(self._instance,
1012+ item_name,
1013+ ctypes.byref(fd))
1014+ if status != _geis_bindings.GEIS_STATUS_SUCCESS:
1015+ raise GeisError('error retrieving GEIS fd')
1016+ return fd.value
1017+ raise ValueError('unsupported config item name')
1018+
1019+ def set_configuration(self, name, value):
1020+ """ Sets a named configuration value. """
1021+ raise ValueError('unsupported config item name')
1022+
1023+ def register_class_callback(self, callback, *args):
1024+ """ Registers a python callback to receive GEIS gesture class events.
1025+ """
1026+ context = self, callback, args
1027+ self._class_curry = ctypes.py_object(context)
1028+ _geis_register_class_callback(self._instance,
1029+ self._cb_wrapper,
1030+ self._class_curry)
1031+
1032+ def register_device_callback(self, callback, *args):
1033+ """ Registers a python callback to receive GEIS gesture device events.
1034+ """
1035+ context = self, callback, args
1036+ self._device_curry = ctypes.py_object(context)
1037+ _geis_register_device_callback(self._instance,
1038+ self._cb_wrapper,
1039+ self._device_curry)
1040+
1041+ def register_event_callback(self, callback, *args):
1042+ """ Registers a python callback to receive general GEIS events.
1043+ """
1044+ self._event_curry = ctypes.py_object((self, callback, args))
1045+ _geis_register_event_callback(self._instance,
1046+ self._cb_wrapper,
1047+ self._event_curry)
1048+
1049+ def dispatch_events(self):
1050+ """ Pumps the geis event loop. """
1051+ return _geis_dispatch_events(self._instance)
1052+
1053+ def next_event(self):
1054+ """ Pulls the next event, if any, off the geis event queue.
1055+
1056+ :return: a geis.Event object
1057+ :raise: geis.NoMoreEvents
1058+ """
1059+ event = Event()
1060+ status = _geis_next_event(self._instance, event)
1061+ if status not in [_geis_bindings.GEIS_STATUS_CONTINUE,
1062+ _geis_bindings.GEIS_STATUS_SUCCESS]:
1063+ raise NoMoreEvents()
1064+ return event
1065+
1066+
1067+class Event(object):
1068+ """ An event returned from the GEIS API.
1069+ """
1070+
1071+ def __init__(self, internal=ctypes.c_void_p()):
1072+ self._event = internal
1073+
1074+ @property
1075+ def _as_parameter_(self):
1076+ return ctypes.byref(self._event)
1077+
1078+ def type(self):
1079+ """ Gets the type of the event.
1080+ """
1081+ return _geis_event_type(self._event)
1082+
1083+ def attrs(self):
1084+ """ Gets the attributes associated with the event.
1085+ """
1086+ attr_list = {}
1087+ for i in range(_geis_event_attr_count(self._event)):
1088+ attr = _geis_event_attr(self._event, i)
1089+ attr_name = _geis_attr_name(attr)
1090+ attr_list[attr_name] = _attr_types.get(_geis_attr_type(attr),
1091+ _attr_type_unknown)(attr)
1092+ return attr_list
1093+
1094+
1095+class Filter(object):
1096+ """ A Geis Filter object.
1097+ """
1098+
1099+ def __init__(self, geis, name):
1100+ self._filter = _geis_lib.geis_filter_new(geis, name)
1101+
1102+ def __del__(self):
1103+ _geis_lib.geis_filter_delete(self._filter)
1104+
1105+ @property
1106+ def _as_parameter_(self):
1107+ return self._filter
1108+
1109+ def name(self):
1110+ """ Gets the name of the filter.
1111+ """
1112+ return _geis_lib.geis_filter_name(self._filter)
1113+
1114+ def add_term(self, facility, *terms):
1115+ """ Adds a new term to the filter.
1116+
1117+ :param facility: the filter facility to which the terms belong
1118+ :param terms: a collection of (name, operation, value) tuples
1119+ """
1120+ for term in terms:
1121+ if len(term) != 3:
1122+ raise ValueError('invalid filter term')
1123+ name, op, value = term
1124+ _geis_lib.geis_filter_add_term(self._filter, facility,
1125+ name, op, value,
1126+ 0)
1127+
1128+
1129+class Subscription(object):
1130+ """ A Geis subscription object.
1131+ """
1132+
1133+ def __init__(self, geis):
1134+ """Constructs a GEIS subscription object.
1135+
1136+ A subscription is a request to the gesture recognizer to receive gesture
1137+ events.
1138+
1139+ The default subscription is to receive all events from all devices for
1140+ all regions. The domain of the events received can be restructed
1141+ through the use of filters.
1142+
1143+ :param geis: The GEIS v2 instance.
1144+ :raise: Exception
1145+ """
1146+ object.__init__(self)
1147+ self._sub = _geis_subscription_new(geis, "py", 0)
1148+
1149+ def __del__(self):
1150+ _geis_subscription_delete(self._sub)
1151+
1152+ def activate(self):
1153+ """ Activates the subscription.
1154+ """
1155+ _geis_subscription_activate(self._sub)
1156+
1157+ def deactivate(self):
1158+ """ Deactivates the subscription.
1159+ """
1160+ _geis_subscription_deactivate(self._sub)
1161+
1162+ def name(self):
1163+ """ Gets the name of the subscription.
1164+ """
1165+ return _geis_subscription_name(self._sub)
1166+
1167+ def add_filter(self, filt):
1168+ """Adds a filter to the subscription.
1169+
1170+ :param filter: the filter to add
1171+ """
1172+ _geis_lib.geis_subscription_add_filter(self._sub, filt)
1173+
1174+ def remove_filter(self, filt):
1175+ """ Removes a filter from the subscription.
1176+
1177+ :param filter: the filter to remove
1178+ """
1179+ _geis_lib.geis_subscription_remove_filter(self._sub, filt)
1180+
1181+
1182
1183=== added file 'python/pygeis'
1184--- python/pygeis 1970-01-01 00:00:00 +0000
1185+++ python/pygeis 2011-05-27 15:36:38 +0000
1186@@ -0,0 +1,136 @@
1187+#!/usr/bin/python
1188+#
1189+# @file pygies
1190+# @brief a demo/test program for the GEIS python bindings
1191+#
1192+# Copyright (C) 2011 Canonical Ltd
1193+#
1194+# This program is free software; you can redistribute it and/or modify
1195+# it under the terms of the GNU General Public License as published by
1196+# the Free Software Foundation; either version 3 of the License, or
1197+# (at your option) any later version.
1198+#
1199+# This program is distributed in the hope that it will be useful,
1200+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1201+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1202+# GNU General Public License for more details.
1203+#
1204+# You should have received a copy of the GNU General Public License
1205+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1206+#
1207+
1208+import argparse
1209+import geis
1210+import glib
1211+import sys
1212+
1213+
1214+def _print_gesture(attrs):
1215+ touchset = attrs[geis.GEIS_EVENT_ATTRIBUTE_TOUCHSET]
1216+ groupset = attrs[geis.GEIS_EVENT_ATTRIBUTE_GROUPSET]
1217+ print " touches (" + str(len(touchset)) + "):"
1218+ for touch in touchset:
1219+ print " ", touch.id(), touch.attrs()
1220+ print " groups:"
1221+ for group in groupset:
1222+ print " ", group.id(), ":"
1223+ for frame in group:
1224+ print " frame ", frame.id(), ":"
1225+ for (k, v) in frame.attrs().iteritems():
1226+ print " " + k + ":", v
1227+ print " touches: ", frame.touches()
1228+
1229+def _do_init_complete(event, sub):
1230+ print "init complete"
1231+ sub.activate()
1232+
1233+def _do_device_available(event, sub):
1234+ print "device available"
1235+
1236+def _do_gesture_begin(event, sub):
1237+ print "gesture begin"
1238+ _print_gesture(event.attrs())
1239+
1240+def _do_gesture_update(event, sub):
1241+ print "gesture update"
1242+ _print_gesture(event.attrs())
1243+
1244+def _do_gesture_end(event, sub):
1245+ print "gesture end"
1246+ _print_gesture(event.attrs())
1247+
1248+def _do_other_event(event, sub):
1249+ print "unknown geis event received"
1250+
1251+_geis_event_action = {
1252+ geis.GEIS_EVENT_INIT_COMPLETE: _do_init_complete,
1253+ geis.GEIS_EVENT_DEVICE_AVAILABLE: _do_device_available,
1254+ geis.GEIS_EVENT_GESTURE_BEGIN: _do_gesture_begin,
1255+ geis.GEIS_EVENT_GESTURE_UPDATE: _do_gesture_update,
1256+ geis.GEIS_EVENT_GESTURE_END: _do_gesture_end
1257+}
1258+
1259+
1260+def _dispatch_geis_events(fd, condition, g):
1261+ """ Performs GEIS event loop processing. """
1262+ status = g.dispatch_events()
1263+ while status == geis.GEIS_STATUS_CONTINUE:
1264+ status = g.dispatch_events()
1265+
1266+ try:
1267+ while True:
1268+ event = g.next_event()
1269+ _geis_event_action.get(event.type(), _do_other_event)(event, None)
1270+ except geis.NoMoreEvents:
1271+ pass
1272+ return True
1273+
1274+
1275+def _class_callback(g, event, sub):
1276+ if event.type() == geis.GEIS_EVENT_CLASS_AVAILABLE:
1277+ gclass = event.attrs()[geis.GEIS_EVENT_ATTRIBUTE_CLASS]
1278+ name = gclass.name()
1279+ print ".. adding class %s" % name
1280+ filt = geis.Filter(g, name)
1281+ filt.add_term(geis.GEIS_FILTER_CLASS,
1282+ (geis.GEIS_CLASS_ATTRIBUTE_NAME, geis.GEIS_FILTER_OP_EQ, name),
1283+ (geis.GEIS_GESTURE_ATTRIBUTE_TOUCHES, geis.GEIS_FILTER_OP_GT, 2))
1284+ sub.add_filter(filt)
1285+
1286+
1287+def _event_callback(geis, event, sub):
1288+ _geis_event_action.get(event.type(), _do_other_event)(event, sub)
1289+
1290+
1291+class Options(argparse.ArgumentParser):
1292+
1293+ def __init__(self):
1294+ argparse.ArgumentParser.__init__(self,
1295+ description="monitor uTouch gestures")
1296+ self.add_argument('-V', '--version', action='version', version='1.0')
1297+
1298+
1299+if __name__ == '__main__':
1300+ options = Options()
1301+ try:
1302+ options.parse_args()
1303+ except argparse.ArgumentError, ex:
1304+ print ex
1305+ sys.exit(1)
1306+
1307+ g = geis.Geis(geis.GEIS_INIT_TRACK_DEVICES,
1308+ geis.GEIS_INIT_TRACK_GESTURE_CLASSES)
1309+ geis_fd = g.get_configuration(geis.GEIS_CONFIGURATION_FD)
1310+ sub = geis.Subscription(g)
1311+ g.register_class_callback(_class_callback, sub)
1312+ g.register_event_callback(_event_callback, sub)
1313+
1314+ try:
1315+ ml = glib.MainLoop()
1316+ glib.io_add_watch(geis_fd, glib.IO_IN, _dispatch_geis_events, g)
1317+ ml.run()
1318+
1319+ except KeyboardInterrupt:
1320+ pass
1321+
1322+
1323
1324=== added file 'python/run_pygeis'
1325--- python/run_pygeis 1970-01-01 00:00:00 +0000
1326+++ python/run_pygeis 2011-05-27 15:36:38 +0000
1327@@ -0,0 +1,11 @@
1328+#!/bin/sh
1329+#
1330+# Runs the pygeis program from inside the build tree.
1331+#
1332+tool_path=$(dirname $0)
1333+
1334+LD_LIBRARY_PATH=$tool_path/../libutouch-geis/.libs
1335+PYTHONPATH=$tool_path/.libs
1336+
1337+export LD_LIBRARY_PATH PYTHONPATH
1338+$tool_path/pygeis "$@"
1339
1340=== added directory 'tools'
1341=== added file 'tools/Makefile.am'
1342--- tools/Makefile.am 1970-01-01 00:00:00 +0000
1343+++ tools/Makefile.am 2011-05-27 15:36:38 +0000
1344@@ -0,0 +1,23 @@
1345+#
1346+# @file tools/Makefile.am
1347+# @brief automake recipe for the GEIS tools
1348+#
1349+#
1350+# Copyright 2011 Canonical, Ltd.
1351+#
1352+# This file is part of the utouch-geis library. This library is free software;
1353+# you can redistribute it and/or modify it under the terms of the GNU Lesser
1354+# General Public License as published by the Free Software Foundation; either
1355+# version 3 of the License, or (at your option) any later version.
1356+#
1357+# This library is distributed in the hope that it will be useful, but WITHOUT
1358+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1359+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
1360+# details.
1361+#
1362+# You should have received a copy of the GNU General Public License
1363+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1364+#
1365+
1366+SUBDIRS = geisview
1367+
1368
1369=== added directory 'tools/geisview'
1370=== added file 'tools/geisview/Makefile.am'
1371--- tools/geisview/Makefile.am 1970-01-01 00:00:00 +0000
1372+++ tools/geisview/Makefile.am 2011-05-27 15:36:38 +0000
1373@@ -0,0 +1,46 @@
1374+#
1375+# @file tools/geisview/Makefile.am
1376+# @brief automake recipe for the geisview tool
1377+#
1378+# Copyright 2011 Canonical, Ltd.
1379+#
1380+# This file is part of the utouch-geis library. This library is free software;
1381+# you can redistribute it and/or modify it under the terms of the GNU Lesser
1382+# General Public License as published by the Free Software Foundation; either
1383+# version 3 of the License, or (at your option) any later version.
1384+#
1385+# This library is distributed in the hope that it will be useful, but WITHOUT
1386+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1387+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
1388+# details.
1389+#
1390+# You should have received a copy of the GNU Lesser General Public License
1391+# along with this program; if not, write to the Free Software Foundation, Inc.,
1392+# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1393+
1394+geisviewdir = $(pythondir)/geisview
1395+shareddir = $(datadir)/geisview
1396+xdgdir = $(datadir)/applications
1397+
1398+dist_bin_SCRIPTS = geisview
1399+dist_shared_DATA = \
1400+ geisview.ui \
1401+ filter_definition.ui \
1402+ filter_list.ui
1403+
1404+geisview_PYTHON = \
1405+ __init__.py \
1406+ defaults.py \
1407+ deviceview.py \
1408+ filter_definition.py \
1409+ filter_list.py
1410+
1411+defaults.py: defaults.py.in Makefile
1412+ $(AM_V_GEN)$(SED) \
1413+ -e 's,[@]shareddir[@],$(shareddir),g' \
1414+ $< >$@
1415+
1416+BUILT_SOURCES = defaults.py
1417+EXTRA_DIST = defaults.py.in
1418+CLEANFILES = $(BUILT_SOURCES)
1419+
1420
1421=== added file 'tools/geisview/__init__.py'
1422--- tools/geisview/__init__.py 1970-01-01 00:00:00 +0000
1423+++ tools/geisview/__init__.py 2011-05-27 15:36:38 +0000
1424@@ -0,0 +1,24 @@
1425+#!/usr/bin/python
1426+#
1427+# @file geisview/__init__.py
1428+# @brief Module __init__ for geisview
1429+#
1430+# This program is a handy diagnostic tool for viewing the raw data produced
1431+# through the GEIS multi-touch and gesture interface.
1432+#
1433+# Copyright (C) 2011 Canonical Ltd
1434+#
1435+# This program is free software; you can redistribute it and/or modify
1436+# it under the terms of the GNU General Public License as published by
1437+# the Free Software Foundation; either version 3 of the License, or
1438+# (at your option) any later version.
1439+#
1440+# This program is distributed in the hope that it will be useful,
1441+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1442+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1443+# GNU General Public License for more details.
1444+#
1445+# You should have received a copy of the GNU General Public License
1446+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1447+#
1448+
1449
1450=== added file 'tools/geisview/defaults.py.in'
1451--- tools/geisview/defaults.py.in 1970-01-01 00:00:00 +0000
1452+++ tools/geisview/defaults.py.in 2011-05-27 15:36:38 +0000
1453@@ -0,0 +1,62 @@
1454+#
1455+# @file geisview/defaults.py
1456+# @brief Default values for geisview.
1457+#
1458+# Copyright (C) 2011 Canonical Ltd
1459+#
1460+# This program is free software; you can redistribute it and/or modify
1461+# it under the terms of the GNU General Public License as published by
1462+# the Free Software Foundation; either version 3 of the License, or
1463+# (at your option) any later version.
1464+#
1465+# This program is distributed in the hope that it will be useful,
1466+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1467+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1468+# GNU General Public License for more details.
1469+#
1470+# You should have received a copy of the GNU General Public License
1471+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1472+#
1473+
1474+import os
1475+import gettext
1476+
1477+
1478+root_dir = os.path.dirname(__file__)
1479+if os.path.exists(os.path.join(root_dir, "Makefile.am")):
1480+ # running in source directory
1481+ data_dir = root_dir
1482+ locale_dir = os.path.join(data_dir, "locale")
1483+ ui_dir = data_dir
1484+else:
1485+ # running from installed
1486+ data_dir = os.path.join("@shareddir@")
1487+ locale_dir = os.path.join(data_dir, "locale")
1488+ ui_dir = data_dir
1489+
1490+
1491+i18n_domain = "geisview"
1492+gettext.bindtextdomain(i18n_domain, locale_dir)
1493+gettext.textdomain(i18n_domain)
1494+from gettext import gettext as _
1495+
1496+version = "1.0"
1497+appname = _("GEIS Viewer")
1498+appname_short = _("geisview")
1499+copyright = 'Copyright 2011 Canonical, Ltd.'
1500+description = _("A GEIS data viewer.\n\nGEIS Viewer is a part of "
1501+ "the Canonical uTouch gesture recognition stack.")
1502+authors = ["Stephen M. Webb <stephen.webb@canonical.com"]
1503+
1504+LICENSE = _("%s is free software; you can redistribute it and/or modify "
1505+ "it under the terms of the GNU General Public License as published by "
1506+ "the Free Software Foundation; either version 2 of the License, or "
1507+ "(at your option) any later version.\n\n").replace("%s", appname),
1508+_("%s is distributed in the hope that it will be useful, "
1509+ "but WITHOUT ANY WARRANTY; without even the implied warranty of "
1510+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the "
1511+ "GNU General Public License for more details.\n\n").replace("%s", appname),
1512+_("You should have received a copy of the GNU General Public License "
1513+ "along with this program. If not, see <http://www.gnu.org/licenses/>.")
1514+
1515+
1516
1517=== added file 'tools/geisview/deviceview.py'
1518--- tools/geisview/deviceview.py 1970-01-01 00:00:00 +0000
1519+++ tools/geisview/deviceview.py 2011-05-27 15:36:38 +0000
1520@@ -0,0 +1,46 @@
1521+#
1522+# @file geisview/deviceview.py
1523+# @brief Device viewer for geisview.
1524+#
1525+# Copyright (C) 2011 Canonical Ltd
1526+#
1527+# This program is free software; you can redistribute it and/or modify
1528+# it under the terms of the GNU General Public License as published by
1529+# the Free Software Foundation; either version 3 of the License, or
1530+# (at your option) any later version.
1531+#
1532+# This program is distributed in the hope that it will be useful,
1533+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1534+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1535+# GNU General Public License for more details.
1536+#
1537+# You should have received a copy of the GNU General Public License
1538+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1539+#
1540+
1541+import pygtk
1542+pygtk.require('2.0')
1543+import gtk
1544+
1545+class DeviceView(gtk.Window):
1546+
1547+ def __init__(self, devices):
1548+ gtk.Window.__init__(self)
1549+ self.set_title("GEIS Devices")
1550+ self.set_size_request(200, 200)
1551+
1552+ self._devices = devices
1553+ self._tree_store = gtk.TreeStore(str)
1554+ for device in devices:
1555+ it = self._tree_store.append(None, ["%s" % device])
1556+ self._tree_view = gtk.TreeView(self._tree_store)
1557+ self._tree_view.set_mode(gtk.SELECTION_SINGLE)
1558+ cell = gtk.CellRendererText()
1559+ col = gtk.TreeViewColumn('Label')
1560+ col.pack_start(cell, True)
1561+ col.add_attribute(cell, 'text', 0)
1562+ self._tree_view.append_column(col)
1563+
1564+ self.add(self._tree_view)
1565+ self.show_all()
1566+
1567
1568=== added file 'tools/geisview/filter_definition.py'
1569--- tools/geisview/filter_definition.py 1970-01-01 00:00:00 +0000
1570+++ tools/geisview/filter_definition.py 2011-05-27 15:36:38 +0000
1571@@ -0,0 +1,135 @@
1572+#
1573+# @file geisview/filter_definition.py
1574+# @brief A GEIS filter definition dialog
1575+#
1576+# Copyright (C) 2011 Canonical Ltd
1577+#
1578+# This program is free software; you can redistribute it and/or modify
1579+# it under the terms of the GNU General Public License as published by
1580+# the Free Software Foundation; either version 3 of the License, or
1581+# (at your option) any later version.
1582+#
1583+# This program is distributed in the hope that it will be useful,
1584+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1585+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1586+# GNU General Public License for more details.
1587+#
1588+# You should have received a copy of the GNU General Public License
1589+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1590+#
1591+
1592+import geis
1593+import geisview.defaults
1594+import os
1595+import pygtk
1596+pygtk.require("2.0")
1597+import gtk
1598+
1599+# A list of filter facilities to choose from
1600+geis_filter_facilities = ('GEIS_FILTER_REGION',
1601+ 'GEIS_FILTER_DEVICE',
1602+ 'GEIS_FILTER_CLASS')
1603+
1604+geis_region_terms = ('GEIS_REGION_ATTRIBUTE_WINDOWID')
1605+
1606+geis_device_terms = ('GEIS_DEVICE_ATTRIBUTE_ID',
1607+ 'GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH')
1608+
1609+geis_gesture_terms = ('GEIS_GESTURE_ATTRIBUTE_TOUCHES',
1610+ 'GEIS_CLASS_ATTRIBUTE_NAME')
1611+
1612+geis_term_op = {'GEIS_FILTER_OP_EQ': '==',
1613+ 'GEIS_FILTER_OP_NE': '!=',
1614+ 'GEIS_FILTER_OP_GT': '>',
1615+ 'GEIS_FILTER_OP_GE': '>=',
1616+ 'GEIS_FILTER_OP_LT': '<',
1617+ 'GEIS_FILTER_OP_LE': '<='}
1618+
1619+facility_combo_name_col = 0
1620+facility_combo_value_col = 1
1621+
1622+
1623+def populate_term_op(store):
1624+ for (name, symbol) in geis_term_op:
1625+ row = store.append()
1626+ store.set(row, symbol, geis.__dict__[name])
1627+
1628+
1629+class FilterDefinition(object):
1630+
1631+ def __init__(self):
1632+ print "FilterDefinition.__init__() begins"
1633+ builder = gtk.Builder()
1634+ builder.add_from_file(os.path.join(geisview.defaults.ui_dir,
1635+ "filter_definition.ui"))
1636+ builder.connect_signals(self)
1637+
1638+ # prime the name field
1639+ self._dialog = builder.get_object("filter_definition");
1640+ self._name_entry = builder.get_object("name_entry");
1641+
1642+ # prime the facility combo
1643+ self._facility_store = builder.get_object("facility_store");
1644+ for fac in geis_filter_facilities:
1645+ row = self._facility_store.append()
1646+ self._facility_store.set(row,
1647+ facility_combo_name_col, fac,
1648+ facility_combo_value_col, geis.__dict__[fac])
1649+ self._facility_combo = builder.get_object("facility_combo");
1650+ self._facility_combo.set_active(0)
1651+
1652+ # prime the filter terms
1653+ self._term_list_view = builder.get_object("term_list_view");
1654+ self._term_list_store = builder.get_object("term_list_store")
1655+
1656+ self._ok_button = builder.get_object("ok_button");
1657+ self._dialog.show_all()
1658+ print "FilterDefinition.__init__() ends"
1659+
1660+ def run(self):
1661+ print "FilterDefinition.run() begins"
1662+ response = self._dialog.run()
1663+ if (response):
1664+ name = self._name_entry.get_text()
1665+ print "FilterDefinition.run() name=%s" % name
1666+ print "FilterDefinition.run() facility=%s" % self._facility_store[self._facility_combo.get_active()][facility_combo_value_col]
1667+ self._dialog.destroy()
1668+ print "FilterDefinition.run() ends, response=%s" % response
1669+
1670+ def on_name_changed(self, widget, data=None):
1671+ name = self._name_entry.get_text()
1672+ if len(name) > 0:
1673+ self._ok_button.set_sensitive(True)
1674+ else:
1675+ self._ok_button.set_sensitive(False)
1676+
1677+ def on_add_term(self, widget, data=None):
1678+ print "FilterDefinition.on_add_term()"
1679+ row = self._term_list_store.append()
1680+ self._term_list_store.set(row,
1681+ 0, "<attr name>",
1682+ 1, "==",
1683+ 2, "<value>")
1684+
1685+ def on_edit_term(self, widget, data=None):
1686+ print "FilterDefinition.on_edit_term()"
1687+
1688+ def on_remove_term(self, widget, data=None):
1689+ print "FilterDefinition.on_remove_term()"
1690+
1691+ def on_term_attr_editing_started(self, widget, entry, path, data=None):
1692+ print "FilterDefinition.on_term_attr_editing_started()"
1693+ choices = gtk.ListStore(str, str)
1694+ for c in geis_gesture_terms:
1695+ choices.append([c, geis.__dict__[c]])
1696+ completion = gtk.EntryCompletion()
1697+ completion.set_model(choices)
1698+ completion.set_text_column(0)
1699+ completion.set_inline_completion(True)
1700+ completion.set_popup_completion(False)
1701+ entry.set_completion(completion)
1702+ entry.set_text("")
1703+
1704+ def on_term_op_edited(self, widget, path, new_text, data=None):
1705+ print "FilterDefinition.on_term_op_edited(%s, %s, %s)" % (widget, path, new_text)
1706+
1707
1708=== added file 'tools/geisview/filter_definition.ui'
1709--- tools/geisview/filter_definition.ui 1970-01-01 00:00:00 +0000
1710+++ tools/geisview/filter_definition.ui 2011-05-27 15:36:38 +0000
1711@@ -0,0 +1,329 @@
1712+<?xml version="1.0" encoding="UTF-8"?>
1713+<interface>
1714+ <requires lib="gtk+" version="2.24"/>
1715+ <!-- interface-naming-policy project-wide -->
1716+ <object class="GtkListStore" id="facility_store">
1717+ <columns>
1718+ <!-- column-name name -->
1719+ <column type="gchararray"/>
1720+ <!-- column-name value -->
1721+ <column type="gint"/>
1722+ </columns>
1723+ </object>
1724+ <object class="GtkDialog" id="filter_definition">
1725+ <property name="can_focus">False</property>
1726+ <property name="border_width">5</property>
1727+ <property name="modal">True</property>
1728+ <property name="window_position">center-on-parent</property>
1729+ <property name="default_width">320</property>
1730+ <property name="default_height">260</property>
1731+ <property name="destroy_with_parent">True</property>
1732+ <property name="type_hint">dialog</property>
1733+ <child internal-child="vbox">
1734+ <object class="GtkVBox" id="dialog-vbox1">
1735+ <property name="visible">True</property>
1736+ <property name="can_focus">False</property>
1737+ <property name="spacing">2</property>
1738+ <child internal-child="action_area">
1739+ <object class="GtkHButtonBox" id="dialog-action_area1">
1740+ <property name="visible">True</property>
1741+ <property name="can_focus">False</property>
1742+ <property name="layout_style">end</property>
1743+ <child>
1744+ <object class="GtkButton" id="cancel">
1745+ <property name="label">gtk-cancel</property>
1746+ <property name="visible">True</property>
1747+ <property name="can_focus">True</property>
1748+ <property name="receives_default">True</property>
1749+ <property name="use_action_appearance">False</property>
1750+ <property name="use_stock">True</property>
1751+ </object>
1752+ <packing>
1753+ <property name="expand">False</property>
1754+ <property name="fill">False</property>
1755+ <property name="position">0</property>
1756+ </packing>
1757+ </child>
1758+ <child>
1759+ <object class="GtkButton" id="ok_button">
1760+ <property name="label">gtk-ok</property>
1761+ <property name="visible">True</property>
1762+ <property name="sensitive">False</property>
1763+ <property name="can_focus">True</property>
1764+ <property name="can_default">True</property>
1765+ <property name="has_default">True</property>
1766+ <property name="receives_default">True</property>
1767+ <property name="use_action_appearance">False</property>
1768+ <property name="use_stock">True</property>
1769+ </object>
1770+ <packing>
1771+ <property name="expand">False</property>
1772+ <property name="fill">False</property>
1773+ <property name="position">1</property>
1774+ </packing>
1775+ </child>
1776+ </object>
1777+ <packing>
1778+ <property name="expand">False</property>
1779+ <property name="fill">True</property>
1780+ <property name="pack_type">end</property>
1781+ <property name="position">0</property>
1782+ </packing>
1783+ </child>
1784+ <child>
1785+ <object class="GtkTable" id="table1">
1786+ <property name="visible">True</property>
1787+ <property name="can_focus">False</property>
1788+ <property name="n_rows">2</property>
1789+ <property name="n_columns">2</property>
1790+ <child>
1791+ <object class="GtkLabel" id="label2">
1792+ <property name="visible">True</property>
1793+ <property name="can_focus">False</property>
1794+ <property name="xalign">0</property>
1795+ <property name="label" translatable="yes">Filter _Name:</property>
1796+ <property name="use_underline">True</property>
1797+ </object>
1798+ <packing>
1799+ <property name="x_options">GTK_FILL</property>
1800+ <property name="x_padding">6</property>
1801+ </packing>
1802+ </child>
1803+ <child>
1804+ <object class="GtkLabel" id="label3">
1805+ <property name="visible">True</property>
1806+ <property name="can_focus">False</property>
1807+ <property name="xalign">0</property>
1808+ <property name="label" translatable="yes">Filter _Facility:</property>
1809+ <property name="use_underline">True</property>
1810+ </object>
1811+ <packing>
1812+ <property name="top_attach">1</property>
1813+ <property name="bottom_attach">2</property>
1814+ <property name="x_options">GTK_FILL</property>
1815+ <property name="x_padding">6</property>
1816+ </packing>
1817+ </child>
1818+ <child>
1819+ <object class="GtkEntry" id="name_entry">
1820+ <property name="visible">True</property>
1821+ <property name="can_focus">True</property>
1822+ <property name="invisible_char">•</property>
1823+ <signal name="changed" handler="on_name_changed" swapped="no"/>
1824+ </object>
1825+ <packing>
1826+ <property name="left_attach">1</property>
1827+ <property name="right_attach">2</property>
1828+ <property name="y_options"></property>
1829+ </packing>
1830+ </child>
1831+ <child>
1832+ <object class="GtkComboBox" id="facility_combo">
1833+ <property name="visible">True</property>
1834+ <property name="can_focus">True</property>
1835+ <property name="model">facility_store</property>
1836+ <property name="active">0</property>
1837+ <child>
1838+ <object class="GtkCellRendererText" id="name"/>
1839+ <attributes>
1840+ <attribute name="text">0</attribute>
1841+ </attributes>
1842+ </child>
1843+ </object>
1844+ <packing>
1845+ <property name="left_attach">1</property>
1846+ <property name="right_attach">2</property>
1847+ <property name="top_attach">1</property>
1848+ <property name="bottom_attach">2</property>
1849+ <property name="y_options"></property>
1850+ </packing>
1851+ </child>
1852+ </object>
1853+ <packing>
1854+ <property name="expand">False</property>
1855+ <property name="fill">False</property>
1856+ <property name="position">1</property>
1857+ </packing>
1858+ </child>
1859+ <child>
1860+ <object class="GtkVBox" id="vbox1">
1861+ <property name="visible">True</property>
1862+ <property name="can_focus">False</property>
1863+ <child>
1864+ <object class="GtkLabel" id="label1">
1865+ <property name="visible">True</property>
1866+ <property name="can_focus">False</property>
1867+ <property name="xalign">0</property>
1868+ <property name="label" translatable="yes">Filter _Terms:</property>
1869+ <property name="use_underline">True</property>
1870+ </object>
1871+ <packing>
1872+ <property name="expand">False</property>
1873+ <property name="fill">True</property>
1874+ <property name="padding">6</property>
1875+ <property name="position">0</property>
1876+ </packing>
1877+ </child>
1878+ <child>
1879+ <object class="GtkHBox" id="hbox1">
1880+ <property name="visible">True</property>
1881+ <property name="can_focus">False</property>
1882+ <child>
1883+ <object class="GtkScrolledWindow" id="scrolledwindow1">
1884+ <property name="visible">True</property>
1885+ <property name="can_focus">True</property>
1886+ <property name="hscrollbar_policy">automatic</property>
1887+ <property name="vscrollbar_policy">automatic</property>
1888+ <property name="shadow_type">etched-in</property>
1889+ <child>
1890+ <object class="GtkTreeView" id="term_list_view">
1891+ <property name="visible">True</property>
1892+ <property name="can_focus">True</property>
1893+ <property name="model">term_list_store</property>
1894+ <child>
1895+ <object class="GtkTreeViewColumn" id="attr">
1896+ <property name="title" translatable="yes">Attribute</property>
1897+ <property name="clickable">True</property>
1898+ <child>
1899+ <object class="GtkCellRendererText" id="term_attr">
1900+ <property name="editable">True</property>
1901+ <signal name="editing-started" handler="on_term_attr_editing_started" swapped="no"/>
1902+ </object>
1903+ <attributes>
1904+ <attribute name="text">0</attribute>
1905+ </attributes>
1906+ </child>
1907+ </object>
1908+ </child>
1909+ <child>
1910+ <object class="GtkTreeViewColumn" id="op">
1911+ <property name="title" translatable="yes">Operator</property>
1912+ <property name="clickable">True</property>
1913+ <child>
1914+ <object class="GtkCellRendererCombo" id="term_op">
1915+ <property name="editable">True</property>
1916+ </object>
1917+ <attributes>
1918+ <attribute name="text">1</attribute>
1919+ <attribute name="model">1</attribute>
1920+ </attributes>
1921+ </child>
1922+ </object>
1923+ </child>
1924+ <child>
1925+ <object class="GtkTreeViewColumn" id="value">
1926+ <property name="title" translatable="yes">Value</property>
1927+ <property name="clickable">True</property>
1928+ <child>
1929+ <object class="GtkCellRendererText" id="term_value">
1930+ <property name="editable">True</property>
1931+ </object>
1932+ <attributes>
1933+ <attribute name="text">2</attribute>
1934+ </attributes>
1935+ </child>
1936+ </object>
1937+ </child>
1938+ </object>
1939+ </child>
1940+ </object>
1941+ <packing>
1942+ <property name="expand">True</property>
1943+ <property name="fill">True</property>
1944+ <property name="position">0</property>
1945+ </packing>
1946+ </child>
1947+ <child>
1948+ <object class="GtkVButtonBox" id="vbuttonbox1">
1949+ <property name="visible">True</property>
1950+ <property name="can_focus">False</property>
1951+ <property name="layout_style">start</property>
1952+ <child>
1953+ <object class="GtkButton" id="add_term">
1954+ <property name="label">gtk-add</property>
1955+ <property name="visible">True</property>
1956+ <property name="can_focus">True</property>
1957+ <property name="receives_default">True</property>
1958+ <property name="use_action_appearance">False</property>
1959+ <property name="use_stock">True</property>
1960+ <signal name="clicked" handler="on_add_term" swapped="no"/>
1961+ </object>
1962+ <packing>
1963+ <property name="expand">False</property>
1964+ <property name="fill">False</property>
1965+ <property name="position">0</property>
1966+ </packing>
1967+ </child>
1968+ <child>
1969+ <object class="GtkButton" id="edit_term">
1970+ <property name="label">gtk-edit</property>
1971+ <property name="visible">True</property>
1972+ <property name="can_focus">True</property>
1973+ <property name="receives_default">True</property>
1974+ <property name="use_action_appearance">False</property>
1975+ <property name="use_stock">True</property>
1976+ <signal name="clicked" handler="on_edit_term" swapped="no"/>
1977+ </object>
1978+ <packing>
1979+ <property name="expand">False</property>
1980+ <property name="fill">False</property>
1981+ <property name="position">1</property>
1982+ </packing>
1983+ </child>
1984+ <child>
1985+ <object class="GtkButton" id="remove_term">
1986+ <property name="label">gtk-remove</property>
1987+ <property name="visible">True</property>
1988+ <property name="can_focus">True</property>
1989+ <property name="receives_default">True</property>
1990+ <property name="use_action_appearance">False</property>
1991+ <property name="use_stock">True</property>
1992+ <signal name="clicked" handler="on_remove_term" swapped="no"/>
1993+ </object>
1994+ <packing>
1995+ <property name="expand">False</property>
1996+ <property name="fill">False</property>
1997+ <property name="position">2</property>
1998+ </packing>
1999+ </child>
2000+ </object>
2001+ <packing>
2002+ <property name="expand">False</property>
2003+ <property name="fill">True</property>
2004+ <property name="padding">6</property>
2005+ <property name="position">1</property>
2006+ </packing>
2007+ </child>
2008+ </object>
2009+ <packing>
2010+ <property name="expand">True</property>
2011+ <property name="fill">True</property>
2012+ <property name="position">1</property>
2013+ </packing>
2014+ </child>
2015+ </object>
2016+ <packing>
2017+ <property name="expand">True</property>
2018+ <property name="fill">True</property>
2019+ <property name="padding">6</property>
2020+ <property name="position">2</property>
2021+ </packing>
2022+ </child>
2023+ </object>
2024+ </child>
2025+ <action-widgets>
2026+ <action-widget response="0">cancel</action-widget>
2027+ <action-widget response="1">ok_button</action-widget>
2028+ </action-widgets>
2029+ </object>
2030+ <object class="GtkListStore" id="term_list_store">
2031+ <columns>
2032+ <!-- column-name attr_name -->
2033+ <column type="gchararray"/>
2034+ <!-- column-name op -->
2035+ <column type="gchararray"/>
2036+ <!-- column-name value -->
2037+ <column type="gchararray"/>
2038+ </columns>
2039+ </object>
2040+</interface>
2041
2042=== added file 'tools/geisview/filter_list.py'
2043--- tools/geisview/filter_list.py 1970-01-01 00:00:00 +0000
2044+++ tools/geisview/filter_list.py 2011-05-27 15:36:38 +0000
2045@@ -0,0 +1,59 @@
2046+#
2047+# @file geisview/filter_list.py
2048+# @brief A geisview filter list dialog
2049+#
2050+# Copyright (C) 2011 Canonical Ltd
2051+#
2052+# This program is free software; you can redistribute it and/or modify
2053+# it under the terms of the GNU General Public License as published by
2054+# the Free Software Foundation; either version 3 of the License, or
2055+# (at your option) any later version.
2056+#
2057+# This program is distributed in the hope that it will be useful,
2058+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2059+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2060+# GNU General Public License for more details.
2061+#
2062+# You should have received a copy of the GNU General Public License
2063+# along with this program. If not, see <http://www.gnu.org/licenses/>.
2064+#
2065+
2066+import geisview.defaults
2067+import geisview.filter_definition
2068+import os
2069+import pygtk
2070+pygtk.require("2.0")
2071+import gtk
2072+
2073+class FilterList(object):
2074+
2075+ def __init__(self):
2076+ self._builder = gtk.Builder()
2077+ self._builder.add_from_file(os.path.join(geisview.defaults.ui_dir,
2078+ "filter_list.ui"))
2079+ self._builder.connect_signals(self)
2080+
2081+ self._dialog = self._builder.get_object("filter_list");
2082+ self._name_entry = self._builder.get_object("name_entry");
2083+ self._facility_combo = self._builder.get_object("facility_combo");
2084+ self._filter_list_store = self._builder.get_object("filter_list_store")
2085+
2086+ self._dialog.show_all()
2087+
2088+ def run(self):
2089+ print "FilterList.run() begins"
2090+ response = self._dialog.run()
2091+ self._dialog.destroy()
2092+ print "FilterList.run() ends, response=%s" % response
2093+
2094+ def on_add_filter(self, widget, data=None):
2095+ print "FilterList.on_add_filter()"
2096+ dlg = geisview.filter_definition.FilterDefinition()
2097+ dlg.run()
2098+
2099+ def on_edit_filter(self, widget, data=None):
2100+ print "FilterList.on_edit_filter()"
2101+
2102+ def on_remove_filter(self, widget, data=None):
2103+ print "FilterList.on_remove_filter()"
2104+
2105
2106=== added file 'tools/geisview/filter_list.ui'
2107--- tools/geisview/filter_list.ui 1970-01-01 00:00:00 +0000
2108+++ tools/geisview/filter_list.ui 2011-05-27 15:36:38 +0000
2109@@ -0,0 +1,174 @@
2110+<?xml version="1.0" encoding="UTF-8"?>
2111+<interface>
2112+ <requires lib="gtk+" version="2.24"/>
2113+ <!-- interface-naming-policy project-wide -->
2114+ <object class="GtkDialog" id="filter_list">
2115+ <property name="can_focus">False</property>
2116+ <property name="border_width">5</property>
2117+ <property name="title" translatable="yes">GEIS Filters</property>
2118+ <property name="modal">True</property>
2119+ <property name="window_position">center-on-parent</property>
2120+ <property name="destroy_with_parent">True</property>
2121+ <property name="type_hint">dialog</property>
2122+ <child internal-child="vbox">
2123+ <object class="GtkVBox" id="dialog-vbox1">
2124+ <property name="visible">True</property>
2125+ <property name="can_focus">False</property>
2126+ <child internal-child="action_area">
2127+ <object class="GtkHButtonBox" id="dialog-action_area1">
2128+ <property name="visible">True</property>
2129+ <property name="can_focus">False</property>
2130+ <property name="layout_style">end</property>
2131+ <child>
2132+ <object class="GtkButton" id="cancel">
2133+ <property name="label">gtk-cancel</property>
2134+ <property name="visible">True</property>
2135+ <property name="can_focus">True</property>
2136+ <property name="receives_default">True</property>
2137+ <property name="use_action_appearance">False</property>
2138+ <property name="use_stock">True</property>
2139+ </object>
2140+ <packing>
2141+ <property name="expand">False</property>
2142+ <property name="fill">False</property>
2143+ <property name="position">0</property>
2144+ </packing>
2145+ </child>
2146+ <child>
2147+ <object class="GtkButton" id="ok">
2148+ <property name="label">gtk-ok</property>
2149+ <property name="visible">True</property>
2150+ <property name="can_focus">True</property>
2151+ <property name="can_default">True</property>
2152+ <property name="has_default">True</property>
2153+ <property name="receives_default">True</property>
2154+ <property name="use_action_appearance">False</property>
2155+ <property name="use_stock">True</property>
2156+ </object>
2157+ <packing>
2158+ <property name="expand">False</property>
2159+ <property name="fill">False</property>
2160+ <property name="position">1</property>
2161+ </packing>
2162+ </child>
2163+ </object>
2164+ <packing>
2165+ <property name="expand">False</property>
2166+ <property name="fill">True</property>
2167+ <property name="pack_type">end</property>
2168+ <property name="position">0</property>
2169+ </packing>
2170+ </child>
2171+ <child>
2172+ <object class="GtkHBox" id="hbox1">
2173+ <property name="visible">True</property>
2174+ <property name="can_focus">False</property>
2175+ <property name="spacing">3</property>
2176+ <child>
2177+ <object class="GtkScrolledWindow" id="scrolledwindow1">
2178+ <property name="visible">True</property>
2179+ <property name="can_focus">True</property>
2180+ <property name="hscrollbar_policy">automatic</property>
2181+ <property name="vscrollbar_policy">automatic</property>
2182+ <property name="shadow_type">etched-in</property>
2183+ <child>
2184+ <object class="GtkTreeView" id="filter_list_view">
2185+ <property name="visible">True</property>
2186+ <property name="can_focus">True</property>
2187+ <property name="headers_visible">False</property>
2188+ <property name="headers_clickable">False</property>
2189+ </object>
2190+ </child>
2191+ </object>
2192+ <packing>
2193+ <property name="expand">True</property>
2194+ <property name="fill">True</property>
2195+ <property name="position">0</property>
2196+ </packing>
2197+ </child>
2198+ <child>
2199+ <object class="GtkVButtonBox" id="vbuttonbox1">
2200+ <property name="visible">True</property>
2201+ <property name="can_focus">False</property>
2202+ <property name="spacing">3</property>
2203+ <property name="layout_style">start</property>
2204+ <child>
2205+ <object class="GtkButton" id="add_filter">
2206+ <property name="label">gtk-add</property>
2207+ <property name="visible">True</property>
2208+ <property name="can_focus">True</property>
2209+ <property name="receives_default">True</property>
2210+ <property name="use_action_appearance">False</property>
2211+ <property name="use_stock">True</property>
2212+ <signal name="clicked" handler="on_add_filter" swapped="no"/>
2213+ </object>
2214+ <packing>
2215+ <property name="expand">False</property>
2216+ <property name="fill">False</property>
2217+ <property name="position">0</property>
2218+ </packing>
2219+ </child>
2220+ <child>
2221+ <object class="GtkButton" id="edit_filter">
2222+ <property name="label">gtk-edit</property>
2223+ <property name="visible">True</property>
2224+ <property name="can_focus">True</property>
2225+ <property name="receives_default">True</property>
2226+ <property name="use_action_appearance">False</property>
2227+ <property name="use_stock">True</property>
2228+ <signal name="clicked" handler="on_edit_filter" swapped="no"/>
2229+ </object>
2230+ <packing>
2231+ <property name="expand">False</property>
2232+ <property name="fill">False</property>
2233+ <property name="position">1</property>
2234+ </packing>
2235+ </child>
2236+ <child>
2237+ <object class="GtkButton" id="remove_filter">
2238+ <property name="label">gtk-remove</property>
2239+ <property name="visible">True</property>
2240+ <property name="can_focus">True</property>
2241+ <property name="receives_default">True</property>
2242+ <property name="use_action_appearance">False</property>
2243+ <property name="use_stock">True</property>
2244+ <signal name="clicked" handler="on_remove_filter" swapped="no"/>
2245+ </object>
2246+ <packing>
2247+ <property name="expand">False</property>
2248+ <property name="fill">False</property>
2249+ <property name="position">2</property>
2250+ </packing>
2251+ </child>
2252+ </object>
2253+ <packing>
2254+ <property name="expand">False</property>
2255+ <property name="fill">True</property>
2256+ <property name="padding">6</property>
2257+ <property name="position">1</property>
2258+ </packing>
2259+ </child>
2260+ </object>
2261+ <packing>
2262+ <property name="expand">True</property>
2263+ <property name="fill">True</property>
2264+ <property name="position">1</property>
2265+ </packing>
2266+ </child>
2267+ <child>
2268+ <placeholder/>
2269+ </child>
2270+ </object>
2271+ </child>
2272+ <action-widgets>
2273+ <action-widget response="0">cancel</action-widget>
2274+ <action-widget response="1">ok</action-widget>
2275+ </action-widgets>
2276+ </object>
2277+ <object class="GtkListStore" id="filter_list_model">
2278+ <columns>
2279+ <!-- column-name name -->
2280+ <column type="gchararray"/>
2281+ </columns>
2282+ </object>
2283+</interface>
2284
2285=== added file 'tools/geisview/geisview'
2286--- tools/geisview/geisview 1970-01-01 00:00:00 +0000
2287+++ tools/geisview/geisview 2011-05-27 15:36:38 +0000
2288@@ -0,0 +1,250 @@
2289+#!/usr/bin/python
2290+#
2291+# @file geisview
2292+# @brief A viewer for raw GEIS data.
2293+#
2294+# This program is a handy diagnostic tool for viewing the raw data produced
2295+# through the GEIS multi-touch and gesture interface.
2296+#
2297+# Copyright (C) 2011 Canonical Ltd
2298+#
2299+# This program is free software; you can redistribute it and/or modify
2300+# it under the terms of the GNU General Public License as published by
2301+# the Free Software Foundation; either version 3 of the License, or
2302+# (at your option) any later version.
2303+#
2304+# This program is distributed in the hope that it will be useful,
2305+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2306+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2307+# GNU General Public License for more details.
2308+#
2309+# You should have received a copy of the GNU General Public License
2310+# along with this program. If not, see <http://www.gnu.org/licenses/>.
2311+#
2312+
2313+import argparse
2314+import geis
2315+import geisview.defaults
2316+import geisview.deviceview
2317+import geisview.filter_list
2318+from gettext import gettext as _
2319+import glib
2320+import os
2321+import sys
2322+
2323+import pygtk
2324+pygtk.require("2.0")
2325+import gtk
2326+
2327+
2328+
2329+class GeisViewer(object):
2330+ """Provides a GUI client to display raw GEIS data.
2331+ """
2332+
2333+ def __init__(self):
2334+ self._builder = gtk.Builder()
2335+ self._builder.add_from_file(os.path.join(geisview.defaults.ui_dir,
2336+ "geisview.ui"))
2337+ self._builder.connect_signals(self)
2338+
2339+ self._main_window = self._builder.get_object("main_window")
2340+ self._filters_dialog = self._builder.get_object("filters_dialog")
2341+
2342+ self._geis = geis.Geis(geis.GEIS_INIT_TRACK_DEVICES,
2343+ geis.GEIS_INIT_TRACK_GESTURE_CLASSES)
2344+ self._geis_event_store = self._builder.get_object("geis_event_store")
2345+
2346+ geis_fd = self._geis.get_configuration(geis.GEIS_CONFIGURATION_FD)
2347+ glib.io_add_watch(geis_fd, glib.IO_IN, self._dispatch_geis_events)
2348+
2349+ self._devices = {}
2350+
2351+ self._sub = geis.Subscription(self._geis)
2352+
2353+ self._main_window.show()
2354+
2355+ def gtk_main_quit(self, widget, data=None):
2356+ gtk.main_quit()
2357+
2358+ def on_menu_item_save(self, widget, data=None):
2359+ print "on_menu_item_save"
2360+
2361+ def on_menu_item_save_as(self, widget, data=None):
2362+ print "on_menu_item_save_as"
2363+
2364+ def on_edit_clear_events_menu_item(self, widget, data=None):
2365+ self._geis_event_store.clear()
2366+
2367+ def on_edit_filters_menu_item_activate(self, widget, data=None):
2368+ print "on_edit_filters_menu_item_activate"
2369+ filter_list_dialog = geisview.filter_list.FilterList()
2370+ filter_list_dialog.run()
2371+
2372+ def on_view_device_menu_item_activate(self, widget, data=None):
2373+ device_view = geisview.deviceview.DeviceView(self._devices)
2374+
2375+ def on_menu_item_about(self, widget, data=None):
2376+ about = gtk.AboutDialog()
2377+ about.set_transient_for(self._main_window)
2378+ about.set_name(geisview.defaults.appname)
2379+ about.set_version(geisview.defaults.version)
2380+ about.set_copyright(geisview.defaults.copyright)
2381+ about.set_license(geisview.defaults.license)
2382+ about.set_wrap_license(True)
2383+ about.set_comments(geisview.defaults.description)
2384+ about.set_authors(geisview.defaults.authors)
2385+ about.set_logo_icon_name("geisview")
2386+ about.set_translator_credits(geisview.defaults.translator_credit)
2387+ about.connect("response", lambda d, r: d.destroy())
2388+ about.show()
2389+
2390+ def _detail_touches(self, event_row, touchset):
2391+ count_label = _("touches: %i") % len(touchset)
2392+ slot_label = _("touch slot %i")
2393+ touch_row = self._geis_event_store.append(event_row)
2394+ self._geis_event_store.set(touch_row, 0, count_label)
2395+ for touch in touchset:
2396+ slot_row = self._geis_event_store.append(touch_row)
2397+ self._geis_event_store.set(slot_row, 0, slot_label % touch.id())
2398+ for (k, v) in touch.attrs().iteritems():
2399+ attr_row = self._geis_event_store.append(slot_row)
2400+ self._geis_event_store.set(attr_row, 0, "%s: %s" % (k, v))
2401+
2402+ def _detail_frame(self, group_row, frame):
2403+ """Extracts and display the details of a gesture frame.
2404+ """
2405+ frame_label = _("frame: %i") % frame.id()
2406+ touch_label = _("touch indexes %s") % frame.touches()
2407+
2408+ dev = None
2409+
2410+ frame_row = self._geis_event_store.append(group_row)
2411+ self._geis_event_store.set(frame_row, 0, frame_label)
2412+ for (k, v) in frame.attrs().iteritems():
2413+ row = self._geis_event_store.append(frame_row)
2414+ self._geis_event_store.set(row, 0, "%s: %s" % (k, v))
2415+ if k == geis.GEIS_GESTURE_ATTRIBUTE_DEVICE_ID and v in self._devices:
2416+ dev = self._devices[v]
2417+ self._geis_event_store.append(frame_row, [touch_label, None, None])
2418+
2419+ if dev:
2420+ print "device %s extents %s" % (dev.id(), dev.extents())
2421+
2422+
2423+ def _detail_gesture(self, event_row, attrs):
2424+ touchset = attrs[geis.GEIS_EVENT_ATTRIBUTE_TOUCHSET]
2425+ groupset = attrs[geis.GEIS_EVENT_ATTRIBUTE_GROUPSET]
2426+ self._detail_touches(event_row, touchset)
2427+ count_label = _("groups: %i") % len(touchset)
2428+ group_label = _("group %i")
2429+ it = self._geis_event_store.append(event_row, [count_label, None, None])
2430+ for group in groupset:
2431+ group_row = self._geis_event_store.append(it,
2432+ [group_label % group.id(), None, None])
2433+ for frame in group:
2434+ self._detail_frame(group_row, frame)
2435+
2436+ def _detail_gesture_class(self, event_row, gesture_class):
2437+ for (k, v) in gesture_class.attrs().iteritems():
2438+ row = self._geis_event_store.append(event_row)
2439+ self._geis_event_store.set(row, 0, "%s: %s" % (k, v))
2440+
2441+ def _detail_device(self, event_row, device):
2442+ for (k, v) in device.attrs().iteritems():
2443+ row = self._geis_event_store.append(event_row)
2444+ self._geis_event_store.set(row, 0, "%s: %s" % (k, v))
2445+
2446+ def _do_gesture_begin(self, event):
2447+ it = self._geis_event_store.append(None)
2448+ self._geis_event_store.set(it, 0, _("Gesture Begin"))
2449+ self._detail_gesture(it, event.attrs())
2450+
2451+ def _do_gesture_update(self, event):
2452+ it = self._geis_event_store.append(None)
2453+ self._geis_event_store.set(it, 0, _("Gesture Update"))
2454+ self._detail_gesture(it, event.attrs())
2455+
2456+ def _do_gesture_end(self, event):
2457+ it = self._geis_event_store.append(None)
2458+ self._geis_event_store.set(it, 0, _("Gesture End"))
2459+ self._detail_gesture(it, event.attrs())
2460+
2461+ def _do_class_added(self, event):
2462+ gclass = event.attrs()[geis.GEIS_EVENT_ATTRIBUTE_CLASS]
2463+ it = self._geis_event_store.append(None)
2464+ self._geis_event_store.set(it,
2465+ 0, _("Class %s Added: %s") % (gclass.id(), gclass.name()))
2466+ self._detail_gesture_class(it, gclass)
2467+
2468+ def _do_device_added(self, event):
2469+ device = event.attrs()[geis.GEIS_EVENT_ATTRIBUTE_DEVICE]
2470+ self._devices[device.id()] = device
2471+ it = self._geis_event_store.append(None)
2472+ self._geis_event_store.set(it,
2473+ 0, _("Device %s Added: %s") % (device.id(), device.name()))
2474+ self._detail_device(it, device)
2475+
2476+ def _do_init_complete(self, event):
2477+ it = self._geis_event_store.append(None)
2478+ self._geis_event_store.set(it,
2479+ 0, _("GEIS initialization complete"))
2480+ f = geis.Filter(self._geis, "filter")
2481+ f.add_term(geis.GEIS_FILTER_CLASS,
2482+ (geis.GEIS_GESTURE_ATTRIBUTE_TOUCHES, geis.GEIS_FILTER_OP_GE, 2))
2483+ self._sub.add_filter(f)
2484+ self._sub.activate()
2485+
2486+ def _do_other_event(self, event):
2487+ event_label = _("Unknown Event")
2488+ it = self._geis_event_store.append(None, [event_label, None, None])
2489+
2490+ def _dispatch_geis_events(self, fd, condition):
2491+ """ Performs GEIS event loop processing. """
2492+ _geis_event_action = {
2493+ geis.GEIS_EVENT_GESTURE_BEGIN: self._do_gesture_begin,
2494+ geis.GEIS_EVENT_GESTURE_UPDATE: self._do_gesture_update,
2495+ geis.GEIS_EVENT_GESTURE_END: self._do_gesture_end,
2496+ geis.GEIS_EVENT_CLASS_AVAILABLE: self._do_class_added,
2497+ geis.GEIS_EVENT_DEVICE_AVAILABLE: self._do_device_added,
2498+ geis.GEIS_EVENT_INIT_COMPLETE: self._do_init_complete
2499+ }
2500+
2501+ status = self._geis.dispatch_events()
2502+ while status == geis.GEIS_STATUS_CONTINUE:
2503+ status = self._geis.dispatch_events()
2504+
2505+ try:
2506+ while True:
2507+ event = self._geis.next_event()
2508+ _geis_event_action.get(event.type(), self._do_other_event)(event)
2509+ except geis.NoMoreEvents:
2510+ pass
2511+ return True
2512+
2513+
2514+
2515+class Options(argparse.ArgumentParser):
2516+ """Handles the geisviewer command-line arguments.
2517+ """
2518+
2519+ def __init__(self):
2520+ argparse.ArgumentParser.__init__(self,
2521+ description="monitor uTouch gestures")
2522+ self.add_argument('-V', '--version', action='version', version='1.0')
2523+
2524+
2525+def main():
2526+ options = Options()
2527+ try:
2528+ options.parse_args()
2529+ except argparse.ArgumentError, ex:
2530+ print ex
2531+ sys.exit(1)
2532+
2533+ geis_viewer = GeisViewer()
2534+ gtk.main()
2535+
2536+
2537+if __name__ == '__main__':
2538+ main()
2539
2540=== added file 'tools/geisview/geisview.ui'
2541--- tools/geisview/geisview.ui 1970-01-01 00:00:00 +0000
2542+++ tools/geisview/geisview.ui 2011-05-27 15:36:38 +0000
2543@@ -0,0 +1,333 @@
2544+<?xml version="1.0" encoding="UTF-8"?>
2545+<interface>
2546+ <requires lib="gtk+" version="2.24"/>
2547+ <!-- interface-naming-policy project-wide -->
2548+ <object class="GtkListStore" id="geis_event_detail">
2549+ <columns>
2550+ <!-- column-name label -->
2551+ <column type="gchararray"/>
2552+ <!-- column-name value -->
2553+ <column type="gchararray"/>
2554+ </columns>
2555+ </object>
2556+ <object class="GtkTreeStore" id="geis_event_store">
2557+ <columns>
2558+ <!-- column-name event_type -->
2559+ <column type="gchararray"/>
2560+ <!-- column-name value -->
2561+ <column type="gchararray"/>
2562+ <!-- column-name data -->
2563+ <column type="gpointer"/>
2564+ </columns>
2565+ </object>
2566+ <object class="GtkImage" id="image1">
2567+ <property name="visible">True</property>
2568+ <property name="can_focus">False</property>
2569+ <property name="stock">gtk-missing-image</property>
2570+ </object>
2571+ <object class="GtkWindow" id="main_window">
2572+ <property name="can_focus">False</property>
2573+ <property name="default_width">480</property>
2574+ <property name="default_height">420</property>
2575+ <signal name="destroy" handler="gtk_main_quit" swapped="no"/>
2576+ <child>
2577+ <object class="GtkVBox" id="vbox1">
2578+ <property name="visible">True</property>
2579+ <property name="can_focus">False</property>
2580+ <child>
2581+ <object class="GtkMenuBar" id="menubar1">
2582+ <property name="visible">True</property>
2583+ <property name="can_focus">False</property>
2584+ <child>
2585+ <object class="GtkMenuItem" id="menu_file">
2586+ <property name="visible">True</property>
2587+ <property name="can_focus">False</property>
2588+ <property name="use_action_appearance">False</property>
2589+ <property name="label" translatable="yes">_File</property>
2590+ <property name="use_underline">True</property>
2591+ <child type="submenu">
2592+ <object class="GtkMenu" id="menu1">
2593+ <property name="visible">True</property>
2594+ <property name="can_focus">False</property>
2595+ <child>
2596+ <object class="GtkImageMenuItem" id="menu_item_new">
2597+ <property name="label">gtk-new</property>
2598+ <property name="visible">True</property>
2599+ <property name="can_focus">False</property>
2600+ <property name="use_action_appearance">False</property>
2601+ <property name="use_underline">True</property>
2602+ <property name="use_stock">True</property>
2603+ </object>
2604+ </child>
2605+ <child>
2606+ <object class="GtkImageMenuItem" id="menu_item_open">
2607+ <property name="label">gtk-open</property>
2608+ <property name="visible">True</property>
2609+ <property name="can_focus">False</property>
2610+ <property name="use_action_appearance">False</property>
2611+ <property name="use_underline">True</property>
2612+ <property name="use_stock">True</property>
2613+ </object>
2614+ </child>
2615+ <child>
2616+ <object class="GtkImageMenuItem" id="menu_item_save">
2617+ <property name="label">gtk-save</property>
2618+ <property name="visible">True</property>
2619+ <property name="can_focus">False</property>
2620+ <property name="use_action_appearance">False</property>
2621+ <property name="use_underline">True</property>
2622+ <property name="use_stock">True</property>
2623+ <signal name="activate-item" handler="on_menu_item_save" swapped="no"/>
2624+ </object>
2625+ </child>
2626+ <child>
2627+ <object class="GtkImageMenuItem" id="menu_item_save_as">
2628+ <property name="label">gtk-save-as</property>
2629+ <property name="visible">True</property>
2630+ <property name="can_focus">False</property>
2631+ <property name="use_action_appearance">False</property>
2632+ <property name="use_underline">True</property>
2633+ <property name="use_stock">True</property>
2634+ <signal name="activate-item" handler="on_menu_item_save_as" swapped="no"/>
2635+ </object>
2636+ </child>
2637+ <child>
2638+ <object class="GtkSeparatorMenuItem" id="separatormenuitem1">
2639+ <property name="visible">True</property>
2640+ <property name="can_focus">False</property>
2641+ <property name="use_action_appearance">False</property>
2642+ </object>
2643+ </child>
2644+ <child>
2645+ <object class="GtkImageMenuItem" id="quit_menu_item">
2646+ <property name="label">gtk-quit</property>
2647+ <property name="visible">True</property>
2648+ <property name="can_focus">False</property>
2649+ <property name="use_action_appearance">False</property>
2650+ <property name="use_underline">True</property>
2651+ <property name="use_stock">True</property>
2652+ <signal name="activate-item" handler="gtk_main_quit" swapped="no"/>
2653+ <signal name="activate" handler="gtk_main_quit" swapped="no"/>
2654+ </object>
2655+ </child>
2656+ </object>
2657+ </child>
2658+ </object>
2659+ </child>
2660+ <child>
2661+ <object class="GtkMenuItem" id="menu_edit">
2662+ <property name="visible">True</property>
2663+ <property name="can_focus">False</property>
2664+ <property name="use_action_appearance">False</property>
2665+ <property name="label" translatable="yes">_Edit</property>
2666+ <property name="use_underline">True</property>
2667+ <child type="submenu">
2668+ <object class="GtkMenu" id="menu2">
2669+ <property name="visible">True</property>
2670+ <property name="can_focus">False</property>
2671+ <child>
2672+ <object class="GtkImageMenuItem" id="menu_item_cut">
2673+ <property name="label">gtk-cut</property>
2674+ <property name="visible">True</property>
2675+ <property name="can_focus">False</property>
2676+ <property name="use_action_appearance">False</property>
2677+ <property name="use_underline">True</property>
2678+ <property name="use_stock">True</property>
2679+ </object>
2680+ </child>
2681+ <child>
2682+ <object class="GtkImageMenuItem" id="menu_item_copy">
2683+ <property name="label">gtk-copy</property>
2684+ <property name="visible">True</property>
2685+ <property name="can_focus">False</property>
2686+ <property name="use_action_appearance">False</property>
2687+ <property name="use_underline">True</property>
2688+ <property name="use_stock">True</property>
2689+ </object>
2690+ </child>
2691+ <child>
2692+ <object class="GtkImageMenuItem" id="menu_item_paste">
2693+ <property name="label">gtk-paste</property>
2694+ <property name="visible">True</property>
2695+ <property name="can_focus">False</property>
2696+ <property name="use_action_appearance">False</property>
2697+ <property name="use_underline">True</property>
2698+ <property name="use_stock">True</property>
2699+ </object>
2700+ </child>
2701+ <child>
2702+ <object class="GtkImageMenuItem" id="menu_item_delete">
2703+ <property name="label">gtk-delete</property>
2704+ <property name="visible">True</property>
2705+ <property name="can_focus">False</property>
2706+ <property name="use_action_appearance">False</property>
2707+ <property name="use_underline">True</property>
2708+ <property name="use_stock">True</property>
2709+ </object>
2710+ </child>
2711+ <child>
2712+ <object class="GtkMenuItem" id="edit_clear_events_menu_item">
2713+ <property name="visible">True</property>
2714+ <property name="can_focus">False</property>
2715+ <property name="use_action_appearance">False</property>
2716+ <property name="label" translatable="yes">Clear Events</property>
2717+ <property name="use_underline">True</property>
2718+ <signal name="activate" handler="on_edit_clear_events_menu_item" swapped="no"/>
2719+ </object>
2720+ </child>
2721+ <child>
2722+ <object class="GtkMenuItem" id="edit_filters_menu_item">
2723+ <property name="visible">True</property>
2724+ <property name="can_focus">False</property>
2725+ <property name="use_action_appearance">False</property>
2726+ <property name="label" translatable="yes">Filters...</property>
2727+ <property name="use_underline">True</property>
2728+ <signal name="activate" handler="on_edit_filters_menu_item_activate" swapped="no"/>
2729+ </object>
2730+ </child>
2731+ </object>
2732+ </child>
2733+ </object>
2734+ </child>
2735+ <child>
2736+ <object class="GtkMenuItem" id="menu_view">
2737+ <property name="visible">True</property>
2738+ <property name="can_focus">False</property>
2739+ <property name="use_action_appearance">False</property>
2740+ <property name="label" translatable="yes">_View</property>
2741+ <property name="use_underline">True</property>
2742+ <child type="submenu">
2743+ <object class="GtkMenu" id="menu4">
2744+ <property name="visible">True</property>
2745+ <property name="can_focus">False</property>
2746+ <child>
2747+ <object class="GtkImageMenuItem" id="view_device_menu_item">
2748+ <property name="label" translatable="yes">Show _Devices</property>
2749+ <property name="visible">True</property>
2750+ <property name="can_focus">False</property>
2751+ <property name="use_action_appearance">False</property>
2752+ <property name="use_underline">True</property>
2753+ <property name="image">image1</property>
2754+ <property name="use_stock">False</property>
2755+ <signal name="activate" handler="on_view_device_menu_item_activate" swapped="no"/>
2756+ </object>
2757+ </child>
2758+ </object>
2759+ </child>
2760+ </object>
2761+ </child>
2762+ <child>
2763+ <object class="GtkMenuItem" id="menu_help">
2764+ <property name="visible">True</property>
2765+ <property name="can_focus">False</property>
2766+ <property name="use_action_appearance">False</property>
2767+ <property name="label" translatable="yes">_Help</property>
2768+ <property name="use_underline">True</property>
2769+ <child type="submenu">
2770+ <object class="GtkMenu" id="menu3">
2771+ <property name="visible">True</property>
2772+ <property name="can_focus">False</property>
2773+ <child>
2774+ <object class="GtkImageMenuItem" id="menu_item_about">
2775+ <property name="label">gtk-about</property>
2776+ <property name="visible">True</property>
2777+ <property name="can_focus">False</property>
2778+ <property name="use_action_appearance">False</property>
2779+ <property name="use_underline">True</property>
2780+ <property name="use_stock">True</property>
2781+ <signal name="activate-item" handler="gtk_main_quit" swapped="no"/>
2782+ <signal name="activate" handler="on_menu_item_about" swapped="no"/>
2783+ </object>
2784+ </child>
2785+ </object>
2786+ </child>
2787+ </object>
2788+ </child>
2789+ </object>
2790+ <packing>
2791+ <property name="expand">False</property>
2792+ <property name="fill">True</property>
2793+ <property name="position">0</property>
2794+ </packing>
2795+ </child>
2796+ <child>
2797+ <object class="GtkVPaned" id="vpaned1">
2798+ <property name="visible">True</property>
2799+ <property name="can_focus">True</property>
2800+ <child>
2801+ <object class="GtkScrolledWindow" id="scrolledwindow1">
2802+ <property name="visible">True</property>
2803+ <property name="can_focus">True</property>
2804+ <property name="hscrollbar_policy">automatic</property>
2805+ <property name="vscrollbar_policy">automatic</property>
2806+ <property name="window_placement_set">True</property>
2807+ <property name="shadow_type">etched-in</property>
2808+ <child>
2809+ <object class="GtkTreeView" id="event_treeview">
2810+ <property name="visible">True</property>
2811+ <property name="can_focus">True</property>
2812+ <property name="border_width">1</property>
2813+ <property name="model">geis_event_store</property>
2814+ <property name="headers_visible">False</property>
2815+ <property name="headers_clickable">False</property>
2816+ <child>
2817+ <object class="GtkTreeViewColumn" id="label">
2818+ <property name="title" translatable="yes">column</property>
2819+ <child>
2820+ <object class="GtkCellRendererText" id="cellrenderertext1"/>
2821+ <attributes>
2822+ <attribute name="text">0</attribute>
2823+ </attributes>
2824+ </child>
2825+ </object>
2826+ </child>
2827+ </object>
2828+ </child>
2829+ </object>
2830+ <packing>
2831+ <property name="resize">False</property>
2832+ <property name="shrink">True</property>
2833+ </packing>
2834+ </child>
2835+ <child>
2836+ <object class="GtkScrolledWindow" id="scrolledwindow2">
2837+ <property name="can_focus">True</property>
2838+ <property name="hscrollbar_policy">automatic</property>
2839+ <property name="vscrollbar_policy">automatic</property>
2840+ <property name="shadow_type">in</property>
2841+ <child>
2842+ <object class="GtkTreeView" id="treeview2">
2843+ <property name="visible">True</property>
2844+ <property name="can_focus">True</property>
2845+ <property name="model">geis_event_detail</property>
2846+ </object>
2847+ </child>
2848+ </object>
2849+ <packing>
2850+ <property name="resize">True</property>
2851+ <property name="shrink">True</property>
2852+ </packing>
2853+ </child>
2854+ </object>
2855+ <packing>
2856+ <property name="expand">True</property>
2857+ <property name="fill">True</property>
2858+ <property name="position">1</property>
2859+ </packing>
2860+ </child>
2861+ <child>
2862+ <object class="GtkStatusbar" id="statusbar1">
2863+ <property name="visible">True</property>
2864+ <property name="can_focus">False</property>
2865+ <property name="spacing">2</property>
2866+ </object>
2867+ <packing>
2868+ <property name="expand">False</property>
2869+ <property name="fill">True</property>
2870+ <property name="position">2</property>
2871+ </packing>
2872+ </child>
2873+ </object>
2874+ </child>
2875+ </object>
2876+</interface>

Subscribers

People subscribed via source and target branches