I have a QStandardItemModel that needs different horizontal header labels in different views.
I'm having trouble finding information about how to decouple the header of a QTreeView from the model in that way. Is this possible?
See a simple code example below.
In this example - we have ItemTypeA, which is our top level item, and its horizontal axis represents the attributes "Name | Interpolaton | Normalize".
The children of ItemTypeA (ItemTypeB) have items in the horizontal axis that represent "Name | Multiply"
TreeViewA shows everything, and TreeViewB only shows the children of the selected Top Level Item (selection connection not implemented in this example).
from PySide.QtGui import *
from PySide.QtCore import *
class MyModel(QStandardItemModel):
def __init__(self):
super(MyModel, self).__init__()
iroot = self.invisibleRootItem()
self.setHorizontalHeaderLabels(['Name', 'Interpolation', 'Normalize'])
def newTopLevelItem(self, name = 'myTopLevelItem'):
item = ItemTypeA(name)
root_item = self.invisibleRootItem()
root_item.appendRow([item]+item.settingItems())
return item
class ItemTypeA(QStandardItem):
def __init__(self, *args, **kwargs):
super(ItemTypeA, self).__init__(*args, **kwargs)
self.s_interpolation =QStandardItem('0')
self.s_normalize = QStandardItem('False')
def settingItems(self):
return [
self.s_interpolation,
self.s_normalize
]
def newChildItem(self, name = 'newChildItem'):
childItem = ItemTypeB( name )
self.appendRow( [childItem]+childItem.settingItems() )
class ItemTypeB(QStandardItem):
def __init__(self, *args, **kwargs):
super(ItemTypeB, self).__init__(*args, **kwargs)
self.s_multiply = QStandardItem('1.0')
def settingItems(self):
return [
self.s_multiply,
]
class TreeViewA(QTreeView):
'''
THIS VIEW Needs the Headers:
Item Name | Interpolation | Normalize
'''
def __init__(self):
super(TreeViewA, self).__init__()
model = MyModel()
self.setModel(model)
newItem = model.newTopLevelItem()
newItem.newChildItem()
class TreeViewB(QTreeView):
'''
THIS VIEW Needs the Headers:
Item Name | Multiply
'''
def __init__(self, sourceView):
super(TreeViewB, self).__init__()
model = sourceView.model()
self.setModel(model)
self.setRootIndex(model.index(0,0))
class MyWidget(QWidget):
def __init__(self):
super(MyWidget, self).__init__()
layout = QHBoxLayout()
viewA = TreeViewA()
viewB = TreeViewB(viewA)
layout.addWidget(viewA)
layout.addWidget(viewB)
self.setLayout(layout)
widget = MyWidget()
widget.show()
Thoughts?
The solution for these cases would be to use QIdentityProxyModel but this class is not present in PySide and PySide, so we must use a similar class such as QSortFilterProxyModel and overwrite the headerData method.
...
class HeaderProxyModel(QSortFilterProxyModel):
def __init__(self, *args, **kwargs):
QSortFilterProxyModel.__init__(self, *args, **kwargs)
self.labels = []
def setHeaderLabels(self, labels):
self.labels = labels
def headerData(self, section,orientation, role = Qt.DisplayRole):
if orientation == Qt.Horizontal and 0 <= section < self.columnCount() and role==Qt.DisplayRole and section < len(self.labels) :
return self.labels[section]
return QSortFilterProxyModel.headerData(self, section, orientation, role)
class TreeViewB(QTreeView):
'''
THIS VIEW Needs the Headers:
Item Name | Multiply
'''
def __init__(self, sourceView):
super(TreeViewB, self).__init__()
model = sourceView.model()
proxy = HeaderProxyModel()
proxy.setSourceModel(model)
proxy.setHeaderLabels(["Name", "Multiply"])
self.setModel(proxy)
self.setRootIndex(proxy.index(0,0))
...