class Example(Frame): def __init__(self, master): Frame.__init__(self, master) self.dict = {'Asia': ['Japan', 'China', 'India'], 'Europe': ['Portugal', 'Switzerland', 'Ukraine']} self.var_a = StringVar(self) self.var_b = StringVar(self) self.var_a.trace('w', self.update_options) self.option_menu_a = OptionMenu(self, self.var_a, *self.dict.keys()) self.option_menu_a.pack(side="top") self.option_menu_a["width"] = 10 self.option_menu_b = OptionMenu(self, self.var_b, '') self.option_menu_b["width"] = 10 self.option_menu_b.pack(side="top") self.var_a.set('Asia') def update_options(self, *args): countries = self.dict[self.var_a.get()] self.var_b.set(countries[0]) menu = self.option_menu_b['menu'] menu.delete(0, 'end') for c in countries: menu.add_command(label=c, command=lambda x=c: self.var_b.set(x))
class DateWidget(Frame): """Gets a date from the user.""" def __init__(self, master): """Make boxes, register callbacks etc.""" Frame.__init__(self, master) self.label = Label(self, text="När är du född?") self.label.pack() self.entry_text = StringVar() self.entry_text.trace("w", lambda *args: self.onEntryChanged()) self.entry = Entry(self, width=date_entry_width, textvariable=self.entry_text) self.entry.insert(0, "ÅÅÅÅ-MM-DD") self.entry.pack(pady=small_pad) self.button = Button(self, text="Uppdatera", command=lambda: self.onDateChanged()) self.button.pack() self.entry.focus_set() self.entry.select_range(0, END) self.entry.bind("<Return>", lambda x: self.onDateChanged()) def setListener(self, pred_view): """Select whom to notify when a new date is entered.""" self.pred_view = pred_view def onDateChanged(self): """Notifies the PredictionWidget that the date has been changed.""" try: date = datetime.datetime.strptime(self.entry.get(), "%Y-%m-%d").date() self.pred_view.update(date) except ValueError: self.entry.configure(foreground="red") def onEntryChanged(self): """Reset the text color.""" self.entry.configure(foreground="")
class GuiGeneratorSelect(Frame): def __init__(self, parent, generators): Frame.__init__(self, parent) self.parent = parent self.pack() self._generators = generators self._generatorName = StringVar() self._generatorName.set(generators[0].getName()) self._generatorName.trace("w", self._switchSettings) self._generatorLbl = Label(self, text="Generator"); self._generatorLbl.pack(side=LEFT) param = (self, self._generatorName) + tuple(i.getName() for i in generators) self._generatorOpt = OptionMenu(*param) self._generatorOpt.pack(side=LEFT) self._switchSettings() def _switchSettings(self, *args): print("DBG: switch generator settings") for i in self._generators: if i.getName() == self._generatorName.get(): i.pack() self._generatorGui = i print("pack " + str(i.getName())) else: i.pack_forget() print("unpack " + str(i.getName())) def getCurrGeneratorGui(self): return self._generatorGui
def init_before_run(self, nb_models, coefficients): ''' See base class. ''' current_dmu = StringVar() current_dmu.trace('w', self.frame.on_dmu_change) self.current_dmu = current_dmu self.increment = 100 / (len(coefficients) * nb_models) self.frame.progress_bar['value'] = 0
class EntryTextHolder(Entry): def __init__(self, master=None): Entry.__init__(self, master) self._value = StringVar() self['textvariable'] = self._value self._value.trace('w', self._valuechanged) self.model = TextHolderModel(view=self) def _valuechanged(self, *args): self.model.text = self._value.get() #--- model --> view def update_text(self): text = self.model.text if text != self.get(): self.delete(0, 'end') self.insert(0, text)
class FileEditBar(Frame, object): def __init__(self, master, directory='.', filesettings=None, defaultname='*unknown{}', importhook=None, deletehook=None, projecthook=None, filecontenthook=None, selectfilehook=None, fileslisthook=None, updatehook=None, onchangehook=None): self.master = master Frame.__init__(self, master) self.selected_file = StringVar() self.selected_file.trace("w", self.select_file) self._dirty = False self._dirty_file_name = '' self._editor_dirty = False self.dir = directory self.fsettings = filesettings self.defaultname = defaultname # hooks self.import_hook = importhook self.delete_hook = deletehook self.save_project_hook = projecthook self.filecontent_hook = filecontenthook self.update_hook = updatehook self.select_file_hook = selectfilehook self.files_list_hook = fileslisthook self.onchange_hook = onchangehook row = 0 self.columnconfigure(1, weight=2) files = [] self.file_buffer = {} self.file_reload = True if len(files) == 0: files.append("") self.list_files = OptionMenu(*(self, self.selected_file) + tuple(files)) self.list_files.grid(row=row, column=1, sticky="NWE") # new file self.btn_newfile = Button(self, text='New', command=self.new_file) self.btn_newfile.grid(row=row, column=2, sticky="E") # import file self.btn_importfile = Button(self, text='Import', command=self.import_file) self.btn_importfile.grid(row=row, column=3, sticky="E") # delete file self.btn_delfile = Button(self, text='Delete', command=self.delete_file) self.btn_delfile.grid(row=row, column=4, sticky="E") # save button self.btn_update_file = Button(self, text='Save', command=self.save_file) self.btn_update_file.grid(row=row, column=6, sticky="E") # save as.. button self.btn_saveas_file = Button(self, text='Save as...', command=self.saveas_file) self.btn_saveas_file.grid(row=row, column=7, sticky="E") # editor row += 1 self.editor = SyntaxHighlightingText(self, change_hook=self.onchange_filecontent) self.editor.grid(row=row, column=1, columnspan=7, sticky="NWES") self.rowconfigure(row, weight=1) @property def dirty(self): return self._dirty or self.file_buffer != {} @dirty.setter def dirty(self, d): self._dirty = (d or self.file_buffer != {}) if self.onchange_hook: self.onchange_hook(dirty=self._dirty) def new_file(self): self.list_files['menu'].add_command(label=self.defaultname.format(self.fsettings.get('extension', '.mln')), command=_setit(self.selected_file, self.defaultname.format(self.fsettings.get('extension', '.mln')))) self.selected_file.set(self.defaultname.format(self.fsettings.get('extension', '.mln'))) self.file_buffer[self.defaultname.format(self.fsettings.get('extension', '.mln'))] = '' self.editor.delete("1.0", END) self.dirty = True def import_file(self): filename = askopenfilename(initialdir=self.dir, filetypes=self.fsettings.get('ftypes'), defaultextension=self.fsettings.get('extension', '.mln')) if filename: fpath, fname = ntpath.split(filename) self.dir = os.path.abspath(fpath) content = mlnpath(filename).content if self.import_hook is not None: self.import_hook(fname, content) self.update_file_choices() self.selected_file.set(fname) self.dirty = True def delete_file(self): fname = self.selected_file.get().strip() # remove element from project mlns and buffer if fname in self.file_buffer: del self.file_buffer[fname] if self.delete_hook is not None: self.delete_hook(fname) f = self.update_file_choices() # select first element from remaining list if f: self.list_files['menu'].invoke(0) else: self.selected_file.set('') self.editor.delete("1.0", END) self.dirty = True def save_all_files(self): current = self.selected_file.get().strip() for f in self.file_buffer: content = self.file_buffer[f] if f == current: content = self.editor.get("1.0", END).strip() if self.update_hook is not None: self.update_hook(f, f.strip('*'), content) # reset buffer, dirty flag for editor and update mln selections self.file_buffer.clear() self._editor_dirty = False self.update_file_choices() self.dirty = False if self.save_project_hook is not None: self.save_project_hook() def save_file(self): oldfname = self.selected_file.get().strip() if oldfname == self.defaultname.format(self.fsettings.get('extension', '.mln')): self.saveas_file() else: self.update_file(oldfname, new=oldfname.strip('*'), askoverwrite=False) def saveas_file(self): oldfname = self.selected_file.get().strip() res = tkinter.simpledialog.askstring('Save as', "Enter a filename", initialvalue=oldfname.strip('*')) if res is None: return elif res: if not res.endswith(self.fsettings.get('extension')): res = res + self.fsettings.get('extension') self.update_file(oldfname, new=res) def update_file(self, old, new=None, askoverwrite=True): success = 1 content = self.editor.get("1.0", END).strip() if self.update_hook is not None: success = self.update_hook(old.strip('*'), new, content, askoverwrite=askoverwrite) if success != -1: if old in self.file_buffer: del self.file_buffer[old] # reset dirty flag for editor and update mln selections self._editor_dirty = False self.update_file_choices() fn = new if new is not None and new != '' else old if new != '': self.selected_file.set(fn) self.dirty = False if self.save_project_hook is not None: self.save_project_hook() def select_file(self, *_): filename = self.selected_file.get().strip() self.dirty = True if filename is not None and filename != '': # filename is neither None nor empty if self._editor_dirty: # save current state to buffer before updating editor self.file_buffer[self._dirty_file_name] = self.editor.get("1.0", END).strip() self._editor_dirty = True if '*' in filename else False if not self.file_reload: self.file_reload = True return if '*' in filename:# is edited # load previously edited content from buffer instead of mln file in project content = self.file_buffer.get(filename, '').strip() self.editor.delete("1.0", END) content = content.replace("\r", "") self.editor.insert(INSERT, content) self._editor_dirty = True self._dirty_file_name = '*' + filename if '*' not in filename else filename return if self.files_list_hook is not None and self.filecontent_hook is not None: files = self.files_list_hook() if filename in files: # load content from mln file in project content = self.filecontent_hook(filename) self.editor.delete("1.0", END) content = content.replace("\r", "") self.editor.insert(INSERT, content) self._editor_dirty = False else: # should not happen self.editor.delete("1.0", END) self.list_files['menu'].delete(0, 'end') if self.select_file_hook is not None: self.select_file_hook() def update_file_choices(self): self.list_files['menu'].delete(0, 'end') files = [] if self.files_list_hook is not None: files = self.files_list_hook() new_files = sorted([i for i in files if '*'+i not in self.file_buffer] + list(self.file_buffer.keys())) for f in new_files: self.list_files['menu'].add_command(label=f, command=_setit(self.selected_file, f)) return new_files def onchange_filecontent(self, *_): if not self._editor_dirty: self._editor_dirty = True self.dirty = True self.file_reload = False # do not reload file, only change filename to *filename fname = self.selected_file.get().strip() fname = '*' + fname if '*' not in fname else fname self._dirty_file_name = fname self.file_buffer[self._dirty_file_name] = self.editor.get("1.0", END).strip() self.update_file_choices() self.selected_file.set(self._dirty_file_name) def clear(self, keep=False): self.file_buffer.clear() if not keep: self.editor.delete("1.0", END) self.dirty = False
def create_selection_menu(self, cb_on_select, *opts, always_trigger_onselect=False, no_destructure=False, pass_selection_to_callback=False): """ Quick way of creating a drop-down menu with a set of options and selection callbacks. :param cb_on_select: Menu item selection event callback :param opts: Menu options. These should be a list of two-element tuples where the first item is the label and the second is the corresponding value :param always_trigger_onselect: Whether the selection callback should be triggered even if an already-selected item was selected :param no_destructure: Whether option values should be destructured into the arguments of the callback :param pass_selection_to_callback: Whether or not to pass the selected value to the selection callback function :return: Getter function for the currently selected `value` (not label) """ options_dict = dict() selection_active = StringVar(self.root) selection_previous = StringVar(self.root) for (key, value) in opts: options_dict[key] = value menu = OptionMenu(self.options_frame, selection_active, *options_dict.keys()) def on_select(*args): """ Callback function for when a menu item is selected :param args: Ignored arguments. Just contains the modified variable :return: None """ # Check if a previously un-selected item was selected (or if the event should be processed anyway) if selection_active.get() != selection_previous.get( ) or always_trigger_onselect: selection_previous.set(selection_active.get()) # Call callback if one was specified if cb_on_select: if pass_selection_to_callback: # Attempt to destructure parameter as much as possible # This is just a lazy way of passing sets of arguments in less LOC if (not no_destructure) and dir( options_dict[selection_active.get( )]).__contains__("__iter__"): if type(options_dict[ selection_active.get()]) is dict: cb_on_select( **options_dict[selection_active.get()]) else: cb_on_select( *(options_dict[selection_active.get()])) else: cb_on_select(options_dict[selection_active.get()]) else: cb_on_select() # Set a callback for when variable changes value selection_active.trace("w", on_select) # Pack menu if a side as packed, else assume packing will be done elsewhere menu.pack(side="left") # Select a menu option. This also triggers an initial callback selection_active.set(opts[0][0]) # Return a getter function to the active *value* (not key) return lambda: options_dict[selection_active.get()]
class GuiApplication: def __init__(self): self.window = Tk() self.window.title(MAIN_TITLE) # this is so dumb if system() == 'Windows': with open('temp_icon.ico', 'wb') as temp_icon: temp_icon.write(base64.b64decode(ICON_WIN)) self.window.iconbitmap('temp_icon.ico') os.remove('temp_icon.ico') self.window.wm_title(MAIN_TITLE) #self.window.resizable(False, False) # stupid shit only happens on mac??? if system() == "Darwin": self.window.tk_setPalette(background="#e8e8e8") self.initialize_gui() def initialize_gui(self, initial_values=None): self.selections = {} self.combobox_selections = {} self.checkbox_text = {} self.main_frame = Frame(self.window) self.gridcontainer = Frame(self.main_frame) self.frames = { 'rom-settings': ttk.LabelFrame(self.gridcontainer, text="ROM Settings"), 'gameplay': ttk.LabelFrame(self.gridcontainer, text="Gameplay Settings"), 'aesthetics': ttk.LabelFrame(self.gridcontainer, text="Aesthetic Settings"), } self.frames['rom-settings'].pack(side=TOP, fill=X, padx=2, pady=2) self.frames['gameplay'].pack(side=LEFT, fill=BOTH, expand=True, anchor="w", padx=2, pady=2) self.frames['aesthetics'].pack(side=RIGHT, fill=BOTH, expand=True, anchor="w", padx=2, pady=2) #self.gridcontainer.add(self.frames['rom-settings'], text='ROM Options') #self.gridcontainer.add(self.frames['gameplay'], text='Gameplay Rules') #self.gridcontainer.add(self.frames['aesthetic'], text='Aesthetic Rules') self.add_rom_settings() self.add_settings_from_file() self.add_main_settings() self.gridcontainer.pack(expand=True, fill=BOTH, anchor="center", padx=5, pady=5) self.main_frame.pack(expand=True, fill=BOTH) self.window.update_idletasks() self.window.mainloop() def select_rom_input(self): input_rom = filedialog.askopenfilename(title="Select Input ROM", filetypes=[("ROM Files", (".z64", ".n64")), ("All Files", "*")]) self.selections['input_rom'].set(input_rom) #if input_rom != "": #if self.selections['output_rom'].get() == "": #path_parts = input_rom.split(".") #guessed_output_file = f'{".".join(path_parts[:-1])}.out.{path_parts[-1]}' #self.selections['output_rom'].set(guessed_output_file) def select_rom_output(self): output_suggestion = 'SM64_Randomizer.z64' current_input = self.selections['input_rom'].get() if current_input: path = Path(current_input) file = path.stem ext = path.suffix output_suggestion = f'{file}.out{ext}' output_int = 1 while os.path.exists(output_suggestion): file = ".".join(output_suggestion.split(".")[:-1]) ext = output_suggestion.split(".")[-1] output_suggestion = f'{file}.{output_int}.{ext}' output_rom = filedialog.asksaveasfilename( title="Select Output Path", filetypes=[("ROM Files", (".z64"))], #initialdir=self.selections["output_rom"], initialfile=output_suggestion) if output_rom != "": self.selections['output_rom'].set(output_rom) def toggle_checkbox_label(self, key): def trigger(): if bool(self.selections[key].get()): self.checkbox_text[key].set("Enabled") else: self.checkbox_text[key].set("Disabled") return trigger def set_random_seed(self): self.seed_entry.set(randint(0, 1e19)) def set_seed_as_num(self, *args): byte_entry = bytes(self.seed_entry.get(), 'utf8') self.selections['seed'].set( int.from_bytes(byte_entry, 'little', signed=False)) def check_validity(self): rom_file = self.selections['input_rom'].get() self.check_error = None if not len(rom_file): self.check_error = 'Please select a ROM-File first' return False if not os.path.isfile(rom_file): self.check_error = 'The selected ROM is invalid' return False out_file = self.selections['output_rom'].get() if not len(out_file): self.check_error = 'Please select an output path' return False return True def read_from_clipboard(self): data = pyperclip.paste() try: json_data = json.loads(data) except Exception: messagebox.showerror( title=MAIN_TITLE, message= f"Sorry, the settings in your clipboard are not valid. Please try again." ) return if json_data['version'] != __version__: messagebox.showerror( title=MAIN_TITLE, message= f"Sorry, the settings version do not match. Please ensure you're using the same version when copying the settings." ) return json_data["input_rom"] = self.selections['input_rom'].get() json_data["output_rom"] = self.selections['output_rom'].get() for (key, tkinter_var) in self.selections.items(): if key in json_data: tkinter_var.set(json_data[key]) self.seed_entry.set(json_data["seed"]) self.set_seed_as_num() self.pasteSettings.configure(text="Settings applied!") self.window.update() s = Timer( 2, lambda: self.pasteSettings.configure( text="Paste Settings from Clipboard")) s.start() def copy_to_clipboard(self): output = {"version": __version__} data = {key: var.get() for (key, var) in self.selections.items()} output.update(data) # this makes no sense for other people del output['input_rom'] del output['output_rom'] output['seed'] = self.seed_entry.get() pyperclip.copy(json.dumps(output)) self.copySettings.configure(text="Settings copied!") s = Timer( 2, lambda: self.copySettings.configure( text="Copy Settings to Clipboard")) s.start() def generate_rom(self): try: if not self.check_validity(): messagebox.showerror(title="ROM Generation Failed", message=self.check_error) return params = [] input_rom = None for (key, tkinter_var) in self.selections.items(): key_in_arg_format = f"--{key.replace('_', '-')}" if key == 'input_rom': input_rom = tkinter_var.get() elif key == 'output_rom': params.append('--out') params.append(tkinter_var.get()) elif isinstance(tkinter_var, BooleanVar): # boolean args work by adding the param or not if tkinter_var.get(): params.append(key_in_arg_format) elif isinstance(tkinter_var, StringVar): params.append(key_in_arg_format) params.append(quote(tkinter_var.get())) else: raise NotImplementedError( f'arg format for {type(tkinter_var)} is not implemented yet' ) args = [input_rom, *params] from Rom import ROM test_output = os.path.join(tempfile.gettempdir(), 'test_output.z64') try: with ROM(input_rom, test_output) as test_rom: test_rom.verify_header() except Exception as excp: messagebox.showerror( title="ROM Generation failed", message= f'Sorry, the specified ROM is not valid. Verification failed with error: {excp}' ) try: run_with_args(args) except Exception as err: messagebox.showerror( title="ROM Generation failed", message= f"Unfortunately, generation failed with error:\n {err}\nPlease submit this error to the projects github: https://github.com/andre-meyer/sm64-randomizer/issues" ) print(err) return rom_output = self.selections['output_rom'].get() (folder_containing_rom, filename_output) = os.path.split(rom_output) messagebox.showinfo( title="ROM Generation completed!", message= f"Your randomized ROM was created as \"{filename_output}\"! Have fun!" ) #if system() == "Windows": #subprocess.Popen('explorer /select,"' + rom_output.replace("/", "\\") + '"', shell=True) #else: #webbrowser.open("file:///" + folder_containing_rom) return True except Exception as excp: messagebox.showerror( title="ROM Generation failed", message= f'Sorry, ROM generation failed with error:\n {excp}\nPlease submit this error to the projects github: https://github.com/andre-meyer/sm64-randomizer/issues' ) def add_setting_field(self, field): master = self.frames[field['category']] optionFrame = Frame(master) key = field['name'] if field['type'] == 'checkbox': self.selections[key] = BooleanVar(optionFrame) checkboxField = ttk.Checkbutton(optionFrame, text=field['label'], variable=self.selections[key]) if 'help' in field: CreateToolTip(checkboxField, field['help']) checkboxField.pack(side=LEFT) elif field['type'] == 'select': optionLabel = ttk.Label(optionFrame, text=field['label']) optionLabel.pack(side=LEFT) if 'help' in field: CreateToolTip(optionLabel, field['help']) self.selections[key] = StringVar(optionFrame) self.combobox_selections[key] = StringVar(optionFrame) choice_dict = { option['label']: option['value'] for option in field['options'] } choice_dict_invert = { option['value']: option['label'] for option in field['options'] } self.selections[key].set(field['options'][0]['value']) optionsField = ttk.OptionMenu( optionFrame, self.combobox_selections[key], field['options'][0]['label'], *[option['label'] for option in field['options']], command=lambda *args, sel_key=key, choices=choice_dict: self. selections[sel_key].set(choices[self.combobox_selections[ sel_key].get()])) self.selections[key].trace( 'w', lambda *args, sel_key=key, choices=choice_dict_invert: self. combobox_selections[sel_key].set(choice_dict_invert[ self.selections[sel_key].get()])) optionsField.pack(side=LEFT, fill=X, expand=True) optionFrame.pack(side=TOP, padx=5, pady=(5, 1), fill=X) def add_settings_from_file(self): with open( os.path.join(application_path, 'Data', 'configurableParams.json'), 'r') as json_file: fields = json.loads(json_file.read()) for field in fields: self.add_setting_field(field) """ def add_gameplay_settings(self): self.add_setting_fields(gameplay_settings, self.frames['gameplay']) def add_aesthetic_settings(self): self.add_setting_fields(aesthetic_settings, self.frames['aesthetic']) """ def add_main_settings(self): buttonsFrame = Frame(self.main_frame, padx=5, pady=5, height=60) buttonsFrame.pack_propagate(0) generateButton = ttk.Button(buttonsFrame, text="Generate ROM", command=self.generate_rom, width=10) generateButton.pack(side=LEFT, fill=BOTH, expand=True) self.copySettings = ttk.Button(buttonsFrame, text="Copy Settings to Clipboard", command=self.copy_to_clipboard, width=20) self.copySettings.pack(side=LEFT, fill=BOTH, expand=True) self.pasteSettings = ttk.Button(buttonsFrame, text="Paste Settings from Clipboard", command=self.read_from_clipboard, width=30) self.pasteSettings.pack(side=LEFT, fill=BOTH, expand=True) buttonsFrame.pack(fill=X, anchor="center", side=BOTTOM) def add_rom_settings(self): inputFrame = Frame(self.frames['rom-settings']) self.seed_entry = StringVar() self.seed_entry.trace('w', self.set_seed_as_num) self.selections['seed'] = StringVar() self.set_random_seed() seedFrame = Frame(inputFrame) seedLabel = Label(seedFrame, text="Seed", width=10) seedLabel.pack(side=LEFT) seedEntry = Entry(seedFrame, textvariable=self.seed_entry) seedEntry.pack(side=LEFT, fill=BOTH, expand=True) seedRandom = ttk.Button(seedFrame, text='New', command=self.set_random_seed, width=15) seedRandom.pack(side=RIGHT) seedFrame.pack(side=TOP, fill=X, expand=True) self.selections['input_rom'] = StringVar() baseRomLabel = Label(inputFrame, text="Input ROM", width=10) baseRomLabel.pack(side=LEFT, padx=(0, 0)) baseRomEntry = Entry(inputFrame, textvariable=self.selections['input_rom']) baseRomEntry.pack(side=LEFT, fill=BOTH, expand=True) romSelectButton = ttk.Button(inputFrame, text='Select ROM', command=self.select_rom_input, width=15) romSelectButton.pack(side=RIGHT) inputFrame.pack(side=TOP, fill=X, expand=True) outputFrame = Frame(self.frames['rom-settings']) self.selections['output_rom'] = StringVar() outputPathLabel = Label(outputFrame, text="Output ROM", width=10) outputPathLabel.pack(side=LEFT, padx=(0, 0)) outputRomEntry = Entry(outputFrame, textvariable=self.selections['output_rom']) outputRomEntry.pack(side=LEFT, fill=BOTH, expand=True) outputSelectButton = ttk.Button(outputFrame, text='Select Output', command=self.select_rom_output, width=15) outputSelectButton.pack(side=RIGHT) outputFrame.pack(side=TOP, fill=X, expand=True)
class Card : def __init__(self,name="Nom monstre",att=1,pv=1,bonus=None,photo='',monster_type="unknown") : self.name=name self.att = att self.pv = pv if not bonus : bonus=[] # a cause du fonctionnement etrange de python pour les valeurs d arguments [] par defaut self.bonus=bonus self.is_spell=(pv<1) self.photofile=photo self.dumping_file = os.path.join("CardFiles",monster_type+"_monsters.sav") self.monster_type = monster_type #global all_monsters name=self.name.replace(" ","_") self.content=self # try : # self.image = image.load(os.path.join("Card",name+".png")) # except : # self.image=None def equivalentto(self,other) : return self==other def show(self) : pass def constructor(self) : return ('Card("'+self.name+'",'+str(self.att)+","+str(self.pv)+ ",["+",".join([p.constructor() for p in self.bonus])+"],"+ repr(self.photofile)+",'"+self.monster_type+"')") def takePlace(self,*ar1,**ars) : pass def addBonus(self,bonus) : self.bonus.append(bonus) def getCost(self) : if self.pv > 0 : cost=self.att/2.+self.pv/2.+sum([p.getCost(self) for p in self.bonus]) else : #print self.bonus #if self.bonus : #print self.bonus[0].getCost #print self.bonus[0].getCost() #if len(self.bonus)>1 : print "** anomalie **" S = 0 for p in self.bonus: if p.is_cost_alterator: S += p.getCost(self) else: S += p.getCost() cost=S# +0.5*(len(self.bonus)-1): why? if cost < 0: cost = 0 if hasattr(self,"cost") and self.cost!=None : # pour les monstres du save, l attribut cost est None print ("cout=",cost," so ",int(floor(cost))) self.cost.set(int(floor(cost))) self.getStars() return cost def getStars(self): stars = sum([p.getStars() for p in self.bonus]) if stars>2 : stars=(stars-1)*2 if stars<0 : stars=0 if hasattr(self,"stars") and self.stars != None : # pour les monstres du save, l attribut stars existe = None self.stars.set('* '*stars) #print "stars=",stars return stars def getDescription(self): for b in reversed(self.bonus) : try : b.getDescription() except Exception : self.bonus.remove(b) return self.name +" ("+str(self.att)+" "+str(self.pv)+'\n'*bool(self.bonus)+'\n'.join( [b.getDescription() for b in self.bonus]) +" )" def getInlineDescription(self): for b in reversed(self.bonus) : try : b.getInlineDescription() except Exception : self.bonus.remove(b) return self.name +" ("+str(self.att)+" "+str(self.pv)+' '.join( [b.getInlineDescription() for b in self.bonus]) +" )" def postAndSave(self,*args): if self.name=="nom monstre" or self.name=="change name" or self.name in Card.blocked_creature : self.name="change name" self.refreshWidget() return if not self.verifyBonus() : return self.deleteCreature(self.name) temp=self.category.get() pygame.init() fenetre=self.card_win.master self.card_win.pack_forget() self.save(None) done=False while not done : for event in pygame.event.get() : if event.type == pygame.QUIT : done=True pygame.display.quit() self = Card("nom monstre",1,1) #card.pack_forget() self.initWidget(fenetre) self.category.set(temp) self.setFile("dummy_arg") def verifyBonus(self) : nb=[b.__class__.__name__ for b in self.bonus] if len(set(nb))!=len(nb) : showinfo("Not Allowed","You can't have twice the same bonus") return False for b1,b2 in [("Insaisissable","Provocation"),("Insaisissable","Inciblable"),("Errant","Incarnation"), ("Camouflage","Provocation"),("Camouflage","ChaqueTour"),("NePeutPasAttaquer","ALaPlaceDeLAttaque"), ("NePeutPasAttaquer","NePeutPasAttaquerLesHeros"),("NePeutPasAttaquerLesHeros","ALaPlaceDeLAttaque"), ("GardienDeVie","QuandIlEstBlesse"),("Charge","NePeutPasRisposter"),("Furie","ALaPlaceDeLAttaque"), ("NePeutPasRiposter","NePeutPasAttaquer"),("NePeutPasRiposter","CoutReduit"),("CriDeGuerre","Incarnation"), ("Charge","CriDeGuerrre"),("Insaisissable","InsensibleALaMagie"),("Charge","Errant"),("CriDeGuerre","Errant"), ("Errant","RaleDAgonie"),("AttaqueADistance","AvecAttaque"),("Errant","AuDebutDuProchainTour"), ("BonusParEnnemi","Determine"),("QuandIlEstBlesse","Incassable"),("Souffrant","QuandIlEstBlesse") ] : if b1 in nb and b2 in nb : showinfo("Not Allowed","You can't have this combination of powers: {0} and {1}".format(b1,b2)) return False total=self.constructor() if "QuandUnAllieEstTue" in nb and (("Spell.Invocation" in total) or ("CopieMain" in total) or ("PlaceCarteDansMain" in total)): showinfo("Not Allowed","You can't have anything to do with Invocation or card creation if you have QuandUnAllieEstTue") return False return True def save(self,*args): if (self.name in Card.blocked_creature) : return for b in self.bonus : # on veut que la plainte maudite soit en dernier if b.__class__.__name__=="PlainteMaudite" : self.bonus.remove(b) self.bonus.append(b) break image = self.createImage() print ("apres createImage") name=self.name.replace(" ","_") pygame.image.save(image,"Cards/"+name+".png") print ("save image done") # now new monster loaded_monsters=readMonsters(self.dumping_file) #print "Monsters from file = ",file_monsters #remove_widget(self) loaded_monsters[self.name] = self #print "Monsters from file (after) = ",file_monsters global all_monsters all_monsters.update(loaded_monsters) #print "window reinit done" with open(self.dumping_file,"wb") as savefile : savefile.write(bytes("\n".join([m.constructor() for k,m in sorted(loaded_monsters.items())]),'UTF-8')) # with open(self.dumping_file+".old","rb") as filepickle : # print "now in file", self.dumping_file,":",pickle.load(filepickle).keys() # filepickle.close() with open(os.path.join("CardFiles","all_monsters.sav"), "wb" ) as f : f.write(bytes("\n".join([m.constructor() for m in all_monsters.values()]),'UTF-8')) recupfile=os.path.join("CardFiles","recup_monsters.sav") if (not os.path.isfile(recupfile)) or len(all_monsters)>=len(open(recupfile,'r').readlines()): with open(recupfile, "wb" ) as f : f.write(bytes("\n".join([m.constructor() for k,m in sorted(all_monsters.items())]),'UTF-8')) print ("SAVED in all_monsters.sav and recup_monsters.sav") else: print ("WARNING : Recup monster file bigger than all monsters file") def initWidget(self,fenetre) : #print "init" self.card_win = PanedWindow(fenetre, orient=VERTICAL) fenetre.child=self self.refreshWidget() def Open(self,*args) : print ("open monster ", self.opening.get()) #deck_with_card = self.deck_check(self.opening.get()) creature = Card.monster_list[self.opening.get()] if not ( creature.name in Card.blocked_creature) : self.card_win.pack_forget() fenetre=self.card_win.master #for i in Card.monster_list.keys() : # print i, Card.monster_list[i].getInlineDescription() self = Card.monster_list[self.opening.get()] print (self.name +" loaded") if self.pv<1 : self.is_spell=True else : self.is_spell=False #self.card_win.pack_forget() for b in self.bonus: b.parent = self.bonus b.card = self self.initWidget(fenetre) else: showinfo("Sorry","You can't open this monsters because he comes from the campaign.") def clicDelete(self,*args) : #self.card_win.pack_forget() #fenetre=self.card_win.master """ for i in all_monsters.keys() : print i, all_monsters[i].getInlineDescription() """ creature= self.delete.get() if creature in Card.blocked_creature : print ("not possible : creature in campaign") self.delete.set('delete') return if askyesno('Beware!', 'Confirm the deletion of '+creature+"?"): self.deleteCreature(creature) self.card_win.pack_forget() #self.initWidget(fenetre) self.setFile(*args) def deleteCreature(self,creature) : dm=None global all_monsters if not creature in all_monsters : print (creature," is not in all_monsters") try : fm=os.path.join("CardFiles",self.category.get()+"_monsters.sav") dm = readMonsters(fm) except: print ("error reading file ",fm) else : print ("delete monster ", creature) try : fm = os.path.join("CardFiles",(all_monsters[creature].monster_type)+"_monsters.sav") dm = readMonsters(fm) except: print ("ERROR : no type for ",creature, " or read error") del all_monsters[creature] fall=os.path.join("CardFiles","all_monsters.sav") with open(fall,"wb") as savefile : savefile.write(bytes("\n".join([m.constructor() for m in all_monsters.values()]), 'UTF-8')) print ("deletion of monster ", creature, "done") shutil.copyfile(fall,"CardFiles/recup_monsters.sav") if dm and creature in dm : del dm[creature] with open(fm,"wb") as savefile : print('dmv',dm.values()) savefile.write(bytes("\n".join([m.constructor() for m in dm.values()]), 'UTF-8')) print ("deletion of monster ", creature, " in ",fm," done" ) else : print (creature," not found in dedicated file") def choosePhoto(self,*args) : from tkinter.filedialog import askopenfilename #Tk().withdraw() # we don't want a full GUI, so keep the root window from appearing filename = askopenfilename(defaultextension=".gif",filetypes=[ ("image",("*.jpg", "*.gif","*.png")),('PNG file','*.png'),('Jpg file','*.jpg'),('GIF file','*.gif')]) # show an "Open" dialog box and return the path to the selected file if filename: import os.path chem=os.path.dirname(os.path.realpath(__file__)).replace('\\','/')+'/' #print chem if chem in filename : filename=filename.replace(chem,'') print ("filename modif",filename) try : pilImage = Image.open(filename) PhotoImage(pilImage,master=None) #ImageTk.PhotoImage(monimage) self.photofile=filename print ("photo choosen !") except Exception : print ("echec ouverture image") raise self.refreshWidget() def setFile(self,*args): self.dumping_file = os.path.join("CardFiles",self.category.get()+"_monsters.sav") print ("Change dumping file to ",self.dumping_file) self.monster_type = self.category.get() Card.monster_list=readMonsters(self.dumping_file) #from cardPowers import * self.refreshWidget() def refreshWidget(self) : #print "refresh" self.card_win.pack_forget() import unicodedata #Card window self.card_win = PanedWindow(self.card_win.master, orient=VERTICAL) self.card_win.pack(side=TOP, expand=True, fill=BOTH, pady=2, padx=2) #Create the name zone name_zone=PanedWindow(self.card_win, orient=HORIZONTAL) name = StringVar() name.set(self.name) def modifName(*args) : try : assert('"' not in name.get()) name.get().encode('ascii') except Exception as e: print ("error on name") name.set(self.name) return old = self.name in Card.blocked_creature self.name=name.get() if old or self.name in Card.blocked_creature : self.refreshWidget() name.trace("w", modifName) name_wid=Entry(name_zone, width=30,textvariable=name) name_wid.pack() name_zone.add(name_wid) #Create the cost ad star stringvar #print int(floor(self.getCost())) self.cost=StringVar() self.stars=StringVar() cost_wid=Label(None, textvariable=self.cost, background='red',width=5, anchor=W) star_wid=Label(None, textvariable=self.stars, background='blue', anchor=E) self.cost.set(str(int(floor(self.getCost())))) self.stars.set("*"*self.getStars()) #Add them in name zone name_zone.add(cost_wid) name_zone.add(star_wid) #Create an Image Zone image_zone=Button(self.card_win, command=self.choosePhoto) if hasattr(self,"photofile") and self.photofile : print ("Image: ",self.photofile) try : pilImage=Image.open(self.photofile) img=PhotoImage(pilImage,master=image_zone) except : decomp=self.photofile.split('/') for i in range(1,6) : try : fname="/".join(decomp[-i:]) print ("try to open",fname) pilImage = Image.open(fname) img=PhotoImage(pilImage,master=image_zone) self.photofile=fname break except : self.photofile=None if self.photofile : w, h = img.width(), img.height() print('wh',w,h) if h>400 : print("reduction") img=PhotoImage(pilImage.resize((w//2,h//2), Image.ANTIALIAS),master=image_zone) image_zone=Button(self.card_win,image=img, command=self.choosePhoto) image_zone.image=img #image_zone.configure(image=image_zone.image,width=50,height=50,compound=RIGHT) #image_zone.pack() #print "IMAGE CHANGED" else : from os import path fname=self.name.replace(" ","_") if path.isfile("Cards/"+fname+".png") : image_zone.config(text='image can be taken from\n'+"Cards/"+fname+".png",background='white',anchor=CENTER) else : image_zone.config(text='clic to choose image',background='white',anchor=CENTER) #image_zone.pack() # POWER ZONE power_zone=PanedWindow(self.card_win, orient=VERTICAL) #fenetre=self.card_win.master def removePowerCreator(px) : def removePower(*args) : #print 'avant',list_pow self.bonus.remove(px) #print 'apres',list_pow #self.card_win.pack_forget() self.refreshWidget() return removePower for p in self.bonus : powline = PanedWindow(self.card_win, orient=HORIZONTAL) pow_wid=p.initWidget(powline) powline.add(pow_wid) removepow=Button(powline, text="X", command=removePowerCreator(p), anchor=E) removepow.pack() powline.add(removepow) power_zone.add(powline) def addPower(*args) : if addBonus.get()!= "add bonus": name=addBonus.get() else: name=add_cost_alteration.get() print ("added :",name) import CardPowers self.bonus+=[eval('CardPowers.'+name+'()')] self.bonus[-1].parent=self.bonus self.bonus[-1].card=self #self.card_win.pack_forget() self.refreshWidget() #Add bonus Option menu addBonus = StringVar(power_zone) addBonus.set("add bonus") # default value if not self.pv: addBonus_wid = Spell.getSpellMenu(power_zone, addBonus) else: addBonus_wid = getBonusMenu(power_zone, addBonus) addBonus.trace('w', addPower) if self.pv>0 or len(self.bonus)==0 or all([b.is_cost_alterator for b in self.bonus]): addBonus_wid.pack() #Add this to power zone power_zone.add(addBonus_wid) #Create save zone save_zone = PanedWindow(self.card_win, orient=HORIZONTAL) if self.monster_type != "all" and not(self.name in Card.blocked_creature) : save_wid = Button(save_zone, text="Save", command=self.postAndSave) elif self.monster_type != "all" : save_wid = Button(save_zone, text="creature in campaign", command=None) else: save_wid = Button(save_zone, text="nead type", command=None) save_wid.pack() #Create the open button save_zone.pack() if Card.monster_list.keys(): self.opening = StringVar(save_zone) self.opening.set("Open") choice = [na for na in Card.monster_list.keys() if na not in Card.blocked_creature] choice.sort() #print all_monsters.keys() open_wid = OptionMenu(save_zone, self.opening,*choice) self.opening.trace('w', self.Open) open_wid.pack() save_zone.add(open_wid) if Card.monster_list.keys(): self.delete = StringVar(save_zone) self.delete.set("Delete") choice = [na for na in Card.monster_list.keys() if na not in Card.blocked_creature] choice.sort() delete_wid = OptionMenu(save_zone, self.delete,*choice) self.delete.trace('w', self.clicDelete) delete_wid.pack() save_zone.add(delete_wid) #Create the type button self.category = StringVar(save_zone) self.category.set(self.monster_type) choice = [file2name(t,"_monsters.sav") for t in glob.glob("CardFiles/*_monsters.sav")] if "recup" in choice: choice.remove("recup") #print all_monsters.keys() category_wid = OptionMenu(save_zone, self.category,*choice) self.category.trace('w', self.setFile) category_wid.pack() #Add it to save zone save_zone.add(save_wid) save_zone.add(category_wid) #Create a new Strength zone for att and pv strength_zone=PanedWindow(self.card_win, orient=HORIZONTAL) att=StringVar() att.set(str(self.att)) pv=StringVar() ; pv.set(str(self.pv)) def modifiedAttPv(*args) : print ("modifiedAttPv") self.pv=int(pv.get()) if self.pv<1 and self.is_spell==False : if len(self.bonus)==0 : self.is_spell=True self.refreshWidget() else : self.pv=1 self.refreshWidget() if self.pv>0 and self.is_spell==True : if len(self.bonus)==0 : self.is_spell=False self.refreshWidget() else : self.pv=0 self.refreshWidget() self.att=int(att.get()) self.getCost() att_wid = Spinbox(strength_zone, from_=0, to=1000,textvariable=att,command=modifiedAttPv) att_wid.pack() strength_zone.add(att_wid) strength_zone.add(Label(strength_zone, text=' ', background='white', anchor=CENTER)) pv_wid = Spinbox(strength_zone, from_=0, to=1000,textvariable=pv,command=modifiedAttPv) pv_wid.pack() strength_zone.add(pv_wid) #Put it all in window self.card_win.add(name_zone) self.card_win.add(image_zone) self.card_win.add(power_zone) self.card_win.add(strength_zone) self.card_win.add(save_zone) self.card_win.pack() def createImage(self,black=False): width=189*2; height=277*2 screen = pygame.display.set_mode((width,height)) print ("Type = ",self.monster_type) if self.monster_type in all_backgrounds.keys(): try: bg = pygame.image.load(all_backgrounds[self.monster_type]) except: print ("error (? when load of bg") else: bg = pygame.image.load('gameAnimationImages/Card_face_avant.gif') #fond = PhotoImage(file =bg,master=fenetre) pilImage = Image.open( #ligne1 = canvas.create_line(75, 0, 75, 120) #ligne2 = canvas.create_line(0, 60, 150, 60) if self.photofile and not black: try : img=pygame.image.load(self.photofile) except : decomp=self.photofile.split('/') for i in range(1,6) : try : fname="/".join(decomp[-i:]) print ("try to open",fname) img=pygame.image.load(fname) self.photofile=fname break except: pass img = pygame.image.load(self.photofile) w, h = img.get_size() factor=max(150.*2./w,90.*2./h) img=pygame.transform.scale(img,(int(w*factor),int(h*factor))) #fenetre.photo=PhotoImage(file=self.photofile,master=canvas) #img=ImageTk.PhotoImage(img,master=fenetre) screen.blit(img,(width/2.-w*factor/2.,140.-h*factor/4.)) else : try : name=self.name.replace(" ","_") img=pygame.image.load("Cards/"+name+".png") print ("* Found for image ","Cards/"+name+".png") screen.blit(img,(0,0)) except : pass screen.blit(bg,(0,0)) pygame.font.init() #print pygame.font.get_fonts() if self.monster_type in white_font_types: color = (255,255,255) else: color = (0,0,0) centerText(screen,(width/2.+10.,33.*2.),self.name,36-(len(self.name)>11)*(len(self.name)-11)//3,color) #txt = canvas.create_text(101, 32, text=self.name, font=("Calibri",12-(len(self.name)>11)*(len(self.name)-11)/5,"bold"), anchor=CENTER) if not(self.is_spell): centerText(screen,(24*2.,258*2.),str(self.att),40,color) centerText(screen,(169*2.,255*2.),str(self.pv),40,color) else : centerText(screen,(width/2.,265*2.),"SPELL",30,color) #elif self.is_spell: # txt = canvas.create_text(100,265, text="SPELL", anchor=CENTER, font=("Calibri",14,'bold')) #txt = canvas.create_text(22,35, text=int(floor(self.getCost())), anchor=CENTER, font=("Calibri",18,'bold')) centerText(screen,(22*2.,35*2.),str(int(floor(self.getCost()))),50,color) #txt1 = canvas.create_text(92,257, text='*'*self.getStars(), anchor=CENTER, font=("Calibri",26,'bold')) centerText(screen,(92*2.,257*2.),'*'*self.getStars(),60,color) if not(self.monster_type == "unknown"): if self.monster_type in all_type_colors: Color = all_type_colors[self.monster_type] else: Color = "human" else: Color = "human" centerText(screen,(95*2.,142*2.),self.monster_type.capitalize(),26,Color) if len(self.bonus)>0 : powers = "e%96".join([b.getDescription() for b in self.bonus if b.getDescription()]) powers = [p.split("\n") for p in powers.split("e%96")] print ("powers are ",powers) else : powers ="" #print "POWERS = ", powers if powers: space=min([80., 160./sum([len(p)*3+2 for p in powers])]) print ("Space: ",space) line = 0 for i,b in enumerate(powers): if b!=[''] : print ("power",b) size = min([36.,500./max([len(p) for p in b]) * 2.]) for x,part in enumerate(b): centerText(screen,(90*2.,167*2.+line*space),part,int(size),color) line += 3 line += 2 #canvas.pack() #print "toto!" pygame.display.flip() return screen def init_as_invocation(self,master,spells=False): # monster widget in invocation widget #print "monster init_as_invocation" self.content=StringVar() self.content.set(self.name) self.content.trace("w", self.is_changed_as_invocation) l = [ m for m in Card.monster_list.keys() if (spells or all_monsters[m].pv>0) and not(m in Card.blocked_creature) and (spells or not "PlainteMaudite" in all_monsters[m].constructor()) and not any([b.__class__.__name__=="Charge" for b in all_monsters[m].bonus]) and not any([b.__class__.__name__=="Errant" for b in all_monsters[m].bonus]) and not any([b.__class__.__name__=="Essentiel" for b in all_monsters[m].bonus]) and not any([b.__class__.__name__=="Incarnation" for b in all_monsters[m].bonus]) #and not any([b.__class__.__name__=="AuDebutDuProchainTour" for b in all_monsters[m].bonus]) ] self.widget=OptionMenu(master,self.content,*l) return self.widget def init_as_card(self,master): # monster widget in invocation widget #print "monster init_as_invocation" self.content=StringVar() self.content.set(self.name) self.content.trace("w", self.is_changed_as_invocation) l = [ m for m in Card.monster_list.keys() if not(m in Card.blocked_creature) ] self.widget=OptionMenu(master,self.content,*l) return self.widget def is_changed_as_invocation(self,*args): print ("monster is_changed_as_invocation") if self.content.get()!= "Troll gris": new= Card.monster_list[self.content.get()] else: new = Card("Troll gris",4,4) #print self.content.get() if self.parent : #parent.spell=new #print "self.parent = True" self.parent.monster=new new.parent = self.parent new.card=self.card else : raise "ce cas existe ?! me dire comment" self.bonus[self.bonus.index(self)]=new #self.card_win.pack_forget() self.card.refreshWidget()
class NoteBag: config = None notes = None # Config Options notes_filename = None notes_dir = None note_template_filename = None document_editor = None # GUI Elements note_name_action_strvar = None note_name_entry_strvar = None note_name_entry = None note_names_label_strvar = None note_names_listbox = None ## Config/Init Methods def load_config(self): """ Load NoteBag's config file, and use it to set config options. """ config = self.config = read_config(CONFIG_FILENAME) self.notes_list_filename = config.get("NoteBag", "Notes List File") self.notes_dir = config.get("NoteBag", "Notes Directory") self.note_template_filename = config.get("NoteBag", "Note Template Filename") self.document_editor = config.get("NoteBag", "Document Editor") def save_config(self): """ Save NoteBag's current configuration to its config file. """ save_config(self.config, CONFIG_FILENAME) def load_notes_list(self): """ Load the list of notes. """ # TODO handle exceptions notes_list_path = self.notes_list_path() if not os.path.isfile(notes_list_path): self.notes = {} else: self.notes = read_notes_list(notes_list_path) def save_notes_list(self): """ Save the list of notes. """ save_notes_list(self.notes, self.notes_list_path()) ## Back-End Methods def notes_list_path(self): """ Return the path to the notes list file. """ return os.path.join(self.notes_dir, self.notes_list_filename) def template_note_path(self): """ Return the path to the template note file. """ return os.path.join(get_called_script_dir(), self.note_template_filename) def note_filename_exists(self, filename): """ If a note filename already exists case-insensitively, return the proper filename from self.notes. """ for existing in self.notes.values(): if filename.lower() == existing.lower(): return existing return False def note_name_exists(self, note_name): """ If the given note name matches an existing note name case-insensitively, return the "proper" note name from self.notes; if the given note name does not exist, return None. """ note_names = self.notes.keys() for existing_note_name in note_names: if note_name.lower() == existing_note_name.lower(): return existing_note_name return None def get_note_path(self, note_name): """ Return the path to an existing note document. """ note_filename = self.notes[note_name] note_path = os.path.join(self.notes_dir, note_filename) return note_path def new_note_filename(self, note_name): """ Return an unused filename appropriate for the given note name. Note filenames are .rtf files. All "un-kosher" characters are stripped out of the note name, so the filesystem doesn't choke on them. """ filename_base = sanitize_note_name(note_name) filename = filename_base + ".rtf" if not self.note_filename_exists(filename): return filename suffix_num = 2 while self.note_filename_exists(filename): filename = "{0}-{1}.rtf".format(filename_base, str(suffix_num)) suffix_num += 1 return filename def get_listbox_selected_note_name(self): """ Return the note name that is selected in the listbox; if there is no selection, return None. """ selections = self.note_names_listbox.curselection() if not selections: return None selection = selections[0] note_name = self.note_names_listbox.get(selection) return note_name def get_entered_note_name(self): """ Get the text that has been entered into the "Note Name" text entry box, with all leading and trailing spaces stripped off. """ return self.note_name_entry.get().strip("\t ") def add_note(self, note_name, note_filename=None): """ Add a note document, and save the list of notes. """ if not note_filename: note_filename = self.new_note_filename(note_name) note_path = os.path.join(self.notes_dir, note_filename) create_skeleton_note(note_name, note_path, self.template_note_path()) self.notes[note_name] = note_filename self.save_notes_list() def update_note_names_list(self): """ Update the listbox of the existing notes, and the list's label. If there is any text entered into the "Note Name" text entry box, only list note names that contain the entered text. (This is where incremental search happens.) """ search_str = self.get_entered_note_name() note_names = self.notes.keys() # Remove strings that don't match if search_str: def string_matches_search(s): return search_str.lower() in s.lower() note_names = filter(string_matches_search, note_names) # Sort Alphabetically note_names = sorted(note_names, key=lambda s: s.lower()) # Update the note name listbox note_names_listbox = self.note_names_listbox note_names_listbox.delete(0, END) for note_name in note_names: note_names_listbox.insert(END, note_name) # Update the note name list label if search_str: s = "All Note Names Containing '{0}':".format(search_str) else: s = "All Existing Notes:" self.note_names_label_strvar.set(s) def open_note(self, note_name): """ Open a note for editing. """ note_filename = self.notes[note_name] note_path = os.path.join(self.notes_dir, note_filename) open_note(note_path, self.document_editor) ## GUI Callbacks def note_name_action_callback(self, *_args, **_kwargs): """ A callback to perform an action based on the text in the "Note Name" text entry box. If the name of an existing note has been entered into the text box, open the note; if some other text has been entered, create a note with the entered text as a name; if no text has been entered, show a warning dialog box and do nothing. """ note_name = self.get_entered_note_name() if not note_name: messagebox.showwarning("Error", "Can't add note: no note name entered") return key = self.note_name_exists(note_name) if key: # The note exists; open it. self.open_note(key) else: # The note doesn't exist; create it. # TODO popup a small confirmation/note setup dialog. self.add_note(note_name) self.clear_note_name_entry() self.open_note(note_name) self.clear_note_name_entry() def note_name_entry_changed(self, *_args, **_kwargs): """ A callback to update the text entry action ("Open"/"Add") button's label, and update the incremental note list search, based on the text in the "Note Name" text entry box. """ self.update_note_names_list() entered_note_name = self.get_entered_note_name() if self.note_name_exists(entered_note_name): self.note_name_action_strvar.set("Open") else: self.note_name_action_strvar.set("Add") def clear_note_name_entry(self): """ Clear the "Note Name" text entry box. """ self.note_name_entry.delete(0, END) def open_note_from_listbox(self, *_args, **_kwargs): """ If a note name has been selected in the note name list, open it; otherwise, show a warning dialog box and do nothing. """ note_name = self.get_listbox_selected_note_name() if not note_name: # TODO show a warning dialog box or something messagebox.showwarning("Error", "Can't Open: No note selected") return self.open_note(note_name) def delete_note_from_listbox(self, *_args, **_kwargs): """ If a note name has been selected in the note name list, delete it after prompting the user to confirm; otherwise, show a warning dialog box and do nothing. """ note_name = self.get_listbox_selected_note_name() if not note_name: messagebox.showwarning("Error", "Can't Delete: No note selected") return if not messagebox.askyesno("Really Delete Note?", "WARNING: This will remove the note document file from your hard drive! You cannot undo this!\n\nReally remove '{0}'?".format(note_name), icon=messagebox.ERROR): return note_path = self.get_note_path(note_name) del(self.notes[note_name]) self.save_notes_list() os.remove(note_path) self.update_note_names_list() ## Main Code def __init__(self, master): ## High-level Layout input_frame = Frame(master) notes_frame = Frame(master) input_frame.pack(fill=X, padx=15) notes_frame.pack(fill=BOTH, expand=True, padx=10, pady=10) ## Input Frame Setup note_name_label = Label(input_frame, text="Note Name: ") note_name_label.pack(side=LEFT) self.note_name_entry_strvar = StringVar() self.note_name_entry_strvar.set("") self.note_name_entry_strvar.trace("w", self.note_name_entry_changed) self.note_name_entry = Entry(input_frame, textvariable=self.note_name_entry_strvar) note_name_entry = self.note_name_entry note_name_entry.pack(side=LEFT, fill=X, expand=True) note_name_entry.focus_set() note_name_entry.bind("<Return>", self.note_name_action_callback) note_name_entry.bind("<KP_Enter>", self.note_name_action_callback) self.note_name_action_strvar = StringVar() note_name_action_strvar = self.note_name_action_strvar note_name_action_strvar.set("Add") note_name_action_button = Button(input_frame, textvar=note_name_action_strvar, command=self.note_name_action_callback) note_name_action_button.pack(side=LEFT) clear_note_name_button = Button(input_frame, text="Clear", command=self.clear_note_name_entry) clear_note_name_button.pack(side=LEFT) ## Notes Frame Setup # List of existing notes self.note_names_label_strvar = StringVar() note_names_label_strvar = self.note_names_label_strvar note_names_label = Label(notes_frame, textvar=note_names_label_strvar) note_names_label.pack(anchor=W) note_names_listbox = self.note_names_listbox = Listbox(notes_frame) note_names_listbox.pack(side=LEFT, fill=BOTH, expand=True) note_names_listbox.bind("<Return>", self.open_note_from_listbox) note_names_listbox.bind("<KP_Enter>", self.open_note_from_listbox) note_names_listbox.bind("<Double-Button-1>", self.open_note_from_listbox) # Add scrollbar to list of notes notes_scrollbar = Scrollbar(notes_frame) notes_scrollbar.pack(side=LEFT, fill=Y) note_names_listbox.config(yscrollcommand=notes_scrollbar.set) notes_scrollbar.config(command=note_names_listbox.yview) ## Controls note_controls = Frame(notes_frame) note_controls.pack(side=LEFT, fill=Y) open_note_button = Button(note_controls, text="Open", command=self.open_note_from_listbox) open_note_button.pack(fill=X) delete_note_button = Button(note_controls, text="Delete", command=self.delete_note_from_listbox) delete_note_button.pack(fill=X) ## Final Initialization self.load_config() self.load_notes_list() self.update_note_names_list()
#number texts font = {'font': (None, 20)} entries = [] numbers = [] for x in range(9): # make numbers and entries 2d lists row1 = [] row2 = [] # strange things were happening when trying to use only 1 'row[]' numbers.append(row1) entries.append(row2) for y in range(9): # get string var sv = StringVar() sv.set('') sv.trace("w", lambda *_, var = sv, x=x, y=y: callback(var,x,y)) numbers[x].append(sv) # get entry and attach string var num = Entry( canvas, textvariable = sv, width = 2, **font) num.grid(column = x, row = y, padx = (8), pady = (7)) entries[x].append(num) #offset grid if x == 0: num.grid(padx = (34,8)) if x == 8: num.grid(padx = (8, 34)) if y == 0: num.grid(pady = (33,7)) if y == 8:
class App(): def __init__(self): # Create app self.root = tk.Tk() self.root.grid_propagate(0) # global styles config = json.loads(open('src/config.json').read()) themeId = config['activeThemeId'] theme = list(filter( lambda x: config['themes'][x]['themeId'] == themeId, config['themes']))[0] self.globalStyles = config['themes'][theme]['style'] self.backgroundColor = self.globalStyles['backgroundColor'] self.foregroundColor = self.globalStyles['foregroundColor'] self.hoverColor = self.globalStyles['hoverColor'] self.fontColor = self.globalStyles['fontColor'] self.textEntryColor = self.globalStyles['textEntryColor'] self.starColor = self.globalStyles['starColor'] self.padl = 15 # tk styles self.textBorderColor = self.globalStyles['textBorderColor'] self.textHighlightColor = self.globalStyles['textHighlightColor'] # ttk styles classes self.style = ttk.Style() self.style.configure("BW.TCheckbutton", foreground=self.fontColor, background=self.backgroundColor, bordercolor=self.backgroundColor, side='LEFT') self.style.configure('TCombobox', background=self.backgroundColor, bordercolor=self.backgroundColor, relief='flat', lightcolor=self.backgroundColor, darkcolor=self.backgroundColor, borderwidth=4, foreground=self.foregroundColor) # App parameters self.root.title('TwoPAGER Tool') self.root_h = 220 self.root_w = 330 self.root.geometry(str(self.root_w) + 'x' + str(self.root_h)) windowWidth = self.root.winfo_reqwidth() windowHeight = self.root.winfo_reqheight() # Gets both half the screen width/height and window width/height positionRight = int(self.root.winfo_screenwidth()/2 - windowWidth) positionDown = int(self.root.winfo_screenheight()/3 - windowHeight) # Positions the window in the center of the page. self.root.geometry("+{}+{}".format(positionRight, positionDown)) self.root.resizable(0, 0) self.root.configure(background=self.backgroundColor, highlightcolor='#fff') # App images self.root.wm_iconbitmap('src/assets/images/HazusHIcon.ico') self.img_data = ImageTk.PhotoImage(Image.open( "src/assets/images/data_blue.png").resize((20, 20), Image.BICUBIC)) self.img_edit = ImageTk.PhotoImage(Image.open( "src/assets/images/edit_blue.png").resize((20, 20), Image.BICUBIC)) self.img_folder = ImageTk.PhotoImage(Image.open( "src/assets/images/folder_icon.png").resize((20, 20), Image.BICUBIC)) # Init dynamic row self.row = 0 def getStudyRegions(self): """Gets all study region names imported into your local Hazus install Returns: studyRegions: list -- study region names """ # list all Windows SQL Server drivers drivers = [ '{ODBC Driver 17 for SQL Server}', '{ODBC Driver 13.1 for SQL Server}', '{ODBC Driver 13 for SQL Server}', '{ODBC Driver 11 for SQL Server} ', '{SQL Server Native Client 11.0}', '{SQL Server Native Client 10.0}', '{SQL Native Client}', '{SQL Server}' ] comp_name = os.environ['COMPUTERNAME'] # create connection with the latest driver for driver in drivers: try: conn = py.connect('Driver={d};SERVER={cn}\HAZUSPLUSSRVR;UID=SA;PWD=Gohazusplus_02'.format( d=driver, cn=comp_name)) break except: continue exclusionRows = ['master', 'tempdb', 'model', 'msdb', 'syHazus', 'CDMS', 'flTmpDB'] cursor = conn.cursor() cursor.execute('SELECT [StateID] FROM [syHazus].[dbo].[syState]') for state in cursor: exclusionRows.append(state[0]) cursor = conn.cursor() cursor.execute('SELECT * FROM sys.databases') studyRegions = [] for row in cursor: if row[0] not in exclusionRows: studyRegions.append(row[0]) studyRegions.sort(key=lambda x: x.lower()) return studyRegions def setup(self, scenario_name, folder_path): # Make a folder in folder_path for scenario_name if not os.path.exists(folder_path + '\\' + scenario_name): os.makedirs(folder_path + '\\' + scenario_name) # Connect to Hazus SQL Server database where scenario results are stored # list all Windows SQL Server drivers drivers = [ '{ODBC Driver 17 for SQL Server}', '{ODBC Driver 13.1 for SQL Server}', '{ODBC Driver 13 for SQL Server}', '{ODBC Driver 11 for SQL Server} ', '{SQL Server Native Client 11.0}', '{SQL Server Native Client 10.0}', '{SQL Native Client}', '{SQL Server}' ] comp_name = os.environ['COMPUTERNAME'] # create connection with the latest driver for driver in drivers: try: cnxn = py.connect('Driver={d};SERVER={cn}\HAZUSPLUSSRVR;DATABASE={sn};UID=hazuspuser;PWD=Gohazusplus_02'.format( d=driver, cn=comp_name, sn=scenario_name)) break except: continue return comp_name, cnxn def read_sql(self, comp_name, cnxn, scenario_name): # Select Hazus results from SQL Server scenario database sql_econ_loss = """SELECT Tract, SUM(ISNULL(BldgLoss, 0) + ISNULL(ContentLoss, 0) + ISNULL(InvLoss, 0) + ISNULL(RelocLoss, 0) + ISNULL(IncLoss, 0) + ISNULL(RentLoss, 0) + ISNULL(WageLoss, 0)) AS EconLoss FROM %s.dbo.[eqTractEconLoss] GROUP BY [eqTractEconLoss].Tract""" % scenario_name sql_county_fips = """SELECT Tract, CountyFips FROM %s.dbo.[hzTract]""" % scenario_name sql_demographics = """SELECT Tract, Population, Households FROM %s.dbo.[hzDemographicsT]""" % scenario_name sql_impact = """SELECT Tract, DebrisW, DebrisS, DisplacedHouseholds AS DisplHouse, ShortTermShelter AS Shelter FROM %s.dbo.[eqTract]""" % scenario_name sql_injury = """SELECT Tract, SUM(ISNULL(Level1Injury, 0)) AS Level1Injury, SUM(ISNULL(Level2Injury, 0)) AS Level2Injury, SUM(ISNULL(Level3Injury, 0)) AS Level3Injury, SUM(ISNULL(Level1Injury, 0) + ISNULL(Level2Injury, 0) + ISNULL(Level3Injury, 0)) AS NonFatal5p FROM %s.dbo.[eqTractCasOccup] WHERE CasTime = 'C' AND InOutTot = 'Tot' GROUP BY Tract""" % scenario_name sql_building_damage = """SELECT Tract, SUM(ISNULL(PDsNoneBC, 0)) As NoDamage, SUM(ISNULL(PDsSlightBC, 0) + ISNULL(PDsModerateBC, 0)) AS GreenTag, SUM(ISNULL(PDsExtensiveBC, 0)) AS YellowTag, SUM(ISNULL(PDsCompleteBC, 0)) AS RedTag FROM %s.dbo.[eqTractDmg] WHERE DmgMechType = 'STR' GROUP BY Tract""" % scenario_name sql_building_damage_occup = """SELECT Occupancy, SUM(ISNULL(PDsNoneBC, 0)) As NoDamage, SUM(ISNULL(PDsSlightBC, 0) + ISNULL(PDsModerateBC, 0)) AS GreenTag, SUM(ISNULL(PDsExtensiveBC, 0)) AS YellowTag, SUM(ISNULL(PDsCompleteBC, 0)) AS RedTag FROM %s.dbo.[eqTractDmg] WHERE DmgMechType = 'STR' GROUP BY Occupancy""" % scenario_name sql_building_damage_bldg_type = """SELECT eqBldgType, SUM(ISNULL(PDsNoneBC, 0)) As NoDamage, SUM(ISNULL(PDsSlightBC, 0) + ISNULL(PDsModerateBC, 0)) AS GreenTag, SUM(ISNULL(PDsExtensiveBC, 0)) AS YellowTag, SUM(ISNULL(PDsCompleteBC, 0)) AS RedTag FROM %s.dbo.[eqTractDmg] WHERE DmgMechType = 'STR' GROUP BY eqBldgType""" % scenario_name sql_tract_spatial = """SELECT Tract, Shape.STAsText() AS Shape FROM %s.dbo.[hzTract]""" % scenario_name # Group tables and queries into iterable hazus_results = {'econ_loss': sql_econ_loss, 'county_fips': sql_county_fips, 'demographics': sql_demographics, 'impact': sql_impact, 'injury': sql_injury, 'building_damage': sql_building_damage, 'building_damage_occup': sql_building_damage_occup, 'building_damage_bldg_type': sql_building_damage_bldg_type, 'tract_spatial': sql_tract_spatial} # Read Hazus result tables from SQL Server into dataframes with Tract ID as index hazus_results_df = {table: pd.read_sql( query, cnxn) for table, query in hazus_results.items()} for name, dataframe in hazus_results_df.items(): if (name != 'building_damage_occup') and (name != 'building_damage_bldg_type'): dataframe.set_index('Tract', append=False, inplace=True) return hazus_results_df def results(self, hazus_results_df): # Join and group Hazus result dataframes into final TwoPAGER dataframes tract_results = hazus_results_df['county_fips'].join([hazus_results_df['econ_loss'], hazus_results_df['demographics'], hazus_results_df['impact'], hazus_results_df['injury'], hazus_results_df['building_damage']]) county_results = tract_results.groupby('CountyFips').sum() return tract_results, county_results def to_csv(self, hazus_results_df, tract_results, county_results, folder_path, scenario_name): # Export TwoPAGER dataframes to text files two_pager_df = {'building_damage_occup': hazus_results_df['building_damage_occup'], 'building_damage_bldg_type': hazus_results_df['building_damage_bldg_type'], 'tract_results': tract_results, 'county_results': county_results} for name, dataframe in two_pager_df.items(): path = folder_path + '\\' + scenario_name + '\\' + name + '.csv' dataframe.to_csv(path) def two_pager(self, scenario_name, folder_path, ftp=False): comp_name, cnxn = self.setup(scenario_name, folder_path) hazus_results_df = self.read_sql(comp_name, cnxn, scenario_name) tract_results, county_results = self.results(hazus_results_df) self.to_csv(hazus_results_df, tract_results, county_results, folder_path, scenario_name) # to_shp(folder_path, scenario_name, hazus_results_df, tract_results) # if ftp == True: # credentials = to_ftp(folder_path, scenario_name) # print('Hazus earthquake results available for download at: https://' + # credentials['host'] + credentials['dir'] + '/' + scenario_name) print('Hazus earthquake results available locally at: ' + folder_path + '\\' + scenario_name) def browsefunc(self): self.output_directory = filedialog.askdirectory() self.input_studyRegion = self.dropdownMenu.get() self.text_outputDir.delete("1.0", 'end-1c') if len(self.input_studyRegion) > 0: self.text_outputDir.insert( "1.0", self.output_directory + '/' + self.input_studyRegion) self.root.update_idletasks() else: self.text_outputDir.insert("1.0", self.output_directory) self.root.update_idletasks() def on_field_change(self, index, value, op): try: self.input_studyRegion = self.dropdownMenu.get() self.output_directory = str( self.text_outputDir.get("1.0", 'end-1c')) check = self.input_studyRegion in self.output_directory if (len(self.output_directory) > 0) and (not check): self.output_directory = '/'.join( self.output_directory.split('/')[0:-1]) self.text_outputDir.delete('1.0', tk.END) self.text_outputDir.insert( "1.0", self.output_directory + '/' + self.input_studyRegion) self.root.update_idletasks() except: pass def getTextFields(self): dict = { 'output_directory': '/'.join(self.text_outputDir.get("1.0", 'end-1c').split('/')[0:-1]) } return dict def focus_next_widget(self, event): event.widget.tk_focusNext().focus() return("break") def on_enter_dir(self, e): self.button_outputDir['background'] = self.hoverColor def on_leave_dir(self, e): self.button_outputDir['background'] = self.backgroundColor def on_enter_run(self, e): self.button_run['background'] = '#006b96' def on_leave_run(self, e): self.button_run['background'] = '#0078a9' def run(self): try: if (len(self.dropdownMenu.get()) > 0) and (len(self.text_outputDir.get("1.0", 'end-1c')) > 0): self.root.update() sleep(1) func_row = self.row t0 = time() ### RUN FUNC HERE ### self.two_pager(self.input_studyRegion, self.output_directory) print('Total elasped time: ' + str(time() - t0)) tk.messagebox.showinfo("Hazus", "Success! Output files can be found at: " + self.output_directory + '/' + self.input_studyRegion) else: tk.messagebox.showwarning( 'Hazus', 'Make sure a study region and output directory have been selected') except: ctypes.windll.user32.MessageBoxW( None, u"Unable to open correctly: " + str(sys.exc_info()[1]), u'Hazus - Message', 0) def build_gui(self): # App body # Required label self.label_required1 = tk.Label( self.root, text='*', font='Helvetica 14 bold', background=self.backgroundColor, fg=self.starColor) self.label_required1.grid(row=self.row, column=0, padx=( self.padl, 0), pady=(20, 5), sticky=W) # Scenario name label self.label_scenarioName = tk.Label( self.root, text='Study Region', font='Helvetica 10 bold', background=self.backgroundColor, fg=self.fontColor) self.label_scenarioName.grid( row=self.row, column=1, padx=0, pady=(20, 5), sticky=W) self.row += 1 # Get options for dropdown options = self.getStudyRegions() self.variable = StringVar(self.root) self.variable.set(options[0]) # default value # Scenario name dropdown menu self.v = StringVar() self.v.trace(W, self.on_field_change) self.dropdownMenu = ttk.Combobox( self.root, textvar=self.v, values=options, width=40, style='H.TCombobox') self.dropdownMenu.grid(row=self.row, column=1, padx=(0, 0), pady=(0, 0), sticky=W) self.dropdownMenu.bind("<Tab>", self.focus_next_widget) # Scenario icon self.img_scenarioName = tk.Label( self.root, image=self.img_data, background=self.backgroundColor) self.img_scenarioName.grid( row=self.row, column=2, padx=0, pady=(0, 0), sticky=W) self.row += 1 # Required label self.label_required3 = tk.Label( self.root, text='*', font='Helvetica 14 bold', background=self.backgroundColor, fg=self.starColor) self.label_required3.grid(row=self.row, column=0, padx=( self.padl, 0), pady=(10, 0), sticky=W) # Output directory label self.label_outputDir = tk.Label(self.root, text='Output Directory', font='Helvetica 10 bold', background=self.backgroundColor, fg=self.fontColor) self.label_outputDir.grid( row=self.row, column=1, padx=0, pady=(10, 0), sticky=W) self.row += 1 # Output directory text form self.text_outputDir = tk.Text(self.root, height=1, width=37, font='Helvetica 10', background=self.textEntryColor, relief='flat', highlightbackground=self.textBorderColor, highlightthickness=1, highlightcolor=self.textHighlightColor) self.text_outputDir.grid( row=self.row, column=1, padx=(0, 0), pady=(0, 0), sticky=W) self.text_outputDir.bind("<Tab>", self.focus_next_widget) # Output directory browse button self.button_outputDir = tk.Button(self.root, text="", image=self.img_folder, command=self.browsefunc, relief='flat', background=self.backgroundColor, fg='#dfe8e8', cursor="hand2", font='Helvetica 8 bold') self.button_outputDir.grid( row=self.row, column=2, padx=0, pady=(0, 0), sticky=W) self.button_outputDir.bind("<Tab>", self.focus_next_widget) self.button_outputDir.bind("<Enter>", self.on_enter_dir) self.button_outputDir.bind("<Leave>", self.on_leave_dir) self.row += 1 # Run button self.button_run = tk.Button(self.root, text='Run', width=5, command=self.run, background='#0078a9', fg='#fff', cursor="hand2", font='Helvetica 8 bold', relief='flat') self.button_run.grid(row=self.row, column=1, columnspan=1, sticky='nsew', padx=50, pady=(30, 20)) self.button_run.bind("<Enter>", self.on_enter_run) self.button_run.bind("<Leave>", self.on_leave_run) self.row += 1 # Run app def start(self): self.build_gui() self.root.mainloop()
canvas.create_image(sw, sh, image=img, anchor="nw") if img is not None: iy = sh + img.width() / (int(yo.get()) + 1) while iy < sh + img.height(): canvas.create_line(sw, iy, root.winfo_screenwidth(), iy, fill='red') iy += img.width() / (int(yo.get()) + 1) ix = sw + img.width() / (int(xo.get()) + 1) while ix < sw + img.width(): canvas.create_line(ix, sh, ix, root.winfo_screenheight(), fill='red') ix += img.width() / (int(xo.get()) + 1) yo.trace("w", mriezkuj) xo.trace("w", mriezkuj) loading() canvas.pack() root.mainloop()
class StudentGUI(tk.Frame): """Student GUI frame to be used in the main GUI This class contains multiple input widgets for the GUI, as well as the Server class used to connect with the socket client. """ # Settings header_1_style = "TkDefaultFont 42 bold" header_2_style = "TkDefaultFont 18 bold" default_style = "TkDefaultFont 14" def __init__(self, parent, *args, **kwargs): """Constructor Args: parent (tk.widget): parent widget to make the frame a child of *args: Variable length argument list **kwargs: Arbitrary keyword argument list """ ttk.Frame.__init__(self, parent, *args, **kwargs) self.parent = parent # Mutex for the networking thread self.socket_queue = Queue() # Socket server self.server = Server(port=25565) self.server.start(self.socket_queue) # Instantiated signals class to generate signals self.ecg_signals = Signals() # ============ GUI Variables ============ # Instructor realtime setting variables self.hr = IntVar(self, value=80) self.threshold = IntVar(self, value=20) self.hr_paced = IntVar(self, value=80) # Manual Override variables self.position = IntVar(self, value=0) self.override_position = BooleanVar(self, value=False) self.hr1 = StringVar(self, value='0') self.pathway_1 = IntVar(self, value=0) self.pathway_2 = IntVar(self, value=0) self.is_paced = BooleanVar(self, value=False) # Serial in position self.serial_position = IntVar(self, value='0') # Command variables self.wait_for_update = BooleanVar(self, value=False) self.wait_for_position = BooleanVar(self, value=False) self.wait_for_pathway_1 = BooleanVar(self, value=False) self.wait_for_pathway_2 = BooleanVar(self, value=False) # ============ Main Frame Sides =========== # Signals frame frame_signals = Frame(self, bg='black') frame_signals.pack(side=tk.LEFT) # Monitor value frame frame_values = Frame(self, bg='black') frame_values.pack(side=tk.RIGHT, padx=10) # Take care of plotting self.plot_point = 0 self.new_x = [0.0] self.new_y = [0.0] self.last_x = 0 self.last_x_lim = 0 self.position_to_show = 0 self.variation = 0 self.flat_span = False self.end_flat = 0 self.flat_span_y = 0 # HR Monitor setup tk.Label(frame_values, text="HR", font=self.header_2_style, bg="black", fg="lime green").pack() tk.Label(frame_values, textvariable=self.hr1, font=self.header_1_style, bg="black", fg="lime green").pack() # Serial selection setup Options = [''] Options.extend(serial.tools.list_ports.comports()) self.s = 'RIP' self.ser = None self.variable = StringVar(self) self.variable.set(Options[0]) #Default option w = OptionMenu(frame_signals, self.variable, *Options) w.grid(row=2, column=1) self.variable.trace('w', self.change_dropdown) # Create plotting canvas fig = plt.Figure(figsize=(14, 4.5), dpi=100, facecolor='k', edgecolor='k') canvas = FigureCanvasTkAgg(fig, master=frame_signals) canvas.get_tk_widget().grid(row=1, column=1) # Sets plot customisations self.ax = fig.add_subplot(111) self.ax.set_xlim(self.last_x_lim, 4) self.ax.set_ylim(-3.0, 3.0) self.ax.set_yticklabels([]) self.ax.set_xticklabels([]) self.ax.xaxis.set_tick_params(width=1, top=True) self.ax.set_facecolor('black') self.line, = self.ax.plot(0, 0) self.ax.get_lines()[0].set_color("xkcd:lime") # Starts an animated plot for the ECG signal self.ani = animation.FuncAnimation(fig, self.animate, interval=24, blit=True) # Polling Initialisation for socket connection self.after(10, self.read_socket) def animate(self, i): """Animation function that is called periodically Args: i (int): the current frame value (not used) Returns: line (matplotlib.line): The line to plot with the next value """ # Set the position index value based on which source is responsible for the signal if self.override_position.get(): position_index = self.position.get() else: position_index = self.serial_position.get() # Set initial heart rate to use hr_to_use = self.hr.get() # Adjust position and heart rate based on alternative pathways and pacer setting if position_index == 4: position_index = position_index + self.pathway_1.get() elif position_index == 6: position_index = position_index + self.pathway_2.get() # Show the paced signal if pacer override is active if not position_index == 16 and self.is_paced.get(): position_index = 26 hr_to_use = self.hr_paced.get() else: # If no overrides or special settings, just keep the position the same position_index = position_index # Print what position is being printed print(self.ecg_signals.signal_index[position_index]) # Display heart rate value on GUI if position_index == 0: self.hr1.set(0) else: self.hr1.set(hr_to_use) # Get the ECG signal values for the corresponding settings [x, y] = self.ecg_signals.get_signal( self.ecg_signals.signal_index[position_index], hr_to_use, self.variation) # If not currently traveling between beats if not self.flat_span: # Set a variable to the potential next value x_val = self.last_x + x[self.plot_point] # If the potential new value is not going backwards if x_val > self.new_x[-1]: # Add the new x and y values to the axis lists self.new_x.append(x_val) self.new_y.append(y[self.plot_point]) # Update the line self.line.set_data(self.new_x, self.new_y) # update the data # If at the end of the beat if self.plot_point == 29: # Update where the last x value to build from is self.last_x = self.new_x[-1] # Start plotting for a flat area self.end_flat = (x[-1] - x[-2]) + self.new_x[-1] self.flat_span_y = y[-1] self.flat_span = True # Go back to the start of the heart beat if at the end of the beat if self.plot_point == 29: self.plot_point = 0 # Go to the next beat value otherwise else: self.plot_point = self.plot_point + 1 # If current traveling between beats else: # Add the new x and y values to the axis lists self.new_x.append(self.new_x[-1] + 0.05) self.new_y.append(self.flat_span_y) # Update the line self.line.set_data(self.new_x, self.new_y) # update the data # If reached the end of the flat line area between beats if self.new_x[-1] >= self.end_flat: # Stop plotting flat self.flat_span = False self.last_x = self.new_x[-1] # If at the end of the plotting window if self.new_x[-1] >= self.last_x_lim + 5: # Shift the plotting window (this is used instead of a reset to allow for future ECG output options) self.last_x_lim += 5 self.ax.set_xlim(self.last_x_lim, self.last_x_lim + 5) # Returns the new line to the plot return self.line, def change_dropdown(self, *args): """Callback function for when a COM port is selected. This will automatically send an updated pathway. Args: *args: Variable length argument list """ # If the current selected port is not empty if not self.variable.get() == '': # Try to connect try: choice = self.variable.get().split(' -') # Open the COM port self.ser = serial.Serial(choice[0], 9600) print('Connection established.') # Start the polling for the serial self.after(10, self.read_serial) # Print exception if it fails except SerialException as e: print('Error: {}'.format(e)) def read_socket(self): """Reads the socket connection and interprets the contents for a command to run. The valid commands are as follows: - update: listen for an incoming ECG settings update - start-pos: start manual position override - stop-pos: stop manual position override - manual-pos: listen for a new override position - chpa1: listen for an updated alternative pathway 1 - chpa2: listen for an updated alternative pathway 2 - close: close the socket - start-pace: start pacing override - stop-pace: stop pacing override - cal: signal for the microcontroller to recalibrate - ressig: reset the student GUI signal """ # If there is something in the socket queue if not self.socket_queue.empty(): # Read from the queue message = self.socket_queue.get() # Print the value print(message) # If a previous command set the GUI to wait for a new ECG customisation if self.wait_for_update.get(): # Strip the new value of any commas (for multivalue messages) result = [ x.strip() for x in message.decode('utf-8').split(',') ] # Set the ECG customisation values self.hr.set(result[0]) self.threshold.set(result[1]) self.hr_paced.set(result[2]) # Stop waiting for an update self.wait_for_update.set(False) # If the previous command set the GUI to wait for a new manual override position elif self.wait_for_position.get(): # Set the position to the new incoming value self.position.set(int(message.decode('utf-8'))) # Stop listening for new value self.wait_for_position.set(False) # Override the position self.override_position.set(True) # If the previous command set the GUI to wait for a new pathway elif self.wait_for_pathway_1.get(): # Set the new pathway self.pathway_1.set(int(message.decode('utf-8'))) print(self.pathway_1.get()) # Stop listening for a new pathway self.wait_for_pathway_1.set(False) # If the previous command set the GUI to wait for a new pathway elif self.wait_for_pathway_2.get(): # Set the new pathway self.pathway_2.set(int(message.decode('utf-8'))) print(self.pathway_2.get()) # Stop listening for a new pathway self.wait_for_pathway_2.set(False) # Determine what command to run otherwise else: if message == b'update': self.wait_for_update.set(True) elif message == b'start-pos': self.wait_for_position.set(True) elif message == b'stop-pos': self.override_position.set(False) elif message == b'manual-pos': self.wait_for_position.set(True) elif message == b'chpa1': self.wait_for_pathway_1.set(True) elif message == b'chpa2': self.wait_for_pathway_2.set(True) elif message == b'close': self.destroy() elif message == b'start-pace': self.is_paced.set(True) elif message == b'stop-pace': self.is_paced.set(False) elif message == b'cal': self.write_serial(b'C') elif message == b'ressig': self.position_to_show = 0 # Put this function to call on another timer self.after(10, self.read_socket) def pause_plot(self): """Pause the plotting animation""" self.ani.event_source.stop() def start_plot(self): """Start the plotting animation""" self.ani.event_source.start() def write_serial(self, message): """Write a message to the microcontroller over serial Args: message (str): Message to write the microcontroller """ # If a serial connection exists if not self.ser == None: # Try to write the message try: self.ser.write(message) print(message) # Print an exception if one occurs except Exception as e: print('Error: {}'.format(e)) def read_serial(self): """Read from the serial""" # If a serial connection exists if not self.ser == None: # Try to read try: # If there is an incoming message if self.ser.in_waiting: # Read in one byte self.s = self.ser.read() # Update the GUI position with that value self.serial_position.set(int(self.s)) print(int(self.s)) # Catch an exception and print it except Exception as e: print('Error: {}'.format(e)) # Put read serial back on a timer self.after(10, self.read_serial) def stop_gui(self): """Cleanup any option connections""" # Try to close out of the serial and the server try: self.server.stop() self.ser.close() # Print any exceptions that occur except Exception as e: print(e)
class DUnits(Frame): def __init__(self, parent, controller): Frame.__init__(self, parent) self.controller = controller self.left_value = StringVar() # the input on the left self.right_value = StringVar() # the input on the right self.columnconfigure(0, weight=1, pad=5) self.columnconfigure(1, weight=1, pad=5) self.rowconfigure(0, pad=5) self.rowconfigure(1, pad=5) self.rowconfigure(2, pad=5) self.rowconfigure(3, weight=1, pad=5) # Title bbutton = Button(self, text="<", command=lambda: controller.show_frame("MainPage")) bbutton.grid(row=0, column=0, padx=10, sticky=W) title = Label(self, text="Digital Storage") title.grid(row=0, columnspan=4, padx=10) # Labels flabel = Label(self, text="From:") flabel.grid(row=1, column=0, padx=10, sticky=W) tlabel = Label(self, text="To:") tlabel.grid(row=1, column=1, padx=10, sticky=W) # In/Outputs self.left = Entry(self, textvariable=self.left_value) self.left.grid(row=2, column=0, padx=10, sticky=E + W) self.right = Entry(self, textvariable=self.right_value) self.right.grid(row=2, column=1, padx=10, sticky=E + W) # Options self.loptions = Listbox(self, exportselection=0) self.loptions.grid(row=3, column=0, padx=12, pady=8, sticky=N + E + S + W) self.roptions = Listbox(self, exportselection=0) self.roptions.grid(row=3, column=1, padx=12, pady=8, sticky=N + E + S + W) self.loptions.bind('<<ListboxSelect>>', lambda a: self.update_outputs(1)) self.roptions.bind('<<ListboxSelect>>', lambda a: self.update_outputs(0)) # Insert all keys in the dictionary in the listboxes units = [ 'bit', 'kilobit', 'kibibit', 'megabit', 'mebibit', 'gigabit', 'gibibit', 'terabit', 'tebibit', 'petabit', 'pebibit', 'byte', 'kilobyte', 'kibibyte', 'megabyte', 'mebibyte', 'gigabyte', 'gibibyte', 'terabyte', 'tebibyte', 'petabyte', 'pebibyte' ] for x in units: self.loptions.insert('end', x) self.roptions.insert('end', x) self.loptions.select_set(0) # select first item on the left self.roptions.select_set(0) # select first item on the right # If the contents of an entry box change, update each box self.update_in_progress = False self.left_value.trace("w", lambda a, b, c: self.update_outputs(0)) self.right_value.trace("w", lambda a, b, c: self.update_outputs(1)) def update_outputs(self, *args): if self.update_in_progress: return try: self.update_in_progress = True temp_left = self.left_value.get() temp_right = self.right_value.get() lselection = self.loptions.curselection() left_units = self.loptions.get(lselection[0]) rselection = self.roptions.curselection() right_units = self.roptions.get(rselection[0]) if args[0] == 0: self.right_value.set( convert_dunits(float(temp_left), left_units, right_units)) else: self.left_value.set( convert_dunits(float(temp_right), right_units, left_units)) except ValueError: if args[0] == 0: self.right_value.set("Invalid input!") else: self.left_value.set("Invalid input!") except: print("Unexpected error:", sys.exc_info()[0]) raise self.update_in_progress = False
class Application(ttk.Frame): """The application, which is the main content frame in the root window.""" def __init__(self, root=None, title='Cabinet Calc'): """Construct an Application object.""" if root is None: # Create a new root window to be our master self.root = Tk() else: # Our master will be what was passed in as `root' self.root = root super().__init__(self.root, padding=5) # Instance variables self.root.title(title) self.jobname = StringVar() self.description = StringVar() self.fullwidth = StringVar() self.height = StringVar() self.depth = StringVar() self.fillers = StringVar() self.prim_material = StringVar() self.prim_thickness = StringVar() self.door_material = StringVar() self.door_thickness = StringVar() self.legs = StringVar() self.bottom_thickness = StringVar() self.btmpanel1_thickness = StringVar() self.btmpanel2_thickness = StringVar() self.stacked_btm = StringVar() self.btm_material = StringVar() self.doors_per_cab = IntVar() self.output = '' self.job = None self.initialize_vars() self.make_widgets() def initialize_vars(self): """Initialize all attributes to default vaules.""" self.jobname.set('') self.description.set('') self.fullwidth.set('') self.height.set('') self.depth.set('') self.fillers.set('NEITHER') self.prim_material.set(MATERIALS[PRIM_MAT_DEFAULT]) self.prim_thickness.set(MATL_THICKNESSES[self.prim_material.get()][0]) self.door_material.set(MATERIALS[DOOR_MAT_DEFAULT]) self.door_thickness.set(MATL_THICKNESSES[self.door_material.get()][0]) self.legs.set('no') self.bottom_thickness.set('') self.btmpanel1_thickness.set('') self.btmpanel1_thickness.trace('w', self.btmpnl_thickness_changed) self.btmpanel2_thickness.set('') self.btmpanel2_thickness.trace('w', self.btmpnl_thickness_changed) self.stacked_btm.set('no') self.btm_material.set('') self.doors_per_cab.set(2) self.output = 'No job yet.' self.job = None def make_widgets(self): """Create and layout all the UI elements. Only the widgets that need to be refered to in other parts of the code are made as instance variables (with `self.'). """ ttk.Label(self, text='The Custom Euro-Style Cabinet Configurator').grid( column=0, row=0, sticky=W) inputframe = ttk.Labelframe(self, text='Parameters: ', borderwidth=2, relief='groove', padding=5) ttk.Label(self, text='Job Specification:').grid(column=0, row=2, sticky=W, pady=2) outputframe = ttk.Frame(self, borderwidth=1, relief='sunken') outp_btnsframe = ttk.Frame(self, padding=(0, 10)) self.grid(column=0, row=0, sticky=(N, S, W, E)) inputframe.grid(column=0, row=1, sticky=(N, S, W, E), pady=10) outputframe.grid(column=0, row=3, sticky=(N, S, W, E)) outp_btnsframe.grid(column=0, row=4, sticky=(N, S, W, E)) self.root.columnconfigure(0, weight=1) self.root.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.rowconfigure(3, weight=1) self.fill_inputframe(inputframe) self.fill_outputframe(outputframe) self.fill_outp_btnsframe(outp_btnsframe) def fill_inputframe(self, inpframe): """Layout the widgets for gathering input in the input frame.""" def make_jobframe(): jobframe = ttk.Frame(inpframe, padding=(0, 5, 0, 10)) jobframe.grid(column=0, row=0, sticky=(N, S, W, E)) jobframe.columnconfigure(0, weight=0) jobframe.columnconfigure(1, weight=1) ttk.Label(jobframe, text='Job Name:').grid(column=0, row=0, pady=2, sticky=W) self.jobname_ent = ttk.Entry(jobframe, textvariable=self.jobname, validate='key', validatecommand=(vcmd, '%P')) ttk.Label(jobframe, text='Description:').grid(column=0, row=1, pady=2, sticky=W) self.descrip_ent = ttk.Entry(jobframe, textvariable=self.description, validate='key', validatecommand=(vcmd, '%P')) self.jobname_ent.grid(column=1, row=0, pady=2, sticky=(W, E), padx=(5, 0)) self.descrip_ent.grid(column=1, row=1, pady=2, sticky=(W, E), padx=(5, 0)) self.jobname_ent.focus_set() def make_dimframe(): dimframe = ttk.Frame(inpframe, padding=(0, 10)) dimframe.grid(column=0, row=1, sticky=(N, S, W, E)) dimframe.columnconfigure(0, weight=0) dimframe.columnconfigure(1, weight=1) dimframe.columnconfigure(2, weight=0) dimframe.columnconfigure(3, weight=1) dimframe.columnconfigure(4, weight=0) dimframe.columnconfigure(5, weight=1) ttk.Label(dimframe, text='Width:').grid(column=0, row=0, sticky=W, padx=(0, 3)) self.fullwidth_ent = ttk.Entry(dimframe, width=10, textvariable=self.fullwidth, validate='key', validatecommand=(vcmd, '%P')) ttk.Label(dimframe, text='Height:').grid(column=2, row=0, sticky=E, padx=(6, 3)) self.height_ent = ttk.Entry(dimframe, width=10, textvariable=self.height, validate='key', validatecommand=(vcmd, '%P')) ttk.Label(dimframe, text='Depth:').grid(column=4, row=0, sticky=E, padx=(6, 3)) self.depth_ent = ttk.Entry(dimframe, width=10, textvariable=self.depth, validate='key', validatecommand=(vcmd, '%P')) self.fullwidth_ent.grid(column=1, row=0, sticky=(W, E), padx=3) self.height_ent.grid(column=3, row=0, sticky=(W, E), padx=3) self.depth_ent.grid(column=5, row=0, sticky=(W, E), padx=3) def make_miscframe(): miscframe = ttk.Frame(inpframe, padding=(0, 5)) miscframe.grid(column=0, row=2, sticky=(N, S, W, E)) miscframe.columnconfigure(0, weight=0) miscframe.columnconfigure(1, weight=0) miscframe.columnconfigure(2, weight=0) miscframe.columnconfigure(3, weight=0) miscframe.columnconfigure(4, weight=1) miscframe.columnconfigure(5, weight=1) miscframe.columnconfigure(6, weight=1) ttk.Label(miscframe, text='Fillers for which ends?').grid(column=0, columnspan=2, row=0, sticky=W, padx=(0, 2), pady=2) ttk.Radiobutton(miscframe, value='NEITHER', text='Neither', variable=self.fillers).grid(column=2, row=0, sticky=W, padx=3, pady=2) ttk.Radiobutton(miscframe, value='LEFT', text='Left', variable=self.fillers).grid(column=3, row=0, sticky=W, padx=3, pady=2) ttk.Radiobutton(miscframe, value='RIGHT', text='Right', variable=self.fillers).grid(column=4, row=0, sticky=W, padx=3, pady=2) ttk.Radiobutton(miscframe, value='BOTH', text='Both', variable=self.fillers).grid(column=5, row=0, sticky=W, padx=3, pady=2) ttk.Label(miscframe, text='Material:').grid(column=1, row=1, sticky=(N, W), padx=4, pady=(15, 2)) ttk.Label(miscframe, text='Thickness:').grid(column=2, row=1, sticky=W, padx=4, pady=(15, 2)) ttk.Label(miscframe, text='Measure actual material thickness to the\n' 'nearest 0.01" and adjust values accordingly.').grid( column=3, columnspan=3, row=2, rowspan=2, sticky=(N, W), padx=(8, 4), pady=2) ttk.Label(miscframe, text='Primary:').grid(column=0, row=2, sticky=W, padx=(0, 2), pady=2) self.prim_material_cbx = ttk.Combobox( miscframe, textvariable=self.prim_material, width=max(map(len, MATERIALS)) - 2) self.prim_material_cbx['values'] = MATERIALS # Prevent direct editing of the value in the combobox: self.prim_material_cbx.state(['readonly']) # Call the `selection clear' method when the value changes. It looks # a bit odd visually without doing that. self.prim_material_cbx.bind('<<ComboboxSelected>>', self.prim_material_changed) self.prim_material_cbx.grid(column=1, row=2, sticky=W, padx=(6, 3), pady=2) ttk.Entry(miscframe, textvariable=self.prim_thickness, width=6).grid(column=2, row=2, padx=6, pady=2) ttk.Label(miscframe, text='Doors:').grid(column=0, row=3, sticky=W, padx=(0, 2), pady=2) self.door_material_cbx = ttk.Combobox( miscframe, textvariable=self.door_material, width=max(map(len, MATERIALS)) - 2) self.door_material_cbx['values'] = MATERIALS # Prevent direct editing of the value in the combobox: self.door_material_cbx.state(['readonly']) # Call the `selection clear' method when the value changes. It looks # a bit odd visually without doing that. self.door_material_cbx.bind('<<ComboboxSelected>>', self.door_material_changed) self.door_material_cbx.grid(column=1, row=3, sticky=W, padx=(6, 3), pady=2) # ttk.Label(miscframe, text='Thickness:').grid( # column=4, row=3, sticky=E, padx=4, pady=2) ttk.Entry(miscframe, textvariable=self.door_thickness, width=6).grid(column=2, row=3, padx=6, pady=2) self.legs_thicker_btm_lbl = ttk.Label( miscframe, text='Mounting legs requires bottoms thicker than\n' '3/4" so that leg mounting screws will grab.') self.legs_thicker_btm_lbl.state(['disabled']) self.legs_thicker_btm_lbl.grid(column=3, columnspan=3, row=7, rowspan=2, sticky=(N, W), padx=(8, 4), pady=2) ttk.Checkbutton(miscframe, text='Mount legs on cabinets.', variable=self.legs, command=self.legs_changed, onvalue='yes', offvalue='no').grid(column=0, columnspan=3, row=6, sticky=W, padx=2, pady=(15, 2)) self.bottoms_lbl = ttk.Label(miscframe, text='Bottoms:') self.bottoms_lbl.state(['disabled']) self.bottoms_lbl.grid(column=0, row=9, sticky=W, padx=2, pady=(6, 2)) self.btm_material_lbl = ttk.Label(miscframe, textvariable=self.btm_material, width=max(map(len, MATERIALS)) - 2) self.btm_material_lbl.grid(column=1, row=9, sticky=W, padx=2, pady=(6, 2)) self.bottom_thickness_ent = ttk.Entry( miscframe, textvariable=self.bottom_thickness, width=6) self.bottom_thickness_ent.state(['disabled']) self.bottom_thickness_ent.grid(column=2, row=9, padx=6, pady=(6, 2)) self.stacked_btm_chk = ttk.Checkbutton( miscframe, text='Stack bottom panels:', variable=self.stacked_btm, command=self.stacked_btm_changed, onvalue='yes', offvalue='no') self.stacked_btm_chk.state(['disabled']) self.stacked_btm_chk.grid(column=0, columnspan=2, row=7, sticky=W, padx=(25, 2), pady=2) # ttk.Label(miscframe, text='Upper panel:').grid( # column=1, row=7, sticky=W, padx=(10, 2), pady=2) self.btmpanel1_thickness_ent = ttk.Entry( miscframe, textvariable=self.btmpanel1_thickness, width=6) self.btmpanel1_thickness_ent.state(['disabled']) self.btmpanel1_thickness_ent.grid(column=2, row=7, padx=6, pady=2) # ttk.Label(miscframe, text='Lower panel:').grid( # column=1, row=8, sticky=W, padx=(10, 2), pady=2) self.btmpanel2_thickness_ent = ttk.Entry( miscframe, textvariable=self.btmpanel2_thickness, width=6) self.btmpanel2_thickness_ent.state(['disabled']) self.btmpanel2_thickness_ent.grid(column=2, row=8, padx=6, pady=2) ttk.Label(miscframe, text='Doors per Cabinet:').grid(column=0, columnspan=2, row=10, sticky=W, padx=(0, 6), pady=(15, 2)) drs_per_cab_rb1 = ttk.Radiobutton(miscframe, value=1, text='1', variable=self.doors_per_cab) # Do not allow selection of one door per cabinet. This can only be # enabled after major code changes throughout, to allow for upper # cabinet banks, variable height/width cabinets, etc. drs_per_cab_rb1.state(['disabled']) drs_per_cab_rb1.grid(column=2, row=10, sticky=W, padx=3, pady=(15, 2)) ttk.Radiobutton(miscframe, value=2, text='2', variable=self.doors_per_cab).grid(column=3, row=10, sticky=W, padx=3, pady=(15, 2)) def make_buttonframe(): buttonframe = ttk.Frame(inpframe, padding=(0, 12, 0, 0)) buttonframe.grid(column=0, row=3, sticky=(N, S, W, E)) buttonframe.columnconfigure(0, weight=1) buttonframe.columnconfigure(1, weight=1) buttonframe.columnconfigure(2, weight=1) buttonframe.rowconfigure(0, weight=1) self.calc_button = ttk.Button(buttonframe, text='Calculate', command=self.calculate_job) self.calc_button.state(['disabled']) clear_button = ttk.Button(buttonframe, text='Clear', command=self.clear_input) quit_button = ttk.Button(buttonframe, text='Quit', command=self.quit) self.calc_button.grid(column=0, row=0, sticky=E, padx=2) clear_button.grid(column=1, row=0, sticky=W, padx=2) quit_button.grid(column=2, row=0, padx=2) # Register our validate function to get its function ID. This is used # to disable the `Calculate' button if the fields necessary for # calculation are not filled in. vcmd = self.root.register(self.validate_entry) make_jobframe() make_dimframe() make_miscframe() make_buttonframe() inpframe.columnconfigure(0, weight=1) def fill_outputframe(self, outpframe): """Layout the widgets for showing output in the output frame.""" # self.output_lbl = ttk.Label(outpframe, textvariable=self.output, # font='TkFixedFont') # self.output_lbl.grid(column=0, row=0, sticky=(N, S, E, W), pady=(0, 50)) outpframe.columnconfigure(0, weight=1) outpframe.columnconfigure(1, weight=0) outpframe.rowconfigure(0, weight=1) self.output_txt = Text(outpframe, height=3, relief='flat', background='gray85', font='TkFixedFont') self.output_sb = ttk.Scrollbar(outpframe, orient='vertical', command=self.output_txt.yview) self.output_txt.configure(yscrollcommand=self.output_sb.set) self.output_txt.grid(column=0, row=0, sticky=(N, S, W, E)) self.output_sb.grid(column=1, row=0, sticky=(N, S, E)) self.output_txt.insert('end', self.output) self.output_txt.configure(state='disabled') def fill_outp_btnsframe(self, outp_btnsframe): """Layout the output-dependent buttons in the output buttons frame.""" outp_btnsframe.columnconfigure(0, weight=1) outp_btnsframe.columnconfigure(1, weight=1) outp_btnsframe.rowconfigure(0, weight=1) self.cutlist_button = ttk.Button(outp_btnsframe, text='Save Cutlist', command=self.save_cutlist) self.cutlist_button.state(['disabled']) self.panel_layout_btn = ttk.Button(outp_btnsframe, text='Optimize Panel Layout', command=self.optimize_panel_layout) self.panel_layout_btn.state(['disabled']) self.cutlist_button.grid(column=0, row=0, sticky=E, padx=2) self.panel_layout_btn.grid(column=1, row=0, sticky=W, padx=2) def validate_entry(self, value): """Enable the 'Calculate' button only when we have enough info.""" if self.have_enough_info(): self.calc_button.state(['!disabled']) else: self.calc_button.state(['disabled']) return True def have_enough_info(self): """Return True if we have enough info to calculate a job, False otherwise.""" result = (self.jobname_ent.get() != '' and self.fullwidth_ent.get() != '' and self.height_ent.get() != '' and self.depth_ent.get() != '') return result def prim_material_changed(self, e): """Handle the changing of the primary build material for the job.""" self.prim_thickness.set(MATL_THICKNESSES[self.prim_material.get()][0]) self.prim_material_cbx.selection_clear() if self.legs.get() == 'yes': self.btm_material.set(self.prim_material.get()) btm_thicknesses = MATL_THICKNESSES[self.prim_material.get()][1] self.bottom_thickness.set(sum(btm_thicknesses)) if len(btm_thicknesses) > 1: self.stacked_btm.set('yes') self.btmpanel1_thickness.set(btm_thicknesses[0]) self.btmpanel1_thickness_ent.state(['!disabled']) self.btmpanel2_thickness.set(btm_thicknesses[1]) self.btmpanel2_thickness_ent.state(['!disabled']) self.bottom_thickness_ent.state(['disabled']) else: self.stacked_btm.set('no') self.btmpanel1_thickness.set('') self.btmpanel1_thickness_ent.state(['disabled']) self.btmpanel2_thickness.set('') self.btmpanel2_thickness_ent.state(['disabled']) self.bottom_thickness_ent.state(['!disabled']) def door_material_changed(self, e): """Handle the changing of the door material for the job.""" self.door_thickness.set(MATL_THICKNESSES[self.door_material.get()][0]) self.door_material_cbx.selection_clear() def legs_changed(self): """Handle the changing of whether the cabinets will have legs or not.""" if self.legs.get() == 'yes': self.legs_thicker_btm_lbl.state(['!disabled']) self.bottoms_lbl.state(['!disabled']) self.btm_material.set(self.prim_material.get()) btm_thicknesses = MATL_THICKNESSES[self.prim_material.get()][1] self.bottom_thickness.set(sum(btm_thicknesses)) self.bottom_thickness_ent.state(['!disabled']) self.stacked_btm.set('no') self.stacked_btm_chk.state(['!disabled']) if len(btm_thicknesses) > 1: self.stacked_btm.set('yes') self.btmpanel1_thickness.set(btm_thicknesses[0]) self.btmpanel1_thickness_ent.state(['!disabled']) self.btmpanel2_thickness.set(btm_thicknesses[1]) self.btmpanel2_thickness_ent.state(['!disabled']) self.bottom_thickness_ent.state(['disabled']) else: self.legs_thicker_btm_lbl.state(['disabled']) self.bottoms_lbl.state(['disabled']) self.btm_material.set('') self.bottom_thickness.set('') self.bottom_thickness_ent.state(['disabled']) self.btmpanel1_thickness.set('') self.btmpanel1_thickness_ent.state(['disabled']) self.btmpanel2_thickness.set('') self.btmpanel2_thickness_ent.state(['disabled']) self.stacked_btm.set('no') self.stacked_btm_chk.state(['disabled']) def stacked_btm_changed(self): """Handle the changing of whether cabinet bottoms will be stacked or not.""" if self.stacked_btm.get() == 'yes': half_btm = float(self.bottom_thickness.get()) / 2 self.btmpanel1_thickness_ent.state(['!disabled']) self.btmpanel1_thickness.set(half_btm) self.btmpanel2_thickness_ent.state(['!disabled']) self.btmpanel2_thickness.set(half_btm) self.bottom_thickness_ent.state(['disabled']) else: self.btmpanel1_thickness.set('') self.btmpanel1_thickness_ent.state(['disabled']) self.btmpanel2_thickness.set('') self.btmpanel2_thickness_ent.state(['disabled']) self.bottom_thickness_ent.state(['!disabled']) def btmpnl_thickness_changed(self, *args): """Handle the changing of the thickness of cabinet bottom panels.""" if self.stacked_btm.get() == 'yes': if self.btmpanel1_thickness.get() == '': bp1 = 0.0 else: bp1 = float(self.btmpanel1_thickness.get()) if self.btmpanel2_thickness.get() == '': bp2 = 0.0 else: bp2 = float(self.btmpanel2_thickness.get()) new_thickness = bp1 + bp2 if new_thickness == 0.0: thickness_str = '' else: thickness_str = str(new_thickness) self.bottom_thickness.set(thickness_str) def quit(self): """Quit the app; accomplished by destroying its top-level window.""" self.root.destroy() def clear_input(self): """Clear and reset all input widgets to default values.""" self.initialize_vars() self.legs_thicker_btm_lbl.state(['disabled']) self.bottoms_lbl.state(['disabled']) self.bottom_thickness_ent.state(['disabled']) self.btmpanel1_thickness_ent.state(['disabled']) self.btmpanel2_thickness_ent.state(['disabled']) self.stacked_btm_chk.state(['disabled']) self.calc_button.state(['disabled']) self.cutlist_button.state(['disabled']) self.panel_layout_btn.state(['disabled']) self.output_txt.configure(state='normal', height=3) self.output_txt.delete('1.0', 'end') self.output_txt.insert('end', self.output) self.output_txt.configure(state='disabled') def calculate_job(self): """Calculate a job, given all input parameters.""" if self.legs.get() == 'no': bp_list = [float(self.prim_thickness.get())] else: if self.stacked_btm.get() == 'yes': bp1 = float(self.btmpanel1_thickness.get()) bp2 = float(self.btmpanel2_thickness.get()) bp_list = [bp1, bp2] else: bt = float(self.bottom_thickness.get()) bp_list = [bt] cab_run = Run(float(self.fullwidth.get()), float(self.height.get()), float(self.depth.get()), fillers=Ends.from_string(self.fillers.get()), prim_material=self.prim_material.get(), prim_thickness=float(self.prim_thickness.get()), door_material=self.door_material.get(), door_thickness=float(self.door_thickness.get()), btmpanel_thicknesses=bp_list, has_legs=yn_to_bool(self.legs.get())) if self.description.get() != '': self.job = job.Job(self.jobname.get(), cab_run, self.description.get()) else: self.job = job.Job(self.jobname.get(), cab_run) # Display the computed job specification, ensuring output lines are no # longer than 65 chars. self.output = '' for line in self.job.specification: self.output += textwrap.fill(line, width=65) + '\n' lines = self.output.count('\n') + 1 self.output_txt.configure(state='normal') self.output_txt.delete('1.0', 'end') self.output_txt.insert('end', self.output) self.output_txt.configure(state='disabled', height=lines + 1) # self.output_txt.grid_configure(pady=0) self.cutlist_button.state(['!disabled']) def save_cutlist(self): """Generate a cutlist pdf for the job and save it in a file.""" filename = filedialog.asksaveasfilename( title='Filename to Save Cutlist As', parent=self.root, filetypes=(('PDF Files', '*.pdf'), ('All Files', '*'))) if filename != '': cutlist.save_cutlist(filename, self.job) def optimize_panel_layout(self): """Optimize the panel layout.""" pass
class FilePick(Frame): def __init__(self, master, file_mask, default_file, user_onChange = None, font = None, dirs = (".", ), allowNone = False): """ file_mask: file mask or list of file masks """ self.master = master self.user_onChange = user_onChange Frame.__init__(self, master) self.columnconfigure(0, weight=1) self.unmodified = True self.file_extension = "" if "." in file_mask: self.file_extension = file_mask[file_mask.rfind('.'):] if type(file_mask) != list: file_mask = [file_mask] self.file_masks = file_mask self.allowNone = allowNone self.dirs = dirs # create list of files self.updateList() # pick default if applicable self.set(default_file) def onSelChange(self, name, index=0, mode=0): filename = self.picked_name.get() if self.user_onChange != None: self.user_onChange(filename) def updateList(self): prev_sel = self.get() # get list of files (paths) self.files = [] if self.allowNone: self.files.append("") for fm in self.file_masks: for dir in self.dirs: try: for filename in os.listdir(dir): if fnmatch(filename, fm): if dir != ".": path = os.path.join(dir, filename) else: path = filename self.files.append(path) except: pass self.files.sort() if len(self.files) == 0: self.files.append("(no %s files found)" % self.file_masks) # create list object self._makelist() # reselect self.set(prev_sel) def getList(self): """ returns the current list of files """ return self.files def _makelist(self): if havePMW: self.list = ComboBox(self, selectioncommand = self.onSelChange, scrolledlist_items = self.files, ) self.list.grid(row=0, column=0, padx=0, sticky="NEWS") self.list.component('entryfield').component('entry').configure(state = 'readonly', relief = 'raised') self.picked_name = self.list else: self.picked_name = StringVar() self.list = OptionMenu(*(self, self.picked_name) + tuple(self.files)) self.list.grid(row=0, column=0, sticky="NEW") self.picked_name.trace("w", self.onSelChange) def set(self, filename): default_file = filename if default_file in self.files: if not havePMW: self.picked_name.set(default_file) # default value else: self.list.selectitem(self.files.index(default_file)) self.onSelChange(default_file) pass def get(self): if not hasattr(self, 'picked_name'): return None return self.picked_name.get()
class Plastey(Tk): #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # def __init__(self, *args, **kwargs): Tk.__init__(self, *args, **kwargs) # Set window title self.wm_title('Plastey Configurator') # Create GUI driven variables self._mode = BooleanVar() self._base = BooleanVar() self._comm = BooleanVar() self._pass = StringVar() self._addressed = StringVar() self._connected = StringVar() self._this_host = StringVar() self._this_port = StringVar() self._other_host = StringVar() self._other_port = StringVar() # Create GUI self._build_gui() # Set default values for GUI driven variables self._mode.set(MODE_SINGLE_PLAYER) self._base.set(BASE_OPENED_GEOMETRY) self._comm.set(COMM_SOCKET_SERVER) self._pass.set('') self._addressed.set(ADDR_HAVE_ADDRESS if check(COMM_THIS_HOST) else ADDR_NO_ADDRESS) self._connected.set(CONN_NOT_CONNECTED) self._this_host.set(COMM_THIS_HOST) self._this_port.set(COMM_THIS_PORT) self._other_host.set(COMM_THIS_HOST) self._other_port.set(COMM_OTHER_PORT) # Follow changes on password self._pass.trace('w', self._on_bind_address) # Create folder structures if they don't exists yet makedirs(FILE_TEMPORARY_FOLDER, exist_ok=True) makedirs(FILE_PERMANENT_FOLDER, exist_ok=True) makedirs(FILE_TEMP_SAVE_FOLDER, exist_ok=True) makedirs(FILE_AUTO_SAVE_FOLDER, exist_ok=True) #makedirs(FILE_TEMP_STATE_FOLDER, exist_ok=True) #makedirs(FILE_TEMP_FEEDS_FOLDER, exist_ok=True) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # def _build_gui(self): # Create GUI sections row = 0 col = 0 # Warning text Label(master = self, text = WARN_TEXT, anchor = WEST, justify = CENTER).grid(row = row, column = col, sticky = NORTH_WEST, rowspan = 16) # Set column spacing self.columnconfigure(index = col, pad = GUI_SECTION_PAD_X) row = 0 col += 1 # Game mode options Label(master = self, text = 'Game Mode:').grid(row = row, column = col, sticky = WEST) row += 1 Radiobutton(master = self, text = 'Single Player', value = MODE_SINGLE_PLAYER, variable = self._mode).grid(row = row, column = col, sticky = WEST) row += 1 Radiobutton(master = self, text = 'Multi Player', value = MODE_MULTI_PLAYER, variable = self._mode).grid(row = row, column = col, sticky = WEST) row += 1 # Base object modes Label(master = self, text = 'Base Object:').grid(row = row, column = col, sticky = WEST) row += 1 Radiobutton(master = self, text = 'Plane mesh', value = BASE_OPENED_GEOMETRY, variable = self._base).grid(row = row, column = col, sticky = WEST) row += 1 Radiobutton(master = self, text = 'Sphere mesh', value = BASE_CLOSED_GEOMETRY, variable = self._base).grid(row = row, column = col, sticky = WEST) row += 1 # Start oculus-daemon Label(master = self, text = 'Daemons:').grid(row = row, column = col, sticky = WEST) row += 1 Button(master = self, text = 'Start OVRD', command = self._on_start_oculus_daemon).grid(row = row, column = col, sticky = WEST) # Set column spacing self.columnconfigure(index = col, pad = GUI_SECTION_PAD_X) row = 0 col += 1 # Multiplayer mode options Label(master = self, text = 'Multi Player Options:').grid(row = row, column = col, sticky = WEST, columnspan = 2) row += 1 Label(master = self, text = 'This role:').grid(row = row, column = col, sticky = WEST) Radiobutton(master = self, text = 'Server', value = COMM_SOCKET_SERVER, variable = self._comm).grid(row = row, column = col + 1, sticky = WEST) row += 1 Radiobutton(master = self, text = 'Client', value = COMM_SOCKET_CLIENT, variable = self._comm).grid(row = row, column = col + 1, sticky = WEST) row += 1 Label(master = self, text = 'This host:').grid(row = row, column = col, sticky = WEST) Entry(master = self, textvariable = self._this_host).grid(row = row, column = col + 1, sticky = WEST) row += 1 Label(master = self, text = 'This port:').grid(row = row, column = col, sticky = WEST) Entry(master = self, textvariable = self._this_port).grid(row = row, column = col + 1, sticky = WEST) row += 1 Label(master = self, text = 'Other host:').grid(row = row, column = col, sticky = WEST) Entry(master = self, textvariable = self._other_host).grid(row = row, column = col + 1, sticky = WEST) row += 1 Label(master = self, text = 'Other port:').grid(row = row, column = col, sticky = WEST) Entry(master = self, textvariable = self._other_port).grid(row = row, column = col + 1, sticky = WEST) row += 1 Button(master = self, text = 'Bind address', command = self._on_ask_password).grid(row = row, column = col, sticky = WEST + EAST) Label(master = self, textvariable = self._addressed).grid(row = row, column = col + 1, sticky = WEST) row += 1 Button(master = self, text = 'Connect machines', command = self._on_bind_address).grid(row = row, column = col, sticky = WEST + EAST) Label(master = self, textvariable = self._connected).grid(row = row, column = col + 1, sticky = WEST) # Set column spacing self.columnconfigure(index = col + 1, pad = GUI_SECTION_PAD_X) row = 0 col += 2 # Controller buttons Label(master = self, text = 'Controllers:').grid(row = row, column = col, sticky = WEST) row += 1 Button(master = self, text = 'Start game', command = self._on_start_game).grid(row = row, column = col, sticky = WEST + EAST) row += 1 Button(master = self, text = 'Restart game', command = self._on_restart_game).grid(row = row, column = col, sticky = WEST + EAST) row += 1 Button(master = self, text = 'Stop game', command = self._on_stop_game).grid(row = row, column = col, sticky = WEST + EAST) row += 1 Button(master = self, text = 'Save last mesh', command = self._on_save_mesh).grid(row = row, column = col, sticky = WEST + EAST) row += 1 Button(master = self, text = 'Load last mesh', command = self._on_load_mesh).grid(row = row, column = col, sticky = WEST + EAST) row += 1 Button(master = self, text = 'Save log file', command = self._on_save_log).grid(row = row, column = col, sticky = WEST + EAST) row += 1 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # def _on_ask_password(self, *args, **kwargs): # Create a password-dialog self._dialog = Password(self._pass) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # def _on_start_oculus_daemon(self, *args, **kwargs): print('starting daemon...') #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # def _on_bind_address(self, *args, **kwargs): # Check for status and if address is not bound if not check(COMM_THIS_HOST): # Bind address try: setup(self._this_host, user_pass=self._pass.get()) except CommunicationSetupError as exception: Report(exception.error) # Check status and report to user self._addressed.set(ADDR_HAVE_ADDRESS if check(COMM_THIS_HOST) else ADDR_NO_ADDRESS) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # def _on_connect(self, *args, **kwargs): pass #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # def _on_start_game(self, *args, **kwargs): # HACK: Is this really the best option we have, to get into fullscreen, # other than using the blender's fullscreen option, which will # unfortunately resize the display's resolution??? :( window_command = ['sleep 1'] window_command.append('wmctrl -r :ACTIVE: ' '-e 0,{},{},{},{}'.format(DRAW_DISPLAY_X, DRAW_DISPLAY_Y, DRAW_RESOLUTION_X, DRAW_RESOLUTION_Y)) if DRAW_FULL_SCREEN: window_command.append('wmctrl -r :ACTIVE: -b add,fullscreen') Popen(args = ' && '.join(window_command), shell = True, stdin = PIPE, stderr = PIPE, universal_newlines=True) # Store subprocess, for further communication self._pipe = Popen(args = './plastey', stdin = PIPE, stdout = PIPE, stderr = PIPE, universal_newlines=True) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # def _on_restart_game(self, *args, **kwargs): self._pipe.stdin.write('hello-world\n') #if not self._locked: # self._locked = True # with open(FILE_STATE_RESTART, mode='w') as file: # file.write('') # Thread(name = 'feedbackd-restart', # target = self._get_feedback_to_clean_up).start() #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # def _on_stop_game(self, *args, **kwargs): #if not self._locked: # self._locked = True # with open(FILE_STATE_SHUT_DOWN, mode='w') as file: # file.write('') # Thread(name = 'feedbackd-shutdown', # target = self._get_feedback_to_clean_up).start() self._pipe.communicate('hello-world\n') #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # def _on_save_mesh(self, *args, **kwargs): pass #if self._pipe.poll(): # print('saving inside game') #else: # print('save last auto-saved') #print('parent says: hey there, daemon!\n') #self._pipe.stdin.write('hey there, daemon!\n') #self._pipe.stdin.close() #try: # self._pipe.communicate('hey there, daemon!\n', timeout=0.1) ## Hack: since communicate waits for the subprocess to terminate, the ## timeout value is necessary, however, after the timeout, the app ## won't terminate either. One solution should be ## self._pipe.stdin.write instead of the communicate method, but ## unfortunately the process's stdin.read/input are not getting ## anything.. is it because the value set to shell=True? #except TimeoutExpired: # return #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # def _on_load_mesh(self, *args, **kwargs): pass #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # def _on_save_log(self, *args, **kwargs): pass #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # def run(self): self.mainloop()
class PlaylistControl(Frame): def __init__(self, w, *args, **kwargs): self.EMPTY_SEARCH_TEXT = _( "Search song...") #After defined _ by gettext self.playlist = w.playlist super().__init__(w, *args, **kwargs) #___ self.playlist_handler_edit = TkButtonImgHoverBg( self, command=lambda: TopLevelPlaylistEdit(self) if config.general["playlist"] != "" else None, imgs=(PhotoImage(data=b64img.btn_configplaylist), ), bg=config.colors["BG"], bg_on_hover=config.colors["BTN_BG_HOVER"]) self.playlist_handler_edit.grid(row=0, column=0, sticky="nsew") #___ self.playlist_handler_set = PlaylistHandlerSet(self) self.playlist_handler_set.grid(row=0, column=1, sticky="nsew", padx=(5, 8), pady=5) #___ #When the text is changed, the search function will be called self.state_entry_search = StringVar() self.state_entry_search.trace('w', self._search) self.entry_search = Entry(self, width=15, textvariable=self.state_entry_search) self.entry_search.grid(row=0, column=2, sticky="nsew", pady=5) self.entry_search.insert(0, self.EMPTY_SEARCH_TEXT) self.entry_search.bind("<FocusIn>", self._entryFocusEnter) self.entry_search.bind("<FocusOut>", self._entryFocusLeave) #___ self.btn_search = TkButtonImgHoverBg( self, command=self._entryClear, imgs=(PhotoImage(data=b64img.btn_quitsearch), ), bg=config.colors["BG"], bg_on_hover=config.colors["BTN_BG_HOVER"]) self.btn_search.grid(row=0, column=3, sticky="nsew", padx=(0, 5), pady=5) #___ self.btn_sorttitle = TkButtonImgHoverBg( self, command=lambda: self._sortPlaylist(self.btn_sorttitle, "title"), imgs=(PhotoImage(data=b64img.btn_sorttitle), PhotoImage(data=b64img.btn_sorttitle_up), PhotoImage(data=b64img.btn_sorttitle_down)), bg=config.colors["BG"], bg_on_hover=config.colors["BTN_BG_HOVER"]) self.btn_sorttitle.grid(row=0, column=4, sticky="nsew") #___ self.btn_sortdate = TkButtonImgHoverBg( self, command=lambda: self._sortPlaylist(self.btn_sortdate, "date"), imgs=(PhotoImage(data=b64img.btn_sortdate), PhotoImage(data=b64img.btn_sortdate_up), PhotoImage(data=b64img.btn_sortdate_down)), bg=config.colors["BG"], bg_on_hover=config.colors["BTN_BG_HOVER"], change_img_on_click=True) self.btn_sortdate.grid(row=0, column=5, sticky="nsew") #___ self.btn_sorttime = TkButtonImgHoverBg( self, command=lambda: self._sortPlaylist(self.btn_sorttime, "time"), imgs=(PhotoImage(data=b64img.btn_sorttime), PhotoImage(data=b64img.btn_sorttime_up), PhotoImage(data=b64img.btn_sorttime_down)), bg=config.colors["BG"], bg_on_hover=config.colors["BTN_BG_HOVER"], change_img_on_click=True) self.btn_sorttime.grid(row=0, column=6, sticky="nsew") #___ self.btn_sorttitle.set_img(1) self.__btn_sort_active: Tuple[TkButtonImgHoverBg, str] = [self.btn_sorttitle, 1] #__________________________________________________ def _entryFocusEnter(self, _event): #Delete default text if self.entry_search.get() == self.EMPTY_SEARCH_TEXT: self.entry_search.delete(0, "end") def _entryFocusLeave(self, _event): #Delete text and insert default text if is invalid text if not validEntryText(self.entry_search.get()): self.entry_search.delete(0, "end") self.entry_search.insert(0, self.EMPTY_SEARCH_TEXT) config.playlist["filter"] = "" def _entryClear(self): #Delete text and insert default text if there is no focus if self.entry_search.get() != self.EMPTY_SEARCH_TEXT: self.entry_search.delete(0, "end") config.playlist["filter"] = "" if self.focus_get() != self.entry_search: self.entry_search.insert(0, self.EMPTY_SEARCH_TEXT) def _search(self, *_event): song_name = self.state_entry_search.get() if song_name != self.EMPTY_SEARCH_TEXT: self.playlist.filterName(song_name) config.playlist["filter"] = song_name def setSearch(self, song_name: str): if validEntryText(song_name): self.entry_search.delete(0, "end") self.entry_search.insert(0, song_name) else: self._entryClear() #___ def _sortPlaylist(self, btn: TkButtonImgHoverBg, atr: str): #If click on another sort btn if btn != self.__btn_sort_active[0]: self.__btn_sort_active[0].set_img(0) #Previous btn to normal if btn == self.btn_sorttitle: btn.set_img( 1) #Set title btn to up, the others are set automatically self.__btn_sort_active = [btn, 1] #Status is updated self.playlist.sortBy(atr, False) config.playlist["orderby"] = [atr, 1] #If click on the same sort btn else: #If the btn was in up if self.__btn_sort_active[1] == 1: if btn == self.btn_sorttitle: btn.set_img( 2 ) #Set title btn to down, the others are set automatically self.__btn_sort_active[1] = 2 #Status is updated self.playlist.sortBy(atr, True) config.playlist["orderby"] = [atr, 2] #If the btn was in down elif self.__btn_sort_active[1] == 2: self.btn_sorttitle.set_img( 1 ) #Set title btn to down, the others are set automatically self.__btn_sort_active = [self.btn_sorttitle, 1] #Status is updated self.playlist.sortBy("title", False) config.playlist["orderby"] = ["title", 1] def sortPlaylistForced(self, atr: str, order: int): if atr == "date": self.btn_sortdate.set_img(order) self.btn_sorttitle.set_img(0) self.btn_sorttime.set_img(0) self.__btn_sort_active[0] = self.btn_sortdate elif atr == "time": self.btn_sorttime.set_img(order) self.btn_sorttitle.set_img(0) self.btn_sortdate.set_img(0) self.__btn_sort_active[0] = self.btn_sorttime else: self.btn_sorttitle.set_img(order) self.btn_sortdate.set_img(0) self.btn_sorttime.set_img(0) self.__btn_sort_active[0] = self.btn_sorttitle self.__btn_sort_active[1] = order self.playlist.sortBy(atr, order - 1) #0(False) if order==1 | 1(True) if order==2
def fileWindow(root): '''Makes the window that lets the user specify save files and options.''' def nextPage(): global oldGen2, oldGen3, newGame, language, gender oldGen2 = fromText.get() oldGen3 = toText.get() newGame = gameCombo.get() language = langCombo.get() gender = genderCombo.get() with open(oldGen2, 'br') as file: root.boxes = getBoxes(file.read()) root.nextPage() def nextToggle(*args): if fromText.get() == '' or toText.get() == '': navFrame.disable('next', True) else: navFrame.disable('next', False) def fromDialog(): askOpen = filedialog.askopenfilename file = askOpen(title='Gen II Save File', initialdir=root.dir, filetypes=[('GB Save', '.sav'), ('All Files', '.*')]) if file != '': fromText.set(file) fromEntry.after_idle(fromEntry.xview_moveto, 1) root.dir = getDir(file) def toDialog(): askOpen = filedialog.askopenfilename file = askOpen(title='Gen III Save File', initialdir=root.dir, filetypes=[('GBA Save', '.sav'), ('All Files', '.*')]) if file != '': toText.set(file) toEntry.after_idle(toEntry.xview_moveto, 1) root.dir = getDir(file) def getBoxes(data): from pokeBridge import Box, OldSaveFile boxes = [] for offset in OldSaveFile.BOX_OFFSETS: box = [] count = data[offset] for i in range(count): box.append(data[offset + 1 + i]) for i in range(Box.OLD_SIZE - len(box)): #pad with 0 box.append(0x0) boxes.append(box) return boxes baseFrame = ttk.Frame(root) baseFrame.rowconfigure(0, weight=1) baseFrame.columnconfigure(0, weight=1) mainFrame = ttk.Frame(baseFrame, padding=MAIN_PAD) mainFrame.grid(row=0, column=0) mainFrame.rowconfigure(0, weight=1) mainFrame.columnconfigure(0, weight=1) pickerFrame = ttk.Frame(mainFrame) pickerFrame.grid(row=0, column=0, sticky='s') pickText = "Select the Gen II save file to transfer Pok\u00E9mon from and the Gen III save file to transfer Pok\u00E9mon to." pickLabel = ttk.Label(pickerFrame, text=pickText, wraplength=WIDTH-50, justify='center') pickLabel.grid(row=0, column=0, columnspan=2, pady=10) fromButton = ttk.Button(pickerFrame, text='From...', command=fromDialog) fromButton.grid(row=1, column=0, sticky='e', padx=5, pady=5) fromText = StringVar() fromText.trace('w', nextToggle) fromEntry = ttk.Entry(pickerFrame, textvariable=fromText, state='readonly') fromEntry.grid(row=1, column=1, sticky='w', padx=5, pady=5) toButton = ttk.Button(pickerFrame, text='To...', command=toDialog) toButton.grid(row=2, column=0, sticky='e', padx=5, pady=5) toText = StringVar() toText.trace('w', nextToggle) toEntry = ttk.Entry(pickerFrame, textvariable=toText, state='readonly') toEntry.grid(row=2, column=1, sticky='w', padx=5, pady=5) optionFrame = ttk.Frame(mainFrame) optionFrame.grid(row=1, column=0) optionText = "Select the appropriate options from the drop-down menus below." optionLabel = ttk.Label(optionFrame, text=optionText) optionLabel.grid(row=0, column=0, columnspan=2, pady=10) gameChoices = ['Ruby', 'Sapphire', 'Emerald', 'FireRed', 'LeafGreen'] langChoices = ['English', 'Japanese', 'French', 'Italian', 'German', 'Korean', 'Spanish'] genderChoices = ['Male', 'Female'] gameLabel = ttk.Label(optionFrame, text='Destination Game') gameLabel.grid(row=1, column=0, sticky='e', padx=5, pady=5) gameCombo = ttk.Combobox(optionFrame, values=gameChoices, state='readonly') gameCombo.set(gameChoices[0]) gameCombo.grid(row=1, column=1, sticky='w', padx=5, pady=5) langLabel = ttk.Label(optionFrame, text='Game Language') langLabel.grid(row=2, column=0, sticky='e', padx=5, pady=5) langCombo = ttk.Combobox(optionFrame, values=langChoices, state='readonly') langCombo.set(langChoices[0]) langCombo.grid(row=2, column=1, sticky='w', padx=5, pady=5) genderLabel = ttk.Label(optionFrame, text='OT Gender') genderLabel.grid(row=3, column=0, sticky='e', padx=5, pady=5) genderCombo = ttk.Combobox(optionFrame, values=genderChoices, state='readonly') genderCombo.set(genderChoices[0]) genderCombo.grid(row=3, column=1, sticky='w', padx=5, pady=5) navFrame = Nav(baseFrame, root.prevPage, nextPage) navFrame.grid(row=1, column=0, sticky='we') if debug: fromText.set('C:/Users/Sidnoea/Documents/GitHub/pokeBridge/Old Gen 2.sav') toText.set('C:/Users/Sidnoea/Documents/GitHub/pokeBridge/Old Gen 3.sav') nextToggle() return (baseFrame, 'Select Save Files', {'sticky':'nsew'})
class NewMorphLineWindow(Toplevel): def __init__(self, master=None): super().__init__(master=master) self.set_basic() self.set_widgets() def set_basic(self): self.minsize(600, 400) self.maxsize(600, 400) self.title("Ekstrakcja linii") self.protocol("WM_DELETE_WINDOW", lambda: self.cancel()) self.handleBorder = { "Bez zmian (isolated)": 0, "Odbicie lustrzane (reflect)": 1, "Powielenie skrajnego piksela (replicate)": 2 } def set_widgets(self): self.horizontalSizeW = StringVar(self, value="3") self.horizontalSizeH = StringVar(self, value="1") self.verticalSizeW = StringVar(self, value="3") self.verticalSizeH = StringVar(self, value="1") self.borderType = StringVar(self, list(self.handleBorder.keys())[0]) self.cbVarHorizontal = IntVar(value=1) self.cbVarVertical = IntVar(value=1) self.cbVarOuter = IntVar(value=1) self.cbVarNegate = IntVar(value=0) self.sizeHorizontalWSpin = Spinbox(self, justify='center', font=("Helvetica", 15), from_=1, to=9999, textvariable=self.horizontalSizeW, command=self.update_preview, state='readonly', increment=2) self.sizeHorizontalHSpin = Spinbox(self, justify='center', font=("Helvetica", 15), from_=1, to=9999, textvariable=self.horizontalSizeH, command=self.update_preview, state='readonly', increment=2) self.sizeVerticalWSpin = Spinbox(self, justify='center', font=("Helvetica", 15), from_=1, to=9999, textvariable=self.verticalSizeW, command=self.update_preview, state='readonly', increment=2) self.sizeVerticalHSpin = Spinbox(self, justify='center', font=("Helvetica", 15), from_=1, to=9999, textvariable=self.verticalSizeH, command=self.update_preview, state='readonly', increment=2) self.horizontalSizeW.trace("w", self.update_preview) self.horizontalSizeH.trace("w", self.update_preview) self.verticalSizeW.trace("w", self.update_preview) self.verticalSizeH.trace("w", self.update_preview) self.borderType.trace("w", self.update_preview) self.cbVarHorizontal.trace("w", self.update_preview) self.cbVarVertical.trace("w", self.update_preview) self.cbVarOuter.trace("w", self.update_preview) self.cbVarNegate.trace("w", self.update_preview) self.cbHorizontal = Checkbutton(self, width=0, variable=self.cbVarHorizontal) self.cbVertical = Checkbutton(self, width=0, variable=self.cbVarVertical) self.cbOuterOnly = Checkbutton(self, width=0, variable=self.cbVarOuter) self.cbNegateFirst = Checkbutton(self, width=0, variable=self.cbVarNegate) self.borderList = OptionMenu(self, self.borderType) for border in self.handleBorder: self.borderList['menu'].add_command( label=border, command=lambda v=border: self.borderType.set(v)) self.saveButton = Button(self, image=saveIcon, command=self.update_image) self.cancelButton = Button(self, image=closeIcon, command=self.cancel) self.update_preview() self.place_widgets() def update_image(self): self.master.image.cv2Image = copy.deepcopy(self.master.image.copy) self.master.image.morph_line(int(self.horizontalSizeW.get()), int(self.horizontalSizeH.get()), int(self.verticalSizeW.get()), int(self.verticalSizeH.get()), self.cbVarHorizontal.get(), self.cbVarVertical.get(), self.handleBorder[self.borderType.get()], self.cbVarOuter.get(), self.cbVarNegate.get()) self.master.image.copy = copy.deepcopy(self.master.image.cv2Image) self.master.manager.new_state(self.master.image.cv2Image) self.master.update_visible_image() self.master.update_child_windows() self.destroy() def update_preview(self, *args): self.sizeHorizontalWSpin.config(from_=int(self.horizontalSizeH.get()) + 2) self.sizeHorizontalHSpin.config(to=int(self.horizontalSizeW.get()) - 2) self.sizeVerticalWSpin.config(from_=int(self.verticalSizeH.get()) + 2) self.sizeVerticalHSpin.config(to=int(self.verticalSizeW.get()) - 2) self.master.image.cv2Image = copy.deepcopy(self.master.image.copy) self.master.image.morph_line(int(self.horizontalSizeW.get()), int(self.horizontalSizeH.get()), int(self.verticalSizeW.get()), int(self.verticalSizeH.get()), self.cbVarHorizontal.get(), self.cbVarVertical.get(), self.handleBorder[self.borderType.get()], self.cbVarOuter.get(), self.cbVarNegate.get()) self.master.update_visible_image() self.master.update_child_windows() def place_widgets(self): Label(self, text="Poziome linie", font=("Helvetica", 15)).place(x=85, y=15) Label(self, text="Pionowe linie", font=("Helvetica", 15)).place(x=395, y=15) self.sizeHorizontalWSpin.place(width=100, height=50, x=150, y=60) self.sizeHorizontalHSpin.place(width=100, height=50, x=150, y=120) self.sizeVerticalWSpin.place(width=100, height=50, x=450, y=60) self.sizeVerticalHSpin.place(width=100, height=50, x=450, y=120) Label(self, text="Min. długość", font=("Helvetica", 15)).place(x=30, y=70) Label(self, text="Min. grubość", font=("Helvetica", 15)).place(x=30, y=130) Label(self, text="Min. długość", font=("Helvetica", 15)).place(x=330, y=70) Label(self, text="Min. grubość", font=("Helvetica", 15)).place(x=330, y=130) Label(self, text="Szukać poziomych?", font=("Helvetica", 9)).place(x=70, y=175) Label(self, text="Szukać pionowych?", font=("Helvetica", 9)).place(x=380, y=175) self.cbHorizontal.place(x=180, y=175) self.cbVertical.place(x=500, y=175) Label(self, text="Szukać tylko zewnętrznych?", font=("Helvetica", 11)).place(x=190, y=225) Label(self, text="Wstępnie zanegować?", font=("Helvetica", 11)).place(x=190, y=255) self.cbOuterOnly.place(x=390, y=225) self.cbNegateFirst.place(x=390, y=255) self.borderList.place(width=200, height=50, x=200, y=300) self.saveButton.place(width=40, height=40, x=220, y=355) self.cancelButton.place(width=40, height=40, x=340, y=355) def cancel(self): self.master.image.cv2Image = copy.deepcopy(self.master.image.copy) self.master.update_visible_image() self.master.image.fill_histogram() self.master.update_child_windows() self.destroy()
class Selector(Frame): """The Selector class implements a selector, label and variable(to hold the data) """ caption = None """The caption of the selector""" caption_orientation = None """The orientation of the selector, can be "LEFT", "RIGHT", "TOP", "BOTTOM".""" value = None """The current value of the selector""" values = None """The selectable values""" onchange = None """The onchange-event is triggered when the value is changed.""" do_not_propagate = False """If True, the onchange event isn't triggered on changing the value.""" def __init__(self, _master, _values=None, _caption=None, _caption_orientation=None, _relief=None, _onchange=None): super(Selector, self).__init__(_master, bd=1, relief=_relief) self.value = StringVar() if _values: self.values = _values else: self.values = None if _caption: self.caption = _caption else: self.caption = None if _caption_orientation: self.caption_orientation = _caption_orientation else: self.caption_orientation = LEFT if _onchange: self.onchange = _onchange # Add handling when type is changed else: self.onchange = None do_not_propagate = False self.init_widgets() def set_but_do_not_propagate(self, _value): """Sets the value, but by setting the do_not_propagate-flag, the onchange event will not fire. :param _value: The new value """ self.do_not_propagate = True self.value.set(_value) def _do_onchange(self, *args): """ Calls onchange if assigned. :param args: a list of arguments. """ if self.do_not_propagate == False and self.onchange: self.onchange(_current_index=0, _current_value=self.cb.get()) else: self.do_not_propagate = False def init_widgets(self): """ Initialize visual elements. """ self.value = StringVar() self.cb = ttk.Combobox(self, textvariable=self.value, state='readonly') self.cb['values'] = self.values self.cb.current(0) self.l_caption = ttk.Label(self, text=self.caption) _cb_o = None if self.caption_orientation == LEFT: _cb_o = RIGHT elif self.caption_orientation == RIGHT: _cb_o = LEFT elif self.caption_orientation == TOP: _cb_o = BOTTOM elif self.caption_orientation == BOTTOM: _cb_o = TOP self.cb.pack(side=_cb_o) self.l_caption.pack(side=self.caption_orientation) self.value.trace('w', self._do_onchange)
class BIDSFile(FileInfo): """ BIDSFiles are the main files which will contain the data that is to be converted to BIDS format. For KIT data this is the .con file. For Elekta data this is the .fif file. """ def __init__(self, id_=None, file=None, settings=dict(), parent=None): super(BIDSFile, self).__init__(id_, file, parent) self._settings = settings self._create_vars() if 'emptyroom' in self.file.lower(): self.is_empty_room.set(True) def _create_vars(self): # TODO: Fix # This is called multiple times... FileInfo._create_vars(self) self.run = StringVar(value='1') self.run.trace("w", self.validate) self.task = OptionsVar(options=['None']) self.task.trace("w", self._update_tasks) self.is_junk = BooleanVar() self.is_empty_room = BooleanVar() self.is_empty_room.trace("w", self.propagate_emptyroom_data) self.has_empty_room = BooleanVar() self.hpi = list() self.loaded = False self.extra_data = dict() # event info: a list of lists. The sub-lists contains the event number # and the event description self.event_info = list() # channel info: key - channel name (?), value - something self.channel_info = dict() self.raw = None self.container = None # Set all BIDS files to be saved by default self.requires_save = True def load_data(self): pass def validate(self, validate_container=True, *args): """ Check whether the file is valid (ie. contains all the required info for BIDS exporting). """ self.valid = self.check_valid() if self.container is not None and validate_container: self.container.validate() def check_valid(self): """ Go over all the required settings and determine whether the file is ready to be exported to the bids format. """ is_valid = super(BIDSFile, self).check_valid() # if empty room or junk we consider them good if self.is_empty_room.get() or self.is_junk.get(): return is_valid is_valid &= self.run.get() != '' is_valid &= (self.hpi != list()) return is_valid def get_event_data(self): return ['', ''] def propagate_emptyroom_data(self, *args): """ Callback to propagate the empty room state This is used to tell the container object that the empty room status of this file has changed and change the 'has empty room' state of any other files in the same folder (for KIT). """ if self.container is not None: emptyroom_set = self.container.autodetect_emptyroom() if not emptyroom_set: self.is_empty_room.set(False) self.associated_tab.is_emptyroom_info.value = self.is_empty_room # noqa def _update_tasks(self, *args): """Update the EntryChoice that contains the task options""" if self.associated_tab is not None: self.associated_tab.task_info.value = self.task def __getstate__(self): data = super(BIDSFile, self).__getstate__() data['run'] = self.run.get() # run data['tsk'] = self.task.get() # task # marker coils: data['hpi'] = [hpi.file for hpi in self.hpi] data['ier'] = self.is_empty_room.get() # is empty room data? data['her'] = self.has_empty_room.get() # has empty room data? return data def __setstate__(self, state): super(BIDSFile, self).__setstate__(state) self.run.set(state.get('run', 0)) task = state.get('tsk', '') self.task.options = [task] self.task.set(task) # support old and new format hpi storage self.hpi = state.get('hpi', list()) self.is_empty_room.set(state.get('ier', False)) self.has_empty_room.set(state.get('her', False))
class MainFrame(Frame): ''' This class implements main GUI of the application. Attributes: parent (Tk object): parent of this frame (Tk()). params_frame (ParamsFrame): frame with parameters. data_frame (DataFrame): frame with data and solution. progress_bar (Progressbar): progress bar widget. increment (int): progress bar increment, it is modified in other classes that are responsible for solving the problem and update progress. weights_status_lbl (Label): label that displays if weight restrictions are feasible. weights_status_str (StringVar): StringVar object used for tracking if weight restrictions are feasible. current_categories (list of str): list of current categories. Args: parent (Tk object): parent of this frame (Tk()). ''' def __init__(self, parent, *args, **kwargs): Frame.__init__(self, parent, *args, **kwargs) self.parent = parent self.params_frame = None self.data_frame = None self.progress_bar = None self.increment = 0 self.weights_status_lbl = None self.weights_status_str = StringVar() self.weights_status_str.trace('w', self.on_weights_status_change) self.current_categories = [] self.create_widgets() def create_widgets(self): ''' Creates all widgets that belong to this frame. ''' self.parent.title('pyDEA') self.pack(fill=BOTH, expand=1) self.columnconfigure(0, weight=1, pad=5) self.columnconfigure(1, weight=0, pad=5) self.rowconfigure(0, pad=3, weight=1) self.rowconfigure(1, pad=3) self.rowconfigure(2, pad=3) self.rowconfigure(3, pad=3) self.current_categories = [] data_from_params_file = StringVar() str_var_for_input_output_boxes = ObserverStringVar() self.params_frame = ParamsFrame(self, self.current_categories, data_from_params_file, str_var_for_input_output_boxes, self.weights_status_str) data_frame = DataFrame(self, self.params_frame, self.current_categories, data_from_params_file, str_var_for_input_output_boxes) self.data_frame = data_frame data_frame.grid(row=0, column=0, sticky=N+S+W+E, padx=15, pady=15) self.params_frame.grid(row=0, column=1, sticky=W+E+S+N, padx=15, pady=15, columnspan=2) lbl_progress = Label(self, text='Progress') lbl_progress.grid(row=1, column=0, sticky=W, padx=10, pady=5) self.progress_bar = Progressbar(self, mode='determinate', maximum=100) self.progress_bar.grid(row=2, column=0, sticky=W+E, padx=10, pady=5) run_btn = Button(self, text='Run', command=self.run) run_btn.grid(row=2, column=1, sticky=W, padx=10, pady=10) self.weights_status_lbl = Label(self, text='', foreground='red') self.weights_status_lbl.grid(row=2, column=2, padx=10, pady=5, sticky=W) def on_weights_status_change(self, *args): ''' This method is called when weight restrictions status is changed. ''' self.weights_status_lbl.config(text=self.weights_status_str.get()) def run(self): ''' This method is called when the user presses Run button. Solves the problem and displays solution. ''' clean_up_pickled_files() params = self.params_frame.params run_method = RunMethodGUI(self) run_method.run(params) def construct_categories(self): ''' Returns current categories. Returns: (list of str): list of current categories ''' return [category.strip() for category in self.current_categories if category] def on_dmu_change(self, *args): ''' Updates progress bar. ''' self.progress_bar.step(self.increment) self.progress_bar.update()
class CharacterValueField(Entry): """ Basic field type used to store character values. """ def __init__(self, parent, validate_fun, **kwargs): """ Initialise input field. - validate_fun: A function used to validate the field's input value. """ # Variable for entered value if 'name' in kwargs: self.name = kwargs.get('name') self.value = StringVar(parent, name=self.name) else: self.value = StringVar(parent) self.value.set('') self.value.trace('w', self._follow_changes) self.validator = validate_fun if 'to_trace' in kwargs: self.reference = kwargs.get('to_trace') self.reference.trace('w', self._follow_ref_val) # Entry field Entry.__init__(self, parent, textvariable=self.value, width=kwargs.get('width', FIELD_WIDTH)) def _follow_ref_val(self, *_args): """ If a master - or reference - value is specified for the field, it will update its value on changes to the master field. """ self.value.set(self.reference.get()) def _follow_changes(self, *_args): """ Traces changes to the input value of the field. """ # Get current background color of field. color = self.cget('bg') # It turns red on validation failures. # Any subsequent change must turn the color back # to the default color. if color == FIELD_COLOR_ERROR: self.config(bg=FIELD_COLOR) def enable(self): """ Enables the field. I.e. it's value can be set. """ self.config(state=NORMAL) self.value.set('') def disable(self): """ Disables the field. It's value cannot be set or edited. """ self.value.set('n/a') self.config(state=DISABLED) def get_validated(self, **kwargs): """ Calls assigned validator function on the value of the field. If validation fails, turns the field to red. """ try: value = self.validator(self.value.get(), **kwargs) return value except FieldValidationError: self.config(bg=FIELD_COLOR_ERROR) raise def reset_fld(self): """ Cleans the field's value by setting it to an empty string. """ self.value.set('')
class Config: """Read/write and store all data from config files.""" def __init__(self, cmdLineParams, master=None): self.cmdLineParams = cmdLineParams self.master = master self.ai_path = '' # Path to FG_ROOT/AI directory. self.apt_path = '' # Path to FG_ROOT/Airports/apt.dat.gz file. self.metar_path = '' # Path to FG_ROOT/Airports/metar.dat.gz file. self.aircraft_dirs = [] # List of aircraft directories. # Dictionary whose keys are aircraft names. For each aircraft name 'n', # self.aircraftDict[n] is the list, in self.aircraft_dirs priority # order, of all Aircraft instances with that name. self.aircraftDict = {} self.aircraftList = [] # Sorted list of Aircraft instances. self.scenario_list = [] # List of selected scenarios. # List of all aircraft carriers found in AI scenario folder. # Each entry format is: # ["ship name", "parking position"... , "scenario name"] self.carrier_list = [] self.settings = [] # List of basic settings read from config file. self.text = '' # String to be shown in command line options window. # 'self.aircraftId' is the central variable telling which particular # aircraft is selected in FFGo's interface. It is a tuple of the form # (aircraftName, aircraftDir). self.aircraftId = misc.Observable() self.aircraft = StringVar() self.aircraftDir = StringVar() # Whenever 'self.aircraftId' is set, 'self.aircraft' and # 'self.aircraftDir' are automatically updated to reflect the new value # (and their observers called, even if the values didn't change). self.aircraftId.trace("w", self.updateAircraftNameAndDirFromAircraftId) # Note: the FFGo config file stores the values of 'self.aircraft' and # 'self.aircraftDir' separately (this makes the compatibility # path easy with versions that don't know about aircraftDir). self.airport = StringVar() # ICAO code of the selected airport self.alreadyProposedChanges = StringVar() self.apt_data_source = IntVar() self.auto_update_apt = IntVar() self.carrier = StringVar() # when non-empty, we are in “carrier mode” self.FG_aircraft = StringVar() self.FG_bin = StringVar() self.FG_root = StringVar() self.FG_scenery = StringVar() self.FG_working_dir = StringVar() self.MagneticField_bin = StringVar() self.MagneticField_bin.trace('w', self.updateMagFieldProvider) self.filteredAptList = IntVar() self.language = StringVar() self.park = StringVar() self.rwy = StringVar() self.scenario = StringVar() self.mainWindowGeometry = StringVar() self.saveWindowPosition = IntVar() self.baseFontSize = StringVar() self.TkDefaultFontSize = IntVar() # tkinter.BooleanVar feels kind of messy. Sometimes, it prints out as # 'True', other times as '1'... IntVar seems more predictable. self.showFGCommand = IntVar() self.showFGCommandInSeparateWindow = IntVar() self.FGCommandGeometry = StringVar() self.showFGOutput = IntVar() self.showFGOutputInSeparateWindow = IntVar() self.FGOutputGeometry = StringVar() self.autoscrollFGOutput = IntVar() # Option to translate --parkpos into --lat, --lon and --heading (useful # when --parkpos is broken in FlightGear) self.fakeParkposOption = IntVar() self.airportStatsManager = None # will be initialized later self.aircraftStatsManager = None # ditto self.airportStatsShowPeriod = IntVar() self.airportStatsExpiryPeriod = IntVar() self.aircraftStatsShowPeriod = IntVar() self.aircraftStatsExpiryPeriod = IntVar() self.keywords = {'--aircraft=': self.aircraft, '--airport=': self.airport, '--fg-root=': self.FG_root, '--fg-scenery=': self.FG_scenery, '--carrier=': self.carrier, '--parkpos=': self.park, '--runway=': self.rwy, 'AIRCRAFT_DIR=': self.aircraftDir, 'AI_SCENARIOS=': self.scenario, 'ALREADY_PROPOSED_CHANGES=': self.alreadyProposedChanges, 'APT_DATA_SOURCE=': self.apt_data_source, 'AUTO_UPDATE_APT=': self.auto_update_apt, 'FG_BIN=': self.FG_bin, 'FG_AIRCRAFT=': self.FG_aircraft, 'FG_WORKING_DIR=': self.FG_working_dir, 'MAGNETICFIELD_BIN=': self.MagneticField_bin, 'FILTER_APT_LIST=': self.filteredAptList, 'LANG=': self.language, 'WINDOW_GEOMETRY=': self.mainWindowGeometry, 'SAVE_WINDOW_POSITION=': self.saveWindowPosition, 'BASE_FONT_SIZE=': self.baseFontSize, 'SHOW_FG_COMMAND=': self.showFGCommand, 'SHOW_FG_COMMAND_IN_SEPARATE_WINDOW=': self.showFGCommandInSeparateWindow, 'FG_COMMAND_GEOMETRY=': self.FGCommandGeometry, 'SHOW_FG_OUTPUT=': self.showFGOutput, 'SHOW_FG_OUTPUT_IN_SEPARATE_WINDOW=': self.showFGOutputInSeparateWindow, 'FG_OUTPUT_GEOMETRY=': self.FGOutputGeometry, 'AUTOSCROLL_FG_OUTPUT=': self.autoscrollFGOutput, 'FAKE_PARKPOS_OPTION=': self.fakeParkposOption, 'AIRPORT_STATS_SHOW_PERIOD=': self.airportStatsShowPeriod, 'AIRPORT_STATS_EXPIRY_PERIOD=': self.airportStatsExpiryPeriod, 'AIRCRAFT_STATS_SHOW_PERIOD=': self.aircraftStatsShowPeriod, 'AIRCRAFT_STATS_EXPIRY_PERIOD=': self.aircraftStatsExpiryPeriod} # In order to avoid using a lot of memory, detailed airport data is # only loaded on demand. Since this is quite slow, keep a cache of the # last retrieved data. self.aptDatCache = collections.deque(maxlen=50) self._earlyTranslationsSetup() self._createUserDirectories() self._maybeMigrateFromFGoConfig() # Not having the FlightGear version at this point is not important # enough to justify pestering the user about it. :-) # Defer logging of the detected FG version to fit nicely with # the other startup messages. self.update(ignoreFGVersionError=True, logFGVersion=False) self.setTkDefaultFontSize() self.setupFonts(init=True) def setTkDefaultFontSize(self): """Save unaltered TkDefaultFont size.""" size = tkinter.font.nametofont("TkDefaultFont").actual()["size"] self.TkDefaultFontSize.set(size) def setupFonts(self, init=False): """Setup the default fonts. When called with init=True, custom fonts are created and stored as attributes of self. Otherwise, they are simply configured. """ # According to <http://www.tcl.tk/man/tcl8.4/TkCmd/font.htm>, font # sizes are interpreted this way: # - for positive values, the unit is points; # - for negative values, the unit is pixels; # - 0 is a special value for "a platform-dependent default size". # # Apparently, Tkinter doesn't accept floats for the 'size' parameter of # <font>.configure(), even when positive (tested with Python 2.7.3). baseSize = int(float(self.baseFontSize.get())) # Get the actual size when baseSize == 0, otherwise scaling won't work # since 0*factor == 0, regardless of the (finite) factor. if baseSize == 0: baseSize = self.TkDefaultFontSize.get() def scale(factor): return int(round(baseSize * factor)) def configFontSize(style, factor): font = tkinter.font.nametofont("Tk%sFont" % style) font.configure(size=scale(factor)) # Configure built-in fonts for style in ("Default", "Text", "Fixed", "Caption", "Tooltip"): # The 'if init:' here is a workaround for a weird problem: when # saving the settings from the Preferences dialog, even if the very # same font size is set here as the one that was used at program # initialization, the main window layout gets broken, with the # airport chooser Treeview taking more and more horizontal space # every time the settings are saved. Avoiding to reconfigure the # fonts in such "reinit" conditions works around the problem... if init: configFontSize(style, 1) for style, factor in (("Menu", 20 / 18.), ("Heading", 20 / 18.), ("SmallCaption", 16 / 18.), ("Icon", 14 / 18.)): if init: # Second part of the workaround mentioned above configFontSize(style, factor) # Create or configure custom fonts, depending on 'init' aboutTitleFontSize = scale(42 / 18.) if init: self.aboutTitleFont = tkinter.font.Font( family="Helvetica", weight="bold", size=aboutTitleFontSize) else: self.aboutTitleFont.configure(size=aboutTitleFontSize) # Final part of the workaround mentioned above. Normally, the code # should always be executed, regardless of the value of 'init'. if init: # For the ttk.Treeview widget treeviewHeadingFontSize = scale(1.) # Redundant test, right. Hopefully, one day, we'll be able to get # rid of the workaround and this test won't be redundant anymore. if init: self.treeviewHeadingFont = tkinter.font.Font( weight="normal", size=treeviewHeadingFontSize) else: self.treeviewHeadingFont.configure(size=treeviewHeadingFontSize) style = ttk.Style() style.configure("Treeview.Heading", font=self.treeviewHeadingFont) def makeInstalledAptList(self): logger.notice(_("Building the list of installed airports " "(this may take some time)...")) # writelines() used below doesn't automatically add line terminators airports = [ icao + '\n' for icao in self._findInstalledApt() ] logger.info("Opening '{}' for writing".format(INSTALLED_APT)) with open(INSTALLED_APT, "w", encoding="utf-8") as fout: fout.writelines(airports) def readMetarDat(self): """Fetch METAR station list from metar.dat.gz file""" logger.info("Opening '{}' for reading".format(self.metar_path)) res = [] with gzip.open(self.metar_path, mode='rt', encoding='utf-8') as fin: for line in fin: if not line.startswith('#'): res.append(line.strip()) return res def rebuildApt(self): """Rebuild apt file.""" self._makeAptDigest() def _computeAircraftDirList(self): FG_AIRCRAFT_env = os.getenv("FG_AIRCRAFT", "") if FG_AIRCRAFT_env: FG_AIRCRAFT_envList = FG_AIRCRAFT_env.split(os.pathsep) else: FG_AIRCRAFT_envList = [] # FG_ROOT/Aircraft defaultAircraftDir = os.path.join(self.FG_root.get(), DEFAULT_AIRCRAFT_DIR) aircraft_dirs = (self.FG_aircraft.get().split(os.pathsep) + FG_AIRCRAFT_envList + [defaultAircraftDir]) return aircraft_dirs def logDetectedFlightGearVersion(self, logLevel=LogLevel.notice, prefix=True): if self.FG_version is not None: FG_version = str(self.FG_version) else: FG_version = pgettext("FlightGear version", "none") # Uses the same string as in App.about() message = _("Detected FlightGear version: {ver}").format( ver=FG_version) logger.log(logLevel, prefix, message) def getFlightGearVersion(self, ignoreFGVersionError=False, log=False): # This import requires the translation system [_() function] to be in # place. from .fgdata import fgversion self.FG_version = None # in case an exception is raised below FG_bin = self.FG_bin.get() FG_root = self.FG_root.get() exc = None if FG_bin and FG_root: try: self.FG_version = fgversion.getFlightGearVersion( FG_bin, FG_root, self.FG_working_dir.get()) except fgversion.error as e: exc = e # may need to be raised later if log: self.logDetectedFlightGearVersion() if exc is not None and not ignoreFGVersionError: raise exc # This is a callback for FFGo's misc.Observable class. def updateAircraftNameAndDirFromAircraftId(self, aircraftId): aircraftName, aircraftDir = aircraftId self.aircraft.set(aircraftName) self.aircraftDir.set(aircraftDir) def aircraftWithNameAndDir(self, name, dir_): """Get the Aircraft instance for a given name and directory.""" try: aircrafts = self.aircraftDict[name] except KeyError: raise NoSuchAircraft(name, dir_) for aircraft in aircrafts: # The idea is that the directory 'dir_' passed here should have # been discovered earlier by a filesystem exploration, therefore # there must be one Aircraft instance that has an exact match for # both 'name' and 'dir_' (no need to use 'os.path.samefile()', # which would be slower, could raise errors...). if aircraft.dir == dir_: return aircraft else: raise NoSuchAircraft(name, dir_) def aircraftWithId(self, aircraftId): """Get the Aircraft instance for a given aircraft ID.""" return self.aircraftWithNameAndDir(*self.aircraftId.get()) def getCurrentAircraft(self): """Get the Aircraft instance for the currently-selected aircraft.""" return self.aircraftWithId(self.aircraftId.get()) def _findAircraft(self, acName, acDir): """Return an aircraft ID for 'acName' and 'acDir' if possible. If no aircraft is found with the given name and directory, fall back to: - an identically-named aircraft in a different directory (taking the first in FG_AIRCRAFT precedence order); - if this isn't possible either, fall back to the default aircraft. The returned aircraft ID will have an empty directory component if even the default aircraft isn't available in this case. Log an appropriate warning or notice when a fallback strategy is used. """ if acName in self.aircraftDict: for ac in self.aircraftDict[acName]: if ac.dir == acDir: aircraft = ac break else: aircraft = self.aircraftDict[acName][0] logger.notice( _("Could not find aircraft '{aircraft}' under '{dir}', " "taking it from '{fallback}' instead").format( aircraft=acName, dir=acDir, fallback=aircraft.dir)) else: try: defaultAircrafts = self.aircraftDict[DEFAULT_AIRCRAFT] except KeyError: aircraft = None logger.warning( _("Could not find the default aircraft: {aircraft}") .format(aircraft=DEFAULT_AIRCRAFT)) else: aircraft = defaultAircrafts[0] logger.notice( _("Could not find aircraft '{aircraft}', using " "'{fallback}' from '{dir}' instead").format( aircraft=acName, fallback=aircraft.name, dir=aircraft.dir)) if aircraft is None: return (DEFAULT_AIRCRAFT, '') else: return (aircraft.name, aircraft.dir) def sanityChecks(self): status, *rest = self.decodeParkingSetting(self.park.get()) if status == "invalid": logger.warning( _("Invalid syntax for the parking setting ({setting!r}), " "resetting it.").format(setting=self.park.get())) self.park.set('') if self.rwy.get() and self.park.get(): # Impossible to at the same time set a non-default runway and a # parking position. The latter wins. :-) self.rwy.set('') def update(self, path=None, ignoreFGVersionError=False, logFGVersion=True): """Read config file and update variables. path is a path to different than default config file """ if self.aircraftStatsManager is None: # application init # Requires the translation system to be in place from . import stats_manager self.aircraftStatsManager = \ stats_manager.AircraftStatsManager(self) else: # Save the in-memory statistics (from Aircraft instances) to # persistent storage. This expires old stats, according to # self.aircraftStatsExpiryPeriod. self.aircraftStatsManager.save() del self.settings del self.text del self.aircraft_dirs del self.apt_path del self.ai_path del self.metar_path del self.aircraftDict del self.aircraftList del self.scenario_list del self.carrier_list # The variable will be set again right after reading the config # file, therefore there is no need to run the callbacks now # (such as updating the aircraft image). self.aircraftId.set((DEFAULT_AIRCRAFT, ''), runCallbacks=False) self.airport.set(DEFAULT_AIRPORT) self.alreadyProposedChanges.set('') self.apt_data_source.set(1) self.auto_update_apt.set(1) self.carrier.set('') self.FG_aircraft.set('') self.FG_bin.set('') self.FG_root.set('') self.FG_scenery.set('') self.FG_working_dir.set('') self.MagneticField_bin.set('') self.language.set('') self.baseFontSize.set(DEFAULT_BASE_FONT_SIZE) self.mainWindowGeometry.set('') self.saveWindowPosition.set('1') self.showFGCommand.set('1') self.showFGCommandInSeparateWindow.set('0') self.FGCommandGeometry.set('') self.showFGOutput.set('1') self.showFGOutputInSeparateWindow.set('0') self.FGOutputGeometry.set('') self.autoscrollFGOutput.set('1') self.park.set('') self.fakeParkposOption.set('0') self.rwy.set('') self.scenario.set('') self.filteredAptList.set(0) self.airportStatsShowPeriod.set('365') # approx. one year self.airportStatsExpiryPeriod.set('3652') # approx. ten years self.aircraftStatsShowPeriod.set('365') self.aircraftStatsExpiryPeriod.set('3652') self.settings, self.text = self._read(path) for line in self.settings: cut = line.find('=') + 1 if cut: name = line[:cut] value = line[cut:] if value: if name in self.keywords: var = self.keywords[name] var.set(value) # Useful to know when the airport has been changed self.previousAirport = self.airport.get() self._setLanguage(self.language.get()) setupTranslationHelper(self) self.aircraft_dirs = self._computeAircraftDirList() self.apt_path = os.path.join(self.FG_root.get(), APT_DAT) self.ai_path = os.path.join(self.FG_root.get(), AI_DIR) self.metar_path = os.path.join(self.FG_root.get(), METAR_DAT) self.aircraftDict, self.aircraftList = self._readAircraft() # Load the saved statistics into the new in-memory Aircraft instances # (the set of aircrafts may have just changed, hence the need to save # the stats before the in-memory aircraft list is updated, and reload # them afterwards). self.aircraftStatsManager.load() # Choose a suitable aircraft, even if the one defined by # 'self.aircraft' and 'self.aircraftDir' isn't available. self.aircraftId.set(self._findAircraft(self.aircraft.get(), self.aircraftDir.get())) self.scenario_list, self.carrier_list = self._readScenarios() self.sanityChecks() self.getFlightGearVersion(ignoreFGVersionError=ignoreFGVersionError, log=logFGVersion) def write(self, text=None, path=None): """Write the configuration to a file. text -- content of text window processed by CondConfigParser (pass None to use the value of Config.text) path -- path to the file the config will be written to (the default config file is used if this argument is empty or None) """ if not path: path = CONFIG if text is None: text = self.text options = [] keys = list(self.keywords.keys()) keys.sort() for k in keys: v = self.keywords[k] if k in ('--carrier=', '--airport=', '--parkpos=', '--runway='): if v.get(): options.append(k + v.get()) else: options.append(k + str(v.get())) s = '\n'.join(options) logger.info("Opening config file for writing: '{}'".format(path)) with open(path, mode='w', encoding='utf-8') as config_out: config_out.write(s + '\n' + CUT_LINE + '\n') # Make sure the config file has exactly one newline at the end while text.endswith('\n\n'): text = text[:-1] if not text.endswith('\n'): text += '\n' config_out.write(text) def _findInstalledApt(self): """Walk thru all scenery and find installed airports. Take geographic coordinates from directories names and compare them with airports coordinates in apt file. The result is a sorted list of ICAO codes for matching airports. """ coord_dict = {} sceneries = self.FG_scenery.get().split(os.pathsep) for scenery in sceneries: path = os.path.join(scenery, 'Terrain') if os.path.exists(path): for dir in os.listdir(path): p = os.path.join(path, dir) for coords in os.listdir(p): d = os.path.join(p, coords) if not os.path.isdir(d): continue logger.debug("Exploring Terrain directory '{}' -> '{}'" .format(p, coords)) converted = self._stringToCoordinates(coords) if converted is not None: coord_dict[converted] = None else: logger.notice( _("Ignoring directory '{}' (unexpected name)") .format(d)) coords = coord_dict.keys() res = [] for icao in self.sortedIcao(): airport = self.airports[icao] for c in coords: if (c[0][0] < airport.lat < c[0][1] and c[1][0] < airport.lon < c[1][1]): res.append(icao) return res def _calculateRange(self, coordinates): c = coordinates if c.startswith('s') or c.startswith('w'): c = int(c[1:]) * (-1) return c, c + 1 else: c = int(c[1:]) return c, c + 1 def _createUserDirectories(self): """Create config, log and stats directories if they don't exist.""" for d in USER_DATA_DIR, LOG_DIR, STATS_DIR: os.makedirs(d, exist_ok=True) def _maybeMigrateFromFGoConfig_dialogs(self, parent): message = _("Initialize {prg}'s configuration from your existing " \ "FGo! configuration?").format(prg=PROGNAME) detail = (_("""\ You have no {cfgfile} file but you do have a {fgo_cfgfile} file, which normally belongs to FGo!. Except in rare circumstances (such as using braces or backslashes, or opening brackets at the beginning of a config line), a configuration file from FGo! 1.5.5 or earlier should be usable as is by {prg}.""") .replace('\n', ' ') + "\n\n" + _("""\ If {fgo_cfgfile} was written by FGo! 1.5.5 or earlier, you should probably say “Yes” here in order to initialize {prg}'s configuration based on your FGo! config file (precisely: copy {fgo_cfgfile} to {cfgfile}).""") .replace('\n', ' ') + "\n\n" + _("""\ If {fgo_cfgfile} was written by a version of FGo! that is greater than 1.5.5, it is advised to say “No” here.""") .replace('\n', ' ') ).format(prg=PROGNAME, cfgfile=CONFIG, fgo_cfgfile=FGO_CONFIG) if askyesno(PROGNAME, message, detail=detail, parent=parent): choice = "migrate from FGo!" else: message = _("Create a default {prg} configuration?").format( prg=PROGNAME) detail = _("""\ Choose “Yes” to create a basic {prg} configuration now. If you choose “No”, {prg} will exit and you'll have to create {cfgfile} yourself, or restart {prg} to see the same questions again.""") \ .replace('\n', ' ').format(prg=PROGNAME, cfgfile=CONFIG) if askyesno(PROGNAME, message, detail=detail, parent=parent): choice = "create default cfg" message = _("Creating a default {prg} configuration.").format( prg=PROGNAME) detail = (_("""\ It is suggested that you go to the Settings menu and choose Preferences to review your newly-created configuration.""") .replace('\n', ' ') + "\n\n" + _("""\ You can also reuse most, if not all FlightGear options you had in FGo!'s main text box (the “options window”). Just copy them to the corresponding {prg} text box.""") .replace('\n', ' ') + "\n\n" + _("""\ Note: you may run both FGo! and {prg} simultaneously, as their configurations are kept separate.""") .replace('\n', ' ') ).format(prg=PROGNAME) showinfo(PROGNAME, message, detail=detail, parent=parent) else: choice = "abort" return choice def _maybeMigrateFromFGoConfig(self): if os.path.isfile(FGO_CONFIG) and not os.path.isfile(CONFIG): baseSize = tkinter.font.nametofont("TkDefaultFont").actual()["size"] def configFontSize(val, absolute=False): for style in ("Default", "Text", "Fixed", "Caption", "Tooltip"): font = tkinter.font.nametofont("Tk{}Font".format(style)) if absolute: font.configure(size=val) else: font.configure(size=int(round(baseSize * val))) # Make sure most people can read the following dialogs (the # standard Tk size may be rather small): 140% increase configFontSize(1.4, absolute=False) choice = None # user choice in the to-be-displayed dialogs # It seems we need an otherwise useless Toplevel window in order to # center the Tk standard dialogs... t = tkinter.Toplevel() try: # Transparent if the OS supports it t.attributes('-alpha', '0.0') # Center the Toplevel. To be effective, this would probably # need a visit to the Tk event loop, however it is enough to # have the child dialogs centered, which is what matters here. self.master.eval('tk::PlaceWindow {} center'.format( t.winfo_pathname(t.winfo_id()))) choice = self._maybeMigrateFromFGoConfig_dialogs(t) finally: t.destroy() # Restore font size for later self.setupFonts() call configFontSize(baseSize, absolute=True) if choice in (None, "abort"): raise AbortConfig elif choice == "migrate from FGo!": # shutil.copy() and shutil.copy2() attempt to preserve the file's # permission mode, which is undesirable here → manual copy. with open(FGO_CONFIG, "r", encoding='utf-8') as fgoConfig, \ open(CONFIG, "w", encoding='utf-8') as config: config.write(fgoConfig.read()) else: assert choice == "create default cfg", repr(choice) def _makeAptDigest(self, head=None): """Build apt database from apt.dat.gz""" if self.FG_root.get(): _ProcessApt(self.master, self, self.apt_path, head) def _read(self, path=None): """Read the specified or a default configuration file. - If 'path' is None and CONFIG exists, load CONFIG; - if 'path' is None and CONFIG does not exist, load the configuration from the presets and default, localized config_ll resource; - otherwise, load configuration from the specified file. """ try: # ExitStack not strictly necessary here, but allows clean and # convenient handling of the various files or resources the # configuration may be loaded from. with contextlib.ExitStack() as stack: res = self._read0(stack, path) except OSError as e: message = _('Error loading configuration') showerror(_('{prg}').format(prg=PROGNAME), message, detail=str(e)) res = ([''], '') return res _presetsBlankLineOrCommentCre = re.compile(r"^[ \t]*(#|$)") def _read0(self, stack, path): # Data before the CUT_LINE in the config file, destined to # self.settings settings = [] # Data after the CUT_LINE in the config file, destined to # self.text and to be parsed by CondConfigParser condConfLines = [] if path is not None or (path is None and os.path.exists(CONFIG)): if path is None: path = CONFIG logger.info("Opening config file '{}' for reading".format(path)) configStream = stack.enter_context(open(path, "r", encoding="utf-8")) beforeCutLine = True else: # Use default config if no regular config exists. # Load presets if exists. if resourceExists(PRESETS): with textResourceStream(PRESETS) as presets: for line in presets: line = line.strip() if not self._presetsBlankLineOrCommentCre.match(line): settings.append(line) # Find the currently used language according to the environment. try: lang_code = gettext.translation( MESSAGES, LOCALE_DIR).info()['language'] except OSError: lang_code = 'en' if not resourceExists(DEFAULT_CONFIG_STEM + lang_code): lang_code = 'en' resPath = DEFAULT_CONFIG_STEM + lang_code configStream = stack.enter_context(textResourceStream(resPath)) # There is no "cut line" in the template config files. beforeCutLine = False for line in configStream: if beforeCutLine: line = line.strip() if line != CUT_LINE: if beforeCutLine: # Comments wouldn't be preserved on saving, therefore don't # try to handle them before the "cut line". if line: settings.append(line) else: condConfLines.append(line) else: beforeCutLine = False return (settings, ''.join(condConfLines)) def _readAircraft(self): """ Walk through Aircraft directories and return the available aircrafts. Return a tuple (aircraftDict, aircraftList) listing all aircrafts found via self.aircraft_dirs. aircraftDict is a dictionary whose keys are the names (derived from the -set.xml files) of all aircrafts. For each aircraft name 'n', aircraftDict[n] is the list, in self.aircraft_dirs priority order, of all Aircraft instances with that name. aircraftList is the sorted list of all Aircraft instances, suitable for quick building of the aircraft list in the GUI. """ aircraftDict = {} for dir_ in self.aircraft_dirs: if os.path.isdir(dir_): for d in os.listdir(dir_): self._readAircraftData(dir_, d, aircraftDict) aircraftList = [] # First sort by lowercased aircraft name sortFunc = lambda s: (s.lower(), s) for acName in sorted(aircraftDict.keys(), key=sortFunc): # Then sort by position in self.aircraft_dirs aircraftList.extend(aircraftDict[acName]) return (aircraftDict, aircraftList) def _readAircraftData(self, dir_, d, aircraftDict): path = os.path.join(dir_, d) if os.path.isdir(path): for f in os.listdir(path): self._appendAircraft(f, aircraftDict, path) def _appendAircraft(self, f, aircraftDict, path): if f.endswith('-set.xml'): # Dirty and ugly hack to prevent carrier-set.xml in # seahawk directory to be attached to the aircraft # list. if (not path.startswith('seahawk') and f != 'carrier-set.xml'): name = f[:-8] if name not in aircraftDict: aircraftDict[name] = [] aircraft = Aircraft(name, path) aircraftDict[name].append(aircraft) def sortedIcao(self): return sorted(self.airports.keys()) def _readApt(self): """Read the apt digest file (create a new one if none exists). Return a list of AirportStub instances. """ from .fgdata import apt_dat if not os.path.exists(APT): # Create a new file if self.FG_root is non-empty self._makeAptDigest() if not os.path.isfile(APT): # may happen if self.FG_root was empty self.aptDatSize, self.airports = 0, {} return [] for attempt in itertools.count(start=1): try: self.aptDatSize, self.airports = apt_dat.AptDatDigest.read(APT) except apt_dat.UnableToParseAptDigest: if attempt < 2: self._makeAptDigest() else: raise else: break if self.filteredAptList.get(): installedApt = self._readInstalledAptSet() res = [ self.airports[icao] for icao in self.sortedIcao() if icao in installedApt ] else: res = [ self.airports[icao] for icao in self.sortedIcao() ] return res def _readInstalledAptSet(self): """Read the set of locally installed airports from INSTALLED_APT. Create a new INSTALLED_APT file if none exists yet. Return a frozenset(), which offers very fast membership test compared to a list. """ if not os.path.exists(INSTALLED_APT): self.makeInstalledAptList() logger.info("Opening installed apt file '{}' for reading".format( INSTALLED_APT)) with open(INSTALLED_APT, "r", encoding="utf-8") as f: # Strip the newline char ending every line res = frozenset([ line[:-1] for line in f ]) return res def _readScenarios(self): """Walk through AI scenarios and read carrier data. Return two lists: scenarios: [scenario name, ...] carrier data: [[name, parkking pos, ..., scenario name], ...] Return two empty lists if no scenario is found. """ carriers = [] scenarios = [] if os.path.isdir(self.ai_path): for f in os.listdir(self.ai_path): path = os.path.join(self.ai_path, f) if os.path.isfile(path) and f.lower().endswith('.xml'): scenario_name = f[:-4] scenarios.append(scenario_name) # Appends to 'carriers' self._append_carrier_data(carriers, path, scenario_name) return sorted(scenarios), sorted(carriers) def _append_carrier_data(self, carriers, xmlFilePath, scenario_name): logger.info("Reading scenario data from '{}'".format(xmlFilePath)) root = self._get_root(xmlFilePath) scenario = root.find('scenario') if scenario is not None: for e in scenario.iterfind('entry'): typeElt = e.find('type') if typeElt is not None and typeElt.text == 'carrier': data = self._get_carrier_data(e, scenario_name) carriers.append(data) def _get_root(self, xmlFilePath): tree = ElementTree.parse(xmlFilePath) return tree.getroot() def _get_carrier_data(self, e, scenario_name): nameElt = e.find('name') if nameElt is not None: data = [nameElt.text] else: data = ['unnamed'] for child in e.iterfind('parking-pos'): parkingNameElt = child.find('name') if parkingNameElt is not None: data.append(parkingNameElt.text) data.append(scenario_name) return data # The '1' is the version number of this custom format for the contents of # Config.park, in case we need to change it. aptDatParkConfStart_cre = re.compile(r"::apt\.dat::1::(?P<nameLen>\d+),") aptDatParkConfEnd_cre = re.compile( r"""lat=(?P<lat>{floatRegexp}), lon=(?P<lon>{floatRegexp}), heading=(?P<heading>{floatRegexp})$""".format( floatRegexp=r"-?\d+(\.\d*)?"), re.VERBOSE) def decodeParkingSetting(self, parkConf): status = "invalid" # will be overridden if correct in the end parkName = None options = [] if not parkConf: status = "none" # no parking position else: mo = self.aptDatParkConfStart_cre.match(parkConf) if mo: # Length of the following parking name (after the comma) nameLen = int(mo.group("nameLen")) i = mo.end("nameLen") + 1 + nameLen if len(parkConf) > i and parkConf[i] == ";": mo2 = self.aptDatParkConfEnd_cre.match(parkConf[i+1:]) if mo2: parkName = parkConf[mo.end("nameLen")+1:i] options = ["--lat=" + mo2.group("lat"), "--lon=" + mo2.group("lon"), "--heading=" + mo2.group("heading")] status = "apt.dat" else: # plain parking name parkName = parkConf options = ["--parkpos=" + parkName] status = "groundnet" return (status, parkName, options) def _earlyTranslationsSetup(self): """Setup translations before the config file has been read. The language is determined from the environment (LANGUAGE, LC_ALL, LC_MESSAGES, and LANG—cf. gettext.translation() and gettext.find()). """ try: langCode = gettext.translation( MESSAGES, LOCALE_DIR).info()['language'] except OSError: langCode = 'en' self._setLanguage(langCode) def _setLanguage(self, lang): # Initialize provided language... try: L = gettext.translation(MESSAGES, LOCALE_DIR, languages=[lang]) L.install() # ...or fallback to system default. except Exception: gettext.install(MESSAGES, LOCALE_DIR) # Regexp for directory names such as w040n20 _geoDirCre = re.compile(r"[we]\d{3}[ns]\d{2}$") def _stringToCoordinates(self, coordinates): """Convert geo coordinates to decimal format.""" if not self._geoDirCre.match(coordinates): return None lat = coordinates[4:] lon = coordinates[:4] lat_range = self._calculateRange(lat) lon_range = self._calculateRange(lon) return lat_range, lon_range def _autoUpdateApt(self): if not self.auto_update_apt.get() or not os.path.exists(self.apt_path): return old_timestamp = self._readAptTimestamp() self._updateApt(old_timestamp) def _readAptTimestamp(self): if not os.path.exists(APT_TIMESTAMP): self._writeAptTimestamp('') logger.info("Opening apt timestamp file '{}' for reading".format( APT_TIMESTAMP)) with open(APT_TIMESTAMP, "r", encoding="utf-8") as timestamp: old_modtime = timestamp.read() return old_modtime def _writeAptTimestamp(self, s=None): if s is None: s = self._getAptModTime() logger.info("Opening apt timestamp file '{}' for writing".format( APT_TIMESTAMP)) with open(APT_TIMESTAMP, "w", encoding="utf-8") as timestamp: timestamp.write(s) def _getAptModTime(self): return str(os.path.getmtime(self.apt_path)) def _updateApt(self, old_timestamp): if old_timestamp != self._getAptModTime(): self._makeAptDigest(head=_('Modification of apt.dat.gz detected.')) # The new apt.dat may invalidate the current parking status, *rest = self.decodeParkingSetting(self.park.get()) if status == "apt.dat": # This was a parking position obtained from apt.dat; it may be # invalid with the new file, reset. self.park.set('') # This is also outdated with respect to the new apt.dat. self.aptDatCache.clear() # Accept any arguments to allow safe use as a Tkinter variable observer def updateMagFieldProvider(self, *args): from .geo.magfield import EarthMagneticField, MagVarUnavailable try: self.earthMagneticField = EarthMagneticField(self) except MagVarUnavailable as e: self.earthMagneticField = None self.earthMagneticFieldLastProblem = e.message from .fgdata import airport as airport_mod from .fgdata import parking as parking_mod from .gui import airport_finder as airport_finder_mod from .gui import gps_tool as gps_tool_mod for module in (airport_mod, parking_mod, airport_finder_mod, gps_tool_mod): module.setupEarthMagneticFieldProvider(self.earthMagneticField)
def __init__(self, args, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller self.configure(background='#2D303D') self.controller.title("CMC Video Recorder") camera_options = cameras.keys() global location location = StringVar() location.set('hall') loc_label = Label(self, text="Choose a camera location", background="#2D303D", foreground="#ffffff", padx="20", pady="10", font="16") loc_menu = OptionMenu(self, location, *camera_options) loc_menu.config(background="#21232d", foreground="#ffffff", activebackground="#E95420", padx="20", pady="10", font="16") loc_label.place(relx=.25, rely=.25, anchor="c") loc_menu.place(relx=.25, rely=.35, anchor="c") path_label = Label(self, text="Choose a path to save video", background="#2D303D", foreground="#ffffff", padx="20", pady="10", font="16") button_path = Button(self, text="Choose", command=self.get_path, bd=0, highlightthickness=0, background="#21232d", foreground="#ffffff", activebackground="#E95420", padx="20", pady="10", font="16") path_label.place(relx=.75, rely=.25, anchor="c") button_path.place(relx=.75, rely=.35, anchor="c") def change_dropdown(*args): print(location.get()) # link function to change dropdown location.trace('w', change_dropdown) button_record = Button(self, text="Load camera", command=self.load_camera, bd=0, highlightthickness=0, background="#21232d", foreground="#ffffff", activebackground="#E95420", padx="20", pady="10", font="16") button_record.place(relx=.5, rely=.5, anchor="c")
class WindowApp(object): """ The PDF Stampede app window """ def __init__(self, resizable=(True, True), geometry=(620, 220)): assert (isinstance(resizable, (tuple, list))) assert (isinstance(geometry, (tuple, list))) self.root = Tk() self.config = configparser.ConfigParser() self.config_file_name = "config.ini" self.config.read(self.config_file_name) self.default_case = StringVar(value=self.config["DEFAULT"].get("case", "CASE")) self.default_team = StringVar(value=self.config["DEFAULT"].get("team", "TEAM")) self.default_series = StringVar() self.default_last_index = StringVar() self.root.title("The Stampede") self.root.resizable(width=resizable[0], height=resizable[1]) self.root.geometry('{}x{}'.format(geometry[0], geometry[1])) self.root.minsize(geometry[0], geometry[1]) self.root.maxsize(geometry[0]+200, geometry[1]) self.file_name = StringVar() self.file_name.trace("w", self.file_name_changed) self.stamp_button = None self.add_widgets() self.add_menus() self.center(self.root) def add_widgets(self): # File frame = Frame(self.root) frame.pack(side=TOP, fill=X, expand=True, ipady=5) file_label = Label(frame, text="PDF File", width=10) file_label.pack(side=LEFT, padx=5, pady=5) file_entry = Entry(frame, state=DISABLED, textvariable=self.file_name) file_entry.pack(padx=5, side=LEFT, fill=X, expand=True) file_button = Button(frame, text="Browse...", command=self.choose_pdf) file_button.pack(padx=5, side=RIGHT) # Case frame = Frame(self.root) frame.pack(side=TOP, fill=X, expand=True) case_label = Label(frame, text="Case", width=10) case_label.pack(side=LEFT, padx=5, pady=5) case_entry = Entry(frame, textvariable=self.default_case) case_entry.pack(fill=X, padx=5, expand=True) # Team frame = Frame(self.root) frame.pack(fill=BOTH, expand=True) team_label = Label(frame, text="Team", width=10) team_label.pack(side=LEFT, padx=5, pady=5) team_entry = Entry(frame, textvariable=self.default_team) team_entry.pack(fill=X, padx=5, expand=True) # Series frame = Frame(self.root) frame.pack(fill=BOTH, expand=True) series_label = Label(frame, text="Series", width=10) series_label.pack(side=LEFT, padx=5, pady=5) series_entry = Entry(frame, textvariable=self.default_series) series_entry.pack(fill=X, padx=5, expand=True) # Last index frame = Frame(self.root) frame.pack(fill=BOTH, expand=True) last_index_label = Label(frame, text="Last index", width=10) last_index_label.pack(side=LEFT, padx=5, pady=5) last_index_entry = Entry(frame, textvariable=self.default_last_index) last_index_entry.pack(fill=X, padx=5, expand=True) bottom_frame = Frame(self.root) bottom_frame.pack(side=BOTTOM, fill=X, ipady=5, padx=5) close_button = Button(bottom_frame, text="Quit", command=self.root.quit) close_button.pack(side=RIGHT) self.stamp_button = Button(bottom_frame, text="Stamp it!", state=DISABLED, command=self.stamp_it) self.stamp_button.pack(side=RIGHT) def stamp_it(self): stamp_it( self.file_name.get(), self.default_case.get(), self.default_team.get(), self.default_series.get(), self.default_last_index.get(), ) def add_menus(self): menu_bar = Menu(self.root) stampede_menu = Menu(menu_bar, tearoff=0) stampede_menu.add_command(label="Settings", command=self.edit_default_settings) stampede_menu.add_separator() stampede_menu.add_command(label="Quit", command=self.root.quit) menu_bar.add_cascade(label="Stampede", menu=stampede_menu) self.root.config(menu=menu_bar) def run(self): self.root.mainloop() def center(self, window): window.update_idletasks() width = window.winfo_width() height = window.winfo_height() x = (window.winfo_screenwidth() // 2) - (width // 2) y = (window.winfo_screenheight() // 2) - (height // 2) window.geometry('{}x{}+{}+{}'.format(width, height, x, y)) def edit_default_settings(self): SettingsDialog(self.root, config=self.config, config_file_name=self.config_file_name) def choose_pdf(self): self.file_name.set(filedialog.askopenfilename(filetypes=(("PDF files", "*.pdf"),))) def file_name_changed(self, *args): if self.file_name.get(): self.stamp_button.configure(state=NORMAL) else: self.stamp_button.configure(state=DISABLED)
def __init__(self, output_path="./"): """ Initialize application which uses OpenCV + Tkinter. It displays a video stream in a Tkinter window and stores current snapshot on disk """ self.output_path = output_path # store output path self.current_image = None # current image from the camera self.root = Tk() # initialize root window self.root.geometry('1200x600') self.root.title("Attendance") # set window title self.destructor #function gets fired when the window is closed self.root.protocol('WM_DELETE_WINDOW', self.destructor) self.panel = Label(self.root, background='maroon', padx=320, pady=230) # initialize image panel self.panel.pack(padx=10, pady=10) self.root.config(cursor="arrow") global cam, period, faculty, subject period = StringVar(self.root) faculty = StringVar(self.root) subject = StringVar(self.root) cam = StringVar(self.root) #create a button, that when pressed, will take the current frame and save it to file attdButton = Label(self.root, text="ATTENDANCE", font=("Arial", 20), bg='maroon', fg='white') attdButton.place(x=50, y=50) startButton = Button(self.root, text="Start", borderwidth=2, relief='raised', font=("Arial", 20), padx=50, bg='dark blue', fg='white', command=self.start_cam) startButton.place(x=970, y=160) closeButton = Button(self.root, text="Close", font=("Arial", 20), padx=45, bg="dark blue", fg='white', command=self.destructor) closeButton.place(x=970, y=430) updateButton = Button(self.root, text="Update", font=("Arial", 20), padx=35, bg="dark blue", fg='white', command=self.update) updateButton.place(x=970, y=250) emailButton = Button(self.root, text='Email', font=("Arial", 20), padx=45, bg='dark blue', fg='white', command=self.email) emailButton.place(x=970, y=340) cam = " " global camMenu camMenu = Entry(self.root) camMenu.place(x=50, y=410) camLabel = Label(self.root, text='Choose Camera', font=("Arial Bold", 10)) camLabel.place(x=50, y=390) global lst_subject, lst_faculty facsub = pd.read_csv('Sub_fac.csv') subject_name = facsub['Subject'] faculty_name = facsub['Faculty'] lst_subject = subject_name.tolist() lst_faculty = faculty_name.tolist() periodLabel = Label(self.root, text='Choose Period', font=("Arial Bold", 10)) periodLabel.place(x=50, y=180) choices_period = [ "1" + " " * 30, "2" + " " * 30, "3" + " " * 30, "4" + " " * 30, "5" + " " * 30, "6" + " " * 30, "7" + " " * 30, "8" + " " * 30 ] period.set("Period") popupMenu = OptionMenu(self.root, period, *choices_period) popupMenu.place(x=50, y=200) def change_period(*args): global selected_period selected_period = period.get() # link function to change dropdown period.trace('w', change_period) facultyLabel = Label(self.root, text='Choose Faculty', font=("Arial Bold", 10)) facultyLabel.place(x=50, y=250) length = 25 lst_faculty = [i + " " * (length - len(i)) for i in lst_faculty] choices_faculty = lst_faculty faculty.set("Faculty") popupMenu_f = OptionMenu(self.root, faculty, *choices_faculty) popupMenu_f.place(x=50, y=270) def change_faculty(*args): global selected_faculty selected_faculty = faculty.get() faculty.trace('w', change_faculty) subjectLabel = Label(self.root, text='Choose Subject', font=("Arial Bold", 10)) subjectLabel.place(x=50, y=320) lst_subject = [i + " " * (length - len(i)) for i in lst_subject] choices_subject = lst_subject subject.set("Subject") popupMenu_s = OptionMenu(self.root, subject, *choices_subject) popupMenu_s.place(x=50, y=340) def change_subject(*args): global selected_subject selected_subject = subject.get() subject.trace('w', change_subject) datetimeButton = Label( self.root, borderwidth=2, relief='groove', text="Date : " + str(datetime.datetime.now().strftime("%d-%m-%Y")), font=("Arial Bold", 17), padx=30) datetimeButton.place(x=935, y=50) snapbtn = Button(self.root, text="Snapshot!", command=self.take_snapshot, padx=50, pady=10, bg='dark blue', font=("Arial Bold", 10), fg='white') snapbtn.place(x=500, y=500)
class DropdownList: def __init__(self, master, filemask='*.mln', default=None, allowNone=False, onselchange=None, directory='.'): self.allowNone = allowNone self.directory = directory self.list_frame = master self.onchange = onselchange if type(filemask) != list: filemask = [filemask] self.file_mask = filemask self.updateList() if havePMW: self.list = ComboBox(master, selectioncommand=onselchange, scrolledlist_items = self.files) self.list.component('entryfield').component('entry').configure(state = 'readonly', relief = 'raised') self.picked_name = self.list else: self.picked_name = StringVar() self.list = OptionMenu(*(master, self.picked_name) + tuple(self.files)) if onselchange is not None: self.picked_name.trace("w", self.onchange) if default is not None: self.select(default) else: self.select(self.files[0]) def __getattr__(self, name): return getattr(self.list, name) def get(self): return self.picked_name.get() def select(self, item): if item in self.files: if not havePMW: self.picked_name.set(item) else: self.list.selectitem(item) def updateList(self): self.files = [] if self.allowNone: self.files.append("") if os.path.exists(self.directory): for filename in os.listdir(self.directory): for fm in self.file_mask: if fnmatch(filename, fm): self.files.append(filename) self.files.sort() if len(self.files) == 0 and not self.allowNone: self.files.append("(no %s files found)" % str(self.file_mask)) def makelist(self): if havePMW: self.list = ComboBox(self.list_frame, selectioncommand = self.onSelChange, scrolledlist_items = self.files, ) self.list.grid(row=0, column=0, padx=0, pady=0, sticky="NEWS") self.list.component('entryfield').component('entry').configure(state = 'readonly', relief = 'raised') self.picked_name = self.list else: self.list = OptionMenu(*(self.list_frame, self.picked_name) + tuple(self.files)) self.list.grid(row=0, column=0, sticky="NEW") self.picked_name.trace("w", self.onSelChange) self.select(self.files[0]) def setDirectory(self, directory, keep=False): self.directory = directory self.updateList() self.makelist() # if keep is true, only the files list will be updated but the content of the # text area will not be altered/removed if not keep: self.select("") def onSelChange(self, name, index=0, mode=0): filename = self.picked_name.get() if self.onchange != None: self.onchange(filename)
class BotFrame(ttk.Frame): """Bottom part of the LeftFrame of the GUI. Handles all of the paths involved in the creation of a Job and updates the template in RightFrame when the template path changes. """ def __init__(self, parent, row=2, col=0): ttk.Frame.__init__(self, parent) self.grid(row=row, column=col, pady=10) self.parent = parent title = ttk.Label(self, text="Enviroment options", font=("Helvetica", 16), justify="center") title.grid(row=row, column=col, columnspan=2) self.job = self.parent.job ####################################################################### # Path to where job DQS files will be produced ####################################################################### self.jobsavepath = StringVar() self.jobsavepath.set(self.job.save_path) a = ttk.Button(self, text="Select Save Folder", width=15, command=self.setSavePathWithPrompt) a.grid(row=row + 1, column=col, pady=5, sticky=W) b = ttk.Entry(self, textvariable=self.jobsavepath, width=25) b.grid(row=row + 1, column=col + 1, pady=5, sticky=W + E) ####################################################################### # Path to where the current template is located ####################################################################### self.tmpltpath = StringVar(self) self.tmpltpath.set(self.job.template_path) self.tmpltpath.trace("w", self.setTemplatePath) c = ttk.Button(self, text="Select template", width=15, command=self.setTemplatePathWithPrompt) c.grid(row=row + 2, column=col, pady=5, sticky=W) d = ttk.Entry(self, textvariable=self.tmpltpath, width=25) d.grid(row=row + 2, column=col + 1, pady=5, sticky=W + E) ####################################################################### # Path to where the results will be saved on the cluster ####################################################################### respathl = ttk.Label(self, text="Results save folder: ") respathl.grid(row=row + 6, column=col, pady=3, sticky=W) self.respath = ttk.Entry(self) self.respath.insert(0, self.job.res_path) self.respath.grid(row=row + 6, column=col + 1, pady=3, sticky=W + E) ####################################################################### # Edit template ####################################################################### e = ttk.Button(self, text="Edit template", width=15, command=self.editTemplate) e.grid(row=row + 3, column=col, pady=5, sticky=W + E) self.savetmpbtn = ttk.Button(self, text="Save template", width=15, state=DISABLED, command=self.saveTemplate) self.savetmpbtn.grid(row=row + 3, column=col + 1, pady=5, sticky=W + E) def setSavePathWithPrompt(self): """Callback that will spawn a directory selector through which a new path, where the job DQS files will be saved, can be selected. """ newpath = filedialog.askdirectory( parent=self, title="Please select save destination.", initialdir=self.jobsavepath) # consider exiting via 'x' button the same as pressing cancel if newpath == (): self.jobsavepath.set(newpath) def setTemplatePath(self, *args): """Callback that will track the Entry box of the template path and upon modification will cause the RightFrame template display to reload the new template. """ newpath = self.tmpltpath.get() self.updateTemplatePath(newpath) def setTemplatePathWithPrompt(self): """Callback that will spawn a file selector window through which a new template can be selected. See setTemplatePath. Will cause an update of the RightFrame to redisplay the newly selected template. """ initdir = os.path.dirname(self.tmpltpath.get()) newpath = filedialog.askopenfilename(parent=self, title="Please select a template.", initialdir=initdir) # consider exiting via 'x' button the same as pressing cancel if newpath != (): self.tmpltpath.set(newpath) self.updateTemplatePath(newpath, showerr=True) def updateTemplatePath(self, path, showerr=False): """Updates the RightFrame's template display and replaces the current content with content read from a file at the provided path. If showerr is supplied an error will be raised if the given path does not exist. This is useful if the directory will be created after the path selection or if the update is called from a callback tied to a StringVar/Entry trace methods as a way to silence errors untill the full path has been manually inputed. Parameters ---------- path : str path to the new template showerr : bool if False no error will be raised even if path does not exist, usefull when error needs to be raised later, on a callback initiated by a button click """ tmppath = expandpath(path) activetmpl = self.parent.root.rightFrame.activetmpl if tmppath[0] and os.path.isfile(tmppath[1]): activetmpl.config(state=NORMAL) activetmpl.delete(1.0, END) activetmpl.insert(1.0, open(tmppath[1], "r").read()) activetmpl.config(state=DISABLED) self.job.template_path = tmppath[1] else: if showerr: messagebox.showerror(("Input Error. Input path does not exist " "or is a folder! {}".format(path))) activetmpl.config(state=NORMAL) activetmpl.delete(1.0, END) activetmpl.config(state=DISABLED) def editTemplate(self): """A callback of a Button action that will change the state of the RightFrame Text box and make it editable. """ self.savetmpbtn.config(state=NORMAL) self.activetmpl = self.parent.root.rightFrame.activetmpl self.activetmpl.config(state=NORMAL) def saveTemplate(self): """A Button callback that will save the current template to a file. Spawns a file dialog to retrieve the save location. Changes the state of the RightFrame Text box back to un-editable. """ self.savetmpbtn.config(state=DISABLED) self.activetmpl.config(state=DISABLED) filename = filedialog.asksaveasfilename(initialdir=self.tmpltpath, confirmoverwrite=True) f = open(filename, "w") for line in self.activetmpl.get(1.0, END): f.write(line) f.close() self.tmpltpath.set(filename)
class FilePickEdit(Frame): def __init__(self, master, file_mask, default_file, edit_height = None, user_onChange = None, rename_on_edit=0, font = None, coloring=True, allowNone=False, highlighter=None, directory='.'): """ file_mask: file mask (e.g. "*.foo") or list of file masks (e.g. ["*.foo", "*.abl"]) """ self.master = master self.directory = directory self.user_onChange = user_onChange Frame.__init__(self, master) row = 0 self.unmodified = True self.allowNone = allowNone self.file_extension = "" if type(file_mask) != list: file_mask = [file_mask] if "." in file_mask[0]: self.file_extension = file_mask[0][file_mask[0].rfind('.'):] # read filenames self.file_mask = file_mask self.updateList() # filename frame self.list_frame = Frame(self) self.list_frame.grid(row=row, column=0, sticky="WE") self.list_frame.columnconfigure(0, weight=1) # create list self.picked_name = StringVar() self.makelist() # refresh button self.refresh_button = Button(self.list_frame, text='<- refresh', command=self.refresh, height=1) self.refresh_button.grid(row=0, column=1, sticky='E') # save button self.save_button = Button(self.list_frame, text="save", command=self.save, height=1) self.save_button.grid(row=0, column=2, sticky="E") # editor row += 1 if coloring: self.editor = SyntaxHighlightingText(self, self.onEdit, highlighter=highlighter) else: self.editor = ScrolledText2(self, self.onEdit) if font is not None: self.editor.configure(font=font) if edit_height is not None: self.editor.configure(height=edit_height) self.editor.grid(row=row, column=0, sticky="NEWS") self.rowconfigure(row, weight=1) self.columnconfigure(0, weight=1) # option to change filename on edit row += 1 self.options_frame = Frame(self) self.options_frame.grid(row=row, column=0, sticky=W) self.rename_on_edit = IntVar() self.cb = Checkbutton(self.options_frame, text="rename on edit", variable=self.rename_on_edit) self.cb.pack(side=LEFT) self.cb.configure(command=self.onChangeRename) self.rename_on_edit.set(rename_on_edit) # filename frame row += 1 self.filename_frame = Frame(self) self.filename_frame.grid(row=row, column=0, sticky="WE") self.filename_frame.columnconfigure(0, weight=1) # save as filename self.save_name = StringVar() self.save_edit = Entry(self.filename_frame, textvariable = self.save_name) self.save_edit.grid(row=0, column=0, sticky="WE") self.save_name.trace("w", self.onSaveChange) # pick default if applicableButton self.select(default_file) self.row = row def setDirectory(self, directory, keep=False): self.directory = directory self.updateList() self.makelist() # menu = self.list["menu"] scrolledlist # menu = self.list.listbox#["scrolledlist"] # menu.delete(0, 'end') # add the new ones # for filename in self.files: # menu.add_command(label=filename, command=_setit(self.picked_name, filename, None)) # if keep is true, only the files list will be updated but the content of the # text area will not be altered/removed if not keep: self.select("") def refresh(self): sel = self.get() self.updateList() self.select(sel, notify=False) def reloadFile(self): self.editor.delete("1.0", END) filename = self.picked_name.get() if os.path.exists(os.path.join(self.directory, filename)): new_text = open(os.path.join(self.directory, filename)).read() if new_text.strip() == "": new_text = "// %s is empty\n" % filename new_text = new_text.replace("\r", "") else: new_text = "" self.editor.insert(INSERT, new_text) def setText(self, txt): """ Replaces the text in the edit field as by typing into it. """ self.select("") if txt.strip() == "": txt = "// empty database\n" self.editor.insert(INSERT, txt) self.onEdit() def onSelChange(self): self.reloadFile() filename = self.picked_name.get() self.save_name.set(filename) self.save_edit.configure(state=DISABLED) self.unmodified = True if self.user_onChange is not None: self.user_onChange(filename) def onSaveChange(self, name, index, mode): pass def autoRename(self): # modify "save as" name filename = self.picked_name.get() if filename == "": filename = "new" + self.file_extension # if no file selected, create new filename ext = "" extpos = filename.rfind(".") if extpos != -1: ext = filename[extpos:] base = filename[:extpos] hpos = base.rfind("-") num = 0 if hpos != -1: try: num = int(base[hpos+1:]) base = base[:hpos] except: pass while True: num += 1 filename = "%s-%d%s" % (base, num, ext) if not os.path.exists(filename): break self.save_name.set(filename) # user callback if self.user_onChange is not None: self.user_onChange(filename) def onEdit(self): if self.unmodified: self.unmodified = False # do auto rename if it's enabled or there is no file selected (editing new file) if self.rename_on_edit.get() == 1 or self.picked_name.get() == "": self.autoRename() # enable editing of save as name self.save_edit.configure(state=NORMAL) def onChangeRename(self): # called when clicking on "rename on edit" checkbox if self.rename_on_edit.get() == 1: if (not self.unmodified) and self.save_name.get() == self.picked_name.get(): self.autoRename() else: self.save_name.set(self.picked_name.get()) def updateList(self): self.files = [] if self.allowNone: self.files.append("") if os.path.exists(self.directory): for filename in os.listdir(self.directory): for fm in self.file_mask: if fnmatch(filename, fm): self.files.append(filename) self.files.sort() if len(self.files) == 0 and not self.allowNone: self.files.append("(no %s files found)" % str(self.file_mask)) def select(self, filename, notify=True): """ selects the item given by filename """ if filename in self.files: if not havePMW: self.picked_name.set(filename) else: self.list.selectitem(self.files.index(filename)) if notify: self.onSelChange(filename) else: self.editor.delete("1.0", END) def makelist(self): if havePMW: self.list = ComboBox(self.list_frame, selectioncommand = self.onSelChange, scrolledlist_items = self.files, ) self.list.grid(row=0, column=0, padx=0, pady=0, sticky="NEWS") self.list.component('entryfield').component('entry').configure(state = 'readonly', relief = 'raised') self.picked_name = self.list else: self.list = OptionMenu(*(self.list_frame, self.picked_name) + tuple(self.files)) self.list.grid(row=0, column=0, sticky="NEW") self.picked_name.trace("w", self.onSelChange) def save(self): self.get() def set(self, selected_item): self.select(selected_item) def get(self): """ gets the name of the currently selected file, saving it first if necessary """ filename = self.save_name.get() if self.unmodified == False: self.unmodified = True # save the file f = open(os.path.join(self.directory, filename), "w") f.write(self.editor.get("1.0", END).encode('utf-8')) f.close() # add it to the list of files # if not filename in self.files: # self.files.append(filename) # self.files.sort() # self.list.destroy() # self.makelist() # set it as the new pick #if havePMW: # self.picked_name.selectitem(self.files.index(filename), 1) #else: # self.picked_name.set(filename) # self.select(filename) self.refresh() self.select(filename, notify=False) self.save_edit.configure(state=DISABLED) return filename def get_text(self): return self.editor.get("1.0", END) def get_filename(self): return self.save_name.get() def set_enabled(self, state): self.editor.configure(state=state) if havePMW: self.list.component('entryfield_entry').configure(state=state) # self.list.component('arrowbutton').configure(state=state) self.list.component('arrowbutton').bind('<1>', (lambda a: 'break') if state==DISABLED else self.list._postList) else: self.list.configure(state=state) self.save_button.configure(state=state) self.cb.configure(state=state) self.save_edit.configure(state=state)
class HistoryWindow: def __init__(self, parent, win, hist_dict): self.window = win self.parent_window = parent self.hist_dict = hist_dict self.window.title("Full history") self.window.resizable(False, False) frm_top = Frame(win) frm_bottom = Frame(win) self.search = StringVar() self.search.trace( "w", lambda name, index, mode, sv=self.search: self.on_search(sv)) self.entry_search = Entry(frm_top, textvariable=self.search, width=57) self.entry_search.pack(side=LEFT, fill=BOTH, expand=1) self.btn_clear = Button(frm_top, text="Clear", command=self.on_clear) self.btn_clear.pack(side=RIGHT, fill=BOTH, expand=1) self.list_box = Listbox(frm_bottom, width=60, height=40, selectmode=SINGLE) self.list_box.pack(side=LEFT, fill=BOTH, expand=1) scroll = Scrollbar(frm_bottom, command=self.list_box.yview, orient=VERTICAL) scroll.pack(side=RIGHT, fill=Y) self.list_box.config(yscrollcommand=scroll.set) self.list_box.bind('<<ListboxSelect>>', self.on_listbox_select) frm_top.pack() frm_bottom.pack() self.window.bind("<FocusIn>", self.focus_callback) self.window.protocol("WM_DELETE_WINDOW", self.on_close) self.fill_list_box() def on_clear(self): self.search.set("") self.on_search(self.search) def on_search(self, search): query = search.get().strip().lower() if len(query) < 2: self.fill_list_box() return self.list_box.delete(0, END) search_results = [] for key in self.hist_dict: pos = key.lower().find(query) if pos == -1: continue search_results.append((key, pos)) search_results.sort(key=lambda x: x[1]) self.list_box.insert(END, *[x[0] for x in search_results]) def fill_list_box(self): self.list_box.delete(0, END) hist = sorted(self.hist_dict.items(), key=lambda x: x[1], reverse=True) self.list_box.insert(END, *[x[0] for x in hist]) def on_listbox_select(self, event): w = event.widget selected = w.curselection() if len(selected) == 0: return index = selected[0] value = w.get(index) self.parent_window.cb_model.set(value) def lift(self): self.window.lift() def on_close(self): self.parent_window.hist_window = None self.window.update_idletasks() self.window.destroy() def focus_callback(self, event): self.entry_search.selection_range(0, END) root.lift()
def __init__(self, master, par=False): """ GUI for selecting default parameters - will write parameters to file \ of users choosing. :type master: Tk :param master: Tkinter window :type par: EQcorrscanParameters :param par: Default parameters to start-up with. """ from tkinter import Label, Button, Entry, DoubleVar, StringVar, IntVar from tkinter import BooleanVar, OptionMenu, Checkbutton import tkMessageBox from eqcorrscan.utils import parameters from obspy import UTCDateTime import warnings # Set the default par, only if they don't already exist. if not par: par = parameters.EQcorrscanParameters([''], 2, 10, 4, 100, 2, '1900-01-01', '2300-01-01', '', 'seishub', 4, False, '', 'jpg', False, 8, 'MAD', 6) # Callback functions for all variables (ugly) def update_template_names(*args): par.template_names = [name.strip() for name in template_names.get().split(',')] template_names.set(', '.join(par.template_names)) def update_lowcut(*args): par.lowcut = lowcut.get() lowcut.set(par.lowcut) def update_highcut(*args): par.highcut = highcut.get() if par.highcut >= 0.5 * par.samp_rate: msg = ('Highcut must be less than the Nyquist, setting to ' + str((par.samp_rate / 2.0) - 1)) tkMessageBox.showwarning(title="Nyquist error", message=msg) par.highcut = (par.samp_rate / 2.0) - 1 highcut.set(par.highcut) def update_filt_order(*args): par.filt_order = filt_order.get() filt_order.set(par.filt_order) def update_samp_rate(*args): par.samp_rate = samp_rate.get() if par.highcut >= 0.5 * par.samp_rate: msg = ('Highcut must be less than the Nyquist, setting to ' + str((par.samp_rate / 2.0) - 1)) tkMessageBox.showwarning(title="Nyquist error", message=msg) par.highcut = (par.samp_rate / 2.0) - 1 highcut.set(par.highcut) samp_rate.set(par.samp_rate) def update_debug(*args): par.debug = debug.get() debug.set(par.debug) def update_startdate(*args): par.startdate = UTCDateTime(startdate.get()) startdate.set(str(par.startdate)) def update_enddate(*args): par.enddate = UTCDateTime(enddate.get()) enddate.set(str(par.enddate)) def update_archive(*args): par.archive = archive.get() archive.set(par.archive) def update_arc_type(*args): par.arc_type = arc_type.get() arc_type.set(par.arc_type) def update_cores(*args): par.cores = cores.get() cores.set(par.cores) def update_plotvar(*args): par.plotvar = plotvar.get() plotvar.set(par.plotvar) def update_plot_format(*args): par.plot_format = plot_format.get() plot_format.set(par.plot_format) def update_tempdir(*args): par.tempdir = tempdir.get() tempdir.set(par.tempdir) def update_threshold(*args): par.threshold = threshold.get() threshold.set(par.threshold) def update_threshold_type(*args): par.threshold_type = threshold_type.get() threshold_type.set(par.threshold_type) def update_plotdir(*args): par.plotdir = plotdir.get() plotdir.set(par.plotdir) def update_trigger_interval(*args): par.trigger_interval = trigger_interval.get() trigger_interval.set(par.trigger_interval) # Set some grid parameters nrows = 25 ncolumns = 3 self.master = master master.title("EQcorrscan parameter setup") self.label = Label(master, text="Alpha GUI for default setup") self.label.grid(column=0, columnspan=ncolumns, row=0) # Set up parameter input self.t_names_label = Label(master, text="Template names", anchor='e') self.t_names_label.grid(column=0, row=1, sticky='e') template_names = StringVar() template_names.set(', '.join(par.template_names)) self.t_names_box = Entry(master, bd=2, textvariable=template_names) self.t_names_box.grid(column=1, row=1) template_names.trace("w", update_template_names) self.t_names_lookup = Button(master, text="Lookup", command=lambda: self.get_template_names(par)) self.t_names_lookup.grid(column=2, row=1) self.lowcut_label = Label(master, text="Lowcut (Hz)", anchor='e') self.lowcut_label.grid(column=0, row=2, sticky='e') lowcut = DoubleVar() lowcut.set(par.lowcut) self.lowcut_box = Entry(master, bd=2, textvariable=lowcut) self.lowcut_box.grid(column=1, row=2) lowcut.trace("w", update_lowcut) self.highcut_label = Label(master, text="Highcut (Hz)", anchor='e') self.highcut_label.grid(column=0, row=3, sticky='e') highcut = DoubleVar() highcut.set(par.highcut) self.highcut_box = Entry(master, bd=2, textvariable=highcut) self.highcut_box.grid(column=1, row=3) highcut.trace("w", update_highcut) self.filt_order_label = Label(master, text="Filter order") self.filt_order_label.grid(column=0, row=4, sticky='e') filt_order = DoubleVar() filt_order.set(par.filt_order) self.filt_order_box = Entry(master, bd=2, textvariable=filt_order) self.filt_order_box.grid(column=1, row=4) filt_order.trace("w", update_filt_order) self.samp_rate_label = Label(master, text="Sample rate (Hz)") self.samp_rate_label.grid(column=0, row=5, sticky='e') samp_rate = DoubleVar() samp_rate.set(par.samp_rate) self.samp_rate_box = Entry(master, bd=2, textvariable=samp_rate) self.samp_rate_box.grid(column=1, row=5) samp_rate.trace("w", update_samp_rate) self.debug_label = Label(master, text="Debug") self.debug_label.grid(column=0, row=6, sticky='e') debug = IntVar() debug.set(par.debug) self.debug_box = Entry(master, bd=2, textvariable=debug) self.debug_box.grid(column=1, row=6) debug.trace("w", update_debug) self.startdate_label = Label(master, text="Start date (yyyy-mm-dd)") self.startdate_label.grid(column=0, row=6, sticky='e') startdate = StringVar() startdate.set(par.startdate) self.startdate_box = Entry(master, bd=2, textvariable=startdate) self.startdate_box.grid(column=1, row=6) startdate.trace("w", update_startdate) self.enddate_label = Label(master, text="End date (yyyy-mm-dd)") self.enddate_label.grid(column=0, row=8, sticky='e') enddate = StringVar() enddate.set(par.enddate) self.enddate_box = Entry(master, bd=2, textvariable=enddate) self.enddate_box.grid(column=1, row=8) enddate.trace("w", update_enddate) self.archive_label = Label(master, text="Archive") self.archive_label.grid(column=0, row=9, sticky='e') archive = StringVar() archive.set(par.archive) self.archive_box = Entry(master, bd=2, textvariable=archive) self.archive_box.grid(column=1, row=9) archive.trace("w", update_archive) self.archive_lookup = Button(master, text="Lookup", command=lambda: self.get_archive(par)) self.archive_lookup.grid(column=2, row=9) self.arc_type_label = Label(master, text="Archive type") self.arc_type_label.grid(column=0, row=10, sticky='e') arc_type = StringVar() arc_type.set(par.arc_type) self.arc_type_box = OptionMenu(master, arc_type, "seishub", "fdsn", "day_vols") self.arc_type_box.grid(column=1, row=10, sticky='w,e') arc_type.trace("w", update_arc_type) self.cores_label = Label(master, text="Number of cores") self.cores_label.grid(column=0, row=11, sticky='e') cores = IntVar() cores.set(par.cores) self.cores_box = Entry(master, bd=2, textvariable=cores) self.cores_box.grid(column=1, row=11) cores.trace("w", update_cores) self.plotvar_label = Label(master, text="Plotting on/off") self.plotvar_label.grid(column=0, row=12, sticky='e') plotvar = BooleanVar() plotvar.set(par.plotvar) self.plotvar_box = Checkbutton(master, text='Plot on', var=plotvar, onvalue=True, offvalue=False) self.plotvar_box.grid(column=1, row=12) plotvar.trace("w", update_plotvar) self.plotdir_label = Label(master, text="Plot directory") self.plotdir_label.grid(column=0, row=13, sticky='e') plotdir = StringVar() plotdir.set(par.plotdir) self.plotdir_box = Entry(master, bd=2, textvariable=plotdir) self.plotdir_box.grid(column=1, row=13) plotdir.trace("w", update_plotdir) self.plotdir_lookup = Button(master, text="Lookup", command=lambda: self.get_plotdir(par)) self.plotdir_lookup.grid(column=2, row=13) self.plot_format_label = Label(master, text="Plot format") self.plot_format_label.grid(column=0, row=14, sticky='e') plot_format = StringVar() plot_format.set(par.plot_format) self.plot_format_box = OptionMenu(master, plot_format, "jpg", "eps", "pdf", "png") self.plot_format_box.grid(column=1, row=14, sticky='w,e') plot_format.trace("w", update_plot_format) self.tempdir_label = Label(master, text="Temporary directory") self.tempdir_label.grid(column=0, row=15, sticky='e') tempdir = StringVar() tempdir.set(par.tempdir) self.tempdir_box = Entry(master, bd=2, textvariable=tempdir) self.tempdir_box.grid(column=1, row=15) tempdir.trace("w", update_tempdir) self.tempdir_lookup = Button(master, text="Lookup", command=lambda: self.get_tempdir(par)) self.tempdir_lookup.grid(column=2, row=15) self.threshold_label = Label(master, text="Threshold") self.threshold_label.grid(column=0, row=16, sticky='e') threshold = DoubleVar() threshold.set(par.threshold) self.threshold_box = Entry(master, bd=2, textvariable=threshold) self.threshold_box.grid(column=1, row=16) threshold.trace("w", update_threshold) self.threshold_type_label = Label(master, text="Threshold type") self.threshold_type_label.grid(column=0, row=17, sticky='e') threshold_type = StringVar() threshold_type.set(par.threshold_type) self.threshold_type_box = OptionMenu(master, threshold_type, "MAD", "absolute", "av_chan_corr") self.threshold_type_box.grid(column=1, row=17, sticky='w,e') threshold_type.trace("w", update_threshold_type) self.trigger_interval_label = Label(master, text="Minimum trigger " + "interval (s)") self.trigger_interval_label.grid(column=0, row=18, sticky='e') trigger_interval = DoubleVar() trigger_interval.set(par.trigger_interval) self.trigger_interval_box = Entry(master, bd=2, textvariable=trigger_interval) self.trigger_interval_box.grid(column=1, row=18) trigger_interval.trace("w", update_trigger_interval) # End of user editable section, now we have read/write buttons self.read_button = Button(master, text="Read parameters", command=lambda: self.read_par(master)) self.read_button.grid(column=0, row=nrows-2, sticky='w,e') self.write_button = Button(master, text="Write parameters", command=lambda: self.write_par(par)) self.write_button.grid(column=1, row=nrows-2, sticky='w,e')
borderwidth=1) frame_entry.grid(row=0, column=0) frame_search = tk.Frame(master=window, relief=tk.RAISED, borderwidth=1) frame_search.grid(row=0, column=1) sub_frame_search = tk.Frame(master=frame_search, relief=tk.RAISED) ########### Entry Frame ############### label_name = tk.Label(master=frame_entry, text="Name") entry_name = tk.Entry(master=frame_entry) label_barcode = tk.Label(master=frame_entry, text="Barcode") sv_barcode = StringVar() sv_barcode.trace("w", lambda name, index, mode, sv_barcode=sv_barcode: entry_update_search(sv_barcode)) entry_barcode = tk.Entry(master=frame_entry, textvariable=sv_barcode) label_length = tk.Label(master=frame_entry, text='Raw Length') entry_length = tk.Entry(master=frame_entry) label_slength = tk.Label(master=frame_entry, text='Swage Length') entry_slength = tk.Entry(master=frame_entry) label_cleancode = tk.Label(master=frame_entry, text='Clean Code') sv_cleanCode = StringVar(window) cleanOptions = [ "0: Not Cleaned", "1: Cleaning described in comment", "2: Wiped with Ethanol", "3: Only Vacuumed", "4: Vacuumed and Wiped with Ethanol", "5: Vacuumed with Nitrogen"
class Main(): def __init__(self, master): global profiles self.master = master master.title("Anime Tracker") topFrame = Frame(master,width=300,height=250) topFrame.grid() bottomFrame = Frame(master) bottomFrame.grid() if os.path.isfile("bg.png") == True: background_image=PhotoImage(file="bg.png") background_label=Label(master,image=background_image) background_label.photo=background_image background_label.place(x=0,y=0,relwidth=1,relheight=1) self.eps = StringVar(master) self.time = StringVar(master) self.var = StringVar(master) self.var.trace("w", self.crawl) self.var.set(profiles[0]) o = OptionMenu(master, self.var, *profiles) o.grid(sticky='s',pady=5,column=0,row=0) self.l1 = Label(master, textvariable = self.eps) self.l1.grid(column=0,row=1,pady=2,sticky='s') self.l2 = Label(master, textvariable = self.time) self.l2.grid(column=0,row=2,pady=2,sticky='s') self.b = Button(master, text = "+1", command = self.add) self.b.grid(column=0,row=3,pady=10) def crawl(self, *args): global timeFormat for i in range(len(profiles)): if profiles[i] == self.var.get(): f = open("Profiles/" + profiles[i] + ".txt","r") data = [] for line in f: if len(line) > 0 and line[0] != '#': linesplit = line.split(":") data.append(linesplit[1][:len(linesplit[1])-1]) f.close() complete = False if int(data[0])-int(data[2]) == 0: complete = True if complete == True: epsvar = "Complete!)" timevar = "Complete!)" else: epsvar = str(int(data[0])-int(data[2])) + " remaining)" if timeFormat == 0: timevar = str((int(data[0])*int(data[1]))-(int(data[1])*int(data[2]))) + " remaining)" elif timeFormat == 1: timevar = str(int(((int(data[0])*int(data[1]))-(int(data[1])*int(data[2])))/60)) + " hours " + str(((int(data[0])*int(data[1]))-(int(data[1])*int(data[2])))%60) + " minutes remaining)" elif timeFormat == 2: timevar = str(((int(data[0])*int(data[1]))-(int(data[1])*int(data[2])))/60) + " hours remaining)" self.eps.set(data[2] + '/' + data[0] + " episodes watched (" + epsvar) if timeFormat == 0: self.time.set(str(int(data[1])*int(data[2])) + "/" + str(int(data[0])*int(data[1])) + " minutes watched (" + timevar) elif timeFormat == 1: self.time.set(str(int(int(data[1])*int(data[2])/60)) + "h" + str(int(data[1])*int(data[2])%60) + "m/" + str(int(int(data[0])*int(data[1])/60)) + "h" + str(int(data[0])*int(data[1])%60) + "m (" + timevar) elif timeFormat == 2: self.time.set(str(int(data[1])*int(data[2])/60) + "h/" + str(int(data[0])*int(data[1])/60) + "h (" + timevar) def add(self): all_data = [] with open("Profiles/" + self.var.get() + ".txt") as f: for line in f: name, value = line.split(":") all_data.append((name, int(value))) a=all_data[0] b=all_data[2] if a[1] == b[1]: messagebox.showinfo("Oops!", "This is already complete!") else: if os.path.exists('temp') == False: os.mkdir('temp') with tempfile.NamedTemporaryFile(mode='w', delete=False, dir="temp") as f: for name, value in all_data: if name == "WATCHED": print(f"{name}:{value + 1}", file=f) else: print(f"{name}:{value}", file=f) os.replace(f.name, "Profiles/" + self.var.get() + ".txt") self.crawl shutil.rmtree('temp') self.var.set(self.var.get())
class EditInjectorGUI: """Class representing a window for editing a currently loaded install config in the GUI. Attributes ---------- root : InstallSynAppsGUI The top TK instance that opened this window master : Toplevel The main container Tk object viewFrame Tk frame that contains all widgets dropdown : OptionMenu dropdown menu for selecting from injector files applyButton : Button button that runs the apply method editPanel : ScrolledText Panel for editing the loaded injector file. """ def __init__(self, root, install_config): """Initializer for the EditInjectorGUI class """ self.root = root self.master = Toplevel() self.master.title('Edit Injector Files') self.master.resizable(False, False) self.smallFont = tkFont.Font(family="Helvetica", size=10) self.largeFont = tkFont.Font(family="Helvetica", size=14) self.install_config = install_config self.viewFrame = Frame(self.master, relief=GROOVE, padx=10, pady=10) self.viewFrame.pack() self.injectorList = [] for file in self.install_config.injector_files: self.injectorList.append(file.name) self.currentEditVar = StringVar() self.currentEditVar.set(self.injectorList[0]) self.dropdown = OptionMenu(self.viewFrame, self.currentEditVar, self.injectorList[0], *self.injectorList) self.dropdown.config(width=20) self.dropdown.grid(row=0, column=0, columnspan=1, padx=5, pady=5) self.currentEditVar.trace('w', self.updateEditPanel) Button(self.viewFrame, text='New Injector', command=self.newInjector, width=10).grid(row=0, column=1, columnspan=1) Button(self.viewFrame, text='Apply Changes', command=self.applyChanges, width=10).grid(row=0, column=2, columnspan=1) Button(self.viewFrame, text='Apply and Exit', command=self.applyExit, width=10).grid(row=0, column=3, columnspan=1) Button(self.viewFrame, text='Reload', command=self.reloadPanel, width=10).grid(row=0, column=4, columnspan=1) self.editPanel = ScrolledText.ScrolledText(self.viewFrame, height=37, width=100) self.editPanel.grid(row=1, column=0, columnspan=5) self.updateEditPanel() self.master.mainloop() def newInjector(self): """Function for creating new injector files from within the GUI """ new_name = simpledialog.askstring( 'New Injector', 'Please enter a new injector filename') if new_name is not None: new_target = simpledialog.askstring( 'New Target', 'Please enter an injector target relative path using $(INSTALL), $(SUPPORT), $(AREA_DETECTOR), or $(MOTOR)' ) if new_target is not None: if not new_target.startswith( '$(INSTALL)') and not new_target.startswith( '$(SUPPORT)') and not new_target.startswith( '$(AREA_DETECTOR)' ) and not new_target.startswith('$(MOTOR)'): messagebox.showerror( 'ERROR', 'Please enter a valid relative path.') return self.install_config.add_injector_file(new_name, '', new_target) self.root.updateAllRefs(self.install_config) del self.injectorList[:] for file in self.install_config.injector_files: self.injectorList.append(file.name) self.currentEditVar.set(self.injectorList[0]) self.dropdown = OptionMenu(self.viewFrame, self.currentEditVar, self.injectorList[0], *self.injectorList) self.dropdown.config(width=20) self.dropdown.grid(row=0, column=0, columnspan=1, padx=5, pady=5) self.reloadPanel() def updateEditPanel(self, *args): """Wrapper that reloads the panel based on selection """ self.reloadPanel() def reloadPanel(self): """Reloads Panel based on selection """ target_file = self.currentEditVar.get() contents = '' link = '' for file in self.install_config.injector_files: if file.name == target_file: contents = file.contents link = file.target self.editPanel.delete('1.0', END) self.editPanel.insert(INSERT, '#\n') self.editPanel.insert(INSERT, '# The below contents will be injected into:\n') self.editPanel.insert(INSERT, '# {}\n'.format(link)) self.editPanel.insert(INSERT, '#\n\n') self.editPanel.insert(INSERT, contents) def applyChanges(self): """Method that reads the edit panel, and sets the injector contents to whatever the user wrote. Note that there are no checks to see if the injection will be valid. """ temp = self.editPanel.get('1.0', END).splitlines() new_contents = '' for line in temp: if not line.startswith('#'): new_contents = new_contents + line + '\n' target = self.currentEditVar.get() for file in self.install_config.injector_files: if file.name == target: file.contents = new_contents self.root.writeToLog('Applied updated injector file contents.\n') self.root.unsaved_changes = True self.root.updateAllRefs(self.install_config) def applyExit(self): """Applies changes and exits window """ self.applyChanges() self.master.destroy()
class OptionsFrame(LabelFrame): ''' This class creates Checkbuttons and Radiobuttons for displaying and modifying some of the parameters. Attributes: params (Parameters): object with all parameters. Some of the parameter values are modified in this class. current_categories (list of str): list of categories. input_categories_frame (CategoriesCheckBox): frame with input categories. It is needed in this class to read what categories are input. output_categories_frame (CategoriesCheckBox): frame with output categories. It is needed in this class to read what categories are output. categorical_box (Combobox): Combobox for choosing categorical category. combobox_text_var (StringVar): text variable of categorical_box. options (dict of str to IntVar): dictionary that stores IntVars of Radiobuttons and Checkbuttons. Example: >>> options = {"RETURN_TO_SCALE": IntVar(), "ORIENTATION": IntVar()} multi_tol_strvar (StringVar): StringVar object that stores tolerance of multiplier model. max_slack_box (Checkbutton): Checkbutton for the option "Two phase". Args: parent (Tk object): parent of this widget. params (Parameters): object with all parameters. Some of the parameter values are modified in this class. current_categories (list of str): list of categories. input_categories_frame (CategoriesCheckBox): frame with input categories. It is needed in this class to read what categories are input. output_categories_frame (CategoriesCheckBox): frame with output categories. It is needed in this class to read what categories are output. name (str, optional): name of the LabelFrame that this class represents, defaults to Options. ''' def __init__(self, parent, params, current_categories, input_categories_frame, output_categories_frame, name='Options', *args, **kw): super().__init__(parent, text=name, *args, **kw) self.params = params self.current_categories = current_categories self.input_categories_frame = input_categories_frame self.output_categories_frame = output_categories_frame self.categorical_box = None self.combobox_text_var = StringVar() self.combobox_text_var.trace('w', self.on_categorical_box_change) self.options = dict() self.multi_tol_strvar = StringVar() self.multi_tol_strvar.trace('w', self.on_multi_tol_change) self.max_slack_box = None self.create_widgets() def create_widgets(self): ''' Creates all widgets. ''' rts_lbl = Label(self, text='Return to scale:') rts_lbl.grid(row=0, column=0, padx=XPAD_VALUE, pady=YPAD_VALUE, sticky=W) self._create_frame_with_radio_btns(self, 'RETURN_TO_SCALE', ['VRS', 'CRS'], row_index=1, column_index=0) orientation_lbl = Label(self, text='Orientation:') orientation_lbl.grid(row=0, column=1, sticky=W, padx=XPAD_VALUE, pady=YPAD_VALUE) self._create_frame_with_radio_btns(self, 'ORIENTATION', ['Input', 'Output'], row_index=1, column_index=1) model_lbl = Label(self, text='Model:') model_lbl.grid(row=0, column=2, padx=XPAD_VALUE, pady=YPAD_VALUE, sticky=W) self._create_frame_with_radio_btns(self, 'DEA_FORM', ['Envelopment', 'Multiplier'], row_index=1, column_index=2, add_both=False) other_lbl = Label(self, text='Others:') other_lbl.grid(row=0, column=3, sticky=W, padx=XPAD_VALUE) max_slacks = IntVar() self.options['MAXIMIZE_SLACKS'] = max_slacks frame_other_options = Frame(self) self.max_slack_box = max_slacks_check_btn = Checkbutton( frame_other_options, text='Two phase', variable=max_slacks, command=(lambda: self.on_check_box_click( max_slacks, 'MAXIMIZE_SLACKS'))) max_slacks_check_btn.grid(row=1, column=0, sticky=W) super_efficiency = IntVar() self.options['USE_SUPER_EFFICIENCY'] = super_efficiency super_efficiency_check_btn = Checkbutton(frame_other_options, text='Super efficiency', variable=super_efficiency, command=( lambda: self.on_check_box_click( super_efficiency, 'USE_SUPER_EFFICIENCY'))) super_efficiency_check_btn.grid(row=2, column=0, sticky=W) peel_the_onion = IntVar() self.options['PEEL_THE_ONION'] = peel_the_onion peel_the_onion_check_btn = Checkbutton( frame_other_options, text='Peel the onion', variable=peel_the_onion, command=(lambda: self.on_check_box_click(peel_the_onion, 'PEEL_THE_ONION'))) peel_the_onion_check_btn.grid(row=3, column=0, sticky=W) frame_other_options.grid(row=1, column=3, padx=XPAD_VALUE, pady=YPAD_VALUE, sticky=W) frame_for_toleramce = Frame(self) tolerance_lbl = Label(frame_for_toleramce, text='Multiplier model tolerance:') tolerance_lbl.grid(row=0, column=0, padx=XPAD_VALUE, pady=YPAD_VALUE, sticky=W) tolerance_ent = Entry(frame_for_toleramce, width=5, textvariable=self.multi_tol_strvar) tolerance_ent.insert(END, 0) tolerance_ent.grid(row=0, column=1, sticky=W, padx=XPAD_VALUE) categorical_lbl = Label(frame_for_toleramce, text='Categorical:') categorical_lbl.grid(row=1, column=0, padx=XPAD_VALUE, pady=YPAD_VALUE, sticky=W) self.categorical_box = categorical_box = Combobox( frame_for_toleramce, textvariable=self.combobox_text_var, exportselection=0, state="readonly", width=20, values=(''), postcommand=self.change_categorical_box) categorical_box.grid(row=1, column=1, padx=XPAD_VALUE, pady=YPAD_VALUE, sticky=W) frame_for_toleramce.grid(row=5, column=0, sticky=W, padx=XPAD_VALUE, pady=YPAD_VALUE, columnspan=4) def _create_frame_with_radio_btns(self, parent, name, text, row_index, column_index, add_both=True): ''' Creates frame with one set of Radiobuttons. Args: parent (Tk object): parent of the frame. name (str): name of the parameter that will a key in options dictionary. text (list of str): list with two parameter values that should be displayed next to the first two Radiobuttons. row_index (int): index of the row where the frame should be placed using grid method. column_index (int): index of the column where the frame should be placed using grid method. add_both (bool, optional): True if the third Radiobutton with text "both" must be displayed, False otherwise, defaults to True. ''' assert len(text) == 2 v = IntVar() self.options[name] = v self.options[name].trace( 'w', (lambda *args: self.radio_btn_change(name))) frame_with_radio_btns = Frame(parent) first_option = Radiobutton(frame_with_radio_btns, text=text[0], variable=v, value=1) first_option.grid(row=0, column=0, sticky=W+N, padx=2) v.set(1) second_option = Radiobutton(frame_with_radio_btns, text=text[1], variable=v, value=2) second_option.grid(row=1, column=0, sticky=W+N, padx=2) if add_both: both = Radiobutton(frame_with_radio_btns, text='Both', variable=v, value=3) both.grid(row=3, column=0, sticky=W+N, padx=2) frame_with_radio_btns.grid(row=row_index, column=column_index, padx=1, pady=5, sticky=W+N) def radio_btn_change(self, name, *args): ''' Actions that happen when user clicks on a Radiobutton. Changes the corresponding parameter values and options. Args: name (str): name of the parameter that is a key in options dictionary. *args: are provided by IntVar trace method and are ignored in this method. ''' count = self.options[name].get() self.params.update_parameter(name, COUNT_TO_NAME_RADIO_BTN[name, count]) dea_form = COUNT_TO_NAME_RADIO_BTN[name, count] if self.max_slack_box: # on creation it is None if dea_form == 'multi': # disable max slacks self.max_slack_box.config(state=DISABLED) self.params.update_parameter('MAXIMIZE_SLACKS', '') elif dea_form == 'env': self.max_slack_box.config(state=NORMAL) if self.options['MAXIMIZE_SLACKS'].get() == 1: self.params.update_parameter('MAXIMIZE_SLACKS', 'yes') def change_categorical_box(self): ''' Updates categories that can be chosen as categorical category when the user clicks on the Combobox. ''' values = [category for category in self.current_categories if category and category not in self.input_categories_frame.category_objects.keys() and category not in self.output_categories_frame.category_objects.keys()] values.append('') self.categorical_box.config(values=values) def on_categorical_box_change(self, *args): ''' Updates value of the CATEGORICAL_CATEGORY in parameters. This method is called when the user clicks on the Combobox and chooses one item from the drop-down list. Args: *args: are provided by the StringVar trace method and are ignored in this method. ''' categorical_var = self.combobox_text_var.get() self.params.update_parameter('CATEGORICAL_CATEGORY', categorical_var) def set_params_values(self): ''' Reads all parameter values from the parameter object (params) and sets all widgets and options to these read values. Might display warnings if invalid values are stored in parameter object. ''' self.set_radio_btns() self.set_check_btns() self.change_categorical_box() self.set_categorical_box(self.params.get_parameter_value( 'CATEGORICAL_CATEGORY')) self.set_multi_tol() def set_radio_btns(self): ''' Goes through all Radiobuttons and changes their values according to the values stored in parameter object. Might display warnings. ''' self.set_one_radio_btn('RETURN_TO_SCALE', ['VRS', 'CRS', 'both']) self.set_one_radio_btn('ORIENTATION', ['input', 'output', 'both']) self.set_one_radio_btn('DEA_FORM', ['env', 'multi']) def set_one_radio_btn(self, param_name, valid_values): ''' Sets value of a given set of Radiobuttons according to its value stored in parameter object if this value is valid. Might display warnings. Args: param_name (str): name of parameter whose value must be changed. valid_values (list of str): list of valid values that this parameter might take. ''' param_value = self.params.get_parameter_value(param_name) for count, value in enumerate(valid_values): if param_value == value: self.options[param_name].set(count + 1) return self._show_warning(param_name) self.options[param_name].set(1) def _show_warning(self, param_name): ''' Displays a warning saying that a value of a given parameter is not valid. Args: param_name (str): name of the parameter. ''' showwarning('Warning', 'Parameter <{0}> does not have valid values.' ' It will be set to default'. format(param_name)) def set_check_btns(self): ''' Goes through all Checkbuttons and changes their values according to the values stored in parameter object. Might display warnings. ''' self.set_one_check_btn('MAXIMIZE_SLACKS') self.set_one_check_btn('PEEL_THE_ONION') self.set_one_check_btn('USE_SUPER_EFFICIENCY') def set_one_check_btn(self, param_name): ''' Sets value of a given set of Checkbutton according to its value stored in parameter object if this value is valid. Might display warnings. Args: param_name (str): name of parameter whose value must be changed. ''' param_value = self.params.get_parameter_value(param_name) if param_value: self.options[param_name].set(1) def set_categorical_box(self, categorical_param): ''' Sets the value of Combobox with categorical category according to a given value if this value is in the list of values of this Combobox. If the given value is not in the list of values, a warning is displayed. Args: categorical_param (str): value of the categorical category. ''' if categorical_param in self.categorical_box.cget('values'): self.combobox_text_var.set(categorical_param) else: self._show_warning_combobox(categorical_param) def _show_warning_combobox(self, categorical_param): ''' Displays a warning saying that a value of a given parameter is not a valid categorical category. Args: categorical_param (str): name of the categorical category. ''' showwarning('Warning', 'Category: <{0}> cannot be chosen as a ' 'categorical variable'. format(categorical_param)) def set_multi_tol(self): ''' Sets the value of Entry with multiplier model tolerance according to a given value if this value is valid (non-negative float). If the given value is invalid, a warning is displayed. ''' tol_str = self.params.get_parameter_value('MULTIPLIER_MODEL_TOLERANCE') try: tol = float(tol_str) if (tol < 0): self._show_multi_tol_warning(tol_str) self.multi_tol_strvar.set('0') else: self.multi_tol_strvar.set(tol_str) except ValueError: self._show_multi_tol_warning(tol_str) self.multi_tol_strvar.set('0') def _show_multi_tol_warning(self, tol_str): ''' Displays a warning saying that a value of a multiplier model tolerance is invalid. Args: tol_str (str): value of the multiplier model tolerance. ''' showwarning('Warning', 'Value: <{0}> is not valid as a multiplier' ' model tolerance'. format(tol_str)) def on_multi_tol_change(self, *args): ''' Updates parameter MULTIPLIER_MODEL_TOLERANCE in the parameter object when the user modifies the content of the Entry widget that stores multiplier model tolerance. Args: *args: are provided by the StringVar trace method and are ignored in this method. ''' # this parameter will be validated before run tol_str = self.multi_tol_strvar.get() self.params.update_parameter('MULTIPLIER_MODEL_TOLERANCE', tol_str) def on_check_box_click(self, var, name): ''' Updates parameter specified by the Checkbutton in the parameter object when the user clicks on the Checkbutton. Args: var (IntVar): IntVar of the Checkbutton. name (str): name of the parameter that is the key in options dictionary. ''' if var.get() == 1: self.params.update_parameter(name, 'yes') else: self.params.update_parameter(name, '')
def __init__(self): Cursante.__init__(self) Form.__init__(self) self.id_register = None self.fieldsFrame = Frame(self.root, relief="groove", padding=(15, 15)) self.fieldsFrame.grid(row=0, column=0, padx=10, pady=10) lbl_dni = Label(self.fieldsFrame, text="DNI: ", width=10) lbl_dni.grid(row=1, column=0, columnspan=10) dni = StringVar() e_dni = Entry(self.fieldsFrame, textvariable=dni, width=40) e_dni.grid(row=2, column=0, columnspan=40, pady=(0, 15)) lbl_name = Label(self.fieldsFrame, text="Nombre: ", width=10) lbl_name.grid(row=3, column=0, columnspan=10) name = StringVar() e_name = Entry(self.fieldsFrame, textvariable=name, width=40) e_name.grid(row=4, column=0, columnspan=40, pady=(0, 15)) lbl_surname = Label(self.fieldsFrame, text="Apellido: ", width=10) lbl_surname.grid(row=5, column=0, columnspan=10) surname = StringVar() e_surname = Entry(self.fieldsFrame, textvariable=surname, width=40) e_surname.grid(row=6, column=0, columnspan=40, pady=(0, 15)) lbl_email = Label(self.fieldsFrame, text="Email: ", width=10) lbl_email.grid(row=7, column=0, columnspan=10) email = StringVar() e_email = Entry(self.fieldsFrame, textvariable=email, width=40) e_email.grid(row=8, column=0, columnspan=40, pady=(0, 15)) lbl_phone = Label(self.fieldsFrame, text="Teléfono: ", width=10) lbl_phone.grid(row=9, column=0, columnspan=10) phone = StringVar() e_phone = Entry(self.fieldsFrame, textvariable=phone, width=40) e_phone.grid(row=10, column=0, columnspan=40, pady=(0, 15)) lbl_institute = Label(self.fieldsFrame, text="Institución: ", width=10) lbl_institute.grid(row=11, column=0, columnspan=10) institute = StringVar() e_institute = Combobox(self.fieldsFrame, textvariable=institute, width=37, values=("UNTDF", "UTN", "OTRO"), state="readonly") e_institute.current(0) e_institute.grid(row=12, column=0, columnspan=40, pady=(0, 15)) super().set_fields({ "dni": dni, "nombre": name, "apellido": surname, "email": email, "telefono": phone, "institucion": institute }) dni.trace("w", lambda *args: self.validate_dni(dni, *args)) name.trace("w", lambda *args: self.validate_str(name, *args)) surname.trace("w", lambda *args: self.validate_str(surname, *args)) phone.trace("w", lambda *args: self.validate_phone(phone, *args))
def overwriteWindow(root): '''Creates the window for deciding to overwrite or not.''' def toggle(*args): setState(choice.get(), 'disabled', [gen2Label, gen3Label, gen2Button, gen3Button, gen2Entry, gen3Entry]) setState(not choice.get(), 'disabled', [warningLabel]) if not choice.get() and (gen2Text.get() == '' or gen3Text.get() == ''): navFrame.disable('next', True) else: navFrame.disable('next', False) def gen2Dialog(): askSave = filedialog.asksaveasfilename file = askSave(title='Gen II Save File', initialdir=root.dir, filetypes=[('GB Save', '.sav'), ('All Files', '.*')], defaultextension='.sav') if file != '': gen2Text.set(file) gen2Entry.after_idle(gen2Entry.xview_moveto, 1) root.dir = getDir(file) def gen3Dialog(): askSave = filedialog.asksaveasfilename file = askSave(title='Gen III Save File', initialdir=root.dir, filetypes=[('GBA Save', '.sav'), ('All Files', '.*')], defaultextension='.sav') if file != '': gen3Text.set(file) gen3Entry.after_idle(gen3Entry.xview_moveto, 1) root.dir = getDir(file) def nextPage(): global newGen2, newGen3, oldGen2, oldGen3 if choice.get(): newGen2 = oldGen2 newGen3 = oldGen3 else: newGen2 = gen2Entry.get() newGen3 = gen3Entry.get() root.nextPage() baseFrame = ttk.Frame(root) baseFrame.rowconfigure(0, weight=1) baseFrame.columnconfigure(0, weight=1) mainFrame = ttk.Frame(baseFrame, padding=MAIN_PAD) mainFrame.grid(row=0, column=0, sticky='ns') mainFrame.rowconfigure(0, weight=2) mainFrame.rowconfigure(3, weight=1) instrText = 'Select whether to overwrite the original save files, or to create new save files.' instrLabel = ttk.Label(mainFrame, text=instrText) instrLabel.grid(row=0, column=0) choiceFrame = ttk.Frame(mainFrame) choiceFrame.grid(row=1, column=0) choice = BooleanVar(value=True) choice1Radio = ttk.Radiobutton(choiceFrame, text='Overwrite', variable=choice, command=toggle, value=True) choice1Radio.grid(row=0, column=0, pady=5, sticky='w') warningText = 'WARNING! Once new data is created, this program can not recover old save data.' warningLabel = ttk.Label(choiceFrame, text=warningText, wraplength=300) warningLabel.grid(row=1, column=0, pady=5) choice2Radio = ttk.Radiobutton(choiceFrame, text='Do not overwrite', variable=choice, command=toggle, value=False) choice2Radio.grid(row=2, column=0, pady=5, sticky='w') pickerFrame = ttk.Frame(mainFrame) pickerFrame.grid(row=2, column=0) gen2Label = ttk.Label(pickerFrame, text='New Gen II file:') gen2Label.grid(row=0, column=0, columnspan=2) gen2Button = ttk.Button(pickerFrame, text='To...', command=gen2Dialog) gen2Button.grid(row=1, column=0, sticky='e', padx=5, pady=5) gen2Text = StringVar(pickerFrame) gen2Text.trace('w', toggle) gen2Entry = ttk.Entry(pickerFrame, textvariable=gen2Text, state='readonly') gen2Entry.grid(row=1, column=1, sticky='w', padx=5, pady=5) gen3Label = ttk.Label(pickerFrame, text='New Gen III file:') gen3Label.grid(row=2, column=0, columnspan=2) gen3Button = ttk.Button(pickerFrame, text='To...', command=gen3Dialog) gen3Button.grid(row=3, column=0, sticky='e', padx=5, pady=5) gen3Text = StringVar(pickerFrame) gen3Text.trace('w', toggle) gen3Entry = ttk.Entry(pickerFrame, textvariable=gen3Text, state='readonly') gen3Entry.grid(row=3, column=1, sticky='w', padx=5, pady=5) #todo: make sure user doesn't put the same file for both entries fillerFrame = ttk.Frame(mainFrame) fillerFrame.grid(row=3, column=0, sticky='ns') navFrame = Nav(baseFrame, root.prevPage, nextPage) navFrame.grid(row=1, column=0, sticky='we') if debug: gen2Text.set('C:/Users/Sidnoea/Documents/GitHub/pokeBridge/New Gen 2.sav') gen3Text.set('C:/Users/Sidnoea/Documents/GitHub/pokeBridge/New Gen 3.sav') choice.set(False) toggle() return (baseFrame, 'Overwrite?', {'sticky':'nsew'})
#iconlabel imgWeb = PhotoImage(file="img/web.png") imgAvatar = PhotoImage(file="img/avatar.png") imgSend = PhotoImage(file="img/document-send.png") imgAtt = PhotoImage(file="img/attachment.png") imageLabel = Label(frame, image=imgWeb, bg="cyan4") imageLabel.place(x=16, y=60) #userid label emailLabel = Label(frame, text="Email \t\t\t\t", bg="SkyBlue3", font=('times', 11)) emailLabel.pack(padx=0, pady=0, ipadx=36, ipady=0, fill=BOTH) #userid entry valid = StringVar() valid.trace('w', met_valid) emailId = Entry(frame, font=('times', 12), bg="white", fg="black", textvariable=valid) emailId.image = PhotoImage(file="img/sAvatar.png") emailId.image2 = PhotoImage(file="img/pass.png") passLabel = Button(frame, image=emailId.image, bg="white", bd=0, command=validateId) passLabel.place(x=266, y=204) passLabel.bind("<Return>", validateId) emailId.pack(padx=10, ipadx=34, ipady=4, pady=2) emailId.focus() emailId.bind("<Return>", validateId) #warning label warnLabel = Label(frame, text="", bg="SkyBlue3", fg='red', font=('times', 11)) warnLabel.pack(padx=0, pady=0, ipadx=36, ipady=0, fill=BOTH) # login button
class ConfigurationWindow(Frame): """ Klasa GUI konfiguratora roweru w metodzie 'createBike' jest tworzony obiekt roweru z wykorzystaniem dekoratorów """ def __init__(self, parent, frames, forks, wheelsets, groups, components): """ inicjalizacja obiektu okna - nieistotne dla idei zdania """ super(ConfigurationWindow, self).__init__(parent) self._bike = None self.parent = parent self.frames = frames self.forks = forks self.wheelsets = wheelsets self.groups = groups self.components = components self.parent.title("Bicycle configurator") self._bike_price = StringVar(self.parent) self._bike_weight = StringVar(self.parent) self._bike_travel = StringVar(self.parent) self.price_label = Label(self.parent, textvariable=self._bike_price) self.weight_label = Label(self.parent, textvariable=self._bike_weight) self.travel_label = Label(self.parent, textvariable=self._bike_travel) self.createInterface() self.createBike() self.price_label.pack() self.weight_label.pack() self.travel_label.pack() self.pack(fill=BOTH, expand=1) def createInterface(self): """ Tworzenie interfejsu - nieistotne dla idei zadania """ self.frame_choice = StringVar(self.parent) self.frame_choice.set(tuple(self.frames.keys())[0]) self.frame_choice.trace("w", self.createBike) self.frame_options = OptionMenu(self.parent,self.frame_choice, *self.frames.keys()) Label(self.parent,text="Rama:").pack() self.frame_options.pack(fill=BOTH, expand=1) self.fork_choice = StringVar(self.parent) self.fork_choice.set(tuple(self.forks.keys())[0]) self.fork_choice.trace("w", self.createBike) self.fork_options = OptionMenu(self.parent,self.fork_choice, *self.forks.keys()) Label(self.parent,text="Widelec:").pack() self.fork_options.pack(fill=BOTH, expand=1) self.wheelset_choice = StringVar(self.parent) self.wheelset_choice.set(tuple(self.wheelsets.keys())[0]) self.wheelset_choice.trace("w", self.createBike) self.wheelset_options = OptionMenu(self.parent,self.wheelset_choice, *self.wheelsets.keys()) Label(self.parent,text="Koła:").pack() self.wheelset_options.pack(fill=BOTH, expand=1) self.group_choice = StringVar(self.parent) self.group_choice.set(tuple(self.groups.keys())[0]) self.group_choice.trace("w", self.createBike) self.group_options = OptionMenu(self.parent,self.group_choice, *self.groups.keys()) Label(self.parent,text="Grupa osprzętu:").pack() self.group_options.pack(fill=BOTH, expand=1) self.components_choice = StringVar(self.parent) self.components_choice.set(tuple(self.components.keys())[0]) self.components_choice.trace("w", self.createBike) self.components_options = OptionMenu(self.parent,self.components_choice, *self.components.keys()) Label(self.parent,text="Komponenty:").pack() self.components_options.pack(fill=BOTH, expand=1) def createBike(self, *args): """ Metoda tworząca obiekt roweru na zasadanie dekorowania obiektu klasy 'Frame' """ frame = self.frames[self.frame_choice.get()] fork = self.forks[self.fork_choice.get()] fork.decorated = frame wheelset = self.wheelsets[self.wheelset_choice.get()] wheelset.decorated = fork group = self.groups[self.group_choice.get()] group.decorated = wheelset components = self.components[self.components_choice.get()] components.decorated = group self._bike = components # przypisanie wartości odpowiednim elementom GUI self._bike_price.set("cena: " + str(self._bike.price) + "zł") self._bike_weight.set("waga: " + str(self._bike.weight) + " gr") self._bike_travel.set("skok: " + str(self._bike.travel) + " mm") # uaktualnienie okna self.price_label.update_idletasks() self.weight_label.update_idletasks() # zmiana tytułu okna self.parent.wm_title(self._bike.name)
class Application(Frame): def __init__(self, master=None): Frame.__init__(self, master) self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.sock.bind((host, port)) self.grid() self.columnconfigure(0, minsize=100) self.columnconfigure(1, minsize=200) self.columnconfigure(2, minsize=200) self.columnconfigure(3, minsize=150) self.columnconfigure(4, minsize=150) self.columnconfigure(5, minsize=150) self.columnconfigure(6, minsize=150) self.create_widgets() self.settables = self.assemble_settables() self.gui_logger = logging.getLogger('gui') self.request_update() def create_widgets(self): self.create_monitor() self.create_check_buttons() self.create_ranges() self.create_scales() self.create_radio_buttons() self.create_voices() self.quitButton = Button(self, text='Quit', command=self.quit) self.quitButton.grid(columnspan=7, sticky=E + W) def assemble_settables(self): settables = self.winfo_children() for w in settables: settables += w.winfo_children() return [w for w in settables if w.__class__.__name__ in ['Scale', 'Checkbutton']] def create_radio_buttons(self): # Scale related entries = ['DIATONIC', 'HARMONIC', 'MELODIC', 'PENTATONIC', 'PENTA_MINOR', 'GREEK_CHROMATIC', 'GREEK_ENHARMONIC'] self.scale = StringVar() self.scale.set('DIATONIC') self.rb_frame = Frame(self) for e in entries: rb = Radiobutton(self.rb_frame, value=e, text=e, anchor=W, command=self.send_scale, variable=self.scale) rb.grid(row=len(self.rb_frame.winfo_children()), sticky=W) self.rb_frame.grid(column=1, row=len(self.grid_slaves(column=1)), rowspan=3) def create_monitor(self): self.monitor_frame = LabelFrame(self, text="Monitor and Transport") this_cycle = Scale(self.monitor_frame, label='cycle_pos', orient=HORIZONTAL, from_=1, to=16, resolution=1) this_cycle.disable, this_cycle.enable = (None, None) this_cycle.ref = 'cycle_pos' this_cycle.grid(column=0, row=0, sticky=E + W) self.updateButton = Button(self.monitor_frame, text='Reload all Settings', command=self.request_update) self.updateButton.grid(row=1, sticky=E + W) self.ForceCaesuraButton = Button(self.monitor_frame, text='Force Caesura', command=self.force_caesura) self.ForceCaesuraButton.grid(row=2, sticky=E + W) self.saveBehaviourButton = Button(self.monitor_frame, text='Save current behaviour', command=self.request_saving_behaviour) self.saveBehaviourButton.grid(row=3, sticky=E + W) self.saveBehaviourNameEntry = Entry(self.monitor_frame) self.saveBehaviourNameEntry.grid(row=4, sticky=E + W) self.saveBehaviourNameEntry.bind('<KeyRelease>', self.request_saving_behaviour) self.selected_behaviour = StringVar() self.selected_behaviour.trace('w', self.new_behaviour_chosen) self.savedBehavioursMenu = OptionMenu(self.monitor_frame, self.selected_behaviour, None,) self.savedBehavioursMenu.grid(row=5, sticky=E + W) self.monitor_frame.grid(column=0, row=10, sticky=E + W) def request_update(self): self.send({'sys': 'update'}) def request_saving_behaviour(self, event=None): """callback for save behaviour button and textentry""" if event and event.widget == self.saveBehaviourNameEntry: if event.keysym == 'Return': name = self.saveBehaviourNameEntry.get() self.saveBehaviourNameEntry.delete(0, len(name)) else: return else: # button was pressed name = self.saveBehaviourNameEntry.get() if name: self.send({'sys': ['save_behaviour', name]}) def force_caesura(self): self.send({'force_caesura': True}) def create_voices(self): voice_ids = ['1', '2', '3', '4'] SCALES = OrderedDict([ ('pan_pos', {'min': -1, 'max': 1, 'start': 0.5, 'res': 0.001}), ('volume', {'min': 0, 'max': 1, 'start': 0.666, 'res': 0.001}), ('slide_duration_msecs', {'min': 0, 'max': 2000, 'start': 60, 'res': 1}), ('slide_duration_prop', {'min': 0, 'max': 2, 'start': 0.666, 'res': 0.001}), ('binaural_diff', {'min': 0, 'max': 66, 'start': 0.2, 'res': 0.01}) ]) for vid in voice_ids: counter = 0 for sca in SCALES: name = 'voice_' + vid + '_' + sca setattr(self, 'min_' + name, SCALES[sca]['min']) setattr(self, 'max_' + name, SCALES[sca]['max']) this_sca = Scale(self, label=sca, orient=HORIZONTAL, from_=getattr(self, 'min_' + name), to=getattr(self, 'max_' + name), resolution=SCALES[sca]['res']) this_sca.enable = ('enable' in list(SCALES[sca].keys()) and SCALES[sca]['enable'] or None) this_sca.disable = ('disable' in list(SCALES[sca].keys()) and SCALES[sca]['disable'] or None) this_sca.grid(column=int(2 + int(vid)), row=counter, sticky=E + W) this_sca.bind("<ButtonRelease>", self.scale_handler) this_sca.ref = name counter += 1 CHECK_BUTTONS = OrderedDict( [('mute', False), ('automate_binaural_diffs', True), ('automate_note_duration_prop', True), ('use_proportional_slide_duration', {'val': True, 'label': 'proportional slide'}), ('automate_pan', True), ('automate_wavetables', True)]) for vid in voice_ids: counter = 0 cb_frame = LabelFrame(self, text="Voice {0} - Automation".format(vid)) setattr(self, 'voice_' + vid + '_cb_frame', cb_frame) for cb in CHECK_BUTTONS: options = CHECK_BUTTONS[cb] name = 'voice_' + vid + '_' + cb if isinstance(options, dict) and 'label' in list(options.keys()): label = options['label'] else: label = cb[9:] if cb[:9] == 'automate_' else cb setattr(self, name, IntVar( value=type(options) == dict and options['val'] or options)) self.this_cb = Checkbutton(cb_frame, text=label, variable=getattr(self, name)) self.this_cb.bind('<Button-1>', self.check_boxes_handler) self.this_cb.disable = None self.this_cb.grid(sticky=W, column=0, row=counter) self.this_cb.ref = name counter += 1 # add trigger wavetable-button trigWavetableButton = Button(cb_frame, text='Next Wavetable') trigWavetableButton.bind('<Button-1>', self.trigger_waveform_handler) trigWavetableButton.ref = 'voice_' + vid + "_trigger_wavetable" trigWavetableButton.grid(row=counter) cb_frame.grid(column=int(vid) + 2, row=5, sticky=E + W + N, rowspan=8) for vid in voice_ids: generation_types = ["random", "random_harmonic", "harmonic"] partial_pools = ["even", "odd", "all"] prefix = 'voice_' + vid + '_' types_name = prefix + 'wavetable_generation_type' pools_name = prefix + 'partial_pool' setattr(self, types_name, StringVar()) getattr(self, types_name).set("random") setattr(self, pools_name, StringVar()) getattr(self, pools_name).set("all") target_frame = getattr(self, 'voice_' + vid + '_cb_frame') gen_typ_frame = LabelFrame(target_frame, text="type") gen_typ_frame.grid(row=len(target_frame.winfo_children()), sticky=W) for gen_t in generation_types: gen_t_entry = Radiobutton(gen_typ_frame, value=gen_t, text=gen_t, anchor=W, variable=getattr(self, types_name)) gen_t_entry.bind('<ButtonRelease-1>', self.wt_handler) gen_t_entry.ref = types_name gen_t_entry.grid(row=len(gen_typ_frame.winfo_children()), sticky=W) pp_frame = LabelFrame(target_frame, text="harmonics") for pp in partial_pools: pp_entry = Radiobutton(pp_frame, value=pp, text=pp, anchor=W, variable=getattr(self, pools_name)) pp_entry.bind('<ButtonRelease-1>', self.wt_handler) pp_entry.ref = pools_name pp_entry.grid(row=len(pp_frame.winfo_children()), sticky=E + W) this_num_partials = Scale(pp_frame, label='number of harmonics', orient=HORIZONTAL, from_=1, to=24, resolution=1) this_num_partials.ref = prefix + 'num_partials' this_num_partials.grid(column=0, row=len(pp_frame.winfo_children()), sticky=E + W) this_num_partials.bind("<ButtonRelease>", self.scale_handler) pp_frame.grid(row=len(target_frame.winfo_children()), sticky=E + W) def wt_handler(self, event): print(event.widget.tk) ref = event.widget.ref self.send({ref: getattr(self, ref).get()}) def create_check_buttons(self): self.cb_frame = LabelFrame(self, text="Global Settings") for cb in CHECK_BUTTONS: label = cb target_parent = self.cb_frame if isinstance(CHECK_BUTTONS[cb], dict) and 'sub_frame' in list(CHECK_BUTTONS[cb].keys()): target_parent = getattr(self, CHECK_BUTTONS[cb]['sub_frame']) setattr(self, cb, IntVar(value=type(CHECK_BUTTONS[cb]) == dict and CHECK_BUTTONS[cb]['val'] or CHECK_BUTTONS[cb])) self.this_cb = Checkbutton(target_parent, text=label, variable=getattr(self, cb)) self.this_cb.bind('<Button-1>', self.check_boxes_handler) self.this_cb.disable = (type(CHECK_BUTTONS[cb]) == dict and 'disable' in list(CHECK_BUTTONS[cb].keys())) self.this_cb.grid(sticky=W, column=0, row=len(target_parent.winfo_children())) self.this_cb.ref = cb for but in GLOBAL_BUTTONS: label = but ele = GLOBAL_BUTTONS[but] this_but = Button(self.cb_frame, text=but) this_but.bind('<ButtonRelease-1>', getattr(self, ele['handler'])) this_but.ref = but this_but.grid(sticky=W, column=0, row=len(self.cb_frame.winfo_children())) self.cb_frame.grid(column=0, row=0, rowspan=10, sticky=N) def new_behaviour_chosen(self, a, b, c): self.send({'sys': ['change_behaviour', self.selected_behaviour.get()]}) def set_value(self, name, val): '''sets a widget to the specified value various different widget types need custom setting functionality''' direct = ['scale', 'wavetable_generation_type', 'partial_pool'] if [x for x in direct if match("(voice_\d_|)" + x, name)]: self.gui_logger.info("setting: '{0}' to '{1}' in GUI".format(name, val)) getattr(self, name).set(val) return if name == 'saved_behaviours' and len(val): self.savedBehavioursMenu.destroy() self.savedBehavioursMenu = OptionMenu(self.monitor_frame, self.selected_behaviour, *sorted(val)) self.savedBehavioursMenu.grid(row=5, sticky=E + W) return for w in self.settables: typ = w.__class__.__name__ if w.ref == name: # print "setting '{0}' of type: '{1}' to: {2}".format(name, typ, val) if typ == 'Scale': w.set(val) elif typ == "Checkbutton": w.select() if val else w.deselect() def check_boxes_handler(self, event): '''handles checkbox events. shows and hides gui elements according to their enable/disable fields''' # print event.__dict__ # print event.widget.__dict__ ref = event.widget.ref val = not getattr(self, ref).get() # because is read before the var is changed self.send({ref: val}) # print ref, val # handle gui elements # enable/disable functionality temporarily(?) commented on: # Wed Aug 17 09:39:54 CEST 2011 # if event.widget.disable: # for w in self.children.values(): # # # this try clause is for debugging, remove when stable # try: # w.ref # #print w.ref # except: # pass # if (w.__class__.__name__ == 'Scale' and # (w.disable or w.enable)): # if w.disable == ref: # if val: # w.grid() # else: # w.grid_remove() # elif w.enable == ref: # if val: # w.grid_remove() # else: # w.grid() # #print w.disable, w.enable def create_scales(self): counter = 0 for sca in SCALES: label = SCALES[sca]['label'] if 'label' in list(SCALES[sca].keys()) else sca setattr(self, 'min_' + sca, SCALES[sca]['min']) setattr(self, 'max_' + sca, SCALES[sca]['max']) self.this_scale = Scale(self, label=label, orient=HORIZONTAL, from_=getattr(self, 'min_' + sca), to=getattr(self, 'max_' + sca), resolution=SCALES[sca]['res']) self.this_scale.set(SCALES[sca]['start']) self.this_scale.enable = ('enable' in list(SCALES[sca].keys()) and SCALES[sca]['enable'] or None) self.this_scale.disable = ('disable' in list(SCALES[sca].keys()) and SCALES[sca]['disable'] or None) if 'pos' in list(SCALES[sca].keys()): pos = SCALES[sca]['pos'] col = pos['c'] row = pos['r'] else: row = counter col = 1 counter += 1 self.this_scale.grid(column=col, row=row, sticky=E + W) self.this_scale.ref = sca self.this_scale.bind("<ButtonRelease>", self.scale_handler) def scale_handler(self, event): self.send({event.widget.ref: event.widget.get()}) self.gui_logger.info("handling scale: {0}, with new value: {1}".format( event.widget.ref, event.widget.get())) def trigger_waveform_handler(self, event): self.send({event.widget.ref: True}) # print event.widget.ref, "- triggering wavetable" def send_scale(self): do = {'scale': self.scale.get()} self.send(do) def send(self, msg): self.gui_logger.info("sending: {0}".format(msg)) self.send_sock.sendto(json.dumps(msg), (remote_host, send_port)) def create_ranges(self): counter = 0 for ran in RANGES: setattr(self, 'min_' + ran, RANGES[ran]['min']) setattr(self, 'max_' + ran, RANGES[ran]['max']) self.this_min_scale = Scale(self, label='min ' + ran, orient=HORIZONTAL, from_=getattr(self, 'min_' + ran), to=getattr(self, 'max_' + ran), resolution=RANGES[ran]['res']) self.this_max_scale = Scale(self, label='max ' + ran, orient=HORIZONTAL, from_=getattr(self, 'min_' + ran), to=getattr(self, 'max_' + ran), resolution=RANGES[ran]['res']) self.this_min_scale.set(RANGES[ran]['min_start']) self.this_max_scale.set(RANGES[ran]['max_start']) self.this_min_scale.enable = ('enable' in list(RANGES[ran].keys()) and RANGES[ran]['enable'] or None) self.this_min_scale.disable = ('disable' in list(RANGES[ran].keys()) and RANGES[ran]['disable'] or None) self.this_max_scale.enable = ('enable' in list(RANGES[ran].keys()) and RANGES[ran]['enable'] or None) self.this_max_scale.disable = ('disable' in list(RANGES[ran].keys()) and RANGES[ran]['disable'] or None) self.this_min_scale.grid(column=2, row=counter, sticky=E + W) self.this_max_scale.grid(column=2, row=counter + 1, sticky=E + W) self.this_min_scale.ref = 'min_' + ran self.this_max_scale.ref = 'max_' + ran self.this_min_scale.bind("<ButtonRelease>", self.scale_handler) self.this_max_scale.bind("<ButtonRelease>", self.scale_handler) counter += 2 def socket_read_handler(self, file, mask): data_object = json.loads(file.recv(1024)) do = list(data_object.items())[0] self.set_value(do[0], do[1])
class Tk_Nosy(object): """This class is the tkinter GUI object""" # make a collection of python interpreters to choose from pythonInterpreterCollection = None # will be PyInterpsOnSys object # extra python interpreters can run nosetests concurrently to main window # concurrent_versionL contains tuples = (PI, Popup) concurrent_versionL = [] # additional running python interpreters def __init__(self, master): self.dirname = os.path.abspath( os.curdir ) self.initComplete = 0 self.master = master self.x, self.y, self.w, self.h = -1,-1,-1,-1 # bind master to <Configure> in order to handle any resizing, etc. # postpone self.master.bind("<Configure>", self.Master_Configure) self.master.bind('<Enter>', self.bindConfigure) self.menuBar = Menu(master, relief = "raised", bd=2) self.menuBar.add("command", label = "Change_Dir", command = self.menu_Directory_Change_Dir) disp_Choices = Menu(self.menuBar, tearoff=0) self.display_test_details = StringVar() self.display_test_details.set('N') disp_Choices.add_checkbutton(label='Display Test Details', variable=self.display_test_details, onvalue='Y', offvalue='N') self.display_watched_files = StringVar() self.display_watched_files.set('N') disp_Choices.add_checkbutton(label='Show Watched Files', variable=self.display_watched_files, onvalue='Y', offvalue='N') self.menuBar.add("cascade", label="Display", menu=disp_Choices) py_choices = Menu(self.menuBar, tearoff=0) py_choices.add("command", label = "Change Python Version", command = self.changePythonVersion) py_choices.add("command", label = "Find New Python Interpreter", command = self.findNewPythonInterpreter) py_choices.add("command", label = "Launch Another Python Interpreter", command = self.launchAnotherPythonInterpreter) self.menuBar.add("cascade", label="Python", menu=py_choices) #top_Snippet = Menu(self.menuBar, tearoff=0) self.menuBar.add("command", label = "Run", command = self.menu_Run) self.display_test_details.trace("w", self.rerun_tests) self.display_watched_files.trace("w", self.rerun_tests) master.config(menu=self.menuBar) # make a Status Bar self.statusMessage = StringVar() self.statusMessage.set(self.dirname) self.statusbar = Label(self.master, textvariable=self.statusMessage, bd=1, relief=SUNKEN) self.statusbar.pack(anchor=SW, fill=X, side=BOTTOM) self.statusbar_bg = self.statusbar.cget('bg') # save bg for restore self.arial_12_bold_font = tkinter.font.Font(family="Arial", size=12, weight=tkinter.font.BOLD) self.arial_12_font = tkinter.font.Font(family="Arial", size=12) self.statusbar.config( font=self.arial_12_bold_font ) frame = Frame(master) frame.pack(anchor=NE, fill=BOTH, side=TOP) self.Pass_Fail_Button = Button(frame,text="Pass/Fail Will Be Shown Here", image="", width="15", background="green", anchor=W, justify=LEFT, padx=2) self.Pass_Fail_Button.pack(anchor=NE, fill=X, side=TOP) self.Pass_Fail_Button.bind("<ButtonRelease-1>", self.Pass_Fail_Button_Click) self.master.title("tk_nosy") self.oscillator = 1 # animates character on title self.oscillator_B = 0 # used to return statusbar to statusbar_bg self.lbframe = Frame( frame ) self.lbframe.pack(anchor=SE, side=LEFT, fill=BOTH, expand=1) scrollbar = Scrollbar(self.lbframe, orient=VERTICAL) self.Text_1 = Text(self.lbframe, width="80", height="24", yscrollcommand=scrollbar.set) scrollbar.config(command=self.Text_1.yview) scrollbar.pack(side=RIGHT, fill=Y) self.Text_1.pack(side=LEFT, fill=BOTH, expand=1) self.master.resizable(1,1) # Linux may not respect this self.numNosyCalls = 0 self.need_to_pick_dir = 1 print('sys.argv =',sys.argv) if len(sys.argv)>1: # I don't care what the exception is, if there's a problem, bail # pylint: disable=W0702 print( "Try Dir =",sys.argv[1] ) try: dirname = os.path.abspath( sys.argv[1] ) self.try_change_to_new_dir( dirname ) except Exception: pass # let Alarm force dir selection else: try: if os.path.isdir(os.path.join( self.dirname, 'tests' )): self.try_change_to_new_dir( self.dirname ) except Exception: pass # let Alarm force dir selection print(LICENSE) self.defaultPyInterp = None # need to identify default python interpreter if Tk_Nosy.pythonInterpreterCollection == None: Tk_Nosy.pythonInterpreterCollection = PyInterpsOnSys() self.defaultPyInterp = Tk_Nosy.pythonInterpreterCollection.get_PI_obj_by_py_path( sys.executable ) #print( Tk_Nosy.pythonInterpreterCollection ) self.Alarm() def try_change_to_new_dir(self, dirname): """A legal abspath will switch to dirname.""" # I don't care what the exception is, if there's a problem, bail # pylint: disable=W0702 if dirname: try: dirname = os.path.abspath( dirname ) except: return # let Alarm force dir selection else: return self.dirname = dirname print('Selected dirname =',dirname) fileD.clear() os.chdir( self.dirname ) self.reset_statusbar_bg() self.need_to_pick_dir = 0 #with open(NOSY_USER_DATA_FILE, 'w') as text_file: # text_file.write( self.dirname ) self.numNosyCalls = 0 def reset_statusbar_bg(self): """Return status bar to default state""" self.statusbar.config(bg=self.statusbar_bg) self.statusMessage.set(self.dirname) def set_statusbar_bg(self, c): """Set status bar to show new color and message""" self.statusbar.config(bg=c) self.oscillator_B = 1 # will return to initial color after a few cycles def menu_Directory_Change_Dir(self): """Menu selection to set directory in which to run nosetests""" dirname = self.AskDirectory( title='Choose Directory For Nose Tests', initialdir=".") if dirname: self.try_change_to_new_dir( dirname ) # >>>>>>insert any user code below this comment for section "menu_Directory_Change_Dir" # replace, delete, or comment-out the following print("called menu_Directory_Change_Dir") def menu_Run(self): """User initiates a nosetests run, not file change detection.""" print("called menu_Run") self.callNosy() def rerun_tests(self,*args): self.menu_Run() def callNosy(self): """Run nosetests and display results""" self.numNosyCalls += 1 runL = [(self.defaultPyInterp, self)] for PI,Popup in Tk_Nosy.concurrent_versionL: runL.append( (PI, Popup) ) for PI, tkwindow in runL: tkwindow.Text_1.delete(1.0, END) # turn indicator button gray while running the tests tkwindow.Pass_Fail_Button.config(background="#999999", text='TESTING...', font=self.arial_12_bold_font) self.master.update() self.master.update_idletasks() for PI, tkwindow in runL: self.run_tkwin_nosetests( PI, tkwindow) self.master.winfo_toplevel().wm_geometry("") def run_tkwin_nosetests(self, PI, tkwindow): """Run nosetests for main python interpreter and any concurrent python interpreters. Update GUI to show results. """ if PI.nose_version == None: # if nose was not installed last time we checked, check again PI.nose_version, err_msg = get_nose_version_info( PI.full_path ) if PI.nose_version == None: print( "\a" ) # make beep s = 'Can not verify nose for:\nPython ' + PI.name() tkwindow.Pass_Fail_Button.config(background='orange', text=s, font=self.arial_12_bold_font) s = 'Please verify nose installed for:\n'+str(PI) +\ '\n\n' + err_msg+\ '\n\nFor install instructions see:\n'+\ 'https://nose.readthedocs.org/en/latest/' tkwindow.Text_1.insert(END, s ) ShowError(title='Can not verify nose', message=s) return # pylint: disable=W0201 passedAllTests, numPassed, numFailed, numErrors, numSkipped, outputTextL = \ run_nosetests(self.numNosyCalls, PI, display_test_details=self.display_test_details.get()) max_len_s = 42 num_lines = 1 for s in outputTextL: tkwindow.Text_1.insert(END, s) sL = s.split('\n') for ss in sL: max_len_s = max(max_len_s, len(ss)) num_lines += 1 if self.numNosyCalls % 2: myFont = self.arial_12_bold_font else: myFont = self.arial_12_font if passedAllTests: s = 'PASSED' if numPassed > 1: s = 'PASSED ALL %i TESTS'%numPassed elif numPassed == 1: s = 'PASSED ONE TEST' bg="#00ff00" if numSkipped==1: s = 'passed with 1 SKIP' bg = "#00cc00" elif numSkipped > 1: s = 'passed with %i SKIPS'%numSkipped bg = "#00cc00" elif numPassed==0: s = 'No Tests Found' bg="#ff8000" tkwindow.Pass_Fail_Button.config(background=bg, text=s, font=myFont) #self.master.geometry('200x50') else: s = 'FAILED %i, ERRORS %i, SKIP %i, PASSED %i'%(numFailed, numErrors, numSkipped, numPassed) tkwindow.Pass_Fail_Button.config(background="#ff0000", text=s, font=myFont) #self.master.geometry('516x385') # Show list of files being watched. #self.Text_1.insert(END, '_'*40+'\n') tkwindow.Text_1.insert(END, 'WATCHED *.py FILES'.center(40,'_') + '\n' ) tkwindow.Text_1.insert(END, '%s%s..\n\n'%(self.dirname,os.path.sep) ) num_lines += 3 len_dirname = len( self.dirname ) if self.display_watched_files.get()=='Y': keyL = list(fileD.keys()) keyL.sort() lastdir = '' for key in keyL: dn = os.path.dirname( key ) if dn != lastdir: tkwindow.Text_1.insert(END, '..'+dn[len_dirname:] + '\n') max_len_s = max(max_len_s, len(dn)+1) lastdir = dn num_lines += 1 s = ' ' +os.path.basename( key ) tkwindow.Text_1.insert(END, s + '\n') max_len_s = max(max_len_s, len(s)+1) num_lines += 1 else: num_lines += 1 tkwindow.Text_1.insert(END, ' %i files watched.\n'%len(fileD)) tkwindow.Text_1.config(width=max_len_s) tkwindow.Text_1.config(height=min(40, num_lines)) def bindConfigure(self, event): """Part of goofy main window setup in tkinter.""" # tkinter requires arguments, but I don't use them # pylint: disable=W0613 if not self.initComplete: self.master.bind("<Configure>", self.Master_Configure) self.initComplete = 1 def change_python_exe(self, full_path ): """Allow nosetests to be run under any available python version """ PI = Tk_Nosy.pythonInterpreterCollection.add_interp( full_path ) if PI: self.defaultPyInterp = PI def findNewPythonInterpreter(self): """Find a new python interpreter, one that is not already in the PyInterpsOnSys object (pythonInterpreterCollection). """ if Tk_Nosy.pythonInterpreterCollection == None: print( 'pythonInterpreterCollection NOT yet initialized' ) self.statusMessage.set('Interpreter Collection NOT initialized') self.set_statusbar_bg( '#FF9999' ) return print('Open File') filetypes = [ ('python executable','py*'), ('Any File','*.*')] pathopen = tkFileDialog.askopenfilename(parent=self.master, title='Select Python Executable', filetypes=filetypes, initialdir=self.defaultPyInterp.full_path) if pathopen: self.change_python_exe( pathopen ) self.menu_Run() def kill_popup_window(self, popup_name): """Close a popup window running another verions of python interpreter""" for itup, tup in enumerate(Tk_Nosy.concurrent_versionL): PI, Popup = tup s = '%s %s' % (PI.exe_name, PI.version_str) if popup_name == s: Tk_Nosy.concurrent_versionL.pop( itup ) return True # removed popup from list return False # no popup found def launchAnotherPythonInterpreter(self): """Launch a pop-up window that concurrently runs another python version""" removeNameL=[self.defaultPyInterp.name()] for PI,Popup in Tk_Nosy.concurrent_versionL: removeNameL.append( PI.name() ) piL = Tk_Nosy.pythonInterpreterCollection.get_PI_list( removeNameL=removeNameL ) if len(piL)==0: print( 'All identified python interpreters in use.' ) else: print( [pi.name() for pi in piL] ) rbL = [PI.name() for PI in piL] dialog = Select_Py_Version(self.master, "Launch Another Python Version", dialogOptions={'rbL':rbL}) if dialog.result: PI = Tk_Nosy.pythonInterpreterCollection.get_PI_obj_by_name( dialog.result['selection']) s = '%s %s' % (PI.exe_name, PI.version_str) Popup = SatelliteWindow(self, self.master, s) Tk_Nosy.concurrent_versionL.append( (PI, Popup) ) self.menu_Run() def changePythonVersion(self): """Change to a different python version. If the PyInterpsOnSys object (pythonInterpreterCollection) has been initialized, select from its list. Otherwise find the python interpreter executable (ex. python.exe or python) """ if (Tk_Nosy.pythonInterpreterCollection == None) or \ (Tk_Nosy.pythonInterpreterCollection.num_terps() == 0): # If there is no list of available python interpreters, look for python file print('Open File') filetypes = [ ('python executable','py*'), ('Any File','*.*')] pathopen = tkFileDialog.askopenfilename(parent=self.master, title='Select Python Executable', filetypes=filetypes, initialdir=self.defaultPyInterp.full_path) if pathopen: self.change_python_exe( pathopen ) self.menu_Run() else: rbL = [PI.name() for PI in Tk_Nosy.pythonInterpreterCollection.interpL] dialog = Select_Py_Version(self.master, "Select Python Version", dialogOptions={'rbL':rbL}) if dialog.result: PI = Tk_Nosy.pythonInterpreterCollection.get_PI_obj_by_name( dialog.result['selection'] ) pathopen = PI.full_path self.change_python_exe( pathopen ) self.menu_Run() # return a string containing directory name def AskDirectory(self, title='Choose Directory', initialdir="."): """Run pop-up menu for user to select directory.""" # This is not an error # pylint: disable=E1101 if sys.version_info < (3,): dirname = tkFileDialog.askdirectory(parent=self.master, initialdir=initialdir,title=title) else: dirname = tkFileDialog.askdirectory(parent=self.master, initialdir=initialdir,title=title) return dirname # <-- string def Master_Configure(self, event): """Part of tkinter main window initialization""" if event.widget != self.master: if self.w != -1: return x = int(self.master.winfo_x()) y = int(self.master.winfo_y()) w = int(self.master.winfo_width()) h = int(self.master.winfo_height()) if (self.x, self.y, self.w, self.h) == (-1,-1,-1,-1): self.x, self.y, self.w, self.h = x,y,w,h if self.w!=w or self.h!=h: #print "Master reconfigured... make resize adjustments" self.w=w self.h=h # pylint: disable=W0613 def Pass_Fail_Button_Click(self, event): """Routine for user clicking Pass/Fail Button""" print('Arranging Windows by User Request') num_popups = len(Tk_Nosy.concurrent_versionL) DX = 50 DY = 70 x = 10 y = 10 + num_popups * DY self.master.geometry( '+%i+%i'%(x,y)) for PI,Popup in Tk_Nosy.concurrent_versionL: x += DX y -= DY Popup.geometry( '+%i+%i'%(x,y)) # alarm function is called after specified number of milliseconds def SetAlarm(self, milliseconds=1000): """Reinitialize tkinter alarm mechanism as well as update seconds counter in main window title bar. """ self.master.after( milliseconds, self.Alarm ) self.oscillator += 1 if self.oscillator > 5: self.oscillator = 0 if self.oscillator_B>0: self.oscillator_B += 1 if self.oscillator_B>5: self.oscillator_B = 0 self.reset_statusbar_bg() pad = '|'*self.oscillator s = '%s (v%s)'%(self.defaultPyInterp.exe_name, self.defaultPyInterp.version_str) self.master.title('%i) %s '%(self.numNosyCalls , s + pad )) for PI,Popup in Tk_Nosy.concurrent_versionL: s = '%s (v%s)'%(PI.exe_name, PI.version_str) Popup.title( '%i) %s '%(self.numNosyCalls , s + pad ) ) def Alarm(self): """Look for changed files every second, then reset alarm""" if self.need_to_pick_dir: dirname = self.AskDirectory( title='Choose Directory For Nose Tests', initialdir=".") self.try_change_to_new_dir( dirname ) #first call to numberOfChangedFiles will be > 0 if any .py files are found elif numberOfChangedFiles( self.dirname ) > 0: # or self.numNosyCalls==0 self.callNosy() self.SetAlarm()
labels = [label_first_name, label_last_name, label_email] entries = [entry_first_name, entry_last_name, entry_email] buttons = [button_first, button_last, button_prev, button_next, button_last, button_quit] for i in range(3): labels[i].grid(row = i, column = 0, sticky = 'W') entries[i].grid(row = i, column = 1, columnspan = 6) for j in range(6): buttons[j].grid(row = 3, column = j, sticky = 'E') # def change1(*arg): # first_name.set(first_name.get()) # def change2(*arg): # last_name.set(last_name.get()) # def change3(*arg): # email.set(email.get()) def callback(email): global position_track update_value(position_track) print (email.get()) # first_name.trace("w", change1) # last_name.trace("w", change2) email.trace("w", lambda *args, email = email: callback(email)) window.mainloop()
class BIDSContainer(FileInfo): """ The base object which contains BIDSFiles. For KIT data this is the folder that contains the .con, .mrk etc files. For Elekta data this is the .fif file itself, so the file is a BIDSContainer and a BIDSFile simultanously. """ def __init__(self, id_=None, file=None, settings=None, parent=None): super(BIDSContainer, self).__init__(id_, file, parent) self._settings = settings def _create_vars(self): FileInfo._create_vars(self) self.proj_name = StringVar() self.proj_name.trace("w", self.check_projname_change) self.session_ID = StringVar(value='1') self.session_ID.trace("w", self.validate) # This will be a list of BIDSFile's which have their data extracted # and passed to mne_bids. self.jobs = set() # subject info self.subject_ID = StringVar() self.subject_ID.trace("w", self.validate) # self.subject_age format [DD, MM, YYYY] self.subject_age = [StringVar(), StringVar(), StringVar()] self.subject_gender = OptionsVar(options=['M', 'F', 'U']) self.subject_group = OptionsVar(options=['Participant', 'Control']) self.subject_group.trace("w", self._update_groups) self.contains_required_files = True self.requires_save = True self.extra_data = dict() # List of extra files to be dumped in the same directory as the # scants.tsv self.extra_files = [] # MEG data parameters self.electrode = None self.hsp = None self.readme = None self.make_specific_data = dict() # Whether the object has had any validation done yet. # This will be used to optimise the validation process since once the # BIDSContainer has had it's initial validation checks done, we will # only need to check the job for their validation sate, instead of # running validation on them again. self.validation_initialised = False def load_data(self): """ do all the intial data loading and variable assignment """ pass def init_validation(self): """ Checks the validity of any associated jobs and self""" for job in self.jobs: job.validate(validate_container=False) self.validate() self.validation_initialised = True def validate(self, *args): self.valid = self.check_valid() self._set_bids_button_state() def check_valid(self): is_valid = super(BIDSContainer, self).check_valid() is_valid &= self.proj_name.get() != '' is_valid &= self.subject_ID.get() != '' for job in self.jobs: is_valid &= job.valid return is_valid def check_projname_change(self, *args): """ A function to be called every time the project ID changes to allow the settings to be adjusted accordingly to allow for automatic updating of any applicable defaults """ # re-assign the settings to themselves by evoking the setter method # of self.settings. if self.parent is not None: self.settings = self.parent.proj_settings # not sure if having this here is doubling up and could cause problems self.validate() def _apply_settings(self): # try find the specific project settings if isinstance(self.settings, list): for proj_settings in self.settings: if (proj_settings.get('ProjectID', None) == self.proj_name.get()): self._settings = proj_settings break else: self._settings = dict() # otherwise we already have the dictionary of settings correctly groups = flatten(self.settings.get('Groups', ['Participant', 'Control'])) tasks = flatten(self.settings.get('Tasks', ['None'])) self.subject_group.options = groups for job in self.jobs: job.task.options = tasks job._update_tasks() self._update_groups() def _update_groups(self, *args): """Update the EntryChoice that contains the group options""" if self.associated_tab is not None: self.associated_tab.sub_group_entry.value = self.subject_group def _set_bids_button_state(self): """ Set the state of the button depending on whether it should be active or not """ if self.associated_tab is not None: if self.valid: self.associated_tab.bids_gen_btn.config({"state": ACTIVE}) else: self.associated_tab.bids_gen_btn.config({"state": DISABLED}) def prepare(self): """Prepare all the data in the object to be ready for bids export""" # generate the readme if isinstance(self.settings, dict): self.readme = generate_readme(self.settings) @property def settings(self): return self._settings @settings.setter def settings(self, value): self._settings = value self._apply_settings() def __getstate__(self): # only returns a dictionary of information that we actually need # to store. data = super(BIDSContainer, self).__getstate__() data['prj'] = self.proj_name.get() data['sid'] = self.session_ID.get() data['sji'] = self.subject_ID.get() data['sja'] = [self.subject_age[0].get(), self.subject_age[1].get(), self.subject_age[2].get()] data['sjs'] = self.subject_gender.get() data['sjg'] = self.subject_group.get() return data def __setstate__(self, state): super(BIDSContainer, self).__setstate__(state) self.proj_name.set(state.get('prj', '')) self.session_ID.set(state.get('sid', '')) self.subject_ID.set(state.get('sji', '')) self.subject_age[0].set(state.get('sja', ['', '', ''])[0]) self.subject_age[1].set(state.get('sja', ['', '', ''])[1]) self.subject_age[2].set(state.get('sja', ['', '', ''])[2]) gender = state.get('sjs', 'M') self.subject_gender.options = ['M', 'F', 'U'] self.subject_gender.set(gender) group = state.get('sjg', '') self.subject_group.options = [group] self.subject_group.set(group)
button_quit ] for i in range(3): labels[i].grid(row=i, column=0, sticky='W') entries[i].grid(row=i, column=1, columnspan=6) for j in range(6): buttons[j].grid(row=3, column=j, sticky='E') # def change1(*arg): # first_name.set(first_name.get()) # def change2(*arg): # last_name.set(last_name.get()) # def change3(*arg): # email.set(email.get()) def callback(email): global position_track update_value(position_track) print(email.get()) # first_name.trace("w", change1) # last_name.trace("w", change2) email.trace("w", lambda *args, email=email: callback(email)) window.mainloop()
class c_configFrame(ttk.Frame): ''' classdocs ''' def __init__(self,master,owner,config_data,**params): ''' Constructor ''' try: super().__init__(master,**params) self.owner = owner self.config_data = config_data self.validation_result = StringVar() self.validation_result.trace('w',self.__on_change_validation_result) self.__create_children(config_data) except: raise def __del__(self): ''' Destructor ''' for child in self.children: self.children[child].destroy() def __create_children(self,config_data): try: row=0 ttk.Label(self,text="Required Settings").grid(column=0,row=row,sticky='w') row=row+1 ttk.Label(self,text="Text Editor").grid(column=0,row=row,sticky='w') ttk.Entry(self,textvariable=self.config_data.text_edit,width=100,state="readonly").grid(column=1,row=row,sticky='w') ttk.Button(self,name="btn_select_textedit",text="Select",command=self.__on_btn_select_textedit).grid(column=2,row=row,sticky='w') row=row+1 ttk.Label(self,text="File Compare").grid(column=0,row=row,sticky='w') ttk.Entry(self,textvariable=self.config_data.file_compare,width=100,state="readonly").grid(column=1,row=row,sticky='w') ttk.Button(self,name="btn_select_fielcompare",text="Select",command=self.__on_btn_select_file_compare).grid(column=2,row=row,sticky='w') row=row+1 ttk.Label(self,text="PTC Client directory").grid(column=0,row=row,sticky='w') ttk.Entry(self,textvariable=self.config_data.ptc_client_dir,width=100,state="readonly").grid(column=1,row=row,sticky='w') ttk.Button(self,name="btn_select_ptc_client",text="Select",command=self.__on_btn_select_ptc_client).grid(column=2,row=row,sticky='w') row=row+1 ttk.Label(self,text="PTC Gateway(Rif.bat)").grid(column=0,row=row,sticky='w') ttk.Entry(self,textvariable=self.config_data.rif_bat,width=100,state="readonly").grid(column=1,row=row,sticky='w') ttk.Button(self,name="btn_select_rifbat",text="Select",command=self.__on_btn_select_rifbat).grid(column=2,row=row,sticky='w') row=row+1 ttk.Label(self,text="Mapping Template").grid(column=0,row=row,sticky='w') ttk.Entry(self,textvariable=self.config_data.template,width=100,state="readonly").grid(column=1,row=row,sticky='w') ttk.Button(self,name="btn_select_template",text="Select",command=self.__on_btn_select_template).grid(column=2,row=row,sticky='w') row=row+1 ttk.Label(self,text="Options").grid(column=0,row=row,sticky='w') row=row+1 ttk.Label(self,text="Max number of paralell processes").grid(column=0,row=row,sticky='w') ttk.Entry(self,textvariable=self.config_data.max_threads,width=2,).grid(column=1,row=row,sticky='w') row=row+1 ttk.Label(self,text="Ptc Gateway Mapping GUI").grid(column=0,row=row,sticky='w') ttk.Checkbutton(self,variable=self.config_data.gw_mapping_gui,onvalue=True, offvalue=False).grid(column=1,row=row,sticky='w') row=row+1 ttk.Label(self,text="Ptc Gateway GUI").grid(column=0,row=row,sticky='w') ttk.Checkbutton(self,variable=self.config_data.gw_gui,onvalue=True, offvalue=False).grid(column=1,row=row,sticky='w') row=row+1 ttk.Label(self,text="Ptc Gateway NoGUI All Yes").grid(column=0,row=row,sticky='w') ttk.Checkbutton(self,variable=self.config_data.gw_all_yes,onvalue=True, offvalue=False).grid(column=1,row=row,sticky='w') row=row+1 ttk.Label(self,text="Project Settings").grid(column=0,row=row,sticky='w') row=row+1 ttk.Label(self,text="PTC Project").grid(column=0,row=row,sticky='w') ttk.Entry(self,textvariable=self.config_data.ptc_project,width=100).grid(column=1,row=row,sticky='w') row=row+1 ttk.Label(self,text="Input directory").grid(column=0,row=row,sticky='w') ttk.Entry(self,textvariable=self.config_data.input_dir,width=100,state="readonly").grid(column=1,row=row,sticky='w') ttk.Button(self,name="btn_select_input_dir",text="Select",command=self.__on_btn_select_input_dir).grid(column=2,row=row,sticky='w') row=row+1 ttk.Label(self).grid(column=0,row=row,sticky='w') row=row+1 ttk.Label(self).grid(column=0,row=row,sticky='w') row=row+1 ttk.Label(self).grid(column=0,row=row,sticky='w') row=row+1 self.textfield=Text(self,height=8,width=75,state='disabled') self.textfield.grid(column=1,row=row) ttk.Button(self,name="btn_validate",text="Validate",command=self.__on_btn_validate).grid(column=2,row=row) except: raise else: pass def __on_btn_select_rifbat(self): self.config_data.cmd_select_rifbat() def __on_btn_select_template(self): self.config_data.cmd_select_template() def __on_btn_select_textedit(self): self.config_data.cmd_select_textedit() def __on_btn_select_file_compare(self): self.config_data.cmd_select_filecompare() def __on_btn_select_ptc_client(self): self.config_data.cmd_select_ptc_client() def __on_btn_select_input_dir(self): self.config_data.cmd_select_input_dir() def __on_chk_use_ptc(self): pass def __on_btn_validate(self): (result,text) = self.config_data.cmd_validate_config() self.validation_result.set(text) if(result==True): self.owner.config_valid() pass def __on_change_validation_result(self,*args): try: self.textfield.configure(state='normal') self.textfield.delete(1.0,END) self.textfield.insert(END,self.validation_result.get()) self.textfield.configure(state='disabled') except: raise
class ULDO01(UIExample): def __init__(self, master=None): super(ULDO01, self).__init__(master) master.protocol("WM_DELETE_WINDOW", self.exit) self.board_num = 0 self.digital_props = DigitalProps(self.board_num) # Find the first port that supports output, defaulting to None # if one is not found. self.port = next( (port for port in self.digital_props.port_info if port.supports_output), None) # If the port is configurable, configure it for output if self.port != None and self.port.is_port_configurable: try: ul.d_config_port(self.board_num, self.port.type, DigitalIODirection.OUT) except ULError as e: self.show_ul_error(e) self.running = False self.create_widgets() def get_data_value(self): try: return int(self.data_value_entry.get()) except ValueError: return 0 def data_value_changed(self, *args): try: # Get the data value data_value = self.get_data_value() # Send the value to the device ul.d_out(self.board_num, self.port.type, data_value) except ULError as e: self.stop() self.show_ul_error(e) def exit(self): # Set the port to 0 at exit try: ul.d_out(self.board_num, self.port.type, 0) except ULError as e: self.show_ul_error(e) self.master.destroy() def create_widgets(self): '''Create the tkinter UI''' if self.port != None: main_frame = tk.Frame(self) main_frame.pack(fill=tk.X, anchor=tk.NW) positive_int_vcmd = self.register(self.validate_positive_int_entry) curr_row = 0 value_label = tk.Label(main_frame) value_label["text"] = "Value:" value_label.grid(row=curr_row, column=0, sticky=tk.W) self.data_value_variable = StringVar() self.data_value_entry = tk.Spinbox( main_frame, from_=0, to=255, textvariable=self.data_value_variable, validate="key", validatecommand=(positive_int_vcmd, "%P")) self.data_value_entry.grid(row=curr_row, column=1, sticky=tk.W) self.data_value_variable.trace("w", self.data_value_changed) button_frame = tk.Frame(self) button_frame.pack(fill=tk.X, side=tk.RIGHT, anchor=tk.SE) quit_button = tk.Button(button_frame) quit_button["text"] = "Quit" quit_button["command"] = self.exit quit_button.grid(row=0, column=1, padx=3, pady=3) else: self.create_unsupported_widgets(self.board_num)
def refreshWidget(self) : #print "refresh" self.card_win.pack_forget() import unicodedata #Card window self.card_win = PanedWindow(self.card_win.master, orient=VERTICAL) self.card_win.pack(side=TOP, expand=True, fill=BOTH, pady=2, padx=2) #Create the name zone name_zone=PanedWindow(self.card_win, orient=HORIZONTAL) name = StringVar() name.set(self.name) def modifName(*args) : try : assert('"' not in name.get()) name.get().encode('ascii') except Exception as e: print ("error on name") name.set(self.name) return old = self.name in Card.blocked_creature self.name=name.get() if old or self.name in Card.blocked_creature : self.refreshWidget() name.trace("w", modifName) name_wid=Entry(name_zone, width=30,textvariable=name) name_wid.pack() name_zone.add(name_wid) #Create the cost ad star stringvar #print int(floor(self.getCost())) self.cost=StringVar() self.stars=StringVar() cost_wid=Label(None, textvariable=self.cost, background='red',width=5, anchor=W) star_wid=Label(None, textvariable=self.stars, background='blue', anchor=E) self.cost.set(str(int(floor(self.getCost())))) self.stars.set("*"*self.getStars()) #Add them in name zone name_zone.add(cost_wid) name_zone.add(star_wid) #Create an Image Zone image_zone=Button(self.card_win, command=self.choosePhoto) if hasattr(self,"photofile") and self.photofile : print ("Image: ",self.photofile) try : pilImage=Image.open(self.photofile) img=PhotoImage(pilImage,master=image_zone) except : decomp=self.photofile.split('/') for i in range(1,6) : try : fname="/".join(decomp[-i:]) print ("try to open",fname) pilImage = Image.open(fname) img=PhotoImage(pilImage,master=image_zone) self.photofile=fname break except : self.photofile=None if self.photofile : w, h = img.width(), img.height() print('wh',w,h) if h>400 : print("reduction") img=PhotoImage(pilImage.resize((w//2,h//2), Image.ANTIALIAS),master=image_zone) image_zone=Button(self.card_win,image=img, command=self.choosePhoto) image_zone.image=img #image_zone.configure(image=image_zone.image,width=50,height=50,compound=RIGHT) #image_zone.pack() #print "IMAGE CHANGED" else : from os import path fname=self.name.replace(" ","_") if path.isfile("Cards/"+fname+".png") : image_zone.config(text='image can be taken from\n'+"Cards/"+fname+".png",background='white',anchor=CENTER) else : image_zone.config(text='clic to choose image',background='white',anchor=CENTER) #image_zone.pack() # POWER ZONE power_zone=PanedWindow(self.card_win, orient=VERTICAL) #fenetre=self.card_win.master def removePowerCreator(px) : def removePower(*args) : #print 'avant',list_pow self.bonus.remove(px) #print 'apres',list_pow #self.card_win.pack_forget() self.refreshWidget() return removePower for p in self.bonus : powline = PanedWindow(self.card_win, orient=HORIZONTAL) pow_wid=p.initWidget(powline) powline.add(pow_wid) removepow=Button(powline, text="X", command=removePowerCreator(p), anchor=E) removepow.pack() powline.add(removepow) power_zone.add(powline) def addPower(*args) : if addBonus.get()!= "add bonus": name=addBonus.get() else: name=add_cost_alteration.get() print ("added :",name) import CardPowers self.bonus+=[eval('CardPowers.'+name+'()')] self.bonus[-1].parent=self.bonus self.bonus[-1].card=self #self.card_win.pack_forget() self.refreshWidget() #Add bonus Option menu addBonus = StringVar(power_zone) addBonus.set("add bonus") # default value if not self.pv: addBonus_wid = Spell.getSpellMenu(power_zone, addBonus) else: addBonus_wid = getBonusMenu(power_zone, addBonus) addBonus.trace('w', addPower) if self.pv>0 or len(self.bonus)==0 or all([b.is_cost_alterator for b in self.bonus]): addBonus_wid.pack() #Add this to power zone power_zone.add(addBonus_wid) #Create save zone save_zone = PanedWindow(self.card_win, orient=HORIZONTAL) if self.monster_type != "all" and not(self.name in Card.blocked_creature) : save_wid = Button(save_zone, text="Save", command=self.postAndSave) elif self.monster_type != "all" : save_wid = Button(save_zone, text="creature in campaign", command=None) else: save_wid = Button(save_zone, text="nead type", command=None) save_wid.pack() #Create the open button save_zone.pack() if Card.monster_list.keys(): self.opening = StringVar(save_zone) self.opening.set("Open") choice = [na for na in Card.monster_list.keys() if na not in Card.blocked_creature] choice.sort() #print all_monsters.keys() open_wid = OptionMenu(save_zone, self.opening,*choice) self.opening.trace('w', self.Open) open_wid.pack() save_zone.add(open_wid) if Card.monster_list.keys(): self.delete = StringVar(save_zone) self.delete.set("Delete") choice = [na for na in Card.monster_list.keys() if na not in Card.blocked_creature] choice.sort() delete_wid = OptionMenu(save_zone, self.delete,*choice) self.delete.trace('w', self.clicDelete) delete_wid.pack() save_zone.add(delete_wid) #Create the type button self.category = StringVar(save_zone) self.category.set(self.monster_type) choice = [file2name(t,"_monsters.sav") for t in glob.glob("CardFiles/*_monsters.sav")] if "recup" in choice: choice.remove("recup") #print all_monsters.keys() category_wid = OptionMenu(save_zone, self.category,*choice) self.category.trace('w', self.setFile) category_wid.pack() #Add it to save zone save_zone.add(save_wid) save_zone.add(category_wid) #Create a new Strength zone for att and pv strength_zone=PanedWindow(self.card_win, orient=HORIZONTAL) att=StringVar() att.set(str(self.att)) pv=StringVar() ; pv.set(str(self.pv)) def modifiedAttPv(*args) : print ("modifiedAttPv") self.pv=int(pv.get()) if self.pv<1 and self.is_spell==False : if len(self.bonus)==0 : self.is_spell=True self.refreshWidget() else : self.pv=1 self.refreshWidget() if self.pv>0 and self.is_spell==True : if len(self.bonus)==0 : self.is_spell=False self.refreshWidget() else : self.pv=0 self.refreshWidget() self.att=int(att.get()) self.getCost() att_wid = Spinbox(strength_zone, from_=0, to=1000,textvariable=att,command=modifiedAttPv) att_wid.pack() strength_zone.add(att_wid) strength_zone.add(Label(strength_zone, text=' ', background='white', anchor=CENTER)) pv_wid = Spinbox(strength_zone, from_=0, to=1000,textvariable=pv,command=modifiedAttPv) pv_wid.pack() strength_zone.add(pv_wid) #Put it all in window self.card_win.add(name_zone) self.card_win.add(image_zone) self.card_win.add(power_zone) self.card_win.add(strength_zone) self.card_win.add(save_zone) self.card_win.pack()
def __init__(self) : Game.__init__(self) import socket import tkinter self.local = self.host=socket.gethostbyname(socket.gethostname()) # Get local machine ip from tkinter import Tk,PanedWindow,StringVar,Entry,Button,VERTICAL,HORIZONTAL,Label fenetre=Tk() fenetre.title('Socket parameters') self.netgame_win = PanedWindow(fenetre, orient=VERTICAL) host_zone=PanedWindow(self.netgame_win, orient=HORIZONTAL) host=StringVar() host.set(self.local) def modifHost(*args) : self.host=host.get() if self.local==self.host : start_button.config(text="Create") else : start_button.config(text="Join") host.trace("w", modifHost) host_wid=Entry(host_zone, width=30,textvariable=host) host_wid.pack() host_label=Label(fenetre, text="Host (you are "+self.local+") :") host_zone.add(host_label) host_zone.add(host_wid) self.netgame_win.add(host_zone) port_zone=PanedWindow(self.netgame_win, orient=HORIZONTAL) port=StringVar() self.port=52333 port.set(str(self.port)) # adress_wid=Label(None, textvariable=self.cost, background='red',width=5, anchor=W) def modifPort(*args) : #print "modify port to",port.get() try : self.port=int(port.get()) except : port.set("") port.trace("w", modifPort) port_wid=Entry(fenetre, width=30,textvariable=port) #port_wid.grid(column=0, row=1) host_wid.focus() port_wid.pack() port_label=Label(fenetre, text="Port :") port_zone.add(port_label) port_zone.add(port_wid) self.netgame_win.add(port_zone) #Create the open button def start() : fenetre.destroy() start_button=Button(self.netgame_win,text="Create",command=start) self.netgame_win.add(start_button) self.netgame_win.pack() #fenetre.focus_set() #start_button.focus() fenetre.mainloop() # Import socket module self.soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Reserve a port for your service. if self.local==self.host : self.soc.bind((self.host, self.port)) # Bind to the port print( "socket listening") self.soc.listen(5) # Now wait for client connection. self.soc, addr = self.soc.accept() # Establish connection with client. print( 'Got connection from', addr) #self.soc.send('Thank you for connecting') #c.close() # Close the connection self.firstplayer=choice([1,2]) print( "FIRST PLAYER IS",self.firstplayer) self.soc.send(str(3-self.firstplayer).encode('utf-8')) else : self.soc.connect((self.host, self.port)) print( "connect ok") p=self.soc.recv(1024).decode('utf-8') try : self.firstplayer=int(p) except : print( "error concerning first player, got ",p) self.remains=""
class ULDO01(UIExample): def __init__(self, master=None): super(ULDO01, self).__init__(master) master.protocol("WM_DELETE_WINDOW", self.exit) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) dio_info = self.device_info.get_dio_info() # Find the first port that supports output, defaulting to None # if one is not found. self.port = next( (port for port in dio_info.port_info if port.supports_output), None) if self.port is not None: # If the port is configurable, configure it for output if self.port.is_port_configurable: try: ul.d_config_port(self.board_num, self.port.type, DigitalIODirection.OUT) except ULError as e: show_ul_error(e) self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True) def get_data_value(self): try: return int(self.data_value_entry.get()) except ValueError: return 0 def data_value_changed(self, *args): try: # Get the data value data_value = self.get_data_value() # Send the value to the device ul.d_out(self.board_num, self.port.type, data_value) except ULError as e: show_ul_error(e) def exit(self): # Set the port to 0 at exit try: ul.d_out(self.board_num, self.port.type, 0) except ULError as e: show_ul_error(e) self.master.destroy() def create_widgets(self): '''Create the tkinter UI''' self.device_label = tk.Label(self) self.device_label.pack(fill=tk.NONE, anchor=tk.NW) self.device_label["text"] = ('Board Number ' + str(self.board_num) + ": " + self.device_info.product_name + " (" + self.device_info.unique_id + ")") main_frame = tk.Frame(self) main_frame.pack(fill=tk.X, anchor=tk.NW) positive_int_vcmd = self.register(validate_positive_int_entry) curr_row = 0 value_label = tk.Label(main_frame) value_label["text"] = "Value:" value_label.grid(row=curr_row, column=0, sticky=tk.W) self.data_value_variable = StringVar() self.data_value_entry = tk.Spinbox( main_frame, from_=0, to=255, textvariable=self.data_value_variable, validate="key", validatecommand=(positive_int_vcmd, "%P")) self.data_value_entry.grid(row=curr_row, column=1, sticky=tk.W) self.data_value_variable.trace("w", self.data_value_changed) button_frame = tk.Frame(self) button_frame.pack(fill=tk.X, side=tk.RIGHT, anchor=tk.SE) quit_button = tk.Button(button_frame) quit_button["text"] = "Quit" quit_button["command"] = self.exit quit_button.grid(row=0, column=1, padx=3, pady=3)
# Initialize the radioButFingers array radioButFingers = [Radiobutton(), Radiobutton(), Radiobutton(), Radiobutton()] # Set the radio buttons for text, mode in FINGERS_MODE_LIST: radioButFingers[radi_butt_index] = Radiobutton( root, text=text, variable=finger_control_variable, value=mode) radioButFingers[radi_butt_index].place(x=slider_group_x_offset + 240, y=slider_group_y_offset + 15 + radio_butt_offset * radi_butt_index) radi_butt_index += 1 radioButFingers[2].select() #Select initialy the lock position # Call the finger_control_mode function when the radio buttons change state finger_control_variable.trace("w", finger_control_mode) # ------------- Homing --------------- homingButton = Button(root, text="Homing") homingButton.bind("<Button-1>", Homing) homingButton.grid(row=3, column=4, sticky=W) # ------------ DropList --------------- choices = ['all', '1', '2', '3'] popupList = OptionMenu(root, list_choiceHoming, *choices) # Label(root, text = "Choose the axe").grid( row = 2, column = 4, sticky = W) popupList.grid(row=3, column=4, sticky=E) list_choiceHoming.set('all')
class MainUI: __PLATFORM = ['IOS', 'ANDROID'] __rootList = [] def __init__(self): self.__rootList = [] def initUI(self): self.frame = tkinter.Tk() self.frame.geometry('600x600') # 是x 不是* self.frame.resizable(width=True, height=True) # 宽不可变, 高可变,默认为True self.frame.minsize(700, 600) self.frame.title('工具集') '''工作目录''' panel1 = ttk.Labelframe(self.frame, text='工作目录') # 打包路径label packRootLabel = ttk.Label(panel1, text='打包路径:') packRootLabel.grid(row=0, column=0, padx=3, pady=3) # root下拉菜单 self.packRootPathVar = StringVar() self.packRootPathVar.trace('w', self.__packRootPathChangeCallBack) self.packRootPath = ttk.Combobox(panel1, textvariable=self.packRootPathVar) self.packRootPath.grid(row=0, column=1, padx=3, pady=3, stick='we') # root路径选择按钮 packRootSelBtn = ttk.Button(panel1, text='选择', command=self.selectRootDir) packRootSelBtn.grid(row=0, column=2, padx=3, pady=3) panel1.columnconfigure(1, weight=1) panel1.pack(fill='x', side=TOP, padx=5, pady=5, ipadx=10, ipady=5) '''打包设置''' panel2 = ttk.LabelFrame(self.frame, text='打包设置') childRow1 = ttk.Frame(panel2) # 资源目录label srcPathLabel = ttk.Label(childRow1, text='资源目录:') srcPathLabel.grid(row=0, column=0, padx=3, pady=3) # 资源目录路径 self.srcPathVar = StringVar() self.srcPathVar.trace('w', callback=self.__platformChangeCallBack) srcPath = ttk.Entry(childRow1, textvariable=self.srcPathVar) srcPath.grid(row=0, column=1, padx=3, pady=3, stick='we') # 资源目录路径选择按钮 srcPathBtn = ttk.Button(childRow1, text='选择', command=self.selectSrcDir) srcPathBtn.grid(row=0, column=2, padx=3, pady=3) childRow1.columnconfigure(1, weight=1) childRow1.pack(fill='x', side=TOP) childRow2 = ttk.Frame(panel2) # 平台类型 self.platformComboVar = StringVar() platformCombo = ttk.Combobox(childRow2, values=self.__PLATFORM, state='readonly', width=10, textvariable=self.platformComboVar) platformCombo.current(0) platformCombo.grid(row=0, column=1, padx=3, pady=3) # 是否全新打包 self.isNew = IntVar() isNewCheck = ttk.Checkbutton(childRow2, text='全新打包', variable=self.isNew) isNewCheck.grid(row=0, column=3, padx=3, pady=3) # 是否整包 self.isFull = IntVar() isFullCheck = ttk.Checkbutton(childRow2, text='整包', variable=self.isFull) isFullCheck.grid(row=0, column=4, padx=3, pady=3) childRow2.columnconfigure(5, weight=1) childRow2.pack(fill='x', side=TOP) panel2.pack(fill='x', side=TOP, padx=5, pady=5, ipadx=10, ipady=5) # 开始按钮 startBtn = ttk.Button(self.frame, text='开始打包', command=self.startPack) startBtn.pack() '''输出步骤''' panel3 = ttk.LabelFrame(self.frame, text='总览') headTextBar = ttk.Scrollbar(panel3, orient=VERTICAL) headTextBar.pack(side=RIGHT, fill='y') self.headConsole = Text(panel3, state='disabled', yscrollcommand=headTextBar.set, width=40, foreground='white', background='black') self.headConsole.pack(expand=1, fill=BOTH) panel3.pack(fill='y', side=LEFT, padx=5, pady=5, ipadx=10, ipady=5) '''输出详细信息''' panel4 = ttk.LabelFrame(self.frame, text='详细信息') bottomTextBar = ttk.Scrollbar(panel4, orient=VERTICAL) bottomTextBar.pack(side=RIGHT, fill='y') self.bottomConsole = Text(panel4, state='disabled', yscrollcommand=bottomTextBar.set, foreground='white', background='black') self.bottomConsole.pack(expand=1, fill=BOTH) panel4.pack(expand=1, fill=BOTH, side=LEFT, padx=5, pady=5, ipadx=10, ipady=5) self.frame.after(50, func=self.updateLog) def initUIValues(self): RootInfoMgr.load() self.__rootList = RootInfoMgr.rootPathList self.updateRootList() def show(self): self.frame.mainloop() def updateLog(self): self.headConsole.configure(state='normal') while not Log.infoQueue.empty() : text = Log.infoQueue.get(True, 1) self.headConsole.insert('end', text) self.headConsole.configure(state='disabled') self.bottomConsole.configure(state='normal') while not Log.detailQueue.empty() : text = Log.detailQueue.get(True, 1) self.bottomConsole.insert('end', text) self.bottomConsole.configure(state='disabled') self.frame.after(50, func=self.updateLog) def selectRootDir(self): rootdir = askdirectory() if len(rootdir) > 0 and os.path.exists(rootdir) : self.packRootPathVar.set(rootdir) def selectSrcDir(self): srcdir = askdirectory() if len(srcdir) > 0 and os.path.exists(srcdir) : self.srcPathVar.set(srcdir) def updateRootList(self): self.packRootPath['values'] = self.__rootList if len(self.__rootList) > 0: self.packRootPath.current(0) def startPack(self): self.headConsole.configure(state='normal') self.headConsole.delete(0.0, 'end') self.headConsole.configure(state='disabled') self.bottomConsole.configure(state='normal') self.bottomConsole.delete(0.0, 'end') self.bottomConsole.configure(state='disabled') if not os.path.exists(self.packRootPathVar.get()) : Log.printInfoln('打包目录错了,骚年,你确定有这文件夹?? ' + self.packRootPathVar.get()) return if not os.path.exists(self.srcPathVar.get()) : Log.printInfoln('资源文件目录错了!' + self.srcPathVar.get()) return RootInfoMgr.updateRoot(self.packRootPathVar.get()) RootInfoMgr.writeRootInfo(self.packRootPathVar.get(), os.path.normpath(self.srcPathVar.get()), self.platformComboVar.get()) self.updateRootList() ProcessMgr.start(self.srcPathVar.get(), self.getPlatformType(), self.isNew.get() > 0, self.isFull.get() > 0) def getPlatformType(self): if self.__PLATFORM[0] == self.platformComboVar : return PLATFORM_IOS else : return PLATFORM_ANDROID def __packRootPathChangeCallBack(self, *args): if os.path.exists(self.packRootPathVar.get()) : rootInfo = RootInfoMgr.loadRootInfo(self.packRootPathVar.get()) if rootInfo != None : self.srcPathVar.set(os.path.normpath(rootInfo.srcPath)) self.platformComboVar.set(rootInfo.platform) def __platformChangeCallBack(self, *args): if os.path.exists(self.srcPathVar.get()) : try: self.headConsole.configure(state='normal') self.headConsole.delete(0.0, 'end') self.headConsole.configure(state='disabled') self.bottomConsole.configure(state='normal') self.bottomConsole.delete(0.0, 'end') self.bottomConsole.configure(state='disabled') ProcessMgr.createContext(self.packRootPathVar.get()) except : t, v, tb = sys.exc_info() print(t, v) traceback.print_tb(tb)
class ConfigurationPanel(tk.Frame): def __init__(self, parent, controller): self.conf = Config.get_instance() tk.Frame.__init__(self, parent) self.xadd = 200 self.label = tk.Label(self, text="Configuration", font=LARGE_FONT) self.label.pack(pady=10, padx=10) self.pop = 0 self.cutil = ConfigUtil.get_instance() self.btnBack = ttk.Button( self, text="<< back", command=lambda: controller.show_frame(DefaultPanel)) self.btnBack.place(x=20, y=80) self.lblVirusType = tk.Label(self, text="Select Virus") self.lblVirusType.place(x=400 + self.xadd, y=150) #---------------- combobox to select virus ----------------------- self.combovar = StringVar() self.combovar.trace('w', self.on_change) list_disease = self.cutil.get_all_sections() self.comboBoxVirus = ttk.Combobox(self, textvar=self.combovar, state='readonly', values=list_disease[1:]) self.comboBoxVirus.place(x=500 + self.xadd, y=150) self.comboBoxVirus.current(0) self.set_virus_properties() #combobox on change def set_virus_properties(self): self.conf = Config.get_instance() self.lblPopulation = tk.Label(self, text="Population") self.lblPopulation.place(x=200 + self.xadd, y=250) self.txtPopulation = tk.Text(self, height=1, width=25) self.txtPopulation.insert("end", str(self.conf.get_population())) self.txtPopulation.place(x=300 + self.xadd, y=250) self.lblInitialInfectedPer = tk.Label( self, text="Initial Infected Percentage") self.lblInitialInfectedPer.place(x=105 + self.xadd, y=300) self.txtInitialInfectedPer = tk.Text(self, height=1, width=25) self.txtInitialInfectedPer.insert( "end", str(self.conf.get_initial_infected_percentage())) self.txtInitialInfectedPer.place(x=300 + self.xadd, y=300) self.lblRFactor = tk.Label(self, text="R factor") self.lblRFactor.place(x=215 + self.xadd, y=350) self.sdrRFactor = tk.Scale(self, from_=0, to=10, orient=tk.HORIZONTAL, length=130, showvalue=0, resolution=1, command=self.set_valueRFactor) self.sdrRFactor.set(self.conf.get_r_factor()) self.sdrRFactor.place(x=300 + self.xadd, y=350) self.lblRFactorVal = tk.Label(self, text=self.sdrRFactor.get(), height=1, width=3) self.lblRFactorVal.place(x=450 + self.xadd, y=350) self.lblKFactor = tk.Label(self, text="K factor") self.lblKFactor.place(x=215 + self.xadd, y=400) self.sdrKFactor = tk.Scale(self, from_=0, to=1, orient=tk.HORIZONTAL, length=130, showvalue=0, resolution=0.01, command=self.set_valueKFactor) self.sdrKFactor.set(self.conf.get_k_factor()) self.sdrKFactor.place(x=300 + self.xadd, y=400) self.lblKFactorVal = tk.Label(self, text=self.sdrKFactor.get(), height=1, width=3) self.lblKFactorVal.place(x=450 + self.xadd, y=400) self.lblDaysContagious = tk.Label(self, text="Days Contagious") self.lblDaysContagious.place(x=160 + self.xadd, y=450) self.txtDaysContagious = tk.Text(self, height=1, width=25) self.txtDaysContagious.insert("end", str(self.conf.get_days_contageous())) self.txtDaysContagious.place(x=300 + self.xadd, y=450) #------------------------- mask ------------------------- self.lblMaskIntroducedTimeline = tk.Label(self, text="Mask Timeline") self.lblMaskIntroducedTimeline.place(x=180 + self.xadd, y=500) self.txtMaskIntroducedTimeline = tk.Text(self, height=1, width=25) self.txtMaskIntroducedTimeline.insert( "end", str(self.conf.get_mask_introduced_timeline())) self.txtMaskIntroducedTimeline.place(x=300 + self.xadd, y=500) self.lblMaskUsuageEffectiveness = tk.Label( self, text="Mask Usuage Effectiveness") self.lblMaskUsuageEffectiveness.place(x=95 + self.xadd, y=550) self.sdrMaskUsuageEffectiveness = tk.Scale( self, from_=0, to=100, orient=tk.HORIZONTAL, length=130, showvalue=0, resolution=0.1, command=self.set_valueMaskUsuageEffectiveness) self.sdrMaskUsuageEffectiveness.set( self.conf.get_mask_usage_effectiveness()) self.sdrMaskUsuageEffectiveness.place(x=300 + self.xadd, y=550) self.lblMaskUsuageEffectivenessVal = tk.Label( self, text=self.sdrRFactor.get(), height=1, width=4) self.lblMaskUsuageEffectivenessVal.place(x=450 + self.xadd, y=550) self.lblMaskUsuagePercentage = tk.Label(self, text="Mask Usage Percentage") self.lblMaskUsuagePercentage.place(x=115 + self.xadd, y=600) self.sdrMaskUsuagePercentage = tk.Scale( self, from_=0, to=100, orient=tk.HORIZONTAL, length=130, showvalue=0, resolution=0.1, command=self.set_valueMaskUsuagePercentage) self.sdrMaskUsuagePercentage.set(self.conf.get_mask_usage_percentage()) self.sdrMaskUsuagePercentage.place(x=300 + self.xadd, y=600) self.lblMaskUsuagePercentageVal = tk.Label(self, text=self.sdrRFactor.get(), height=1, width=4) self.lblMaskUsuagePercentageVal.place(x=450 + self.xadd, y=600) #------------------------- quarantine ------------------------- self.lblQuarantineIntroducedTimeline = tk.Label( self, text="Quarantine Timeline") self.lblQuarantineIntroducedTimeline.place(x=100 + 500 + self.xadd, y=250) self.txtQuarantineIntroducedTimeline = tk.Text(self, height=1, width=25) self.txtQuarantineIntroducedTimeline.insert( "end", str(self.conf.get_quarantine_introduced_timeline())) self.txtQuarantineIntroducedTimeline.place(x=250 + 500 + self.xadd, y=250) self.lblQuarantineEffectiveness = tk.Label( self, text="Quarantine Effectiveness") self.lblQuarantineEffectiveness.place(x=70 + 500 + self.xadd, y=300) self.sdrQuarantineUsuageEffectiveness = tk.Scale( self, from_=0, to=100, orient=tk.HORIZONTAL, length=130, showvalue=0, resolution=0.1, command=self.set_valueQuarantineUsuageEffectiveness) self.sdrQuarantineUsuageEffectiveness.set( self.conf.get_qurantine_effectiveness()) self.sdrQuarantineUsuageEffectiveness.place(x=250 + 500 + self.xadd, y=300) self.lblQuarantineUsuageEffectivenessVal = tk.Label( self, text=self.sdrRFactor.get(), height=1, width=4) self.lblQuarantineUsuageEffectivenessVal.place(x=400 + 500 + self.xadd, y=300) self.lblQuarantinePercentage = tk.Label(self, text="Quarantining Percentage") self.lblQuarantinePercentage.place(x=70 + 500 + self.xadd, y=350) self.sdrQuarantinePercentage = tk.Scale( self, from_=0, to=100, orient=tk.HORIZONTAL, length=130, showvalue=0, resolution=0.1, command=self.set_valueQuarantinePercentage) self.sdrQuarantinePercentage.set( self.conf.get_qurantine_usage_percentage()) self.sdrQuarantinePercentage.place(x=250 + 500 + self.xadd, y=350) self.lblQuarantinePercentageVal = tk.Label(self, text=self.sdrRFactor.get(), height=1, width=4) self.lblQuarantinePercentageVal.place(x=400 + 500 + self.xadd, y=350) #------------------------- vaccine ------------------------- self.lblVaccineIntroducedTimeline = tk.Label(self, text="Vaccine Timeline") self.lblVaccineIntroducedTimeline.place(x=115 + 500 + self.xadd, y=400) self.txtVaccineIntroducedTimeline = tk.Text(self, height=1, width=25) self.txtVaccineIntroducedTimeline.insert( "end", str(self.conf.get_vaccine_introduced_timeline())) self.txtVaccineIntroducedTimeline.place(x=250 + 500 + self.xadd, y=400) self.lblVaccineEffectiveness = tk.Label(self, text="Vaccine Effectiveness") self.lblVaccineEffectiveness.place(x=85 + 500 + self.xadd, y=450) self.sdrVaccineEffectiveness = tk.Scale( self, from_=0, to=100, orient=tk.HORIZONTAL, length=130, showvalue=0, resolution=0.1, command=self.set_valueVaccineEffectiveness) self.sdrVaccineEffectiveness.set(self.conf.get_vaccine_effectiveness()) self.sdrVaccineEffectiveness.place(x=250 + 500 + self.xadd, y=450) self.lblVaccineEffectivenessVal = tk.Label(self, text=self.sdrRFactor.get(), height=1, width=4) self.lblVaccineEffectivenessVal.place(x=400 + 500 + self.xadd, y=450) self.lblVaccinePercentage = tk.Label(self, text="Vaccine Percentage") self.lblVaccinePercentage.place(x=100 + 500 + self.xadd, y=500) self.sdrVaccinePercentage = tk.Scale( self, from_=0, to=100, orient=tk.HORIZONTAL, length=130, showvalue=0, resolution=0.1, command=self.set_valueVaccinePercentage) self.sdrVaccinePercentage.set(self.conf.get_vaccine_usage_percentage()) self.sdrVaccinePercentage.place(x=250 + 500 + self.xadd, y=500) self.lblVaccinePercentageVal = tk.Label(self, text=self.sdrRFactor.get(), height=1, width=4) self.lblVaccinePercentageVal.place(x=400 + 500 + self.xadd, y=500) self.btnSet = ttk.Button(self, text="Set", command=self.setButtonOnClick) self.btnSet.place(x=470 + self.xadd, y=650) def on_change(self, index, value, op): self.conf.set_property_name(self.comboBoxVirus.get()) self.conf.load_from_file(self.comboBoxVirus.get()) self.set_virus_properties() def set_valueRFactor(self, v): self.lblRFactorVal.config(text=v) def set_valueKFactor(self, v): self.lblKFactorVal.config(text=v) def set_valueMaskUsuageEffectiveness(self, v): self.lblMaskUsuageEffectivenessVal.config(text=v + '%') def set_valueMaskUsuagePercentage(self, v): self.lblMaskUsuagePercentageVal.config(text=v + '%') def set_valueQuarantineUsuageEffectiveness(self, v): self.lblQuarantineUsuageEffectivenessVal.config(text=v + '%') def set_valueQuarantinePercentage(self, v): self.lblQuarantinePercentageVal.config(text=v + '%') def set_valueVaccineEffectiveness(self, v): self.lblVaccineEffectivenessVal.config(text=v + '%') def set_valueVaccinePercentage(self, v): self.lblVaccinePercentageVal.config(text=v + '%') #print(self.txtVaccineIntroducedTimeline.get(1.0,"end-1c")) #---------------------- changing config values ----------------- def setButtonOnClick(self): conf = Config.get_instance() errorMessage = "" flag = 0 try: population = int(self.txtPopulation.get(1.0, "end-1c")) conf.set_population(population) except: flag = 1 errorMessage += "Population\n" try: daysContagious = int(self.txtDaysContagious.get(1.0, "end-1c")) conf.set_days_contageous(daysContagious) except: flag = 1 errorMessage += "No of days contagious\n" try: initialInfectedPer = int( self.txtInitialInfectedPer.get(1.0, "end-1c")) conf.set_initial_infected_percentage(initialInfectedPer) print(conf.get_initial_infected_percentage()) except: flag = 1 errorMessage += "Initial infected percentage\n" try: maskIntroducedTimeline = int( self.txtMaskIntroducedTimeline.get(1.0, "end-1c")) conf.set_mask_introduced_timeline(maskIntroducedTimeline) except: flag = 1 errorMessage += "Mask introduced timeline\n" try: quarantineIntroducedTimeline = int( self.txtQuarantineIntroducedTimeline.get(1.0, "end-1c")) conf.set_quarantine_introduced_timeline( quarantineIntroducedTimeline) except: flag = 1 errorMessage += "Quarantine introduced timeline\n" try: vaccineIntroducedTimeline = int( self.txtVaccineIntroducedTimeline.get(1.0, "end-1c")) conf.set_vaccine_effectiveness(vaccineIntroducedTimeline) except: flag = 1 errorMessage += "Vaccine Introduced Timeline\n" if flag == 1: tk.messagebox.showinfo("Error", errorMessage + " should be numbers")