Пример #1
0
class PPEditor:

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

    def __init__(self):

        self.editor_issue = "1.2"

        # 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.on()

        if self.command_options['debug'] == True:
            Monitor.global_enable = True
        else:
            Monitor.global_enable = False

        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.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 = tk.StringVar()
        self.display_selected_track_title = tk.StringVar()
        self.display_show = tk.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='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='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_menu)
        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)
        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)

        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 Background',
                             command=self.new_menu_background_track)
        typemenu.add_command(label='Child Show',
                             command=self.new_child_show_track)
        trackmenu.add_cascade(label='New', menu=typemenu)

        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=tk.VERTICAL)
        self.shows_display = Listbox(shows_frame,
                                     selectmode=SINGLE,
                                     height=7,
                                     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=tk.VERTICAL)
        self.medialists_display = Listbox(medialists_frame,
                                          selectmode=SINGLE,
                                          height=7,
                                          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=tk.VERTICAL)
        self.tracks_display = Listbox(tracks_frame,
                                      selectmode=SINGLE,
                                      height=15,
                                      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
        self.options = Options(
            self.pp_dir)  #creates options file in code directory if necessary

        # 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.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,
                     "Initial Media from options is " + self.initial_media_dir)
        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 == 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)

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

    def open_existing_profile(self):
        initial_dir = self.pp_home_dir + os.sep + "pp_profiles"
        if os.path.exists(initial_dir) == False:
            self.mon.err(
                self, "Home 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) == 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) == False:
            self.init()
            return
        self.open_medialists(self.pp_profile_dir)
        self.refresh_tracks_display()

    def new_profile(self, profile):
        d = Edit1Dialog(self.root, "New Profile", "Name", "")
        if d.result == 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" + os.sep + name
        if os.path.exists(to) == 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 + "/pp_home/pp_profiles/ppt_exhibit"
        self.new_profile(profile)

    def new_interactive_profile(self):
        profile = self.pp_dir + "/pp_home/pp_profiles/ppt_interactive"
        self.new_profile(profile)

    def new_menu_profile(self):
        profile = self.pp_dir + "/pp_home/pp_profiles/ppt_menu"
        self.new_profile(profile)

    def new_presentation_profile(self):
        profile = self.pp_dir + "/pp_home/pp_profiles/ppt_presentation"
        self.new_profile(profile)

    def new_blank_profile(self):
        profile = self.pp_dir + "/pp_home/pp_profiles/ppt_blank"
        self.new_profile(profile)

    def new_mediashow_profile(self):
        profile = self.pp_dir + "/pp_home/pp_profiles/ppt_mediashow"
        self.new_profile(profile)

    def new_liveshow_profile(self):
        profile = self.pp_dir + "/pp_home/pp_profiles/ppt_liveshow"
        self.new_profile(profile)

    def new_radiobuttonshow_profile(self):
        profile = self.pp_dir + "/pp_home/pp_profiles/ppt_radiobuttonshow"
        self.new_profile(profile)

    def new_hyperlinkshow_profile(self):
        profile = self.pp_dir + "/pp_home/pp_profiles/ppt_hyperlinkshow"
        self.new_profile(profile)

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

    def open_showlist(self, dir):
        showlist_file = dir + os.sep + "pp_showlist.json"
        if os.path.exists(showlist_file) == False:
            self.mon.err(
                self, "showlist file not found at " + 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'] == 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, dir):
        if self.current_showlist <> None:
            showlist_file = dir + os.sep + "pp_showlist.json"
            self.current_showlist.save_list(showlist_file)

    def add_eventshow(self):
        self.add_show(PPdefinitions.new_shows['eventshow'])

    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_menu(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 <> None:
            d = Edit1Dialog(self.root, "AddShow", "Show Reference", "")
            if d.result == 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 <> 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 <> 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 <> 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 <> 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 == True:

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

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

    def open_medialists(self, dir):
        self.medialists = []
        for file in os.listdir(dir):
            if file.endswith(".json") and file <> 'pp_showlist.json':
                self.medialists = self.medialists + [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 == None:
            d = Edit1Dialog(self.root, "Add Medialist", "File", "")
            if d.result == 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) == 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 remove_medialist(self):
        if self.current_medialist <> 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 <> 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)
        file = self.pp_profile_dir + os.sep + basefile
        self.current_medialist.save_list(file)

# ***************************************
#   Tracks
# ***************************************

    def refresh_tracks_display(self):
        self.tracks_display.delete(0, self.tracks_display.size())
        if self.current_medialist <> 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 <> 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 <> 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 == True:
                self.save_medialist()
            self.refresh_tracks_display()

    def move_track_up(self):
        if self.current_medialist <> 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 <> 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 <> 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 <> 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_background_track(self):
        self.new_track(PPdefinitions.new_tracks['menu-background'], None)

    def new_child_show_track(self):
        self.new_track(PPdefinitions.new_tracks['child-show'], None)

    def remove_track(self):
        if self.current_medialist <> 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 == 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 == 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 file in os.listdir(directory):
            (root_file, ext_file) = os.path.splitext(file)
            if ext_file.lower() in exts:
                file_path = directory + os.sep + 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") == 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 + " - file extension not recognised")

# *********************************************
# update profile
# **********************************************

    def update_all(self):
        self.init()
        for profile_file in os.listdir(self.pp_home_dir + os.sep +
                                       'pp_profiles'):
            # self.mon.log (self,"Updating "+profile_file)
            self.pp_profile_dir = self.pp_home_dir + os.sep + 'pp_profiles' + 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.mon.log (self,"Checking version "+profile_file)
                self.current_showlist.open_json(self.pp_profile_dir + os.sep +
                                                "pp_showlist.json")
                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'] == 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,
                        " Profile " + profile_file + " Already up to date ")
        self.init()
        tkMessageBox.showwarning("Pi Presents", "All profiles updated")

    def update_profile(self):
        #open showlist and update its shows
        # 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()
        replacement_shows = self.update_shows(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)

        # UPDATE MEDIALISTS AND THEIR TRACKS
        for file in os.listdir(self.pp_profile_dir):
            if file.endswith(".json") and file <> 'pp_showlist.json':
                # self.mon.log (self,"Updating medialist " + file)
                #open a medialist and update its tracks
                ifile = open(self.pp_profile_dir + os.sep + 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 + 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']
            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(self, old_shows):
        # get correct spec from type of field
        replacement_shows = []
        for old_show in old_shows:
            show_type = old_show['type']
            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
Пример #2
0
class PPEditor:



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

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

# 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.on()

        if self.command_options['debug'] == True:
            Monitor.global_enable=True
        else:
            Monitor.global_enable=False

        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.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 = tk.StringVar()
        self.display_selected_track_title = tk.StringVar()
        self.display_show = tk.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='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='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_menu)
        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)
        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)
      
        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 Background', command = self.new_menu_background_track)
        typemenu.add_command(label='Child Show', command = self.new_child_show_track)
        trackmenu.add_cascade(label='New', menu = typemenu)

        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=tk.VERTICAL)
        self.shows_display = Listbox(shows_frame, selectmode=SINGLE, height=7,
                                    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=tk.VERTICAL)
        self.medialists_display = Listbox(medialists_frame, selectmode=SINGLE, height=7,
                                    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=tk.VERTICAL)
        self.tracks_display = Listbox(tracks_frame, selectmode=SINGLE, height=15,
                                    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
        self.options=Options(self.pp_dir) #creates options file in code directory if necessary
        
# 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.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,"Initial Media from options is "+self.initial_media_dir)
        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==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)


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

    def open_existing_profile(self):
        initial_dir=self.pp_home_dir+os.sep+"pp_profiles"
        if os.path.exists(initial_dir)==False:
            self.mon.err(self,"Home 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)==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)==False:
            self.init()
            return
        self.open_medialists(self.pp_profile_dir)
        self.refresh_tracks_display()


    def new_profile(self,profile):
        d = Edit1Dialog(self.root,"New Profile","Name", "")
        if d .result == 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"+ os.sep + name
        if os.path.exists(to)== 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+"/pp_home/pp_profiles/ppt_exhibit"
        self.new_profile(profile)

    def new_interactive_profile(self):
        profile = self.pp_dir+"/pp_home/pp_profiles/ppt_interactive"
        self.new_profile(profile)

    def new_menu_profile(self):
        profile = self.pp_dir+"/pp_home/pp_profiles/ppt_menu"
        self.new_profile(profile)

    def new_presentation_profile(self):
        profile = self.pp_dir+"/pp_home/pp_profiles/ppt_presentation"
        self.new_profile(profile)

    def new_blank_profile(self):
        profile = self.pp_dir+"/pp_home/pp_profiles/ppt_blank"
        self.new_profile(profile)

    def new_mediashow_profile(self):
        profile = self.pp_dir+"/pp_home/pp_profiles/ppt_mediashow"
        self.new_profile(profile)
        
    def new_liveshow_profile(self):
        profile = self.pp_dir+"/pp_home/pp_profiles/ppt_liveshow"
        self.new_profile(profile)

    def new_radiobuttonshow_profile(self):
        profile = self.pp_dir+"/pp_home/pp_profiles/ppt_radiobuttonshow"
        self.new_profile(profile)

    def new_hyperlinkshow_profile(self):
        profile = self.pp_dir+"/pp_home/pp_profiles/ppt_hyperlinkshow"
        self.new_profile(profile)

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

    def open_showlist(self,dir):
        showlist_file = dir + os.sep + "pp_showlist.json"
        if os.path.exists(showlist_file)==False:
            self.mon.err(self,"showlist file not found at " + 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'] == 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,dir):
        if self.current_showlist<>None:
            showlist_file = dir + os.sep + "pp_showlist.json"
            self.current_showlist.save_list(showlist_file)
            
    def add_eventshow(self):
        self.add_show(PPdefinitions.new_shows['eventshow'])

    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_menu(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<>None:
            d = Edit1Dialog(self.root,"AddShow",
                                "Show Reference", "")
            if d.result == 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<>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<>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<>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<>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 == True:

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

 

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

    def open_medialists(self,dir):
        self.medialists = []
        for file in os.listdir(dir):
            if file.endswith(".json") and file<>'pp_showlist.json':
                self.medialists = self.medialists + [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==None:
            d = Edit1Dialog(self.root,"Add Medialist",
                                    "File", "")
            if d.result == 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)== 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 remove_medialist(self):
        if self.current_medialist<>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()
            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<>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)
        file = self.pp_profile_dir+ os.sep + basefile
        self.current_medialist.save_list(file)

          
# ***************************************
#   Tracks
# ***************************************
                
    def refresh_tracks_display(self):
        self.tracks_display.delete(0,self.tracks_display.size())
        if self.current_medialist<>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<>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<>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 == True:
                self.save_medialist()
            self.refresh_tracks_display()

    def move_track_up(self):
        if self.current_medialist<>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<>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<>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<>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_background_track(self):
        self.new_track(PPdefinitions.new_tracks['menu-background'],None)

    def new_child_show_track(self):
        self.new_track(PPdefinitions.new_tracks['child-show'],None)

    def remove_track(self):
        if  self.current_medialist<>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==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==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 file in os.listdir(directory):
            (root_file,ext_file)= os.path.splitext(file)
            if ext_file.lower() in exts:
                file_path=directory+os.sep+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") == 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 + " - file extension not recognised")



# *********************************************
# update profile
# **********************************************

    def update_all(self):
        self.init()
        for profile_file in os.listdir(self.pp_home_dir+os.sep+'pp_profiles'):
            # self.mon.log (self,"Updating "+profile_file)
            self.pp_profile_dir = self.pp_home_dir+os.sep+'pp_profiles'+ 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.mon.log (self,"Checking version "+profile_file)
                self.current_showlist.open_json(self.pp_profile_dir+os.sep+"pp_showlist.json")
                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'] == 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," Profile " + profile_file + " Already up to date ")
        self.init()
        tkMessageBox.showwarning("Pi Presents","All profiles updated")
            
    def update_profile(self):
        #open showlist and update its shows
        # 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()
        replacement_shows=self.update_shows(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)

        
        # UPDATE MEDIALISTS AND THEIR TRACKS
        for file in os.listdir(self.pp_profile_dir):
            if file.endswith(".json") and file<>'pp_showlist.json':
                # self.mon.log (self,"Updating medialist " + file)
                #open a medialist and update its tracks
                ifile  = open(self.pp_profile_dir + os.sep + 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 + 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']
            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(self,old_shows):
        # get correct spec from type of field
        replacement_shows=[]
        for old_show in old_shows:
            show_type=old_show['type']
            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 PPWebEditor(App):

    def __init__(self, *args):
        # print 'DOIING _INIT do not use'
        super(PPWebEditor, self).__init__(*args)
        

    def main(self):
        # print 'DOING MAIN executed once when server starts'
        # ***************************************
        # INIT
        # ***************************************
        self.editor_issue="1.3"

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

        ColourMap().init()
        
        # initialise editor options OSC config class, and OSC editors
        self.eo=Options()
        self.eo.init_options(self.editor_dir)
        self.osc_config=OSCConfig()
        self.osc_ute= OSCUnitType()

        
        # initialise variables
        self.init() 

        # BUILD THE GUI
        # frames
        root = gui.Widget(width=900,height=500) #1
        root.set_layout_orientation(gui.Widget.LAYOUT_VERTICAL)         
        top_frame=gui.Widget(width=900,height=40)#1
        top_frame.set_layout_orientation(gui.Widget.LAYOUT_HORIZONTAL)
        bottom_frame=gui.Widget(width=900,height=300)#1
        bottom_frame.set_layout_orientation(gui.Widget.LAYOUT_HORIZONTAL)       
        root.append(top_frame)
        root.append(bottom_frame)

        left_frame=gui.Widget(width=350,height=400)#1
        left_frame.set_layout_orientation(gui.Widget.LAYOUT_VERTICAL)
        left_frame.style['margin']='10px'
        middle_frame=gui.VBox(width=50,height=300)#1
        middle_frame.style['margin']='10px'
        # middle_frame.set_layout_orientation(gui.Widget.LAYOUT_VERTICAL)   
        right_frame=gui.Widget(width=350,height=400)#1
        right_frame.set_layout_orientation(gui.Widget.LAYOUT_VERTICAL)   
        updown_frame=gui.VBox(width=50,height=300)#1
        updown_frame.style['margin']='10px'
        # updown_frame.set_layout_orientation(gui.Widget.LAYOUT_VERTICAL)   

        bottom_frame.append(left_frame)
        bottom_frame.append(middle_frame)
        bottom_frame.append(right_frame)
        bottom_frame.append(updown_frame)

        #menu
        menu = gui.Menu(width=700, height=30)
        top_frame.append(menu)

        #profile menu
        profile_menu = gui.MenuItem('Profile',width=80, height=30)
        profile_open_menu = gui.MenuItem('Open',width=120, height=30)
        profile_open_menu.set_on_click_listener(self,'open_existing_profile')
        profile_validate_menu = gui.MenuItem('Validate',width=120, height=30)
        profile_validate_menu.set_on_click_listener(self, 'validate_profile')
        profile_new_menu = gui.MenuItem('New',width=120, height=30)
        profile_menu.append(profile_open_menu)
        profile_menu.append(profile_validate_menu)
        profile_menu.append(profile_new_menu)

        pmenu = gui.MenuItem('Exhibit',width=150, height=30)
        pmenu.set_on_click_listener(self, 'new_exhibit_profile')
        profile_new_menu.append(pmenu)
        pmenu = gui.MenuItem('Media Show',width=150, height=30)
        pmenu.set_on_click_listener(self, 'new_mediashow_profile')
        profile_new_menu.append(pmenu)
        pmenu = gui.MenuItem('Art Media Show',width=150, height=30)
        pmenu.set_on_click_listener(self, 'new_artmediashow_profile')
        profile_new_menu.append(pmenu)
        pmenu = gui.MenuItem('Menu',width=150, height=30)
        pmenu.set_on_click_listener(self, 'new_menu_profile')
        profile_new_menu.append(pmenu)
        pmenu = gui.MenuItem('Presentation',width=150, height=30)
        pmenu.set_on_click_listener(self, 'new_presentation_profile')
        profile_new_menu.append(pmenu)        
        pmenu = gui.MenuItem('Interactive',width=150, height=30)
        pmenu.set_on_click_listener(self, 'new_interactive_profile')
        profile_new_menu.append(pmenu)
        pmenu = gui.MenuItem('Live Show',width=150, height=30)
        pmenu.set_on_click_listener(self, 'new_liveshow_profile')
        profile_new_menu.append(pmenu)
        pmenu = gui.MenuItem('Art Live Show',width=150, height=30)
        pmenu.set_on_click_listener(self, 'new_artliveshow_profile')
        profile_new_menu.append(pmenu)
        pmenu = gui.MenuItem('RadioButton Show',width=150, height=30)
        pmenu.set_on_click_listener(self, 'new_radiobuttonshow_profile')
        profile_new_menu.append(pmenu)
        pmenu = gui.MenuItem( 'Hyperlink Show',width=150, height=30)
        pmenu.set_on_click_listener(self, 'new_hyperlinkshow_profile')
        profile_new_menu.append(pmenu)
        pmenu = gui.MenuItem( 'Blank',width=150, height=30)
        pmenu.set_on_click_listener(self, 'new_blank_profile')
        profile_new_menu.append(pmenu)
        
        # shows menu              
        show_menu = gui.MenuItem( 'Show',width=80, height=30)
        show_delete_menu = gui.MenuItem('Delete',width=120, height=30)
        show_delete_menu.set_on_click_listener(self, 'remove_show')    
        show_edit_menu = gui.MenuItem('Edit',width=120, height=30)
        show_edit_menu.set_on_click_listener(self, 'm_edit_show')
        show_copy_to_menu = gui.MenuItem( 'Copy To',width=120, height=30)
        show_copy_to_menu.set_on_click_listener(self, 'copy_show')
        show_add_menu = gui.MenuItem( 'Add',width=120, height=30)
        show_menu.append(show_delete_menu)
        show_menu.append(show_edit_menu)
        show_menu.append(show_copy_to_menu)
        show_menu.append(show_add_menu)


        pmenu = gui.MenuItem('Menu',width=150, height=30)
        pmenu.set_on_click_listener(self, 'add_menushow')
        show_add_menu.append(pmenu)
        
        pmenu = gui.MenuItem( 'Media Show',width=150, height=30)
        pmenu.set_on_click_listener(self, 'add_mediashow')
        show_add_menu.append(pmenu)
        
        pmenu = gui.MenuItem('Live Show',width=150, height=30)
        pmenu.set_on_click_listener(self, 'add_liveshow')
        show_add_menu.append(pmenu)

        pmenu = gui.MenuItem('Hyperlink Show',width=150, height=30)
        pmenu.set_on_click_listener(self, 'add_hyperlinkshow')
        show_add_menu.append(pmenu)

        pmenu = gui.MenuItem('RadioButton Show',width=150, height=30)
        pmenu.set_on_click_listener(self, 'add_radiobuttonshow')
        show_add_menu.append(pmenu)

        pmenu = gui.MenuItem( 'Art Mediashow Show',width=150, height=30)
        pmenu.set_on_click_listener(self, 'add_artmediashow')
        show_add_menu.append(pmenu)

        pmenu = gui.MenuItem( 'Art Liveshow Show',width=150, height=30)
        pmenu.set_on_click_listener(self, 'add_artliveshow')
        show_add_menu.append(pmenu)

        # medialists menu
        medialist_menu = gui.MenuItem( 'Medialist',width=80, height=30)
        
        medialist_delete_menu = gui.MenuItem( 'Delete',width=120, height=30)
        medialist_delete_menu.set_on_click_listener(self, 'remove_medialist')

        
        medialist_add_menu = gui.MenuItem( 'Add',width=120, height=30)
        medialist_add_menu.set_on_click_listener(self, 'add_medialist')
        
        medialist_copy_to_menu = gui.MenuItem('Copy To',width=120, height=30)
        medialist_copy_to_menu.set_on_click_listener(self, 'copy_medialist')
        
        medialist_menu.append(medialist_add_menu)
        medialist_menu.append(medialist_delete_menu)
        medialist_menu.append(medialist_copy_to_menu)

        # tracks menu
        track_menu = gui.MenuItem('Track',width=80, height=30)

        track_delete_menu = gui.MenuItem('Delete',width=120, height=30)
        track_delete_menu.set_on_click_listener(self, 'remove_track')
        track_edit_menu = gui.MenuItem( 'Edit',width=120, height=30)
        track_edit_menu.set_on_click_listener(self, 'm_edit_track')
        track_add_from_dir_menu = gui.MenuItem('Add Directory',width=120, height=30)
        track_add_from_dir_menu.set_on_click_listener(self, 'add_tracks_from_dir')
        track_add_from_file_menu = gui.MenuItem('Add File',width=120, height=30)
        track_add_from_file_menu.set_on_click_listener(self, 'add_track_from_file')
        track_new_menu = gui.MenuItem('New',width=120, height=30)

        track_new_video_menu = gui.MenuItem('Video',width=120, height=30)
        track_new_video_menu.set_on_click_listener(self, 'new_video_track')
        track_new_audio_menu = gui.MenuItem('Audio',width=120,height=30)
        track_new_audio_menu.set_on_click_listener(self, 'new_audio_track')
        track_new_image_menu = gui.MenuItem( 'Image',width=120, height=30)
        track_new_image_menu.set_on_click_listener(self, 'new_image_track')
        track_new_web_menu = gui.MenuItem( 'Web',width=120, height=30)
        track_new_web_menu.set_on_click_listener(self, 'new_web_track')
        track_new_message_menu = gui.MenuItem('Message',width=120, height=30)
        track_new_message_menu.set_on_click_listener(self, 'new_message_track')
        track_new_show_menu = gui.MenuItem('Show',width=120, height=30)
        track_new_show_menu.set_on_click_listener(self, 'new_show_track')
        track_new_menu_menu = gui.MenuItem('Menu',width=120, height=30)
        track_new_menu_menu.set_on_click_listener(self, 'new_menu_track')

        track_new_menu.append(track_new_video_menu)
        track_new_menu.append(track_new_audio_menu)
        track_new_menu.append(track_new_image_menu)
        track_new_menu.append(track_new_web_menu)        
        track_new_menu.append(track_new_message_menu)
        track_new_menu.append(track_new_show_menu)
        track_new_menu.append(track_new_menu_menu)
        
        track_menu.append(track_delete_menu)
        track_menu.append(track_edit_menu)
        track_menu.append(track_add_from_dir_menu)
        track_menu.append(track_add_from_file_menu)
        track_menu.append(track_new_menu)


      
        options_menu = gui.MenuItem('Options',width=80, height=30)
        options_edit_menu=gui.MenuItem('Edit',width=80, height=30)
        options_edit_menu.set_on_click_listener(self, 'edit_options')
        options_menu.append(options_edit_menu)

        # osc menu
        osc_menu = gui.MenuItem( 'OSC',width=80, height=30)  
        osc_create_menu = gui.MenuItem( 'Create',width=120, height=30)
        osc_create_menu.set_on_click_listener(self, 'create_osc')
        osc_edit_menu = gui.MenuItem( 'Edit',width=120, height=30)
        osc_edit_menu.set_on_click_listener(self, 'edit_osc')
        osc_delete_menu = gui.MenuItem( 'Delete',width=120, height=30)
        osc_delete_menu.set_on_click_listener(self, 'delete_osc')
        osc_menu.append(osc_create_menu)
        osc_menu.append(osc_edit_menu)
        osc_menu.append(osc_delete_menu)
        
        # help menu
        help_menu = gui.MenuItem( 'Help',width=80, height=30)
        help_text_menu = gui.MenuItem( 'Help',width=80, height=30)
        help_text_menu.set_on_click_listener(self, 'show_help')
        about_menu = gui.MenuItem( 'About',width=80, height=30)
        about_menu.set_on_click_listener(self, 'show_about')
        help_menu.append(help_text_menu)
        help_menu.append(about_menu)

        menu.append(profile_menu)
        menu.append(show_menu)
        menu.append(medialist_menu)
        menu.append(track_menu)
        menu.append(osc_menu)
        menu.append(options_menu)
        menu.append(help_menu)


        
        #shows and medialists
        shows_label=gui.Label('<b>Shows</b>',width=300, height=20)
        shows_label.style['margin']='5px'
        self.shows_display= gui.ListView(width=350, height=150)
        self.shows_display.set_on_selection_listener(self,'show_selected')
        
        medialists_label=gui.Label('<b>Medialists</b>',width=300, height=20)
        medialists_label.style['margin']='5px'
        self.medialists_display= gui.ListView(width=350, height=150)
        self.medialists_display.set_on_selection_listener(self,'medialist_selected')

        left_frame.append(shows_label)
        left_frame.append(self.shows_display)         
        left_frame.append(medialists_label)
        left_frame.append(self.medialists_display)

        #edit show button
        edit_show = gui.Button('Edit\nShow',width=50, height=50)
        edit_show.set_on_click_listener(self, 'm_edit_show')
        middle_frame.append(edit_show)

        #tracks
        tracks_label=gui.Label('<b>Tracks in Selected Medialist</b>',width=300, height=20)
        tracks_label.style['margin']='5px'
        self.tracks_display= gui.ListView(width=350, height=300)
        self.tracks_display.set_on_selection_listener(self,'track_selected')

        right_frame.append(tracks_label)
        right_frame.append(self.tracks_display)  

        #tracks buttons
        add_track = gui.Button('Add',width=50, height=50)
        add_track.set_on_click_listener(self, 'add_track_from_file')
        updown_frame.append(add_track)
        
        edit_track = gui.Button('Edit',width=50, height=50)
        edit_track.set_on_click_listener(self, 'm_edit_track')
        updown_frame.append(edit_track)        

        up_track = gui.Button('Up',width=50, height=50)
        up_track.set_on_click_listener(self, 'move_track_up')
        updown_frame.append(up_track)

        down_track = gui.Button('Down',width=50, height=50)
        down_track.set_on_click_listener(self, 'move_track_down')
        updown_frame.append(down_track)
        return root

        
    def init(self):
        # print 'init'
        self.eo.read_options()
        self.pp_home_dir = self.eo.pp_home_dir
        self.pp_profiles_offset = self.eo.pp_profiles_offset
        self.initial_media_dir = self.eo.initial_media_dir
        self.pp_profile_dir=''
        self.current_medialist=None
        self.current_showlist=None
        self.current_show=None

    def empty_lists(self):
        # print 'empty lists'
        self.shows_display.empty()
        self.medialists_display.empty()
        self.tracks_display.empty()

    def show_help (self):
        OKDialog("Help","Please Read 'manual.pdf'",width=400,height=200).show(self)

  
    def show_about (self):
        OKDialog("About","Web Editor for Pi Presents Profiles<br>"
                              +"For profiles of version: " + self.editor_issue + "<br>Author: Ken Thompson"
                              +"<br>Website: http://pipresents.wordpress.com/<br>",width=400,height=200).show(self)

    def validate_profile(self):
        if self.current_showlist != None:
            val =Validator('Validation Result')
            val.show(self)
            val.validate_profile(self.editor_dir,self.pp_home_dir,self.pp_profile_dir,self.editor_issue,True)


    # **************
    # OPTIONS
    # **************


    def edit_options(self):
        self.eo.edit(self.edit_options_callback)
        self.eo.show(self)

    def edit_options_callback(self):
        # self.eo.show(self)
        self.eo.read_options()
        self.init()
        self.empty_lists()
        



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

    def create_osc(self):
        if self.pp_profile_dir=='':
            return
        # print 'create',OSCConfig.options_file
        if self.osc_config.read() 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()

    def edit_osc(self):
        # print 'edit',OSCConfig.options_file
        if self.osc_config.read() is False:
            # print 'no config file'
            return
        self.osc_ute.edit(self.edit_osc_callback)
        self.osc_ute.show(self)

    def edit_osc_callback(self):
        # self.osc_ute.hide()
        # print 'edit callback', OSCConfig.current_unit_type
        self.osc_editor=OSCWebEditor()
        if OSCConfig.current_unit_type != '':
            self.osc_editor.edit()
            self.osc_editor.show(self)
   
    def delete_osc(self):
        if self.osc_config.read() is False:
            return
        self.osc_config.delete()
        



    
    # **************
    # 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:
            OKDialog('Open Profile',"Profiles directory not found: " + initial_dir + "<br><br>Hint: Data Home option must end in pp_home").show(self)
            return
        open_existing_profile_dialog = gui.FileSelectionDialog('Open Profile','Select profile',False, initial_dir) #width=600,height=200,
        open_existing_profile_dialog.set_on_confirm_value_listener(self, 'open_existing_profile_dialog_confirm')
        open_existing_profile_dialog.show(self)


    def open_existing_profile_dialog_confirm(self, filelist):
        if len(filelist)==0:
            OKDialog('Open Profile',"Nothing Selected").show(self)
            return
        # print 'filelist',filelist[0]
        self.open_profile(filelist[0])
        

    def open_profile(self,dir_path):
        showlist_file = dir_path + os.sep + "pp_showlist.json"
        #print 'open profile',showlist_file
        if os.path.exists(showlist_file) is False:
            OKDialog('Open Profile',"Not a Profile: " + dir_path).show(self)
            return
        self.pp_profile_dir = dir_path
        OSCConfig.options_file=self.pp_profile_dir+ os.sep+'pp_io_config'+os.sep+'osc.cfg'
        # print 'profile direcotry',self.pp_profile_dir
        # self.root.title("Editor for Pi Presents - "+ self.pp_profile_dir)
        if self.open_showlist(self.pp_profile_dir) is False:
            self.init()
            self.empty_lists()
            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 = gui.InputDialog("New Profile","Name",width=400,height=250)
        self.new_profile_template=profile
        d.set_on_confirm_value_listener(self, 'new_profile_confirm')
        d.show(self)

    def new_profile_confirm(self,name):
        if name == "":
            OKDialog("New Profile","Name is blank").show(self)
            return
        to = self.pp_home_dir + os.sep + "pp_profiles"+ self.pp_profiles_offset + os.sep + name
        if os.path.exists(to) is  True:
            OKDialog( "New Profile","Profile exists\n(%s)" % to ).show(self)
            return
        shutil.copytree(self.new_profile_template, to, symlinks=False, ignore=None)
        self.open_profile(to)


        
    def new_exhibit_profile(self):
        profile = self.editor_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.editor_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.editor_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.editor_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.editor_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.editor_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.editor_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.editor_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.editor_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.editor_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.editor_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_hyperlinkshow_1p3'
        self.new_profile(profile)


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

# !!!!! changed app_exit to return
    def open_showlist(self,profile_dir):
        showlist_file = profile_dir + os.sep + "pp_showlist.json"
        if os.path.exists(showlist_file) is False:
            OKDialog('Open Profile',"showlist file not found at " + profile_dir + "<br><br>Hint: Have you opened the profile directory?").show(self)
            return False
        self.current_showlist=ShowList()
        self.current_showlist.open_json(showlist_file)
        if float(self.current_showlist.sissue())<float(self.editor_issue):
            self.update_profile()
            OKDialog('Open Profile',"Version of profile has been updated to "+self.editor_issue+", please re-open").show(self)
            return False
        if float(self.current_showlist.sissue())>float(self.editor_issue):
            OKDialog('Open Profile',"Version of profile is greater than editor").show(self)
            return False
        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:
            self.default_show=default
            d = gui.InputDialog("Add Show","Show Reference",width=400,height=250)
            d.set_on_confirm_value_listener(self, 'add_show_confirm')
            d.show(self)

    def add_show_confirm(self,name):
        # print 'show name',name
        if name == "":
            OKDialog("Add Show","Name is blank").show(self)
            return             
        if self.current_showlist.index_of_show(name) != -1:
            OKDialog("Add Show","A Show with this name already exists").show(self)
            return
        # print 'copy show template',self.default_show,name
        copied_show=self.current_showlist.copy(self.default_show,name)
        # print 'add mediafile from show',name
        mediafile=self.add_medialist(name)
        # print 'mediafile added',mediafile
        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():
            OKCancelDialog("Delete Show","Are you sure?",self.remove_show_confirm).show(self)

    def remove_show_confirm(self,result):
        if result is True:
            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.empty()
        key=0
        for index in range(self.current_showlist.length()):
            value= self.current_showlist.show(index)['title']+"   ["+self.current_showlist.show(index)['show-ref']+"]"
            obj = gui.ListItem(value,width=340, height=20)
            self.shows_display.append(obj,key=key)
            key+=1
        if self.current_showlist.show_is_selected():
            self.shows_display.select_by_key(self.current_showlist.selected_show_index())            
            # self.shows_display.show()

            
    def show_selected(self,event):
        if self.current_showlist is not None and self.current_showlist.length()>0:
            mouse_item_index=self.shows_display.get_key()
            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():
            self.edit_show_dialog=WebEditItem("Edit Show",self.current_showlist.selected_show(),show_types,field_specs,self.show_refs(),
                       self.initial_media_dir,self.pp_home_dir,'show',self.finished_edit_show)
            self.edit_show_dialog.show(self)
            self.edit_show_dialog.show_tab('show')

    def finished_edit_show(self):
        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.empty()
        key=0
        for index in range (len(self.medialists)):
            obj = gui.ListItem(self.medialists[index],width=340, height=20)
            self.medialists_display.append(obj, key=key)
            key+=1
        self.current_medialists_index=-1
        self.current_medialist=None


    def add_medialist(self,name=None):
        if self.current_showlist != None:
            if name is None:
                d = gui.InputDialog("Add Medialist","File",width=400,height=250)
                d.set_on_confirm_value_listener(self, 'add_medialist_confirm')
                d.show(self)
            else:
                medialist_name=self.add_medialist_confirm(name)
                return medialist_name

    def add_medialist_confirm(self,name):
        # print 'add medialist',name
        if name == "":
            OKDialog("Add Medialist","Name is blank").show(self)
            return  ''           
        if self.current_showlist.index_of_show(name) != -1:
            OKDialog("Add Medialist","A medialist with this name already exists").show(self)
            return ''
        if not name.endswith(".json"):
            name=name+(".json")
               
        path = self.pp_profile_dir + os.sep + name
        if os.path.exists(path) is  True:
            OKDialog("Add Medialist","Medialist file exists<br>(%s)" % path).show(self)
            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))
        # print 'medialists',self.medialists
        # add title to medialists display
        # self.medialists_display.insert(END, name)  
        # and set it as the selected medialist
        self.refresh_medialists_display()
        # print 'returning medilaist name',name
        return name


    def copy_medialist(self,to_file=None):
        if self.current_showlist != None:
            if self.current_medialist is not None:
                #from_file= self.current_medialist
                self.from_file= self.medialists[self.current_medialists_index]
                if to_file is None:
                    d = gui.InputDialog("Copy Medialist","File",width=400,height=250)
                d.set_on_confirm_value_listener(self, 'copy_medialist_confirm')
                d.show(self)
            else:
                self.copy_medialist_confirm(to_file)

    def copy_medialist_confirm(self,to_file):
        # print self.from_file,to_file
        if to_file == "":
            OKDialog("Copy Medialist","Name is blank").show(self)
            return ''

        success_file = self.copy_medialist_file(self.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


    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:
            OKDialog("Copy Medialist","Medialist file exists\n(%s)" % to_path).show(self)
            return ''
        
        from_path= self.pp_profile_dir + os.sep + from_file
        if os.path.exists(from_path) is  False:
            OKDialog("Copy Medialist","Medialist file not found\n(%s)" % from_path).show(self)
            return ''

        shutil.copy(from_path,to_path)
        return to_file


    def remove_medialist(self):
        if self.current_medialist is not None:
            OKCancelDialog("Delete Medialist","Are you sure?",self.remove_medialist_confirm).show(self)

    def remove_medialist_confirm(self,result):
        if result is True:
            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()


# removed appexit
    def medialist_selected(self,key):
        """
        user clicks on a medialst in a profile so try and select it.
        """
        # print 'selected',type(self.medialists_display.get_key()),self.medialists_display.get_key()
        if len(self.medialists)>0:
            self.current_medialists_index=self.medialists_display.get_key()

            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()):
                OKDialog(self,"medialist is a different version to showlist: "+ self.medialists[self.current_medialists_index]).show(self)
                #self.app_exit()
                return
            self.refresh_tracks_display()
            self.refresh_medialists_display()


    def refresh_medialists_display(self):
        # print 'refresh medialists'
        self.medialists_display.empty()
        key=0
        for index in range (len(self.medialists)):
            obj = gui.ListItem(self.medialists[index],width=340, height=20)
            self.medialists_display.append(obj,key=key)
            key+=1
                    
        if self.current_medialist is not None:
            self.medialists_display.select_by_key(self.current_medialists_index)
            # self.medialists_display.show(self)

  

    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.empty()
        if self.current_medialist is not None:
            key=0
            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=""
                obj = gui.ListItem(self.current_medialist.track(index)['title']+track_ref_string,width=340, height=20)
                self.tracks_display.append(obj,key=key)
                key+=1                
            if self.current_medialist.track_is_selected():
                self.tracks_display.select_by_key(self.current_medialist.selected_track_index())  

            
    def  track_selected(self,key):
        # print 'track sel', type(self.tracks_display.get_key())
        if self.current_medialist is not None and self.current_medialist.length()>0:
            mouse_item_index=self.tracks_display.get_key()
            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():
            self.edit_track_dialog=WebEditItem("Edit Track",self.current_medialist.selected_track(),track_types,field_specs,
                       self.show_refs(),self.initial_media_dir,self.pp_home_dir,'track',self.finished_edit_track)
            self.edit_track_dialog.show(self)
            self.edit_track_dialog.show_tab('track')

    def finished_edit_track(self):
        self.refresh_tracks_display()
        self.save_medialist()        
            
    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):
        # print 'new menu track'
        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():
            OKCancelDialog("Delete Track","Are you sure?",self.remove_track_confirm).show(self)

    def remove_track_confirm(self,result):
        # print 'confirm',result
        if result is True:
            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
        add_track_from_file_dialog = gui.FileSelectionDialog('Add Track', 'Select Tracks',True, self.eo.initial_media_dir)#600,200,
        add_track_from_file_dialog.set_on_confirm_value_listener(self, 'add_track_from_file_dialog_confirm')
        add_track_from_file_dialog.show(self)


    def add_track_from_file_dialog_confirm(self, filelist):
        if len(filelist)==0:
            OKDialog('Add Track',"Nothing Selected").show(self)
            return
        for file_path in filelist:
            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
        add_tracks_from_dir_dialog = gui.FileSelectionDialog('Add Directory', 'Select Directory',
                                    multiple_selection = False, allow_file_selection=False, selection_folder = self.eo.initial_media_dir)
        add_tracks_from_dir_dialog.set_on_confirm_value_listener(self, 'add_tracks_from_dir_dialog_confirm')
        add_tracks_from_dir_dialog.show(self)


    def add_tracks_from_dir_dialog_confirm(self, result):
        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
        if len(result) == 0:
            OKDialog('Add Tracks',"Nothing Selected").show(self)
            return
        directory=result[0]
        # 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:
            OKDialog('Add Track',afile + " - cannot determine track type, use menu track>new").show(self)