aboutsummaryrefslogtreecommitdiffstats
path: root/scudcloud-1.0/lib/speller.py
blob: 11f365e3af013cf46410e6c70570ec4be9e7083c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import os
from resources import Resources
from PyQt4 import QtGui
from PyQt4.QtCore import QObject
from PyQt4.QtCore import QLocale, QFile, QTextBoundaryFinder

# Checking if python-hunspell is present
try:
     import hunspell
except ImportError:
     class hunspell:
         HunSpell = None

# Simplified version of QupZilla Speller (https://github.com/QupZilla/qupzilla/blob/v1.8/src/lib/plugins/qtwebkit/spellcheck/speller.cpp)
class Speller(QObject):

    hunspell = None
    initialized = False
    startPos = 0

    def __init__(self):
        super(Speller, self).__init__()
        if self.initialized or hunspell.HunSpell is None:
            return
        dictionaryPath = self.getDictionaryPath()
        language = self.parseLanguage(dictionaryPath)
        if not dictionaryPath or language is None:
            return
        self.hunspell = hunspell.HunSpell(dictionaryPath + ".dic", dictionaryPath + ".aff")
        self.initialized = True

    def isMisspelled(self, s):
        return not self.hunspell.spell(s)

    def suggest(self, s):
        return self.hunspell.suggest(s)

    def parseLanguage(self, path):
        if '/' in path:
            pos = path.rfind('/')
            return path[-int(pos + 1):]
        return path

    def dictionaryExists(self, path):
        return QFile(path + ".dic").exists() and QFile(path + ".aff").exists();

    def getDictionaryPath(self):
        dicPath = Resources.SPELL_DICT_PATH + QLocale.system().name()
        if self.dictionaryExists(dicPath):
            return dicPath
        return ''

    def replaceWord(self, element, word):
        action = self.sender()
        new = action.data()
        text = str(element.evaluateJavaScript("this.value"))
        cursorPos = int(element.evaluateJavaScript("this.selectionStart"))
        text = text[:self.startPos] + new + text[self.startPos+len(word):]
        text = text.replace('\\', "\\\\")
        text = text.replace('\n', "\\n")
        text = text.replace('\'', "\\'")
        element.evaluateJavaScript("this.value='{}'".format(text))
        element.evaluateJavaScript("this.selectionStart=this.selectionEnd={}".format(cursorPos))

    def getWord(self, element):
        text = str(element.evaluateJavaScript("this.value"))
        pos = int(int(element.evaluateJavaScript("this.selectionStart")) + int(1))
        finder =  QTextBoundaryFinder(QTextBoundaryFinder.Word, text)
        finder.setPosition(pos)
        self.startPos = finder.toPreviousBoundary()
        return text[self.startPos:finder.toNextBoundary()].strip()

    def populateContextMenu(self, menu, element):
        word = self.getWord(element)
        if self.isMisspelled(word):
            suggests = self.suggest(word)
            count = Resources.SPELL_LIMIT
            if len(suggests) < count:
                count = len(suggests)
            boldFont = menu.font()
            boldFont.setBold(True)
            for i in range(0, count):
                action = QtGui.QAction(suggests[i], self)
                action.triggered.connect(lambda:self.replaceWord(element, word))
                action.setData(suggests[i])
                action.setFont(boldFont)
                menu.addAction(action)
            if count == 0:
                menu.addAction(menu.tr("No suggestions")).setEnabled(False)
            menu.addSeparator();