feat: вкладка «ПО» — словари ОС/аппаратных средств/прикладных программ + большое окно редактирования
- словари: hw_sw.json, os_sw.json, app_sw.json
- кнопка «📚 Из словаря» у каждого списка ПО (мультивыбор)
- большое окно добавления/редактирования позиции (560x220, многострочное)
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
[
|
||||||
|
"Microsoft Office (уточнить версию)",
|
||||||
|
"LibreOffice",
|
||||||
|
"OpenOffice",
|
||||||
|
"1С:Предприятие 8.3 (уточнить конфигурацию)",
|
||||||
|
"Контур.Экстерн",
|
||||||
|
"СБИС",
|
||||||
|
"Kaspersky Endpoint Security",
|
||||||
|
"Kaspersky Security Center",
|
||||||
|
"Почтовый клиент (уточнить)",
|
||||||
|
"Браузер (уточнить)",
|
||||||
|
"СЭД (уточнить систему)",
|
||||||
|
"АРМ оператора (уточнить)",
|
||||||
|
"СКУД ПО (уточнить)",
|
||||||
|
"Видеонаблюдение ПО (уточнить)"
|
||||||
|
]
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[
|
||||||
|
"Сервер (уточнить модель)",
|
||||||
|
"АРМ пользователя (уточнить конфигурацию)",
|
||||||
|
"Ноутбук (уточнить модель)",
|
||||||
|
"Коммутатор (уточнить модель)",
|
||||||
|
"Маршрутизатор (уточнить модель)",
|
||||||
|
"Межсетевой экран (уточнить модель)",
|
||||||
|
"Видеорегистратор (уточнить модель)",
|
||||||
|
"Видеокамера (уточнить модель)",
|
||||||
|
"Контроллер доступа СКУД (уточнить модель)",
|
||||||
|
"Шлагбаум (уточнить модель)",
|
||||||
|
"Турникет (уточнить модель)",
|
||||||
|
"Сетевое хранилище (NAS) (уточнить модель)",
|
||||||
|
"Беспроводная точка доступа (уточнить модель)",
|
||||||
|
"ИБП (уточнить модель)"
|
||||||
|
]
|
||||||
@@ -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 (для планшетов/КПК)"
|
||||||
|
]
|
||||||
+62
-11
@@ -916,11 +916,11 @@ class DokoGenApp:
|
|||||||
sw_frame.pack(fill=tk.BOTH, expand=True)
|
sw_frame.pack(fill=tk.BOTH, expand=True)
|
||||||
|
|
||||||
sw_fields = [
|
sw_fields = [
|
||||||
("ПО и аппаратные средства (модели, производители, количество):", "is_hw_sw_listbox"),
|
("ПО и аппаратные средства (модели, производители, количество):", "is_hw_sw_listbox", "hw_sw.json"),
|
||||||
("Операционные системы:", "is_os_sw_listbox"),
|
("Операционные системы:", "is_os_sw_listbox", "os_sw.json"),
|
||||||
("Прикладные программы (MS Office, OpenOffice и пр.):", "is_app_sw_listbox"),
|
("Прикладные программы (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
|
row = i * 2
|
||||||
ttk.Label(sw_frame, text=label).grid(row=row, column=0, sticky=tk.W, pady=(4, 0))
|
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)
|
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)
|
command=lambda a=attr: self._del_sw_item(getattr(self, a))).pack(fill=tk.X, pady=1)
|
||||||
ttk.Button(btn, text="✏️ Редактировать",
|
ttk.Button(btn, text="✏️ Редактировать",
|
||||||
command=lambda a=attr: self._edit_sw_item(getattr(self, a))).pack(fill=tk.X, pady=1)
|
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)
|
setattr(self, attr, box)
|
||||||
sw_frame.columnconfigure(0, weight=1)
|
sw_frame.columnconfigure(0, weight=1)
|
||||||
|
|
||||||
@@ -1564,11 +1566,61 @@ class DokoGenApp:
|
|||||||
if item:
|
if item:
|
||||||
self.defense_tools_listbox.insert(tk.END, 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('<Return>', lambda e: _ok())
|
||||||
|
dialog.bind('<Escape>', lambda e: _cancel())
|
||||||
|
dialog.wait_window()
|
||||||
|
return result.get('val')
|
||||||
|
|
||||||
def _add_sw_item(self, listbox):
|
def _add_sw_item(self, listbox):
|
||||||
"""Добавить строку в список ПО."""
|
"""Добавить строку в список ПО (большое окно)."""
|
||||||
item = simpledialog.askstring("Добавить", "Введите позицию:")
|
item = self._sw_dialog("Добавить позицию")
|
||||||
if item:
|
if item:
|
||||||
listbox.insert(tk.END, item.strip())
|
listbox.insert(tk.END, item)
|
||||||
|
|
||||||
def _del_sw_item(self, listbox):
|
def _del_sw_item(self, listbox):
|
||||||
"""Удалить выбранную строку из списка ПО."""
|
"""Удалить выбранную строку из списка ПО."""
|
||||||
@@ -1577,17 +1629,16 @@ class DokoGenApp:
|
|||||||
listbox.delete(sel[0])
|
listbox.delete(sel[0])
|
||||||
|
|
||||||
def _edit_sw_item(self, listbox):
|
def _edit_sw_item(self, listbox):
|
||||||
"""Редактировать выбранную строку списка ПО."""
|
"""Редактировать выбранную строку списка ПО (большое окно)."""
|
||||||
sel = listbox.curselection()
|
sel = listbox.curselection()
|
||||||
if not sel:
|
if not sel:
|
||||||
messagebox.showinfo("Редактировать", "Сначала выберите позицию в списке")
|
messagebox.showinfo("Редактировать", "Сначала выберите позицию в списке")
|
||||||
return
|
return
|
||||||
current = listbox.get(sel[0])
|
current = listbox.get(sel[0])
|
||||||
item = simpledialog.askstring("Редактировать", "Измените позицию:",
|
item = self._sw_dialog("Редактировать позицию", initial=current)
|
||||||
initialvalue=current)
|
|
||||||
if item is not None:
|
if item is not None:
|
||||||
listbox.delete(sel[0])
|
listbox.delete(sel[0])
|
||||||
listbox.insert(sel[0], item.strip())
|
listbox.insert(sel[0], item)
|
||||||
|
|
||||||
def _add_user_to_is(self):
|
def _add_user_to_is(self):
|
||||||
user = simpledialog.askstring("Добавить пользователя", "Введите ФИО или должность:")
|
user = simpledialog.askstring("Добавить пользователя", "Введите ФИО или должность:")
|
||||||
|
|||||||
Reference in New Issue
Block a user