Dieser Commit ist enthalten in:
Claude Project Manager
2025-07-03 21:11:05 +02:00
Commit 08ed938105
239 geänderte Dateien mit 21554 neuen und 0 gelöschten Zeilen

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

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: 15px;
}
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, 24)
# 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, 24)))
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, 24)))
# 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)

Datei anzeigen

@ -0,0 +1,76 @@
# Path: views/widgets/platform_button.py
"""
Benutzerdefinierter Button für die Plattformauswahl.
"""
import os
from PyQt5.QtWidgets import QPushButton, QVBoxLayout, QLabel, QWidget
from PyQt5.QtCore import QSize, Qt, pyqtSignal
from PyQt5.QtGui import QIcon, QFont
class PlatformButton(QWidget):
"""Angepasster Button-Widget für Plattformauswahl mit Icon."""
# Signal wenn geklickt
clicked = pyqtSignal()
def __init__(self, platform_name, icon_path=None, enabled=True):
super().__init__()
self.platform = platform_name.lower()
self.setMinimumSize(200, 200)
self.setEnabled(enabled)
# Layout für den Container
layout = QVBoxLayout(self)
layout.setAlignment(Qt.AlignCenter)
layout.setContentsMargins(10, 10, 10, 10)
# Icon-Button
self.icon_button = QPushButton()
self.icon_button.setFlat(True)
self.icon_button.setCursor(Qt.PointingHandCursor)
# Icon setzen, falls vorhanden
if icon_path and os.path.exists(icon_path):
self.icon_button.setIcon(QIcon(icon_path))
self.icon_button.setIconSize(QSize(120, 120)) # Größeres Icon
self.icon_button.setMinimumSize(150, 150)
self.icon_button.setStyleSheet("""
QPushButton {
background-color: transparent;
border: none;
}
QPushButton:hover {
background-color: rgba(200, 200, 200, 50);
border-radius: 10px;
}
QPushButton:pressed {
background-color: rgba(150, 150, 150, 80);
}
QPushButton:disabled {
opacity: 0.5;
}
""")
# Button-Signal verbinden
self.icon_button.clicked.connect(self.clicked)
# Name-Label
self.name_label = QLabel(platform_name)
self.name_label.setAlignment(Qt.AlignCenter)
name_font = QFont()
name_font.setPointSize(12)
name_font.setBold(True)
self.name_label.setFont(name_font)
self.name_label.setStyleSheet("color: black;") # Schwarzer Text
# Widgets zum Layout hinzufügen
layout.addWidget(self.icon_button, 0, Qt.AlignCenter)
layout.addWidget(self.name_label, 0, Qt.AlignCenter)
# Styling für den deaktivierten Zustand
if not enabled:
self.setStyleSheet("opacity: 0.5;")