Exemple #1
0
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')
Exemple #2
0
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)
Exemple #4
0
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()
Exemple #5
0
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]))
Exemple #6
0
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)
Exemple #7
0
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()