U
    HI^1                 =   @   s  d Z dZddlZddlZddlZddlZddlmZ dd Zdd Z	ddl
mZ ed	d
 ddlmZ edd ddlmZ edd ddlmZ ddlmZ ddlZedadd Zdd Zdd Zddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5d6d7d8d9d:d;d<d=d>d?d@dAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTg=ZdUdV ZdWdX ZdYZdZZG d[d\ d\ZG d]d^ d^eZG d_d` d`ejZ e!dakrddl"Z"e"# \Z$Z%e$re&db n
e&d dS )cz5
This file implements the ibus engine for ibus-table
)	TabEngine    Ndgettextc                 C   s
   t d| S )Nz
ibus-tabler   a r   %/usr/share/ibus-table/engine/table.py<lambda>&       r	   c                 C   s   | S Nr   r   r   r   r   r	   '   r
   )require_versionIBusz1.0)r   Gioz2.0)r   GLib)r   )GObjectc                 C   s   t | dkS )u  
    Use our own function instead of ascii.ispunct()
    from “from curses import ascii” because the behaviour
    of the latter is kind of weird. In Python 3.3.2 it does
    for example:

        # >>> from curses import ascii
        # >>> ascii.ispunct('.')
        # True
        # >>> ascii.ispunct(u'.')
        # True
        # >>> ascii.ispunct('a')
        # False
        # >>> ascii.ispunct(u'a')
        # False
        # >>>
        # >>> ascii.ispunct(u'あ')
        # True
        # >>> ascii.ispunct('あ')
        # True
        # >>>

    あ isn’t punctuation. ascii.ispunct() only really works
    in the ascii range, it returns weird results when used
    over the whole unicode range. Maybe we should better use
    unicodedata.category(), which works fine to figure out
    what is punctuation for all of unicode. But at the moment
    I am only porting from Python2 to Python3 and just want to
    preserve the original behaviour for the moment.

    By the way, Python 3.6.6 does not seem the  above bug
    anymore, in Python 3.6.6 we  get

        # >>> from curses import ascii
        # >>> ascii.ispunct('あ')
        # False
        # >>>

    Examples:

    >>> ascii_ispunct('.')
    True
    >>> ascii_ispunct('a')
    False
    >>> ascii_ispunct('あ')
    False
    z !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~)bool)	characterr   r   r   ascii_ispunct5   s    0r   c                 C   s,   | d@ d> |d@ d>  |d@ d>  |d@  S )zReturns a 32bit ARGB value            r   )Zalpharedgreenbluer   r   r   argbg   s    


r   c                 C   s   t d| ||S )zCReturns a 32bit ARGB value with the alpha value set to fully opaquer   )r   )r   r   r   r   r   r   rgbn   s    r   )    i 0     )!   i  ^   )   i     )   i  r   )   i  r   )   i  r   )   i  r   )i   i  r   )ia  i0  r   )ib  i0  r"   )id  i0  r   )ie  i0  r   )if  i0  r   )ig  i0  r   )ih  i0  r   )ii  i0  r   )ij  i0  r   )ik  i0  r   )il  i0  r   )im  i0  r   )in  i0  r   )io  i0  r   )ip  i0  r   )iq  i0  r   )ir  i0  r   )is  i0  r   )it  i0  r   )iu  i0  r"   )iw  i0  r   )ix  i0  r   )iy  i0  r   )iz  i0  r   )i{  i0  r   )i|  i0  r   )i}  i0  r   )i~  i0  r   )i  i0  r   )i  i0  r   )i  i0  r   )i  i0  r   )i  i0  r   )i  i0  r   )i  i0     )i  i0  r   )i  i0  r   )i  i0  r   )i  i0  r   )i  i0     )i  i0  r   )i  i0  r   )i  i0  r'   )i  i0  r   )i  i0  r   )i  id1  r   )i  i11     )i  iO1  r'   )i  iU1  r'   )i  i[1  	   )i  i!     )i  i%  r   )i  i%  r   c                 C   sb   t | }tD ]P\}}}||kr||| k rtjdkrHt|| |   S t|| |   S q| S )u1  
    Convert a character to full width if possible.

    :param char: A character to convert to full width
    :type char: String
    :rtype: String

    Examples:

    >>> unichar_half_to_full('a')
    'ａ'
    >>> unichar_half_to_full('ａ')
    'ａ'
    >>> unichar_half_to_full('☺')
    '☺'
       r   r   ord__HALF_FULL_TABLEsysversion_infochrZunichrcharcodeZhalfZfullsizer   r   r   unichar_half_to_full   s    
r8   c                 C   sb   t | }tD ]P\}}}||kr||| k rtjdkrHt|| |   S t|| |   S q| S )u-  
    Convert a character to half width if possible.

    :param char: A character to convert to half width
    :type char: String
    :rtype: String

    Examples:

    >>> unichar_full_to_half('ａ')
    'a'
    >>> unichar_full_to_half('a')
    'a'
    >>> unichar_full_to_half('☺')
    '☺'
    r,   r.   r4   r   r   r   unichar_full_to_half   s    
r9   r   r)   c                   @   s    e Zd ZdZdd Zdd ZdS )KeyEventzSKey event class used to make the checking of details of the key
    event easy
    c                 C   s  || _ || _|| _t| j | _t| j | _| jtjj	@ dk| _
| jtjj@ dk| _| jtjj@ dk| _| jtjj@ dk| _| jtjj@ dk| _| jtjj@ dk| _| jtjj@ dk| _| jtjj@ dk| _| jtjj@ dk| _| jtjj@ dk| _| jtjj@ dk| _| jtjj@ dk| _ | jtjj!@ dk| _"| jtjj#@ dk| _$| jtjj%@ dk| _&| jtjj'@ dk| _(| jtjj)@ dk| _*| jtjj+@ dk| _,d S Nr   )-valr6   stater   keyval_namenamekeyval_to_unicodeunicodeModifierType
SHIFT_MASKshiftZ	LOCK_MASKlockCONTROL_MASKcontrol	MOD1_MASKmod1Z	MOD2_MASKZmod2Z	MOD3_MASKZmod3Z	MOD4_MASKZmod4Z	MOD5_MASKmod5ZBUTTON1_MASKZbutton1ZBUTTON2_MASKZbutton2ZBUTTON3_MASKZbutton3ZBUTTON4_MASKZbutton4ZBUTTON5_MASKZbutton5Z
SUPER_MASKsuperZ
HYPER_MASKZhyperZ	META_MASKmetaRELEASE_MASKreleaseZMODIFIER_MASKZmodifierselfkeyvalkeycoder=   r   r   r   __init__   s.    zKeyEvent.__init__c                 C   s8   d| j | j| j| j| jf d| j| j| j| j| j	f  S )Nz3val=%s code=%s state=0x%08x name='%s' unicode='%s' z/shift=%s control=%s mod1=%s mod5=%s release=%s
)
r<   r6   r=   r?   rA   rD   rG   rI   rJ   rN   rP   r   r   r   __str__  s$    zKeyEvent.__str__N)__name__
__module____qualname____doc__rS   rU   r   r   r   r   r:      s   r:   c                   @   sn  e Zd ZdZdd ZddejjfddZdd	 Z	d
d Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 Zd2d3 Zd[d6d7Zd8d9 Z d:d; Z!d<d= Z"d>d? Z#d@dA Z$dBdC Z%dDdE Z&dFdG Z'dHdI Z(dJdK Z)dLdM Z*dNdO Z+dPdQ Z,dRdS Z-dTdU Z.dVdW Z/dXdY Z0dZS )\Editorz)Hold user inputs chars and preedit stringc                 C   s"  |
| _ || _t|	| _d| _|| _|| _|| _|| _|| _	|| _
|| _d| _d| _d| _d| _g | _g | _g | _g | _d| _t| j jd| _| j  }|d krd}dd dd |d	D D | _t| jd
| _| jd ks| jt | jkrt | j| _t| jd| _!| j!d kr.| j " | _!| j#| j| j| j!d| _$d| _%t| j&d| _'t| jd| _(| j(d krt)dkrt*j+,d| j(  | j(d kr| - | _(t| jd| _.| j.d kr| j jdd kr| j jd/ dk| _.| j.d krt| j&d| _.d S )N    r   Zchar_promptsz1,2,3,4,5,6,7,8,9c                 S   s   g | ]}t |qS r   r   Zkeyval_from_name).0yr   r   r   
<listcomp>X  s   z#Editor.__init__.<locals>.<listcomp>c                 S   s   g | ]}|  qS r   )stripr^   xr   r   r   r`   Z  s     ,lookuptablepagesizelookuptableorientation	page_sizeselect_keysorientationFonecharchinesemoder   z)Chinese mode found in Gsettings, mode=%s

autoselectauto_selecttrue)0db
_gsettingsint_max_key_length_max_key_length_pinyin_valid_input_chars_pinyin_valid_input_chars_single_wildcard_char_multi_wildcard_char_auto_wildcard_full_width_letter_full_width_punct_chars_valid_chars_invalid#_chars_valid_update_candidates_last%_chars_invalid_update_candidates_last_candidates_candidates_previous_u_chars_strings_cursor_precommitevalime_propertiesget_prompt_charactersget_select_keyssplit_select_keysit_utilvariant_to_valueget_user_value
_page_sizelen_orientationZget_orientationget_new_lookup_table_lookup_table_py_mode	get_value_onechar_chinese_modeDEBUG_LEVELr1   stderrwriteget_default_chinese_mode_auto_selectlower)rP   Z	gsettingsvalid_input_charsZpinyin_valid_input_charssingle_wildcard_charmulti_wildcard_charauto_wildcardZfull_width_letterZfull_width_punctmax_key_lengthZdatabaseZselect_keys_csvr   r   r   rS     s    









zEditor.__init__
   )
1   2   3   4   5   6   7   8   9   0   c              	   C   sf   |dk rd}|t |kr t |}tj|dddd}|D ] }|tjdt|  q6|| |S )z
        (49, 50, 51, 52, 53, 54, 55, 56, 57, 48( are the key codes
        for the characters ('1', '2', '3', '4', '5', '6', '7', '8', '0')
        r   r   T)rh   
cursor_posZcursor_visibleroundz%s.)r   r   ZLookupTableZappend_labelTextnew_from_stringr>   set_orientation)rP   rh   ri   rj   Zlookup_tablerR   r   r   r   r     s     
zEditor.get_new_lookup_tablec                 C   s   | j S )a   
        Returns the list of key codes for the select keys.
        For example, if the select keys are ["1", "2", ...] the
        key codes are [49, 50, ...]. If the select keys are
        ["F1", "F2", ...] the key codes are [65470, 65471, ...]
        )r   rT   r   r   r   r     s    zEditor.get_select_keysc                 C   s  | j  }|dkr2tdkr.tjdd|   |S z6dtjkrvtjd dd 	 }tdkrtjdd|   ntdtjkrtjd dd 	 }tdkrtjdd	|   n4tjd
 dd 	 }tdkrtjdd|   d|ksd|krW dS d|ks d|ks d|kr&W dS | j j
rLtdkrFtjd W dS tdkrbtjd W dS W n   ddl}|  Y dS X dS )a  
        Use db value or LC_CTYPE in your box to determine the _chinese_mode

        0 means to show simplified Chinese only
        1 means to show traditional Chinese only
        2 means to show all characters but show simplified Chinese first
        3 means to show all characters but show traditional Chinese first
        4 means to show all characters

        If nothing can be found return 4 to avoid any special
        Chinese filtering or sorting.

        r   r   zget_default_chinese_mode(): z0default Chinese mode found in database, mode=%s
LC_ALL.z__lc=%s found in LC_ALL
LC_CTYPEz__lc=%s found in LC_CTYPE
ZLANGz__lc=%s  found in LANG
Z_cnZ_sgr"   Z_hkZ_twZ_mor-   ub   get_default_chinese_mode(): last fallback, database is Chinese but we don’t know which variant.
r+   zQget_default_chinese_mode(): last fallback, database is not Chinese, returning 4.
N)rp   get_chinese_moder   r1   r   r   osenvironr   r   _is_chinese	traceback	print_exc)rP   Z_Editor__db_chinese_modeZ_Editor__lcr   r   r   r   r     sx    






zEditor.get_default_chinese_modec                 C   s:   t dkrtjd |   g | _g | _d| _|   dS )uH   
        Clear all input, whether committed to preëdit or not.
        r   zclear_all_input_and_preedit()
r   N)	r   r1   r   r   $clear_input_not_committed_to_preeditr   r   r   update_candidatesrT   r   r   r   clear_all_input_and_preedit  s    z"Editor.clear_all_input_and_preeditc                 C   s   | j | j dkS )u   Checks whether the preëdit is empty

        Returns True if the preëdit is empty, False if not.

        :rtype: boolean
        r\   r|   r}   rT   r   r   r   is_empty  s    zEditor.is_emptyc                 C   sR   t dkrtjd d| _d| _d| _d| _| j	  | j
d g | _g | _dS )uO   
        Clear the input which has not yet been committed to preëdit.
        r   z'clear_input_not_committed_to_preedit()
r\   TN)r   r1   r   r   r|   r}   r~   r   r   clearset_cursor_visibler   r   rT   r   r   r   r     s    
z+Editor.clear_input_not_committed_to_preeditc                 C   sh   | j s>| js"|| j| j | j ks>| jrN|| j| j | j krN|  j |7  _ n|  j|7  _|  }|S )u   
        Add input character and update candidates.

        Returns “True” if candidates were found, “False” if not.
        )r}   r   ru   rw   rx   rv   r|   r   )rP   r5   resr   r   r   	add_input  s2    zEditor.add_inputc                 C   s   d}| j r&| j d }| j dd | _ n`| jr| jd }| jdd | _| js| jr| j| jd | _| j| jd  |  jd8  _|   |S )z'remove and display last input char heldr\   Nr   )r}   r|   r   popr   r   r   )rP   Zlast_input_charr   r   r   	pop_input1  s    

zEditor.pop_inputc                 C   s   | j | j S )z&get characters held, valid and invalidr   rT   r   r   r   get_input_charsB  s    zEditor.get_input_charsc                 C   s   | j | d | }| j | |d  }| j| | j | | j|| j| | j || | j|d | j| | j |d | d S )Nr   )r   r   r   insertrp   parse_phrase)rP   indexZindex_in_phraseheadtailr   r   r   "split_strings_committed_to_preeditF  s    z)Editor.split_strings_committed_to_preeditc                 C   s`   | j r
dS |  r|   | js$dS | jdkr2dS | j| jd | _| j| jd | _d| _dS )u   Remove preëdit left of cursorNr   )r}   r   commit_to_preeditr   r   r   rT   r   r   r   remove_preedit_before_cursorP  s    
z#Editor.remove_preedit_before_cursorc                 C   sl   | j r
dS |  r|   | js$dS | jt| jkr8dS | jd| j | _| jd| j | _t| j| _dS )u   Remove preëdit right of cursorN)r}   r   r   r   r   r   r   rT   r   r   r   remove_preedit_after_cursor^  s    z"Editor.remove_preedit_after_cursorc                 C   sj   | j r
dS |  r|   | js$dS | jdk r2dS |  jd8  _| j| j| _| j| j |   dS )u>   Remove character before cursor in strings comitted to preëditNr   )	r}   r   r   r   r   r   r   r|   r   rT   r   r   r   &remove_preedit_character_before_cursorl  s    
z-Editor.remove_preedit_character_before_cursorc                 C   s\   | j r
dS |  r|   | js$dS | jt| jd kr<dS | j| j | j| j dS )u>   Remove character after cursor in strings committed to preëditNr   )r}   r   r   r   r   r   r   r   rT   r   r   r   %remove_preedit_character_after_cursor{  s    z,Editor.remove_preedit_character_after_cursorc                 C   sT   d}d}d}|   r|   }| jrJt| jd| j }t| j| jd }|||fS )uL  Returns the tabkeys which were used to type the parts
        of the preëdit string.

        Such as “(left_of_current_edit, current_edit, right_of_current_edit)”

        “left_of_current_edit” and “right_of_current_edit” are
        strings of tabkeys which have been typed to get the phrases
        which have already been committed to preëdit, but not
        “really” committed yet. “current_edit” is the string of
        tabkeys of the part of the preëdit string which is not
        committed at all.

        For example, the return value could look like:

        (('gggg', 'aahw'), 'adwu', ('ijgl', 'jbus'))

        See also get_preedit_string_parts() which might return something
        like

        (('王', '工具'), '其', ('漫画', '最新'))

        when the wubi-jidian86 table is used.
        r   r\   N)r   r   tupler   rP   left_of_current_editcurrent_editright_of_current_editr   r   r   get_preedit_tabkeys_parts  s    z Editor.get_preedit_tabkeys_partsc                 C   s&   |   \}}}d|| d| S )uh   Returns the tabkeys which belong to the parts of the preëdit
        string as a single string
        r\   )r   join)rP   Zleft_tabkeysZcurrent_tabkeysZright_tabkeysr   r   r   get_preedit_tabkeys_complete  s    z#Editor.get_preedit_tabkeys_completec                 C   st   d}d}d}| j r,| j t| j  d }n|  r<|  }| jrjt| jd| j }t| j| jd }|||fS )u  Returns the phrases which are parts of the preëdit string.

        Such as “(left_of_current_edit, current_edit, right_of_current_edit)”

        “left_of_current_edit” and “right_of_current_edit” are
        tuples of strings which have already been committed to preëdit, but not
        “really” committed yet. “current_edit” is the phrase in the part of the
        preëdit string which is not yet committed at all.

        For example, the return value could look like:

        (('王', '工具'), '其', ('漫画', '最新'))

        See also get_preedit_tabkeys_parts() which might return something
        like

        (('gggg', 'aahw'), 'adwu', ('ijgl', 'jbus'))

        when the wubi-jidian86 table is used.
        r   r\   r   N)r   rr   r   get_cursor_posr   r   r   r   r   r   r   r   get_preedit_string_parts  s&    zEditor.get_preedit_string_partsc                 C   s&   |   \}}}d|| d| S )u_   Returns the phrases which are parts of the preëdit string as a
        single string

        r\   )r   r   )rP   Zleft_stringsZcurrent_stringZright_stringsr   r   r   get_preedit_string_complete  s    z"Editor.get_preedit_string_completec                 C   sn   d}| j r2| jr2| jd| j  D ]}|t|7 }q | jrZ|t| jt| j  d 7 }n|t|  7 }|S )u%   Get caret position in preëdit stringr   Nr   )r   r   r   r   rr   r   r   r   )rP   Zcaretpartr   r   r   	get_caret  s    zEditor.get_caretc                 C   sx   | j r
dS |  r|   | js$dS | jdkr2dS t| j| jd  dkrZ|  jd8  _n| | jd d |   dS )u(   Move cursor left in the preëdit string.Nr   r   r   r}   r   r   r   r   r   r   r   rT   r   r   r   
arrow_left  s    
 zEditor.arrow_leftc                 C   s|   | j r
dS |  r|   | js$dS | jt| jkr8dS |  jd7  _t| j| jd  dkrp| | jd d |   dS )u)   Move cursor right in the preëdit string.Nr   r   rT   r   r   r   arrow_right  s     zEditor.arrow_rightc                 C   s6   | j r
dS |  r|   | js$dS d| _|   dS )u4   Move cursor to the beginning of the preëdit string.Nr   )r}   r   r   r   r   r   rT   r   r   r   control_arrow_left  s    zEditor.control_arrow_leftc                 C   s<   | j r
dS |  r|   | js$dS t| j| _|   dS )u-   Move cursor to the end of the preëdit stringN)r}   r   r   r   r   r   r   rT   r   r   r   control_arrow_right   s    zEditor.control_arrow_rightr\   r   c              	   C   sF  t dkr&tjdd||||d   |r.|s2dS | j}| jrL|| jd}| jr`|| jd}t	|}|dd}|dd	}t
d
| |}|r|| d }n|}t dkrtjddd|i  d| j|d   d}| jjrp| jrp|dddddddddd}| j|}	|	r8|	d }d}
|D ]*}|| jkr`|
| j| 7 }
n|
|7 }
q@|
}| jsd}|D ]*}|| jkr|| j| 7 }n||7 }q|}|d | }|r|d | }t }|ttdddd t| | js*|d k r*|ttd!d d"d t| nT| js^|d kr^|ttd d d d t| n |ttd d d d t| t d krdt| d t| }||7 }|ttd d#d t|t| t| tj|}d }||dkr*||}|| | | |  |d7 }q| j !| | j "d$ dS )%z append candidate to lookup_tabler   zappend_candidate() z6tabkeys=%(t)s phrase=%(p)s freq=%(f)s user_freq=%(u)s
)tpfuNZ_multi_wildchard_char_Z_single_wildchard_char_z.*z.?^z(remaining_tabkeys=%(remaining_tabkeys)s remaining_tabkeysz4self._chars_valid=%(chars_valid)s phrase=%(phrase)s
)Zchars_validphraser\   !u   ↑1@u   ↑2#u   ↑3$u   ↑4%u   ↑5r    z      s   r!   r   w      r   T)#r   r1   r   r   r|   rx   replacerw   reescapematchendrp   r   r   find_zi_coder   r   AttrListappendattr_foreground_newr   r   strr   r   r   append_attributeget_attr_typer   get_start_indexget_end_indexr   Zappend_candidater   )rP   tabkeysr   freq	user_freqZregexpr   r   Z
table_codeZpossible_table_codesZtable_code_newr5   Zremaining_tabkeys_newZcandidate_textattrsZ
debug_texttextiattrr   r   r    append_candidate_to_lookup_table+  s      
     
  
  
  
  



z'Editor.append_candidate_to_lookup_tablec                 C   s  t dkr\tjdd| j  d| j  d| j  d| j  d| j  d| j	j
  d	| j   | j| jkr~| j| jkr~t| jS | j| _| j| _| j  | jd
 | js| jsg | _| j| _dS | jr| j	jr| j	j| j| j| j| jd| _n&| j	j| j| j| j| j| j| jd| _| j| j| jfkr| j}| j}t|r`| jd rVt|}nt|}n| jd rvt|}nt|}| jd||ddf | jr|    | j| _d
S |  j| jd 7  _| jdd | _| j| _| j| _dS )u   
        Searches for candidates and updates the lookuptable.

        Returns “True” if candidates were found and “False” if not.

        :rtype: Boolean
        r   zupdate_candidates() zself._chars_valid=%s zself._chars_invalid=%s z,self._chars_valid_update_candidates_last=%s z.self._chars_invalid_update_candidates_last=%s zself._candidates=%s zself.db.startchars=%s zself._strings=%s
TF)r  chinese_moder   r   )r  rk   r  r   r   r   r   i ʚ;r   N)!r   r1   r   r   r|   r}   r~   r   r   rp   
startcharsr   r   r   r   r   r   r   r   Z#select_chinese_characters_by_pinyinr   rw   rx   Zselect_wordsr   ry   r   r{   r8   r9   rz   r   fill_lookup_table)rP   Zwildcard_keyZwildcard_phraser   r   r   r     s    
	







 
	zEditor.update_candidatesc                 C   sn   | j s
dS | jrZ| j| j| j|   d  | j| j| j|   d  |  jd7  _|   |   dS )u6   Add selected phrase in lookup table to preëdit stringFr   r   T)	r|   r   r   r   r   r   r   r   r   rT   r   r   r   r     s    

zEditor.commit_to_preeditc                 C   sJ   | j  }| j  }|| }|| }|t| jkr6dS | j | |  S )u   
        Commits the candidate at position “index” in the current
        page of the lookup table to the preëdit. Does not yet “really”
        commit the candidate, only to the preëdit.
        F)r   r   get_cursor_in_pager   r   set_cursor_posr   )rP   r   r   cursor_in_pagecurrent_page_start
real_indexr   r   r   commit_to_preedit_current_page  s    

z%Editor.commit_to_preedit_current_pagec                 C   s  |   }|r|}tdkr| jr|  \}}}|  \}}}d}tdt|D ]$}	|d||	  d ||	  d 7 }qN||7 }tdt|D ]$}	|d||	  d ||	  d 7 }q| jr|dd	d
ddddddd}n6d}
|D ](}|| j	kr|
| j	| 7 }
q|
|7 }
q|
}|S d}| j
rn| jt| j
krL| j
d d }n| j
| j d }d| j|}d| j
}| jjrt|dkr|d| j| 7 }d}
|D ]*}|| j	kr|
| j	| 7 }
n|
|7 }
q|
S )zGet aux stringsr   r\   (r   z) z ()r   1r   2r   3r   4r   5r   r   z	#: )r   r   r   r   r   ranger   r   r   r   r   r   r   rp   r   user_can_define_phraser   )rP   Zinput_chars
aux_stringZtabkeys_leftZdummy_tabkeys_currentZtabkeys_rightZstrings_leftZdummy_string_currentZstrings_rightr
  Zaux_string_newr5   Zcstrr   r   r   get_aux_strings  s         

zEditor.get_aux_stringsc                 C   sz   | j  }| j  }| j  | |krv|t| jk rv|| }| j|| }|D ]&}| j|d |d |d |d d qNdS )zFill more entries to self._lookup_table if needed.

        If the cursor in _lookup_table moved beyond current length,
        add more entries from _candidiate[0] to _lookup_table.r   r   r"   r-   )r  r   r  r  N)r   get_number_of_candidatesget_page_sizer   r   r   r  )rP   ZlooklenZpsizeendposZbatch	candidater   r   r   r  a  s    

zEditor.fill_lookup_tablec                 C   s,   |    | j }|   |s(| jr(dS |S )zBProcess Arrow Down Key Event
        Move Lookup Table cursor downT)r  r   cursor_downr   r   rP   r   r   r   r   r%  t  s    

zEditor.cursor_downc                 C   s$   | j  }|   |s | jr dS |S )z>Process Arrow Up Key Event
        Move Lookup Table cursor upT)r   	cursor_upr   r   r&  r   r   r   r'    s
    

zEditor.cursor_upc                 C   s,   |    | j }|   |s(| jr(dS |S )z?Process Page Down Key Event
        Move Lookup Table page downT)r  r   	page_downr   r   r&  r   r   r   r(    s    

zEditor.page_downc                 C   s$   | j  }|   |s | jr dS |S )z;Process Page Up Key Event
        move Lookup Table page upT)r   page_upr   r   r&  r   r   r   r)    s
    

zEditor.page_upc                 C   s    || j krdS | | j |S )u   
        Commit a candidate which was selected by typing a selection key
        from the lookup table to the preedit. Does not yet “really”
        commit the candidate, only to the preedit.
        F)r   r  r   )rP   rR   r   r   r   
select_key  s
    

zEditor.select_keyc                 C   s   || j krdS | j |}| j }| j }|| }|| }t| j|kr| j| }| jj|d |d dd d| _	d| _
|   dS dS )u  Remove a candidate displayed in the lookup table from the user
        database.

        The candidate indicated by the selection key with the key code
        “keycode” is removed, if possible.  If it is not in the user
        database at all, nothing happens.

        If this is a candidate which is also in the system database,
        removing it from the user database only means that its user
        frequency data is reset. It might still appear in subsequent
        matches but with much lower priority.

        If this is a candidate which is user defined and not in the system
        database, it will not match at all anymore after removing it.

        Fr   r   T)r  r   Zcommitr\   )r   r   r   r   r  r   r   rp   Zremove_phraser~   r   r   )rP   rR   r   r   r  r  r  r$  r   r   r   #remove_candidate_from_user_database  s&    



  z*Editor.remove_candidate_from_user_databasec                 C   s
   | j  S )z get lookup table cursor position)r   r   rT   r   r   r   r     s    zEditor.get_cursor_posc                 C   s   | j S )zGet lookup table)r   rT   r   r   r   get_lookup_table  s    zEditor.get_lookup_tablec                 C   s4   t dkrtjd |  r(|   dS |   dS )zProcess remove_char Key Eventr   zremove_char()
N)r   r1   r   r   r   r   r   rT   r   r   r   remove_char  s    zEditor.remove_charc                 C   s   |   rdS |   dS )zProcess delete Key EventN)r   r   rT   r   r   r   delete  s    zEditor.deletec                 C   sr   t | j}|dkrj| j }| j }t|| }|d7 }||d | ksR||krZ|| }| j| dS dS dS )z+Cycle cursor to next candidate in the page.r   r   TFN)r   r   r   r"  r   rr   r  )rP   Ztotalrh   posZpager   r   r   cycle_next_cand  s    


zEditor.cycle_next_candc                 C   s   t | jdkS )z*Return true if there is only one candidater   )r   r   rT   r   r   r   one_candidate  s    zEditor.one_candidateN)r\   r\   r   r   )1rV   rW   rX   rY   rS   r   ZOrientationZVERTICALr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r   r  r   r  r%  r'  r(  r)  r*  r+  r   r,  r-  r.  r0  r1  r   r   r   r   rZ     sd   w
	L	
$$       
s\I	
	'	rZ   c                       sP  e Zd ZdZd fdd	Zdd Z fddZdd
dZdd ZdddZ	dddZ
dd ZdddZdd ZdddZdd ZdddZdd  Zdd"d#Zd$d% Zdd&d'Zd(d) Zdd*d+Zd,d- Zdd.d/Zd0d1 Zdd2d3Zd4d5 Zdd6d7Zd8d9 Zdd;d<Zd=d> Zdd?d@Z dAdB Z!ddCdDZ"dEdF Z#ddGdHZ$ddIdJZ%dKdL Z&e'j(j)fdMdNZ*dOdP Z+ fdQdRZ, fdSdTZ-dUdV Z.dWdX Z/ddYdZZ0d[d\ Z1d fd]d^	Z2d_d` Z3dadb Z4dcdd Z5dedf Z6dgdh Z7didj Z8dkdl Z9dmdn Z:dodp Z;dqdr Z<dsdt Z=dudv Z>dwdx Z?dydz Z@d{d| ZAd}d~ ZBdd ZCdd ZDdd ZE  ZFS )r   zThe IM Engine for TablesFc                    s  t t| j| |d zttdaW n  tt	fk
rJ   tdaY nX || _
d| _d| _ttdrnd| _|| _|| _d| _dtdtjjd	tjjf | _tj| jjd
ddd| _tdkrtjd| j  tjdd| j d| _| jd| j  | jj!"d| _#| j#r0t$| j#% dk| _#nt&d d| _#| jj!"d| _'| j'd ksf| j'dkrv| jj!"d| _'| j'd krd| _'| j'dkrd| _'| j'dkrd| _'| j'dkrd| _'| jj!"d| _(d | _)t*+| j,d!| _-| j-d kr| jj!"d"| _-| j-d kr$t*+| j.d!| _-t/| j-dkr@| j-d | _-t*+| j,d#| _0| j0d krp| jj!"d$| _0| j0d krt*+| j.d#| _0t/| j0dkr| j0d | _0t*+| j,d%| _1| j1d kr| jj!"d&d kr| jj!"d&% dk| _1| j1d krt*+| j.d%| _1t| jj!"d'| _2d(| _3tj4tj5tj6tj7g| _8tj9tj:tj;tj<g| _=| jj!"d)}| jj!"d*}|rd+d, |>d-D | _8|rd.d, |>d-D | _=| j(| j- | j0 D ]@}t?|}|| j8kr| j8@| || j=kr| j=@| qtjAg| _B| jj!"d/}	|	r:d0d, |	>d-D | _B| jBD ]6}|| j8kr\| j8@| || j=kr@| j=@| q@t*+| j,d1}
|
d kr|
dkrtjA| j=kr| j=CtjA tjA| jBkr| jB@tjA |
dkrtjA| j=kr| j=@tjA tjA| jBkr| jBCtjA tdkrNtjd2tD| j=  tjd3tD| jB  t*+| j.d4| _Ed | _Fd | _Gd| _Hd| _It*+| j.d5t*+| j,d6g| _J| jJd d kr| jj!"d7r| jj!"d7% dk| jJd< | jJd d krt*+| j.d6| jJd< t*+| j.d8t*+| j,d9g| _K| jKd d krf| jj!"d:rf| jj!"d:% dk| jKd< | jKd d krt*+| j.d9| jKd< t*+| j,d;| _L| jLd kr| jj!"d<r| jj!"d<% dk| _L| jLd krt*+| j.d;| _Lt*+| j,d=| _M| jMd krB| jj!"d>d krB| jj!"d>% dk| _M| jMd krbt*+| j.d=| _Mt*+| j,d?| _N| jNd kr| jj!"d@d kr| jj!"d@% dk| _N| jNd krt*+| j.d?| _NtO| j| j(| j)| j-| j0| j1| jJ| jK| j2| j
| _PddAdBtQdCtQdDdEddFdGtQdHtQdIdEdJdKdLtQdMtQdNdEdOdPdQtQdRtQdSdEdTdUdVtQdWtQdXdEdY| _RdZtQd[tQd\d]| jRd^| _S| jjTrdd_d`tQdatQdbdEddddcddtQdetQdfdgdh| _Un@ddi| j' d`tQdjtQdkdEddl| j' dmtQdntQdodEdh| _UdptQdqtQdrds| jUd^| _VddtdutQdvtQdwdEddxdytQdztQd{dEd|| _Wd}tQd~tQdd| jWd^| _XdddtQdvtQddEdddtQdztQddEd| _YdtQdtQdd| jYd^| _ZdddtQdntQddEdddtQdtQddEd| _[dtQdtQdd| j[d^| _\dddtQdtQddEdddtQdtQddEd| _]dtQdtQdd| j]d^| _^dddtQdtQddEdddtQdjtQddEd| __dtQdtQdd| j_d^| _`i | _a| b  d| _cd| _dtee | _ftg| _hti| _j| k  tlmd| jn| _od S )N)Z
connectionZobject_pathZIBUS_TABLE_DEBUG_LEVELr   FInputPurposeTz%s%s%s%sZIBUS_TABLE_LOCATIONZiconsz.dbr\   r   _r   z,TabEngine.__init__() self._engine_name = %s
z!org.freedesktop.ibus.engine.tablez&/org/freedesktop/ibus/engine/table/%s/)ZschemapathZchangedZpinyin_modero   zNWe could not find "pinyin_mode" entry in database, is it an outdated database?symbolZstatus_promptZCNu   中ZYau   ЯZYiu   Їr   zabcdefghijklmnopqrstuvwxyz!@#$%singlewildcardcharr   multiwildcardcharr   autowildcardr   r   r[   Zpage_up_keysZpage_down_keysc                 S   s   g | ]}t |qS r   r]   rb   r   r   r   r`   u  s   z&TabEngine.__init__.<locals>.<listcomp>rd   c                 S   s   g | ]}t |qS r   r]   rb   r   r   r   r`   y  s   Zcommit_keysc                 S   s   g | ]}t |qS r   r]   rb   r   r   r   r`     s   spacekeybehaviorzself._page_down_keys=%s
zself._commit_keys=%s
	inputmodeendeffullwidthlettertabdeffullwidthletterZdef_full_width_letterendeffullwidthpuncttabdeffullwidthpunctZdef_full_width_punct
autocommitZauto_commitrm   rn   alwaysshowlookupZalways_show_lookupu   簡zsc-mode.svgzSimplified Chineseu(   Switch to “Simplified Chinese only”.)numberr5  iconlabeltooltipu   繁ztc-mode.svgzTraditional Chineseu)   Switch to “Traditional Chinese only”.r"   u   簡/大zscb-mode.svgzSimplified Chinese firstu6   Switch to “Simplified Chinese before traditional”.r-   u   繁/大ztcb-mode.svgzTraditional Chinese firstu6   Switch to “Traditional Chinese before simplified”.r+   u   大zcb-mode.svgzAll Chinese charactersu'   Switch to “All Chinese characters”.)zChineseMode.SimplifiedzChineseMode.TraditionalzChineseMode.SimplifiedFirstzChineseMode.TraditionalFirstzChineseMode.AllZChineseModezChinese modezSwitch Chinese modez(Ctrl-;))keyrC  rD  shortcut_hintsub_propertiesu   英zenglish.svgZEnglishzSwitch to English inputu   拼音zchinese.svgZChinesezSwitch to Chinese input)rA  r5  symbol_tablesymbol_pinyinrB  rC  rD  )zInputMode.DirectInputMode.Tableu   ☐ZDirectzSwitch to direct inputu   ☑zibus-table.svgZTablezSwitch to table inputZ	InputModez
Input modezSwitch Input modez(Left Shift)u   ◑zhalf-letter.svgZHalfzSwitch to halfwidth lettersu   ●zfull-letter.svgZFullzSwitch to fullwidth letters)zLetterWidth.HalfzLetterWidth.FullZLetterWidthzLetter widthzSwitch letter widthz(Shift-Space)z,.zhalf-punct.svgzSwitch to halfwidth punctuationu   、。zfull-punct.svgzSwitch to fullwidth punctuation)zPunctuationWidth.HalfzPunctuationWidth.FullZPunctuationWidthzPunctuation widthzSwitch punctuation widthz(Ctrl-.)u
   ☐ 拼音ztab-mode.svgzSwitch to table modeu
   ☑ 拼音zpy-mode.svgZPinyinzSwitch to pinyin mode)zPinyinMode.TablezPinyinMode.PinyinZ
PinyinModezPinyin modezSwitch pinyin modez(Right Shift)u   ☐ 1z
phrase.svgzMultiple character matchz.Switch to matching multiple characters at onceu   ☑ 1zonechar.svgzSingle character matchz)Switch to matching only single characters)zOneCharMode.PhrasezOneCharMode.OneCharZOneCharModezOnechar modezSwitch onechar modez(Ctrl-,)u   ☐ ↑zncommit.svgZNormalzSwitch to normal commit mode (automatic commits go into the preedit instead of into the application. This enables automatic definitions of new shortcuts)u   ☑ ↑zacommit.svgzQSwitch to direct commit mode (automatic commits go directly into the application))zAutoCommitMode.DirectzAutoCommitMode.NormalZAutoCommitModezAuto commit modezSwitch autocommit modez(Ctrl-/))prK   r   rS   Zget_connectionrr   r   getenvr   	TypeError
ValueError
_unit_test_input_purpose_has_input_purposehasattrr   Z_busrp   
_setup_pidr4  sep	_icon_dirbasenamefilenamer   _engine_namer1   r   r   r   ZSettingsrq   Zconnecton_gsettings_value_changedr   r   _ime_pyr   r   printZ_symbolru   rv   r   r   r   rw   r   r   rx   ry   rs   rt   ZKEY_Page_UpZKEY_KP_PriorZKEY_KP_Page_UpZ	KEY_minus_page_up_keysZKEY_Page_DownZKEY_KP_NextZKEY_KP_Page_DownZ	KEY_equal_page_down_keysr   Zunicode_to_keyvalremove	KEY_space_commit_keysr   repr_input_mode	_prev_key
_prev_char_double_quotation_state_single_quotation_staterz   r{   _auto_commitr   _always_show_lookuprZ   _editorr3  chinese_mode_propertieschinese_mode_menur   input_mode_propertiesinput_mode_menuletter_width_propertiesletter_width_menupunctuation_width_propertiespunctuation_width_menupinyin_mode_propertiespinyin_mode_menuonechar_mode_propertiesonechar_mode_menuautocommit_mode_propertiesautocommit_mode_menu
_prop_dict_init_properties_on_save_user_counttime_save_user_startSAVE_USER_COUNT_MAX_save_user_count_maxSAVE_USER_TIMEOUT_save_user_timeoutresetr   Ztimeout_add_seconds_sync_user_dbsync_timeout_id)rP   ZbusZobj_pathrp   Z	unit_testZpage_up_keys_csvZpage_down_keys_csvr   rQ   Zcommit_keys_csvr9  	__class__r   r   rS     st   

    





	

	
























8

					
 zTabEngine.__init__c                 C   s(   | j   d| _d| _d| _|   dS )u6   Clear the preëdit and close the lookup table
        FN)rh  r   rd  re  rb  
_update_uirT   r   r   r   r    s
    
zTabEngine.resetc                    sX   | j dkrt| j  d| _ |   |   | jdkrF| j  d| _tt	| 
  dS )z3Called when this input engine is destroyed
        r   N)r  r   Zsource_remover  do_focus_outrz  rp   
sync_usrdbrK   r   ZdestroyrT   r  r   r   
do_destroy  s    


zTabEngine.do_destroyr   c                 C   s\   || j krdS || _ | | j| j  | | j| j| j   | | j| j| j   |   dS )zSets whether direct input or the current table is used.

        :param mode: Whether to use Pinyin.
                     0: Use direct input.
                     1: Use the current table.
        :type mode: Integer, 0 or 1.
        N)ra  _init_or_update_property_menurl  rn  rz   rp  r{   r  rP   moder   r   r   set_input_mode	  s     


zTabEngine.set_input_modec                 C   s   | j S )zj
        Return the current input mode, direct input: 0, table input: 1.

        :rtype: Integer
        )ra  rT   r   r   r   get_input_mode'  s    zTabEngine.get_input_modec                 C   s   || j jkrdS | j   || j _| | j| |rN| jd d | jd d< n| jd d | jd d< | | j| j |   dS )zSets whether Pinyin is used.

        :param mode: Whether to use Pinyin.
                     True: Use Pinyin.
                     False: Use the current table.
        :type mode: Boolean
        NrJ  rI  r5  rH  )	rh  r   r   r  rr  rk  rl  ra  r  r  r   r   r   set_pinyin_mode/  s$    
 zTabEngine.set_pinyin_modeTc                 C   sN   || j jkrdS || j _| | j| | j  |rJ| jdtj	
| dS )a  Sets whether only single characters should be matched in
        the database.

        :param mode: Whether only single characters should be matched.
                     True: Match only single characters.
                     False: Possibly match multiple characters at once.
        :type mode: Boolean
        :param update_gsettings: Whether to write the change to Gsettings.
                                 Set this to False if this method is
                                 called because the dconf key changed
                                 to avoid endless loops when the dconf
                                 key is changed twice in a short time.
        :type update_gsettings: Boolean

        Nrk   )rh  r   r  rt  rp   reset_phrases_cacherq   	set_valuer   Variantnew_booleanrP   r  update_gsettingsr   r   r   set_onechar_modeI  s     

zTabEngine.set_onechar_modec                 C   s   | j jS )zn
        Returns whether only single characters are matched in the database.

        :rtype: Boolean
        )rh  r   rT   r   r   r   get_onechar_moded  s    zTabEngine.get_onechar_modec                 C   s@   || j krdS || _ | | j| |r<| jdtj| dS )u  Sets whether automatic commits go into the preëdit or into the
        application.

        :param mode: Whether automatic commits  go into the  preëdit
                     or into the application.
                     True: Into the application.
                     False: Into the preëdit.
        :type mode: Boolean
        :param update_gsettings: Whether to write the change to Gsettings.
                                 Set this to False if this method is
                                 called because the dconf key changed
                                 to avoid endless loops when the dconf
                                 key is changed twice in a short time.
        :type update_gsettings: Boolean

        Nr?  )rf  r  rv  rq   r  r   r  r  r  r   r   r   set_autocommit_model  s    
 
zTabEngine.set_autocommit_modec                 C   s   | j S )zP
        Returns the current auto-commit mode.

        :rtype: Boolean
        )rf  rT   r   r   r   get_autocommit_mode  s    zTabEngine.get_autocommit_modec                 C   s:   || j krdS || _ || j_ |r6| jdtj| dS )aR  Sets whether the first candidate will be selected
        automatically during typing.

        :param mode: Whether to select the first candidate automatically.
        :type mode: Boolean
        :param update_gsettings: Whether to write the change to Gsettings.
                                 Set this to False if this method is
                                 called because the dconf key changed
                                 to avoid endless loops when the dconf
                                 key is changed twice in a short time.
        :type update_gsettings: Boolean
        Nrm   )r   rh  rq   r  r   r  r  r  r   r   r   set_autoselect_mode  s    

zTabEngine.set_autoselect_modec                 C   s   | j S )zP
        Returns the current auto-select mode.

        :rtype: Boolean
        )r   rT   r   r   r   get_autoselect_mode  s    zTabEngine.get_autoselect_modec                 C   sD   || j krdS || _ || j_ | j  |r@| jdtj| dS )aA  Sets whether a wildcard should be automatically appended
        to the input.

        :param mode: Whether to append a wildcard automatically.
        :type mode: Boolean
        :param update_gsettings: Whether to write the change to Gsettings.
                                 Set this to False if this method is
                                 called because the dconf key changed
                                 to avoid endless loops when the dconf
                                 key is changed twice in a short time.
        :type update_gsettings: Boolean
        Nr8  )	ry   rh  rp   r  rq   r  r   r  r  r  r   r   r   set_autowildcard_mode  s    


zTabEngine.set_autowildcard_modec                 C   s   | j S )zX
        Returns the  current automatic wildcard mode.

        :rtype: Boolean
        )ry   rT   r   r   r   get_autowildcard_mode  s    zTabEngine.get_autowildcard_moder\   c                 C   sD   || j krdS || _ || j_ | j  |r@| jdtj| dS )a#  Sets the single wildchard character.

        :param char: The character to use as a single wildcard.
        :type char: String  of length 1.
        :param update_gsettings: Whether to write the change to Gsettings.
                                 Set this to False if this method is
                                 called because the dconf key changed
                                 to avoid endless loops when the dconf
                                 key is changed twice in a short time.
        :type update_gsettings: Boolean
        Nr6  )	rw   rh  rp   r  rq   r  r   r  
new_stringrP   r5   r  r   r   r   set_single_wildcard_char  s    


z"TabEngine.set_single_wildcard_charc                 C   s   | j S )zp
        Return the character currently used as a single wildcard.

        :rtype: String of length 1.
        )rw   rT   r   r   r   get_single_wildcard_char  s    z"TabEngine.get_single_wildcard_charc                 C   sX   t |dkr|d }|| jkr"dS || _|| j_| j  |rT| jdtj	| dS )a!  Sets the multi wildchard character.

        :param char: The character to use as a multi wildcard.
        :type mode: String  of length 1.
        :param update_gsettings: Whether to write the change to Gsettings.
                                 Set this to False if this method is
                                 called because the dconf key changed
                                 to avoid endless loops when the dconf
                                 key is changed twice in a short time.
        :type update_gsettings: Boolean
        r   r   Nr7  )
r   rx   rh  rp   r  rq   r  r   r  r  r  r   r   r   set_multi_wildcard_char  s    


z!TabEngine.set_multi_wildcard_charc                 C   s   | j S )zo
        Return the character currently used as a multi wildcard.

        :rtype: String of length 1.
        )rx   rT   r   r   r   get_multi_wildcard_char  s    z!TabEngine.get_multi_wildcard_charc                 C   s   t dkrtjd|  |dkrTtj| jkr:| jtj tj| jkrT| j	tj |dkrtj| jkrv| j	tj tj| jkr| jtj t dkrtjdt
| j  tjdt
| j  |r| jdtj| dS )	a  Sets the behaviour of the space key

        :param mode: How the space key should behave
        :type mode: Boolean
                    True: space is used as a page down key
                          and not as a commit key.
                    False: space is used as a commit key
                           and not used as a page down key
        :param update_gsettings: Whether to write the change to Gsettings.
                                 Set this to False if this method is
                                 called because the dconf key changed
                                 to avoid endless loops when the dconf
                                 key is changed twice in a short time.
        :type update_gsettings: boolean
        r   z set_space_key_behavior_mode(%s)
TFz7set_space_key_behavior_mode(): self._page_down_keys=%s
z4set_space_key_behavior_mode(): self._commit_keys=%s
r9  N)r   r1   r   r   r   r^  r\  r   r_  r]  r`  rq   r  r   r  r  r  r   r   r   set_space_key_behavior_mode
  s@    
z%TabEngine.set_space_key_behavior_modec                 C   s(   d}t j| jkrd}t j| jkr$d}|S )zX
        Returns the current space key behaviour mode.

        :rtype: Boolean
        FT)r   r^  r\  r_  r  r   r   r   get_space_key_behavior_mode6  s    z%TabEngine.get_space_key_behavior_modec                 C   s2   || j krdS || _ |r.| jdtj| dS )av  Sets the whether the lookup table is shown.

        :param mode: Whether to show the lookup table.
        :type mode: Boolean
                    True: Lookup table is shown
                    False: Lookup table is hidden
        :param update_gsettings: Whether to write the change to Gsettings.
                                 Set this to False if this method is
                                 called because the dconf key changed
                                 to avoid endless loops when the dconf
                                 key is changed twice in a short time.
        :type update_gsettings: Boolean
        Nr@  )rg  rq   r  r   r  r  r  r   r   r   set_always_show_lookupD  s    

z TabEngine.set_always_show_lookupc                 C   s   | j S )z_
        Returns whether the lookup table is shown or hidden.

        :rtype: Boolean
        )rg  rT   r   r   r   get_always_show_lookupZ  s    z TabEngine.get_always_show_lookupc                 C   sl   t dkrtjd|  || jjkr(dS |dkrh|dkrh|| j_| jj| |rh| j	dt
j| dS )a  Sets the orientation of the lookup table

        :param orientation: The orientation of the lookup table
        :type mode: integer >= 0 and <= 2
                    IBUS_ORIENTATION_HORIZONTAL = 0,
                    IBUS_ORIENTATION_VERTICAL   = 1,
                    IBUS_ORIENTATION_SYSTEM     = 2.
        :param update_gsettings: Whether to write the change to Gsettings.
                                 Set this to False if this method is
                                 called because the dconf key changed
                                 to avoid endless loops when the dconf
                                 key is changed twice in a short time.
        :type update_gsettings: boolean
        r   z!set_lookup_table_orientation(%s)
Nr   r"   rf   )r   r1   r   r   rh  r   r   r   rq   r  r   r  	new_int32)rP   rj   r  r   r   r   set_lookup_table_orientationb  s     
z&TabEngine.set_lookup_table_orientationc                 C   s   | j jS )zUReturns the current orientation of the lookup table

        :rtype: integer
        )rh  r   rT   r   r   r   get_lookup_table_orientation  s    z&TabEngine.get_lookup_table_orientationc                 C   s   t dkrtjd|  || jjkr(dS |t| jjkrDt| jj}|dk rPd}|| j_| jj| jj| jj| jj	d| j_
|   |r| jdtj| dS )a:  Sets the page size of the lookup table

        :param orientation: The orientation of the lookup table
        :type mode: integer >= 1 and <= number of select keys
        :param update_gsettings: Whether to write the change to Gsettings.
                                 Set this to False if this method is
                                 called because the dconf key changed
                                 to avoid endless loops when the dconf
                                 key is changed twice in a short time.
        :type update_gsettings: boolean
        r   zset_page_size(%s)
Nrg   re   )r   r1   r   r   rh  r   r   r   r   r   r   r  rq   r  r   r  r  )rP   rh   r  r   r   r   set_page_size  s0    

zTabEngine.set_page_sizec                 C   s   | j jS )zSReturns the current page size of the lookup table

        :rtype: integer
        )rh  r   rT   r   r   r   r"    s    zTabEngine.get_page_sizer   c                 C   sz   || j | krdS || j |< || jj |< || jkr@| | j| |rv|r`| jdtj	| n| jdtj	| dS )a  
        Sets whether full width letters should be used.

        :param mode: Whether to use full width letters
        :type mode: Boolean
        :param input_mode: The input mode (direct input: 0, table: 1)
                           for which to set the full width letter mode.
        :type input_mode: Integer
        :param update_gsettings: Whether to write the change to Gsettings.
                                 Set this to False if this method is
                                 called because the Gsettings key changed
                                 to avoid endless loops when the Gsettings
                                 key is changed twice in a short time.
        :type update_gsettings: Boolean
        Nr<  r;  )
rz   rh  ra  r  rn  rq   r  r   r  r  rP   r  
input_moder  r   r   r   set_letter_width  s&    

 

zTabEngine.set_letter_widthc                 C   s   | j S )za
        Return the current full width letter modes.

        :rtype: [Boolean, Boolean]
        )rz   rT   r   r   r   get_letter_width  s    zTabEngine.get_letter_widthc                 C   sz   || j | krdS || j |< || jj |< || jkr@| | j| |rv|r`| jdtj	| n| jdtj	| dS )a  
        Sets whether full width punctuation should be used.

        :param mode: Whether to use full width punctuation
        :type mode: Boolean
        :param input_mode: The input mode (direct input: 0, table: 1)
                           for which to set the full width punctuation mode.
        :type input_mode: Integer
        :param update_gsettings: Whether to write the change to Gsettings.
                                 Set this to False if this method is
                                 called because the Gsettings key changed
                                 to avoid endless loops when the Gsettings
                                 key is changed twice in a short time.
        :type update_gsettings: Boolean
        Nr>  r=  )
r{   rh  ra  r  rp  rq   r  r   r  r  r  r   r   r   set_punctuation_width  s&    

 

zTabEngine.set_punctuation_widthc                 C   s   | j S )zf
        Return the current full width punctuation modes.

        :rtype: [Boolean, Boolean]
        )r{   rT   r   r   r   get_punctuation_width  s    zTabEngine.get_punctuation_widthc                 C   sf   t dkrtjd|  || jjkr(dS || j_| j  | | j	| |rb| j
dtj| dS )a8  Sets the candidate filter mode used for Chinese

        0 means to show simplified Chinese only
        1 means to show traditional Chinese only
        2 means to show all characters but show simplified Chinese first
        3 means to show all characters but show traditional Chinese first
        4 means to show all characters

        :param mode: The Chinese filter mode
        :type mode: integer >= 0 and <= 4
        :param update_gsettings: Whether to write the change to Gsettings.
                                 Set this to False if this method is
                                 called because the dconf key changed
                                 to avoid endless loops when the dconf
                                 key is changed twice in a short time.
        :type update_gsettings: boolean
        r   zset_chinese_mode(%s)
Nrl   )r   r1   r   r   rh  r   rp   r  r  rj  rq   r  r   r  r  r  r   r   r   set_chinese_mode	  s    
 
zTabEngine.set_chinese_modec                 C   s   | j jS )ag  
        Return the current Chinese mode.

        0 means to show simplified Chinese only
        1 means to show traditional Chinese only
        2 means to show all characters but show simplified Chinese first
        3 means to show all characters but show traditional Chinese first
        4 means to show all characters

        :rtype: Integer
        )rh  r   rT   r   r   r   r   !	  s    zTabEngine.get_chinese_modec                 C   sL  t dkr tjdt||f  |d }t|| jk}|d }|D ]^}|| d t|krB|| d }|| d }d|d	 ||d
 d }	d|d |d
 d }
qBtj	|tj
jtj|	tj|tj| j|tj|
ddtjjdd
| j|< | j| | j||d |r6| j| j|  | | j|  n| j| j|  dS )z;
        Initialize or update a ibus property menu
        r   z8_init_or_update_property_menu() menu=%s current_mode=%s
rE  rG  rA  r5  rB  z(%(label)s (%(symbol)s) %(shortcut_hint)srC  rF  )rC  r5  rF  z%(tooltip)s
%(shortcut_hint)srD  )rD  rF  TN)
rE  	prop_typerC  r5  rB  rD  	sensitivevisibler=   	sub_props)current_mode)r   r1   r   r   r`  r   rw  rr   r   PropertyPropTypeZMENUr   r   r   r4  r   rT  	PropState	UNCHECKEDZset_sub_props_init_sub_properties
propertiesupdate_propertyr   )rP   Zmenur  rE  Zupdate_proprG  propr5  rB  rC  rD  r   r   r   r  /	  sX    





 z'TabEngine._init_or_update_property_menuc                    s   t  }t  fdddD ]^}|t j|t jjt j | d t	j
 | d t j | d ddt jjdd		 qd
}||dkr||}| }|| j|<  | d t|kr|t jj n|t jj | | |d7 }q|S )zK
        Initialize the sub properties of the ibus property menus.
        c                    s    |  d S )NrA  r   )rc   modesr   r   r	   ^	  r
   z0TabEngine._init_sub_properties.<locals>.<lambda>)rE  rC  rB  rD  TN)	rE  r  rC  rB  rD  r  r  r=   r  r   rA  r   )r   PropListsortedr   r  r  ZRADIOr   r   r   r4  r   r  r  r   Zget_keyrw  rr   Z	set_stateCHECKEDr  )rP   r  r  r  r  r
  r  rE  r   r  r   r  Y	  s0    





zTabEngine._init_sub_propertiesc              	   C   s$  i | _ t | _| | j| j | jjrF| j	j
dkrF| | j| j	j
 | jjrz| | j| j| j  | | j| j| j  | jr| | j| j	j | jjr| | j| j	j | jjr| jjr| | j| j tjdtjtddtjtdd| ji ddd| _| j | j | !| j d	S )
z4
        Initialize the ibus property menus
        r   setupZSetupzgtk-preferencesu*   Configure ibus-table “%(engine-name)s”zengine-nameT)rE  rC  rB  rD  r  r  N)"rw  r   r  r  r  rl  ra  rp   r   rh  r   rj  _is_cjkrn  rz   rp  r{   rY  rr  r   rt  r   r  rulesrv  rf  r  r   r   r3  rW  Z_setup_propertyr   register_propertiesrT   r   r   r   rx  v	  sb    


	zTabEngine._init_propertiesc                 C   s  t dkr"tjdd||d   |dkr6|   dS |tjjkrFdS || j	d d rr| 
| j| d	  dS || jd d r| jr| t| j| d	  dS || jd d r| jjr| t| j| d	  dS || jd d r&| jjr&| jjr&| t| j| d	  dS || jd d rh| jjrh| jt| j| d	 | jd
 dS || jd d r| jjr| j t| j!| d	 | jd
 dS || j"d d r| jj#r| j$j%dkr| &| j'| d	  dS dS )z-
        Handle clicks on properties
        r   zdo_property_activate() z&ibus_property=%(p)s prop_state=%(ps)s
)r   Zpsr  NrE  r   rA  r  r   )(r   r1   r   r   _start_setupr   r  r  
startswithrl  r  rk  rr  rY  r  r   rq  rt  rp   r  r  rs  rv  r  r  r  ru  rn  r  rm  ra  rp  r  ro  rj  r   rh  r   r  ri  )rP   Zibus_propertyZ
prop_stater   r   r   do_property_activate	  s    
zTabEngine.do_property_activatec                 C   sd   | j dkr2t| j tj\}}|| j kr,dS d| _ tjtdd}ttj|dd| j | _ dS )z@
        Start the setup tool if it is not running yet.
        r   NZIBUS_TABLE_LIB_LOCATIONzibus-setup-tablez--engine-name table:%s)	rR  r   waitpidP_NOWAITr4  r   rK  spawnlrW  )rP   pidZdummy_stateZ	setup_cmdr   r   r   r  	  s    

zTabEngine._start_setupc              	      s  | j  }d|d }|d }d|d }| j jsnd}|D ]*}|| j jkr`|| j j| 7 }q>||7 }q>|}|| | }|stt| tj	
ddd dS tddd}td	d
d}	tddd}
t }|t|dt| |t|	t|t| t| | j jrH|t|
t|t| t| j j t|t|  |ttjjdt| tj	
|}d}||dkr||}|| | | |  |d7 }qttt| || j  d dS )zUpdate Preedit String in UIr\   r   r   r"   FN      r)         r   T)rh  r   r   r   r   rK   r   Zupdate_preedit_textr   r   r   r   r   r   r   r   r}   Zattr_underline_newZAttrUnderlineZSINGLEr   r  r  r   r  r  r   )rP   Zpreedit_string_partsr   r   r   Zcurrent_edit_newr5   Zpreedit_string_completeZ
color_leftZcolor_rightZcolor_invalidr  r	  r
  r  r  r   r   _update_preedit	  s    




  




  zTabEngine._update_preeditc                    s   | j  }| j jr6|d| j j d | j j f 7 }|rt }|t	t
ddddt| tj|}d}||dkr||}|| | | |  |d7 }qrd}|r| jsd	}tt| || n|   dS )
zUpdate Aux String in UIz
 (%d / %d)r            r   NTF)rh  r   r   r   r   r!  r   r   r   r   r   r   r   r   r   r  r  r   r  r  rg  rK   r   Zupdate_auxiliary_textZhide_auxiliary_text)rP   r  r  r	  r
  r  r  r  r   r   _update_aux3
  s8    


  



zTabEngine._update_auxc                 C   sR   | j js|   dS | j  r*|   dS | js<|   dS | | j  d dS )zUpdate Lookup Table in UINT)rh  r   Zhide_lookup_tabler   rg  Zupdate_lookup_tabler,  rT   r   r   r   _update_lookup_tableN
  s    
zTabEngine._update_lookup_tablec                 C   s   |    |   |   dS )zUpdate User InterfaceN)r  r  r  rT   r   r   r   r  `
  s    zTabEngine._update_uic                 C   sB   |r|sdS | j j||d | jdkr0t | _|  jd7  _dS )z3Check the given phrase and update save user db infoNr  r   r   r   )rp   Zcheck_phraserz  r{  r|  )rP   r  r   r   r   r   _check_phrasef
  s    

zTabEngine._check_phrasec                 C   sL   | j dkrHt }|| j }| j | jks2|| jkrH| j  d| _ || _dS )zSave user db to diskr   T)rz  r{  r|  r~  r  rp   r  )rP   ZnowZ
time_deltar   r   r   r  p
  s    


zTabEngine._sync_user_dbc                    sn   t dkrtjdd|i  | j  |   tt| 	t
j| |rV|d | _nd| _| j||d dS )u  
        Commit the string “phrase”, update the user database,
        and clear the preëdit.

        :param phrase: The text to commit
        :type phrase: String
        :param tabkeys: The keys typed to produce this text
        :type tabkeys: String
        r   zcommit_string() phrase=%(p)s
r   r   Nr  )r   r1   r   r   rh  r   r  rK   r   Zcommit_textr   r   r   rc  r  )rP   r   r  r  r   r   commit_string|
  s    

zTabEngine.commit_stringc                 C   sR   t dkrtjd | jjr dS | j s4| j  | j| j	 | j
 d dS )u   
        Commits the current input to the preëdit and then
        commits the preëdit to the application unless there are
        invalid input characters.

        Returns “True” if something was committed, “False” if not.
        r   z#commit_everything_unless_invalid()
Fr  T)r   r1   r   r   rh  r}   r   r   r  r   r   rT   r   r   r    commit_everything_unless_invalid
  s    

z*TabEngine.commit_everything_unless_invalidc                 C   s   ddddddddd	d
d
}||  krD|dkr6|| S | jrD|| S |dkr|| jrx| j rx| jrxt| jj| jkrxdS dS |dkr| j | _| jrdS dS |dkr| j | _| jrdS dS t	|S )z*Convert half width character to full widthu   《u   》u   「u   」u   『u   』u   、u   ……u   ——u   ￥)
<>[]{}\r   r3  r   )r  r   r3  r   r   u   。"u   “u   ”'u   ‘u   ’)
keysra  rc  isdigitrb  r3   r<   rd  re  r8   )rP   r5   Zspecial_punct_dictr   r   r   _convert_to_full_width
  sJ    

z TabEngine._convert_to_full_widthc                 C   s   t dkr,tjd|  tjd||f  |tjjB }|j|kr||j|@ |kr|| j	r||j| j	jkr|t dkrxtjd dS tjd dS )u  Check whether “key” matches a “hotkey” specified by “keyval” and
        “state”.

        Returns True if there is a match, False if not.

        :param key: The key typed
        :type key: KeyEvent object
        :param keyval: The key value to match against
        :type keyval: Integer
        :param state: The state of the modifier keys to match against.
        :type state: Integer
        :rtype: Boolean
        r   z_match_hotkey() typed key: %s
z$trying to match: keyval=%s state=%s
z_match_hotkey(): *Match*!
Tz_match_hotkey(): No match!
F)
r   r1   r   r   r   rB   rM   r<   r=   rb  )rP   rE  rQ   r=   r   r   r   _match_hotkey
  s    zTabEngine._match_hotkeyc                 C   s.   | j |r*| j| j  | j  d dS dS )Nr  TF)rh  r  r  r   r   )rP   r   Z_buttonZ_stater   r   r   do_candidate_clicked
  s    zTabEngine.do_candidate_clickedc                 C   s   | j r| ||| dS dS )uR  A replacement for “return False” in do_process_key_event()

        do_process_key_event should return “True” if a key event has
        been handled completely. It should return “False” if the key
        event should be passed to the application.

        But just doing “return False” doesn’t work well when trying to
        do the unit tests. The MockEngine class in the unit tests
        cannot get that return value. Therefore, it cannot do the
        necessary updates to the self._mock_committed_text etc. which
        prevents proper testing of the effects of such keys passed to
        the application. Instead of “return False”, one can also use
        self.forward_key_event(keyval, keycode, keystate) to pass the
        key to the application. And this works fine with the unit
        tests because a forward_key_event function is implemented in
        MockEngine as well which then gets the key and can test its
        effects.

        Unfortunately, “forward_key_event()” does not work in Qt5
        applications because the ibus module in Qt5 does not implement
        “forward_key_event()”. Therefore, always using
        “forward_key_event()” instead of “return False” in
        “do_process_key_event()” would break ibus-typing-booster
        completely for all Qt5 applictions.

        To work around this problem and make unit testing possible
        without breaking Qt5 applications, we use this helper function
        which uses “forward_key_event()” when unit testing and “return
        False” during normal usage.

        TF)rN  Zforward_key_eventrO   r   r   r   _return_false
  s     zTabEngine._return_falsec                 C   sv   t dkrtjd | jr>| jtjjtjj	fkr>| 
|||S t|||}t dkrbtjd|  | |}|| _|S )ztProcess Key Events
        Key Events include Key Press and Key Release,
        modifier means Key Pressed
        r   zdo_process_key_event()
z'process_key_event() KeyEvent object: %s)r   r1   r   r   rP  rO  r   r2  ZPASSWORDZPINr  r:   _process_key_eventrb  )rP   rQ   rR   r=   rE  resultr   r   r   do_process_key_event"  s$    
zTabEngine.do_process_key_eventc                 C   s   | j  r4| |tjtjjr4| t| j	  dS | j
jr|jtjkrh|jtjj@ rh|jtjj@ shdS | |tjtjjr| j| j| j	  | j	d dS | |tjtjjr| j
jr| j| j| j	  | j	d dS | j	r| |S | |S )a  
        Internal method to process key event

        Returns True if the key event has been completely handled by
        ibus-table and should not be passed through anymore.
        Returns False if the key event has not been handled completely
        and is passed through.
        Tr  )rh  r   r  r   KEY_Shift_LrB   rC   r  rr   ra  rp   r  r<   r^  r=   rM   r  rz   Z
KEY_periodrF   r  r{   _table_mode_process_key_event_english_mode_process_key_event)rP   rE  r   r   r   r  8  sR    

   
zTabEngine._process_key_eventc                 C   s"   | j | j r| jjr| |S |S )u1  Converts “char” to full width *if* full width letter mode is on for
        the current input mode (direct input or table mode) *and* if
        the current table is for CJK.

        :param char: The character to maybe convert to full width
        :type char: String
        :rtype: String

        )rz   ra  rp   r  r  rP   r5   r   r   r   cond_letter_translateh  s    

zTabEngine.cond_letter_translatec                 C   s"   | j | j r| jjr| |S |S )u6  Converts “char” to full width *if* full width punctuation mode is
        on for the current input mode (direct input or table mode)
        *and* if the current table is for CJK.

        :param char: The character to maybe convert to full width
        :type char: String
        :rtype: String

        )r{   ra  rp   r  r  r  r   r   r   cond_punct_translatev  s    

zTabEngine.cond_punct_translatec                 C   s   |j tjj@ r"| |j|j|j S |jdkr@| |j|j|j S |j tjjtjjB @ rj| |j|j|j S t	|j}t
|t
dkr|d}t|r| |}n
| |}||kr| |j|j|j S | | dS )uQ   
        Process a key event in “English” (“Direct input”) mode.
           r\   UTF-8T)r=   r   rB   rM   r  r<   r6   rF   rH   r@   typedecoder   r  r  r  )rP   rE  keychar
trans_charr   r   r   r    s(    



z)TabEngine._english_mode_process_key_eventc                 C   s
  t dkr(tjd tjdd|i  | jr`| j r`| |tj	tj
jr`| | jj  dS | |tj	tj
js| |tjtj
jr| j }|   |S | |tjtj
jr| j }|   |S | |tjtj
jr| jjr| | jj  dS | |tjtj
jr4| jjr4| jjr4| | j  dS | |tjtj
jrn| jj rn| !| jj"d d  dS |j#tj
j$@ r| %|j&|j'|j#S t(|j&}t)|t)dkr|*d	}| j r| j+ s|| j,| j- | j. ks| jj/r|| jj/kr|j#tj
jtj
jB @ st dkr<tjd
dd|i   t0|rR| 1|}n
| 2|}||kr|| _3| %|j&|j'|j#S | 4| dS |j&tj5kr| 6  |   dS |j&tj7tj8fkrB| j r| j+ s| %|j&|j'|j#S | j9r*| j  | j+ }| 4| | %|j&|j'|j#S | j: }| 4| dS |j&tj;tj<fkr| j9r| j  | 4| j+  | %|j&|j'|j#S |j&tj=tj>fkr| j+ s| %|j&|j'|j#S | j? }|   |S |j&tj@tjAfkr | j+ s
| %|j&|j'|j#S | jB }|   |S |j&tjCtjDfkrz|j#tj
j@ rz| j+ sd| %|j&|j'|j#S | jE  |   dS |j&tjFtjGfkr|j#tj
j@ r| j+ s| %|j&|j'|j#S | jH  |   dS |j&tjCtjDfkr| j+ s| %|j&|j'|j#S | jI  |   dS |j&tjFtjGfkrh| j+ sR| %|j&|j'|j#S | jJ  |   dS |j&tjKkr|j#tj
j@ r| j+ s| %|j&|j'|j#S | jL  |   dS |j&tjKkr | j+ s| %|j&|j'|j#S | jM  |   dS |j&tjNkrT|j#tj
j@ rT| j+ s>| %|j&|j'|j#S | jO  |   dS |j&tjNkr| j+ s| %|j&|j'|j#S | jP  |   dS |j&| jQ kr| jjRr|j#tj
j@ r| jS|j&}|   |S |j&| jQ kr$| jjRr$|j#tj
j@ r$| jT|j&}|   |S |j#tj
jtj
jB @ rP| %|j&|j'|j#S |j#tj
j@ rt| %|j&|j'|j#S |	r|| j,| j- | j. ks| jj	r|| jU| j- | j. k	rt dkrtjddd|i   | jjr6tV| jjW| jXkstV| jjWdkr|| jjWd dkr|| jr*| Y  n
| j  nFtV| jjW| jZks`tV| jjW| jj[kr|| jrr| Y  n
| j  | j\|}|s| j9r| jj]r| j^  | Y  | _|S | Y  |   dS | j	r| j` 	r| jjW| jjRd d k	r| Y  |   dS |j&| jak	rB| Y 	r>| jj9	r>| 4d dS |j&| jbk	rp| jjR	rp| jc }|   |S |j&| jdk	r| jjR	r| je }|   |S |j&| jQ k	r| jjR	r| jS|j&	r| j4| j+ | j: d dS |
rvt dk
rtjddd|i   | jjR
s,| 4| j:  n| j  | 4| j+  t0|
rb| 4| 1| n| 4| 2| dS | %|j&|j'|j#S )u   
        Process a key event in “Table” mode, i.e. when the
        table is actually used and not switched off by using
        direct input.
        r   z _table_mode_process_key_event() zrepr(key)=%(key)s
rE  Tr   r(   r\   r  z7_table_mode_process_key_event() leading invalid input: zrepr(keychar)=%(keychar)s
r  z-_table_mode_process_key_event() valid input: r   z!@#$%r   r  z8_table_mode_process_key_event() trailing invalid input: )fr   r1   r   r   rY  rh  r   r  r   ZKEY_Shift_RrB   rC   r  r   r  r   r  Z	KEY_Alt_LrH   r0  Z	KEY_commarF   rp   r  r  r   Z	KEY_slashr  r  r  rf  ZKEY_semicolonr   r  r   r=   rM   r  r<   r6   r@   r  r  r   ru   rw   rx   r  r   r  r  rc  r  Z
KEY_Escaper  Z
KEY_ReturnZKEY_KP_Enterr   r   ZKEY_TabZ
KEY_KP_TabZKEY_DownZKEY_KP_Downr%  ZKEY_UpZ	KEY_KP_Upr'  ZKEY_LeftZKEY_KP_Leftr   Z	KEY_RightZKEY_KP_Rightr   r   r   ZKEY_BackSpacer   r-  Z
KEY_Deleter   r.  r   r   r*  r+  rv   r   r|   rt   r  rs   Zpossible_tabkeys_lengthsr   r   r   r  r1  r_  r\  r(  r[  r)  )rP   rE  r   r  r  r  r   r   r   r    s      
 
   






















 


















z'TabEngine._table_mode_process_key_eventc                 C   sB   t dkrtjd | jr>| | j | | j| j	 | 
  d S )Nr   zdo_focus_in())r   r1   r   r   ry  r  r  r  rl  ra  r  rT   r   r   r   do_focus_in8  s    zTabEngine.do_focus_inc                 C   s   | j rd| _| j  d S r;   )rP  rO  rh  r   rT   r   r   r   r  B  s    zTabEngine.do_focus_outc                 C   s   | j r|| _d S r   )rP  rO  )rP   ZpurposeZ_hintsr   r   r   do_set_content_typeG  s    zTabEngine.do_set_content_typec                 C   s   d| _ |   d S )NT)ry  r  rT   r   r   r   	do_enableK  s    zTabEngine.do_enablec                 C   s
   d| _ d S )NF)ry  rT   r   r   r   
do_disableO  s    zTabEngine.do_disablec                 C   s   | j  r|   dS dS NTF)rh  r)  r  rT   r   r   r   
do_page_upR  s    
zTabEngine.do_page_upc                 C   s   | j  r|   dS dS r  )rh  r(  r  rT   r   r   r   do_page_downX  s    
zTabEngine.do_page_downc                 C   s  t | j|}tjd| j||f  |dkr@| | dS |dkrZ| j	|dd dS |dkrt| j
|dd dS |dkr| j|dd dS |d	kr| j|d
dd dS |dkr| j|d
dd dS |dkr| j|dd dS |dkr| j|dd dS |dkr| j|dd dS |dkr4| j|ddd dS |dkrR| j|ddd dS |dkrn| j|dd dS |dkr| j|dd dS |dkr| j|dd dS |dkr| j|dd dS |dkr| j|dd dS tjd dS )zG
        Called when a value in the settings has been changed.
        u6   Settings changed for engine “%s”: key=%s value=%s
r:  Nrm   F)r  r?  rl   r;  r   )r  r  r=  rf   re   rk   r<  r   r>  r@  r9  r6  r7  r8  zUnknown key
)r   r   rq   r   r1   r   r   rW  r  r  r  r  r  r  r  r  r  r  r  r  r  r  )rP   Z	_settingsrE  valuer   r   r   rX  ^  s|    

  


  




z$TabEngine.on_gsettings_value_changed)F)r   )F)FT)FT)FT)FT)r\   T)r\   T)FT)FT)T)T)Fr   T)Fr   T)r   T)r   )r   )r\   r\   )r\   )GrV   rW   rX   rY   rS   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r"  r  r  r  r  r  r   r  r  rx  r   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r  r  r  rX  __classcell__r   r   r  r   r     s      w	








,


!     
"	     
"

*
5
8;

0 	%0   
r   __main__r   )'rY   __all__r1   r   r   r{  gettextr   r3  ZN_Zgir   Zgi.repositoryr   r   r   r   r   rr   r   r   r   r   r0   r8   r9   r}  r  r:   objectrZ   ZEnginer   rV   ZdoctestZtestmodZFAILEDZ	ATTEMPTEDexitr   r   r   r   <module>   s   


2?,       q                 /
