2do/view.py

218 lines
8.6 KiB
Python

import tkinter as tk
from tktooltip import ToolTip
from tkinter import ttk
from tkinter.messagebox import askyesno
from tkinter.filedialog import askopenfilename, asksaveasfilename
from icecream import ic
from functools import partial
from threading import Thread
import time
import model
import json
import matplotlib.pyplot as plt
queue = model.Queue()
btns = {}
root = tk.Tk()
root.title("Прям очень Таскер")
root.geometry("250x350")
root.option_add("*tearOff", tk.FALSE)
root.iconbitmap(default=model.resource_path("icon.ico"))
def save_session():
path = asksaveasfilename(filetypes=[("Json", '*.json')], defaultextension=".json")
ic(path)
data = {
"tasks": [task.__dict__ for id, task in queue.task_slots.items()],
"break": queue.task_brake.__dict__
}
with open(path, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=4)
def build_plt():
labels = [task.name for id, task in queue.task_slots.items()] + [queue.task_brake.name]
times = [int(task.time/60) for id, task in queue.task_slots.items()] + [int(queue.task_brake.time/60)]
ic(labels)
ic(times)
plt.figure(figsize=(len(labels), 2))
plt.bar(labels, times)
plt.title("Статистика выполнения")
plt.show()
# plt.savefig("chart.png")
def load_session():
path = askopenfilename(filetypes=[("Json", '*.json')])
ic(path)
with open(path, "r", encoding="utf-8") as f:
data = json.load(f)
queue.task_slots = {str(task["id"]): model.Task(**task) for task in data["tasks"]}
queue.task_brake = model.Task(**data["break"]) if data["break"] else None
refrash()
def refrash():
for id, task in queue.task_slots.items():
btns[str(id)]["text"] = f"{id} {task.name} ({task.count})"
if hasattr(btns[str(id)], 'toolTip'):
btns[str(id)].toolTip.on_leave()
btns[str(id)].toolTip.destroy()
btns[str(id)].toolTip = ToolTip(btns[str(id)], msg=task.description)
def start_task_unic(num, event):
if not queue.run_task:
queue.run_task = True
queue.start_unic_task(str(num))
btnLabel.bind("<Button-1>", pause_task)
btnLabel.bind("<Button-3>", stop_task)
if hasattr(btnLabel, 'toolTip'):
btnLabel.toolTip.on_leave()
btnLabel.toolTip.destroy()
btnLabel.toolTip = ToolTip(btnLabel, msg=queue.current_task.description)
Thread(target=do_task).start()
def start_task(event):
if not queue.run_task:
queue.run_task = True
queue.start_task()
btnLabel.bind("<Button-1>", pause_task)
btnLabel.bind("<Button-3>", stop_task)
if hasattr(btnLabel, 'toolTip'):
btnLabel.toolTip.on_leave()
btnLabel.toolTip.destroy()
btnLabel.toolTip = ToolTip(btnLabel, msg=queue.current_task.description)
Thread(target=do_task).start()
def restore_task(event):
queue.run_task = True
queue.current_task_time_max = queue.current_task_time_current + time.time()
Thread(target=do_task).start()
btnLabel.bind("<Button-1>", pause_task)
def pause_task(event):
myText = f"{btnLabel.cget('text')}\nПауза"
queue.run_task = False
time.sleep(0.2)
ic(myText)
btnLabel["text"] = myText
btnLabel.bind("<Button-1>", restore_task)
def stop_task(event):
queue.run_task = False
btnLabel["text"] = "Начать"
btnLabel.bind("<Button-1>", start_task)
if hasattr(btnLabel, 'toolTip'):
btnLabel.toolTip.on_leave()
btnLabel.toolTip.destroy()
btnLabel.toolTip = ToolTip(btnLabel, msg="Начать задачу")
def do_task():
ic(queue.current_task.name)
while queue.current_task_time_max > time.time() and queue.run_task:
queue.current_task_time_current = queue.current_task_time_max - time.time()
m, s = divmod(queue.current_task_time_current, 60)
btnLabel["text"] = f"{queue.current_task.name}\n{int(m)} минут {int(s)} секкунд"
time.sleep(1)
if queue.run_task:
queue.current_task.count += 1
queue.current_task.time += queue.current_task_time
if queue.current_task.id > 0:
ic(queue.task_slots)
if queue.task_slots[str(queue.current_task.id)].finished:
btns[str(queue.current_task.id)]["text"] = f"{queue.current_task.id} {queue.current_task.name} ({queue.current_task.count})\nЗавершено"
else:
btns[str(queue.current_task.id)]["text"] = f"{queue.current_task.id} {queue.current_task.name} ({queue.current_task.count})"
queue.sound()
stop_task(0)
def submit(window, btn, num, name, description, event=0):
name = name.get()
description = description.get()
ic(name, description)
btn["text"] = f"{num} {name} (0)"
if hasattr(btn, 'toolTip'):
btn.toolTip.on_leave()
btn.toolTip.destroy()
btn.toolTip = ToolTip(btn, msg=description)
queue.create_task(name, description, num)
window.destroy()
def finish_unfinished_task(btn, num, event):
if str(num) in queue.task_slots.keys():
if queue.task_slots[str(num)].finished:
result = askyesno(title="Подтвержение операции", message="Отменить завершение задачи?")
else:
result = askyesno(title="Подтвержение операции", message="Завершить задачу?")
if result:
queue.task_slots[str(num)].finished = False if queue.task_slots[str(num)].finished else True
if queue.task_slots[str(num)].finished:
btns[str(num)]["text"] = f"{queue.task_slots[str(num)].id} {queue.task_slots[str(num)].name} ({queue.task_slots[str(num)].count})\nЗавершено"
else:
btns[str(num)]["text"] = f"{queue.task_slots[str(num)].id} {queue.task_slots[str(num)].name} ({queue.task_slots[str(num)].count})"
def click(btn, num, event):
if (str(num) in queue.task_slots.keys()):
start_task_unic(num, 1)
else:
ic(event, btn, num)
window = tk.Toplevel()
window.title("Новая задача")
window.geometry("250x200")
label = ttk.Label(window, text=f"Имя задачи:")
input_name = ttk.Entry(window)
label_description = ttk.Label(window, text=f"Описание задачи (если необходимо):")
input_description = ttk.Entry(window)
window.bind('<Return>', partial(submit, window, btn, num, input_name, input_description))
button_sambit = ttk.Button(window, text="Создать задачу", command = partial(submit, window, btn, num, input_name, input_description))
label.pack(fill="both")
input_name.pack(expand=True, fill="both")
label_description.pack(fill="both")
input_description.pack(expand=True, fill="both")
input_name.focus()
button_sambit.pack(expand=True, fill="both")
window.grab_set()
window.attributes("-topmost",True)
def clear_task(btn, num, event):
result = askyesno(title="Подтвержение операции", message="Хотите удалить задачу?")
if result:
btn["text"] = f"{num} ____________ ()"
queue.delete_task(num)
for c in range(2): root.columnconfigure(index=c, weight=1)
for r in range(4): root.rowconfigure(index=r, weight=1)
for i in range(0,6):
btn = ttk.Button(text=f"{i+1} ____________ ()")
btn.bind("<Button-1>", partial(click, btn, i+1))
btn.bind("<Button-3>", partial(clear_task, btn, i+1))
btn.bind("<Button-2>", partial(finish_unfinished_task, btn, i+1))
btn.grid(column=(i%2), row=(i//2), sticky="nsew")
btns[str(i+1)] = btn
ic(btns)
btnLabel = ttk.Button(text=f"Начать")
btnLabel.bind("<Button-1>", start_task)
btnLabel.bind("<Button-3>", stop_task)
btnLabel.grid(column=0, row=3, columnspan=2, sticky="nsew")
main_menu = tk.Menu()
file_menu = tk.Menu()
file_menu.add_command(label="Сохранить сессию", command=save_session)
file_menu.add_command(label="Загрузить сессию", command=load_session)
# file_menu.add_separator()
# file_menu.add_command(label="Выход")
main_menu.add_cascade(label="Файл", menu=file_menu)
main_menu.add_cascade(label="График сессии", command=build_plt)
main_menu.add_cascade(label="Закрепить", command= lambda: root.attributes("-topmost",True))
root.config(menu=main_menu)
root.update_idletasks()
root.mainloop()