Dieser Commit ist enthalten in:
Claude Project Manager
2025-08-01 23:50:28 +02:00
Commit 04585e95b6
290 geänderte Dateien mit 64086 neuen und 0 gelöschten Zeilen

Datei anzeigen

@ -0,0 +1,203 @@
# Path: views/widgets/language_dropdown.py
"""
Benutzerdefiniertes Dropdown-Widget für die Sprachauswahl mit Flaggen-Icons.
"""
import os
from PyQt5.QtWidgets import (QWidget, QComboBox, QLabel, QHBoxLayout,
QVBoxLayout, QFrame, QListWidget, QListWidgetItem,
QAbstractItemView, QApplication)
from PyQt5.QtCore import Qt, QSize, QEvent, pyqtSignal
from PyQt5.QtGui import QIcon, QPainter, QPen, QColor, QCursor
class LanguageDropdown(QWidget):
"""Benutzerdefiniertes Dropdown für die Sprachauswahl mit Flaggen."""
def __init__(self, language_manager):
super().__init__()
self.language_manager = language_manager
self.is_open = False
self.languages = {}
self.current_language = self.language_manager.get_current_language()
# QApplication-Instanz merken, um einen Event-Filter installieren zu können
self.app = QApplication.instance()
# Verfügbare Sprachen aus dem Manager holen
self.available_languages = self.language_manager.get_available_languages()
self.init_ui()
# Verbinde Signal des Language Managers
self.language_manager.language_changed.connect(self.on_language_changed)
def init_ui(self):
"""Initialisiert die Benutzeroberfläche."""
layout = QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
# Container für die aktuelle Sprachauswahl
self.current_language_container = QFrame()
self.current_language_container.setObjectName("languageSelector")
self.current_language_container.setCursor(Qt.PointingHandCursor)
self.current_language_container.setStyleSheet("""
QFrame#languageSelector {
background-color: transparent;
border-radius: 4px;
}
QFrame#languageSelector:hover {
background-color: rgba(200, 200, 200, 30);
}
""")
current_layout = QHBoxLayout(self.current_language_container)
current_layout.setContentsMargins(5, 5, 5, 5)
# Icon der aktuellen Sprache
self.current_flag = QLabel()
self.current_flag.setFixedSize(24, 16) # Correct flag aspect ratio
# Pfad zum Icon
icon_path = self.get_language_icon_path(self.current_language)
if icon_path:
self.current_flag.setPixmap(QIcon(icon_path).pixmap(QSize(24, 16)))
current_layout.addWidget(self.current_flag)
# Kleiner Pfeil nach unten
arrow_label = QLabel("")
arrow_label.setStyleSheet("font-size: 8px; color: #888888;")
current_layout.addWidget(arrow_label)
layout.addWidget(self.current_language_container)
# Dropdown-Liste (anfangs versteckt)
self.dropdown_list = QListWidget()
self.dropdown_list.setWindowFlags(Qt.Popup | Qt.FramelessWindowHint)
self.dropdown_list.setFocusPolicy(Qt.NoFocus)
self.dropdown_list.setMouseTracking(True)
self.dropdown_list.setFrameShape(QFrame.NoFrame)
self.dropdown_list.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.dropdown_list.setEditTriggers(QAbstractItemView.NoEditTriggers)
self.dropdown_list.setSelectionMode(QAbstractItemView.NoSelection)
self.dropdown_list.setStyleSheet("""
QListWidget {
background-color: white;
border: 1px solid #CCCCCC;
border-radius: 5px;
padding: 5px;
}
QListWidget::item {
padding: 4px;
border-radius: 3px;
}
QListWidget::item:hover {
background-color: #F0F0F0;
}
""")
# Sprachen zum Dropdown hinzufügen
self.populate_dropdown()
# Event-Verbindungen
self.current_language_container.mousePressEvent = self.toggle_dropdown
self.dropdown_list.itemClicked.connect(self.on_language_selected)
# Zugänglichkeit mit Tastaturfokus
self.setFocusPolicy(Qt.StrongFocus)
self.current_language_container.setFocusPolicy(Qt.StrongFocus)
def get_language_icon_path(self, language_code):
"""Gibt den Pfad zum Icon für den angegebenen Sprachcode zurück."""
# Projektbasis-Verzeichnis ermitteln
base_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
icon_path = os.path.join(base_dir, "resources", "icons", f"{language_code}.svg")
if os.path.exists(icon_path):
return icon_path
return None
def populate_dropdown(self):
"""Füllt das Dropdown mit den verfügbaren Sprachen."""
self.dropdown_list.clear()
self.languages = {}
for code, name in self.available_languages.items():
item = QListWidgetItem(name)
# Icon erstellen
icon_path = self.get_language_icon_path(code)
if icon_path:
item.setIcon(QIcon(icon_path))
# Sprach-Code speichern
item.setData(Qt.UserRole, code)
# Zum Dropdown hinzufügen
self.dropdown_list.addItem(item)
self.languages[code] = item
def toggle_dropdown(self, event):
"""Öffnet oder schließt das Dropdown-Menü."""
if not self.is_open:
# Position des Dropdowns unter dem Button berechnen
pos = self.current_language_container.mapToGlobal(self.current_language_container.rect().bottomLeft())
self.dropdown_list.setGeometry(pos.x(), pos.y(), 120, 120) # Größe anpassen
self.dropdown_list.show()
self.is_open = True
if self.app:
self.app.installEventFilter(self)
else:
self.dropdown_list.hide()
self.is_open = False
if self.app:
self.app.removeEventFilter(self)
def on_language_selected(self, item):
"""Wird aufgerufen, wenn eine Sprache im Dropdown ausgewählt wird."""
language_code = item.data(Qt.UserRole)
# Sprache wechseln
if language_code != self.current_language:
self.language_manager.change_language(language_code)
# Dropdown schließen
self.dropdown_list.hide()
self.is_open = False
if self.app:
self.app.removeEventFilter(self)
def on_language_changed(self, language_code):
"""Wird aufgerufen, wenn sich die Sprache im LanguageManager ändert."""
self.current_language = language_code
# Icon aktualisieren
icon_path = self.get_language_icon_path(language_code)
if icon_path:
self.current_flag.setPixmap(QIcon(icon_path).pixmap(QSize(24, 16)))
# Texte aktualisieren (falls vorhanden)
if hasattr(self.parent(), "update_texts"):
self.parent().update_texts()
def keyPressEvent(self, event):
"""Behandelt Tastatureingaben für verbesserte Zugänglichkeit."""
if event.key() == Qt.Key_Space or event.key() == Qt.Key_Return:
self.toggle_dropdown(None)
else:
super().keyPressEvent(event)
def eventFilter(self, obj, event):
"""Schließt das Dropdown, wenn außerhalb geklickt wird."""
if self.is_open and event.type() == QEvent.MouseButtonPress:
# Klickposition relativ zum Dropdown ermitteln
if not self.dropdown_list.geometry().contains(event.globalPos()) and \
not self.current_language_container.geometry().contains(
self.mapFromGlobal(event.globalPos())):
self.dropdown_list.hide()
self.is_open = False
if self.app:
self.app.removeEventFilter(self)
return super().eventFilter(obj, event)