1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-07-02 06:35:29 +02:00

spellchecker: fix codec segfault

Fix the segfault happening when a codec is not properly loaded by
only activated spellcheck when a dictionnary has been successfully
loaded, initializing a default codec and adding error handling.

GitLab: #2063

Change-Id: I48339ce6d13120cfbae3c6c7eb6f40e87f16f084
This commit is contained in:
pmagnier-slimani 2025-06-13 15:12:46 -04:00 committed by François-Simon Fauteux-Chapleau
parent e76bcbd555
commit b15d692a0e
5 changed files with 29 additions and 10 deletions

View file

@ -113,9 +113,7 @@ JamiFlickable {
} }
} }
readonly property bool spellCheckEnabled: property bool spellCheckEnabled: AppSettingsManager.getValue(Settings.EnableSpellCheck) && AppSettingsManager.getValue(Settings.SpellLang) !== ""
AppSettingsManager.getValue(Settings.EnableSpellCheck) &&
AppSettingsManager.getValue(Settings.SpellLang) !== ""
// Spell check is active under the following conditions: // Spell check is active under the following conditions:
// 1. Spell check is enabled in settings // 1. Spell check is enabled in settings
@ -192,7 +190,7 @@ JamiFlickable {
onReleased: function (event) { onReleased: function (event) {
if (event.button === Qt.RightButton) { if (event.button === Qt.RightButton) {
if (spellCheckActive) { if (spellCheckActive && SpellCheckAdapter.hasLoadedDictionary) {
var position = textArea.positionAt(event.x, event.y); var position = textArea.positionAt(event.x, event.y);
textArea.moveCursorSelection(position, TextInput.SelectWords); textArea.moveCursorSelection(position, TextInput.SelectWords);
textArea.selectWord(); textArea.selectWord();
@ -254,7 +252,7 @@ JamiFlickable {
function updateSpellCorrection() { function updateSpellCorrection() {
clearUnderlines(); clearUnderlines();
// We iterate over the whole text to find words to check and underline them if needed // We iterate over the whole text to find words to check and underline them if needed
if (spellCheckActive) { if (spellCheckActive && SpellCheckAdapter.hasLoadedDictionary) {
var text = textArea.text; var text = textArea.text;
var words = SpellCheckAdapter.findWords(text); var words = SpellCheckAdapter.findWords(text);
if (!words) if (!words)

View file

@ -134,6 +134,9 @@ SpellCheckAdapter::setDictionary(const QString& locale)
auto localPath = dictionaryListModel_->pathForLocale(locale); auto localPath = dictionaryListModel_->pathForLocale(locale);
if (spellChecker_.replaceDictionary(localPath)) { if (spellChecker_.replaceDictionary(localPath)) {
settingsManager_->setValue(Settings::Key::SpellLang, locale); settingsManager_->setValue(Settings::Key::SpellLang, locale);
set_hasLoadedDictionary(true);
Q_EMIT dictionaryChanged(); Q_EMIT dictionaryChanged();
} else {
qWarning() << "Failed to set dictionary for locale:" << locale;
} }
} }

View file

@ -33,6 +33,7 @@ class SpellCheckAdapter final : public QObject
QML_SINGLETON QML_SINGLETON
QML_RO_PROPERTY(int, installedDictionaryCount) QML_RO_PROPERTY(int, installedDictionaryCount)
QML_RO_PROPERTY(bool, hasLoadedDictionary)
public: public:
static SpellCheckAdapter* create(QQmlEngine* engine, QJSEngine*) static SpellCheckAdapter* create(QQmlEngine* engine, QJSEngine*)

View file

@ -31,7 +31,10 @@
SpellChecker::SpellChecker() SpellChecker::SpellChecker()
: hunspell_(new Hunspell("", "")) : hunspell_(new Hunspell("", ""))
{} {
// Initialize with default UTF-8 codec
codec_ = QTextCodec::codecForName("UTF-8");
}
bool bool
SpellChecker::spell(const QString& word) SpellChecker::spell(const QString& word)
@ -75,11 +78,26 @@ SpellChecker::replaceDictionary(const QString& dictionaryPath)
QString dictFile = dictionaryPath + ".dic"; QString dictFile = dictionaryPath + ".dic";
QString affixFile = dictionaryPath + ".aff"; QString affixFile = dictionaryPath + ".aff";
// Check if dictionary files exist
if (!QFile::exists(dictFile) || !QFile::exists(affixFile)) {
qWarning() << "Dictionary files not found:" << dictFile << affixFile;
return false;
}
QByteArray dictFilePath = dictFile.toLocal8Bit(); QByteArray dictFilePath = dictFile.toLocal8Bit();
QByteArray affixFilePath = affixFile.toLocal8Bit(); QByteArray affixFilePath = affixFile.toLocal8Bit();
hunspell_.reset(new Hunspell(affixFilePath.constData(), dictFilePath.constData()));
encoding_ =hunspell_->get_dic_encoding(); std::unique_ptr<Hunspell> hunspell(
codec_ = QTextCodec::codecForName(this->encoding_.toLatin1().constData()); new Hunspell(affixFilePath.constData(), dictFilePath.constData()));
auto encoding = hunspell->get_dic_encoding();
auto codec = QTextCodec::codecForName(encoding);
if (!codec) {
return false;
}
hunspell_ = std::move(hunspell);
codec_ = codec;
currentDictionaryPath_ = dictionaryPath; currentDictionaryPath_ = dictionaryPath;
return true; return true;
} }

View file

@ -57,6 +57,5 @@ private:
std::unique_ptr<Hunspell> hunspell_; std::unique_ptr<Hunspell> hunspell_;
QString currentDictionaryPath_; QString currentDictionaryPath_;
QString encoding_;
QTextCodec* codec_; QTextCodec* codec_;
}; };