Updated Protocol Page / Update Flow / Connection Type
This commit is contained in:
parent
f0fadbdd3a
commit
9b6deffa61
3 changed files with 296 additions and 237 deletions
533
gui/__main__.py
533
gui/__main__.py
|
@ -1,5 +1,5 @@
|
||||||
from PyQt6.QtWidgets import QComboBox,QButtonGroup, QLineEdit,QMainWindow, QLabel, QWidget, QVBoxLayout, QStackedWidget, QApplication, QPushButton, QTextEdit, QFrame, QHBoxLayout, QVBoxLayout, QScrollArea, QSystemTrayIcon, QMessageBox, QGridLayout, QCheckBox, QStackedLayout, QGroupBox
|
from PyQt6.QtWidgets import QComboBox,QButtonGroup, QLineEdit,QMainWindow, QLabel, QWidget, QVBoxLayout, QStackedWidget, QApplication, QPushButton, QTextEdit, QFrame, QHBoxLayout, QVBoxLayout, QScrollArea, QSystemTrayIcon, QMessageBox, QGridLayout, QCheckBox, QStackedLayout, QGroupBox
|
||||||
from PyQt6.QtGui import QIcon, QPixmap,QIcon, QPixmap, QTransform, QPainter, QColor, QFont
|
from PyQt6.QtGui import QIcon, QPixmap,QIcon, QPixmap, QTransform, QPainter, QColor, QFont, QPen
|
||||||
from PyQt6 import QtGui
|
from PyQt6 import QtGui
|
||||||
from PyQt6 import QtCore
|
from PyQt6 import QtCore
|
||||||
from PyQt6.QtCore import Qt,QSize,QThread,pyqtSignal, QTimer, QPointF, QRect, QMutex, QMutexLocker, QObject
|
from PyQt6.QtCore import Qt,QSize,QThread,pyqtSignal, QTimer, QPointF, QRect, QMutex, QMutexLocker, QObject
|
||||||
|
@ -12,7 +12,7 @@ import traceback
|
||||||
import random
|
import random
|
||||||
import subprocess
|
import subprocess
|
||||||
from typing import Union
|
from typing import Union
|
||||||
from core.Errors import CommandNotFoundError, MissingSubscriptionError, InvalidSubscriptionError, ProfileActivationError, UnsupportedApplicationVersionError, FileIntegrityError, ProfileModificationError, ProfileStateConflictError
|
from core.Errors import UnknownConnectionTypeError, CommandNotFoundError, MissingSubscriptionError, InvalidSubscriptionError, ProfileActivationError, UnsupportedApplicationVersionError, FileIntegrityError, ProfileModificationError, ProfileStateConflictError
|
||||||
from core.controllers.ApplicationVersionController import ApplicationVersionController
|
from core.controllers.ApplicationVersionController import ApplicationVersionController
|
||||||
from core.controllers.ApplicationController import ApplicationController
|
from core.controllers.ApplicationController import ApplicationController
|
||||||
from core.controllers.ClientController import ClientController
|
from core.controllers.ClientController import ClientController
|
||||||
|
@ -77,10 +77,8 @@ class WorkerThread(QThread):
|
||||||
self.get_subscription()
|
self.get_subscription()
|
||||||
elif self.action == 'DISABLE_PROFILE':
|
elif self.action == 'DISABLE_PROFILE':
|
||||||
self.disable_profile()
|
self.disable_profile()
|
||||||
elif self.action == 'SYNC':
|
elif self.action == 'SYNC' or self.action == 'SYNC_TOR':
|
||||||
self.sync()
|
self.sync()
|
||||||
elif self.action == 'SYNC_TOR':
|
|
||||||
self.tor_sync()
|
|
||||||
elif self.action == 'GET_CONNECTION':
|
elif self.action == 'GET_CONNECTION':
|
||||||
self.get_connection()
|
self.get_connection()
|
||||||
elif self.action == 'SET_CONNECTION':
|
elif self.action == 'SET_CONNECTION':
|
||||||
|
@ -116,7 +114,7 @@ class WorkerThread(QThread):
|
||||||
|
|
||||||
def download_update(self):
|
def download_update(self):
|
||||||
self.text_output.emit("Starting update process...")
|
self.text_output.emit("Starting update process...")
|
||||||
ClientController.__update(client_observer=client_observer)
|
ClientController.update(client_observer=client_observer)
|
||||||
client_observer.subscribe('update_progressing', lambda event: self.text_output.emit(f"Downloading: {event.meta.get('progress'):.1f}%"))
|
client_observer.subscribe('update_progressing', lambda event: self.text_output.emit(f"Downloading: {event.meta.get('progress'):.1f}%"))
|
||||||
client_observer.subscribe('updated', lambda event: self.text_output.emit("Update process completed"))
|
client_observer.subscribe('updated', lambda event: self.text_output.emit("Update process completed"))
|
||||||
|
|
||||||
|
@ -230,7 +228,10 @@ class WorkerThread(QThread):
|
||||||
|
|
||||||
def sync(self):
|
def sync(self):
|
||||||
try:
|
try:
|
||||||
ConfigurationController.set_connection('system')
|
if self.action == 'SYNC_TOR':
|
||||||
|
ConfigurationController.set_connection('tor')
|
||||||
|
else:
|
||||||
|
ConfigurationController.set_connection('system')
|
||||||
ClientController.sync(client_observer=client_observer, connection_observer=connection_observer)
|
ClientController.sync(client_observer=client_observer, connection_observer=connection_observer)
|
||||||
locations = LocationController.get_all()
|
locations = LocationController.get_all()
|
||||||
print(locations)
|
print(locations)
|
||||||
|
@ -240,18 +241,6 @@ class WorkerThread(QThread):
|
||||||
print(e)
|
print(e)
|
||||||
self.sync_output.emit([], False, False, [], False)
|
self.sync_output.emit([], False, False, [], False)
|
||||||
|
|
||||||
def tor_sync(self):
|
|
||||||
try:
|
|
||||||
ConfigurationController.set_connection('tor')
|
|
||||||
self.text_output.emit('Syncing in progress...')
|
|
||||||
ClientController.sync(client_observer=client_observer, connection_observer=connection_observer)
|
|
||||||
locations = LocationController.get_all()
|
|
||||||
all_location_codes = [location.country_name for location in locations]
|
|
||||||
self.sync_output.emit(all_location_codes, True, True, locations, False)
|
|
||||||
except ConnectionError:
|
|
||||||
self.sync_output.emit([], False, False, [], False)
|
|
||||||
except CommandNotFoundError:
|
|
||||||
self.sync_output.emit([], False, False, [], True)
|
|
||||||
|
|
||||||
|
|
||||||
def get_connection(self):
|
def get_connection(self):
|
||||||
|
@ -336,8 +325,11 @@ class CustomWindow(QMainWindow):
|
||||||
self.is_downloading = False
|
self.is_downloading = False
|
||||||
self.current_profile_id = None
|
self.current_profile_id = None
|
||||||
self.connection_manager = ConnectionManager()
|
self.connection_manager = ConnectionManager()
|
||||||
|
|
||||||
current_connection = ConfigurationController.get_connection()
|
current_connection = self.get_current_connection()
|
||||||
|
if current_connection is None:
|
||||||
|
ConfigurationController.set_connection('system')
|
||||||
|
current_connection = 'system'
|
||||||
self.is_tor_mode = current_connection == 'tor'
|
self.is_tor_mode = current_connection == 'tor'
|
||||||
self.is_animating = False
|
self.is_animating = False
|
||||||
self.animation_step = 0
|
self.animation_step = 0
|
||||||
|
@ -416,6 +408,13 @@ class CustomWindow(QMainWindow):
|
||||||
self.check_logging()
|
self.check_logging()
|
||||||
self.init_ui()
|
self.init_ui()
|
||||||
|
|
||||||
|
|
||||||
|
def get_current_connection(self):
|
||||||
|
try:
|
||||||
|
return ConfigurationController.get_connection()
|
||||||
|
except UnknownConnectionTypeError:
|
||||||
|
return None
|
||||||
|
|
||||||
def _setup_gui_directory(self):
|
def _setup_gui_directory(self):
|
||||||
os.makedirs(self.gui_dir, exist_ok=True)
|
os.makedirs(self.gui_dir, exist_ok=True)
|
||||||
|
|
||||||
|
@ -739,26 +738,24 @@ class CustomWindow(QMainWindow):
|
||||||
self.menu_page = MenuPage(self.page_stack, self)
|
self.menu_page = MenuPage(self.page_stack, self)
|
||||||
self.editor_page = EditorPage(self.page_stack, self)
|
self.editor_page = EditorPage(self.page_stack, self)
|
||||||
self.pages = [MenuPage(self.page_stack, self),
|
self.pages = [MenuPage(self.page_stack, self),
|
||||||
ProtocolPage(self.page_stack, self),
|
ProtocolPage(self.page_stack, self),
|
||||||
WireGuardPage(self.page_stack, self),
|
LocationPage(self.page_stack, self),
|
||||||
ResidentialPage(self.page_stack, self),
|
BrowserPage(self.page_stack, self),
|
||||||
HidetorPage(self.page_stack, self),
|
ScreenPage(self.page_stack, self),
|
||||||
lokinetPage(self.page_stack, self),
|
ResumePage(self.page_stack, self),
|
||||||
OpenPage(self.page_stack, self),
|
WireGuardPage(self.page_stack, self),
|
||||||
TorPage(self.page_stack, self),
|
ResidentialPage(self.page_stack, self),
|
||||||
TorLocationPage(self.page_stack, self),
|
HidetorPage(self.page_stack, self),
|
||||||
PaymentPage(self.page_stack, self),
|
InstallSystemPackage(self.page_stack, self),
|
||||||
LocationPage(self.page_stack, self),
|
WelcomePage(self.page_stack, self),
|
||||||
BrowserPage(self.page_stack, self),
|
PaymentPage(self.page_stack, self),
|
||||||
ScreenPage(self.page_stack, self),
|
PaymentConfirmed(self.page_stack, self),
|
||||||
ResumePage(self.page_stack, self),
|
IdPage(self.page_stack, self),
|
||||||
IdPage(self.page_stack, self),
|
TorPage(self.page_stack, self),
|
||||||
InstallSystemPackage(self.page_stack, self),
|
EditorPage(self.page_stack, self),
|
||||||
WelcomePage(self.page_stack, self),
|
Settings(self.page_stack, self),
|
||||||
PaymentConfirmed(self.page_stack, self),
|
ConnectionPage(self.page_stack, self),
|
||||||
EditorPage(self.page_stack, self),
|
SyncScreen(self.page_stack, self)]
|
||||||
Settings(self.page_stack, self),
|
|
||||||
ConnectionPage(self.page_stack, self)]
|
|
||||||
for page in self.pages:
|
for page in self.pages:
|
||||||
self.page_stack.addWidget(page)
|
self.page_stack.addWidget(page)
|
||||||
# Conectar la señal currentChanged al método page_changed
|
# Conectar la señal currentChanged al método page_changed
|
||||||
|
@ -801,7 +798,7 @@ class CustomWindow(QMainWindow):
|
||||||
self.disable_marquee()
|
self.disable_marquee()
|
||||||
|
|
||||||
def check_first_launch(self):
|
def check_first_launch(self):
|
||||||
config_file = os.path.join(Constants.HV_CONFIG_HOME, '.first_launch')
|
config_file = os.path.join(self.gui_dir, "first_launch.txt")
|
||||||
|
|
||||||
os.makedirs(Constants.HV_CONFIG_HOME, exist_ok=True)
|
os.makedirs(Constants.HV_CONFIG_HOME, exist_ok=True)
|
||||||
|
|
||||||
|
@ -875,9 +872,7 @@ class CustomWindow(QMainWindow):
|
||||||
elif isinstance(current_page, ResumePage):
|
elif isinstance(current_page, ResumePage):
|
||||||
self.update_status('Choose a name for your profile')
|
self.update_status('Choose a name for your profile')
|
||||||
current_page.eliminacion()
|
current_page.eliminacion()
|
||||||
elif isinstance(current_page, ProtocolPage):
|
|
||||||
if not self.connection_manager.is_synced():
|
|
||||||
self.update_status('Choose a sync method')
|
|
||||||
elif isinstance(current_page, IdPage):
|
elif isinstance(current_page, IdPage):
|
||||||
pass
|
pass
|
||||||
elif isinstance(current_page, LocationPage):
|
elif isinstance(current_page, LocationPage):
|
||||||
|
@ -1026,8 +1021,6 @@ class Worker(QObject):
|
||||||
self.update_signal.emit("Application version file integrity could not be verified.", False, None, None, None)
|
self.update_signal.emit("Application version file integrity could not be verified.", False, None, None, None)
|
||||||
except ProfileModificationError:
|
except ProfileModificationError:
|
||||||
self.update_signal.emit("WireGuard configuration could not be attached.", False, None, None, None)
|
self.update_signal.emit("WireGuard configuration could not be attached.", False, None, None, None)
|
||||||
#except OSError:
|
|
||||||
# self.update_signal.emit("Connection could not be established.", False, None, None, None)
|
|
||||||
except ProfileStateConflictError:
|
except ProfileStateConflictError:
|
||||||
self.update_signal.emit("The profile is already being enabled...", False, None, None, None)
|
self.update_signal.emit("The profile is already being enabled...", False, None, None, None)
|
||||||
except CommandNotFoundError as e :
|
except CommandNotFoundError as e :
|
||||||
|
@ -1111,79 +1104,23 @@ class MenuPage(Page):
|
||||||
self.is_system_connected = False
|
self.is_system_connected = False
|
||||||
self.profile_button_map = {}
|
self.profile_button_map = {}
|
||||||
|
|
||||||
self.update_button = QPushButton(self)
|
|
||||||
self.update_button.setGeometry(750, 530, 25, 25)
|
|
||||||
self.update_button.setObjectName("update_button")
|
|
||||||
update_icon = QtGui.QIcon(os.path.join(self.btn_path, "available-updates.png"))
|
|
||||||
self.update_button.setIcon(update_icon)
|
|
||||||
self.update_button.setIconSize(self.update_button.size())
|
|
||||||
self.update_button.clicked.connect(self.check_updates)
|
|
||||||
|
|
||||||
#self.label.setStyleSheet("background-color: rgba(0, 255, 0, 51);")
|
#self.label.setStyleSheet("background-color: rgba(0, 255, 0, 51);")
|
||||||
self.create_interface_elements() # Establecer el color de fondo y el color del texto utilizando hojas de estilo
|
self.create_interface_elements() # Establecer el color de fondo y el color del texto utilizando hojas de estilo
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def on_update_check_finished(self):
|
||||||
|
|
||||||
def check_updates(self):
|
|
||||||
self.update_status.update_status("Checking for updates...")
|
|
||||||
self.worker = WorkerThread('CHECK_FOR_UPDATE')
|
|
||||||
self.worker.text_output.connect(self.update_status.update_status)
|
|
||||||
self.worker.finished.connect(self.on_update_check_finished)
|
|
||||||
self.worker.start()
|
|
||||||
|
|
||||||
def on_update_check_finished(self, result):
|
|
||||||
if result:
|
|
||||||
reply = QMessageBox.question(self, 'Update Available',
|
reply = QMessageBox.question(self, 'Update Available',
|
||||||
'An update is available. Would you like to download it?',
|
'An update is available. Would you like to download it?',
|
||||||
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
|
||||||
if reply == QMessageBox.StandardButton.Yes:
|
if reply == QMessageBox.StandardButton.Yes:
|
||||||
self.worker = WorkerThread('DOWNLOAD_UPDATE')
|
self.worker = WorkerThread('DOWNLOAD_UPDATE')
|
||||||
self.worker.text_output.connect(self.update_status.update_status)
|
|
||||||
self.worker.update_finished.connect(self.on_update_download_finished)
|
|
||||||
self.worker.start()
|
self.worker.start()
|
||||||
else:
|
else:
|
||||||
self.update_status.update_status("Update cancelled by user.")
|
self.update_status.update_status("Update cancelled by user.")
|
||||||
else:
|
|
||||||
self.update_status.update_status("No updates available.")
|
|
||||||
|
|
||||||
def on_update_download_finished(self, result: dict):
|
|
||||||
if result["status"] and result["path"]:
|
|
||||||
self.countdown_timer = QTimer()
|
|
||||||
self.countdown_timer.setInterval(1000)
|
|
||||||
self.countdown_seconds = 3
|
|
||||||
self.new_app_path = result["path"]
|
|
||||||
|
|
||||||
def update_countdown():
|
|
||||||
if self.countdown_seconds > 0:
|
|
||||||
self.update_status.update_status(f"New version downloaded. Restarting in {self.countdown_seconds} second{'s' if self.countdown_seconds > 1 else ''}...")
|
|
||||||
self.countdown_seconds -= 1
|
|
||||||
else:
|
|
||||||
self.countdown_timer.stop()
|
|
||||||
self.restart_application()
|
|
||||||
|
|
||||||
def restart_application():
|
|
||||||
QApplication.quit()
|
|
||||||
current_app = Constants.APPIMAGE_PATH
|
|
||||||
|
|
||||||
if os.path.exists(self.new_app_path):
|
|
||||||
try:
|
|
||||||
os.remove(current_app)
|
|
||||||
os.execv(self.new_app_path, [self.new_app_path] + sys.argv[1:])
|
|
||||||
except PermissionError:
|
|
||||||
self.update_status.update_status(f"Permission denied: Unable to remove {current_app}")
|
|
||||||
else:
|
|
||||||
self.update_status.update_status(f"Error: New application not found at {self.new_app_path}")
|
|
||||||
|
|
||||||
self.restart_application = restart_application
|
|
||||||
self.countdown_timer.timeout.connect(update_countdown)
|
|
||||||
self.countdown_timer.start()
|
|
||||||
|
|
||||||
atexit.register(restart_application)
|
|
||||||
else:
|
|
||||||
self.update_status.update_status("Failed to download update.")
|
|
||||||
|
|
||||||
def create_interface_elements(self):
|
def create_interface_elements(self):
|
||||||
for icon_name, function, position in [
|
for icon_name, function, position in [
|
||||||
|
@ -1579,11 +1516,6 @@ class MenuPage(Page):
|
||||||
editar_profile = {"profile_number": profile_number, "name": name, "protocol": protocol}
|
editar_profile = {"profile_number": profile_number, "name": name, "protocol": protocol}
|
||||||
self.page_stack.currentWidget().add_selected_profile(editar_profile)
|
self.page_stack.currentWidget().add_selected_profile(editar_profile)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def launch(self):
|
def launch(self):
|
||||||
pass
|
pass
|
||||||
|
@ -1648,7 +1580,10 @@ class MenuPage(Page):
|
||||||
if len(self.profile_info) == 6:
|
if len(self.profile_info) == 6:
|
||||||
self.update_status.update_status('Maximum number of profiles reached!')
|
self.update_status.update_status('Maximum number of profiles reached!')
|
||||||
return
|
return
|
||||||
self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(ProtocolPage)))
|
if not self.connection_manager.is_synced():
|
||||||
|
self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(SyncScreen)))
|
||||||
|
else:
|
||||||
|
self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(ProtocolPage)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -2517,138 +2452,12 @@ class ProtocolPage(Page):
|
||||||
self.coming_soon_label.setGeometry(210, 50, 200, 40)
|
self.coming_soon_label.setGeometry(210, 50, 200, 40)
|
||||||
self.coming_soon_label.setStyleSheet("font-size: 22px;")
|
self.coming_soon_label.setStyleSheet("font-size: 22px;")
|
||||||
|
|
||||||
self.sync_label = QLabel("Sync finds out what plans, countries, \n& browsers are available", self)
|
|
||||||
self.sync_label.setGeometry(100, 120,500,60)
|
|
||||||
self.sync_label.setStyleSheet("font-size: 20px;")
|
|
||||||
|
|
||||||
self.button_sync = QPushButton(self)
|
|
||||||
self.button_sync.setObjectName("sync_button")
|
|
||||||
self.button_sync.setGeometry(100, 250,150,60)
|
|
||||||
self.button_sync.setIconSize(self.button_sync.size())
|
|
||||||
icon = QIcon(os.path.join(self.btn_path, "sync_button.png"))
|
|
||||||
self.button_sync.setIcon(icon)
|
|
||||||
self.button_sync.clicked.connect(self.handle_core_action_sync_button)
|
|
||||||
|
|
||||||
self.tor_button_sync = QPushButton(self)
|
|
||||||
self.tor_button_sync.setObjectName("tor_sync")
|
|
||||||
self.tor_button_sync.setGeometry(300, 250,150,60)
|
|
||||||
self.tor_button_sync.setIconSize(self.tor_button_sync.size())
|
|
||||||
tor_icon = QIcon(os.path.join(self.btn_path, "tor_sync.png"))
|
|
||||||
self.tor_button_sync.setIcon(tor_icon)
|
|
||||||
self.tor_button_sync.clicked.connect(lambda: self.handle_core_action_sync_button(True))
|
|
||||||
|
|
||||||
self.button_sync.setVisible(True)
|
|
||||||
self.tor_button_sync.setVisible(True)
|
|
||||||
|
|
||||||
|
|
||||||
self.coming_soon_label.setVisible(False)
|
self.coming_soon_label.setVisible(False)
|
||||||
self.title.setGeometry(585, 40, 185, 40); self.title.setText("Pick a Protocol")
|
self.title.setGeometry(585, 40, 185, 40); self.title.setText("Pick a Protocol")
|
||||||
self.display.setGeometry(QtCore.QRect(0, 50, 580, 435))#relacion 4:3
|
self.display.setGeometry(QtCore.QRect(0, 50, 580, 435))#relacion 4:3
|
||||||
self.create_interface_elements()
|
self.create_interface_elements()
|
||||||
|
|
||||||
|
|
||||||
def sync_button(self, toggle: bool, sync_complete: bool=False):
|
|
||||||
self.button_sync.setDisabled(toggle)
|
|
||||||
self.tor_button_sync.setDisabled(toggle)
|
|
||||||
|
|
||||||
|
|
||||||
if sync_complete:
|
|
||||||
for button in self.buttons:
|
|
||||||
button.setDisabled(toggle)
|
|
||||||
self.button_sync.setVisible(False)
|
|
||||||
self.tor_button_sync.setVisible(False)
|
|
||||||
self.sync_label.setVisible(False)
|
|
||||||
|
|
||||||
def handle_core_action_sync_button(self, tor: bool = False):
|
|
||||||
self.sync_button(True)
|
|
||||||
|
|
||||||
if tor:
|
|
||||||
self.main_window.set_toggle_state(True)
|
|
||||||
self.sync_button(True)
|
|
||||||
self.update_status.update_status('Syncing through Tor in progress...')
|
|
||||||
self.worker_thread = WorkerThread('SYNC_TOR')
|
|
||||||
self.worker_thread.sync_output.connect(self.update_output)
|
|
||||||
self.worker_thread.text_output.connect(self.update_text_output)
|
|
||||||
self.worker_thread.start()
|
|
||||||
return
|
|
||||||
|
|
||||||
self.update_status.update_status('Syncing in progress...')
|
|
||||||
self.worker_thread = WorkerThread('SYNC')
|
|
||||||
self.worker_thread.sync_output.connect(self.update_output)
|
|
||||||
self.worker_thread.start()
|
|
||||||
|
|
||||||
|
|
||||||
def update_text_output(self, text):
|
|
||||||
self.update_status.update_status(text)
|
|
||||||
|
|
||||||
def update_output(self, available_locations, status, is_tor, locations, is_os_error):
|
|
||||||
if is_os_error:
|
|
||||||
install_page = self.page_stack.findChild(InstallSystemPackage)
|
|
||||||
install_page.configure(package_name='tor', distro='debian', is_sync=True)
|
|
||||||
self.page_stack.setCurrentIndex(self.page_stack.indexOf(install_page))
|
|
||||||
self.sync_button(False)
|
|
||||||
return
|
|
||||||
|
|
||||||
if status is False:
|
|
||||||
self.sync_button(False)
|
|
||||||
self.update_status.update_status('An error occurred during sync')
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self.update_status.update_status('Sync complete')
|
|
||||||
self.connection_manager.set_synced(True)
|
|
||||||
|
|
||||||
available_locations_list = []
|
|
||||||
self.connection_manager.store_locations(locations)
|
|
||||||
|
|
||||||
grid_positions = [
|
|
||||||
(395, 90, 185, 75),
|
|
||||||
(585, 90, 185, 75),
|
|
||||||
(395, 195, 185, 75),
|
|
||||||
(585, 195, 185, 75),
|
|
||||||
(395, 300, 185, 75),
|
|
||||||
(585, 300, 185, 75),
|
|
||||||
(395, 405, 185, 75),
|
|
||||||
(585, 405, 185, 75)
|
|
||||||
]
|
|
||||||
|
|
||||||
list1 = []
|
|
||||||
for i, location in enumerate(available_locations):
|
|
||||||
position_index = i % len(grid_positions)
|
|
||||||
list1.append((QPushButton, location, grid_positions[position_index]))
|
|
||||||
|
|
||||||
for item in list1:
|
|
||||||
available_locations_list.append(item)
|
|
||||||
|
|
||||||
self.sync_button(False, True)
|
|
||||||
location_page = self.find_location_page()
|
|
||||||
hidetor_page = self.find_hidetor_page()
|
|
||||||
print(f' the available locations list is {available_locations_list}')
|
|
||||||
|
|
||||||
if location_page:
|
|
||||||
location_page.create_interface_elements(available_locations_list)
|
|
||||||
if hidetor_page:
|
|
||||||
hidetor_page.create_interface_elements(available_locations_list)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def find_location_page(self):
|
|
||||||
for i in range(self.page_stack.count()):
|
|
||||||
page = self.page_stack.widget(i)
|
|
||||||
if isinstance(page, LocationPage):
|
|
||||||
return page
|
|
||||||
return None
|
|
||||||
|
|
||||||
def find_hidetor_page(self):
|
|
||||||
for i in range(self.page_stack.count()):
|
|
||||||
page = self.page_stack.widget(i)
|
|
||||||
if isinstance(page, HidetorPage):
|
|
||||||
return page
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def create_interface_elements(self):
|
def create_interface_elements(self):
|
||||||
self.buttonGroup = QButtonGroup(self)
|
self.buttonGroup = QButtonGroup(self)
|
||||||
self.buttons = []
|
self.buttons = []
|
||||||
|
@ -2667,6 +2476,10 @@ class ProtocolPage(Page):
|
||||||
self.buttons.append(boton)
|
self.buttons.append(boton)
|
||||||
self.buttonGroup.addButton(boton, j)
|
self.buttonGroup.addButton(boton, j)
|
||||||
boton.clicked.connect(lambda _, page=page_class, protocol=icon_name: self.show_protocol(page, protocol))
|
boton.clicked.connect(lambda _, page=page_class, protocol=icon_name: self.show_protocol(page, protocol))
|
||||||
|
|
||||||
|
def enable_protocol_buttons(self):
|
||||||
|
for button in self.buttons:
|
||||||
|
button.setDisabled(False)
|
||||||
|
|
||||||
def update_swarp_json(self):
|
def update_swarp_json(self):
|
||||||
self.update_status.write_data({"protocol": self.selected_protocol_icon})
|
self.update_status.write_data({"protocol": self.selected_protocol_icon})
|
||||||
|
@ -5724,6 +5537,252 @@ class ClickableValueLabel(QLabel):
|
||||||
self.setStyleSheet(self.default_style)
|
self.setStyleSheet(self.default_style)
|
||||||
|
|
||||||
|
|
||||||
|
class SyncScreen(Page):
|
||||||
|
def __init__(self, page_stack, main_window=None, parent=None):
|
||||||
|
super().__init__("SyncScreen", page_stack, main_window, parent)
|
||||||
|
self.main_window = main_window
|
||||||
|
self.btn_path = main_window.btn_path
|
||||||
|
self.update_status = main_window
|
||||||
|
self.connection_manager = main_window.connection_manager
|
||||||
|
self.is_tor_mode = main_window.is_tor_mode
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
self.heading_label = QLabel("You're about to fetch data from\nSimplified Privacy.", self)
|
||||||
|
self.heading_label.setGeometry(15, 80, 750, 80)
|
||||||
|
self.heading_label.setStyleSheet("font-size: 36px; font-weight: bold; color: white;")
|
||||||
|
|
||||||
|
self.data_description = QLabel("This data includes what plans, countries,\nbrowsers, and version upgrades are\navailable. As well as coordinating billing.", self)
|
||||||
|
self.data_description.setGeometry(22, 190, 750, 90)
|
||||||
|
self.data_description.setStyleSheet("font-size: 26px; font-weight: bold; color: #ffff00;")
|
||||||
|
|
||||||
|
self.instructions = QLabel("Use the toggle in the bottom right to\ndecide if you want to use Tor or not.\nThen hit \"Next\"", self)
|
||||||
|
self.instructions.setGeometry(22, 345, 750, 100)
|
||||||
|
self.instructions.setStyleSheet("font-size: 30px; font-weight: bold; color: white;")
|
||||||
|
|
||||||
|
self.arrow_label = QLabel(self)
|
||||||
|
self.arrow_label.setGeometry(520, 400, 180, 130)
|
||||||
|
arrow_pixmap = QPixmap(os.path.join(self.btn_path, "arrow-down.png"))
|
||||||
|
|
||||||
|
self.arrow_label.setPixmap(arrow_pixmap)
|
||||||
|
self.arrow_label.raise_()
|
||||||
|
|
||||||
|
self.button_go.setVisible(True)
|
||||||
|
self.button_back.setVisible(True)
|
||||||
|
self.button_go.clicked.connect(self.perform_sync)
|
||||||
|
self.button_back.clicked.connect(self.go_back)
|
||||||
|
|
||||||
|
def go_back(self):
|
||||||
|
self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(MenuPage)))
|
||||||
|
|
||||||
|
def perform_sync(self):
|
||||||
|
self.button_go.setEnabled(False)
|
||||||
|
self.button_back.setEnabled(False)
|
||||||
|
self.update_status.update_status('Syncing in progress...')
|
||||||
|
if self.main_window.get_current_connection() == 'tor':
|
||||||
|
self.worker_thread = WorkerThread('SYNC_TOR')
|
||||||
|
else:
|
||||||
|
self.worker_thread = WorkerThread('SYNC')
|
||||||
|
|
||||||
|
self.worker_thread.sync_output.connect(self.update_output)
|
||||||
|
self.worker_thread.start()
|
||||||
|
|
||||||
|
def update_output(self, available_locations, status, is_tor, locations, is_os_error):
|
||||||
|
if is_os_error:
|
||||||
|
install_page = self.page_stack.findChild(InstallSystemPackage)
|
||||||
|
install_page.configure(package_name='tor', distro='debian', is_sync=True)
|
||||||
|
self.page_stack.setCurrentIndex(self.page_stack.indexOf(install_page))
|
||||||
|
self.button_go.setEnabled(True)
|
||||||
|
self.button_back.setEnabled(True)
|
||||||
|
return
|
||||||
|
|
||||||
|
if status is False:
|
||||||
|
self.button_go.setEnabled(True)
|
||||||
|
self.button_back.setEnabled(True)
|
||||||
|
self.update_status.update_status('An error occurred during sync')
|
||||||
|
return
|
||||||
|
|
||||||
|
self.update_status.update_status('Sync complete')
|
||||||
|
self.connection_manager.set_synced(True)
|
||||||
|
|
||||||
|
update_available = ClientController.can_be_updated()
|
||||||
|
|
||||||
|
if not update_available:
|
||||||
|
menu_page = self.page_stack.findChild(MenuPage)
|
||||||
|
menu_page.on_update_check_finished()
|
||||||
|
|
||||||
|
|
||||||
|
available_locations_list = []
|
||||||
|
self.connection_manager.store_locations(locations)
|
||||||
|
|
||||||
|
grid_positions = [
|
||||||
|
(395, 90, 185, 75),
|
||||||
|
(585, 90, 185, 75),
|
||||||
|
(395, 195, 185, 75),
|
||||||
|
(585, 195, 185, 75),
|
||||||
|
(395, 300, 185, 75),
|
||||||
|
(585, 300, 185, 75),
|
||||||
|
(395, 405, 185, 75),
|
||||||
|
(585, 405, 185, 75)
|
||||||
|
]
|
||||||
|
|
||||||
|
list1 = []
|
||||||
|
for i, location in enumerate(available_locations):
|
||||||
|
position_index = i % len(grid_positions)
|
||||||
|
list1.append((QPushButton, location, grid_positions[position_index]))
|
||||||
|
|
||||||
|
for item in list1:
|
||||||
|
available_locations_list.append(item)
|
||||||
|
|
||||||
|
location_page = self.find_location_page()
|
||||||
|
hidetor_page = self.find_hidetor_page()
|
||||||
|
protocol_page = self.find_protocol_page()
|
||||||
|
|
||||||
|
if location_page:
|
||||||
|
location_page.create_interface_elements(available_locations_list)
|
||||||
|
if hidetor_page:
|
||||||
|
hidetor_page.create_interface_elements(available_locations_list)
|
||||||
|
if protocol_page:
|
||||||
|
protocol_page.enable_protocol_buttons()
|
||||||
|
|
||||||
|
self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(ProtocolPage)))
|
||||||
|
|
||||||
|
def find_location_page(self):
|
||||||
|
for i in range(self.page_stack.count()):
|
||||||
|
page = self.page_stack.widget(i)
|
||||||
|
if isinstance(page, LocationPage):
|
||||||
|
return page
|
||||||
|
return None
|
||||||
|
|
||||||
|
def find_hidetor_page(self):
|
||||||
|
for i in range(self.page_stack.count()):
|
||||||
|
page = self.page_stack.widget(i)
|
||||||
|
if isinstance(page, HidetorPage):
|
||||||
|
return page
|
||||||
|
return None
|
||||||
|
|
||||||
|
def find_protocol_page(self):
|
||||||
|
for i in range(self.page_stack.count()):
|
||||||
|
page = self.page_stack.widget(i)
|
||||||
|
if isinstance(page, ProtocolPage):
|
||||||
|
return page
|
||||||
|
return None
|
||||||
|
|
||||||
|
class WelcomePage(Page):
|
||||||
|
def __init__(self, page_stack, main_window=None, parent=None):
|
||||||
|
super().__init__("Welcome", page_stack, main_window, parent)
|
||||||
|
self.btn_path = main_window.btn_path
|
||||||
|
self.update_status = main_window
|
||||||
|
self.ui_elements = []
|
||||||
|
self.button_next.clicked.connect(self.go_to_install)
|
||||||
|
self.button_next.setVisible(True)
|
||||||
|
self._setup_welcome_ui()
|
||||||
|
self._setup_stats_display()
|
||||||
|
|
||||||
|
def _setup_welcome_ui(self):
|
||||||
|
welcome_title = QLabel("Welcome to HydraVeilVPN", self)
|
||||||
|
welcome_title.setGeometry(20, 45, 760, 60)
|
||||||
|
welcome_title.setStyleSheet("""
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: cyan;
|
||||||
|
""")
|
||||||
|
welcome_title.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||||
|
|
||||||
|
welcome_msg = QLabel(
|
||||||
|
"Before we begin your journey, we need to set up a few essential components. "
|
||||||
|
"Click 'Next' to take you to the installation page.", self)
|
||||||
|
welcome_msg.setGeometry(40, 100, 720, 80)
|
||||||
|
welcome_msg.setWordWrap(True)
|
||||||
|
welcome_msg.setStyleSheet("""
|
||||||
|
font-size: 16px;
|
||||||
|
color: cyan;
|
||||||
|
""")
|
||||||
|
welcome_msg.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||||
|
|
||||||
|
def _setup_stats_display(self):
|
||||||
|
stats_container = QWidget(self)
|
||||||
|
stats_container.setGeometry(70, 200, 730, 240)
|
||||||
|
|
||||||
|
stats_title = QLabel(stats_container)
|
||||||
|
stats_title.setText("Features & Services")
|
||||||
|
stats_title.setGeometry(190, 10, 300, 30)
|
||||||
|
stats_title.setStyleSheet("""
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: cyan;
|
||||||
|
""")
|
||||||
|
|
||||||
|
grid_widget = QWidget(stats_container)
|
||||||
|
grid_widget.setGeometry(0, 70, 700, 190)
|
||||||
|
grid_layout = QGridLayout(grid_widget)
|
||||||
|
grid_layout.setSpacing(30)
|
||||||
|
|
||||||
|
stats = [
|
||||||
|
("Browsers", "browsers_mini.png", "10 Supported Browsers", True),
|
||||||
|
("WireGuard", "wireguard_mini.png", "6 Global Locations", True),
|
||||||
|
("Proxy", "just proxy_mini.png", "5 Proxy Locations", True),
|
||||||
|
("Tor", "toricon_mini.png", "Tor Network Access", True)
|
||||||
|
]
|
||||||
|
|
||||||
|
for i, (title, icon_name, count, available) in enumerate(stats):
|
||||||
|
row = i // 2
|
||||||
|
col = i % 2
|
||||||
|
|
||||||
|
stat_widget = QWidget()
|
||||||
|
stat_layout = QHBoxLayout(stat_widget)
|
||||||
|
stat_layout.setContentsMargins(20, 10, 2, 10)
|
||||||
|
stat_layout.setSpacing(15)
|
||||||
|
|
||||||
|
icon_label = QLabel()
|
||||||
|
icon_path = os.path.join(self.btn_path, icon_name)
|
||||||
|
icon_label.setPixmap(QPixmap(icon_path).scaled(30, 30, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation))
|
||||||
|
icon_label.setFixedSize(30, 30)
|
||||||
|
stat_layout.addWidget(icon_label)
|
||||||
|
|
||||||
|
text_widget = QWidget()
|
||||||
|
text_layout = QVBoxLayout(text_widget)
|
||||||
|
text_layout.setSpacing(5)
|
||||||
|
text_layout.setContentsMargins(0, 0, 30, 0)
|
||||||
|
|
||||||
|
title_widget = QWidget()
|
||||||
|
title_layout = QHBoxLayout(title_widget)
|
||||||
|
title_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
title_layout.setSpacing(10)
|
||||||
|
|
||||||
|
title_label = QLabel(title)
|
||||||
|
title_label.setStyleSheet("font-size: 16px; font-weight: bold; color: #2c3e50;")
|
||||||
|
title_layout.addWidget(title_label)
|
||||||
|
|
||||||
|
status_indicator = QLabel("●")
|
||||||
|
status_indicator.setStyleSheet("color: #2ecc71; font-size: 16px;")
|
||||||
|
title_layout.addWidget(status_indicator)
|
||||||
|
|
||||||
|
title_layout.addStretch()
|
||||||
|
text_layout.addWidget(title_widget)
|
||||||
|
|
||||||
|
count_label = QLabel(count)
|
||||||
|
count_label.setStyleSheet("color: #34495e;")
|
||||||
|
text_layout.addWidget(count_label)
|
||||||
|
|
||||||
|
stat_layout.addWidget(text_widget, stretch=1)
|
||||||
|
|
||||||
|
stat_widget.setStyleSheet("""
|
||||||
|
QWidget {
|
||||||
|
background-color: transparent;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
|
||||||
|
grid_layout.addWidget(stat_widget, row, col)
|
||||||
|
|
||||||
|
|
||||||
|
def go_to_install(self):
|
||||||
|
install_page = self.page_stack.findChild(InstallSystemPackage)
|
||||||
|
install_page.configure(package_name='all', distro='debian')
|
||||||
|
self.page_stack.setCurrentIndex(self.page_stack.indexOf(install_page))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
window = CustomWindow()
|
window = CustomWindow()
|
||||||
|
|
BIN
gui/resources/images/arrow-down.png
Normal file
BIN
gui/resources/images/arrow-down.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
Before Width: | Height: | Size: 211 KiB After Width: | Height: | Size: 32 KiB |
Loading…
Reference in a new issue