forked from Support/sp-hydra-veil-gui
630 lines
28 KiB
Python
Executable file
630 lines
28 KiB
Python
Executable file
import functools
|
|
import os
|
|
from itertools import chain
|
|
|
|
from PyQt6 import QtCore, QtGui
|
|
from PyQt6.QtCore import Qt, QSize, pyqtSlot
|
|
from PyQt6.QtGui import QIcon, QPainter, QPixmap
|
|
from PyQt6.QtWidgets import (
|
|
QApplication, QButtonGroup, QFrame, QHBoxLayout, QLabel, QLineEdit,
|
|
QMessageBox, QPushButton, QScrollArea, QTextEdit, QVBoxLayout, QWidget,
|
|
)
|
|
|
|
from gui.v2.actions.menu_profiles import find_verification_icon, get_profile_details, load_menu_profiles, menu_icons
|
|
from gui.v2.actions.menu_tasks import (
|
|
continue_menu_task, create_profile as create_profile_action,
|
|
delete_profile as delete_profile_action, disable_profile as disable_profile_action,
|
|
download_update, edit_profile as edit_profile_action, enable_profile as enable_profile_action,
|
|
)
|
|
from gui.v2.actions.menu_results import MenuResult
|
|
from gui.v2.ui.pages.Page import Page
|
|
from gui.v2.ui.pages.location_verification_page import LocationVerificationPage
|
|
from gui.v2.ui.styles.styles import SCROLLBAR_CYAN_QSS
|
|
from gui.v2.ui.popups.confirmation_popup import ConfirmationPopup
|
|
from gui.v2.ui.popups.endpoint_verification_popup import EndpointVerificationPopup
|
|
from gui.v2.ui.popups.ticket_data_loss_popup import TicketDataLossPopup
|
|
|
|
|
|
class MenuPage(Page):
|
|
def __init__(self, page_stack=None, main_window=None, parent=None):
|
|
super().__init__("Menu", page_stack, main_window, parent)
|
|
self.main_window = main_window
|
|
self.connection_manager = main_window.connection_manager
|
|
self.btn_path = main_window.btn_path
|
|
self.page_stack = page_stack
|
|
self.profile_info = {}
|
|
self.additional_labels = []
|
|
self.update_status = main_window
|
|
self.title.setGeometry(400, 40, 380, 30)
|
|
self.title.setText("Load Profile")
|
|
|
|
self.scroll_area = QScrollArea(self)
|
|
self.scroll_area.setGeometry(420, 80, 370, 350)
|
|
self.scroll_area.setWidgetResizable(True)
|
|
self.scroll_area.setHorizontalScrollBarPolicy(
|
|
Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
|
self.scroll_area.setVerticalScrollBarPolicy(
|
|
Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
|
self.scroll_area.setStyleSheet(SCROLLBAR_CYAN_QSS)
|
|
|
|
self.scroll_widget = QWidget()
|
|
self.scroll_widget.setStyleSheet("background-color: transparent;")
|
|
self.scroll_area.setWidget(self.scroll_widget)
|
|
|
|
self.not_connected_profile = os.path.join(
|
|
self.btn_path, "button_profile.png")
|
|
self.connected_profile = os.path.join(
|
|
self.btn_path, "button_session_profile.png")
|
|
self.system_wide_connected_profile = os.path.join(
|
|
self.btn_path, "button_system_profile.png")
|
|
self.connected_tor_profile = os.path.join(
|
|
self.btn_path, "button_session_tor.png")
|
|
self.worker = None
|
|
self.reverse_id = None
|
|
self._task_busy = False
|
|
self.button_states = {}
|
|
self.profile_button_map = {}
|
|
self.font_style = f"font-family: '{main_window.open_sans_family}';" if main_window.open_sans_family else ""
|
|
|
|
self.create_interface_elements()
|
|
|
|
def showEvent(self, event):
|
|
super().showEvent(event)
|
|
self._set_verification_icons_enabled()
|
|
|
|
def _set_verification_icons_enabled(self):
|
|
parents = filter(None, (button.parent() for button in getattr(self, 'buttons', [])))
|
|
icons = chain.from_iterable(parent.findChildren(QPushButton) for parent in parents)
|
|
verification_icons = filter(
|
|
lambda icon: icon.geometry().width() == 20 and icon.geometry().height() == 20,
|
|
icons,
|
|
)
|
|
for icon in verification_icons:
|
|
icon.setEnabled(self.connection_manager.is_synced())
|
|
|
|
def on_update_check_finished(self):
|
|
reply = QMessageBox.question(self, 'Update Available',
|
|
'An update is available. Would you like to download it?',
|
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
|
|
if reply == QMessageBox.StandardButton.Yes:
|
|
self.worker = download_update(self.handle_task_result)
|
|
else:
|
|
self.update_status.update_status('Update canceled')
|
|
|
|
def create_interface_elements(self):
|
|
button_definitions = {
|
|
"create_profile": (self.create_prof, (410, 440, 110, 60), True, True),
|
|
"edit_profile": (self.edit_prof, (540, 440, 110, 60), False, True),
|
|
"launch": (self.connect, (0, 440, 185, 63), False, False),
|
|
"disconnect": (self.disconnect, (200, 433, 185, 73), True, False),
|
|
"disconnect_system_wide": (self.disconnect, (200, 433, 185, 73), True, False),
|
|
"just": (self.connect, (200, 433, 185, 73), False, False),
|
|
"just_session": (self.connect, (200, 433, 185, 73), False, True),
|
|
"settings": (self.settings_gui, (670, 440, 110, 60), True, True),
|
|
}
|
|
buttons = {}
|
|
for icon_name, (function, position, enabled, visible) in button_definitions.items():
|
|
boton = QPushButton(self)
|
|
boton.setGeometry(QtCore.QRect(*position))
|
|
boton.setObjectName("create_edit_settings_buttons")
|
|
icon = QtGui.QIcon(os.path.join(self.btn_path, f"{icon_name}.png"))
|
|
boton.setIcon(icon)
|
|
boton.setIconSize(boton.size())
|
|
boton.clicked.connect(functools.partial(function))
|
|
boton.setEnabled(enabled)
|
|
boton.setVisible(visible)
|
|
buttons[icon_name] = boton
|
|
|
|
button_attributes = {
|
|
"disconnect_button": "disconnect",
|
|
"boton_launch": "launch",
|
|
"boton_create": "create_profile",
|
|
"boton_edit": "edit_profile",
|
|
"boton_just": "just",
|
|
"boton_just_session": "just_session",
|
|
"connect_button": "just_session",
|
|
"disconnect_system_wide_button": "disconnect_system_wide",
|
|
"settings_button": "settings",
|
|
}
|
|
self.__dict__.update({attribute: buttons[name] for attribute, name in button_attributes.items()})
|
|
|
|
self.refresh_menu_buttons()
|
|
|
|
def _make_confirmation_popup(self, message, button_text='Proceed'):
|
|
popup = ConfirmationPopup(
|
|
self, message=message, action_button_text=button_text, cancel_button_text="Cancel")
|
|
popup.setWindowModality(Qt.WindowModality.ApplicationModal)
|
|
return popup
|
|
|
|
def delete_profile(self):
|
|
self._set_task_busy(True)
|
|
self.worker = delete_profile_action(self.reverse_id, self.handle_task_result)
|
|
|
|
def refresh_profiles_data(self):
|
|
self.refresh_menu_buttons()
|
|
|
|
def refresh_menu_buttons(self, state_change=None):
|
|
menu_data = load_menu_profiles(
|
|
getattr(self.update_status, 'gui_config_file', None),
|
|
self.update_status.update_status, self.reverse_id, state_change,
|
|
)
|
|
self.profiles_data = menu_data["display_profiles"]
|
|
self.profile_info = self.profiles_data
|
|
self.number_of_profiles = len(self.profiles_data)
|
|
self.connection_manager.set_connected_profiles(menu_data["enabled_kinds"])
|
|
icon_paths = {"session_tor": self.connected_tor_profile,
|
|
"session": self.connected_profile, "system": self.system_wide_connected_profile}
|
|
self.button_states = {profile_id: icon_paths[kind] for profile_id, kind in menu_data["enabled_kinds"].items()}
|
|
self.update_status.update_image(appearance_value=menu_data["background"])
|
|
for button in getattr(self, 'buttons', []):
|
|
button.parent().deleteLater()
|
|
if hasattr(self, 'button_group'):
|
|
self.button_group.deleteLater()
|
|
self.profile_button_map.clear()
|
|
self.button_group = QButtonGroup(self)
|
|
self.buttons = []
|
|
for profile_name, profile_value in self.profiles_data.items():
|
|
self.create_profile_widget(profile_name, profile_value)
|
|
self.update_scroll_widget_size()
|
|
if menu_data["selected_details"] is not None:
|
|
self._render_profile_details(menu_data["selected_details"])
|
|
return
|
|
self.clear_profile_details()
|
|
|
|
def update_scroll_widget_size(self):
|
|
if self.number_of_profiles == 0:
|
|
self.scroll_widget.setFixedSize(370, 0)
|
|
return
|
|
|
|
rows = (self.number_of_profiles + 1) // 2
|
|
height = rows * 120
|
|
self.scroll_widget.setFixedSize(370, height)
|
|
|
|
def clear_profile_details(self):
|
|
for label in self.additional_labels:
|
|
label.deleteLater()
|
|
self.additional_labels.clear()
|
|
self.selected_profiles.clear()
|
|
self.selected_wireguard.clear()
|
|
self.selected_residential.clear()
|
|
self.update_status.current_profile_id = None
|
|
self.current_profile_location = None
|
|
self.reverse_id = None
|
|
self.boton_edit.setEnabled(False)
|
|
self.boton_launch.setEnabled(False)
|
|
self.boton_just.setVisible(False)
|
|
self.boton_just_session.setVisible(False)
|
|
self.disconnect_button.setVisible(False)
|
|
self.disconnect_system_wide_button.setVisible(False)
|
|
if not hasattr(self, 'button_group'):
|
|
return
|
|
self.button_group.setExclusive(False)
|
|
for button in self.buttons:
|
|
button.setChecked(False)
|
|
self.button_group.setExclusive(True)
|
|
|
|
def create_profile_widget(self, key, value):
|
|
profile_id = value['id']
|
|
|
|
parent_label = self.create_parent_label(profile_id)
|
|
button = self.create_profile_button(parent_label, profile_id, key)
|
|
|
|
self.profile_button_map[profile_id] = button
|
|
|
|
self.create_profile_name_label(parent_label, value["name"])
|
|
self.create_profile_icons(parent_label, value)
|
|
|
|
def create_parent_label(self, profile_id):
|
|
parent_label = QLabel(self.scroll_widget)
|
|
profile_list = list(self.profiles_data.keys())
|
|
index = profile_list.index(f'Profile_{profile_id}')
|
|
row, column = divmod(index, 2)
|
|
|
|
parent_label.setGeometry(column * 179, row * 120, 175, 100)
|
|
parent_label.setVisible(True)
|
|
return parent_label
|
|
|
|
def create_profile_button(self, parent_label, profile_id, key):
|
|
button = QPushButton(parent_label)
|
|
button.setGeometry(0, 0, 175, 60)
|
|
button.setStyleSheet("""
|
|
QPushButton {
|
|
background-color: transparent;
|
|
border: none;
|
|
}
|
|
QPushButton:hover {
|
|
background-color: rgba(200, 200, 200, 50);
|
|
}
|
|
QPushButton:checked {
|
|
background-color: rgba(200, 200, 200, 80);
|
|
}
|
|
""")
|
|
|
|
icon = QIcon(self.button_states.get(
|
|
profile_id, self.not_connected_profile))
|
|
button.setIcon(icon)
|
|
button.setIconSize(QtCore.QSize(175, 60))
|
|
|
|
button.show()
|
|
button.setCheckable(True)
|
|
self.button_group.addButton(button)
|
|
self.buttons.append(button)
|
|
|
|
button.clicked.connect(
|
|
lambda checked, pid=profile_id: self.print_profile_details(f"Profile_{pid}"))
|
|
|
|
return button
|
|
|
|
def create_profile_name_label(self, parent_label, name):
|
|
child_label = QLabel(parent_label)
|
|
child_label.setGeometry(0, 65, 175, 30)
|
|
child_label.setText(str(name or "Unnamed Profile"))
|
|
child_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
child_label.setAttribute(
|
|
Qt.WidgetAttribute.WA_TransparentForMouseEvents)
|
|
child_label.show()
|
|
|
|
def create_profile_icons(self, parent_label, value):
|
|
for index, icon in enumerate(menu_icons(self.btn_path, value)):
|
|
child_label = QLabel(parent_label)
|
|
child_label.setObjectName("label_profiles")
|
|
child_label.setGeometry(3 + index * 60, 5, 50, 50)
|
|
child_label.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents)
|
|
child_label.setStyleSheet("background-color: rgba(128, 128, 128, 0.5); border-radius: 25px;")
|
|
pixmap = self._load_profile_icon_pixmap(icon["path"], icon["kind"])
|
|
child_label.setPixmap(self._add_browser_warning(pixmap, icon["warning"]))
|
|
child_label.show()
|
|
|
|
def _load_profile_icon_pixmap(self, image_path, label_name):
|
|
pixmap = QPixmap(image_path)
|
|
fallback_names = {
|
|
'location': 'default_location_mini.png',
|
|
'browser': 'default_browser_mini.png',
|
|
}
|
|
fallback_name = fallback_names.get(label_name)
|
|
if not pixmap.isNull() or fallback_name is None:
|
|
return pixmap
|
|
|
|
pixmap = QPixmap(os.path.join(self.btn_path, fallback_name))
|
|
if not pixmap.isNull():
|
|
return pixmap
|
|
|
|
placeholder = QPixmap(50, 50)
|
|
placeholder.fill(QtGui.QColor(200, 200, 200))
|
|
return placeholder
|
|
|
|
def _add_browser_warning(self, pixmap, needs_warning):
|
|
if not needs_warning:
|
|
return pixmap
|
|
painter = QPainter(pixmap)
|
|
painter.drawPixmap(pixmap.width() - 22, pixmap.height() - 21,
|
|
QPixmap(os.path.join(self.btn_path, 'warning.png')))
|
|
painter.end()
|
|
return pixmap
|
|
|
|
def create_verification_widget(self, values):
|
|
verification_widget = QWidget(self)
|
|
verification_widget.setGeometry(0, 90, 400, 300)
|
|
verification_widget.setStyleSheet("background: transparent;")
|
|
|
|
verification_layout = QVBoxLayout(verification_widget)
|
|
verification_layout.setContentsMargins(20, 20, 20, 20)
|
|
verification_layout.setSpacing(15)
|
|
|
|
for label, full_value, value in values:
|
|
container = QWidget()
|
|
container.setStyleSheet("background: transparent;")
|
|
container_layout = QHBoxLayout(container)
|
|
container_layout.setContentsMargins(0, 0, 0, 0)
|
|
container_layout.setSpacing(10)
|
|
|
|
label_widget = QLabel(label + ":")
|
|
label_widget.setStyleSheet(
|
|
f"color: white; font-size: 12px; {self.font_style}")
|
|
label_widget.setMinimumWidth(120)
|
|
container_layout.addWidget(label_widget)
|
|
|
|
value_widget = QLineEdit()
|
|
value_widget.setReadOnly(True)
|
|
|
|
value_widget.setText(value)
|
|
value_widget.setCursorPosition(0)
|
|
value_widget.setStyleSheet(f"""
|
|
QLineEdit {{
|
|
color: white;
|
|
background: transparent;
|
|
border: none;
|
|
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
|
|
padding: 5px 0px;
|
|
font-size: 12px;
|
|
{self.font_style}
|
|
}}
|
|
""")
|
|
container_layout.addWidget(value_widget, 1)
|
|
|
|
checkmark_widget = QLabel("✓")
|
|
checkmark_widget.setStyleSheet(
|
|
f"color: #4CAF50; font-size: 20px; font-weight: bold; {self.font_style}")
|
|
checkmark_widget.setFixedSize(20, 20)
|
|
checkmark_widget.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
checkmark_widget.setVisible(bool(value and value != "N/A"))
|
|
container_layout.addWidget(checkmark_widget)
|
|
|
|
copy_button = QPushButton()
|
|
copy_button.setIcon(
|
|
QIcon(os.path.join(self.btn_path, "paste_button.png")))
|
|
copy_button.setIconSize(QSize(24, 24))
|
|
copy_button.setFixedSize(30, 30)
|
|
copy_button.setStyleSheet(f"""
|
|
QPushButton {{
|
|
background: transparent;
|
|
border: none;
|
|
}}
|
|
QPushButton:hover {{
|
|
background: rgba(255, 255, 255, 0.1);
|
|
border-radius: 4px;
|
|
}}
|
|
""")
|
|
|
|
copy_button.clicked.connect(
|
|
lambda checked=False, val=full_value: self.copy_verification_value(val))
|
|
container_layout.addWidget(copy_button)
|
|
|
|
verification_layout.addWidget(container)
|
|
|
|
verification_widget.show()
|
|
return verification_widget
|
|
|
|
def copy_verification_value(self, value):
|
|
if value and value != "N/A":
|
|
clipboard = QApplication.clipboard()
|
|
clipboard.setText(value)
|
|
self.update_status.update_status(
|
|
"Verification value copied to clipboard")
|
|
|
|
def print_profile_details(self, profile_name):
|
|
summary = self.profile_info.get(profile_name)
|
|
if summary is None:
|
|
self.clear_profile_details()
|
|
return
|
|
details = get_profile_details(summary["id"], summary,
|
|
self.connection_manager.is_profile_connected(summary["id"]),
|
|
self.update_status.update_status)
|
|
self._render_profile_details(details)
|
|
|
|
def _render_profile_details(self, details):
|
|
self.reverse_id = details["id"]
|
|
self.update_status.current_profile_id = self.reverse_id
|
|
self.current_profile_location = details["location"]
|
|
target_button = self.profile_button_map.get(self.reverse_id)
|
|
if target_button is not None:
|
|
target_button.setChecked(True)
|
|
self.connection_manager.set_profile_button_objects(self.reverse_id, target_button)
|
|
self.boton_edit.setEnabled(not details["is_connected"] and not self._task_busy)
|
|
self.boton_launch.setEnabled(not self._task_busy)
|
|
self.boton_just.setEnabled(not self._task_busy)
|
|
self.boton_just_session.setEnabled(not self._task_busy)
|
|
self._set_verification_icons_enabled()
|
|
self.update_button_visibility(details["is_connected"], details["is_session"])
|
|
self.update_status_message(details)
|
|
for label in self.additional_labels:
|
|
label.deleteLater()
|
|
self.additional_labels.clear()
|
|
if details["background_asset"]:
|
|
self._detail_image(details["background_asset"], (0, 60, 410, 354), lower=True)
|
|
renderers = {"verification": self._render_verification,
|
|
"operator_details": self._render_operator_details,
|
|
"protocol_image": self._render_protocol_image}
|
|
renderers[details["display_mode"]](details)
|
|
if details["show_verified_icon"]:
|
|
self._detail_image("verified_profile.png", (20, 50, 100, 80))
|
|
self.add_selected_profile(details["selection"])
|
|
|
|
def _detail_image(self, asset, geometry, lower=False, pixmap=None):
|
|
label = QLabel(self)
|
|
label.setGeometry(*geometry)
|
|
label.setPixmap(pixmap if pixmap is not None else QPixmap(os.path.join(self.btn_path, asset)))
|
|
label.setScaledContents(True)
|
|
label.show()
|
|
if lower:
|
|
label.lower()
|
|
self.additional_labels.append(label)
|
|
return label
|
|
|
|
def _render_verification(self, details):
|
|
self.additional_labels.append(self.create_verification_widget(details["verification_values"]))
|
|
|
|
def _render_protocol_image(self, details):
|
|
pixmap = QPixmap(os.path.join(self.btn_path, details["primary_asset"]))
|
|
if details["location_overlay"]:
|
|
pixmap = self.build_encrypted_proxy_detail_pixmap(pixmap, details["location"], details["overlay_y"])
|
|
self._detail_image(details["primary_asset"], (0, 80 if details["raised_primary"] else 90, 400, 300), pixmap=pixmap)
|
|
|
|
def _render_operator_details(self, details):
|
|
color = "black" if details["is_session"] else "white"
|
|
self._detail_image(f"icon_{details['location']}.png", (20, 125, 100, 100))
|
|
text_blocks = [
|
|
((130, 110, 260, 250), f"Location: {details['location_text']}\n\nOperator: {details['operator_name']}",
|
|
QtGui.QTextOption.WrapMode.WrapAtWordBoundaryOrAnywhere),
|
|
((20, 260, 370, 80), f"Nostr: {details['nostr_public_key']}", QtGui.QTextOption.WrapMode.WrapAnywhere),
|
|
]
|
|
for geometry, text, wrapping in text_blocks:
|
|
widget = QTextEdit(self)
|
|
widget.setGeometry(*geometry)
|
|
widget.setReadOnly(True)
|
|
widget.setFrameStyle(QFrame.Shape.NoFrame)
|
|
widget.setStyleSheet(f"background: transparent; border: none; color: {color}; font-size: 17px;")
|
|
widget.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
|
widget.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
|
widget.setWordWrapMode(wrapping)
|
|
widget.setText(text)
|
|
widget.show()
|
|
self.additional_labels.append(widget)
|
|
|
|
def build_encrypted_proxy_detail_pixmap(self, pixmap, location, overlay_y):
|
|
if pixmap.isNull():
|
|
return pixmap
|
|
|
|
location_pixmap = QPixmap(os.path.join(
|
|
self.btn_path, f"icon_mini_{location}.png"))
|
|
if location_pixmap.isNull():
|
|
location_pixmap = QPixmap(os.path.join(
|
|
self.btn_path, "default_location_mini.png"))
|
|
if location_pixmap.isNull():
|
|
return pixmap
|
|
|
|
icon_size = max(42, min(72, int(min(pixmap.width(), pixmap.height()) * 0.22)))
|
|
location_pixmap = location_pixmap.scaled(
|
|
icon_size,
|
|
icon_size,
|
|
Qt.AspectRatioMode.KeepAspectRatio,
|
|
Qt.TransformationMode.SmoothTransformation)
|
|
x = int(pixmap.width() * 0.58)
|
|
y = int(pixmap.height() * overlay_y)
|
|
x = min(max(0, x), max(0, pixmap.width() - location_pixmap.width()))
|
|
y = min(max(0, y), max(0, pixmap.height() - location_pixmap.height()))
|
|
|
|
painter = QPainter(pixmap)
|
|
painter.drawPixmap(x, y, location_pixmap)
|
|
painter.end()
|
|
return pixmap
|
|
|
|
def show_profile_verification(self, profile_id):
|
|
location_icon_name = find_verification_icon(
|
|
profile_id,
|
|
self.btn_path,
|
|
self.connection_manager.get_location_info,
|
|
self.update_status.update_status,
|
|
)
|
|
|
|
if location_icon_name:
|
|
verification_page = LocationVerificationPage(
|
|
self.page_stack, self.custom_window, location_icon_name, self)
|
|
self.page_stack.addWidget(verification_page)
|
|
self.page_stack.setCurrentIndex(
|
|
self.page_stack.indexOf(verification_page))
|
|
|
|
def _set_task_busy(self, busy):
|
|
self._task_busy = busy
|
|
for button in (self.boton_just, self.boton_just_session, self.disconnect_button,
|
|
self.disconnect_system_wide_button, self.boton_create, self.boton_edit):
|
|
button.setEnabled(not busy)
|
|
self.scroll_area.setEnabled(not busy)
|
|
self.boton_just.setEnabled(not busy and self.reverse_id is not None)
|
|
self.boton_just_session.setEnabled(not busy and self.reverse_id is not None)
|
|
self.boton_edit.setEnabled(not busy and self.reverse_id is not None
|
|
and not self.connection_manager.is_profile_connected(self.reverse_id))
|
|
|
|
def connect(self):
|
|
self._set_task_busy(True)
|
|
self.update_status.update_status("Attempting to connect...")
|
|
self.worker = enable_profile_action({"id": self.reverse_id}, self.handle_task_result)
|
|
|
|
def disconnect(self):
|
|
self._set_task_busy(True)
|
|
self.update_status.update_status("Disconnecting...")
|
|
self.worker = disable_profile_action(self.reverse_id, self.connection_manager.get_connected_profiles(),
|
|
self.handle_task_result)
|
|
|
|
def create_prof(self):
|
|
self._set_task_busy(True)
|
|
self.worker = create_profile_action(getattr(self.update_status, "gui_config_file", None),
|
|
self.connection_manager.is_synced(), self.handle_task_result)
|
|
|
|
def update_button_visibility(self, is_connected, is_session_profile):
|
|
self.boton_just_session.setVisible(
|
|
not is_connected and is_session_profile)
|
|
self.boton_just.setVisible(not is_connected and not is_session_profile)
|
|
self.disconnect_button.setVisible(is_connected and is_session_profile)
|
|
self.disconnect_system_wide_button.setVisible(
|
|
is_connected and not is_session_profile)
|
|
|
|
def update_status_message(self, state):
|
|
if not state["profile_loaded"]:
|
|
self.update_status.update_status("Profile data could not be loaded. Sync or restart and try again.")
|
|
return
|
|
|
|
status_handlers = {
|
|
True: self.update_status.enable_marquee,
|
|
False: self.update_status.update_status,
|
|
}
|
|
status_handlers[state["use_marquee"]](state["message"])
|
|
|
|
def edit_prof(self):
|
|
self._set_task_busy(True)
|
|
self.worker = edit_profile_action(getattr(self.update_status, "gui_config_file", None),
|
|
self.connection_manager.is_synced(), self.handle_task_result)
|
|
|
|
def settings_gui(self):
|
|
self.custom_window.navigator.navigate("settings")
|
|
|
|
|
|
def show_ticket_data_loss_popup(self, ticket_number, billing_code):
|
|
self.custom_window.navigator.navigate("menu")
|
|
self.update_status.update_status('Critical: invalid billing code from ticket.')
|
|
self.popup = TicketDataLossPopup(
|
|
self,
|
|
ticket_number=ticket_number,
|
|
billing_code=billing_code,
|
|
)
|
|
self.popup.show()
|
|
|
|
def DisplayInstallScreen(self, package_name):
|
|
self.custom_window.navigator.navigate("install_system_package")
|
|
install_page = self.custom_window.navigator.get_cached("install_system_package")
|
|
if install_page is not None:
|
|
install_page.configure(package_name=package_name, distro='debian')
|
|
|
|
@pyqtSlot(object)
|
|
def handle_task_result(self, result: MenuResult):
|
|
if "sync_data" in result:
|
|
self.update_status.update_values(*result["sync_data"])
|
|
if result.get("clear_selection") and result.get("profile_id") == self.reverse_id:
|
|
self.clear_profile_details()
|
|
if result.get("refresh"):
|
|
self.refresh_menu_buttons(result)
|
|
self._set_task_busy(result.get("busy", False))
|
|
if result.get("message"):
|
|
handlers = {True: self.update_status.enable_marquee, False: self.update_status.update_status}
|
|
handlers[bool(result.get("is_enabled"))](result["message"])
|
|
handlers = {"confirmation": self._show_confirmation, "verification": self._show_verification,
|
|
"navigate": self._navigate_result, "install": self._show_install_result,
|
|
"ticket_data_loss": self._show_ticket_loss_result}
|
|
handler = handlers.get(result["status"])
|
|
if handler is not None:
|
|
handler(result)
|
|
|
|
def _show_confirmation(self, result):
|
|
popup = self._make_confirmation_popup(result["message"], result["button_text"])
|
|
popup.finished.connect(functools.partial(self._confirmation_response, result["request"]))
|
|
self.popup = popup
|
|
popup.show()
|
|
|
|
def _confirmation_response(self, request, accepted):
|
|
self._set_task_busy(accepted)
|
|
self.worker = continue_menu_task(request, "continue" if accepted else "abort", self.handle_task_result)
|
|
|
|
def _show_verification(self, result):
|
|
popup = EndpointVerificationPopup(self, message=result["message"])
|
|
popup.finished.connect(functools.partial(self._verification_response, result["request"]))
|
|
self.popup = popup
|
|
popup.show()
|
|
|
|
def _verification_response(self, request, accepted, choice):
|
|
self._set_task_busy(accepted)
|
|
self.worker = continue_menu_task(request, choice if accepted else "abort", self.handle_task_result)
|
|
|
|
def _navigate_result(self, result):
|
|
if "profile_id" in result:
|
|
self.update_status.current_profile_id = result["profile_id"]
|
|
destination = result["destination"]
|
|
page = self.custom_window.navigator.get_cached(destination)
|
|
if destination == "ticket_or_billing_choice" and page is not None:
|
|
page.populate()
|
|
self.custom_window.navigator.navigate(destination)
|
|
|
|
def _show_install_result(self, result):
|
|
self.DisplayInstallScreen(result["package_name"])
|
|
|
|
def _show_ticket_loss_result(self, result):
|
|
self.show_ticket_data_loss_popup(result["ticket_number"], result["billing_code"])
|