The posted code creates a singe Model/Proxy QTableView. The multi-selection feature has been enabled for it.
There are four items total. Two of them include a character "A". Other two include character "B" in their "item" names.
QPushButton when pressed calls for the clicked() method.
When called this method first queries a Proxy Model connected to the QTableView:
proxyModel=self.tableview.model()
Then the method asks a proxyModel to return a total number of rows:
rows=proxyModel.rowCount()
Knowing how many rows in a QTabelView's model it iterates each row. First it is querying a row index:
index=proxyModel.index(row, 0)
Knowing index it proceeds with asking for a value stored in self.items variable by calling data() method supplying it with a queried in a previous step a QModelIndex (a variable index here) and a Role flag.
item=proxyModel.data(index, Qt.DisplayRole).toPyObject()
'toPyObject()' is used to convert the data received from .data() method to a "regular" Python variable.
Lastly it checks if the characters "B" in a received string. If so it selects QTableView row using:
self.tableview.selectRow(row)
Now what I want is to get the same selection functionality from inside of the scope of Proxy Model's filterAcceptsRow() if that is possible.
If it is not possible I would like to know if there is any other way of doing it... should be I using QItemSelectionModel? Then how?
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
class Model(QAbstractTableModel):
def __init__(self, parent=None, *args):
QAbstractTableModel.__init__(self, parent, *args)
self.items = ['Item_A_001','Item_A_002','Item_B_001','Item_B_002']
def rowCount(self, parent=QModelIndex()):
return len(self.items)
def columnCount(self, parent=QModelIndex()):
return 1
def data(self, index, role):
if not index.isValid(): return QVariant()
elif role != Qt.DisplayRole:
return QVariant()
row=index.row()
if row<len(self.items):
return QVariant(self.items[row])
else:
return QVariant()
class Proxy(QSortFilterProxyModel):
def __init__(self):
super(Proxy, self).__init__()
def filterAcceptsRow(self, row, parent):
return True
class MyWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
tableModel=Model(self)
proxyModel=Proxy()
proxyModel.setSourceModel(tableModel)
self.tableview=QTableView(self)
self.tableview.setModel(proxyModel)
self.tableview.horizontalHeader().setStretchLastSection(True)
self.tableview.setSelectionMode(QAbstractItemView.MultiSelection)
button=QPushButton(self)
button.setText('Select Items with B')
button.clicked.connect(self.clicked)
layout = QVBoxLayout(self)
layout.addWidget(self.tableview)
layout.addWidget(button)
self.setLayout(layout)
def clicked(self, arg):
proxyModel=self.tableview.model()
self.tableview.clearSelection()
rows=proxyModel.rowCount()
for row in range(rows):
index=proxyModel.index(row, 0)
item=proxyModel.data(index, Qt.DisplayRole).toPyObject()
if '_B_' in item:
self.tableview.selectRow(row)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
You can achieve the selection within the filterAcceptsRow() method of the proxy model, but doing so would require the following:
That your proxy model (or source model) contain a reference to the QTableView instance.
That your proxy model contain an attribute indicating whether it is active. This is because you want to only select the table rows when the button is clicked, but filterAcceptsRow() is called automatically by the proxy model. Therefore, you would want to avoid calling the view's selectRow() method until the button is clicked.
To achieve #1, you could define a simple setter method in your proxy model class:
def setView(self, view):
self._view = view
You would also need to of course invoke that setter within your MyWindow class's constructor:
proxyModel.setView(self.tableview)
Achieving #2 is a simple matter of creating this attribute in the proxy model class's constructor
self.filterActive = False
Now that your classes are prepared, you can implement your desired behavior. In your filterAcceptsRow() re-implementation, you only want to select the rows if they contain '_B_' and is the filter is active (that is, the button was clicked):
def filterAcceptsRow(self, row, parent):
if self.filterActive and '_B_' in self.sourceModel().data(self.sourceModel().index(row, 0), Qt.DisplayRole).toPyObject():
self._view.selectRow(row)
return True
Finally, you want to make sure that these conditions are met once the button is clicked, so in your clicked() method you need to set the proxyModel's filterActive attribute to True and you need to call the QSortFilterProxyModel class's invalidateFilter() method to indicate that the existing filter is invalid and therefore filterAcceptsRow() should be called again:
def clicked(self, arg):
proxyModel=self.tableview.model()
self.tableview.clearSelection()
proxyModel.filterActive = True
proxyModel.invalidateFilter()
So the new code, in full, is:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
class Model(QAbstractTableModel):
def __init__(self, parent=None, *args):
QAbstractTableModel.__init__(self, parent, *args)
self.items = ['Item_A_001','Item_A_002','Item_B_001','Item_B_002']
def rowCount(self, parent=QModelIndex()):
return len(self.items)
def columnCount(self, parent=QModelIndex()):
return 1
def data(self, index, role):
if not index.isValid(): return QVariant()
elif role != Qt.DisplayRole:
return QVariant()
row=index.row()
if row<len(self.items):
return QVariant(self.items[row])
else:
return QVariant()
class Proxy(QSortFilterProxyModel):
def __init__(self):
super(Proxy, self).__init__()
self.filterActive = False
def setView(self, view):
self._view = view
def filterAcceptsRow(self, row, parent):
if self.filterActive and '_B_' in self.sourceModel().data(self.sourceModel().index(row, 0), Qt.DisplayRole).toPyObject():
self._view.selectRow(row)
return True
class MyWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
tableModel=Model(self)
proxyModel=Proxy()
proxyModel.setSourceModel(tableModel)
self.tableview=QTableView(self)
self.tableview.setModel(proxyModel)
self.tableview.horizontalHeader().setStretchLastSection(True)
self.tableview.setSelectionMode(QAbstractItemView.MultiSelection)
proxyModel.setView(self.tableview)
button=QPushButton(self)
button.setText('Select Items with B')
button.clicked.connect(self.clicked)
layout = QVBoxLayout(self)
layout.addWidget(self.tableview)
layout.addWidget(button)
self.setLayout(layout)
def clicked(self, arg):
proxyModel=self.tableview.model()
self.tableview.clearSelection()
proxyModel.filterActive = True
proxyModel.invalidateFilter()
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
Having said all of that, the purpose of filterAcceptsRow() is so that you can implement your own custom filtering in a subclass of QSortFilterProxyModel. So, a more typical implementation (following your desired rule) would be:
def filterAcceptsRow(self, row, parent):
if not self.filterActive or '_B_' in self.sourceModel().data(self.sourceModel().index(row, 0), Qt.DisplayRole).toPyObject():
return True
return False
And even then, because the filtering could be done with regex, reimplementation of filterAcceptsRow() isn't even necessary. You could just call proxyModel.setFilterRegExp(QRegExp("_B_", Qt.CaseInsensitive, QRegExp.FixedString)) and proxyModel.setFilterKeyColumn(0) to achieve the same thing, filter-wise.
Hope that helps!
Related
I am trying to update my model when a combo box is changed. I have a function connected to the combobox that updates the model but from this question - "the delegates should use the base functions of the model whenever they provide standard behavior (accessing index.model()._data is not good)". I also want the change of the combobox to affect what appears in a QLineEdit.
QItemDelegate:
class Delegate(QItemDelegate):
def __init__(self):
QItemDelegate.__init__(self)
self.type_items = ["1", "2"]
def createEditor(self, parent, option, index):
if index.column() == 0:
comboBox = QComboBox(parent)
for text in self.type_items:
comboBox.addItem(text, (index.row(), index.column()))
comboBox.currentIndexChanged.connect(lambda: self.comboBoxChanged(comboBox, index))
return comboBox
return super().createEditor(parent, option, index)
# updates model but does not update view - shows what I want to happen
def comboBoxChanged(self, comboBox, index):
if comboBox.currentText() == "1":
index.model()._data[index.row()][0] = "1"
index.model()._data[index.row()][1] = "One"
elif comboBox.currentText() == "2":
index.model()._data[index.row()][0] = "2"
index.model()._data[index.row()][1] = "Two"
# self.dataChanged.emit(index, index) # can't call this here
QAbstractTableModel:
class TableModel(QAbstractTableModel):
def __init__(self, data):
super(TableModel, self).__init__()
self._data = data
def data(self, index, role):
if role in (Qt.DisplayRole, Qt.EditRole):
return self._data[index.row()][index.column()]
def rowCount(self, index=None):
return len(self._data)
def columnCount(self, index=None):
return len(self._data[0])
def flags(self, index):
return super().flags(index) | Qt.ItemIsEditable
def setData(self, index, value, role=Qt.EditRole):
if role == Qt.EditRole:
self._data[index.row()][index.column()] = value
self.dataChanged.emit(index, index)
return True
return False
Main:
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
localWidget = QWidget()
self.table = QTableView()
data = [["1", "One"]]
self.model = TableModel(data)
self.table.setModel(self.model)
self.table.setItemDelegate(Delegate())
self.print_data = QPushButton("Print data")
self.print_data.clicked.connect(self.printData)
for row in range(self.model.rowCount()):
for column in range(self.model.columnCount()):
index = self.model.index(row, column)
self.table.openPersistentEditor(index)
layout_v = QVBoxLayout()
layout_v.addWidget(self.table)
layout_v.addWidget(self.print_data)
localWidget.setLayout(layout_v)
self.setCentralWidget(localWidget)
self.show()
def printData(self):
print(self.model._data)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
How can I register the change in the qcombobox to correctly update the model?
and
How do I make this trigger the change in qlineedit?
The data of a model should be preferably updated by using the existing setData function, which provides a centralized interface that avoids confusing bugs and mistakes.
In your case, you need to set the data of the sibling index, which is the index at the same row in the next column (no need to set the index value itself, as Qt is able to get it automatically from the combo, and it should be done in setModelData() anyway).
def comboBoxChanged(self, comboBox, index):
if comboBox.currentText() == "1":
value = "One"
elif comboBox.currentText() == "2":
value = "Two"
sibling = index.sibling(index.row(), 1)
index.model().setData(sibling, value)
Just to be clear, your code could have worked, but dataChanged is a signal of the model, not the delegate, so it should have been:
index.model().dataChanged.emit(index, index)
But, as already said, it's better to avoid using different ways of changing data in the model, especially if done from outside it. The major benefit of having a single function that takes care of that is that whenever something is going to change in the structure and implementation of the model the only thing left to check is all the occurrences of that function call (in case the column order changes, for example).
I am trying to make everything shown by the current code un-editable.
Previous searches all suggest either modifying the flags() function of the model or using the setEditTriggers of the table. I do both in this code, but neither of them work.
Looking at a widget-by-widget case, I can find readonly modes for LineEdit and others, but not for ComboBox. So I can not even modify the delegate to force the readonly constraint, not that I would necessarily like to do it this way.
EDIT: to clarify, when I say I want the user to not be able to 'edit' I mean that he shouldn't be able to change the state of the widget in any way. E.g. he won't be able to click on a ComboBox (or at least changing the current selected item/index).
from PyQt5 import QtCore, QtWidgets
import sys
class MyWindow(QtWidgets.QWidget):
def __init__(self, *args):
super().__init__(*args)
tableview = TableView()
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(tableview)
self.setLayout(layout)
class Delegate(QtWidgets.QStyledItemDelegate):
def __init__(self, model):
super().__init__()
self.model = model
def createEditor(self, parent, option, index):
widget = QtWidgets.QComboBox(parent)
widget.addItems(['', 'Cat', 'Dog'])
return widget
def setModelData(self, widget, model, index):
self.model.setData(index, widget.currentIndex())
class Model(QtCore.QAbstractTableModel):
def __init__(self, parent=None):
QtCore.QAbstractTableModel.__init__(self, parent=parent)
self.value = 0
def flags(self, index):
return QtCore.Qt.ItemIsEnabled
def data(self, index, role=QtCore.Qt.DisplayRole):
if not index.isValid() or role != QtCore.Qt.DisplayRole:
return QtCore.QVariant()
return QtCore.QVariant(self.value)
def setData(self, index, value, role=QtCore.Qt.EditRole):
self.value = value
print("data[{}][{}] = {}".format(index.row(), index.column(), value))
return True
def rowCount(self, parent=QtCore.QModelIndex()):
return 1
def columnCount(self, parent=QtCore.QModelIndex()):
return 1
class TableView(QtWidgets.QTableView):
def __init__(self, parent=None):
super().__init__(parent)
self.model = Model(self)
delegate = Delegate(self.model)
self.setItemDelegate(delegate)
self.setModel(self.model)
self.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers)
for row in range(self.model.rowCount()):
for column in range(self.model.columnCount()):
index = self.model.index(row, column)
self.openPersistentEditor(index)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
Explanation:
Some concepts must be clarified:
For Qt to disable editing that a view (QListView, QTableView, QTreeView, etc.) or item of the view implies only that the editor will not open through user events such as clicked, double-clicked, etc.
The user interaction in Qt follows the following path:
The user interacts through the OS with the mouse, keyboard, etc.
the OS notifies Qt of that interaction.
Qt creates QEvents and sends it to the widgets.
The widget analyzes what you should modify regarding the QEvent you receive.
In your case, using openPersistentEditor() shows the widgets, and so the edibility from the Qt point of view is not valid for this case.
Solution:
Considering the above a possible general methodology to make a widget not editable: block some point of the user-widget interaction path. In this case, the simplest thing is to prevent the widget from receiving the QEvents through an event filter.
Considering the above, the solution is:
class DisableEventsManager(QtCore.QObject):
def __init__(self, *, qobject, events=None, apply_childrens=False):
if not isinstance(qobject, QtCore.QObject):
raise TypeError(
f"{qobject} must belong to a class that inherits from QObject"
)
super().__init__(qobject)
self._qobject = qobject
self._events = events or []
self._qobject.installEventFilter(self)
self._children_filter = []
if apply_childrens:
for child in self._qobject.findChildren(QtWidgets.QWidget):
child_filter = DisableEventsManager(
qobject=child, events=events, apply_childrens=apply_childrens
)
self._children_filter.append(child_filter)
#property
def events(self):
return self._events
#events.setter
def events(self, events):
self._events = events
for child_filter in self._children_filter:
child_filter.events = events
def eventFilter(self, obj, event):
if self.events and self._qobject is obj:
if event.type() in self.events:
return True
return super().eventFilter(obj, event)
def createEditor(self, parent, option, index):
combo = QtWidgets.QComboBox(parent)
combo.addItems(["", "Cat", "Dog"])
combo_event_filter = DisableEventsManager(qobject=combo)
combo_event_filter.events = [
QtCore.QEvent.KeyPress,
QtCore.QEvent.FocusIn,
QtCore.QEvent.MouseButtonPress,
QtCore.QEvent.MouseButtonDblClick,
]
return combo
Here is a simple example of a qtableView where every cell have a different item. In the example here i used numbers, but ultimately i wish to display animated gifs for every cells. I wish to keep the MVC design and insert a custom widget proceduraly.
import random
import math
from PyQt4 import QtCore, QtGui
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, data, columns, parent=None):
super(TableModel, self).__init__(parent)
self._columns = columns
self._data = data[:]
def rowCount(self, parent=QtCore.QModelIndex()):
if parent.isValid() or self._columns == 0:
return 0
return math.ceil(len(self._data )*1.0/self._columns)
def columnCount(self, parent=QtCore.QModelIndex()):
if parent.isValid():
return 0
return self._columns
def data(self, index, role=QtCore.Qt.DisplayRole):
if not index.isValid():
return
if role == QtCore.Qt.DisplayRole:
try:
value = self._data[ index.row() * self._columns + index.column() ]
return value
except:
pass
class Widget(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
data = [random.choice(range(10)) for i in range(20)]
l = QtGui.QHBoxLayout(self)
splitter = QtGui.QSplitter()
l.addWidget(splitter)
tvf = QtGui.QTableView()
model = TableModel(data, 3, self)
tvf.setModel(model)
splitter.addWidget( tvf )
if __name__=="__main__":
import sys
a=QtGui.QApplication(sys.argv)
w=Widget()
w.show()
sys.exit(a.exec_())
After reading a bit more and with the help of #eyllanesc, i understand that there is 2 ways of achieving this: delegates or itemWidget.
It seem that delegates won't work for me since it's not possible to insert widget into cells that way.
ItemWidget seems the way to go but this is not MVC compatible ? i do not wish to loop the function to insert into the table...
is there a third way ?
There are two tableViews: A and B. viewA is linked to proxyA. While a viewB is linked to proxyB. Both proxy share the same source model.
From what I've learned if Qt.CheckStateRole is specified then the source model's data() "assigns" a checkbox to each modelIndex.
Since this checkbox-to-modelIndex assignment is taking place inside of sourceModel's both views A and B are getting the checkboxes.
Question: How to isolate viewA from getting the checkboxes? How to make viewA checkbox-less? The goal is to make sure the checkboxes only appear in viewB. Is it possible to override some viewA property so it doesn't display the checkboxes? May be I could use viewB proxy and do some call from proxy 'filterAcceptsRow()`?
The problem apparently is that sourceModel is not aware of views. It doesn't care if the indexes are queried for viewA or B. While with the proxy models I can set proxyA.setObjectName('proxyA') and then using its objectName do some logic. But how to control the checkboxes from inside of Proxy then?....
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
class Model(QAbstractTableModel):
def __init__(self, parent=None, *args):
QAbstractTableModel.__init__(self, parent, *args)
self.items = ['Item_003','Item_000','Item_005','Item_004','Item_001']
def rowCount(self, parent=QModelIndex()):
return len(self.items)
def columnCount(self, parent=QModelIndex()):
return 1
def data(self, index, role):
if not index.isValid(): return QVariant()
row=index.row()
if role == Qt.DisplayRole:
return QVariant(self.items[row])
elif role == Qt.CheckStateRole:
return QVariant(Qt.Checked)
else:
return QVariant()
class Proxy(QSortFilterProxyModel):
def __init__(self):
super(Proxy, self).__init__()
class MyWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
layout=QHBoxLayout(self)
self.setLayout(layout)
tableModel=Model(self)
proxyA=Proxy()
proxyA.setSourceModel(tableModel)
proxyB=Proxy()
proxyB.setSourceModel(tableModel)
self.ViewA=QTableView(self)
self.ViewA.setModel(proxyA)
self.ViewB=QTableView(self)
self.ViewB.setModel(proxyB)
layout.addWidget(self.ViewA)
layout.addWidget(self.ViewB)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
There is a dictionary with three keys: 'Animals', 'Birds' and 'Fish'.
The main dialog has two List views. The left view viewA displays the list of the keys mentioned above.
When one of its items is clicked the right view viewB displays the list of the species.
The question is how to manage viewB's display... Let's say the user clicks 'Animals': listB goes ahead and builds a brand new list of QListWidgetItem for every animal in a list. Then the user clicks 'Birds'. What should I do with already built viewB's "animal" items? Should I hide them? (hiding "Animals" items (instead of deleting) would allow me unhide them later when 'Animals' is clicked again (makes total sense if ListItems are heavy on graphics: thumbs, icons and etc. If a list of animals is 1000+ there will be a noticeable difference between rebuilding the ListItems from scratch and unhiding the ones that were build on a last click).
Another approach I see is to user viewB.clear() every time viewA's item is clicked. So the listB items are rebuilt every time listA item is clicked. But as I have mentioned with a long list of items it could be really slow. What logic to implement in situation like this?
from PyQt4 import QtCore, QtGui
app=QtGui.QApplication(sys.argv)
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
layout=QtGui.QHBoxLayout()
self.setLayout(layout)
self.viewA=QtGui.QListWidget()
self.viewA.addItems(elements.keys())
self.viewA.itemClicked.connect(self.aClicked)
self.viewB=QtGui.QListWidget()
layout.addWidget(self.viewA)
layout.addWidget(self.viewB)
self.show()
def aClicked(self, item):
key='%s'%item.text()
values=elements.get(key)
items=[QtGui.QListWidgetItem(val) for val in values]
result=[self.viewB.addItem(item) for item in items]
elements={'Animals':['Bison','Panther','Elephant'],'Birds':['Duck','Hawk','Pigeon'],'Fish':['Shark','Salmon','Piranha']}
window=Window()
sys.exit(app.exec_())
I suggest to use Model-View approach instead.
You'll have two models: KeysModel and ValuesModel inherited from QAbstractListModel or QStringListModel. Two views QTableView: KeysView and ValuesView. And one proxy model QSortFilterProxyModel ProxyModel which will help you to show values filtered by a key in ValuesView.
When an item in KeysView is selected just assign a new filter to ProxyModel and values in ValuesView will be changed.
On the other class QColumnView it can design hierarchy of data. Try read document it.
Using a single model for both views: QListView and QTableView:
import os,sys
from PyQt4 import QtCore, QtGui
app=QtGui.QApplication(sys.argv)
elements={'Animals':{1:'Bison',2:'Panther',3:'Elephant'},'Birds':{1:'Duck',2:'Hawk',3:'Pigeon'},'Fish':{1:'Shark',2:'Salmon',3:'Piranha'}}
class DataModel(QtCore.QAbstractTableModel):
def __init__(self):
QtCore.QAbstractTableModel.__init__(self)
self.modelDict={}
self.items=[]
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.items)
def columnCount(self, index=QtCore.QModelIndex()):
return 4
def data(self, index, role):
if not index.isValid() or not (0<=index.row()<len(self.items)): return QtCore.QVariant()
key=str(self.items[index.row()])
column=index.column()
if role==QtCore.Qt.ItemDataRole: return self.modelDict.get(str(index.data().toString()))
if role==QtCore.Qt.DisplayRole:
if column==0:
return key
else:
return self.modelDict.get(key).get(column)
def addItem(self, itemName=None, column=0):
totalItems=self.rowCount()+1
self.beginInsertRows(QtCore.QModelIndex(), totalItems, column)
if not itemName: itemName='Item %s'%self.rowCount()
self.items.append(itemName)
self.endInsertRows()
def buildItems(self):
for key in self.modelDict:
index=QtCore.QModelIndex()
self.addItem(key)
class ProxyTableModel(QtGui.QSortFilterProxyModel):
def __init__(self, parent=None):
super(ProxyTableModel, self).__init__(parent)
def headerData(self, column, orientation, role=QtCore.Qt.DisplayRole):
if role == QtCore.Qt.TextAlignmentRole:
if orientation == QtCore.Qt.Horizontal:
return QtCore.QVariant(int(QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter))
return QtCore.QVariant(int(QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter))
if role != QtCore.Qt.DisplayRole:
return QtCore.QVariant()
if orientation==QtCore.Qt.Horizontal:
if column==1:
return QtCore.QVariant("Species 1")
elif column==2:
return QtCore.QVariant("Species 2")
elif column==3:
return QtCore.QVariant("Species 3")
return QtCore.QVariant(int(column + 1))
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
mainLayout=QtGui.QHBoxLayout()
self.setLayout(mainLayout)
self.dataModel=DataModel()
self.dataModel.modelDict=elements
self.dataModel.buildItems()
self.proxyModel=ProxyTableModel()
self.proxyModel.setFilterKeyColumn(0)
self.proxyModel.setSourceModel(self.dataModel)
self.viewA=QtGui.QListView()
self.viewA.setModel(self.dataModel)
self.viewA.clicked.connect(self.onClick)
self.viewB=QtGui.QTableView()
self.viewB.setModel(self.proxyModel)
self.viewB.setColumnHidden(0,True)
mainLayout.addWidget(self.viewA)
mainLayout.addWidget(self.viewB)
self.show()
def onClick(self):
index=self.viewA.currentIndex()
key=self.dataModel.data(index, QtCore.Qt.DisplayRole)
value=self.dataModel.data(index, QtCore.Qt.ItemDataRole)
self.proxyModel.setFilterRegExp('%s'%key)
print 'onClick(): key: %s'%type('%s'%key)
window=Window()
sys.exit(app.exec_())