PDA

View Full Version : QItemSelectionModel synchronization problem - SOLVED



d_stranz
16th May 2014, 20:06
I have a tree-structured set of data, for which I have created a QAbstractItemModel to display it in a QTreeView. At the same time, I implemented a custom QSortFilterProxyModel that flattens the tree-based QAbstractItemModel into a table (each leaf in the tree is a row in the table, and the higher level tree items repeat for their leaf rows). This works fine.

Most of the data in the structure is numeric, and I have implemented a set of QGraphicsView-based scatterplots, pie charts, bar charts, etc. that will display selected columns from the table. These are all derived from QAbstractItemView, so they use QAbstractItemModel instances to source their data. I've done this by creating another proxy model that can be configured to pull x, y, and z coordinate data out of the table model by telling the proxy which column and role to use for which coordinate.

All of this now works great. When the tree-structured data is updated, the tree view, table view, and all the plots update just fine.

I now am trying to get selection from the tree, table, and plots synchronized. I want the same items to show as selected whether they appear in the tree, table, or plot views, and I want to be able to select an item from any of these. Because of all the proxy models, I can't just create a custom QItemSelectionModel and install it everywhere, because Qt then complains that the models used are different for different views. That's true - except for the tree, everything else uses proxies, sometimes several layers of them so model indexes are being mapped to and from source models all over the place.

So, I am at the point where I am handling selection of QGraphicsItem instances from the plots and mapping them to their underlying QModelIndex instances. I then use the default QItemSelectionModel for each view and call the select() slot. This results in the QItemSelectionModel::selectionChanged() signal being fired.

Here's where the trouble starts. I want to handle that signal in the other views to synchronize the selections there. QAbstractItemView, the base class for all of my plot views, doesn't have any way to set the selection except through the selection model. But if I do that, then I get another selectionChanged() signal from that instance and I end up with this recursive mess of select() and selectionChanged() calls.

As I write this, I am starting to think that the way to solve this is to implement my own QItemSelectionModel instance and install it on each view. This class would probably trap the selectionChanged() signal and map it into something else so I could prevent recursion, or maybe I would reimplement the select() slot so it doesn't fire the signal in the first place.

Does that make sense? If not, can someone please suggest an alternative?

Thanks in advance for any help / advice.

Edit ---

Duh, sometimes the simplest solutions get lost in the confusion of over-thinking the problem. I've solved the recursion problem by setting a boolean flag in the slot that handles the selectionChanged() signals from the various views. When the slot is first entered, I check the flag, and if it is not set, I set the flag, update the rest of the views, then clear the flag. When one of the selection models in the other views issues its signal, it is blocked from recursion in the slot by the flag. So all of the plots are now in sync, and I need to get the tree and table views synced as well.