[Interest] Replacing QListWidget that uses cell widgets with QListView & model
Murphy, Sean
Sean.Murphy at centauricorp.com
Fri Sep 3 19:09:55 CEST 2021
We've got an application we're working on where we'd like to replace a QListWidget that uses
cell widgets, with a view/model/delegate and we're running into a snag. Here's what we have:
We have a "layerData" class with three member variables:
- bool visible
- QString name
- double opacity
We have a custom "layerControl" widget class that has three controls (QToolButton, QLineEdit, QSlider
respectively) for displaying/setting those parameters. This widget has separate signals (bool, QString,
double) which are emitted when their respective control is modified.
Originally, we had a QListWidget where we'd call setCellWidget(new layerControl()) to populate
the list with one our "layerControl" widgets per row. This worked well, but now we've realized that
we want to display this same information in a couple different views (some of which are QTableViews,
some are QListViews), so we're converting everything over to view/model/delegate so that we can
just use a single shared model and changes that are made on any view are immediately reflected in the
other views.
To convert over to the view/model/delegate way of doing things I've got this so far:
- I've created a model (inherited from QAbstractItemModel) that takes a QVector<layerData> for
its underlying data, and in data() returns the bool parameter for column 0, the QString parameter
for column 1, and the double for column 2.
- I set the same instance of this model on both a QTableView and a QListView
- I've created a delegate class, "layerWidgetDelegate", that uses our "layerControl" widget as its editor
- on the QListView, I call setItemDelegateForColumn(0, new layerWidgetDelegate()), and then I loop
though all the rows of the view, calling openPersistentEditor(model->index(row, 0)) so the
"layerControl" widgets are always shown in the QListView
- in the delegate, I've connected the editor's 3 distinct signals (bool, QString, double) up to calling the
model's setData() function with the appropriate column (0, 1, 2 respectively)
This setup works fine when the user makes a change in the QListView. Using the "layerControl" item
delegate/editor to make a change on any of the three parameters, the change immediately ripples
through the model and the table view is updated to match. But we're having trouble going the other
way, but only for columns 1 & 2. If the user makes a change in the table view to something in column 0,
that change propagates through the model, the delegate's setEditorData() is called with an index
of (row, 0), and then the editor widget's QToolButton's state is updated to match the new value. But if
the user makes a change in the table view to something in column 1, the model's underlying data is correctly
updated, it still emits the correct dataChanged() signal for the index (row, 1), but the item delegate's
setEditorData() function is never called and therefor the QLineEdit is never updated. The same thing
happens if the user makes a change in the table view to something in column 2 - the model's setData() is
correctly called, the dataChanged() signal is correctly emitted, but the delegate's setEditorData() function
is never called, and therefore the QSlider never gets updated.
Anyone have any tips for this? The basic problem with what I'm doing is that I'm trying to use a three
column model in a single column widget (the QListView), but I STILL want all three columns of data to
come through because I need to populate the delegate. It appears something in the QListView
class prevents setEditorData() from being called when the index isn't in column 0.
The only hack I've found that works so far is in my model's setData() function, if the passed in index is for
column 1 or 2, then I make sure to emit column 0 in the dataChanged() signal, which then forces the
view to call the setEditorData() function, and then in there I update the editor widget with all three
types of data since I don't really know which column changed at that point.
This was more long winded than I wanted, hopefully you can follow all of this!
Sean
More information about the Interest
mailing list