Elementary.entry: Fix ref leak in filter callback handling.

This commit is contained in:
Kai Huuhko 2014-06-05 18:15:38 +03:00
parent 4f1efb1ee1
commit a0ecc41572
2 changed files with 47 additions and 19 deletions

1
TODO
View File

@ -5,7 +5,6 @@ BUGS
* Elm.Map: overlays_show segfaults, scrollers in examples are jumpy
* Elementary: when we use custom function callbacks we usually leak some
reference around, some examples:
- Entry.markup_filter_append()
- Fileselector.custom_filter_append()
- Multibuttonentry.format_function_set()
- Multibuttonentry.filter_append()

View File

@ -719,18 +719,21 @@ cdef void py_elm_entry_filter_cb(void *data, Evas_Object *entry, char **text) wi
"""
cdef:
Entry en = object_from_instance(entry)
object ret
cb_func, cb_data = <object>data
try:
ret = cb_func(en, _touni(text[0]), cb_data)
except Exception:
traceback.print_exc()
for cb_func, cb_data in en.markup_filters:
try:
ret = cb_func(en, _touni(text[0]), cb_data)
except Exception:
traceback.print_exc()
if ret is None:
free(text[0])
text[0] = NULL
return
if isinstance(ret, unicode): ret = PyUnicode_AsUTF8String(ret)
text[0] = strdup(<char *>ret)
class EntryAnchorInfo(object):
@ -810,6 +813,11 @@ cdef class Entry(LayoutClass):
"""
cdef list markup_filters
def __cinit__(self):
self.markup_filters = []
def __init__(self, evasObject parent, *args, **kwargs):
"""By default, entries are:
@ -1403,13 +1411,16 @@ cdef class Entry(LayoutClass):
.. versionadded:: 1.8
"""
if not callable(func):
raise TypeError("func must be callable")
if not self.markup_filters:
elm_entry_markup_filter_append(self.obj,
py_elm_entry_filter_cb,
NULL)
cb_data = (func, data)
# TODO: This is now a ref leak. It should be stored somewhere and
# deleted in the remove method.
Py_INCREF(cb_data)
elm_entry_markup_filter_append(self.obj,
py_elm_entry_filter_cb,
<void *>cb_data)
self.markup_filters.append(cb_data)
def markup_filter_prepend(self, func, data=None):
"""Prepend a markup filter function for text inserted in the entry
@ -1423,11 +1434,16 @@ cdef class Entry(LayoutClass):
.. versionadded:: 1.8
"""
if not callable(func):
raise TypeError("func must be callable")
if not self.markup_filters:
elm_entry_markup_filter_append(self.obj,
py_elm_entry_filter_cb,
NULL)
cb_data = (func, data)
Py_INCREF(cb_data)
elm_entry_markup_filter_prepend(self.obj,
py_elm_entry_filter_cb,
<void *>cb_data)
self.markup_filters.insert(0, cb_data)
def markup_filter_remove(self, func, data=None):
"""Remove a markup filter from the list
@ -1441,11 +1457,24 @@ cdef class Entry(LayoutClass):
.. versionadded:: 1.8
"""
cb_data = (func, data)
Py_INCREF(cb_data)
f = None
d = None
lst = self.markup_filters
for i, (f, d) in enumerate(lst):
if func is f and data is d:
break
if f is not func or d is not data:
raise ValueError("Callback was not registered with this object.")
lst.pop(i)
if lst:
return
elm_entry_markup_filter_remove(self.obj,
py_elm_entry_filter_cb,
<void *>cb_data)
NULL)
@DEPRECATED("1.8", "Use the module level markup_to_utf8() method instead.")
def markup_to_utf8(self, string):