QComboBox, созданный с помощью StyledItemDelegate, не выбирает правильное значение при настройке данных модели - почему? - PullRequest
0 голосов
/ 07 июня 2019

Мне нужно добавить функцию в сложный редактор панелей, который я унаследовал. Базовый класс панели редактора VSP инициализируется в соответствии со стандартной парадигмой VMC. В настоящее время он поддерживает создание редакторов ячеек (или элементов) типа QDoubleSpinBox (для целых, двойных и т. Д.); QComboBox для bools; и окно QLineEdit для всего остального. Мне нужно добавить случай, когда я создаю определенный QComboBox для некоторых перечислений языка QString (например, "english", "french"). Когда я делаю это, мне кажется, что я никогда не могу выделить какой-либо текстовый элемент в раскрывающемся списке, и он постоянно возвращается к значению по умолчанию. Что я делаю не так и как я могу это исправить?

// cfgEdVSP.cpp

bool CfgEdVSP::init()
{
    delete m_viewLayout;
    delete m_view;
    delete m_model;

    // Setup GUI Model
    m_model = new VSPTreeModel(m_schemaFile, m_nodes, this);

    // Setup GUI View
    m_view = new QTreeView(this);
    m_view->setSelectionBehavior(QAbstractItemView::SelectRows);
    m_view->setSelectionMode(QAbstractItemView::SingleSelection);

    // Attach the Model to the View
    m_view->setModel(m_model);

    // Setup GUI Model-View Delegate
    m_view->setItemDelegate(new VSPItemDelegate(this));

    m_view->header()->resizeSection(1, 240);
    m_view->header()->setResizeMode(0, QHeaderView::ResizeToContents);
    m_view->header()->setResizeMode(1, QHeaderView::ResizeToContents);
    m_view->header()->resizeSection(1, 140);
    m_view->header()->setResizeMode(2, QHeaderView::ResizeToContents);
    m_view->header()->resizeSection(2, 80);
    m_view->header()->setResizeMode(3, QHeaderView::ResizeToContents);
    m_view->header()->resizeSection(3, 80);
    m_view->header()->setResizeMode(4, QHeaderView::Stretch);
    m_view->header()->resizeSection(4, 80);
    m_view->expandToDepth(0);

    // The view will take the form of a QHBoxLayout (i.e. widgets lined up horizontally)
    m_viewLayout    = new QHBoxLayout();
    m_viewLayout->addWidget(m_view, 1);
    addMainLayout(m_viewLayout);

...

    // setup context menu used for editing (similar to CfgEdADG <R-CLK>, copy/paste, etc )
    createActions();

    // [1] set property Qt:CustomContextMenu so that the view will emit a
    // customContextMenuRequested() signal (see below).
    m_view->setContextMenuPolicy(Qt::CustomContextMenu);

    m_valPopup = new QMenu(m_view);

...

    // [2] Ensure that we have a SLOT to match the customContextMenuRequested signal
    connect(m_view, SIGNAL(customContextMenuRequested(const QPoint &)),
                     SLOT(vspTableContextMenuRequested(const QPoint &)));

    return true;
}

// VSPTreeModel.h

class VSPTreeModel : public QAbstractItemModel
{
    Q_OBJECT

public:
    VSPTreeModel(const QString& schemaFile,
                 const QVector<VSPConfigNode>& nodes,
                 QObject *parent = 0);
    ~VSPTreeModel();

...

    bool setData(const QModelIndex &index, const QVariant &value,
                 int role = Qt::EditRole); 
}

// VSPTreeModel.cpp

bool VSPTreeModel::setData(const QModelIndex &index, const QVariant &value,
                        int role)
{
    QString strValue = value.toString();

    if (role != Qt::EditRole)
        return false;

    VSPTreeItem *item = getItem(index);  //Note if index is invalid will return rootItem
    bool result = item ? item->setData(index.column(), value) : false;

    if (result)
        emit dataChanged(index, index);

    return result;
}

// VSPItemDelegate.h 

class VSPItemDelegate : public QStyledItemDelegate {
   Q_OBJECT

public:

    VSPItemDelegate(QObject* parent = 0) : QStyledItemDelegate(parent){}                                         m_logger(Logger::getInstance("VSP")){} 

    QWidget* createComboBoxEditor(QWidget *parent,
                                  const QStyleOptionViewItem & option,
                                  const QModelIndex & index ) const;


    QWidget* enumEditor(QWidget* parent, const QStyleOptionViewItem 
& option, const QModelIndex & index) const;

private:
    Logger *m_logger;
};

// VSPItemDelegate.cpp

QWidget * VSPItemDelegate::createEditor ( QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
    VSPTreeItem* item = reinterpret_cast<VSPTreeItem*> (index.internalPointer());
    ConfigTableDataset* data = item->getData();

    // We're going to call the PARENT CLASS createEditor method...
    // This returns the widget used for editing the data item specified by
    // the index value given, UNLESS...

    // If data is an ENUM or BOOL then ensure a QComboBox is created

    QWidget *editor = NULL;

// CODE I ADDED START ##########################################
    if ( (data->type() == CfgNode::ENUM) ) 
    {
       editor = ((QComboBox *)enumEditor(parent, option, index));
       return editor;
    } 
// CODE I ADDED END  ###########################################
    else 
    {
       editor = QStyledItemDelegate::createEditor(parent, option, index);
    }

    if (!index.internalPointer())
        return editor;

    if(QDoubleSpinBox* sbox = dynamic_cast<QDoubleSpinBox*>(editor))
    {
...
    }
    else if(QComboBox* cbox = dynamic_cast<QComboBox*>(editor))
    {
        if(data->type() == CfgNode::BOOL) {
            cbox->setItemText(0, cbox->itemText(0).toLower());
            cbox->setItemText(1, cbox->itemText(1).toLower());
        }
    }
    else if (QLineEdit* editBox = dynamic_cast<QLineEdit*>(editor))
    {
...

    }
    else
    {
// UNKNOWN TYPE OF EDITOR
...
    }
    return editor;
}

// CODE I ADDED START ##########################################
QWidget * VSPItemDelegate::enumEditor(QWidget* parent, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
    QComboBox* cbox = new QComboBox(parent);

    QStringList languageList;
    languageList << "english" << "french";
    cbox->insertItems(0, languageList);

    return cbox;
}
// CODE I ADDED END  ###########################################

С моими изменениями или без них ожидаемые результаты для числового, логического и текстового редактирования работают корректно и содержат правильное значение, тогда наступает момент, когда VSPTreeModel :: setData () добавит новое значение в модель. Экран панели также правильно обновлен. Обратите внимание, что это похоже на поведение по умолчанию QStyledTemDelegate, поскольку нет явного метода VSPItemDelegate :: SetModelData (). Однако для дополнительного случая перечисления QComboBox значение равно НЕПРАВИЛЬНО, когда выполняется VSPTreeModel :: setData () (например, «english», когда оно должно быть «французским», и панель всегда обновляется, возвращается к значению по умолчанию: «english») , Кроме того, я нахожу странным, что метод VSPItemDelegate :: createEditor () вызывается AT ALL, поскольку я не могу найти для этого никакой ссылки на соединение SIGNAL / SLOT. Я очень новичок в Qt, поэтому не знаю, будет ли это поведение по умолчанию?!?

...