From: Abdelrazak Younes Date: Sat, 4 Apr 2009 16:40:47 +0000 (+0000) Subject: More SpellChecker cleanups. X-Git-Tag: 2.0.0~6943 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=a4169da13995ce6f50528b30f0668b0c10756832;p=features.git 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 --- diff --git a/src/Buffer.cpp b/src/Buffer.cpp index c5e70a7144..04572db74b 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -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 diff --git a/src/Buffer.h b/src/Buffer.h index e50076f221..37382e5dff 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -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, diff --git a/src/frontends/qt4/GuiSpellchecker.cpp b/src/frontends/qt4/GuiSpellchecker.cpp index 5937e86693..0051aba140 100644 --- a/src/frontends/qt4/GuiSpellchecker.cpp +++ b/src/frontends/qt4/GuiSpellchecker.cpp @@ -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 -#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; - - 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)); + wordED->setText(toqstr(word_.word())); + suggestionsLW->clear(); - 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; - - 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(); + WordLangTuple word_lang; + docstring_list suggestions; + + 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; + + // end of document + if (from == to) { + showSummary(); + exitEarly_ = true; + return; } + word_ = word_lang; - LYXERR(Debug::GUI, "Found word \"" << to_utf8(word_.word()) << "\""); + 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()); - 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()); + 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 diff --git a/src/frontends/qt4/GuiSpellchecker.h b/src/frontends/qt4/GuiSpellchecker.h index e890b4c367..1aebefae3c 100644 --- a/src/frontends/qt4/GuiSpellchecker.h +++ b/src/frontends/qt4/GuiSpellchecker.h @@ -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