今回は、ViewにMayaのOutlinerみたいなフィルターをつけてみたいと思います!
Viewに表示するものが多いと、目的のものを見つけるのが大変なので、こういうフィルターが設定できると使い勝手がぐっと良くなりますよね!(*´ω`*)b
見た目の作成
まずは、フィルター用の文字を入れるWidgetと、肝心のリストを表示するViewを用意したいと思います。
今回は、「QWidget」に「QLineEdit」と「QListView」を突っ込んで作ります。
from PySide import QtCore from PySide import QtGui from maya import cmds class ItemView(QtGui.QWidget): def __init__(self, *args, **kwargs): super(ItemView, self).__init__(*args, **kwargs) layout = QtGui.QVBoxLayout(self) self.__filter = QtGui.QLineEdit(self) layout.addWidget(self.__filter) self.__listView = QtGui.QListView(self) layout.addWidget(self.__listView)
この段階では、こんな感じの見た目になります。
フィルターの実装1
まず、表示項目をフィルタリングしたい場合は、「QSortFilterProxyModel」をViewに設定します。
from PySide import QtCore from PySide import QtGui from maya import cmds class ItemView(QtGui.QWidget): def __init__(self, *args, **kwargs): super(ItemView, self).__init__(*args, **kwargs) layout = QtGui.QVBoxLayout(self) self.__filter = QtGui.QLineEdit(self) layout.addWidget(self.__filter) self.__proxyModel = QtGui.QSortFilterProxyModel(self) self.__listView = QtGui.QListView(self) self.__listView.setModel(self.__proxyModel) layout.addWidget(self.__listView)
「QSortFilterProxyModel」は、QStandardItemModelなどのようにデータを追加するものではなく、設定されたModelをフィルタリングするクラスです。なので、Viewに表示するためのModelを、「QSortFilterProxyModel」に渡してあげる必要があります。
図にすると、こんな感じでしょうか。
QStandardItemModel→QSortFilterProxyModel→QListView
しかし!このままではViewにモデルを設定するルートがないので、モデルを外部から設定できるように「setSourceModel」を追加します。
from PySide import QtCore from PySide import QtGui from maya import cmds class ItemView(QtGui.QWidget): def __init__(self, *args, **kwargs): super(ItemView, self).__init__(*args, **kwargs) layout = QtGui.QVBoxLayout(self) self.__filter = QtGui.QLineEdit(self) layout.addWidget(self.__filter) self.__proxyModel = QtGui.QSortFilterProxyModel(self) self.__listView = QtGui.QListView(self) self.__listView.setModel(self.__proxyModel) layout.addWidget(self.__listView) def setSourceModel(self, model): self.__proxyModel.setSourceModel(model)
フィルターの実装2
次は、QLineEditを編集したら、フィルタリングを実行する処理を追加します。
まず、QLineEditの文字が変更された時にSignal「textChanged」とコネクションします。
from PySide import QtCore from PySide import QtGui from maya import cmds class ItemView(QtGui.QWidget): def __init__(self, *args, **kwargs): super(ItemView, self).__init__(*args, **kwargs) layout = QtGui.QVBoxLayout(self) self.__filter = QtGui.QLineEdit(self) self.__filter.textChanged.connect(self.filterChanged) layout.addWidget(self.__filter) self.__proxyModel = QtGui.QSortFilterProxyModel(self) self.__listView = QtGui.QListView(self) self.__listView.setModel(self.__proxyModel) layout.addWidget(self.__listView) def setSourceModel(self, model): self.__proxyModel.setSourceModel(model)
次に、Slot側の実装です。
from PySide import QtCore from PySide import QtGui from maya import cmds class ItemView(QtGui.QWidget): def __init__(self, *args, **kwargs): super(ItemView, self).__init__(*args, **kwargs) layout = QtGui.QVBoxLayout(self) self.__filter = QtGui.QLineEdit(self) self.__filter.textChanged.connect(self.filterChanged) layout.addWidget(self.__filter) self.__proxyModel = QtGui.QSortFilterProxyModel(self) self.__listView = QtGui.QListView(self) self.__listView.setModel(self.__proxyModel) layout.addWidget(self.__listView) def setSourceModel(self, model): self.__proxyModel.setSourceModel(model) def filterChanged(self, filter): regExp = QtCore.QRegExp( filter, QtCore.Qt.CaseSensitive, QtCore.QRegExp.Wildcard ) self.__proxyModel.setFilterRegExp(regExp)
フィルタリング用の文字列を元に、QRegExpのインスタンスを作成します。
第1引数は、元となる文字です。ここでは、QLineEditに入力した文字列が指定されます。
第2引数は、大文字・小文字を無視するかどうかです。「CaseSensitive」は区別する、「CaseInsensitive」は区別しないとなります。
第3引数は、第1引数で指定した文字のあ使い方を設定します。ここでは、ワイルドカードとして認識するように設定しています。その他の種類については、コチラをご覧ください。
最後に、Viewに設定した「QSortFilterProxyModel」の「setFilterRegExp」を使って、フィルタリングの情報(QRegExp)を設定します。
テスト
テスト用に、シーン内にあるすべてのノード名をQStandardItemModelにつっこんで、簡易的なOutlinerを作ってみます。
from PySide import QtCore from PySide import QtGui from maya import cmds itemView = ItemView() itemView.setWindowFlags(QtCore.Qt.Window) model = QtGui.QStandardItemModel(itemView) for node in cmds.ls(): model.appendRow(QtGui.QStandardItem(node)) itemView.setSourceModel(model) itemView.show()
すると、このような感じで動作します!(`・ω・´)ゞ
大文字・小文字の区別、文字パターンの種類とかを、別途オプションで用意すると、更にいい感じになりそうですねっ!∠( ゚д゚)/