コード例 #1
0
ファイル: app.py プロジェクト: ashokkmr1/DL-ODT-for-UAV
class App(Tk):

    def __init__(self):
        Tk.__init__(self)
        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)

        self.progress_bar = None
        self.prog_win = None

        self.working_folder = None

        self.main_container = Frame(
            self,
            highlightbackground="black",
            highlightcolor="black",
            highlightthickness=1
        )
        self.frames = {}

        self.main_container.grid(row=0, column=0, sticky="nsew")
        self.main_container.grid_rowconfigure(0, weight=1)
        self.main_container.grid_columnconfigure(0, weight=1)

        for F in (Steps, DTType, UploadMul, AnnotateMul, PreDataMul, TrainingMul, Upload, Annotate, SingleDetection, SingleTracking, Mul_Object_Detection, References):
            frame = F(self.main_container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(Steps)

    def show_frame(self, frame):
        self.frames[frame].tkraise()
        self.frames[frame].event_generate("<<ShowFrame>>")

    def show_progress(self, start):
        if start:
            self.prog_win = Toplevel(self.main_container, padx=8, pady=8)
            self.prog_win.transient(self)
            self.prog_win.title('Working...')
            self.prog_win.resizable(0, 0)
            self.progress_bar = Progressbar(self.prog_win,
                                            orient=HORIZONTAL,
                                            mode='indeterminate',
                                            length=250,
                                            takefocus=True)
            self.progress_bar.grid()
            self.progress_bar.start()
        else:
            self.progress_bar.stop()
            self.prog_win.destroy()
コード例 #2
0
ファイル: MPExport.py プロジェクト: jaredmixpanel/mpexport_py
class MPExportApp(object):
    """docstring for MPExportApp"""
    def __init__(self, master):
        super(MPExportApp, self).__init__()
        self.master = master
        self.export_type = StringVar()

        master.columnconfigure(1, weight=1)

        export_type_label = Label(master, text="Data Type: ")
        export_type_label.grid(row=0, column=0, sticky=E)

        radio_group_frame = Frame(master)
        radio_group_frame.grid(row=0, column=1, sticky=W)

        self.events_radio_button = Radiobutton(radio_group_frame, text='Events', value='events', variable=self.export_type,
                                               command=self.radio_button_changed)

        self.events_radio_button.select()
        self.events_radio_button.grid(row=0, column=0)

        self.people_radio_button = Radiobutton(radio_group_frame, text='People', value='people', variable=self.export_type,
                                               command=self.radio_button_changed)
        self.people_radio_button.grid(row=0, column=1)

        api_key_label = Label(master, text="API Key: ")
        api_key_label.grid(row=1, column=0, sticky=E)

        self.api_key_entry = Entry(master)
        self.api_key_entry.grid(row=1, column=1, columnspan=2, sticky=(E,W))

        api_secret_label = Label(master, text="API Secret: ")
        api_secret_label.grid(row=2, column=0, sticky=E)

        self.api_secret_entry = Entry(master)
        self.api_secret_entry.grid(row=2, column=1, columnspan=2, sticky=(E, W))

        self.project_token_label = Label(master, text="Project Token: ", state=DISABLED)
        self.project_token_label.grid(row=3, column=0, sticky=E)

        self.project_token_entry = Entry(master, state=DISABLED)
        self.project_token_entry.grid(row=3, column=1, columnspan=2, sticky=(E, W))

        self.events_label = Label(master, text="Events: ")
        self.events_label.grid(row=4, column=0, sticky=E)

        self.events_entry = Entry(master)
        self.events_entry.insert(0, 'Event A,Event B,Event C')
        self.events_entry.bind('<FocusIn>', partial(self.clear_placeholder_text, self.events_entry))
        self.events_entry.grid(row=4, column=1, columnspan=2, sticky=(E, W))

        where_label = Label(master, text="Where: ")
        where_label.grid(row=5, column=0, sticky=E)
        self.where_entry = Entry(master)
        self.where_entry.grid(row=5, column=1, columnspan=2, sticky=(E, W))

        self.from_date_label = Label(master, text="From Date: ")
        self.from_date_label.grid(row=6, column=0, sticky=E)

        self.from_date_entry = Entry(master)
        self.from_date_entry.insert(0, 'YYYY-MM-DD')
        self.from_date_entry.bind('<FocusIn>', partial(self.clear_placeholder_text, self.from_date_entry))
        self.from_date_entry.grid(row=6, column=1, columnspan=2, sticky=(E, W))

        self.to_date_label = Label(master, text="To Date: ")
        self.to_date_label.grid(row=7, column=0, sticky=E)

        self.to_date_entry = Entry(master)
        self.to_date_entry.insert(0, 'YYYY-MM-DD')
        self.to_date_entry.bind('<FocusIn>', partial(self.clear_placeholder_text, self.to_date_entry))
        self.to_date_entry.grid(row=7, column=1, columnspan=2, sticky=(E, W))

        export_button = Button(master, text="EXPORT", fg="green", command=self.export)
        export_button.grid(row=8, column=1, sticky=(E, W))

        self.delete_button = Button(master, text="DELETE", fg='red', state=DISABLED,
                                    command=lambda: threading.Thread(target=self.delete_people).start())
        self.delete_button.grid(row=9, column=1, sticky=(E, W))

        self.progress_bar = Progressbar(master)
        self.progress_bar_value = IntVar()
        self.progress_bar.config(mode='determinate', orient='horizontal', variable=self.progress_bar_value)
        self.progress_bar.grid(row=10, column=0, columnspan=3, sticky=(E, W))


    def clear_placeholder_text(self, entry, event):
        entry_text = entry.get()
        if entry_text == 'Event A,Event B,Event C' or entry_text == 'YYYY-MM-DD':
            entry.delete(0, END)

    def make_events_string(self, events):
        events = events.replace(', ', ',')
        events = events.split(',')
        events_string = '['
        for x in range(0, len(events)):
            events_string += '"' + events[x] + '"'
            if x != len(events)-1:
                events_string += ','
            else:
                events_string += ']'
        return events_string

    def radio_button_changed(self):
        if self.export_type.get() == 'people':
            self.project_token_label.config(state=NORMAL)
            self.project_token_entry.config(state=NORMAL)
            self.events_label.config(state=DISABLED)
            self.events_entry.config(state=DISABLED)
            self.from_date_label.config(state=DISABLED)
            self.from_date_entry.config(state=DISABLED)
            self.to_date_label.config(state=DISABLED)
            self.to_date_entry.config(state=DISABLED)
            self.delete_button.config(state=NORMAL)
        elif self.export_type.get() == 'events':
            self.project_token_label.config(state=DISABLED)
            self.project_token_entry.config(state=DISABLED)
            self.events_label.config(state=NORMAL)
            self.events_entry.config(state=NORMAL)
            self.from_date_label.config(state=NORMAL)
            self.from_date_entry.config(state=NORMAL)
            self.to_date_label.config(state=NORMAL)
            self.to_date_entry.config(state=NORMAL)
            self.delete_button.config(state=DISABLED)

    def export(self):
        if self.api_key_entry.get() == '':
            print 'API Key Required!'
            return
        elif self.api_secret_entry.get() == '':
            print 'API Secret Required!'
            return

        self.output_dir = askdirectory(title='Choose output directory', mustexist=True, parent=self.master)
        if not self.output_dir:
            return
        print 'Output directory is ' + self.output_dir

        self.progress_bar.start()
        if self.export_type.get() == 'people':
            self.export_thread = threading.Thread(target=self.export_people)
        elif self.export_type.get() == 'events':
            self.export_thread = threading.Thread(target=self.export_events)

        self.export_thread.start()

    def export_people(self):

        mixpanel = Mixpanel(
            api_key=self.api_key_entry.get(),
            api_secret=self.api_secret_entry.get(),
            endpoint=API_ENDPOINT
            )

        '''Here is the place to define your selector to target only the users that you're after'''
        '''parameters = {'selector':'(properties["$email"] == "Albany") or (properties["$city"] == "Alexandria")'}'''
        selector = self.where_entry.get()

        parameters = {}

        if selector:
            parameters['selector'] = selector

        response = mixpanel.request(['engage'], parameters)

        try:
            result = '\nAPI ERROR! - ' + json.loads(response)['error'] + '\n'
            if result:
                print result
                self.progress_bar.stop()
                self.progress_bar_value.set(0)
                return
        except KeyError, e:
            pass

        parameters['session_id'] = json.loads(response)['session_id']
        parameters['page'] = 0
        global_total = json.loads(response)['total']
        if global_total == 0:
            print 'Query returned 0 profiles!'
            self.progress_bar.stop()
            self.progress_bar_value.set(0)
            return

        print "Session id is %s \n" % parameters['session_id']
        print "Here are the # of people %d" % global_total
        filename = self.output_dir + "/people_export_"+str(int(time.time()))
        jsonfile = filename + ".json"
        csvfile = filename + ".csv"
        has_results = True
        total = 0
        with tempfile.NamedTemporaryFile(delete=False) as temp:
            with open(jsonfile, 'w') as j:
                j.write('[')
                while has_results:
                    responser = json.loads(response)['results']
                    response_count = len(responser)
                    total += response_count
                    has_results = response_count == 1000
                    i = 0
                    for data in responser:
                        dump = json.dumps(data)
                        temp.write(dump + '\n')
                        j.write(dump)
                        i += 1
                        if i != response_count:
                            j.write(',')

                    print "%d / %d" % (total,global_total)
                    parameters['page'] += 1
                    if has_results:
                        j.write(',')
                        response = mixpanel.request(['engage'], parameters)
                    else:
                        j.write(']')

                print 'JSON saved to ' + j.name
                j.close()

        mixpanel.people_json_to_csv(csvfile, temp.name)
        temp.close()
        os.remove(temp.name)
        self.progress_bar.stop()
        self.progress_bar_value.set(0)
コード例 #3
0
ファイル: tk_appwindow.py プロジェクト: plewto/Llia
class TkApplicationWindow(AbstractApplicationWindow):

    def __init__(self, app):
        self.root = Tk()
        self.root.title("Llia")
        self.root.config(background=factory.bg())
        super(TkApplicationWindow, self).__init__(app, self.root)
        self.root.withdraw()
        if app.config()["enable-splash"]:
            splash = TkSplashWindow(self.root, app)
        self.root.deiconify()
        self.root.protocol("WM_DELETE_WINDOW", self.exit_app)
        self.llia_graph = None
        self._main = layout.BorderFrame(self.root)
        self._main.config(background=factory.bg())
        self._main.pack(anchor="nw", expand=True, fill=BOTH)
        self._progressbar = None
        self._init_status_panel()
        self._init_menu()
        self._init_center_frame(self._main.center)
        self.root.minsize(width=665, height=375)
        self.group_windows = []
        self.add_synth_group()
        self._scene_filename = ""
        
    def _init_status_panel(self):
        south = self._main.south
        south.configure(padx=4, pady=4)
        self._lab_status = factory.label(south, "", modal=False)
        b_panic = factory.panic_button(south)
        b_down = factory.button(south, "-")
        b_up = factory.button(south, "+")
        b_panic.grid(row=0, column=0)
        self._progressbar = Progressbar(south,mode="indeterminate")
        self._progressbar.grid(row=0,column=PROGRESSBAR_COLUMN, sticky='w', padx=8)
        self._lab_status.grid(row=0,column=4, sticky='w')
        south.config(background=factory.bg())
        b_down.configure(command=lambda: self.root.lower())
        b_up.configure(command=lambda: self.root.lift())
        self.update_progressbar(100, 0)
        
    def _tab_change_callback(self, event):
        self.llia_graph.sync()
    
    def _init_center_frame(self, master):
        nb = ttk.Notebook(master)
        nb.pack(expand=True, fill="both")
        frame_synths = layout.FlowGrid(nb, 6)
        frame_efx = layout.FlowGrid(nb, 6)
        frame_controllers = layout.FlowGrid(nb, 6)
        self.llia_graph = LliaGraph(nb, self.app)
        nb.add(frame_synths, text = "Synths")
        nb.add(frame_efx, text = "Effects")
        nb.add(frame_controllers, text = "Controllers")
        nb.add(self.llia_graph, text="Graph")
        nb.bind("<Button-1>", self._tab_change_callback)

        def display_info_callback(event):
            sp = event.widget.synth_spec
            msg = "%s:    %s" % (sp["format"],sp["description"])
            self.status(msg)

        def clear_info_callback(*_):
            self.status("")
        
        for st in con.SYNTH_TYPES:
            sp = specs[st]
            ttp = "Add %s Synthesizer (%s)" % (st, sp["description"])
            b = factory.logo_button(frame_synths, st, ttip=ttp)
            b.synth_spec = sp
            b.bind("<Button-1>", self._show_add_synth_dialog)
            b.bind("<Enter>", display_info_callback)
            b.bind("<Leave>", clear_info_callback)
            frame_synths.add(b)
        for st in con.EFFECT_TYPES:
            sp = specs[st]
            ttp = "Add %s Effect (%s)" % (st, sp["description"])
            b = factory.logo_button(frame_efx, st, ttip=ttp)
            b.synth_spec = sp
            b.bind("<Button-1>", self._show_add_efx_dialog)
            b.bind("<Enter>", display_info_callback)
            b.bind("<Leave>", clear_info_callback)
            frame_efx.add(b)
        for st in con.CONTROLLER_SYNTH_TYPES:
            sp = specs[st]
            ttp = "Add %s Effect (%s)" % (st, sp["description"])
            b = factory.logo_button(frame_controllers, st, ttip=ttp)
            b.synth_spec = sp
            b.bind("<Button-1>", self._show_add_controller_dialog)
            b.bind("<Enter>", display_info_callback)
            b.bind("<Leave>", clear_info_callback)
            frame_controllers.add(b)
    
    @staticmethod
    def menu(master):
        m = Menu(master, tearoff=0)
        m.config(background=factory.bg(), foreground=factory.fg())
        return m
    
    def _init_menu(self):
        main_menu = self.menu(self.root)
        self.root.config(menu=main_menu)
        file_menu = self.menu(main_menu)
        osc_menu = self.menu(main_menu)
        midi_menu = self.menu(main_menu)
        bus_menu = self.menu(main_menu)
        #buffer_menu = self.menu(main_menu)
        tune_menu = self.menu(main_menu)
        help_menu = self.menu(main_menu)
        main_menu.add_cascade(label="File", menu=file_menu)
        main_menu.add_cascade(label="OSC", menu=osc_menu)
        main_menu.add_cascade(label="MIDI", menu=midi_menu)
        #main_menu.add_cascade(label="Buses", menu=bus_menu)
        #main_menu.add_cascade(label="Buffers", menu=buffer_menu)
        #main_menu.add_cascade(label="Tune", menu=tune_menu)
        #main_menu.add_cascade(label="Help", menu=help_menu)
        self._init_file_menu(file_menu)
        self._init_osc_menu(osc_menu)
        self._init_midi_menu(midi_menu)
        self._init_bus_menu(bus_menu)
        #self._init_buffer_menu(buffer_menu)
        self._init_tune_menu(tune_menu)
        self._init_help_menu(help_menu)

    def _init_file_menu(self, fmenu):
        fmenu.add_command(label="Save Scene", command = self.save_scene)
        fmenu.add_command(label="Load Scene", command = self.load_scene)
        fmenu.add_separator()
        fmenu.add_command(label="Lliascript (Legacy)", command = self.show_history_editor)
        fmenu.add_separator()
        fmenu.add_command(label="New Synth Group", command = self._add_synth_group)
        fmenu.add_separator()
        fmenu.add_command(label="Restart", command = self._interactive_tabula_rasa)
        fmenu.add_command(label="Quit", command = self.exit_app)

    def _init_osc_menu(self, iomenu):
        iomenu.add_command(label="Ping", command = self.ping_global)
        iomenu.add_command(label="Dump", command = self.app.proxy.dump)
        iomenu.add_command(label="Toggle OSC Trace", command = self.toggle_osc_trace)

    def _init_midi_menu(self, mmenu):
        map_menu = self.menu(mmenu)
        mmenu.add_command(label = "Channel Names", command = self.show_channel_name_dialog)
        mmenu.add_command(label = "Controller Names", command = self.show_controller_name_dialog)
        mmenu.add_cascade(label = "MIDI Maps", menu = map_menu)
        mmenu.add_command(label = "Toggle MIDI Input Trace", command = self.toggle_midi_input_trace)
        mmenu.add_command(label = "Toggle MIDI Output Trace", command = self.toggle_midi_output_trace)
        mmenu.add_command(label = "Toggle Program Pretty Printer", command = self.toggle_program_pretty_printer)
        
    def _init_bus_menu(self, bmenu):
        bmenu.add_command(label="Audio", command=self.show_audiobus_dialog)
        bmenu.add_command(label="Control", command=self.show_controlbus_dialog)
        
    # def _init_buffer_menu(self, bmenu):
    #     bmenu.add_command(label="View Buffers", command=self.show_bufferlist_dialog)

    def _init_tune_menu(self, tmenu):
        tmenu.add_command(label = "FIX ME: Nothing to see here")

    def _init_help_menu(self, hmenu):
        pass
        
    def exit_gui(self):
        try:
            self.root.destroy()
        except:
            pass

    def confirm_exit(self):
        return tkMessageBox.askyesno("Exit Llia", "Exit Llia?")
        
    def exit_app(self):
        self.app.exit_()

    def as_widget(self):
        return self.root
        
    def status(self, msg):
        self._lab_status.config(text=str(msg))

    def warning(self, msg):
        msg = "WARNING: %s" % msg
        self._lab_status.config(text=msg)
        
    def clear_status(self):
        self.status("")
                                              
    def start_gui_loop(self):
        self.root.mainloop()

    def show_about_dialog(self):
        from llia.gui.tk.tk_about_dialog import TkAboutDialog
        dialog = TkAboutDialog(self.root, self.app)
        self.root.wait_window(dialog)

    def display_help(self, topic=None):
        pass
        
    def show_history_editor(self):
        from llia.gui.tk.tk_history import TkHistoryEditor
        dialog = TkHistoryEditor(self.root, self.app)
        self.root.wait_window(dialog)

    def ping_global(self):
        try:
            rs = self.app.proxy.ping()
            if rs:
                self.status("Ping OK")
            else:
                self.warning("Ping Error")
        except LliaPingError as err:
            self.warning(err.message)

    def toggle_osc_trace(self):
        LliaProxy.trace = not LliaProxy.trace
        if LliaProxy.trace:
            self.status("OSC transmission trace enabled")
        else:
            self.status("OSC transmission trace disabled")

    def show_channel_name_dialog(self):
        from llia.gui.tk.tk_channel_name_editor import TkChannelNameEditor
        dialog = TkChannelNameEditor(self.root, self.app)
        self.root.wait_window(dialog)
  
    def show_controller_name_dialog(self):
        from llia.gui.tk.tk_controller_name_editor import TkControllerNameEditor
        dialog = TkControllerNameEditor(self.root, self.app)
        self.root.wait_window(dialog)
    
    def toggle_midi_input_trace(self):
        flag = not self.app.midi_in_trace
        self.app.midi_in_trace = flag
        self.app.midi_receiver.enable_trace(flag)
        if flag:
            self.status("MIDI input trace enabled")
        else:
            self.status("MIDI output trace disabled")

    def toggle_midi_output_trace(self):
        self.status("MIDI output not available") # FIX ME

    def toggle_program_pretty_printer(self):
        self.app.pp_enabled = not self.app.pp_enabled
        if self.app.pp_enabled:
            self.status("Pretty printer enabled")
        else:
            self.status("Pretty printer disabled")
        
    def show_audiobus_dialog(self):
        from llia.gui.tk.tk_audiobus_editor import TkAudiobusEditor
        dialog = TkAudiobusEditor(self.root, self.app)
        self.root.wait_window(dialog)

    def show_controlbus_dialog(self):
        from llia.gui.tk.tk_controlbus_editor import TkControlbusEditor
        dialog = TkControlbusEditor(self.root, self.app)
        self.root.wait_window(dialog)

    # def show_bufferlist_dialog(self):
    #     from llia.gui.tk.tk_buffer_info import TkBufferListDialog
    #     dialog = TkBufferListDialog(self.root, self.app)
    #     self.root.wait_window(dialog)

    def _show_add_synth_dialog(self, event):
        w = event.widget
        st = w.config()["text"][-1]
        dialog = TkAddSynthDialog(self.root, self.app, st, False)
        self.root.wait_window(dialog)
        
    def _show_add_efx_dialog(self, event):
        w = event.widget
        st = w.config()["text"][-1]
        dialog = TkAddSynthDialog(self.root, self.app, st, is_efx=True, is_controller=False)
        self.root.wait_window(dialog)

    def _show_add_controller_dialog(self, event):
        w = event.widget
        st = w.config()["text"][-1]
        dialog = TkAddSynthDialog(self.root, self.app, st, is_efx=False, is_controller=True)
        self.root.wait_window(dialog)
        
    def _add_synth_group(self):
        sh = self.app.ls_parser.synthhelper
        sh.new_group()
        
    def add_synth_group(self, name=None):
        gw = GroupWindow(self.app, self.root, name)
        # gw.transient(self.root)  # If executed keeps main app window behind all other windows.
        self.group_windows.append(gw)
        self.status("Added new Synth Group Window")
        return gw

    def display_synth_editor(self, sid):
        try:
            swin = self[sid]
            grpid = swin.group_index
            grp = self.group_windows[grpid]
            #grp.deiconify()
            grp.show_synth_editor(sid)
        except (KeyError, IndexError):
            msg = "Can not find editor for %s" % sid
            self.warning(msg)

    def update_progressbar(self, count, value):
        self._progressbar.config(mode="determinate", maximum=count)
        self._progressbar.step()
        self.root.update_idletasks()
            
    def busy(self, flag, message=""):
        if message:
            self.status(message)
        self._progressbar.config(mode="indeterminate")
        if flag:
            self._progressbar.grid(row=0, column=PROGRESSBAR_COLUMN, sticky='w', padx=8)
            self._progressbar.start()
        else:
            self._progressbar.stop()
            # self._progressbar.grid_remove()
        self.root.update_idletasks()

    def save_scene(self, *_):
        options = {'defaultextension' : '.llia',
                   'filetypes' : [('Llia Scenes', '*.llia'),
                                  ('all files', '*')],
                   'initialfile' : self._scene_filename,
                   'parent' : self.root,
                   'title' : "Save Llia Scene"}
        filename = tkFileDialog.asksaveasfilename(**options)
        if filename:
            try:
                self.app.ls_parser.save_scene(filename)
                self._scene_filename = filename
                self.status("Scene saved as '%s'" % filename)
            except Exception as ex:
                self.warning(ex.message)
        else:
            self.status("Scene save canceld")    

    def load_scene(self, *_):
        options = {'defaultextension' : '.llia',
                   'filetypes' : [('Llia Scenes', '*.llia'),
                                  ('all files', '*')],
                   'initialfile' : self._scene_filename,
                   'parent' : self.root,
                   'title' : "Load Llia Scene"}
        filename = tkFileDialog.askopenfilename(**options)
        if filename:
            try:
                self.app.ls_parser.load_scene(filename)
                self.status("Scene '%s' loaded" % filename)
                self._scene_filename = filename
            except Exception as ex:
                self.warning(ex.message)
        else:
            self.status("Load scene canceld")
            
    def tabula_rasa(self):
        for grp in self.group_windows:
            grp.tabula_rasa()
        self.group_windows = []

    def _interactive_tabula_rasa(self, *_):
        # ISSUE: Check config and ask user confirmation before existing
        self.app.ls_parser.tabula_rasa()
コード例 #4
0
ファイル: main.py プロジェクト: sskkcisos/quora-analytics
class QuoraAnalyticsUI(Notebook):

  def __init__(self):
    self.parent = Tkinter.Tk()
    Notebook.__init__(self, self.parent)
    #self.parent.title('Quora Analytics')
    self.parent.title('Quora Backup and Analytics')
    self.parent.wm_title('Quora Backup and Analytics')
    self.parent.grid_rowconfigure(0, weight=1)
    self.parent.grid_columnconfigure(0, weight=1)
    self.parent.resizable(True, True)
    self.grid_rowconfigure(0, weight=1)
    self.grid_columnconfigure(0, weight=1)
    self.crawler = QuoraCrawler(driver=QuoraCrawler.CHROME_DRIVER)
    self._add_frames()
    self.pack(fill='both', expand=True)

  def _add_frames(self):
    # Adding Answer Backup Frame
    f1 = Frame(self)
    f1.grid(column=0, row=0, sticky="NWES")
    for i in range(4):
      f1.grid_rowconfigure(i, weight=0, pad=5)
    f1.grid_rowconfigure(4, weight=1, pad=5)
    for i in range(4):
      f1.grid_columnconfigure(i, weight=1, pad=5)

    Label(f1, anchor='e', text='Answers Count : ').grid(column=0, row=0, sticky='EWNS')
    self.answer_count = StringVar(value=len(self.crawler.answer_list))
    Label(f1, anchor='w', textvariable=self.answer_count).grid(column=1, row=0, sticky='EWNS')
    Label(f1, anchor='e', text='User Name : ').grid(column=2, row=0, sticky='EWNS')
    self.user = StringVar(value='Unknown')
    Label(f1, anchor='w', textvariable=self.user).grid(column=3, row=0, sticky='EWNS')

    tf_col = '#e6e6e6'
    tf = Tkinter.Frame(f1, relief=GROOVE, borderwidth='2p')
    tf.grid(row=1, columnspan=2, column=0, sticky='EWNS')
    Label(tf, text='Quora User Options', bg=tf_col, anchor='c').grid(column=0, row=0, columnspan=2, sticky='EWNS')
    Button(tf, text='Login', command=lambda : self.thread('login'),
      highlightbackground=tf_col).grid(column=0, row=1, sticky='EWNS')
    Button(tf, text='Logout', command=lambda : self.thread('logout'),
      highlightbackground=tf_col).grid(column=1, row=1, sticky='EWNS')
    tf.grid_rowconfigure(0, weight=1, pad=5)
    tf.grid_rowconfigure(1, weight=1, pad=5)
    tf.grid_columnconfigure(0, weight=1, pad=5)
    tf.grid_columnconfigure(1, weight=1, pad=5)

    tf = Frame(f1, relief=GROOVE, borderwidth='2p')
    tf.grid(row=1, columnspan=2, column=2, sticky='EWNS')
    Label(tf, text='Answer List Option', bg=tf_col, anchor='c').grid(column=0, columnspan=2, row=0, sticky='EWNS')
    Button(tf, text='Reset', command=lambda : self.thread('reset'),
      highlightbackground=tf_col).grid(column=0, row=1, sticky='EWNS')
    Button(tf, text='Update', command=lambda : self.thread('update'),
      highlightbackground=tf_col).grid(column=1, row=1, sticky='EWNS')
    tf.grid_rowconfigure(0, weight=1, pad=5)
    tf.grid_rowconfigure(1, weight=1, pad=5)
    tf.grid_columnconfigure(0, weight=1, pad=5)
    tf.grid_columnconfigure(1, weight=1, pad=5)

    # Add Progress Bar
    self.backup_progress = Progressbar(f1, orient="horizontal", length=100, mode="determinate")
    self.backup_progress.grid(row=2, columnspan=4, column=0, sticky='EWNS')

    # Adding Status Pane
    self.backup_status = StringVar(value='Ready')
    Label(f1, textvariable=self.backup_status, anchor='w').grid(row=3, column=0, columnspan=4, sticky='EWNS')

    # Adding The list of all answers
    tree = Treeview(f1, columns=('sno', 'date', 'question'))
    tree.heading('sno', text='S. No')
    tree.heading('date', text='Date')
    tree.heading('question', text='Question')

    tree.column("#0", width=0, stretch=False)
    tree.column('sno', width=40, stretch=False, anchor='center')
    tree.column('date', width=120, stretch=False, anchor='center')
    tree.column('question', stretch=True, anchor='w')
    tree.grid(column=0, columnspan=4, row=4, sticky='EWNS')
    tree.bind("<Double-1>", self.tree_item_click)
    self.answer_tree = tree
    self.populate_tree()

    f2 = Frame(self)
    self.add(f1, text='Answer Backup', underline=7)
    self.add(f2, text='Analytics')

  def tree_item_click(self, event):
    idx_clicked = self.answer_tree.identify_row(event.y)
    if idx_clicked:
      print "Tree Item Clicked - ", idx_clicked

  def show_busy_dialog(self):
    tkMessageBox.showerror(
      title='Task in Progress',
      message=BUSY_MSG,
      icon=tkMessageBox.INFO
    )

  def thread(self, task):
    print "Starting a new Thread for " + task
    if self.backup_status.get() != 'Ready': self.show_busy_dialog()
    else:
      self.backup_status.set('Starting a new Task...')
      task_ids = (
        ('login', self.login_crawler),
        ('logout', self.logout_crawler),
        ('update', self.update_answer_list),
        ('reset', self.reset_answer_list)
      )

      for task_relation in task_ids:
        if task == task_relation[0]: Thread(target=task_relation[1]).start()

  def reset_answer_list(self):
    confirm = tkMessageBox.askquestion(
      title='Confirm Reset',
      message=RESET_MSG,
      icon='warning'
    )
    if confirm == 'yes':
      self.backup_status.set('Reseting Answer List...')
      self.backup_progress.start(interval=500)
      self.crawler.reset_answer_list()
      self.answer_count.set(len(self.crawler.answer_list))
      self.populate_tree()

    self.backup_status.set('Ready')
    self.backup_progress.stop()
    self.backup_progress['value'] = 0

  def update_answer_list(self):
    try:
      self.backup_status.set('Checking Login Status...')
      self.backup_progress.start(interval=500)
      if not self.crawler.check_login(self.backup_progress, self.backup_status):
        self.backup_status.set('Logged Out !! Cannot continue')
        tkMessageBox.showerror(
          title='Login Required',
          message=LOGIN_REQ_MSG,
          icon=tkMessageBox.INFO
        )
      else:
        self.backup_progress['value'] = 10
        self.backup_status.set('Updating Answer List...It may take few minutes')
        self.crawler.update_answer_list(self.backup_progress, self.backup_status)
        self.answer_count.set(len(self.crawler.answer_list))
        self.populate_tree()
    except STException:
      tkMessageBox.showerror(
        title='Operation Aborted',
        message=TIMEOUT_MSG,
        icon=tkMessageBox.ERROR
      )

    self.backup_status.set('Ready')
    self.backup_progress.stop()
    self.backup_progress['value'] = 0

  def login_crawler(self):
    try:
      self.backup_status.set('Checking Login Status...')
      self.backup_progress.start(interval=500)
      self.backup_progress['value'] = 10
      if self.crawler.check_login(self.backup_progress, self.backup_status):
        self.backup_progress['value'] = 100
        self.backup_progress.stop()
        tkMessageBox.showinfo(
          title='Login Successful',
          message=ALREADY_LOGIN_MSG,
          icon=tkMessageBox.INFO
        )
        self.user.set(self.crawler.get_user_name())
      else:
        # Opening Pop Up
        self.backup_status.set('Waiting For Credentials...')
        self.backup_progress['value'] = 40
        self.loginpop = PasswordPopUp(self)
        self.loginpop.grab_set() # To lock parent window when child is shown
        self.parent.wait_window(self.loginpop)
        self.loginpop.grab_release() # Reactivate parent window
        email = self.loginpop.uname.strip()
        passw = self.loginpop.passw.strip()
        if len(email) > 0 and len(passw) > 0:
          try:
            self.backup_status.set('Trying to log in with ' + email + ' ...')
            self.backup_progress['value'] = 60
            self.crawler.login(email, passw, self.backup_progress, self.backup_status)
            self.user.set(self.crawler.get_user_name())
          except QuoraCrawler.InvalidCredentialException, e:
            self.backup_status.set('Login Unsuccessful')
            self.backup_progress['value'] = 100
            self.backup_progress.stop()
            tkMessageBox.showerror(
              title='Invalid Credentials',
              message=e.message,
              icon=tkMessageBox.ERROR
            )
    except STException:
      tkMessageBox.showerror(
        title='Operation Aborted',
        message=TIMEOUT_MSG,
        icon=tkMessageBox.ERROR
      )

    self.backup_status.set('Ready')
    self.backup_progress.stop()
    self.backup_progress['value'] = 0

  def logout_crawler(self):
    try:
      self.backup_progress.start(interval=500)
      self.backup_status.set('Trying to Logging Out')
      self.crawler.logout(self.backup_progress, self.backup_status)
      self.user.set('Logged Out')
    except STException:
      tkMessageBox.showerror(
        title='Operation Aborted',
        message=TIMEOUT_MSG,
        icon=tkMessageBox.ERROR
      )
    self.backup_status.set('Ready')
    self.backup_progress.stop()
    self.backup_progress['value'] = 0

  def populate_tree(self):
    for i in self.answer_tree.get_children():
        self.answer_tree.delete(i)
    for idx, answer in enumerate(self.crawler.answer_list):
      self.answer_tree.insert('', 'end', idx + 1,
                              value=((idx + 1, answer[1], answer[2])))

  def destroy(self):
    self.crawler.quit()
    Notebook.destroy(self)
コード例 #5
0
class VideoScanProgressScreen(GuiBaseFrame):
    def __init__(self, parent, controller, **kw):
        GuiBaseFrame.__init__(self, parent, controller, **kw)
        self.counting_left_frames = None

    def init_widgets(self):
        self.content_wrapper = Frame(self)
        self.content_wrapper.configure(background="white")
        self.screen_title = Header1Label(
            self.content_wrapper, text="Scanning video for information...\n")
        self.progress_bar = Progressbar(self.content_wrapper,
                                        orient=HORIZONTAL,
                                        mode="indeterminate",
                                        length=WINDOW_WIDTH / 2)
        self.wait_text = PLabel(
            self.content_wrapper,
            text="\nThis might take a few minutes."
            "\nPlease do not change the video files while this is running.\n")
        self.left_frames_count = PLabel(self.content_wrapper,
                                        text=LEFT_FRAMES_COUNT_PREFIX + "0")
        self.right_frames_count = PLabel(self.content_wrapper,
                                         text=RIGHT_FRAMES_COUNT_PREFIX + "0")
        self.elapsed_time_label = PLabel(self.content_wrapper)
        self.empty_space = PLabel(self.content_wrapper, text=" ")
        self.next_button = Button(
            self.content_wrapper,
            text="Next",
            state=DISABLED,
            command=lambda: self.controller.show_next_frame())

    def add_widgets_to_frame(self):
        self.screen_title.pack()
        self.progress_bar.pack()
        self.wait_text.pack()
        self.left_frames_count.pack()
        self.right_frames_count.pack()
        self.elapsed_time_label.pack()
        self.empty_space.pack()
        self.next_button.pack()
        self.content_wrapper.place(relx=SCREENS_REL_X,
                                   rely=SCREEN_REL_Y_45,
                                   anchor=CENTER)

    def on_show_frame(self):
        self.start_time = time.time()
        self.progress_bar.start()
        self.frame_count_thread = threading.Thread(
            target=self.controller.video_frame_loader.count_frames_in_videos,
            kwargs={"controller": self.controller})
        self.frame_count_thread.start()
        self.master.after(50, self.check_thread)

    def update_frame(self, data):
        if LEFT_FRAMES_COUNT_PREFIX in data:
            self.left_frames_count.configure(text=data)
        if RIGHT_FRAMES_COUNT_PREFIX in data:
            self.right_frames_count.configure(text=data)

        self.elapsed_time_label.configure(
            text=ELAPSED_TIME_PREFIX +
            str(datetime.timedelta(seconds=int(time.time() -
                                               self.start_time))))

    def on_hide_frame(self):
        self.progress_bar.stop()

    def check_thread(self):
        if self.frame_count_thread.is_alive():
            self.master.after(50, self.check_thread)
        else:
            self.progress_bar.stop()
            self.wait_text.configure(text="\nDone!\nPress Next to continue.\n")
            self.next_button.configure(state=NORMAL)
コード例 #6
0
ファイル: main.py プロジェクト: Alafazam/quora-analytics
class QuoraAnalyticsUI(Notebook):
    def __init__(self):
        self.parent = Tkinter.Tk()
        Notebook.__init__(self, self.parent)
        # self.parent.title('Quora Analytics')
        self.parent.title("Quora Backup and Analytics")
        self.parent.wm_title("Quora Backup and Analytics")
        self.parent.grid_rowconfigure(0, weight=1)
        self.parent.grid_columnconfigure(0, weight=1)
        self.parent.resizable(True, True)
        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)
        self.crawler = QuoraCrawler(driver=QuoraCrawler.CHROME_DRIVER)
        self._add_frames()
        self.pack(fill="both", expand=True)

    def _add_frames(self):
        # Adding Answer Backup Frame
        f1 = Frame(self)
        f1.grid(column=0, row=0, sticky="NWES")
        for i in range(4):
            f1.grid_rowconfigure(i, weight=0, pad=5)
        f1.grid_rowconfigure(4, weight=1, pad=5)
        for i in range(4):
            f1.grid_columnconfigure(i, weight=1, pad=5)

        Label(f1, anchor="e", text="Answers Count : ").grid(column=0, row=0, sticky="EWNS")
        self.answer_count = StringVar(value=len(self.crawler.answer_list))
        Label(f1, anchor="w", textvariable=self.answer_count).grid(column=1, row=0, sticky="EWNS")
        Label(f1, anchor="e", text="User Name : ").grid(column=2, row=0, sticky="EWNS")
        self.user = StringVar(value="Unknown")
        Label(f1, anchor="w", textvariable=self.user).grid(column=3, row=0, sticky="EWNS")

        tf_col = "#e6e6e6"
        tf = Tkinter.Frame(f1, relief=GROOVE, borderwidth="2p")
        tf.grid(row=1, columnspan=2, column=0, sticky="EWNS")
        Label(tf, text="Quora User Options", bg=tf_col, anchor="c").grid(column=0, row=0, columnspan=2, sticky="EWNS")
        Button(tf, text="Login", command=lambda: self.thread("login"), highlightbackground=tf_col).grid(
            column=0, row=1, sticky="EWNS"
        )
        Button(tf, text="Logout", command=lambda: self.thread("logout"), highlightbackground=tf_col).grid(
            column=1, row=1, sticky="EWNS"
        )
        tf.grid_rowconfigure(0, weight=1, pad=5)
        tf.grid_rowconfigure(1, weight=1, pad=5)
        tf.grid_columnconfigure(0, weight=1, pad=5)
        tf.grid_columnconfigure(1, weight=1, pad=5)

        tf = Frame(f1, relief=GROOVE, borderwidth="2p")
        tf.grid(row=1, columnspan=2, column=2, sticky="EWNS")
        Label(tf, text="Answer List Option", bg=tf_col, anchor="c").grid(column=0, columnspan=2, row=0, sticky="EWNS")
        Button(tf, text="Reset", command=lambda: self.thread("reset"), highlightbackground=tf_col).grid(
            column=0, row=1, sticky="EWNS"
        )
        Button(tf, text="Update", command=lambda: self.thread("update"), highlightbackground=tf_col).grid(
            column=1, row=1, sticky="EWNS"
        )
        tf.grid_rowconfigure(0, weight=1, pad=5)
        tf.grid_rowconfigure(1, weight=1, pad=5)
        tf.grid_columnconfigure(0, weight=1, pad=5)
        tf.grid_columnconfigure(1, weight=1, pad=5)

        # Add Progress Bar
        self.backup_progress = Progressbar(f1, orient="horizontal", length=100, mode="determinate")
        self.backup_progress.grid(row=2, columnspan=4, column=0, sticky="EWNS")

        # Adding Status Pane
        self.backup_status = StringVar(value="Ready")
        Label(f1, textvariable=self.backup_status, anchor="w").grid(row=3, column=0, columnspan=4, sticky="EWNS")

        # Adding The list of all answers
        tree = Treeview(f1, columns=("sno", "date", "question"))
        tree.heading("sno", text="S. No")
        tree.heading("date", text="Date")
        tree.heading("question", text="Question")

        tree.column("#0", width=0, stretch=False)
        tree.column("sno", width=40, stretch=False, anchor="center")
        tree.column("date", width=120, stretch=False, anchor="center")
        tree.column("question", stretch=True, anchor="w")
        tree.grid(column=0, columnspan=4, row=4, sticky="EWNS")
        tree.bind("<Double-1>", self.tree_item_click)
        self.answer_tree = tree
        self.populate_tree()

        f2 = Frame(self)
        self.add(f1, text="Answer Backup", underline=7)
        self.add(f2, text="Analytics")

    def tree_item_click(self, event):
        idx_clicked = self.answer_tree.identify_row(event.y)
        if idx_clicked:
            print "Tree Item Clicked - ", idx_clicked

    def show_busy_dialog(self):
        tkMessageBox.showerror(title="Task in Progress", message=BUSY_MSG, icon=tkMessageBox.INFO)

    def thread(self, task):
        print "Starting a new Thread for " + task
        if self.backup_status.get() != "Ready":
            self.show_busy_dialog()
        else:
            self.backup_status.set("Starting a new Task...")
            task_ids = (
                ("login", self.login_crawler),
                ("logout", self.logout_crawler),
                ("update", self.update_answer_list),
                ("reset", self.reset_answer_list),
            )

            for task_relation in task_ids:
                if task == task_relation[0]:
                    Thread(target=task_relation[1]).start()

    def reset_answer_list(self):
        confirm = tkMessageBox.askquestion(title="Confirm Reset", message=RESET_MSG, icon="warning")
        if confirm == "yes":
            self.backup_status.set("Reseting Answer List...")
            self.backup_progress.start(interval=500)
            self.crawler.reset_answer_list()
            self.answer_count.set(len(self.crawler.answer_list))
            self.populate_tree()

        self.backup_status.set("Ready")
        self.backup_progress.stop()
        self.backup_progress["value"] = 0

    def update_answer_list(self):
        try:
            self.backup_status.set("Checking Login Status...")
            self.backup_progress.start(interval=500)
            if not self.crawler.check_login(self.backup_progress, self.backup_status):
                self.backup_status.set("Logged Out !! Cannot continue")
                tkMessageBox.showerror(title="Login Required", message=LOGIN_REQ_MSG, icon=tkMessageBox.INFO)
            else:
                self.backup_progress["value"] = 10
                self.backup_status.set("Updating Answer List...It may take few minutes")
                self.crawler.update_answer_list(self.backup_progress, self.backup_status)
                self.answer_count.set(len(self.crawler.answer_list))
                self.populate_tree()
        except STException:
            tkMessageBox.showerror(title="Operation Aborted", message=TIMEOUT_MSG, icon=tkMessageBox.ERROR)

        self.backup_status.set("Ready")
        self.backup_progress.stop()
        self.backup_progress["value"] = 0

    def login_crawler(self):
        try:
            self.backup_status.set("Checking Login Status...")
            self.backup_progress.start(interval=500)
            self.backup_progress["value"] = 10
            if self.crawler.check_login(self.backup_progress, self.backup_status):
                self.backup_progress["value"] = 100
                self.backup_progress.stop()
                tkMessageBox.showinfo(title="Login Successful", message=ALREADY_LOGIN_MSG, icon=tkMessageBox.INFO)
                self.user.set(self.crawler.get_user_name())
            else:
                # Opening Pop Up
                self.backup_status.set("Waiting For Credentials...")
                self.backup_progress["value"] = 40
                self.loginpop = PasswordPopUp(self)
                self.loginpop.grab_set()  # To lock parent window when child is shown
                self.parent.wait_window(self.loginpop)
                self.loginpop.grab_release()  # Reactivate parent window
                email = self.loginpop.uname.strip()
                passw = self.loginpop.passw.strip()
                if len(email) > 0 and len(passw) > 0:
                    try:
                        self.backup_status.set("Trying to log in with " + email + " ...")
                        self.backup_progress["value"] = 60
                        self.crawler.login(email, passw, self.backup_progress, self.backup_status)
                        self.user.set(self.crawler.get_user_name())
                    except QuoraCrawler.InvalidCredentialException, e:
                        self.backup_status.set("Login Unsuccessful")
                        self.backup_progress["value"] = 100
                        self.backup_progress.stop()
                        tkMessageBox.showerror(title="Invalid Credentials", message=e.message, icon=tkMessageBox.ERROR)
        except STException:
            tkMessageBox.showerror(title="Operation Aborted", message=TIMEOUT_MSG, icon=tkMessageBox.ERROR)

        self.backup_status.set("Ready")
        self.backup_progress.stop()
        self.backup_progress["value"] = 0

    def logout_crawler(self):
        try:
            self.backup_progress.start(interval=500)
            self.backup_status.set("Trying to Logging Out")
            self.crawler.logout(self.backup_progress, self.backup_status)
            self.user.set("Logged Out")
        except STException:
            tkMessageBox.showerror(title="Operation Aborted", message=TIMEOUT_MSG, icon=tkMessageBox.ERROR)
        self.backup_status.set("Ready")
        self.backup_progress.stop()
        self.backup_progress["value"] = 0

    def populate_tree(self):
        for i in self.answer_tree.get_children():
            self.answer_tree.delete(i)
        for idx, answer in enumerate(self.crawler.answer_list):
            self.answer_tree.insert("", "end", idx + 1, value=((idx + 1, answer[1], answer[2])))

    def destroy(self):
        self.crawler.quit()
        Notebook.destroy(self)
コード例 #7
0
ファイル: main.py プロジェクト: offtirael/MuBlas
class iface():
        def __init__(self):
            
            root.title("MuBlas")
            
            self.lab1 = Label(root, text="Music directory")
            self.lab1.grid(row = 0, column = 0)
            
            self.music_entry = Entry(root,width=50,bd=1)
            self.music_entry.grid(row = 1, column = 0)
            
            self.m_dir_but = Button(root)
            self.m_dir_but["text"] = "Choose directory"
            self.m_dir_but.grid(row = 1, column = 1)
            self.m_dir_but.bind("<Button-1>", self.ask_mus_dir)
            
            self.lab3 = Label(root, text="Size in MBytes")
            self.lab3.grid(row = 2, column = 0)
            
            self.size_entry = Entry(root,width=5,bd=1)
            self.size_entry.grid(row = 2, column = 1)
            
            self.lab2 = Label(root, text="Destination directory")
            self.lab2.grid(row = 3, column = 0)
            
            self.destination_entry = Entry(root,width=50,bd=1)
            self.destination_entry.grid(row = 4, column = 0)
            
            self.dest_dir_but = Button(root)
            self.dest_dir_but["text"] = "Choose directory"
            self.dest_dir_but.grid(row = 4, column = 1)
            self.dest_dir_but.bind("<Button-1>", self.ask_out_dir)
            
            self.process_but = Button(root)
            self.process_but["text"] = "Run"
            self.process_but.grid(row = 6, column = 0)
            self.process_but.bind("<Button-1>", self.start)
            
            self.exit_but = Button(root)
            self.exit_but["text"] = "Exit"
            self.exit_but.grid(row = 6, column = 1)
            self.exit_but.bind("<Button-1>", self.exit_app)
            
            self.pr_bar = Progressbar(root, mode='indeterminate')
            self.pr_bar.grid(row = 5, column = 0, sticky = "we", columnspan = 2)
            
            #self.pr_bar.start()
            

        def ask_mus_dir(self, event):
            dirname = tkFileDialog.askdirectory(parent = root,initialdir="/",title='Please select a directory')
            self.music_entry.delete(0, END)
            self.music_entry.insert(0, dirname)

        def ask_out_dir(self, event):
            dirname = tkFileDialog.askdirectory(parent = root,initialdir="/",title='Please select a directory')
            self.destination_entry.delete(0, END)
            self.destination_entry.insert(0, dirname)
            
        def start(self, event):
            self.pr_bar.start()
            self.process_but["state"] = DISABLED
            
            m_dir = self.music_entry.get()
            d_dir = self.destination_entry.get()
            sz = 1024000 * int(self.size_entry.get())
            
            mbls = MuBlas.MuBlas(m_dir, d_dir, sz)
            mbls.start()
            
            self.process_but["state"] = NORMAL
            self.pr_bar.stop()
            
        def exit_app(self, event):
            root.destroy()
            
        def process(self):
コード例 #8
0
ファイル: Metadator.py プロジェクト: Guts/Metadator
class Metadator(Tk):
    def __init__(self):
        u"""
        Main window constructor
        Creates 1 frame and 2 labeled subframes
        """
        # first: the log
        # see: http://sametmax.com/ecrire-des-logs-en-python/
        self.logger = logging.getLogger()
        self.logger.setLevel(logging.DEBUG)  # all errors will be get
        log_form = logging.Formatter('%(asctime)s || %(levelname)s || %(message)s')
        logfile = RotatingFileHandler('Metadator_LOG.log', 'a', 5000000, 1)
        logfile.setLevel(logging.DEBUG)
        logfile.setFormatter(log_form)
        self.logger.addHandler(logfile)
        self.logger.info('\n\t ======== Metadator ========')  # first messages
        self.logger.info('Starting the UI')

        # checking the path to GDAL in the path
        if "GDAL_DATA" not in env.keys():
            try:
                gdal.SetConfigOption(str('GDAL_DATA'),
                                     str(path.abspath(r'data/gdal')))
            except:
                print("Oups! Something has gone wrong...\
                      see: https://github.com/Guts/Metadator/issues/21")
        else:
            pass

        # basics settings
        Tk.__init__(self)           # constructor of parent graphic class
        self.title(u'Metadator {0}'.format(MetadatorVersion))
        self.style = Style()        # more friendly windows style
        if opersys == 'win32':
            self.logger.info('Op. system: {0}'.format(platform.platform()))
            self.iconbitmap('Metadator.ico')    # windows icon
            self.uzer = env.get(u'USERNAME')
        elif opersys == 'linux2':
            self.logger.info('Op. system: {0}'.format(platform.platform()))
            self.uzer = env.get(u'USER')
            icon = Image("photo", file=r'data/img/metadator.gif')
            self.call('wm', 'iconphoto', self._w, icon)
            self.minsize(580, 100)
            self.style.theme_use('clam')
        elif opersys == 'darwin':
            self.logger.info('Op. system: {0}'.format(platform.platform()))
            self.uzer = env.get(u'USER')
        else:
            self.logger.warning('Operating system not tested')
            self.logger.info('Op. system: {0}'.format(platform.platform()))
        self.resizable(width=False, height=False)
        self.focus_force()

        self.logger.info('GDAL version: {}'.format(gdal.__version__))

        # variables
        self.def_rep = ""       # folder to search for
        self.def_lang = 'FR'    # language to start
        self.def_doc = IntVar()     # to export into Word
        self.def_xls = IntVar()     # to export into Excel 2003
        self.def_xml = IntVar()     # to export into ISO 19139
        self.def_cat = IntVar()     # to merge all output Word files
        self.def_odt = IntVar()     # to export into OpenDocumentText
        self.def_dict = IntVar()    # to make a dictionnary of data
        self.def_kass = IntVar()    # to handle field name case sensitive
        self.def_stat = IntVar()    # to active/disable stats fields
        self.li_pro = []            # list for profiles in language selected
        self.li_shp = []            # list for shapefiles path
        self.li_tab = []            # list for MapInfo tables path
        self.num_folders = 0        # number of folders explored
        self.today = strftime("%Y-%m-%d")   # date of the day
        self.dico_layer = OD()      # dictionary about layer properties
        self.dico_profil = OD()     # dictionary from profile selected
        self.dico_fields = OD()     # dictionary for fields information
        self.dico_rekur = OD()      # dictionary of recurring attributes
        self.dico_err = OD()     # errors list
        self.dico_help = OD()                # dictionary of help texts
        li_lang = [lg for lg in listdir(r'locale')]   # available languages
        self.blabla = OD()      # texts dictionary

        # GUI fonts
        ft_tit = tkFont.Font(family="Times", size=10, weight=tkFont.BOLD)

        # fillfulling
        self.load_settings()
        self.load_texts(self.def_lang)
        self.li_profiles(self.def_lang)
        self.li_rekurs(self.def_lang)
        self.recup_help(self.def_lang)

        # Tabs
        self.nb = Notebook(self)
        self.tab_globals = Frame(self.nb)   # tab_id = 0
        self.tab_options = Frame(self.nb)   # tab_id = 1
        self.tab_attribs = Frame(self.nb)   # tab_id = 2
        self.nb.add(self.tab_globals,
                    text=self.blabla.get('gui_tab1'), padding=3)
        self.nb.add(self.tab_options,
                    text=self.blabla.get('gui_tab2'), padding=3)
        self.nb.add(self.tab_attribs,
                    text=self.blabla.get('gui_tab3'), padding=3)
        self.logger.info('UI created')

                ### Tab 1: global
        # Frames
        self.FrPath = Labelframe(self.tab_globals,
                                 name='main',
                                 text=self.blabla.get('tab1_fr1'))
        self.FrProg = Labelframe(self.tab_globals,
                                 name='progression',
                                 text=self.blabla.get('tab1_frprog'))
            ## Frame 1
        # target folder
        self.labtarg = Label(self.FrPath, text=self.blabla.get('tab1_path'))
        self.target = Entry(self.FrPath, width=25)
        self.browsetarg = Button(self.FrPath,       # browse button
                                 text=self.blabla.get('tab1_browse'),
                                 command=lambda: self.setpathtarg(),
                                 takefocus=True)
        self.browsetarg.focus_force()               # force the focus on
        self.profil = Label(self.FrPath, text=self.blabla.get('tab1_prof'))
        # profiles switcher
        self.ddl_profil = Combobox(self.FrPath, values=self.li_pro, width=5)
        self.ddl_profil.current(0)
        self.ddl_profil.bind("<<ComboboxSelected>>", self.select_profil)
        # widgets placement
        self.labtarg.grid(row=1, column=1, columnspan=1,
                          sticky=N + S + W + E, padx=2, pady=8)
        self.target.grid(row=1, column=2, columnspan=1,
                         sticky=N + S + W + E, padx=2, pady=8)
        self.browsetarg.grid(row=1, column=3,
                             sticky=N + S + W + E, padx=2, pady=8)
        self.profil.grid(row=2, column=1,
                         sticky=N + S + W + E, padx=2, pady=8)
        self.ddl_profil.grid(row=2, column=2, sticky=W + E + N + S,
                             columnspan=2, padx=2, pady=8)

        # tooltips
        InfoBulle(self.target, message=self.dico_help.get(30)[1])
        InfoBulle(self.browsetarg, message=self.dico_help.get(30)[1])
        InfoBulle(self.ddl_profil, message=self.dico_help.get(31)[1])

            ## Frame 2
        # variables
        self.status = StringVar(self.FrProg, '')
        # widgets
        self.prog_layers = Progressbar(self.FrProg, orient="horizontal")
        self.prog_fields = Progressbar(self.FrProg, orient="horizontal")
        # widgets placement
        Label(self.FrProg, textvariable=self.status,
                           foreground='DodgerBlue').pack(expand=1)
        self.prog_layers.pack(expand=1, fill=X)

        # Frames placement
        self.FrPath.pack(expand=1, fill='both')
        self.FrProg.pack(expand=1, fill='both')

                ### Tab 2: options
        # Export options
        caz_doc = Checkbutton(self.tab_options,
                              text=u'HTML / Word (.doc/.docx)',
                              variable=self.def_doc,
                              command=lambda: self.catalog_dependance())
        caz_xls = Checkbutton(self.tab_options,
                              text=u'Excel 2003 (.xls)',
                              variable=self.def_xls)
        caz_xml = Checkbutton(self.tab_options,
                              text=u'XML (ISO 19139)',
                              variable=self.def_xml)
        self.caz_cat = Checkbutton(self.tab_options,
                                   text=self.blabla.get('tab2_merge'),
                                   variable=self.def_cat)
        caz_odt = Checkbutton(self.tab_options,
                              text=u'Open Document Text (.odt)',
                              variable=self.def_odt)
        # widgets placement
        caz_doc.grid(row=1,
                     column=0,
                     sticky=N + S + W + E,
                     padx=2, pady=2)
        self.caz_cat.grid(row=2,
                          column=0,
                          sticky=N + S + W + E,
                          padx=2, pady=2)
        caz_xls.grid(row=1,
                     column=1,
                     sticky=N + S + W + E,
                     padx=2, pady=2)
        caz_xml.grid(row=2,
                     column=1,
                     sticky=N + S + W + E,
                     padx=2, pady=2)
        caz_odt.grid(row=3,
                     column=1,
                     sticky=N + S + W + E,
                     padx=2, pady=2)
        # disabling the widgets which work only on Windows OS
        if opersys != 'win32':
            self.logger.info('Disabling Windows reserved functions.')
            self.def_doc.set(0)
            self.def_cat.set(0)
            caz_doc.configure(state='disabled')
            self.caz_cat.configure(state='disabled')
        else:
            pass
        # make the catalog option depending on the Word option
        self.catalog_dependance()

        # tooltips
        InfoBulle(caz_doc,
                  message=self.dico_help.get(33)[1],
                  image=self.dico_help.get(33)[2])
        InfoBulle(caz_xls,
                  message=self.dico_help.get(34)[1],
                  image=self.dico_help.get(34)[2])
        InfoBulle(caz_xml,
                  message=self.dico_help.get(35)[1],
                  image=self.dico_help.get(35)[2])
        InfoBulle(caz_odt,
                  message=self.dico_help.get(36)[1],
                  image=self.dico_help.get(36)[2])
        InfoBulle(self.caz_cat,
                  message=self.dico_help.get(37)[1],
                  image=self.dico_help.get(37)[2])

                ### Tab 3: recurring attributes
        # Attribute selector
        self.lab_chps = Label(self.tab_attribs, text=self.blabla.get('tab3_sele'))
        self.ddl_attr = Combobox(self.tab_attribs, values=self.dico_rekur.keys())
        self.ddl_attr.bind("<<ComboboxSelected>>", self.edit_rekur)
        self.supr = Button(self.tab_attribs, text=self.blabla.get('tab3_supp'),
                           command=self.del_rekur)
        # frame
        self.FrRekur = Labelframe(self.tab_attribs,
                                  name='attributes',
                                  text=self.blabla.get('tab3_tit'))
        # attribute settings
        self.tab3_LBnom = Label(self.FrRekur,
                                text=self.blabla.get('tab3_nom'),
                                state=DISABLED)
        self.tab3_ENnom = Entry(self.FrRekur, state=DISABLED)
        self.tab3_LBdesc = Label(self.FrRekur,
                                 text=self.blabla.get('tab3_desc'),
                                 state=DISABLED)
        self.tab3_TXdesc = Text(self.FrRekur,
                                height=5, width=30,
                                wrap=WORD, state=DISABLED)
        self.tab3_CBcass = Checkbutton(self.FrRekur,
                                       text=self.blabla.get('tab3_cass'),
                                       variable=self.def_kass,
                                       state=DISABLED)
        self.tab3_CBstat = Checkbutton(self.FrRekur,
                                       text=self.blabla.get('tab3_stat'),
                                       variable=self.def_stat,
                                       state=DISABLED)
        # Validation button
        self.save = Button(self.FrRekur,
                           text=self.blabla.get('tab3_save'),
                           command=self.save_rekur,
                           state='disabled')

        # widgets placement
        self.lab_chps.grid(row=1, column=1, sticky=N + S + W,
                           padx=2, pady=2)
        self.ddl_attr.grid(row=1, column=2, sticky=N + S + W + E,
                           padx=2, pady=2)
        self.supr.grid(row=1, column=3, sticky=N + S + W + E,
                       padx=2, pady=2)
        self.tab3_LBnom.grid(row=1, column=0, columnspan=1,
                             sticky=N + S + W, padx=2, pady=2)
        self.tab3_ENnom.grid(row=1, column=1, columnspan=1,
                             sticky=N + S + W + E, padx=2, pady=2)
        self.tab3_LBdesc.grid(row=2, column=0, columnspan=1,
                              sticky=N + S + W + E, padx=2, pady=2)
        self.tab3_TXdesc.grid(row=2, column=1, columnspan=2,
                              sticky=N + S + W + E, padx=2, pady=2)
        self.tab3_CBcass.grid(row=3, column=0, columnspan=1,
                              sticky=N + S + W + E, padx=2, pady=2)
        self.tab3_CBstat.grid(row=3, column=1, columnspan=1,
                              sticky=N + S + W + E, padx=2, pady=2)
        self.save.grid(row=5, column=0, columnspan=4,
                       sticky=N + S + W + E, padx=2, pady=2)

        # Frame placement
        self.FrRekur.grid(row=2, column=1, columnspan=3,
                          sticky=N + S + W + E, padx=2, pady=2)

        # tooltips
        InfoBulle(self.lab_chps, message=self.dico_help.get(38)[1])
        InfoBulle(self.ddl_attr, message=self.dico_help.get(39)[1])
        InfoBulle(self.supr, message=self.dico_help.get(40)[1])
        InfoBulle(self.tab3_CBcass, message=self.dico_help.get(41)[1])
        InfoBulle(self.tab3_CBstat, message=self.dico_help.get(42)[1])

            ## Main frame
        # Hola
        self.welcome = Label(self,
                             text=self.blabla.get('hi') + self.uzer,
                             font=ft_tit,
                             foreground="red2")
        # Image
        self.icone = PhotoImage(master=self, file=r'data/img/metadator.gif')
        Label(self, image=self.icone).grid(row=2,
                                           column=0,
                                           padx=2,
                                           pady=2,
                                           sticky=N + S + W + E)
        # credits
        s = Style(self)
        s.configure('Kim.TButton', foreground='DodgerBlue',
                    borderwidth=0, relief="flat")
        Button(self,
               text='by Julien M. (2015)',
               style='Kim.TButton',
               command=lambda: open_new('https://github.com/Guts')).grid(row=3,
                                                                         padx=2,
                                                                         pady=2,
                                                                         sticky=W+E)
        # language switcher
        self.ddl_lang = Combobox(self, values=li_lang, width=5)
        self.ddl_lang.current(li_lang.index(self.def_lang))
        self.ddl_lang.bind("<<ComboboxSelected>>", self.change_lang)
        # Go go go button
        self.val = Button(self,
                          text=self.blabla.get('tab1_go'),
                          state='active',
                          command=lambda: self.process())
        # Cancel button
        self.can = Button(self,
                          text=self.blabla.get('gui_quit'),
                          command=self.destroy)
        # widgets placement
        self.welcome.grid(row=0, column=0, columnspan=1, sticky=N + S + W + E,
                          padx=2, pady=2)
        self.ddl_lang.grid(row=1, column=0, sticky=N, padx=2, pady=0)
        self.can.grid(row=4, column=0, sticky=N + S + W + E, padx=2, pady=2)
        self.val.grid(row=4, column=1, sticky=N + S + W + E, padx=2, pady=2)

        # tooltips
        InfoBulle(self.ddl_lang, message=self.dico_help.get(32)[1])

                ### Notebook placement
        self.nb.grid(row=0, rowspan=4, column=1, sticky=N + S + W + E)
        # keep updated list of profiles
        self.maj()

    def maj(self):
        """
        update the profiles dropdown list every second
        """
        try:
            self.li_profiles(self.ddl_lang.get())
            self.ddl_profil['values'] = self.li_pro
            self.after(1000, self.maj)
        except WindowsError:    # avoid an error occuring with browse button
            self.after(1000, self.maj)
            pass

    def alter_state(self, parent, new_state):
        """
        just a function to change easily  the state of  all children widgets
        of a parent class

        parent=Tkinter class with children (Frame, Labelframe, Tk, etc.)
        new_state=Tkinter keyword for widget state (ACTIVE, NORMAL, DISABLED)
        """
        for child in parent.winfo_children():
            child.configure(state=new_state)
        # end of function
        return parent, new_state

    def catalog_dependance(self):
        """ unselect the catalog option if the word option is unselected """
        if self.def_doc.get() == 0:
            self.def_cat.set(0)
            self.caz_cat.config(state='disabled')
        elif self.def_doc.get() == 1:
            self.caz_cat.config(state='normal')
        # end of function
        return

    def load_settings(self):
        u""" load settings from last execution """
        confile = 'options.ini'
        config = ConfigParser.RawConfigParser()
        config.read(confile)
        # basics
        self.def_lang = config.get('basics', 'def_codelang')
        self.def_rep = config.get('basics', 'def_rep')
        # export preferences
        self.def_doc.set(config.get('export_preferences', 'def_word'))
        self.def_cat.set(config.get('export_preferences', 'def_cat'))
        self.def_xls.set(config.get('export_preferences', 'def_xls'))
        self.def_xml.set(config.get('export_preferences', 'def_xml'))
        self.def_dict.set(config.get('export_preferences', 'def_dict'))
        self.def_odt.set(config.get('export_preferences', 'def_odt'))
        # log
        self.logger.info('Last options loaded')
        # End of function
        return config, self.def_rep, self.def_lang, self.def_doc

    def save_settings(self):
        u""" save options in order to make the next execution easier """
        confile = 'options.ini'
        config = ConfigParser.RawConfigParser()
        # add sections
        config.add_section('basics')
        config.add_section('export_preferences')
        # basics
        config.set('basics', 'def_codelang', self.ddl_lang.get())
        config.set('basics', 'def_rep', self.target.get())
        # export preferences
        config.set('export_preferences', 'def_word', self.def_doc.get())
        config.set('export_preferences', 'def_cat', self.def_cat.get())
        config.set('export_preferences', 'def_xls', self.def_xls.get())
        config.set('export_preferences', 'def_xml', self.def_xml.get())
        config.set('export_preferences', 'def_dict', self.def_dict.get())
        config.set('export_preferences', 'def_odt', self.def_odt.get())
        # Writing the configuration file
        with open(confile, 'wb') as configfile:
            config.write(configfile)
        # End of function
        return config

    def change_lang(self, event):
        u""" update the texts dictionary with the language selected """
        new_lang = event.widget.get()
        # change to the new language selected
        self.load_texts(new_lang)
        self.li_profiles(new_lang)
        self.li_rekurs(new_lang)
        self.ddl_profil.delete(0, END)
        self.ddl_profil.config(values=self.li_pro)
        self.ddl_profil.update()
        self.ddl_attr.config(values=self.dico_rekur.keys())
        self.recup_help(new_lang)
        # update widgets text
          # tab1
        self.nb.tab(0, text=self.blabla.get('gui_tab1'))
        self.welcome.config(text=self.blabla.get('hi') + self.uzer)
        self.can.config(text=self.blabla.get('gui_quit'))
        self.FrPath.config(text=self.blabla.get('tab1_fr1'))
        self.FrProg.config(text=self.blabla.get('tab1_frprog'))
        self.labtarg.config(text=self.blabla.get('tab1_path'))
        self.browsetarg.config(text=self.blabla.get('tab1_browse'))
        self.val.config(text=self.blabla.get('tab1_go'))
        self.profil.config(text=self.blabla.get('tab1_prof'))
          # tab2
        self.nb.tab(1, text=self.blabla.get('gui_tab2'))
        self.caz_cat.config(text=self.blabla.get('tab2_merge'))
          # tab3
        self.nb.tab(2, text=self.blabla.get('gui_tab3'))
        self.lab_chps.config(text=self.blabla.get('tab3_sele'))
        self.supr.config(text=self.blabla.get('tab3_supp'))
        self.FrRekur.config(text=self.blabla.get('tab3_tit'))
        self.tab3_LBnom.config(text=self.blabla.get('tab3_nom'))
        self.tab3_LBdesc.config(text=self.blabla.get('tab3_desc'))
        self.tab3_CBcass.config(text=self.blabla.get('tab3_cass'))
        self.tab3_CBstat.config(text=self.blabla.get('tab3_stat'))
        self.save.config(text=self.blabla.get('tab3_save'))

        # End of function
        return self.blabla

    def load_texts(self, lang='FR'):
        u"""
        Load texts according to the selected language
        """
        # clearing the text dictionary
        self.blabla.clear()
        # open xml cursor
        xml = ET.parse('locale/{0}/lang_{0}.xml'.format(lang))
        # Looping and gathering texts from the xml file
        for elem in xml.getroot().getiterator():
            self.blabla[elem.tag] = elem.text
        # updating the GUI
        self.update()
        # en of function
        return self.blabla

    def setpathtarg(self):
        """ ...browse and insert the path of target folder """
        foldername = askdirectory(parent=self,
                                  initialdir=self.def_rep,
                                  mustexist=True,
                                  title=self.blabla.get('gui_cible'))
        # check if a folder has been choosen
        if foldername:
            try:
                self.target.delete(0, END)
                self.target.insert(0, foldername)
            except:
                info(title=self.blabla.get('nofolder'),
                     message=self.blabla.get('nofolder'))
                return

        # count shapefiles and MapInfo files in a separated thread
        proc = threading.Thread(target=self.li_geofiles,
                                args=(foldername, ))
        proc.daemon = True
        proc.start()

        # end of function
        return foldername

    def li_geofiles(self, foldertarget):
        u""" List shapefiles and MapInfo files (.tab, not .mid/mif) contained
        in the folders structure """
        # reseting global variables
        self.li_shp = []
        self.li_tab = []
        self.browsetarg.config(state=DISABLED)
        # Looping in folders structure
        self.status.set(self.blabla.get('tab1_prog1'))
        self.prog_layers.start()
        for root, dirs, files in walk(unicode(foldertarget)):
            self.num_folders = self.num_folders + len(dirs)
            for f in files:
                """ looking for files with geographic data """
                try:
                    unicode(path.join(root, f))
                    full_path = path.join(root, f)
                except UnicodeDecodeError:
                    full_path = path.join(root, f.decode('latin1'))
                # Looping on files contained
                if path.splitext(full_path.lower())[1].lower() == '.shp'\
                   and (path.isfile('{0}.dbf'.format(full_path[:-4]))
                        or path.isfile('{0}.DBF'.format(full_path[:-4])))\
                   and (path.isfile('{0}.shx'.format(full_path[:-4]))
                        or path.isfile('{0}.SHX'.format(full_path[:-4]))):
                    """ listing compatible shapefiles """
                    # add complete path of shapefile
                    self.li_shp.append(full_path)
                elif path.splitext(full_path.lower())[1] == '.tab'\
                    and (path.isfile(full_path[:-4] + '.dat')
                         or path.isfile(full_path[:-4] + '.DAT'))\
                    and (path.isfile(full_path[:-4] + '.map')
                         or path.isfile(full_path[:-4] + '.MAP'))\
                    and (path.isfile(full_path[:-4] + '.id')
                         or path.isfile(full_path[:-4] + '.ID')):
                    """ listing MapInfo tables """
                    # add complete path of MapInfo file
                    self.li_tab.append(full_path)
        # stopping the progress bar
        self.prog_layers.stop()
        # Lists ordering and tupling
        self.li_shp.sort()
        self.li_shp = tuple(self.li_shp)
        self.li_tab.sort()
        self.li_tab = tuple(self.li_tab)
        # setting the label text and activing the buttons
        self.status.set(unicode(len(self.li_shp)) + u' shapefiles - '
                        + unicode(len(self.li_tab)) + u' tables (MapInfo) - '
                        + unicode(self.num_folders) + self.blabla.get('log_numfold'))
        self.browsetarg.config(state=ACTIVE)
        self.val.config(state=ACTIVE)
        # End of function
        return foldertarget, self.li_shp, self.li_tab

    def li_profiles(self, lang):
        u"""
        list profiles already existing
        """
        # reseting global variable
        self.li_pro = []
        # Looping in folders structure
        folder_profiles = path.join('locale/', lang + '/profiles/')
        self.li_pro = [lg[:-4] for lg in listdir(folder_profiles)]
        self.li_pro.append(self.blabla.get('tab1_new'))
        # End of function
        return folder_profiles, self.li_pro

    def li_rekurs(self, lang):
        u"""
        List recurring attributes that already exist in the selected language
        """
        # clearing the text dictionary
        self.dico_rekur.clear()
        champis = path.abspath(r'locale/{0}/champignons_{0}.xml'.format(lang))
        xml = ET.parse(champis)
        # Looping and gathering texts from the xml file
        for elem in xml.findall('champ'):
            rek_name = elem.find('intitule').text
            rek_desc = elem.find('description').text
            rek_kass = elem.find('case').text
            rek_stat = elem.find('stats').text
            self.dico_rekur[rek_name] = rek_desc, rek_kass, rek_stat
        self.dico_rekur[self.blabla.get('tab3_new')] = '', 0, 0
        # updating the GUI
        self.update()
        # End of function
        return self.dico_rekur

    def edit_rekur(self, event):
        u"""
        preparing the form to edit a recurring attribute
        """
        rekur = event.widget.get()
        # deactivate the selector
        self.ddl_attr.config(state=DISABLED)
        # activate the form
        self.alter_state(self.FrRekur, NORMAL)
        # change to the new language selected
        self.tab3_ENnom.insert(0, rekur)
        self.tab3_TXdesc.insert(1.0, self.dico_rekur.get(rekur)[0])
        self.def_kass.set(self.dico_rekur.get(rekur)[1])
        self.def_stat.set(self.dico_rekur.get(rekur)[2])
        # End of function
        return self.dico_rekur

    def save_rekur(self):
        u""" save the recurring attribute edited """
        # check if the attribute already exists
        if self.tab3_ENnom.get() in self.dico_rekur:
            if not askyesno(title=self.blabla.get('tab3_alert_exist1'),
                            message=self.blabla.get('tab3_alert_exist2')):
                return
            else:
                pass
        else:
            pass

        # save
        self.dico_rekur[self.tab3_ENnom.get()] = self.tab3_TXdesc.get(1.0, END).rstrip(),\
                                                 self.def_kass.get(),\
                                                 self.def_stat.get()
        # reset the form
        self.tab3_ENnom.delete(0, END)
        self.tab3_TXdesc.delete(1.0, END)
        self.def_kass.set(0)
        self.def_stat.set(0)
        # deactivate the form
        self.alter_state(self.FrRekur, DISABLED)
        # updating the dropdown list
        self.ddl_attr.config(state=NORMAL)
        self.ddl_attr.delete(0, END)
        self.ddl_attr['values'] = self.dico_rekur.keys()

        # End of function
        return self.dico_rekur

    def del_rekur(self):
        u""" delete the selected recurring attribute """
        # reactivate the selector
        self.ddl_attr.config(state=ACTIVE)
        self.dico_rekur.pop(self.ddl_attr.get())

        self.ddl_attr.delete(0, END)
        self.ddl_attr['values'] = self.dico_rekur.keys()
        # reset the form
        self.tab3_ENnom.delete(0, END)
        self.tab3_TXdesc.delete(1.0, END)
        self.def_kass.set(0)
        self.def_stat.set(0)
        # deactivate the form
        self.alter_state(self.FrRekur, DISABLED)

        # End of function
        return self.dico_rekur

    def saveas_rekurs(self, lang):
        u""" save the recurring fields into the file dedicated """
        rekur = ET.Element(u'champs')
        xml_path = r'locale/{0}/champignons_{0}.xml'.format(lang)
        self.dico_rekur.pop(self.blabla.get('tab3_new'))
        with open(xml_path, 'w') as champis:
            for elem in self.dico_rekur.keys():
                rek = ET.SubElement(rekur, u'champ')
                # name of recurring attribute
                rek_name = ET.SubElement(rek, u'intitule')
                rek_name.text = elem
                # description of recurring attribute
                rek_desc = ET.SubElement(rek, u'description')
                rek_desc.text = self.dico_rekur.get(elem)[0]
                # stats option of recurring attribute
                rek_stats = ET.SubElement(rek, u'stats')
                rek_stats.text = unicode(self.dico_rekur.get(elem)[1])
                # case sensitive option of recurring attribute
                rek_case = ET.SubElement(rek, u'case')
                rek_case.text = unicode(self.dico_rekur.get(elem)[2])

        # creating the xml tree
        out_rekurs = ET.ElementTree(rekur)
        # saving it
        out_rekurs.write(xml_path,
                         encoding='utf-8',
                         xml_declaration='version="1.0"',
                         method='xml')

        # End of function
        return self.dico_rekur

    def select_profil(self, event):
        """ when a profile is selected... """
        profsel = event.widget.get()
        # if user wants to use an existing profile or create a new one
        if profsel == self.blabla.get('tab1_new'):
            self.val.config(text=self.blabla.get('tab1_crprofil'))
        else:
            self.val.config(text=self.blabla.get('tab1_go'))

        # end of function
        return self.val

    def recup_profil(self, lang):
        """ get the information from the profile selected """
        # clearing the profile dictionary
        self.dico_profil.clear()
        # specific path to profile file
        path_profile = path.join('locale/{0}/profiles/{1}.xml'.format(lang,
                                                                      self.ddl_profil.get()))
        with open(path_profile, 'r') as profile:
            # open xml parser
            xml = ET.parse(profile)
            # basic informations
            self.dico_profil['description'] = xml.find('description').text
            self.dico_profil['sources'] = xml.find('sources').text
            self.dico_profil['url'] = xml.find('url').text
            self.dico_profil['url_label'] = xml.find('url_label').text
            self.dico_profil[u'diffusion'] = xml.find('diffusion').text
            # data language
            lang_data = xml.find(u'lang_data')
            self.dico_profil[u"lang_data"] = lang_data.find(u'name').text
            # metadata language
            lang_metad = xml.find(u'lang_metad')
            self.dico_profil[u"lang_md"] = lang_metad.find(u'name').text
            # diffusion constraints
            diff = xml.find(u'diffusion')
            self.dico_profil['diffusion'] = diff.find(u'name').text
            # update rythm
            rythm = xml.find(u'rythm')
            self.dico_profil['rythm'] = rythm.find(u'name').text
            # INSPIRE themes
            themes = xml.find('themesinspire')
            li_themesinspire = [theme.find('name').text for theme in themes.findall('theme')]
            self.dico_profil['themesinspire'] = li_themesinspire
            # custom keywords
            keywords = xml.find('keywords')
            li_keywords = [keyword.find('name').text for keyword in keywords.findall('keyword')]
            self.dico_profil['keywords'] = li_keywords
            # places keywords
            geokeywords = xml.find('geokeywords')
            li_geokeywords = [geokeyword.find('name').text for geokeyword in geokeywords.findall('geokeyword')]
            self.dico_profil['geokeywords'] = li_geokeywords
            # contacts
            contacts = xml.find(u'contacts')
            # point of contact
            cont = contacts.find(u'pointdecontact')
            self.dico_profil[u'cont_name'] = cont.find(u'name').text
            self.dico_profil[u'cont_orga'] = cont.find(u'org').text
            self.dico_profil[u'cont_mail'] = cont.find(u'mail').text
            self.dico_profil[u'cont_role'] = cont.find(u'role').text
            self.dico_profil[u'cont_func'] = cont.find(u'func')[0].text
            self.dico_profil[u'cont_street'] = cont.find(u'street').text
            self.dico_profil[u'cont_city'] = cont.find(u'city').text
            self.dico_profil[u'cont_cp'] = cont.find(u'cp').text
            self.dico_profil[u'cont_country'] = cont.find(u'country').text
            self.dico_profil[u'cont_phone'] = cont.find(u'tel').text
            # second contact (responsable, etc.)
            resp = contacts.find(u'second_contact')
            self.dico_profil[u'resp_name'] = resp.find(u'name').text
            self.dico_profil[u'resp_orga'] = resp.find(u'org').text
            self.dico_profil[u'resp_mail'] = resp.find(u'mail').text
            self.dico_profil[u'resp_role'] = resp.find(u'role').text
            self.dico_profil[u'resp_func'] = resp.find(u'func')[0].text
            self.dico_profil[u'resp_street'] = resp.find(u'street').text
            self.dico_profil[u'resp_city'] = resp.find(u'city').text
            self.dico_profil[u'resp_cp'] = resp.find(u'cp').text
            self.dico_profil[u'resp_country'] = resp.find(u'country').text
            self.dico_profil[u'resp_phone'] = resp.find(u'tel').text
        # End of function
        return self.dico_profil

    def recup_help(self, lang):
        """ get the help texts """
        # specific path to xml file
        path_help = 'locale/%s/help_%s.xml' % (lang, lang)
        # reading and parsing the xml
        with open(path_help, 'r') as source:
            xml = ET.parse(source)                  # xml cursor
            for tooltip in xml.findall('tooltip'):
                idu = tooltip.find('id').text
                ref = tooltip.find('ref').text
                txt = tooltip.find('txt').text
                img = tooltip.find('image').text
                doc = tooltip.find('doc').text
                # fillfulling the INSPIRE dictionary
                self.dico_help[int(idu)] = ref, txt, img, doc
        # End of function
        return self.dico_help

    def process(self):
        u""" launch the different processes """
        # display the main tab
        self.nb.select(0)
        # check option selected: process or create a new profile
        if self.ddl_profil.get() == self.blabla.get('tab1_new'):
            # launching the profile form
            self.logger.info('Creation of a new profile')
            tr_profile = threading.Thread(target=NewProfile,
                                          args=(self.blabla,
                                                self.ddl_lang.get(),
                                                self.dico_help,
                                                self.li_pro))
            tr_profile.daemon = True
            tr_profile.run()
            # NewProfile(self.blabla, self.ddl_lang.get(), self.li_pro)
            self.li_profiles(self.ddl_lang.get())   # updating the dropdow list
            self.ddl_profil['values'] = self.li_pro
            return
        # check if the target folder has been selected
        if self.target.get() == "":
            info(title=self.blabla.get('info_blanktarget1'),
                 message=self.blabla.get('info_blanktarget2'))
            return
        # check if a profile has been selected
        if self.ddl_profil.get() == "":
            info(title=self.blabla.get('info_blankprofile1'),
                 message=self.blabla.get('info_blankprofile2'))
            return
        # disabling others GUI parts
        self.tab_globals.focus_force()
        self.alter_state(self.FrPath, DISABLED)

        # check if there are some layers into the folder structure
        if len(self.li_shp) + len(self.li_tab) == 0:
            self.logger.warning("No geofiles found in the folder structure")
            self.status.set(self.blabla.get('log_nodata'))
            return
        # specific variables
        dest = path.join(self.target.get(), 'metadator')
        if not path.isdir(dest):    # test if folder already exists
            mkdir(dest, 0777)       # if not, we create it
        # getting profile informations
        self.recup_profil(self.ddl_lang.get())
        # saving options in a separated thread
        tr_options = threading.Thread(target=self.save_settings)
        tr_options.daemon = True
        tr_options.start()
        self.logger.info('Current options saved')
        # saving recurring fiels in a separated thread
        tr_rekurs = threading.Thread(target=self.saveas_rekurs,
                                     args=(self.ddl_lang.get(), ))
        tr_rekurs.daemon = True
        tr_rekurs.start()
        # configuring the progression bar
        self.prog_layers["maximum"] = len(self.li_shp) + len(self.li_tab)
        self.prog_layers["value"]
        # Processing the shapefiles
        self.logger.info('\tStart processing the files')
        for shp in self.li_shp:
            """ looping on shapefiles list """
            self.logger.info('Processing: %s' % path.basename(shp))
            self.status.set(path.basename(shp))
            # reset recipient data
            self.dico_layer.clear()
            self.dico_fields.clear()
            # getting separated process threads
            Read_SHP(shp,
                     self.dico_layer,
                     self.dico_fields,
                     'shape',
                     self.blabla)
            # checking layer error
            if self.dico_layer.get('error'):
                # increment the progress bar
                self.prog_layers["value"] = self.prog_layers["value"] + 1
                self.update()
                self.logger.warning('This shape has an issue: %s' % shp)
                continue
            # getting fields statistics only if needed
            if self.def_doc.get() == 1 or self.def_xls.get() == 1 or self.def_odt.get() == 1:
                StatsFields(shp, self.dico_fields, self.dico_rekur, self.blabla)
            # export according to options selected
            if self.def_doc.get() == 1:
                ExportToHTML(dest,
                             self.dico_layer,
                             self.dico_fields,
                             self.dico_profil,
                             self.dico_rekur,
                             self.blabla)
                html_path = path.join(dest,
                                      "{0}_MD.html".format(self.dico_layer['name'][:-4]))
                ExportToDocX(html_path, dest)
            if self.def_xls.get() == 1:
                ExportToXLS(dest,
                            self.dico_layer,
                            self.dico_fields,
                            self.dico_profil,
                            self.dico_rekur,
                            self.blabla)
            if self.def_xml.get() == 1:
                ExportToXML(dest,
                            self.dico_layer,
                            self.dico_profil,
                            '',
                            self.blabla,
                            1,
                            0)
            if self.def_odt.get() == 1:
                ExportToODT(dest,
                            self.dico_layer,
                            self.dico_fields,
                            self.dico_profil,
                            self.dico_rekur,
                            self.blabla)
            # increment the progress bar
            self.prog_layers["value"] = self.prog_layers["value"] + 1
            self.update()

        # Processing the MapInfo tables
        for tab in self.li_tab:
            """ looping on MapInfo tables list """
            self.logger.info('Processing: %s' % path.basename(tab))
            self.status.set(path.basename(tab))
            # reset recipient data
            self.dico_layer.clear()
            self.dico_fields.clear()
            # getting the informations
            Read_TAB(tab,
                     self.dico_layer,
                     self.dico_fields,
                     'table',
                     self.blabla)
            # checking layer error
            if self.dico_layer.get('error'):
                self.logger.warning('This MapInfo table has an issue: %s' % tab)
                # increment the progress bar
                self.prog_layers["value"] = self.prog_layers["value"] +1
                self.update()
                continue
            # getting fields statistics only if needed
            if self.def_doc.get() == 1 \
               or self.def_xls.get() == 1 \
               or self.def_odt.get() == 1:
                StatsFields(tab, self.dico_fields, self.dico_rekur, self.blabla)
            # export according to options selected
            if self.def_doc.get() == 1:
                ExportToHTML(dest,
                             self.dico_layer,
                             self.dico_fields,
                             self.dico_profil,
                             self.dico_rekur,
                             self.blabla)
                html_path = path.join(dest,
                                      "{0}_MD.html".format(self.dico_layer['name'][:-4]))
                ExportToDocX(html_path, dest)
            if self.def_xls.get() == 1:
                ExportToXLS(dest,
                            self.dico_layer,
                            self.dico_fields,
                            self.dico_profil,
                            self.dico_rekur,
                            self.blabla)
            if self.def_xml.get() == 1:
                ExportToXML(dest,
                            self.dico_layer,
                            self.dico_profil,
                            '',
                            self.blabla,
                            1,
                            0)
            if self.def_odt.get() == 1:
                ExportToODT(dest,
                            self.dico_layer,
                            self.dico_fields,
                            self.dico_profil,
                            self.dico_rekur,
                            self.blabla)
            # increment the progress bar
            self.prog_layers["value"] = self.prog_layers["value"] + 1
            self.update()

        # Word catalog export
        if self.def_doc.get() == 1 and self.def_cat.get() == 1:
            self.status.set(self.blabla.get('info_cat'))
            self.update()
            DocxMerger(dest, '00_Metadator_Catalog', 'metadator_')
        else:
            pass

        # final message
        # msg = self.blabla.get('info_end2') + self.blabla.get('info_end3')
        # info(title=self.blabla.get('info_end'), message=msg)
        # opening the destination folder
        self.open_dir_file(dest)
        # cleaning up
        logging.info('Hurray! It worked! All seem to have been fine!')
        self.destroy()
        # end of function
        return

    def open_dir_file(self, target):
        """
        Open a file or a directory in the explorer of the operating system
        http://sametmax.com/ouvrir-un-fichier-avec-le-bon-programme-en-python
        """
        # check if the file or the directory exists
        if not path.exists(target):
            raise IOError('No such file: {0}'.format(target))

        # check the read permission
        if not access(target, R_OK):
            raise IOError('Cannot access file: {0}'.format(target))

        # open the directory or the file according to the os
        if opersys == 'win32':  # Windows
            proc = startfile(target)

        elif opersys.startswith('linux'):  # Linux:
            proc = subprocess.Popen(['xdg-open', target],
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)

        elif opersys == 'darwin':  # Mac:
            proc = subprocess.Popen(['open', '--', target],
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)

        else:
            raise NotImplementedError(
                "Your `%s` isn't a supported operating system`." % opersys)

        # end of function
        return proc
コード例 #9
0
class AbstractProgressScreen(GuiBaseFrame):
    # Backend logic thread should be making calls to controller.update_frame() to update the UI while logic runs.
    def __init__(self, parent, controller, backend_logic_function, **kw):
        GuiBaseFrame.__init__(self, parent, controller, **kw)
        self.backend_logic_function = backend_logic_function

    def init_widgets(self):
        self.content_wrapper = Frame(self)
        self.content_wrapper.configure(bg="white")

        self.screen_title = Header1Label(self.content_wrapper)
        self.empty_space_1 = PLabel(self.content_wrapper)
        self.progress_bar_control_var = DoubleVar()
        self.progress_bar = Progressbar(self.content_wrapper,
                                        orient=HORIZONTAL,
                                        mode="determinate",
                                        length=WINDOW_WIDTH / 2,
                                        variable=self.progress_bar_control_var)
        self.wait_text = PLabel(self.content_wrapper)
        self.information_display = PLabel(self.content_wrapper)
        self.empty_space_2 = PLabel(self.content_wrapper)
        self.next_button = Button(self.content_wrapper,
                                  text="Next",
                                  state=DISABLED,
                                  command=lambda: self.on_next_button())

    def add_widgets_to_frame(self):
        self.screen_title.pack()
        self.empty_space_1.pack()
        self.progress_bar.pack()
        self.wait_text.pack()
        self.information_display.pack()
        self.empty_space_2.pack()
        self.next_button.pack()
        self.content_wrapper.place(relx=SCREENS_REL_X,
                                   rely=SCREEN_REL_Y_45,
                                   anchor=CENTER)

    def on_show_frame(self):
        self.wait_text.configure(
            text="\nThis might take a few minutes."
            "\nPlease do not change the video files while this is "
            "running.\n")
        self.start_time = time.time()
        self.backend_logic_thread = threading.Thread(
            target=self.backend_logic_function,
            kwargs={"controller": self.controller})
        self.backend_logic_thread.start()
        self.master.after(THREAD_CHECK_ALIVE_INTERVAL_MS, self.check_thread)

    # Data should be a dictionary with keys "percent_done" and "message_list".
    def update_frame(self, data):
        percent_done = data[PROGRESS_SCREEN_PERCENT_DONE]
        message_list = data[PROGRESS_SCREEN_MESSAGE_LIST]

        self.progress_bar_control_var.set(percent_done)

        elapsed_time_seconds = int(time.time() - self.start_time)
        elapsed_time_message = ELAPSED_TIME_PREFIX + str(
            datetime.timedelta(seconds=elapsed_time_seconds))

        if elapsed_time_seconds == 0:
            estimated_time_left_string = ESTIMATED_TIME_LEFT_PREFIX + "Calculating..."
        else:
            estimated_time_left_seconds = int(
                elapsed_time_seconds / percent_done *
                100.0) - elapsed_time_seconds
            estimated_time_left_string = ESTIMATED_TIME_LEFT_PREFIX + \
                                         str(datetime.timedelta(seconds=estimated_time_left_seconds))

        message_list.append(elapsed_time_message)
        message_list.append(estimated_time_left_string)

        self.set_information_display_text(message_list)

    def on_hide_frame(self):
        self.progress_bar.stop()

    def set_title(self, title):
        self.screen_title.configure(text=title)

    def set_information_display_text(self, message_list):
        self.information_display.configure(text=("\n".join(message_list)))

    def check_thread(self):
        if self.backend_logic_thread.is_alive():
            self.master.after(THREAD_CHECK_ALIVE_INTERVAL_MS,
                              self.check_thread)
        else:
            self.progress_bar.stop()
            self.wait_text.configure(text="\nDone!\nPress Next to continue.\n")
            self.next_button.configure(state=NORMAL)

    def on_next_button(self):
        self.controller.show_next_frame()
コード例 #10
0
ファイル: tk_synthwindow.py プロジェクト: plewto/Llia
class TkSynthWindow(Frame):

    """
    Provides common synth editor elements: 
          bank editor
          MIDI tab
          Mapping tabs

     TkSynthWindow is customized by adding one or more TkSubEditor.
    """
    
    def __init__(self, master, sproxy):
        """
        Construct new TkSynthWindow

        master - The Tk container for self.  In practice this is an 
                 instance of llia.gui.tk.GroupWindow

        sproxy - An instance of llia.Proxy.
        """
        Frame.__init__(self, master)
        self.config(background=factory.bg())
        self.synth = sproxy
        self.synth.synth_editor = self
        self.app = sproxy.app
        self.sid = sproxy.sid
        self.group_index = -1
        factory.set_pallet(sproxy.specs["pallet"])
        main = factory.paned_window(self)
        main.pack(expand=True, fill="both")
        self.bank_editor = TkBankEditor(main, self, sproxy)
        self.bus_and_buffer_editor = None
        east = factory.frame(main)
        self.notebook = factory.notebook(east)
        self.notebook.pack(anchor="nw", expand=True, fill="both")
        south = factory.frame(east)
        south.pack(after=self.notebook, anchor="w", expand=True, fill="x")
        self._lab_status = factory.label(south, "<status>")
        self._lab_extended = factory.label(south, "")
        b_panic = factory.panic_button(south, command=self.panic)
        b_lower = factory.button(south, "-", command=self.lower_window)
        b_lift = factory.button(south, "+", command=self.lift_window)
        b_panic.grid(row=0, column=0)
        self._lab_status.grid(row=0, column=4, sticky='ew')
        self._lab_extended.grid(row=0,column=5,sticky='e',padx=16)
        self._lab_extended.config(fg="#f1f1cd")
        self._progressbar = Progressbar(south,mode="indeterminate")
        self._progressbar.grid(row=0,column=PROGRESSBAR_COLUMN, sticky='w', padx=8)
        south.config(background=factory.bg())
        main.add(self.bank_editor)
        main.add(east)
        self.list_channel = None
        self.list_keytab = None
        self.var_transpose = StringVar()
        self.var_keyrange_low = StringVar()
        self.var_keyrange_high = StringVar()
        self.var_bendrange = StringVar()
        self._init_midi_tab(self.notebook)
        self._init_map1_tab(self.notebook) # MIDI controllers and pitchwheel
        self._init_map2_tab(self.notebook) # velocity, aftertouch, keynumber
        self._init_info_tab(self.notebook)
        self._child_editors = {}
        self.update_progressbar(100, 0)
        
    def enable(self, flag):
        for ed in self._child_editors.values():
            ed.enable(flag)
        if flag:
            msg = ""
        else:
            msg = "Editor locked while in extended mode"
        self._lab_extended.config(text=msg)
        
    def panic(self):
        self.synth.osc_transmitter.x_all_notes_off()
        self.status("All notes off")
        
    def clear_status(self):
        self._lab_status.config(text="")
        
    def add_child_editor(self, child_name, child):
        # Adds child editor to list of editors without adding a notebook tab.
        self._child_editors[child_name] = child

    def _create_basic_tab(self,text):
        f = factory.frame(self.notebook)
        self.notebook.add(f, text=text)
        return f

    # icon_filename = "resources/%s/logo_32.png" % sy.specs["format"]
    # icon = factory.image(icon_filename)
    # group.notebook.add(swin, text=sy.sid, image=icon, compound="top")
    
    def _create_compund_tab(self,text,image_filename):
        try:
            icon = factory.image(image_filename)
            f = factory.frame(self.notebook)
            self.notebook.add(f,text=text,image=icon,compound="top")
            return f
        except IOError:
            msg = "IOError while loading image file '%s'" % image_filename
            print(msg)
            return self._create_basic_tab(text)
    
    def create_tab(self, tab_text, image_filename=""):
        if not image_filename:
            rs = self._create_basic_tab(tab_text)
        else:
            rs = self._create_compund_tab(tab_text,image_filename)
        return rs
       
    def remove_synth(self, *_):
        sid = self.synth.sid
        parser = self.app.ls_parser
        sh = parser.synthhelper
        sh.destroy_editor(sid)
        sh.remove_synth(sid, force=True)
        self.status("Removed synth: %s" % sid)

    def _init_info_tab(self, master):
        img = factory.image("resources/Tabs/info.png")
        frame = factory.frame(master)
        inner_frame = factory.frame(frame)
        master.add(frame, text="Info", image=img,compound="top")
        text_widget = factory.text_widget(inner_frame)
        text_widget.config(width=120, height=40)
        vsb = factory.scrollbar(inner_frame, orientation='vertical')
        vsb.config(command=text_widget.yview)
        text_widget.config(yscrollcommand=vsb.set, wrap='word',)
        text_widget.grid(row=0, column=0,sticky="ewns")
        vsb.grid(row=0, column=1, sticky='ns')
        inner_frame.grid(row=0, column=0, rowspan=8, columnspan=8, sticky="ewns")
        self._info_text_widget = text_widget

    def lift_window(self):
        mw = self.app.main_window()
        grp = mw.group_windows[self.group_index]
        grp.lift()
        self.status("Lift window")

    def lower_window(self):
        mw = self.app.main_window()
        grp = mw.group_windows[self.group_index]
        grp.lower()
        self.status("Lower window")
        
    def sync_program_tab(self):
        bnk = self.synth.bank()
        prog = bnk[None]
        slot = bnk.current_slot
        pp = self.synth.specs["pretty-printer"]
        if pp:
            txt = pp(prog, slot)
        else:
            txt = ""
        self._info_text_widget.delete(1.0, "end")
        self._info_text_widget.insert("end", txt)

    def _init_midi_tab(self, master):
        img = factory.image("resources/Tabs/midi.png")
        frame = factory.frame(master)
        master.add(frame, text = "Performance", image=img, compound="top")
        frame_channel = factory.frame(frame)
        frame_keytab = factory.frame(frame)
        lab_transpose = factory.label(frame, "Transpose")
        lab_keyrange = factory.label(frame, "Key Range")
        lab_bend = factory.label(frame, "Bend Range")
        self.list_channel = factory.listbox(frame_channel)
        sb_channel = factory.scrollbar(frame_channel)
        sb_channel.config(command=self.list_channel.yview)
        self.list_channel.config(yscrollcommand=sb_channel.set)
        self.list_keytab = factory.listbox(frame_keytab)
        sb_keytab = factory.scrollbar(frame_keytab)
        sb_keytab.config(command=self.list_keytab.yview)
        self.list_keytab.config(yscrollcommand=sb_keytab.set)
        spin_transpose = factory.int_spinbox(frame,self.var_transpose,-36,36)
        spin_keylow = factory.int_spinbox(frame,self.var_keyrange_low,0,127)
        spin_keyhigh = factory.int_spinbox(frame,self.var_keyrange_high,0,127)
        spin_bendrange = factory.int_spinbox(frame,self.var_bendrange, 0, 2400)
        factory.padding_label(frame).grid(row=0)
        lab_channel = factory.label(frame,"MIDI Input Channel")
        lab_channel.grid(row=0,column=0,columnspan=2, pady=8)
        frame_channel.grid(row=1, column=0, rowspan=4, columnspan=2,padx=8,pady=8)
        self.list_channel.pack(side="left", expand=True, fill="both")
        sb_channel.pack(after=self.list_channel, side="right", expand=True, fill="y")
        lab_ktab = factory.label(frame, "Key Table")
        lab_ktab.grid(row=0,column=2,columnspan=2,pady=8)
        frame_keytab.grid(row=1, column=2, rowspan=4, columnspan=2,padx=8,pady=8)
        self.list_keytab.pack(side="left", expand=True, fill="both")
        sb_keytab.pack(after=self.list_keytab, side="right", 
                       expand=True, fill="y")
        factory.padding_label(frame).grid(row=6)
        lab_transpose.grid(row=7, column=0, sticky="w", padx=4, pady=4)
        lab_keyrange.grid(row=8, column=0, sticky="w", padx=4, pady=4)
        lab_bend.grid(row=9, column=0, sticky="w", padx=4, pady=4)

        spin_transpose.grid(row=7, column=1, padx=4)
        spin_keylow.grid(row=8, column=1, padx=4)
        spin_keyhigh.grid(row=8, column=2, padx=4)
        spin_bendrange.grid(row=9, column=1, padx=4)
   
        def channel_callback(_):
            i = self.list_channel.curselection()[0]
            c = i+1
            self.synth.midi_input_channel(c)
            self.status("MIDI Input Channel = %s" % c)

        def keytab_callback(_):
            i = self.list_keytab.curselection()[0]
            kt = self.list_keytab.get(i)
            self.synth.keytable(kt)
            self.status("Using keytable: %s" % kt)

        def transpose_callback(*_):
            try:
                x = int(self.var_transpose.get())
                self.synth.transpose(x)
                self.status("Transpose = %s" % x)
            except ValueError:
                self.warning("Invalid transpose")
                
        def keyrange_callback(*_):
            try:
                a = int(self.var_keyrange_low.get())
                b = int(self.var_keyrange_high.get())
                a, b = min(a,b), max(a,b)
                self.synth.key_range((a,b))
                self.status("Key range = [%3d, %3d]" % (a, b))
            except ValueError:
                self.warning("Invalid keyrange")
                
        def bend_callback(*_):
            try:
                b = int(self.var_bendrange.get())
                self.synth.bend_range(b)
                self.status("Bend range = %s" % b)
            except ValueError:
                self.warning("Invalid Bendrange")
        
        self.list_channel.bind("<<ListboxSelect>>", channel_callback)
        self.list_keytab.bind("<<ListboxSelect>>", keytab_callback)
        spin_transpose.config(command=transpose_callback)
        spin_transpose.bind("<Return>", transpose_callback)
        spin_keylow.config(command=keyrange_callback)
        spin_keylow.bind("<Return>", keyrange_callback)
        spin_keyhigh.config(command=keyrange_callback)
        spin_keyhigh.bind("<Return>", keyrange_callback)
        spin_bendrange.config(command=bend_callback)
        spin_bendrange.bind("<Return>", bend_callback)

    def sync_midi_tab(self):
        self.list_channel.delete(0, "end")
        for c in self.app.config().channel_assignments.formatted_list():
            self.list_channel.insert("end", c)
        mic = self.synth.midi_input_channel()-1
        self.list_channel.selection_set(mic)
        self.list_keytab.delete(0, "end")
        target, index = self.synth.keytable(), 0
        for i, kt in enumerate(sorted(self.app.keytables.keys())):
            self.list_keytab.insert("end", kt)
            if target == kt: index = i
        self.list_keytab.selection_set(index)
        self.var_transpose.set(self.synth.transpose())
        lo, hi = self.synth.key_range()
        self.var_keyrange_low.set(lo)
        self.var_keyrange_high.set(hi)
        self.var_bendrange.set(self.synth.bend_range())

    # map1_tab -> MIDI controller, pitch wheel
    def _init_map1_tab(self, master):
        img = factory.image("resources/Tabs/map.png")
        HELP_TOPIC = "parameter-maps"
        frame = factory.frame(master)
        master.add(frame, text="Map1", image=img, compound="top")
        north = factory.label_frame(frame, "MIDI Controller Maps")
        south = factory.label_frame(frame, "Pitch Wheel Maps")
        north.grid(row=0, column=0, sticky="ew", padx=8, pady=8)
        south.grid(row=1, column=0, sticky="ew", padx=8, pady=8)

        def help_callback():
            self.app.main_window().display_help(HELP_TOPIC)
       
        list_cc_maps = factory.listbox(north, 
                                       ttip="Active MIDI controller maps")
        list_cc_maps.config(width=80, height=16)
        self.list_cc_maps = list_cc_maps
        sb = factory.scrollbar(north, orientation="vertical")
        sb.config(command=list_cc_maps.yview)
        list_cc_maps.config(yscrollcommand=sb.set)
        b_add_cc = factory.add_button(north, ttip="Add new controller map")
        b_delete_cc = factory.delete_button(north, 
                                            ttip="Delete controller map")
        list_cc_maps.grid(row=0, column=0, rowspan=4, 
                          columnspan=8, sticky="ew")
        sb.grid(row=0, column=8, rowspan=4, sticky="ns")
        b_add_cc.grid(row=4, column=0, sticky="ew")
        b_delete_cc.grid(row=4, column=1, sticky="ew")

        list_pwheel_maps = factory.listbox(south, 
                                           ttip="Active pitch wheel maps")
        list_pwheel_maps.config(width=80, height=8)
        self.list_pwheel_maps = list_pwheel_maps
        sb = factory.scrollbar(south, orientation="vertical")

        sb.config(command=list_pwheel_maps.yview)
        list_pwheel_maps.config(yscrollcommand=sb.set)
        b_add_pw = factory.add_button(south, ttip="Add pitchwheel map")
        b_delete_pw = factory.delete_button(south, 
                                            ttip="Delete pitchwheel map")
        b_help = factory.help_button(south, command=help_callback)
        list_pwheel_maps.grid(row=0, column=0, rowspan=4,
                              columnspan=8, sticky="ew")
        sb.grid(row=0, column=8, rowspan=4, sticky="ns")
        b_add_pw.grid(row=4, column=0, sticky="ew")
        b_delete_pw.grid(row=4, column=1, sticky="ew")
        b_help.grid(row=4, column=7, sticky="ew")

        def add_cc_callback():
            dialog = add_map_dialog(self.synth, "cc", self.app)

        def delete_cc_callback():
            dialog = delete_map_dialog(self, self.synth, "cc", self.app)

        def add_pw_callback():
            dialog = add_map_dialog(self.synth, "PitchWheel", self.app)

        def delete_pw_callback():
            dialog = delete_map_dialog(self, self.synth, "PitchWheel", self.app)

        b_add_cc.config(command=add_cc_callback)
        b_delete_cc.config(command=delete_cc_callback)
        b_add_pw.config(command=add_pw_callback)
        b_delete_pw.config(command=delete_pw_callback)
        
    def sync_map1_tab(self):
        perf = self.synth.bank()[None].performance
        cmaps = perf.controller_maps
        pwmaps = perf.pitchwheel_maps
        self.list_cc_maps.delete(0, "end")
        for ctrl, mapper in cmaps.items():
            s = str(mapper)
            for q in s.split('\n'):
                self.list_cc_maps.insert("end", q)
        self.list_pwheel_maps.delete(0, "end")
        for q in str(pwmaps).split('\n'):
            self.list_pwheel_maps.insert("end", q)

    def _init_map2_tab(self, master):
        img = factory.image("resources/Tabs/map.png")
        HELP_TOPIC = "parameter-maps"
        HEIGHT = 8
        frame = factory.frame(master)
        master.add(frame, text="Map2",image=img,compound="top")
        north = factory.label_frame(frame, "Velocity Maps")
        center = factory.label_frame(frame, "Aftertouch Maps")
        south = factory.label_frame(frame, "Keynumber Maps")
        north.grid(row=0, column=0, sticky="ew", padx=8, pady=8)
        center.grid(row=1, column=0, sticky="ew", padx=8)
        south.grid(row=2, column=0, sticky="ew", padx=8, pady=8)

        def help_callback():
            self.app.main_window().display_help(HELP_TOPIC)

        list_vel_maps = factory.listbox(north, ttip="Active velocity maps")
        list_vel_maps.config(width=80, height=HEIGHT)
        self.list_vel_maps = list_vel_maps
        sb = factory.scrollbar(north, orientation="vertical")
        sb.config(command=list_vel_maps.yview)
        list_vel_maps.config(yscrollcommand=sb.set)
        b_add_vel = factory.add_button(north, ttip="Add velocity map")
        b_delete_vel = factory.delete_button(north, 
                                             ttip="Delete velocity map")
        list_vel_maps.grid(row=0, column=0, columnspan=8, sticky="ew")
        sb.grid(row=0, column=8, sticky="ns")
        b_add_vel.grid(row=1, column=0, sticky="ew")
        b_delete_vel.grid(row=1, column=1, sticky="ew")

        list_atouch_maps = factory.listbox(center, 
                                           ttip="Active after touch maps")
        list_atouch_maps.config(width=80, height=HEIGHT)
        self.list_atouch_maps = list_atouch_maps
        sb = factory.scrollbar(center, orientation="vertical")
        sb.config(command=list_atouch_maps.yview)
        list_atouch_maps.config(yscrollcommand=sb.set)
        b_add_atouch = factory.add_button(center, ttip="Add after touch map")
        b_delete_atouch = factory.delete_button(center, 
                                                ttip="Delete after touch map")
        list_atouch_maps.grid(row=0, column=0, columnspan=8, sticky="ew")
        sb.grid(row=0, column=8, sticky="ns")
        b_add_atouch.grid(row=1, column=0, sticky="ew")
        b_delete_atouch.grid(row=1, column=1, sticky="ew")

        list_keynum_maps = factory.listbox(south, 
                                           ttip="Active key number maps")
        list_keynum_maps.config(width=80, height=HEIGHT)
        self.list_keynum_maps = list_keynum_maps
        sb = factory.scrollbar(south, orientation="vertical")
        sb.config(command=list_keynum_maps.yview)
        list_keynum_maps.config(yscrollcommand=sb.set)
        b_add_keynum = factory.add_button(south, ttip="Add key number map")
        b_delete_keynum = factory.delete_button(south, 
                                                ttip="Delete key number map")
	b_help = factory.help_button(south, command=help_callback)
        list_keynum_maps.grid(row=0, column=0, columnspan=8, sticky="ew")
        sb.grid(row=0, column=8, sticky="ns")
        b_add_keynum.grid(row=1, column=0, sticky="ew")
        b_delete_keynum.grid(row=1, column=1, sticky="ew")
        b_help.grid(row=1, column=7, sticky="ew")

        def add_map_callback(event):
            widget = event.widget
            if widget is b_add_vel:
                dialog = add_map_dialog(self.synth, "velocity", self.app)
            elif widget is b_add_atouch:
                dialog = add_map_dialog(self.synth, "aftertouch", self.app)
            elif widget is b_add_keynum:
                dialog = add_map_dialog(self.synth, "keynumber", self.app)
            else:
                msg = "Invalid widget - Should never see this"
                raise ValueError(msg)

        def delete_map_callback(event):
            widget = event.widget
            if widget is b_delete_vel:
                dialog = delete_map_dialog(self, self.synth, "velocity", self.app)
            elif widget is b_delete_atouch:
                dialog = delete_map_dialog(self, self.synth, "aftertouch", self.app)
            elif widget is b_delete_keynum:
                dialog = delete_map_dialog(self, self.synth, "keynumber", self.app)
            else:
                msg = "Invalid widget - Should never see this"
                raise ValueError(msg)

        b_add_vel.bind("<Button-1>", add_map_callback)
        b_add_atouch.bind("<Button-1>", add_map_callback)
        b_add_keynum.bind("<Button-1>", add_map_callback)
        b_delete_vel.bind("<Button-1>", delete_map_callback)
        b_delete_atouch.bind("<Button-1>", delete_map_callback)
        b_delete_keynum.bind("<Button-1>", delete_map_callback)
        
    def sync_map2_tab(self):
        perf = self.synth.bank()[None].performance
        vmaps = perf.velocity_maps
        atmaps = perf.aftertouch_maps
        knmaps = perf.keynumber_maps
        self.list_vel_maps.delete(0, 'end')
        self.list_atouch_maps.delete(0, 'end')
        self.list_keynum_maps.delete(0, 'end')
        for q in str(vmaps).split('\n'):
            self.list_vel_maps.insert('end', q)
        for q in str(atmaps).split('\n'):
            self.list_atouch_maps.insert('end', q)
        for q in str(knmaps).split('\n'):
            self.list_keynum_maps.insert('end', q)            
        
    def status(self, msg):
        self._lab_status.config(text = msg)

    def warning(self, msg):
        msg = "WARNING: %s" % msg
        self._lab_status.config(text = msg)

    def set_value(self, param, value):
        for ed in self._child_editors.items():
            ed.set_value(param, value)

    def set_aspect(self, param, value):
        for ed in self._child_editors.values():
            ed.set_value(param, value)
    
    def sync(self, *ignore):
        self.sync_program_tab()
        self.sync_midi_tab()
        self.sync_map1_tab()
        self.sync_map2_tab()
        if "bank" not in ignore:
            self.bank_editor.sync_no_propegate()
        for key, ed in self._child_editors.items():
            if key not in ignore:
                ed.sync(*ignore)
                
    def annotation_keys(self):
        """
        See TkSubEditor annotation
        """
        acc = []
        for ed in self._child_editors.values():
            acc += ed.annotation_keys()
        return acc

    def set_annotation(self, key, text):
        """
        See TkSubEditor annotation
        """
        for ed in self._child_editors.values():
            ed.annotation(key, text)

    def get_annotation(self, key):
        """
        See TkSubEditor annotation
        """
        rs = None
        for ed in self._child_editors.values():
            rs = ed.get_annotation(key)
            if rs != None:
                return rs
        return None

    def update_progressbar(self, count, value):
        """
        Set progress bar to position value/count, where.
        count - Expected number of steps.
        value - Current step number.
        """
        self._progressbar.config(mode="determinate", maximum=count)
        self._progressbar.step()
        self.update_idletasks()
    
    def busy(self, flag, message=""):
        """
        Set progress bar to 'busy'
        """
        if message:
            self.status(message)
        self._progressbar.config(mode="indeterminate")
        if flag:
            self._progressbar.grid(row=0,column=PROGRESSBAR_COLUMN, sticky='w', padx=8)
            self._progressbar.start()
        else:
            self._progressbar.stop()
        self.update_idletasks()