From c98a106d979a961afc2457d4b341d21effbecd9b Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Mon, 14 Jul 2025 02:06:25 -0300 Subject: [PATCH 01/27] Fixed the new diary modal to accept the key "enter" and automatically the function --- src/pilgrim/ui/screens/new_diary_modal.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/pilgrim/ui/screens/new_diary_modal.py b/src/pilgrim/ui/screens/new_diary_modal.py index 2695216..cafd468 100644 --- a/src/pilgrim/ui/screens/new_diary_modal.py +++ b/src/pilgrim/ui/screens/new_diary_modal.py @@ -8,6 +8,7 @@ from textual.widgets import Label, Input, Button class NewDiaryModal(ModalScreen[str]): BINDINGS = [ Binding("escape", "cancel", "Cancel"), + Binding("enter", "create_diary", "Create",priority=True), ] def __init__(self): super().__init__() @@ -31,15 +32,23 @@ class NewDiaryModal(ModalScreen[str]): def on_button_pressed(self, event: Button.Pressed) -> None: """Handles button clicks.""" if event.button.id == "create_diary_button": - diary_name = self.name_input.value.strip() - if diary_name: - self.dismiss(diary_name) - else: - self.notify("Diary name cannot be empty.", severity="warning") - self.name_input.focus() + self.action_create_diary() elif event.button.id == "cancel_button": self.dismiss("") def action_cancel(self) -> None: """Action to cancel the modal.""" - self.dismiss("") \ No newline at end of file + self.dismiss("") + + def action_create_diary(self) -> None: + diary_name = self.name_input.value.strip() + if diary_name: + self.dismiss(diary_name) + else: + self.notify("Diary name cannot be empty.", severity="warning") + self.name_input.focus() + + def on_input_submitted(self, event: Input.Submitted) -> None: + if event.input.id == "NewDiaryModal-NameInput": + self.action_create_diary() + From f174fd1d8a6277512d4413dea93e72a997cf0c83 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Mon, 14 Jul 2025 02:23:29 -0300 Subject: [PATCH 02/27] Fixed the edit diary modal to accept the key "enter" and automatically the function --- src/pilgrim/ui/screens/edit_diary_modal.py | 30 +++++++++++++++------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/pilgrim/ui/screens/edit_diary_modal.py b/src/pilgrim/ui/screens/edit_diary_modal.py index 4f577eb..e54b71f 100644 --- a/src/pilgrim/ui/screens/edit_diary_modal.py +++ b/src/pilgrim/ui/screens/edit_diary_modal.py @@ -8,6 +8,7 @@ from textual.widgets import Label, Input, Button class EditDiaryModal(ModalScreen[tuple[int,str]]): BINDINGS = [ Binding("escape", "cancel", "Cancel"), + Binding("enter", "edit_diary", "Save",priority=True), ] def __init__(self, diary_id: int): @@ -32,17 +33,28 @@ class EditDiaryModal(ModalScreen[tuple[int,str]]): def on_button_pressed(self, event: Button.Pressed) -> None: if event.button.id == "save_diary_button": - new_diary_name = self.name_input.value.strip() - if new_diary_name and new_diary_name != self.current_diary_name: - self.dismiss((self.diary_id, new_diary_name)) - elif new_diary_name == self.current_diary_name: - self.notify("No changes made.", severity="warning") - self.dismiss(None) - else: - self.notify("Diary name cannot be empty.", severity="warning") - self.name_input.focus() + self.action_edit_diary() elif event.button.id == "cancel_button": self.dismiss(None) + def on_key(self, event): + if event.key == "enter": + self.action_edit_diary() + event.prevent_default() + + def action_edit_diary(self) -> None: + new_diary_name = self.name_input.value.strip() + if new_diary_name and new_diary_name != self.current_diary_name: + self.dismiss((self.diary_id, new_diary_name)) + elif new_diary_name == self.current_diary_name: + self.notify("No changes made.", severity="warning") + self.dismiss(None) + else: + self.notify("Diary name cannot be empty.", severity="warning") + self.name_input.focus() + + def on_input_submitted(self, event: Input.Submitted) -> None: + if event.input.id == "edit_diary_name_input": + self.action_edit_diary() def action_cancel(self) -> None: self.dismiss(None) \ No newline at end of file From 18760e174cafe3a1a5d8b22d861183619fa5753f Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Tue, 15 Jul 2025 02:14:53 -0300 Subject: [PATCH 03/27] Add a functionality that automatically opens the diary after creation, Change the responsibility of diary creation to the new_diary_modal.py instead of the diary_list_screen.py --- src/pilgrim/ui/screens/diary_list_screen.py | 30 +++++++-------------- src/pilgrim/ui/screens/new_diary_modal.py | 26 +++++++++++++++--- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/pilgrim/ui/screens/diary_list_screen.py b/src/pilgrim/ui/screens/diary_list_screen.py index 066fbae..b553ed2 100644 --- a/src/pilgrim/ui/screens/diary_list_screen.py +++ b/src/pilgrim/ui/screens/diary_list_screen.py @@ -206,29 +206,17 @@ class DiaryListScreen(Screen): """Action to create new diary""" self.app.push_screen(NewDiaryModal(),self._on_new_diary_submitted) - def _on_new_diary_submitted(self,result): - self.notify(str(result)) - if result: - self.notify(f"Creating Diary:{result}'...") - self.call_later(self._async_create_diary,result) + def _on_new_diary_submitted(self, result): + """Callback after diary creation""" + if result: # Se result não é string vazia, o diário foi criado + self.notify(f"Returning to diary list...") + # Atualiza a lista de diários + self.refresh_diaries() else: - self.notify(f"Canceled...") - - async def _async_create_diary(self,name: str): - - try: - service = self.app.service_manager.get_travel_diary_service() - created_diary = await service.async_create(name) - if created_diary: - self.diary_id_map[created_diary.id] = created_diary.id - await self.async_refresh_diaries() - self.notify(f"Diary: '{name}' created!") - else: - self.notify("Error Creating the diary") - except Exception as e: - self.notify(f"Exception on creating the diary: {str(e)}") - + self.notify(f"Creation canceled...") + def _on_screen_resume(self) -> None: + self.refresh_diaries() def action_edit_selected_diary(self): """Action to edit selected diary""" diff --git a/src/pilgrim/ui/screens/new_diary_modal.py b/src/pilgrim/ui/screens/new_diary_modal.py index cafd468..2238875 100644 --- a/src/pilgrim/ui/screens/new_diary_modal.py +++ b/src/pilgrim/ui/screens/new_diary_modal.py @@ -4,14 +4,17 @@ from textual.containers import Vertical, Horizontal from textual.screen import ModalScreen from textual.widgets import Label, Input, Button +from pilgrim.ui.screens.edit_entry_screen import EditEntryScreen + class NewDiaryModal(ModalScreen[str]): BINDINGS = [ Binding("escape", "cancel", "Cancel"), Binding("enter", "create_diary", "Create",priority=True), ] - def __init__(self): + def __init__(self,autoopen=True): super().__init__() + self.auto_open = autoopen self.name_input = Input(id="NewDiaryModal-NameInput",classes="NewDiaryModal-NameInput") # This ID is fine, it's specific to the input def compose(self) -> ComposeResult: @@ -34,7 +37,7 @@ class NewDiaryModal(ModalScreen[str]): if event.button.id == "create_diary_button": self.action_create_diary() elif event.button.id == "cancel_button": - self.dismiss("") + self.dismiss() def action_cancel(self) -> None: """Action to cancel the modal.""" @@ -43,7 +46,7 @@ class NewDiaryModal(ModalScreen[str]): def action_create_diary(self) -> None: diary_name = self.name_input.value.strip() if diary_name: - self.dismiss(diary_name) + self.call_later(self._async_create_diary, diary_name) else: self.notify("Diary name cannot be empty.", severity="warning") self.name_input.focus() @@ -52,3 +55,20 @@ class NewDiaryModal(ModalScreen[str]): if event.input.id == "NewDiaryModal-NameInput": self.action_create_diary() + async def _async_create_diary(self, name: str): + + try: + service = self.app.service_manager.get_travel_diary_service() + created_diary = await service.async_create(name) + if created_diary: + self.dismiss(name) + self.app.push_screen(EditEntryScreen(diary_id=created_diary.id)) + self.notify(f"Diary: '{name}' created!") + else: + self.notify("Error Creating the diary") + except Exception as e: + self.notify(f"Exception on creating the diary: {str(e)}") + + + + From f838a5b42132d76877df8080b02f1ae4e7be71bc Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Tue, 15 Jul 2025 15:51:30 -0300 Subject: [PATCH 04/27] Add the auto-open option to the new_diary_modal.py --- src/pilgrim/ui/screens/new_diary_modal.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pilgrim/ui/screens/new_diary_modal.py b/src/pilgrim/ui/screens/new_diary_modal.py index 2238875..c98af64 100644 --- a/src/pilgrim/ui/screens/new_diary_modal.py +++ b/src/pilgrim/ui/screens/new_diary_modal.py @@ -62,7 +62,10 @@ class NewDiaryModal(ModalScreen[str]): created_diary = await service.async_create(name) if created_diary: self.dismiss(name) - self.app.push_screen(EditEntryScreen(diary_id=created_diary.id)) + + if self.auto_open: + self.app.push_screen(EditEntryScreen(diary_id=created_diary.id)) + self.notify(f"Diary: '{name}' created!") else: self.notify("Error Creating the diary") From a3123fe32271fedebeaff428bbe7365a0f095938 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Wed, 16 Jul 2025 00:25:37 -0300 Subject: [PATCH 05/27] Bump the version to 0.0.4 on about_screen.py and pyproject.toml --- pyproject.toml | 2 +- src/pilgrim/ui/screens/about_screen.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 6657a3e..eb7ec6b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ [project] name = "Pilgrim" - version = "0.0.3" + version = "0.0.4" authors = [ { name="Gustavo Henrique Santos Souza de Miranda", email="gustavohssmiranda@gmail.com" } ] diff --git a/src/pilgrim/ui/screens/about_screen.py b/src/pilgrim/ui/screens/about_screen.py index 52626bf..2d8566d 100644 --- a/src/pilgrim/ui/screens/about_screen.py +++ b/src/pilgrim/ui/screens/about_screen.py @@ -20,7 +20,7 @@ class AboutScreen(Screen[bool]): self.app_title = Label("Pilgrim", id="AboutScreen_AboutTitle",classes="AboutScreen_AboutTitle") self.content = Label("A TUI Based Travel Diary Application", id="AboutScreen_AboutContent", classes="AboutScreen_AboutContent") - self.version = Label("Version: 0.0.1", id="AboutScreen_AboutVersion", + self.version = Label("Version: 0.0.4", id="AboutScreen_AboutVersion", classes="AboutScreen_AboutVersion") self.developer = Label("Developed By: Gustavo Henrique Miranda ", id="AboutScreen_AboutAuthor") self.contact = Label("git.gustavomiranda.xyz", id="AboutScreen_AboutContact", From 2b851fc7c798b1024f3a57ed5ba5387ee8002d14 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Wed, 16 Jul 2025 00:39:28 -0300 Subject: [PATCH 06/27] Add the use of importlib.metadata.version to keep the version string in sync with the pyproject.toml --- src/pilgrim/ui/screens/about_screen.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pilgrim/ui/screens/about_screen.py b/src/pilgrim/ui/screens/about_screen.py index 2d8566d..eb6cd80 100644 --- a/src/pilgrim/ui/screens/about_screen.py +++ b/src/pilgrim/ui/screens/about_screen.py @@ -3,7 +3,7 @@ from textual.binding import Binding from textual.screen import Screen from textual.widgets import Header, Footer, Button, Label, TextArea from textual.containers import Container - +from importlib.metadata import version class AboutScreen(Screen[bool]): """Screen to display application information.""" @@ -20,7 +20,7 @@ class AboutScreen(Screen[bool]): self.app_title = Label("Pilgrim", id="AboutScreen_AboutTitle",classes="AboutScreen_AboutTitle") self.content = Label("A TUI Based Travel Diary Application", id="AboutScreen_AboutContent", classes="AboutScreen_AboutContent") - self.version = Label("Version: 0.0.4", id="AboutScreen_AboutVersion", + self.version = Label(f"Version: {version('Pilgrim')}", id="AboutScreen_AboutVersion", classes="AboutScreen_AboutVersion") self.developer = Label("Developed By: Gustavo Henrique Miranda ", id="AboutScreen_AboutAuthor") self.contact = Label("git.gustavomiranda.xyz", id="AboutScreen_AboutContact", From 167c2d892883c5d500ce9d0d9bfdece538d47fea Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Wed, 16 Jul 2025 00:50:07 -0300 Subject: [PATCH 07/27] Change to call the method in the super class on the _on_screen_resume method --- src/pilgrim/ui/screens/diary_list_screen.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pilgrim/ui/screens/diary_list_screen.py b/src/pilgrim/ui/screens/diary_list_screen.py index b553ed2..649a508 100644 --- a/src/pilgrim/ui/screens/diary_list_screen.py +++ b/src/pilgrim/ui/screens/diary_list_screen.py @@ -216,6 +216,7 @@ class DiaryListScreen(Screen): self.notify(f"Creation canceled...") def _on_screen_resume(self) -> None: + super()._on_screen_resume() self.refresh_diaries() def action_edit_selected_diary(self): From 3843be6e1302bb03bddc36197e4684ab5b333ed4 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Wed, 16 Jul 2025 02:55:52 -0300 Subject: [PATCH 08/27] Add the tomli library and create the config_manager.py to manage the configuration file and also add the dependency injection on the ui.py via the Application class --- pyproject.toml | 2 ++ src/pilgrim/application.py | 5 +++-- src/pilgrim/ui/ui.py | 4 +++- src/pilgrim/utils/__init__.py | 3 ++- src/pilgrim/utils/config_manager.py | 35 +++++++++++++++++++++++++++++ 5 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 src/pilgrim/utils/config_manager.py diff --git a/pyproject.toml b/pyproject.toml index eb7ec6b..4ccb712 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,6 +20,8 @@ dependencies = [ "sqlalchemy", "textual", + "tomli", + ] [template.plugins.default] diff --git a/src/pilgrim/application.py b/src/pilgrim/application.py index 380c4c2..e7b5419 100644 --- a/src/pilgrim/application.py +++ b/src/pilgrim/application.py @@ -1,17 +1,18 @@ from pilgrim.database import Database from pilgrim.service.servicemanager import ServiceManager from pilgrim.ui.ui import UIApp -from pilgrim.utils import DirectoryManager +from pilgrim.utils import DirectoryManager, ConfigManager class Application: def __init__(self): self.config_dir = DirectoryManager.get_config_directory() self.database = Database() + self.config_manager = ConfigManager() session = self.database.session() session_manager = ServiceManager() session_manager.set_session(session) - self.ui = UIApp(session_manager) + self.ui = UIApp(session_manager,self.config_manager) def run(self): self.database.create() diff --git a/src/pilgrim/ui/ui.py b/src/pilgrim/ui/ui.py index 2443f74..5557993 100644 --- a/src/pilgrim/ui/ui.py +++ b/src/pilgrim/ui/ui.py @@ -9,6 +9,7 @@ from pilgrim.service.servicemanager import ServiceManager from pilgrim.ui.screens.about_screen import AboutScreen from pilgrim.ui.screens.diary_list_screen import DiaryListScreen from pilgrim.ui.screens.edit_entry_screen import EditEntryScreen +from pilgrim.utils import ConfigManager CSS_FILE_PATH = Path(__file__).parent / "styles" / "pilgrim.css" @@ -16,9 +17,10 @@ CSS_FILE_PATH = Path(__file__).parent / "styles" / "pilgrim.css" class UIApp(App): CSS_PATH = CSS_FILE_PATH - def __init__(self,service_manager: ServiceManager, **kwargs): + def __init__(self,service_manager: ServiceManager, config_manager: ConfigManager, **kwargs): super().__init__(**kwargs) self.service_manager = service_manager + self.config_manager = config_manager def on_mount(self) -> None: diff --git a/src/pilgrim/utils/__init__.py b/src/pilgrim/utils/__init__.py index f419fe1..b9fbd1b 100644 --- a/src/pilgrim/utils/__init__.py +++ b/src/pilgrim/utils/__init__.py @@ -1,3 +1,4 @@ from .directory_manager import DirectoryManager +from .config_manager import ConfigManager -__all__ = ['DirectoryManager'] +__all__ = ['DirectoryManager', 'ConfigManager'] diff --git a/src/pilgrim/utils/config_manager.py b/src/pilgrim/utils/config_manager.py new file mode 100644 index 0000000..05b821f --- /dev/null +++ b/src/pilgrim/utils/config_manager.py @@ -0,0 +1,35 @@ +from threading import Lock + +import tomli +from pilgrim.utils import DirectoryManager + +class SingletonMeta(type): + _instances = {} + _lock: Lock = Lock() + + def __call__(cls, *args, **kwargs): + with cls._lock: + if cls not in cls._instances: + instance = super().__call__(*args, **kwargs) + cls._instances[cls] = instance + return cls._instances[cls] + +class ConfigManager(metaclass=SingletonMeta): + def __init__(self): + self.database_url = None + self.database_type = None + self.auto_open_diary = None + self.auto_open_new_diary = None + @staticmethod + def read_config(): + try: + with open(f"{DirectoryManager.get_config_directory()}/config.toml", "rb") as f: + data = tomli.load(f) + print(data) + except FileNotFoundError: + print("Error: config.toml not found.") + except tomli.TOMLDecodeError as e: + print(f"Error decoding TOML: {e}") + + def set_database_url(self): + pass \ No newline at end of file From fe35cb93bdae42f7e4626586b1733b97fdd82feb Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Wed, 16 Jul 2025 15:30:47 -0300 Subject: [PATCH 09/27] Move get_database_path from database.py to directory_manager.py --- src/pilgrim/database.py | 30 ++++---------------------- src/pilgrim/utils/directory_manager.py | 24 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/pilgrim/database.py b/src/pilgrim/database.py index aba4219..5f8bd97 100644 --- a/src/pilgrim/database.py +++ b/src/pilgrim/database.py @@ -5,36 +5,14 @@ from pathlib import Path import os import shutil + Base = declarative_base() -def get_database_path() -> Path: - """ - Get the database file path following XDG Base Directory specification. - Creates the directory if it doesn't exist. - """ - # Get home directory - home = Path.home() - - # Create .pilgrim directory if it doesn't exist - pilgrim_dir = home / ".pilgrim" - pilgrim_dir.mkdir(exist_ok=True) - - # Database file path - db_path = pilgrim_dir / "database.db" - - # If database doesn't exist in new location but exists in current directory, - # migrate it - if not db_path.exists(): - current_db = Path("database.db") - if current_db.exists(): - shutil.copy2(current_db, db_path) - print(f"Database migrated from {current_db} to {db_path}") - - return db_path + class Database: - def __init__(self): - db_path = get_database_path() + def __init__(self,): + db_path = "./" self.engine = create_engine( f"sqlite:///{db_path}", echo=False, diff --git a/src/pilgrim/utils/directory_manager.py b/src/pilgrim/utils/directory_manager.py index c6a0708..a03601a 100644 --- a/src/pilgrim/utils/directory_manager.py +++ b/src/pilgrim/utils/directory_manager.py @@ -1,4 +1,5 @@ import os +import shutil from pathlib import Path @@ -37,3 +38,26 @@ class DirectoryManager: def get_diary_images_directory(directory_name: str) -> Path: """Returns the images directory path for a specific diary.""" return DirectoryManager.get_diary_data_directory(directory_name) / "images" + + @staticmethod + def get_database_path() -> Path: + """ + Get the database file path following XDG Base Directory specification. + Creates the directory if it doesn't exist. + """ + + pilgrim_dir = DirectoryManager.get_config_directory() + pilgrim_dir.mkdir(exist_ok=True) + + # Database file path + db_path = pilgrim_dir / "database.db" + + # If database doesn't exist in new location but exists in current directory, + # migrate it + if not db_path.exists(): + current_db = Path("database.db") + if current_db.exists(): + shutil.copy2(current_db, db_path) + print(f"Database migrated from {current_db} to {db_path}") + + return db_path From a540347127818bced8931703b138a37486e6a3e1 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Wed, 16 Jul 2025 15:31:19 -0300 Subject: [PATCH 10/27] Add Tomli_w library to pyproject.toml --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 4ccb712..0a1b086 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,7 @@ "sqlalchemy", "textual", "tomli", + "tomli_w" ] From bdaa37e355330a67f131c0a83f8279a9481fb3f4 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Wed, 16 Jul 2025 16:01:34 -0300 Subject: [PATCH 11/27] Add the database file path now is read by the configuration file --- src/pilgrim/application.py | 6 +-- src/pilgrim/database.py | 7 +-- src/pilgrim/utils/config_manager.py | 79 +++++++++++++++++++++++++---- 3 files changed, 77 insertions(+), 15 deletions(-) diff --git a/src/pilgrim/application.py b/src/pilgrim/application.py index e7b5419..7ab3acf 100644 --- a/src/pilgrim/application.py +++ b/src/pilgrim/application.py @@ -1,20 +1,20 @@ from pilgrim.database import Database from pilgrim.service.servicemanager import ServiceManager from pilgrim.ui.ui import UIApp -from pilgrim.utils import DirectoryManager, ConfigManager +from pilgrim.utils import ConfigManager class Application: def __init__(self): - self.config_dir = DirectoryManager.get_config_directory() - self.database = Database() self.config_manager = ConfigManager() + self.database = Database(self.config_manager) session = self.database.session() session_manager = ServiceManager() session_manager.set_session(session) self.ui = UIApp(session_manager,self.config_manager) def run(self): + self.config_manager.read_config() self.database.create() self.ui.run() diff --git a/src/pilgrim/database.py b/src/pilgrim/database.py index 5f8bd97..fd144a0 100644 --- a/src/pilgrim/database.py +++ b/src/pilgrim/database.py @@ -5,16 +5,17 @@ from pathlib import Path import os import shutil +from pilgrim.utils import ConfigManager Base = declarative_base() class Database: - def __init__(self,): - db_path = "./" + def __init__(self,config_manager:ConfigManager): + db_path = config_manager.database_url self.engine = create_engine( - f"sqlite:///{db_path}", + f"sqlite:///{config_manager.database_url}", echo=False, connect_args={"check_same_thread": False}, ) diff --git a/src/pilgrim/utils/config_manager.py b/src/pilgrim/utils/config_manager.py index 05b821f..66d643c 100644 --- a/src/pilgrim/utils/config_manager.py +++ b/src/pilgrim/utils/config_manager.py @@ -1,8 +1,13 @@ +import os.path +from os import PathLike from threading import Lock import tomli +import tomli_w + from pilgrim.utils import DirectoryManager + class SingletonMeta(type): _instances = {} _lock: Lock = Lock() @@ -14,22 +19,78 @@ class SingletonMeta(type): cls._instances[cls] = instance return cls._instances[cls] + class ConfigManager(metaclass=SingletonMeta): def __init__(self): self.database_url = None self.database_type = None self.auto_open_diary = None self.auto_open_new_diary = None - @staticmethod - def read_config(): + self.config_dir = DirectoryManager.get_config_directory() + self.__data = None + + def read_config(self): + if os.path.exists(f"{DirectoryManager.get_config_directory()}/config.toml"): + try: + with open(f"{DirectoryManager.get_config_directory()}/config.toml", "rb") as f: + data = tomli.load(f) + print(data) + except FileNotFoundError: + print("Error: config.toml not found.") + except tomli.TOMLDecodeError as e: + print(f"Error decoding TOML: {e}") + + self.__data = data + self.database_url = self.__data["database"]["url"] + self.database_type = self.__data["database"]["type"] + + if self.__data["settings"]["diary"]["auto_open_diary_on_startup"] == "": + self.auto_open_diary = None + self.auto_open_new_diary = self.__data["settings"]["diary"]["auto_open_on_creation"] + else: + print("Error: config.toml not found.") + self.create_config() + self.read_config() + + def create_config(self, config: dict = None): + default = { + "database": { + "url": f"{DirectoryManager.get_config_directory()}/database.db", + "type": "sqlite" + }, + "settings": { + "diary": { + "auto_open_diary_on_startup": "", + "auto_open_on_creation": False + } + } + } + if config is None: + config = default try: - with open(f"{DirectoryManager.get_config_directory()}/config.toml", "rb") as f: - data = tomli.load(f) - print(data) + with open(f"{DirectoryManager.get_config_directory()}/config.toml", "wb") as f: + tomli_w.dump(config, f) except FileNotFoundError: print("Error: config.toml not found.") - except tomli.TOMLDecodeError as e: - print(f"Error decoding TOML: {e}") - def set_database_url(self): - pass \ No newline at end of file + def save_config(self): + if self.__data is None: + self.read_config() + self.__data["database"]["url"] = self.database_url + self.__data["database"]["type"] = self.database_type + self.__data["settings"]["diary"]["auto_open_diary_on_startup"] = self.auto_open_diary or "" + self.__data["settings"]["diary"]["auto_open_on_creation"] = self.auto_open_new_diary + + self.create_config(self.__data) + + def set_config_dir(self, value): + self.config_dir = value + + def set_database_url(self, value: str): + self.database_url = value + + def set_auto_open_diary(self, value: str): + self.auto_open_diary = value + + def set_auto_open_new_diary(self, value: bool): + self.auto_open_new_diary = value From 967c7e4ce64587b42764632c4a2bb46bb58118b6 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Wed, 16 Jul 2025 16:39:31 -0300 Subject: [PATCH 12/27] Fix the Database no being put on the right path according with the config.toml --- src/pilgrim/application.py | 5 +++-- src/pilgrim/database.py | 13 ++++++++++--- src/pilgrim/ui/screens/new_diary_modal.py | 2 +- src/pilgrim/utils/config_manager.py | 14 ++++++++++---- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/pilgrim/application.py b/src/pilgrim/application.py index 7ab3acf..1d2f11a 100644 --- a/src/pilgrim/application.py +++ b/src/pilgrim/application.py @@ -7,14 +7,15 @@ from pilgrim.utils import ConfigManager class Application: def __init__(self): self.config_manager = ConfigManager() + self.config_manager.read_config() # Chamar antes de criar o Database self.database = Database(self.config_manager) session = self.database.session() session_manager = ServiceManager() session_manager.set_session(session) - self.ui = UIApp(session_manager,self.config_manager) + self.ui = UIApp(session_manager, self.config_manager) def run(self): - self.config_manager.read_config() + print(f"URL do banco: {self.config_manager.database_url}") self.database.create() self.ui.run() diff --git a/src/pilgrim/database.py b/src/pilgrim/database.py index fd144a0..8d472af 100644 --- a/src/pilgrim/database.py +++ b/src/pilgrim/database.py @@ -12,10 +12,17 @@ Base = declarative_base() class Database: - def __init__(self,config_manager:ConfigManager): - db_path = config_manager.database_url + + def __init__(self, config_manager: ConfigManager): + self.db_path = config_manager.database_url + + # Garantir que o diretório existe + db_dir = os.path.dirname(self.db_path) + if not os.path.exists(db_dir): + os.makedirs(db_dir, exist_ok=True) + self.engine = create_engine( - f"sqlite:///{config_manager.database_url}", + f"sqlite:///{self.db_path}", echo=False, connect_args={"check_same_thread": False}, ) diff --git a/src/pilgrim/ui/screens/new_diary_modal.py b/src/pilgrim/ui/screens/new_diary_modal.py index e91f516..ecf25bc 100644 --- a/src/pilgrim/ui/screens/new_diary_modal.py +++ b/src/pilgrim/ui/screens/new_diary_modal.py @@ -12,7 +12,7 @@ class NewDiaryModal(ModalScreen[str]): Binding("escape", "cancel", "Cancel"), Binding("enter", "create_diary", "Create",priority=True), ] - def __init__(self,autoopen=True): + def __init__(self,autoopen:bool = True): super().__init__() self.auto_open = autoopen self.name_input = Input(id="NewDiaryModal-NameInput",classes="NewDiaryModal-NameInput") # This ID is fine, it's specific to the input diff --git a/src/pilgrim/utils/config_manager.py b/src/pilgrim/utils/config_manager.py index 66d643c..59c1faf 100644 --- a/src/pilgrim/utils/config_manager.py +++ b/src/pilgrim/utils/config_manager.py @@ -53,9 +53,14 @@ class ConfigManager(metaclass=SingletonMeta): self.read_config() def create_config(self, config: dict = None): + # Garantir que o diretório de configuração existe + config_dir = DirectoryManager.get_config_directory() + if not os.path.exists(config_dir): + os.makedirs(config_dir, exist_ok=True) + default = { "database": { - "url": f"{DirectoryManager.get_config_directory()}/database.db", + "url": f"{config_dir}/database.db", "type": "sqlite" }, "settings": { @@ -67,11 +72,12 @@ class ConfigManager(metaclass=SingletonMeta): } if config is None: config = default + try: - with open(f"{DirectoryManager.get_config_directory()}/config.toml", "wb") as f: + with open(f"{config_dir}/config.toml", "wb") as f: tomli_w.dump(config, f) - except FileNotFoundError: - print("Error: config.toml not found.") + except Exception as e: + print(f"Erro ao criar config: {e}") def save_config(self): if self.__data is None: From a13c56a3a3f9a35644a7e8a7cb7cb17d3be25dda Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Wed, 16 Jul 2025 17:24:45 -0300 Subject: [PATCH 13/27] Fix the NewDiaryModal not accessing the toml file properly to set the auto_open flag --- src/pilgrim/ui/screens/new_diary_modal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pilgrim/ui/screens/new_diary_modal.py b/src/pilgrim/ui/screens/new_diary_modal.py index ecf25bc..0e713a5 100644 --- a/src/pilgrim/ui/screens/new_diary_modal.py +++ b/src/pilgrim/ui/screens/new_diary_modal.py @@ -12,9 +12,9 @@ class NewDiaryModal(ModalScreen[str]): Binding("escape", "cancel", "Cancel"), Binding("enter", "create_diary", "Create",priority=True), ] - def __init__(self,autoopen:bool = True): + def __init__(self): super().__init__() - self.auto_open = autoopen + self.auto_open = self.app.config_manager.auto_open_new_diary self.name_input = Input(id="NewDiaryModal-NameInput",classes="NewDiaryModal-NameInput") # This ID is fine, it's specific to the input def compose(self) -> ComposeResult: From 4436d5e081e4c300f745372336cc46ba118ae712 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Miranda Date: Wed, 16 Jul 2025 18:12:32 -0300 Subject: [PATCH 14/27] Update src/pilgrim/utils/directory_manager.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- src/pilgrim/utils/directory_manager.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pilgrim/utils/directory_manager.py b/src/pilgrim/utils/directory_manager.py index a03601a..7a39670 100644 --- a/src/pilgrim/utils/directory_manager.py +++ b/src/pilgrim/utils/directory_manager.py @@ -45,11 +45,7 @@ class DirectoryManager: Get the database file path following XDG Base Directory specification. Creates the directory if it doesn't exist. """ - pilgrim_dir = DirectoryManager.get_config_directory() - pilgrim_dir.mkdir(exist_ok=True) - - # Database file path db_path = pilgrim_dir / "database.db" # If database doesn't exist in new location but exists in current directory, @@ -57,7 +53,11 @@ class DirectoryManager: if not db_path.exists(): current_db = Path("database.db") if current_db.exists(): - shutil.copy2(current_db, db_path) - print(f"Database migrated from {current_db} to {db_path}") + try: + shutil.copy2(current_db, db_path) + # Consider using logging instead of print + print(f"Database migrated from {current_db} to {db_path}") + except (OSError, shutil.Error) as e: + raise RuntimeError(f"Failed to migrate database: {e}") return db_path From 23ef60b55a649de3f33ed93efb8906e3e47a9dc6 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Wed, 16 Jul 2025 18:28:42 -0300 Subject: [PATCH 15/27] Improve exception handling, remove debug print statements --- src/pilgrim/utils/config_manager.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/pilgrim/utils/config_manager.py b/src/pilgrim/utils/config_manager.py index 59c1faf..7a0f856 100644 --- a/src/pilgrim/utils/config_manager.py +++ b/src/pilgrim/utils/config_manager.py @@ -34,11 +34,11 @@ class ConfigManager(metaclass=SingletonMeta): try: with open(f"{DirectoryManager.get_config_directory()}/config.toml", "rb") as f: data = tomli.load(f) - print(data) - except FileNotFoundError: - print("Error: config.toml not found.") + except tomli.TOMLDecodeError as e: - print(f"Error decoding TOML: {e}") + raise ValueError(f"Invalid TOML configuration: {e}") + except Exception as e: + raise RuntimeError(f"Error reading configuration: {e}") self.__data = data self.database_url = self.__data["database"]["url"] @@ -77,17 +77,22 @@ class ConfigManager(metaclass=SingletonMeta): with open(f"{config_dir}/config.toml", "wb") as f: tomli_w.dump(config, f) except Exception as e: - print(f"Erro ao criar config: {e}") + raise RuntimeError(f"Error creating configuration: {e}") def save_config(self): if self.__data is None: self.read_config() + if self.__data is None: + raise RuntimeError("Error reading configuration.") + self.__data["database"]["url"] = self.database_url self.__data["database"]["type"] = self.database_type self.__data["settings"]["diary"]["auto_open_diary_on_startup"] = self.auto_open_diary or "" self.__data["settings"]["diary"]["auto_open_on_creation"] = self.auto_open_new_diary - - self.create_config(self.__data) + try: + self.create_config(self.__data) + except Exception as e: + raise RuntimeError(f"Error saving configuration: {e}") def set_config_dir(self, value): self.config_dir = value From 71d5491233007421c01cfba8665a296906a70045 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Thu, 17 Jul 2025 20:32:54 -0300 Subject: [PATCH 16/27] Improve the CSS and the code for the photo sidebar --- src/pilgrim/ui/screens/edit_entry_screen.py | 30 ++++++++--------- src/pilgrim/ui/styles/pilgrim.css | 37 +++++++++------------ 2 files changed, 29 insertions(+), 38 deletions(-) diff --git a/src/pilgrim/ui/screens/edit_entry_screen.py b/src/pilgrim/ui/screens/edit_entry_screen.py index e2902c1..7c11556 100644 --- a/src/pilgrim/ui/screens/edit_entry_screen.py +++ b/src/pilgrim/ui/screens/edit_entry_screen.py @@ -87,7 +87,7 @@ class EditEntryScreen(Screen): self.text_entry = TextArea(id="text_entry", classes="EditEntryScreen-text-entry") # Sidebar widgets - self.sidebar_title = Static("📸 Photos", classes="EditEntryScreen-sidebar-title") + self.sidebar_title = Static("Photos", classes="EditEntryScreen-sidebar-title") self.photo_list = OptionList(id="photo_list", classes="EditEntryScreen-sidebar-photo-list") self.photo_info = Static("", classes="EditEntryScreen-sidebar-photo-info") self.help_text = Static("", classes="EditEntryScreen-sidebar-help") @@ -296,30 +296,28 @@ class EditEntryScreen(Screen): if not self.cached_photos: self.photo_info.update("No photos found for this diary") - self.help_text.update("📸 No photos available\n\nUse Photo Manager to add photos") + self.help_text.update("No photos available\n\nUse Photo Manager to add photos") return # Add photos to the list with hash for photo in self.cached_photos: # Show name and hash in the list photo_hash = str(photo.photo_hash)[:8] - self.photo_list.add_option(f"📷 {photo.name} \\[{photo_hash}\]") + self.photo_list.add_option(f"{photo.name} \\[{photo_hash}\]") - self.photo_info.update(f"📸 {len(self.cached_photos)} photos in diary") + self.photo_info.update(f"{len(self.cached_photos)} photos in diary") # Updated help a text with hash information help_text = ( - "[b]⌨️ Sidebar Shortcuts[/b]\n" + "[b]Sidebar Shortcuts[/b]\n" "[b][green]i[/green][/b]: Insert photo into entry\n" "[b][green]n[/green][/b]: Add new photo\n" "[b][green]d[/green][/b]: Delete selected photo\n" "[b][green]e[/green][/b]: Edit selected photo\n" "[b][yellow]Tab[/yellow][/b]: Back to editor\n" "[b][yellow]F8[/yellow][/b]: Show/hide sidebar\n" - "[b][yellow]F9[/yellow][/b]: Switch focus (if needed)\n\n" "[b]📝 Photo References[/b]\n" - "Use: \\[\\[photo:name:hash\\]\\]\n" - "Or: \\[\\[photo::hash\\]\\]" + "\\[\\[photo::hash\\]\\]" ) self.help_text.update(help_text) except Exception as e: @@ -429,9 +427,7 @@ class EditEntryScreen(Screen): photo_details += f"🔗 {photo_hash}\n" photo_details += f"📅 {selected_photo.addition_date}\n" photo_details += f"💬 {selected_photo.caption or 'No caption'}\n" - photo_details += f"📁 {selected_photo.filepath}\n\n" photo_details += f"[b]Reference formats:[/b]\n" - photo_details += f"\\[\\[photo:{selected_photo.name}:{photo_hash}\\]\\]\n" photo_details += f"\\[\\[photo::{photo_hash}\\]\\]" self.photo_info.update(photo_details) @@ -742,15 +738,15 @@ class EditEntryScreen(Screen): self.notify(f"Selected photo: {selected_photo.name} \\[{photo_hash}\\]") # Update photo info with details including hash - photo_details = f"📷 {selected_photo.name}\n" - photo_details += f"🔗 {photo_hash}\n" - photo_details += f"📅 {selected_photo.addition_date}\n" + photo_details = f"Name: {selected_photo.name}\n" + photo_details += f"Hash: {photo_hash}\n" + photo_details += f"Date: {selected_photo.addition_date}\n" if selected_photo.caption: - photo_details += f"💬 {selected_photo.caption}\n" - photo_details += f"📁 {selected_photo.filepath}\n\n" + photo_details += f"Caption: {selected_photo.caption}\n" + else: + photo_details += f"Caption: No Caption\n" photo_details += f"[b]Reference formats:[/b]\n" - photo_details += f"\\[\\[photo:{selected_photo.name}:{photo_hash}\\]\\]\n" - photo_details += f"\\[\\[photo::{photo_hash}\\]\\]" + photo_details += f"\\[\\[photo::{photo_hash}]]" self.photo_info.update(photo_details) diff --git a/src/pilgrim/ui/styles/pilgrim.css b/src/pilgrim/ui/styles/pilgrim.css index 5b52192..b36a146 100644 --- a/src/pilgrim/ui/styles/pilgrim.css +++ b/src/pilgrim/ui/styles/pilgrim.css @@ -389,22 +389,9 @@ Screen.-modal { width: 1fr; } -.EditEntryScreen-sidebar { - width: 40; - min-height: 10; - border-left: solid green; - padding: 1; - background: $surface-darken-2; - color: $primary; - text-style: bold; - content-align: left top; +.EditEntryScreen-sidebar{ + background: $primary-darken-1; } - -.EditEntryScreen-content-container { - layout: horizontal; - height: 1fr; -} - .EditEntryScreen-sidebar-title { text-align: center; text-style: bold; @@ -417,30 +404,38 @@ Screen.-modal { .EditEntryScreen-sidebar-content { height: 1fr; layout: vertical; + margin-left: 2; + margin-right: 2; + } .EditEntryScreen-sidebar-photo-list { - height: 1fr; + height: 0.5fr; /* Pega o espaço restante disponível */ + min-height: 10; /* Garante altura mínima para não sumir */ border: solid $accent; margin-bottom: 1; + overflow-y: auto; /* Adiciona scroll vertical se necessário */ } .EditEntryScreen-sidebar-photo-info { - height: auto; - min-height: 3; + height: 0.5fr; + max-height: 15; /* Limita altura máxima */ + min-height: 6; border: solid $warning; - padding: 1; margin-bottom: 1; background: $surface-darken-1; + overflow-y: auto; /* Adiciona scroll se exceder max-height */ } .EditEntryScreen-sidebar-help { - height: auto; - min-height: 8; + height: 1fr; + max-height: 10; /* Altura máxima menor que info */ + min-height: 8; /* Altura mínima menor */ border: solid $success; padding: 1; background: $surface-darken-1; text-style: italic; + overflow-y: auto; /* Adiciona scroll se exceder max-height */ } /* Photo Modal Styles */ From 165bc10a631fb4b0d0e5a62693fec04e00ed808d Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Thu, 17 Jul 2025 20:48:59 -0300 Subject: [PATCH 17/27] Change the CSS to fit the text better and also limited the width of the sidebar --- src/pilgrim/ui/styles/pilgrim.css | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/pilgrim/ui/styles/pilgrim.css b/src/pilgrim/ui/styles/pilgrim.css index b36a146..2d1b7f9 100644 --- a/src/pilgrim/ui/styles/pilgrim.css +++ b/src/pilgrim/ui/styles/pilgrim.css @@ -391,6 +391,7 @@ Screen.-modal { .EditEntryScreen-sidebar{ background: $primary-darken-1; + width: 35%; } .EditEntryScreen-sidebar-title { text-align: center; @@ -411,7 +412,7 @@ Screen.-modal { .EditEntryScreen-sidebar-photo-list { height: 0.5fr; /* Pega o espaço restante disponível */ - min-height: 10; /* Garante altura mínima para não sumir */ + min-height: 8; /* Garante altura mínima para não sumir */ border: solid $accent; margin-bottom: 1; overflow-y: auto; /* Adiciona scroll vertical se necessário */ @@ -419,8 +420,8 @@ Screen.-modal { .EditEntryScreen-sidebar-photo-info { height: 0.5fr; - max-height: 15; /* Limita altura máxima */ - min-height: 6; + max-height: 13; /* Limita altura máxima */ + min-height: 5; border: solid $warning; margin-bottom: 1; background: $surface-darken-1; @@ -429,7 +430,7 @@ Screen.-modal { .EditEntryScreen-sidebar-help { height: 1fr; - max-height: 10; /* Altura máxima menor que info */ + max-height: 12; /* Altura máxima menor que info */ min-height: 8; /* Altura mínima menor */ border: solid $success; padding: 1; From 1d08f4e40df9cca2ac5465a4ca1d32986f11fa1b Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Thu, 17 Jul 2025 21:39:05 -0300 Subject: [PATCH 18/27] Change the CSS to better distribute the elements of the sidebar --- src/pilgrim/ui/styles/pilgrim.css | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/pilgrim/ui/styles/pilgrim.css b/src/pilgrim/ui/styles/pilgrim.css index 2d1b7f9..5b9bf3b 100644 --- a/src/pilgrim/ui/styles/pilgrim.css +++ b/src/pilgrim/ui/styles/pilgrim.css @@ -391,7 +391,7 @@ Screen.-modal { .EditEntryScreen-sidebar{ background: $primary-darken-1; - width: 35%; + width: 45%; } .EditEntryScreen-sidebar-title { text-align: center; @@ -405,23 +405,24 @@ Screen.-modal { .EditEntryScreen-sidebar-content { height: 1fr; layout: vertical; - margin-left: 2; - margin-right: 2; + margin-left: 1; + margin-right: 1; } .EditEntryScreen-sidebar-photo-list { - height: 0.5fr; /* Pega o espaço restante disponível */ - min-height: 8; /* Garante altura mínima para não sumir */ + height: 2fr; /* Pega o espaço restante disponível */ + min-height: 5; /* Garante altura mínima para não sumir */ border: solid $accent; margin-bottom: 1; overflow-y: auto; /* Adiciona scroll vertical se necessário */ } .EditEntryScreen-sidebar-photo-info { - height: 0.5fr; - max-height: 13; /* Limita altura máxima */ - min-height: 5; + height: 1fr; + max-height: 15; /* Limita altura máxima */ + min-height: 13; + padding: 1; border: solid $warning; margin-bottom: 1; background: $surface-darken-1; @@ -430,7 +431,7 @@ Screen.-modal { .EditEntryScreen-sidebar-help { height: 1fr; - max-height: 12; /* Altura máxima menor que info */ + max-height: 10; /* Altura máxima menor que info */ min-height: 8; /* Altura mínima menor */ border: solid $success; padding: 1; From a9d39f415a46d9645025908b1f0d0ddc42d068fa Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Fri, 18 Jul 2025 00:03:13 -0300 Subject: [PATCH 19/27] Fix the photo edit to properly pass the original photo hash that was missing --- src/pilgrim/ui/screens/edit_entry_screen.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pilgrim/ui/screens/edit_entry_screen.py b/src/pilgrim/ui/screens/edit_entry_screen.py index 7c11556..0e5a027 100644 --- a/src/pilgrim/ui/screens/edit_entry_screen.py +++ b/src/pilgrim/ui/screens/edit_entry_screen.py @@ -611,7 +611,8 @@ class EditEntryScreen(Screen): addition_date=original_photo.addition_date, caption=photo_data["caption"], entries=original_photo.entries if original_photo.entries is not None else [], - id=original_photo.id + id=original_photo.id, + photo_hash=original_photo.photo_hash, ) result = photo_service.update(original_photo, updated_photo) From 0567495ff927488bf82d5a78292f743ad00bf422 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Fri, 18 Jul 2025 02:27:16 -0300 Subject: [PATCH 20/27] Refactor the edit and add photo modal and remove the hashing methods out of the modals --- src/pilgrim/ui/screens/modals/add_photo_modal.py | 16 +++------------- .../ui/screens/modals/edit_photo_modal.py | 13 ++++--------- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/src/pilgrim/ui/screens/modals/add_photo_modal.py b/src/pilgrim/ui/screens/modals/add_photo_modal.py index 89181b2..7384fe0 100644 --- a/src/pilgrim/ui/screens/modals/add_photo_modal.py +++ b/src/pilgrim/ui/screens/modals/add_photo_modal.py @@ -15,12 +15,6 @@ class AddPhotoModal(Screen): self.result = None self.created_photo = None - def _generate_photo_hash(self, photo_data: dict) -> str: - """Generate a short, unique hash for a photo""" - # Use temporary data for hash generation - unique_string = f"{photo_data['name']}_{photo_data.get('photo_id', 0)}_new" - hash_object = hashlib.md5(unique_string.encode()) - return hash_object.hexdigest()[:8] def compose(self) -> ComposeResult: yield Container( @@ -82,13 +76,9 @@ class AddPhotoModal(Screen): if new_photo: self.created_photo = new_photo - # Generate hash for the new photo - photo_hash = self._generate_photo_hash({ - "name": new_photo.name, - "photo_id": new_photo.id - }) + - self.notify(f"Photo '{new_photo.name}' added successfully!\nHash: {photo_hash}\nReference: \\[\\[photo:{new_photo.name}:{photo_hash}\\]\\]", + self.notify(f"Photo '{new_photo.name}' added successfully!\nHash: {new_photo.photo_hash[:8]}\nReference: \\[\\[photo:{new_photo.name}:{new_photo.photo_hash[:8]}\\]\\]", severity="information", timeout=5) # Return the created photo data to the calling screen @@ -97,7 +87,7 @@ class AddPhotoModal(Screen): "name": photo_data["name"], "caption": photo_data["caption"], "photo_id": new_photo.id, - "hash": photo_hash + "hash": new_photo.photo_hash } self.dismiss(self.result) else: diff --git a/src/pilgrim/ui/screens/modals/edit_photo_modal.py b/src/pilgrim/ui/screens/modals/edit_photo_modal.py index 9a44d1d..010b6f8 100644 --- a/src/pilgrim/ui/screens/modals/edit_photo_modal.py +++ b/src/pilgrim/ui/screens/modals/edit_photo_modal.py @@ -12,15 +12,11 @@ class EditPhotoModal(Screen): self.photo = photo self.result = None - def _generate_photo_hash(self, photo: Photo) -> str: - """Generate a short, unique hash for a photo""" - unique_string = f"{photo.name}_{photo.id}_{photo.addition_date}" - hash_object = hashlib.md5(unique_string.encode()) - return hash_object.hexdigest()[:8] + def compose(self) -> ComposeResult: # Generate hash for this photo - photo_hash = self._generate_photo_hash(self.photo) + photo_hash = None yield Container( Static("✏️ Edit Photo", classes="EditPhotoModal-Title"), @@ -45,10 +41,9 @@ class EditPhotoModal(Screen): id="caption-input", classes="EditPhotoModal-Input" ), - Static(f"🔗 Photo Hash: {photo_hash}", classes="EditPhotoModal-Hash"), + Static(f"🔗 Photo Hash: {self.photo.photo_hash[:8]}", classes="EditPhotoModal-Hash"), Static("Reference formats:", classes="EditPhotoModal-Label"), - Static(f"\\[\\[photo:{self.photo.name}:{photo_hash}\\]\\]", classes="EditPhotoModal-Reference"), - Static(f"\\[\\[photo::{photo_hash}\\]\\]", classes="EditPhotoModal-Reference"), + Static(f"\\[\\[photo::{self.photo.photo_hash[:8]}\\]\\]", classes="EditPhotoModal-Reference"), Horizontal( Button("Save Changes", id="save-button", classes="EditPhotoModal-Button"), Button("Cancel", id="cancel-button", classes="EditPhotoModal-Button"), From ca53ac77787443cb5e383f84c171591b3c6174ff Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Fri, 18 Jul 2025 02:37:07 -0300 Subject: [PATCH 21/27] Remove the unused import and unused variable --- src/pilgrim/ui/screens/modals/edit_photo_modal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pilgrim/ui/screens/modals/edit_photo_modal.py b/src/pilgrim/ui/screens/modals/edit_photo_modal.py index 010b6f8..b277164 100644 --- a/src/pilgrim/ui/screens/modals/edit_photo_modal.py +++ b/src/pilgrim/ui/screens/modals/edit_photo_modal.py @@ -3,7 +3,7 @@ from textual.screen import Screen from textual.widgets import Static, Input, Button from textual.containers import Container, Horizontal from pilgrim.models.photo import Photo -import hashlib + class EditPhotoModal(Screen): """Modal for editing an existing photo (name and caption only)""" @@ -16,7 +16,7 @@ class EditPhotoModal(Screen): def compose(self) -> ComposeResult: # Generate hash for this photo - photo_hash = None + yield Container( Static("✏️ Edit Photo", classes="EditPhotoModal-Title"), From 9e4b08234f7a6d7051eddffef65e5dbc20914bf3 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Sat, 19 Jul 2025 00:16:29 -0300 Subject: [PATCH 22/27] Fix the bug that collides the hash if identical images --- src/pilgrim/models/photo.py | 4 ++++ src/pilgrim/service/photo_service.py | 17 ++++++++++++----- .../ui/screens/modals/add_photo_modal.py | 6 ++++++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/pilgrim/models/photo.py b/src/pilgrim/models/photo.py index 02fdcc0..3a1ac9b 100644 --- a/src/pilgrim/models/photo.py +++ b/src/pilgrim/models/photo.py @@ -4,6 +4,7 @@ from pathlib import Path from sqlalchemy import Column, Integer, String, ForeignKey, DateTime from sqlalchemy.orm import relationship +from sqlalchemy.sql.schema import Index from pilgrim.models.photo_in_entry import photo_entry_association from ..database import Base @@ -24,6 +25,9 @@ class Photo(Base): ) fk_travel_diary_id = Column(Integer, ForeignKey("travel_diaries.id"),nullable=False) + __table_args__ = ( + Index('idx_photo_hash_diary', 'hash', 'fk_travel_diary_id'), + ) def __init__(self, filepath, name, photo_hash, addition_date=None, caption=None, entries=None, fk_travel_diary_id=None, **kw: Any): super().__init__(**kw) diff --git a/src/pilgrim/service/photo_service.py b/src/pilgrim/service/photo_service.py index 4907dfb..f23ae3f 100644 --- a/src/pilgrim/service/photo_service.py +++ b/src/pilgrim/service/photo_service.py @@ -14,8 +14,9 @@ class PhotoService: def __init__(self, session): self.session = session - def _hash_file(self, filepath: Path) -> str: - """Calculate hash of a file using SHA3-384.""" + @staticmethod + def hash_file(filepath: Path) -> str: + """Calculate the hash of a file using SHA3-384.""" hash_func = hashlib.new('sha3_384') with open(filepath, 'rb') as f: while chunk := f.read(8192): @@ -64,10 +65,18 @@ class PhotoService: return dest_path + def check_photo_by_hash(self, photohash:str, traveldiaryid:int): + photo = (self.session.query(Photo).filter(Photo.photo_hash == photohash,Photo.fk_travel_diary_id == traveldiaryid) + .first()) + return photo + def create(self, filepath: Path, name: str, travel_diary_id: int, caption=None, addition_date=None) -> Photo | None: travel_diary = self.session.query(TravelDiary).filter(TravelDiary.id == travel_diary_id).first() if not travel_diary: return None + photo_hash = self.hash_file(filepath) + if self.check_photo_by_hash(photo_hash, travel_diary_id): + return None # Copy photo to diary's images directory copied_path = self._copy_photo_to_diary(filepath, travel_diary) @@ -79,8 +88,6 @@ class PhotoService: except ValueError: addition_date = None - # Calculate hash from the copied file - photo_hash = self._hash_file(copied_path) new_photo = Photo( filepath=str(copied_path), # Store the path to the copied file @@ -118,7 +125,7 @@ class PhotoService: old_path.unlink() original.filepath = str(new_path) # Update hash based on the new copied file - original.photo_hash = self._hash_file(new_path) + original.photo_hash = self.hash_file(new_path) original.name = photo_dst.name original.addition_date = photo_dst.addition_date diff --git a/src/pilgrim/ui/screens/modals/add_photo_modal.py b/src/pilgrim/ui/screens/modals/add_photo_modal.py index 7384fe0..5a7c8cb 100644 --- a/src/pilgrim/ui/screens/modals/add_photo_modal.py +++ b/src/pilgrim/ui/screens/modals/add_photo_modal.py @@ -63,10 +63,16 @@ class AddPhotoModal(Screen): async def _async_create_photo(self, photo_data: dict): """Creates a new photo asynchronously using PhotoService""" + + try: service_manager = self.app.service_manager photo_service = service_manager.get_photo_service() + if photo_service.check_photo_by_hash(photo_service.hash_file(photo_data["filepath"]),self.diary_id): + self.notify("Photo already exists in database", severity="error") + return + new_photo = photo_service.create( filepath=Path(photo_data["filepath"]), name=photo_data["name"], From a1e718c1fc59b05a6a70bc31d1e417b3d08f5874 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Miranda Date: Sat, 19 Jul 2025 17:34:05 -0300 Subject: [PATCH 23/27] Update CHANGELOG.md Added info for the next alpha version 0.0.4 --- CHANGELOG.md | 89 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 809bfe6..09c6605 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,51 +1,70 @@ -# Changelog - +Changelog All notable changes to this project will be documented in this file. +The format is based on Keep a Changelog, and this project adheres to Semantic Versioning. +Unreleased +Planned -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +Installation Method 1 (repository compilation) +Organization of trips by date, location, or theme +Enhanced photo management features +Search functionality +Export features +Testing implementation -## [Unreleased] +[0.0.4] - 2025-07-19 +Added -### Planned +Support for creating new diaries asynchronously, with an option to automatically open the newly created diary +Unified "Enter" key support for saving or creating diaries across relevant modals +Automatic diary list refresh when returning to the diary screen +Application configuration management with a new centralized config system +Database location and initialization now configurable via the new config manager +Automatic migration of database file to the configuration directory +Display of database URL on application startup for transparency +Duplicate photo detection before photo creation to prevent redundant entries +Photo hash indexing to improve photo lookup performance -- Installation Method 1 (repository compilation) -- Organization of trips by date, location, or theme -- Enhanced photo management features -- Search functionality -- Export features -- Testing implementation +Changed -## [0.0.3] - 2025-07-07 +Enhanced feedback and validation when editing or creating diary names +Streamlined and unified save logic for diary modals, reducing duplicated behavior +About screen now displays the actual installed application version dynamically +Sidebar and photo-related UI text updated to remove emoji icons for a cleaner appearance +Sidebar layout and scrolling behavior improved for better usability +Photo hash generation now relies on existing service-provided hashes instead of local computation -### Changed -- Removed the dependency on textual-dev from pyproject.toml +Improved -## [0.0.2] - 2025-07-07 +Enhanced feedback and validation when editing or creating diary names +Streamlined and unified save logic for diary modals, reducing duplicated behavior +Sidebar layout and scrolling behavior for better usability -### Changed -- Changed the license in pyproject.toml to BSD +[0.0.3] - 2025-07-07 +Changed -## [0.0.1] - 2025-07-06 +Removed the dependency on textual-dev from pyproject.toml -### Added +[0.0.2] - 2025-07-07 +Changed -- Initial alpha release of Pilgrim travel diary application -- Create and edit travel diaries -- Create and edit diary entries -- Photo ingestion system -- Photo addition and reference via sidebar -- Text User Interface (TUI) built with Textual framework -- Pre-compiled binary installation method (Method 2) -- Support for Linux operating systems -- Basic project documentation (README) +Changed the license in pyproject.toml to BSD -### Known Issues +[0.0.1] - 2025-07-06 +Added -- Installation Method 1 not yet implemented -- No testing suite implemented yet -- Some features may be unstable in an alpha version +Initial alpha release of Pilgrim travel diary application +Create and edit travel diaries +Create and edit diary entries +Photo ingestion system +Photo addition and reference via sidebar +Text User Interface (TUI) built with Textual framework +Pre-compiled binary installation method (Method 2) +Support for Linux operating systems +Basic project documentation (README) -[Unreleased]: https://github.com/username/pilgrim/compare/v0.0.1...HEAD +Known Issues -[0.0.1]: https://github.com/username/pilgrim/releases/tag/v0.0.1 +Installation Method 1 not yet implemented +No testing suite implemented yet +Some features may be unstable in an alpha version +Chat controls Sonnet 4 From 0cbcbd3a8dfaee38404c940c9aeb37b4326d10d8 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Miranda Date: Sat, 19 Jul 2025 17:40:01 -0300 Subject: [PATCH 24/27] Update CHANGELOG.md Revert the markdown format missing from the last update --- CHANGELOG.md | 108 +++++++++++++++++++++++++-------------------------- 1 file changed, 53 insertions(+), 55 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09c6605..ff3e8f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,70 +1,68 @@ -Changelog +# Changelog + All notable changes to this project will be documented in this file. The format is based on Keep a Changelog, and this project adheres to Semantic Versioning. -Unreleased -Planned -Installation Method 1 (repository compilation) -Organization of trips by date, location, or theme -Enhanced photo management features -Search functionality -Export features -Testing implementation +## Unreleased -[0.0.4] - 2025-07-19 -Added +## Planned +* Installation Method 1 (repository compilation) +* Organization of trips by date, location, or theme +* Enhanced photo management features +* Search functionality +* Export features +* Testing implementation -Support for creating new diaries asynchronously, with an option to automatically open the newly created diary -Unified "Enter" key support for saving or creating diaries across relevant modals -Automatic diary list refresh when returning to the diary screen -Application configuration management with a new centralized config system -Database location and initialization now configurable via the new config manager -Automatic migration of database file to the configuration directory -Display of database URL on application startup for transparency -Duplicate photo detection before photo creation to prevent redundant entries -Photo hash indexing to improve photo lookup performance +## [0.0.4] - 2025-07-19 -Changed +### Added +* Support for creating new diaries asynchronously, with an option to automatically open the newly created diary +* Unified "Enter" key support for saving or creating diaries across relevant modals +* Automatic diary list refresh when returning to the diary screen +* Application configuration management with a new centralized config system +* Database location and initialization now configurable via the new config manager +* Automatic migration of database file to the configuration directory +* Display of database URL on application startup for transparency +* Duplicate photo detection before photo creation to prevent redundant entries +* Photo hash indexing to improve photo lookup performance -Enhanced feedback and validation when editing or creating diary names -Streamlined and unified save logic for diary modals, reducing duplicated behavior -About screen now displays the actual installed application version dynamically -Sidebar and photo-related UI text updated to remove emoji icons for a cleaner appearance -Sidebar layout and scrolling behavior improved for better usability -Photo hash generation now relies on existing service-provided hashes instead of local computation +### Changed +* Enhanced feedback and validation when editing or creating diary names +* Streamlined and unified save logic for diary modals, reducing duplicated behavior +* About screen now displays the actual installed application version dynamically +* Sidebar and photo-related UI text updated to remove emoji icons for a cleaner appearance +* Sidebar layout and scrolling behavior improved for better usability +* Photo hash generation now relies on existing service-provided hashes instead of local computation -Improved +### Improved +* Enhanced feedback and validation when editing or creating diary names +* Streamlined and unified save logic for diary modals, reducing duplicated behavior +* Sidebar layout and scrolling behavior for better usability -Enhanced feedback and validation when editing or creating diary names -Streamlined and unified save logic for diary modals, reducing duplicated behavior -Sidebar layout and scrolling behavior for better usability +## [0.0.3] - 2025-07-07 -[0.0.3] - 2025-07-07 -Changed +### Changed +* Removed the dependency on textual-dev from pyproject.toml -Removed the dependency on textual-dev from pyproject.toml +## [0.0.2] - 2025-07-07 -[0.0.2] - 2025-07-07 -Changed +### Changed +* Changed the license in pyproject.toml to BSD -Changed the license in pyproject.toml to BSD +## [0.0.1] - 2025-07-06 -[0.0.1] - 2025-07-06 -Added +### Added +* Initial alpha release of Pilgrim travel diary application +* Create and edit travel diaries +* Create and edit diary entries +* Photo ingestion system +* Photo addition and reference via sidebar +* Text User Interface (TUI) built with Textual framework +* Pre-compiled binary installation method (Method 2) +* Support for Linux operating systems +* Basic project documentation (README) -Initial alpha release of Pilgrim travel diary application -Create and edit travel diaries -Create and edit diary entries -Photo ingestion system -Photo addition and reference via sidebar -Text User Interface (TUI) built with Textual framework -Pre-compiled binary installation method (Method 2) -Support for Linux operating systems -Basic project documentation (README) - -Known Issues - -Installation Method 1 not yet implemented -No testing suite implemented yet -Some features may be unstable in an alpha version -Chat controls Sonnet 4 +### Known Issues +* Installation Method 1 not yet implemented +* No testing suite implemented yet +* Some features may be unstable in an alpha version From 9a698596b173622039dd24cfb5318c6bddc4373f Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Miranda Date: Sat, 19 Jul 2025 18:52:53 -0300 Subject: [PATCH 25/27] Update and rename pylint.yml to pylint_sonarqube.yml Add RUFF and SonarQube scanning --- .github/workflows/pylint.yml | 24 ----------- .github/workflows/pylint_sonarqube.yml | 60 ++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 24 deletions(-) delete mode 100644 .github/workflows/pylint.yml create mode 100644 .github/workflows/pylint_sonarqube.yml diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml deleted file mode 100644 index e1e14af..0000000 --- a/.github/workflows/pylint.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Pylint - -on: [push] - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ["3.10"] - steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - pip install pylint - - name: Analysing the code with pylint - run: | - pylint --disable=C0114,C0115,C0116 --exit-zero $(git ls-files '*.py') diff --git a/.github/workflows/pylint_sonarqube.yml b/.github/workflows/pylint_sonarqube.yml new file mode 100644 index 0000000..60d434e --- /dev/null +++ b/.github/workflows/pylint_sonarqube.yml @@ -0,0 +1,60 @@ +name: Pylint and SonarCloud + +on: + push: + branches: [ main, master, staging ] + pull_request: + branches: [ main, master, staging ] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.10"] + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Needed for SonarCloud + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + pip install pylint ruff coverage pytest + + - name: Analysing the code with pylint (console output) + run: | + pylint --disable=C0114,C0115,C0116 --exit-zero $(git ls-files '*.py') + + - name: Generate Pylint report for SonarCloud + run: | + pylint --disable=C0114,C0115,C0116 --output-format=json --exit-zero $(git ls-files '*.py') > pylint-report.json + + - name: Run Ruff + run: | + ruff check --output-format=json . > ruff-report.json || true + + - name: Run tests with coverage (if you have tests) + run: | + if [ -d "tests" ] || [ -f "test_*.py" ] || [ -f "*_test.py" ]; then + coverage run -m pytest || true + coverage xml + fi + + - name: SonarCloud Scan + uses: SonarSource/sonarcloud-github-action@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + with: + args: > + -Dsonar.python.pylint.reportPaths=pylint-report.json + -Dsonar.python.coverage.reportPaths=coverage.xml + -Dsonar.python.ruff.reportPaths=ruff-report.json + From cc68bbcf2e3a189a892fe0a5514b58987ee68dd1 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Miranda Date: Sat, 19 Jul 2025 18:56:19 -0300 Subject: [PATCH 26/27] Update pylint_sonarqube.yml Add the missing parameters for SonarQube --- .github/workflows/pylint_sonarqube.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/pylint_sonarqube.yml b/.github/workflows/pylint_sonarqube.yml index 60d434e..a22d3cf 100644 --- a/.github/workflows/pylint_sonarqube.yml +++ b/.github/workflows/pylint_sonarqube.yml @@ -54,6 +54,8 @@ jobs: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} with: args: > + -Dsonar.projectKey=gmbrax_Pilgrim + -Dsonar.organization=gmbrax -Dsonar.python.pylint.reportPaths=pylint-report.json -Dsonar.python.coverage.reportPaths=coverage.xml -Dsonar.python.ruff.reportPaths=ruff-report.json From 78e45e26fde7550d577baf555a5c1a697095c6e0 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Miranda Date: Sat, 19 Jul 2025 19:06:53 -0300 Subject: [PATCH 27/27] Update pylint_sonarqube.yml Fix the ruff error on the sonarcloud scan --- .github/workflows/pylint_sonarqube.yml | 33 +++++++++++++------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/.github/workflows/pylint_sonarqube.yml b/.github/workflows/pylint_sonarqube.yml index a22d3cf..b0522ae 100644 --- a/.github/workflows/pylint_sonarqube.yml +++ b/.github/workflows/pylint_sonarqube.yml @@ -1,5 +1,4 @@ name: Pylint and SonarCloud - on: push: branches: [ main, master, staging ] @@ -12,43 +11,46 @@ jobs: strategy: matrix: python-version: ["3.10"] + steps: - uses: actions/checkout@v4 with: - fetch-depth: 0 # Needed for SonarCloud - + fetch-depth: 0 # Necessário para SonarCloud + - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - + - name: Install dependencies run: | python -m pip install --upgrade pip if [ -f requirements.txt ]; then pip install -r requirements.txt; fi pip install pylint ruff coverage pytest - + - name: Analysing the code with pylint (console output) run: | - pylint --disable=C0114,C0115,C0116 --exit-zero $(git ls-files '*.py') - + pylint --disable=C0114,C0115,C0116 --exit-zero $(git ls-files '*.py') || true + - name: Generate Pylint report for SonarCloud run: | - pylint --disable=C0114,C0115,C0116 --output-format=json --exit-zero $(git ls-files '*.py') > pylint-report.json - + pylint --disable=C0114,C0115,C0116 --output-format=json --exit-zero $(git ls-files '*.py') > pylint-report.json || true + - name: Run Ruff run: | ruff check --output-format=json . > ruff-report.json || true - + - name: Run tests with coverage (if you have tests) run: | if [ -d "tests" ] || [ -f "test_*.py" ] || [ -f "*_test.py" ]; then coverage run -m pytest || true - coverage xml + coverage xml || true + else + echo "No tests found, skipping coverage" fi - + - name: SonarCloud Scan - uses: SonarSource/sonarcloud-github-action@master + uses: SonarSource/sonarqube-scan-action@v5.0.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} @@ -57,6 +59,5 @@ jobs: -Dsonar.projectKey=gmbrax_Pilgrim -Dsonar.organization=gmbrax -Dsonar.python.pylint.reportPaths=pylint-report.json + -Dsonar.python.ruff.reportPaths=ruff-report.json -Dsonar.python.coverage.reportPaths=coverage.xml - -Dsonar.python.ruff.reportPaths=ruff-report.json -