3866 3976 3977: Two 'spell' entries; remove Enchant dependency (patch by Tim Lyons)
svn: r17563
This commit is contained in:
parent
cbe4a1805f
commit
ff638d041b
8
README
8
README
@ -33,10 +33,8 @@ The following packages are *STRONGLY RECOMMENDED* to be installed:
|
|||||||
Obtain it from: http://tilloy.net/dev/pyexiv2/download.html
|
Obtain it from: http://tilloy.net/dev/pyexiv2/download.html
|
||||||
|
|
||||||
The following packages are optional
|
The following packages are optional
|
||||||
python gtkspell
|
python gtkspell Enable spell checking in the notes, gtkspell contains the
|
||||||
python enchant Enable spell checking in the notes, gtkspell contains the
|
libraries.
|
||||||
libraries, enchant is needed to query the installed languages.
|
|
||||||
Both must be present for spell check to activate
|
|
||||||
|
|
||||||
ttf-freefont More font support in the reports
|
ttf-freefont More font support in the reports
|
||||||
|
|
||||||
@ -62,6 +60,8 @@ The following packages are optional
|
|||||||
It can be in python-gnome2-extras or python-gtkhtml2
|
It can be in python-gnome2-extras or python-gtkhtml2
|
||||||
depending on distributions.
|
depending on distributions.
|
||||||
|
|
||||||
|
No longer needed in 3.3:
|
||||||
|
python-enchant Enchant
|
||||||
No longer needed in 3.2:
|
No longer needed in 3.2:
|
||||||
python glade bindings
|
python glade bindings
|
||||||
No longer needed in 3.1:
|
No longer needed in 3.1:
|
||||||
|
255
src/Spell.py
255
src/Spell.py
@ -50,12 +50,6 @@ LOG = logging.getLogger(".Spell")
|
|||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
import gtk
|
import gtk
|
||||||
|
|
||||||
try:
|
|
||||||
import enchant
|
|
||||||
HAVE_ENCHANT = True
|
|
||||||
except ImportError:
|
|
||||||
HAVE_ENCHANT = False
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import gtkspell
|
import gtkspell
|
||||||
HAVE_GTKSPELL = True
|
HAVE_GTKSPELL = True
|
||||||
@ -78,236 +72,63 @@ import config
|
|||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
|
|
||||||
# All official dictionaries available for GNU Aspell.
|
|
||||||
# ftp://ftp.gnu.org/gnu/aspell/dict/0index.html
|
|
||||||
LANGUAGES = {
|
|
||||||
'af': _('Afrikaans'),
|
|
||||||
'am': _('Amharic'),
|
|
||||||
'ar': _('Arabic'),
|
|
||||||
'az': _('Azerbaijani'),
|
|
||||||
'be': _('Belarusian'),
|
|
||||||
'bg': _('Bulgarian'),
|
|
||||||
'bn': _('Bengali'),
|
|
||||||
'br': _('Breton'),
|
|
||||||
'ca': _('Catalan'),
|
|
||||||
'cs': _('Czech'),
|
|
||||||
'csb': _('Kashubian'),
|
|
||||||
'cy': _('Welsh'),
|
|
||||||
'da': _('Danish'),
|
|
||||||
'de': _('German'),
|
|
||||||
'de-alt': _('German - Old Spelling'),
|
|
||||||
'el': _('Greek'),
|
|
||||||
'en': _('English'),
|
|
||||||
'eo': _('Esperanto'),
|
|
||||||
'es': _('Spanish'),
|
|
||||||
'et': _('Estonian'),
|
|
||||||
'fa': _('Persian'),
|
|
||||||
'fi': _('Finnish'),
|
|
||||||
'fo': _('Faroese'),
|
|
||||||
'fr': _('French'),
|
|
||||||
'fy': _('Frisian'),
|
|
||||||
'ga': _('Irish'),
|
|
||||||
'gd': _('Scottish Gaelic'),
|
|
||||||
'gl': _('Galician'),
|
|
||||||
'gu': _('Gujarati'),
|
|
||||||
'gv': _('Manx Gaelic'),
|
|
||||||
'he': _('Hebrew'),
|
|
||||||
'hi': _('Hindi'),
|
|
||||||
'hil': _('Hiligaynon'),
|
|
||||||
'hr': _('Croatian'),
|
|
||||||
'hsb': _('Upper Sorbian'),
|
|
||||||
'hu': _('Hungarian'),
|
|
||||||
'hy': _('Armenian'),
|
|
||||||
'ia': _('Interlingua'),
|
|
||||||
'id': _('Indonesian'),
|
|
||||||
'is': _('Icelandic'),
|
|
||||||
'it': _('Italian'),
|
|
||||||
'ku': _('Kurdi'),
|
|
||||||
'la': _('Latin'),
|
|
||||||
'lt': _('Lithuanian'),
|
|
||||||
'lv': _('Latvian'),
|
|
||||||
'mg': _('Malagasy'),
|
|
||||||
'mi': _('Maori'),
|
|
||||||
'mk': _('Macedonian'),
|
|
||||||
'mn': _('Mongolian'),
|
|
||||||
'mr': _('Marathi'),
|
|
||||||
'ms': _('Malay'),
|
|
||||||
'mt': _('Maltese'),
|
|
||||||
'nb': _('Norwegian Bokmal'),
|
|
||||||
'nds': _('Low Saxon'),
|
|
||||||
'nl': _('Dutch'),
|
|
||||||
'nn': _('Norwegian Nynorsk'),
|
|
||||||
'ny': _('Chichewa'),
|
|
||||||
'or': _('Oriya'),
|
|
||||||
'pa': _('Punjabi'),
|
|
||||||
'pl': _('Polish'),
|
|
||||||
'pt': _('Portuguese'),
|
|
||||||
'pt_BR': _('Brazilian Portuguese'),
|
|
||||||
'pt_PT': _('Portuguese'),
|
|
||||||
'qu': _('Quechua'),
|
|
||||||
'ro': _('Romanian'),
|
|
||||||
'ru': _('Russian'),
|
|
||||||
'rw': _('Kinyarwanda'),
|
|
||||||
'sc': _('Sardinian'),
|
|
||||||
'sk': _('Slovak'),
|
|
||||||
'sl': _('Slovenian'),
|
|
||||||
'sr': _('Serbian'),
|
|
||||||
'sv': _('Swedish'),
|
|
||||||
'sw': _('Swahili'),
|
|
||||||
'ta': _('Tamil'),
|
|
||||||
'te': _('Telugu'),
|
|
||||||
'tet': _('Tetum'),
|
|
||||||
'tl': _('Tagalog'),
|
|
||||||
'tn': _('Setswana'),
|
|
||||||
'tr': _('Turkish'),
|
|
||||||
'uk': _('Ukrainian'),
|
|
||||||
'uz': _('Uzbek'),
|
|
||||||
'vi': _('Vietnamese'),
|
|
||||||
'wa': _('Walloon'),
|
|
||||||
'yi': _('Yiddish'),
|
|
||||||
'zu': _('Zulu'),
|
|
||||||
}
|
|
||||||
|
|
||||||
class Spell(object):
|
class Spell(object):
|
||||||
"""Attach a gtkspell instance to the passed TextView instance.
|
"""Attach a gtkspell instance to the passed TextView instance.
|
||||||
"""
|
"""
|
||||||
lang = locale.getlocale()[0] or "en"
|
_spellcheck_options = {'off': _('Off')}
|
||||||
_installed_languages = {'off': _('None')}
|
|
||||||
|
if HAVE_GTKSPELL:
|
||||||
|
_spellcheck_options['on'] = _('On')
|
||||||
|
|
||||||
if HAVE_ENCHANT and HAVE_GTKSPELL:
|
|
||||||
#gtkspell depends on enchant but has no api to query the installed
|
|
||||||
#languages. Hence, we use enchant to do this if available.
|
|
||||||
for language in enchant.list_languages():
|
|
||||||
try:
|
|
||||||
name = LANGUAGES[language]
|
|
||||||
except KeyError:
|
|
||||||
name = language
|
|
||||||
if name == language:
|
|
||||||
parts = name.split('_')
|
|
||||||
if len(parts) == 2:
|
|
||||||
try:
|
|
||||||
name = LANGUAGES[parts[0]]
|
|
||||||
name += ': ' + parts[1]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
_installed_languages[language] = " ".join(name.split('_'))
|
|
||||||
|
|
||||||
elif not HAVE_ENCHANT and HAVE_GTKSPELL:
|
|
||||||
# if lang is None, default to en:
|
|
||||||
tested = False
|
|
||||||
#we try a hack to get the locale language.
|
|
||||||
for (lang_code, lang_name) in LANGUAGES.items():
|
|
||||||
# if this lang is the current locale:
|
|
||||||
if (lang == lang_code):
|
|
||||||
tested = True
|
|
||||||
# if it is english, we know it works:
|
|
||||||
if lang == "en":
|
|
||||||
_installed_languages[lang] = lang_name
|
|
||||||
print _("Warning: spelling checker language limited to "
|
|
||||||
"locale 'en'; install pyenchant/python-enchant "
|
|
||||||
"for better options.")
|
|
||||||
elif locale.getlocale()[1] == "UTF8":
|
|
||||||
# Only worked with UTF8 versions of language.
|
|
||||||
# But, we need to test it:
|
|
||||||
try:
|
|
||||||
#work around gtkspell bug with tv
|
|
||||||
tv = gtk.TextView()
|
|
||||||
gtkspell.Spell(tv).set_language(lang_code)
|
|
||||||
_installed_languages[lang_code] = lang_name
|
|
||||||
print _("Warning: spelling checker language limited to "
|
|
||||||
"locale '%s'; install pyenchant/python-enchant "
|
|
||||||
"for better options.") % lang
|
|
||||||
except:
|
|
||||||
# FIXME: this does not work anymore since 10/2008!!!
|
|
||||||
# if pyenchant is installed we can avoid it, otherwise
|
|
||||||
# perhaps future gtkspell3 will offer a solution.
|
|
||||||
print _("Warning: spelling checker disabled; "
|
|
||||||
"install pyenchant/python-enchant to enable.")
|
|
||||||
# if we matched, we're done looking
|
|
||||||
break
|
|
||||||
if not tested:
|
|
||||||
# if we didn't see a match on lang, then there is no spell check
|
|
||||||
print _("Warning: spelling checker disabled; "
|
|
||||||
"install pyenchant/python-enchant to enable.")
|
|
||||||
|
|
||||||
def __init__(self, textview):
|
def __init__(self, textview):
|
||||||
self.textview = textview
|
self.textview = textview
|
||||||
|
|
||||||
if self.lang and config.get('behavior.spellcheck'):
|
if HAVE_GTKSPELL and config.get('behavior.spellcheck'):
|
||||||
# if LANG is not a correct key (pt_BR or pt_PT),
|
self.spellcheck = 'on'
|
||||||
# try only the language part of LANG
|
|
||||||
if self.lang not in self._installed_languages:
|
|
||||||
self.lang = self.lang.split('_')[0]
|
|
||||||
# if this still doesn't work we fall back to 'off'
|
|
||||||
if self.lang not in self._installed_languages:
|
|
||||||
self.lang = 'off'
|
|
||||||
else:
|
else:
|
||||||
self.lang = 'off'
|
self.spellcheck = 'off'
|
||||||
|
|
||||||
self._active_language = 'off'
|
self._active_spellcheck = 'off'
|
||||||
self.__real_set_active_language(self.lang)
|
self.__real_set_active_spellcheck(self.spellcheck)
|
||||||
|
|
||||||
# Private
|
# Private
|
||||||
|
|
||||||
def __real_set_active_language(self, lang_code):
|
def __real_set_active_spellcheck(self, spellcheck_code):
|
||||||
"""Set the active language by it's code."""
|
"""Set active spellcheck by its code."""
|
||||||
if self._active_language == 'off':
|
if self._active_spellcheck == 'off':
|
||||||
if lang_code == 'off':
|
if spellcheck_code == 'off':
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
gtkspell_spell = gtkspell.Spell(self.textview)
|
try:
|
||||||
|
gtkspell_spell = gtkspell.Spell(self.textview)
|
||||||
|
self._active_spellcheck = spellcheck_code
|
||||||
|
except:
|
||||||
|
# attaching the spellchecker will fail if
|
||||||
|
# the language does not exist
|
||||||
|
# and presumably if there is no dictionary
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
gtkspell_spell = gtkspell.get_from_text_view(self.textview)
|
if spellcheck_code == 'on':
|
||||||
if lang_code == 'off':
|
|
||||||
gtkspell_spell.detach()
|
|
||||||
self._active_language = lang_code
|
|
||||||
return
|
return
|
||||||
try:
|
else:
|
||||||
gtkspell_spell.set_language(lang_code)
|
gtkspell_spell = gtkspell.get_from_text_view(self.textview)
|
||||||
self._active_language = lang_code
|
gtkspell_spell.detach()
|
||||||
except RuntimeError:
|
self._active_spellcheck = spellcheck_code
|
||||||
#This catches error with old gtkspell versions that generate
|
|
||||||
#this exception if dict cannot be loaded.
|
|
||||||
gtkspell_spell.detach()
|
|
||||||
self._active_language = 'off'
|
|
||||||
|
|
||||||
# Public API
|
# Public API
|
||||||
|
|
||||||
def get_all_languages(self):
|
def get_all_spellchecks(self):
|
||||||
"""Get the list of installed language names."""
|
"""Get the list of installed spellcheck names."""
|
||||||
langs = self._installed_languages.values()
|
return self._spellcheck_options.values()
|
||||||
langs.sort(sort_languages)
|
|
||||||
return langs
|
|
||||||
|
|
||||||
def set_active_language(self, language):
|
def set_active_spellcheck(self, spellcheck):
|
||||||
"""Set active language by it's name."""
|
"""Set active spellcheck by it's name."""
|
||||||
for code, name in self._installed_languages.items():
|
for code, name in self._spellcheck_options.items():
|
||||||
if name == language:
|
if name == spellcheck:
|
||||||
self.__real_set_active_language(code)
|
self.__real_set_active_spellcheck(code)
|
||||||
return
|
return
|
||||||
|
|
||||||
def get_active_language(self):
|
def get_active_spellcheck(self):
|
||||||
"""Get the name of the active language."""
|
"""Get the name of the active spellcheck."""
|
||||||
return self._installed_languages[self._active_language]
|
return self._spellcheck_options[self._active_spellcheck]
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# sort_languages
|
|
||||||
#
|
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
def sort_languages(lang_a, lang_b):
|
|
||||||
"""Put language names in alphabetical order.
|
|
||||||
|
|
||||||
Except 'None', which should be always the first.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if lang_a == _('None'):
|
|
||||||
return -1
|
|
||||||
if lang_b == _('None'):
|
|
||||||
return 1
|
|
||||||
if lang_a < lang_b:
|
|
||||||
return -1
|
|
||||||
if lang_a > lang_b:
|
|
||||||
return 1
|
|
||||||
return 0
|
|
||||||
|
@ -359,12 +359,12 @@ class StyledTextEditor(gtk.TextView):
|
|||||||
"""Signal handler.
|
"""Signal handler.
|
||||||
|
|
||||||
Insert extra menuitems:
|
Insert extra menuitems:
|
||||||
1. Insert language selector submenu for spell checking.
|
1. Insert spellcheck selector submenu for spell checking.
|
||||||
2. Insert extra menus depending on ULR match result.
|
2. Insert extra menus depending on ULR match result.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# spell checker submenu
|
# spell checker submenu
|
||||||
spell_menu = gtk.MenuItem(_('Spell'))
|
spell_menu = gtk.MenuItem(_('Spellcheck'))
|
||||||
spell_menu.set_submenu(self._create_spell_menu())
|
spell_menu.set_submenu(self._create_spell_menu())
|
||||||
spell_menu.show_all()
|
spell_menu.show_all()
|
||||||
menu.prepend(spell_menu)
|
menu.prepend(spell_menu)
|
||||||
@ -548,22 +548,22 @@ class StyledTextEditor(gtk.TextView):
|
|||||||
"[a-z0-9-]*(\\.[a-z0-9][a-z0-9-]*)+", MAIL)
|
"[a-z0-9-]*(\\.[a-z0-9][a-z0-9-]*)+", MAIL)
|
||||||
|
|
||||||
def _create_spell_menu(self):
|
def _create_spell_menu(self):
|
||||||
"""Create a menu with all the installed languages.
|
"""Create a menu with all the installed spellchecks.
|
||||||
|
|
||||||
It is called each time the popup menu is opened. Each language
|
It is called each time the popup menu is opened. Each spellcheck
|
||||||
forms a radio menu item, and the selected language is set as active.
|
forms a radio menu item, and the selected spellcheck is set as active.
|
||||||
|
|
||||||
@returns: menu containing all the installed languages.
|
@returns: menu containing all the installed spellchecks.
|
||||||
@returntype: gtk.Menu
|
@returntype: gtk.Menu
|
||||||
|
|
||||||
"""
|
"""
|
||||||
active_language = self.spellcheck.get_active_language()
|
active_spellcheck = self.spellcheck.get_active_spellcheck()
|
||||||
|
|
||||||
menu = gtk.Menu()
|
menu = gtk.Menu()
|
||||||
group = None
|
group = None
|
||||||
for lang in self.spellcheck.get_all_languages():
|
for lang in self.spellcheck.get_all_spellchecks():
|
||||||
menuitem = gtk.RadioMenuItem(group, lang)
|
menuitem = gtk.RadioMenuItem(group, lang)
|
||||||
menuitem.set_active(lang == active_language)
|
menuitem.set_active(lang == active_spellcheck)
|
||||||
menuitem.connect('activate', self._spell_change_cb, lang)
|
menuitem.connect('activate', self._spell_change_cb, lang)
|
||||||
menu.append(menuitem)
|
menu.append(menuitem)
|
||||||
|
|
||||||
@ -705,9 +705,9 @@ class StyledTextEditor(gtk.TextView):
|
|||||||
action.set_value(style_value)
|
action.set_value(style_value)
|
||||||
self._internal_style_change = False
|
self._internal_style_change = False
|
||||||
|
|
||||||
def _spell_change_cb(self, menuitem, language):
|
def _spell_change_cb(self, menuitem, spellcheck):
|
||||||
"""Set spell checker language according to user selection."""
|
"""Set spell checker spellcheck according to user selection."""
|
||||||
self.spellcheck.set_active_language(language)
|
self.spellcheck.set_active_spellcheck(spellcheck)
|
||||||
|
|
||||||
def _open_url_cb(self, menuitem, url, flavor):
|
def _open_url_cb(self, menuitem, url, flavor):
|
||||||
"""Open the URL in a browser."""
|
"""Open the URL in a browser."""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user