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
|
||||
* 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
|
||||
reference around, some examples:
|
||||
- Fileselector.custom_filter_append()
|
||||
- Multibuttonentry.format_function_set()
|
||||
- Multibuttonentry.filter_append()
|
||||
- Multibuttonentry.filterprepend()
|
||||
... maybe do like is done in genlist filter_set() ??
|
||||
|
||||
Failing unit tests
|
||||
------------------
|
||||
|
@ -22,8 +24,6 @@ TODO
|
|||
http://www.freedesktop.org/wiki/Software/DBusBindings
|
||||
(requires fd.org shell account?)
|
||||
* Review the internal functions and name them consistently
|
||||
* Evas: SmartObject needs testing
|
||||
* Improve ethumb
|
||||
* edje: complete the unit tests
|
||||
* Initial Evas GL support (for Elm)
|
||||
* 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)
|
||||
- ``changed`` - Genlist is now changed their items and properties and all
|
||||
calculation is finished. (since 1.16)
|
||||
- ``filter,done`` - Genlist filter operation is completed.. (since 1.17)
|
||||
|
||||
|
||||
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
|
||||
|
||||
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 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 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 (*GenlistItemFilterGetFunc) (void *data, Evas_Object *obj, void *key)
|
||||
ctypedef void (*GenlistItemDelFunc) (void *data, Evas_Object *obj)
|
||||
|
||||
ctypedef struct Elm_Genlist_Item_Class_Func:
|
||||
GenlistItemLabelGetFunc text_get
|
||||
GenlistItemIconGetFunc content_get
|
||||
GenlistItemStateGetFunc state_get
|
||||
GenlistItemFilterGetFunc filter_get
|
||||
GenlistItemDelFunc del_ "del"
|
||||
|
||||
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)
|
||||
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)
|
||||
void elm_genlist_filter_set(Evas_Object *obj, void *key)
|
||||
|
|
|
@ -19,6 +19,7 @@ cdef class GenlistItemClass(object):
|
|||
object _text_get_func
|
||||
object _content_get_func
|
||||
object _state_get_func
|
||||
object _filter_get_func
|
||||
object _del_func
|
||||
object _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.content_get = _py_elm_genlist_item_content_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
|
||||
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,
|
||||
content_get_func=None, state_get_func=None, del_func=None,
|
||||
decorate_item_style=None, decorate_all_item_style=None,
|
||||
*args, **kwargs):
|
||||
filter_get_func=None, *args, **kwargs):
|
||||
|
||||
"""GenlistItemClass constructor.
|
||||
|
||||
|
@ -106,6 +108,14 @@ cdef class GenlistItemClass(object):
|
|||
else:
|
||||
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 callable(del_func):
|
||||
self._del_func = del_func
|
||||
|
@ -136,7 +146,7 @@ cdef class GenlistItemClass(object):
|
|||
def __repr__(self):
|
||||
return ("<%s(%#x, refcount=%d, Elm_Genlist_Item_Class=%#x, "
|
||||
"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__,
|
||||
<uintptr_t><void *>self,
|
||||
PY_REFCOUNT(self),
|
||||
|
@ -145,6 +155,7 @@ cdef class GenlistItemClass(object):
|
|||
self._text_get_func,
|
||||
self._content_get_func,
|
||||
self._state_get_func,
|
||||
self._filter_get_func,
|
||||
self._del_func)
|
||||
|
||||
def ref(self):
|
||||
|
@ -237,3 +248,15 @@ cdef class GenlistItemClass(object):
|
|||
"""
|
||||
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,
|
||||
flags))
|
||||
|
||||
|
||||
property focus_on_selection:
|
||||
"""
|
||||
|
||||
|
@ -709,6 +708,33 @@ cdef class Genlist(Object):
|
|||
def __get__(self):
|
||||
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
|
||||
# =============
|
||||
|
@ -1070,6 +1096,16 @@ cdef class Genlist(Object):
|
|||
def callback_changed_del(self, 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:
|
||||
"""
|
||||
|
||||
|
|
|
@ -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