Initial commit: Dabit Time Manager project
Python-based time management application with UDP discovery, TCP protocol communication, time sync, and drift monitoring. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
124
gui/sync_panel.py
Normal file
124
gui/sync_panel.py
Normal file
@@ -0,0 +1,124 @@
|
||||
"""탭2: PC시간 동기화 패널"""
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
import threading
|
||||
from datetime import datetime
|
||||
|
||||
from models.controller import Controller
|
||||
from services.time_sync_service import sync_all
|
||||
|
||||
|
||||
class SyncPanel(ttk.Frame):
|
||||
"""PC 시간 동기화 패널."""
|
||||
|
||||
def __init__(self, parent, shared_controllers: list[Controller]):
|
||||
super().__init__(parent)
|
||||
self._controllers = shared_controllers
|
||||
self._check_vars: list[tk.BooleanVar] = []
|
||||
self._syncing = False
|
||||
self._build_ui()
|
||||
self._update_clock()
|
||||
|
||||
def _build_ui(self):
|
||||
# --- 상단: 현재 PC 시간 ---
|
||||
top = ttk.LabelFrame(self, text="현재 PC 시간", padding=10)
|
||||
top.pack(fill=tk.X, padx=5, pady=5)
|
||||
|
||||
self._clock_label = ttk.Label(top, text="", font=("Consolas", 18))
|
||||
self._clock_label.pack()
|
||||
|
||||
# --- 중간: 컨트롤러 체크리스트 ---
|
||||
mid = ttk.LabelFrame(self, text="동기화 대상 컨트롤러", padding=5)
|
||||
mid.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
|
||||
|
||||
btn_row = ttk.Frame(mid)
|
||||
btn_row.pack(fill=tk.X)
|
||||
ttk.Button(btn_row, text="전체 선택", command=self._select_all).pack(side=tk.LEFT, padx=2)
|
||||
ttk.Button(btn_row, text="전체 해제", command=self._deselect_all).pack(side=tk.LEFT, padx=2)
|
||||
ttk.Button(btn_row, text="목록 새로고침", command=self.refresh_list).pack(side=tk.LEFT, padx=2)
|
||||
|
||||
self._check_frame = ttk.Frame(mid)
|
||||
self._check_frame.pack(fill=tk.BOTH, expand=True, pady=5)
|
||||
|
||||
# --- 하단: 동기화 실행 + 결과 ---
|
||||
bot = ttk.LabelFrame(self, text="동기화", padding=5)
|
||||
bot.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
|
||||
|
||||
self._btn_sync = ttk.Button(bot, text="동기화 실행", command=self._on_sync)
|
||||
self._btn_sync.pack(pady=5)
|
||||
|
||||
self._log = tk.Text(bot, height=8, state=tk.DISABLED, wrap=tk.WORD)
|
||||
self._log.pack(fill=tk.BOTH, expand=True)
|
||||
|
||||
def _update_clock(self):
|
||||
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
self._clock_label.config(text=now)
|
||||
self.after(1000, self._update_clock)
|
||||
|
||||
def refresh_list(self):
|
||||
"""컨트롤러 체크리스트 갱신."""
|
||||
for w in self._check_frame.winfo_children():
|
||||
w.destroy()
|
||||
self._check_vars.clear()
|
||||
|
||||
for ctrl in self._controllers:
|
||||
var = tk.BooleanVar(value=ctrl.selected)
|
||||
self._check_vars.append(var)
|
||||
cb = ttk.Checkbutton(
|
||||
self._check_frame,
|
||||
text=ctrl.display_label,
|
||||
variable=var,
|
||||
command=lambda c=ctrl, v=var: setattr(c, "selected", v.get()),
|
||||
)
|
||||
cb.pack(anchor=tk.W)
|
||||
|
||||
def _select_all(self):
|
||||
for var in self._check_vars:
|
||||
var.set(True)
|
||||
for ctrl in self._controllers:
|
||||
ctrl.selected = True
|
||||
|
||||
def _deselect_all(self):
|
||||
for var in self._check_vars:
|
||||
var.set(False)
|
||||
for ctrl in self._controllers:
|
||||
ctrl.selected = False
|
||||
|
||||
def _log_message(self, msg: str):
|
||||
self._log.config(state=tk.NORMAL)
|
||||
self._log.insert(tk.END, msg + "\n")
|
||||
self._log.see(tk.END)
|
||||
self._log.config(state=tk.DISABLED)
|
||||
|
||||
def _on_sync(self):
|
||||
if self._syncing:
|
||||
return
|
||||
selected = [c for c in self._controllers if c.selected]
|
||||
if not selected:
|
||||
self._log_message("동기화할 컨트롤러가 없습니다.")
|
||||
return
|
||||
|
||||
self._syncing = True
|
||||
self._btn_sync.config(state=tk.DISABLED)
|
||||
self._log_message(f"--- 동기화 시작: {datetime.now().strftime('%H:%M:%S')} ---")
|
||||
|
||||
threading.Thread(target=self._sync_thread, daemon=True).start()
|
||||
|
||||
def _sync_thread(self):
|
||||
results = sync_all(self._controllers)
|
||||
self.after(0, self._sync_done, results)
|
||||
|
||||
def _sync_done(self, results):
|
||||
self._syncing = False
|
||||
self._btn_sync.config(state=tk.NORMAL)
|
||||
|
||||
ok_count = 0
|
||||
for ctrl, ok, msg in results:
|
||||
status = "OK" if ok else "FAIL"
|
||||
self._log_message(f" [{status}] {ctrl.display_label}: {msg}")
|
||||
if ok:
|
||||
ok_count += 1
|
||||
|
||||
total = len(results)
|
||||
self._log_message(f"--- 완료: {ok_count}/{total} 성공 ---\n")
|
||||
Reference in New Issue
Block a user