TreeViewの中身を正規表現で検索する¶
PySideの各種Viewは、ProxyModelを使用することでリスト内の絞り込み検索を
追加することができます。
ただ、TreeViewの場合などとくに顕著ですが
文字列で「絞り込んでほしくないItem」、例としてGroup用の階層などがある場合は
あえて検索文字で絞り込みたくない場合などもあります。
ので、その辺踏まえてTreeViewで検索をするための構造を作ってみます。
コード¶
まずはコード。
解説¶
まずはQAbstractItemModelを使用してTreeViewとModelを作成します。
実行するとこんな感じのUIが表示されます。
まず、このTreeViewの場合
特になにもしない場合 GroupA GroupBも検索で引っかかってしまい
「テスト」などで検索をしてもなにも表示されなくなってしまいます。
(親が検索にひっかからないと子は表示されないため)
ので、より細かく検索条件を分岐させる必要があります。
その分岐をするのが、 QSortFilterProxyModelのVirtual関数、「filterAcceptRow」 です。
1 2 3 4 5 6 7 8 9 10 11 12 |
|
filterAcceptsRow関数は、表示するかどうかを各Itemごとに判定して
表示するかどうかを bool で返します。
parentとrowを引数として受け取ります。
これは、表示するかどうか判定したいItemからみた「親」アイテムと、その親から見た「何番目のItemか」
という情報になります。
このparentはModelIndexになるので internalPointer を使用して実体のItemを取得してしています。
internalPointerについては以前の QtCore.QAbstractItemModelを使用したカスタムモデルの作成を
参考にしてください。
で。
今回の場合は、「親がGroupItem」オブジェクトだった場合は検索対象のItem(TreeItem)なので
正規表現によるチェックをするために、オーバーライドする前の filterAcceptsRow を実行するようにします。
それ以外の場合、この場合でいうと GroupItemの場合は
かならず表示するようにしたいので True を返すようにします。
このようにすると、 GroupItemの場合は
ProxyModelでどのような条件がきたとしても「絶対表示する」ようになるので
今回のTreeViewのように特定のItemは判定外にする...といった事が可能になります。
余談ですが、filterAcceptsRow意外にもfilterAcceptsColumn関数もあるので
条件をRowではなくColumn単位で指定したい場合は
同じような形でfilterAcceptsColumnで実装すればOKです。
検索文字列を指定のものにしたい場合¶
今回のサンプルの場合は列が1つなので問題ないのですが
例えば列が複数あって、すべてを検索対象にしたい...というケースも発生します。
その場合は、ProxyModelの self.proxymodel.setFilterRole(PROXY_FILTER_ROLE) を使用することで
検索対象にする文字列を Model側で指定することが出来ます。
まずは、Proxy側で setFilterRole に対してRoleを指定します。
Roleは、 UserRole を使用しても良いし、すでに使っている場合は↓のように + 1 したものを
別途定義するとかでもOKです。
1 2 3 4 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
そして、Modelの data で、PROXY_FILTER_ROLEだった場合は、検索対象にしたい
文字列を返すようにしておくと、ProxyModelでの絞り込み対象の文字列を
カスタマイズすることができます。