forked from Support/sp-hydra-veil-gui
817 lines
34 KiB
Python
Executable file
817 lines
34 KiB
Python
Executable file
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
|
|
|
|
|
|
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()
|
|
|
|
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
|
|
self.extraccion()
|
|
|
|
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:
|
|
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')
|