diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..353c8cc --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# Virtual environments +.env +.venv +env/ +venv/ +ENV/ + +# IDE +.idea/ +.vscode/ +*.swp +*.swo +*~ + +# Flatpak build artifacts +build-dir/ +.flatpak-builder/ + +# OS +.DS_Store +Thumbs.db diff --git a/README.md b/README.md index 6482daf..ebbc92c 100644 --- a/README.md +++ b/README.md @@ -61,4 +61,4 @@ python3 src/main.py ## License -This project is licensed under the terms of the MIT License. See the [LICENSE](LICENSE) file for more details. +This project is licensed under the terms of the GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later). See the [LICENSE](LICENSE) file for more details. diff --git a/src/i18n.py b/src/i18n.py index 00fe2b9..52dcc98 100644 --- a/src/i18n.py +++ b/src/i18n.py @@ -1,6 +1,6 @@ class I18NManager: """A simple internationalization manager to handle string translations.""" - def __init__(self, initial_language="es"): + def __init__(self, initial_language="en"): """Initializes the manager with a given language.""" self.language = initial_language self.translations = { @@ -28,7 +28,7 @@ def __init__(self, initial_language="es"): "sign_button_tooltip_select_area": "Arrastre sobre el documento para seleccionar el área de la firma", "sign_button_tooltip_sign": "Firmar el documento", "preferences": "Preferencias", "general": "General", "language": "Idioma", "certificates": "Certificados", "close_button": "Cerrar", - "toggle_sidebar_tooltip": "Mostrar/Ocular panel lateral", + "toggle_sidebar_tooltip": "Mostrar/Ocultar panel lateral", "manage_certificates_tooltip": "Gestionar certificados", "toast_select_area": "Arrastre para seleccionar un área y pulse el botón de firma", "signatures_found_toast": "Se encontraron {} firmas en el documento.", @@ -38,8 +38,6 @@ def __init__(self, initial_language="es"): "sig_validity_error": "La firma no es criptográficamente válida.", "signer": "Firmante", "sign_date": "Fecha de Firma", - "signer": "Firmante", - "sign_date": "Fecha de Firma", "go_to_signatures": "Ver Firmas", "show_signatures_tooltip": "Mostrar firmas existentes en el documento", "signature_settings": "Ajustes de Firma", @@ -68,7 +66,18 @@ def __init__(self, initial_language="es"): "prev_result_tooltip": "Resultado anterior", "next_result_tooltip": "Siguiente resultado", "print_document": "Imprimir Documento...", - "show_signatures_menu_item": "Mostrar Firmas" + "show_signatures_menu_item": "Mostrar Firmas", + "print_error_title": "Error de Impresión", + "print_error_message": "No se pudo imprimir el documento: {}", + "print_success_toast": "Documento enviado a la impresora.", + "template": "Plantilla", + "template_content": "Contenido de la Plantilla", + "font": "Fuente", + "size": "Tamaño", + "size_small": "Pequeño", + "size_normal": "Normal", + "size_large": "Grande", + "size_huge": "Muy Grande" }, "en": { "window_title": "GNOME-Sign", "open_pdf": "Open PDF...", "prev_page": "Previous page", "next_page": "Next page", @@ -100,10 +109,8 @@ def __init__(self, initial_language="es"): "signatures_found_toast": "Found {} signatures in the document.", "sig_details_title": "Signature Details", "sig_validity_title": "Signature Status", - "sig_validity_ok": "The signature is criptographically valid.", - "sig_validity_error": "The signature is not criptographically valid", - "signer": "Signer", - "sign_date": "Signature Date", + "sig_validity_ok": "The signature is cryptographically valid.", + "sig_validity_error": "The signature is not cryptographically valid.", "signer": "Signer", "sign_date": "Signature Date", "go_to_signatures": "View Signatures", @@ -117,7 +124,7 @@ def __init__(self, initial_language="es"): "signature_reason_label": "Reason", "signature_location_label": "Location", "signature_contact_label": "Contact", - "sig_integrity_ok": "The signature is criptographically valid and the document has not been modified.", + "sig_integrity_ok": "The signature is cryptographically valid and the document has not been modified.", "sig_integrity_error": "The signature is invalid or the document has been modified.", "sig_trust_ok": "The signer's certificate is trusted.", "sig_trust_untrusted": "Could not establish trust in the signer's certificate.", @@ -134,7 +141,18 @@ def __init__(self, initial_language="es"): "prev_result_tooltip": "Previous result", "next_result_tooltip": "Next result", "print_document": "Print Document...", - "show_signatures_menu_item": "Show Signatures" + "show_signatures_menu_item": "Show Signatures", + "print_error_title": "Print Error", + "print_error_message": "Could not print document: {}", + "print_success_toast": "Document sent to printer.", + "template": "Template", + "template_content": "Template Content", + "font": "Font", + "size": "Size", + "size_small": "Small", + "size_normal": "Normal", + "size_large": "Large", + "size_huge": "Huge" } } diff --git a/src/main.py b/src/main.py index e6d5743..e6138f3 100644 --- a/src/main.py +++ b/src/main.py @@ -606,10 +606,6 @@ def search_text(self, text): if self.search_results: self.select_search_result(0) self.display_page(self.current_page, keep_sidebar_view=True) - self.window.sidebar.populate_search_results(self.search_results) - if self.search_results: - self.select_search_result(0) - self.display_page(self.current_page, keep_sidebar_view=True) def clear_search(self): """Clears the current search.""" @@ -654,9 +650,12 @@ def next_search_result(self, button=None): self.select_search_result(next_index) def previous_search_result(self, button=None): - """Navigates to the previous search result.""" - if self.current_search_result_index > 0: - self.select_search_result(self.current_search_result_index - 1) + """Navigates to the previous search result, wrapping around to the end.""" + num_results = len(self.search_results) + if num_results == 0: + return + prev_index = (self.current_search_result_index - 1) % num_results + self.select_search_result(prev_index) def _update_actions_state(self): """Centralized method to update the enabled state of actions.""" @@ -830,6 +829,17 @@ def remove_certificate(self, path): self.config.save() + def remove_template(self, template_id): + """Removes a signature template and updates the active template if necessary.""" + was_active = self.config.get_active_template_id() == template_id + self.config.delete_template(template_id) + # If the deleted template was the active one, select a new active template + if was_active: + templates = self.config.get_signature_templates() + new_active_id = templates[0]['id'] if templates else None + self.config.set_active_template_id(new_active_id) + self.config.save() + def request_add_new_certificate(self): """Manages the full flow of adding a new certificate.""" def on_file_chooser_response(dialog, response): diff --git a/src/ui/app_window.py b/src/ui/app_window.py index ad8242f..79f95d0 100644 --- a/src/ui/app_window.py +++ b/src/ui/app_window.py @@ -203,8 +203,9 @@ def update_search_nav_buttons(self): num_results = len(app.search_results) self.search_nav_box.set_visible(num_results > 0) if num_results > 0: - self.prev_search_button.set_sensitive(app.current_search_result_index > 0) - self.next_search_button.set_sensitive(app.current_search_result_index < num_results - 1) + # Navigation buttons are only useful when there are multiple results to navigate between + self.prev_search_button.set_sensitive(num_results > 1) + self.next_search_button.set_sensitive(num_results > 1) def _on_search_changed(self, entry): """Handles the 'search-changed' signal from the search entry."""