Captain_s-Log/app/ui/notes_list.py
Vic Sergeev a385308f38 working
2026-07-04 16:04:48 +03:00

230 lines
No EOL
7.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Список заметок"""
import tkinter as tk
from tkinter import ttk
from datetime import datetime
from app.config import Config
from app.ui.dialogs import ConfirmDialog
class NotesList(tk.Frame):
"""Виджет списка заметок"""
def __init__(self, parent, db, on_note_select=None, on_note_delete=None):
super().__init__(parent, bg=Config.COLORS['list_bg'])
self.db = db
self.on_note_select = on_note_select
self.on_note_delete = on_note_delete
self.notes = []
self.selected_note_id = None
self.create_widgets()
def create_widgets(self):
# Заголовок
self.header_label = tk.Label(
self,
text="Заметки",
bg=Config.COLORS['list_bg'],
fg=Config.COLORS['fg'],
font=('Arial', 12, 'bold')
)
self.header_label.pack(fill='x', padx=10, pady=(10, 5))
# Разделитель
separator = tk.Frame(self, height=1, bg=Config.COLORS['separator'])
separator.pack(fill='x', padx=5)
# Canvas и Scrollbar для списка
self.canvas = tk.Canvas(
self,
bg=Config.COLORS['list_bg'],
highlightthickness=0
)
self.scrollbar = ttk.Scrollbar(
self,
orient="vertical",
command=self.canvas.yview
)
self.notes_frame = tk.Frame(self.canvas, bg=Config.COLORS['list_bg'])
self.notes_frame.bind("<Configure>",
lambda e: self.canvas.configure(scrollregion=self.canvas.bbox("all")))
self.canvas_window = self.canvas.create_window(
(0, 0), window=self.notes_frame, anchor="nw"
)
self.canvas.configure(yscrollcommand=self.scrollbar.set)
self.canvas.pack(side="left", fill="both", expand=True)
self.scrollbar.pack(side="right", fill="y")
# Bind для изменения размера
self.canvas.bind('<Configure>', self.on_canvas_configure)
# Bind для колесика мыши
self.canvas.bind_all("<MouseWheel>", self.on_mousewheel)
def on_canvas_configure(self, event):
self.canvas.itemconfig(self.canvas_window, width=event.width)
def on_mousewheel(self, event):
self.canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
def load_notes(self, date):
"""Загрузить заметки для выбранной даты"""
# Очищаем текущий список
for widget in self.notes_frame.winfo_children():
widget.destroy()
date_str = date.strftime('%Y-%m-%d')
self.notes = self.db.get_notes_with_content_by_date(date_str)
if not self.notes:
empty_label = tk.Label(
self.notes_frame,
text="Нет заметок\nна этот день",
bg=Config.COLORS['list_bg'],
fg=Config.COLORS['fg'],
font=('Arial', 10),
justify='center'
)
empty_label.pack(expand=True, pady=20)
return
for note in self.notes:
self.create_note_item(note)
def create_note_item(self, note):
"""Создать элемент списка для заметки"""
item_frame = tk.Frame(
self.notes_frame,
bg=Config.COLORS['list_bg'],
cursor='hand2'
)
item_frame.pack(fill='x', padx=5, pady=2)
# Рамка для элемента
content_frame = tk.Frame(
item_frame,
bg=Config.COLORS['list_bg'],
highlightbackground=Config.COLORS['separator'],
highlightthickness=1
)
content_frame.pack(fill='x', padx=5, pady=2)
# Левая часть с датой
date_frame = tk.Frame(content_frame, bg=Config.COLORS['list_bg'])
date_frame.pack(side='left', padx=(10, 5), pady=5)
# Получаем дату заметки
created_at = datetime.strptime(
note['created_at'], '%Y-%m-%d %H:%M:%S'
)
day_month = created_at.strftime('%d.%m')
year = created_at.strftime('%Y')
tk.Label(
date_frame,
text=day_month,
bg=Config.COLORS['list_bg'],
fg=Config.COLORS['fg'],
font=('Arial', 11, 'bold')
).pack(anchor='w')
tk.Label(
date_frame,
text=year,
bg=Config.COLORS['list_bg'],
fg=Config.COLORS['fg'],
font=('Arial', 9)
).pack(anchor='w')
# Средняя часть с заголовком
title_frame = tk.Frame(content_frame, bg=Config.COLORS['list_bg'])
title_frame.pack(side='left', fill='x', expand=True, padx=10, pady=5)
title = note.get('title', '')
if not title:
# Берем первые 22 символа текста
content = note.get('content', '')
title = content[:22] + ('...' if len(content) > 22 else '')
if not title:
title = "Пустая заметка"
title_label = tk.Label(
title_frame,
text=title,
bg=Config.COLORS['list_bg'],
fg=Config.COLORS['fg'],
font=('Arial', 10),
anchor='w',
justify='left'
)
title_label.pack(anchor='w')
# Кнопка удаления
delete_btn = tk.Button(
content_frame,
text="🗑",
command=lambda n=note: self.delete_note(n),
bg=Config.COLORS['list_bg'],
fg=Config.COLORS['danger'],
relief='flat',
font=('Arial', 14),
cursor='hand2',
width=2
)
delete_btn.pack(side='right', padx=(0, 10), pady=5)
# Привязываем события клика для выбора заметки
for widget in [item_frame, content_frame, date_frame, title_frame, title_label]:
widget.bind('<Button-1>', lambda e, n=note: self.select_note(n))
# Подсветка при наведении
for widget in [content_frame, date_frame, title_frame]:
widget.bind('<Enter>', lambda e, f=content_frame:
f.configure(bg=Config.COLORS['list_selected']))
widget.bind('<Leave>', lambda e, f=content_frame:
f.configure(bg=Config.COLORS['list_bg']))
def select_note(self, note):
"""Выбрать заметку"""
self.selected_note_id = note['id']
# Обновляем визуальное выделение
for widget in self.notes_frame.winfo_children():
if isinstance(widget, tk.Frame):
for child in widget.winfo_children():
if isinstance(child, tk.Frame):
child.configure(bg=Config.COLORS['list_bg'])
if self.on_note_select:
self.on_note_select(note)
def delete_note(self, note):
"""Удалить заметку с подтверждением"""
dialog = ConfirmDialog(
self.winfo_toplevel(),
"Удаление заметки",
"Вы уверены, что хотите удалить эту заметку?"
)
self.wait_window(dialog)
if dialog.result:
self.db.delete_note(note['id'])
if self.on_note_delete:
self.on_note_delete()
# Перезагружаем список
if hasattr(self, 'current_date'):
self.load_notes(self.current_date)
def refresh(self, date):
"""Обновить список заметок"""
self.current_date = date
self.load_notes(date)