import os from PyQt6.QtWidgets import ( QApplication, QWidget, QPushButton, QButtonGroup, QScrollArea ) from PyQt6.QtGui import QPixmap, QIcon, QPainter, QColor, QFont from PyQt6.QtCore import Qt from PyQt6 import QtCore from gui.v2.ui.pages.Page import Page class BrowserPage(Page): def __init__(self, page_stack, main_window, parent=None): super().__init__("Browser", page_stack, main_window, parent) self.btn_path = main_window.btn_path self.update_status = main_window self.selected_browser_icon = None self.display.setGeometry(QtCore.QRect(5, 10, 390, 520)) self.title.setGeometry(395, 40, 380, 40) self.title.setText("Pick a Browser") self.button_back.setVisible(True) cm = main_window.connection_manager if cm.is_synced(): from gui.v2.actions.sync import generate_grid_positions browsers = cm.get_browser_list() positions = generate_grid_positions(len(browsers)) available = [(QPushButton, brw, positions[i]) for i, brw in enumerate(browsers)] self.create_interface_elements(available) def create_interface_elements(self, available_browsers): self._setup_scroll_area() button_widget = self._create_button_widget() self._populate_button_widget(button_widget, available_browsers) self.scroll_area.setWidget(button_widget) def _setup_scroll_area(self): self.scroll_area = QScrollArea(self) self.scroll_area.setGeometry(400, 90, 385, 400) self.scroll_area.setWidgetResizable(True) self.scroll_area.setHorizontalScrollBarPolicy( Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self._apply_scroll_area_style() def _apply_scroll_area_style(self): self.scroll_area.setStyleSheet(""" QScrollArea { background: transparent; border: none; } QScrollBar:vertical { border: 1px solid white; background: white; width: 10px; margin: 0px 0px 0px 0px; } QScrollBar::handle:vertical { background: cyan; min-height: 0px; } QScrollBar::add-line:vertical { height: 0px; subcontrol-position: bottom; subcontrol-origin: margin; } QScrollBar::sub-line:vertical { height: 0px; subcontrol-position: top; subcontrol-origin: margin; } """) def _create_button_widget(self): button_widget = QWidget() button_widget.setStyleSheet("background: transparent;") self.buttonGroup = QButtonGroup(self) self.buttons = [] return button_widget def _populate_button_widget(self, button_widget, available_browsers): dimensions = self._get_button_dimensions() total_height = self._create_browser_buttons( button_widget, available_browsers, dimensions) self._set_final_widget_size(button_widget, dimensions, total_height) def _get_button_dimensions(self): return { 'width': 185, 'height': 75, 'spacing': 20, 'x_offset': 195 } def _create_browser_buttons(self, button_widget, browser_icons, dims): total_height = 0 for browser_tuple in browser_icons: _, browser_string, geometry = browser_tuple x_coord = geometry[0] - 395 y_coord = geometry[1] - 90 self._create_single_button( button_widget, browser_string, x_coord, y_coord, dims) total_height = max(total_height, y_coord + dims['height']) return total_height def _create_single_button(self, parent, icon_name, x_coord, y_coord, dims): button = QPushButton(parent) button.setFixedSize(dims['width'], dims['height']) button.move(x_coord, y_coord) button.setIconSize(button.size()) button.setCheckable(True) browser_name, version = icon_name.split(':') button.setIcon(QIcon(BrowserPage.create_browser_button_image( f"{browser_name} {version}", self.btn_path))) if button.icon().isNull(): fallback_path = os.path.join( self.btn_path, "default_browser_button.png") button.setIcon(QIcon(BrowserPage.create_browser_button_image( f"{browser_name} {version}", fallback_path, True))) self._apply_button_style(button) self.buttons.append(button) self.buttonGroup.addButton(button) button.clicked.connect( lambda _, b=icon_name: self.show_browser(b.replace(':', ' '))) @staticmethod def create_browser_button_image(browser_text, btn_path, is_fallback=False): if ':' in browser_text: browser_name, version = browser_text.split(':', 1) else: browser_name, version = browser_text.split( )[0], ' '.join(browser_text.split()[1:]) if is_fallback: base_image = QPixmap(btn_path) else: base_image = QPixmap(os.path.join( btn_path, f"{browser_name}_button.png")) if base_image.isNull(): base_image = QPixmap(185, 75) base_image.fill(QColor(44, 62, 80)) painter = QPainter(base_image) if painter.isActive(): BrowserPage._setup_version_font(painter, version, base_image) if is_fallback: BrowserPage._setup_browser_name( painter, browser_name, base_image) painter.end() return base_image @staticmethod def _setup_browser_name(painter, browser_name, base_image): font_size = 13 app_font = QApplication.font() app_font.setPointSize(font_size) app_font.setWeight(QFont.Weight.Bold) painter.setFont(app_font) painter.setPen(QColor(0, 255, 255)) text_rect = painter.fontMetrics().boundingRect(browser_name) while text_rect.width() > base_image.width() * 0.6 and font_size > 6: font_size -= 1 x = (base_image.width() - text_rect.width()) // 2 - 30 y = (base_image.height() + text_rect.height()) // 2 - 10 painter.drawText(x, y, browser_name) @staticmethod def _setup_version_font(painter, version, base_image): font_size = 11 painter.setFont(QFont('Arial', font_size)) painter.setPen(QColor(0x88, 0x88, 0x88)) text_rect = painter.fontMetrics().boundingRect(version) while text_rect.width() > base_image.width() * 0.6 and font_size > 6: font_size -= 1 painter.setFont(QFont('Arial', font_size)) text_rect = painter.fontMetrics().boundingRect(version) x = (base_image.width() - text_rect.width()) // 2 - 27 y = (base_image.height() + text_rect.height()) // 2 + 10 painter.drawText(x, y, version) def _apply_button_style(self, button): button.setStyleSheet(""" QPushButton { background: transparent; border: none; } QPushButton:hover { background-color: rgba(200, 200, 200, 30); } QPushButton:checked { background-color: rgba(200, 200, 200, 50); } """) def _set_final_widget_size(self, widget, dims, total_height): widget.setFixedSize(dims['width'] * 2 + 5, total_height + dims['spacing']) def show_browser(self, browser): browser_name, version = browser.split( )[0], ' '.join(browser.split()[1:]) try: base_image = self._create_browser_display_image( browser_name, version) self.display.setPixmap(base_image.scaled( self.display.size(), Qt.AspectRatioMode.KeepAspectRatio)) except Exception: pass self.selected_browser_icon = browser self.button_next.setVisible(True) self.update_swarp_json() def _create_browser_display_image(self, browser_name, version): base_image = QPixmap(os.path.join( self.btn_path, f"{browser_name}_icon.png")) painter = QPainter(base_image) painter.setFont(QFont('Arial', 25)) painter.setPen(QColor(0, 255, 255)) text_rect = painter.fontMetrics().boundingRect(version) x = (base_image.width() - text_rect.width()) // 2 y = base_image.height() - 45 painter.drawText(x, y, version) painter.end() return base_image def update_swarp_json(self): inserted_data = { "browser": self.selected_browser_icon } self.update_status.write_data(inserted_data) def gestionar_next(self): self.custom_window.navigator.navigate("screen")