Size of editor in QItemDelegate

623 views Asked by At

I have a custom Delegate, subclassed from QItemDelegate, that provides a QComboBox in the very first column and a QLineEdit in all other columns.

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);
}

The editTrigger has been set to selectClicked. I want the combo box to cover the entire cell in the QTableView. However, now it just appears as blip on the left hand corner. I tried setting the minimum size by passing the cell size through an event filter that listens for mousePressed on QTableView. However, the corresponding slot in the delegate is never called. Here's the code:

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;
}

installed on qApp.

MainWindow.cpp:

eFilter = new MultiEventFilter();
    connect(eFilter, SIGNAL(passCellSize(QSize)),
            sensor_display_delegate, SLOT(setEditorSize(QSize)));

SensorDisplayDelegate.cpp slot:

void SensorDisplayDelegate::setEditorSize(const QSize &size)
{
    editorSize = size;
}

where QSize editorSize is a private member. How can I set the size of the editor correctly? I need something general that can be applied to the QLineEdit editors as well. Also, is it necessary to explicitly emit commitData() when the editor is closed? I have not seen this done in any example codes involving QComboBox.

1

There are 1 answers

0
tinkertime On

I suspect your eventFilter is intercepting the click events before the selection indexes have been set. So, you're effectively always hitting an empty idxs IndexList?

Try replacing that loop with something like:

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()));
    }
}