diff options
author | Kai Huuhko <kai.huuhko@gmail.com> | 2014-06-05 18:15:38 +0300 |
---|---|---|
committer | Kai Huuhko <kai.huuhko@gmail.com> | 2014-06-05 18:16:14 +0300 |
commit | a0ecc4157274d473f056b89207f5dc54a8184e10 (patch) | |
tree | 6d439d9b7a7bea758c1a9217ef2b183b9866f967 | |
parent | 4f1efb1ee1c5263f17dc74338fe4d191a39195f3 (diff) |
Elementary.entry: Fix ref leak in filter callback handling.
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | efl/elementary/entry.pyx | 65 |
2 files changed, 47 insertions, 19 deletions
@@ -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 | ||
736 | class EntryAnchorInfo(object): | 739 | class 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): |