Refactor SpellChecker
- use Gspell instead of GtkSpell, it seems to have alot less problems and needs less code
This commit is contained in:
		
							parent
							
								
									f75dd8bcad
								
							
						
					
					
						commit
						7692b376ee
					
				
					 10 changed files with 93 additions and 188 deletions
				
			
		| 
						 | 
					@ -18,7 +18,7 @@
 | 
				
			||||||
- python3-crypto to enable End to end encryption
 | 
					- python3-crypto to enable End to end encryption
 | 
				
			||||||
- python3-gnupg to enable GPG encryption
 | 
					- python3-gnupg to enable GPG encryption
 | 
				
			||||||
- For zeroconf (bonjour) you need dbus-glib, python-avahi
 | 
					- For zeroconf (bonjour) you need dbus-glib, python-avahi
 | 
				
			||||||
- gir1.2-gtkspell3-3.0 and aspell-LANG where lang is your locale eg. en, fr etc
 | 
					- gir1.2-gspell-1 and hunspell-LANG where lang is your locale eg. en, fr etc
 | 
				
			||||||
- gir1.2-secret-1 for GNOME Keyring or KDE support as password storage
 | 
					- gir1.2-secret-1 for GNOME Keyring or KDE support as password storage
 | 
				
			||||||
- D-Bus running to have gajim-remote working. Some distributions split dbus-x11, which is needed for dbus to work with Gajim. Version >= 0.80 is required.
 | 
					- D-Bus running to have gajim-remote working. Some distributions split dbus-x11, which is needed for dbus to work with Gajim. Version >= 0.80 is required.
 | 
				
			||||||
- python3-dbus bindings (>=1.2.0)
 | 
					- python3-dbus bindings (>=1.2.0)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1173,7 +1173,6 @@ class ChatControl(ChatControlBase):
 | 
				
			||||||
                self.handlers[i].disconnect(i)
 | 
					                self.handlers[i].disconnect(i)
 | 
				
			||||||
            del self.handlers[i]
 | 
					            del self.handlers[i]
 | 
				
			||||||
        self.conv_textview.del_handlers()
 | 
					        self.conv_textview.del_handlers()
 | 
				
			||||||
        self.remove_speller()
 | 
					 | 
				
			||||||
        self.msg_textview.destroy()
 | 
					        self.msg_textview.destroy()
 | 
				
			||||||
        # PluginSystem: calling shutdown of super class (ChatControlBase) to let
 | 
					        # PluginSystem: calling shutdown of super class (ChatControlBase) to let
 | 
				
			||||||
        # it remove it's GUI extension points
 | 
					        # it remove it's GUI extension points
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,7 +32,6 @@ import time
 | 
				
			||||||
from gi.repository import Gtk
 | 
					from gi.repository import Gtk
 | 
				
			||||||
from gi.repository import Gdk
 | 
					from gi.repository import Gdk
 | 
				
			||||||
from gi.repository import Pango
 | 
					from gi.repository import Pango
 | 
				
			||||||
from gi.repository import GObject
 | 
					 | 
				
			||||||
from gi.repository import GLib
 | 
					from gi.repository import GLib
 | 
				
			||||||
from gi.repository import Gio
 | 
					from gi.repository import Gio
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,7 +41,6 @@ from gajim import message_control
 | 
				
			||||||
from gajim import dialogs
 | 
					from gajim import dialogs
 | 
				
			||||||
from gajim import history_window
 | 
					from gajim import history_window
 | 
				
			||||||
from gajim import notify
 | 
					from gajim import notify
 | 
				
			||||||
from gajim import gtkspell
 | 
					 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from gajim import emoticons
 | 
					from gajim import emoticons
 | 
				
			||||||
| 
						 | 
					@ -66,6 +64,9 @@ from gajim.command_system.implementation.middleware import CommandTools
 | 
				
			||||||
from gajim.command_system.implementation import standard
 | 
					from gajim.command_system.implementation import standard
 | 
				
			||||||
from gajim.command_system.implementation import execute
 | 
					from gajim.command_system.implementation import execute
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if app.HAVE_SPELL:
 | 
				
			||||||
 | 
					    from gi.repository import Gspell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
################################################################################
 | 
					################################################################################
 | 
				
			||||||
class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
 | 
					class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
 | 
				
			||||||
| 
						 | 
					@ -345,8 +346,7 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
 | 
				
			||||||
        self.set_emoticon_popover()
 | 
					        self.set_emoticon_popover()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Attach speller
 | 
					        # Attach speller
 | 
				
			||||||
        self.spell = None
 | 
					        self.spell_checker = None
 | 
				
			||||||
        self.spell_handlers = []
 | 
					 | 
				
			||||||
        self.set_speller()
 | 
					        self.set_speller()
 | 
				
			||||||
        self.conv_textview.tv.show()
 | 
					        self.conv_textview.tv.show()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -471,44 +471,22 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
 | 
				
			||||||
        image.set_from_pixbuf(icon)
 | 
					        image.set_from_pixbuf(icon)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_speller(self):
 | 
					    def set_speller(self):
 | 
				
			||||||
        if not gtkspell.HAS_GTK_SPELL or not app.config.get('use_speller'):
 | 
					        if not app.HAVE_SPELL or not app.config.get('use_speller'):
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def _on_focus_in(*args):
 | 
					        gspell_lang = self.get_speller_language()
 | 
				
			||||||
            if self.spell is None:
 | 
					        if gspell_lang 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
 | 
					            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):
 | 
					        self.spell_checker = Gspell.Checker.new(gspell_lang)
 | 
				
			||||||
        if self.spell is None:
 | 
					        spell_buffer = Gspell.TextBuffer.get_from_gtk_text_buffer(
 | 
				
			||||||
            return
 | 
					            self.msg_textview.get_buffer())
 | 
				
			||||||
        self.spell.detach()
 | 
					        spell_buffer.set_spell_checker(self.spell_checker)
 | 
				
			||||||
        for id_ in self.spell_handlers:
 | 
					        spell_view = Gspell.TextView.get_from_gtk_text_view(self.msg_textview)
 | 
				
			||||||
            self.msg_textview.disconnect(id_)
 | 
					        spell_view.set_inline_spell_checking(False)
 | 
				
			||||||
            self.spell_handlers.remove(id_)
 | 
					        spell_view.set_enable_language_menu(True)
 | 
				
			||||||
        self.spell = None
 | 
					
 | 
				
			||||||
 | 
					        self.spell_checker.connect('notify::language', self.on_language_changed)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_speller_language(self):
 | 
					    def get_speller_language(self):
 | 
				
			||||||
        per_type = 'contacts'
 | 
					        per_type = 'contacts'
 | 
				
			||||||
| 
						 | 
					@ -521,16 +499,20 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
 | 
				
			||||||
            lang = app.config.get('speller_language')
 | 
					            lang = app.config.get('speller_language')
 | 
				
			||||||
            if not lang:
 | 
					            if not lang:
 | 
				
			||||||
                lang = app.LANG
 | 
					                lang = app.LANG
 | 
				
			||||||
        return lang or None
 | 
					        gspell_lang = Gspell.language_lookup(lang)
 | 
				
			||||||
 | 
					        if gspell_lang is None:
 | 
				
			||||||
 | 
					            gspell_lang = Gspell.language_get_default()
 | 
				
			||||||
 | 
					        return gspell_lang
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def on_language_changed(self, spell, lang):
 | 
					    def on_language_changed(self, checker, param):
 | 
				
			||||||
 | 
					        gspell_lang = checker.get_language()
 | 
				
			||||||
        per_type = 'contacts'
 | 
					        per_type = 'contacts'
 | 
				
			||||||
        if self.type_id == message_control.TYPE_GC:
 | 
					        if self.type_id == message_control.TYPE_GC:
 | 
				
			||||||
            per_type = 'rooms'
 | 
					            per_type = 'rooms'
 | 
				
			||||||
        if not app.config.get_per(per_type, self.contact.jid):
 | 
					        if not app.config.get_per(per_type, self.contact.jid):
 | 
				
			||||||
            app.config.add_per(per_type, self.contact.jid)
 | 
					            app.config.add_per(per_type, self.contact.jid)
 | 
				
			||||||
        app.config.set_per(
 | 
					        app.config.set_per(per_type, self.contact.jid,
 | 
				
			||||||
            per_type, self.contact.jid, 'speller_language', lang)
 | 
					                           'speller_language', gspell_lang.get_code())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def on_banner_label_populate_popup(self, label, menu):
 | 
					    def on_banner_label_populate_popup(self, label, menu):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -253,6 +253,21 @@ except Exception:
 | 
				
			||||||
    glog.info(_('Unable to load idle module'))
 | 
					    glog.info(_('Unable to load idle module'))
 | 
				
			||||||
    HAVE_IDLE = False
 | 
					    HAVE_IDLE = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					HAVE_SPELL = False
 | 
				
			||||||
 | 
					try:
 | 
				
			||||||
 | 
					    spell_log = logging.getLogger('gajim.speller')
 | 
				
			||||||
 | 
					    gi.require_version('Gspell', '1')
 | 
				
			||||||
 | 
					    from gi.repository import Gspell
 | 
				
			||||||
 | 
					    langs = Gspell.language_get_available()
 | 
				
			||||||
 | 
					    for lang in langs:
 | 
				
			||||||
 | 
					        spell_log.info('%s (%s) dict available',
 | 
				
			||||||
 | 
					                       lang.get_name(), lang.get_code())
 | 
				
			||||||
 | 
					    if langs:
 | 
				
			||||||
 | 
					        HAVE_SPELL = True
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        spell_log.info('No dicts available')
 | 
				
			||||||
 | 
					except ImportError:
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gajim_identity = {'type': 'pc', 'category': 'client', 'name': 'Gajim'}
 | 
					gajim_identity = {'type': 'pc', 'category': 'client', 'name': 'Gajim'}
 | 
				
			||||||
gajim_common_features = [nbxmpp.NS_BYTESTREAM, nbxmpp.NS_SI, nbxmpp.NS_FILE,
 | 
					gajim_common_features = [nbxmpp.NS_BYTESTREAM, nbxmpp.NS_SI, nbxmpp.NS_FILE,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,7 +50,6 @@ from gajim import message_control
 | 
				
			||||||
from gajim.chat_control_base import ChatControlBase
 | 
					from gajim.chat_control_base import ChatControlBase
 | 
				
			||||||
from gajim import dataforms_widget
 | 
					from gajim import dataforms_widget
 | 
				
			||||||
from gajim import gui_menu_builder
 | 
					from gajim import gui_menu_builder
 | 
				
			||||||
from gajim import gtkspell
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
from gajim.common import helpers
 | 
					from gajim.common import helpers
 | 
				
			||||||
from gajim.common import app
 | 
					from gajim.common import app
 | 
				
			||||||
| 
						 | 
					@ -66,6 +65,9 @@ try:
 | 
				
			||||||
except (ImportError, ValueError):
 | 
					except (ImportError, ValueError):
 | 
				
			||||||
    HAS_GST = False
 | 
					    HAS_GST = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if app.HAVE_SPELL:
 | 
				
			||||||
 | 
					    from gi.repository import Gspell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#---------- PreferencesWindow class -------------#
 | 
					#---------- PreferencesWindow class -------------#
 | 
				
			||||||
class PreferencesWindow:
 | 
					class PreferencesWindow:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
| 
						 | 
					@ -187,7 +189,7 @@ class PreferencesWindow:
 | 
				
			||||||
        self.xml.get_object('xhtml_checkbutton').set_active(st)
 | 
					        self.xml.get_object('xhtml_checkbutton').set_active(st)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # use speller
 | 
					        # use speller
 | 
				
			||||||
        if gtkspell.HAS_GTK_SPELL:
 | 
					        if app.HAVE_SPELL:
 | 
				
			||||||
            st = app.config.get('use_speller')
 | 
					            st = app.config.get('use_speller')
 | 
				
			||||||
            self.xml.get_object('speller_checkbutton').set_active(st)
 | 
					            self.xml.get_object('speller_checkbutton').set_active(st)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
| 
						 | 
					@ -657,30 +659,22 @@ class PreferencesWindow:
 | 
				
			||||||
            if isinstance(ctrl, ChatControlBase):
 | 
					            if isinstance(ctrl, ChatControlBase):
 | 
				
			||||||
                ctrl.set_speller()
 | 
					                ctrl.set_speller()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def remove_speller(self):
 | 
					 | 
				
			||||||
        for ctrl in self._get_all_controls():
 | 
					 | 
				
			||||||
            if isinstance(ctrl, ChatControlBase):
 | 
					 | 
				
			||||||
                if ctrl.spell is not None:
 | 
					 | 
				
			||||||
                    ctrl.remove_speller()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def on_speller_checkbutton_toggled(self, widget):
 | 
					    def on_speller_checkbutton_toggled(self, widget):
 | 
				
			||||||
        active = widget.get_active()
 | 
					        active = widget.get_active()
 | 
				
			||||||
        app.config.set('use_speller', active)
 | 
					        app.config.set('use_speller', active)
 | 
				
			||||||
        if active:
 | 
					        if not active:
 | 
				
			||||||
            lang = app.config.get('speller_language')
 | 
					            return
 | 
				
			||||||
            if not lang:
 | 
					        lang = app.config.get('speller_language')
 | 
				
			||||||
                lang = app.LANG
 | 
					        gspell_lang = Gspell.language_lookup(lang)
 | 
				
			||||||
 | 
					        if gspell_lang is None:
 | 
				
			||||||
            available = gtkspell.test_language(lang)
 | 
					            gspell_lang = Gspell.language_get_default()
 | 
				
			||||||
            if not available:
 | 
					        if gspell_lang is None:
 | 
				
			||||||
                dialogs.AspellDictError(lang)
 | 
					            dialogs.AspellDictError(lang)
 | 
				
			||||||
                app.config.set('use_speller', False)
 | 
					            app.config.set('use_speller', False)
 | 
				
			||||||
                widget.set_active(False)
 | 
					            widget.set_active(False)
 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                app.config.set('speller_language', lang)
 | 
					 | 
				
			||||||
                self.apply_speller()
 | 
					 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self.remove_speller()
 | 
					            app.config.set('speller_language', gspell_lang.get_code())
 | 
				
			||||||
 | 
					            self.apply_speller()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def on_positive_184_ack_checkbutton_toggled(self, widget):
 | 
					    def on_positive_184_ack_checkbutton_toggled(self, widget):
 | 
				
			||||||
        self.on_checkbutton_toggled(widget, 'positive_184_ack')
 | 
					        self.on_checkbutton_toggled(widget, 'positive_184_ack')
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,6 +34,7 @@ from gi.repository import Gdk
 | 
				
			||||||
from gi.repository import GdkPixbuf
 | 
					from gi.repository import GdkPixbuf
 | 
				
			||||||
from gi.repository import GObject
 | 
					from gi.repository import GObject
 | 
				
			||||||
from gi.repository import GLib
 | 
					from gi.repository import GLib
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import nbxmpp
 | 
					import nbxmpp
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
| 
						 | 
					@ -42,7 +43,6 @@ from gajim import gtkgui_helpers
 | 
				
			||||||
from gajim import vcard
 | 
					from gajim import vcard
 | 
				
			||||||
from gajim import conversation_textview
 | 
					from gajim import conversation_textview
 | 
				
			||||||
from gajim import dataforms_widget
 | 
					from gajim import dataforms_widget
 | 
				
			||||||
from gajim import gtkspell
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
from random import randrange
 | 
					from random import randrange
 | 
				
			||||||
from gajim.common import pep
 | 
					from gajim.common import pep
 | 
				
			||||||
| 
						 | 
					@ -64,6 +64,9 @@ from gajim.common import dataforms
 | 
				
			||||||
from gajim.common.exceptions import GajimGeneralException
 | 
					from gajim.common.exceptions import GajimGeneralException
 | 
				
			||||||
from gajim.common.connection_handlers_events import MessageOutgoingEvent
 | 
					from gajim.common.connection_handlers_events import MessageOutgoingEvent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if app.HAVE_SPELL:
 | 
				
			||||||
 | 
					    from gi.repository import Gspell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
log = logging.getLogger('gajim.dialogs')
 | 
					log = logging.getLogger('gajim.dialogs')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3077,15 +3080,19 @@ class SingleMessageWindow:
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self.to_entry.set_text(to)
 | 
					            self.to_entry.set_text(to)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if app.config.get('use_speller') and gtkspell.HAS_GTK_SPELL and action == 'send':
 | 
					        if app.config.get('use_speller') and app.HAVE_SPELL and action == 'send':
 | 
				
			||||||
            try:
 | 
					            lang = app.config.get('speller_language')
 | 
				
			||||||
                lang = app.config.get('speller_language')
 | 
					            gspell_lang = Gspell.language_lookup(lang)
 | 
				
			||||||
                if not lang:
 | 
					            if gspell_lang is None:
 | 
				
			||||||
                    lang = app.LANG
 | 
					 | 
				
			||||||
                self.spell = gtkspell.Spell(self.message_textview, lang)
 | 
					 | 
				
			||||||
                self.spell.attach(self.message_textview)
 | 
					 | 
				
			||||||
            except OSError:
 | 
					 | 
				
			||||||
                AspellDictError(lang)
 | 
					                AspellDictError(lang)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                spell_buffer = Gspell.TextBuffer.get_from_gtk_text_buffer(
 | 
				
			||||||
 | 
					                    self.message_textview.get_buffer())
 | 
				
			||||||
 | 
					                spell_buffer.set_spell_checker(Gspell.Checker.new(gspell_lang))
 | 
				
			||||||
 | 
					                spell_view = Gspell.TextView.get_from_gtk_text_view(
 | 
				
			||||||
 | 
					                    self.message_textview)
 | 
				
			||||||
 | 
					                spell_view.set_inline_spell_checking(True)
 | 
				
			||||||
 | 
					                spell_view.set_enable_language_menu(True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.prepare_widgets_for(self.action)
 | 
					        self.prepare_widgets_for(self.action)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,8 +63,8 @@ class FeaturesWindow:
 | 
				
			||||||
                _('On Windows the Windows Credential Vault is used.')),
 | 
					                _('On Windows the Windows Credential Vault is used.')),
 | 
				
			||||||
            _('Spell Checker'): (self.speller_available,
 | 
					            _('Spell Checker'): (self.speller_available,
 | 
				
			||||||
                _('Spellchecking of composed messages.'),
 | 
					                _('Spellchecking of composed messages.'),
 | 
				
			||||||
                _('Requires libgtkspell.'),
 | 
					                _('Requires Gspell'),
 | 
				
			||||||
                _('Requires libgtkspell and libenchant.')),
 | 
					                _('Requires Gspell')),
 | 
				
			||||||
            _('Automatic status'): (self.idle_available,
 | 
					            _('Automatic status'): (self.idle_available,
 | 
				
			||||||
                _('Ability to measure idle time, in order to set auto status.'),
 | 
					                _('Ability to measure idle time, in order to set auto status.'),
 | 
				
			||||||
                _('Requires libxss library.'),
 | 
					                _('Requires libxss library.'),
 | 
				
			||||||
| 
						 | 
					@ -164,11 +164,7 @@ class FeaturesWindow:
 | 
				
			||||||
        return True
 | 
					        return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def speller_available(self):
 | 
					    def speller_available(self):
 | 
				
			||||||
        try:
 | 
					        return app.HAVE_SPELL
 | 
				
			||||||
            __import__('gajim.gtkspell')
 | 
					 | 
				
			||||||
        except ValueError:
 | 
					 | 
				
			||||||
            return False
 | 
					 | 
				
			||||||
        return True
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def idle_available(self):
 | 
					    def idle_available(self):
 | 
				
			||||||
        from gajim.common import sleepy
 | 
					        from gajim.common import sleepy
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,104 +0,0 @@
 | 
				
			||||||
## src/gtkspell.py
 | 
					 | 
				
			||||||
##
 | 
					 | 
				
			||||||
## (C) 2008 Thorsten P. 'dGhvcnN0ZW5wIEFUIHltYWlsIGNvbQ==\n'.decode("base64")
 | 
					 | 
				
			||||||
## (C) 2015 Yann Leboulanger <asterix AT lagaule.org>
 | 
					 | 
				
			||||||
##
 | 
					 | 
				
			||||||
## This file is part of Gajim.
 | 
					 | 
				
			||||||
##
 | 
					 | 
				
			||||||
## Gajim is free software; you can redistribute it and/or modify
 | 
					 | 
				
			||||||
## it under the terms of the GNU General Public License as published
 | 
					 | 
				
			||||||
## by the Free Software Foundation; version 3 only.
 | 
					 | 
				
			||||||
##
 | 
					 | 
				
			||||||
## Gajim is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
					 | 
				
			||||||
## GNU General Public License for more details.
 | 
					 | 
				
			||||||
##
 | 
					 | 
				
			||||||
## You should have received a copy of the GNU General Public License
 | 
					 | 
				
			||||||
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from gi.repository import GObject
 | 
					 | 
				
			||||||
from gi.repository import Gtk
 | 
					 | 
				
			||||||
from gi.repository import GLib
 | 
					 | 
				
			||||||
import gi
 | 
					 | 
				
			||||||
try:
 | 
					 | 
				
			||||||
    gi.require_version('GtkSpell', '3.0')
 | 
					 | 
				
			||||||
    from gi.repository import GtkSpell
 | 
					 | 
				
			||||||
    HAS_GTK_SPELL = True
 | 
					 | 
				
			||||||
except (ImportError, ValueError):
 | 
					 | 
				
			||||||
    HAS_GTK_SPELL = False
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def ensure_attached(func):
 | 
					 | 
				
			||||||
    def f(self, *args, **kwargs):
 | 
					 | 
				
			||||||
        if self.spell:
 | 
					 | 
				
			||||||
            func(self, *args, **kwargs)
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            raise RuntimeError("Spell object is already detached")
 | 
					 | 
				
			||||||
    return f
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Spell(GObject.GObject):
 | 
					 | 
				
			||||||
    __gsignals__ = {
 | 
					 | 
				
			||||||
        'language_changed': (GObject.SignalFlags.RUN_FIRST, None, (str,))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __init__(self, textview, language=None, create=True, jid=None,
 | 
					 | 
				
			||||||
    per_type=None):
 | 
					 | 
				
			||||||
        GObject.GObject.__init__(self)
 | 
					 | 
				
			||||||
        if not isinstance(textview, Gtk.TextView):
 | 
					 | 
				
			||||||
            raise TypeError("Textview must be derived from Gtk.TextView")
 | 
					 | 
				
			||||||
        spell = GtkSpell.Checker.get_from_text_view(textview)
 | 
					 | 
				
			||||||
        if create:
 | 
					 | 
				
			||||||
            if spell:
 | 
					 | 
				
			||||||
                raise RuntimeError("Textview has already a Spell obj attached")
 | 
					 | 
				
			||||||
            self.spell = GtkSpell.Checker.new()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            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:
 | 
					 | 
				
			||||||
            if spell:
 | 
					 | 
				
			||||||
                self.spell = spell
 | 
					 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                raise RuntimeError("Textview has no Spell object attached")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def on_language_changed(self, spell, lang):
 | 
					 | 
				
			||||||
        self.emit('language_changed', lang)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @ensure_attached
 | 
					 | 
				
			||||||
    def set_language(self, language):
 | 
					 | 
				
			||||||
        if not self.spell.set_language(language):
 | 
					 | 
				
			||||||
            raise OSError("Unable to set language: '%s'" % language)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @ensure_attached
 | 
					 | 
				
			||||||
    def recheck_all(self):
 | 
					 | 
				
			||||||
        self.spell.recheck_all()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def detach(self):
 | 
					 | 
				
			||||||
        if self.spell is not None:
 | 
					 | 
				
			||||||
            self.spell.detach()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    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 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
 | 
					 | 
				
			||||||
| 
						 | 
					@ -30,6 +30,10 @@ from gi.repository import Pango
 | 
				
			||||||
from gajim.common import app
 | 
					from gajim.common import app
 | 
				
			||||||
from gajim import gtkgui_helpers
 | 
					from gajim import gtkgui_helpers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if app.HAVE_SPELL:
 | 
				
			||||||
 | 
					    from gi.repository import Gspell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MessageTextView(Gtk.TextView):
 | 
					class MessageTextView(Gtk.TextView):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Class for the message textview (where user writes new messages) for
 | 
					    Class for the message textview (where user writes new messages) for
 | 
				
			||||||
| 
						 | 
					@ -101,6 +105,7 @@ class MessageTextView(Gtk.TextView):
 | 
				
			||||||
    def _on_focus_in(self, *args):
 | 
					    def _on_focus_in(self, *args):
 | 
				
			||||||
        if not self.has_text():
 | 
					        if not self.has_text():
 | 
				
			||||||
            self.get_buffer().set_text('')
 | 
					            self.get_buffer().set_text('')
 | 
				
			||||||
 | 
					        self.toggle_speller(True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _on_focus_out(self, *args):
 | 
					    def _on_focus_out(self, *args):
 | 
				
			||||||
        buf = self.get_buffer()
 | 
					        buf = self.get_buffer()
 | 
				
			||||||
| 
						 | 
					@ -109,6 +114,12 @@ class MessageTextView(Gtk.TextView):
 | 
				
			||||||
        if text == '':
 | 
					        if text == '':
 | 
				
			||||||
            buf.insert_with_tags(
 | 
					            buf.insert_with_tags(
 | 
				
			||||||
                start, self.PLACEHOLDER, self.placeholder_tag)
 | 
					                start, self.PLACEHOLDER, self.placeholder_tag)
 | 
				
			||||||
 | 
					            self.toggle_speller(False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def toggle_speller(self, activate):
 | 
				
			||||||
 | 
					        if app.HAVE_SPELL and app.config.get('use_speller'):
 | 
				
			||||||
 | 
					            spell_view = Gspell.TextView.get_from_gtk_text_view(self)
 | 
				
			||||||
 | 
					            spell_view.set_inline_spell_checking(activate)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def remove_placeholder(self):
 | 
					    def remove_placeholder(self):
 | 
				
			||||||
        self._on_focus_in()
 | 
					        self._on_focus_in()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,7 +75,9 @@ function install_deps {
 | 
				
			||||||
        mingw-w64-"${ARCH}"-adwaita-icon-theme \
 | 
					        mingw-w64-"${ARCH}"-adwaita-icon-theme \
 | 
				
			||||||
        mingw-w64-"${ARCH}"-libwebp \
 | 
					        mingw-w64-"${ARCH}"-libwebp \
 | 
				
			||||||
        mingw-w64-"${ARCH}"-sqlite3 \
 | 
					        mingw-w64-"${ARCH}"-sqlite3 \
 | 
				
			||||||
        mingw-w64-"${ARCH}"-goocanvas
 | 
					        mingw-w64-"${ARCH}"-goocanvas \
 | 
				
			||||||
 | 
					        mingw-w64-"${ARCH}"-gspell \
 | 
				
			||||||
 | 
					        mingw-w64-"${ARCH}"-hunspell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    build_pip install setuptools_scm
 | 
					    build_pip install setuptools_scm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -136,6 +138,10 @@ function install_gajim {
 | 
				
			||||||
    mkdir "${PACKAGE_DIR}"/gajim/data/plugins
 | 
					    mkdir "${PACKAGE_DIR}"/gajim/data/plugins
 | 
				
			||||||
    7z x -o"${PACKAGE_DIR}"/gajim/data/plugins "${BUILD_ROOT}"/plugin_installer.zip
 | 
					    7z x -o"${PACKAGE_DIR}"/gajim/data/plugins "${BUILD_ROOT}"/plugin_installer.zip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Install language dicts
 | 
				
			||||||
 | 
					    curl -o "${BUILD_ROOT}"/speller_dicts.zip https://gajim.org/downloads/snap/win/build/speller_dicts.zip
 | 
				
			||||||
 | 
					    7z x -o"${MINGW_ROOT}"/share "${BUILD_ROOT}"/speller_dicts.zip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Install themes
 | 
					    # Install themes
 | 
				
			||||||
    # rm -Rf "${MINGW_ROOT}"/etc
 | 
					    # rm -Rf "${MINGW_ROOT}"/etc
 | 
				
			||||||
    # rm -Rf "${MINGW_ROOT}"/share/themes
 | 
					    # rm -Rf "${MINGW_ROOT}"/share/themes
 | 
				
			||||||
| 
						 | 
					@ -194,7 +200,6 @@ function cleanup_install {
 | 
				
			||||||
    rm -Rf "${MINGW_ROOT}"/share/ffmpeg
 | 
					    rm -Rf "${MINGW_ROOT}"/share/ffmpeg
 | 
				
			||||||
    rm -Rf "${MINGW_ROOT}"/share/vala
 | 
					    rm -Rf "${MINGW_ROOT}"/share/vala
 | 
				
			||||||
    rm -Rf "${MINGW_ROOT}"/share/readline
 | 
					    rm -Rf "${MINGW_ROOT}"/share/readline
 | 
				
			||||||
    rm -Rf "${MINGW_ROOT}"/share/xml
 | 
					 | 
				
			||||||
    rm -Rf "${MINGW_ROOT}"/share/bash-completion
 | 
					    rm -Rf "${MINGW_ROOT}"/share/bash-completion
 | 
				
			||||||
    rm -Rf "${MINGW_ROOT}"/share/common-lisp
 | 
					    rm -Rf "${MINGW_ROOT}"/share/common-lisp
 | 
				
			||||||
    rm -Rf "${MINGW_ROOT}"/share/emacs
 | 
					    rm -Rf "${MINGW_ROOT}"/share/emacs
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue