Filters the items in this tree based on the inputed keywords.
        
        :param      terms           | {<int> column: [<str> term, ..], ..}
                    autoExpand      | <bool>
                    caseSensitive   | <bool>
                    parent          | <QtGui.QTreeWidgetItem> || None
        
        :return     <bool> | found

def __filterItems(self,
                      terms,
                      autoExpand=True, 
                      caseSensitive=False,
                      parent=None,
                      level=0):
        """
        Filters the items in this tree based on the inputed keywords.
        
        :param      terms           | {<int> column: [<str> term, ..], ..}
                    autoExpand      | <bool>
                    caseSensitive   | <bool>
                    parent          | <QtGui.QTreeWidgetItem> || None
        
        :return     <bool> | found
        """
        # make sure we're within our mex level for filtering
        max_level = self.maximumFilterLevel()
        if max_level != None and level > max_level:
            return False
        
        found = False
        items = []
        
        # collect the items to process
        if not parent:
            for i in range(self.topLevelItemCount()):
                items.append(self.topLevelItem(i))
        else:
            for c in range(parent.childCount()):
                items.append(parent.child(c))
        
        for item in items:
            # if there is no filter keywords, then all items will be visible
            if not any(terms.values()):
                found = True
                item.setHidden(False)
                if autoExpand:
                    if item.parent() is not None or self.rootIsDecorated():
                        item.setExpanded(False)
                
                self.__filterItems(terms,
                                   autoExpand, 
                                   caseSensitive,
                                   item,
                                   level + 1)
            
            else:
                # match all generic keywords
                generic         = terms.get(-1, [])
                generic_found   = dict((key, False) for key in generic)
                
                # match all specific keywords
                col_found  = dict((col, False) for col in terms if col != -1)
                
                # look for any matches for any column
                mfound = False
                
                for column in self._filteredColumns:
                    # determine the check text based on case sensitivity
                    if caseSensitive:
                        check = nativestring(item.text(column))
                    else:
                        check = nativestring(item.text(column)).lower()
                    
                    specific = terms.get(column, [])
                    
                    # make sure all the keywords match
                    for key in generic + specific:
                        if not key:
                            continue
                        
                        # look for exact keywords
                        elif key.startswith('"') and key.endswith('"'):
                            if key.strip('"') == check:
                                if key in generic:
                                    generic_found[key] = True
                                
                                if key in specific:
                                    col_found[column] = True
                        
                        # look for ending keywords
                        elif key.startswith('*') and not key.endswith('*'):
                            if check.endswith(key.strip('*')):
                                if key in generic:
                                    generic_found[key] = True
                                if key in specific:
                                    col_found[column] = True
                        
                        # look for starting keywords
                        elif key.endswith('*') and not key.startswith('*'):
                            if check.startswith(key.strip('*')):
                                if key in generic:
                                    generic_found[key] = True
                                if key in specific:
                                    col_found[column] = True
                        
                        # look for generic keywords
                        elif key.strip('*') in check:
                            if key in generic:
                                generic_found[key] = True
                            if key in specific:
                                col_found[column] = True
                    
                    mfound = all(col_found.values()) and \
                             all(generic_found.values())
                    if mfound:
                        break
                
                # if this item is not found, then check all children
                if not mfound and (autoExpand or item.isExpanded()):
                    mfound = self.__filterItems(terms,
                                                autoExpand, 
                                                caseSensitive,
                                                item,
                                                level + 1)
                
                item.setHidden(not mfound)
                
                if mfound:
                    found = True
                
                if mfound and autoExpand and item.childCount():
                    item.setExpanded(True)
        
        return found