https://bugs.kde.org/show_bug.cgi?id=474573

            Bug ID: 474573
           Summary: runners/services: look for the same keystrokes search
                    sequence in other keyboard language layouts
    Classification: Plasma
           Product: krunner
           Version: unspecified
          Platform: unspecified
                OS: Linux
            Status: REPORTED
          Severity: wishlist
          Priority: NOR
         Component: general
          Assignee: plasma-b...@kde.org
          Reporter: sulmp...@yandex.ru
                CC: alexander.loh...@gmx.de, natalie_clar...@yahoo.de
  Target Milestone: ---

Created attachment 161649
  --> https://bugs.kde.org/attachment.cgi?id=161649&action=edit
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);
}
```

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to