added new wg debugging tool

This commit is contained in:
John 2025-09-19 01:14:43 +01:00
parent 94050228f3
commit 52a4fd8be7

555
gui/__main__.py Normal file → Executable file
View file

@ -895,6 +895,7 @@ class CustomWindow(QMainWindow):
IdPage(self.page_stack, self), IdPage(self.page_stack, self),
TorPage(self.page_stack, self), TorPage(self.page_stack, self),
EditorPage(self.page_stack, self), EditorPage(self.page_stack, self),
FastModePromptPage(self.page_stack, self),
FastRegistrationPage(self.page_stack, self), FastRegistrationPage(self.page_stack, self),
Settings(self.page_stack, self), Settings(self.page_stack, self),
ConnectionPage(self.page_stack, self), ConnectionPage(self.page_stack, self),
@ -949,6 +950,34 @@ class CustomWindow(QMainWindow):
else: else:
return False return False
def has_shown_fast_mode_prompt(self):
flag_file = os.path.join(self.gui_config_home, '.fast-mode-prompted')
return os.path.exists(flag_file)
def mark_fast_mode_prompt_shown(self):
os.makedirs(self.gui_config_home, exist_ok=True)
flag_file = os.path.join(self.gui_config_home, '.fast-mode-prompted')
try:
with open(flag_file, 'w') as f:
f.write('shown')
except Exception as e:
print(f"Error writing fast mode flag: {e}")
def set_fast_mode_enabled(self, enabled):
config = self._load_gui_config()
if config is None:
config = {"logging": {"gui_logging_enabled": False, "log_level": "INFO"}}
if "registrations" not in config:
config["registrations"] = {}
config["registrations"]["fast_registration_enabled"] = bool(enabled)
self._save_gui_config(config)
def navigate_after_profile_created(self):
if not self.has_shown_fast_mode_prompt():
self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(FastModePromptPage)))
else:
self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(MenuPage)))
def enable_marquee(self, text): def enable_marquee(self, text):
self.marquee_text = text + " " self.marquee_text = text + " "
self.marquee_position = 0 self.marquee_position = 0
@ -1015,7 +1044,7 @@ class CustomWindow(QMainWindow):
if isinstance(current_page, MenuPage): if isinstance(current_page, MenuPage):
self.update_status(None) self.update_status(None)
if isinstance(previous_page, (ResumePage, EditorPage, Settings, FastRegistrationPage)): if isinstance(previous_page, (ResumePage, EditorPage, Settings, FastRegistrationPage, FastModePromptPage)):
current_page.eliminacion() current_page.eliminacion()
else: else:
@ -3893,7 +3922,10 @@ class ResumePage(Page):
self.create_core_profiles(new_profile, profile_id) self.create_core_profiles(new_profile, profile_id)
# Restablecer el índice de la página actual al menú principal main = self.update_status
if hasattr(main, 'navigate_after_profile_created'):
main.navigate_after_profile_created()
else:
self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(MenuPage))) self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(MenuPage)))
self.update_status.clear_data() self.update_status.clear_data()
@ -4497,11 +4529,7 @@ class EditorPage(Page):
else: else:
location = self.connection_manager.get_location_info(new_value) location = self.connection_manager.get_location_info(new_value)
if profile.has_wireguard_configuration():
profile.delete_wireguard_configuration()
if profile.has_proxy_configuration():
profile.delete_proxy_configuration()
if location: if location:
profile.location.code = location.code profile.location.code = location.code
@ -4614,7 +4642,8 @@ class Settings(Page):
("Subscriptions", self.show_subscription_page), ("Subscriptions", self.show_subscription_page),
("Create/Edit", self.show_registrations_page), ("Create/Edit", self.show_registrations_page),
("Delete Profile", self.show_delete_page), ("Delete Profile", self.show_delete_page),
("Error Logs", self.show_logs_page) ("Error Logs", self.show_logs_page),
("Debug Help", self.show_debug_page)
] ]
@ -4657,12 +4686,14 @@ class Settings(Page):
self.subscription_page = self.create_subscription_page() self.subscription_page = self.create_subscription_page()
self.logs_page = self.create_logs_page() self.logs_page = self.create_logs_page()
self.delete_page = self.create_delete_page() self.delete_page = self.create_delete_page()
self.debug_page = self.create_debug_page()
self.content_layout.addWidget(self.account_page) self.content_layout.addWidget(self.account_page)
self.content_layout.addWidget(self.wireguard_page) self.content_layout.addWidget(self.wireguard_page)
self.content_layout.addWidget(self.subscription_page) self.content_layout.addWidget(self.subscription_page)
self.content_layout.addWidget(self.logs_page) self.content_layout.addWidget(self.logs_page)
self.content_layout.addWidget(self.delete_page) self.content_layout.addWidget(self.delete_page)
self.content_layout.addWidget(self.debug_page)
self.show_account_page() self.show_account_page()
@ -4751,6 +4782,344 @@ class Settings(Page):
return page return page
def create_debug_page(self):
page = QWidget()
layout = QVBoxLayout(page)
layout.setContentsMargins(20, 20, 20, 20)
layout.setSpacing(15)
title = QLabel("DEBUG HELP")
title.setStyleSheet(f"color: #808080; font-size: 12px; font-weight: bold; {self.font_style}")
layout.addWidget(title)
scroll_area = QScrollArea()
scroll_area.setWidgetResizable(True)
scroll_area.setStyleSheet(f"""
QScrollArea {{
border: none;
background: transparent;
}}
QScrollArea > QWidget > QWidget {{
background: transparent;
}}
""")
scroll_content = QWidget()
scroll_layout = QVBoxLayout(scroll_content)
scroll_layout.setSpacing(15)
app_path = sys.executable if hasattr(sys, 'frozen') else os.path.abspath(__file__)
if hasattr(sys, 'frozen'):
app_dir = os.path.dirname(app_path)
else:
app_dir = os.path.dirname(os.path.dirname(app_path))
app_path_label = QLabel(f"Application Path: {app_path}")
app_path_label.setStyleSheet(f"color: white; font-size: 14px; {self.font_style}")
app_path_label.setWordWrap(True)
scroll_layout.addWidget(app_path_label)
app_dir_label = QLabel(f"Application Directory: {app_dir}")
app_dir_label.setStyleSheet(f"color: white; font-size: 14px; {self.font_style}")
app_dir_label.setWordWrap(True)
scroll_layout.addWidget(app_dir_label)
command_group = QGroupBox("CLI Commands")
command_group.setStyleSheet(f"""
QGroupBox {{
color: white;
font-weight: bold;
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 8px;
padding: 15px;
font-size: 10px;
margin-top: 15px;
{self.font_style}
}}
QGroupBox::title {{
subcontrol-origin: margin;
left: 10px;
padding: 0 5px;
}}
""")
command_layout = QVBoxLayout(command_group)
self.cli_command = QLineEdit()
self.cli_command.setReadOnly(True)
self.cli_command.setText(f"{app_path} --cli profile enable -i 1")
self.cli_command.setStyleSheet(f"""
QLineEdit {{
color: white;
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 4px;
padding: 8px;
font-family: 'Courier New', monospace;
font-size: 12px;
}}
""")
command_layout.addWidget(self.cli_command)
copy_button = QPushButton("Copy Command")
copy_button.setFixedSize(120, 40)
copy_button.setStyleSheet(f"""
QPushButton {{
font-size: 12px;
background: #007AFF;
color: white;
border: none;
border-radius: 5px;
font-weight: bold;
{self.font_style}
}}
QPushButton:hover {{
background: #0056CC;
}}
""")
copy_button.clicked.connect(self.copy_cli_command)
command_layout.addWidget(copy_button)
execute_button = QPushButton("Execute Command")
execute_button.setFixedSize(120, 40)
execute_button.setStyleSheet(f"""
QPushButton {{
font-size: 10px;
background: #4CAF50;
color: white;
border: none;
border-radius: 5px;
font-weight: bold;
{self.font_style}
}}
QPushButton:hover {{
background: #45a049;
}}
""")
execute_button.clicked.connect(self.execute_cli_command)
command_layout.addWidget(execute_button)
scroll_layout.addWidget(command_group)
debug_helper_group = QGroupBox("Debug Helper")
debug_helper_group.setStyleSheet(f"""
QGroupBox {{
color: white;
font-weight: bold;
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 8px;
padding: 15px;
font-size: 10px;
margin-top: 15px;
{self.font_style}
}}
QGroupBox::title {{
subcontrol-origin: margin;
left: 10px;
padding: 0 5px;
}}
""")
debug_helper_layout = QVBoxLayout(debug_helper_group)
profile_label = QLabel("Select System-wide Profile:")
profile_label.setStyleSheet(f"color: white; font-size: 12px; {self.font_style}")
debug_helper_layout.addWidget(profile_label)
self.debug_profile_selector = QComboBox()
self.debug_profile_selector.setStyleSheet(self.get_combobox_style())
self.debug_profile_selector.currentTextChanged.connect(self.on_debug_profile_selected)
debug_helper_layout.addWidget(self.debug_profile_selector)
self.ping_instruction_label = QLabel("")
self.ping_instruction_label.setStyleSheet(f"color: white; font-size: 12px; {self.font_style}")
self.ping_instruction_label.setWordWrap(True)
self.ping_instruction_label.hide()
debug_helper_layout.addWidget(self.ping_instruction_label)
ping_buttons_layout = QHBoxLayout()
self.copy_ping_button = QPushButton("Copy Ping Command")
self.copy_ping_button.setFixedSize(140, 40)
self.copy_ping_button.setStyleSheet(f"""
QPushButton {{
font-size: 12px;
background: #007AFF;
color: white;
border: none;
border-radius: 5px;
font-weight: bold;
{self.font_style}
}}
QPushButton:hover {{
background: #0056CC;
}}
QPushButton:disabled {{
background: #666666;
}}
""")
self.copy_ping_button.clicked.connect(self.copy_ping_command)
self.copy_ping_button.setEnabled(False)
ping_buttons_layout.addWidget(self.copy_ping_button)
self.test_ping_button = QPushButton("Test Ping")
self.test_ping_button.setFixedSize(120, 40)
self.test_ping_button.setStyleSheet(f"""
QPushButton {{
font-size: 12px;
background: #4CAF50;
color: white;
border: none;
border-radius: 5px;
font-weight: bold;
{self.font_style}
}}
QPushButton:hover {{
background: #45a049;
}}
QPushButton:disabled {{
background: #666666;
}}
""")
self.test_ping_button.clicked.connect(self.test_ping_connection)
self.test_ping_button.setEnabled(False)
ping_buttons_layout.addWidget(self.test_ping_button)
debug_helper_layout.addLayout(ping_buttons_layout)
self.ping_result_label = QLabel("")
self.ping_result_label.setStyleSheet(f"color: white; font-size: 12px; font-weight: bold; {self.font_style}")
self.ping_result_label.setWordWrap(True)
self.ping_result_label.hide()
debug_helper_layout.addWidget(self.ping_result_label)
self.update_debug_profile_list()
scroll_layout.addWidget(debug_helper_group)
scroll_area.setWidget(scroll_content)
layout.addWidget(scroll_area)
return page
def copy_cli_command(self):
clipboard = QApplication.clipboard()
clipboard.setText(self.cli_command.text())
self.update_status.update_status("CLI command copied to clipboard")
def execute_cli_command(self):
try:
command = self.cli_command.text().split()
subprocess.Popen(command)
self.update_status.update_status("CLI command executed")
except Exception as e:
self.update_status.update_status(f"Error executing command: {str(e)}")
def update_debug_profile_list(self):
self.debug_profile_selector.clear()
profiles = ProfileController.get_all()
system_profiles = {pid: profile for pid, profile in profiles.items() if isinstance(profile, SystemProfile)}
if system_profiles:
for profile_id, profile in system_profiles.items():
self.debug_profile_selector.addItem(f"Profile {profile_id}: {profile.name}", profile_id)
else:
self.debug_profile_selector.addItem("No system-wide profiles found", None)
def on_debug_profile_selected(self, text):
profile_id = self.debug_profile_selector.currentData()
if profile_id is None:
self.ping_instruction_label.hide()
self.copy_ping_button.setEnabled(False)
self.test_ping_button.setEnabled(False)
self.ping_result_label.hide()
return
profile = ProfileController.get(profile_id)
if profile and isinstance(profile, SystemProfile):
ip_address = self.extract_endpoint_ip(profile)
if ip_address:
self.ping_instruction_label.setText(f"Step 1, Can you Ping it? Copy-paste the command below into your terminal. This VPN Node's IP address is {ip_address}")
self.ping_instruction_label.show()
self.copy_ping_button.setEnabled(True)
self.test_ping_button.setEnabled(True)
self.ping_result_label.hide()
else:
self.ping_instruction_label.setText("Could not extract IP address from WireGuard configuration")
self.ping_instruction_label.show()
self.copy_ping_button.setEnabled(False)
self.test_ping_button.setEnabled(False)
self.ping_result_label.hide()
def extract_endpoint_ip(self, profile):
try:
profile_path = Constants.HV_PROFILE_CONFIG_HOME + f'/{profile.id}'
wg_conf_path = f'{profile_path}/wg.conf.bak'
if not os.path.exists(wg_conf_path):
return None
with open(wg_conf_path, 'r') as f:
content = f.read()
for line in content.split('\n'):
if line.strip().startswith('Endpoint = '):
endpoint = line.strip().split(' = ')[1]
ip_address = endpoint.split(':')[0]
return ip_address
return None
except Exception:
return None
def copy_ping_command(self):
profile_id = self.debug_profile_selector.currentData()
if profile_id is None:
return
profile = ProfileController.get(profile_id)
if profile and isinstance(profile, SystemProfile):
ip_address = self.extract_endpoint_ip(profile)
if ip_address:
ping_command = f"ping {ip_address}"
clipboard = QApplication.clipboard()
clipboard.setText(ping_command)
self.update_status.update_status("Ping command copied to clipboard")
def test_ping_connection(self):
profile_id = self.debug_profile_selector.currentData()
if profile_id is None:
return
profile = ProfileController.get(profile_id)
if profile and isinstance(profile, SystemProfile):
ip_address = self.extract_endpoint_ip(profile)
if ip_address:
self.test_ping_button.setEnabled(False)
self.ping_result_label.setText("Testing ping...")
self.ping_result_label.setStyleSheet(f"color: #FFA500; font-size: 12px; font-weight: bold; {self.font_style}")
self.ping_result_label.show()
def ping_test():
try:
if sys.platform == "win32":
result = subprocess.run(['ping', '-n', '4', ip_address],
capture_output=True, text=True, timeout=10)
else:
result = subprocess.run(['ping', '-c', '4', ip_address],
capture_output=True, text=True, timeout=10)
if result.returncode == 0:
self.ping_result_label.setText("✅ Ping successful - Connection is working!")
self.ping_result_label.setStyleSheet(f"color: #4CAF50; font-size: 12px; font-weight: bold; {self.font_style}")
else:
self.ping_result_label.setText("❌ Ping failed - Connection issue detected")
self.ping_result_label.setStyleSheet(f"color: #F44336; font-size: 12px; font-weight: bold; {self.font_style}")
except subprocess.TimeoutExpired:
self.ping_result_label.setText("❌ Ping timeout - Connection issue detected")
self.ping_result_label.setStyleSheet(f"color: #F44336; font-size: 12px; font-weight: bold; {self.font_style}")
except Exception as e:
self.ping_result_label.setText(f"❌ Ping error: {str(e)}")
self.ping_result_label.setStyleSheet(f"color: #F44336; font-size: 12px; font-weight: bold; {self.font_style}")
finally:
self.test_ping_button.setEnabled(True)
threading.Thread(target=ping_test, daemon=True).start()
def on_profile_selected(self, button): def on_profile_selected(self, button):
self.delete_button.setEnabled(True) self.delete_button.setEnabled(True)
self.selected_profile_id = self.profile_buttons.id(button) self.selected_profile_id = self.profile_buttons.id(button)
@ -4903,6 +5272,10 @@ class Settings(Page):
self.content_layout.setCurrentWidget(self.logs_page) self.content_layout.setCurrentWidget(self.logs_page)
self.update_button_states(4) self.update_button_states(4)
def show_debug_page(self):
self.content_layout.setCurrentWidget(self.debug_page)
self.update_button_states(5)
def update_button_states(self, active_index): def update_button_states(self, active_index):
for i, btn in enumerate(self.menu_buttons): for i, btn in enumerate(self.menu_buttons):
btn.setChecked(i == active_index) btn.setChecked(i == active_index)
@ -4975,6 +5348,50 @@ class Settings(Page):
] ]
for i, (label, key) in enumerate(info_items): for i, (label, key) in enumerate(info_items):
if key == "billing_code":
billing_container = QWidget()
billing_layout = QVBoxLayout(billing_container)
billing_layout.setContentsMargins(0, 0, 0, 0)
billing_layout.setSpacing(5)
stat_widget = self.create_stat_widget(label, "N/A")
billing_layout.addWidget(stat_widget)
copy_button = QPushButton("Copy")
copy_button.setFixedSize(60, 30)
copy_button.setStyleSheet(f"""
QPushButton {{
background: #007AFF;
color: white;
border: none;
border-radius: 4px;
font-size: 11px;
font-weight: bold;
{self.font_style}
}}
QPushButton:hover {{
background: #0056CC;
}}
""")
copy_button.clicked.connect(lambda: self.copy_billing_code())
billing_layout.addWidget(copy_button)
row, col = divmod(i, 2)
subscription_layout.addWidget(billing_container, row, col)
old_label = stat_widget.findChild(QLabel, "value_label")
if old_label:
old_label.setParent(None)
old_label.deleteLater()
value_label = ClickableValueLabel("N/A", stat_widget)
value_label.setObjectName("value_label")
value_label.setStyleSheet(f"color: #00ffff; font-size: 12px; font-family: 'Retro Gaming', sans-serif;")
value_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
stat_widget.layout().insertWidget(0, value_label)
self.subscription_info[key] = value_label
else:
stat_widget = self.create_stat_widget(label, "N/A") stat_widget = self.create_stat_widget(label, "N/A")
row, col = divmod(i, 2) row, col = divmod(i, 2)
subscription_layout.addWidget(stat_widget, row, col) subscription_layout.addWidget(stat_widget, row, col)
@ -4994,7 +5411,7 @@ class Settings(Page):
layout.addWidget(subscription_group) layout.addWidget(subscription_group)
clipboard_hint = QLabel("💡 Click on the billing code to copy it to clipboard") clipboard_hint = QLabel("💡 Click on the billing code or use the Copy button to copy it to clipboard")
clipboard_hint.setStyleSheet(f"color: #666666; font-size: 11px; font-style: italic; {self.font_style}") clipboard_hint.setStyleSheet(f"color: #666666; font-size: 11px; font-style: italic; {self.font_style}")
clipboard_hint.setAlignment(Qt.AlignmentFlag.AlignCenter) clipboard_hint.setAlignment(Qt.AlignmentFlag.AlignCenter)
layout.addWidget(clipboard_hint) layout.addWidget(clipboard_hint)
@ -5032,6 +5449,16 @@ class Settings(Page):
for label in self.subscription_info.values(): for label in self.subscription_info.values():
label.setText("N/A") label.setText("N/A")
def copy_billing_code(self):
if "billing_code" in self.subscription_info:
billing_code = self.subscription_info["billing_code"].text()
if billing_code and billing_code != "N/A":
clipboard = QApplication.clipboard()
clipboard.setText(billing_code)
self.update_status.update_status("Billing code copied to clipboard")
else:
self.update_status.update_status("No billing code available to copy")
def showEvent(self, event): def showEvent(self, event):
super().showEvent(event) super().showEvent(event)
@ -5058,6 +5485,10 @@ class Settings(Page):
self.logs_page = self.create_logs_page() self.logs_page = self.create_logs_page()
self.content_layout.addWidget(self.logs_page) self.content_layout.addWidget(self.logs_page)
self.content_layout.removeWidget(self.debug_page)
self.debug_page = self.create_debug_page()
self.content_layout.addWidget(self.debug_page)
self.content_layout.setCurrentIndex(current_index) self.content_layout.setCurrentIndex(current_index)
if self.content_layout.currentWidget() == self.subscription_page: if self.content_layout.currentWidget() == self.subscription_page:
@ -5252,12 +5683,14 @@ class Settings(Page):
self.registrations_page = self.create_registrations_page() self.registrations_page = self.create_registrations_page()
self.logs_page = self.create_logs_page() self.logs_page = self.create_logs_page()
self.delete_page = self.create_delete_page() self.delete_page = self.create_delete_page()
self.debug_page = self.create_debug_page()
self.content_layout.addWidget(self.account_page) self.content_layout.addWidget(self.account_page)
self.content_layout.addWidget(self.subscription_page) self.content_layout.addWidget(self.subscription_page)
self.content_layout.addWidget(self.registrations_page) self.content_layout.addWidget(self.registrations_page)
self.content_layout.addWidget(self.logs_page) self.content_layout.addWidget(self.logs_page)
self.content_layout.addWidget(self.delete_page) self.content_layout.addWidget(self.delete_page)
self.content_layout.addWidget(self.debug_page)
self.show_account_page() self.show_account_page()
@ -6706,6 +7139,32 @@ class FastRegistrationPage(Page):
self.initialize_default_selections() self.initialize_default_selections()
def initialize_default_selections(self):
if not self.selected_values['location']:
locations = self.connection_manager.get_location_list()
if locations:
random_index = random.randint(0, len(locations) - 1)
self.selected_values['location'] = locations[random_index]
if not self.selected_values['browser']:
browsers = self.connection_manager.get_browser_list()
if browsers:
random_index = random.randint(0, len(browsers) - 1)
self.selected_values['browser'] = browsers[random_index]
def get_next_available_profile_id(self) -> int:
profiles = ProfileController.get_all()
if not profiles:
return 1
existing_ids = sorted(profiles.keys())
for i in range(1, max(existing_ids) + 2):
if i not in existing_ids:
return i
return 1
def showEvent(self, event): def showEvent(self, event):
super().showEvent(event) super().showEvent(event)
self.initialize_default_selections() self.initialize_default_selections()
@ -6729,6 +7188,7 @@ class FastRegistrationPage(Page):
self.create_location_section() self.create_location_section()
self.create_browser_section() self.create_browser_section()
self.create_resolution_section() self.create_resolution_section()
self.update_ui_state_for_connection()
def create_protocol_section(self): def create_protocol_section(self):
label = QLabel("Protocol", self) label = QLabel("Protocol", self)
@ -6907,6 +7367,17 @@ class FastRegistrationPage(Page):
next_button.setIconSize(next_button.size()) next_button.setIconSize(next_button.size())
self.buttons.append(next_button) self.buttons.append(next_button)
def update_ui_state_for_connection(self):
is_system_wide = self.selected_values['connection'] == 'system-wide'
for button in self.buttons:
if hasattr(button, 'geometry'):
button_geometry = button.geometry()
if button_geometry.y() == 350:
if button_geometry.x() in [115, 340, 400, 625]:
button.setEnabled(not is_system_wide)
def show_previous_value(self, key): def show_previous_value(self, key):
if key == 'protocol': if key == 'protocol':
protocols = ['wireguard', 'hidetor'] protocols = ['wireguard', 'hidetor']
@ -6925,6 +7396,7 @@ class FastRegistrationPage(Page):
current_index = connections.index(self.selected_values[key]) current_index = connections.index(self.selected_values[key])
previous_index = (current_index - 1) % len(connections) previous_index = (current_index - 1) % len(connections)
self.selected_values[key] = connections[previous_index] self.selected_values[key] = connections[previous_index]
self.update_ui_state_for_connection()
elif key == 'location': elif key == 'location':
locations = self.connection_manager.get_location_list() locations = self.connection_manager.get_location_list()
if locations and self.selected_values[key] in locations: if locations and self.selected_values[key] in locations:
@ -6967,6 +7439,7 @@ class FastRegistrationPage(Page):
current_index = connections.index(self.selected_values[key]) current_index = connections.index(self.selected_values[key])
next_index = (current_index + 1) % len(connections) next_index = (current_index + 1) % len(connections)
self.selected_values[key] = connections[next_index] self.selected_values[key] = connections[next_index]
self.update_ui_state_for_connection()
elif key == 'location': elif key == 'location':
locations = self.connection_manager.get_location_list() locations = self.connection_manager.get_location_list()
if locations and self.selected_values[key] in locations: if locations and self.selected_values[key] in locations:
@ -7048,6 +7521,9 @@ class FastRegistrationPage(Page):
resume_page = self.find_resume_page() resume_page = self.find_resume_page()
if resume_page: if resume_page:
if profile_data['connection'] == 'system-wide':
resume_page.handle_core_action_create_profile('CREATE_SYSTEM_PROFILE', profile_data_for_resume, 'system')
else:
resume_page.handle_core_action_create_profile('CREATE_SESSION_PROFILE', profile_data_for_resume, 'session') resume_page.handle_core_action_create_profile('CREATE_SESSION_PROFILE', profile_data_for_resume, 'session')
def create_tor_profile(self, profile_data): def create_tor_profile(self, profile_data):
@ -7082,6 +7558,69 @@ class FastRegistrationPage(Page):
return page return page
return None return None
class FastModePromptPage(Page):
def __init__(self, page_stack, main_window):
super().__init__("FastModePrompt", page_stack, main_window)
self.page_stack = page_stack
self.update_status = main_window
self.title.setGeometry(500, 40, 350, 40)
self.title.setText("Quick Setup Option")
self.button_back.setVisible(False)
self.button_apply.setVisible(False)
container = QWidget(self)
container.setGeometry(QtCore.QRect(80, 100, 640, 360))
v = QVBoxLayout(container)
v.setContentsMargins(0, 0, 0, 0)
v.setSpacing(20)
large_text = QLabel("Would you like to switch to convenient \"fast mode\" for profile creation going forward? (recommended)")
large_text.setWordWrap(True)
large_text.setStyleSheet("color: white; font-size: 18px;")
large_text.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
v.addWidget(large_text)
buttons_row = QWidget()
h = QHBoxLayout(buttons_row)
h.setContentsMargins(0, 0, 0, 0)
h.setSpacing(20)
yes_btn = QPushButton("Yes Fast Mode")
yes_btn.setCursor(QtCore.Qt.CursorShape.PointingHandCursor)
yes_btn.setFixedSize(240, 56)
yes_btn.setStyleSheet("background-color: #27ae60; color: white; font-weight: bold; font-size: 16px; border: none; border-radius: 6px;")
yes_btn.clicked.connect(self.choose_yes)
no_btn = QPushButton("No Keep This")
no_btn.setCursor(QtCore.Qt.CursorShape.PointingHandCursor)
no_btn.setFixedSize(160, 42)
no_btn.setStyleSheet("background-color: #c0392b; color: white; font-size: 14px; border: none; border-radius: 6px;")
no_btn.clicked.connect(self.choose_no)
h.addStretch()
h.addWidget(yes_btn)
h.addWidget(no_btn)
h.addStretch()
v.addWidget(buttons_row)
small_text = QLabel("You can toggle this anytime in the \"Options\" Menu, under \"Create/Edit\"")
small_text.setWordWrap(True)
small_text.setStyleSheet("color: #999999; font-size: 12px;")
small_text.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
v.addWidget(small_text)
def finalize(self):
self.update_status.mark_fast_mode_prompt_shown()
self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(MenuPage)))
def choose_yes(self):
self.update_status.set_fast_mode_enabled(True)
self.finalize()
def choose_no(self):
self.update_status.set_fast_mode_enabled(False)
self.finalize()
def initialize_default_selections(self): def initialize_default_selections(self):
if not self.selected_values['location']: if not self.selected_values['location']:
locations = self.connection_manager.get_location_list() locations = self.connection_manager.get_location_list()