more beauty
This commit is contained in:
72
main.py
72
main.py
@@ -1,14 +1,15 @@
|
||||
# main.py
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
from PyQt6.QtWidgets import QApplication
|
||||
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 PyQt6.QtWidgets import QApplication, QSplashScreen
|
||||
from PyQt6.QtGui import QPixmap, QFont
|
||||
from PyQt6.QtCore import qInstallMessageHandler
|
||||
|
||||
from ui import UffWindow
|
||||
from ui import UffWindow, ModernSplashScreen, ModelLoaderThread
|
||||
|
||||
qInstallMessageHandler(qt_message_handler)
|
||||
os.environ["QT_LOGGING_RULES"] = "qt.text.font.db=false;qt.qpa.fonts=false"
|
||||
@@ -18,18 +19,61 @@ if __name__ == "__main__":
|
||||
app = QApplication(sys.argv)
|
||||
app.setFont(QFont("Segoe UI", 10))
|
||||
|
||||
splash = None
|
||||
if os.path.exists("assets/uff_banner.jpeg"):
|
||||
try:
|
||||
splash = QSplashScreen(QPixmap("assets/uff_banner.jpeg"))
|
||||
splash.show()
|
||||
except: pass
|
||||
# 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")
|
||||
app.setWindowIcon(app_icon)
|
||||
|
||||
window = UffWindow(splash)
|
||||
window.show()
|
||||
window.start_model_loading()
|
||||
# 2. SPLASH SCREEN ERSTELLEN
|
||||
splash_pix = QPixmap("assets/uff_banner.jpeg")
|
||||
# Falls kein Bild da ist, nehmen wir ein leeres (damit es nicht crasht)
|
||||
if splash_pix.isNull():
|
||||
splash_pix = QPixmap(600, 400)
|
||||
splash_pix.fill(Qt.GlobalColor.white)
|
||||
|
||||
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()
|
||||
time.sleep(0.3) # Nur für den Effekt
|
||||
|
||||
splash.set_progress(30, "Verbinde Datenbank...")
|
||||
app.processEvents()
|
||||
|
||||
# Hauptfenster erstellen (aber noch versteckt lassen)
|
||||
window = UffWindow()
|
||||
|
||||
splash.set_progress(50, "Lade Benutzeroberfläche...")
|
||||
app.processEvents()
|
||||
time.sleep(0.2)
|
||||
|
||||
# 4. DAS SCHWERE KI-MODELL LADEN
|
||||
splash.set_progress(60, "Lade KI-Modell (das dauert kurz)...")
|
||||
app.processEvents()
|
||||
|
||||
# Wir starten den Thread, aber wir müssen warten bis er fertig ist,
|
||||
# bevor wir den Splash schließen.
|
||||
loader = ModelLoaderThread()
|
||||
|
||||
def on_loaded(model):
|
||||
splash.set_progress(100, "Fertig!")
|
||||
app.processEvents()
|
||||
time.sleep(0.5) # Kurz warten bei 100%
|
||||
|
||||
window.on_model_loaded(model) # Modell an Fenster übergeben
|
||||
window.show() # Fenster zeigen
|
||||
splash.finish(window) # Splash schließen
|
||||
|
||||
loader.model_loaded.connect(on_loaded)
|
||||
loader.start()
|
||||
|
||||
sys.exit(app.exec())
|
||||
|
||||
except Exception as e:
|
||||
import traceback
|
||||
print("CRITICAL MAIN CRASH:")
|
||||
|
||||
89
ui.py
89
ui.py
@@ -1,26 +1,76 @@
|
||||
# ui.py
|
||||
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
||||
import os
|
||||
from PyQt6.QtWidgets import (QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
||||
QLineEdit, QPushButton, QLabel, QFileDialog,
|
||||
QProgressBar, QMessageBox, QListWidget, QListWidgetItem,
|
||||
QSplitter, QFrame, QScrollArea, QStyle, QGraphicsDropShadowEffect)
|
||||
from PyQt6.QtCore import Qt, QUrl, QThread, pyqtSignal
|
||||
from PyQt6.QtGui import QDesktopServices, QColor, QFont
|
||||
QSplitter, QFrame, QScrollArea, QStyle, QGraphicsDropShadowEffect,
|
||||
QSplashScreen) # QSplashScreen hier wichtig
|
||||
from PyQt6.QtCore import Qt, QUrl, QThread, pyqtSignal, QRect
|
||||
from PyQt6.QtGui import QDesktopServices, QColor, QFont, QPainter, QIcon, QPixmap # Painter & Icon neu
|
||||
from sentence_transformers import SentenceTransformer
|
||||
|
||||
from database import DatabaseHandler
|
||||
from indexer import IndexerThread
|
||||
from config import STYLESHEET
|
||||
|
||||
# Thread zum Laden des Modells (UI-Helper)
|
||||
# --- NEU: Ein moderner Splash Screen mit Ladebalken ---
|
||||
class ModernSplashScreen(QSplashScreen):
|
||||
def __init__(self, pixmap):
|
||||
super().__init__(pixmap)
|
||||
self.progress = 0
|
||||
self.message = "Initialisiere..."
|
||||
# Schriftart für den Ladetext
|
||||
self.font = QFont("Segoe UI", 10, QFont.Weight.Bold)
|
||||
|
||||
def set_progress(self, value, text):
|
||||
self.progress = value
|
||||
self.message = text
|
||||
self.repaint() # Erzwingt neuzeichnen
|
||||
|
||||
def drawContents(self, painter):
|
||||
# 1. Das normale Bild zeichnen
|
||||
super().drawContents(painter)
|
||||
|
||||
# 2. Ladebalken-Hintergrund (unten)
|
||||
# Wir malen direkt auf das Bild
|
||||
bg_rect = self.rect()
|
||||
bar_height = 20
|
||||
# Position: Ganz unten am Bild
|
||||
bar_rect = QRect(0, bg_rect.height() - bar_height, bg_rect.width(), bar_height)
|
||||
|
||||
# Hintergrund des Balkens (dunkelgrau)
|
||||
painter.setPen(Qt.PenStyle.NoPen)
|
||||
painter.setBrush(QColor(50, 50, 50))
|
||||
painter.drawRect(bar_rect)
|
||||
|
||||
# 3. Der Fortschritt (türkis/blau)
|
||||
# Breite basierend auf % berechnen
|
||||
progress_width = int(bg_rect.width() * (self.progress / 100))
|
||||
prog_rect = QRect(0, bg_rect.height() - bar_height, progress_width, bar_height)
|
||||
|
||||
painter.setBrush(QColor("#3498db")) # UFF-Blau
|
||||
painter.drawRect(prog_rect)
|
||||
|
||||
# 4. Text zeichnen (zentriert über dem Balken oder darin)
|
||||
painter.setPen(QColor("white"))
|
||||
painter.setFont(self.font)
|
||||
# Text etwas oberhalb des Balkens zeichnen
|
||||
text_rect = QRect(0, bg_rect.height() - bar_height - 30, bg_rect.width(), 25)
|
||||
painter.drawText(text_rect, Qt.AlignmentFlag.AlignCenter, self.message)
|
||||
|
||||
# --- Thread zum Laden des Modells ---
|
||||
class ModelLoaderThread(QThread):
|
||||
model_loaded = pyqtSignal(object)
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
# Das ist der schwere Teil, der dauert
|
||||
model = SentenceTransformer('all-MiniLM-L6-v2')
|
||||
self.model_loaded.emit(model)
|
||||
except: self.model_loaded.emit(None)
|
||||
except:
|
||||
self.model_loaded.emit(None)
|
||||
|
||||
# Widget für einzelne Ergebnisse
|
||||
# --- SearchResultItem (Unverändert, aber der Vollständigkeit halber hier) ---
|
||||
class SearchResultItem(QFrame):
|
||||
def __init__(self, filename, filepath, snippet, parent=None):
|
||||
super().__init__(parent)
|
||||
@@ -76,16 +126,21 @@ class SearchResultItem(QFrame):
|
||||
target = self.filepath.split(" :: ")[0] if " :: " in self.filepath else self.filepath
|
||||
QDesktopServices.openUrl(QUrl.fromLocalFile(target))
|
||||
|
||||
# --- Das Hauptfenster ---
|
||||
class UffWindow(QMainWindow):
|
||||
def __init__(self, splash=None):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.splash = splash
|
||||
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):
|
||||
self.setWindowTitle("UFF Search")
|
||||
self.setWindowTitle("UFF Search v1.0")
|
||||
self.resize(1100, 750)
|
||||
self.setStyleSheet(STYLESHEET)
|
||||
|
||||
@@ -158,7 +213,7 @@ class UffWindow(QMainWindow):
|
||||
search_box.addWidget(self.btn_go)
|
||||
|
||||
status_box = QHBoxLayout()
|
||||
self.lbl_status = QLabel("Modell wird geladen...")
|
||||
self.lbl_status = QLabel("Bereit.")
|
||||
self.lbl_status.setObjectName("StatusLabel")
|
||||
self.prog = QProgressBar()
|
||||
self.prog.hide()
|
||||
@@ -187,14 +242,8 @@ class UffWindow(QMainWindow):
|
||||
self.btn_go.setEnabled(enabled)
|
||||
self.folder_list.setEnabled(enabled)
|
||||
|
||||
def start_model_loading(self):
|
||||
if self.splash: self.splash.showMessage("Lade KI-Modell...", Qt.AlignmentFlag.AlignBottom, Qt.GlobalColor.white)
|
||||
self.loader = ModelLoaderThread()
|
||||
self.loader.model_loaded.connect(self.on_model_loaded)
|
||||
self.loader.start()
|
||||
|
||||
# Methoden für Model Loading (wird jetzt von main gesteuert)
|
||||
def on_model_loaded(self, model):
|
||||
if self.splash: self.splash.finish(self)
|
||||
if not model:
|
||||
QMessageBox.critical(self, "Fehler", "Modell konnte nicht geladen werden.")
|
||||
return
|
||||
@@ -202,6 +251,10 @@ class UffWindow(QMainWindow):
|
||||
self.lbl_status.setText("Bereit für deine Suche.")
|
||||
self.set_ui_enabled(True)
|
||||
|
||||
# ... RESTLICHE METHODEN (search, add_folder etc.) bleiben gleich wie vorher ...
|
||||
# (Kopiere hier einfach die Methoden aus deiner alten ui.py rein,
|
||||
# search, load_saved_folders, add_new_folder, delete_selected_folder, rescan, start_idx, cancel_idx, idx_done)
|
||||
|
||||
def search(self):
|
||||
query = self.input.text()
|
||||
if not query: return
|
||||
|
||||
Reference in New Issue
Block a user