Skip to content

Instantly share code, notes, and snippets.

@pashango2
Created December 23, 2016 17:11
Show Gist options
  • Save pashango2/c548c28525c630f124da835648062f5d to your computer and use it in GitHub Desktop.
Save pashango2/c548c28525c630f124da835648062f5d to your computer and use it in GitHub Desktop.
汎用検索オブジェクト
#! usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, print_function, absolute_import
"""
# 汎用検索オブジェクト
QAbstractItemViewに対して付加可能な検索オブジェクト。
ツリー型モデルとテーブル型の両対応をしている。
# 使い方
```
import sys
app = QApplication(sys.argv)
widget = QWidget()
layout = QVBoxLayout(widget)
line_edit = QLineEdit(widget)
table_view = QTableView(widget)
layout.addWidget(line_edit)
layout.addWidget(table_view)
table_model = QStandardItemModel(3, 3)
table_model.setItem(0, 0, QStandardItem("りんご"))
table_model.setItem(0, 1, QStandardItem("\\100"))
table_model.setItem(1, 0, QStandardItem("バナナ"))
table_model.setItem(1, 1, QStandardItem("\\100"))
table_model.setItem(2, 0, QStandardItem("メロン"))
table_model.setItem(2, 1, QStandardItem("\\100"))
table_view.setModel(table_model)
finder_obj = FinderObject(table_model, table_view, widget)
line_edit.textChanged.connect(finder_obj.find)
line_edit.returnPressed.connect(finder_obj.findNext)
finder_obj.indexFound.connect(table_view.setCurrentIndex)
next_act = finder_obj.createFindNextAction("次へ", widget)
prev_act = finder_obj.createFindPreviousAction("前へ", widget)
widget.addActions([next_act, prev_act])
widget.show()
app.exec_()
```
"""
from PySide.QtCore import *
from PySide.QtGui import *
class FinderObject(QObject):
indexFound = Signal(QModelIndex)
def __init__(self, model, view, parent=None):
"""
:type view: QAbstractItemView
:type parent: QObject or None
:type model: QAbstractItemModel
"""
super(FinderObject, self).__init__(parent)
self.model = model
self.view = view
self._cmp_func = self._default_cmp
self._find_str = ""
self._current_index = QModelIndex()
self.find_role = Qt.DisplayRole
def _default_cmp(self, find_str, index):
""" 標準の比較関数
:type find_str: str or unicode
:type index: QModelIndex
"""
data = index.data(self.find_role)
return data and find_str.lower() in data.lower()
def next_index(self, index=QModelIndex()):
""" 次のQModelIndexを求める
:rtype: QModelIndex
:type index: QModelIndex
"""
if index.isValid():
_index = index.child(0, 0)
if not _index.isValid():
_index = index.sibling(index.row(), index.column() + 1)
if not _index.isValid():
_index = index.sibling(index.row() + 1, 0)
if not _index.isValid():
_index = index.parent()
_index = _index.sibling(_index.row() + 1, 0)
if not _index.isValid():
_index = self.model.index(0, 0)
return _index
else:
return self.model.index(0, 0)
def _last_index(self, index=QModelIndex()):
""" 最後の葉のQModelIndexを求める
:type index: QModelIndex
"""
while self.model.rowCount(index) > 1:
index = self.model.index(self.model.rowCount(index) - 1, 0, index)
index = index.sibling(index.row(), self.model.columnCount(index.parent()) - 1)
return index
def prev_index(self, index=QModelIndex()):
""" 前のQModelIndexを求める
:rtype: QModelIndex
:type index: QModelIndex
"""
if index.isValid():
_index = index.sibling(index.row(), index.column() - 1)
if not _index.isValid():
_index = index.sibling(index.row() - 1, 0)
if _index.isValid():
_index = self._last_index(_index)
if _index.isValid():
_index = _index.sibling(_index.row(), self.model.columnCount(_index.parent()) - 1)
if not _index.isValid():
_index = index.parent()
if not _index.isValid():
_index = self._last_index()
return _index
else:
return self._last_index()
@Slot(str)
def find(self, find_str):
""" 検索
:type find_str: str or unicode
"""
self._find_str = find_str
current_index = self.view.currentIndex()
if not current_index.isValid() or not self._cmp_func(find_str, current_index):
self._find()
def _find(self, forward=True):
""" 検索(内部関数)
:type forward: bool
"""
if not self._find_str:
return
index = self.view.currentIndex()
index = stop_index = self.next_index(index) if forward else self.prev_index(index)
while True:
if self._cmp_func(self._find_str, index):
self.indexFound.emit(index)
break
index = self.next_index(index) if forward else self.prev_index(index)
if index == stop_index:
break
@Slot()
def findNext(self):
""" 次を探索 """
self._find()
@Slot()
def findPrevious(self):
""" 前を探索 """
self._find(forward=False)
def createFindNextAction(self, text, parent=None):
"""
:type parent: QWidget
:type text: str
"""
act = QAction(text, parent, triggered=self.findNext)
act.setShortcut(QKeySequence.FindNext)
return act
def createFindPreviousAction(self, text, parent=None):
"""
:type parent: QWidget
:type text: str
"""
act = QAction(text, parent, triggered=self.findPrevious)
act.setShortcut(QKeySequence.FindPrevious)
return act
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment