PDA

View Full Version : openPersistentEditor() -- how should it be used?



fpeelo
11th January 2008, 22:28
Hi

I want to change the way a column is displayed in a table view. Actually, I only want to display a column of booleans as checkboxes, so just selecting a different widget as the editor for all the cells in one column.

The Icons example shows a table with the editors for two columns replaced. (The Icons example also shows checkboxes in the first column. I couldn't see how to do that either, but it has to do with variants so it would be a separate topic.) This example uses QTableWidget. But I have the data in a model, as described by the "Delegate Classes" page in Qt Assistant. So the documentation for QTableWidget says I should be using QTableModel, QTableView and QItemDelegate. There is an example delegate in the documentation for using a QSpinBox as a cell control. Following this, I wrote a delegate which provides a QCheckBox editor for the cells in the table. But they don't display as checkboxes when the cell is not being edited.

In the Icons example, the cells are displayed using their custom controls by using openPersistentEditor(). I have been searching in Qt Assistant, Google and here to see how that should be used in something other than QTableWidget.

My problem is simply that, in the examples, openPersistentEditor() is used when data are added to the table. But adding data to the table is something that should be done to the table model, which does not know anything about what view is being used, whether there is a delegate or anything like that!

And the model should not know about display issues! Lots of lines are added to the table model; the view and delegate, if any, could be created much later. Then there is a setModel() so that the data can be displayed. They could be displayed in multiple views, some with persistent editors, some not.

So, only the delegate, which is the object created to make the cells display in this way, knows that the editor should be persistent. But it does not have the openPersistentEditor() method, and it does not seem to have any way to know when or how to call that method in the table view!

So, it seems to me that the view should make the editor persistent when it decides to display a cell, or maybe when it calls the delegate's createEditor() method. The delegate is the object which knows whether the editor should be persistent or not. And the actual function call to make the editor persistent is made while doing something to the data model - which should neither know nor care about the editor. Which all leaves me confused.

Are there any examples of these methods being used with the model/view architecture?

Thanks in advance

Frank

jacek
11th January 2008, 23:10
There's a difference between having a specific editor for given cell and displaying that cell's content in specific way. Although both are handled by a delegate.

As far as I understand, you want to influence the way your cell is displayed by opening a persistent editor, but this way you are just exploiting editing mechanism instead of fixing your delegate.

In case of checkboxes the easiest way is to set the Qt::ItemIsUserCheckable flag in your model.

fpeelo
12th January 2008, 17:39
There's a difference between having a specific editor for given cell and displaying that cell's content in specific way. Although both are handled by a delegate.

Thanks for your reply. Yes, that's where I started. It led to me finding openPersistentEditor() in the documentation, which seemed to be the nearest thing I could find to example/documentation of how to do what I wanted. But having found it, I cannot see how it should be used.

In general, if I understand the Model/View Programming documentation, you have a model which contains the data, separate from a combination of view and delegate which decide how to show the data.

Now, the delegate decides - after the model is complete - that a column of booleans should be handled in a particular way. openPersistentEditor() is a view method; the delegate methods do not get a pointer to the view. I cannot find view methods or signals that could be trapped to call the method. In the Icons Example, openPersistentEditor() is called when adding the data to a QTableWidget; I cannot do that as the data were already added long ago.

All of which leads me to believe that I am misunderstanding something fundamental, and I cannot see what it is. Hence the question.


As far as I understand, you want to influence the way your cell is displayed by opening a persistent editor, but this way you are just exploiting editing mechanism instead of fixing your delegate.

yes, that is how the Icons example in the documentation did it. I want the boolean column to appear as a column of checkboxes, and also to be edited as such. The QCheckBox knows how to draw that correctly. I don't, of course: it depends on whether the program is compiled on Linux, Windows or the Mac, what style is in operation, etc. So I don't see how I could override the paint method, like in the Star Delegate example, and draw my own checkbox, when I don't know what it should look like.


In case of checkboxes the easiest way is to set the Qt::ItemIsUserCheckable flag in your model.

If that works, it would be brilliant! Should this work with the standard delegate? I got rid of my delegate and put ItemIsUserCheckable in the model:


Qt::ItemFlags CProcTableModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags result = Qt::ItemIsEnabled;

if (index.isValid())
result = QAbstractItemModel::flags(index) | Qt::ItemIsEditable;

if (index.column() == ixSelected)
result |= Qt::ItemIsUserCheckable;

return result;
}

The model's data() method uses

return QVariant((bool)m_Selected[ix]);
for both Qt:: DisplayRole and Qt::EditRole on any cell in that column. It doesn't make any difference; the cells are still displayed as "true" or "false" and edited with a combobox with values "True" and "False" (with the different capitalisation; curious but not important).

What obvious thing have I missed?

Thanks

Frank

jacek
12th January 2008, 18:58
So I don't see how I could override the paint method [...] when I don't know what it should look like.
You don't have to, the QStyle instance knows that.


What obvious thing have I missed?
The Qt::CheckStateRole.

fpeelo
12th January 2008, 23:50
The Qt::CheckStateRole.

Thanks for that; I now have the columns displaying with checkboxes.

But I have to say, it wasn't obvious! The documentation in Qt Assistant is so good for so many things, it's a surprise it's so bad on this point. Even with the key word "Qt::CheckStateRole" from your post, searching the documentation did not show me how to do it.

But your answer let me use Google, which found me a post from someone else at
http://lists.trolltech.com/qt-interest/2006-05/thread00066-0.html
who was similarly stumped, with an answer from Martin Gebert.

For the benefit of anyone who stumbles across this thread when looking for checkboxes:


To implement a table model, you must subclass QAbstractTableMode, and implement a data() method
In the data method, if role == Qt::CheckStateRole, you can return Qt::Unchecked, Qt::PartiallyChecked or Qt::Checked to add a checkbox to the cell
Qt::Unchecked, Qt::PartiallyChecked and Qt::Checked are of type Qt::CheckState. data() returns a QVariant. QVariant does not know about Qt::CheckState, but it can take the Qt::CheckState values as integers
The value returned by data() for the Qt:: DisplayRole role does not seem to influence the checkbox. It just defines a label that goes beside the checkbox.
When you want to change the state of the cell, you don't click the checkbox. You click the area beside it which would have a label.


Sorry if this looks like stating the obvious. And even more if I still have it wrong!

I now have the column displaying as checkboxes. But I haven't got the editing working right. Fortunately I can live without editing this column, for now, so I'll leave it at that.

Thanks again

Frank