diff --git a/Tagger.py b/Tagger.py index 220772b..1b63fcd 100644 --- a/Tagger.py +++ b/Tagger.py @@ -2,15 +2,17 @@ import tkinter as tk from tkinter import ttk -from src.gui.gui import App -from src.core.file_handler import list_files -from src.core.SQL_handler import SQLite3FileHandler +from src.ui.gui import App +from src.core.file_manager import list_files, FileManager +from src.core.tag_manager import TagManager from pathlib import Path class State(): def __init__(self) -> None: - self.app = App() - self.sql_handler = SQLite3FileHandler(Path("Test.db3")) + self.tagmanager = TagManager() + self.filehandler = FileManager(self.tagmanager) + self.app = App(self.filehandler, self.tagmanager) + STATE = State() diff --git a/Test.db3 b/Test.db3 new file mode 100644 index 0000000..581b170 Binary files /dev/null and b/Test.db3 differ diff --git a/src/core/SQL_handler.py b/src/core/SQL_handler.py deleted file mode 100644 index de219eb..0000000 --- a/src/core/SQL_handler.py +++ /dev/null @@ -1,125 +0,0 @@ -import sqlite3 -from pathlib import Path -from typing import Any, List, Tuple - - -class SQLite3FileHandler: - def __init__(self, db_path: Path): - self.db_path = Path(db_path) - need_init = not self.db_path.exists() # zjistíme, jestli soubor existuje před connect - self.conn = sqlite3.connect(str(self.db_path)) - self.cursor = self.conn.cursor() - - if need_init: - self.create_tables() - - - def create_tables(self) -> None: - """ - Vytvoří tabulky (bez chyby pokud už existují). - """ - script = """ - CREATE TABLE IF NOT EXISTS TAGS ( - ID INTEGER PRIMARY KEY, - TAG_NAME TEXT NOT NULL UNIQUE - ); - - CREATE TABLE IF NOT EXISTS FILES ( - ID INTEGER PRIMARY KEY, - PATH TEXT NOT NULL, - FILE_NAME TEXT NOT NULL, - HASH TEXT NOT NULL - ); - - CREATE TABLE IF NOT EXISTS RELATIONS ( - ID INTEGER PRIMARY KEY, - IDS INTEGER NOT NULL, - TYPE TEXT NOT NULL, - IDT INTEGER NOT NULL - ); - - CREATE TABLE IF NOT EXISTS TAG_CATEGORY ( - ID INTEGER PRIMARY KEY, - TAG_CAT_NAME TEXT NOT NULL UNIQUE - ); - """ - # executescript umí více příkazů najednou - self.conn.executescript(script) - self.conn.commit() - - def insert_tag(self, tag_name: str) -> None: - query = "INSERT INTO TAGS (TAG_NAME) VALUES (?)" - self.cursor.execute(query, (tag_name,)) - self.conn.commit() - - def delete_tag(self, tag_name: str) -> None: - query = "DELETE FROM TAGS WHERE TAG_NAME = ?" - self.cursor.execute(query, (tag_name,)) - self.conn.commit() - - def insert_category(self, tag_cat_name: str) -> None: - query = "INSERT INTO TAG_CATEGORY (TAG_CAT_NAME) VALUES (?)" - self.cursor.execute(query, (tag_cat_name,)) - self.conn.commit() - - def delete_category(self, tag_cat_name: str) -> None: - """ - Smaže kategorii podle názvu. - """ - query = "DELETE FROM TAG_CATEGORY WHERE TAG_CAT_NAME = ?" - self.cursor.execute(query, (tag_cat_name,)) - self.conn.commit() - - def insert_relation_tag_cat(self, tag_id: int, tag_cat_id: int) -> None: - query = "INSERT INTO RELATIONS (IDS, TYPE, IDT) VALUES (?, ?, ?)" - self.cursor.execute(query, (tag_id, "Category", tag_cat_id)) - self.conn.commit() - - def delete_relation_tag_cat(self, tag_id: int, tag_cat_id: int) -> None: - """ - Smaže vztah mezi tagem a kategorií podle IDS a IDT. - TYPE je pevně "Category". - """ - query = "DELETE FROM RELATIONS WHERE IDS = ? AND TYPE = ? AND IDT = ?" - self.cursor.execute(query, (tag_id, "Category", tag_cat_id)) - self.conn.commit() - - def insert_file(self, path: str, file_name: str, hash_value: str) -> None: - """ - Vloží nový soubor do tabulky FILES. - """ - query = "INSERT INTO FILES (PATH, FILE_NAME, HASH) VALUES (?, ?, ?)" - self.cursor.execute(query, (path, file_name, hash_value)) - self.conn.commit() - - def delete_file(self, file_id: int) -> None: - """ - Smaže soubor podle jeho ID. - """ - query = "DELETE FROM FILES WHERE ID = ?" - self.cursor.execute(query, (file_id,)) - self.conn.commit() - - def insert_relation_tag_file(self, tag_id: int, file_id: int) -> None: - query = "INSERT INTO RELATIONS (IDS, TYPE, IDT) VALUES (?, ?, ?)" - self.cursor.execute(query, (tag_id, "File", file_id)) - self.conn.commit() - - def delete_relation_tag_file(self, tag_id: int, file_id: int) -> None: - """ - Smaže vztah mezi tagem a souborem podle IDS a IDT. - TYPE je pevně "File". - """ - query = "DELETE FROM RELATIONS WHERE IDS = ? AND TYPE = ? AND IDT = ?" - self.cursor.execute(query, (tag_id, "File", file_id)) - self.conn.commit() - - def fetch_all(self, table_name: str) -> List[Tuple[Any]]: - """Vrátí všechny řádky z tabulky.""" - query = f"SELECT * FROM {table_name}" - self.cursor.execute(query) - return self.cursor.fetchall() - - def close(self) -> None: - """Zavře připojení k databázi.""" - self.conn.close() diff --git a/src/core/dataclass.py b/src/core/dataclass.py deleted file mode 100644 index 3de7064..0000000 --- a/src/core/dataclass.py +++ /dev/null @@ -1,12 +0,0 @@ -from pathlib import Path - -class State(self): - - -class TagManager(self, SaveHandler, ): - self.SaveHandler = SaveHandler - -class FileManager(): - - - diff --git a/src/core/file.py b/src/core/file.py new file mode 100644 index 0000000..7a4780a --- /dev/null +++ b/src/core/file.py @@ -0,0 +1,42 @@ +from pathlib import Path +import json + +class File(): + def __init__(self, file_path: Path, tagmanager = None) -> None: + self.file_path = file_path + self.metadata_filename = self.get_metadata_filename(self.file_path) + self.new = True + self.ignored = False + self.tags = [] + self.tagmanager = tagmanager + self.get_metadata() + + def get_metadata_filename(self, file_path: Path) -> Path: + file_name = file_path.name + metadata_filename =Path(f".{file_name}.!tag") + return metadata_filename + + def get_metadata(self) -> None: + if not self.metadata_filename.exists(): + self.new = True + self.ignored = False + self.tags = [] + else: + self.load_metadata() + + def save_metadata(self) -> None: + """Save object state into metadata file as JSON.""" + data = { + "new": self.new, + "ignored": self.ignored, + "tags": self.tags, + } + with open(self.metadata_filename, "w", encoding="utf-8") as f: + json.dump(data, f, indent=2, ensure_ascii=False) + + def load_metadata(self) -> None: + with open(self.metadata_filename, "r", encoding="utf-8") as f: + data = json.load(f) + self.new = data.get("new", True) + self.ignored = data.get("ignored", False) + self.tags = data.get("tags", []) diff --git a/src/core/file_handler.py b/src/core/file_manager.py similarity index 52% rename from src/core/file_handler.py rename to src/core/file_manager.py index f3677fd..da02c3c 100644 --- a/src/core/file_handler.py +++ b/src/core/file_manager.py @@ -1,13 +1,21 @@ -# Module header -import sys - -if __name__ == "__main__": - sys.exit("This module is not intended to be executed as the main program.") - # Imports from pathlib import Path +from .file import File +from .tag_manager import TagManager -# Functions + +class FileManager(): + def __init__(self, tagmanager: TagManager) -> None: + self.filelist = [] + self.folders = [] + self.tagmanager = tagmanager + + def append(self, folder: Path) -> None: + self.folders.append(folder) + for each in list_files(folder): + file = File(each, self.tagmanager) + self.filelist.append(file) + def list_files(folder_path: str | Path) -> list[Path]: """ Vrátí seznam Path objektů všech souborů uvnitř složky (rekurzivně). diff --git a/src/core/image_handler.py b/src/core/image.py similarity index 100% rename from src/core/image_handler.py rename to src/core/image.py diff --git a/src/gui/__init__.py b/src/core/tag.py similarity index 100% rename from src/gui/__init__.py rename to src/core/tag.py diff --git a/src/core/tag_manager.py b/src/core/tag_manager.py new file mode 100644 index 0000000..5a0d59e --- /dev/null +++ b/src/core/tag_manager.py @@ -0,0 +1,3 @@ +class TagManager(): + def __init__(self): + pass \ No newline at end of file diff --git a/src/ui/__init__.py b/src/ui/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/gui/gui.py b/src/ui/gui.py similarity index 97% rename from src/gui/gui.py rename to src/ui/gui.py index 6e453d6..0ec9514 100644 --- a/src/gui/gui.py +++ b/src/ui/gui.py @@ -6,21 +6,23 @@ import tkinter as tk from tkinter import ttk, simpledialog, messagebox from src.core.image_handler import load_icon +from src.core.file_manager import FileManager class App: - def __init__(self): + def __init__(self, filehandler: FileManager): self.states = {} # Tree states (checkbox on/off) self.files = {} # Path -> set(tags), napojíš na SQLite3FileHandler self.selected_tree_item_for_context = None self.selected_list_index_for_context = None + self.filehandler = filehandler # ================================================== # MAIN GUI # ================================================== def main(self) -> None: root = tk.Tk() - root.title("Tag manager") + root.title("Tagger") root.geometry("900x600") self.root = root