2006-03-05 17:24:44 +00:00
|
|
|
/**
|
2007-08-31 05:53:55 +00:00
|
|
|
* \file GuiSpellchecker.cpp
|
2006-03-05 17:24:44 +00:00
|
|
|
* This file is part of LyX, the document processor.
|
|
|
|
* Licence details can be found in the file COPYING.
|
|
|
|
*
|
|
|
|
* \author John Levon
|
2007-10-06 19:51:03 +00:00
|
|
|
* \author Edwin Leuven
|
2006-03-05 17:24:44 +00:00
|
|
|
*
|
|
|
|
* Full author contact details are available in file CREDITS.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2007-08-31 05:53:55 +00:00
|
|
|
#include "GuiSpellchecker.h"
|
2007-09-05 20:33:29 +00:00
|
|
|
|
2006-03-05 17:24:44 +00:00
|
|
|
#include "qt_helpers.h"
|
|
|
|
|
2007-10-06 19:51:03 +00:00
|
|
|
#include "Buffer.h"
|
|
|
|
#include "BufferParams.h"
|
|
|
|
#include "BufferView.h"
|
2009-04-04 16:40:47 +00:00
|
|
|
#include "buffer_funcs.h"
|
2007-10-06 19:51:03 +00:00
|
|
|
#include "Cursor.h"
|
|
|
|
#include "CutAndPaste.h"
|
|
|
|
#include "Language.h"
|
2009-03-29 21:18:16 +00:00
|
|
|
#include "LyX.h"
|
2007-10-06 19:51:03 +00:00
|
|
|
#include "LyXRC.h"
|
|
|
|
#include "Paragraph.h"
|
|
|
|
|
2008-02-18 07:14:42 +00:00
|
|
|
#include "support/debug.h"
|
2007-10-06 19:51:03 +00:00
|
|
|
#include "support/docstring.h"
|
2009-04-04 16:40:47 +00:00
|
|
|
#include "support/docstring_list.h"
|
|
|
|
#include "support/ExceptionMessage.h"
|
2008-02-18 07:14:42 +00:00
|
|
|
#include "support/gettext.h"
|
2007-11-13 23:21:29 +00:00
|
|
|
#include "support/lstrings.h"
|
2008-02-18 07:14:42 +00:00
|
|
|
#include "support/textutils.h"
|
2007-10-06 19:51:03 +00:00
|
|
|
|
2006-05-03 19:51:15 +00:00
|
|
|
#include <QListWidgetItem>
|
2007-04-24 15:32:14 +00:00
|
|
|
|
2009-03-29 19:49:52 +00:00
|
|
|
#include "SpellChecker.h"
|
2007-10-06 19:51:03 +00:00
|
|
|
|
|
|
|
#include "frontends/alert.h"
|
|
|
|
|
2007-12-12 10:16:00 +00:00
|
|
|
using namespace std;
|
2007-12-12 18:57:56 +00:00
|
|
|
using namespace lyx::support;
|
2007-10-06 19:51:03 +00:00
|
|
|
|
2006-03-05 17:24:44 +00:00
|
|
|
namespace lyx {
|
|
|
|
namespace frontend {
|
|
|
|
|
2007-10-06 19:51:03 +00:00
|
|
|
|
2007-11-23 09:44:02 +00:00
|
|
|
GuiSpellchecker::GuiSpellchecker(GuiView & lv)
|
2008-02-05 12:43:19 +00:00
|
|
|
: GuiDialog(lv, "spellchecker", qt_("Spellchecker")), exitEarly_(false),
|
2009-04-04 16:40:47 +00:00
|
|
|
progress_(0), count_(0)
|
2007-04-24 15:32:14 +00:00
|
|
|
{
|
|
|
|
setupUi(this);
|
|
|
|
|
2007-09-05 20:33:29 +00:00
|
|
|
connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
|
2007-11-06 13:40:31 +00:00
|
|
|
connect(replacePB, SIGNAL(clicked()), this, SLOT(replace()));
|
|
|
|
connect(ignorePB, SIGNAL(clicked()), this, SLOT(ignore()));
|
|
|
|
connect(replacePB_3, SIGNAL(clicked()), this, SLOT(accept()));
|
|
|
|
connect(addPB, SIGNAL(clicked()), this, SLOT(add()));
|
2007-04-24 15:32:14 +00:00
|
|
|
|
2007-10-06 19:51:03 +00:00
|
|
|
connect(replaceCO, SIGNAL(highlighted(QString)),
|
|
|
|
this, SLOT(replaceChanged(QString)));
|
2007-04-24 15:32:14 +00:00
|
|
|
connect(suggestionsLW, SIGNAL(itemDoubleClicked(QListWidgetItem*)),
|
2007-11-06 13:40:31 +00:00
|
|
|
this, SLOT(replace()));
|
2007-04-24 15:32:14 +00:00
|
|
|
connect(suggestionsLW, SIGNAL(itemClicked(QListWidgetItem*)),
|
|
|
|
this, SLOT(suggestionChanged(QListWidgetItem*)));
|
2007-09-05 20:33:29 +00:00
|
|
|
|
|
|
|
wordED->setReadOnly(true);
|
|
|
|
|
|
|
|
bc().setPolicy(ButtonPolicy::NoRepeatedApplyReadOnlyPolicy);
|
|
|
|
bc().setCancel(closePB);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-06 19:51:03 +00:00
|
|
|
void GuiSpellchecker::suggestionChanged(QListWidgetItem * item)
|
2007-04-24 15:32:14 +00:00
|
|
|
{
|
|
|
|
if (replaceCO->count() != 0)
|
|
|
|
replaceCO->setItemText(0, item->text());
|
|
|
|
else
|
|
|
|
replaceCO->addItem(item->text());
|
|
|
|
|
|
|
|
replaceCO->setCurrentIndex(0);
|
|
|
|
}
|
|
|
|
|
2007-09-05 20:33:29 +00:00
|
|
|
|
2007-10-06 19:51:03 +00:00
|
|
|
void GuiSpellchecker::replaceChanged(const QString & str)
|
2007-04-24 15:32:14 +00:00
|
|
|
{
|
2008-12-05 10:20:26 +00:00
|
|
|
if (suggestionsLW->currentItem()
|
|
|
|
&& suggestionsLW->currentItem()->text() == str)
|
2007-04-24 15:32:14 +00:00
|
|
|
return;
|
|
|
|
|
2007-10-06 19:51:03 +00:00
|
|
|
for (int i = 0; i != suggestionsLW->count(); ++i) {
|
2007-04-24 15:32:14 +00:00
|
|
|
if (suggestionsLW->item(i)->text() == str) {
|
|
|
|
suggestionsLW->setCurrentRow(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-06 19:51:03 +00:00
|
|
|
void GuiSpellchecker::reject()
|
2007-04-24 15:32:14 +00:00
|
|
|
{
|
2007-09-11 17:06:15 +00:00
|
|
|
slotClose();
|
2007-04-24 15:32:14 +00:00
|
|
|
QDialog::reject();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-06 19:51:03 +00:00
|
|
|
void GuiSpellchecker::updateContents()
|
2006-03-05 17:24:44 +00:00
|
|
|
{
|
2007-11-06 13:40:31 +00:00
|
|
|
// The clauses below are needed because the spellchecker
|
|
|
|
// has many flaws (see bugs 1950, 2218).
|
|
|
|
// Basically, we have to distinguish the case where a
|
|
|
|
// spellcheck has already been performed for the whole
|
|
|
|
// document (exitEarly() == true, isVisible() == false)
|
|
|
|
// from the rest (exitEarly() == false, isVisible() == true).
|
|
|
|
// FIXME: rewrite the whole beast!
|
|
|
|
static bool check_after_early_exit;
|
|
|
|
if (exitEarly()) {
|
|
|
|
// a spellcheck has already been performed,
|
2007-10-06 19:51:03 +00:00
|
|
|
check();
|
2007-11-06 13:40:31 +00:00
|
|
|
check_after_early_exit = true;
|
|
|
|
}
|
|
|
|
else if (isVisible()) {
|
|
|
|
// the above check triggers a second update,
|
|
|
|
// and isVisible() is true then. Prevent a
|
|
|
|
// second check that skips the first word
|
|
|
|
if (check_after_early_exit)
|
|
|
|
// don't check, but reset the bool.
|
|
|
|
// business as usual after this.
|
|
|
|
check_after_early_exit = false;
|
|
|
|
else
|
|
|
|
// perform spellcheck (default case)
|
|
|
|
check();
|
|
|
|
}
|
2006-03-05 17:24:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-06 19:51:03 +00:00
|
|
|
void GuiSpellchecker::accept()
|
2006-03-05 17:24:44 +00:00
|
|
|
{
|
2009-04-04 16:40:47 +00:00
|
|
|
theSpellChecker()->accept(word_);
|
|
|
|
check();
|
2006-03-05 17:24:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-06 19:51:03 +00:00
|
|
|
void GuiSpellchecker::add()
|
2006-03-05 17:24:44 +00:00
|
|
|
{
|
2009-04-04 16:40:47 +00:00
|
|
|
theSpellChecker()->insert(word_);
|
|
|
|
check();
|
2006-03-05 17:24:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-06 19:51:03 +00:00
|
|
|
void GuiSpellchecker::ignore()
|
2006-03-05 17:24:44 +00:00
|
|
|
{
|
2007-10-06 19:51:03 +00:00
|
|
|
check();
|
2006-03-05 17:24:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-06 19:51:03 +00:00
|
|
|
void GuiSpellchecker::replace()
|
2006-03-05 17:24:44 +00:00
|
|
|
{
|
2007-10-06 19:51:03 +00:00
|
|
|
replace(qstring_to_ucs4(replaceCO->currentText()));
|
2006-03-05 17:24:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-04-04 16:40:47 +00:00
|
|
|
void GuiSpellchecker::updateSuggestions(docstring_list & words)
|
2006-03-05 17:24:44 +00:00
|
|
|
{
|
2009-04-04 16:40:47 +00:00
|
|
|
wordED->setText(toqstr(word_.word()));
|
|
|
|
suggestionsLW->clear();
|
2006-03-05 17:24:44 +00:00
|
|
|
|
2009-04-04 16:40:47 +00:00
|
|
|
if (words.empty() == 0) {
|
|
|
|
suggestionChanged(new QListWidgetItem(wordED->text()));
|
|
|
|
return;
|
2006-03-05 17:24:44 +00:00
|
|
|
}
|
2009-04-04 16:40:47 +00:00
|
|
|
for (size_t i = 0; i != words.size(); ++i)
|
|
|
|
suggestionsLW->addItem(toqstr(words[i]));
|
|
|
|
|
|
|
|
suggestionChanged(suggestionsLW->item(0));
|
|
|
|
suggestionsLW->setCurrentRow(0);
|
2006-03-05 17:24:44 +00:00
|
|
|
}
|
|
|
|
|
2007-10-06 19:51:03 +00:00
|
|
|
|
2007-12-12 19:28:07 +00:00
|
|
|
bool GuiSpellchecker::initialiseParams(string const &)
|
2007-10-06 19:51:03 +00:00
|
|
|
{
|
2007-11-15 20:04:51 +00:00
|
|
|
LYXERR(Debug::GUI, "Spellchecker::initialiseParams");
|
2007-10-06 19:51:03 +00:00
|
|
|
|
2009-04-04 16:40:47 +00:00
|
|
|
if (!theSpellChecker())
|
2007-10-06 19:51:03 +00:00
|
|
|
return false;
|
|
|
|
|
2009-04-04 16:40:47 +00:00
|
|
|
DocIterator const begin = doc_iterator_begin(&buffer());
|
|
|
|
Cursor const & cur = bufferview()->cursor();
|
|
|
|
progress_ = countWords(begin, cur);
|
|
|
|
total_ = progress_ + countWords(cur, doc_iterator_end(&buffer()));
|
2007-10-06 19:51:03 +00:00
|
|
|
count_ = 0;
|
2009-04-04 16:40:47 +00:00
|
|
|
return true;
|
2007-10-06 19:51:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GuiSpellchecker::clearParams()
|
|
|
|
{
|
2007-11-15 20:04:51 +00:00
|
|
|
LYXERR(Debug::GUI, "Spellchecker::clearParams");
|
2007-10-06 19:51:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GuiSpellchecker::check()
|
|
|
|
{
|
2007-11-15 20:04:51 +00:00
|
|
|
LYXERR(Debug::GUI, "Check the spelling of a word");
|
2007-10-06 19:51:03 +00:00
|
|
|
|
2009-04-04 16:40:47 +00:00
|
|
|
DocIterator from = bufferview()->cursor();
|
|
|
|
while (from && from.pos() && isLetter(from))
|
|
|
|
from.backwardPos();
|
|
|
|
DocIterator to;
|
2007-10-06 19:51:03 +00:00
|
|
|
exitEarly_ = false;
|
2009-04-04 16:40:47 +00:00
|
|
|
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_);
|
2009-03-29 21:18:16 +00:00
|
|
|
slotClose();
|
2007-10-06 19:51:03 +00:00
|
|
|
return;
|
2009-04-04 16:40:47 +00:00
|
|
|
}
|
|
|
|
throw message;
|
|
|
|
}
|
|
|
|
LYXERR(Debug::GUI, "Found word \"" << word_lang.word() << "\"");
|
|
|
|
count_ += progress;
|
|
|
|
progress_ += progress;
|
|
|
|
|
|
|
|
// end of document
|
|
|
|
if (from == to) {
|
|
|
|
showSummary();
|
|
|
|
exitEarly_ = true;
|
|
|
|
return;
|
2007-10-06 19:51:03 +00:00
|
|
|
}
|
2009-04-04 16:40:47 +00:00
|
|
|
word_ = word_lang;
|
2007-10-06 19:51:03 +00:00
|
|
|
|
2009-04-04 16:40:47 +00:00
|
|
|
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);
|
2007-10-06 19:51:03 +00:00
|
|
|
|
|
|
|
// FIXME: if we used a lfun like in find/replace, dispatch would do
|
|
|
|
// that for us
|
2009-04-04 16:40:47 +00:00
|
|
|
int const size = to.pos() - from.pos();
|
|
|
|
BufferView * bv = const_cast<BufferView *>(bufferview());
|
|
|
|
bv->putSelectionAt(from, size, false);
|
2007-10-06 19:51:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GuiSpellchecker::showSummary()
|
|
|
|
{
|
2009-03-29 21:18:16 +00:00
|
|
|
if (count_ == 0) {
|
2007-10-09 21:21:01 +00:00
|
|
|
slotClose();
|
2007-10-06 19:51:03 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
docstring message;
|
|
|
|
if (count_ != 1)
|
|
|
|
message = bformat(_("%1$d words checked."), count_);
|
|
|
|
else
|
|
|
|
message = _("One word checked.");
|
|
|
|
|
2007-10-09 21:21:01 +00:00
|
|
|
slotClose();
|
2007-10-06 19:51:03 +00:00
|
|
|
Alert::information(_("Spelling check completed"), message);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GuiSpellchecker::replace(docstring const & replacement)
|
|
|
|
{
|
2007-11-15 20:04:51 +00:00
|
|
|
LYXERR(Debug::GUI, "GuiSpellchecker::replace("
|
|
|
|
<< to_utf8(replacement) << ")");
|
2008-09-29 10:52:17 +00:00
|
|
|
BufferView * bv = const_cast<BufferView *>(bufferview());
|
|
|
|
cap::replaceSelectionWithString(bv->cursor(), replacement, true);
|
|
|
|
bv->buffer().markDirty();
|
2007-10-06 19:51:03 +00:00
|
|
|
// If we used an LFUN, we would not need that
|
2008-09-29 10:52:17 +00:00
|
|
|
bv->processUpdateFlags(Update::Force | Update::FitCursor);
|
2007-10-06 19:51:03 +00:00
|
|
|
// fix up the count
|
|
|
|
--count_;
|
|
|
|
check();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GuiSpellchecker::replaceAll(docstring const & replacement)
|
|
|
|
{
|
|
|
|
// TODO: add to list
|
|
|
|
replace(replacement);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-23 09:44:02 +00:00
|
|
|
Dialog * createGuiSpellchecker(GuiView & lv) { return new GuiSpellchecker(lv); }
|
2007-10-06 19:51:03 +00:00
|
|
|
|
2006-03-05 17:24:44 +00:00
|
|
|
} // namespace frontend
|
|
|
|
} // namespace lyx
|
2007-04-24 15:32:14 +00:00
|
|
|
|
2008-11-14 14:28:50 +00:00
|
|
|
#include "moc_GuiSpellchecker.cpp"
|