Загрузка данных
# -*- coding: utf-8 -*-
# Файл: modules/project_list.py
import os
import tkinter as tk
from tkinter import Toplevel, messagebox, ttk
from modules.database_module import Session, get_all_indicators_by_group, list_groups
class ProjectListWindow:
"""
Окно для выбора проекта, группы и показателя.
Не содержит логики работы с событиями.
"""
def __init__(self, manager, root_window=None):
self.manager = manager
self.root_window = root_window
self.window = Toplevel(root_window)
self.window.title("Выбор параметров проекта")
self.window.geometry("500x250")
self.window.resizable(False, False)
self.session = Session()
self.group_names_to_codes = {}
self.name_to_code_map = {}
self._create_widgets()
self.update_project_list()
# Если проекты есть, загружаем данные для первого из них
if self.project_combobox["values"]:
self.project_combobox.current(0)
self._load_data()
def _create_widgets(self):
main_frame = tk.Frame(self.window)
main_frame.pack(padx=10, pady=10, fill="both", expand=True)
# Выбор проекта
tk.Label(main_frame, text="Проект:").pack(anchor="w", pady=(0, 2))
self.project_combobox = ttk.Combobox(main_frame, state="readonly")
self.project_combobox.pack(fill="x", padx=15, pady=5)
self.project_combobox.bind("<<ComboboxSelected>>", self._load_data)
# Выбор Группы
tk.Label(main_frame, text="Группа:").pack(anchor="w")
self.group_combobox = ttk.Combobox(main_frame, state="readonly")
self.group_combobox.bind("<<ComboboxSelected>>", self.update_indicators_list)
self.group_combobox.pack(fill="x", padx=15, pady=5)
# Выбор Показателя
tk.Label(main_frame, text="Показатель:").pack(anchor="w")
self.indicator_combobox = ttk.Combobox(main_frame, state="readonly")
self.indicator_combobox.pack(fill="x", padx=15, pady=5)
def update_project_list(self):
"""Обновляет список проектов."""
projects = self.manager.list_projects()
try:
display_names = []
self.name_to_code_map = {}
for p in projects:
display_names.append(p.name)
self.name_to_code_map[p.name] = p.id
self.project_combobox["values"] = display_names
if display_names:
self.project_combobox.set(display_names[0])
self.window.after(0, self._load_data)
return bool(display_names)
except Exception as e:
print(f"Ошибка загрузки проектов: {e}")
return False
def _on_project_select(self, event):
"""
Этот метод вызывается, когда пользователь выбирает элемент в Combobox.
Он нужен, чтобы принудительно перерисовать текст в поле.
"""
# Получаем выбранный объект Project
selected_object = self.project_combobox.get()
# Если выбранный объект существует и у него есть атрибут 'name'
if hasattr(selected_object, "name"):
self.project_combobox.set(selected_object.name)
try:
# Создаем карту "Имя -> Объект Project" для быстрого доступа
self.project_objects_map = {}
project_objects = []
for p in projects:
# Ключ - имя, значение - объект
self.project_objects_map[p.name] = p
project_objects.append(p)
self.project_combobox.bind("<<ComboboxSelected>>", self._on_project_select)
# Если список не пуст, выбираем первый элемент
if project_objects:
self.project_combobox.set(project_objects[0])
self._load_data()
return bool(project_objects)
except Exception as e:
print(f"Ошибка загрузки проектов: {e}")
return False
def _load_data(self, event=None):
"""Загружает данные (группы и показатели)."""
# Получаем выбранное ИМЯ из списка
selected_human_name = self.project_combobox.get()
if not selected_human_name:
# Очистка списков, если ничего не выбрано
self.group_combobox.set("")
self.indicator_combobox.set("")
self.group_combobox["values"] = []
self.indicator_combobox["values"] = []
self.group_names_to_codes.clear()
return
# print(
# f"[ДИАГНОСТИКА] Пользователь выбрал проект: '{selected_human_name}'. Загружаем данные..."
# )
try:
# --- 1. ИЩЕМ КОД ПО ИМЕНИ ---
# Используем карту, которую мы создали в update_project_list
project_code = self.name_to_code_map.get(selected_human_name)
if not project_code:
print(
f"[ОШИБКА] Код для имени '{selected_human_name}' не найден в карте."
)
return
# print(f"[ДИАГНОСТИКА] Данные для кода: {project_code}")
# --- 2. ЛОГИКА ЗАГРУЗКИ ГРУПП И ПОКАЗАТЕЛЕЙ ---
groups = list_groups(session=self.session)
if groups:
group_names = [group.name for group in groups]
self.group_combobox["values"] = group_names
if group_names:
first_group_name = group_names[0]
self.group_combobox.set(first_group_name)
self.group_names_to_codes.clear()
for group in groups:
self.group_names_to_codes[group.name] = group.code
first_group_code = self.group_names_to_codes[first_group_name]
indicators = get_all_indicators_by_group(
first_group_code, session=self.session
)
if indicators:
indicator_names = [i.name for i in indicators]
self.indicator_combobox["values"] = indicator_names
if indicator_names:
self.indicator_combobox.set(indicator_names[0])
except Exception as e:
print(f"[ОШИБКА] Не удалось загрузить данные: {e}")
def update_indicators_list(self, event=None):
"""Обновляет список показателей при выборе новой группы."""
selected_group_name = self.group_combobox.get()
if (
not selected_group_name
or selected_group_name not in self.group_names_to_codes
):
self.indicator_combobox.set("")
self.indicator_combobox["values"] = []
return
try:
selected_group_code = self.group_names_to_codes.get(selected_group_name)
if selected_group_code:
indicators = get_all_indicators_by_group(
selected_group_code, session=self.session
)
if indicators and len(indicators) > 0:
indicator_names = [i.name for i in indicators]
self.indicator_combobox["values"] = indicator_names
# Устанавливаем первый показатель по умолчанию
if indicator_names and (
not self.indicator_combobox.get()
or self.indicator_combobox.get() not in indicator_names
):
self.indicator_combobox.set(indicator_names[0])
else:
self.indicator_combobox["values"] = []
self.indicator_combobox.set("")
except Exception as e:
print(f"[ОШИБКА] Не удалось загрузить показатели: {e}")
def get_selected_data(self):
"""
Возвращает словарь с выбранными данными.
Теперь гарантированно возвращает 'indicator_code'.
"""
# Получаем выбранные имена из интерфейса
project_display_name = self.project_combobox.get()
group_name = self.group_combobox.get()
indicator_name = self.indicator_combobox.get()
# Получаем коды для проекта и группы из наших карт
project_code = self.name_to_code_map.get(project_display_name)
group_code = self.group_names_to_codes.get(group_name)
# --- НОВАЯ ЛОГИКА: Поиск КОДА показателя ---
indicator_code = None
# 1. Проверяем, что мы смогли получить код группы.
if group_code:
# 2. Запрашиваем список ВСЕХ показателей для этой группы из БД.
# Используем уже существующий метод, который работает с SQLAlchemy
indicators = get_all_indicators_by_group(group_code, session=self.session)
# 3. Ищем в этом списке тот показатель, имя которого совпадает с
# выбранным в combobox.
if indicators:
for indicator in indicators:
# Сравниваем имя из базы с именем, которое выбрал
# пользователь
if indicator.name == indicator_name:
# Нашли совпадение! Берем КОД из объекта.
indicator_code = indicator.code
break # Выходим из цикла, так как нашли нужное.
# --- ВОЗВРАЩАЕМ РЕЗУЛЬТАТ ---
return {
"project_name": project_display_name,
"project_code": project_code,
"group_name": group_name,
"group_code": group_code,
"indicator_name": indicator_name,
"indicator_code": indicator_code, # <-- Теперь этот ключ будет в словаре!
}