204 Zeilen
7.7 KiB
Python
204 Zeilen
7.7 KiB
Python
# 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)
|