Мне нужно добавить функцию в сложный редактор панелей, который я унаследовал. Базовый класс панели редактора 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, поэтому не знаю, будет ли это поведение по умолчанию?!?