I have an application in which I am experiencing a problem.
In order to explain the problem I have simplified it to the maximum to be able to expose it here.
My problem is the following:
I have a QTableView
, associated to a QSortFilterProxyModel
.
I do a search in the table to find the record that contains the searched text, and once found, I select that row.
If the QSortFilterProxyModel
is not sorted, it works correctly (Option 1).
QSortFilterProxyModel
is sorted don't works (Option 2).maptoSource
and it has not been possible (Option 2).The error is:
QSortFilterProxyModel: index from wrong model passed to mapToSource
I am clear that the model row must be converted to a QSortFilterProxyModel row, but I don't know how.
Any ideas?
Thank you very much.
Sample Code:
from PyQt5.QtWidgets import (QApplication, QPushButton,QComboBox,QMainWindow)
from PyQt5.QtWidgets import (QTableView,QAbstractItemView,QVBoxLayout,QLineEdit,QWidget)
from PyQt5.QtGui import QStandardItemModel,QStandardItem
from PyQt5.QtCore import QSortFilterProxyModel,Qt
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setup_gui()
def setup_gui(self):
widget=QWidget(self)
self.setCentralWidget(widget)
self.qlineedit = QLineEdit()
self.qlineedit.textChanged.connect(self.find_text)
self.table_view = QTableView()
self.main_layout = QVBoxLayout(widget)
self.main_layout.addWidget(self.qlineedit)
self.main_layout.addWidget(self.table_view)
self.table_model = QStandardItemModel()
row=0
for b in ['Fast','Medium','Cool','Double']:
item=QStandardItem(b)
self.table_model.setItem(row, 0, item)
row+=1
self.model_filter_proxy = QSortFilterProxyModel()
self.model_filter_proxy.setSourceModel(self.table_model)
self.model_filter_proxy.sort(0)
self.table_view.setModel(self.model_filter_proxy)
# Setup Table view
# Selection one row at same time
self.table_view.setSelectionMode(QAbstractItemView.SingleSelection)
# Seleccionar toda la fila
self.table_view.setSelectionBehavior(QAbstractItemView.SelectRows)
self.table_view.setStyleSheet("QTableView::item:selected{ background-color: green ; selection-color: white; }")
def find_text(self,text):
column=0
self.table_view.clearSelection()
start = self.table_model.index(0, column)
matches = self.table_model.match(
start,
Qt.DisplayRole,
text,
hits=1,
flags=Qt.MatchContains
)
if matches:
# Option 1
index = matches[0]
row=index.row()
# Option 2
mapped_index = self.model_filter_proxy.mapToSource(matches[0])
row=mapped_index.row()
self.table_view.selectRow(row)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
app.setStyle("fusion")
w=MainWindow()
w.show()
sys.exit(app.exec_())
With @musicamante comments, the correct code is:
from PyQt5.uic import loadUiType, loadUi
from PyQt5.QtWidgets import (QApplication, QPushButton,QComboBox,QMainWindow)
from PyQt5.QtWidgets import (QTableView,QAbstractItemView,QVBoxLayout,QLineEdit,QWidget)
from PyQt5.QtGui import QStandardItemModel,QStandardItem
from PyQt5.QtCore import QSortFilterProxyModel,Qt
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setup_gui()
def setup_gui(self):
widget=QWidget(self)
self.setCentralWidget(widget)
self.qlineedit = QLineEdit()
self.qlineedit.textChanged.connect(self.find_text)
self.table_view = QTableView()
self.main_layout = QVBoxLayout(widget)
self.main_layout.addWidget(self.qlineedit)
self.main_layout.addWidget(self.table_view)
self.table_model = QStandardItemModel()
row=0
for b in ['Fast','Medium','Cool','Double']:
item=QStandardItem(b)
self.table_model.setItem(row, 0, item)
row+=1
self.model_filter_proxy = QSortFilterProxyModel()
self.model_filter_proxy.setSourceModel(self.table_model)
self.model_filter_proxy.sort(0)
self.table_view.setModel(self.model_filter_proxy)
# Setup Table view
# Selection one row at same time
self.table_view.setSelectionMode(QAbstractItemView.SingleSelection)
# Seleccionar toda la fila
self.table_view.setSelectionBehavior(QAbstractItemView.SelectRows)
self.table_view.setStyleSheet("QTableView::item:selected{ background-color: green ; selection-color: white; }")
def find_text(self,text):
column=0
self.table_view.clearSelection()
start = self.table_model.index(0, column)
matches = self.table_model.match(
start,
Qt.DisplayRole,
text,
hits=1,
flags=Qt.MatchContains
)
if matches:
# Option 1
#index = matches[0]
#row=index.row()
# Option 2
#mapped_index = self.model_filter_proxy.mapToSource(matches[0])
mapped_index = self.model_filter_proxy.mapFromSource(matches[0])
row=mapped_index.row()
self.table_view.selectRow(row)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
app.setStyle("fusion")
w=MainWindow()
w.show()
sys.exit(app.exec_())