Русский
Русский
English
Статистика
Реклама

Проверка орфографии в приложениях Qt

В данной статье описано как добавить к вашему приложению на Qt проверку орфографии с подсветкой орфографически некорректных слов и возможность замены на более подходящие варианты. Для этого используется словарь hunspell.

Для подсветки орфографически некорректных слов используется модифицированный класс QSyntaxHighlighter, для отображения и ввода текста используется модифицированный класс QTextEdit.

Первым делом, поскольку мы работаем с библиотекой hunspell, необходимо её подключить. Для этого в .pro файл добавляем строку: LIBS += -lhunspell.

Далее создадим свои собственные классы унаследованные от QSyntaxHighlighter и QTextEdit.

Заголовочный файл 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

Мы будем подсвечивать слова, которые не содержаться в словаре, а при вызове контекстного меню предлагать возможные варианты замены. Данная функция сделана на основе статьи, найденной на просторах интернета.

// 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;}

Остается только определить классы и грамотно использовать данную функцию:

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

Заключение:

Таким образом за примерно 150 строк кода вы получите функционал по проверке орфографии, который можно будет использовать в ваших приложениях на Qt с минимальным количеством зависимостей.

Источник: habr.com
К списку статей
Опубликовано: 28.02.2021 18:05:07
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

C++

Qt

Hunspell

Орфография

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru