У меня есть собственный делегат, подкласс из QItemDelegate, который предоставляет QComboBox в самом первом столбце и QLineEdit во всех остальных столбцах.
SensorDisplayDelegate::SensorDisplayDelegate(QObject *parent) :
QItemDelegate(parent)
{}
QWidget *SensorDisplayDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
int col = index.column();
if(col == 0)
{
QComboBox *comboBox = new QComboBox(parent);
connect(comboBox, SIGNAL(activated(int)), this, SLOT(setData(int)));
comboBox->setEditable(false);
//comboBox->setMaximumSize(editorSize);
comboBox->setInsertPolicy(QComboBox::NoInsert);
currentComboBox = comboBox;
return comboBox;
}
else
{
QLineEdit *lineEdit = new QLineEdit(parent);
return lineEdit;
}
return NULL;
}
void SensorDisplayDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
int col = index.column();
if(col == 0)
{
QComboBox *comboBox = static_cast<QComboBox*>(editor);
QStringList comboItems = index.data(Qt::EditRole).toStringList();
comboBox->addItem("Add New Sensor");
comboBox->addItems(comboItems);
QCompleter *completer = new QCompleter(comboItems);
completer->setCaseSensitivity(Qt::CaseInsensitive);
comboBox->setCompleter(completer);
comboBox->showPopup();
}
else
{
QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
lineEdit->setText(index.data(Qt::EditRole).toString());
lineEdit->show();
}
}
void SensorDisplayDelegate::setModelData(QWidget *editor,
QAbstractItemModel *model,
const QModelIndex &index) const
{
int col = index.column();
if(col == 0)
{
QComboBox *comboBox = static_cast<QComboBox*>(editor);
if(comboBox->currentIndex() == 0)
emit addNewSensor();
else
emit populateSensorView(comboBox->currentText());
}
else
{
QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
model->setData(index, QVariant(lineEdit->text()));
}
}
void SensorDisplayDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
{
editor->setGeometry(option.rect);
}
QSize SensorDisplayDelegate::sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
return editorSize;
}void SensorDisplayDelegate::setData(int option)
{
emit commitData(currentComboBox);
emit closeEditor(currentComboBox);
}
EditTrigger был установлен в selectClicked. Я хочу, чтобы поле со списком покрывало всю ячейку в QTableView. Тем не менее, теперь это просто выглядит как блик в левом углу. Я попытался установить минимальный размер, передавая размер ячейки через фильтр событий, который прослушивает mousePressed в QTableView. Однако соответствующий слот в делегате никогда не вызывается. Вот код:
MultiEventFilter.cpp:
bool MultiEventFilter::eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::MouseButtonPress)
{
if(obj->objectName() == "sensorlocationTableView")
{
QTableView *sensorView = static_cast<QTableView*>(obj);
QModelIndexList idxs = sensorView->selectionModel()->selectedIndexes();
if(!idxs.empty())
{
QModelIndex idx = idxs.at(0);
emit passCellSize(QSize(sensorView->columnWidth(idx.column()),
sensorView->rowHeight(idx.row())));
}
}
}
return false;
}
установлен на qApp.
mainwindow.cpp:
eFilter = new MultiEventFilter();
connect(eFilter, SIGNAL(passCellSize(QSize)),
sensor_display_delegate, SLOT(setEditorSize(QSize)));
Слот SensorDisplayDelegate.cpp:
void SensorDisplayDelegate::setEditorSize(const QSize &size)
{
editorSize = size;
}
где QSize editorSize является закрытым членом.
Как правильно установить размер редактора? Мне нужно что-то общее, что можно применить и к редакторам QLineEdit.
Кроме того, необходимо ли явно использовать commitData (), когда редактор закрыт? Я не видел, чтобы это было сделано ни в одном примере кода с участием QComboBox.
Я подозреваю, что ваш eventFilter
перехватывает события щелчка до того, как были установлены индексы выбора. Таким образом, вы эффективно всегда поражаете пустое idxs
IndexList?
Попробуйте заменить этот цикл на что-то вроде:
bool MultiEventFilter::eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::MouseButtonPress)
{
if(obj->objectName() == "sensorlocationTableView")
{
emit locationTableViewClicked();
}
}
return false;
}
....
connect(eFilter, SIGNAL(locationTableViewClicked()),
sensor_display_delegate, SLOT(setEditorSize()));
...
void SensorDisplayDelegate::setEditorSize()
{
QModelIndexList idxs = sensorView->selectionModel()->selectedIndexes();
if(!idxs.empty())
{
QModelIndex idx = idxs.at(0);
editorSize = QSize(sensorView->columnWidth(idx.column()),
sensorView->rowHeight(idx.row()));
}
}
Других решений пока нет …