class NewActionModulation(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.parent = parent
        self.initUI()

    def initUI(self):
        self.parent.title("Test")
        self.frameTab = Frame(self, relief=RAISED, borderwidth=1)
        self.frameTab.grid(row=3, column=0, columnspan=4)
        self.grid(row=0, column=0)
        self.frameTab.grid(row=0, column=0)
        self.note_book = Notebook(self.frameTab)
        self.specific_actions = ActionModulation.ActionModulation(self.note_book)
        self.note_book.add(self.specific_actions.getFrame(), text="specific actions")
        self.general_actions = GeneralActionModulation.GeneralActionModulation(self.note_book)
        self.note_book.add(self.general_actions.getFrame(), text="general actions")
        self.note_book.grid(row=0, column=0)

        self.frameButtons = Frame(self, relief=RAISED, borderwidth=1)
        self.frameButtons.grid(row=3, column=0, columnspan=4)
        self.buttonReset = Button(self.frameButtons, text="Reset")
        self.buttonReset.grid(row=0, column=0)
        self.buttonAbort = Button(self.frameButtons, text="Abort")
        self.buttonAbort.grid(row=0, column=1)
        self.buttonStop = Button(self.frameButtons, text="Stop")
        self.buttonStop.grid(row=0, column=2)
        self.buttonSendAction = Button(self.frameButtons, text="Send Action")
        self.buttonSendAction.grid(row=0, column=4)
        self.buttonSendEmotion = Button(self.frameButtons, text="Send Emotion")
        self.buttonSendEmotion.grid(row=0, column=5)

    def getCurrentTab(self):
        return self.note_book.index(self.note_book.select())

    def getFirstTab(self):
        return self.specific_actions

    def getSecondTab(self):
        return self.general_actions

    def getButtonSendAction(self):
        return self.buttonSendAction

    def getButtonSendEmotion(self):
        return self.buttonSendEmotion

    def getButtonReset(self):
        return self.buttonReset

    def getButtonAbort(self):
        return self.buttonAbort

    def getButtonStop(self):
        return self.buttonStop
Beispiel #2
0
class MainWindow(object):
    def __init__(self, root, debugger):
        '''
        -----------------------------------------------------
        | main button toolbar                               |
        -----------------------------------------------------
        |       < ma | in content area >      |             |
        |            |                        |             |
        | File list  | File name              | Inspector   |
        | (stack/    | Code area              |             |
        | breakpnts) |                        |             |
        |            |                        |             |
        |            |                        |             |
        -----------------------------------------------------
        |     status bar area                               |
        -----------------------------------------------------

        '''

        # Obtain and expand the current working directory.
        base_path = os.path.abspath(os.getcwd())
        base_path = os.path.normcase(base_path) + '/'

        # Create a filename normalizer based on the CWD.
        self.filename_normalizer = filename_normalizer(base_path)

        self.debugger = debugger
        # Associate the debugger with this view.
        self.debugger.view = self

        # Root window
        self.root = root
        self.root.title('Bugjar')
        self.root.geometry('1024x768')

        # Prevent the menus from having the empty tearoff entry
        self.root.option_add('*tearOff', False)
        # Catch the close button
        self.root.protocol("WM_DELETE_WINDOW", self.cmd_quit)
        # Catch the "quit" event.
        self.root.createcommand('exit', self.cmd_quit)

        # Setup the menu
        self._setup_menubar()

        # Set up the main content for the window.
        self._setup_button_toolbar()
        self._setup_main_content()
        self._setup_status_bar()

        # Now configure the weights for the root frame
        self.root.columnconfigure(0, weight=1)
        self.root.rowconfigure(0, weight=0)
        self.root.rowconfigure(1, weight=1)
        self.root.rowconfigure(2, weight=0)

        debugger.start()

    ######################################################
    # Internal GUI layout methods.
    ######################################################

    def _setup_menubar(self):
        # Menubar
        self.menubar = Menu(self.root)

        # self.menu_Apple = Menu(self.menubar, name='Apple')
        # self.menubar.add_cascade(menu=self.menu_Apple)

        self.menu_file = Menu(self.menubar)
        self.menubar.add_cascade(menu=self.menu_file, label='File')

        self.menu_program = Menu(self.menubar)
        self.menubar.add_cascade(menu=self.menu_program, label='Program')

        self.menu_help = Menu(self.menubar)
        self.menubar.add_cascade(menu=self.menu_help, label='Help')

        # self.menu_Apple.add_command(label='Test', command=self.cmd_dummy)

        # self.menu_file.add_command(label='New', command=self.cmd_dummy, accelerator="Command-N")
        self.menu_file.add_command(label='Open...',
                                   command=self.cmd_open_file,
                                   accelerator="Command-O")
        self.root.bind('<Command-o>', self.cmd_open_file)
        # self.menu_file.add_command(label='Close', command=self.cmd_dummy)

        self.menu_program.add_command(label='Run',
                                      command=self.cmd_run,
                                      accelerator="R")
        self.root.bind('<r>', self.cmd_run)
        self.menu_program.add_command(label='Step',
                                      command=self.cmd_step,
                                      accelerator="S")
        self.root.bind('<s>', self.cmd_step)
        self.menu_program.add_command(label='Next',
                                      command=self.cmd_next,
                                      accelerator="N")
        self.root.bind('<n>', self.cmd_next)
        self.menu_program.add_command(label='Return',
                                      command=self.cmd_return,
                                      accelerator="BackSpace")
        self.root.bind('<BackSpace>', self.cmd_return)

        self.menu_help.add_command(label='Open Documentation',
                                   command=self.cmd_bugjar_docs)
        self.menu_help.add_command(label='Open Bugjar project page',
                                   command=self.cmd_bugjar_page)
        self.menu_help.add_command(label='Open Bugjar on GitHub',
                                   command=self.cmd_bugjar_github)
        self.menu_help.add_command(label='Open BeeWare project page',
                                   command=self.cmd_beeware_page)

        # last step - configure the menubar
        self.root['menu'] = self.menubar

    def _setup_button_toolbar(self):
        '''
        The button toolbar runs as a horizontal area at the top of the GUI.
        It is a persistent GUI component
        '''

        # Main toolbar
        self.toolbar = Frame(self.root)
        self.toolbar.grid(column=0, row=0, sticky=(W, E))

        # Buttons on the toolbar
        self.run_button = Button(self.toolbar,
                                 text='Run',
                                 command=self.cmd_run)
        self.run_button.grid(column=0, row=0)

        self.step_button = Button(self.toolbar,
                                  text='Step',
                                  command=self.cmd_step)
        self.step_button.grid(column=1, row=0)

        self.next_button = Button(self.toolbar,
                                  text='Next',
                                  command=self.cmd_next)
        self.next_button.grid(column=2, row=0)

        self.return_button = Button(self.toolbar,
                                    text='Return',
                                    command=self.cmd_return)
        self.return_button.grid(column=3, row=0)

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

    def _setup_main_content(self):
        '''
        Sets up the main content area. It is a persistent GUI component
        '''

        # Main content area
        self.content = PanedWindow(self.root, orient=HORIZONTAL)
        self.content.grid(column=0, row=1, sticky=(N, S, E, W))

        # Create subregions of the content
        self._setup_file_lists()
        self._setup_code_area()
        self._setup_inspector()

        # Set up weights for the left frame's content
        self.content.columnconfigure(0, weight=1)
        self.content.rowconfigure(0, weight=1)

        self.content.pane(0, weight=1)
        self.content.pane(1, weight=2)
        self.content.pane(2, weight=1)

    def _setup_file_lists(self):

        self.file_notebook = Notebook(self.content, padding=(0, 5, 0, 5))
        self.content.add(self.file_notebook)

        self._setup_stack_frame_list()
        self._setup_breakpoint_list()

    def _setup_stack_frame_list(self):
        self.stack_frame = Frame(self.content)
        self.stack_frame.grid(column=0, row=0, sticky=(N, S, E, W))
        self.file_notebook.add(self.stack_frame, text='Stack')

        self.stack = StackView(self.stack_frame,
                               normalizer=self.filename_normalizer)
        self.stack.grid(column=0, row=0, sticky=(N, S, E, W))

        # # The tree's vertical scrollbar
        self.stack_scrollbar = Scrollbar(self.stack_frame, orient=VERTICAL)
        self.stack_scrollbar.grid(column=1, row=0, sticky=(N, S))

        # # Tie the scrollbar to the text views, and the text views
        # # to each other.
        self.stack.config(yscrollcommand=self.stack_scrollbar.set)
        self.stack_scrollbar.config(command=self.stack.yview)

        # Setup weights for the "stack" tree
        self.stack_frame.columnconfigure(0, weight=1)
        self.stack_frame.columnconfigure(1, weight=0)
        self.stack_frame.rowconfigure(0, weight=1)

        # Handlers for GUI events
        self.stack.bind('<<TreeviewSelect>>', self.on_stack_frame_selected)

    def _setup_breakpoint_list(self):
        self.breakpoints_frame = Frame(self.content)
        self.breakpoints_frame.grid(column=0, row=0, sticky=(N, S, E, W))
        self.file_notebook.add(self.breakpoints_frame, text='Breakpoints')

        self.breakpoints = BreakpointView(self.breakpoints_frame,
                                          normalizer=self.filename_normalizer)
        self.breakpoints.grid(column=0, row=0, sticky=(N, S, E, W))

        # The tree's vertical scrollbar
        self.breakpoints_scrollbar = Scrollbar(self.breakpoints_frame,
                                               orient=VERTICAL)
        self.breakpoints_scrollbar.grid(column=1, row=0, sticky=(N, S))

        # Tie the scrollbar to the text views, and the text views
        # to each other.
        self.breakpoints.config(yscrollcommand=self.breakpoints_scrollbar.set)
        self.breakpoints_scrollbar.config(command=self.breakpoints.yview)

        # Setup weights for the "breakpoint list" tree
        self.breakpoints_frame.columnconfigure(0, weight=1)
        self.breakpoints_frame.columnconfigure(1, weight=0)
        self.breakpoints_frame.rowconfigure(0, weight=1)

        # Handlers for GUI events
        self.breakpoints.tag_bind('breakpoint', '<Double-Button-1>',
                                  self.on_breakpoint_double_clicked)
        self.breakpoints.tag_bind('breakpoint', '<<TreeviewSelect>>',
                                  self.on_breakpoint_selected)
        self.breakpoints.tag_bind('file', '<<TreeviewSelect>>',
                                  self.on_breakpoint_file_selected)

    def _setup_code_area(self):
        self.code_frame = Frame(self.content)
        self.code_frame.grid(column=1, row=0, sticky=(N, S, E, W))

        # Label for current file
        self.current_file = StringVar()
        self.current_file_label = Label(self.code_frame,
                                        textvariable=self.current_file)
        self.current_file_label.grid(column=0, row=0, sticky=(W, E))

        # Code display area
        self.code = DebuggerCode(self.code_frame, debugger=self.debugger)
        self.code.grid(column=0, row=1, sticky=(N, S, E, W))

        # Set up weights for the code frame's content
        self.code_frame.columnconfigure(0, weight=1)
        self.code_frame.rowconfigure(0, weight=0)
        self.code_frame.rowconfigure(1, weight=1)

        self.content.add(self.code_frame)

    def _setup_inspector(self):
        self.inspector_frame = Frame(self.content)
        self.inspector_frame.grid(column=2, row=0, sticky=(N, S, E, W))

        self.inspector = InspectorView(self.inspector_frame)
        self.inspector.grid(column=0, row=0, sticky=(N, S, E, W))

        # The tree's vertical scrollbar
        self.inspector_scrollbar = Scrollbar(self.inspector_frame,
                                             orient=VERTICAL)
        self.inspector_scrollbar.grid(column=1, row=0, sticky=(N, S))

        # Tie the scrollbar to the text views, and the text views
        # to each other.
        self.inspector.config(yscrollcommand=self.inspector_scrollbar.set)
        self.inspector_scrollbar.config(command=self.inspector.yview)

        # Setup weights for the "breakpoint list" tree
        self.inspector_frame.columnconfigure(0, weight=1)
        self.inspector_frame.columnconfigure(1, weight=0)
        self.inspector_frame.rowconfigure(0, weight=1)

        self.content.add(self.inspector_frame)

    def _setup_status_bar(self):
        # Status bar
        self.statusbar = Frame(self.root)
        self.statusbar.grid(column=0, row=2, sticky=(W, E))

        # Current status
        self.run_status = StringVar()
        self.run_status_label = Label(self.statusbar,
                                      textvariable=self.run_status)
        self.run_status_label.grid(column=0, row=0, sticky=(W, E))
        self.run_status.set('Not running')

        # Main window resize handle
        self.grip = Sizegrip(self.statusbar)
        self.grip.grid(column=1, row=0, sticky=(S, E))

        # Set up weights for status bar frame
        self.statusbar.columnconfigure(0, weight=1)
        self.statusbar.columnconfigure(1, weight=0)
        self.statusbar.rowconfigure(0, weight=0)

    ######################################################
    # Utility methods for controlling content
    ######################################################

    def show_file(self, filename, line=None, breakpoints=None):
        """Show the content of the nominated file.

        If specified, line is the current line number to highlight. If the
        line isn't currently visible, the window will be scrolled until it is.

        breakpoints is a list of line numbers that have current breakpoints.

        If refresh is true, the file will be reloaded and redrawn.
        """
        # Set the filename label for the current file
        self.current_file.set(self.filename_normalizer(filename))

        # Update the code view; this means changing the displayed file
        # if necessary, and updating the current line.
        if filename != self.code.filename:
            self.code.filename = filename
            for bp in self.debugger.breakpoints(filename).values():
                if bp.enabled:
                    self.code.enable_breakpoint(bp.line)
                else:
                    self.code.disable_breakpoint(bp.line)

        self.code.line = line

    ######################################################
    # TK Main loop
    ######################################################

    def mainloop(self):
        self.root.mainloop()

    ######################################################
    # TK Command handlers
    ######################################################

    def cmd_quit(self):
        "Quit the debugger"
        self.debugger.stop()
        self.root.quit()

    def cmd_run(self, event=None):
        "Run until the next breakpoint, or end of execution"
        self.debugger.do_run()

    def cmd_step(self, event=None):
        "Step into the next line of code"
        self.debugger.do_step()

    def cmd_next(self, event=None):
        "Run the next line of code in the current frame"
        self.debugger.do_next()

    def cmd_return(self, event=None):
        "Return to the previous frame"
        self.debugger.do_return()

    def cmd_open_file(self, event=None):
        "Open a file in the breakpoint pane"
        filename = tkFileDialog.askopenfilename(
            initialdir=os.path.abspath(os.getcwd()))

        if filename:
            # Convert to canonical form
            filename = os.path.abspath(filename)
            filename = os.path.normcase(filename)

            # Show the file contents
            self.code.filename = filename

            # Ensure the file appears on the breakpoint list
            self.breakpoints.insert_filename(filename)

            # Show the breakpoint panel
            self.file_notebook.select(self.breakpoints_frame)

            # ... select the new filename
            self.breakpoints.selection_set(filename)

            # .. and clear any currently selected item on the stack tree
            self.stack.selection_remove(self.stack.selection())

    def cmd_bugjar_page(self):
        "Show the Bugjar project page"
        webbrowser.open_new('http://pybee.org/bugjar')

    def cmd_bugjar_github(self):
        "Show the Bugjar GitHub repo"
        webbrowser.open_new('http://github.com/pybee/bugjar')

    def cmd_bugjar_docs(self):
        "Show the Bugjar documentation"
        # If this is a formal release, show the docs for that
        # version. otherwise, just show the head docs.
        if len(NUM_VERSION) == 3:
            webbrowser.open_new('http://bugjar.readthedocs.org/en/v%s/' %
                                VERSION)
        else:
            webbrowser.open_new('http://bugjar.readthedocs.org/')

    def cmd_beeware_page(self):
        "Show the BeeWare project page"
        webbrowser.open_new('http://pybee.org/')

    ######################################################
    # Handlers for GUI actions
    ######################################################

    def on_stack_frame_selected(self, event):
        "When a stack frame is selected, highlight the file and line"
        if event.widget.selection():
            _, index = event.widget.selection()[0].split(':')
            line, frame = self.debugger.stack[int(index)]

            # Display the file in the code view
            self.show_file(filename=frame['filename'], line=line)

            # Display the contents of the selected frame in the inspector
            self.inspector.show_frame(frame)

            # Clear any currently selected item on the breakpoint tree
            self.breakpoints.selection_remove(self.breakpoints.selection())

    def on_breakpoint_selected(self, event):
        "When a breakpoint on the tree has been selected, show the breakpoint"
        if event.widget.selection():
            parts = event.widget.focus().split(':')
            bp = self.debugger.breakpoint((parts[0], int(parts[1])))
            self.show_file(filename=bp.filename, line=bp.line)

            # Clear any currently selected item on the stack tree
            self.stack.selection_remove(self.stack.selection())

    def on_breakpoint_file_selected(self, event):
        "When a file is selected on the breakpoint tree, show the file"
        if event.widget.selection():
            filename = event.widget.focus()
            self.show_file(filename=filename)

            # Clear any currently selected item on the stack tree
            self.stack.selection_remove(self.stack.selection())

    def on_breakpoint_double_clicked(self, event):
        "When a breakpoint on the tree is double clicked, toggle it's status"
        if event.widget.selection():
            parts = event.widget.focus().split(':')
            bp = self.debugger.breakpoint((parts[0], int(parts[1])))
            if bp.enabled:
                self.debugger.disable_breakpoint(bp)
            else:
                self.debugger.enable_breakpoint(bp)

            # Clear any currently selected item on the stack tree
            self.stack.selection_remove(self.stack.selection())

    ######################################################
    # Handlers for debugger responses
    ######################################################

    def on_stack(self, stack):
        "A report of a new stack"
        # Make sure the stack frame list is displayed
        self.file_notebook.select(self.stack_frame)

        # Update the stack list
        self.stack.update_stack(stack)

        if len(stack) > 0:
            # Update the display of the current file
            line = stack[-1][0]
            filename = stack[-1][1]['filename']
            self.show_file(filename=filename, line=line)

            # Select the current stack frame in the frame list
            self.stack.selection_set('frame:%s' % (len(stack) - 1))
        else:
            # No current frame (probably end of execution),
            # so clear the current line marker
            self.code.line = None

    def on_line(self, filename, line):
        "A single line of code has been executed"
        self.run_status.set('Line (%s:%s)' % (filename, line))

    def on_call(self, args):
        "A callable has been invoked"
        self.run_status.set('Call: %s' % args)

    def on_return(self, retval):
        "A callable has returned"
        self.run_status.set('Return: %s' % retval)

    def on_exception(self, name, value):
        "An exception has been raised"
        self.run_status.set('Exception: %s - %s' % (name, value))
        tkMessageBox.showwarning(message='%s: %s' % (name, value))

    def on_postmortem(self):
        "An exception has been raised"
        self.run_status.set('Post mortem mode')
        tkMessageBox.showerror(
            message='Entering post mortem mode. Step/Next will restart')

    def on_restart(self):
        "The code has finished running, and will start again"
        self.run_status.set('Not running')
        tkMessageBox.showinfo(
            message='Program has finished, and will restart.')

    def on_info(self, message):
        "The debugger needs to inform the user of something"
        tkMessageBox.showinfo(message=message)

    def on_warning(self, message):
        "The debugger needs to warn the user of something"
        tkMessageBox.showwarning(message=message)

    def on_error(self, message):
        "The debugger needs to report an error"
        tkMessageBox.showerror(message=message)

    def on_breakpoint_enable(self, bp):
        "A breakpoint has been enabled in the debugger"
        # If the breakpoint is in the currently displayed file, updated
        # the display of the breakpoint.
        if bp.filename == self.code.filename:
            self.code.enable_breakpoint(bp.line, temporary=bp.temporary)

        # ... then update the display of the breakpoint on the tree
        self.breakpoints.update_breakpoint(bp)

    def on_breakpoint_disable(self, bp):
        "A breakpoint has been disabled in the debugger"
        # If the breakpoint is in the currently displayed file, updated
        # the display of the breakpoint.
        if bp.filename == self.code.filename:
            self.code.disable_breakpoint(bp.line)

        # ... then update the display of the breakpoint on the tree
        self.breakpoints.update_breakpoint(bp)

    def on_breakpoint_ignore(self, bp, count):
        "A breakpoint has been ignored by the debugger"
        # If the breakpoint is in the currently displayed file, updated
        # the display of the breakpoint.
        if bp.filename == self.code.filename:
            self.code.ignore_breakpoint(bp.line)

        # ... then update the display of the breakpoint on the tree
        self.breakpoints.update_breakpoint(bp)

    def on_breakpoint_clear(self, bp):
        "A breakpoint has been cleared in the debugger"
        # If the breakpoint is in the currently displayed file, updated
        # the display of the breakpoint.
        if bp.filename == self.code.filename:
            self.code.clear_breakpoint(bp.line)

        # ... then update the display of the breakpoint on the tree
        self.breakpoints.update_breakpoint(bp)
Beispiel #3
0
class MainWindow(object):
    def __init__(self, root, debugger):
        '''
        -----------------------------------------------------
        | main button toolbar                               |
        -----------------------------------------------------
        |       < ma | in content area >      |             |
        |            |                        |             |
        | File list  | File name              | Inspector   |
        | (stack/    | Code area              |             |
        | breakpnts) |                        |             |
        |            |                        |             |
        |            |                        |             |
        -----------------------------------------------------
        |     status bar area                               |
        -----------------------------------------------------

        '''

        # Obtain and expand the current working directory.
        base_path = os.path.abspath(os.getcwd())
        base_path = os.path.normcase(base_path) + '/'

        # Create a filename normalizer based on the CWD.
        self.filename_normalizer = filename_normalizer(base_path)

        self.debugger = debugger
        # Associate the debugger with this view.
        self.debugger.view = self

        # Root window
        self.root = root
        self.root.title('Bugjar')
        self.root.geometry('1024x768')

        # Prevent the menus from having the empty tearoff entry
        self.root.option_add('*tearOff', False)
        # Catch the close button
        self.root.protocol("WM_DELETE_WINDOW", self.cmd_quit)
        # Catch the "quit" event.
        self.root.createcommand('exit', self.cmd_quit)

        # Setup the menu
        self._setup_menubar()

        # Set up the main content for the window.
        self._setup_button_toolbar()
        self._setup_main_content()
        self._setup_status_bar()

        # Now configure the weights for the root frame
        self.root.columnconfigure(0, weight=1)
        self.root.rowconfigure(0, weight=0)
        self.root.rowconfigure(1, weight=1)
        self.root.rowconfigure(2, weight=0)

        debugger.start()

    ######################################################
    # Internal GUI layout methods.
    ######################################################

    def _setup_menubar(self):
        # Menubar
        self.menubar = Menu(self.root)

        # self.menu_Apple = Menu(self.menubar, name='Apple')
        # self.menubar.add_cascade(menu=self.menu_Apple)

        self.menu_file = Menu(self.menubar)
        self.menubar.add_cascade(menu=self.menu_file, label='File')

        self.menu_program = Menu(self.menubar)
        self.menubar.add_cascade(menu=self.menu_program, label='Program')

        self.menu_help = Menu(self.menubar)
        self.menubar.add_cascade(menu=self.menu_help, label='Help')

        # self.menu_Apple.add_command(label='Test', command=self.cmd_dummy)

        # self.menu_file.add_command(label='New', command=self.cmd_dummy, accelerator="Command-N")
        self.menu_file.add_command(label='Open...', command=self.cmd_open_file, accelerator="Command-O")
        self.root.bind('<Command-o>', self.cmd_open_file)
        # self.menu_file.add_command(label='Close', command=self.cmd_dummy)

        self.menu_program.add_command(label='Run', command=self.cmd_run, accelerator="R")
        self.root.bind('<r>', self.cmd_run)
        self.menu_program.add_command(label='Step', command=self.cmd_step, accelerator="S")
        self.root.bind('<s>', self.cmd_step)
        self.menu_program.add_command(label='Next', command=self.cmd_next, accelerator="N")
        self.root.bind('<n>', self.cmd_next)
        self.menu_program.add_command(label='Return', command=self.cmd_return, accelerator="BackSpace")
        self.root.bind('<BackSpace>', self.cmd_return)

        self.menu_help.add_command(label='Open Documentation', command=self.cmd_bugjar_docs)
        self.menu_help.add_command(label='Open Bugjar project page', command=self.cmd_bugjar_page)
        self.menu_help.add_command(label='Open Bugjar on GitHub', command=self.cmd_bugjar_github)
        self.menu_help.add_command(label='Open BeeWare project page', command=self.cmd_beeware_page)

        # last step - configure the menubar
        self.root['menu'] = self.menubar

    def _setup_button_toolbar(self):
        '''
        The button toolbar runs as a horizontal area at the top of the GUI.
        It is a persistent GUI component
        '''

        # Main toolbar
        self.toolbar = Frame(self.root)
        self.toolbar.grid(column=0, row=0, sticky=(W, E))

        # Buttons on the toolbar
        self.run_button = Button(self.toolbar, text='Run', command=self.cmd_run)
        self.run_button.grid(column=0, row=0)

        self.step_button = Button(self.toolbar, text='Step', command=self.cmd_step)
        self.step_button.grid(column=1, row=0)

        self.next_button = Button(self.toolbar, text='Next', command=self.cmd_next)
        self.next_button.grid(column=2, row=0)

        self.return_button = Button(self.toolbar, text='Return', command=self.cmd_return)
        self.return_button.grid(column=3, row=0)

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

    def _setup_main_content(self):
        '''
        Sets up the main content area. It is a persistent GUI component
        '''

        # Main content area
        self.content = PanedWindow(self.root, orient=HORIZONTAL)
        self.content.grid(column=0, row=1, sticky=(N, S, E, W))

        # Create subregions of the content
        self._setup_file_lists()
        self._setup_code_area()
        self._setup_inspector()

        # Set up weights for the left frame's content
        self.content.columnconfigure(0, weight=1)
        self.content.rowconfigure(0, weight=1)

        self.content.pane(0, weight=1)
        self.content.pane(1, weight=2)
        self.content.pane(2, weight=1)

    def _setup_file_lists(self):

        self.file_notebook = Notebook(self.content, padding=(0, 5, 0, 5))
        self.content.add(self.file_notebook)

        self._setup_stack_frame_list()
        self._setup_breakpoint_list()

    def _setup_stack_frame_list(self):
        self.stack_frame = Frame(self.content)
        self.stack_frame.grid(column=0, row=0, sticky=(N, S, E, W))
        self.file_notebook.add(self.stack_frame, text='Stack')

        self.stack = StackView(self.stack_frame, normalizer=self.filename_normalizer)
        self.stack.grid(column=0, row=0, sticky=(N, S, E, W))

        # # The tree's vertical scrollbar
        self.stack_scrollbar = Scrollbar(self.stack_frame, orient=VERTICAL)
        self.stack_scrollbar.grid(column=1, row=0, sticky=(N, S))

        # # Tie the scrollbar to the text views, and the text views
        # # to each other.
        self.stack.config(yscrollcommand=self.stack_scrollbar.set)
        self.stack_scrollbar.config(command=self.stack.yview)

        # Setup weights for the "stack" tree
        self.stack_frame.columnconfigure(0, weight=1)
        self.stack_frame.columnconfigure(1, weight=0)
        self.stack_frame.rowconfigure(0, weight=1)

        # Handlers for GUI events
        self.stack.bind('<<TreeviewSelect>>', self.on_stack_frame_selected)

    def _setup_breakpoint_list(self):
        self.breakpoints_frame = Frame(self.content)
        self.breakpoints_frame.grid(column=0, row=0, sticky=(N, S, E, W))
        self.file_notebook.add(self.breakpoints_frame, text='Breakpoints')

        self.breakpoints = BreakpointView(self.breakpoints_frame, normalizer=self.filename_normalizer)
        self.breakpoints.grid(column=0, row=0, sticky=(N, S, E, W))

        # The tree's vertical scrollbar
        self.breakpoints_scrollbar = Scrollbar(self.breakpoints_frame, orient=VERTICAL)
        self.breakpoints_scrollbar.grid(column=1, row=0, sticky=(N, S))

        # Tie the scrollbar to the text views, and the text views
        # to each other.
        self.breakpoints.config(yscrollcommand=self.breakpoints_scrollbar.set)
        self.breakpoints_scrollbar.config(command=self.breakpoints.yview)

        # Setup weights for the "breakpoint list" tree
        self.breakpoints_frame.columnconfigure(0, weight=1)
        self.breakpoints_frame.columnconfigure(1, weight=0)
        self.breakpoints_frame.rowconfigure(0, weight=1)

        # Handlers for GUI events
        self.breakpoints.tag_bind('breakpoint', '<Double-Button-1>', self.on_breakpoint_double_clicked)
        self.breakpoints.tag_bind('breakpoint', '<<TreeviewSelect>>', self.on_breakpoint_selected)
        self.breakpoints.tag_bind('file', '<<TreeviewSelect>>', self.on_breakpoint_file_selected)

    def _setup_code_area(self):
        self.code_frame = Frame(self.content)
        self.code_frame.grid(column=1, row=0, sticky=(N, S, E, W))

        # Label for current file
        self.current_file = StringVar()
        self.current_file_label = Label(self.code_frame, textvariable=self.current_file)
        self.current_file_label.grid(column=0, row=0, sticky=(W, E))

        # Code display area
        self.code = DebuggerCode(self.code_frame, debugger=self.debugger)
        self.code.grid(column=0, row=1, sticky=(N, S, E, W))

        # Set up weights for the code frame's content
        self.code_frame.columnconfigure(0, weight=1)
        self.code_frame.rowconfigure(0, weight=0)
        self.code_frame.rowconfigure(1, weight=1)

        self.content.add(self.code_frame)

    def _setup_inspector(self):
        self.inspector_frame = Frame(self.content)
        self.inspector_frame.grid(column=2, row=0, sticky=(N, S, E, W))

        self.inspector = InspectorView(self.inspector_frame)
        self.inspector.grid(column=0, row=0, sticky=(N, S, E, W))

        # The tree's vertical scrollbar
        self.inspector_scrollbar = Scrollbar(self.inspector_frame, orient=VERTICAL)
        self.inspector_scrollbar.grid(column=1, row=0, sticky=(N, S))

        # Tie the scrollbar to the text views, and the text views
        # to each other.
        self.inspector.config(yscrollcommand=self.inspector_scrollbar.set)
        self.inspector_scrollbar.config(command=self.inspector.yview)

        # Setup weights for the "breakpoint list" tree
        self.inspector_frame.columnconfigure(0, weight=1)
        self.inspector_frame.columnconfigure(1, weight=0)
        self.inspector_frame.rowconfigure(0, weight=1)

        self.content.add(self.inspector_frame)

    def _setup_status_bar(self):
        # Status bar
        self.statusbar = Frame(self.root)
        self.statusbar.grid(column=0, row=2, sticky=(W, E))

        # Current status
        self.run_status = StringVar()
        self.run_status_label = Label(self.statusbar, textvariable=self.run_status)
        self.run_status_label.grid(column=0, row=0, sticky=(W, E))
        self.run_status.set('Not running')

        # Main window resize handle
        self.grip = Sizegrip(self.statusbar)
        self.grip.grid(column=1, row=0, sticky=(S, E))

        # Set up weights for status bar frame
        self.statusbar.columnconfigure(0, weight=1)
        self.statusbar.columnconfigure(1, weight=0)
        self.statusbar.rowconfigure(0, weight=0)

    ######################################################
    # Utility methods for controlling content
    ######################################################

    def show_file(self, filename, line=None, breakpoints=None):
        """Show the content of the nominated file.

        If specified, line is the current line number to highlight. If the
        line isn't currently visible, the window will be scrolled until it is.

        breakpoints is a list of line numbers that have current breakpoints.

        If refresh is true, the file will be reloaded and redrawn.
        """
        # Set the filename label for the current file
        self.current_file.set(self.filename_normalizer(filename))

        # Update the code view; this means changing the displayed file
        # if necessary, and updating the current line.
        if filename != self.code.filename:
            self.code.filename = filename
            for bp in self.debugger.breakpoints(filename).values():
                if bp.enabled:
                    self.code.enable_breakpoint(bp.line)
                else:
                    self.code.disable_breakpoint(bp.line)

        self.code.line = line

    ######################################################
    # TK Main loop
    ######################################################

    def mainloop(self):
        self.root.mainloop()

    ######################################################
    # TK Command handlers
    ######################################################

    def cmd_quit(self):
        "Quit the debugger"
        self.debugger.stop()
        self.root.quit()

    def cmd_run(self, event=None):
        "Run until the next breakpoint, or end of execution"
        self.debugger.do_run()

    def cmd_step(self, event=None):
        "Step into the next line of code"
        self.debugger.do_step()

    def cmd_next(self, event=None):
        "Run the next line of code in the current frame"
        self.debugger.do_next()

    def cmd_return(self, event=None):
        "Return to the previous frame"
        self.debugger.do_return()

    def cmd_open_file(self, event=None):
        "Open a file in the breakpoint pane"
        filename = tkFileDialog.askopenfilename(initialdir=os.path.abspath(os.getcwd()))

        if filename:
            # Convert to canonical form
            filename = os.path.abspath(filename)
            filename = os.path.normcase(filename)

            # Show the file contents
            self.code.filename = filename

            # Ensure the file appears on the breakpoint list
            self.breakpoints.insert_filename(filename)

            # Show the breakpoint panel
            self.file_notebook.select(self.breakpoints_frame)

            # ... select the new filename
            self.breakpoints.selection_set(filename)

            # .. and clear any currently selected item on the stack tree
            self.stack.selection_remove(self.stack.selection())

    def cmd_bugjar_page(self):
        "Show the Bugjar project page"
        webbrowser.open_new('http://pybee.org/bugjar')

    def cmd_bugjar_github(self):
        "Show the Bugjar GitHub repo"
        webbrowser.open_new('http://github.com/pybee/bugjar')

    def cmd_bugjar_docs(self):
        "Show the Bugjar documentation"
        # If this is a formal release, show the docs for that
        # version. otherwise, just show the head docs.
        if len(NUM_VERSION) == 3:
            webbrowser.open_new('http://bugjar.readthedocs.org/en/v%s/' % VERSION)
        else:
            webbrowser.open_new('http://bugjar.readthedocs.org/')

    def cmd_beeware_page(self):
        "Show the BeeWare project page"
        webbrowser.open_new('http://pybee.org/')

    ######################################################
    # Handlers for GUI actions
    ######################################################

    def on_stack_frame_selected(self, event):
        "When a stack frame is selected, highlight the file and line"
        if event.widget.selection():
            _, index = event.widget.selection()[0].split(':')
            line, frame = self.debugger.stack[int(index)]

            # Display the file in the code view
            self.show_file(filename=frame['filename'], line=line)

            # Display the contents of the selected frame in the inspector
            self.inspector.show_frame(frame)

            # Clear any currently selected item on the breakpoint tree
            self.breakpoints.selection_remove(self.breakpoints.selection())

    def on_breakpoint_selected(self, event):
        "When a breakpoint on the tree has been selected, show the breakpoint"
        if event.widget.selection():
            parts = event.widget.focus().split(':')
            bp = self.debugger.breakpoint((parts[0], int(parts[1])))
            self.show_file(filename=bp.filename, line=bp.line)

            # Clear any currently selected item on the stack tree
            self.stack.selection_remove(self.stack.selection())

    def on_breakpoint_file_selected(self, event):
        "When a file is selected on the breakpoint tree, show the file"
        if event.widget.selection():
            filename = event.widget.focus()
            self.show_file(filename=filename)

            # Clear any currently selected item on the stack tree
            self.stack.selection_remove(self.stack.selection())

    def on_breakpoint_double_clicked(self, event):
        "When a breakpoint on the tree is double clicked, toggle it's status"
        if event.widget.selection():
            parts = event.widget.focus().split(':')
            bp = self.debugger.breakpoint((parts[0], int(parts[1])))
            if bp.enabled:
                self.debugger.disable_breakpoint(bp)
            else:
                self.debugger.enable_breakpoint(bp)

            # Clear any currently selected item on the stack tree
            self.stack.selection_remove(self.stack.selection())

    ######################################################
    # Handlers for debugger responses
    ######################################################

    def on_stack(self, stack):
        "A report of a new stack"
        # Make sure the stack frame list is displayed
        self.file_notebook.select(self.stack_frame)

        # Update the stack list
        self.stack.update_stack(stack)

        if len(stack) > 0:
            # Update the display of the current file
            line = stack[-1][0]
            filename = stack[-1][1]['filename']
            self.show_file(filename=filename, line=line)

            # Select the current stack frame in the frame list
            self.stack.selection_set('frame:%s' % (len(stack) - 1))
        else:
            # No current frame (probably end of execution),
            # so clear the current line marker
            self.code.line = None

    def on_line(self, filename, line):
        "A single line of code has been executed"
        self.run_status.set('Line (%s:%s)' % (filename, line))

    def on_call(self, args):
        "A callable has been invoked"
        self.run_status.set('Call: %s' % args)

    def on_return(self, retval):
        "A callable has returned"
        self.run_status.set('Return: %s' % retval)

    def on_exception(self, name, value):
        "An exception has been raised"
        self.run_status.set('Exception: %s - %s' % (name, value))
        tkMessageBox.showwarning(message='%s: %s' % (name, value))

    def on_postmortem(self):
        "An exception has been raised"
        self.run_status.set('Post mortem mode')
        tkMessageBox.showerror(message='Entering post mortem mode. Step/Next will restart')

    def on_restart(self):
        "The code has finished running, and will start again"
        self.run_status.set('Not running')
        tkMessageBox.showinfo(message='Program has finished, and will restart.')

    def on_info(self, message):
        "The debugger needs to inform the user of something"
        tkMessageBox.showinfo(message=message)

    def on_warning(self, message):
        "The debugger needs to warn the user of something"
        tkMessageBox.showwarning(message=message)

    def on_error(self, message):
        "The debugger needs to report an error"
        tkMessageBox.showerror(message=message)

    def on_breakpoint_enable(self, bp):
        "A breakpoint has been enabled in the debugger"
        # If the breakpoint is in the currently displayed file, updated
        # the display of the breakpoint.
        if bp.filename == self.code.filename:
            self.code.enable_breakpoint(bp.line, temporary=bp.temporary)

        # ... then update the display of the breakpoint on the tree
        self.breakpoints.update_breakpoint(bp)

    def on_breakpoint_disable(self, bp):
        "A breakpoint has been disabled in the debugger"
        # If the breakpoint is in the currently displayed file, updated
        # the display of the breakpoint.
        if bp.filename == self.code.filename:
            self.code.disable_breakpoint(bp.line)

        # ... then update the display of the breakpoint on the tree
        self.breakpoints.update_breakpoint(bp)

    def on_breakpoint_ignore(self, bp, count):
        "A breakpoint has been ignored by the debugger"
        # If the breakpoint is in the currently displayed file, updated
        # the display of the breakpoint.
        if bp.filename == self.code.filename:
            self.code.ignore_breakpoint(bp.line)

        # ... then update the display of the breakpoint on the tree
        self.breakpoints.update_breakpoint(bp)

    def on_breakpoint_clear(self, bp):
        "A breakpoint has been cleared in the debugger"
        # If the breakpoint is in the currently displayed file, updated
        # the display of the breakpoint.
        if bp.filename == self.code.filename:
            self.code.clear_breakpoint(bp.line)

        # ... then update the display of the breakpoint on the tree
        self.breakpoints.update_breakpoint(bp)
Beispiel #4
0
class MainApplication(Tk):
    def __init__(self, network_discoverer):
        Tk.__init__(self)
        self.winfo_toplevel().title("fHTTP")
        self.title_font = tkfont.Font(family='Helvetica',
                                      size=14,
                                      weight='bold',
                                      slant='italic')
        self.h2_font = tkfont.Font(family='Helvetica', size=12, weight='bold')
        self.h3_font = tkfont.Font(family='Helvetica', size=11, weight='bold')
        self.network_discoverer = network_discoverer
        self.own_mac_address = network_discoverer.get_own_mac_address()
        self.own_ip_address = network_discoverer.get_own_ip_address()
        self.ip_to_mac = None
        self.ip_to_mac_record = None
        self.configure(background='darkgrey')

        self.is_spoofing = self.is_extracting = self.is_filtering = False
        self.verbose_mode = False  # verbose mode on/off for output frame

        self.victims = None
        self.target = None

        width = int(self.winfo_screenwidth() * 0.5)
        height = int(self.winfo_screenheight() * 0.8)
        x_start = int(self.winfo_screenwidth() * 0.25)
        y_start = int(self.winfo_screenheight() * 0.1)
        self.geometry('%dx%d+%d+%d' % (width, height, x_start, y_start))
        self.resizable(0, 0)  # do not feel like dealing with resizable frames
        self.conf_menu_bar()  # configure menu-bar

        img_icon = PhotoImage(file=media_dir + os.path.sep + 'fhttp_logo.ico')
        self.tk.call('wm', 'iconphoto', self._w, img_icon)

        for row in range(0, 100):
            self.rowconfigure(row, weight=1)
            self.columnconfigure(row, weight=1)

        # notebook configuration (tabs)
        style = Style()
        style.theme_settings(
            "default", {
                "TNotebook": {
                    "configure": {
                        "tabmargins": [0, 0, 0, 0]
                    }
                },
                "TNotebook.Tab": {
                    "configure": {
                        "padding": [8, 1, 8, 1]
                    }
                }
            })
        self.notebook = Notebook(self)
        self.notebook.grid(row=1,
                           column=0,
                           columnspan=100,
                           rowspan=10,
                           sticky='nesw',
                           padx=5)

        # output frame configuration
        self.output = OutputFrame(parent=self)
        self.output.grid(row=13,
                         column=0,
                         columnspan=100,
                         rowspan=85,
                         sticky='nesw',
                         padx=5)

        # notebook frames
        self.tabs = {}
        self.tab_mapping = OrderedDict([
            (StartFrame, 'Start'),
            (LocalNetworkScanFrame, 'Local Network Scan'),
            (ARPSpoofFrame, 'ARP Spoofing'),
            (InjectorExtractorFrame, 'Injection and Extraction')
        ])
        for tab in self.tab_mapping.keys():
            tab_frame_name = self.tab_mapping[tab]
            frame = tab(parent=self.notebook, controller=self)
            self.notebook.add(frame, text=tab_frame_name)
            self.tabs[tab.__name__] = frame

        self.notebook.tab(self.notebook.index(
            self.tabs['InjectorExtractorFrame']),
                          state=DISABLED)
        self.notebook.tab(self.notebook.index(self.tabs['ARPSpoofFrame']),
                          state=DISABLED)

        tkMessageBox.showinfo(
            "fHTTP", "\n\n\nWelcome to fhttp\n\n"
            "We inherently trust no one, including each other\n\n\n".ljust(
                500))

    def conf_menu_bar(self):
        menu_bar = Menu(self)
        # help menu
        help_menu = Menu(menu_bar, tearoff=0)
        help_menu.add_command(label='About', command=self.display_about)
        help_menu.add_command(label='Support and Documentation',
                              command=self.display_support_doc)
        # help_menu.add_separator()
        menu_bar.add_cascade(label='Help', menu=help_menu)

        menu_bar.add_command(label='Exit', command=self.quit)
        self.config(menu=menu_bar)

    def clean_output_and_attack_frame(self):
        self.output = OutputFrame(parent=self)
        self.output.grid(row=13,
                         column=0,
                         columnspan=100,
                         rowspan=85,
                         sticky='nesw',
                         padx=5)

    @staticmethod
    def display_about():
        tkMessageBox.showinfo(
            "About",
            "fhttp is an application which is capable of exploiting vulnerabilities "
            "such as ARP cache poisoning. The (man-in-the-middle) positions that are acquired "
            "through the exploitation of these vulnerabilities are then used for things such as "
            "packet-sniffing, the `theft' of (insecure) cookies and img-tag-injection\n\n"
            "Abdel K. Bokharouss and Adriaan Knapen \n")

    @staticmethod
    def display_support_doc():
        webbrowser.open('https://github.com/akbokha/fhttp')

    def show_frame(self, page_name, select=True, update=False):
        frame = self.tabs[page_name]
        if update:
            try:
                frame.update()
            except AttributeError:
                pass
        if select:
            self.notebook.select(self.notebook.index(frame))

    def scan_and_update(self):
        self.ip_to_mac_record = self.network_discoverer.get_ip_to_mac_mapping(
            update=True)
        self.ip_to_mac = self.ip_to_mac_record.get_all()
Beispiel #5
0
class Application(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        self.master = master
        self.master.title("Netstat Live")
        self.pack(fill=tk.BOTH, expand=tk.Y)
        
        master.protocol("WM_DELETE_WINDOW", self.app_quit)
        self._app_quit = False
        
        self._freeze = False
        
        self.tabs = Notebook(self)
        
        self.tabs_frames = OrderedDict()
        self.tabs_frames['TCP4'] = {'query': netstat_tcp4}
        self.tabs_frames['UDP4'] = {'query': netstat_udp4}
        self.tabs_frames['TCP6'] = {'query': netstat_tcp6}
        self.tabs_frames['UDP6'] = {'query': netstat_udp6}
        
        for tab in self.tabs_frames:
            # Creating tabs
            self.tabs_frames[tab]['tab'] = tk.Frame(self.tabs)
            self.tabs.add(self.tabs_frames[tab]['tab'], text=tab)
            #self.tabs_frames[tab]['tab'].pack(fill=tk.BOTH)
            # Adding Treeview widget to tabs
            self.tabs_frames[tab]['tbl'] = Treeview(self.tabs_frames[tab]['tab'])
            self.tabs_frames[tab]['tbl']['columns'] = ('Pid', 'User', 'Local addr', 'Remote addr', 'State')
            for column in self.tabs_frames[tab]['tbl']['columns']:
                self.tabs_frames[tab]['tbl'].heading(column, text=column)
                self.tabs_frames[tab]['tbl'].column(column, width=150)
            self.tabs_frames[tab]['scrollbar_y'] = Scrollbar(self.tabs_frames[tab]['tab'], orient=tk.VERTICAL, command=self.tabs_frames[tab]['tbl'].yview)
            self.tabs_frames[tab]['tbl']['yscroll'] = self.tabs_frames[tab]['scrollbar_y'].set
            self.tabs_frames[tab]['scrollbar_y'].pack(side=tk.RIGHT, fill=tk.Y)
            self.tabs_frames[tab]['tbl'].pack(expand=tk.Y, fill=tk.BOTH)
            # Bind right click event for displaying context menu
            self.tabs_frames[tab]['tbl'].bind('<Button-3>', self.context_menu_popup)
            self.tabs_frames[tab]['tbl'].bind('<Button-1>', self.context_menu_unpost)
            # Creating queue for each tab
            self.tabs_frames[tab]['queue'] = Queue(maxsize=1)
        self.tabs.pack(fill=tk.BOTH, expand=tk.Y)
        
        # Freeze button
        self.buttons = tk.Frame(master)
        self.buttons.pack(side=tk.BOTTOM, fill=tk.BOTH)
        self.freeze_btn = tk.Button(self.buttons, text='Freeze', command=self.freeze_btn_handler)
        self.freeze_btn.pack(side=tk.RIGHT)
        
        # Check dependencies
        self._xclip = True
        self._whois = True
        try:
            out = subprocess.check_output(['xclip', '-h'], stderr=subprocess.STDOUT)
        except:
            self._xclip = False
        try:
            out = subprocess.check_output(['whois', '--version'], stderr=subprocess.STDOUT)
        except:
            self._whois = False
        
        # Connections list context menu
        self._remote_addr = ''
        self.context_menu = tk.Menu(self, tearoff=0)
        if self._xclip:
            self.context_menu.add_command(label='Copy remote addr.', command=self.xclip)
        if self._whois:
            self.context_menu.add_command(label='Whois', command=self.whois)
        self.tabs.bind('<Button-1>', self.context_menu_unpost)
        
        self.poll = Thread(target=self.thread)
        self.poll.start()
        
    def context_menu_popup(self, event):
        current_tab = self.get_active_tab()
        tbl = self.tabs_frames[current_tab]['tbl']
        item = tbl.identify_row(event.y)
        if item and len(tbl.get_children(item)) == 0:
            tbl.selection_set(item)
            # Get remote addr value
            self._remote_addr = tbl.set(item, column='Remote addr')
            self.context_menu.post(event.x_root, event.y_root)
        else:
            # Mouse pointer is not over item
            pass
    
    def context_menu_unpost(self, event):
        self.context_menu.unpost()

    def get_active_tab(self):
        try:
            current_tab = self.tabs.tab(self.tabs.select(), 'text')
            return current_tab
        except RuntimeError:
            # Sometimes raised on KeyboardInterrupt
            sys.stderr.write('Terminated.\n')
            self._app_quit = True
            sys.exit(0)
    
    def thread(self):
        while not self._app_quit:
            current_tab = self.tabs_frames[self.get_active_tab()]
            if current_tab['queue'].empty():
                # Get netstat data
                try:
                    netstat = current_tab['query']()
                except RuntimeError:
                    sys.stderr.write('Main thread destroyed.\n')
                # Put to queue
                current_tab['queue'].put(netstat, True)
            else:
                sleep(0.5)
    
    def app_quit(self):
        self._app_quit = True
        self.master.destroy()
    
    def refresh(self):
        current_tab = self.get_active_tab()
        queue = self.tabs_frames[current_tab]['queue']
        if not self._freeze and not queue.empty():
            
            # Get active tab
            tbl = self.tabs_frames[current_tab]['tbl']
            
            # Remember focus
            self.tabs_frames[current_tab]['focus'] = tbl.selection()
            
            data = queue.get(False)
            processes = []
            for proc in data:
                processes.append(proc[6])
            processes = tuple(set(processes)) # Unique list of processes in netstat
            
            # Clear tree:
            for proc in tbl.get_children():
                tbl.delete(*tbl.get_children(proc))
        
            for proc in processes:
                proc_name = '%s (%s)' % (os.path.basename(str(proc)), str(proc))
                if not tbl.exists(proc_name):
                    # Create root items for each process name
                    tbl.insert('', 'end', proc_name, text=proc_name)
        
            for proc in data:
                proc_name = '%s (%s)' % (os.path.basename(str(proc[6])), str(proc[6]))
                #         Pid           User          Local addr    Remote addr   State
                values = (str(proc[5]), str(proc[1]), str(proc[2]), str(proc[3]), str(proc[4]))
                h = hash(tuple(proc))
                try:
                    tbl.insert(proc_name, 'end', h, text=proc_name, values=values)
                except:
                    pass
    
            # Removing empty root items
            for proc in tbl.get_children():
                if len(tbl.get_children(proc)) == 0:
                    tbl.delete(proc)
            
            # Restore focus
            try:
                tbl.selection_set(self.tabs_frames[current_tab]['focus'])
            except:
                pass
            
        self.master.after(500, self.refresh)
        
    def freeze_btn_handler(self):
        # Toggle freeze state
        if self._freeze:
            self.freeze_btn['text'] = 'Freeze'
        else:
            self.freeze_btn['text'] = 'Continue'
        self._freeze = not self._freeze

    def xclip(self, data=None):
        if not data:
            data = self._remote_addr
        try:
            xclip = subprocess.Popen(['xclip', '-selection', 'clipboard'], stdin=subprocess.PIPE)
            xclip.communicate(input=data)
            xclip.terminate()
        except:
            pass
    
    def whois(self, addr=None):
        if not addr:
            addr = self._remote_addr
        addr = addr.split(':')
        try:
            reverse = subprocess.check_output(['dig', '+short', '-x', addr[0]])
        except:
            reverse = None
        
        try:
            out = subprocess.check_output(['whois', addr[0]])
        except:
            out = 'No info for this host.'
        
        self.whois_popup = {}
        self.whois_popup['window'] = tk.Toplevel(self)
        self.whois_popup['window'].title('Whois %s' % addr[0])
        self.whois_popup['frame'] = tk.Frame(self.whois_popup['window'])
        self.whois_popup['frame'].pack(fill=tk.BOTH, expand=tk.Y)
        self.whois_popup['text'] = tk.Text(self.whois_popup['frame'], wrap=tk.WORD, height=32, width=96)
        self.whois_popup['text'].pack(fill=tk.BOTH, expand=tk.Y, side=tk.LEFT)
        self.whois_popup['scrollbar_y'] = Scrollbar(self.whois_popup['frame'])
        self.whois_popup['scrollbar_y'].config(command=self.whois_popup['text'].yview)
        self.whois_popup['scrollbar_y'].pack(side=tk.RIGHT, fill=tk.Y)
        self.whois_popup['text'].config(yscrollcommand=self.whois_popup['scrollbar_y'].set)
        if reverse:
            reverse = 'Reverse lookup: %s\n' % reverse
            self.whois_popup['text'].insert(tk.END, reverse)
        self.whois_popup['text'].insert(tk.END, out)
            
        tk.Button(self.whois_popup['window'], text='Ok', command=self.whois_popup['window'].destroy).pack()
Beispiel #6
0
class Interface():
    def __init__(self):
        print("PASTA ATUAL MAIN: " + os.getcwd())
        self.errorReport = ErrorReport("logs_errors/error_db.log")
        self.db = DatabaseGui()
        if self.db.checkStatus():
            self.defineFontsVars()
            self.configWindow("1.0.0")
            self.defineVars()
            self.configWidgetsMenuOptions()
            self.configWidgetsCreateForm()
            self.configWidgetsGetApps()

            self.setWidgets()

            ############################ FUNCAO TEMPORARIA APENAS PARA DESENVOLVIMENTO
            self.nextTabFrameFieldForm()
        else:
            self.errorReport.showAndSaveError(
                self.db.getErrorDb(), "Erro ao inicializar banco de dados")

    def defineVars(self):
        self.frameOld = None
        self.optionVar = IntVar()
        self.nameFormVar = StringVar()
        self.pathImageFormVar = StringVar()
        self.titleFormVar = StringVar()

        self.validateDateReg = self.window.register(validateDate)
        self.validatePhoneReg = self.window.register(validatePhone)

        self.nameFormVar.trace("w", self.checkInfoAppCompleted)
        self.pathImageFormVar.trace("w", self.checkInfoAppCompleted)

        self.menuOptionsFunctions = [
            self.activeOptionCreateForm, self.activeOptionGetApps
        ]
        self.listElementThisForm = {}
        self.idTemporaryElement = 0
        self.menuRightStateVar = False

    def defineFontsVars(self):
        self.font = ("Arial", 13)
        self.fontMin = ("Arial", 10)
        self.fontMax = ("Arial", 15)

    def setWidgets(self):
        self.optionVar.set(0)
        self.pathImageFormVar.set("link da imagem")
        self.rb1.invoke(
        )  #Aciona o RadioButton CreateForm para renderizar os elementos na frameCreateForm

    def configWindow(self, version):
        self.window = Tk()
        self.window.title("Forms App {}".format(version))
        self.window.geometry("900x500+150+100")
        self.window.iconbitmap("images/imagesFormsApp/imageApp.ico")

        title = "Crie seu App, formulários, realize estatísticas, \nedite e estude seus dados com o Forms App"
        image = renderPhoto("images/imagesFormsApp/imageApp.png", (60, 60))
        Label(self.window, font=("Arial Rounded MT Bold", 15), background="thistle", foreground="chocolate", \
         text=title, padx=10, pady=10, image=image, compound=RIGHT)\
        .pack(side=TOP, fill="x", ipady=5)
        self.frameBody = Frame(self.window, background="paleturquoise")
        self.frameBody.pack(side=TOP, expand=True, fill=BOTH)

        self.menuRight = Frame(self.frameBody,
                               background="paleturquoise",
                               width=150)
        self.menuRight.pack(side=RIGHT, fill=Y)

    def configWidgetsMenuOptions(self):
        frameOptions = Frame(self.frameBody, background="paleturquoise")
        frameOptions.pack(side=LEFT, fill=Y, padx=5, pady=5)

        self.rb1 = Radiobutton(frameOptions,
                               font=self.font,
                               text="Novo App",
                               variable=self.optionVar,
                               value=0,
                               indicatoron=0,
                               width=15,
                               height=2,
                               command=self.actionOptions)
        self.rb1.grid(row=1, column=0)
        self.rb2 = Radiobutton(frameOptions,
                               font=self.font,
                               text="Todos",
                               variable=self.optionVar,
                               value=1,
                               indicatoron=0,
                               width=15,
                               height=2,
                               command=self.actionOptions)
        self.rb2.grid(row=2, column=0)

    def configWidgetsCreateForm(self):
        self.frameCreateForm = Frame(self.frameBody)

        self.framesNotebook = Notebook(self.frameCreateForm)
        self.framesNotebook.pack(expand=True, fill=BOTH)

        self.tabFrameInfoForm = Frame(self.framesNotebook)
        self.tabFrameFieldForm = Frame(self.framesNotebook)

        self.framesNotebook.add(self.tabFrameInfoForm,
                                compound=LEFT,
                                image=renderPhoto(
                                    "images\\imagesFormsApp\\app.png",
                                    (40, 40)),
                                sticky=W + E + N + S,
                                text="Info App",
                                padding='0.1i')
        self.framesNotebook.add(self.tabFrameFieldForm,
                                compound=LEFT,
                                image=renderPhoto(
                                    "images\\imagesFormsApp\\document.png",
                                    (40, 40)),
                                sticky=W + E + N + S,
                                text="Item",
                                padding='0.1i')
        self.framesNotebook.hide(self.tabFrameFieldForm)

        # -------------- tabFrameInfoForm -------------

        title = "Crie seu App aqui"
        Label(self.tabFrameInfoForm, text=title, font=self.font)\
        .grid(row=0, column=0, columnspan=5)

        Label(self.tabFrameInfoForm, text="Nome",
              font=self.fontMin).grid(row=1, column=0)
        inputName = Entry(self.tabFrameInfoForm,
                          font=self.fontMin,
                          textvariable=self.nameFormVar)
        inputName.grid(row=1, column=1, pady=10, sticky=W + E + N + S)
        #inputName.bind("<KeyPress>", self.checkInfoAppCompleted)

        Label(self.tabFrameInfoForm, text="Descrição",
              font=self.fontMin).grid(row=2, column=0)
        self.textWidget = Text(self.tabFrameInfoForm,
                               pady=10,
                               font=self.fontMin,
                               width=50,
                               height=3)
        self.textWidget.grid(row=2, column=1, sticky=W + E + N + S)
        self.descriptionFormVar = self.createVarByTextWidget(self.textWidget)

        self.imageWidget = Label(self.tabFrameInfoForm,
                                 padx=10,
                                 pady=10,
                                 background="lightcyan",
                                 anchor=N)
        self.imageWidget.grid(row=1,
                              column=2,
                              rowspan=2,
                              sticky=W + E + N + S,
                              padx=10,
                              pady=10)

        Label(self.tabFrameInfoForm, padx=10, pady=10, background="lightcyan", font=self.fontMin, textvariable=self.pathImageFormVar)\
        .grid(row=3, column=1, sticky=W+E+N+S)
        Button(self.tabFrameInfoForm, font=self.fontMin, text="Procurar Imagem", command=self.actionChoiseImageForm)\
        .grid(row=3, column=2, padx=10, pady=10)

        self.buttonNext = Button(self.tabFrameInfoForm,
                                 state="disabled",
                                 font=self.fontMin,
                                 text="Prosseguir",
                                 command=self.actionNextTabFrameFieldForm)
        self.buttonNext.grid(row=4, column=1, padx=20, pady=15)

        # -------------- tabFrameFieldForm -------------

        Label(self.tabFrameFieldForm, textvariable=self.titleFormVar, font=self.font)\
        .pack(side=TOP)

        frameBodyForm = Frame(self.tabFrameFieldForm, background="lightcyan")
        frameBodyForm.pack(side=TOP, fill=BOTH, expand=True, padx=5)

        frameMenuElementsForm = Frame(
            frameBodyForm)  #Frame que contera todos os elementos existentes
        frameMenuElementsForm.pack(side=LEFT, fill=Y, ipadx=5)
        self.frameRenderElementsForm = Frame(
            frameBodyForm
        )  #Frame que contera todos os elementos escolhidos pelo usuario
        self.frameRenderElementsForm.pack(side=LEFT, fill=Y, ipadx=5, ipady=5)

        Label(frameMenuElementsForm, text="Elementos",
              font=self.font).pack(side=TOP)
        for element in self.db.getAllElemments(
        ):  #Mostra todos os elementos em forma de botoes para serem adicionados no formulário
            function = lambda id_element=element[0], name_element=element[1], type_element=element[2], multline=element[3], widget_tkinter=element[5]:\
             self.actionAddElement(id_element, name_element, type_element, multline, widget_tkinter)

            Button(frameMenuElementsForm, width=15, height=2, \
             text=element[1], command=function, repeatdelay=700, \
             borderwidth=3, activebackground="lightseagreen", \
             background="darkcyan", cursor="sb_right_arrow").pack(side=TOP)

        #Cria opcoes especificas no meu direito para FieldForm
        self.createMenuSideForFieldForm()

    def checkInfoAppCompleted(
            self, a, b, c
    ):  #checa se todos os campos de informacoes do app foram preenchidas
        if self.nameFormVar.get(
        ) and self.pathImageFormVar.get() <> "link da imagem":
            self.buttonNext.config(state="active")
            self.titleFormVar.set("Crie o formulário para seu App( " +
                                  self.nameFormVar.get() + " ) aqui!")
        else:
            self.activeDeactivateTabFrameFieldForm()
            self.buttonNext.config(state="disabled")
            self.buttonSaveApp.config(state="disabled")

    def checkFormCompleted(self):
        if self.listElementThisForm:
            self.buttonSaveApp.config(state="active")
        else:
            self.buttonSaveApp.config(state="disabled")

    def actionAddElement(
        self, id_element, name_element, type_element, multline, widget_tkinter
    ):  #Adiciona elemento para renderizacao com evento de botao
        infoAppFrame = Frame(self.frameRenderElementsForm,
                             background="powderblue")
        infoAppFrame.pack(side=TOP, fill=X)
        infoAppFrame.idTemporaryElement = self.idTemporaryElement

        def removeElement(
        ):  #Funcao que remove o frame da tela e deleta o item da lista de elementos adicionados do formulario
            del self.listElementThisForm[infoAppFrame.idTemporaryElement]
            infoAppFrame.destroy()
            self.checkFormCompleted()

        Button(infoAppFrame, text="X", command=removeElement, font=("Arial", 6), takefocus=False)\
        .pack(side=RIGHT, ipadx=2, padx=2)

        nameElementVar = StringVar()
        nameElement = Entry(infoAppFrame, width=18, justify=CENTER, relief=FLAT, \
         textvariable=nameElementVar, font=("Agency FB", 14))
        nameElement.pack(side=LEFT, padx=10, fill=X)
        nameElementVar.set(name_element)
        nameElement.focus_force()
        nameElement.select_range(0, END)

        self.viewElement(infoAppFrame, widget_tkinter)

        #Salva na lista o id do elemento,nome da variavel controladora e o tipo de dado que sera inserido no banco
        self.listElementThisForm[self.idTemporaryElement] = (id_element,
                                                             nameElementVar,
                                                             type_element,
                                                             infoAppFrame)
        self.idTemporaryElement += 1
        self.checkFormCompleted()

    def viewElement(self, infoAppFrame, widget_tkinter):
        "Apenas renderiza os elementos na tela sem mais configuracoes"

        if widget_tkinter == "entry":
            inputElement = Entry(infoAppFrame,
                                 takefocus=False,
                                 state="disabled",
                                 width=40,
                                 font=self.font)
        elif widget_tkinter == "text":
            inputElement = Text(infoAppFrame,
                                takefocus=False,
                                state="disabled",
                                width=40,
                                height=4,
                                font=self.font)

        elif widget_tkinter == "spinbox":
            inputElement = Spinbox(infoAppFrame,
                                   takefocus=False,
                                   state="disabled",
                                   width=7,
                                   font=self.font)
        elif widget_tkinter == "entry-date":
            inputElement = Entry(infoAppFrame,
                                 takefocus=False,
                                 state="disabled",
                                 width=10,
                                 font=self.font)
        elif widget_tkinter == "entry-phone":
            inputElement = Entry(infoAppFrame,
                                 takefocus=False,
                                 state="disabled",
                                 width=15,
                                 font=self.font)

        inputElement.pack(side=LEFT, padx=10, pady=10)

        return inputElement

    def renderElement(self, infoAppFrame, widget_tkinter):
        "Renderiza os elementos na tela com configurações de variáveis"
        inputElementVar = None
        if widget_tkinter == "entry":
            inputElementVar = StringVar()
            inputElement = Entry(infoAppFrame,
                                 width=40,
                                 textvariable=inputElementVar,
                                 font=self.font)

        elif widget_tkinter == "entry-date":
            inputElementVar = StringVar()
            inputElement = Entry(infoAppFrame,
                                 width=10,
                                 textvariable=inputElementVar,
                                 font=self.font)
            inputElement.config(validate="key",
                                validatecommand=(self.validadeDateReg, '%i',
                                                 '%P', '%S', '%s'))

        elif widget_tkinter == "entry-phone":
            inputElementVar = StringVar()
            inputElement = Entry(infoAppFrame,
                                 width=15,
                                 textvariable=inputElementVar,
                                 font=self.font)
            inputElement.config(validate="key",
                                validatecommand=(self.validadePhoneReg, '%i',
                                                 '%P', '%S', '%s'))

        elif widget_tkinter == "spinbox":
            inputElementVar = StringVar()
            inputElement = Spinbox(infoAppFrame,
                                   width=5,
                                   textvariable=inputElementVar,
                                   font=self.font)

        elif widget_tkinter == "text":
            inputElement = Text(infoAppFrame,
                                width=40,
                                height=4,
                                font=self.font)
            inputElementVar = self.createVarByTextWidget(inputElement)

        inputElement.pack(side=LEFT, padx=10, pady=10)

        return (inputElement, inputElementVar)

    def createVarByTextWidget(self, textWidget):
        def funcSet(value):
            textWidget.delete("0.0", END)
            textWidget.insert("0.0", value)

        return type(
            "StringVar", (), {
                "set": staticmethod(funcSet),
                "get": staticmethod(lambda: textWidget.get("0.0", END))
            })

    def actionChoiseImageForm(self):
        path_origin = tkFileDialog.askopenfilename(
            initialdir="/",
            title="Selecione o Arquivo",
            filetypes=(("Arquivos jpeg", "*.jpg"), ("Arquivos png", "*.png"),
                       ("Todos arquivos", "*.*")))
        if path_origin:
            file_name = os.path.basename(path_origin)
            self.pathImageFormVar.set("images/iconsApps/" + file_name)

            path_origin = path_origin.encode("latin-1")
            path_destiny = ("images/iconsApps/" + file_name).encode("latin-1")

            print(path_origin, path_destiny, type(savePhoto))

            savePhoto(path_origin, path_destiny, (100, 100))
            image = renderPhoto(path_destiny, (100, 100))
            self.imageWidget["image"] = image
            self.imageWidget["background"] = "SystemButtonFace"

    def actionNextTabFrameFieldForm(self):
        "Salva o app na db e pula para a proxima aba"
        #self.nameFormVar.set("Eventos Mensais")
        #self.textWidget.insert("0.0", "Eventos e palestrar de tecnologia que estão perto de ocorrer no ano de 2018.")
        self.nextTabFrameFieldForm()

    def cleanInfoApp(self):
        self.nameFormVar.set("")
        self.pathImageFormVar.set("")
        self.descriptionFormVar.set("")

    def cleanFieldForm(self):
        for element in self.listElementThisForm.values():
            element[-1].destroy()

    def saveAll(self):
        nameTableFormated = self.formatNameTable(self.nameFormVar.get()) + str(
            randint(1, 1000000))
        appId = self.saveApp(nameTableFormated)  #Salva as informacoes do App
        self.saveFieldsForm(
            appId)  #Salva as ordens dos elementos no formulario
        self.saveTableForm(
            nameTableFormated)  #Salva a tabela para inserir os futuros itens

        self.cleanInfoApp()  #Limpa todos os campos preenchimentos de Info App
        self.cleanFieldForm(
        )  #Remove todos os Itens adicionados na criacao do formulario
        self.activeDeactivateTabFrameFieldForm(
        )  #Torna a aba Item invisivel novamente

    def saveApp(self, nameTableFormated):
        "Salva o app no banco de dados"

        self.db.saveRecordApp(self.nameFormVar.get(),
                              self.textWidget.get("0.0", END),
                              nameTableFormated, self.pathImageFormVar.get())

        return self.db.getIdOfLastRecordInApps()[0]

    def saveFieldsForm(self, appId):
        #(id_element, nameElementVar, type_element, inputElement)
        index_posicao = 0
        indexTemps = list(self.listElementThisForm)
        indexTemps.sort()

        for indexTemp in indexTemps:
            id_element, nameElementVar, type_element, _ = self.listElementThisForm.get(
                indexTemp)
            #salvar em saveFieldApp ---> id_formulario, id_elemento, titulo, texto_ajuda, index_posicao

            self.db.saveFieldApp(appId, id_element, str(nameElementVar.get()),
                                 "", index_posicao)
            index_posicao += 1

    def saveTableForm(self, nameTableFormated):
        try:
            fields_types = map(lambda element: self.formatNameColumn(element[1].get())+\
            " "+element[2], self.listElementThisForm.values())
            self.db.saveTableApp(nameTableFormated, fields_types)
        except Exception as error:
            self.errorReport.showAndSaveError(
                error.message, "Erro ocorreu durante salvamento da tabela")

    def createMenuSideForFieldForm(self):
        if not self.menuRightStateVar:
            self.menuRight["background"] = "red"
            self.menuRightCreateForm = Frame(self.menuRight)
            self.menuRightCreateForm.pack(side=TOP, padx=10, pady=10)

            self.buttonSaveApp = Button(self.menuRightCreateForm, command=self.saveAll, \
             font=self.font, text="Salvar App")
            self.buttonSaveApp.pack(side=TOP, ipadx=10)
        self.menuRightStateVar = True

    def hideMenuFieldForm(self):
        self.menuRightCreateForm.forget()

    def showMenuFieldForm(self):
        self.menuRightCreateForm.pack(side=TOP, padx=10, pady=10)

    def nextTabFrameFieldForm(self):
        self.activeDeactivateTabFrameFieldForm()
        self.framesNotebook.select(self.tabFrameFieldForm)

    def activeDeactivateTabFrameFieldForm(self):
        self.framesNotebook.hide(self.tabFrameFieldForm)

    def formatNameColumn(self, name_field):
        name_formated = "_".join(name_field.lower().split(" ")[0:2])
        return name_formated

    def formatNameTable(self, name_form):
        name_formated = "_".join(name_form.lower().split(" ")[0:2])
        return name_formated

    def configWidgetsGetApps(
        self
    ):  # Configura todos os widgets que pertencem ao frame que mostra todos os apps e forms
        self.frameGetApps = Frame(self.frameBody)

        self.frameAbasGetApps = Notebook(self.frameGetApps)
        self.frameAbasGetApps.pack(side=TOP, fill=BOTH)

        frameApp = Frame(self.frameAbasGetApps)
        frameInfoApp = Frame(frameApp)
        frameInfoApp.pack(side=TOP, fill=BOTH)
        frameFieldsApp = Frame(frameApp)
        frameFieldsApp.pack(side=TOP, fill=BOTH)

        for idApp, nomeApp, pathImage in self.db.getAllInfoForms(
                "id", "nome_formulario", "caminho_imagem"):
            image = renderPhoto(pathImage, (35, 35))
            self.frameAbasGetApps.add(frameApp,
                                      compound=LEFT,
                                      image=image,
                                      text=nomeApp,
                                      sticky=W + E + N + S)
            break

    # def generateTabsApps(self):
    # 	self.listTabsApps = []
    # 	for app_info in self.db.getAllInfoForms("id", "nome_formulario"):
    # 		self.listTabsApps.append(self.generateTab(  ))

    # def activeTabApp(self, name_form, description, name_table, path_image):

    # 	self.frameInfoApp
    # 	self.frameFieldsApp

    def actionOptions(self):
        if self.frameOld: self.frameOld.forget()
        self.frameOld = self.menuOptionsFunctions[self.optionVar.get()]()

    def activeOptionCreateForm(self):
        self.frameCreateForm.pack(side=LEFT, expand=True, fill=BOTH)
        self.showMenuFieldForm()
        return self.frameCreateForm

    def activeOptionGetApps(self):
        self.frameGetApps.pack(side=LEFT, expand=True, fill=BOTH)
        self.hideMenuFieldForm()
        return self.frameGetApps
Beispiel #7
0
class View(Toplevel):
    def __init__(self, model):
        self.model = model
        self.model_config = self.model.get_config()
        self.channels_num = 0
        self.channels_amount = 0

        self.root = Tk()
        self.root.resizable(width=FALSE, height=FALSE)
        self.root.title("RaaS. event_proxy configurator")
        #: self.root.iconbitmap('resourse/vit.ico')
        self.config_route = self.model.get_config_route()

        self.panelFrame = Frame(self.root, height=60)
        self.canvas = Canvas(self.root, borderwidth=0)
        self.textFrame = Frame(self.canvas, height=340, width=600)
        self.mainFrame = LabelFrame(self.root, width=200, text="Main:",
                                    height=340, relief=RAISED, borderwidth=1)
        self.chanelFrame = LabelFrame(self.root, width=370, text="Channels:",
                                      height=340, relief=RAISED, borderwidth=1)

        #: self.vsb = Scrollbar(self.root, orient="horizontal",
        #:                     command=self.canvas.xview)
        #:self.canvas.configure(xscrollcommand=self.vsb.set)
        #:self.vsb.pack(side="bottom", fill="x")
        self.canvas.pack(side="bottom", fill="both", expand=True)
        self.canvas.configure(scrollregion=self.canvas.bbox("all"))
        self.root.protocol("WM_DELETE_WINDOW", self.quit_handler)

        self.tabs = Notebook(self.root)
        self.in_channel_text = []
        self.out_port_text = []
        self.out_channel_text = []

        self.c = self.model.get_channels().keys()
        self.channels_len = len(self.model.get_channels())
        #:print self.model.get_channels()
        self.panelFrame.pack(side='top', fill='x')
        self.textFrame.pack(side='bottom', fill='both', expand=1)
        self.mainFrame.place(x=10, y=60)
        self.chanelFrame.place(x=220, y=60)
        self.tabs.place(x=230, y=80)

        x = (self.root.winfo_screenwidth() - self.root.winfo_reqwidth()) / 2
        y = (self.root.winfo_screenheight() - self.root.winfo_reqheight()) / 2
        self.root.geometry("+%d+%d" % (x-150, y-150))

        for i in range(self.channels_len):
            self.channels_num += 1
            self.channels_amount += 1

            self.f1 = Frame(self.tabs, height=290, width=350)
            self.tabs.add(self.f1, text='Channel {0}'.format(i + 1))

            self.in_channel = Label(self.f1, text="In channel")
            self.out_port = Label(self.f1, text="Out port")
            self.out_channel = Label(self.f1, text="Out channel")

            self.in_channel_text.append(Entry(self.f1, width=20, bd=3))
            self.in_channel_text[i].insert(0, self.c[i])

            self.out_port_text.append(Entry(self.f1, width=20, bd=3))
            self.out_port_text[i].insert(0, self.model.get_channels()[
                self.c[i]].out_port)

            self.out_channel_text.append(Entry(self.f1, width=20, bd=3))
            self.out_channel_text[i].insert(0, self.model.get_channels()[
                self.c[i]].out_channel)

            self.in_channel.place(x=5, y=10)
            self.in_channel_text[i].place(x=5, y=30)

            self.out_port.place(x=5, y=50)
            self.out_port_text[i].place(x=5, y=70)

            self.out_channel.place(x=5, y=90)
            self.out_channel_text[i].place(x=5, y=110)

            self.del_ch_btn = Button(self.f1, text='Delete channel {0}'.format(
                self.channels_amount),
                                     command=
                                     lambda: self.del_channel(i))
            self.del_ch_btn.bind("<Button-1>")
            self.del_ch_btn.place(x=5, y=140, width=100, height=30)

        self.server_host_label = Label(self.root, text="Server host")
        self.server_port_label = Label(self.root, text="Server port")
        self.raas_port_label = Label(self.root, text="Raas port")
        self.encoding_label = Label(self.root, text='Encoding')
        self.levenshtein_distance_label = Label(self.root,
                                                text='Levenshtein distance')
        self.window_time_label = Label(self.root, text='Window time')

        self.server_host_entity = Entry(self.root, width=20, bd=3)
        self.server_host_entity.insert(0, self.model_config['server_host'])

        self.server_port_entity = Entry(self.root, width=20, bd=3)
        self.server_port_entity.insert(0, self.model_config['server_port'])

        self.raas_port_entity = Entry(self.root, width=20, bd=3)
        self.raas_port_entity.insert(0, self.model_config['raas_port'])

        self.encoding_entry = Entry(self.root, width=20, bd=3)
        self.encoding_entry.insert(0, self.model_config['encoding'])

        self.levenshtein_distance_entry = Entry(self.root, width=20, bd=3)
        self.levenshtein_distance_entry.insert(0, self.model_config[
            'levenshtein_distance'])

        self.window_time_entry = Entry(self.root, width=20, bd=3)
        self.window_time_entry.insert(0, self.model_config['window_time'])

        self.var = IntVar()
        self.cfg_debug = self.model_config['debug']
        if self.cfg_debug == 'True':
            self.var.set(1)
        else:
            self.var.set(0)
        self.check_debug = Checkbutton(self.root, text='Debug',
                                       variable=self.var)

        self.filter_var = IntVar()
        self.cfg_use_filter = self.model_config['use_filter']
        if self.cfg_use_filter == 'True':
            self.filter_var.set(1)
        else:
            self.filter_var.set(0)
        self.check_use_filter = Checkbutton(self.root, text='Use filter',
                                            variable=self.filter_var)

        self.addBtn = Button(self.panelFrame, text='Add channel')
        self.saveBtn = Button(self.panelFrame, text='Save')
        self.quitBtn = Button(self.panelFrame, text='Quit')

        self.saveBtn.bind("<Button-1>", self.SaveFile)
        self.quitBtn.bind("<Button-1>", self.Quit)
        self.addBtn.bind("<Button-1>", self.add_channel)

        self.saveBtn.place(x=10, y=10, width=40, height=40)
        self.quitBtn.place(x=60, y=10, width=40, height=40)
        self.addBtn.place(x=220, y=10, width=80, height=40)

        self.server_host_label.place(x=20, y=80)
        self.server_host_entity.place(x=20, y=100)

        self.server_port_label.place(x=20, y=120)
        self.server_port_entity.place(x=20, y=140)

        self.raas_port_label.place(x=20, y=160)
        self.raas_port_entity.place(x=20, y=180)

        self.encoding_label.place(x=20, y=200)
        self.encoding_entry.place(x=20, y=220)

        self.check_debug.place(x=20, y=250)
        self.f = Frame(self.root, height=1, width=190, bg='grey')
        self.f.place(x=15, y=275)

        self.levenshtein_distance_label.place(x=20, y=280)
        self.levenshtein_distance_entry.place(x=20, y=300)

        self.window_time_label.place(x=20, y=320)
        self.window_time_entry.place(x=20, y=340)

        self.check_use_filter.place(x=20, y=370)

    def del_channel(self, numb):
        rwidth = self.root.winfo_width()
        rheight = self.root.winfo_height()
        if self.channels_num > 6:
            self.chanelFrame.config(width=self.chanelFrame.winfo_width() - 65)
            self.root.geometry("%dx%d" % (rwidth - 65, rheight))

        if self.channels_num == 6:
            self.chanelFrame.config(width=self.chanelFrame.winfo_width() - 20)
            self.root.geometry("%dx%d" % (rwidth - 20, rheight))

        dvar = self.tabs.tabs().index(self.tabs.select())

        self.in_channel_text.pop(dvar)
        self.out_channel_text.pop(dvar)
        self.out_port_text.pop(dvar)
        self.channels_num -= 1
        self.tabs.forget(self.tabs.select())

        tabs_list = self.tabs.tabs()
        self.root.update()

    def add_channel(self, env):
        if self.channels_num > 15:
            tkMessageBox.showerror('Error',
                                   'You can not add more than 16 channels')
            return False

        rwidth = self.root.winfo_width()
        rheight = self.root.winfo_height()

        if self.channels_num == 5:
            self.chanelFrame.config(width=self.chanelFrame.winfo_width() + 20)
            self.root.geometry("%dx%d" % (rwidth + 20, rheight))

        if self.channels_num > 5:
            self.chanelFrame.config(width=self.chanelFrame.winfo_width() + 65)
            self.root.geometry("%dx%d" % (rwidth + 65, rheight))

        self.f1 = Frame(self.tabs, height=290, width=350)
        self.tabs.add(self.f1,
                      text='Channel {0}'.format(self.channels_amount + 1))

        self.in_channel = Label(self.f1, text="In channel")
        self.out_port = Label(self.f1, text="Out port")
        self.out_channel = Label(self.f1, text="Out channel")

        self.in_channel_text.append(Entry(self.f1, width=20, bd=3))

        self.out_port_text.append(Entry(self.f1, width=20, bd=3))

        self.out_channel_text.append(Entry(self.f1, width=20, bd=3))

        self.in_channel.place(x=5, y=10)
        self.in_channel_text[self.channels_num].place(x=5, y=30)

        self.out_port.place(x=5, y=50)
        self.out_port_text[self.channels_num].place(x=5, y=70)

        self.out_channel.place(x=5, y=90)
        self.out_channel_text[self.channels_num].place(x=5, y=110)

        self.del_ch_btn = Button(self.f1, text='Delete channel {0}'.format(
            self.channels_num + 1),
                                 command=
                                 lambda: self.del_channel(self.channels_num))
        self.del_ch_btn.bind("<Button-1>")
        self.del_ch_btn.place(x=5, y=140, width=100, height=30)

        self.channels_num += 1
        self.channels_amount += 1

    def Quit(self, env):
        if tkMessageBox.askyesno('Quit', 'Whant to save config before quit?'):
            self.SaveFile(env)
        self.root.destroy()

    def quit_handler(self):
        if tkMessageBox.askyesno('Quit', 'Whant to save config before quit?'):
            self.save_handler()
        self.root.destroy()

    def validate_int(self, var, text, channel):
        if not var.isdigit():
            tkMessageBox.showerror("Error",
                                   "Error in {1}. Value of field '{0}' must be int.".format(text, channel))
            return False
        return True

    def validate_empty(self, var, text):
        if not var:
            tkMessageBox.showerror("Error",
                                   "Field {0} must be not empty.".format(text))
            return False
        return True

    def validate_channels(self):
        if not self.channels_num:
            tkMessageBox.showerror("Error",
                                   "You must add at least one channel")
            return False
        return True

    def validate_change_field(self):
        self.validating_config = self.model.get_updated_config()
        self.flag = False
        if self.server_host_entity.get() != str(self.validating_config['server_host']):
            self.flag = True
        if self.server_port_entity.get() != str(self.validating_config['server_port']):
            self.flag = True
        if self.raas_port_entity.get() != str(self.validating_config['raas_port']):
            self.flag = True
        if self.encoding_entry.get() != str(self.validating_config['encoding']):
            self.flag = True
        if str(self.levenshtein_distance_entry.get()) != str(self.validating_config['levenshtein_distance']):
            self.flag = True
        if str(self.window_time_entry.get()) != str(self.validating_config['window_time']):
            self.flag = True
        self.tmp = IntVar()
        if self.validating_config['debug'] == 'True':
            self.tmp.set(1)
        else:
            self.tmp.set(0)
        if self.tmp.get() != self.var.get():
            self.flag = True
        self.tmp_filter = IntVar()
        if self.validating_config['use_filter'] == 'True':
            self.tmp_filter.set(1)
        else:
            self.tmp_filter.set(0)
        if self.tmp_filter.get() != self.filter_var.get():
            self.flag = True
        #TODO: add validating of channels
        if self.channels_num != self.channels_amount or self.channels_len != self.channels_num:
            return True
        for i in range(self.channels_num):
            if self.in_channel_text[i].get() != str(self.c[i]):
                self.flag = True
            if self.out_port_text[i].get() != str(self.model.get_channels()[
                self.c[i]].out_port):
                self.flag = True
            if self.out_channel_text[i].get() != str(self.model.get_channels()[
                self.c[i]].out_channel):
                self.flag = True
        return self.flag

    def validate_all(self):
        #if not self.validate_change_field():
        #    return False
        if not self.validate_channels():
            return False
        if not self.validate_empty(self.server_host_entity.get(),
                                   'Server host'):
            return False
        if not self.validate_empty(self.encoding_entry.get(), 'Encoding'):
            return False
        if not self.validate_empty(self.levenshtein_distance_entry.get(),
                                   'Levenshtein distance'):
            return False
        if not self.validate_int(self.server_port_entity.get(), 'Server port',
                                 ''):
            return False
        if not self.validate_int(self.raas_port_entity.get(), 'Raas port', ''):
            return False
        if not self.validate_int(self.levenshtein_distance_entry.get(),
                                 'Levenshtein distance', ''):
            return False
        if not self.validate_int(self.window_time_entry.get(), 'Window time',
                                 ''):
            return False
        for i in range(self.channels_num):
            if not self.validate_int(self.in_channel_text[i].get(),
                                     'In channel',
                                     ' Channel {0}'.format(i + 1)):
                return False
            if not self.validate_int(self.out_port_text[i].get(), 'Out port',
                                     ' Channel {0}'.format(i + 1)):
                return False
            if not self.validate_int(self.out_channel_text[i].get(),
                                     'Out channel',
                                     ' Channel {0}'.format(i + 1)):
                return False
        return True

    def SaveFile(self, env):
        self.save_handler()

    def save_handler(self):
        if not self.validate_all():
            return False

        config = ConfigParser.RawConfigParser()
        config.add_section('Main')
        config.set('Main', 'server_host', self.server_host_entity.get())
        config.set('Main', 'server_port', self.server_port_entity.get())
        config.set('Main', 'raas_port', self.raas_port_entity.get())
        result = 'False'
        if self.var.get():
            result = 'True'
        config.set('Main', 'debug', result)
        config.set('Main', 'encoding', self.encoding_entry.get())
        config.set('Main', 'levenshtein_distance',
                   self.levenshtein_distance_entry.get())
        config.set('Main', 'window_time', self.window_time_entry.get())
        result_filter = 'False'
        if self.filter_var.get():
            result_filter = 'True'
        config.set('Main', 'use_filter', result_filter)

        for i in range(self.channels_num):
            config.add_section('Channel{0}'.format(i + 1))
            config.set('Channel{0}'.format(i + 1), 'in_channel',
                       self.in_channel_text[i].get())
            config.set('Channel{0}'.format(i + 1), 'out_port',
                       self.out_port_text[i].get())
            config.set('Channel{0}'.format(i + 1), 'out_channel',
                       self.out_channel_text[i].get())

        with open(self.config_route, 'wb') as configfile:
            config.write(configfile)
        tkMessageBox.showinfo("Info", "Successfully saved.")

    def run(self):
        self.root.mainloop()
Beispiel #8
0
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