20#include "Checker_p.hpp"
21#include "Codetable.hpp"
24#include <QActionGroup>
25#include <QApplication>
26#include <QLibraryInfo>
32static void dict_describe_cb(
const char*
const lang_tag,
38 QList<QString>* languages =
static_cast<QList<QString>*
>(user_data);
39 languages->append(lang_tag);
42static enchant::Broker* get_enchant_broker() {
43#ifdef QTSPELL_ENCHANT2
44 static enchant::Broker broker;
47 return enchant::Broker::instance();
52class TranslationsInit {
55#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
56 QString translationsPath = QLibraryInfo::path(QLibraryInfo::TranslationsPath);
58 QString translationsPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
61 QDir packageDir = QDir(QString(
"%1/../").arg(QApplication::applicationDirPath()));
62#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
63 translationsPath = packageDir.absolutePath() + translationsPath.mid(QLibraryInfo::path(QLibraryInfo::PrefixPath).length());
65 translationsPath = packageDir.absolutePath() + translationsPath.mid(QLibraryInfo::location(QLibraryInfo::PrefixPath).length());
68 bool success = spellTranslator.load(
"QtSpell_" + QLocale::system().name(), translationsPath);
70 QApplication::instance()->installTranslator(&spellTranslator);
73 QTranslator spellTranslator;
79CheckerPrivate::CheckerPrivate()
83CheckerPrivate::~CheckerPrivate()
88void CheckerPrivate::init()
90 static TranslationsInit tsInit;
93 setLanguageInternal(
"");
98 return get_enchant_broker()->dict_exists(lang.toStdString());
103 , d_ptr(new CheckerPrivate())
125 bool success = d->setLanguageInternal(lang);
138bool CheckerPrivate::setLanguageInternal(
const QString &newLang)
146 lang = QLocale::system().name();
147 if(lang.toLower() ==
"c" || lang.isEmpty()){
148 qWarning() <<
"Cannot use system locale " << lang;
156 speller = get_enchant_broker()->request_dict(lang.toStdString());
157 }
catch(enchant::Exception& e) {
158 qWarning() <<
"Failed to load dictionary: " << e.what();
169 d->decodeCodes = decode;
175 return d->decodeCodes;
181 d->spellingCheckbox = show;
187 return d->spellingCheckbox;
193 return d->spellingEnabled;
200 d->speller->add(word.toUtf8().data());
207 if(!d->speller || !d->spellingEnabled){
211 if(word.length() < 2){
215 return d->speller->check(word.toUtf8().data());
216 }
catch(
const enchant::Exception&){
224 d->speller->add_to_session(word.toUtf8().data());
232 std::vector<std::string> suggestions;
233 d->speller->suggest(word.toUtf8().data(), suggestions);
234 for(std::size_t i = 0, n = suggestions.size(); i < n; ++i){
235 list.append(QString::fromUtf8(suggestions[i].c_str()));
243 enchant::Broker* broker = get_enchant_broker();
244 QList<QString> languages;
245 broker->list_dicts(dict_describe_cb, &languages);
246 std::sort(languages.begin(), languages.end());
252 QString language, country, extra;
254 if(!country.isEmpty()){
255 QString decoded = QString(
"%1 (%2)").arg(language, country);
256 if(!extra.isEmpty()) {
257 decoded += QString(
" [%1]").arg(extra);
268 d->spellingEnabled = enabled;
272void Checker::showContextMenu(QMenu* menu,
const QPoint& pos,
int wordPos)
275 QAction* insertPos = menu->actions().first();
276 if(d->speller && d->spellingEnabled){
277 QString word =
getWord(wordPos);
281 if(!suggestions.isEmpty()){
282 for(
int i = 0, n = qMin(10, suggestions.length()); i < n; ++i){
283 QAction* action =
new QAction(suggestions[i], menu);
284 action->setProperty(
"wordPos", wordPos);
285 action->setProperty(
"suggestion", suggestions[i]);
286 connect(action, &QAction::triggered,
this, &Checker::slotReplaceWord);
287 menu->insertAction(insertPos, action);
289 if(suggestions.length() > 10) {
290 QMenu* moreMenu =
new QMenu();
291 for(
int i = 10, n = suggestions.length(); i < n; ++i){
292 QAction* action =
new QAction(suggestions[i], moreMenu);
293 action->setProperty(
"wordPos", wordPos);
294 action->setProperty(
"suggestion", suggestions[i]);
295 connect(action, &QAction::triggered,
this, &Checker::slotReplaceWord);
296 moreMenu->addAction(action);
298 QAction* action =
new QAction(tr(
"More..."), menu);
299 menu->insertAction(insertPos, action);
300 action->setMenu(moreMenu);
302 menu->insertSeparator(insertPos);
305 QAction* addAction =
new QAction(tr(
"Add \"%1\" to dictionary").arg(word), menu);
306 addAction->setData(wordPos);
307 connect(addAction, &QAction::triggered,
this, &Checker::slotAddWord);
308 menu->insertAction(insertPos, addAction);
310 QAction* ignoreAction =
new QAction(tr(
"Ignore \"%1\"").arg(word), menu);
311 ignoreAction->setData(wordPos);
312 connect(ignoreAction, &QAction::triggered,
this, &Checker::slotIgnoreWord);
313 menu->insertAction(insertPos, ignoreAction);
314 menu->insertSeparator(insertPos);
317 if(d->spellingCheckbox){
318 QAction* action =
new QAction(tr(
"Check spelling"), menu);
319 action->setCheckable(
true);
320 action->setChecked(d->spellingEnabled);
322 menu->insertAction(insertPos, action);
324 if(d->speller && d->spellingEnabled){
325 QMenu* languagesMenu =
new QMenu();
326 QActionGroup* actionGroup =
new QActionGroup(languagesMenu);
329 QAction* action =
new QAction(text, languagesMenu);
330 action->setData(lang);
331 action->setCheckable(
true);
333 connect(action, &QAction::triggered,
this, &Checker::slotSetLanguage);
334 languagesMenu->addAction(action);
335 actionGroup->addAction(action);
337 QAction* langsAction =
new QAction(tr(
"Languages"), menu);
338 langsAction->setMenu(languagesMenu);
339 menu->insertAction(insertPos, langsAction);
340 menu->insertSeparator(insertPos);
347void Checker::slotAddWord()
349 int wordPos = qobject_cast<QAction*>(QObject::sender())->data().toInt();
355void Checker::slotIgnoreWord()
357 int wordPos = qobject_cast<QAction*>(QObject::sender())->data().toInt();
363void Checker::slotReplaceWord()
365 QAction* action = qobject_cast<QAction*>(QObject::sender());
366 int wordPos = action->property(
"wordPos").toInt();
368 getWord(wordPos, &start, &end);
369 insertWord(start, end, action->property(
"suggestion").toString());
372void Checker::slotSetLanguage(
bool checked)
375 QAction* action = qobject_cast<QAction*>(QObject::sender());
376 QString lang = action->data().toString();
378 action->setChecked(
false);
An abstract class providing spell checking support.
void setShowCheckSpellingCheckbox(bool show)
Set whether to display an "Check spelling" checkbox in the UI.
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.
void setDecodeLanguageCodes(bool decode)
Set whether to decode language codes in the UI.
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.
bool getShowCheckSpellingCheckbox() const
Return whether a "Check spelling" checkbox is displayed in the UI.
bool getSpellingEnabled() const
Return whether spellchecking is performed.
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)").
QString getLanguage() const
Retreive the current spelling language.
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.