From 9e32e58c4cbb39617b5f8173c793ea98c35881bd Mon Sep 17 00:00:00 2001 From: Valentin Korenjak Date: Wed, 4 Mar 2026 22:35:03 +0100 Subject: [PATCH] malo prepucano po nasvetih kopilota, fix za shutdown na linux-u, nekaj dodatkov na temo robustnosti --- nastavitve.py | 2 +- projector.py | 98 ++++++++++++++++++++++++++++++++------------------- settings.json | 4 +-- 3 files changed, 65 insertions(+), 39 deletions(-) diff --git a/nastavitve.py b/nastavitve.py index 569d745..d5c938f 100755 --- a/nastavitve.py +++ b/nastavitve.py @@ -15,7 +15,7 @@ DEFAULT_SETTINGS = { "screen_width_percent": 60, "font_bold": True, "show_song_info": True, - "split_by_stanza": True + "split_by_stanza": False } SETTINGS_FILE = "settings.json" diff --git a/projector.py b/projector.py index f64adc3..6559920 100755 --- a/projector.py +++ b/projector.py @@ -7,16 +7,28 @@ import json import os import math import subprocess +import sys +import tkinter.messagebox as messagebox DB_PATH = 'songs.db' SETTINGS_PATH = 'settings.json' +BASE_DIR = os.path.dirname(os.path.abspath(__file__)) + class SongProjector: def __init__(self, root): self.root = root - self.conn = sqlite3.connect(DB_PATH) - self.cursor = self.conn.cursor() + # ... + try: + # Odpri read-only; ne bo ustvaril prazne baze, če datoteka manjka + self.conn = sqlite3.connect(f"file:{DB_PATH}?mode=ro", uri=True) + self.cursor = self.conn.cursor() + except sqlite3.OperationalError as e: + # Jasno sporočilo in varen izhod + messagebox.showerror("Napaka baze", f"Ne morem odpreti baze '{DB_PATH}':\n{e}") + root.destroy() + sys.exit(1) self.current_song = None self.pages = [] self.current_page_index = 0 @@ -27,22 +39,29 @@ class SongProjector: # -------------------------------------------------- # Nastavitve # -------------------------------------------------- - if not os.path.exists(SETTINGS_PATH): - self.settings = { - "font_name": "Times New Roman", - "bg_color": "#000000", - "fg_color": "#FFFFFF", - "font_size": 32, - "screen_width_percent": 60, - "font_bold": True, - "show_song_info": True - } - with open(SETTINGS_PATH, "w", encoding="utf-8") as f: - json.dump(self.settings, f, indent=4) - else: - with open(SETTINGS_PATH, "r", encoding="utf-8") as f: - self.settings = json.load(f) + DEFAULT_SETTINGS = { + "font_name": "Times New Roman", + "bg_color": "#000000", + "fg_color": "#FFFFFF", + "font_size": 32, + "screen_width_percent": 60, + "font_bold": True, + "show_song_info": True, + "split_by_stanza": False # TODO: mogoče nekoč (prelom po kitici namesto po višini) + } + if not os.path.exists(SETTINGS_PATH): + self.settings = DEFAULT_SETTINGS.copy() + with open(SETTINGS_PATH, "w", encoding="utf-8") as f: + json.dump(self.settings, f, indent=4, ensure_ascii=False) + else: + try: + with open(SETTINGS_PATH, "r", encoding="utf-8") as f: + self.settings = json.load(f) + except (json.JSONDecodeError, OSError): + # Povratek na varne privzete + self.settings = DEFAULT_SETTINGS.copy() + self.line_height = int(int(self.settings["font_size"]) * 1.5) # -------------------------------------------------- @@ -171,7 +190,7 @@ class SongProjector: # Upravljanje tipkovnice # ------------------------------------------------------ def key_pressed(self, event): - if event.keysym.isdigit(): + if event.char and event.char.isdigit(): self.song_number += event.char elif event.keysym == "BackSpace": self.song_number = self.song_number[:-1] @@ -205,17 +224,20 @@ class SongProjector: # Posebni ukazi if self.song_number == "9999": - subprocess.Popen(["shutdown", "/s", "/f", "/t", "0"]) + if sys.platform.startswith("win"): + subprocess.Popen(["shutdown", "/s", "/t", "0"]) # brez /f – manj agresivno + else: + subprocess.Popen(["shutdown", "-h", "now"]) return elif self.song_number == "7777": - subprocess.Popen(["python", "nastavitve.py"]) + subprocess.Popen([sys.executable, os.path.join(BASE_DIR, "nastavitve.py")]) # fixme: novi proces ne dobi stdin-a; predelati na tkinter aplikacijo? self.exit_program() return elif self.song_number == "8888": self.exit_program() return elif self.song_number == "6666": - subprocess.Popen(["python", "add_song.py"]) + subprocess.Popen([sys.executable, os.path.join(BASE_DIR, "add_song.py")]) # fixme: novi proces ne dobi stdin-a; predelati na tkinter aplikacijo? self.exit_program() return @@ -392,26 +414,30 @@ class SongProjector: self.search_entry.bind("", self.perform_search) def perform_search(self, event=None): - query = self.search_entry.get().strip().lower() + query = self.search_entry.get().strip() self.search_label.destroy() self.search_entry.destroy() + self.label.pack(expand=True) - if query: - self.cursor.execute("SELECT id, title FROM songs") - all_results = self.cursor.fetchall() + if not query: + self.label.config(text="(Prazno iskanje)") + return - matched = [] - for song_id, title in all_results: - if query in title.lower(): - matched.append((song_id, title)) + try: + self.cursor.execute( + "SELECT id, title FROM songs WHERE title LIKE ? COLLATE NOCASE", + (f"%{query}%",) + ) + matched = self.cursor.fetchall() + except Exception as e: + self.label.config(text=f"Napaka pri iskanju: {e}") + return - if matched: - found = "\n".join(f"{id}: {title}" for id, title in matched) - self.label.pack(expand=True) - self.label.config(text=found) - else: - self.label.pack(expand=True) - self.label.config(text="Ni zadetkov.") + if matched: + found = "\n".join(f"{sid}: {title}" for sid, title in matched) + self.label.config(text=found) + else: + self.label.config(text="Ni zadetkov.") # ------------------------------------------------------ # Izhod diff --git a/settings.json b/settings.json index 3d4467a..f33cd86 100644 --- a/settings.json +++ b/settings.json @@ -2,9 +2,9 @@ "font_name": "Times New Roman", "bg_color": "#000000", "fg_color": "#FFFFFF", - "font_size": 38, + "font_size": 32, "screen_width_percent": 60, "font_bold": true, "show_song_info": true, - "split_by_stanza": true + "split_by_stanza": false } \ No newline at end of file