From a8b6fa2fa661040a1be07334a4be76e56ec69095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sun, 28 Jun 2026 20:12:56 +0200 Subject: [PATCH] Finale I --- __pycache__/astrometry_gui.cpython-312.pyc | Bin 88800 -> 97192 bytes astrometry_gui.py | 132 +++++++++++++++++++-- profiles/HU 0815.json | 60 ++++++++++ profiles/Test.json | 60 ++++++++++ 4 files changed, 245 insertions(+), 7 deletions(-) create mode 100644 profiles/HU 0815.json create mode 100644 profiles/Test.json diff --git a/__pycache__/astrometry_gui.cpython-312.pyc b/__pycache__/astrometry_gui.cpython-312.pyc index 44e363e6bbd6252ebd2830484875d964f62ea538..84a327f48c0b120c7a4398e74e65f1f8185f99f9 100644 GIT binary patch delta 16902 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 delta 10413 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 diff --git a/astrometry_gui.py b/astrometry_gui.py index 5f552be..fa15cd1 100644 --- a/astrometry_gui.py +++ b/astrometry_gui.py @@ -8,6 +8,8 @@ Abhängigkeiten: """ import asyncio +import base64 +import json import tkinter as tk from tkinter import ttk, filedialog, messagebox, scrolledtext import threading @@ -180,7 +182,7 @@ class AstrometryGUI: def __init__(self, root: tk.Tk): self.root = root - self.root.title("Astrometry.net — solve-field GUI") + self.root.title("Astrometry.net — solve-field GUI vom Astronomiemuseum") self.root.geometry("1000x840") self.root.minsize(800, 620) @@ -278,12 +280,15 @@ class AstrometryGUI: # ----------------------------------------------------------------------- def _build_ui(self): + self._build_menu() + top = ttk.Frame(self.root, padding=4) top.pack(fill=tk.X) self._build_conn_bar(top) self.nb = ttk.Notebook(self.root) self.nb.pack(fill=tk.BOTH, expand=True, padx=6, pady=(0, 4)) + self.nb.bind("<>", self._on_tab_changed) for title, builder in [ ("Input / Output", self._tab_io), @@ -336,6 +341,20 @@ class AstrometryGUI: self._current_task: asyncio.Future | None = None + def _build_menu(self): + menubar = tk.Menu(self.root) + + profile_menu = tk.Menu(menubar, tearoff=False) + profile_menu.add_command(label="Profil speichern…", command=self._save_profile) + profile_menu.add_command(label="Profil laden…", command=self._load_profile) + menubar.add_cascade(label="Profil", menu=profile_menu) + + self.root.config(menu=menubar) + + def _on_tab_changed(self, _event=None): + if self.nb.select() == str(self.results_tab): + self._refresh_results_tab() + # ----------------------------------------------------------------------- # Verbindungs-Leiste # ----------------------------------------------------------------------- @@ -605,7 +624,7 @@ class AstrometryGUI: ("Weitermachen (--continue)", self.v_continue, "Überspringt bereits gelöste Bilder (prüft ob .solved-Datei existiert).\n" "Ideal für unterbrochene Batch-Verarbeitungen."), - ("SExtractor nutzen (--use-sextractor)", self.v_sextractor, + ("SExtractor nutzen (--use-source-extractor)", self.v_sextractor, "Verwendet SExtractor statt des eingebauten Quellenerkennungs-Algorithmus.\n" "Muss auf dem Server installiert sein. Oft besser bei schwierigen Bildern."), ("Als FITS-Bild behandeln (--fits-image)", self.v_fits_image, @@ -799,7 +818,7 @@ class AstrometryGUI: flag("--resort", self.v_resort) flag("--continue", self.v_continue) flag("--no-delete-temp", self.v_no_del_temp) - flag("--use-sextractor", self.v_sextractor) + flag("--use-source-extractor", self.v_sextractor) flag("--fits-image", self.v_fits_image) flag("--no-verify", self.v_no_verify) flag("--just-augment", self.v_just_augment) @@ -967,11 +986,11 @@ class AstrometryGUI: except Exception as exc: self._log(f"[FEHLER] Remote-Inhalt l\u00f6schen: {exc}\n", "error") - def _show_results_tab(self): - self.nb.select(self.results_tab) - def _refresh_results_tab(self): remote_dir = self.v_remote_dir.get().strip() + self.root.config(cursor="watch") + self.nb.config(cursor="watch") + self.results_tree.config(cursor="watch") self._submit(self._async_refresh_results_tab(remote_dir)) async def _async_refresh_results_tab(self, remote_dir: str, returncode: int | None = None): @@ -1015,9 +1034,11 @@ class AstrometryGUI: await ssh.exec_stream(cmd, _capture) await ssh.close() self.root.after(0, lambda: self._set_results_items(entries)) + self.root.after(0, self._clear_wait_cursor) except Exception as exc: self.root.after(0, lambda: self._set_results_info(f"[FEHLER] {exc}")) self.root.after(0, lambda: self._set_results_items([])) + self.root.after(0, self._clear_wait_cursor) def _set_results_info(self, text: str): self.results_info.config(text=text, foreground="gray") @@ -1040,6 +1061,11 @@ class AstrometryGUI: ), ) + def _clear_wait_cursor(self): + self.root.config(cursor="") + self.nb.config(cursor="") + self.results_tree.config(cursor="") + def _format_size(self, size_text: str) -> str: try: size = int(size_text) @@ -1065,8 +1091,11 @@ class AstrometryGUI: messagebox.showwarning("Datei fehlt", "Die ausgewählte Datei konnte nicht gefunden werden.") return suggested = os.path.basename(entry["remote"]) + source_dir = os.path.dirname(self.v_local_file.get().strip()) if self.v_local_file.get().strip() else "" + initial_dir = source_dir if source_dir and os.path.isdir(source_dir) else os.getcwd() local_dir = filedialog.askdirectory( title="Zielordner für Download auswählen", + initialdir=initial_dir, ) if not local_dir: return @@ -1102,7 +1131,6 @@ class AstrometryGUI: rc = await ssh.exec_stream(cmd, self._log) await ssh.close() self._current_task = None - self.root.after(0, self._show_results_tab) await self._async_refresh_results_tab(self.v_remote_dir.get().strip(), rc) except Exception as exc: self._log(f"[FEHLER] {exc}\n", "error") @@ -1267,6 +1295,96 @@ class AstrometryGUI: self.root.clipboard_clear() self.root.clipboard_append(self.cmd_text.get("1.0", tk.END).strip()) + def _encrypt_text(self, text: str) -> str: + if not text: + return "" + key = b"AstrometryGuiInternalKey-2026" + plain = text.encode("utf-8") + encrypted = bytes(b ^ key[i % len(key)] for i, b in enumerate(plain)) + return base64.b64encode(encrypted).decode("ascii") + + def _decrypt_text(self, token: str) -> str: + if not token: + return "" + key = b"AstrometryGuiInternalKey-2026" + encrypted = base64.b64decode(token.encode("ascii")) + plain = bytes(b ^ key[i % len(key)] for i, b in enumerate(encrypted)) + return plain.decode("utf-8") + + def _collect_profile_data(self) -> dict: + vars_data = {} + for name, value in self.__dict__.items(): + if name.startswith("v_") and hasattr(value, "get"): + vars_data[name] = value.get() + if "v_pass" in vars_data: + vars_data["v_pass"] = "" + return { + "format": 2, + "variables": vars_data, + "secrets": { + "v_pass_enc": self._encrypt_text(self.v_pass.get()), + }, + "idx_text": self.idx_text.get("1.0", tk.END).strip(), + } + + def _apply_profile_data(self, data: dict): + vars_data = data.get("variables", {}) + for name, value in vars_data.items(): + var = getattr(self, name, None) + if var is not None and hasattr(var, "set"): + var.set(value) + + secrets = data.get("secrets", {}) + encrypted_pass = secrets.get("v_pass_enc") or secrets.get("v_pass_dpapi") + if encrypted_pass: + try: + self.v_pass.set(self._decrypt_text(encrypted_pass)) + except Exception: + pass + + self.idx_text.delete("1.0", tk.END) + idx_text = data.get("idx_text", "") + if idx_text: + self.idx_text.insert("1.0", idx_text) + + self._refresh_cmd() + + def _save_profile(self): + profile_dir = os.path.join(os.getcwd(), "profiles") + os.makedirs(profile_dir, exist_ok=True) + path = filedialog.asksaveasfilename( + title="Profil speichern", + initialdir=profile_dir, + defaultextension=".json", + filetypes=[("JSON-Dateien", "*.json"), ("Alle Dateien", "*.*")], + ) + if not path: + return + data = self._collect_profile_data() + try: + with open(path, "w", encoding="utf-8") as f: + json.dump(data, f, ensure_ascii=False, indent=2) + self._log(f"[OK] Profil gespeichert: {path}\n", "ok") + except Exception as exc: + messagebox.showerror("Profil speichern", f"Speichern fehlgeschlagen:\n{exc}") + + def _load_profile(self): + profile_dir = os.path.join(os.getcwd(), "profiles") + path = filedialog.askopenfilename( + title="Profil laden", + initialdir=profile_dir if os.path.isdir(profile_dir) else os.getcwd(), + filetypes=[("JSON-Dateien", "*.json"), ("Alle Dateien", "*.*")], + ) + if not path: + return + try: + with open(path, "r", encoding="utf-8") as f: + data = json.load(f) + self._apply_profile_data(data) + self._log(f"[OK] Profil geladen: {path}\n", "ok") + except Exception as exc: + messagebox.showerror("Profil laden", f"Laden fehlgeschlagen:\n{exc}") + # ----------------------------------------------------------------------- # Log (thread-sicher via Queue) # ----------------------------------------------------------------------- diff --git a/profiles/HU 0815.json b/profiles/HU 0815.json new file mode 100644 index 0000000..0f1da39 --- /dev/null +++ b/profiles/HU 0815.json @@ -0,0 +1,60 @@ +{ + "format": 2, + "variables": { + "v_host": "10.42.44.25", + "v_port": 22, + "v_user": "eskimue", + "v_pass": "", + "v_local_file": "", + "v_remote_dir": "/tmp/astrometry", + "v_input_file": "", + "v_out_prefix": "", + "v_out_dir": "/tmp/astrometry", + "v_new_fits": "", + "v_wcs": "", + "v_corr": "", + "v_rdls": "", + "v_axy": "", + "v_solved": "", + "v_match": "", + "v_scale_units": "degwidth", + "v_scale_low": "20", + "v_scale_high": "30", + "v_scale_est": "", + "v_scale_err": "", + "v_ra": "", + "v_dec": "", + "v_radius": "1.0", + "v_depth": "", + "v_cpulimit": "300", + "v_plot_scale": "", + "v_plot_scale_auto": true, + "v_plot_target_long_edge": "900", + "v_downsample": "6", + "v_tweak_order": "2", + "v_odds_solve": "", + "v_odds_reject": "", + "v_odds_tune": "", + "v_objs": "", + "v_pixel_error": "", + "v_parity": "both", + "v_overwrite": true, + "v_no_plots": false, + "v_no_tweak": false, + "v_resort": false, + "v_verbose": false, + "v_timestamp": true, + "v_no_del_temp": false, + "v_continue": false, + "v_sextractor": false, + "v_fits_image": false, + "v_no_verify": false, + "v_just_augment": false, + "v_invert": true, + "v_extra": "" + }, + "secrets": { + "v_pass_enc": "EQERAQYJAA==" + }, + "idx_text": "" +} \ No newline at end of file diff --git a/profiles/Test.json b/profiles/Test.json new file mode 100644 index 0000000..10b0bb5 --- /dev/null +++ b/profiles/Test.json @@ -0,0 +1,60 @@ +{ + "format": 2, + "variables": { + "v_host": "10.42.44.25", + "v_port": 22, + "v_user": "eskimue", + "v_pass": "", + "v_local_file": "C:/Users/ich/Cloud__Museum/Museumsentwicklung/Shop/Faksimile/2026/Heinlein Dieter/IMG_410328-1956_08_30-20000+2000-Te3-26-50.png", + "v_remote_dir": "/tmp/astrometry", + "v_input_file": "/tmp/astrometry/IMG_410328-1956_08_30-20000+2000-Te3-26-50.png", + "v_out_prefix": "", + "v_out_dir": "/tmp/astrometry", + "v_new_fits": "/tmp/astrometry/IMG_410328-1956_08_30-20000+2000-Te3-26-50.fits", + "v_wcs": "", + "v_corr": "", + "v_rdls": "", + "v_axy": "", + "v_solved": "", + "v_match": "", + "v_scale_units": "degwidth", + "v_scale_low": "20", + "v_scale_high": "30", + "v_scale_est": "", + "v_scale_err": "", + "v_ra": "", + "v_dec": "", + "v_radius": "1.0", + "v_depth": "", + "v_cpulimit": "300", + "v_plot_scale": "0.15", + "v_plot_scale_auto": true, + "v_plot_target_long_edge": "900", + "v_downsample": "6", + "v_tweak_order": "2", + "v_odds_solve": "", + "v_odds_reject": "", + "v_odds_tune": "", + "v_objs": "", + "v_pixel_error": "", + "v_parity": "both", + "v_overwrite": true, + "v_no_plots": false, + "v_no_tweak": false, + "v_resort": false, + "v_verbose": false, + "v_timestamp": true, + "v_no_del_temp": false, + "v_continue": false, + "v_sextractor": false, + "v_fits_image": false, + "v_no_verify": false, + "v_just_augment": false, + "v_invert": true, + "v_extra": "" + }, + "secrets": { + "v_pass_enc": "EQERAQYJAA==" + }, + "idx_text": "" +} \ No newline at end of file