Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Hotkeys в русском тексте, небольшой хак для корректной работы =) 
:(
    Опции темы
_GRIN_
Дата 17.3.2011, 20:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


одинокий падаван
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 18.11.2007
Где: Калуга

Репутация: 6
Всего: 7



Наткнулся на то, что при задании мнемноник для кнопок и лэйблов (типа tr("&Cancel") ) в английском варианте всё работает, но после перевода лингвистом имя кнопки пишется правильное ("Отмена") но нажатие Alt+О (русское О)  и Alt+C (английское C) эфекта не дают. Судя по интерфейсу SMPlayer-a эта проблема именно в библиотеке и встречался с ней не только я (под линухом)

Решил следующим образом:
Код

void CTest::keyPressEvent(QKeyEvent*ev)
{
    int shift = (ev->modifiers() & Qt::ShiftModifier) ? Qt::SHIFT : 0;
    int ctrl = (ev->modifiers() & Qt::ControlModifier) ? Qt::CTRL : 0;
    int alt = (ev->modifiers() & Qt::AltModifier) ? Qt::ALT : 0;
    QKeySequence ks(ev->key() + shift + ctrl + alt);
    QList<QPair<QWidget*,bool> >widgets;
    foreach(QObject*child,children())
        if(child->isWidgetType()) {
            QAbstractButton*but = qobject_cast<QAbstractButton*>(child);
            if(but && but->isVisible() && (but->shortcut() == ks)) {
                widgets.append(QPair<QWidget*,bool>(but,true));
            }
            QLabel*label = qobject_cast<QLabel*>(child);
            if(label && label->isVisible() && label->buddy() && (ks == QKeySequence::mnemonic(label->text()))) {
                widgets.append(QPair<QWidget*,bool>(label->buddy(),false));
            }
        }
    if(widgets.count()) {
        QPair<QWidget*,bool>pair;
        int index = 0;
        int last = widgets.count()-1;
        for(int i=last;i>=0;i--) {
            if(widgets.at(i).first->hasFocus()) {
                index = (i == last) ? 0 : (i+1);
                break;
            }
        }
        pair = widgets.at(index);
        pair.first->setFocus();
        if(pair.second) {
            QAbstractButton*but = qobject_cast<QAbstractButton*>(pair.first);
            Q_ASSERT(but);
            but->click();
        }
        ev->accept();
    } else {
        ev->ignore();
    }
}

Работает =)

Хотелось бы услышать мнение коллег и гуру, может чё соптимизировать, а может я вообще велосипед изобрёл =)

Это сообщение отредактировал(а) _GRIN_ - 18.3.2011, 09:29


--------------------
Дорогу осилит идущий
PM MAIL Skype   Вверх
_GRIN_
Дата 25.3.2011, 19:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


одинокий падаван
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 18.11.2007
Где: Калуга

Репутация: 6
Всего: 7



=) вообщем таки стал применять и довёл до рабочего состояния

содержимое хидера shortcuts.h
Код

class QWidget; //forward declaration - for faster compilation
class QKeyEvent; //forward declaration- for faster compilation
bool checkWidgetShortcuts(QWidget*widget,QKeyEvent*ev);


содержимое сишника shortcuts.cpp
Код

#include <QWidget>
#include <QKeyEvent>
#include <QAbstractButton>
#include <QLabel>
#include <QTabWidget>
#include "qglobal.h"

namespace {
    struct SItem
    {
        QWidget*w;
        enum EType {
            BUTTON,
            LABEL,
            TAB
        } type;
        int data;

        SItem(QWidget*_w,EType _t,int _d=0) : w(_w),type(_t),data(_d) {}
    };

    QList<QWidget*> visible_widgets(QWidget*w)
    {
        QList<QWidget*> list;
        Q_ASSERT(w);
        if(w->isVisible() && w->isEnabled()) {
            list.append(w);
            foreach(QObject*child,w->children())
                if(child->isWidgetType())
                    list << visible_widgets(qobject_cast<QWidget*>(child));
        }
        return list;
    }
} //anonymus namespace

bool checkWidgetShortcuts(QWidget*widget,QKeyEvent*ev)
{
    Q_ASSERT(widget && ev);
    bool ret_val = false;
    int shift = (ev->modifiers() & Qt::ShiftModifier) ? (int)Qt::SHIFT : 0;
    int ctrl = (ev->modifiers() & Qt::ControlModifier) ? (int)Qt::CTRL : 0;
    int alt = (ev->modifiers() & Qt::AltModifier) ? (int)Qt::ALT : 0;
    QKeySequence ks(ev->key() + shift + ctrl + alt);
    QList<SItem>list;
    foreach(QWidget*cw,visible_widgets(widget)) {
        if(qobject_cast<QAbstractButton*>(cw)) {
            QAbstractButton*but = qobject_cast<QAbstractButton*>(cw);
            if(but->shortcut() == ks)
                list.append(SItem(but,SItem::BUTTON));
        } else if(qobject_cast<QLabel*>(cw)) {
            QLabel*label = qobject_cast<QLabel*>(cw);
            if(label->buddy() && label->buddy()->isVisible()
                && (ks == QKeySequence::mnemonic(label->text())))
            {
                list.append(SItem(label->buddy(),SItem::LABEL));
            }
        } else if(qobject_cast<QTabWidget*>(cw)) {
            QTabWidget*tab = qobject_cast<QTabWidget*>(cw);
            for(int i=0;i<tab->count();i++)
                if(ks == QKeySequence::mnemonic(tab->tabText(i))) {
                    list.append(SItem(tab,SItem::TAB,i));
                    break;
                }
        }
    }
    if(list.count()) {
        int index = 0;
        int last = list.count()-1;
        for(int i=last;i>=0;i--) {
            if(list.at(i).w->hasFocus()) {
                index = (i == last) ? 0 : (i+1);
                break;
            }
        }
        const SItem& item = list.at(index);
        item.w->setFocus();
        switch(item.type) {
        case SItem::BUTTON: qobject_cast<QAbstractButton*>(item.w)->click(); break;
        case SItem::LABEL: break; //do nothing - just check
        case SItem::TAB: qobject_cast<QTabWidget*>(item.w)->setCurrentIndex(item.data); break;
        default: Q_ASSERT(false); break;
        }
        ev->accept();
        ret_val = true;
    } else {
        ev->ignore();
    }
    return ret_val;
}


пример использования:
Код

void CMainWindow::keyPressEvent(QKeyEvent*event)
{
    if(!checkWidgetShortcuts(this,event)) {
        // do something with keyevent if needed
    }
}


Пока тока наследников от QAbstractButton, QLabel имеющих buddy и QTabWidget обрабатывает - возможно в процессе добавлю ещё - архитектура позваляет - в этом плане код расширяемый =).

P.S. ну хоть один коммент, SABORG  твоё мнение особенно интересно =)







--------------------
Дорогу осилит идущий
PM MAIL Skype   Вверх
bsa
Дата 25.3.2011, 21:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 24
Всего: 196



PM   Вверх
_GRIN_
Дата 25.3.2011, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


одинокий падаван
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 18.11.2007
Где: Калуга

Репутация: 6
Всего: 7



bsa, возможно я не правильно перевёл

"I have same problem with cyrillic. For example, Qt Creator translated to Russian, menu "&File" is translated to "&Файл" (cyrillic letter 'Ф' is on key with latin letter 'A'), I press Alt-A and no any effect, but shortcut activates when I switch layout to Russian and press Alt-Ф. This is not useful because while programming I (not only) use mostly English layout."

но получается, что у человека наоборот работают русские мненоники (!!!) единственное, он хочет, что бы шоткат не зависел от раскладки клавиатуры.

я проверял русские раскладки на убунте 10.10 (дома) 10.4 (рабочий ноут), и на дебиане (рабочий комп) - нигде русская раскладка не работала - я потому за описанный выше хак и взялся.



--------------------
Дорогу осилит идущий
PM MAIL Skype   Вверх
bsa
Дата 26.3.2011, 00:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 24
Всего: 196



Это я и написал. У меня не работают русские в английской раскладке, а в русской работают. Ubuntu 10.10. Проверял в Qt Creator 2.2-beta, Qt 4.7 
PM   Вверх
_GRIN_
Дата 26.3.2011, 00:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


одинокий падаван
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 18.11.2007
Где: Калуга

Репутация: 6
Всего: 7



bsa, ясно - я в 4.6.3 проверял - не работало - может просто пофиксили к 4.7


--------------------
Дорогу осилит идущий
PM MAIL Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets"
JackYF
Любитель
  • В заголовке темы в квадратных скобках обозначьте используемую вами библиотеку, например: [QT],[GTK],[wx].
  • Если вопрос актуален только для некоторой версии библиотеки, либо, если вы пользуетесь не самой последней версией, укажите это. Например: [QT4], [GTK2].
  • Все начинающие изучать Qt - не забудьте зайти сюда.
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • В вопросе укажите полную версию версию библиотеки, а также все дополнительные используемые программные пакеты.
  • Не забывайте пользоваться кнопкой "Код".
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема »


 




[ Время генерации скрипта: 0.0470 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.