Listbox and listview iterators
Often, you find yourself iterating over all items in a QListBox (or you own subclass) to get selected items only. Using a generator (Python 2.2 +), this gets very intuitive:
def ListBoxIterator(listbox):
i = listbox.firstItem()
while i:
yield i
i = i.next()
If you then want to get selected items only, you can do this very pythonic(tm) by using ifilter(...) from the itertools module (Python 2.3+)
ifilter(lambda x: x.isSelected(),
ListBoxIterator(listbox))
It is also possible to use this in a list comprehension, which returns a list immediately and not another iterator:
selected_items = [i for i in ListBoxIterator(listbox) if i.isSelected()]
Another possibility is installing this function as a method of the QListBox class, enabling its use as a iterable object:
QListBox.__iter__ = ListBoxIterator
...
for item in listbox:
print item
For a QListView, there are two different iterators, one that only walks over first-level children:
def FlatLVIterator(parent):
child = parent.firstChild()
while child:
yield child
child = child.nextSibling()
The other one traverses the whole tree below a node:
def DeepLVIterator(parent):
child = parent.firstChild()
while child:
yield child
for c in DeepLVIterator(child):
yield c
child = child.nextSibling()
Note, that you can supply both instances of QListView and QListViewItem to this generators, which would not be possible in C++, because they do not have a common base class interface. In Python, everything is method- (or message-, if you prefer Smalltalk) based, and both classes have a firstChild() member.
The searching functions in QListView are very limited. This generator delivers all matches for a given string or QRegExp:
def SearchLVIterator(parent, searchPattern):
for item in DeepLVIterator(parent):
txt = item.text(0)
if txt.contains(searchPattern):
yield item
This is only a shortcut, because it could also be done with ifilter(...) or a list comprehension.
PyQt Wiki