Beispiel #1
0
class UITester(TkApplication):
    def __init__(self, uifile, rootwidget, rootmenu=None, master=None):
        self.uifile = uifile
        self.rootwidget = rootwidget
        self.rootmenu = rootmenu
        TkApplication.__init__(self, master)

    def _create_ui(self):
        self.builder = Builder()
        self.builder.add_from_file(self.uifile)
        self.builder.get_object(self.rootwidget, self.master)

        if self.rootmenu:
            menu = self.builder.get_object(self.rootmenu, top)
            self.set_menu(menu)

        #show callbacks defined
        bag = {}
        callbacks = self.builder.connect_callbacks({})
        if callbacks is not None:
            for cb in callbacks:

                def create_cb(cbname):
                    def dummy_cb(event=None):
                        print('on:', cbname)

                    return dummy_cb

                bag[cb] = create_cb(cb)
            self.builder.connect_callbacks(bag)

        self.set_title('Pygubu UI Tester')
        self.set_resizable()
Beispiel #2
0
class UITester(TkApplication):
    def __init__(self, uifile, rootwidget, rootmenu=None, master=None):
        self.uifile = uifile
        self.rootwidget = rootwidget
        self.rootmenu = rootmenu
        TkApplication.__init__(self, master)

    def _create_ui(self):
        self.builder = Builder()
        self.builder.add_from_file(self.uifile)
        self.builder.get_object(self.rootwidget, self.master)

        if self.rootmenu:
            menu = self.builder.get_object(self.rootmenu, top)
            self.set_menu(menu)

        #show callbacks defined
        bag = {}
        callbacks = self.builder.connect_callbacks({})
        if callbacks is not None:
            for cb in callbacks:
                def create_cb(cbname):
                    def dummy_cb(event=None):
                        print('on:', cbname)
                    return dummy_cb
                bag[cb] = create_cb(cb)
            self.builder.connect_callbacks(bag)
            

        self.set_title('Pygubu UI Tester')
        self.set_resizable()
Beispiel #3
0
class UITester(TkApplication):
    def _create_ui(self):
        self.builder = Builder()
        self.builder.add_from_file(sys.argv[1])
        self.builder.get_object('mainwindow', self.master)

        try:
            menu = self.builder.get_object('mainmenu', top)
            self.set_menu(menu)
        except:
            pass

        #show callbacks defined
        self.builder.connect_callbacks({})

        self.set_title('Pygubu UI tester')
        self.set_resizable()
Beispiel #4
0
class UITester(TkApplication):
    def _create_ui(self):
        self.builder = Builder()
        self.builder.add_from_file(sys.argv[1])
        self.builder.get_object('mainwindow', self.master)

        try:
            menu = self.builder.get_object('mainmenu', top)
            self.set_menu(menu)
        except:
            pass

        #show callbacks defined
        self.builder.connect_callbacks({})

        self.set_title('Pygubu UI tester')
        self.set_resizable()
Beispiel #5
0
class AllCanvasTab(TkApplication):
    def _create_ui(self):
        self.pygubu_builder = Builder()
        self.pygubu_builder.add_from_file(path.join(SCRIPT_DIR, "forms", "all_screens_tab.ui"))
        self.canvas = list()
        self.predator_draw_object = [None, None, None, None]
        self.setup()

    def setup(self):
        self.canvas.append(self._create_canvas('canvas_one'))
        self.canvas.append(self._create_canvas('canvas_two'))
        self.canvas.append(self._create_canvas('canvas_three'))
        self.canvas.append(self._create_canvas('canvas_four'))

    def _create_canvas(self, identifier):
        self.pygubu_builder.get_object(identifier + '_label', self.master)
        return self.pygubu_builder.get_object(identifier, self.master)

    def change_background(self, color, id_number):
        self.canvas[id_number].configure(background=color)
Beispiel #6
0
class SecondaryWindow(TkApplication):
    def _create_ui(self):
        self.pygubu_builder = Builder()
        self.pygubu_builder.add_from_file(path.join(SCRIPT_DIR, "forms", "secondary_window.ui"))

        self.style = Style()

        self.canvas = list()
        self.predator_draw_object = [None, None, None, None]

        self.current_background_color = BACKGROUND_COLOR

        self.setup()

    def setup(self):
        self.set_title("Piscis")
        self.pygubu_builder.get_object('main_frame', self.master)

        self.canvas.append(self._create_canvas('canvas_one'))
        self.canvas.append(self._create_canvas('canvas_two'))
        self.canvas.append(self._create_canvas('canvas_three'))
        self.canvas.append(self._create_canvas('canvas_four'))

        self.change_background_color(BACKGROUND_COLOR)

    def _create_canvas(self, identifier):
        return self.pygubu_builder.get_object(identifier, self.master)

    def set_fullscreen(self):
        self.master.overrideredirect(True)
        self.master.geometry("%dx%d+0+0" % (self.master.winfo_screenwidth(), self.master.winfo_screenheight()))

    def change_background_color(self, color):
        self.style.configure('TFrame', background=color)
        self.current_background_color = color

    def change_canvas_background(self, color, id_number):
        self.canvas[id_number].configure(background=color)
Beispiel #7
0
class Visualizer(Subject, Observer):
    """ A visualizer gui which waits for updates and provides updates on user actions. """

    def __init__(self, master):
        """ Initialises this gui with an interface. """
        Subject.__init__(self)  # Call parent constructors
        Observer.__init__(self)
        self._update_thread = None  # Thread to update the graphs
        self._builder = Builder()   # Setup form from build file
        self._builder.add_from_file("PartyProblemSimulator/Visualizer/gui.ui")
        self.mainwindow = self._builder.get_object("frm_main")
        self._builder.get_object("cnv_display").config(width=250, height=250)
        self._builder.get_object("cnv_graph_fitness").config(width=500, height=250)
        self._builder.get_object("cnv_graph_evaluations").config(width=500, height=250)
        self._setup_eventhandlers()

    def _setup_eventhandlers(self): # pragma : no cover
        """ Sets the event handlers for form controls. """
        btn_solve = self._builder.get_object("btn_solve")
        btn_solve.config(command=self._btn_solve_press)

    def _btn_solve_press(self):
        """ Notify observers that a problem is ready to be solved. """
        if self._validate_input(): # Extract form information if valid
            self._notify_observers()

    def _validate_input(self):
        """ Extracts and validates the input. """
        valid = True
        clique_size = self._builder.get_object("tb_clique_size").get()
        graph_size = self._builder.get_object("tb_graph_size").get()
        method = self._builder.get_object("cb_method").get()

        # Validation
        try:
            graph_size = int(graph_size)
            if graph_size < 1:
                raise Exception()
        except Exception:
            valid = False
            self._builder.get_object("lbl_error").config(text="Graph size must be an integer > 1.")
        
        try:
            clique_size = int(clique_size)
            if (clique_size <= 1) or (clique_size > graph_size):
                raise Exception()
        except Exception:
            valid = False
            self._builder.get_object("lbl_error").config(text="Clique size must be an integer > 1.")
        
        if (method not in ["BlindGA", "EvoSAP", "EvoSAP1", "EvoSAP2", "FlipGA", "FlipGA1", "FlipGA2"]) and valid:
            self._builder.get_object("lbl_error").config(text="Please select a method from the list provided.")
            valid = False
        
        if valid:   # Reset error label if entry is valid.
            self._builder.get_object("lbl_error").config(text="")

        return valid
    
    def _update_gui(self, generation, eval_count, fitness, history, finished, graph):# pragma: no cover
        """ Updates the relevant gui components. """
        self._builder.get_object("lbl_generations").config(text="Generation: {}".format(generation))
        self._builder.get_object("lbl_eval_count").config(text="Eval Count: {}".format(eval_count))
        self._builder.get_object("lbl_best_fitness").config(text="Best Fitness: {0:.2f}/1".format(fitness))
        if finished:
            self._builder.get_object("lbl_error").config(text="Finished!")
            self._builder.get_object("btn_solve").config(state="normal")
        else:
            self._builder.get_object("lbl_error").config(text="Computing...")
        # Update plots on seperate threads for efficiency
        plots_thread = Thread(target=self._draw_plots, args=(history,))
        graph_thread = Thread(target=self._draw_graph, args=(graph,))
        plots_thread.start()
        graph_thread.start()
        plots_thread.join()
        graph_thread.join()

    def _draw_graph(self, graph):
        """ Draws the graph provided. """
        cnv_display = self._builder.get_object("cnv_display")
        cnv_display.delete("all")   # Clear canvas

        vertex_size = 10
        edge_thickness = 1
        # Draw vertices
        vertex_offset = vertex_size / 2
        center_canvas = (cnv_display.winfo_width() / 2, cnv_display.winfo_height() / 2)
        distance = center_canvas[0] / 1.5 #Quater of the screen
        degrees = 360 / len(graph.get_vertices())
        for vertex in graph.get_vertices():
            # Calculate a new location for the vertex on canvas
            center_x = center_canvas[0] + ((distance) * sin(degrees * vertex.get_id()))
            center_y = center_canvas[1] + ((distance) * cos(degrees * vertex.get_id()))
            vertex.set_location(x=center_x, y=center_y)
            cnv_display.create_oval(center_x - vertex_offset, center_y - vertex_offset, center_x + vertex_offset, center_y + vertex_offset, fill='cyan')

        # Draw edges
        for edge in graph.get_edges():
            start_x = edge.get_origin().get_location()[0]   # Get locations
            start_y = edge.get_origin().get_location()[1]
            end_x = edge.get_target().get_location()[0]
            end_y = edge.get_target().get_location()[1]
            colour = self._determine_colour(edge.get_colour())  # Determine colour
            cnv_display.create_line(start_x, start_y, end_x, end_y, width=edge_thickness, fill=colour)
    
    def _draw_plots(self, history): # pragma: no cover
        """ Draws the plots. """
        cnv_graph_fitness = self._builder.get_object("cnv_graph_fitness")
        cnv_graph_evaluations = self._builder.get_object("cnv_graph_evaluations")
        cnv_graph_fitness.delete("all")
        cnv_graph_evaluations.delete("all")
        # Determine axis locations
        origin = (50, 220)
        end_x = (origin[0] + 430, origin[1])
        end_y = (origin[0], origin[1] - 210)
        # Draw graph axis
        cnv_graph_fitness.create_line(origin[0], origin[1], end_x[0], end_x[1], fill="black")
        cnv_graph_fitness.create_line(origin[0], origin[1], end_y[0], end_y[1], fill="black")
        cnv_graph_evaluations.create_line(origin[0], origin[1], end_x[0], end_x[1], fill="black")
        cnv_graph_evaluations.create_line(origin[0], origin[1], end_y[0], end_y[1], fill="black")
        # Label axis
        horizontal_label_location = ((origin[0] + end_x[0])/2, origin[1] + 20)
        cnv_graph_fitness.create_text(horizontal_label_location[0], horizontal_label_location[1], font="arial 10", text="Generation")
        cnv_graph_evaluations.create_text(horizontal_label_location[0], horizontal_label_location[1], font="arial 10", text="Generation")
        # Draw Horizontal labels
        label_x = 0
        label_y = origin[1] + 10
        if len(history['fitness']) >= 10:
            horizontal_increment = (end_x[0] - origin[0]) / 10  # Calculate increments to do horizontally
            count = 0
            while count < 11:
                label_x = origin[0] + (count * horizontal_increment)    # Determine axis details
                generation = len(history['fitness']) / 10
                cnv_graph_fitness.create_text(label_x, label_y, font="arial 8", text="{}".format(int(generation * count)))  # Label axis
                cnv_graph_evaluations.create_text(label_x, label_y, font="arial 8", text="{}".format(int(generation * count)))
                cnv_graph_fitness.create_line(label_x, label_y - 12, label_x, label_y - 8)  # Show a small line on the axis
                cnv_graph_evaluations.create_line(label_x, label_y - 12, label_x, label_y - 8)
                count = count + 1
        else:   # Special case if there are < 10 cases
            no_increments = len(history['fitness'])
            horizontal_increment = (end_x[0] - origin[0]) / (no_increments + 1)
            count = 1
            while count <= no_increments:
                label_x = origin[0] + (count * horizontal_increment)    # Determine axis details
                generation = len(history['fitness']) / 10
                cnv_graph_fitness.create_text(label_x, label_y, font="arial 8", text="{}".format(int(generation * count)))  # Label axis
                cnv_graph_evaluations.create_text(label_x, label_y, font="arial 8", text="{}".format(int(generation * count)))
                cnv_graph_fitness.create_line(label_x, label_y - 12, label_x, label_y - 8)  # Show a small line on the axis
                cnv_graph_evaluations.create_line(label_x, label_y - 12, label_x, label_y - 8)
                count = count + 1
            
        # Draw points and labels
        fitness_thread = Thread(target=self._draw_fitness_points, args=(cnv_graph_fitness, origin, end_y, end_x, history['fitness'],))
        evals_thread = Thread(target=self._draw_evaluation_points, args=(cnv_graph_evaluations, origin, end_y, end_x, history['evaluation'],))
        fitness_thread.start()
        evals_thread.start()
        fitness_thread.join()
        evals_thread.join()

        
    def _draw_fitness_points(self, cnv_graph_fitness, graph_origin, vertical_end, horizontal_end, fitness_history): # pragma: no cover
        """ Draws the fitness graph. """
        # Draw vertical axis values (Increments of 0.1 from 0)
        increment = (graph_origin[1] - vertical_end[1]) / 10
        count = 0
        while count < 1:
            text_location = (graph_origin[0], graph_origin[1] - ((count * 10) * increment))    # Add the label slightly to the left of axis
            cnv_graph_fitness.create_text(text_location[0] - 15, text_location[1], font="arial 8", text="{0:.1f}".format(count))   # Create label
            cnv_graph_fitness.create_line(text_location[0] - 2, text_location[1], text_location[0] + 2, text_location[1])
            count = count + 0.1
        # Draw points
        horizontal_increment = (horizontal_end[0] - graph_origin[0]) / len(fitness_history)    # Calculate an even spacing between fitness values
        count = 0
        previous_point = None
        if len(fitness_history) == 1:   # Special case of a single point
            location_y = graph_origin[1] - (fitness_history[0] * (graph_origin[1] - vertical_end[1]))
            location_x = graph_origin[0] + ((horizontal_end[0] - graph_origin[0]) / 2)
            cnv_graph_fitness.create_text(location_x, location_y, fill="blue", text="x")
        else:
            while count < len(fitness_history): # Do a line graph
                location_y = graph_origin[1] - (fitness_history[count] * (graph_origin[1] - vertical_end[1]))
                location_x = graph_origin[0] + (1 * (horizontal_increment * count)) + 5
                current_point = (location_x, location_y)
                if previous_point is not None:
                    cnv_graph_fitness.create_line(previous_point[0], previous_point[1], current_point[0], current_point[1], fill="blue")
                previous_point = current_point
                count = count + 1

    def _draw_evaluation_points(self, cnv_graph_evaluations, graph_origin, vertical_end, horizontal_end, evaluation_history): # pragma: no cover
        """ Draws the evaluation graph. """
        # Draw vertical axis values (Increments of 0.1 from 0)
        increment = (graph_origin[1] - vertical_end[1]) / 10
        count = 0
        while count <= 1:
            text_location = (graph_origin[0], graph_origin[1] - ((count * 10) * increment))    # Add the label slightly to the left of axis
            cnv_graph_evaluations.create_text(text_location[0] - 25, text_location[1], font="arial 8", text="{}".format(int(evaluation_history[-1] * count) + 1))   # Create label
            cnv_graph_evaluations.create_line(text_location[0] - 2, text_location[1], text_location[0] + 2, text_location[1])
            count = count + 0.1
        # Draw points
        horizontal_increment = (horizontal_end[0] - graph_origin[0]) / len(evaluation_history)    # Calculate an even spacing between evaluation values
        count = 0
        previous_point = None
        if len(evaluation_history) == 1:   # Special case of a single point
            location_y = vertical_end[1]    # Top most point
            location_x = graph_origin[0] + ((horizontal_end[0] - graph_origin[0]) / 2)
            cnv_graph_evaluations.create_text(location_x, location_y, fill="blue", text="x")
        else:
            while count < len(evaluation_history): # Do a line graph
                location_y = graph_origin[1] - ((evaluation_history[count] / evaluation_history[-1]) * (graph_origin[1] - vertical_end[1])) # position varies
                location_x = graph_origin[0] + (count * (horizontal_increment)) + 5
                current_point = (location_x, location_y)
                if previous_point is not None:
                    cnv_graph_evaluations.create_line(previous_point[0], previous_point[1], current_point[0], current_point[1], fill="blue")
                previous_point = current_point
                count = count + 1

    def _determine_colour(self, colour_code):
        """ Determines the colour code of an edge. """
        if colour_code == 0:
            return 'red'
        elif colour_code == 1:
            return 'green'
        elif colour_code == 2:
            return 'cyan'
        else:
            return 'blue'

    def _notify_observers(self):
        """ Notifies observers. """
        clique_size = int(self._builder.get_object("tb_clique_size").get()) # Get update parameters
        graph_size = int(self._builder.get_object("tb_graph_size").get())
        method = self._builder.get_object("cb_method").get()
        update_argument = {"clique_size": clique_size, "graph_size": graph_size, "method": method}    # Argument to update observers with
        for o in self._observers:
            o.update(update_argument)
        # Disable solve button
        self._builder.get_object("btn_solve").config(state="disabled")

    def update(self, args):
        """ Update details on form to show progress if required. """
        if ('graph' and 'generation' and 'evals' and 'best_fitness' and 'finished' and 'history') in args:
            if (self._update_thread is None) or (not self._update_thread.isAlive()):
                self._update_thread = Thread(target=self._update_gui, args=(args['generation'], args['evals'], float(args['best_fitness']), args['history'], args['finished'], args['graph'],))
                self._update_thread.start()
Beispiel #8
0
class MainWindow(TkApplication):
    def _create_ui(self):
        self.pygubu_builder = Builder()
        self.pygubu_builder.add_from_file(path.join(SCRIPT_DIR, "forms", "main_window.ui"))

        self.secondary_window = SecondaryWindow(Toplevel())
        # self.secondary_window.master.withdraw()

        self.predator = [None, None, None, None]
        self.drawer = PredatorDrawer(None)
        self.current_tab = 0
        self.tabs = list()
        self.remaining_secs = 0
        self.all_tab = None
        self.after_id = 0

        self.isDrawOnAllScreenActive = [True, True, True, True]

        self.predator_factory = PredatorFactory()

        self.setup()

    def setup(self):
        self.set_title(PISCIS_TITLE)

        self.pygubu_builder.get_object('main_frame', self.master)
        self.set_menu(self.pygubu_builder.get_object('main_menu', self.master))

        self.create_tabs()

        self.pygubu_builder.connect_callbacks(self)

        for i, item in enumerate(self.predator):
            draw_all_outlines(self.tabs[i], self.all_tab, self.secondary_window, i)

    def create_tabs(self):
        self.all_tab = self._create_canvas_tab('tab_all_screens')
        self.tabs.append(self._create_canvas_tab('tab_single_tab_one'))
        self.tabs.append(self._create_canvas_tab('tab_single_tab_two'))
        self.tabs.append(self._create_canvas_tab('tab_single_tab_three'))
        self.tabs.append(self._create_canvas_tab('tab_single_tab_four'))

    def _create_canvas_tab(self, identifier):
        if identifier == 'tab_all_screens':
            return AllCanvasTab(self.pygubu_builder.get_object(identifier, self.master))
        else:
            self.current_tab += 1
            return SingleCanvasTab(self.pygubu_builder.get_object(identifier, self.master), self.current_tab - 1, self)

    @staticmethod
    def on_about():
        showinfo(PISCIS_TITLE, PISCIS_TITLE + " - " + PISCIS_VERSION + "\n" + PISCIS_CONTACT)

    def on_exit(self):
        self.stop_all_simulations()
        self.master.quit()

    def stop_all_simulations(self):
        for i, item in enumerate(self.predator):
            self.tabs[i].on_stop()

    def on_fullscreen(self):
        self.secondary_window.set_fullscreen()

    def on_change_fullscreen(self):
        new_color = askcolor(color=self.secondary_window.current_background_color, title="Change Background-Color")[1]
        self.secondary_window.change_background_color(new_color)

    def create_predator(self, color, target_diameter, scaling_velocity, starting_position=None):
        if starting_position is None:
            starting_position = .5, .5

        self.predator_factory.starting_position = starting_position
        self.predator_factory.target_diameter = target_diameter
        self.predator_factory.scaling_velocity = scaling_velocity
        self.predator_factory.color = color

        return self.predator_factory.create()

    def get_predator_color(self):
        return self.predator_factory.color

    def start_predator(self, predator, id_number):
        if predator is None:
            showinfo("No Predator found", "Please place a stimuli first!")
            return
        self.isDrawOnAllScreenActive[id_number] = True
        predator.start_scaling(int(time.time() * 1000))
        self.predator[id_number] = predator
        self.drawer.start()
        self.start_update()

    def start_update(self):
        self.after_id = self.master.after(25, self.update)

    def update(self):
        self.after_id = self.master.after(25, self.update)
        self.render()

    def render(self):
        for i, item in enumerate(self.predator):
            self.draw_predators(i, item)
            # self.drawer.draw_all_outlines(self.tabs[i], self.all_tab, self.secondary_window, i)

    def draw_predators(self, i, item):
        if item is not None:
            self.drawer.predator = item
            self.draw_predators_on_all_screens(i)

    def draw_predators_on_all_screens(self, i):
        if self.isDrawOnAllScreenActive[i]:
            self.drawer.draw_predator(self.tabs[i], self.all_tab, self.secondary_window, i)

    def change_background_color_of_all_canvas(self, id_number, color):
        self.all_tab.change_background(id_number, color)
        self.secondary_window.change_canvas_background(id_number, color)

    def stop_drawing(self):
        self.drawer.stop()
Beispiel #9
0
class SingleCanvasTab(TkApplication):
    def __init__(self, master, id_number, parent=None):
        TkApplication.__init__(self, master)
        self.id_number = id_number
        self.parent = parent

        self.change_background_color(self.current_background_color)
        self.target_diameter = 0
        self.scaling_velocity = 0

        self.remaining_secs_run = 0
        self.remaining_secs_pause = 0

        self.predator = None
        self.predator_draw_object = None

        self.starting_position = None

        self.run_timer = None
        self.pause_timer = None

    def _create_ui(self):
        self.pygubu_builder = Builder()
        self.pygubu_builder.add_from_file(path.join(SCRIPT_DIR, "forms", "single_canvas_tab.ui"))

        self.setup()

    def setup(self):
        self.canvas = self.pygubu_builder.get_object('canvas', self.master)
        self.canvas.bind("<Button-1>", self.set_starting_position)

        self.current_background_color = BACKGROUND_COLOR
        self.color = PREDATOR_COLOR

        self._create_scale_slider()
        self._create_speed_slider()
        self._create_interval_controls()
        self._create_buttons()

        self.pygubu_builder.connect_callbacks(self)

    def _create_scale_slider(self):
        self.pygubu_builder.get_object('scale', self.master)

    def _create_speed_slider(self):
        self.pygubu_builder.get_object('speed', self.master)

    def _create_interval_controls(self):
        self.pygubu_builder.get_object('interval', self.master)
        self.pygubu_builder.get_object('interval_run', self.master)
        self.pygubu_builder.get_object('interval_pause', self.master)

        self._create_running_interval_settings()
        self._create_pausing_interval_settings()

    def _create_pausing_interval_settings(self):
        self.interval_seconds_pause = self.pygubu_builder.get_object('spin_seconds_pause', self.master)
        self.interval_minutes_pause = self.pygubu_builder.get_object('spin_minutes_pause', self.master)
        self.remaining_secs_label_pause = self.pygubu_builder.get_object('remaining_secs_pause', self.master)

    def _create_running_interval_settings(self):
        self.interval_seconds_run = self.pygubu_builder.get_object('spin_seconds_run', self.master)
        self.interval_minutes_run = self.pygubu_builder.get_object('spin_minutes_run', self.master)
        self.remaining_secs_label_run = self.pygubu_builder.get_object('remaining_secs_run', self.master)

    def _create_buttons(self):
        self.pygubu_builder.get_object('background', self.master)
        self.pygubu_builder.get_object('stimuli_color', self.master)
        self.pygubu_builder.get_object('generate', self.master)
        self.pygubu_builder.get_object('simulate', self.master)

    def on_generate(self):
        self.canvas.delete(self.predator_draw_object)
        self.predator = self.parent.create_predator(self.color, self.target_diameter, self.scaling_velocity,
                                                    self.starting_position)
        self.draw_preview_predator()
        self.parent.isDrawOnAllScreenActive[self.id_number] = False
        self.starting_position = None

    def draw_preview_predator(self):
        drawer = PredatorDrawer(self.predator)
        width, height = self.canvas.winfo_width(), self.canvas.winfo_height()
        begin_x, begin_y, end_x, end_y = drawer.calculate_coordinates(width, height, self.target_diameter)
        self.predator_draw_object = self.canvas.create_oval(begin_x, begin_y, end_x,
                                                            end_y,
                                                            fill=self.color, outline=self.color)

    def on_background(self):
        new_color = askcolor(color=self.current_background_color, title="Change Background-Color")[1]
        self.change_background_color(new_color)

    def on_stimuli_color(self):
        new_color = askcolor(color=self.parent.get_predator_color(), title="Change Predator-Color")[1]
        self.color = new_color
        if self.predator is not None:
            self.predator.color = self.color

    def on_scale_slider(self, value):
        self.target_diameter = float(value)
        if self.predator is not None:
            self.predator.set_target_diameter(self.target_diameter)

    def on_speed_slider(self, value):
        self.scaling_velocity = float(value) / 5
        if self.predator is not None:
            self.predator.set_scaling_velocity(self.scaling_velocity)

    def on_start(self):
        self.parent.start_predator(self.predator, self.id_number)
        if self.remaining_secs_run > 0:
            self.update_pause_remaining_seconds_label()
            self.start_run_timer()

    def start_run_timer(self):
        self.run_timer = Timer(1.0, self.reduce_run_remaining_seconds)
        self.run_timer.start()

    def reduce_run_remaining_seconds(self):
        self.remaining_secs_run -= 1
        self.update_run_remaining_seconds_label()
        if int(self.remaining_secs_run) > 0:
            self.start_run_timer()
        else:
            self.on_stop()
            self.update_run_remaining_seconds_label()
            self.set_run_remaining_seconds()
            self.start_pause_timer()

    def start_pause_timer(self):
        self.pause_timer = Timer(1.0, self.reduce_pause_remaining_seconds)
        self.pause_timer.start()

    def reduce_pause_remaining_seconds(self):
        self.remaining_secs_pause -= 1
        self.update_pause_remaining_seconds_label()
        if int(self.remaining_secs_pause) > 0:
            self.start_pause_timer()
        else:
            self.update_pause_remaining_seconds_label()
            self.set_pause_remaining_seconds()
            self.on_start()

    def on_stop(self):
        self.stop_pause_timer()
        self.stop_run_timer()
        self.parent.stop_drawing()

    def stop_pause_timer(self):
        if self.pause_timer is not None:
            self.pause_timer.cancel()
            self.set_pause_remaining_seconds()

    def stop_run_timer(self):
        if self.run_timer is not None:
            self.run_timer.cancel()
            self.set_run_remaining_seconds()

    def on_pause_seconds_changed(self):
        self.set_pause_remaining_seconds()
        self.update_pause_remaining_seconds_label()

    def on_pause_minutes_changed(self):
        self.set_pause_remaining_seconds()
        self.update_pause_remaining_seconds_label()

    def set_pause_remaining_seconds(self):
        self.remaining_secs_pause = self.minutes_to_seconds(self.interval_minutes_pause.get()) + int(
            self.interval_seconds_pause.get())

    def update_pause_remaining_seconds_label(self):
        self.remaining_secs_label_pause.configure(text=self.remaining_secs_pause)

    def on_run_seconds_changed(self):
        self.set_run_remaining_seconds()
        self.update_run_remaining_seconds_label()

    def on_run_minutes_changed(self):
        self.set_run_remaining_seconds()
        self.update_run_remaining_seconds_label()

    def set_run_remaining_seconds(self):
        self.remaining_secs_run = self.minutes_to_seconds(self.interval_minutes_run.get()) + int(
            self.interval_seconds_run.get())

    def update_run_remaining_seconds_label(self):
        self.remaining_secs_label_run.configure(text=self.remaining_secs_run)

    def minutes_to_seconds(self, value):
        return int(value) * MIN_TO_SEC

    def change_background_color(self, color):
        self.canvas.configure(background=color)
        self.parent.change_background_color_of_all_canvas(color, self.id_number)
        self.current_background_color = color

    def set_starting_position(self, event):
        self.starting_position = event.x / self.canvas.winfo_width(), event.y / self.canvas.winfo_height()
        self.on_generate()
Beispiel #10
0
class MacronSetupWizard:
    def __init__(self):
        self.root = root = Tk()
        root.withdraw()
        root.title('Setup Wizard')
        root.geometry('500x360')
        root.iconbitmap(RESOURCE_PATH + 'icon.ico')

        # Center window
        root.update_idletasks()
        width = root.winfo_width()
        height = root.winfo_height()
        x = (root.winfo_screenwidth() // 2) - (width // 2)
        y = (root.winfo_screenheight() // 2) - (height // 2)
        root.geometry('{}x{}+{}+{}'.format(width, height, x, y))
        root.deiconify()

        root.resizable(width=False, height=False)

        self.settings = {
            'app_name': 'MacronApp',
            'install_path':
            'C:\Program Files',  # TODO: Get default install path
            'create_shortcut': True,
            'start_after_setup': True
        }

        with open(RESOURCE_PATH + '.setupdata') as f:
            setupData = load(f)
            self.settings['app_name'] = setupData['app_name']
            self.settings['app_repo_url'] = setupData['app_repo_url']

        with open(RESOURCE_PATH + 'LICENSE') as f:
            self.settings['app_license'] = f.read()

        with open(RESOURCE_PATH + 'intro-view.xml') as f:
            self.navigate(f.read())

        self.mainwindow = self.builder.get_object('Frame_0', root)
        self.root.title(self.settings['app_name'] + ' Setup Wizard')
        self.builder.get_object('WelcomeLabel').config(
            text='Welcome to the {} Setup Wizard'.format(
                self.settings['app_name']))
        self.builder.get_object('IntroLabel').config(
            text='''This wizard will install {} on your computer.

It is recommended that you close all other applications before continuing.

Click Next to continue, or Cancel to exit Setup.'''.format(
                self.settings['app_name']))
        # self.set_image(
        #   (160, 310),
        #   self.settings['setup_banner'],
        #   self.builder.get_object('SetupBanner')
        # )

        root.mainloop()

    def on_intro_next(self):
        with open(RESOURCE_PATH + 'license-view.xml') as f:
            self.navigate(f.read())

        # self.set_image(
        #   (60, 60),
        #   self.settings['setup_logo'],
        #   self.builder.get_object('SetupLogo')
        # )
        self.builder.get_object('LicenseInput').delete('1.0', END)
        self.builder.get_object('LicenseInput').insert(
            '1.0', self.settings['app_license'])
        self.builder.get_object('LicenseInput').config(state=DISABLED)
        self.builder.get_object('Radiobutton_5').select()
        self.builder.get_object('Button_2').configure(state=DISABLED)

    def on_license_next(self):
        with open(RESOURCE_PATH + 'settings-view.xml') as f:
            self.navigate(f.read())

        # self.set_image(
        #   (60, 60),
        #   self.settings['setup_logo'],
        #   self.builder.get_object('SetupLogo')
        # )
        self.builder.get_object('SetupReadyLabel').config(
            text='Setup is ready to download and install {} on your computer.'.
            format(self.settings['app_name']))
        self.builder.get_object('Entry_2').insert(
            0, self.settings['install_path'])
        self.builder.get_object('Checkbutton_3').select()
        self.builder.get_object('Checkbutton_4').select()

    def on_settings_next(self):
        self.settings['create_shortcut'] = self.builder.create_variable(
            'boolean:create_shortcut').get()
        self.settings['start_after_setup'] = self.builder.create_variable(
            'boolean:start_after_setup').get()

        with open(RESOURCE_PATH + 'download-view.xml') as f:
            self.navigate(f.read())

        # self.set_image(
        #   (60, 60),
        #   self.settings['setup_logo'],
        #   self.builder.get_object('SetupLogo')
        # )
        self.builder.get_object('FinishButton').config(state=DISABLED)
        self.downloadThread = threading.Thread(target=self.download)
        self.downloadThread.start()

    def on_license_back(self):
        with open(RESOURCE_PATH + 'intro-view.xml') as f:
            self.navigate(f.read())

    def on_settings_back(self):
        with open(RESOURCE_PATH + 'license-view.xml') as f:
            self.navigate(f.read())

    def on_not_accept(self):
        self.builder.get_object('Button_2').configure(state=DISABLED)

    def on_accept(self):
        self.builder.get_object('Button_2').configure(state=NORMAL)

    def on_browse_dir(self):
        response = filedialog.askdirectory(
            title='Please select installation path...')
        self.settings['install_path'] = response
        entry = self.builder.get_object('Entry_2')
        entry.delete(0, END)
        entry.insert(0, response)

    def download(self):
        self.builder.get_object('DownloadStatusLabel').config(
            text="Obtaining latest release...")

        def reporthook(blocknum, blocksize, totalsize):
            self.builder.get_object('DownloadStatusLabel').config(
                text="Downloading...")

            readsofar = blocknum * blocksize
            if totalsize > 0:
                percent = readsofar * 1e2 / totalsize
                self.builder.create_variable('double:download_progress').set(
                    percent)
                self.builder.get_object('DownloadRatio').config(
                    # text='{:.1} %'.format(percent)
                    text="{:.1f} / {:.1f} MB".format(readsofar /
                                                     1048576, totalsize /
                                                     1048576))

                if readsofar >= totalsize:  # near the end
                    self.builder.get_object('DownloadStatusLabel').config(
                        text="Download complete")
                    self.builder.get_object('RetryButton').config(
                        state=DISABLED)
            else:  # total size is unknown
                pass

        try:
            repoURL = urlopen(self.settings['app_repo_url'] + '/.setupdata')
            data = repoURL.read()
            encoding = repoURL.info().get_content_charset('utf-8')
            latestSetupData = loads(data.decode(encoding))

            try:  # download
                filehandle, _ = urlretrieve(
                    url=latestSetupData['app_repo_url'] +
                    latestSetupData['latest_windows_dist_url'],
                    reporthook=reporthook)

                try:  # install
                    self.builder.get_object('InstallStatusLabel').config(
                        text="Installing...")
                    ZipFile(filehandle).extractall(
                        self.settings['install_path'])
                    if self.settings['create_shortcut']:
                        CoInitialize()
                        appPath = '{}\\{}\\{}.exe'.format(
                            self.settings['install_path'],
                            self.settings['app_name'],
                            self.settings['app_name'])
                        self.createShortcut(path=os.path.join(
                            desktop(),
                            self.settings['app_name'].replace('_', ' ') +
                            '.lnk'),
                                            target=appPath,
                                            wDir='{}\\{}'.format(
                                                self.settings['install_path'],
                                                self.settings['app_name']),
                                            icon=appPath)
                    self.builder.get_object('InstallStatusLabel').config(
                        text="Installation complete!")
                    self.builder.get_object('FinishButton').config(
                        state=NORMAL)
                except:
                    messagebox.showwarning(
                        title='{} Setup Wizard'.format(
                            self.settings['app_name']),
                        message=
                        'Setup is unable to install additional files. Please try again.'
                    )
            except:
                messagebox.showwarning(
                    title='{} Setup Wizard'.format(self.settings['app_name']),
                    message=
                    'Setup is unable to download additional files. Please make sure that you have an internet connection, then click Retry.'
                )
        except:
            messagebox.showwarning(
                title='{} Setup Wizard'.format(self.settings['app_name']),
                message=
                'An unexpected error occured. Setup wizard is unable to obtain additional files. Click Retry.'
            )

    def on_finish(self):
        if self.settings['start_after_setup']:
            startfile('{}\\{}\\{}.exe'.format(self.settings['install_path'],
                                              self.settings['app_name'],
                                              self.settings['app_name']))

        self.root.destroy()

    def on_retry_download(self):
        response = messagebox.showwarning(
            type=messagebox.YESNO,
            title='{} Setup Wizard'.format(self.settings['app_name']),
            message='Are you sure you want to retry downloading?')

        if response == 'yes':
            self.downloadThread = threading.Thread(target=self.download)
            self.downloadThread.start()

    def on_cancel(self):
        response = messagebox.showwarning(
            type=messagebox.OKCANCEL,
            title='{} Setup Wizard'.format(self.settings['app_name']),
            message='Are you sure you want to cancel the installation process?'
        )

        if response == 'ok':
            # if self.downloadThread: self.downloadThread._Thread_stop()
            self.root.destroy()

    # Helpers
    def navigate(self, next_view_ui):
        self.builder = Builder()
        self.builder.add_from_string(next_view_ui)
        self.mainwindow = self.builder.get_object('Frame_0', self.root)
        self.builder.connect_callbacks(self)

    # convert bytes to MB.... GB... etc...
    def human_bytes(self, num):
        step_unit = 1000.0  #1024 bad the size
        for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
            if num < step_unit: return "%3.1f %s" % (num, x)
            num /= step_unit

    def createShortcut(self, path, target='', wDir='', icon=''):
        ext = path[-3:]
        if ext == 'url':
            shortcut = file(path, 'w')
            shortcut.write('[InternetShortcut]\n')
            shortcut.write('URL=%s' % target)
            shortcut.close()
        else:
            shell = Dispatch('WScript.Shell')
            shortcut = shell.CreateShortCut(path)
            shortcut.Targetpath = target
            shortcut.WorkingDirectory = wDir
            if icon == '':
                pass
            else:
                shortcut.IconLocation = icon
            shortcut.save()