class FormChildClassification: def __init__(self, frm_parent, connection): self.connection = connection self.directive = Message() self.decide = True self.id_selected = 0 self.frm_child_list = LabelFrame(frm_parent) self.frm_child_crud = LabelFrame(frm_parent) self.frm_child_crud.config(fg=TEXT_COLOR, font=SUBTITLE_FONT) self.initialize_components() def initialize_components(self): """ Method that initialize the visual components for each form associated with the local administration """ # Resources for the Forms self.new_icon = PhotoImage(file=r"./Resources/create.png") self.view_icon = PhotoImage(file=r"./Resources/view.png") self.modify_icon = PhotoImage(file=r"./Resources/modify.png") self.remove_icon = PhotoImage(file=r"./Resources/delete.png") self.save_icon = PhotoImage(file=r"./Resources/save.png") self.back_icon = PhotoImage(file=r"./Resources/back.png") self.cancel_icon = PhotoImage(file=r"./Resources/cancel.png") # Components for List FRM lbl_sep1 = Label(self.frm_child_list) lbl_sep1.grid(row=0, column=0, padx=10, pady=25) self.trv_available = Treeview(self.frm_child_list, height=15, columns=('N', 'Name', '# categories')) self.trv_available.heading('#0', text='ID', anchor=CENTER) self.trv_available.heading('#1', text='N', anchor=CENTER) self.trv_available.heading('#2', text='Name', anchor=CENTER) self.trv_available.heading('#3', text='# categories', anchor=CENTER) self.trv_available.column('#0', width=0, minwidth=50, stretch=NO) self.trv_available.column('#1', width=20, minwidth=20, stretch=NO) self.trv_available.column('#2', width=200, minwidth=200, stretch=NO) self.trv_available.column('#3', width=150, minwidth=150, stretch=NO) self.trv_available.grid(row=0, column=1, sticky=W, pady=25) vsb_trv_av = Scrollbar(self.frm_child_list, orient="vertical", command=self.trv_available.yview) vsb_trv_av.grid(row=0, column=2, pady=25, sticky=NS) self.trv_available.configure(yscrollcommand=vsb_trv_av.set) frm_aux4 = Frame(self.frm_child_list) btn_new = Button(frm_aux4, image=self.new_icon, command=self.click_new) btn_new.grid(row=0, column=0, pady=5, padx=5, sticky=E) btn_new_ttp = CreateToolTip(btn_new, 'New classification') btn_view = Button(frm_aux4, image=self.view_icon, command=self.click_view) btn_view.grid(row=1, column=0, pady=5, padx=5, sticky=E) btn_view_ttp = CreateToolTip(btn_view, 'View classification') btn_edit = Button(frm_aux4, image=self.modify_icon, command=self.click_update) btn_edit.grid(row=2, column=0, pady=5, padx=5, sticky=E) btn_edit_ttp = CreateToolTip(btn_edit, 'Edit classification') btn_delete = Button(frm_aux4, image=self.remove_icon, command=self.click_delete) btn_delete.grid(row=3, column=0, pady=5, padx=5, sticky=E) btn_delete_ttp = CreateToolTip(btn_delete, 'Delete classification') frm_aux4.grid(row=0, column=4, pady=25, padx=25, sticky=NW) # Components CRUD self.frm_class = LabelFrame(self.frm_child_crud) self.frm_class.config(fg=TEXT_COLOR, font=SUBTITLE_FONT) lbl_class = Label(self.frm_child_crud, text='Name*') lbl_class.config(fg=TEXT_COLOR, font=LABEL_FONT) lbl_class.grid(row=0, column=0, pady=10, padx=20, sticky=W) lbl_desc_categories = Label( self.frm_child_crud, text='Enter categories separated by an Enter (\\n)') lbl_desc_categories.config(fg=TEXT_COLOR, font=LABEL_FONT) lbl_desc_categories.grid(row=1, column=0, pady=10, padx=20, columnspan=4, sticky=W) lbl_categories = Label(self.frm_child_crud, text='Categories*') lbl_categories.config(fg=TEXT_COLOR, font=LABEL_FONT) lbl_categories.grid(row=2, column=0, pady=10, padx=20, sticky=NW) lbl_sep2 = Label(self.frm_child_crud) lbl_sep2.grid(row=2, column=1, padx=20, pady=10) self.txt_name_class = Entry(self.frm_child_crud, width=50, font=TEXT_FONT) self.txt_name_class.grid(row=0, column=2, columnspan=2, pady=10, sticky=W) self.txt_categories = Text(self.frm_child_crud, height=10, width=50, font=TEXT_FONT) self.txt_categories.grid(row=2, column=2, pady=10, sticky=W) vsb_txt_cat = Scrollbar(self.frm_child_crud, orient="vertical", command=self.txt_categories.yview) vsb_txt_cat.grid(row=2, column=3, pady=10, sticky=NS) self.txt_categories.configure(yscrollcommand=vsb_txt_cat.set) sep_aux1 = Separator(self.frm_child_crud, orient=VERTICAL) sep_aux1.grid(row=0, column=4, sticky=NS, rowspan=3, padx=20) self.btn_save = Button(self.frm_child_crud, image=self.save_icon, command=self.click_save) btn_save_ttp = CreateToolTip(self.btn_save, 'Save classification') self.btn_back = Button(self.frm_child_crud, image=self.back_icon, command=self.click_back) btn_back_ttp = CreateToolTip(self.btn_back, 'Go back') self.btn_cancel = Button(self.frm_child_crud, image=self.cancel_icon, command=self.click_cancel) btn_cancel_ttp = CreateToolTip(self.btn_cancel, 'Cancel') def retrieve_list(self): # Remove existing elements in the list for item in self.trv_available.get_children(): self.trv_available.delete(item) self.directive = Message(action=67) self.connection = self.directive.send_directive(self.connection) # Adding elements into the list for index, item in enumerate(self.connection.message.information): elements = item.split('¥') self.trv_available.insert('', 'end', text=elements[0], values=(index + 1, summarize_text(elements[1], 200), summarize_text(elements[2], 150))) if len(self.trv_available.get_children()) != 0: self.trv_available.selection_set( self.trv_available.get_children()[0]) def show_frm(self): self.retrieve_list() self.frm_child_list.grid(row=1, column=0, columnspan=9, rowspan=8, pady=10, padx=10) def hide_frm(self): self.clear_fields() self.frm_child_list.grid_forget() self.frm_child_crud.grid_forget() def click_new(self): self.classification = Classification() self.frm_child_crud['text'] = 'New Classification' self.txt_name_class.focus_set() self.btn_save.grid(row=0, column=5, padx=20) self.btn_cancel.grid(row=1, column=5, padx=20) self.frm_child_list.grid_forget() self.frm_child_crud.grid(row=1, column=0, columnspan=9, rowspan=8, pady=10, padx=10) def click_view(self): if len(self.trv_available.selection()) == 1: id_selected = int( self.trv_available.item( self.trv_available.selection())['text']) # Retrieve selected classification from the database self.directive = Message(action=70, information=[id_selected]) self.connection = self.directive.send_directive(self.connection) self.classification = Classification( id=id_selected, name=self.connection.message.information[0], categories=self.connection.message.information[1]) # Insert information into visual components self.txt_name_class.insert(0, self.classification.name) # Section to insert categories in textbox length_string = 0 for item in self.classification.categories: elements = item.split('¥') self.txt_categories.insert('end-1c', elements[1] + '\n') length_string += len(elements[1]) + 1 self.txt_categories.delete('end-2c', 'end') self.frm_child_crud['text'] = 'View classification' self.txt_name_class['bg'] = DISABLED_COLOR self.txt_categories['bg'] = DISABLED_COLOR self.txt_name_class['state'] = DISABLED self.txt_categories['state'] = DISABLED self.btn_back.grid(row=0, column=5, padx=20) self.frm_child_list.grid_forget() self.frm_child_crud.grid(row=1, column=0, columnspan=9, rowspan=8, pady=10, padx=10) else: messagebox.showwarning(parent=self.frm_child_list, title='No selection', message='You must select one item') def click_update(self): if len(self.trv_available.selection()) == 1: id_selected = int( self.trv_available.item( self.trv_available.selection())['text']) self.directive = Message(action=70, information=[id_selected, 'validate']) self.connection = self.directive.send_directive(self.connection) if self.connection.message.action == 5: # An error ocurred while trying to update the item messagebox.showerror( parent=self.frm_child_list, title='Can not update the item', message=self.connection.message.information[0]) else: self.classification = Classification( id=id_selected, name=self.connection.message.information[0], categories=self.connection.message.information[1]) self.txt_name_class.insert(0, self.classification.name) # Section to insert categories in textbox length_string = 0 for item in self.classification.categories: elements = item.split('¥') self.txt_categories.insert('end-1c', elements[1] + '\n') length_string += len(elements[1]) + 1 self.txt_categories.delete('end-2c', 'end') self.frm_child_crud['text'] = 'Update classification' self.txt_name_class.focus_set() self.btn_save.grid(row=0, column=5, padx=20) self.btn_cancel.grid(row=1, column=5, padx=20) self.frm_child_list.grid_forget() self.frm_child_crud.grid(row=1, column=0, columnspan=9, rowspan=8, pady=10, padx=10) else: messagebox.showwarning(parent=self.frm_child_list, title='No selection', message='You must select one item') def click_delete(self): if len(self.trv_available.selection()) == 1: decision = messagebox.askyesno( parent=self.frm_child_list, title='Confirmation', message='Are you sure you want to delete the item?') if decision: id_selected = int( self.trv_available.item( self.trv_available.selection())['text']) self.directive = Message(action=69, information=[id_selected]) self.connection = self.directive.send_directive( self.connection) if self.connection.message.action == 5: # An error ocurred while deleting the item messagebox.showerror( parent=self.frm_child_list, title='Can not delete the item', message=self.connection.message.information[0]) else: self.retrieve_list() else: messagebox.showwarning(parent=self.frm_child_list, title='No selection', message='You must select one item') def click_save(self): if self.validate_fields(): self.classification.name = self.txt_name_class.get() if self.classification.id == 0: # Creating a new classification self.directive = Message( action=66, information=[self.classification.name]) self.connection = self.directive.send_directive( self.connection) self.classification.id = self.connection.message.information[0] self.classification.categories = self.txt_categories.get( '1.0', 'end-1c').split('\n') for item in self.classification.categories: if item: # None blank space will be saved self.directive = Message( action=71, information=[item, self.classification.id]) self.connection = self.directive.send_directive( self.connection) else: # Updating a classification self.directive = Message(action=68, information=[ self.classification.id, self.classification.name ]) self.connection = self.directive.send_directive( self.connection) # Delete categories associated with the current classification self.directive = Message(action=74, information=[self.classification.id]) self.connection = self.directive.send_directive( self.connection) # Create categories for the current classification self.classification.categories = self.txt_categories.get( '1.0', 'end-1c').split('\n') for item in self.classification.categories: if item: # None blank space will be saved self.directive = Message( action=71, information=[item, self.classification.id]) self.connection = self.directive.send_directive( self.connection) self.click_back() def click_back(self): self.clear_fields() self.frm_child_crud.grid_forget() self.show_frm() def click_cancel(self): decision = True categories_aux = len( self.txt_categories.get('1.0', 'end-1c').split('\n')) categories_aux = categories_aux - 1 if self.classification.id == 0 else categories_aux if self.txt_name_class.get() != self.classification.name or \ categories_aux != len(self.classification.categories): decision = messagebox.askyesno( parent=self.frm_child_crud, title='Cancel', message='Are you sure you want to cancel?') if decision: self.click_back() def validate_fields(self): if len(self.txt_name_class.get()) == 0: messagebox.showwarning( parent=self.frm_child_crud, title='Missing information', message='You must insert a name for the classification') return False if len(self.txt_categories.get('1.0', 'end-1c')) != 0: categories_aux = self.txt_categories.get('1.0', 'end-1c').split('\n') for item in categories_aux: for char in item: if char.isspace( ) or char == '\t' or not char or char == '\n': messagebox.showwarning( parent=self.frm_child_crud, title='Missing information', message='A category can not be empty') return False return True else: messagebox.showwarning( parent=self.frm_child_crud, title='Missing information', message='You must insert at least one category') return False def clear_fields(self): self.btn_save.grid_forget() self.btn_cancel.grid_forget() self.btn_back.grid_forget() self.txt_name_class['state'] = NORMAL self.txt_categories['state'] = NORMAL self.txt_name_class['bg'] = ENABLED_COLOR self.txt_categories['bg'] = ENABLED_COLOR self.txt_name_class.delete(0, END) self.txt_categories.delete('1.0', 'end-1c')
class FormChildAED: def __init__(self, frm_parent, title, connection): self.connection = connection self.directive = Message() self.title = title self.decide = True self.id_selected = 0 self.frm_child_list = LabelFrame(frm_parent) self.frm_child_crud = LabelFrame(frm_parent) self.frm_child_crud.config(fg=TEXT_COLOR, font=SUBTITLE_FONT) self.initialize_components() def initialize_components(self): """ Method that initialize the visual components for each form associated with the local administration """ # Resources for the Forms self.new_icon = PhotoImage(file=r"./Resources/create.png") self.modify_icon = PhotoImage(file=r"./Resources/modify.png") self.remove_icon = PhotoImage(file=r"./Resources/delete.png") self.save_icon = PhotoImage(file=r"./Resources/save.png") self.cancel_icon = PhotoImage(file=r"./Resources/cancel.png") # Components for List Form lbl_sep1 = Label(self.frm_child_list) lbl_sep1.grid(row=0, column=0, padx=10, pady=25) self.trv_available = Treeview(self.frm_child_list, height=15, columns=('N', 'Name', 'Surname', 'E-mail')) self.trv_available.heading('#0', text='ID', anchor=CENTER) self.trv_available.heading('#1', text='N', anchor=CENTER) self.trv_available.heading('#2', text='Name', anchor=CENTER) self.trv_available.heading('#3', text='Surname', anchor=CENTER) self.trv_available.heading('#4', text='E-mail', anchor=CENTER) self.trv_available.column('#0', width=0, minwidth=50, stretch=NO) self.trv_available.column('#1', width=20, minwidth=20, stretch=NO) self.trv_available.column('#2', width=200, minwidth=200, stretch=NO) self.trv_available.column('#3', width=200, minwidth=200, stretch=NO) self.trv_available.column('#4', width=400, minwidth=400, stretch=NO) self.trv_available.grid(row=0, column=1, sticky=W, pady=25) vsb_trv_av = Scrollbar(self.frm_child_list, orient="vertical", command=self.trv_available.yview) vsb_trv_av.grid(row=0, column=2, pady=25, sticky=NS) self.trv_available.configure(yscrollcommand=vsb_trv_av.set) frm_aux4 = Frame(self.frm_child_list) btn_new = Button(frm_aux4, image=self.new_icon, command=self.click_new) btn_new.grid(row=0, column=0, pady=5, padx=5, sticky=E) btn_new_ttp = CreateToolTip(btn_new, 'New ' + self.title.lower()) btn_edit = Button(frm_aux4, image=self.modify_icon, command=self.click_update) btn_edit.grid(row=1, column=0, pady=5, padx=5, sticky=E) btn_edit_ttp = CreateToolTip(btn_edit, 'Edit ' + self.title.lower()) btn_delete = Button(frm_aux4, image=self.remove_icon, command=self.click_delete) btn_delete.grid(row=2, column=0, pady=5, padx=5, sticky=E) btn_delete_ttp = CreateToolTip(btn_delete, 'Delete ' + self.title.lower()) frm_aux4.grid(row=0, column=3, pady=25, padx=25, sticky=NW) # Components for CRUD FRM lbl_name = Label(self.frm_child_crud, text='Name*') lbl_name.config(fg=TEXT_COLOR, font=LABEL_FONT) lbl_name.grid(row=0, column=0, pady=10, padx=20, sticky=W) lbl_surname = Label(self.frm_child_crud, text='Surname*') lbl_surname.config(fg=TEXT_COLOR, font=LABEL_FONT) lbl_surname.grid(row=1, column=0, pady=10, padx=20, sticky=W) lbl_email = Label(self.frm_child_crud, text='E-mail*') lbl_email.config(fg=TEXT_COLOR, font=LABEL_FONT) lbl_email.grid(row=2, column=0, pady=10, padx=20, sticky=W) self.lbl_old_passwd = Label(self.frm_child_crud, text='Old password*') self.lbl_old_passwd.config(fg=TEXT_COLOR, font=LABEL_FONT) self.lbl_passwd = Label(self.frm_child_crud, text='New password*') self.lbl_passwd.config(fg=TEXT_COLOR, font=LABEL_FONT) self.lbl_passwd_conf = Label(self.frm_child_crud, text='Confirm new password*') self.lbl_passwd_conf.config(fg=TEXT_COLOR, font=LABEL_FONT) self.txt_name = Entry(self.frm_child_crud) self.txt_name.grid(row=0, column=1, pady=10, padx=20, sticky=W) self.txt_surname = Entry(self.frm_child_crud) self.txt_surname.grid(row=1, column=1, pady=10, padx=20, sticky=W) self.txt_email = Entry(self.frm_child_crud) self.txt_email.grid(row=2, column=1, pady=10, padx=20, sticky=W) self.txt_old_passwd = Entry(self.frm_child_crud, show="*") self.txt_passwd = Entry(self.frm_child_crud, show="*") self.txt_passwd_conf = Entry(self.frm_child_crud, show="*") sep_aux2 = Separator(self.frm_child_crud, orient=VERTICAL) sep_aux2.grid(row=0, column=2, sticky=NS, rowspan=6) frm_aux = Frame(self.frm_child_crud) btn_save = Button(frm_aux, image=self.save_icon, command=self.click_save) btn_save.grid(row=0, column=0, padx=5, pady=5, sticky=E) btn_save_ttp = CreateToolTip(btn_save, 'Save ' + self.title.lower()) btn_cancel = Button(frm_aux, image=self.cancel_icon, command=self.click_cancel) btn_cancel.grid(row=1, column=0, padx=5, pady=5, sticky=E) btn_cancel_ttp = CreateToolTip(btn_cancel, 'Cancel') frm_aux.grid(row=0, column=3, pady=10, padx=25, sticky=N, rowspan=6) def retrieve_list(self): """ Method that retrieve users information from the server and displays them in the TreeView from the List Form """ # Remove existing elements in the list for item in self.trv_available.get_children(): self.trv_available.delete(item) # Retrieve information from the server if self.title == 'Experimenter': self.directive = Message(action=17) elif self.title == 'Designer': self.directive = Message(action=22) elif self.title == 'Administrator': self.directive = Message(action=12) else: raise Exception('Error en recuperacion: tipo de usuario') self.connection = self.directive.send_directive(self.connection) # Adding elements in the list for index, item in enumerate(self.connection.message.information): elements = item.split('¥') self.trv_available.insert('', 'end', text=elements[0], values=(index + 1, elements[1], elements[2], elements[3])) # Mark first element of the treeview if exist if len(self.trv_available.get_children()) != 0: self.trv_available.selection_set( self.trv_available.get_children()[0]) def show_frm(self): """ Show the List form when the User administration is called """ self.retrieve_list() self.frm_child_list.grid(row=1, column=0, columnspan=9, rowspan=8, pady=10, padx=10) def hide_frm(self): """ Hide the User administration Forms """ self.clear_fields() self.frm_child_list.grid_forget() self.frm_child_crud.grid_forget() def click_new(self): """ Initialize CRUD Form for creating a new user. """ self.user = Designer() self.frm_child_list.grid_forget() self.txt_name.focus_set() self.frm_child_crud['text'] = 'New ' + self.title.lower() self.lbl_passwd.grid(row=3, column=0, pady=10, padx=20, sticky=W) self.lbl_passwd_conf.grid(row=4, column=0, pady=10, padx=20, sticky=W) self.txt_passwd.grid(row=3, column=1, pady=10, padx=20, sticky=W) self.txt_passwd_conf.grid(row=4, column=1, pady=10, padx=20, sticky=W) self.frm_child_crud.grid(row=1, column=0, columnspan=9, rowspan=8, pady=10, padx=10) def click_update(self): """ Initialize CRUD Form for updating a user. It loads information of selected User into visual components """ if len(self.trv_available.selection()) == 1: id_selected = int( self.trv_available.item( self.trv_available.selection())['text']) if self.title == 'Experimenter': self.directive = Message(action=20, information=[id_selected]) elif self.title == 'Designer': self.directive = Message(action=25, information=[id_selected]) else: self.directive = Message(action=15, information=[id_selected]) self.connection = self.directive.send_directive(self.connection) if self.connection.message.action == 5: # An error ocurred while trying to update the item messagebox.showerror( parent=self.frm_child_list, title='Can not update the item', message=self.connection.message.information[0]) else: self.user = Designer( id=id_selected, name=self.connection.message.information[0], surname=self.connection.message.information[1], user=self.connection.message.information[2], password=self.connection.message.information[3]) self.txt_name.insert(0, self.user.name) self.txt_surname.insert(0, self.user.surname) self.txt_email.insert(0, self.user.user) self.frm_child_list.grid_forget() self.txt_name.focus_set() self.frm_child_crud['text'] = 'Update ' + self.title.lower() self.lbl_old_passwd.grid(row=3, column=0, pady=10, padx=20, sticky=W) self.lbl_passwd.grid(row=4, column=0, pady=10, padx=20, sticky=W) self.lbl_passwd_conf.grid(row=5, column=0, pady=10, padx=20, sticky=W) self.txt_old_passwd.grid(row=3, column=1, pady=10, padx=20, sticky=W) self.txt_passwd.grid(row=4, column=1, pady=10, padx=20, sticky=W) self.txt_passwd_conf.grid(row=5, column=1, pady=10, padx=20, sticky=W) self.frm_child_crud.grid(row=1, column=0, columnspan=9, rowspan=8, pady=10, padx=10) else: messagebox.showwarning(parent=self.frm_child_list, title='No selection', message='You must select one item') def click_delete(self): """ Method that removes a selected user from the initial list (changes are updated in DB) """ if len(self.trv_available.selection()) == 1: decision = messagebox.askyesno( parent=self.frm_child_list, title='Confirmation', message='Are you sure you want to delete the item?') if decision: id_selected = int( self.trv_available.item( self.trv_available.selection())['text']) if self.title == 'Experimenter': self.directive = Message(action=19, information=[id_selected]) elif self.title == 'Designer': self.directive = Message(action=24, information=[id_selected]) else: self.directive = Message(action=14, information=[id_selected]) self.connection = self.directive.send_directive( self.connection) if self.connection.message.action == 5: # An error ocurred while deleting the item messagebox.showerror( parent=self.frm_child_list, title='Can not delete the item', message=self.connection.message.information[0]) else: self.retrieve_list() else: messagebox.showwarning(parent=self.frm_child_list, title='No selection', message='You must select one item') def click_save(self): """ Saves information of the user inserted into the visual components and sends to the server """ if self.validate_fields(): self.user.name = self.txt_name.get() self.user.surname = self.txt_surname.get() self.user.user = self.txt_email.get() self.user.password = self.txt_passwd.get() if self.user.id == 0: # Creating an user if self.title == 'Experimenter': self.directive = Message( action=16, information=[ self.user.name, self.user.surname, self.user.user, hashlib.sha1( self.user.password.encode()).hexdigest() ]) elif self.title == 'Designer': self.directive = Message( action=21, information=[ self.user.name, self.user.surname, self.user.user, hashlib.sha1( self.user.password.encode()).hexdigest() ]) else: self.directive = Message( action=11, information=[ self.user.name, self.user.surname, self.user.user, hashlib.sha1( self.user.password.encode()).hexdigest() ]) else: # Updating an user if self.title == 'Experimenter': self.directive = Message( action=18, information=[ self.user.id, self.user.name, self.user.surname, self.user.user, hashlib.sha1( self.user.password.encode()).hexdigest() ]) elif self.title == 'Designer': self.directive = Message( action=23, information=[ self.user.id, self.user.name, self.user.surname, self.user.user, hashlib.sha1( self.user.password.encode()).hexdigest() ]) else: self.directive = Message(action=13, information=[ self.user.id, self.user.name, self.user.surname, self.user.user, self.user.password ]) self.connection = self.directive.send_directive(self.connection) if self.connection.message.action == 5: messagebox.showwarning(parent=self.frm_child_crud, title='Repeated e-mail', message=self.connection.message.comment) else: self.clear_fields() self.frm_child_crud.grid_forget() self.show_frm() def click_cancel(self): """ Function activated when 'Cancel' button is pressed in frm_child_crud """ decision = True if self.txt_name.get() != self.user.name or \ self.txt_surname.get() != self.user.surname or \ self.txt_email.get() != self.user.user or len(self.txt_passwd.get()) != 0 or \ len(self.txt_passwd_conf.get()) != 0: if self.user.id != 0 and len( self.txt_passwd_conf.get()) != 0 or self.user.id == 0: decision = messagebox.askyesno( parent=self.frm_child_crud, title='Cancel', message='Are you sure you want to cancel?') if decision: self.clear_fields() self.frm_child_crud.grid_forget() self.show_frm() def validate_fields(self): if len(self.txt_name.get()) == 0: messagebox.showwarning( parent=self.frm_child_crud, title='Missing information', message='You must insert a name for the {}'.format( self.title.lower())) return False if len(self.txt_surname.get()) == 0: messagebox.showwarning( parent=self.frm_child_crud, title='Missing information', message='You must insert a surname for the {}'.format( self.title.lower())) return False if len(self.txt_email.get()) == 0: messagebox.showwarning( parent=self.frm_child_crud, title='Missing information', message='You must insert an e-mail for the {}'.format( self.title.lower())) return False # If updating an user if self.user.id != 0 and len(self.txt_old_passwd.get()) == 0: messagebox.showwarning( parent=self.frm_child_crud, title='Missing information', message='You must insert the old password for the {}'.format( self.title.lower())) return False if len(self.txt_passwd.get()) == 0: messagebox.showwarning( parent=self.frm_child_crud, title='Missing information', message='You must insert a new password for the {}'.format( self.title.lower())) return False if len(self.txt_passwd_conf.get()) == 0: messagebox.showwarning( parent=self.frm_child_crud, title='Missing information', message='You must confirm the new password for the {}'.format( self.title.lower())) return False if self.txt_passwd.get() != self.txt_passwd_conf.get(): messagebox.showwarning( parent=self.frm_child_crud, title='Password field', message= 'The new password you provided does not match the confirmation' ) return False # If updating an user if self.user.id != 0 and self.user.password != hashlib.sha1( self.txt_old_passwd.get().encode()).hexdigest(): messagebox.showwarning(parent=self.frm_child_crud, title='Old password field', message='The old password is incorrect') return False return True def clear_fields(self): self.txt_name.delete(0, END) self.txt_surname.delete(0, END) self.txt_email.delete(0, END) self.txt_old_passwd.delete(0, END) self.txt_passwd.delete(0, END) self.txt_passwd_conf.delete(0, END) self.lbl_old_passwd.grid_forget() self.lbl_passwd.grid_forget() self.lbl_passwd_conf.grid_forget() self.txt_old_passwd.grid_forget() self.txt_passwd.grid_forget() self.txt_passwd_conf.grid_forget()
class FormParentDesigner: def __init__(self, window, connection, current_designer): self.connection = connection self.current_designer = current_designer self.frm_parent = LabelFrame(window) self.tlevel_auth_scenario = Toplevel(window) self.tlevel_auth_scenario.protocol("WM_DELETE_WINDOW", self.click_authenticate_cancel) self.tlevel_auth_scenario.withdraw() self.frm_general = LabelFrame(window) self.tlevel_image_exp = Toplevel(window) self.tlevel_image_exp.title('Diagram') self.tlevel_image_exp.protocol("WM_DELETE_WINDOW", self.close_tlevel_image) self.tlevel_image_exp.withdraw() self.initialize_components() def initialize_components(self): # Resources for the Forms self.new_icon = PhotoImage(file=r"./Resources/create.png") self.modify_icon = PhotoImage(file=r"./Resources/modify.png") self.remove_icon = PhotoImage(file=r"./Resources/delete.png") self.save_icon = PhotoImage(file=r"./Resources/save.png") self.cancel_icon = PhotoImage(file=r"./Resources/cancel.png") self.add_icon = PhotoImage(file=r"./Resources/down_arrow.png") self.delete_icon = PhotoImage(file=r"./Resources/up_arrow.png") self.next_icon = PhotoImage(file=r"./Resources/next.png") self.back_icon = PhotoImage(file=r"./Resources/back.png") self.copy_icon = PhotoImage(file=r"./Resources/copy.png") self.open_icon = PhotoImage(file=r"./Resources/open.png") self.complete_icon = PhotoImage(file=r"./Resources/complete.png") self.incomplete_icon = PhotoImage(file=r"./Resources/incomplete.png") self.optional_icon = PhotoImage(file=r"./Resources/optional.png") self.refresh_icon = PhotoImage(file=r"./Resources/refresh.png") # Initialize visual components for displaying available experiment scenarios lbl_title = Label(self.frm_parent, text='Experiments') lbl_title.config(fg=TEXT_COLOR, font=TITLE_FONT) lbl_title.grid(row=0, column=0, columnspan=9, pady=20, sticky=EW) sep_aux5 = Separator(self.frm_parent, orient=HORIZONTAL) sep_aux5.grid(row=1, column=0, sticky=EW, columnspan=9) lbl_sep1 = Label(self.frm_parent) lbl_sep1.grid(row=2, column=0, padx=10, pady=20, rowspan=2) lbl_experimental_trv = Label(self.frm_parent, text='Select an experiment') lbl_experimental_trv.config(fg=TEXT_COLOR, font=SUBTITLE2_FONT) lbl_experimental_trv.grid(row=2, column=1, pady=20, sticky=W) lbl_sep2 = Label(self.frm_parent) lbl_sep2.grid(row=2, column=3, padx=10, pady=20, rowspan=2) lbl_problem_desc = Label(self.frm_parent, text='Information') lbl_problem_desc.config(fg=TEXT_COLOR, font=SUBTITLE2_FONT) lbl_problem_desc.grid(row=2, column=4, pady=20, sticky=W) lbl_sep3 = Label(self.frm_parent) lbl_sep3.grid(row=2, column=6, padx=10, pady=20, rowspan=2) self.trv_available = Treeview(self.frm_parent, height=11, columns='Title') self.trv_available.heading('#0', text='ID', anchor=CENTER) self.trv_available.heading('#1', text='Title', anchor=CENTER) self.trv_available.column('#0', width=0, minwidth=50, stretch=NO) self.trv_available.column('#1', width=400, minwidth=400, stretch=NO) self.trv_available.bind("<ButtonRelease-1>", self.select_experimental_scenario) self.trv_available.grid(row=3, column=1, sticky=W, pady=20) vsb_trv_av = Scrollbar(self.frm_parent, orient="vertical", command=self.trv_available.yview) vsb_trv_av.grid(row=3, column=2, pady=20, sticky=NS) self.trv_available.configure(yscrollcommand=vsb_trv_av.set) self.txt_scenario_desc = Text(self.frm_parent, height=15, width=40) self.txt_scenario_desc.config(font=TEXT_FONT, bg=DISABLED_COLOR) self.txt_scenario_desc.grid(row=3, column=4, pady=20, sticky=W) vsb_txt_sc = Scrollbar(self.frm_parent, orient="vertical", command=self.txt_scenario_desc.yview) vsb_txt_sc.grid(row=3, column=5, pady=20, sticky=NS) self.txt_scenario_desc.configure(yscrollcommand=vsb_txt_sc.set) sep_aux1 = Separator(self.frm_parent, orient=VERTICAL) sep_aux1.grid(row=2, column=7, sticky=NS, rowspan=2) btn_access = Button(self.frm_parent, image=self.next_icon, command=self.click_enter_scenario) btn_access.grid(row=2, column=8, padx=30, pady=5) btn_access_ttp = CreateToolTip(btn_access, 'Go') btn_refresh = Button(self.frm_parent, image=self.refresh_icon, command=self.retrieve_list) btn_refresh.grid(row=3, column=8, padx=30, pady=5, sticky=N) btn_refresh_ttp = CreateToolTip(btn_refresh, 'Refresh list') # Window dialog to authenticate the selected experimental scenario lbl_access_auth = Label(self.tlevel_auth_scenario, text='Insert access code: ') lbl_access_auth.config(fg=TEXT_COLOR, font=SUBTITLE2_FONT) lbl_access_auth.grid(pady=10, padx=20, sticky=W) self.txt_auth_scenario = Entry(self.tlevel_auth_scenario, width=50) self.txt_auth_scenario.config(font=SUBTITLE2_FONT, show="*") self.txt_auth_scenario.grid(row=0, column=1, padx=20, pady=10, sticky=W) btn_access_auth = Button(self.tlevel_auth_scenario, image=self.next_icon, command=self.click_authenticate_scenario) btn_access_auth.grid(row=0, column=2, padx=20, pady=10, sticky=W) btn_access_auth_ttp = CreateToolTip(btn_access_auth, 'Go') btn_cancel_auth = Button(self.tlevel_auth_scenario, image=self.cancel_icon, command=self.click_authenticate_cancel) btn_cancel_auth.grid(row=1, column=2, padx=20, pady=10, sticky=W) btn_cancel_auth_ttp = CreateToolTip(btn_cancel_auth, 'Cancel') # Experiment form lbl_sep4 = Label(self.frm_general) lbl_sep4.grid(row=0, column=0, padx=10, pady=5, rowspan=2) self.lbl_exp_title = Label(self.frm_general, text='Experiment: {}') self.lbl_exp_title.config(fg=TEXT_COLOR, font=TITLE_FONT) self.lbl_exp_title.grid(row=0, column=1, columnspan=5, pady=5, sticky=EW) self.txt_exp_desc = Text(self.frm_general, height=4, width=157) self.txt_exp_desc.config(font=TEXT_FONT, bg=DISABLED_COLOR) self.txt_exp_desc.grid(row=1, column=1, pady=5, sticky=W) vsb_txt_expd = Scrollbar(self.frm_general, orient="vertical", command=self.txt_exp_desc.yview) vsb_txt_expd.grid(row=1, column=2, pady=5, sticky=NS) self.txt_exp_desc.configure(yscrollcommand=vsb_txt_expd.set) lbl_sep11 = Label(self.frm_general) lbl_sep11.grid(row=1, column=3, padx=10, pady=5) self.btn_view_dd = Button(self.frm_general, text='View >>\ndiagram', command=self.click_expand_dd) btn_view_dd_ttp = CreateToolTip(self.btn_view_dd, 'Experiment description diagram') sep_aux3 = Separator(self.frm_general, orient=HORIZONTAL) sep_aux3.grid(row=2, column=0, sticky=EW, columnspan=6) lbl_sep5 = Label(self.frm_general) lbl_sep5.grid(row=3, column=0, padx=10, pady=5, rowspan=2) self.lbl_prob_title = Label(self.frm_general, text='Problem {} of {}: {}') self.lbl_prob_title.config(fg=TEXT_COLOR, font=SUBTITLE_FONT) self.lbl_prob_title.grid(row=3, column=1, columnspan=2, pady=5, sticky=W) self.txt_prob_desc = Text(self.frm_general, height=7, width=157) self.txt_prob_desc.config(font=TEXT_FONT, bg=DISABLED_COLOR) self.txt_prob_desc.grid(row=4, column=1, pady=5, sticky=W) vsb_txt_probd = Scrollbar(self.frm_general, orient="vertical", command=self.txt_prob_desc.yview) vsb_txt_probd.grid(row=4, column=2, pady=5, sticky=NS) self.txt_prob_desc.configure(yscrollcommand=vsb_txt_probd.set) lbl_sep12 = Label(self.frm_general) lbl_sep12.grid(row=3, column=3, padx=10, pady=5, rowspan=2) sep_aux2 = Separator(self.frm_general, orient=HORIZONTAL) sep_aux2.grid(row=5, column=0, sticky=EW, columnspan=4) lbl_sep6 = Label(self.frm_general) lbl_sep6.grid(row=6, column=0, padx=10, pady=5, rowspan=2) lbl_solution_title = Label(self.frm_general, text='Your solution') lbl_solution_title.config(fg=TEXT_COLOR, font=SUBTITLE_FONT) lbl_solution_title.grid(row=6, column=1, pady=5, columnspan=2, sticky=W) self.btn_next_scenario = Button(self.frm_general, image=self.next_icon, command=self.click_next_scenario) self.btn_next_scenario.grid(row=3, column=5, padx=30, pady=5, sticky=W) btn_next_scenario_ttp = CreateToolTip(self.btn_next_scenario, 'Next component') sep_aux4 = Separator(self.frm_general, orient=VERTICAL) sep_aux4.grid(row=3, column=4, sticky=NS, rowspan=5) self.tab_control = Notebook(self.frm_general) self.tab_patterns = Frame(self.tab_control) self.tab_control.add(self.tab_patterns, text="Design patterns", padding=10, image=self.incomplete_icon, compound=RIGHT) lbl_av_patterns = Label(self.tab_patterns, text='Patterns browser') lbl_av_patterns.config(fg=TEXT_COLOR, font=SUBTITLE2_FONT) lbl_av_patterns.grid(row=0, column=1, pady=10, columnspan=6, sticky=W) lbl_content = Label(self.tab_patterns, text='Pattern content') lbl_content.config(fg=TEXT_COLOR, font=SUBTITLE2_FONT) lbl_content.grid(row=0, column=8, pady=10, sticky=W) lbl_sel_patterns = Label(self.tab_patterns, text='Selected patterns') lbl_sel_patterns.config(fg=TEXT_COLOR, font=SUBTITLE2_FONT) lbl_sel_patterns.grid(row=3, column=1, pady=10, columnspan=6, sticky=W) lbl_sep7 = Label(self.tab_patterns) lbl_sep7.grid(row=0, column=0, padx=10, pady=10, rowspan=5) self.lbx_av_patterns = Listbox(self.tab_patterns, height=6, width=60, exportselection=0) self.lbx_av_patterns.grid(row=1, column=1, sticky=W, columnspan=5) self.lbx_av_patterns.bind('<<ListboxSelect>>', self.select_available_pattern) vsb_trv_avpat = Scrollbar(self.tab_patterns, orient="vertical", command=self.lbx_av_patterns.yview) vsb_trv_avpat.grid(row=1, column=6, pady=10, sticky=NS) self.lbx_av_patterns.configure(yscrollcommand=vsb_trv_avpat.set) lbl_sep8 = Label(self.tab_patterns) lbl_sep8.grid(row=0, column=7, padx=10, pady=10, rowspan=5) self.btn_view_pd = Button(self.tab_patterns, text='View diagram >>', command=self.click_expand_pd) btn_view_pd_ttp = CreateToolTip(self.btn_view_pd, 'Pattern section diagram') self.txt_pattern_content = Text(self.tab_patterns, height=18, width=85) self.txt_pattern_content.config(font=TEXT_FONT, bg=DISABLED_COLOR) self.txt_pattern_content.tag_configure("center", justify='center') self.txt_pattern_content.tag_add("center", 1.0, "end") self.txt_pattern_content.grid(row=1, column=8, sticky=W, columnspan=2, rowspan=4) vsb_txt_content = Scrollbar(self.tab_patterns, orient="vertical", command=self.txt_pattern_content.yview) vsb_txt_content.grid(row=1, column=10, rowspan=4, pady=10, sticky=NS) self.txt_pattern_content.configure(yscrollcommand=vsb_txt_content.set) btn_add = Button(self.tab_patterns, image=self.add_icon, command=self.click_add_patt) btn_add.grid(row=2, column=3, pady=10, sticky=E) btn_add_ttp = CreateToolTip(btn_add, 'Add pattern') btn_remove = Button(self.tab_patterns, image=self.delete_icon, command=self.click_remove_patt) btn_remove.grid(row=2, column=4, pady=10) btn_remove_ttp = CreateToolTip(btn_remove, 'Remove pattern') self.lbx_sel_patterns = Listbox(self.tab_patterns, height=6, width=60, exportselection=0) self.lbx_sel_patterns.grid(row=4, column=1, sticky=W, columnspan=5) vsb_trv_selpat = Scrollbar(self.tab_patterns, orient="vertical", command=self.lbx_sel_patterns.yview) vsb_trv_selpat.grid(row=4, column=6, pady=10, sticky=NS) self.lbx_sel_patterns.configure(yscrollcommand=vsb_trv_selpat.set) lbl_sep9 = Label(self.tab_patterns) lbl_sep9.grid(row=0, column=11, padx=10, pady=10, rowspan=5) self.tab_desc = Frame(self.tab_control) self.tab_control.add(self.tab_desc, text="Notes", padding=10, image=self.incomplete_icon, compound=RIGHT) lbl_sep10 = Label(self.tab_desc) lbl_sep10.grid(row=0, column=0, padx=10, pady=20) self.txt_solution_desc = Text(self.tab_desc, height=20, width=145) self.txt_solution_desc.config(font=TEXT_FONT) self.txt_solution_desc.bind("<Key>", self.txt_notes_modified) self.txt_solution_desc.grid(row=0, column=1, pady=20, sticky=W) vsb_txt_solution_desc = Scrollbar(self.tab_desc, orient="vertical", command=self.txt_solution_desc.yview) vsb_txt_solution_desc.grid(row=0, column=2, pady=20, sticky=NS) self.txt_solution_desc.configure(yscrollcommand=vsb_txt_solution_desc.set) lbl_sep14 = Label(self.tab_desc) lbl_sep14.grid(row=0, column=3, padx=10, pady=20) self.tab_file = Frame(self.tab_control) self.tab_control.add(self.tab_file, text="File", padding=1, image=self.optional_icon, compound=RIGHT) lbl_upload = Label(self.tab_file, text='Attach a file to the solution: ') lbl_upload.config(fg=TEXT_COLOR, font=SUBTITLE2_FONT) lbl_upload.grid(row=0, column=0, padx=20, pady=20, sticky=W) btn_open = Button(self.tab_file, image=self.open_icon, command=self.click_attach_file) btn_open.grid(row=1, column=0, padx=20, pady=10, sticky=E) btn_open_ttp = CreateToolTip(btn_open, 'Attach file') btn_quit = Button(self.tab_file, image=self.remove_icon, command=self.click_remove_file) btn_quit.grid(row=2, column=0, padx=20, pady=10, sticky=E) btn_quit_ttp = CreateToolTip(btn_quit, 'Remove file') self.canvas_solution = Canvas(self.tab_file, width=350, height=350) self.canvas_solution.config(background='white', borderwidth=1) self.canvas_solution.grid(row=0, column=1, padx=10, pady=10, rowspan=10, sticky=NS) self.tab_control.grid(row=7, column=1, pady=10, sticky=W, columnspan=2) self.canvas_expanded = Canvas(self.tlevel_image_exp, width=500, height=500) self.canvas_expanded.config(background='white', borderwidth=1) self.canvas_expanded.grid() def show_frm(self): self.retrieve_list() self.frm_parent.grid(row=0, column=0, columnspan=9, rowspan=9, pady=10, padx=10) def hide_frm(self): self.frm_parent.grid_forget() self.frm_general.grid_forget() def retrieve_list(self): """ This function shows the existing 'Experimental scenarios for the specified designer' in the home TreeView, if not 'Experimental scenario' then an information box is showed """ # Remove existing elements in the list for item in self.trv_available.get_children(): self.trv_available.delete(item) # Retrieve scenario for current designer self.directive = Message(action=82, information=['my scenarios', self.current_designer.id]) self.connection = self.directive.send_directive(self.connection) # Set visual components with retrieved scenarios for item in self.connection.message.information: elements = item.split('¥') self.trv_available.insert('', 'end', text=elements[0], values=(summarize_text(elements[1], 400),)) if len(self.trv_available.get_children()) != 0: self.trv_available.selection_set(self.trv_available.get_children()[0]) self.select_experimental_scenario() else: self.txt_scenario_desc['state'] = NORMAL self.txt_scenario_desc.delete('1.0', 'end-1c') self.txt_scenario_desc.insert('1.0', 'No experiments available for you') self.txt_scenario_desc['state'] = DISABLED def select_experimental_scenario(self, event=None): """ Retrieves information of the selected experimental scenario form the server and saves in a local variable for future usage, also shows the description of the selected experimental scenario in a textbox """ if self.trv_available.item(self.trv_available.selection())['text'] != '': id_selected_ex_scenario = int(self.trv_available.item(self.trv_available.selection())['text']) # Retrieve id of selected item from TreeView self.directive = Message(action=85, information=[id_selected_ex_scenario]) self.connection = self.directive.send_directive(self.connection) self.experimental_scenario = ExperimentalSC(id=id_selected_ex_scenario, title=self.connection.message.information[0], description=self.connection.message.information[1], access_code=self.connection.message.information[2], state=self.connection.message.information[3], availability=self.connection.message.information[4], id_experiment=self.connection.message.information[6], id_description_diagram=self.connection.message.information[5], connection=self.connection) if self.experimental_scenario.description_diagram is not None: self.file_dd = self.experimental_scenario.description_diagram else: self.file_dd = None # Insert description of the current scenario into visual component self.txt_scenario_desc['state'] = NORMAL self.txt_scenario_desc.delete('1.0', 'end-1c') self.txt_scenario_desc.insert('1.0', self.experimental_scenario.description) self.txt_scenario_desc['state'] = DISABLED def click_enter_scenario(self): """ Shows pop-up window that allows validation of access code for the experimental scenario (necessary before showing the problems of the experimental scenario) """ if self.trv_available.item(self.trv_available.selection())['text'] != '': self.tlevel_auth_scenario.title('Need to authenticate') self.tlevel_auth_scenario.deiconify() self.tlevel_auth_scenario.grab_set() self.txt_auth_scenario.focus_set() def click_authenticate_scenario(self): """ If validation process is correct the the experimental scenario and it's problems are loaded into the visual components """ if self.validate_access_code(): self.load_experiment() self.txt_auth_scenario.delete(0, END) self.tlevel_auth_scenario.grab_release() self.tlevel_auth_scenario.withdraw() self.frm_parent.grid_forget() self.frm_general.grid(row=0, column=0, columnspan=9, rowspan=9, pady=10, padx=10) else: messagebox.showerror(parent=self.tlevel_auth_scenario, title='Wrong access code', message='The access code you provided is wrong, retry') def initialize_component_variables(self): """ Initialize to zero or empty state all variables associated with the resolution of a problem for the designers (solutions and measurements) """ self.attached_file = None self.av_patterns_seen = [] self.solution_time = 0 self.selection_time = [] # Time for selecting solution patterns (may be more than one solution pattern) self.selected_pattern_sol = [] # Indicates that any pattern solution has been selected yet def click_authenticate_cancel(self): """ Cancel validation of access code for an experimental scenario, it hides the validation pop-up window """ self.txt_auth_scenario.delete(0, END) self.tlevel_auth_scenario.grab_release() self.tlevel_auth_scenario.withdraw() def validate_access_code(self): """ Verifies that the provided code matches the stored access code for the selected experimental scenario """ if len(self.txt_auth_scenario.get()) != 0: if self.txt_auth_scenario.get() == self.experimental_scenario.access_code: return True return False def click_next_scenario(self): """ After clicking next scenario component. This method prompts the user to confirm his decision. After confirming the system saves the important information (solutions and measurements) and then continue to the next scenario component if available, otherwise the experiment will be closed """ decision = messagebox.askyesno(parent=self.frm_general, title='Confirmation', message="Are you sure you want to continue? Yo won't be able to make any change " "later") if decision: # Confirmation of action if self.save_changes(): self.problems_counter += 1 if self.problems_counter == len(self.experimental_scenario.problems): # If no more problems available messagebox.showinfo(parent=self.frm_general, title='Experiment', message="This concludes the execution of the experiment. Thank you!") self.finish_experiment() self.clear_visual_components() self.hide_frm() self.show_frm() else: # If another scenario component available messagebox.showinfo(parent=self.frm_general, title='Next problem', message="You are about to start a new problem, press Ok when you are ready.") self.clear_visual_components() self.initialize_component_variables() self.load_problem() def save_changes(self): # Validate any problem with info inserted into visual components if self.validate_component_frm(): # No problem, proceed to save info self.solution_time += self.time_thread.seconds self.time_thread.stop() # Stop thread timer acquisition_end_date = datetime.now() # Get measurements of important metrics for the current component problem_id = self.experimental_scenario.problems[self.problems_counter].id current_measurements = [] # Solution time measurement_1 = Measurement(value=float(self.solution_time), acquisition_start_date=self.acquisition_start_date, acquisition_end_date=acquisition_end_date, id_metric=1, id_designer=self.current_designer.id, id_problem=problem_id) current_measurements.append(measurement_1) # Save measurements associated with patterns only when these are available for designer if self.pattern_decision: # Selection time # Getting average if more than one value for this metric selection_time = 0 if len(self.selection_time) == 0 else sum(self.selection_time) / len(self.selection_time) measurement_2 = Measurement(value=float(selection_time), acquisition_start_date=self.acquisition_start_date, acquisition_end_date=acquisition_end_date, id_metric=2, id_designer=self.current_designer.id, id_problem=problem_id) current_measurements.append(measurement_2) # Viewed patterns measurement_3 = Measurement(value=float(len(self.av_patterns_seen)), acquisition_start_date=self.acquisition_start_date, acquisition_end_date=acquisition_end_date, id_metric=3, id_designer=self.current_designer.id, id_problem=problem_id) current_measurements.append(measurement_3) # Chosen patterns measurement_4 = Measurement(value=float(self.lbx_sel_patterns.size()), acquisition_start_date=self.acquisition_start_date, acquisition_end_date=acquisition_end_date, id_metric=4, id_designer=self.current_designer.id, id_problem=problem_id) current_measurements.append(measurement_4) for item in current_measurements: self.directive = Message(action=96, information=[item.value, item.acquisition_start_date, item.acquisition_end_date, item.id_metric, item.id_designer, item.id_problem]) self.connection = self.directive.send_directive(self.connection) # Get info and build the solution to send to the server # Create diagram in DB id_diagram = None if self.attached_file is not None: self.directive = Message(action=61, information=[self.attached_file.file_bytes, self.attached_file.name, 'sent sol']) self.connection = self.directive.send_directive(self.connection) id_diagram = self.connection.message.information[0] # Create object for the solution solution_aux = Solution(annotations=self.txt_solution_desc.get('1.0', 'end-1c'), diagram_id=id_diagram, patterns_id=self.sel_patterns_ids) # Create the solution in DB self.directive = Message(action=101, information=[solution_aux.annotations, solution_aux.diagram_id, self.current_designer.id, problem_id, solution_aux.patterns_id]) self.connection = self.directive.send_directive(self.connection) return True return False def finish_experiment(self): """ This section checks in the server if current designer is the last of the current experimental scenario, and if True changes it's state to finished, otherwise the state remains in executed """ self.directive = Message(action=83, information=['finished', self.experimental_scenario.id]) self.connection = self.directive.send_directive(self.connection) def validate_component_frm(self): if self.pattern_decision: if self.lbx_sel_patterns.size() == 0: messagebox.showwarning(parent=self.frm_general, title='Missing information', message="You haven't selected any pattern") return False if len(self.txt_solution_desc.get('1.0', 'end-1c')) == 0: messagebox.showwarning(parent=self.frm_general, title='Missing information', message='You must add notes to your solution') return False return True def click_attach_file(self): """ Create a File object that is uploaded by the user, validating that there is not a file uploaded already. """ if self.attached_file is None: filename = filedialog.askopenfilename(initialdir=os.getcwd(), title="Select image file", filetypes=[("Diagrams", ".jpg .png .tiff")]) if not filename: return # user cancelled; stop this method self.attached_file = File() self.attached_file.read_file(filename) # Display image into canvas load = Image.open(self.attached_file.filename) load = load.resize((350, 350), Image.ANTIALIAS) self.render = ImageTk.PhotoImage(load) if self.attached_file.image is not None: # if an image was already loaded self.canvas_solution.delete(self.attached_file.image) # remove the previous image self.attached_file.image = self.canvas_solution.create_image(0, 0, anchor='nw', image=self.render) def click_remove_file(self): """ Remove an uploaded file from the system validating it is already uploaded. This method also delete any image in the canvas that may be fulfilled with an image. """ if self.attached_file is not None: # if an image was already loaded self.canvas_solution.delete(self.attached_file.image) self.attached_file = None def click_add_patt(self): """ Adds a pattern to the selected pattern listbox (when available to the designer). """ element = self.lbx_av_patterns.curselection() if element is not None: # Check if listbox is selected index = element[0] id_selected = self.av_patterns_ids[index] if not id_selected in self.sel_patterns_ids: # Check if current pattern_id is not in the 'selected patterns list' if id_selected in self.current_ideal_patterns and not id_selected in self.selected_pattern_sol: # Check if selected pattern matches ideal patterns and for the first time self.selected_pattern_sol.append(id_selected) self.selection_time.append(self.time_thread.seconds) for item in self.available_patterns: if item.id == id_selected: # Find selected pattern in available patterns list self.selected_pattern = item break self.sel_patterns_ids.append(id_selected) # Append pattern_id to selected patterns ids self.lbx_sel_patterns.insert(END, self.selected_pattern.get_joined_main_s()) # Insert pattern name into selected listbox patters self.check_selected_patterns() def click_remove_patt(self): """ Removes a pattern from the selected pattern listbox (when available to the designer). """ element = self.lbx_sel_patterns.curselection() if element is not None: # Check if listbox is selected if element: index = element[0] id_selected = self.sel_patterns_ids[index] self.lbx_sel_patterns.delete(element) # Remove from listbox if id_selected in self.current_ideal_patterns and id_selected in self.selected_pattern_sol: # Check if selected pattern matches ideal patterns and if the the selected pattern correspond to the one selected previously as the pattern solution del self.selection_time[self.selected_pattern_sol.index(id_selected)] self.selected_pattern_sol.remove(id_selected) for item in reversed(self.sel_patterns_ids): if item == id_selected: self.sel_patterns_ids.remove(item) break self.check_selected_patterns() def click_expand_pd(self): # Fill canvas with retrieved image load = Image.open(self.file_pd.filename) load = load.resize((500, 500), Image.ANTIALIAS) self.render_pd = ImageTk.PhotoImage(load) self.canvas_expanded.delete() self.file_pd.image = self.canvas_expanded.create_image(0, 0, anchor='nw', image=self.render_pd) # and display new image self.tlevel_image_exp.deiconify() self.tlevel_image_exp.grab_set() def click_expand_dd(self): # Fill canvas with retrieved image load = Image.open(self.file_dd.filename) load = load.resize((500, 500), Image.ANTIALIAS) self.render_dd = ImageTk.PhotoImage(load) self.canvas_expanded.delete() self.file_dd.image = self.canvas_expanded.create_image(0, 0, anchor='nw', image=self.render_dd) # and display new image self.tlevel_image_exp.deiconify() self.tlevel_image_exp.grab_set() def close_tlevel_image(self): self.tlevel_image_exp.grab_release() self.tlevel_image_exp.withdraw() def clear_visual_components(self): self.txt_prob_desc['state'] = NORMAL self.txt_prob_desc.delete('1.0', 'end-1c') self.lbx_av_patterns.delete(0, END) self.lbx_sel_patterns.delete(0, END) self.txt_pattern_content['state'] = NORMAL self.txt_pattern_content.delete('1.0', 'end-1c') self.txt_pattern_content['state'] = DISABLED self.txt_solution_desc.delete('1.0', 'end-1c') if self.attached_file is not None: # if an image was already loaded self.canvas_solution.delete(self.attached_file.image) self.attached_file = None self.tab_control.tab(0, image=self.incomplete_icon) self.tab_control.tab(1, image=self.incomplete_icon) def load_experiment(self): # Retrieve all information of problems of current scenario self.experimental_scenario.retrieve_problems(Pattern.get_available_patterns(self.connection)) self.initialize_component_variables() self.problems_counter = 0 self.current_designer.get_current_role( self.experimental_scenario.id) # Get role for current experimental scenario # Retrieve patterns for designer in current experimental scenario self.directive = Message(action=42, information=[self.experimental_scenario.id, 1 if self.current_designer.current_group == 'experimental' else 2]) self.connection = self.directive.send_directive(self.connection) self.available_patterns = Pattern.get_patterns(self.connection, self.connection.message.information) # Make patterns visible if the patterns are available for current designer in current experimental scenario if self.available_patterns: self.tab_control.tab(0, state='normal') self.tab_control.select(0) self.pattern_decision = True else: self.tab_control.tab(0, state='hidden') self.tab_control.select(1) self.pattern_decision = False self.btn_view_dd.grid_forget() if self.experimental_scenario.description_diagram is not None: self.btn_view_dd.grid(row=1, column=5, padx=10, pady=10, sticky=N) self.lbl_exp_title['text'] = 'Experiment: {}'.format(self.experimental_scenario.title) self.txt_exp_desc['state'] = NORMAL self.txt_exp_desc.delete('1.0', 'end-1c') self.txt_exp_desc.insert('1.0', self.experimental_scenario.description) self.txt_exp_desc['state'] = DISABLED self.load_problem() def load_problem(self): # Ask for available patterns in current problem for the current designer, depending of the role self.lbl_prob_title['text'] = 'Problem {} of {}: {}'.format(self.problems_counter + 1, len(self.experimental_scenario.problems), self.experimental_scenario.problems[self.problems_counter].brief_description) self.txt_prob_desc['state'] = NORMAL self.txt_prob_desc.delete('1.0', 'end-1c') self.txt_prob_desc.insert('1.0', self.experimental_scenario.problems[self.problems_counter].description) self.txt_prob_desc['state'] = DISABLED self.av_patterns_ids = [] self.sel_patterns_ids = [] for item in self.available_patterns: self.av_patterns_ids.append(item.id) self.lbx_av_patterns.insert(END, item.get_joined_main_s()) self.current_ideal_patterns = self.experimental_scenario.problems[self.problems_counter].solution.patterns_id # Get the patterns of the ideal solution for current problem # Make patterns visible if the patterns are available for current designer in current experimental scenario if self.pattern_decision: self.tab_control.select(0) else: self.tab_control.select(1) self.btn_view_pd.grid_forget() self.time_thread = TimerClass() self.time_thread.begin() self.acquisition_start_date = datetime.now() def select_available_pattern(self, event): id_selected = self.av_patterns_ids[self.lbx_av_patterns.curselection()[0]] # Add selected pattern to the seen pattern (metric) if not id_selected in self.av_patterns_seen: self.av_patterns_seen.append(id_selected) # Retrieve info of the selected pattern (in available patterns list) for item in self.available_patterns: if item.id == id_selected: self.selected_pattern = item break # Set visual components depending on the selected pattern and its info self.btn_view_pd.grid_forget() self.txt_pattern_content['state'] = NORMAL self.txt_pattern_content.delete('1.0', 'end-1c') for item in self.selected_pattern.sections: self.txt_pattern_content.insert('end-1c', item.name + ": ") if item.data_type == 'File': # The section content is a file if item.diagram_id != 0: self.directive = Message(action=65, information=[item.diagram_id]) self.connection = self.directive.send_directive(self.connection) self.file_pd = File() self.file_pd.write_file(self.connection.message.information[0], self.connection.message.information[1]) self.btn_view_pd.grid(row=0, column=9, sticky=E) self.txt_pattern_content.insert('end-1c', "\nClick up button to see diagram ^\n\n") else: self.file_pd = None self.txt_pattern_content.insert('end-1c', "\nNo diagram loaded for this section\n\n") else: self.txt_pattern_content.insert('end-1c', "\n" + item.content + "\n\n") self.txt_pattern_content['state'] = DISABLED def txt_notes_modified(self, event): """ Method that checks if text box of additional notes (solution) is filled or not, so tab image is selected """ if self.txt_solution_desc.get('1.0', 'end-1c') != '': self.tab_control.tab(1, image=self.complete_icon) else: self.tab_control.tab(1, image=self.incomplete_icon) def check_selected_patterns(self): """ Method that checks if list box of selected patterns (solution) is filled or not, so tab image is selected """ if self.lbx_sel_patterns.size() != 0: self.tab_control.tab(0, image=self.complete_icon) else: self.tab_control.tab(0, image=self.incomplete_icon)
class FormChildSection: def __init__(self, frm_parent, connection): self.connection = connection self.directive = Message() self.decide = True self.id_selected = 0 self.frm_child_list = LabelFrame(frm_parent) self.frm_child_crud = LabelFrame(frm_parent) self.frm_child_crud.config(fg=TEXT_COLOR, font=SUBTITLE_FONT) self.initialize_components() def initialize_components(self): """ Method that initialize the visual components for each form associated with the local administration """ # Resources for the Forms self.new_icon = PhotoImage(file=r"./Resources/create.png") self.view_icon = PhotoImage(file=r"./Resources/view.png") self.modify_icon = PhotoImage(file=r"./Resources/modify.png") self.remove_icon = PhotoImage(file=r"./Resources/delete.png") self.save_icon = PhotoImage(file=r"./Resources/save.png") self.cancel_icon = PhotoImage(file=r"./Resources/cancel.png") self.back_icon = PhotoImage(file=r"./Resources/back.png") # Components for List FRM lbl_sep1 = Label(self.frm_child_list) lbl_sep1.grid(row=0, column=0, padx=10, pady=25) self.trv_available = Treeview(self.frm_child_list, height=15, columns=('N', 'Name', 'Description', 'Data Type')) self.trv_available.heading('#0', text='ID', anchor=CENTER) self.trv_available.heading('#1', text='N', anchor=CENTER) self.trv_available.heading('#2', text='Name', anchor=CENTER) self.trv_available.heading('#3', text='Description', anchor=CENTER) self.trv_available.heading('#4', text='Data Type', anchor=CENTER) self.trv_available.column('#0', width=0, minwidth=50, stretch=NO) self.trv_available.column('#1', width=20, minwidth=20, stretch=NO) self.trv_available.column('#2', width=200, minwidth=200, stretch=NO) self.trv_available.column('#3', width=400, minwidth=400, stretch=NO) self.trv_available.column('#4', width=200, minwidth=200, stretch=NO) self.trv_available.grid(row=0, column=1, sticky=W, pady=25) vsb_trv_av = Scrollbar(self.frm_child_list, orient="vertical", command=self.trv_available.yview) vsb_trv_av.grid(row=0, column=2, pady=25, sticky=NS) self.trv_available.configure(yscrollcommand=vsb_trv_av.set) frm_aux4 = Frame(self.frm_child_list) btn_new = Button(frm_aux4, image=self.new_icon, command=self.click_new) btn_new.grid(row=0, column=0, pady=5, padx=5, sticky=E) btn_new_ttp = CreateToolTip(btn_new, 'New section') btn_view = Button(frm_aux4, image=self.view_icon, command=self.click_view) btn_view.grid(row=1, column=0, pady=5, padx=5, sticky=E) btn_view_ttp = CreateToolTip(btn_view, 'View section') btn_edit = Button(frm_aux4, image=self.modify_icon, command=self.click_update) btn_edit.grid(row=2, column=0, pady=5, padx=5, sticky=E) btn_edit_ttp = CreateToolTip(btn_edit, 'Edit section') btn_delete = Button(frm_aux4, image=self.remove_icon, command=self.click_delete) btn_delete.grid(row=3, column=0, pady=5, padx=5, sticky=E) btn_delete_ttp = CreateToolTip(btn_delete, 'Delete section') frm_aux4.grid(row=0, column=4, pady=25, padx=25, sticky=NW) # Components for CRUD FRM self.frm_aux1 = Frame(self.frm_child_crud) lbl_type = Label(self.frm_aux1, text='Data type*') lbl_type.config(fg=TEXT_COLOR, font=LABEL_FONT) lbl_type.grid(row=0, column=0, pady=10, padx=20, sticky=W) lbl_name = Label(self.frm_aux1, text='Name*') lbl_name.config(fg=TEXT_COLOR, font=LABEL_FONT) lbl_name.grid(row=1, column=0, pady=10, padx=20, sticky=W) lbl_description = Label(self.frm_aux1, text='Description*\t') lbl_description.config(fg=TEXT_COLOR, font=LABEL_FONT) lbl_description.grid(row=2, column=0, pady=10, padx=20, sticky=NW) self.cbx_data = Combobox(self.frm_aux1, state="readonly") self.cbx_data['values'] = ['Text', 'File', 'Classification'] self.cbx_data.grid(row=0, column=2, pady=10, sticky=W) self.cbx_data.bind("<<ComboboxSelected>>", self.cbx_data_selected) self.txt_name = Entry(self.frm_aux1, width=50, font=TEXT_FONT) self.txt_name.grid(row=1, column=2, pady=10, sticky=W) lbl_sep2 = Label(self.frm_aux1) lbl_sep2.grid(row=0, column=1, rowspan=3, padx=10, pady=10) self.txt_description = Text(self.frm_aux1, height=6, width=50, font=TEXT_FONT) self.txt_description.grid(row=2, column=2, pady=10, sticky=W) vsb_txt_desc = Scrollbar(self.frm_aux1, orient="vertical", command=self.txt_description.yview) vsb_txt_desc.grid(row=2, column=3, pady=10, sticky=NS) self.txt_description.configure(yscrollcommand=vsb_txt_desc.set) sep_aux1 = Separator(self.frm_aux1, orient=VERTICAL) sep_aux1.grid(row=0, column=4, sticky=NS, rowspan=4, padx=20) self.btn_save = Button(self.frm_aux1, image=self.save_icon, command=self.click_save) btn_save_ttp = CreateToolTip(self.btn_save, 'Save section') self.btn_back = Button(self.frm_aux1, image=self.back_icon, command=self.click_back) btn_back_ttp = CreateToolTip(self.btn_back, 'Go back') self.btn_cancel = Button(self.frm_aux1, image=self.cancel_icon, command=self.click_cancel) btn_cancel_ttp = CreateToolTip(self.btn_cancel, 'Cancel') self.frm_aux1.grid() # Frame for showing available classifications self.frm_aux2 = Frame(self.frm_aux1) lbl_class = Label(self.frm_aux2, text='Classification\t') lbl_class.config(fg=TEXT_COLOR, font=LABEL_FONT) lbl_class.grid(row=0, column=0, pady=10, padx=20, sticky=W) lbl_category = Label(self.frm_aux2, text='Categories') lbl_category.config(fg=TEXT_COLOR, font=LABEL_FONT) lbl_category.grid(row=1, column=0, pady=10, padx=20, sticky=NW) lbl_sep3 = Label(self.frm_aux2) lbl_sep3.grid(row=0, column=1, rowspan=2, padx=10, pady=10) self.cbx_classification = Combobox(self.frm_aux2, state="readonly") self.cbx_classification.bind("<<ComboboxSelected>>", self.cbx_class_selected) self.cbx_classification.grid(row=0, column=2, pady=10, sticky=NW) self.lbx_category = Listbox(self.frm_aux2, font=TEXT_FONT, height=10, width=50, selectmode='none') self.lbx_category.config(bg=DISABLED_COLOR) self.lbx_category.grid(row=1, column=2, pady=10, sticky=W) vsb_lbx_cat = Scrollbar(self.frm_aux2, orient="vertical", command=self.lbx_category.yview) vsb_lbx_cat.grid(row=1, column=3, pady=10, sticky=NS) self.lbx_category.configure(yscrollcommand=vsb_lbx_cat.set) def retrieve_list(self): # Remove existing elements in the list for item in self.trv_available.get_children(): self.trv_available.delete(item) self.directive = Message(action=32) self.connection = self.directive.send_directive(self.connection) # Adding elements into the list for index, item in enumerate(self.connection.message.information): elements = item.split('¥') self.trv_available.insert('', 'end', text=elements[0], values=(index + 1, summarize_text(elements[1], 200), summarize_text(elements[2], 400), summarize_text(elements[3], 200))) if len(self.trv_available.get_children()) != 0: self.trv_available.selection_set( self.trv_available.get_children()[0]) def show_frm(self): self.retrieve_list() self.frm_child_list.grid(row=1, column=0, columnspan=9, rowspan=8, pady=10, padx=10) def hide_frm(self): self.clear_fields() self.frm_child_list.grid_forget() self.frm_child_crud.grid_forget() def click_new(self): self.section = Section() self.txt_name.focus_set() self.frm_child_crud['text'] = 'New section' self.btn_save.grid(row=0, column=5, padx=20) self.btn_cancel.grid(row=1, column=5, padx=20) self.frm_child_list.grid_forget() self.frm_child_crud.grid(row=1, column=0, columnspan=9, rowspan=8, pady=10, padx=10) def click_view(self): if len(self.trv_available.selection()) == 1: id_selected = int( self.trv_available.item( self.trv_available.selection())['text']) self.directive = Message(action=35, information=[id_selected]) self.connection = self.directive.send_directive(self.connection) self.section = Section( section_id=id_selected, name=self.connection.message.information[0], description=self.connection.message.information[1], data_type=self.connection.message.information[2]) self.txt_name.insert(0, self.section.name) self.txt_description.insert('1.0', self.section.description) self.cbx_data.set(self.section.data_type) if self.section.data_type == 'Classification': self.section.classification_id = self.connection.message.information[ 3] self.retrieve_classifications() self.directive = Message( action=70, information=[self.section.classification_id]) self.connection = self.directive.send_directive( self.connection) self.cbx_classification.set( self.connection.message.information[0]) self.cbx_class_selected() self.frm_aux2.grid(row=3, column=0, columnspan=4, sticky=W) self.txt_name['bg'] = DISABLED_COLOR self.txt_description['bg'] = DISABLED_COLOR self.lbx_category['bg'] = DISABLED_COLOR self.txt_name['state'] = DISABLED self.txt_description['state'] = DISABLED self.cbx_data['state'] = DISABLED self.cbx_classification['state'] = DISABLED self.lbx_category['state'] = DISABLED self.frm_child_crud['text'] = 'View section' self.btn_back.grid(row=0, column=5, padx=20) self.frm_child_list.grid_forget() self.frm_child_crud.grid(row=1, column=0, columnspan=9, rowspan=8, pady=10, padx=10) else: messagebox.showwarning(parent=self.frm_child_list, title='No selection', message='You must select one item') def click_update(self): if len(self.trv_available.selection()) == 1: id_selected = int( self.trv_available.item( self.trv_available.selection())['text']) self.directive = Message(action=35, information=[id_selected, 'validate']) self.connection = self.directive.send_directive(self.connection) if self.connection.message.action == 5: # An error ocurred while trying to update the item messagebox.showerror( parent=self.frm_child_list, title='Can not update the item', message=self.connection.message.information[0]) else: self.section = Section( section_id=id_selected, name=self.connection.message.information[0], description=self.connection.message.information[1], data_type=self.connection.message.information[2]) self.txt_name.insert(0, self.section.name) self.txt_description.insert('1.0', self.section.description) self.cbx_data.set(self.section.data_type) if self.section.data_type == 'Classification': self.section.classification_id = self.connection.message.information[ 3] self.retrieve_classifications() self.directive = Message( action=70, information=[self.section.classification_id]) self.connection = self.directive.send_directive( self.connection) self.cbx_classification.set( self.connection.message.information[0]) self.cbx_class_selected() self.frm_aux2.grid(row=3, column=0, columnspan=4, sticky=W) self.frm_child_crud['text'] = 'Update section' self.btn_save.grid(row=0, column=5, padx=20) self.btn_cancel.grid(row=1, column=5, padx=20) self.frm_child_list.grid_forget() self.frm_child_crud.grid(row=1, column=0, columnspan=9, rowspan=8, pady=10, padx=10) else: messagebox.showwarning(parent=self.frm_child_list, title='No selection', message='You must select one item') def click_delete(self): if len(self.trv_available.selection()) == 1: decision = messagebox.askyesno( parent=self.frm_child_list, title='Confirmation', message='Are you sure you want to delete the item?') if decision: id_selected = int( self.trv_available.item( self.trv_available.selection())['text']) self.directive = Message(action=34, information=[id_selected]) self.connection = self.directive.send_directive( self.connection) if self.connection.message.action == 5: # An error ocurred while deleting the item messagebox.showerror( parent=self.frm_child_list, title='Can not delete the item', message=self.connection.message.information[0]) else: self.retrieve_list() else: messagebox.showwarning(parent=self.frm_child_list, title='No selection', message='You must select one item') def click_save(self): if self.validate_fields(): self.section.name = self.txt_name.get() self.section.description = self.txt_description.get( '1.0', 'end-1c') self.section.data_type = self.cbx_data.get() if self.section.section_id == 0: # If creating a section if self.section.data_type == 'Classification': id_class = self.classifications[ self.cbx_classification.current()] self.directive = Message(action=31, information=[ self.section.name, self.section.description, self.section.data_type, id_class ]) else: self.directive = Message(action=31, information=[ self.section.name, self.section.description, self.section.data_type ]) else: # If updating a section if self.section.data_type == 'Classification': id_class = self.classifications[ self.cbx_classification.current()] self.directive = Message(action=33, information=[ self.section.section_id, self.section.name, self.section.description, self.section.data_type, id_class ]) else: self.directive = Message(action=33, information=[ self.section.section_id, self.section.name, self.section.description, self.section.data_type ]) self.connection = self.directive.send_directive(self.connection) self.click_back() def click_back(self): self.clear_fields() self.frm_child_crud.grid_forget() self.show_frm() def click_cancel(self): decision = True if self.txt_name.get() != self.section.name or \ self.txt_description.get('1.0', 'end-1c') != self.section.description or \ self.cbx_data.get() != self.section.data_type: decision = messagebox.askyesno( parent=self.frm_child_crud, title='Cancel', message='Are you sure you want to cancel?') if decision: self.click_back() def cbx_data_selected(self, event): if self.cbx_data.get() == 'Classification': self.retrieve_classifications() self.frm_aux2.grid(row=3, column=0, columnspan=4, sticky=W) else: self.frm_aux2.grid_forget() self.txt_name.focus_set() def cbx_class_selected(self, event=None): id_class = self.classifications[self.cbx_classification.current()] self.directive = Message(action=72, information=[id_class]) self.connection = self.directive.send_directive(self.connection) self.lbx_category.delete(0, END) for index, item in enumerate(self.connection.message.information): item = item.split('¥') self.lbx_category.insert(END, '{}) {}'.format(index + 1, item[1])) def retrieve_classifications(self): self.classifications = [] self.lbx_category.delete(0, END) self.directive = Message(action=67) self.connection = self.directive.send_directive(self.connection) classifications = [] for item in self.connection.message.information: elements = item.split('¥') classifications.append(elements[1]) self.classifications.append(int(elements[0])) self.cbx_classification['values'] = [] self.cbx_classification['values'] = classifications def validate_fields(self): if len(self.txt_name.get()) == 0: messagebox.showwarning( parent=self.frm_child_crud, title='Missing information', message='You must insert a name for the section') return False if len(self.txt_description.get('1.0', 'end-1c')) == 0: messagebox.showwarning( parent=self.frm_child_crud, title='Missing information', message='You must insert a description for the section') return False if len(self.cbx_data.get()) == 0: messagebox.showwarning( parent=self.frm_child_crud, title='Missing information', message='You must select data type for the section') return False if self.cbx_data.get() == 'Classification' and len( self.cbx_classification.get()) == 0: messagebox.showwarning( parent=self.frm_child_crud, title='Missing information', message='You must select a classification for this section') return False return True def clear_fields(self): self.btn_save.grid_forget() self.btn_cancel.grid_forget() self.btn_back.grid_forget() self.txt_name['state'] = NORMAL self.txt_description['state'] = NORMAL self.cbx_data['state'] = NORMAL self.cbx_classification['state'] = NORMAL self.lbx_category['state'] = NORMAL self.txt_name['bg'] = ENABLED_COLOR self.txt_description['bg'] = ENABLED_COLOR self.lbx_category['bg'] = ENABLED_COLOR self.txt_name.delete(0, END) self.txt_description.delete('1.0', 'end-1c') self.cbx_data.set('') self.cbx_classification.set('') self.lbx_category.delete(0, END) self.frm_aux2.grid_forget()
class FormChildTemplate: def __init__(self, frm_parent, connection): self.connection = connection self.directive = Message() self.decide_template = True self.id_selected = 0 self.frm_child_list = LabelFrame(frm_parent) self.frm_child_crud = LabelFrame(frm_parent) self.frm_child_crud.config(fg=TEXT_COLOR, font=SUBTITLE_FONT) self.initialize_components() def initialize_components(self): """ Method that initialize the visual components for each form associated with the local administration """ # Resources for the Forms self.new_icon = PhotoImage(file=r"./Resources/create.png") self.modify_icon = PhotoImage(file=r"./Resources/modify.png") self.remove_icon = PhotoImage(file=r"./Resources/delete.png") self.save_icon = PhotoImage(file=r"./Resources/save.png") self.cancel_icon = PhotoImage(file=r"./Resources/cancel.png") self.add_icon = PhotoImage(file=r"./Resources/right.png") self.delete_icon = PhotoImage(file=r"./Resources/left.png") self.up_arrow = PhotoImage(file=r"./Resources/up_arrow.png") self.down_arrow = PhotoImage(file=r"./Resources/down_arrow.png") self.star_icon = PhotoImage(file=r"./Resources/star.png") self.back_icon = PhotoImage(file=r"./Resources/back.png") self.view_icon = PhotoImage(file=r"./Resources/view.png") # Components for List FRM lbl_sep1 = Label(self.frm_child_list) lbl_sep1.grid(row=0, column=0, padx=10, pady=25) self.trv_available = Treeview(self.frm_child_list, height=20, columns=('N', 'Name')) self.trv_available.heading('#0', text='ID', anchor=CENTER) self.trv_available.heading('#1', text='N', anchor=CENTER) self.trv_available.heading('#2', text='Name', anchor=CENTER) self.trv_available.column('#0', width=0, minwidth=50, stretch=NO) self.trv_available.column('#1', width=20, minwidth=20, stretch=NO) self.trv_available.column('#2', width=375, minwidth=375, stretch=NO) self.trv_available.bind("<ButtonRelease-1>", self.select_template_summary) self.trv_available.grid(row=0, column=1, sticky=W, pady=25) vsb_trv_av = Scrollbar(self.frm_child_list, orient="vertical", command=self.trv_available.yview) vsb_trv_av.grid(row=0, column=2, pady=25, sticky=NS) self.trv_available.configure(yscrollcommand=vsb_trv_av.set) frm_aux4 = Frame(self.frm_child_list) btn_new = Button(frm_aux4, image=self.new_icon, command=self.click_new) btn_new.grid(row=0, column=0, pady=5, padx=5, sticky=E) btn_new_ttp = CreateToolTip(btn_new, 'New template') btn_view = Button(frm_aux4, image=self.view_icon, command=self.click_view) btn_view.grid(row=1, column=0, pady=5, padx=5, sticky=E) btn_view_ttp = CreateToolTip(btn_new, 'View template') btn_edit = Button(frm_aux4, image=self.modify_icon, command=self.click_update) btn_edit.grid(row=2, column=0, pady=5, padx=5, sticky=E) btn_edit_ttp = CreateToolTip(btn_edit, 'Edit template') btn_delete = Button(frm_aux4, image=self.remove_icon, command=self.click_delete) btn_delete.grid(row=3, column=0, pady=5, padx=5, sticky=E) btn_delete_ttp = CreateToolTip(btn_delete, 'Delete template') frm_aux4.grid(row=0, column=3, pady=25, padx=25, sticky=NW) sep_template = Separator(self.frm_child_list, orient=VERTICAL) sep_template.grid(row=0, column=4, sticky=NS, padx=25) frm_aux3 = Frame(self.frm_child_list) lbl_sep3 = Label(frm_aux3) lbl_sep3.grid(row=0, column=0, padx=10, pady=25, rowspan=3) lbl_details = Label(frm_aux3, text='Details') lbl_details.config(fg=TEXT_COLOR, font=SUBTITLE_FONT) lbl_details.grid(row=0, column=1, sticky=W, pady=25, columnspan=2) self.txt_summary = Text(frm_aux3, height=22, width=50) self.txt_summary.config(font=TEXT_FONT, bg=DISABLED_COLOR) self.txt_summary.grid(row=1, column=1) vsb_txt_sum = Scrollbar(frm_aux3, orient="vertical", command=self.txt_summary.yview) vsb_txt_sum.grid(row=1, column=2, sticky=NS) self.txt_summary.configure(yscrollcommand=vsb_txt_sum.set) lbl_sep4 = Label(frm_aux3) lbl_sep4.grid(row=0, column=3, padx=10, pady=25, rowspan=3) lbl_sep5 = Label(frm_aux3) lbl_sep5.grid(row=2, column=1, pady=5, columnspan=2) frm_aux3.grid(row=0, column=5) # Components for CRUD FRM lbl_sep6 = Label(self.frm_child_crud) lbl_sep6.grid(row=0, column=0, padx=10, pady=25, rowspan=10) lbl_name = Label(self.frm_child_crud, text='Name*') lbl_name.config(fg=TEXT_COLOR, font=LABEL_FONT) lbl_name.grid(row=0, column=1, pady=25, sticky=NW) lbl_description = Label(self.frm_child_crud, text='Description*') lbl_description.config(fg=TEXT_COLOR, font=LABEL_FONT) lbl_description.grid(row=0, column=6, pady=25, sticky=NW) lbl_sep3 = Label(self.frm_child_crud) lbl_sep3.grid(row=0, column=2, padx=10, pady=25) self.txt_name = Entry(self.frm_child_crud, width=30, font=TEXT_FONT) self.txt_name.grid(row=0, column=3, pady=25, sticky=NW) lbl_sep4 = Label(self.frm_child_crud) lbl_sep4.grid(row=0, column=7, padx=10, pady=25) self.txt_description = Text(self.frm_child_crud, height=5, width=49) self.txt_description.config(font=TEXT_FONT) self.txt_description.grid(row=0, column=8, pady=25, sticky=W) vsb_txt_desc = Scrollbar(self.frm_child_crud, orient="vertical", command=self.txt_description.yview) vsb_txt_desc.grid(row=0, column=9, pady=25, sticky=NS) self.txt_description.configure(yscrollcommand=vsb_txt_desc.set) lbl_sep7 = Label(self.frm_child_crud) lbl_sep7.grid(row=0, column=5, padx=10, pady=25, rowspan=3) lbl_sep8 = Label(self.frm_child_crud) lbl_sep8.grid(row=0, column=10, padx=10, pady=25, rowspan=2) lbl_available_d = Label(self.frm_child_crud, text='Available sections') lbl_available_d.config(fg=TEXT_COLOR, font=LABEL_FONT) lbl_available_d.grid(row=1, column=1, pady=10, sticky=W, columnspan=4) lbl_selected_d = Label(self.frm_child_crud, text='Selected sections*') lbl_selected_d.config(fg=TEXT_COLOR, font=LABEL_FONT) lbl_selected_d.grid(row=1, column=6, pady=10, sticky=W, columnspan=4) self.trv_available_sections = Treeview(self.frm_child_crud, height=10, columns=('N', 'Name', 'Data Type')) self.trv_available_sections.heading('#0', text='ID', anchor=CENTER) self.trv_available_sections.heading('#1', text='N', anchor=CENTER) self.trv_available_sections.heading('#2', text='Name', anchor=CENTER) self.trv_available_sections.heading('#3', text='Data Type', anchor=CENTER) self.trv_available_sections.column('#0', width=0, minwidth=20, stretch=NO) self.trv_available_sections.column('#1', width=20, minwidth=20, stretch=NO) self.trv_available_sections.column('#2', width=150, minwidth=150, stretch=NO) self.trv_available_sections.column('#3', width=120, minwidth=120, stretch=NO) self.trv_available_sections.bind("<Button-1>", self.click_trv_asections) self.trv_available_sections.grid(row=2, column=1, rowspan=7, columnspan=3, sticky=W, pady=10) vsb_trv_avs = Scrollbar(self.frm_child_crud, orient="vertical", command=self.trv_available_sections.yview) vsb_trv_avs.grid(row=2, column=4, rowspan=7, pady=10, sticky=NS) self.trv_available_sections.configure(yscrollcommand=vsb_trv_avs.set) self.trv_selected_sections = Treeview(self.frm_child_crud, height=10, columns=('N', 'Name', 'Data type', 'Mandatory', 'Main')) self.trv_selected_sections.heading('#0', text='ID', anchor=CENTER) self.trv_selected_sections.heading('#1', text='N', anchor=CENTER) self.trv_selected_sections.heading('#2', text='Name', anchor=CENTER) self.trv_selected_sections.heading('#3', text='Data type', anchor=CENTER) self.trv_selected_sections.heading('#4', text='Mandatory', anchor=CENTER) self.trv_selected_sections.heading('#5', text='Main', anchor=CENTER) self.trv_selected_sections.column('#0', width=0, minwidth=20, stretch=NO) self.trv_selected_sections.column('#1', width=20, minwidth=20, stretch=NO) self.trv_selected_sections.column('#2', width=150, minwidth=150, stretch=NO) self.trv_selected_sections.column('#3', width=120, minwidth=120, stretch=NO) self.trv_selected_sections.column('#4', width=80, minwidth=80, stretch=NO) self.trv_selected_sections.column('#5', width=80, minwidth=80, stretch=NO) self.trv_selected_sections.bind("<Button-1>", self.click_trv_ssections) self.trv_selected_sections.bind("<Double-1>", self.click_switch_mandatory) self.trv_selected_sections.grid(row=2, column=6, rowspan=7, columnspan=3, sticky=W, pady=10) vsb_trv_ses = Scrollbar(self.frm_child_crud, orient="vertical", command=self.trv_selected_sections.yview) vsb_trv_ses.grid(row=2, column=9, rowspan=7, pady=10, sticky=NS) self.trv_selected_sections.configure(yscrollcommand=vsb_trv_ses.set) self.lbl_note_optional = Label( self.frm_child_crud, text= 'NOTES:\tTo switch between optional and mandatory, double click ' 'on selected section.\n\tChoose one or up to three main sections ' 'by first selecting the target sections\n\tand then clicking the ' 'star button.\n') self.lbl_note_optional.config(fg=TEXT_COLOR, font=NOTE_FONT, justify=LEFT) self.btn_add = Button(self.frm_child_crud, image=self.add_icon, command=self.click_add) btn_add_ttp = CreateToolTip(self.btn_add, 'Add section') self.btn_remove = Button(self.frm_child_crud, image=self.delete_icon, command=self.click_remove) btn_remove_ttp = CreateToolTip(self.btn_remove, 'Remove section') self.btn_main_section = Button(self.frm_child_crud, image=self.star_icon, command=self.click_main_section) btn_main_section_ttp = CreateToolTip(self.btn_main_section, 'Main section(s)') self.btn_up = Button(self.frm_child_crud, image=self.up_arrow, command=self.click_up) btn_up_ttp = CreateToolTip(self.btn_up, 'Move up') self.btn_down = Button(self.frm_child_crud, image=self.down_arrow, command=self.click_down) btn_down_ttp = CreateToolTip(self.btn_down, 'Move down') sep_aux1 = Separator(self.frm_child_crud, orient=VERTICAL) sep_aux1.grid(row=0, column=11, sticky=NS, rowspan=10) frm_aux1 = Frame(self.frm_child_crud) self.btn_save = Button(frm_aux1, image=self.save_icon, command=self.click_save) btn_save_ttp = CreateToolTip(self.btn_save, 'Save template') self.btn_back = Button(frm_aux1, image=self.back_icon, command=self.click_back) btn_back_ttp = CreateToolTip(self.btn_back, 'Go back') self.btn_cancel = Button(frm_aux1, image=self.cancel_icon, command=self.click_cancel) btn_cancel_ttp = CreateToolTip(self.btn_cancel, 'Cancel') frm_aux1.grid(row=0, column=12, pady=10, padx=25, sticky=NW, rowspan=10) def retrieve_list(self): # Remove existing elements in the list for item in self.trv_available.get_children(): self.trv_available.delete(item) self.directive = Message(action=37) self.connection = self.directive.send_directive(self.connection) # Adding elements into the list for index, item in enumerate(self.connection.message.information): elements = item.split('¥') self.trv_available.insert('', 'end', text=elements[0], values=(index + 1, summarize_text(elements[1], 375))) if len(self.trv_available.get_children()) != 0: self.trv_available.selection_set( self.trv_available.get_children()[0]) self.select_template_summary() def select_template_summary(self, event=None): """ Function activated when the event of selecting an item in the available templates TV is generated. It fills the summary text box with information of the selected template :param event: """ if self.trv_available.item( self.trv_available.selection())['text'] != '': # Clear summary txt box self.txt_summary['state'] = NORMAL self.txt_summary.delete('1.0', 'end-1c') self.id_selected = int( self.trv_available.item(self.trv_available.selection()) ['text']) # Retrieve id of selected item from TreeView self.directive = Message(action=40, information=[self.id_selected ]) # ask for the template self.connection = self.directive.send_directive(self.connection) # Insert template's name and description self.txt_summary.insert( 'end-1c', "Name:\n{}\n\n".format(self.connection.message.information[0])) self.txt_summary.insert( 'end-1c', "Description:\n{}\n\nSections:\n".format( self.connection.message.information[1])) self.directive = Message(action=77, information=[ self.id_selected ]) # ask for the sections of the selected template self.connection = self.directive.send_directive(self.connection) # Adding elements in the summary text box index = 0 for item in self.connection.message.information: elements = item.split('¥') self.txt_summary.insert('end-1c', "{}) {}\t\t{}\t\t{}\n".format(index + 1, elements[3], 'optional' \ if elements[7] == '' else 'mandatory', '' if elements[8] == '' else '(MAIN)')) index += 1 self.txt_summary['state'] = DISABLED def show_frm(self): self.retrieve_list() self.frm_child_list.grid(row=1, column=0, columnspan=9, rowspan=8, pady=10, padx=10) def hide_frm(self): self.clear_fields() self.frm_child_list.grid_forget() self.frm_child_crud.grid_forget() def click_new(self): self.view_decision = False # Decision when viewing a template self.template = Template() self.retrieve_sections() self.txt_name.focus_set() self.show_cu_buttons() self.frm_child_crud['text'] = 'New template' self.frm_child_list.grid_forget() self.frm_child_crud.grid(row=1, column=0, columnspan=9, rowspan=8, pady=10, padx=10) def click_view(self): if len(self.trv_available.selection()) == 1: self.view_decision = True # Decision when viewing a template self.directive = Message(action=40, information=[self.id_selected]) self.connection = self.directive.send_directive(self.connection) self.template = Template( id=self.id_selected, name=self.connection.message.information[0], description=self.connection.message.information[1], sections=self.connection.message.information[2]) self.txt_name.insert(0, self.template.name) self.txt_description.insert('1.0', self.template.description) self.retrieve_sections(self.template.sections) self.txt_name.focus_set() self.disable_visual_components() self.btn_back.grid(row=0, column=0, padx=5, pady=5, sticky=W) self.frm_child_list.grid_forget() self.frm_child_crud['text'] = 'View template' self.frm_child_crud.grid(row=1, column=0, columnspan=9, rowspan=8, pady=10, padx=10) else: messagebox.showwarning(parent=self.frm_child_list, title='No selection', message='You must select one item') def click_update(self): if len(self.trv_available.selection()) == 1: self.view_decision = False # Decision when viewing a template self.directive = Message( action=40, information=[self.id_selected, 'validate']) self.connection = self.directive.send_directive(self.connection) if self.connection.message.action == 5: # An error ocurred while trying to update the item messagebox.showerror( parent=self.frm_child_list, title='Can not edit the template', message=self.connection.message.information[0]) else: self.template = Template( id=self.id_selected, name=self.connection.message.information[0], description=self.connection.message.information[1], sections=self.connection.message.information[2]) self.txt_name.insert(0, self.template.name) self.txt_description.insert('1.0', self.template.description) self.retrieve_sections(self.template.sections) self.txt_name.focus_set() self.show_cu_buttons() self.frm_child_crud['text'] = 'Update template' self.frm_child_list.grid_forget() self.frm_child_crud.grid(row=1, column=0, columnspan=9, rowspan=8, pady=10, padx=10) else: messagebox.showwarning(parent=self.frm_child_list, title='No selection', message='You must select one item') def click_delete(self): if len(self.trv_available.selection()) == 1: decision = messagebox.askyesno( parent=self.frm_child_list, title='Confirmation', message='Are you sure you want to delete the item?') if decision: self.directive = Message(action=39, information=[self.id_selected]) self.connection = self.directive.send_directive( self.connection) if self.connection.message.action == 5: # An error ocurred while deleting the item messagebox.showerror( parent=self.frm_child_list, title='Can not delete the item', message=self.connection.message.information[0]) else: self.retrieve_list() else: messagebox.showwarning(parent=self.frm_child_list, title='No selection', message='You must select one item') def show_cu_buttons(self): self.btn_add.grid(row=5, column=5, padx=25) self.btn_remove.grid(row=6, column=5, padx=25) self.btn_main_section.grid(row=2, column=10, padx=25) self.btn_down.grid(row=6, column=10, padx=25) self.btn_up.grid(row=5, column=10, padx=25) self.btn_save.grid(row=0, column=0, padx=5, pady=5, sticky=W) self.btn_cancel.grid(row=1, column=0, padx=5, pady=5, sticky=W) self.lbl_note_optional.grid(row=9, column=6, columnspan=4, sticky=W) def disable_visual_components(self): self.txt_name['bg'] = DISABLED_COLOR self.txt_description['bg'] = DISABLED_COLOR self.txt_name['state'] = DISABLED self.txt_description['state'] = DISABLED self.btn_add.grid_forget() self.btn_remove.grid_forget() self.btn_main_section.grid_forget() self.btn_down.grid_forget() self.btn_up.grid_forget() def retrieve_sections(self, s_sections=None): if s_sections is None: s_sections = [] self.directive = Message(action=32) self.connection = self.directive.send_directive(self.connection) a_sections = self.connection.message.information for item in self.trv_available_sections.get_children(): self.trv_available_sections.delete(item) for item in self.trv_selected_sections.get_children(): self.trv_selected_sections.delete(item) for item in s_sections: item_aux1 = item.split('¥')[2:6] item_aux2 = [item.split('¥')[-1]] item = item_aux1 + item_aux2 item = '¥'.join(item) if item in a_sections: a_sections.remove(item) for index, item in enumerate(a_sections): elements = item.split('¥') self.trv_available_sections.insert( '', 'end', text=elements[0], values=(index + 1, summarize_text(elements[1], 150), summarize_text(elements[3], 120))) for index, item in enumerate(s_sections): elements = item.split('¥') self.trv_selected_sections.insert( '', 'end', text=elements[2], values=(index + 1, summarize_text(elements[3], 150), summarize_text(elements[5], 120), elements[7], elements[8])) def click_add(self): """ Function that moves a 'Section' from available tree view to selected tree view (in frm_child_crud) """ if len(self.trv_available_sections.selection()) != 0 and len( self.trv_selected_sections.selection()) == 0: if len(self.trv_selected_sections.get_children()) != 0: index = self.trv_selected_sections.item( self.trv_selected_sections.get_children()[-1])['values'][0] else: index = 0 for row in self.trv_available_sections.selection(): index += 1 values = self.trv_available_sections.item(row)['values'] self.trv_selected_sections.insert( '', 'end', text=self.trv_available_sections.item(row)['text'], values=(index, values[1], values[2], '✓', '')) self.trv_available_sections.delete(row) def click_remove(self): """ Function that moves a 'Section' from selected tree view to available tree view (in frm_child_crud) """ if len(self.trv_selected_sections.selection()) != 0 and len( self.trv_available_sections.selection()) == 0: if len(self.trv_available_sections.get_children()) != 0: index = self.trv_available_sections.item( self.trv_available_sections.get_children() [-1])['values'][0] else: index = 0 for row in self.trv_selected_sections.selection(): index += 1 values = self.trv_selected_sections.item(row)['values'] self.trv_available_sections.insert( '', 'end', text=self.trv_selected_sections.item(row)['text'], values=(index, values[1], values[2])) self.trv_selected_sections.delete(row) def click_up(self): # Make sure only one item in 'selected sections' is selected if len(self.trv_selected_sections.selection()) == 1 and len( self.trv_available_sections.selection()) == 0: item = self.trv_selected_sections.selection() index = self.trv_selected_sections.index(item) self.trv_selected_sections.move(item, '', index - 1) def click_down(self): # Make sure only one item in 'selected sections' is selected if len(self.trv_selected_sections.selection()) == 1 and len( self.trv_available_sections.selection()) == 0: item = self.trv_selected_sections.selection() index = self.trv_selected_sections.index(item) self.trv_selected_sections.move(item, '', index + 1) def click_main_section(self): # Make sure a max of three items of 'selected sections' are selected if 4 > len(self.trv_selected_sections.selection()) > 0 and len( self.trv_available_sections.selection()) == 0: # First change all sections as normal (not main) for item in self.trv_selected_sections.get_children(): if self.trv_selected_sections.item(item)['values'][3] != '': values = self.trv_selected_sections.item(item)['values'] self.trv_selected_sections.item( item, values=(values[0], values[1], values[2], values[3], '')) # Set new main sections cont_error = False for row in self.trv_selected_sections.selection(): values = self.trv_selected_sections.item(row)['values'] if values[2] == 'Classification' or values[2] == 'Text': self.trv_selected_sections.item( row, values=(values[0], values[1], values[2], values[3], '✓')) else: # File sections can not be main cont_error = True if cont_error: messagebox.showwarning( parent=self.frm_child_crud, title='Main section(s)', message= "Main section(s) must be of 'Text' or 'Classification' data type" ) else: messagebox.showwarning( parent=self.frm_child_crud, title='Main section(s)', message= 'You must select a minimum of one and a maximum of three sections' ) def click_trv_asections(self, event): """ Function that removes selection from 'available' tree view when 'selected' tree view is selected (in frm_child_crud) """ self.trv_selected_sections.selection_remove( self.trv_selected_sections.selection()) def click_trv_ssections(self, event): """ Function that removes selection from 'selected' tree view when 'available' tree view is selected (in frm_child_crud) """ self.trv_available_sections.selection_remove( self.trv_available_sections.selection()) def click_save(self): if self.validate_fields(): self.template.name = self.txt_name.get() self.template.description = self.txt_description.get( '1.0', 'end-1c') if self.template.id == 0: # Creating a template self.directive = Message(action=36, information=[ self.template.name, self.template.description, [], [], [] ]) for item in self.trv_selected_sections.get_children(): values = self.trv_selected_sections.item(item)['values'] self.directive.information[2].append( int(self.trv_selected_sections.item(item)['text'])) self.directive.information[3].append(values[4]) if values[4] != '': self.directive.information[4].append('✓') else: self.directive.information[4].append(values[3]) else: # Updating a template self.directive = Message(action=38, information=[ self.template.id, self.template.name, self.template.description, [], [], [] ]) for item in self.trv_selected_sections.get_children(): values = self.trv_selected_sections.item(item)['values'] self.directive.information[3].append( int(self.trv_selected_sections.item(item)['text'])) self.directive.information[4].append(values[4]) if values[4] != '': self.directive.information[5].append('✓') else: self.directive.information[5].append(values[3]) self.connection = self.directive.send_directive(self.connection) self.clear_fields() self.frm_child_crud.grid_forget() self.show_frm() def click_cancel(self): decision = True if self.txt_name.get() != self.template.name or \ self.txt_description.get('1.0', 'end-1c') != self.template.description or \ len(self.trv_selected_sections.get_children()) != len(self.template.sections): decision = messagebox.askyesno( parent=self.frm_child_crud, title='Cancel', message='Are you sure you want to cancel?') if decision: self.click_back() def click_back(self): self.clear_fields() self.frm_child_crud.grid_forget() self.show_frm() def validate_fields(self): text_section = False if len(self.txt_name.get()) == 0: messagebox.showwarning(parent=self.frm_child_crud, title='Missing information', message='You must provide a name') return False if len(self.txt_description.get('1.0', 'end-1c')) == 0: messagebox.showwarning(parent=self.frm_child_crud, title='Missing information', message='You must provide a description') return False if len(self.trv_selected_sections.get_children()) == 0: messagebox.showwarning( parent=self.frm_child_crud, title='Missing information', message='You must select at least one section') return False for item in self.trv_selected_sections.get_children(): values = self.trv_selected_sections.item(item)['values'] if values[2] == 'Text' or values[2] == 'Classification': text_section = True break if not text_section: messagebox.showwarning( parent=self.frm_child_crud, title='Missing information', message='At least one section has to be of text type') return False for item in self.trv_selected_sections.get_children(): values = self.trv_selected_sections.item(item)['values'] if values[4] == '✓': if values[2] == 'Text' or values[2] == 'Classification': return True else: messagebox.showwarning( parent=self.frm_child_crud, title='Main section', message= 'The main section has to be of text or classification type' ) return False messagebox.showwarning( parent=self.frm_child_crud, title='Main section', message='You must set one of the selected section as main') return False def clear_fields(self): self.txt_name['state'] = NORMAL self.txt_description['state'] = NORMAL self.txt_name['bg'] = ENABLED_COLOR self.txt_description['bg'] = ENABLED_COLOR self.txt_name.delete(0, END) self.txt_description.delete('1.0', 'end-1c') self.btn_save.grid_forget() self.btn_cancel.grid_forget() self.btn_back.grid_forget() self.lbl_note_optional.grid_forget() def click_switch_mandatory(self, event): if not self.view_decision: # Only if not viewing a template # Make sure only one item in 'selected sections' is selected if len(self.trv_selected_sections.selection()) == 1 and len( self.trv_available_sections.selection()) == 0: values = self.trv_selected_sections.item( self.trv_selected_sections.focus())['values'] if values[3] == '': self.trv_selected_sections.item( self.trv_selected_sections.focus(), values=(values[0], values[1], values[2], '✓', values[4])) else: self.trv_selected_sections.item( self.trv_selected_sections.focus(), values=(values[0], values[1], values[2], '', values[4]))
class Application(Frame): def __init__(self, master=None): Frame.__init__(self, master) self.ranking = [] ## Define os três frames existentes na janela principal ## A janela principal foi dividida em 3 frames (esquerda, central e direita) self.leftframe = Frame(self) self.leftframe.grid(row=0, column=0, stick=Tk.NS + Tk.E) self.centerframe = Frame(self) self.centerframe.grid(row=0, column=1, stick=Tk.NS) self.rightframe = Frame(self) self.rightframe.grid(row=0, column=2, stick=Tk.NS + Tk.W) # Inicializei as instancias aqui porque senão self.botaoSelecionaEntrada\ # não existe quando da criação dos botoes do frame esquerdo # container 1 - contem os objetos para leitura de arquivo # container 2 - contem os objetos para entrada de dados manual # container 3 - contem os objetos para escolha aleatoria dos rankings self.container1 = LabelFrame(self.centerframe, text="Escolha o arquivo", padx=5, pady=5) self.container2 = LabelFrame(self.centerframe, text="Entrada de dados", padx=5, pady=5) self.container3 = LabelFrame(self.centerframe, text="Escolha aleatória", padx=5, pady=5) ### #### Monta frame esquerdo #### Frame dos botões ### lblframe = LabelFrame(self.leftframe, text="Selecione entrada", padx=5, pady=5) lblframe.grid(row=0, column=0) button1 = Button(lblframe, text="Arquivo", width=20, command=lambda: self.botaoSelecionaEntrada(1)) button1.grid(row=0, column=0) button2 = Button(lblframe, text="Manual", width=20, command=lambda: self.botaoSelecionaEntrada(2)) button2.grid(row=1, column=0) button3 = Button(lblframe, text="Aleatório", width=20, command=lambda: self.botaoSelecionaEntrada(3)) button3.grid(row=2, column=0) lblframe = LabelFrame(self.leftframe, text="Calculadora", padx=5, pady=5) lblframe.grid(row=3, column=0, pady=20) button1 = Button(lblframe, text="Calculadora", width=20, command=lambda: self.Calculadora()) button1.grid(row=0, column=0) button2 = Button(lblframe, text="Reset", width=20, command=lambda: self.resetDisplayResults()) button2.grid(row=1, column=0) ### ### Monta Frame central ### ### O Frame central contém 3 "containers" que serão ligados e desligados em tempo ### de execução através dos botões existentes no frame esquerdo ### ##Entrada através de arquivo ## self.mySelectionF = Tk.StringVar() labelvalue = self.mySelectionF self.container1.grid(row=0, column=0) buttonFile = Tk.Button(self.container1, text='Ler arquivo', width=10, command=self.askopenfilename) buttonFile.grid(row=0, column=0, sticky='N') self.displayRanking1() ### Desliga objeto do frame da tela self.container1.isgridded = True #self.container1.grid_forget() # # Entrada manual # #### DESISTI DE FAZER ASSIM SE DER TEMPO VOLTO A FAZER SENAO #### FAÇO DEPOIS DA ENTRAGA DA AD #### #self.mySelection = Tk.StringVar() #labelvalue = self.mySelection #self.container2 = LabelFrame(self.centerframe, text="Entrada de dados", padx=5, pady=5) ## Foi criado la em cima #self.container2.grid(row=0, column=0) # label com nome do ranking #self.label = Label(self.container2, text=labelvalue) #self.label.grid(row=0,column=1) # campo de entrada #entryA = Entry(self.container2,width=6) #criamos o campo de texto #entryA.grid(column=0,row=1,sticky='EW'+'S') # Botao #button4 = Tk.Button(self.container2, text = '->', width = 10) #button4.grid( row=2,column=0,sticky='EW'+'N') #Combobox #self.comboboxM = ttk.Combobox(self.container2, width= 15, state="readonly", textvariable = self.mySelection) #self.comboboxM["values"] = ("Ranking 1", "Ranking 2") #self.comboboxM.grid(row=0, column=0) #self.comboboxM.bind("<<ComboboxSelected>>", self.callbackFunc) #ListBox #value=["one", "two", "three", "four", "five", "six", "seven","eight","nine","ten","eleven","twelve"] ### Somente para teste #value = [] #self.listbox = Listbox(self.container2,selectmode=Tk.SINGLE) #scrollbar = Tk.Scrollbar(self.container2, orient=Tk.VERTICAL) #self.listbox.config( yscrollcommand=scrollbar.set) #scrollbar.configure(command=self.listbox.yview) #scrollbar.config(command=self.listbox.yview) #self.listbox.insert(Tk.END, None) #for item in value: # self.listbox.insert(Tk.END, item) #self.listbox.grid(row=1, column=1,stick=Tk.W) #scrollbar.grid(row=1,column=2,stick=Tk.NS+Tk.W) ### Aqui resolvi fazer assim, senão não ia dar tempo para fazer do jeito que eu queria ### Caminho mais fácil, senão nao consigo fazer os testes se é que vou conseguir self.container2.grid(row=0, column=0) self.v1 = Tk.IntVar(value=1) #self.v1 = Tk.StringVar(value="1") self.v1.set(1) self.v2 = Tk.IntVar(value=1) #self.v2 = Tk.StringVar(value="1") self.v2.set(1) self.displayEntradaManual() #self.label = Label(self.container2, text="Escolha o tipo de entrada") #self.label.grid(row=0,column=0, columnspan=2) #self.rb1 = Tk.Radiobutton(self.container2, text="Ranking", variable=self.v1, value=1,state=Tk.ACTIVE,indicatoron=1) #self.rb1.grid(row=1,column=0) #self.rb2 = Tk.Radiobutton(self.container2, text="Score", variable=self.v1, value=2,state=Tk.ACTIVE,indicatoron=1) #self.rb2.grid(row=1,column=1) #self.label = Label(self.container2, text="Ranking / Score 1") #self.label.grid(row=2,column=0) #self.entryM1 = Entry(self.container2,width=30) #criamos o campo de texto #self.entryM1.grid(row=3,column=0,sticky='EW'+'S',columnspan=2) #self.rb3 = Tk.Radiobutton(self.container2, text="Ranking", variable=self.v2, value=1,state=Tk.ACTIVE,indicatoron=1) #self.rb3.grid(row=4,column=0) #self.rb4 = Tk.Radiobutton(self.container2, text="Score", variable=self.v2, value=2,state=Tk.ACTIVE,indicatoron=1) #self.rb4.grid(row=4,column=1) #self.label = Label(self.container2, text="Ranking / Score 2") #self.label.grid(row=5,column=0) #self.entryM2 = Entry(self.container2,width=30) #criamos o campo de texto #self.entryM2.grid(row=6,column=0,sticky='EW'+'S',columnspan=2) self.container2.isgridded = False self.container2.grid_forget() ##entrada aleatoria #self.container3 = LabelFrame(self.centerframe, text="Entrada de dados", padx=5, pady=5) self.mySelectionA = Tk.StringVar() self.container3.grid(row=0, column=0) self.container3A = LabelFrame(self.container3, text="Define tamanho", padx=5, pady=5) self.container3A.grid(row=0, column=0) # label com nome do ranking self.label = Label(self.container3A, text='Selecione o tamanho dos rankings') self.label.grid(row=0, column=0, sticky="S") self.entryB = Entry(self.container3A, width=6) #criamos o campo de texto self.entryB.grid(row=1, column=0, sticky='EW' + 'S') button5 = Tk.Button(self.container3A, text='Gerar', width=10, command=self.gerarRankingAleatorio) button5.grid(row=2, column=0, sticky='EW' + 'N') self.displayRanking() #self.container3B = LabelFrame(self.container3,text="Visualiza RANKINGs", padx=5, pady=5) #self.container3B.grid(row=0, column=1) self.container3.isgridded = False self.container3.grid_forget() ####self.container3B = LabelFrame(self.container3, text="Visualiza RANKINGs", padx=5, pady=5) ####self.container3B.grid(row=0, column=1) ####self.comboboxA = ttk.Combobox(self.container3B, width= 15, state="readonly", textvariable = self.mySelectionA) ####self.comboboxA["values"] = ("Ranking 1", "Ranking 2") ####self.comboboxA.grid(row=0, column=1) ####self.comboboxA.bind("<<ComboboxSelected>>", self.callbackRandom) #value=["one", "two", "three", "four", "five", "six", "seven","eight","nine","ten","eleven","twelve"] ### Somente para teste ####value = [] ####self.listbox = Listbox(self.container3B,selectmode=Tk.SINGLE) ####scrollbar = Tk.Scrollbar(self.container3B, orient=Tk.VERTICAL) ####self.listbox.config( yscrollcommand=scrollbar.set) ####scrollbar.configure(command=self.listbox.yview) ####scrollbar.config(command=self.listbox.yview) ####self.listbox.insert(Tk.END, None) ####for item in value: #### self.listbox.insert(Tk.END, item) ####self.listbox.grid(row=1, column=1,stick=Tk.W) ####scrollbar.grid(row=1,column=2,stick=Tk.NS+Tk.W) ####self.container3.isgridded = False ####self.container3.grid_forget() ### #### Monta frame direito ### self.lblframe = LabelFrame(self.rightframe, text="RESULTADOS", padx=5, pady=5) self.lblframe.grid(row=0, column=0) self.label = Label(self.lblframe, text="Kemeny = ") self.label.grid(row=0, column=0, sticky=Tk.W) result = str(0) self.labelkemeny = Label(self.lblframe, text=result) self.labelkemeny.grid(row=0, column=1) self.label = Label(self.lblframe, text="Footrule = ") self.label.grid(row=1, column=0, sticky=Tk.W) self.labelfootrule = Label(self.lblframe, text=result) self.labelfootrule.grid(row=1, column=1) self.label = Label(self.lblframe, text="*** Inversões ***") self.label.grid(row=2, column=0) self.label = Label(self.lblframe, text="Inversões Ranking 1 = ") self.label.grid(row=3, column=0, sticky=Tk.W) self.label = Label(self.lblframe, text="Inversões Ranking 2 = ") self.label.grid(row=4, column=0, sticky=Tk.W) self.labelinv1 = Label(self.lblframe, text=result) self.labelinv1.grid(row=3, column=1) self.labelinv2 = Label(self.lblframe, text=result) self.labelinv2.grid(row=4, column=1) self.bye = Button(self.rightframe, text="Bye Bye", command=self.quit) self.bye.grid(row=5, column=0) self.pack() # Monta radiobutton no frame central container 2 def displayEntradaManual(self): """@ Show RadioButton on container2 in Application Class @example self.displayEntradaManual() """ self.label = Label(self.container2, text="Escolha o tipo de entrada") self.label.grid(row=0, column=0, columnspan=2) self.rb1 = Tk.Radiobutton(self.container2, text="Ranking", variable=self.v1, value=1, state=Tk.ACTIVE, indicatoron=1) self.rb1.grid(row=1, column=0) self.rb2 = Tk.Radiobutton(self.container2, text="Score", variable=self.v1, value=2, state=Tk.ACTIVE, indicatoron=1) self.rb2.grid(row=1, column=1) self.label = Label(self.container2, text="Ranking / Score 1") self.label.grid(row=2, column=0) self.entryM1 = Entry(self.container2, width=30) #criamos o campo de texto self.entryM1.grid(row=3, column=0, sticky='EW' + 'S', columnspan=2) self.rb3 = Tk.Radiobutton(self.container2, text="Ranking", variable=self.v2, value=1, state=Tk.ACTIVE, indicatoron=1) self.rb3.grid(row=4, column=0) self.rb4 = Tk.Radiobutton(self.container2, text="Score", variable=self.v2, value=2, state=Tk.ACTIVE, indicatoron=1) self.rb4.grid(row=4, column=1) self.label = Label(self.container2, text="Ranking / Score 2") self.label.grid(row=5, column=0) self.entryM2 = Entry(self.container2, width=30) #criamos o campo de texto self.entryM2.grid(row=6, column=0, sticky='EW' + 'S', columnspan=2) self.label = Label(self.container2, text="Formato da entrada(ranking): 5 4 3 2 1") self.label.grid(row=7, column=0, sticky='W') self.label = Label( self.container2, text="Formato da entrada(score): 0.65 0.32 0.62 0.23 0.34") self.label.grid(row=8, column=0, sticky='W') self.container2.isgridded = False self.container2.grid_forget() # Reset nos valores do frame direito def resetDisplayResults(self): """@ Reset values kemeny, footrule and Inversions and clean labels @example self.resetDisplayResults() """ del self.ranking[:] result = str(0) self.labelkemeny = Label(self.lblframe, text=result) self.labelkemeny.grid(row=0, column=1) self.labelfootrule = Label(self.lblframe, text=result) self.labelfootrule.grid(row=1, column=1) self.labelinv1 = Label(self.lblframe, text=result) self.labelinv1.grid(row=3, column=1) self.labelinv2 = Label(self.lblframe, text=result) self.labelinv2.grid(row=4, column=1) if self.buttonClick == 1: self.displayRanking1() if self.buttonClick == 2: self.entryM1.delete(0, 'end') #limpamos o campo de texto self.entryM1.grid(row=3, column=0, sticky='EW' + 'S', columnspan=2) self.entryM2.delete(0, 'end') #limpamos o campo de texto self.entryM2.grid(row=6, column=0, sticky='EW' + 'S', columnspan=2) if self.buttonClick == 3: self.displayRanking() messagebox.showinfo("Mensagem", "Kemeny, footrule e inversões zeradas!") # Metodo que retorna um evento de selecao def displayRanking(self): """@ Show combobox on screen @example self.displayRanking() """ self.container3B = LabelFrame(self.container3, text="Visualiza RANKINGs", padx=5, pady=5) self.container3B.grid(row=0, column=1) self.comboboxA = ttk.Combobox(self.container3B, width=15, state="readonly", textvariable=self.mySelectionA) self.comboboxA["values"] = ("Ranking 1", "Ranking 2") self.comboboxA.grid(row=0, column=1) self.comboboxA.bind("<<ComboboxSelected>>", self.callbackRandom) #value=["one", "two", "three", "four", "five", "six", "seven","eight","nine","ten","eleven","twelve"] ### Somente para teste self.displayRankingListbox() #####value = [] #####self.listbox = Listbox(self.container3B,selectmode=Tk.SINGLE) #####scrollbar = Tk.Scrollbar(self, orient=Tk.VERTICAL) #####self.listbox.config( yscrollcommand=scrollbar.set) #####scrollbar.configure(command=self.listbox.yview) #####scrollbar.config(command=self.listbox.yview) #####self.listbox.insert(Tk.END, None) #####for item in value: ##### self.listbox.insert(Tk.END, item) #####self.listbox.grid(row=1, column=1,stick=Tk.W) #####scrollbar.grid(row=1,column=2,stick=Tk.NS+Tk.W) #self.container3B = LabelFrame(self.container3B,text="Visualiza RANKINGs", padx=5, pady=5) #self.container3B.grid(row=0, column=1) def displayRankingListbox(self, value=[]): """@note show Ranking on display @param[in] a list @example self.displayRankingListbox([1 2 3 4 5]) """ self.value = value self.listbox = Listbox(self.container3B, selectmode=Tk.SINGLE) scrollbar = Tk.Scrollbar(self.container3B, orient=Tk.VERTICAL) self.listbox.config(yscrollcommand=scrollbar.set) scrollbar.configure(command=self.listbox.yview) scrollbar.config(command=self.listbox.yview) self.listbox.insert(Tk.END, None) for item in value: self.listbox.insert(Tk.END, item) self.listbox.grid(row=1, column=1, stick=Tk.W) scrollbar.grid(row=1, column=2, stick=Tk.NS + Tk.W) ## Segui o Caminho mais fácil ## Dupliquei displayRanking e alterei o container apenas ## Não é o correto, mas não está errado, se sobrar tempo faço da forma correta def displayRanking1(self): """@ Show combobox on screen @example self.displayRanking1() """ self.container1B = LabelFrame(self.container1, text="Visualiza RANKINGs", padx=5, pady=5) self.container1B.grid(row=0, column=1) self.comboboxF = ttk.Combobox(self.container1B, width=15, state="readonly", textvariable=self.mySelectionF) self.comboboxF["values"] = ("Ranking 1", "Ranking 2") self.comboboxF.grid(row=0, column=1) self.comboboxF.bind("<<ComboboxSelected>>", self.callbackRandom) #value=["one", "two", "three", "four", "five", "six", "seven","eight","nine","ten","eleven","twelve"] ### Somente para teste self.displayRankingListbox1() ''' value = [] self.listbox = Listbox(self.container3B,selectmode=Tk.SINGLE) scrollbar = Tk.Scrollbar(self, orient=Tk.VERTICAL) self.listbox.config( yscrollcommand=scrollbar.set) scrollbar.configure(command=self.listbox.yview) scrollbar.config(command=self.listbox.yview) self.listbox.insert(Tk.END, None) for item in value: self.listbox.insert(Tk.END, item) self.listbox.grid(row=1, column=1,stick=Tk.W) scrollbar.grid(row=1,column=2,stick=Tk.NS+Tk.W) ''' #self.container3B = LabelFrame(self.container3B,text="Visualiza RANKINGs", padx=5, pady=5) #self.container3B.grid(row=0, column=1) def displayRankingListbox1(self, value=[]): """@note show Ranking on display @param[in] a list @example self.displayRankingListbox([1 2 3 4 5]) """ self.value = value self.listbox = Listbox(self.container1B, selectmode=Tk.SINGLE) scrollbar = Tk.Scrollbar(self.container1B, orient=Tk.VERTICAL) self.listbox.config(yscrollcommand=scrollbar.set) scrollbar.configure(command=self.listbox.yview) scrollbar.config(command=self.listbox.yview) self.listbox.insert(Tk.END, None) for item in value: self.listbox.insert(Tk.END, item) self.listbox.grid(row=1, column=1, stick=Tk.W) scrollbar.grid(row=1, column=2, stick=Tk.NS + Tk.W) # # Gera dois rankings Aleatórios a partir de um inteiro # os rankings sao colocados em um vetor self.ranking def gerarRankingAleatorio(self): """@note Build a random Ranking and show on display @example self.gerarRankingAleatorio() """ self.resetDisplayResults() try: value = int(self.entryB.get()) except ValueError: messagebox.showinfo("ERRO!", "Informar o tamanho do ranking a ser gerado!") return #choice = self.mySelectionA.get() ### Não precisei a selecao acontece em displayrankinglistbox #index = self.comboboxA.current() ### nao precisei a selecao acontece em displayrankinglistbox if value < 1: messagebox.showinfo("Title", "Valor inválido ( " + value + " )") else: del self.ranking[:] for _ in range(2): self.ranking.append(Ranking(value)) messagebox.showinfo("Title", "Rankings 1 e 2 gerados") self.comboboxA.current(0) self.displayRankingListbox(getattr(self.ranking[0], 'ranking')) #self.resetDisplayResults() #def callbackFunc(self, event): # select = self.mySelection.get() # self.labelvalue = select # self.label = Label(self.container2, text=self.labelvalue) # self.label.grid(row=0,column=1) # print(select) def callbackRandom(self, event): """@note auxiliary method to gerarRankingAleatorio @example self.callbackRandom() """ #select = self.mySelection.get() try: #_ = self.ranking[0] #_ = getattr(self.ranking[0],"ranking") index = self.comboboxA.current() array = getattr(self.ranking[index], 'ranking') self.listbox.delete(0, Tk.END) self.listbox.insert(Tk.END, None) for item in array: self.listbox.insert(Tk.END, item) self.listbox.grid(row=1, column=1, stick=Tk.W) except IndexError: messagebox.showinfo("ERRO!", "Não existem Rankings gerados!") return def askopenfilename(self): """@note Open ranking file @example self.askopenfilename() """ filepath = askopenfilename() if filepath: #self.container1.filepaths.append(filepath) with open(filepath, "r+") as f: del self.ranking[:] for line in f: value = line.replace("\n", "").replace( "\r", "") # do something with the line try: value = literal_eval(value) except SyntaxError: messagebox.showinfo("ERRO!", "Arquivo incompatível!") return else: if type(value) is int: del self.ranking[:] for _ in range(2): self.ranking.append(Ranking(value)) messagebox.showinfo("Title", "Rankings 1 e 2 gerados") elif type(value) is list: self.ranking.append(Ranking(value)) elif type(value) is tuple: self.ranking.append(Ranking(value)) #for line in inputfile.readline(): ## line = line.replace("\n", "").replace("\r", "") # print(line) # #value = literal_eval(line) # #print(type(value)) self.comboboxF.current(0) self.displayRankingListbox1(getattr(self.ranking[0], 'ranking')) f.close() def botaoSelecionaEntrada(self, value): """@note Build a rank from tuple. @param[in] integer @example self.botaoSelecionaEntrada(1) """ self.buttonClick = value print("Called" + str(self.value)) self.container1.isgridded = False self.container1.grid_forget() self.container2.isgridded = False self.container2.grid_forget() self.container3.isgridded = False self.container3.grid_forget() if self.buttonClick == 1: self.container1.isgridded = True self.container1.grid(row=0, column=0) if self.buttonClick == 2: # Ativa radiobutton do ranking / score (nao esta ativando) self.v1.set(1) self.v2.set(1) # Liga container 2 self.displayEntradaManual() self.container2.isgridded = True self.container2.grid(row=0, column=0) if self.buttonClick == 3: self.container3.isgridded = True self.container3.grid(row=0, column=0) def checkType(self, lista): """@note Verify there are only digits from list @param[in] list @return Boolean @example self.checkType([1, 3, 4, 2]) """ for x in lista: if type(x) is str: return False return True def Calculadora(self): """@note Method to activate auxiliaries methods to show results @example self.Calculadora() """ try: if self.buttonClick == 1: #value1 = self.entryM1.get().split() #value2 = self.entryM2.get().split() #print("Valor 1", value1, "Valor 2",value2) #del self.ranking[:] # Adiciona a entrada 1 ao vetor self.ranking #if int(self.v1.get()) == 1: # self.ranking.append(Ranking(value1)) #else: # self.ranking.append(Ranking(tuple(value1))) # Adiciona a entrada 2 ao vetor self.ranking #if int(self.v2.get()) == 1: # self.ranking.append(Ranking(value2)) #else: # self.ranking.append(Ranking(tuple(value2))) try: #_ = self.ranking[0] _ = getattr(self.ranking[0], "ranking") except IndexError: messagebox.showinfo("ERRO!", "Não existem Rankings gerados!") return self.showKemeny() self.showFootrule() self.showInvert() print(getattr(self.ranking[0], 'ranking')) print(getattr(self.ranking[1], 'ranking')) if self.buttonClick == 2: value1 = self.entryM1.get().split() value2 = self.entryM2.get().split() print("Valor 1", value1, "Valor 2", value2) if self.checkType(value1) and self.checkType(value2) or\ not (len(value1)) or any(d is None for d in value1) or value1 is None or\ not (len(value2)) or any(d is None for d in value2) or value2 is None or\ len(value1) != len(set(value1)) or len(value2) != len(set(value2)) or\ len(set(value1)) != len(set(value2)): messagebox.showinfo( "ERRO!", "Erro na entrada de dados - Ranking inválido!") else: del self.ranking[:] # Adiciona a entrada 1 ao vetor self.ranking if int(self.v1.get()) == 1: self.ranking.append(Ranking(tuple(value1))) else: self.ranking.append(Ranking(value1)) # Adiciona a entrada 2 ao vetor self.ranking if int(self.v2.get()) == 1: self.ranking.append(Ranking(tuple(value2))) else: self.ranking.append(Ranking(value2)) self.showKemeny() self.showFootrule() self.showInvert() #print(getattr(self.ranking[0],'ranking')) #print(getattr(self.ranking[1],'ranking')) if self.buttonClick == 3: try: _ = getattr(self.ranking[0], "ranking") except (IndexError, AttributeError): messagebox.showinfo("Title", "Não existem Rankings gerados!") else: # print(len(getattr(self.ranking,"ranking"))) self.showKemeny() self.showFootrule() self.showInvert() except AttributeError: messagebox.showinfo("ERRO!", "Não existem valores a ser calculados!") return def showKemeny(self): """@note Calculate Kemeny distance from Ranking Class than show on screen @example self.showKemeny() """ value1 = Ranking(getattr(self.ranking[0], 'ranking')) value2 = Ranking(getattr(self.ranking[1], 'ranking')) print(value1, value2) result = value1.kDist(value2) self.labelkemeny = Label(self.lblframe, text=result) self.labelkemeny.grid(row=0, column=1) def showFootrule(self): """@note Calculate Footrule distance from Ranking Class than show on screen @example self.showFootrule() """ value1 = Ranking(getattr(self.ranking[0], 'ranking')) value2 = Ranking(getattr(self.ranking[1], 'ranking')) print(value1, value2) result = value1.fDist(value2) self.labelfootrule = Label(self.lblframe, text=result) self.labelfootrule.grid(row=1, column=1) def showInvert(self): """@note Calculate inversions from Ranking Class than show on screen @example self.showInvert() """ value1 = Ranking(getattr(self.ranking[0], 'ranking')) value2 = Ranking(getattr(self.ranking[1], 'ranking')) print(value1, value2) result = value1.invCount() self.labelinv1 = Label(self.lblframe, text=result) self.labelinv1.grid(row=3, column=1) result = value2.invCount() self.labelinv2 = Label(self.lblframe, text=result) self.labelinv2.grid(row=4, column=1)
class FormChildReport: def __init__(self, frm_parent, connection): self.connection = connection self.id_selected = 0 self.frm_child_report = LabelFrame(frm_parent) self.tlevel_comp_detail = Toplevel(frm_parent) self.tlevel_comp_detail.protocol("WM_DELETE_WINDOW", self.click_exit_component_det) self.tlevel_comp_detail.withdraw() self.tlevel_sol_detail = Toplevel(frm_parent) self.tlevel_sol_detail.protocol("WM_DELETE_WINDOW", self.click_exit_solution_det) self.tlevel_sol_detail.withdraw() self.tlevel_diagram = Toplevel(self.tlevel_sol_detail) self.tlevel_diagram.protocol("WM_DELETE_WINDOW", self.click_exit_diagram) self.tlevel_diagram.withdraw() self.initialize_components() def initialize_components(self): """ Method that initialize the visual components for each form associated with the configuration of experiments """ # Button icons used in the forms self.csv_icon = PhotoImage(file=r"./Resources/csv.png") self.info_icon = PhotoImage(file=r"./Resources/info.png") # Components for Report form (list of experiments) # General selection section lbl_sep1 = Label(self.frm_child_report) lbl_sep1.grid(row=0, column=0, padx=10, pady=10, rowspan=7) lbl_available_exp = Label(self.frm_child_report, text='Select an experiment', anchor=W) lbl_available_exp.config(fg=TEXT_COLOR, font=SUBTITLE2_FONT) lbl_available_exp.grid(row=0, column=1, pady=10, sticky=W) self.trv_available_exp = Treeview(self.frm_child_report, height=5, columns=('N', 'Experiment')) self.trv_available_exp.heading('#0', text='ID', anchor=CENTER) self.trv_available_exp.heading('#1', text='N', anchor=CENTER) self.trv_available_exp.heading('#2', text='Experiment', anchor=CENTER) self.trv_available_exp.column('#0', width=0, minwidth=50, stretch=NO) self.trv_available_exp.column('#1', width=20, minwidth=20, stretch=NO) self.trv_available_exp.column('#2', width=250, minwidth=250, stretch=NO) self.trv_available_exp.bind("<ButtonRelease-1>", self.select_experiment_general) self.trv_available_exp.grid(row=1, column=1, columnspan=3, sticky=W, pady=10) vsb_trv_avex = Scrollbar(self.frm_child_report, orient="vertical", command=self.trv_available_exp.yview) vsb_trv_avex.grid(row=1, column=4, pady=10, sticky=NS) self.trv_available_exp.configure(yscrollcommand=vsb_trv_avex.set) btn_detail_exp = Button(self.frm_child_report, image=self.info_icon, command=self.click_view_experiment) btn_detail_exp.grid(row=0, column=3, pady=10, padx=5, sticky=E) btn_detail_exp_ttp = CreateToolTip(btn_detail_exp, 'View experiment information') btn_csv = Button(self.frm_child_report, image=self.csv_icon, command=self.click_csv) btn_csv.grid(row=0, column=2, pady=10, sticky=E) btn_csv_ttp = CreateToolTip(btn_csv, 'Generate .csv file') lbl_available_sc = Label(self.frm_child_report, text='Select a scenario', anchor=W) lbl_available_sc.config(font=SUBTITLE2_FONT, fg=TEXT_COLOR) lbl_available_sc.grid(row=2, column=1, pady=10, columnspan=2, sticky=W) self.trv_available_sc = Treeview(self.frm_child_report, height=5, columns=('N', 'Experimental scenario')) self.trv_available_sc.heading('#0', text='ID', anchor=CENTER) self.trv_available_sc.heading('#1', text='N', anchor=CENTER) self.trv_available_sc.heading('#2', text='Experimental scenario', anchor=CENTER) self.trv_available_sc.column('#0', width=0, minwidth=50, stretch=NO) self.trv_available_sc.column('#1', width=20, minwidth=20, stretch=NO) self.trv_available_sc.column('#2', width=250, minwidth=250, stretch=NO) self.trv_available_sc.bind("<ButtonRelease-1>", self.select_scenario_general) self.trv_available_sc.grid(row=3, column=1, columnspan=3, sticky=W, pady=10) vsb_trv_avsc = Scrollbar(self.frm_child_report, orient="vertical", command=self.trv_available_sc.yview) vsb_trv_avsc.grid(row=3, column=4, pady=10, sticky=NS) self.trv_available_sc.configure(yscrollcommand=vsb_trv_avsc.set) btn_detail_sc = Button(self.frm_child_report, image=self.info_icon, command=self.click_view_scenario) btn_detail_sc.grid(row=2, column=3, pady=10, sticky=E) btn_detail_sc_ttp = CreateToolTip(btn_detail_sc, 'View scenario information') lbl_available_prob = Label(self.frm_child_report, text='Select a problem', anchor=W) lbl_available_prob.config(font=SUBTITLE2_FONT, fg=TEXT_COLOR) lbl_available_prob.grid(row=4, column=1, pady=10, columnspan=2, sticky=W) self.trv_available_prob = Treeview(self.frm_child_report, height=5, columns=('N', 'Design problem')) self.trv_available_prob.heading('#0', text='ID', anchor=CENTER) self.trv_available_prob.heading('#1', text='N', anchor=CENTER) self.trv_available_prob.heading('#2', text='Design problem', anchor=CENTER) self.trv_available_prob.column('#0', width=0, minwidth=50, stretch=NO) self.trv_available_prob.column('#1', width=20, minwidth=20, stretch=NO) self.trv_available_prob.column('#2', width=250, minwidth=250, stretch=NO) self.trv_available_prob.bind("<ButtonRelease-1>", self.select_problem_general) self.trv_available_prob.grid(row=5, column=1, columnspan=3, sticky=W, pady=10) vsb_trv_avprob = Scrollbar(self.frm_child_report, orient="vertical", command=self.trv_available_prob.yview) vsb_trv_avprob.grid(row=5, column=4, pady=10, sticky=NS) self.trv_available_prob.configure(yscrollcommand=vsb_trv_avprob.set) btn_detail_prob = Button(self.frm_child_report, image=self.info_icon, command=self.click_view_problem) btn_detail_prob.grid(row=4, column=3, pady=10, sticky=E) btn_detail_prob_ttp = CreateToolTip(btn_detail_prob, 'View problem report') sep_aux1 = Separator(self.frm_child_report, orient=VERTICAL) sep_aux1.grid(row=0, column=5, sticky=NS, rowspan=7, padx=30) # Detailed selection section self.trv_detail_sc = Treeview(self.frm_child_report, height=8, columns=('N', 'Scenario', 'M1', 'M2', 'M3', 'M4')) self.trv_detail_sc.heading('#0', text='ID', anchor=CENTER) self.trv_detail_sc.heading('#1', text='N', anchor=CENTER) self.trv_detail_sc.heading('#2', text='Scenario', anchor=CENTER) self.trv_detail_sc.heading('#3', text='M1', anchor=CENTER) self.trv_detail_sc.heading('#4', text='M2', anchor=CENTER) self.trv_detail_sc.heading('#5', text='M3', anchor=CENTER) self.trv_detail_sc.heading('#6', text='M4', anchor=CENTER) self.trv_detail_sc.column('#0', width=0, minwidth=50, stretch=NO) self.trv_detail_sc.column('#1', width=20, minwidth=20, stretch=NO) self.trv_detail_sc.column('#2', width=250, minwidth=250, stretch=NO) self.trv_detail_sc.column('#3', width=55, minwidth=55, stretch=NO) self.trv_detail_sc.column('#4', width=55, minwidth=55, stretch=NO) self.trv_detail_sc.column('#5', width=55, minwidth=55, stretch=NO) self.trv_detail_sc.column('#6', width=55, minwidth=55, stretch=NO) self.trv_detail_sc.grid(row=0, column=6, rowspan=2, sticky=W, pady=10) vsb_trv_detsc = Scrollbar(self.frm_child_report, orient="vertical", command=self.trv_detail_sc.yview) vsb_trv_detsc.grid(row=0, column=7, rowspan=2, pady=10, sticky=NS) self.trv_detail_sc.configure(yscrollcommand=vsb_trv_detsc.set) self.trv_detail_prob = Treeview(self.frm_child_report, height=8, columns=('N', 'Problem', 'M1', 'M2', 'M3', 'M4')) self.trv_detail_prob.heading('#0', text='ID', anchor=CENTER) self.trv_detail_prob.heading('#1', text='N', anchor=CENTER) self.trv_detail_prob.heading('#2', text='Problem', anchor=CENTER) self.trv_detail_prob.heading('#3', text='M1', anchor=CENTER) self.trv_detail_prob.heading('#4', text='M2', anchor=CENTER) self.trv_detail_prob.heading('#5', text='M3', anchor=CENTER) self.trv_detail_prob.heading('#6', text='M4', anchor=CENTER) self.trv_detail_prob.column('#0', width=0, minwidth=50, stretch=NO) self.trv_detail_prob.column('#1', width=20, minwidth=20, stretch=NO) self.trv_detail_prob.column('#2', width=250, minwidth=250, stretch=NO) self.trv_detail_prob.column('#3', width=55, minwidth=55, stretch=NO) self.trv_detail_prob.column('#4', width=55, minwidth=55, stretch=NO) self.trv_detail_prob.column('#5', width=55, minwidth=55, stretch=NO) self.trv_detail_prob.column('#6', width=55, minwidth=55, stretch=NO) self.trv_detail_prob.grid(row=2, column=6, rowspan=2, sticky=W, pady=10) vsb_trv_detprob = Scrollbar(self.frm_child_report, orient="vertical", command=self.trv_detail_prob.yview) vsb_trv_detprob.grid(row=2, column=7, rowspan=2, pady=10, sticky=NS) self.trv_detail_prob.configure(yscrollcommand=vsb_trv_detprob.set) self.trv_detail_designer = Treeview(self.frm_child_report, height=8, columns=('N', 'Designer', 'M1', 'M2', 'M3', 'M4')) self.trv_detail_designer.heading('#0', text='ID', anchor=CENTER) self.trv_detail_designer.heading('#1', text='N', anchor=CENTER) self.trv_detail_designer.heading('#2', text='Designer', anchor=CENTER) self.trv_detail_designer.heading('#3', text='M1', anchor=CENTER) self.trv_detail_designer.heading('#4', text='M2', anchor=CENTER) self.trv_detail_designer.heading('#5', text='M3', anchor=CENTER) self.trv_detail_designer.heading('#6', text='M4', anchor=CENTER) self.trv_detail_designer.column('#0', width=0, minwidth=50, stretch=NO) self.trv_detail_designer.column('#1', width=20, minwidth=20, stretch=NO) self.trv_detail_designer.column('#2', width=250, minwidth=250, stretch=NO) self.trv_detail_designer.column('#3', width=55, minwidth=55, stretch=NO) self.trv_detail_designer.column('#4', width=55, minwidth=55, stretch=NO) self.trv_detail_designer.column('#5', width=55, minwidth=55, stretch=NO) self.trv_detail_designer.column('#6', width=55, minwidth=55, stretch=NO) self.trv_detail_designer.bind("<Double-1>", self.view_detailed_solution) self.trv_detail_designer.grid(row=4, column=6, rowspan=2, sticky=W, pady=10) vsb_trv_detdesig = Scrollbar(self.frm_child_report, orient="vertical", command=self.trv_detail_designer.yview) vsb_trv_detdesig.grid(row=4, column=7, rowspan=2, pady=10, sticky=NS) self.trv_detail_designer.configure(yscrollcommand=vsb_trv_detdesig.set) lbl_notes = Label(self.frm_child_report, text='NOTE:\tDouble click on a designer to see\tLEGEND:\tM1=Solution ' 'time | M3=Viewed patterns\n\this solution for a problem ^.\t\t\t' 'M2=Selection time | M4=Selection efficiency\n') lbl_notes.config(fg=TEXT_COLOR, font=NOTE_FONT, justify=LEFT) lbl_notes.grid(row=6, column=6, pady=10, sticky=W) lbl_sep2 = Label(self.frm_child_report) lbl_sep2.grid(row=0, column=8, padx=10, pady=10, rowspan=7) # Components for component (experiment, scenario or problem) details lbl_sep3 = Label(self.tlevel_comp_detail) lbl_sep3.grid(row=0, column=0, padx=10, pady=20) self.txt_detail_component = Text(self.tlevel_comp_detail, height=25, width=60) self.txt_detail_component.config(font=TEXT_FONT, bg=DISABLED_COLOR) self.txt_detail_component.grid(row=0, column=1, pady=20, sticky=W) vsb_txt_detcomp = Scrollbar(self.tlevel_comp_detail, orient="vertical", command=self.txt_detail_component.yview) vsb_txt_detcomp.grid(row=0, column=2, pady=20, sticky=NS) self.txt_detail_component.configure(yscrollcommand=vsb_txt_detcomp.set) lbl_sep4 = Label(self.tlevel_comp_detail) lbl_sep4.grid(row=0, column=3, padx=10, pady=20) # Components of expanded detailed sent solution lbl_sep5 = Label(self.tlevel_sol_detail) lbl_sep5.grid(row=0, column=0, padx=10, pady=20, rowspan=3) lbl_sep6 = Label(self.tlevel_sol_detail) lbl_sep6.grid(row=0, column=1, pady=10) self.btn_detail_sol = Button(self.tlevel_sol_detail, text='View diagram >>', command=self.click_view_diagram_sol) self.txt_detail_solution = Text(self.tlevel_sol_detail, height=25, width=60) self.txt_detail_solution.config(font=TEXT_FONT, bg=DISABLED_COLOR) self.txt_detail_solution.grid(row=1, column=1, sticky=W, columnspan=2) vsb_txt_detsol = Scrollbar(self.tlevel_sol_detail, orient="vertical", command=self.txt_detail_solution.yview) vsb_txt_detsol.grid(row=1, column=3, sticky=NS) self.txt_detail_solution.configure(yscrollcommand=vsb_txt_detsol.set) lbl_sep7 = Label(self.tlevel_sol_detail) lbl_sep7.grid(row=0, column=4, padx=10, pady=20, rowspan=3) lbl_sep8 = Label(self.tlevel_sol_detail) lbl_sep8.grid(row=2, column=1, pady=10, columnspan=2) # Components of expanded sent solution diagram self.canvas_expanded = Canvas(self.tlevel_diagram, width=500, height=500) self.canvas_expanded.config(background='white', borderwidth=1) self.canvas_expanded.grid() def show_frm(self): """ Displays the home list of the 'Experiments' form """ self.frm_child_report.grid(row=1, column=0, columnspan=9, rowspan=8, pady=10, padx=10) self.retrieve_experiments() def hide_frm(self): """ Hides all forms that are currently active """ self.clear_components() self.frm_child_report.grid_forget() def retrieve_experiments(self): """ This function shows the existing 'Experiments' in the home TreeView """ # Remove existing elements in the list for item in self.trv_available_exp.get_children(): self.trv_available_exp.delete(item) self.directive = Message(action=92, information=['finished']) self.connection = self.directive.send_directive(self.connection) if len(self.connection.message.information) != 0: for index, item in enumerate(self.connection.message.information): elements = item.split('¥') self.trv_available_exp.insert('', 'end', text=elements[0], values=(index + 1, summarize_text(elements[1], 250))) self.available_patterns = Pattern.get_available_patterns(self.connection) '''if len(self.trv_available_exp.get_children()) != 0: self.trv_available_exp.selection_set(self.trv_available_exp.get_children()[0]) self.select_experiment_general()''' else: messagebox.showwarning(parent=self.frm_child_report, title='No experiments', message='No experiments in finished state') def retrieve_scenarios(self, scenarios=None): """ This function shows the existing Experimental scenarios in an 'Experiment' """ # Remove existing elements in the list for item in self.trv_available_sc.get_children(): self.trv_available_sc.delete(item) for index, item in enumerate(scenarios): elements = item.split('¥') self.trv_available_sc.insert('', 'end', text=elements[0], values=(index + 1, summarize_text(elements[1], 250))) '''if len(self.trv_available_sc.get_children()) != 0: self.trv_available_sc.selection_set(self.trv_available_sc.get_children()[0]) self.select_scenario()''' def retrieve_problems(self, problems=None): """ This function shows the existing Problems in an 'Experimental scenario' """ # Remove existing elements in the list for item in self.trv_available_prob.get_children(): self.trv_available_prob.delete(item) for index, item in enumerate(problems): elements = item.split('¥') self.trv_available_prob.insert('', 'end', text=elements[0], values=(index + 1, summarize_text(elements[1], 250))) '''if len(self.trv_available_prob.get_children()) != 0: self.trv_available_prob.selection_set(self.trv_available_prob.get_children()[0]) self.select_problem()''' def select_experiment_general(self, event=None): """ This function is activated when the 'Click Experiments TreeView' event ocurrs, it indicates than an experiments has been selected """ if len(self.trv_available_exp.selection()) == 1: self.clear_components(3) id_selected_exp = int(self.trv_available_exp.item(self.trv_available_exp.selection())[ 'text']) # Retrieve id of selected item from TreeView self.directive = Message(action=95, information=[id_selected_exp]) self.connection = self.directive.send_directive(self.connection) self.experiment = Experiment(id=id_selected_exp, name=self.connection.message.information[0], description=self.connection.message.information[1], design_type=self.connection.message.information[2], state=self.connection.message.information[3], creation_date=self.connection.message.information[5], execution_date=self.connection.message.information[6], finished_date=self.connection.message.information[7]) self.retrieve_scenarios(self.connection.message.information[4]) # Ask to server for dataframe of the measurements for the scenarios of selected experiment self.directive = Message(action=107, information=[id_selected_exp, 'experiment']) self.connection = self.directive.send_directive(self.connection) final_df = get_mean_value(self.connection.message.information[0]) for index, row in final_df.iterrows(): self.trv_detail_sc.insert('', 'end', text=row.id, values=(index + 1, summarize_text(row.variable, 250), row.m1, row.m2, row.m3, row.m4)) def select_scenario_general(self, event=None): """ Function activated when a scenario is selecteded """ if len(self.trv_available_sc.selection()) == 1: self.clear_components(2) id_selected_sc = int(self.trv_available_sc.item(self.trv_available_sc.selection())[ 'text']) # Retrieve id of selected item from TreeView self.directive = Message(action=85, information=[id_selected_sc, 'report', 1]) self.connection = self.directive.send_directive(self.connection) self.scenario = ExperimentalSC(id=id_selected_sc, title=self.connection.message.information[0], description=self.connection.message.information[1], id_description_diagram=self.connection.message.information[2], info_designers=self.connection.message.information[4]) self.retrieve_problems(self.connection.message.information[3]) # Ask to server for dataframe of the measurements for the problems of selected scenario self.directive = Message(action=107, information=[id_selected_sc, 'scenario']) self.connection = self.directive.send_directive(self.connection) final_df = get_mean_value(self.connection.message.information[0]) for index, row in final_df.iterrows(): self.trv_detail_prob.insert('', 'end', text=row.id, values=(index + 1, summarize_text(row.variable, 250), row.m1, row.m2, row.m3, row.m4)) def select_problem_general(self, event=None): """ Function activated when a scenario is selected """ if len(self.trv_available_prob.selection()) == 1: self.clear_components(1) id_selected_prob = int(self.trv_available_prob.item(self.trv_available_prob.selection())[ 'text']) # Retrieve id of selected item from TreeView self.directive = Message(action=55, information=[id_selected_prob]) self.connection = self.directive.send_directive(self.connection) self.problem = Problem(id=id_selected_prob, brief_description=self.connection.message.information[0], description=self.connection.message.information[1], id_solution=self.connection.message.information[2], av_patterns=self.available_patterns, connection=self.connection) # Ask to server for dataframe of the measurements for the designers of selected problem self.directive = Message(action=107, information=[id_selected_prob, 'problem']) self.connection = self.directive.send_directive(self.connection) final_df = get_mean_value(self.connection.message.information[0]) for index, row in final_df.iterrows(): self.trv_detail_designer.insert('', 'end', text=row.id, values=(index + 1, summarize_text(row.variable, 250), row.m1, row.m2, row.m3, row.m4)) def click_view_experiment(self): """ Function activated when 'Experiment detail' button is pressed, it shows the tlevel_detail window showing main information of the selected experimentin trv_available_sc """ if len(self.trv_available_exp.selection()) == 1: self.txt_detail_component['state'] = NORMAL self.txt_detail_component.delete('1.0', 'end-1c') self.txt_detail_component.insert('1.0', 'EXPERIMENT NAME\n{}\n\n' 'DESCRIPTION\n{}\n\n' 'DESIGN TYPE\n{}\n\n' 'CREATION DATETIME\n{}\n\n' 'EXECUTION DATETIME\n{}\n\n' 'FINISHED DATETIME\n{}'. format(self.experiment.name, self.experiment.description, 'One group' if self.experiment.design_type == 1 else 'Two groups', self.experiment.creation_date.strftime('%c'), self.experiment.execution_date.strftime('%c'), self.experiment.finished_date.strftime('%c'))) self.txt_detail_component['state'] = DISABLED self.tlevel_comp_detail.deiconify() self.tlevel_comp_detail.grab_set() else: messagebox.showwarning(parent=self.frm_child_report, title='No selection', message='You must select one item') def click_view_scenario(self): """ Function activated when 'Scenario detail' button is pressed, it shows the tlevel_detail window showing main information of the selected experimental scenario in trv_available_sc """ if len(self.trv_available_sc.selection()) == 1: self.txt_detail_component['state'] = NORMAL self.txt_detail_component.delete('1.0', 'end-1c') self.txt_detail_component.insert('1.0', 'EXPERIMENTAL SCENARIO TITLE\n{}\n\n' 'DESCRIPTION\n{}\n\n' 'DESIGNERS SCENARIO ASSIGNED: {}\n\n' 'DESIGNERS COMPLETED SCENARIO: {}\n\n' 'DESIGNERS DID NOT COMPLETE SCENARIO: {}\n\n' 'DESIGNERS DID NOT RUN SCENARIO: {}'. format(self.scenario.title, self.scenario.description, self.scenario.info_designers[0], self.scenario.info_designers[1], self.scenario.info_designers[2], self.scenario.info_designers[3])) self.txt_detail_component['state'] = DISABLED self.tlevel_comp_detail.deiconify() self.tlevel_comp_detail.grab_set() else: messagebox.showwarning(parent=self.frm_child_report, title='No selection', message='You must select one item') def click_view_problem(self): """ Function activated when 'Problem detail' button is pressed, it shows the tlevel_detail window showing main information of the selected problem in trv_available_prob """ if len(self.trv_available_prob.selection()) == 1: aux_patterns = '' for item in self.problem.solution.patterns: aux_patterns += '- {}\n'.format(item.get_joined_main_s()) self.txt_detail_component['state'] = NORMAL self.txt_detail_component.delete('1.0', 'end-1c') self.txt_detail_component.insert('1.0', 'PROBLEM BRIEF DESCRIPTION\n{}\n\n' 'DESCRIPTION\n{}\n\n' 'EXPECTED SOLUTION NOTES\n{}\n\n' 'EXPECTED SOLUTION PATTERNS\n{}'. format(self.problem.brief_description, self.problem.description, self.problem.solution.annotations, 'No patterns configured' if aux_patterns == '' else aux_patterns)) self.txt_detail_component['state'] = DISABLED self.tlevel_comp_detail.deiconify() self.tlevel_comp_detail.grab_set() else: messagebox.showwarning(parent=self.frm_child_report, title='No selection', message='You must select one item') def click_view_diagram_sol(self): # Fill summary problem canvas with retrieved image load = Image.open(self.solution.diagram.filename) load = load.resize((500, 500), Image.ANTIALIAS) self.render = ImageTk.PhotoImage(load) self.canvas_expanded.delete() self.solution.diagram.image = self.canvas_expanded.create_image(0, 0, anchor='nw', image=self.render) # and display new image self.tlevel_diagram.deiconify() self.tlevel_diagram.grab_set() def click_csv(self): if len(self.trv_available_exp.selection()) == 1: # Get report in .zip (temporarly) path = askdirectory(title='Select destination folder') # shows dialog box and return the path if path: # Retrieve zip file and create into the selected folder self.directive = Message(action=106, information=[self.experiment.id]) self.connection = self.directive.send_directive(self.connection) report_file = File() report_file.write_permanent_file(self.connection.message.information[0], self.connection.message.information[1], path) messagebox.showinfo(parent=self.frm_child_report, title='Report created', message='Zipped report created: "{}"'.format(report_file.filename)) else: messagebox.showwarning(parent=self.frm_child_report, title='No selection', message='You must select one item') def view_detailed_solution(self, event=None): if len(self.trv_detail_designer.selection()) == 1: id_selected_desig = self.trv_detail_designer.item(self.trv_detail_designer.selection())[ 'text'] # Retrieve id of selected item from TreeView if id_selected_desig != 'X': if self.trv_detail_designer.item(self.trv_detail_designer.selection())['values'][2] != 'X': # Here asks for the sent solution of specific designer self.directive = Message(action=105, information=[int(id_selected_desig), self.problem.id]) self.connection = self.directive.send_directive(self.connection) # Getting assigned patterns in current experimental scenario assigned_patterns = [] for item in self.connection.message.information[4]: for pattern in self.available_patterns: if item == pattern.id: assigned_patterns.append(pattern) chosen_patterns = [] # Getting patterns of sent solution for item in self.connection.message.information[2]: id_pattern = int(item.split('¥')[0]) for pattern in self.available_patterns: if id_pattern == pattern.id: chosen_patterns.append(pattern) # Getting current group for the designer current_group = self.connection.message.information[3] # Creating the auxiliar solution self.solution = Solution(annotations=self.connection.message.information[0], patterns=chosen_patterns, diagram_id=self.connection.message.information[1], connection=self.connection) # Adjust visual components depending on the sent solution self.btn_detail_sol.grid_forget() if self.solution.diagram_id is not None: self.btn_detail_sol.grid(row=0, column=2, pady=10, sticky=E) aux_patterns_assign = '' for item in assigned_patterns: aux_patterns_assign += '- {}\n'.format(item.get_joined_main_s()) aux_patterns_sent_sol = '' for item in self.solution.patterns: aux_patterns_sent_sol += '- {}\n'.format(item.get_joined_main_s()) self.txt_detail_solution['state'] = NORMAL self.txt_detail_solution.delete('1.0', 'end-1c') self.txt_detail_solution.insert('1.0', 'CURRENT PROBLEM\n{}\n\n' 'CURRENT DESIGNER\n{}\n\n' 'ASSIGNED GROUP\n{}\n\n' 'SENT SOLUTION NOTES\n{}\n\n' 'SENT SOLUTION DIAGRAM\n{}\n\n' 'ASSIGNED PATTERNS\n{}\n\n' 'CHOSEN PATTERNS\n{}'. format(self.problem.brief_description, self.trv_detail_designer.item( self.trv_detail_designer.selection())['values'][1], 'Control group' if current_group == 1 else 'Experimental group', self.solution.annotations, 'No diagram in solution' if self.solution.diagram_id is None else 'Click up button to see diagram ^', 'No patterns configured' if aux_patterns_assign == '' else aux_patterns_assign, 'No patterns chosen' if aux_patterns_sent_sol == '' else aux_patterns_sent_sol)) self.txt_detail_solution['state'] = DISABLED self.tlevel_sol_detail.deiconify() self.tlevel_sol_detail.grab_set() else: messagebox.showwarning(parent=self.frm_child_report, title='Wrong selection', message='The selected designer does not have a solution for the current ' 'problem') def clear_components(self, decision=4): if decision > 0: # When selecting an problem form general list for item in self.trv_detail_designer.get_children(): self.trv_detail_designer.delete(item) if decision > 1: # When selecting a scenario form general list for item in self.trv_available_prob.get_children(): self.trv_available_prob.delete(item) for item in self.trv_detail_prob.get_children(): self.trv_detail_prob.delete(item) if decision > 2: # When selecting an experiment form general list for item in self.trv_available_sc.get_children(): self.trv_available_sc.delete(item) for item in self.trv_detail_sc.get_children(): self.trv_detail_sc.delete(item) if decision > 3: # Clearing information from all the treeviews for item in self.trv_available_exp.get_children(): self.trv_available_exp.delete(item) def click_exit_component_det(self): self.tlevel_comp_detail.grab_release() self.tlevel_comp_detail.withdraw() def click_exit_diagram(self): self.tlevel_diagram.grab_release() self.tlevel_diagram.withdraw() def click_exit_solution_det(self): self.tlevel_sol_detail.grab_release() self.tlevel_sol_detail.withdraw()