Ejemplo n.º 1
0
class ViewportCard(object):
    '''
    Manages the graphical representation of a card in a
    Tkinter canvas. Creates and destroys items as necessary, facilitates
    editing, and so on and so forth.

    Members:
    * card: model.Card
    * viewport: GPViewport
    * gpfile: gpfile.GraphPaperFile, contains model.graph()
    * canvas: TKinter canvas we get drawn on
    * editing: bool, text is being edited
    * moving: bool, being dragged
    * moving_edgescroll_id: callback id to scroll periodically when hovering
      near edge of screen
    * resize_state: {}
    * resize_edgescroll_id: as moving_edgescroll_id
    * slot: calls callbacks whenever geometry changes
    * new_edge: if an edge is being dragged out from a handle, this is it.
    * card_after_new_edge: bool, if we should make a new card when edge is dropped.
    '''
    def __init__(self, viewport, gpfile, card):
        self.card = card
        self.viewport = viewport
        self.gpfile = gpfile
        self.canvas = viewport.canvas
        self.draw()
        self.editing = False
        self.moving = False
        self.moving_edgescroll_id = None
        self.resize_state = None
        self.resize_edgescroll_id = None
        # slot triggered when geometry (pos/size) changes
        # fn args: (self, x, y, w, h)
        self.geom_slot = Slot()
        self.deletion_slot = Slot()
        self.new_edge = None

    def draw(self):
        self.frame_thickness = 5
        self.window = ResizableCanvasFrame(self.canvas,
                                           self.card.x,
                                           self.card.y,
                                           self.card.w,
                                           self.card.h,
                                           min_width=MIN_CARD_SIZE,
                                           min_height=MIN_CARD_SIZE)
        self.text = ScrolledText(self.window, wrap=WORD)
        self.text.pack(expand=1, fill='both')
        # set up text for editing, dragging, deleting
        self.text.bind("<Button-1>", self.mousedown)
        self.text.bind("<Shift-Button-1>", self.shiftmousedown)
        self.text.bind("<Double-Button-1>", self.doubleclick)
        self.text.bind("<B1-Motion>", self.mousemove)
        self.text.bind("<ButtonRelease-1>", self.mouseup)
        self.text.bind("<FocusIn>", self.focusin)
        self.text.bind("<FocusOut>", self.focusout)
        self.text.bind("<Control-Delete>", self.ctrldelete)
        self.text.insert(END, self.card.text)
        # set up frame for resizing
        self.window.bind('<Configure>', self.configure)
        self.window.save_callback = self.save_card
        # draw edge handles
        self.edge_handles = None
        #self.redraw_edge_handles()

    def redraw_edge_handles(self):
        '''
        Either creates or modifies the edge handles, little circles poking
        out the side of the card, based on the current position and width.

        self.edge_handles is a list of itemids of the circles in (top,
        right, bottom, left) order.
        '''
        def create_circle(bbox):
            # create circle suitable for edge-handle use
            new = self.canvas.create_oval(bbox[0],
                                          bbox[1],
                                          bbox[2],
                                          bbox[3],
                                          fill='green',
                                          outline='')
            self.canvas.addtag_withtag('card_handle_tag',
                                       new)  # for z-ordering
            self.canvas.tag_bind(new, '<Button-1>', self.handle_click)
            self.canvas.tag_bind(new, '<Shift-Button-1>',
                                 self.handle_shift_click)
            self.canvas.tag_bind(new, '<B1-Motion>', self.handle_mousemove)
            self.canvas.tag_bind(new, '<ButtonRelease-1>', self.handle_mouseup)
            return new

        x, y = self.window.canvas_coords()
        w, h = self.window.winfo_width(), self.window.winfo_height()
        # 2*radius should be < MIN_CARD_SIZE, and offset < radius
        radius = 30
        offset = 19  # offset of center of circle from card edge
        left_coords = (x + offset, y + h / 2)
        right_coords = (x + w - offset, y + h / 2)
        top_coords = (x + w / 2, y + offset)
        bottom_coords = (x + w / 2, y + h - offset)
        all_coords = (top_coords, right_coords, bottom_coords, left_coords)
        bboxes = [(x - radius, y - radius, x + radius, y + radius)
                  for x, y in all_coords]
        if self.edge_handles:
            # move the edge handles
            for i, box in enumerate(bboxes):
                #self.canvas.coords(handle, box[0], box[1], box[2], box[3])
                self.canvas.delete(self.edge_handles[i])
                self.edge_handles[i] = create_circle(box)
                #self.canvas.itemconfig(handle, bbox = box)
        else:
            # create new ones
            self.edge_handles = [create_circle(b) for b in bboxes]
        # have to do this every time, every time we recreate the edge handles
        self.viewport.fix_z_order()

    def get_text(self):
        "gets the text from the actual editor, which may not be saved yet"
        return self.text.get('0.0', END)

    def save_text(self):
        # get text from window
        text = self.get_text()
        if text != self.card.text:
            self.card.text = text
            self.gpfile.commit()

    def canvas_coords(self):
        return self.window.canvas_coords()

    def start_moving(self, event):
        # set up state for a drag
        self.moving = True
        self.foocoords = (event.x, event.y)
        self.set_moving_edgescroll_callback()

    def edge_scroll(self):
        # if any edges are too close to the edge, move and scroll the canvas
        canvas_coords = self.canvas_coords()
        relative_mouse_pos = self.foocoords
        canvas_mouse_coords = (canvas_coords[0] + relative_mouse_pos[0] +
                               self.frame_thickness, canvas_coords[1] +
                               relative_mouse_pos[1] + self.frame_thickness)
        scroll_x, scroll_y = self.viewport.edge_scroll(canvas_mouse_coords)
        # move the opposite direction the viewport scrolled
        scroll_x, scroll_y = -scroll_x, -scroll_y
        #print 'card.edgescroll x y', scroll_x, scroll_y, 'relative_mouse_pos', relative_mouse_pos
        self.window.move(scroll_x, scroll_y)
        self.viewport.reset_scroll_region()
        self.set_moving_edgescroll_callback()

    def set_moving_edgescroll_callback(self):
        self.moving_edgescroll_id = self.text.after(10, self.edge_scroll)

    def cancel_moving_edgescroll_callback(self):
        self.text.after_cancel(self.moving_edgescroll_id)
        self.moving_edgescroll_id = None

    def mousedown(self, event):
        self.window.lift()

    def doubleclick(self, event):
        self.start_moving(event)
        return 'break'

    def shiftmousedown(self, event):
        self.mousedown(event)
        self.start_moving(event)
        return "break"

    def mousemove(self, event):
        if self.moving:
            # coords are relative to card, not canvas
            if self.foocoords:
                delta = (event.x - self.foocoords[0],
                         event.y - self.foocoords[1])
            else:
                delta = (event.x, event.y)
            self.window.move(delta[0], delta[1])
            self.geometry_callback()
            self.viewport.reset_scroll_region()
            return "break"

    def mouseup(self, event):
        if self.moving:
            self.moving = False
            new_coords = self.canvas_coords()
            self.card.x, self.card.y = new_coords[0], new_coords[1]
            self.gpfile.commit()
            self.cancel_moving_edgescroll_callback()
            self.geometry_callback()

    # next several functions are bound to the circular edge handles
    def handle_click(self, event):
        # create new edge
        self.new_edge = ViewportEdge(self.viewport, self.gpfile, None, self,
                                     None)
        self.new_edge.mousemove(event)  # give it a real start pos

    def handle_shift_click(self, event):
        self.handle_click(event)
        self.new_edge.make_new_card = True

    def handle_mousemove(self, event):
        if self.new_edge:
            self.new_edge.mousemove(event)

    def handle_mouseup(self, event):
        if self.new_edge:
            self.new_edge.mouseup(event)
            self.new_edge = None

    def configure(self, event):
        self.redraw_edge_handles()

    def focusin(self, event):
        self.editing = True

    def focusout(self, event):
        self.editing = False
        self.save_text()

    def ctrldelete(self, event):
        title_sample = self.get_text().split('\n', 1)[0]
        if len(title_sample) > 20:
            title_sample = title_sample[:20] + '...'
        # delete the card
        if tkMessageBox.askokcancel(
                "Delete?",
                "Delete card \"%s\" and all its edges?" % title_sample):
            for handle in self.edge_handles:
                self.canvas.delete(handle)
            self.deletion_slot.signal()
            self.viewport.remove_card(self)
            self.card.delete()
            self.window.destroy()
            self.gpfile.commit()
        return "break"

    def save_card(self):
        # grab values from self.window,
        # and put them in the model.card
        self.card.x, self.card.y = self.window.canvas_coords()
        self.card.w, self.card.h = self.window.winfo_width(
        ), self.window.winfo_height()
        self.geometry_callback()  # here so it gets called after resizing
        self.gpfile.commit()

    def add_geom_signal(self, fn):
        return self.geom_slot.add(fn)

    def remove_geom_signal(self, handle):
        self.geom_slot.remove(handle)

    def add_deletion_signal(self, fn):
        return self.deletion_slot.add(fn)

    def remove_deletion_signal(self, handle):
        self.deletion_slot.remove(handle)

    def geometry_callback(self):
        x, y = self.canvas_coords()
        w, h = self.window.winfo_width(), self.window.winfo_height()
        self.geom_slot.signal(self, x, y, w, h)

    def highlight(self):
        self.text.config(background='#ffffa2')

    def unhighlight(self):
        self.text.config(background='white')
Ejemplo n.º 2
0
class SigBridgeUI(Tk):
    server = None
    server_thread = None

    def __init__(self):
        Tk.__init__(self)

        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        # 2 rows: firts with settings, second with registrar data
        self.main_frame = Frame(self)
        # Commands row doesn't expands
        self.main_frame.rowconfigure(0, weight=0)
        # Logs row will grow
        self.main_frame.rowconfigure(1, weight=1)
        # Main frame can enlarge
        self.main_frame.columnconfigure(0, weight=1)
        self.main_frame.columnconfigure(1, weight=1)
        self.main_frame.grid(row=0, column=0)

        # Run/Stop button
        self.server_button = Button(self.main_frame, text="Connect", command=self.start_server)
        self.server_button.grid(row=0, column=0)

        # Clear button
        self.clear_button = Button(self.main_frame, text="Clear Log", command=self.clear_log)
        self.clear_button.grid(row=0, column=1)

        # Logs Widget
        self.log_widget = ScrolledText(self.main_frame)
        self.log_widget.grid(row=1, column=0, columnspan=2)
        # made not editable
        self.log_widget.config(state='disabled')

        # Queue where the logging handler will write
        self.log_queue = Queue.Queue()

        # Setup the logger
        self.uilogger = logging.getLogger('SigBridgeUI')
        self.uilogger.setLevel(logging.INFO)
        formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')

        # Use the QueueLogger as Handler
        hl = QueueLogger(queue=self.log_queue)
        hl.setFormatter(formatter)
        self.uilogger.addHandler(hl)

        # self.log_widget.update_idletasks()
        self.set_geometry()

        # Setup the update_widget callback reading logs from the queue
        self.start_log()

    def clear_log(self):
        self.log_widget.config(state='normal')
        self.log_widget.delete(0.0, END)
        self.log_widget.config(state='disabled')

    def start_log(self):
        self.uilogger.info("SigBridge Started.")
        self.update_widget()
        # self.control_log_button.configure(text="Pause Log", command=self.stop_log)

    def update_widget(self):
        self.log_widget.config(state='normal')
        # Read from the Queue and add to the log widger
        while not self.log_queue.empty():
            line = self.log_queue.get()
            tag = "error" if " ERROR " in line else 'info'
            self.log_widget.insert(END, line, tag)
            self.log_widget.see(END)  # Scroll to the bottom
            self.log_widget.update_idletasks()
        self.log_widget.tag_config('error', foreground="red")
        self.log_widget.config(state='disabled')
        self.log_widget.after(10, self.update_widget)

    def set_geometry(self):
        # set position in window
        w = 600  # width for the Tk
        h = 300  # height for the Tk

        # get screen width and height
        ws = self.winfo_screenwidth()   # width of the screen
        hs = self.winfo_screenheight()  # height of the screen

        # calculate x and y coordinates for the Tk window
        x = (ws/2) - (w/2)
        y = (hs/2) - (h/2)

        # set the dimensions of the screen 
        # and where it is placed
        self.geometry('%dx%d+%d+%d' % (w, h, x, y))

    def start_server(self):
        try:
            self.server = SigServer(('0.0.0.0', 25), None, self.uilogger)
            self.server_thread = threading.Thread(name='server', target=self.server.run)
            self.server_thread.daemon = True
            self.server_thread.start()
            self.server_button.configure(text="Disconnect", command=self.stop_server)
        except Exception as err:
            self.uilogger("Cannot start the server: %s" % err.message)

        # self.label_variable.set(self.entry_variable.get()+"(Started Signal Server)")
        # self.entry.focus_set()
        # self.entry.selection_range(0, END)

    def stop_server(self):
        self.server.shutdown()
        self.server_button.configure(text="Connect", command=self.start_server)
        self.server = None
Ejemplo n.º 3
0
class LogFrame:
    def __init__(self, root, options, main_logger):
        self.root = root
        self.options = options
        self.main_logger = main_logger

        self.frame = tk.Frame(self.root)
        self.frame.columnconfigure(0, weight=1)
        # first row doesn't expoands
        self.frame.rowconfigure(0, weight=0)
        # let the second row grow
        self.frame.rowconfigure(1, weight=1)

        self.log_commands_frame = tk.LabelFrame(self.frame,
                                                text="Controls",
                                                padx=5,
                                                pady=5)
        self.log_commands_frame.grid(row=0,
                                     column=0,
                                     sticky=tk.NSEW,
                                     padx=4,
                                     pady=5)

        self.log_messages_frame = tk.Frame(self.frame)
        self.log_messages_frame.grid(row=1, column=0, sticky=tk.NSEW)
        # let the SIP trace growing
        self.log_messages_frame.columnconfigure(0, weight=1)
        self.log_messages_frame.rowconfigure(0, weight=1)

        self.log_messages = ScrolledText(self.log_messages_frame)
        self.log_messages.grid(row=0, column=0, sticky=tk.NSEW)

        # Log Messages frame
        row = 0
        self.log_messages_clear_button = tk.Button(
            self.log_commands_frame,
            text="Clear",
            command=self.clear_log_messages)
        self.log_messages_clear_button.grid(row=row, column=0, sticky=tk.N)

        self.log_messages_pause_button = tk.Button(
            self.log_commands_frame,
            text="Pause",
            command=self.pause_log_messages)
        self.log_messages_pause_button.grid(row=row, column=1, sticky=tk.N)
        row = row + 1

    def get_frame(self):
        return self.frame

    def clear_log_messages(self):
        self.log_messages.config(state='normal')
        self.log_messages.delete(0.0, tk.END)
        self.log_messages.config(state='disabled')

    def pause_log_messages(self):
        if self.log_messages_alarm is not None:
            self.log_messages.after_cancel(self.log_messages_alarm)
            self.log_messages_pause_button.configure(
                text="Resume", command=self.start_log_messages)
            self.log_messages_alarm = None

    def start_log_messages(self):
        self.update_log_messages_widget()
        self.log_messages_pause_button.configure(
            text="Pause", command=self.pause_log_messages)

    def update_log_messages_widget(self):
        self.update_widget(self.log_messages, self.log_queue)
        self.log_messages_alarm = self.log_messages.after(
            20, self.update_log_messages_widget)

    def update_widget(self, widget, queue):
        widget.config(state='normal')
        while not queue.empty():
            line = queue.get()
            widget.insert(tk.END, line)
            widget.see(tk.END)  # Scroll to the bottom
            widget.update_idletasks()
        widget.config(state='disabled')
Ejemplo n.º 4
0
class ViewportCard(object):
    """
    Manages the graphical representation of a card in a
    Tkinter canvas. Creates and destroys items as necessary, facilitates
    editing, and so on and so forth.

    Members:
    * card: model.Card
    * viewport: GPViewport
    * gpfile: gpfile.GraphPaperFile, contains model.graph()
    * canvas: TKinter canvas we get drawn on
    * editing: bool, text is being edited
    * moving: bool, being dragged
    * moving_edgescroll_id: callback id to scroll periodically when hovering
      near edge of screen
    * resize_state: {}
    * resize_edgescroll_id: as moving_edgescroll_id
    * slot: calls callbacks whenever geometry changes
    * new_edge: if an edge is being dragged out from a handle, this is it.
    * card_after_new_edge: bool, if we should make a new card when edge is dropped.
    """

    def __init__(self, viewport, gpfile, card):
        self.card = card
        self.viewport = viewport
        self.gpfile = gpfile
        self.canvas = viewport.canvas
        self.draw()
        self.editing = False
        self.moving = False
        self.moving_edgescroll_id = None
        self.resize_state = None
        self.resize_edgescroll_id = None
        # slot triggered when geometry (pos/size) changes
        # fn args: (self, x, y, w, h)
        self.geom_slot = Slot()
        self.deletion_slot = Slot()
        self.new_edge = None

    def draw(self):
        self.frame_thickness = 5
        self.window = ResizableCanvasFrame(
            self.canvas,
            self.card.x,
            self.card.y,
            self.card.w,
            self.card.h,
            min_width=MIN_CARD_SIZE,
            min_height=MIN_CARD_SIZE,
        )
        self.text = ScrolledText(self.window, wrap=WORD)
        self.text.pack(expand=1, fill="both")
        # set up text for editing, dragging, deleting
        self.text.bind("<Button-1>", self.mousedown)
        self.text.bind("<Shift-Button-1>", self.shiftmousedown)
        self.text.bind("<Double-Button-1>", self.doubleclick)
        self.text.bind("<B1-Motion>", self.mousemove)
        self.text.bind("<ButtonRelease-1>", self.mouseup)
        self.text.bind("<FocusIn>", self.focusin)
        self.text.bind("<FocusOut>", self.focusout)
        self.text.bind("<Control-Delete>", self.ctrldelete)
        self.text.insert(END, self.card.text)
        # set up frame for resizing
        self.window.bind("<Configure>", self.configure)
        self.window.save_callback = self.save_card
        # draw edge handles
        self.edge_handles = None
        # self.redraw_edge_handles()

    def redraw_edge_handles(self):
        """
        Either creates or modifies the edge handles, little circles poking
        out the side of the card, based on the current position and width.

        self.edge_handles is a list of itemids of the circles in (top,
        right, bottom, left) order.
        """

        def create_circle(bbox):
            # create circle suitable for edge-handle use
            new = self.canvas.create_oval(bbox[0], bbox[1], bbox[2], bbox[3], fill="green", outline="")
            self.canvas.addtag_withtag("card_handle_tag", new)  # for z-ordering
            self.canvas.tag_bind(new, "<Button-1>", self.handle_click)
            self.canvas.tag_bind(new, "<Shift-Button-1>", self.handle_shift_click)
            self.canvas.tag_bind(new, "<B1-Motion>", self.handle_mousemove)
            self.canvas.tag_bind(new, "<ButtonRelease-1>", self.handle_mouseup)
            return new

        x, y = self.window.canvas_coords()
        w, h = self.window.winfo_width(), self.window.winfo_height()
        # 2*radius should be < MIN_CARD_SIZE, and offset < radius
        radius = 30
        offset = 19  # offset of center of circle from card edge
        left_coords = (x + offset, y + h / 2)
        right_coords = (x + w - offset, y + h / 2)
        top_coords = (x + w / 2, y + offset)
        bottom_coords = (x + w / 2, y + h - offset)
        all_coords = (top_coords, right_coords, bottom_coords, left_coords)
        bboxes = [(x - radius, y - radius, x + radius, y + radius) for x, y in all_coords]
        if self.edge_handles:
            # move the edge handles
            for i, box in enumerate(bboxes):
                # self.canvas.coords(handle, box[0], box[1], box[2], box[3])
                self.canvas.delete(self.edge_handles[i])
                self.edge_handles[i] = create_circle(box)
                # self.canvas.itemconfig(handle, bbox = box)
        else:
            # create new ones
            self.edge_handles = [create_circle(b) for b in bboxes]
        # have to do this every time, every time we recreate the edge handles
        self.viewport.fix_z_order()

    def get_text(self):
        "gets the text from the actual editor, which may not be saved yet"
        return self.text.get("0.0", END)

    def save_text(self):
        # get text from window
        text = self.get_text()
        if text != self.card.text:
            self.card.text = text
            self.gpfile.commit()

    def canvas_coords(self):
        return self.window.canvas_coords()

    def start_moving(self, event):
        # set up state for a drag
        self.moving = True
        self.foocoords = (event.x, event.y)
        self.set_moving_edgescroll_callback()

    def edge_scroll(self):
        # if any edges are too close to the edge, move and scroll the canvas
        canvas_coords = self.canvas_coords()
        relative_mouse_pos = self.foocoords
        canvas_mouse_coords = (
            canvas_coords[0] + relative_mouse_pos[0] + self.frame_thickness,
            canvas_coords[1] + relative_mouse_pos[1] + self.frame_thickness,
        )
        scroll_x, scroll_y = self.viewport.edge_scroll(canvas_mouse_coords)
        # move the opposite direction the viewport scrolled
        scroll_x, scroll_y = -scroll_x, -scroll_y
        # print 'card.edgescroll x y', scroll_x, scroll_y, 'relative_mouse_pos', relative_mouse_pos
        self.window.move(scroll_x, scroll_y)
        self.viewport.reset_scroll_region()
        self.set_moving_edgescroll_callback()

    def set_moving_edgescroll_callback(self):
        self.moving_edgescroll_id = self.text.after(10, self.edge_scroll)

    def cancel_moving_edgescroll_callback(self):
        self.text.after_cancel(self.moving_edgescroll_id)
        self.moving_edgescroll_id = None

    def mousedown(self, event):
        self.window.lift()

    def doubleclick(self, event):
        self.start_moving(event)
        return "break"

    def shiftmousedown(self, event):
        self.mousedown(event)
        self.start_moving(event)
        return "break"

    def mousemove(self, event):
        if self.moving:
            # coords are relative to card, not canvas
            if self.foocoords:
                delta = (event.x - self.foocoords[0], event.y - self.foocoords[1])
            else:
                delta = (event.x, event.y)
            self.window.move(delta[0], delta[1])
            self.geometry_callback()
            self.viewport.reset_scroll_region()
            return "break"

    def mouseup(self, event):
        if self.moving:
            self.moving = False
            new_coords = self.canvas_coords()
            self.card.x, self.card.y = new_coords[0], new_coords[1]
            self.gpfile.commit()
            self.cancel_moving_edgescroll_callback()
            self.geometry_callback()

    # next several functions are bound to the circular edge handles
    def handle_click(self, event):
        # create new edge
        self.new_edge = ViewportEdge(self.viewport, self.gpfile, None, self, None)
        self.new_edge.mousemove(event)  # give it a real start pos

    def handle_shift_click(self, event):
        self.handle_click(event)
        self.new_edge.make_new_card = True

    def handle_mousemove(self, event):
        if self.new_edge:
            self.new_edge.mousemove(event)

    def handle_mouseup(self, event):
        if self.new_edge:
            self.new_edge.mouseup(event)
            self.new_edge = None

    def configure(self, event):
        self.redraw_edge_handles()

    def focusin(self, event):
        self.editing = True

    def focusout(self, event):
        self.editing = False
        self.save_text()

    def ctrldelete(self, event):
        title_sample = self.get_text().split("\n", 1)[0]
        if len(title_sample) > 20:
            title_sample = title_sample[:20] + "..."
        # delete the card
        if tkMessageBox.askokcancel("Delete?", 'Delete card "%s" and all its edges?' % title_sample):
            for handle in self.edge_handles:
                self.canvas.delete(handle)
            self.deletion_slot.signal()
            self.viewport.remove_card(self)
            self.card.delete()
            self.window.destroy()
            self.gpfile.commit()
        return "break"

    def save_card(self):
        # grab values from self.window,
        # and put them in the model.card
        self.card.x, self.card.y = self.window.canvas_coords()
        self.card.w, self.card.h = self.window.winfo_width(), self.window.winfo_height()
        self.geometry_callback()  # here so it gets called after resizing
        self.gpfile.commit()

    def add_geom_signal(self, fn):
        return self.geom_slot.add(fn)

    def remove_geom_signal(self, handle):
        self.geom_slot.remove(handle)

    def add_deletion_signal(self, fn):
        return self.deletion_slot.add(fn)

    def remove_deletion_signal(self, handle):
        self.deletion_slot.remove(handle)

    def geometry_callback(self):
        x, y = self.canvas_coords()
        w, h = self.window.winfo_width(), self.window.winfo_height()
        self.geom_slot.signal(self, x, y, w, h)

    def highlight(self):
        self.text.config(background="#ffffa2")

    def unhighlight(self):
        self.text.config(background="white")
Ejemplo n.º 5
0
Archivo: gui.py Proyecto: svenno/SPLiT
class LogFrame:
    def __init__(self, root, options, main_logger):
        self.root = root
        self.options = options
        self.main_logger = main_logger

        self.frame = tk.Frame(self.root)
        self.frame.columnconfigure(0, weight=1)
        # first row doesn't expoands
        self.frame.rowconfigure(0, weight=0)
        # let the second row grow
        self.frame.rowconfigure(1, weight=1)

        self.log_commands_frame = tk.LabelFrame(self.frame, text="Controls", padx=5, pady=5)
        self.log_commands_frame.grid(row=0, column=0, sticky=tk.NSEW, padx=4, pady=5)

        self.log_messages_frame = tk.Frame(self.frame)
        self.log_messages_frame.grid(row=1, column=0, sticky=tk.NSEW)
        # let the SIP trace growing
        self.log_messages_frame.columnconfigure(0, weight=1)
        self.log_messages_frame.rowconfigure(0, weight=1)

        self.log_messages = ScrolledText(self.log_messages_frame)
        self.log_messages.grid(row=0, column=0, sticky=tk.NSEW)

        # Log Messages frame
        row = 0
        self.log_messages_clear_button = tk.Button(self.log_commands_frame, text="Clear", command=self.clear_log_messages)
        self.log_messages_clear_button.grid(row=row, column=0, sticky=tk.N)
        
        self.log_messages_pause_button = tk.Button(self.log_commands_frame, text="Pause", command=self.pause_log_messages)
        self.log_messages_pause_button.grid(row=row, column=1, sticky=tk.N)
        row = row + 1

    def get_frame(self): 
        return self.frame

    def clear_log_messages(self):
        self.log_messages.config(state='normal')
        self.log_messages.delete(0.0, tk.END)
        self.log_messages.config(state='disabled')

    def pause_log_messages(self):
        if self.log_messages_alarm is not None:
            self.log_messages.after_cancel(self.log_messages_alarm)
            self.log_messages_pause_button.configure(text="Resume", command=self.start_log_messages)
            self.log_messages_alarm = None

    def start_log_messages(self):
        self.update_log_messages_widget()
        self.log_messages_pause_button.configure(text="Pause", command=self.pause_log_messages)
        
    def update_log_messages_widget(self):
        self.update_widget(self.log_messages, self.log_queue) 
        self.log_messages_alarm = self.log_messages.after(20, self.update_log_messages_widget)

    def update_widget(self, widget, queue):
        widget.config(state='normal')
        while not queue.empty():
            line = queue.get()
            widget.insert(tk.END, line)
            widget.see(tk.END)  # Scroll to the bottom
            widget.update_idletasks()
        widget.config(state='disabled')
Ejemplo n.º 6
0
class LogReader(object):

    def __init__(self, root, **kwargs):
        self.root = root
        self.filenameLog = kwargs.get('filenameLog', None)

        self.ClearDisplay = kwargs.get('ClearDisplay', False)
        ''' By default don't display Filenames and directory '''

        mainstyle = ttk.Style()
#         mainstyle.theme_use(mainstyle.theme_names()[0])
        mainstyle.configure('My.TFrame',
                            background='gray50',
                            foreground='gray97',
                            font="Monospace 12")

        Btnstyle = ttk.Style()
        Btnstyle.configure('My.TButton',
                           background='gray50',
                           foreground='gray97',
                           font="Monospace 12")
        root.title("Log reader v0.1")

        Chkstyle = ttk.Style()
        Chkstyle.configure('My.TCheckbutton',
                           background='gray50',
                           foreground='gray97',
                           font="Monospace 12")

        Chkstyle = ttk.Style()
        Chkstyle.configure('My.TLabel',
                           background='gray50',
                           foreground='gray97',
                           font="Monospace 12")

        root.title("Libretto v0.1")

        self.initParam()

        #======================================================================
        # Main Frame
        #======================================================================
        self.f0 = ttk.Frame(self.root, style='My.TFrame')
        self.f0.pack(expand=True, fill='both')
        LabelUP = ttk.Label(
            self.f0, text="Please select the log file then click on read",
            style='My.TLabel')
        LabelUP.pack(side="top")

        self.fDisp = ttk.Frame(self.f0, style='My.TFrame')
        self.fDisp.pack(expand=True, fill='both', side="right")

        self.fParam = ttk.Frame(self.f0, style='My.TFrame')
        self.fParam.pack(side="left")

        #======================================================================
        # Frame fDisp
        #======================================================================
        # Display stdout
        self.customFont = tkFont.Font(
            family="Helvetica", size=12)
        self.text_area = ScrolledText(
            self.fDisp, font=self.customFont, undo=True, background='gray20', foreground="gray92")
        self.text_area.pack(expand=True, fill='both')
        self.text_area.configure(state='normal')
        self.text_area.yview(END)
        self.text_area.after(0)

        self.text_area.tag_configure("comment",
                                     font="Helvetica 12",
                                     foreground="gray60")
        self.text_area.tag_configure("subsubTitle",
                                     font="Helvetica 12 bold")
        self.text_area.tag_configure("subTitle",
                                     font="Helvetica 14 bold")
        self.text_area.tag_configure("Title",
                                     font="Helvetica 16 bold")
        self.text_area.tag_configure("warn",
                                     font="Helvetica 12 bold",
                                     foreground="red")
        self.text_area.tag_configure("File",
                                     font="Helvetica 10",
                                     foreground="DarkSlateGray1")
        self.text_area.tag_configure("FileOther",
                                     font="Helvetica 10",
                                     foreground="plum")
        self.text_area.tag_configure("Directory",
                                     font="Helvetica 10",
                                     foreground="goldenrod1")
        self.text_area.tag_configure("validate",
                                     font="Helvetica 12 bold",
                                     foreground="OliveDrab1")
        self.text_area.tag_configure("param",
                                     font="Helvetica 12",
                                     foreground="wheat")

        # stdout redirection
        sys.stdout = StdoutRedirector(self.text_area)

        #======================================================================
        # Parameters
        #======================================================================

        # File Selection button
        SelectLogFileBtn = ttk.Button(
            self.fParam, text="Select the log file", style='My.TButton')
        SelectLogFileBtn.grid(row=0, column=0)
        SelectLogFileBtn.configure(command=lambda: self.set_LogFile())
        Label = ttk.Label(self.fParam, text="", style='My.TLabel')
        Label.grid(row=1, column=0)

        # Refresh button
        SelectLogFileBtn = ttk.Button(
            self.fParam, text="Refresh", style='My.TButton')
        SelectLogFileBtn.grid(row=2, column=0)
        SelectLogFileBtn.configure(command=lambda: self.RefreshLog())

        Label = ttk.Label(self.fParam, text="", style='My.TLabel')
        Label.grid(row=9, column=0)

        # Display Files button
        ChkBtnDispFilenames = ttk.Checkbutton(
            self.fParam, text="Display the filenames", style='My.TCheckbutton')
        ChkBtnDispFilenames.grid(row=10, column=0)
        ChkBtnDispFilenames.configure(variable=self.Entry_DispFilenames,
                                      command=lambda: self.set_DispFilenames())

        # Display Comments button
        ChkBtnDispCom = ttk.Checkbutton(
            self.fParam, text="Display the comments", style='My.TCheckbutton')
        ChkBtnDispCom.grid(row=11, column=0)
        ChkBtnDispCom.configure(variable=self.Entry_DispComment,
                                command=lambda: self.set_DispComment())

        # Display Directories button
        ChkBtnDispDir = ttk.Checkbutton(
            self.fParam, text="Display the directories", style='My.TCheckbutton')
        ChkBtnDispDir.grid(row=12, column=0)
        ChkBtnDispDir.configure(variable=self.Entry_DispDir,
                                command=lambda: self.set_DispDir())

        # Display Warnings button
        ChkBtnDispWarn = ttk.Checkbutton(
            self.fParam, text="Display the warnings", style='My.TCheckbutton')
        ChkBtnDispWarn.grid(row=13, column=0)
        ChkBtnDispWarn.configure(variable=self.Entry_DispWarn,
                                 command=lambda: self.set_DispWarn())

        # Display Warnings button
        ChkBtnDispParam = ttk.Checkbutton(
            self.fParam, text="Display the parameters", style='My.TCheckbutton')
        ChkBtnDispParam.grid(row=14, column=0)
        ChkBtnDispParam.configure(variable=self.Entry_DispParam,
                                  command=lambda: self.set_DispParam())

        self.RefreshLog()
        if self.ClearDisplay:
            self.UpdateAllDisp()

    def printExample(self):
        return ["=========================================",
                "= Welcome in the Log Reader        ",
                "=========================================",
                "", "=== This is a big title ! ===",
                "    ~ A little bit different of this sub-Title",
                "        *  And guess what, now a sub-sub-Title ! ",
                "            # right now I am commenting my example",
                "            p_Dodo is a parameter",
                "            BlablablaAudyIsTheBestBlablabla...",
                "            X_something is a most of the time the filename of " +
                " an MRI image or created",
                "            Z_something is the filename of a file which is not an " +
                "mri image (it can be some stats or a matrix)",
                "            D_anotherthing is a directory",
                "    > Well this task seems to be a success",
                "    !! But this is a message you should read"]

    def initParam(self):
        self.logExtension = ("*.txt", "*.log")

        self.LogMessage = None
        self.listHideBal = []
        global DefaultFileNameMRIImage
        global DefaultFileNameMRIMasks
        global DefaultFileNameOther
        global DefaultFileNameMatrix
        global DefaultDirectory
        global DefaultName
        global DefaultWarning
        global DefaultTitle
        global DefaultSubTitle
        global DefaultSubSubTitle
        global DefaultComment
        global DefaultValidate
        global DefaultParameter

        self.DefaultFileNameMRIImage = DefaultFileNameMRIImage
        self.DefaultFileNameMRIMasks = DefaultFileNameMRIMasks
        self.DefaultFileNameOther = DefaultFileNameOther
        self.DefaultFileNameMatrix = DefaultFileNameMatrix
        self.DefaultDirectory = DefaultDirectory
        self.DefaultName = DefaultName
        self.DefaultWarning = DefaultWarning
        self.DefaultTitle = DefaultTitle
        self.DefaultSubTitle = DefaultSubTitle
        self.DefaultSubSubTitle = DefaultSubSubTitle
        self.DefaultComment = DefaultComment
        self.DefaultValidate = DefaultValidate
        self.DefaultParameter = DefaultParameter

        self.DispWarn = True
        self.Entry_DispWarn = IntVar(value=1)
        self.DispParam = True
        self.Entry_DispParam = IntVar(value=1)

        if self.ClearDisplay:
            self.DispFilenames = False
            self.Entry_DispFilenames = IntVar(value=0)
            self.DispComment = False
            self.Entry_DispComment = IntVar(value=0)
            self.DispDir = False
            self.Entry_DispDir = IntVar(value=0)
        else:
            self.DispFilenames = True
            self.Entry_DispFilenames = IntVar(value=1)
            self.DispComment = True
            self.Entry_DispComment = IntVar(value=1)
            self.DispDir = True
            self.Entry_DispDir = IntVar(value=1)

    def DispOrHide(self, DispSomething, listHideBal):
        if DispSomething:
            # update the balise to hide list
            listHideBal = [e for e in self.listHideBal if e not in listHideBal]
        else:
            listHideBal = listHideBal + self.listHideBal
        self.listHideBal = listHideBal
        self.resetDisp()
        self.watchLog(bal=self.listHideBal)

    def set_DispFilenames(self):
        self.DispFilenames = self.Entry_DispFilenames.get()
        listbal0 = [self.DefaultFileNameMRIImage,
                    self.DefaultFileNameMatrix,
                    self.DefaultFileNameMRIMasks,
                    self.DefaultFileNameOther]
        self.DispOrHide(self.DispFilenames, listbal0)

    def set_DispDir(self):
        self.DispDir = self.Entry_DispDir.get()
        listbal0 = [self.DefaultDirectory]
        self.DispOrHide(self.DispDir, listbal0)

    def set_DispComment(self):
        self.DispComment = self.Entry_DispComment.get()
        listbal0 = [self.DefaultComment]
        self.DispOrHide(self.DispComment, listbal0)

    def set_DispWarn(self):
        self.DispWarn = self.Entry_DispWarn.get()
        listbal0 = [self.DefaultWarning]
        self.DispOrHide(self.DispWarn, listbal0)

    def set_DispParam(self):
        self.DispParam = self.Entry_DispParam.get()
        listbal0 = [self.DefaultParameter]
        self.DispOrHide(self.DispParam, listbal0)

    def UpdateAllDisp(self):
        self.set_DispComment()
        self.set_DispDir()
        self.set_DispFilenames()

    def set_LogFile(self):
        self.filenameLog = self.OpenFile(
            self.OriginalDirectory, self.logExtension)
        self.RefreshLog()

    def filterLog(self, str0, bal):
        ''' delete the lines which contain a specific balise '''
        if type(bal) != list:
            if type(bal) != str:
                if not bal:
                    return str0
            else:
                bal = [bal]
        try:
            str1 = DeleteTabulation(str0)
        except:
            str1 = str0

        for e in bal:
            if str1[0:len(e)] == e:
                return None
        return str0

    def loadLog(self):
        ''' load a log '''
        if self.filenameLog:
            with open(self.filenameLog) as f:
                self.LogMessage = f.read().splitlines()
        else:
            self.LogMessage = self.printExample()

    def watchLog(self, bal=None):
        ''' display the log '''
        for line in self.LogMessage:
            l = self.filterLog(line, bal)
            if l:
                print l

    def resetDisp(self):
        ''' '''
        self.text_area.delete('1.0', END)

    def RefreshLog(self):
        self.loadLog()
        self.resetDisp()
        self.watchLog(bal=self.listHideBal)

    def OpenFile(self, initialdir0="", filetype='*.*'):
        if filetype != '*.*':
            filetypes0 = (("Files", filetype),
                          ("All Files", "*.*"))
            name = askopenfilename(initialdir=initialdir0,
                                   filetypes=filetypes0,
                                   title="Choose a file.")
        else:
            name = askopenfilename(initialdir=initialdir0,
                                   title="Choose a file.")
        return name

    def close(self):
        print "close"
        exit()