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 aQSortFilterProxyModel
.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).
- If
QSortFilterProxyModel
is sorted don't works (Option 2).
- I have tried to convert the row that the model gives me through
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_())
CodePudding user response:
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_())