working
This commit is contained in:
commit
a385308f38
44 changed files with 1614 additions and 0 deletions
230
app/ui/notes_list.py
Normal file
230
app/ui/notes_list.py
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
"""Список заметок"""
|
||||
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)
|
||||
Loading…
Add table
Add a link
Reference in a new issue