Ejemplo n.º 1
0
 def loadplaylist(self):
     progress_dialog = tk.Toplevel()
     progress_dialog.title("Loading Playlist")
     bar = Progressbar(progress_dialog,
                       orient="horizontal",
                       length=500,
                       value=0,
                       mode="determinate")
     bar.grid(row=4, columnspan=2)
     thread = threading.Thread(target=self.threadedPlaylistLoad,
                               args=(bar, progress_dialog))
     thread.start()
Ejemplo n.º 2
0
class App(Tk):

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

        self.progress_bar = None
        self.prog_win = None

        self.working_folder = None

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

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

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

        self.show_frame(Steps)

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

    def show_progress(self, start):
        if start:
            self.prog_win = Toplevel(self.main_container, padx=8, pady=8)
            self.prog_win.transient(self)
            self.prog_win.title('Working...')
            self.prog_win.resizable(0, 0)
            self.progress_bar = Progressbar(self.prog_win,
                                            orient=HORIZONTAL,
                                            mode='indeterminate',
                                            length=250,
                                            takefocus=True)
            self.progress_bar.grid()
            self.progress_bar.start()
        else:
            self.progress_bar.stop()
            self.prog_win.destroy()
Ejemplo n.º 3
0
Archivo: biab.py Proyecto: ob/biab
 def layout_gui(self):
     master = self.master
     s = Style()
     s.theme_use('default')
     s.configure('TProgressbar', thickness=50)
     helv36 = tkFont.Font(family='Helvetica', size=36, weight='bold')
     b = Button(master, text="Quit", command=self.quit, width=10, height=2)
     b['font'] = helv36
     b.grid(row=0, column=0)
     pb = Progressbar(master,
                      orient=VERTICAL,
                      length=100,
                      mode='determinate',
                      style='TProgressbar')
     pb['value'] = 50
     pb.grid(row=0, column=1)
Ejemplo n.º 4
0
class FrProgres(LabelFrame):
    def __init__(self, title, txt):
        LabelFrame.__init__(self, text=title)
        # Bar of global progress
        Label(self, text = 'Global progress').grid(row=1, column = 0)
        self.proglob = Progressbar(self,
                                orient = HORIZONTAL,
                                max = 50,
                                length = 200,
                                mode = 'determinate')
        # Bar of attributes progress
        Label(self, text = 'Attributes progress').grid(row=3, column = 0)
        self.progatt = Progressbar(self,
                                orient = HORIZONTAL,
                                max = 50,
                                length = 200,
                                mode = 'determinate')

        # Widgets placement
        self.proglob.grid(row=2, column = 0,  sticky = N+S+W+E,
                          padx = 2, pady = 2)
        self.progatt.grid(row=4, column = 0,  sticky = N+S+W+E,
                          padx = 2, pady = 2)
Ejemplo n.º 5
0
class Application(Frame):
    def run(self):
        appid = self.var_appid.get().strip()
        if len(appid) == 0:
            tkMessageBox.showinfo(title=u"错误", message="请输入公众账号ID")
            return

        mch_id = self.var_mch_id.get().strip()
        if len(mch_id) == 0:
            tkMessageBox.showinfo(title=u"错误", message="请输入商户号")
            return

        mch_key = self.var_mch_key.get().strip()
        if len(mch_key) == 0:
            tkMessageBox.showinfo(title=u"错误", message="请输入商户密钥")
            return

        bill_date_from = self.var_bill_date_from.get().strip()
        if len(bill_date_from) == 0:
            tkMessageBox.showinfo(title=u"错误", message="请输入开始日期")
            return

        path = self.var_path.get().strip()
        if len(path) == 0:
            tkMessageBox.showinfo(title=u"错误", message="请选择输出目录")
            return

        sub_mch_id = self.txt_sub_mch_id.get(1.0, END)
        if len(sub_mch_id) > 0:
            sub_mch_ids = list(set(sub_mch_id.split()))
        else:
            sub_mch_ids = []

        # save settings
        config.save(appid, mch_id, mch_key, sub_mch_id, path)

        bill_date_to = self.var_bill_date_to.get().strip()
        if len(bill_date_to) == 0:
            bill_date_to = (datetime.now() +
                            timedelta(days=-1)).strftime("%Y%m%d")

        s = datetime.strptime(bill_date_from, "%Y%m%d")
        e = datetime.strptime(bill_date_to, "%Y%m%d")

        def work_proc(self, path, s, e, sub_mch_ids, event):

            self.btn_run.config(state='disabled')

            days = (e - s).days + 1
            max = days * (len(sub_mch_ids) if len(sub_mch_ids) > 0 else 1)

            self.prg_bar.config({'maximum': max})

            while s <= e:
                if len(sub_mch_ids) > 0:
                    for sub_mch_id in sub_mch_ids:
                        r = download_bill(mch_key, appid, mch_id, s,
                                          sub_mch_id)
                        self.save_bill(r, s, mch_id, sub_mch_id)
                        self.prg_bar.step()

                else:
                    r = download_bill(mch_key, appid, mch_id, s)
                    self.save_bill(r, s, mch_id)
                    self.prg_bar.step()

                s += timedelta(days=1)

            self.btn_run.config(state='normal')

            event.set()

        self.running = True

        work_thread = threading.Thread(target=work_proc,
                                       args=(self, path, s, e, sub_mch_ids,
                                             self.event))
        work_thread.start()

    def save_bill(self, text, bill_date, mch_id, sub_mch_id=None):
        bill_date = bill_date.strftime("%Y%m%d")
        if text.startswith('<xml>'):
            f = '%s_%s_%s.xml' % (
                bill_date, mch_id,
                sub_mch_id) if sub_mch_id else '%s_%s_.xml' % (bill_date,
                                                               mch_id)
        else:
            f = '%s_%s_%s.csv' % (
                bill_date, mch_id,
                sub_mch_id) if sub_mch_id else '%s_%s_.csv' % (bill_date,
                                                               mch_id)

        fullname = os.path.join(self.var_path.get().strip(), f)
        with open(fullname, 'wb') as csv:
            csv.write(text)

    def select_path(self):
        self.var_path.set(tkFileDialog.askdirectory())

    def createWidgets(self, settings):
        row = 0

        # 公众号ID
        self.lbl_appid = Label(self, text=u"公众帐号ID", fg='red')
        self.lbl_appid.grid(column=0, row=row, sticky=(E, N))

        self.var_appid = StringVar(self, value=settings.get('appid'))
        self.txt_appid = Entry(self,
                               textvariable=self.var_appid,
                               width=60,
                               font=self.font)
        self.txt_appid.grid(column=1, row=row, columnspan=2, sticky=(W, N))

        row += 1

        # 商户号
        self.lbl_mch_id = Label(self, text=u"商户号", fg='red')
        self.lbl_mch_id.grid(column=0, row=row, sticky=(E, N))

        self.var_mch_id = StringVar(self, value=settings.get('mch_id'))
        self.txt_mch_id = Entry(self,
                                textvariable=self.var_mch_id,
                                width=60,
                                font=self.font)
        self.txt_mch_id.grid(column=1, row=row, columnspan=2, sticky=(W, N))

        row += 1

        # 商户密钥
        self.lbl_mch_key = Label(self, text=u"商户密钥", fg='red')
        self.lbl_mch_key.grid(column=0, row=row, sticky=(E, N))

        self.var_mch_key = StringVar(self, value=settings.get('mch_key'))
        self.txt_mch_key = Entry(self,
                                 textvariable=self.var_mch_key,
                                 width=60,
                                 font=self.font)
        self.txt_mch_key.grid(column=1, row=row, columnspan=2, sticky=(W, N))

        row += 1

        # 子商户号
        self.lbl_sub_mch_id = Label(self, text=u"子商户号")
        self.lbl_sub_mch_id.grid(column=0, row=row, sticky=(E, N))

        self.txt_sub_mch_id = Text(self, height=5, width=60, font=self.font)
        if settings.get('sub_mch_id'):
            self.txt_sub_mch_id.insert(END, settings.get('sub_mch_id'))
        self.txt_sub_mch_id.grid(column=1,
                                 row=row,
                                 columnspan=2,
                                 sticky=(W, N))

        row += 1

        # 开始日期
        self.lbl_bill_date_from = Label(self, text=u"开始日期", fg='red')
        self.lbl_bill_date_from.grid(column=0, row=row, sticky=(E, N))

        self.var_bill_date_from = StringVar()
        self.var_bill_date_from.set(
            (datetime.now() - timedelta(days=1)).strftime("%Y%m%d"))
        self.txt_bill_date_from = Entry(self,
                                        width=8,
                                        textvariable=self.var_bill_date_from,
                                        font=self.font)
        self.txt_bill_date_from.grid(column=1,
                                     row=row,
                                     columnspan=2,
                                     sticky=(W, N))

        row += 1

        # 结束日期
        self.lbl_bill_date_to = Label(self, text=u"结束日期")
        self.lbl_bill_date_to.grid(column=0, row=row, sticky=(E, N))

        self.var_bill_date_to = StringVar()
        self.txt_bill_date_to = Entry(self,
                                      width=8,
                                      textvariable=self.var_bill_date_to,
                                      font=self.font)
        self.txt_bill_date_to.grid(column=1,
                                   row=row,
                                   columnspan=2,
                                   sticky=(W, N))

        row += 1

        # 输出目录
        self.lbl_path = Label(self, text=u"输出目录", fg='red')
        self.lbl_path.grid(column=0, row=row, sticky=(E, N))

        path = settings.get('path')
        self.var_path = StringVar(
            self,
            value=path if path else os.path.dirname(os.path.abspath(cur_path)))
        self.txt_path = Entry(self,
                              textvariable=self.var_path,
                              width=55,
                              font=self.font)
        self.txt_path.grid(column=1, row=row, sticky=(W, N, E))

        self.btn_select_path = Button(self,
                                      text=u"...",
                                      command=self.select_path)
        self.btn_select_path.grid(column=2, row=row, sticky=(E))

        row += 1

        # 进度条
        self.prg_bar = Progressbar(self)
        self.prg_bar.grid(column=0,
                          row=row,
                          columnspan=3,
                          sticky=(W, E),
                          pady=(10, 0))

        row += 1

        # 执行按钮
        buttonFrame = Frame(self)
        buttonFrame.grid(column=0,
                         row=row,
                         columnspan=3,
                         pady=(15, 0),
                         sticky=(W, E))

        self.btn_run = Button(buttonFrame,
                              width=20,
                              text=u"下载",
                              fg='blue',
                              command=self.run)
        self.btn_run.pack()

    def loop(self):
        if self.running and self.event.is_set():
            self.running = False
            self.event.clear()

            tkMessageBox.showinfo(title=u"成功", message="账单下载结束")
            subprocess.call('explorer "%s"' %
                            self.var_path.get().strip().replace('/', '\\'),
                            shell=True)

        self.master.after(100, self.loop)

    def __init__(self, master=None):
        Frame.__init__(self, master)

        self.font = tkFont.nametofont("TkDefaultFont")
        self.font.configure(family='MS Gothic', size=9)

        self.grid(column=0, row=0, sticky=(N, W, E, S), padx=10, pady=10)

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

        settings = config.load()
        self.createWidgets(settings)

        self.event = threading.Event()

        self.running = False
        self.loop()
Ejemplo n.º 6
0
class JobList(Frame):
    # NOTE: job_params contains information about a Job in the Joblist
    # NOTE: plot_args contains information about plotting information, which occurs after the jobs have been and the data files have been created

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

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

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

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

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

        self.reinit_variables()

        self.top_level_windows = list()

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

        self.lift()

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

        self.last_job_id = -1

        self.job_outcomes = list()

        self.plot_args = list()

        self.on_button = False

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        if not plotGraphs:
            return

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        if self.on_button:

            self.set_grid()

    def on_close(self):
        self.plot_args = list()
        self.withdraw()
        self.destroy()
Ejemplo n.º 7
0
class MPExportApp(object):
    """docstring for MPExportApp"""
    def __init__(self, master):
        super(MPExportApp, self).__init__()
        self.master = master
        self.export_type = StringVar()

        master.columnconfigure(1, weight=1)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

        self.export_thread.start()

    def export_people(self):

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

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

        parameters = {}

        if selector:
            parameters['selector'] = selector

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

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

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

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

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

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

        mixpanel.people_json_to_csv(csvfile, temp.name)
        temp.close()
        os.remove(temp.name)
        self.progress_bar.stop()
        self.progress_bar_value.set(0)
Ejemplo n.º 8
0
class TkApplicationWindow(AbstractApplicationWindow):

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def _interactive_tabula_rasa(self, *_):
        # ISSUE: Check config and ask user confirmation before existing
        self.app.ls_parser.tabula_rasa()
Ejemplo n.º 9
0
class CoilSnakeFrontend:
    PREFS_FNAME = "prefs.yml"
    def __init__(self):
        try:
            with open(self.PREFS_FNAME, 'r') as f:
                self._prefs = yaml.load(f, Loader=yaml.CSafeLoader)
        except IOError:
            self._prefs = { 'title': 0 }
    def getPrefsValue(self, key):
        try:
            return self._prefs[key]
        except KeyError:
            return ""
    def savePrefs(self):
        with open(self.PREFS_FNAME, "w") as f:
            yaml.dump(self._prefs, f, Dumper=yaml.CSafeDumper)
    def toggleTitles(self):
        self._prefs["title"] = (~(self._prefs["title"]))|1
        self.savePrefs()
    def aboutMenu(self):
        am = Toplevel(self._root)
        #Label(am, text="CoilSnake " + CoilSnake._VERSION,
        #        font=("Helvetica", 16)).pack(fill=X)
        photo = PhotoImage(file="resources/logo.gif")
        photoLabel = Label(am, image=photo)
        photoLabel.photo = photo
        photoLabel.pack(fill='both', expand=1)

        Label(am,
                text=
                (("CoilSnake %s\n"
                + "Released on %s\n\n"
                + "Created by MrTenda\n"
                + "Logo art by Reg\n\n"
                + "With help from\n"
                + "  Penguin, Reg, H.S, Michael1,\n"
                + "  Mr. Accident, AnyoneEB, Goplat, Captain Bozo,\n"
                + "  and the rest of the PK Hack community.\n"
                + "\n"
                + "Running on Python %s") % (
                    CoilSnake._VERSION,
                    CoilSnake._RELEASE_DATE, python_version())),
                anchor="w",justify="left",bg="white",borderwidth=5,
                relief=GROOVE).pack(
                        fill='both', expand=1)
        Button(am, text="Toggle Alternate Titles",
                command=self.toggleTitles).pack(fill=X)
        Button(am, text="Close", command=am.destroy).pack(fill=X)
        am.resizable(False, False)
        am.title("About")
    def setText(self, entry, str):
        entry.delete(0, END)
        entry.insert(0, str)
        entry.xview(END)
    def setEmulatorExe(self):
        self._prefs["Emulator"] = tkFileDialog.askopenfilename(
                parent=self._root,
                title="Select an Emulator Executable",
                initialfile=self.getPrefsValue("Emulator"))
        self.savePrefs()
    def setCccExe(self):
        self._prefs["CCC"] = tkFileDialog.askopenfilename(
                parent=self._root,
                title="Select the CCC Executable",
                initialfile=self.getPrefsValue("CCC"))
        self.savePrefs()
    def toggleErrorDetails(self):
        if self.getPrefsValue("ErrorDetails") == "1":
            self._prefs["ErrorDetails"] = "0"
        else:
            self._prefs["ErrorDetails"] = "1"
    def browseForRom(self, entry, save=False):
        if save:
            fname = tkFileDialog.asksaveasfilename(
                    parent=self._root, title="Select an output ROM",
                    filetypes=[('SNES ROMs','*.smc'), ('SNES ROMs','*.sfc'), ('All files','*.*')])
        else:
            fname = tkFileDialog.askopenfilename(
                    parent=self._root, title="Select a ROM",
                    filetypes=[('SNES ROMs','*.smc'), ('SNES ROMs', '*.sfc'), ('All files','*.*')])
        if len(fname) > 0:
            self.setText(entry, fname)
    def browseForProject(self, entry, save=False):
        fname = tkFileDialog.askdirectory(
                parent=self._root, title="Select a Project Directory",
                mustexist=(not save))
        self.setText(entry, fname)
    def runRom(self, entry):
        romFname = entry.get()
        if self.getPrefsValue("Emulator") == "":
            tkMessageBox.showerror(parent=self._root,
                    title="Error",
                    message="""Emulator executable not specified.
Please specify it in the Preferences menu.""")
        elif romFname != "":
            Popen([self.getPrefsValue("Emulator"), romFname])
    def resetConsole(self):
        self._console.delete(1.0, END)
        self._console.see(END)
    def doExport(self, romEntry, projEntry):
        if (romEntry.get() != "") and (projEntry.get() != ""):
            # Update the GUI
            self.resetConsole()
            self._exportB["state"] = DISABLED
            self._importB["state"] = DISABLED
            self._upgradeB["state"] = DISABLED
            # Save the fields to preferences
            self._prefs["export_rom"] = romEntry.get()
            self._prefs["export_proj"] = projEntry.get()
            self.savePrefs()

            self._progBar["value"] = 0
            print "Initializing CoilSnake\n"
            self._cs = CoilSnake.CoilSnake()
            self._progBar.step(10)
            thread = Thread(target=self._doExportHelp,
                    args=(romEntry.get(), projEntry.get(),
                        time(), ))
            thread.start()
    def _doExportHelp(self, rom, proj, startTime):
        try:
            if self._cs.romToProj(rom, proj):
                print "Done! (Took %0.2fs)" % (time()-startTime)
        except Exception as inst:
            print "\nError:", str(inst)
            if self.getPrefsValue("ErrorDetails") == "1":
                print_exc()
        self._progBar["value"] = 0
        self._exportB["state"] = NORMAL
        self._importB["state"] = NORMAL
        self._upgradeB["state"] = NORMAL
        del(self._cs)
    def doImport(self, projEntry, cleanRomEntry, romEntry):
        if self.getPrefsValue("CCC") == "":
            tkMessageBox.showerror(parent=self._root,
                    title="Error",
                    message="""CCScript Compiler executable not specified.
Please specify it in the Preferences menu.""")
        elif ((projEntry.get() != "") and (cleanRomEntry.get() != "")
                and (romEntry.get() != "")):
            # Update the GUI
            self.resetConsole()
            self._exportB["state"] = DISABLED
            self._importB["state"] = DISABLED
            self._upgradeB["state"] = DISABLED
            self._importRunB["state"] = DISABLED
            # Save the fields to preferences
            self._prefs["import_proj"] = projEntry.get()
            self._prefs["import_baserom"] = cleanRomEntry.get()
            self._prefs["import_rom"] = romEntry.get()
            self.savePrefs()

            oldRom = cleanRomEntry.get()
            newRom = romEntry.get()
            projDir = projEntry.get()
            # Reset the progress bar
            self._progBar["value"] = 0

            self._console.delete(1.0, END)
            # Run CoilSnake as usual
            print "Initializing CoilSnake\n"
            self._cs = CoilSnake.CoilSnake()
            self._progBar.step(10)
            thread = Thread(target=self._doImportHelp,
                    args=(projDir, oldRom, newRom, time()))
            thread.start()
    def _doImportHelp(self, proj, oldRom, newRom, startTime):
        try:
            if self._cs.projToRom(proj, oldRom, newRom,
                    self.getPrefsValue("CCC")):
                print "Done! (Took %0.2fs)" % (time()-startTime)
        except Exception as inst:
            print "\nError:", str(inst)
            if self.getPrefsValue("ErrorDetails") == "1":
                print_exc()
        self._progBar["value"] = 0
        self._exportB["state"] = NORMAL
        self._importB["state"] = NORMAL
        self._upgradeB["state"] = NORMAL
        self._importRunB["state"] = NORMAL
        del(self._cs)
    def doUpgrade(self, romEntry, projEntry):
        if (romEntry.get() != "") and (projEntry.get() != ""):
            # Update the GUI
            self.resetConsole()
            self._exportB["state"] = DISABLED
            self._importB["state"] = DISABLED
            self._upgradeB["state"] = DISABLED
            # Save the fields to preferences
            self._prefs["upgrade_rom"] = romEntry.get()
            self._prefs["upgrade_proj"] = projEntry.get()
            self.savePrefs()

            self._progBar["value"] = 0
            print "Initializing CoilSnake\n"
            self._cs = CoilSnake.CoilSnake()
            self._progBar.step(10)
            thread = Thread(target=self._doUpgradeHelp,
                    args=(romEntry.get(), projEntry.get(),
                        time(), ))
            thread.start()
    def _doUpgradeHelp(self, rom, proj, startTime):
        try:
            if self._cs.upgradeProject(rom, proj):
                print "Done! (Took %0.2fs)" % (time()-startTime)
        except Exception as inst:
            print "\nError:", str(inst)
            if self.getPrefsValue("ErrorDetails") == "1":
                print_exc()
        self._progBar["value"] = 0
        self._exportB["state"] = NORMAL
        self._importB["state"] = NORMAL
        self._upgradeB["state"] = NORMAL
        del(self._cs)
    def expandRom(self, ex=False):
        r = Rom.Rom('resources/romtypes.yaml')
        fname = tkFileDialog.askopenfilename(
                    parent=self._root, title="Select a ROM to expand",
                    filetypes=[('SNES ROMs','*.smc'), ('SNES ROMs','*.sfc'), ('All files','*.*')])
        if len(fname) > 0:
            r.load(fname)
            if ((not ex) and (len(r) >= 0x400000)) or (ex and (len(r) >= 0x600000)):
                tkMessageBox.showerror(parent=self._root, title="Error", message="This ROM is already expanded.")
            else:
                if ex:
                    r.expand(0x600000)
                else:
                    r.expand(0x400000)
                r.save(fname)
                del(r)
                tkMessageBox.showinfo(parent=self._root, title="Expansion Successful", message="Your ROM was expanded.")
    def expandRomEx(self):
        self.expandRom(ex=True)
    def addHeaderRom(self):
        r = Rom.Rom('resources/romtypes.yaml')
        fname = tkFileDialog.askopenfilename(
                    parent=self._root, title="Select a ROM to which to add a header",
                    filetypes=[('SNES ROMs','*.smc'), ('SNES ROMs','*.sfc'), ('All files','*.*')])
        if len(fname) > 0:
            r.load(fname)
            r.addHeader()
            r.save(fname)
            del(r)
            tkMessageBox.showinfo(parent=self._root, title="Header Addition Successful", message="Your ROM was given a header.")
    def stripHeaderRom(self):
        r = Rom.Rom('resources/romtypes.yaml')
        fname = tkFileDialog.askopenfilename(
                    parent=self._root, title="Select a ROM from which to remove a header",
                    filetypes=[('SNES ROMs','*.smc'), ('SNES ROMs','*.sfc'), ('All files','*.*')])
        if len(fname) > 0:
            r.load(fname)
            r.save(fname)
            del(r)
            tkMessageBox.showinfo(parent=self._root, title="Header Remove Successful", message="Your ROM's header was removed.")
    def main(self):
        self._root = Tk()
        if self.getPrefsValue("title") == 1:
            self._root.wm_title(getTitle() + " " + CoilSnake._VERSION)
        else:
            self._root.wm_title("CoilSnake" + " " + CoilSnake._VERSION)
            if self.getPrefsValue("title") == 0:
                self._prefs["title"] = 1
                self.savePrefs()

        menuBar = Menu(self._root)
        # Preferences pulldown menu
        prefMenu = Menu(menuBar, tearoff=0)
        prefMenu.add_command(label="CCScript Compiler Executable",
                command=self.setCccExe)
        prefMenu.add_command(label="Emulator Executable",
                command=self.setEmulatorExe)
        prefMenu.add_command(label="Toggle Error Details",
                command=self.toggleErrorDetails)
        menuBar.add_cascade(label="Preferences", menu=prefMenu)
        # Tools pulldown menu
        toolsMenu = Menu(menuBar, tearoff=0)
        toolsMenu.add_command(label="Expand ROM to 32 MBit",
                command=self.expandRom)
        toolsMenu.add_command(label="Expand ROM to 48 MBit",
                command=self.expandRomEx)
        toolsMenu.add_command(label="Add Header to ROM",
                command=self.addHeaderRom)
        toolsMenu.add_command(label="Remove Header from ROM",
                command=self.stripHeaderRom)
        menuBar.add_cascade(label="Tools", menu=toolsMenu)
        # Help menu
        helpMenu = Menu(menuBar, tearoff=0)
        helpMenu.add_command(label="About", command=self.aboutMenu)
        menuBar.add_cascade(label="Help", menu=helpMenu)

        self._root.config(menu=menuBar)


        # Left side: Export
        a=Label(self._root, text="ROM -> New Project",justify=CENTER).grid(
                row=0, column=1, columnspan=1)
        # ROM file selector
        Label(self._root, text="Input ROM:").grid(
                row=1, column=0, sticky=E)
        inRom = Entry(self._root)
        inRom.grid(row=1, column=1)
        self.setText(inRom, self.getPrefsValue("export_rom"))
        def browseTmp():
            self.browseForRom(inRom)
        def runTmp():
            self.runRom(inRom)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=1, column=2, sticky=W)
        Button(self._root, text="Run",
                command=runTmp).grid(row=1, column=3, sticky=W)
        # Project dir selector
        Label(self._root, text="Output Directory:").grid(
                row=2, column=0, sticky=E)
        outProj = Entry(self._root)
        outProj.grid(row=2, column=1)
        self.setText(outProj, self.getPrefsValue("export_proj"))
        def browseTmp():
            self.browseForProject(outProj, save=True)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=2, column=2, sticky=W)
        # Export Button
        def exportTmp():
            self.doExport(inRom, outProj)
        self._exportB = Button(self._root, text="Decompile", command=exportTmp)
        self._exportB.grid(row=3, column=1, columnspan=1, sticky=W+E)

        # Right side: Import
        Label(self._root, text="Project -> New ROM").grid(
                row=0, column=5, columnspan=1)
        # Base ROM file selector
        Label(self._root, text="Base Expanded ROM:").grid(
                row=1, column=4, sticky=E)
        baseRom = Entry(self._root)
        baseRom.grid(row=1, column=5)
        self.setText(baseRom, self.getPrefsValue("import_baserom"))
        def browseTmp():
            self.browseForRom(baseRom)
        def runTmp():
            self.runRom(baseRom)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=1, column=6)
        Button(self._root, text="Run",
                command=runTmp).grid(row=1, column=7, sticky=E+W)
        # Project dir selector
        Label(self._root, text="Project Directory:").grid(
                row=2, column=4, sticky=E)
        inProj = Entry(self._root, text=self.getPrefsValue("import_proj"))
        inProj.grid(row=2, column=5)
        self.setText(inProj, self.getPrefsValue("import_proj"))
        def browseTmp():
            self.browseForProject(inProj, save=False)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=2, column=6)
        # ROM file selector
        Label(self._root, text="Output ROM:").grid(
                row=3, column=4, sticky=E)
        outRom = Entry(self._root, text=self.getPrefsValue("import_rom"))
        outRom.grid(row=3, column=5)
        self.setText(outRom, self.getPrefsValue("import_rom"))
        def browseTmp():
            self.browseForRom(outRom, save=True)
        def runTmp():
            self.runRom(outRom)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=3, column=6)
        self._importRunB = Button(self._root, text="Run",
                command=runTmp)
        self._importRunB.grid(row=3, column=7, sticky=E+W)
        # Import Button
        def importTmp():
            self.doImport(inProj, baseRom, outRom)
        self._importB = Button(self._root, text="Compile", command=importTmp)
        self._importB.grid(row=4, column=5, columnspan=1, sticky=W+E)

        # Upgrade
        a=Label(self._root, text="Upgrade Project",justify=CENTER).grid(
                row=5, column=1, columnspan=1)
        # ROM file selector
        Label(self._root, text="Base ROM:").grid(
                row=6, column=0, sticky=E)
        upgradeRom = Entry(self._root)
        upgradeRom.grid(row=6, column=1)
        self.setText(upgradeRom, self.getPrefsValue("upgrade_rom"))
        def browseTmp():
            self.browseForRom(upgradeRom)
        def runTmp():
            self.runRom(upgradeRom)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=6, column=2, sticky=W)
        Button(self._root, text="Run",
                command=runTmp).grid(row=6, column=3, sticky=W)
        # Project dir selector
        Label(self._root, text="Project Directory:").grid(
                row=7, column=0, sticky=E)
        upgradeProj = Entry(self._root)
        upgradeProj.grid(row=7, column=1)
        self.setText(upgradeProj, self.getPrefsValue("upgrade_proj"))
        def browseTmp():
            self.browseForProject(upgradeProj, save=True)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=7, column=2, sticky=W)
        # Upgrade Button
        def upgradeTmp():
            self.doUpgrade(upgradeRom, upgradeProj)
        self._upgradeB = Button(self._root, text="Upgrade", command=upgradeTmp)
        self._upgradeB.grid(row=8, column=1, columnspan=1, sticky=W+E)

        # Progress bar
        self._progBar = Progressbar(self._root,
                orient=HORIZONTAL, mode='determinate')
        self._progBar.grid(row=9, column=0, columnspan=8, sticky=W+E)
        def updProg(dp):
            Progress.__updateProgress__(dp)
            # Note: The number of modules is hardcoded here as "19"
            self._progBar.step((90.0/19) * (dp/100.0))
        Progress.updateProgress = updProg

        # Console
        consoleFrame = Frame(self._root)
        consoleFrame.grid(row=10, column=0, columnspan=8, sticky=W+E)
        s = Scrollbar(consoleFrame)
        self._console = Text(consoleFrame, width=80, height=6)
        s.pack(side=RIGHT, fill=Y)
        self._console.pack(fill=X)
        s.config(command=self._console.yview)
        self._console.config(yscrollcommand=s.set)

        # Stdout Redirector
        class StdoutRedirector:
            def __init__(self, textArea):
                self._tA = textArea
            def write(self,str):
                if str.startswith("\b\b\b\b\b\b\b\b"):
                    self._tA.delete("end-9c", "end")
                    self._tA.insert(END, str[8:])
                else:
                    self._tA.insert(END, str)
                self._tA.see(END)
            def flush(self):
                pass
        self._consoleStdout = StdoutRedirector(self._console)
        sys.stdout = self._consoleStdout
        sys.stderr = self._consoleStdout

        self._root.mainloop()
Ejemplo n.º 10
0
class DataSyncer:
    _logger = logging.getLogger('DataSyncer')    
    def __init__(self):
        self.root = Tk()
        self.file_list = {}
        self.bag_num_thres = 5
        self.file_size = 0
        self.finish_size = 0
        self.usb_model = None
        self._lock = threading.Lock() 
        self.sync_proc = None
        self.sync_thread = None
        self.stop_thread = None
        self.status = SYNC_NOT_READY
        self.sync_dst_bag = ''
        self.sync_dst_dataset = ''
        self.usb_status = ''
        self.net_status = ''
        self.sync_status = ''
        self.cur_time = 0 

        # GUI interface
        self.frame = Frame(self.root)
        self.root.title('TuSimple Data Syncer')
        self.root.geometry('500x700')
        self.root.protocol("WM_DELETE_WINDOW", self.exit)
        self.style = Style(self.root)
        self.style.layout('text.Horizontal.TProgressbar',
                     [('Horizontal.Progessbar.trough',
                         {'children': [('Horizontal.Progressbar.pbar',
                                        {'side':'left', 'sticky':'ns'})],
                          'sticky': 'nswe'}),
                         ('Horizontal.Progressbar.label', {'side':'right', 'sticky':''})])
        self.font_size = tkFont.Font(family='Times New Roman', size=15)
        self.create_layout()
        self.gui_update()
        self.search_usb_update()
        self.search_net_update()
        DataSyncer._logger.info('GUI layout created')
        self.root.mainloop()
        
    def create_layout(self):
        # usb label 
        usb_lbl = Label(text='usb status:', height=4, width=20, font=self.font_size)
        usb_lbl.grid(column=0, row=0)

        # usb status label
        self.usb_status_lbl = Label(text=self.usb_status, height=4, width=20, font=self.font_size)
        self.usb_status_lbl.grid(column=1, row=0)

        # network label 
        net_lbl = Label(text='network status:', height=4, width=20, font=self.font_size)
        net_lbl.grid(column=0, row=1)

        # network status label
        self.net_status_lbl = Label(text=self.net_status, height=4, font=self.font_size)
        self.net_status_lbl.grid(column=1, row=1)

        # start date label
        start_lbl = Label(text='start date:', height=4, font=self.font_size)
        start_lbl.grid(column=0, row=2)
        
        # start date text
        self.start_txt = Entry(width=25, font=self.font_size) 
        self.start_txt.grid(column=1, row=2)
        
        # end date label
        end_lbl = Label(text='end date:', height=4, font=self.font_size)
        end_lbl.grid(column=0, row=3)
        
        # end date text
        self.end_txt = Entry(width=25, font=self.font_size) 
        self.end_txt.grid(column=1, row=3)

        # start button
        self.usb_button = Button(text='USB sync', height=3,  command= lambda: self.start_button_click('USB'), font=self.font_size)
        self.usb_button.grid(column=0, row=4, sticky=N+S+E+W) 

        # stop button
        self.stop_button = Button(text='stop sync', height=3, command= lambda: self.stop_button_click(), font=self.font_size)
        self.stop_button.grid(column=1, row=4, sticky=N+S+E+W) 

        # start button
        self.net_button = Button(text='Net sync', height=3, command= lambda: self.start_button_click('Net'), font=self.font_size)
        self.net_button.grid(column=0, row=5, sticky=N+S+E+W) 
        
        # start button
        self.exit_button = Button(text='exit', height=3, command=self.exit, font=self.font_size)
        self.exit_button.grid(column=1, row=5, sticky=N+S+E+W) 

        # sync status label
        self.sync_status_lbl = Label(text=self.sync_status, width=50, height=4, font=self.font_size)
        self.sync_status_lbl.grid(column=0, row=6, columnspan=2)

        # progress bar
        self.progressbar = Progressbar(orient='horizontal', length=240, mode='determinate', style='text.Horizontal.TProgressbar')

        # time estimator
        self.time_est = Label(height=3, font=self.font_size)
        
    def usb_status_set(self, text):
        self.usb_status = text

    def net_status_set(self, text):
        self.net_status = text

    def sync_status_set(self, text):
        self.sync_status = text

    def usb_status_config(self, text):
        self.usb_status_lbl.configure(text=text)

    def net_status_config(self, text):
        self.net_status_lbl.configure(text=text)

    def sync_status_config(self, text):
        self.sync_status_lbl.configure(text=text)

    def prog_status_config(self, val, maximum, text):
        self.progressbar.configure(value=val, maximum=maximum)
        self.style.configure('text.Horizontal.TProgressbar',
                             text=text)

    def start_date_get(self):
        return self.start_txt.get() 
    
    def end_date_get(self):
        return self.end_txt.get() 

    def set_status(self, status):
        with self._lock:
            self.status = status

    def get_status(self):
        with self._lock:
            return self.status

    def forget_progressbar(self):
        self.cur_time = 0 
        self.finish_size = 0 
        if len(self.progressbar.grid_info()) != 0:
            self.progressbar.grid_forget()
        if len(self.time_est.grid_info()) != 0:
            self.time_est.grid_forget()

    def search_usb_update(self):
        self.root.after(USB_FREQ, self.search_usb)

    def search_net_update(self):
        self.root.after(NET_FREQ, self.search_net)
 
    def gui_update(self):
        self.root.after(UPDATE_FREQ, self.status_update)

    def progressbar_update(self):
        self.root.after(PROG_FREQ, self.progressbar_calculator)

    def progressbar_calculator(self):
        if self.get_status() == SYNCING:
            self.progressbar.grid(column=0, row=12, columnspan=2)
            self.time_est.grid(column=0, row=13, columnspan=2)
            finish_size = 0
            for key, folders in self.file_list.iteritems():
                if 'bag' in self.file_list[key].values():
                    path = os.path.join(self.sync_dst_bag, key)
                    if os.path.exists(path):
                        try:
                            finish_size += self.get_size(path)
                        except OSError:
                            DataSyncer._logger.error('Unable to get size at {}'.format(path))
                for data_folder, data_type in folders.iteritems():
                    if data_type == 'dataset':
                        path = os.path.join(self.sync_dst_dataset, data_folder)
                        if os.path.exists(path):
                            try:
                                finish_size += self.get_size(path)
                            except OSError:
                                DataSyncer._logger.error('Unable to get size at {}'.format(path))
            # calculate percent
            val = finish_size * 1. / self.file_size * 100
            maximum = 100 
            self.prog_status_config(val, maximum, '{}/{}'.format(int(val), maximum))
            # calculate speed and estimated time
            if self.cur_time == 0:
                self.cur_time = time.time()
            else:
                t_diff = time.time() - self.cur_time 
                self.cur_time = time.time()
                s_diff = finish_size - self.finish_size
                self.finish_size = finish_size
                # speed in MB/s, t_diff in KB, needs to divide by 1024, time left in min
                sync_speed = s_diff * 1. / t_diff if t_diff != 0 else 0 
                time_left = int(math.ceil((self.file_size - self.finish_size) * 1. / sync_speed / 60) if sync_speed != 0 else 0) 
                self.time_est.configure(text='Sync speed: {:.1f}MB/s, Estimate: {}min'.format(sync_speed/1024, time_left))
            self.progressbar_update()

    def start_button_click(self, sync_type):
        if self.get_status() == SYNCING or (self.sync_thread != None and self.sync_thread.isAlive()):
            self.sync_status_set('Unable to sync: syncing in progress')  
            DataSyncer._logger.warn('Unable to sync: syncing in progress')
            return
        self.sync_thread = threading.Thread(target=self.start_sync, args=(sync_type,))
        self.sync_thread.start()

    def stop_button_click(self):
        '''
        if self.stop_thread != None and self.stop_thread.isAlive(): 
            self.sync_status_set('Unable to stop: stopping now')
            DataSyncer._logger.warn('Unable to sync: stopping now')
            return
        '''
        if self.get_status() != SYNCING:
            self.sync_status_set('Unable to stop: no syncing in progress')
            DataSyncer._logger.warn('Unable to sync: no syncing in progress')
            return
        self.stop_thread = threading.Thread(target=self.stop_sync)
        self.stop_thread.start()

    def status_update(self):
        self.usb_status_config(self.usb_status)
        self.net_status_config(self.net_status)
        self.sync_status_config(self.sync_status)
        self.gui_update()
        '''
        if self.sync_thread != None and self.sync_thread.isAlive() and self.get_status() in [SYNC_NOT_READY, SYNC_STOPPING]:
            self.sync_thread.join()
            DataSyncer._logger.info('sync thread joined!')
        if self.stop_thread != None and self.stop_thread.isAlive() and self.get_status() in [SYNC_NOT_READY]:
            self.stop_thread.join()
            DataSyncer._logger.info('stop thread joined!')
        '''

    # check if usb is availble
    def search_usb(self):
        dev_path = os.path.join('/media', USER)
        dev_name = None
        try:
            devs = os.listdir(dev_path)
            for dev in devs:
                _dev = dev.lower()
                if DEV_PRE.lower() in _dev:
                    dev_name = dev
            if dev_name:
                self.usb_status = dev 
            else:
                self.usb_status = 'No USB found'
            self.usb_model = dev_name
            if self.get_status() != SYNCING:
                self.search_usb_update()
        except OSError:
            self.usb_status = '{} USB not found'.format(DEV_PRE)
            self.usb_model = None
            
    # search if network is available
    def search_net(self):
        try:
            res = os.system("ping -c 1 " + NETWORK_IP + '> /dev/null 2>&1')
            if res == 0:
                if os.path.ismount(BAG_MOUNT_POINT):
                    self.net_status = 'Network is ready for sync'
                else:
                    self.net_status = 'Mount point unfound'
            else:
                self.net_status = 'Network is unreachable'
            if self.get_status() != SYNCING:
                self.search_net_update()
        except OSError:
            print('Unable to check the network availability')

    # check file list
    def check_file_type(self, path):
        items = os.listdir(path)
        if 'top.json' in items:
            return 'dataset'
        elif 'record.json' in items or 'log' in items:
            return 'bag'
        else:
            return None
        
    # count how many bags one folder has 
    def count_bag(self, folder):
        try:
            items = os.listdir(folder)
        except OSError:
            DataSyncer._logger.error('Unable to open file: {}'.format(folder))
            return False
        bag_num = 0
        for item in items:
            if item.endswith('.bag'):
                bag_num += 1
        return bag_num

    # add to bag list 
    def add_file_list(self, start_date, end_date):
        # empty the file list 
        self.file_list = {}
        self.file_size = 0
        # adding into file list
        try:
            dates = os.listdir(SYNC_SRC)
            for date in dates:
                if date < start_date or date > end_date:
                    continue
                self.file_list[date] = {} 
                path = os.path.join(SYNC_SRC, date)
                self.file_size += self.get_size(path)
                bag_folders = os.listdir(path) 
                for f in bag_folders:
                    f_path = os.path.join(SYNC_SRC, date, f)
                    file_type = self.check_file_type(f_path)
                    if file_type == 'dataset':
                        ds = Dataset(f_path)
                        _t = (ds.meta['ts_end'] - ds.meta['ts_begin']) * 1. / 1e9 / 60
                        if _t > self.bag_num_thres * 5:
                            self.file_list[date][f] = 'dataset'
                    elif file_type == 'bag':
                        bag_num = self.count_bag(f_path)
                        if bag_num >= self.bag_num_thres:
                            self.file_list[date][f] = 'bag'
                    else:
                        DataSyncer._logger.warn('{} is not a data folder'.format(f_path))
                if len(self.file_list[date]) == 0:
                    del(self.file_list[date])
        except OSError as e:
            DataSyncer._logger.error('Unable to open files when adding to bag list')

    # check user input format
    @staticmethod 
    def check_date_format(date_text):
        try:
            datetime.datetime.strptime(date_text, '%Y-%m-%d')
            return True
        except ValueError:
            return False

    # check if usb condition is met for sync
    def check_dst_condition(self, sync_type):
        condition = self.usb_model if sync_type == 'USB' else self.net_status
        if not condition:
            self.sync_status_set('Unable to sync: {} is not avaible'.format(sync_type))
            DataSyncer._logger.error('Unable to sync: {} is not avaible'.format(sync_type))
            return False
        return True

   # check if date is met for sync
    def check_date_condition(self):
        start_date = self.start_date_get()
        end_date = self.end_date_get()
        prompt = 'Unable to sync: '
        if start_date == '' or end_date == '':
            self.sync_status_set(prompt + 'dates null')
            DataSyncer._logger.error(prompt + 'dates null')
            return False
        elif not self.check_date_format(start_date) or not self.check_date_format(end_date):
            self.sync_status_set(prompt + 'format should be YYYY-MM-DD')
            DataSyncer._logger.error(prompt + 'format should be YYYY-MM-DD')
            return False
        elif start_date > end_date:
            self.sync_status_set(prompt + 'start date later than end date')
            DataSyncer._logger.error(prompt + 'start date later than end date')
            return False
        else:
            self.add_file_list(start_date, end_date)
            if len(self.file_list) == 0:
                self.sync_status_set(prompt + 'no bag between these dates')
                DataSyncer._logger.error(prompt + 'no bag between these dates')
                return False
            else:
                return True

    # check both conditions
    def check_sync_condition(self, sync_type):
        if self.check_dst_condition(sync_type) and self.check_date_condition():
            self.set_status(SYNC_READY)
        else:
            self.set_status(SYNC_NOT_READY)
        
    # start syncing
    def start_sync(self, sync_type):
        # check destination
        self.check_sync_condition(sync_type)
        if self.get_status() == SYNC_NOT_READY:
            return
        
        self.set_status(SYNCING)
        # generate dist path
        if sync_type == 'USB':
            self.sync_dst_bag = self.sync_dst_dataset = os.path.join('/media', USER, self.usb_model, 'import')
        else:
            self.sync_dst_bag = os.path.join(BAG_MOUNT_POINT, 'data_collection')
            self.sync_dst_dataset = DATASET_MOUNT_POINT
        try:
            folders = os.listdir(self.sync_dst_bag)
        except OSError:
            self.sync_status_set('No such path: {}'.format(self.sync_dst_bag))
            DataSyncer._logger.error('Unable to open file: {}'.format(self.sync_dst_bag))
            return

        # sanity check
        self.sync_status_set('Sanity check...please wait')
        self.sanity_check()
        DataSyncer._logger.info('Sanity check finished')
        self.progressbar_update()

        # start to sync bag one by one
        for key, f_list in self.file_list.iteritems():
            if key not in folders and 'bag' in f_list.values():
                try:
                    os.mkdir(os.path.join(self.sync_dst_bag, key))
                except OSError:
                    self.set_status(SYNC_NOT_READY)
                    DataSyncer._logger.error('Unable to create {} under {}'.format(key, self.sync_dst_bag))
                    return
            for f in f_list.keys():
                if self.get_status() == SYNCING: 
                    self.sync_status_set('Syncing: ' + f)
                    cmd = ['rsync', '--progress', '-r', '--append']
                    cmd.append(os.path.join(SYNC_SRC, key, f))
                    sync_dst = os.path.join(self.sync_dst_bag, key) if f_list[f] == 'bag' else self.sync_dst_dataset
                    cmd.append(sync_dst)
                    self.sync_proc = subprocess.Popen(cmd)
                    self.sync_proc.communicate()
                    if self.sync_proc.returncode not in [0, 20]:
                        self.sync_status_set('Syncing progress error code: {}'.format(self.sync_proc.returncode))
                        DataSyncer._logger.error('rsync progress error code: {}'.format(self.sync_proc.returncode))

        if self.get_status() == EXIT:
            DataSyncer._logger.info('exiting...')
            return

        # reset status 
        if self.get_status() == SYNCING:
            self.set_status(SYNC_NOT_READY)
            if self.sync_proc.returncode == 0:
                self.sync_status_set(sync_type + ' sync completed')
                DataSyncer._logger.info(sync_type + ' sync completed')

        # post deletion
        self.post_delete()
        # restart update
        self.search_usb_update()
        self.search_net_update()
        # forget progressbar and its related speed/time estimator
        self.forget_progressbar()
        DataSyncer._logger.info('syncing thread finished')

    # stop syncing
    def stop_sync(self):
        if self.sync_proc != None and self.sync_proc.poll() == None:
            DataSyncer._logger.info('start stopping')
            self.sync_proc.terminate()
            if self.get_status() != EXIT:
                self.set_status(SYNC_NOT_READY)
            self.sync_proc.communicate()
            DataSyncer._logger.info('returncode is: {}'.format(self.sync_proc.returncode))
            if self.sync_proc.returncode in [0, 20]:
                self.sync_status_set('stop success')
            DataSyncer._logger.info('stop syncing thread finished')

    # sanity check before syncing to avoid - matching the use of rsync --append
    def sanity_check(self):
        for key, bag_folder in self.file_list.iteritems():
            for f in bag_folder.keys():
                try:
                    # assumption: all files in destination must be included by those in source
                    sync_dst = os.path.join(self.sync_dst_bag, key, f) if bag_folder[f] == 'bag' else os.path.join(self.sync_dst_dataset, f)
                    items = os.listdir(sync_dst)
                    for item in items:
                        src_path = os.path.join(SYNC_SRC, key, f, item)
                        dst_path = os.path.join(sync_dst, item)
                        if os.path.isfile(dst_path):
                            s_size = self.get_file_size(src_path)
                            d_size = self.get_file_size(dst_path)
                        else:
                            s_size = self.get_dir_size(src_path)
                            d_size = self.get_dir_size(dst_path)
                        if s_size != d_size:
                            try:
                                os.remove(dst_path)
                            except OSError:
                                shutil.rmtree(dst_path)
                            finally:
                                DataSyncer._logger.warn('removed {}'.format(dst_path))
                except OSError:
                    DataSyncer._logger.error('Unable to do OS operation in Sanity check')
             
    # post-delete the .active bag 
    # TO-DO: include post check
    def post_delete(self):
        for key, bag_folder in self.file_list.iteritems():
            for f in bag_folder.keys():
                try:
                    if bag_folder[f] == 'bag':
                        path = os.path.join(self.sync_dst_bag, key, f)
                        items = os.listdir(path)
                        for item in items:
                            if item.endswith('.active'):
                                path = os.path.join(path, item)
                                os.remove(path)
                except OSError:
                    DataSyncer._logger.error('Unable to do OS operation in post delete')

    # wait threads finish
    def wait_thread(self):
        while True:
            if (self.sync_thread != None and self.sync_thread.isAlive()) or (self.stop_thread != None and self.stop_thread.isAlive()):
                time.sleep(0.5)
                continue
            else:
                break

    # close window exit
    def exit(self):
        self.set_status(EXIT)
        self.stop_sync()
        time.sleep(0.5)
        self.root.destroy()
        sys.exit(0)

    # get folder size in KB in general
    def get_size(self, path):
        return int(subprocess.check_output(['du', '-s', path]).split()[0])

    # calculate file's logical size
    def get_file_size(self, path):
        return int(subprocess.check_output(['ls', '-l', path]).split()[4])

    # calculate folde'r logical size
    def get_dir_size(self, path):
        size = 0
        for item in os.listdir(path):
            item_path = os.path.join(path, item)
            size += self.get_file_size(item_path) if os.path.isfile(item_path) else self.get_dir_size(item_path)
        return int(size)
Ejemplo n.º 11
0
class MiCall(tk.Frame):
    CONFIG_FILE = os.path.expanduser("~/.micall.config")
    def __init__(self, parent, *args, **kwargs):
        self.pssm = Pssm(path_to_lookup=AssetWrapper('micall/g2p/g2p_fpr.txt').path,
                         path_to_matrix=AssetWrapper('micall/g2p/g2p.matrix').path)

        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.parent = parent
        parent.report_callback_exception = self.report_callback_exception

        self.rundir = None  # path to MiSeq run folder containing data
        self.workdir = gettempdir()  # default to temp directory
        os.chdir(self.workdir)
        
        self.line_counter = LineCounter()

        self.run_info = None
        self.target_files = []

        self.button_frame = tk.Frame(self)
        self.button_frame.pack(side='top')
        self.console_frame = tk.Frame(self)
        self.console_frame.pack(side='top', fill='both', expand=True)
        
        try:
            with open(MiCall.CONFIG_FILE, 'rU') as f:
                self.config = json.load(f)
        except:
            self.config = {}

        self.nthreads = self.config.get('threads', None)
        if not self.nthreads:
            self.nthreads = int(round(cpu_count() * 0.5))
            self.config['threads'] = self.nthreads
            self.write_config()

        self.button_run = tk.Button(
            self.button_frame, text="Run", command=self.process_files
        )
        self.button_run.grid(row=0, column=1, sticky='W')

        self.progress_bar = Progressbar(self.button_frame, orient='horizontal', length=500, mode='determinate')
        self.progress_bar.grid(row=1, columnspan=5)

        scrollbar = tk.Scrollbar(self.console_frame)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.console = tk.Text(self.console_frame,
                               bg='black',
                               fg='white',
                               yscrollcommand=scrollbar.set)
        self.console.pack(side=tk.LEFT, fill=tk.BOTH)
        self.console.tag_configure('ERROR', foreground="red")
        scrollbar.config(command=self.console.yview)

        # redirect stderr to Text widget
        #sys.stderr = Redirector(self.console)

        self.write('Welcome to MiCall v{}, running with {} threads.\n'.format(
            pipeline_version,
            self.nthreads))

    def write(self, msg):
        """
        Write to Text widget, scroll to bottom, and then disable editing again.
        :param msg:
        :return:
        """
        self.console.config(state=tk.NORMAL)
        self.console.insert(tk.END, msg)
        self.console.see(tk.END)
        self.console.config(state=tk.DISABLED)
        
    def write_config(self):
        try:
            with open(MiCall.CONFIG_FILE, 'w') as f:
                json.dump(self.config, f, indent=4)
        except:
            pass # For now, we don't care if config fails

    def open_files(self):
        """
        Transfer FASTQ files into working folder, uncompress.
        :return:
        """
        fastq_files = []
        setting_name = 'run_path'
        run_path = self.config.get(setting_name, '')
        self.rundir = tkFileDialog.askdirectory(
            title='Choose a folder of FASTQ files:',
            initialdir=run_path)
        if not self.rundir:
            return fastq_files
        self.config[setting_name] = self.rundir
        self.write_config()
        self.write('Selected folder %s\n' % (self.rundir,))

        # check for presence of FASTQ files
        for root, _dirs, files in os.walk(self.rundir):
            for file in files:
                if len(fastq_re.findall(file)) > 0:
                    fastq_files.append(os.path.join(root, file))

        if fastq_files:
            self.write('Found %d FASTQ files.\n' % (len(fastq_files),))
        else:  # empty list
            self.write('Error, folder does not seem to contain any FASTQ(.gz) files!\n')
            self.rundir = None

        return fastq_files

    def callback(self, message=None, progress=None, max_progress=None):
        """ Report progress to the user.
        
        @param message: a string to write in the window, or None to not write
        @param progress: an integer value to update the progress bar
        @param max_progress: an integer value that represents completed progress
        """
        if max_progress:
            self.progress_bar['maximum'] = max_progress
        if progress is not None:
            self.progress_bar['value'] = progress
        if message is not None:
            self.write(message + '\n')

        self.parent.update()

    def make_tree(self, path):
        if not os.path.isdir(path):
            parent = os.path.dirname(path)
            self.make_tree(parent)
            os.mkdir(path)


    def process_sample(self, fastq1, progress, prefixes, image_paths, error_log):
        fastq2 = fastq1.replace('_R1_001', '_R2_001').replace('censored1',
                                                              'censored2')
        if not os.path.exists(fastq2):
            raise IOError('ERROR: Missing R2 file for {}'.format(fastq1))
        
        prefix = os.path.basename(fastq1).replace('_L001_R1_001.fastq',
                                                  '').replace('.censored1.fastq',
                                                              '')
        prefixes.append(prefix)
        output_csv = prefix + '.prelim.csv'
        self.write('Processing sample {} ({})\n'.format(prefix, progress))
        with open(output_csv, 'wb') as handle:
            prelim_map(fastq1,
                       fastq2,
                       handle,
                       nthreads=self.nthreads,
                       callback=self.callback,
                       stderr=error_log)
        
        # prepare file handles for remap stage
        with open(output_csv, 'rU') as prelim_csv, \
             open(os.path.join(self.workdir, prefix + '.remap.csv'), 'wb') as remap_csv, \
             open(os.path.join(self.workdir, prefix + '.remap_counts.csv'), 'wb') as counts_csv, \
             open(os.path.join(self.workdir, prefix + '.remap_conseq.csv'), 'wb') as conseq_csv, \
             open(os.path.join(self.workdir, prefix + '.unmapped1.fastq'), 'w') as unmapped1, \
             open(os.path.join(self.workdir, prefix + '.unmapped2.fastq'), 'w') as unmapped2:
            
            self.write('... remapping\n')
            self.parent.update()
            self.progress_bar['value'] = 0
            remap(fastq1,
                  fastq2,
                  prelim_csv,
                  remap_csv,
                  counts_csv,
                  conseq_csv,
                  unmapped1,
                  unmapped2,
                  self.workdir,
                  nthreads=self.nthreads,
                  callback=self.callback,
                  stderr=error_log)
            
        # prepare file handles for conversion from SAM format to alignment
        with open(os.path.join(self.workdir, prefix + '.remap.csv'), 'rU') as remap_csv, \
             open(os.path.join(self.workdir, prefix + '.aligned.csv'), 'wb') as aligned_csv, \
             open(os.path.join(self.workdir, prefix + '.insert.csv'), 'wb') as insert_csv, \
             open(os.path.join(self.workdir, prefix + '.failed.csv'), 'wb') as failed_csv:
            
            self.write('... converting into alignment\n')
            self.parent.update()
            sam2aln(remap_csv,
                    aligned_csv,
                    insert_csv,
                    failed_csv,
                    nthreads=self.nthreads)
            
        with open(os.path.join(self.workdir, prefix + '.aligned.csv'), 'rU') as aligned_csv, \
             open(os.path.join(self.workdir, prefix + '.nuc.csv'), 'wb') as nuc_csv, \
             open(os.path.join(self.workdir, prefix + '.amino.csv'), 'wb') as amino_csv, \
             open(os.path.join(self.workdir, prefix + '.coord_ins.csv'), 'wb') as coord_ins_csv, \
             open(os.path.join(self.workdir, prefix + '.conseq.csv'), 'wb') as conseq_csv, \
             open(os.path.join(self.workdir, prefix + '.failed_align.csv'), 'wb') as failed_align_csv, \
             open(os.path.join(self.workdir, prefix + '.nuc_variants.csv'), 'wb') as nuc_variants_csv:
            
            self.parent.update()
            aln2counts(aligned_csv,
                       nuc_csv,
                       amino_csv,
                       coord_ins_csv,
                       conseq_csv,
                       failed_align_csv,
                       nuc_variants_csv,
                       callback=self.callback)
            
        self.write('... generating coverage plots\n')
        self.parent.update()
        with open(os.path.join(self.workdir, prefix + '.amino.csv'), 'rU') as amino_csv:
            image_paths += coverage_plot(amino_csv)
        self.write('... performing g2p scoring on samples covering HIV-1 V3\n')
        self.parent.update()
        with open(os.path.join(self.workdir, prefix + '.remap.csv'), 'rU') as remap_csv, \
             open(os.path.join(self.workdir, prefix + '.nuc.csv'), 'rU') as nuc_csv, \
             open(os.path.join(self.workdir, prefix + '.g2p.csv'), 'wb') as g2p_csv:
            
            sam_g2p(pssm=self.pssm,
                    remap_csv=remap_csv,
                    nuc_csv=nuc_csv,
                    g2p_csv=g2p_csv)
    
    def build_run_summary(self, sample_count, error_count):
        summary = '{} sample'.format(sample_count)
        if sample_count != 1:
            summary += 's'
        if error_count > 0:
            summary += ' with {} error'.format(error_count)
            if error_count > 1:
                summary += 's'
        return summary

    def process_files(self):
        """
        Perform MiCall data processing on FASTQ files in working directory.
        """
        # look for FASTQ files
        fastq_files = self.open_files()
        if len(fastq_files) == 0:
            return

        savedir_setting_name = 'results_path'
        savedir = self.config.get(savedir_setting_name, '')
        savedir = tkFileDialog.askdirectory(title='Choose a folder to save results',
                                            initialdir=savedir)
        if not savedir:
            return
        self.config[savedir_setting_name] = savedir
        if os.path.exists(savedir) and os.listdir(savedir):
            self.write('Run FAILED - results folder is not empty: {}\n'.format(
                savedir))
            return
        
        workdir_purged_setting_name = 'workdir_purged'
        is_workdir_purged = self.config.get(workdir_purged_setting_name)
        if is_workdir_purged is None:
            self.config[workdir_purged_setting_name] = is_workdir_purged = True
        self.write_config()
        
        self.workdir = os.path.join(savedir, 'working')
        if os.path.exists(self.workdir):
            shutil.rmtree(self.workdir)
        self.make_tree(self.workdir)
        os.chdir(self.workdir)

        # transfer FASTQ.gz files to working folder
        self.callback(progress=0, max_progress=len(fastq_files))
        self.target_files = []
        for file_index, src in enumerate(fastq_files):
            if src.startswith(self.workdir):
                # Working file from previous run.
                continue
            self.callback(progress=file_index)
            filename = os.path.basename(src)
            prefix = filename.split('.')[0]
            dest = os.path.join(self.workdir, filename)

            if '_R1_001' in dest or 'censored1' in dest:
                self.target_files.append(dest.replace('.gz', ''))

            # neither file type is present
            if not dest.endswith('.gz'):
                shutil.copy(src, dest)
            else:
                dest = os.path.join(self.workdir, prefix+'.fastq')
                with gzip.open(src, 'rb') as zip_src, open(dest, 'w') as fastq_dest:
                    shutil.copyfileobj(zip_src, fastq_dest)
        self.callback(progress=len(fastq_files))

        # remove duplicate entries
        self.target_files = sorted(set(self.target_files))

        self.write('Transferred %d sets of FASTQ files to working directory.\n' % len(self.target_files))

        image_paths = []
        prefixes = []
        error_count = 0
        sample_count = len(self.target_files)
        run_summary = self.build_run_summary(sample_count, error_count)
        with open(os.path.join(savedir, 'micall.log'), 'w') as error_log:
            for sample_index, fastq1 in enumerate(self.target_files):
                try:
                    progress = '{} of {}'.format(sample_index+1, run_summary)
                    self.process_sample(fastq1, progress, prefixes, image_paths, error_log)
                except:
                    msg = traceback.format_exc()
                    self.write(msg)
                    error_log.write(msg)
                    error_count += 1
                    run_summary = self.build_run_summary(sample_count, error_count)

        # collate results to results folder
        for target_file, extension in files_to_collate:
            if extension is None:
                extension = '.' + target_file
            collate.collate_named_files(src_dir=self.workdir, sample_list=prefixes, extension=extension,
                                        output_path=os.path.join(savedir, target_file))

        # copy coverage plots
        imagedir = os.path.join(savedir, 'coverage')
        if not os.path.exists(imagedir):
            os.mkdir(imagedir)
        for src in image_paths:
            dest = os.path.join(imagedir, os.path.basename(src))
            shutil.move(src, dest)

        # clean up working files
        os.chdir(savedir)
        if is_workdir_purged:
            shutil.rmtree(self.workdir)

        self.write('Run complete: {}.\n'.format(run_summary))

    def report_callback_exception(self, exc_type, exc_value, exc_traceback):
        message = ''.join(traceback.format_exception(exc_type,
                                                     exc_value,
                                                     exc_traceback))
        self.write(message)
Ejemplo n.º 12
0
class RunningOperationsPage(BaseInputPage, object):
	def __init__(self, parent, controller, frame_number):
		BaseInputPage.__init__(self, parent, controller, frame_number)

		self.move_back = False
		self.need_subjects_file = False

		self.downloaded_file_path = '~/Downloads/'

		self.operation = Operations(self.controller)

		self.start = tk.Button(self, text='Start Execution', command=lambda : self.executeCommand())
		self.start.grid(row=self.starting_row, column=0, sticky='W', padx=5, pady=3)

		self.stop = tk.Button(self, text='Stop Execution', state="disabled", command=lambda : self.terminateCommand())
		self.stop.grid(row=self.starting_row, column=2, sticky='E', padx=5, pady=3)

		self.progressbar = Progressbar(self)
		self.progressbar.configure(mode='determinate', max=100)
		self.progressbar.grid(row=self.starting_row+1, column=0, columnspan=3, sticky='ew', padx=10, pady=10)

		self.controller.progressbar = self.progressbar

		self.output = Text(self, height=15, width=100)
		self.output.grid(row=self.starting_row+2, column=0, columnspan=3, sticky='ew', padx=10)
		self.hyperlink = HyperlinkManager(self.output)

		self.lf_subject_file = LabelFrame(self, text='Visual QC', padx=15, font='Helvetica 14 bold')
		self.lf_subject_file.grid(row=self.starting_row+3, column=0, columnspan=3, sticky='WE', padx=5, pady=5, ipadx=5, ipady=5)
		self.lf_subject_file.grid_rowconfigure(0, weight=1)
		self.lf_subject_file.grid_columnconfigure(4, weight=1)
		createToolTip(self.lf_subject_file, self.controller.desc.subject_file)

		self.lb_subject_file = Label(self.lf_subject_file, text="Select flagged subjects textfile", font='Helvetica 13 bold')
		self.lb_subject_file.grid(row=0, column=0, sticky="W", pady=3)

		self.select = tk.Button(self.lf_subject_file, text='Select flagged subjects file', command=lambda : self.chooseFile(self, controller, controller.selected_subjects, 'Selected Subjects', default_dir=self.downloaded_file_path))
		self.select.grid(row=1, column=0, sticky='W', padx=5, pady=3)

		lb_or = Label(self.lf_subject_file, text="-OR-", font='Helvetica 13 bold')
		lb_or.grid(row=1, column=1, sticky="W", pady=3)

		self.continue_with_all_sub = tk.Button(self.lf_subject_file, text='Continue with all subjects', command=lambda : self.continueWithAllSub())
		self.continue_with_all_sub.grid(row=1, column=2, sticky='W', padx=10, pady=3)

		self.controller.display = self.output

	def chooseFile(self, parent, controller, place_holder, message, default_dir=''):
		super(RunningOperationsPage, self).chooseFile(parent, controller, place_holder, message, default_dir=default_dir)
		self.executeCommand()

	def setFrameTitle(self):
		self.title.set('Press Start Execution')

	def onShowFrame(self, event):
		super(RunningOperationsPage, self).onShowFrame(event)
		self.resetAll()
		self.silentMode()

	def resetAll(self):
		self.resetUI()
		self.operation.resetOperations()

	def moveToNextPage(self):
		super(RunningOperationsPage, self).moveToNextPage()

	def resetClickCounter(self):
		self.move_back = False
		self.setRequiredInputError('')

	def userAgreed(self):
		if self.move_back: return True
		self.setRequiredInputError('Warning: All progress will be lost. If you wish to continue, press the button again.')
		self.move_back = True
		return False

	def moveToPrevPage(self):
		if self.userAgreed():
			self.resetAll()
			super(RunningOperationsPage, self).moveToPrevPage()

	def resetUI(self):
		self.start.config(state="normal")
		self.start.config(text='Start Execution')
		self.btn_prev.config(state="normal")
		self.btn_next.config(state="disabled")
		self.stop.config(state="disabled")
		self.output.delete('1.0', END)
		self.title.set("Press 'Start Execution' to begin")
		self.progressbar.config(value=0)
		self.need_subjects_file = False
		self.disableChildren(self.lf_subject_file.winfo_children())
		self.resetClickCounter()

	def continueWithAllSub(self):
		self.need_subjects_file = False
		self.executeCommand()

	def silentMode(self):
		if self.controller.silent:
			self.executeCommand()

	def executeCommand(self):
		if self.start['text'] == 'Continue Execution' and self.need_subjects_file and not self.controller.silent:
			selected_subjects_file_path  = self.controller.selected_subjects.get()
			new_subjects = []
			try:
				with open(selected_subjects_file_path, 'r') as f:
					new_subjects = f.readlines()
				new_subjects = [subj.strip() for subj in new_subjects]
				self.downloaded_file_path = os.path.dirname(selected_subjects_file_path)
				self.controller.selected_subjects.set('')
				self.operation.updateSubjects(new_subjects)
				self.setRequiredInputError('')
				self.need_subjects_file = False
			except Exception as e:
				self.controller.logger.error(e.message)
				self.controller.logger.error(traceback.format_exc())
				self.setRequiredInputError('Please import correct textfile downloaded from the QC page.')
				return False

		self.disableChildren(self.lf_subject_file.winfo_children())
		self.start.config(state="disabled")
		self.stop.config(state="normal")
		self.resetClickCounter()
		if self.start['text'] == 'Continue Execution':
			self.operation.incrementStage()
		self.title.set('Please wait')
		self.operation.startThreads(self)

	def terminateCommand(self):
		if self.userAgreed():
			self.stop.config(state="disabled")
			self.operation.stopThreads()

	def pause(self, operation_name='', data='', need_pause=False):
		if need_pause and not self.controller.silent:
			self.start.config(state="disabled")
			self.start.config(text='Continue Execution')
			self.title.set('Please input subject file')
			self.btn_prev.config(state="normal")
			self.stop.config(state="disabled")
			self.resetClickCounter()
			self.need_subjects_file = True
			self.enableChildren(self.lf_subject_file.winfo_children())
		if data:
			self.insertHyperLink(operation_name, data)

	def finished(self, operation_name='', data=''):
		self.start.config(text="Start Execution")
		self.start.config(state="disabled")
		self.btn_prev.config(state="normal")
		self.stop.config(state="disabled")
		self.title.set('Completed')
		self.controller.updateMessage('All operations completed. You may now close the application.')
		self.resetClickCounter()
		if data:
			self.insertHyperLink(operation_name, data)

	def insertHyperLink(self, heading, link):
		self.output.insert(END, '\n\n')
		self.output.insert(END, "QC Page for " + heading, self.hyperlink.add(partial(webbrowser.open, link)))
		self.output.insert(END, '\n\n')
		self.output.see(END)

	def toggleChildren(self):
		self.disableChildren(self.lf_subject_file.winfo_children())

	def disableChildren(self, childList):
		for child in childList:
			try:
				self.disableChildren(child.winfo_children())
			except:
				pass
			try:
				child.configure(state='disable')
			except:
				pass

	def enableChildren(self, childList):
		for child in childList:
			try:
				self.enableChildren(child.winfo_children())
			except:
				pass
			try:
				child.configure(state='normal')
			except:
				pass
Ejemplo n.º 13
0
class Metadator_GUI(Tk):
    """ Main class """
    def __init__(self):
        # basics settings
        Tk.__init__(self)               # constructor of parent graphic class
        self.focus_force()              # put the window on foreground
        self.resizable(width = False,      # freeze dimensions
                       height = False)
        self.iconbitmap('../data/images/metadator.ico')     # icon
        self.title(u'Choose your maps before and after')
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)
        # Frames
        self.frmain = LabelFrame(self, text = 'General')
        self.frprog = LabelFrame(self, text = 'Progression')

        # GUI variables
        self.nbshp = StringVar()    # number of shapefiles
        self.nbtab = StringVar()    # number of MapInfo files

        #### Main frame
        # Labels
        self.labglob = Label(self.frmain, text = u' Please paste or browse the path of your maps')
        self.labefore = Label(self, text = u'Map before: ')
        self.labafter = Label(self, text = u'Map after: ')
        self.numfiles = Label(self, textvariable = self.nbshp)
        # paths to image
        self.pathbefore = Entry(self, width = 35)
        self.pathafter = Entry(self, width = 35)
        # browse buttons
        self.browsebef = Button(self, text = 'Browse',
                                      command = self.setpathbef)
        self.browseaft = Button(self, text = 'Browse',
                                      command = self.setpathaft)

        # target folder
        self.labtarg = Label(self, text = u'Destination folder: ')
        self.target = Entry(self, width = 35)
        self.browsetarg = Button(self, text = 'Browse',
                              command = self.setpathtarg)
        # basic buttons
        self.validate = Button(self, text = 'Launch',
                                     relief= 'raised',
                                     command = self.bell)
        self.cancel = Button(self, text = 'Cancel (quit)',
                                   relief= 'groove',
                                   command = self.destroy)


        #### Progression frame
        # Progress bar
        self.prog = Progressbar(self,
                    orient=HORIZONTAL,
                    max = 50,
                    length=200,
                    mode='determinate')


        # widgets placement
        self.labglob.grid(row = 0, column = 0, columnspan = 3)
        self.labefore.grid(row = 1, column = 1, columnspan = 1)
        self.labafter.grid(row = 2, column = 1, columnspan = 1)
        self.labtarg.grid(row = 3, column = 1, columnspan = 1)
        self.pathbefore.grid(row = 1, column = 2, columnspan = 1)
        self.pathafter.grid(row = 2, column = 2, columnspan = 1)
        self.target.grid(row = 3, column = 2, columnspan = 1)
        self.browsebef.grid(row = 1, column = 3, columnspan = 1)
        self.browseaft.grid(row = 2, column = 3, columnspan = 1)
        self.browsetarg.grid(row = 3, column = 3, columnspan = 1)
        self.validate.grid(row = 4, column = 1, columnspan = 2)
        self.cancel.grid(row = 4, column = 3, columnspan = 1, sticky = "W")
        self.numfiles.grid(row=5, column= 2, columnspan = 2)
        self.prog.grid(row=6, column = 0, columnspan = 4)

        # frames placement
        self.frmain.grid(row=6)

    def setpathbef(self):
        """ ...browse and insert the path of FIRST image  """
        self.filename = askopenfilename(parent = self,
                                            title = 'Select the "before" image',
                                            filetypes = (("Images", "*.jpg;*.jpeg;*.png;*.tiff"),
                                                         ("All files", "*.*")))
        if self.filename:
            try:
                self.pathbefore.insert(0, self.filename)
            except:
                print 'no file indicated'
        # end of function
        return self.filename

    def setpathaft(self):
        """ ...browse and insert the path of SECOND image """
        self.filename = askopenfilename(parent = self,
                                        title = 'Select the "after" image',
                                        filetypes = (("Images", "*.jpg;*.jpeg;*.png;*.tiff"),
                                                     ("All files", "*.*")))
        if self.filename:
            try:
                self.pathafter.insert(0, self.filename)
            except:
                print 'no file indicated'
        # end of function
        return self.filename

    def setpathtarg(self):
        """ ...browse and insert the path of DESTINATION FOLDER """
        self.foldername = askdirectory(parent = self,
                                     title = 'Select the destination folder')
        if self.foldername:
            try:
                self.target.insert(0, self.foldername)
            except:
                print 'no folder indicated'
        # calculate number of shapefiles and MapInfo files
        self.nbshp.set(len(self.ligeofiles(self.foldername)[0]))
        self.nbtab.set(len(self.ligeofiles(self.foldername)[1]))
        # end of function
        return self.foldername

    def ligeofiles(self, foldertarget):
        u""" List shapefiles and MapInfo files (.tab, not .mid/mif) contained
        in the folders structure """
        # Lists objects
        self.lishp = [] # for shapefiles
        self.litab = [] # for MapInfo tables
        # Looping in folders structure
        for root, dirs, files in walk(foldertarget):
            for i in files:
                # Looping on files contained
                if path.splitext(path.join(root, i))[1] == u'.shp' and \
                   path.isfile(path.join(root, i)[:-4] + u'.dbf') and \
                   path.isfile(path.join(root, i)[:-4] + u'.shx') and \
                   path.isfile(path.join(root, i)[:-4] + u'.prj'):
                    # add complete path of shapefile
                    self.lishp.append(path.join(root, i))
                elif path.splitext(path.join(root, i))[1] == u'.tab' and \
                   path.isfile(path.join(root, i)[:-4] + u'.dat') and \
                   path.isfile(path.join(root, i)[:-4] + u'.map') and \
                   path.isfile(path.join(root, i)[:-4] + u'.id'):
                    # add complete path of MapInfo file
                    self.litab.append(path.join(root, i))
        # Lists ordering and tupling
        self.lishp.sort()
        self.lishp = tuple(self.lishp)
        self.litab.sort()
        self.litab = tuple(self.litab)
        # End of function
        return self.lishp, self.litab

    def listing_profils(self):
        u""" Liste les profils existants contenus dans le répertoire dédié"""
        global dico_profils, new
        for i in glob(home + r'/data/profils/*.xml'):
            dico_profils[path.splitext(path.basename(i))[0]] = i
        if new > 0:
            listing_lang()
            load_textes(deroul_lang.get())
            deroul_profils.setlist(sorted(dico_profils.keys()))
            fen_choix.update()
        # Fin de fonction
        return dico_profils
Ejemplo n.º 14
0
# -*- coding:utf-8 -*-
# User: liaochenchen
# Date: 2019/12/19

from Tkinter import *

from ttk import Progressbar

import ttk

window = Tk()

window.title("Welcome to LikeGeeks app")

window.geometry('350x200')

style = ttk.Style()

style.theme_use('default')

style.configure("black.Horizontal.TProgressbar", background='black')

bar = Progressbar(window, length=200, style='black.Horizontal.TProgressbar')

bar['value'] = 70

bar.grid(column=0, row=0)

window.mainloop()
Ejemplo n.º 15
0
class MiCall(tk.Frame):
    CONFIG_FILE = os.path.expanduser("~/.micall.config")

    def __init__(self, parent, *args, **kwargs):
        self.pssm = Pssm(
            path_to_lookup=AssetWrapper('micall/g2p/g2p_fpr.txt').path,
            path_to_matrix=AssetWrapper('micall/g2p/g2p.matrix').path)

        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.parent = parent
        parent.report_callback_exception = self.report_callback_exception

        self.rundir = None  # path to MiSeq run folder containing data
        self.workdir = gettempdir()  # default to temp directory
        os.chdir(self.workdir)

        self.line_counter = LineCounter()

        self.run_info = None
        self.target_files = []

        self.button_frame = tk.Frame(self)
        self.button_frame.pack(side='top')
        self.console_frame = tk.Frame(self)
        self.console_frame.pack(side='top', fill='both', expand=True)

        try:
            with open(MiCall.CONFIG_FILE, 'rU') as f:
                self.config = json.load(f)
        except:
            self.config = {}

        self.nthreads = self.config.get('threads', None)
        if not self.nthreads:
            self.nthreads = int(round(cpu_count() * 0.5))
            self.config['threads'] = self.nthreads
            self.write_config()

        self.button_run = tk.Button(self.button_frame,
                                    text="Run",
                                    command=self.process_files)
        self.button_run.grid(row=0, column=1, sticky='W')

        self.progress_bar = Progressbar(self.button_frame,
                                        orient='horizontal',
                                        length=500,
                                        mode='determinate')
        self.progress_bar.grid(row=1, columnspan=5)

        scrollbar = tk.Scrollbar(self.console_frame)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.console = tk.Text(self.console_frame,
                               bg='black',
                               fg='white',
                               yscrollcommand=scrollbar.set)
        self.console.pack(side=tk.LEFT, fill=tk.BOTH)
        self.console.tag_configure('ERROR', foreground="red")
        scrollbar.config(command=self.console.yview)

        # redirect stderr to Text widget
        #sys.stderr = Redirector(self.console)

        self.write('Welcome to MiCall v{}, running with {} threads.\n'.format(
            pipeline_version, self.nthreads))

    def write(self, msg):
        """
        Write to Text widget, scroll to bottom, and then disable editing again.
        :param msg:
        :return:
        """
        self.console.config(state=tk.NORMAL)
        self.console.insert(tk.END, msg)
        self.console.see(tk.END)
        self.console.config(state=tk.DISABLED)

    def write_config(self):
        try:
            with open(MiCall.CONFIG_FILE, 'w') as f:
                json.dump(self.config, f, indent=4)
        except:
            pass  # For now, we don't care if config fails

    def open_files(self):
        """
        Transfer FASTQ files into working folder, uncompress.
        :return:
        """
        fastq_files = []
        setting_name = 'run_path'
        run_path = self.config.get(setting_name, '')
        self.rundir = tkFileDialog.askdirectory(
            title='Choose a folder of FASTQ files:', initialdir=run_path)
        if not self.rundir:
            return fastq_files
        self.config[setting_name] = self.rundir
        self.write_config()
        self.write('Selected folder %s\n' % (self.rundir, ))

        # check for presence of FASTQ files
        for root, _dirs, files in os.walk(self.rundir):
            for file in files:
                if len(fastq_re.findall(file)) > 0:
                    fastq_files.append(os.path.join(root, file))

        if fastq_files:
            self.write('Found %d FASTQ files.\n' % (len(fastq_files), ))
        else:  # empty list
            self.write(
                'Error, folder does not seem to contain any FASTQ(.gz) files!\n'
            )
            self.rundir = None

        return fastq_files

    def callback(self, message=None, progress=None, max_progress=None):
        """ Report progress to the user.
        
        @param message: a string to write in the window, or None to not write
        @param progress: an integer value to update the progress bar
        @param max_progress: an integer value that represents completed progress
        """
        if max_progress:
            self.progress_bar['maximum'] = max_progress
        if progress is not None:
            self.progress_bar['value'] = progress
        if message is not None:
            self.write(message + '\n')

        self.parent.update()

    def make_tree(self, path):
        if not os.path.isdir(path):
            parent = os.path.dirname(path)
            self.make_tree(parent)
            os.mkdir(path)

    def process_sample(self, fastq1, progress, prefixes, image_paths,
                       error_log):
        fastq2 = fastq1.replace('_R1_001',
                                '_R2_001').replace('censored1', 'censored2')
        if not os.path.exists(fastq2):
            raise IOError('ERROR: Missing R2 file for {}'.format(fastq1))

        prefix = os.path.basename(fastq1).replace('_L001_R1_001.fastq',
                                                  '').replace(
                                                      '.censored1.fastq', '')
        prefixes.append(prefix)
        output_csv = prefix + '.prelim.csv'
        self.write('Processing sample {} ({})\n'.format(prefix, progress))
        with open(output_csv, 'wb') as handle:
            prelim_map(fastq1,
                       fastq2,
                       handle,
                       nthreads=self.nthreads,
                       callback=self.callback,
                       stderr=error_log)

        # prepare file handles for remap stage
        with open(output_csv, 'rU') as prelim_csv, \
             open(os.path.join(self.workdir, prefix + '.remap.csv'), 'wb') as remap_csv, \
             open(os.path.join(self.workdir, prefix + '.remap_counts.csv'), 'wb') as counts_csv, \
             open(os.path.join(self.workdir, prefix + '.remap_conseq.csv'), 'wb') as conseq_csv, \
             open(os.path.join(self.workdir, prefix + '.unmapped1.fastq'), 'w') as unmapped1, \
             open(os.path.join(self.workdir, prefix + '.unmapped2.fastq'), 'w') as unmapped2:

            self.write('... remapping\n')
            self.parent.update()
            self.progress_bar['value'] = 0
            remap(fastq1,
                  fastq2,
                  prelim_csv,
                  remap_csv,
                  counts_csv,
                  conseq_csv,
                  unmapped1,
                  unmapped2,
                  self.workdir,
                  nthreads=self.nthreads,
                  callback=self.callback,
                  stderr=error_log)

        # prepare file handles for conversion from SAM format to alignment
        with open(os.path.join(self.workdir, prefix + '.remap.csv'), 'rU') as remap_csv, \
             open(os.path.join(self.workdir, prefix + '.aligned.csv'), 'wb') as aligned_csv, \
             open(os.path.join(self.workdir, prefix + '.insert.csv'), 'wb') as insert_csv, \
             open(os.path.join(self.workdir, prefix + '.failed.csv'), 'wb') as failed_csv:

            self.write('... converting into alignment\n')
            self.parent.update()
            sam2aln(remap_csv,
                    aligned_csv,
                    insert_csv,
                    failed_csv,
                    nthreads=self.nthreads)

        with open(os.path.join(self.workdir, prefix + '.aligned.csv'), 'rU') as aligned_csv, \
             open(os.path.join(self.workdir, prefix + '.nuc.csv'), 'wb') as nuc_csv, \
             open(os.path.join(self.workdir, prefix + '.amino.csv'), 'wb') as amino_csv, \
             open(os.path.join(self.workdir, prefix + '.coord_ins.csv'), 'wb') as coord_ins_csv, \
             open(os.path.join(self.workdir, prefix + '.conseq.csv'), 'wb') as conseq_csv, \
             open(os.path.join(self.workdir, prefix + '.failed_align.csv'), 'wb') as failed_align_csv, \
             open(os.path.join(self.workdir, prefix + '.nuc_variants.csv'), 'wb') as nuc_variants_csv:

            self.parent.update()
            aln2counts(aligned_csv,
                       nuc_csv,
                       amino_csv,
                       coord_ins_csv,
                       conseq_csv,
                       failed_align_csv,
                       nuc_variants_csv,
                       callback=self.callback)

        self.write('... generating coverage plots\n')
        self.parent.update()
        with open(os.path.join(self.workdir, prefix + '.amino.csv'),
                  'rU') as amino_csv:
            image_paths += coverage_plot(amino_csv)
        self.write('... performing g2p scoring on samples covering HIV-1 V3\n')
        self.parent.update()
        with open(os.path.join(self.workdir, prefix + '.remap.csv'), 'rU') as remap_csv, \
             open(os.path.join(self.workdir, prefix + '.nuc.csv'), 'rU') as nuc_csv, \
             open(os.path.join(self.workdir, prefix + '.g2p.csv'), 'wb') as g2p_csv:

            sam_g2p(pssm=self.pssm,
                    remap_csv=remap_csv,
                    nuc_csv=nuc_csv,
                    g2p_csv=g2p_csv)

    def build_run_summary(self, sample_count, error_count):
        summary = '{} sample'.format(sample_count)
        if sample_count != 1:
            summary += 's'
        if error_count > 0:
            summary += ' with {} error'.format(error_count)
            if error_count > 1:
                summary += 's'
        return summary

    def process_files(self):
        """
        Perform MiCall data processing on FASTQ files in working directory.
        """
        # look for FASTQ files
        fastq_files = self.open_files()
        if len(fastq_files) == 0:
            return

        savedir_setting_name = 'results_path'
        savedir = self.config.get(savedir_setting_name, '')
        savedir = tkFileDialog.askdirectory(
            title='Choose a folder to save results', initialdir=savedir)
        if not savedir:
            return
        self.config[savedir_setting_name] = savedir
        if os.path.exists(savedir) and os.listdir(savedir):
            self.write('Run FAILED - results folder is not empty: {}\n'.format(
                savedir))
            return

        workdir_purged_setting_name = 'workdir_purged'
        is_workdir_purged = self.config.get(workdir_purged_setting_name)
        if is_workdir_purged is None:
            self.config[workdir_purged_setting_name] = is_workdir_purged = True
        self.write_config()

        self.workdir = os.path.join(savedir, 'working')
        if os.path.exists(self.workdir):
            shutil.rmtree(self.workdir)
        self.make_tree(self.workdir)
        os.chdir(self.workdir)

        # transfer FASTQ.gz files to working folder
        self.callback(progress=0, max_progress=len(fastq_files))
        self.target_files = []
        for file_index, src in enumerate(fastq_files):
            if src.startswith(self.workdir):
                # Working file from previous run.
                continue
            self.callback(progress=file_index)
            filename = os.path.basename(src)
            prefix = filename.split('.')[0]
            dest = os.path.join(self.workdir, filename)

            if '_R1_001' in dest or 'censored1' in dest:
                self.target_files.append(dest.replace('.gz', ''))

            # neither file type is present
            if not dest.endswith('.gz'):
                shutil.copy(src, dest)
            else:
                dest = os.path.join(self.workdir, prefix + '.fastq')
                with gzip.open(src, 'rb') as zip_src, open(dest,
                                                           'w') as fastq_dest:
                    shutil.copyfileobj(zip_src, fastq_dest)
        self.callback(progress=len(fastq_files))

        # remove duplicate entries
        self.target_files = sorted(set(self.target_files))

        self.write(
            'Transferred %d sets of FASTQ files to working directory.\n' %
            len(self.target_files))

        image_paths = []
        prefixes = []
        error_count = 0
        sample_count = len(self.target_files)
        run_summary = self.build_run_summary(sample_count, error_count)
        with open(os.path.join(savedir, 'micall.log'), 'w') as error_log:
            for sample_index, fastq1 in enumerate(self.target_files):
                try:
                    progress = '{} of {}'.format(sample_index + 1, run_summary)
                    self.process_sample(fastq1, progress, prefixes,
                                        image_paths, error_log)
                except:
                    msg = traceback.format_exc()
                    self.write(msg)
                    error_log.write(msg)
                    error_count += 1
                    run_summary = self.build_run_summary(
                        sample_count, error_count)

        # collate results to results folder
        for target_file, extension in files_to_collate:
            if extension is None:
                extension = '.' + target_file
            collate.collate_named_files(src_dir=self.workdir,
                                        sample_list=prefixes,
                                        extension=extension,
                                        output_path=os.path.join(
                                            savedir, target_file))

        # copy coverage plots
        imagedir = os.path.join(savedir, 'coverage')
        if not os.path.exists(imagedir):
            os.mkdir(imagedir)
        for src in image_paths:
            dest = os.path.join(imagedir, os.path.basename(src))
            shutil.move(src, dest)

        # clean up working files
        os.chdir(savedir)
        if is_workdir_purged:
            shutil.rmtree(self.workdir)

        self.write('Run complete: {}.\n'.format(run_summary))

    def report_callback_exception(self, exc_type, exc_value, exc_traceback):
        message = ''.join(
            traceback.format_exception(exc_type, exc_value, exc_traceback))
        self.write(message)
class LowerScrollingFrame(ScrollableFrame):
	#self.mangaFrame ==> the MangaFrame that we get our image and updates from
	def __init__(self,parent,*args,**kwargs):
		self.parent=parent
		ScrollableFrame.__init__(self,self.parent,*args,**kwargs)
		self.disableDynamicRows() #really annoying to have it on
		self.__body()
		self.mangaFrame=None
		self.imageNotFound=self.image=ImageTk.PhotoImage(Image.open("Image-not-found.gif"))
		self.image=self.imageNotFound
		self.redraw()

	def __body(self):
		self.BUTTONS={}
		self.BUTTONS["Update"]=Button(self,text="Update",command=self.updateManga)
		self.BUTTONS["CheckForUpdates"]=Button(self,text="Check Updates",command=self.updateManga_check)
		self.BUTTONS["Delete"]=Button(self,text="Delete",command=self.deleteManga)

		self.BUTTONS["Update"].grid(row=0,column=0,sticky=N+S+E+W)
		self.BUTTONS["CheckForUpdates"].grid(row=1,column=0,sticky='nsew')
		self.BUTTONS["Delete"].grid(row=2,column=0,sticky=N+S+E+W)

		self.LABELS={}
		self.LABELS["Status"]=Label(self,text="Status:\nUnknown")
		self.LABELS["ChapterCount"]=Label(self,text="Chapters:\nUnknown")
		self.LABELS["Updates"]=Label(self,text="Updates:\nUnknown")
		self.LABELS["Summary"]=LabelResizing(self,text="Summary:\n")
		self.LABELS["Picture"]=Label(self,image=None)
		self.LABELS["UpdatingStatus"]=Label(self,text="")

		self.LABELS["Status"].grid(row=0,column=1)
		self.LABELS["ChapterCount"].grid(row=1,column=1)
		self.LABELS["Updates"].grid(row=2,column=1)
		self.LABELS["Summary"].grid(row=3,column=0,sticky='nwe')
		self.LABELS["Picture"].grid(row=0,column=2,rowspan=5)
		self.LABELS["UpdatingStatus"].grid(row=5,column=0,columnspan=3)

		self.PROGRESSBAR=Progressbar(self)
		self.PROGRESSBAR.grid(row=6,column=0,columnspan=3,sticky=E+W)

		self.bindChidrenScrolling()
		self.grid_columnconfigure(0,weight=1)
		self.grid_columnconfigure(1,weight=2)

	def setManga(self,MangaFrame):
		#this should be a manga frame
		self.mangaFrame=MangaFrame
		self.image=self.mangaFrame.getImage()
		self.redraw()
	def redraw(self,*args):
		try:
			if self.mangaFrame.inProgress==False:self.BUTTONS["Update"].config(text="Update")
			else:self.BUTTONS["Update"].config(text="Cancel")
			self.LABELS["ChapterCount"].config(text="{} Chapters".format(self.mangaFrame.numberOfChapters()))
			self.LABELS["Updates"].config(text="{} Updates".format(self.mangaFrame.numberOfUpdates()))
			self.progressSet(self.mangaFrame.getProgress())
			self.LABELS["UpdatingStatus"].config(text=self.mangaFrame.getStatus())
			self.LABELS["Summary"].config(text="Summary: "+self.mangaFrame.getSummary())
		except Exception as e:
			print e
			self.LABELS["Status"].config(text="Status:\nUnknown")
			self.LABELS["ChapterCount"].config(text="Chapters:\nUnknown")
			self.LABELS["Updates"].config(text="Updates:\nUnknown")
			self.progressReset()
			self.LABELS["UpdatingStatus"].config(text="")
			self.LABELS["Summary"].config(text="Summary:\nUnknown")
		self.LABELS["Picture"].config(image=self.image)

	def progressSet(self,value):
		self.PROGRESSBAR.config(value=value)
	def progressStep(self,value):
		self.PROGRESSBAR.step(value)
	def progressReset(self):
		self.PROGRESSBAR.config(value=0)

	def updateManga(self):
		if not self.mangaFrame.inProgress:self.mangaFrame.updateManga(self)
		else: self.mangaFrame.cancelUpdate()
		self.redraw()
	def updateManga_check(self):
		self.mangaFrame.updateManga_check() #look to see if there are any updates
		self.redraw() #change the number we have for the number of updates
	def deleteManga(self):
		rmtree("files/"+self.mangaFrame.getName())
		self.parent.populateLibrary()
		self.mangaFrame=None
		self.image=self.imageNotFound
		self.redraw()
Ejemplo n.º 17
0
class CoilSnakeFrontend:
    PREFS_FNAME = "prefs.yml"
    def __init__(self):
        try:
            with open(self.PREFS_FNAME, 'r') as f:
                self._prefs = yaml.load(f, Loader=yaml.CSafeLoader)
        except IOError:
            self._prefs = {
                    'Emulator': "",
                    'CCC': "",
                    'import_proj': "",
                    'import_baserom': "",
                    'import_rom': "",
                    'export_proj': "",
                    'export_rom': "",
                    'title': 0,
                    }
    def savePrefs(self):
        with open(self.PREFS_FNAME, "w") as f:
            yaml.dump(self._prefs, f, Dumper=yaml.CSafeDumper)
    def toggleTitles(self):
        self._prefs["title"] = (~(self._prefs["title"]))|1
        self.savePrefs()
    def aboutMenu(self):
        am = Toplevel(self._root)
        Label(am, text="CoilSnake " + _version,
                font=("Helvetica", 16)).pack(fill=X)
        Label(am,
                text=
                "Released on " + _releaseDate + ".\n\n"
                + "Created by MrTenda.\n\n"
                + "With help from\n"
                + "  Penguin, Mr. Accident, Goplat,\n"
                + "  AnyoneEB, Captain Bozo,\n"
                + "  and the rest of the PK Hack community.",
                anchor="w",justify="left",bg="white",borderwidth=5,
                relief=GROOVE).pack(
                        fill='both', expand=1)
        Button(am, text="Toggle Alternate Titles",
                command=self.toggleTitles).pack(fill=X)
        Button(am, text="Close", command=am.destroy).pack(fill=X)
        am.resizable(False, False)
        am.title("About")
    def setText(self, entry, str):
        entry.delete(0, END)
        entry.insert(0, str)
        entry.xview(END)
    def setEmulatorExe(self):
        self._prefs["Emulator"] = tkFileDialog.askopenfilename(
                parent=self._root,
                title="Select an Emulator Executable",
                initialfile=self._prefs["Emulator"])
        self.savePrefs()
    def setCccExe(self):
        self._prefs["CCC"] = tkFileDialog.askopenfilename(
                parent=self._root,
                title="Select the CCC Executable",
                initialfile=self._prefs["CCC"])
        self.savePrefs()
    def browseForRom(self, entry, save=False):
        if save:
            fname = tkFileDialog.asksaveasfilename(
                    parent=self._root, title="Select an output ROM",
                    filetypes=[('SNES ROMs','*.smc'), ('All files','*.*')])
        else:
            fname = tkFileDialog.askopenfilename(
                    parent=self._root, title="Select a ROM",
                    filetypes=[('SNES ROMs','*.smc'), ('All files','*.*')])
        self.setText(entry, fname)
    def browseForProject(self, entry, save=False):
        fname = tkFileDialog.askdirectory(
                parent=self._root, title="Select a Project Directory",
                mustexist=(not save))
        self.setText(entry, fname)
    def runRom(self, entry):
        romFname = entry.get()
        if self._prefs["Emulator"] == "":
            tkMessageBox.showerror(parent=self._root,
                    title="Error",
                    message="""Emulator executable not specified.
Please specify it in the Preferences menu.""")
        elif romFname != "":
            Popen([self._prefs["Emulator"], romFname])
    def resetConsole(self):
        self._console.delete(1.0, END)
        self._console.see(END)
    def doExport(self, romEntry, projEntry):
        if (romEntry.get() != "") and (projEntry.get() != ""):
            # Update the GUI
            self.resetConsole()
            self._exportB["state"] = DISABLED
            self._importB["state"] = DISABLED
            # Save the fields to preferences
            self._prefs["export_rom"] = romEntry.get()
            self._prefs["export_proj"] = projEntry.get()
            self.savePrefs()

            self._progBar["value"] = 0
            print "Initializing CoilSnake\n"
            self._cs = CoilSnake.CoilSnake()
            self._progBar.step(10)
            thread = Thread(target=self._doExportHelp,
                    args=(romEntry.get(), projEntry.get()+"/Project.snake",
                        time(), ))
            thread.start()
    def _doExportHelp(self, rom, proj, startTime):
        try:
            self._cs.romToProj(rom, proj)
            print "Done! (Took %0.2fs)" % (time()-startTime)
        except Exception as inst:
            print "\nError! Something went wrong:"
            print_exc()
        self._progBar["value"] = 0
        self._exportB["state"] = NORMAL
        self._importB["state"] = NORMAL
        del(self._cs)
    def doImport(self, projEntry, cleanRomEntry, romEntry):
        if self._prefs["CCC"] == "":
            tkMessageBox.showerror(parent=self._root,
                    title="Error",
                    message="""CCScript Compiler executable not specified.
Please specify it in the Preferences menu.""")
        elif ((projEntry.get() != "") and (cleanRomEntry.get() != "")
                and (romEntry.get() != "")):
            # Update the GUI
            self.resetConsole()
            self._exportB["state"] = DISABLED
            self._importB["state"] = DISABLED
            self._importRunB["state"] = DISABLED
            # Save the fields to preferences
            self._prefs["import_proj"] = projEntry.get()
            self._prefs["import_baserom"] = cleanRomEntry.get()
            self._prefs["import_rom"] = romEntry.get()
            self.savePrefs()

            oldRom = cleanRomEntry.get()
            newRom = romEntry.get()
            projDir = projEntry.get()
            # Reset the progress bar
            self._progBar["value"] = 0
            # Copy the clean rom to the output rom
            self._console.delete(1.0, END)
            print "Copying ROM"
            copyfile(oldRom, newRom)
            self._progBar.step(2)
            # Get a list of the script filenames in projDir/ccscript
            scriptFnames = [ projDir + "/ccscript/" + x 
                    for x in listdir(projDir + "/ccscript")
                    if x.endswith('.ccs') ]
            # Compile scripts using the CCC, and put the data at $F00000
            print "Calling external CCScript Compiler"
            process = Popen(
                    [self._prefs["CCC"], "-n", "-o", newRom, "-s", "F00000",
                        "--summary", projDir + "/ccscript/summary.txt"] +
                    scriptFnames)
            process.wait()
            self._progBar.step(4)
            # Run CoilSnake as usual
            print "Initializing CoilSnake\n"
            self._cs = CoilSnake.CoilSnake()
            self._progBar.step(4)
            thread = Thread(target=self._doImportHelp,
                    args=(projDir+"/Project.snake", newRom, time()))
            thread.start()
    def _doImportHelp(self, proj, rom, startTime):
        try:
            self._cs.projToRom(proj, rom, rom)
            print "Done! (Took %0.2fs)" % (time()-startTime)
        except Exception as inst:
            print "\nError! Something went wrong:"
            print_exc()
        self._progBar["value"] = 0
        self._exportB["state"] = NORMAL
        self._importB["state"] = NORMAL
        self._importRunB["state"] = NORMAL
        del(self._cs)
    def expandRom(self, ex=False):
        r = Rom.Rom('romtypes.yaml')
        fname = tkFileDialog.askopenfilename(
                    parent=self._root, title="Select a ROM to expand",
                    filetypes=[('SNES ROMs','*.smc'), ('All files','*.*')])
        r.load(fname)
        EbRomExpander.expandRom(r, ex)
        r.save(fname)
        del(r)
        tkMessageBox.showinfo("Expansion Successful",
                "Your ROM was expanded.")
    def expandRomEx(self):
        self.expandRom(ex=True)
    def main(self):
        self._root = Tk()
        if self._prefs["title"] == 1:
            self._root.wm_title(getTitle() + " " + _version)
        else:
            self._root.wm_title("CoilSnake" + " " + _version)
            if self._prefs["title"] == 0:
                self._prefs["title"] = 1
                self.savePrefs()

        menuBar = Menu(self._root)
        # Preferences pulldown menu
        prefMenu = Menu(menuBar, tearoff=0)
        prefMenu.add_command(label="CCScript Compiler Executable",
                command=self.setCccExe)
        prefMenu.add_command(label="Emulator Executable",
                command=self.setEmulatorExe)
        menuBar.add_cascade(label="Preferences", menu=prefMenu)
        # Tools pulldown menu
        toolsMenu = Menu(menuBar, tearoff=0)
        toolsMenu.add_command(label="Expand ROM to 32 MBit",
                command=self.expandRom)
        toolsMenu.add_command(label="Expand ROM to 48 MBit",
                command=self.expandRomEx)
        menuBar.add_cascade(label="Tools", menu=toolsMenu)
        # Help menu
        helpMenu = Menu(menuBar, tearoff=0)
        helpMenu.add_command(label="About", command=self.aboutMenu)
        menuBar.add_cascade(label="Help", menu=helpMenu)

        self._root.config(menu=menuBar)


        # Left side: Export
        a=Label(self._root, text="ROM -> New Project",justify=CENTER).grid(
                row=0, column=1, columnspan=1)
        # ROM file selector
        Label(self._root, text="Input ROM:").grid(
                row=1, column=0, sticky=E)
        inRom = Entry(self._root)
        inRom.grid(row=1, column=1)
        self.setText(inRom, self._prefs["export_rom"])
        def browseTmp():
            self.browseForRom(inRom)
        def runTmp():
            self.runRom(inRom)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=1, column=2, sticky=W)
        Button(self._root, text="Run",
                command=runTmp).grid(row=1, column=3, sticky=W)
        # Project dir selector
        Label(self._root, text="Output Directory:").grid(
                row=2, column=0, sticky=E)
        outProj = Entry(self._root)
        outProj.grid(row=2, column=1)
        self.setText(outProj, self._prefs["export_proj"])
        def browseTmp():
            self.browseForProject(outProj, save=True)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=2, column=2, sticky=W)
        # Export Button
        def exportTmp():
            self.doExport(inRom, outProj)
        self._exportB = Button(self._root, text="Export", command=exportTmp)
        self._exportB.grid(row=4, column=1, columnspan=1, sticky=W+E)

        # Right side: Import
        Label(self._root, text="Project -> New ROM").grid(
                row=0, column=5, columnspan=1)
        # Base ROM file selector
        Label(self._root, text="Base Expanded ROM:").grid(
                row=1, column=4, sticky=E)
        baseRom = Entry(self._root)
        baseRom.grid(row=1, column=5)
        self.setText(baseRom, self._prefs["import_baserom"])
        def browseTmp():
            self.browseForRom(baseRom)
        def runTmp():
            self.runRom(baseRom)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=1, column=6)
        Button(self._root, text="Run",
                command=runTmp).grid(row=1, column=7, sticky=W)
        # Project dir selector
        Label(self._root, text="Project Directory:").grid(
                row=2, column=4, sticky=E)
        inProj = Entry(self._root, text=self._prefs["import_proj"])
        inProj.grid(row=2, column=5)
        self.setText(inProj, self._prefs["import_proj"])
        def browseTmp():
            self.browseForProject(inProj, save=False)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=2, column=6)
        # ROM file selector
        Label(self._root, text="Output ROM:").grid(
                row=3, column=4, sticky=E)
        outRom = Entry(self._root, text=self._prefs["import_rom"])
        outRom.grid(row=3, column=5)
        self.setText(outRom, self._prefs["import_rom"])
        def browseTmp():
            self.browseForRom(outRom, save=True)
        def runTmp():
            self.runRom(outRom)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=3, column=6)
        self._importRunB = Button(self._root, text="Run",
                command=runTmp)
        self._importRunB.grid(row=3, column=7, sticky=W)
        # Import Button
        def importTmp():
            self.doImport(inProj, baseRom, outRom)
        self._importB = Button(self._root, text="Import", command=importTmp)
        self._importB.grid(row=4, column=5, columnspan=1, sticky=W+E)

        # Progress bar
        self._progBar = Progressbar(self._root,
                orient=HORIZONTAL, mode='determinate')
        self._progBar.grid(row=5, column=0, columnspan=8, sticky=W+E)
        def updProg(dp):
            Progress.__updateProgress__(dp)
            # Note: The number of modules is hardcoded here as "12"
            self._progBar.step((90.0/12) * (dp/100.0))
        Progress.updateProgress = updProg

        # Console
        consoleFrame = Frame(self._root)
        consoleFrame.grid(row=6, column=0, columnspan=8, sticky=W+E)
        s = Scrollbar(consoleFrame)
        self._console = Text(consoleFrame, width=80, height=6)
        s.pack(side=RIGHT, fill=Y)
        self._console.pack(fill=X)
        s.config(command=self._console.yview)
        self._console.config(yscrollcommand=s.set)

        # Stdout Redirector
        class StdoutRedirector:
            def __init__(self, textArea):
                self._tA = textArea
            def write(self,str):
                if str.startswith("\b\b\b\b\b\b\b\b"):
                    self._tA.delete("end-9c", "end")
                    self._tA.insert(END, str[8:])
                else:
                    self._tA.insert(END, str)
                self._tA.see(END)
            def flush(self):
                pass
        self._consoleStdout = StdoutRedirector(self._console)
        sys.stdout = self._consoleStdout
        sys.stderr = self._consoleStdout

        self._root.mainloop()
Ejemplo n.º 18
0
class iface():
        def __init__(self):
            
            root.title("MuBlas")
            
            self.lab1 = Label(root, text="Music directory")
            self.lab1.grid(row = 0, column = 0)
            
            self.music_entry = Entry(root,width=50,bd=1)
            self.music_entry.grid(row = 1, column = 0)
            
            self.m_dir_but = Button(root)
            self.m_dir_but["text"] = "Choose directory"
            self.m_dir_but.grid(row = 1, column = 1)
            self.m_dir_but.bind("<Button-1>", self.ask_mus_dir)
            
            self.lab3 = Label(root, text="Size in MBytes")
            self.lab3.grid(row = 2, column = 0)
            
            self.size_entry = Entry(root,width=5,bd=1)
            self.size_entry.grid(row = 2, column = 1)
            
            self.lab2 = Label(root, text="Destination directory")
            self.lab2.grid(row = 3, column = 0)
            
            self.destination_entry = Entry(root,width=50,bd=1)
            self.destination_entry.grid(row = 4, column = 0)
            
            self.dest_dir_but = Button(root)
            self.dest_dir_but["text"] = "Choose directory"
            self.dest_dir_but.grid(row = 4, column = 1)
            self.dest_dir_but.bind("<Button-1>", self.ask_out_dir)
            
            self.process_but = Button(root)
            self.process_but["text"] = "Run"
            self.process_but.grid(row = 6, column = 0)
            self.process_but.bind("<Button-1>", self.start)
            
            self.exit_but = Button(root)
            self.exit_but["text"] = "Exit"
            self.exit_but.grid(row = 6, column = 1)
            self.exit_but.bind("<Button-1>", self.exit_app)
            
            self.pr_bar = Progressbar(root, mode='indeterminate')
            self.pr_bar.grid(row = 5, column = 0, sticky = "we", columnspan = 2)
            
            #self.pr_bar.start()
            

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

        def ask_out_dir(self, event):
            dirname = tkFileDialog.askdirectory(parent = root,initialdir="/",title='Please select a directory')
            self.destination_entry.delete(0, END)
            self.destination_entry.insert(0, dirname)
            
        def start(self, event):
            self.pr_bar.start()
            self.process_but["state"] = DISABLED
            
            m_dir = self.music_entry.get()
            d_dir = self.destination_entry.get()
            sz = 1024000 * int(self.size_entry.get())
            
            mbls = MuBlas.MuBlas(m_dir, d_dir, sz)
            mbls.start()
            
            self.process_but["state"] = NORMAL
            self.pr_bar.stop()
            
        def exit_app(self, event):
            root.destroy()
            
        def process(self):
Ejemplo n.º 19
0
class GUI:
    def __init__(self, master):
        ################-GLOBAL-VARS-############################
        self.version = 1.1
        self.loadingMsg = "Loading......................."
        self.driver = ""
        self.tupleDates = []
        self.roomTimeList = []
        self.roomIndex = 0
        self.outputTimeArray = []
        self.userInfo = []
        self.master = master
        self.outputEmail = ""

        ###############-WINDOW-SETUP-############################
        self.master.title("LibCal Booker v" + str(self.version))
        self.master.resizable(width=False, height=False)
        self.master.protocol("WM_DELETE_WINDOW", self.window_close)
        self.master.createcommand('exit', self.window_close)
        self.master.bind('<Return>', self.submit_click)

        ###############-LOAD-FILE-###############################
        # TODO: Check fields of json, if do not match, transfer over files
        try:
            with open("userInfo.json") as data_file:
                self.userInfo = json.load(data_file)
        except:
            print "No existing user"
            with open("userInfo.json", "w+") as data_file:
                self.userInfo = dict(version=self.version,
                                     first="Mitchell",
                                     last="Pynn",
                                     email="*****@*****.**",
                                     override=0,
                                     confirm=1,
                                     browser=0,
                                     firstLoad=True,
                                     authEmail="")
                json.dump(self.userInfo, data_file)

        ###################-DATE SELECTION-######################
        # set up availDates
        self.availDates = [self.loadingMsg]
        # set up chosen date and give default value
        self.chosenDate = StringVar(self.master)
        self.chosenDate.set(self.loadingMsg)
        # set up dateOptionMenu
        self.dateOptionMenu = OptionMenu(self.master,
                                         self.chosenDate,
                                         *self.availDates,
                                         command=self.date_click)
        self.dateOptionMenu.grid(row=0,
                                 column=0,
                                 columnspan=1,
                                 sticky=(N, S, E, W),
                                 pady=(8, 0),
                                 padx=(5, 0))

        ##################-ROOM SELECTION-######################
        # set up availRooms
        self.availRooms = [
            'LI 1004', 'LI 1006', 'LI 1007', 'LI 1008', 'LI 1009', 'LI 1010',
            'LI 4001', 'LI 4002', 'LI 4003', 'LI 4004', 'LI 4005', 'LI 4006',
            'LI 4007', 'LI 4008', 'LI 4009', 'LI 4010'
        ]
        self.availTimes = [
            '8:00am - 8:30am', '8:30am - 9:00am', '9:00am - 9:30am',
            '9:30am - 10:00am', '10:00am - 10:30am', '10:30am - 11:00am',
            '11:00am - 11:30am', '11:30am - 12:00pm', '12:00pm - 12:30pm',
            '12:30pm - 1:00pm', '1:00pm - 1:30pm', '1:30pm - 2:00pm',
            '2:00pm - 2:30pm', '2:30pm - 3:00pm', '3:00pm - 3:30pm',
            '3:30pm - 4:00pm', '4:00pm - 4:30pm', '4:30pm - 5:00pm',
            '5:00pm - 5:30pm', '5:30pm - 6:00pm', '6:00pm - 6:30pm',
            '6:30pm - 7:00pm', '7:00pm - 7:30pm', '7:30pm - 8:00pm',
            '8:00pm - 8:30pm', '8:30pm - 9:00pm', '9:00pm - 9:30pm',
            '9:30pm - 10:00pm', '10:00pm - 10:30pm', '10:30pm - 11:00pm',
            '11:00pm - 11:30pm', '11:30pm - 11:59pm'
        ]
        # set up chosen room and give default value
        self.chosenRoom = StringVar(self.master)
        self.chosenRoom.set(self.availRooms[0])
        # set up roomOptionMenu
        self.roomOptionMenu = OptionMenu(self.master,
                                         self.chosenRoom,
                                         *self.availRooms,
                                         command=self.room_click)
        self.roomOptionMenu.grid(row=1,
                                 column=0,
                                 columnspan=1,
                                 sticky=(N, S, E, W),
                                 padx=(5, 0),
                                 pady=(5, 0))

        ##################-TIME SELECTION-####################
        self.timeOptionList = Listbox(self.master,
                                      selectmode=EXTENDED,
                                      height=20,
                                      exportselection=0,
                                      takefocus=0)
        self.timeOptionList.grid(row=2,
                                 column=0,
                                 rowspan=200,
                                 columnspan=1,
                                 sticky=(N, S, E, W),
                                 padx=(5, 0),
                                 pady=5)
        self.timeOptionList.insert(0, self.loadingMsg)
        self.timeOptionList.config(state=DISABLED)

        #################-BUTTONS-##########################
        # user info
        self.infoLabel = Label(self.master,
                               text="[ U S E R  I N F O ]",
                               font=("Helvetica", 16, "bold"))
        self.infoLabel.grid(row=0, column=1, columnspan=2, sticky=E + W)

        # first Name label and input
        self.fnameLabel = Label(self.master,
                                text="First: ",
                                font=("Helvetica", 12, "bold"))
        self.fnameLabel.grid(row=1, column=1, sticky=W)

        self.fnameEntry = Entry(self.master)
        self.fnameEntry.grid(row=1, column=2, stick=E + W, padx=(0, 5))
        self.fnameEntry.insert(0, self.userInfo["first"])

        # last name label and input
        self.lnameLabel = Label(self.master,
                                text="Last: ",
                                font=("Helvetica", 12, "bold"))
        self.lnameLabel.grid(row=2, column=1, sticky=W)

        self.lnameEntry = Entry(self.master)
        self.lnameEntry.grid(row=2, column=2, stick=E + W, padx=(0, 5))
        self.lnameEntry.insert(0, self.userInfo["last"])

        # email label and entry
        self.emailLabel = Label(self.master,
                                text="Email: ",
                                font=("Helvetica", 12, "bold"))
        self.emailLabel.grid(row=3, column=1, sticky=W)

        self.emailEntry = Entry(self.master)
        self.emailEntry.grid(row=3, column=2, stick=E + W, padx=(0, 5))
        self.emailEntry.insert(0, self.userInfo["email"])

        # showBrowser checkbox
        self.browserVal = IntVar(self.master)
        self.browserVal.set(self.userInfo["browser"])
        self.browser = Checkbutton(self.master,
                                   text="Show web browser",
                                   variable=self.browserVal,
                                   command=self.browser_show,
                                   onvalue=1,
                                   offvalue=0,
                                   font=("Helvetica", 12),
                                   takefocus=0)
        self.browser.grid(row=4, column=2, sticky=W)

        # override checkbox
        self.overrideVal = IntVar(self.master)
        self.overrideVal.set(self.userInfo["override"])
        self.override = Checkbutton(self.master,
                                    text="Override 2hr max",
                                    variable=self.overrideVal,
                                    onvalue=1,
                                    offvalue=0,
                                    font=("Helvetica", 12),
                                    takefocus=0)
        self.override.grid(row=5, column=2, sticky=W)

        # confirm checkbox
        self.confirmVal = IntVar(self.master)
        self.confirmVal.set(self.userInfo["confirm"])
        self.confirm = Checkbutton(self.master,
                                   text="Enable confirm dialog",
                                   variable=self.confirmVal,
                                   onvalue=1,
                                   offvalue=0,
                                   font=("Helvetica", 12),
                                   takefocus=0)
        self.confirm.grid(row=6, column=2, sticky=W)

        # submit button
        self.submit = Button(self.master,
                             text="Submit",
                             command=self.submit_click,
                             takefocus=0)
        self.submit.grid(row=8,
                         column=2,
                         sticky=(N, S, E, W),
                         padx=(0, 5),
                         pady=(0, 5))
        self.submit["state"] = "disabled"

        # loading bar
        self.loadingBar = Progressbar(self.master,
                                      orient=HORIZONTAL,
                                      length=100,
                                      mode='determinate')
        self.loadingBar.grid(row=9,
                             column=2,
                             sticky=(N, S, E, W),
                             padx=(0, 5),
                             pady=(0, 5))
        self.loadingBar["value"] = 10

        # email
        self.emm = Button(self.master,
                          text="email tester",
                          command=self.test_email_click,
                          takefocus=0)
        self.emm.grid(row=10,
                      column=2,
                      sticky=(N, S, E, W),
                      padx=(0, 5),
                      pady=(0, 5))

        # update skeleton GUI, then load data
        self.master.update()
        self.load_data()

        # make sure window on top
        self.master.lift()

        # show welcome message if first load
        if self.userInfo["firstLoad"]:
            tkMessageBox.showinfo(
                "Welcome",
                "Currently, booking multiple rooms is not permitted. You are limited to only booking one room per session. However, booking multiple time slots per room is permitted.\n\nMake sure to update the [ USER INFO ] section with your own name and email. \n\nCreated by Mitchell Pynn "
            )

    def test_email_click(self):
        self.outputEmail = "*****@*****.**"

    def email_click(self, randVals):
        """
        Shows basic usage of the Gmail API.

        Creates a Gmail API service object and outputs a list of label names
        of the user's Gmail account.
        """
        credentials = self.get_credentials()
        http = credentials.authorize(httplib2.Http())
        service = discovery.build('gmail', 'v1', http=http)

        userProfile = service.users().getProfile(userId='me').execute()

        # set user JSON auth email
        self.userInfo["authEmail"] = userProfile['emailAddress']

        for idItem in randVals:
            print idItem
            try:
                # please newer_than:1d to: + idItem
                email1 = service.users().messages().list(userId='me',
                                                         q='to:' +
                                                         idItem).execute()
                output = email1['messages']

                text = service.users().messages().get(
                    userId='me', id=output[0]['id']).execute()
                ampFix = text['snippet'].replace('&amp;', '&')


                confirmUrl = \
                re.findall('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+|]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', ampFix)[
                    0] + '&m=confirm'
                print(confirmUrl)

                self.driver.execute_script("window.open('" + confirmUrl +
                                           "', 'new_window')")
                self.driver.switch_to.window(self.driver.window_handles[1])
                try:
                    # wait until page is loaded and success element found
                    element = WebDriverWait(self.driver, 5).until(
                        EC.presence_of_element_located(
                            (By.CLASS_NAME, "final_msg")))

                    # close tab and return to main page
                    self.driver.close()
                    self.driver.switch_to.window(self.driver.window_handles[0])

                except:
                    print "Could not book room " + idItem

            except:
                print('An error occurred confirming the room: ????')

    def get_credentials(self):
        """Gets valid user credentials from storage.

        If nothing has been stored, or if the stored credentials are invalid,
        the OAuth2 flow is completed to obtain the new credentials.

        Returns:
            Credentials, the obtained credential.
        """
        home_dir = os.path.expanduser('~')
        credential_dir = os.path.join(home_dir, '.credentials')
        if not os.path.exists(credential_dir):
            os.makedirs(credential_dir)
        credential_path = os.path.join(credential_dir,
                                       self.outputEmail + '.json')

        store = Storage(credential_path)
        credentials = store.get()
        if not credentials or credentials.invalid:
            flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
            flow.user_agent = APPLICATION_NAME
            if flags:
                credentials = tools.run_flow(flow, store, flags)
            else:  # Needed only for compatibility with Python 2.6
                credentials = tools.run(flow, store)
            print('Storing credentials to ' + credential_path)
        return credentials

    def browser_show(self):
        if self.browserVal.get() == 1:
            # hide window/throw in corner
            self.driver.set_window_position(0, 0)
            self.driver.set_window_size(100, 600)
        else:
            # hide window/throw in corner
            self.driver.set_window_position(3000, 3000)
            self.driver.set_window_size(100, 300)

    def save_data(self):
        # update userFile when submitted
        with open("userInfo.json", 'r+') as data_file:
            self.userInfo["first"] = self.fnameEntry.get()
            self.userInfo["last"] = self.lnameEntry.get()
            self.userInfo["email"] = self.emailEntry.get()
            self.userInfo["confirm"] = self.confirmVal.get()
            self.userInfo["override"] = self.overrideVal.get()
            self.userInfo["browser"] = self.browserVal.get()
            self.userInfo["firstLoad"] = False

            data_file.seek(0)
            json.dump(self.userInfo, data_file)
            data_file.truncate()

    def window_close(self):
        # save data
        self.save_data()
        # destroy GUI and quit driver
        self.master.destroy()
        self.driver.quit()

        # clean log files if exist (maybe good to keep?)
        dir = os.listdir(os.getcwd())
        for item in dir:
            if item.endswith(".log"):
                os.remove(os.path.join(os.getcwd(), item))

    # from -> http://stackoverflow.com/a/12578715
    def is_windows_64bit(self):
        if 'PROCESSOR_ARCHITEW6432' in os.environ:
            return True
        return os.environ['PROCESSOR_ARCHITECTURE'].endswith('64')

    def load_data(self):
        self.loadingBar["value"] = 25
        self.master.update_idletasks()

        # connect to webdriver - Try Google Chrome, then Firefox
        chrome = False
        try:
            chromeOptions = webdriver.ChromeOptions()
            prefs = {
                "profile.managed_default_content_settings.images": 2,
                "profile.managed_default_content_settings.stylesheet": 2
            }
            chromeOptions.add_experimental_option("prefs", prefs)

            if platform.system() == 'Darwin':
                self.driver = webdriver.Chrome(
                    executable_path=os.getcwd() +
                    '/bin/chrome/chromedriverDarwin',
                    chrome_options=chromeOptions)
            elif platform.system() == 'Windows':
                self.driver = webdriver.Chrome(
                    executable_path=os.getcwd() +
                    '/bin/chrome/chromedriverWindows.exe',
                    chrome_options=chromeOptions)
            elif platform.system() == 'Linux':
                self.driver = webdriver.Chrome(executable_path=os.getcwd() +
                                               '/bin/chrome/chromedriverLinux',
                                               chrome_options=chromeOptions)
            else:
                print "Fatal error - incompatible operating system"
                exit()
            chrome = True
        except:
            print "Could not load Chrome, trying Firefox."

        if not chrome:
            try:
                # setup firefox profile, no images, no css for speed
                firefox_profile = webdriver.FirefoxProfile()
                firefox_profile.add_extension(
                    os.getcwd() + "/bin/ext/quickjava-2.1.2-fx.xpi")
                firefox_profile.set_preference(
                    "thatoneguydotnet.QuickJava.curVersion", "2.1.2.1"
                )  ## Prevents loading the 'thank you for installing screen'
                firefox_profile.set_preference(
                    "thatoneguydotnet.QuickJava.startupStatus.Images",
                    2)  ## Turns images off
                firefox_profile.set_preference(
                    "thatoneguydotnet.QuickJava.startupStatus.AnimatedImage",
                    2)  ## Turns animated images off
                firefox_profile.set_preference(
                    "thatoneguydotnet.QuickJava.startupStatus.CSS", 2)  ## CSS
                firefox_profile.set_preference(
                    "thatoneguydotnet.QuickJava.startupStatus.Flash",
                    2)  ## Flash
                firefox_profile.set_preference(
                    "thatoneguydotnet.QuickJava.startupStatus.Java",
                    2)  ## Java
                firefox_profile.set_preference(
                    "thatoneguydotnet.QuickJava.startupStatus.Silverlight",
                    2)  ## Silverlight

                # load driver according to operating system,
                if platform.system() == 'Darwin':
                    self.driver = webdriver.Firefox(
                        executable_path=os.getcwd() +
                        '/bin/gecko/geckodriverDarwin',
                        firefox_profile=firefox_profile)
                elif platform.system() == 'Windows':
                    if self.is_windows_64bit():
                        self.driver = webdriver.Firefox(
                            executable_path=os.getcwd() +
                            '/bin/gecko/geckodriverWindows64.exe',
                            firefox_profile=firefox_profile)
                    else:
                        self.driver = webdriver.Firefox(
                            executable_path=os.getcwd() +
                            '/bin/gecko/geckodriverWindows.exe',
                            firefox_profile=firefox_profile)
                elif platform.system() == 'Linux':
                    self.driver = webdriver.Firefox(
                        executable_path=os.getcwd() +
                        '/bin/gecko/geckodriverLinux',
                        firefox_profile=firefox_profile)
                else:
                    print "Fatal error - incompatible operating system"
                    exit()
            except:
                # get no firefox exception
                print "You must have Firefox or Google Chrome installed"
                exit(6)

        # hide window/throw in corner or show
        self.browser_show()
        self.master.lift()

        self.loadingBar["value"] = 50
        self.master.update_idletasks()

        # load intial site
        self.driver.get("http://libcal.lakeheadu.ca/rooms_acc.php?gid=13445")
        assert "The Chancellor Paterson Library" in self.driver.title

        # scrape dates, only have to do once
        self.tupleDates = collections.OrderedDict()
        dateWheel = Select(self.driver.find_element_by_id("datei"))
        for date in dateWheel.options:
            self.tupleDates[date.text] = date.get_attribute("value")

        self.loadingBar["value"] = 75
        self.master.update_idletasks()

        # remove loading option, pull dates from tuple to list
        # set chosen date to top entry in date list
        # format: {'Monday June 1st': '06-01-17'}
        self.availDates.remove(self.loadingMsg)
        for key, value in self.tupleDates.iteritems():
            self.availDates.append(key)
        self.chosenDate.set(self.availDates[0])

        # get menu, clear and add dates
        menu = self.dateOptionMenu["menu"]
        menu.delete(0, "end")
        for val in self.availDates:
            menu.add_command(
                label=val, command=lambda pvalue=val: self.date_click(pvalue))

        # update GUI, will show current date in selection
        self.master.update()
        # initial load data
        self.date_click()
        # make sure on top
        self.master.lift()

    def date_click(self, value=""):
        # do nothing if same day clicked
        if value:
            if self.chosenDate.get() == value:
                return
            else:
                self.chosenDate.set(value)
                self.loadingBar["value"] = 20
                self.submit["state"] = "disabled"
                self.master.update_idletasks()

        # clear timeOptionList contents, showing loading message
        self.timeOptionList.delete(0, END)
        self.timeOptionList.insert(0, self.loadingMsg)
        self.timeOptionList.config(state=DISABLED)
        if value:
            self.loadingBar["value"] = 40
        self.master.update()

        # load selected date webpage
        self.driver.get(
            "http://libcal.lakeheadu.ca/rooms_acc.php?gid=13445&d=" +
            self.tupleDates[self.chosenDate.get()] + "&cap=0")

        # does this wait until page is loaded?
        assert "The Chancellor Paterson Library" in self.driver.title
        # make sure loaded?

        # create 2D array of [0]'s
        self.roomTimeList = [[0] for _ in range(16)]

        if value:
            self.loadingBar["value"] = 60
            self.master.update_idletasks()
        self.room_click("room")

    def room_click(self, value=""):
        if value == "room":
            self.loadingBar["value"] = 95
        else:
            self.loadingBar["value"] = 30
            self.submit["state"] = "disabled"
            self.master.update_idletasks()
        # set roomIndex to new room
        self.roomIndex = self.availRooms.index(self.chosenRoom.get())

        # clear timeOptionList contents, showing loading message
        self.timeOptionList.delete(0, END)
        self.timeOptionList.insert(0, self.loadingMsg)
        self.timeOptionList.config(state=DISABLED)
        if value != "room":
            self.loadingBar["value"] = 40
        self.master.update()

        form = self.driver.find_element_by_id("roombookingform")
        if value != "room":
            self.loadingBar["value"] = 60
            self.master.update_idletasks()
        rooms = form.find_elements_by_tag_name("fieldset")
        if value != "room":
            self.loadingBar["value"] = 80
            self.master.update_idletasks()

        # don't scrape again if already loaded
        if self.roomTimeList[self.roomIndex] == [0]:
            for room in rooms:
                # find selected room
                if room.find_element_by_tag_name(
                        "h2").text[:7] != self.chosenRoom.get():
                    continue
                # go through each room, pulling times to array
                times_out = []
                check_boxes = room.find_elements_by_class_name("checkbox")

                for box in check_boxes:
                    # output checkbox text
                    times_out.append(
                        self.availTimes.index(
                            box.find_element_by_tag_name("label").text))
                self.roomTimeList.insert(self.roomIndex, times_out)
                break

        # for the selected room, set time slots
        self.timeOptionList.config(state=NORMAL)
        self.timeOptionList.delete(0, END)
        if len(self.roomTimeList[self.roomIndex]) > 0:
            for timeSlot in self.roomTimeList[self.roomIndex]:
                self.timeOptionList.insert(END, self.availTimes[timeSlot])
        else:
            self.timeOptionList.insert(END, "No times available")
            self.timeOptionList.config(state=DISABLED)

        # update height, update the whole list if it isnt first run
        self.timeOptionList.configure(
            height=len(self.roomTimeList[self.roomIndex]))

        # colorize alternating lines of the listbox
        for i in range(0, len(self.roomTimeList[self.roomIndex]), 2):
            self.timeOptionList.itemconfigure(i, background='#f0f0ff')

        self.loadingBar["value"] = 100
        self.master.update_idletasks()

        # update GUI size and remove loading bar
        self.submit["state"] = "normal"
        self.master.update()

    def submit_click(self, value=""):
        if self.emailEntry.get().strip()[-13:] != "@lakeheadu.ca":
            tkMessageBox.showerror(
                "Email format error",
                "Please make sure to use a valid @lakeheadu.ca email address")
            return

        self.save_data()

        selection = self.timeOptionList.curselection()
        if selection == ():
            return
        if len(selection) > 4 and self.overrideVal.get() != 1:
            tkMessageBox.showerror("2hr Limit",
                                   "Sorry, you can only book 2hrs per day")
            return
        if self.confirmVal.get() == 1:
            outputTimes = ""
            lineBreak = '-' * (len(self.chosenDate.get()) + 2)
            for index in selection:
                pIndex = self.roomTimeList[self.roomIndex][int(index)]
                outputTimes += self.availTimes[pIndex] + "\n"
            if not tkMessageBox.askokcancel(
                    "Please confirm the following times",
                    self.chosenDate.get() + "\n" + lineBreak + "\n" +
                    self.availRooms[self.roomIndex] + "\n" + outputTimes):
                return

        # if output, get times
        self.outputTimeArray = []
        for index in selection:
            pIndex = self.roomTimeList[self.roomIndex][int(index)]
            self.outputTimeArray.append(self.availTimes[pIndex])

        # book rooms
        self.book_times()

        # check if any rooms were unavailable
        if len(self.outputTimeArray) > 0:
            outputText = "The following times were unavailable to book\n----------------------------------------\n"
            for item in self.outputTimeArray:
                outputText += item + "\n"
            tkMessageBox.showerror("Unavailable", outputText)

        # clear booked room time slots,
        self.roomTimeList[self.roomIndex] = [0]
        self.room_click()

    def book_times(self):
        # refresh page
        try:
            self.driver.refresh()
        except:
            print "Could not load the browser"
        assert "The Chancellor Paterson Library" in self.driver.title

        outputText = "Successfully booked the following rooms \n" + self.chosenDate.get(
        ) + "\n" + '-' * (len(self.chosenDate.get()) +
                          2) + "\n" + self.chosenRoom.get()
        outputLength = 0
        outputRandomId = []
        self.outputEmail = self.emailEntry.get().strip(
        )[:-13] + "@lakeheadu.ca"
        while True:
            # get rooms
            form = self.driver.find_element_by_id("roombookingform")
            rooms = form.find_elements_by_tag_name("fieldset")

            for room in rooms:
                # find selected room
                if room.find_element_by_tag_name(
                        "h2").text[:7] != self.availRooms[self.roomIndex]:
                    continue

                consect = 0
                selectedTimes = []
                checkBoxes = room.find_elements_by_class_name("checkbox")
                for box in checkBoxes:
                    # loops through times from start every time, how can I keep place of where left off?
                    timeSlot = box.find_element_by_tag_name("label")
                    if timeSlot.text in self.outputTimeArray:
                        consect += 1
                        # adding another time will not overflow 2hrs, add it
                        if consect <= 4:
                            # check for consecutive, if array is blank, add time regardless
                            # try the simplify
                            if selectedTimes != []:
                                for selectedIndex in selectedTimes:
                                    # check if time is in consecutive order
                                    # can I put or in between two conditions????
                                    if (self.availTimes.index(timeSlot.text) -
                                            1) == selectedIndex or (
                                                self.availTimes.index(
                                                    timeSlot.text) +
                                                1) == selectedIndex:
                                        outputText += "\n" + timeSlot.text
                                        # add to selectedTimes
                                        selectedTimes.append(
                                            self.availTimes.index(
                                                timeSlot.text))
                                        # remove timeSlot from array
                                        self.outputTimeArray.remove(
                                            timeSlot.text)
                                        # click timeSlot
                                        timeSlot.click()
                                        break
                            else:
                                outputText += "\n" + timeSlot.text
                                # add to selectedTimes
                                selectedTimes.append(
                                    self.availTimes.index(timeSlot.text))
                                # remove timeSlot from array
                                self.outputTimeArray.remove(timeSlot.text)
                                # click timeSlot
                                timeSlot.click()

                        # if 4 boxes are selected, break and book the selected rooms
                        else:
                            break
                    # if at least one box is selected, book it, must be consecutive
                    elif consect > 0:
                        break

                break
            if consect > 0:
                # fill info of form
                self.driver.find_element_by_id("fname").send_keys(
                    self.fnameEntry.get())
                self.driver.find_element_by_id("lname").send_keys(
                    self.lnameEntry.get())

                # always uses random_id, override 2hrs just prevents user from booking more
                # then 2hrs at a time
                randId = self.id_generator()
                outputRandomId.append(randId)
                self.driver.find_element_by_id(
                    "email").send_keys(self.emailEntry.get().strip()[:-13] +
                                       "+" + randId + "@lakeheadu.ca")

                # submit
                self.driver.find_element_by_id("s-lc-rm-ac-but").click()

                # assert it is success
                try:
                    # search for success element / fail
                    # handle failure
                    element = WebDriverWait(self.driver, 10).until(
                        EC.visibility_of_element_located(
                            (By.ID, "s-lc-rm-ac-success")))
                except TimeoutException:
                    tkMessageBox.showerror(
                        "ERROR", "Error booking the room. Exiting...")
                    self.driver.quit()
            # refresh page
            self.driver.refresh()

            # if out of times to book or cannot book times, break out
            if len(self.outputTimeArray) <= 0 or len(
                    self.outputTimeArray) == outputLength:
                break

            outputLength = len(self.outputTimeArray)

        # print success message
        if len(self.outputTimeArray) <= 0:
            print outputRandomId
            tkMessageBox.showinfo("Success", outputText)
            # ask to confirm
            # if email used to book rooms does not match email authEmail
            ## show message that redirection is happening
            if tkMessageBox.askyesno(
                    "Confirm times",
                    "Would you like to confirm your booked times?"):
                # check if
                if self.userInfo['authEmail'] != self.outputEmail:
                    tkMessageBox.showinfo(
                        "Redirecting...", "Press OK and login with " +
                        self.outputEmail + " in the browser that will open.")
                self.email_click(outputRandomId)

    # random ID generator -> http://stackoverflow.com/a/2257449
    def id_generator(self,
                     size=8,
                     chars=string.ascii_uppercase + string.digits):
        return ''.join(random.choice(chars) for _ in range(size))
Ejemplo n.º 20
0
class Application(Frame):
    def run(self):
        appid = self.var_appid.get().strip()
        if len(appid) == 0:
            tkMessageBox.showinfo(title=u"错误", message="请输入公众账号ID")
            return

        mch_id = self.var_mch_id.get().strip()
        if len(mch_id) == 0:
            tkMessageBox.showinfo(title=u"错误", message="请输入商户号")
            return

        mch_key = self.var_mch_key.get().strip()
        if len(mch_key) == 0:
            tkMessageBox.showinfo(title=u"错误", message="请输入商户密钥")
            return

        bill_date_from = self.var_bill_date_from.get().strip()
        if len(bill_date_from) == 0:
            tkMessageBox.showinfo(title=u"错误", message="请输入开始日期")
            return
            
        path = self.var_path.get().strip()
        if len(path) == 0:
            tkMessageBox.showinfo(title=u"错误", message="请选择输出目录")
            return
            
        sub_mch_id = self.txt_sub_mch_id.get(1.0, END)
        if len(sub_mch_id) > 0:
            sub_mch_ids = list(set(sub_mch_id.split()))
        else:
            sub_mch_ids = []
        
        # save settings    
        config.save(appid, mch_id, mch_key, sub_mch_id, path)

        bill_date_to = self.var_bill_date_to.get().strip()
        if len(bill_date_to) == 0:
            bill_date_to = (datetime.now() + timedelta(days=-1)).strftime("%Y%m%d")
        
        s = datetime.strptime(bill_date_from, "%Y%m%d")
        e = datetime.strptime(bill_date_to, "%Y%m%d")
        
        def work_proc(self, path, s, e, sub_mch_ids, event):
            
            self.btn_run.config(state='disabled')
            
            days = (e - s).days + 1
            max = days * (len(sub_mch_ids) if len(sub_mch_ids) > 0 else 1)
            
            self.prg_bar.config({'maximum': max})

            while s <= e:
                if len(sub_mch_ids) > 0:
                    for sub_mch_id in sub_mch_ids:
                        r = download_bill(mch_key, appid, mch_id, s, sub_mch_id)
                        self.save_bill(r, s, mch_id, sub_mch_id)
                        self.prg_bar.step()
                
                else:
                    r = download_bill(mch_key, appid, mch_id, s)
                    self.save_bill(r, s, mch_id)
                    self.prg_bar.step()
                    
                s += timedelta(days=1)

            self.btn_run.config(state='normal')
            
            event.set()
        
        self.running = True
        
        work_thread = threading.Thread(target=work_proc, args=(self, path, s, e, sub_mch_ids, self.event))
        work_thread.start()
    
    def save_bill(self, text, bill_date, mch_id, sub_mch_id=None):
        bill_date = bill_date.strftime("%Y%m%d")
        if text.startswith('<xml>'):
            f = '%s_%s_%s.xml' % (bill_date, mch_id, sub_mch_id) if sub_mch_id else '%s_%s_.xml' % (bill_date, mch_id)
        else:
            f = '%s_%s_%s.csv' % (bill_date, mch_id, sub_mch_id) if sub_mch_id else '%s_%s_.csv' % (bill_date, mch_id)

        fullname = os.path.join(self.var_path.get().strip(), f)
        with open(fullname, 'wb') as csv:
            csv.write(text)
            
    def select_path(self):
        self.var_path.set(tkFileDialog.askdirectory())
        
    def createWidgets(self, settings):
        row = 0
        
        # 公众号ID
        self.lbl_appid = Label(self, text=u"公众帐号ID", fg='red')
        self.lbl_appid.grid(column=0, row=row, sticky=(E, N))

        self.var_appid = StringVar(self, value=settings.get('appid')) 
        self.txt_appid = Entry(self, textvariable=self.var_appid, width=60, font=self.font)
        self.txt_appid.grid(column=1, row=row, columnspan=2, sticky=(W, N))

        row += 1
        
        
        # 商户号
        self.lbl_mch_id = Label(self, text=u"商户号", fg='red')
        self.lbl_mch_id.grid(column=0, row=row, sticky=(E, N))

        self.var_mch_id = StringVar(self, value=settings.get('mch_id')) 
        self.txt_mch_id = Entry(self, textvariable=self.var_mch_id, width=60, font=self.font)
        self.txt_mch_id.grid(column=1, row=row, columnspan=2, sticky=(W, N))

        row += 1
        
        # 商户密钥
        self.lbl_mch_key = Label(self, text=u"商户密钥", fg='red')
        self.lbl_mch_key.grid(column=0, row=row, sticky=(E, N))

        self.var_mch_key = StringVar(self, value=settings.get('mch_key')) 
        self.txt_mch_key = Entry(self, textvariable=self.var_mch_key, width=60, font=self.font)
        self.txt_mch_key.grid(column=1, row=row, columnspan=2, sticky=(W, N))

        row += 1
        
        # 子商户号
        self.lbl_sub_mch_id = Label(self, text=u"子商户号")
        self.lbl_sub_mch_id.grid(column=0, row=row, sticky=(E, N))

        self.txt_sub_mch_id = Text(self, height=5, width=60, font=self.font)
        if  settings.get('sub_mch_id'):
            self.txt_sub_mch_id.insert(END, settings.get('sub_mch_id'))
        self.txt_sub_mch_id.grid(column=1, row=row, columnspan=2, sticky=(W, N))

        row += 1
        
        # 开始日期
        self.lbl_bill_date_from = Label(self, text=u"开始日期", fg='red')
        self.lbl_bill_date_from.grid(column=0, row=row, sticky=(E, N))

        self.var_bill_date_from = StringVar() 
        self.var_bill_date_from.set((datetime.now() - timedelta(days=1)).strftime("%Y%m%d")) 
        self.txt_bill_date_from = Entry(self, width=8, textvariable=self.var_bill_date_from, font=self.font)
        self.txt_bill_date_from.grid(column=1, row=row, columnspan=2, sticky=(W, N))

        row += 1
        
        # 结束日期
        self.lbl_bill_date_to = Label(self, text=u"结束日期")
        self.lbl_bill_date_to.grid(column=0, row=row, sticky=(E, N))

        self.var_bill_date_to = StringVar() 
        self.txt_bill_date_to = Entry(self, width=8, textvariable=self.var_bill_date_to, font=self.font)
        self.txt_bill_date_to.grid(column=1, row=row, columnspan=2, sticky=(W, N))

        row += 1
        
        # 输出目录
        self.lbl_path = Label(self, text=u"输出目录", fg='red')
        self.lbl_path.grid(column=0, row=row, sticky=(E, N))

        path = settings.get('path')
        self.var_path = StringVar(self, value=path if path else os.path.dirname(os.path.abspath(cur_path))) 
        self.txt_path = Entry(self, textvariable=self.var_path, width=55, font=self.font)
        self.txt_path.grid(column=1, row=row, sticky=(W, N, E))

        self.btn_select_path = Button(self, text=u"...", command=self.select_path)
        self.btn_select_path.grid(column=2, row=row, sticky=(E))
        
        row += 1
        
        # 进度条
        self.prg_bar = Progressbar(self)
        self.prg_bar.grid(column=0, row=row, columnspan=3, sticky=(W, E), pady=(10, 0))
        
        row += 1
        
        # 执行按钮
        buttonFrame = Frame(self)
        buttonFrame.grid(column=0, row=row, columnspan=3, pady=(15, 0), sticky=(W, E))
        
        self.btn_run = Button(buttonFrame, width=20, text=u"下载", fg='blue', command=self.run)
        self.btn_run.pack()

    def loop(self):
        if self.running and self.event.is_set():
            self.running = False
            self.event.clear()
            
            tkMessageBox.showinfo(title=u"成功", message="账单下载结束")
            subprocess.call('explorer "%s"' % self.var_path.get().strip().replace('/', '\\'), shell=True)
            
        self.master.after(100, self.loop)

                
    def __init__(self, master=None):
        Frame.__init__(self, master)
        
        self.font = tkFont.nametofont("TkDefaultFont")
        self.font.configure(family='MS Gothic', size=9)

        self.grid(column=0, row=0, sticky=(N, W, E, S), padx=10, pady=10)

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

        settings = config.load()
        self.createWidgets(settings)
        
        self.event = threading.Event()

        self.running = False
        self.loop()
Ejemplo n.º 21
0
class QuoraAnalyticsUI(Notebook):

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  def destroy(self):
    self.crawler.quit()
    Notebook.destroy(self)
Ejemplo n.º 22
0
        self.running = False

def hello():
   tkMessageBox.showinfo("Say Hello", "Hello World")


top = Tk()
top.title("Converter")
L1 = Label(top, text = "Hexadecimal", width=20)
L1.grid(row=0, column=0)
L2 = Label(top, text = "Binary", width=20)
L2.grid(row=0, column=1)
L3 = Label(top, text = "Decimal", width=20)
L3.grid(row=0, column=2)
progressBar = Progressbar(top, orient='horizontal', mode='determinate', length=240)
progressBar.grid(row=3, column = 1, columnspan = 2)

B1 = Button(top, text = "Say Hello", command = hello)
B1.grid(row=31, column=3)


E1 = Entry(top, bd = 3)

E1.grid(row=1, column=0)
E2 = Entry(top, bd = 3)
E2.grid(row=1, column=1)

E3 = Entry(top, bd = 3)
E3.grid(row=1, column=2)

top.mainloop()
Ejemplo n.º 23
0
class Window(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.parent = parent
        self.initUI()
        
    def initUI(self):
        self.parent.title("Network/Port Scan")
        self.style = Style()
        self.style.configure("TFrame", background = "#000000")
        self.style.configure("TCheckbutton", background = "#000000")
        self.style.configure("TButton", background = "#000000") 
        self.pack(fill=BOTH, expand=1)
        
        # Configure layout
        self.columnconfigure(0, weight=1)
        self.columnconfigure(1, weight=1)
        self.columnconfigure(2, weight=1)
        self.rowconfigure(5, weight = 1)
        self.rowconfigure(6, weight = 1)
        
        # Title of program
        lbl = Label(self, text="Network/Port Scan")
        lbl.grid(sticky = W, pady=5, padx=5)

        # Text Box
        area = ScrolledText(self, height = 20)
        area.grid(row=1, column=0, columnspan=3, rowspan=4, padx=3, sticky = N+S+E+W)
        self.area = area

        # IP Address Button
        self.ip = BooleanVar()
        ip_add_button = Checkbutton(self, text="IP Address",variable=self.ip, width=10)
        ip_add_button.grid(row = 1, column = 3, sticky = N)
        ip_add_button.config(anchor = W, activebackground = "red")

        # Port Button
        self.port = BooleanVar()
        port_button = Checkbutton(self, text="Ports", variable=self.port, width=10)
        port_button.grid(row = 1, column = 3)
        port_button.config(anchor = W, activebackground = "orange")
        
        # Host Name Button
        self.host = BooleanVar()
        host_name_button = Checkbutton(self, text="Host Name",variable=self.host, width=10)
        host_name_button.grid(row = 1, column = 3, sticky = S)
        host_name_button.config(anchor = W, activebackground = "yellow")
        
        # Gateway Button
        self.gateway = BooleanVar()
        gateway_btn = Checkbutton(self, text="Gateway", variable=self.gateway, width=10)
        gateway_btn.grid(row = 2, column = 3, sticky = N)
        gateway_btn.config(anchor = W, activebackground = "green")

        # Services Button
        self.service = BooleanVar()
        service_btn = Checkbutton(self, text="Services", variable = self.service, width=10)
        service_btn.grid(row = 2, column = 3)
        service_btn.config(anchor = W, activebackground = "blue")

        # Starting IP label
        ip_label = Label(self, text = "Starting IP:  ")
        ip_label.grid(row = 5, column = 0, pady = 1, padx = 3, sticky = W)
        self.ip_from = Entry(self, width = 15)
        self.ip_from.insert(0, start_ip)
        self.ip_from.grid(row = 5 , column = 0, pady = 1, padx = 3, sticky = E)

        # Ending IP label
        ip_label_two = Label(self, text = "Ending IP:  ")
        ip_label_two.grid(row = 5, column = 1, pady = 1, padx = 5, sticky = W)
        self.ip_to = Entry(self, width = 15)
        self.ip_to.insert(0, end_ip)
        self.ip_to.grid(row = 5 , column = 1, pady = 1, padx = 5, sticky = E)
        
        # Starting Port Label
        port_label = Label(self, text = "Starting Port:  ")
        port_label.grid(row = 5, column = 0, pady = 3, padx = 5, sticky = S+W)
        self.port_from = Entry(self, width = 15)
        self.port_from.insert(0, 0)
        self.port_from.grid(row = 5 , column = 0, pady = 1, padx = 5, sticky = S+E)

        # Ending Port Label
        port_label_two = Label(self, text = "Ending Port:  ")
        port_label_two.grid(row = 5, column = 1, pady = 3, padx = 5, sticky = S+W)
        self.port_to = Entry(self, width = 15)
        self.port_to.insert(0, 1025)
        self.port_to.grid(row = 5 , column = 1, pady = 1, padx = 5, sticky = S+E)

        # Scan Me 
        self_scan_button = Button(self, text="Scan Me", command = lambda : self.onClick(1), width = 33)
        self_scan_button.grid(row = 6, column = 1, sticky = N)

        # Scan near me Button
        scan_other_button = Button(self, text="Scan Near Me", width = 33, command = lambda : self.onClick(2))
        scan_other_button.grid(row = 6, column = 0, pady=1, sticky = N)
        
        # Clear button
        clear_button = Button(self, text="Clear text", command = self.clear_text, width = 12)
        clear_button.grid(row = 6, column = 3, pady=1, sticky = N)

        # Progress Bar
        self.label_scanning = Progressbar(self, orient = HORIZONTAL, length = 175)
        self.label_scanning.grid(row = 6, column = 0, columnspan = 4, padx = 7, pady = 7, sticky = E+S+W)
        self.label_scanning.config(mode = "determinate")

     
    # Clear what is in the text box.   
    def clear_text(self):
        self.area.delete(0.0, 'end')
        # empty my lists.
        my_ports[:] = []
        ip_address_up[:] = []
        target_host_name[:] = []
        target_port_up[:] = []
        
    # On click methods for scan me and scan others.
    def onClick(self, button_id):
        
        if button_id == 1:
            
            # Check to see if host button is marked
            if self.host.get() == 1:
                message = my_host_name()
                self.area.insert(0.0, message, ("warning"))
                self.area.tag_configure("warning", foreground = "blue")    
                
            # Check to see if ports button is marked   
            if self.port.get() == 1:
                # Check port entry widgets. 
                if self.port_from:
                    if self.port_to:
                        # Get the user input
                        starting_port = self.port_from.get()
                        ending_port = self.port_to.get()                
                        message, total = scan_my_ports(int(starting_port), int(ending_port))
                        for i in message:
                            new_message = "My TCP " + i + "\n"
                            self.area.insert(0.0, new_message, ("ports"))
                            #self.area.tag_configure("ports", foreground = "green")
                    
                    time = "The TCP port scan completed in: " + str(total) + "\n"
                    self.area.insert(0.0, time, ("timing"))
                    self.area.tag_configure("timing", foreground = "red")
                else:
                    self.area.insert(0.0, "No valid ports specified.")
                
            # Check to see if IP button is marked     
            if self.ip.get() == 1:
                message = my_ip()
                self.area.insert(0.0, message)
            
            # Check if gateway button is marked.
            if self.gateway.get() == 1:
                message = my_gateway()
                self.area.insert(0.0, message)

            # Check if service button is marked.
            if self.service.get() == 1:
                message, time = scan_my_services()
                for i in message:
                    new_message = i + "\n"
                    self.area.insert(0.0, new_message)
                new_time = "The local scan completed in: " + str(time) + "\n"
                self.area.insert(0.0. new_time, ("timing"))
                self.area.tag_configure("timing", foreground = "red")
                
        # If Scan other button is clicked. 
        elif button_id == 2:
            
            # Check other IP's 
            if self.ip.get() == 1:
                # Check the entry widgets.
                if self.ip_from:
                    if self.ip_to:
                        # Get the ranges from the entry widgets
                        starting_ipv4_address = self.ip_from.get()
                        ending_ipv4_address = self.ip_to.get()
                        
                        # Pass the values from the entry widgets into the function to scan nearby IP addresses.
                        message, time = ping_ip_other(starting_ipv4_address, ending_ipv4_address)
                        if message:
                            for i in message:
                                new_message = "The address:     {:>15} {:>15}".format(i,"is UP\n")
                                self.area.insert(0.0, new_message)
                        
                        total_time =  "Range scanned: " + str(starting_ipv4_address) +" to " + str(ending_ipv4_address) + "\n" + "The IP scan completed in:  " + str(time) + "\n"
                        self.area.insert(0.0, total_time, ("timing"))
                        self.area.tag_configure("timing", foreground = "red")

                else:
                    self.area.insert(0.0, "No Ip range is specified.")
                
                
            # Check others Ports
            if self.port.get() == 1:
                # Check port entry widgets. 
                if self.port_from:
                    if self.port_to:
                        # Get the user input
                        starting_port = self.port_from.get()
                        ending_port = self.port_to.get()
                        
                        
                        message, time = scan_ports_other(int(starting_port), int(ending_port))
                        if message:
                            for i in message:
                                new_msg = "The " + i +"\n"
                                self.area.insert(0.0, new_msg)
                        else:
                            new_msg = "Must scan nearby IP addresses first.\n"
                    
                    total_time = "TCP Port scan completed in: " + str(time) + "\n"
                    self.area.insert(0.0, total_time, ("timing"))
                    self.area.tag_configure("timing", foreground = "red")
                    
                else:
                    self.area.insert(0.0, "No Port range specified.")
            
            # Check other host names. Based on IP's scanned.
            if self.host.get() == 1:
                message, time = scan_host_other(ip_address_up)
                # Check that IP's of other computers were collected 
                if message:
                    for i in message:
                        new_message = "Host name: "+ str(i) + "\n"
                        self.area.insert(0.0, new_message)

                else:
                    new_msg = "Must scan nearby IP addresses first. \n"
                    self.area.insert(0.0, new_msg)
                    
                total = "The host scan completed in: " + str(time) + "\n"
                self.area.insert(0.0, total, ("timing"))
                self.area.tag_configure("timing", foreground = "red")
                
            # Check gateway return the gateway of the host machine again.
            if self.gateway.get() == 1:
                message = "\n" + str(my_gateway())
                self.area.insert(0.0, message)

            # Check what services are running on which IP and port.
            if self.service.get() == 1:
                message, time = services_other()
                if message:
                    for i in message:
                        new_message = i + "\n"
                        self.area.insert(0.0, new_message)
                    
                else:
                    new_msg = "The IP addresses and ports must be scanned first."
                    self.area.insert(0.0, new_msg)
                    
                new_time = "The service scan completed in: " + str(time) + "\n"
                self.area.insert(0.0, new_time, ("timing"))
                self.area.tag_configure("timing", foreground = "red")
                
        else:
            pass
Ejemplo n.º 24
0
class QuoraAnalyticsUI(Notebook):
    def __init__(self):
        self.parent = Tkinter.Tk()
        Notebook.__init__(self, self.parent)
        # self.parent.title('Quora Analytics')
        self.parent.title("Quora Backup and Analytics")
        self.parent.wm_title("Quora Backup and Analytics")
        self.parent.grid_rowconfigure(0, weight=1)
        self.parent.grid_columnconfigure(0, weight=1)
        self.parent.resizable(True, True)
        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)
        self.crawler = QuoraCrawler(driver=QuoraCrawler.CHROME_DRIVER)
        self._add_frames()
        self.pack(fill="both", expand=True)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def destroy(self):
        self.crawler.quit()
        Notebook.destroy(self)
Ejemplo n.º 25
0
class Window(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.parent = parent
        self.initUI()

    def initUI(self):
        self.parent.title("Network/Port Scan")
        self.style = Style()
        self.style.configure("TFrame", background="#000000")
        self.style.configure("TCheckbutton", background="#000000")
        self.style.configure("TButton", background="#000000")
        self.pack(fill=BOTH, expand=1)

        # Configure layout
        self.columnconfigure(0, weight=1)
        self.columnconfigure(1, weight=1)
        self.columnconfigure(2, weight=1)
        self.rowconfigure(5, weight=1)
        self.rowconfigure(6, weight=1)

        # Title of program
        lbl = Label(self, text="Network/Port Scan")
        lbl.grid(sticky=W, pady=5, padx=5)

        # Text Box
        area = ScrolledText(self, height=20)
        area.grid(row=1,
                  column=0,
                  columnspan=3,
                  rowspan=4,
                  padx=3,
                  sticky=N + S + E + W)
        self.area = area

        # IP Address Button
        self.ip = BooleanVar()
        ip_add_button = Checkbutton(self,
                                    text="IP Address",
                                    variable=self.ip,
                                    width=10)
        ip_add_button.grid(row=1, column=3, sticky=N)
        ip_add_button.config(anchor=W, activebackground="red")

        # Port Button
        self.port = BooleanVar()
        port_button = Checkbutton(self,
                                  text="Ports",
                                  variable=self.port,
                                  width=10)
        port_button.grid(row=1, column=3)
        port_button.config(anchor=W, activebackground="orange")

        # Host Name Button
        self.host = BooleanVar()
        host_name_button = Checkbutton(self,
                                       text="Host Name",
                                       variable=self.host,
                                       width=10)
        host_name_button.grid(row=1, column=3, sticky=S)
        host_name_button.config(anchor=W, activebackground="yellow")

        # Gateway Button
        self.gateway = BooleanVar()
        gateway_btn = Checkbutton(self,
                                  text="Gateway",
                                  variable=self.gateway,
                                  width=10)
        gateway_btn.grid(row=2, column=3, sticky=N)
        gateway_btn.config(anchor=W, activebackground="green")

        # Services Button
        self.service = BooleanVar()
        service_btn = Checkbutton(self,
                                  text="Services",
                                  variable=self.service,
                                  width=10)
        service_btn.grid(row=2, column=3)
        service_btn.config(anchor=W, activebackground="blue")

        # Starting IP label
        ip_label = Label(self, text="Starting IP:  ")
        ip_label.grid(row=5, column=0, pady=1, padx=3, sticky=W)
        self.ip_from = Entry(self, width=15)
        self.ip_from.insert(0, start_ip)
        self.ip_from.grid(row=5, column=0, pady=1, padx=3, sticky=E)

        # Ending IP label
        ip_label_two = Label(self, text="Ending IP:  ")
        ip_label_two.grid(row=5, column=1, pady=1, padx=5, sticky=W)
        self.ip_to = Entry(self, width=15)
        self.ip_to.insert(0, end_ip)
        self.ip_to.grid(row=5, column=1, pady=1, padx=5, sticky=E)

        # Starting Port Label
        port_label = Label(self, text="Starting Port:  ")
        port_label.grid(row=5, column=0, pady=3, padx=5, sticky=S + W)
        self.port_from = Entry(self, width=15)
        self.port_from.insert(0, 0)
        self.port_from.grid(row=5, column=0, pady=1, padx=5, sticky=S + E)

        # Ending Port Label
        port_label_two = Label(self, text="Ending Port:  ")
        port_label_two.grid(row=5, column=1, pady=3, padx=5, sticky=S + W)
        self.port_to = Entry(self, width=15)
        self.port_to.insert(0, 1025)
        self.port_to.grid(row=5, column=1, pady=1, padx=5, sticky=S + E)

        # Scan Me
        self_scan_button = Button(self,
                                  text="Scan Me",
                                  command=lambda: self.onClick(1),
                                  width=33)
        self_scan_button.grid(row=6, column=1, sticky=N)

        # Scan near me Button
        scan_other_button = Button(self,
                                   text="Scan Near Me",
                                   width=33,
                                   command=lambda: self.onClick(2))
        scan_other_button.grid(row=6, column=0, pady=1, sticky=N)

        # Clear button
        clear_button = Button(self,
                              text="Clear text",
                              command=self.clear_text,
                              width=12)
        clear_button.grid(row=6, column=3, pady=1, sticky=N)

        # Progress Bar
        self.label_scanning = Progressbar(self, orient=HORIZONTAL, length=175)
        self.label_scanning.grid(row=6,
                                 column=0,
                                 columnspan=4,
                                 padx=7,
                                 pady=7,
                                 sticky=E + S + W)
        self.label_scanning.config(mode="determinate")

    # Clear what is in the text box.
    def clear_text(self):
        self.area.delete(0.0, 'end')
        # empty my lists.
        my_ports[:] = []
        ip_address_up[:] = []
        target_host_name[:] = []
        target_port_up[:] = []

    # On click methods for scan me and scan others.
    def onClick(self, button_id):

        if button_id == 1:

            # Check to see if host button is marked
            if self.host.get() == 1:
                message = my_host_name()
                self.area.insert(0.0, message, ("warning"))
                self.area.tag_configure("warning", foreground="blue")

            # Check to see if ports button is marked
            if self.port.get() == 1:
                # Check port entry widgets.
                if self.port_from:
                    if self.port_to:
                        # Get the user input
                        starting_port = self.port_from.get()
                        ending_port = self.port_to.get()
                        message, total = scan_my_ports(int(starting_port),
                                                       int(ending_port))
                        for i in message:
                            new_message = "My TCP " + i + "\n"
                            self.area.insert(0.0, new_message, ("ports"))
                            #self.area.tag_configure("ports", foreground = "green")

                    time = "The TCP port scan completed in: " + str(
                        total) + "\n"
                    self.area.insert(0.0, time, ("timing"))
                    self.area.tag_configure("timing", foreground="red")
                else:
                    self.area.insert(0.0, "No valid ports specified.")

            # Check to see if IP button is marked
            if self.ip.get() == 1:
                message = my_ip()
                self.area.insert(0.0, message)

            # Check if gateway button is marked.
            if self.gateway.get() == 1:
                message = my_gateway()
                self.area.insert(0.0, message)

            # Check if service button is marked.
            if self.service.get() == 1:
                message, time = scan_my_services()
                for i in message:
                    new_message = i + "\n"
                    self.area.insert(0.0, new_message)
                new_time = "The local scan completed in: " + str(time) + "\n"
                self.area.insert(0.0.new_time, ("timing"))
                self.area.tag_configure("timing", foreground="red")

        # If Scan other button is clicked.
        elif button_id == 2:

            # Check other IP's
            if self.ip.get() == 1:
                # Check the entry widgets.
                if self.ip_from:
                    if self.ip_to:
                        # Get the ranges from the entry widgets
                        starting_ipv4_address = self.ip_from.get()
                        ending_ipv4_address = self.ip_to.get()

                        # Pass the values from the entry widgets into the function to scan nearby IP addresses.
                        message, time = ping_ip_other(starting_ipv4_address,
                                                      ending_ipv4_address)
                        if message:
                            for i in message:
                                new_message = "The address:     {:>15} {:>15}".format(
                                    i, "is UP\n")
                                self.area.insert(0.0, new_message)

                        total_time = "Range scanned: " + str(
                            starting_ipv4_address) + " to " + str(
                                ending_ipv4_address
                            ) + "\n" + "The IP scan completed in:  " + str(
                                time) + "\n"
                        self.area.insert(0.0, total_time, ("timing"))
                        self.area.tag_configure("timing", foreground="red")

                else:
                    self.area.insert(0.0, "No Ip range is specified.")

            # Check others Ports
            if self.port.get() == 1:
                # Check port entry widgets.
                if self.port_from:
                    if self.port_to:
                        # Get the user input
                        starting_port = self.port_from.get()
                        ending_port = self.port_to.get()

                        message, time = scan_ports_other(
                            int(starting_port), int(ending_port))
                        if message:
                            for i in message:
                                new_msg = "The " + i + "\n"
                                self.area.insert(0.0, new_msg)
                        else:
                            new_msg = "Must scan nearby IP addresses first.\n"

                    total_time = "TCP Port scan completed in: " + str(
                        time) + "\n"
                    self.area.insert(0.0, total_time, ("timing"))
                    self.area.tag_configure("timing", foreground="red")

                else:
                    self.area.insert(0.0, "No Port range specified.")

            # Check other host names. Based on IP's scanned.
            if self.host.get() == 1:
                message, time = scan_host_other(ip_address_up)
                # Check that IP's of other computers were collected
                if message:
                    for i in message:
                        new_message = "Host name: " + str(i) + "\n"
                        self.area.insert(0.0, new_message)

                else:
                    new_msg = "Must scan nearby IP addresses first. \n"
                    self.area.insert(0.0, new_msg)

                total = "The host scan completed in: " + str(time) + "\n"
                self.area.insert(0.0, total, ("timing"))
                self.area.tag_configure("timing", foreground="red")

            # Check gateway return the gateway of the host machine again.
            if self.gateway.get() == 1:
                message = "\n" + str(my_gateway())
                self.area.insert(0.0, message)

            # Check what services are running on which IP and port.
            if self.service.get() == 1:
                message, time = services_other()
                if message:
                    for i in message:
                        new_message = i + "\n"
                        self.area.insert(0.0, new_message)

                else:
                    new_msg = "The IP addresses and ports must be scanned first."
                    self.area.insert(0.0, new_msg)

                new_time = "The service scan completed in: " + str(time) + "\n"
                self.area.insert(0.0, new_time, ("timing"))
                self.area.tag_configure("timing", foreground="red")

        else:
            pass
class RecordFrame(MyFrame):

    def __init__(self, parent):
        MyFrame.__init__(self, parent, 'Parametrize', (100,0))

        self.record_options = DataDumper.load_json_data(Constants.CONFIG_PATH)['record_options']
        self.record_time.set_value(self.record_options['duration'])
        self.thread = None

    def init_ui(self):
        MyFrame.init_ui(self)

        self.columnconfigure(0, weight=2, minsize=150)
        self.columnconfigure(1, weight=3, minsize=100)

        self.file_name      = TextEntry(self, 'Recorded file name')
        self.record_time    = TextEntry(self, 'Record time')
        self.progress_bar   = Progressbar(self, orient='horizontal', mode='determinate')

        self.progress_bar.grid(columnspan=2, sticky='NESW')

        Button(self, text='Record', command=self.threaded_record).grid(columnspan=2, sticky='NESW')

    def threaded_record(self):
        if self.thread == None or not self.thread.isAlive():
            self.thread = threading.Thread(target=self.record)
            self.thread.start()

    def record(self):

        frequency = int(self.record_options['frequency'])
        record_time = int(self.record_time.get_value())

        format = pyaudio.paInt16
        n_channels = 2
        chunk = 1024
        output_filename = Constants.RAW_FILES_PATH + self.file_name.get_value() + '.wav'

        splitted = self.file_name.get_value().split('/')
        if len(splitted) > 1:
            splitted = splitted[:-1]
            acc = Constants.RAW_FILES_PATH
            for el in splitted:
                acc += el + '/'
                if not os.path.isdir(acc):
                    os.mkdir(acc)

        audio = pyaudio.PyAudio()

        stream = audio.open(format=format, channels=n_channels,
                        rate=frequency, input=True,
                        frames_per_buffer=chunk)

        frames = []
        progress_step = 100. / int(frequency / chunk * record_time)


        for i in range(0, int(frequency / chunk * record_time)):
            data = stream.read(chunk)
            frames.append(data)
            self.progress_bar.step(progress_step)

        stream.stop_stream()
        stream.close()
        audio.terminate()

        waveFile = wave.open(output_filename, 'wb')
        waveFile.setnchannels(n_channels)
        waveFile.setsampwidth(audio.get_sample_size(format))
        waveFile.setframerate(frequency)
        waveFile.writeframes(b''.join(frames))
        waveFile.close()

        tkMessageBox.showinfo('Info', 'Finished recording')
        self.progress_bar.step(-100)
Ejemplo n.º 27
0
class InterfaceGauche(LabelFrame):
    """Left frame of the GUI, giving the buttons and the current price and winner"""
    def __init__(self, tk_frame, police, **kwargs):
        LabelFrame.__init__(self, tk_frame, text="Tirage", font=police, **kwargs)
        self.waiting_time = 10

        self.message = Label(self, text="Appuyez sur le bouton pour lancer le tirage", font=police)
        self.message.grid(column=0, row=0, columnspan=2)

        self.bouton_quitter = Button(self, text="Quitter", command=self.quit, font=police)
        self.bouton_quitter.grid(column=0, row=1, pady=10)

        self.bouton_cliquer = Button(self, text="Lancer!", fg="red",
                                     command=self.click, font=police)
        self.bouton_cliquer.grid(column=1, row=1)

        self.message_price = Label(self, text="Tirage pour:", font=police)
        self.price = Label(self, text='', bg="white", width=40, height=1, font=police)
        self.message_price.grid(column=0, row=3)
        self.price.grid(column=1, row=3, columnspan=1, padx=10, pady=10)

        self.message_name = Label(self, text="Le gagnant est:", font=police)
        self.name = Label(self, text="", bg="white", width=40, height=1, font=police)
        self.message_name.grid(column=0, row=4)
        self.name.grid(column=1, row=4, columnspan=1, pady=10)
        
        self.parent_name = self.winfo_parent()
        self.parent = self._nametowidget(self.parent_name)

        # Part waiting time
        self.interval = Label(self, text="Intervalle entre tirages (s)", font=police)
        self.interval.grid(column=0, row=6, columnspan=1, pady=10)
        self.v = StringVar()
        self.v.set(self.waiting_time)
        self.interval_length = Entry(self, textvariable=self.v,  width=5, justify=CENTER, font=police)
        self.interval_length.grid(column=1, row=6, columnspan=1)
        self.progress_bar = Progressbar(self, length=300)
        self.progress_bar.grid(column=0, row=8, columnspan=2, pady=10)
        self.nb_players_text = Label(self, text="Nombre de joueurs", font=police)
        self.nb_players_text.grid(column=0, row=10, columnspan=1, pady=10)
        self.nb_players = Label(self, text="0", font=police)
        self.nb_players.grid(column=1, row=10, columnspan=1, pady=10)
        self.nb_prices_text = Label(self, text="Nombre de prix restants", font=police)
        self.nb_prices_text.grid(column=0, row=11, columnspan=1, pady=10)
        self.nb_prices = Label(self, text="0", font=police)
        self.nb_prices.grid(column=1, row=11, columnspan=1, pady=10)

        # police=tkFont.Font(self, size=12)#, family='Courier')
        # self.config(, font=police)
        # for i in range(5):
        # self.grid_rowconfigure(2, weight=1)
        # self.grid_rowconfigure(5, weight=1)
        # self.grid_rowconfigure(7, weight=1)
        # self.grid_rowconfigure(9, weight=1)
        for i in range(2):
            self.grid_columnconfigure(i, weight=1)

    def click(self):
        """When click is selected, the tombola starts"""
        try:
            self.waiting_time = int(self.v.get())
        except ValueError:
            showerror("Error", "L'intervalle doit être un nombre")
            return
        self.progress_bar['maximum'] = self.waiting_time+0.01
        self.interval_length.config(state=DISABLED)
        self.parent.draw_tombola(self.waiting_time)

        if not self.parent.list_prices:
            self.bouton_cliquer.config(state=DISABLED)
            self.price["text"] = "Tous les lots ont été tirés"
            self.name["text"] = ""
            self.update()
            
    def update_nb_players(self):        
        self.nb_players["text"] = len(self.parent.list_names)
        self.nb_players.update()
        
    def update_nb_prices(self):        
        self.nb_prices["text"] = len(self.parent.list_prices)
        self.nb_prices.update()
Ejemplo n.º 28
0
class TkSynthWindow(Frame):

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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