Created attachment 161649 [details] Search example I would like to discuss this feature and how it can be implemented for all languages supported in KDE. ### How it is work For example, keystroke sequence like `лфеу` in `Cyrilic ЙЦУКЕН` is `kate` in `QWERTY`. And vice versa, not only the `RU -> EN` search is implemented, but also the `EN -> RU`. This is useful for systems with multiple keyboard language layouts in case when you forget to switch layout. ### Problem However, the task of implementation for all languages looks rather non-trivial. I assume that it is possible to use some kind of system library in this conversion, like `xkb`. So, I would like to know if the community is interested in this feature, and in what ways it could be implemented. ### How it is implemented now At the moment, I have implemented a prototype that has the desired behavior for EN (English) - RU (Russian) layouts by using simple convertation table. Convertation table: ``` class LayoutRuEnConverter { enum class LayoutType { RU_TO_EN = 0, EN_TO_RU = 1 }; using LayoutMap = QMap<QChar, QChar>; using LayoutMaps = QMap<LayoutType, LayoutMap>; public: LayoutRuEnConverter() = default; bool isStrHasRuChar(const QString &str) const { for (auto c: str) { if (ruCharsMap[c]) { return true; } } return false; } QString invertLayout(const QString &str) const { return convertLayout(str, isStrHasRuChar(str) ? LayoutType::RU_TO_EN : LayoutType::EN_TO_RU); } private: QMap<QChar, bool> getRuCharsMap() const { const QString ruChars = "абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"; QMap<QChar, bool> t; for (auto c: ruChars) { t[c] = true; } return t; } LayoutMaps initLayouts() const { const QString qwertyEn = "`qwertyuiop[]asdfghjkl;'zxcvbnm,./~@#$^&QWERTYUIOP{}|ASDFGHJKL:\"ZXCVBNM<>?"; const QString qwertyRu = "ёйцукенгшщзхъфывапролджэячсмитьбю.Ё\"№;:?ЙЦУКЕНГШЩЗХЪ/ФЫВАПРОЛДЖЭЯЧСМИТЬБЮ,"; const int N = qwertyEn.count(); LayoutMap layoutRuToEnMap; LayoutMap layoutEnToRuMap; for (int i = 0; i < N; ++i) { layoutRuToEnMap[qwertyRu[i]] = qwertyEn[i]; layoutEnToRuMap[qwertyEn[i]] = qwertyRu[i]; } LayoutMaps res; res[LayoutType::RU_TO_EN] = layoutRuToEnMap; res[LayoutType::EN_TO_RU] = layoutEnToRuMap; return res; } QString convertLayout(const QString &str, const LayoutType layoutType) const { QString res = ""; for (auto c: str) { res += !layouts[layoutType][c].isNull() ? layouts[layoutType][c] : c; } return res; } const QMap<QChar, bool> ruCharsMap = getRuCharsMap(); const LayoutMaps layouts = initLayouts(); }; ``` And in match() function, converted search query is executed. ``` void match(Plasma::RunnerContext &context) { const auto doMatch = [this]() { matchNameKeywordAndGenericName(); matchCategories(); matchJumpListActions(); }; term = context.query(); // Splitting the query term to match using subsequences queryList = term.split(QLatin1Char(' ')); weightedTermLength = weightedLength(term); doMatch(); // Invert language layout (RU <-> EN) in queryList. std::transform(queryList.cbegin(), queryList.cend(), queryList.begin(), [this](const QString& str) { return m_layoutConverter->invertLayout(str); }); // Do match again with converted queryList. doMatch(); context.addMatches(matches); } ```
What a fascinatingly cool idea.
*** Bug 477652 has been marked as a duplicate of this bug. ***
*** Bug 485202 has been marked as a duplicate of this bug. ***