feature/session #27

Merged
Shikiryu merged 7 commits from feature/session into main 2023-06-02 12:24:15 +02:00
7 changed files with 267 additions and 4 deletions

1
.gitignore vendored
View File

@ -6,3 +6,4 @@ theme.py
!/dist/drawingtraining !/dist/drawingtraining
/*.spec /*.spec
/build/ /build/
/config.json

View File

@ -8,6 +8,7 @@ from src.util import Util
class Toolbar: class Toolbar:
def __init__(self, image_window, timer): def __init__(self, image_window, timer):
self.timers = []
self.current_image = None self.current_image = None
self.current_original_image = None self.current_original_image = None
self.image_window = image_window self.image_window = image_window
@ -47,6 +48,7 @@ class Toolbar:
self.timer_label.pack(side=RIGHT, ipadx=20) self.timer_label.pack(side=RIGHT, ipadx=20)
def display_new_timer(self): def display_new_timer(self):
self.timer = self.timers.pop(0)
self.timer_label.configure(text=Util.format_seconds(self.timer)) self.timer_label.configure(text=Util.format_seconds(self.timer))
self.timer_check = self.image_window.window.after(1000, self.update_timer, self.timer) self.timer_check = self.image_window.window.after(1000, self.update_timer, self.timer)
@ -59,7 +61,7 @@ class Toolbar:
self.timer_check = self.image_window.window.after(1000, self.update_timer, current) self.timer_check = self.image_window.window.after(1000, self.update_timer, current)
else: else:
self.image_window.window.after_cancel(self.timer_check) self.image_window.window.after_cancel(self.timer_check)
if len(self.image_window.images) == 0: if len(self.image_window.image.images) == 0 or len(self.timers) == 0:
self.image_window.window.destroy() self.image_window.window.destroy()
self.image_window.window.update() self.image_window.window.update()
return return

49
src/entity/config.py Normal file
View File

@ -0,0 +1,49 @@
import json
import os
from pathlib import Path
from configparser import *
import typing
class Config(object):
_CONFIG_FILE: typing.Optional[str] = None
_CONFIG: typing.Optional[dict] = None
def __init__(self, config_file=None):
if config_file is None:
config_file = "config.json"
# Check that specified config file exists
if not os.path.exists(config_file):
Path(config_file).touch()
with open(config_file, 'w') as configfile:
json.dump({"session": []}, configfile)
Config._CONFIG_FILE = config_file
with open(config_file, 'r') as f:
Config._CONFIG = json.load(f)
@staticmethod
def save():
with open(Config._CONFIG_FILE, 'w') as configfile:
json.dump(Config._CONFIG, configfile)
@staticmethod
def get_config_file() -> str:
return Config._CONFIG_FILE
@staticmethod
def get_required_env_var(env_var: str) -> str:
if env_var not in os.environ:
raise Exception(f"Please set the {env_var} environment variable")
return os.environ[env_var]
@staticmethod
def get_required_config_var(config_var: str) -> str:
assert Config._CONFIG
if config_var not in Config._CONFIG:
raise Exception(f"Please set the {config_var} variable in the config file {Config._CONFIG_FILE}")
return Config._CONFIG[config_var]

View File

@ -0,0 +1,10 @@
class DrawingElement:
def __init__(self, data=None):
if data is not None:
for key, value in data.items():
setattr(self, key, value)
else:
self.timer = 0
self.number_of_drawings = 0

View File

@ -1,14 +1,22 @@
from tkinter import * from tkinter import *
from tkinter import filedialog from tkinter import filedialog
from pathlib import Path from pathlib import Path
from src.entity.config import Config
from src.util import Util from src.util import Util
from functools import partial from functools import partial
from src.window.image import ImageWindow from src.window.image import ImageWindow
from src.window.session import SessionWindow
class App: class App:
def __init__(self, root): def __init__(self, root):
super().__init__() super().__init__()
self.list_in_session = None
self.custom = False
self.config = Config()
self.session = None
self.session_window = None
self.image_window = None self.image_window = None
self.root = root self.root = root
self.selected_folder = "" self.selected_folder = ""
@ -36,12 +44,16 @@ class App:
t = i t = i
new_button = Button(self.button_frame, text=Util.format_seconds(t), new_button = Button(self.button_frame, text=Util.format_seconds(t),
command=partial(self.set_timer_in_seconds, t)) command=partial(self.set_timer_in_seconds, t))
self.buttons.append(new_button) self.buttons.append(new_button)
self.button_frame.columnconfigure(i, weight=1) self.button_frame.columnconfigure(i, weight=1)
new_button.grid(row=0, column=i, sticky=W + E) new_button.grid(row=0, column=i, sticky=W + E)
i += 1 i += 1
new_button = Button(self.button_frame, text="Custom", command=self.custom_session)
self.buttons.append(new_button)
self.button_frame.columnconfigure(i, weight=1)
new_button.grid(row=0, column=i, sticky=W + E)
self.launch_button = Button(root, text="Let's draw!", command=self.lets_draw, state="disabled") self.launch_button = Button(root, text="Let's draw!", command=self.lets_draw, state="disabled")
self.launch_button.pack(side="bottom") self.launch_button.pack(side="bottom")
@ -49,6 +61,10 @@ class App:
self.image_window = ImageWindow(self) self.image_window = ImageWindow(self)
self.image_window.lets_draw(self.found_images.copy(), self.timer) self.image_window.lets_draw(self.found_images.copy(), self.timer)
def custom_session(self):
self.session_window = SessionWindow(self)
self.session_window.open()
def select_folder(self): def select_folder(self):
self.selected_folder = filedialog.askdirectory() self.selected_folder = filedialog.askdirectory()
self.found_images = list( self.found_images = list(
@ -58,12 +74,13 @@ class App:
self.check_lets_draw() self.check_lets_draw()
def check_lets_draw(self): def check_lets_draw(self):
if self.selected_folder != "" and len(self.found_images) > 0 and self.timer != 0: if self.selected_folder != "" and len(self.found_images) > 0 and (self.timer != 0 or self.custom):
self.launch_button.config(state="normal") self.launch_button.config(state="normal")
else: else:
self.launch_button.config(state="disabled") self.launch_button.config(state="disabled")
def set_timer_in_seconds(self, user_data): def set_timer_in_seconds(self, user_data):
self.custom = False
self.timer = user_data self.timer = user_data
for button in self.buttons: for button in self.buttons:
if button['text'] == Util.format_seconds(self.timer): if button['text'] == Util.format_seconds(self.timer):
@ -71,3 +88,11 @@ class App:
else: else:
button.config(bg="gray85") button.config(bg="gray85")
self.check_lets_draw() self.check_lets_draw()
def set_custom(self, list_in_session):
self.custom = True
self.list_in_session = list_in_session
self.check_lets_draw()
for button in self.buttons:
button.config(bg="gray85")
self.buttons[-1].config(bg="blue")

View File

@ -37,6 +37,7 @@ class ImageWindow:
def on_closing(self): def on_closing(self):
self.countdown_sound.stop() self.countdown_sound.stop()
self.window.destroy()
def next_image(self): def next_image(self):
if self.toolbar.timer_check is not None: if self.toolbar.timer_check is not None:
@ -46,8 +47,17 @@ class ImageWindow:
def lets_draw(self, images, timer): def lets_draw(self, images, timer):
random.shuffle(images) random.shuffle(images)
timers = []
if self.app.custom:
for element in self.app.list_in_session:
for number in range(int(element.number_of_drawings)):
timers.append(int(element.timer))
else:
for i in images:
timers.append(timer)
self.image.images = images self.image.images = images
self.toolbar.timer = timer self.toolbar.timers = timers
self.next_image() self.next_image()
def play_countdown(self): def play_countdown(self):

166
src/window/session.py Normal file
View File

@ -0,0 +1,166 @@
from functools import partial
from tkinter import *
from src.entity.config import Config
from src.entity.session.drawing import DrawingElement
from src.util import Util
class SessionWindow:
def __init__(self, app):
self.total_row_time_value_label = None
self.down_button = None
self.up_button = None
self.timer_input = None
self.number_of_drawings_input = None
self.selected_element_index = -1
self.delete_button = None
self.add_button = None
self.app = app
self.window = Toplevel(app.root)
self.window.title("Custom session")
self.window.geometry("600x600")
self.window.protocol("WM_DELETE_WINDOW", self.save_on_closing)
self.left_column = Frame(self.window, width=300, height=600)
self.right_column = Frame(self.window, width=300, height=600)
self.left_column.grid(row=0, column=0, sticky="ns")
self.right_column.grid(row=0, column=1, sticky="ns")
self.list_in_session = []
def open(self):
list = Config._CONFIG['session']
if list:
self.list_in_session = [DrawingElement(e) for e in list]
self.update_session_list()
def update_session_list(self):
self.reset_list()
for i, session in enumerate(self.list_in_session):
bg = "blue" if i == self.selected_element_index else "grey85"
new_session = Button(self.left_column,
text=session.number_of_drawings + " drawings of " + session.timer + "s each",
command=partial(self.edit_element, i),
bg=bg
)
new_session.grid(row=i, column=0)
button_frame = Frame(self.left_column)
self.add_button = Button(button_frame, text="+", command=self.add_element)
self.add_button.pack(side=LEFT, padx=0, pady=0)
self.delete_button = Button(button_frame, text="-", command=self.remove_element)
self.delete_button.pack(side=LEFT, padx=0, pady=0)
self.up_button = Button(button_frame, text="^", command=self.up_element)
self.up_button.pack(side=LEFT, padx=0, pady=0)
self.down_button = Button(button_frame, text="v", command=self.down_element)
self.down_button.pack(side=LEFT, padx=0, pady=0)
save_session_button = Button(button_frame, text="v", command=self.save_session)
save_session_button.pack(side=LEFT, padx=0, pady=0)
button_frame.grid()
def reset_element(self):
for widget in self.right_column.winfo_children():
widget.destroy()
def reset_list(self):
for widget in self.left_column.winfo_children():
widget.destroy()
def update_element(self, index=None):
self.reset_element()
if index is not None:
self.selected_element_index = index
element = self.list_in_session[self.selected_element_index]
self.update_session_list()
else:
element = DrawingElement()
number_of_drawings_label = Label(self.right_column, text="Number of drawings")
number_of_drawings_label.pack()
self.number_of_drawings_input = Entry(self.right_column)
self.number_of_drawings_input.insert(INSERT, element.number_of_drawings)
self.number_of_drawings_input.bind("<KeyRelease>", lambda e: self.update_local_timer(e))
self.number_of_drawings_input.pack()
self.number_of_drawings_input.focus_set()
timer_label = Label(self.right_column, text="Time per drawing in seconds")
timer_label.pack()
self.timer_input = Entry(self.right_column)
self.timer_input.insert(INSERT, element.timer)
self.timer_input.bind("<KeyRelease>", lambda e: self.update_local_timer(e))
self.timer_input.pack()
total_row_time_label = Label(self.right_column, text="Total row time")
total_row_time_label.pack()
self.total_row_time_value_label = Label(self.right_column, text="")
self.total_row_time_value_label.pack()
self.update_local_timer()
save_button = Button(self.right_column, text="Save", command=self.save)
save_button.pack()
def update_local_timer(self, event=None):
self.total_row_time_value_label.config(
text=Util.format_seconds(int(self.timer_input.get()) * int(self.number_of_drawings_input.get()))
)
def remove_element(self):
self.list_in_session.pop(self.selected_element_index)
self.selected_element_index = -1
self.update_session_list()
def edit_element(self, i):
self.update_element(i)
def add_element(self):
self.selected_element_index = -1
self.update_session_list()
self.update_element()
def up_element(self):
self.list_in_session.insert(self.selected_element_index - 1,
self.list_in_session.pop(self.selected_element_index))
self.selected_element_index -= 1
self.update_session_list()
def down_element(self):
self.list_in_session.insert(self.selected_element_index + 1,
self.list_in_session.pop(self.selected_element_index))
self.selected_element_index += 1
self.update_session_list()
def save(self):
element = DrawingElement() if self.selected_element_index < 0 \
else self.list_in_session[self.selected_element_index]
element.timer = self.timer_input.get()
element.number_of_drawings = self.number_of_drawings_input.get()
if self.selected_element_index < 0:
self.list_in_session.append(element)
else:
self.list_in_session[self.selected_element_index] = element
self.update_session_list()
self.selected_element_index = -1
self.reset_element()
def save_on_closing(self):
# TODO save
self.window.destroy()
def save_session(self):
Config._CONFIG['session'] = []
for element in self.list_in_session:
Config._CONFIG['session'].append(element.__dict__)
Config.save()
self.app.set_custom(self.list_in_session)
self.window.destroy()