for(; it != end; ++it) {
Dialog * const dialog = it->second.get();
- if (dialog->isVisibleView())
+ if (dialog && dialog->isVisibleView())
dialog->checkStatus();
}
}
+++ /dev/null
-/**
- * \file ControlSpellchecker.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Edwin Leuven
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "ControlSpellchecker.h"
-
-#include "Buffer.h"
-#include "BufferParams.h"
-#include "BufferView.h"
-#include "Cursor.h"
-#include "CutAndPaste.h"
-#include "debug.h"
-#include "gettext.h"
-#include "Language.h"
-#include "LyXRC.h"
-#include "Paragraph.h"
-
-#if defined(USE_ASPELL)
-# include "ASpell_local.h"
-#elif defined(USE_PSPELL)
-# include "PSpell.h"
-#endif
-
-#if defined(USE_ISPELL)
-# include "ISpell.h"
-#else
-# include "SpellBase.h"
-#endif
-
-#include "support/textutils.h"
-#include "support/convert.h"
-#include "support/docstring.h"
-
-#include "frontends/alert.h"
-// FIXME: those two headers are needed because of the
-// WorkArea::redraw() call below.
-#include "frontends/LyXView.h"
-#include "frontends/WorkArea.h"
-
-using std::advance;
-using std::distance;
-using std::endl;
-using std::string;
-
-namespace lyx {
-
-using support::bformat;
-using support::contains;
-
-namespace frontend {
-
-
-ControlSpellchecker::ControlSpellchecker(Dialog & parent)
- : Controller(parent), exitEarly_(false),
- oldval_(0), newvalue_(0), count_(0), speller_(0)
-{
-}
-
-
-ControlSpellchecker::~ControlSpellchecker()
-{
- delete speller_;
-}
-
-
-static SpellBase * getSpeller(BufferParams const & bp)
-{
- string lang = (lyxrc.isp_use_alt_lang)
- ? lyxrc.isp_alt_lang
- : bp.language->code();
-
-#if defined(USE_ASPELL)
- if (lyxrc.use_spell_lib)
- return new ASpell(bp, lang);
-#elif defined(USE_PSPELL)
- if (lyxrc.use_spell_lib)
- return new PSpell(bp, lang);
-#endif
-
-#if defined(USE_ISPELL)
- lang = lyxrc.isp_use_alt_lang ?
- lyxrc.isp_alt_lang : bp.language->lang();
-
- return new ISpell(bp, lang);
-#else
- return new SpellBase;
-#endif
-}
-
-
-bool ControlSpellchecker::initialiseParams(std::string const &)
-{
- LYXERR(Debug::GUI) << "Spellchecker::initialiseParams" << endl;
-
- speller_ = getSpeller(buffer().params());
- if (!speller_)
- return false;
-
- // reset values to initial
- oldval_ = 0;
- newvalue_ = 0;
- count_ = 0;
-
- bool const success = speller_->error().empty();
-
- if (!success) {
- Alert::error(_("Spellchecker error"),
- _("The spellchecker could not be started\n")
- + speller_->error());
- delete speller_;
- speller_ = 0;
- }
-
- return success;
-}
-
-
-void ControlSpellchecker::clearParams()
-{
- LYXERR(Debug::GUI) << "Spellchecker::clearParams" << endl;
- delete speller_;
- speller_ = 0;
-}
-
-
-static bool isLetter(DocIterator const & dit)
-{
- return dit.inTexted()
- && dit.inset().allowSpellCheck()
- && dit.pos() != dit.lastpos()
- && (dit.paragraph().isLetter(dit.pos())
- // We want to pass the ' and escape chars to ispell
- || contains(from_utf8(lyxrc.isp_esc_chars + '\''),
- dit.paragraph().getChar(dit.pos())))
- && !dit.paragraph().isDeleted(dit.pos());
-}
-
-
-static WordLangTuple nextWord(Cursor & cur, ptrdiff_t & progress)
-{
- BufferParams const & bp = cur.bv().buffer().params();
- bool inword = false;
- bool ignoreword = false;
- cur.resetAnchor();
- docstring word;
- string lang_code;
-
- while (cur.depth()) {
- if (isLetter(cur)) {
- if (!inword) {
- inword = true;
- ignoreword = false;
- cur.resetAnchor();
- word.clear();
- lang_code = cur.paragraph().getFontSettings(bp, cur.pos()).language()->code();
- }
- // Insets like optional hyphens and ligature
- // break are part of a word.
- if (!cur.paragraph().isInset(cur.pos())) {
- Paragraph::value_type const c =
- cur.paragraph().getChar(cur.pos());
- word += c;
- if (isDigit(c))
- ignoreword = true;
- }
- } else { // !isLetter(cur)
- if (inword)
- if (!word.empty() && !ignoreword) {
- cur.setSelection();
- return WordLangTuple(word, lang_code);
- }
- inword = false;
- }
-
- cur.forwardPos();
- ++progress;
- }
-
- return WordLangTuple(docstring(), string());
-}
-
-
-void ControlSpellchecker::check()
-{
- LYXERR(Debug::GUI) << "Check the spelling of a word" << endl;
-
- SpellBase::Result res = SpellBase::OK;
-
- Cursor cur = bufferview()->cursor();
- while (cur && cur.pos() && isLetter(cur))
- cur.backwardPos();
-
- ptrdiff_t start = 0;
- ptrdiff_t total = 0;
- DocIterator it = DocIterator(buffer().inset());
- for (start = 0; it != cur; it.forwardPos())
- ++start;
-
- for (total = start; it; it.forwardPos())
- ++total;
-
- exitEarly_ = false;
-
- while (res == SpellBase::OK || res == SpellBase::IGNORED_WORD) {
- word_ = nextWord(cur, start);
-
- // end of document
- if (getWord().empty()) {
- showSummary();
- exitEarly_ = true;
- return;
- }
-
- ++count_;
-
- // Update slider if and only if value has changed
- float progress = total ? float(start)/total : 1;
- newvalue_ = int(100.0 * progress);
- if (newvalue_!= oldval_) {
- LYXERR(Debug::GUI) << "Updating spell progress." << endl;
- oldval_ = newvalue_;
- // set progress bar
- dialog().partialUpdateView(SPELL_PROGRESSED);
- }
-
- // speller might be dead ...
- if (!checkAlive())
- return;
-
- res = speller_->check(word_);
-
- // ... or it might just be reporting an error
- if (!checkAlive())
- return;
- }
-
- LYXERR(Debug::GUI) << "Found word \"" << to_utf8(getWord()) << "\"" << endl;
-
- int const size = cur.selEnd().pos() - cur.selBegin().pos();
- cur.pos() -= size;
- bufferview()->putSelectionAt(cur, size, false);
- // FIXME: if we used a lfun like in find/replace, dispatch would do
- // that for us
- bufferview()->update();
- // FIXME: this Controller is very badly designed...
- lyxview().currentWorkArea()->redraw();
-
- // set suggestions
- if (res != SpellBase::OK && res != SpellBase::IGNORED_WORD) {
- LYXERR(Debug::GUI) << "Found a word needing checking." << endl;
- dialog().partialUpdateView(SPELL_FOUND_WORD);
- }
-}
-
-
-bool ControlSpellchecker::checkAlive()
-{
- if (speller_->alive() && speller_->error().empty())
- return true;
-
- docstring message;
- if (speller_->error().empty())
- message = _("The spellchecker has died for some reason.\n"
- "Maybe it has been killed.");
- else
- message = _("The spellchecker has failed.\n") + speller_->error();
-
- dialog().slotClose();
-
- Alert::error(_("The spellchecker has failed"), message);
- return false;
-}
-
-
-void ControlSpellchecker::showSummary()
-{
- if (!checkAlive() || count_ == 0) {
- dialog().slotClose();
- return;
- }
-
- docstring message;
- if (count_ != 1)
- message = bformat(_("%1$d words checked."), count_);
- else
- message = _("One word checked.");
-
- dialog().slotClose();
- Alert::information(_("Spelling check completed"), message);
-}
-
-
-void ControlSpellchecker::replace(docstring const & replacement)
-{
- LYXERR(Debug::GUI) << "ControlSpellchecker::replace("
- << to_utf8(replacement) << ")" << std::endl;
- cap::replaceSelectionWithString(bufferview()->cursor(), replacement, true);
- buffer().markDirty();
- // If we used an LFUN, we would not need that
- bufferview()->update();
- // fix up the count
- --count_;
- check();
-}
-
-
-void ControlSpellchecker::replaceAll(docstring const & replacement)
-{
- // TODO: add to list
- replace(replacement);
-}
-
-
-void ControlSpellchecker::insert()
-{
- speller_->insert(word_);
- check();
-}
-
-
-docstring const ControlSpellchecker::getSuggestion() const
-{
- return speller_->nextMiss();
-}
-
-
-docstring const ControlSpellchecker::getWord() const
-{
- return word_.word();
-}
-
-
-void ControlSpellchecker::ignoreAll()
-{
- speller_->accept(word_);
- check();
-}
-
-} // namespace frontend
-} // namespace lyx
+++ /dev/null
-// -*- C++ -*-
-/**
- * \file ControlSpellchecker.h
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Edwin Leuven
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#ifndef CONTROLSPELLCHECKER_H
-#define CONTROLSPELLCHECKER_H
-
-#include "Dialog.h"
-#include "WordLangTuple.h"
-
-
-namespace lyx {
-
-class SpellBase;
-
-namespace frontend {
-
-/** A controller for Spellchecker dialogs.
- */
-class ControlSpellchecker : public Controller
-{
-public:
- enum State {
- SPELL_PROGRESSED, //< update progress bar
- SPELL_FOUND_WORD //< found a bad word
- };
-
- ControlSpellchecker(Dialog &);
- ~ControlSpellchecker();
- ///
- virtual bool initialiseParams(std::string const & data);
- ///
- virtual void clearParams();
- /// Not needed here
- virtual void dispatchParams() {}
- ///
- virtual bool isBufferDependent() const { return true; }
- ///
- virtual bool exitEarly() const { return exitEarly_; }
-
- /// replace word with replacement
- void replace(docstring const &);
-
- /// replace all occurances of word
- 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();
-
- /// get suggestion
- docstring const getSuggestion() const;
-
- /// get word
- docstring const getWord() const;
-
- /// returns progress value
- int getProgress() const { return oldval_; }
-
- /// returns word count
- int getCount() const { return count_; }
-
-private:
- /// give error message is spellchecker dies
- bool checkAlive();
-
- /// show count of checked words at normal exit
- void showSummary();
-
-private:
- /// set to true when spellchecking is finished
- bool exitEarly_;
-
- /// current word being checked and lang code
- WordLangTuple word_;
-
- /// values for progress
- int oldval_;
- int newvalue_;
-
- /// word count
- int count_;
-
- /// The actual spellchecker object
- SpellBase * speller_;
-};
-
-} // namespace frontend
-} // namespace lyx
-
-#endif // CONTROLSPELLCHECKER_H
ControlPrint.cpp \
ControlSearch.cpp \
ControlSendto.cpp \
- ControlSpellchecker.cpp \
ControlThesaurus.cpp \
ControlToc.cpp \
frontend_helpers.cpp
ControlPrint.h \
ControlSearch.h \
ControlSendto.h \
- ControlSpellchecker.h \
ControlThesaurus.h \
ControlToc.h \
frontend_helpers.h
#include "GuiSearch.h"
#include "GuiSendto.h"
#include "GuiShowFile.h"
-#include "GuiSpellchecker.h"
#include "GuiToc.h"
#include "GuiView.h"
#include "TocWidget.h"
{
BOOST_ASSERT(isValidName(name));
- Dialog * dialog = 0;
GuiViewBase & guiview = static_cast<GuiViewBase &>(lyxview_);
- if (name == "aboutlyx") {
- dialog = createGuiAbout(lyxview_);
- } else if (name == "bibitem") {
- dialog = new GuiBibitemDialog(lyxview_);
- } else if (name == "bibtex") {
- dialog = createGuiBibtex(lyxview_);
- } else if (name == "box") {
- dialog = createGuiBox(lyxview_);
- } else if (name == "branch") {
- dialog = createGuiBranch(lyxview_);
- } else if (name == "changes") {
- dialog = createGuiChanges(lyxview_);
- } else if (name == "character") {
- dialog = createGuiCharacter(lyxview_);
- } else if (name == "citation") {
- dialog = createGuiCitation(lyxview_);
- } else if (name == "document") {
- dialog = new GuiDocumentDialog(lyxview_);
- } else if (name == "embedding") {
- dialog = createGuiEmbeddedFiles(lyxview_);
- } else if (name == "errorlist") {
- dialog = createGuiErrorList(lyxview_);
- } else if (name == "ert") {
- dialog = createGuiERT(lyxview_);
- } else if (name == "external") {
- dialog = new GuiExternalDialog(lyxview_);
- } else if (name == "file") {
- dialog = createGuiShowFile(lyxview_);
- } else if (name == "findreplace") {
- dialog = new GuiSearchDialog(lyxview_);
- } else if (name == "float") {
- dialog = createGuiFloat(lyxview_);
- } else if (name == "graphics") {
- dialog = new GuiGraphicsDialog(lyxview_);
- } else if (name == "include") {
- dialog = createGuiInclude(lyxview_);
- } else if (name == "index") {
- dialog = new GuiIndexDialog(lyxview_);
- } else if (name == "nomenclature") {
- dialog = new GuiNomenclDialog(lyxview_);
- } else if (name == "label") {
- dialog = new GuiLabelDialog(lyxview_);
- } else if (name == "log") {
- dialog = createGuiLog(lyxview_);
- } else if (name == "view-source") {
- dialog = createGuiViewSource(lyxview_);
- } else if (name == "mathdelimiter") {
- dialog = new GuiDelimiterDialog(lyxview_);
- } else if (name == "mathmatrix") {
- dialog = new GuiMathMatrixDialog(lyxview_);
- } else if (name == "note") {
- dialog = createGuiNote(lyxview_);
- } else if (name == "paragraph") {
+ if (name == "aboutlyx")
+ return createGuiAbout(lyxview_);
+ if (name == "bibitem")
+ return new GuiBibitemDialog(lyxview_);
+ if (name == "bibtex")
+ return createGuiBibtex(lyxview_);
+ if (name == "box")
+ return createGuiBox(lyxview_);
+ if (name == "branch")
+ return createGuiBranch(lyxview_);
+ if (name == "changes")
+ return createGuiChanges(lyxview_);
+ if (name == "character")
+ return createGuiCharacter(lyxview_);
+ if (name == "citation")
+ return createGuiCitation(lyxview_);
+ if (name == "document")
+ return new GuiDocumentDialog(lyxview_);
+ if (name == "embedding")
+ return createGuiEmbeddedFiles(lyxview_);
+ if (name == "errorlist")
+ return createGuiErrorList(lyxview_);
+ if (name == "ert")
+ return createGuiERT(lyxview_);
+ if (name == "external")
+ return new GuiExternalDialog(lyxview_);
+ if (name == "file")
+ return createGuiShowFile(lyxview_);
+ if (name == "findreplace")
+ return new GuiSearchDialog(lyxview_);
+ if (name == "float")
+ return createGuiFloat(lyxview_);
+ if (name == "graphics")
+ return new GuiGraphicsDialog(lyxview_);
+ if (name == "include")
+ return createGuiInclude(lyxview_);
+ if (name == "index")
+ return new GuiIndexDialog(lyxview_);
+ if (name == "nomenclature")
+ return new GuiNomenclDialog(lyxview_);
+ if (name == "label")
+ return new GuiLabelDialog(lyxview_);
+ if (name == "log")
+ return createGuiLog(lyxview_);
+ if (name == "view-source")
+ return createGuiViewSource(lyxview_);
+ if (name == "mathdelimiter")
+ return new GuiDelimiterDialog(lyxview_);
+ if (name == "mathmatrix")
+ return new GuiMathMatrixDialog(lyxview_);
+ if (name == "note")
+ return createGuiNote(lyxview_);
+ if (name == "paragraph") {
#ifdef USE_DOCK_WIDGET
- DockView<ControlParagraph, GuiParagraph> * dv =
- new DockView<ControlParagraph, GuiParagraph>(guiview, name,
- Qt::TopDockWidgetArea);
+ return new DockView<ControlParagraph, GuiParagraph>(guiview, name,
+ Qt::TopDockWidgetArea);
#else
- DialogView<ControlParagraph, GuiParagraph> * dv =
- new DialogView<ControlParagraph, GuiParagraph>(guiview, name);
+ return new DialogView<ControlParagraph, GuiParagraph>(guiview, name);
#endif
- dialog = dv;
- } else if (name == "prefs") {
- dialog = new GuiPrefsDialog(lyxview_);
- } else if (name == "print") {
- dialog = new GuiPrintDialog(lyxview_);
- } else if (name == "ref") {
- dialog = createGuiRef(lyxview_);
- } else if (name == "sendto") {
- dialog = new GuiSendtoDialog(lyxview_);
- } else if (name == "spellchecker") {
- dialog = new GuiSpellcheckerDialog(lyxview_);
- } else if (name == "tabular") {
- dialog = createGuiTabular(lyxview_);
- } else if (name == "tabularcreate") {
- dialog = createGuiTabularCreate(lyxview_);
- } else if (name == "texinfo") {
- dialog = createGuiTexInfo(lyxview_);
+ }
+ if (name == "prefs")
+ return new GuiPrefsDialog(lyxview_);
+ if (name == "print")
+ return new GuiPrintDialog(lyxview_);
+ if (name == "ref")
+ return createGuiRef(lyxview_);
+ if (name == "sendto")
+ return new GuiSendtoDialog(lyxview_);
+ if (name == "spellchecker")
+ return createGuiSpellchecker(lyxview_);
+ if (name == "tabular")
+ return createGuiTabular(lyxview_);
+ if (name == "tabularcreate")
+ return createGuiTabularCreate(lyxview_);
+ if (name == "texinfo")
+ return createGuiTexInfo(lyxview_);
#ifdef HAVE_LIBAIKSAURUS
- } else if (name == "thesaurus") {
- dialog = new GuiThesaurusDialog(lyxview_);
+ if (name == "thesaurus")
+ return new GuiThesaurusDialog(lyxview_);
#endif
- } else if (name == "toc") {
+ if (name == "toc") {
#ifdef Q_WS_MACX
// On Mac show as a drawer at the right
- dialog = new DockView<GuiToc, TocWidget>(guiview, name,
+ return new DockView<GuiToc, TocWidget>(guiview, name,
Qt::RightDockWidgetArea, Qt::Drawer);
#else
- dialog = new DockView<GuiToc, TocWidget>(guiview, name);
+ return new DockView<GuiToc, TocWidget>(guiview, name);
#endif
- } else if (name == "url") {
- dialog = new GuiURLDialog(lyxview_);
- } else if (name == "vspace") {
- dialog = createGuiVSpace(lyxview_);
- } else if (name == "wrap") {
- dialog = createGuiWrap(lyxview_);
- } else if (name == "listings") {
- dialog = createGuiListings(lyxview_);
}
-
- return dialog;
+ if (name == "url")
+ return new GuiURLDialog(lyxview_);
+ if (name == "vspace")
+ return createGuiVSpace(lyxview_);
+ if (name == "wrap")
+ return createGuiWrap(lyxview_);
+ if (name == "listings")
+ return createGuiListings(lyxview_);
+
+ return 0;
}
* Licence details can be found in the file COPYING.
*
* \author John Levon
+ * \author Edwin Leuven
*
* Full author contact details are available in file CREDITS.
*/
#include "GuiSpellchecker.h"
-#include "ControlSpellchecker.h"
#include "qt_helpers.h"
+#include "Buffer.h"
+#include "BufferParams.h"
+#include "BufferView.h"
+#include "Cursor.h"
+#include "CutAndPaste.h"
+#include "debug.h"
+#include "gettext.h"
+#include "Language.h"
+#include "LyXRC.h"
+#include "Paragraph.h"
+
+#include "support/textutils.h"
+#include "support/convert.h"
+#include "support/docstring.h"
+
#include <QProgressBar>
#include <QLineEdit>
#include <QPushButton>
#include <QTextCharFormat>
#include <QTextDocument>
-
+#if defined(USE_ASPELL)
+# include "ASpell_local.h"
+#elif defined(USE_PSPELL)
+# include "PSpell.h"
+#endif
+
+#if defined(USE_ISPELL)
+# include "ISpell.h"
+#else
+# include "SpellBase.h"
+#endif
+
+#include "frontends/alert.h"
+// FIXME: those two headers are needed because of the
+// WorkArea::redraw() call below.
+#include "frontends/LyXView.h"
+#include "frontends/WorkArea.h"
+
+using std::advance;
+using std::distance;
+using std::endl;
using std::string;
+
namespace lyx {
namespace frontend {
-GuiSpellcheckerDialog::GuiSpellcheckerDialog(LyXView & lv)
- : GuiDialog(lv, "spellchecker")
+using support::bformat;
+using support::contains;
+
+GuiSpellchecker::GuiSpellchecker(LyXView & lv)
+ : GuiDialog(lv, "spellchecker"), Controller(this), exitEarly_(false),
+ oldval_(0), newvalue_(0), count_(0), speller_(0)
{
setupUi(this);
setViewTitle(_("Spellchecker"));
- setController(new ControlSpellchecker(*this));
+ setController(this, false);
connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
+ connect(replacePB, SIGNAL(clicked()), this, SLOT(replaceClicked()));
+ connect(ignorePB, SIGNAL(clicked()), this, SLOT(ignoreClicked()));
+ connect(replacePB_3, SIGNAL(clicked()), this, SLOT(acceptClicked()));
+ connect(addPB, SIGNAL(clicked()), this, SLOT(addClicked()));
- connect(replaceCO, SIGNAL(highlighted(const QString &)),
- this, SLOT(replaceChanged(const QString &)));
- connect(replacePB, SIGNAL(clicked()),
- this, SLOT(replaceClicked()));
- connect(ignorePB, SIGNAL(clicked()),
- this, SLOT(ignoreClicked()));
- connect(replacePB_3, SIGNAL(clicked()),
- this, SLOT(acceptClicked()));
- connect(addPB, SIGNAL(clicked()),
- this, SLOT(addClicked()));
+ connect(replaceCO, SIGNAL(highlighted(QString)),
+ this, SLOT(replaceChanged(QString)));
connect(suggestionsLW, SIGNAL(itemDoubleClicked(QListWidgetItem*)),
- this, SLOT(replaceClicked() ) );
+ this, SLOT(replaceClicked()));
connect(suggestionsLW, SIGNAL(itemClicked(QListWidgetItem*)),
this, SLOT(suggestionChanged(QListWidgetItem*)));
}
-ControlSpellchecker & GuiSpellcheckerDialog::controller()
+GuiSpellchecker::~GuiSpellchecker()
{
- return static_cast<ControlSpellchecker &>(GuiDialog::controller());
+ delete speller_;
}
-void GuiSpellcheckerDialog::acceptClicked()
-{
- accept();
-}
-
-
-void GuiSpellcheckerDialog::addClicked()
-{
- add();
-}
-
-
-void GuiSpellcheckerDialog::replaceClicked()
-{
- replace();
-}
-
-
-void GuiSpellcheckerDialog::ignoreClicked()
-{
- ignore();
-}
-
-
-void GuiSpellcheckerDialog::suggestionChanged(QListWidgetItem * item)
+void GuiSpellchecker::suggestionChanged(QListWidgetItem * item)
{
if (replaceCO->count() != 0)
replaceCO->setItemText(0, item->text());
}
-void GuiSpellcheckerDialog::replaceChanged(const QString & str)
+void GuiSpellchecker::replaceChanged(const QString & str)
{
if (suggestionsLW->currentItem()->text() == str)
return;
- for (int i = 0; i < suggestionsLW->count(); ++i) {
+ for (int i = 0; i != suggestionsLW->count(); ++i) {
if (suggestionsLW->item(i)->text() == str) {
suggestionsLW->setCurrentRow(i);
break;
}
-void GuiSpellcheckerDialog::closeEvent(QCloseEvent * e)
+void GuiSpellchecker::closeEvent(QCloseEvent * e)
{
slotClose();
GuiDialog::closeEvent(e);
}
-void GuiSpellcheckerDialog::reject()
+void GuiSpellchecker::reject()
{
slotClose();
QDialog::reject();
}
-void GuiSpellcheckerDialog::updateContents()
+void GuiSpellchecker::updateContents()
{
- if (isVisibleView() || controller().exitEarly())
- controller().check();
+ if (isVisibleView() || exitEarly())
+ check();
}
-void GuiSpellcheckerDialog::accept()
+void GuiSpellchecker::accept()
{
- controller().ignoreAll();
+ ignoreAll();
}
-void GuiSpellcheckerDialog::add()
+void GuiSpellchecker::add()
{
- controller().insert();
+ insert();
}
-void GuiSpellcheckerDialog::ignore()
+void GuiSpellchecker::ignore()
{
- controller().check();
+ check();
}
-void GuiSpellcheckerDialog::replace()
+void GuiSpellchecker::replace()
{
- controller().replace(qstring_to_ucs4(replaceCO->currentText()));
+ replace(qstring_to_ucs4(replaceCO->currentText()));
}
-void GuiSpellcheckerDialog::partialUpdate(int state)
+void GuiSpellchecker::partialUpdate(int state)
{
switch (state) {
- case ControlSpellchecker::SPELL_PROGRESSED:
- spellcheckPR->setValue(controller().getProgress());
+ case SPELL_PROGRESSED:
+ spellcheckPR->setValue(getProgress());
break;
- case ControlSpellchecker::SPELL_FOUND_WORD: {
- wordED->setText(toqstr(controller().getWord()));
+ case SPELL_FOUND_WORD: {
+ wordED->setText(toqstr(getWord()));
suggestionsLW->clear();
docstring w;
- while (!(w = controller().getSuggestion()).empty())
+ while (!(w = getSuggestion()).empty())
suggestionsLW->addItem(toqstr(w));
if (suggestionsLW->count() == 0)
}
}
+
+static SpellBase * getSpeller(BufferParams const & bp)
+{
+ string lang = (lyxrc.isp_use_alt_lang)
+ ? lyxrc.isp_alt_lang
+ : bp.language->code();
+
+#if defined(USE_ASPELL)
+ if (lyxrc.use_spell_lib)
+ return new ASpell(bp, lang);
+#elif defined(USE_PSPELL)
+ if (lyxrc.use_spell_lib)
+ return new PSpell(bp, lang);
+#endif
+
+#if defined(USE_ISPELL)
+ lang = lyxrc.isp_use_alt_lang ?
+ lyxrc.isp_alt_lang : bp.language->lang();
+
+ return new ISpell(bp, lang);
+#else
+ return new SpellBase;
+#endif
+}
+
+
+bool GuiSpellchecker::initialiseParams(std::string const &)
+{
+ LYXERR(Debug::GUI) << "Spellchecker::initialiseParams" << endl;
+
+ speller_ = getSpeller(buffer().params());
+ if (!speller_)
+ return false;
+
+ // reset values to initial
+ oldval_ = 0;
+ newvalue_ = 0;
+ count_ = 0;
+
+ bool const success = speller_->error().empty();
+
+ if (!success) {
+ Alert::error(_("Spellchecker error"),
+ _("The spellchecker could not be started\n")
+ + speller_->error());
+ delete speller_;
+ speller_ = 0;
+ }
+
+ return success;
+}
+
+
+void GuiSpellchecker::clearParams()
+{
+ LYXERR(Debug::GUI) << "Spellchecker::clearParams" << endl;
+ delete speller_;
+ speller_ = 0;
+}
+
+
+static bool isLetter(DocIterator const & dit)
+{
+ return dit.inTexted()
+ && dit.inset().allowSpellCheck()
+ && dit.pos() != dit.lastpos()
+ && (dit.paragraph().isLetter(dit.pos())
+ // We want to pass the ' and escape chars to ispell
+ || contains(from_utf8(lyxrc.isp_esc_chars + '\''),
+ dit.paragraph().getChar(dit.pos())))
+ && !dit.paragraph().isDeleted(dit.pos());
+}
+
+
+static WordLangTuple nextWord(Cursor & cur, ptrdiff_t & progress)
+{
+ BufferParams const & bp = cur.bv().buffer().params();
+ bool inword = false;
+ bool ignoreword = false;
+ cur.resetAnchor();
+ docstring word;
+ string lang_code;
+
+ while (cur.depth()) {
+ if (isLetter(cur)) {
+ if (!inword) {
+ inword = true;
+ ignoreword = false;
+ cur.resetAnchor();
+ word.clear();
+ lang_code = cur.paragraph().getFontSettings(bp, cur.pos()).language()->code();
+ }
+ // Insets like optional hyphens and ligature
+ // break are part of a word.
+ if (!cur.paragraph().isInset(cur.pos())) {
+ Paragraph::value_type const c =
+ cur.paragraph().getChar(cur.pos());
+ word += c;
+ if (isDigit(c))
+ ignoreword = true;
+ }
+ } else { // !isLetter(cur)
+ if (inword)
+ if (!word.empty() && !ignoreword) {
+ cur.setSelection();
+ return WordLangTuple(word, lang_code);
+ }
+ inword = false;
+ }
+
+ cur.forwardPos();
+ ++progress;
+ }
+
+ return WordLangTuple(docstring(), string());
+}
+
+
+void GuiSpellchecker::check()
+{
+ LYXERR(Debug::GUI) << "Check the spelling of a word" << endl;
+
+ SpellBase::Result res = SpellBase::OK;
+
+ Cursor cur = bufferview()->cursor();
+ while (cur && cur.pos() && isLetter(cur))
+ cur.backwardPos();
+
+ ptrdiff_t start = 0;
+ ptrdiff_t total = 0;
+ DocIterator it = DocIterator(buffer().inset());
+ for (start = 0; it != cur; it.forwardPos())
+ ++start;
+
+ for (total = start; it; it.forwardPos())
+ ++total;
+
+ exitEarly_ = false;
+
+ while (res == SpellBase::OK || res == SpellBase::IGNORED_WORD) {
+ word_ = nextWord(cur, start);
+
+ // end of document
+ if (getWord().empty()) {
+ showSummary();
+ exitEarly_ = true;
+ return;
+ }
+
+ ++count_;
+
+ // Update slider if and only if value has changed
+ float progress = total ? float(start)/total : 1;
+ newvalue_ = int(100.0 * progress);
+ if (newvalue_!= oldval_) {
+ LYXERR(Debug::GUI) << "Updating spell progress." << endl;
+ oldval_ = newvalue_;
+ // set progress bar
+ dialog().partialUpdateView(SPELL_PROGRESSED);
+ }
+
+ // speller might be dead ...
+ if (!checkAlive())
+ return;
+
+ res = speller_->check(word_);
+
+ // ... or it might just be reporting an error
+ if (!checkAlive())
+ return;
+ }
+
+ LYXERR(Debug::GUI) << "Found word \"" << to_utf8(getWord()) << "\"" << endl;
+
+ int const size = cur.selEnd().pos() - cur.selBegin().pos();
+ cur.pos() -= size;
+ bufferview()->putSelectionAt(cur, size, false);
+ // FIXME: if we used a lfun like in find/replace, dispatch would do
+ // that for us
+ bufferview()->update();
+ // FIXME: this Controller is very badly designed...
+ lyxview().currentWorkArea()->redraw();
+
+ // set suggestions
+ if (res != SpellBase::OK && res != SpellBase::IGNORED_WORD) {
+ LYXERR(Debug::GUI) << "Found a word needing checking." << endl;
+ dialog().partialUpdateView(SPELL_FOUND_WORD);
+ }
+}
+
+
+bool GuiSpellchecker::checkAlive()
+{
+ if (speller_->alive() && speller_->error().empty())
+ return true;
+
+ docstring message;
+ if (speller_->error().empty())
+ message = _("The spellchecker has died for some reason.\n"
+ "Maybe it has been killed.");
+ else
+ message = _("The spellchecker has failed.\n") + speller_->error();
+
+ dialog().slotClose();
+
+ Alert::error(_("The spellchecker has failed"), message);
+ return false;
+}
+
+
+void GuiSpellchecker::showSummary()
+{
+ if (!checkAlive() || count_ == 0) {
+ dialog().slotClose();
+ return;
+ }
+
+ docstring message;
+ if (count_ != 1)
+ message = bformat(_("%1$d words checked."), count_);
+ else
+ message = _("One word checked.");
+
+ dialog().slotClose();
+ Alert::information(_("Spelling check completed"), message);
+}
+
+
+void GuiSpellchecker::replace(docstring const & replacement)
+{
+ LYXERR(Debug::GUI) << "GuiSpellchecker::replace("
+ << to_utf8(replacement) << ")" << std::endl;
+ cap::replaceSelectionWithString(bufferview()->cursor(), replacement, true);
+ buffer().markDirty();
+ // If we used an LFUN, we would not need that
+ bufferview()->update();
+ // fix up the count
+ --count_;
+ check();
+}
+
+
+void GuiSpellchecker::replaceAll(docstring const & replacement)
+{
+ // TODO: add to list
+ replace(replacement);
+}
+
+
+void GuiSpellchecker::insert()
+{
+ speller_->insert(word_);
+ check();
+}
+
+
+docstring GuiSpellchecker::getSuggestion() const
+{
+ return speller_->nextMiss();
+}
+
+
+docstring GuiSpellchecker::getWord() const
+{
+ return word_.word();
+}
+
+
+void GuiSpellchecker::ignoreAll()
+{
+ speller_->accept(word_);
+ check();
+}
+
+
+Dialog * createGuiSpellchecker(LyXView & lv) { return new GuiSpellchecker(lv); }
+
} // namespace frontend
} // namespace lyx
*
* \author John Levon
* \author Kalle Dalheimer
+ * \author Edwin Leuven
*
* Full author contact details are available in file CREDITS.
*/
#define GUISPELLCHECKER_H
#include "GuiDialog.h"
-#include "ControlSpellchecker.h"
#include "ui_SpellcheckerUi.h"
+#include "Dialog.h"
+#include "WordLangTuple.h"
class QListWidgetItem;
namespace lyx {
+
+class SpellBase;
+
namespace frontend {
-class GuiSpellcheckerDialog : public GuiDialog, public Ui::SpellcheckerUi
+class GuiSpellchecker
+ : public GuiDialog, public Ui::SpellcheckerUi, public Controller
{
Q_OBJECT
public:
- GuiSpellcheckerDialog(LyXView & lv);
+ GuiSpellchecker(LyXView & lv);
+ ~GuiSpellchecker();
public Q_SLOTS:
void suggestionChanged(QListWidgetItem *);
private Q_SLOTS:
- void acceptClicked();
- void addClicked();
- void replaceClicked();
- void ignoreClicked();
+ void accept();
+ void add();
+ void ignore();
+ void replace();
void replaceChanged(const QString &);
void reject();
/// update from controller
void partialUpdate(int id);
/// parent controller
- ControlSpellchecker & controller();
- ////
- void accept();
- void add();
- void ignore();
- void replace();
+ Controller & controller() { return *this; }
///
void updateContents();
+
+ ///
+ enum State {
+ SPELL_PROGRESSED, //< update progress bar
+ SPELL_FOUND_WORD //< found a bad word
+ };
+
+ ///
+ bool initialiseParams(std::string const & data);
+ ///
+ void clearParams();
+ /// Not needed here
+ void dispatchParams() {}
+ ///
+ bool isBufferDependent() const { return true; }
+ ///
+ bool exitEarly() const { return exitEarly_; }
+
+ /// replace word with replacement
+ void replace(docstring const &);
+
+ /// replace all occurances of word
+ 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();
+ /// get suggestion
+ docstring getSuggestion() const;
+ /// get word
+ docstring getWord() const;
+ /// returns progress value
+ int getProgress() const { return oldval_; }
+ /// returns word count
+ int getCount() const { return count_; }
+ /// give error message is spellchecker dies
+ bool checkAlive();
+ /// show count of checked words at normal exit
+ void showSummary();
+
+ /// set to true when spellchecking is finished
+ bool exitEarly_;
+ /// current word being checked and lang code
+ WordLangTuple word_;
+ /// values for progress
+ int oldval_;
+ int newvalue_;
+ /// word count
+ int count_;
+ /// The actual spellchecker object
+ SpellBase * speller_;
};
} // namespace frontend