1 /*
2 * This file is part of Licq, an instant messaging client for UNIX.
3 * Copyright (C) 2009 Licq developers
4 *
5 * Licq is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * Licq is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Licq; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include "spellchecker.h"
21
22 #include <QFileInfo>
23 #include <QRegExp>
24 #include <QSyntaxHighlighter>
25 #include <QTextCodec>
26
27 #include <hunspell/hunspell.hxx>
28
29
30 using namespace LicqQtGui;
31 /* TRANSLATOR LicqQtGui::SpellChecker */
32
SpellChecker(QTextDocument * parent,const QString & dicFile)33 SpellChecker::SpellChecker(QTextDocument* parent, const QString& dicFile)
34 : QSyntaxHighlighter(parent),
35 mySpeller(NULL)
36 {
37 setDictionary(dicFile);
38 }
39
~SpellChecker()40 SpellChecker::~SpellChecker()
41 {
42 if (mySpeller != NULL)
43 delete mySpeller;
44 }
45
setDictionary(const QString & dicFile)46 void SpellChecker::setDictionary(const QString& dicFile)
47 {
48 if (dicFile == myDicFile)
49 return;
50 myDicFile = dicFile;
51
52 if (mySpeller != NULL)
53 {
54 delete mySpeller;
55 mySpeller = NULL;
56 }
57
58 // If dicFile is empty or refers to a non-existent file, disable spell checking
59 if (dicFile.isEmpty() || !QFileInfo(dicFile).isReadable())
60 return;
61
62 QString affFile = dicFile.left(dicFile.lastIndexOf('.')) + ".aff";
63 mySpeller = new Hunspell(affFile.toLatin1(), dicFile.toLatin1());
64 mySpellerCodec = QTextCodec::codecForName(mySpeller->get_dic_encoding());
65 }
66
highlightBlock(const QString & text)67 void SpellChecker::highlightBlock(const QString& text)
68 {
69 if (mySpeller == NULL)
70 return;
71
72 QTextCharFormat myBadSpelling;
73 myBadSpelling.setUnderlineStyle(QTextCharFormat::SpellCheckUnderline);
74 myBadSpelling.setUnderlineColor(Qt::red);
75
76 QRegExp wordSplit("\\b\\w+\\b");
77 int pos = 0;
78 while ((pos = wordSplit.indexIn(text, pos)) != -1)
79 {
80 int len = wordSplit.matchedLength();
81 if (!checkWord(wordSplit.cap()))
82 setFormat(pos, len, myBadSpelling);
83 pos += len;
84 }
85 }
86
getSuggestions(const QString & word)87 QStringList SpellChecker::getSuggestions(const QString& word)
88 {
89 if (mySpeller == NULL || checkWord(word))
90 return QStringList();
91
92 char** wordList;
93 int count = mySpeller->suggest(&wordList, mySpellerCodec->fromUnicode(word).data());
94 if (count <= 0)
95 return QStringList();
96
97 QStringList ret;
98 for (int i = 0; i < count; ++i)
99 ret.append(mySpellerCodec->toUnicode(wordList[i]));
100 mySpeller->free_list(&wordList, count);
101
102 return ret;
103 }
104
checkWord(const QString & word)105 bool SpellChecker::checkWord(const QString& word)
106 {
107 if (mySpeller == NULL)
108 return true;
109
110 return (mySpeller->spell(mySpellerCodec->fromUnicode(word).data()) != 0);
111 }
112