Vérification orthographique dans les applications Qt

Cet article décrit comment ajouter un vérificateur d' orthographe à votre application Qt avec la mise en évidence des mots mal orthographiés et la possibilité de les remplacer par des variantes plus appropriées. Le dictionnaire hunspell est utilisé pour cela .





Pour mettre en évidence les mots incorrects, la classe QSyntaxHighlighter modifiée est utilisée et la classe QTextEdit modifiée est utilisée pour afficher et saisir du texte .





Tout d'abord, puisque nous travaillons avec la bibliothèque hunspell , nous devons l'inclure. Pour ce faire, ajoutez la ligne au fichier .pro: LIBS + = -lhunspell .





Ensuite, créons nos propres classes héritées de QSyntaxHighlighter et QTextEdit .





Fichier d'en-tête 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
      
      



Nous mettrons en évidence les mots qui ne sont pas contenus dans le dictionnaire, et lors de l'appel du menu contextuel, nous proposerons des options de remplacement possibles. Cette fonction est basée sur un article trouvé sur 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;
}

      
      



Il ne reste plus qu'à définir les classes et à utiliser cette fonction à bon escient:





#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();
}

      
      



Conclusion:

Ainsi, dans environ 150 lignes de code, vous disposerez d'une fonctionnalité de vérification orthographique utilisable dans vos applications Qt avec un minimum de dépendances.








All Articles