PDA

View Full Version : Custom editor-delegate communication



AlexVhr
19th December 2012, 11:36
I've got a custom editor (nothing fancy - a widget with a couple of buttons and a label on it), which is linked to a model by a simple custom delegate via QDataWidgetMapper. The delegate calls setEditorData() and everything is fine, until the time when user ends editing in the widget. At this point data should be relayed back to the model, but the delegate does not have any idea that user is done with the editor, so setModelData() does not get called. So the question is - how do I notify the delegate that it's time to commit the data to the model? Thanks!

anda_skoa
19th December 2012, 13:58
http://qt-project.org/doc/qt-4.8/qabstractitemdelegate.html#commitData

AlexVhr
19th December 2012, 14:51
I've seen this, but how can it be used in practice? It's a signal - but which slot should I connect it to? Or do I just call it as a method? If yes, then how can my editor widget know, which delegate it is connected to? It's just a widget. Do I need to explicitly pass a delegate reference to editor's widget's constructor?

anda_skoa
20th December 2012, 18:06
You don't have to connect the signal to anything, this is done somewhere in the view. You or rather your delegate is the one notifying the view about editing finished.

There are several ways to get that signal emitted.

Your editor could emit an "editing finished" signal that has the editor itself as its argument. In this case you can simply connect that signal to commitData.
Your editor could emit a signal and you have a slot in your delegate that is connected to that and in that slot you emit commitData with the editor widget's pointer as its argument.
You could pass the delegate to the editor and do a signal/signal connect there.
You could add a method to your delegate that emits commitData, pass the delegate to the editor and have the editor call that method.

Cheers,
_

AlexVhr
30th December 2012, 22:48
Sorry for the delay - was chased from my town by angry customers. Back to the topic...


You don't have to connect the signal to anything, this is done somewhere in the view. You or rather your delegate is the one notifying the view about editing finished._

Whoops, forgot to mention a little detail - there is no view, the editor is placed on a QWidget and connected to the model through a QDataWidgetMapper. So, it's the editor who knows when the editing is finished.




There are several ways to get that signal emitted.
Your editor could emit an "editing finished" signal that has the editor itself as its argument. In this case you can simply connect that signal to commitData._

Can you be more specific? Connect to what object's commitData(), exactly? Delegate does not have a slot with the name "commitData", it has a signal with the same name. But I tried to do like you said - I declared MyEditorClass.editingFinished(QWidget) signal, connected myEditorInstance.editingFinished to myDelegateInstance.commitData, ensured that myEditorInstance.editingFinished.emit(myEditorInst ance) is called, and nothing is happening, i.e., myDelegateInstance.setModelData() is not called.




Your editor could emit a signal and you have a slot in your delegate that is connected to that and in that slot you emit commitData with the editor widget's pointer as its argument. _

Tried that too: I declared MyEditorClass.editingFinished(QWidget) signal, declared MyDelegate.testSlot(QWidget), connected them, and inside testSlot() I did commitData.emit(editor). The myDelegateInstance.testSlot(editor) is called correctly, but that's it. Emitting myDelegate.commitData(editor) does not have any result.



You could pass the delegate to the editor and do a signal/signal connect there.
You could add a method to your delegate that emits commitData, pass the delegate to the editor and have the editor call that method. _

Could I see some code, please? An example, a tutorial - anything?

wysota
31st December 2012, 00:11
QDataWidgetMapper is the "view" in this case.

AlexVhr
31st December 2012, 07:10
QDataWidgetMapper is the "view" in this case.

And what does that practically mean in the given case? QDataWidgetMapper does not have commitData() slot\signal\method. Is it supposed to emit it somehow by itself? If yes, then how do I "motivate" it to do that?

anda_skoa
31st December 2012, 12:24
Both things you tried should have worked.
I've checked the code of QDataWidgetMapper and commitData doesn't do anything in the case that QDataWidgetMapper::submitPolicy is "Manual submit".

You could try changing that to AutoSubmit or connecting some signal to QDataWidgetMapper::submit() or call submit manually.

Cheers,
_

AlexVhr
31st December 2012, 13:57
It is set to AutoSubmit, actually. And standard editor widgets (QLineEdit etc) work perfectly.

wysota
2nd January 2013, 13:49
It is set to AutoSubmit, actually. And standard editor widgets (QLineEdit etc) work perfectly.

Does your editor class have a USER property defined along with a NOTIFY signal for it? Do you have a mechanism for determining the user is done with using the editor? I think this is where NOTIFY signal for a USER property kicks in with default Qt editor widgets. Also have a look at QItemEditorFactory and QItemEditorCreator classes.

AlexVhr
30th January 2013, 11:42
So far I've managed to make it work with Tab key, but clicking away is still not producing desired results. Here (http://pastebin.com/95sknVHs)is the full test case, if someone cares to look at it (it's Python + PySide though)

Added after 1 49 minutes:

Ok, it looks like the problem was caused by my way of dealing with the fact that QDataWidgetMapper only supports a single delegate. After getting rid of my 'universal delegate' everything works using signals as it should. The only problem now is to get around that 'one delegate per QDataWidgetMapper' problem.