Este artículo describe cómo agregar un corrector ortográfico a su aplicación Qt resaltando palabras mal escritas y la capacidad de reemplazarlas con variantes más adecuadas. Para ello se utiliza el diccionario hunspell .
Para resaltar palabras incorrectas de ortografía, se usa la clase QSyntaxHighlighter modificada y la clase QTextEdit modificada se usa para mostrar e ingresar texto .
En primer lugar, dado que estamos trabajando con la biblioteca hunspell , debemos incluirla. Para hacer esto, agregue la línea al archivo .pro: LIBS + = -lhunspell .
A continuación, creemos nuestras propias clases heredadas de QSyntaxHighlighter y QTextEdit .
Archivo de encabezado Classes.h:
#ifndef CLASSES_H
#define CLASSES_H
#include <QSyntaxHighlighter>
#include <QTextEdit>
class SpellingHighlighter : public QSyntaxHighlighter //
{
Q_OBJECT
public:
SpellingHighlighter(QTextEdit *parent) :QSyntaxHighlighter(parent) {}
protected:
virtual void highlightBlock(const QString &text) override;
};
class BodyTextEdit : public QTextEdit //
{
Q_OBJECT
public:
BodyTextEdit(QWidget* parent = 0);
public slots:
void openCustomMenu(QPoint);
void correctWord(QAction * act);
protected:
SpellingHighlighter * m_highLighter;
};
#endif // CLASSES_H
Destacaremos palabras que no están contenidas en el diccionario, y al llamar al menú contextual, ofreceremos posibles opciones de reemplazo. Esta función se basa en un artículo que se encuentra en Internet.
// correct - , getSuggests -
QStringList suggestCorrections(const QString &word, bool &correct, bool getSuggests = false)
{
static Hunspell * m_hunSpell = new Hunspell("/usr/share/hunspell/ru_RU.aff", "/usr/share/hunspell/ru_RU.dic");// debian
static QString encoderStr = QString::fromLatin1( m_hunSpell->get_dic_encoding());// , KOI8-R
static QTextCodec * m_codec = QTextCodec::codecForName(encoderStr.toLatin1().constData());
correct = m_hunSpell->spell(m_codec->fromUnicode(word).constData()) != 0; //
if (getSuggests == false)
return QStringList();
QStringList suggestions;
char **suggestWordList = NULL;
try {
// Encode from Unicode to the encoding used by current dictionary
int count = m_hunSpell->suggest(&suggestWordList, m_codec->fromUnicode(word).constData());//
QString lowerWord = word.toLower();
for (int i = 0; i < count; ++i) {
QString suggestion = m_codec->toUnicode(suggestWordList[i]);
suggestions << suggestion;
free(suggestWordList[i]);
}
}
catch(...)
{
qDebug() <<"Error keyword";
}
return suggestions;
}
Todo lo que queda es definir las clases y usar esta función sabiamente:
#include <QSyntaxHighlighter>
#include <QCompleter>
#include <QTextCodec>
#include <QAction>
#include <QTextEdit>
#include <QMenu>
#include "hunspell/hunspell.hxx" // from package libhunspell-dev
#include <QDebug>
#include "classes.h"
//
QStringList suggestCorrections(const QString &word, bool &correct, bool getSuggests = false)
{
static Hunspell * m_hunSpell = new Hunspell("/usr/share/hunspell/ru_RU.aff", "/usr/share/hunspell/ru_RU.dic");
static QString encoderStr = QString::fromLatin1( m_hunSpell->get_dic_encoding());
static QTextCodec * m_codec = QTextCodec::codecForName(encoderStr.toLatin1().constData());
correct = m_hunSpell->spell(m_codec->fromUnicode(word).constData()) != 0;
if (getSuggests == false)
return QStringList();
QStringList suggestions;
char **suggestWordList = NULL;
try {
// Encode from Unicode to the encoding used by current dictionary
int count = m_hunSpell->suggest(&suggestWordList, m_codec->fromUnicode(word).constData());
QString lowerWord = word.toLower();
for (int i = 0; i < count; ++i) {
QString suggestion = m_codec->toUnicode(suggestWordList[i]);
suggestions << suggestion;
free(suggestWordList[i]);
}
}
catch(...)
{
qDebug() <<"Error keyword";
}
return suggestions;
}
//
void SpellingHighlighter::highlightBlock(const QString &text)
{
QStringList list = text.split(QRegExp("\\s+"), QString::KeepEmptyParts);//
QTextCharFormat spellingFormat;//
spellingFormat.setUnderlineStyle(QTextCharFormat::SpellCheckUnderline);
spellingFormat.setUnderlineColor(Qt::red);
int count_word = list.size();
int pointer = 0;
for (int i= 0; i< count_word; i++)
{
bool correct = false;
QString sect = text.section(QRegExp("\\s+"), i, i, QString::SectionIncludeLeadingSep);
sect.remove(QRegExp("[,!?&*|]"));//
suggestCorrections(sect, correct);//
if (!correct)
{
setFormat(pointer, sect.length(),spellingFormat);
}
pointer += sect.length();
}
};
BodyTextEdit::BodyTextEdit(QWidget* parent )
:
QTextEdit(parent)
{
this->setContextMenuPolicy(Qt::CustomContextMenu);
m_highLighter = new SpellingHighlighter(this);
connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(openCustomMenu(QPoint)));
}
//
void BodyTextEdit::openCustomMenu(QPoint pos)
{
QMenu* popupmenu = this->createStandardContextMenu();
QTextCursor cursor = this->textCursor();
cursor.select(QTextCursor::WordUnderCursor);
this->setTextCursor(cursor);
if (this->textCursor().hasSelection())
{
QString text = this->textCursor().selectedText();
bool correct = false;
QStringList suggest = suggestCorrections(text, correct, true);
auto firstAction = popupmenu->actions().first();
if (!correct)
{
QList<QAction*> addedActions;
for (auto word : suggest)
{
QAction * act = new QAction(word, popupmenu);
act->setData(word);
addedActions.append(act);
}
popupmenu->insertActions(firstAction, addedActions);
connect(popupmenu, SIGNAL(triggered(QAction*)), this, SLOT(correctWord(QAction*)));
}
}
popupmenu->exec(this->mapToGlobal(pos));
delete popupmenu;
}
//
void BodyTextEdit::correctWord(QAction *act)
{
if (act->data().isNull())
return;
QString word = act->data().toString();
QTextCursor cursor = this->textCursor();
cursor.beginEditBlock();
cursor.removeSelectedText();
cursor.insertText(word);
cursor.endEditBlock();
}
Conclusión:
Por lo tanto, en aproximadamente 150 líneas de código, tendrá una función de corrección ortográfica que se puede utilizar en sus aplicaciones Qt con un mínimo de dependencias.