Reputation: 686
How to arrange the filtered QListwidget items in the following order,
For example, In My Program, my search term is "I", I want to arrange item starts with "I" ("India", "Iceland", "Iran"), then item containing anywhere ("America", "China", "Fiji","Russia"), finally items end with search term "I" ("Brunei", "Mali")
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QListWidget,QLineEdit,QVBoxLayout
from PyQt5.QtCore import Qt,QEvent
items = ["America","canada","Mali","India","Russia", "Fiji","Nepal","Iran","China","Japan","IceLand","Brunei"]
class Listwidget(QWidget):
def __init__(self):
super(). __init__()
self.setWindowTitle("List Box Samples")
self.le = QLineEdit()
self.le.textChanged.connect(self.func_textchanged)
self.lb_master = QListWidget()
self.lb_search = QListWidget()
vbox = QVBoxLayout(self)
vbox.addWidget(self.le)
vbox.addWidget(self.lb_search)
self.lb_master.addItems(items)
self.lb_search.addItems(items)
self.le.setFocus()
self.le.installEventFilter(self)
def eventFilter(self, source,event):
if event.type() == QEvent.KeyPress and source is self.le:
if event.key() == Qt.Key_Backspace:
if len(self.le.text()) == 0:
self.fun_normal()
return super(Listwidget,self).eventFilter(source,event)
def fun_normal(self):
self.lb_search.clear()
if normal_count > 0:
for item in item_normal:
self.lb_search.addItem(item.text())
def func_search(self):
self.lb_search.clear()
if search_count > 0:
for item in item_anywhere:
self.lb_search.addItem(item.text())
def func_textchanged(self):
global item_normal,item_anywhere,search_count,normal_count
item_normal = self.lb_master.findItems("*",Qt.MatchWildcard)
item_anywhere = self.lb_master.findItems(self.le.text(), Qt.MatchContains)
normal_count = len(item_normal)
search_count = len(item_anywhere)
self.func_search()
if __name__ == "__main__":
app = QApplication(sys.argv)
win = Listwidget()
win.show()
sys.exit(app.exec_())
Upvotes: 1
Views: 623
Reputation: 3079
There are few ways to do go about what you are trying to acheive. One is to sort the list based on a key.
In your case, it could be
item_anywhere.sort(key=lambda item: item.text().lower().find(self.le.text()))
Output:
['India', 'Iran', 'IceLand', 'Fiji', 'China', 'Mali', 'America', 'Russia', 'Brunei']
As you can see there is a small problem with this approach, that is, "Mali" is in the middle of the list and not towards the end.
The only approach I could think of right now is to use filter
function.
Below are the steps I followed:
find
method to find the strings (you have already done this part).I
or whatever the search text is.I
. def func_textchanged(self):
search_text = self.le.text().lower()
item_anywhere = self.lb_master.findItems(search_text, Qt.MatchContains)
start_list = list(filter(lambda item: item.text().lower().startswith(search_text), item_anywhere))
start_text = [x.text().lower() for x in start_list]
def bw_filter(item):
# checks if the letter is between the start and end letter, then checks if it already exists in start_list
item_text = item.text().lower()
return search_text in item_text[1:-1] and item_text not in start_text
bw_lst = list(filter(bw_filter, item_anywhere))
bw_lst.sort(key=lambda item: item.text().lower().find(search_text)) # sort it based on index
bw_text = [x.text().lower() for x in bw_lst]
def end_filter(item):
# checks if the string ends with search string, then checks if it already exists in
# start_list and between list
item_text = item.text().lower()
return item_text.endswith(search_text) and item_text.lower() not in start_text and item_text not in bw_text
end_lst = list(filter(end_filter, item_anywhere))
self.lb_search.clear()
for item in start_list + bw_lst + end_lst: # concatenate list
self.lb_search.addItem(item.text())
Upvotes: 1