189 lines
No EOL
6.9 KiB
Python
189 lines
No EOL
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) |