diff --git a/dokogen/ui.py b/dokogen/ui.py index d3ec04e..bc909fb 100644 --- a/dokogen/ui.py +++ b/dokogen/ui.py @@ -2172,23 +2172,38 @@ class DokoGenApp: profit = getattr(self.model, 'profit', '') or '' profit_tax = getattr(self.model, 'profit_tax', '') or '' - w = tk.Toplevel(self.root) + # Родитель — окно ПП 127 (dialog), а не главное окно; + # grab_set + lift — чтобы окно не уходило на задний план + w = tk.Toplevel(dialog) w.title(f"🧮 Авторасчёт показателя {num} — {name[:60]}") - w.geometry("720x560") - w.transient(self.root) - frm = ttk.Frame(w, padding=10) - frm.pack(fill=tk.BOTH, expand=True) + w.geometry("820x700") + w.transient(dialog) + w.lift() + w.focus_force() + + # Внешняя рамка: тело со скроллом + кнопки снизу (всегда видны) + outer = ttk.Frame(w, padding=10) + outer.pack(fill=tk.BOTH, expand=True) + + canvas = tk.Canvas(outer, highlightthickness=0) + scrollbar = ttk.Scrollbar(outer, orient=tk.VERTICAL, command=canvas.yview) + frm = ttk.Frame(canvas) + frm.bind("", lambda e: canvas.configure(scrollregion=canvas.bbox("all"))) + canvas.create_window((0, 0), window=frm, anchor="nw") + canvas.configure(yscrollcommand=scrollbar.set) + canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) + scrollbar.pack(side=tk.RIGHT, fill=tk.Y) if num == '9': ttk.Label(frm, text="Показатель 9 — ущерб бюджетам РФ (применим ко всем субъектам КИИ)", font=('Arial', 10, 'bold')).pack(anchor=tk.W) ttk.Label(frm, text="Формула: №9 = ΔБ / Бусредн × 100%, где ΔБ = ΔНП + ΔНДПИ + ΔДИВ + ΔВСО + ΔНС\n" "ΔНП = ΔДоходов × (налог на прибыль / прибыль); если ΔДоходов > прибыли — весь налог.", - foreground='gray', wraplength=660, justify=tk.LEFT).pack(anchor=tk.W, pady=(2, 6)) + foreground='gray', wraplength=760, justify=tk.LEFT).pack(anchor=tk.W, pady=(2, 6)) def _row(label, key, default=''): ttk.Label(frm, text=label).pack(anchor=tk.W, pady=(4, 0)) - e = ttk.Entry(frm, width=60) + e = ttk.Entry(frm, width=70) e.insert(0, str(default or '')) e.pack(fill=tk.X) return e @@ -2204,18 +2219,18 @@ class DokoGenApp: e_div = _row("Снижение выплат от дивидендов ΔДИВ (руб.):", 'div', '0') e_vso = _row("Снижение выплат сторонних организаций ΔВСО (руб.):", 'vso', '0') e_ns = _row("Снижение сборов ΔНС (руб.):", 'ns', '0') - result = tk.Text(frm, height=10, wrap=tk.WORD, state=tk.NORMAL) + result = tk.Text(frm, height=8, wrap=tk.WORD, state=tk.NORMAL) result.pack(fill=tk.BOTH, expand=True, pady=(8, 0)) else: ttk.Label(frm, text="Показатель 8 — ущерб субъекту КИИ", font=('Arial', 10, 'bold')).pack(anchor=tk.W) ttk.Label(frm, text="Применим только для: госкорпорации, ГУП, госкомпании, стратегического АО/предприятия " "(Указ Президента № 1009).\nФормула: №8 = ΔДоходов / Дусредн × 100%.", - foreground='gray', wraplength=660, justify=tk.LEFT).pack(anchor=tk.W, pady=(2, 6)) + foreground='gray', wraplength=760, justify=tk.LEFT).pack(anchor=tk.W, pady=(2, 6)) def _row(label, key, default=''): ttk.Label(frm, text=label).pack(anchor=tk.W, pady=(4, 0)) - e = ttk.Entry(frm, width=60) + e = ttk.Entry(frm, width=70) e.insert(0, str(default or '')) e.pack(fill=tk.X) return e @@ -2230,7 +2245,7 @@ class DokoGenApp: 'dincome', f"{_d_loss:,.0f}" if _d_loss else '') e_budget = _row("Доходы субъекта КИИ, усреднённые за 5 лет (руб.):", 'budget', f"{_d_avg:,.0f}" if _d_avg else '') - result = tk.Text(frm, height=10, wrap=tk.WORD, state=tk.NORMAL) + result = tk.Text(frm, height=8, wrap=tk.WORD, state=tk.NORMAL) result.pack(fill=tk.BOTH, expand=True, pady=(8, 0)) def _calc(): @@ -2240,7 +2255,7 @@ class DokoGenApp: b = _num(e_budget.get()) if d is None or b is None or b <= 0: result.delete('1.0', tk.END) - result.insert('1.0', "Заполните оба поля (ΔДоходов и Дусредн).") + result.insert('1.0', "Заполните оба поля (ущерб и доходы за 5 лет).") return val = d / b * 100 lines.append(f"Суммарный экономический ущерб от нарушения критических процессов: {d:,.0f} руб.") @@ -2316,12 +2331,10 @@ class DokoGenApp: elif 'Категория значимости: III' in cat_line: cat = 'III' if cat: - # Выбрать в комбобоксе соответствующую категорию opts = list(combo['values']) target = next((o for o in opts if o.startswith(f"{cat} категория")), None) if target: var.set(target) - # Обоснование с расчётом prefix = f"Показатель {num}. {name} — {cat} категория." full = prefix + "\n" + txt cur = justify_txt.get('1.0', 'end-1c').strip() @@ -2340,14 +2353,23 @@ class DokoGenApp: justify_txt.insert('end', '\n' + full) else: justify_txt.insert('1.0', full) + w.grab_release() w.destroy() - btns = ttk.Frame(frm) + # Кнопки — вне скролла, всегда видны + btns = ttk.Frame(outer) btns.pack(fill=tk.X, pady=(8, 0)) ttk.Button(btns, text="🧮 Рассчитать", command=_calc).pack(side=tk.LEFT, padx=2) ttk.Button(btns, text="✔️ Применить категорию", command=_apply).pack(side=tk.LEFT, padx=2) - ttk.Button(btns, text="Отмена", command=w.destroy).pack(side=tk.LEFT, padx=2) + ttk.Button(btns, text="Отмена", + command=lambda: (w.grab_release(), w.destroy())).pack(side=tk.LEFT, padx=2) + # Захват фокуса — окно не уходит на задний план + try: + w.grab_set() + except Exception: + pass + w.lift() rows = [] # (num, name, values{III:..,II:..,I:..}, var, applicable) _combos = {} # num -> комбобокс (для автозаполнения)