189 lines
6.9 KiB
Python
189 lines
6.9 KiB
Python
|
|
"""Виджет календаря"""
|
|||
|
|
import tkinter as tk
|
|||
|
|
from tkinter import ttk
|
|||
|
|
import calendar
|
|||
|
|
from datetime import datetime
|
|||
|
|
from app.config import Config
|
|||
|
|
|
|||
|
|
|
|||
|
|
class CalendarWidget(tk.Frame):
|
|||
|
|
"""Кастомный виджет календаря"""
|
|||
|
|
|
|||
|
|
def __init__(self, parent, db, on_date_select=None):
|
|||
|
|
super().__init__(parent, bg=Config.COLORS['calendar_bg'])
|
|||
|
|
self.db = db
|
|||
|
|
self.on_date_select = on_date_select
|
|||
|
|
|
|||
|
|
self.current_date = datetime.now()
|
|||
|
|
self.selected_date = datetime.now()
|
|||
|
|
|
|||
|
|
self.create_widgets()
|
|||
|
|
self.update_calendar()
|
|||
|
|
|
|||
|
|
def create_widgets(self):
|
|||
|
|
# Заголовок с месяцем и годом
|
|||
|
|
self.header_frame = tk.Frame(self, bg=Config.COLORS['calendar_bg'])
|
|||
|
|
self.header_frame.pack(fill='x', pady=(10, 5))
|
|||
|
|
|
|||
|
|
self.prev_btn = tk.Button(
|
|||
|
|
self.header_frame,
|
|||
|
|
text="◀",
|
|||
|
|
command=self.prev_month,
|
|||
|
|
bg=Config.COLORS['calendar_bg'],
|
|||
|
|
fg=Config.COLORS['fg'],
|
|||
|
|
relief='flat',
|
|||
|
|
font=('Arial', 12),
|
|||
|
|
cursor='hand2'
|
|||
|
|
)
|
|||
|
|
self.prev_btn.pack(side='left', padx=(20, 0))
|
|||
|
|
|
|||
|
|
self.month_label = tk.Label(
|
|||
|
|
self.header_frame,
|
|||
|
|
text="",
|
|||
|
|
bg=Config.COLORS['calendar_bg'],
|
|||
|
|
fg=Config.COLORS['calendar_header'],
|
|||
|
|
font=('Arial', 14, 'bold')
|
|||
|
|
)
|
|||
|
|
self.month_label.pack(side='left', expand=True)
|
|||
|
|
|
|||
|
|
self.next_btn = tk.Button(
|
|||
|
|
self.header_frame,
|
|||
|
|
text="▶",
|
|||
|
|
command=self.next_month,
|
|||
|
|
bg=Config.COLORS['calendar_bg'],
|
|||
|
|
fg=Config.COLORS['fg'],
|
|||
|
|
relief='flat',
|
|||
|
|
font=('Arial', 12),
|
|||
|
|
cursor='hand2'
|
|||
|
|
)
|
|||
|
|
self.next_btn.pack(side='right', padx=(0, 20))
|
|||
|
|
|
|||
|
|
# Дни недели
|
|||
|
|
days_frame = tk.Frame(self, bg=Config.COLORS['calendar_bg'])
|
|||
|
|
days_frame.pack(fill='x', padx=5, pady=5)
|
|||
|
|
|
|||
|
|
days = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс']
|
|||
|
|
for i, day in enumerate(days):
|
|||
|
|
days_frame.grid_columnconfigure(i, weight=1)
|
|||
|
|
tk.Label(
|
|||
|
|
days_frame,
|
|||
|
|
text=day,
|
|||
|
|
bg=Config.COLORS['calendar_bg'],
|
|||
|
|
fg=Config.COLORS['fg'],
|
|||
|
|
font=('Arial', 9, 'bold')
|
|||
|
|
).grid(row=0, column=i)
|
|||
|
|
|
|||
|
|
# Сетка календаря
|
|||
|
|
self.calendar_frame = tk.Frame(self, bg=Config.COLORS['calendar_bg'])
|
|||
|
|
self.calendar_frame.pack(fill='both', expand=True, padx=5, pady=5)
|
|||
|
|
|
|||
|
|
self.day_buttons = []
|
|||
|
|
for row in range(6):
|
|||
|
|
self.calendar_frame.grid_rowconfigure(row, weight=1)
|
|||
|
|
for col in range(7):
|
|||
|
|
self.calendar_frame.grid_columnconfigure(col, weight=1)
|
|||
|
|
btn = tk.Label(
|
|||
|
|
self.calendar_frame,
|
|||
|
|
text="",
|
|||
|
|
bg=Config.COLORS['calendar_bg'],
|
|||
|
|
fg=Config.COLORS['fg'],
|
|||
|
|
font=('Arial', 10),
|
|||
|
|
cursor='hand2'
|
|||
|
|
)
|
|||
|
|
btn.grid(row=row, column=col, sticky='nsew', padx=1, pady=1)
|
|||
|
|
btn.bind('<Button-1>', lambda e, r=row, c=col: self.on_day_click(r, c))
|
|||
|
|
self.day_buttons.append(btn)
|
|||
|
|
|
|||
|
|
def update_calendar(self):
|
|||
|
|
year = self.current_date.year
|
|||
|
|
month = self.current_date.month
|
|||
|
|
|
|||
|
|
# Обновляем заголовок
|
|||
|
|
months = ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь',
|
|||
|
|
'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь']
|
|||
|
|
self.month_label.config(text=f"{months[month - 1]} {year}")
|
|||
|
|
|
|||
|
|
# Получаем дни с заметками
|
|||
|
|
days_with_notes = self.db.get_dates_with_notes(year, month)
|
|||
|
|
|
|||
|
|
# Создаем календарь
|
|||
|
|
cal = calendar.monthcalendar(year, month)
|
|||
|
|
|
|||
|
|
for idx, btn in enumerate(self.day_buttons):
|
|||
|
|
row = idx // 7
|
|||
|
|
col = idx % 7
|
|||
|
|
|
|||
|
|
if row < len(cal) and col < len(cal[row]):
|
|||
|
|
day = cal[row][col]
|
|||
|
|
if day != 0:
|
|||
|
|
btn.config(text=str(day))
|
|||
|
|
|
|||
|
|
# Определяем цвет фона
|
|||
|
|
today = datetime.now()
|
|||
|
|
is_today = (day == today.day and
|
|||
|
|
month == today.month and
|
|||
|
|
year == today.year)
|
|||
|
|
|
|||
|
|
is_selected = (day == self.selected_date.day and
|
|||
|
|
month == self.selected_date.month and
|
|||
|
|
year == self.selected_date.year)
|
|||
|
|
|
|||
|
|
has_notes = day in days_with_notes
|
|||
|
|
|
|||
|
|
if is_today and is_selected:
|
|||
|
|
btn.config(
|
|||
|
|
bg=Config.COLORS['today_bg'],
|
|||
|
|
fg=Config.COLORS['fg']
|
|||
|
|
)
|
|||
|
|
elif is_today:
|
|||
|
|
btn.config(
|
|||
|
|
bg=Config.COLORS['today_bg'],
|
|||
|
|
fg=Config.COLORS['fg']
|
|||
|
|
)
|
|||
|
|
elif is_selected:
|
|||
|
|
btn.config(
|
|||
|
|
bg=Config.COLORS['accent'],
|
|||
|
|
fg=Config.COLORS['fg']
|
|||
|
|
)
|
|||
|
|
elif has_notes:
|
|||
|
|
btn.config(
|
|||
|
|
bg='#5a7a3a',
|
|||
|
|
fg=Config.COLORS['fg']
|
|||
|
|
)
|
|||
|
|
else:
|
|||
|
|
btn.config(
|
|||
|
|
bg=Config.COLORS['calendar_bg'],
|
|||
|
|
fg=Config.COLORS['fg']
|
|||
|
|
)
|
|||
|
|
else:
|
|||
|
|
btn.config(text="", bg=Config.COLORS['calendar_bg'])
|
|||
|
|
else:
|
|||
|
|
btn.config(text="", bg=Config.COLORS['calendar_bg'])
|
|||
|
|
|
|||
|
|
def prev_month(self):
|
|||
|
|
if self.current_date.month == 1:
|
|||
|
|
self.current_date = self.current_date.replace(year=self.current_date.year - 1, month=12)
|
|||
|
|
else:
|
|||
|
|
self.current_date = self.current_date.replace(month=self.current_date.month - 1)
|
|||
|
|
self.update_calendar()
|
|||
|
|
|
|||
|
|
def next_month(self):
|
|||
|
|
if self.current_date.month == 12:
|
|||
|
|
self.current_date = self.current_date.replace(year=self.current_date.year + 1, month=1)
|
|||
|
|
else:
|
|||
|
|
self.current_date = self.current_date.replace(month=self.current_date.month + 1)
|
|||
|
|
self.update_calendar()
|
|||
|
|
|
|||
|
|
def on_day_click(self, row, col):
|
|||
|
|
year = self.current_date.year
|
|||
|
|
month = self.current_date.month
|
|||
|
|
cal = calendar.monthcalendar(year, month)
|
|||
|
|
|
|||
|
|
if row < len(cal) and col < len(cal[row]):
|
|||
|
|
day = cal[row][col]
|
|||
|
|
if day != 0:
|
|||
|
|
self.selected_date = datetime(year, month, day)
|
|||
|
|
self.update_calendar()
|
|||
|
|
|
|||
|
|
if self.on_date_select:
|
|||
|
|
self.on_date_select(self.selected_date)
|