import os from PyQt6.QtWidgets import ( QLabel, QPushButton, QLineEdit, QTextEdit, QFrame, QDialog, QVBoxLayout, QHBoxLayout, QMessageBox, QGraphicsDropShadowEffect ) from PyQt6.QtGui import QPixmap, QIcon, QPainter, QColor, QTransform from PyQt6.QtCore import Qt, QSize, QTimer, QPointF from PyQt6 import QtCore, QtGui from core.controllers.ProfileController import ProfileController from core.controllers.LocationController import LocationController from gui.v2.ui.pages.Page import Page from gui.v2.ui.pages.browser_page import BrowserPage from gui.v2.ui.pages.location_page import LocationPage from gui.v2.ui.pages.screen_page import ScreenPage from gui.v2.ui.popups.confirmation_popup import ConfirmationPopup from gui.v2.workers.page_data_worker import PageDataWorker class EditorPage(Page): def __init__(self, page_stack, main_window): super().__init__("Editor", page_stack, main_window) self.page_stack = page_stack self.update_status = main_window self.connection_manager = main_window.connection_manager self.labels = [] self.buttons = [] self.title.setGeometry(570, 40, 185, 40) self.title.setText("Edit Profile") self.button_apply.setVisible(True) self.button_apply.clicked.connect(self.go_selected) self.button_back.setVisible(True) try: self.button_back.clicked.disconnect() except TypeError: pass self.button_back.clicked.connect(self.go_back) self.name_handle = QLabel(self) self.name_handle.setGeometry(110, 70, 400, 30) self.name_handle.setStyleSheet('color: #cacbcb;') self.name_handle.setText("Profile Name:") self.name_hint = QLabel(self) self.name_hint.setGeometry(265, 100, 190, 20) self.name_hint.setStyleSheet( 'color: #888888; font-size: 10px; font-style: italic;') self.name_hint.setText("Click here to edit profile name") self.name_hint.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) self.name = QLineEdit(self) self.name.setPlaceholderText("Enter name") self.name.setGeometry(265, 70, 190, 30) self.name.setStyleSheet( "color: cyan; border: 1px solid #666666; border-radius: 3px; background-color: rgba(0, 0, 0, 0.3);") self.name.setCursor(QtCore.Qt.CursorShape.IBeamCursor) self.name.focusInEvent = lambda event: self.name_hint.hide() self.name.focusOutEvent = lambda event: self.name_hint.show( ) if not self.name.text() else self.name_hint.hide() self.name.textChanged.connect( lambda text: self.name_hint.hide() if text else self.name_hint.show()) self.temp_changes = {} self.original_values = {} self.res_hint_shown = False self.display.setGeometry(QtCore.QRect(0, 60, 540, 405)) self.display.hide() self.garaje = QLabel(self) self.garaje.setGeometry(QtCore.QRect(0, 70, 540, 460)) self.brow_disp = QLabel(self) self.brow_disp.setGeometry(QtCore.QRect(0, 50, 540, 460)) self.brow_disp.setPixmap( QPixmap(os.path.join(self.btn_path, "browser only.png"))) self.brow_disp.hide() self.brow_disp.lower() self._prefetched_profiles = None self._editor_workers = set() @staticmethod def prepare_data(custom_window): return ProfileController.get_all() def _selected_profiles_str(self): menu_page = self.find_menu_page() if menu_page is not None and menu_page.selected_profiles: return ', '.join( [f"Profile_{profile['profile_number']}" for profile in menu_page.selected_profiles]) profile_id = getattr(self.update_status, 'current_profile_id', None) if profile_id is not None: return f"Profile_{int(profile_id)}" return '' def update_name_value(self): original_name = self.data_profile.get('name', '') new_name = self.name.text() if original_name != new_name: self.update_temp_value('name', new_name) else: pass def go_back(self): selected_profiles_str = self._selected_profiles_str() if self.has_unsaved_changes(selected_profiles_str): self.show_unsaved_changes_popup() else: self.custom_window.navigator.navigate("menu") def find_menu_page(self): return self.custom_window.navigator.get_cached("menu") def find_resume_page(self): return self.custom_window.navigator.get_cached("resume") def find_protocol_page(self): return self.custom_window.navigator.get_cached("protocol") def showEvent(self, event): super().showEvent(event) self.res_hint_shown = False worker = PageDataWorker("editor", EditorPage.prepare_data, self.custom_window) worker.data_ready.connect( lambda name, profiles: self._on_editor_data_ready(profiles)) worker.failed.connect( lambda name, error: self._on_editor_data_failed(error)) worker.finished.connect( lambda w=worker: self._cleanup_editor_worker(w)) self._editor_workers.add(worker) worker.start() def _on_editor_data_ready(self, profiles): self._prefetched_profiles = profiles self.extraccion() def _on_editor_data_failed(self, error): self.update_status.update_status(f"Editor data load failed: {error}") self.extraccion() def _cleanup_editor_worker(self, worker): self._editor_workers.discard(worker) worker.deleteLater() def extraccion(self): self.data_profile = {} for label in self.labels: label.deleteLater() self.labels = [] for button in self.buttons: button.deleteLater() self.buttons = [] selected_profiles_str = self._selected_profiles_str() menu_page = self.find_menu_page() if menu_page: if self._prefetched_profiles is not None: new_profiles = self._prefetched_profiles self._prefetched_profiles = None else: new_profiles = ProfileController.get_all() self.profiles_data = menu_page.match_core_profiles( profiles_dict=new_profiles) self.data_profile = self.profiles_data[selected_profiles_str].copy( ) profile_id = int(selected_profiles_str.split('_')[1]) self.data_profile['id'] = profile_id if selected_profiles_str in self.temp_changes: for key, value in self.temp_changes[selected_profiles_str].items(): self.data_profile[key] = value self.name.textChanged.connect(self.update_name_value) self.verificate(self.data_profile, selected_profiles_str) def verificate(self, data_profile, selected_profile_str): protocol = data_profile.get("protocol", "") try: if protocol == "wireguard": self.process_and_show_labels(data_profile, { "protocol": ['wireguard', 'residential', 'hidetor'], "connection": ['browser-only', 'system-wide'], "location": self.connection_manager.get_location_list(), "browser": self.connection_manager.get_browser_list(), "dimentions": self.connection_manager.get_available_resolutions(data_profile.get('id', '')) }, selected_profile_str) elif protocol == "residential" or protocol == "hidetor": self.process_and_show_labels(data_profile, { "protocol": ['residential', 'wireguard', 'hidetor'], "connection": ['tor', 'just proxy'], "location": self.connection_manager.get_location_list(), "browser": self.connection_manager.get_browser_list(), "dimentions": self.connection_manager.get_available_resolutions(data_profile.get('id', '')) }, selected_profile_str) elif protocol == "open": self.process_and_show_labels(data_profile, { "protocol": ['open'] }, selected_profile_str) except Exception as e: print(f'An error occurred in verificate: {e}') def process_and_show_labels(self, data_profile, parameters, selected_profile_str): protocol = data_profile.get('protocol', "") connection = data_profile.get('connection', "") location = data_profile.get('location', "") country_garaje = location name = data_profile.get('name', "") self.name.setText(name) if protocol == "hidetor": if connection == "just proxy": self.display.setPixmap(QPixmap(os.path.join( self.btn_path, f"icon_{location}.png"))) else: self.display.setPixmap(QPixmap(os.path.join( self.btn_path, f"hdtor_{location}.png"))) self.display.show() self.display.setGeometry(0, 100, 400, 394) self.display.setScaledContents(True) self.garaje.hide() self.brow_disp.hide() if protocol == "wireguard": self.display.setGeometry(0, 60, 540, 405) self.display.show() self.display.setPixmap(QPixmap(os.path.join( self.btn_path, f"wireguard_{location}.png"))) self.garaje.hide() if connection == "browser-only": is_supported = data_profile.get('browser_supported', False) image_name = "browser only.png" if is_supported else "unsupported_browser_only.png" self.brow_disp.setPixmap( QPixmap(os.path.join(self.btn_path, image_name))) self.brow_disp.show() else: self.brow_disp.hide() if protocol == "residential": self.display.setGeometry(0, 60, 540, 405) self.brow_disp.show() self.garaje.show() self.display.hide() if country_garaje: country_garaje = 'brazil' self.garaje.setPixmap(QPixmap(os.path.join( self.btn_path, f"{country_garaje} garaje.png"))) profile_id = data_profile.get('id') profile_obj = ProfileController.get(profile_id) location_info = None if location: try: if '_' in location: country_code, location_code = location.split('_', 1) location_info = LocationController.get( country_code, location_code) except Exception: location_info = None operator_name = "" l_name = "" o_name = "" n_key = "" if location_info: if hasattr(location_info, 'operator') and location_info.operator: operator_name = location_info.operator.name o_name = location_info.operator.name n_key = location_info.operator.nostr_public_key l_name = f"{location_info.country_name}, {location_info.name}" if hasattr( location_info, 'country_name') else "" if operator_name != 'Simplified Privacy' and operator_name != "" and protocol != 'hidetor': text_color = "white" if profile_obj and profile_obj.is_session_profile(): text_color = "black" l_img = QLabel(self) l_img.setGeometry(20, 125, 150, 150) pixmap_loc = QPixmap(os.path.join( self.btn_path, f"icon_{location}.png")) l_img.setPixmap(pixmap_loc) l_img.setScaledContents(True) l_img.show() self.labels.append(l_img) info_txt = QTextEdit(self) info_txt.setGeometry(180, 120, 300, 250) info_txt.setReadOnly(True) info_txt.setFrameStyle(QFrame.Shape.NoFrame) info_txt.setStyleSheet( f"background: transparent; border: none; color: {text_color}; font-size: 19px;") info_txt.setVerticalScrollBarPolicy( Qt.ScrollBarPolicy.ScrollBarAlwaysOff) info_txt.setHorizontalScrollBarPolicy( Qt.ScrollBarPolicy.ScrollBarAlwaysOff) info_txt.setWordWrapMode( QtGui.QTextOption.WrapMode.WrapAtWordBoundaryOrAnywhere) info_txt.setText( f"Location: {l_name}\n\nOperator: {o_name}") info_txt.show() self.labels.append(info_txt) nostr_txt = QTextEdit(self) nostr_txt.setGeometry(20, 300, 450, 170) nostr_txt.setReadOnly(True) nostr_txt.setFrameStyle(QFrame.Shape.NoFrame) nostr_txt.setStyleSheet( f"background: transparent; border: none; color: {text_color}; font-size: 21px;") nostr_txt.setVerticalScrollBarPolicy( Qt.ScrollBarPolicy.ScrollBarAlwaysOff) nostr_txt.setHorizontalScrollBarPolicy( Qt.ScrollBarPolicy.ScrollBarAlwaysOff) nostr_txt.setWordWrapMode( QtGui.QTextOption.WrapMode.WrapAnywhere) nostr_txt.setText(f"Nostr: {n_key}") nostr_txt.show() self.labels.append(nostr_txt) for i, key in enumerate(parameters.keys()): if key == 'browser': browser_value = f"{data_profile.get(key, '')}" split_value = browser_value.split(':', 1) browser_type = split_value[0] browser_version = split_value[1] if len( split_value) > 1 else '' browser_value = f"{browser_type} {browser_version}" if browser_version == '': browser_version = data_profile.get('browser_version', '') browser_value = f"{browser_type} {browser_version}" if connection == 'system-wide' or not browser_value.strip(): base_image = QPixmap() else: base_image = BrowserPage.create_browser_button_image( browser_value, self.btn_path) if base_image.isNull(): fallback_path = os.path.join( self.btn_path, "default_browser_button.png") base_image = BrowserPage.create_browser_button_image( browser_value, fallback_path, True) elif key == 'location': current_value = f"{data_profile.get(key, '')}" image_path = os.path.join( self.btn_path, f"button_{current_value}.png") base_image = QPixmap(image_path) locations = self.connection_manager.get_location_info( current_value) provider = locations.operator.name if locations and hasattr( locations, 'operator') else None fallback_path = os.path.join( self.btn_path, "default_location_button.png") if base_image.isNull(): if locations and hasattr(locations, 'country_name'): location_name = locations.country_name base_image = LocationPage.create_location_button_image( location_name, fallback_path, provider) else: base_image = LocationPage.create_location_button_image( current_value, fallback_path, provider) else: if locations and hasattr(locations, 'country_name'): base_image = LocationPage.create_location_button_image( f'{locations.country_code}_{locations.code}', fallback_path, provider, image_path) else: base_image = LocationPage.create_location_button_image( current_value, fallback_path, provider, image_path) elif key == 'dimentions': current_value = f"{data_profile.get(key, '')}" if current_value != 'None': base_image = ScreenPage.create_resolution_button_image( self, current_value) else: image_path = os.path.join( self.btn_path, f"{data_profile.get(key, '')}_button.png") current_value = data_profile.get(key, '') base_image = QPixmap(image_path) if key == 'dimentions': label = QPushButton(self) label.setGeometry(565, 90 + i * 80, 185, 75) label.setFlat(True) label.setStyleSheet("border: none; background: transparent;") original_icon = QIcon(base_image) label.setIconSize(QSize(185, 75)) label.setCursor(QtCore.Qt.CursorShape.PointingHandCursor) label.clicked.connect(self.show_custom_res_dialog) template_path = os.path.join( self.btn_path, "resolution_template_button.png") template_pixmap = QPixmap(template_path).scaled( 187, 75) if os.path.exists(template_path) else None if not getattr(self, 'res_hint_shown', False) and connection != 'system-wide': self.res_hint_shown = True if template_pixmap: label.setIcon(QIcon(template_pixmap)) else: label.setIcon(QIcon()) hint_label = QLabel("Click here to customize", label) hint_label.setGeometry(15, 0, 155, 75) hint_label.setWordWrap(True) hint_label.setAlignment( QtCore.Qt.AlignmentFlag.AlignCenter) hint_label.setStyleSheet( "color: #00ffff; font-weight: bold; font-size: 16px; background: transparent;") hint_label.setCursor( QtCore.Qt.CursorShape.PointingHandCursor) hint_label.setAttribute( QtCore.Qt.WidgetAttribute.WA_TransparentForMouseEvents) shadow = QGraphicsDropShadowEffect(hint_label) shadow.setBlurRadius(20) shadow.setColor(QColor(0, 255, 255)) shadow.setOffset(0, 0) hint_label.setGraphicsEffect(shadow) def restore(): try: if hint_label and not hint_label.isHidden(): hint_label.hide() label.setIcon(original_icon) except: pass QTimer.singleShot(3500, restore) else: label.setIcon(original_icon) else: label = QLabel(key, self) label.setGeometry(565, 90 + i * 80, 185, 75) label.setPixmap(base_image) label.setScaledContents(True) label.show() self.labels.append(label) try: if key == 'browser': value_index = [item.replace( ':', ' ') for item in parameters[key]].index(browser_value) else: value_index = parameters[key].index(current_value) except ValueError: value_index = 0 prev_button = QPushButton(self) prev_button.setGeometry(535, 90 + i * 80, 30, 75) prev_button.clicked.connect( lambda _, k=key, idx=value_index: self.show_previous_value(k, idx, parameters)) prev_button.show() icon_path = os.path.join(self.btn_path, f"UP_button.png") icon = QPixmap(icon_path) transform = QTransform().rotate(180) rotated_icon = icon.transformed(transform) prev_button.setIcon(QIcon(rotated_icon)) prev_button.setIconSize(prev_button.size()) if (key == 'location' or key == 'browser') and not self.connection_manager.is_synced(): w = prev_button.width() h = prev_button.height() outline_pix = QPixmap(w, h) outline_pix.fill(Qt.GlobalColor.transparent) painter = QPainter(outline_pix) painter.setRenderHint(QPainter.RenderHint.Antialiasing) pen = QtGui.QPen(QColor(0, 255, 0)) pen.setWidth(3) painter.setPen(pen) painter.setBrush(Qt.BrushStyle.NoBrush) left_points = [ QPointF(w*0.65, h*0.15), QPointF(w*0.25, h*0.50), QPointF(w*0.65, h*0.85)] painter.drawPolygon(QtGui.QPolygonF(left_points)) painter.end() prev_button.setIcon(QIcon(outline_pix)) prev_button.setIconSize(prev_button.size()) if (key == 'location' or key == 'browser') and not self.connection_manager.is_synced(): prev_button.setStyleSheet(""" QPushButton { background-color: transparent; border: none; } QPushButton:hover { background-color: rgba(0, 255, 0, 0.1); border-radius: 3px; } QPushButton:pressed { background-color: rgba(0, 255, 0, 0.2); border-radius: 3px; } """) self.buttons.append(prev_button) next_button = QPushButton(self) next_button.setGeometry(750, 90 + i * 80, 30, 75) next_button.clicked.connect( lambda _, k=key, idx=value_index: self.show_next_value(k, idx, parameters)) next_button.show() self.buttons.append(next_button) next_button.setIcon( QIcon(os.path.join(self.btn_path, f"UP_button.png"))) next_button.setIconSize(next_button.size()) if (key == 'location' or key == 'browser') and not self.connection_manager.is_synced(): w = next_button.width() h = next_button.height() outline_pix_r = QPixmap(w, h) outline_pix_r.fill(Qt.GlobalColor.transparent) painter_r = QPainter(outline_pix_r) painter_r.setRenderHint(QPainter.RenderHint.Antialiasing) pen_r = QtGui.QPen(QColor(0, 255, 0)) pen_r.setWidth(3) painter_r.setPen(pen_r) painter_r.setBrush(Qt.BrushStyle.NoBrush) right_points = [ QPointF(w*0.35, h*0.15), QPointF(w*0.75, h*0.50), QPointF(w*0.35, h*0.85)] painter_r.drawPolygon(QtGui.QPolygonF(right_points)) painter_r.end() next_button.setIcon(QIcon(outline_pix_r)) next_button.setIconSize(next_button.size()) if (key == 'location' or key == 'browser') and not self.connection_manager.is_synced(): next_button.setStyleSheet(""" QPushButton { background-color: transparent; border: none; } QPushButton:hover { background-color: rgba(0, 255, 0, 0.1); border-radius: 3px; } QPushButton:pressed { background-color: rgba(0, 255, 0, 0.2); border-radius: 3px; } """) prev_button.setVisible(True) next_button.setVisible(True) if key == 'protocol' or (protocol == 'wireguard' and key == 'connection'): prev_button.setDisabled(True) next_button.setDisabled(True) if connection == 'system-wide' and (key == 'browser' or key == 'dimentions'): prev_button.setVisible(False) next_button.setVisible(False) def on_sync_complete_for_edit_profile(self, available_locations, available_browsers, status, is_tor, locations, all_browsers): if status: self.update_status.update_status('Sync complete.') self.extraccion() else: self.update_status.update_status( 'Sync failed. Please try again later.') def show_previous_value(self, key: str, index: int, parameters: dict) -> None: if key == 'browser' or key == 'location': if not self.connection_manager.is_synced(): self.update_status.update_status('Syncing in progress..') self.update_status.sync() self.update_status.worker_thread.sync_output.connect( self.on_sync_complete_for_edit_profile) return previous_index = (index - 1) % len(parameters[key]) previous_value = parameters[key][previous_index] self.update_temp_value(key, previous_value) def show_next_value(self, key: str, index: int, parameters: dict) -> None: if key == 'browser' or key == 'location': if not self.connection_manager.is_synced(): self.update_status.update_status('Syncing in progress..') self.update_status.sync() self.update_status.worker_thread.sync_output.connect( self.on_sync_complete_for_edit_profile) return next_index = (index + 1) % len(parameters[key]) next_value = parameters[key][next_index] self.update_temp_value(key, next_value) def update_temp_value(self, key: str, new_value: str) -> None: selected_profiles_str = self._selected_profiles_str() if selected_profiles_str not in self.temp_changes: self.temp_changes[selected_profiles_str] = {} self.original_values[selected_profiles_str] = self.data_profile.copy( ) self.temp_changes[selected_profiles_str][key] = new_value self.extraccion() def show_custom_res_dialog(self): dialog = QDialog(self) dialog.setWindowTitle("Custom Resolution") dialog.setFixedSize(300, 150) dialog.setModal(True) dialog.setStyleSheet(""" QDialog { background-color: #2c3e50; border: 2px solid #00ffff; border-radius: 10px; } QLabel { color: white; font-size: 12px; } QLineEdit { background-color: #34495e; color: white; border: 1px solid #00ffff; border-radius: 5px; padding: 5px; font-size: 12px; } QPushButton { background-color: #2c3e50; color: white; border: 2px solid #00ffff; border-radius: 5px; padding: 8px; font-size: 12px; } QPushButton:hover { background-color: #34495e; } """) layout = QVBoxLayout() input_layout = QHBoxLayout() width_label = QLabel("Width:") width_input = QLineEdit() width_input.setPlaceholderText("1920") height_label = QLabel("Height:") height_input = QLineEdit() height_input.setPlaceholderText("1080") input_layout.addWidget(width_label) input_layout.addWidget(width_input) input_layout.addWidget(height_label) input_layout.addWidget(height_input) button_layout = QHBoxLayout() ok_button = QPushButton("OK") cancel_button = QPushButton("Cancel") button_layout.addWidget(cancel_button) button_layout.addWidget(ok_button) layout.addLayout(input_layout) layout.addLayout(button_layout) dialog.setLayout(layout) def validate_and_accept(): try: width = int(width_input.text()) height = int(height_input.text()) if width <= 0 or height <= 0: return host_w = self.custom_window.host_screen_width host_h = self.custom_window.host_screen_height adjusted = False if width > host_w: width = host_w - 50 adjusted = True if height > host_h: height = host_h - 50 adjusted = True if adjusted: QMessageBox.information( dialog, "Notice", "Adjusted to fit host size") self.update_temp_value('dimentions', f"{width}x{height}") dialog.accept() except ValueError: pass ok_button.clicked.connect(validate_and_accept) cancel_button.clicked.connect(dialog.reject) width_input.returnPressed.connect(validate_and_accept) height_input.returnPressed.connect(validate_and_accept) dialog.exec() def has_unsaved_changes(self, profile_str: str) -> bool: return profile_str in self.temp_changes and bool(self.temp_changes[profile_str]) def show_apply_changes_popup(self, selected_profiles_str: str) -> bool: if selected_profiles_str not in self.temp_changes: return False temp_changes = self.temp_changes[selected_profiles_str] current_data = self.original_values[selected_profiles_str] current_browser = f"{current_data.get('browser', '')} {current_data.get('browser_version', '')}" if 'location' in temp_changes and temp_changes['location'] != current_data.get('location'): message = "A new location would require a new subscription code.\nDo you want to proceed with erasing the old one?" elif 'browser' in temp_changes and temp_changes['browser'] != current_browser: message = "Changing the browser would delete all data associated with it. Proceed?" else: return False self.popup = ConfirmationPopup( self, message=message, action_button_text="Continue", cancel_button_text="Cancel" ) self.popup.setWindowModality(Qt.WindowModality.ApplicationModal) self.popup.finished.connect( lambda result: self.handle_apply_changes_response(result)) self.popup.show() return True def show_unsaved_changes_popup(self) -> None: self.popup = ConfirmationPopup( self, message="You have unsaved changes. Do you want to continue?", action_button_text="Continue", cancel_button_text="Cancel" ) self.popup.setWindowModality(Qt.WindowModality.ApplicationModal) self.popup.finished.connect( lambda result: self.handle_unsaved_changes_response(result)) self.popup.show() def _refresh_menu_and_navigate(self): menu_page = self.find_menu_page() if menu_page is not None and hasattr(menu_page, 'refresh_menu_buttons'): menu_page.refresh_menu_buttons() self.custom_window.navigator.navigate("menu") def handle_apply_changes_response(self, result: bool) -> None: if result: self.commit_changes() self._refresh_menu_and_navigate() def handle_unsaved_changes_response(self, result: bool) -> None: if result: self.temp_changes.clear() self._refresh_menu_and_navigate() def go_selected(self) -> None: selected_profiles_str = self._selected_profiles_str() if selected_profiles_str in self.temp_changes and self.temp_changes[selected_profiles_str]: needs_confirmation = self.show_apply_changes_popup( selected_profiles_str) if not needs_confirmation: self.commit_changes() self._refresh_menu_and_navigate() else: self.custom_window.navigator.navigate("menu") def commit_changes(self) -> None: selected_profiles_str = self._selected_profiles_str() if selected_profiles_str in self.temp_changes: for key, new_value in self.temp_changes[selected_profiles_str].items(): self.update_core_profiles(key, new_value) self.temp_changes.pop(selected_profiles_str, None) self.original_values.pop(selected_profiles_str, None) def update_core_profiles(self, key, new_value): profile = ProfileController.get( int(self.update_status.current_profile_id)) self.update_res = False if key == 'dimentions': profile.resolution = new_value self.update_res = True elif key == 'name': profile.name = new_value elif key == 'connection': if new_value == 'tor': profile.connection.code = new_value profile.connection.masked = True elif new_value == 'just proxy': profile.connection.code = 'system' profile.connection.masked = True else: self.update_status.update_status( 'System wide profiles not supported atm') elif key == 'browser': browser_type, browser_version = new_value.split(':', 1) profile.application_version.application_code = browser_type profile.application_version.version_number = browser_version elif key == 'protocol': if self.data_profile.get('connection') == 'system-wide': self.edit_to_session() else: profile.connection.code = 'wireguard' if new_value == 'wireguard' else 'tor' profile.connection.masked = False if new_value == 'wireguard' else True else: location = self.connection_manager.get_location_info(new_value) if location: profile.location.code = location.code profile.location.country_code = location.country_code profile.location.time_zone = location.time_zone profile.subscription = None ProfileController.update(profile) def edit_to_session(self): id = int(self.update_status.current_profile_id) profile = self.data_profile default_app = 'firefox:123.0' default_resolution = '1024x760' location_code = self.connection_manager.get_location_info( profile.get('location')) connection_type = 'tor' profile_data = { 'id': int(id), 'name': profile.get('name'), 'country_code': location_code.country_code, 'code': location_code.code, 'application': default_app, 'connection_type': connection_type, 'resolution': default_resolution, } resume_page = self.find_resume_page() if resume_page: resume_page.handle_core_action_create_profile( 'CREATE_SESSION_PROFILE', profile_data, 'session')