Refactor Speller
This commit is contained in:
parent
970d6f8c3f
commit
3c103315ec
|
@ -58,13 +58,6 @@ from gajim.common.exceptions import GajimGeneralException
|
|||
from gajim.common.const import AvatarSize
|
||||
|
||||
from gajim.command_system.implementation.hosts import ChatCommands
|
||||
|
||||
try:
|
||||
from gajim import gtkspell
|
||||
HAS_GTK_SPELL = True
|
||||
except (ImportError, ValueError):
|
||||
HAS_GTK_SPELL = False
|
||||
|
||||
from gajim.chat_control_base import ChatControlBase
|
||||
|
||||
################################################################################
|
||||
|
@ -1180,10 +1173,7 @@ class ChatControl(ChatControlBase):
|
|||
self.handlers[i].disconnect(i)
|
||||
del self.handlers[i]
|
||||
self.conv_textview.del_handlers()
|
||||
if app.config.get('use_speller') and HAS_GTK_SPELL:
|
||||
spell_obj = gtkspell.get_from_text_view(self.msg_textview)
|
||||
if spell_obj:
|
||||
spell_obj.detach()
|
||||
self.remove_speller()
|
||||
self.msg_textview.destroy()
|
||||
# PluginSystem: calling shutdown of super class (ChatControlBase) to let
|
||||
# it remove it's GUI extension points
|
||||
|
|
|
@ -35,12 +35,14 @@ from gi.repository import Pango
|
|||
from gi.repository import GObject
|
||||
from gi.repository import GLib
|
||||
from gi.repository import Gio
|
||||
|
||||
from gajim import gtkgui_helpers
|
||||
from gajim.gtkgui_helpers import Color
|
||||
from gajim import message_control
|
||||
from gajim import dialogs
|
||||
from gajim import history_window
|
||||
from gajim import notify
|
||||
from gajim import gtkspell
|
||||
import re
|
||||
|
||||
from gajim import emoticons
|
||||
|
@ -64,11 +66,6 @@ from gajim.command_system.implementation.middleware import CommandTools
|
|||
from gajim.command_system.implementation import standard
|
||||
from gajim.command_system.implementation import execute
|
||||
|
||||
try:
|
||||
from gajim import gtkspell
|
||||
HAS_GTK_SPELL = True
|
||||
except (ImportError, ValueError):
|
||||
HAS_GTK_SPELL = False
|
||||
|
||||
################################################################################
|
||||
class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
|
||||
|
@ -355,7 +352,8 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
|
|||
self.set_emoticon_popover()
|
||||
|
||||
# Attach speller
|
||||
if app.config.get('use_speller') and HAS_GTK_SPELL:
|
||||
self.spell = None
|
||||
self.spell_handlers = []
|
||||
self.set_speller()
|
||||
self.conv_textview.tv.show()
|
||||
|
||||
|
@ -480,24 +478,57 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
|
|||
image.set_from_pixbuf(icon)
|
||||
|
||||
def set_speller(self):
|
||||
# now set the one the user selected
|
||||
if not gtkspell.HAS_GTK_SPELL or not app.config.get('use_speller'):
|
||||
return
|
||||
|
||||
def _on_focus_in(*args):
|
||||
if self.spell is None:
|
||||
return
|
||||
self.spell.attach(self.msg_textview)
|
||||
|
||||
def _on_focus_out(*args):
|
||||
if self.spell is None:
|
||||
return
|
||||
if not self.msg_textview.has_text():
|
||||
self.spell.detach()
|
||||
|
||||
lang = self.get_speller_language()
|
||||
if not lang:
|
||||
return
|
||||
try:
|
||||
self.spell = gtkspell.Spell(self.msg_textview, lang)
|
||||
self.spell.connect('language_changed', self.on_language_changed)
|
||||
handler_id = self.msg_textview.connect('focus-in-event',
|
||||
_on_focus_in)
|
||||
self.spell_handlers.append(handler_id)
|
||||
handler_id = self.msg_textview.connect('focus-out-event',
|
||||
_on_focus_out)
|
||||
self.spell_handlers.append(handler_id)
|
||||
except OSError:
|
||||
dialogs.AspellDictError(lang)
|
||||
app.config.set('use_speller', False)
|
||||
|
||||
def remove_speller(self):
|
||||
if self.spell is None:
|
||||
return
|
||||
self.spell.detach()
|
||||
for id_ in self.spell_handlers:
|
||||
self.msg_textview.disconnect(id_)
|
||||
self.spell_handlers.remove(id_)
|
||||
self.spell = None
|
||||
|
||||
def get_speller_language(self):
|
||||
per_type = 'contacts'
|
||||
if self.type_id == message_control.TYPE_GC:
|
||||
if self.type_id == 'gc':
|
||||
per_type = 'rooms'
|
||||
lang = app.config.get_per(per_type, self.contact.jid,
|
||||
'speller_language')
|
||||
lang = app.config.get_per(
|
||||
per_type, self.contact.jid, 'speller_language')
|
||||
if not lang:
|
||||
# use the default one
|
||||
lang = app.config.get('speller_language')
|
||||
if not lang:
|
||||
lang = app.LANG
|
||||
if lang:
|
||||
try:
|
||||
self.spell = gtkspell.Spell(self.msg_textview, lang)
|
||||
self.msg_textview.lang = lang
|
||||
self.spell.connect('language_changed', self.on_language_changed)
|
||||
except (GObject.GError, RuntimeError, TypeError, OSError):
|
||||
dialogs.AspellDictError(lang)
|
||||
return lang or None
|
||||
|
||||
def on_language_changed(self, spell, lang):
|
||||
per_type = 'contacts'
|
||||
|
@ -505,9 +536,8 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
|
|||
per_type = 'rooms'
|
||||
if not app.config.get_per(per_type, self.contact.jid):
|
||||
app.config.add_per(per_type, self.contact.jid)
|
||||
app.config.set_per(per_type, self.contact.jid, 'speller_language',
|
||||
lang)
|
||||
self.msg_textview.lang = lang
|
||||
app.config.set_per(
|
||||
per_type, self.contact.jid, 'speller_language', lang)
|
||||
|
||||
def on_banner_label_populate_popup(self, label, menu):
|
||||
"""
|
||||
|
|
|
@ -50,12 +50,7 @@ from gajim import message_control
|
|||
from gajim.chat_control_base import ChatControlBase
|
||||
from gajim import dataforms_widget
|
||||
from gajim import gui_menu_builder
|
||||
|
||||
try:
|
||||
from gajim import gtkspell
|
||||
HAS_GTK_SPELL = True
|
||||
except (ImportError, ValueError):
|
||||
HAS_GTK_SPELL = False
|
||||
from gajim import gtkspell
|
||||
|
||||
from gajim.common import helpers
|
||||
from gajim.common import app
|
||||
|
@ -192,7 +187,7 @@ class PreferencesWindow:
|
|||
self.xml.get_object('xhtml_checkbutton').set_active(st)
|
||||
|
||||
# use speller
|
||||
if HAS_GTK_SPELL:
|
||||
if gtkspell.HAS_GTK_SPELL:
|
||||
st = app.config.get('use_speller')
|
||||
self.xml.get_object('speller_checkbutton').set_active(st)
|
||||
else:
|
||||
|
@ -660,23 +655,13 @@ class PreferencesWindow:
|
|||
def apply_speller(self):
|
||||
for ctrl in self._get_all_controls():
|
||||
if isinstance(ctrl, ChatControlBase):
|
||||
try:
|
||||
spell_obj = gtkspell.get_from_text_view(ctrl.msg_textview)
|
||||
except (TypeError, RuntimeError, OSError):
|
||||
spell_obj = None
|
||||
|
||||
if not spell_obj:
|
||||
ctrl.set_speller()
|
||||
|
||||
def remove_speller(self):
|
||||
for ctrl in self._get_all_controls():
|
||||
if isinstance(ctrl, ChatControlBase):
|
||||
try:
|
||||
spell_obj = gtkspell.get_from_text_view(ctrl.msg_textview)
|
||||
except (TypeError, RuntimeError):
|
||||
spell_obj = None
|
||||
if spell_obj:
|
||||
spell_obj.detach()
|
||||
if ctrl.spell is not None:
|
||||
ctrl.remove_speller()
|
||||
|
||||
def on_speller_checkbutton_toggled(self, widget):
|
||||
active = widget.get_active()
|
||||
|
@ -685,15 +670,10 @@ class PreferencesWindow:
|
|||
lang = app.config.get('speller_language')
|
||||
if not lang:
|
||||
lang = app.LANG
|
||||
tv = Gtk.TextView()
|
||||
try:
|
||||
gtkspell.Spell(tv, lang)
|
||||
except (TypeError, RuntimeError, OSError):
|
||||
dialogs.ErrorDialog(
|
||||
_('Dictionary for lang %s not available') % lang,
|
||||
_('You have to install %s dictionary to use spellchecking, or '
|
||||
'choose another language by setting the speller_language option.'
|
||||
) % lang)
|
||||
|
||||
available = gtkspell.test_language(lang)
|
||||
if not available:
|
||||
dialogs.AspellDictError(lang)
|
||||
app.config.set('use_speller', False)
|
||||
widget.set_active(False)
|
||||
else:
|
||||
|
|
|
@ -42,6 +42,7 @@ from gajim import gtkgui_helpers
|
|||
from gajim import vcard
|
||||
from gajim import conversation_textview
|
||||
from gajim import dataforms_widget
|
||||
from gajim import gtkspell
|
||||
|
||||
from random import randrange
|
||||
from gajim.common import pep
|
||||
|
@ -50,12 +51,6 @@ from gajim.common import const
|
|||
from gajim.options_dialog import OptionsDialog
|
||||
from gajim.common.const import Option, OptionKind, OptionType
|
||||
|
||||
try:
|
||||
from gajim import gtkspell
|
||||
HAS_GTK_SPELL = True
|
||||
except (ImportError, ValueError):
|
||||
HAS_GTK_SPELL = False
|
||||
|
||||
# those imports are not used in this file, but in files that 'import dialogs'
|
||||
# so they can do dialog.GajimThemesWindow() for example
|
||||
from gajim.filetransfers_window import FileTransfersWindow
|
||||
|
@ -1486,11 +1481,11 @@ class FileChooserDialog(Gtk.FileChooserDialog):
|
|||
class AspellDictError:
|
||||
def __init__(self, lang):
|
||||
ErrorDialog(
|
||||
_('Dictionary for lang %s not available') % lang,
|
||||
_('You have to install %s dictionary to use spellchecking, or '
|
||||
'choose another language by setting the speller_language option.'
|
||||
'\n\nHighlighting misspelled words feature will not be used') % lang)
|
||||
app.config.set('use_speller', False)
|
||||
_('Dictionary for lang "%s" not available') % lang,
|
||||
_('You have to install the dictionary "%s" to use spellchecking, '
|
||||
'or choose another language by setting the speller_language '
|
||||
'option.\n\n'
|
||||
'Highlighting misspelled words feature will not be used') % lang)
|
||||
|
||||
class ConfirmationDialog(HigDialog):
|
||||
"""
|
||||
|
@ -3082,14 +3077,14 @@ class SingleMessageWindow:
|
|||
else:
|
||||
self.to_entry.set_text(to)
|
||||
|
||||
if app.config.get('use_speller') and HAS_GTK_SPELL and action == 'send':
|
||||
if app.config.get('use_speller') and gtkspell.HAS_GTK_SPELL and action == 'send':
|
||||
try:
|
||||
lang = app.config.get('speller_language')
|
||||
if not lang:
|
||||
lang = app.LANG
|
||||
gtkspell.Spell(self.conversation_textview.tv, lang)
|
||||
gtkspell.Spell(self.message_textview, lang)
|
||||
except (GObject.GError, TypeError, RuntimeError, OSError):
|
||||
self.spell = gtkspell.Spell(self.message_textview, lang)
|
||||
self.spell.attach(self.message_textview)
|
||||
except OSError:
|
||||
AspellDictError(lang)
|
||||
|
||||
self.prepare_widgets_for(self.action)
|
||||
|
|
|
@ -19,9 +19,16 @@
|
|||
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GLib
|
||||
import gi
|
||||
gi.require_version('GtkSpell', '3.0')
|
||||
from gi.repository import GtkSpell
|
||||
try:
|
||||
from gi.repository import GtkSpell
|
||||
HAS_GTK_SPELL = True
|
||||
except ImportError:
|
||||
HAS_GTK_SPELL = False
|
||||
|
||||
from gajim.common import app
|
||||
|
||||
|
||||
def ensure_attached(func):
|
||||
|
@ -48,12 +55,13 @@ class Spell(GObject.GObject):
|
|||
if spell:
|
||||
raise RuntimeError("Textview has already a Spell obj attached")
|
||||
self.spell = GtkSpell.Checker.new()
|
||||
if not self.spell:
|
||||
raise OSError("Unable to create spell object.")
|
||||
if not self.spell.attach(textview):
|
||||
raise OSError("Unable to attach spell object.")
|
||||
if not self.spell.set_language(language):
|
||||
|
||||
try:
|
||||
self.spell.set_language(language)
|
||||
except GLib.GError as error:
|
||||
if error.domain == 'gtkspell-error-quark':
|
||||
raise OSError("Unable to set language: '%s'" % language)
|
||||
|
||||
self.spell.connect('language-changed', self.on_language_changed)
|
||||
|
||||
else:
|
||||
|
@ -74,12 +82,25 @@ class Spell(GObject.GObject):
|
|||
def recheck_all(self):
|
||||
self.spell.recheck_all()
|
||||
|
||||
@ensure_attached
|
||||
def detach(self):
|
||||
if self.spell is not None:
|
||||
self.spell.detach()
|
||||
self.spell = None
|
||||
|
||||
def attach(self, textview):
|
||||
spell = GtkSpell.Checker.get_from_text_view(textview)
|
||||
if spell is None:
|
||||
print('attached')
|
||||
self.spell.attach(textview)
|
||||
|
||||
|
||||
GObject.type_register(Spell)
|
||||
|
||||
def get_from_text_view(textview):
|
||||
return Spell(textview, create=False)
|
||||
|
||||
def test_language(lang):
|
||||
spell = GtkSpell.Checker.new()
|
||||
try:
|
||||
spell.set_language(lang)
|
||||
except GLib.GError as error:
|
||||
if error.domain == 'gtkspell-error-quark':
|
||||
return False
|
||||
return True
|
||||
|
|
|
@ -2858,18 +2858,6 @@ class Interface:
|
|||
# get transports type from DB
|
||||
app.transport_type = app.logger.get_transports_type()
|
||||
|
||||
# test is dictionnary is present for speller
|
||||
if app.config.get('use_speller'):
|
||||
lang = app.config.get('speller_language')
|
||||
if not lang:
|
||||
lang = app.LANG
|
||||
tv = Gtk.TextView()
|
||||
try:
|
||||
from gajim import gtkspell
|
||||
spell = gtkspell.Spell(tv, lang)
|
||||
except (ImportError, TypeError, RuntimeError, OSError, ValueError):
|
||||
dialogs.AspellDictError(lang)
|
||||
|
||||
if app.config.get('soundplayer') == '':
|
||||
# only on first time Gajim starts
|
||||
commands = ('paplay', 'aplay', 'play', 'ossplay')
|
||||
|
|
|
@ -57,7 +57,7 @@ class MessageTextView(Gtk.TextView):
|
|||
self.undo_list = []
|
||||
# needed to know if we undid something
|
||||
self.undo_pressed = False
|
||||
self.lang = None # Lang used for spell checking
|
||||
|
||||
_buffer = self.get_buffer()
|
||||
self.begin_tags = {}
|
||||
self.end_tags = {}
|
||||
|
@ -92,12 +92,15 @@ class MessageTextView(Gtk.TextView):
|
|||
_buffer.insert_with_tags(
|
||||
start, self.PLACEHOLDER, self.placeholder_tag)
|
||||
|
||||
def _on_focus_in(self, *args):
|
||||
def has_text(self):
|
||||
buf = self.get_buffer()
|
||||
start, end = buf.get_bounds()
|
||||
text = buf.get_text(start, end, True)
|
||||
if text == self.PLACEHOLDER:
|
||||
buf.set_text('')
|
||||
return text != self.PLACEHOLDER
|
||||
|
||||
def _on_focus_in(self, *args):
|
||||
if not self.has_text():
|
||||
self.get_buffer().set_text('')
|
||||
|
||||
def _on_focus_out(self, *args):
|
||||
buf = self.get_buffer()
|
||||
|
|
Loading…
Reference in New Issue