summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Andreoli <dave@gurumeditation.it>2016-01-20 22:55:43 +0100
committerDave Andreoli <dave@gurumeditation.it>2016-01-20 22:55:43 +0100
commit005dd26f73f0a634d16286362b80ce98e2e277a8 (patch)
tree35878d110c4e4baae022bd2016c4156cc0272bef
parent90595ffdcada4bc3f6084165e13c87a5b3fbf8e2 (diff)
Implemented Genlist filter ability
It is somehow not perfectly working, see TODO for more info
-rw-r--r--TODO4
-rw-r--r--doc/elementary/genlist.rst1
-rw-r--r--efl/elementary/genlist.pxi18
-rw-r--r--efl/elementary/genlist_cdef.pxi3
-rw-r--r--efl/elementary/genlist_item_class.pxi27
-rw-r--r--efl/elementary/genlist_widget.pxi38
-rw-r--r--examples/elementary/test_genlist_filter.py84
7 files changed, 170 insertions, 5 deletions
diff --git a/TODO b/TODO
index 516d3c5..4e41a98 100644
--- a/TODO
+++ b/TODO
@@ -3,12 +3,14 @@ BUGS
3==== 3====
4* EdjeEdit: PartState API does not work 4* EdjeEdit: PartState API does not work
5* Elm.Map: overlays_show segfaults, scrollers in examples are jumpy 5* Elm.Map: overlays_show segfaults, scrollers in examples are jumpy
6* Genlist: "filter,done" event is not always fired (see the genlist_filter.py test)
6* Elementary: when we use custom function callbacks we usually leak some 7* Elementary: when we use custom function callbacks we usually leak some
7 reference around, some examples: 8 reference around, some examples:
8 - Fileselector.custom_filter_append() 9 - Fileselector.custom_filter_append()
9 - Multibuttonentry.format_function_set() 10 - Multibuttonentry.format_function_set()
10 - Multibuttonentry.filter_append() 11 - Multibuttonentry.filter_append()
11 - Multibuttonentry.filterprepend() 12 - Multibuttonentry.filterprepend()
13 ... maybe do like is done in genlist filter_set() ??
12 14
13Failing unit tests 15Failing unit tests
14------------------ 16------------------
@@ -22,8 +24,6 @@ TODO
22 http://www.freedesktop.org/wiki/Software/DBusBindings 24 http://www.freedesktop.org/wiki/Software/DBusBindings
23 (requires fd.org shell account?) 25 (requires fd.org shell account?)
24* Review the internal functions and name them consistently 26* Review the internal functions and name them consistently
25* Evas: SmartObject needs testing
26* Improve ethumb
27* edje: complete the unit tests 27* edje: complete the unit tests
28* Initial Evas GL support (for Elm) 28* Initial Evas GL support (for Elm)
29* Add more documentation for callbacks, events, etc. 29* Add more documentation for callbacks, events, etc.
diff --git a/doc/elementary/genlist.rst b/doc/elementary/genlist.rst
index e6cb8d0..1d1b482 100644
--- a/doc/elementary/genlist.rst
+++ b/doc/elementary/genlist.rst
@@ -348,6 +348,7 @@ Emitted signals
348- ``item,unfocused`` - When the genlist item has lost focus. (since 1.10) 348- ``item,unfocused`` - When the genlist item has lost focus. (since 1.10)
349- ``changed`` - Genlist is now changed their items and properties and all 349- ``changed`` - Genlist is now changed their items and properties and all
350 calculation is finished. (since 1.16) 350 calculation is finished. (since 1.16)
351- ``filter,done`` - Genlist filter operation is completed.. (since 1.17)
351 352
352 353
353Enumerations 354Enumerations
diff --git a/efl/elementary/genlist.pxi b/efl/elementary/genlist.pxi
index 71935a0..d395297 100644
--- a/efl/elementary/genlist.pxi
+++ b/efl/elementary/genlist.pxi
@@ -80,6 +80,24 @@ cdef Eina_Bool _py_elm_genlist_item_state_get(void *data, Evas_Object *obj, cons
80 80
81 return ret if ret is not None else 0 81 return ret if ret is not None else 0
82 82
83cdef Eina_Bool _py_elm_genlist_item_filter_get(void *data, Evas_Object *obj, void *key) with gil:
84 cdef:
85 GenlistItem item = <GenlistItem>data
86 object pykey = <object>key
87
88 func = item.item_class._filter_get_func
89 if func is None:
90 return 1
91
92 try:
93 o = object_from_instance(obj)
94 ret = func(o, pykey, item.item_data)
95 except Exception:
96 traceback.print_exc()
97 return 0
98
99 return 1 if ret else 0
100
83cdef void _py_elm_genlist_object_item_del(void *data, Evas_Object *obj) with gil: 101cdef void _py_elm_genlist_object_item_del(void *data, Evas_Object *obj) with gil:
84 cdef GenlistItem item = <GenlistItem>data 102 cdef GenlistItem item = <GenlistItem>data
85 103
diff --git a/efl/elementary/genlist_cdef.pxi b/efl/elementary/genlist_cdef.pxi
index c990620..89779d3 100644
--- a/efl/elementary/genlist_cdef.pxi
+++ b/efl/elementary/genlist_cdef.pxi
@@ -64,12 +64,14 @@ cdef extern from "Elementary.h":
64 ctypedef char *(*GenlistItemLabelGetFunc) (void *data, Evas_Object *obj, const char *part) 64 ctypedef char *(*GenlistItemLabelGetFunc) (void *data, Evas_Object *obj, const char *part)
65 ctypedef Evas_Object *(*GenlistItemIconGetFunc) (void *data, Evas_Object *obj, const char *part) 65 ctypedef Evas_Object *(*GenlistItemIconGetFunc) (void *data, Evas_Object *obj, const char *part)
66 ctypedef Eina_Bool (*GenlistItemStateGetFunc) (void *data, Evas_Object *obj, const char *part) 66 ctypedef Eina_Bool (*GenlistItemStateGetFunc) (void *data, Evas_Object *obj, const char *part)
67 ctypedef Eina_Bool (*GenlistItemFilterGetFunc) (void *data, Evas_Object *obj, void *key)
67 ctypedef void (*GenlistItemDelFunc) (void *data, Evas_Object *obj) 68 ctypedef void (*GenlistItemDelFunc) (void *data, Evas_Object *obj)
68 69
69 ctypedef struct Elm_Genlist_Item_Class_Func: 70 ctypedef struct Elm_Genlist_Item_Class_Func:
70 GenlistItemLabelGetFunc text_get 71 GenlistItemLabelGetFunc text_get
71 GenlistItemIconGetFunc content_get 72 GenlistItemIconGetFunc content_get
72 GenlistItemStateGetFunc state_get 73 GenlistItemStateGetFunc state_get
74 GenlistItemFilterGetFunc filter_get
73 GenlistItemDelFunc del_ "del" 75 GenlistItemDelFunc del_ "del"
74 76
75 ctypedef struct Elm_Genlist_Item_Class: 77 ctypedef struct Elm_Genlist_Item_Class:
@@ -155,3 +157,4 @@ cdef extern from "Elementary.h":
155 Elm_Object_Item * elm_genlist_nth_item_get(const Evas_Object *obj, unsigned int nth) 157 Elm_Object_Item * elm_genlist_nth_item_get(const Evas_Object *obj, unsigned int nth)
156 void elm_genlist_focus_on_selection_set(Evas_Object *obj, Eina_Bool enabled) 158 void elm_genlist_focus_on_selection_set(Evas_Object *obj, Eina_Bool enabled)
157 Eina_Bool elm_genlist_focus_on_selection_get(const Evas_Object *obj) 159 Eina_Bool elm_genlist_focus_on_selection_get(const Evas_Object *obj)
160 void elm_genlist_filter_set(Evas_Object *obj, void *key)
diff --git a/efl/elementary/genlist_item_class.pxi b/efl/elementary/genlist_item_class.pxi
index 06546ba..68875d3 100644
--- a/efl/elementary/genlist_item_class.pxi
+++ b/efl/elementary/genlist_item_class.pxi
@@ -19,6 +19,7 @@ cdef class GenlistItemClass(object):
19 object _text_get_func 19 object _text_get_func
20 object _content_get_func 20 object _content_get_func
21 object _state_get_func 21 object _state_get_func
22 object _filter_get_func
22 object _del_func 23 object _del_func
23 object _item_style 24 object _item_style
24 object _decorate_item_style 25 object _decorate_item_style
@@ -29,6 +30,7 @@ cdef class GenlistItemClass(object):
29 self.cls.func.text_get = _py_elm_genlist_item_text_get 30 self.cls.func.text_get = _py_elm_genlist_item_text_get
30 self.cls.func.content_get = _py_elm_genlist_item_content_get 31 self.cls.func.content_get = _py_elm_genlist_item_content_get
31 self.cls.func.state_get = _py_elm_genlist_item_state_get 32 self.cls.func.state_get = _py_elm_genlist_item_state_get
33 self.cls.func.filter_get = _py_elm_genlist_item_filter_get
32 # In C the struct member is del but we rename it to del_ in pxd 34 # In C the struct member is del but we rename it to del_ in pxd
33 self.cls.func.del_ = _py_elm_genlist_object_item_del 35 self.cls.func.del_ = _py_elm_genlist_object_item_del
34 36
@@ -39,7 +41,7 @@ cdef class GenlistItemClass(object):
39 def __init__(self, item_style=None, text_get_func=None, 41 def __init__(self, item_style=None, text_get_func=None,
40 content_get_func=None, state_get_func=None, del_func=None, 42 content_get_func=None, state_get_func=None, del_func=None,
41 decorate_item_style=None, decorate_all_item_style=None, 43 decorate_item_style=None, decorate_all_item_style=None,
42 *args, **kwargs): 44 filter_get_func=None, *args, **kwargs):
43 45
44 """GenlistItemClass constructor. 46 """GenlistItemClass constructor.
45 47
@@ -106,6 +108,14 @@ cdef class GenlistItemClass(object):
106 else: 108 else:
107 self._state_get_func = self.state_get 109 self._state_get_func = self.state_get
108 110
111 if filter_get_func is not None:
112 if callable(filter_get_func):
113 self._filter_get_func = filter_get_func
114 else:
115 raise TypeError("filter_get_func is not callable!")
116 else:
117 self._filter_get_func = self.filter_get
118
109 if del_func is not None: 119 if del_func is not None:
110 if callable(del_func): 120 if callable(del_func):
111 self._del_func = del_func 121 self._del_func = del_func
@@ -136,7 +146,7 @@ cdef class GenlistItemClass(object):
136 def __repr__(self): 146 def __repr__(self):
137 return ("<%s(%#x, refcount=%d, Elm_Genlist_Item_Class=%#x, " 147 return ("<%s(%#x, refcount=%d, Elm_Genlist_Item_Class=%#x, "
138 "item_style=%r, text_get_func=%s, content_get_func=%s, " 148 "item_style=%r, text_get_func=%s, content_get_func=%s, "
139 "state_get_func=%s, del_func=%s)>") % \ 149 "state_get_func=%s, filter_get_func=%s, del_func=%s)>") % \
140 (type(self).__name__, 150 (type(self).__name__,
141 <uintptr_t><void *>self, 151 <uintptr_t><void *>self,
142 PY_REFCOUNT(self), 152 PY_REFCOUNT(self),
@@ -145,6 +155,7 @@ cdef class GenlistItemClass(object):
145 self._text_get_func, 155 self._text_get_func,
146 self._content_get_func, 156 self._content_get_func,
147 self._state_get_func, 157 self._state_get_func,
158 self._filter_get_func,
148 self._del_func) 159 self._del_func)
149 160
150 def ref(self): 161 def ref(self):
@@ -237,3 +248,15 @@ cdef class GenlistItemClass(object):
237 """ 248 """
238 return False 249 return False
239 250
251 def filter_get(self, evasObject obj, key, item_data):
252 """To be called by Genlist for each row when filter is enabled.
253
254 :param obj: the Genlist instance
255 :param key: the filter key given in the filter_set function
256 :param item_data: the value given to genlist append/prepend.
257
258 :return: Wheter the item should be visible or not
259 :rtype: bool
260 """
261 return True
262
diff --git a/efl/elementary/genlist_widget.pxi b/efl/elementary/genlist_widget.pxi
index 6961255..416678b 100644
--- a/efl/elementary/genlist_widget.pxi
+++ b/efl/elementary/genlist_widget.pxi
@@ -685,7 +685,6 @@ cdef class Genlist(Object):
685 <const char *>pattern if pattern is not None else NULL, 685 <const char *>pattern if pattern is not None else NULL,
686 flags)) 686 flags))
687 687
688
689 property focus_on_selection: 688 property focus_on_selection:
690 """ 689 """
691 690
@@ -709,6 +708,33 @@ cdef class Genlist(Object):
709 def __get__(self): 708 def __get__(self):
710 return bool(elm_genlist_focus_on_selection_get(self.obj)) 709 return bool(elm_genlist_focus_on_selection_get(self.obj))
711 710
711 property filter:
712 """ Set filter mode with key.
713
714 This initiates the filter mode of genlist with user/application
715 provided key. If key is None, the filter mode is turned off.
716
717 The given key will be passed back in the filter_get function of
718 the GenlistItemClass
719
720 :type: any python object
721
722 .. versionadded:: 1.17
723
724 """
725 def __set__(self, object key):
726 self.data['__filterkeyref'] = key # keep a reference for key
727 elm_genlist_filter_set(self.obj, <void *>key if key is not None else NULL)
728
729 def __get__(self):
730 return self.data['__filterkeyref']
731
732 def filter_set(self, key):
733 self.data['__filterkeyref'] = key
734 elm_genlist_filter_set(self.obj, <void*>key if key is not None else NULL)
735 def filter_get(self):
736 return self.data['__filterkeyref']
737
712 # 738 #
713 # Drag and Drop 739 # Drag and Drop
714 # ============= 740 # =============
@@ -1070,6 +1096,16 @@ cdef class Genlist(Object):
1070 def callback_changed_del(self, func): 1096 def callback_changed_del(self, func):
1071 self._callback_del("changed", func) 1097 self._callback_del("changed", func)
1072 1098
1099 def callback_filter_done_add(self, func, *args, **kwargs):
1100 """Genlist filter operation is completed.
1101
1102 .. versionadded:: 1.17
1103 """
1104 self._callback_add("filter,done", func, args, kwargs)
1105
1106 def callback_filter_done_del(self, func):
1107 self._callback_del("filter,done", func)
1108
1073 property scroller_policy: 1109 property scroller_policy:
1074 """ 1110 """
1075 1111
diff --git a/examples/elementary/test_genlist_filter.py b/examples/elementary/test_genlist_filter.py
new file mode 100644
index 0000000..7b35491
--- /dev/null
+++ b/examples/elementary/test_genlist_filter.py
@@ -0,0 +1,84 @@
1#!/usr/bin/env python
2# encoding: utf-8
3
4import os
5
6from efl.evas import EXPAND_BOTH, FILL_BOTH, EXPAND_HORIZ, FILL_HORIZ
7
8from efl import elementary as elm
9from efl.elementary import StandardWindow, Box, Entry, Genlist, GenlistItemClass
10
11
12names = [
13 "Aaliyah", "Aamir", "Aaralyn", "Aaron", "Abagail",
14 "Babitha", "Bahuratna", "Bandana", "Bulbul", "Cade", "Caldwell",
15 "Chandan", "Caster", "Dagan", "Daulat", "Dag", "Earl", "Ebenzer",
16 "Ellison", "Elizabeth", "Filbert", "Fitzpatrick", "Florian", "Fulton",
17 "Frazer", "Gabriel", "Gage", "Galen", "Garland", "Gauhar", "Hadden",
18 "Hafiz", "Hakon", "Haleem", "Hank", "Hanuman", "Jabali", "Jaimini",
19 "Jayadev", "Jake", "Jayatsena", "Jonathan", "Kamaal", "Jeirk",
20 "Jasper", "Jack", "Mac", "Macy", "Marlon", "Milson"
21]
22
23
24# item class functions
25def gl_text_get(obj, part, item_data):
26 return item_data
27
28def gl_filter_get(obj, key, item_data):
29 print('"%s" -> "%s"' % (item_data, key))
30 if not key:
31 return True
32 if key.lower() in item_data.lower():
33 return True
34 return False
35
36
37def entry_changed_cb(en, gl):
38 gl.filter = en.text or None
39
40
41def test_genlist_filter(parent):
42 win = StandardWindow("genlist-filter", "Genlist Filter", autodel=True,
43 size=(420, 600), focus_highlight_enabled=True)
44
45 # main vertical box
46 box = Box(win, size_hint_expand=EXPAND_BOTH)
47 win.resize_object_add(box)
48 box.show()
49
50
51 # the Genlist widget
52 gl = Genlist(win, mode=elm.ELM_LIST_COMPRESS, homogeneous=True,
53 select_mode=elm.ELM_OBJECT_SELECT_MODE_ALWAYS,
54 size_hint_expand=EXPAND_BOTH, size_hint_fill=FILL_BOTH)
55 gl.callback_filter_done_add(lambda g: print("filter,done"))
56 gl.show()
57 box.pack_end(gl)
58
59 itc = GenlistItemClass(item_style="default",
60 text_get_func=gl_text_get,
61 filter_get_func=gl_filter_get)
62
63 for i in range(500):
64 gl.item_append(itc, names[i % len(names)])
65
66
67 # the entry
68 en = Entry(box, single_line=True,
69 size_hint_expand=EXPAND_HORIZ, size_hint_fill=FILL_HORIZ)
70 en.part_text_set('guide', 'Type here to filter items')
71 en.callback_changed_user_add(entry_changed_cb, gl)
72 box.pack_start(en)
73 en.show()
74
75
76 #
77 win.show()
78 en.focus = True
79
80
81if __name__ == "__main__":
82 elm.policy_set(elm.ELM_POLICY_QUIT, elm.ELM_POLICY_QUIT_LAST_WINDOW_CLOSED)
83 test_genlist_filter(None)
84 elm.run()