Port from GtkSpell to Gspell
This commit is contained in:
parent
28073ee118
commit
5df562d302
@ -75,11 +75,9 @@ The following packages are **STRONGLY RECOMMENDED** to be installed:
|
||||
|
||||
The following packages are optional:
|
||||
------------------------------------
|
||||
* **gtkspell**
|
||||
* **gspell**
|
||||
|
||||
Enable spell checking in the notes. Gtkspell depends on
|
||||
enchant. A version of gtkspell with gobject introspection
|
||||
is needed, so minimally version 3.0.0.
|
||||
Enable spell checking in the notes.
|
||||
|
||||
* **rcs**
|
||||
|
||||
|
@ -302,7 +302,7 @@ Styled Text Buffer
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
.. autoclass:: GtkSpellState
|
||||
.. autoclass:: GspellState
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
@ -790,6 +790,8 @@ class GrampsLocale:
|
||||
"""
|
||||
return self.language
|
||||
|
||||
def locale_code(self):
|
||||
return self.lang
|
||||
|
||||
def get_addon_translator(self, filename, domain="addon",
|
||||
languages=None):
|
||||
|
@ -363,53 +363,12 @@ def show_settings():
|
||||
def verstr(nums):
|
||||
return '.'.join(str(num) for num in nums)
|
||||
|
||||
#GTKSPELL_MIN_VER = (3, 0)
|
||||
#gtkspell_min_ver_str = verstr(GTKSPELL_MIN_VER)
|
||||
# ENCHANT_MIN_VER = (0, 0) # TODO ?
|
||||
gtkspell_ver_tp = (0, 0)
|
||||
# Attempting to import gtkspell gives an error dialog if gtkspell is
|
||||
# not available so test first and log just a warning to the console
|
||||
# instead.
|
||||
try:
|
||||
from gi import Repository
|
||||
repository = Repository.get_default()
|
||||
gtkspell_ver = _("not found")
|
||||
if repository.enumerate_versions("GtkSpell"):
|
||||
try:
|
||||
gi.require_version('GtkSpell', '3.0')
|
||||
from gi.repository import GtkSpell as Gtkspell
|
||||
gtkspell_ver = str(Gtkspell._version)
|
||||
aaa = Gtkspell._version.split(".")
|
||||
v1 = int(aaa[0])
|
||||
v2 = int(aaa[1])
|
||||
gtkspell_ver_tp = (v1, v2)
|
||||
# print("gtkspell_ver " + gtkspell_ver)
|
||||
except Exception:
|
||||
gtkspell_ver = _("not found")
|
||||
elif repository.enumerate_versions("Gtkspell"):
|
||||
try:
|
||||
gi.require_version('Gtkspell', '3.0')
|
||||
from gi.repository import Gtkspell
|
||||
gtkspell_ver = str(Gtkspell._version)
|
||||
gtkspell_ver_tp = Gtkspell._version
|
||||
# print("gtkspell_ver " + gtkspell_ver)
|
||||
except Exception:
|
||||
gtkspell_ver = _("not found")
|
||||
gi.require_version('Gspell', '1')
|
||||
from gi.repository import Gspell
|
||||
gspell_ver = str(Gspell._version)
|
||||
except Exception:
|
||||
gtkspell_ver = _("not found")
|
||||
|
||||
try:
|
||||
import enchant
|
||||
enchant_result = enchant.get_enchant_version()
|
||||
except Exception:
|
||||
from ctypes import cdll, c_char_p
|
||||
try:
|
||||
enchant = cdll.LoadLibrary("libenchant")
|
||||
except FileNotFoundError:
|
||||
enchant = cdll.LoadLibrary("libenchant-2")
|
||||
enchant_ver_call = enchant.enchant_get_version
|
||||
enchant_ver_call.restype = c_char_p
|
||||
enchant_result = enchant_ver_call().decode("utf-8")
|
||||
gspell_ver = _("not found")
|
||||
|
||||
#RCS_MIN_VER = (5, 9, 4)
|
||||
#rcs_ver_str = verstr(RCS_MIN_VER)
|
||||
@ -539,8 +498,7 @@ def show_settings():
|
||||
print('')
|
||||
print("Optional:")
|
||||
print("---------")
|
||||
print(' Gtkspell :', gtkspell_ver)
|
||||
print(' Enchant :', enchant_result)
|
||||
print(' Gspell :', gspell_ver)
|
||||
print(' RCS :', rcs_ver)
|
||||
print(' PILLOW :', pil_ver)
|
||||
print(' GExiv2 : %s' % gexiv2_str)
|
||||
|
@ -71,7 +71,7 @@ from .display import display_help
|
||||
from gramps.gen.plug.utils import available_updates
|
||||
from .plug import PluginWindows
|
||||
#from gramps.gen.errors import WindowActiveError
|
||||
from .spell import HAVE_GTKSPELL
|
||||
from .spell import HAVE_GSPELL
|
||||
from gramps.gen.constfunc import win
|
||||
_ = glocale.translation.gettext
|
||||
from gramps.gen.utils.symbols import Symbols
|
||||
@ -1654,14 +1654,14 @@ class GrampsPreferences(ConfigureDialog):
|
||||
row, 'behavior.spellcheck', start=1, stop=3,
|
||||
tooltip=_("Enable the spelling checker"
|
||||
" for notes."))
|
||||
if not HAVE_GTKSPELL:
|
||||
if not HAVE_GSPELL:
|
||||
obj.set_sensitive(False)
|
||||
spell_dict = {'gramps_wiki_build_spell_url':
|
||||
URL_WIKISTRING +
|
||||
"GEPS_029:_GTK3-GObject_introspection"
|
||||
"_Conversion#Spell_Check_Install"}
|
||||
obj.set_tooltip_text(
|
||||
_("GtkSpell not loaded. "
|
||||
_("Gspell not loaded. "
|
||||
"Spell checking will not be available.\n"
|
||||
"To build it for Gramps see "
|
||||
"%(gramps_wiki_build_spell_url)s") % spell_dict)
|
||||
|
@ -20,8 +20,7 @@
|
||||
#
|
||||
|
||||
"""
|
||||
Provide an interface to the gtkspell interface. This requires
|
||||
python-gnome-extras package. If the gtkspell package is not
|
||||
Provide an interface to the gspell interface. If the gspell package is not
|
||||
present, we default to no spell checking.
|
||||
|
||||
"""
|
||||
@ -45,33 +44,24 @@ LOG = logging.getLogger(".Spell")
|
||||
# GTK libraries
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gi.repository import Gtk
|
||||
from gi import Repository
|
||||
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
HAVE_GTKSPELL = False
|
||||
HAVE_GSPELL = False
|
||||
|
||||
# Attempting to import gtkspell gives an error dialog if gtkspell is not
|
||||
# available so test first and log just a warning to the console instead.
|
||||
repository = Repository.get_default()
|
||||
if repository.enumerate_versions("GtkSpell"):
|
||||
try:
|
||||
import gi
|
||||
gi.require_version('GtkSpell', '3.0')
|
||||
from gi.repository import GtkSpell as Gtkspell
|
||||
HAVE_GTKSPELL = True
|
||||
except:
|
||||
pass
|
||||
elif repository.enumerate_versions("Gtkspell"):
|
||||
try:
|
||||
import gi
|
||||
gi.require_version('Gtkspell', '3.0')
|
||||
from gi.repository import Gtkspell
|
||||
HAVE_GTKSPELL = True
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
import gi
|
||||
gi.require_version('Gspell', '1')
|
||||
from gi.repository import Gspell
|
||||
langs = Gspell.language_get_available()
|
||||
for lang in langs:
|
||||
LOG.debug('%s (%s) dict available', lang.get_name(), lang.get_code())
|
||||
if langs:
|
||||
HAVE_GSPELL = True
|
||||
else:
|
||||
LOG.warning(_("You have no installed dictionaries."))
|
||||
except (ImportError, ValueError):
|
||||
pass
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -87,81 +77,47 @@ from gramps.gen.config import config
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
class Spell:
|
||||
"""Attach a gtkspell instance to the passed TextView instance.
|
||||
"""Attach a Gspell instance to the passed TextView instance.
|
||||
"""
|
||||
_spellcheck_options = {'off': _('Off')}
|
||||
|
||||
if HAVE_GTKSPELL:
|
||||
if HAVE_GSPELL:
|
||||
_spellcheck_options['on'] = _('On')
|
||||
|
||||
def __init__(self, textview):
|
||||
self.textview = textview
|
||||
self._active_spellcheck = 'off'
|
||||
|
||||
if HAVE_GTKSPELL and config.get('behavior.spellcheck'):
|
||||
if not HAVE_GSPELL:
|
||||
return
|
||||
|
||||
locale_code = glocale.locale_code()
|
||||
gspell_language = None
|
||||
if locale_code is not None:
|
||||
gspell_language = Gspell.language_lookup(locale_code[:5])
|
||||
if gspell_language is None:
|
||||
gspell_language= Gspell.language_lookup(locale_code[:2])
|
||||
checker = Gspell.Checker.new(gspell_language)
|
||||
buffer = Gspell.TextBuffer.get_from_gtk_text_buffer(textview.get_buffer())
|
||||
buffer.set_spell_checker(checker)
|
||||
self.gspell_view = Gspell.TextView.get_from_gtk_text_view(textview)
|
||||
|
||||
if config.get('behavior.spellcheck'):
|
||||
self.spellcheck = 'on'
|
||||
else:
|
||||
self.spellcheck = 'off'
|
||||
|
||||
self._active_spellcheck = 'off'
|
||||
self.__real_set_active_spellcheck(self.spellcheck)
|
||||
|
||||
# Private
|
||||
|
||||
def __real_set_active_spellcheck(self, spellcheck_code):
|
||||
"""Set active spellcheck by its code."""
|
||||
if self._active_spellcheck == 'off':
|
||||
if spellcheck_code == 'off':
|
||||
return
|
||||
else:
|
||||
try:
|
||||
#transfer full GTK object, so assign to an attribute!
|
||||
if Gtkspell._namespace == "Gtkspell":
|
||||
self.gtkspell_spell = Gtkspell.Spell.new()
|
||||
elif Gtkspell._namespace == "GtkSpell":
|
||||
self.gtkspell_spell = Gtkspell.Checker.new()
|
||||
try:
|
||||
#check for dictionary in system locale (LANG)
|
||||
#if exist it will be default one
|
||||
self.gtkspell_spell.set_language(None)
|
||||
#TODO: use "get_language_list" for use when there
|
||||
#is no English or systemlocale one
|
||||
except:
|
||||
#else check for English dictionary
|
||||
#if exist it will be default one
|
||||
#other installed one will also be available
|
||||
self.gtkspell_spell.set_language("en")
|
||||
#if that fails no spellchecker will be available
|
||||
with self.textview.undo_disabled():
|
||||
success = self.gtkspell_spell.attach(self.textview)
|
||||
try:
|
||||
#show decoded language codes in the context menu
|
||||
#requires the iso-codes package from http://pkg-isocodes.alioth.debian.org
|
||||
self.gtkspell_spell.set_property("decode-language-codes", True)
|
||||
except TypeError:
|
||||
#available in GtkSpell since version 3.0.3 (2013-06-04)
|
||||
pass
|
||||
self._active_spellcheck = spellcheck_code
|
||||
except Exception as err:
|
||||
# attaching the spellchecker will fail if
|
||||
# the language does not exist
|
||||
# and presumably if there is no dictionary
|
||||
if not self.gtkspell_spell.get_language_list():
|
||||
LOG.warning(_("You have no installed dictionaries. "
|
||||
"Either install one or disable spell "
|
||||
"checking"))
|
||||
else:
|
||||
LOG.warning(_("Spelling checker initialization "
|
||||
"failed: %s"), err)
|
||||
else:
|
||||
if spellcheck_code == 'on':
|
||||
return
|
||||
else:
|
||||
if Gtkspell._namespace == "Gtkspell":
|
||||
self.gtkspell_spell = Gtkspell.Spell.get_from_text_view(self.textview)
|
||||
elif Gtkspell._namespace == "GtkSpell":
|
||||
self.gtkspell_spell = Gtkspell.Checker.get_from_text_view(self.textview)
|
||||
self.gtkspell_spell.detach()
|
||||
self._active_spellcheck = spellcheck_code
|
||||
if self._active_spellcheck == spellcheck_code:
|
||||
return
|
||||
|
||||
self.gspell_view.set_inline_spell_checking(spellcheck_code == 'on')
|
||||
self.gspell_view.set_enable_language_menu(spellcheck_code == 'on')
|
||||
self._active_spellcheck = spellcheck_code
|
||||
|
||||
# Public API
|
||||
|
||||
|
@ -116,15 +116,15 @@ class LinkTag(Gtk.TextTag):
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GtkSpellState class
|
||||
# GspellState class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class GtkSpellState:
|
||||
class GspellState:
|
||||
"""
|
||||
A simple state machine kinda thingy.
|
||||
|
||||
Trying to track Gtk.Spell activities on a buffer and re-apply formatting
|
||||
after Gtk.Spell replaces a misspelled word.
|
||||
Trying to track Gspell activities on a buffer and re-apply formatting
|
||||
after Gspell replaces a misspelled word.
|
||||
"""
|
||||
(STATE_NONE,
|
||||
STATE_CLICKED,
|
||||
@ -180,10 +180,10 @@ class GtkSpellState:
|
||||
|
||||
def get_word_extents_from_mark(self, textbuffer, mark):
|
||||
"""
|
||||
Get the word extents as Gtk.Spell does.
|
||||
Get the word extents as Gspell does.
|
||||
|
||||
Used to get the beginning of the word, in which user right clicked.
|
||||
Formatting found at that position used after Gtk.Spell replaces
|
||||
Formatting found at that position used after Gspell replaces
|
||||
misspelled words.
|
||||
"""
|
||||
start = textbuffer.get_iter_at_mark(mark)
|
||||
@ -198,7 +198,7 @@ class GtkSpellState:
|
||||
|
||||
def forward_word_end(self, iter):
|
||||
"""
|
||||
Gtk.Spell style Gtk.TextIter.forward_word_end.
|
||||
Gspell style Gtk.TextIter.forward_word_end.
|
||||
|
||||
The parameter 'iter' is changing as side effect.
|
||||
"""
|
||||
@ -217,7 +217,7 @@ class GtkSpellState:
|
||||
|
||||
def backward_word_start(self, iter):
|
||||
"""
|
||||
Gtk.Spell style Gtk.TextIter.backward_word_start.
|
||||
Gspell style Gtk.TextIter.backward_word_start.
|
||||
|
||||
The parameter 'iter' is changing as side effect.
|
||||
"""
|
||||
@ -310,8 +310,8 @@ class StyledTextBuffer(UndoableBuffer):
|
||||
|
||||
self.linkcolor = 'blue'
|
||||
|
||||
# init gtkspell "state machine"
|
||||
self.gtkspell_state = GtkSpellState(self)
|
||||
# init gspell "state machine"
|
||||
self.gspell_state = GspellState(self)
|
||||
|
||||
# Virtual methods
|
||||
|
||||
@ -385,6 +385,8 @@ class StyledTextBuffer(UndoableBuffer):
|
||||
else:
|
||||
value = StyledTextTagType.STYLE_DEFAULT[style]
|
||||
for tname in tag_names:
|
||||
if tname is None:
|
||||
continue
|
||||
if tname.startswith(str(style)):
|
||||
value = tname.split(' ', 1)[1]
|
||||
value = StyledTextTagType.STYLE_TYPE[style](value)
|
||||
@ -612,6 +614,8 @@ class StyledTextBuffer(UndoableBuffer):
|
||||
s_tags = []
|
||||
|
||||
for g_tagname, g_ranges in g_tags.items():
|
||||
if g_tagname is None:
|
||||
continue
|
||||
if g_tagname.startswith('link'):
|
||||
tag = self.get_tag_table().lookup(g_tagname)
|
||||
s_ranges = [(start, end+1) for (start, end) in g_ranges]
|
||||
|
@ -402,7 +402,8 @@ class StyledTextEditor(Gtk.TextView):
|
||||
self.match = self.textbuffer.match_check(iter_at_location.get_offset())
|
||||
tooltip = None
|
||||
for tag in (tag for tag in iter_at_location.get_tags()
|
||||
if tag.get_property('name').startswith("link")):
|
||||
if tag.get_property('name') is not None and
|
||||
tag.get_property('name').startswith("link")):
|
||||
self.match = (x, y, LINK, tag.data, tag)
|
||||
tooltip = self.make_tooltip_from_link(tag)
|
||||
break
|
||||
@ -808,7 +809,7 @@ class StyledTextEditor(Gtk.TextView):
|
||||
"""
|
||||
Remove all formats from the selection or from all.
|
||||
|
||||
Remove only our own tags without touching other ones (e.g. Gtk.Spell),
|
||||
Remove only our own tags without touching other ones (e.g. Gspell),
|
||||
thus remove_all_tags() can not be used.
|
||||
"""
|
||||
clear_anything = self.textbuffer.clear_selection()
|
||||
|
Loading…
Reference in New Issue
Block a user