ó
âdc           @` sª   d  Z  d d l m Z m Z m Z m Z d d l Td d l Z e j d ƒ d d l	 Z	 d d l
 m Z d d	 l
 m Z d d l
 m Z d
 g Z d e f d „  ƒ  YZ d S(   u)   Custom popup usable for GTK text entries.i    (   t   absolute_importt   divisiont   print_functiont   unicode_literals(   t   *Nu   2.0i   (   t   utilsi   (   t   popup_hide_contextu
   EntryPopupt
   EntryPopupc           B` sX  e  Z d  Z d d d d „ Z e d „  ƒ Z e d „  ƒ Z e d „  ƒ Z e j d „  ƒ Z e d	 „  ƒ Z	 e d
 „  ƒ Z
 e d „  ƒ Z d „  Z d „  Z d „  Z d „  Z d „  Z e d „ Z d „  Z d „  Z d „  Z d „  Z d d „ Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d  „  Z  d! „  Z! d" „  Z" RS(#   i   iÿÿÿÿiÈ   i   c         C` s   | |  _  | |  _ | |  _ | |  _ t j d d ƒ |  _ |  j  j |  _	 |  j
 |  _ t j |  _ t j |  _ d „  |  _ t j |  _ t j d t ƒ |  _ t |  _ d  |  _ d |  _ d  |  _ d  |  _ t |  _ t |  _ d  |  _ |  j | | ƒ t j |  j |  j  |  j  ƒ |  _! |  j" ƒ  d  S(   Nt   return_valuec         S` s   | S(   N(    (   t   key_namet	   tree_patht   stop_event_propagation(    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyt   <lambda>,   t    u    (   NN(#   t   _entryt   _widtht   _heightt   _max_num_visible_rowst   pgutilst   create_empty_funct   Nonet   on_assign_from_selected_rowt   assign_textt   on_assign_last_valuet   assign_from_selected_rowt   on_row_left_mouse_button_presst
   empty_funct%   on_entry_left_mouse_button_press_funct$   on_entry_key_press_before_show_popupt   on_entry_key_presst"   on_entry_after_assign_by_key_presst   Truet%   on_entry_changed_show_popup_conditiont   trigger_popupt   _filter_rows_funct   _last_assigned_entry_textt&   _previous_assigned_entry_text_positiont   _previous_assigned_entry_textt   _show_popup_first_timet   Falset   _clear_filtert   _tree_view_widtht	   _init_guit   popup_hide_context_t   PopupHideContextt   _popupt   hidet   _popup_hide_contextt   _connect_events(   t   selft   entryt   column_typest   rowst   widtht   heightt   max_num_visible_rows(    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyt   __init__   s4    														c         C` s   |  j  S(   N(   t   _rows(   R1   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyR4   F   s    c         C` s   |  j  S(   N(   t   _rows_filtered(   R1   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyt   rows_filteredJ   s    c         C` s   |  j  S(   N(   R"   (   R1   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyt   filter_rows_funcN   s    c         C` sK   | |  _  | d  k	 r+ |  j j |  j ƒ n |  j j t j d t ƒ ƒ d  S(   NR   (   R"   R   R:   t   set_visible_funct   _filter_rowsR   R   R   (   R1   t   func(    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyR<   R   s    	c         C` s   |  j  S(   N(   R-   (   R1   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyt   popupZ   s    c         C` s   |  j  S(   N(   t
   _tree_view(   R1   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyt	   tree_view^   s    c         C` s   |  j  S(   N(   R#   (   R1   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyt   last_assigned_entry_textb   s    c         C` s   |  j  |  j ƒ d  S(   N(   R   R#   (   R1   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyt   assign_last_valuef   s    c         C` s…   |  j  ƒ  r t |  j ƒ d k r |  j j ƒ  |  j j |  j j ƒ  ƒ |  j j	 ƒ  |  j
 ƒ  |  j r |  j ƒ  t |  _ q n  d  S(   Ni    (   t   is_shownt   lenR:   R/   t&   connect_button_press_events_for_hidingR-   t
   set_screenR   t
   get_screent   showt   _update_positionR&   t   save_last_valueR'   (   R1   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyRJ   i   s    "
	
c         C` s-   |  j  ƒ  r) |  j j ƒ  |  j j ƒ  n  d  S(   N(   RE   R-   R.   R/   t)   disconnect_button_press_events_for_hiding(   R1   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyR.   w   s    c         C` s   |  j  j ƒ  S(   N(   R-   t
   get_mapped(   R1   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyRE   |   s    c         C` s  |  j  j ƒ  } | r. t d „  | Dƒ ƒ } n d } |  j  j d ƒ } | | } t | |  j ƒ } |  j d k rÖ |  j  j ƒ  j	 |  _ | |  j k rÖ t
 |  j j ƒ  j |  j j ƒ  j ƒ } |  j | d 7_ qÖ n  |  j  j |  j | | ƒ | d k r	|  j ƒ  n  d S(   uu  
    Resize the tree view in the popup.
    
    Update the height of the tree view according to the number of rows. If the
    number of rows is 0, hide the entire popup.
    
    Determine the initial width of the tree view based on the items displayed
    in the tree view. For subsequent calls of this function, the width of the
    tree view will remain the same.
    c         s` s   |  ] } | j  ƒ  d  Vq d S(   i   N(   t   cell_get_size(   t   .0t   column(    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pys	   <genexpr>Œ   s    i    u   vertical-separatori   N(   RA   t   get_columnst   maxt   style_get_propertyt   minR   R)   R   t   get_allocationR5   t   intt   _scrolled_windowt   get_hadjustmentt   uppert	   page_sizet   set_size_requestR.   (   R1   t   num_rowst   columnst   cell_heightt   vertical_spacingt
   row_heightt   num_visible_rowst   vscrollbar_width(    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyt   resize   s"    
c         C` sP   | s |  j  j | ƒ } n  | d  k	 rL |  j  j d | |  j  j | ƒ ƒ n  d  S(   Nu   row-changed(   R:   t   convert_child_path_to_pathR   t   emitt   get_iter(   R1   t   row_patht   is_path_filtered(    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyt   refresh_row¡   s
    	c         C` s*   |  j  j | f ƒ |  j  j | f ƒ d  S(   N(   RA   t
   set_cursor(   R1   t   row_num(    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyt
   select_row©   s    c         C` s3   |  j  j t |  j ƒ f ƒ |  j  j ƒ  j ƒ  d  S(   N(   RB   Rk   RF   R:   t   get_selectiont   unselect_all(   R1   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyt   unselect°   s    c         C` s;   |  j  j ƒ  j ƒ  \ } } | d  k r+ d S|  j | | ƒ S(   N(   NN(   RA   Rn   t   get_selectedR   R   (   R1   t
   tree_modelt	   tree_iter(    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyR   µ   s    c         C` s   |  j  | ƒ |  j ƒ  S(   N(   Rm   R   (   R1   Rl   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyt   select_and_assign_row¼   s    i    c         C` sç   | d k r$ |  j | ƒ \ } } n‘ t | ƒ r? | | ƒ } n  | d | k r… |  j j | f ƒ |  j ƒ  |  j ƒ  d \ } } n0 t | ƒ r  | | ƒ } n  |  j | ƒ \ } } |  j |  j |  j	 | | ƒ | |  _ | |  _	 d S(   uF  
    After a particular key is pressed, select the row specified by `tree_path`
    and assign the value from the selected row to the entry.
    
    One can pass functions for `next_row` and `current_row_before_unselection`
    parameters if `tree_path` is `None` and `tree_path` is used to compute these
    parameters.
    i    N(   NN(
   R   Rt   t   callableRA   t   scroll_to_cellRp   RD   R   R$   R%   (   R1   R
   t   next_rowt    next_row_if_no_current_selectiont   current_row_before_unselectiont    row_to_scroll_before_unselectiont   positiont   text(    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyt%   select_and_assign_row_after_key_pressÀ   s&    

	c         C` s   |  j  j ƒ  |  _ d  S(   N(   R   t   get_textR#   (   R1   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyRL   é   s    c         C` so  t  j | Œ  |  _ x | D] } |  j j | ƒ q W|  j j ƒ  |  _ t  j d |  j ƒ |  _ |  j j t	 ƒ |  j j
 t ƒ |  j j t ƒ |  j j |  j |  j ƒ t  j ƒ  |  _ |  j j t  j t  j ƒ |  j j t  j ƒ |  j j |  j ƒ |  j j ƒ  j d d ƒ t  j d t  j ƒ |  _ |  j j t ƒ |  j j t  j j ƒ |  j j |  j ƒ |  j j  ƒ  d  S(   Nt   modeliÿÿÿÿi    t   type(!   t   gtkt	   ListStoreR9   t   appendt
   filter_newR:   t   TreeViewRA   t   set_hover_selectionR   t   set_headers_visibleR'   t   set_enable_searchR\   R   R   t   ScrolledWindowRX   t
   set_policyt   POLICY_NEVERt   POLICY_AUTOMATICt   set_shadow_typet   SHADOW_ETCHED_INt   addt   get_vscrollbart   Windowt   WINDOW_POPUPR-   t   set_resizablet   set_type_hintt   gdkt   WINDOW_TYPE_HINT_TOOLTIPt   show_all(   R1   R3   R4   t   row(    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyR*   ì   s&    c         C` sÇ   |  j  j d |  j ƒ |  j  j d |  j ƒ |  j  j d |  j ƒ |  j  j d |  j ƒ |  j j d |  j ƒ |  j j d |  j	 ƒ |  j  |  j
 |  j j ƒ  g } x | D] } |  j j | ƒ q© Wd  S(   Nu   changedu   button-press-eventu   key-press-eventu   focus-out-eventu   realize(   R   t   connectt   _on_entry_changedt!   _on_entry_left_mouse_button_presst   _on_entry_key_press_eventt   _on_entry_focus_out_eventRA   t   connect_aftert   _on_after_tree_view_realizet    _on_tree_view_button_press_eventR-   RX   R   R/   t,   exclude_widget_from_hiding_with_button_press(   R1   t5   wigets_to_exclude_from_hiding_popup_with_button_presst   widget(    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyR0     s    c         C` s5   t  j |  j ƒ } | d  k	 r1 |  j j | Œ  n  d  S(   N(   t   utils_t   get_position_below_widgetR   R   R-   t   move(   R1   R{   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyRK     s    c         C` s!   |  j  r t S|  j | | ƒ Sd  S(   N(   R(   R   R"   (   R1   R4   t   row_iter(    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyR>   #  s    	c      	   ` sô  t  j j | j ƒ } ˆ  j ƒ  rb | d k rb ˆ  j ƒ  ˆ  j } ˆ  j ƒ  | r^ ˆ  j ƒ  n  t	 Sˆ  j ƒ  rìˆ  j
 j ƒ  \ } } t	 } | d k rÇ ˆ  j | d	 d
 „  d t ˆ  j ƒ d d d ƒn| d k rˆ  j | d	 d „  d d d t ˆ  j ƒ d ƒnÔ | d k rIˆ  j | d	 ‡  f d †  d t ˆ  j ƒ d d d ƒn | d k rˆ  j | d	 ‡  f d †  d d d t ˆ  j ƒ d ƒnL | d k r°ˆ  j ƒ  ˆ  j ƒ  n) | d k rÓˆ  j ƒ  ˆ  j ƒ  n t } ˆ  j | | | ƒ St Sd  S(   Nu   Upu   KP_Upu   Downu   KP_Downu   Page_Upu
   KP_Page_Upu	   Page_Downu   KP_Page_DownRw   c         S` s   |  d d S(   Ni    i   (    (   R
   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyR   B  R   Rx   i   Ry   i    c         S` s   |  d d S(   Ni    i   (    (   R
   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyR   H  R   c         ` s   t  |  d ˆ  j d ƒ S(   Ni    (   RS   R   (   R
   (   R1   (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyR   N  R   c         ` s%   t  |  d ˆ  j t ˆ  j ƒ d ƒ S(   Ni    i   (   RU   R   RF   R:   (   R
   (   R1   (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyR   T  s   u   Returnu   KP_Enteru   Escape(   u   Upu   KP_Upu   Downu   KP_Downu   Page_Upu
   KP_Page_Upu	   Page_Downu   KP_Page_Down(   u   Upu   KP_Up(   u   Downu   KP_Down(   u   Page_Upu
   KP_Page_Up(   u	   Page_Downu   KP_Page_Down(   u   Returnu   KP_Enter(   R   R•   t   keyval_namet   keyvalRE   R   R&   RJ   Rp   R   RA   t
   get_cursorR}   RF   R:   RL   R.   RD   R'   R   (   R1   R2   t   eventR	   t   show_popup_first_timeR
   t   unused_R   (    (   R1   sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyRœ   )  s^     	
	
	
	


c         C` sÁ   |  j  r½ |  j ƒ  d  |  _ d  |  _ |  j ƒ  s? |  j ƒ  d  S|  j } | sw |  j j	 ƒ  |  j
 d t |  j ƒ ƒ n  |  j ƒ  |  j ƒ  | r½ |  j j	 ƒ  |  j
 d t |  j ƒ ƒ q½ n  d  S(   NR]   (   R!   RL   R   R$   R%   R    R.   R&   R:   t   refilterRd   RF   Rp   RJ   (   R1   R2   R¬   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyRš   e  s     	
		
	

c         C` s°   | j  |  j k r¬ |  j j ƒ  sA |  j j ƒ  |  j j d ƒ n  t |  _ |  j j	 ƒ  t
 |  _ |  j } | s‹ |  j d t |  j ƒ ƒ n  |  j ƒ  |  j ƒ  |  j ƒ  n  d  S(   NiÿÿÿÿR]   (   t   buttont   _BUTTON_MOUSE_LEFTR   t	   has_focust
   grab_focust   set_positionR   R(   R:   R®   R'   R&   Rd   RF   RJ   Rp   R   (   R1   R2   R«   R¬   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyR›     s    			

c         C` s7   | j  |  j k r3 |  j ƒ  |  j ƒ  |  j ƒ  n  d  S(   N(   R¯   R°   R   RL   R.   (   R1   RB   R«   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyR    —  s    

c         C` s   |  j  ƒ  d  S(   N(   RL   (   R1   R2   R«   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyR   Ÿ  s    c         C` s   |  j  d t |  j ƒ ƒ d  S(   NR]   (   Rd   RF   R:   (   R1   RB   (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyRŸ   ¢  s    (#   t   __name__t
   __module__R°   R8   t   propertyR4   R;   R<   t   setterR@   RB   RC   RD   RJ   R.   RE   Rd   R   Rj   Rm   Rp   R   Rt   R}   RL   R*   R0   RK   R>   Rœ   Rš   R›   R    R   RŸ   (    (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyR      s>   '					"				
#		 				<				(   t   __doc__t
   __future__R    R   R   R   t   future.builtinst   pygtkt   requireR   R   R   R   R   R+   R¤   t   __all__t   objectR   (    (    (    sQ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/gui/entry_popup.pyt   <module>   s   "
	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 # -*- coding: utf-8 -*-

"""Undo context for GTK text entries."""

from __future__ import absolute_import, division, print_function, unicode_literals
from future.builtins import *

import collections

import pygtk
pygtk.require('2.0')
import gtk

__all__ = [
  'EntryUndoContext',
]


class EntryUndoContext(object):
  """
  This class adds undo/redo capabilities to a `gtk.Entry` object.
  
  Attributes:
  
  * `undo_enabled` - If `True`, add user actions (insert text, delete text) to
    the undo history.
  """
  
  _ActionData = collections.namedtuple('_ActionData', ['action_type', 'position', 'text'])
  
  _ACTION_TYPES = ['insert', 'delete']
  
  def __init__(self, entry):
    self._entry = entry
    
    self.undo_enabled = True
    
    self._undo_stack = []
    self._redo_stack = []
    
    self._last_action_group = []
    self._last_action_type = None
    
    self._cursor_changed_by_action = False
    
    self._entry.connect('insert-text', self._on_entry_insert_text)
    self._entry.connect('delete-text', self._on_entry_delete_text)
    self._entry.connect('notify::cursor-position', self._on_entry_notify_cursor_position)
    self._entry.connect('key-press-event', self._on_entry_key_press_event)
  
  def undo(self):
    self._undo_redo(
      self._undo_stack,
      self._redo_stack,
      action_handlers={
        'insert': lambda action_data: self._entry.delete_text(
          action_data.position, action_data.position + len(action_data.text)),
        'delete': lambda action_data: self._entry.insert_text(
          action_data.text, action_data.position)},
      action_handlers_get_cursor_position={
        'insert': lambda last_action_data: last_action_data.position,
        'delete': lambda last_action_data: (
          last_action_data.position + len(last_action_data.text))},
      actions_iterator=reversed)
  
  def redo(self):
    self._undo_redo(
      self._redo_stack,
      self._undo_stack,
      action_handlers={
        'insert': lambda action_data: self._entry.insert_text(
          action_data.text, action_data.position),
        'delete': lambda action_data: self._entry.delete_text(
          action_data.position, action_data.position + len(action_data.text))},
      action_handlers_get_cursor_position={
        'insert': lambda last_action_data: (
          last_action_data.position + len(last_action_data.text)),
        'delete': lambda last_action_data: last_action_data.position})
  
  def undo_push(self, undo_push_list):
    """
    Manually add changes to the undo history. The changes are treated as one
    undo group (i.e. a single `undo()` call will undo all specified changes at
    once).
    
    If there are pending changes not yet added to the undo history, they are
    added first (as a separate undo group), and then the changes specified in
    this method.
    
    Calling this method completely removes the redo history.
    
    Parameters:
    
    * `undo_push_list` - List of `(action_type, position, text)` tuples to add
      as one undo action. `action_type` can be 'insert' for text insertion or
      'delete' for text deletion (other values raise `ValueError`). `position`
      is the starting entry cursor position of the changed text. `text` is the
      changed text.
    
    Raises:
    
    * `ValueError` - invalid `action_type`.
    """
    self._redo_stack = []
    
    self._undo_stack_push()
    
    for action_type, position, text in undo_push_list:
      if action_type not in self._ACTION_TYPES:
        raise ValueError('invalid action type "{0}"'.format(action_type))
      self._last_action_group.append(self._ActionData(action_type, position, text))
    
    self._undo_stack_push()
  
  def can_undo(self):
    return bool(self._undo_stack)
  
  def can_redo(self):
    return bool(self._redo_stack)
  
  def _on_entry_insert_text(self, entry, new_text, new_text_length, position):
    if self.undo_enabled and new_text:
      self._on_entry_action(entry.get_position(), new_text, 'insert')
   
  def _on_entry_delete_text(self, entry, start, end):
    if self.undo_enabled:
      text_to_delete = entry.get_text()[start:end]
      if text_to_delete:
        self._on_entry_action(start, text_to_delete, 'delete')
  
  def _on_entry_notify_cursor_position(self, entry, property_spec):
    if self._cursor_changed_by_action:
      self._cursor_changed_by_action = False
    else:
      self._undo_stack_push()
  
  def _on_entry_key_press_event(self, entry, event):
    if (event.state & gtk.accelerator_get_default_mod_mask()) == gtk.gdk.CONTROL_MASK:
      key_name = gtk.gdk.keyval_name(gtk.gdk.keyval_to_lower(event.keyval))
      if key_name == 'z':
        self.undo()
        return True
      elif key_name == 'y':
        self.redo()
        return True
  
  def _on_entry_action(self, position, text, action_type):
    self._redo_stack = []
    
    if self._last_action_type != action_type:
      self._undo_stack_push()
    
    self._last_action_group.append(self._ActionData(action_type, position, text))
    self._last_action_type = action_type
    
    self._cursor_changed_by_action = True
  
  def _undo_redo(
        self,
        stack_to_pop_from,
        stack_to_push_to,
        action_handlers,
        action_handlers_get_cursor_position,
        actions_iterator=None):
    self._undo_stack_push()
    
    if not stack_to_pop_from:
      return
    
    actions = stack_to_pop_from.pop()
    
    if actions_iterator is None:
      action_list = actions
    else:
      action_list = list(actions_iterator(actions))
    
    stack_to_push_to.append(actions)
    
    self.undo_enabled = False
    
    for action in action_list:
      action_handlers[action.action_type](action)
    
    self._entry.set_position(
      action_handlers_get_cursor_position[action_list[-1].action_type](action_list[-1]))
    
    self.undo_enabled = True
  
  def _undo_stack_push(self):
    if self._last_action_group:
      self._undo_stack.append(self._last_action_group)
      self._last_action_group = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      