fork download
  1. import tkinter as tk
  2. from tkinter import messagebox
  3. import yaml
  4. import os
  5. from datetime import datetime
  6. from collections import defaultdict
  7.  
  8. class RoutineDiaryApp:
  9. def __init__(self, root):
  10. self.root = root
  11. self.root.title("Routine Diary")
  12. self.root.geometry("600x500")
  13.  
  14. self.tasks_file = "tasks.txt"
  15. self.diary_file = "diary.yaml"
  16.  
  17. # Данные
  18. self.all_tasks = [] # Все задачи из файла
  19. self.today = datetime.now().strftime("%Y-%m-%d")
  20. self.today_clicks = defaultdict(int) # Счетчики кликов на сегодня
  21. self.clicked_tasks = set() # Задачи, нажатые сегодня
  22.  
  23. # Загрузка данных
  24. self.load_tasks()
  25. self.load_diary()
  26.  
  27. # GUI элементы
  28. self.create_widgets()
  29. self.update_buttons()
  30.  
  31. def load_tasks(self):
  32. """Загрузка списка задач из файла"""
  33. try:
  34. if os.path.exists(self.tasks_file):
  35. with open(self.tasks_file, 'r', encoding='utf-8') as f:
  36. self.all_tasks = sorted([line.strip() for line in f if line.strip()])
  37. else:
  38. # Создаем пример файла, если его нет
  39. with open(self.tasks_file, 'w', encoding='utf-8') as f:
  40. f.write("eat shizaprotective tablet\ntroll on dvach\nwipe ass after taking shit\n")
  41. self.all_tasks = ["eat shizaprotective tablet", "troll on dvach", "wipe ass after taking shit"]
  42. except Exception as e:
  43. messagebox.showerror("Error", f"Failed to load tasks: {e}")
  44. self.all_tasks = []
  45.  
  46. def load_diary(self):
  47. """Загрузка истории из YAML файла"""
  48. try:
  49. if os.path.exists(self.diary_file):
  50. with open(self.diary_file, 'r', encoding='utf-8') as f:
  51. diary_data = yaml.safe_load(f) or []
  52.  
  53. # Ищем записи за сегодня
  54. for day_entry in diary_data:
  55. if isinstance(day_entry, dict) and self.today in day_entry:
  56. today_data = day_entry[self.today]
  57. for task, timestamps in today_data.items():
  58. if isinstance(timestamps, list):
  59. self.today_clicks[task] = len(timestamps)
  60. if timestamps:
  61. self.clicked_tasks.add(task)
  62. break
  63. except Exception as e:
  64. print(f"Warning: Could not load diary: {e}")
  65. # Создаем пустой файл
  66. self.save_to_diary([])
  67.  
  68. def save_to_diary(self, data):
  69. """Сохранение данных в YAML файл"""
  70. try:
  71. with open(self.diary_file, 'w', encoding='utf-8') as f:
  72. yaml.dump(data, f, allow_unicode=True, default_flow_style=False)
  73. except Exception as e:
  74. messagebox.showerror("Error", f"Failed to save diary: {e}")
  75.  
  76. def create_widgets(self):
  77. """Создание элементов интерфейса"""
  78. # Фрейм для кнопок
  79. self.button_frame = tk.Frame(self.root)
  80. self.button_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
  81.  
  82. # Scrollbar для кнопок
  83. scrollbar = tk.Scrollbar(self.button_frame)
  84. scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
  85.  
  86. # Canvas для скроллирования кнопок
  87. self.canvas = tk.Canvas(self.button_frame, yscrollcommand=scrollbar.set)
  88. self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
  89.  
  90. scrollbar.config(command=self.canvas.yview)
  91.  
  92. # Фрейм для кнопок внутри canvas
  93. self.inner_frame = tk.Frame(self.canvas)
  94. self.canvas_window = self.canvas.create_window((0, 0), window=self.inner_frame, anchor=tk.NW)
  95.  
  96. # Привязка событий для скроллинга
  97. self.inner_frame.bind("<Configure>", self.on_frame_configure)
  98. self.canvas.bind("<Configure>", self.on_canvas_configure)
  99.  
  100. # Метка с текущей датой
  101. self.date_label = tk.Label(self.root, text=f"Today: {self.today}", font=("Arial", 12, "bold"))
  102. self.date_label.pack(pady=5)
  103.  
  104. def on_frame_configure(self, event):
  105. """Обновление scrollregion при изменении размера фрейма"""
  106. self.canvas.configure(scrollregion=self.canvas.bbox("all"))
  107.  
  108. def on_canvas_configure(self, event):
  109. """Обновление ширины внутреннего фрейма при изменении размера canvas"""
  110. self.canvas.itemconfig(self.canvas_window, width=event.width)
  111.  
  112. def update_buttons(self):
  113. """Обновление отображения кнопок"""
  114. # Очистка старых кнопок
  115. for widget in self.inner_frame.winfo_children():
  116. widget.destroy()
  117.  
  118. # Разделение задач на нажатые и ненажатые
  119. unclicked = sorted([t for t in self.all_tasks if t not in self.clicked_tasks])
  120. clicked = sorted([t for t in self.all_tasks if t in self.clicked_tasks])
  121.  
  122. # Создание кнопок для ненажатых задач
  123. for task in unclicked:
  124. btn = tk.Button(self.inner_frame, text=task,
  125. command=lambda t=task: self.on_task_click(t),
  126. bg="lightgray", height=2, width=40)
  127. btn.pack(pady=2, padx=5, fill=tk.X)
  128.  
  129. # Создание кнопок для нажатых задач (с количеством кликов)
  130. for task in clicked:
  131. count = self.today_clicks[task]
  132. btn_text = f"{task} ({count})"
  133. btn = tk.Button(self.inner_frame, text=btn_text,
  134. command=lambda t=task: self.on_task_click(t),
  135. bg="lightgreen", height=2, width=40)
  136. btn.pack(pady=2, padx=5, fill=tk.X)
  137.  
  138. def on_task_click(self, task):
  139. """Обработка клика по кнопке задачи"""
  140. try:
  141. current_time = datetime.now()
  142. timestamp = current_time.strftime("%Y-%m-%d %H:%M")
  143.  
  144. # Обновление счетчиков
  145. self.today_clicks[task] += 1
  146. self.clicked_tasks.add(task)
  147.  
  148. # Загрузка существующего дневника
  149. diary_data = []
  150. if os.path.exists(self.diary_file):
  151. with open(self.diary_file, 'r', encoding='utf-8') as f:
  152. diary_data = yaml.safe_load(f) or []
  153.  
  154. # Поиск или создание записи за сегодня
  155. today_entry = None
  156. for entry in diary_data:
  157. if isinstance(entry, dict) and self.today in entry:
  158. today_entry = entry
  159. break
  160.  
  161. if not today_entry:
  162. today_entry = {self.today: {}}
  163. diary_data.append(today_entry)
  164.  
  165. # Добавление timestamp
  166. if task not in today_entry[self.today]:
  167. today_entry[self.today][task] = []
  168.  
  169. today_entry[self.today][task].append(timestamp)
  170.  
  171. # Сохранение
  172. self.save_to_diary(diary_data)
  173.  
  174. # Обновление интерфейса
  175. self.update_buttons()
  176.  
  177. except Exception as e:
  178. messagebox.showerror("Error", f"Failed to log task: {e}")
  179.  
  180. def main():
  181. root = tk.Tk()
  182. app = RoutineDiaryApp(root)
  183. root.mainloop()
  184.  
  185. if __name__ == "__main__":
  186. main()
Runtime error #stdin #stdout #stderr 0.94s 37172KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
Traceback (most recent call last):
  File "./prog.py", line 1, in <module>
ModuleNotFoundError: No module named 'tkinter'