Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """interface for updating handout data file for Germanna ACE.
- Author: Michael G. Cividanes
- Date: 2023-04-10
- email: [email protected]
- """
- from functools import partial
- import tkinter
- from tkinter import messagebox
- from tkinter import ttk
- from tkinter import filedialog as fd
- import os
- import json
- import requests
- import ace_exceptions as ace
- from settings import HEIGHT_,WIDTH_,CUR_DIR,ICON,DEBUG,DEF_CLASS_LIST,BACKGROUND_COLOR,\
- FOREGROUND_COLOR,TITLE_FONT,ENTRY_FONT,FULL_WIDTH,H_PAD,V_PAD,HIGHLIGHT_COLOR,BORDER_SIZE,\
- H_PAD_SMALL,V_PAD_SMALL,WHITE_,DB_FORGROUND_COLOR,DB_BACKGROUND_COLOR,DB_HIGHLIGHT_COLOR,\
- DB_BUTTON_BG_COLOR,SRC_FILE, SMALL_FONT
- from handouts import handout
- if DEBUG:
- HEIGHT_ += 100
- class handoutData:
- """data object for handout updater program."""
- def __init__(self,filename):
- self.handout_title = ""
- self.handout_url = ""
- self.selected_classes = []
- self.description = ""
- self.issues = []
- self.cur_data = []
- self.read_data(filename)
- self.cur_classes = self.get_classes()
- def read_data(self,filename):
- """read data from file"""
- with open(filename,"r") as file:
- cur_data = json.load(file)
- for entry in cur_data:
- self.cur_data.append(handout(entry["name"],entry["url"],\
- entry["classes"],entry["description"],entry["issues"]))
- def write_data(self):
- """write data to file"""
- with open(SRC_FILE,"w") as file:
- json.dump(self.cur_data,file,indent=4)
- def set_info(self,gen_info,selected_classes,description,issues):
- """set handout information"""
- self.handout_title = gen_info[0]
- self.handout_url = gen_info[1]
- self.selected_classes = selected_classes
- self.description = description
- self.issues = issues
- def add_handout(self):
- """add handout to data"""
- self.cur_data.append(handout(self.handout_title,self.handout_url,self.selected_classes,\
- self.description,self.issues))
- self.handout_title = ""
- self.handout_url = ""
- self.description = ""
- self.issues=[]
- def get_classes(self):
- """get list of classes"""
- class_list = []
- for entry in self.cur_data:
- for cls in entry.classes:
- if cls not in class_list:
- class_list.append(cls)
- return class_list
- def get_info(self):
- """get handout information"""
- return self.handout_title,self.handout_url,self.selected_classes,self.description,self.issues
- class general_frame_gui():
- def __init__(self,parent):
- """GUI for general information"""
- frame = tkinter.Frame(parent)
- tkinter.Label(frame,text="Handout Title:",font=TITLE_FONT).grid(row=0,column=0,sticky="w",columnspan=2)
- self.in_handout_name = tkinter.Entry(frame,font=ENTRY_FONT,width=90)
- self.in_handout_name.grid(row=0,column=2,columnspan=10,sticky="we")
- tkinter.Label(frame,text="Handout URL:",font=TITLE_FONT).grid(row=1,column=0,sticky="w",columnspan=2)
- self.in_handout_url = tkinter.Entry(frame,font=ENTRY_FONT)
- self.in_handout_url.grid(row=1,column=2,columnspan=10,sticky="we")
- frame.grid(row=0,column=0,sticky="we",columnspan=12,padx=H_PAD,pady=V_PAD)
- def check_handout_name(self):
- """checks that the handout name is long enough"""
- handout_title = self.in_handout_name.get()
- if len(handout_title) > 10:
- print("Handout name is long enough")
- return True
- else:
- tkinter.messagebox.showinfo("Handout title too short", "Handout title is too short to be a valid title. Did you type it correctly and in the correct place?")
- return False
- def check_handout_url(self):
- """checks that the url is long enough to be valid"""
- url_value = self.in_handout_url.get()
- if len(url_value) > 15:
- try:
- if requests.get(url_value).status_code == 200:
- return True
- else:
- messagebox.showerror("Error","There is no response from the URL. This can be caused by a mistyped URL.")
- except:
- messagebox.showerror("Error","There is no response from the URL. This can be caused by a mistyped URL.")
- return False
- else:
- messagebox.showerror("Error","Handout url is too short. Did you mis-type it?")
- return False
- def get_info(self):
- """get handout information"""
- if self.check_handout_name():
- if self.check_handout_url():
- return self.in_handout_name.get(),self.in_handout_url.get()
- else:
- return False
- else:
- return False
- def clear_input(self):
- """clear input fields"""
- self.in_handout_name.delete(0,"end")
- self.in_handout_url.delete(0,"end")
- class class_selector_gui():
- def __init__(self,parent,cur_data):
- """GUI for class selection frame"""
- frame = tkinter.Frame(parent,bg=BACKGROUND_COLOR,highlightbackground=HIGHLIGHT_COLOR,\
- highlightthickness=BORDER_SIZE)
- frame.grid(row=1,column=0,sticky="we",columnspan=12,padx=H_PAD,pady=V_PAD)
- self.selected_classes = []
- self.class_chx_boxes = []
- tkinter.Label(frame,text="Select Classes:",font=TITLE_FONT,bg=BACKGROUND_COLOR).grid(row=0,column=0,sticky="we",\
- columnspan=12,padx=H_PAD,pady=V_PAD)
- list_of_classes = ""
- if len(cur_data.cur_classes) > len(DEF_CLASS_LIST):
- list_of_classes = cur_data.cur_classes
- else:
- list_of_classes = DEF_CLASS_LIST
- for cls in list_of_classes:
- temp_check_box = tkinter.Checkbutton(frame,text=cls,bg=BACKGROUND_COLOR,\
- fg=FOREGROUND_COLOR,font=SMALL_FONT,command = partial(self.add_class,cls))
- self.class_chx_boxes.append(temp_check_box)
- row = 1
- col = 0
- for i in range(len(self.class_chx_boxes)):
- if row > 10:
- row = 1
- col += 1
- self.class_chx_boxes[i].grid(row=row,column=col,sticky="w",padx=H_PAD_SMALL,pady=V_PAD_SMALL)
- row += 1
- def add_class(self,cls):
- """add class to selected classes"""
- if cls not in self.selected_classes:
- self.selected_classes.append(cls)
- else:
- self.selected_classes.remove(cls)
- def get_info(self):
- """get selected classes"""
- if len(self.selected_classes) == 0:
- tkinter.messagebox.showinfo("No classes selected", "No classes were selected. Please select at least one class.")
- return False
- else:
- return self.selected_classes
- def clear_input(self):
- """clear input"""
- for box in self.class_chx_boxes:
- box.deselect()
- self.selected_classes = []
- class description_frame_gui():
- def __init__(self,parent):
- """GUI for description frame"""
- frame = tkinter.Frame(parent,bg=BACKGROUND_COLOR,highlightbackground=HIGHLIGHT_COLOR,\
- highlightthickness=BORDER_SIZE)
- frame.grid(row=2,column=0,sticky="we",columnspan=6,padx=H_PAD,pady=V_PAD,ipady=V_PAD)
- tkinter.Label(frame,text="Description:",font=TITLE_FONT,bg=BACKGROUND_COLOR).grid(row=0,column=0,sticky="we",columnspan=6,padx=H_PAD,pady=V_PAD)
- self.in_description = tkinter.Text(frame,font=ENTRY_FONT,height=14,width=50)
- self.in_description.grid(row=1,column=0,sticky="w",columnspan=6,padx=H_PAD_SMALL,pady=V_PAD_SMALL)
- def get_info(self):
- """get description"""
- description = self.in_description.get("1.0","end-1c")
- if len(description) > 125:
- if len(description.split())>19 and len(description.split())<49:
- return description
- else:
- if len(description.split())>=49:
- answer = tkinter.messagebox.askyesno("Description Length", "That description is quite long. Generally we want the handout descriptions to be between 20 and 50 words. Are you sure you want to enter this description?")
- print("answer:",answer)
- if answer:
- print("description:",description)
- return description
- else:
- return False
- else:
- pass
- if len(description.split())<=19:
- tkinter.messagebox.showinfo("Description too short", "Description is too short. It should be between 20 and 50 words.")
- return False
- def clear_input(self):
- """clear description"""
- self.in_description.delete("1.0","end")
- class issues_frame_gui():
- def __init__(self,parent):
- """GUI for issues frame"""
- frame = tkinter.Frame(parent,bg=BACKGROUND_COLOR,highlightbackground=HIGHLIGHT_COLOR,\
- highlightthickness=BORDER_SIZE)
- frame.grid(row=2,column=6,sticky="e",columnspan=6,padx=H_PAD,pady=V_PAD)
- tkinter.Label(frame,text="Issues this handout is meant to address:",font=TITLE_FONT,bg=BACKGROUND_COLOR).grid(row=0,column=0,sticky="w",columnspan=6,padx=H_PAD,pady=V_PAD)
- tkinter.Label(frame,text="Current issues:",font=SMALL_FONT,bg=BACKGROUND_COLOR).grid(row=1,column=0,sticky="w",columnspan=6,padx=H_PAD_SMALL,pady=V_PAD_SMALL)
- self.in_issues = tkinter.Text(frame,font=ENTRY_FONT,height=10,width=50,state="disabled")
- self.in_issues.grid(row=2,column=0,sticky="w",columnspan=6,padx=H_PAD,pady=V_PAD)
- self.issues_entry = tkinter.Entry(frame,font=ENTRY_FONT)
- self.issues_entry.grid(row=3,column=0,sticky="w",columnspan=4,padx=H_PAD,pady=V_PAD)
- self.issues_entry.bind("<Return>",lambda event: self.add_issue())
- tkinter.Button(frame,text="Add Issue",font=ENTRY_FONT,command=self.add_issue).grid(row=3,column=4,sticky="w",columnspan=2,padx=H_PAD,pady=V_PAD)
- def add_issue(self):
- """add issue to issues"""
- self.in_issues.config(state="normal")
- self.in_issues.insert(tkinter.END,"✏ "+self.issues_entry.get())
- self.issues_entry.delete(0,"end")
- self.in_issues.config(state="disabled")
- def get_info(self):
- """get issues"""
- issues = self.in_issues.get("1.0","end-1c").split("✏ ")
- for item in issues:
- if item == "":
- issues.remove(item)
- if len(issues) == 0:
- tkinter.messagebox.showinfo("No issues", "No issues were added. Please add at least one issue.")
- return False
- else:
- return issues
- def clear_input(self):
- """clear input"""
- self.issues_entry.delete(0,"end")
- self.in_issues.config(state="normal")
- self.in_issues.delete("1.0","end")
- self.in_issues.config(state="disabled")
- def clear_data(self):
- self.in_issues.delete(0,"end")
- self.issues_entry.delete(0,"end")
- class debug_gui():
- def __init__(self,parent,cd,gi,sl,hd,hi):
- """GUI for debug frame"""
- self.cur_data= cd
- self.gen_info = gi
- self.select_classes = sl
- self.description = hd
- self.issues = hi
- frame = tkinter.Frame(parent,bg=DB_BACKGROUND_COLOR,highlightbackground=HIGHLIGHT_COLOR,\
- highlightthickness=BORDER_SIZE)
- frame.grid(row=4,column=0,sticky="we",columnspan=12,padx=H_PAD,pady=V_PAD)
- tkinter.Label(frame,text="Debug menu:",font=TITLE_FONT,bg=BACKGROUND_COLOR).grid(row=0,column=0,sticky="we",columnspan=12,padx=H_PAD,pady=V_PAD)
- tkinter.Button(frame,text="Print data",font=ENTRY_FONT,command=self.print_data).grid(row=1,column=0,sticky="w",columnspan=2,padx=H_PAD,pady=V_PAD)
- tkinter.Button(frame,text="Check data",font=ENTRY_FONT,command=self.check_data).grid(row=1,column=2,sticky="w",columnspan=2,padx=H_PAD,pady=V_PAD)
- tkinter.Button(frame,text="Clear data",font=ENTRY_FONT,command=self.clear_data).grid(row=1,column=4,sticky="w",columnspan=2,padx=H_PAD,pady=V_PAD)
- tkinter.Button(frame,text="Check Handouts",font=ENTRY_FONT,command=self.check_handouts).grid(row=1,column=6,sticky="w",columnspan=2,padx=H_PAD,pady=V_PAD)
- tkinter.Button(frame,text="Check Classes",font=ENTRY_FONT,command=self.check_classes).grid(row=1,column=8,sticky="w",columnspan=2,padx=H_PAD,pady=V_PAD)
- tkinter.Button(frame,text="Check Issues",font=ENTRY_FONT,command=self.check_issues).grid(row=1,column=10,sticky="w",columnspan=2,padx=H_PAD,pady=V_PAD)
- tkinter.Button(frame,text="Check URL",font=ENTRY_FONT,command=self.check_url).grid(row=1,column=12,sticky="w",columnspan=2,padx=H_PAD,pady=V_PAD)
- def check_url(self):
- """check url"""
- print("Checking url...")
- if self.gen_info.in_handout_url.get() == "":
- print("url is empty!")
- else:
- print("url is good!")
- def check_issues(self):
- """check issues"""
- print("Checking issues...")
- if self.issues.get_info() == []:
- print("No issues!")
- else:
- print("Issues are good!")
- def check_classes(self):
- """check classes"""
- print("Checking classes...")
- if self.select_classes.get_classes() == []:
- print("No classes!")
- else:
- print("Classes are good!")
- def check_handouts(self):
- """check handouts"""
- print("Checking handouts...")
- for handout in self.cur_data.cur_data:
- print("Checking handout:",handout.name)
- if handout.name == "":
- print("Handout has no name!")
- if handout.url == "":
- print("Handout has no url!")
- if handout.classes == []:
- print("Handout has no classes!")
- if handout.description == "":
- print("Handout has no description!")
- if handout.issues == []:
- print("Handout has no issues!")
- print(f"the handout \"{handout.name}\" is good!")
- def clear_data(self):
- """clear data"""
- self.gen_info.clear_input()
- self.select_classes.clear_input()
- self.description.clear_input()
- self.issues.clear_input()
- def check_data(self):
- """check data for errors"""
- print("There are currently "+str(len(self.cur_data.cur_data))+" handouts in the data file.")
- def print_data(self):
- """print data to console"""
- print("Curent data:",self.cur_data.get_info())
- print("general info:",self.gen_info.get_info())
- print("Selected Classes:",self.select_classes.get_info())
- print("Description:",self.description.get_info())
- print("Issues:",self.issues.get_info())
- class HandoutUpdater:
- """main GUI class"""
- def __init__(self):
- self.cur_data = handoutData(os.path.join(CUR_DIR,SRC_FILE))
- self.main_window = tkinter.Tk()
- self.main_window.geometry(f"{WIDTH_}x{HEIGHT_}")
- self.main_window.resizable(False,True)
- self.main_window.bind("<Configure>",lambda event:self.print_size(event))
- self.main_window.title("Germanna ACE Handout Updater")
- self.main_window.iconbitmap(os.path.join(CUR_DIR,ICON))
- self.general_info_frame = general_frame_gui(self.main_window)
- self.class_selector_frame = class_selector_gui(self.main_window,self.cur_data)
- self.description_frame = description_frame_gui(self.main_window)
- self.issues_frame = issues_frame_gui(self.main_window)
- tkinter.Button(self.main_window,text="Update Source",command=self.update_source).grid(row=3,column=0,sticky="w",columnspan=3,padx=H_PAD,pady=V_PAD)
- tkinter.Button(self.main_window,text="Add Handout",command=self.add_handout).grid(row=3,column=10,sticky="e",columnspan=3,padx=H_PAD,pady=V_PAD)
- self.debug = None
- if DEBUG:
- self.debug = debug_gui(self.main_window,self.cur_data,self.general_info_frame,self.class_selector_frame,\
- self.description_frame,self.issues_frame)
- self.main_window.mainloop()
- def update_source(self):
- """update source file"""
- filename = fd.askopenfilename(initialdir=CUR_DIR,title="Select file",filetypes=(("Germanna ACE DATA","*.gad"),("all files","*.*")))
- self.cur_data.read_data(filename)
- def check_content(self):
- """checks that the content is acceptable"""
- content_check = []
- content_check.append(self.general_info_frame.get_info())
- content_check.append(self.class_selector_frame.get_info())
- content_check.append(self.description_frame.get_info()[1])
- content_check.append(self.issues_frame.get_info())
- if False in content_check:
- return False
- else:
- return True, content_check
- def add_handout(self):
- """add handout to source file"""
- content = self.check_content()
- print("content:",content)
- if content[0]:
- self.cur_data.set_info(content[1][0],content[1][1],content[1][2],content[1][3])
- self.cur_data.add_handout()
- #self.general_info_frame.clear_input()
- #self.class_selector_frame.clear_input()
- #self.description_frame.clear_input()
- #self.issues_frame.clear_input()
- #self.cur_data.write_data()
- def print_size(self,event):
- """print size of window"""
- print(self.main_window.winfo_width(),"x",self.main_window.winfo_height())
- if __name__ == "__main__":
- HandoutUpdater()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement