Implemented Genlist filter ability
It is somehow not perfectly working, see TODO for more info
This commit is contained in:
parent
90595ffdca
commit
005dd26f73
4
TODO
4
TODO
|
@ -3,12 +3,14 @@ BUGS
|
||||||
====
|
====
|
||||||
* EdjeEdit: PartState API does not work
|
* EdjeEdit: PartState API does not work
|
||||||
* Elm.Map: overlays_show segfaults, scrollers in examples are jumpy
|
* Elm.Map: overlays_show segfaults, scrollers in examples are jumpy
|
||||||
|
* Genlist: "filter,done" event is not always fired (see the genlist_filter.py test)
|
||||||
* Elementary: when we use custom function callbacks we usually leak some
|
* Elementary: when we use custom function callbacks we usually leak some
|
||||||
reference around, some examples:
|
reference around, some examples:
|
||||||
- Fileselector.custom_filter_append()
|
- Fileselector.custom_filter_append()
|
||||||
- Multibuttonentry.format_function_set()
|
- Multibuttonentry.format_function_set()
|
||||||
- Multibuttonentry.filter_append()
|
- Multibuttonentry.filter_append()
|
||||||
- Multibuttonentry.filterprepend()
|
- Multibuttonentry.filterprepend()
|
||||||
|
... maybe do like is done in genlist filter_set() ??
|
||||||
|
|
||||||
Failing unit tests
|
Failing unit tests
|
||||||
------------------
|
------------------
|
||||||
|
@ -22,8 +24,6 @@ TODO
|
||||||
http://www.freedesktop.org/wiki/Software/DBusBindings
|
http://www.freedesktop.org/wiki/Software/DBusBindings
|
||||||
(requires fd.org shell account?)
|
(requires fd.org shell account?)
|
||||||
* Review the internal functions and name them consistently
|
* Review the internal functions and name them consistently
|
||||||
* Evas: SmartObject needs testing
|
|
||||||
* Improve ethumb
|
|
||||||
* edje: complete the unit tests
|
* edje: complete the unit tests
|
||||||
* Initial Evas GL support (for Elm)
|
* Initial Evas GL support (for Elm)
|
||||||
* Add more documentation for callbacks, events, etc.
|
* Add more documentation for callbacks, events, etc.
|
||||||
|
|
|
@ -348,6 +348,7 @@ Emitted signals
|
||||||
- ``item,unfocused`` - When the genlist item has lost focus. (since 1.10)
|
- ``item,unfocused`` - When the genlist item has lost focus. (since 1.10)
|
||||||
- ``changed`` - Genlist is now changed their items and properties and all
|
- ``changed`` - Genlist is now changed their items and properties and all
|
||||||
calculation is finished. (since 1.16)
|
calculation is finished. (since 1.16)
|
||||||
|
- ``filter,done`` - Genlist filter operation is completed.. (since 1.17)
|
||||||
|
|
||||||
|
|
||||||
Enumerations
|
Enumerations
|
||||||
|
|
|
@ -80,6 +80,24 @@ cdef Eina_Bool _py_elm_genlist_item_state_get(void *data, Evas_Object *obj, cons
|
||||||
|
|
||||||
return ret if ret is not None else 0
|
return ret if ret is not None else 0
|
||||||
|
|
||||||
|
cdef Eina_Bool _py_elm_genlist_item_filter_get(void *data, Evas_Object *obj, void *key) with gil:
|
||||||
|
cdef:
|
||||||
|
GenlistItem item = <GenlistItem>data
|
||||||
|
object pykey = <object>key
|
||||||
|
|
||||||
|
func = item.item_class._filter_get_func
|
||||||
|
if func is None:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
try:
|
||||||
|
o = object_from_instance(obj)
|
||||||
|
ret = func(o, pykey, item.item_data)
|
||||||
|
except Exception:
|
||||||
|
traceback.print_exc()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
return 1 if ret else 0
|
||||||
|
|
||||||
cdef void _py_elm_genlist_object_item_del(void *data, Evas_Object *obj) with gil:
|
cdef void _py_elm_genlist_object_item_del(void *data, Evas_Object *obj) with gil:
|
||||||
cdef GenlistItem item = <GenlistItem>data
|
cdef GenlistItem item = <GenlistItem>data
|
||||||
|
|
||||||
|
|
|
@ -64,12 +64,14 @@ cdef extern from "Elementary.h":
|
||||||
ctypedef char *(*GenlistItemLabelGetFunc) (void *data, Evas_Object *obj, const char *part)
|
ctypedef char *(*GenlistItemLabelGetFunc) (void *data, Evas_Object *obj, const char *part)
|
||||||
ctypedef Evas_Object *(*GenlistItemIconGetFunc) (void *data, Evas_Object *obj, const char *part)
|
ctypedef Evas_Object *(*GenlistItemIconGetFunc) (void *data, Evas_Object *obj, const char *part)
|
||||||
ctypedef Eina_Bool (*GenlistItemStateGetFunc) (void *data, Evas_Object *obj, const char *part)
|
ctypedef Eina_Bool (*GenlistItemStateGetFunc) (void *data, Evas_Object *obj, const char *part)
|
||||||
|
ctypedef Eina_Bool (*GenlistItemFilterGetFunc) (void *data, Evas_Object *obj, void *key)
|
||||||
ctypedef void (*GenlistItemDelFunc) (void *data, Evas_Object *obj)
|
ctypedef void (*GenlistItemDelFunc) (void *data, Evas_Object *obj)
|
||||||
|
|
||||||
ctypedef struct Elm_Genlist_Item_Class_Func:
|
ctypedef struct Elm_Genlist_Item_Class_Func:
|
||||||
GenlistItemLabelGetFunc text_get
|
GenlistItemLabelGetFunc text_get
|
||||||
GenlistItemIconGetFunc content_get
|
GenlistItemIconGetFunc content_get
|
||||||
GenlistItemStateGetFunc state_get
|
GenlistItemStateGetFunc state_get
|
||||||
|
GenlistItemFilterGetFunc filter_get
|
||||||
GenlistItemDelFunc del_ "del"
|
GenlistItemDelFunc del_ "del"
|
||||||
|
|
||||||
ctypedef struct Elm_Genlist_Item_Class:
|
ctypedef struct Elm_Genlist_Item_Class:
|
||||||
|
@ -155,3 +157,4 @@ cdef extern from "Elementary.h":
|
||||||
Elm_Object_Item * elm_genlist_nth_item_get(const Evas_Object *obj, unsigned int nth)
|
Elm_Object_Item * elm_genlist_nth_item_get(const Evas_Object *obj, unsigned int nth)
|
||||||
void elm_genlist_focus_on_selection_set(Evas_Object *obj, Eina_Bool enabled)
|
void elm_genlist_focus_on_selection_set(Evas_Object *obj, Eina_Bool enabled)
|
||||||
Eina_Bool elm_genlist_focus_on_selection_get(const Evas_Object *obj)
|
Eina_Bool elm_genlist_focus_on_selection_get(const Evas_Object *obj)
|
||||||
|
void elm_genlist_filter_set(Evas_Object *obj, void *key)
|
||||||
|
|
|
@ -19,6 +19,7 @@ cdef class GenlistItemClass(object):
|
||||||
object _text_get_func
|
object _text_get_func
|
||||||
object _content_get_func
|
object _content_get_func
|
||||||
object _state_get_func
|
object _state_get_func
|
||||||
|
object _filter_get_func
|
||||||
object _del_func
|
object _del_func
|
||||||
object _item_style
|
object _item_style
|
||||||
object _decorate_item_style
|
object _decorate_item_style
|
||||||
|
@ -29,6 +30,7 @@ cdef class GenlistItemClass(object):
|
||||||
self.cls.func.text_get = _py_elm_genlist_item_text_get
|
self.cls.func.text_get = _py_elm_genlist_item_text_get
|
||||||
self.cls.func.content_get = _py_elm_genlist_item_content_get
|
self.cls.func.content_get = _py_elm_genlist_item_content_get
|
||||||
self.cls.func.state_get = _py_elm_genlist_item_state_get
|
self.cls.func.state_get = _py_elm_genlist_item_state_get
|
||||||
|
self.cls.func.filter_get = _py_elm_genlist_item_filter_get
|
||||||
# In C the struct member is del but we rename it to del_ in pxd
|
# In C the struct member is del but we rename it to del_ in pxd
|
||||||
self.cls.func.del_ = _py_elm_genlist_object_item_del
|
self.cls.func.del_ = _py_elm_genlist_object_item_del
|
||||||
|
|
||||||
|
@ -39,7 +41,7 @@ cdef class GenlistItemClass(object):
|
||||||
def __init__(self, item_style=None, text_get_func=None,
|
def __init__(self, item_style=None, text_get_func=None,
|
||||||
content_get_func=None, state_get_func=None, del_func=None,
|
content_get_func=None, state_get_func=None, del_func=None,
|
||||||
decorate_item_style=None, decorate_all_item_style=None,
|
decorate_item_style=None, decorate_all_item_style=None,
|
||||||
*args, **kwargs):
|
filter_get_func=None, *args, **kwargs):
|
||||||
|
|
||||||
"""GenlistItemClass constructor.
|
"""GenlistItemClass constructor.
|
||||||
|
|
||||||
|
@ -106,6 +108,14 @@ cdef class GenlistItemClass(object):
|
||||||
else:
|
else:
|
||||||
self._state_get_func = self.state_get
|
self._state_get_func = self.state_get
|
||||||
|
|
||||||
|
if filter_get_func is not None:
|
||||||
|
if callable(filter_get_func):
|
||||||
|
self._filter_get_func = filter_get_func
|
||||||
|
else:
|
||||||
|
raise TypeError("filter_get_func is not callable!")
|
||||||
|
else:
|
||||||
|
self._filter_get_func = self.filter_get
|
||||||
|
|
||||||
if del_func is not None:
|
if del_func is not None:
|
||||||
if callable(del_func):
|
if callable(del_func):
|
||||||
self._del_func = del_func
|
self._del_func = del_func
|
||||||
|
@ -136,7 +146,7 @@ cdef class GenlistItemClass(object):
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return ("<%s(%#x, refcount=%d, Elm_Genlist_Item_Class=%#x, "
|
return ("<%s(%#x, refcount=%d, Elm_Genlist_Item_Class=%#x, "
|
||||||
"item_style=%r, text_get_func=%s, content_get_func=%s, "
|
"item_style=%r, text_get_func=%s, content_get_func=%s, "
|
||||||
"state_get_func=%s, del_func=%s)>") % \
|
"state_get_func=%s, filter_get_func=%s, del_func=%s)>") % \
|
||||||
(type(self).__name__,
|
(type(self).__name__,
|
||||||
<uintptr_t><void *>self,
|
<uintptr_t><void *>self,
|
||||||
PY_REFCOUNT(self),
|
PY_REFCOUNT(self),
|
||||||
|
@ -145,6 +155,7 @@ cdef class GenlistItemClass(object):
|
||||||
self._text_get_func,
|
self._text_get_func,
|
||||||
self._content_get_func,
|
self._content_get_func,
|
||||||
self._state_get_func,
|
self._state_get_func,
|
||||||
|
self._filter_get_func,
|
||||||
self._del_func)
|
self._del_func)
|
||||||
|
|
||||||
def ref(self):
|
def ref(self):
|
||||||
|
@ -237,3 +248,15 @@ cdef class GenlistItemClass(object):
|
||||||
"""
|
"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def filter_get(self, evasObject obj, key, item_data):
|
||||||
|
"""To be called by Genlist for each row when filter is enabled.
|
||||||
|
|
||||||
|
:param obj: the Genlist instance
|
||||||
|
:param key: the filter key given in the filter_set function
|
||||||
|
:param item_data: the value given to genlist append/prepend.
|
||||||
|
|
||||||
|
:return: Wheter the item should be visible or not
|
||||||
|
:rtype: bool
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
|
@ -685,7 +685,6 @@ cdef class Genlist(Object):
|
||||||
<const char *>pattern if pattern is not None else NULL,
|
<const char *>pattern if pattern is not None else NULL,
|
||||||
flags))
|
flags))
|
||||||
|
|
||||||
|
|
||||||
property focus_on_selection:
|
property focus_on_selection:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -709,6 +708,33 @@ cdef class Genlist(Object):
|
||||||
def __get__(self):
|
def __get__(self):
|
||||||
return bool(elm_genlist_focus_on_selection_get(self.obj))
|
return bool(elm_genlist_focus_on_selection_get(self.obj))
|
||||||
|
|
||||||
|
property filter:
|
||||||
|
""" Set filter mode with key.
|
||||||
|
|
||||||
|
This initiates the filter mode of genlist with user/application
|
||||||
|
provided key. If key is None, the filter mode is turned off.
|
||||||
|
|
||||||
|
The given key will be passed back in the filter_get function of
|
||||||
|
the GenlistItemClass
|
||||||
|
|
||||||
|
:type: any python object
|
||||||
|
|
||||||
|
.. versionadded:: 1.17
|
||||||
|
|
||||||
|
"""
|
||||||
|
def __set__(self, object key):
|
||||||
|
self.data['__filterkeyref'] = key # keep a reference for key
|
||||||
|
elm_genlist_filter_set(self.obj, <void *>key if key is not None else NULL)
|
||||||
|
|
||||||
|
def __get__(self):
|
||||||
|
return self.data['__filterkeyref']
|
||||||
|
|
||||||
|
def filter_set(self, key):
|
||||||
|
self.data['__filterkeyref'] = key
|
||||||
|
elm_genlist_filter_set(self.obj, <void*>key if key is not None else NULL)
|
||||||
|
def filter_get(self):
|
||||||
|
return self.data['__filterkeyref']
|
||||||
|
|
||||||
#
|
#
|
||||||
# Drag and Drop
|
# Drag and Drop
|
||||||
# =============
|
# =============
|
||||||
|
@ -1070,6 +1096,16 @@ cdef class Genlist(Object):
|
||||||
def callback_changed_del(self, func):
|
def callback_changed_del(self, func):
|
||||||
self._callback_del("changed", func)
|
self._callback_del("changed", func)
|
||||||
|
|
||||||
|
def callback_filter_done_add(self, func, *args, **kwargs):
|
||||||
|
"""Genlist filter operation is completed.
|
||||||
|
|
||||||
|
.. versionadded:: 1.17
|
||||||
|
"""
|
||||||
|
self._callback_add("filter,done", func, args, kwargs)
|
||||||
|
|
||||||
|
def callback_filter_done_del(self, func):
|
||||||
|
self._callback_del("filter,done", func)
|
||||||
|
|
||||||
property scroller_policy:
|
property scroller_policy:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from efl.evas import EXPAND_BOTH, FILL_BOTH, EXPAND_HORIZ, FILL_HORIZ
|
||||||
|
|
||||||
|
from efl import elementary as elm
|
||||||
|
from efl.elementary import StandardWindow, Box, Entry, Genlist, GenlistItemClass
|
||||||
|
|
||||||
|
|
||||||
|
names = [
|
||||||
|
"Aaliyah", "Aamir", "Aaralyn", "Aaron", "Abagail",
|
||||||
|
"Babitha", "Bahuratna", "Bandana", "Bulbul", "Cade", "Caldwell",
|
||||||
|
"Chandan", "Caster", "Dagan", "Daulat", "Dag", "Earl", "Ebenzer",
|
||||||
|
"Ellison", "Elizabeth", "Filbert", "Fitzpatrick", "Florian", "Fulton",
|
||||||
|
"Frazer", "Gabriel", "Gage", "Galen", "Garland", "Gauhar", "Hadden",
|
||||||
|
"Hafiz", "Hakon", "Haleem", "Hank", "Hanuman", "Jabali", "Jaimini",
|
||||||
|
"Jayadev", "Jake", "Jayatsena", "Jonathan", "Kamaal", "Jeirk",
|
||||||
|
"Jasper", "Jack", "Mac", "Macy", "Marlon", "Milson"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# item class functions
|
||||||
|
def gl_text_get(obj, part, item_data):
|
||||||
|
return item_data
|
||||||
|
|
||||||
|
def gl_filter_get(obj, key, item_data):
|
||||||
|
print('"%s" -> "%s"' % (item_data, key))
|
||||||
|
if not key:
|
||||||
|
return True
|
||||||
|
if key.lower() in item_data.lower():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def entry_changed_cb(en, gl):
|
||||||
|
gl.filter = en.text or None
|
||||||
|
|
||||||
|
|
||||||
|
def test_genlist_filter(parent):
|
||||||
|
win = StandardWindow("genlist-filter", "Genlist Filter", autodel=True,
|
||||||
|
size=(420, 600), focus_highlight_enabled=True)
|
||||||
|
|
||||||
|
# main vertical box
|
||||||
|
box = Box(win, size_hint_expand=EXPAND_BOTH)
|
||||||
|
win.resize_object_add(box)
|
||||||
|
box.show()
|
||||||
|
|
||||||
|
|
||||||
|
# the Genlist widget
|
||||||
|
gl = Genlist(win, mode=elm.ELM_LIST_COMPRESS, homogeneous=True,
|
||||||
|
select_mode=elm.ELM_OBJECT_SELECT_MODE_ALWAYS,
|
||||||
|
size_hint_expand=EXPAND_BOTH, size_hint_fill=FILL_BOTH)
|
||||||
|
gl.callback_filter_done_add(lambda g: print("filter,done"))
|
||||||
|
gl.show()
|
||||||
|
box.pack_end(gl)
|
||||||
|
|
||||||
|
itc = GenlistItemClass(item_style="default",
|
||||||
|
text_get_func=gl_text_get,
|
||||||
|
filter_get_func=gl_filter_get)
|
||||||
|
|
||||||
|
for i in range(500):
|
||||||
|
gl.item_append(itc, names[i % len(names)])
|
||||||
|
|
||||||
|
|
||||||
|
# the entry
|
||||||
|
en = Entry(box, single_line=True,
|
||||||
|
size_hint_expand=EXPAND_HORIZ, size_hint_fill=FILL_HORIZ)
|
||||||
|
en.part_text_set('guide', 'Type here to filter items')
|
||||||
|
en.callback_changed_user_add(entry_changed_cb, gl)
|
||||||
|
box.pack_start(en)
|
||||||
|
en.show()
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
win.show()
|
||||||
|
en.focus = True
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
elm.policy_set(elm.ELM_POLICY_QUIT, elm.ELM_POLICY_QUIT_LAST_WINDOW_CLOSED)
|
||||||
|
test_genlist_filter(None)
|
||||||
|
elm.run()
|
Loading…
Reference in New Issue