Memeriksa Ejaan dalam Aplikasi Qt

Artikel ini menjelaskan cara menambahkan pemeriksa ejaan ke aplikasi Qt Anda dengan menyorot kata yang salah eja dan kemampuan untuk menggantinya dengan varian yang lebih cocok. Kamus hunspell digunakan untuk ini .





Untuk menyorot ejaan kata yang salah, kelas QSyntaxHighlighter yang dimodifikasi digunakan , dan kelas QTextEdit yang dimodifikasi digunakan untuk menampilkan dan memasukkan teks .





Pertama-tama, karena kita bekerja dengan perpustakaan hunspell , kita perlu memasukkannya. Untuk melakukan ini, tambahkan baris ke file .pro: LIBS + = -lhunspell .





Selanjutnya, mari buat kelas kita sendiri yang diwarisi dari QSyntaxHighlighter dan QTextEdit .





File header 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
      
      



Kami akan menyoroti kata-kata yang tidak terdapat dalam kamus, dan saat memanggil menu konteks, kami akan menawarkan opsi penggantian yang memungkinkan. Fungsi ini didasarkan pada artikel yang ditemukan di 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;
}

      
      



Yang tersisa hanyalah mendefinisikan kelas dan menggunakan fungsi ini dengan bijak:





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

      
      



Kesimpulan:

Jadi, di sekitar 150 baris kode, Anda akan memiliki fungsi pemeriksa ejaan yang dapat digunakan dalam aplikasi Qt Anda dengan dependensi minimum.








All Articles