]> git.lyx.org Git - lyx.git/commitdiff
next one
authorAndré Pönitz <poenitz@gmx.net>
Sat, 6 Oct 2007 19:51:03 +0000 (19:51 +0000)
committerAndré Pönitz <poenitz@gmx.net>
Sat, 6 Oct 2007 19:51:03 +0000 (19:51 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@20797 a592a061-630c-0410-9148-cb99ea01b6c8

src/frontends/Dialogs.cpp
src/frontends/controllers/ControlSpellchecker.cpp [deleted file]
src/frontends/controllers/ControlSpellchecker.h [deleted file]
src/frontends/controllers/Makefile.am
src/frontends/qt4/Dialogs.cpp
src/frontends/qt4/GuiSpellchecker.cpp
src/frontends/qt4/GuiSpellchecker.h

index 8f1969553d518f01d96a7cc09874ca234c1d2069..9095d9236926810c0d55db67fa47260c91bc48de 100644 (file)
@@ -194,7 +194,7 @@ void Dialogs::checkStatus()
 
        for(; it != end; ++it) {
                Dialog * const dialog = it->second.get();
-               if (dialog->isVisibleView())
+               if (dialog && dialog->isVisibleView())
                        dialog->checkStatus();
        }
 }
diff --git a/src/frontends/controllers/ControlSpellchecker.cpp b/src/frontends/controllers/ControlSpellchecker.cpp
deleted file mode 100644 (file)
index 42e8897..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-/**
- * \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
diff --git a/src/frontends/controllers/ControlSpellchecker.h b/src/frontends/controllers/ControlSpellchecker.h
deleted file mode 100644 (file)
index 28e314c..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-// -*- 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
index 75587338c93d2dda4eff90fcd44de45ca5cc5190..ffb999b38e85417d816dfcc521bd4e4b0b28c540 100644 (file)
@@ -20,7 +20,6 @@ SOURCEFILES = \
        ControlPrint.cpp \
        ControlSearch.cpp \
        ControlSendto.cpp \
-       ControlSpellchecker.cpp \
        ControlThesaurus.cpp \
        ControlToc.cpp \
        frontend_helpers.cpp 
@@ -38,7 +37,6 @@ HEADERFILES = \
        ControlPrint.h \
        ControlSearch.h \
        ControlSendto.h \
-       ControlSpellchecker.h \
        ControlThesaurus.h \
        ControlToc.h \
        frontend_helpers.h
index 65be9a6835475af84c8a82c88f35995df1ce13ae..c98f957fccb010d013fc93910fbb4c819c54ba34 100644 (file)
@@ -30,7 +30,6 @@
 #include "GuiSearch.h"
 #include "GuiSendto.h"
 #include "GuiShowFile.h"
-#include "GuiSpellchecker.h"
 #include "GuiToc.h"
 #include "GuiView.h"
 #include "TocWidget.h"
@@ -141,110 +140,107 @@ Dialog * Dialogs::build(string const & name)
 {
        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;
 }
 
 
index 52302e418b5df6f6ea3fbc8018a52eca30124baf..2236de3ee50eb6c86e8bd9adb8f6d03e1729969d 100644 (file)
@@ -4,6 +4,7 @@
  * 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*)));
 
@@ -62,37 +98,13 @@ GuiSpellcheckerDialog::GuiSpellcheckerDialog(LyXView & lv)
 }
 
 
-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());
@@ -103,12 +115,12 @@ void GuiSpellcheckerDialog::suggestionChanged(QListWidgetItem * item)
 }
 
 
-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;
@@ -117,64 +129,64 @@ void GuiSpellcheckerDialog::replaceChanged(const QString & str)
 }
 
 
-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)
@@ -188,6 +200,283 @@ void GuiSpellcheckerDialog::partialUpdate(int state)
        }
 }
 
+
+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
 
index 1a9ff470a8feee17be234b7f3c60d7c7a9054e81..52fa3719f3ad57ea5e7d5b498c1c880215a678a0 100644 (file)
@@ -6,6 +6,7 @@
  *
  * \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();
 
@@ -46,14 +53,63 @@ private:
        /// 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