made installer and fixed releated bug fixes

This commit is contained in:
2026-01-10 14:46:36 +01:00
parent 8739455231
commit f1413a2eca
8 changed files with 107 additions and 28 deletions

2
.gitignore vendored
View File

@@ -4,4 +4,4 @@
/build
__pycache__/
*.iss
*.spec
UFF-Search.spec

View File

@@ -2,10 +2,6 @@
# UFF Search - Unsorted Folder Full-Text Search
![GitHub stars](https://img.shields.io/github/stars/BildoBeucklin/unsorted-folder-full-text-search?style=social)
![GitHub forks](https://img.shields.io/github/forks/BildoBeucklin/unsorted-folder-full-text-search?style=social)
![GitHub license](https://img.shields.io/github/license/BildoBeucklin/unsorted-folder-full-text-search)
UFF Search is a powerful desktop application for Windows that allows you to perform fast, intelligent, and fuzzy full-text searches on your local files, including searching inside ZIP archives.
It builds a local search index for the folders you specify, allowing you to quickly find documents based on their meaning (semantic search) and specific keywords, even with typos in your search query.
@@ -68,12 +64,18 @@ To create a standalone executable from the source code, you can use `pyinstaller
2. **Build the executable:**
```bash
pyinstaller --name "UFF_Search" --windowed --onefile --icon="favicon.ico" --add-data "assets;assets" main.py
pyinstaller --noconfirm --onedir --windowed --add-data "assets;assets" --icon "assets/favicon.ico" main.py
```
This command will create a single executable file in the `dist` folder.
Or:
```bash
pyinstaller main.spec
```
Both of these commands will create a single executable file in the `dist` folder. It may take some time to build.
## Usage
(texts are only in german)
1. Start the application.
2. Click **" + Hinzufügen"** (Add) to select a folder you want to index. The application will start scanning it immediately.
3. Once indexing is complete, type your search query into the search bar and press Enter or click **"Suchen"** (Search).
@@ -94,6 +96,7 @@ This command will create a single executable file in the `dist` folder.
* `openpyxl` for `.xlsx` files.
* `python-pptx` for `.pptx` files.
* **Index Location:** The search index database (`uff_index.db`) is stored in `%LOCALAPPDATA%\UFF_Search` on Windows.
* **Size:** (ca. 400-600 MB)
## License

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View File

@@ -15,22 +15,32 @@ if not os.path.exists(APP_DATA_DIR):
DB_NAME = os.path.join(APP_DATA_DIR, "uff_index.db")
LOG_FILE = os.path.join(APP_DATA_DIR, "uff.log")
def resource_path(relative_path):
"""
Holt den absoluten Pfad zu Ressourcen.
Funktioniert für Dev-Modus UND für PyInstaller EXE (_MEIPASS).
"""
try:
# PyInstaller erstellt temporären Ordner _MEIPASS
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
# --- LOGGING KLASSE ---
class Logger(object):
def __init__(self):
# "w" überschreibt bei jedem Start. Nutze "a" für anhängen (append).
self.terminal = sys.stdout # Optional: Falls du es AUCH im Terminal sehen willst
self.terminal = sys.stdout
self.log = open(LOG_FILE, "w", encoding="utf-8")
def write(self, message):
# Optional: ins Terminal schreiben (auskommentieren, wenn du nur Logfile willst)
# self.terminal.write(message)
self.log.write(message)
self.log.flush()
def flush(self):
# self.terminal.flush()
self.log.flush()
# --- AKTIVIERUNG DES LOGGERS ---

17
main.py
View File

@@ -7,7 +7,7 @@ from PyQt6.QtGui import QPixmap, QFont, QIcon
from PyQt6.QtCore import qInstallMessageHandler, QTimer, Qt
# Config zuerst!
from config import qt_message_handler, LOG_FILE
from config import qt_message_handler, LOG_FILE, resource_path
from ui import UffWindow, ModernSplashScreen, ModelLoaderThread
@@ -19,15 +19,14 @@ if __name__ == "__main__":
app = QApplication(sys.argv)
app.setFont(QFont("Segoe UI", 10))
# 1. ICON SETZEN (Für die ganze App)
# Wenn assets/icon.png existiert, wird es genutzt.
if os.path.exists("assets/icon.png"):
app_icon = QIcon("assets/icon.png")
icon_path = resource_path("assets/uff_icon.jpeg") # <--- HIER
if os.path.exists(icon_path):
app_icon = QIcon(icon_path)
app.setWindowIcon(app_icon)
# 2. SPLASH SCREEN ERSTELLEN
splash_pix = QPixmap("assets/uff_banner.jpeg")
# Falls kein Bild da ist, nehmen wir ein leeres (damit es nicht crasht)
# SPLASH LADEN (Mit resource_path)
banner_path = resource_path("assets/uff_banner.jpeg")
splash_pix = QPixmap(banner_path)
if splash_pix.isNull():
splash_pix = QPixmap(600, 400)
splash_pix.fill(Qt.GlobalColor.white)
@@ -35,8 +34,6 @@ if __name__ == "__main__":
splash = ModernSplashScreen(splash_pix)
splash.show()
# 3. LADEN SIMULIEREN & STARTEN
# Wir nutzen einen kleinen Trick, um den Start visuell zu "begleiten"
splash.set_progress(10, "Lade Konfiguration...")
app.processEvents()

72
main.spec Normal file
View File

@@ -0,0 +1,72 @@
# -*- mode: python ; coding: utf-8 -*-
from PyInstaller.utils.hooks import collect_all
# --- 1. SPEZIELLE BIBLIOTHEKEN SAMMELN ---
# sentence_transformers und rapidfuzz sind komplex, wir holen alles automatisch
datas = [('assets', 'assets')]
binaries = []
hiddenimports = [
'docx',
'openpyxl',
'pptx',
'pdfplumber',
'rapidfuzz',
'sentence_transformers',
'numpy'
]
# Sammle alle Daten für die KI-Bibliothek (verhindert Import-Fehler)
tmp_ret = collect_all('sentence_transformers')
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
# Sammle rapidfuzz sicherheitshalber auch komplett
tmp_ret = collect_all('rapidfuzz')
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
# --- 2. ANALYSE ---
a = Analysis(
['main.py'],
pathex=[],
binaries=binaries,
datas=datas,
hiddenimports=hiddenimports,
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure)
# --- 3. EXE ERSTELLEN ---
exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name='UFF_Search', # Name der Datei (UFF_Search.exe)
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon='assets\\favicon.ico', # Pfad zum Icon
)
# --- 4. ORDNER ZUSAMMENSTELLEN ---
coll = COLLECT(
exe,
a.binaries,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='UFF_Search', # Name des Ordners
)

7
ui.py
View File

@@ -1,6 +1,6 @@
# ui.py
import os
from PyQt6.QtWidgets import (QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
QLineEdit, QPushButton, QLabel, QFileDialog,
QProgressBar, QMessageBox, QListWidget, QListWidgetItem,
QSplitter, QFrame, QScrollArea, QStyle, QGraphicsDropShadowEffect,
@@ -133,10 +133,7 @@ class UffWindow(QMainWindow):
self.db = DatabaseHandler()
self.initUI()
# NEU: Icon setzen
if os.path.exists("assets/uff_icon.jpeg"):
self.setWindowIcon(QIcon("assets/uff_icon.jpeg"))
self.load_saved_folders()
def initUI(self):