add burger menu
This commit is contained in:
		
							parent
							
								
									f859211729
								
							
						
					
					
						commit
						55f033ab37
					
				@ -20,5 +20,10 @@ class ThemeManager(QObject):
 | 
				
			|||||||
            self.settings.setValue("theme", theme)
 | 
					            self.settings.setValue("theme", theme)
 | 
				
			||||||
            self.theme_changed.emit(self.theme)
 | 
					            self.theme_changed.emit(self.theme)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def toggle_theme(self):
 | 
				
			||||||
 | 
					        """Переключает тему между светлой и темной."""
 | 
				
			||||||
 | 
					        new_theme = "light" if self.is_dark() else "dark"
 | 
				
			||||||
 | 
					        self.set_theme(new_theme)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Глобальный экземпляр
 | 
					# Глобальный экземпляр
 | 
				
			||||||
theme_manager = ThemeManager()
 | 
					theme_manager = ThemeManager()
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										334
									
								
								app/ui/views/side_menu_view.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										334
									
								
								app/ui/views/side_menu_view.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,334 @@
 | 
				
			|||||||
 | 
					# app/ui/views/side_menu_view.py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from PySide6.QtWidgets import (
 | 
				
			||||||
 | 
					    QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QFrame, 
 | 
				
			||||||
 | 
					    QScrollArea, QSizePolicy, QGraphicsDropShadowEffect
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					from PySide6.QtCore import Qt, QSize, QPropertyAnimation, QEasingCurve, Property
 | 
				
			||||||
 | 
					from PySide6.QtGui import QIcon, QColor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from app.core.theme import theme_manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SideMenuButton(QPushButton):
 | 
				
			||||||
 | 
					    """Кастомная кнопка для пунктов бокового меню."""
 | 
				
			||||||
 | 
					    def __init__(self, icon_path: str, text: str):
 | 
				
			||||||
 | 
					        super().__init__()
 | 
				
			||||||
 | 
					        self.setCursor(Qt.PointingHandCursor)
 | 
				
			||||||
 | 
					        self.setObjectName("SideMenuButton")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        layout = QHBoxLayout(self)
 | 
				
			||||||
 | 
					        layout.setContentsMargins(10, 8, 10, 8)
 | 
				
			||||||
 | 
					        layout.setSpacing(15)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        icon_label = QLabel(icon_path) # Используем текстовые иконки
 | 
				
			||||||
 | 
					        icon_label.setObjectName("SideMenuButtonIcon")
 | 
				
			||||||
 | 
					        icon_label.setFixedSize(24, 24)
 | 
				
			||||||
 | 
					        icon_label.setAlignment(Qt.AlignCenter)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        text_label = QLabel(text)
 | 
				
			||||||
 | 
					        text_label.setObjectName("SideMenuButtonText")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        layout.addWidget(icon_label)
 | 
				
			||||||
 | 
					        layout.addWidget(text_label)
 | 
				
			||||||
 | 
					        layout.addStretch()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SideMenuFooterButton(QPushButton):
 | 
				
			||||||
 | 
					    """Кастомная кнопка для футера бокового меню."""
 | 
				
			||||||
 | 
					    def __init__(self, icon_path: str, text: str):
 | 
				
			||||||
 | 
					        super().__init__()
 | 
				
			||||||
 | 
					        self.setCursor(Qt.PointingHandCursor)
 | 
				
			||||||
 | 
					        self.setObjectName("SideMenuFooterButton")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        layout = QVBoxLayout(self)
 | 
				
			||||||
 | 
					        layout.setContentsMargins(5, 8, 5, 8)
 | 
				
			||||||
 | 
					        layout.setSpacing(4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        icon_label = QLabel(icon_path)
 | 
				
			||||||
 | 
					        icon_label.setObjectName("SideMenuFooterIcon")
 | 
				
			||||||
 | 
					        icon_label.setAlignment(Qt.AlignCenter)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        text_label = QLabel(text)
 | 
				
			||||||
 | 
					        text_label.setObjectName("SideMenuFooterText")
 | 
				
			||||||
 | 
					        text_label.setAlignment(Qt.AlignCenter)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        layout.addWidget(icon_label)
 | 
				
			||||||
 | 
					        layout.addWidget(text_label)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SideMenuView(QFrame):
 | 
				
			||||||
 | 
					    """Виджет бокового меню."""
 | 
				
			||||||
 | 
					    def __init__(self, parent=None):
 | 
				
			||||||
 | 
					        super().__init__(parent)
 | 
				
			||||||
 | 
					        self.setObjectName("SideMenuView")
 | 
				
			||||||
 | 
					        self.setFixedWidth(280)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # --- Основной макет ---
 | 
				
			||||||
 | 
					        main_layout = QVBoxLayout(self)
 | 
				
			||||||
 | 
					        main_layout.setContentsMargins(0, 0, 0, 0)
 | 
				
			||||||
 | 
					        main_layout.setSpacing(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # --- Компоненты ---
 | 
				
			||||||
 | 
					        self.header = self._create_header()
 | 
				
			||||||
 | 
					        self.account_list_container = self._create_account_list()
 | 
				
			||||||
 | 
					        self.scroll_area = self._create_scroll_area()
 | 
				
			||||||
 | 
					        self.footer = self._create_footer()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        main_layout.addWidget(self.header)
 | 
				
			||||||
 | 
					        main_layout.addWidget(self.account_list_container)
 | 
				
			||||||
 | 
					        main_layout.addWidget(self.scroll_area)
 | 
				
			||||||
 | 
					        main_layout.addWidget(self.footer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # --- Анимация списка аккаунтов ---
 | 
				
			||||||
 | 
					        self.account_list_container.setVisible(False)
 | 
				
			||||||
 | 
					        self.account_list_animation = QPropertyAnimation(self.account_list_container, b"maximumHeight")
 | 
				
			||||||
 | 
					        self.account_list_animation.setDuration(300)
 | 
				
			||||||
 | 
					        self.account_list_animation.setEasingCurve(QEasingCurve.InOutQuart)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # --- Состояние анимации ---
 | 
				
			||||||
 | 
					        self.is_closing_animation = False
 | 
				
			||||||
 | 
					        self.account_list_animation.finished.connect(self._on_animation_finished)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.update_styles()
 | 
				
			||||||
 | 
					        theme_manager.theme_changed.connect(self.update_styles)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _create_header(self):
 | 
				
			||||||
 | 
					        """Создает заголовок меню."""
 | 
				
			||||||
 | 
					        header_widget = QWidget()
 | 
				
			||||||
 | 
					        header_layout = QVBoxLayout(header_widget)
 | 
				
			||||||
 | 
					        header_layout.setContentsMargins(15, 50, 15, 10)
 | 
				
			||||||
 | 
					        header_layout.setSpacing(10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Верхняя часть: Аватар и кнопка темы
 | 
				
			||||||
 | 
					        top_row_layout = QHBoxLayout()
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        avatar_button = QPushButton("👤")
 | 
				
			||||||
 | 
					        avatar_button.setObjectName("AvatarButton")
 | 
				
			||||||
 | 
					        avatar_button.setFixedSize(60, 60)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.theme_toggle_button = QPushButton("☀️")
 | 
				
			||||||
 | 
					        self.theme_toggle_button.setObjectName("ThemeToggleButton")
 | 
				
			||||||
 | 
					        self.theme_toggle_button.setCursor(Qt.PointingHandCursor)
 | 
				
			||||||
 | 
					        self.theme_toggle_button.clicked.connect(theme_manager.toggle_theme)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        top_row_layout.addWidget(avatar_button)
 | 
				
			||||||
 | 
					        top_row_layout.addStretch()
 | 
				
			||||||
 | 
					        top_row_layout.addWidget(self.theme_toggle_button)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Нижняя часть: Имя пользователя и кнопка раскрытия
 | 
				
			||||||
 | 
					        self.account_toggle_button = QPushButton()
 | 
				
			||||||
 | 
					        self.account_toggle_button.setObjectName("AccountToggleButton")
 | 
				
			||||||
 | 
					        self.account_toggle_button.setCursor(Qt.PointingHandCursor)
 | 
				
			||||||
 | 
					        self.account_toggle_button.clicked.connect(self.toggle_account_list)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        bottom_row_layout = QHBoxLayout(self.account_toggle_button)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        user_info_layout = QVBoxLayout()
 | 
				
			||||||
 | 
					        user_info_layout.setSpacing(0)
 | 
				
			||||||
 | 
					        user_info_layout.addWidget(QLabel("Your Name"))
 | 
				
			||||||
 | 
					        user_info_layout.addWidget(QLabel("@yourusername"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.expand_icon = QLabel("▼")
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        bottom_row_layout.addLayout(user_info_layout)
 | 
				
			||||||
 | 
					        bottom_row_layout.addStretch()
 | 
				
			||||||
 | 
					        bottom_row_layout.addWidget(self.expand_icon)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        header_layout.addLayout(top_row_layout)
 | 
				
			||||||
 | 
					        header_layout.addWidget(self.account_toggle_button)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return header_widget
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _create_account_list(self):
 | 
				
			||||||
 | 
					        """Создает выпадающий список аккаунтов."""
 | 
				
			||||||
 | 
					        container = QWidget()
 | 
				
			||||||
 | 
					        container.setObjectName("AccountListContainer")
 | 
				
			||||||
 | 
					        layout = QVBoxLayout(container)
 | 
				
			||||||
 | 
					        layout.setContentsMargins(15, 10, 15, 10)
 | 
				
			||||||
 | 
					        layout.setSpacing(15)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Пример аккаунтов
 | 
				
			||||||
 | 
					        accounts = [
 | 
				
			||||||
 | 
					            ("Your Name", "@yourusername", True),
 | 
				
			||||||
 | 
					            ("Second Account", "@second", False)
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for name, username, is_current in accounts:
 | 
				
			||||||
 | 
					            # Здесь можно создать более сложный виджет для каждого аккаунта
 | 
				
			||||||
 | 
					            label = QLabel(f"{name} ({username}) {'✔' if is_current else ''}")
 | 
				
			||||||
 | 
					            layout.addWidget(label)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return container
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _create_scroll_area(self):
 | 
				
			||||||
 | 
					        """Создает прокручиваемую область с пунктами меню."""
 | 
				
			||||||
 | 
					        scroll_area = QScrollArea()
 | 
				
			||||||
 | 
					        scroll_area.setWidgetResizable(True)
 | 
				
			||||||
 | 
					        scroll_area.setFrameShape(QFrame.NoFrame)
 | 
				
			||||||
 | 
					        scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
 | 
				
			||||||
 | 
					        scroll_area.setObjectName("ScrollArea")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        content_widget = QWidget()
 | 
				
			||||||
 | 
					        content_layout = QVBoxLayout(content_widget)
 | 
				
			||||||
 | 
					        content_layout.setContentsMargins(15, 10, 15, 10)
 | 
				
			||||||
 | 
					        content_layout.setSpacing(5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Секция 1
 | 
				
			||||||
 | 
					        content_layout.addWidget(SideMenuButton("👥", "People You May Like"))
 | 
				
			||||||
 | 
					        content_layout.addWidget(SideMenuButton("⭐", "Fun Fest"))
 | 
				
			||||||
 | 
					        content_layout.addWidget(SideMenuButton("💡", "Creator Center"))
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        content_layout.addSpacing(10)
 | 
				
			||||||
 | 
					        content_layout.addWidget(self._create_divider())
 | 
				
			||||||
 | 
					        content_layout.addSpacing(10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Секция 2
 | 
				
			||||||
 | 
					        content_layout.addWidget(self._create_category_label("CATEGORY"))
 | 
				
			||||||
 | 
					        content_layout.addWidget(SideMenuButton("📄", "Drafts"))
 | 
				
			||||||
 | 
					        content_layout.addWidget(SideMenuButton("💬", "My Comments"))
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        content_layout.addStretch() # Заполняет пространство внизу
 | 
				
			||||||
 | 
					        scroll_area.setWidget(content_widget)
 | 
				
			||||||
 | 
					        return scroll_area
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _create_footer(self):
 | 
				
			||||||
 | 
					        """Создает футер меню."""
 | 
				
			||||||
 | 
					        footer_widget = QWidget()
 | 
				
			||||||
 | 
					        footer_widget.setObjectName("SideMenuFooter")
 | 
				
			||||||
 | 
					        layout = QHBoxLayout(footer_widget)
 | 
				
			||||||
 | 
					        layout.setContentsMargins(15, 10, 15, 20)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        layout.addWidget(SideMenuFooterButton("📱", "Scan"))
 | 
				
			||||||
 | 
					        layout.addWidget(SideMenuFooterButton("❓", "Help"))
 | 
				
			||||||
 | 
					        layout.addWidget(SideMenuFooterButton("⚙️", "Settings"))
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return footer_widget
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _create_divider(self):
 | 
				
			||||||
 | 
					        divider = QFrame()
 | 
				
			||||||
 | 
					        divider.setFrameShape(QFrame.HLine)
 | 
				
			||||||
 | 
					        divider.setObjectName("Divider")
 | 
				
			||||||
 | 
					        return divider
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _create_category_label(self, text):
 | 
				
			||||||
 | 
					        label = QLabel(text)
 | 
				
			||||||
 | 
					        label.setObjectName("CategoryLabel")
 | 
				
			||||||
 | 
					        return label
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _on_animation_finished(self):
 | 
				
			||||||
 | 
					        """Срабатывает после завершения анимации."""
 | 
				
			||||||
 | 
					        if self.is_closing_animation:
 | 
				
			||||||
 | 
					            self.account_list_container.setVisible(False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def toggle_account_list(self):
 | 
				
			||||||
 | 
					        """Анимирует показ/скрытие списка аккаунтов."""
 | 
				
			||||||
 | 
					        self.account_list_animation.stop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.account_list_container.isVisible():
 | 
				
			||||||
 | 
					            # --- Закрытие ---
 | 
				
			||||||
 | 
					            self.is_closing_animation = True
 | 
				
			||||||
 | 
					            self.expand_icon.setText("▼")
 | 
				
			||||||
 | 
					            end_height = 0
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            # --- Открытие ---
 | 
				
			||||||
 | 
					            self.is_closing_animation = False
 | 
				
			||||||
 | 
					            self.expand_icon.setText("▲")
 | 
				
			||||||
 | 
					            self.account_list_container.setVisible(True)
 | 
				
			||||||
 | 
					            end_height = self.account_list_container.sizeHint().height()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.account_list_animation.setStartValue(self.account_list_container.height())
 | 
				
			||||||
 | 
					        self.account_list_animation.setEndValue(end_height)
 | 
				
			||||||
 | 
					        self.account_list_animation.start()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update_styles(self):
 | 
				
			||||||
 | 
					        """Обновляет стили в зависимости от темы."""
 | 
				
			||||||
 | 
					        is_dark = theme_manager.is_dark()
 | 
				
			||||||
 | 
					        self.theme_toggle_button.setText("🌙" if is_dark else "☀️")
 | 
				
			||||||
 | 
					        self.setStyleSheet(self.get_stylesheet())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_stylesheet(self):
 | 
				
			||||||
 | 
					        is_dark = theme_manager.is_dark()
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        bg_color = "#1c1c1e" if is_dark else "#ffffff"
 | 
				
			||||||
 | 
					        text_color = "#f2f2f7" if is_dark else "#000000"
 | 
				
			||||||
 | 
					        secondary_text_color = "#8e8e93" if is_dark else "#888888"
 | 
				
			||||||
 | 
					        divider_color = "#3c3c3c" if is_dark else "#e7e7e7"
 | 
				
			||||||
 | 
					        button_hover_bg = "#2c2c2e" if is_dark else "#f0f0f0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return f"""
 | 
				
			||||||
 | 
					            #SideMenuView {{
 | 
				
			||||||
 | 
					                background-color: {bg_color};
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            QPushButton {{
 | 
				
			||||||
 | 
					                border: none;
 | 
				
			||||||
 | 
					                background: transparent;
 | 
				
			||||||
 | 
					                text-align: left;
 | 
				
			||||||
 | 
					                color: {text_color};
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* --- Header --- */
 | 
				
			||||||
 | 
					            #AvatarButton {{
 | 
				
			||||||
 | 
					                font-size: 40px;
 | 
				
			||||||
 | 
					                border-radius: 30px;
 | 
				
			||||||
 | 
					                background-color: {divider_color};
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            #ThemeToggleButton {{
 | 
				
			||||||
 | 
					                font-size: 24px;
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            #AccountToggleButton {{
 | 
				
			||||||
 | 
					                padding: 8px;
 | 
				
			||||||
 | 
					                border-radius: 8px;
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            #AccountToggleButton:hover {{
 | 
				
			||||||
 | 
					                background-color: {button_hover_bg};
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            #AccountToggleButton QLabel {{
 | 
				
			||||||
 | 
					                color: {text_color};
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            #AccountToggleButton > QLabel:first-child {{ /* Имя */
 | 
				
			||||||
 | 
					                font-weight: bold;
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            #AccountToggleButton > QLabel:last-child {{ /* @username */
 | 
				
			||||||
 | 
					                color: {secondary_text_color};
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* --- Account List --- */
 | 
				
			||||||
 | 
					            #AccountListContainer {{
 | 
				
			||||||
 | 
					                background-color: transparent;
 | 
				
			||||||
 | 
					                color: {text_color};
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* --- Menu Buttons --- */
 | 
				
			||||||
 | 
					            #SideMenuButton, #SideMenuFooterButton {{
 | 
				
			||||||
 | 
					                border-radius: 8px;
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            #SideMenuButton:hover, #SideMenuFooterButton:hover {{
 | 
				
			||||||
 | 
					                background-color: {button_hover_bg};
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            #SideMenuButtonIcon, #SideMenuFooterIcon {{
 | 
				
			||||||
 | 
					                font-size: 18px;
 | 
				
			||||||
 | 
					                color: {text_color};
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            #SideMenuButtonText, #SideMenuFooterText {{
 | 
				
			||||||
 | 
					                font-size: 14px;
 | 
				
			||||||
 | 
					                color: {text_color};
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            #SideMenuFooterText {{
 | 
				
			||||||
 | 
					                font-size: 11px;
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* --- Other --- */
 | 
				
			||||||
 | 
					            #Divider {{
 | 
				
			||||||
 | 
					                background-color: {divider_color};
 | 
				
			||||||
 | 
					                border: none;
 | 
				
			||||||
 | 
					                height: 1px;
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            #CategoryLabel {{
 | 
				
			||||||
 | 
					                color: {secondary_text_color};
 | 
				
			||||||
 | 
					                font-size: 12px;
 | 
				
			||||||
 | 
					                font-weight: bold;
 | 
				
			||||||
 | 
					                padding: 5px 10px;
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            #ScrollArea {{
 | 
				
			||||||
 | 
					                border: none;
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
@ -1,41 +1,125 @@
 | 
				
			|||||||
from PySide6.QtWidgets import (
 | 
					from PySide6.QtWidgets import (
 | 
				
			||||||
    QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QFrame, 
 | 
					    QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QFrame, 
 | 
				
			||||||
    QStackedWidget, QSpacerItem, QSizePolicy, QGraphicsDropShadowEffect
 | 
					    QStackedWidget, QSpacerItem, QSizePolicy, QGraphicsDropShadowEffect,
 | 
				
			||||||
 | 
					    QGraphicsOpacityEffect
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
from PySide6.QtCore import Qt, QSize
 | 
					from PySide6.QtCore import Qt, QSize, QPropertyAnimation, QEasingCurve, Property
 | 
				
			||||||
from PySide6.QtGui import QIcon, QColor
 | 
					from PySide6.QtGui import QIcon, QColor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from app.core.theme import theme_manager
 | 
					from app.core.theme import theme_manager
 | 
				
			||||||
 | 
					from app.ui.views.side_menu_view import SideMenuView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class YobbleHomeView(QWidget):
 | 
					class YobbleHomeView(QWidget):
 | 
				
			||||||
    def __init__(self, username: str):
 | 
					    def __init__(self, username: str):
 | 
				
			||||||
        super().__init__()
 | 
					        super().__init__()
 | 
				
			||||||
        self.username = username
 | 
					        self.username = username
 | 
				
			||||||
        self.setWindowTitle(f"Yobble Home - {username}")
 | 
					        self.setWindowTitle(f"Yobble Home - {username}")
 | 
				
			||||||
 | 
					        self.setMinimumSize(360, 640)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # --- Основной макет ---
 | 
					        # --- Основной макет ---
 | 
				
			||||||
        main_layout = QVBoxLayout(self)
 | 
					        # Используем QHBoxLayout, чтобы можно было разместить меню и контент рядом
 | 
				
			||||||
 | 
					        # Но на самом деле меню будет поверх контента
 | 
				
			||||||
 | 
					        main_layout = QHBoxLayout(self)
 | 
				
			||||||
        main_layout.setContentsMargins(0, 0, 0, 0)
 | 
					        main_layout.setContentsMargins(0, 0, 0, 0)
 | 
				
			||||||
        main_layout.setSpacing(0)
 | 
					        main_layout.setSpacing(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # --- Виджет для основного контента ---
 | 
				
			||||||
 | 
					        self.content_widget = QWidget()
 | 
				
			||||||
 | 
					        content_layout = QVBoxLayout(self.content_widget)
 | 
				
			||||||
 | 
					        content_layout.setContentsMargins(0, 0, 0, 0)
 | 
				
			||||||
 | 
					        content_layout.setSpacing(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # 1. Верхняя панель
 | 
					        # 1. Верхняя панель
 | 
				
			||||||
        self.top_bar = self.create_top_bar()
 | 
					        self.top_bar = self.create_top_bar()
 | 
				
			||||||
        main_layout.addWidget(self.top_bar)
 | 
					        content_layout.addWidget(self.top_bar)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # 2. Центральная область контента
 | 
					        # 2. Центральная область контента
 | 
				
			||||||
        self.content_stack = QStackedWidget()
 | 
					        self.content_stack = QStackedWidget()
 | 
				
			||||||
        self.setup_content_pages()
 | 
					        self.setup_content_pages()
 | 
				
			||||||
        main_layout.addWidget(self.content_stack, 1)
 | 
					        content_layout.addWidget(self.content_stack, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # 3. Нижняя панель навигации
 | 
					        # 3. Нижняя панель навигации
 | 
				
			||||||
        self.bottom_bar = self.create_bottom_bar()
 | 
					        self.bottom_bar = self.create_bottom_bar()
 | 
				
			||||||
        main_layout.addWidget(self.bottom_bar)
 | 
					        content_layout.addWidget(self.bottom_bar)
 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.update_styles()  # Применяем стили при инициализации
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        # Подключаемся к сигналу смены темы
 | 
					        main_layout.addWidget(self.content_widget)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # --- Боковое меню и оверлей ---
 | 
				
			||||||
 | 
					        self.setup_side_menu()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.update_styles()
 | 
				
			||||||
        theme_manager.theme_changed.connect(self.update_styles)
 | 
					        theme_manager.theme_changed.connect(self.update_styles)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def setup_side_menu(self):
 | 
				
			||||||
 | 
					        """Настраивает боковое меню и оверлей."""
 | 
				
			||||||
 | 
					        # Оверлей для затемнения контента
 | 
				
			||||||
 | 
					        self.overlay = QFrame(self)
 | 
				
			||||||
 | 
					        self.overlay.setObjectName("Overlay")
 | 
				
			||||||
 | 
					        self.overlay.hide()
 | 
				
			||||||
 | 
					        self.overlay.mousePressEvent = lambda event: self.toggle_side_menu()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Эффект прозрачности для оверлея
 | 
				
			||||||
 | 
					        self.opacity_effect = QGraphicsOpacityEffect(self.overlay)
 | 
				
			||||||
 | 
					        self.overlay.setGraphicsEffect(self.opacity_effect)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # Боковое меню
 | 
				
			||||||
 | 
					        self.side_menu = SideMenuView(self)
 | 
				
			||||||
 | 
					        self.side_menu.move(-self.side_menu.width(), 0) # Изначально скрыто за экраном
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Анимация для меню
 | 
				
			||||||
 | 
					        self.menu_animation = QPropertyAnimation(self.side_menu, b"pos")
 | 
				
			||||||
 | 
					        self.menu_animation.setEasingCurve(QEasingCurve.InOutCubic)
 | 
				
			||||||
 | 
					        self.menu_animation.setDuration(300)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Анимация для оверлея
 | 
				
			||||||
 | 
					        self.opacity_animation = QPropertyAnimation(self.opacity_effect, b"opacity")
 | 
				
			||||||
 | 
					        self.opacity_animation.setDuration(300)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # --- Состояние анимации ---
 | 
				
			||||||
 | 
					        self.is_menu_closing = False
 | 
				
			||||||
 | 
					        self.opacity_animation.finished.connect(self._on_menu_animation_finished)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _on_menu_animation_finished(self):
 | 
				
			||||||
 | 
					        """Срабатывает после завершения анимации оверлея."""
 | 
				
			||||||
 | 
					        if self.is_menu_closing:
 | 
				
			||||||
 | 
					            self.overlay.hide()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def toggle_side_menu(self):
 | 
				
			||||||
 | 
					        """Показывает или скрывает боковое меню с анимацией."""
 | 
				
			||||||
 | 
					        # Останавливаем текущие анимации, чтобы избежать конфликтов
 | 
				
			||||||
 | 
					        self.menu_animation.stop()
 | 
				
			||||||
 | 
					        self.opacity_animation.stop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        is_hidden = self.side_menu.pos().x() < 0
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if is_hidden:
 | 
				
			||||||
 | 
					            # --- Открытие ---
 | 
				
			||||||
 | 
					            self.is_menu_closing = False
 | 
				
			||||||
 | 
					            self.overlay.show()
 | 
				
			||||||
 | 
					            self.menu_animation.setStartValue(self.side_menu.pos())
 | 
				
			||||||
 | 
					            self.menu_animation.setEndValue(self.side_menu.pos().__class__(0, 0))
 | 
				
			||||||
 | 
					            self.opacity_animation.setStartValue(self.opacity_effect.opacity())
 | 
				
			||||||
 | 
					            self.opacity_animation.setEndValue(0.5)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            # --- Закрытие ---
 | 
				
			||||||
 | 
					            self.is_menu_closing = True
 | 
				
			||||||
 | 
					            self.menu_animation.setStartValue(self.side_menu.pos())
 | 
				
			||||||
 | 
					            self.menu_animation.setEndValue(self.side_menu.pos().__class__(-self.side_menu.width(), 0))
 | 
				
			||||||
 | 
					            self.opacity_animation.setStartValue(self.opacity_effect.opacity())
 | 
				
			||||||
 | 
					            self.opacity_animation.setEndValue(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.menu_animation.start()
 | 
				
			||||||
 | 
					        self.opacity_animation.start()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def resizeEvent(self, event):
 | 
				
			||||||
 | 
					        """Обновляет геометрию оверлея и меню при изменении размера окна."""
 | 
				
			||||||
 | 
					        super().resizeEvent(event)
 | 
				
			||||||
 | 
					        self.overlay.setGeometry(self.rect())
 | 
				
			||||||
 | 
					        if self.side_menu.pos().x() < 0:
 | 
				
			||||||
 | 
					            self.side_menu.move(-self.side_menu.width(), 0)
 | 
				
			||||||
 | 
					        self.side_menu.setFixedHeight(self.height())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def update_styles(self):
 | 
					    def update_styles(self):
 | 
				
			||||||
        """Обновляет стили компонента при смене темы."""
 | 
					        """Обновляет стили компонента при смене темы."""
 | 
				
			||||||
        self.setStyleSheet(self.get_stylesheet())
 | 
					        self.setStyleSheet(self.get_stylesheet())
 | 
				
			||||||
@ -50,6 +134,8 @@ class YobbleHomeView(QWidget):
 | 
				
			|||||||
        self.burger_menu_button = QPushButton("☰")
 | 
					        self.burger_menu_button = QPushButton("☰")
 | 
				
			||||||
        self.burger_menu_button.setObjectName("BurgerMenuButton")
 | 
					        self.burger_menu_button.setObjectName("BurgerMenuButton")
 | 
				
			||||||
        self.burger_menu_button.setFocusPolicy(Qt.NoFocus)
 | 
					        self.burger_menu_button.setFocusPolicy(Qt.NoFocus)
 | 
				
			||||||
 | 
					        self.burger_menu_button.setCursor(Qt.PointingHandCursor)
 | 
				
			||||||
 | 
					        self.burger_menu_button.clicked.connect(self.toggle_side_menu) # Подключаем сигнал
 | 
				
			||||||
        top_bar_layout.addWidget(self.burger_menu_button)
 | 
					        top_bar_layout.addWidget(self.burger_menu_button)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.title_label = QLabel("Чаты")
 | 
					        self.title_label = QLabel("Чаты")
 | 
				
			||||||
@ -167,11 +253,15 @@ class YobbleHomeView(QWidget):
 | 
				
			|||||||
        top_bar_bg = "#2c2c2e" if is_dark else "#f5f5f5"
 | 
					        top_bar_bg = "#2c2c2e" if is_dark else "#f5f5f5"
 | 
				
			||||||
        top_bar_border = "#3c3c3c" if is_dark else "#e0e0e0"
 | 
					        top_bar_border = "#3c3c3c" if is_dark else "#e0e0e0"
 | 
				
			||||||
        hover_color = "#d0d0d0" if not is_dark else "#444444"
 | 
					        hover_color = "#d0d0d0" if not is_dark else "#444444"
 | 
				
			||||||
 | 
					        overlay_color = "rgba(0, 0, 0, 0.5)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return f"""
 | 
					        return f"""
 | 
				
			||||||
            YobbleHomeView {{
 | 
					            #content_widget {{
 | 
				
			||||||
                background-color: {bg_color};
 | 
					                background-color: {bg_color};
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
 | 
					            #Overlay {{
 | 
				
			||||||
 | 
					                background-color: {overlay_color};
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* Глобальные стили для кнопок */
 | 
					            /* Глобальные стили для кнопок */
 | 
				
			||||||
            QPushButton {{
 | 
					            QPushButton {{
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user