crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> При вызове метода closeEditor для наследника QTableView editor не удаляется
smallmazila
  опции профиля:
сообщение 29.12.2011, 14:15
Сообщение #1


Новичок


Группа: Новичок
Сообщений: 2
Регистрация: 29.12.2011
Пользователь №: 3102

Спасибо сказали: 0 раз(а)




Репутация:   0  


Приветствую всех участников форума!

Кратко о задаче:
Есть связка LVTableView, LVTableItemDelegate и CableComboBox. Каждый объект является наследником соответственно от QTableView, QItemDelegate, QComboBox.

LVTableView.cpp
#include "LVTableView.h"

#include "LVModel.h"

LVTableView::LVTableView(DataModel* model)
{
    if (model)
        setModel(model);
}

LVTableView::~LVTableView()
{

}

void LVTableView::init(DataModel* model)
{
    clearSpans();
    if (model)setModel(model);
    LVModel* lvm = dynamic_cast<LVModel*>(this->model());
    if (lvm && lvm->getRowCount() > 0)
    {
        setSpan(0,LVModel::NOMVOLTAGE_ID,lvm->getRowCount(),1);
        setSpan(0,LVModel::WIRESPOSITION_ID,lvm->getRowCount(),1);
        setSpan(0,LVModel::SOURCEVOLTAGE_ID,lvm->getRowCount(),1);
        setSpan(0,LVModel::SUMLOSTVOLTAGE_ID,lvm->getRowCount(),1);
    }
    resizeRowsToContents();
    resizeColumnsToContents();
}

void LVTableView::setModel(DataModel* model)
{
    LVModel* m = dynamic_cast<LVModel*>(model);
    if (m)
        QTableView::setModel(m);
}

void LVTableView::closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint)
{
    QTableView::closeEditor(editor,hint);
}


LVTableItemDelegate.cpp
#include "LVTableItemDelegate.h"

#include "Sector.h"
#include "BaseLineCalcControls.h"
#include "LVModel.h"
#include "LVModelEditController.h"
#include "LVEditors.h"

LVTableItemDelegate::LVTableItemDelegate(LVModelEditController*mec, QWidget *parent /* = 0 */)
    : QItemDelegate(parent)
{
}

LVTableItemDelegate::~LVTableItemDelegate()
{
    if (m_modelEditController)
        delete m_modelEditController;
}

void LVTableItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QItemDelegate::paint(painter, option, index);
}

QWidget* LVTableItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{    
    if (index.column() == LVModel::VISIBLE_ID)
        return 0;
    else if (index.column() == LVModel::NUMBER_ID)
    {
        QComboBox *combo = qobject_cast<QComboBox*>(LVEditors::LVSectorNameEditor(m_modelEditController->field(index), m_sectorNames, parent).editor());
        return combo;
    }        
    else if (index.column() == LVModel::SPECRESISTLEP_ID)
    {
        QComboBox *combo = qobject_cast<QComboBox*>(LVEditors::LVWireSpecResistEditor(m_activeResistNames,m_activeResistSections,parent).editor());
        return combo;
    }
        else
        return QItemDelegate::createEditor(parent, option, index);
}

void LVTableItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    if (index.column() == LVModel::NUMBER_ID)
    {
        QString text = index.model()->data(index).toString();
        LVEditors::LVSectorNameEditor::setData(editor,QVariant(text));
    }
    else if (index.column() == LVModel::SPECRESISTLEP_ID)
    {
        QString text = index.model()->data(index).toString();
        LVEditors::LVWireSpecResistEditor::setData(editor,QVariant(text));
    }
    else
        QItemDelegate::setEditorData(editor,index);
}

void LVTableItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
        if (index.column() == LVModel::NUMBER_ID)
    {
        QString text = LVEditors::LVSectorNameEditor::getData(editor).toString();
        model->setData(index, text);
    }
    else if (index.column() == LVModel::SPECRESISTLEP_ID)
    {
        QString text = LVEditors::LVWireSpecResistEditor::getData(editor).toString();
        QString sectionText = LVEditors::LVWireSpecResistEditor::getSectionData(editor).toString();
        model->setData(index, text);
        QModelIndex sectionIndex = model->index(index.row(),LVModel::CABLESECTION_ID);
        model->setData(sectionIndex,sectionText);
    }
    else
        QItemDelegate::setModelData(editor,model,index);
}

void LVTableItemDelegate::updateEditorGeometry ( QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
    QItemDelegate::updateEditorGeometry(editor,option,index);
}


LVEditors.h
#ifndef LVEDITORS_H
#define LVEDITORS_H

#include "BaseEditor.h"

#include <QComboBox>
#include <QLineEdit>
#include <QFile>
#include <QTextStream>
#include <QCheckBox>
#include <QStringList>

#include "LVSector.h"
#include "BaseBreakNode.h"
#include "LVNode.h"

namespace LVEditors
{
    /************************************************************************/
    /*     LVSectorNameEditor - редактор поля Номер участка                   */
    /*     Входные параметры:                                                    */
    /*        sector - участок ЛЭП                                            */
    /*        parent - родительский Widget                                    */
    /*     Выходные параметры:                                                */
    /*        m_editor - Widget редакитрования Номера участка                    */
    /*        доступ через метод editor()                                        */
    /************************************************************************/
    class LVSectorNameEditor
        : public BaseEditor
    {
    public:
        LVSectorNameEditor(Sector*sector, QStringList* sectorNames, QWidget*parent = 0)
            : m_sector(sector), m_sectorNames(sectorNames), m_parent(parent)
        {
            m_editor = 0;
            init();
        }
        virtual ~LVSectorNameEditor(){};
        void init()
        {
            QComboBox *combo = new QComboBox(m_parent);
            combo->setSizeAdjustPolicy(QComboBox::AdjustToContents);
            QLineEdit*lineEdit = new QLineEdit();
            combo->setLineEdit(lineEdit);
            LVSector* lvsector = dynamic_cast<LVSector*>(m_sector);
            if (lvsector && lvsector->getPrevNode())
                combo->addItem(lvsector->getName());
            if (dynamic_cast<LVNode*>(lvsector->getNode()))
                combo->addItem(lvsector->getName());
            combo->addItem(BaseBreakNode::getBreakString());
            if (m_sectorNames)
                for (int i = 0; i < m_sectorNames->size(); i++)
                    combo->addItem(m_sectorNames->at(i));
            m_editor = combo;
        }
        static QVariant getData(QWidget* widget)
        {
            QComboBox *comboBox = qobject_cast<QComboBox*>(widget);
            return QVariant(comboBox?comboBox->currentText():"");            
        }
        static void setData(QWidget* widget, QVariant val)
        {
            QComboBox *comboBox = qobject_cast<QComboBox*>(widget);
            if (comboBox)
            {
                int comboIndex = comboBox->findText(val.toString());
                comboBox->setCurrentIndex(comboIndex);
            }
        }
    private:
        QStringList* m_sectorNames;
        Sector* m_sector;
        QWidget*m_parent;
    };

    /************************************************************************/
    /*     CableComboBox            - Widget для редактирвоания поля Удельное   */
    /*                                активное сопротивление ВЛ (Rо.вл)        */
    /*     Входные параметры:                                                    */
    /*        parent - родительский Widget                                    */
    /*     Поля:                                                                */
    /*        section - список доступных площадей сечений провода                */
    /************************************************************************/
    class CableComboBox : public QComboBox
    {
    public:
        CableComboBox(QWidget *parent = 0)
            :QComboBox(parent)
        {
        };
        ~CableComboBox(){};

        QStringList section;
    };

    /************************************************************************/
    /*     LVWireSpecResistEditor - редактор поля Удельное активное            */
    /*                              сопротивление ВЛ (Rо.вл)                    */
    /*     Входные параметры:                                                    */
    /*        parent - родительский Widget                                    */
    /*     Выходные параметры:                                                */
    /*        m_editor - Widget редакитрования Удельное активное                */
    /*                    сопротивление ВЛ (Rо.вл)                            */
    /*        доступ через метод editor()                                        */
    /************************************************************************/
    class LVWireSpecResistEditor
        : public BaseEditor
    {
    public:
        LVWireSpecResistEditor(QStringList* activeResistNames, QStringList* activeResistSections, QWidget*parent = 0)
            : m_parent(parent), m_activeResistNames(activeResistNames), m_activeResistSections(activeResistSections)
        {
            m_editor = 0;
            init();
        }
        ~LVWireSpecResistEditor(){};
        void init()
        {
            CableComboBox *comboBox = new CableComboBox(m_parent);
            comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
            if (m_activeResistNames && m_activeResistSections)
                for (int i = 0; i < m_activeResistNames->size(); i++)
                {
                    comboBox->addItem(m_activeResistNames->at(i));
                    comboBox->section.append(m_activeResistSections->at(i));
                }
            m_editor = comboBox;
        }
        static QVariant getData(QWidget* widget)
        {
            QComboBox *comboBox = qobject_cast<QComboBox*>(widget);
            return QVariant(comboBox?comboBox->currentText():"");            
        }
        static void setData(QWidget* widget, QVariant val)
        {
            CableComboBox *comboBox = dynamic_cast<CableComboBox*>(widget);
            if (comboBox)
            {
                int comboIndex = comboBox->findText(val.toString());
                comboBox->setCurrentIndex(comboIndex);
            }
        }
        static QVariant getSectionData(QWidget* widget)
        {
            CableComboBox *comboBox = dynamic_cast<CableComboBox*>(widget);
            return QVariant((comboBox && comboBox->currentIndex() > -1)?comboBox->section.at(comboBox->currentIndex()):"");
        }
    private:
        QStringList *m_activeResistSections;
        QStringList *m_activeResistNames;
        QWidget*m_parent;
    };
};
#endif //LVEDITORS_H


Классу LVTableView назначается делегат LVTableItemView, в методе createEditor создаются два редактора для сответствующих слобцов таблицы:
LVWireSpecResistEditor
и
LVSectorNameEditor.

для первого используется наследник QComboBox - CableComboBox.

ПРОБЛЕМА: при потере фокуса Editor-а или нажатии Enter при активном Editor-е наблюдается два исхода:
1. отрабатывает как должно: из Editor-а данные переносятся в модель и редактор удалется.
2. отрабатывает не корректно: из Editor-а данные переносятся в модель, а редактор не удаляется, а остается активным. Причем ни обновление данных в модели, ни потеря фокуса Editor-ом ни нажатие Enter не приводят к удалению Editor-а.
Соотношение корректных и некорректных исходов где то 80 на 20.

Если кто сталкивался с такой проблемой подскажите как ее решить.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BlueIceScream
  опции профиля:
сообщение 29.12.2011, 16:04
Сообщение #2


Студент
*

Группа: Участник
Сообщений: 56
Регистрация: 21.11.2011
Из: Республика Дагестан
Пользователь №: 3016

Спасибо сказали: 18 раз(а)




Репутация:   3  


Что то в вашем коде я не заметила

emit commitData
emit closeEditor

void QAbstractItemDelegate::closeEditor ( QWidget * editor, QAbstractItemDelegate::EndEditHint hint = NoHint ) [signal]
void QAbstractItemDelegate::commitData ( QWidget * editor ) [signal]
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
smallmazila
  опции профиля:
сообщение 30.12.2011, 4:47
Сообщение #3


Новичок


Группа: Новичок
Сообщений: 2
Регистрация: 29.12.2011
Пользователь №: 3102

Спасибо сказали: 0 раз(а)




Репутация:   0  


я так понял что если не вызывать emit CommitData и emit closeEditor, то они будут генерироваться по умолчанию для каждого editor-а при завершении редактирования.

при отладке метод closeEditor класса LVTableView вызывается.

НАБЛЮДЕНИЕ: в некоторых случаях при завершении редактирования этот метод вызывается 2 раза. После этого editor не удаляется с экрана и некоторое время LVTableView не реагирует на двойной клик мыши.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BlueIceScream
  опции профиля:
сообщение 30.12.2011, 14:51
Сообщение #4


Студент
*

Группа: Участник
Сообщений: 56
Регистрация: 21.11.2011
Из: Республика Дагестан
Пользователь №: 3016

Спасибо сказали: 18 раз(а)




Репутация:   3  


Цитата
я так понял что если не вызывать emit CommitData и emit closeEditor, то они будут генерироваться по умолчанию для каждого editor-а при завершении редактирования

И как вы это поняли? Как представление узнает что виджет больше не нужен?

Попробуйте все-таки явно генерировать closeEditor и commitData

свяжите их с сигналом returnPressed(или аналогичным) вашего виджета редактирования

типа такого например как для QLineEdit

QWidget *<item delegate class>::createEditor (....)
{
  QLineEdit * editor = new QLineEdit(parent);
  connect (editor,SIGNAL(returnPressed()),this,SLOT(editorCloser()));
  return editor;
}

void <item delegate class>::editorCloser()
{
  QLineEdit * lineEdit = qobject_cast<QLineEdit*>(sender());
  emit commitData(lineEdit);
  emit closeEditor(lineEdit);
}


Сообщение отредактировал BlueIceScream - 30.12.2011, 15:28
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 17.2.2025, 12:44