254 lines
10 KiB
Python
Executable file
254 lines
10 KiB
Python
Executable file
import os
|
|
|
|
from PyQt6.QtWidgets import QApplication, QLabel, QPushButton, QButtonGroup
|
|
from PyQt6.QtGui import QPixmap, QIcon, QPainter, QColor, QFont, QTransform
|
|
from PyQt6.QtCore import Qt
|
|
from PyQt6 import QtCore
|
|
|
|
from gui.v2.ui.pages.Page import Page
|
|
|
|
|
|
class LocationPage(Page):
|
|
def __init__(self, page_stack, main_window, parent=None):
|
|
super().__init__("Location", page_stack, main_window, parent)
|
|
self.selected_location_icon = None
|
|
self.update_status = main_window
|
|
self.button_reverse.setVisible(True)
|
|
self.connection_manager = main_window.connection_manager
|
|
self.button_reverse.clicked.connect(self.reverse)
|
|
self.display.setGeometry(QtCore.QRect(5, 10, 390, 520))
|
|
self.title.setGeometry(395, 40, 380, 40)
|
|
self.title.setText("Pick a location")
|
|
|
|
self.initial_display = QLabel(self)
|
|
self.initial_display.setGeometry(5, 22, 355, 485)
|
|
self.initial_display.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
self.initial_display.setWordWrap(True)
|
|
|
|
self.verification_button = QPushButton("More Info", self)
|
|
self.verification_button.setGeometry(10, 70, 160, 40)
|
|
self.verification_button.setStyleSheet(f"""
|
|
QPushButton {{
|
|
background-color: rgba(60, 80, 120, 1.0);
|
|
border: 2px solid rgba(100, 140, 200, 1.0);
|
|
border-radius: 5px;
|
|
color: rgb(255, 255, 255);
|
|
font-size: 15px;
|
|
font-weight: bold;
|
|
padding: 5px 10px;
|
|
}}
|
|
QPushButton:hover {{
|
|
background-color: rgba(80, 100, 140, 1.0);
|
|
border: 2px solid rgba(120, 160, 220, 1.0);
|
|
}}
|
|
QPushButton:disabled {{
|
|
background-color: rgba(40, 50, 70, 0.6);
|
|
border: 2px solid rgba(70, 90, 110, 0.6);
|
|
opacity: 0.5;
|
|
}}
|
|
""")
|
|
self.verification_button.setCursor(
|
|
QtCore.Qt.CursorShape.PointingHandCursor)
|
|
self.verification_button.setEnabled(False)
|
|
self.verification_button.show()
|
|
|
|
if self.connection_manager.is_synced():
|
|
from gui.v2.actions.sync import generate_grid_positions
|
|
locs = self.connection_manager.get_location_list()
|
|
positions = generate_grid_positions(len(locs))
|
|
available = [(QPushButton, loc, positions[i]) for i, loc in enumerate(locs)]
|
|
self.create_interface_elements(available)
|
|
|
|
def showEvent(self, event):
|
|
super().showEvent(event)
|
|
self.button_next.setVisible(False)
|
|
for button in self.buttons:
|
|
button.setChecked(False)
|
|
if hasattr(self, 'verification_button'):
|
|
self.verification_button.setEnabled(False)
|
|
|
|
def create_interface_elements(self, available_locations):
|
|
self.buttonGroup = QButtonGroup(self)
|
|
self.buttons = []
|
|
|
|
for j, (object_type, icon_name, geometry) in enumerate(available_locations):
|
|
boton = object_type(self)
|
|
boton.setGeometry(*geometry)
|
|
boton.setIconSize(boton.size())
|
|
boton.setCheckable(True)
|
|
|
|
locations = self.connection_manager.get_location_info(icon_name)
|
|
if locations and not (hasattr(locations, 'is_wireguard_capable') and locations.is_wireguard_capable):
|
|
boton.setVisible(False)
|
|
icon_path = os.path.join(self.btn_path, f"button_{icon_name}.png")
|
|
boton.setIcon(QIcon(icon_path))
|
|
fallback_path = os.path.join(
|
|
self.btn_path, "default_location_button.png")
|
|
provider = locations.operator.name if locations and hasattr(
|
|
locations, 'operator') else None
|
|
if boton.icon().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)
|
|
boton.setIcon(QIcon(base_image))
|
|
else:
|
|
base_image = LocationPage.create_location_button_image(
|
|
'', fallback_path, provider)
|
|
boton.setIcon(QIcon(base_image))
|
|
else:
|
|
if locations and hasattr(locations, 'country_name'):
|
|
base_image = LocationPage.create_location_button_image(
|
|
f'{locations.country_code}_{locations.code}', fallback_path, provider, icon_path)
|
|
boton.setIcon(QIcon(base_image))
|
|
else:
|
|
base_image = LocationPage.create_location_button_image(
|
|
'', fallback_path, provider, icon_path)
|
|
boton.setIcon(QIcon(base_image))
|
|
|
|
self.buttons.append(boton)
|
|
self.buttonGroup.addButton(boton, j)
|
|
boton.location_icon_name = icon_name
|
|
boton.setCursor(QtCore.Qt.CursorShape.PointingHandCursor)
|
|
boton.clicked.connect(
|
|
lambda checked, loc=icon_name: self.show_location(loc))
|
|
|
|
def update_swarp_json(self, get_connection=False):
|
|
profile_data = self.update_status.read_data()
|
|
self.connection_type = profile_data.get("connection", "")
|
|
if get_connection:
|
|
return self.connection_type
|
|
inserted_data = {
|
|
"location": self.selected_location_icon
|
|
}
|
|
self.update_status.write_data(inserted_data)
|
|
|
|
def show_location(self, location):
|
|
self.initial_display.hide()
|
|
|
|
max_size = QtCore.QSize(300, 300)
|
|
target_size = self.display.size().boundedTo(max_size)
|
|
|
|
self.display.setPixmap(QPixmap(os.path.join(self.btn_path, f"icon_{location}.png")).scaled(
|
|
target_size, Qt.AspectRatioMode.KeepAspectRatio))
|
|
self.selected_location_icon = location
|
|
self.button_next.setVisible(True)
|
|
self.button_next.clicked.connect(self.go_selected)
|
|
self.update_swarp_json()
|
|
|
|
try:
|
|
self.verification_button.clicked.disconnect()
|
|
except TypeError:
|
|
pass
|
|
|
|
self.verification_button.clicked.connect(
|
|
lambda: self.show_location_verification(location))
|
|
self.verification_button.setEnabled(True)
|
|
|
|
def reverse(self):
|
|
self.custom_window.navigator.navigate("protocol")
|
|
|
|
def go_selected(self):
|
|
if self.connection_type == "system-wide":
|
|
self.custom_window.navigator.navigate("resume")
|
|
else:
|
|
self.custom_window.navigator.navigate("browser")
|
|
|
|
def show_location_verification(self, location_icon_name):
|
|
from gui.v2.ui.pages.location_verification_page import LocationVerificationPage
|
|
verification_page = LocationVerificationPage(
|
|
self.page_stack, self.update_status, location_icon_name, self)
|
|
self.page_stack.addWidget(verification_page)
|
|
self.page_stack.setCurrentIndex(
|
|
self.page_stack.indexOf(verification_page))
|
|
|
|
@staticmethod
|
|
def create_location_button_image(location_name, fallback_image_path, provider=None, existing_icon_path=None):
|
|
if existing_icon_path:
|
|
base_image = QPixmap(existing_icon_path)
|
|
if base_image.isNull():
|
|
base_image = QPixmap(fallback_image_path)
|
|
draw_location_text = False
|
|
else:
|
|
base_image = QPixmap(fallback_image_path)
|
|
draw_location_text = True
|
|
|
|
if base_image.isNull():
|
|
return base_image
|
|
|
|
painter = QPainter(base_image)
|
|
try:
|
|
if draw_location_text:
|
|
font_size = 12
|
|
app_font = QApplication.font()
|
|
app_font.setPointSize(font_size)
|
|
app_font.setWeight(QFont.Weight.Bold)
|
|
text_length = len(location_name)
|
|
|
|
if text_length <= 10:
|
|
font_stretch = 100
|
|
text_width_scale = 1.1
|
|
text_height_scale = 1.4
|
|
elif text_length <= 15:
|
|
font_stretch = 90
|
|
text_width_scale = 1.0
|
|
text_height_scale = 2
|
|
else:
|
|
font_stretch = 100
|
|
text_width_scale = 1.1
|
|
text_height_scale = 4.5
|
|
app_font.setStretch(font_stretch)
|
|
painter.setFont(app_font)
|
|
painter.setPen(QColor(0, 255, 255))
|
|
|
|
text_rect = painter.fontMetrics().boundingRect(location_name)
|
|
max_width = 110
|
|
|
|
while text_rect.width() > max_width:
|
|
font_size -= 1
|
|
app_font.setPointSize(font_size)
|
|
app_font.setWeight(QFont.Weight.Bold)
|
|
painter.setFont(app_font)
|
|
text_rect = painter.fontMetrics().boundingRect(location_name)
|
|
|
|
x = ((base_image.width() - text_rect.width()) // 2) - 30
|
|
y = ((base_image.height() + text_rect.height()) // 2) - 15
|
|
|
|
transform = QTransform()
|
|
transform.scale(text_width_scale, text_height_scale)
|
|
painter.setTransform(transform)
|
|
|
|
x_scaled = int(x / text_width_scale)
|
|
y_scaled = int(y / text_height_scale)
|
|
|
|
shadow_offset = 1
|
|
painter.setPen(QColor(0, 0, 0))
|
|
painter.drawText(x_scaled + shadow_offset,
|
|
y_scaled + shadow_offset, location_name)
|
|
|
|
painter.setPen(QColor(0, 255, 255))
|
|
painter.drawText(x_scaled, y_scaled, location_name)
|
|
|
|
painter.setTransform(QTransform())
|
|
|
|
if provider:
|
|
|
|
painter.setPen(QColor(128, 128, 128))
|
|
|
|
provider_text_font = QApplication.font()
|
|
provider_text_font.setPointSize(7)
|
|
provider_text_font.setWeight(QFont.Weight.Normal)
|
|
painter.setFont(provider_text_font)
|
|
provider_text_rect = painter.fontMetrics().boundingRect(provider)
|
|
|
|
provider_x = (
|
|
(base_image.width() - provider_text_rect.width()) // 2) - 30
|
|
provider_y = 50
|
|
px = int(provider_x)
|
|
py = int(provider_y)
|
|
|
|
painter.setFont(provider_text_font)
|
|
painter.drawText(px + 5, py + 2, provider)
|
|
finally:
|
|
painter.end()
|
|
return base_image
|