def right_frame(parent):
        rf_width = 300
        rf_height = 360
        # right side frame
        frame_right = LabelFrame(
            parent.building_pos_window,
            text="Building Position",
            width=rf_width - 10,
            height=rf_height - 10,
        )

        frame_right.grid_rowconfigure(0, weight=1)
        frame_right.grid_columnconfigure(0, weight=1)
        frame_right.grid_propagate(False)

        canvas_right = Canvas(frame_right)
        canvas_right.grid(row=0, column=0, sticky=N + W)

        # Link a scrollbar to the canvas
        def on_mousewheel(event):
            canvas_right.yview_scroll(int(-1 * (event.delta / 120)), "units")

        def bound_to_mousewheel(event):
            canvas_right.bind_all("<MouseWheel>", on_mousewheel)

        def unbound_to_mousewheel(event):
            canvas_right.unbind_all("<MouseWheel>")

        y_scrollbar = Scrollbar(frame_right,
                                orient="vertical",
                                command=canvas_right.yview)
        y_scrollbar.grid(row=0, column=1, sticky='ns')
        canvas_right.configure(yscrollcommand=y_scrollbar.set)

        inner_frame_right = Frame(canvas_right)
        inner_frame_right.bind('<Enter>', bound_to_mousewheel)
        inner_frame_right.bind('<Leave>', unbound_to_mousewheel)

        canvas_right.create_window((0, 0),
                                   window=inner_frame_right,
                                   anchor='nw')

        idx = 0
        for e_name in BuildingNames:
            building_name_xy_config_frame(
                inner_frame_right, idx, e_name.value,
                parent.bot_building_pos.get(e_name.value, [-1, -1])
                if parent.bot_building_pos is not None else [-1, -1])
            idx = idx + 1

        inner_frame_right.update_idletasks()

        frame_right.config(width=rf_width - 10, height=360 - 10)
        canvas_right.config(width=rf_width - 10,
                            height=360 - 10,
                            scrollregion=canvas_right.bbox("all"))

        frame_right.grid(row=0, column=1, padx=5, pady=5, sticky=N + W)

        return inner_frame_right
Beispiel #2
0
    def config_frame(self):
        frame_canvas = LabelFrame(self,
                                  text='Config',
                                  width=self.windows_size[0],
                                  height=self.windows_size[1] - 200
                                  )
        frame_canvas.grid_rowconfigure(0, weight=1)
        frame_canvas.grid_columnconfigure(0, weight=1)
        frame_canvas.grid_propagate(False)

        # Add a canvas in that frame
        canvas = Canvas(frame_canvas)
        canvas.grid(row=0, column=0, sticky=N+W)

        # Link a scrollbar to the canvas

        def on_mousewheel(event):
            canvas.yview_scroll(int(-1*(event.delta/120)), "units")

        def bound_to_mousewheel(event):
            canvas.bind_all("<MouseWheel>", on_mousewheel)

        def unbound_to_mousewheel(event):
            canvas.unbind_all("<MouseWheel>")

        y_scrollbar = Scrollbar(frame_canvas, orient="vertical", command=canvas.yview)
        y_scrollbar.grid(row=0, column=1, sticky='ns')
        canvas.configure(yscrollcommand=y_scrollbar.set)

        inner_frame = Frame(canvas)
        inner_frame.bind('<Enter>', bound_to_mousewheel)
        inner_frame.bind('<Leave>', unbound_to_mousewheel)

        canvas.create_window((0, 0), window=inner_frame, anchor='nw')

        for i in range(len(atf.bot_config_title_fns)):
            title_fns, sub_fns = atf.bot_config_title_fns[i]
            check = section_frame(
                self,
                inner_frame,
                title_fns,
                sub_fns
            )
            check.grid(row=i, column=0, sticky=N + W)

        inner_frame.update_idletasks()

        frame_canvas.config(width=self.windows_size[0] - 20, height=self.windows_size[1] - 350)
        canvas.config(width=self.windows_size[0] - 20, height=self.windows_size[1] - 350, scrollregion=canvas.bbox("all"))

        return frame_canvas
Beispiel #3
0
class LoadGUI(Frame):
    """Loading frame which allows the users to pick quizzes.
    """
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.grid(row=0, column=0, sticky="nsew")
        self.grid_columnconfigure(0, weight=1)
        self.cover_photo = PhotoImage(file="static/cover.png")
        self.cover_label = Label(self, image=self.cover_photo)
        self.cover_label.grid(row=0, column=0, padx=(20,20), pady=(20,10), sticky="ew")
        self.select_frame = LabelFrame(self, text="Select a quiz")
        self.select_frame.grid(row=1, column=0, padx=(20,20), pady=(10,20), sticky="ew")
        for i in range(0,4):
            self.select_frame.grid_rowconfigure(i, weight=1)
        self.select_frame.grid_columnconfigure(0, weight=4)
        self.select_frame.grid_columnconfigure(1, weight=1)
        self.quiz_list = Listbox(self.select_frame)
        self.quiz_list.grid(row=0, column=0, rowspan=4, padx=(10,10), pady=(10,10), sticky="ew")
        self.start_button = Button(self.select_frame, text="Start quiz", command=self.start_chosen)
        self.start_button.grid(row=0, column=1, padx=(0,10), pady=(10,5), sticky="nsew")
        self.refresh_button = Button(self.select_frame, text="Refresh list", command=self.refresh)
        self.refresh_button.grid(row=1, column=1, padx=(0,10), pady=(5,5), sticky="nsew")
        self.help_button = Button(self.select_frame, text="Help", command=var.HELP_URL)
        self.help_button.grid(row=2, column=1, padx=(0,10), pady=(5,5), sticky="nsew")
        self.quit_button = Button(self.select_frame, text="Quit", command=root.destroy)
        self.quit_button.grid(row=3, column=1, padx=(0,10), pady=(5,10), sticky="nsew")
        self.get_quizzes()

    def get_quizzes(self):
        """[summary]
        """
        self.dir_list = sorted([i[:-5] for i in os.listdir() if i.endswith(".json") and "quiz" in i.lower()])
        for f in self.dir_list:
            self.quiz_list.insert("end", f)

    def refresh(self):
        """[summary]
        """
        self.quiz_list.delete(0, "end")
        self.get_quizzes()

    def start_chosen(self):
        """[summary]
        """
        self.filename = self.quiz_list.get("active") + ".json"
        file_handler.parse_file(self.filename)
        file_handler.parse_leaderboard()
        quiz_gui.add_questions()
        quiz_gui.tkraise()
Beispiel #4
0
 def __init__(self, modelProc, tick):
     self.modelProc = modelProc
     self.tick = tick
     self.queue = modelProc.getQueue()
     # ----------------- Model parameters -----------------
     # Waiting time between two events
     self.refreshRate = DEFAULT_REFRESH_RATE
     # Elapsed time (in number of ticks)
     self.count = 0
     # ------------------------ GUI -----------------------
     # Main window
     self.window = Tk()
     self.window.title("Model Rendering")
     self.window.configure(bg=BG_COLOR)
     self.window.protocol("WM_DELETE_WINDOW", self.onClosing)
     # Main pane
     mainPane = PanedWindow(self.window, orient=HORIZONTAL, bg=BG_COLOR)
     mainPane.pack(side=TOP, expand=Y, fill=BOTH, pady=5, padx=5)
     # Canvas frame
     canvasFrame = LabelFrame(mainPane, text="Rendering", padx=10, pady=10, bg=BG_COLOR)
     mainPane.add(canvasFrame)
     self.canvas = Canvas(canvasFrame, width=CANVAS_X, height=CANVAS_Y, background="white")
     self.canvas.pack()
     # Parameters frame
     paramFrame = LabelFrame(mainPane, text="Simulation parameters",\
     padx=20, pady=20, bg=BG_COLOR)
     mainPane.add(paramFrame)
     # ===> Refresh rate slider
     self.stepVar = DoubleVar(paramFrame, value=DEFAULT_REFRESH_RATE)
     slider = Scale(paramFrame, from_=0, to_=0.5, resolution=0.001, length=350, orient=VERTICAL,\
     variable=self.stepVar, label="# Refresh rate", bg=BG_COLOR, bd=1)
     slider.bind("<ButtonRelease-1>", self.updateRate)
     slider.grid(row=1, column=1)
     # ===> Elapsed time
     self.timeLabel = Label(paramFrame, text="# Elapsed time (hours) :\n0", bg=BG_COLOR)
     self.timeLabel.grid(row=3, column=1)
     # Rows and columns configuration
     paramFrame.grid_columnconfigure(0, weight=1)
     paramFrame.grid_columnconfigure(1, weight=2)
     paramFrame.grid_columnconfigure(2, weight=1)
     paramFrame.grid_rowconfigure(0, weight=1)
     paramFrame.grid_rowconfigure(2, weight=2)
     paramFrame.grid_rowconfigure(4, weight=2)
Beispiel #5
0
    def _setup_widgets(self):
        container = LabelFrame(text=" Output Text ", bg="black", fg='white')
        container.pack(expand=1, fill="both", padx=5, pady=5)
        # create a treeview with dual scrollbars
        ttk.Style().configure("Treeview",
                              background="black",
                              foreground="white",
                              fieldbackground="black")
        self.tree = ttk.Treeview(columns=self.list_header, show="headings")
        self.tree.column('Port', width=0)
        self.tree.column('Status', width=40)
        self.tree.grid(column=0,
                       row=0,
                       sticky='nsew',
                       in_=container,
                       padx=5,
                       pady=5)

        container.grid_columnconfigure(0, weight=1)
        container.grid_rowconfigure(0, weight=1)
Beispiel #6
0
    def __init__(self, thread_cls):
        super().__init__()
        self.window = self
        self.last_request = 0
        self.running = False
        self.thread_cls = thread_cls
        self.img = None
        self.title("HomEMOstasis")

        # our ms azure api key :)
        self.ety_key = "eed879d931a146d1ac9992ce47e71342"
        self.grid()
        self.grid_columnconfigure(0, weight=1)
        self.grid_columnconfigure(1, weight=2)
        self.grid_rowconfigure(4, weight=1)

        self.vid = VideoCapture()

        # Create LabelFrames
        lf_request = LabelFrame(self, text="Control Panel")
        lf_request.grid(row=0, column=0, columnspan=1,
                        sticky=W+E, padx=5, pady=3)
        lf_request.grid_columnconfigure(0, weight=1)
        lf_console = LabelFrame(self, text="Console")
        lf_console.grid(row=4, column=0, columnspan=1,
                        sticky=N+S+W+E, padx=5, pady=3)
        lf_console.grid_columnconfigure(0, weight=1)
        lf_console.grid_rowconfigure(0, weight=1)
        lf_img = LabelFrame(self, text="Webcam View")
        lf_img.grid(row=0, column=1, rowspan=5, sticky=N+S+W+E)
        lf_img.grid_columnconfigure(0, weight=1)
        lf_img.grid_rowconfigure(0, weight=1)

        self.btn_start = Button(lf_request,
                                  text="Start Analysis",
                                  command=self.start_analysis,
                                  state='normal')
        self.btn_start.grid(sticky = 'nsew', row = 0, column = 0,)

        self.btn_stop = Button(lf_request,
                                  text="Stop Analysis",
                                  command=self.stop_analysis,
                                  state='disabled')
        self.btn_stop.grid(sticky = 'nsew', row = 0, column = 1)

        lf_request.grid_columnconfigure(0, weight=1, uniform="group1")
        lf_request.grid_columnconfigure(1, weight=1, uniform="group1")
        lf_request.grid_rowconfigure(0, weight=1)
        
        # Create Output Console
        self.console = ScrolledText(
            lf_console, state='disable', width=60, bg='gray20', fg='white')
        self.console.grid(sticky=N+S+W+E)

        # Create Output Image
        self.plot = ResultImg(lf_img)
        self.plot.grid(sticky=N+S+W+E)

        self.update()
Beispiel #7
0
    def create_single_form(self, tab):
        form = Frame(tab)
        center = LabelFrame(form, width=450, height=250, padx=50, pady=20)
        btm_frame = Frame(form, width=450, height=45, pady=3)

        # layout all of the main containers
        form.pack(fill=tk.BOTH, expand=True)
        center.pack(fill=tk.BOTH, expand=True)
        btm_frame.pack(side=tk.RIGHT, padx=5, pady=5)

        center.grid_propagate(False)
        btm_frame.pack_propagate(False)
        center.grid_rowconfigure(5, pad=30)

        lb_eta = Label(center, text="Percentile for frequency (Eta): ")
        lb_eta.grid(row=0, sticky='W')
        var = tk.DoubleVar()
        sl_eta = Scale(center,
                       variable=var,
                       from_=0,
                       to=1,
                       resolution=0.01,
                       orient=tk.HORIZONTAL,
                       length=140)
        sl_eta.set(0.4)
        sl_eta.grid(row=0, column=1, columnspan=2, padx=5, sticky='W')
        self.single_form.append({'name': 'eta', 'obj': sl_eta})

        lb_epsilon = Label(center, text="Parallelism (Epsilon): ")
        lb_epsilon.grid(row=1, sticky='W')
        var2 = tk.DoubleVar()
        sl_epsilon = Scale(center,
                           variable=var2,
                           from_=0,
                           to=1,
                           resolution=0.01,
                           orient=tk.HORIZONTAL,
                           length=140)
        sl_epsilon.set(0.1)
        sl_epsilon.grid(row=1, column=1, columnspan=2, padx=5, sticky='W')
        self.single_form.append({'name': 'epsilon', 'obj': sl_epsilon})

        lb_gate = Label(center, text="Non-conformances management: ")
        lb_gate.grid(row=2, sticky='W')
        cb_gate = ttk.Combobox(center)
        cb_gate.set('removal')
        cb_gate['values'] = ('removal', 'replacement', 'repair')
        cb_gate.grid(row=2, column=1, padx=5, sticky='W')
        self.single_form.append({'name': 'alg_manag', 'obj': cb_gate})

        lb_pool = Label(center, text="Res. Pool Sim: ")
        lb_pool.grid(row=3, sticky='W')
        var3 = tk.DoubleVar()
        sl_pool = Scale(center,
                        variable=var3,
                        from_=0,
                        to=1,
                        resolution=0.01,
                        orient=tk.HORIZONTAL,
                        length=140)
        sl_pool.set(0.85)
        sl_pool.grid(row=3, column=1, columnspan=2, padx=5, sticky='W')
        self.single_form.append({'name': 'rp_similarity', 'obj': sl_pool})

        lb_gate = Label(center, text="Gateways discovery: ")
        lb_gate.grid(row=4, sticky='W')
        cb_gate = ttk.Combobox(center)
        cb_gate.set('discovery')
        cb_gate['values'] = ('discovery', 'random', 'equiprobable')
        cb_gate.grid(row=4, column=1, padx=5, sticky='W')
        self.single_form.append({'name': 'gate_management', 'obj': cb_gate})

        var4 = tk.BooleanVar()
        ck_semi = ttk.Checkbutton(center, variable=var4, text="Semi-automatic")
        ck_semi.grid(row=5, column=0, padx=5, sticky='W')
        self.single_form.append({'name': 'pdef_method', 'obj': var4})

        # Bottom elements
        b_ok = Button(btm_frame, text="Execute", command=self.execute_single)
        b_ok.grid(row=0, sticky='W')
        b_cancel = Button(btm_frame, text="Back", command=self.back)
        b_cancel.grid(row=0, column=1, sticky='W')

        form.pack(side=tk.TOP, fill=tk.X, padx=5, pady=5)
        return form
Beispiel #8
0
       state="hidden")  # insert a second tab for demo purposes

t1.grid_rowconfigure(
    2, weight=1)  # weight attr is similar to flex:1 in css flexbox
t1.grid_columnconfigure(0, weight=1)

section1 = LabelFrame(t1, text="Team Data")  # tkinter fieldsets
section2 = LabelFrame(t1, text="")
section3 = LabelFrame(t1, text="Team List", bd=2)

section1.grid(row=0, column=0, padx=20, pady=5, sticky="new")
section2.grid(row=1, column=0, padx=20, pady=5, sticky="new")
section3.grid(row=2, column=0, columnspan=4, padx=20, pady=5, sticky="nsew")
""" SECTION 1 - TEAM DATA """

section1.grid_rowconfigure(0, weight=1)
section1.grid_columnconfigure([1, 2], weight=1)

team_label = Label(section1, text='Member', font=('bold', 11))
team_label.grid(row=0, column=0, padx=10, pady=10)
team_text = StringVar()
# below set have assumed for ex. a pc username named fdrandom
# would be the user of F.D. in db Team column and on the tk menu
team_text.set(f"{userPC[0].upper()}.{userPC[1].upper()}.")
# team_text.set to a default value -> team_text.set(TeamPPL[0])
team_dropdown = OptionMenu(section1, team_text, *TeamPPL)  # dropdown menu
# dropdown menu bg and fg colour when user hovers over
team_dropdown['menu'].config(activebackground='#007bff',
                             activeforeground="white")
team_dropdown.grid(row=0, column=1, ipadx=15, padx=6, pady=12, sticky="ew")
trackFaces = tk.Button(frame_track,
                       text="Track Faces",
                       command=TrackImages,
                       font=('times', 15, ' bold '))
trackFaces.grid(row=0, column=0)

takeAttendance = tk.Button(frame_track,
                           text="Take Attendance",
                           command=takeAttendance,
                           font=('times', 15, ' bold '))
takeAttendance.grid(row=0, column=1)

frame_track.grid(row=0, ipady=10, ipadx=10)
# Center buttons in frame
frame_track.grid_rowconfigure(0, weight=1)
frame_track.grid_columnconfigure(0, weight=1)
frame_track.grid_columnconfigure(1, weight=1)

# frame_mainContent ROW 1
frame_addUser = LabelFrame(frame_mainContent, text="Add User")

frame_enterData = Frame(frame_addUser)
# frame_enterData ROW 0
lbl_enterID = tk.Label(frame_enterData,
                       text="Enter ID",
                       font=('times', 15, ' bold '))
lbl_enterID.grid(row=0, column=0, sticky="W")
txt_enterID = tk.Entry(frame_enterData, font=('times', 15, ' bold '))
txt_enterID.grid(row=0, column=1)
clearButton_enterID = tk.Button(frame_enterData,
Beispiel #10
0
    def __init__(self, master, cnf={}, **kw):
        super().__init__(master, cnf, **kw)

        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)
        self.grid_columnconfigure(1, weight=1)
        self.grid_columnconfigure(2, weight=1)

        system_info_frame = LabelFrame(self,
                                       text="System Information",
                                       pady=5,
                                       font=load_font(RelativeSize.normal))
        system_info_frame.grid_rowconfigure(0, weight=1)
        system_info_frame.grid_columnconfigure(0, weight=1)
        system_info_frame.grid(row=0, column=0, sticky="nsew")

        self.system_info_tree = AutosizeTreeview(system_info_frame,
                                                 columns="value")
        self.system_info_tree.heading("#0", text="command")
        self.system_info_tree.column("#0", stretch=True, width=50)
        self.system_info_tree.heading("#1", text="result")
        self.system_info_tree.column("#1", stretch=True, width=50)
        self.system_info_tree.grid(row=0, column=0, sticky="nsew")

        system_info_xscroll = Scrollbar(system_info_frame,
                                        orient="horizontal",
                                        command=self.system_info_tree.xview)
        system_info_yscroll = Scrollbar(system_info_frame,
                                        orient="vertical",
                                        command=self.system_info_tree.yview)
        system_info_xscroll.grid(row=1, column=0, sticky="nsew")
        system_info_yscroll.grid(row=0, column=1, sticky="nsew")
        self.system_info_tree.configure(xscroll=system_info_xscroll.set,
                                        yscroll=system_info_yscroll.set)

        connection_status_frame = LabelFrame(self,
                                             text="Connection Status",
                                             font=load_font(
                                                 RelativeSize.normal))
        connection_status_frame.grid_rowconfigure(0, weight=1)
        connection_status_frame.grid_rowconfigure(1, weight=1)
        connection_status_frame.grid_rowconfigure(2, weight=1)
        connection_status_frame.grid_columnconfigure(0, weight=1)
        connection_status_frame.grid_columnconfigure(1, weight=1)
        connection_status_frame.grid_columnconfigure(2, weight=1)
        connection_status_frame.grid(row=0, column=1, sticky="nsew")

        self.signal_status_bar = Progressbar(connection_status_frame,
                                             orient="vertical",
                                             mode="determinate")
        self.signal_status_bar.grid(row=1, column=1, sticky="nsew")
        self.signal_status_text = Label(connection_status_frame)
        self.signal_status_text.grid(row=1, column=1)

        battery_status_frame = LabelFrame(self,
                                          text="Battery Status",
                                          font=load_font(RelativeSize.normal))
        battery_status_frame.grid_rowconfigure(0, weight=1)
        battery_status_frame.grid_rowconfigure(1, weight=1)
        battery_status_frame.grid_rowconfigure(2, weight=1)
        battery_status_frame.grid_columnconfigure(0, weight=1)
        battery_status_frame.grid_columnconfigure(1, weight=1)
        battery_status_frame.grid_columnconfigure(2, weight=1)
        battery_status_frame.grid(row=0, column=2, sticky="nsew")

        self.battery_status_bar = Progressbar(battery_status_frame,
                                              orient="vertical",
                                              mode="determinate")
        self.battery_status_bar.grid(row=1, column=1, sticky="nsew")
        self.battery_status_text = Label(battery_status_frame)
        self.battery_status_text.grid(row=1, column=1)
Beispiel #11
0
class QuizGUI(Frame):
    """Initializes the GUI for the quiz, along with the implementation of dynamically-created widgets.
    """
    def __init__(self, master=None):
        self.widget_list = [] # List to store dynamic widgets.
        self.image_list = [] # list to store image objects.
        self.button_list = [] # List to store answer buttons.

        Frame.__init__(self, master)
        self.style_manager = ttk.Style()
        self.style_manager.layout("TNotebook.Tab", [])
        self.master.title("Quiz Framework")
        self.master.resizable(False, False)
        self.grid(column=0, row=0, padx=(20,20), pady=(10,20))

        self.menubar = Menu(self)
        self.filemenu = Menu(self.menubar, tearoff=0)
        self.filemenu.add_command(label="Load quiz", command=self.raise_load)
        self.filemenu.add_command(label="Leaderboard", command=leader_gui.show)
        self.filemenu.add_command(label="Exit", command=root.destroy)
        self.menubar.add_cascade(label="Quiz", menu=self.filemenu)
        self.helpmenu = Menu(self.menubar, tearoff=0)
        self.helpmenu.add_command(label="About", command=var.HELP_URL)
        self.menubar.add_cascade(label="Help", menu=self.helpmenu)
        self.master.config(menu=self.menubar)

        self.info_frame = LabelFrame(self, text="Current quiz:")
        self.info_frame.grid(column=0, row=0, padx=(0,10), sticky="nsew")
        self.quiz_name_label = Label(self.info_frame, text="Name:")
        self.quiz_name_label.grid(column=0, row=0, padx=(10,0), pady=(10,0), sticky="w")
        self.quiz_name = Label(self.info_frame, textvariable=var.name)
        self.quiz_name.grid(column=1, row=0, padx=(0,10), pady=(10,0), sticky="w")
        self.quiz_desc_label = Label(self.info_frame, text="Description:")
        self.quiz_desc_label.grid(column=0, row=1, padx=(10,0), pady=(0,10), sticky="nw")
        self.quiz_desc = Label(self.info_frame, textvariable=var.desc, justify="left")
        self.quiz_desc.grid(column=1, row=1, padx=(0,10), pady=(0,10), sticky="w")

        self.stat_frame = LabelFrame(self, text="Statistics:")
        self.stat_frame.grid(column=1, row=0, sticky="nsew", padx=(10,0))
        self.timer_label = Label(self.stat_frame, text="Time:")
        self.timer_label.grid(column=0, row=0, padx=(10,0), pady=(10,0), sticky="w")
        self.timer = Label(self.stat_frame, textvariable=var.time_text)
        self.timer.grid(column=1, row=0, padx=(0,10), pady=(10,0), sticky="w")
        self.score_label = Label(self.stat_frame, text="Correct:")
        self.score_label.grid(column=0, row=1, padx=(10,0), pady=(0,10), sticky="w")
        self.score = Label(self.stat_frame, textvariable=var.correct_text)
        self.score.grid(column=1, row=1, padx=(0,10), pady=(0,10), sticky="w")

        self.quiz_frame = LabelFrame(self, text="Quiz:")
        self.quiz_frame.grid(column=0, row=1, pady=(10,10), columnspan=2, sticky="ew")
        self.quiz_frame.grid_columnconfigure(0, weight=1)
        self.quiz_frame.grid_rowconfigure(0, weight=1)
        self.quiz_notebook = ttk.Notebook(self.quiz_frame)
        self.quiz_notebook.grid(column=0, row=1, padx=(10,10), pady=(10,10), sticky="ew")
        self.add_questions()

        self.options_frame = Frame(self)
        self.options_frame.grid(column=0, row=2, columnspan=2, sticky="ew")
        for i in range(0,3):
            self.options_frame.grid_columnconfigure(i, weight=1)
        self.start_button = Button(self.options_frame, text="Start", command=handler.start_quiz)
        self.start_button.grid(column=0, row=0, ipadx=20, ipady=5, padx=(0,10), sticky="ew")
        self.reset_button = Button(self.options_frame, text="Reset", state="disabled", command=handler.reset_quiz)
        self.reset_button.grid(column=1, row=0, ipadx=20, ipady=5, padx=(0,10), sticky="ew")
        self.skip_button = Button(self.options_frame, text="Skip", command=self.skip)
        self.skip_button.grid(column=2, row=0, ipadx=20, ipady=5, padx=(0,10), sticky="ew")
        self.load_button = Button(self.options_frame, text="Load quiz", command=self.raise_load)
        self.load_button.grid(column=3, row=0, ipadx=20, ipady=5, padx=(0,0), sticky="ew")

    def add_questions(self):
        """Dynamically create widgets based on pre-defined data.
        """
        random.shuffle(var.questions["questions"]) # Shuffling questions
        self.image_list = []
        for q in range(0, len(var.questions["questions"])): # Iterate through the pre-defined list of questions
            random.shuffle(var.questions["questions"][q]["answers"])
            self.question_num = "Question " + str(q+1) + ": " # Question number
            self.current_question = self.question_num + var.questions["questions"][q]["question"] 
            self.current_image = var.questions["questions"][q]["image"]
            self.answer_list = var.questions["questions"][q]["answers"]

            self.question_frame = Frame(self.quiz_notebook)
            self.question_frame.grid_columnconfigure(0, weight=1)
            self.quiz_notebook.add(self.question_frame, text=self.question_num, sticky="nsew")
            self.question_label = Label(self.question_frame, text=self.current_question, wraplength=350)
            self.question_label.grid(column=0, row=0, padx=(10,10), pady=(10,10), sticky="ew")
            if self.current_image != "":
                self.image_obj = PhotoImage(file=self.current_image)
            else:
                self.image_obj = PhotoImage(file="static/blank.png")
            self.image_list.append(self.image_obj)
            self.question_image = Label(self.question_frame, image=self.image_list[q], relief="ridge")
            self.question_image.image = self.image_obj
            self.question_image.grid(column=0, row=1, padx=(10,10), pady=(0,10), sticky="ew")
            for i in enumerate(self.answer_list, 1):
                # Refrain from using lambda to attach a function without initially triggering it,
                # as the argument doesn't get passed until the very last iteration of the for loop.
                self.quiz_answer = Button(self.question_frame, text=i[1]["text"], command=functools.partial(self.ans_check, answer_arg=i[1]["key"], question_idx=q))
                self.button_list.append(self.quiz_answer)
                # Check if the current answer is the last in the list.
                if i[0] % 4 != 0:
                    self.quiz_answer.grid(column=0, row=2+i[0], padx=(10,10), ipady=10, sticky="ew")
                else:
                    self.quiz_answer.grid(column=0, row=2+i[0], padx=(10,10), pady=(0,10), ipady=10, sticky="ew")

    def kill_questions(self):
        """Kill all notebook frames.
        """
        for frame in quiz_gui.quiz_notebook.winfo_children():
            for wdg in frame.winfo_children():
                wdg.destroy()

    def raise_load(self):
        """Raise the loading frame.
        """
        self.load_confirm = simpledialog.messagebox.askyesno("Warning", "Your current progress will not be saved. Do you wish to continue?")
        if self.load_confirm:
            handler.reset_quiz()
            self.kill_questions()
            load_gui.tkraise()

    def ans_check(self, answer_arg:str, question_idx:int):
        """Check the answer by comparing it to the dictionary's answer key.
        """
        handler.check_answers(answer_arg, question_idx)

    def skip(self):
        """Skips the current question
        """
        pass
Beispiel #12
0
class BornDigitalGUI(Frame):
    def __init__(self, master):
        ##### Configure Canvas #####
        Frame.__init__(self, master)
        self.master = master
        self.canvas = Canvas(master, borderwidth=0)
        self.frame = Frame(self.canvas)
        self.canvas.create_window((4,4), window=self.frame, anchor='nw', tags='self.frame')
        self.master.title('Born Digital Accessioner 1.0')
        self.initmenu()
        self.frame.config(bg='gainsboro', highlightthickness=0)
        self.canvas.config(bg='gainsboro', highlightthickness=0)
        self.canvas.grid_rowconfigure(0, weight=1)
        self.canvas.grid_columnconfigure(0, weight=1)
        self.frame.grid_rowconfigure(0, weight=1)
        self.frame.grid_columnconfigure(0, weight=1)
        self.master.grid_rowconfigure(0, weight=1)
        self.master.grid_columnconfigure(0, weight=1)
        self.canvas.grid(row=0, column=0, sticky="nsew")
        self.frame.grid(row=0, column=0, sticky="nsew")

        ##### Execute login process by pressing Enter ####
        self.master.bind('<Return>', self.asloginprocess)
        
        ########### Step 1: Login to ArchivesSpace API ###########
        
        ## Set Step 1 Variable Inputs ##
        self.authenticate = StringVar()
        self.api_url = StringVar()
        self.username = StringVar()
        self.password = StringVar()
        self.login_confirmed = StringVar()
        
        ## Create Step 1 Widgets ##
        
        self.login_labelframe = LabelFrame(self.frame, text='Step 1: Connect to ArchivesSpace', font=('Arial', 14), bg='gainsboro', padx=1, pady=1)
        self.api_url_label = Label(self.login_labelframe, text='ArchivesSpace URL: ', font=('Arial', 13), bg='gainsboro')
        self.username_label = Label(self.login_labelframe, text='ArchivesSpace Username: '******'Arial', 13), bg='gainsboro')
        self.password_label = Label(self.login_labelframe, text='ArchivesSpace Password: '******'Arial', 13), bg='gainsboro')
        self.api_url_entry = Entry(self.login_labelframe, width=32, textvariable=self.api_url, highlightthickness=0)
        self.username_entry = Entry(self.login_labelframe, width=32, textvariable=self.username, highlightthickness=0)
        self.password_entry =Entry(self.login_labelframe, width=32, textvariable=self.password, show='*', highlightthickness=0)
        self.login_confirmed_variable = Label(self.login_labelframe, textvariable=self.login_confirmed, width=25, font=('Arial', 13), bg='gainsboro', highlightthickness=0, anchor='e')
        self.connect_button = Button(self.login_labelframe, text='Connect!',command=self.asloginprocess, width=10, relief=RAISED, bd=1, padx=3, pady=3, highlightthickness=0, cursor="hand1")

        ## Set Set Step 1 Widget Layout ##
        self.login_labelframe.grid(column=0, columnspan=2, sticky="nsew", padx=5, pady=5)
        self.login_labelframe.grid_rowconfigure(0, weight=1)
        self.login_labelframe.grid_columnconfigure(0, weight=1)
        self.api_url_label.grid(column=0, row=2, sticky="nw")
        self.api_url_entry.grid(column=0, row=3, sticky="nw")
        self.username_label.grid(column=0, row=4, sticky="nw")
        self.username_entry.grid(column=0, row=5, sticky="nw")
        self.password_label.grid(column=0, row=6, sticky="nw")
        self.password_entry.grid(column=0, row=7, sticky="nw")
        self.login_confirmed_variable.grid(column=1, row=6, sticky="ns")
        self.connect_button.grid(column=1, row=7, sticky="ne")
        
        ########### Step 2: Select Input CSV ###########

        ## Set Step 2 Variable Inputs ##
        self.csv_filename = StringVar()
        
        ## Create Step 2 Widgets ##
        self.fileselect_labelframe = LabelFrame(self.frame, text='Step 2: Select Input CSV', font=('Arial', 14), bg='gainsboro', highlightthickness=0, padx=1, pady=1)
        self.file_selected_label = Label(self.fileselect_labelframe, text='Selection: ', font=('Arial', 13), anchor='w', bg='gainsboro', highlightthickness=0)
        self.selected_csv_variable = Label(self.fileselect_labelframe, textvariable=self.csv_filename, width=65, font=('Arial', 11), anchor='w', bg='gainsboro', highlightthickness=0)
        self.input_csv_button = Button(self.fileselect_labelframe, text='Select File', command=self.csvbutton, relief=RAISED, bd=1, padx=3, pady=3, highlightthickness=0, cursor="hand1")
        
        ## Set Step 2 Layout ##
        self.fileselect_labelframe.grid(column=0, columnspan=2, sticky="nsew", padx=5, pady=5)  
        self.fileselect_labelframe.grid_rowconfigure(0, weight=1)
        self.fileselect_labelframe.grid_columnconfigure(0, weight=1)
        self.input_csv_button.grid(column=1, row=9, sticky='se')
        self.file_selected_label.grid(column=0, columnspan=1, row=10, sticky='w')
        self.selected_csv_variable.grid(column=0, row=11, columnspan=2, sticky='w')

        ## Set Step _ Variable Inputs ##
        self.csv_output = StringVar()

        ########### Step 3: Choose an Action ###########
        
        ## Create Step 3 Widgets ##
        self.action_labelframe = LabelFrame(self.frame, text='Step 3: Choose Action', font=('Arial', 14), bg='gainsboro', highlightthickness=0, padx=1, pady=1)
        self.create_components_button = Button(self.action_labelframe, text='Create records', width=30, command=self.run_create_script, relief=RAISED, bd=1, padx=3, pady=3, highlightthickness=0, cursor="hand1")
        self.update_components_button =  Button(self.action_labelframe, text='Update records', width=30, command=self.run_update_script, relief=RAISED, bd=1, padx=3, pady=3, highlightthickness=0, cursor="hand1")
        
        ## Set Step 3 Layout ##
        self.action_labelframe.grid(column=0, columnspan=2, sticky="nsew", padx=5, pady=5)
        self.action_labelframe.grid_rowconfigure(0, weight=1)
        self.action_labelframe.grid_columnconfigure(0, weight=1)
        self.create_components_button.grid(row=12, columnspan=2)
        self.update_components_button.grid(row=13, columnspan=2)

        ########### Step 4: Review Output ###########

        ## Set Step 4 Variable Inputs ##
        self.update_attempts = StringVar()
        self.updates_success = StringVar()
        self.elapsed_time = StringVar()
        self.log_file = StringVar()
        self.error_dialog = StringVar()
        self.script_status = StringVar()
        self.parent_id = StringVar()
        self.resource_id = StringVar()
        self.repo_id_no = StringVar()

        ## Create Step 4 Widgets ##
        self.output_labelframe = LabelFrame(self.frame, text='Step 4: Review Output', font=('Arial', 14), bg='gainsboro', highlightthickness=0, padx=1, pady=1)
        self.script_status_variable = Label(self.output_labelframe, textvariable=self.script_status, font=('Arial', 13), anchor='e', bg='gainsboro', highlightthickness=0)
        self.record_updates_attempted_label = Label(self.output_labelframe, text='Record updates attempted: ', width=30, font=('Arial', 13), anchor='w', bg='gainsboro', highlightthickness=0)
        self.record_updates_attempted_variable = Label(self.output_labelframe, textvariable=self.update_attempts, width=30, font=('Arial', 13), anchor='w', bg='gainsboro', highlightthickness=0)
        self.records_updated_successsfully_label = Label(self.output_labelframe, text='Records updated successfully: ', width=30, font=('Arial', 13), anchor='w', bg='gainsboro', highlightthickness=0)
        self.records_updated_successsfully_variable = Label(self.output_labelframe, textvariable=self.updates_success, width=30, font=('Arial', 13), anchor='w', bg='gainsboro', highlightthickness=0)
        self.elapsed_time_label = Label(self.output_labelframe, text='Elapsed time: ', width=30, font=('Arial', 13), anchor='w', bg='gainsboro', highlightthickness=0)
        self.elapsed_time_variable = Label(self.output_labelframe, textvariable=self.elapsed_time, width=30, font=('Arial', 13), anchor='w', bg='gainsboro', highlightthickness=0)
        self.view_output_file_button = Button(self.output_labelframe, text='Open Output File', command=self.opencsvoutput, relief=RAISED, bd=1, padx=3, pady=3, highlightthickness=0, cursor="hand1")
        self.view_error_log_button = Button(self.output_labelframe, text='Open Log', command=self.openerrorlog, relief=RAISED, bd=1, padx=3, pady=3, highlightthickness=0, cursor="hand1")
        self.view_url_button = Button(self.output_labelframe, text='Open in ArchivesSpace', command=self.openparent_record, relief=RAISED, bd=1, padx=3, pady=3, highlightthickness=0, cursor="hand1")

        ## Set Step 5 Layout ##    
        self.output_labelframe.grid(column=0, columnspan=2, sticky="nsew", padx=5, pady=5)   
        self.output_labelframe.grid_rowconfigure(0, weight=1)
        self.output_labelframe.grid_columnconfigure(0, weight=1)
        self.script_status_variable.grid(column=1, row=14, sticky='e')
        self.record_updates_attempted_label.grid(column=0, row=15)
        self.records_updated_successsfully_label.grid(column=0, row=16)
        self.elapsed_time_label.grid(column=0, row=17)
        self.record_updates_attempted_variable.grid(column=1, row=15, sticky='w')
        self.records_updated_successsfully_variable.grid(column=1, row=16, sticky='w')
        self.elapsed_time_variable.grid(column=1, row=17, sticky='w')     
        self.view_output_file_button.grid(column=1, row=18, sticky="ne")
        self.view_error_log_button.grid(column=1, row=19, sticky="ne")
        self.view_url_button.grid(column=1, row=20, sticky="ne")
        
        ## Clear Inputs, Help Buttons
        
        self.clear_labelframe = LabelFrame(self.frame, text=None, bg='gainsboro', highlightthickness=0, padx=1, pady=1)
        self.clear_labelframe.grid(column=0, columnspan=2, sticky="nsew", padx=5, pady=5)
        self.clear_labelframe.grid_rowconfigure(0, weight=1)
        self.clear_labelframe.grid_columnconfigure(0, weight=1)
        self.clear_all_inputs_button = Button(self.clear_labelframe, text='Clear Inputs', command=self.clear_inputs, relief=RAISED, bd=1, padx=5, pady=5, highlightthickness=0, cursor="hand1")
        self.clear_all_inputs_button.grid(column=0, row=21)
        
        #Initiates error logging
        self.error_log()
   
    ####### Functions #########
    
    #initializes file menu - see https://stackoverflow.com/questions/34442626/why-is-the-menu-not-showing-on-my-tkinter-gui/34442773
    def initmenu(self):
        menubar = Menu(self.master)
        self.master.config(menu=menubar)
        filemenu = Menu(menubar)
        filemenu.add_command(label='Help', command=self.new_window)
        filemenu.add_command(label='Template', command=self.open_template)
        filemenu.add_command(label="Exit", command=self.client_exit)
        menubar.add_cascade(label="File", menu=filemenu)
    
    #Opens the help file in a new window
    def new_window(self):
        self.newwindow = Toplevel(self.master)
        self.newwindow.title('Born-Digital Accessioner Help')
        f = open('./files/bd_accessioner_help.txt', 'r', encoding='utf-8')
        self.textbox = Text(self.newwindow, width=115)
        self.textbox.pack(side='top', fill='both', expand=True)
        self.textbox.insert(0.0, f.read())
        self.textbox.config(state=DISABLED, wrap=WORD)
        self.textbox.grid_rowconfigure(0, weight=1)
        self.textbox.grid_columnconfigure(0, weight=1)
        
    #exits program
    def client_exit(self):
        self.quit()
    
    #opens the born-dig-accessioner template in the system's default program
    def open_template(self):
        #Open template file
        if sys.platform == "win32":
            os.startfile('./files/Template_Digital_Accessioning_Service_Metadata_102017.xlsx')
        else:
            opener = "open" if sys.platform == "darwin" else "xdg-open"
            subprocess.call([opener, './files/Template_Digital_Accessioning_Service_Metadata_102017.xlsx'])
        
    #logs in to ArchivesSpace API
    def asloginprocess(self, event=None):
        try:
            #basic/imperfect check for improperly formatted URLs
            urlcheck = re.compile(
                r'^https?://'
                r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?|'
                r'localhost|'
                r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'
                r'(?::\d+)?'
                r'(?:/?|[/?]\S+)$', re.IGNORECASE)
            #if URL field is empty; missing field error checks may be obsolete now but I'm leaving it in because the URL checks may not be perfect
            if self.api_url.get() == '':
                self.login_confirmed.set('Missing value, try again')
            #empty username field
            if self.username.get() == '':
                self.login_confirmed.set('Missing value, try again')
            #empty password field
            if self.password.get() == '':
                self.login_confirmed.set('Missing value, try again')
            #uses reg ex above to check formulation of URL; may not be perfect but anything it misses gets caught later 
            if not re.match(urlcheck, self.api_url.get()):
                self.login_confirmed.set('Invalid URL, try again')
            else:
                if self.api_url.get().endswith('/'):
                    self.api_url.set(self.api_url.get() + 'api')
                else:
                    self.api_url.set(self.api_url.get() + '/api')
                #self.api_url.set(self.api_url.get())
                auth = requests.post(self.api_url.get()+'/users/'+self.username.get()+'/login?password='******'error' in auth.keys():
                    self.login_confirmed.set('Login failed, try again')
                elif 'session' in auth.keys():
                    session = auth["session"]
                    h = {'X-ArchivesSpace-Session':session, 'Content_Type': 'application/json'}
                    self.login_confirmed.set('Login successful!')
                    self.authenticate.set(h)
                    return h
        #this captures a URL that is valid but not correct, plus any other errors
        except Exception:
            self.login_confirmed.set('Error, check login info and try again') 
    
    #gets headers without logging in to API again - a bit of a hack with the JSON loads (bc the StringVar doesn't return key/value pair), but it works for now
    def get_headers(self):
        headers_string = self.authenticate.get()
        if self.authenticate.get() == '':
            messagebox.showerror('Error!', 'Please log in to the ArchivesSpace API')
            return
        else:
            valid_json = headers_string.replace("'", "\"")
            headers_json = json.loads(valid_json)
            return headers_json
    
    #opens CSV
    def opencsv(self):
        filename = self.csv_filename.get()
        if self.csv_filename.get() == '':
            messagebox.showinfo('Error!', 'Please choose an input CSV')
            return
        else:
            try:
                file = open(filename, 'r', encoding='utf-8', errors='replace')
                csvin = csv.reader(file)
                #Skips first two rows
                next(csvin, None)
                next(csvin, None)
                return csvin
            except:
                problem = messagebox.showerror('Error', 'Could not open CSV file.') 
                logging.exception('Error: ')
                return
    
    def outputcsv(self):
        filename = self.csv_filename.get()
        newname = filename.rsplit(".", 1)[0]
        if self.csv_filename.get() == '':
            messagebox.showinfo('Error!', 'Please choose an input CSV')
            return
        else:
            c = open(newname + '_outfile.csv', 'a', encoding='utf-8', newline='')
            csvoutputfile = newname + '_outfile.csv'
            self.csv_output.set(str(csvoutputfile))
            writer = csv.writer(c)
            return (c, writer)
        
    def timer(self, start):
        elapsedTime = time.time() - start
        m, s = divmod(elapsedTime, 60)
        h, m = divmod(m, 60)
        self.elapsed_time.set('%d:%02d:%02d' % (h, m, s))

    #gets a list of repositories
    def repos(self, header_value):
        repo_list = requests.get(self.api_url.get() + '/repositories', headers=header_value).json()
        repo_d = {}
        for repo in repo_list:
            if repo['repo_code'] not in repo_d:
                repo_d[repo['repo_code']] = repo['uri'][14:]
        return repo_d 
    
    #the ao_id here is the parent archival object ID       
    def create_child_component(self, header_value, repo_num, ao_id, unit_id, extent_type, ao_title, container):
        ''''This function creates a new archival component, based on the data in the born-digtial accessioning worksheet'''
        #First, check if there is a value in the top container field. There won't always be one.
        if container != '':
            try:
                #form a new child component using data from the DAS spreadsheet
                child_component = {"publish": True, "title": ao_title, "level": "item",
                         "component_id": unit_id, "jsonmodel_type": "archival_object","linked_events": [],
                         "extents": [{"number": '1',
                                      "portion": "whole",
                                      "extent_type": extent_type,
                                      "jsonmodel_type": "extent"}],
                         "instances": [{"instance_type": 'mixed_materials',
                                        "jsonmodel_type": 'instance',
                                        "sub_container": {"jsonmodel_type": 'sub_container',
                                                          "top_container": {"ref": container}
                                                          }
                                        }
                                       ],
                        "resource": {"ref": '/repositories/'+repo_num+'+/resources/'+self.resource_id.get()},
                        "parent": {"ref": '/repositories/'+repo_num+'/archival_objects/'+ao_id}}                      
            except Exception as exc:
                logging.exception('Error: ')
                #Do I want this here or do I want to continue when something goes wrong?
                messagebox.showerror('Error!', 'Something went wrong. Please check error log.')
                return
        #if there is no value in the top container field of the DAS spreadsheet, create a child component without a top container
        else:
            child_component = {"publish": True, "title": ao_title, "level": "item",
                     "component_id": unit_id, "jsonmodel_type": "archival_object","linked_events": [],
                     "extents": [{ "number": '1', "portion": "whole", "extent_type": extent_type, "jsonmodel_type": "extent"}],
                     "resource": {"ref": '/repositories/'+repo_num+'+/resources/'+self.resource_id.get()},
                     "parent": {"ref": '/repositories/'+repo_num+'/archival_objects/'+ao_id}}
        #convert the data back into JSON
        child_component_data = json.dumps(child_component)      
        #Post the child archival object
        child_post = requests.post(self.api_url.get()+'/repositories/'+repo_num+'/archival_objects',headers=header_value,data=child_component_data).json()
        return child_post
    
    #Don't use all of those arguments,but need them to make action() work - can I use ***kwargs in the action part?); or default arguments
    def update_child_component(self, header_value, repo_num, ao_id, unit_id, extent_type, ao_title=None, container=None):
        #as of right now this function leaves the ArchivesSpace title intact, but could be modified to take title from spreadsheet
        component_json = requests.get(self.api_url.get()+'/repositories/'+repo_num+'/archival_objects/'+ao_id,headers=header_value).json()
        #updates component ID
        component_json['component_id'] = unit_id
        #updates extent
        component_json['extents']= [{ "number": '1', "portion": "whole", "extent_type": extent_type, "jsonmodel_type": "extent"}]
        component_data = json.dumps(component_json)
        component_post = requests.post(self.api_url.get()+'/repositories/'+repo_num+'/archival_objects/'+ao_id,headers=header_value,data=component_data).json()
        return component_post
    
    def create_event (self, header_value, user, ao_id, repo_num, event_type, outcome_value, date_value, note_value):
        '''This function creates an event in ASpace, based on the four possible parameters provided in the born-digital accessioning worksheet'''
        agent_authorizor = user['agent_record']['ref']
        # Get the event type
        event_type = event_type.lower()
        # Get the event outcome
        outcome_value = outcome_value.lower()
        # Get the event date - add a check so that if there's only 2 digits for YY make it YYYY
        if date_value != '':
            if '-' in date_value:
                date_value = date_value.replace('-', '/')
            if date_value[-4:].isdigit():
                date_value = datetime.datetime.strptime(date_value, '%m/%d/%Y').strftime('%Y-%m-%d')
            else:
                date_value = datetime.datetime.strptime(date_value, '%m/%d/%y').strftime('%Y-%m-%d')
        event = {"event_type": event_type, "jsonmodel_type": "event",
                 "outcome": outcome_value,
                 "outcome_note": note_value,
                 "linked_agents": [{ "role": "authorizer", "ref": agent_authorizor }],
                 "linked_records": [{ "role": "source", "ref": '/repositories/'+repo_num+'/archival_objects/'+ao_id }],
                 "date": { "begin": date_value, "date_type": "single", "label": "event", "jsonmodel_type": "date" }}    
        # Post that event
        event_post = requests.post(self.api_url.get()+'/repositories/'+repo_num+'/events',headers=header_value,json=event).json()
        logging.debug(str(event_post))
        return event_post

    def get_top_containers(self, csv_var, repo_dictionary, header_value):
        logging.debug('Setting parent ID')
        #takes the first parent URL and sets it as the parent
        self.parent_id.set(csv_var[0][2].rpartition("_")[2])
        logging.debug(self.parent_id.get())
        #this gets a list of top containers for the parent component - assumes there will only be one parent...is this true??
        parent_component = requests.get(self.api_url.get()+'/repositories/'+repo_dictionary.get(csv_var[0][0])+'/archival_objects/'+self.parent_id.get(),headers=header_value).json()
        tc_list = [instance['sub_container']['top_container']['ref'] for instance in parent_component['instances']]        
        tuplelist = []
        for tc_uri in tc_list:
            top_container = requests.get(self.api_url.get() + tc_uri, headers=header_value).json()
            tuplelist.append((top_container['uri'], top_container['indicator']))
        return tuplelist

    #this function runs when either the create or update button is pushed. When the create button is pressed, the action variable takes
    #on the value of the create function, and when the update button is pressed the action variable takes the value of the update function
    def process_file(self, action):
        #Initiates the confirmation dialog
        go = self.areyousure()
        if go == True:
            #captures start time
            starttime = time.time()
            headers = self.get_headers()
            if headers != None:
                #Gets current user - Kevin has proposed changing this to accept a user besides the current user
                current_user = requests.get(self.api_url.get() + '/users/current-user', headers=headers).json()
                repo_dict = self.repos(headers)
                csvfile = self.opencsv()
                csvlist = [row for row in csvfile]
                #takes the resource id and sets it as a StringVar
                logging.debug('Setting resource ID')
                if '/#' in str(csvlist[0][2]):
                    self.resource_id.set(csvlist[0][2].partition('/#')[0].rpartition('/')[2])
                else:
                    self.resource_id.set(csvlist[0][2].partition('#')[0].rpartition('/')[2])
                logging.debug(self.resource_id.get())
                #see if this works - and see what happens when you set Open in ArchivesSpace URL
                if action == self.create_child_component:
                    tc_indicator_list = self.get_top_containers(csvlist, repo_dict, headers)
                if csvlist != None:
                    x = 0
                    fileobject, csvoutfile = self.outputcsv()
                    try:
                        for i, row in enumerate(csvlist, 1):
                            logging.debug('Working on row ' + str(i))                      
                            #should be a better way to skip empty/invalid rows, but i've added this for now - CHANGE THIS!!!!
                            if row[0] in repo_dict:
                                # save the original row length - used to get event data later on
                                original_row_length = len(row)
                                # Getting data from CSV file
                                repo = repo_dict.get(row[0])
                                parent_ao_id = str(row[2]).rpartition("_")[2]
                                #if calling the update component script, will set the URL as the most recently updated record - 
                                #this is for the Open in ArchivesSpace button
                                if action == self.update_child_component:
                                    self.parent_id.set(parent_ao_id)
                                #gets the title of the ao, accounting for any HTML that might be present
                                title = cgi.escape(row[3])
                                component_id = row[4]
                                extent = row[5]       
                                top_container = row[6]
                                if top_container != '':
                                    logging.debug('Matching top_containers')
                                    for uri, indicator in tc_indicator_list:
                                        if uri != None:
                                            if indicator == top_container:
                                                top_container = uri
                                        else:
                                            #should continue with script or no??
                                            logging.debug('uri == None')
                                #this runs either the create archival objects or update archival objects script, and returns the result
                                logging.debug('Calling action function')
                                updated_component = action(headers, repo, parent_ao_id, component_id, extent, title, top_container)
                                logging.debug('Finishing action function')
                                if updated_component != None:
                                    if 'uri' in updated_component: 
                                        updated_component_uri = updated_component['uri']
                                        row.append(updated_component_uri)
                                        #creating events based on the rows in the spreadsheet
                                        if original_row_length > 9 and row[8] != '':
                                            new_event = self.create_event(headers, current_user, updated_component_uri, repo, row[8], row[9], row[10], cgi.escape(row[11]))
                                            row.append(new_event['uri'])
                                        if original_row_length > 13 and row[14] != '':
                                            new_event = self.create_event(headers, current_user, updated_component_uri, repo, row[12], row[13], row[14], cgi.escape(row[15]))
                                            row.append(new_event['uri'])
                                        if original_row_length > 17 and row[16] != '':
                                            new_event = self.create_event(headers, current_user, updated_component_uri, repo, row[16], row[17], row[18], cgi.escape(row[19]))
                                            row.append(new_event['uri'])
                                        if original_row_length > 21 and row[20] != '':
                                            new_event = self.create_event(headers, current_user, updated_component_uri, repo, row[20], row[21], row[22], cgi.escape(row[23]))
                                            row.append(new_event['uri'])
                                        x = self.process_results(updated_component, x)
                                        csvoutfile.writerow(row)
                                    #this catches most errors related to failed posts.
                                    else:
                                        logging.debug('Error: ' + str(updated_component))
                                        csvoutfile.writerow(row)
                                elif updated_component == None:
                                    logging.debug('Component did not create/update')
                                    csvoutfile.writerow(row)
                    except:
                        logging.exception('Error: ')
                        csvoutfile.writerow(row)
                        #this will stop the script - should I have it continue instead??
                        #messagebox.showerror('Error!', 'Something went wrong! Check logs!')
                        #return
                    self.update_attempts.set(str(i))
                    self.updates_success.set(str(x))
                    self.timer(starttime)
                    #add logging here
                    logging.debug('Update attempts: ' + str(i))
                    logging.debug('Updated successfully: ' + str(x))
                    logging.debug('Elapsed time: ' + self.elapsed_time.get())
                    #change this so that it's inside the loop
                    done = self.script_finished()
                    fileobject.close()
                else:
                    return
            else:
                return
        else:
            return
    
    #connected to "create child component" button
    def run_create_script(self):
        self.process_file(self.create_child_component)
    
    #connected to "update child component" button
    def run_update_script(self):
        self.process_file(self.update_child_component)
  
  #Initiate logging - is this all I need? See logging cookbook in Python docs  
    def error_log(self):
        #make sure this works on all systems...add another temp folder for pre-Windows 10?
        if sys.platform == "win32":
            self.log_file.set('\\Windows\\Temp\\error_log.log')
        else:
            self.log_file.set('/tmp/error_log.log')
        #Basic logging config
        logging.basicConfig(filename=self.log_file.get(), level=logging.DEBUG,
                            format='%(asctime)s %(levelname)s %(name)s %(message)s')

    def process_results(self, jsonname, counter):
        for key, value in jsonname.items():
            if key == 'status':
                counter +=1
                return counter
            if key == 'error':
                logging.debug(str(datetime.datetime.now()))
                logging.debug(str(jsonname.get('error')))

### WIDGET FILE HANDLING ###

    #File open dialog for input CSV button widget
    def csvbutton(self):
        filename = filedialog.askopenfilename(parent=self.frame)
        self.csv_filename.set(str(filename))
        return filename
    
    #opens csv output file via button widget
    def opencsvoutput(self):
        filename = self.csv_output.get()
        if sys.platform == "win32":
            os.startfile(filename)
        else:
            opener = "open" if sys.platform == "darwin" else "xdg-open"
            subprocess.call([opener, filename])
    
    #opens program log via button widget - will this work if there is no log?
    def openerrorlog(self):
        #filename = self.log_file.get()
        if sys.platform == "win32":
            try:
                os.startfile('\\Windows\\Temp\\error_log.log')
            except:
                messagebox.showerror('Error!', 'Error log does not exist')
        else:
            opener = "open" if sys.platform == "darwin" else "xdg-open"
            try:
                subprocess.call([opener, '/tmp/error_log.log'])
            except:
                messagebox.showerror('Error!', 'Error log does not exist')
    
    #Opens the parent record in ArchivesSpace staff interface via button widget
    def openparent_record(self):
        #this is where I could use the resource ID
        url_end = self.parent_id.get()
        resource = self.resource_id.get()
        get_api = self.api_url.get()
        base_url = get_api[:-3]
        #add something here to make sure there are enough/not to many forward slashes...still works but doesn't look right
        full_url = base_url + '/resources/' + resource + '#tree::archival_object_' + url_end
        if full_url[-1].isdigit() :
            try:
                webbrowser.open(full_url, new=2)
            except:
                messagebox.showerror('Error!', '\n                     Invalid URL')
        else:
            if 'https' in base_url:
                webbrowser.open(base_url, new=2)
            else:
                messagebox.showerror('Error!', '\n                     Invalid URL')
  
    #message box confirming actions, that script is about run
    def areyousure(self):
        result = messagebox.askyesno('Are you sure?', '\n      Click YES to proceed, NO to cancel')
        if result == True:
            self.script_status.set('...Updates in progress...')
            self.script_status.get()
        if result == False:
            false = messagebox.showinfo('Updates Canceled', '\n\n      Press OK to return to menu')
        return result
        
    #Show script finished message on frame
    def script_finished(self):
    #    box = messagebox.showinfo('Done!', 'Script finished. Check outfile for details')
        self.script_status.set('Updates finished!')
        self.script_status.get()
    
    #Clear all GUI inputs - start fresh
    def clear_inputs(self):
        r = messagebox.askyesno('Are you sure?', '\nClick YES to clear inputs, NO to cancel')
        if r == True:
            self.api_url.set('')
            self.username.set('')
            self.password.set('')
            self.login_confirmed.set('')
            self.csv_filename.set('')
            self.update_attempts.set('')
            self.updates_success.set('')
            self.elapsed_time.set('')
            self.script_status.set('')
            self.parent_id.set('')
        else:
            return    
Beispiel #13
0
def openaboutwindow(main_root_title):
    global about_window

    # Defines the path to config.ini and opens it for reading/writing
    config_file = 'Runtime/config.ini'  # Creates (if doesn't exist) and defines location of config.ini
    config = ConfigParser()
    config.read(config_file)

    try:  # If "About" window is already opened, display a message, then close the "About" window
        if about_window.winfo_exists():
            messagebox.showinfo(
                title=f'"{about_window.wm_title()}" Info!',
                parent=about_window,
                message=
                f'"{about_window.wm_title()}" is already opened, closing window instead'
            )
            about_window.destroy()
            return
    except NameError:
        pass

    def about_exit_function():  # Exit function when hitting the 'X' button
        func_parser = ConfigParser()
        func_parser.read(config_file)
        if func_parser['save_window_locations'][
                'about'] == 'yes':  # If auto save position on close is checked
            try:
                if func_parser['save_window_locations'][
                        'about position'] != about_window.geometry():
                    func_parser.set('save_window_locations', 'about position',
                                    about_window.geometry())
                    with open(config_file, 'w') as configfile:
                        func_parser.write(configfile)
            except (Exception, ):
                pass

        about_window.destroy()  # Close window

    about_window = Toplevel()
    about_window.title('About')
    about_window.configure(background="#434547")
    if config['save_window_locations']['about position'] == '' or config[
            'save_window_locations']['about'] == 'no':
        window_height = 650
        window_width = 720
        screen_width = about_window.winfo_screenwidth()
        screen_height = about_window.winfo_screenheight()
        x_coordinate = int((screen_width / 2) - (window_width / 2))
        y_coordinate = int((screen_height / 2) - (window_height / 2))
        about_window.geometry("{}x{}+{}+{}".format(window_width, window_height,
                                                   x_coordinate, y_coordinate))
    elif config['save_window_locations']['about position'] != '' and config[
            'save_window_locations']['about'] == 'yes':
        about_window.geometry(
            config['save_window_locations']['about position'])
    about_window.resizable(False, False)
    about_window.protocol('WM_DELETE_WINDOW', about_exit_function)

    about_window.grid_columnconfigure(0, weight=1)

    detect_font = font.nametofont(
        "TkDefaultFont")  # Get default font value into Font object
    set_font = detect_font.actual().get("family")

    about_information_frame = LabelFrame(about_window,
                                         text=' About ',
                                         labelanchor="nw")
    about_information_frame.grid(column=0,
                                 row=0,
                                 columnspan=1,
                                 padx=5,
                                 pady=(0, 3),
                                 sticky=N + S + E + W)
    about_information_frame.configure(fg="#3498db",
                                      bg="#434547",
                                      bd=3,
                                      font=(set_font, 10, "bold"))
    about_information_frame.grid_rowconfigure(0, weight=1)
    about_information_frame.grid_columnconfigure(0, weight=1)

    about_window_text = Text(about_information_frame,
                             background="#434547",
                             foreground="white",
                             relief=FLAT,
                             height=10)
    about_window_text.pack()
    about_window_text.insert(INSERT, f"{main_root_title}\n")
    about_window_text.insert(INSERT, "\n")
    about_window_text.insert(
        INSERT,
        "Development: jlw4049\n\nContributors: BassThatHertz, aaronrausch")
    about_window_text.insert(INSERT, "\n\n")
    about_window_text.insert(
        INSERT,
        "Power audio encoding GUI, that mostly uses FFMPEG at the heart. \n")
    about_window_text.configure(state=DISABLED)

    about_information_frame = LabelFrame(about_window,
                                         text=' License ',
                                         labelanchor="nw")
    about_information_frame.grid(column=0,
                                 row=1,
                                 columnspan=1,
                                 padx=5,
                                 pady=(0, 3),
                                 sticky=N + S + E + W)
    about_information_frame.configure(fg="#3498db",
                                      bg="#434547",
                                      bd=3,
                                      font=(set_font, 10, "bold"))
    about_information_frame.grid_rowconfigure(0, weight=1)
    about_information_frame.grid_columnconfigure(0, weight=1)

    license_text = """
    Copyright (c) 2012-2022 Scott Chacon and others

    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
    "Software"), to deal in the Software without restriction, including
    without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to
    permit persons to whom the Software is furnished to do so, subject to
    the following conditions:
    
    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.
    
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    """

    about_window_license = Text(about_information_frame,
                                background="#434547",
                                foreground="white",
                                relief=FLAT)
    about_window_license.pack(anchor='center')
    about_window_license.insert(INSERT, license_text)
    about_window_license.configure(state=DISABLED)
def show_streams_mediainfo_function(x):  # Stream Viewer
    global stream_win_text_area, exit_stream_window, stream_window
    video_input = pathlib.Path(x)  # "x" is passed through from main GUI

    # Defines the path to config.ini and opens it for reading/writing
    config_file = 'Runtime/config.ini'  # Creates (if it doesn't exist) and defines location of config.ini
    config = ConfigParser()
    config.read(config_file)

    detect_font = font.nametofont("TkDefaultFont")  # Get default font value into Font object
    set_font = detect_font.actual().get("family")
    # set_font_size = detect_font.actual().get("size")

    try:
        stream_win_text_area.config(state=NORMAL)
        stream_win_text_area.delete(1.0, END)
    except (NameError, TclError):
        stream_window = Toplevel()
        stream_window.title("Audio Streams")
        stream_window.configure(background="#434547")
        stream_window.resizable(False, False)  # Disable resize of this window
        if config['save_window_locations']['audio window - view streams - position'] != '' and \
                config['save_window_locations']['audio window - view streams'] == 'yes':
            stream_window.geometry(config['save_window_locations']['audio window - view streams - position'])
        stream_window.protocol('WM_DELETE_WINDOW', exit_stream_window)
        stream_window.grid_columnconfigure(0, weight=1)
        stream_window.grid_rowconfigure(0, weight=1)

        stream_window_frame = LabelFrame(stream_window, text=' Audio Streams ', labelanchor="n")
        stream_window_frame.grid(column=0, row=0, columnspan=1, padx=5, pady=(0, 3), sticky=N + S + E + W)
        stream_window_frame.configure(fg="#3498db", bg="#434547", bd=3, font=(set_font, 10, "bold"))
        stream_window_frame.grid_rowconfigure(0, weight=1)
        stream_window_frame.grid_columnconfigure(0, weight=1)

        stream_win_text_area = scrolledtext.ScrolledText(stream_window_frame, width=80, height=25, tabs=10, spacing2=3,
                                                         spacing1=2, spacing3=3)
        stream_win_text_area.config(bg='black', fg='#CFD2D1', bd=8)
        stream_win_text_area.grid(column=0, pady=5, padx=5, sticky=N + E + S + W)

    character_space = 30  # Can be changed to adjust space of all items in the list automatically
    media_info = MediaInfo.parse(video_input)  # Uses pymediainfo to get information for track selection
    for track in media_info.tracks:  # For loop to loop through mediainfo tracks
        # Formatting --------------------------------------------------------------------------------------------------
        if track.track_type == 'Audio':  # Only grab audio track information
            if str(track.stream_identifier) != 'None':  # Gets stream #
                audio_track_id_space = 'Track#' + ' ' * int(f'{character_space - len("Track#")}')
                audio_track_id = audio_track_id_space + f': {str(int(track.stream_identifier) + 1)}\n'
            else:
                audio_track_id = ''
            if str(track.format) != 'None':  # Gets format string of tracks (aac, ac3 etc...)
                audio_format_space = 'Codec' + ' ' * int(f'{character_space - len("Codec")}')
                audio_format = audio_format_space + f": {str(track.commercial_name)} - ({str(track.format).lower()})\n"
            else:
                audio_format = ''
            if str(track.channel_s) != 'None':  # Gets audio channels of input tracks
                audio_channel_space = 'Channels' + ' ' * int(f'{character_space - len("Channels")}')
                if str(track.channel_s) == '8':
                    show_channels = '7.1'
                elif str(track.channel_s) == '6':
                    show_channels = '5.1'
                elif str(track.channel_s) == '3':
                    show_channels = '2.1'
                else:
                    show_channels = str(track.channel_s)
                audio_channels = audio_channel_space + f": {show_channels} - {str(track.channel_layout)}\n"
            else:
                audio_channels = ''
            if str(track.bit_rate_mode) != 'None':  # Gets audio bit rate mode
                audio_bitrate_mode_space = 'Bit rate mode' + ' ' * int(f'{character_space - len("Bit rate mode")}')
                if str(track.other_bit_rate_mode) != 'None':  # Get secondary string of audio bit rate mode
                    audio_bitrate_mode = audio_bitrate_mode_space + f": {str(track.bit_rate_mode)} / " \
                                                                    f"{str(track.other_bit_rate_mode[0])}\n"
                else:
                    audio_bitrate_mode = audio_bitrate_mode_space + f": {str(track.bit_rate_mode)}\n"
            else:
                audio_bitrate_mode = ''
            if str(track.other_bit_rate) != 'None':  # Gets audio bit rate of input tracks
                audio_bitrate_space = 'Bit rate' + ' ' * int(f'{character_space - len("Bit rate")}')
                audio_bitrate = audio_bitrate_space + f": {str(track.other_bit_rate[0])}\n"
            else:
                audio_bitrate = ''
            if str(track.other_language) != 'None':  # Gets audio language of input tracks
                audio_language_space = 'Language' + ' ' * int(f'{character_space - len("Language")}')
                audio_language = audio_language_space + f": {str(track.other_language[0])}\n"
            else:
                audio_language = ''
            if str(track.title) != 'None':  # Gets audio title of input tracks
                audio_title_space = 'Title' + ' ' * int(f'{character_space - len("Title")}')
                if len(str(track.title)) > 40:  # Counts title character length
                    audio_title = audio_title_space + f": {str(track.title)[:40]}...\n"  # If title > 40 characters
                else:
                    audio_title = audio_title_space + f": {str(track.title)}\n"  # If title is < 40 characters
            else:
                audio_title = ''
            if str(track.other_sampling_rate) != 'None':  # Gets audio sampling rate of input tracks
                audio_sampling_rate_space = 'Sampling Rate' + ' ' * int(f'{character_space - len("Sampling Rate")}')
                audio_sampling_rate = audio_sampling_rate_space + f": {str(track.other_sampling_rate[0])}\n"
            else:
                audio_sampling_rate = ''
            if str(track.other_duration) != 'None':  # Gets audio duration of input tracks
                audio_duration_space = 'Duration' + ' ' * int(f'{character_space - len("Duration")}')
                audio_duration = audio_duration_space + f": {str(track.other_duration[0])}\n"
            else:
                audio_duration = ''
            if str(track.delay) != 'None':  # Gets audio delay of input tracks
                if str(track.delay) == '0':
                    audio_delay = ''
                else:
                    audio_delay_space = 'Delay' + ' ' * int(f'{character_space - len("Delay")}')
                    audio_del_to_vid_space = 'Delay to Video' + ' ' * int(f'{character_space - len("Delay to Video")}')
                    audio_delay = audio_delay_space + f': {str(track.delay)}ms\n' \
                                  + audio_del_to_vid_space + f': {str(track.delay_relative_to_video)}ms\n '
            else:
                audio_delay = ''
            if str(track.other_stream_size) != 'None':  # Get tracks stream size
                audio_track_size_space = 'Stream size' + ' ' * int(f'{character_space - len("Stream size")}')
                audio_track_stream_size = audio_track_size_space + f": {str(track.other_stream_size[4])}\n"
            else:
                audio_track_stream_size = ''
            if str(track.other_bit_depth) != 'None':  # Get tracks bit-depth
                audio_track_b_depth_space = 'Bit Depth' + ' ' * int(f'{character_space - len("Bit Depth")}')
                audio_track_bit_depth = audio_track_b_depth_space + f": {(track.other_bit_depth[0])}\n"
            else:
                audio_track_bit_depth = ''
            if str(track.compression_mode) != 'None':
                audio_track_compression_space = 'Compression' + ' ' * int(f'{character_space - len("Compression")}')
                audio_track_compression = audio_track_compression_space + f": {str(track.compression_mode)}\n"
            else:
                audio_track_compression = ''
            if str(track.default) != 'None':  # Get tracks default boolean
                audio_track_default_space = 'Default' + ' ' * int(f'{character_space - len("Default")}')
                audio_track_default = audio_track_default_space + f": {str(track.default)}\n"
            else:
                audio_track_default = ''
            if str(track.forced) != 'None':  # Get tracks forced boolean
                audio_track_forced_space = 'Forced' + ' ' * int(f'{character_space - len("Forced")}')
                audio_track_forced = audio_track_forced_space + f": {str(track.forced)}"
            else:
                audio_track_forced = ''

            # ---------------------------------------------------------------------------------------------- Formatting
            audio_track_info = str(audio_track_id + audio_format + audio_channels + audio_bitrate_mode +
                                   audio_bitrate + audio_sampling_rate + audio_delay + audio_duration +
                                   audio_language + audio_title + audio_track_stream_size + audio_track_bit_depth +
                                   audio_track_compression + audio_track_default + audio_track_forced)  # Formatting
            media_info_track_string = 80 * '#' + '\n' + audio_track_info + '\n' + 80 * '#' + '\n'  # String to insert
            stream_win_text_area.configure(state=NORMAL)  # Enable textbox
            stream_win_text_area.insert(INSERT, media_info_track_string)  # Insert string
            stream_win_text_area.insert(INSERT, '\n')  # Insert a newline
            stream_win_text_area.configure(state=DISABLED)  # Disable textbox

    def right_click_menu_func(x_y_pos):  # Function for mouse button 3 (right click) to pop up menu
        right_click_menu.tk_popup(x_y_pos.x_root, x_y_pos.y_root)  # This gets the position of cursor

    def copy_selected_text():  # Function to copy only selected text
        pya_hotkey('ctrl', 'c')
        time_sleep(.01)  # Slow program incase ctrl+c is slower

    right_click_menu = Menu(stream_window, tearoff=False)  # This is the right click menu
    right_click_menu.add_command(label='Copy Selected Text', command=copy_selected_text)
    right_click_menu.add_command(label='Copy All Text', command=pyperclip_copy(stream_win_text_area.get(1.0, END)))
    stream_window.bind('<Button-3>', right_click_menu_func)  # Uses mouse button 3 (right click) to pop up menu
    Hovertip(stream_win_text_area, 'Right click to copy', hover_delay=1200)  # Hover tip tool-tip
Beispiel #15
0
    def create_general_form(self, tab):
        form = Frame(tab)
        center = LabelFrame(form, padx=90, pady=30, width=450, height=250)
        btm_frame = Frame(form, pady=3, width=450, height=40)

        # layout all of the main containers
        form.pack(fill=tk.BOTH, expand=True)
        center.pack(fill=tk.BOTH, expand=True)
        btm_frame.pack(side=tk.RIGHT, padx=5, pady=5)

        center.grid_propagate(False)
        btm_frame.pack_propagate(False)
        center.grid_rowconfigure(0, pad=20)
        center.grid_rowconfigure(1, pad=20)
        center.grid_columnconfigure(1, weight=2, pad=20)

        en_file = Entry(center, state='disabled', width=200)
        en_file.grid(row=0, column=1, columnspan=2, padx=5, sticky='W')

        # Center elements
        def open_file():
            en_file.config(state='normal')
            en_file.delete(0, 'end')
            en_file.config(state='disabled')
            file = filedialog.askopenfilename(
                initialdir=os.path.join(os.getcwd(), 'inputs'),
                title="Select file",
                filetypes=(("csv files", "*.csv"), ("XES files", "*.xes"),
                           ("all files", "*.*")))
            en_file.config(state='normal')
            en_file.insert(0, os.path.basename(file))
            en_file.config(state='disabled')

        b_select = Button(center, text="Select event-log", command=open_file)
        b_select.grid(row=0, sticky='W')
        self.general_form.append({'name': 'file', 'obj': en_file})

        lb_exec_mode = Label(center, text="Exec. Mode: ")
        lb_exec_mode.grid(row=1, sticky='W')
        cb_exec_mode = ttk.Combobox(center)
        cb_exec_mode.set('single')
        cb_exec_mode['values'] = ('single', 'optimizer')
        cb_exec_mode.grid(row=1, column=1, padx=5, sticky='W')
        self.general_form.append({'name': 'exec_mode', 'obj': cb_exec_mode})

        lb_eval_metric = Label(center, text="Evaluation metric: ")
        lb_eval_metric.grid(row=2, sticky='W')
        cb_eval_metric = ttk.Combobox(center)
        cb_eval_metric.set('tsd')
        cb_eval_metric['values'] = ('tsd', 'dl_mae', 'tsd_min', 'mae')
        cb_eval_metric.grid(row=2, column=1, padx=5, sticky='W')
        self.general_form.append({'name': 'sim_metric', 'obj': cb_eval_metric})

        lb_rep = Label(center, text="Repetitions: ")
        lb_rep.grid(row=3, sticky='W')
        var = tk.IntVar()
        sl_rep = Scale(center,
                       variable=var,
                       from_=1,
                       to=30,
                       resolution=1,
                       orient=tk.HORIZONTAL)
        sl_rep.grid(row=3, column=1, padx=5, sticky='W')
        self.general_form.append({'name': 'repetitions', 'obj': sl_rep})
        # Bottom elements
        b_ok = Button(btm_frame, text="Next", command=self.next_tab)
        b_ok.grid(row=0)
        form.pack(side=tk.TOP, fill=tk.X, padx=5, pady=5)
        return form
Beispiel #16
0
def open_general_settings():  # General Settings Window
    global general_settings_window

    try:  # Check if window is already open, if it's open break from function
        if general_settings_window.winfo_exists():
            return
    except NameError:
        pass

    def general_settings_exit_function(
    ):  # Exit function when hitting the 'X' button
        general_parser = ConfigParser()
        general_parser.read(config_file)
        if general_parser['save_window_locations'][
                'general settings'] == 'yes':  # If auto save position on
            try:
                if general_parser['save_window_locations']['general settings position'] != \
                        general_settings_window.geometry():
                    general_parser.set('save_window_locations',
                                       'general settings position',
                                       general_settings_window.geometry())
                    with open(config_file, 'w') as generalfile:
                        general_parser.write(generalfile)
            except (Exception, ):
                pass
        general_settings_window.grab_release()  # Release grab on window
        general_settings_window.destroy()  # Close window

    # Config Parser
    config_file = 'Runtime/config.ini'
    config_parser = ConfigParser()
    config_parser.read(config_file)
    # Config Parser

    general_settings_window = Toplevel()  # Define toplevel()
    general_settings_window.title('General Settings')
    detect_font = font.nametofont(
        "TkDefaultFont")  # Get default font value into Font object
    set_font = detect_font.actual().get("family")
    color1 = "#434547"
    general_settings_window.configure(background=color1)
    if config_parser['save_window_locations']['general settings position'] == '' or \
            config_parser['save_window_locations']['general settings'] == 'no':
        window_height = 670
        window_width = 640
        screen_width = general_settings_window.winfo_screenwidth()
        screen_height = general_settings_window.winfo_screenheight()
        x_coordinate = int((screen_width / 2) - (window_width / 2))
        y_coordinate = int((screen_height / 2) - (window_height / 2))
        general_settings_window.geometry(
            f"{window_width}x{window_height}+{x_coordinate}+{y_coordinate}")
    elif config_parser['save_window_locations']['general settings position'] != '' and \
            config_parser['save_window_locations']['general settings'] == 'yes':
        general_settings_window.geometry(config_parser['save_window_locations']
                                         ['general settings position'])
    general_settings_window.protocol('WM_DELETE_WINDOW',
                                     general_settings_exit_function)
    general_settings_window.grab_set(
    )  # Focus all of tkinters attention on this window only

    general_settings_window.rowconfigure(0, weight=1)
    general_settings_window.grid_columnconfigure(0, weight=1)

    # Themes ----------------------------------------------------------------------------------------------------------
    # Hover over button theme ---------------------------------------
    class HoverButton(Button):
        def __init__(self, master, **kw):
            Button.__init__(self, master=master, **kw)
            self.defaultBackground = self["background"]
            self.bind("<Enter>", self.on_enter)
            self.bind("<Leave>", self.on_leave)

        def on_enter(self, _):
            self['background'] = self['activebackground']

        def on_leave(self, _):
            self['background'] = self.defaultBackground

    # --------------------------------------- Hover over button theme
    # Settings Notebook Frame -----------------------------------------------------------------------------------------
    tabs = ttk.Notebook(general_settings_window)
    tabs.grid(row=0,
              column=0,
              columnspan=4,
              sticky=E + W + N + S,
              padx=0,
              pady=0)
    settings_tab = Frame(tabs, background="#434547")
    tabs.add(settings_tab, text=' Paths ')

    for n in range(4):
        settings_tab.grid_columnconfigure(n, weight=1)
    for n in range(2):
        settings_tab.grid_rowconfigure(n, weight=1)

    # ----------------------------------------------------------------------------------------  Settings Notebook Frame
    # ---------------------------------------------------------------------------------------------------------- Themes

    path_frame = LabelFrame(settings_tab, text=' Tool Paths ', labelanchor="n")
    path_frame.grid(column=0,
                    row=0,
                    columnspan=4,
                    padx=5,
                    pady=(10, 3),
                    sticky=N + S + E + W)
    path_frame.configure(fg="#3498db",
                         bg="#434547",
                         bd=3,
                         font=(set_font, 10, "bold"))
    for p_f in range(5):
        path_frame.grid_rowconfigure(p_f, weight=1)
    for p_f in range(4):
        path_frame.grid_columnconfigure(p_f, weight=1)

    # FFMPEG Path -----------------------------------------------------------------------------------------------------
    ffmpeg_frame = LabelFrame(path_frame, text=' FFMPEG ', labelanchor="nw")
    ffmpeg_frame.grid(column=0,
                      row=0,
                      columnspan=4,
                      padx=5,
                      pady=(5, 3),
                      sticky=E + W)
    ffmpeg_frame.configure(fg="#3498db",
                           bg="#434547",
                           bd=3,
                           font=(set_font, 9, "italic"))
    ffmpeg_frame.grid_rowconfigure(0, weight=1)
    ffmpeg_frame.grid_columnconfigure(0, weight=1)
    ffmpeg_frame.grid_columnconfigure(1, weight=20)

    def set_ffmpeg_path():
        path = filedialog.askopenfilename(
            title='Select Location to "ffmpeg.exe"',
            initialdir=pathlib.Path(ffmpeg_entry_box.get()).parent,
            filetypes=[('ffmpeg', 'ffmpeg.exe')],
            parent=general_settings_window)
        if path:
            ffmpeg_parser = ConfigParser()
            ffmpeg_parser.read(config_file)
            ffmpeg = f'"{str(pathlib.Path(path))}"'
            ffmpeg_parser.set('ffmpeg_path', 'path', ffmpeg)
            with open(config_file, 'w') as ffmpeg_configfile:
                ffmpeg_parser.write(ffmpeg_configfile)
            ffmpeg_entry_box.config(state=NORMAL)
            ffmpeg_entry_box.delete(0, END)
            ffmpeg_entry_box.insert(
                0,
                str(
                    pathlib.Path(
                        str(ffmpeg_parser['ffmpeg_path']['path']).replace(
                            '"', '')).resolve()))
            ffmpeg_entry_box.config(state=DISABLED)

    set_ffmpeg_path = HoverButton(ffmpeg_frame,
                                  text="Set Path",
                                  command=set_ffmpeg_path,
                                  foreground="white",
                                  background="#23272A",
                                  borderwidth="3",
                                  activebackground='grey')
    set_ffmpeg_path.grid(row=0,
                         column=0,
                         columnspan=1,
                         padx=5,
                         pady=5,
                         sticky=N + S + E + W)

    saved_ffmpeg_path = pathlib.Path(
        str(config_parser['ffmpeg_path']['path']).replace('"', '')).resolve()
    ffmpeg_entry_box = Entry(ffmpeg_frame, borderwidth=4, background="#CACACA")
    ffmpeg_entry_box.grid(row=0,
                          column=1,
                          columnspan=3,
                          padx=5,
                          pady=5,
                          sticky=N + S + E + W)
    ffmpeg_entry_box.insert(0, str(saved_ffmpeg_path))
    ffmpeg_entry_box.config(state=DISABLED)

    # MPV Path --------------------------------------------------------------------------------------------------------
    mpv_frame = LabelFrame(path_frame, text=' MPV ', labelanchor="nw")
    mpv_frame.grid(column=0,
                   row=1,
                   columnspan=4,
                   padx=5,
                   pady=(5, 3),
                   sticky=E + W)
    mpv_frame.configure(fg="#3498db",
                        bg="#434547",
                        bd=3,
                        font=(set_font, 9, "italic"))
    mpv_frame.grid_rowconfigure(0, weight=1)
    mpv_frame.grid_columnconfigure(0, weight=1)
    mpv_frame.grid_columnconfigure(1, weight=20)

    def set_mpv_path():
        path = filedialog.askopenfilename(title='Select Location to "mpv.exe"',
                                          initialdir=pathlib.Path(
                                              mpv_entry_box.get()).parent,
                                          filetypes=[('mpv', 'mpv.exe')],
                                          parent=general_settings_window)
        if path:
            mpv_cfg_parser = ConfigParser()
            mpv_cfg_parser.read(config_file)
            mpv = f'"{str(pathlib.Path(path))}"'
            mpv_cfg_parser.set('mpv_player_path', 'path', mpv)
            with open(config_file, 'w') as mpv_cfg:
                mpv_cfg_parser.write(mpv_cfg)
            mpv_entry_box.config(state=NORMAL)
            mpv_entry_box.delete(0, END)
            mpv_entry_box.insert(
                0,
                str(
                    pathlib.Path(
                        str(mpv_cfg_parser['mpv_player_path']['path']).replace(
                            '"', '')).resolve()))
            mpv_entry_box.config(state=DISABLED)

    set_mpv_path = HoverButton(mpv_frame,
                               text="Set Path",
                               command=set_mpv_path,
                               foreground="white",
                               background="#23272A",
                               borderwidth="3",
                               activebackground='grey')
    set_mpv_path.grid(row=0,
                      column=0,
                      columnspan=1,
                      padx=5,
                      pady=5,
                      sticky=N + S + E + W)

    saved_mpv_path = pathlib.Path(
        str(config_parser['mpv_player_path']['path']).replace('"',
                                                              '')).resolve()
    mpv_entry_box = Entry(mpv_frame, borderwidth=4, background="#CACACA")
    mpv_entry_box.grid(row=0,
                       column=1,
                       columnspan=3,
                       padx=5,
                       pady=5,
                       sticky=N + S + E + W)
    mpv_entry_box.insert(0, str(saved_mpv_path))
    mpv_entry_box.config(state=DISABLED)

    # Media Info Gui Path ---------------------------------------------------------------------------------------------
    mediainfogui_frame = LabelFrame(path_frame,
                                    text=' MediaInfo GUI ',
                                    labelanchor="nw")
    mediainfogui_frame.grid(column=0,
                            row=2,
                            columnspan=4,
                            padx=5,
                            pady=(5, 3),
                            sticky=E + W)
    mediainfogui_frame.configure(fg="#3498db",
                                 bg="#434547",
                                 bd=3,
                                 font=(set_font, 9, "italic"))
    mediainfogui_frame.grid_rowconfigure(0, weight=1)
    mediainfogui_frame.grid_columnconfigure(0, weight=1)
    mediainfogui_frame.grid_columnconfigure(1, weight=20)

    def set_mediainfogui_path():
        path = filedialog.askopenfilename(
            title='Select Location to "mediainfo.exe"',
            initialdir=pathlib.Path(mediainfogui_entry_box.get()).parent,
            filetypes=[('mediainfo', 'mediainfo.exe')],
            parent=general_settings_window)
        if path:
            mediainfo_cfg_parser = ConfigParser()
            mediainfo_cfg_parser.read(config_file)
            mediainfogui = f'"{str(pathlib.Path(path))}"'
            mediainfo_cfg_parser.set('mediainfogui_path', 'path', mediainfogui)
            with open(config_file, 'w') as mediainfo_cfg:
                mediainfo_cfg_parser.write(mediainfo_cfg)
            mediainfogui_entry_box.config(state=NORMAL)
            mediainfogui_entry_box.delete(0, END)
            mediainfogui_entry_box.insert(
                0,
                str(
                    pathlib.Path(
                        str(mediainfo_cfg_parser['mediainfogui_path']
                            ['path']).replace('"', '')).resolve()))
            mediainfogui_entry_box.config(state=DISABLED)

    set_mediainfogui_path = HoverButton(mediainfogui_frame,
                                        text="Set Path",
                                        command=set_mediainfogui_path,
                                        foreground="white",
                                        background="#23272A",
                                        borderwidth="3",
                                        activebackground='grey')
    set_mediainfogui_path.grid(row=0,
                               column=0,
                               columnspan=1,
                               padx=5,
                               pady=5,
                               sticky=N + S + E + W)

    saved_mediainfogui_path = pathlib.Path(
        str(config_parser['mediainfogui_path']['path']).replace('"',
                                                                '')).resolve()
    mediainfogui_entry_box = Entry(mediainfogui_frame,
                                   borderwidth=4,
                                   background="#CACACA")
    mediainfogui_entry_box.grid(row=0,
                                column=1,
                                columnspan=3,
                                padx=5,
                                pady=5,
                                sticky=N + S + E + W)
    mediainfogui_entry_box.insert(0, str(saved_mediainfogui_path))
    mediainfogui_entry_box.config(state=DISABLED)

    # FDK-AAC Path ----------------------------------------------------------------------------------------------------
    fdkaac_frame = LabelFrame(path_frame, text=' FDK-AAC ', labelanchor="nw")
    fdkaac_frame.grid(column=0,
                      row=3,
                      columnspan=4,
                      padx=5,
                      pady=(5, 3),
                      sticky=E + W)
    fdkaac_frame.configure(fg="#3498db",
                           bg="#434547",
                           bd=3,
                           font=(set_font, 9, "italic"))
    fdkaac_frame.grid_rowconfigure(0, weight=1)
    fdkaac_frame.grid_columnconfigure(0, weight=1)
    fdkaac_frame.grid_columnconfigure(1, weight=20)
    saved_fdkaac_path = None

    def set_fdk_aac_path():
        path = filedialog.askopenfilename(
            title='Select Location to "fdkaac.exe"',
            initialdir=pathlib.Path(fdkaac_entry_box.get()).parent,
            filetypes=[('FDK-AAC', 'fdkaac.exe')],
            parent=general_settings_window)
        if path:
            fdk_parser = ConfigParser()
            fdk_parser.read(config_file)
            fdkaac = f'"{str(pathlib.Path(path))}"'
            fdk_parser.set('fdkaac_path', 'path', fdkaac)
            with open(config_file, 'w') as fdk_cfg:
                fdk_parser.write(fdk_cfg)
            fdkaac_entry_box.config(state=NORMAL)
            fdkaac_entry_box.delete(0, END)
            fdkaac_entry_box.insert(
                0,
                str(
                    pathlib.Path(
                        str(fdk_parser['fdkaac_path']['path']).replace(
                            '"', '')).resolve()))
            fdkaac_entry_box.config(state=DISABLED)

    set_fdkaac_path = HoverButton(fdkaac_frame,
                                  text="Set Path",
                                  command=set_fdk_aac_path,
                                  foreground="white",
                                  background="#23272A",
                                  borderwidth="3",
                                  activebackground='grey')
    set_fdkaac_path.grid(row=0,
                         column=0,
                         columnspan=1,
                         padx=5,
                         pady=5,
                         sticky=N + S + E + W)

    if config_parser['fdkaac_path']['path'] == '':
        saved_fdkaac_path = 'not installed'.title()
    elif config_parser['fdkaac_path']['path'] != '':
        if pathlib.Path(
                str(config_parser['fdkaac_path']['path']).replace(
                    '"', '')).exists():
            saved_fdkaac_path = '"' + str(
                pathlib.Path(
                    str(config_parser['fdkaac_path']['path']).replace(
                        '"', '')).resolve()) + '"'
        else:
            saved_fdkaac_path = 'not installed'.title()
            func_parser = ConfigParser()
            func_parser.read(config_file)
            func_parser.set('fdkaac_path', 'path', '')
            with open(config_file, 'w') as configfile:
                func_parser.write(configfile)

    fdkaac_entry_box = Entry(fdkaac_frame, borderwidth=4, background="#CACACA")
    fdkaac_entry_box.grid(row=0,
                          column=1,
                          columnspan=3,
                          padx=5,
                          pady=5,
                          sticky=N + S + E + W)
    fdkaac_entry_box.insert(0, str(saved_fdkaac_path).replace('"', ''))
    fdkaac_entry_box.config(state=DISABLED)

    # QAAC Path -------------------------------------------------------------------------------------------------------
    qaac_frame = LabelFrame(path_frame, text=' QAAC ', labelanchor="nw")
    qaac_frame.grid(column=0,
                    row=4,
                    columnspan=4,
                    padx=5,
                    pady=(5, 3),
                    sticky=E + W)
    qaac_frame.configure(fg="#3498db",
                         bg="#434547",
                         bd=3,
                         font=(set_font, 9, "italic"))
    qaac_frame.grid_rowconfigure(0, weight=1)
    qaac_frame.grid_rowconfigure(1, weight=1)
    for q_f in range(4):
        qaac_frame.grid_columnconfigure(q_f, weight=1)
    saved_qaac_path = None

    def set_qaac_path():
        path = filedialog.askopenfilename(
            title='Select Location to "qaac64.exe"',
            initialdir=pathlib.Path(qaac_entry_box.get()).parent,
            filetypes=[('qaac64', 'qaac64.exe')],
            parent=general_settings_window)
        if path:
            qaac_parser = ConfigParser()
            qaac_parser.read(config_file)
            qaac = f'"{str(pathlib.Path(path))}"'
            qaac_parser.set('qaac_path', 'path', qaac)
            with open(config_file, 'w') as qaac_cfg:
                qaac_parser.write(qaac_cfg)
            qt_folder_path = pathlib.Path(
                pathlib.Path(
                    str(qaac_parser['qaac_path']['path']).replace(
                        '"', '')).resolve().parent / 'QTfiles64')
            qaac_parser.set('qaac_path', 'qt_path', f'"{str(qt_folder_path)}"')
            with open(config_file, 'w') as qaac_cfg:
                qaac_parser.write(qaac_cfg)
            qaac_entry_box.config(state=NORMAL)
            qaac_entry_box.delete(0, END)
            qaac_entry_box.insert(
                0,
                str(
                    pathlib.Path(
                        str(qaac_parser['qaac_path']['path']).replace(
                            '"', '')).resolve()))
            qaac_entry_box.config(state=DISABLED)

            update_qaac_file_paths()

    set_qaac_path = HoverButton(qaac_frame,
                                text="Set Path",
                                command=set_qaac_path,
                                foreground="white",
                                background="#23272A",
                                borderwidth="3",
                                activebackground='grey')
    set_qaac_path.grid(row=0,
                       column=0,
                       columnspan=1,
                       padx=5,
                       pady=5,
                       sticky=N + S + E + W)

    if config_parser['qaac_path']['path'] == '':
        saved_qaac_path = 'not installed'.title()
    elif config_parser['qaac_path']['path'] != '':
        if pathlib.Path(
                str(config_parser['qaac_path']['path']).replace('"',
                                                                '')).exists():
            saved_qaac_path = '"' + str(
                pathlib.Path(
                    str(config_parser['qaac_path']['path']).replace(
                        '"', '')).resolve()) + '"'
        else:
            saved_qaac_path = 'not installed'.title()
            func_parser = ConfigParser()
            func_parser.read(config_file)
            func_parser.set('qaac_path', 'path', '')
            with open(config_file, 'w') as configfile:
                func_parser.write(configfile)

    qaac_entry_box = Entry(qaac_frame, borderwidth=4, background="#CACACA")
    qaac_entry_box.grid(row=0,
                        column=1,
                        columnspan=3,
                        padx=5,
                        pady=5,
                        sticky=N + S + E + W)
    qaac_entry_box.insert(0, str(saved_qaac_path).replace('"', ''))
    qaac_entry_box.config(state=DISABLED)

    def update_qaac_file_paths():
        global qt_folder, list_of_qaac_files
        update_parser = ConfigParser()
        update_parser.read(config_file)

        if update_parser['qaac_path'][
                'path'] == '':  # if path to qaac is empty
            qt_folder = pathlib.Path(pathlib.Path.cwd() / 'Apps' / 'qaac' /
                                     'QTfiles64')
        elif update_parser['qaac_path'][
                'path'] != '':  # if path to qaac is not empty
            qt_folder = pathlib.Path(
                pathlib.Path(
                    str(update_parser['qaac_path']['path']).replace(
                        '"', '')).resolve().parent / 'QTfiles64')

        pathlib.Path(qt_folder).mkdir(parents=True, exist_ok=True)

        list_of_qaac_files = [
            pathlib.Path(qt_folder / 'ASL.dll'),
            pathlib.Path(qt_folder / 'CoreAudioToolbox.dll'),
            pathlib.Path(qt_folder / 'CoreFoundation.dll'),
            pathlib.Path(qt_folder / 'icudt62.dll'),
            pathlib.Path(qt_folder / 'libdispatch.dll'),
            pathlib.Path(qt_folder / 'libicuin.dll'),
            pathlib.Path(qt_folder / 'libicuuc.dll'),
            pathlib.Path(qt_folder / 'objc.dll')
        ]

    update_qaac_file_paths()

    def check_for_qaac_files():
        global list_of_qaac_files
        checked_qaac_files = []
        for files in list_of_qaac_files:
            checked_qaac_files.append(pathlib.Path(files).is_file())

        if all(checked_qaac_files):
            qaac_status_label.config(text='Status: Ready')
        else:
            qaac_status_label.config(text='Status: Missing QTFiles')

        general_settings_window.after(1000, check_for_qaac_files)

    qaac_status_label = Label(qaac_frame,
                              text="",
                              background="#434547",
                              foreground="white",
                              width=10)
    qaac_status_label.grid(row=1,
                           column=0,
                           columnspan=2,
                           padx=(5, 5),
                           pady=(2, 0),
                           sticky=W + E)
    check_for_qaac_files()

    qt_files_download = HoverButton(
        qaac_frame,
        text="Download QTfiles64",
        command=lambda: webbrowser.open(
            'https://github.com/AnimMouse/QTFiles/releases'),
        foreground="white",
        background="#23272A",
        borderwidth="3",
        activebackground='grey')
    qt_files_download.grid(row=1,
                           column=2,
                           columnspan=1,
                           padx=5,
                           pady=(2, 0),
                           sticky=N + S + E + W)

    qt_files_dir = HoverButton(qaac_frame,
                               text="Open QTfiles64 Directory",
                               command=lambda: webbrowser.open(qt_folder),
                               foreground="white",
                               background="#23272A",
                               borderwidth="3",
                               activebackground='grey')
    qt_files_dir.grid(row=1,
                      column=3,
                      columnspan=1,
                      padx=5,
                      pady=(2, 0),
                      sticky=N + S + E + W)

    # save path frame -------------------------------------------------------------------------------------------------
    save_path_frame = LabelFrame(settings_tab,
                                 text=' Save Paths ',
                                 labelanchor="n")
    save_path_frame.grid(column=0,
                         row=1,
                         columnspan=4,
                         padx=5,
                         pady=(10, 3),
                         sticky=N + S + E + W)
    save_path_frame.configure(fg="#3498db",
                              bg="#434547",
                              bd=3,
                              font=(set_font, 10, "bold"))
    save_path_frame.grid_rowconfigure(0, weight=1)
    save_path_frame.grid_rowconfigure(1, weight=1)
    for s_p in range(4):
        save_path_frame.grid_columnconfigure(s_p, weight=1)

    # Manual Auto Path ------------------------------------------------------------------------------------------------
    manual_auto_frame = LabelFrame(save_path_frame,
                                   text=' Manual/Auto Encode Path ',
                                   labelanchor="nw")
    manual_auto_frame.grid(column=0,
                           row=0,
                           columnspan=4,
                           padx=5,
                           pady=(5, 3),
                           sticky=E + W)
    manual_auto_frame.configure(fg="#3498db",
                                bg="#434547",
                                bd=3,
                                font=(set_font, 9, "italic"))
    manual_auto_frame.grid_rowconfigure(0, weight=1)
    manual_auto_frame.grid_columnconfigure(0, weight=2)
    manual_auto_frame.grid_columnconfigure(1, weight=20)
    manual_auto_frame.grid_columnconfigure(3, weight=1)

    def set_manual_auto_path():
        path = filedialog.askdirectory(title='Output Path Manual/Auto',
                                       parent=general_settings_window)
        if path:
            manual_path_parser = ConfigParser()
            manual_path_parser.read(config_file)
            path = str(pathlib.Path(path))
            manual_path_parser.set('output_path', 'path', path)
            with open(config_file, 'w') as manual_path_configfile:
                manual_path_parser.write(manual_path_configfile)
            manual_auto_entry_box.config(state=NORMAL)
            manual_auto_entry_box.delete(0, END)
            manual_auto_entry_box.insert(
                0,
                str(
                    pathlib.Path(str(
                        manual_path_parser['output_path']['path']))))
            manual_auto_entry_box.config(state=DISABLED)

    set_manual_auto_path = HoverButton(manual_auto_frame,
                                       text="Set Path",
                                       command=set_manual_auto_path,
                                       foreground="white",
                                       background="#23272A",
                                       borderwidth="3",
                                       activebackground='grey')
    set_manual_auto_path.grid(row=0,
                              column=0,
                              columnspan=1,
                              padx=5,
                              pady=5,
                              sticky=N + S + E + W)

    saved_manual_auto_path = None
    if config_parser['output_path']['path'] == 'file input directory':
        saved_manual_auto_path = str(
            config_parser['output_path']['path']).title()
    elif config_parser['output_path']['path'] != 'file input directory':
        saved_manual_auto_path = str(
            pathlib.Path(config_parser['output_path']['path']).resolve())
    manual_auto_entry_box = Entry(manual_auto_frame,
                                  borderwidth=4,
                                  background="#CACACA")
    manual_auto_entry_box.grid(row=0,
                               column=1,
                               columnspan=2,
                               padx=5,
                               pady=5,
                               sticky=N + S + E + W)
    manual_auto_entry_box.insert(0, saved_manual_auto_path)
    manual_auto_entry_box.config(state=DISABLED)

    def reset_manual_auto_path():
        msg = messagebox.askyesno(
            title='Prompt',
            message='Reset path to directory of input file?',
            parent=general_settings_window)
        if msg:
            reset_manual_path_parser = ConfigParser()
            reset_manual_path_parser.read(config_file)
            reset_manual_path_parser.set('output_path', 'path',
                                         'file input directory')
            with open(config_file, 'w') as r_mp_cfg:
                reset_manual_path_parser.write(r_mp_cfg)
            manual_auto_entry_box.config(state=NORMAL)
            manual_auto_entry_box.delete(0, END)
            manual_auto_entry_box.insert(
                0,
                str(reset_manual_path_parser['output_path']['path']).title())
            manual_auto_entry_box.config(state=DISABLED)

    reset_manual_auto_path = HoverButton(manual_auto_frame,
                                         text="X",
                                         command=reset_manual_auto_path,
                                         foreground="white",
                                         background="#23272A",
                                         borderwidth="3",
                                         activebackground='grey')
    reset_manual_auto_path.grid(row=0,
                                column=3,
                                columnspan=1,
                                padx=5,
                                pady=5,
                                sticky=N + S + E + W)

    # Batch Path ------------------------------------------------------------------------------------------------------
    batch_frame = LabelFrame(save_path_frame,
                             text=' Batch Processing Path ',
                             labelanchor="nw")
    batch_frame.grid(column=0,
                     row=1,
                     columnspan=4,
                     padx=5,
                     pady=(5, 3),
                     sticky=E + W)
    batch_frame.configure(fg="#3498db",
                          bg="#434547",
                          bd=3,
                          font=(set_font, 9, "italic"))
    batch_frame.grid_rowconfigure(0, weight=1)
    batch_frame.grid_columnconfigure(0, weight=2)
    batch_frame.grid_columnconfigure(1, weight=20)
    batch_frame.grid_columnconfigure(3, weight=1)

    def set_batch_path():
        path = filedialog.askdirectory(title='Output Path Manual/Auto',
                                       parent=general_settings_window)
        if path:
            bath_path_parser = ConfigParser()
            bath_path_parser.read(config_file)
            path = str(pathlib.Path(path))
            bath_path_parser.set('batch_path', 'path', path)
            with open(config_file, 'w') as batch_cfg:
                bath_path_parser.write(batch_cfg)
            batch_entry_box.config(state=NORMAL)
            batch_entry_box.delete(0, END)
            batch_entry_box.insert(
                0,
                str(pathlib.Path(str(bath_path_parser['batch_path']['path']))))
            batch_entry_box.config(state=DISABLED)

    set_batch_path_button = HoverButton(batch_frame,
                                        text="Set Path",
                                        command=set_batch_path,
                                        foreground="white",
                                        background="#23272A",
                                        borderwidth="3",
                                        activebackground='grey')
    set_batch_path_button.grid(row=0,
                               column=0,
                               columnspan=1,
                               padx=5,
                               pady=5,
                               sticky=N + S + E + W)

    saved_batch_path = None
    if config_parser['batch_path']['path'] == 'file input directory':
        saved_batch_path = str(config_parser['batch_path']['path']).title()
    elif config_parser['batch_path']['path'] != 'file input directory':
        saved_batch_path = str(
            pathlib.Path(config_parser['batch_path']['path']).resolve())
    batch_entry_box = Entry(batch_frame, borderwidth=4, background="#CACACA")
    batch_entry_box.grid(row=0,
                         column=1,
                         columnspan=2,
                         padx=5,
                         pady=5,
                         sticky=N + S + E + W)
    batch_entry_box.insert(0, saved_batch_path)
    batch_entry_box.config(state=DISABLED)

    def reset_batch_path():
        msg = messagebox.askyesno(
            title='Prompt',
            message='Reset path to directory of input file?',
            parent=general_settings_window)
        if msg:
            reset_batch_path_parser = ConfigParser()
            reset_batch_path_parser.read(config_file)
            reset_batch_path_parser.set('batch_path', 'path',
                                        'file input directory')
            with open(config_file, 'w') as reset_bp_cfg:
                reset_batch_path_parser.write(reset_bp_cfg)
            batch_entry_box.config(state=NORMAL)
            batch_entry_box.delete(0, END)
            batch_entry_box.insert(
                0,
                str(reset_batch_path_parser['batch_path']['path']).title())
            batch_entry_box.config(state=DISABLED)

    reset_batch_path_button = HoverButton(batch_frame,
                                          text="X",
                                          command=reset_batch_path,
                                          foreground="white",
                                          background="#23272A",
                                          borderwidth="3",
                                          activebackground='grey')
    reset_batch_path_button.grid(row=0,
                                 column=3,
                                 columnspan=1,
                                 padx=5,
                                 pady=5,
                                 sticky=N + S + E + W)
Beispiel #17
0
    def __init__(self, thread_cls):
        super().__init__()
        self.thread_cls = thread_cls
        self.img = None
        self.title("Emotion API")
        self.grid()
        self.grid_columnconfigure(0, weight=1)
        self.grid_columnconfigure(1, weight=2)
        self.grid_rowconfigure(4, weight=1)

        # Create LabelFrames
        lf_key = LabelFrame(self, text="Emotion API Key")
        lf_key.grid(row=0,
                    column=0,
                    columnspan=1,
                    sticky=W + E,
                    padx=5,
                    pady=3)
        lf_key.grid_columnconfigure(0, weight=1)
        lf_mode = LabelFrame(self, text="Mode")
        lf_mode.grid(row=1,
                     column=0,
                     columnspan=1,
                     sticky=W + E,
                     padx=5,
                     pady=3)
        for i in range(3):
            lf_mode.grid_columnconfigure(i, weight=1)
        lf_source = LabelFrame(self, text="Image Source", height=50)
        lf_source.grid(row=2,
                       column=0,
                       columnspan=1,
                       sticky=W + E,
                       padx=5,
                       pady=3)
        lf_source.rowconfigure(0, weight=1)
        lf_source.grid_propagate(False)
        lf_source.columnconfigure(0, weight=1)
        lf_source.columnconfigure(1, weight=5)
        lf_source.columnconfigure(2, weight=1)
        lf_request = LabelFrame(self, text="Request Result")
        lf_request.grid(row=3,
                        column=0,
                        columnspan=1,
                        sticky=W + E,
                        padx=5,
                        pady=3)
        lf_request.grid_columnconfigure(0, weight=1)
        lf_console = LabelFrame(self, text="Console")
        lf_console.grid(row=4,
                        column=0,
                        columnspan=1,
                        sticky=N + S + W + E,
                        padx=5,
                        pady=3)
        lf_console.grid_columnconfigure(0, weight=1)
        lf_console.grid_rowconfigure(0, weight=1)
        lf_img = LabelFrame(self, text="Output Image")
        lf_img.grid(row=0, column=1, rowspan=5, sticky=N + S + W + E)
        lf_img.grid_columnconfigure(0, weight=1)
        lf_img.grid_rowconfigure(0, weight=1)

        # Create Input Fields
        self.ety_key = Entry(lf_key)
        self.ety_key.insert(END, "bfe9b2f471e04b29a8fabfe3dd9f647d")
        self.ety_key.grid(sticky=W + E, padx=3)
        self.var_mode = StringVar()
        Radiobutton(lf_mode,
                    text="Local Image",
                    variable=self.var_mode,
                    value='local',
                    command=self.change_mode).grid(row=1, column=0)
        Radiobutton(lf_mode,
                    text="URL Image",
                    variable=self.var_mode,
                    value='url',
                    command=self.change_mode).grid(row=1, column=1)
        Radiobutton(lf_mode,
                    text="Camera",
                    variable=self.var_mode,
                    value='cam',
                    command=self.change_mode).grid(row=1, column=2)
        # Local Image Source
        self.lb_filename = Label(lf_source, text="..")
        self.btn_fileopen = Button(lf_source,
                                   text="Open..",
                                   command=self.get_local_img)
        # URL Image Source
        self.lb_url = Label(lf_source, text="URL")
        self.ety_url = Entry(lf_source)
        self.ety_url.insert(END, "https://i.imgflip.com/qiev6.jpg")
        self.btn_url = Button(lf_source,
                              text="Get Image",
                              command=self.get_url_img)
        # Camera Image Source
        self.btn_get_cam = Button(lf_source,
                                  text="Get the Camera Image",
                                  command=self.get_cam_img)
        # set default mode: local raw image
        self.var_mode.set('local')
        self.change_mode()
        # request btn
        self.btn_request = Button(lf_request,
                                  text="Request Result",
                                  command=self.run_request,
                                  state='disable')
        self.btn_request.grid(sticky=W + E)

        # Create Output Console
        self.console = ScrolledText(lf_console,
                                    state='disable',
                                    width=60,
                                    bg='gray20',
                                    fg='white')
        self.console.grid(sticky=N + S + W + E)

        # Create Output Image
        self.plot = ResultImg(lf_img)
        self.plot.grid(sticky=N + S + W + E)