add doxc compatibilty
This commit is contained in:
@@ -6,3 +6,4 @@ sentence-transformers==2.2.2
|
|||||||
transformers==4.28.1
|
transformers==4.28.1
|
||||||
torch==1.13.1
|
torch==1.13.1
|
||||||
numpy==1.24.2
|
numpy==1.24.2
|
||||||
|
python-docx
|
||||||
42
uff_app.py
42
uff_app.py
@@ -7,6 +7,12 @@ import zipfile
|
|||||||
import io
|
import io
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
# NEU: Word Support
|
||||||
|
try:
|
||||||
|
import docx
|
||||||
|
except ImportError:
|
||||||
|
docx = None # Fallback, falls nicht installiert
|
||||||
|
|
||||||
from sentence_transformers import SentenceTransformer, util
|
from sentence_transformers import SentenceTransformer, util
|
||||||
from rapidfuzz import process, fuzz
|
from rapidfuzz import process, fuzz
|
||||||
|
|
||||||
@@ -48,6 +54,10 @@ sys.stderr = sys.stdout
|
|||||||
print(f"--- START LOGGING ---")
|
print(f"--- START LOGGING ---")
|
||||||
print(f"Logfile: {log_file_path}")
|
print(f"Logfile: {log_file_path}")
|
||||||
|
|
||||||
|
# Check ob docx installiert ist und warnen im Log
|
||||||
|
if docx is None:
|
||||||
|
print("WARNUNG: 'python-docx' ist nicht installiert. .docx Dateien werden ignoriert.")
|
||||||
|
|
||||||
def qt_message_handler(mode, context, message):
|
def qt_message_handler(mode, context, message):
|
||||||
msg_lower = message.lower()
|
msg_lower = message.lower()
|
||||||
ignore_keywords = [
|
ignore_keywords = [
|
||||||
@@ -73,7 +83,6 @@ class SearchResultItem(QFrame):
|
|||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.filepath = filepath
|
self.filepath = filepath
|
||||||
|
|
||||||
# Optik der Karte
|
|
||||||
self.setFrameShape(QFrame.Shape.StyledPanel)
|
self.setFrameShape(QFrame.Shape.StyledPanel)
|
||||||
self.setStyleSheet("""
|
self.setStyleSheet("""
|
||||||
SearchResultItem {
|
SearchResultItem {
|
||||||
@@ -91,7 +100,7 @@ class SearchResultItem(QFrame):
|
|||||||
layout = QVBoxLayout(self)
|
layout = QVBoxLayout(self)
|
||||||
layout.setContentsMargins(10, 10, 10, 10)
|
layout.setContentsMargins(10, 10, 10, 10)
|
||||||
|
|
||||||
# 1. Dateiname (Sieht aus wie ein Link, ist aber ein Button)
|
# 1. Dateiname
|
||||||
self.btn_title = QPushButton(filename)
|
self.btn_title = QPushButton(filename)
|
||||||
self.btn_title.setCursor(Qt.CursorShape.PointingHandCursor)
|
self.btn_title.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||||
self.btn_title.setStyleSheet("""
|
self.btn_title.setStyleSheet("""
|
||||||
@@ -109,13 +118,12 @@ class SearchResultItem(QFrame):
|
|||||||
""")
|
""")
|
||||||
self.btn_title.clicked.connect(self.open_file)
|
self.btn_title.clicked.connect(self.open_file)
|
||||||
|
|
||||||
# 2. Snippet (Textvorschau)
|
# 2. Snippet
|
||||||
# Wir nutzen QLabel mit WordWrap. HTML für Fettung ist okay.
|
|
||||||
self.lbl_snippet = QLabel(snippet)
|
self.lbl_snippet = QLabel(snippet)
|
||||||
self.lbl_snippet.setWordWrap(True)
|
self.lbl_snippet.setWordWrap(True)
|
||||||
self.lbl_snippet.setStyleSheet("color: #444; font-size: 10pt; margin-top: 5px;")
|
self.lbl_snippet.setStyleSheet("color: #444; font-size: 10pt; margin-top: 5px;")
|
||||||
|
|
||||||
# 3. Pfad (Grau und klein)
|
# 3. Pfad
|
||||||
self.lbl_path = QLabel(filepath)
|
self.lbl_path = QLabel(filepath)
|
||||||
self.lbl_path.setStyleSheet("color: #888; font-size: 8pt; margin-top: 5px;")
|
self.lbl_path.setStyleSheet("color: #888; font-size: 8pt; margin-top: 5px;")
|
||||||
|
|
||||||
@@ -124,19 +132,13 @@ class SearchResultItem(QFrame):
|
|||||||
layout.addWidget(self.lbl_path)
|
layout.addWidget(self.lbl_path)
|
||||||
|
|
||||||
def open_file(self):
|
def open_file(self):
|
||||||
"""
|
|
||||||
Öffnet die Datei direkt über QDesktopServices.
|
|
||||||
"""
|
|
||||||
print(f"Öffne Datei: {self.filepath}")
|
print(f"Öffne Datei: {self.filepath}")
|
||||||
|
|
||||||
target_path = self.filepath
|
target_path = self.filepath
|
||||||
# Falls es ein ZIP-Pfad ist (erkennbar am Trenner " :: ")
|
|
||||||
if " :: " in target_path:
|
if " :: " in target_path:
|
||||||
target_path = target_path.split(" :: ")[0]
|
target_path = target_path.split(" :: ")[0]
|
||||||
|
|
||||||
url = QUrl.fromLocalFile(target_path)
|
url = QUrl.fromLocalFile(target_path)
|
||||||
success = QDesktopServices.openUrl(url)
|
success = QDesktopServices.openUrl(url)
|
||||||
|
|
||||||
if not success:
|
if not success:
|
||||||
print("Fehler: Konnte Datei nicht öffnen.")
|
print("Fehler: Konnte Datei nicht öffnen.")
|
||||||
|
|
||||||
@@ -267,12 +269,25 @@ class IndexerThread(QThread):
|
|||||||
ext = os.path.splitext(filename)[1].lower()
|
ext = os.path.splitext(filename)[1].lower()
|
||||||
text = ""
|
text = ""
|
||||||
try:
|
try:
|
||||||
|
# --- PDF ---
|
||||||
if ext == ".pdf":
|
if ext == ".pdf":
|
||||||
try:
|
try:
|
||||||
with pdfplumber.open(stream) as pdf:
|
with pdfplumber.open(stream) as pdf:
|
||||||
for p in pdf.pages:
|
for p in pdf.pages:
|
||||||
if t := p.extract_text(): text += t + "\n"
|
if t := p.extract_text(): text += t + "\n"
|
||||||
except: pass
|
except: pass
|
||||||
|
|
||||||
|
# --- WORD / DOCX ---
|
||||||
|
elif ext == ".docx" and docx is not None:
|
||||||
|
try:
|
||||||
|
# python-docx kann file-like objects (BytesIO oder file) lesen
|
||||||
|
doc = docx.Document(stream)
|
||||||
|
for para in doc.paragraphs:
|
||||||
|
text += para.text + "\n"
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Docx Error {filename}: {e}")
|
||||||
|
|
||||||
|
# --- PLAIN TEXT ---
|
||||||
elif ext in [".txt", ".md", ".py", ".json", ".csv", ".html", ".log", ".ini", ".xml"]:
|
elif ext in [".txt", ".md", ".py", ".json", ".csv", ".html", ".log", ".ini", ".xml"]:
|
||||||
try:
|
try:
|
||||||
content = stream.read()
|
content = stream.read()
|
||||||
@@ -347,7 +362,7 @@ class UffWindow(QMainWindow):
|
|||||||
self.load_saved_folders()
|
self.load_saved_folders()
|
||||||
|
|
||||||
def initUI(self):
|
def initUI(self):
|
||||||
self.setWindowTitle("UFF Search v6.0 (Widget List)")
|
self.setWindowTitle("UFF Search")
|
||||||
self.resize(1000, 700)
|
self.resize(1000, 700)
|
||||||
central = QWidget()
|
central = QWidget()
|
||||||
self.setCentralWidget(central)
|
self.setCentralWidget(central)
|
||||||
@@ -458,7 +473,7 @@ class UffWindow(QMainWindow):
|
|||||||
if not query: return
|
if not query: return
|
||||||
|
|
||||||
self.lbl_status.setText("Suche läuft...")
|
self.lbl_status.setText("Suche läuft...")
|
||||||
QApplication.processEvents() # UI Update erzwingen
|
QApplication.processEvents()
|
||||||
|
|
||||||
# 1. Alte Ergebnisse löschen
|
# 1. Alte Ergebnisse löschen
|
||||||
while self.results_layout.count():
|
while self.results_layout.count():
|
||||||
@@ -481,7 +496,6 @@ class UffWindow(QMainWindow):
|
|||||||
item = SearchResultItem(fname, fpath, snippet)
|
item = SearchResultItem(fname, fpath, snippet)
|
||||||
self.results_layout.addWidget(item)
|
self.results_layout.addWidget(item)
|
||||||
|
|
||||||
# Stretch am Ende, damit alles oben bleibt
|
|
||||||
self.results_layout.addStretch()
|
self.results_layout.addStretch()
|
||||||
|
|
||||||
# --- Folder Management ---
|
# --- Folder Management ---
|
||||||
|
|||||||
Reference in New Issue
Block a user