Results 1 to 2 of 2

Thread: Contiguous selection and custom proxy model

  1. #1
    Join Date
    Jun 2021
    Posts
    2
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Contiguous selection and custom proxy model

    Hi there,

    I'm using PySide2 to write a simple app to display list of items in a grid like layout with some filtering but I have a problem with selection.

    It starts with a ListModel of items (called Assets for example) that is plugged into SortFilterModel where I do my filtering based on a name and that is plugged into IdenityProxyModel where I reorganize the list to a table and that is displayed in TableView.

    It all "seems" to work until I use CTRL+SHIFT selection and query the self.selectionModel().selectedIndexes() later where I found out it selects the wrong stuff. I'm not really sure if my .index() and .parent() methods are correct at all too.

    If you select cells horizontally it seems to work but it behaves odd when selecting vertically. Please see the image for the issue.

    Thanks a lot for any help!

    selection.jpg


    Qt Code:
    1. from PySide2 import QtWidgets, QtGui, QtCore
    2. from PySide2.QtCore import Qt
    3. import math
    4. import sys
    5.  
    6.  
    7. class CustomTableView(QtWidgets.QTableView):
    8. def __init__(self):
    9. super(CustomTableView, self).__init__()
    10. self.setMouseTracking(True)
    11.  
    12. def mousePressEvent(self, event: QtGui.QMouseEvent) -> None:
    13. if event.button() == Qt.LeftButton:
    14. super(CustomTableView, self).mousePressEvent(event)
    15. elif event.button() == Qt.RightButton:
    16. self.doSomethingWithSelected()
    17.  
    18. def doSomethingWithSelected(self):
    19. for ix in self.selectionModel().selectedIndexes():
    20. print("Selected Indexes:", ix.row(), ix.column(), ix.data(Qt.DisplayRole))
    21.  
    22.  
    23. class CustomListModel(QtCore.QAbstractListModel):
    24. def __init__(self, parent=None):
    25. super(CustomListModel, self).__init__(parent)
    26. self._data = [
    27. "Asset_A1",
    28. "Asset_A2",
    29. "Asset_A3",
    30. "Asset_B1",
    31. "Asset_B2",
    32. "Asset_B3",
    33. "Asset_C1",
    34. "Asset_C2",
    35. "Asset_C3",
    36. "Asset_C4",
    37. "Asset_D1",
    38. "Asset_D2",
    39. "Asset_D3",
    40. "Asset_D4",
    41. ]
    42.  
    43. def rowCount(self, parent=QtCore.QModelIndex()):
    44. return len(self._data)
    45.  
    46. def data(self, index, role=Qt.DisplayRole):
    47. if role == Qt.DisplayRole:
    48. return self._data[index.row()]
    49.  
    50. def parent(self, index: QtCore.QModelIndex) -> QtCore.QObject:
    51. return QtCore.QModelIndex()
    52.  
    53.  
    54. class CustomList2TableProxyModel(QtCore.QIdentityProxyModel):
    55. def __init__(self, columns=1, parent=None):
    56. super(CustomList2TableProxyModel, self).__init__(parent)
    57. self._columns = columns
    58.  
    59. def columnCount(self, parent=QtCore.QModelIndex()):
    60. return self._columns
    61.  
    62. def rowCount(self, parent=QtCore.QModelIndex()):
    63. if parent.isValid():
    64. return 0
    65. return math.ceil(self.sourceModel().rowCount()/self.columnCount())
    66.  
    67. def mapToSource(self, proxyIndex):
    68. if proxyIndex.isValid():
    69. r = proxyIndex.row()
    70. c = proxyIndex.column()
    71. row = r * self.columnCount() + c
    72. return self.sourceModel().index(row, 0)
    73. return QtCore.QModelIndex()
    74.  
    75. def mapFromSource(self, sourceIndex):
    76. r = math.ceil(sourceIndex.row()/self.columnCount())
    77. c = sourceIndex.row() % self.columnCount()
    78. return self.index(r, c)
    79.  
    80. def data(self, index, role=Qt.DisplayRole):
    81. r = index.row()
    82. c = index.column()
    83. row = r*self.columnCount() + c
    84. if row < self.sourceModel().rowCount():
    85. return super(CustomList2TableProxyModel, self).data(index, role)
    86.  
    87. def parent(self, index: QtCore.QModelIndex) -> QtCore.QObject:
    88. return QtCore.QModelIndex()
    89.  
    90. def index(self, row, column, parent=QtCore.QModelIndex()):
    91. if parent.isValid():
    92. return QtCore.QModelIndex()
    93. return self.createIndex(row, column)
    94.  
    95. # def sibling(self, row: int, column: int, idx: QtCore.QModelIndex) -> QtCore.QModelIndex:
    96. # print("Sibling", row, column, idx.data(Qt.DisplayRole))
    97.  
    98.  
    99. class CustomMainWindow(QtWidgets.QMainWindow):
    100. def __init__(self):
    101. super(CustomMainWindow, self).__init__()
    102. self.initUI()
    103.  
    104. def initUI(self):
    105. self.mainLayout = QtWidgets.QHBoxLayout()
    106. self.mainWidget = QtWidgets.QWidget()
    107.  
    108. # List Model
    109. self.listViewWidget = QtWidgets.QWidget()
    110. self.listViewLayout = QtWidgets.QVBoxLayout()
    111. sourceModel = CustomListModel()
    112. self.listView = QtWidgets.QListView()
    113. self.listView.setModel(sourceModel)
    114. self.listViewLayout.addWidget(QtWidgets.QLabel("QAbstractListModel: Source model"))
    115. self.listViewLayout.addWidget(self.listView)
    116. self.listViewWidget.setLayout(self.listViewLayout)
    117.  
    118. # Filter model
    119. self.filterListViewWidget = QtWidgets.QWidget()
    120. self.filterListViewLayout = QtWidgets.QVBoxLayout()
    121. self.filterListView = QtWidgets.QListView()
    122. self.filterProxy = QtCore.QSortFilterProxyModel()
    123. self.filterProxy.setSourceModel(sourceModel)
    124. self.filterProxy.setFilterRegExp(QtCore.QRegExp("1", Qt.CaseInsensitive, QtCore.QRegExp.FixedString))
    125. self.filterProxy.setFilterKeyColumn(0)
    126. self.filterListView.setModel(self.filterProxy)
    127. self.filterListViewLayout.addWidget(QtWidgets.QLabel("QSortFilterProxyModel: Filter '1'"))
    128. self.filterListViewLayout.addWidget(self.filterListView)
    129. self.filterListViewWidget.setLayout(self.filterListViewLayout)
    130.  
    131. # List to Grid model
    132. self.gridViewWidget = QtWidgets.QWidget()
    133. self.gridViewLayout = QtWidgets.QVBoxLayout()
    134. self.gridView = CustomTableView()
    135. self.gridProxy = CustomList2TableProxyModel(2)
    136. self.gridProxy.setSourceModel(self.filterProxy)
    137. self.gridView.setModel(self.gridProxy)
    138. self.gridViewLayout.addWidget(QtWidgets.QLabel("QIdentityProxyModel: List to table model"))
    139. self.gridViewLayout.addWidget(self.gridView)
    140. self.gridViewWidget.setLayout(self.gridViewLayout)
    141.  
    142. # Assemble main Layout
    143. self.mainLayout.addWidget(self.listViewWidget)
    144. self.mainLayout.addWidget(self.filterListViewWidget)
    145. self.mainLayout.addWidget(self.gridViewWidget)
    146. self.mainWidget.setLayout(self.mainLayout)
    147. self.setCentralWidget(self.mainWidget)
    148.  
    149.  
    150. if __name__ == '__main__':
    151. app = QtWidgets.QApplication(sys.argv)
    152. w = CustomMainWindow()
    153. w.show()
    154. sys.exit(app.exec_())
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jun 2021
    Posts
    2
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: Contiguous selection and custom proxy model

    I think I managed to solve it. I had to reimplement sibling method in CustomList2TableProxyModel like so:

    Qt Code:
    1. def sibling(self, row: int, column: int, idx: QtCore.QModelIndex) -> QtCore.QModelIndex:
    2. return self.createIndex(row, column)
    To copy to clipboard, switch view to plain text mode 

Similar Threads

  1. QTreeView selection artifacts with custom tree model
    By gfgit in forum Qt Programming
    Replies: 0
    Last Post: 30th April 2020, 16:11
  2. Replies: 1
    Last Post: 26th February 2014, 21:49
  3. Custom Model and Proxy Model
    By frank100 in forum Qt Programming
    Replies: 1
    Last Post: 20th December 2010, 15:30
  4. Replies: 1
    Last Post: 19th November 2009, 00:21
  5. Custom proxy model issue
    By Khal Drogo in forum Qt Programming
    Replies: 13
    Last Post: 30th November 2007, 13:41

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.