diff --git a/dokogen/dictionaries/app_sw.json b/dokogen/dictionaries/app_sw.json new file mode 100644 index 0000000..e43a91b --- /dev/null +++ b/dokogen/dictionaries/app_sw.json @@ -0,0 +1,16 @@ +[ + "Microsoft Office (уточнить версию)", + "LibreOffice", + "OpenOffice", + "1С:Предприятие 8.3 (уточнить конфигурацию)", + "Контур.Экстерн", + "СБИС", + "Kaspersky Endpoint Security", + "Kaspersky Security Center", + "Почтовый клиент (уточнить)", + "Браузер (уточнить)", + "СЭД (уточнить систему)", + "АРМ оператора (уточнить)", + "СКУД ПО (уточнить)", + "Видеонаблюдение ПО (уточнить)" +] diff --git a/dokogen/dictionaries/hw_sw.json b/dokogen/dictionaries/hw_sw.json new file mode 100644 index 0000000..1c52c42 --- /dev/null +++ b/dokogen/dictionaries/hw_sw.json @@ -0,0 +1,16 @@ +[ + "Сервер (уточнить модель)", + "АРМ пользователя (уточнить конфигурацию)", + "Ноутбук (уточнить модель)", + "Коммутатор (уточнить модель)", + "Маршрутизатор (уточнить модель)", + "Межсетевой экран (уточнить модель)", + "Видеорегистратор (уточнить модель)", + "Видеокамера (уточнить модель)", + "Контроллер доступа СКУД (уточнить модель)", + "Шлагбаум (уточнить модель)", + "Турникет (уточнить модель)", + "Сетевое хранилище (NAS) (уточнить модель)", + "Беспроводная точка доступа (уточнить модель)", + "ИБП (уточнить модель)" +] diff --git a/dokogen/dictionaries/os_sw.json b/dokogen/dictionaries/os_sw.json new file mode 100644 index 0000000..ea8c544 --- /dev/null +++ b/dokogen/dictionaries/os_sw.json @@ -0,0 +1,15 @@ +[ + "Windows 10 Pro 64bit", + "Windows 11 Pro", + "Windows Server 2019", + "Windows Server 2022", + "Astra Linux Special Edition", + "РЕД ОС", + "Альт Рабочая станция", + "Альт Сервер", + "Ubuntu Server", + "CentOS", + "Debian", + "MS-DOS (для АРМ специального назначения)", + "Android (для планшетов/КПК)" +] diff --git a/dokogen/ui.py b/dokogen/ui.py index bfdbb9c..42bf218 100644 --- a/dokogen/ui.py +++ b/dokogen/ui.py @@ -916,11 +916,11 @@ class DokoGenApp: sw_frame.pack(fill=tk.BOTH, expand=True) sw_fields = [ - ("ПО и аппаратные средства (модели, производители, количество):", "is_hw_sw_listbox"), - ("Операционные системы:", "is_os_sw_listbox"), - ("Прикладные программы (MS Office, OpenOffice и пр.):", "is_app_sw_listbox"), + ("ПО и аппаратные средства (модели, производители, количество):", "is_hw_sw_listbox", "hw_sw.json"), + ("Операционные системы:", "is_os_sw_listbox", "os_sw.json"), + ("Прикладные программы (MS Office, OpenOffice и пр.):", "is_app_sw_listbox", "app_sw.json"), ] - for i, (label, attr) in enumerate(sw_fields): + for i, (label, attr, dict_name) in enumerate(sw_fields): row = i * 2 ttk.Label(sw_frame, text=label).grid(row=row, column=0, sticky=tk.W, pady=(4, 0)) box = tk.Listbox(sw_frame, height=4, exportselection=False) @@ -936,6 +936,8 @@ class DokoGenApp: command=lambda a=attr: self._del_sw_item(getattr(self, a))).pack(fill=tk.X, pady=1) ttk.Button(btn, text="✏️ Редактировать", command=lambda a=attr: self._edit_sw_item(getattr(self, a))).pack(fill=tk.X, pady=1) + ttk.Button(btn, text="📚 Из словаря", + command=lambda a=attr, d=dict_name: self._select_sw_from_dict(getattr(self, a), d)).pack(fill=tk.X, pady=1) setattr(self, attr, box) sw_frame.columnconfigure(0, weight=1) @@ -1564,11 +1566,61 @@ class DokoGenApp: if item: self.defense_tools_listbox.insert(tk.END, item) + def _select_sw_from_dict(self, listbox, dict_name): + """Выбор позиций из словаря (JSON) — можно несколько.""" + import json + dict_path = os.path.join(os.path.dirname(__file__), 'dictionaries', dict_name) + try: + with open(dict_path, 'r', encoding='utf-8') as f: + items = json.load(f) + title = "Выбор из словаря" + self._select_from_dialog(title, items, listbox) + except Exception as e: + messagebox.showerror("Ошибка", f"Не удалось загрузить словарь: {e}") + + def _sw_dialog(self, title, initial=""): + """Большое окно для ввода/редактирования позиции ПО.""" + dialog = tk.Toplevel(self.root) + dialog.title(title) + dialog.geometry("560x220") + dialog.transient(self.root) + dialog.grab_set() + dialog.resizable(True, True) + + frame = ttk.Frame(dialog, padding=10) + frame.pack(fill=tk.BOTH, expand=True) + + ttk.Label(frame, text="Текст позиции:").pack(anchor=tk.W) + txt = tk.Text(frame, width=70, height=6, wrap=tk.WORD) + txt.pack(fill=tk.BOTH, expand=True, pady=5) + txt.insert('1.0', initial) + txt.focus_set() + + result = {} + + def _ok(): + result['val'] = txt.get('1.0', 'end-1c').strip() + dialog.destroy() + + def _cancel(): + result['val'] = None + dialog.destroy() + + btn_frame = ttk.Frame(frame) + btn_frame.pack(fill=tk.X) + ttk.Button(btn_frame, text="✅ ОК", command=_ok).pack(side=tk.RIGHT, padx=2) + ttk.Button(btn_frame, text="Отмена", command=_cancel).pack(side=tk.RIGHT, padx=2) + + dialog.bind('', lambda e: _ok()) + dialog.bind('', lambda e: _cancel()) + dialog.wait_window() + return result.get('val') + def _add_sw_item(self, listbox): - """Добавить строку в список ПО.""" - item = simpledialog.askstring("Добавить", "Введите позицию:") + """Добавить строку в список ПО (большое окно).""" + item = self._sw_dialog("Добавить позицию") if item: - listbox.insert(tk.END, item.strip()) + listbox.insert(tk.END, item) def _del_sw_item(self, listbox): """Удалить выбранную строку из списка ПО.""" @@ -1577,17 +1629,16 @@ class DokoGenApp: listbox.delete(sel[0]) def _edit_sw_item(self, listbox): - """Редактировать выбранную строку списка ПО.""" + """Редактировать выбранную строку списка ПО (большое окно).""" sel = listbox.curselection() if not sel: messagebox.showinfo("Редактировать", "Сначала выберите позицию в списке") return current = listbox.get(sel[0]) - item = simpledialog.askstring("Редактировать", "Измените позицию:", - initialvalue=current) + item = self._sw_dialog("Редактировать позицию", initial=current) if item is not None: listbox.delete(sel[0]) - listbox.insert(sel[0], item.strip()) + listbox.insert(sel[0], item) def _add_user_to_is(self): user = simpledialog.askstring("Добавить пользователя", "Введите ФИО или должность:")