Skip to content

Commit

Permalink
Improve and simplify setting input methods and dictionaries using new…
Browse files Browse the repository at this point in the history
… helper functions

Resolves: #318

New behaviour:

Let’s start the setup tool in Hindi locale:

    $ LC_ALL=hi_IN.UTF-8 python3 setup/main.py &

Setting 'dictionary' or 'inputmethod' to an empty string actually sets
the default for the current locale:

    $ dconf write /org/freedesktop/ibus/engine/typing-booster/dictionary '""'
    $ dconf read /org/freedesktop/ibus/engine/typing-booster/dictionary
    'hi_IN,en_GB'

    $ dconf write /org/freedesktop/ibus/engine/typing-booster/inputmethod '""'
    $ dconf read /org/freedesktop/ibus/engine/typing-booster/inputmethod
    'hi-inscript2,NoIME'

The typing booster engine does the same as the setup tool, it converts empty
strings to the locale defaults, but only at startup. So when the typing booster
engine runs in a different locale than the setup tool, setting empty strings
does not cause a conflict. The code to set the locale defaults is only
executed in the setup tool then because the typing booster engine is already
running. And when it next restarts, these keys are not empty strings anymore
because the setup tool already changed them.

The new code also does some normalization of the 'dictionary' and 'inputmethod'
values (removes encodings, changes to CLDR locale spellings, removes duplicates,
normalizes the spellings of the special dictionary 'None' and the special
input method 'NoIME'):

    $ dconf write /org/freedesktop/ibus/engine/typing-booster/dictionary '"nOnE, en_US.UTF8,en_US,en.UTF-8,en,C, nan_TW.utf8@latin,sr_RS.utf8@latin"'
    $ dconf read /org/freedesktop/ibus/engine/typing-booster/dictionary
    'None,en_US,en,en_US_POSIX,nan_Latn_TW,sr_Latn_RS'

    $ dconf write /org/freedesktop/ibus/engine/typing-booster/inputmethod '"nOiME,, t-latn-post,foobar, "'
    $ dconf read /org/freedesktop/ibus/engine/typing-booster/inputmethod
    'NoIME,t-latn-post,foobar'
  • Loading branch information
mike-fabian committed Jun 23, 2022
1 parent d0df28b commit 02d9197
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 176 deletions.
90 changes: 15 additions & 75 deletions engine/hunspell_table.py
Expand Up @@ -384,34 +384,13 @@ def __init__(
self._dictionary_names: List[str] = []
dictionary = itb_util.variant_to_value(
self._gsettings.get_value('dictionary'))
if dictionary:
# There is a dictionary setting in Gsettings, use that:
names = [x.strip() for x in dictionary.split(',')]
for name in names:
if name:
self._dictionary_names.append(name)
else:
# There is no dictionary setting in Gsettings. Get the default
# dictionaries for the current effective value of
# LC_CTYPE and save it to Gsettings:
self._dictionary_names = itb_util.get_default_dictionaries(
itb_util.get_effective_lc_ctype())
self._dictionary_names = itb_util.dictionaries_str_to_list(dictionary)
if ','.join(self._dictionary_names) != dictionary:
# Value changed due to normalization or getting the locale
# defaults, save it back to settings:
self._gsettings.set_value(
'dictionary',
GLib.Variant.new_string(','.join(self._dictionary_names)))
if (len(self._dictionary_names)
> itb_util.MAXIMUM_NUMBER_OF_DICTIONARIES):
LOGGER.warning(
'Trying to set more than the allowed maximum of '
'%s dictionaries.\n'
'Trying to set: %s\n'
'Really setting: %s\n',
itb_util.MAXIMUM_NUMBER_OF_DICTIONARIES,
self._dictionary_names,
self._dictionary_names[
:itb_util.MAXIMUM_NUMBER_OF_DICTIONARIES])
self._dictionary_names = self._dictionary_names[
:itb_util.MAXIMUM_NUMBER_OF_DICTIONARIES]
self.database.hunspell_obj.set_dictionary_names(
self._dictionary_names[:])

Expand All @@ -429,32 +408,13 @@ def __init__(
# Try to get the selected input methods from Gsettings:
inputmethod = itb_util.variant_to_value(
self._gsettings.get_value('inputmethod'))
if inputmethod:
inputmethods = [re.sub(re.escape('noime'), 'NoIME', x.strip(),
flags=re.IGNORECASE)
for x in inputmethod.split(',') if x]
for ime in inputmethods:
self._current_imes.append(ime)
if self._current_imes == []:
# There is no ime set in Gsettings, get a default list
# of input methods for the current effective value of LC_CTYPE
# and save it to Gsettings:
self._current_imes = itb_util.get_default_input_methods(
itb_util.get_effective_lc_ctype())
self._current_imes = itb_util.input_methods_str_to_list(inputmethod)
if ','.join(self._current_imes) != inputmethod:
# Value changed due to normalization or getting the locale
# defaults, save it back to settings:
self._gsettings.set_value(
'inputmethod',
GLib.Variant.new_string(','.join(self._current_imes)))
if len(self._current_imes) > itb_util.MAXIMUM_NUMBER_OF_INPUT_METHODS:
LOGGER.warning(
'Trying to set more than the allowed maximum of '
'%s input methods.\n'
'Trying to set: %s\n'
'Really setting: %s\n',
itb_util.MAXIMUM_NUMBER_OF_INPUT_METHODS,
self._current_imes,
self._current_imes[:itb_util.MAXIMUM_NUMBER_OF_INPUT_METHODS])
self._current_imes = (
self._current_imes[:itb_util.MAXIMUM_NUMBER_OF_INPUT_METHODS])

self._commit_happened_after_focus_in = False

Expand Down Expand Up @@ -1376,6 +1336,8 @@ def set_current_imes(
:param imes: List of input methods
If a single string is used, it should contain
the names of the input methods separated by commas.
If the string is empty, the default input
methods for the current locale are set.
:param update_gsettings: Whether to write the change to Gsettings.
Set this to False if this method is
called because the Gsettings key changed
Expand All @@ -1384,22 +1346,9 @@ def set_current_imes(
'''
LOGGER.debug('imes=%s type(imes)=%s', imes, type(imes))
if isinstance(imes, str):
imes = [x.strip() for x in imes.split(',')]
imes = [re.sub(re.escape('noime'), 'NoIME', x.strip(),
flags=re.IGNORECASE)
for x in imes if x]
imes = itb_util.input_methods_str_to_list(imes)
if imes == self._current_imes: # nothing to do
return
if len(imes) > itb_util.MAXIMUM_NUMBER_OF_INPUT_METHODS:
LOGGER.error(
'Trying to set more than the allowed maximum of '
'%s input methods.\n'
'Trying to set: %s\n'
'Really setting: %s\n',
itb_util.MAXIMUM_NUMBER_OF_INPUT_METHODS,
imes,
imes[:itb_util.MAXIMUM_NUMBER_OF_INPUT_METHODS])
imes = imes[:itb_util.MAXIMUM_NUMBER_OF_INPUT_METHODS]
if set(imes) != set(self._current_imes):
# Input methods have been added or removed from the list
# of current input methods. Initialize the
Expand Down Expand Up @@ -1431,6 +1380,8 @@ def set_dictionary_names(
If a single string is used, it should contain
the names of the dictionaries separated
by commas.
If the string is empty, the default
dictionaries for the current locale are set.
:param update_gsettings: Whether to write the change to Gsettings.
Set this to False if this method is
called because the Gsettings key changed
Expand All @@ -1440,21 +1391,10 @@ def set_dictionary_names(
LOGGER.debug('dictionary_names=%s type(dictionary_names)=%s',
dictionary_names, type(dictionary_names))
if isinstance(dictionary_names, str):
dictionary_names = [x.strip() for x in dictionary_names.split(',')]
dictionary_names = [x for x in dictionary_names if x]
dictionary_names = itb_util.dictionaries_str_to_list(
dictionary_names)
if dictionary_names == self._dictionary_names: # nothing to do
return
if len(dictionary_names) > itb_util.MAXIMUM_NUMBER_OF_DICTIONARIES:
LOGGER.error(
'Trying to set more than the allowed maximum of '
'%s dictionaries.\n'
'Trying to set: %s\n'
'Really setting: %s\n',
itb_util.MAXIMUM_NUMBER_OF_DICTIONARIES,
dictionary_names,
dictionary_names[:itb_util.MAXIMUM_NUMBER_OF_DICTIONARIES])
dictionary_names = (
dictionary_names[:itb_util.MAXIMUM_NUMBER_OF_DICTIONARIES])
self._dictionary_names = dictionary_names
self.database.hunspell_obj.set_dictionary_names(dictionary_names)
self._update_dictionary_menu_dicts()
Expand Down
6 changes: 3 additions & 3 deletions engine/itb_util.py
Expand Up @@ -633,7 +633,7 @@ def input_methods_str_to_list(imes_str: str) -> List[str]:
If the input contains duplicates, the duplicates are removed:
>>> input_methods_str_to_list('a ,a,b , c , a ,d,e,f')
>>> input_methods_str_to_list('a ,a,b , c ,, a ,d,e,f, ')
['a', 'b', 'c', 'd', 'e', 'f']
Non-standard spellings of the special input method ['NoIME']
Expand All @@ -647,7 +647,7 @@ def input_methods_str_to_list(imes_str: str) -> List[str]:
imes: List[str] = []
for ime in [re.sub(re.escape('noime'), 'NoIME', x.strip(),
flags=re.IGNORECASE)
for x in imes_str.split(',') if x]:
for x in imes_str.split(',') if x.strip()]:
if ime not in imes:
imes.append(ime)
if len(imes) > MAXIMUM_NUMBER_OF_INPUT_METHODS:
Expand Down Expand Up @@ -721,7 +721,7 @@ def dictionaries_str_to_list(dictionaries_str: str) -> List[str]:
dictionaries: List[str] = []
for dictionary in [re.sub(re.escape('none'), 'None', x.strip(),
flags=re.IGNORECASE)
for x in dictionaries_str.split(',') if x]:
for x in dictionaries_str.split(',') if x.strip()]:
if dictionary != 'None':
dictionary = locale_normalize(dictionary)
if dictionary and dictionary not in dictionaries:
Expand Down
118 changes: 20 additions & 98 deletions setup/main.py
Expand Up @@ -2120,35 +2120,10 @@ def _fill_dictionaries_listbox(self) -> None:
self._dictionary_names = []
dictionary = itb_util.variant_to_value(
self._gsettings.get_value('dictionary'))
if dictionary:
names = [x.strip() for x in dictionary.split(',')]
for name in names:
if name:
self._dictionary_names.append(name)
if self._dictionary_names == []:
# There are no dictionaries set in dconf, get a default list of
# dictionaries from the current effective value of LC_CTYPE:
self._dictionary_names = itb_util.get_default_dictionaries(
itb_util.get_effective_lc_ctype())
# And save the default dictionaries to settings:
self._gsettings.set_value(
'dictionary',
GLib.Variant.new_string(','.join(self._dictionary_names)))
if (len(self._dictionary_names)
> itb_util.MAXIMUM_NUMBER_OF_DICTIONARIES):
LOGGER.error(
'Trying to set more than the allowed maximum of '
'%s dictionaries.\n'
'Trying to set: %s\n'
'Really setting: %s\n',
itb_util.MAXIMUM_NUMBER_OF_DICTIONARIES,
self._dictionary_names,
self._dictionary_names[
:itb_util.MAXIMUM_NUMBER_OF_DICTIONARIES])
self._dictionary_names = (
self._dictionary_names[
:itb_util.MAXIMUM_NUMBER_OF_DICTIONARIES])
# Save reduced list of dictionaries back to settings:
self._dictionary_names = itb_util.dictionaries_str_to_list(dictionary)
if ','.join(self._dictionary_names) != dictionary:
# Value changed due to normalization or getting the locale
# defaults, save it back to settings:
self._gsettings.set_value(
'dictionary',
GLib.Variant.new_string(','.join(self._dictionary_names)))
Expand Down Expand Up @@ -2228,34 +2203,10 @@ def _fill_input_methods_listbox(self) -> None:
self._current_imes = []
inputmethod = itb_util.variant_to_value(
self._gsettings.get_value('inputmethod'))
if inputmethod:
inputmethods = [re.sub(re.escape('noime'), 'NoIME', x.strip(),
flags=re.IGNORECASE)
for x in inputmethod.split(',') if x]
for ime in inputmethods:
self._current_imes.append(ime)
if self._current_imes == []:
# There is no ime set in dconf, get a default list of
# input methods for the current effective value of LC_CTYPE:
self._current_imes = itb_util.get_default_input_methods(
itb_util.get_effective_lc_ctype())
# And save the default input methods to settings:
self._gsettings.set_value(
'inputmethod',
GLib.Variant.new_string(','.join(self._current_imes)))
if len(self._current_imes) > itb_util.MAXIMUM_NUMBER_OF_INPUT_METHODS:
LOGGER.error(
'Trying to set more than the allowed maximum of '
'%s input methods.\n'
'Trying to set: %s\n'
'Really setting: %s\n',
itb_util.MAXIMUM_NUMBER_OF_INPUT_METHODS,
self._current_imes,
self._current_imes[
:itb_util.MAXIMUM_NUMBER_OF_INPUT_METHODS])
self._current_imes = (
self._current_imes[:itb_util.MAXIMUM_NUMBER_OF_INPUT_METHODS])
# Save reduced list of input methods back to settings:
self._current_imes = itb_util.input_methods_str_to_list(inputmethod)
if ','.join(self._current_imes) != inputmethod:
# Value changed due to normalization or getting the locale
# defaults, save it back to settings:
self._gsettings.set_value(
'inputmethod',
GLib.Variant.new_string(','.join(self._current_imes)))
Expand Down Expand Up @@ -2477,19 +2428,11 @@ def _on_restore_all_defaults_button_clicked(
schema = gsettings.get_property('settings-schema')
for key in schema.list_keys():
if key in ('googleapplicationcredentials',
'dictionaryinstalltimestamp',
'inputmethod',
'dictionary'):
'dictionaryinstalltimestamp'):
LOGGER.info('Skipping reset of gsettings key=%s', key)
continue
LOGGER.info('Resetting gsettings key=%s', key)
gsettings.reset(key)
LOGGER.info('Setting input methods to default for current locale:')
self.set_current_imes(itb_util.get_default_input_methods(
itb_util.get_effective_lc_ctype()), update_gsettings=True)
LOGGER.info('Setting dictionaries to default for current locale:')
self.set_dictionary_names(itb_util.get_default_dictionaries(
itb_util.get_effective_lc_ctype()), update_gsettings=True)
else:
LOGGER.info('Restore all defaults cancelled.')
self._restore_all_defaults_button.set_sensitive(True)
Expand Down Expand Up @@ -3209,8 +3152,7 @@ def _on_dictionaries_default_button_clicked(self, *_args: Any) -> None:
Sets the dictionaries to the default for the current locale.
'''
self.set_dictionary_names(itb_util.get_default_dictionaries(
itb_util.get_effective_lc_ctype()))
self.set_dictionary_names(itb_util.dictionaries_str_to_list(''))

def _on_dictionary_selected(
self, _listbox: Gtk.ListBox, listbox_row: Gtk.ListBoxRow) -> None:
Expand Down Expand Up @@ -3527,8 +3469,7 @@ def _on_input_methods_default_button_clicked(self, *_args: Any) -> None:
Sets the input methods to the default for the current locale.
'''
self.set_current_imes(itb_util.get_default_input_methods(
itb_util.get_effective_lc_ctype()))
self.set_current_imes(itb_util.input_methods_str_to_list(''))

def _on_input_method_selected(
self, _listbox: Gtk.ListBox, listbox_row: Gtk.ListBoxRow) -> None:
Expand Down Expand Up @@ -5293,30 +5234,20 @@ def set_current_imes(
:param imes: List of input methods
If a single string is used, it should contain
the names of the input methods separated by commas.
If the string is empty, the default input
methods for the current locale are set.
: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.
'''
LOGGER.debug('imes=%s type(imes)=%s', imes, type(imes))
LOGGER.debug('imes=“%s” type(imes)=%s update_gsettings=%s',
imes, type(imes), update_gsettings)
if isinstance(imes, str):
imes = [x.strip() for x in imes.split(',')]
imes = [re.sub(re.escape('noime'), 'NoIME', x.strip(),
flags=re.IGNORECASE)
for x in imes if x]
imes = itb_util.input_methods_str_to_list(imes)
if imes == self._current_imes: # nothing to do
return
if len(imes) > itb_util.MAXIMUM_NUMBER_OF_INPUT_METHODS:
LOGGER.error(
'Trying to set more than the allowed maximum of '
'%s input methods.\n'
'Trying to set: %s\n'
'Really setting: %s\n',
itb_util.MAXIMUM_NUMBER_OF_INPUT_METHODS,
imes,
imes[:itb_util.MAXIMUM_NUMBER_OF_INPUT_METHODS])
imes = imes[:itb_util.MAXIMUM_NUMBER_OF_INPUT_METHODS]
self._current_imes = imes
self._fill_input_methods_listbox()
if update_gsettings:
Expand All @@ -5343,6 +5274,8 @@ def set_dictionary_names(
If a single string is used, it should contain
the names of the dictionaries separated
by commas.
If the string is empty, the default
dictionaries for the current locale are set.
:param update_gsettings: Whether to write the change to Gsettings.
Set this to False if this method is
called because the Gsettings key changed
Expand All @@ -5352,21 +5285,10 @@ def set_dictionary_names(
LOGGER.debug('dictionary_names=%s type(dictionary_names)=%s',
dictionary_names, type(dictionary_names))
if isinstance(dictionary_names, str):
dictionary_names = [x.strip() for x in dictionary_names.split(',')]
dictionary_names = [x for x in dictionary_names if x]
dictionary_names = itb_util.dictionaries_str_to_list(
dictionary_names)
if dictionary_names == self._dictionary_names: # nothing to do
return
if len(dictionary_names) > itb_util.MAXIMUM_NUMBER_OF_DICTIONARIES:
LOGGER.error(
'Trying to set more than the allowed maximum of '
'%s dictionaries.\n'
'Trying to set: %s\n'
'Really setting: %s\n',
itb_util.MAXIMUM_NUMBER_OF_DICTIONARIES,
dictionary_names,
dictionary_names[:itb_util.MAXIMUM_NUMBER_OF_DICTIONARIES])
dictionary_names = dictionary_names[
:itb_util.MAXIMUM_NUMBER_OF_DICTIONARIES]
self._dictionary_names = dictionary_names
self._fill_dictionaries_listbox()
if update_gsettings:
Expand Down

0 comments on commit 02d9197

Please sign in to comment.