Commit 5780c03d authored by Martin's avatar Martin

Merge tag 'upstream/0.16.11.git20171126' into debian/experimental

parents 60d74b78 4f12af26
......@@ -18,7 +18,7 @@
- python3-crypto to enable End to end encryption
- python3-gnupg to enable GPG encryption
- 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
- 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)
......
......@@ -1173,7 +1173,6 @@ class ChatControl(ChatControlBase):
self.handlers[i].disconnect(i)
del self.handlers[i]
self.conv_textview.del_handlers()
self.remove_speller()
self.msg_textview.destroy()
# PluginSystem: calling shutdown of super class (ChatControlBase) to let
# it remove it's GUI extension points
......
......@@ -32,7 +32,6 @@ import time
from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import Pango
from gi.repository import GObject
from gi.repository import GLib
from gi.repository import Gio
......@@ -42,7 +41,6 @@ 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
......@@ -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 execute
if app.HAVE_SPELL:
from gi.repository import Gspell
################################################################################
class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
......@@ -345,8 +346,7 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
self.set_emoticon_popover()
# Attach speller
self.spell = None
self.spell_handlers = []
self.spell_checker = None
self.set_speller()
self.conv_textview.tv.show()
......@@ -471,44 +471,22 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
image.set_from_pixbuf(icon)
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
def _on_focus_in(*args):
if self.spell is None:
return
self.spell.attach(self.msg_textview)
gspell_lang = self.get_speller_language()
if gspell_lang is None:
return
def _on_focus_out(*args):
if self.spell is None:
return
if not self.msg_textview.has_text():
self.spell.detach()
self.spell_checker = Gspell.Checker.new(gspell_lang)
spell_buffer = Gspell.TextBuffer.get_from_gtk_text_buffer(
self.msg_textview.get_buffer())
spell_buffer.set_spell_checker(self.spell_checker)
spell_view = Gspell.TextView.get_from_gtk_text_view(self.msg_textview)
spell_view.set_inline_spell_checking(False)
spell_view.set_enable_language_menu(True)
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
self.spell_checker.connect('notify::language', self.on_language_changed)
def get_speller_language(self):
per_type = 'contacts'
......@@ -521,16 +499,20 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
lang = app.config.get('speller_language')
if not 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'
if self.type_id == message_control.TYPE_GC:
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)
app.config.set_per(per_type, self.contact.jid,
'speller_language', gspell_lang.get_code())
def on_banner_label_populate_popup(self, label, menu):
"""
......
......@@ -253,6 +253,21 @@ except Exception:
glog.info(_('Unable to load idle module'))
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, ValueError):
pass
gajim_identity = {'type': 'pc', 'category': 'client', 'name': 'Gajim'}
gajim_common_features = [nbxmpp.NS_BYTESTREAM, nbxmpp.NS_SI, nbxmpp.NS_FILE,
......
......@@ -474,7 +474,7 @@ class ConnectionVcard:
app.nec.push_incoming_event(
VcardNotPublishedEvent(None, conn=self))
def get_vcard_photo(self, vcard):
def _get_vcard_photo(self, vcard, jid):
try:
photo = vcard['PHOTO']['BINVAL']
except (KeyError, AttributeError):
......@@ -488,7 +488,7 @@ class ConnectionVcard:
try:
photo_decoded = base64.b64decode(photo.encode('utf-8'))
except binascii.Error as error:
app.log('avatar').warning('Invalid Avatar: %s', error)
app.log('avatar').warning('Invalid avatar for %s: %s', jid, error)
return None, None
avatar_sha = hashlib.sha1(photo_decoded).hexdigest()
......@@ -532,7 +532,7 @@ class ConnectionVcard:
def _on_own_avatar_received(self, jid, resource, room, vcard):
avatar_sha, photo_decoded = self.get_vcard_photo(vcard)
avatar_sha, photo_decoded = self._get_vcard_photo(vcard, jid)
app.log('avatar').info(
'Received own (vCard): %s', avatar_sha)
......@@ -570,7 +570,7 @@ class ConnectionVcard:
"""
Called when we receive a vCard Parse the vCard and trigger Events
"""
avatar_sha, photo_decoded = self.get_vcard_photo(vcard)
avatar_sha, photo_decoded = self._get_vcard_photo(vcard, jid)
app.interface.save_avatar(photo_decoded)
# Received vCard from a contact
......
......@@ -50,7 +50,6 @@ from gajim import message_control
from gajim.chat_control_base import ChatControlBase
from gajim import dataforms_widget
from gajim import gui_menu_builder
from gajim import gtkspell
from gajim.common import helpers
from gajim.common import app
......@@ -66,6 +65,9 @@ try:
except (ImportError, ValueError):
HAS_GST = False
if app.HAVE_SPELL:
from gi.repository import Gspell
#---------- PreferencesWindow class -------------#
class PreferencesWindow:
"""
......@@ -187,7 +189,7 @@ class PreferencesWindow:
self.xml.get_object('xhtml_checkbutton').set_active(st)
# use speller
if gtkspell.HAS_GTK_SPELL:
if app.HAVE_SPELL:
st = app.config.get('use_speller')
self.xml.get_object('speller_checkbutton').set_active(st)
else:
......@@ -657,30 +659,22 @@ class PreferencesWindow:
if isinstance(ctrl, ChatControlBase):
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):
active = widget.get_active()
app.config.set('use_speller', active)
if active:
lang = app.config.get('speller_language')
if not lang:
lang = app.LANG
available = gtkspell.test_language(lang)
if not available:
dialogs.AspellDictError(lang)
app.config.set('use_speller', False)
widget.set_active(False)
else:
app.config.set('speller_language', lang)
self.apply_speller()
if not active:
return
lang = app.config.get('speller_language')
gspell_lang = Gspell.language_lookup(lang)
if gspell_lang is None:
gspell_lang = Gspell.language_get_default()
if gspell_lang is None:
dialogs.AspellDictError(lang)
app.config.set('use_speller', False)
widget.set_active(False)
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):
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 GObject
from gi.repository import GLib
import os
import nbxmpp
import time
......@@ -42,7 +43,6 @@ 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
......@@ -64,6 +64,9 @@ from gajim.common import dataforms
from gajim.common.exceptions import GajimGeneralException
from gajim.common.connection_handlers_events import MessageOutgoingEvent
if app.HAVE_SPELL:
from gi.repository import Gspell
import logging
log = logging.getLogger('gajim.dialogs')
......@@ -3077,15 +3080,19 @@ class SingleMessageWindow:
else:
self.to_entry.set_text(to)
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
self.spell = gtkspell.Spell(self.message_textview, lang)
self.spell.attach(self.message_textview)
except OSError:
if app.config.get('use_speller') and app.HAVE_SPELL and action == 'send':
lang = app.config.get('speller_language')
gspell_lang = Gspell.language_lookup(lang)
if gspell_lang is None:
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)
......
......@@ -63,8 +63,8 @@ class FeaturesWindow:
_('On Windows the Windows Credential Vault is used.')),
_('Spell Checker'): (self.speller_available,
_('Spellchecking of composed messages.'),
_('Requires libgtkspell.'),
_('Requires libgtkspell and libenchant.')),
_('Requires Gspell'),
_('Requires Gspell')),
_('Automatic status'): (self.idle_available,
_('Ability to measure idle time, in order to set auto status.'),
_('Requires libxss library.'),
......@@ -164,11 +164,7 @@ class FeaturesWindow:
return True
def speller_available(self):
try:
__import__('gajim.gtkspell')
except ValueError:
return False
return True
return app.HAVE_SPELL
def idle_available(self):
from gajim.common import sleepy
......
## 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 import gtkgui_helpers
if app.HAVE_SPELL:
from gi.repository import Gspell
class MessageTextView(Gtk.TextView):
"""
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):
if not self.has_text():
self.get_buffer().set_text('')
self.toggle_speller(True)
def _on_focus_out(self, *args):
buf = self.get_buffer()
......@@ -109,6 +114,12 @@ class MessageTextView(Gtk.TextView):
if text == '':
buf.insert_with_tags(
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):
self._on_focus_in()
......
......@@ -202,7 +202,7 @@ class VcardWindow:
except AttributeError:
pass
def set_values(self, vcard):
def _set_values(self, vcard, jid):
for i in vcard.keys():
if i == 'PHOTO' and self.xml.get_object('information_notebook').\
get_n_pages() > 4:
......@@ -215,7 +215,7 @@ class VcardWindow:
photo_decoded = base64.b64decode(
photo_encoded.encode('utf-8'))
except binascii.Error as error:
app.log('avatar').warning('Invalid Avatar: %s', error)
app.log('avatar').warning('Invalid avatar for %s: %s', jid, error)
continue
pixbuf = gtkgui_helpers.get_pixbuf_from_data(photo_decoded)
if pixbuf is None:
......@@ -266,7 +266,7 @@ class VcardWindow:
def _nec_vcard_received(self, jid, resource, room, vcard):
self.clear_values()
self.set_values(vcard)
self._set_values(vcard, jid)
def set_os_info(self, obj):
if obj.conn.name != self.account:
......
......@@ -75,7 +75,9 @@ function install_deps {
mingw-w64-"${ARCH}"-adwaita-icon-theme \
mingw-w64-"${ARCH}"-libwebp \
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
......@@ -122,7 +124,7 @@ function install_gajim {
build_pip install .
QL_VERSION=$(MSYSTEM= build_python -c \
"import gajim; import sys; sys.stdout.write(gajim.__version__.split('-')[0])")
"import gajim; import sys; sys.stdout.write(gajim.__version__.split('+')[0])")
QL_VERSION_DESC=$(MSYSTEM= build_python -c \
"import gajim; import sys; sys.stdout.write(gajim.__version__)")
......@@ -136,6 +138,10 @@ function install_gajim {
mkdir "${PACKAGE_DIR}"/gajim/data/plugins
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
# rm -Rf "${MINGW_ROOT}"/etc
# rm -Rf "${MINGW_ROOT}"/share/themes
......@@ -194,7 +200,6 @@ function cleanup_install {
rm -Rf "${MINGW_ROOT}"/share/ffmpeg
rm -Rf "${MINGW_ROOT}"/share/vala
rm -Rf "${MINGW_ROOT}"/share/readline
rm -Rf "${MINGW_ROOT}"/share/xml
rm -Rf "${MINGW_ROOT}"/share/bash-completion
rm -Rf "${MINGW_ROOT}"/share/common-lisp
rm -Rf "${MINGW_ROOT}"/share/emacs
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment