mirror of
https://git.lyx.org/repos/lyx.git
synced 2025-01-26 18:07:18 +00:00
More SpellChecker cleanups.
* Buffer::spellCheck() new method constructed from mutiple bits of GuiSpellchecker.cpp. * GuiSpellchecker: lots of simplifications. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@29090 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
1352592874
commit
a4169da139
@ -50,6 +50,7 @@
|
||||
#include "ParagraphParameters.h"
|
||||
#include "ParIterator.h"
|
||||
#include "PDFOptions.h"
|
||||
#include "SpellChecker.h"
|
||||
#include "sgml.h"
|
||||
#include "TexRow.h"
|
||||
#include "TexStream.h"
|
||||
@ -59,6 +60,7 @@
|
||||
#include "Undo.h"
|
||||
#include "VCBackend.h"
|
||||
#include "version.h"
|
||||
#include "WordLangTuple.h"
|
||||
#include "WordList.h"
|
||||
|
||||
#include "insets/InsetBibitem.h"
|
||||
@ -79,6 +81,7 @@
|
||||
#include "support/lassert.h"
|
||||
#include "support/convert.h"
|
||||
#include "support/debug.h"
|
||||
#include "support/docstring_list.h"
|
||||
#include "support/ExceptionMessage.h"
|
||||
#include "support/FileName.h"
|
||||
#include "support/FileNameList.h"
|
||||
@ -3115,8 +3118,41 @@ bool Buffer::nextWord(DocIterator & from, DocIterator & to,
|
||||
}
|
||||
to.forwardPos();
|
||||
}
|
||||
|
||||
from = to;
|
||||
word.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int Buffer::spellCheck(DocIterator & from, DocIterator & to,
|
||||
WordLangTuple & word_lang, docstring_list & suggestions) const
|
||||
{
|
||||
int progress = 0;
|
||||
SpellChecker::Result res = SpellChecker::OK;
|
||||
SpellChecker * speller = theSpellChecker();
|
||||
suggestions.clear();
|
||||
docstring word;
|
||||
while (nextWord(from, to, word)) {
|
||||
++progress;
|
||||
string lang_code = lyxrc.spellchecker_use_alt_lang
|
||||
? lyxrc.spellchecker_alt_lang
|
||||
: from.paragraph().getFontSettings(params(), from.pos()).language()->code();
|
||||
WordLangTuple wl(word, lang_code);
|
||||
res = speller->check(wl);
|
||||
// ... just bail out if the spellchecker reports an error.
|
||||
if (!speller->error().empty()) {
|
||||
throw ExceptionMessage(WarningException,
|
||||
_("The spellchecker has failed."), speller->error());
|
||||
}
|
||||
if (res != SpellChecker::OK && res != SpellChecker::IGNORED_WORD) {
|
||||
word_lang = wl;
|
||||
break;
|
||||
}
|
||||
from = to;
|
||||
}
|
||||
while (!(word = speller->nextMiss()).empty())
|
||||
suggestions.push_back(word);
|
||||
return progress;
|
||||
}
|
||||
|
||||
} // namespace lyx
|
||||
|
@ -28,6 +28,7 @@ class BiblioInfo;
|
||||
class BufferParams;
|
||||
class BufferSet;
|
||||
class DocIterator;
|
||||
class docstring_list;
|
||||
class ErrorItem;
|
||||
class ErrorList;
|
||||
class FuncRequest;
|
||||
@ -54,6 +55,7 @@ class TeXErrors;
|
||||
class TexRow;
|
||||
class TocBackend;
|
||||
class Undo;
|
||||
class WordLangTuple;
|
||||
|
||||
namespace frontend {
|
||||
class GuiBufferDelegate;
|
||||
@ -500,6 +502,9 @@ public:
|
||||
bool nextWord(DocIterator & from, DocIterator & to,
|
||||
docstring & word) const;
|
||||
|
||||
int spellCheck(DocIterator & from, DocIterator & to,
|
||||
WordLangTuple & word_lang, docstring_list & suggestions) const;
|
||||
|
||||
private:
|
||||
/// search for macro in local (buffer) table or in children
|
||||
MacroData const * getBufferMacro(docstring const & name,
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "Buffer.h"
|
||||
#include "BufferParams.h"
|
||||
#include "BufferView.h"
|
||||
#include "buffer_funcs.h"
|
||||
#include "Cursor.h"
|
||||
#include "CutAndPaste.h"
|
||||
#include "Language.h"
|
||||
@ -27,16 +28,14 @@
|
||||
|
||||
#include "support/debug.h"
|
||||
#include "support/docstring.h"
|
||||
#include "support/docstring_list.h"
|
||||
#include "support/ExceptionMessage.h"
|
||||
#include "support/gettext.h"
|
||||
#include "support/lstrings.h"
|
||||
#include "support/textutils.h"
|
||||
|
||||
#include <QListWidgetItem>
|
||||
|
||||
#if defined(USE_ASPELL)
|
||||
# include "ASpell_local.h"
|
||||
#endif
|
||||
|
||||
#include "SpellChecker.h"
|
||||
|
||||
#include "frontends/alert.h"
|
||||
@ -50,7 +49,7 @@ namespace frontend {
|
||||
|
||||
GuiSpellchecker::GuiSpellchecker(GuiView & lv)
|
||||
: GuiDialog(lv, "spellchecker", qt_("Spellchecker")), exitEarly_(false),
|
||||
oldprogress_(0), newprogress_(0), count_(0), speller_(0)
|
||||
progress_(0), count_(0)
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
@ -139,13 +138,15 @@ void GuiSpellchecker::updateContents()
|
||||
|
||||
void GuiSpellchecker::accept()
|
||||
{
|
||||
ignoreAll();
|
||||
theSpellChecker()->accept(word_);
|
||||
check();
|
||||
}
|
||||
|
||||
|
||||
void GuiSpellchecker::add()
|
||||
{
|
||||
insert();
|
||||
theSpellChecker()->insert(word_);
|
||||
check();
|
||||
}
|
||||
|
||||
|
||||
@ -161,30 +162,20 @@ void GuiSpellchecker::replace()
|
||||
}
|
||||
|
||||
|
||||
void GuiSpellchecker::partialUpdate(int state)
|
||||
void GuiSpellchecker::updateSuggestions(docstring_list & words)
|
||||
{
|
||||
switch (state) {
|
||||
case SPELL_PROGRESSED:
|
||||
spellcheckPR->setValue(oldprogress_);
|
||||
break;
|
||||
wordED->setText(toqstr(word_.word()));
|
||||
suggestionsLW->clear();
|
||||
|
||||
case SPELL_FOUND_WORD: {
|
||||
wordED->setText(toqstr(word_.word()));
|
||||
suggestionsLW->clear();
|
||||
|
||||
docstring w;
|
||||
while (!(w = speller_->nextMiss()).empty())
|
||||
suggestionsLW->addItem(toqstr(w));
|
||||
|
||||
if (suggestionsLW->count() == 0)
|
||||
suggestionChanged(new QListWidgetItem(wordED->text()));
|
||||
else
|
||||
suggestionChanged(suggestionsLW->item(0));
|
||||
|
||||
suggestionsLW->setCurrentRow(0);
|
||||
break;
|
||||
}
|
||||
if (words.empty() == 0) {
|
||||
suggestionChanged(new QListWidgetItem(wordED->text()));
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i != words.size(); ++i)
|
||||
suggestionsLW->addItem(toqstr(words[i]));
|
||||
|
||||
suggestionChanged(suggestionsLW->item(0));
|
||||
suggestionsLW->setCurrentRow(0);
|
||||
}
|
||||
|
||||
|
||||
@ -192,54 +183,21 @@ bool GuiSpellchecker::initialiseParams(string const &)
|
||||
{
|
||||
LYXERR(Debug::GUI, "Spellchecker::initialiseParams");
|
||||
|
||||
speller_ = theSpellChecker();
|
||||
if (!speller_)
|
||||
if (!theSpellChecker())
|
||||
return false;
|
||||
|
||||
// reset values to initial
|
||||
oldprogress_ = 0;
|
||||
newprogress_ = 0;
|
||||
DocIterator const begin = doc_iterator_begin(&buffer());
|
||||
Cursor const & cur = bufferview()->cursor();
|
||||
progress_ = countWords(begin, cur);
|
||||
total_ = progress_ + countWords(cur, doc_iterator_end(&buffer()));
|
||||
count_ = 0;
|
||||
|
||||
bool const success = speller_->error().empty();
|
||||
|
||||
if (!success) {
|
||||
Alert::error(_("Spellchecker error"),
|
||||
_("The spellchecker could not be started\n")
|
||||
+ speller_->error());
|
||||
speller_ = 0;
|
||||
}
|
||||
|
||||
return success;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void GuiSpellchecker::clearParams()
|
||||
{
|
||||
LYXERR(Debug::GUI, "Spellchecker::clearParams");
|
||||
speller_ = 0;
|
||||
}
|
||||
|
||||
|
||||
static WordLangTuple nextWord(Cursor & cur, ptrdiff_t & progress)
|
||||
{
|
||||
Buffer const & buf = cur.bv().buffer();
|
||||
cur.resetAnchor();
|
||||
docstring word;
|
||||
DocIterator from = cur;
|
||||
DocIterator to;
|
||||
if (!buf.nextWord(from, to, word))
|
||||
return WordLangTuple(docstring(), string());
|
||||
|
||||
cur.setCursor(from);
|
||||
cur.resetAnchor();
|
||||
cur.setCursor(to);
|
||||
cur.setSelection();
|
||||
string lang_code = lyxrc.spellchecker_use_alt_lang
|
||||
? lyxrc.spellchecker_alt_lang
|
||||
: from.paragraph().getFontSettings(buf.params(), cur.pos()).language()->code();
|
||||
++progress;
|
||||
return WordLangTuple(word, lang_code);
|
||||
}
|
||||
|
||||
|
||||
@ -247,72 +205,50 @@ void GuiSpellchecker::check()
|
||||
{
|
||||
LYXERR(Debug::GUI, "Check the spelling of a word");
|
||||
|
||||
SpellChecker::Result res = SpellChecker::OK;
|
||||
|
||||
Cursor cur = bufferview()->cursor();
|
||||
while (cur && cur.pos() && isLetter(cur))
|
||||
cur.backwardPos();
|
||||
|
||||
ptrdiff_t start = 0;
|
||||
ptrdiff_t total = 0;
|
||||
DocIterator it = doc_iterator_begin(&buffer());
|
||||
for (start = 1; it != cur; it.forwardPos())
|
||||
++start;
|
||||
|
||||
for (total = start; it; it.forwardPos())
|
||||
++total;
|
||||
|
||||
DocIterator from = bufferview()->cursor();
|
||||
while (from && from.pos() && isLetter(from))
|
||||
from.backwardPos();
|
||||
DocIterator to;
|
||||
exitEarly_ = false;
|
||||
WordLangTuple word_lang;
|
||||
docstring_list suggestions;
|
||||
|
||||
while (res == SpellChecker::OK || res == SpellChecker::IGNORED_WORD) {
|
||||
word_ = nextWord(cur, start);
|
||||
|
||||
// end of document
|
||||
if (word_.word().empty()) {
|
||||
showSummary();
|
||||
exitEarly_ = true;
|
||||
return;
|
||||
}
|
||||
|
||||
++count_;
|
||||
|
||||
// Update slider if and only if value has changed
|
||||
float progress = total ? float(start)/total : 1;
|
||||
newprogress_ = int(100.0 * progress);
|
||||
if (newprogress_!= oldprogress_) {
|
||||
LYXERR(Debug::GUI, "Updating spell progress.");
|
||||
oldprogress_ = newprogress_;
|
||||
// set progress bar
|
||||
partialUpdate(SPELL_PROGRESSED);
|
||||
}
|
||||
|
||||
res = speller_->check(word_);
|
||||
|
||||
// ... just bail out if the spellchecker reports an error.
|
||||
if (!speller_->error().empty()) {
|
||||
docstring const message =
|
||||
_("The spellchecker has failed.\n") + speller_->error();
|
||||
int progress;
|
||||
try {
|
||||
progress = buffer().spellCheck(from, to, word_lang, suggestions);
|
||||
} catch (ExceptionMessage const & message) {
|
||||
if (message.type_ == WarningException) {
|
||||
Alert::warning(message.title_, message.details_);
|
||||
slotClose();
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw message;
|
||||
}
|
||||
LYXERR(Debug::GUI, "Found word \"" << word_lang.word() << "\"");
|
||||
count_ += progress;
|
||||
progress_ += progress;
|
||||
|
||||
LYXERR(Debug::GUI, "Found word \"" << to_utf8(word_.word()) << "\"");
|
||||
// end of document
|
||||
if (from == to) {
|
||||
showSummary();
|
||||
exitEarly_ = true;
|
||||
return;
|
||||
}
|
||||
word_ = word_lang;
|
||||
|
||||
int const progress_bar = total_
|
||||
? int(100.0 * float(progress_)/total_) : 100;
|
||||
LYXERR(Debug::GUI, "Updating spell progress.");
|
||||
// set progress bar
|
||||
spellcheckPR->setValue(progress_bar);
|
||||
// set suggestions
|
||||
updateSuggestions(suggestions);
|
||||
|
||||
int const size = cur.selEnd().pos() - cur.selBegin().pos();
|
||||
cur.pos() -= size;
|
||||
BufferView * bv = const_cast<BufferView *>(bufferview());
|
||||
bv->putSelectionAt(cur, size, false);
|
||||
// FIXME: if we used a lfun like in find/replace, dispatch would do
|
||||
// that for us
|
||||
// FIXME: this Controller is very badly designed...
|
||||
bv->processUpdateFlags(Update::Force | Update::FitCursor);
|
||||
|
||||
// set suggestions
|
||||
if (res != SpellChecker::OK && res != SpellChecker::IGNORED_WORD) {
|
||||
LYXERR(Debug::GUI, "Found a word needing checking.");
|
||||
partialUpdate(SPELL_FOUND_WORD);
|
||||
}
|
||||
int const size = to.pos() - from.pos();
|
||||
BufferView * bv = const_cast<BufferView *>(bufferview());
|
||||
bv->putSelectionAt(from, size, false);
|
||||
}
|
||||
|
||||
|
||||
@ -356,20 +292,6 @@ void GuiSpellchecker::replaceAll(docstring const & replacement)
|
||||
}
|
||||
|
||||
|
||||
void GuiSpellchecker::insert()
|
||||
{
|
||||
speller_->insert(word_);
|
||||
check();
|
||||
}
|
||||
|
||||
|
||||
void GuiSpellchecker::ignoreAll()
|
||||
{
|
||||
speller_->accept(word_);
|
||||
check();
|
||||
}
|
||||
|
||||
|
||||
Dialog * createGuiSpellchecker(GuiView & lv) { return new GuiSpellchecker(lv); }
|
||||
|
||||
} // namespace frontend
|
||||
|
@ -23,6 +23,7 @@ class QListWidgetItem;
|
||||
|
||||
namespace lyx {
|
||||
|
||||
class docstring_list;
|
||||
class SpellChecker;
|
||||
|
||||
namespace frontend {
|
||||
@ -38,6 +39,7 @@ public Q_SLOTS:
|
||||
void suggestionChanged(QListWidgetItem *);
|
||||
|
||||
private Q_SLOTS:
|
||||
/// ignore all occurances of word
|
||||
void accept();
|
||||
void add();
|
||||
void ignore();
|
||||
@ -47,16 +49,10 @@ private Q_SLOTS:
|
||||
|
||||
private:
|
||||
/// update from controller
|
||||
void partialUpdate(int id);
|
||||
void updateSuggestions(docstring_list & words);
|
||||
///
|
||||
void updateContents();
|
||||
|
||||
///
|
||||
enum State {
|
||||
SPELL_PROGRESSED, //< update progress bar
|
||||
SPELL_FOUND_WORD //< found a bad word
|
||||
};
|
||||
|
||||
///
|
||||
bool initialiseParams(std::string const & data);
|
||||
///
|
||||
@ -75,8 +71,6 @@ private:
|
||||
void replaceAll(docstring const &);
|
||||
/// insert word in personal dictionary
|
||||
void insert();
|
||||
/// ignore all occurances of word
|
||||
void ignoreAll();
|
||||
/// check text until next misspelled/unknown word
|
||||
/// returns true when finished
|
||||
void check();
|
||||
@ -88,12 +82,10 @@ private:
|
||||
/// current word being checked and lang code
|
||||
WordLangTuple word_;
|
||||
/// values for progress
|
||||
int oldprogress_;
|
||||
int newprogress_;
|
||||
int total_;
|
||||
int progress_;
|
||||
/// word count
|
||||
int count_;
|
||||
/// The actual spellchecker object
|
||||
SpellChecker * speller_;
|
||||
};
|
||||
|
||||
} // namespace frontend
|
||||
|
Loading…
x
Reference in New Issue
Block a user