Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt Модель/Представление _ [РЕШЕНО] откат к старым данным при редактировании через делегат (QItemDelegate::eventFilter)

Автор: igor_bogomolov 28.9.2009, 18:27

Всем привет.

Есть у меня табличка, данные которой редактирую через делегаты. Для этих делегатов мне нужно такое поведение, что бы дынные фиксировались обратно в модель, только при нажатии Enter, во всех остальных случаях происходил откат к старым данным. Не нашёл никакого другого решения, кроме как перекрыть метод eventFilter у делегата.
Для редактирования через QSpinBox, достаточно оказалось следущего кода

SpinBoxDelegate::eventFilter
bool SpinBoxDelegate::eventFilter(QObject* editor, QEvent* event )
{
    QSpinBox* spinBox = static_cast<QSpinBox*>(editor);
    if (event->type() == QEvent::KeyPress) {
        QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
        if(keyEvent->key() == Qt::Key_Tab || keyEvent->key() == Qt::Key_Backtab) {
            emit closeEditor(spinBox);
            return true;
        }
    } else if (event->type() == QEvent::FocusOut) {
        emit closeEditor(spinBox);
        return true;
    }
    return QItemDelegate::eventFilter(editor, event);
}

А вот для случая редактирования через QComboBox, подобного поведения никак добиться не получается :(
ComboBoxDelegate::eventFilter
bool ComboBoxDelegate::eventFilter(QObject* editor, QEvent* event )
{
    static bool flag = false;
    QComboBox* comboBox = static_cast<QComboBox*>(editor);
    if (event->type() == QEvent::KeyPress) {
        QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
        if(keyEvent->key() == Qt::Key_Tab || keyEvent->key() == Qt::Key_Backtab) {
            emit closeEditor(comboBox);
            return true;
        } else if(keyEvent->key() == Qt::Key_Right || keyEvent->key() == Qt::Key_Left) {
            return true;
        }
    }
    return QItemDelegate::eventFilter(editor, event);
}

Кто сможет подправить так, чтобы при щелчке мышкой вне комбо бокса и его выпадающего списка, редактирование закрывалось, но данные в модель не фиксировались?
Или может есть какой другой способ добиться такого поведения?

Автор: kwisp 28.9.2009, 18:42

извини не по теме.
объясни пожалуйста почему static_cast пользуешь?

Автор: igor_bogomolov 28.9.2009, 19:07

Сам я для классов наследованных от QObject всегда использовал qobject_cast, в данном случае синтаксис перенял из примера в ассистенте. Или вопрос почему не dynamic_cast? Насколько я понимаю здесь нет динамического приведения типов.

Автор: kwisp 28.9.2009, 19:21

igor_bogomolov,
ясно.
мне вот эти строчки показалась опасными при поддержке или если придется код заимствовать.

Цитата
QSpinBox* spinBox = static_cast<QSpinBox*>(editor);
QComboBox* comboBox = static_cast<QComboBox*>(editor);

Автор: igor_bogomolov 14.12.2009, 17:37

Продублирую, что бы закрыть тему.

Решил так:

bool ComboBoxDelegate::eventFilter(QObject* editor, QEvent* event )
{
    QComboBox * comboBox = static_cast<QComboBox*>(editor);
    if (comboBox) {
        if (event->type() == QEvent::KeyPress) {
            QKeyEvent * keyEvent = static_cast<QKeyEvent*>(event);
            if(keyEvent->key()==Qt::Key_Tab || keyEvent->key()==Qt::Key_Backtab) {
                emit closeEditor(comboBox, QAbstractItemDelegate::RevertModelCache);
                return true;
            } else if(keyEvent->key() == Qt::Key_Right || keyEvent->key() == Qt::Key_Left) {
                return true;
            }
        } else if (event->type() == QEvent::FocusOut) {
            QWidget * widget = qApp->focusWidget();
            if(!widget) return false;

            if (QLatin1String(widget->metaObject()->className()) == QLatin1String("QComboBoxListView") ||
                QLatin1String(widget->metaObject()->className()) == QLatin1String("QComboBox" )) {
                return true;
            }

            emit closeEditor(comboBox, QAbstractItemDelegate::RevertModelCache);
            return true;
        }
    }
    return QItemDelegate::eventFilter(editor, event);
}

Автор: Litkevich Yuriy 14.12.2009, 20:06

igor_bogomolov, я вот думаю как бы тему переобозвать, чтобы соответствовать конечной задаче.

Автор: igor_bogomolov 15.12.2009, 0:01

Не знаю. Например - "Как отловить потерю фокуса у QComboBox в делегате"
Как только указать, что имеется в виду "полная" потеря фокуса виджетом, а не переход фокуса на его выпадающий список?
В подзаголовке что-нибудь написать? Не знаю правда, осуществляется ли по нему поиск? С поиском на сайте - беда полнейшая. Очень тяжело что либо искать :(

Могу так же выложить свои делегаты имитирующие виджеты(QPushButton, QLineEdit, QCheckBox(точнее его чекер)). http://www.prog.org.ru/topic_11696_0.html

Автор: Litkevich Yuriy 15.12.2009, 10:38

Цитата(igor_bogomolov @ 28.9.2009, 21:27) *
что бы дынные фиксировались обратно в модель, только при нажатии Enter, во всех остальных случаях происходил откат к старым данным.
я собственно по вот этой теме думал обозвать, только как кратко написать?

Аналогия из области QSqlTableModel::OnRowChange, т.е. что-то вроде QSqlTableModel::RollbackOnRowFieldChange

Может быть так:
Реализация RollbackOnRowFieldChange с помощью QItemDelegate::eventFilter
??

Автор: igor_bogomolov 15.12.2009, 11:06

О. Вон оно как. :)
Я в общем то не против. Хотя сам бы никогда такую тему не нашел.
Может, все таки по Русски как то обозвать. "откат к старым данным при редактировании через делегат" ?

Хотя, мне на самом деле без разницы. Делай так как считаешь нужным :)

Автор: Litkevich Yuriy 15.12.2009, 12:48

Цитата(igor_bogomolov @ 15.12.2009, 14:06) *
Хотя сам бы никогда такую тему не нашел.
в этом-то у меня и загвоздка. Я исхожу из того, что кто-то будет искать решение.

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)