Add basic string search

This commit is contained in:
Veronica Berglyd Olsen
2024-03-23 23:54:41 +01:00
parent 0feac3163f
commit 9153707075
2 changed files with 71 additions and 4 deletions
+28
View File
@@ -304,6 +304,34 @@ class DocDuplicator:
# END Class DocDuplicator # END Class DocDuplicator
class DocSearch:
def __init__(self, project: NWProject) -> None:
self._project = project
return
def iterSearch(self, search: str) -> Iterable[tuple[NWItem, list[tuple[int, int, str]]]]:
"""Iteratively search through documents in the project."""
num = len(search)
cap = min(num+100, 100)
storage = self._project.storage
for item in self._project.tree:
if item.isFileType():
text = storage.getDocument(item.itemHandle).readDocument() or ""
prev = 0
results = []
count = 0
while (pos := text.find(search, prev)) >= 0 and count < 100:
count += 1
context = text[pos:pos+cap].partition("\n")[0]
results.append((pos, num, context))
prev = pos + num
yield item, results
return
# END Class DocSearch
class ProjectBuilder: class ProjectBuilder:
"""A class to build a new project from a set of user-defined """A class to build a new project from a set of user-defined
parameter provided by the New Project Wizard. parameter provided by the New Project Wizard.
+43 -4
View File
@@ -25,10 +25,16 @@ from __future__ import annotations
import logging import logging
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtGui import QPalette from PyQt5.QtGui import QPalette
from PyQt5.QtWidgets import QHBoxLayout, QLabel, QLineEdit, QTreeWidget, QVBoxLayout, QWidget from PyQt5.QtWidgets import (
QHBoxLayout, QLabel, QLineEdit, QTreeWidget, QTreeWidgetItem, QVBoxLayout,
QWidget
)
from novelwriter import CONFIG, SHARED from novelwriter import CONFIG, SHARED
from novelwriter.core.coretools import DocSearch
from novelwriter.core.item import NWItem
from novelwriter.extensions.modified import NIconToolButton from novelwriter.extensions.modified import NIconToolButton
from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON
@@ -51,13 +57,14 @@ class GuiProjectSearch(QWidget):
self.viewLabel.setContentsMargins(mPx, mPx, 0, mPx) self.viewLabel.setContentsMargins(mPx, mPx, 0, mPx)
# Controls # Controls
self.searchBox = QLineEdit(self) self.searchText = QLineEdit(self)
self.searchBox.setPlaceholderText(self.tr("Search text ...")) self.searchText.setPlaceholderText(self.tr("Search text ..."))
self.searchButton = NIconToolButton(self, iPx) self.searchButton = NIconToolButton(self, iPx)
self.searchButton.clicked.connect(self._processSearch)
self.searchBar = QHBoxLayout() self.searchBar = QHBoxLayout()
self.searchBar.addWidget(self.searchBox) self.searchBar.addWidget(self.searchText)
self.searchBar.addWidget(self.searchButton) self.searchBar.addWidget(self.searchButton)
# Search Result # Search Result
@@ -96,4 +103,36 @@ class GuiProjectSearch(QWidget):
return return
##
# Private Slots
##
@pyqtSlot()
def _processSearch(self) -> None:
"""Perform a search."""
self.searchResult.clear()
if text := self.searchText.text():
search = DocSearch(SHARED.project)
for item, results in search.iterSearch(text):
self._appendResultSet(item, results)
return
##
# Internal Functions
##
def _appendResultSet(self, item: NWItem, results: list[tuple[int, int, str]]) -> None:
"""Populate the result tree."""
if results:
tItem = QTreeWidgetItem()
tItem.setText(0, f"{item.itemName} ({len(results)})")
rItems = []
for start, end, context in results:
rItem = QTreeWidgetItem()
rItem.setText(0, context)
rItems.append(rItem)
tItem.addChildren(rItems)
self.searchResult.addTopLevelItem(tItem)
return
# END Class GuiProjectSearch # END Class GuiProjectSearch