Example #1
0
class ScrolledList(object):
    # TODO add columns to the Scrolled list:
    #   http://stackoverflow.com/questions/5286093/display-listbox-with-columns-using-tkinter

    def __init__(self, parent_frame):
        self._vsbar = Scrollbar(parent_frame)
        self._hsbar = Scrollbar(parent_frame, orient='horizontal')
        self._list = Listbox(parent_frame, relief=SUNKEN, font=('courier', 12))

        self._vsbar.config(command=self._list.yview, relief=SUNKEN)
        self._hsbar.config(command=self._list.xview, relief=SUNKEN)
        self._list.config(yscrollcommand=self._vsbar.set, relief=SUNKEN)
        self._list.config(xscrollcommand=self._hsbar.set)

        self._vsbar.pack(side=RIGHT, fill=Y)
        self._hsbar.pack(side=BOTTOM, fill=X)
        self._list.pack(side=LEFT, expand=YES, fill=BOTH)
        #self._list.bind('<Double-1>', self.handlelist)

        self._list_pos = 0

    def clear(self):
        self._list.delete(0, END)
        self._list_pos = 0

    def append_list_entry(self, entry_str, fg=None):
        pos = self._list_pos
        self._list_pos += 1
        self._list.insert(END, entry_str)
        if fg:
            self._list.itemconfig(pos, fg=fg)
        return pos

    def highlight_entry(self, entry_index, bg):
        self._list.itemconfig(index=entry_index, bg=bg)
Example #2
0
class OSCRemote(object):
    def __init__(self):

        self.editor_issue = "1.3"

        # get command options
        self.command_options = remote_options()

        # get directory holding the code
        self.pp_dir = sys.path[0]

        if not os.path.exists(self.pp_dir + os.sep + "pp_oscremote.py"):
            tkMessageBox.showwarning("Pi Presents",
                                     "Bad Application Directory")
            exit()

        # Initialise logging
        Monitor.log_path = self.pp_dir
        self.mon = Monitor()
        self.mon.init()

        Monitor.classes = ['OSCRemote', 'OSCConfig', 'OSCEditor']

        Monitor.log_level = int(self.command_options['debug'])

        self.mon.log(self, "Pi Presents Remote is starting")
        self.mon.log(self, " OS and separator " + os.name + '  ' + os.sep)
        self.mon.log(self,
                     "sys.path[0] -  location of code: code " + sys.path[0])

        self.setup_gui()

        # OSC config class
        self.osc_config = OSCConfig()

        self.init()

        #and start the system
        self.root.after(1000, self.run_app)
        self.root.mainloop()

    def init(self):
        self.osc_config_file = self.pp_dir + os.sep + 'pp_config' + os.sep + 'pp_oscremote.cfg'
        self.read_create_osc()
        self.pp_home_dir = self.osc_config.pp_home_dir
        self.pp_profiles_offset = self.osc_config.pp_profiles_offset
        self.mon.log(self, "Data Home from options is " + self.pp_home_dir)
        self.mon.log(
            self, "Current Profiles Offset from options is " +
            self.pp_profiles_offset)
        self.pp_profile_dir = ''

        self.current_showlist = None
        self.current_show = None
        self.current_show_ref = ''
        self.shows_display.delete(0, END)
        self.results.set('')

    def add_status(self, text):
        self.status_display.insert(END, text + '\n')
        self.status_display.see(END)

    def run_app(self):
        self.client = None
        self.server = None
        self.st = None

        # initialise OSC variables
        self.prefix = '/pipresents'
        self.this_unit = '/' + self.osc_config.this_unit_name
        self.add_status('this unit is: ' + self.this_unit)
        self.controlled_unit = '/' + self.osc_config.controlled_unit_1_name
        self.add_status('controlled unit is: ' + self.controlled_unit)

        #connect client then start server to listen for replies
        self.init_client()
        self.add_status('connecting to controlled unit: ' +
                        self.osc_config.controlled_unit_1_ip + ':' +
                        self.osc_config.controlled_unit_1_port + ' ' +
                        self.osc_config.controlled_unit_1_name)
        self.connect_client(self.osc_config.controlled_unit_1_ip,
                            self.osc_config.controlled_unit_1_port)
        self.add_status('listening for replies on:' +
                        self.osc_config.this_unit_ip + ':' +
                        self.osc_config.this_unit_port)
        self.init_server(self.osc_config.this_unit_ip,
                         self.osc_config.this_unit_port, self.client)
        self.add_initial_handlers()
        self.start_server()

# ***************************************
#  RESPOND TO BUTTONS
# ***************************************

    def open_show(self):
        self.msg_path = '/core/open '
        self.msg_arg_text = self.current_show_ref
        self.display_msg_text()

    def close_show(self):
        self.msg_path = '/core/close '
        self.msg_arg_text = self.current_show_ref
        self.display_msg_text()

    def exit_pipresents(self):
        self.msg_path = '/core/exitpipresents'
        self.msg_arg_text = ''
        self.display_msg_text()

    def play_event(self):
        self.msg_path = '/core/event'
        self.msg_arg_text = 'pp-play'
        self.display_msg_text()

    def pause_event(self):
        self.msg_path = '/core/event'
        self.msg_arg_text = 'pp-pause'
        self.display_msg_text()
        pass

    def stop_event(self):
        self.msg_path = '/core/event'
        self.msg_arg_text = 'pp-stop'
        self.display_msg_text()
        pass

    def up_event(self):
        self.msg_path = '/core/event'
        self.msg_arg_text = 'pp-up'
        self.display_msg_text()

    def down_event(self):
        self.msg_path = '/core/event'
        self.msg_arg_text = 'pp-down'
        self.display_msg_text()

    def output(self):
        self.msg_path = '/core/output'
        self.msg_arg_text = ''
        self.display_msg_text()

    def loopback(self):
        self.msg_path = '/system/loopback'
        self.msg_arg_text = ''
        self.display_msg_text()

    def server_info(self):
        self.msg_path = '/system/server-info'
        self.msg_arg_text = ''
        self.display_msg_text()

    # and put the created text in the results box in the gui
    def display_msg_text(self):
        self.results.set(self.prefix + self.controlled_unit + self.msg_path +
                         ' ' + self.msg_arg_text)

    #calback from the Send button
    # parses the message string into fields and sends - NO error checking
    def send_message(self):
        msg_text = self.results.get()
        self.add_status('Send message:' + msg_text)
        self.mon.log(self, 'send message: ' + msg_text)
        fields = msg_text.split()
        address = fields[0]
        arg_list = fields[1:]
        self.send(address, arg_list)

    # ***************************************
    # OSC CLIENT TO SEND MESSAGES
    # ***************************************

    def init_client(self):
        self.client = OSC.OSCClient()

    def connect_client(self, ip, port):
        self.mon.log(self, 'connect to: ' + ip + ':' + str(port))
        self.client.connect((ip, int(port)))

    def send(self, address, arg_list):
        msg = OSC.OSCMessage()
        msg.setAddress(address)
        for arg in arg_list:
            msg.append(arg)
        self.client.send(msg)

    def disconnect_client(self):
        self.client.close()
        return

    # ***************************************
    # OSC SERVER TO LISTEN TO REPLIES
    # ***************************************

    def init_server(self, ip, port_text, client):
        self.mon.log(self, 'Start Server: ' + ip + ':' + port_text)
        self.server = OSC.OSCServer((ip, int(port_text)), client)

    def start_server(self):
        self.st = threading.Thread(target=self.server.serve_forever)
        self.st.start()

    def close_server(self):
        if self.server != None:
            self.server.close()
        self.mon.log(self, 'Waiting for Server-thread to finish')
        if self.st != None:
            self.st.join()  ##!!!
        self.mon.log(self, 'server thread closed')

    def add_initial_handlers(self):
        self.server.addMsgHandler('default', self.no_match_handler)
        self.server.addMsgHandler(
            self.prefix + self.this_unit + "/system/loopback-reply",
            self.loopback_reply_handler)
        self.server.addMsgHandler(
            self.prefix + self.this_unit + "/system/server-info-reply",
            self.server_info_reply_handler)

    def no_match_handler(self, addr, tags, stuff, source):
        text = ''
        text += "no match for new osc msg from %s" % OSC.getUrlStr(
            source) + '\n'
        text += "with addr : %s" % addr + '\n'
        text += "typetags %s" % tags + '\n'
        text += "data %s" % stuff + '\n'
        self.add_status(text + '\n')

    def loopback_reply_handler(self, addr, tags, stuff, source):
        self.add_status('Loopback reply  received from: ' +
                        self.pretty_list(source))

    def server_info_reply_handler(self, addr, tags, stuff, source):
        self.add_status('Server Information from: ' +
                        self.pretty_list(source) + '\n   ' +
                        self.pretty_list(stuff))

    def pretty_list(self, fields):
        text = ' '
        for field in fields:
            text += str(field) + ' '
        return text

    # ***************************************
    # INIT EXIT MISC
    # ***************************************

    def e_edit_osc(self):
        self.disconnect_client()
        self.close_server()
        self.edit_osc()
        self.init()
        self.add_status('\n\n\nRESTART')
        self.run_app()

    def app_exit(self):
        self.disconnect_client()
        self.close_server()
        if self.root is not None:
            self.root.destroy()
        self.mon.finish()
        sys.exit()

    def show_help(self):
        tkMessageBox.showinfo("Help", "Read 'manual.pdf'")

    def about(self):
        tkMessageBox.showinfo(
            "About", "Simple Remote Control for Pi Presents\n" +
            "Author: Ken Thompson" +
            "\nWebsite: http://pipresents.wordpress.com/")

    def setup_gui(self):
        # set up the gui

        # root is the Tkinter root widget
        self.root = Tk()
        self.root.title("Remote Control for Pi Presents")

        # self.root.configure(background='grey')

        self.root.resizable(False, False)

        # define response to main window closing
        self.root.protocol("WM_DELETE_WINDOW", self.app_exit)

        # bind some display fields
        self.filename = StringVar()
        self.display_show = StringVar()
        self.results = StringVar()
        self.status = StringVar()

        # define menu
        menubar = Menu(self.root)

        profilemenu = Menu(menubar, tearoff=0, bg="grey", fg="black")
        profilemenu.add_command(label='Select',
                                command=self.open_existing_profile)
        menubar.add_cascade(label='Profile', menu=profilemenu)

        toolsmenu = Menu(menubar, tearoff=0, bg="grey", fg="black")
        menubar.add_cascade(label='Tools', menu=toolsmenu)

        osc_configmenu = Menu(menubar, tearoff=0, bg="grey", fg="black")
        menubar.add_cascade(label='OSC', menu=osc_configmenu)
        osc_configmenu.add_command(label='Edit', command=self.e_edit_osc)

        helpmenu = Menu(menubar, tearoff=0, bg="grey", fg="black")
        menubar.add_cascade(label='Help', menu=helpmenu)
        helpmenu.add_command(label='Help', command=self.show_help)
        helpmenu.add_command(label='About', command=self.about)

        self.root.config(menu=menubar)

        #top frame
        top_frame = Frame(self.root, padx=5, pady=5)
        top_frame.pack(side=TOP)

        results_label = Label(top_frame,
                              text="Message to Send",
                              font="arial 12 bold")
        results_label.pack(side=LEFT)
        results_display = Entry(top_frame, textvariable=self.results, width=70)
        results_display.pack(side=LEFT, fill=BOTH, expand=1)
        send_button = Button(top_frame,
                             width=5,
                             height=1,
                             text='Send',
                             fg='black',
                             command=self.send_message,
                             bg="light grey")
        send_button.pack(side=RIGHT)

        #bottom frame
        bottom_frame = Frame(self.root, padx=5, pady=5)
        bottom_frame.pack(side=TOP, fill=BOTH, expand=1)
        left_frame = Frame(bottom_frame, padx=5)
        left_frame.pack(side=LEFT)
        right_frame = Frame(bottom_frame, padx=5, pady=5)
        right_frame.pack(side=LEFT)

        suplabel_frame = Frame(right_frame, pady=5)
        suplabel_frame.pack(side=TOP)
        commands_label = Label(suplabel_frame,
                               text="Show Control",
                               font="arial 12 bold")
        commands_label.pack()

        supervisor_frame = Frame(right_frame, pady=5)
        supervisor_frame.pack(side=TOP)

        # supervisor buttons
        add_button = Button(supervisor_frame,
                            width=5,
                            height=1,
                            text='Open\nShow',
                            fg='black',
                            command=self.open_show,
                            bg="light grey")
        add_button.pack(side=LEFT)
        add_button = Button(supervisor_frame,
                            width=5,
                            height=1,
                            text='Close\nShow',
                            fg='black',
                            command=self.close_show,
                            bg="light grey")
        add_button.pack(side=LEFT)
        add_button = Button(supervisor_frame,
                            width=10,
                            height=1,
                            text='Exit\nPi Presents',
                            fg='black',
                            command=self.exit_pipresents,
                            bg="light grey")
        add_button.pack(side=LEFT)

        # events buttons
        oplabel_frame = Frame(right_frame, pady=5)
        oplabel_frame.pack(side=TOP)
        operations_label = Label(oplabel_frame,
                                 text="Input Events",
                                 font="arial 12 bold")
        operations_label.pack()

        operations_frame = Frame(right_frame, pady=5)
        operations_frame.pack(side=TOP)

        add_button = Button(operations_frame,
                            width=5,
                            height=1,
                            text='Play',
                            fg='black',
                            command=self.play_event,
                            bg="light grey")
        add_button.pack(side=LEFT)
        add_button = Button(operations_frame,
                            width=5,
                            height=1,
                            text='Pause',
                            fg='black',
                            command=self.pause_event,
                            bg="light grey")
        add_button.pack(side=LEFT)
        add_button = Button(operations_frame,
                            width=5,
                            height=1,
                            text='Stop',
                            fg='black',
                            command=self.stop_event,
                            bg="light grey")
        add_button.pack(side=LEFT)
        add_button = Button(operations_frame,
                            width=5,
                            height=1,
                            text='Up',
                            fg='black',
                            command=self.up_event,
                            bg="light grey")
        add_button.pack(side=LEFT)
        add_button = Button(operations_frame,
                            width=5,
                            height=1,
                            text='Down',
                            fg='black',
                            command=self.down_event,
                            bg="light grey")
        add_button.pack(side=LEFT)

        # animate buttons
        animate_frame = Frame(right_frame, pady=5)
        animate_frame.pack(side=TOP)
        animate_label = Label(animate_frame,
                              text="Control Outputs",
                              font="arial 12 bold")
        animate_label.pack()

        animate_frame = Frame(right_frame, pady=5)
        animate_frame.pack(side=TOP)

        add_button = Button(animate_frame,
                            width=5,
                            height=1,
                            text='Output',
                            fg='black',
                            command=self.output,
                            bg="light grey")
        add_button.pack(side=LEFT)

        # system buttons
        systemlabel_frame = Frame(right_frame, pady=5)
        systemlabel_frame.pack(side=TOP)
        system_label = Label(systemlabel_frame,
                             text="System",
                             font="arial 12 bold")
        system_label.pack()

        system_frame = Frame(right_frame, pady=5)
        system_frame.pack(side=TOP)

        add_button = Button(system_frame,
                            width=5,
                            height=1,
                            text='Loopback',
                            fg='black',
                            command=self.loopback,
                            bg="light grey")
        add_button.pack(side=LEFT)
        add_button = Button(system_frame,
                            width=10,
                            height=1,
                            text='Server Info',
                            fg='black',
                            command=self.server_info,
                            bg="light grey")
        add_button.pack(side=LEFT)

        # define display of showlist
        shows_title_frame = Frame(left_frame)
        shows_title_frame.pack(side=TOP)
        shows_label = Label(shows_title_frame, text="Shows")
        shows_label.pack()
        shows_frame = Frame(left_frame)
        shows_frame.pack(side=TOP)
        scrollbar = Scrollbar(shows_frame, orient=VERTICAL)
        self.shows_display = Listbox(shows_frame,
                                     selectmode=SINGLE,
                                     height=12,
                                     width=40,
                                     bg="white",
                                     activestyle=NONE,
                                     fg="black",
                                     yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.shows_display.yview)
        scrollbar.pack(side=RIGHT, fill=Y)
        self.shows_display.pack(side=LEFT, fill=BOTH, expand=1)
        self.shows_display.bind("<ButtonRelease-1>", self.e_select_show)

        # status_frame
        status_frame = Frame(self.root, padx=5, pady=5)
        status_frame.pack(side=TOP, fill=BOTH, expand=1)
        status_label = Label(status_frame, text="Status", font="arial 12 bold")
        status_label.pack(side=LEFT)
        scrollbar = Scrollbar(status_frame, orient=VERTICAL)
        self.status_display = Text(status_frame,
                                   height=10,
                                   yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.status_display.yview)
        scrollbar.pack(side=RIGHT, fill=Y)
        self.status_display.pack(side=LEFT, fill=BOTH, expand=1)

    # ***************************************
    # SHOWLIST
    # ***************************************

    def open_existing_profile(self):
        initial_dir = self.pp_home_dir + os.sep + "pp_profiles" + self.pp_profiles_offset
        if os.path.exists(initial_dir) is False:
            self.mon.err(
                self, "Profiles directory not found: " + initial_dir +
                "\n\nHint: Data Home option must end in pp_home")
            return
        dir_path = tkFileDialog.askdirectory(initialdir=initial_dir)
        # dir_path="C:\Users\Ken\pp_home\pp_profiles\\ttt"
        if len(dir_path) > 0:
            self.open_profile(dir_path)

    def open_profile(self, dir_path):
        showlist_file = dir_path + os.sep + "pp_showlist.json"
        if os.path.exists(showlist_file) is False:
            self.mon.err(
                self, "Not a Profile: " + dir_path +
                "\n\nHint: Have you opened the profile directory?")
            return
        self.pp_profile_dir = dir_path
        self.root.title("Remote for Pi Presents - " + self.pp_profile_dir)
        self.open_showlist(self.pp_profile_dir)

    def open_showlist(self, profile_dir):
        showlist_file = profile_dir + os.sep + "pp_showlist.json"
        if os.path.exists(showlist_file) is False:
            self.mon.err(
                self, "showlist file not found at " + profile_dir +
                "\n\nHint: Have you opened the profile directory?")
            self.app_exit()
        self.current_showlist = ShowList()
        self.current_showlist.open_json(showlist_file)
        if float(self.current_showlist.sissue()) != float(self.editor_issue):
            self.mon.err(
                self, "Version of profile does not match Remote: " +
                self.editor_issue)
            self.app_exit()
        self.refresh_shows_display()

    def refresh_shows_display(self):
        self.shows_display.delete(0, self.shows_display.size())
        for index in range(self.current_showlist.length()):
            self.shows_display.insert(
                END,
                self.current_showlist.show(index)['title'] + "   [" +
                self.current_showlist.show(index)['show-ref'] + "]")
        if self.current_showlist.show_is_selected():
            self.shows_display.itemconfig(
                self.current_showlist.selected_show_index(), fg='red')
            self.shows_display.see(self.current_showlist.selected_show_index())

    def e_select_show(self, event):
        print 'select show', self.current_showlist.length()
        if self.current_showlist is not None and self.current_showlist.length(
        ) > 0:
            mouse_item_index = int(event.widget.curselection()[0])
            self.current_showlist.select(mouse_item_index)
            self.current_show_ref = self.current_showlist.selected_show(
            )['show-ref']
            self.refresh_shows_display()
        else:
            self.current_show_ref = ''


# ***************************************
#  OSC CONFIGURATION
# ***************************************

    def read_create_osc(self):
        if self.osc_config.read(self.osc_config_file) is False:
            self.osc_config.create(self.osc_config_file)
            eosc = OSCEditor(self.root, self.osc_config_file, 'remote',
                             'Create OSC Remote Configuration')
            self.osc_config.read(self.osc_config_file)

    def edit_osc(self):
        if self.osc_config.read(self.osc_config_file) is False:
            self.osc_config.create(self.osc_config_file)
        eosc = OSCEditor(self.root, self.osc_config_file, 'remote',
                         'Edit OSC Reomote Configuration')
Example #3
0
class JobList(Frame):
    # NOTE: job_params contains information about a Job in the Joblist
    # NOTE: plot_args contains information about plotting information, which occurs after the jobs have been and the data files have been created

    def __init__(self, parent=None, **kwargs):
        Frame.__init__(self, parent)
        self.parent = parent
        self.job_list_yscroll = Scrollbar(self, orient=Tkinter.VERTICAL)
        self.job_list_xscroll = Scrollbar(self, orient=Tkinter.HORIZONTAL)
        self.job_list = Listbox(self, xscrollcommand=self.job_list_xscroll, yscrollcommand=self.job_list_yscroll)
        self.job_list_xscroll['command'] = self.job_list.xview
        self.job_list_yscroll['command'] = self.job_list.yview
        self.new_job_frame = Frame(self)
        add_icon_filename = kwargs['add_icon_filename'] if 'add_icon_filename' in kwargs else None
        if add_icon_filename == None:
            self.add_job_button = Button(self.new_job_frame, text='Add Job', command=self.on_add)
        else:
            add_icon = PhotoImage(file=add_icon_filename)
            self.add_job_button = Button(self.new_job_frame, text='Add Job', compound='bottom', image=add_icon, command=self.on_add)
        self.remove_job_button = Button(self.new_job_frame, text='Remove Job', command=self.on_remove)
        self.progress_frame = Frame(self)
        self.progress_value = Tkinter.IntVar()
        self.progress_bar = Progressbar(self.progress_frame, variable=self.progress_value)
        self.button_frame = Frame(self)
        self.process_button = ProcessButton(parent=self.button_frame, start_jobs=self.start_jobs)
        self.quit_button = QuitButton(parent=self.button_frame, close_other_windows=self.close_top_level_windows)

        self.run_job = kwargs['run_job'] if 'run_job' in kwargs else None

        self.create_plots = kwargs['create_plots'] if 'create_plots' in kwargs else None

        self.log_filename = kwargs['log_filename'] if 'log_filename' in kwargs else None

        self.bind('<<AskToClearJobs>>', self.ask_to_clear_jobs)
        self.bind('<<AskToPlotGraphs>>', self.ask_to_plot_graphs)
        self.bind('<<CreatePlotGUI>>', self.create_plot_gui)
        self.parent.bind('<ButtonPress>', self.on_press)
        self.parent.bind('<Configure>', self.on_resize)

        self.reinit_variables()

        self.top_level_windows = list()

        # NOTE: Because there seems to be an issue resizing child widgets when the top level (Tk) widget is being resized,
        # the resize option will be disabled for this window
        self.parent.resizable(width=False, height=False)

        self.lift()

    def reinit_variables(self):
        self.job_params = dict()

        self.last_job_id = -1

        self.job_outcomes = list()

        self.plot_args = list()

        self.on_button = False

    def add_job_params(self, input_args):
        self.job_params = input_args
        # Add each element to the job list
        for job in self.job_params:
            self.add_job(job)

    def add_job(self, job):
        try:
            index_end = job['input_directory'].rindex('/')
            index_start = job['input_directory'].rindex('/', 0, index_end)
            input_directory_text = job['input_directory']
            list_text = 'Job ' + str(job['job_id']) + ' \'' + input_directory_text + '\''
            if job['start'] != None:
                list_text += ' ' + str(job['start'])
                if job['end'] != None:
                    list_text += ' to'
            if job['end'] != None:
                list_text += ' ' + str(job['end'])

            if job['job_id'] > self.last_job_id:
                self.last_job_id = job['job_id']

            self.job_list.insert(Tkinter.END, list_text)

            # Add the list text to the job params as an optional parameter to read later to display in a future Graph GUI (or for any other useful purpose)
            job['list_text'] = list_text

            # The line number is used wrt the GUI to indicate which job in the job list is being currently executed.
            job['line_number'] = self.job_list.size() - 1
            #print str(job['line_number'])

            self.job_params[job['job_id']] = job
        except KeyError as ke:
            # Should show some error message indicating that there is a problem.
            pass

        #print str(self.job_params)
        #print 'Added Job ' + str(job['job_id'])

    def ask_to_clear_jobs(self, event):
        for job in self.job_params.itervalues():
            line_number = job['line_number']
            self.job_list.itemconfig(line_number, foreground='black')

        # Update parent to refresh widget appearance
        self.parent.update()

        # Reactivate process button
        self.process_button.config(state = Tkinter.NORMAL)

        # Note: Display a pop-up that tells the user that the job is done and asks if the job list should be cleared.

        clearList = msg.askyesno(title='Jobs Finished', message='All jobs have been completed.  Would you like to clear the job list?', master=self)
        if clearList:
            self.clear_list()

    def ask_to_plot_graphs(self, event):
        # TODO: Add a dialog that also asks to create a graph of the 'Other Type Of Plot'
        plotGraphs = msg.askyesno(title='Plot Graphs', message='Create plots of data?', master=self)

        if not plotGraphs:
            return

        # TODO: Iterate through the jobs to display to the user an interface that asks if they want to graphs of the outputs
        if self.create_plots != None:
            output_files_list = list()
            for job_outcome in self.job_outcomes:
                for output_outcomes in job_outcome[2]:
                    (station, output_directory, output_files) = output_outcomes
                    for output_files_tuple in output_files:
                        for output_file_tuple in output_files_tuple:
                            (output_file, output_file_success) = output_file_tuple
                            if output_file_success:
                                # If there is a list text variable (the 4th (or 3rd by 0 based index) variable), then add it to our output list
                                if len(job_outcome) == 4:
                                    output_files_list.append([output_file, job_outcome[3]])
                                else:
                                    output_files_list.append([output_file])

            plots_thread = PlotsThread(self.create_plots, output_files_list, self)
            plots_thread.start()

    def add_plot(self, args=dict()):
        self.plot_args.append(args)

    def finished_adding_plots(self):
        self.event_generate('<<CreatePlotGUI>>', when='tail')

    def create_plot_gui(self, event):
        # TODO: This should be replaced with a new window that allows the user to drag and drop the icons from one frame to another
        graph_names = list()
        for args in self.plot_args:
            graph_name = args['output_file']
            graph_names.append(graph_name)
        dnd_graphs_frame = Dnd.createFrame(self, 'Drag and Drop Output Plots', graph_names, self.finish_creating_plot_gui)

    # This is the entry point for the
    def finish_creating_plot_gui(self, plot_labels):
        graph_count = 1
        for plot_label in plot_labels:
            for args in self.plot_args:
                #print 'Looking in ' + args['plot_title'] + ' for ' + plot_label
                #print 'The plot label is: ' + plot_label
                #print 'The output file is: ' + args['output_file']
                if plot_label == args['output_file']:
                    #print 'Creating graph ' + str(graph_count)
                    graph_count += 1
                    graph_window = ModelRunnerGraphGUI.GraphWindow(parent=self, title=args['window_title'], df=args['df'], plot=args['plot'], plot_title=args['plot_title'], y_label=args['y_label'], log_filename=self.log_filename)
                    graph_window.set_grid()
                    self.top_level_windows.append(graph_window)
        #print 'Creating plot GUI

        # Have to clear out list here instead of clear_list because clear_list() removes plot_args before this method has a chance to read
        # them and create the appropriate plot graph windows
        self.reinit_variables()

    # Clear all the elements in the list
    def clear_list(self):

        # Save plot args because they are need later in this run
        plot_args = self.plot_args
        self.reinit_variables()
        # Restore the plot args
        self.plot_args = plot_args

        self.job_list.delete(0, self.job_list.size())
        self.progress_value.set(0)
        # Update parent to refresh widget appearance
        self.parent.update()

    def on_add(self):
        single_job = JobParameters(parent=self.parent, beginning_year=1950, ending_year=2100, job_id=self.last_job_id + 1, entry=self)
        single_job.set_grid()

    def on_remove(self):
        selection = self.job_list.curselection()
        for line_number in selection:
            line_text = self.job_list.get(line_number)
            job_id = int(line_text[4:line_text.index(' ', 4)])
            job = self.job_params.pop(job_id)
            self.job_list.delete(line_number)
            print 'Removed Job ' + str(job['job_id'])
        # Fix line number
        for line_number in range(self.job_list.size()):
            line_text = self.job_list.get(line_number)
            job_id = int(line_text[4:line_text.index(' ', 4)])
            #print 'Job ' + str(job_id) + ' is now on line ' + str(line_number)
            self.job_params[job_id]['line_number'] = line_number

    def set_grid(self):
        self.grid(sticky=Tkinter.N + Tkinter.S + Tkinter.W + Tkinter.E, padx=4, pady=4)
        self.columnconfigure(0, minsize=600)
        self.rowconfigure(0, minsize=300)
        self.job_list.grid(row=0, column=0, sticky=Tkinter.N + Tkinter.S + Tkinter.E + Tkinter.W)
        self.job_list_yscroll.grid(row=0, column=1, sticky=Tkinter.N + Tkinter.S + Tkinter.W)
        self.job_list_xscroll.grid(row=1, column=0, sticky=Tkinter.E + Tkinter.W + Tkinter.N)
        self.new_job_frame.grid(row=2, column=0, pady=3, sticky=Tkinter.W)
        self.remove_job_button.grid(row=0, column=0)
        self.add_job_button.grid(row=0, column=1)
        self.progress_frame.grid(row=3, column=0, pady=3)
        self.progress_frame.columnconfigure(0, minsize=600)
        self.progress_bar.grid(row=0, column=0, sticky=Tkinter.E + Tkinter.W + Tkinter.N + Tkinter.S)
        self.button_frame.grid(row=4, column=0, sticky=Tkinter.E + Tkinter.W + Tkinter.N + Tkinter.S)
        self.button_frame.columnconfigure(0, minsize=300)
        self.button_frame.columnconfigure(1, minsize=300)
        self.process_button.pack(side=Tkinter.RIGHT)
        self.quit_button.pack(side=Tkinter.RIGHT)

    def start_jobs(self):
        # If there are no queued jobs then simply return
        if len(self.job_params) == 0 or len(self.job_list.get(0)) == 0:
            return
        # Deactivate the process button
        self.process_button.config(state = Tkinter.DISABLED)
        # Initialize the progress bar
        self.progress_value.set(0)
        # Update parent to refresh widget appearance
        self.parent.update()
        # Start process thread
        jobs_thread = JobsThread(self.job_params, self.run_job, self.on_update, self.on_resume)
        jobs_thread.start()
        self['cursor'] = 'wait'

    def on_update(self, status, line_number, step):
        if status == 'init':
            self.job_list.itemconfig(line_number, foreground='green')
            self.job_list.activate(line_number)
        elif status == 'success':
            self.job_list.itemconfig(line_number, foreground='blue')
        elif status == 'fail':
            self.job_list.itemconfig(line_number, foreground='red')
        self.progress_value.set(step)
        # Update parent to refresh widget appearance
        self.parent.update()

    def on_resume(self, job_outcomes=list()):
        self.progress_value.set(100)
        self.job_outcomes = job_outcomes
        self.event_generate('<<AskToClearJobs>>', when='tail')
        self.event_generate('<<AskToPlotGraphs>>', when='tail')
        self['cursor'] = 'arrow'

    def close_top_level_windows(self):
        #print 'Closing other top level windows'
        for top_level_window in self.top_level_windows:
            if top_level_window:
                top_level_window.withdraw()
                top_level_window.destroy()

    def notify_of_close(self, top_level_window):
        if top_level_window in self.top_level_windows:
            #print 'Removing top level window'
            self.top_level_windows.remove(top_level_window)

    def on_press(self, event):
        self.on_button = True
        self.release_pattern = "<B%d-ButtonRelease-%d>" % (event.num, event.num)
        self.parent.bind(self.release_pattern, self.on_release)

    def on_release(self, event):
        self.on_button = False

    def on_resize(self, event):
        self.parent.lift()

        if self.on_button:

            self.set_grid()

    def on_close(self):
        self.plot_args = list()
        self.withdraw()
        self.destroy()
class photGUI(Frame):
    """The base class for the phot_calc GUI"""
    
    # This is the constructor for the GUI
    def __init__(self,master=None):
        # We begin by calling the base class's constructor first
        Frame.__init__(self,master)
    
        # We now have an empty window!
        
        # This command sets up a grid structure in the window
        self.grid()
        
        # This loop generates rows and columns in the grid
        for i in range(13):
            self.rowconfigure(i,minsize=10)
        for i in range(3):
            self.columnconfigure(i,minsize=30)
        
        # These are methods which appear below the constructor
        self.defineUnits() # this sets up the units I'll be using in the converter
        self.createWidgets() # this places the elements (or widgets) in the grid
        
        # This command "binds" the user's click to a method (varChoice)
        # This method will determine which variable the user wants (Distance, Mass, Time)
        self.inputlist.bind("<Button-1>",self.__varChoice)
    
        # This is a similar command for the selection of unit
        self.unitlist.bind("<Button-1>",self.__unitChoice)
    
        # Finally, this bind reads in whatever value is in the text box when the user hits return
        # and carries out the unit conversion
        
        self.inputfield.bind("<Return>",self.__calcConversion)
    
    # This function creates and defines the units
    
    def defineUnits(self):
        '''Method defines tuples that carry the various units stored by the converter'''
        
        self.speed = 2.997924580000019e10
        self.h = 6.6260755e-27     
        # Wavelengths
        
        self.wavunits = ('nm','um', 'cm','m')
        self.wavvalues = (1.0e-7, 1.0e-4,1.0,1.0e2)
        
        self.frequnits = ('Hz','MHz','GHz','THz')
        self.freqvalues = (1.0, 1.0e6, 1.0e9, 1.0e12)
        
        self.energunits = ('eV','keV','MeV','GeV','erg')
        self.energvalues = (1.0,1.0e3,1.0e6,1.0e9,1.6e-12)
        
        # Keep the unit values in dictionaries, and use the above strings as keys
        
        self.wavdict = {}        
        self.createUnitDict(self.wavdict,self.wavunits,self.wavvalues) # this method is shown below
        
        self.freqdict = {}
        self.createUnitDict(self.freqdict,self.frequnits,self.freqvalues)
        
        self.energdict = {}
        self.createUnitDict(self.energdict, self.energunits, self.energvalues)  
    
        self.myunits = self.wavunits
        self.myvalues = self.wavvalues
        self.mydict = self.wavdict
    
        
    def createUnitDict(self,mydict,mykeys,myvalues):
        '''This method takes a set of units and values, and creates a dictionary to store them in'''
        for i in range(len(myvalues)):
            mydict[mykeys[i]] = myvalues[i]
               
    def createWidgets(self):
        '''This method creates all widgets and adds them to the GUI'''
        
        # Create Widgets in order of appearance
        # This is not necessary, but makes code easier to read
        
        # Start with text telling user what to do
        self.varlabel = Text(self,height=1, width=20)
        self.varlabel.insert(END,"Which Variable?")
        
        # Place widget on the Frame according to a grid
        self.varlabel.grid(row=0,column=0,sticky=W)
        
        # Second text label asking user which units are being used
        self.unitlabel = Text(self,height=1,width=20)
        self.unitlabel.insert(END,"Which Units?")
        self.unitlabel.grid(row=0,column=1,sticky=W)
        
        # Third text label asking user for numerical value
        
        self.numlabel = Text(self,height=1, width=20)
        self.numlabel.insert(END,"Enter Variable Values")
        self.numlabel.grid(row=0,column=2,sticky=W)
        
        # This creates a list of options for the user to select
        self.inputlist = Listbox(self, height=4, selectmode=SINGLE)
      
        # Tuple of choices we're going to put in this list
        self.paramlist = ('Frequency', 'Wavelength', 'Energy')
        
        # Add each item separately
        for item in self.paramlist:
            self.inputlist.insert(END,item)
            
        # Add it to the grid    
        self.inputlist.grid(row=1, column=0,rowspan=4,sticky=W)
        
        # Add a unit list (several combinations of units allowed)
        
        self.unitlist = Listbox(self, height=4,selectmode=SINGLE)
        self.unitlist.grid(row=1,column=1,rowspan=4, sticky=W)
    
        # Number Entry Boxes (and Text Labels)
        
        self.inputlabel = Text(self,height=1,width=20)
        self.inputlabel.insert(END,"Waiting Selection")
        self.inputlabel.grid(row=1,column=2,sticky=W)
        
        self.inputfield = Entry(self)
        self.inputfield.grid(row=2,column=2,sticky=W)
        
        # Text Output Boxes
        self.wavoutput = Text(self, height=5, width=20)
        self.wavoutput.grid(row=7,column=0,rowspan=5,sticky=W)
        self.wavoutput.insert(END, "Wavelength: \n")
        
        self.freqoutput = Text(self, height=5, width=20)
        self.freqoutput.grid(row=7,column=1,rowspan=5,sticky=W)
        self.freqoutput.insert(END, "Frequency: \n")
        
        self.energoutput = Text(self, height=5, width=20)
        self.energoutput.grid(row=7,column=2,rowspan=5,sticky=W)
        self.energoutput.insert(END, "Energy: \n")
        
        # Create the Quit Button
        self.quitButton=Button(self,text='Quit',command=self.quit)
        self.quitButton.grid(row =13, column=0, sticky=W)
             

    # Event handler functions begin here    
    # This handler defines the choice of units available to the user, 
    # depending on selected variable
    
    def __varChoice(self, event):
        '''Handles the selection of variable: updates the list of units'''
        # Firstly, delete anything already in the units column
        self.unitlist.delete(first=0,last=len(self.myvalues))
        num = 0
        
        # Identify which option was clicked on
        try:
            num = self.inputlist.curselection()[0]       
            self.varchoice = int(num)
            
        except:
            self.varchoice = 0
            return
        
        # Get the string associated with this choice
        selection= self.inputlist.get(self.varchoice)
        
        print selection, " chosen"
        
        # Highlight current choice in red
        self.inputlist.itemconfig(self.varchoice, selectbackground='red')
        
        # If statement defines units being used
        if selection =='Wavelength':
            self.myunits = self.wavunits
            self.myvalues = self.wavvalues
            self.mydict = self.wavdict
        elif selection == 'Frequency':
            self.myunits = self.frequnits
            self.myvalues = self.freqvalues
            self.mydict = self.freqdict
        elif selection == 'Energy':
            self.myunits = self.energunits
            self.myvalues = self.energvalues
            self.mydict = self.energdict
            
        
        self.inputlabel.delete("1.0",index2=END)
        self.inputlabel.insert(END,selection)
        
        
        for i in range(len(self.myunits)):
            self.unitlist.insert(END,self.myunits[i])
        
    def __unitChoice(self,event):
        '''Handles the selection of units'''
        num = 0
        # Find which number is selected
        try:
            num = self.unitlist.curselection()[0]       
            self.unitchoice = int(num)
            
        except:
            self.unitchoice = 0
            return
        
        # Get the string (i.e. which unit is selected)
        selection= self.unitlist.get(self.unitchoice)
        
        print selection, " chosen"
        
        # Highlight current choice in red
        self.unitlist.itemconfig(self.unitchoice, selectbackground='red')
        
    # Handler takes current state of GUI, and calculates results
    def __calcConversion(self,event):
        '''This method takes the current state of all GUI variables, calculates one of four equations'''
        
        # Which variable has been selected for calculation?
        # This decides what equation to use
        
        a = self.inputfield.get()
        var = self.unitlist.get(self.unitchoice)
        a=float(a)
        
        freq = 0.0
        wav = 0.0
        energy = 0.0
        
        if self.varchoice==0:
            freq = a
            freq = freq*self.mydict[var]
            wav = self.speed/freq
            energy = self.h*freq/self.energdict['erg']
            
        elif self.varchoice==1:
            wav = a
            wav = wav*self.mydict[var]
            freq = self.speed/wav
            energy = self.speed*self.h/wav
            
        elif self.varchoice==2:
            energy = a
            energy=energy*self.energdict["erg"]
            freq = energy/self.h
            wav = self.speed*self.h/energy
            energy = energy*self.mydict[var]/self.energdict["erg"]
        
        # Remove all text in the output boxes
        self.wavoutput.delete("1.0",index2=END)
        self.freqoutput.delete("1.0",index2=END)
        self.energoutput.delete("1.0",index2=END)
        
        self.wavoutput.insert(END, "Wavelength: \n")
        self.freqoutput.insert(END, "Frequency: \n")
        self.energoutput.insert(END, "Energy: \n")
        
        # Calculate each conversion and output it to the GUI
        for i in range(len(self.wavvalues)):
            # As all units stored in cgs values, conversion is simple
            output = wav/self.wavvalues[i]
            
            # Express output in 
            
            # Add to the output list
            self.wavoutput.insert(END,self.wavunits[i] + ":  %.4e" % output+"\n")  
            
            
        for i in range(len(self.freqvalues)):
            # As all units stored in cgs values, conversion is simple
            output = freq/self.freqvalues[i]
            # Add to the output list
            self.freqoutput.insert(END,self.frequnits[i] + ":  %.4e" % output+"\n")        
            
        for i in range(len(self.energvalues)):
            # As all units stored in cgs values, conversion is simple
            output = energy/self.energvalues[i]
            # Add to the output list
            self.energoutput.insert(END,self.energunits[i] + ":  %.4e" % output+"\n")       
Example #5
0
class App(tk.Frame):
    def __init__(self, master, *args, **kw):
        super().__init__(master, *args, **kw)
        self.root = master
        self.master.title('Rebuild List')
        # Width, Height of application
        self.master.geometry("575x600")
        self.store = Combobox_Autocomplete
        self.alldicts = {}
        self.create_widgets()
        self.create_widgets1()

    def create_widgets(self, *args):
        # Image
        self.imgtitle = ImageTk.PhotoImage(Image.open('snapsrebuild.png'))
        self.lab = tk.Label(image=self.imgtitle)
        self.lab.grid(row=0, column=0, columnspan=6, padx=20, pady=20)
        # Supplies Label
        self.consume_label = tk.Label(self.root, text='Supplies:', font=('Arial', 12, 'bold'))
        self.consume_label.grid(row=1, column=0, columnspan=2, padx=50)
        # AutoCompleteBox
        self.entry_0 = tk.StringVar()
        self.combobox_autocomplete = Combobox_Autocomplete(self.root, list_of_items, textvariable=self.entry_0,
                                                           width=32, highlightthickness=1)
        self.combobox_autocomplete.grid(row=2, column=0, sticky="W", padx=20, pady=10)
        # Insert Button
        self.insert_butt = tk.Button(self.root, text='Insert', command=lambda: self.commando())
        self.insert_butt.place(x=220, y=155)
        # List Box
        self.list_box = Listbox(self.root, border=1, width=40, height=20, justify='center')
        self.list_box.grid(row=3, rowspan=5, column=0, padx=20)
        # Delete Button
        self.del_button = tk.Button(self.root, text='Delete', command=lambda: self.delbutton())
        self.del_button.place(x=175, y=520)
        # Check Button
        self.check_button = tk.Button(self.root, text='Check', command=lambda: self.checkbutton())
        self.check_button.place(x=50, y=520)
        # Uncheck Button
        self.uncheck_button = tk.Button(self.root, text='Uncheck', command=lambda: self.uncheckbutton())
        self.uncheck_button.place(x=105, y=520)

        self.list_box.insert(END, "Dragon Claws")
        self.list_box.insert(END, "Super Combat Potions")
    def delbutton(self):
        self.list_box.delete(ACTIVE)

    def checkbutton(self):
        self.list_box.itemconfig(ACTIVE, {'bg': 'green'})

    def uncheckbutton(self):
        self.list_box.itemconfig(ACTIVE, {'bg': '#ffffff'})


    # def commando(self):
    #     x = 'Consumables'
    #     self.alldicts.update({x: (self.entry_0.get())})
    #     self.list_box.insert(END, self.entry_0.get())
    #     for (key, value) in self.alldicts.items():
    #         print(key, "::", value)
    #     return ()

    #######################################################################################################################

    def create_widgets1(self):
        # Gear Label
        self.consume_label1 = tk.Label(self.root, text='Gear', font=('Arial', 12, 'bold'))
        self.consume_label1.grid(row=1, column=2, padx=50)
        self.entry_1 = tk.StringVar()
        self.combobox_autocomplete1 = Combobox_Autocomplete(self.root, list_of_items, textvariable=self.entry_1,
                                                            width=32,
                                                            highlightthickness=1)
        self.combobox_autocomplete1.grid(row=2, column=2, padx=20, pady=10, sticky="W")
        # Insert Button
        self.insert_butt1 = tk.Button(self.root, text='Insert', command=lambda: self.commando1())
        self.insert_butt1.place(x=505, y=155)
        # List Box
        self.list_box1 = Listbox(self.root, border=1, width=40, height=20)
        self.list_box1.grid(row=3, rowspan=5, column=2, padx=20)
        # Delete Button
        self.del_button1 = tk.Button(self.root, text='Delete', command=lambda: self.delbutton1())
        self.del_button1.place(x=502, y=520)
        # Check Button
        self.check_button1 = tk.Button(self.root, text='Check', command=lambda: self.checkbutton1())
        self.check_button1.place(x=305, y=520)
        # Uncheck Button
        self.uncheck_button1 = tk.Button(self.root, text='Uncheck', command=lambda: self.uncheckbutton1())
        self.uncheck_button1.place(x=400, y=520)


        self.headers = [" ITEM", "                                            PRICE"]
        self.row_format = "{:<8}  {:>8}"
        self.list_box1.insert(0, self.row_format.format(*self.headers, sp="       " * 6))
        self.list_box1.insert(1, '-----------------------------------------------------------')

    def delbutton1(self):
        self.list_box1.delete(ACTIVE)

    def checkbutton1(self):
        self.list_box1.itemconfig(ACTIVE, {'bg': 'green'})

    def uncheckbutton1(self):
        self.list_box1.itemconfig(ACTIVE, {'bg': '#ffffff'})




    def commando1(self):
        x = 'Gear'
        self.alldicts.update({x: (self.entry_1.get())})
        for (key, value) in self.alldicts.items():
            print(key, "::", value)
        for item in names:
            if item in self.entry_1.get():
                indexNumber = names.index(self.entry_1.get())
                print(indexNumber)
                self.priceIndex = prices[indexNumber]
                self.ent = self.entry_1.get()
                self.headers1 = [self.ent,'                            ', f"{self.priceIndex:,d}"]
                self.row_format1 = "{:<8}  {:>8} {:>8}"
                self.list_box1.insert(END, self.row_format1.format(*self.headers1))
        return ()
class App(tk.Frame):
    def __init__(self, master, *args, **kw):
        super().__init__(master, *args, **kw)
        self.root = master
        self.master.title('Rebuild List')
        # Width, Height of application
        self.master.geometry("775x700")
        self.store = Combobox_Autocomplete
        self.alldicts = {}
        self.create_widgets()
        self.create_widgets1()
        self.refresh_button()

    def create_widgets(self, *args):
        # Calculate button
        self.imgtitle = ImageTk.PhotoImage(
            Image.open(
                'C:\\Users\\Chris\\PycharmProjects\\untitled\\snapsrebuild.png'
            ))
        self.lab = tk.Label(image=self.imgtitle)
        self.lab.grid(row=0, column=3, padx=20, pady=20)
        # Heading Labels
        # Consumable Label
        self.consume_label = tk.Label(self.root,
                                      text='Items:',
                                      font=('Arial', 12, 'bold'))
        self.consume_label.grid(row=1, column=0, columnspan=3, padx=50)
        # Rebuild List Center Text
        self.consume_label = tk.Label(self.root,
                                      text='Rebuild List',
                                      font=('Arial', 12, 'bold'))
        self.consume_label.grid(row=1, column=3, padx=50)
        # Armour Text
        self.consume_label = tk.Label(self.root,
                                      text='items:',
                                      font=('Arial', 12, 'bold'))
        self.consume_label.grid(row=1, column=5, columnspan=3, padx=50)
        #######################################################################################################################
        #                                               Left Side buttons and input
        #######################################################################################################################
        # 111111
        # Check Button Number One
        self.is_checked = IntVar()
        self.option_yes = tk.Checkbutton(self.root,
                                         text="",
                                         onvalue=1,
                                         offvalue=0,
                                         variable=self.is_checked,
                                         command=self.callback)
        self.option_yes.grid(row=2, column=0, padx=15)
        # Entry Label To the right of the checkbox
        self.entry_0 = tk.StringVar()
        self.combobox_autocomplete = Combobox_Autocomplete(
            self.root,
            list_of_items,
            textvariable=self.entry_0,
            highlightthickness=1)
        self.combobox_autocomplete.grid(row=2, column=1)
        # Insert button
        self.insert_butt = tk.Button(self.root,
                                     text='Insert',
                                     command=lambda: self.commando())
        self.insert_butt.grid(row=2, column=2, padx=10)
        ########################################################################################################################
        # Check Button Number Two                                                                                22222
        self.is_checked1 = IntVar()
        self.option_yes1 = tk.Checkbutton(self.root,
                                          text="",
                                          onvalue=1,
                                          offvalue=0,
                                          variable=self.is_checked1,
                                          command=self.callback1)
        self.option_yes1.grid(row=3, column=0, padx=15)
        # Entry Label To the right of the checkbox
        self.entry_1 = tk.StringVar()
        self.combobox_autocomplete1 = Combobox_Autocomplete(
            self.root,
            list_of_items,
            textvariable=self.entry_1,
            highlightthickness=1)
        self.combobox_autocomplete1.grid(row=3, column=1)
        # Insert button
        self.insert_butt1 = tk.Button(self.root,
                                      text='Insert',
                                      command=lambda: self.commando1())
        self.insert_butt1.grid(row=3, column=2, padx=10)
        ########################################################################################################################
        # Check Button Number Three                                                                             3333333
        self.is_checked2 = IntVar()
        self.option_yes2 = tk.Checkbutton(self.root,
                                          text="",
                                          onvalue=1,
                                          offvalue=0,
                                          variable=self.is_checked2,
                                          command=self.callback2)
        self.option_yes2.grid(row=4, column=0, padx=15)
        # Entry Label To the right of the checkbox
        self.entry_2 = tk.StringVar()
        self.combobox_autocomplete2 = Combobox_Autocomplete(
            self.root,
            list_of_items,
            textvariable=self.entry_2,
            highlightthickness=1)
        self.combobox_autocomplete2.grid(row=4, column=1)
        # Insert button
        self.insert_butt2 = tk.Button(self.root,
                                      text='Insert',
                                      command=lambda: self.commando2())
        self.insert_butt2.grid(row=4, column=2, padx=10)
        ########################################################################################################################
        # Check Button Number Four                                                                              4444444
        self.is_checked3 = IntVar()
        self.option_yes3 = tk.Checkbutton(self.root,
                                          text="",
                                          onvalue=1,
                                          offvalue=0,
                                          variable=self.is_checked3,
                                          command=self.callback3)
        self.option_yes3.grid(row=5, column=0, padx=15)
        # Entry Label To the right of the checkbox
        self.entry_3 = tk.StringVar()
        self.combobox_autocomplete3 = Combobox_Autocomplete(
            self.root,
            list_of_items,
            textvariable=self.entry_3,
            highlightthickness=1)
        self.combobox_autocomplete3.grid(row=5, column=1)
        # Insert button
        self.insert_butt3 = tk.Button(self.root,
                                      text='Insert',
                                      command=lambda: self.commando3())
        self.insert_butt3.grid(row=5, column=2, padx=10)
        ########################################################################################################################
        # Parts list (listbox)                                                                                 LISTBOX:
        self.list_box = Listbox(self.root,
                                border=0,
                                width=40,
                                height=20,
                                justify='center')
        self.list_box.grid(row=2, rowspan=5, column=3, pady=5)
        # Create scrollbar
        self.scrollbar = tk.Scrollbar(self.root)
        self.scrollbar.grid(row=3, column=4)
        # Set scrollbar to parts
        self.list_box.configure(yscrollcommand=self.scrollbar.set)
        self.scrollbar.configure(command=self.list_box.yview)

    ########################################################################################################################
    # LEFT SIDE FUNCTIONS
    ########################################################################################################################
    # Insert Button On the left right
    def commando(self):
        x = 'Consumables'
        self.alldicts.update({x: (self.entry_0.get())})
        self.list_box.delete(0)
        self.list_box.insert(0, self.entry_0.get())
        for (key, value) in self.alldicts.items():
            print(key, "::", value)
        return ()

    def commando1(self):
        x = 'Consumables1'
        self.alldicts.update({x: (self.entry_1.get())})
        self.list_box.delete(1)
        self.list_box.insert(1, self.entry_1.get())
        for (key, value) in self.alldicts.items():
            print(key, "::", value)
        return ()
        # Insert Button On the left right

    def commando2(self):
        x = 'Consumables2'
        self.alldicts.update({x: (self.entry_2.get())})
        self.list_box.delete(2)
        self.list_box.insert(2, self.entry_2.get())
        for (key, value) in self.alldicts.items():
            print(key, "::", value)
        return ()
        # Insert Button On the left right

    def commando3(self):
        x = 'Consumables3'
        self.alldicts.update({x: (self.entry_3.get())})
        self.list_box.delete(3)
        self.list_box.insert(3, self.entry_3.get())
        for (key, value) in self.alldicts.items():
            print(key, "::", value)
        return ()

    #######################################################################################################################
    def callback(self):
        if self.is_checked.get():
            self.list_box.itemconfig(0, {'bg': 'green'})
        else:
            self.list_box.itemconfig(0, {'bg': '#ffffff'})

    def callback1(self):
        if self.is_checked1.get():
            self.list_box.itemconfig(1, {'bg': 'green'})
        else:
            self.list_box.itemconfig(1, {'bg': '#ffffff'})

    def callback2(self):
        if self.is_checked2.get():
            self.list_box.itemconfig(2, {'bg': 'green'})
        else:
            self.list_box.itemconfig(2, {'bg': '#ffffff'})

    def callback3(self):
        if self.is_checked3.get():
            self.list_box.itemconfig(3, {'bg': 'green'})
        else:
            self.list_box.itemconfig(3, {'bg': '#ffffff'})

    ########################################################################################################################
    # RIGHT SIDE BUTTONS AND LABELS
    ########################################################################################################################
    # 5555555
    def create_widgets1(self, *args):
        # Check Button Number One
        self.is_checked4 = IntVar()
        self.option_yes4 = tk.Checkbutton(self.root,
                                          text="",
                                          onvalue=1,
                                          offvalue=0,
                                          variable=self.is_checked4,
                                          command=self.callback4)
        self.option_yes4.grid(row=2, column=7, padx=15)
        # Entry Label To the right of the checkbox
        self.entry_4 = tk.StringVar()
        self.combobox_autocomplete4 = Combobox_Autocomplete(
            self.root,
            list_of_items,
            textvariable=self.entry_4,
            highlightthickness=1)
        self.combobox_autocomplete4.grid(row=2, column=6)
        # Insert button
        self.insert_butt4 = tk.Button(self.root,
                                      text='Insert',
                                      command=lambda: self.commando4())
        self.insert_butt4.grid(row=2, column=5, padx=10)
        ########################################################################################################################
        # Check Button Number Two                                                                               666666
        self.is_checked5 = IntVar()
        self.option_yes5 = tk.Checkbutton(self.root,
                                          text="",
                                          onvalue=1,
                                          offvalue=0,
                                          variable=self.is_checked5,
                                          command=self.callback5)
        self.option_yes5.grid(row=3, column=7, padx=15)
        # Entry Label To the right of the checkbox
        self.entry_5 = tk.StringVar()
        self.combobox_autocomplete5 = Combobox_Autocomplete(
            self.root,
            list_of_items,
            textvariable=self.entry_5,
            highlightthickness=1)
        self.combobox_autocomplete5.grid(row=3, column=6)
        # Insert button
        self.insert_butt5 = tk.Button(self.root,
                                      text='Insert',
                                      command=lambda: self.commando5())
        self.insert_butt5.grid(row=3, column=5, padx=10)
        ########################################################################################################################
        # Check Button Number Three                                                                             777777
        self.is_checked6 = IntVar()
        self.option_yes6 = tk.Checkbutton(self.root,
                                          text="",
                                          onvalue=1,
                                          offvalue=0,
                                          variable=self.is_checked6,
                                          command=self.callback6)

        self.option_yes6.grid(row=4, column=7, padx=15)
        # Entry Label To the right of the checkbox
        self.entry_6 = tk.StringVar()
        self.combobox_autocomplete6 = Combobox_Autocomplete(
            self.root,
            list_of_items,
            textvariable=self.entry_6,
            highlightthickness=1)
        self.combobox_autocomplete6.grid(row=4, column=6)
        # Insert button
        self.insert_butt6 = tk.Button(self.root,
                                      text='Insert',
                                      command=lambda: self.commando6())
        self.insert_butt6.grid(row=4, column=5, padx=10)
        ########################################################################################################################
        # Check Button Number Four                                                                             888888
        self.is_checked7 = IntVar()
        self.option_yes7 = tk.Checkbutton(self.root,
                                          text="",
                                          onvalue=1,
                                          offvalue=0,
                                          variable=self.is_checked7,
                                          command=self.callback7)

        self.option_yes7.grid(row=5, column=7, padx=15)
        # Entry Label To the right of the checkbox
        self.entry_7 = tk.StringVar()
        self.combobox_autocomplete7 = Combobox_Autocomplete(
            self.root,
            list_of_items,
            textvariable=self.entry_7,
            highlightthickness=1)
        self.combobox_autocomplete7.grid(row=5, column=6)
        # Insert button
        self.insert_butt7 = tk.Button(self.root,
                                      text='Insert',
                                      command=lambda: self.commando7())
        self.insert_butt7.grid(row=5, column=5, padx=10)

    ########################################################################################################################
    #        FUNCTIONS FOR THE RIGHT SIDE
    ########################################################################################################################
    # Insert Buttons on the right side
    def commando4(self):
        x = 'Consumables'
        self.alldicts.update({x: (self.entry_4.get())})
        self.list_box.delete(4)
        self.list_box.insert(4, self.entry_4.get())
        for (key, value) in self.alldicts.items():
            print(key, "::", value)
        return ()

    def commando5(self):
        x = 'Consumables1'
        self.alldicts.update({x: (self.entry_5.get())})
        self.list_box.delete(5)
        self.list_box.insert(5, self.entry_5.get())
        for (key, value) in self.alldicts.items():
            print(key, "::", value)
        return ()

    def commando6(self):
        x = 'Consumables1'
        self.alldicts.update({x: (self.entry_6.get())})
        self.list_box.delete(6)
        self.list_box.insert(6, self.entry_6.get())
        for (key, value) in self.alldicts.items():
            print(key, "::", value)
        return ()

    def commando7(self):
        x = 'Consumables1'
        self.alldicts.update({x: (self.entry_7.get())})
        self.list_box.delete(7)
        self.list_box.insert(7, self.entry_7.get())
        for (key, value) in self.alldicts.items():
            print(key, "::", value)
        return ()

    ########################################################################################################################
    def callback4(self):
        if self.is_checked4.get():
            self.list_box.itemconfig(4, {'bg': 'green'})
        else:
            self.list_box.itemconfig(4, {'bg': '#ffffff'})

    def callback5(self):
        if self.is_checked5.get():
            self.list_box.itemconfig(5, {'bg': 'green'})
        else:
            self.list_box.itemconfig(5, {'bg': '#ffffff'})

    def callback6(self):
        if self.is_checked6.get():
            self.list_box.itemconfig(6, {'bg': 'green'})
        else:
            self.list_box.itemconfig(6, {'bg': '#ffffff'})

    def callback7(self):
        if self.is_checked7.get():
            self.list_box.itemconfig(7, {'bg': 'green'})
        else:
            self.list_box.itemconfig(7, {'bg': '#ffffff'})

    #########################################################################################################################
    # Refresh button
    def refresh_button(self, *args):
        self.refresher = tk.Button(self.root,
                                   text='Refresh',
                                   command=lambda: self.refresh())
        self.refresher.grid(row=7, column=3, pady=10)

    # Need to refresh the colours that have been checked already, must clear the list box.
    def refresh(self, *args):
        self.list_box.delete(0, END)
        self.combobox_autocomplete.delete(0, "end")
        self.combobox_autocomplete1.delete(0, "end")
        self.combobox_autocomplete2.delete(0, "end")
        self.combobox_autocomplete3.delete(0, "end")
        self.combobox_autocomplete4.delete(0, "end")
        self.combobox_autocomplete5.delete(0, "end")
        self.combobox_autocomplete6.delete(0, "end")
        self.combobox_autocomplete7.delete(0, "end")
Example #7
0
class InputDevice(object):

    def __init__(self):
        # root is the Tkinter root widget
        self.root = Tk()
        self.root.title("Input Device Utility")

        # self.root.configure(background='grey')

        self.root.resizable(False,False)

        # define response to main window closing
        self.root.protocol ("WM_DELETE_WINDOW", self.app_exit)

        self.my_device =''
        self.my_device_display = StringVar()
        self.device_list=[]
        self.matches=0


        # overall display
        root_frame=Frame(self.root)
        root_frame.pack(side=LEFT)

        devices_frame=Frame(root_frame,padx=5,pady=10)
        devices_frame.pack(side=LEFT)
        
        devices_label = Label(devices_frame, text="Devices in dev/input")
        devices_label.pack(side=TOP)
        
        devices_list_frame=Frame(devices_frame,padx=5,pady=10)
        devices_list_frame.pack(side=TOP)

        selected_device_title=Label(devices_frame,text='Selected device')
        selected_device_title.pack(side=TOP)
        self.selected_device_var=StringVar()
        selected_device=Label(devices_frame,textvariable=self.selected_device_var,fg="red")
        selected_device.pack(side=TOP)

        events_frame=Frame(root_frame,padx=5,pady=10)
        events_frame.pack(side=LEFT)
        events_title=Label(events_frame,text='Received Events')
        events_title.pack(side=TOP)
        events_list_frame=Frame(events_frame,padx=5,pady=10)
        events_list_frame.pack(side=TOP)


        # list of devices
        scrollbar = Scrollbar(devices_list_frame, orient=VERTICAL)
        self.devices_display = Listbox(devices_list_frame, selectmode=SINGLE, height=20,
                                     width = 60, bg="white",activestyle=NONE,
                                     fg="black", yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.devices_display.yview)
        scrollbar.pack(side=RIGHT, fill=Y)
        self.devices_display.pack(side=LEFT, fill=BOTH, expand=1)
        self.devices_display.bind("<ButtonRelease-1>", self.e_select_device)

        # events display
        scrollbar = Scrollbar(events_list_frame, orient=VERTICAL)
        self.events_display = Text(events_list_frame,width=40,height=20, wrap='word', font="arial 11",padx=5,yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.events_display.yview)
        scrollbar.pack(side=RIGHT, fill=Y)
        self.events_display.pack(side=LEFT, fill=BOTH, expand=1)
        self.events_display.config(state=NORMAL)
        self.events_display.delete(1.0, END)
        self.events_display.config(state=DISABLED)


        self.selected_device_index=-1
        self.matches=0
        
        self.get_all_devices()
        self.refresh_devices_display()


        self.root.after(10,self.event_loop)

        # and enter Tkinter event loop
        self.root.mainloop()        



    # ***************************************
    # INIT AND EXIT
    # ***************************************
    def app_exit(self):
        self.root.destroy()
        exit()

    def event_loop(self):
        if self.matches>0:
            self.get_events()
        self.root.after(10,self.event_loop)

    def refresh_devices_display(self):
        self.devices_display.delete(0,self.devices_display.size())
        for device in self.all_devices:
            self.devices_display.insert(END, device[0]+ ' ' +device[1])        
        if self.selected_device_index >= 0:
            self.devices_display.itemconfig(self.selected_device_index,fg='red')            
            self.devices_display.see(self.selected_device_index)


    def e_select_device(self,event):
        self.selected_device_index=-1
        if len(self.all_devices)>0:
            self.selected_device_index=int(event.widget.curselection()[0])
            selected_device=self.all_devices[self.selected_device_index]
            self.selected_device_name=selected_device[0]
            self.selected_device_var.set(self.selected_device_name)
            self.get_matching_devices()
            self.refresh_devices_display()


    def get_all_devices(self):
        self.all_devices=[]
        devices = [evdev.InputDevice(fn) for fn in evdev.list_devices()]
        for device in devices:
            self.all_devices.append([device.name,device.fn])
            

    def get_matching_devices(self):
        self.matches=0
        self.matching_devices=[]
        devices = [evdev.InputDevice(fn) for fn in evdev.list_devices()]
        for device in devices:
            if self.selected_device_name in device.name:
                device_ref = evdev.InputDevice(device.fn)
                self.matching_devices.append(device_ref)
                self.matches+=1

              
    def get_events(self):
        r,w,x = select(self.matching_devices, [], [],0)
        if r == []:
            return
        for event in r[0].read():
            if event.type == evdev.ecodes.EV_KEY:
                key_event = evdev.categorize(event)
                if key_event.keystate == 1:
                    key_text='Down'
                else:
                    key_text='Up'
                # print key_event.keycode,key_text
                if type(key_event.keycode) is list:
                    code_text=', '.join(key_event.keycode)
                else:
                    code_text=key_event.keycode
                                        
                self.events_display.config(state=NORMAL)
                self.events_display.insert(END,'\n'+ code_text + ' ' + key_text)
                self.events_display.config(state=DISABLED)
                self.events_display.see(END)
Example #8
0
class Gamelist():
    def __init__(self, drive, platform):
        GameListData.game_list_data_json = GameListData().get_game_list()
        self.json_game_list_data = GameListData.game_list_data_json

        if drive == 'USB(*)':
            self.drive_to_show = '/dev_' + drive.lower().replace('(*)', '')
        else:
            self.drive_to_show = '/dev_' + drive.lower() + '/'

        self.platform_to_show = platform + '_games'
        self.WCM_BASE_PATH  = AppPaths.wcm_gui
        self.last_selection = (None, 0)
        self.list_of_items = []

        self.selected_title_id   = None
        self.selected_title      = None
        self.selected_path       = None
        self.selected_filename   = None
        self.drive_system_path_array = None

        self.is_cleared = False


    def create_main_frame(self, entry_field_title_id, entry_field_title, entry_field_filename, entry_field_iso_path, entry_field_platform, drive_system_array):
        self.entry_field_title_id       = entry_field_title_id
        self.entry_field_title          = entry_field_title
        self.entry_field_filename       = entry_field_filename
        self.entry_field_iso_path       = entry_field_iso_path
        self.entry_field_platform       = entry_field_platform
        self.drive_system_path_array    = drive_system_array

        self.corrected_index = []
        self.main_frame = Frame()

        self.popup_menu = Menu(self.main_frame, tearoff=0)

        self.popup_menu.add_command(label="Delete",
                                    command=self.delete_selected)
        self.popup_menu.add_command(label="Rename",
                                    command=self.rename_selected)
        # self.popup_menu.add_command(label="Refetch",
        #                             command=self.refetch)
        # self.popup_menu.add_command(label="Select All",
        #                             command=self.select_all)




        s = Scrollbar(self.main_frame)
        self._listbox = Listbox(self.main_frame, width=465)
        self._listbox.bind('<Enter>', self._bound_to_mousewheel)
        self._listbox.bind('<Leave>', self._unbound_to_mousewheel)
        self._listbox.bind("<Button-3>", self.popup) # Button-2 on Aqua

        s.pack(side=RIGHT, fill=Y)
        self._listbox.pack(side=LEFT, fill=Y)

        s['command'] = self._listbox.yview
        self._listbox['yscrollcommand'] = s.set



        # default filters
        if 'ALL_games' == self.platform_to_show:
            # iterate all platforms
            for platform in self.json_game_list_data:
                for list_game in self.json_game_list_data[platform]:
                    # titles in the list has been designed to be unique
                    if '/dev_all/' == self.drive_to_show or self.drive_to_show in list_game['path']:
                        self.add_item(list_game['title'])

        else:
            for list_game in self.json_game_list_data[self.platform_to_show]:
                if '/dev_all/' == self.drive_to_show or self.drive_to_show in list_game['path']:
                    self.add_item(list_game['title'])

        for x in range(19 - self._listbox.size()):
            self.add_item('')


        # adding shade to every other row of the list
        for x in range(0, self._listbox.size()):
            if x % 2 == 0:
                self._listbox.itemconfig(x, {'fg': 'white'}, background='#001738')
            else:
                self._listbox.itemconfig(x, {'fg': 'white'}, background='#001F4C')

        self.label = Label(self.main_frame)
        self.selection_poller()

        return self.main_frame

    def selection_poller(self):
        self.label.after(200, self.selection_poller)
        self.new_selection = self._listbox.curselection()
        # cursor har been initiated
        if self._listbox.curselection() is not ():
            if self.new_selection[0] is not self.last_selection[0] or self.is_cleared:
                self.entry_fields_update(self.new_selection)
                self.is_cleared = False
                self.last_selection = self.new_selection


    def entry_fields_update(self, new_selection):
        for platform in self.json_game_list_data:

            for list_game in self.json_game_list_data[platform]:
                self.selected_title = self._listbox.get(new_selection[0])
                tmp_title = list_game['title']

                match = self.selected_title == str(tmp_title)
                if match:
                    self.selected_title_id   = str(list_game['title_id']).replace('-', '')
                    self.selected_title      = str(list_game['title'])
                    self.selected_path       = str(list_game['path'])
                    self.selected_filename   = str(list_game['filename'])
                    self.selected_platform   = str(list_game['platform'])

                    # parse drive and system from json data
                    path_array = filter(None, self.selected_path.split('/'))
                    self.drive_system_path_array[0] = path_array[0]
                    self.drive_system_path_array[1] = path_array[1]
                    self.drive_system_path_array[2] = '/'.join(path_array[2:len(path_array)]).replace('//', '')


                    self.entry_field_title_id.delete(0, len(self.entry_field_title_id.get())-1)
                    self.entry_field_title_id.delete(0, END)
                    self.entry_field_title_id.insert(0, self.selected_title_id)

                    self.entry_field_title.delete(0, END)
                    self.entry_field_title.insert(0, self.selected_title)

                    self.entry_field_filename.delete(0, END)
                    self.entry_field_filename.insert(0, self.selected_filename)

                    self.entry_field_platform.delete(0, END)
                    self.entry_field_platform.insert(0, self.selected_platform)

                    return True



    def get_selected_path(self):
        return self.current_iso_path

    def get_listbox(self):
        return self._listbox

    def get_ascending_index(self, list_of_items, item, ignore_case=True):
        lo = 0
        hi = len(list_of_items)

        if ignore_case:
            item = item.lower()
            while lo < hi:
                mid = (lo + hi) // 2

                if item < list_of_items[mid].lower():
                    hi = mid
                else:
                    lo = mid + 1
        else:
            while lo < hi:
                mid = (lo + hi) // 2

                if item < list_of_items[mid]:
                    hi = mid
                else:
                    lo = mid + 1
        return lo

    def add_item(self, item):
        if item != '':
            self.list_of_items = self._listbox.get(0, END)
            # getting ascending index in order to sort alphabetically
            index = self.get_ascending_index(self.list_of_items, item)

            self._listbox.insert(index, item)
        else:
            self._listbox.insert(END, item)

    def get_items(self):
        return self.list_of_items

    def _bound_to_mousewheel(self, event):
        self._listbox.bind_all("<MouseWheel>", self._on_mousewheel)

    def _unbound_to_mousewheel(self, event):
        self._listbox.unbind_all("<MouseWheel>")

    def _on_mousewheel(self, event):
        self._listbox.yview_scroll(int(-1*(event.delta/30)), "units")

    def popup(self, event):
        try:
            self._listbox.selection_clear(0, END)
            self._listbox.selection_set(self._listbox.nearest(event.y))
            self._listbox.activate(self._listbox.nearest(event.y))
        finally:
            if self._listbox.get(self._listbox.curselection()[0]) is not '':
                self.popup_menu.tk_popup(event.x_root + 43, event.y_root + 12, 0)
                self.popup_menu.grab_release()
                self.popup_menu.focus_set()

    def delete_selected(self):
        import tkMessageBox
        game_folder_path = os.path.join(AppPaths.game_work_dir, '..')
        response = tkMessageBox.askyesno('Delete game folder', 'Delete \'' + self.entry_field_title.get() + '\'?\n\nFolder path: ' + os.path.realpath(game_folder_path))
        # yes
        if response:
            # remove game from visual game list
            for i in self._listbox.curselection()[::-1]:
                self._listbox.delete(i)
                removed_index = i

            # remove game from json game list
            platform_key = self.entry_field_platform.get() + '_games'
            self.json_game_list_data[platform_key] = [x for x in self.json_game_list_data[platform_key] if x['title'] != self.selected_title]

            # update the json game list file
            with open(GameListData.GAME_LIST_DATA_PATH, 'w') as newFile:
                json_text = json.dumps(self.json_game_list_data, indent=4, separators=(",", ":"))
                newFile.write(json_text)

            # remove the game build folder too
            if AppPaths.game_work_dir != os.path.join(AppPaths.wcm_gui, 'work_dir'):
                if os.path.isdir(game_folder_path):
                    if 'webman-classics-maker' in game_folder_path:
                        shutil.rmtree(game_folder_path)
                # clear entry_fields
                self.clear_entries_and_path()
                # set cursor
                self._listbox.select_set(removed_index) #This only sets focus on the first item.

    def rename_selected(self):
        self.entry_field_title.selection_range(0, END)
        self.entry_field_title.focus_set()

    def select_all(self):
        self._listbox.selection_set(0, 'end')


    def clear_entries_and_path(self):
        self.entry_field_title_id.delete(0, len(self.entry_field_title_id.get())-1)
        self.entry_field_title_id.delete(0, END)
        self.entry_field_title.delete(0, END)
        self.entry_field_platform.delete(0, END)
        self.entry_field_filename.delete(0, END)

        self.is_cleared = True



    def get_selected_build_dir_path(self):
        self.build_dir_path = ''
        if self.selected_filename not in {'', None}:
            filename = self.selected_filename
            title_id = self.selected_title_id.replace('-', '')
            build_base_path = AppPaths.builds

            tmp_filename = filename
            # removes the file extension from tmp_filename
            for file_ext in GlobalVar.file_extensions:
                if filename.upper().endswith(file_ext):
                    tmp_filename = filename[0:len(filename)-len(file_ext)]
                    break
            game_folder_name = tmp_filename.replace(' ', '_') + '_(' + title_id.replace('-', '') + ')'

            self.build_dir_path = os.path.join(build_base_path, game_folder_name)
        return self.build_dir_path
class InputDevice(object):
    def __init__(self):
        # root is the Tkinter root widget
        self.root = Tk()
        self.root.title("Input Device Utility")

        # self.root.configure(background='grey')

        self.root.resizable(False, False)

        # define response to main window closing
        self.root.protocol("WM_DELETE_WINDOW", self.app_exit)

        self.my_device = ''
        self.my_device_display = StringVar()
        self.device_list = []
        self.matches = 0

        # overall display
        root_frame = Frame(self.root)
        root_frame.pack(side=LEFT)

        devices_frame = Frame(root_frame, padx=5, pady=10)
        devices_frame.pack(side=LEFT)

        devices_label = Label(devices_frame, text="Devices in dev/input")
        devices_label.pack(side=TOP)

        devices_list_frame = Frame(devices_frame, padx=5, pady=10)
        devices_list_frame.pack(side=TOP)

        selected_device_title = Label(devices_frame, text='Selected device')
        selected_device_title.pack(side=TOP)
        self.selected_device_var = StringVar()
        selected_device = Label(devices_frame,
                                textvariable=self.selected_device_var,
                                fg="red")
        selected_device.pack(side=TOP)

        events_frame = Frame(root_frame, padx=5, pady=10)
        events_frame.pack(side=LEFT)
        events_title = Label(events_frame, text='Received Events')
        events_title.pack(side=TOP)
        events_list_frame = Frame(events_frame, padx=5, pady=10)
        events_list_frame.pack(side=TOP)

        # list of devices
        scrollbar = Scrollbar(devices_list_frame, orient=VERTICAL)
        self.devices_display = Listbox(devices_list_frame,
                                       selectmode=SINGLE,
                                       height=20,
                                       width=60,
                                       bg="white",
                                       activestyle=NONE,
                                       fg="black",
                                       yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.devices_display.yview)
        scrollbar.pack(side=RIGHT, fill=Y)
        self.devices_display.pack(side=LEFT, fill=BOTH, expand=1)
        self.devices_display.bind("<ButtonRelease-1>", self.e_select_device)

        # events display
        scrollbar = Scrollbar(events_list_frame, orient=VERTICAL)
        self.events_display = Text(events_list_frame,
                                   width=40,
                                   height=20,
                                   wrap='word',
                                   font="arial 11",
                                   padx=5,
                                   yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.events_display.yview)
        scrollbar.pack(side=RIGHT, fill=Y)
        self.events_display.pack(side=LEFT, fill=BOTH, expand=1)
        self.events_display.config(state=NORMAL)
        self.events_display.delete(1.0, END)
        self.events_display.config(state=DISABLED)

        self.selected_device_index = -1
        self.matches = 0

        self.get_all_devices()
        self.refresh_devices_display()

        self.root.after(10, self.event_loop)

        # and enter Tkinter event loop
        self.root.mainloop()

    # ***************************************
    # INIT AND EXIT
    # ***************************************
    def app_exit(self):
        self.root.destroy()
        exit()

    def event_loop(self):
        if self.matches > 0:
            self.get_events()
        self.root.after(10, self.event_loop)

    def refresh_devices_display(self):
        self.devices_display.delete(0, self.devices_display.size())
        for device in self.all_devices:
            self.devices_display.insert(END, device[0] + ' ' + device[1])
        if self.selected_device_index >= 0:
            self.devices_display.itemconfig(self.selected_device_index,
                                            fg='red')
            self.devices_display.see(self.selected_device_index)

    def e_select_device(self, event):
        self.selected_device_index = -1
        if len(self.all_devices) > 0:
            self.selected_device_index = int(event.widget.curselection()[0])
            selected_device = self.all_devices[self.selected_device_index]
            self.selected_device_name = selected_device[0]
            self.selected_device_var.set(self.selected_device_name)
            self.get_matching_devices()
            self.refresh_devices_display()

    def get_all_devices(self):
        self.all_devices = []
        devices = [evdev.InputDevice(fn) for fn in evdev.list_devices()]
        for device in devices:
            self.all_devices.append([device.name, device.fn])

    def get_matching_devices(self):
        self.matches = 0
        self.matching_devices = []
        devices = [evdev.InputDevice(fn) for fn in evdev.list_devices()]
        for device in devices:
            if self.selected_device_name in device.name:
                device_ref = evdev.InputDevice(device.fn)
                self.matching_devices.append(device_ref)
                self.matches += 1

    def get_events(self):
        r, w, x = select(self.matching_devices, [], [], 0)
        if r == []:
            return
        for event in r[0].read():
            if event.type == evdev.ecodes.EV_KEY:
                key_event = evdev.categorize(event)
                if key_event.keystate == 1:
                    key_text = 'Down'
                else:
                    key_text = 'Up'
                # print key_event.keycode,key_text
                if type(key_event.keycode) is list:
                    code_text = ', '.join(key_event.keycode)
                else:
                    code_text = key_event.keycode

                self.events_display.config(state=NORMAL)
                self.events_display.insert(END,
                                           '\n' + code_text + ' ' + key_text)
                self.events_display.config(state=DISABLED)
                self.events_display.see(END)
Example #10
0
class GUI(Frame):
    # In intialize the object, taking in the parent as in input parameter
    def __init__(self, parent):
        Frame.__init__(self, parent)
        # Initialize the api
        self.api = API()
        # Set the ip and port to communicate with the master server
        self.SERVER_IP = config.masterip
        self.SERVER_PORT = config.port
        # Set the initial server status to 0, will change to 1 if server is active
        # self.serverStatus = 0
        # Declare a list which will hold the files that have been flagged for deletion
        self.toDelete = []

        self.parent = parent
        # Initialize the GUI
        self.initUI()

    # Function to initialize UI
    def initUI(self):
        # Set the name of the UI window
        self.parent.title("Bennington File System Client")
        # Set the style using the default theme
        self.style = Style()
        self.style.theme_use("default")
        self.pack(fill=BOTH, expand=1)

        # Set the "Open File" options
        self.file_opt = options = {}
        # Allow for any file to be choosable
        options["defaultextension"] = ""
        options["filetypes"] = ""
        # Set the directory window will open up to initially
        options["initialdir"] = "C:\\"
        options["parent"] = self

        # Create a label object which holds the text labeling the listbox
        lbl = Label(self, text="Bennington File System Files List", foreground="black")
        # Place the text in the top left
        lbl.grid(column=0, row=0, pady=4, padx=5)

        # Create the listbox, which will contain a list of all the files on the system
        self.area = Listbox(self, height=20)
        # Place the lisbox in the UI frame
        self.area.grid(row=1, column=0, columnspan=1, rowspan=10, padx=5, sticky=N + W + E + S)

        # Ask the master server which files it has, then populate the listbox with the response
        self.getFiles()

        # Create a button labeled 'Upload', and bind the uploadFile() function to it
        uploadbtn = Button(self, text="Upload", command=self.uploadFile)
        # Place the button in the UI frame
        uploadbtn.grid(row=1, column=3)

        # Create a button labeled 'Download', and bind the downloadFile() function to it
        dwnbtn = Button(self, text="Download", command=self.downloadFile)
        # Place the button in the UI frame
        dwnbtn.grid(row=2, column=3)

        # Create a button labeled 'Delete', and bind the deleteFile() function to it
        delbtn = Button(self, text="Delete", command=self.deleteFile)
        # Place the button in the UI frame
        delbtn.grid(row=3, column=3)

        # Create a button labeled 'Undelete', and bind the undeleteFile() function to it
        undelbtn = Button(self, text="Undelete", command=self.undeleteFile)
        # Place the button in the UI frame
        undelbtn.grid(row=4, column=3)

        # Create a button labeled 'Refresh List', and bind the getFiles() function to it
        refbtn = Button(self, text="Refresh List", command=self.getFiles)
        # Place the button in the UI frame
        refbtn.grid(row=5, column=3)

        # Create a button labeled 'Quit', and bind the exitProgram() function to it
        quitButton = Button(self, text="Quit", command=self.exitProgram)
        # Place the button in the UI frame
        quitButton.grid(sticky=W, padx=5, pady=4)

    # Downloads the active selection in the listbox
    def downloadFile(self):
        # Get the filename from the active listbox item
        fileName = self.currentSelectionFileName()
        # Call the API read function to get all the data associated with that file
        self.api.read(fileName, 0, -1, fileName)

    # Get the file name of the active selection in the listbox
    def currentSelectionFileName(self):
        # Get the index of the active selection
        index = self.currentSelectionIndex()
        # From the listbox object, pass in the index to get the filename
        fileName = self.area.get(index)
        return fileName

    # Get the index of the active selection in the listbox
    def currentSelectionIndex(self):
        # Get the index of the active selection
        index = self.area.curselection()[0]
        return index

    # Mark the active selection in the listbox for deletion
    def deleteFile(self):
        # Get the index of the current active selection
        index = self.currentSelectionIndex()
        # Get the filename of the current active selection
        filename = self.area.get(index)
        # Call the API function to mark file for deletion
        self.api.delete(filename)
        # Change the background color of the selection to denote it has been marked for deletion
        self.area.itemconfig(index, {"bg": "salmon"})
        # Append the filename to the toDelete list
        self.toDelete.append(filename)

    # Unmarks the active selection in the listbox for deletion
    def undeleteFile(self):
        # Get the index of the current active selection
        index = self.currentSelectionIndex()
        # Get the filename of the current active selection
        filename = self.area.get(index)
        # See if the file has been marked for deletion
        if filename in self.toDelete:
            # Call the API function to unmark file for deletion
            self.api.undelete(filename)
            # Change the background color of the selection to denote it is no longer marked for deletion
            self.area.itemconfig(index, {"bg": "white"})
            # Remove the filename from the toDelete list
            self.toDelete.remove(filename)

    # Upload a file from local machine to the distributed file system
    def uploadFile(self):
        # Get the file name and file path of the file the user wants to upload
        fileinfo = self.openFile()
        # Create a file with the filename provided
        self.api.create(fileinfo[0])
        # Append the file data from the file at the given file path
        self.api.append(fileinfo[0], fileinfo[1], 1)
        # Once that is complete, refresh the file list in the listbox
        self.getFiles()

    # Prompt the user to select a file
    def openFile(self):
        # Prompt the user to select a file, and store the returned file path
        filepath = tkFileDialog.askopenfilename(**self.file_opt)
        # Parse the filepath, and store the last element of the split as the file name
        filename = filepath.split("/")[-1]
        # Return a list containing the file name and file path
        return [filename, filepath]

    # Get the list of existing files from the master server
    def getFiles(self):
        try:
            # Get the file data using the API's fileList() function
            # At this stage, the data has lots of extra things in it, so it needs to be cleaned up
            data = self.api.fileList()
            # Split the string at every * character
            data = re.split("\*", data)
            # Declare an empty array which will hold the file names found from the parsing
            fileNames = []
            for item in data:
                # Split the element at every ^ character
                tempitem = re.split("\^", item)
                for thing in tempitem:
                    # If the element has a | in it, but is not just a |, then it is the filename
                    if "|" in thing and not thing == "|":
                        # Append the filename (with the | stripped out) to the fileNames list
                        fileNames.append(thing.strip("|"))

            # If the file is marked for deletion and still in the fileNames list
            # keep the file in the toDelete list
            temp = []
            for item in self.toDelete:
                if item in fileNames:
                    temp.append(item)

            # Update the toDelete list
            self.toDelete = temp

            # Remove all entries in the listbox
            self.area.delete(0, END)

            # Populate the listbox with the file names returned from the master
            for item in fileNames:
                self.area.insert(END, item)
                self.checkIfMarked(item)

        except Exception as e:
            raise e

    # Check to see if the provided file name exists in the toDelete list
    def checkIfMarked(self, fileName):
        # If the file name is in the toDelete list
        if fileName in self.toDelete:
            # Change the background color of the element to denote that it has been marked for deletion
            self.area.itemconfig(END, {"bg": "salmon"})

    # An exit function that quits the UI (any additional clean up pre-close should go in here)
    def exitProgram(self):
        self.quit()
Example #11
0
class hillGUI(Frame):
    """The base class for the hill_calc GUI"""
    
    # This is the constructor for the GUI
    def __init__(self,master=None):
        # We begin by calling the base class's constructor first
        Frame.__init__(self,master)
    
        # We now have an empty window!
        
        # This command sets up a grid structure in the window
        self.grid()
        
        # This loop generates rows and columns in the grid
        for i in range(10):
            self.rowconfigure(i,minsize=10)
        for i in range(3):
            self.columnconfigure(i,minsize=10)
        
        # These are methods which appear below the constructor
        #self.defineUnits() # this sets up the units I'll be using in the converter
        self.createWidgets() # this places the elements (or widgets) in the grid
        
        # This command "binds" the user's click to a method (varChoice)
        # This method will determine which variable the user wants (Distance, Mass, Time)
        self.inputlist.bind("<Button-1>",self.__varChoice)
    
        # This is a similar command for the selection of unit
        self.unitlist.bind("<Button-1>",self.__unitChoice)
    
        # Finally, this bind reads in whatever value is in the text box when the user hits return
        # and carries out the unit conversion
        
        for i in range(len(self.inputfield)):
            self.inputfield[i].bind("<Return>",self.__calcConversion)
               
    def createUnitDict(self,mydict,mykeys,myvalues):
        '''This method takes a set of units and values, and creates a dictionary to store them in'''
        for i in range(len(myvalues)):
            mydict[mykeys[i]] = myvalues[i]
            
    def createWidgets(self):
        '''This method creates all widgets and adds them to the GUI'''
        
        # Create Widgets in order of appearance
        # This is not necessary, but makes code easier to read
        
        # Start with text telling user what to do
        self.varlabel = Text(self,height=1, width=20)
        self.varlabel.insert(END,"Which Variable?")
        
        # Place widget on the Frame according to a grid
        self.varlabel.grid(row=0,column=0,sticky=W)
        
        # Second text label asking user which units are being used
        self.unitlabel = Text(self,height=2,width=20)
        self.unitlabel.insert(END,"Planet Mass Units?\n (a=AU, Ms=Msol)")
        self.unitlabel.grid(row=0,column=1,sticky=W)
        
        # Third text label asking user for numerical value
        
        self.numlabel = Text(self,height=1, width=20)
        self.numlabel.insert(END,"Enter Variable Values")
        self.numlabel.grid(row=0,column=2,sticky=W)
        
        # This creates a list of options for the user to select
        self.inputlist = Listbox(self, height=4, selectmode=SINGLE)
      
        # Tuple of choices we're going to put in this list
        self.paramlist = ('Semi Major Axis', 'Planet Mass', 'Star Mass','Hill Radius')
        
        # Add each item separately
        for item in self.paramlist:
            self.inputlist.insert(END,item)
            
        # Add it to the grid    
        self.inputlist.grid(row=1, column=0,rowspan=4,sticky=W)
        
        # Add a unit list (several combinations of units allowed)
        
        self.unitlist = Listbox(self, height=4,selectmode=SINGLE)
        self.unitlist.grid(row=1,column=1,rowspan=4, sticky=W)
        
        self.massunits = ('Earth Masses','Neptune Masses', 'Jupiter Masses', 'Solar Masses') 
        self.massvalues = ( 3.00343905235e-06, 5.1500311727e-5, 0.000954588419846,1.0)
    
        self.massdict = {}
        self.createUnitDict(self.massdict, self.massunits,self.massvalues)
    
        for item in self.massunits:
            self.unitlist.insert(END,item)
    
        # Number Entry Boxes (and Text Labels)
        
        self.inputfield = []
        self.inputlabels = []
    
        irow = 0
        for i in range(len(self.paramlist)):
            
            irow = irow+1
            self.inputlabels.append(Text(self,height=1,width=20))
            self.inputlabels[i].insert(END,self.paramlist[i])
            self.inputlabels[i].grid(row=irow,column=2,sticky='N')
            irow = irow+1
            self.inputfield.append(Entry(self))
            self.inputfield[i].insert(END, "1.0")
            self.inputfield[i].grid(row =irow, column=2,sticky='N')
        
        # Text Output Box
        self.outputtext = Text(self, height=1, width=40)
        self.outputtext.grid(row=7,column=0,columnspan=2,sticky=W)
        self.outputtext.insert(END, "WAITING: ")
        # Create the Quit Button
        self.quitButton=Button(self,text='Quit',command=self.quit)
        self.quitButton.grid(row =8, column=0, sticky=W)
             

    # Event handler functions begin here    
    # This handler defines the choice of units available to the user, 
    # depending on selected variable
    
    def __varChoice(self, event):
        '''Handles the selection of variable: updates the list of units'''
        # Firstly, delete anything already in the units column
#        self.unitlist.delete(first=0,last=len(self.myvalues))
        num = 0
        
        # Identify which option was clicked on
        try:
            num = self.inputlist.curselection()[0]       
            self.varchoice = int(num)
            
        except:
            self.varchoice = 0
            return
        
        # Get the string associated with this choice
        selection= self.inputlist.get(self.varchoice)
        
        print selection, " chosen"
        
        # Highlight current choice in red
        self.inputlist.itemconfig(self.varchoice, selectbackground='red')

    def __unitChoice(self,event):
        '''Handles the selection of units'''
        num = 0
        # Find which number is selected
        try:
            num = self.unitlist.curselection()[0]       
            self.unitchoice = int(num)
            
        except:
            self.unitchoice = 0
            return
        
        # Get the string (i.e. which unit is selected)
        selection= self.unitlist.get(self.unitchoice)
        
        print selection, " chosen"
        
        # Highlight current choice in red
        self.unitlist.itemconfig(self.unitchoice, selectbackground='red')
        
        # If statement defines units being used
        
        self.massconvert = self.massdict[selection]
        
        
        # Remove all text in the output box, and tell user to define units
        self.outputtext.delete("1.0",index2=END)
        self.outputtext.insert(END, "Now Enter Values")
        
    # Handler takes current state of GUI, and calculates results
    def __calcConversion(self,event):
        '''This method takes the current state of all GUI variables, calculates one of four equations'''
        print 'Calculating'
        # Which variable has been selected for calculation?
        # This decides what equation to use
        
        a = self.inputfield[0].get()
        a=float(a)
        
        mp = self.inputfield[1].get()
        mp=float(mp)*self.massconvert
        
        ms = self.inputfield[2].get()
        ms = float(ms)
        
        rh = self.inputfield[3].get()
        rh = float(rh)
        
        if self.varchoice==0:
            a = rh*(3*ms/mp)*0.3333
            value = a
        elif self.varchoice==1:
            mp = 3*ms*rh**3/a**3
            value = mp
        elif self.varchoice==2:
            ms = mp*a**3/(3*rh**3)
            value = ms
        elif self.varchoice==3:
            rh = a *(mp/(3*ms))**0.3333
            value = rh
            
        
        # Remove all text in the output box and insert new stuff
        self.outputtext.delete("1.0",index2=END)
        self.outputtext.insert(END,str(self.paramlist[self.varchoice])+":    "+str(value))
Example #12
0
class PPEditor(object):

    # ***************************************
    # INIT
    # ***************************************

    def __init__(self):
    
        self.editor_issue="1.3"

        # get command options
        self.command_options=ed_options()

        # get directory holding the code
        self.pp_dir=sys.path[0]
            
        if not os.path.exists(self.pp_dir+os.sep+"pp_editor.py"):
            tkMessageBox.showwarning("Pi Presents","Bad Application Directory")
            exit()
            
          
        # Initialise logging
        Monitor.log_path=self.pp_dir
        self.mon=Monitor()
        self.mon.init()
        
        Monitor.classes  = ['PPEditor','EditItem','Validator']

        Monitor.log_level = int(self.command_options['debug'])

        self.mon.log (self, "Pi Presents Editor is starting")
        self.mon.log (self," OS and separator " + os.name +'  ' + os.sep)
        self.mon.log(self,"sys.path[0] -  location of code: code "+sys.path[0])


        # set up the gui
 
        # root is the Tkinter root widget
        self.root = Tk()
        self.root.title("Editor for Pi Presents")

        # self.root.configure(background='grey')

        self.root.resizable(False,False)

        # define response to main window closing
        self.root.protocol ("WM_DELETE_WINDOW", self.app_exit)

        # bind some display fields
        self.filename = StringVar()
        self.display_selected_track_title = StringVar()
        self.display_show = StringVar()


        # define menu
        menubar = Menu(self.root)

        profilemenu = Menu(menubar, tearoff=0, bg="grey", fg="black")
        profilemenu.add_command(label='Open', command = self.open_existing_profile)
        profilemenu.add_command(label='Validate', command = self.validate_profile)
        menubar.add_cascade(label='Profile', menu = profilemenu)

        ptypemenu = Menu(profilemenu, tearoff=0, bg="grey", fg="black")
        ptypemenu.add_command(label='Exhibit', command = self.new_exhibit_profile)
        ptypemenu.add_command(label='Media Show', command = self.new_mediashow_profile)
        ptypemenu.add_command(label='Art Media Show', command = self.new_artmediashow_profile)
        ptypemenu.add_command(label='Menu', command = self.new_menu_profile)
        ptypemenu.add_command(label='Presentation', command = self.new_presentation_profile)
        ptypemenu.add_command(label='Interactive', command = self.new_interactive_profile)
        ptypemenu.add_command(label='Live Show', command = self.new_liveshow_profile)
        ptypemenu.add_command(label='Art Live Show', command = self.new_artliveshow_profile)
        ptypemenu.add_command(label='RadioButton Show', command = self.new_radiobuttonshow_profile)
        ptypemenu.add_command(label='Hyperlink Show', command = self.new_hyperlinkshow_profile)
        ptypemenu.add_command(label='Blank', command = self.new_blank_profile)
        profilemenu.add_cascade(label='New from Template', menu = ptypemenu)
        
        showmenu = Menu(menubar, tearoff=0, bg="grey", fg="black")
        showmenu.add_command(label='Delete', command = self.remove_show)
        showmenu.add_command(label='Edit', command = self.m_edit_show)
        showmenu.add_command(label='Copy To', command = self.copy_show)
        menubar.add_cascade(label='Show', menu = showmenu)

        stypemenu = Menu(showmenu, tearoff=0, bg="grey", fg="black")
        stypemenu.add_command(label='Menu', command = self.add_menushow)
        stypemenu.add_command(label='MediaShow', command = self.add_mediashow)
        stypemenu.add_command(label='LiveShow', command = self.add_liveshow)
        stypemenu.add_command(label='HyperlinkShow', command = self.add_hyperlinkshow)
        stypemenu.add_command(label='RadioButtonShow', command = self.add_radiobuttonshow)
        stypemenu.add_command(label='ArtMediaShow', command = self.add_artmediashow)
        stypemenu.add_command(label='ArtLiveShow', command = self.add_artliveshow)
        showmenu.add_cascade(label='Add', menu = stypemenu)
        
        medialistmenu = Menu(menubar, tearoff=0, bg="grey", fg="black")
        menubar.add_cascade(label='MediaList', menu = medialistmenu)
        medialistmenu.add_command(label='Add', command = self.add_medialist)
        medialistmenu.add_command(label='Delete', command = self.remove_medialist)
        medialistmenu.add_command(label='Copy To', command = self.copy_medialist)
      
        trackmenu = Menu(menubar, tearoff=0, bg="grey", fg="black")
        trackmenu.add_command(label='Delete', command = self.remove_track)
        trackmenu.add_command(label='Edit', command = self.m_edit_track)
        trackmenu.add_command(label='Add from Dir', command = self.add_tracks_from_dir)
        trackmenu.add_command(label='Add from File', command = self.add_track_from_file)


        menubar.add_cascade(label='Track', menu = trackmenu)

        typemenu = Menu(trackmenu, tearoff=0, bg="grey", fg="black")
        typemenu.add_command(label='Video', command = self.new_video_track)
        typemenu.add_command(label='Audio', command = self.new_audio_track)
        typemenu.add_command(label='Image', command = self.new_image_track)
        typemenu.add_command(label='Web', command = self.new_web_track)
        typemenu.add_command(label='Message', command = self.new_message_track)
        typemenu.add_command(label='Show', command = self.new_show_track)
        typemenu.add_command(label='Menu Track', command = self.new_menu_track)
        trackmenu.add_cascade(label='New', menu = typemenu)

        oscmenu = Menu(menubar, tearoff=0, bg="grey", fg="black")
        menubar.add_cascade(label='OSC', menu = oscmenu)
        oscmenu.add_command(label='Create OSC configuration', command = self.create_osc)
        oscmenu.add_command(label='Edit OSC Configuration', command = self.edit_osc)
        oscmenu.add_command(label='Delete OSC Configuration', command = self.delete_osc)


        toolsmenu = Menu(menubar, tearoff=0, bg="grey", fg="black")
        menubar.add_cascade(label='Tools', menu = toolsmenu)
        toolsmenu.add_command(label='Update All', command = self.update_all)
        
        optionsmenu = Menu(menubar, tearoff=0, bg="grey", fg="black")
        menubar.add_cascade(label='Options', menu = optionsmenu)
        optionsmenu.add_command(label='Edit', command = self.edit_options)

        helpmenu = Menu(menubar, tearoff=0, bg="grey", fg="black")
        menubar.add_cascade(label='Help', menu = helpmenu)
        helpmenu.add_command(label='Help', command = self.show_help)
        helpmenu.add_command(label='About', command = self.about)
         
        self.root.config(menu=menubar)

        top_frame=Frame(self.root)
        top_frame.pack(side=TOP)
        bottom_frame=Frame(self.root)
        bottom_frame.pack(side=TOP, fill=BOTH, expand=1)        

        left_frame=Frame(bottom_frame, padx=5)
        left_frame.pack(side=LEFT)
        middle_frame=Frame(bottom_frame,padx=5)
        middle_frame.pack(side=LEFT)              
        right_frame=Frame(bottom_frame,padx=5,pady=10)
        right_frame.pack(side=LEFT)
        updown_frame=Frame(bottom_frame,padx=5)
        updown_frame.pack(side=LEFT)
        
        tracks_title_frame=Frame(right_frame)
        tracks_title_frame.pack(side=TOP)
        tracks_label = Label(tracks_title_frame, text="Tracks in Selected Medialist")
        tracks_label.pack()
        tracks_frame=Frame(right_frame)
        tracks_frame.pack(side=TOP)
        shows_title_frame=Frame(left_frame)
        shows_title_frame.pack(side=TOP)
        shows_label = Label(shows_title_frame, text="Shows")
        shows_label.pack()
        shows_frame=Frame(left_frame)
        shows_frame.pack(side=TOP)
        shows_title_frame=Frame(left_frame)
        shows_title_frame.pack(side=TOP)
        medialists_title_frame=Frame(left_frame)
        medialists_title_frame.pack(side=TOP)
        medialists_label = Label(medialists_title_frame, text="Medialists")
        medialists_label.pack()
        medialists_frame=Frame(left_frame)
        medialists_frame.pack(side=LEFT)
        
        # define buttons 

        add_button = Button(middle_frame, width = 5, height = 2, text='Edit\nShow',
                            fg='black', command = self.m_edit_show, bg="light grey")
        add_button.pack(side=RIGHT)
        
        add_button = Button(updown_frame, width = 5, height = 1, text='Add',
                            fg='black', command = self.add_track_from_file, bg="light grey")
        add_button.pack(side=TOP)
        add_button = Button(updown_frame, width = 5, height = 1, text='Edit',
                            fg='black', command = self.m_edit_track, bg="light grey")
        add_button.pack(side=TOP)
        add_button = Button(updown_frame, width = 5, height = 1, text='Up',
                            fg='black', command = self.move_track_up, bg="light grey")
        add_button.pack(side=TOP)
        add_button = Button(updown_frame, width = 5, height = 1, text='Down',
                            fg='black', command = self.move_track_down, bg="light grey")
        add_button.pack(side=TOP)


        # define display of showlist 
        scrollbar = Scrollbar(shows_frame, orient=VERTICAL)
        self.shows_display = Listbox(shows_frame, selectmode=SINGLE, height=12,
                                     width = 40, bg="white",activestyle=NONE,
                                     fg="black", yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.shows_display.yview)
        scrollbar.pack(side=RIGHT, fill=Y)
        self.shows_display.pack(side=LEFT, fill=BOTH, expand=1)
        self.shows_display.bind("<ButtonRelease-1>", self.e_select_show)

    
        # define display of medialists
        scrollbar = Scrollbar(medialists_frame, orient=VERTICAL)
        self.medialists_display = Listbox(medialists_frame, selectmode=SINGLE, height=12,
                                          width = 40, bg="white",activestyle=NONE,
                                          fg="black",yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.medialists_display.yview)
        scrollbar.pack(side=RIGHT, fill=Y)
        self.medialists_display.pack(side=LEFT,  fill=BOTH, expand=1)
        self.medialists_display.bind("<ButtonRelease-1>", self.select_medialist)


        # define display of tracks
        scrollbar = Scrollbar(tracks_frame, orient=VERTICAL)
        self.tracks_display = Listbox(tracks_frame, selectmode=SINGLE, height=25,
                                      width = 40, bg="white",activestyle=NONE,
                                      fg="black",yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.tracks_display.yview)
        scrollbar.pack(side=RIGHT, fill=Y)
        self.tracks_display.pack(side=LEFT,fill=BOTH, expand=1)
        self.tracks_display.bind("<ButtonRelease-1>", self.e_select_track)


        # initialise editor options class and OSC config class
        self.options=Options(self.pp_dir) # creates options file in code directory if necessary
        self.osc_config=OSCConfig()
        
        # initialise variables      
        self.init()
        
        # and enter Tkinter event loop
        self.root.mainloop()        


    # ***************************************
    # INIT AND EXIT
    # ***************************************
    def app_exit(self):
        self.root.destroy()
        exit()


    def init(self):
        self.options.read()
        self.pp_home_dir = self.options.pp_home_dir
        self.pp_profiles_offset = self.options.pp_profiles_offset
        self.initial_media_dir = self.options.initial_media_dir
        self.mon.log(self,"Data Home from options is "+self.pp_home_dir)
        self.mon.log(self,"Current Profiles Offset from options is "+self.pp_profiles_offset)
        self.mon.log(self,"Initial Media from options is "+self.initial_media_dir)
        self.pp_profile_dir=''
        self.osc_config_file = ''
        self.current_medialist=None
        self.current_showlist=None
        self.current_show=None
        self.shows_display.delete(0,END)
        self.medialists_display.delete(0,END)
        self.tracks_display.delete(0,END)



    # ***************************************
    # MISCELLANEOUS
    # ***************************************

    def edit_options(self):
        """edit the options then read them from file"""
        eo = OptionsDialog(self.root, self.options.options_file,'Edit Options')
        if eo.result is True: self.init()



    def show_help (self):
        tkMessageBox.showinfo("Help","Read 'manual.pdf'")
  

    def about (self):
        tkMessageBox.showinfo("About","Editor for Pi Presents Profiles\n"
                              +"For profile version: " + self.editor_issue + "\nAuthor: Ken Thompson"
                              +"\nWebsite: http://pipresents.wordpress.com/")

    def validate_profile(self):
        val =Validator()
        val.validate_profile(self.root,self.pp_dir,self.pp_home_dir,self.pp_profile_dir,self.editor_issue,True)


    # **************
    # OSC CONFIGURATION
    # **************

    def create_osc(self):
        if self.pp_profile_dir=='':
            return
        if self.osc_config.read(self.osc_config_file) is False:
            iodir=self.pp_profile_dir+os.sep+'pp_io_config'
            if not os.path.exists(iodir):
                os.makedirs(iodir)
            self.osc_config.create(self.osc_config_file)

    def edit_osc(self):
        if self.osc_config.read(self.osc_config_file) is False:
            # print 'no config file'
            return
        osc_ut=OSCUnitType(self.root,self.osc_config.this_unit_type)
        self.req_unit_type=osc_ut.result
        if self.req_unit_type != None:
            # print self.req_unit_type
            eosc = OSCEditor(self.root, self.osc_config_file,self.req_unit_type,'Edit OSC Configuration')
            
    def delete_osc(self):
        if self.osc_config.read(self.osc_config_file) is False:
            return
        os.rename(self.osc_config_file,self.osc_config_file+'.bak')
        

    
    # **************
    # PROFILES
    # **************

    def open_existing_profile(self):
        initial_dir=self.pp_home_dir+os.sep+"pp_profiles"+self.pp_profiles_offset
        if os.path.exists(initial_dir) is False:
            self.mon.err(self,"Profiles directory not found: " + initial_dir + "\n\nHint: Data Home option must end in pp_home")
            return
        dir_path=tkFileDialog.askdirectory(initialdir=initial_dir)
        # dir_path="C:\Users\Ken\pp_home\pp_profiles\\ttt"
        if len(dir_path)>0:
            self.open_profile(dir_path)
        

    def open_profile(self,dir_path):
        showlist_file = dir_path + os.sep + "pp_showlist.json"
        if os.path.exists(showlist_file) is False:
            self.mon.err(self,"Not a Profile: " + dir_path + "\n\nHint: Have you opened the profile directory?")
            return
        self.pp_profile_dir = dir_path
        self.root.title("Editor for Pi Presents - "+ self.pp_profile_dir)
        if self.open_showlist(self.pp_profile_dir) is False:
            self.init()
            return
        self.open_medialists(self.pp_profile_dir)
        self.refresh_tracks_display()
        self.osc_config_file=self.pp_profile_dir+os.sep+'pp_io_config'+os.sep+'osc.cfg'


    def new_profile(self,profile):
        d = Edit1Dialog(self.root,"New Profile","Name", "")
        if d .result  is  None:
            return
        name=str(d.result)
        if name == "":
            tkMessageBox.showwarning("New Profile","Name is blank")
            return
        to = self.pp_home_dir + os.sep + "pp_profiles"+ self.pp_profiles_offset + os.sep + name
        if os.path.exists(to) is  True:
            tkMessageBox.showwarning( "New Profile","Profile exists\n(%s)" % to )
            return
        shutil.copytree(profile, to, symlinks=False, ignore=None)
        self.open_profile(to)


        
    def new_exhibit_profile(self):
        profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_exhibit_1p3'
        self.new_profile(profile)

    def new_interactive_profile(self):
        profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_interactive_1p3'
        self.new_profile(profile)

    def new_menu_profile(self):
        profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_menu_1p3'
        self.new_profile(profile)

    def new_presentation_profile(self):
        profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_presentation_1p3'
        self.new_profile(profile)

    def new_blank_profile(self):
        profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep +"ppt_blank_1p3"
        self.new_profile(profile)

    def new_mediashow_profile(self):
        profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_mediashow_1p3'
        self.new_profile(profile)
        
    def new_liveshow_profile(self):
        profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_liveshow_1p3'
        self.new_profile(profile)

    def new_artmediashow_profile(self):
        profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_artmediashow_1p3'
        self.new_profile(profile)
        
    def new_artliveshow_profile(self):
        profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_artliveshow_1p3'
        self.new_profile(profile)

    def new_radiobuttonshow_profile(self):
        profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_radiobuttonshow_1p3'
        self.new_profile(profile)

    def new_hyperlinkshow_profile(self):
        profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_hyperlinkshow_1p3'
        self.new_profile(profile)

    # ***************************************
    # Shows
    # ***************************************

    def open_showlist(self,profile_dir):
        showlist_file = profile_dir + os.sep + "pp_showlist.json"
        if os.path.exists(showlist_file) is False:
            self.mon.err(self,"showlist file not found at " + profile_dir + "\n\nHint: Have you opened the profile directory?")
            self.app_exit()
        self.current_showlist=ShowList()
        self.current_showlist.open_json(showlist_file)
        if float(self.current_showlist.sissue())<float(self.editor_issue) or  (self.command_options['forceupdate']  is  True and float(self.current_showlist.sissue()) == float(self.editor_issue)):
            self.update_profile()
            self.mon.err(self,"Version of profile has been updated to "+self.editor_issue+", please re-open")
            return False
        if float(self.current_showlist.sissue())>float(self.editor_issue):
            self.mon.err(self,"Version of profile is greater than editor, must exit")
            self.app_exit()
        self.refresh_shows_display()
        return True


    def save_showlist(self,showlist_dir):
        if self.current_showlist is not None:
            showlist_file = showlist_dir + os.sep + "pp_showlist.json"
            self.current_showlist.save_list(showlist_file)
            
    def add_mediashow(self):
        self.add_show(PPdefinitions.new_shows['mediashow'])

    def add_liveshow(self):
        self.add_show(PPdefinitions.new_shows['liveshow'])

    def add_radiobuttonshow(self):
        self.add_show(PPdefinitions.new_shows['radiobuttonshow'])

    def add_hyperlinkshow(self):
        self.add_show(PPdefinitions.new_shows['hyperlinkshow'])

    def add_artliveshow(self):
        self.add_show(PPdefinitions.new_shows['artliveshow'])

    def add_artmediashow(self):
        self.add_show(PPdefinitions.new_shows['artmediashow'])
        
    def add_menushow(self):
        self.add_show(PPdefinitions.new_shows['menu'])

    def add_start(self):  
        self.add_show(PPdefinitions.new_shows['start'])


    def add_show(self,default):
        # append it to the showlist and then add the medialist
        if self.current_showlist is not None:
            d = Edit1Dialog(self.root,"AddShow","Show Reference", "")
            if d.result  is  None:
                return
            name=str(d.result)
            if name == "":
                tkMessageBox.showwarning("Add Show","Name is blank")
                return
                                         
            if self.current_showlist.index_of_show(name) != -1:
                tkMessageBox.showwarning("Add Show","A Show with this name already exists")
                return            
            copied_show=self.current_showlist.copy(default,name)
            mediafile=self.add_medialist(name)
            if mediafile != '':
                copied_show['medialist']=mediafile
            self.current_showlist.append(copied_show)
            self.save_showlist(self.pp_profile_dir)
            self.refresh_shows_display()

            
    def remove_show(self):
        if  self.current_showlist is not None and self.current_showlist.length()>0 and self.current_showlist.show_is_selected():
            if tkMessageBox.askokcancel("Delete Show","Delete Show"):
                index= self.current_showlist.selected_show_index()
                self.current_showlist.remove(index)
                self.save_showlist(self.pp_profile_dir)
                self.refresh_shows_display()

    def show_refs(self):
        _show_refs=[]
        for index in range(self.current_showlist.length()):
            if self.current_showlist.show(index)['show-ref'] != "start":
                _show_refs.append(copy.deepcopy(self.current_showlist.show(index)['show-ref']))
        return _show_refs
 
    def refresh_shows_display(self):
        self.shows_display.delete(0,self.shows_display.size())
        for index in range(self.current_showlist.length()):
            self.shows_display.insert(END, self.current_showlist.show(index)['title']+"   ["+self.current_showlist.show(index)['show-ref']+"]")        
        if self.current_showlist.show_is_selected():
            self.shows_display.itemconfig(self.current_showlist.selected_show_index(),fg='red')            
            self.shows_display.see(self.current_showlist.selected_show_index())

            
    def e_select_show(self,event):
        if self.current_showlist is not None and self.current_showlist.length()>0:
            mouse_item_index=int(event.widget.curselection()[0])
            self.current_showlist.select(mouse_item_index)
            self.refresh_shows_display()

    def copy_show(self):
        if  self.current_showlist is not None and self.current_showlist.show_is_selected():
            self.add_show(self.current_showlist.selected_show())

        
    def m_edit_show(self):
        self.edit_show(PPdefinitions.show_types,PPdefinitions.show_field_specs)
        
     

    def edit_show(self,show_types,field_specs):
        if self.current_showlist is not None and self.current_showlist.show_is_selected():
            d=EditItem(self.root,"Edit Show",self.current_showlist.selected_show(),show_types,field_specs,self.show_refs(),
                       self.initial_media_dir,self.pp_home_dir,'show')
            if d.result  is  True:

                self.save_showlist(self.pp_profile_dir)
                self.refresh_shows_display()

 

    # ***************************************
    #   Medialists
    # ***************************************

    def open_medialists(self,profile_dir):
        self.medialists = []
        for this_file in os.listdir(profile_dir):
            if this_file.endswith(".json") and this_file not in ('pp_showlist.json','schedule.json'):
                self.medialists = self.medialists + [this_file]
        self.medialists_display.delete(0,self.medialists_display.size())
        for index in range (len(self.medialists)):
            self.medialists_display.insert(END, self.medialists[index])
        self.current_medialists_index=-1
        self.current_medialist=None


    def add_medialist(self,name=None):
        if name is None:
            d = Edit1Dialog(self.root,"Add Medialist","File", "")
            if d.result  is  None:
                return ''
            name=str(d.result)
            if name == "":
                tkMessageBox.showwarning("Add medialist","Name is blank")
                return ''
            
        if not name.endswith(".json"):
            name=name+(".json")
                
        path = self.pp_profile_dir + os.sep + name
        if os.path.exists(path) is  True:
            tkMessageBox.showwarning("Add medialist","Medialist file exists\n(%s)" % path)
            return ''
        nfile = open(path,'wb')
        nfile.write("{")
        nfile.write("\"issue\":  \""+self.editor_issue+"\",\n")
        nfile.write("\"tracks\": [")
        nfile.write("]")
        nfile.write("}")
        nfile.close()
        # append it to the list
        self.medialists.append(copy.deepcopy(name))
        # add title to medialists display
        self.medialists_display.insert(END, name)  
        # and set it as the selected medialist
        self.refresh_medialists_display()
        return name


    def copy_medialist(self,to_file=None):
        if self.current_medialist is not None:
            #from_file= self.current_medialist 
            from_file= self.medialists[self.current_medialists_index]
            if to_file is None:
                d = Edit1Dialog(self.root,"Copy Medialist","File", "")
                if d.result  is  None:
                    return ''
                to_file=str(d.result)
                if to_file == "":
                    tkMessageBox.showwarning("Copy medialist","Name is blank")
                    return ''
                
            success_file = self.copy_medialist_file(from_file,to_file)
            if success_file =='':
                return ''

            # append it to the list
            self.medialists.append(copy.deepcopy(success_file))
            # add title to medialists display
            self.medialists_display.insert(END, success_file)
            # and reset  selected medialist
            self.current_medialist=None
            self.refresh_medialists_display()
            self.refresh_tracks_display()
            return success_file
        else:
            return ''

    def copy_medialist_file(self,from_file,to_file):
        if not to_file.endswith(".json"):
            to_file+=(".json")
                
        to_path = self.pp_profile_dir + os.sep + to_file
        if os.path.exists(to_path) is  True:
            tkMessageBox.showwarning("Copy medialist","Medialist file exists\n(%s)" % to_path)
            return ''
        
        from_path= self.pp_profile_dir + os.sep + from_file
        if os.path.exists(from_path) is  False:
            tkMessageBox.showwarning("Copy medialist","Medialist file not found\n(%s)" % from_path)
            return ''

        shutil.copy(from_path,to_path)
        return to_file


    def remove_medialist(self):
        if self.current_medialist is not None:
            if tkMessageBox.askokcancel("Delete Medialist","Delete Medialist"):
                os.remove(self.pp_profile_dir+ os.sep + self.medialists[self.current_medialists_index])
                self.open_medialists(self.pp_profile_dir)
                self.refresh_medialists_display()
                self.refresh_tracks_display()


    def select_medialist(self,event):
        """
        user clicks on a medialst in a profile so try and select it.
        """
        # needs forgiving int for possible tkinter upgrade
        if len(self.medialists)>0:
            self.current_medialists_index=int(event.widget.curselection()[0])
            self.current_medialist=MediaList('ordered')
            if not self.current_medialist.open_list(self.pp_profile_dir+ os.sep + self.medialists[self.current_medialists_index],self.current_showlist.sissue()):
                self.mon.err(self,"medialist is a different version to showlist: "+ self.medialists[self.current_medialists_index])
                self.app_exit()        
            self.refresh_tracks_display()
            self.refresh_medialists_display()


    def refresh_medialists_display(self):
        self.medialists_display.delete(0,len(self.medialists))
        for index in range (len(self.medialists)):
            self.medialists_display.insert(END, self.medialists[index])
        if self.current_medialist is not None:
            self.medialists_display.itemconfig(self.current_medialists_index,fg='red')
            self.medialists_display.see(self.current_medialists_index)

    def save_medialist(self):
        basefile=self.medialists[self.current_medialists_index]
        # print type(basefile)
        # basefile=str(basefile)
        # print type(basefile)
        medialist_file = self.pp_profile_dir+ os.sep + basefile
        self.current_medialist.save_list(medialist_file)

  
          
    # ***************************************
    #   Tracks
    # ***************************************
          
    def refresh_tracks_display(self):
        self.tracks_display.delete(0,self.tracks_display.size())
        if self.current_medialist is not None:
            for index in range(self.current_medialist.length()):
                if self.current_medialist.track(index)['track-ref'] != '':
                    track_ref_string="  ["+self.current_medialist.track(index)['track-ref']+"]"
                else:
                    track_ref_string=""
                self.tracks_display.insert(END, self.current_medialist.track(index)['title']+track_ref_string)        
            if self.current_medialist.track_is_selected():
                self.tracks_display.itemconfig(self.current_medialist.selected_track_index(),fg='red')            
                self.tracks_display.see(self.current_medialist.selected_track_index())
            
    def e_select_track(self,event):
        if self.current_medialist is not None and self.current_medialist.length()>0:
            mouse_item_index=int(event.widget.curselection()[0])
            self.current_medialist.select(mouse_item_index)
            self.refresh_tracks_display()

    def m_edit_track(self):
        self.edit_track(PPdefinitions.track_types,PPdefinitions.track_field_specs)

    def edit_track(self,track_types,field_specs):      
        if self.current_medialist is not None and self.current_medialist.track_is_selected():
            d=EditItem(self.root,"Edit Track",self.current_medialist.selected_track(),track_types,field_specs,
                       self.show_refs(),self.initial_media_dir,self.pp_home_dir,'track')
            if d.result  is  True:
                self.save_medialist()
            self.refresh_tracks_display()

    def move_track_up(self):
        if self.current_medialist is not None and self.current_medialist.track_is_selected():
            self.current_medialist.move_up()
            self.refresh_tracks_display()
            self.save_medialist()

    def move_track_down(self):
        if self.current_medialist is not None and self.current_medialist.track_is_selected():
            self.current_medialist.move_down()
            self.refresh_tracks_display()
            self.save_medialist()
        
    def new_track(self,fields,values):
        if self.current_medialist is not None:
            # print '\nfields ', fields
            # print '\nvalues ', values
            new_track=copy.deepcopy(fields)
            # print ',\new track ',new_track
            self.current_medialist.append(new_track)
            # print '\nbefore values ',self.current_medialist.print_list()
            if values is not None:
                self.current_medialist.update(self.current_medialist.length()-1,values)
            self.current_medialist.select(self.current_medialist.length()-1)
            self.refresh_tracks_display()
            self.save_medialist()

    def new_message_track(self):
        self.new_track(PPdefinitions.new_tracks['message'],None)
            
    def new_video_track(self):
        self.new_track(PPdefinitions.new_tracks['video'],None)
  
    def new_audio_track(self):
        self.new_track(PPdefinitions.new_tracks['audio'],None)

    def new_web_track(self):
        self.new_track(PPdefinitions.new_tracks['web'],None)
        
    def new_image_track(self):
        self.new_track(PPdefinitions.new_tracks['image'],None)

    def new_show_track(self):
        self.new_track(PPdefinitions.new_tracks['show'],None)

    def new_menu_track(self):
        self.new_track(PPdefinitions.new_tracks['menu'],None)
 
    def remove_track(self):
        if  self.current_medialist is not None and self.current_medialist.length()>0 and self.current_medialist.track_is_selected():
            if tkMessageBox.askokcancel("Delete Track","Delete Track"):
                index= self.current_medialist.selected_track_index()
                self.current_medialist.remove(index)
                self.save_medialist()
                self.refresh_tracks_display()
                
    def add_track_from_file(self):
        if self.current_medialist is None: return
        # print "initial directory ", self.options.initial_media_dir
        files_path=tkFileDialog.askopenfilename(initialdir=self.options.initial_media_dir, multiple=True)
        # fix for tkinter bug
        files_path =  self.root.tk.splitlist(files_path)
        for file_path in files_path:
            file_path=os.path.normpath(file_path)
            # print "file path ", file_path
            self.add_track(file_path)
        self.save_medialist()

    def add_tracks_from_dir(self):
        if self.current_medialist is None: return
        image_specs =[PPdefinitions.IMAGE_FILES,PPdefinitions.VIDEO_FILES,PPdefinitions.AUDIO_FILES,
                      PPdefinitions.WEB_FILES,('All files', '*')]
        # last one is ignored in finding files in directory, for dialog box only
        directory=tkFileDialog.askdirectory(initialdir=self.options.initial_media_dir)
        # deal with tuple returned on Cancel
        if len(directory) == 0: return
        # make list of exts we recognise
        exts = []
        for image_spec in image_specs[:-1]:
            image_list=image_spec[1:]
            for ext in image_list:
                exts.append(copy.deepcopy(ext))
        for this_file in os.listdir(directory):
            (root_file,ext_file)= os.path.splitext(this_file)
            if ext_file.lower() in exts:
                file_path=directory+os.sep+this_file
                # print "file path before ", file_path
                file_path=os.path.normpath(file_path)
                # print "file path after ", file_path
                self.add_track(file_path)
        self.save_medialist()


    def add_track(self,afile):
        relpath = os.path.relpath(afile,self.pp_home_dir)
        # print "relative path ",relpath
        common = os.path.commonprefix([afile,self.pp_home_dir])
        # print "common ",common
        if common.endswith("pp_home")  is  False:
            location = afile
        else:
            location = "+" + os.sep + relpath
            location = string.replace(location,'\\','/')
            # print "location ",location
        (root,title)=os.path.split(afile)
        (root,ext)= os.path.splitext(afile)
        if ext.lower() in PPdefinitions.IMAGE_FILES:
            self.new_track(PPdefinitions.new_tracks['image'],{'title':title,'track-ref':'','location':location})
        elif ext.lower() in PPdefinitions.VIDEO_FILES:
            self.new_track(PPdefinitions.new_tracks['video'],{'title':title,'track-ref':'','location':location})
        elif ext.lower() in PPdefinitions.AUDIO_FILES:
            self.new_track(PPdefinitions.new_tracks['audio'],{'title':title,'track-ref':'','location':location})
        elif ext.lower() in PPdefinitions.WEB_FILES:
            self.new_track(PPdefinitions.new_tracks['web'],{'title':title,'track-ref':'','location':location})
        else:
            self.mon.err(self,afile + " - cannot determine track type, use menu track>new")



    # *********************************************
    # UPDATE PROFILE
    # **********************************************

    def update_all(self):
        self.init()
        for profile_file in os.listdir(self.pp_home_dir+os.sep+'pp_profiles'+self.pp_profiles_offset):
            # self.mon.log (self,"Updating "+profile_file)
            self.pp_profile_dir = self.pp_home_dir+os.sep+'pp_profiles'+self.pp_profiles_offset + os.sep + profile_file
            if not os.path.exists(self.pp_profile_dir+os.sep+"pp_showlist.json"):
                tkMessageBox.showwarning("Pi Presents","Not a profile, skipping "+self.pp_profile_dir)
            else:
                self.current_showlist=ShowList()
                self.current_showlist.open_json(self.pp_profile_dir+os.sep+"pp_showlist.json")
                self.mon.log (self,"Version of profile "+ profile_file + ' is ' + self.current_showlist.sissue())
                if float(self.current_showlist.sissue())<float(self.editor_issue):
                    self.mon.log(self,"Version of profile "+profile_file+ "  is being updated to "+self.editor_issue)
                    self.update_profile()
                elif (self.command_options['forceupdate']  is  True and float(self.current_showlist.sissue()) == float(self.editor_issue)):
                    self.mon.log(self, "Forced updating of " + profile_file + ' to '+self.editor_issue)
                    self.update_profile()
                elif float(self.current_showlist.sissue())>float(self.editor_issue):
                    tkMessageBox.showwarning("Pi Presents", "Version of profile " +profile_file+ " is greater than editor, skipping")
                else:
                    self.mon.log(self," Skipping Profile " + profile_file + " It is already up to date ")
        self.init()
        tkMessageBox.showwarning("Pi Presents","All profiles updated")
            
    def update_profile(self):

        self.update_medialists()   # medialists and their tracks
        self.update_shows()         #shows in showlist, also creates menu tracks for 1.2>1.3
        

    def update_shows(self):
        # open showlist into a list of dictionaries
        self.mon.log (self,"Updating show ")
        ifile  = open(self.pp_profile_dir + os.sep + "pp_showlist.json", 'rb')
        shows = json.load(ifile)['shows']
        ifile.close()

        # special 1.2>1.3 create menu medialists with menu track from show
        #go through shows - if type = menu and version is greater copy its medialist to a new medialist with  name = <show-ref>-menu1p3.json
        for show in shows:
            #create a new medialist medialist != show-ref as menus can't now share medialists
            if show['type']=='menu' and float(self.current_showlist.sissue())<float(self.editor_issue):
                to_file=show['show-ref']+'-menu1p3.json'
                from_file = show['medialist']
                if to_file != from_file:
                    self.copy_medialist_file(from_file,to_file)
                else:
                    self.mon.warn(self, 'medialist file' + to_file + ' already exists, must exit with incomplete update')
                    return False

                #update the reference to the medialist
                show['medialist']=to_file
                
                #delete show fields so they are recreated with new default content
                del show['controls']
                
                # open the  medialist and add the menu track then populate some of its fields from the show
                ifile  = open(self.pp_profile_dir + os.sep + to_file, 'rb')
                tracks = json.load(ifile)['tracks']
                ifile.close()
                
                new_track=copy.deepcopy(PPdefinitions.new_tracks['menu'])
                tracks.append(copy.deepcopy(new_track))

                # copy menu parameters from menu show to menu track and init values of some              
                self.transfer_show_params(show,tracks,'menu-track',("entry-colour","entry-font", "entry-select-colour", 
                                                                    "hint-colour", "hint-font", "hint-text", "hint-x","hint-y",
                                                                    "menu-bullet", "menu-columns", "menu-direction", "menu-guidelines",
                                                                    "menu-horizontal-padding", "menu-horizontal-separation", "menu-icon-height", "menu-icon-mode",
                                                                    "menu-icon-width", "menu-rows", "menu-strip", "menu-strip-padding",  "menu-text-height", "menu-text-mode", "menu-text-width",
                                                                     "menu-vertical-padding", "menu-vertical-separation",
                                                                    "menu-window"))
                                          
                # and save the medialist
                dic={'issue':self.editor_issue,'tracks':tracks}
                ofile  = open(self.pp_profile_dir + os.sep + to_file, "wb")
                json.dump(dic,ofile,sort_keys=True,indent=1)
                # end for show in shows

        #update the fields in  all shows
        replacement_shows=self.update_shows_in_showlist(shows)
        dic={'issue':self.editor_issue,'shows':replacement_shows}
        ofile  = open(self.pp_profile_dir + os.sep + "pp_showlist.json", "wb")
        json.dump(dic,ofile,sort_keys=True,indent=1)
        return True


    def transfer_show_params(self,show,tracks,track_ref,fields):
        # find the menu track in medialist
        for index,track in enumerate(tracks):
            if track['track-ref']== 'menu-track':
                break
            
        #update some fields with new default content
        tracks[index]['links']=PPdefinitions.new_tracks['menu']['links']

        #transfer values from show to track
        for field in fields:
            tracks[index][field]=show[field]
            # print show[field], tracks[index][field]
            pass
            
        
                                          

    def update_medialists(self):
         # UPDATE MEDIALISTS AND THEIR TRACKS
        for this_file in os.listdir(self.pp_profile_dir):
            if this_file.endswith(".json") and this_file not in  ('pp_showlist.json','schedule.json'):
                self.mon.log (self,"Updating medialist " + this_file)
                # open a medialist and update its tracks
                ifile  = open(self.pp_profile_dir + os.sep + this_file, 'rb')
                tracks = json.load(ifile)['tracks']
                ifile.close()
                replacement_tracks=self.update_tracks(tracks)
                dic={'issue':self.editor_issue,'tracks':replacement_tracks}
                ofile  = open(self.pp_profile_dir + os.sep + this_file, "wb")
                json.dump(dic,ofile,sort_keys=True,indent=1)       



    def update_tracks(self,old_tracks):
        # get correct spec from type of field
        replacement_tracks=[]
        for old_track in old_tracks:
            # print '\nold track ',old_track
            track_type=old_track['type']
            #update if new tracks has the track type otherwise skip
            if track_type in PPdefinitions.new_tracks:
                spec_fields=PPdefinitions.new_tracks[track_type]
                left_overs=dict()
                # go through track and delete fields not in spec
                for key in old_track.keys():
                    if key in spec_fields:
                        left_overs[key]=old_track[key]
                # print '\n leftovers',left_overs
                replacement_track=copy.deepcopy(PPdefinitions.new_tracks[track_type])
                # print '\n before update', replacement_track
                replacement_track.update(left_overs)
                # print '\nafter update',replacement_track
                replacement_tracks.append(copy.deepcopy(replacement_track))
        return replacement_tracks


    def update_shows_in_showlist(self,old_shows):
        # get correct spec from type of field
        replacement_shows=[]
        for old_show in old_shows:
            show_type=old_show['type']
            ## menu to menushow
            spec_fields=PPdefinitions.new_shows[show_type]
            left_overs=dict()
            # go through track and delete fields not in spec
            for key in old_show.keys():
                if key in spec_fields:
                    left_overs[key]=old_show[key]
            # print '\n leftovers',left_overs
            replacement_show=copy.deepcopy(PPdefinitions.new_shows[show_type])
            replacement_show.update(left_overs)
            replacement_shows.append(copy.deepcopy(replacement_show))
        return replacement_shows                
class exo(Frame):
    """The base class for the exo_convert GUI"""
    
    # This is the constructor for the GUI
    def __init__(self,master=None):
        Frame.__init__(self,master)
        
        self.grid()
        
        for i in range(2):
            self.columnconfigure(i,minsize=10)
            self.rowconfigure(i,minsize=10)
         
        self.defineUnits()
        self.createWidgets()
        
        # Bind choice of variable (distance,mass,time)
        # Highlights variable selection and presents unit options
        self.inputlist.bind("<Button-1>",self.__varChoice)
    
        # Bind choice of unit (highlights unit selection)
        self.unitlist.bind("<Button-1>",self.__unitChoice)
    
        # Bind Entry of variable value to calculation
        self.inputfield.bind("<Return>",self.__calcConversion)
    
    # This function creates and defines the units
    
    def defineUnits(self):
        # Tuples which represent the various units allowed by each option
        
        # Distances
        
        self.distunits = ('pc','AU','Solar Radii','Jupiter Radii', 'Saturn Radii','Neptune Radii ','Earth Radii','Mars Radii', 'Moon Radii','cm')
        # All values in cm 
        self.distvalues = (3.08568025e18, 1.496e13, 6.995e10,7.1492e9,6.0268e9,2.4764e9,6.371e8,3.396e8,1.73814e8,1.0)
        
        # Masses
        
        self.massunits = ('Solar Masses', 'Jupiter Masses','Saturn Masses', 'Neptune Masses', 'Earth Masses', 'Mars Masses', 'Moon Masses',  'kg','g')
        # All values in g
        self.massvalues = (1.988920e33,1.8986e30,5.6834e29, 1.0243e29, 5.9736e27,6.4185e26, 7.3477e25, 1000.0,1.0)
        
        # Time
        
        self.timeunits = ('seconds','minutes' ,'hours', 'days','Martian sols','weeks', 'years', 'Mars years', 'Jupiter years')
        # All values in seconds
        self.timevalues = (1.0,60.0,3600.0, 86400.0,88775.244, 604800.0,31556926.0,59354294.4 , 374335776.0)
    
        # Keep the unit values in dictionaries, and use the above strings as keys
        
        self.distdict = {}        
        self.createUnitDict(self.distdict,self.distunits,self.distvalues)
        
        self.massdict = {}
        self.createUnitDict(self.massdict,self.massunits,self.massvalues)
        
        self.timedict = {}
        self.createUnitDict(self.timedict, self.timeunits, self.timevalues)  
    
        self.myunits = self.timeunits
        self.myvalues = self.timevalues
        self.mydict = self.timedict
        
        
    # This function creates a unit dictionary, with keys and unit values in cgs
    def createUnitDict(self,mydict,mykeys,myvalues):
        for i in range(len(myvalues)):
            mydict[mykeys[i]] = myvalues[i]
               
    # This function creates and adds all widgets to the GUI
    def createWidgets(self):
        
        # Create Widgets in order of appearance
        # This is not necessary, but makes code easier to read
        
        
        # Start with text telling user what to do
        self.varlabel = Text(self,height=1, width=20)
        self.varlabel.insert(END,"Which Variable?")
        
        # Place widget on the Frame according to a grid
        self.varlabel.grid(row=0,column=0,sticky=W)
        
        # Second text label asking user which units are being used
        
        self.unitlabel = Text(self,height=2,width=20)
        self.unitlabel.insert(END,"Which Units are you \nworking in?")
        self.unitlabel.grid(row=0,column=1,sticky=W)
        
        # Third text label asking user for numerical value
        
        self.numlabel = Text(self,height=1, width=20)
        self.numlabel.insert(END,"Enter Variable Value")
        self.numlabel.grid(row=0,column=2,sticky=W)
        
        # This creates a list of options for the user to select
        self.inputlist = Listbox(self, height=3, selectmode=SINGLE)
      
        # Tuple of choices we're going to put in this list
        paramlist = ('Distance', 'Time', 'Mass')
        
        # Add each item separately
        for item in paramlist:
            self.inputlist.insert(END,item)
            
        # Add it to the grid    
        self.inputlist.grid(row=1, sticky=W)
        
        # Add a unit list which produces a set of unit choices dependent on inputlist
        
        self.unitlist = Listbox(self, height=10,selectmode=SINGLE)
        self.unitlist.grid(row=1,column=1, sticky=W)
              
        # Number Entry Box
        self.inputfield = Entry(self)
        self.inputfield.insert(END, "0")
        self.inputfield.grid(row =1, column=2,sticky=W)
        
        
        # Text Output Box
        self.outputtext = Text(self, height=10)
        self.outputtext.grid(row=2,column=0,columnspan=3,sticky=W)
        self.outputtext.insert(END, "WAITING: ")
        # Create the Quit Button
        self.quitButton=Button(self,text='Quit',command=self.quit)
        self.quitButton.grid(row =3, column=0, sticky=W)
             

    # Event handler functions begin here    
    # This handler defines the choice of units available to the user, 
    # depending on selected variable
    
    def __varChoice(self, event):
        
        self.unitlist.delete(first=0,last=len(self.myvalues))
        num = 0
        try:
            num = self.inputlist.curselection()[0]       
            choice = int(num)
            
        except:
            choice = 0
            return
        
        # Highlight current choice in red
        self.inputlist.itemconfig(choice, selectbackground='red')
        
        if choice==0:
            #print 'Distance chosen'
            self.mydict=self.distdict
            self.myunits= self.distunits
            self.myvalues = self.distvalues
        elif choice==1:
            # print 'Time chosen'
            self.mydict=self.timedict
            self.myunits= self.timeunits
            self.myvalues = self.timevalues
        elif choice==2:
            # print 'Mass chosen'
            self.mydict=self.massdict
            self.myunits= self.massunits
            self.myvalues = self.massvalues
        
        # Add the units to the unitlist 
            
        for item in self.myunits:
            self.unitlist.insert(END,item)    
        del num
        
    def __unitChoice(self,event):
        num = 0
        try:
            num = self.unitlist.curselection()[0]       
            choice = int(num)
            
        except:
            choice = 0
            return
        
        # Highlight current choice in red
        self.unitlist.itemconfig(choice, selectbackground='red')
        
        
    # Handler takes current state of GUI, and calculates results
    def __calcConversion(self,event):
        
        num = 0
        # What units are being used?
        try:       
            num = self.unitlist.curselection()[0]       
            choice = int(num)
        except:
            choice = 0
            return
        
        self.outputtext.delete("1.0",index2=END)
        # Highlight current choice in red
        self.unitlist.itemconfig(choice, selectbackground='red')
          
        # What is the value in the entry field?
        value = self.inputfield.get()
        value = float(value)
 
        # Now perform calculation using dictionary 
 
        var = self.unitlist.get(choice)
       
        # Convert value to cgs
        
        value = value*self.mydict[var]
        
        # Create a new list of output answers
        
        output=[]
        self.outputtext.insert(END,"OUTPUT:    \n\n")
        
        # Calculate and output it to the GUI
        for i in range(len(self.myvalues)):
            output.append(value/self.myvalues[i])
            self.outputtext.insert(END,self.myunits[i] + ":  "+str(output[i])+"\n")    
Example #14
0
class OSCRemote(object):

    def __init__(self):
    
        self.editor_issue="1.3"

        # get command options
        self.command_options=remote_options()

        # get directory holding the code
        self.pp_dir=sys.path[0]
            
        if not os.path.exists(self.pp_dir+os.sep+"pp_oscremote.py"):
            tkMessageBox.showwarning("Pi Presents","Bad Application Directory")
            exit()
            
          
        # Initialise logging
        Monitor.log_path=self.pp_dir
        self.mon=Monitor()
        self.mon.init()
        
        Monitor.classes  = ['OSCRemote','OSCConfig','OSCEditor']

        Monitor.log_level = int(self.command_options['debug'])

        self.mon.log (self, "Pi Presents Remote is starting")
        self.mon.log (self," OS and separator " + os.name +'  ' + os.sep)
        self.mon.log(self,"sys.path[0] -  location of code: code "+sys.path[0])

        self.setup_gui()

        # OSC config class
        self.osc_config=OSCConfig()

        self.init()

        #and start the system
        self.root.after(1000,self.run_app)
        self.root.mainloop()


    def init(self):
        self.osc_config_file = self.pp_dir + os.sep + 'pp_config' + os.sep + 'pp_oscremote.cfg'
        self.read_create_osc()
        self.pp_home_dir = self.osc_config.pp_home_dir
        self.pp_profiles_offset = self.osc_config.pp_profiles_offset
        self.mon.log(self,"Data Home from options is "+self.pp_home_dir)
        self.mon.log(self,"Current Profiles Offset from options is "+self.pp_profiles_offset)
        self.pp_profile_dir=''

        self.current_showlist=None
        self.current_show=None
        self.current_show_ref=''
        self.shows_display.delete(0,END)
        self.results.set('')

        
    def add_status(self,text):
        self.status_display.insert(END,text+'\n')
        self.status_display.see(END)

    def run_app(self):
        self.client=None
        self.server=None
        self.st=None
        
        # initialise OSC variables
        self.prefix='/pipresents'
        self.this_unit='/' + self.osc_config.this_unit_name
        self.add_status('this unit is: '+self.this_unit)
        self.controlled_unit='/'+self.osc_config.controlled_unit_1_name
        self.add_status('controlled unit is: '+self.controlled_unit)
       
        #connect client then start server to listen for replies
        self.init_client()
        self.add_status('connecting to controlled unit: '+self.osc_config.controlled_unit_1_ip+':'+self.osc_config.controlled_unit_1_port +' '+self.osc_config.controlled_unit_1_name)
        self.connect_client(self.osc_config.controlled_unit_1_ip,self.osc_config.controlled_unit_1_port)
        self.add_status('listening for replies on:'+self.osc_config.this_unit_ip+':'+self.osc_config.this_unit_port)
        self.init_server(self.osc_config.this_unit_ip,self.osc_config.this_unit_port,self.client)
        self.add_initial_handlers()
        self.start_server()


# ***************************************
#  RESPOND TO BUTTONS
# ***************************************

    def open_show(self):
        self.msg_path= '/core/open '
        self.msg_arg_text= self.current_show_ref
        self.display_msg_text()


    def close_show(self):
        self.msg_path= '/core/close '
        self.msg_arg_text=self.current_show_ref
        self.display_msg_text()


    def exit_pipresents(self):
        self.msg_path= '/core/exitpipresents'
        self.msg_arg_text=''
        self.display_msg_text()

    
    def play_event(self):
        self.msg_path= '/core/event'
        self.msg_arg_text = 'pp-play'
        self.display_msg_text()


    def pause_event(self):
        self.msg_path= '/core/event'
        self.msg_arg_text='pp-pause'
        self.display_msg_text()
        pass

    def stop_event(self):
        self.msg_path= '/core/event'
        self.msg_arg_text='pp-stop'
        self.display_msg_text()
        pass
    
    def up_event(self):
        self.msg_path= '/core/event'
        self.msg_arg_text='pp-up'
        self.display_msg_text()


    def down_event(self):
        self.msg_path= '/core/event'
        self.msg_arg_text='pp-down'
        self.display_msg_text()


    def output(self):
        self.msg_path= '/core/output'
        self.msg_arg_text=''
        self.display_msg_text()

    def loopback(self):
        self.msg_path= '/system/loopback'
        self.msg_arg_text=''
        self.display_msg_text()        


    def server_info(self):
        self.msg_path= '/system/server-info'
        self.msg_arg_text=''
        self.display_msg_text()         


    # and put the created text in the results box in the gui
    def display_msg_text(self):
        self.results.set(self.prefix+self.controlled_unit+self.msg_path+' '+self.msg_arg_text)


    #calback from the Send button
    # parses the message string into fields and sends - NO error checking
    def send_message(self):
        msg_text=self.results.get()
        self.add_status('Send message:'+msg_text)
        self.mon.log(self,'send message: ' + msg_text )
        fields=msg_text.split()
        address = fields[0]
        arg_list=fields[1:]
        self.send(address,arg_list)


    # ***************************************
    # OSC CLIENT TO SEND MESSAGES
    # ***************************************

    def init_client(self):
       self.client = OSC.OSCClient()

    def connect_client(self,ip,port):
        self.mon.log(self,'connect to: '+ip+':'+str(port))
        self.client.connect( (ip, int(port)) ) 


    def send(self,address,arg_list):
        msg = OSC.OSCMessage()
        msg.setAddress(address)
        for arg in arg_list:
            msg.append(arg)
        self.client.send(msg)    


    def disconnect_client(self):
        self.client.close()
        return


    # ***************************************
    # OSC SERVER TO LISTEN TO REPLIES
    # ***************************************

    def init_server(self,ip,port_text,client):
        self.mon.log(self,'Start Server: '+ip+':'+port_text)
        self.server = OSC.OSCServer((ip,int(port_text)),client)

    def start_server(self):
        self.st = threading.Thread( target = self.server.serve_forever )
        self.st.start()

    def close_server(self):
        if self.server != None:
            self.server.close()
        self.mon.log(self, 'Waiting for Server-thread to finish')
        if self.st != None:
            self.st.join() ##!!!
        self.mon.log(self,'server thread closed')


    def add_initial_handlers(self):
        self.server.addMsgHandler('default', self.no_match_handler)     
        self.server.addMsgHandler(self.prefix+self.this_unit+"/system/loopback-reply", self.loopback_reply_handler)
        self.server.addMsgHandler(self.prefix+self.this_unit+"/system/server-info-reply", self.server_info_reply_handler)

    def no_match_handler(self,addr, tags, stuff, source):
        text=''
        text+= "no match for new osc msg from %s" % OSC.getUrlStr(source)+'\n'
        text+= "with addr : %s" % addr+'\n'
        text+= "typetags %s" % tags+'\n'
        text+= "data %s" % stuff+'\n'
        self.add_status(text+'\n')

        
    def loopback_reply_handler(self,addr, tags, stuff, source):
        self.add_status('Loopback reply  received from: '+  self.pretty_list(source))


    def server_info_reply_handler(self,addr, tags, stuff, source):
        self.add_status('Server Information from: '+  self.pretty_list(source)  + '\n   ' + self.pretty_list(stuff))


    def pretty_list(self,fields):
        text=' '
        for field in fields:
            text += str(field) + ' '
        return text


    # ***************************************
    # INIT EXIT MISC
    # ***************************************

    def e_edit_osc(self):
        self.disconnect_client()
        self.close_server()
        self.edit_osc()
        self.init()
        self.add_status('\n\n\nRESTART')
        self.run_app()


    def app_exit(self):
        self.disconnect_client()
        self.close_server()
        if self.root is not None:
            self.root.destroy()
        self.mon.finish()
        sys.exit() 


    def show_help (self):
        tkMessageBox.showinfo("Help","Read 'manual.pdf'")
  

    def about (self):
        tkMessageBox.showinfo("About","Simple Remote Control for Pi Presents\n"
                              +"Author: Ken Thompson"
                              +"\nWebsite: http://pipresents.wordpress.com/")


    def setup_gui(self):
        # set up the gui
 
        # root is the Tkinter root widget
        self.root = Tk()
        self.root.title("Remote Control for Pi Presents")

        # self.root.configure(background='grey')

        self.root.resizable(False,False)

        # define response to main window closing
        self.root.protocol ("WM_DELETE_WINDOW", self.app_exit)

        # bind some display fields
        self.filename = StringVar()
        self.display_show = StringVar()
        self.results = StringVar()
        self.status = StringVar()

        # define menu
        menubar = Menu(self.root)

        profilemenu = Menu(menubar, tearoff=0, bg="grey", fg="black")
        profilemenu.add_command(label='Select', command = self.open_existing_profile)
        menubar.add_cascade(label='Profile', menu = profilemenu)

        
        toolsmenu = Menu(menubar, tearoff=0, bg="grey", fg="black")
        menubar.add_cascade(label='Tools', menu = toolsmenu)

        osc_configmenu = Menu(menubar, tearoff=0, bg="grey", fg="black")
        menubar.add_cascade(label='OSC', menu = osc_configmenu)
        osc_configmenu.add_command(label='Edit', command = self.e_edit_osc)

        helpmenu = Menu(menubar, tearoff=0, bg="grey", fg="black")
        menubar.add_cascade(label='Help', menu = helpmenu)
        helpmenu.add_command(label='Help', command = self.show_help)
        helpmenu.add_command(label='About', command = self.about)
         
        self.root.config(menu=menubar)



        #top frame
        top_frame=Frame(self.root,padx=5,pady=5)
        top_frame.pack(side=TOP)
        
        results_label = Label(top_frame, text="Message to Send",font="arial 12 bold")
        results_label.pack(side=LEFT)
        results_display=Entry(top_frame, textvariable=self.results, width=70)
        results_display.pack(side=LEFT,fill=BOTH, expand=1)
        send_button = Button(top_frame, width = 5, height = 1, text='Send',
                            fg='black', command = self.send_message, bg="light grey")
        send_button.pack(side=RIGHT)

        #bottom frame
        bottom_frame=Frame(self.root,padx=5,pady=5)
        bottom_frame.pack(side=TOP, fill=BOTH, expand=1) 
        left_frame=Frame(bottom_frame, padx=5)
        left_frame.pack(side=LEFT)            
        right_frame=Frame(bottom_frame,padx=5,pady=5)
        right_frame.pack(side=LEFT)

        suplabel_frame=Frame(right_frame,pady=5)
        suplabel_frame.pack(side=TOP)
        commands_label = Label(suplabel_frame, text="Show Control",font="arial 12 bold")
        commands_label.pack()
                            
        supervisor_frame=Frame(right_frame,pady=5)
        supervisor_frame.pack(side=TOP)

        # supervisor buttons 
        add_button = Button(supervisor_frame, width = 5, height = 1, text='Open\nShow',
                            fg='black', command = self.open_show, bg="light grey")
        add_button.pack(side=LEFT)
        add_button = Button(supervisor_frame, width = 5, height = 1, text='Close\nShow',
                            fg='black', command = self.close_show, bg="light grey")
        add_button.pack(side=LEFT)
        add_button = Button(supervisor_frame, width = 10, height = 1, text='Exit\nPi Presents',
                            fg='black', command = self.exit_pipresents, bg="light grey")
        add_button.pack(side=LEFT)

        # events buttons        
        oplabel_frame=Frame(right_frame,pady=5)
        oplabel_frame.pack(side=TOP)
        operations_label = Label(oplabel_frame, text="Input Events",
                                 font="arial 12 bold")
        operations_label.pack()
        
        operations_frame=Frame(right_frame,pady=5)
        operations_frame.pack(side=TOP)
                              
        add_button = Button(operations_frame, width = 5, height = 1, text='Play',
                            fg='black', command = self.play_event, bg="light grey")
        add_button.pack(side=LEFT)   
        add_button = Button(operations_frame, width = 5, height = 1, text='Pause',
                            fg='black', command = self.pause_event, bg="light grey")
        add_button.pack(side=LEFT)
        add_button = Button(operations_frame, width = 5, height = 1, text='Stop',
                            fg='black', command = self.stop_event, bg="light grey")
        add_button.pack(side=LEFT)
        add_button = Button(operations_frame, width = 5, height = 1, text='Up',
                            fg='black', command = self.up_event, bg="light grey")
        add_button.pack(side=LEFT)
        add_button = Button(operations_frame, width = 5, height = 1, text='Down',
                            fg='black', command = self.down_event, bg="light grey")
        add_button.pack(side=LEFT)


        # animate buttons        
        animate_frame=Frame(right_frame,pady=5)
        animate_frame.pack(side=TOP)
        animate_label = Label(animate_frame, text="Control Outputs",
                                 font="arial 12 bold")
        animate_label.pack()
        
        animate_frame=Frame(right_frame,pady=5)
        animate_frame.pack(side=TOP)
                              
        add_button = Button(animate_frame, width = 5, height = 1, text='Output',
                            fg='black', command = self.output, bg="light grey")
        add_button.pack(side=LEFT)  

        
        # system buttons        
        systemlabel_frame=Frame(right_frame,pady=5)
        systemlabel_frame.pack(side=TOP)
        system_label = Label(systemlabel_frame, text="System",
                                 font="arial 12 bold")
        system_label.pack()
        
        system_frame=Frame(right_frame,pady=5)
        system_frame.pack(side=TOP)
                              
        add_button = Button(system_frame, width = 5, height = 1, text='Loopback',
                            fg='black', command = self.loopback, bg="light grey")
        add_button.pack(side=LEFT)   
        add_button = Button(system_frame, width = 10, height = 1, text='Server Info',
                            fg='black', command = self.server_info, bg="light grey")
        add_button.pack(side=LEFT)



        # define display of showlist
        shows_title_frame=Frame(left_frame)
        shows_title_frame.pack(side=TOP)
        shows_label = Label(shows_title_frame, text="Shows")
        shows_label.pack()
        shows_frame=Frame(left_frame)
        shows_frame.pack(side=TOP)
        scrollbar = Scrollbar(shows_frame, orient=VERTICAL)
        self.shows_display = Listbox(shows_frame, selectmode=SINGLE, height=12,
                                     width = 40, bg="white",activestyle=NONE,
                                     fg="black", yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.shows_display.yview)
        scrollbar.pack(side=RIGHT, fill=Y)
        self.shows_display.pack(side=LEFT, fill=BOTH, expand=1)
        self.shows_display.bind("<ButtonRelease-1>", self.e_select_show)


        # status_frame      
        status_frame=Frame(self.root,padx=5,pady=5)
        status_frame.pack(side=TOP, fill=BOTH, expand=1)
        status_label = Label(status_frame, text="Status",font="arial 12 bold")
        status_label.pack(side=LEFT)
        scrollbar = Scrollbar(status_frame, orient=VERTICAL)
        self.status_display=Text(status_frame,height=10, yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.status_display.yview)
        scrollbar.pack(side=RIGHT, fill=Y)
        self.status_display.pack(side=LEFT,fill=BOTH, expand=1)


    # ***************************************
    # SHOWLIST
    # ***************************************

    def open_existing_profile(self):
        initial_dir=self.pp_home_dir+os.sep+"pp_profiles"+self.pp_profiles_offset
        if os.path.exists(initial_dir) is False:
            self.mon.err(self,"Profiles directory not found: " + initial_dir + "\n\nHint: Data Home option must end in pp_home")
            return
        dir_path=tkFileDialog.askdirectory(initialdir=initial_dir)
        # dir_path="C:\Users\Ken\pp_home\pp_profiles\\ttt"
        if len(dir_path)>0:
            self.open_profile(dir_path)

    def open_profile(self,dir_path):
        showlist_file = dir_path + os.sep + "pp_showlist.json"
        if os.path.exists(showlist_file) is False:
            self.mon.err(self,"Not a Profile: " + dir_path + "\n\nHint: Have you opened the profile directory?")
            return
        self.pp_profile_dir = dir_path
        self.root.title("Remote for Pi Presents - "+ self.pp_profile_dir)
        self.open_showlist(self.pp_profile_dir)

    def open_showlist(self,profile_dir):
        showlist_file = profile_dir + os.sep + "pp_showlist.json"
        if os.path.exists(showlist_file) is False:
            self.mon.err(self,"showlist file not found at " + profile_dir + "\n\nHint: Have you opened the profile directory?")
            self.app_exit()
        self.current_showlist=ShowList()
        self.current_showlist.open_json(showlist_file)
        if float(self.current_showlist.sissue()) != float(self.editor_issue):
            self.mon.err(self,"Version of profile does not match Remote: "+self.editor_issue)
            self.app_exit()
        self.refresh_shows_display()


    def refresh_shows_display(self):
        self.shows_display.delete(0,self.shows_display.size())
        for index in range(self.current_showlist.length()):
            self.shows_display.insert(END, self.current_showlist.show(index)['title']+"   ["+self.current_showlist.show(index)['show-ref']+"]")        
        if self.current_showlist.show_is_selected():
            self.shows_display.itemconfig(self.current_showlist.selected_show_index(),fg='red')            
            self.shows_display.see(self.current_showlist.selected_show_index())

    def e_select_show(self,event):
        print 'select show', self.current_showlist.length()
        if self.current_showlist is not None and self.current_showlist.length()>0:
            mouse_item_index=int(event.widget.curselection()[0])
            self.current_showlist.select(mouse_item_index)
            self.current_show_ref=self.current_showlist.selected_show()['show-ref']
            self.refresh_shows_display()
        else:
            self.current_show_ref=''


# ***************************************
#  OSC CONFIGURATION
# ***************************************

    def read_create_osc(self):
        if self.osc_config.read(self.osc_config_file) is False:
            self.osc_config.create(self.osc_config_file)
            eosc = OSCEditor(self.root, self.osc_config_file,'remote','Create OSC Remote Configuration')
            self.osc_config.read(self.osc_config_file)


    def edit_osc(self):
        if self.osc_config.read(self.osc_config_file) is False:
            self.osc_config.create(self.osc_config_file)
        eosc = OSCEditor(self.root, self.osc_config_file,'remote','Edit OSC Reomote Configuration')
Example #15
0
class StatePopup(object):
    def __init__(self, master, default_value, state_probs):
        top = self.top = Toplevel(master.canvas)
        self.master = master

        self.l = Label(top, text="New State")
        self.l.grid(row=0, column=0, columnspan=2)

        self.lb = Listbox(
            top
        )  # OptionMenu(top, Tkinter.StringVar().set(self.states[-1]), *self.states)
        self.lb.insert("end", "0")
        for i, (state,
                color) in enumerate(self.master.trail.colorlist.items()):
            str = ",".join(["{:x}".format(x) for x in state])
            self.lb.insert("end", str)
            self.lb.itemconfig(i + 1, {"bg": color})
        self.lb.grid(row=1, column=1, padx=MARGIN_LR / 2, pady=MARGIN_TB)
        self.lb.config(height=5, width=8)
        self.lb.bind(
            "<Double-Button-1>",
            lambda x: self.set_text(self.lb.get(self.lb.curselection())))

        self.e = Entry(top)
        self.e.insert(0, default_value)
        self.e.bind("<Control-KeyRelease-a>", lambda x: self.select_all())
        self.e.grid(row=1,
                    column=0,
                    sticky=N,
                    padx=MARGIN_LR / 2,
                    pady=MARGIN_TB)
        self.e.select_range(0, 'end')
        self.e.icursor('end')
        self.e.focus()

        self.b = Button(top, text='Ok', command=self.check_cleanup)
        self.top.protocol("WM_DELETE_WINDOW", self.close)
        self.b.grid(row=3, column=0, columnspan=2)

        self.l2 = Label(top, text="Probabilities")
        self.l2.grid(row=4, column=0, columnspan=2)
        for i, x in enumerate(state_probs):
            # if x > 0:
            #    l = Label(top, text=hex(i)[2:] + ":" + str(x))
            #    l.pack()
            pass

        self.top.bind("<Return>", lambda x: self.check_cleanup())
        self.top.bind("<Escape>", lambda x: self.close())
        self.value = None
        self.top.wait_visibility()
        # stop interaction in other gui
        self.top.grab_set()

    def set_text(self, text):
        self.e.delete(0, 'end')
        self.e.insert(0, text)

    def select_all(event):
        event.e.select_range(0, 'end')
        # move cursor to the end
        event.e.icursor('end')
        return 'break'

    def check_cleanup(self):
        newstate = self.e.get()
        if newstate == "":
            self.value = range(
                0, 2**(self.master.trail.statebitsize /
                       self.master.trail.statesize))
        elif newstate == "*":
            self.value = range(
                1, 2**(self.master.trail.statebitsize /
                       self.master.trail.statesize))
        else:
            try:
                state = []
                for x in newstate.split(","):
                    x = x.strip()
                    x = int(x, 16)
                    assert x < 2**(self.master.trail.statebitsize /
                                   self.master.trail.statesize)
                    state.append(x)
                assert len(state) > 0
                self.value = state
            except Exception as e:
                print "Exception: " + str(e)
                self.value = None
                return

        self.close()

    def close(self):
        self.top.grab_release()
        self.top.destroy()