Hello community,

here is the log from the commit of package rednotebook for openSUSE:Factory 
checked in at 2017-03-10 21:46:18
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rednotebook (Old)
 and      /work/SRC/openSUSE:Factory/.rednotebook.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rednotebook"

Fri Mar 10 21:46:18 2017 rev:41 rq:477814 version:1.15

Changes:
--------
--- /work/SRC/openSUSE:Factory/rednotebook/rednotebook.changes  2017-03-03 
17:55:41.490573231 +0100
+++ /work/SRC/openSUSE:Factory/.rednotebook.new/rednotebook.changes     
2017-03-10 21:46:18.750391598 +0100
@@ -1,0 +2,9 @@
+Fri Mar  3 20:39:34 UTC 2017 - zai...@opensuse.org
+
+- Update to version 1.15:
+  + Bundle pygtkspellcheck 4.0.5 since earlier versions contain a
+    bug (lp#1615629).
+  + Fix toggling autostart (lp#1628497).
+  + Set system tray icon name (lp#1660129).
+
+-------------------------------------------------------------------

Old:
----
  rednotebook-1.14.tar.gz

New:
----
  rednotebook-1.15.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ rednotebook.spec ++++++
--- /var/tmp/diff_new_pack.pUcxDt/_old  2017-03-10 21:46:19.594271908 +0100
+++ /var/tmp/diff_new_pack.pUcxDt/_new  2017-03-10 21:46:19.598271342 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           rednotebook
-Version:        1.14
+Version:        1.15
 Release:        0
 Summary:        Graphical diary and journal
 License:        GPL-3.0+

++++++ rednotebook-1.14.tar.gz -> rednotebook-1.15.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rednotebook-1.14/CHANGELOG 
new/rednotebook-1.15/CHANGELOG
--- old/rednotebook-1.14/CHANGELOG      2016-09-26 15:27:34.000000000 +0200
+++ new/rednotebook-1.15/CHANGELOG      2017-02-11 16:13:36.000000000 +0100
@@ -1,3 +1,8 @@
+== 1.15 (2017-02-11) ==
+* Bundle pygtkspellcheck 4.0.5 since earlier versions contain a bug 
(lp:1615629).
+* Fix toggling autostart (lp:1628497).
+* Set system tray icon name (lp:1660129).
+
 == 1.14 (2016-09-26) ==
 * Use new pygtkspellcheck API (lp:1592727).
 * Fix conversion from old single "Tags" category to new tags format.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rednotebook-1.14/PKG-INFO 
new/rednotebook-1.15/PKG-INFO
--- old/rednotebook-1.14/PKG-INFO       2016-09-26 15:27:34.000000000 +0200
+++ new/rednotebook-1.15/PKG-INFO       2017-02-11 16:13:36.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: rednotebook
-Version: 1.14
+Version: 1.15
 Summary: Graphical daily journal with calendar, templates and keyword searching
 Home-page: http://rednotebook.sourceforge.net
 Author: Jendrik Seipp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rednotebook-1.14/rednotebook/external/spellcheck.py 
new/rednotebook-1.15/rednotebook/external/spellcheck.py
--- old/rednotebook-1.14/rednotebook/external/spellcheck.py     1970-01-01 
01:00:00.000000000 +0100
+++ new/rednotebook-1.15/rednotebook/external/spellcheck.py     2017-01-20 
11:18:11.000000000 +0100
@@ -0,0 +1,658 @@
+# -*- coding:utf-8 -*-
+#
+# Copyright (C) 2012, Maximilian Köhl <linuxm...@googlemail.com>
+# Copyright (C) 2012, Carlos Jenkins <car...@jenkins.co.cr>
+#
+# This program 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, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""
+RedNotebook bundles its own copy of pygtkspellcheck, because pygtkspellcheck
+versions < 4.0 don't decode UTF-8 from GTK widgets. The earliest Ubuntu version
+with a fixed pygtkspellcheck (4.0.5) is 17.04 (see also
+https://bugs.launchpad.net/rednotebook/+bug/1615629).
+
+A simple but quite powerful spellchecking library written in pure Python for 
Gtk
+based on Enchant. It supports PyGObject as well as PyGtk for Python 2 and 3 
with
+automatic switching and binding detection. For automatic translation of the 
user
+interface it can use Gedit’s translation files.
+"""
+
+import enchant
+import gettext
+import logging
+import re
+import sys
+
+# public objects
+__all__ = ['SpellChecker', 'NoDictionariesFound', 'NoGtkBindingFound']
+
+# logger
+logger = logging.getLogger(__name__)
+
+class NoDictionariesFound(Exception):
+    """
+    There aren't any dictionaries installed on the current system so
+    spellchecking could not work in any way.
+    """
+
+class NoGtkBindingFound(Exception):
+    """
+    Could not find any loaded Gtk binding.
+    """
+
+if sys.version_info.major == 3:
+    _py3k = True
+else:
+    _py3k = False
+
+if _py3k:
+    # there is only the gi binding for Python 3
+    from gi.repository import Gtk as gtk
+    _pygobject = True
+else:
+    # find any loaded gtk binding
+    if 'gi.repository.Gtk' in sys.modules:
+        gtk = sys.modules['gi.repository.Gtk']
+        _pygobject = True
+    elif 'gtk' in sys.modules:
+        gtk = sys.modules['gtk']
+        _pygobject = False
+    else:
+        raise NoGtkBindingFound('could not find any loaded Gtk binding')
+
+# select base list class
+try:
+    from collections import UserList
+    _list = UserList
+except ImportError:
+    _list = list
+
+
+
+# select base string
+if _py3k:
+    basestring = str
+
+# map between Gedit's translation and PyGtkSpellcheck's
+_GEDIT_MAP = {'Languages' : 'Languages',
+              'Ignore All' : 'Ignore _All',
+              'Suggestions' : 'Suggestions',
+              '(no suggestions)' : '(no suggested words)',
+              'Add "{}" to Dictionary' : 'Add w_ord',
+              'Unknown' : 'Unknown'}
+
+# translation
+if gettext.find('gedit'):
+    _gedit = gettext.translation('gedit', fallback=True).gettext
+    _ = lambda message: _gedit(_GEDIT_MAP[message]).replace('_', '')
+else:
+    locale_name = 'py{}gtkspellcheck'.format(sys.version_info.major)
+    _ = gettext.translation(locale_name, fallback=True).gettext
+
+def code_to_name(code, separator='_'):
+    # Escape underscores for GTK menuitems.
+    return code.replace(separator, separator * 2)
+
+class SpellChecker(object):
+    """
+    Main spellchecking class, everything important happens here.
+
+    :param view: GtkTextView the SpellChecker should be attached to.
+    :param language: The language which should be used for spellchecking.
+        Use a combination of two letter lower-case ISO 639 language code with a
+        two letter upper-case ISO 3166 country code, for example en_US or 
de_DE.
+    :param prefix: A prefix for some internal GtkTextMarks.
+    :param collapse: Enclose suggestions in its own menu.
+    :param params: Dictionary with Enchant broker parameters that should be set
+      e.g. `enchant.myspell.dictionary.path`.
+
+    .. attribute:: languages
+
+        A list of supported languages.
+
+        .. function:: exists(language)
+
+            Checks if a language exists.
+
+            :param language: language to check
+    """
+    FILTER_WORD = 'word'
+    FILTER_LINE = 'line'
+    FILTER_TEXT = 'text'
+
+    DEFAULT_FILTERS = {FILTER_WORD : [r'[0-9.,]+'],
+                       FILTER_LINE : 
[(r'(https?|ftp|file):((//)|(\\\\))+[\w\d:'
+                                       r'#@%/;$()~_?+-=\\.&]+'),
+                                      r'[\w\d]+@[\w\d.]+'],
+                       FILTER_TEXT : []}
+
+    class _LanguageList(_list):
+        def __init__(self, *args, **kwargs):
+            if sys.version_info.major == 3:
+                super().__init__(*args, **kwargs)
+            else:
+                _list.__init__(self, *args, **kwargs)
+            self.mapping = dict(self)
+
+        @classmethod
+        def from_broker(cls, broker):
+            return cls(sorted([(language, code_to_name(language))
+                               for language in broker.list_languages()],
+                              key=lambda language: language[1]))
+
+        def exists(self, language):
+            return language in self.mapping
+
+    class _Mark():
+        def __init__(self, buffer, name, start):
+            self._buffer = buffer
+            self._name = name
+            self._mark = self._buffer.create_mark(self._name, start, True)
+
+        @property
+        def iter(self):
+            return self._buffer.get_iter_at_mark(self._mark)
+
+        @property
+        def inside_word(self):
+            return self.iter.inside_word()
+
+        @property
+        def word(self):
+            start = self.iter
+            if not start.starts_word():
+                start.backward_word_start()
+            end = self.iter
+            if end.inside_word():
+                end.forward_word_end()
+            return start, end
+
+        def move(self, location):
+            self._buffer.move_mark(self._mark, location)
+
+    def __init__(self, view, language='en', prefix='gtkspellchecker',
+                 collapse=True, params={}):
+        self._view = view
+        self.collapse = collapse
+        self._view.connect('populate-popup',
+                           lambda entry, menu:self._extend_menu(menu))
+        self._view.connect('popup-menu', self._click_move_popup)
+        self._view.connect('button-press-event', self._click_move_button)
+        self._prefix = prefix
+        self._broker = enchant.Broker()
+        for param, value in params.items(): self._broker.set_param(param, 
value)
+        self.languages = SpellChecker._LanguageList.from_broker(self._broker)
+        if self.languages.exists(language):
+            self._language = language
+        elif self.languages.exists('en'):
+            logger.warning(('no installed dictionary for language "{}", '
+                            'fallback to english'.format(language)))
+            self._language = 'en'
+        else:
+            if self.languages:
+                self._language = self.languages[0][0]
+                logger.warning(('no installed dictionary for language "{}" '
+                                'and english, fallback to first language in'
+                                'language list ("{}")').format(language,
+                                                                
self._language))
+            else:
+                logger.critical('no dictionaries found')
+                raise NoDictionariesFound()
+        self._dictionary = self._broker.request_dict(self._language)
+        self._deferred_check = False
+        self._filters = dict(SpellChecker.DEFAULT_FILTERS)
+        self._regexes = {SpellChecker.FILTER_WORD : re.compile('|'.join(
+                             self._filters[SpellChecker.FILTER_WORD])),
+                         SpellChecker.FILTER_LINE : re.compile('|'.join(
+                             self._filters[SpellChecker.FILTER_LINE])),
+                         SpellChecker.FILTER_TEXT : re.compile('|'.join(
+                             self._filters[SpellChecker.FILTER_TEXT]),
+                                                               re.MULTILINE)}
+        self._enabled = True
+        self.buffer_initialize()
+
+    @property
+    def language(self):
+        """
+        The language used for spellchecking.
+        """
+        return self._language
+
+    @language.setter
+    def language(self, language):
+        if language != self._language and self.languages.exists(language):
+            self._language = language
+            self._dictionary = self._broker.request_dict(language)
+            self.recheck()
+
+    @property
+    def enabled(self):
+        """
+        Enable or disable spellchecking.
+        """
+        return self._enabled
+
+    @enabled.setter
+    def enabled(self, enabled):
+        if enabled and not self._enabled:
+            self.enable()
+        elif not enabled and self._enabled:
+            self.disable()
+
+    def buffer_initialize(self):
+        """
+        Initialize the GtkTextBuffer associated with the GtkTextView. If you
+        have associated a new GtkTextBuffer with the GtkTextView call this
+        method.
+        """
+        if _pygobject:
+            self._misspelled = gtk.TextTag.new('{}-misspelled'\
+                                               .format(self._prefix))
+        else:
+            self._misspelled = 
gtk.TextTag('{}-misspelled'.format(self._prefix))
+        self._misspelled.set_property('underline', 4)
+        self._buffer = self._view.get_buffer()
+        self._buffer.connect('insert-text', self._before_text_insert)
+        self._buffer.connect_after('insert-text', self._after_text_insert)
+        self._buffer.connect_after('delete-range', self._range_delete)
+        self._buffer.connect_after('mark-set', self._mark_set)
+        start = self._buffer.get_bounds()[0]
+        self._marks = {'insert-start' : SpellChecker._Mark(self._buffer,
+                           '{}-insert-start'.format(self._prefix), start),
+                       'insert-end' : SpellChecker._Mark(self._buffer,
+                           '{}-insert-end'.format(self._prefix), start),
+                       'click' : SpellChecker._Mark(self._buffer,
+                           '{}-click'.format(self._prefix), start)}
+        self._table = self._buffer.get_tag_table()
+        self._table.add(self._misspelled)
+        self.ignored_tags = []
+        def tag_added(tag, *args):
+            if hasattr(tag, 'spell_check') and not getattr(tag, 'spell_check'):
+                self.ignored_tags.append(tag)
+        def tag_removed(tag, *args):
+            if tag in self.ignored_tags:
+                self.ignored_tags.remove(tag)
+        self._table.connect('tag-added', tag_added)
+        self._table.connect('tag-removed', tag_removed)
+        self._table.foreach(tag_added, None)
+        self.no_spell_check = self._table.lookup('no-spell-check')
+        if not self.no_spell_check:
+            if _pygobject:
+                self.no_spell_check = gtk.TextTag.new('no-spell-check')
+            else:
+                self.no_spell_check = gtk.TextTag('no-spell-check')
+            self._table.add(self.no_spell_check)
+        self.recheck()
+
+    def recheck(self):
+        """
+        Rechecks the spelling of the whole text.
+        """
+        start, end = self._buffer.get_bounds()
+        self.check_range(start, end, True)
+
+    def disable(self):
+        """
+        Disable spellchecking.
+        """
+        self._enabled = False
+        start, end = self._buffer.get_bounds()
+        self._buffer.remove_tag(self._misspelled, start, end)
+
+    def enable(self):
+        """
+        Enable spellchecking.
+        """
+        self._enabled = True
+        self.recheck()
+
+    def append_filter(self, regex, filter_type):
+        """
+        Append a new filter to the filter list. Filters are useful to ignore
+        some misspelled words based on regular expressions.
+
+        :param regex: The regex used for filtering.
+        :param filter_type: The type of the filter.
+
+        Filter Types:
+
+        :const:`SpellChecker.FILTER_WORD`: The regex must match the whole word
+            you want to filter. The word separation is done by Pango's word
+            separation algorithm so, for example, urls won't work here because
+            they are split in many words.
+
+        :const:`SpellChecker.FILTER_LINE`: If the expression you want to match
+            is a single line expression use this type. It should not be an open
+            end expression because then the rest of the line with the text you
+            want to filter will become correct.
+
+        :const:`SpellChecker.FILTER_TEXT`: Use this if you want to filter
+           multiline expressions. The regex will be compiled with the
+           `re.MULTILINE` flag. Same with open end expressions apply here.
+        """
+        self._filters[filter_type].append(regex)
+        if filter_type == SpellChecker.FILTER_TEXT:
+            self._regexes[filter_type] = re.compile('|'.join(
+                self._filters[filter_type]), re.MULTILINE)
+        else:
+            self._regexes[filter_type] = re.compile('|'.join(
+                self._filters[filter_type]))
+
+    def remove_filter(self, regex, filter_type):
+        """
+        Remove a filter from the filter list.
+
+        :param regex: The regex which used for filtering.
+        :param filter_type: The type of the filter.
+        """
+        self._filters[filter_type].remove(regex)
+        if filter_type == SpellChecker.FILTER_TEXT:
+            self._regexes[filter_type] = re.compile('|'.join(
+                self._filters[filter_type]), re.MULTILINE)
+        else:
+            self._regexes[filter_type] = re.compile('|'.join(
+                self._filters[filter_type]))
+
+    def append_ignore_tag(self, tag):
+        """
+        Appends a tag to the list of ignored tags. A string will be automatic
+        resolved into a tag object.
+
+        :param tag: Tag object or tag name.
+        """
+        if isinstance(tag, basestring):
+            tag = self._table.lookup(tag)
+        self.ignored_tags.append(tag)
+
+    def remove_ignore_tag(self, tag):
+        """
+        Removes a tag from the list of ignored tags. A string will be automatic
+        resolved into a tag object.
+
+        :param tag: Tag object or tag name.
+        """
+        if isinstance(tag, basestring):
+            tag = self._table.lookup(tag)
+        self.ignored_tags.remove(tag)
+
+    def add_to_dictionary(self, word):
+        """
+        Adds a word to user's dictionary.
+
+        :param word: The word to add.
+        """
+        self._dictionary.add_to_pwl(word)
+        self.recheck()
+
+    def ignore_all(self, word):
+        """
+        Ignores a word for the current session.
+
+        :param word: The word to ignore.
+        """
+        self._dictionary.add_to_session(word)
+        self.recheck()
+
+    def check_range(self, start, end, force_all=False):
+        """
+        Checks a specified range between two GtkTextIters.
+
+        :param start: Start iter - checking starts here.
+        :param end: End iter - checking ends here.
+        """
+        if not self._enabled:
+            return
+        if end.inside_word(): end.forward_word_end()
+        if not start.starts_word() and (start.inside_word() or
+                                        start.ends_word()):
+            start.backward_word_start()
+        self._buffer.remove_tag(self._misspelled, start, end)
+        cursor = self._buffer.get_iter_at_mark(self._buffer.get_insert())
+        precursor = cursor.copy()
+        precursor.backward_char()
+        highlight = (cursor.has_tag(self._misspelled) or
+                     precursor.has_tag(self._misspelled))
+        if not start.get_offset():
+            start.forward_word_end()
+            start.backward_word_start()
+        word_start = start.copy()
+        while word_start.compare(end) < 0:
+            word_end = word_start.copy()
+            word_end.forward_word_end()
+            in_word = ((word_start.compare(cursor) < 0) and
+                       (cursor.compare(word_end) <= 0))
+            if in_word and not force_all:
+                if highlight:
+                    self._check_word(word_start, word_end)
+                else:
+                    self._deferred_check = True
+            else:
+                self._check_word(word_start, word_end)
+                self._deferred_check = False
+            word_end.forward_word_end()
+            word_end.backward_word_start()
+            if word_start.equal(word_end):
+                break
+            word_start = word_end.copy()
+
+    def _languages_menu(self):
+        def _set_language(item, code):
+            self.language = code
+        if _pygobject:
+            menu = gtk.Menu.new()
+            group = []
+        else:
+            menu = gtk.Menu()
+            group = gtk.RadioMenuItem()
+        connect = []
+        for code, name in self.languages:
+            if _pygobject:
+                item = gtk.RadioMenuItem.new_with_label(group, name)
+                group.append(item)
+            else:
+                item = gtk.RadioMenuItem(group, name)
+            if code == self.language:
+                item.set_active(True)
+            connect.append((item, code))
+            menu.append(item)
+        for item, code in connect:
+            item.connect('activate', _set_language, code)
+        return menu
+
+    def _suggestion_menu(self, word):
+        menu = []
+        suggestions = self._dictionary.suggest(word)
+        if not suggestions:
+            if _pygobject:
+                item = gtk.MenuItem.new()
+                label = gtk.Label.new('')
+            else:
+                item = gtk.MenuItem()
+                label = gtk.Label()
+            try:
+                label.set_halign(gtk.Align.LEFT)
+            except AttributeError:
+                label.set_alignment(0.0, 0.5)
+            label.set_markup('<i>{text}</i>'.format(text=_('(no 
suggestions)')))
+            item.add(label)
+            menu.append(item)
+        else:
+            for suggestion in suggestions:
+                if _pygobject:
+                    item = gtk.MenuItem.new()
+                    label = gtk.Label.new('')
+                else:
+                    item = gtk.MenuItem()
+                    label = gtk.Label()
+                label.set_markup('<b>{text}</b>'.format(text=suggestion))
+                try:
+                    label.set_halign(gtk.Align.LEFT)
+                except AttributeError:
+                    label.set_alignment(0.0, 0.5)
+                item.add(label)
+                item.connect('activate', self._replace_word, word, suggestion)
+                menu.append(item)
+        if _pygobject:
+            menu.append(gtk.SeparatorMenuItem.new())
+            item = gtk.MenuItem.new_with_label(
+                _('Add "{}" to Dictionary').format(word))
+        else:
+            menu.append(gtk.SeparatorMenuItem())
+            item = gtk.MenuItem(_('Add "{}" to Dictionary').format(word))
+        item.connect('activate', lambda *args: self.add_to_dictionary(word))
+        menu.append(item)
+        if _pygobject:
+            item = gtk.MenuItem.new_with_label(_('Ignore All'))
+        else:
+            item = gtk.MenuItem(_('Ignore All'))
+        item.connect('activate', lambda *args: self.ignore_all(word))
+        menu.append(item)
+        return menu
+
+    def _extend_menu(self, menu):
+        if not self._enabled:
+            return
+        if _pygobject:
+            separator = gtk.SeparatorMenuItem.new()
+        else:
+            separator = gtk.SeparatorMenuItem()
+        separator.show()
+        menu.prepend(separator)
+        if _pygobject:
+            languages = gtk.MenuItem.new_with_label(_('Languages'))
+        else:
+            languages = gtk.MenuItem(_('Languages'))
+        languages.set_submenu(self._languages_menu())
+        languages.show_all()
+        menu.prepend(languages)
+        if self._marks['click'].inside_word:
+            start, end = self._marks['click'].word
+            if start.has_tag(self._misspelled):
+                if _py3k:
+                    word = self._buffer.get_text(start, end, False)
+                else:
+                    word = self._buffer.get_text(start, end,
+                                                 False).decode('utf-8')
+                items = self._suggestion_menu(word)
+                if self.collapse:
+                    if _pygobject:
+                        suggestions = gtk.MenuItem.new_with_label(
+                            _('Suggestions'))
+                        submenu = gtk.Menu.new()
+                    else:
+                        suggestions = gtk.MenuItem(_('Suggestions'))
+                        submenu = gtk.Menu()
+                    for item in items:
+                        submenu.append(item)
+                    suggestions.set_submenu(submenu)
+                    suggestions.show_all()
+                    menu.prepend(suggestions)
+                else:
+                    items.reverse()
+                    for item in items:
+                        menu.prepend(item)
+                        menu.show_all()
+
+    def _click_move_popup(self, *args):
+        self._marks['click'].move(self._buffer.get_iter_at_mark(
+            self._buffer.get_insert()))
+        return False
+
+    def _click_move_button(self, widget, event):
+        if event.button == 3:
+            if self._deferred_check:  self._check_deferred_range(True)
+            x, y = self._view.window_to_buffer_coords(2, int(event.x),
+                                                      int(event.y))
+            iter = self._view.get_iter_at_location(x, y)
+            if isinstance(iter, tuple):
+                iter = iter[1]
+            self._marks['click'].move(iter)
+        return False
+
+    def _before_text_insert(self, textbuffer, location, text, length):
+        self._marks['insert-start'].move(location)
+
+    def _after_text_insert(self, textbuffer, location, text, length):
+        start = self._marks['insert-start'].iter
+        self.check_range(start, location)
+        self._marks['insert-end'].move(location)
+
+    def _range_delete(self, textbuffer, start, end):
+        self.check_range(start, end)
+
+    def _mark_set(self, textbuffer, location, mark):
+        if mark == self._buffer.get_insert() and self._deferred_check:
+            self._check_deferred_range(False)
+
+    def _replace_word(self, item, old_word, new_word):
+        start, end = self._marks['click'].word
+        offset = start.get_offset()
+        self._buffer.begin_user_action()
+        self._buffer.delete(start, end)
+        self._buffer.insert(self._buffer.get_iter_at_offset(offset), new_word)
+        self._buffer.end_user_action()
+        self._dictionary.store_replacement(old_word, new_word)
+
+    def _check_deferred_range(self, force_all):
+        start = self._marks['insert-start'].iter
+        end = self._marks['insert-end'].iter
+        self.check_range(start, end, force_all)
+
+    def _check_word(self, start, end):
+        if start.has_tag(self.no_spell_check):
+            return
+        for tag in self.ignored_tags:
+            if start.has_tag(tag):
+                return
+        if _py3k:
+            word = self._buffer.get_text(start, end, False).strip()
+        else:
+            word = self._buffer.get_text(start, end, 
False).decode('utf-8').strip()
+        if not word:
+            return
+        if len(self._filters[SpellChecker.FILTER_WORD]):
+            if self._regexes[SpellChecker.FILTER_WORD].match(word):
+                return
+        if len(self._filters[SpellChecker.FILTER_LINE]):
+            line_start = self._buffer.get_iter_at_line(start.get_line())
+            line_end = end.copy()
+            line_end.forward_to_line_end()
+            if _py3k:
+                line = self._buffer.get_text(line_start, line_end, False)
+            else:
+                line = self._buffer.get_text(line_start, line_end,
+                                             False).decode('utf-8')
+            for match in 
self._regexes[SpellChecker.FILTER_LINE].finditer(line):
+                if match.start() <= start.get_line_offset() <= match.end():
+                    start = self._buffer.get_iter_at_line_offset(
+                        start.get_line(), match.start())
+                    end = 
self._buffer.get_iter_at_line_offset(start.get_line(),
+                                                               match.end())
+                    self._buffer.remove_tag(self._misspelled, start, end)
+                    return
+        if len(self._filters[SpellChecker.FILTER_TEXT]):
+            text_start, text_end = self._buffer.get_bounds()
+            if _py3k:
+                text = self._buffer.get_text(text_start, text_end, False)
+            else:
+                text = self._buffer.get_text(text_start, text_end,
+                                             False).decode('utf-8')
+            for match in 
self._regexes[SpellChecker.FILTER_TEXT].finditer(text):
+                if match.start() <= start.get_offset() <= match.end():
+                    start = self._buffer.get_iter_at_offset(match.start())
+                    end = self._buffer.get_iter_at_offset(match.end())
+                    self._buffer.remove_tag(self._misspelled, start, end)
+                    return
+        if not self._dictionary.check(word):
+            self._buffer.apply_tag(self._misspelled, start, end)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rednotebook-1.14/rednotebook/gui/editor.py 
new/rednotebook-1.15/rednotebook/gui/editor.py
--- old/rednotebook-1.14/rednotebook/gui/editor.py      2016-09-26 
13:58:58.000000000 +0200
+++ new/rednotebook-1.15/rednotebook/gui/editor.py      2017-01-20 
11:06:28.000000000 +0100
@@ -24,17 +24,17 @@
 import gtk
 import pango
 
-try:
-    import gtkspellcheck
-except ImportError:
-    logging.warning(
-        'For spell checking, please install pygtkspellcheck 
(python-gtkspellcheck).')
-    gtkspellcheck = None
-
 from rednotebook.gui import t2t_highlight
 from rednotebook import undo
 from rednotebook.util import filesystem
 
+try:
+    from rednotebook.external import spellcheck
+except ImportError:
+    logging.warning(
+        'For spell checking, please install enchant (python-enchant).')
+    spellcheck = None
+
 
 DEFAULT_FONT = gtk.settings_get_default().get_property('gtk-font-name')
 
@@ -268,10 +268,10 @@
 
     def can_spell_check(self):
         """Return True if spell checking is available."""
-        return gtkspellcheck is not None
+        return spellcheck is not None
 
     def is_spell_check_enabled(self):
-        return self._spell_checker and self._spell_checker.enabled
+        return bool(self._spell_checker and self._spell_checker.enabled)
 
     def _enable_spell_check(self):
         assert self.can_spell_check()
@@ -279,10 +279,11 @@
             self._spell_checker.enable()
         else:
             try:
-                self._spell_checker = gtkspellcheck.SpellChecker(
+                self._spell_checker = spellcheck.SpellChecker(
                     self.day_text_view, filesystem.LANGUAGE)
-            # TODO: Find out which exceptions can be thrown here. Seems to
-            #       depend on the library version.
+            except spellcheck.NoDictionariesFound:
+                logging.warning('No spell checking dictionaries found.')
+                self._spell_checker = None
             except Exception as err:
                 logging.error(
                     'Spell checking could not be enabled. %s: %s' %
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rednotebook-1.14/rednotebook/gui/main_window.py 
new/rednotebook-1.15/rednotebook/gui/main_window.py
--- old/rednotebook-1.14/rednotebook/gui/main_window.py 2016-07-14 
16:27:00.000000000 +0200
+++ new/rednotebook-1.15/rednotebook/gui/main_window.py 2017-01-29 
13:59:47.000000000 +0100
@@ -242,6 +242,11 @@
 
     def setup_tray_icon(self):
         self.tray_icon = gtk.StatusIcon()
+        try:
+            # Available in PyGTK >= 2.22
+            self.tray_icon.set_name('RedNotebook')
+        except AttributeError:
+            pass
         visible = (self.journal.config.read('closeToTray') == 1)
         self.tray_icon.set_visible(visible)
         logging.debug('Tray icon visible: %s' % visible)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rednotebook-1.14/rednotebook/gui/options.py 
new/rednotebook-1.15/rednotebook/gui/options.py
--- old/rednotebook-1.14/rednotebook/gui/options.py     2016-03-28 
21:43:27.000000000 +0200
+++ new/rednotebook-1.15/rednotebook/gui/options.py     2017-01-18 
21:30:56.000000000 +0100
@@ -82,7 +82,7 @@
 class AutostartOption(TickOption):
     def __init__(self):
         self.autostart_file = os.path.expanduser(
-            '~.config/autostart/rednotebook.desktop')
+            '~/.config/autostart/rednotebook.desktop')
         autostart_file_exists = os.path.exists(self.autostart_file)
         TickOption.__init__(
             self, _('Load RedNotebook at startup'), None, 
value=autostart_file_exists)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rednotebook-1.14/rednotebook/info.py 
new/rednotebook-1.15/rednotebook/info.py
--- old/rednotebook-1.14/rednotebook/info.py    2016-09-26 15:27:32.000000000 
+0200
+++ new/rednotebook-1.15/rednotebook/info.py    2017-02-11 16:13:25.000000000 
+0100
@@ -26,7 +26,7 @@
         return string
 
 
-version = '1.14'
+version = '1.15'
 author = 'Jendrik Seipp'
 author_mail = 'jendrikse...@web.de'
 url = 'http://rednotebook.sourceforge.net'


Reply via email to