PDA

View Full Version : Models and Delegates



bgeller
25th February 2010, 23:55
I have successfully set up a ui form with a QTableView, the model is set to QSqlRelationTableModel. The basic operations are working. Now I need to enhance some of the columns to alter the display of the data and how the data will be edited.

I am fine with subclassing both the model and the delegate. However I am a bit baffled about what methods comprise or belong in the model and what belongs in the delegate. I have reviewed the Qt documentation as best as I can, but I feel that I am missing some fundamental understanding about these classes. I have read through several examples but nothing seems to provide a clear definition of when the methods in these
classes are called.

For example, I was able to alter the display of one column in the model by adding the data() method to my custom model. But then I read that paint() in the delegate should handle this.

Can anyone shed some light on this issue? If there is a more appropriate group in this forum to post my question, please let me know.

Thank you,

Barbara

JohannesMunk
27th February 2010, 10:52
Maybe chapter 10 of Mark Summerfields book will help you?

http://www.qtrac.eu/marksummerfield.html

http://www.qtrac.eu/C++-GUI-Programming-with-Qt-4-1st-ed.zip

Johannes

bgeller
27th February 2010, 17:15
I have the 2nd Edition of his book and have read Chapter 10 and Chapter 13 multiple times. There is no documentation in the book that clearly says when you should override the model and when you should override the delegate. There seems to be multiple ways to do the same thing but no clear documentation as to the best approach.

I have searched a lot so far, but I am unable to find anything other than the very basic info saying that you can use a model and a delegate.

It was nice to get a reply. I am wondering if I should post my question in a different area on the forum. Is there a moderator that can tell me if that is ok or would help me any faster?

Barbara

aamer4yu
27th February 2010, 17:52
For example, I was able to alter the display of one column in the model by adding the data() method to my custom model.
Can you tell how you were able to alter the display ??
Model is for what is the data. Delegates are for how the data is displayed. For example if you want to display the text in color, what will you choose to alter, model or delegate ?
:rolleyes:

bgeller
27th February 2010, 18:36
Can you tell how you were able to alter the display ??
Model is for what is the data. Delegates are for how the data is displayed. For example if you want to display the text in color, what will you choose to alter, model or delegate ?


Sorry, I am not sure what you reply was saying. Are you asking me how I used the data() method in the modal to alter the display? I am testing to ensure I am in the correct column and if the role is DisplayRole. Then I take the model value, which was a double and convert it into a string. The display in my table is exactly what I want to see. So this does work. But it may not be the most efficient.

I have seen some documentation that says you should alter the display in the paint() method in the delegate. Ok, which approch is more correct? Are there speed issues, memory issues? What are the trade offs?

And since I can alter the display in the model, should I alter the edit their too? I have seen other samples that indicate the createEditor() in the delegate is the place to change how the data in the table is edited.

I am more than happy to provide more details if needed. My thanks for any feedback.

Barbara

franz
2nd March 2010, 20:03
The model merely provides hints for displaying. It depends on the delegate whether for example the Qt::BackgroundColorRole is actually used or not.

bgeller
2nd March 2010, 21:47
I am not sure what you mean by "hints for displaying". In my model I have changed the display for one columns from a double to a QString. There is no hinting, it does work.

What you have said does not pertain to my question. I have seen some explanations saying the model class provides the interface that views and delegates use to access data. My main issue is what methods should be part of the model and what goes in the delegate.

I can modify the displayed information from the model by using the data() method. I could also alter the display by using the paint() method in the delegate. The issue is, which is the correct way to implement this. Are there any trade offs?

franz
3rd March 2010, 06:47
My view on this is that if the actual information changes, then you should do that in the model. The delegate decides how things are rendered or edited, so if you want to change how things are displayed or edited you change the delegate.

aamer4yu
3rd March 2010, 06:52
I guess you are a bit confused, and confusing others too. Dont mix the data and display part.
I will try to explain somewhat :
Model is used for getting data. There are various roles which provide data based on context. Lets take a QListWidget for example.
The text you see is fetched from model via display role, the icon, if any, from decoration role. So these data are fetched from model.(QListWidget maintains a model internally)
But wait, these are simply fetched, not drawn. So its like you know you need to draw something, and you know what to draw. But who does the drawing ? Delegates :-)
Even the view uses delegates to do the drawing. Say your list widget has items "one","two", etc. You know need to draw "one". But what color ? what font ? what position ? These are decided by the delegate.

Hope this clears you a bit.
As for editors, yes you are right that delegates handle the editors. Editors are like temporary widget which do some processing on data, and return you data in new format.
For example in the spin box delegate, you see some integer say "10". Now you want to increase,, so when you double click, the view triggers the event and delegate returns a editor. This editor is a spin box, You set 10 to it intiially, and when it is finished, you get the updated value. This updated value is stored in the model. Rest is again history :D

wysota
3rd March 2010, 08:46
Sorry, I am not sure what you reply was saying. Are you asking me how I used the data() method in the modal to alter the display? I am testing to ensure I am in the correct column and if the role is DisplayRole. Then I take the model value, which was a double and convert it into a string. The display in my table is exactly what I want to see. So this does work. But it may not be the most efficient.
It's fine and efficient.


I have seen some documentation that says you should alter the display in the paint() method in the delegate. Ok, which approch is more correct?
What is returned by QAbstractItemModel::data() for Qt::DisplayRole is a "data piece". QAbstractItemDelegate::paint() takes multiple "data pieces" into consideration and renders them all (or some of them) to the item. They are two different mechenisms - there is no "better" here, they do different tasks.



And since I can alter the display in the model, should I alter the edit their too? I have seen other samples that indicate the createEditor() in the delegate is the place to change how the data in the table is edited.
Do you wish the data in your model to be editable? Did you implement setData() for your model?


In my model I have changed the display for one columns from a double to a QString. There is no hinting, it does work.
In your situation data() should return a double for Qt::EditRole and a QString for Qt::DisplayRole. Then the delegate picks them both up and does what it thinks is best.


My main issue is what methods should be part of the model and what goes in the delegate.
The interfaces for both classes are well defined, there shouldn't be any doubt what should go where.


I can modify the displayed information from the model by using the data() method.
You don't "modify" the data, you return the data.

bgeller
3rd March 2010, 20:13
I guess you are a bit confused, and confusing others too. Dont mix the data and display part.


I am not sure how I am confusing other people. I am simply attempting to understand the true low level funcationality of these clases.

The docs and examples I have read clearly say you can use data() in the model or paint() in the delegate. I was trying to find out the real differences and some of this is a matter of choice it seems.

I can put color information in the data() method. What I really believe is going on, is that paint() in the delegate asks the model for information. So it may not be as simple as just saying the delegate does everything.

And I have successfully been able to implement a custom editor for one of my columns. And I do see that the model is a proxy for the data.

bgeller
3rd March 2010, 20:43
It's fine and efficient. They are two different mechanisms - there is no "better" here, they do different tasks.

I believe I understand what you are saying. My issue was if there is a preferred place to make the alterations of what is displayed. As a test I was able to make the changes in both methods. So this seems to be a matter of preference.


Do you wish the data in your model to be editable? Did you implement setData() for your model? In your situation data() should return a double for Qt::EditRole and a QString for Qt::DisplayRole.

For one of my columns in the tableView, I really do want to both display it as a string and allow the user to edit it as a string. The data is best stored as a double in the sql table. I did have to re-implement several methods in the delegate and setData() in the model. I also needed to had a QValidator with a regular expression. I am impressed at how much flexibility the model / delegate classes provide.

Thanks for helping.

wysota
3rd March 2010, 20:55
The docs and examples I have read clearly say you can use data() in the model or paint() in the delegate.
It's not "or", it's "and". Always both routines are used. You can't choose between the two, you always use both.



I believe I understand what you are saying. My issue was if there is a preferred place to make the alterations of what is displayed. As a test I was able to make the changes in both methods. So this seems to be a matter of preference.
More like a matter of effect you wish to obtain. When you change the way the model returns data you affect all places where the data is used. When you change the delegate you only affect the view the delegate is installed on. Imagine you have two views showing the same data. If you modify the "looks" of the data in the model, both views will display the same thing, if you install two different delegates on each of the views, the display will differ. Also some things can't be done by changing the model - i.e. try making it display some text and two icons besides it (one on the left of the text and the other on the right of the text).



I am impressed at how much flexibility the model / delegate classes provide.
They are fine when dealing with simple situations but at some point you start stumbling against the wall. The architecture is already reaching its limits but hopefully it will be replaced (or complemented) by ItemViewsNG within a year or so.

aamer4yu
4th March 2010, 04:46
I can put color information in the data() method.
But simply having color information wont paint it in that color ! Unless your delegate knows about it. But still its the delegate that actually draws things.

I can put color information in the data() method. What I really believe is going on, is that paint() in the delegate asks the model for information.
You are getting it right. The model is the data provider, delegate the painter.