我想使用 QPdfSearchModel 用 pdf 中的所有搜索结果填充 QListView。问题是我正在寻找的字符串可以有或没有空格。例如。当我搜索“ABC DEF”时,QListView 应该显示“ABC DEF”和“ABCDEF”的所有结果。
在 QPdfSearchModel 中,您只能设置单个搜索词。因此,我想扩展这一功能以包含多个搜索词。
我创建了一个新类“CombinedListModel”来组合多个 QPDFSearchmodels 的结果。这部分有效,因为我能够看到 QListView 中所有搜索字符串的所有命中。但是,与 PdfViewer 的链接消失了,因为单击 QListView 中的项目不会执行任何操作。
import sys
from PySide6.QtCore import Qt, QModelIndex
from PySide6.QtWidgets import QApplication, QMainWindow, QListView, QVBoxLayout, QWidget, QLineEdit
from PySide6.QtPdf import QPdfDocument, QPdfSearchModel
from PySide6.QtPdfWidgets import QPdfView
from PySide6 import QtGui
class CombinedListModel(QPdfSearchModel):
def __init__(self, models, parent=None):
super(CombinedListModel, self).__init__(parent)
self.models = models
def rowCount(self, parent=QModelIndex()):
return sum(model.rowCount(QModelIndex()) for model in self.models)
def data(self, index, role=Qt.DisplayRole):
if not index.isValid():
return None
current_row = index.row()
for model in self.models:
if current_row < model.rowCount(QModelIndex()):
return model.data(model.index(current_row), role)
current_row -= model.rowCount(QModelIndex())
return None
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("PDF Search Viewer")
self.search_bar = QLineEdit(self)
self.search_bar.textChanged.connect(self.on_search_text_changed)
self.list_view = QListView(self)
self.list_view.clicked.connect(self.on_list_view_clicked)
layout = QVBoxLayout()
layout.addWidget(self.search_bar)
layout.addWidget(self.list_view)
container = QWidget()
container.setLayout(layout)
self.setCentralWidget(container)
self.pdf_document = QPdfDocument(self)
self.pdf_document.load(r"C:\temp\OCR_highlighted.pdf") # Path to your PDF file
self.pdf_viewer = QPdfView(self)
self.pdf_viewer.setDocument(self.pdf_document)
self.pdf_viewer.setPageMode(QPdfView.PageMode.MultiPage)
layout.addWidget(self.pdf_viewer)
self.search_bar.setText("ABCDEF;ABC DEF")
def on_search_text_changed(self, text):
# create multiple search models
search_terms = text.split(';') # Split the search terms by semicolon
self.search_models = [QPdfSearchModel(self) for _ in search_terms]
for model, term in zip(self.search_models, search_terms):
model.setDocument(self.pdf_document)
model.setSearchString(term)
print(f"Found: {len(sum([model.resultsOnPage(i) for i in range(self.pdf_document.pageCount())],[]))} times")
combined_model = CombinedListModel(self.search_models)
if False:
self.list_view.setModel(self.search_models[(0)])
self.pdf_viewer.setSearchModel(self.search_models[0])
else:
self.list_view.setModel(combined_model)
self.pdf_viewer.setSearchModel(combined_model) # --> This does not work properly (links are gone)
def on_list_view_clicked(self, index):
self.pdf_viewer.setCurrentSearchResultIndex(index.row()) # --> This does not work properly with combined model (links are gone)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
QPdfView
类使用 resultAtIndex()
类的 resultsOnPage()
和 QPdfSearchModel
方法,但目前无法重写这些方法,如 Musicamante 所评论的。 (视图在渲染页面时调用它们。)因此,不可能同时渲染多个模型的搜索结果(QPdfLink
对象)。
您最好的选择是,当单击搜索结果时,将搜索模型更改为相应的模型。 (先调用
setSearchModel()
,然后再调用 setCurrentSearchResultIndex()
。)