summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Huuhko <kai.huuhko@gmail.com>2014-06-05 18:15:38 +0300
committerKai Huuhko <kai.huuhko@gmail.com>2014-06-05 18:16:14 +0300
commita0ecc4157274d473f056b89207f5dc54a8184e10 (patch)
tree6d439d9b7a7bea758c1a9217ef2b183b9866f967
parent4f1efb1ee1c5263f17dc74338fe4d191a39195f3 (diff)
Elementary.entry: Fix ref leak in filter callback handling.
-rw-r--r--TODO1
-rw-r--r--efl/elementary/entry.pyx65
2 files changed, 47 insertions, 19 deletions
diff --git a/TODO b/TODO
index edbf3f9..6dd0f1d 100644
--- a/TODO
+++ b/TODO
@@ -5,7 +5,6 @@ BUGS
5* Elm.Map: overlays_show segfaults, scrollers in examples are jumpy 5* Elm.Map: overlays_show segfaults, scrollers in examples are jumpy
6* Elementary: when we use custom function callbacks we usually leak some 6* Elementary: when we use custom function callbacks we usually leak some
7 reference around, some examples: 7 reference around, some examples:
8 - Entry.markup_filter_append()
9 - Fileselector.custom_filter_append() 8 - Fileselector.custom_filter_append()
10 - Multibuttonentry.format_function_set() 9 - Multibuttonentry.format_function_set()
11 - Multibuttonentry.filter_append() 10 - Multibuttonentry.filter_append()
diff --git a/efl/elementary/entry.pyx b/efl/elementary/entry.pyx
index ce6313f..bacaaca 100644
--- a/efl/elementary/entry.pyx
+++ b/efl/elementary/entry.pyx
@@ -719,18 +719,21 @@ cdef void py_elm_entry_filter_cb(void *data, Evas_Object *entry, char **text) wi
719 """ 719 """
720 cdef: 720 cdef:
721 Entry en = object_from_instance(entry) 721 Entry en = object_from_instance(entry)
722 object ret
722 723
723 cb_func, cb_data = <object>data 724 for cb_func, cb_data in en.markup_filters:
724 try: 725 try:
725 ret = cb_func(en, _touni(text[0]), cb_data) 726 ret = cb_func(en, _touni(text[0]), cb_data)
726 except Exception: 727 except Exception:
727 traceback.print_exc() 728 traceback.print_exc()
728 729
729 if ret is None: 730 if ret is None:
730 free(text[0]) 731 free(text[0])
731 text[0] = NULL 732 text[0] = NULL
732 return 733 return
733 734
735 if isinstance(ret, unicode): ret = PyUnicode_AsUTF8String(ret)
736
734 text[0] = strdup(<char *>ret) 737 text[0] = strdup(<char *>ret)
735 738
736class EntryAnchorInfo(object): 739class EntryAnchorInfo(object):
@@ -810,6 +813,11 @@ cdef class Entry(LayoutClass):
810 813
811 """ 814 """
812 815
816 cdef list markup_filters
817
818 def __cinit__(self):
819 self.markup_filters = []
820
813 def __init__(self, evasObject parent, *args, **kwargs): 821 def __init__(self, evasObject parent, *args, **kwargs):
814 """By default, entries are: 822 """By default, entries are:
815 823
@@ -1403,13 +1411,16 @@ cdef class Entry(LayoutClass):
1403 .. versionadded:: 1.8 1411 .. versionadded:: 1.8
1404 1412
1405 """ 1413 """
1414 if not callable(func):
1415 raise TypeError("func must be callable")
1416
1417 if not self.markup_filters:
1418 elm_entry_markup_filter_append(self.obj,
1419 py_elm_entry_filter_cb,
1420 NULL)
1421
1406 cb_data = (func, data) 1422 cb_data = (func, data)
1407 # TODO: This is now a ref leak. It should be stored somewhere and 1423 self.markup_filters.append(cb_data)
1408 # deleted in the remove method.
1409 Py_INCREF(cb_data)
1410 elm_entry_markup_filter_append(self.obj,
1411 py_elm_entry_filter_cb,
1412 <void *>cb_data)
1413 1424
1414 def markup_filter_prepend(self, func, data=None): 1425 def markup_filter_prepend(self, func, data=None):
1415 """Prepend a markup filter function for text inserted in the entry 1426 """Prepend a markup filter function for text inserted in the entry
@@ -1423,11 +1434,16 @@ cdef class Entry(LayoutClass):
1423 .. versionadded:: 1.8 1434 .. versionadded:: 1.8
1424 1435
1425 """ 1436 """
1437 if not callable(func):
1438 raise TypeError("func must be callable")
1439
1440 if not self.markup_filters:
1441 elm_entry_markup_filter_append(self.obj,
1442 py_elm_entry_filter_cb,
1443 NULL)
1444
1426 cb_data = (func, data) 1445 cb_data = (func, data)
1427 Py_INCREF(cb_data) 1446 self.markup_filters.insert(0, cb_data)
1428 elm_entry_markup_filter_prepend(self.obj,
1429 py_elm_entry_filter_cb,
1430 <void *>cb_data)
1431 1447
1432 def markup_filter_remove(self, func, data=None): 1448 def markup_filter_remove(self, func, data=None):
1433 """Remove a markup filter from the list 1449 """Remove a markup filter from the list
@@ -1441,11 +1457,24 @@ cdef class Entry(LayoutClass):
1441 .. versionadded:: 1.8 1457 .. versionadded:: 1.8
1442 1458
1443 """ 1459 """
1444 cb_data = (func, data) 1460 f = None
1445 Py_INCREF(cb_data) 1461 d = None
1462 lst = self.markup_filters
1463
1464 for i, (f, d) in enumerate(lst):
1465 if func is f and data is d:
1466 break
1467
1468 if f is not func or d is not data:
1469 raise ValueError("Callback was not registered with this object.")
1470
1471 lst.pop(i)
1472 if lst:
1473 return
1474
1446 elm_entry_markup_filter_remove(self.obj, 1475 elm_entry_markup_filter_remove(self.obj,
1447 py_elm_entry_filter_cb, 1476 py_elm_entry_filter_cb,
1448 <void *>cb_data) 1477 NULL)
1449 1478
1450 @DEPRECATED("1.8", "Use the module level markup_to_utf8() method instead.") 1479 @DEPRECATED("1.8", "Use the module level markup_to_utf8() method instead.")
1451 def markup_to_utf8(self, string): 1480 def markup_to_utf8(self, string):