class CopilotInnerFrame(CopilotBaseFrame): def __init__(self, master, config): super(CopilotInnerFrame, self).__init__(master, config) if config.full_screen: self._make_full(master) self.master.grid_rowconfigure(1, weight=1) self.master.grid_columnconfigure(1, weight=1) self._create_header() self._sb = Scrollbar(self._master, orient=VERTICAL) self._sb.grid(row=1, column=3, sticky='nse') self._next_hidden = False def _cmd_back(self): self._master.destroy() def _create_header(self): self.back_btn = Button( self._master, text='< Back', command=self._cmd_back ) self.back_btn.grid(row=0, column=0, sticky='w') self._frame_lbl = Label( self.master, text='', anchor='center', font=self._config.item_font ) self._frame_lbl.grid(row=0, column=1, sticky='ew') self._next_btn = Button( self.master, text='Next >' ) self._next_btn.grid(row=0, column=2, sticky='e') def _hide_next(self): if not self._next_hidden: self._next_btn.grid_remove() self._next_hidden = True def _show_next(self): if self._next_hidden: self._next_btn.grid(row=0, column=2, sticky='e') self._next_hidden = False
class CopilotInnerFrame(CopilotBaseFrame): def __init__(self, master, config): super(CopilotInnerFrame, self).__init__(master, config) if config.full_screen: self._make_full(master) self.master.grid_rowconfigure(1, weight=1) self.master.grid_columnconfigure(1, weight=1) self._create_header() self._sb = Scrollbar(self._master, orient=VERTICAL) self._sb.grid(row=1, column=3, sticky='nse') self._next_hidden = False def _cmd_back(self): self._master.destroy() def _create_header(self): self.back_btn = Button(self._master, text='< Back', command=self._cmd_back) self.back_btn.grid(row=0, column=0, sticky='w') self._frame_lbl = Label(self.master, text='', anchor='center', font=self._config.item_font) self._frame_lbl.grid(row=0, column=1, sticky='ew') self._next_btn = Button(self.master, text='Next >') self._next_btn.grid(row=0, column=2, sticky='e') def _hide_next(self): if not self._next_hidden: self._next_btn.grid_remove() self._next_hidden = True def _show_next(self): if self._next_hidden: self._next_btn.grid(row=0, column=2, sticky='e') self._next_hidden = False
class Playback(Module): ''' Module to handle playback of audio and video files. ''' def __init__(self, app): self.app = app self.current = None if AUDIO_LIBS_INSTALLED: info( ' - initializing module: Audio' ) self.sfile = None self.p = pyaudio.PyAudio() self.currentInterval = None self.started = False self.paused = False self.sync = threading.Event() self.stoprequest = threading.Event() # widget management #self.frame = Frame(self.app.BOTTOM) self.frame = Frame(self.app.LEFT)#, pady=7) self.header = Header(self.frame, text="Playback") self.playBtn = Button(self.frame, text="⏯", command=self.playpauseAV, state='disabled', takefocus=0) # NOTE: not currently appearing self.app.bind('<space>', self.playpauseAV ) self.app.bind('<Escape>', self.stopAV ) if VIDEO_LIBS_INSTALLED: info( ' - initializing module: Video' ) self.app.bind('<space>', self.playpauseAV ) self.app.bind('<Escape>', self.stopAV ) self.grid() self.reset() def update(self): ''' don't change the audio file when we change frames ''' pass def reset(self): ''' try to load an audio file ''' if AUDIO_LIBS_INSTALLED: self.current = None audioFallbacks = [ '.wav', '.flac', '.ogg', '.mp3' ] for codec in audioFallbacks: if self.loadAudio( codec ) == True: self.playBtn.config( state='normal' ) return def loadAudio(self, codec): ''' load an audio file with a specific codec ''' audiofile = self.app.Data.getFileLevel( codec ) if audiofile != None: try: audiofile = self.app.Data.unrelativize(audiofile) self.sfile = AudioSegment.from_file( audiofile ) self.current = audiofile self.duration = len(self.sfile)/1000.0 return True except Exception as e: error('Unable to load audio file: `%s`' % audiofile, e) return False def playpauseAV(self, event): ''' ''' # debug(self.started, self.paused, '1858') if self.started == False or self.currentInterval != self.app.TextGrid.selectedItem: #if we haven't started playing or we're in a new interval #reset monitoring variables self.currentInterval = self.app.TextGrid.selectedItem self.started = False self.paused = False if self.app.TextGrid.selectedItem: start, end = self.app.TextGrid.getMinMaxTime() else: start = self.app.TextGrid.start end = self.app.TextGrid.end # if VIDEO_LIBS_INSTALLED and AUDIO_LIBS_INSTALLED: # self.readyVideo() # self.readyAudio(start, end) # self.playAudio() # elif AUDIO_LIBS_INSTALLED: # self.readyAudio(start, end) # self.playAudio() # elif VIDEO_LIBS_INSTALLED: # self.readyVideo() # self.dicomframeQ = queue.Queue() # for i in range(len(self.pngs)): # self.dicomframeQ.put(self.pngs[i]) # self.playVideoNoAudio() if self.app.Dicom.isLoaded(): self.readyVideo() if AUDIO_LIBS_INSTALLED: self.readyAudio(start, end) self.playAudio() elif self.app.Dicom.isLoaded(): self.dicomframeQ = queue.Queue() for i in range(len(self.pngs)): self.dicomframeQ.put(self.pngs[i]) self.playVideoNoAudio() elif self.started == True: if self.paused == False: self.paused = True self.stream.stop_stream() else: self.paused = False self.playAudio() def readyAudio(self, start, end): ''' ''' #audio stuff start_idx = round(float(start)*1000) end_idx = round(float(end)*1000) self.flen = float(self.app.TextGrid.frame_len) fpb = 512 extrafs = (end_idx-start_idx)%fpb extrasecs = extrafs/self.sfile.frame_rate pad = AudioSegment.silent(duration=round(extrasecs*1000)) seg_nopad = self.sfile[start_idx:end_idx] self.seg = seg_nopad + pad # seg.append() self.audioframe = 0 # open stream using callback (3) self.stream = self.p.open(format=self.p.get_format_from_width(self.seg.sample_width), channels=self.seg.channels, rate=self.seg.frame_rate, frames_per_buffer=fpb, output=True, start=False, stream_callback=self.callback) # debug(self.seg.frame_count()/fpb, 'number of chunks') # debug(self.seg.frame_count()%fpb, 'last chunk size') # self.chunkcount = 0 def readyVideo(self): ''' ''' self.app.Trace.reset() tags = self.app.TextGrid.selectedItem[0].gettags(self.app.TextGrid.selectedItem[1]) framenums = [tag[5:] for tag in tags if tag[:5]=='frame'] self.framestart = int(framenums[0]) imgs = self.app.Dicom.getFrames(framenums) canvas = self.app.Dicom.zframe.canvas bbox = canvas.bbox(canvas.find_all()[0]) dim = (bbox[2] - bbox[0], bbox[3] - bbox[1]) self.pngs = [] traces = self.app.Data.getTopLevel('traces') file = self.app.Data.getCurrentFilename() l = util.CROSSHAIR_SELECT_RADIUS for frame, img in zip(framenums, imgs): img = img.resize(dim) draw = ImageDraw.Draw(img) for name in traces: color = traces[name]['color'] if file in traces[name]['files'] and frame in traces[name]['files'][file]: for pt in traces[name]['files'][file][frame]: x = int(pt['x'] * img.width) y = int(pt['y'] * img.height) draw.line((x-l, y, x+l, y), fill=color) draw.line((x, y-l, x, y+l), fill=color) del draw self.pngs.append(ImageTk.PhotoImage(img)) #video w/audio stuff self.dicomframe_timer = 0 self.dicomframe_num = 1 self.dicomframeQ = queue.Queue() self.dicomframeQ.put(self.pngs[0]) #put now, because audio callback puts frames when audio segments end # for i in range(len(self.pngs)): # self.dicomframeQ.put(self.pngs[i]) def callback(self, in_data, frame_count, time_info, status): ''' Called by pyaudio stream. Gets chunks of audio ready for playing With video capabilities, also updates video frame information ''' # self.sync.clear() # self.chunkcount+=1 data = b''.join([self.seg.get_frame(i) for i in range(self.audioframe, self.audioframe+frame_count)]) # debug(len(data), 'line 1960') self.audioframe+=frame_count if self.app.Dicom.isLoaded(): #check & update video frame canvas = self.app.Dicom.zframe.canvas callbacklen = frame_count/self.seg.frame_rate self.dicomframe_timer += callbacklen #go to next frame if self.dicomframe_timer % self.flen != self.dicomframe_timer and self.dicomframe_num < len(self.pngs): floor = math.floor(self.dicomframe_timer/self.flen) # debug(floor, 'line 1961') self.dicomframe_timer = self.dicomframe_timer-self.flen*floor if floor > 1: for i in range(floor-1): # debug(self.dicomframe_num+self.framestart+i, 'putting frame into Q') if self.dicomframe_num+i < len(self.pngs): self.dicomframeQ.put(self.pngs[self.dicomframe_num+i]) else: self.dicomframeQ.put(self.pngs[self.dicomframe_num]) # self.sync.set() self.dicomframe_num+=floor # debug(self.dicomframe_num, len(self.pngs), 'line 1968') # else: #stop video loop if self.dicomframe_num >= len(self.pngs): self.stoprequest.set() return (data, pyaudio.paContinue) def playAudio(self): self.stream.start_stream() self.started = True if self.app.Dicom.isLoaded(): self.playVideoWithAudio() else: pass #write a loop that keeps audio playing # stop stream (6) if self.stoprequest.is_set(): self.stopAV() # self.stream.stop_stream() # if self.stoprequest.is_set(): # self.stream.close() # self.started = False # debug(self.chunkcount) # close PyAudio (7) # self.p.terminate() # NOTE: needs to be removed in order to play multiple audio files in a row def playVideoWithAudio(self): ''' ''' # self.sync.wait() if self.paused == True: return canvas = self.app.Dicom.zframe.canvas # debug(self.dicomframeQ.qsize(),'line 1991') try: pic = self.dicomframeQ.get(timeout=.5) canvas.itemconfig(canvas.find_all()[0] , image=pic ) # canvas.lift(pic) # canvas.img = pic canvas.update() except Exception as e: error(e) # debug(pic, 'displayed') # debug(self.dicomframe_num+self.framestart, 'displayed') if not self.stoprequest.is_set() or not self.dicomframeQ.empty(): #should this if be at the top? self.playVideoWithAudio() # canvas.after(10, self.playVideoWithAudio) def playVideoNoAudio(self): ''' ''' canvas = self.app.Dicom.zframe.canvas # pic = self.dicomframeQ.get() pic = self.dicomframeQ.get(block=False) canvas.itemconfig( canvas.find_all()[0], image=pic ) canvas.update() if not self.dicomframeQ.empty() and self.stoprequest.is_set() == False: #should this if be at the top? self.playVideoNoAudio() def stopAV(self,event=None): self.stoprequest.set() if AUDIO_LIBS_INSTALLED: self.stream.stop_stream() self.stream.close() self.started = False self.paused = False self.app.framesJumpTo() self.stoprequest.clear() def grid(self): ''' grid widgets ''' self.frame.grid( row=8 ) self.header.grid() self.playBtn.grid() def grid_remove(self): ''' remove widgets from grid ''' self.frame.grid_remove() self.header.grid_remove() self.playBtn.grid_remove()
class StreamFrame(Frame): def __init__(self, master): super(StreamFrame, self).__init__(master) self.root = master # check if user has saved the training sentiment analyzers pol_checkfile = os.path.exists('files/sa_polarity.pickle') subj_checkfile = os.path.exists('files/sa_subjectivity.pickle') if not (pol_checkfile and subj_checkfile): # if we cant find the SA files # These frames will hold the widgets nofiles_frm = Frame( self ) # this for the the warning message and the back and exit buttons nofiles_frm.grid(row=3, column=0, pady=5) exit_frm = Frame(self) # exit frame, contains back and exit button exit_frm.grid(row=4, column=0, pady=5) message = "SA files not found." read_write.log_message("[WARN] (frames.StreamFrame) : " + message) message += "\nClick Start Training first to train the NLTK classifiers." Label(nofiles_frm, text=message).grid(row=0, column=0, padx=10, pady=5) self.mng_stream_btn = Button( nofiles_frm, text="Start Stream") # ignore this, if there are no tweets # Build the widgets for nofiles_frm self.back_btn = Button(exit_frm, text="Back") self.back_btn.grid(row=1, column=1, ipadx=5, ipady=3, pady=15) self.exit_btn = Button(exit_frm, text="Exit", command=self.safe_exit) self.exit_btn.grid(row=1, column=3, ipadx=5, ipady=3, padx=15, pady=10) else: # These frames will hold the widgets label_frm = Frame(self) # this for the label and entry label_frm.grid(row=0, column=2, padx=10, pady=10, ipady=20, ipadx=20) # Frame for keywords self.keywords_frm = Frame( self ) # this will be hidden until user wants to see previous keywords self.keywords_frm.grid(row=0, column=3, rowspan=3, pady=15) # Build the widgets for label_frm Label(label_frm, text="Keyword:").grid(row=0, column=0, padx=20) self.keyword_entry = Entry(label_frm, width=30) self.keyword_entry.grid(row=0, column=1, columnspan=3) # Build the widgets for button_frm self.mng_stream_btn = Button( label_frm, text="Start Stream") # this will change from start to stop self.mng_stream_btn.grid(row=1, column=1, ipadx=5, ipady=3, pady=20) self.pause_stream_btn = Button( label_frm, text="Pause Stream") # if user starts stream, show this button self.pause_stream_btn.grid(row=1, column=3, ipadx=5, ipady=3, padx=10, pady=20) self.pause_stream_btn.grid_remove() # Build the widgets for keywords_frm self.manage_keywords_btn = Button( self.keywords_frm, command=self.show_keywords, text=">>>") # this will change into "<<<" when user clicks it self.manage_keywords_btn.grid(row=0, column=0, ipadx=5, ipady=3, padx=10) # Build the widgets for exit_frm self.back_btn = Button(label_frm, text="Back") self.back_btn.grid(row=2, column=1, ipadx=5, ipady=3, pady=15) self.exit_btn = Button(label_frm, text="Exit", command=self.safe_exit) self.exit_btn.grid(row=2, column=3, ipadx=5, ipady=3, padx=15, pady=10) # this method creates a new list box and populates it with the data from keywords.json def show_keywords(self): # first re-configure the button to show the desired text and change the command into hiding method self.manage_keywords_btn.config(text="<<<", command=self.hide_keywords) self.previous_keywords = read_write.read_keywords( ) # get any previous keywords # if there are keywords and the list is not empty if len(self.previous_keywords) > 0: # build the list box self.keyword_lb = Listbox(self.keywords_frm, height=10) self.keyword_lb.grid(column=1, row=0, pady=10, padx=5, sticky=(N, S, E, W)) # add a binding method self.keyword_lb.bind('<Double-1>', self.select_keyword) # and add the OK button. This happens here, because we don'w want a button without a list box self.select_keyword_btn = Button(self.keywords_frm, text="OK", command=self.select_keyword) self.select_keyword_btn.grid(row=3, column=1, ipady=3, ipadx=5, pady=10) # adding the keywords to the list box counter = 0 for keyword in self.previous_keywords: self.keyword_lb.insert(counter, keyword) counter += 1 # Colorize alternating lines of the listbox for i in range(0, len(self.previous_keywords), 2): self.keyword_lb.itemconfigure(i, background='#f0f0ff') # this method changes the button again and it is called to hide the list box def hide_keywords(self): self.manage_keywords_btn.config(text=">>>", command=self.show_keywords) try: # this may result to an error, because we can call hide_keywords before we initialize # the list box. This happening if no keywords are present in keywords.json self.keyword_lb.destroy() self.select_keyword_btn.destroy() except AttributeError: pass def select_keyword(self, *args): idxs = self.keyword_lb.curselection() if len(idxs) == 1: idx = int(idxs[0]) name = self.previous_keywords[idx] self.keyword_entry.delete(0, "end") self.keyword_entry.insert(0, name) def safe_exit(self): x = messagebox.askyesno(title="Exit", message="Are you sure you want to exit?", icon="question") if x: stream_util.stream_controller.stop() read_write.log_message("[INFO]" + stream_util.LOG_NAME + "Exiting...") self.root.destroy()
class CodeStructure(BaseWidget): def __init__(self, master, manager): BaseWidget.__init__(self, master, 'Code structure', style='border.TFrame') self.rowconfigure(1, weight=1) self.columnconfigure(0, weight=1) self._manager = manager header = Frame(self) header.columnconfigure(0, weight=1) self._close_btn = Button(header, style='close.TButton', padding=0, command=lambda: self.visible.set(False)) self._close_btn.grid(row=0, column=1) self.filename = Label(header, padding=(4, 0)) self.filename.grid(row=0, column=0, sticky='w') self.codetree = CodeTree(self) self._sx = AutoHideScrollbar(self, orient='horizontal', command=self.codetree.xview) self._sy = AutoHideScrollbar(self, orient='vertical', command=self.codetree.yview) self.goto_frame = Frame(self) Label(self.goto_frame, text='Go to:').pack(side='left') self.goto_entry = AutoCompleteCombobox2(self.goto_frame, completevalues=[]) self.goto_entry.pack(side='left', fill='x', expand=True, pady=4, padx=4) self._goto_index = 0 self.codetree.configure(xscrollcommand=self._sx.set, yscrollcommand=self._sy.set) header.grid(row=0, columnspan=2, sticky='we') self.codetree.grid(row=1, column=0, sticky='ewns') self._sx.grid(row=2, column=0, sticky='ew') self._sy.grid(row=1, column=1, sticky='ns') Frame(self, style='separator.TFrame', height=1).grid(row=3, column=0, columnspan=2, sticky='ew') self.goto_frame.grid(row=4, column=0, columnspan=2, sticky='nsew') self.set_callback = self.codetree.set_callback self.goto_entry.bind('<Return>', self.goto) self.goto_entry.bind('<<ComboboxSelected>>', self.goto) self.goto_entry.bind('<Key>', self._reset_goto) @property def manager(self): return self._manager @manager.setter def manager(self, new_manager): if CONFIG.get("General", "layout") in ["vertical", "horizontal2"]: self.configure(style='TFrame') self._close_btn.grid_remove() else: self.configure(style='border.TFrame') self._close_btn.grid() if self.visible.get(): try: self._manager.forget(self) except TclError: pass self._manager = new_manager self.show() else: self._manager = new_manager def _reset_goto(self, event): self._goto_index = 0 def focus_set(self): self.goto_entry.focus_set() def hide(self): try: layout = CONFIG.get("General", "layout") if layout in ["vertical", "horizontal2"]: self.manager.hide(self) else: # save layout old = CONFIG.get("Layout", layout).split() w = self.master.winfo_width() pos = '%.3f' % (self.master.sashpos(0)/w) CONFIG.set("Layout", layout, f"{pos} {old[1]}") CONFIG.save() self.manager.forget(self) except TclError: pass def show(self): layout = CONFIG.get("General", "layout") if layout in ["vertical", "horizontal2"]: self.manager.add(self, text=self.name) self.manager.select(self) else: self.manager.insert(0, self, weight=1) w = self.master.winfo_width() pos = int(float(CONFIG.get("Layout", layout).split()[0]) * w) self.master.sashpos(0, pos) def _visibility_trace(self, *args): visible = self.visible.get() if visible: self.show() else: self.hide() CONFIG.set('Code structure', 'visible', str(visible)) CONFIG.save() def get_cells(self): return self.codetree.cells def clear(self, event=None): self.codetree.delete(*self.codetree.get_children()) self.filename.configure(text='') def populate(self, title, text): reset = self.filename.cget('text') != title self.filename.configure(text=title) self._sx.timer = self._sx.threshold + 1 self._sy.timer = self._sy.threshold + 1 try: names = list(self.codetree.populate(text, reset)) except TclError: logging.exception('CodeStructure Error') self.codetree.delete(*self.codetree.get_children()) return names.sort() self.goto_entry.delete(0, "end") self.goto_entry.set_completion_list(names) self.event_generate('<<Populate>>') def goto(self, event): name = self.goto_entry.get() res = self.codetree.tag_has(name) if res: if self._goto_index >= len(res): self._goto_index = 0 self.codetree.see(res[self._goto_index]) self.codetree.selection_remove(*self.codetree.selection()) self.codetree.selection_set(res[self._goto_index]) self._goto_index += 1
class Main(Frame): def __init__(self): super().__init__(root) self.init_main() def init_main(self): Style().configure("TButton", padding=(0, 5, 0, 5), font='serif 10') self.columnconfigure(0, pad=3) self.columnconfigure(1, pad=3) self.columnconfigure(2, pad=3) self.columnconfigure(3, pad=3) self.rowconfigure(0, pad=3) self.rowconfigure(1, pad=3) self.rowconfigure(2, pad=3) self.rowconfigure(3, pad=3) self.rowconfigure(4, pad=3) self.equation = StringVar() self.var = IntVar() self.var.set(1) self.equation.set('enter the expression') self.entry = Entry(self, justify="right", textvariable=self.equation) self.entry.grid(row=0, columnspan=4, sticky=W + E) rad_base = Radiobutton(self, text="Simple", variable=self.var, value=1, command=self.selected) rad_base.grid(row=1, columnspan=2) rad_ex = Radiobutton(self, text="Extended", variable=self.var, value=2, command=self.selected) rad_ex.grid(row=1, column=2, columnspan=2) cls = Button(self, text="Cls", command=self.cls) cls.grid(row=2, column=0) bck = Button(self, text="Back", command=self.back) bck.grid(row=2, column=1) lbl = Button(self, command=lambda: self.equation.set(":)")) lbl.grid(row=2, column=2) clo = Button(self, text="Close", command=quit) clo.grid(row=2, column=3) sev = Button(self, text="7", command=lambda: self.press(7)) sev.grid(row=3, column=0) eig = Button(self, text="8", command=lambda: self.press(8)) eig.grid(row=3, column=1) nin = Button(self, text="9", command=lambda: self.press(9)) nin.grid(row=3, column=2) div = Button(self, text="/", command=lambda: self.press("/")) div.grid(row=3, column=3) fou = Button(self, text="4", command=lambda: self.press(4)) fou.grid(row=4, column=0) fiv = Button(self, text="5", command=lambda: self.press(5)) fiv.grid(row=4, column=1) six = Button(self, text="6", command=lambda: self.press(6)) six.grid(row=4, column=2) mul = Button(self, text="*", command=lambda: self.press("*")) mul.grid(row=4, column=3) one = Button(self, text="1", command=lambda: self.press(1)) one.grid(row=5, column=0) two = Button(self, text="2", command=lambda: self.press(2)) two.grid(row=5, column=1) thr = Button(self, text="3", command=lambda: self.press(3)) thr.grid(row=5, column=2) mns = Button(self, text="-", command=lambda: self.press("-")) mns.grid(row=5, column=3) zer = Button(self, text="0", command=lambda: self.press(0)) zer.grid(row=6, column=0) dot = Button(self, text=".", command=lambda: self.press(".")) dot.grid(row=6, column=1) equ = Button(self, text="=", command=self.equal) equ.grid(row=6, column=2) pls = Button(self, text="+", command=lambda: self.press("+")) pls.grid(row=6, column=3) self.btn_1 = Button(self, text="sin", command=lambda: self.sin()) self.btn_1.grid_remove() self.btn_2 = Button(self, text="cos", command=lambda: self.cos()) self.btn_2.grid_remove() self.btn_3 = Button(self, text="tan", command=lambda: self.tan()) self.btn_3.grid_remove() self.btn_4 = Button(self, text="log", command=lambda: self.log()) self.btn_4.grid_remove() self.btn_5 = Button(self, text="ln", command=lambda: self.ln()) self.btn_5.grid_remove() self.pack() def press(self, num): global expression expression += str(num) self.equation.set(expression) def equal(self): try: global expression total = str(eval(expression)) self.equation.set(total) expression = "" except: self.equation.set('error') expression = "" def cls(self): global expression expression = "" self.equation.set("") def back(self): global expression expression = expression[:-1] self.equation.set(expression) def selected(event): global val_get val_get = int(event.var.get()) if val_get == 1: event.btn_1.grid_remove() event.btn_2.grid_remove() event.btn_3.grid_remove() event.btn_4.grid_remove() event.btn_5.grid_remove() elif val_get == 2: event.btn_1.grid(row=2, column=4) event.btn_2.grid(row=3, column=4) event.btn_3.grid(row=4, column=4) event.btn_4.grid(row=5, column=4) event.btn_5.grid(row=6, column=4) event.entry.grid(row=0, columnspan=5, sticky=W + E) def sin(self): global expression expression = math.sin(float(expression)) self.equation.set(float(expression)) def cos(self): global expression expression = math.cos(float(expression)) self.equation.set(float(expression)) def tan(self): global expression expression = math.tan(float(expression)) self.equation.set(float(expression)) def log(self): global expression expression = math.log(float(expression)) self.equation.set(float(expression)) def ln(self): global expression expression = math.log1p(float(expression)) self.equation.set(float(expression))
class EuchreApp(Tk): def __init__(self, title, controller, user_player): self.user_player = user_player Tk.__init__(self) self.title(title) self.centerWindow() self.w = Frame(self) self.w.pack(fill=BOTH, expand=1) for x in range(15): self.w.columnconfigure(x, weight=1) self.w.rowconfigure(3, weight=1) self.w.rowconfigure(6, weight=1) self.w.rowconfigure(7, weight=1) self.w.rowconfigure(8, weight=1) self.w.rowconfigure(11, weight=1) self.lblTitle = Label(self.w, text="Euchre") self.lblTitle.grid(row=0, column=5, columnspan=5) # Center Table self.btnDeck = Button(self.w, text="Deck", state="disabled") self.btnDeck.grid(row=4, column=5, rowspan=5, columnspan=2, sticky=N+S+E+W) self.lblTrump = Label(self.w, text="Trump: ") self.lblTrump.grid(row=4, column=7, columnspan=3) self.lblCurrentPlayer = Label(self.w, text="Current Player: ") self.lblCurrentPlayer.grid(row=5, column=7, columnspan=3) self.btnP1CardPlayed = Button(self.w, state="disabled") self.btnP1CardPlayed.grid(row=8, column=8, sticky=N+S+E+W) self.btnP2CardPlayed = Button(self.w, state="disabled") self.btnP2CardPlayed.grid(row=7, column=7, sticky=N+S+E+W) self.btnP3CardPlayed = Button(self.w, state="disabled") self.btnP3CardPlayed.grid(row=6, column=8, sticky=N+S+E+W) self.btnP4CardPlayed = Button(self.w, state="disabled") self.btnP4CardPlayed.grid(row=7, column=9, sticky=N+S+E+W) self.btnNewHand = Button(self.w, text="New Hand", command=lambda: controller.restart_trick()) self.btnNewHand.grid(row=7, column=8, sticky=N+S+E+W) self.btnDeal = Button(self.w, text="Deal", command=lambda:controller.deal()) self.btnDeal.grid(row=4, column=7, rowspan=5, columnspan=3, sticky=N+S+E+W) def player_choose_card_callback_factory(player, card): return lambda: controller.player_choose_card(player, card) # Player 1 hand self.lblPlayer1Title = Label(self.w, text=("You" if user_player else "Player 1")) self.lblPlayer1Title.grid(row=9, column=5, columnspan=5) self.lblPlayer1Points = Label(self.w, text=("Points: 0")) self.lblPlayer1Points.grid(row=10, column=5, columnspan=5) self.btnPlayer1Cards = [] for i in range(5): self.btnPlayer1Cards.append(Button(self.w, command=player_choose_card_callback_factory(0, i), state="disabled")) self.btnPlayer1Cards[i].grid(row=11, column=5+i, sticky=N+S+E+W) # Player 2 hand self.lblPlayer2Title = Label(self.w, text="Player 2") self.lblPlayer2Title.grid(row=4, column=0, columnspan=5) self.lblPlayer2Points = Label(self.w, text="Points: 0") self.lblPlayer2Points.grid(row=5, column=0, columnspan=5) self.btnPlayer2Cards = [] for i in range(5): self.btnPlayer2Cards.append(Button(self.w, command=player_choose_card_callback_factory(1, i), state="disabled")) self.btnPlayer2Cards[i].grid(row=6, column=0+i, rowspan=3, sticky=N+S+E+W) # Player 3 hand self.lblPlayer3Title = Label(self.w, text="Player 3") self.lblPlayer3Title.grid(row=1, column=5, columnspan=5) self.lblPlayer3Points = Label(self.w, text="Points: 0") self.lblPlayer3Points.grid(row=2, column=5, columnspan=5) self.btnPlayer3Cards = [] for i in range(5): self.btnPlayer3Cards.append(Button(self.w, command=player_choose_card_callback_factory(2, i), state="disabled")) self.btnPlayer3Cards[i].grid(row=3, column=5+i, sticky=N+S+E+W) # Player 4 hand self.lblPlayer4Title = Label(self.w, text="Player 4") self.lblPlayer4Title.grid(row=4, column=10, columnspan=5) self.lblPlayer4Points = Label(self.w, text="Points: 0") self.lblPlayer4Points.grid(row=5, column=10, columnspan=5) self.btnPlayer4Cards = [] for i in range(5): self.btnPlayer4Cards.append(Button(self.w, command=player_choose_card_callback_factory(3, i), state="disabled")) self.btnPlayer4Cards[i].grid(row=6, column=10+i, rowspan=3, sticky=N+S+E+W) def centerWindow(self): w = 1000 h = 600 sw = self.winfo_screenwidth() sh = self.winfo_screenheight() x = (sw - w)/2 y = (sh - h)/2 self.geometry('%dx%d+%d+%d' % (w, h, x, y)) def restart_trick(self, dealer): self.btnNewHand.grid_remove() self.btnDeal.grid() self.lblPlayer1Title.config(text=("You" if self.user_player else "Player 1") + (": dealer" if dealer % 4 == 0 else "")) self.lblPlayer2Title.config(text="Player 2" + (": dealer" if dealer % 4 == 1 else "")) self.lblPlayer3Title.config(text="Player 3" + (": dealer" if dealer % 4 == 2 else "")) self.lblPlayer4Title.config(text="Player 4" + (": dealer" if dealer % 4 == 3 else "")) self.lblPlayer1Points.config(text="Points: 0") self.lblPlayer2Points.config(text="Points: 0") self.lblPlayer3Points.config(text="Points: 0") self.lblPlayer4Points.config(text="Points: 0") for c in self.btnPlayer1Cards: c.config(text="") for c in self.btnPlayer2Cards: c.config(text="") for c in self.btnPlayer3Cards: c.config(text="") for c in self.btnPlayer4Cards: c.config(text="") def deal(self, trump): self.btnDeal.grid_remove() self.lblTrump.config(text="Trump: " + str(trump)) self.new_round() def new_round(self): self.btnP1CardPlayed.config(text="") self.btnP1CardPlayed.grid_remove() self.btnP2CardPlayed.config(text="") self.btnP2CardPlayed.grid_remove() self.btnP3CardPlayed.config(text="") self.btnP3CardPlayed.grid_remove() self.btnP4CardPlayed.config(text="") self.btnP4CardPlayed.grid_remove() def update_player_hand(self, player, player_num): if player_num == 0: for c in self.btnPlayer1Cards: c.config(text="") c.grid_remove() for i, c in enumerate(player.hand.cards): self.btnPlayer1Cards[i].grid() self.btnPlayer1Cards[i].config(text=str(c.rank) + str(c.suit)) elif player_num == 1: for c in self.btnPlayer2Cards: c.config(text="") c.grid_remove() for i, c in enumerate(player.hand.cards): self.btnPlayer2Cards[i].grid() if self.user_player: self.btnPlayer2Cards[i].config(text="???") else: self.btnPlayer2Cards[i].config(text=str(c.rank) + str(c.suit)) elif player_num == 2: for c in self.btnPlayer3Cards: c.config(text="") c.grid_remove() for i, c in enumerate(player.hand.cards): self.btnPlayer3Cards[i].grid() if self.user_player: self.btnPlayer3Cards[i].config(text="???") else: self.btnPlayer3Cards[i].config(text=str(c.rank) + str(c.suit)) elif player_num == 3: for c in self.btnPlayer4Cards: c.config(text="") c.grid_remove() for i, c in enumerate(player.hand.cards): self.btnPlayer4Cards[i].grid() if self.user_player: self.btnPlayer4Cards[i].config(text="???") else: self.btnPlayer4Cards[i].config(text=str(c.rank) + str(c.suit)) self.update_player_points(player, player_num) def update_player_points(self, player, player_num): if player_num == 0: self.lblPlayer1Points.config(text="Points: " + str(player.points)) elif player_num == 1: self.lblPlayer2Points.config(text="Points: " + str(player.points)) elif player_num == 2: self.lblPlayer3Points.config(text="Points: " + str(player.points)) elif player_num == 3: self.lblPlayer4Points.config(text="Points: " + str(player.points)) def activate_player_turn(self, player, player_num): if player_num == 0: for i, c in enumerate(player.hand.cards): if player.valid_cards[i]: self.btnPlayer1Cards[i].config(state="enabled") elif player_num == 1: for i, c in enumerate(player.hand.cards): if player.valid_cards[i]: self.btnPlayer2Cards[i].config(state="enabled") elif player_num == 2: for i, c in enumerate(player.hand.cards): if player.valid_cards[i]: self.btnPlayer3Cards[i].config(state="enabled") elif player_num == 3: for i, c in enumerate(player.hand.cards): if player.valid_cards[i]: self.btnPlayer4Cards[i].config(state="enabled") def deactivate_player_turn(self, player, player_num): if player_num == 0: for i, c in enumerate(player.hand.cards): self.btnPlayer1Cards[i].config(state="disabled") elif player_num == 1: for i, c in enumerate(player.hand.cards): self.btnPlayer2Cards[i].config(state="disabled") elif player_num == 2: for i, c in enumerate(player.hand.cards): self.btnPlayer3Cards[i].config(state="disabled") elif player_num == 3: for i, c in enumerate(player.hand.cards): self.btnPlayer4Cards[i].config(state="disabled") def update_current_player(self, player_num): self.lblCurrentPlayer.config(text="Current Player: " + str(player_num)) def player_play_card(self, player, player_num, card): self.update_player_hand(player, player_num) if player_num == 0: self.btnP1CardPlayed.grid() self.btnP1CardPlayed.config(text=str(card.rank)+str(card.suit)) elif player_num == 1: self.btnP2CardPlayed.grid() self.btnP2CardPlayed.config(text=str(card.rank)+str(card.suit)) elif player_num == 2: self.btnP3CardPlayed.grid() self.btnP3CardPlayed.config(text=str(card.rank)+str(card.suit)) elif player_num == 3: self.btnP4CardPlayed.grid() self.btnP4CardPlayed.config(text=str(card.rank)+str(card.suit)) def game_over(self): self.btnNewHand.grid()
class Control(Module): ''' This class provides a clean interface for managing Undo/Redo functionality. Implementation relies on storing two lists of actions as stacks, one for Undo and one for Redo. Calling Undo/Redo should pop the corresponding stack and execute the inverse of that action, pushing the inverse action to the other stack (so its inversion can also be executed). Note: both stacks get cleared on - change files - change frames - Dicom.resetZoom() ''' def __init__(self, app): info( ' - initializing module: Control' ) # reference to our main object containing other functionality managers self.app = app # initialize our stacks self.reset() # some images for the buttons # Source for icons: https://material.io/tools/icons/?style=outline # License: Apache Version 2.0 www.apache.org/licenses/LICENSE-2.0.txt data_copy = '''R0lGODlhGAAYAPAAAAAAAAAAACH5BAEAAAEALAAAAAAYABgAAAJHjI+pCe3/1oHUSdOunmDvHFTWBYrjUnbMuWIqAqEqCMdt+HI25yrVTZMEcT3NMPXJEZckJdKorCWbU2H0JqvKTBErl+XZFAAAOw''' data_paste = '''R0lGODlhGAAYAPAAAAAAAAAAACH5BAEAAAEALAAAAAAYABgAAAJBjI+pq+DAonlPToqza7rv9FlBeJCSOUJpd3EXm7piDKoi+nkqvnttPaMhUAzeiwJMapJDm8U44+kynCkmiM1qZwUAOw''' self.img_copy = PhotoImage(data=data_copy) self.img_paste = PhotoImage(data=data_paste) # bind Ctrl+z to UNDO and Ctrl+Shift+Z to REDO if util.get_platform() == 'Linux': self.app.bind('<Control-z>', self.undo ) self.app.bind('<Control-Z>', self.redo ) else: self.app.bind('<Command-z>', self.undo ) self.app.bind('<Command-Z>', self.redo ) # also make some buttons and bind them self.frame = Frame(self.app.LEFT)#, pady=7) self.frame.grid( row=5 ) self.header = Header(self.frame, text="Points") self.selectAllBtn = Button(self.frame, text='⬚', command=self.selectAll, takefocus=0, style="symbol.TButton", width=1.5) self.copyBtn = Button(self.frame, image=self.img_copy, command=self.copy, takefocus=0) # FIXME: add tooltip for "Copy" self.pasteBtn = Button(self.frame, image=self.img_paste, command=self.paste, takefocus=0) # FIXME: add tooltip for "Paste" self.undoBtn = Button(self.frame, text='↶', command=self.undo, takefocus=0, width=1.5, style="symbol.TButton") self.redoBtn = Button(self.frame, text='↷', command=self.redo, takefocus=0, width=1.5, style="symbol.TButton") self.updateButtons() def push(self, item): ''' add an item to the undo-stack and empty out the redo-stack ''' self.uStack.append( item ) self.rStack = [] self.updateButtons() def reset(self): ''' reset our stacks ''' self.uStack = [] # undo self.rStack = [] # redo def update(self): ''' changing files and changing frames should have the same effect ''' self.reset() def selectAll(self): self.app.Trace.selectAll() def copy(self): self.app.Trace.copy() def paste(self): self.app.Trace.paste() def undo(self, event=None): ''' perform the undo-ing ''' if len(self.uStack): item = self.uStack.pop() if item['type'] == 'add': chs = item['chs'] for ch in chs: self.app.Trace.remove( ch ) self.rStack.append({ 'type':'delete', 'chs':chs }) elif item['type'] == 'delete': chs = item['chs'] for ch in chs: ch.draw() self.rStack.append({ 'type':'add', 'chs':chs }) elif item['type'] == 'move': chs = item['chs'] coords = item['coords'] for i in range(len(chs)): chs[i].dragTo( coords[i] ) self.rStack.append({ 'type':'move', 'chs':chs, 'coords':coords }) elif item['type'] == 'recolor': oldColor = self.app.Trace.recolor( item['trace'], item['color'] ) self.rStack.append({ 'type':'recolor', 'trace':item['trace'], 'color':oldColor }) elif item['type'] == 'rename': self.app.Trace.renameTrace( newName=item['old'], oldName=item['new'] ) # this is backwards on purpose self.rStack.append({ 'type':'rename', 'old':item['old'], 'new':item['new'] }) else: error(item) raise NotImplementedError self.app.Trace.unselectAll() self.app.Trace.write() self.updateButtons() else: warn( 'Nothing to undo!' ) def redo(self, event=None): ''' perform the redo-ing ''' if len(self.rStack): item = self.rStack.pop() if item['type'] == 'add': chs = item['chs'] for ch in chs: self.app.Trace.remove( ch ) self.uStack.append({ 'type':'delete', 'chs':chs }) elif item['type'] == 'delete': chs = item['chs'] for ch in chs: ch.draw() self.uStack.append({ 'type':'add', 'chs':chs }) elif item['type'] == 'move': chs = item['chs'] coords = item['coords'] for i in range(len(chs)): chs[i].dragTo( coords[i] ) self.uStack.append({ 'type':'move', 'chs':chs, 'coords':coords }) elif item['type'] == 'recolor': oldColor = self.app.Trace.recolor( item['trace'], item['color'] ) self.uStack.append({ 'type':'recolor', 'trace':item['trace'], 'color':oldColor }) elif item['type'] == 'rename': self.app.Trace.renameTrace( newName=item['new'], oldName=item['old'] ) self.uStack.append({ 'type':'rename', 'old':item['old'], 'new':item['new'] }) else: error(item) raise NotImplementedError self.app.Trace.unselectAll() self.app.Trace.write() self.updateButtons() else: warn( 'Nothing to redo!' ) def updateButtons(self): ''' Don't allow clicking buttons that wrap empty stacks. However, users will still be able to access that functionality thru key bindings. ''' self.undoBtn['state'] = 'normal' if len(self.uStack) else 'disabled' self.redoBtn['state'] = 'normal' if len(self.rStack) else 'disabled' self.grid() def grid(self): ''' Grid button widgets ''' self.header.grid(row=0,column=0, columnspan=5) self.selectAllBtn.grid(row=1, column=0) self.copyBtn.grid(row=1, column=1, ipady=3) self.pasteBtn.grid(row=1, column=2, ipady=3) self.undoBtn.grid(row=1, column=3) self.redoBtn.grid(row=1, column=4) def grid_remove(self): ''' Remove button widgets from grid ''' self.undoBtn.grid_remove() self.redoBtn.grid_remove()
class Dicom(Module): def __init__(self, app): info(' - initializing module: Dicom') self.app = app if LIBS_INSTALLED: # grid load button self.frame_holder = Frame(self.app.LEFT) #, pady=7) self.frame_holder.grid(row=2) self.frame = Frame(self.frame_holder) self.frame.pack(expand=True) self.method = StringVar(self.app) self.mode = None self.reader = None # zoom buttons self.zbframe = Frame(self.app.LEFT) self.zbframe.grid(row=6, column=0) # zoom frame (contains our tracing canvas) self.zframe = ZoomFrame(self.app.RIGHT, 1.3, app) # zoom in, zoom out, reset zoom buttons #self.header = Header(self.zbframe, text="Zoom") self.zoomResetBtn = Button(self.zbframe, text='⊜', command=self.zoomReset, width=1.5, style="symbol.TButton", takefocus=0) #, pady=7 ) self.zoomInBtn = Button(self.zbframe, text='⊕', command=self.zoomIn, width=1.5, style="symbol.TButton", takefocus=0) self.zoomOutBtn = Button(self.zbframe, text='⊝', command=self.zoomOut, width=1.5, style="symbol.TButton", takefocus=0) # reset zoom keyboard shortcut if util.get_platform() == 'Linux': self.app.bind('<Control-0>', self.zoomReset) else: self.app.bind('<Command-0>', self.zoomReset) self.reset() self.grid() def zoomReset(self, fromButton=False): ''' reset zoom frame canvas and rebind it ''' if self.isLoaded(): # creates a new canvas object and we redraw everything to it self.zframe.resetCanvas() # self.zframe.canvas.bind('<Button-1>', self.app.onClickZoom ) # self.zframe.canvas.bind('<ButtonRelease-1>', self.app.onRelease ) # self.zframe.canvas.bind('<Motion>', self.app.onMotion ) # we want to go here only after a button press if fromButton: self.app.framesUpdate() def zoomIn(self): self.zframe.zoomIn() def zoomOut(self): self.zframe.zoomOut() def update(self, _frame=None): ''' change the image on the zoom frame ''' if self.reader and self.reader.loaded: self.zframe.setImage(self.reader.getFrame(_frame or self.app.frame)) def load(self, event=None): ''' brings a dicom file into memory if it exists ''' if LIBS_INSTALLED: if self.reader and not self.reader.loaded: self.reader.load() self.app.frame = 1 self.update() self.loadBtn['state'] = 'disabled' def chooseMethod(self, event=None): if self.mode: cls = LABEL_TO_READER[self.mode][self.method.get()] if self.mode == 'dicom': dcm = self.app.Data.checkFileLevel('.dicom') if dcm: if cls == DicomPNGReader and self.app.Data.getFileLevel( 'processed'): self.reader = cls(dcm, self.app.Data.path) else: self.reader = cls(dcm) else: self.reader = None elif self.mode == 'ult': ult = self.app.Data.checkFileLevel('.ult') meta = self.app.Data.checkFileLevel('US.txt') if ult and meta: self.reader = cls(ult, meta) else: self.reader = None self.zframe.resetImageDimensions() if not self.reader: self.loadBtn['state'] = 'disabled' elif self.reader.loaded: self.loadBtn['state'] = 'disabled' self.update() else: self.loadBtn['state'] = 'normal' def isLoaded(self): return self.reader and self.reader.loaded def getFrames(self, framenums): return [self.reader.getFrame(int(x)) for x in framenums] def getFrameTimes(self): if self.reader: return self.reader.getFrameTimes() elif self.mode == 'dicom': rd = DicomReader( self.app.Data.unrelativize( self.app.Data.getFileLevel('.dicom'))) return rd.getFrameTimes() elif self.mode == 'ult': rd = ULTScanLineReader( self.app.Data.unrelativize(self.app.Data.getFileLevel('.ult')), self.app.Data.unrelativize( self.app.Data.getFileLevel('US.txt'))) return rd.getFrameTimes() else: return [0] def reset(self): ''' new files should default to not showing dicom unless it has already been processed ''' # hide frame navigation widgets # self.grid_remove() self.zframe.shown = False self.zframe.setImage(None) self.frame.destroy() self.frame = Frame(self.frame_holder) self.frame.pack(expand=True) self.reader = None if self.app.Data.getFileLevel('.dicom'): self.mode = 'dicom' elif self.app.Data.getFileLevel('.ult'): self.mode = 'ult' else: self.mode = None self.method.set('') options = [x.label for x in READERS[self.mode]] or ['[no ultrasound]'] self.methodMenu = OptionMenu(self.frame, self.method, '---', *options, command=self.chooseMethod) self.methodMenu.grid(row=0) self.loadBtn = Button(self.frame, text='Load frames', command=self.load, takefocus=0, state='disabled') self.loadBtn.grid(row=1) if len(READERS[self.mode]) == 1: self.method.set(options[0]) self.chooseMethod() def grid(self): ''' Grid frame navigation, zoom reset, and Control (Undo/Redo) widgets ''' self.app.framesHeader.grid(row=0) self.app.framesPrevBtn.grid(row=0, column=0) self.app.framesEntryText.grid(row=0, column=1) self.app.framesEntryBtn.grid(row=0, column=2) self.app.framesNextBtn.grid(row=0, column=3) #self.header.grid(row=0, column=0, columnspan=5) self.zoomInBtn.grid(row=0, column=3) self.zoomResetBtn.grid(row=0, column=2) self.zoomOutBtn.grid(row=0, column=1) self.app.Control.grid() def grid_remove(self): ''' Remove widgets from grid ''' self.app.framesHeader.grid_remove() self.app.framesPrevBtn.grid_remove() self.app.framesEntryText.grid_remove() self.app.framesEntryBtn.grid_remove() self.app.framesNextBtn.grid_remove() self.zoomInBtn.grid_remove() self.zoomResetBtn.grid_remove() self.zoomOutBtn.grid_remove() self.app.Control.grid_remove()