The example demonstrates the use of QSortProxyModel, QStandardItemModel and QTreeView. One standard item model is used to create two views containing the same data. The second view uses a proxy model to allow sorting and filtering. Changes in the second view are not reflected in the first view even though the underlying models are the same.
Part 1 creates the basic GUI.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''
PyQt4 conversion of Qt Basic Sort/Filter Example
The Basic Sort/Filter Model example illustrates how to use
QSortFilterProxyModel to perform basic sorting and filtering.
BEHAVIOUR:
=========
GUI is laid out. The initial conditions for each widget
are in place. Both the case sentivity checkboxes are checked.
The Filter Column combobox is set to 'Sender'.
NOTES:
=====
Create Window class and implement methods to build the GUI
(refactored the original C++ to split the creation of the
various screen areas up for easier reading.)
Create signal/slot connections, adding stub methods for the slots.
last modified: 2012-01-30 jg
ref:
http://developer.qt.nokia.com/doc/qt-4.8/itemviews-basicsortfiltermodel.html
'''
from PyQt4.QtGui import (QApplication, QWidget, QGroupBox, QHBoxLayout, QLabel,
QVBoxLayout, QGridLayout, QTreeView, QSortFilterProxyModel,
QCheckBox, QLineEdit, QComboBox, QStandardItemModel)
from PyQt4.QtCore import (Qt, pyqtSlot, QRegExp)
class Window(QWidget):
def __init__(self, parent=None): # initialise base class
super(Window, self).__init__(parent)
layout = QVBoxLayout()
layout.addWidget(self._createSourcePanel())
layout.addWidget(self._createProxyPanel())
self.setLayout(layout)
# private methods ---------------------------------------------------------
def _createSourcePanel(self):
sourceGroupBox = QGroupBox(self.tr("Original Model"))
sourceView = QTreeView()
sourceView.setRootIsDecorated(False)
sourceView.setAlternatingRowColors(True)
sourceLayout = QHBoxLayout()
sourceLayout.addWidget(sourceView)
sourceGroupBox.setLayout(sourceLayout)
return sourceGroupBox
def _createProxyPanel(self):
proxyGroupBox = QGroupBox(self.tr("Sorted/Filter Model"))
proxyView = QTreeView()
proxyView.setRootIsDecorated(False)
proxyView.setAlternatingRowColors(True)
proxyView.sortByColumn(1, Qt.AscendingOrder)
proxyModel = QSortFilterProxyModel()
proxyModel.setDynamicSortFilter(True)
proxyView.setModel(proxyModel)
proxyView.setSortingEnabled(True) # click col hdr to sort
proxyLayout = QVBoxLayout()
proxyLayout.addWidget(proxyView)
proxyLayout.addLayout(self._createProxyFilterPanel())
proxyGroupBox.setLayout(proxyLayout)
return proxyGroupBox
def _createProxyFilterPanel(self):
sortCaseSensitivityCheckBox = QCheckBox(self.tr("Case sensitive sorting"));
sortCaseSensitivityCheckBox.setChecked(True)
filterCaseSensitivityCheckBox = QCheckBox(self.tr("Case sensitive filter"));
filterCaseSensitivityCheckBox.setChecked(True)
filterPatternLineEdit = QLineEdit();
filterPatternLabel = QLabel(self.tr("&Filter pattern:"));
filterPatternLabel.setBuddy(filterPatternLineEdit);
filterSyntaxComboBox = QComboBox();
filterSyntaxComboBox.addItem(self.tr("Regular expression"), QRegExp.RegExp);
filterSyntaxComboBox.addItem(self.tr("Wildcard"), QRegExp.Wildcard);
filterSyntaxComboBox.addItem(self.tr("Fixed string"), QRegExp.FixedString);
filterSyntaxLabel = QLabel(self.tr("Filter &syntax:"));
filterSyntaxLabel.setBuddy(filterSyntaxComboBox);
filterColumnComboBox = QComboBox();
filterColumnComboBox.addItem(self.tr("Subject"));
filterColumnComboBox.addItem(self.tr("Sender"));
filterColumnComboBox.addItem(self.tr("Date"));
filterColumnComboBox.setCurrentIndex(1)
filterColumnLabel = QLabel(self.tr("Filter &column:"));
filterColumnLabel.setBuddy(filterColumnComboBox);
# connect signals/slots for event handling
filterPatternLineEdit.textChanged.connect(self._filterRegExpChanged)
filterSyntaxComboBox.currentIndexChanged.connect(self._filterRegExpChanged)
filterColumnComboBox.currentIndexChanged.connect(self._filterColumnChanged)
filterCaseSensitivityCheckBox.toggled.connect(self._filterRegExpChanged)
sortCaseSensitivityCheckBox.toggled.connect(self._sortChanged)
grid = QGridLayout()
grid.addWidget(filterPatternLabel, 0, 0)
grid.addWidget(filterPatternLineEdit, 0, 1)
grid.addWidget(filterSyntaxLabel, 1, 0)
grid.addWidget(filterSyntaxComboBox, 1, 1)
grid.addWidget(filterColumnLabel, 2, 0)
grid.addWidget(filterColumnComboBox, 2, 1)
grid.addWidget(filterCaseSensitivityCheckBox, 3, 0)
grid.addWidget(sortCaseSensitivityCheckBox, 3, 1, Qt.AlignRight)
return grid
# private slots -----------------------------------------------------------
@pyqtSlot()
def _filterRegExpChanged(self):
pass
@pyqtSlot()
def _filterColumnChanged(self):
pass
@pyqtSlot()
def _sortChanged(self):
pass
# main ========================================================================
def main():
import sys
app = QApplication(sys.argv)
mw = Window()
mw.setWindowTitle("Basic Sort/Filter Model - Part 1")
mw.resize(500, 450)
mw.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
