diff --git a/gui/__main__.py b/gui/__main__.py index c2fd84c..e0ba2ce 100644 --- a/gui/__main__.py +++ b/gui/__main__.py @@ -162,7 +162,7 @@ class WorkerThread(QThread): self.profiles_output.emit(profiles) def create_profile(self, profile_type): - location = LocationController.get(self.profile_data['location_code']) + location = LocationController.get(self.profile_data['country_code'], self.profile_data['code']) if location is None: self.text_output.emit(f"Invalid location code: {self.profile_data['location_code']}") return @@ -214,8 +214,8 @@ class WorkerThread(QThread): ConfigurationController.set_connection('system') ClientController.sync(client_observer=client_observer, connection_observer=connection_observer) locations = LocationController.get_all() - print(locations) - all_location_codes = [location.name for location in locations] + print(f'locations: {locations}') + all_location_codes = [location.country_name for location in locations] self.sync_output.emit(all_location_codes, True, False, locations, False) except Exception as e: print(e) @@ -227,7 +227,7 @@ class WorkerThread(QThread): 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.name for location in locations] + 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) @@ -308,7 +308,7 @@ class CustomWindow(QMainWindow): ) self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground) self.setAttribute(Qt.WidgetAttribute.WA_NoSystemBackground) - self.setWindowTitle("Simplified Privacy VPN") + self.setWindowTitle("HydraVeil VPN") self._data = {"Profile_1": {}} self.gui_dir = os.path.join(Constants.HV_DATA_HOME, "gui") @@ -1093,11 +1093,9 @@ class MenuPage(Page): self.additional_labels = [] self.update_status = main_window self.title.setGeometry(400, 40, 380, 30); self.title.setText("Load Profile") - self.label = QLineEdit(self) - - self.label.setFont(QFont("Arial", 8)) - self.label.setVisible(False) - self.label.returnPressed.connect(self.show_save_animation) + + + 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") @@ -1122,29 +1120,6 @@ class MenuPage(Page): - def show_save_animation(self): - profile = ProfileController.get(int(self.reverse_id)) - self.label.setStyleSheet(""" - QLineEdit { - background-color: rgba(40, 167, 69, 0.3); - border: none; - color: black; - } - """) - - QTimer.singleShot(200, lambda: self.label.setStyleSheet(""" - QLineEdit { - background-color: rgba(0, 0, 0, 0); - border: none; - color: %s; - } - """ % ('black' if profile.connection.code == 'wireguard' else 'white'))) - - self.label.setText(self.label.text()) - - profile.url = self.label.text() - ProfileController.update(profile, resolution=True) - def check_updates(self): @@ -1265,7 +1240,6 @@ class MenuPage(Page): def on_popup_finished(self, result): if result: - self.label.setVisible(False) profile_id = self.reverse_id self.update_status.update_status(f'Deleting profile...') self.worker_thread = WorkerThread('DESTROY_PROFILE', profile_data={'id': profile_id}) @@ -1418,7 +1392,16 @@ class MenuPage(Page): child_label.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents) image_path = self.get_icon_path(label_name, value, connection_type) - child_label.setPixmap(QPixmap(image_path)) + pixmap = QPixmap(image_path) + # Check if the pixmap is null (image doesn't exist) + if pixmap.isNull() and label_name == 'location': + # Use a fallback/default image + fallback_path = os.path.join(self.btn_path, "default_location_mini.png") + pixmap = QPixmap(fallback_path) + if pixmap.isNull(): + pixmap = QPixmap(50, 50) + pixmap.fill(QtGui.QColor(200, 200, 200)) + child_label.setPixmap(pixmap) child_label.show() def create_other_icons(self, parent_label, value, connection_type): @@ -1430,7 +1413,16 @@ class MenuPage(Page): child_label.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents) image_path = self.get_icon_path(label_name, value, connection_type) - child_label.setPixmap(QPixmap(image_path)) + pixmap = QPixmap(image_path) + if pixmap.isNull() and label_name == 'location': + # Use a fallback/default image + fallback_path = os.path.join(self.btn_path, "default_location_mini.png") + pixmap = QPixmap(fallback_path) + # If even the fallback is null, create a simple colored square + if pixmap.isNull(): + pixmap = QPixmap(50, 50) + pixmap.fill(QtGui.QColor(200, 200, 200)) # Light gray fallback + child_label.setPixmap(pixmap) child_label.show() def get_icon_path(self, label_name, value, connection_type): @@ -1504,14 +1496,7 @@ class MenuPage(Page): self.additional_labels.append(label_principal) if protocol.lower() == "hidetor": - self.label.setGeometry(70, 77, 280, 30) - self.label.setStyleSheet(""" - QLineEdit { - background-color: rgba(0, 0, 0, 0); - border: none; - color: white; - } - """) + label_principal.setGeometry(0, 80, 400, 300) label_background = QLabel(self) label_background.setGeometry(0, 60, 410, 354) @@ -1528,14 +1513,7 @@ class MenuPage(Page): if protocol.lower() == "wireguard" and connection.lower() == "browser-only": - self.label.setGeometry(95, 71, 280, 30) - self.label.setStyleSheet(""" - QLineEdit { - background-color: rgba(0, 0, 0, 0); - border: none; - color: black; - } - """) + # Redimensionar el QLabel principal label_principal.setGeometry(0, 80, 400, 300) @@ -1549,14 +1527,7 @@ class MenuPage(Page): label_background.lower() self.additional_labels.append(label_background) if protocol.lower() == "residential" and connection.lower() == "tor": - self.label.setStyleSheet(""" - QLineEdit { - background-color: rgba(0, 0, 0, 0); - border: none; - color: white; - border-radius: 10px; - } - """) + label_background = QLabel(self) label_background.setGeometry(0, 60, 410, 354) pixmap = QPixmap(os.path.join(self.btn_path, "browser_tor.png")) @@ -1606,28 +1577,9 @@ class MenuPage(Page): editar_profile = {"profile_number": profile_number, "name": name, "protocol": protocol} self.page_stack.currentWidget().add_selected_profile(editar_profile) - if profile: - name = profile.get("name", "") - profile = ProfileController.get(int(self.reverse_id)) - if isinstance(profile, SessionProfile): - self.label.setVisible(True) - homepage_url = SessionProfile.get_url(profile) - self.label.setText(homepage_url) - self.label.raise_() - else: - self.label.setVisible(False) + + - def check_wireguard_rotation(self): - profile = ProfileController.get(int(self.reverse_id)) - if not profile.has_wireguard_configuration(): - return False - - rotation_frequency = profile.connection.wireguard_rotation_frequency - if not rotation_frequency: - return False - - time_elapsed = datetime.now(timezone.utc) - profile.connection.wireguard_rotation_last_performed - return time_elapsed > timedelta(hours=rotation_frequency) @@ -1636,12 +1588,6 @@ class MenuPage(Page): def connect(self): - if self.check_wireguard_rotation(): - profile = ProfileController.get(int(self.reverse_id)) - profile.delete_wireguard_configuration() - profile.connection.wireguard_rotation_last_performed = datetime.now(timezone.utc) - ProfileController.update(profile) - self.boton_just.setEnabled(False) self.boton_just_session.setEnabled(False) if self.connection_manager.get_is_profile_being_enabled(int(self.reverse_id)): @@ -1747,11 +1693,10 @@ class MenuPage(Page): self.main_window.off_label.setParent(None) for widget in self.findChildren(QLabel): - if widget != self.title and widget != self.label: + if widget != self.title: widget.setParent(None) self.profile_info.clear() - self.label.clear() self.main_window.toggle_bg.setParent(self.main_window.toggle_button) self.main_window.toggle_handle.setParent(self.main_window.toggle_button) @@ -1952,21 +1897,20 @@ class ConnectionManager: def get_location_info(self, location_key): if location_key in self._location_mapping: return self._location_mapping[location_key] - - for code, name in self._location_mapping.items(): - if name == location_key: - return code + return None def store_locations(self, locations): - self._location_list = [] + self._location_mapping = {} + self._location_list = locations for location in locations: - self._location_list.append(location.name) + self._location_mapping[location.country_name] = location def get_location_list(self): if self.is_synced(): - return self._location_list + location_names = [location.country_name for location in self._location_list] + return location_names else: return self.wireguard_locations @@ -2454,7 +2398,7 @@ class WelcomePage(Page): self._setup_stats_display() def _setup_welcome_ui(self): - welcome_title = QLabel("Welcome to SimplifiedPrivacyVPN", self) + welcome_title = QLabel("Welcome to HydraVeilVPN", self) welcome_title.setGeometry(20, 45, 760, 60) welcome_title.setStyleSheet(""" font-size: 32px; @@ -2656,17 +2600,23 @@ class ProtocolPage(Page): available_locations_list = [] self.connection_manager.store_locations(locations) - location_geometry = { - "The Netherlands": (395, 300, 185, 75), - "US (Ohio)": (585, 90, 185, 75), - "Malaysia": (395, 90, 185, 75), - "US (Seattle)": (395, 195, 185, 75), - #"Romania": (585, 195, 185, 75), - #"Finland": (395, 300, 185, 75), - "Iceland": (585, 195, 185, 75), - "Moldova": (585, 300, 185, 75) - } - list1 = [(QPushButton, location, location_geometry[location]) for location in available_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) @@ -3209,15 +3159,17 @@ class LocationPage(Page): button.setChecked(False) def create_interface_elements(self, available_locations): + print(available_locations) self.buttonGroup = QButtonGroup(self) self.buttons = [] for j, (object_type, icon_name, geometry) in enumerate(available_locations): + print(object_type, icon_name, geometry) boton = object_type(self) boton.setGeometry(*geometry) boton.setIconSize(boton.size()) boton.setCheckable(True) - boton.setIcon(QIcon(os.path.join(self.btn_path, f"{icon_name}_button.png"))) + boton.setIcon(QIcon(os.path.join(self.btn_path, f"{icon_name.lower()}_button.png"))) self.buttons.append(boton) self.buttonGroup.addButton(boton, j) boton.clicked.connect(lambda _, location=icon_name: self.show_location(location)) @@ -3739,9 +3691,9 @@ class ResumePage(Page): else: application = '' - + print(profile.get('location')) location = self.connection_manager.get_location_info(profile.get('location')) - + print(location) if profile.get('protocol') == 'wireguard': connection_type = 'wireguard' elif profile.get('protocol') == 'residential': @@ -3758,7 +3710,8 @@ class ResumePage(Page): profile_data = { 'id': int(id), 'name': profile.get('name'), - 'location_code': location, + 'country_code': location.country_code, + 'code': location.code, 'application': application, 'connection_type': connection_type, 'resolution': profile.get('dimentions', ''), @@ -3813,7 +3766,7 @@ class EditorPage(Page): self.buttons = [] # Lista para almacenar los labels dinĂ¡micamente 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) @@ -3826,7 +3779,7 @@ class EditorPage(Page): self.name = QLineEdit(self) self.name.setGeometry(250, 68, 400, 30) - self.name.textChanged.connect(self.update_name_value) + self.name.setStyleSheet("border: transparent;") self.temp_changes = {} @@ -3845,8 +3798,12 @@ class EditorPage(Page): self.brow_disp.lower() def update_name_value(self): + original_name = self.data_profile.get('name', '') new_name = self.name.text() - self.update_temp_value('name', new_name) + if original_name != new_name: + self.update_temp_value('name', new_name) + else: + pass def go_back(self): selected_profiles_str = ', '.join([f"Profile_{profile['profile_number']}" for profile in self.page_stack.widget(0).selected_profiles]) @@ -3899,7 +3856,7 @@ class EditorPage(Page): 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): @@ -3987,7 +3944,10 @@ class EditorPage(Page): if browser_version == '': browser_version = data_profile.get('browser_version', '') current_value = f"{data_profile.get(key, '')} {browser_version}" - base_image = BrowserPage.create_browser_button_image(current_value, self.btn_path) + if connection == 'system-wide' or not current_value.strip(): + base_image = QPixmap() + else: + base_image = BrowserPage.create_browser_button_image(current_value, self.btn_path) else: image_path = os.path.join(self.btn_path, f"{data_profile.get(key, '')}_button.png") current_value = data_profile.get(key, '') @@ -4140,7 +4100,6 @@ class EditorPage(Page): self.original_values.pop(selected_profiles_str, None) def update_core_profiles(self, key, new_value): - print('new value', new_value) profile = ProfileController.get(int(self.update_status.current_profile_id)) self.update_res = False if key == 'dimentions': @@ -4183,12 +4142,12 @@ class EditorPage(Page): profile.delete_proxy_configuration() if location: - profile.location.code = location + profile.location.code = location.country_code profile.location.time_zone = self.connection_manager.get_timezone(location) profile.subscription = None - ProfileController.update(profile, resolution=self.update_res) + ProfileController.update(profile) @@ -4232,15 +4191,15 @@ class EditorPage(Page): profile = self.data_profile default_app = 'firefox:123.0' default_resolution = '1024x760' - - location = self.connection_manager.get_location_info(profile.get('location')) + location_code = self.connection_manager.get_location_info(profile.get('location')) connection_type = 'tor' profile_data = { 'id': int(id), 'name': profile.get('name'), - 'location_code': location, + 'country_code': location_code.country_code, + 'code': location_code.code, 'application': default_app , 'connection_type': connection_type, 'resolution': default_resolution, @@ -4287,7 +4246,6 @@ class Settings(Page): def setup_menu_buttons(self): menu_items = [ ("Overview", self.show_account_page), - ("WireGuard Settings", self.show_wireguard_page), ("Subscriptions", self.show_subscription_page), ("Delete Profile", self.show_delete_page), ("Error Logs", self.show_logs_page) @@ -4326,7 +4284,6 @@ class Settings(Page): def setup_pages(self): self.account_page = self.create_account_page() - self.wireguard_page = self.create_wireguard_page() self.subscription_page = self.create_subscription_page() self.logs_page = self.create_logs_page() self.delete_page = self.create_delete_page() @@ -4454,59 +4411,7 @@ class Settings(Page): self.content_layout.addWidget(self.delete_page) self.content_layout.setCurrentWidget(self.delete_page) - def create_wireguard_page(self): - page = QWidget() - layout = QVBoxLayout(page) - layout.setSpacing(20) - layout.setContentsMargins(20, 20, 20, 20) - - title = QLabel("WireGuard Settings") - title.setStyleSheet("color: #808080; font-size: 12px; font-weight: bold;") - layout.addWidget(title) - - profile_group = QGroupBox("Profile Selection") - profile_group.setStyleSheet("QGroupBox { color: white; padding: 15px; }") - profile_layout = QVBoxLayout(profile_group) - - self.wireguard_profile_selector = QComboBox() - self.wireguard_profile_selector.setStyleSheet(self.get_combobox_style()) - self.populate_wireguard_profiles() - profile_layout.addWidget(self.wireguard_profile_selector) - layout.addWidget(profile_group) - - rotation_group = QGroupBox("Key Rotation Settings") - rotation_group.setStyleSheet("QGroupBox { color: white; padding: 15px; }") - rotation_layout = QVBoxLayout(rotation_group) - - self.enable_rotation = QCheckBox("Enable WireGuard key rotation") - self.enable_rotation.setStyleSheet(self.get_checkbox_style()) - rotation_layout.addWidget(self.enable_rotation) - - self.rotation_combo = QComboBox() - self.rotation_combo.addItems(["1 day", "3 days", "1 week", "2 weeks"]) - self.rotation_combo.setStyleSheet(self.get_combobox_style()) - self.rotation_combo.setEnabled(False) - rotation_layout.addWidget(self.rotation_combo) - - layout.addWidget(rotation_group) - - save_button = QPushButton() - save_button.setFixedSize(75, 46) - save_button.setIcon(QIcon(os.path.join(self.btn_path, f"save.png"))) - save_button.setIconSize(QSize(75, 46)) - save_button.clicked.connect(self.save_wireguard_settings) - - button_layout = QHBoxLayout() - button_layout.addStretch() - button_layout.addWidget(save_button) - layout.addLayout(button_layout) - - self.wireguard_profile_selector.currentIndexChanged.connect(self.load_profile_wireguard_settings) - self.enable_rotation.stateChanged.connect(lambda state: self.rotation_combo.setEnabled(state == Qt.CheckState.Checked.value)) - - layout.addStretch() - self.load_profile_wireguard_settings() - return page + def get_combobox_style(self) -> str: return """ @@ -4563,23 +4468,7 @@ class Settings(Page): self.wireguard_profile_selector.addItem(f"Profile {profile_id}: {profile.name}", profile_id) - def load_profile_wireguard_settings(self) -> None: - profile_id = self.wireguard_profile_selector.currentData() - if profile_id is None: - return - - profile = ProfileController.get(profile_id) - rotation_settings = profile.connection.wireguard_rotation_frequency - if rotation_settings: - self.enable_rotation.setChecked(True) - self.rotation_combo.setEnabled(True) - frequency_hours = rotation_settings - duration_text = self.convert_duration(frequency_hours, to_hours=False) - self.rotation_combo.setCurrentText(duration_text) - else: - self.enable_rotation.setChecked(False) - self.rotation_combo.setEnabled(False) def convert_duration(self, value: Union[str, int], to_hours: bool = True) -> Union[str, int]: if to_hours: @@ -4602,47 +4491,24 @@ class Settings(Page): else: raise ValueError(f"Hours value {hours} cannot be converted to days or weeks cleanly") - def save_wireguard_settings(self) -> None: - profile_id = self.wireguard_profile_selector.currentData() - if profile_id is None: - return - profile = ProfileController.get(profile_id) - if not self.enable_rotation.isChecked(): - profile.connection.wireguard_rotation_frequency = None - profile.connection.wireguard_rotation_last_performed = None - ProfileController.update(profile) - self.update_status.update_status("WireGuard rotation disabled for this profile") - return - rotation_duration = self.rotation_combo.currentText() - try: - hours = self.convert_duration(rotation_duration, to_hours=True) - profile.connection.wireguard_rotation_frequency = hours - profile.connection.wireguard_rotation_last_performed = datetime.now(timezone.utc) - ProfileController.update(profile) - self.update_status.update_status("WireGuard settings saved successfully") - except ValueError: - self.update_status.update_status("An error occurred while saving the WireGuard settings") def show_account_page(self): self.content_layout.setCurrentWidget(self.account_page) self.update_button_states(0) - def show_wireguard_page(self): - self.content_layout.setCurrentWidget(self.wireguard_page) - self.update_button_states(1) def show_subscription_page(self): self.content_layout.setCurrentWidget(self.subscription_page) - self.update_button_states(2) + self.update_button_states(1) def show_delete_page(self): self.content_layout.setCurrentWidget(self.delete_page) - self.update_button_states(3) + self.update_button_states(2) def show_logs_page(self): self.content_layout.setCurrentWidget(self.logs_page) - self.update_button_states(4) + self.update_button_states(3) def update_button_states(self, active_index): for i, btn in enumerate(self.menu_buttons): @@ -4770,9 +4636,6 @@ class Settings(Page): self.account_page = self.create_account_page() self.content_layout.addWidget(self.account_page) - self.content_layout.removeWidget(self.wireguard_page) - self.wireguard_page = self.create_wireguard_page() - self.content_layout.addWidget(self.wireguard_page) self.content_layout.removeWidget(self.subscription_page) self.subscription_page = self.create_subscription_page() @@ -4968,13 +4831,11 @@ class Settings(Page): def setup_pages(self): self.account_page = self.create_account_page() - self.wireguard_page = self.create_wireguard_page() self.subscription_page = self.create_subscription_page() self.logs_page = self.create_logs_page() self.delete_page = self.create_delete_page() self.content_layout.addWidget(self.account_page) - self.content_layout.addWidget(self.wireguard_page) self.content_layout.addWidget(self.subscription_page) self.content_layout.addWidget(self.logs_page) self.content_layout.addWidget(self.delete_page) @@ -4991,7 +4852,7 @@ class Settings(Page): title.setStyleSheet("color: #808080; font-size: 12px; font-weight: bold;") layout.addWidget(title) - log_text = QLabel(f"If enabled, these Error Logs would be stored locally on your computer\nat {Constants.HV_DATA_HOME}") + log_text = QLabel(f"If enabled, these Error Logs would be stored locally on your computer\nat {Constants.HV_DATA_HOME}/gui") log_text.setStyleSheet("color: white; font-size: 14px;") layout.addWidget(log_text) @@ -5048,6 +4909,7 @@ class Settings(Page): else: self.update_status.stop_gui_logging() + self.update_status.update_status("Logging settings saved successfully") except Exception as e: diff --git a/gui/resources/images/default_location_mini.png b/gui/resources/images/default_location_mini.png new file mode 100644 index 0000000..66e55e8 Binary files /dev/null and b/gui/resources/images/default_location_mini.png differ diff --git a/gui/resources/images/germany_mini.png b/gui/resources/images/germany.png similarity index 100% rename from gui/resources/images/germany_mini.png rename to gui/resources/images/germany.png diff --git a/gui/resources/images/original.png b/gui/resources/images/original.png index 162b3a8..fdfbfbd 100644 Binary files a/gui/resources/images/original.png and b/gui/resources/images/original.png differ