backport changes to fix #7884: detect missing dictionaries, add default dictionary location for hunspell, act on preference changes

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/branches/BRANCH_2_0_X@40599 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Stephan Witt 2012-01-11 17:05:18 +00:00
parent b5ef74803d
commit 12e0991465
12 changed files with 137 additions and 11 deletions

View File

@ -31,7 +31,8 @@ struct AppleSpellChecker::Private
SpellChecker::Result toResult(SpellCheckResult status);
string toString(SpellCheckResult status);
int numDictionaries() const;
/// the speller
AppleSpeller speller;
@ -82,7 +83,7 @@ string AppleSpellChecker::Private::toString(SpellCheckResult status)
SpellChecker::Result AppleSpellChecker::check(WordLangTuple const & word)
{
if (!hasDictionary(word.lang()))
return WORD_OK;
return NO_DICTIONARY;
string const word_str = to_utf8(word.word());
string const lang = d->languageMap[word.lang()->lang()];
@ -168,6 +169,20 @@ bool AppleSpellChecker::hasDictionary(Language const * lang) const
}
int AppleSpellChecker::numDictionaries() const
{
int result = 0;
map<string, string>::const_iterator it = d->languageMap.begin();
map<string, string>::const_iterator et = d->languageMap.end();
for (; it != et; ++it) {
string const langmap = it->second;
result += langmap.empty() ? 0 : 1;
}
return result;
}
int AppleSpellChecker::numMisspelledWords() const
{
return AppleSpeller_numMisspelledWords(d->speller);

View File

@ -30,6 +30,7 @@ public:
void remove(WordLangTuple const &);
void accept(WordLangTuple const &);
bool hasDictionary(Language const * lang) const;
int numDictionaries() const;
bool canCheckParagraph() const { return true; }
int numMisspelledWords() const;
void misspelledWord(int index, int & start, int & length) const;

View File

@ -65,6 +65,7 @@ struct AspellChecker::Private
bool isValidDictionary(AspellConfig * config,
string const & lang, string const & variety);
int numDictionaries() const;
bool checkAspellData(AspellConfig * config,
string const & basepath, string const & datapath, string const & dictpath,
string const & lang, string const & variety);
@ -313,6 +314,20 @@ AspellSpeller * AspellChecker::Private::speller(Language const * lang)
}
int AspellChecker::Private::numDictionaries() const
{
int result = 0;
Spellers::const_iterator it = spellers_.begin();
Spellers::const_iterator et = spellers_.end();
for (; it != et; ++it) {
Speller aspell = it->second;
result += aspell.e_speller != 0;
}
return result;
}
string AspellChecker::Private::toAspellWord(docstring const & word) const
{
size_t mpos;
@ -406,7 +421,7 @@ SpellChecker::Result AspellChecker::check(WordLangTuple const & word)
AspellSpeller * m = d->speller(word.lang());
if (!m)
return WORD_OK;
return NO_DICTIONARY;
if (word.word().empty())
// MSVC compiled Aspell doesn't like it.
@ -494,6 +509,12 @@ bool AspellChecker::hasDictionary(Language const * lang) const
}
int AspellChecker::numDictionaries() const
{
return d->numDictionaries();
}
docstring const AspellChecker::error()
{
Spellers::iterator it = d->spellers_.begin();

View File

@ -31,6 +31,7 @@ public:
void remove(WordLangTuple const &);
void accept(WordLangTuple const &);
bool hasDictionary(Language const * lang) const;
int numDictionaries() const;
docstring const error();
void advanceChangeNumber();
//@}

View File

@ -112,7 +112,10 @@ SpellChecker::Result EnchantChecker::check(WordLangTuple const & word)
{
enchant::Dict * m = d->speller(word.lang()->code());
if (!m || word.word().empty())
if (!m)
return NO_DICTIONARY;
if (word.word().empty())
return WORD_OK;
string utf8word = to_utf8(word.word());
@ -188,6 +191,12 @@ bool EnchantChecker::hasDictionary(Language const * lang) const
}
int EnchantChecker::numDictionaries() const
{
return d->spellers_.size();
}
docstring const EnchantChecker::error()
{
return docstring();

View File

@ -37,6 +37,7 @@ public:
void remove(WordLangTuple const &);
void accept(WordLangTuple const &);
bool hasDictionary(Language const * lang) const;
int numDictionaries() const;
docstring const error();
void advanceChangeNumber();
///@}

View File

@ -55,10 +55,13 @@ struct HunspellChecker::Private
Private();
~Private();
void cleanCache();
void setUserPath(std::string path);
const string dictPath(int selector);
bool haveLanguageFiles(string const & hpath);
bool haveDictionary(Language const * lang, string & hpath);
bool haveDictionary(Language const * lang);
int numDictionaries() const;
Hunspell * addSpeller(Language const * lang, string & hpath);
Hunspell * addSpeller(Language const * lang);
Hunspell * speller(Language const * lang);
@ -74,31 +77,53 @@ struct HunspellChecker::Private
IgnoreList ignored_;
///
LangPersonalWordList personal_;
///
std::string user_path_;
/// the location below system/user directory
/// there the aff+dic files lookup will happen
const string dictDirectory(void) const { return "dicts"; }
int maxLookupSelector(void) const { return 3; }
int maxLookupSelector(void) const { return 4; }
const string HunspellDictionaryName(Language const * lang) {
return lang->variety().empty()
? lang->code()
: lang->code() + "-" + lang->variety();
}
const string osPackageDictDirectory(void) {
return "/usr/share/myspell";
}
};
HunspellChecker::Private::Private()
{
setUserPath(lyxrc.hunspelldir_path);
}
HunspellChecker::Private::~Private()
{
cleanCache();
}
void HunspellChecker::Private::setUserPath(std::string path)
{
if (user_path_ != lyxrc.hunspelldir_path) {
cleanCache();
user_path_ = path;
}
}
void HunspellChecker::Private::cleanCache()
{
Spellers::iterator it = spellers_.begin();
Spellers::iterator end = spellers_.end();
for (; it != end; ++it) {
if ( 0 != it->second) delete it->second;
delete it->second;
it->second = 0;
}
LangPersonalWordList::const_iterator pdit = personal_.begin();
@ -125,6 +150,9 @@ bool HunspellChecker::Private::haveLanguageFiles(string const & hpath)
const string HunspellChecker::Private::dictPath(int selector)
{
switch (selector) {
case 3:
return addName(osPackageDictDirectory(),dictDirectory());
break;
case 2:
return addName(package().system_support().absFileName(),dictDirectory());
break;
@ -132,7 +160,7 @@ const string HunspellChecker::Private::dictPath(int selector)
return addName(package().user_support().absFileName(),dictDirectory());
break;
default:
return lyxrc.hunspelldir_path;
return user_path_;
}
}
@ -167,6 +195,8 @@ bool HunspellChecker::Private::haveDictionary(Language const * lang, string & hp
bool HunspellChecker::Private::haveDictionary(Language const * lang)
{
bool result = false;
setUserPath(lyxrc.hunspelldir_path);
for ( int p = 0; !result && p < maxLookupSelector(); p++ ) {
string lpath = dictPath(p);
result = haveDictionary(lang, lpath);
@ -181,10 +211,11 @@ bool HunspellChecker::Private::haveDictionary(Language const * lang)
Hunspell * HunspellChecker::Private::speller(Language const * lang)
{
setUserPath(lyxrc.hunspelldir_path);
Spellers::iterator it = spellers_.find(lang->lang());
if (it != spellers_.end())
if (it != spellers_.end()) {
return it->second;
}
return addSpeller(lang);
}
@ -228,6 +259,19 @@ Hunspell * HunspellChecker::Private::addSpeller(Language const * lang)
}
int HunspellChecker::Private::numDictionaries() const
{
int result = 0;
Spellers::const_iterator it = spellers_.begin();
Spellers::const_iterator et = spellers_.end();
for (; it != et; ++it) {
result += it->second != 0;
}
return result;
}
bool HunspellChecker::Private::isIgnored(WordLangTuple const & wl) const
{
IgnoreList::const_iterator it = ignored_.begin();
@ -298,7 +342,7 @@ SpellChecker::Result HunspellChecker::check(WordLangTuple const & wl)
Hunspell * h = d->speller(wl.lang());
if (!h)
return WORD_OK;
return NO_DICTIONARY;
int info;
string const encoding = h->get_dic_encoding();
@ -377,6 +421,12 @@ bool HunspellChecker::hasDictionary(Language const * lang) const
}
int HunspellChecker::numDictionaries() const
{
return d->numDictionaries();
}
docstring const HunspellChecker::error()
{
return docstring();

View File

@ -31,6 +31,7 @@ public:
void remove(WordLangTuple const &);
void accept(WordLangTuple const &);
bool hasDictionary(Language const * lang) const;
int numDictionaries() const;
docstring const error();
void advanceChangeNumber();
///@}

View File

@ -42,7 +42,9 @@ public:
/// number of other ignored "word"
IGNORED_WORD,
/// number of personal dictionary "word"
LEARNED_WORD
LEARNED_WORD,
/// missing dictionary for language
NO_DICTIONARY
};
virtual ~SpellChecker() {}
@ -51,6 +53,7 @@ public:
static bool misspelled(Result res) {
return res != WORD_OK
&& res != IGNORED_WORD
&& res != NO_DICTIONARY
&& res != LEARNED_WORD; }
/// check the given word of the given lang code and return the result
@ -71,6 +74,9 @@ public:
/// check if dictionary exists
virtual bool hasDictionary(Language const *) const = 0;
/// how many valid dictionaries were found
virtual int numDictionaries() const = 0;
/// if speller can spell check whole paragraph return true
virtual bool canCheckParagraph() const { return false; }

View File

@ -375,6 +375,17 @@ void SpellcheckerWidget::Private::check()
BufferView * bv = gv_->documentBufferView();
if (!bv || bv->buffer().text().empty())
return;
SpellChecker * speller = theSpellChecker();
if (speller && !speller->hasDictionary(bv->buffer().language())) {
int dsize = speller->numDictionaries();
if (0 == dsize) {
dv_->hide();
QMessageBox::information(p,
qt_("Spell Checker"),
qt_("Spell checker has no dictionaries."));
return;
}
}
DocIterator from = bv->cursor();
DocIterator to;

View File

@ -808,6 +808,9 @@ void MenuDefinition::expandSpellingSuggestions(BufferView const * bv)
FuncRequest(LFUN_SPELLING_REMOVE, arg)));
}
break;
case SpellChecker::NO_DICTIONARY:
LYXERR(Debug::GUI, "No dictionary for language " + from_ascii(wl.lang()->lang()));
// FALLTHROUGH
case SpellChecker::WORD_OK:
case SpellChecker::COMPOUND_WORD:
case SpellChecker::ROOT_FOUND:

View File

@ -65,6 +65,11 @@ What's new
- Display some commands from mathtools.sty natively (bug 7949).
- Add the directory /usr/share/myspell as default location for dictionary
lookup of hunspell spell checker backend (a common location on linux).
Detect value change of preferences path to hunspell dictionaries
to avoid the need for a restart. This is related to bug 7884.
* DOCUMENTATION AND LOCALIZATION
@ -158,6 +163,8 @@ What's new
- Fix tabbar visibility in fullscreen mode when opening/closing files (bug 7963).
- Show a message box if the current spell checker has no dictionaries (bug 7884).
* DOCUMENTATION AND LOCALIZATION