20#include "Codetable.hpp"
23#include <QApplication>
24#include <QLibraryInfo>
29static void dict_describe_cb(
const char*
const lang_tag,
35 QList<QString>* languages =
static_cast<QList<QString>*
>(user_data);
36 languages->append(lang_tag);
39static enchant::Broker* get_enchant_broker() {
40#ifdef QTSPELL_ENCHANT2
41 static enchant::Broker broker;
44 return enchant::Broker::instance();
49class 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);
100bool 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);
193void 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);
267void Checker::slotAddWord()
269 int wordPos = qobject_cast<QAction*>(QObject::sender())->property(
"wordPos").toInt();
275void Checker::slotIgnoreWord()
277 int wordPos = qobject_cast<QAction*>(QObject::sender())->property(
"wordPos").toInt();
283void 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());
292void 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.
const QString & getLanguage() const
Retreive the current spelling language.
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.
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.