add CHANGELOG, icon_full, update gitignore

This commit is contained in:
2026-05-22 18:42:25 +02:00
parent 408f36135d
commit c474b82bf0
7 changed files with 158 additions and 125 deletions
+45 -87
View File
@@ -12,18 +12,28 @@ from dtc_client import DTCClient, fills_to_trades, monitor_realtime
from tralgo_api import build_session, send_trade
try:
from PIL import Image, ImageDraw, ImageTk
from PIL import Image, ImageTk
_PIL_AVAILABLE = True
except ImportError:
_PIL_AVAILABLE = False
try:
import pystray
_PYSTRAY_AVAILABLE = True
except ImportError:
_PYSTRAY_AVAILABLE = False
_ICON_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "icon.png")
_ICON_FULL_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "icon_full.png")
_ICON_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "icon.png")
def _load_icon(path, size):
"""Open icon, crop transparent padding, add 8 % margin, resize to size×size."""
img = Image.open(path).convert("RGBA")
bbox = img.getbbox()
if bbox:
img = img.crop(bbox)
m = max(img.width, img.height) // 12 # ~8 % margin
canvas_sz = max(img.width, img.height) + 2 * m
canvas = Image.new("RGBA", (canvas_sz, canvas_sz), (0, 0, 0, 0))
ox = (canvas_sz - img.width) // 2
oy = (canvas_sz - img.height) // 2
canvas.paste(img, (ox, oy), img)
return canvas.resize((size, size), Image.LANCZOS)
# ── Config window ─────────────────────────────────────────────────────────────
@@ -335,7 +345,8 @@ class ManualImportWindow:
def _run():
all_fills = []
error_msg = None
dtc_error = None
try:
client = DTCClient(host, port)
client.connect()
@@ -345,27 +356,27 @@ class ManualImportWindow:
all_fills.extend(fills)
client.disconnect()
except Exception as e:
error_msg = str(e)
dtc_error = str(e)
if error_msg:
self.win.after(0, lambda: self._search_done([], error_msg))
if dtc_error and not all_fills:
self.win.after(0, lambda: self._search_done([], dtc_error))
return
# Filter by date range
filtered = []
filtered_fills = []
for f in all_fills:
if not f.get("datetime"):
filtered.append(f)
filtered_fills.append(f)
continue
d = f["datetime"].strftime("%Y-%m-%d")
if date_from and d < date_from:
continue
if date_to and d > date_to:
continue
filtered.append(f)
filtered_fills.append(f)
trades = fills_to_trades(filtered, instruments)
self.win.after(0, lambda: self._search_done(trades, None))
all_trades = fills_to_trades(filtered_fills, instruments)
err = dtc_error if not all_trades else None
self.win.after(0, lambda: self._search_done(all_trades, err))
threading.Thread(target=_run, daemon=True).start()
@@ -515,12 +526,12 @@ class App:
def __init__(self):
self.root = tk.Tk()
self.root.withdraw()
self.root.title("GizerBridge")
self.root.tk.call("wm", "iconname", self.root, "gizerbridge")
if _PIL_AVAILABLE:
try:
_base = Image.open(_ICON_PATH).convert("RGBA")
# multiple sizes → WM picks best for taskbar / alt-tab
self._wm_icons = [
ImageTk.PhotoImage(_base.resize((sz, sz), Image.LANCZOS))
ImageTk.PhotoImage(_load_icon(_ICON_PATH, sz))
for sz in (256, 128, 64, 48, 32)
]
self.root.iconphoto(True, *self._wm_icons)
@@ -541,7 +552,6 @@ class App:
def run(self):
self.root.after(200, self._process_queue)
self._setup_tray()
if not self.config.get("api_key"):
self.root.after(100, lambda: ConfigWindow(
@@ -554,56 +564,6 @@ class App:
def _set_icon_color(self, color):
self._status_color = color
if hasattr(self, "_tray") and _PIL_AVAILABLE:
try:
self._tray.icon = self._make_tray_image(color)
except Exception:
pass
# ── Pystray helpers ───────────────────────────────────────────────────────
def _make_tray_image(self, color="yellow"):
"""256×256 logo with a small colored status dot in the bottom-right."""
img = Image.open(_ICON_PATH).convert("RGBA").resize((256, 256), Image.LANCZOS)
dot_colors = {
"green": (0, 200, 0, 255),
"red": (220, 0, 0, 255),
"yellow": (230, 190, 0, 255),
}
c = dot_colors.get(color, (160, 160, 160, 255))
draw = ImageDraw.Draw(img)
r = 30
x0, y0 = 256 - 2*r - 8, 256 - 2*r - 8
draw.ellipse([x0, y0, x0 + 2*r, y0 + 2*r],
fill=c, outline=(0, 0, 0, 160), width=3)
return img
def _setup_tray(self):
if not _PYSTRAY_AVAILABLE or not _PIL_AVAILABLE:
return
menu = pystray.Menu(
pystray.MenuItem("GizerBridge", self._tray_show, default=True),
pystray.Menu.SEPARATOR,
pystray.MenuItem("Manueller Import",
lambda: self._queue.put(self._open_manual_import)),
pystray.MenuItem("Einstellungen",
lambda: self._queue.put(self._open_config)),
pystray.MenuItem("Log",
lambda: self._queue.put(self._open_log)),
pystray.Menu.SEPARATOR,
pystray.MenuItem("Beenden",
lambda: self._queue.put(self._quit)),
)
self._tray = pystray.Icon(
"gizerbridge",
self._make_tray_image("yellow"),
"GizerBridge",
menu,
)
self._tray.run_detached()
def _tray_show(self, *_):
self._queue.put(lambda: (self.root.deiconify(), self.root.lift()))
# ── Main window ───────────────────────────────────────────────────────────
@@ -621,14 +581,14 @@ class App:
hdr.pack(fill=tk.X)
if _PIL_AVAILABLE:
try:
_img = Image.open(_ICON_PATH).convert("RGBA")
_img = _img.resize((128, 128), Image.LANCZOS)
self._hdr_photo = ImageTk.PhotoImage(_img)
tk.Label(hdr, image=self._hdr_photo).pack(side=tk.LEFT, padx=(0, 8))
self._hdr_photo = ImageTk.PhotoImage(_load_icon(_ICON_FULL_PATH, 128))
tk.Label(hdr, image=self._hdr_photo).pack(side=tk.LEFT)
except Exception:
pass
tk.Label(hdr, text="GizerBridge",
font=("", 13, "bold")).pack(side=tk.LEFT)
tk.Label(hdr, text="GizerBridge",
font=("", 13, "bold")).pack(side=tk.LEFT)
else:
tk.Label(hdr, text="GizerBridge",
font=("", 13, "bold")).pack(side=tk.LEFT)
# ── Status row ──
sf = tk.Frame(self.root, padx=14)
@@ -652,8 +612,7 @@ class App:
tk.Button(bf, text=text, width=15,
command=cmd).pack(side=tk.LEFT, padx=(0, 6))
close_action = self.root.withdraw if _PYSTRAY_AVAILABLE else self._quit
self.root.protocol("WM_DELETE_WINDOW", close_action)
self.root.protocol("WM_DELETE_WINDOW", self._quit)
# ── Monitor thread ────────────────────────────────────────────────────────
@@ -687,8 +646,6 @@ class App:
accounts = cfg.get("accounts", [])
instruments = self._active_instruments(cfg)
self._log(f"Verbinde mit Sierra Chart DTC {host}:{port}")
def _on_trade(trade):
if trade["trade_id"] in self.sent:
return
@@ -708,6 +665,12 @@ class App:
self._update_status_msg(err_msg)
self._queue.put(lambda: self._set_icon_color("red"))
if not accounts:
self._log("Keine Konten konfiguriert.")
return
self._log(f"Verbinde mit Sierra Chart DTC {host}:{port}")
def _on_ready(existing_ids):
self.sent.update(existing_ids)
save_sent(self.sent)
@@ -830,11 +793,6 @@ class App:
def _quit(self):
self._stop.set()
save_sent(self.sent)
if hasattr(self, "_tray"):
try:
self._tray.stop()
except Exception:
pass
try:
self.root.quit()
self.root.destroy()