Under Linux Ubuntu 20.04 OS, the default QFileDialog does not provide a search function. I built a custom QFileDialog window and displayed the matched files in the 'setNameFilter' under 'Files of type'. However, due to the excessive number of matches, the screen is occupied by the window.
import sys, os , re from PyQt5.QtCore import * from PyQt5.QtWidgets import * class CustomFileDialog(QFileDialog): directoryChanged = pyqtSignal(str) def __init__(self, init_dir=None, *args, **kwargs): super(CustomFileDialog, self).__init__(*args, **kwargs) self.setOption(QFileDialog.DontUseNativeDialog, True) self.setWindowTitle('Open Files') self.search_bar = QLineEdit(self) self.search_bar.setFixedWidth(130) self.search_bar.setPlaceholderText('Search...') self.search_btn = QPushButton(self) self.search_btn.setFixedWidth(25) self.search_btn.setIcon(self.style().standardIcon(QStyle.SP_FileDialogContentsView)) self.search_btn.clicked.connect(self.handle_search) search_layout = QHBoxLayout() search_layout.addWidget(self.search_bar) search_layout.addWidget(self.search_btn) search_layout.setContentsMargins(0, 0, 0, 0) search_widget = QWidget() search_widget.setLayout(search_layout) self.layout().addWidget(search_widget, 0, 0) self.setNameFilter('txt files (*.txt)') if init_dir: self.setDirectory(init_dir) self.temp_files = [] self.filterSelected.connect(self.change_directory) def handle_search(self): self.filter_files(self.search_bar.text()) def filter_files(self, text): if text: self.search_files(text) else: self.setNameFilter('txt files (*.txt)') def search_files(self, search_text): self.temp_files.clear() pattern = re.compile(search_text) for root, dirs, files in os.walk(self.directory().absolutePath()): for file in files: if pattern.search(search_text) and file.endswith('.txt'): file_path = os.path.join(root, file) self.temp_files.append(file_path) self.update_view(search_text) def update_view(self, search_text): if self.temp_files: # filter_string = ';;'.join([f"{os.path.basename(f)}" for f in self.temp_files]) filter_string =';;'.join([f"Match file {f}" for f in range(60)]) self.setNameFilter(filter_string) else: self.setNameFilter('No matching files (*.txt)') def change_directory(self, file_path): for temp_file in self.temp_files: if file_path in temp_file: file_dir = temp_file.split(file_path)[0] self.setDirectory(file_dir) self.directoryChanged.emit(file_dir) def get_current_name_filter(self): filters = self.nameFilters() if filters: return filters[0] return Nonedef get_open_file_names(): app = QApplication(sys.argv) dialog = CustomFileDialog() dialog.setFileMode(QFileDialog.ExistingFiles) dialog.setViewMode(QFileDialog.Detail) if dialog.exec_(): file_names = dialog.selectedFiles() print(file_names) return file_names return []if __name__ == "__main__": get_open_file_names()I tried using methods to limit the height, such as setFixedHeight for QListview() and QCombobox(), which only restrict the display of filtered files, but the screen is still occupied.
def update_view(self, search_text): if self.temp_files: # filter_string = ';;'.join([f"{os.path.basename(f)}" for f in self.temp_files]) filter_string =';;'.join([f"Match file {f}" for f in range(60)]) combo_boxes = self.findChildren(QComboBox) for combo_box in combo_boxes: combo_box.setView(QListView()) combo_box.clear() for file in self.temp_files: combo_box.addItem(os.path.basename(file)) item_height = combo_box.view().sizeHintForRow(0) visible_items = min(10, combo_box.count()) combo_box.view().setFixedHeight(item_height * visible_items) self.setNameFilter(filter_string) else: self.setNameFilter('No matching files (*.txt)')

