class AbstractTitleDescriptionMultipleButtonsScreen(GuiBaseFrame): def __init__(self, parent, controller, title, process_description_message_list, button_text_list, button_command_list, **kw): self.screen_title = title self.process_description_message_list = process_description_message_list self.button_text_list = button_text_list self.button_command_list = button_command_list GuiBaseFrame.__init__(self, parent, controller, **kw) def init_widgets(self): self.content_wrapper = Frame(self) self.screen_title = Header1Label(self.content_wrapper, text=self.screen_title) self.screen_description_label = PLabel( self.content_wrapper, text=("\n\n".join(self.process_description_message_list))) self.button_wrapper = Frame(self.content_wrapper) if len(self.button_text_list) != len(self.button_command_list): raise ValueError( "Button text list and command list must have the same length " "(each text must correspond with a command in both lists).") self.buttons = [] for i in range(0, len(self.button_text_list)): self.buttons.append((Button(self.button_wrapper, text=self.button_text_list[i], command=self.button_command_list[i]))) def add_widgets_to_frame(self): self.screen_title.pack() self.screen_description_label.pack() self.button_wrapper.pack() for button in self.buttons: button.pack() self.content_wrapper.place(relx=SCREENS_REL_X, rely=SCREEN_REL_Y_47, anchor=CENTER) def on_show_frame(self): pass def update_frame(self, data): pass def on_hide_frame(self): pass
class AbstractTitleDescriptionNextScreen(GuiBaseFrame): def __init__(self, parent, controller, title, process_description_message_list, **kw): self.screen_title = title self.process_description_message_list = process_description_message_list GuiBaseFrame.__init__(self, parent, controller, **kw) def init_widgets(self): self.content_wrapper = Frame(self) self.screen_title = Header1Label(self.content_wrapper, text=self.screen_title) self.screen_description_label = PLabel( self.content_wrapper, text=("\n\n".join(self.process_description_message_list))) self.button_wrapper = Frame(self.content_wrapper) self.next_button = Button(self.button_wrapper, text="Next", command=lambda: self.on_next_button()) def add_widgets_to_frame(self): self.screen_title.pack() self.screen_description_label.pack() self.button_wrapper.pack() self.next_button.pack() self.content_wrapper.place(relx=SCREENS_REL_X, rely=SCREEN_REL_Y_45, anchor=CENTER) def on_show_frame(self): pass def update_frame(self, data): pass def on_hide_frame(self): pass def on_next_button(self): raise NotImplementedError
class AbstractTimeSelectionStartScreen(AbstractTimeSelectionBaseScreen): def __init__(self, parent, controller, **kw): AbstractTimeSelectionBaseScreen.__init__(self, parent, controller, **kw) def init_widgets(self): AbstractTimeSelectionBaseScreen.init_widgets(self) self.screen_instruction_1_filename_label = PLabel(self.content_wrapper) self.screen_instruction_2_label = PLabel(self.content_wrapper) self.empty_label_1 = PLabel(self.content_wrapper) def add_widgets_to_frame(self): self.pack_title_and_instruction_widgets() self.empty_label_1.pack() self.screen_instruction_1_filename_label.pack() self.screen_instruction_2_label.pack() self.pack_lower_half_widgets() self.content_wrapper.place(relx=SCREENS_REL_X, rely=SCREEN_REL_Y_45, anchor=CENTER) def on_show_frame(self): self.set_instruction_1_filename(self.controller.get_filename_of_video_with_0_offset() + "\n") self.set_error_message("") def update_frame(self, data): AbstractTimeSelectionBaseScreen.update_frame(self, data) def on_hide_frame(self): pass def set_input_checks(self): AbstractTimeSelectionBaseScreen.set_input_checks(self) def on_input_check_success(self): AbstractTimeSelectionBaseScreen.on_input_check_success(self) def prev_button_command(self): AbstractTimeSelectionBaseScreen.prev_button_command(self) def next_button_command(self): AbstractTimeSelectionBaseScreen.next_button_command(self) def set_instruction_1_filename(self, file_of_video_to_open): self.screen_instruction_1_filename_label.configure(text=file_of_video_to_open) def set_instruction_2_text(self, timestamp_instr_text): self.screen_instruction_2_label.configure(text=timestamp_instr_text)
class WelcomeScreen(GuiBaseFrame): def __init__(self, parent, controller, **kw): GuiBaseFrame.__init__(self, parent, controller, **kw) def init_widgets(self): self.text_container = Frame(self) self.welcome_label = Header1Label( self.text_container, text="Welcome to the full WALL-E footage processing experience!!") self.description_label = PLabel( self.text_container, text="This process helps you perform the following in order:\n" "\t1) Frame matching the videos\n" "\t2) Finding and generating the best SR map\n" "\t3) Stereo rectifying the videos", justify=LEFT) self.advisory_label = PLabel( self.text_container, text="(Note: the GUI experience looks best on a Mac)") self.good_luck_label = PLabel(self.text_container, text="Good Luck!") self.next_button = Button( self.text_container, text="Get Started", command=lambda: self.controller.show_next_frame()) def add_widgets_to_frame(self): self.welcome_label.pack() self.description_label.pack() self.advisory_label.pack() self.good_luck_label.pack() self.next_button.pack() self.text_container.place(relx=SCREENS_REL_X, rely=SCREEN_REL_Y_45, anchor=CENTER) def on_show_frame(self): pass def on_hide_frame(self): pass
class FinalScreen(GuiBaseFrame): def __init__(self, parent, controller, **kw): GuiBaseFrame.__init__(self, parent, controller, **kw) def init_widgets(self): self.text_container = Frame(self) self.screen_title = Header1Label(self.text_container, text="Stereo Rectification Complete!") self.text_1 = PLabel(self.text_container, text=("\n".join([ "Your videos have been stereo rectified!", "You can find them in the follow " "paths on your system:" ]))) self.filenames = PLabel(self.text_container) self.thanks_label = PLabel(self.text_container, text="Thank you for your patience!") self.finish_button = Button(self.text_container, text="Finish and Close Window", command=lambda: sys.exit()) def add_widgets_to_frame(self): self.screen_title.pack() self.text_1.pack() self.filenames.pack() self.thanks_label.pack() self.finish_button.pack() self.text_container.place(relx=SCREENS_REL_X, rely=SCREEN_REL_Y_45, anchor=CENTER) def on_show_frame(self): self.filenames.configure(text=("\n".join([ "Left video:", self.controller.left_video_filename_sr, "", "Right video:", self.controller.right_video_filename_sr ]))) def on_hide_frame(self): pass
class VideoScanProgressScreen(GuiBaseFrame): def __init__(self, parent, controller, **kw): GuiBaseFrame.__init__(self, parent, controller, **kw) self.counting_left_frames = None def init_widgets(self): self.content_wrapper = Frame(self) self.content_wrapper.configure(background="white") self.screen_title = Header1Label( self.content_wrapper, text="Scanning video for information...\n") self.progress_bar = Progressbar(self.content_wrapper, orient=HORIZONTAL, mode="indeterminate", length=WINDOW_WIDTH / 2) self.wait_text = PLabel( self.content_wrapper, text="\nThis might take a few minutes." "\nPlease do not change the video files while this is running.\n") self.left_frames_count = PLabel(self.content_wrapper, text=LEFT_FRAMES_COUNT_PREFIX + "0") self.right_frames_count = PLabel(self.content_wrapper, text=RIGHT_FRAMES_COUNT_PREFIX + "0") self.elapsed_time_label = PLabel(self.content_wrapper) self.empty_space = PLabel(self.content_wrapper, text=" ") self.next_button = Button( self.content_wrapper, text="Next", state=DISABLED, command=lambda: self.controller.show_next_frame()) def add_widgets_to_frame(self): self.screen_title.pack() self.progress_bar.pack() self.wait_text.pack() self.left_frames_count.pack() self.right_frames_count.pack() self.elapsed_time_label.pack() self.empty_space.pack() self.next_button.pack() self.content_wrapper.place(relx=SCREENS_REL_X, rely=SCREEN_REL_Y_45, anchor=CENTER) def on_show_frame(self): self.start_time = time.time() self.progress_bar.start() self.frame_count_thread = threading.Thread( target=self.controller.video_frame_loader.count_frames_in_videos, kwargs={"controller": self.controller}) self.frame_count_thread.start() self.master.after(50, self.check_thread) def update_frame(self, data): if LEFT_FRAMES_COUNT_PREFIX in data: self.left_frames_count.configure(text=data) if RIGHT_FRAMES_COUNT_PREFIX in data: self.right_frames_count.configure(text=data) self.elapsed_time_label.configure( text=ELAPSED_TIME_PREFIX + str(datetime.timedelta(seconds=int(time.time() - self.start_time)))) def on_hide_frame(self): self.progress_bar.stop() def check_thread(self): if self.frame_count_thread.is_alive(): self.master.after(50, self.check_thread) else: self.progress_bar.stop() self.wait_text.configure(text="\nDone!\nPress Next to continue.\n") self.next_button.configure(state=NORMAL)
def on_show_frame(self): self.canvas_wrappers = [] self.canvases = [] self.page_num = 0 if len(self.controller.sr_results) == 0: self.controller.show_frame(SrNoFramesFoundScreen) else: pages = int(ceil(len(self.controller.sr_results) / 10.0)) for page in range(0, pages): canvas_wrapper = Frame(self.content_wrapper, borderwidth="1", relief="solid") canvas = Canvas(canvas_wrapper, width=int(WINDOW_WIDTH * 7 / 8), height=(WINDOW_HEIGHT * 2 / 3)) scroll_bar = Scrollbar(canvas_wrapper, orient=VERTICAL, command=canvas.yview) results_list_frame = Frame(canvas) canvas.configure(yscrollcommand=scroll_bar.set) canvas.create_window(0, 0, window=results_list_frame) canvas.bind_all("<Up>", self.on_up_key) canvas.bind_all("<Down>", self.on_down_key) canvas.bind_all("<Left>", self.on_left_key) canvas.bind_all("<Right>", self.on_right_key) canvas.grid(row=0, column=0, sticky="nsew") scroll_bar.grid(row=0, column=1, sticky="ns") canvas_wrapper.grid(row=2, column=0, columnspan=3, sticky="nsew") select_buttons_on_page = [] for row in range(0, RESULTS_PER_PAGE): result_num = page * RESULTS_PER_PAGE + row if result_num < len(self.controller.sr_results): frame_num = self.controller.sr_results[result_num][ FRAME_NUM_LABEL] result_entry = Frame(results_list_frame, borderwidth="1", relief="solid") description = PLabel( result_entry, text="Frame #" + str(int(frame_num)) + ", Time: " + str(datetime.timedelta(seconds=frame_num / 30))) preview_wrapper = Frame(result_entry) left_video_preview = Label( preview_wrapper, image=self.controller.sr_results[result_num][LEFT]) right_video_preview = Label( preview_wrapper, image=self.controller.sr_results[result_num] [RIGHT]) select_button = SrSelectButton( preview_wrapper, self.controller, self.controller.sr_results[result_num] [SR_MAP_LABEL], text="Select") select_buttons_on_page.append(select_button) description.pack() left_video_preview.grid(row=row, column=0) right_video_preview.grid(row=row, column=1) select_button.grid(row=row, column=2) preview_wrapper.pack() result_entry.pack() for i in range(0, len(select_buttons_on_page)): select_buttons_on_page[i].configure( command=select_buttons_on_page[i].use_sr_map) self.master.update_idletasks() canvas.config(scrollregion=canvas.bbox("all")) canvas.yview_moveto(0) self.canvas_wrappers.append(canvas_wrapper) self.canvases.append(canvas) self.prev_result_page = Button( self.content_wrapper, text="<", command=lambda: self.prev_page_command()) self.page_info_label = PLabel( self.content_wrapper, text=get_page_info_label_message(self.page_num, len(self.canvases), RESULTS_PER_PAGE)) self.next_result_page = Button( self.content_wrapper, text=">", command=lambda: self.next_page_command()) self.prev_result_page.grid(row=3, column=0) self.page_info_label.grid(row=3, column=1) self.next_result_page.grid(row=3, column=2) self.canvas_wrappers[self.page_num].tkraise()
class AbstractTimeSelectionBaseScreen(GuiBaseFrame): def __init__(self, parent, controller, **kw): GuiBaseFrame.__init__(self, parent, controller, **kw) self.input_checks = [] self.set_input_checks() def init_widgets(self): self.content_wrapper = Frame(self) self.screen_title = Header1Label(self.content_wrapper) self.screen_instruction_1_label = PLabel(self.content_wrapper) self.input_content_wrapper = Frame(self.content_wrapper) self.hour_input, self.minute_input, self.seconds_input = setup_hms_input( self, self.input_content_wrapper) self.error_message_label = PLabel(self.content_wrapper, fg="red") self.button_wrapper = Frame(self.content_wrapper) self.back_button = Button(self.button_wrapper, text="Back", command=lambda: self.prev_button_command()) self.next_button = Button(self.button_wrapper, text="Next", command=lambda: self.next_button_command()) def add_widgets_to_frame(self): GuiBaseFrame.add_widgets_to_frame(self) def on_show_frame(self): GuiBaseFrame.on_show_frame(self) def update_frame(self, data): GuiBaseFrame.update_frame(self, data) def on_hide_frame(self): GuiBaseFrame.on_hide_frame(self) def set_input_checks(self): raise NotImplementedError def on_input_check_success(self): raise NotImplementedError def next_button_command(self): if self.perform_input_checks(): self.set_error_message("") self.on_input_check_success() self.controller.show_next_frame() def prev_button_command(self): self.controller.show_prev_frame() def perform_input_checks(self): for input_check in self.input_checks: if not input_check(self): return False return True def pack_title_and_instruction_widgets(self): self.screen_title.pack() self.screen_instruction_1_label.pack() # Packs inputs, error message labels, and buttons def pack_lower_half_widgets(self): self.input_content_wrapper.pack() self.error_message_label.pack() self.back_button.grid(row=0, column=0) self.next_button.grid(row=0, column=1) self.button_wrapper.pack() def set_title(self, title): self.screen_title.configure(text=title) def set_instruction_1_text(self, text): self.screen_instruction_1_label.configure(text=text) def set_error_message(self, error_message): self.error_message_label.configure(text=error_message) def add_input_check(self, input_check_lambda): self.input_checks.append(input_check_lambda)
class AbstractProgressScreen(GuiBaseFrame): # Backend logic thread should be making calls to controller.update_frame() to update the UI while logic runs. def __init__(self, parent, controller, backend_logic_function, **kw): GuiBaseFrame.__init__(self, parent, controller, **kw) self.backend_logic_function = backend_logic_function def init_widgets(self): self.content_wrapper = Frame(self) self.content_wrapper.configure(bg="white") self.screen_title = Header1Label(self.content_wrapper) self.empty_space_1 = PLabel(self.content_wrapper) self.progress_bar_control_var = DoubleVar() self.progress_bar = Progressbar(self.content_wrapper, orient=HORIZONTAL, mode="determinate", length=WINDOW_WIDTH / 2, variable=self.progress_bar_control_var) self.wait_text = PLabel(self.content_wrapper) self.information_display = PLabel(self.content_wrapper) self.empty_space_2 = PLabel(self.content_wrapper) self.next_button = Button(self.content_wrapper, text="Next", state=DISABLED, command=lambda: self.on_next_button()) def add_widgets_to_frame(self): self.screen_title.pack() self.empty_space_1.pack() self.progress_bar.pack() self.wait_text.pack() self.information_display.pack() self.empty_space_2.pack() self.next_button.pack() self.content_wrapper.place(relx=SCREENS_REL_X, rely=SCREEN_REL_Y_45, anchor=CENTER) def on_show_frame(self): self.wait_text.configure( text="\nThis might take a few minutes." "\nPlease do not change the video files while this is " "running.\n") self.start_time = time.time() self.backend_logic_thread = threading.Thread( target=self.backend_logic_function, kwargs={"controller": self.controller}) self.backend_logic_thread.start() self.master.after(THREAD_CHECK_ALIVE_INTERVAL_MS, self.check_thread) # Data should be a dictionary with keys "percent_done" and "message_list". def update_frame(self, data): percent_done = data[PROGRESS_SCREEN_PERCENT_DONE] message_list = data[PROGRESS_SCREEN_MESSAGE_LIST] self.progress_bar_control_var.set(percent_done) elapsed_time_seconds = int(time.time() - self.start_time) elapsed_time_message = ELAPSED_TIME_PREFIX + str( datetime.timedelta(seconds=elapsed_time_seconds)) if elapsed_time_seconds == 0: estimated_time_left_string = ESTIMATED_TIME_LEFT_PREFIX + "Calculating..." else: estimated_time_left_seconds = int( elapsed_time_seconds / percent_done * 100.0) - elapsed_time_seconds estimated_time_left_string = ESTIMATED_TIME_LEFT_PREFIX + \ str(datetime.timedelta(seconds=estimated_time_left_seconds)) message_list.append(elapsed_time_message) message_list.append(estimated_time_left_string) self.set_information_display_text(message_list) def on_hide_frame(self): self.progress_bar.stop() def set_title(self, title): self.screen_title.configure(text=title) def set_information_display_text(self, message_list): self.information_display.configure(text=("\n".join(message_list))) def check_thread(self): if self.backend_logic_thread.is_alive(): self.master.after(THREAD_CHECK_ALIVE_INTERVAL_MS, self.check_thread) else: self.progress_bar.stop() self.wait_text.configure(text="\nDone!\nPress Next to continue.\n") self.next_button.configure(state=NORMAL) def on_next_button(self): self.controller.show_next_frame()