19 #include "QtSpell.hpp"
20 #include "Codetable.hpp"
22 #include <enchant++.h>
23 #include <QApplication>
24 #include <QLibraryInfo>
27 #include <QTranslator>
29 static void dict_describe_cb(
const char*
const lang_tag,
35 QList<QString>* languages =
static_cast<QList<QString>*
>(user_data);
36 languages->append(lang_tag);
39 static enchant::Broker* get_enchant_broker() {
40 #ifdef QTSPELL_ENCHANT2
41 static enchant::Broker broker;
44 return enchant::Broker::instance();
49 class TranslationsInit {
52 QString translationsPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
54 QDir packageDir = QDir(QString(
"%1/../").arg(QApplication::applicationDirPath()));
55 translationsPath = packageDir.absolutePath() + translationsPath.mid(QLibraryInfo::location(QLibraryInfo::PrefixPath).length());
57 spellTranslator.load(
"QtSpell_" + QLocale::system().name(), translationsPath);
58 QApplication::instance()->installTranslator(&spellTranslator);
61 QTranslator spellTranslator;
69 return get_enchant_broker()->dict_exists(lang.toStdString());
76 m_spellingCheckbox(false),
77 m_spellingEnabled(true)
79 static TranslationsInit tsInit;
83 setLanguageInternal(
"");
93 bool success = setLanguageInternal(lang);
100 bool Checker::setLanguageInternal(
const QString &lang)
107 if(m_lang.isEmpty()){
108 m_lang = QLocale::system().name();
109 if(m_lang.toLower() ==
"c" || m_lang.isEmpty()){
110 qWarning(
"Cannot use system locale %s", m_lang.toLatin1().data());
111 m_lang = QString::null;
118 m_speller = get_enchant_broker()->request_dict(m_lang.toStdString());
119 }
catch(enchant::Exception& e) {
120 qWarning(
"Failed to load dictionary: %s", e.what());
121 m_lang = QString::null;
131 m_speller->add(word.toUtf8().data());
137 if(!m_speller || !m_spellingEnabled){
141 if(word.length() < 2){
145 return m_speller->check(word.toUtf8().data());
146 }
catch(
const enchant::Exception&){
153 m_speller->add_to_session(word.toUtf8().data());
160 std::vector<std::string> suggestions;
161 m_speller->suggest(word.toUtf8().data(), suggestions);
162 for(std::size_t i = 0, n = suggestions.size(); i < n; ++i){
163 list.append(QString::fromUtf8(suggestions[i].c_str()));
171 enchant::Broker* broker = get_enchant_broker();
172 QList<QString> languages;
173 broker->list_dicts(dict_describe_cb, &languages);
180 QString language, country, extra;
182 if(!country.isEmpty()){
183 QString decoded = QString(
"%1 (%2)").arg(language, country);
184 if(!extra.isEmpty()) {
185 decoded += QString(
" [%1]").arg(extra);
193 void Checker::showContextMenu(QMenu* menu,
const QPoint& pos,
int wordPos)
195 QAction* insertPos = menu->actions().first();
196 if(m_speller && m_spellingEnabled){
197 QString word =
getWord(wordPos);
201 if(!suggestions.isEmpty()){
202 for(
int i = 0, n = qMin(10, suggestions.length()); i < n; ++i){
203 QAction* action =
new QAction(suggestions[i], menu);
204 action->setProperty(
"wordPos", wordPos);
205 action->setProperty(
"suggestion", suggestions[i]);
206 connect(action, SIGNAL(triggered()),
this, SLOT(slotReplaceWord()));
207 menu->insertAction(insertPos, action);
209 if(suggestions.length() > 10) {
210 QMenu* moreMenu =
new QMenu();
211 for(
int i = 10, n = suggestions.length(); i < n; ++i){
212 QAction* action =
new QAction(suggestions[i], moreMenu);
213 action->setProperty(
"wordPos", wordPos);
214 action->setProperty(
"suggestion", suggestions[i]);
215 connect(action, SIGNAL(triggered()),
this, SLOT(slotReplaceWord()));
216 moreMenu->addAction(action);
218 QAction* action =
new QAction(tr(
"More..."), menu);
219 menu->insertAction(insertPos, action);
220 action->setMenu(moreMenu);
222 menu->insertSeparator(insertPos);
225 QAction* addAction =
new QAction(tr(
"Add \"%1\" to dictionary").arg(word), menu);
226 addAction->setData(wordPos);
227 connect(addAction, SIGNAL(triggered()),
this, SLOT(slotAddWord()));
228 menu->insertAction(insertPos, addAction);
230 QAction* ignoreAction =
new QAction(tr(
"Ignore \"%1\"").arg(word), menu);
231 ignoreAction->setData(wordPos);
232 connect(ignoreAction, SIGNAL(triggered()),
this, SLOT(slotIgnoreWord()));
233 menu->insertAction(insertPos, ignoreAction);
234 menu->insertSeparator(insertPos);
237 if(m_spellingCheckbox){
238 QAction* action =
new QAction(tr(
"Check spelling"), menu);
239 action->setCheckable(
true);
240 action->setChecked(m_spellingEnabled);
242 menu->insertAction(insertPos, action);
244 if(m_speller && m_spellingEnabled){
245 QMenu* languagesMenu =
new QMenu();
246 QActionGroup* actionGroup =
new QActionGroup(languagesMenu);
249 QAction* action =
new QAction(text, languagesMenu);
250 action->setData(lang);
251 action->setCheckable(
true);
253 connect(action, SIGNAL(triggered(
bool)),
this, SLOT(slotSetLanguage(
bool)));
254 languagesMenu->addAction(action);
255 actionGroup->addAction(action);
257 QAction* langsAction =
new QAction(tr(
"Languages"), menu);
258 langsAction->setMenu(languagesMenu);
259 menu->insertAction(insertPos, langsAction);
260 menu->insertSeparator(insertPos);
267 void Checker::slotAddWord()
269 int wordPos = qobject_cast<QAction*>(QObject::sender())->property(
"wordPos").toInt();
275 void Checker::slotIgnoreWord()
277 int wordPos = qobject_cast<QAction*>(QObject::sender())->property(
"wordPos").toInt();
283 void Checker::slotReplaceWord()
285 QAction* action = qobject_cast<QAction*>(QObject::sender());
286 int wordPos = action->property(
"wordPos").toInt();
288 getWord(wordPos, &start, &end);
289 insertWord(start, end, action->property(
"suggestion").toString());
292 void Checker::slotSetLanguage(
bool checked)
295 QAction* action = qobject_cast<QAction*>(QObject::sender());
296 QString lang = action->data().toString();
298 action->setChecked(
false);
Checker(QObject *parent=0)
QtSpell::Checker object constructor.
bool setLanguage(const QString &lang)
Set the spell checking language.
virtual bool isAttached() const =0
Returns whether a widget is attached to the checker.
QList< QString > getSpellingSuggestions(const QString &word) const
Retreive a list of spelling suggestions for the misspelled word.
static QList< QString > getLanguageList()
Requests the list of languages available for spell checking.
virtual ~Checker()
QtSpell::Checker object destructor.
bool getDecodeLanguageCodes() const
Return whether langauge codes are decoded in the UI.
void setSpellingEnabled(bool enabled)
Set whether spell checking should be performed.
bool checkWord(const QString &word) const
Check the specified word.
void languageChanged(const QString &newLang)
This signal is emitted when the user selects a new language from the spellchecker UI.
virtual void checkSpelling(int start=0, int end=-1)=0
Check the spelling.
virtual QString getWord(int pos, int *start=0, int *end=0) const =0
Get the word at the specified cursor position.
virtual void insertWord(int start, int end, const QString &word)=0
Replaces the specified range with the specified word.
static QString decodeLanguageCode(const QString &lang)
Translates a language code to a human readable format (i.e. "en_US" -> "English (United States)").
void addWordToDictionary(const QString &word)
Add the specified word to the user dictionary.
void ignoreWord(const QString &word) const
Ignore a word for the current session.
const QString & getLanguage() const
Retreive the current spelling language.
static Codetable * instance()
Get codetable instance.
void lookup(const QString &language_code, QString &language_name, QString &country_name, QString &extra) const
Looks up the language and country name for the specified language code. If no matching entries are fo...
bool checkLanguageInstalled(const QString &lang)
Check whether the dictionary for a language is installed.