diff --git a/kde/frameworks/tier1/sonnet/ispellchecker.patch b/kde/frameworks/tier1/sonnet/ispellchecker.patch index 6b288976..2b45cc75 100644 --- a/kde/frameworks/tier1/sonnet/ispellchecker.patch +++ b/kde/frameworks/tier1/sonnet/ispellchecker.patch @@ -1,180 +1,184 @@ diff --git a/src/plugins/ispellchecker/ispellcheckerclient.h b/src/plugins/ispellchecker/ispellcheckerclient.h --- a/src/plugins/ispellchecker/ispellcheckerclient.h +++ b/src/plugins/ispellchecker/ispellcheckerclient.h @@ -12,6 +12,8 @@ #include #include +#include + namespace Sonnet { class SpellerPlugin; } @@ -41,9 +43,8 @@ } private: - bool m_wasCOMInitialized = false; - ISpellCheckerFactory* m_spellCheckerFactory = nullptr; - QStringList m_languages; + // we internally keep all spell checker interfaces alive + QMap m_languages; }; #endif diff --git a/src/plugins/ispellchecker/ispellcheckerclient.cpp b/src/plugins/ispellchecker/ispellcheckerclient.cpp --- a/src/plugins/ispellchecker/ispellcheckerclient.cpp +++ b/src/plugins/ispellchecker/ispellcheckerclient.cpp -@@ -15,49 +15,47 @@ +@@ -15,52 +15,50 @@ { qCDebug(SONNET_ISPELLCHECKER) << " ISpellCheckerClient::ISpellCheckerClient"; - // init com if needed - m_wasCOMInitialized = SUCCEEDED(CoInitializeEx(nullptr, COINIT_MULTITHREADED)); + // init com if needed, use same variant as e.g. Qt in qtbase/src/corelib/io/qfilesystemengine_win.cpp + CoInitialize(nullptr); - // get factory - if (SUCCEEDED(CoCreateInstance(__uuidof(SpellCheckerFactory), nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_spellCheckerFactory)))) { + // get factory & collect all known languages + instantiate the spell checkers for them + ISpellCheckerFactory *spellCheckerFactory = nullptr; + if (SUCCEEDED(CoCreateInstance(__uuidof(SpellCheckerFactory), nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&spellCheckerFactory))) && spellCheckerFactory) { // if we have a factory, cache the language names IEnumString* enumLanguages = nullptr; - if (SUCCEEDED(m_spellCheckerFactory->get_SupportedLanguages(&enumLanguages))) { + if (SUCCEEDED(spellCheckerFactory->get_SupportedLanguages(&enumLanguages))) { HRESULT hr = S_OK; while (S_OK == hr) { LPOLESTR string = nullptr; hr = enumLanguages->Next(1, &string, nullptr); if (S_OK == hr) { - m_languages.push_back(QString::fromWCharArray(string)); + ISpellChecker *spellChecker = nullptr; + if (SUCCEEDED(spellCheckerFactory->CreateSpellChecker(string, &spellChecker)) && spellChecker) { + m_languages.insert(QString::fromWCharArray(string), spellChecker); + } CoTaskMemFree(string); } } enumLanguages->Release(); } - } else { - m_spellCheckerFactory = nullptr; + spellCheckerFactory->Release(); } } ISpellCheckerClient::~ISpellCheckerClient() { - // de-init com if needed - if (m_wasCOMInitialized) { - CoUninitialize(); - } - - // release factory - if (m_spellCheckerFactory) { - m_spellCheckerFactory->Release(); - } + // FIXME: we at the moment leak all checkers as sonnet does the cleanup to late for proper com cleanup :/ } SpellerPlugin *ISpellCheckerClient::createSpeller(const QString &language) { - // create requested spellchecker, might internally fail to create instance + // create requested spellchecker if we know the language qCDebug(SONNET_ISPELLCHECKER) << " SpellerPlugin *ISpellCheckerClient::createSpeller(const QString &language) ;" << language; - ISpellCheckerDict *ad = new ISpellCheckerDict(m_spellCheckerFactory, language); - return ad; + const auto it = m_languages.find(language); + if (it != m_languages.end()) { + return new ISpellCheckerDict(it.value(), language); + } + return nullptr; } QStringList ISpellCheckerClient::languages() const + { +- return m_languages; ++ return m_languages.keys(); + } diff --git a/src/plugins/ispellchecker/ispellcheckerdict.h b/src/plugins/ispellchecker/ispellcheckerdict.h --- a/src/plugins/ispellchecker/ispellcheckerdict.h +++ b/src/plugins/ispellchecker/ispellcheckerdict.h @@ -14,7 +14,7 @@ class ISpellCheckerDict : public Sonnet::SpellerPlugin { public: - explicit ISpellCheckerDict(ISpellCheckerFactory *spellCheckerFactory, const QString &language); + explicit ISpellCheckerDict(ISpellChecker *spellChecker, const QString &language); ~ISpellCheckerDict() override; bool isCorrect(const QString &word) const override; @@ -26,8 +26,8 @@ bool addToSession(const QString &word) override; private: - // spell checker com object - ISpellChecker *m_spellChecker = nullptr; + // spell checker com object, we don't own this + ISpellChecker * const m_spellChecker; }; #endif diff --git a/src/plugins/ispellchecker/ispellcheckerdict.cpp b/src/plugins/ispellchecker/ispellcheckerdict.cpp --- a/src/plugins/ispellchecker/ispellcheckerdict.cpp +++ b/src/plugins/ispellchecker/ispellcheckerdict.cpp @@ -9,29 +9,24 @@ using namespace Sonnet; -ISpellCheckerDict::ISpellCheckerDict(ISpellCheckerFactory *spellCheckerFactory, const QString &language) +ISpellCheckerDict::ISpellCheckerDict(ISpellChecker *spellChecker, const QString &language) : SpellerPlugin(language) + , m_spellChecker(spellChecker) { - // try to init checker - if (!SUCCEEDED(spellCheckerFactory->CreateSpellChecker(language.toStdWString().c_str(), &m_spellChecker))) { - m_spellChecker = nullptr; - } + Q_ASSERT(m_spellChecker); } ISpellCheckerDict::~ISpellCheckerDict() { - // release com if needed - if (m_spellChecker) { - m_spellChecker->Release(); - } + // we don't own m_spellChecker! } bool ISpellCheckerDict::isCorrect(const QString &word) const { // check if we are incorrect, we only need to check one enum entry for that, only empty enum means OK bool ok = true; IEnumSpellingError* enumSpellingError = nullptr; - if (m_spellChecker && SUCCEEDED(m_spellChecker->Check(word.toStdWString().c_str(), &enumSpellingError))) { + if (SUCCEEDED(m_spellChecker->Check(word.toStdWString().c_str(), &enumSpellingError))) { ISpellingError *spellingError = nullptr; if (S_OK == enumSpellingError->Next(&spellingError)) { ok = false; @@ -47,7 +42,7 @@ // query suggestions QStringList replacements; IEnumString* words = nullptr; - if (m_spellChecker && SUCCEEDED(m_spellChecker->Suggest(word.toStdWString().c_str(), &words))) { + if (SUCCEEDED(m_spellChecker->Suggest(word.toStdWString().c_str(), &words))) { HRESULT hr = S_OK; while (S_OK == hr) { LPOLESTR string = nullptr; @@ -73,11 +68,11 @@ bool ISpellCheckerDict::addToPersonal(const QString &word) { // add word "permanently" to the dictionary - return m_spellChecker && SUCCEEDED(m_spellChecker->Add(word.toStdWString().c_str())); + return SUCCEEDED(m_spellChecker->Add(word.toStdWString().c_str())); } bool ISpellCheckerDict::addToSession(const QString &word) { // ignore word for this session - return m_spellChecker && SUCCEEDED(m_spellChecker->Ignore(word.toStdWString().c_str())); + return SUCCEEDED(m_spellChecker->Ignore(word.toStdWString().c_str())); } diff --git a/kde/frameworks/tier1/sonnet/sonnet.py b/kde/frameworks/tier1/sonnet/sonnet.py index ccea6632..905694ba 100644 --- a/kde/frameworks/tier1/sonnet/sonnet.py +++ b/kde/frameworks/tier1/sonnet/sonnet.py @@ -1,38 +1,38 @@ import info class subinfo(info.infoclass): def setTargets(self): self.versionInfo.setDefaultValues() self.description = "Spelling framework for Qt, plugin-based." self.patchToApply["5.67.0"] = [ ("ispellchecker.patch", 1), ] - self.patchLevel["5.67.0"] = 6 + self.patchLevel["5.67.0"] = 7 def registerOptions(self): # hunspell just when needed, on Windows(visual studio) or Mac we try with the OS specific checkers self.options.dynamic.registerOption("useHunspell", CraftCore.compiler.isLinux or CraftCore.compiler.isMinGW()) def setDependencies(self): self.buildDependencies["virtual/base"] = None self.buildDependencies["kde/frameworks/extra-cmake-modules"] = None self.runtimeDependencies["libs/qt5/qtbase"] = None if self.options.dynamic.useHunspell: self.runtimeDependencies["libs/hunspell"] = None from Package.CMakePackageBase import * class Package(CMakePackageBase): def __init__(self): CMakePackageBase.__init__(self) # always use just hunspell, if at all! self.subinfo.options.configure.args += " -DCMAKE_DISABLE_FIND_PACKAGE_ASPELL=ON" if not self.subinfo.options.dynamic.useHunspell: self.subinfo.options.configure.args += " -DCMAKE_DISABLE_FIND_PACKAGE_HUNSPELL=ON"