Beispiel #1
0
	def textFieldConstructor(self, labelText, value):
		def selectAllText(event):
			xField = event.widget
			xField.tag_add(SEL, '1.0', 'end')
			xField.mark_set(INSERT, "1.0")
			xField.see(INSERT)
			return 'break'
			
		#Label(self.body, text=labelText).grid(row=0, column=0, sticky='nw')
		Label(self.body, text=labelText).pack(side=TOP)
		
		#xTextbox = Text(self.body) ## ver que width y height poner
		xTextbox = ScrollText(self.body)
		#xTextbox.bind('<KeyRelease>', lambda event: apply())
		xTextbox.bind('<Control-Key-a>', lambda event: selectAllText(event) )
		xTextbox.bind('<Control-Key-A>', lambda event: selectAllText(event) )
		#xTextbox.grid(row=1, column=0, sticky='nw')
		xTextbox.pack(side=BOTTOM, fill=BOTH, expand=True)
		xTextbox.insert('1.0', value)
		self.entries[labelText] = xTextbox
		if self.firstField == None:
			self.firstField = xTextbox
			
		#SQL buttons from module
		params = {'parent':self.upper, 'field':self.firstField}
		MOD.runModules('TOPLEVEL', params)
 def add_tab(self, text='new', dirty=True):
     f = ttk.Frame(self.nb)
     # see http://stackoverflow.com/questions/13832720/how-to-attach-a-scrollbar-to-a-text-widget
     t = ScrolledText(f, relief=tk.RAISED, wrap=tk.WORD)
     t.insert(tk.INSERT, text)
     t.pack(fill=tk.BOTH, expand=1)
     t.bind("<KeyRelease>", self.update)
     self.nb.add(f)
     self.tabs.append(t)
     self.nb.select(self.nb.tabs()[-1])
     self.update(dirty=dirty)
Beispiel #3
0
def initializeResponseEntry():
    responseEntry = ScrolledText(width=40, height=6, background=darkSalmon)
    responseEntry.insert(END, 'Type here')
    responseEntry.grid(row=2, sticky=EW, padx=50)
    responseEntry.bind('<KeyRelease>', typing)
    responseEntry.bind('<BackSpace>', blankButtons())
    responseEntry.bind('<Button-1>', clearText)
    return responseEntry
Beispiel #4
0
class BlockdiagEditor(object):
    """
    Interactive editor UI for blockdiag
    """
    def __init__(self, diag_method, source, diag_image):
        self.diag_method = diag_method
        self.source = intern(source.encode("utf-8"))
        self.image_format = "PNG"
        self.tmp = NamedTemporaryFile(mode="wb")
        self.root = Tk.Tk()
        self.root.geometry("1024x768")
        self.root.protocol("WM_DELETE_WINDOW", self.quit)

        # Frames
        self.frame = Tk.Frame(self.root)
        self.frame.master.title("blockdiag editor")
        self.frame.pack(fill=Tk.BOTH, expand=1, padx=3, pady=3)
        self.btn_frame = Tk.Frame(self.frame)
        self.btn_frame.pack(fill=Tk.BOTH, padx=3, pady=3)
        self.text_frame = Tk.Frame(self.frame)
        self.text_frame.pack(fill=Tk.BOTH, expand=1, padx=3, pady=3)
        self.image_frame = Tk.Frame(self.frame)
        self.image_frame.pack(fill=Tk.BOTH, expand=1, padx=3, pady=3)
        self.image_frame.grid_rowconfigure(0, weight=1, minsize=0)
        self.image_frame.grid_columnconfigure(0, weight=1, minsize=0)

        # Button
        self.upd_btn = Tk.Button(self.btn_frame,
                                 bd=2,
                                 text="Update Canvas",
                                 command=self.redraw_diag_image)
        self.upd_btn.pack(side=Tk.LEFT)
        self.link_btn = Tk.Button(self.btn_frame,
                                  bd=2,
                                  text="Permanent link",
                                  command=self.open_permanent_link)
        self.link_btn.pack(side=Tk.LEFT)
        self.quit_btn = Tk.Button(self.btn_frame,
                                  bd=2,
                                  text="Quit",
                                  command=self.quit)
        self.quit_btn.pack(side=Tk.LEFT)

        # Text Editor
        self.text = ScrolledText(self.text_frame, wrap=Tk.WORD)
        self.text.pack(fill=Tk.BOTH, expand=1)
        self.text.insert(Tk.END, source)
        self.text.focus_set()
        self.text.bind("<KeyRelease-Control_L>", self.redraw_diag_image)
        self.text.bind("<KeyRelease-Control_R>", self.redraw_diag_image)

        # Image Viewer
        self.image = ImageTk.PhotoImage(file=diag_image)
        self.canvas = Tk.Canvas(self.image_frame,
                                scrollregion=(0, 0, self.image.width(),
                                              self.image.height()))
        self.canvas.grid(row=0, column=0, sticky=Tk.N + Tk.E + Tk.W + Tk.S)
        # Add Scrollbar
        xscr = Tk.Scrollbar(self.image_frame,
                            orient=Tk.HORIZONTAL,
                            command=self.canvas.xview)
        xscr.grid(row=1, column=0, sticky=Tk.E + Tk.W)
        yscr = Tk.Scrollbar(self.image_frame,
                            orient=Tk.VERTICAL,
                            command=self.canvas.yview)
        yscr.grid(row=0, column=1, sticky=(Tk.N, Tk.S))
        self.canvas.config(xscrollcommand=xscr.set, yscrollcommand=yscr.set)
        self.canvas.create_image(0, 0, image=self.image, anchor=Tk.NW)

    def redraw_canvas(self, file_name):
        self.image = ImageTk.PhotoImage(file=file_name)
        self.canvas.config(scrollregion=(0, 0, self.image.width(),
                                         self.image.height()))
        self.canvas.create_image(0, 0, image=self.image, anchor=Tk.NW)

    def redraw_diag_image(self, event=None):
        source = intern(self.text.get("1.0", Tk.END).encode("utf-8"))
        if source is not self.source:
            self.diag_method(source, self.tmp.name, self.image_format)
            if getsize(self.tmp.name) > 0:
                self.redraw_canvas(self.tmp.name)
            self.source = source

    def open_permanent_link(self):
        url = self.make_permanent_link()
        webbrowser.open_new_tab(url)

    def make_permanent_link(self):
        import base64
        source = intern(self.text.get("1.0", Tk.END).encode("utf-8"))
        url = _DIAG_LINK_PREFIX + base64.urlsafe_b64encode(source)
        print url
        return url

    def quit(self):
        self.tmp.close()
        self.root.destroy()
Beispiel #5
0
class ClientGUI(object):

  def __init__(self, windowTitle="Client GUI"):
    # create new instance of TK
    self.base_gui = pygui.Tk()

    # store the windowTitle in an object attribute
    self.base_window_title = windowTitle

    # Connection Details
    self.connection_host = ''
    self.connection_name = ''
    self.connection_port = 0

    # Client Object
    self.client = None

    # [Connection GUI Initialization] ::start
    self.connection_gui_bootstrapped = False
    self.connection_config_frame = pygui.Frame(self.base_gui)
    self.host_to_use_field = pygui.Entry(self.connection_config_frame)
    self.port_to_use_field = pygui.Entry(self.connection_config_frame)
    self.name_field = pygui.Entry(self.connection_config_frame)
    self.connect_server_btn = pygui.Button(self.connection_config_frame, text="Connect", command=self.connect_to_server)
    # [Connection GUI Initialization] ::end

    # [Main GUI Initialization] ::start
    self.main_gui_bootstrapped = False
    self.chat_room_frame = pygui.Frame(self.base_gui)
    self.activity_log_area = ScrolledText(self.chat_room_frame, height=10, width=50)
    self.message_field = pygui.Entry(self.chat_room_frame)
    self.submit_msg_btn = pygui.Button(self.chat_room_frame, text="Send", command=self.send_msg)

    self.exit_chat_btn = pygui.Button(self.chat_room_frame,
                                      text="Leave Chat Room",
                                      command=lambda: self.switch_context('connection'))
    # [Connection GUI Initialization] ::end

  def bootstrap(self):
    if self.client is None:
      print "Client Object must be specified. Call the set_client() method and set the ClientGUI Object."
      sys.exit(1)

    self.connection_gui()

    # set window title
    self.base_gui.wm_title(self.base_window_title)

    # handle close button
    self.base_gui.protocol("WM_DELETE_WINDOW", self.destroy_gui)

    # Start the GUI
    self.base_gui.mainloop()

  def connection_gui(self):
    # [Config Section] :start
    # assemble the UI and the frame if the attribute does not exist
    if self.connection_gui_bootstrapped is False:
      # Add field for host/hostname to use
      pygui.Label(self.connection_config_frame, text="Host").grid(row=0, column=0)
      self.host_to_use_field.grid(row=0, column=1)

      # Add field for port to use
      pygui.Label(self.connection_config_frame, text="Port").grid(row=1, column=0)
      self.port_to_use_field.grid(row=1, column=1)

      # Add field for chat username/alias
      pygui.Label(self.connection_config_frame, text="Name").grid(row=2, column=0)
      self.name_field.grid(row=2, column=1)

      self.connect_server_btn.grid(row=3, column=1)

      self.connection_gui_bootstrapped = True

    self.connection_config_frame.pack(side=pygui.TOP, padx=10, pady=10)
    # [Config Section] :end

  def main_gui(self):
    # [Chat Room] ::start
    # assemble the UI and the frame if the attribute does not exist
    if self.main_gui_bootstrapped is False:
      self.activity_log_area.grid(row=0)
      self.activity_log_area.edit_modified(0)
      self.activity_log_area.config(highlightbackground="black")
      self.activity_log_area.bind('<<Modified>>', self.scroll_to_end)

      self.message_field.grid(row=1, column=0)
      self.message_field.config(width=30)
      self.message_field.bind("<Return>", self.send_msg)

      self.submit_msg_btn.grid(row=1, column=1)

      self.exit_chat_btn.grid(row=2)

      self.main_gui_bootstrapped = True

    # empty the chat logs
    self.activity_log_area.delete("1.0", pygui.END)

    # show the frame for chat room
    self.chat_room_frame.pack(side=pygui.TOP, padx=10, pady=10)
    # [Chat Room] ::end

  def destroy_gui(self):
    # disconnect from the server
    self.client.disconnect()

    # destroy the window
    self.base_gui.destroy()

  def switch_context(self, context):
    if context == 'main':
      # hide the connection frame/GUI from the window
      if hasattr(self, 'connection_config_frame'):
        self.connection_config_frame.pack_forget()

      self.main_gui()

      title = "%s connected on %s:%s - %s" % (strip_uid(self.connection_name),
                                              self.connection_host,
                                              str(self.connection_port),
                                              self.base_window_title)

      # change the window title to show the connection details
      self.base_gui.wm_title(title)

    else:
      # disconnect from the server
      self.client.disconnect()

      # hide the chat room frame/GUI from the window
      if hasattr(self, 'chat_room_frame'):
        self.chat_room_frame.pack_forget()

      self.connection_gui()

      # set window title
      self.base_gui.wm_title(self.base_window_title)

  def scroll_to_end(self, *_):
    # scroll to the end of text area
    self.activity_log_area.see(pygui.END)
    self.activity_log_area.edit_modified(0)

  def connect_to_server(self):
    hostval = self.host_to_use_field.get()
    portval = self.port_to_use_field.get()
    nameval = self.name_field.get()

    if hostval != '' and portval != '' and nameval != '':
      self.connection_host = str(hostval)
      self.connection_name = str(nameval)

      # check if the host supplied is a valid ip address
      if not is_ipv4(self.connection_host):
        msgBox.showinfo("Client GUI", "Invalid IP Address")
        return

      # check if the input for port number is a valid integer
      try:
        self.connection_port = int(portval)
      except ValueError:
        msgBox.showinfo("Client GUI", "Invalid Port Number")
        return

      # initiate client-server connection
      if self.client.connect(self.connection_host, self.connection_port, self.connection_name) is True:
        # swap UI components/widgets
        self.switch_context('main')

        # log any broadcast message and disconnect on lost connection
        self.client.start_communications(self.log, lambda: self.switch_context('connection'))
      else:
        msgBox.showinfo("Client GUI", "Cant connect to server. Please try again later.")

    else:
      msgBox.showinfo("Client GUI", "Please enter the host, and port to connect to as well as your chat name")

  def set_client(self, client):
    self.client = client

  def send_msg(self, *_):
    message = self.message_field.get()

    # only send messages which are not empty
    if message:
      # show the message on your side
      self.log('[' + strip_uid(self.connection_name) + '] ' + message)

      # send the message to the other side
      self.client.send_msg(str(message))

      # delete the message
      self.message_field.delete(0, pygui.END)

  def log(self, message):
    self.activity_log_area.insert(pygui.END, message + "\n")
Beispiel #6
0
class client_GUI(Thread):

    alias = None
    room = None
    flag = False
    in_room = False
    client = socket()
    IP = raw_input("IP Address: ")
    if not IP:
        IP = 'localhost'
    try:
        client.connect((IP, 9000))
    except Exception as e:
        print "Could not connect to IP"
        logging.exception(e)
        exit()

    def __init__(self, master):
        Thread.__init__(self)
        frame = Frame(master)
        frame.pack()
        self.setAlias()

    #creates the thread for listening to the Server
    def run(self):
        Recieve(self.client)

    def clearWindow(self):
        for widget in root.winfo_children():
            widget.destroy()

    def assemble_packet(self, msg, code):
        parser = Parser()
        if code == utils.codes["send_msg"]:
            date = datetime.datetime.now().strftime(utils.DATE_FORMAT)
            packet = parser.assemble(utils.codes["send_msg"], self.alias,
                                     self.room, date, msg)
        elif code == utils.codes["set_alias"]:
            packet = parser.assemble(utils.codes["set_alias"], msg, "", "", "")
        elif code == utils.codes["set_room"]:
            packet = parser.assemble(utils.codes["set_room"], self.alias, msg,
                                     "", "")
        elif code == utils.codes["get_roomlist"]:
            packet = parser.assemble(utils.codes["get_roomlist"], self.alias,
                                     self.room, "", "")
        logging.info("Sending packet %s" % (packet))
        return packet

    def breakdown_packet(self, packet):
        parser = Parser()
        parser.breakdown(packet)
        if parser.code == utils.codes["recv_msg"]:
            return parser.body
        elif parser.code == utils.codes["recv_roomlist"]:
            return parser.body
        elif parser.code == utils.codes["alias_success"]:
            self.alias = parser.alias
            return parser.body
        elif parser.code == utils.codes["alias_invalid"]:
            return parser.alias
        elif parser.code == utils.codes["room_success"]:
            self.room = parser.room
            return parser.room
        elif parser.code == utils.codes["room_invalid"]:
            return parser.room
        else:
            logging.info("Invalid packet recieved")
            return

    def setAlias(self):
        def setRoom():
            aliasCheck = None
            self.alias = self.aliasInfo.get().translate(None, '\\')
            self.alias = self.alias.translate(None, ' ')
            if len(self.alias) > 20:
                self.alias = self.alias[:19]
            packet = self.assemble_packet(self.alias, utils.codes["set_alias"])
            try:
                self.client.send(packet)
            except Exception as e:
                logging.exception(e)
            time.sleep(1)
            if not inputQueue.empty():
                aliasCheck = str(inputQueue.get())
                if aliasCheck.startswith(utils.codes["alias_success"]):
                    roomList = self.breakdown_packet(aliasCheck)
                    self.clearWindow()
                    self.changeRoom(roomList)
                else:
                    self.flag = True
                    self.clearWindow()
                    self.setAlias()
            else:
                self.flag = True
                self.clearWindow()
                self.setAlias()

        self.intro = Label(root,
                           text="Welcome to TrashTalk",
                           width=600,
                           font=8000,
                           fg="red",
                           pady=100)
        self.intro.pack(anchor=CENTER)
        self.aliasLabel = Label(root, text="Set Your Alias:", pady=10)
        self.aliasLabel.pack(anchor=CENTER)
        self.aliasInfo = Entry(root, width=40)
        self.aliasInfo.pack(anchor=CENTER)
        self.spacing = Label(root, text="", pady=70)
        if self.flag:
            self.spacing.config(text="Invalid, please try again", fg="red")
        self.spacing.pack(anchor=CENTER)
        self.login = Button(root,
                            height=2,
                            width=10,
                            text="Pick A Room",
                            command=setRoom)
        self.login.pack(anchor=CENTER)

    def changeRoom(self, roomList):
        def enterRoom():
            self.clearWindow()
            chosenRoom = self.v.get()
            if not chosenRoom:
                chosenRoom = firstRoom
            packet = self.assemble_packet(chosenRoom, utils.codes["set_room"])
            try:
                self.client.send(packet)
            except Exception as e:
                logging.exception(e)
            time.sleep(1)
            if not inputQueue.empty():
                roomCheck = str(inputQueue.get())
                if roomCheck.startswith(utils.codes["room_success"]):
                    self.room = chosenRoom
                    self.in_room = True
                    self.inRoom(chosenRoom)
            else:
                self.changeRoom(roomList)

        root.title("TrashTalk")
        rooms = roomList.split()
        firstRoom = rooms[0]
        self.v = StringVar(value=firstRoom)
        self.roomLabel = Label(
            root,
            text="Select which Chat Room You Would Like to Join",
            pady=70,
            font=800)
        self.roomLabel.pack(anchor=CENTER)
        for room in rooms:
            self.b = Radiobutton(root, text=room, variable=self.v, value=room)
            self.b.pack(anchor=CENTER)
        self.b.deselect()
        self.login = Button(root,
                            height=2,
                            width=20,
                            text="Enter Chosen Room",
                            command=enterRoom)
        self.login.place(relx=0.5, y=400, anchor=CENTER)

    def inRoom(self, room):
        def newMessage():
            message = self.entryBox.get()
            if message:
                self.entryBox.delete(0, 'end')
                message = message.translate(None, '\\')
                if len(message) > 900:
                    message = message[:899]
                packet = self.assemble_packet(message, utils.codes["send_msg"])
                try:
                    self.client.send(packet)
                except Exception as e:
                    logging.exception(e)

        def changingRoom():
            packet = self.assemble_packet("", utils.codes["get_roomlist"])
            try:
                self.client.send(packet)
            except Exception as e:
                logging.exception(e)
            time.sleep(1)
            if not inputQueue.empty():
                roomCheck = str(inputQueue.get())
                if roomCheck.startswith(utils.codes["recv_roomlist"]):
                    in_room = False
                    roomList = self.breakdown_packet(roomCheck)
                    self.clearWindow()
                    self.changeRoom(roomList)

        def exitProgram():
            self.client.close()
            os._exit(1)

        root.title("TrashTalk - " + room)
        self.messageHistory = ScrolledText(root, undo=True)
        self.messageHistory.bind("<Key>", lambda e: "break")
        self.messageHistory.pack(anchor=W)
        self.messageHistory.insert(
            END, "Welcome " + self.alias + " to the " + room + " chat room!")
        self.entryBox = Entry(root, width=85)
        self.entryBox.place(x=0, y=400, anchor=W)
        self.sendButton = Button(root,
                                 height=2,
                                 width=19,
                                 text="Send Message",
                                 command=newMessage)
        self.sendButton.place(x=518, y=388, anchor=NW)
        self.sendButton = Button(root,
                                 height=4,
                                 width=25,
                                 text="Change Room",
                                 command=changingRoom)
        self.sendButton.place(x=725, y=300, anchor=NW)
        self.sendButton = Button(root,
                                 height=4,
                                 width=25,
                                 text="Quit",
                                 command=exitProgram)
        self.sendButton.place(x=725, y=400, anchor=NW)

        def update_chat():
            if not buildQueue.empty():
                MYINFO = buildQueue.get()
                if MYINFO.startswith(utils.codes["leave_room"]):
                    changingRoom()
                elif self.in_room:
                    msg = self.breakdown_packet(MYINFO)
                    endOfBox = self.messageHistory.vbar.get()
                    self.messageHistory.insert(END, "\n" + msg)
                    if endOfBox[1] == 1.0:
                        endOfBox = self.messageHistory.see("end")
            root.after(100, update_chat)

        root.after(100, update_chat)
Beispiel #7
0

def producer(id):
    for i in range(5):
        time.sleep(0.1)
        print('put')
        dataQueue.put('[producer id=%d, count=%d]' % (id, i))


def consumer(root):
    while not dataQueue.empty():
        data = dataQueue.get(block=False)
        root.insert('end', 'consumer got => %s\n' % str(data))
        root.see('end')
    root.after(250, lambda: consumer(root))  # 4 times per sec


def makethreads():
    for i in range(4):
        thread.start_new_thread(producer, (i, ))


if __name__ == '__main__':
    # main GUI thread: spawn batch of worker threads on each mouse click
    from ScrolledText import ScrolledText
    root = ScrolledText()
    root.pack()
    root.bind('<Button-1>', lambda event: makethreads())
    consumer(root)  # start queue check loop in main thread
    root.mainloop()  # pop-up window, enter tk event loop
Beispiel #8
0
class Tkui(base.BaseUI):
    """
  This is a ui class which handles the complete Tk user interface.
  """

    def __init__(self):
        """ Initializes."""
        base.BaseUI.__init__(self)

        # internal ui queue
        self._event_queue = Queue.Queue()

        # map of session -> (bold, foreground, background)
        self._currcolors = {}

        # ses -> string
        self._unfinishedcolor = {}

        self._viewhistory = 0
        self._do_i_echo = 1

        # holds a map of window names -> window references
        self._windows = {}

        # instantiate all the widgets
        self._tk = Tk()
        self._tk.geometry("800x600")

        self.settitle()

        if os.name == "posix":
            fnt = tkFont.Font(family="Courier", size=12)
        else:
            fnt = tkFont.Font(family="Fixedsys", size=12)

        self._entry = CommandEntry(
            self._tk, self, fg="white", bg="black", insertbackground="yellow", font=fnt, insertwidth="2"
        )
        self._entry.pack(side="bottom", fill="both")

        self._topframe = Frame(self._tk)
        self._topframe.pack(side="top", fill="both", expand=1)

        self._txt = ScrolledText(self._topframe, fg="white", bg="black", font=fnt, height=20)
        self._txt.pack(side="bottom", fill="both", expand=1)

        self._txt.bind("<KeyPress>", self._ignoreThis)
        self._txtbuffer = ScrolledText(self._topframe, fg="white", bg="black", font=fnt, height=20)
        self._txtbuffer.bind("<KeyPress-Escape>", self.escape)
        self._txtbuffer.bind("<KeyPress>", self._ignoreThis)

        self._entry.focus_set()
        self._initColorTags()
        self.dequeue()

        exported.hook_register("config_change_hook", self.configChangeHandler)
        exported.hook_register("to_user_hook", self.write)

        # FIXME - fix this explanation.  this is just terrible.
        tc = config.BoolConfig(
            "saveinputhighlight",
            0,
            1,
            "Allows you to change the behavior of the command entry.  When "
            "saveinputhighlight is off, we discard whatever is on the entry "
            "line.  When it is on, we will retain the contents allowing you "
            "to press the enter key to do whatever you typed again.",
        )
        exported.add_config("saveinputhighlight", tc)

        self._quit = 0

    def runui(self):
        global HELP_TEXT
        exported.add_help("tkui", HELP_TEXT)
        exported.write_message('For tk help type "#help tkui".')
        exported.add_command("colorcheck", colorcheck_cmd)

        # run the tk mainloop here
        self._tk.mainloop()

    def wantMainThread(self):
        # The tkui needs the main thread of execution so we return
        # a 1 here.
        return 1

    def quit(self):
        if not self._quit:
            self._quit = 1
            self._topframe.quit()

    def dequeue(self):
        qsize = self._event_queue.qsize()
        if qsize > 10:
            qsize = 10

        for i in range(qsize):
            ev = self._event_queue.get_nowait()
            ev.execute(self)

        self._tk.after(25, self.dequeue)

    def settitle(self, title=""):
        """
    Sets the title bar to the Lyntin title plus the given string.

    @param title: the title to set
    @type  title: string
    """
        if title:
            title = constants.LYNTINTITLE + title
        else:
            title = constants.LYNTINTITLE
        self._event_queue.put(_TitleEvent(self._tk, title))

    def removeWindow(self, windowname):
        """
    This removes a NamedWindow from our list of NamedWindows.

    @param windowname: the name of the window to write to
    @type  windowname: string
    """
        if self._windows.has_key(windowname):
            del self._windows[windowname]

    def writeWindow(self, windowname, message):
        """
    This writes to the window named "windowname".  If the window
    does not exist, we spin one off.  It handles ansi text and
    messages just like writing to the main window.

    @param windowname: the name of the window to write to
    @type  windowname: string

    @param message: the message to write to the window
    @type  message: string or Message instance
    """
        self._event_queue.put(_WriteWindowEvent(windowname, message))

    def writeWindow_internal(self, windowname, message):
        if not self._windows.has_key(windowname):
            self._windows[windowname] = NamedWindow(windowname, self, self._tk)
        self._windows[windowname].write(message)

    def _ignoreThis(self, tkevent):
        """ This catches keypresses from the history buffer."""
        # kludge so that ctrl-c doesn't get caught allowing windows
        # users to copy the buffer....
        if tkevent.keycode == 17 or tkevent.keycode == 67:
            return

        self._entry.focus()
        if tkevent.char:
            # we do this little song and dance so as to pass events
            # we don't want to deal with to the entry widget essentially
            # by creating a new event and tossing it in the event list.
            # it only sort of works--but it's the best code we've got
            # so far.
            args = ("event", "generate", self._entry, "<KeyPress>")
            args = args + ("-rootx", tkevent.x_root)
            args = args + ("-rooty", tkevent.y_root)
            args = args + ("-keycode", tkevent.keycode)
            args = args + ("-keysym", tkevent.keysym)

            self._tk.tk.call(args)

        return "break"

    def pageUp(self):
        """ Handles prior (Page-Up) events."""
        if self._viewhistory == 0:
            self._txtbuffer.pack(side="top", fill="both", expand=1)

            self._viewhistory = 1
            self._txtbuffer.delete("1.0", "end")
            lotofstuff = self._txt.get("1.0", "end")
            self._txtbuffer.insert("end", lotofstuff)
            for t in self._txt.tag_names():
                taux = None
                tst = 0
                for e in self._txt.tag_ranges(t):
                    if tst == 0:
                        taux = e
                        tst = 1
                    else:
                        tst = 0
                        self._txtbuffer.tag_add(t, str(taux), str(e))

            self._txtbuffer.yview("moveto", "1")
            if os.name != "posix":
                self._txtbuffer.yview("scroll", "20", "units")
            self._tk.update_idletasks()
            self._txt.yview("moveto", "1.0")
            if os.name != "posix":
                self._txt.yview("scroll", "220", "units")

        else:
            # yscroll up stuff
            self._txtbuffer.yview("scroll", "-15", "units")

    def pageDown(self):
        """ Handles next (Page-Down) events."""
        if self._viewhistory == 1:
            # yscroll down stuff
            self._txtbuffer.yview("scroll", "15", "units")

    def escape(self, tkevent):
        """ Handles escape (Escape) events."""
        if self._viewhistory == 1:
            self._txtbuffer.forget()
            self._viewhistory = 0
        else:
            self._entry.clearInput()

    def configChangeHandler(self, args):
        """ This handles config changes including mudecho. """
        name = args["name"]
        newvalue = args["newvalue"]

        if name == "mudecho":
            if newvalue == 1:
                # echo on
                self._do_i_echo = 1
                self._entry.configure(show="")
            else:
                # echo off
                self._do_i_echo = 0
                self._entry.configure(show="*")

    def _yadjust(self):
        """Handles y scrolling after text insertion."""
        self._txt.yview("moveto", "1")
        # if os.name != 'posix':
        self._txt.yview("scroll", "20", "units")

    def _clipText(self):
        """
    Scrolls the text buffer up so that the new text written at
    the bottom of the text buffer can be seen.
    """
        temp = self._txt.index("end")
        ind = temp.find(".")
        temp = temp[:ind]
        if temp.isdigit() and int(temp) > 800:
            self._txt.delete("1.0", "100.end")

    def write(self, args):
        """
    This writes text to the text buffer for viewing by the user.

    This is overridden from the 'base.BaseUI'.
    """
        self._event_queue.put(_OutputEvent(args))

    def write_internal(self, args):
        mess = args["message"]
        if type(mess) == types.StringType:
            mess = message.Message(mess, message.LTDATA)

        line = mess.data
        ses = mess.session

        if line == "" or self.showTextForSession(ses) == 0:
            return

        color, leftover = buffer_write(mess, self._txt, self._currcolors, self._unfinishedcolor)

        if mess.type == message.MUDDATA:
            self._unfinishedcolor[ses] = leftover
            self._currcolors[ses] = color

        self._clipText()
        self._yadjust()

    def convertColor(self, name):
        """
    Tk has this really weird color palatte.  So I switched to using
    color names in most cases and rgb values in cases where I couldn't
    find a good color name.

    This method allows me to specify either an rgb or a color name
    and it converts the color names to rgb.

    @param name: either an rgb value or a name
    @type  name: string

    @returns: the rgb color value
    @rtype: string
    """
        if name.startswith("#"):
            return name

        rgb = self._tk._getints(self._tk.tk.call("winfo", "rgb", self._txt, name))
        rgb = "#%02x%02x%02x" % (rgb[0] / 256, rgb[1] / 256, rgb[2] / 256)
        print name, "converted to: ", rgb

        return rgb

    def _initColorTags(self):
        """ Sets up Tk tags for the text widget (fg/bg/u)."""
        for ck in fg_color_codes.keys():
            color = self.convertColor(fg_color_codes[ck])
            self._txt.tag_config(ck, foreground=color)
            self._txtbuffer.tag_config(ck, foreground=color)

        for ck in bg_color_codes.keys():
            self._txt.tag_config(ck, background=bg_color_codes[ck])
            self._txtbuffer.tag_config(ck, background=bg_color_codes[ck])

        self._txt.tag_config("u", underline=1)
        self._txtbuffer.tag_config("u", underline=1)

    def colorCheck(self):
        """
    Goes through and displays all the combinations of fg and bg
    with the text string involved.  Purely for debugging
    purposes.
    """
        fgkeys = ["30", "31", "32", "33", "34", "35", "36", "37"]
        bgkeys = ["40", "41", "42", "43", "44", "45", "46", "47"]

        self._txt.insert("end", "color check:\n")
        for bg in bgkeys:
            for fg in fgkeys:
                self._txt.insert("end", str(fg), (fg, bg))
                self._txt.insert("end", str("b" + fg), ("b" + fg, bg))
            self._txt.insert("end", "\n")

            for fg in fgkeys:
                self._txt.insert("end", str(fg), (fg, "b" + bg))
                self._txt.insert("end", str("b" + fg), ("b" + fg, "b" + bg))
            self._txt.insert("end", "\n")

        self._txt.insert("end", "\n")
        self._txt.insert("end", "\n")
Beispiel #9
0
    lines= str(len(raw.split("\n")))
    chars=str(len(raw.replace("\n","")))
    raw = raw.translate(string.maketrans("",""), string.punctuation)
    a= str(" ".join(raw.split()))
    if chars=="0" and lines == "1":
        wordcount.set("0 Words 0 Lines 0 Characters")
    else:  
        b=a.split(" ")
        if b[0]=="":
            wordcount.set("0 Words "+lines+ " Lines "+chars+" Characters")
        else:
            wordcount.set(str(len(b))+" Words "+lines+ " Lines "+chars+" Characters")

    master.after(100,autoupdate)
    
wordcount=StringVar()

textbox = ScrolledText(master)
textbox.pack()
textbox.focus_set()
textbox.event_generate('<<Paste>>')
textbox.bind('<Control-a>', highlightall)
textbox.bind('<Control-A>', highlightall)

words=Label(master,textvariable=wordcount)
words.pack(side=BOTTOM,padx=20)

autoupdate()
mainloop()

Beispiel #10
0
    def compile_code(self, event=None):
        if not hasattr(self.editwin.io, 'filename') or self.editwin.io.filename is None:
            return

        filename = self.editwin.io.filename
        try:
            f = self.editwin.ftype.get()
        except:
            return

        if f in ('C/l',):
            compiler = 'gcc'
            command = idleConf.GetOption('extensions', 'CompileCode', 'compile_c')
        elif f in ('C++/l',):
            compiler = 'g++'
            command = idleConf.GetOption('extensions', 'CompileCode', 'compile_cpp')
        else:
            return

        def close_(w, event=None):
            w.grab_release()
            w.withdraw()

        raw_name = os.path.splitext(filename)[0]
        exe_name = raw_name+'.exe'
        basename = os.path.basename(filename)

        args = command.format(raw_name)

        sub_win = Toplevel(self.text)
        sub_win.title('In compilation')

        ce = ScrolledText(
            sub_win, width=80, height=24,
            fg='#b7b7b7', bg='black', font='Consolas 10',
            insertbackground='white',
        )

        ce.bind('<Escape>', lambda event: close_(sub_win, event))
        ce.pack(fill='both', expand=True)
        ce.focus_set()
        
        def compile_():
            sp = subprocess.Popen(
                args, stdin=subprocess.PIPE,
                stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True,
            )
            self.compile_failed = compile_failed = sp.wait()
            compile_message = sp.communicate()[1]
            compile_message = re.sub(
                r'^{}:'.format(filename.replace('\\', r'\\')),
                basename+':',
                compile_message,
                flags=re.M,
            )
            self.compile_message = compile_message

            if not compile_message:
                return

            if compile_failed:
                title = 'Compilation failed'
            else:
                title = 'Compilation succeeded (with warning)'

            sub_win.title(title)

##            ce.insert('1.0', compile_message)
##            ce.focus_set()

        d = threading.Thread(name='comp', target=compile_)
        d.start()
        d.join(6)
        if d.is_alive():
            p = subprocess.Popen(
                'taskkill /im {} /f /t'.format(compiler),
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                shell=True,
            )
            stdout, stderr = p.communicate()

        if not self.compile_message:
            close_(sub_win, None)
            tkMessageBox.showinfo(
                parent=self.text,
                title=compiler,
                message='Compilation succeeded.',
            )
        else:
            ce.insert('end', self.compile_message)

        ce.focus_set()
class GUI_hcheck:

    # do everything!
	def __init__(self):
		self.top = Tk()
		self.top.title('Health Check Tool')
		self.top.geometry('1400x800')

		#------- Label,Entry defination ----------#
		self.l1 = Label(self.top, text="IP:").grid(row=1, column=1, sticky="w")
		self.e1 = Entry(self.top)
		self.e1.grid(row=1, column=2,sticky="ew")
		self.l2 = Label(self.top, text="User:"******"w")
		self.e2 = Entry(self.top)
		self.e2.grid(row=2, column=2,sticky="ew")
		self.l3 = Label(self.top, text="Passwd:").grid(row=3, column=1, sticky="w")
		self.e3 = Entry(self.top)
		self.e3['show'] = '*'
		self.e3.grid(row=3, column=2,sticky="ew")
		self.l4 = Label(self.top, text="Command pool:").grid(row=4, column=1, sticky="e")
		self.l5 = Label(self.top, text="To be run command:").grid(row=4, column=5, sticky="e")
		self.e4 = Entry(self.top, width=30)
		self.e4.grid(row=16, column=0, columnspan=3, sticky="ew")

		#------- Checkbutton defination ----------#
		self.cb1State = IntVar()
		self.cb1 = Checkbutton(self.top, variable=self.cb1State, text = "Always Yes", command=self.callCheckbutton)
		self.cb1.grid(row=21, column=16)

		#------- Listbox defination ----------#
		self.cmdfm = Frame(self.top)
		self.cmdsb = Scrollbar(self.cmdfm)
		self.cmdsb_x = Scrollbar(self.cmdfm,orient = HORIZONTAL)
		self.cmdsb.pack(side=RIGHT, fill=Y)
		self.cmdsb_x.pack(side=BOTTOM, fill=X)
		self.cmdls = Listbox(self.cmdfm, selectmode=EXTENDED, height=25, width=40, xscrollcommand=self.cmdsb_x.set, yscrollcommand=self.cmdsb.set)
		self.cmdsb.config(command=self.cmdls.yview)
		self.cmdsb_x.config(command=self.cmdls.xview)
		self.cmdls.pack(side=LEFT, fill=BOTH)
		self.cmdfm.grid(row=5, rowspan=10, column=0,columnspan=4,sticky="ew")
		self.db_file = os.path.join(os.getcwd(),'%s' % constants.DB_NAME)
		flist = utility.load_file(self.db_file)
		if flist != None:
			log.debug ("db file found, start load command")
			for element in flist:
				element = element.strip('\n')
				if element == '' or element.startswith('#'):
					continue
				self.cmdls.insert(END, element)
		else:
			log.debug ("db file doesn't existed, initail cmd")
			for element in constants.CMD_LIST_COMM:
				self.cmdls.insert(END, element)

		self.dirfm = Frame(self.top)
		self.dirsb = Scrollbar(self.dirfm)
		self.dirsb_x = Scrollbar(self.dirfm,orient = HORIZONTAL)
		self.dirsb.pack(side=RIGHT, fill=Y)
		self.dirsb_x.pack(side=BOTTOM, fill=X)
		self.dirs = Listbox(self.dirfm, selectmode=EXTENDED, height=25, width=40, xscrollcommand=self.dirsb_x.set,yscrollcommand=self.dirsb.set)
		self.dirsb.config(command=self.dirs.yview)
		self.dirsb_x.config(command=self.dirs.xview)
		self.dirs.pack(side=LEFT, fill=BOTH)
		self.dirfm.grid(row=5, rowspan=10, column=5,columnspan=4,sticky="ew")

		#------- Buttion defination ----------#
		# add command button
		self.b1 = Button(self.top,text=">>",width=6,borderwidth=3,relief=RAISED, command=self.move_cmd)
		self.b1.grid(row=7, column=4)
		# del command button
		self.b2 = Button(self.top,text="<<",width=6,borderwidth=3,relief=RAISED, command=self.del_cmd)
		self.b2.grid(row=8, column=4)
		# move up command button
		self.b3 = Button(self.top,text="up",width=6,borderwidth=3,relief=RAISED, command=self.up_cmd)
		self.b3.grid(row=7, column=10)
		# move down command button
		self.b4 = Button(self.top,text="down",width=6,borderwidth=3,relief=RAISED, command=self.down_cmd)
		self.b4.grid(row=8, column=10)
		# start command button
		self.b5 = Button(self.top,text="Start",bg='red',width=10,borderwidth=3,relief=RAISED, command=self.start_process)
		self.b5.grid(row=2, column=11)
		# yes button
		self.b6 = Button(self.top,text="Yes",width=6,borderwidth=3,relief=RAISED, command=self.set_confirm_yes)
		self.b6.grid(row=21, column=13)
		# No button
		self.b7 = Button(self.top,text="No",width=6,borderwidth=3,relief=RAISED, command=self.set_confirm_no)
		self.b7.grid(row=21, column=14)
		# Skip button
		self.b8 = Button(self.top,text="Skip",width=6,borderwidth=3,relief=RAISED, command=self.set_confirm_skip)
		self.b8.grid(row=21, column=15)
		# Add button
		self.b9 = Button(self.top,text="add cmd",width=10,borderwidth=3,relief=RAISED, command=self.add_command)
		self.b9.grid(row=15, column=1)
		# Del button
		self.b10 = Button(self.top,text="del cmd",width=10,borderwidth=3,relief=RAISED, command=self.del_command)
		self.b10.grid(row=15, column=2)
		# Manual button
		self.manual = False
		self.b11 = Button(self.top,text="Manual model",width=10,borderwidth=3,relief=RAISED, command=self.manual_mode)
		self.b11.grid(row=2, column=12)

		#------- ScrolledText defination ----------#
		self.sfm = Frame(self.top)
		self.console = ScrolledText(self.sfm,height=45, width=86,bg='black',fg='green',insertbackground='green')
		self.console['font'] = ('lucida console','10')
		self.console.bind("<Return>", self.process_input)
		self.console.pack()
		self.sfm.grid(row=4, rowspan=15, column=11,columnspan=10,sticky="ew")

		self.redir = redirect(self.console)
		sys.stdout = self.redir
		sys.stderr = self.redir
		self.fconsole = logging.StreamHandler(sys.stdout)
		self.fconsole.setLevel(logging.INFO)
		logging.getLogger('').addHandler(self.fconsole)

		#------- Menu defination ----------#
		self.menubar = Menu()
		# file menu
		self.fmenu = Menu()
		#self.fmenu.add_command(label = 'New',command=self.new_win)
		self.fmenu.add_command(label = 'Import cmd',command=self.load_cmd)
		self.fmenu.add_command(label = 'Export cmd',command=self.export_cmd)
		self.menubar.add_cascade(label = 'File', menu = self.fmenu)
		# edit menu
		self.emenu = Menu()
		self.cmenu = Menu()
		self.cvar = StringVar()
		for item in ['white/black', 'black/white', 'green/black']:
			self.cmenu.add_radiobutton(label = item, variable=self.cvar, value=item, command=self.sel_color_style)
		self.emenu.add_cascade(label = 'console style', menu = self.cmenu)
		self.emenu.add_command(label = 'reset cmd pool',command=self.reset_cmd_pool)
		self.menubar.add_cascade(label = 'Edit', menu = self.emenu)

		self.top['menu'] = self.menubar

	def new_win(self):
		#GUI_hcheck()
		pass

	def sel_color_style(self):
		log.debug ("select console color style: %s " % self.cvar.get())
		color = self.cvar.get()
		if color == 'white/black':
			self.console.config(bg='black',fg='white',insertbackground='white')
		elif color == 'black/white':
			self.console.config(bg='white',fg='black',insertbackground='black')
		elif color == 'green/black':
			self.console.config(bg='black',fg='green',insertbackground='green')

	def move_cmd(self):
		if self.cmdls.curselection() != ():
			for i in self.cmdls.curselection():
				if utility.elemet_exists(self.dirs.get(0,END), self.cmdls.get(i)) == None:
					self.dirs.insert(END,self.cmdls.get(i))
					log.debug ("move command %s" % self.cmdls.get(i))
		else:
			tkMessageBox.showwarning('Message', 'Please select at lease one item')

	def load_cmd(self):
		file = tkFileDialog.askopenfilename()
		flist = utility.load_file(file)
		if flist != None:
			self.dirs.delete(0,END)
			for element in flist:
				element = element.strip('\n')
				if element == '' or element.startswith('#'):
					continue
				if utility.elemet_exists(self.dirs.get(0,END), element) == None:
					self.dirs.insert(END, element)
		else:
			tkMessageBox.showerror('Message', 'import failed')

	def export_cmd(self):
		file = tkFileDialog.askopenfilename()
		if utility.export_file(self.dirs.get(0,END), file) == True:
			tkMessageBox.showinfo('Message', 'export finish')
		else:
			tkMessageBox.showerror('Message', 'export failed')

	def del_cmd(self):
		if self.dirs.curselection() != ():
			for i in self.dirs.curselection():
				self.dirs.delete(i)
		else:
			tkMessageBox.showwarning('Message', 'Please select at lease one item')

	def up_cmd(self):
		select = self.dirs.curselection()
		if (len(select)) >= 2:
			tkMessageBox.showwarning('Message', 'Only one select is supported')
			return
		log.debug ("move up select pos: %s" % str(select))
		if select != () and select != (0,):
			element = self.dirs.get(select)
			self.dirs.delete(select)
			self.dirs.insert((select[0] - 1), element)
			self.dirs.select_set(select[0] - 1)

	def down_cmd(self):
		select = self.dirs.curselection()
		if (len(select)) >= 2:
			tkMessageBox.showwarning('Message', 'Only one select is supported')
			return
		log.debug ("move down select pos: %s" % str(select))
		if select != () and select != (END,):
			element = self.dirs.get(select)
			self.dirs.delete(select)
			self.dirs.insert((select[0] + 1), element)
			self.dirs.select_set(select[0] + 1)

	def start_process(self):
		log.debug ("current thread total numbers: %d" % threading.activeCount())
		response = tkMessageBox.askokcancel('Message', 'Will start healthcheck, please click OK to continue, or cancel')
		if response == False:
			return
		th = threading.Thread(target=self.start_cmd)
		th.setDaemon(True)
		th.start()

	def start_cmd(self):
		self.manual = False
		cmd = list(self.dirs.get(0,END))
		if len(cmd) == 0:
			log.info ("To be run cmd numbers none, quit...")
			return
		log.debug ("fetch cmd list from GUI: %s" % cmd)
		(ip, port) = utility.getipinfo(self.e1.get())
		log.debug ("get ip infor-> ip: %s, port:%s" % (ip,port))
		if ip == False:
			log.error ("Given ip infor is wrong! The right ip address: xxx.xxx.xxx.xxx or IP:port ")
			return
		self.b5.config(state=DISABLED)
		self.b11.config(state=DISABLED)
		self.console.delete('1.0',END)
		try:
			self.wf = Workflow(cmd, ip, self.e2.get(), self.e3.get(), port)
			self.wf.start()
		except:
			pass
		self.b5.config(state=NORMAL)
		self.b11.config(state=NORMAL)

	def manual_mode(self):
		cmd = []
		(ip, port) = utility.getipinfo(self.e1.get())
		log.debug ("get ip infor-> ip: %s, port:%s" % (ip,port))
		if ip == False:
			log.error ("Given ip infor is wrong! The right ip address: xxx.xxx.xxx.xxx or IP:port ")
			return
		self.wf_manual = Workflow(cmd, ip, self.e2.get(), self.e3.get(), port)
		if self.wf_manual.setup_ssh(self.wf_manual.hostip) == False:
			log.error ("\nssh setup error! please check ip/user/passwd and network is okay")
			del self.wf_manual
			return
		self.console.delete('1.0',END)
		self.console.insert(END, "Switch to manual mode...\n\
Please input command directly after \">>> \"\n\n")
		self.prompt = ">>> "
		self.insert_prompt()
		self.manual = True
		self.b5.config(state=DISABLED)
		self.b11.config(state=DISABLED)

	def set_confirm_yes(self):
		try:
			self.wf.set_confirm('Yes')
		except AttributeError:
			log.debug("wf doesn't existed")
	def set_confirm_no(self):
		try:
			self.wf.set_confirm('No')
		except AttributeError:
			log.debug("wf doesn't existed")
	def set_confirm_skip(self):
		try:
			self.wf.set_confirm('Skip')
		except AttributeError:
			log.debug("wf doesn't existed")

	def callCheckbutton(self):
		try:
			if self.cb1State.get() == 1:
				self.wf.set_automatic(5)
			else:
				self.wf.set_automatic(None)
		except AttributeError:
			log.debug("wf doesn't existed")
			self.cb1.deselect()
			tkMessageBox.showwarning('Message', 'please press start button first')

	def saveinfo(self):
		pass

	def add_command(self):
		item = self.e4.get()
		if item != '':
			if utility.elemet_exists(self.cmdls.get(0,END), item) == None:
				self.cmdls.insert(END,item)
				self.cmdls.see(END)
				log.debug ("add new command %s" % item)
				self.save_command()
		else:
			tkMessageBox.showwarning('Message', 'entry can not empty')

	def del_command(self):
		if self.cmdls.curselection() != ():
			for i in self.cmdls.curselection():
				self.cmdls.delete(i)
				self.save_command()
		else:
			tkMessageBox.showwarning('Message', 'Please select at lease one item')

	def save_command(self):
		if utility.export_file(self.cmdls.get(0,END), self.db_file) != True:
			log.error ("save command pool failed")

	def reset_cmd_pool(self):
		log.debug ("start to reset command pool list")
		self.cmdls.delete(0,END)
		for element in constants.CMD_LIST_COMM:
			self.cmdls.insert(END, element)
		self.save_command()

	def insert_prompt(self):
		c = self.console.get("end-2c")
		if c != "\n":
			self.console.insert("end", "\n")
		self.console.insert("end", self.prompt, ("prompt",))
		#self.text.insert("end", self.prompt)
		# this mark lets us find the end of the prompt, and thus
		# the beggining of the user input
		self.console.mark_set("end-of-prompt", "end-1c")
		self.console.mark_gravity("end-of-prompt", "left")

	def process_input(self,event):
		index = self.console.index("end-1c linestart")
		line = self.console.get(index,'end-1c')
		log.debug ("last line: %s" % line)
		if self.manual == True:
			self.console.insert("end", "\n")
			command = self.console.get("end-of-prompt", "end-1c")
			command = command.strip()
			if command != '':
				if command == 'bye' or command == 'exit':
					log.info ("quit from manual mode...")
					self.wf_manual.ssh.close()
					self.manual = False
					self.b5.config(state=NORMAL)
					self.b11.config(state=NORMAL)
					return
				elif command == 'help':
					log.info ("This is used for run command on target server by ssh, for example: >>> df -h, >>> svcs -xv")
				elif self.wf_manual.remote_cmd(command) == 1:
					log.error ("command %s execute failed" % command)
			self.insert_prompt()
			self.console.see("end")
			# this prevents the class binding from firing, since we 
			# inserted the newline in this method
			return "break"
		else:
			if line == 'Yes' or line == 'y' or line == 'yes': 
				self.set_confirm_yes()
			elif line == 'No' or line == 'n' or line == 'no':
				self.set_confirm_no()
			elif line == 'Skip' or line == 's' or line == 'skip':
				self.set_confirm_skip()
			else:
				pass
Beispiel #12
0
class ServerGUI(object):
    server_on = False

    def __init__(self, window_title="Server GUI"):
        self.base_gui = pygui.Tk()

        self.window_title = window_title
        self.server_port = 0
        self.server = None

        # [GUI Initialization] ::start
        self.server_config_frame = pygui.Frame(self.base_gui)
        self.port_to_use_field = pygui.Entry(self.server_config_frame)
        self.server_controls_frame = pygui.Frame(self.base_gui)
        self.create_server_btn = pygui.Button(self.server_controls_frame,
                                              text="Start Server",
                                              command=self.invoke_server)
        self.stop_server_btn = pygui.Button(self.server_controls_frame,
                                            text="Stop Server",
                                            command=self.stop_server)
        self.quit_btn = pygui.Button(self.server_controls_frame,
                                     text="Quit",
                                     command=self.destroy_gui)
        # [GUI Initialization] ::end

        self.server_logs_frame = pygui.Frame(self.base_gui)
        self.activity_log_area = ScrolledText(self.server_logs_frame,
                                              height=10,
                                              width=50)

    def bootstrap(self):
        if self.server is None:
            print "Server Object must be specified. Call the set_server() method and set the ServerGUI Object."
            sys.exit(1)

        # set window title
        self.base_gui.wm_title(self.window_title)

        # [Config Section] :start
        self.server_config_frame.pack(side=pygui.TOP, pady=10)

        # Add field for port to use
        pygui.Label(self.server_config_frame,
                    text="Server port to use").grid(row=0, column=0)

        self.port_to_use_field.grid(row=0, column=1)
        self.port_to_use_field.bind("<Return>", self.invoke_server)
        # [Config Section] :end

        # [Controls Section] ::start
        self.server_controls_frame.pack(side=pygui.RIGHT, fill=pygui.Y)

        # Add Start server button
        self.create_server_btn.grid(row=0, column=1)

        # Stop Server
        self.stop_server_btn.grid(row=1, column=1)

        # Quit Button
        self.quit_btn.grid(row=2, column=1)
        # [Controls Section] ::end

        # [Logs Section] ::start
        self.server_logs_frame.pack(side=pygui.LEFT, padx=10, pady=10)

        # Create a text area for showing logs.
        pygui.Label(self.server_logs_frame, text="Logs").grid(row=0)

        self.activity_log_area.edit_modified(0)
        self.activity_log_area.grid(row=1)
        self.activity_log_area.config(highlightbackground="black")
        self.activity_log_area.bind('<<Modified>>', self.scroll_to_end)
        # [Logs Section] ::end

        # handle close button
        self.base_gui.protocol("WM_DELETE_WINDOW", self.destroy_gui)

        # Start the GUI
        self.base_gui.mainloop()

    def set_server(self, server):
        self.server = server

    def scroll_to_end(self, *_):
        # scroll to the end of text area
        self.activity_log_area.see(pygui.END)
        self.activity_log_area.edit_modified(0)

    def destroy_gui(self):
        self.stop_server()
        self.base_gui.destroy()

    def stop_server(self, *_):
        if self.server_on is True:
            self.server.stop(self.log)

            # set the SERVER_ON flag to false to enable create a new server instance
            self.server_on = False
        else:
            self.log("Server already stopped.")

    def invoke_server(self, *_):
        portval = self.port_to_use_field.get()

        if portval != '':
            # check if the input for port number is a valid integer
            try:
                self.server_port = int(portval)
            except ValueError:
                msgBox.showinfo("Client GUI", "Invalid Port Number")
                return

            # start the server if not yet started
            if self.server_on is False:
                # log the message
                self.server.set_port(self.server_port)

                if not self.server.invoke(self.log):
                    msgBox.showinfo(
                        "Client GUI",
                        "Cannot bind to port: %s. Please select another port to bind on."
                        % str(self.server_port))

                    return

                # Prevent starting another instance of server
                self.server_on = True
            else:
                self.log("Server already started on port: " +
                         str(self.server_port))
        else:
            self.log(
                "Please provide port number for the server to bind on. Thanks!"
            )

    def log(self, message):
        self.activity_log_area.insert(pygui.END, message + "\n")
Beispiel #13
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")
Beispiel #14
0
frm_log = Frame(mw,
                width=480,
                height=330,
                highlightbackground='gray',
                highlightcolor='black',
                highlightthickness=2)
frm_log.place(x=40, y=430, width=480, height=330)

log_text_area = ScrolledText(
    master=frm_log,
    # wrap=mw.WORD,
    highlightthickness=0)
log_text_area.configure(state='disabled')
log_text_area.pack(fill=BOTH)

log_text_area.bind('<Command-a>', select_all_text)
# log_text_area.bind('<Control-a>', select_all_text)

# ======== Odometry and Measurement Logging Frame ========
frm_pos = Frame(mw,
                width=511,
                height=330,
                highlightbackground='gray',
                highlightcolor='black',
                highlightthickness=2)
frm_pos.place(x=603, y=430, width=511, height=330)

pos_text_area = ScrolledText(
    master=frm_pos,
    # wrap=mw.WORD,
    highlightthickness=0)
Beispiel #15
0
class TextBox:
    def __init__(self):

        self.WIDTH = 600
        self.HEIGHT = 800
        self.FONT = "helvetica"
        self.FONT_SIZE = 12

        # colours specified as RGB fractions
        self.bg_input = [1, 1, 1]
        self.fg_input = [0, 0, 0]

        self.bg_article = [0, 0, 0]
        self.fg_min_article = [0.5, 0.5, 0.5]
        self.fg_max_article = [0.9, 0.9, 0.9]
        self.fg_solution_article = [1, 1, 1]  #[0.3, 0.5, 1.0] #[1, 0.7, 0.4]

        invert = False
        if invert:
            self.bg_input = [1. - v for v in self.bg_input]
            self.fg_input = [1. - v for v in self.fg_input]

            self.bg_article = [1. - v for v in self.bg_article]
            self.fg_min_article = [1. - v for v in self.fg_min_article]
            self.fg_max_article = [1. - v for v in self.fg_max_article]

        self.text = ""  # what is shown in the box
        self.allText = ""  # the text for the entire article
        self.sentences = []  # list of sentences in article
        # dictionary mapping from size to k-hot encoding indicating
        # which sentences are in the summary
        self.solutions = []
        # (not used) how much weight is put on each sentence
        self.weights = []

        self.only_summary = True
        self.summary_size = 1
        self.summary_coherence = 0.0
        self.summary_independence = 0.8

        self.summarizer = Summarizer(parent=self)

        self.root = Tk()

        self.draw(init=True)

        #self.root.mainloop()

    def draw(self, init=False):

        if init:
            # show main article body
            self.tk_article = ScrolledText(self.root)

            # let user paste and enter text
            self.tk_user_input = ScrolledText(self.root)

            self.tk_summary_size_scale = Scale(self.root)
            self.tk_summary_size_scale_label = Label(self.root, text="Length")

            self.tk_summary_coherence_scale = Scale(self.root)
            self.tk_summary_coherence_scale_label = Label(self.root,
                                                          text="Coherence")

            self.tk_summary_independence_scale = Scale(self.root)
            self.tk_summary_independence_scale_label = Label(
                self.root, text="Independence")

            self.tk_toggle_view = Button(self.root,
                                         text="more",
                                         command=self.handleToggleView)
            self.tk_recalculate = Button(self.root,
                                         text="Update",
                                         command=self.handleRecalculate)

            self.root.geometry("%dx%d" % (self.WIDTH, self.HEIGHT))
            self.root.title("QuickReader V4")

            self.tk_article.configure(width=25,
                                      height=6,
                                      bd=0,
                                      highlightthickness=0,
                                      wrap="word",
                                      font=self.FONT)

            self.tk_user_input.configure(width=25,
                                         height=3,
                                         bd=0,
                                         highlightthickness=0,
                                         wrap="word",
                                         font=self.FONT)

            self.tk_summary_size_scale.configure(
                bd=0,
                from_=0,
                to=20,
                orient=HORIZONTAL,
                sliderrelief=FLAT,
                command=lambda event: self.handleSlider(
                    self.tk_summary_size_scale.get()))

            ######
            self.tk_summary_coherence_scale.configure(
                bd=0,
                from_=0,
                to=1,
                orient=HORIZONTAL,
                sliderrelief=FLAT,
                resolution=0.05,
                command=lambda event: self.handleCoherenceSlider(
                    self.tk_summary_coherence_scale.get()))

            self.tk_summary_coherence_scale.set(self.summary_coherence)

            ######
            self.tk_summary_independence_scale.configure(
                bd=0,
                from_=0,
                to=1.5,
                orient=HORIZONTAL,
                sliderrelief=FLAT,
                resolution=0.05,
                command=lambda event: self.handleIndependenceSlider(
                    self.tk_summary_independence_scale.get()))

            self.tk_summary_independence_scale.set(self.summary_independence)

            # set colours
            self.root.configure(background="black")

            self.tk_summary_size_scale.configure(troughcolor="#444444",
                                                 fg="black",
                                                 background="white",
                                                 activebackground="#bbbbbb")

            self.tk_summary_coherence_scale.configure(
                troughcolor="#444444",
                fg="black",
                background="white",
                activebackground="#bbbbbb")

            self.tk_summary_independence_scale.configure(
                troughcolor="#444444",
                fg="black",
                background="white",
                activebackground="#bbbbbb")

            self.tk_article.configure(bg=toHex(self.bg_article),
                                      fg="white",
                                      insertbackground="blue")
            self.tk_article.vbar.configure(bg="white",
                                           width=10,
                                           troughcolor="black")

            self.tk_user_input.configure(bg=toHex(self.bg_input),
                                         fg=toHex(self.fg_input),
                                         insertbackground="blue")
            self.tk_user_input.vbar.configure(bg="white",
                                              width=10,
                                              troughcolor="black")

            self.tk_user_input.focus()
            self.tk_user_input.bind("<KeyRelease-Return>",
                                    (lambda event: self.handleUserInput(
                                        self.tk_user_input.get("0.0", END))))
            self.root.bind("<Configure>", self.resize)

    def setText(self, text, redraw=False):
        self.text = text
        if redraw: self.updateArticleInfo()

    def setSentences(self, sentences, redraw=False):
        self.sentences = sentences
        if redraw: self.updateArticleInfo()

    def setSolutions(self, solutions, redraw=False):
        self.solutions = solutions
        if redraw: self.updateArticleInfo()

    def setWeights(self, weights, redraw=False):
        self.weights = weights
        if redraw: self.updateArticleInfo()

    def handleToggleView(self):

        print("View toggle!")

        self.only_summary = not self.only_summary

        if self.only_summary:
            self.tk_toggle_view.configure(text="more")
        else:
            self.tk_toggle_view.configure(text="less")

        self.updateSummary()

    def handleRecalculate(self):
        print("Update!")

        self.handleUserInput(self.allText)

    def handleSlider(self, value):

        print("Slider:", value)

        self.summary_size = value

        self.updateSummary()

    def handleCoherenceSlider(self, value):

        print("Coherence Slider:", value)

        self.summary_coherence = value

        #self.updateSummary()

    def handleIndependenceSlider(self, value):

        print("Independence Slider:", value)

        self.summary_independence = value

        #self.updateSummary()

    def updateSummary(self):

        l = self.summary_size

        if self.only_summary and l != 0:
            self.setText('\n\n'.join([
                self.sentences[i] for i in range(len(self.sentences))
                if self.solutions[l][i] == 1
            ]))
        else:
            self.setText(self.allText, redraw=False)

        self.updateArticleInfo()

        self.setWeights([0. for _ in self.sentences], redraw=True)

        self.tk_article.yview_moveto(0)  #vbar.set(0, 0) #configure(jump=0)

    def handleUserInput(self, inStr):
        self.tk_user_input.delete("0.0", END)

        if inStr.strip() == "": return

        text = inStr

        text = ''.join([ch for ch in text if ord(ch) < 128])

        self.setText(text, redraw=False)
        self.setSolutions([], redraw=False)
        self.setWeights([], redraw=True)

        text, sentences, solutions = self.summarizer.summarize(
            text,
            coherence_weight=self.summary_coherence,
            independence_weight=self.summary_independence,
            size_weight=1.,
            beam_width=3,
            hard_size_limit=None)

        self.allText = text
        self.sentences = sentences
        self.solutions = solutions

        self.solutions[0] = [1. for _ in sentences]

        # get max length for summary
        max_len = max(solutions.keys())
        set_len = min(max_len, 3)
        self.tk_summary_size_scale.configure(from_=0, to=max_len)
        self.tk_summary_size_scale.set(set_len)
        self.summary_size = set_len

        # text: all the text in one long string
        # sentences: the text split up into a list of sentences
        # solution: dictionary mapping summary size to a one-hot vector over the sentences, indicating
        #   which sentences are included in the summarization

        # the text should be the same, but update it anyways since it needs to contain the
        #  exact same stuff as the sentences

        self.updateSummary()

        #self.updateArticleInfo()

    def resize(self, event=[]):
        LINEH = 20.0

        pixelX = self.root.winfo_width()
        pixelY = self.root.winfo_height()

        bf = 5  # buffer size in pixels

        # update find_icon, wiki_icon, and graph_icon

        # set toggle and recalculate button
        toggleW = 50
        toggleH = 35 * 1
        self.tk_toggle_view.place(x=pixelX - toggleW,
                                  y=0,
                                  width=toggleW,
                                  height=toggleH)

        updateW = 50
        updateH = 35 * 2
        self.tk_recalculate.place(x=pixelX - updateW,
                                  y=toggleH,
                                  width=updateW,
                                  height=updateH)

        buttonH = toggleH + updateH

        labelW = 90

        # set position of size scale
        scaleW = pixelX - updateW - labelW
        scaleH = 35
        self.tk_summary_size_scale.place(x=labelW,
                                         y=0,
                                         width=scaleW,
                                         height=scaleH)

        self.tk_summary_size_scale_label.place(x=0,
                                               y=0,
                                               width=labelW,
                                               height=scaleH)

        # set position of coherence scale
        coherenceW = pixelX - updateW - labelW
        coherenceH = 35
        self.tk_summary_coherence_scale.place(x=labelW,
                                              y=scaleH,
                                              width=scaleW,
                                              height=scaleH)

        self.tk_summary_coherence_scale_label.place(x=0,
                                                    y=scaleH,
                                                    width=labelW,
                                                    height=coherenceH)

        # set position of independence scale
        independenceW = pixelX - updateW - labelW
        independenceH = 35
        self.tk_summary_independence_scale.place(x=labelW,
                                                 y=scaleH + coherenceH,
                                                 width=scaleW,
                                                 height=scaleH)

        self.tk_summary_independence_scale_label.place(x=0,
                                                       y=scaleH + coherenceH,
                                                       width=labelW,
                                                       height=independenceH)

        # update user input
        inputW = pixelX
        inputH = int(3.0 * LINEH)
        self.tk_user_input.place(x=0,
                                 y=pixelY - inputH,
                                 width=inputW,
                                 height=inputH)

        # update article
        articleW = pixelX
        articleH = pixelY - inputH - scaleH - coherenceH - independenceH
        self.tk_article.place(x=0,
                              y=scaleH + coherenceH + independenceH,
                              width=articleW,
                              height=articleH)

    def updateArticleInfo(self):

        self.articleClear()

        self.articleCat(self.text)

        if self.weights != []:
            self.articleColour()

        self.root.update()

    def articleClear(self):
        self.tk_article.delete("1.0", END)
        self.tk_article.update()

        self.root.update()

        return

    def articleCat(self, inStr):

        self.tk_article.insert(END, inStr)

        self.tk_article.yview(END)

    def articleColour(self):
        '''
		solution = self.solutions[self.summary_size]

		allText = self.text #self.tk_article.get('1.0', 'end-1c')

		# make sure weights are normalised
		maxW = max(self.weights)
		minW = min(self.weights)

		weights = self.weights
		if maxW != minW:
			weights = [(v-minW)/(maxW-minW) for v in self.weights]

		for i in range(len(self.sentences)):
			if self.only_summary and solution[i] != 1.: continue

			s = self.sentences[i]
			if len(s.strip()) == 0:

				continue

			tagNameA = ''.join([random.choice('abcdefghijklmnopqrstuvwxyz') for _ in range(10)])
			L_Size = 12 # if solution[i] == 1 else 10
			
			L_Colour = blend(self.fg_min_article, self.fg_max_article, weights[i])
			L_Colour = self.fg_solution_article if solution[i] == 1 else L_Colour

			countVar = StringVar(self.root)
			pos = self.tk_article.search(s, "1.0", stopindex="end", count=countVar)

			self.tk_article.tag_add(tagNameA, pos, "{} + {}c".format(pos, countVar.get()))

			bolding = "normal" #"bold" if self.solution[i] == 1 else "normal" #
			font = (self.FONT, L_Size, bolding)
			self.tk_article.tag_config(tagNameA, foreground=toHex(L_Colour), font=font)#self.FONT+' %s'%(L_Size))

		
		self.root.update()
		'''

        solution = self.solutions[self.summary_size]

        allText = self.text  #self.tk_article.get('1.0', 'end-1c')

        #print("=========")
        for i in range(len(self.sentences)):
            if self.only_summary and solution[i] != 1.: continue

            s = self.sentences[i]
            #if len(s.strip()) == 0:
            #	continue

            #print("- ", s)

            tagNameA = ''.join([
                random.choice('abcdefghijklmnopqrstuvwxyz') for _ in range(10)
            ])
            L_Size = self.FONT_SIZE  # if solution[i] == 1 else 10

            L_Colour = self.fg_solution_article if solution[
                i] == 1 else self.fg_min_article
            #print("\t", L_Colour)

            countVar = StringVar(self.root)
            pos = self.tk_article.search(s,
                                         "1.0",
                                         stopindex="end",
                                         count=countVar)

            self.tk_article.tag_add(tagNameA, pos,
                                    "{} + {}c".format(pos, countVar.get()))

            bolding = "normal"  #"bold" if self.solution[i] == 1 else "normal" #
            font = (self.FONT, L_Size, bolding)
            self.tk_article.tag_config(tagNameA,
                                       foreground=toHex(L_Colour),
                                       font=font)  #self.FONT+' %s'%(L_Size))

        self.root.update()
Beispiel #16
0
   def __init__(self, master):
      Client.__init__(self)
      self.started = False          # use it to not try stopping if didn't start
      self.parent = master          # used to distroy it on exit
      master.title("TomIRC")        # app's title
      master.resizable(0, 0)        # user cannot resize it
      # master.config(width = 720, height = 526)
      # master.grid_propagate(False)  # doesn't change size because of inner elements

      result = InitialDialog(master, "Connection settings").result
      if not result:
         self.onExit()
         return

      self.started = True
      self.start(result[0], result[1])
      self.name = result[2]

      master.protocol("WM_DELETE_WINDOW", self.onExit)

      # add a menu
      menu = Menu(master)
      master.config(menu = menu)

      filemenu = Menu(menu)
      menu.add_cascade(label = "File", menu = filemenu)
      filemenu.add_command(label = "Change your username", command = self.changeName)
      filemenu.add_separator()
      filemenu.add_command(label = "Quit", command = self.onExit)
      menu.add_command(label = "About", command = self.aboutBox)

      # use a menu entry as an information bar
      menu.add_command(label = "               ", state = DISABLED)
      menu.add_command(label = "Connected to %s:%s as %s" % (result[0], result[1],\
                       self.name), state = DISABLED, background = "gray", \
                       font = tkFont.Font(family = "Times", weight = tkFont.BOLD,\
                              size = 10))
      menu.add_command(label = "                                         ",\
                       state = DISABLED)
      menu.add_command(label = "          Connected users           ",\
                       state = DISABLED, background = "gray", \
                       font = tkFont.Font(family = "Times", weight = tkFont.BOLD, \
                                          size = 10))
      menu.config(disabledforeground = "#777")
      self.menu = menu

      # list of connected users
      self.connectedUsers = StringVar()         # used to update the userList
      self.userList = Listbox(master, height = 15, width = 21, selectmode = MULTIPLE, \
                              listvariable = self.connectedUsers)
      self.userList.bind('<<ListboxSelect>>', self.onListSelect)
      # self.connectedUsers.set("default_user\n" + self.name)

      # add widget for displaying incoming text
      text = ScrolledText(master, height = 20, width = 75, state = DISABLED)
      text.tag_config("a", background = "lightgray")        # set a tag for the author
      text.tag_config('s', background = "darkgray")         # set a tag for the server
      self.display = text

      # add the text input
      text = ScrolledText(master, height = 5, width = 75)
      text.bind('<KeyRelease-Return>', self.sendMessage)
      text.focus_set()
      self.input = text

      # add a label to state errors and warnings
      self.infoLabel = StringVar(value = "Registered successfully...")
      label = Label(master, textvariable = self.infoLabel, anchor = W, fg = "#555")

      label.grid(row = 2, column = 0, columnspan = 2, sticky = W)
      self.display.grid(row = 0, column = 0, sticky = N)
      self.input.grid(row = 1, column = 0)
      self.userList.grid(row = 0, column = 1, rowspan = 2, sticky = N + S)
      self.send("REG " + self.name)          # register the user
      self.populateList()
Beispiel #17
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')
Beispiel #18
0
class UploadWizard(Wizard):
    def __init__(self, root, data):
        self.root = root
        self.data = data
        self.secure = False
        super(UploadWizard, self).__init__(
            width=450,
            height=300,
            cancelcommand=self._handle_cancel,
            finishcommand=self._handle_finish,
        )
        self.servers = ServerList()
        self.server_lbox = None
        self.upthread = None
        self.old_upload_state = None
        self.setup_gui()

    def setup_gui(self):
        self.title("Upload Wizard")
        self.protocol("WM_DELETE_WINDOW", self._handle_cancel)
        self.setup_gui_server_pane()
        self.setup_gui_user_pane()
        self.setup_gui_program_pane()
        self.setup_gui_upload_pane()

    def setup_gui_server_pane(self):
        fr = self.add_pane(
            'server', 'Select Server',
            entrycommand=self._enter_server_pane
        )
        fr.config(padx=20, pady=20)
        self.ssl_enable = IntVar()
        lbox_lbl = Label(fr, text="Select a Server to upload to:")
        self.server_lbox = ScrolledListbox(
            fr, horiz_scroll=False, width=20, highlightthickness=1)
        muck_lbl = Label(fr, text="Name")
        host_lbl = Label(fr, text="Host")
        port_lbl = Label(fr, text="Port")
        svalid = (self.register(self._serv_validate))
        pvalid = (self.register(self._port_validate), '%P')
        self.muck_entry = Entry(
            fr, width=30, validate=ALL, validatecommand=svalid)
        self.host_entry = Entry(
            fr, width=30, validate=ALL, validatecommand=svalid)
        self.port_entry = Entry(
            fr, width=10, validate=ALL, validatecommand=pvalid)
        self.port_entry.insert(END, '8888')
        self.ssl_cb = Checkbutton(
            fr, text="SSL",
            variable=self.ssl_enable,
            highlightthickness=3,
            command=self._update_server_buttons,
        )
        self.serv_del = Button(fr, text="-", width=1, command=self._del_server)
        self.serv_add = Button(fr, text="+", width=1, command=self._add_server)
        self.serv_save = Button(fr, text="Save", command=self._save_server)
        ToolTip(self.serv_del, "Delete selected Favorite Server")
        ToolTip(self.serv_add, "Enter a new Server")
        ToolTip(self.serv_save, "Save as a Favorite Server")
        self.server_lbox.bind('<<ListboxSelect>>', self._server_listbox_select)
        lbox_lbl.grid(row=0, column=0, sticky=N+W)
        self.server_lbox.grid(
            row=1, column=0, rowspan=8, padx=5, sticky=N+S+E+W)
        muck_lbl.grid(row=1, column=1, sticky=W, padx=5)
        self.muck_entry.grid(row=2, column=1, columnspan=3, sticky=E+W, padx=5)
        host_lbl.grid(row=3, column=1, sticky=W, padx=5)
        self.host_entry.grid(row=4, column=1, columnspan=3, sticky=E+W, padx=5)
        port_lbl.grid(row=5, column=1, sticky=W, padx=5)
        self.port_entry.grid(row=6, column=1, columnspan=2, sticky=E+W, padx=5)
        self.ssl_cb.grid(row=6, column=3, sticky=E, padx=5)
        self.serv_del.grid(row=8, column=1, sticky=N+W, padx=5)
        self.serv_add.grid(row=8, column=2, sticky=N+W, padx=5)
        self.serv_save.grid(row=8, column=3, sticky=N+E, padx=5)
        fr.grid_columnconfigure(2, weight=1, minsize=50)
        fr.grid_rowconfigure(7, weight=1)
        self.server_lbox.focus()
        return fr

    def setup_gui_user_pane(self):
        fr = self.add_pane(
            'user', 'Select a user',
            entrycommand=self._enter_user_pane
        )
        fr.config(padx=20, pady=20)
        lbox_lbl = Label(fr, text="Select a User to upload to:")
        self.user_lbox = ScrolledListbox(fr, horiz_scroll=False, width=20)
        user_lbl = Label(fr, text="UserName")
        pass_lbl = Label(fr, text="Password")
        uvalid = (self.register(self._user_validate))
        self.user_entry = Entry(
            fr, width=30, validate=ALL, validatecommand=uvalid)
        self.pass_entry = Entry(
            fr, width=30, show="*", validate=ALL, validatecommand=uvalid)
        self.user_del = Button(fr, text="-", width=1, command=self._del_user)
        self.user_add = Button(fr, text="+", width=1, command=self._add_user)
        self.user_save = Button(fr, text="Save", command=self._save_user)
        ToolTip(self.user_del, "Delete selected User")
        ToolTip(self.user_add, "Enter a new User")
        ToolTip(self.user_save, "Save User Info")
        self.user_lbox.bind('<<ListboxSelect>>', self._user_listbox_select)
        lbox_lbl.grid(row=0, column=0, sticky=N+W)
        self.user_lbox.grid(row=1, column=0, rowspan=8, padx=5, sticky=N+S+E+W)
        user_lbl.grid(row=1, column=1, sticky=W, padx=5)
        self.user_entry.grid(row=2, column=1, columnspan=3, sticky=E+W, padx=5)
        pass_lbl.grid(row=3, column=1, sticky=W, padx=5)
        self.pass_entry.grid(row=4, column=1, columnspan=3, sticky=E+W, padx=5)
        self.user_del.grid(row=6, column=1, sticky=N+W, padx=5)
        self.user_add.grid(row=6, column=2, sticky=N+W, padx=5)
        self.user_save.grid(row=6, column=3, sticky=N+E, padx=5)
        fr.grid_columnconfigure(2, weight=1, minsize=50)
        fr.grid_rowconfigure(5, weight=1)
        return fr

    def setup_gui_program_pane(self):
        fr = self.add_pane(
            'program', 'Program Info',
            entrycommand=self._enter_program_pane
        )
        pvalid = (self.register(self._program_validate))
        fr.config(padx=20, pady=20)
        prog_lbl = Label(fr, text="Program Name or DBRef")
        self.prog_entry = Entry(
            fr, width=30, validate=ALL, validatecommand=pvalid)
        global previous_progname
        self.prog_entry.insert(END, previous_progname)
        prog_lbl.grid(row=0, column=0, sticky=W+S)
        self.prog_entry.grid(row=1, column=0, sticky=N+E+W)
        fr.grid_columnconfigure(0, weight=1)
        fr.grid_rowconfigure(2, weight=1)
        return fr

    def setup_gui_upload_pane(self):
        fr = self.add_pane(
            'upload', 'Uploading',
            entrycommand=self._enter_upload_pane
        )
        fr.config(padx=20, pady=20)
        self.upload_lbl = Label(
            fr, text="", justify=LEFT, anchor=W, wraplength=400)
        self.progressbar = ProgressBar(
            fr, length=300,
            value=10.0, maximum=100.0,
            mode=INDETERMINATE,
        )
        self.console_log = ScrolledText(
            fr, font='TkFixedFont',
            relief=SUNKEN,
            borderwidth=2,
            background="black",
            foreground="white",
            width=1,
            height=1,
            insertontime=0,
            takefocus=0,
            cursor='arrow',
        )
        ro_binds = [
            "<Key>",
            "<<Cut>>",
            "<<Clear>>",
            "<<Paste>>",
            "<<PasteSelection>>",
            "<Double-Button-1>",
        ]
        for bind in ro_binds:
            self.console_log.bind(bind, lambda e: "break")
        self.upload_lbl.grid(row=0, column=0, sticky=W+S)
        self.progressbar.grid(row=1, column=0, sticky=N+E+W, padx=15, pady=5)
        self.console_log.grid(row=2, column=0, sticky=N+S+E+W)
        fr.grid_columnconfigure(0, weight=1)
        fr.grid_rowconfigure(2, weight=1)
        return fr

    def _enter_server_pane(self):
        self.set_finish_enabled(False)
        self.set_next_enabled(False)
        self.set_next_text()
        self.set_default_button("next")
        self.set_finish_text("Done")
        self._populate_server_listbox()
        if self.server_lbox.size() > 0:
            self.server_lbox.focus()
        else:
            self.muck_entry.focus()
        self._update_server_buttons()

    def _enter_user_pane(self):
        self.set_finish_enabled(False)
        self.set_next_enabled(False)
        self.set_next_text()
        self.set_default_button("next")
        self._populate_user_listbox()
        if self.user_lbox.size() > 0:
            self.user_lbox.focus()
        else:
            self.user_entry.focus()
        self._update_user_buttons()

    def _enter_program_pane(self):
        self.set_finish_enabled(False)
        self.set_next_enabled(False)
        self.set_next_text("Upload")
        self.set_default_button("next")
        self.prog_entry.focus()

    def _enter_upload_pane(self):
        self.set_default_button("finish")
        self.set_next_text()
        self.set_prev_enabled(False)
        self.set_finish_enabled(False)
        self._upload_start()
        global previous_progname
        previous_progname = self.prog_entry.get()

    def _populate_server_listbox(self):
        self.server_lbox.delete(0, END)
        for serv in self.servers.get_servers():
            self.server_lbox.insert(END, str(serv))

    def _update_server_listbox(self):
        sel = self.server_lbox.curselection()
        self._populate_server_listbox()
        if sel:
            self.server_lbox.selection_set(sel[0])
        self._update_server_buttons()

    def _server_listbox_select(self, event=None):
        try:
            sel = int(self.server_lbox.curselection()[0])
            servers = self.servers.get_servers()
            serv = servers[sel]
            self.muck_entry.delete(0, END)
            self.host_entry.delete(0, END)
            self.port_entry.delete(0, END)
            self.muck_entry.insert(END, serv.name)
            self.host_entry.insert(END, serv.host)
            self.port_entry.insert(END, serv.port)
            self.ssl_enable.set(serv.ssl)
            self._update_server_buttons()
        except (ValueError, IndexError):
            return

    def _update_server_buttons(self, event=None):
        add_state = 'normal'
        del_state = 'normal'
        save_state = 'normal'
        items = self.server_lbox.curselection()
        if not items:
            del_state = 'disabled'
            if not self.muck_entry.get():
                if not self.host_entry.get():
                    if self.port_entry.get() == '8888':
                        if not self.ssl_enable.get():
                            add_state = 'disabled'
        if not self.host_entry.get() or not self.port_entry.get():
            save_state = 'disabled'
        self.serv_del.config(state=del_state)
        self.serv_add.config(state=add_state)
        self.serv_save.config(state=save_state)
        self.set_next_enabled(
            bool(items or (self.host_entry.get() and self.port_entry.get()))
        )

    def _serv_validate(self):
        self.after_idle(self._update_server_buttons)
        return True

    def _port_validate(self, val):
        self.after_idle(self._update_server_buttons)
        if val == '':
            return True
        try:
            val = int(val)
            return True
        except ValueError:
            self.bell()
        return False

    def _add_server(self):
        self.server_lbox.selection_clear(0, END)
        self.muck_entry.delete(0, END)
        self.host_entry.delete(0, END)
        self.port_entry.delete(0, END)
        self.port_entry.insert(END, '8888')
        self.ssl_enable.set('0')
        self.muck_entry.focus()
        self._update_server_buttons()

    def _del_server(self):
        del_confirmed = askyesno(
            "Delete Server",
            "Are you sure you want to delete this server?",
            parent=self
        )
        if del_confirmed:
            try:
                sel = int(self.server_lbox.curselection()[0])
                self.servers.del_server(sel)
                self.servers.save()
                self._update_server_listbox()
            except (ValueError, IndexError):
                self.bell()

    def _save_server(self):
        sel = -1
        try:
            sel = int(self.server_lbox.curselection()[0])
            self.servers.del_server(sel)
            self._update_server_listbox()
        except (ValueError, IndexError):
            pass
        server = ServerInfo(
            name=self.muck_entry.get(),
            host=self.host_entry.get(),
            port=self.port_entry.get(),
            use_ssl=self.ssl_enable.get()
        )
        self.servers.add_server(server)
        self.servers.save()
        self._update_server_listbox()
        if sel >= 0:
            self.server_lbox.selection_set(sel)
        self._server_listbox_select()
        self._update_server_buttons()

    def _populate_user_listbox(self):
        host = self.host_entry.get()
        port = int(self.port_entry.get())
        serv = self.servers.find_by_host_and_port(host, port)
        self.user_lbox.delete(0, END)
        if not serv:
            return
        for user in serv.get_users():
            self.user_lbox.insert(END, user.user)

    def _update_user_listbox(self):
        sel = self.user_lbox.curselection()
        self._populate_user_listbox()
        if sel:
            self.user_lbox.selection_set(sel[0])
        self._update_user_buttons()

    def _user_listbox_select(self, event=None):
        host = self.host_entry.get()
        port = int(self.port_entry.get())
        serv = self.servers.find_by_host_and_port(host, port)
        if not serv:
            return
        try:
            sel = int(self.user_lbox.curselection()[0])
            users = serv.get_users()
            user = users[sel]
            self.user_entry.delete(0, END)
            self.pass_entry.delete(0, END)
            self.user_entry.insert(END, user.user)
            self.pass_entry.insert(END, user.password)
            self._update_server_buttons()
        except (ValueError, IndexError):
            return

    def _update_user_buttons(self, event=None):
        add_state = 'normal'
        del_state = 'normal'
        save_state = 'normal'
        host = self.host_entry.get()
        port = int(self.port_entry.get())
        serv = self.servers.find_by_host_and_port(host, port)
        if not serv:
            del_state = 'disabled'
            add_state = 'disabled'
            save_state = 'disabled'
        items = self.user_lbox.curselection()
        if not items:
            del_state = 'disabled'
            if not self.user_entry.get():
                if not self.pass_entry.get():
                    add_state = 'disabled'
        if not self.user_entry.get():
            save_state = 'disabled'
        self.user_del.config(state=del_state)
        self.user_add.config(state=add_state)
        self.user_save.config(state=save_state)
        self.set_next_enabled(
            bool(items or (self.user_entry.get() and self.pass_entry.get()))
        )

    def _user_validate(self):
        self.after_idle(self._update_user_buttons)
        return True

    def _add_user(self):
        self.user_lbox.selection_clear(0, END)
        self.user_entry.delete(0, END)
        self.pass_entry.delete(0, END)
        self._update_user_buttons()
        self.user_entry.focus()

    def _del_user(self):
        del_confirmed = askyesno(
            "Delete User",
            "Are you sure you want to delete this user?",
            parent=self
        )
        if del_confirmed:
            host = self.host_entry.get()
            port = int(self.port_entry.get())
            serv = self.servers.find_by_host_and_port(host, port)
            if not serv:
                return
            try:
                sel = int(self.server_lbox.curselection()[0])
                serv.del_user(sel)
                self.servers.save()
                self._update_user_listbox()
            except (ValueError, IndexError):
                self.bell()

    def _save_user(self):
        host = self.host_entry.get()
        port = int(self.port_entry.get())
        serv = self.servers.find_by_host_and_port(host, port)
        if not serv:
            return
        serv.add_user(
            user=self.user_entry.get(),
            password=self.pass_entry.get(),
        )
        self.servers.save()
        self._update_user_listbox()

    def _update_program_buttons(self, event=None):
        self.set_next_enabled(bool(self.prog_entry.get()))

    def _program_validate(self):
        self.after_idle(self._update_program_buttons)
        return True

    def _upload_start(self):
        force_ssl = bool(self.ssl_enable.get())
        host = self.host_entry.get()
        port = int(self.port_entry.get())
        user = self.user_entry.get()
        password = self.pass_entry.get()
        progname = self.prog_entry.get()
        self.upload_lbl.config(text="Connecting to %s:%s..." % (host, port))
        self.progressbar.start()
        self.upthread = UploadThread(
            host, port, force_ssl,
            user, password, progname,
            self.data,
        )
        self.upthread.start()
        self.old_upload_state = ''
        self._update_upload_state()

    def _update_upload_state(self):
        logtxt = self.upthread.get_log_text()
        if logtxt:
            self.console_log.insert(END, logtxt)
            self.console_log.see(END)
        state = self.upthread.state
        self.upload_lbl.config(text=self.upthread.status)
        if state in [UPLOAD_FAIL, UPLOAD_SUCCESS]:
            self.set_finish_enabled(True)
            self.set_cancel_enabled(False)
        else:
            self.after(100, self._update_upload_state)
        if state == UPLOADING:
            uploaded = self.upthread.bytes_uploaded
            total = self.upthread.total_bytes
            pcnt = float(uploaded) / total
            self.progressbar.config(value=pcnt)
        if state == self.old_upload_state:
            return
        self.old_upload_state = state
        if state == UPLOADING:
            self.progressbar.stop()
            self.progressbar.config(mode=DETERMINATE)
        elif state == UPLOAD_FAIL:
            self.progressbar.stop()
            self.progressbar.grid_forget()
        elif state == UPLOAD_SUCCESS:
            self.progressbar.stop()
            self.progressbar.config(mode=DETERMINATE)
            self.progressbar.config(value=100.0)

    def _handle_cancel(self):
        self.destroy()

    def _handle_finish(self):
        self.destroy()
Beispiel #19
0
class Globby_Text_Editor(tk.Frame):
    def __init__(self, parent_widget, settings):
        # some initial values
        # TODO this Values are obsolete since Project_Settings covers them
        # --> self.settings.projects_path
        self.hash_opened_filename = None
        self.opened_filename = None
        self.settings = settings

        self.edit_button_list=[
            {'text':'new page', 'cmd':self.on_new_page,
                'keytxt':'CTRL+n','hotkey':'<Control-n>'},
            {'text':'del page', 'cmd':self.on_del_page,
                'keytxt':'CTRL+n','hotkey':'<DELETE>'} ,
            {'text':'save', 'cmd':self.on_save,
                'keytxt':'CTRL+s','hotkey':'<Control-s>'},
            {'text':'undo', 'cmd':self.on_undo,
                'keytxt':'CTRL+z','hotkey':'<Control-z>'},
            {'text':'redo', 'cmd':self.on_redo,
                'keytxt':'CTRL+y','hotkey':'<Control-y>'}]

        self.syntax_button_list=[
            {'text':'**bold**', 'cmd':self.on_tag_insert, 'open_tag':'**',
                'close_tag':'**','keytxt':'CTRL+b','hotkey':'<Control-b>'},
            {'text':'//italic//', 'cmd':self.on_tag_insert, 'open_tag':'//',
                'close_tag':'//', 'keytxt':'CTRL+i','hotkey':'<Control-i>'},
            {'text':'__underline__', 'cmd':self.on_tag_insert, 'open_tag':'__',
                'close_tag':'__', 'keytxt':'CTRL+u','hotkey':'<Control-u>'},
            {'text':'[Link]', 'cmd':self.on_tag_insert, 'open_tag':'[',
                'close_tag':']', 'keytxt':'CTRL+l','hotkey':'<Control-l>'},
            {'text':'¸¸sub¸¸', 'cmd':self.on_tag_insert, 'open_tag':'¸¸',
                'close_tag':'¸¸', 'keytxt':'CTRL+d','hotkey':'<Control-d>'},
            {'text':'^^upper^^', 'cmd':self.on_tag_insert, 'open_tag':'^^',
                'close_tag':'^^', 'keytxt':'CTRL+q','hotkey':'<Control-q>'},
            {'text':'-~smaller~-', 'cmd':self.on_tag_insert, 'open_tag':'-~',
                'close_tag':'~-', 'keytxt':'CTRL+w','hotkey':'<Control-w>'},
            {'text':'+~bigger~+', 'cmd':self.on_tag_insert, 'open_tag':'+~',
                'close_tag':'~+', 'keytxt':'CTRL+e','hotkey':'<Control-e>'},
            {'text':'~~strike_thru~~', 'cmd':self.on_tag_insert, 'open_tag':'~~',
                'close_tag':'~~', 'keytxt':'CTRL+t','hotkey':'<Control-t>'} ]

        # build Widgets
        tk.Frame.__init__(self, parent_widget)
        self.pack(fill=tk.BOTH, expand=tk.YES)

        #self.baseframe = tk.Frame(parent_widget)
        #self.baseframe.pack(fill=tk.BOTH, expand=tk.YES)
        self.editor()
        self.button_frame()

        # start tracking text changes inside the editfield
        thread.start_new_thread(self.on_txt_changes, ('',))



    def editor(self):
        """ combine some Widgets to an enhanced editor (incl. Scrollbar)

        --> self.text
                the text widget itself

        --> self.opened_file_label
                Label on top of the editfield to show the name of the current
                opened File
                It can be used to show textchanges
        """
        # build widgets
        self.txtfrm = tk.Frame(self)
        self.txtfrm.pack(fill=tk.BOTH, side=tk.LEFT, expand=tk.YES)
        self.opened_file_label = tk.Label(self.txtfrm, text="No File chosen")
        self.opened_file_label.pack(fill=tk.X)
        self.text = ScrolledText(self.txtfrm, bg="white",
                                undo=1, maxundo=30,
                                wrap=tk.WORD)
        self.text.pack(fill=tk.BOTH, expand=tk.YES, side=tk.LEFT)
        self.text.insert(1.0, u"Please open a File to edit")

        # build first(reference -- new name??) hash for comparison on changes
        self.hash_opened_filename = hash(self.text.get(1.0,tk.END))

        # Set focus on textwidget and move cursor to the upper left
        self.text.focus_set()
        self.text.mark_set(tk.INSERT, '0.0')      # goto line
        self.text.see(tk.INSERT)                  # scroll to line


    def label_button_row(self, parent_widget=None,
                            btnlst=None, start_count=0):
        """Build a 2 column table with a label beside each button in a row.
        Bind a keyboard sequence to the button command.
        Display this keyboard sequence on the label.

        todo:
            - think about a parameter for the widget to bind the Hotkeys
            - rename to: labled_button_row, draw_labled_button_row

        Parameter:
        --> parent_widget:
                Parent widget to place the table

        --> btnlst:
                Type: List of dicts representing a button
                Example:
                    {'text':'**bold**',     # displayed on the Button (string)
                    'cmd':self.on_tag_insert,   # command
                    'open_tag':'**',        # chars representing the beginning
                                            # of a tag for inserting (string)
                    'close_tag':'**',       # chars representing the end
                                            # of a tag for inserting (string)
                    'keytxt':'CTRL+b',      # displayed on the Label (string)
                    'hotkey':'<Control-b>'} # keyboard sequence (string)
                Note:
                    The existence of 'open_tag' and 'close_tag' in btnlst
                    decides which command is bound to the Button.
                    If they aren't there 'cmd' must be a function without
                    parameters!!!
                    otherwise 'cmd' needs following parameters:
                        otag = btn['open_tag']
                        ctag = btn['close_tag']
                        event = None  # Placeholder for a keysequence

        --> start_count:
                Type: int

                Description:
                    The table is relized with tkinter grid layout manager.
                    start_count is used if there is already a grid
                    (with a Label beside a button).
                    start_count can add the automatic genrated
                    buttons under the existing.
                    In Globby_Editor it is used to put a label_button_row
                    under a Tkinter menubutton(file choose, headlines).
        """
        i = start_count
        for btn in btnlst:
            try:
                otag = btn['open_tag']
                ctag = btn['close_tag']
                event = None
                doit = lambda e=event, o=otag, c=ctag:self.on_tag_insert(e,o,c)
                tk.Button(parent_widget, text=btn['text'], command=doit,
                        relief=tk.RIDGE
                        ).grid(column=0, row=i, sticky=tk.W+tk.E)
                self.text.bind(btn['hotkey'],doit)
            except KeyError:
                tk.Button(parent_widget, text=btn['text'], command=btn['cmd'],
                        relief=tk.RIDGE
                        ).grid(column=0, row=i, sticky=tk.W+tk.E)
            tk.Label(parent_widget, text=btn['keytxt'], relief=tk.FLAT
                ).grid(column=1, row=i, sticky=tk.W)
            i +=1


    def button_frame(self):
        """draws a frame to hold a edit- and syntax-buttons under each other
        """
        self.btnfrm = tk.Frame(self)
        self.btnfrm.pack(fill=tk.BOTH, side=tk.LEFT)
        self.edit_buttons()
        self.syntax_buttons()


    def edit_buttons(self):
        """draws a frame with buttons for editing (save, undo, redo, open)
        """

        # genrate a labelframe
        self.efrm = tk.LabelFrame(self.btnfrm, text="Edit Buttons")
        self.efrm.pack(fill=tk.BOTH, padx=5, pady=5)

        # generate a button with a pulldown menue to open a file to edit
        self.file_open_mbtn = tk.Menubutton(self.efrm, text='Open File')
        # generate the pulldown menue
        self.file_open_menu = tk.Menu(self.file_open_mbtn,
                                        postcommand=self.gen_file2edit_menu)
        # bind the pulldown menue to the menubutton
        self.file_open_mbtn.config(menu=self.file_open_menu, relief=tk.RIDGE)


        self.file_open_mbtn.grid(column=0,row=0, sticky=tk.W+tk.E)

        # label beside the Button to display the associated keyboard shortcut
        self.file_open_lbl = tk.Label(self.efrm, text='CTRL+o', relief=tk.FLAT)
        self.file_open_lbl.grid(column=1, row=0, sticky=tk.W+tk.E)


        # generate buttons as described in self.edit_button_list
        self.label_button_row(self.efrm, self.edit_button_list, 2)


        # bind keyboard shortcut to the menue
        self.text.bind('<Control-o>',
                lambda e: self.file_open_menu.tk_popup(e.x_root, e.y_root))


    def gen_file2edit_menu(self):
        """generates a (new) menu bound to the file chooser button
        so every time when a project is created or deleted
        gen_choose_project_menu should be called
        """
        # delete all existing menue entrys
        self.file_open_menu.delete(0,tk.END)
        proj_path = os.path.join(self.settings.projects_path,
                                self.settings.current_project )
        print "proj_path", proj_path
        for this_file in os.listdir(proj_path):
            splitted = os.path.splitext(this_file)
            if splitted[1] == ".txt" and splitted[0] != "menue":
                #print "this_file",this_file
                open_file = os.path.join(proj_path, this_file)
                do_it = lambda bla = open_file:self.on_open(bla)
                self.file_open_menu.add_command(label=splitted, command=do_it)




    def syntax_buttons(self):
        """draws a frame with buttons for insert (wiki)markup

        idea: new parameter for on_tag_insert()
            jump_in_between=True/False so a pulldown list for different levels
            of headlines arn't necessary
        """

        # genrate a labelframe
        self.sfrm = tk.LabelFrame(self.btnfrm, text="Syntax Buttons")
        self.sfrm.pack(fill=tk.BOTH, padx=5, pady=5)

        # generate a button with a pulldown menue für headline Syntax
        self.headln_menubtn = tk.Menubutton(self.sfrm, text='= Headlines =')
        # generate the pulldown menue
        self.headln_menu = tk.Menu(self.headln_menubtn)
        # bind the pulldown menue to the menubutton
        self.headln_menubtn.config(menu=self.headln_menu, relief=tk.RIDGE)
        # generate menue entrys
        i=1
        for entry in ('h1','h2','h3','h4','h5','h6'):
            otag = '\n\n'+'='*i+' '
            ctag = ' '+'='*i+'\n\n'
            doit = lambda event=None, o=otag, c=ctag:self.on_tag_insert(event,o,c)
            self.headln_menu.add_command(label=entry, command=doit)
            i+=1
        self.headln_menubtn.grid(column=0,row=0, sticky=tk.W+tk.E)

        # label beside the Button to display the associated keyboard shortcut
        self.headln_lbl = tk.Label(self.sfrm, text='CTRL+h', relief=tk.FLAT)
        self.headln_lbl.grid(column=1, row=0, sticky=tk.W+tk.E)

        # generate buttons as described in self.edit_button_list
        self.label_button_row(self.sfrm, self.syntax_button_list, 1)

        # bind keyboard shortcut to the menue
        self.text.bind('<Control-h>',
                lambda e: self.headln_menu.tk_popup(e.x_root, e.y_root))


    def on_txt_changes(self, dummy_value=tk.NONE):
        """ tracks text changes inside the editfield by comparing hash values
        new name: visualize_txt_changes???
        """
        while True:
            new_hash = hash(self.text.get(1.0, tk.END))
            if new_hash != self.hash_opened_filename:
                #print "changes"
                self.opened_file_label.configure(fg="red")
            else:
                #print "no changes"
                self.opened_file_label.configure(fg="black")
            sleep(0.2)


    def on_open(self, file_to_open=None):
        """- opens a *.txt file from project folder
        - generates a reference hash.
        - Brings the cursor to the upper left and show this position
          in the textfield

        Parameter:
        --> file_to_open:
                complete path for file to open
        idea:
            - rename file_to_open to openfile or file_to_open
        """
        self.opened_file_to_open = file_to_open
        self.opened_file_label.configure(text=file_to_open)
        self.text.delete(1.0, tk.END)

        self.opened_filename = os.path.basename(file_to_open)


        # write file content into the editfield
        editfile = codecs.open(file_to_open,'r', 'utf-8')
        self.text.insert(1.0, editfile.read())
        editfile.close()

        # generate reference hash for a comparison to track text changes
        self.hash_opened_filename = hash(self.text.get(1.0,tk.END))

        self.text.edit_reset()                  # clear tk's undo/redo stacks
        self.text.focus_set()                   # focus to textfield
        self.text.mark_set(tk.INSERT, '0.0')    # place cursor to upper left
        self.text.see(tk.INSERT)                # and display this line


    def on_save(self):
        """ Safes the current edited file"""
        if self.opened_filename:
            print "on_safe_"
            print "  self.opened_filename",self.opened_filename

            self.hash_opened_filename = hash(self.text.get(1.0,tk.END))


            path_to_safe_file = os.path.join(self.settings.projects_path,
                                    self.settings.current_project,
                                    self.opened_filename)

            safefile = codecs.open(path_to_safe_file,'w', 'utf-8')
            safefile.write(self.text.get(1.0,tk.END))
            safefile.close()
            self.text.edit_reset()        #clear tk's undo/redo stacks
        else:
            showinfo('Globby Text Editor','No File to save \n\n'
                    'You need to choose a File before editing')


    def on_undo(self):
        try:                                    # tk8.4 keeps undo/redo stacks
            self.text.edit_undo( )              # exception if stacks empty
        except tk.TclError:
            showinfo('Globby Text Editor', 'Nothing to undo')


    def on_redo(self):
        print "redo"
        try:                                  # tk8.4 keeps undo/redo stacks
            self.text.edit_redo()             # exception if stacks empty
        except tk.TclError:
            showinfo('Globby Text Editor', 'Nothing to redo')


    def on_new_page(self):
        """ Ask the user to name the new File, create a blank File and load it
        into the Editorwidget

        TODO:   check if file with the new filename allready exists
                check if Filename contains Specialchars
        """
        print "on_new_page"
        nfile_name = tkSimpleDialog.askstring("New File Name",
                                    "Fill in a new File Name")
        proj_path = os.path.join(self.settings.projects_path,
                                self.settings.current_project)
        nfile_name = os.path.join(proj_path, nfile_name.strip()+'.txt')
        nfile = codecs.open(nfile_name, 'w', 'utf-8')

        current_project = self.settings.current_project
        infostring1 = u'# Diese Datei wurde automatisch mit '
        infostring2 = u'dem Projekt "%s" erstellt' % current_project
        nfile.write(infostring1+infostring2 )
        nfile.close()

        self.on_open(nfile_name)

    def on_del_page(self):
        """"""
        print "del page"
        # self.settings.current_project
        del_file = os.path.join(self.settings.projects_path,
                                    self.settings.current_project,
                                    self.opened_filename)

        del_page = askyesno("Do you really want to delete ", del_file)

        if del_page:
            #self.set_project(self.new_project_name)
            print "%s geloescht" % del_file
            os.remove(del_file)


    def on_tag_insert(self, event=None, open_tag=None, close_tag=None):
        """ inserts a (wiki)tag to the current cursor position.

        If there is no text marked in the editfield, open_tag and close_tag
        are inserted to the current cursor position behind each other and the
        cursor jumps in between.
        Otherwise the marked string is enclosed by open_tag and close_tag and
        inserted to the current cursor position. Here the new cursor position
        is right behind the complete inserted string with tags.

        At this moment this behavior is quite buggy :-(

        idea:
            - new parameter for on_tag_insert()
              jump_in_between=True/False so a pulldown list for different levels
              of headlines arn't necessary
            - rename to: on_insert_tag?? on_tag_insert

        Parameter:
        --> event                       # keyboard shortcut
        --> open_tag                    # string
        --> close_tag                   # string

        """
        #print 'event',event
        #print 'open_tag',open_tag
        #print 'close_tag',close_tag

        ## when no String is selected:
        if not self.text.tag_ranges(tk.SEL):
            print "no String is selected"
            insert_point = self.text.index('insert')
            insertline = insert_point.split('.')[0]
            addit = 1
            if event != None:
                print "event not None"
                addit = 2
            insertrow = str(int(insert_point.split('.')[1])+len(open_tag)+addit)
            new_insert_point = insertline+'.'+ insertrow
            self.text.insert(insert_point, open_tag+''+close_tag)
            # place cursor to insert_point
            self.text.mark_set(tk.INSERT, new_insert_point)
            # display this position on the editfield
            self.text.see(tk.INSERT)

        ## when a String is selected:
        else:
            #print "im else"
            marked_text = self.text.get(self.text.index(tk.SEL_FIRST),
                                        self.text.index(tk.SEL_LAST))
            replace_index = self.text.index(tk.SEL_FIRST)
            print "replace_index in selected", replace_index
            self.text.delete(self.text.index(tk.SEL_FIRST),
                            self.text.index(tk.SEL_LAST))
            self.text.insert(replace_index, open_tag+marked_text+close_tag)
Beispiel #20
0
class Tkui(base.BaseUI):
    """
  This is a ui class which handles the complete Tk user interface.
  """
    def __init__(self):
        """ Initializes."""
        base.BaseUI.__init__(self)

        # internal ui queue
        self._event_queue = Queue.Queue()

        # map of session -> (bold, foreground, background)
        self._currcolors = {}

        # ses -> string
        self._unfinishedcolor = {}

        self._viewhistory = 0
        self._do_i_echo = 1

        # holds a map of window names -> window references
        self._windows = {}

        # instantiate all the widgets
        self._tk = Tk()
        self._tk.geometry("800x600")

        self.settitle()

        if os.name == 'posix':
            fnt = tkFont.Font(family="Courier", size=12)
        else:
            fnt = tkFont.Font(family="Fixedsys", size=12)

        self._entry = CommandEntry(self._tk,
                                   self,
                                   fg='white',
                                   bg='black',
                                   insertbackground='yellow',
                                   font=fnt,
                                   insertwidth='2')
        self._entry.pack(side='bottom', fill='both')

        self._topframe = Frame(self._tk)
        self._topframe.pack(side='top', fill='both', expand=1)

        self._txt = ScrolledText(self._topframe,
                                 fg='white',
                                 bg='black',
                                 font=fnt,
                                 height=20)
        self._txt.pack(side='bottom', fill='both', expand=1)

        self._txt.bind("<KeyPress>", self._ignoreThis)
        self._txtbuffer = ScrolledText(self._topframe,
                                       fg='white',
                                       bg='black',
                                       font=fnt,
                                       height=20)
        self._txtbuffer.bind("<KeyPress-Escape>", self.escape)
        self._txtbuffer.bind("<KeyPress>", self._ignoreThis)

        self._entry.focus_set()
        self._initColorTags()
        self.dequeue()

        exported.hook_register("config_change_hook", self.configChangeHandler)
        exported.hook_register("to_user_hook", self.write)

        # FIXME - fix this explanation.  this is just terrible.
        tc = config.BoolConfig(
            "saveinputhighlight", 0, 1,
            "Allows you to change the behavior of the command entry.  When "
            "saveinputhighlight is off, we discard whatever is on the entry "
            "line.  When it is on, we will retain the contents allowing you "
            "to press the enter key to do whatever you typed again.")
        exported.add_config("saveinputhighlight", tc)

        self._quit = 0

    def runui(self):
        global HELP_TEXT
        exported.add_help("tkui", HELP_TEXT)
        exported.write_message("For tk help type \"#help tkui\".")
        exported.add_command("colorcheck", colorcheck_cmd)

        # run the tk mainloop here
        self._tk.mainloop()

    def wantMainThread(self):
        # The tkui needs the main thread of execution so we return
        # a 1 here.
        return 1

    def quit(self):
        if not self._quit:
            self._quit = 1
            self._topframe.quit()

    def dequeue(self):
        qsize = self._event_queue.qsize()
        if qsize > 10:
            qsize = 10

        for i in range(qsize):
            ev = self._event_queue.get_nowait()
            ev.execute(self)

        self._tk.after(25, self.dequeue)

    def settitle(self, title=""):
        """
    Sets the title bar to the Lyntin title plus the given string.

    @param title: the title to set
    @type  title: string
    """
        if title:
            title = constants.LYNTINTITLE + title
        else:
            title = constants.LYNTINTITLE
        self._event_queue.put(_TitleEvent(self._tk, title))

    def removeWindow(self, windowname):
        """
    This removes a NamedWindow from our list of NamedWindows.

    @param windowname: the name of the window to write to
    @type  windowname: string
    """
        if self._windows.has_key(windowname):
            del self._windows[windowname]

    def writeWindow(self, windowname, message):
        """
    This writes to the window named "windowname".  If the window
    does not exist, we spin one off.  It handles ansi text and
    messages just like writing to the main window.

    @param windowname: the name of the window to write to
    @type  windowname: string

    @param message: the message to write to the window
    @type  message: string or Message instance
    """
        self._event_queue.put(_WriteWindowEvent(windowname, message))

    def writeWindow_internal(self, windowname, message):
        if not self._windows.has_key(windowname):
            self._windows[windowname] = NamedWindow(windowname, self, self._tk)
        self._windows[windowname].write(message)

    def _ignoreThis(self, tkevent):
        """ This catches keypresses from the history buffer."""
        # kludge so that ctrl-c doesn't get caught allowing windows
        # users to copy the buffer....
        if tkevent.keycode == 17 or tkevent.keycode == 67:
            return

        self._entry.focus()
        if tkevent.char:
            # we do this little song and dance so as to pass events
            # we don't want to deal with to the entry widget essentially
            # by creating a new event and tossing it in the event list.
            # it only sort of works--but it's the best code we've got
            # so far.
            args = ('event', 'generate', self._entry, "<KeyPress>")
            args = args + ('-rootx', tkevent.x_root)
            args = args + ('-rooty', tkevent.y_root)
            args = args + ('-keycode', tkevent.keycode)
            args = args + ('-keysym', tkevent.keysym)

            self._tk.tk.call(args)

        return "break"

    def pageUp(self):
        """ Handles prior (Page-Up) events."""
        if self._viewhistory == 0:
            self._txtbuffer.pack(side='top', fill='both', expand=1)

            self._viewhistory = 1
            self._txtbuffer.delete("1.0", "end")
            lotofstuff = self._txt.get('1.0', 'end')
            self._txtbuffer.insert('end', lotofstuff)
            for t in self._txt.tag_names():
                taux = None
                tst = 0
                for e in self._txt.tag_ranges(t):
                    if tst == 0:
                        taux = e
                        tst = 1
                    else:
                        tst = 0
                        self._txtbuffer.tag_add(t, str(taux), str(e))

            self._txtbuffer.yview('moveto', '1')
            if os.name != 'posix':
                self._txtbuffer.yview('scroll', '20', 'units')
            self._tk.update_idletasks()
            self._txt.yview('moveto', '1.0')
            if os.name != 'posix':
                self._txt.yview('scroll', '220', 'units')

        else:
            # yscroll up stuff
            self._txtbuffer.yview('scroll', '-15', 'units')

    def pageDown(self):
        """ Handles next (Page-Down) events."""
        if self._viewhistory == 1:
            # yscroll down stuff
            self._txtbuffer.yview('scroll', '15', 'units')

    def escape(self, tkevent):
        """ Handles escape (Escape) events."""
        if self._viewhistory == 1:
            self._txtbuffer.forget()
            self._viewhistory = 0
        else:
            self._entry.clearInput()

    def configChangeHandler(self, args):
        """ This handles config changes including mudecho. """
        name = args["name"]
        newvalue = args["newvalue"]

        if name == "mudecho":
            if newvalue == 1:
                # echo on
                self._do_i_echo = 1
                self._entry.configure(show='')
            else:
                # echo off
                self._do_i_echo = 0
                self._entry.configure(show='*')

    def _yadjust(self):
        """Handles y scrolling after text insertion."""
        self._txt.yview('moveto', '1')
        # if os.name != 'posix':
        self._txt.yview('scroll', '20', 'units')

    def _clipText(self):
        """
    Scrolls the text buffer up so that the new text written at
    the bottom of the text buffer can be seen.
    """
        temp = self._txt.index("end")
        ind = temp.find(".")
        temp = temp[:ind]
        if (temp.isdigit() and int(temp) > 800):
            self._txt.delete("1.0", "100.end")

    def write(self, args):
        """
    This writes text to the text buffer for viewing by the user.

    This is overridden from the 'base.BaseUI'.
    """
        self._event_queue.put(_OutputEvent(args))

    def write_internal(self, args):
        mess = args["message"]
        if type(mess) == types.StringType:
            mess = message.Message(mess, message.LTDATA)

        line = mess.data
        ses = mess.session

        if line == '' or self.showTextForSession(ses) == 0:
            return

        color, leftover = buffer_write(mess, self._txt, self._currcolors,
                                       self._unfinishedcolor)

        if mess.type == message.MUDDATA:
            self._unfinishedcolor[ses] = leftover
            self._currcolors[ses] = color

        self._clipText()
        self._yadjust()

    def convertColor(self, name):
        """
    Tk has this really weird color palatte.  So I switched to using
    color names in most cases and rgb values in cases where I couldn't
    find a good color name.

    This method allows me to specify either an rgb or a color name
    and it converts the color names to rgb.

    @param name: either an rgb value or a name
    @type  name: string

    @returns: the rgb color value
    @rtype: string
    """
        if name.startswith("#"):
            return name

        rgb = self._tk._getints(
            self._tk.tk.call('winfo', 'rgb', self._txt, name))
        rgb = "#%02x%02x%02x" % (rgb[0] / 256, rgb[1] / 256, rgb[2] / 256)
        print name, "converted to: ", rgb

        return rgb

    def _initColorTags(self):
        """ Sets up Tk tags for the text widget (fg/bg/u)."""
        for ck in fg_color_codes.keys():
            color = self.convertColor(fg_color_codes[ck])
            self._txt.tag_config(ck, foreground=color)
            self._txtbuffer.tag_config(ck, foreground=color)

        for ck in bg_color_codes.keys():
            self._txt.tag_config(ck, background=bg_color_codes[ck])
            self._txtbuffer.tag_config(ck, background=bg_color_codes[ck])

        self._txt.tag_config("u", underline=1)
        self._txtbuffer.tag_config("u", underline=1)

    def colorCheck(self):
        """
    Goes through and displays all the combinations of fg and bg
    with the text string involved.  Purely for debugging
    purposes.
    """
        fgkeys = ['30', '31', '32', '33', '34', '35', '36', '37']
        bgkeys = ['40', '41', '42', '43', '44', '45', '46', '47']

        self._txt.insert('end', 'color check:\n')
        for bg in bgkeys:
            for fg in fgkeys:
                self._txt.insert('end', str(fg), (fg, bg))
                self._txt.insert('end', str("b" + fg), ("b" + fg, bg))
            self._txt.insert('end', '\n')

            for fg in fgkeys:
                self._txt.insert('end', str(fg), (fg, "b" + bg))
                self._txt.insert('end', str("b" + fg), ("b" + fg, "b" + bg))
            self._txt.insert('end', '\n')

        self._txt.insert('end', '\n')
        self._txt.insert('end', '\n')
Beispiel #21
0
class NamedWindow:
    """
  This creates a window for the Tkui which you can then write to 
  programmatically.  This allows modules to spin off new named windows
  and write to them.
  """

    def __init__(self, windowname, master, partk):
        """
    Initializes the window

    @param windowname: the name of the new window
    @type  windowname: string

    @param master: the main tk window
    @type  master: toplevel
    """
        self._parent = master
        self._tk = Toplevel(partk)
        self._windowname = windowname

        # map of session -> (bold, foreground, background)
        self._currcolors = {}

        # ses -> string
        self._unfinishedcolor = {}

        self._do_i_echo = 1

        self._tk.geometry("500x300")
        self._tk.title("Lyntin -- " + self._windowname)

        self._tk.protocol("WM_DELETE_WINDOW", self.close)

        if os.name == "posix":
            fontname = "Courier"
        else:
            fontname = "Fixedsys"
        fnt = tkFont.Font(family=fontname, size=12)

        self._txt = ScrolledText(self._tk, fg="white", bg="black", font=fnt, height=20)
        self._txt.pack(side=TOP, fill=BOTH, expand=1)

        # handles improper keypresses
        self._txt.bind("<KeyPress>", self._ignoreThis)

        # initialize color tags
        self._initColorTags()

    def convertColor(self, name):
        """
    Tk has this really weird color palatte.  So I switched to using
    color names in most cases and rgb values in cases where I couldn't
    find a good color name.

    This method allows me to specify either an rgb or a color name
    and it converts the color names to rgb.

    @param name: either an rgb value or a name
    @type  name: string

    @returns: the rgb color value
    @rtype: string
    """
        if name[0] == "#":
            return name

        rgb = self._tk._getints(self._tk.tk.call("winfo", "rgb", self._txt, name))
        rgb = "#%02x%02x%02x" % (rgb[0] / 256, rgb[1] / 256, rgb[2] / 256)
        print name, "converted to: ", rgb

        return rgb

    def _initColorTags(self):
        """ Sets up Tk tags for the text widget (fg/bg)."""
        for ck in fg_color_codes.keys():
            color = self.convertColor(fg_color_codes[ck])
            self._txt.tag_config(ck, foreground=color)

        for ck in bg_color_codes.keys():
            self._txt.tag_config(ck, background=bg_color_codes[ck])

        self._txt.tag_config("u", underline=1)

    def _ignoreThis(self, tkevent):
        """
    This catches keypresses to this window.
    """
        return "break"

    def close(self):
        """
    Closes and destroys references to this window.
    """
        self._parent.removeWindow(self._windowname)
        self._tk.destroy()

    def _yadjust(self):
        """Handles y scrolling after text insertion."""
        self._txt.yview("moveto", "1")
        # if os.name != 'posix':
        self._txt.yview("scroll", "20", "units")

    def _clipText(self):
        """
    Scrolls the text buffer up so that the new text written at
    the bottom of the text buffer can be seen.
    """
        temp = self._txt.index("end")
        ind = temp.find(".")
        temp = temp[:ind]
        if temp.isdigit() and int(temp) > 800:
            self._txt.delete("1.0", "100.end")

    def write(self, msg):
        """
    This writes text to the text buffer for viewing by the user.

    This is overridden from the 'base.BaseUI'.
    """
        if type(msg) == types.TupleType:
            msg = msg[0]

        if type(msg) == types.StringType:
            msg = message.Message(msg, message.LTDATA)

        line = msg.data
        ses = msg.session

        if line == "":
            return

        color, leftover = buffer_write(msg, self._txt, self._currcolors, self._unfinishedcolor)

        if msg.type == message.MUDDATA:
            self._unfinishedcolor[ses] = leftover
            self._currcolors[ses] = color

        self._clipText()
        self._yadjust()
Beispiel #22
0
class NamedWindow:
    """
  This creates a window for the Tkui which you can then write to 
  programmatically.  This allows modules to spin off new named windows
  and write to them.
  """
    def __init__(self, windowname, master, partk):
        """
    Initializes the window

    @param windowname: the name of the new window
    @type  windowname: string

    @param master: the main tk window
    @type  master: toplevel
    """
        self._parent = master
        self._tk = Toplevel(partk)
        self._windowname = windowname

        # map of session -> (bold, foreground, background)
        self._currcolors = {}

        # ses -> string
        self._unfinishedcolor = {}

        self._do_i_echo = 1

        self._tk.geometry("500x300")
        self._tk.title("Lyntin -- " + self._windowname)

        self._tk.protocol("WM_DELETE_WINDOW", self.close)

        if os.name == "posix":
            fontname = "Courier"
        else:
            fontname = "Fixedsys"
        fnt = tkFont.Font(family=fontname, size=12)

        self._txt = ScrolledText(self._tk,
                                 fg="white",
                                 bg="black",
                                 font=fnt,
                                 height=20)
        self._txt.pack(side=TOP, fill=BOTH, expand=1)

        # handles improper keypresses
        self._txt.bind("<KeyPress>", self._ignoreThis)

        # initialize color tags
        self._initColorTags()

    def convertColor(self, name):
        """
    Tk has this really weird color palatte.  So I switched to using
    color names in most cases and rgb values in cases where I couldn't
    find a good color name.

    This method allows me to specify either an rgb or a color name
    and it converts the color names to rgb.

    @param name: either an rgb value or a name
    @type  name: string

    @returns: the rgb color value
    @rtype: string
    """
        if name[0] == "#":
            return name

        rgb = self._tk._getints(
            self._tk.tk.call('winfo', 'rgb', self._txt, name))
        rgb = "#%02x%02x%02x" % (rgb[0] / 256, rgb[1] / 256, rgb[2] / 256)
        print name, "converted to: ", rgb

        return rgb

    def _initColorTags(self):
        """ Sets up Tk tags for the text widget (fg/bg)."""
        for ck in fg_color_codes.keys():
            color = self.convertColor(fg_color_codes[ck])
            self._txt.tag_config(ck, foreground=color)

        for ck in bg_color_codes.keys():
            self._txt.tag_config(ck, background=bg_color_codes[ck])

        self._txt.tag_config("u", underline=1)

    def _ignoreThis(self, tkevent):
        """
    This catches keypresses to this window.
    """
        return "break"

    def close(self):
        """
    Closes and destroys references to this window.
    """
        self._parent.removeWindow(self._windowname)
        self._tk.destroy()

    def _yadjust(self):
        """Handles y scrolling after text insertion."""
        self._txt.yview('moveto', '1')
        # if os.name != 'posix':
        self._txt.yview('scroll', '20', 'units')

    def _clipText(self):
        """
    Scrolls the text buffer up so that the new text written at
    the bottom of the text buffer can be seen.
    """
        temp = self._txt.index("end")
        ind = temp.find(".")
        temp = temp[:ind]
        if (temp.isdigit() and int(temp) > 800):
            self._txt.delete("1.0", "100.end")

    def write(self, msg):
        """
    This writes text to the text buffer for viewing by the user.

    This is overridden from the 'base.BaseUI'.
    """
        if type(msg) == types.TupleType:
            msg = msg[0]

        if type(msg) == types.StringType:
            msg = message.Message(msg, message.LTDATA)

        line = msg.data
        ses = msg.session

        if line == '':
            return

        color, leftover = buffer_write(msg, self._txt, self._currcolors,
                                       self._unfinishedcolor)

        if msg.type == message.MUDDATA:
            self._unfinishedcolor[ses] = leftover
            self._currcolors[ses] = color

        self._clipText()
        self._yadjust()
Beispiel #23
0
class myPanel(tkinter.Tk):
    def __init__(self):
        tkinter.Tk.__init__(self, 'lsx')

        try:
            self.ss = self.clipboard_get()
        except:
            self.ss = ''
        self.cnt = 0
        self.slices = paragraph(self.ss, qrlen)
        self.string = None

        if not os.path.exists('config.ini'):
            x = - 100 + 0.2 * self.winfo_screenwidth() # 100: 补偿初始Tk界面为200x200
            y = - 100 + 0.7 * self.winfo_screenheight()
            xy = '+%d+%d'%(x,y)
            with open('config.ini','w') as f:
                f.write(xy)
        with open('config.ini','r') as f:
            xy = f.read()
        self.geometry(xy)
        self.minsize(450,206)

        self.qrc = tkinter.Label(self)
        self.ent = ScrolledText(self, width=1, height=15)
        self.ent.insert(1.0, self.ss)
        self.ent.mark_set('insert','0.0') # 程序首次运行时不使用see函数,否则会有未知原因半行内容沉没在Text窗体上面一点点
        self.ent.focus()

        text = self.slices[self.cnt]
        basic = (len(self.slices),len(self.ss))
        info = 'Page: %s, Length: %s'%basic
        if zh_cn:
            info = '共%s页, %s字'%basic

        self.withdraw() # withdraw/deiconify 阻止页面闪烁
        self.update_idletasks()
        self.ent.pack(padx=2, pady=2, fill='both', expand=True, side='right') # RIGHT为了在Label隐藏再显示后所在位置一致
        self.qrc.pack()
        self.setQrcode(text, info)
        self.deiconify()

        self.qrc.bind('<Button-2>',self.onExit)
        self.qrc.bind('<Button-1>',self.fliping)
        self.qrc.bind('<Button-3>',self.fliping)
        self.qrc.bind('<Double-Button-1>',self.setting)
        self.qrc.bind('<Double-ButtonRelease-3>',self.openFile) # 没有Release会在窗口打开之后的鼠标抬起时唤起右键菜单

        self.ent.bind('<Escape>',self.onExit)
        self.ent.bind('<F1>',self.openFile)
        self.ent.bind('<F2>',self.fliping)
        self.ent.bind('<F3>',self.fliping)
        self.ent.bind('<F4>',self.setting)

        self.ent.bind('<KeyRelease>',self.refresh)
        self.ent.bind('<ButtonRelease-1>',self.selected)
        self.bind('<Destroy>',lambda evt:self.onExit(evt,close=True))

    def setQrcode(self, string, info):
        if self.string != string:
            self.string = string
            if string == '':
                self.qrc.forget()
            else:
                global img
                img = qrmake(string)
                self.qrc.config(image=img)
                self.qrc.pack()
        log(string, info)
        self.title('Text Helper v1.06 (%s)'%info)
        if zh_cn:
            self.title('文本助手v1.06 (%s)'%info)

    def refresh(self, evt):
        if evt.keysym in ['Control_L', 'Return', 'BackSpace']:
            ss2 = self.ent.get('0.0', 'end')[:-1]
            if self.ss != ss2:
                self.ss = ss2
                self.cnt = 0
                self.slices = paragraph(self.ss, qrlen)

            text = self.slices[self.cnt]
            basic = (len(self.slices),len(self.ss))
            info = 'Page: %s, Length: %s'%basic
            if zh_cn:
                info = '共%s页, %s字'%basic
            self.setQrcode(text, info)

    def fliping(self, evt):
        if evt.num == 1 or evt.keysym == 'F3':
            self.cnt = min(self.cnt+1,len(self.slices)-1)
        else:
            self.cnt = max(self.cnt-1,0)
        cur1 = getIndex(''.join(self.slices[:self.cnt]))
        cur2 = getIndex(''.join(self.slices[:self.cnt+1]))
        self.setCursor(cur1, cur2)

        text = self.slices[self.cnt]
        basic = (self.cnt+1,len(self.slices),len(text),len(self.ss))
        info = 'Page: %s/%s, Sel: %s/%s'%basic
        if zh_cn:
            info = '第%s/%s页, 共%s/%s字'%basic
        self.setQrcode(text, info)

    def selected(self, evt):
        if self.ent.tag_ranges('sel'):
            text = self.ent.selection_get()
            info = 'Sel: %s/%s'%(len(text),len(self.ss))
            if zh_cn:
                info = '选中%s/%s字'%(len(text),len(self.ss))
            self.setQrcode(text, info)

    def setCursor(self, cur1, cur2):
        self.ent.mark_set('insert', cur1)
        self.ent.tag_remove('sel','0.0','end')
        self.ent.tag_add('sel',cur1,cur2)
        self.ent.see(cur1)

    def setting(self, evt):
        max_page = len(self.slices)
        num = tkinter.simpledialog.askinteger('Goto','Go to page (1-%s):'%max_page, initialvalue=self.cnt+1)
        self.ent.focus()
        if num:
            self.cnt = max(1,min(max_page,num)) - 1

            text = self.slices[self.cnt]
            basic = (self.cnt+1,len(self.slices),len(text),len(self.ss))
            info = 'Page: %s/%s, Sel: %s/%s'%basic
            if zh_cn:
                info = '第%s/%s页, 共%s/%s字'%basic
            self.setQrcode(text, info)

    def openFile(self, evt):
        path = tkinter.filedialog.askopenfilename()
        if path != '':
            filename = os.path.basename(path)
            with open(path,'rb') as f:
                s = f.read()
            try:
                try:
                    res = s.decode()
                except:
                    try:
                        res = s.decode('gbk')
                    except:
                        raise
            except:
                s = base64.urlsafe_b64encode(filename.encode()+b'\n'+s).decode()
                total = int((len(s)-1)/(qrlen-10)+1)
                res = ''
                for i in range(total):
                    res += '%04d%04d.%s,'%(total, i+1, s[(qrlen-10)*i:(qrlen-10)*(i+1)])

            self.ss = res
            self.cnt = 0
            self.slices = paragraph(self.ss, qrlen)
            self.ent.delete(1.0, 'end')
            self.ent.insert(1.0, res)

            text = self.slices[self.cnt]
            basic = (len(self.slices),len(self.ss))
            info = 'Page: %s, Length: %s'%basic
            if zh_cn:
                info = '共%s页, %s字'%basic
            self.setQrcode(text, info)

    def onExit(self, evt, close=False):
        xy = '+%d+%d'%(self.winfo_x(),self.winfo_y())
        with open('config.ini','w') as f:
            f.write(xy)
        if not close:
            self.destroy()
Beispiel #24
0
import thread, Queue as queue, time
dataQueue = queue.Queue()    # infinite size

def producer(id):
  for i in range(5):
    time.sleep(0.1)
    print('put')
    dataQueue.put('[producer id=%d, count=%d]' % (id, i))

def consumer(root):
  while not dataQueue.empty():
    data = dataQueue.get(block=False)
    root.insert('end', 'consumer got => %s\n' % str(data))
    root.see('end')
  root.after(250, lambda: consumer(root))    # 4 times per sec

def makethreads():
  for i in range(4):
    thread.start_new_thread(producer, (i,))

       
if __name__ == '__main__':
  # main GUI thread: spawn batch of worker threads on each mouse click
  from ScrolledText import ScrolledText
  root = ScrolledText()
  root.pack()
  root.bind('<Button-1>', lambda event: makethreads())
  consumer(root)                       # start queue check loop in main thread
  root.mainloop()                      # pop-up window, enter tk event loop