2017-10-11 11 views
1

J'ai un exemple de travail ci-dessous qui ajoute la fonctionnalité de filtre de recherche. J'ai l'impression que ce que je fais est exagéré. Il a été reconstitué à partir de projets que j'ai trouvés en ligne. Est-ce que je dois vraiment créer ce SearchProxyFilter entier pour faire une recherche simple de filtrage de chaîne sur ma liste d'articles? J'ai le sentiment que je fais quelque chose de mal ou plus que ce dont j'ai besoin. Toute suggestion serait appréciée.Filtre de recherche dans QTreeview Pyside

enter image description here

####### 
# Imports 
####### 
import sys 
import os 
from PySide import QtGui, QtCore 

####### 
# Main 
####### 
class SortModel(QtGui.QSortFilterProxyModel): 

    def __init__(self, *args, **kwargs): 
     super(SortModel, self).__init__(*args, **kwargs) 
     self._pattern = '' 

    @property 
    def pattern(self): 
     return self._pattern 

    def filterAcceptsRow(self, sourceRow, sourceParent): 
     if not self.pattern: 
      return True 

     sm = self.sourceModel() 
     modelIdx = sm.index(sourceRow, 0) 
     if modelIdx.isValid(): 
      txt = modelIdx.data(role=QtCore.Qt.DisplayRole) 
      if not self.pattern.lower() in txt.lower(): 
       return False 

     return True 

    def lessThan(self, left, right): 
     leftData = self.sourceModel().data(left) 
     rightData = self.sourceModel().data(right) 

     if leftData: 
      leftData = leftData.lower() 
     if rightData: 
      rightData = rightData.lower() 

     return leftData < rightData 

class UserBrowser(QtGui.QDialog): 

    def __init__(self, parent=None): 
     super(UserBrowser, self).__init__(parent) 
     self.resize(300, 500) 
     self.setWindowTitle('Users') 
     self.setModal(True) 
     self.initUI() 

    def initUI(self): 
     self.results = '' 
     self.filepath = '' 

     self.ui_search = QtGui.QLineEdit() 
     self.ui_search.setPlaceholderText('Search...') 

     self.source_model = QtGui.QStandardItemModel() 
     self.user_model = SortModel(self) 
     self.user_model.setSourceModel(self.source_model) 
     self.user_model.setDynamicSortFilter(True) 
     self.user_model.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive) 

     self.ui_items = QtGui.QTreeView() 
     self.ui_items.setModel(self.user_model) 
     self.ui_items.setAlternatingRowColors(False) 
     self.ui_items.setSortingEnabled(True) 
     self.ui_items.sortByColumn(0, QtCore.Qt.AscendingOrder) 
     self.ui_items.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) 
     self.ui_items.header().setResizeMode(QtGui.QHeaderView.ResizeToContents) 
     self.ui_items.setHeaderHidden(True) 
     self.ui_items.setRootIsDecorated(False) 

     gdl = QtGui.QGridLayout() 
     gdl.setContentsMargins(10, 10, 10, 10) 
     gdl.addWidget(self.ui_search, 0, 0) 
     gdl.addWidget(self.ui_items, 1, 0) 
     self.setLayout(gdl) 
     self.create_model() 

     self.ui_search.textChanged.connect(self.changed_text) 

    # Methods 
    def create_model(self): 
     model = self.source_model 
     model.clear() 
     model.setHorizontalHeaderLabels(['Names']) 

     users = ['kevin','Marry','Doug','Leslie','Michelle','John'] 
     for x in users: 
      item = QtGui.QStandardItem() 
      item.setData(x , role=QtCore.Qt.DisplayRole) 
      model.appendRow(item) 

     self.ui_items.sortByColumn(0, QtCore.Qt.AscendingOrder) 

    # Actions 
    def changed_text(self, text): 
     self.user_model._pattern = text 
     self.user_model.invalidateFilter() 

def main(): 
    app = QtGui.QApplication(sys.argv) 
    ex = UserBrowser() 
    ex.show() 
    sys.exit(app.exec_()) 

if __name__ == '__main__': 
    main() 

Répondre

1

Cela peut être fait beaucoup plus simplement avec un QCompleter:

class UserBrowser(QtGui.QDialog): 
    ...  
    def initUI(self): 
     ... 
     self.completer = QtGui.QCompleter(self) 
     self.completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) 
     self.completer.setModelSorting(
      QtGui.QCompleter.CaseInsensitivelySortedModel) 

     self.ui_items = QtGui.QTreeView() 
     self.ui_items.setModel(self.completer.completionModel()) 
     ... 
     self.create_model() 
     ...  
     self.ui_search.textChanged.connect(self.completer.setCompletionPrefix) 

    # Methods 
    def create_model(self): 
     users = ['kevin','Marry','Doug','Leslie','Michelle','John'] 
     users.sort(key=str.lower) 
     self.completer.setModel(QtGui.QStringListModel(users)) 
+0

Je me sentais comme si j'étais plus compliquer les choses. Merci :) – JokerMartini

+0

est-il possible d'avoir la recherche regarder le texte est «dans» plutôt que «commence par» – JokerMartini

+0

@JokerMartini. Oui - mais vous finirez probablement là où vous avez commencé si vous essayez de l'implémenter. Voir [cette question] (https://stackoverflow.com/q/5129211/984421), par exemple. Malheureusement, je ne vois pas de moyen facile de contourner le mécanisme de filtrage par défaut que 'QCompleter' utilise. Il y a [setFilterMode] (https://doc.qt.io/qt-5/qcompleter.html#filterMode-prop), qui fait exactement ce que vous voulez - mais c'est seulement Qt5. – ekhumoro