[C++, Qt] Проверка орфографии в приложениях Qt
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
В данной статье описано как добавить к вашему приложению на 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
===========
Похожие новости:
- [C++, Qt, Разработка под Android] Фото из Android смартфона в Qt Widgets
- [Open source, Программирование, C++, C, Машинное обучение] Программисты создали проект «Этот код не существует»
- [Open source, C++, Разработка игр] Free Heroes of might and magic 2 – open-source проект, в котором хочется участвовать
- [Программирование, Java, Совершенный код, C#, Kotlin] Лучший язык программирования
- [C++, Разработка под Arduino, DIY или Сделай сам, Data Engineering] ESP 8266: отправка данных на сайт методом Get запроса
- [Open source, Программирование, C++] Overview of recent changes in rotor (v0.10… v0.14)
- [Open source, Программирование, C++] Обзор последних изменений в rotor'е (v0.10… v0.14)
- [Разработка на Raspberry Pi, Умный дом, Интернет вещей, Микросервисы] Первый опыт с Raspberry Pi или микросервисы для дома
- [Программирование, C++, Работа с 3D-графикой, Разработка игр, CGI (графика)] Vulkan. Руководство разработчика. Image view (перевод)
- [Программирование, C++, Параллельное программирование] OOX 2.0: Out of Order eXecution made easy
Теги для поиска: #_c++, #_qt, #_hunspell, #_qt, #_c++, #_orfografija (орфография), #_c++, #_qt
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 20:01
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
В данной статье описано как добавить к вашему приложению на 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(); } =========== Источник: habr.com =========== Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 20:01
Часовой пояс: UTC + 5