PDA

View Full Version : Custom item delegate gets the wrong editing widget in eventFilter



forgottenduck
27th October 2014, 21:48
So I've implemented a custom text edit widget which only accepts numbers and other math symbols as edit, as well as doing some other stuff with the key press event. My widget works fine when tested on it's own but it seems that when it is used in the delegate that I created it doesn't receive the keypressevents.

After some research I determined that I was missing a crucial part of my custom delegate implementation. I still needed to implement eventFilter() and return false on a keypress event so that the editor would receive the event. What I discovered while doing this is that my delegate seems to be using a QExpandingLineEdit instead of my custom editor. So even with the event filter, my custom widget is not getting the keypress events. I don't understand what I'm missing from my implementation.



MathEditDelegate::MathEditDelegate(QObject *parent) :
QStyledItemDelegate(parent)
{
}

void MathEditDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const{
if(MathEdit* edit = qobject_cast<MathEdit*>(editor)){
QString currentText = index.data(Qt::DisplayRole | Qt::EditRole).toString();
edit->setHtml(currentText);
}
else
QStyledItemDelegate::setEditorData(editor, index);
}

bool MathEditDelegate::eventFilter(QObject *editor, QEvent *event){
if(event->type()==QEvent::KeyPress){
qDebug()<<editor->metaObject()->className(); //This should be MathEdit, but instead is always QExpandingLineEdit
return false;
}
return QStyledItemDelegate::eventFilter(editor, event);
}

void MathEditDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const{
if(MathEdit* edit = qobject_cast<MathEdit*>(editor)){
model->setData(index, edit->toHtml(), Qt::DisplayRole | Qt::EditRole);
}
else
QStyledItemDelegate::setModelData(editor, model, index);
}

QWidget* MathEditDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/*option*/, const QModelIndex &/*index*/){
MathEdit* edit = new MathEdit(parent);
return edit;
}

I've implemented createEditor so shouldn't the editor in eventFilter be the editor I created and not the default "QExpandingLineEdit"?
Upon further testing, I noticed that all of my functions with editor as an argument are coming in as QExpandingLineEdits and not MathEdits. I even made a minimal example with just a standard table view and model with the delegate assigned, and I got the same results as I did in the larger project. I have no idea what I'm missing.

Any insight would be appreciated.


EDIT:
Turns out I was just missing the override keyword on my methods. How embarrassing.

d_stranz
27th October 2014, 22:30
Turns out I was just missing the override keyword on my methods. How embarrassing.

The methods you show are already defined as virtual in the base classes you inherit from. You shouldn't need to add any keyword to have them treated as such in a derived class, unless C++-11 has turned the semantics of virtual methods on its head.

And why do you install an event filter? Shouldn't you just reimplement the QAbstractItemDelegate::editorEvent() method instead?

anda_skoa
28th October 2014, 08:33
The methods you show are already defined as virtual in the base classes you inherit from. You shouldn't need to add any keyword to have them treated as such in a derived class, unless C++-11 has turned the semantics of virtual methods on its head.

C++11 and onward do not change the behavior of virtual. The override keyword helps to detect when one is not actually overriding, e.g. when there is a signature mismatch or the virtual gets removed from the base class.

Cheers,
_

forgottenduck
28th October 2014, 14:14
And why do you install an event filter? Shouldn't you just reimplement the QAbstractItemDelegate::editorEvent() method instead?

As I understand editorEvent(), it is the method called when the editor is opened, while eventFilter is used to capture all the events while the editor is open. Using eventFilter() I was able to get the events to pass to my editor widget (after adding override).

wysota
28th October 2014, 14:20
"override" is a compile time check, it cannot make your software "start working". And you shouldn't need to filter events, the editor will receive key events in its keyPressEvent() implementation.

forgottenduck
30th October 2014, 21:40
It definitely seems like you're right about that. I must have changed something else to get it working because removing override and getting rid of eventFilter(), changed nothing about how the application behaves. Anyway, it's been working as intended so I doubt I'll go back and track down the issue I was having.

Thanks for your help.