[Fixed] QStyledItemDelegate - custom Editor pop up
-
Hi,
I have this current UI:
https://www.dropbox.com/s/2a966y27uxd1sni/currentUi.pngWhen I click a field in the column "target power" I create a custom Editor and pop it up like this :
https://www.dropbox.com/s/8prshq65g0pvwfo/popUpUi.pngThen problem I have is that whenever I click the background in my custom widget, this editor get closed (if the background is also another cell of my QTableView), I thought of it and the best way would be to have a "done" button that close the editor, no other trigger should close the editor, anyway to force it to stay open?
Another thing, the text is black instead of white when the row is selected on my custom widget column, should be white like the default behavior.
Thank you,I'll post the code in the post below
-
Custom QStyledItemDelegate
-paint
@void IntervalDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{if (option.state & QStyle::State_Selected) { painter->fillRect(option.rect, option.palette.highlight()); } if (index.column() == 3) { Interval interval = index.model()->data(index, Qt::DisplayRole).value<Interval>(); QString stepTypePower = Interval::getStepTypeToString(interval.getPowerStepType()); QStyledItemDelegate::paint(painter, option, index); /// to get gray background when row selected.. painter->drawText(option.rect, Qt::AlignLeft | Qt::AlignVCenter, stepTypePower ); } else { QStyledItemDelegate::paint(painter, option, index); }
}@
-createEditor
@QWidget *IntervalDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const{
/// Duration; if (index.column() == 1 ) { QTimeEdit *editor = new QTimeEdit(parent); editor->setDisplayFormat("mm:ss"); return editor; } /// Display Msg else if (index.column() == 2 ) { QLineEdit *editor = new QLineEdit(parent); return editor; } /// Power else if (index.column() == 3 ) { PowerEditor *editor = new PowerEditor(parent); return editor; } else { return QStyledItemDelegate::createEditor(parent, option, index); } // if (index.data().canConvert<StarRating>()) { // StarEditor *editor = new StarEditor(parent); // connect(editor, SIGNAL(editingFinished()), // this, SLOT(commitAndCloseEditor())); // return editor;
}@
-setEditorData
@void IntervalDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{/// Duration; if (index.column() == 1 ) { QTime time1 = index.model()->data(index, Qt::EditRole).toTime(); QTimeEdit *timeEdit = static_cast<QTimeEdit*>(editor); timeEdit->setTime(time1); } else if (index.column() == 2 ) { QString displayMsg = index.model()->data(index, Qt::EditRole).toString(); QLineEdit *lineEdit = static_cast<QLineEdit*>(editor); lineEdit->setText(displayMsg); } /// Power else if (index.column() == 3 ) { Interval interval = index.model()->data(index, Qt::EditRole).value<Interval>(); PowerEditor *powerEditor = qobject_cast<PowerEditor*>(editor); powerEditor->setInterval(interval); } else { QStyledItemDelegate::setEditorData(editor, index); }
}@
-updateEditorGeometry
@void IntervalDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index ) const {
/// Power if (index.column() == 3) { qDebug() << "Power geo need more space to display"; editor->setGeometry(option.rect.x(), option.rect.y(), 200, 90); } else { editor->setGeometry(option.rect); }
}
@ -
Custom Widget
@PowerEditor::PowerEditor(QWidget *parent) :
QWidget(parent),
ui(new Ui::PowerEditor)
{
ui->setupUi(this);setAutoFillBackground(true);
}
//////////////////////////////////////////////////////////////////////////////////////////
void PowerEditor::setInterval(const Interval &interval) {
this->myInterval = interval;ui->spinBox_ftpStart->setValue(myInterval.getFTP_start()*100); ui->spinBox_ftpEnd->setValue(myInterval.getFTP_end()*100);
}
//////////////////////////////////////////////////////////////////////////////////////////
QSize PowerEditor::sizeHint() const {
return QSize(200, 90);
}
QSize PowerEditor::minimumSizeHint() const {
return QSize(200, 90);
}@ -
Hi,
For the editor, you might be interested by open/closePersistentEditor
-
Thanks for the tip, I tried with this function.
It is nice, but my clicks on my widget still pass trough the widget and go on the cell below it, resulting in the editor closing too soon.The use-case I would like is to remove the editor only when a click is detected outside the editor, right now the editor pop up on top of other QTable cell, so the click on the editor get trough the editor on the cell below and it close my editor. I think setting a property on my editor so that click doesnt pass would do it, but didnt work so far (Transparent to FALSE)
@ connect(ui->tableView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(cellChanged(QModelIndex,QModelIndex)) );
void WorkoutCreator::cellChanged(QModelIndex currentIndex, QModelIndex previousIndex) {
ui->tableView->closePersistentEditor(previousIndex); qDebug() << "cell changed"; if (currentIndex.column() == 3) { ui->tableView->openPersistentEditor(currentIndex); }
}
@ -
I'm also checking to use a QTreeView instead of a QTableView, would you know a good complete example of a QTreeView with a custom model? I'm wondering what data type to use, right now I have a QList<CustomObject> for my data in the QTableView model
-
with this attribute on my custom editor, it doesn't get closed when you click on the editor background.
Setting to fixed!@setAttribute(Qt::WA_NoMousePropagation);@
-
IIRC C++ GUI Programming with Qt-4 contains an example of tree model implementation