369 Zeilen
12 KiB
Python
369 Zeilen
12 KiB
Python
"""
|
|
Accounts Overview View - Account-Übersicht im Mockup-Style
|
|
"""
|
|
|
|
import logging
|
|
from PyQt5.QtWidgets import (
|
|
QWidget, QHBoxLayout, QVBoxLayout, QLabel, QPushButton,
|
|
QScrollArea, QGridLayout, QFrame, QMessageBox
|
|
)
|
|
from PyQt5.QtCore import Qt, pyqtSignal
|
|
from PyQt5.QtGui import QFont
|
|
|
|
from views.widgets.account_card import AccountCard
|
|
|
|
logger = logging.getLogger("accounts_overview")
|
|
|
|
|
|
class SidebarFilter(QWidget):
|
|
"""Sidebar mit Plattform-Filter nach Styleguide"""
|
|
filter_changed = pyqtSignal(str)
|
|
|
|
def __init__(self, language_manager=None):
|
|
super().__init__()
|
|
self.language_manager = language_manager
|
|
self.filter_buttons = []
|
|
self.account_counts = {}
|
|
self.init_ui()
|
|
|
|
if self.language_manager:
|
|
self.language_manager.language_changed.connect(self.update_texts)
|
|
self.update_texts()
|
|
|
|
def init_ui(self):
|
|
"""Initialisiert die UI nach Styleguide"""
|
|
self.setMaximumWidth(260) # Styleguide: Sidebar-Breite
|
|
self.setObjectName("filter_sidebar") # For QSS targeting
|
|
|
|
layout = QVBoxLayout(self)
|
|
layout.setContentsMargins(20, 20, 20, 20)
|
|
layout.setSpacing(8)
|
|
|
|
# Title removed - no longer needed
|
|
|
|
# Filter Buttons
|
|
self.filters = [
|
|
("Alle", "all"),
|
|
("Instagram", "instagram"),
|
|
("TikTok", "tiktok"),
|
|
("Facebook", "facebook"),
|
|
("X (Twitter)", "x"),
|
|
("VK", "vk"),
|
|
("OK.ru", "ok"),
|
|
("Gmail", "gmail")
|
|
]
|
|
|
|
for name, key in self.filters:
|
|
btn = self._create_filter_button(name, key)
|
|
self.filter_buttons.append((btn, key))
|
|
layout.addWidget(btn)
|
|
|
|
layout.addStretch()
|
|
|
|
def _create_filter_button(self, name, key):
|
|
"""Erstellt einen Filter-Button"""
|
|
btn = QPushButton(f"{name} (0)")
|
|
btn.setObjectName(key)
|
|
btn.setCursor(Qt.PointingHandCursor)
|
|
btn.setObjectName("filter_button") # For QSS targeting
|
|
btn.clicked.connect(lambda: self._on_filter_clicked(key))
|
|
|
|
# Erste Option als aktiv setzen
|
|
if key == "all":
|
|
btn.setProperty("selected", "true")
|
|
btn.setStyle(btn.style())
|
|
|
|
return btn
|
|
|
|
def _on_filter_clicked(self, key):
|
|
"""Behandelt Filter-Klicks"""
|
|
# Update button states
|
|
for btn, btn_key in self.filter_buttons:
|
|
btn.setProperty("selected", "true" if btn_key == key else "false")
|
|
btn.setStyle(btn.style())
|
|
|
|
self.filter_changed.emit(key)
|
|
|
|
def update_counts(self, counts):
|
|
"""Aktualisiert die Account-Anzahlen"""
|
|
self.account_counts = counts
|
|
|
|
for btn, key in self.filter_buttons:
|
|
count = counts.get(key, 0)
|
|
name = next(name for name, k in self.filters if k == key)
|
|
btn.setText(f"{name} ({count})")
|
|
|
|
def update_texts(self):
|
|
"""Aktualisiert die Texte gemäß der aktuellen Sprache"""
|
|
if not self.language_manager:
|
|
return
|
|
|
|
# Title removed - no text update needed
|
|
|
|
|
|
class AccountsOverviewView(QWidget):
|
|
"""
|
|
Account-Übersicht im Mockup-Style mit:
|
|
- Sidebar-Filter
|
|
- Grid-Layout mit Account-Karten
|
|
"""
|
|
|
|
# Signals
|
|
account_login_requested = pyqtSignal(dict)
|
|
account_export_requested = pyqtSignal(dict)
|
|
account_delete_requested = pyqtSignal(dict)
|
|
export_requested = pyqtSignal() # Für Kompatibilität
|
|
|
|
def __init__(self, db_manager=None, language_manager=None):
|
|
super().__init__()
|
|
self.db_manager = db_manager
|
|
self.language_manager = language_manager
|
|
self.current_filter = "all"
|
|
self.accounts = []
|
|
self.init_ui()
|
|
|
|
if self.language_manager:
|
|
self.language_manager.language_changed.connect(self.update_texts)
|
|
self.update_texts()
|
|
|
|
def init_ui(self):
|
|
"""Initialisiert die UI nach Styleguide"""
|
|
self.setObjectName("accounts_overview") # For QSS targeting
|
|
|
|
# Hauptlayout
|
|
main_layout = QHBoxLayout(self)
|
|
main_layout.setContentsMargins(0, 0, 0, 0)
|
|
main_layout.setSpacing(0)
|
|
|
|
# Sidebar
|
|
self.sidebar = SidebarFilter(self.language_manager)
|
|
self.sidebar.filter_changed.connect(self._on_filter_changed)
|
|
main_layout.addWidget(self.sidebar)
|
|
|
|
# Content Area
|
|
content_widget = QWidget()
|
|
content_widget.setObjectName("accounts_content") # For QSS targeting
|
|
content_layout = QVBoxLayout(content_widget)
|
|
content_layout.setContentsMargins(40, 30, 40, 30)
|
|
content_layout.setSpacing(20)
|
|
|
|
# Header
|
|
header_layout = QHBoxLayout()
|
|
|
|
self.title = QLabel("Alle Accounts")
|
|
title_font = QFont("Poppins", 24)
|
|
title_font.setBold(True)
|
|
self.title.setFont(title_font)
|
|
self.title.setObjectName("section_title") # For QSS targeting
|
|
header_layout.addWidget(self.title)
|
|
|
|
header_layout.addStretch()
|
|
|
|
content_layout.addLayout(header_layout)
|
|
|
|
# Scroll Area für Accounts
|
|
self.scroll = QScrollArea()
|
|
self.scroll.setWidgetResizable(True)
|
|
# No inline styles - handled by QSS
|
|
|
|
# Grid Container
|
|
self.container = QWidget()
|
|
self.container.setObjectName("grid_container") # For QSS targeting
|
|
self.grid_layout = QGridLayout(self.container)
|
|
self.grid_layout.setSpacing(24) # Styleguide Grid-Gap
|
|
self.grid_layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
self.scroll.setWidget(self.container)
|
|
content_layout.addWidget(self.scroll)
|
|
|
|
main_layout.addWidget(content_widget)
|
|
|
|
# Initial load
|
|
self.load_accounts()
|
|
|
|
def load_accounts(self):
|
|
"""Lädt Accounts aus der Datenbank"""
|
|
if not self.db_manager:
|
|
return
|
|
|
|
try:
|
|
# Hole alle Accounts aus der Datenbank
|
|
self.accounts = self.db_manager.get_all_accounts()
|
|
self._update_display()
|
|
self._update_sidebar_counts()
|
|
except Exception as e:
|
|
logger.error(f"Fehler beim Laden der Accounts: {e}")
|
|
self.accounts = []
|
|
QMessageBox.warning(
|
|
self,
|
|
"Fehler",
|
|
f"Fehler beim Laden der Accounts:\n{str(e)}"
|
|
)
|
|
|
|
def _update_display(self):
|
|
"""Aktualisiert die Anzeige basierend auf dem aktuellen Filter"""
|
|
# Clear existing widgets
|
|
while self.grid_layout.count():
|
|
child = self.grid_layout.takeAt(0)
|
|
if child.widget():
|
|
child.widget().deleteLater()
|
|
|
|
# Filter accounts
|
|
if self.current_filter == "all":
|
|
filtered_accounts = self.accounts
|
|
else:
|
|
filtered_accounts = [
|
|
acc for acc in self.accounts
|
|
if acc.get("platform", "").lower() == self.current_filter
|
|
]
|
|
|
|
# Gruppiere nach Plattform wenn "Alle" ausgewählt
|
|
if self.current_filter == "all":
|
|
self._display_grouped_accounts(filtered_accounts)
|
|
else:
|
|
self._display_accounts_grid(filtered_accounts)
|
|
|
|
def _display_grouped_accounts(self, accounts):
|
|
"""Zeigt Accounts gruppiert nach Plattform"""
|
|
# Gruppiere Accounts nach Plattform
|
|
platforms = {}
|
|
for acc in accounts:
|
|
platform = acc.get("platform", "unknown").lower()
|
|
if platform not in platforms:
|
|
platforms[platform] = []
|
|
platforms[platform].append(acc)
|
|
|
|
row = 0
|
|
for platform, platform_accounts in sorted(platforms.items()):
|
|
if not platform_accounts:
|
|
continue
|
|
|
|
# Platform Header
|
|
header = QLabel(platform.capitalize())
|
|
header_font = QFont("Poppins", 18)
|
|
header_font.setWeight(QFont.DemiBold)
|
|
header.setFont(header_font)
|
|
header.setObjectName("platform_header") # For QSS targeting
|
|
self.grid_layout.addWidget(header, row, 0, 1, 3)
|
|
row += 1
|
|
|
|
# Accounts
|
|
col = 0
|
|
for acc in platform_accounts:
|
|
card = self._create_account_card(acc)
|
|
self.grid_layout.addWidget(card, row, col)
|
|
col += 1
|
|
if col > 2: # 3 columns
|
|
col = 0
|
|
row += 1
|
|
|
|
if col > 0:
|
|
row += 1
|
|
row += 1 # Extra space between platforms
|
|
|
|
# Add stretch
|
|
self.grid_layout.setRowStretch(row, 1)
|
|
|
|
def _display_accounts_grid(self, accounts):
|
|
"""Zeigt Accounts in einem einfachen Grid"""
|
|
row = 0
|
|
col = 0
|
|
|
|
for acc in accounts:
|
|
card = self._create_account_card(acc)
|
|
self.grid_layout.addWidget(card, row, col)
|
|
col += 1
|
|
if col > 2: # 3 columns
|
|
col = 0
|
|
row += 1
|
|
|
|
# Add stretch
|
|
self.grid_layout.setRowStretch(row + 1, 1)
|
|
|
|
def _create_account_card(self, account_data):
|
|
"""Erstellt eine Account-Karte"""
|
|
card = AccountCard(account_data, self.language_manager)
|
|
|
|
# Verbinde Signals
|
|
card.login_requested.connect(self.account_login_requested.emit)
|
|
card.export_requested.connect(self.account_export_requested.emit)
|
|
card.delete_requested.connect(self._on_delete_requested)
|
|
|
|
return card
|
|
|
|
def _on_delete_requested(self, account_data):
|
|
"""Behandelt Delete-Anfragen mit Bestätigung"""
|
|
msg_box = QMessageBox(self)
|
|
msg_box.setWindowTitle("Account löschen")
|
|
msg_box.setText(f"Möchten Sie den Account '{account_data.get('username', '')}' wirklich löschen?")
|
|
msg_box.setIcon(QMessageBox.Question)
|
|
|
|
# Custom Buttons hinzufügen
|
|
delete_button = msg_box.addButton("Löschen", QMessageBox.YesRole)
|
|
cancel_button = msg_box.addButton("Abbrechen", QMessageBox.NoRole)
|
|
msg_box.setDefaultButton(cancel_button) # Abbrechen als Standard
|
|
|
|
# Set object name for QSS targeting
|
|
delete_button.setObjectName("delete_confirm_button")
|
|
|
|
msg_box.exec_()
|
|
|
|
if msg_box.clickedButton() == delete_button:
|
|
self.account_delete_requested.emit(account_data)
|
|
# Reload accounts nach Löschung
|
|
self.load_accounts()
|
|
|
|
def _on_filter_changed(self, filter_key):
|
|
"""Behandelt Filter-Änderungen"""
|
|
self.current_filter = filter_key
|
|
|
|
# Update title
|
|
if filter_key == "all":
|
|
self.title.setText("Alle Accounts")
|
|
else:
|
|
platform_name = filter_key.capitalize()
|
|
if filter_key == "x":
|
|
platform_name = "X (Twitter)"
|
|
self.title.setText(f"{platform_name} Accounts")
|
|
|
|
self._update_display()
|
|
|
|
def _update_sidebar_counts(self):
|
|
"""Aktualisiert die Account-Anzahlen in der Sidebar"""
|
|
counts = {"all": len(self.accounts)}
|
|
|
|
# Zähle Accounts pro Plattform
|
|
for acc in self.accounts:
|
|
platform = acc.get("platform", "").lower()
|
|
if platform:
|
|
counts[platform] = counts.get(platform, 0) + 1
|
|
|
|
self.sidebar.update_counts(counts)
|
|
|
|
def update_texts(self):
|
|
"""Aktualisiert die Texte gemäß der aktuellen Sprache"""
|
|
if not self.language_manager:
|
|
return
|
|
|
|
# Update title based on current filter
|
|
if self.current_filter == "all":
|
|
self.title.setText(
|
|
self.language_manager.get_text("accounts_overview.all_accounts", "Alle Accounts")
|
|
)
|
|
else:
|
|
platform_name = self.current_filter.capitalize()
|
|
if self.current_filter == "x":
|
|
platform_name = "X (Twitter)"
|
|
self.title.setText(
|
|
self.language_manager.get_text(
|
|
f"accounts_overview.{self.current_filter}_accounts",
|
|
f"{platform_name} Accounts"
|
|
)
|
|
)
|
|
|
|
def update_session_status(self, account_id, status):
|
|
"""
|
|
Session-Status-Update deaktiviert (Session-Funktionalität entfernt).
|
|
"""
|
|
# Session-Funktionalität wurde entfernt - diese Methode macht nichts mehr
|
|
pass |